diff --git a/.agents/workflows/1.md b/.agents/workflows/1.md
deleted file mode 100644
index 4db78530..00000000
--- a/.agents/workflows/1.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-description: 审查
----
-
-审查是否符合代码规范
-是否有代码缺陷
\ No newline at end of file
diff --git a/.agents/workflows/bug-fix.md b/.agents/workflows/bug-fix.md
new file mode 100644
index 00000000..59bf93b1
--- /dev/null
+++ b/.agents/workflows/bug-fix.md
@@ -0,0 +1,139 @@
+---
+description: Bug 修复流程
+---
+
+## 工作流说明
+
+此工作流指导如何修复 Bug。
+
+## 步骤
+
+### 1. 复现 Bug
+
+- 根据 Issue 描述复现问题
+- 记录详细的复现步骤
+- 收集相关日志和错误信息
+- 确认环境信息
+
+### 2. 分析问题
+
+- 查看相关代码
+- 使用调试器定位问题
+- 检查日志输出
+- 识别根本原因
+
+### 3. 创建修复分支
+
+```bash
+git checkout -b fix/your-bug-fix
+```
+
+### 4. 编写回归测试
+
+先编写测试来复现 Bug:
+
+```typescript
+// src/__tests__/unit/bugFix.test.ts
+import { describe, it, expect } from "vitest";
+import { buggyFunction } from "@/modules/example";
+
+describe("buggyFunction", () => {
+ it("should not crash with null input", () => {
+ expect(() => buggyFunction(null)).not.toThrow();
+ });
+});
+```
+
+### 5. 修复代码
+
+- 最小化修改
+- 保持代码可读性
+- 添加必要的注释
+- 更新相关类型定义
+
+### 6. 运行测试
+
+```bash
+# 确保新测试通过
+npm run test
+
+# 运行所有测试
+npm run test:all
+
+# 代码检查
+npm run lint
+npm run format
+```
+
+### 7. 本地验证
+
+- 验证 Bug 已修复
+- 测试相关功能
+- 检查是否引入新问题
+- 测试边界情况
+
+### 8. 更新文档
+
+- 更新 CHANGELOG.md(如果需要)
+- 更新相关文档(如需要)
+
+### 9. 提交代码
+
+```bash
+git add .
+git commit -m "fix(scope): describe the bug fix" -s
+git push origin fix/your-bug-fix
+```
+
+### 10. 创建 Pull Request
+
+- 引用相关 Issue(`Fixes #123`)
+- 描述修复方法
+- 说明复现步骤
+- 添加测试说明
+
+### 11. 代码审查
+
+- 响应审查意见
+- 进行必要的修改
+- 确保所有 CI 检查通过
+
+### 12. 合并
+
+- 等待审查批准
+- Squash 合并到 main 分支
+- 删除修复分支
+
+## 注意事项
+
+- ⚠️ 修复前先理解问题根源
+- ⚠️ 最小化修改范围
+- ⚠️ 添加回归测试防止复发
+- ⚠️ 考虑向后兼容性
+- ⚠️ 测试所有受影响的功能
+
+## 常见 Bug 类型
+
+### IPC 通信问题
+
+- 检查事件名称是否匹配
+- 检查数据格式是否正确
+- 检查异步处理
+
+### 状态管理问题
+
+- 检查响应式依赖
+- 检查状态更新时机
+- 检查内存泄漏
+
+### 类型错误
+
+- 检查类型定义
+- 检查类型断言
+- 检查可选值处理
+
+## 相关文档
+
+- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
+- [TESTING.md](../../TESTING.md) - 测试文档
+- [TROUBLESHOOTING.md](../../TROUBLESHOOTING.md) - 问题排查
diff --git a/.agents/workflows/code-review.md b/.agents/workflows/code-review.md
new file mode 100644
index 00000000..5dc92cfb
--- /dev/null
+++ b/.agents/workflows/code-review.md
@@ -0,0 +1,245 @@
+---
+description: 代码审查流程
+---
+
+## 工作流说明
+
+此工作流指导如何进行代码审查。
+
+## 审查清单
+
+### 代码质量
+
+- [ ] 代码遵循项目规范
+- [ ] TypeScript 类型正确
+- [ ] 没有 `any` 类型(除非必要)
+- [ ] ESLint 和 Prettier 通过
+- [ ] 代码可读性良好
+
+### 功能实现
+
+- [ ] 实现符合需求
+- [ ] 边界情况处理
+- [ ] 错误处理完善
+- [ ] 没有引入新 Bug
+
+### 测试
+
+- [ ] 包含足够的测试
+- [ ] 测试覆盖率合理
+- [ ] 所有测试通过
+- [ ] E2E 测试(如需要)
+
+### 文档
+
+- [ ] 更新了相关文档
+- [ ] 代码注释充分
+- [ ] API 文档(如需要)
+- [ ] CHANGELOG.md(如需要)
+
+### 安全性
+
+- [ ] 没有安全漏洞
+- [ ] 输入验证完善
+- [ ] 权限检查正确
+- [ ] 敏感信息保护
+
+### 性能
+
+- [ ] 没有明显的性能问题
+- [ ] 内存使用合理
+- [ ] 没有不必要的渲染
+- [ ] 资源加载优化
+
+## 审查流程
+
+### 1. 理解变更
+
+- 阅读 PR 描述
+- 查看 Issue 链接
+- 理解变更目的
+- 检查变更范围
+
+### 2. 代码审查
+
+**主进程代码:**
+
+```bash
+# 检查类型安全
+npx tsc --noEmit
+
+# 检查代码质量
+npm run lint
+```
+
+**渲染进程代码:**
+
+- 组件结构
+- 状态管理
+- 事件处理
+- 样式实现
+
+### 3. 测试验证
+
+```bash
+# 运行单元测试
+npm run test
+
+# 运行 E2E 测试
+npm run test:e2e
+
+# 检查覆盖率
+npm run test:coverage
+```
+
+### 4. 提供反馈
+
+**正面反馈:**
+
+- 好的实现
+- 优秀的代码
+- 有价值的贡献
+
+**建设性反馈:**
+
+- 指出问题
+- 提出建议
+- 解释原因
+
+**反馈格式:**
+
+````markdown
+### 问题
+
+**位置:** `src/components/AppCard.vue:45`
+
+**描述:** 这里缺少错误处理,可能导致应用崩溃。
+
+**建议:**
+
+```typescript
+try {
+ await installPackage();
+} catch (error) {
+ console.error("Install failed:", error);
+ showError(error.message);
+}
+```
+````
+
+````
+
+### 5. 批准或要求修改
+
+**批准条件:**
+- 所有审查项目通过
+- 所有测试通过
+- CI 检查通过
+- 没有阻塞问题
+
+**要求修改:**
+- 指出必须修复的问题
+- 给出明确的修改建议
+- 等待作者响应
+
+## 审查原则
+
+### 及时性
+
+- 尽快响应 PR
+- 设定响应时间预期
+- 优先处理紧急 PR
+
+### 建设性
+
+- 提供具体的反馈
+- 给出改进建议
+- 解释审查理由
+
+### 尊重
+
+- 尊重作者的贡献
+- 使用礼貌的语言
+- 认可好的实现
+
+### 一致性
+
+- 遵循项目规范
+- 保持审查标准一致
+- 参考之前类似 PR
+
+## 常见问题
+
+### 类型安全问题
+
+**问题:** 使用了 `any` 类型
+
+**建议:**
+```typescript
+// ❌ 避免
+const data: any = response;
+
+// ✅ 推荐
+interface ResponseData {
+ id: string;
+ name: string;
+}
+const data: ResponseData = response;
+````
+
+### 代码重复
+
+**问题:** 代码重复
+
+**建议:**
+
+```typescript
+// 提取公共函数
+function formatSize(size: number): string {
+ return size > 1024 ? `${size / 1024} MB` : `${size} KB`;
+}
+```
+
+### 错误处理
+
+**问题:** 缺少错误处理
+
+**建议:**
+
+```typescript
+async function loadApps() {
+ try {
+ const response = await axios.get("/api/apps");
+ return response.data;
+ } catch (error) {
+ logger.error({ err: error }, "Failed to load apps");
+ throw error;
+ }
+}
+```
+
+## 审查后操作
+
+### 批准
+
+- 点击 "Approve review"
+- 添加评论(可选)
+- 等待合并
+
+### 要求修改
+
+- 选择 "Request changes"
+- 提供详细反馈
+- 等待作者更新
+
+### 评论
+
+- 选择 "Comment"
+- 提供建议或问题
+- 不阻止合并
+
+## 相关文档
+
+- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
+- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
+- [AGENTS.md](../../AGENTS.md) - AI 编码指南
diff --git a/.agents/workflows/documentation.md b/.agents/workflows/documentation.md
new file mode 100644
index 00000000..472faade
--- /dev/null
+++ b/.agents/workflows/documentation.md
@@ -0,0 +1,264 @@
+---
+description: 文档更新流程
+---
+
+## 工作流说明
+
+此工作流指导如何更新项目文档。
+
+## 步骤
+
+### 1. 确定需要更新的文档
+
+根据变更内容确定需要更新的文档:
+
+- README.md - 主要说明
+- DEVELOPMENT.md - 开发指南
+- CONTRIBUTING.md - 贡献指南
+- TESTING.md - 测试文档
+- DEPLOYMENT.md - 部署文档
+- TROUBLESHOOTING.md - 问题排查
+- FAQ.md - 常见问题
+- AGENTS.md - AI 编码指南
+- CHANGELOG.md - 变更日志
+
+### 2. 创建文档分支
+
+```bash
+git checkout -b docs/update-documentation
+```
+
+### 3. 更新文档
+
+#### README.md
+
+添加新功能说明:
+
+```markdown
+## 新功能
+
+### 应用更新
+
+现在支持一键更新所有可更新的应用。
+
+### 下载管理
+
+改进了下载队列管理,支持暂停和继续。
+```
+
+#### DEVELOPMENT.md
+
+添加开发指南:
+
+```markdown
+## 新功能开发
+
+### 添加新功能步骤
+
+1. 理解需求
+2. 设计方案
+3. 实现功能
+4. 编写测试
+5. 提交 PR
+```
+
+#### CONTRIBUTING.md
+
+更新贡献指南:
+
+```markdown
+### 新功能贡献
+
+- 遵循现有代码风格
+- 编写充分的测试
+- 更新相关文档
+```
+
+#### TESTING.md
+
+添加测试示例:
+
+```typescript
+describe("New Feature", () => {
+ it("should work correctly", () => {
+ // 测试代码
+ });
+});
+```
+
+#### CHANGELOG.md
+
+添加变更记录:
+
+```markdown
+## [4.10.0](https://github.com/elysia-best/apm-app-store/compare/v4.9.9...v4.10.0) (2026-03-10)
+
+### Features
+
+- feat(download): add pause and resume for downloads
+- feat(update): add batch update for apps
+
+### Bug Fixes
+
+- fix(ui): correct dark mode toggle persistence
+```
+
+### 4. 检查文档质量
+
+- [ ] 语法正确
+- [ ] 格式统一
+- [ ] 链接有效
+- [ ] 内容准确
+- [ ] 示例可运行
+
+### 5. 运行文档测试
+
+```bash
+# 如果有文档测试
+npm run test:docs
+
+# 检查链接
+npm run check-links
+```
+
+### 6. 本地预览
+
+使用 Markdown 预览工具查看效果。
+
+### 7. 提交文档
+
+```bash
+git add .
+git commit -m "docs: update documentation for new features" -s
+git push origin docs/update-documentation
+```
+
+### 8. 创建 Pull Request
+
+- 说明更新的内容
+- 提供预览截图(如需要)
+- 引用相关 Issue
+
+### 9. 代码审查
+
+- 响应审查意见
+- 确保文档质量
+- 合并到 main 分支
+
+## 文档编写规范
+
+### 格式规范
+
+- 使用 Markdown
+- 保持一致的标题层级
+- 使用代码块展示示例
+- 使用表格对比选项
+
+### 语言规范
+
+- 使用简洁清晰的语言
+- 避免技术术语(或解释)
+- 保持中英文术语一致
+- 使用被动语态
+
+### 示例规范
+
+```typescript
+// 好的示例
+import { ref } from "vue";
+
+const count = ref(0);
+
+function increment() {
+ count.value++;
+}
+```
+
+### 链接规范
+
+```markdown
+- 内部链接: [文档名](./document.md)
+- 外部链接: [Vue 文档](https://vuejs.org/)
+- 锚点链接: [章节](#section-name)
+```
+
+## 文档模板
+
+### 新功能文档
+
+````markdown
+## 功能名称
+
+### 描述
+
+简要描述功能
+
+### 使用方法
+
+```typescript
+// 示例代码
+```
+````
+
+### 配置选项
+
+| 选项 | 类型 | 默认值 | 说明 |
+| ------ | ------ | --------- | -------- |
+| option | string | 'default' | 选项说明 |
+
+### 注意事项
+
+- 注意事项 1
+- 注意事项 2
+
+````
+
+### API 文档
+
+```markdown
+## API 函数名
+
+### 签名
+```typescript
+function functionName(param1: Type1, param2: Type2): ReturnType
+````
+
+### 参数
+
+| 参数 | 类型 | 必填 | 说明 |
+| ------ | ----- | ---- | -------- |
+| param1 | Type1 | 是 | 参数说明 |
+| param2 | Type2 | 否 | 参数说明 |
+
+### 返回值
+
+| 类型 | 说明 |
+| ---------- | ---------- |
+| ReturnType | 返回值说明 |
+
+### 示例
+
+```typescript
+const result = functionName(arg1, arg2);
+```
+
+### 错误
+
+抛出 `Error` 异常的情况说明。
+
+```
+
+## 注意事项
+
+- ⚠️ 保持文档与代码同步
+- ⚠️ 更新示例代码
+- ⚠️ 检查链接有效性
+- ⚠️ 使用统一的格式
+- ⚠️ 提供清晰的说明
+
+## 相关文档
+
+- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
+- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
+- [AGENTS.md](../../AGENTS.md) - AI 编码指南
+```
diff --git a/.agents/workflows/feature-development.md b/.agents/workflows/feature-development.md
new file mode 100644
index 00000000..6ed4b69a
--- /dev/null
+++ b/.agents/workflows/feature-development.md
@@ -0,0 +1,135 @@
+---
+description: 新功能开发流程
+---
+
+## 工作流说明
+
+此工作流指导如何开发新功能。
+
+## 步骤
+
+### 1. 理解需求
+
+- 阅读 Issue 描述
+- 确认功能范围
+- 识别依赖关系
+- 设计 API 和数据结构
+
+### 2. 设计方案
+
+- 设计 UI/UX(如需要)
+- 设计数据流
+- 确定 IPC 通信(如需要)
+- 编写技术方案文档(可选)
+
+### 3. 创建功能分支
+
+```bash
+git checkout -b feature/your-feature-name
+```
+
+### 4. 更新类型定义
+
+在 `src/global/typedefinition.ts` 中添加新的类型定义:
+
+```typescript
+export interface NewFeatureData {
+ id: string;
+ name: string;
+ // ...其他字段
+}
+```
+
+### 5. 编写测试
+
+先编写测试,遵循 TDD 原则:
+
+```typescript
+// src/__tests__/unit/newFeature.test.ts
+import { describe, it, expect } from "vitest";
+import { newFunction } from "@/modules/newFeature";
+
+describe("newFunction", () => {
+ it("should work correctly", () => {
+ const result = newFunction(input);
+ expect(result).toBe(expected);
+ });
+});
+```
+
+### 6. 实现功能
+
+按照以下顺序实现:
+
+- 后端逻辑(Electron 主进程)
+- 前端逻辑(Vue 组件)
+- IPC 通信(如需要)
+- 样式和布局
+
+### 7. 运行测试
+
+```bash
+# 单元测试
+npm run test
+
+# E2E 测试
+npm run test:e2e
+
+# 代码检查
+npm run lint
+npm run format
+```
+
+### 8. 本地测试
+
+- 测试所有功能场景
+- 测试边界情况
+- 测试错误处理
+- 检查性能影响
+
+### 9. 更新文档
+
+- 更新 API 文档(如需要)
+- 更新用户文档(如需要)
+- 更新 CHANGELOG.md
+
+### 10. 提交代码
+
+```bash
+git add .
+git commit -m "feat(scope): add new feature" -s
+git push origin feature/your-feature-name
+```
+
+### 11. 创建 Pull Request
+
+- 使用 PR 模板
+- 引用相关 Issue
+- 添加测试说明
+- 添加截图/录屏(UI 变更)
+
+### 12. 代码审查
+
+- 响应审查意见
+- 进行必要的修改
+- 确保所有 CI 检查通过
+
+### 13. 合并
+
+- 等待审查批准
+- Squash 合并到 main 分支
+- 删除功能分支
+
+## 注意事项
+
+- ⚠️ 保持 PR 小而聚焦(建议 < 500 行)
+- ⚠️ 确保 TypeScript 严格模式通过
+- ⚠️ 不引入 `any` 类型(必要时使用 `eslint-disable`)
+- ⚠️ 所有新功能必须有测试
+- ⚠️ 遵循代码规范
+
+## 相关文档
+
+- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
+- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
+- [TESTING.md](../../TESTING.md) - 测试文档
diff --git a/.agents/workflows/performance-optimization.md b/.agents/workflows/performance-optimization.md
new file mode 100644
index 00000000..edbb3430
--- /dev/null
+++ b/.agents/workflows/performance-optimization.md
@@ -0,0 +1,333 @@
+---
+description: 性能优化流程
+---
+
+## 工作流说明
+
+此工作流指导如何优化应用性能。
+
+## 步骤
+
+### 1. 识别性能问题
+
+使用工具分析性能:
+
+- Chrome DevTools Performance
+- Vue DevTools
+- Vite Build Analysis
+- 内存分析工具
+
+### 2. 分析瓶颈
+
+确定性能瓶颈:
+
+- 渲染性能
+- 网络请求
+- 内存使用
+- CPU 使用
+- 磁盘 I/O
+
+### 3. 创建优化分支
+
+```bash
+git checkout -b perf/optimize-performance
+```
+
+### 4. 添加性能测试
+
+```typescript
+// src/__tests__/perf/performance.test.ts
+import { describe, it, expect } from "vitest";
+import { heavyFunction } from "@/modules/example";
+
+describe("heavyFunction", () => {
+ it("should complete within 100ms", () => {
+ const start = performance.now();
+ heavyFunction();
+ const duration = performance.now() - start;
+ expect(duration).toBeLessThan(100);
+ });
+});
+```
+
+### 5. 实施优化
+
+#### 渲染性能优化
+
+```typescript
+// 使用 computed 缓存计算结果
+const filteredApps = computed(() => {
+ return apps.value.filter(app => app.category === selectedCategory);
+});
+
+// 使用 v-memo 优化列表渲染
+
+
+ {{ app.name }}
+
+
+
+// 防抖和节流
+import { debounce } from 'lodash-es';
+
+const debouncedSearch = debounce((query: string) => {
+ searchApps(query);
+}, 300);
+```
+
+#### 网络请求优化
+
+```typescript
+// 使用缓存
+const appCache = new Map();
+
+async function fetchApps(category: string): Promise {
+ if (appCache.has(category)) {
+ return appCache.get(category)!;
+ }
+
+ const apps = await axios.get(`/api/apps/${category}`);
+ appCache.set(category, apps.data);
+ return apps.data;
+}
+
+// 并发请求
+const [apps1, apps2] = await Promise.all([
+ fetchApps("category1"),
+ fetchApps("category2"),
+]);
+```
+
+#### 内存优化
+
+```typescript
+// 及时清理事件监听
+onMounted(() => {
+ window.addEventListener("resize", handleResize);
+});
+
+onUnmounted(() => {
+ window.removeEventListener("resize", handleResize);
+});
+
+// 避免内存泄漏
+let timer: number;
+
+function startTimer() {
+ clearInterval(timer);
+ timer = setInterval(() => {
+ // 定时任务
+ }, 1000);
+}
+
+onUnmounted(() => {
+ clearInterval(timer);
+});
+```
+
+#### 代码分割
+
+```typescript
+// 动态导入组件
+const AppDetailModal = defineAsyncComponent(
+ () => import("@/components/AppDetailModal.vue"),
+);
+
+// 路由懒加载
+const routes = [
+ {
+ path: "/app/:id",
+ component: () => import("@/views/AppDetail.vue"),
+ },
+];
+```
+
+### 6. 测试性能
+
+```bash
+# 运行性能测试
+npm run test:perf
+
+# 使用 DevTools 分析
+# 1. 打开 DevTools
+# 2. 切换到 Performance 标签
+# 3. 点击 Record
+# 4. 执行操作
+# 5. 停止录制并分析
+```
+
+### 7. 对比优化效果
+
+记录优化前后的数据:
+
+- 渲染时间
+- 内存使用
+- 网络请求数
+- 应用启动时间
+
+### 8. 验证功能
+
+```bash
+# 确保功能正常
+npm run test
+
+# 手动测试主要流程
+```
+
+### 9. 代码审查
+
+检查优化是否:
+
+- 提升了性能
+- 没有破坏功能
+- 代码可读
+- 易于维护
+
+### 10. 更新文档
+
+- 记录优化内容
+- 更新性能指标
+- 添加优化说明
+
+### 11. 提交代码
+
+```bash
+git add .
+git commit -m "perf(scope): optimize performance" -s
+git push origin perf/optimize-performance
+```
+
+### 12. 创建 Pull Request
+
+- 说明优化内容
+- 提供性能对比
+- 展示优化效果
+
+## 性能优化清单
+
+### 渲染性能
+
+- [ ] 使用 computed 缓存
+- [ ] 使用 v-memo 优化
+- [ ] 避免不必要的重新渲染
+- [ ] 使用虚拟滚动(大数据集)
+- [ ] 图片懒加载
+
+### 网络性能
+
+- [ ] 减少请求数量
+- [ ] 使用缓存
+- [ ] 压缩资源
+- [ ] 使用 CDN
+- [ ] 并发请求
+
+### 内存性能
+
+- [ ] 清理事件监听
+- [ ] 避免内存泄漏
+- [ ] 释放不再使用的资源
+- [ ] 使用对象池(如需要)
+- [ ] 优化数据结构
+
+### 构建性能
+
+- [ ] 代码分割
+- [ ] Tree shaking
+- [ ] 压缩代码
+- [ ] 优化依赖
+- [ ] 使用缓存
+
+## 性能监控
+
+### 关键指标
+
+- **FCP (First Contentful Paint):** < 1.5s
+- **LCP (Largest Contentful Paint):** < 2.5s
+- **TTI (Time to Interactive):** < 3.5s
+- **CLS (Cumulative Layout Shift):** < 0.1
+- **FID (First Input Delay):** < 100ms
+
+### 监控工具
+
+```typescript
+// 使用 Performance API
+const perfData = performance.getEntriesByType("navigation")[0];
+console.log("Page Load Time:", perfData.loadEventEnd - perfData.fetchStart);
+
+// 使用 Vue DevTools
+// 监控组件渲染时间
+```
+
+## 常见性能问题
+
+### 1. 大列表渲染
+
+**问题:** 渲染大量数据导致卡顿
+
+**解决方案:**
+
+```vue
+
+
+
+ {{ item.name }}
+
+
+
+```
+
+### 2. 频繁的 DOM 更新
+
+**问题:** 频繁更新 DOM 导致性能下降
+
+**解决方案:**
+
+```typescript
+// 使用 requestAnimationFrame
+function animate() {
+ updatePosition();
+ requestAnimationFrame(animate);
+}
+```
+
+### 3. 内存泄漏
+
+**问题:** 内存持续增长
+
+**解决方案:**
+
+```typescript
+// 及时清理
+onUnmounted(() => {
+ clearInterval(timer);
+ removeEventListener("resize", handleResize);
+ clearTimeout(timeout);
+});
+```
+
+### 4. 不必要的计算
+
+**问题:** 重复计算相同结果
+
+**解决方案:**
+
+```typescript
+// 使用 computed
+const expensiveValue = computed(() => {
+ return heavyCalculation(data.value);
+});
+```
+
+## 注意事项
+
+- ⚠️ 不要过早优化
+- ⚠️ 先测量再优化
+- ⚠️ 保持代码可读
+- ⚠️ 避免过度优化
+- ⚠️ 持续监控性能
+
+## 相关文档
+
+- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
+- [TESTING.md](../../TESTING.md) - 测试文档
+- [TROUBLESHOOTING.md](../../TROUBLESHOOTING.md) - 问题排查
diff --git a/.agents/workflows/refactoring.md b/.agents/workflows/refactoring.md
new file mode 100644
index 00000000..09f36201
--- /dev/null
+++ b/.agents/workflows/refactoring.md
@@ -0,0 +1,284 @@
+---
+description: 代码重构流程
+---
+
+## 工作流说明
+
+此工作流指导如何安全地重构代码。
+
+## 步骤
+
+### 1. 识别重构需求
+
+分析代码中的问题:
+
+- 代码重复
+- 复杂度过高
+- 性能问题
+- 可读性差
+- 难以维护
+
+### 2. 制定重构计划
+
+- 确定重构范围
+- 列出具体改进点
+- 评估影响范围
+- 制定测试策略
+
+### 3. 创建重构分支
+
+```bash
+git checkout -b refactor/your-refactor
+```
+
+### 4. 编写测试
+
+如果代码缺少测试,先添加测试:
+
+```typescript
+// src/__tests__/unit/refactorTarget.test.ts
+import { describe, it, expect } from "vitest";
+import { functionToRefactor } from "@/modules/example";
+
+describe("functionToRefactor", () => {
+ it("should maintain existing behavior", () => {
+ const result = functionToRefactor(input);
+ expect(result).toBe(expected);
+ });
+});
+```
+
+### 5. 逐步重构
+
+**原则:**
+
+- 小步迭代
+- 保持测试通过
+- 不改变外部行为
+
+**示例:**
+
+```typescript
+// 重构前
+function processApp(app: any) {
+ if (app) {
+ return {
+ name: app.name,
+ pkgname: app.pkgname,
+ version: app.version,
+ };
+ }
+ return null;
+}
+
+// 重构后 - 添加类型
+interface App {
+ name: string;
+ pkgname: string;
+ version: string;
+}
+
+function processApp(app: App | null): App | null {
+ if (!app) return null;
+
+ return {
+ name: app.name,
+ pkgname: app.pkgname,
+ version: app.version,
+ };
+}
+```
+
+### 6. 运行测试
+
+```bash
+# 每次重构后运行测试
+npm run test
+
+# 确保所有测试通过
+npm run test:all
+```
+
+### 7. 性能验证
+
+如果重构涉及性能:
+
+```bash
+# 运行性能测试
+npm run test:perf
+
+# 对比重构前后性能
+```
+
+### 8. 代码审查
+
+自我检查:
+
+- 代码更清晰
+- 性能未下降
+- 测试全部通过
+- 没有引入新问题
+
+### 9. 更新文档
+
+- 更新相关文档
+- 添加注释说明
+- 更新 CHANGELOG.md
+
+### 10. 提交代码
+
+```bash
+git add .
+git commit -m "refactor(scope): describe the refactoring" -s
+git push origin refactor/your-refactor
+```
+
+### 11. 创建 Pull Request
+
+- 说明重构原因
+- 展示改进效果
+- 提供性能对比(如需要)
+
+### 12. 代码审查
+
+- 响应审查意见
+- 确保所有测试通过
+- 合并到 main 分支
+
+## 重构原则
+
+### 不改变外部行为
+
+- 保持 API 兼容
+- 保持输出一致
+- 保持错误处理
+
+### 小步迭代
+
+- 每次只改一处
+- 频繁运行测试
+- 及时提交代码
+
+### 测试驱动
+
+- 先写测试
+- 重构代码
+- 确保通过
+
+### 保持简单
+
+- 减少复杂度
+- 提高可读性
+- 增强可维护性
+
+## 常见重构模式
+
+### 提取函数
+
+```typescript
+// 重构前
+function processApps(apps: App[]) {
+ for (const app of apps) {
+ if (app.installed) {
+ console.log(app.name + " is installed");
+ }
+ }
+}
+
+// 重构后
+function logInstalledApp(app: App) {
+ if (app.installed) {
+ console.log(`${app.name} is installed`);
+ }
+}
+
+function processApps(apps: App[]) {
+ apps.forEach(logInstalledApp);
+}
+```
+
+### 提取类型
+
+```typescript
+// 重构前
+function createDownload(data: any) {
+ return {
+ id: data.id,
+ name: data.name,
+ pkgname: data.pkgname,
+ };
+}
+
+// 重构后
+interface DownloadData {
+ id: number;
+ name: string;
+ pkgname: string;
+}
+
+function createDownload(data: DownloadData): DownloadItem {
+ return {
+ id: data.id,
+ name: data.name,
+ pkgname: data.pkgname,
+ status: "queued",
+ progress: 0,
+ downloadedSize: 0,
+ totalSize: 0,
+ speed: 0,
+ timeRemaining: 0,
+ startTime: Date.now(),
+ logs: [],
+ source: "APM Store",
+ retry: false,
+ };
+}
+```
+
+### 简化条件
+
+```typescript
+// 重构前
+function getStatus(status: string): string {
+ if (status === "queued") {
+ return "Queued";
+ } else if (status === "downloading") {
+ return "Downloading";
+ } else if (status === "installing") {
+ return "Installing";
+ } else if (status === "completed") {
+ return "Completed";
+ } else if (status === "failed") {
+ return "Failed";
+ } else {
+ return "Unknown";
+ }
+}
+
+// 重构后
+const statusMap: Record = {
+ queued: "Queued",
+ downloading: "Downloading",
+ installing: "Installing",
+ completed: "Completed",
+ failed: "Failed",
+};
+
+function getStatus(status: string): string {
+ return statusMap[status] || "Unknown";
+}
+```
+
+## 注意事项
+
+- ⚠️ 不要在重构中引入新功能
+- ⚠️ 不要同时重构多处
+- ⚠️ 确保测试覆盖充分
+- ⚠️ 保持提交历史清晰
+- ⚠️ 及时回退有问题的重构
+
+## 相关文档
+
+- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
+- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
+- [TESTING.md](../../TESTING.md) - 测试文档
diff --git a/.agents/workflows/release.md b/.agents/workflows/release.md
new file mode 100644
index 00000000..be960e5d
--- /dev/null
+++ b/.agents/workflows/release.md
@@ -0,0 +1,211 @@
+---
+description: 发布流程
+---
+
+## 工作流说明
+
+此工作流指导如何发布新版本。
+
+## 步骤
+
+### 1. 更新版本号
+
+```bash
+# 更新版本
+npm version patch # 1.0.0 → 1.0.1
+npm version minor # 1.0.0 → 1.1.0
+npm version major # 1.0.0 → 2.0.0
+
+# 或手动编辑 package.json
+```
+
+### 2. 更新 CHANGELOG.md
+
+```bash
+# 生成变更日志
+npm run changelog
+```
+
+或手动更新:
+
+```markdown
+## [1.0.1](https://github.com/elysia-best/apm-app-store/compare/v1.0.0...v1.0.1) (2026-03-10)
+
+### Bug Fixes
+
+- fix(ui): correct dark mode toggle persistence (#123)
+
+### Features
+
+- feat(install): add retry mechanism for failed installations (#124)
+```
+
+### 3. 运行完整测试
+
+```bash
+# 运行所有测试
+npm run test:all
+
+# 运行代码检查
+npm run lint
+npm run format
+
+# 构建项目
+npm run build:vite
+```
+
+### 4. 提交变更
+
+```bash
+git add .
+git commit -m "chore(release): bump version to x.x.x" -s
+git push origin main
+```
+
+### 5. 创建 Git 标签
+
+```bash
+# 创建标签
+git tag v{version}
+
+# 推送标签
+git push origin v{version}
+```
+
+### 6. 触发 CI 构建
+
+推送标签后会自动触发 GitHub Actions 构建。
+
+### 7. 验证构建
+
+在 GitHub Actions 页面查看:
+
+- 所有测试通过
+- 构建成功
+- 构建产物生成
+
+### 8. 检查 Release
+
+GitHub Actions 会自动创建 Release:
+
+- 访问 Releases 页面
+- 检查版本信息
+- 确认构建产物
+
+### 9. 发布说明
+
+如果需要,更新 Release 说明:
+
+- 添加主要变更
+- 添加已知问题
+- 添加升级说明
+
+### 10. 通知用户
+
+- 更新 README
+- 发布公告
+- 通知用户
+
+## 发布检查清单
+
+### 代码质量
+
+- [ ] 所有测试通过
+- [ ] 代码检查通过
+- [ ] 没有已知严重 Bug
+- [ ] 性能测试通过
+
+### 文档
+
+- [ ] CHANGELOG.md 更新
+- [ ] README.md 更新(如需要)
+- [ ] API 文档更新(如需要)
+
+### 构建
+
+- [ ] 本地构建成功
+- [ ] CI 构建成功
+- [ ] 构建产物正确
+
+### 发布
+
+- [ ] 版本号正确
+- [ ] 标签已推送
+- [ ] Release 已创建
+- [ ] 构建产物已上传
+
+## 版本号规范
+
+遵循 [Semantic Versioning](https://semver.org/):
+
+- **MAJOR:** 不兼容的 API 变更
+- **MINOR:** 向后兼容的功能新增
+- **PATCH:** 向后兼容的 Bug 修复
+
+### 示例
+
+```
+4.9.9 → 4.9.10 (PATCH: Bug 修复)
+4.9.9 → 4.10.0 (MINOR: 新功能)
+4.9.9 → 5.0.0 (MAJOR: 重大变更)
+```
+
+## 发布后
+
+### 更新开发分支
+
+```bash
+git checkout develop
+git merge main
+git push origin develop
+```
+
+### 监控反馈
+
+- 收集用户反馈
+- 监控 Bug 报告
+- 记录性能数据
+
+### 准备下一个版本
+
+- 创建新的 Issue
+- 规划新功能
+- 评估技术债务
+
+## 回滚流程
+
+如果发现严重问题:
+
+### 1. 立即停止推广
+
+- 通知用户暂停升级
+- 更新下载页面
+
+### 2. 修复问题
+
+```bash
+git checkout main
+git checkout -b fix/critical-issue
+# 修复问题
+git push origin fix/critical-issue
+```
+
+### 3. 紧急发布
+
+```bash
+npm version patch
+git tag -a v{x.x.x} -m "Hotfix: description"
+git push origin v{x.x.x}
+```
+
+### 4. 通知用户
+
+- 发布新版本
+- 说明问题和修复
+- 提供升级说明
+
+## 相关文档
+
+- [DEPLOYMENT.md](../../DEPLOYMENT.md) - 部署文档
+- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
+- [CHANGELOG.md](../../CHANGELOG.md) - 变更日志
diff --git a/.agents/workflows/security-audit.md b/.agents/workflows/security-audit.md
new file mode 100644
index 00000000..fab0ada7
--- /dev/null
+++ b/.agents/workflows/security-audit.md
@@ -0,0 +1,435 @@
+---
+description: 安全审计流程
+---
+
+## 工作流说明
+
+此工作流指导如何进行安全审计。
+
+## 步骤
+
+### 1. 确定审计范围
+
+确定需要审计的方面:
+
+- 代码安全
+- 依赖安全
+- 数据安全
+- 网络安全
+- 权限管理
+
+### 2. 创建审计分支
+
+```bash
+git checkout -b security/security-audit
+```
+
+### 3. 代码安全审计
+
+#### 检查 SQL 注入
+
+```typescript
+// ❌ 不安全
+const query = `SELECT * FROM apps WHERE name = '${appName}'`;
+
+// ✅ 安全
+const query = "SELECT * FROM apps WHERE name = ?";
+db.query(query, [appName]);
+```
+
+#### 检查 XSS 攻击
+
+```typescript
+// ❌ 不安全
+element.innerHTML = userInput;
+
+// ✅ 安全
+element.textContent = userInput;
+// 或使用 DOMPurify
+import DOMPurify from "dompurify";
+element.innerHTML = DOMPurify.sanitize(userInput);
+```
+
+#### 检查命令注入
+
+```typescript
+// ❌ 不安全
+const cmd = `apm install ${packageName}`;
+exec(cmd);
+
+// ✅ 安全
+const args = ["apm", "install", packageName];
+spawn("apm", args);
+```
+
+#### 检查路径遍历
+
+```typescript
+// ❌ 不安全
+const filePath = path.join(basePath, userInput);
+
+// ✅ 安全
+const safePath = path.normalize(userInput).replace(/^(\.\.(\/|\\|$))+/, "");
+const filePath = path.join(basePath, safePath);
+```
+
+### 4. 依赖安全审计
+
+```bash
+# 检查依赖漏洞
+npm audit
+
+# 自动修复
+npm audit fix
+
+# 手动修复
+npm audit fix --force
+```
+
+#### 检查 package.json
+
+```json
+{
+ "dependencies": {
+ "axios": "^1.13.2",
+ "pino": "^10.3.0"
+ },
+ "devDependencies": {
+ "@playwright/test": "^1.40.0"
+ }
+}
+```
+
+### 5. 数据安全审计
+
+#### 检查敏感信息
+
+```typescript
+// ❌ 不安全 - 硬编码密钥
+const apiKey = "sk-1234567890";
+
+// ✅ 安全 - 使用环境变量
+const apiKey = process.env.API_KEY;
+
+// ❌ 不安全 - 记录敏感信息
+logger.info({ password: user.password }, "User logged in");
+
+// ✅ 安全 - 不记录敏感信息
+logger.info({ userId: user.id }, "User logged in");
+```
+
+#### 检查数据加密
+
+```typescript
+// 加密敏感数据
+import crypto from "crypto";
+
+function encrypt(text: string, key: string): string {
+ const iv = crypto.randomBytes(16);
+ const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
+ let encrypted = cipher.update(text, "utf8", "hex");
+ encrypted += cipher.final("hex");
+ return iv.toString("hex") + ":" + encrypted;
+}
+```
+
+### 6. 网络安全审计
+
+#### 检查 HTTPS
+
+```typescript
+// ❌ 不安全 - HTTP
+const baseURL = "http://api.example.com";
+
+// ✅ 安全 - HTTPS
+const baseURL = "https://api.example.com";
+```
+
+#### 检查证书验证
+
+```typescript
+// 配置 Axios 验证证书
+const axiosInstance = axios.create({
+ httpsAgent: new https.Agent({
+ rejectUnauthorized: true,
+ }),
+});
+```
+
+#### 检查 CORS
+
+```typescript
+// 配置 CORS
+app.use(
+ cors({
+ origin: "https://yourdomain.com",
+ credentials: true,
+ }),
+);
+```
+
+### 7. 权限管理审计
+
+#### 检查权限提升
+
+```typescript
+// 检查 pkexec 可用性
+const checkSuperUserCommand = async (): Promise => {
+ if (process.getuid && process.getuid() !== 0) {
+ const { stdout } = await execAsync("which /usr/bin/pkexec");
+ return stdout.trim().length > 0 ? "/usr/bin/pkexec" : "";
+ }
+ return "";
+};
+```
+
+#### 检查上下文隔离
+
+```typescript
+// electron/preload/index.ts
+// ✅ 安全 - 启用上下文隔离
+contextBridge.exposeInMainWorld("ipcRenderer", {
+ send: (...args) => ipcRenderer.send(...args),
+ on: (...args) => ipcRenderer.on(...args),
+ invoke: (...args) => ipcRenderer.invoke(...args),
+});
+
+// ❌ 不安全 - 禁用上下文隔离
+contextIsolation: false;
+```
+
+### 8. 运行安全工具
+
+```bash
+# 使用 Snyk 扫描
+npx snyk test
+
+# 使用 npm audit
+npm audit
+
+# 使用 ESLint 安全规则
+npm run lint
+```
+
+### 9. 修复安全问题
+
+根据审计结果修复发现的问题:
+
+```typescript
+// 修复示例
+function validateInput(input: string): boolean {
+ // 验证输入
+ const regex = /^[a-zA-Z0-9-_]+$/;
+ return regex.test(input);
+}
+
+function sanitizeInput(input: string): string {
+ // 清理输入
+ return input.trim().replace(/[<>]/g, "");
+}
+```
+
+### 10. 安全测试
+
+```typescript
+// src/__tests__/security/security.test.ts
+import { describe, it, expect } from "vitest";
+import { validateInput, sanitizeInput } from "@/modules/security";
+
+describe("Security", () => {
+ describe("validateInput", () => {
+ it("should reject malicious input", () => {
+ expect(validateInput('')).toBe(false);
+ });
+
+ it("should accept valid input", () => {
+ expect(validateInput("valid-app-name")).toBe(true);
+ });
+ });
+
+ describe("sanitizeInput", () => {
+ it("should remove dangerous characters", () => {
+ expect(sanitizeInput("")).toBe("scriptapp/script");
+ });
+ });
+});
+```
+
+### 11. 更新文档
+
+- 记录安全问题
+- 说明修复方法
+- 更新安全指南
+
+### 12. 提交代码
+
+```bash
+git add .
+git commit -m "security: fix security vulnerabilities" -s
+git push origin security/security-audit
+```
+
+### 13. 创建 Pull Request
+
+- 说明安全问题
+- 展示修复方法
+- 提供安全测试结果
+
+## 安全检查清单
+
+### 代码安全
+
+- [ ] 输入验证
+- [ ] 输出编码
+- [ ] 参数化查询
+- [ ] 错误处理
+- [ ] 日志安全
+
+### 依赖安全
+
+- [ ] 定期更新依赖
+- [ ] 使用 `npm audit`
+- [ ] 检查已知漏洞
+- [ ] 使用可信源
+
+### 数据安全
+
+- [ ] 敏感数据加密
+- [ ] 不记录敏感信息
+- [ ] 使用环境变量
+- [ ] 安全存储
+
+### 网络安全
+
+- [ ] 使用 HTTPS
+- [ ] 验证证书
+- [ ] 配置 CORS
+- [ ] 防止 CSRF
+
+### 权限管理
+
+- [ ] 最小权限原则
+- [ ] 上下文隔离
+- [ ] 权限检查
+- [ ] 审计日志
+
+## 常见安全问题
+
+### 1. XSS 攻击
+
+**问题:** 用户输入包含恶意脚本
+
+**解决方案:**
+
+```typescript
+import DOMPurify from "dompurify";
+
+function sanitizeHTML(html: string): string {
+ return DOMPurify.sanitize(html);
+}
+```
+
+### 2. SQL 注入
+
+**问题:** 恶意 SQL 代码注入
+
+**解决方案:**
+
+```typescript
+// 使用参数化查询
+db.query("SELECT * FROM apps WHERE name = ?", [appName]);
+```
+
+### 3. 命令注入
+
+**问题:** 恶意命令注入
+
+**解决方案:**
+
+```typescript
+// 使用 spawn 而非 exec
+const args = ["apm", "install", packageName];
+spawn("apm", args);
+```
+
+### 4. 路径遍历
+
+**问题:** 访问未授权文件
+
+**解决方案:**
+
+```typescript
+// 验证路径
+const safePath = path.normalize(userPath).replace(/^(\.\.(\/|\\|$))+/, "");
+```
+
+### 5. 敏感信息泄露
+
+**问题:** 日志中包含敏感信息
+
+**解决方案:**
+
+```typescript
+// 不记录敏感信息
+logger.info({ userId: user.id }, "User logged in");
+```
+
+## 安全最佳实践
+
+### 1. 最小权限原则
+
+只授予必要的权限,避免过度授权。
+
+### 2. 深度防御
+
+多层安全防护,不依赖单一安全措施。
+
+### 3. 输入验证
+
+验证所有输入,包括用户输入和 API 响应。
+
+### 4. 输出编码
+
+对输出进行编码,防止 XSS 攻击。
+
+### 5. 定期审计
+
+定期进行安全审计,及时发现和修复问题。
+
+### 6. 安全更新
+
+及时更新依赖和系统,修复已知漏洞。
+
+## 安全工具
+
+### 静态分析
+
+- ESLint
+- TypeScript
+- SonarQube
+
+### 动态分析
+
+- OWASP ZAP
+- Burp Suite
+- Snyk
+
+### 依赖扫描
+
+- npm audit
+- Snyk
+- Dependabot
+
+## 注意事项
+
+- ⚠️ 不要忽视安全问题
+- ⚠️ 及时修复漏洞
+- ⚠️ 定期更新依赖
+- ⚠️ 保持安全意识
+- ⚠️ 遵循安全最佳实践
+
+## 相关文档
+
+- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
+- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
+- [SECURITY.md](../../SECURITY.md) - 安全政策
diff --git a/.agents/workflows/testing.md b/.agents/workflows/testing.md
new file mode 100644
index 00000000..bea9e889
--- /dev/null
+++ b/.agents/workflows/testing.md
@@ -0,0 +1,108 @@
+---
+description: 测试编写流程
+---
+
+## 工作流说明
+
+此工作流指导如何为新功能或 Bug 修复编写测试。
+
+## 步骤
+
+### 1. 确定测试范围
+
+分析需要测试的功能点:
+
+- 单元测试:测试独立函数/组件
+- 集成测试:测试模块间交互
+- E2E 测试:测试完整用户流程
+
+### 2. 编写单元测试(Vitest)
+
+在 `src/__tests__/unit/` 目录下创建测试文件:
+
+```typescript
+import { describe, it, expect } from "vitest";
+import { someFunction } from "@/modules/example";
+
+describe("someFunction", () => {
+ it("should return expected result", () => {
+ const result = someFunction(input);
+ expect(result).toBe(expected);
+ });
+});
+```
+
+### 3. 编写组件测试
+
+```typescript
+import { describe, it, expect } from "vitest";
+import { mount } from "@vue/test-utils";
+import AppCard from "@/components/AppCard.vue";
+
+describe("AppCard", () => {
+ it("should render app name", () => {
+ const wrapper = mount(AppCard, {
+ props: {
+ app: {
+ name: "Test App",
+ pkgname: "test-app",
+ },
+ },
+ });
+ expect(wrapper.text()).toContain("Test App");
+ });
+});
+```
+
+### 4. 编写 E2E 测试(Playwright)
+
+在 `e2e/` 目录下创建测试文件:
+
+```typescript
+import { test, expect } from "@playwright/test";
+
+test("install app from store", async ({ page }) => {
+ await page.goto("http://localhost:3344");
+ await page.click("text=Test App");
+ await page.click('button:has-text("安装")');
+ await expect(page.locator(".install-progress")).toBeVisible();
+});
+```
+
+### 5. 运行测试
+
+```bash
+# 运行单元测试
+npm run test
+
+# 运行测试并监听
+npm run test:watch
+
+# 运行 E2E 测试
+npm run test:e2e
+
+# 生成覆盖率报告
+npm run test:coverage
+```
+
+### 6. 确保测试通过
+
+- 所有单元测试必须通过
+- E2E 测试覆盖主要用户流程
+- 测试覆盖率不低于 70%
+
+### 7. 提交代码
+
+测试通过后,提交代码并创建 PR。
+
+## 注意事项
+
+- ⚠️ 不要测试第三方库的功能
+- ⚠️ 保持测试独立性和可重复性
+- ⚠️ 使用有意义的测试名称
+- ⚠️ Mock 外部依赖(APM 命令、API 调用)
+
+## 相关文档
+
+- [TESTING.md](../../TESTING.md) - 测试框架和规范
+- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
diff --git a/.agents/workflows/代码审查.md b/.agents/workflows/代码审查.md
deleted file mode 100644
index 4db78530..00000000
--- a/.agents/workflows/代码审查.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-description: 审查
----
-
-审查是否符合代码规范
-是否有代码缺陷
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 2bc0b863..5761404b 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -1,11 +1,52 @@
---
-
-name: 🐞 Bug report
-about: Create a report to help us improve
-title: "[Bug] the title of bug report"
+name: Bug 报告
+about: 创建一个 Bug 报告以帮助我们改进
+title: "[Bug] "
labels: bug
-assignees: ''
-
+assignees: ""
---
-#### Describe the bug
+## 描述
+
+清晰简洁地描述这个 Bug 是什么。
+
+## 复现步骤
+
+1. 打开 '...'
+2. 点击 '....'
+3. 滚动到 '....'
+4. 看到错误
+
+## 期望行为
+
+清晰简洁地描述你期望发生什么。
+
+## 实际行为
+
+清晰简洁地描述实际发生了什么。
+
+## 截图
+
+如果适用,添加截图以帮助解释你的问题。
+
+## 环境信息
+
+**操作系统:** [例如: Ubuntu 22.04]
+
+**APM 版本:** [例如: 1.0.0]
+
+**应用商店版本:** [例如: 4.9.9]
+
+**桌面环境:** [例如: GNOME, KDE]
+
+## 日志
+
+如果相关,粘贴日志到以下区域(使用代码块):
+
+```
+粘贴日志内容
+```
+
+## 额外上下文
+
+添加任何其他关于问题的上下文信息。
diff --git a/.github/ISSUE_TEMPLATE/help_wanted.md b/.github/ISSUE_TEMPLATE/help_wanted.md
index 6fba797e..8e24b4a5 100644
--- a/.github/ISSUE_TEMPLATE/help_wanted.md
+++ b/.github/ISSUE_TEMPLATE/help_wanted.md
@@ -1,10 +1,23 @@
---
-name: 🥺 Help wanted
-about: Confuse about the use of electron-vue-vite
-title: "[Help] the title of help wanted report"
-labels: help wanted
-assignees: ''
-
+name: 功能请求 / 帮助请求
+about: 为这个项目建议一个新想法
+title: "[Feature] "
+labels: enhancement
+assignees: ""
---
-#### Describe the problem you confuse
+## 你的功能请求是否与问题有关?
+
+清晰简洁地描述问题。例如:我在 [...] 时总是感到沮丧
+
+## 你想要的解决方案是什么?
+
+清晰简洁地描述你想要发生什么。
+
+## 你考虑过哪些替代方案?
+
+清晰简洁地描述你考虑过的任何替代解决方案或功能。
+
+## 额外上下文
+
+添加任何其他关于功能请求的上下文或截图。
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 6dcf3a08..c45b8818 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -15,6 +15,7 @@ on:
- ".gitignore"
- ".github/**"
- "!.github/workflows/build.yml"
+ - "!.github/workflows/test.yml"
pull_request:
branches: [main]
paths-ignore:
@@ -32,7 +33,28 @@ permissions:
contents: write
jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v6
+ with:
+ node-version: 20
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run tests
+ run: npm run test
+
+ - name: Run lint
+ run: npm run lint
+
build:
+ needs: test
runs-on: ${{ matrix.os }}
container: ${{ matrix.docker_image }}
@@ -46,7 +68,6 @@ jobs:
docker_image: "debian:12"
- package: rpm
docker_image: "almalinux:8"
-
steps:
- name: Install Build Dependencies
@@ -71,7 +92,7 @@ jobs:
node-version: 20
- name: Install Dependencies
- run: |
+ run: |
npm install
- name: Download host-spawn
@@ -119,4 +140,4 @@ jobs:
files: |
artifacts/**/*.deb
artifacts/**/*.rpm
- generate_release_notes: true
\ No newline at end of file
+ generate_release_notes: true
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 00000000..6b23e95e
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,83 @@
+name: Test
+
+on:
+ push:
+ branches: [main, develop]
+ pull_request:
+ branches: [main, develop]
+
+jobs:
+ unit-tests:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v6
+ with:
+ node-version: 20
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run unit tests
+ run: npm run test -- --coverage
+
+ - name: Upload coverage to Codecov
+ uses: codecov/codecov-action@v4
+ with:
+ files: ./coverage/lcov.info
+ flags: unittests
+ name: codecov-umbrella
+
+ e2e-tests:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v6
+ with:
+ node-version: 20
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Install Playwright Browsers
+ run: npx playwright install --with-deps chromium
+
+ - name: Run E2E tests
+ run: npm run test:e2e
+
+ - name: Upload test results
+ if: always()
+ uses: actions/upload-artifact@v6
+ with:
+ name: playwright-report
+ path: playwright-report/
+ retention-days: 30
+
+ lint:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v6
+ with:
+ node-version: 20
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run ESLint
+ run: npm run lint
+
+ - name: Check formatting
+ run: npm run format -- --check
diff --git a/.gitignore b/.gitignore
index 4fa88e0d..c9dbc7d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,15 @@ dist-electron
release
*.local
+# Test coverage
+coverage
+.nyc_output
+
+# Playwright
+test-results
+playwright-report
+playwright/.cache
+
# Editor directories and files
.vscode/.debug.env
.idea
diff --git a/AGENTS.md b/AGENTS.md
index db3d87a6..71e08164 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,121 +1,128 @@
-# AI Coding Guidance for APM App Store
+# APM 应用商店 - AI 编码指南
-**Repository:** elysia-best/apm-app-store
-**Project Type:** Electron + Vue 3 + Vite Desktop Application
-**Purpose:** Desktop app store client for APM (AmberPM) package manager
-**License:** MulanPSL-2.0
+**仓库:** elysia-best/apm-app-store
+**项目类型:** Electron + Vue 3 + Vite 桌面应用
+**用途:** APM (AmberPM) 包管理器的桌面应用商店客户端
+**许可证:** GPL-3.0
---
-If you are an AI coding agent working on this repo, make sure to follow the guidelines below:
+如果你是 AI 编码代理,在此仓库工作时,请遵循以下指南:
-## 🏗️ Project Architecture Overview
+## 🏗️ 项目架构概览
-### Technology Stack
-- **Frontend Framework:** Vue 3 with Composition API (`
```
-### Props and Events Pattern
+### Props 和 Events 模式
```typescript
-// Props definition
+// Props 定义
const props = defineProps<{
app: App | null;
show: boolean;
}>();
-// Emits definition
+// Emits 定义
const emit = defineEmits<{
close: [];
install: [];
remove: [];
}>();
-// Usage
-emit('install');
+// 使用
+emit("install");
```
-### IPC Event Listeners in Vue
+### Vue 中的 IPC 事件监听
-**Always use in `onMounted` for proper cleanup:**
+**始终在 `onMounted` 中使用以便正确清理:**
```typescript
onMounted(() => {
- window.ipcRenderer.on('install-complete', (_event: IpcRendererEvent, result: DownloadResult) => {
- // Handle event
- });
+ window.ipcRenderer.on(
+ "install-complete",
+ (_event: IpcRendererEvent, result: DownloadResult) => {
+ // 处理事件
+ },
+ );
- window.ipcRenderer.on('install-log', (_event: IpcRendererEvent, log: InstallLog) => {
- // Handle log
- });
+ window.ipcRenderer.on(
+ "install-log",
+ (_event: IpcRendererEvent, log: InstallLog) => {
+ // 处理日志
+ },
+ );
});
```
---
-## 🔧 Main Process Patterns
+## 🔧 主进程模式
-### Spawning APM Commands
+### 生成 APM 命令
```typescript
-import { spawn } from 'node:child_process';
+import { spawn } from "node:child_process";
-// Check for privilege escalation
+// 检查权限提升
const superUserCmd = await checkSuperUserCommand();
const execCommand = superUserCmd.length > 0 ? superUserCmd : SHELL_CALLER_PATH;
-const execParams = superUserCmd.length > 0
- ? [SHELL_CALLER_PATH, 'apm', 'install', '-y', pkgname]
- : ['apm', 'install', '-y', pkgname];
+const execParams =
+ superUserCmd.length > 0
+ ? [SHELL_CALLER_PATH, "apm", "install", "-y", pkgname]
+ : ["apm", "install", "-y", pkgname];
-// Spawn process
+// 生成进程
const child = spawn(execCommand, execParams, {
shell: true,
env: process.env,
});
-// Stream output
-child.stdout.on('data', (data) => {
- webContents.send('install-log', { id, time: Date.now(), message: data.toString() });
+// 流式输出
+child.stdout.on("data", (data) => {
+ webContents.send("install-log", {
+ id,
+ time: Date.now(),
+ message: data.toString(),
+ });
});
-// Handle completion
-child.on('close', (code) => {
+// 处理完成
+child.on("close", (code) => {
const success = code === 0;
- webContents.send('install-complete', { id, success, exitCode: code, /* ... */ });
+ webContents.send("install-complete", {
+ id,
+ success,
+ exitCode: code /* ... */,
+ });
});
```
-### Parsing APM Output
+### 解析 APM 输出
-**APM outputs are text-based with specific formats:**
+**APM 输出是基于文本的特定格式:**
```typescript
-// Installed packages format: "pkgname/repo,version arch [flags]"
-// Example: "code/stable,1.108.2 amd64 [installed]"
+// 已安装包格式: "pkgname/repo,version arch [flags]"
+// 示例: "code/stable,1.108.2 amd64 [installed]"
const parseInstalledList = (output: string) => {
const apps: InstalledAppInfo[] = [];
- const lines = output.split('\n');
+ const lines = output.split("\n");
for (const line of lines) {
- const match = line.trim().match(/^(\S+)\/\S+,\S+\s+(\S+)\s+(\S+)\s+\[(.+)\]$/);
+ const match = line
+ .trim()
+ .match(/^(\S+)\/\S+,\S+\s+(\S+)\s+(\S+)\s+\[(.+)\]$/);
if (match) {
apps.push({
pkgname: match[1],
@@ -312,23 +339,23 @@ const parseInstalledList = (output: string) => {
---
-## 🌐 API Integration
+## 🌐 API 集成
-### Base Configuration
+### 基础配置
-```typescript
+````typescript
// src/global/storeConfig.ts
export const APM_STORE_BASE_URL = 'https://erotica.spark-app.store';
-// URL structure:
-// /{arch}/{category}/applist.json - App list
-// /{arch}/{category}/{pkgname}/icon.png - App icon
-// /{arch}/{category}/{pkgname}/screen_N.png - Screenshots (1-5)
-// /{arch}/categories.json - Categories mapping
+// URL 结构:
+// /{arch}/{category}/applist.json - 应用列表
+// /{arch}/{category}/{pkgname}/icon.png - 应用图标
+// /{arch}/{category}/{pkgname}/screen_N.png - 截图 (1-5)
+// /{arch}/categories.json - 分类映射
-### Home (主页) 页面数据
+### 首页 (主页) 数据
-The store may provide a special `home` directory under `{arch}` for a localized homepage. Two JSON files are expected:
+商店可能会在 `{arch}` 下提供一个特殊的 `home` 目录用于本地化首页。预期有两个 JSON 文件:
- `homelinks.json` — 用于构建首页的轮播或链接块。每个条目示例:
@@ -340,49 +367,58 @@ The store may provide a special `home` directory under `{arch}` for a localized
"type": "_blank",
"url": "https://bbs.spark-app.store/"
}
-```
+````
-- `homelist.json` — 描述若干推荐应用列表,每项引用一个 JSON 列表(`jsonUrl`):
+- `homelist.json` — 描述若干推荐应用列表,每项引用一个 JSON 列表(`jsonUrl`):
```json
[
- { "name":"装机必备", "type":"appList", "jsonUrl":"/home/lists/NecessaryforInstallation.json" }
+ {
+ "name": "装机必备",
+ "type": "appList",
+ "jsonUrl": "/home/lists/NecessaryforInstallation.json"
+ }
]
```
-Parsing rules used by the app:
-- Resolve `imgUrl` by prefixing: `${APM_STORE_BASE_URL}/{arch}${imgUrl}`.
+应用使用的解析规则:
+
+- 通过前缀解析 `imgUrl`: `${APM_STORE_BASE_URL}/{arch}${imgUrl}`。
- `type: _blank` → 使用系统浏览器打开链接;`type: _self` → 在当前页面打开。
-- For `homelist.json` entries with `type: "appList"`, fetch the referenced `jsonUrl` and map each item to the app shape used by the UI:
+- 对于 `homelist.json` 中 `type: "appList"` 的条目,获取引用的 `jsonUrl` 并将每个项映射到 UI 使用的应用形状:
- `Name` → `name`
- `Pkgname` → `pkgname`
- `Category` → `category`
- `More` → `more`
-Where to implement:
-- Renderer: `src/App.vue` loads and normalizes `homelinks.json` and `homelist.json` on selecting the `home` category and exposes data to a new `HomeView` component.
-- Component: `src/components/HomeView.vue` renders link cards and recommended app sections (re-uses `AppCard.vue`).
+实现位置:
-Notes:
-- The `home` directory path is: `/{arch}/home/` under the configured `APM_STORE_BASE_URL`.
-- Missing or partially invalid files are handled gracefully — individual failures don't block showing other home sections.
-```
+- 渲染进程: `src/App.vue` 在选择 `home` 分类时加载并规范化 `homelinks.json` 和 `homelist.json`,并将数据暴露给新的 `HomeView` 组件。
+- 组件: `src/components/HomeView.vue` 渲染链接卡片和推荐应用部分(复用 `AppCard.vue`)。
-### Axios Usage
+注意事项:
+
+- `home` 目录路径是: 配置的 `APM_STORE_BASE_URL` 下的 `/{arch}/home/`。
+- 缺失或部分无效的文件会被优雅地处理 — 个别失败不会阻止显示其他首页部分。
+
+````
+
+### Axios 使用
```typescript
const axiosInstance = axios.create({
baseURL: APM_STORE_BASE_URL,
- timeout: 1000, // Note: Very short timeout!
+ timeout: 1000, // 注意: 非常短的超时时间!
});
-// Loading apps by category
+// 按分类加载应用
const response = await axiosInstance.get(
`/${window.apm_store.arch}/${category}/applist.json`
);
-```
+````
+
+**开发代理 (vite.config.ts):**
-**Development Proxy (vite.config.ts):**
```typescript
server: {
proxy: {
@@ -397,373 +433,399 @@ server: {
---
-## 🎯 Deep Link Protocol (SPK URI Scheme)
+## 🎯 Deep Link 协议 (SPK URI Scheme)
**URL Scheme:** `spk://`
-### Supported SPK URI Format
+### 支持的 SPK URI 格式
-Format: `spk://search/{pkgname}`
+格式: `spk://search/{pkgname}`
-**Examples:**
-- `spk://search/code` - Search for and open "code" app
-- `spk://search/steam` - Search for and open "steam" app
-- `spk://search/store.spark-app.hmcl` - Search for and open "HMCL" game
+**示例:**
-### Implementation Pattern
+- `spk://search/code` - 搜索并打开 "code" 应用
+- `spk://search/steam` - 搜索并打开 "steam" 应用
+- `spk://search/store.spark-app.hmcl` - 搜索并打开 "HMCL" 游戏
+
+### 实现模式
```typescript
-// electron/main/deeplink.ts - Parse command line and route
+// electron/main/deeplink.ts - 解析命令行并路由
export function handleCommandLine(commandLine: string[]) {
- const deeplinkUrl = commandLine.find((arg) =>
- arg.startsWith('spk://')
- );
+ const deeplinkUrl = commandLine.find((arg) => arg.startsWith("spk://"));
if (!deeplinkUrl) return;
try {
const url = new URL(deeplinkUrl);
const action = url.hostname; // 'search'
- if (action === 'search') {
- // Format: spk://search/pkgname
- // url.pathname will be '/pkgname'
- const pkgname = url.pathname.split('/').filter(Boolean)[0];
+ if (action === "search") {
+ // 格式: spk://search/pkgname
+ // url.pathname 将是 '/pkgname'
+ const pkgname = url.pathname.split("/").filter(Boolean)[0];
if (pkgname) {
- listeners.emit('search', { pkgname });
+ listeners.emit("search", { pkgname });
}
}
} catch (error) {
- logger.error({ err: error }, 'Error parsing SPK URI');
+ logger.error({ err: error }, "Error parsing SPK URI");
}
}
-// src/App.vue - Handle in renderer
+// src/App.vue - 在渲染进程中处理
window.ipcRenderer.on(
- 'deep-link-search',
+ "deep-link-search",
(_event: IpcRendererEvent, data: { pkgname: string }) => {
- // Trigger search with the pkgname
+ // 使用 pkgname 触发搜索
searchQuery.value = data.pkgname;
- }
+ },
);
```
---
-## 🛡️ Security Considerations
+## 🛡️ 安全考虑
-### Privilege Escalation
+### 权限提升
-**Always check for `pkexec` availability:**
+**始终检查 `pkexec` 的可用性:**
```typescript
const checkSuperUserCommand = async (): Promise => {
if (process.getuid && process.getuid() !== 0) {
- const { stdout } = await execAsync('which /usr/bin/pkexec');
- return stdout.trim().length > 0 ? '/usr/bin/pkexec' : '';
+ const { stdout } = await execAsync("which /usr/bin/pkexec");
+ return stdout.trim().length > 0 ? "/usr/bin/pkexec" : "";
}
- return '';
+ return "";
};
```
-### Context Isolation
+### 上下文隔离
-**Current Status:** Context isolation is **enabled** (default Electron behavior).
+**当前状态:** 上下文隔离已 **启用** (Electron 默认行为)。
+
+**通过 Preload 安全地暴露 IPC:**
-**IPC Exposed via Preload (Safe):**
```typescript
// electron/preload/index.ts
-contextBridge.exposeInMainWorld('ipcRenderer', {
+contextBridge.exposeInMainWorld("ipcRenderer", {
on: (...args) => ipcRenderer.on(...args),
send: (...args) => ipcRenderer.send(...args),
invoke: (...args) => ipcRenderer.invoke(...args),
});
```
-**⚠️ Do NOT enable nodeIntegration or disable contextIsolation!**
+**⚠️ 不要启用 nodeIntegration 或禁用 contextIsolation!**
---
-## 🎨 UI/UX Patterns
+## 🎨 UI/UX 模式
-### Tailwind CSS Usage
+### Tailwind CSS 使用
+
+**暗色模式支持:**
-**Dark Mode Support:**
```vue
-
+
```
-**Theme Toggle:**
+**主题切换:**
+
```typescript
const isDarkTheme = ref(false);
watch(isDarkTheme, (newVal) => {
- localStorage.setItem('theme', newVal ? 'dark' : 'light');
- document.documentElement.classList.toggle('dark', newVal);
+ localStorage.setItem("theme", newVal ? "dark" : "light");
+ document.documentElement.classList.toggle("dark", newVal);
});
```
-### Modal Pattern
+### 模态框模式
```vue
```
-### Loading States
+### 加载状态
```typescript
const loading = ref(true);
-// In template
+// 在模板中
Loading...
{{ apps.length }} apps
```
---
-## 🧪 Testing & Quality
+## 🧪 测试与质量
-### ESLint Configuration
+### ESLint 配置
```typescript
// eslint.config.ts
export default defineConfig([
- globalIgnores(['**/3rdparty/**', '**/node_modules/**', '**/dist/**', '**/dist-electron/**']),
+ globalIgnores([
+ "**/3rdparty/**",
+ "**/node_modules/**",
+ "**/dist/**",
+ "**/dist-electron/**",
+ ]),
tseslint.configs.recommended,
- pluginVue.configs['flat/essential'],
+ pluginVue.configs["flat/essential"],
eslintConfigPrettier,
eslintPluginPrettierRecommended,
]);
```
-### TypeScript Configuration
+### TypeScript 配置
```json
{
"compilerOptions": {
- "strict": true, // Strict mode enabled
- "noEmit": true, // No emit (Vite handles build)
+ "strict": true, // 严格模式已启用
+ "noEmit": true, // 不输出 (Vite 处理构建)
"module": "ESNext",
"target": "ESNext",
- "jsx": "preserve", // Vue JSX
- "resolveJsonModule": true // Import JSON files
+ "jsx": "preserve", // Vue JSX
+ "resolveJsonModule": true // 导入 JSON 文件
}
}
```
-### Code Quality Commands
+### 代码质量命令
```bash
-npm run lint # Run ESLint
-npm run lint:fix # Auto-fix issues
-npm run format # Format with Prettier
+npm run lint # 运行 ESLint
+npm run lint:fix # 自动修复问题
+npm run format # 使用 Prettier 格式化
```
---
-## 🚀 Build & Development
+## 🚀 构建与开发
-### Development Mode
+### 开发模式
```bash
-npm run dev # Start dev server (Vite + Electron)
+npm run dev # 启动开发服务器 (Vite + Electron)
```
-**Dev Server:** `http://127.0.0.1:3344/` (port from package.json)
+**开发服务器:** `http://127.0.0.1:3344/` (来自 package.json)
-### Production Build
+### 生产构建
```bash
-npm run build # Build all (deb + rpm)
-npm run build:deb # Build Debian package only
-npm run build:rpm # Build RPM package only
+npm run build # 构建所有 (deb + rpm)
+npm run build:deb # 仅构建 Debian 包
+npm run build:rpm # 仅构建 RPM 包
```
-**Build Output:**
-- `dist-electron/` - Compiled Electron code
-- `dist/` - Compiled renderer assets
-- Packaged app in project root
+**构建输出:**
-### Build Configuration
+- `dist-electron/` - 编译的 Electron 代码
+- `dist/` - 编译的渲染器资源
+- 打包的应用在项目根目录
+
+### 构建配置
**electron-builder.yml:**
+
- App ID: `cn.eu.org.simplelinux.apmstore`
-- Linux targets: deb, rpm
-- Includes extras/ directory in resources
-- Auto-update disabled (Linux package manager handles updates)
+- Linux 目标: deb, rpm
+- 包含 extras/ 目录在资源中
+- 自动更新禁用 (Linux 包管理器处理更新)
---
-## 📦 Important Files to Understand
+## 📦 重要文件说明
### 1. electron/main/backend/install-manager.ts
-**Purpose:** Core package management logic
-**Key Responsibilities:**
-- Task queue management
-- APM command spawning
-- Progress reporting
-- Installed/upgradable list parsing
-**Critical Functions:**
-- `processNextInQueue()` - Task processor
-- `parseInstalledList()` - Parse APM output
-- `checkSuperUserCommand()` - Privilege escalation
+**用途:** 核心包管理逻辑
+**主要职责:**
+
+- 任务队列管理
+- APM 命令生成
+- 进度报告
+- 已安装/可升级列表解析
+
+**关键函数:**
+
+- `processNextInQueue()` - 任务处理器
+- `parseInstalledList()` - 解析 APM 输出
+- `checkSuperUserCommand()` - 权限提升
### 2. src/App.vue
-**Purpose:** Root component
-**Key Responsibilities:**
-- App state management
-- Category/app loading
-- Modal orchestration
-- Deep link handling
+
+**用途:** 根组件
+**主要职责:**
+
+- 应用状态管理
+- 分类/应用加载
+- 模态框协调
+- Deep Link 处理
### 3. src/global/downloadStatus.ts
-**Purpose:** Download queue state
-**Key Features:**
-- Reactive download list
-- Download item CRUD operations
-- Change watchers for UI updates
+
+**用途:** 下载队列状态
+**关键特性:**
+
+- 响应式下载列表
+- 下载项 CRUD 操作
+- UI 更新的变化监听器
### 4. electron/preload/index.ts
-**Purpose:** Renderer-Main bridge
-**Key Features:**
-- IPC API exposure
-- Architecture detection
-- Loading animation
+
+**用途:** 渲染进程-主进程桥梁
+**关键特性:**
+
+- IPC API 暴露
+- 架构检测
+- 加载动画
### 5. vite.config.ts
-**Purpose:** Build configuration
-**Key Features:**
-- Electron plugin setup
-- Dev server proxy
-- Tailwind integration
+
+**用途:** 构建配置
+**关键特性:**
+
+- Electron 插件设置
+- 开发服务器代理
+- Tailwind 集成
---
-## 🐛 Common Pitfalls & Solutions
+## 🐛 常见陷阱与解决方案
-### 1. Duplicate Task Handling
+### 1. 重复任务处理
+
+**问题:** 用户多次点击安装
+**解决方案:**
-**Problem:** User clicks install multiple times
-**Solution:**
```typescript
if (tasks.has(id) && !download.retry) {
- logger.warn('Task already exists, ignoring duplicate');
+ logger.warn("Task already exists, ignoring duplicate");
return;
}
```
-### 2. Window Close Behavior
+### 2. 窗口关闭行为
+
+**问题:** 任务运行时关闭窗口
+**解决方案:**
-**Problem:** Closing window while tasks are running
-**Solution:**
```typescript
-win.on('close', (event) => {
+win.on("close", (event) => {
event.preventDefault();
if (tasks.size > 0) {
- win.hide(); // Hide instead of closing
+ win.hide(); // 隐藏而不是关闭
win.setSkipTaskbar(true);
} else {
- win.destroy(); // Allow close if no tasks
+ win.destroy(); // 没有任务时允许关闭
}
});
```
-### 3. App Data Normalization
+### 3. 应用数据规范化
+
+**问题:** API 返回 PascalCase,应用使用 camelCase
+**解决方案:**
-**Problem:** API returns PascalCase, app uses camelCase
-**Solution:**
```typescript
const normalizedApp: App = {
name: appJson.Name,
pkgname: appJson.Pkgname,
version: appJson.Version,
- // ... map all fields
+ // ... 映射所有字段
};
```
-### 4. Screenshot Loading
+### 4. 截图加载
+
+**问题:** 并非所有应用都有 5 张截图
+**解决方案:**
-**Problem:** Not all apps have 5 screenshots
-**Solution:**
```typescript
for (let i = 1; i <= 5; i++) {
const img = new Image();
img.src = screenshotUrl;
img.onload = () => screenshots.value.push(screenshotUrl);
- // No onerror handler - silently skip missing images
+ // 没有 onerror 处理器 - 静默跳过缺失的图片
}
```
---
-## 📚 Logging Best Practices
+## 📚 日志最佳实践
-### Pino Logger Usage
+### Pino Logger 使用
```typescript
-import pino from 'pino';
-const logger = pino({ name: 'module-name' });
+import pino from "pino";
+const logger = pino({ name: "module-name" });
-// Levels: trace, debug, info, warn, error, fatal
-logger.info('Application started');
-logger.error({ err }, 'Failed to load apps');
+// 级别: trace, debug, info, warn, error, fatal
+logger.info("Application started");
+logger.error({ err }, "Failed to load apps");
logger.warn(`Package ${pkgname} not found`);
```
-### Log Locations
+### 日志位置
-**Development:** Console with `pino-pretty`
-**Production:** Structured JSON to stdout
+**开发:** 控制台使用 `pino-pretty`
+**生产:** 结构化 JSON 到 stdout
---
-## 🔄 State Management
+## 🔄 状态管理
-### Global State (src/global/storeConfig.ts)
+### 全局状态 (src/global/storeConfig.ts)
```typescript
export const currentApp = ref(null);
export const currentAppIsInstalled = ref(false);
```
-**Usage Pattern:**
-```typescript
-import { currentApp, currentAppIsInstalled } from '@/global/storeConfig';
+**使用模式:**
-// Set current app
+```typescript
+import { currentApp, currentAppIsInstalled } from "@/global/storeConfig";
+
+// 设置当前应用
currentApp.value = selectedApp;
-// Check installation status
-window.ipcRenderer.invoke('check-installed', app.pkgname)
+// 检查安装状态
+window.ipcRenderer
+ .invoke("check-installed", app.pkgname)
.then((isInstalled: boolean) => {
currentAppIsInstalled.value = isInstalled;
});
```
-### Download Queue (src/global/downloadStatus.ts)
+### 下载队列 (src/global/downloadStatus.ts)
```typescript
export const downloads = ref([]);
-// Add download
+// 添加下载
downloads.value.push(newDownload);
-// Remove download
+// 移除下载
export const removeDownloadItem = (pkgname: string) => {
- const index = downloads.value.findIndex(d => d.pkgname === pkgname);
+ const index = downloads.value.findIndex((d) => d.pkgname === pkgname);
if (index !== -1) downloads.value.splice(index, 1);
};
-// Watch changes
+// 监听变化
export const watchDownloadsChange = (callback: () => void) => {
watch(downloads, callback, { deep: true });
};
@@ -771,124 +833,130 @@ export const watchDownloadsChange = (callback: () => void) => {
---
-## 🎯 Contribution Guidelines
+## 🎯 贡献指南
-### When Adding New Features
+### 添加新功能时
-1. **Add TypeScript types first** (src/global/typedefinition.ts)
-2. **Update IPC handlers** if main-renderer communication needed
-3. **Follow existing component patterns** (props, emits, setup)
-4. **Test with actual APM commands** (don't mock in development)
-5. **Update README TODO list** when completing tasks
+1. **首先添加 TypeScript 类型** (src/global/typedefinition.ts)
+2. **更新 IPC 处理器** (如果需要主进程-渲染进程通信)
+3. **遵循现有组件模式** (props, emits, setup)
+4. **使用实际的 APM 命令测试** (不要在开发中使用 mock)
+5. **完成任务时更新 README TODO 列表**
-### Code Style
+### 代码风格
-- **Use TypeScript strict mode** - no `any` types without `eslint-disable`
-- **Avoid used of eslint-disable directly** - use `undefined` instead if you really do not know its type.
-- **Prefer Composition API** - `