# 系统设置保存按钮工作流程分析 # System Settings Save Button Workflow Analysis ## 文档概述 / Document Overview 本文档详细分析了 ERPAuto 系统设置界面中保存按钮的完整工作流程,包括架构设计、数据流转、技术实现细节以及错误处理机制。 This document provides a comprehensive analysis of the save button workflow in the ERPAuto system settings interface, including architecture design, data flow, technical implementation details, and error handling mechanisms. --- ## 目录 / Table of Contents 1. [架构概览](#架构概览) 2. [数据流程图](#数据流程图) 3. [组件详解](#组件详解) 4. [数据结构](#数据结构) 5. [错误处理机制](#错误处理机制) 6. [安全考虑](#安全考虑) 7. [技术实现细节](#技术实现细节) --- ## 架构概览 / Architecture Overview ### 系统架构 / System Architecture 系统设置保存功能采用典型的 Electron 三层架构模式: The system settings save functionality follows the classic Electron three-tier architecture pattern: ```mermaid graph TB subgraph "Renderer Process 渲染进程" UI[SettingsPage.tsx
UI Component] end subgraph "Preload Script 预加载脚本" BRIDGE[contextBridge API
Security Boundary] end subgraph "Main Process 主进程" IPC[settings-handler.ts
IPC Handler] SERVICE[ConfigManager.ts
Configuration Service] FILE[.env File
Persistent Storage] end UI -->|IPC Invoke| BRIDGE BRIDGE -->|Secure Channel| IPC IPC -->|Business Logic| SERVICE SERVICE -->|Write| FILE FILE -->|Confirm| SERVICE SERVICE -->|Result| IPC IPC -->|Response| BRIDGE BRIDGE -->|Promise Resolve| UI style UI fill:#e1f5ff style BRIDGE fill:#fff4e1 style IPC fill:#ffe1f5 style SERVICE fill:#e1ffe1 style FILE fill:#f5f5f5 ``` ### 核心设计模式 / Core Design Patterns 1. **单向数据流**:数据从 UI → Main Process → File,响应沿相反路径返回 2. **安全隔离**:Preload 脚本作为安全桥梁,通过 `contextBridge` 暴露受限 API 3. **单例模式**:ConfigManager 使用单例确保配置一致性 4. **缓存优先**:配置读取优先从内存缓存获取,写入时同步到磁盘 --- ## 数据流程图 / Data Flow Diagrams ### 完整保存流程 / Complete Save Flow ```mermaid sequenceDiagram actor User as 用户 User participant UI as SettingsPage.tsx participant Preload as preload/index.ts participant IPC as settings-handler.ts participant Config as ConfigManager.ts participant File as .env File User->>UI: 点击保存按钮
Click Save Button activate UI UI->>UI: handleSaveSettings() Note over UI: 检查是否修改
Check isModified UI->>Preload: window.electron.settings
.saveSettings(settings) activate Preload Preload->>IPC: ipcRenderer.invoke
('settings:saveSettings', settings) activate IPC IPC->>IPC: 验证用户类型
Validate User Type IPC->>Config: configManager
.saveAllSettings(settings) activate Config Config->>Config: 更新内存缓存
Update Cache Note over Config: set('erp.url', value)
set('erp.username', value)
... (40+ fields) Config->>File: fs.writeFileSync
(.env, content) activate File File-->>Config: true/false deactivate File Config-->>IPC: Promise deactivate Config IPC-->>Preload: {success, error?} deactivate IPC Preload-->>UI: Promise resolve deactivate Preload alt 保存成功 / Save Success UI->>UI: setIsModified(false) UI->>User: 显示成功消息
Show Success Message else 保存失败 / Save Failed UI->>User: 显示错误消息
Show Error Message end deactivate UI ``` ### 数据转换流程 / Data Transformation Flow ```mermaid graph LR subgraph "UI State" STATE[Settings Interface
settings.erp.url = 'https://...'] end subgraph "Type Conversion" T1[SettingsData Object
TypeScript Interface] end subgraph "IPC Transport" JSON[JSON Serialization
String Transfer] end subgraph "Service Layer" CACHE[Config Cache
Map] end subgraph "File System" ENV[.env File Format
KEY=VALUE] end STATE -->|Object| T1 T1 -->|JSON.stringify| JSON JSON -->|Deserialize| T1 T1 -->|set key-value| CACHE CACHE -->|Format| ENV style STATE fill:#e1f5ff style JSON fill:#fff4e1 style CACHE fill:#e1ffe1 style ENV fill:#f5f5f5 ``` --- ## 组件详解 / Component Details ### 1. 渲染进程 / Renderer Process #### SettingsPage.tsx (`src/renderer/src/pages/SettingsPage.tsx`) **主要职责 / Main Responsibilities:** - 用户界面渲染和交互 - 本地状态管理(settings, isModified, message) - 调用 IPC 通信 **关键函数 / Key Functions:** ```typescript // 第 61-73 行 / Lines 61-73 const handleSaveSettings = async () => { try { const result = await window.electron.settings.saveSettings(settings as any) if (result.success) { setIsModified(false) // 清除修改标记 showMessage('success', '设置保存成功') } else { showMessage('error', result.error || '保存失败') } } catch (error) { showMessage('error', '保存设置时发生错误') } } ``` **状态管理 / State Management:** | 状态变量 | 类型 | 用途 | | ------------ | ---------------- | ----------------------------------------------------------- | | `settings` | `Settings` | 当前配置数据,结构为 `{ erp: { url, username, password } }` | | `isModified` | `boolean` | 标记配置是否已修改,控制保存按钮启用状态 | | `isLoading` | `boolean` | 加载状态,显示加载动画 | | `message` | `object \| null` | 临时消息,3秒后自动消失 | **UI 交互逻辑 / UI Interaction Logic:** ```mermaid stateDiagram-v2 [*] --> Loading: 组件挂载 Loading --> Ready: loadSettings() Ready --> Modified: updateSettings() Modified --> Modified: 继续修改 Modified --> Ready: 保存成功 Modified --> Error: 保存失败 Error --> Modified: 用户继续操作 Ready --> [*]: 组件卸载 note right of Modified 保存按钮启用 Save Button Enabled end note note right of Ready 保存按钮禁用 Save Button Disabled end note ``` ### 2. 预加载脚本 / Preload Script #### preload/index.ts (`src/preload/index.ts`) **主要职责 / Main Responsibilities:** - 安全桥梁,暴露受限 API 到渲染进程 - 类型安全的 IPC 通道定义 **关键代码 / Key Code:** ```typescript // 第 89-97 行 / Lines 89-97 settings: { getUserType: () => ipcRenderer.invoke('settings:getUserType'), getSettings: () => ipcRenderer.invoke('settings:getSettings'), saveSettings: (settings: SettingsData) => ipcRenderer.invoke('settings:saveSettings', settings), resetDefaults: () => ipcRenderer.invoke('settings:resetDefaults'), testErpConnection: () => ipcRenderer.invoke('settings:testErpConnection'), testDbConnection: () => ipcRenderer.invoke('settings:testDbConnection') } ``` **安全隔离机制 / Security Isolation:** ```mermaid graph TB Renderer[Renderer Process
Untrusted Context] Preload[Preload Script
Trusted Context] Main[Main Process
Trusted Context] Renderer -->|window.electron| Preload Preload -->|ipcRenderer.invoke| Main Main -->|Validation| Preload Preload -->|Return Promise| Renderer style Renderer fill:#ffe1e1 style Preload fill:#e1ffe1 style Main fill:#e1e1ff ``` ### 3. 主进程 / Main Process #### settings-handler.ts (`src/main/ipc/settings-handler.ts`) **主要职责 / Main Responsibilities:** - IPC 通道注册和处理 - 权限验证(基于用户类型) - 业务逻辑协调 **保存设置处理函数 / Save Settings Handler:** ```typescript // 第 83-102 行 / Lines 83-102 ipcMain.handle( 'settings:saveSettings', async (_event, settings: SettingsData): Promise => { try { log.info('Saving settings') const success = await configManager.saveAllSettings(settings) if (success) { log.info('Settings saved successfully') return { success: true } } else { log.warn('Failed to save settings') return { success: false, error: '保存设置失败' } } } catch (error) { const message = error instanceof Error ? error.message : 'Unknown error' log.error('Error saving settings', { error: message }) return { success: false, error: `保存设置失败:${message}` } } } ) ``` **用户类型过滤 / User Type Filtering:** ```typescript // 第 31-54 行 / Lines 31-54 function filterSettingsByUserType(settings: SettingsData, userType: UserType): SettingsData { if (userType === 'Admin') { return settings // Admin 获取完整配置 } // User 用户获取受限配置 return { erp: { username: settings.erp.username, password: settings.erp.password, headless: settings.erp.headless, url: settings.erp.url, ignoreHttpsErrors: settings.erp.ignoreHttpsErrors, autoCloseBrowser: settings.erp.autoCloseBrowser }, paths: settings.paths, execution: settings.execution, database: settings.database, extraction: settings.extraction, validation: settings.validation, ui: settings.ui } } ``` **权限控制矩阵 / Permission Control Matrix:** | 功能 / Feature | Admin | User | Guest | | -------------- | ----- | ------- | ----- | | 查看所有设置 | ✅ | ⚠️ 部分 | ❌ | | 保存设置 | ✅ | ✅ | ❌ | | 恢复默认值 | ✅ | ❌ | ❌ | | 测试 ERP 连接 | ✅ | ✅ | ❌ | | 测试数据库连接 | ✅ | ✅ | ❌ | ### 4. 配置管理服务 / Configuration Manager Service #### config-manager.ts (`src/main/services/config/config-manager.ts`) **主要职责 / Main Responsibilities:** - .env 文件读写 - 配置缓存管理 - 默认值管理 - 类型转换和验证 **类结构 / Class Structure:** ```typescript export class ConfigManager { private static instance: ConfigManager | null = null // 单例模式 private envPath: string // .env 文件路径 private configCache: Map // 内存缓存 private initialized: boolean = false // 初始化标记 // 单例获取方法 public static getInstance(): ConfigManager // 配置读取 public get(key: string, defaultValue?: string): string | undefined public getBoolean(key: string, defaultValue?: boolean): boolean public getNumber(key: string, defaultValue?: number): number // 配置写入 public set(key: string, value: string | number | boolean): void // 持久化 public async save(): Promise // 高级操作 public getAllSettings(): SettingsData public async saveAllSettings(settings: SettingsData): Promise public resetToDefaults(): SettingsData } ``` **保存详细流程 / Save Detailed Flow:** ```mermaid graph TD START[saveAllSettings] --> STEP1[更新 ERP 配置 6 字段] STEP1 --> STEP2[更新数据库配置 7 字段] STEP2 --> STEP3[更新路径配置 3 字段] STEP3 --> STEP4[更新提取配置 5 字段] STEP4 --> STEP5[更新校验配置 5 字段] STEP5 --> STEP6[更新 UI 配置 3 字段] STEP6 --> STEP7[更新执行配置 1 字段] STEP7 --> SAVE[调用 save 方法] SAVE --> BUILD[构建 .env 内容] BUILD --> WRITE[写入文件系统] WRITE --> CHECK{检查结果} CHECK -->|成功| SUCCESS[返回 true] CHECK -->|失败| FAILURE[返回 false] ``` **.env 文件格式 / .env File Format:** ```bash # =========================== # ERP 系统配置 # =========================== ERP_URL=https://68.11.34.30:8082/ ERP_USERNAME= ERP_PASSWORD= ERP_HEADLESS=true ERP_IGNORE_HTTPS_ERRORS=true ERP_AUTO_CLOSE_BROWSER=true # =========================== # 数据库配置 - MySQL # =========================== DB_TYPE=mysql DB_NAME=BLD_DB DB_USERNAME=remote_user DB_PASSWORD= DB_MYSQL_HOST=192.168.31.83 DB_MYSQL_PORT=3306 DB_MYSQL_CHARSET=utf8mb4 # =========================== # 路径配置 # =========================== PATH_DATA_DIR=D:/python/playwrite/data/ PATH_DEFAULT_OUTPUT=离散备料计划维护_合并.xlsx PATH_VALIDATION_OUTPUT=物料状态校验结果.xlsx # ... 更多配置节 ``` --- ## 数据结构 / Data Structures ### SettingsData 接口 / Interface Definition **类型定义位置 / Type Definition Location:** `src/main/types/settings.types.ts` (第 136-151 行) ```typescript export interface SettingsData { erp: ErpConfig database: DatabaseConfig paths: PathsConfig extraction: ExtractionConfig validation: ValidationConfig ui: UiConfig execution: ExecutionConfig } ``` ### 完整数据结构树 / Complete Data Structure Tree ```mermaid graph TB Settings[SettingsData] Settings --> Erp[ErpConfig] Erp --> Erp1[url: string] Erp --> Erp2[username: string] Erp --> Erp3[password: string] Erp --> Erp4[headless: boolean] Erp --> Erp5[ignoreHttpsErrors: boolean] Erp --> Erp6[autoCloseBrowser: boolean] Settings --> DB[DatabaseConfig] DB --> DB1[dbType: mysql or sqlserver] DB --> DB2[server: string] DB --> DB3[mysqlHost: string] DB --> DB4[mysqlPort: number] DB --> DB5[database: string] DB --> DB6[username: string] DB --> DB7[password: string] Settings --> Paths[PathsConfig] Paths --> Paths1[dataDir: string] Paths --> Paths2[defaultOutput: string] Paths --> Paths3[validationOutput: string] Settings --> Extract[ExtractionConfig] Extract --> Extract1[batchSize: number] Extract --> Extract2[verbose: boolean] Extract --> Extract3[autoConvert: boolean] Extract --> Extract4[mergeBatches: boolean] Extract --> Extract5[enableDbPersistence: boolean] Settings --> Valid[ValidationConfig] Valid --> Valid1[dataSource: ValidationDataSource] Valid --> Valid2[batchSize: number] Valid --> Valid3[matchMode: MatchMode] Valid --> Valid4[enableCrud: boolean] Valid --> Valid5[defaultManager: string] Settings --> UI[UiConfig] UI --> UI1[fontFamily: string] UI --> UI2[fontSize: number] UI --> UI3[productionIdInputWidth: number] Settings --> Exec[ExecutionConfig] Exec --> Exec1[dryRun: boolean] style Settings fill:#e1f5ff style Erp fill:#ffe1f5 style DB fill:#e1ffe1 style Paths fill:#fff4e1 style Extract fill:#f5e1ff style Valid fill:#ffe1e1 style UI fill:#e1f5ff style Exec fill:#f5f5f5 ``` ### IPC 通信数据格式 / IPC Communication Data Format **请求格式 / Request Format:** ```json { "erp": { "url": "https://68.11.34.30:8082/", "username": "admin", "password": "password123", "headless": true, "ignoreHttpsErrors": true, "autoCloseBrowser": true }, "database": { ... }, "paths": { ... }, "extraction": { ... }, "validation": { ... }, "ui": { ... }, "execution": { ... } } ``` **响应格式 / Response Format:** ```json // 成功 / Success { "success": true } // 失败 / Failure { "success": false, "error": "保存设置失败:Access denied" } ``` --- ## 错误处理机制 / Error Handling Mechanism ### 错误处理层次 / Error Handling Layers ```mermaid graph TB subgraph "UI Layer" UI_TRY[try-catch in handleSaveSettings] UI_MSG[showMessage display] end subgraph "IPC Layer" IPC_TRY[try-catch in handler] IPC_LOG[Structured logging] IPC_RETURN[Return error object] end subgraph "Service Layer" SVC_TRY[try-catch in save] SVC_LOG[Console error log] SVC_RETURN[Return false] end subgraph "File System" FS_CHECK[File exists check] FS_WRITE[Write with error handling] end UI_TRY -->|Catch| UI_MSG IPC_TRY -->|Catch| IPC_LOG --> IPC_RETURN SVC_TRY -->|Catch| SVC_LOG --> SVC_RETURN FS_WRITE -->|Error| SVC_TRY style UI_TRY fill:#ffe1e1 style IPC_TRY fill:#ffe1e1 style SVC_TRY fill:#ffe1e1 ``` ### 错误场景分析 / Error Scenario Analysis | 错误场景 / Error Scenario | 触发位置 / Location | 处理方式 / Handling | 用户反馈 / User Feedback | | ------------------------- | ------------------- | --------------------- | ------------------------ | | IPC 通信失败 | Renderer | try-catch | 显示"保存设置时发生错误" | | 权限不足 | Main Process | 检查 UserType | 返回权限错误信息 | | 文件写入失败 | ConfigManager | fs.writeFileSync 捕获 | 返回"保存设置失败" | | 无效数据类型 | IPC Handler | TypeScript 类型检查 | 返回验证错误 | | 磁盘空间不足 | File System | OS 异常捕获 | 返回系统错误信息 | ### 日志记录策略 / Logging Strategy ```typescript // Main Process 结构化日志 / Structured Logging log.info('Saving settings') log.info('Settings saved successfully') log.warn('Failed to save settings') log.error('Error saving settings', { error: message }) ``` **日志级别使用 / Log Level Usage:** - `info`: 正常操作流程 - `warn`: 潜在问题(如保存失败但未崩溃) - `error`: 严重错误(如异常抛出) --- ## 安全考虑 / Security Considerations ### 安全机制层级 / Security Layers ```mermaid graph TB L1[Layer 1: Context Isolation
渲染进程隔离] L2[Layer 2: contextBridge
受限 API 暴露] L3[Layer 3: User Type Filtering
基于角色的访问控制] L4[Layer 4: File System Permissions
.env 文件保护] L1 --> L2 --> L3 --> L4 style L1 fill:#e1f5ff style L2 fill:#fff4e1 style L3 fill:#e1ffe1 style L4 fill:#ffe1f5 ``` ### 关键安全措施 / Key Security Measures 1. **密码明文存储风险 / Password Storage Risk** - ⚠️ 当前:密码以明文形式存储在 .env 文件中 - 🔒 建议:实现加密存储机制 2. **用户权限隔离 / User Permission Isolation** - ✅ 实现:基于用户类型过滤可见配置 - ✅ 实现:Guest 用户无法访问设置页面 3. **IPC 通信安全 / IPC Communication Security** - ✅ 实现:使用 `contextBridge` 而非直接暴露 - ✅ 实现:类型安全的 TypeScript 接口 4. **文件系统访问 / File System Access** - ✅ 实现:.env 文件仅主进程可访问 - ⚠️ 风险:文件权限取决于操作系统 ### 敏感数据流向 / Sensitive Data Flow ```mermaid sequenceDiagram participant User as 用户输入 participant UI as UI State (内存) participant IPC as IPC Channel participant Cache as Config Cache participant File as .env File User->>UI: password = "secret123" UI->>IPC: JSON 传输 (未加密) IPC->>Cache: Map.set('erp.password', 'secret123') Cache->>File: 写入明文到磁盘 Note over File: ⚠️ 安全风险:
密码以明文形式持久化 ``` --- ## 技术实现细节 / Technical Implementation Details ### 文件位置索引 / File Location Index | 组件 / Component | 文件路径 / File Path | 关键行数 / Key Lines | | ---------------- | -------------------------------------------- | --------------------- | | UI 组件 | `src/renderer/src/pages/SettingsPage.tsx` | 61-73 (保存处理) | | 预加载脚本 | `src/preload/index.ts` | 89-97 (API 定义) | | IPC 处理器 | `src/main/ipc/settings-handler.ts` | 83-102 (保存处理) | | 配置管理器 | `src/main/services/config/config-manager.ts` | 437-483 (保存方法) | | 类型定义 | `src/main/types/settings.types.ts` | 136-171 (接口定义) | | IPC 注册 | `src/main/ipc/index.ts` | 导入 settings-handler | ### 性能特性 / Performance Characteristics 1. **异步操作 / Async Operations** - 所有 IPC 调用使用 `async/await` 模式 - 避免阻塞主进程事件循环 2. **内存优化 / Memory Optimization** - 使用 Map 缓存配置,减少文件读取 - 按需加载配置项 3. **写入策略 / Write Strategy** - 每次保存完整重写 .env 文件 - 原子写入(writeFileSync) ### 依赖关系图 / Dependency Graph ```mermaid graph TD A[SettingsPage.tsx] -->|imports| B[lucide-react] A -->|uses| C[window.electron.settings] C -->|exposed by| D[preload/index.ts] D -->|imports| E[electron API] D -->|imports| F[SettingsData Type] G[settings-handler.ts] -->|imports| H[ipcMain] G -->|imports| I[ConfigManager] G -->|imports| J[SessionManager] G -->|imports| K[Logger] I -->|imports| L[fs/path] I -->|imports| M[SettingsData Type] I -->|imports| N[DEFAULT_SETTINGS] style A fill:#e1f5ff style D fill:#fff4e1 style G fill:#ffe1f5 style I fill:#e1ffe1 ``` ### 关键代码片段分析 / Key Code Snippet Analysis **1. 状态更新逻辑 / State Update Logic** ```typescript // SettingsPage.tsx 第 50-59 行 const updateSettings = (category: string, key: string, value: any) => { setSettings((prev) => ({ ...prev, [category]: { ...(prev as any)[category], [key]: value } })) setIsModified(true) // 标记为已修改 } ``` **设计要点 / Design Points:** - 不可变更新模式(Immutable Update Pattern) - 使用展开运算符保持对象引用 - 自动启用保存按钮 **2. 配置保存逻辑 / Configuration Save Logic** ```typescript // config-manager.ts 第 437-483 行 public async saveAllSettings(settings: SettingsData): Promise { // 批量更新缓存 (40+ 字段) this.set('erp.url', settings.erp.url) this.set('erp.username', settings.erp.username) // ... 更多字段 // 同步写入文件 return this.save() } ``` **设计要点 / Design Points:** - 先更新内存,后写入磁盘 - 失败时缓存保持不变 - 返回布尔值表示成功/失败 **3. .env 文件生成逻辑 / .env File Generation** ```typescript // config-manager.ts 第 179-345 行 public async save(): Promise { const lines: string[] = [] // 构建格式化的 .env 内容 lines.push('# ===========================') lines.push('# ERP 系统配置') lines.push('# ===========================') lines.push(`ERP_URL=${this.configCache.get('erp.url') || DEFAULT_SETTINGS.erp.url}`) const content = lines.join('\n') fs.writeFileSync(this.envPath, content, 'utf-8') return true } ``` **设计要点 / Design Points:** - 添加注释分隔符提高可读性 - 使用默认值作为后备 - 同步写入确保一致性 --- ## 扩展与改进建议 / Extension and Improvement Suggestions ### 短期改进 / Short-term Improvements 1. **输入验证 / Input Validation** - 添加 URL 格式验证 - 密码强度检查 - 端口号范围验证 2. **用户体验 / User Experience** - 添加保存进度指示器 - 实现自动保存功能 - 添加配置导入/导出 3. **错误处理 / Error Handling** - 更详细的错误消息 - 错误恢复建议 - 错误日志导出 ### 长期改进 / Long-term Improvements 1. **安全性增强 / Security Enhancement** ```typescript // 建议实现密码加密 interface SecureSettingsData extends SettingsData { erp: { ...ErpConfig encryptedPassword: string // 替代明文密码 } } ``` 2. **配置版本控制 / Configuration Versioning** - 实现配置历史记录 - 支持回滚到之前版本 - 配置变更审计日志 3. **实时配置重载 / Live Config Reload** - 监听 .env 文件变化 - 自动重载配置 - 通知相关服务更新 --- ## 测试建议 / Testing Recommendations ### 单元测试 / Unit Tests ```typescript // 测试用例示例 describe('ConfigManager', () => { it('should save settings successfully', async () => { const manager = ConfigManager.getInstance() const settings: SettingsData = { /* mock data */ } const result = await manager.saveAllSettings(settings) expect(result).toBe(true) }) it('should handle file write errors', async () => { // Mock fs.writeFileSync to throw error const result = await manager.saveAllSettings(settings) expect(result).toBe(false) }) }) ``` ### 集成测试 / Integration Tests ```typescript describe('Settings Save Flow', () => { it('should complete full save cycle', async () => { // 1. User modifies settings // 2. Clicks save button // 3. Verifies .env file updated // 4. Confirms UI feedback }) }) ``` --- ## 附录 / Appendix ### 完整配置字段列表 / Complete Configuration Field List | 类别 / Category | 字段数 / Field Count | 字段列表 / Field List | | ---------------- | -------------------- | ---------------------------------------------------------------------- | | ERP | 6 | url, username, password, headless, ignoreHttpsErrors, autoCloseBrowser | | Database | 7 | dbType, server, mysqlHost, mysqlPort, database, username, password | | Paths | 3 | dataDir, defaultOutput, validationOutput | | Extraction | 5 | batchSize, verbose, autoConvert, mergeBatches, enableDbPersistence | | Validation | 5 | dataSource, batchSize, matchMode, enableCrud, defaultManager | | UI | 3 | fontFamily, fontSize, productionIdInputWidth | | Execution | 1 | dryRun | | **总计 / Total** | **30** | | ### 相关文档 / Related Documentation - [Electron Security Guidelines](https://www.electronjs.org/docs/latest/tutorial/security) - [IPC 通信最佳实践](https://www.electronjs.org/docs/latest/tutorial/ipc) - [环境变量管理规范](.env.example) ### 版本历史 / Version History | 版本 / Version | 日期 / Date | 变更 / Changes | | -------------- | ----------- | -------------------------- | | 1.0 | 2025-03-03 | 初始版本 / Initial version | --- **文档生成时间 / Document Generated:** 2025-03-03 **最后更新 / Last Updated:** 2025-03-03 **维护者 / Maintainer:** ERPAuto Development Team