代理模块修改
This commit is contained in:
@@ -320,3 +320,40 @@ appStore.toggleModule(moduleId, enabled)
|
||||
4. **避免循环依赖**:模块的 `index.ts` 只导出配置,不导入其他模块的 store
|
||||
5. **进程配置的 executable**:通常留空,由模块组件在运行时根据用户设置确定实际路径
|
||||
6. **内置模块**:设置 `builtin: true` 的模块不可被用户禁用,开关处于禁用状态
|
||||
|
||||
## 跨模块开发经验(代理模块沉淀)
|
||||
|
||||
以下要点来自代理模块开发,对后续涉及子进程管理、外部 API 交互、shadcn-vue 组件使用的模块同样适用。
|
||||
|
||||
### Tauri 命令与主线程
|
||||
|
||||
- **同步命令(`pub fn`)会阻塞主线程**:Tauri 的同步命令在主线程执行,其内部的 `std::thread::sleep`、磁盘 I/O、网络请求会阻塞所有 async 命令的调度。涉及等待/阻塞操作的命令必须声明为 `pub async fn`,并用 `tauri::async_runtime::spawn_blocking(|| { std::thread::sleep(...) }).await` 将阻塞操作放到线程池。
|
||||
- **Windows 端口释放有延迟**:`child.kill()` + `child.wait()` 后 TCP 端口不会立即可用,需等待约 800ms 再重新绑定。重启类命令应预留此延迟。
|
||||
- **`Mutex` 持锁期间禁止 sleep**:`ProcessManager::check_and_cleanup` 等持锁函数中不要执行长时间 sleep,否则会阻塞所有需要该锁的命令(如状态查询)。应先释放锁再 sleep,或移出临界区。
|
||||
- **进程监控线程**:`start_monitoring_thread` 每 3 秒检查一次进程状态,崩溃时自动重启(可配置 `maxRestarts`)。前端通过监听 `process-status-changed` 事件更新 UI。
|
||||
|
||||
### 外部 API 交互
|
||||
|
||||
- **API 就绪轮询**:子进程 spawn 后 API 不会立即可用(需初始化配置、加载 geo 文件等)。前端应在请求前轮询健康检查接口(如 `/version`),500ms 间隔、10s 超时。
|
||||
- **缓存配置避免频繁读盘**:后端 Manager 每次方法调用都从磁盘读 settings 会拖慢批量操作。建议在 Manager 内维护内存缓存,`save_settings` 时同步更新。
|
||||
- **并发请求限流**:批量测速等场景不要一次性 `Promise.all` 全部请求,应分批(如每批 20 个),避免压垮子进程。
|
||||
|
||||
### shadcn-vue / reka-ui 注意事项
|
||||
|
||||
- **Select 禁止空字符串 value**:`<SelectItem value="">` 会触发警告并失效。使用哨兵值(如 `__default__`、`__all__`)替代空字符串,在 `@update:model-value` 回调中转回空值。
|
||||
- **Select 双击问题**:reka-ui Select 的 DismissableLayer + closeAutoFocus 会导致连续点击两个 Select 时第一次点击仅关闭上一个、需第二次点击才打开下一个。当前未完美解决,建议同一界面避免放置过多相邻 Select。
|
||||
- **Switch 使用 `model-value` / `update:model-value`**:reka-ui v2+ 的 Switch 不再使用 `checked` / `update:checked`。
|
||||
- **Sonner toast 不可见**:通常是缺少 `vue-sonner/lib/index.css` 导入,而非 z-index 问题。确保在入口处导入该 CSS。
|
||||
- **AlertDialog 替代 confirm()**:原生 `confirm()` 在 Tauri WebView 中样式不一致,使用 shadcn-vue AlertDialog 封装 Promise 化的 `showConfirm()` 函数,支持 destructive 样式。
|
||||
|
||||
### 数据一致性与自愈
|
||||
|
||||
- **配置文件与磁盘 reconcile**:settings.json 中的列表(如订阅 profiles)可能与磁盘文件不同步(用户手动删除、反序列化失败被 default 覆盖)。每次 `load_settings` 时应扫描磁盘补全缺失条目,并在 `currentProfile` 为 null 时自动指向第一个。
|
||||
- **操作顺序防重复**:导入文件后写入 settings 时,若先写文件再 load_settings(含 reconcile 扫盘),reconcile 会扫到新文件添加一次,随后 push 又添加一次。应先 load_settings → 写文件 → push(加去重保护)。
|
||||
- **子进程崩溃循环防护**:子进程因依赖文件损坏(如 geo 数据库)崩溃时,`restart_on_crash` 会反复重启。需配置备用下载源(如 jsdelivr 镜像)避免无代理时 GitHub 超时。
|
||||
|
||||
### UI 细节
|
||||
|
||||
- **瀑布流布局避免卡片等高撑开**:使用 `columns-1 md:columns-2 gap-4 [&>*]:mb-4 [&>*]:break-inside-avoid` 替代 `grid`,让卡片按内容高度自然排列。
|
||||
- **模块禁用清理系统状态**:模块 `onDisable` 钩子应清理系统级副作用(如系统代理注册表项),避免模块停用后遗留导致系统异常。
|
||||
- **应用退出清理**:在 `lib.rs` 的 `quit_app` 命令和托盘退出事件中都要调用 `cleanup_on_exit` + `stop_all`,确保任何退出路径都清理干净。
|
||||
|
||||
Reference in New Issue
Block a user