8.1 原生API概述
8.1.1 Sciter原生API简介
Sciter提供了丰富的原生API,允许开发者在TIScript中直接调用系统级功能,这使得Sciter应用能够:
- 文件系统操作:读写文件、目录遍历、文件监控
- 网络通信:HTTP请求、WebSocket连接、TCP/UDP通信
- 系统集成:系统通知、托盘图标、剪贴板操作
- 硬件访问:摄像头、麦克风、传感器数据
- 进程管理:启动外部程序、进程间通信
- 数据库连接:SQLite、ODBC数据库操作
8.1.2 API分类
// Sciter原生API命名空间
namespace SciterAPI {
// 文件系统API
var FileSystem = {
// 文件操作
readFile: function(path, encoding) { /* ... */ },
writeFile: function(path, content, encoding) { /* ... */ },
deleteFile: function(path) { /* ... */ },
copyFile: function(src, dest) { /* ... */ },
moveFile: function(src, dest) { /* ... */ },
// 目录操作
createDirectory: function(path) { /* ... */ },
removeDirectory: function(path) { /* ... */ },
listDirectory: function(path) { /* ... */ },
// 文件信息
getFileInfo: function(path) { /* ... */ },
exists: function(path) { /* ... */ },
isFile: function(path) { /* ... */ },
isDirectory: function(path) { /* ... */ }
};
// 网络API
var Network = {
// HTTP请求
httpGet: function(url, options) { /* ... */ },
httpPost: function(url, data, options) { /* ... */ },
httpRequest: function(method, url, options) { /* ... */ },
// WebSocket
createWebSocket: function(url, protocols) { /* ... */ },
// 下载
downloadFile: function(url, localPath, options) { /* ... */ }
};
// 系统API
var System = {
// 系统信息
getSystemInfo: function() { /* ... */ },
getEnvironmentVariable: function(name) { /* ... */ },
setEnvironmentVariable: function(name, value) { /* ... */ },
// 进程管理
executeProcess: function(command, args, options) { /* ... */ },
killProcess: function(pid) { /* ... */ },
// 系统通知
showNotification: function(title, message, options) { /* ... */ },
// 剪贴板
getClipboardText: function() { /* ... */ },
setClipboardText: function(text) { /* ... */ }
};
// 数据库API
var Database = {
// SQLite
openSQLite: function(path) { /* ... */ },
// ODBC
openODBC: function(connectionString) { /* ... */ }
};
}
8.3.2 WebSocket通信
// WebSocket客户端管理器
class WebSocketClient {
function this(url, protocols = []) {
this.url = url;
this.protocols = protocols;
this.ws = null;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
this.reconnectInterval = 1000;
this.heartbeatInterval = 30000;
this.heartbeatTimer = null;
this.messageQueue = [];
this.eventHandlers = {
open: [],
message: [],
close: [],
error: [],
reconnect: []
};
}
// 连接WebSocket
function connect() {
return new Promise(function(resolve, reject) {
try {
this.ws = new WebSocket(this.url, this.protocols);
this.ws.onopen = function(event) {
stdout.println('WebSocket连接已建立');
this.reconnectAttempts = 0;
// 发送队列中的消息
this.flushMessageQueue();
// 启动心跳
this.startHeartbeat();
// 触发事件
this.emit('open', event);
resolve(event);
}.bind(this);
this.ws.onmessage = function(event) {
var message = this.parseMessage(event.data);
this.emit('message', message);
}.bind(this);
this.ws.onclose = function(event) {
stdout.println('WebSocket连接已关闭:', event.code, event.reason);
this.stopHeartbeat();
this.emit('close', event);
// 自动重连
if (!event.wasClean && this.reconnectAttempts < this.maxReconnectAttempts) {
this.scheduleReconnect();
}
}.bind(this);
this.ws.onerror = function(event) {
stdout.println('WebSocket错误:', event);
this.emit('error', event);
reject(event);
}.bind(this);
} catch (error) {
reject(error);
}
}.bind(this));
}
// 发送消息
function send(data, type = 'text') {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
var message = this.formatMessage(data, type);
this.ws.send(message);
return true;
} else {
// 连接未建立,加入队列
this.messageQueue.push({ data: data, type: type });
return false;
}
}
// 发送JSON消息
function sendJSON(data) {
return this.send(JSON.stringify(data), 'json');
}
// 发送二进制消息
function sendBinary(data) {
return this.send(data, 'binary');
}
// 关闭连接
function close(code = 1000, reason = '') {
if (this.ws) {
this.stopHeartbeat();
this.ws.close(code, reason);
}
}
// 添加事件监听器
function on(event, handler) {
if (this.eventHandlers[event]) {
this.eventHandlers[event].push(handler);
}
}
// 移除事件监听器
function off(event, handler) {
if (this.eventHandlers[event]) {
var index = this.eventHandlers[event].indexOf(handler);
if (index !== -1) {
this.eventHandlers[event].splice(index, 1);
}
}
}
// 触发事件
function emit(event, data) {
if (this.eventHandlers[event]) {
for (var handler of this.eventHandlers[event]) {
try {
handler(data);
} catch (error) {
stdout.println('WebSocket事件处理错误:', error.message);
}
}
}
}
// 解析消息
function parseMessage(data) {
try {
// 尝试解析为JSON
var parsed = JSON.parse(data);
return {
type: 'json',
data: parsed,
raw: data
};
} catch (e) {
// 普通文本消息
return {
type: 'text',
data: data,
raw: data
};
}
}
// 格式化消息
function formatMessage(data, type) {
switch (type) {
case 'json':
return JSON.stringify(data);
case 'binary':
return data;
default:
return String(data);
}
}
// 清空消息队列
function flushMessageQueue() {
while (this.messageQueue.length > 0) {
var message = this.messageQueue.shift();
this.send(message.data, message.type);
}
}
// 启动心跳
function startHeartbeat() {
this.stopHeartbeat();
this.heartbeatTimer = setInterval(function() {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.send('ping', 'heartbeat');
}
}.bind(this), this.heartbeatInterval);
}
// 停止心跳
function stopHeartbeat() {
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer);
this.heartbeatTimer = null;
}
}
// 安排重连
function scheduleReconnect() {
this.reconnectAttempts++;
var delay = this.reconnectInterval * Math.pow(2, this.reconnectAttempts - 1);
stdout.println(`WebSocket重连尝试 ${this.reconnectAttempts}/${this.maxReconnectAttempts},${delay}ms后重连`);
setTimeout(function() {
this.emit('reconnect', {
attempt: this.reconnectAttempts,
maxAttempts: this.maxReconnectAttempts
});
this.connect().catch(function(error) {
stdout.println('重连失败:', error);
});
}.bind(this), delay);
}
// 获取连接状态
function getState() {
if (!this.ws) {
return 'DISCONNECTED';
}
switch (this.ws.readyState) {
case WebSocket.CONNECTING:
return 'CONNECTING';
case WebSocket.OPEN:
return 'OPEN';
case WebSocket.CLOSING:
return 'CLOSING';
case WebSocket.CLOSED:
return 'CLOSED';
default:
return 'UNKNOWN';
}
}
// 获取连接信息
function getInfo() {
return {
url: this.url,
protocols: this.protocols,
state: this.getState(),
reconnectAttempts: this.reconnectAttempts,
queuedMessages: this.messageQueue.length
};
}
}
// WebSocket服务器(用于测试)
class WebSocketServer {
function this(port = 8080) {
this.port = port;
this.server = null;
this.clients = new Set();
this.messageHandlers = new Map();
}
// 启动服务器
function start() {
return new Promise(function(resolve, reject) {
try {
// 使用Sciter的WebSocket服务器API
this.server = System.net.createWebSocketServer({
port: this.port,
onConnection: this.handleConnection.bind(this),
onError: function(error) {
stdout.println('WebSocket服务器错误:', error);
reject(error);
}
});
stdout.println('WebSocket服务器启动,端口:', this.port);
resolve();
} catch (error) {
reject(error);
}
}.bind(this));
}
// 处理新连接
function handleConnection(client) {
stdout.println('新的WebSocket连接');
this.clients.add(client);
client.on('message', function(data) {
this.handleMessage(client, data);
}.bind(this));
client.on('close', function() {
stdout.println('WebSocket连接关闭');
this.clients.delete(client);
}.bind(this));
client.on('error', function(error) {
stdout.println('WebSocket客户端错误:', error);
this.clients.delete(client);
}.bind(this));
}
// 处理消息
function handleMessage(client, data) {
try {
var message = JSON.parse(data);
var handler = this.messageHandlers.get(message.type);
if (handler) {
handler(client, message.data);
} else {
// 默认回显消息
client.send(JSON.stringify({
type: 'echo',
data: message
}));
}
} catch (error) {
stdout.println('消息处理错误:', error.message);
}
}
// 注册消息处理器
function onMessage(type, handler) {
this.messageHandlers.set(type, handler);
}
// 广播消息
function broadcast(data) {
var message = JSON.stringify(data);
for (var client of this.clients) {
try {
client.send(message);
} catch (error) {
stdout.println('广播消息失败:', error.message);
this.clients.delete(client);
}
}
}
// 停止服务器
function stop() {
if (this.server) {
this.server.close();
this.server = null;
}
// 关闭所有客户端连接
for (var client of this.clients) {
client.close();
}
this.clients.clear();
}
}
// 使用示例
function webSocketExample() {
// 创建WebSocket客户端
var client = new WebSocketClient('ws://localhost:8080');
// 添加事件监听器
client.on('open', function(event) {
stdout.println('连接已建立');
// 发送测试消息
client.sendJSON({
type: 'greeting',
message: 'Hello, WebSocket!'
});
});
client.on('message', function(message) {
stdout.println('收到消息:', message.type, message.data);
});
client.on('close', function(event) {
stdout.println('连接已关闭:', event.code, event.reason);
});
client.on('error', function(error) {
stdout.println('连接错误:', error);
});
client.on('reconnect', function(info) {
stdout.println('正在重连:', info.attempt, '/', info.maxAttempts);
});
// 连接到服务器
client.connect()
.then(function() {
stdout.println('WebSocket客户端连接成功');
})
.catch(function(error) {
stdout.println('WebSocket客户端连接失败:', error);
});
// 定期发送消息
setInterval(function() {
if (client.getState() === 'OPEN') {
client.sendJSON({
type: 'ping',
timestamp: Date.now()
});
}
}, 5000);
// 10秒后关闭连接
setTimeout(function() {
client.close();
}, 10000);
}
8.4 系统通知和托盘
8.4.1 系统通知
// 系统通知管理器
class NotificationManager {
function this() {
this.notifications = new Map();
this.notificationId = 0;
this.defaultOptions = {
icon: null,
timeout: 5000,
persistent: false,
actions: [],
sound: true
};
}
// 显示通知
function show(title, message, options = {}) {
try {
var config = Object.assign({}, this.defaultOptions, options);
var notificationId = ++this.notificationId;
// 创建通知对象
var notification = {
id: notificationId,
title: title,
message: message,
options: config,
timestamp: new Date(),
dismissed: false
};
// 使用Sciter的系统通知API
var systemNotification = System.notification.show({
title: title,
body: message,
icon: config.icon,
timeout: config.persistent ? 0 : config.timeout,
actions: config.actions,
sound: config.sound,
onClick: function() {
this.handleNotificationClick(notification);
}.bind(this),
onClose: function() {
this.handleNotificationClose(notification);
}.bind(this),
onAction: function(actionId) {
this.handleNotificationAction(notification, actionId);
}.bind(this)
});
notification.systemNotification = systemNotification;
this.notifications.set(notificationId, notification);
// 自动清理非持久通知
if (!config.persistent && config.timeout > 0) {
setTimeout(function() {
this.dismiss(notificationId);
}.bind(this), config.timeout);
}
return {
success: true,
notificationId: notificationId,
notification: notification
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// 处理通知点击
function handleNotificationClick(notification) {
stdout.println('通知被点击:', notification.title);
if (notification.options.onClick) {
notification.options.onClick(notification);
}
// 默认行为:关闭通知
this.dismiss(notification.id);
}
// 处理通知关闭
function handleNotificationClose(notification) {
stdout.println('通知被关闭:', notification.title);
if (notification.options.onClose) {
notification.options.onClose(notification);
}
this.notifications.delete(notification.id);
}
// 处理通知动作
function handleNotificationAction(notification, actionId) {
stdout.println('通知动作被触发:', notification.title, actionId);
var action = notification.options.actions.find(a => a.id === actionId);
if (action && action.handler) {
action.handler(notification, actionId);
}
}
// 关闭通知
function dismiss(notificationId) {
var notification = this.notifications.get(notificationId);
if (notification && !notification.dismissed) {
notification.dismissed = true;
if (notification.systemNotification) {
notification.systemNotification.close();
}
this.notifications.delete(notificationId);
return {
success: true,
notificationId: notificationId
};
}
return {
success: false,
error: '通知不存在或已关闭',
notificationId: notificationId
};
}
// 关闭所有通知
function dismissAll() {
var dismissed = [];
for (var [id, notification] of this.notifications) {
var result = this.dismiss(id);
dismissed.push(result);
}
return {
success: true,
dismissed: dismissed
};
}
// 获取活动通知列表
function getActiveNotifications() {
var active = [];
for (var [id, notification] of this.notifications) {
if (!notification.dismissed) {
active.push({
id: notification.id,
title: notification.title,
message: notification.message,
timestamp: notification.timestamp
});
}
}
return {
success: true,
notifications: active,
count: active.length
};
}
// 检查通知权限
function checkPermission() {
try {
var permission = System.notification.permission;
return {
success: true,
permission: permission, // granted, denied, default
supported: System.notification.supported
};
} catch (error) {
return {
success: false,
error: error.message,
supported: false
};
}
}
// 请求通知权限
function requestPermission() {
return new Promise(function(resolve, reject) {
try {
System.notification.requestPermission(function(permission) {
resolve({
success: true,
permission: permission
});
});
} catch (error) {
reject({
success: false,
error: error.message
});
}
});
}
// 预定义通知类型
function showInfo(title, message, options = {}) {
return this.show(title, message, Object.assign({
icon: 'info',
sound: false
}, options));
}
function showWarning(title, message, options = {}) {
return this.show(title, message, Object.assign({
icon: 'warning',
sound: true,
timeout: 8000
}, options));
}
function showError(title, message, options = {}) {
return this.show(title, message, Object.assign({
icon: 'error',
sound: true,
persistent: true,
actions: [
{
id: 'dismiss',
title: '关闭',
handler: function(notification) {
// 自动关闭
}
}
]
}, options));
}
function showSuccess(title, message, options = {}) {
return this.show(title, message, Object.assign({
icon: 'success',
sound: false,
timeout: 3000
}, options));
}
}
// 使用示例
function notificationExample() {
var notificationManager = new NotificationManager();
// 检查通知权限
var permissionResult = notificationManager.checkPermission();
stdout.println('通知权限状态:', JSON.stringify(permissionResult, null, 2));
if (permissionResult.permission !== 'granted') {
// 请求通知权限
notificationManager.requestPermission()
.then(function(result) {
stdout.println('权限请求结果:', JSON.stringify(result, null, 2));
if (result.permission === 'granted') {
showTestNotifications();
}
})
.catch(function(error) {
stdout.println('权限请求失败:', error);
});
} else {
showTestNotifications();
}
function showTestNotifications() {
// 显示信息通知
notificationManager.showInfo('信息', '这是一条信息通知');
// 显示警告通知
setTimeout(function() {
notificationManager.showWarning('警告', '这是一条警告通知');
}, 2000);
// 显示错误通知
setTimeout(function() {
notificationManager.showError('错误', '这是一条错误通知', {
onClick: function(notification) {
stdout.println('错误通知被点击');
}
});
}, 4000);
// 显示成功通知
setTimeout(function() {
notificationManager.showSuccess('成功', '操作完成');
}, 6000);
// 显示带动作的通知
setTimeout(function() {
notificationManager.show('任务完成', '文件下载已完成', {
persistent: true,
actions: [
{
id: 'open',
title: '打开文件',
handler: function(notification) {
stdout.println('打开文件');
}
},
{
id: 'folder',
title: '打开文件夹',
handler: function(notification) {
stdout.println('打开文件夹');
}
}
]
});
}, 8000);
}
// 10秒后关闭所有通知
setTimeout(function() {
var result = notificationManager.dismissAll();
stdout.println('关闭所有通知:', JSON.stringify(result, null, 2));
}, 10000);
}
8.4.2 系统托盘
// 系统托盘管理器
class TrayManager {
function this() {
this.tray = null;
this.menu = null;
this.isVisible = false;
this.blinkTimer = null;
this.contextMenu = [];
}
// 创建托盘图标
function create(options = {}) {
try {
var {
icon = 'app-icon.png',
tooltip = 'Sciter Application',
visible = true
} = options;
// 使用Sciter的系统托盘API
this.tray = System.tray.create({
icon: icon,
tooltip: tooltip,
visible: visible,
onClick: this.handleClick.bind(this),
onDoubleClick: this.handleDoubleClick.bind(this),
onRightClick: this.handleRightClick.bind(this)
});
this.isVisible = visible;
return {
success: true,
tray: this.tray
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// 处理单击事件
function handleClick(event) {
stdout.println('托盘图标被单击');
// 默认行为:显示/隐藏主窗口
var mainWindow = view.windowState;
if (mainWindow === 'minimized' || mainWindow === 'hidden') {
view.windowState = 'normal';
view.focus();
} else {
view.windowState = 'minimized';
}
}
// 处理双击事件
function handleDoubleClick(event) {
stdout.println('托盘图标被双击');
// 默认行为:恢复并激活主窗口
view.windowState = 'normal';
view.focus();
}
// 处理右键点击事件
function handleRightClick(event) {
stdout.println('托盘图标被右键点击');
if (this.contextMenu.length > 0) {
this.showContextMenu();
}
}
// 设置图标
function setIcon(iconPath) {
if (this.tray) {
try {
this.tray.setIcon(iconPath);
return { success: true };
} catch (error) {
return {
success: false,
error: error.message
};
}
}
return {
success: false,
error: '托盘未创建'
};
}
// 设置提示文本
function setTooltip(tooltip) {
if (this.tray) {
try {
this.tray.setTooltip(tooltip);
return { success: true };
} catch (error) {
return {
success: false,
error: error.message
};
}
}
return {
success: false,
error: '托盘未创建'
};
}
// 显示托盘图标
function show() {
if (this.tray) {
this.tray.setVisible(true);
this.isVisible = true;
return { success: true };
}
return {
success: false,
error: '托盘未创建'
};
}
// 隐藏托盘图标
function hide() {
if (this.tray) {
this.tray.setVisible(false);
this.isVisible = false;
return { success: true };
}
return {
success: false,
error: '托盘未创建'
};
}
// 闪烁托盘图标
function blink(duration = 3000, interval = 500) {
if (!this.tray) {
return {
success: false,
error: '托盘未创建'
};
}
this.stopBlink();
var originalIcon = this.tray.getIcon();
var blinkIcon = 'blink-icon.png'; // 闪烁时的图标
var isOriginal = true;
this.blinkTimer = setInterval(function() {
if (isOriginal) {
this.tray.setIcon(blinkIcon);
} else {
this.tray.setIcon(originalIcon);
}
isOriginal = !isOriginal;
}.bind(this), interval);
// 指定时间后停止闪烁
setTimeout(function() {
this.stopBlink();
this.tray.setIcon(originalIcon);
}.bind(this), duration);
return { success: true };
}
// 停止闪烁
function stopBlink() {
if (this.blinkTimer) {
clearInterval(this.blinkTimer);
this.blinkTimer = null;
}
}
// 设置上下文菜单
function setContextMenu(menuItems) {
this.contextMenu = menuItems;
if (this.tray) {
this.menu = this.buildMenu(menuItems);
return { success: true };
}
return {
success: false,
error: '托盘未创建'
};
}
// 构建菜单
function buildMenu(items) {
var menu = [];
for (var item of items) {
if (item.type === 'separator') {
menu.push({ type: 'separator' });
} else {
menu.push({
id: item.id,
text: item.text,
enabled: item.enabled !== false,
checked: item.checked || false,
icon: item.icon,
submenu: item.submenu ? this.buildMenu(item.submenu) : null,
onClick: item.onClick
});
}
}
return menu;
}
// 显示上下文菜单
function showContextMenu() {
if (this.tray && this.menu) {
this.tray.showContextMenu(this.menu);
}
}
// 显示气泡提示
function showBalloon(title, message, options = {}) {
if (!this.tray) {
return {
success: false,
error: '托盘未创建'
};
}
var {
icon = 'info', // info, warning, error
timeout = 5000,
onClick = null
} = options;
try {
this.tray.showBalloon({
title: title,
text: message,
icon: icon,
timeout: timeout,
onClick: onClick
});
return { success: true };
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// 销毁托盘图标
function destroy() {
this.stopBlink();
if (this.tray) {
this.tray.destroy();
this.tray = null;
this.menu = null;
this.isVisible = false;
return { success: true };
}
return {
success: false,
error: '托盘未创建'
};
}
// 获取托盘状态
function getStatus() {
return {
created: this.tray !== null,
visible: this.isVisible,
blinking: this.blinkTimer !== null,
hasContextMenu: this.contextMenu.length > 0
};
}
}
// 使用示例
function trayExample() {
var trayManager = new TrayManager();
// 创建托盘图标
var createResult = trayManager.create({
icon: 'assets/app-icon.png',
tooltip: 'Sciter应用程序',
visible: true
});
if (createResult.success) {
stdout.println('托盘图标创建成功');
// 设置上下文菜单
trayManager.setContextMenu([
{
id: 'show',
text: '显示窗口',
onClick: function() {
view.windowState = 'normal';
view.focus();
}
},
{
id: 'hide',
text: '隐藏窗口',
onClick: function() {
view.windowState = 'minimized';
}
},
{ type: 'separator' },
{
id: 'settings',
text: '设置',
icon: 'settings-icon.png',
submenu: [
{
id: 'general',
text: '常规设置',
onClick: function() {
stdout.println('打开常规设置');
}
},
{
id: 'advanced',
text: '高级设置',
onClick: function() {
stdout.println('打开高级设置');
}
}
]
},
{
id: 'about',
text: '关于',
onClick: function() {
trayManager.showBalloon('关于', 'Sciter应用程序 v1.0', {
icon: 'info'
});
}
},
{ type: 'separator' },
{
id: 'exit',
text: '退出',
onClick: function() {
// 确认退出
var result = view.msgbox({
type: 'question',
title: '确认退出',
text: '确定要退出应用程序吗?',
buttons: ['是', '否']
});
if (result === 0) {
trayManager.destroy();
view.close();
}
}
}
]);
// 测试气泡提示
setTimeout(function() {
trayManager.showBalloon('欢迎', '应用程序已最小化到系统托盘', {
icon: 'info',
timeout: 3000
});
}, 2000);
// 测试闪烁
setTimeout(function() {
trayManager.blink(2000, 300);
}, 5000);
// 监听窗口最小化事件
view.on('statechange', function(event) {
if (event.detail.state === 'minimized') {
trayManager.showBalloon('最小化', '应用程序已最小化到托盘', {
icon: 'info',
timeout: 2000
});
}
});
} else {
stdout.println('托盘图标创建失败:', createResult.error);
}
}
8.5 数据库操作
8.5.1 SQLite数据库
// SQLite数据库管理器
class SQLiteManager {
function this(dbPath) {
this.dbPath = dbPath;
this.db = null;
this.isConnected = false;
this.transactionLevel = 0;
}
// 连接数据库
function connect() {
try {
// 使用Sciter的SQLite API
this.db = System.database.sqlite.open(this.dbPath);
this.isConnected = true;
stdout.println('SQLite数据库连接成功:', this.dbPath);
return {
success: true,
database: this.db
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// 关闭数据库连接
function close() {
if (this.db && this.isConnected) {
try {
this.db.close();
this.isConnected = false;
this.db = null;
stdout.println('SQLite数据库连接已关闭');
return { success: true };
} catch (error) {
return {
success: false,
error: error.message
};
}
}
return {
success: false,
error: '数据库未连接'
};
}
// 执行SQL查询
function query(sql, params = []) {
if (!this.isConnected) {
return {
success: false,
error: '数据库未连接'
};
}
try {
var statement = this.db.prepare(sql);
var result;
if (params.length > 0) {
result = statement.all(params);
} else {
result = statement.all();
}
return {
success: true,
data: result,
rowCount: result.length
};
} catch (error) {
return {
success: false,
error: error.message,
sql: sql,
params: params
};
}
}
// 执行SQL命令(INSERT, UPDATE, DELETE)
function execute(sql, params = []) {
if (!this.isConnected) {
return {
success: false,
error: '数据库未连接'
};
}
try {
var statement = this.db.prepare(sql);
var result;
if (params.length > 0) {
result = statement.run(params);
} else {
result = statement.run();
}
return {
success: true,
changes: result.changes,
lastInsertRowid: result.lastInsertRowid
};
} catch (error) {
return {
success: false,
error: error.message,
sql: sql,
params: params
};
}
}
// 开始事务
function beginTransaction() {
if (!this.isConnected) {
return {
success: false,
error: '数据库未连接'
};
}
try {
if (this.transactionLevel === 0) {
this.db.exec('BEGIN TRANSACTION');
} else {
// 嵌套事务使用保存点
this.db.exec(`SAVEPOINT sp${this.transactionLevel}`);
}
this.transactionLevel++;
return {
success: true,
transactionLevel: this.transactionLevel
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// 提交事务
function commitTransaction() {
if (!this.isConnected) {
return {
success: false,
error: '数据库未连接'
};
}
if (this.transactionLevel === 0) {
return {
success: false,
error: '没有活动的事务'
};
}
try {
this.transactionLevel--;
if (this.transactionLevel === 0) {
this.db.exec('COMMIT');
} else {
// 释放保存点
this.db.exec(`RELEASE SAVEPOINT sp${this.transactionLevel}`);
}
return {
success: true,
transactionLevel: this.transactionLevel
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// 回滚事务
function rollbackTransaction() {
if (!this.isConnected) {
return {
success: false,
error: '数据库未连接'
};
}
if (this.transactionLevel === 0) {
return {
success: false,
error: '没有活动的事务'
};
}
try {
this.transactionLevel--;
if (this.transactionLevel === 0) {
this.db.exec('ROLLBACK');
} else {
// 回滚到保存点
this.db.exec(`ROLLBACK TO SAVEPOINT sp${this.transactionLevel}`);
}
return {
success: true,
transactionLevel: this.transactionLevel
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// 创建表
function createTable(tableName, columns, options = {}) {
var {
ifNotExists = true,
primaryKey = null,
indexes = []
} = options;
var sql = `CREATE TABLE ${ifNotExists ? 'IF NOT EXISTS' : ''} ${tableName} (`;
var columnDefs = [];
for (var [name, type] of Object.entries(columns)) {
var columnDef = `${name} ${type}`;
if (primaryKey === name) {
columnDef += ' PRIMARY KEY';
}
columnDefs.push(columnDef);
}
sql += columnDefs.join(', ') + ')';
var result = this.execute(sql);
if (result.success && indexes.length > 0) {
// 创建索引
for (var index of indexes) {
var indexSql = `CREATE INDEX IF NOT EXISTS idx_${tableName}_${index.columns.join('_')} ON ${tableName} (${index.columns.join(', ')})`;
this.execute(indexSql);
}
}
return result;
}
// 插入数据
function insert(tableName, data) {
var columns = Object.keys(data);
var values = Object.values(data);
var placeholders = columns.map(() => '?').join(', ');
var sql = `INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`;
return this.execute(sql, values);
}
// 批量插入数据
function insertBatch(tableName, dataArray) {
if (dataArray.length === 0) {
return {
success: false,
error: '数据数组为空'
};
}
var beginResult = this.beginTransaction();
if (!beginResult.success) {
return beginResult;
}
try {
var insertedCount = 0;
for (var data of dataArray) {
var result = this.insert(tableName, data);
if (result.success) {
insertedCount++;
} else {
this.rollbackTransaction();
return {
success: false,
error: `批量插入失败: ${result.error}`,
insertedCount: insertedCount
};
}
}
var commitResult = this.commitTransaction();
if (commitResult.success) {
return {
success: true,
insertedCount: insertedCount
};
} else {
return commitResult;
}
} catch (error) {
this.rollbackTransaction();
return {
success: false,
error: error.message,
insertedCount: insertedCount
};
}
}
// 更新数据
function update(tableName, data, where, whereParams = []) {
var setClause = Object.keys(data).map(key => `${key} = ?`).join(', ');
var values = Object.values(data).concat(whereParams);
var sql = `UPDATE ${tableName} SET ${setClause}`;
if (where) {
sql += ` WHERE ${where}`;
}
return this.execute(sql, values);
}
// 删除数据
function delete(tableName, where, whereParams = []) {
var sql = `DELETE FROM ${tableName}`;
if (where) {
sql += ` WHERE ${where}`;
}
return this.execute(sql, whereParams);
}
// 查询数据
function select(tableName, options = {}) {
var {
columns = '*',
where = null,
whereParams = [],
orderBy = null,
limit = null,
offset = null
} = options;
var sql = `SELECT ${Array.isArray(columns) ? columns.join(', ') : columns} FROM ${tableName}`;
if (where) {
sql += ` WHERE ${where}`;
}
if (orderBy) {
sql += ` ORDER BY ${orderBy}`;
}
if (limit) {
sql += ` LIMIT ${limit}`;
if (offset) {
sql += ` OFFSET ${offset}`;
}
}
return this.query(sql, whereParams);
}
// 获取表信息
function getTableInfo(tableName) {
var result = this.query(`PRAGMA table_info(${tableName})`);
if (result.success) {
return {
success: true,
columns: result.data,
columnCount: result.data.length
};
}
return result;
}
// 获取数据库信息
function getDatabaseInfo() {
try {
var tablesResult = this.query("SELECT name FROM sqlite_master WHERE type='table'");
var indexesResult = this.query("SELECT name FROM sqlite_master WHERE type='index'");
var viewsResult = this.query("SELECT name FROM sqlite_master WHERE type='view'");
return {
success: true,
tables: tablesResult.success ? tablesResult.data.map(row => row.name) : [],
indexes: indexesResult.success ? indexesResult.data.map(row => row.name) : [],
views: viewsResult.success ? viewsResult.data.map(row => row.name) : [],
path: this.dbPath,
connected: this.isConnected
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// 备份数据库
function backup(backupPath) {
if (!this.isConnected) {
return {
success: false,
error: '数据库未连接'
};
}
try {
this.db.backup(backupPath);
return {
success: true,
backupPath: backupPath
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// 恢复数据库
function restore(backupPath) {
try {
// 关闭当前连接
this.close();
// 复制备份文件
System.fs.copyFile(backupPath, this.dbPath);
// 重新连接
var connectResult = this.connect();
return {
success: connectResult.success,
error: connectResult.error,
restoredFrom: backupPath
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
}
// 使用示例
function sqliteExample() {
var dbManager = new SQLiteManager('example.db');
// 连接数据库
var connectResult = dbManager.connect();
if (!connectResult.success) {
stdout.println('数据库连接失败:', connectResult.error);
return;
}
// 创建用户表
var createTableResult = dbManager.createTable('users', {
id: 'INTEGER PRIMARY KEY AUTOINCREMENT',
name: 'TEXT NOT NULL',
email: 'TEXT UNIQUE NOT NULL',
age: 'INTEGER',
created_at: 'DATETIME DEFAULT CURRENT_TIMESTAMP'
}, {
indexes: [
{ columns: ['email'] },
{ columns: ['name', 'age'] }
]
});
stdout.println('创建表结果:', JSON.stringify(createTableResult, null, 2));
// 插入测试数据
var users = [
{ name: '张三', email: 'zhangsan@example.com', age: 25 },
{ name: '李四', email: 'lisi@example.com', age: 30 },
{ name: '王五', email: 'wangwu@example.com', age: 28 }
];
var insertResult = dbManager.insertBatch('users', users);
stdout.println('批量插入结果:', JSON.stringify(insertResult, null, 2));
// 查询数据
var selectResult = dbManager.select('users', {
orderBy: 'age DESC',
limit: 10
});
stdout.println('查询结果:', JSON.stringify(selectResult, null, 2));
// 更新数据
var updateResult = dbManager.update('users',
{ age: 26 },
'name = ?',
['张三']
);
stdout.println('更新结果:', JSON.stringify(updateResult, null, 2));
// 事务示例
var transactionResult = dbManager.beginTransaction();
if (transactionResult.success) {
var insertResult1 = dbManager.insert('users', {
name: '赵六',
email: 'zhaoliu@example.com',
age: 35
});
var insertResult2 = dbManager.insert('users', {
name: '孙七',
email: 'sunqi@example.com',
age: 32
});
if (insertResult1.success && insertResult2.success) {
dbManager.commitTransaction();
stdout.println('事务提交成功');
} else {
dbManager.rollbackTransaction();
stdout.println('事务回滚');
}
}
// 获取数据库信息
var dbInfo = dbManager.getDatabaseInfo();
stdout.println('数据库信息:', JSON.stringify(dbInfo, null, 2));
// 备份数据库
var backupResult = dbManager.backup('example_backup.db');
stdout.println('备份结果:', JSON.stringify(backupResult, null, 2));
// 关闭数据库连接
dbManager.close();
}
8.5.2 其他数据库支持
// 通用数据库连接管理器
class DatabaseManager {
function this() {
this.connections = new Map();
this.defaultConnection = null;
}
// 添加数据库连接
function addConnection(name, config) {
try {
var connection;
switch (config.type) {
case 'sqlite':
connection = new SQLiteManager(config.path);
break;
case 'mysql':
connection = System.database.mysql.connect({
host: config.host,
port: config.port || 3306,
user: config.user,
password: config.password,
database: config.database
});
break;
case 'postgresql':
connection = System.database.postgresql.connect({
host: config.host,
port: config.port || 5432,
user: config.user,
password: config.password,
database: config.database
});
break;
default:
throw new Error(`不支持的数据库类型: ${config.type}`);
}
this.connections.set(name, {
connection: connection,
config: config,
type: config.type
});
if (!this.defaultConnection) {
this.defaultConnection = name;
}
return {
success: true,
connectionName: name
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// 获取数据库连接
function getConnection(name = null) {
var connectionName = name || this.defaultConnection;
if (!connectionName) {
return {
success: false,
error: '没有可用的数据库连接'
};
}
var connectionInfo = this.connections.get(connectionName);
if (!connectionInfo) {
return {
success: false,
error: `连接不存在: ${connectionName}`
};
}
return {
success: true,
connection: connectionInfo.connection,
type: connectionInfo.type
};
}
// 移除数据库连接
function removeConnection(name) {
var connectionInfo = this.connections.get(name);
if (connectionInfo) {
try {
if (connectionInfo.connection.close) {
connectionInfo.connection.close();
}
this.connections.delete(name);
if (this.defaultConnection === name) {
this.defaultConnection = this.connections.size > 0 ?
this.connections.keys().next().value : null;
}
return { success: true };
} catch (error) {
return {
success: false,
error: error.message
};
}
}
return {
success: false,
error: `连接不存在: ${name}`
};
}
// 获取所有连接信息
function getConnectionList() {
var connections = [];
for (var [name, info] of this.connections) {
connections.push({
name: name,
type: info.type,
isDefault: name === this.defaultConnection
});
}
return {
success: true,
connections: connections,
defaultConnection: this.defaultConnection
};
}
// 设置默认连接
function setDefaultConnection(name) {
if (this.connections.has(name)) {
this.defaultConnection = name;
return { success: true };
}
return {
success: false,
error: `连接不存在: ${name}`
};
}
}
// 使用示例
function databaseManagerExample() {
var dbManager = new DatabaseManager();
// 添加SQLite连接
dbManager.addConnection('main', {
type: 'sqlite',
path: 'main.db'
});
// 添加MySQL连接(如果支持)
dbManager.addConnection('mysql', {
type: 'mysql',
host: 'localhost',
user: 'root',
password: 'password',
database: 'testdb'
});
// 获取连接列表
var connectionList = dbManager.getConnectionList();
stdout.println('数据库连接列表:', JSON.stringify(connectionList, null, 2));
// 使用默认连接
var defaultConn = dbManager.getConnection();
if (defaultConn.success) {
stdout.println('使用默认连接:', defaultConn.type);
if (defaultConn.type === 'sqlite') {
var connectResult = defaultConn.connection.connect();
stdout.println('连接结果:', JSON.stringify(connectResult, null, 2));
}
}
}
8.6 本章总结
8.6.1 核心要点
文件系统操作
- 文件读写、复制、移动、删除
- 目录管理和搜索
- 文件监控和变化检测
- 路径处理和文件信息获取
网络通信
- HTTP客户端请求处理
- 文件上传和下载
- 请求拦截器和响应处理
- WebSocket实时通信
- 连接管理和自动重连
系统集成
- 系统通知管理
- 托盘图标和上下文菜单
- 权限检查和用户交互
- 系统事件监听
数据库操作
- SQLite数据库管理
- 事务处理和批量操作
- 数据库备份和恢复
- 多数据库连接管理
8.6.2 最佳实践
错误处理
- 统一的错误返回格式
- 详细的错误信息记录
- 优雅的错误恢复机制
- 用户友好的错误提示
资源管理
- 及时释放文件句柄
- 正确关闭数据库连接
- 清理定时器和监听器
- 内存使用优化
安全考虑
- 文件路径验证
- SQL注入防护
- 网络请求安全
- 权限检查机制
性能优化
- 异步操作处理
- 批量数据操作
- 连接池管理
- 缓存策略应用
8.6.3 练习题
基础练习
- 创建一个文件管理器,实现文件的基本操作
- 实现一个简单的HTTP客户端,支持GET和POST请求
- 创建系统通知功能,支持不同类型的通知
- 实现SQLite数据库的基本CRUD操作
进阶练习
- 开发文件同步工具,监控文件变化并自动同步
- 实现WebSocket聊天客户端,支持实时消息传递
- 创建系统托盘应用,提供快捷操作菜单
- 开发数据库管理工具,支持多种数据库类型
高级练习
- 构建完整的文件备份系统,支持增量备份
- 实现分布式文件传输系统
- 开发系统监控工具,集成通知和托盘功能
- 创建数据库迁移工具,支持版本管理
通过本章的学习,你已经掌握了Sciter中原生API的集成方法,能够开发功能丰富的桌面应用程序。下一章我们将学习性能优化与调试,帮助你构建高性能的Sciter应用。
8.1.3 API使用原则
- 安全性:原生API具有系统级权限,需要谨慎使用
- 异步处理:大多数API操作是异步的,需要正确处理回调
- 错误处理:必须实现完善的错误处理机制
- 资源管理:及时释放文件句柄、网络连接等资源
- 跨平台兼容:考虑不同操作系统的差异
8.2 文件系统操作
8.2.1 基础文件操作
// 文件操作管理器
class FileManager {
function this() {
this.encoding = 'utf-8';
}
// 读取文件
function readFile(filePath, encoding = null) {
try {
var actualEncoding = encoding || this.encoding;
// 检查文件是否存在
if (!System.fs.stat(filePath)) {
throw new Error('文件不存在: ' + filePath);
}
// 读取文件内容
var content = System.fs.readFile(filePath, actualEncoding);
return {
success: true,
content: content,
size: content.length,
encoding: actualEncoding
};
} catch (error) {
return {
success: false,
error: error.message,
filePath: filePath
};
}
}
// 写入文件
function writeFile(filePath, content, encoding = null) {
try {
var actualEncoding = encoding || this.encoding;
// 确保目录存在
var dirPath = System.path.dirname(filePath);
this.ensureDirectory(dirPath);
// 写入文件
System.fs.writeFile(filePath, content, actualEncoding);
return {
success: true,
filePath: filePath,
size: content.length,
encoding: actualEncoding
};
} catch (error) {
return {
success: false,
error: error.message,
filePath: filePath
};
}
}
// 追加文件内容
function appendFile(filePath, content, encoding = null) {
try {
var actualEncoding = encoding || this.encoding;
// 如果文件不存在,创建新文件
if (!System.fs.stat(filePath)) {
return this.writeFile(filePath, content, actualEncoding);
}
// 读取现有内容
var existingContent = System.fs.readFile(filePath, actualEncoding);
var newContent = existingContent + content;
// 写入合并后的内容
return this.writeFile(filePath, newContent, actualEncoding);
} catch (error) {
return {
success: false,
error: error.message,
filePath: filePath
};
}
}
// 复制文件
function copyFile(sourcePath, destPath) {
try {
// 检查源文件
if (!System.fs.stat(sourcePath)) {
throw new Error('源文件不存在: ' + sourcePath);
}
// 确保目标目录存在
var destDir = System.path.dirname(destPath);
this.ensureDirectory(destDir);
// 读取源文件
var content = System.fs.readFile(sourcePath, 'binary');
// 写入目标文件
System.fs.writeFile(destPath, content, 'binary');
return {
success: true,
sourcePath: sourcePath,
destPath: destPath,
size: content.length
};
} catch (error) {
return {
success: false,
error: error.message,
sourcePath: sourcePath,
destPath: destPath
};
}
}
// 移动文件
function moveFile(sourcePath, destPath) {
try {
// 先复制文件
var copyResult = this.copyFile(sourcePath, destPath);
if (!copyResult.success) {
return copyResult;
}
// 删除源文件
var deleteResult = this.deleteFile(sourcePath);
if (!deleteResult.success) {
// 如果删除失败,尝试删除已复制的文件
this.deleteFile(destPath);
return deleteResult;
}
return {
success: true,
sourcePath: sourcePath,
destPath: destPath
};
} catch (error) {
return {
success: false,
error: error.message,
sourcePath: sourcePath,
destPath: destPath
};
}
}
// 删除文件
function deleteFile(filePath) {
try {
if (!System.fs.stat(filePath)) {
return {
success: true,
message: '文件不存在,无需删除',
filePath: filePath
};
}
System.fs.unlink(filePath);
return {
success: true,
filePath: filePath
};
} catch (error) {
return {
success: false,
error: error.message,
filePath: filePath
};
}
}
// 获取文件信息
function getFileInfo(filePath) {
try {
var stat = System.fs.stat(filePath);
if (!stat) {
throw new Error('文件不存在: ' + filePath);
}
return {
success: true,
path: filePath,
size: stat.size,
isFile: stat.isFile,
isDirectory: stat.isDirectory,
created: new Date(stat.ctime),
modified: new Date(stat.mtime),
accessed: new Date(stat.atime),
permissions: stat.mode
};
} catch (error) {
return {
success: false,
error: error.message,
filePath: filePath
};
}
}
// 确保目录存在
function ensureDirectory(dirPath) {
try {
if (System.fs.stat(dirPath)) {
return { success: true, existed: true };
}
// 递归创建父目录
var parentDir = System.path.dirname(dirPath);
if (parentDir !== dirPath) {
this.ensureDirectory(parentDir);
}
System.fs.mkdir(dirPath);
return {
success: true,
created: true,
dirPath: dirPath
};
} catch (error) {
return {
success: false,
error: error.message,
dirPath: dirPath
};
}
}
}
// 使用示例
function fileOperationExample() {
var fileManager = new FileManager();
// 写入文件
var writeResult = fileManager.writeFile('test.txt', 'Hello, Sciter!');
stdout.println('写入结果:', JSON.stringify(writeResult, null, 2));
// 读取文件
var readResult = fileManager.readFile('test.txt');
stdout.println('读取结果:', JSON.stringify(readResult, null, 2));
// 追加内容
var appendResult = fileManager.appendFile('test.txt', '\n追加的内容');
stdout.println('追加结果:', JSON.stringify(appendResult, null, 2));
// 获取文件信息
var infoResult = fileManager.getFileInfo('test.txt');
stdout.println('文件信息:', JSON.stringify(infoResult, null, 2));
// 复制文件
var copyResult = fileManager.copyFile('test.txt', 'backup/test_copy.txt');
stdout.println('复制结果:', JSON.stringify(copyResult, null, 2));
}
8.2.2 目录操作
// 目录操作管理器
class DirectoryManager {
function this() {
this.fileManager = new FileManager();
}
// 列出目录内容
function listDirectory(dirPath, options = {}) {
try {
var {
recursive = false,
includeFiles = true,
includeDirectories = true,
filter = null,
sortBy = 'name' // name, size, modified
} = options;
if (!System.fs.stat(dirPath)) {
throw new Error('目录不存在: ' + dirPath);
}
var items = [];
// 获取目录项
var entries = System.fs.readdir(dirPath);
for (var entry of entries) {
var fullPath = System.path.join(dirPath, entry);
var stat = System.fs.stat(fullPath);
if (!stat) continue;
var item = {
name: entry,
path: fullPath,
isFile: stat.isFile,
isDirectory: stat.isDirectory,
size: stat.size,
modified: new Date(stat.mtime),
created: new Date(stat.ctime)
};
// 应用过滤器
if (filter && !filter(item)) {
continue;
}
// 根据类型过滤
if ((item.isFile && !includeFiles) ||
(item.isDirectory && !includeDirectories)) {
continue;
}
items.push(item);
// 递归处理子目录
if (recursive && item.isDirectory) {
var subItems = this.listDirectory(fullPath, options);
if (subItems.success) {
items = items.concat(subItems.items);
}
}
}
// 排序
this.sortItems(items, sortBy);
return {
success: true,
path: dirPath,
items: items,
count: items.length
};
} catch (error) {
return {
success: false,
error: error.message,
path: dirPath
};
}
}
// 创建目录
function createDirectory(dirPath, recursive = true) {
try {
if (System.fs.stat(dirPath)) {
return {
success: true,
existed: true,
path: dirPath
};
}
if (recursive) {
return this.fileManager.ensureDirectory(dirPath);
} else {
System.fs.mkdir(dirPath);
return {
success: true,
created: true,
path: dirPath
};
}
} catch (error) {
return {
success: false,
error: error.message,
path: dirPath
};
}
}
// 删除目录
function removeDirectory(dirPath, recursive = false) {
try {
if (!System.fs.stat(dirPath)) {
return {
success: true,
message: '目录不存在,无需删除',
path: dirPath
};
}
if (recursive) {
// 递归删除目录内容
var listResult = this.listDirectory(dirPath, {
includeFiles: true,
includeDirectories: true
});
if (listResult.success) {
// 先删除文件,再删除子目录
var files = listResult.items.filter(item => item.isFile);
var dirs = listResult.items.filter(item => item.isDirectory);
// 删除文件
for (var file of files) {
this.fileManager.deleteFile(file.path);
}
// 删除子目录(逆序,确保先删除深层目录)
dirs.sort((a, b) => b.path.length - a.path.length);
for (var dir of dirs) {
System.fs.rmdir(dir.path);
}
}
}
// 删除目录本身
System.fs.rmdir(dirPath);
return {
success: true,
path: dirPath
};
} catch (error) {
return {
success: false,
error: error.message,
path: dirPath
};
}
}
// 复制目录
function copyDirectory(sourcePath, destPath, options = {}) {
try {
var { overwrite = false } = options;
if (!System.fs.stat(sourcePath)) {
throw new Error('源目录不存在: ' + sourcePath);
}
if (System.fs.stat(destPath) && !overwrite) {
throw new Error('目标目录已存在: ' + destPath);
}
// 创建目标目录
this.createDirectory(destPath, true);
// 获取源目录内容
var listResult = this.listDirectory(sourcePath, {
recursive: true,
includeFiles: true,
includeDirectories: true
});
if (!listResult.success) {
throw new Error('无法读取源目录: ' + listResult.error);
}
var copiedFiles = 0;
var copiedDirs = 0;
for (var item of listResult.items) {
var relativePath = System.path.relative(sourcePath, item.path);
var targetPath = System.path.join(destPath, relativePath);
if (item.isDirectory) {
this.createDirectory(targetPath);
copiedDirs++;
} else {
var copyResult = this.fileManager.copyFile(item.path, targetPath);
if (copyResult.success) {
copiedFiles++;
}
}
}
return {
success: true,
sourcePath: sourcePath,
destPath: destPath,
copiedFiles: copiedFiles,
copiedDirectories: copiedDirs
};
} catch (error) {
return {
success: false,
error: error.message,
sourcePath: sourcePath,
destPath: destPath
};
}
}
// 排序项目
function sortItems(items, sortBy) {
switch (sortBy) {
case 'name':
items.sort((a, b) => a.name.localeCompare(b.name));
break;
case 'size':
items.sort((a, b) => b.size - a.size);
break;
case 'modified':
items.sort((a, b) => b.modified.getTime() - a.modified.getTime());
break;
}
}
// 搜索文件
function searchFiles(dirPath, pattern, options = {}) {
try {
var {
recursive = true,
caseSensitive = false,
searchContent = false,
fileExtensions = null
} = options;
var results = [];
var regex = new RegExp(pattern, caseSensitive ? 'g' : 'gi');
var listResult = this.listDirectory(dirPath, {
recursive: recursive,
includeFiles: true,
includeDirectories: false
});
if (!listResult.success) {
return listResult;
}
for (var item of listResult.items) {
var matched = false;
var matchType = '';
var matchDetails = null;
// 检查文件扩展名
if (fileExtensions) {
var ext = System.path.extname(item.name).toLowerCase();
if (!fileExtensions.includes(ext)) {
continue;
}
}
// 检查文件名
if (regex.test(item.name)) {
matched = true;
matchType = 'filename';
}
// 搜索文件内容
if (searchContent && !matched) {
var readResult = this.fileManager.readFile(item.path);
if (readResult.success && regex.test(readResult.content)) {
matched = true;
matchType = 'content';
// 找到匹配的行
var lines = readResult.content.split('\n');
var matchedLines = [];
for (var i = 0; i < lines.length; i++) {
if (regex.test(lines[i])) {
matchedLines.push({
lineNumber: i + 1,
content: lines[i].trim()
});
}
}
matchDetails = { matchedLines: matchedLines };
}
}
if (matched) {
results.push({
...item,
matchType: matchType,
matchDetails: matchDetails
});
}
}
return {
success: true,
pattern: pattern,
searchPath: dirPath,
results: results,
count: results.length
};
} catch (error) {
return {
success: false,
error: error.message,
pattern: pattern,
searchPath: dirPath
};
}
}
}
// 使用示例
function directoryOperationExample() {
var dirManager = new DirectoryManager();
// 创建测试目录结构
dirManager.createDirectory('test_project/src/components');
dirManager.createDirectory('test_project/src/utils');
dirManager.createDirectory('test_project/docs');
var fileManager = new FileManager();
// 创建一些测试文件
fileManager.writeFile('test_project/src/components/Button.js', 'export class Button {}');
fileManager.writeFile('test_project/src/components/Modal.js', 'export class Modal {}');
fileManager.writeFile('test_project/src/utils/helpers.js', 'export function helper() {}');
fileManager.writeFile('test_project/README.md', '# Test Project\nThis is a test project.');
// 列出目录内容
var listResult = dirManager.listDirectory('test_project', {
recursive: true,
sortBy: 'name'
});
stdout.println('目录内容:', JSON.stringify(listResult, null, 2));
// 搜索文件
var searchResult = dirManager.searchFiles('test_project', 'Button', {
recursive: true,
searchContent: true
});
stdout.println('搜索结果:', JSON.stringify(searchResult, null, 2));
// 复制目录
var copyResult = dirManager.copyDirectory('test_project', 'test_project_backup');
stdout.println('复制结果:', JSON.stringify(copyResult, null, 2));
}
8.2.3 文件监控
// 文件监控管理器
class FileWatcher {
function this() {
this.watchers = new Map();
this.watchId = 0;
}
// 监控文件或目录
function watch(path, options = {}) {
try {
var {
recursive = false,
events = ['created', 'modified', 'deleted'],
debounceMs = 100,
filter = null
} = options;
var watchId = ++this.watchId;
// 创建监控器
var watcher = {
id: watchId,
path: path,
options: options,
lastEvents: new Map(),
callbacks: [],
active: true
};
// 使用Sciter的文件系统监控API
var systemWatcher = System.fs.watch(path, {
recursive: recursive,
callback: function(event) {
this.handleFileEvent(watcher, event);
}.bind(this)
});
watcher.systemWatcher = systemWatcher;
this.watchers.set(watchId, watcher);
return {
success: true,
watchId: watchId,
path: path
};
} catch (error) {
return {
success: false,
error: error.message,
path: path
};
}
}
// 处理文件事件
function handleFileEvent(watcher, event) {
try {
var { path, type, filename } = event;
var fullPath = filename ? System.path.join(path, filename) : path;
// 应用过滤器
if (watcher.options.filter && !watcher.options.filter(fullPath, type)) {
return;
}
// 防抖处理
var eventKey = fullPath + ':' + type;
var now = Date.now();
var lastTime = watcher.lastEvents.get(eventKey) || 0;
if (now - lastTime < watcher.options.debounceMs) {
return;
}
watcher.lastEvents.set(eventKey, now);
// 创建事件对象
var fileEvent = {
type: type,
path: fullPath,
filename: filename,
timestamp: new Date(),
watchId: watcher.id
};
// 触发回调
for (var callback of watcher.callbacks) {
try {
callback(fileEvent);
} catch (callbackError) {
stdout.println('文件监控回调错误:', callbackError.message);
}
}
} catch (error) {
stdout.println('文件事件处理错误:', error.message);
}
}
// 添加事件监听器
function on(watchId, callback) {
var watcher = this.watchers.get(watchId);
if (watcher) {
watcher.callbacks.push(callback);
return true;
}
return false;
}
// 移除事件监听器
function off(watchId, callback) {
var watcher = this.watchers.get(watchId);
if (watcher) {
var index = watcher.callbacks.indexOf(callback);
if (index !== -1) {
watcher.callbacks.splice(index, 1);
return true;
}
}
return false;
}
// 停止监控
function unwatch(watchId) {
var watcher = this.watchers.get(watchId);
if (watcher) {
watcher.active = false;
if (watcher.systemWatcher) {
watcher.systemWatcher.close();
}
this.watchers.delete(watchId);
return {
success: true,
watchId: watchId
};
}
return {
success: false,
error: '监控器不存在',
watchId: watchId
};
}
// 停止所有监控
function unwatchAll() {
var stopped = [];
for (var [watchId, watcher] of this.watchers) {
var result = this.unwatch(watchId);
stopped.push(result);
}
return {
success: true,
stopped: stopped
};
}
// 获取监控状态
function getWatcherInfo(watchId) {
var watcher = this.watchers.get(watchId);
if (watcher) {
return {
success: true,
id: watcher.id,
path: watcher.path,
options: watcher.options,
active: watcher.active,
callbackCount: watcher.callbacks.length
};
}
return {
success: false,
error: '监控器不存在',
watchId: watchId
};
}
// 列出所有监控器
function listWatchers() {
var watchers = [];
for (var [watchId, watcher] of this.watchers) {
watchers.push({
id: watcher.id,
path: watcher.path,
active: watcher.active,
callbackCount: watcher.callbacks.length
});
}
return {
success: true,
watchers: watchers,
count: watchers.length
};
}
}
// 使用示例
function fileWatcherExample() {
var watcher = new FileWatcher();
// 监控项目目录
var watchResult = watcher.watch('test_project', {
recursive: true,
events: ['created', 'modified', 'deleted'],
debounceMs: 200,
filter: function(path, type) {
// 只监控特定文件类型
var ext = System.path.extname(path).toLowerCase();
return ['.js', '.ts', '.css', '.html', '.md'].includes(ext);
}
});
if (watchResult.success) {
stdout.println('开始监控:', watchResult.path);
// 添加事件监听器
watcher.on(watchResult.watchId, function(event) {
stdout.println('文件事件:', {
type: event.type,
path: event.path,
time: event.timestamp.toLocaleString()
});
});
// 模拟文件操作
setTimeout(function() {
var fileManager = new FileManager();
// 创建新文件
fileManager.writeFile('test_project/new_file.js', 'console.log("Hello");');
// 修改现有文件
setTimeout(function() {
fileManager.appendFile('test_project/README.md', '\n\n## 更新内容');
}, 500);
// 删除文件
setTimeout(function() {
fileManager.deleteFile('test_project/new_file.js');
}, 1000);
}, 1000);
// 10秒后停止监控
setTimeout(function() {
watcher.unwatch(watchResult.watchId);
stdout.println('停止监控');
}, 10000);
} else {
stdout.println('监控失败:', watchResult.error);
}
}
8.3 网络请求处理
8.3.1 HTTP客户端
// HTTP客户端管理器
class HttpClient {
function this(options = {}) {
this.baseURL = options.baseURL || '';
this.timeout = options.timeout || 30000;
this.headers = options.headers || {};
this.interceptors = {
request: [],
response: []
};
}
// 发送HTTP请求
function request(method, url, options = {}) {
return new Promise(function(resolve, reject) {
try {
var {
data = null,
headers = {},
timeout = this.timeout,
responseType = 'json', // json, text, blob
withCredentials = false
} = options;
// 构建完整URL
var fullURL = this.buildURL(url);
// 合并请求头
var requestHeaders = Object.assign({}, this.headers, headers);
// 应用请求拦截器
var requestConfig = {
method: method,
url: fullURL,
data: data,
headers: requestHeaders,
timeout: timeout
};
for (var interceptor of this.interceptors.request) {
requestConfig = interceptor(requestConfig) || requestConfig;
}
// 创建XMLHttpRequest
var xhr = new XMLHttpRequest();
// 设置超时
xhr.timeout = timeout;
// 设置响应类型
if (responseType === 'blob') {
xhr.responseType = 'blob';
} else if (responseType === 'text') {
xhr.responseType = 'text';
}
// 设置事件处理器
xhr.onload = function() {
var response = this.createResponse(xhr, responseType);
// 应用响应拦截器
for (var interceptor of this.interceptors.response) {
response = interceptor(response) || response;
}
if (xhr.status >= 200 && xhr.status < 300) {
resolve(response);
} else {
reject(new Error('HTTP Error: ' + xhr.status + ' ' + xhr.statusText));
}
}.bind(this);
xhr.onerror = function() {
reject(new Error('Network Error'));
};
xhr.ontimeout = function() {
reject(new Error('Request Timeout'));
};
// 打开连接
xhr.open(method.toUpperCase(), requestConfig.url, true);
// 设置请求头
for (var [key, value] of Object.entries(requestConfig.headers)) {
xhr.setRequestHeader(key, value);
}
// 发送请求
if (data) {
if (typeof data === 'object' && !(data instanceof FormData)) {
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
} else {
xhr.send(data);
}
} else {
xhr.send();
}
} catch (error) {
reject(error);
}
}.bind(this));
}
// 创建响应对象
function createResponse(xhr, responseType) {
var data;
if (responseType === 'json') {
try {
data = JSON.parse(xhr.responseText);
} catch (e) {
data = xhr.responseText;
}
} else if (responseType === 'blob') {
data = xhr.response;
} else {
data = xhr.responseText;
}
return {
data: data,
status: xhr.status,
statusText: xhr.statusText,
headers: this.parseHeaders(xhr.getAllResponseHeaders()),
config: {
method: xhr.method,
url: xhr.responseURL
}
};
}
// 解析响应头
function parseHeaders(headerString) {
var headers = {};
if (!headerString) return headers;
var lines = headerString.split('\r\n');
for (var line of lines) {
var parts = line.split(': ');
if (parts.length === 2) {
headers[parts[0].toLowerCase()] = parts[1];
}
}
return headers;
}
// 构建完整URL
function buildURL(url) {
if (url.startsWith('http://') || url.startsWith('https://')) {
return url;
}
if (this.baseURL) {
return this.baseURL.replace(/\/$/, '') + '/' + url.replace(/^\//, '');
}
return url;
}
// GET请求
function get(url, options = {}) {
return this.request('GET', url, options);
}
// POST请求
function post(url, data, options = {}) {
return this.request('POST', url, Object.assign({ data: data }, options));
}
// PUT请求
function put(url, data, options = {}) {
return this.request('PUT', url, Object.assign({ data: data }, options));
}
// DELETE请求
function delete(url, options = {}) {
return this.request('DELETE', url, options);
}
// PATCH请求
function patch(url, data, options = {}) {
return this.request('PATCH', url, Object.assign({ data: data }, options));
}
// 添加请求拦截器
function addRequestInterceptor(interceptor) {
this.interceptors.request.push(interceptor);
}
// 添加响应拦截器
function addResponseInterceptor(interceptor) {
this.interceptors.response.push(interceptor);
}
// 下载文件
function downloadFile(url, localPath, options = {}) {
return new Promise(function(resolve, reject) {
var {
onProgress = null,
headers = {}
} = options;
this.request('GET', url, {
headers: headers,
responseType: 'blob'
}).then(function(response) {
try {
// 将blob数据写入文件
var fileManager = new FileManager();
var writeResult = fileManager.writeFile(localPath, response.data, 'binary');
if (writeResult.success) {
resolve({
success: true,
localPath: localPath,
size: writeResult.size,
url: url
});
} else {
reject(new Error('文件写入失败: ' + writeResult.error));
}
} catch (error) {
reject(error);
}
}).catch(reject);
}.bind(this));
}
// 上传文件
function uploadFile(url, filePath, options = {}) {
return new Promise(function(resolve, reject) {
try {
var {
fieldName = 'file',
additionalFields = {},
headers = {},
onProgress = null
} = options;
// 读取文件
var fileManager = new FileManager();
var readResult = fileManager.readFile(filePath, 'binary');
if (!readResult.success) {
reject(new Error('文件读取失败: ' + readResult.error));
return;
}
// 创建FormData
var formData = new FormData();
// 添加文件
var fileName = System.path.basename(filePath);
var blob = new Blob([readResult.content]);
formData.append(fieldName, blob, fileName);
// 添加其他字段
for (var [key, value] of Object.entries(additionalFields)) {
formData.append(key, value);
}
// 发送请求
this.request('POST', url, {
data: formData,
headers: headers
}).then(resolve).catch(reject);
} catch (error) {
reject(error);
}
}.bind(this));
}
}
// 使用示例
function httpClientExample() {
// 创建HTTP客户端
var client = new HttpClient({
baseURL: 'https://api.example.com',
timeout: 10000,
headers: {
'User-Agent': 'Sciter-App/1.0'
}
});
// 添加请求拦截器
client.addRequestInterceptor(function(config) {
stdout.println('发送请求:', config.method, config.url);
// 添加认证头
config.headers['Authorization'] = 'Bearer your-token-here';
return config;
});
// 添加响应拦截器
client.addResponseInterceptor(function(response) {
stdout.println('收到响应:', response.status, response.statusText);
return response;
});
// GET请求示例
client.get('/users/1')
.then(function(response) {
stdout.println('用户数据:', JSON.stringify(response.data, null, 2));
})
.catch(function(error) {
stdout.println('请求失败:', error.message);
});
// POST请求示例
client.post('/users', {
name: 'John Doe',
email: 'john@example.com'
})
.then(function(response) {
stdout.println('创建用户成功:', JSON.stringify(response.data, null, 2));
})
.catch(function(error) {
stdout.println('创建用户失败:', error.message);
});
// 文件下载示例
client.downloadFile('https://example.com/file.pdf', 'downloads/file.pdf')
.then(function(result) {
stdout.println('下载完成:', result.localPath, '大小:', result.size);
})
.catch(function(error) {
stdout.println('下载失败:', error.message);
});
// 文件上传示例
client.uploadFile('/upload', 'local_file.jpg', {
fieldName: 'image',
additionalFields: {
description: '测试图片',
category: 'test'
}
})
.then(function(response) {
stdout.println('上传成功:', JSON.stringify(response.data, null, 2));
})
.catch(function(error) {
stdout.println('上传失败:', error.message);
});
}