10.1 项目规划与架构设计

10.1.1 项目需求分析

在开始项目开发之前,我们需要进行详细的需求分析和架构设计。本章将通过一个完整的桌面应用项目来演示Sciter的实际应用。

// 项目需求管理器
namespace ProjectPlanning {
    
    // 需求分析器
    class RequirementAnalyzer {
        function this() {
            this.requirements = new Map();
            this.stakeholders = [];
            this.priorities = ['low', 'medium', 'high', 'critical'];
            this.categories = ['functional', 'non-functional', 'technical', 'business'];
        }
        
        // 添加需求
        function addRequirement(id, requirement) {
            this.requirements.set(id, {
                id: id,
                title: requirement.title,
                description: requirement.description,
                category: requirement.category || 'functional',
                priority: requirement.priority || 'medium',
                stakeholder: requirement.stakeholder,
                acceptanceCriteria: requirement.acceptanceCriteria || [],
                dependencies: requirement.dependencies || [],
                estimatedEffort: requirement.estimatedEffort || 0,
                status: 'pending',
                createdAt: new Date().toISOString(),
                updatedAt: new Date().toISOString()
            });
            
            stdout.println(`需求已添加: ${id} - ${requirement.title}`);
        }
        
        // 更新需求状态
        function updateRequirementStatus(id, status) {
            var requirement = this.requirements.get(id);
            if (requirement) {
                requirement.status = status;
                requirement.updatedAt = new Date().toISOString();
                stdout.println(`需求状态已更新: ${id} -> ${status}`);
            }
        }
        
        // 获取需求列表
        function getRequirements(filter = null) {
            var requirements = Array.from(this.requirements.values());
            
            if (filter) {
                requirements = requirements.filter(req => {
                    if (filter.category && req.category !== filter.category) return false;
                    if (filter.priority && req.priority !== filter.priority) return false;
                    if (filter.status && req.status !== filter.status) return false;
                    if (filter.stakeholder && req.stakeholder !== filter.stakeholder) return false;
                    return true;
                });
            }
            
            return requirements;
        }
        
        // 生成需求报告
        function generateReport() {
            var requirements = Array.from(this.requirements.values());
            var report = {
                totalRequirements: requirements.length,
                byCategory: {},
                byPriority: {},
                byStatus: {},
                totalEffort: 0
            };
            
            // 统计分类
            for (var category of this.categories) {
                report.byCategory[category] = requirements.filter(req => req.category === category).length;
            }
            
            // 统计优先级
            for (var priority of this.priorities) {
                report.byPriority[priority] = requirements.filter(req => req.priority === priority).length;
            }
            
            // 统计状态
            var statuses = ['pending', 'in-progress', 'completed', 'cancelled'];
            for (var status of statuses) {
                report.byStatus[status] = requirements.filter(req => req.status === status).length;
            }
            
            // 计算总工作量
            report.totalEffort = requirements.reduce((sum, req) => sum + req.estimatedEffort, 0);
            
            return report;
        }
    }
    
    // 架构设计器
    class ArchitectureDesigner {
        function this() {
            this.components = new Map();
            this.layers = ['presentation', 'business', 'data', 'infrastructure'];
            this.patterns = ['mvc', 'mvp', 'mvvm', 'component-based'];
            this.technologies = [];
        }
        
        // 添加组件
        function addComponent(id, component) {
            this.components.set(id, {
                id: id,
                name: component.name,
                type: component.type,
                layer: component.layer,
                responsibilities: component.responsibilities || [],
                dependencies: component.dependencies || [],
                interfaces: component.interfaces || [],
                technologies: component.technologies || [],
                description: component.description
            });
            
            stdout.println(`组件已添加: ${id} - ${component.name}`);
        }
        
        // 定义组件依赖
        function addDependency(fromComponent, toComponent, type = 'uses') {
            var component = this.components.get(fromComponent);
            if (component) {
                component.dependencies.push({
                    target: toComponent,
                    type: type,
                    description: `${fromComponent} ${type} ${toComponent}`
                });
                
                stdout.println(`依赖已添加: ${fromComponent} -> ${toComponent}`);
            }
        }
        
        // 验证架构
        function validateArchitecture() {
            var issues = [];
            
            // 检查循环依赖
            var cycles = this.detectCycles();
            if (cycles.length > 0) {
                issues.push({
                    type: 'circular-dependency',
                    message: '检测到循环依赖',
                    details: cycles
                });
            }
            
            // 检查层级违规
            var layerViolations = this.checkLayerViolations();
            if (layerViolations.length > 0) {
                issues.push({
                    type: 'layer-violation',
                    message: '检测到层级违规',
                    details: layerViolations
                });
            }
            
            // 检查孤立组件
            var orphanComponents = this.findOrphanComponents();
            if (orphanComponents.length > 0) {
                issues.push({
                    type: 'orphan-components',
                    message: '发现孤立组件',
                    details: orphanComponents
                });
            }
            
            return {
                isValid: issues.length === 0,
                issues: issues
            };
        }
        
        // 检测循环依赖
        function detectCycles() {
            var visited = new Set();
            var recursionStack = new Set();
            var cycles = [];
            
            for (var [componentId] of this.components) {
                if (!visited.has(componentId)) {
                    this.detectCyclesHelper(componentId, visited, recursionStack, [], cycles);
                }
            }
            
            return cycles;
        }
        
        // 循环依赖检测辅助方法
        function detectCyclesHelper(componentId, visited, recursionStack, path, cycles) {
            visited.add(componentId);
            recursionStack.add(componentId);
            path.push(componentId);
            
            var component = this.components.get(componentId);
            if (component) {
                for (var dependency of component.dependencies) {
                    var targetId = dependency.target;
                    
                    if (!visited.has(targetId)) {
                        this.detectCyclesHelper(targetId, visited, recursionStack, path, cycles);
                    } else if (recursionStack.has(targetId)) {
                        // 找到循环
                        var cycleStart = path.indexOf(targetId);
                        var cycle = path.slice(cycleStart).concat([targetId]);
                        cycles.push(cycle);
                    }
                }
            }
            
            path.pop();
            recursionStack.delete(componentId);
        }
        
        // 检查层级违规
        function checkLayerViolations() {
            var violations = [];
            var layerOrder = this.layers;
            
            for (var [componentId, component] of this.components) {
                var componentLayerIndex = layerOrder.indexOf(component.layer);
                
                for (var dependency of component.dependencies) {
                    var targetComponent = this.components.get(dependency.target);
                    if (targetComponent) {
                        var targetLayerIndex = layerOrder.indexOf(targetComponent.layer);
                        
                        // 上层不应该依赖下层
                        if (componentLayerIndex < targetLayerIndex) {
                            violations.push({
                                from: componentId,
                                to: dependency.target,
                                fromLayer: component.layer,
                                toLayer: targetComponent.layer,
                                message: `${component.layer}层组件不应依赖${targetComponent.layer}层组件`
                            });
                        }
                    }
                }
            }
            
            return violations;
        }
        
        // 查找孤立组件
        function findOrphanComponents() {
            var referencedComponents = new Set();
            
            // 收集所有被引用的组件
            for (var [componentId, component] of this.components) {
                for (var dependency of component.dependencies) {
                    referencedComponents.add(dependency.target);
                }
            }
            
            // 查找没有被引用且没有依赖的组件
            var orphans = [];
            for (var [componentId, component] of this.components) {
                if (!referencedComponents.has(componentId) && component.dependencies.length === 0) {
                    orphans.push(componentId);
                }
            }
            
            return orphans;
        }
        
        // 生成架构图
        function generateArchitectureDiagram() {
            var diagram = {
                nodes: [],
                edges: [],
                layers: {}
            };
            
            // 添加节点
            for (var [componentId, component] of this.components) {
                diagram.nodes.push({
                    id: componentId,
                    label: component.name,
                    layer: component.layer,
                    type: component.type
                });
                
                // 按层分组
                if (!diagram.layers[component.layer]) {
                    diagram.layers[component.layer] = [];
                }
                diagram.layers[component.layer].push(componentId);
            }
            
            // 添加边
            for (var [componentId, component] of this.components) {
                for (var dependency of component.dependencies) {
                    diagram.edges.push({
                        from: componentId,
                        to: dependency.target,
                        type: dependency.type,
                        label: dependency.type
                    });
                }
            }
            
            return diagram;
        }
    }
}

// 使用示例
function projectPlanningExample() {
    // 需求分析示例
    var analyzer = new ProjectPlanning.RequirementAnalyzer();
    
    // 添加功能需求
    analyzer.addRequirement('REQ-001', {
        title: '用户登录功能',
        description: '用户可以通过用户名和密码登录系统',
        category: 'functional',
        priority: 'high',
        stakeholder: '最终用户',
        acceptanceCriteria: [
            '用户可以输入用户名和密码',
            '系统验证用户凭据',
            '登录成功后跳转到主界面',
            '登录失败显示错误信息'
        ],
        estimatedEffort: 8
    });
    
    analyzer.addRequirement('REQ-002', {
        title: '数据可视化',
        description: '以图表形式展示业务数据',
        category: 'functional',
        priority: 'medium',
        stakeholder: '业务用户',
        acceptanceCriteria: [
            '支持多种图表类型',
            '数据实时更新',
            '支持交互操作'
        ],
        estimatedEffort: 16
    });
    
    analyzer.addRequirement('REQ-003', {
        title: '性能要求',
        description: '应用启动时间不超过3秒',
        category: 'non-functional',
        priority: 'high',
        stakeholder: '所有用户',
        estimatedEffort: 12
    });
    
    // 生成需求报告
    var report = analyzer.generateReport();
    stdout.println('需求分析报告:', JSON.stringify(report, null, 2));
    
    // 架构设计示例
    var designer = new ProjectPlanning.ArchitectureDesigner();
    
    // 添加组件
    designer.addComponent('ui-layer', {
        name: 'UI层',
        type: 'layer',
        layer: 'presentation',
        responsibilities: ['用户界面', '用户交互', '数据展示'],
        technologies: ['Sciter', 'CSS', 'JavaScript']
    });
    
    designer.addComponent('business-layer', {
        name: '业务逻辑层',
        type: 'layer',
        layer: 'business',
        responsibilities: ['业务规则', '数据处理', '业务流程'],
        technologies: ['JavaScript', 'Business Rules Engine']
    });
    
    designer.addComponent('data-layer', {
        name: '数据访问层',
        type: 'layer',
        layer: 'data',
        responsibilities: ['数据存储', '数据检索', '数据持久化'],
        technologies: ['SQLite', 'File System']
    });
    
    // 定义依赖关系
    designer.addDependency('ui-layer', 'business-layer', 'calls');
    designer.addDependency('business-layer', 'data-layer', 'uses');
    
    // 验证架构
    var validation = designer.validateArchitecture();
    stdout.println('架构验证结果:', JSON.stringify(validation, null, 2));
    
    // 生成架构图
    var diagram = designer.generateArchitectureDiagram();
    stdout.println('架构图:', JSON.stringify(diagram, null, 2));
    
    stdout.println('项目规划示例完成');
}

10.2 完整项目开发

10.2.1 项目结构设计

// 项目结构管理器
namespace ProjectStructure {
    
    // 项目生成器
    class ProjectGenerator {
        function this() {
            this.templates = new Map();
            this.projectTypes = ['desktop-app', 'utility-tool', 'dashboard', 'game'];
            this.initializeTemplates();
        }
        
        // 初始化项目模板
        function initializeTemplates() {
            // 桌面应用模板
            this.templates.set('desktop-app', {
                name: '桌面应用',
                structure: {
                    'src/': {
                        'components/': {
                            'common/': {},
                            'pages/': {},
                            'dialogs/': {}
                        },
                        'services/': {
                            'api/': {},
                            'data/': {},
                            'utils/': {}
                        },
                        'assets/': {
                            'images/': {},
                            'styles/': {},
                            'fonts/': {}
                        },
                        'config/': {},
                        'main.js': 'entry point',
                        'app.htm': 'main window'
                    },
                    'tests/': {
                        'unit/': {},
                        'integration/': {},
                        'e2e/': {}
                    },
                    'docs/': {
                        'api/': {},
                        'user-guide/': {}
                    },
                    'build/': {},
                    'dist/': {},
                    'package.json': 'project configuration',
                    'README.md': 'project documentation',
                    '.gitignore': 'git ignore rules'
                },
                files: {
                    'src/main.js': this.getMainJsTemplate(),
                    'src/app.htm': this.getAppHtmlTemplate(),
                    'package.json': this.getPackageJsonTemplate('desktop-app'),
                    'README.md': this.getReadmeTemplate()
                }
            });
            
            // 工具应用模板
            this.templates.set('utility-tool', {
                name: '工具应用',
                structure: {
                    'src/': {
                        'core/': {},
                        'ui/': {},
                        'plugins/': {},
                        'utils/': {},
                        'main.js': 'entry point',
                        'tool.htm': 'main interface'
                    },
                    'plugins/': {},
                    'config/': {},
                    'package.json': 'project configuration'
                },
                files: {
                    'src/main.js': this.getToolMainTemplate(),
                    'src/tool.htm': this.getToolHtmlTemplate(),
                    'package.json': this.getPackageJsonTemplate('utility-tool')
                }
            });
        }
        
        // 生成项目
        function generateProject(projectName, projectType, options = {}) {
            var template = this.templates.get(projectType);
            if (!template) {
                throw new Error(`未知的项目类型: ${projectType}`);
            }
            
            var project = {
                name: projectName,
                type: projectType,
                structure: this.processStructure(template.structure, options),
                files: this.processFiles(template.files, projectName, options),
                metadata: {
                    createdAt: new Date().toISOString(),
                    generator: 'Sciter Project Generator',
                    version: '1.0.0'
                }
            };
            
            stdout.println(`项目已生成: ${projectName} (${template.name})`);
            return project;
        }
        
        // 处理项目结构
        function processStructure(structure, options) {
            var processed = {};
            
            for (var key in structure) {
                if (typeof structure[key] === 'object' && structure[key] !== null) {
                    processed[key] = this.processStructure(structure[key], options);
                } else {
                    processed[key] = structure[key];
                }
            }
            
            return processed;
        }
        
        // 处理项目文件
        function processFiles(files, projectName, options) {
            var processed = {};
            
            for (var filePath in files) {
                var content = files[filePath];
                
                // 替换模板变量
                content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
                content = content.replace(/\{\{AUTHOR\}\}/g, options.author || 'Unknown');
                content = content.replace(/\{\{DESCRIPTION\}\}/g, options.description || '');
                content = content.replace(/\{\{VERSION\}\}/g, options.version || '1.0.0');
                
                processed[filePath] = content;
            }
            
            return processed;
        }
        
        // 获取主入口文件模板
        function getMainJsTemplate() {
            return `// {{PROJECT_NAME}} - 主入口文件
// 作者: {{AUTHOR}}
// 版本: {{VERSION}}

include "src/components/common/app-framework.js";
include "src/services/api/api-client.js";
include "src/services/data/data-manager.js";

// 应用程序类
class Application {
    function this() {
        this.isInitialized = false;
        this.config = null;
        this.services = {};
    }
    
    // 初始化应用
    function initialize() {
        if (this.isInitialized) {
            return;
        }
        
        try {
            // 加载配置
            this.loadConfiguration();
            
            // 初始化服务
            this.initializeServices();
            
            // 设置全局错误处理
            this.setupErrorHandling();
            
            // 初始化UI
            this.initializeUI();
            
            this.isInitialized = true;
            stdout.println('应用初始化完成');
        } catch (error) {
            stdout.println('应用初始化失败:', error.message);
            throw error;
        }
    }
    
    // 加载配置
    function loadConfiguration() {
        this.config = {
            appName: '{{PROJECT_NAME}}',
            version: '{{VERSION}}',
            debug: true,
            window: {
                width: 1200,
                height: 800,
                resizable: true,
                center: true
            },
            database: {
                path: 'data/app.db',
                autoCreate: true
            }
        };
    }
    
    // 初始化服务
    function initializeServices() {
        this.services.dataManager = new DataManager(this.config.database);
        this.services.apiClient = new ApiClient(this.config.api);
    }
    
    // 设置错误处理
    function setupErrorHandling() {
        window.addEventListener('error', function(event) {
            stdout.println('全局错误:', event.error.message);
            // 这里可以添加错误报告逻辑
        });
    }
    
    // 初始化UI
    function initializeUI() {
        // 设置窗口属性
        if (this.config.window) {
            var win = Window.this;
            if (this.config.window.center) {
                win.center();
            }
        }
        
        // 初始化主界面
        this.initializeMainInterface();
    }
    
    // 初始化主界面
    function initializeMainInterface() {
        // 这里添加主界面初始化逻辑
        stdout.println('主界面初始化完成');
    }
    
    // 启动应用
    function start() {
        this.initialize();
        stdout.println('{{PROJECT_NAME}} 已启动');
    }
    
    // 关闭应用
    function shutdown() {
        try {
            // 清理资源
            if (this.services.dataManager) {
                this.services.dataManager.close();
            }
            
            stdout.println('应用已关闭');
        } catch (error) {
            stdout.println('关闭应用时发生错误:', error.message);
        }
    }
}

// 全局应用实例
var app = new Application();

// 文档就绪时启动应用
document.ready = function() {
    app.start();
};

// 窗口关闭时清理资源
window.addEventListener('beforeunload', function() {
    app.shutdown();
});`;
        }
        
        // 获取HTML模板
        function getAppHtmlTemplate() {
            return `<!DOCTYPE html>
<html>
<head>
    <title>{{PROJECT_NAME}}</title>
    <meta charset="utf-8">
    <style>
        @import url("src/assets/styles/main.css");
    </style>
    <script type="text/tiscript">
        include "src/main.js";
    </script>
</head>
<body>
    <div id="app">
        <header class="app-header">
            <h1>{{PROJECT_NAME}}</h1>
            <nav class="app-nav">
                <!-- 导航菜单 -->
            </nav>
        </header>
        
        <main class="app-main">
            <aside class="app-sidebar">
                <!-- 侧边栏 -->
            </aside>
            
            <section class="app-content">
                <!-- 主要内容区域 -->
                <div class="welcome-message">
                    <h2>欢迎使用 {{PROJECT_NAME}}</h2>
                    <p>这是一个基于Sciter构建的桌面应用程序。</p>
                </div>
            </section>
        </main>
        
        <footer class="app-footer">
            <p>&copy; 2024 {{PROJECT_NAME}} v{{VERSION}}</p>
        </footer>
    </div>
</body>
</html>`;
        }
        
        // 获取package.json模板
        function getPackageJsonTemplate(projectType) {
            return `{
  "name": "{{PROJECT_NAME}}",
  "version": "{{VERSION}}",
  "description": "{{DESCRIPTION}}",
  "main": "src/main.js",
  "author": "{{AUTHOR}}",
  "license": "MIT",
  "scripts": {
    "start": "sciter src/app.htm",
    "build": "sciter-packager src/app.htm",
    "test": "sciter-test tests/",
    "lint": "eslint src/"
  },
  "dependencies": {
    "sciter-js": "^5.0.0"
  },
  "devDependencies": {
    "sciter-packager": "^1.0.0",
    "sciter-test": "^1.0.0",
    "eslint": "^8.0.0"
  },
  "keywords": [
    "sciter",
    "desktop-app",
    "${projectType}"
  ]
}`;
        }
        
        // 获取README模板
        function getReadmeTemplate() {
            return `# {{PROJECT_NAME}}

{{DESCRIPTION}}

## 功能特性

- 现代化的用户界面
- 高性能的桌面应用
- 跨平台支持
- 易于扩展和维护

## 安装和运行

### 前置要求

- Sciter SDK
- Node.js (可选,用于构建工具)

### 运行应用

\`\`\`bash
# 直接运行
sciter src/app.htm

# 或使用npm脚本
npm start
\`\`\`

### 构建应用

\`\`\`bash
npm run build
\`\`\`

## 项目结构

\`\`\`
{{PROJECT_NAME}}/
├── src/                 # 源代码
│   ├── components/      # 组件
│   ├── services/        # 服务层
│   ├── assets/          # 资源文件
│   ├── config/          # 配置文件
│   ├── main.js          # 主入口
│   └── app.htm          # 主窗口
├── tests/               # 测试文件
├── docs/                # 文档
├── build/               # 构建输出
└── package.json         # 项目配置
\`\`\`

## 开发指南

### 添加新功能

1. 在 \`src/components/\` 中创建新组件
2. 在 \`src/services/\` 中添加相关服务
3. 更新主界面和路由
4. 添加相应的测试

### 代码规范

- 使用一致的代码风格
- 添加适当的注释
- 编写单元测试
- 遵循组件化开发原则

## 许可证

MIT License

## 作者

{{AUTHOR}}

## 版本历史

- v{{VERSION}} - 初始版本`;
        }
        
        // 获取工具应用主文件模板
        function getToolMainTemplate() {
            return `// {{PROJECT_NAME}} - 工具应用主文件

class ToolApplication {
    function this() {
        this.plugins = new Map();
        this.config = {};
    }
    
    function initialize() {
        this.loadPlugins();
        this.setupUI();
    }
    
    function loadPlugins() {
        // 加载插件逻辑
    }
    
    function setupUI() {
        // 设置用户界面
    }
}

var toolApp = new ToolApplication();
document.ready = function() {
    toolApp.initialize();
};`;
        }
        
        // 获取工具应用HTML模板
        function getToolHtmlTemplate() {
            return `<!DOCTYPE html>
<html>
<head>
    <title>{{PROJECT_NAME}}</title>
    <script type="text/tiscript">
        include "main.js";
    </script>
</head>
<body>
    <div id="tool-interface">
        <h1>{{PROJECT_NAME}}</h1>
        <!-- 工具界面 -->
    </div>
</body>
</html>`;
        }
        
        // 创建项目文件
        function createProjectFiles(project, basePath) {
            var createdFiles = [];
            
            try {
                // 创建目录结构
                this.createDirectoryStructure(project.structure, basePath);
                
                // 创建文件
                for (var filePath in project.files) {
                    var fullPath = `${basePath}/${filePath}`;
                    var content = project.files[filePath];
                    
                    // 这里应该使用实际的文件写入API
                    // System.fs.writeFile(fullPath, content);
                    
                    createdFiles.push(fullPath);
                    stdout.println(`文件已创建: ${fullPath}`);
                }
                
                stdout.println(`项目创建完成: ${createdFiles.length} 个文件`);
                return createdFiles;
            } catch (error) {
                stdout.println('创建项目文件失败:', error.message);
                throw error;
            }
        }
        
        // 创建目录结构
        function createDirectoryStructure(structure, basePath) {
            for (var key in structure) {
                if (key.endsWith('/')) {
                    // 这是一个目录
                    var dirPath = `${basePath}/${key}`;
                    // System.fs.createDirectory(dirPath);
                    
                    if (typeof structure[key] === 'object') {
                        this.createDirectoryStructure(structure[key], dirPath.slice(0, -1));
                    }
                }
            }
        }
    }
}

// 使用示例
function projectStructureExample() {
    var generator = new ProjectStructure.ProjectGenerator();
    
    // 生成桌面应用项目
    var project = generator.generateProject('MyDesktopApp', 'desktop-app', {
        author: 'John Doe',
        description: '一个功能强大的桌面应用程序',
        version: '1.0.0'
    });
    
    stdout.println('生成的项目:', JSON.stringify(project.metadata, null, 2));
    
    // 创建项目文件(在实际环境中)
    // var createdFiles = generator.createProjectFiles(project, './my-desktop-app');
    
    stdout.println('项目结构示例完成');
}

10.2.2 核心功能实现

// 核心功能模块
namespace CoreFeatures {
    
    // 用户认证管理器
    class AuthenticationManager {
        function this() {
            this.currentUser = null;
            this.sessionTimeout = 30 * 60 * 1000; // 30分钟
            this.sessionTimer = null;
            this.loginAttempts = new Map();
            this.maxLoginAttempts = 3;
            this.lockoutDuration = 15 * 60 * 1000; // 15分钟
        }
        
        // 用户登录
        function login(username, password) {
            return new Promise((resolve, reject) => {
                try {
                    // 检查账户是否被锁定
                    if (this.isAccountLocked(username)) {
                        reject(new Error('账户已被锁定,请稍后再试'));
                        return;
                    }
                    
                    // 验证用户凭据
                    this.validateCredentials(username, password)
                        .then(user => {
                            // 登录成功
                            this.currentUser = user;
                            this.startSession();
                            this.clearLoginAttempts(username);
                            
                            // 记录登录日志
                            this.logLoginEvent(username, 'success');
                            
                            resolve({
                                success: true,
                                user: user,
                                token: this.generateSessionToken(user)
                            });
                        })
                        .catch(error => {
                            // 登录失败
                            this.recordFailedAttempt(username);
                            this.logLoginEvent(username, 'failure', error.message);
                            reject(error);
                        });
                } catch (error) {
                    reject(error);
                }
            });
        }
        
        // 验证用户凭据
        function validateCredentials(username, password) {
            return new Promise((resolve, reject) => {
                // 模拟异步验证过程
                setTimeout(() => {
                    // 这里应该连接到实际的用户数据库
                    var users = [
                        { id: 1, username: 'admin', password: 'admin123', role: 'administrator', name: '管理员' },
                        { id: 2, username: 'user', password: 'user123', role: 'user', name: '普通用户' }
                    ];
                    
                    var user = users.find(u => u.username === username);
                    
                    if (!user) {
                        reject(new Error('用户不存在'));
                        return;
                    }
                    
                    // 在实际应用中,应该使用加密的密码比较
                    if (user.password !== password) {
                        reject(new Error('密码错误'));
                        return;
                    }
                    
                    // 返回用户信息(不包含密码)
                    var { password: _, ...userInfo } = user;
                    resolve(userInfo);
                }, 500);
            });
        }
        
        // 检查账户是否被锁定
        function isAccountLocked(username) {
            var attempts = this.loginAttempts.get(username);
            if (!attempts) {
                return false;
            }
            
            var now = Date.now();
            var recentAttempts = attempts.filter(time => now - time < this.lockoutDuration);
            
            return recentAttempts.length >= this.maxLoginAttempts;
        }
        
        // 记录失败的登录尝试
        function recordFailedAttempt(username) {
            if (!this.loginAttempts.has(username)) {
                this.loginAttempts.set(username, []);
            }
            
            this.loginAttempts.get(username).push(Date.now());
        }
        
        // 清除登录尝试记录
        function clearLoginAttempts(username) {
            this.loginAttempts.delete(username);
        }
        
        // 开始会话
        function startSession() {
            // 清除现有的会话定时器
            if (this.sessionTimer) {
                clearTimeout(this.sessionTimer);
            }
            
            // 设置会话超时
            this.sessionTimer = setTimeout(() => {
                this.logout('session_timeout');
            }, this.sessionTimeout);
        }
        
        // 刷新会话
        function refreshSession() {
            if (this.currentUser) {
                this.startSession();
            }
        }
        
        // 生成会话令牌
        function generateSessionToken(user) {
            var payload = {
                userId: user.id,
                username: user.username,
                role: user.role,
                timestamp: Date.now()
            };
            
            // 简化的令牌生成(实际应用中应使用JWT等标准)
            return btoa(JSON.stringify(payload));
        }
        
        // 用户登出
        function logout(reason = 'user_action') {
            if (this.currentUser) {
                this.logLoginEvent(this.currentUser.username, 'logout', reason);
                this.currentUser = null;
            }
            
            if (this.sessionTimer) {
                clearTimeout(this.sessionTimer);
                this.sessionTimer = null;
            }
            
            // 触发登出事件
            document.dispatchEvent(new CustomEvent('user-logout', {
                detail: { reason: reason }
            }));
        }
        
        // 检查用户是否已登录
        function isLoggedIn() {
            return this.currentUser !== null;
        }
        
        // 获取当前用户
        function getCurrentUser() {
            return this.currentUser;
        }
        
        // 检查用户权限
        function hasPermission(permission) {
            if (!this.currentUser) {
                return false;
            }
            
            // 管理员拥有所有权限
            if (this.currentUser.role === 'administrator') {
                return true;
            }
            
            // 这里应该实现更复杂的权限检查逻辑
            var userPermissions = this.getUserPermissions(this.currentUser.role);
            return userPermissions.includes(permission);
        }
        
        // 获取用户权限列表
        function getUserPermissions(role) {
            var permissions = {
                'administrator': ['read', 'write', 'delete', 'admin'],
                'user': ['read', 'write'],
                'guest': ['read']
            };
            
            return permissions[role] || [];
        }
        
        // 记录登录事件
        function logLoginEvent(username, event, details = '') {
            var logEntry = {
                timestamp: new Date().toISOString(),
                username: username,
                event: event,
                details: details,
                ip: 'localhost', // 在实际应用中获取真实IP
                userAgent: navigator.userAgent
            };
            
            // 这里应该将日志保存到数据库或文件
            stdout.println('登录日志:', JSON.stringify(logEntry));
        }
    }
    
    // 数据管理器
    class DataManager {
        function this(config = {}) {
            this.config = Object.assign({
                database: 'app.db',
                autoBackup: true,
                backupInterval: 24 * 60 * 60 * 1000, // 24小时
                maxBackups: 7
            }, config);
            
            this.connection = null;
            this.cache = new Map();
            this.backupTimer = null;
        }
        
        // 初始化数据库
        function initialize() {
            return new Promise((resolve, reject) => {
                try {
                    // 这里应该使用实际的数据库连接
                    // this.connection = new SQLite.Database(this.config.database);
                    
                    // 创建必要的表
                    this.createTables()
                        .then(() => {
                            // 启动自动备份
                            if (this.config.autoBackup) {
                                this.startAutoBackup();
                            }
                            
                            stdout.println('数据库初始化完成');
                            resolve();
                        })
                        .catch(reject);
                } catch (error) {
                    reject(error);
                }
            });
        }
        
        // 创建数据表
        function createTables() {
            return new Promise((resolve, reject) => {
                var tables = [
                    {
                        name: 'users',
                        schema: `
                            CREATE TABLE IF NOT EXISTS users (
                                id INTEGER PRIMARY KEY AUTOINCREMENT,
                                username TEXT UNIQUE NOT NULL,
                                password TEXT NOT NULL,
                                email TEXT,
                                role TEXT DEFAULT 'user',
                                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                                updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
                            )
                        `
                    },
                    {
                        name: 'settings',
                        schema: `
                            CREATE TABLE IF NOT EXISTS settings (
                                key TEXT PRIMARY KEY,
                                value TEXT,
                                type TEXT DEFAULT 'string',
                                updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
                            )
                        `
                    },
                    {
                        name: 'logs',
                        schema: `
                            CREATE TABLE IF NOT EXISTS logs (
                                id INTEGER PRIMARY KEY AUTOINCREMENT,
                                level TEXT NOT NULL,
                                message TEXT NOT NULL,
                                data TEXT,
                                timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
                            )
                        `
                    }
                ];
                
                // 模拟表创建过程
                setTimeout(() => {
                    stdout.println(`已创建 ${tables.length} 个数据表`);
                    resolve();
                }, 100);
            });
        }
        
        // 查询数据
        function query(sql, params = []) {
            return new Promise((resolve, reject) => {
                try {
                    // 检查缓存
                    var cacheKey = this.getCacheKey(sql, params);
                    if (this.cache.has(cacheKey)) {
                        var cached = this.cache.get(cacheKey);
                        if (Date.now() - cached.timestamp < 60000) { // 1分钟缓存
                            resolve(cached.data);
                            return;
                        }
                    }
                    
                    // 模拟数据库查询
                    setTimeout(() => {
                        var result = this.simulateQuery(sql, params);
                        
                        // 缓存结果
                        this.cache.set(cacheKey, {
                            data: result,
                            timestamp: Date.now()
                        });
                        
                        resolve(result);
                    }, 50);
                } catch (error) {
                    reject(error);
                }
            });
        }
        
        // 执行SQL语句
        function execute(sql, params = []) {
            return new Promise((resolve, reject) => {
                try {
                    // 清除相关缓存
                    this.clearRelatedCache(sql);
                    
                    // 模拟SQL执行
                    setTimeout(() => {
                        var result = {
                            affectedRows: 1,
                            insertId: Date.now(),
                            success: true
                        };
                        
                        resolve(result);
                    }, 30);
                } catch (error) {
                    reject(error);
                }
            });
        }
        
        // 模拟查询执行
        function simulateQuery(sql, params) {
            // 这里应该是实际的数据库查询逻辑
            if (sql.includes('SELECT * FROM users')) {
                return [
                    { id: 1, username: 'admin', email: 'admin@example.com', role: 'administrator' },
                    { id: 2, username: 'user', email: 'user@example.com', role: 'user' }
                ];
            }
            
            if (sql.includes('SELECT * FROM settings')) {
                return [
                    { key: 'theme', value: 'dark', type: 'string' },
                    { key: 'language', value: 'zh-CN', type: 'string' },
                    { key: 'autoSave', value: 'true', type: 'boolean' }
                ];
            }
            
            return [];
        }
        
        // 获取缓存键
        function getCacheKey(sql, params) {
            return btoa(sql + JSON.stringify(params));
        }
        
        // 清除相关缓存
        function clearRelatedCache(sql) {
            // 简化的缓存清除逻辑
            if (sql.includes('INSERT') || sql.includes('UPDATE') || sql.includes('DELETE')) {
                this.cache.clear();
            }
        }
        
        // 开始事务
        function beginTransaction() {
            return new Promise((resolve, reject) => {
                // 模拟事务开始
                setTimeout(() => {
                    resolve({
                        commit: () => this.commitTransaction(),
                        rollback: () => this.rollbackTransaction()
                    });
                }, 10);
            });
        }
        
        // 提交事务
        function commitTransaction() {
            return new Promise((resolve) => {
                setTimeout(() => {
                    stdout.println('事务已提交');
                    resolve();
                }, 10);
            });
        }
        
        // 回滚事务
        function rollbackTransaction() {
            return new Promise((resolve) => {
                setTimeout(() => {
                    stdout.println('事务已回滚');
                    resolve();
                }, 10);
            });
        }
        
        // 备份数据库
        function backup() {
            return new Promise((resolve, reject) => {
                try {
                    var timestamp = new Date().toISOString().replace(/[:.]/g, '-');
                    var backupFile = `backup_${timestamp}.db`;
                    
                    // 模拟备份过程
                    setTimeout(() => {
                        stdout.println(`数据库已备份到: ${backupFile}`);
                        
                        // 清理旧备份
                        this.cleanupOldBackups();
                        
                        resolve(backupFile);
                    }, 1000);
                } catch (error) {
                    reject(error);
                }
            });
        }
        
        // 启动自动备份
        function startAutoBackup() {
            this.backupTimer = setInterval(() => {
                this.backup().catch(error => {
                    stdout.println('自动备份失败:', error.message);
                });
            }, this.config.backupInterval);
            
            stdout.println('自动备份已启动');
        }
        
        // 停止自动备份
        function stopAutoBackup() {
            if (this.backupTimer) {
                clearInterval(this.backupTimer);
                this.backupTimer = null;
                stdout.println('自动备份已停止');
            }
        }
        
        // 清理旧备份
        function cleanupOldBackups() {
            // 这里应该实现实际的文件清理逻辑
            stdout.println('清理旧备份文件');
        }
        
        // 关闭数据库连接
        function close() {
            this.stopAutoBackup();
            
            if (this.connection) {
                // this.connection.close();
                this.connection = null;
            }
            
            this.cache.clear();
            stdout.println('数据库连接已关闭');
        }
    }
    
    // 配置管理器
    class ConfigurationManager {
        function this() {
            this.config = new Map();
            this.watchers = new Map();
            this.configFile = 'config.json';
            this.autoSave = true;
        }
        
        // 加载配置
        function load() {
            return new Promise((resolve, reject) => {
                try {
                    // 模拟从文件加载配置
                    setTimeout(() => {
                        var defaultConfig = {
                            'app.name': 'Sciter Application',
                            'app.version': '1.0.0',
                            'app.debug': false,
                            'ui.theme': 'light',
                            'ui.language': 'zh-CN',
                            'ui.fontSize': 14,
                            'window.width': 1200,
                            'window.height': 800,
                            'window.resizable': true,
                            'window.center': true,
                            'data.autoSave': true,
                            'data.saveInterval': 30000,
                            'security.sessionTimeout': 1800000
                        };
                        
                        for (var key in defaultConfig) {
                            this.config.set(key, defaultConfig[key]);
                        }
                        
                        stdout.println('配置已加载');
                        resolve();
                    }, 100);
                } catch (error) {
                    reject(error);
                }
            });
        }
        
        // 保存配置
        function save() {
            return new Promise((resolve, reject) => {
                try {
                    var configObject = {};
                    for (var [key, value] of this.config) {
                        configObject[key] = value;
                    }
                    
                    var configJson = JSON.stringify(configObject, null, 2);
                    
                    // 这里应该写入实际文件
                    // System.fs.writeFile(this.configFile, configJson);
                    
                    setTimeout(() => {
                        stdout.println('配置已保存');
                        resolve();
                    }, 50);
                } catch (error) {
                    reject(error);
                }
            });
        }
        
        // 获取配置值
        function get(key, defaultValue = null) {
            return this.config.get(key) || defaultValue;
        }
        
        // 设置配置值
        function set(key, value) {
            var oldValue = this.config.get(key);
            this.config.set(key, value);
            
            // 触发监听器
            if (this.watchers.has(key)) {
                var watchers = this.watchers.get(key);
                for (var watcher of watchers) {
                    try {
                        watcher(value, oldValue, key);
                    } catch (error) {
                        stdout.println('配置监听器错误:', error.message);
                    }
                }
            }
            
            // 自动保存
            if (this.autoSave) {
                this.save().catch(error => {
                    stdout.println('自动保存配置失败:', error.message);
                });
            }
        }
        
        // 监听配置变化
        function watch(key, callback) {
            if (!this.watchers.has(key)) {
                this.watchers.set(key, []);
            }
            
            this.watchers.get(key).push(callback);
            
            // 返回取消监听的函数
            return () => {
                var watchers = this.watchers.get(key);
                if (watchers) {
                    var index = watchers.indexOf(callback);
                    if (index > -1) {
                        watchers.splice(index, 1);
                    }
                }
            };
        }
        
        // 获取所有配置
        function getAll() {
            var result = {};
            for (var [key, value] of this.config) {
                result[key] = value;
            }
            return result;
        }
        
        // 批量设置配置
        function setMultiple(configs) {
            for (var key in configs) {
                this.set(key, configs[key]);
            }
        }
        
        // 重置配置
        function reset() {
            this.config.clear();
            this.watchers.clear();
            return this.load();
        }
    }
}

// 使用示例
function coreFeaturesExample() {
    // 认证管理器示例
    var authManager = new CoreFeatures.AuthenticationManager();
    
    authManager.login('admin', 'admin123')
        .then(result => {
            stdout.println('登录成功:', JSON.stringify(result, null, 2));
            
            // 检查权限
            var hasAdminPermission = authManager.hasPermission('admin');
            stdout.println('是否有管理员权限:', hasAdminPermission);
        })
        .catch(error => {
            stdout.println('登录失败:', error.message);
        });
    
    // 数据管理器示例
    var dataManager = new CoreFeatures.DataManager();
    
    dataManager.initialize()
        .then(() => {
            return dataManager.query('SELECT * FROM users');
        })
        .then(users => {
            stdout.println('用户列表:', JSON.stringify(users, null, 2));
        })
        .catch(error => {
            stdout.println('数据操作失败:', error.message);
        });
    
    // 配置管理器示例
    var configManager = new CoreFeatures.ConfigurationManager();
    
    configManager.load()
        .then(() => {
            // 监听主题变化
            configManager.watch('ui.theme', (newValue, oldValue) => {
                stdout.println(`主题已从 ${oldValue} 更改为 ${newValue}`);
            });
            
            // 设置配置
            configManager.set('ui.theme', 'dark');
            
            // 获取配置
            var theme = configManager.get('ui.theme');
            stdout.println('当前主题:', theme);
        })
        .catch(error => {
            stdout.println('配置操作失败:', error.message);
        });
    
    stdout.println('核心功能示例完成');
}

10.4 用户界面设计

10.4.1 UI组件库

// UI组件库命名空间
namespace UIComponents {
    
    // 基础组件类
    class BaseComponent {
        function this(element) {
            this.element = element;
            this.initialized = false;
            this.eventHandlers = {};
        }
        
        function initialize() {
            if (this.initialized) return;
            
            this.setupEvents();
            this.render();
            this.initialized = true;
        }
        
        function setupEvents() {
            // 子类实现
        }
        
        function render() {
            // 子类实现
        }
        
        function destroy() {
            // 清理事件监听器
            for (var event in this.eventHandlers) {
                this.element.off(event, this.eventHandlers[event]);
            }
            this.initialized = false;
        }
        
        function on(event, handler) {
            this.eventHandlers[event] = handler;
            this.element.on(event, handler);
        }
        
        function emit(event, data) {
            this.element.post(new Event(event, data));
        }
    }
    
    // 按钮组件
    class Button : BaseComponent {
        function this(element, options = {}) {
            super(element);
            this.options = {
                type: "primary",
                size: "medium",
                disabled: false,
                loading: false,
                ...options
            };
        }
        
        function setupEvents() {
            this.on("click", function(evt) {
                if (this.options.disabled || this.options.loading) {
                    evt.stopPropagation();
                    return false;
                }
                this.emit("button-click", { button: this });
            });
        }
        
        function render() {
            this.element.attributes.addClass("btn");
            this.element.attributes.addClass("btn-" + this.options.type);
            this.element.attributes.addClass("btn-" + this.options.size);
            
            if (this.options.disabled) {
                this.element.attributes.addClass("disabled");
            }
            
            if (this.options.loading) {
                this.element.attributes.addClass("loading");
                this.element.html = '<span class="spinner"></span>' + this.element.text;
            }
        }
        
        function setLoading(loading) {
            this.options.loading = loading;
            this.render();
        }
        
        function setDisabled(disabled) {
            this.options.disabled = disabled;
            this.render();
        }
    }
    
    // 输入框组件
    class Input : BaseComponent {
        function this(element, options = {}) {
            super(element);
            this.options = {
                placeholder: "",
                required: false,
                pattern: null,
                maxLength: null,
                validator: null,
                ...options
            };
            this.isValid = true;
            this.errorMessage = "";
        }
        
        function setupEvents() {
            this.on("input", function(evt) {
                this.validate();
                this.emit("input-change", { 
                    value: this.getValue(), 
                    isValid: this.isValid 
                });
            });
            
            this.on("blur", function(evt) {
                this.validate();
                this.showValidation();
            });
        }
        
        function render() {
            if (this.options.placeholder) {
                this.element.attributes["placeholder"] = this.options.placeholder;
            }
            
            if (this.options.maxLength) {
                this.element.attributes["maxlength"] = this.options.maxLength;
            }
            
            if (this.options.pattern) {
                this.element.attributes["pattern"] = this.options.pattern;
            }
        }
        
        function getValue() {
            return this.element.value || "";
        }
        
        function setValue(value) {
            this.element.value = value;
            this.validate();
        }
        
        function validate() {
            var value = this.getValue();
            
            // 必填验证
            if (this.options.required && !value) {
                this.isValid = false;
                this.errorMessage = "此字段为必填项";
                return false;
            }
            
            // 正则验证
            if (this.options.pattern && value) {
                var regex = new RegExp(this.options.pattern);
                if (!regex.test(value)) {
                    this.isValid = false;
                    this.errorMessage = "格式不正确";
                    return false;
                }
            }
            
            // 自定义验证
            if (this.options.validator && value) {
                var result = this.options.validator(value);
                if (result !== true) {
                    this.isValid = false;
                    this.errorMessage = result || "验证失败";
                    return false;
                }
            }
            
            this.isValid = true;
            this.errorMessage = "";
            return true;
        }
        
        function showValidation() {
            var container = this.element.parent;
            var errorElement = container.$("span.error-message");
            
            if (!this.isValid) {
                this.element.attributes.addClass("error");
                if (!errorElement) {
                    errorElement = new Element("span");
                    errorElement.attributes.addClass("error-message");
                    container.append(errorElement);
                }
                errorElement.text = this.errorMessage;
            } else {
                this.element.attributes.removeClass("error");
                if (errorElement) {
                    errorElement.remove();
                }
            }
        }
    }
    
    // 模态框组件
    class Modal : BaseComponent {
        function this(element, options = {}) {
            super(element);
            this.options = {
                title: "",
                closable: true,
                maskClosable: true,
                width: "500px",
                height: "auto",
                ...options
            };
            this.isVisible = false;
        }
        
        function setupEvents() {
            // 关闭按钮事件
            var closeBtn = this.element.$(".modal-close");
            if (closeBtn) {
                closeBtn.on("click", function() {
                    this.hide();
                });
            }
            
            // 遮罩点击事件
            if (this.options.maskClosable) {
                this.element.on("click", function(evt) {
                    if (evt.target === this.element) {
                        this.hide();
                    }
                });
            }
            
            // ESC键关闭
            if (this.options.closable) {
                view.on("keydown", function(evt) {
                    if (evt.keyCode === 27 && this.isVisible) {
                        this.hide();
                    }
                });
            }
        }
        
        function render() {
            this.element.attributes.addClass("modal");
            
            var dialog = this.element.$(".modal-dialog");
            if (dialog) {
                dialog.style.width = this.options.width;
                if (this.options.height !== "auto") {
                    dialog.style.height = this.options.height;
                }
            }
            
            var title = this.element.$(".modal-title");
            if (title && this.options.title) {
                title.text = this.options.title;
            }
        }
        
        function show() {
            this.element.style.display = "flex";
            this.isVisible = true;
            this.emit("modal-show", { modal: this });
            
            // 添加动画
            this.element.attributes.addClass("show");
        }
        
        function hide() {
            this.element.attributes.removeClass("show");
            
            // 延迟隐藏以完成动画
            view.timer(300, function() {
                this.element.style.display = "none";
                this.isVisible = false;
                this.emit("modal-hide", { modal: this });
            });
        }
        
        function setTitle(title) {
            this.options.title = title;
            var titleElement = this.element.$(".modal-title");
            if (titleElement) {
                titleElement.text = title;
            }
        }
        
        function setContent(content) {
            var body = this.element.$(".modal-body");
            if (body) {
                body.html = content;
            }
        }
    }
}

10.4.2 主题系统

// 主题管理器
class ThemeManager {
    function this() {
        this.currentTheme = "light";
        this.themes = {
            light: {
                primary: "#007bff",
                secondary: "#6c757d",
                success: "#28a745",
                danger: "#dc3545",
                warning: "#ffc107",
                info: "#17a2b8",
                background: "#ffffff",
                surface: "#f8f9fa",
                text: "#212529",
                textSecondary: "#6c757d"
            },
            dark: {
                primary: "#0d6efd",
                secondary: "#6c757d",
                success: "#198754",
                danger: "#dc3545",
                warning: "#fd7e14",
                info: "#0dcaf0",
                background: "#212529",
                surface: "#343a40",
                text: "#ffffff",
                textSecondary: "#adb5bd"
            }
        };
        this.loadTheme();
    }
    
    function setTheme(themeName) {
        if (!this.themes[themeName]) {
            throw new Error("主题不存在: " + themeName);
        }
        
        this.currentTheme = themeName;
        this.applyTheme();
        this.saveTheme();
    }
    
    function applyTheme() {
        var theme = this.themes[this.currentTheme];
        var root = document.documentElement;
        
        for (var property in theme) {
            root.style.setProperty("--color-" + property, theme[property]);
        }
        
        document.body.attributes.removeClass("theme-light", "theme-dark");
        document.body.attributes.addClass("theme-" + this.currentTheme);
    }
    
    function addTheme(name, colors) {
        this.themes[name] = colors;
    }
    
    function getTheme(name) {
        return this.themes[name || this.currentTheme];
    }
    
    function getCurrentTheme() {
        return this.currentTheme;
    }
    
    function saveTheme() {
        Storage.userDataPath("theme.json").save(JSON.stringify({
            current: this.currentTheme
        }));
    }
    
    function loadTheme() {
        try {
            var data = Storage.userDataPath("theme.json").load();
            if (data) {
                var config = JSON.parse(data);
                this.currentTheme = config.current || "light";
            }
        } catch (e) {
            this.currentTheme = "light";
        }
        this.applyTheme();
    }
}

10.4.3 响应式布局

// 响应式布局管理器
class ResponsiveManager {
    function this() {
        this.breakpoints = {
            xs: 0,
            sm: 576,
            md: 768,
            lg: 992,
            xl: 1200,
            xxl: 1400
        };
        this.currentBreakpoint = "lg";
        this.listeners = [];
        this.init();
    }
    
    function init() {
        this.updateBreakpoint();
        view.on("size", function() {
            this.updateBreakpoint();
        });
    }
    
    function updateBreakpoint() {
        var width = view.box(#width);
        var newBreakpoint = "xs";
        
        for (var bp in this.breakpoints) {
            if (width >= this.breakpoints[bp]) {
                newBreakpoint = bp;
            }
        }
        
        if (newBreakpoint !== this.currentBreakpoint) {
            var oldBreakpoint = this.currentBreakpoint;
            this.currentBreakpoint = newBreakpoint;
            this.notifyListeners(oldBreakpoint, newBreakpoint);
        }
    }
    
    function addListener(callback) {
        this.listeners.push(callback);
    }
    
    function removeListener(callback) {
        var index = this.listeners.indexOf(callback);
        if (index > -1) {
            this.listeners.splice(index, 1);
        }
    }
    
    function notifyListeners(oldBreakpoint, newBreakpoint) {
        for (var listener in this.listeners) {
            try {
                listener(newBreakpoint, oldBreakpoint);
            } catch (e) {
                stdout.printf("响应式监听器错误: %s\n", e.toString());
            }
        }
    }
    
    function getCurrentBreakpoint() {
        return this.currentBreakpoint;
    }
    
    function isBreakpoint(bp) {
        var bpIndex = Object.keys(this.breakpoints).indexOf(bp);
        var currentIndex = Object.keys(this.breakpoints).indexOf(this.currentBreakpoint);
        return currentIndex >= bpIndex;
    }
    
    function getViewportSize() {
        return {
            width: view.box(#width),
            height: view.box(#height)
        };
    }
}

10.4.4 应用示例

// 应用初始化
class App {
    function this() {
        this.themeManager = new ThemeManager();
        this.responsiveManager = new ResponsiveManager();
        this.components = {};
        this.init();
    }
    
    function init() {
        this.initComponents();
        this.setupThemeToggle();
        this.setupResponsiveLayout();
    }
    
    function initComponents() {
        // 初始化按钮组件
        var buttons = document.$$("button[data-component='button']");
        for (var btn in buttons) {
            var options = JSON.parse(btn.attributes["data-options"] || "{}");
            this.components[btn.id] = new UIComponents.Button(btn, options);
            this.components[btn.id].initialize();
        }
        
        // 初始化输入框组件
        var inputs = document.$$("input[data-component='input']");
        for (var input in inputs) {
            var options = JSON.parse(input.attributes["data-options"] || "{}");
            this.components[input.id] = new UIComponents.Input(input, options);
            this.components[input.id].initialize();
        }
        
        // 初始化模态框组件
        var modals = document.$$(".modal[data-component='modal']");
        for (var modal in modals) {
            var options = JSON.parse(modal.attributes["data-options"] || "{}");
            this.components[modal.id] = new UIComponents.Modal(modal, options);
            this.components[modal.id].initialize();
        }
    }
    
    function setupThemeToggle() {
        var themeToggle = document.$("#theme-toggle");
        if (themeToggle) {
            themeToggle.on("click", function() {
                var currentTheme = this.themeManager.getCurrentTheme();
                var newTheme = currentTheme === "light" ? "dark" : "light";
                this.themeManager.setTheme(newTheme);
            });
        }
    }
    
    function setupResponsiveLayout() {
        this.responsiveManager.addListener(function(newBreakpoint, oldBreakpoint) {
            stdout.printf("断点变化: %s -> %s\n", oldBreakpoint, newBreakpoint);
            
            // 根据断点调整布局
            var sidebar = document.$("#sidebar");
            if (sidebar) {
                if (this.responsiveManager.isBreakpoint("md")) {
                    sidebar.style.display = "block";
                } else {
                    sidebar.style.display = "none";
                }
            }
        });
    }
    
    function getComponent(id) {
        return this.components[id];
    }
    
    function showModal(id, title, content) {
        var modal = this.getComponent(id);
        if (modal) {
            modal.setTitle(title);
            modal.setContent(content);
            modal.show();
        }
    }
}

// 应用启动
var app = new App();

10.5 测试与质量保证

10.5.1 单元测试框架

// 简单的测试框架
namespace TestFramework {
    
    class TestSuite {
        function this(name) {
            this.name = name;
            this.tests = [];
            this.results = {
                passed: 0,
                failed: 0,
                total: 0
            };
        }
        
        function test(description, testFunction) {
            this.tests.push({
                description: description,
                testFunction: testFunction
            });
        }
        
        function run() {
            stdout.printf("\n运行测试套件: %s\n", this.name);
            stdout.printf("=" * 50 + "\n");
            
            for (var test in this.tests) {
                this.runTest(test);
            }
            
            this.printResults();
        }
        
        function runTest(test) {
            try {
                var assert = new Assert();
                test.testFunction(assert);
                
                if (assert.hasFailures()) {
                    this.results.failed++;
                    stdout.printf("✗ %s\n", test.description);
                    for (var failure in assert.failures) {
                        stdout.printf("  %s\n", failure);
                    }
                } else {
                    this.results.passed++;
                    stdout.printf("✓ %s\n", test.description);
                }
            } catch (e) {
                this.results.failed++;
                stdout.printf("✗ %s\n", test.description);
                stdout.printf("  错误: %s\n", e.toString());
            }
            
            this.results.total++;
        }
        
        function printResults() {
            stdout.printf("\n测试结果:\n");
            stdout.printf("通过: %d\n", this.results.passed);
            stdout.printf("失败: %d\n", this.results.failed);
            stdout.printf("总计: %d\n", this.results.total);
            
            var successRate = (this.results.passed / this.results.total * 100).toFixed(2);
            stdout.printf("成功率: %s%%\n", successRate);
        }
    }
    
    class Assert {
        function this() {
            this.failures = [];
        }
        
        function equal(actual, expected, message) {
            if (actual !== expected) {
                this.failures.push(message || 
                    String.printf("期望 %v 等于 %v", actual, expected));
            }
        }
        
        function notEqual(actual, expected, message) {
            if (actual === expected) {
                this.failures.push(message || 
                    String.printf("期望 %v 不等于 %v", actual, expected));
            }
        }
        
        function isTrue(value, message) {
            if (value !== true) {
                this.failures.push(message || 
                    String.printf("期望 %v 为 true", value));
            }
        }
        
        function isFalse(value, message) {
            if (value !== false) {
                this.failures.push(message || 
                    String.printf("期望 %v 为 false", value));
            }
        }
        
        function isNull(value, message) {
            if (value !== null) {
                this.failures.push(message || 
                    String.printf("期望 %v 为 null", value));
            }
        }
        
        function isNotNull(value, message) {
            if (value === null) {
                this.failures.push(message || "期望值不为 null");
            }
        }
        
        function throws(func, message) {
            var threw = false;
            try {
                func();
            } catch (e) {
                threw = true;
            }
            
            if (!threw) {
                this.failures.push(message || "期望函数抛出异常");
            }
        }
        
        function hasFailures() {
            return this.failures.length > 0;
        }
    }
}

10.5.2 测试用例示例

// 组件测试
var componentTests = new TestFramework.TestSuite("UI组件测试");

componentTests.test("Button组件初始化", function(assert) {
    var element = new Element("button");
    var button = new UIComponents.Button(element, {
        type: "primary",
        size: "large"
    });
    
    button.initialize();
    
    assert.isTrue(button.initialized, "按钮应该已初始化");
    assert.equal(button.options.type, "primary", "按钮类型应该为primary");
    assert.equal(button.options.size, "large", "按钮大小应该为large");
});

componentTests.test("Input组件验证", function(assert) {
    var element = new Element("input");
    var input = new UIComponents.Input(element, {
        required: true,
        pattern: "^\\d+$"
    });
    
    input.initialize();
    
    // 测试空值验证
    input.setValue("");
    assert.isFalse(input.isValid, "空值应该验证失败");
    
    // 测试格式验证
    input.setValue("abc");
    assert.isFalse(input.isValid, "非数字应该验证失败");
    
    // 测试正确值
    input.setValue("123");
    assert.isTrue(input.isValid, "数字应该验证成功");
});

// 主题测试
var themeTests = new TestFramework.TestSuite("主题系统测试");

themeTests.test("主题切换", function(assert) {
    var themeManager = new ThemeManager();
    
    assert.equal(themeManager.getCurrentTheme(), "light", "默认主题应该为light");
    
    themeManager.setTheme("dark");
    assert.equal(themeManager.getCurrentTheme(), "dark", "主题应该切换为dark");
});

themeTests.test("自定义主题", function(assert) {
    var themeManager = new ThemeManager();
    
    themeManager.addTheme("custom", {
        primary: "#ff0000",
        background: "#000000"
    });
    
    var customTheme = themeManager.getTheme("custom");
    assert.equal(customTheme.primary, "#ff0000", "自定义主题颜色应该正确");
});

// 运行所有测试
function runAllTests() {
    componentTests.run();
    themeTests.run();
}

10.6 打包与部署

10.6.1 构建配置

// 构建工具
class BuildTool {
    function this(config = {}) {
        this.config = {
            srcDir: "src",
            distDir: "dist",
            assetsDir: "assets",
            minify: true,
            sourceMaps: false,
            ...config
        };
        this.tasks = [];
    }
    
    function addTask(name, taskFunction) {
        this.tasks.push({
            name: name,
            execute: taskFunction
        });
    }
    
    function build() {
        stdout.printf("开始构建项目...\n");
        
        // 清理输出目录
        this.cleanDist();
        
        // 执行构建任务
        for (var task in this.tasks) {
            try {
                stdout.printf("执行任务: %s\n", task.name);
                task.execute(this.config);
                stdout.printf("任务完成: %s\n", task.name);
            } catch (e) {
                stdout.printf("任务失败: %s - %s\n", task.name, e.toString());
                return false;
            }
        }
        
        stdout.printf("构建完成!\n");
        return true;
    }
    
    function cleanDist() {
        var distPath = System.path(this.config.distDir);
        if (distPath.exists()) {
            distPath.remove(true);
        }
        distPath.mkdir();
    }
    
    function copyFiles(srcPattern, destDir) {
        var srcPath = System.path(this.config.srcDir);
        var files = srcPath.scan(srcPattern);
        
        for (var file in files) {
            var relativePath = file.relativeTo(srcPath);
            var destPath = System.path(this.config.distDir, destDir, relativePath);
            
            destPath.parent.mkdir(true);
            file.copyTo(destPath);
        }
    }
    
    function minifyJS(filePath) {
        if (!this.config.minify) return;
        
        // 简单的JS压缩(移除注释和多余空白)
        var content = filePath.load();
        
        // 移除单行注释
        content = content.replace(/\/\/.*$/gm, "");
        
        // 移除多行注释
        content = content.replace(/\/\*[\s\S]*?\*\//g, "");
        
        // 移除多余空白
        content = content.replace(/\s+/g, " ");
        content = content.replace(/;\s*}/g, "}");
        
        filePath.save(content);
    }
    
    function generateManifest() {
        var manifest = {
            name: "Sciter Application",
            version: "1.0.0",
            description: "A Sciter desktop application",
            main: "main.htm",
            buildTime: new Date().toISOString()
        };
        
        var manifestPath = System.path(this.config.distDir, "manifest.json");
        manifestPath.save(JSON.stringify(manifest, null, 2));
    }
}

10.6.2 部署脚本

// 部署管理器
class DeploymentManager {
    function this(config = {}) {
        this.config = {
            appName: "SciterApp",
            version: "1.0.0",
            platform: System.PLATFORM,
            outputDir: "release",
            ...config
        };
    }
    
    function createInstaller() {
        stdout.printf("创建安装程序...\n");
        
        var installerScript = this.generateInstallerScript();
        var scriptPath = System.path(this.config.outputDir, "installer.nsi");
        scriptPath.save(installerScript);
        
        // 如果有NSIS,可以调用makensis
        try {
            System.exec("makensis " + scriptPath.toString());
            stdout.printf("安装程序创建成功\n");
        } catch (e) {
            stdout.printf("创建安装程序失败: %s\n", e.toString());
        }
    }
    
    function generateInstallerScript() {
        return `
!define APP_NAME "${this.config.appName}"
!define APP_VERSION "${this.config.version}"
!define PUBLISHER "Your Company"
!define WEB_SITE "https://yourwebsite.com"
!define APP_EXE "${this.config.appName}.exe"

Name "\${APP_NAME}"
OutFile "\${APP_NAME}-\${APP_VERSION}-Setup.exe"
InstallDir "$PROGRAMFILES\\\${APP_NAME}"

Section "MainSection" SEC01
    SetOutPath "$INSTDIR"
    File /r "dist\\*"
    
    CreateDirectory "$SMPROGRAMS\\\${APP_NAME}"
    CreateShortCut "$SMPROGRAMS\\\${APP_NAME}\\\${APP_NAME}.lnk" "$INSTDIR\\\${APP_EXE}"
    CreateShortCut "$DESKTOP\\\${APP_NAME}.lnk" "$INSTDIR\\\${APP_EXE}"
SectionEnd

Section "Uninstall"
    Delete "$INSTDIR\\*"
    RMDir /r "$INSTDIR"
    Delete "$SMPROGRAMS\\\${APP_NAME}\\*"
    RMDir "$SMPROGRAMS\\\${APP_NAME}"
    Delete "$DESKTOP\\\${APP_NAME}.lnk"
SectionEnd
`;
    }
    
    function createPortableVersion() {
        stdout.printf("创建便携版...\n");
        
        var portableDir = System.path(this.config.outputDir, "portable");
        portableDir.mkdir(true);
        
        // 复制应用文件
        var distDir = System.path("dist");
        distDir.copyTo(portableDir);
        
        // 创建便携版标识文件
        var portableFlag = System.path(portableDir, "portable.flag");
        portableFlag.save("This is a portable version");
        
        stdout.printf("便携版创建完成\n");
    }
    
    function generateUpdateInfo() {
        var updateInfo = {
            version: this.config.version,
            releaseDate: new Date().toISOString(),
            downloadUrl: "https://yourwebsite.com/downloads/latest",
            changelog: [
                "新功能: 添加了主题切换",
                "改进: 优化了性能",
                "修复: 修复了已知问题"
            ],
            minVersion: "1.0.0"
        };
        
        var updatePath = System.path(this.config.outputDir, "update.json");
        updatePath.save(JSON.stringify(updateInfo, null, 2));
    }
}

10.6.3 自动更新系统

// 自动更新管理器
class UpdateManager {
    function this(config = {}) {
        this.config = {
            updateUrl: "https://yourwebsite.com/api/updates",
            currentVersion: "1.0.0",
            checkInterval: 24 * 60 * 60 * 1000, // 24小时
            ...config
        };
        this.updateTimer = null;
    }
    
    function startAutoCheck() {
        this.checkForUpdates();
        
        this.updateTimer = view.timer(this.config.checkInterval, function() {
            this.checkForUpdates();
        });
    }
    
    function stopAutoCheck() {
        if (this.updateTimer) {
            this.updateTimer.close();
            this.updateTimer = null;
        }
    }
    
    function checkForUpdates() {
        stdout.printf("检查更新...\n");
        
        try {
            var response = this.httpGet(this.config.updateUrl);
            var updateInfo = JSON.parse(response);
            
            if (this.isNewerVersion(updateInfo.version, this.config.currentVersion)) {
                this.showUpdateDialog(updateInfo);
            } else {
                stdout.printf("当前已是最新版本\n");
            }
        } catch (e) {
            stdout.printf("检查更新失败: %s\n", e.toString());
        }
    }
    
    function isNewerVersion(newVersion, currentVersion) {
        var newParts = newVersion.split(".").map(function(part) {
            return parseInt(part);
        });
        var currentParts = currentVersion.split(".").map(function(part) {
            return parseInt(part);
        });
        
        for (var i = 0; i < Math.max(newParts.length, currentParts.length); i++) {
            var newPart = newParts[i] || 0;
            var currentPart = currentParts[i] || 0;
            
            if (newPart > currentPart) return true;
            if (newPart < currentPart) return false;
        }
        
        return false;
    }
    
    function showUpdateDialog(updateInfo) {
        var dialog = `
            <div class="update-dialog">
                <h3>发现新版本</h3>
                <p>版本: ${updateInfo.version}</p>
                <p>发布日期: ${updateInfo.releaseDate}</p>
                <div class="changelog">
                    <h4>更新内容:</h4>
                    <ul>
                        ${updateInfo.changelog.map(function(item) {
                            return "<li>" + item + "</li>";
                        }).join("")}
                    </ul>
                </div>
                <div class="buttons">
                    <button id="update-now">立即更新</button>
                    <button id="update-later">稍后提醒</button>
                    <button id="skip-version">跳过此版本</button>
                </div>
            </div>
        `;
        
        // 显示更新对话框
        app.showModal("update-modal", "软件更新", dialog);
        
        // 绑定按钮事件
        document.$("#update-now").on("click", function() {
            this.downloadAndInstall(updateInfo);
        });
        
        document.$("#update-later").on("click", function() {
            app.getComponent("update-modal").hide();
        });
        
        document.$("#skip-version").on("click", function() {
            this.skipVersion(updateInfo.version);
            app.getComponent("update-modal").hide();
        });
    }
    
    function downloadAndInstall(updateInfo) {
        stdout.printf("开始下载更新...\n");
        
        // 这里应该实现实际的下载和安装逻辑
        // 可以使用Sciter的HTTP API下载文件
        // 然后启动安装程序
        
        try {
            var tempPath = System.path(System.TEMP, "update.exe");
            this.downloadFile(updateInfo.downloadUrl, tempPath);
            
            // 启动安装程序
            System.exec(tempPath.toString() + " /S");
            
            // 退出当前应用
            view.close();
        } catch (e) {
            stdout.printf("更新失败: %s\n", e.toString());
        }
    }
    
    function skipVersion(version) {
        var config = {
            skippedVersions: [version]
        };
        Storage.userDataPath("update-config.json").save(JSON.stringify(config));
    }
    
    function httpGet(url) {
        // 简化的HTTP GET实现
        // 实际应用中应该使用Sciter的HTTP API
        return "";
    }
    
    function downloadFile(url, localPath) {
        // 简化的文件下载实现
        // 实际应用中应该使用Sciter的HTTP API
    }
}

10.6.4 构建和部署示例

// 构建和部署示例
function buildAndDeploy() {
    // 创建构建工具
    var buildTool = new BuildTool({
        srcDir: "src",
        distDir: "dist",
        minify: true
    });
    
    // 添加构建任务
    buildTool.addTask("复制HTML文件", function(config) {
        buildTool.copyFiles("*.htm", "");
    });
    
    buildTool.addTask("复制CSS文件", function(config) {
        buildTool.copyFiles("*.css", "styles");
    });
    
    buildTool.addTask("处理JavaScript文件", function(config) {
        buildTool.copyFiles("*.js", "scripts");
        
        // 压缩JS文件
        var jsFiles = System.path(config.distDir, "scripts").scan("*.js");
        for (var file in jsFiles) {
            buildTool.minifyJS(file);
        }
    });
    
    buildTool.addTask("复制资源文件", function(config) {
        buildTool.copyFiles("assets/*", "assets");
    });
    
    buildTool.addTask("生成清单文件", function(config) {
        buildTool.generateManifest();
    });
    
    // 执行构建
    if (buildTool.build()) {
        stdout.printf("构建成功,开始部署...\n");
        
        // 创建部署管理器
        var deploymentManager = new DeploymentManager({
            appName: "MySciterApp",
            version: "1.0.0"
        });
        
        // 创建安装程序
        deploymentManager.createInstaller();
        
        // 创建便携版
        deploymentManager.createPortableVersion();
        
        // 生成更新信息
        deploymentManager.generateUpdateInfo();
        
        stdout.printf("部署完成!\n");
    } else {
        stdout.printf("构建失败!\n");
     }
 }

10.7 本章总结

10.7.1 核心要点

  1. 项目规划与架构设计

    • 需求分析和管理
    • 架构设计和组件依赖
    • 项目结构规划
  2. 核心功能实现

    • 用户认证和权限管理
    • 数据管理和持久化
    • 配置管理和监听
  3. 用户界面设计

    • 组件化开发
    • 主题系统
    • 响应式布局
  4. 测试与质量保证

    • 单元测试框架
    • 测试用例编写
    • 自动化测试
  5. 打包与部署

    • 构建配置和任务
    • 安装程序创建
    • 自动更新系统

10.7.2 最佳实践

  1. 项目管理

    • 明确需求和目标
    • 合理的架构设计
    • 模块化开发
  2. 代码质量

    • 编写测试用例
    • 代码审查
    • 持续集成
  3. 用户体验

    • 响应式设计
    • 主题定制
    • 性能优化
  4. 部署策略

    • 自动化构建
    • 多平台支持
    • 版本管理

10.7.3 练习题

基础练习

  1. 项目初始化

    • 使用ProjectGenerator创建一个新的Sciter项目
    • 配置基本的项目结构和文件
    • 实现简单的Hello World应用
  2. 组件开发

    • 创建一个自定义按钮组件
    • 实现组件的初始化和事件处理
    • 添加组件的样式和主题支持
  3. 数据管理

    • 实现一个简单的数据管理器
    • 支持数据的增删改查操作
    • 添加数据验证功能

进阶练习

  1. 完整应用开发

    • 开发一个待办事项管理应用
    • 实现用户认证和数据持久化
    • 添加主题切换和设置功能
  2. 测试框架应用

    • 为你的应用编写完整的测试用例
    • 实现自动化测试流程
    • 生成测试报告
  3. 部署配置

    • 配置完整的构建流程
    • 创建安装程序和便携版
    • 实现自动更新功能

高级练习

  1. 企业级应用

    • 开发一个多用户的项目管理系统
    • 实现角色权限管理
    • 支持数据导入导出
  2. 插件系统

    • 设计和实现插件架构
    • 支持动态加载和卸载插件
    • 提供插件开发API
  3. 跨平台部署

    • 配置多平台构建
    • 实现平台特定的功能
    • 统一的更新和分发机制

通过本章的学习,你已经掌握了Sciter应用开发的完整流程,从项目规划到最终部署。这些知识和技能将帮助你开发出高质量的桌面应用程序。


恭喜你完成了Sciter桌面应用开发教程!

本教程涵盖了从基础概念到高级应用的完整内容,包括: - Sciter基础知识和环境搭建 - TIScript语言详解 - HTML/CSS在Sciter中的应用 - 事件处理和用户交互 - 组件化开发 - 数据绑定和状态管理 - 样式和主题系统 - 原生API集成 - 性能优化与调试 - 项目实战与部署

现在你已经具备了开发专业Sciter应用的能力,可以开始你的桌面应用开发之旅了!