diff --git a/superpowers/plans/2026-06-07-sysapp-management-plan.md b/superpowers/plans/2026-06-07-sysapp-management-plan.md new file mode 100644 index 0000000..1b445db --- /dev/null +++ b/superpowers/plans/2026-06-07-sysapp-management-plan.md @@ -0,0 +1,961 @@ +# SysApp(第三方应用集成)管理界面实施计划 + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers-subagent-driven-development (recommended) or superpowers-executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 在 admin-ui 后台实现 SysApp(第三方应用集成)管理模块,提供对微信/支付宝/Stripe 等第三方平台应用凭证信息的统一管理能力。 + +**Architecture:** 完全照搬现有 `oauth2-client` 模块的 CRUD 模式 —— `BaseService` 13 行极简继承 + `RuiTable` 列表页 + `FormDialog` 弹窗(el-tabs 4 Tab)。**不引入新依赖**。 + +**Tech Stack:** Vue 3, TypeScript, Element Plus, Vite, Pinia + +--- + +## 文件变更清单 + +| # | 文件 | 变更类型 | 说明 | +|---|------|---------|------| +| 1 | `admin-ui/src/service/system/sysAppService.ts` | 新建 | Service(继承 BaseService) | +| 2 | `admin-ui/src/service/system/index.ts` | 修改 | 追加导出 sysAppService | +| 3 | `admin-ui/src/locales/zh-CN.ts` | 修改 | 加 `systemApp: '应用集成'` | +| 4 | `admin-ui/src/locales/en-US.ts` | 修改 | 加 `systemApp: 'App Integration'` | +| 5 | `admin-ui/src/router/modules/system.ts` | 修改 | 注册 `/system/app` 路由 | +| 6 | `admin-ui/src/views/system/app/Index.vue` | 新建 | 列表页(RuiTable) | +| 7 | `admin-ui/src/views/system/app/SysAppFormDialog.vue` | 新建 | 表单弹窗(4 Tab) | + +**合计:新建 3 个文件 + 修改 4 个文件 = 7 个文件** + +--- + +## 任务依赖图 + +``` +Task 1 (Service) ──┬── Task 2 (Service Index) + │ + ├── Task 5 (列表页) ──┐ + │ │ + └── Task 6 (表单) ────┴── Task 7 (端到端验证) + +Task 3 (i18n) ──┐ +Task 4 (Router) ┴── Task 5 (列表页) +``` + +--- + +## Task 1: 创建 SysApp Service + +**Files:** +- Create: `admin-ui/src/service/system/sysAppService.ts` + +- [ ] **Step 1: 写入 Service 文件** + +在 `admin-ui/src/service/system/sysAppService.ts` 创建: + +```typescript +import { BaseService } from '../BaseService' + +/** + * SysApp(第三方应用集成)服务 + * + *

负责与后端 /system/admin/app 接口的通信,继承 BaseService 获得标准 CRUD 能力。

+ * + *

后续升级路径:后端文件上传接口(rui/rui-framework#4)就绪后,可在此文件追加 + * `uploadCertificate(file: File)` 方法,并将表单中 certificates 字段从 JSON textarea + * 升级为文件上传组件。

+ */ +class SysAppService extends BaseService { + constructor() { + super('/system/admin/app') + } +} + +/** SysApp 服务单例 */ +export const sysAppService = new SysAppService() +``` + +- [ ] **Step 2: 验证类型检查** + +Run: +```bash +cd admin-ui && npx vue-tsc --noEmit --skipLibCheck src/service/system/sysAppService.ts +``` +Expected: 无错误输出 + +- [ ] **Step 3: Commit** + +```bash +git add admin-ui/src/service/system/sysAppService.ts +git commit -m "feat(sysApp): add sysAppService extending BaseService for /system/admin/app" +``` + +--- + +## Task 2: 在 Service 统一入口导出 sysAppService + +**Files:** +- Modify: `admin-ui/src/service/system/index.ts` + +- [ ] **Step 1: 追加导出语句** + +在文件末尾追加: + +```typescript +export { sysAppService } from './sysAppService' +``` + +- [ ] **Step 2: 验证导入** + +Run: +```bash +cd admin-ui && npx vue-tsc --noEmit --skipLibCheck src/service/system/index.ts +``` +Expected: 无错误输出 + +- [ ] **Step 3: Commit** + +```bash +git add admin-ui/src/service/system/index.ts +git commit -m "feat(sysApp): export sysAppService from system service index" +``` + +--- + +## Task 3: 配置国际化(中英文) + +**Files:** +- Modify: `admin-ui/src/locales/zh-CN.ts` +- Modify: `admin-ui/src/locales/en-US.ts` + +- [ ] **Step 1: 在 zh-CN.ts 添加中文** + +定位到 `systemOAuth2Client: 'OAuth2客户端',` 这一行,在其后添加: + +```typescript + systemApp: '应用集成', +``` + +(注意缩进:与 systemOAuth2Client 保持一致的 4 空格) + +- [ ] **Step 2: 在 en-US.ts 添加英文** + +定位到 `systemOAuth2Client: 'OAuth2 Client',`(或对应位置),在其后添加: + +```typescript + systemApp: 'App Integration', +``` + +(如果 en-US.ts 没有 systemOAuth2Client 这一行,则加在 system 块的合理位置,参考 systemOAuth2Client 的就近位置) + +- [ ] **Step 3: 验证** + +Run: +```bash +grep -n "systemApp" admin-ui/src/locales/zh-CN.ts admin-ui/src/locales/en-US.ts +``` +Expected: 两个文件各有一行匹配 + +- [ ] **Step 4: Commit** + +```bash +git add admin-ui/src/locales/zh-CN.ts admin-ui/src/locales/en-US.ts +git commit -m "feat(sysApp): add systemApp i18n key (zh-CN: '应用集成', en-US: 'App Integration')" +``` + +--- + +## Task 4: 注册路由 + +**Files:** +- Modify: `admin-ui/src/router/modules/system.ts` + +- [ ] **Step 1: 在 M 常量加键** + +定位到 `systemOAuth2Client: 'menu.systemOAuth2Client',` 这一行,在其后添加: + +```typescript + systemApp: 'menu.systemApp', +``` + +- [ ] **Step 2: 在 systemRoutes 数组加路由** + +定位到 `system/oauth2-client` 路由条目,在其后添加: + +```typescript + { path: 'system/app', name: 'SystemApp', component: () => import('@/views/system/app/Index.vue'), meta: { i18n: M.systemApp } }, +``` + +- [ ] **Step 3: 验证** + +Run: +```bash +grep -n "systemApp\|system/app" admin-ui/src/router/modules/system.ts +``` +Expected: 至少 2 行匹配(一个 M 常量,一个 systemRoutes 数组) + +- [ ] **Step 4: Commit** + +```bash +git add admin-ui/src/router/modules/system.ts +git commit -m "feat(sysApp): register /system/app route in system router" +``` + +--- + +## Task 5: 创建列表页 + +**Files:** +- Create: `admin-ui/src/views/system/app/Index.vue` + +> **依赖**:Task 1(Service)、Task 3(i18n)、Task 4(Router)必须先完成。 + +- [ ] **Step 1: 创建目录** + +```bash +mkdir -p admin-ui/src/views/system/app +``` + +- [ ] **Step 2: 写入列表页** + +创建 `admin-ui/src/views/system/app/Index.vue`,内容如下: + +```vue + + + +``` + +- [ ] **Step 3: 验证类型检查** + +Run: +```bash +cd admin-ui && npx vue-tsc --noEmit --skipLibCheck +``` +Expected: 无错误输出 + +- [ ] **Step 4: Commit** + +```bash +git add admin-ui/src/views/system/app/Index.vue +git commit -m "feat(sysApp): add SysApp list page with RuiTable, search, status switch" +``` + +--- + +## Task 6: 创建表单弹窗 + +**Files:** +- Create: `admin-ui/src/views/system/app/SysAppFormDialog.vue` + +> **依赖**:Task 1(Service)必须先完成。 + +- [ ] **Step 1: 写入表单弹窗** + +创建 `admin-ui/src/views/system/app/SysAppFormDialog.vue`,内容如下: + +```vue + + + +``` + +- [ ] **Step 2: 验证类型检查** + +Run: +```bash +cd admin-ui && npx vue-tsc --noEmit --skipLibCheck +``` +Expected: 无错误输出 + +- [ ] **Step 3: Commit** + +```bash +git add admin-ui/src/views/system/app/SysAppFormDialog.vue +git commit -m "feat(sysApp): add SysApp form dialog with 4 tabs (basic/credentials/api/advanced)" +``` + +--- + +## Task 7: 端到端验证 + +**Files:** 无(验证任务) + +> **依赖**:所有前置任务(Task 1-6)已完成。 + +- [ ] **Step 1: 运行类型检查** + +Run: +```bash +pnpm --filter admin-ui type-check +``` +Expected: 0 errors + +- [ ] **Step 2: 运行 Lint** + +Run: +```bash +pnpm --filter admin-ui lint +``` +Expected: 0 errors + +- [ ] **Step 3: 启动 dev server 并验证** + +```bash +pnpm dev:admin +``` + +打开浏览器,登录后访问 `/system/app`,逐条验证: + +- [ ] **Step 3.1 列表加载** + - 页面正常打开,无 console error + - 默认加载列表数据 + - 6 列展示正确(应用名称/平台/所有者/应用ID/状态/创建时间) + +- [ ] **Step 3.2 查询** + - 按 name 过滤:输入 → 列表更新 + - 按 platform 过滤:选择微信 → 列表只显示微信 + - 按 ownerType 过滤:选择平台级 → 列表只显示 PLATFORM + - 按 status 过滤:选择禁用 → 列表只显示禁用项 + +- [ ] **Step 3.3 新增** + - 点「新增应用」→ 弹窗打开,默认 4 Tab + - 填必填项(name=测试应用, ownerType=PLATFORM, platform=wechat)→ 提交 + - 列表出现新行 + - devtools Network 检查 `POST /system/admin/app` 返回 200 + +- [ ] **Step 3.4 编辑** + - 点行内编辑 → 弹窗加载详情 + - 4 个 Tab 正确回显 + - 修改 name → 提交 → 列表更新 + +- [ ] **Step 3.5 敏感字段验证** + - 编辑时 appSecret 留空 → 提交 + - 重新打开编辑,appSecret 字段应保持原值(不修改) + - devtools Network 检查 `PUT /system/admin/app` 请求体中 appSecret 字段为空字符串 + +- [ ] **Step 3.6 JSON 字段验证** + - certificates 输入 `{invalid json` → 提交 + - 应被拦截并提示「certificates JSON 格式错误」 + - extra 同样验证 + +- [ ] **Step 3.7 启停** + - 点击状态 Switch → 接口调用 → 列表状态切换 + - 模拟失败:可在 devtools 拦截请求,验证 row.status 回滚 + +- [ ] **Step 3.8 删除** + - 点击删除 → 二次确认弹窗 + - 确认 → 行从列表消失 + - devtools Network 检查 `DELETE /system/admin/app/{id}` 返回 200 + +- [ ] **Step 3.9 批量删除** + - 勾选 2-3 行 → 批量删除按钮(toolbar)→ 确认 → 全部消失 + +- [ ] **Step 3.10 导出** + - 点击导出 → 下载 CSV 文件 + - 文件名包含日期 + - 字段对应列表列 + +- [ ] **Step 3.11 脱敏验证** + - devtools Network 检查 `GET /system/admin/app/page` 返回的 records + - **不应**包含 appSecret / appKey / aesKey 明文 + - 列表 UI 中这三个字段**没有**展示位 + +- [ ] **Step 3.12 菜单展示** + - 侧边栏「系统管理」分组下出现「应用集成」子菜单 + - 点击跳转 `/system/app` + - 中文/英文切换均正常 + +- [ ] **Step 4: 验证 git log** + +Run: +```bash +git log --oneline -10 +``` +Expected: 看到 6 个提交: +- feat(sysApp): add sysAppService extending BaseService +- feat(sysApp): export sysAppService from system service index +- feat(sysApp): add systemApp i18n key +- feat(sysApp): register /system/app route in system router +- feat(sysApp): add SysApp list page +- feat(sysApp): add SysApp form dialog + +--- + +## 回滚计划 + +如果出现问题,按以下顺序回滚: + +1. 回滚 Task 6: `git revert `(删除表单) +2. 回滚 Task 5: `git revert `(删除列表页) +3. 回滚 Task 4: `git revert `(取消路由) +4. 回滚 Task 3: `git revert `(删除 i18n) +5. 回滚 Task 2: `git revert `(取消导出) +6. 回滚 Task 1: `git revert `(删除 Service) + +如需完全回滚:`git reset --hard ` + +--- + +## 测试清单 + +### 静态检查 +- [ ] `pnpm --filter admin-ui type-check` 0 errors +- [ ] `pnpm --filter admin-ui lint` 0 errors + +### 列表功能 +- [ ] 列表加载正常 +- [ ] 4 个查询条件均生效 +- [ ] 分页正常 +- [ ] 列设置可隐藏/显示列 +- [ ] 导出 CSV 成功 + +### 表单功能 +- [ ] 新增:填写必填项 → 提交 → 列表出现新行 +- [ ] 编辑:弹窗加载详情 → 修改 → 提交 → 列表更新 +- [ ] 必填校验:name/ownerType/platform 未填时拦截 +- [ ] JSON 校验:certificates/extra 非法格式拦截 +- [ ] 敏感字段:appSecret/appKey/aesKey 留空不修改 + +### 交互 +- [ ] 启停:状态 Switch 切换正常,失败时回滚 +- [ ] 单删:删除确认 → 行消失 +- [ ] 批删:选中多行 → 批量删除 → 全部消失 +- [ ] 弹窗:宽度 760px,4 Tab 可切换 + +### 菜单与导航 +- [ ] 侧边栏「系统管理 → 应用集成」菜单显示 +- [ ] 路由跳转正常 +- [ ] 中英文 i18n 切换正常 + +### 脱敏 +- [ ] 列表中无任何明文密钥字段 +- [ ] 列表接口返回的 records 不含 appSecret/appKey/aesKey 明文 + +--- + +## 关联信息 + +- **Spec 文档**: `docs/superpowers/specs/2026-06-07-sysapp-management-design.md` +- **工单**: rui/rui-frontend#4 +- **后端 Issue**: rui/rui-framework#4(文件上传接口依赖,本期不阻塞) +- **参考实现**: `admin-ui/src/views/system/oauth2-client/Index.vue` + `OAuth2ClientFormDialog.vue` + +--- + +**计划状态**: 待评审 +**下一步**: 用户评审通过后,使用 `superpowers-subagent-driven-development` 或 `superpowers-executing-plans` 执行