11 KiB
TDesign 插件前端重构评估
1. 范围与结论
本次只重构独立插件仓库的前端,不修改官方 Sub2API Core 的 Go、Vue、迁移、鉴权或构建配置。
独立插件仓库当前工作目录:/tmp/sub2api-add-repo.pzrg17
官方 Core 当前工作目录:/Users/qiu/Desktop/Sub2API
建议把 TDesign starter 作为统一插件控制面的 UI 基座,而不是把 starter 合并到 Core 的 frontend/。插件控制面只登录一次;订阅是安装后挂载到控制面里的业务模块,不是第二个后台系统。
2. Starter 基线
已拉取:/Users/qiu/Desktop/tdesign-vue-next-starter-v1
仓库: https://github.com/Tencent/tdesign-vue-next-starter
分支: develop
提交: d6f8fafad9c1596cac8dfac8d52a88d0ca692acc
版本: package.json 0.14.0
已确认的技术栈:
- Vue 3.5、TypeScript、Vite 8、Pinia 3、Vue Router 5
tdesign-vue-next^1.20.2tdesign-icons-vue-next^0.4.4- ECharts
^6.1.0 - Node.js
>=22.12.0
Starter 的基线构建已通过:npm ci --ignore-scripts、npm run build。
ECharts 已在 starter 的 src/hooks/index.ts 中通过 echarts/core 初始化。starter 没有 line-icons 或 lineicon 依赖;TDesign Icons 本身是线性图标风格,后续统一使用 tdesign-icons-vue-next,避免混用多个图标系统。
3. 当前插件页面清单
3.1 Plugin Admin
入口:plugins/plugin-admin/ui/index.html、plugins/plugin-admin/ui/app.js
这是通用插件控制面,不是订阅业务页面。现有职责应拆成以下路由:
#/overview
#/plugins
#/plugins/:plugin_id/overview
#/plugins/:plugin_id/revisions
#/plugins/:plugin_id/config
#/plugins/:plugin_id/menu
#/plugins/:plugin_id/operations
#/marketplace
#/operations
页面职责:
| 页面 | 主要内容 | TDesign 组件方向 |
|---|---|---|
| 登录 | Core 管理员账号登录、2FA、会话过期 | TForm、TInput、TButton、TAlert |
| 概览 | 已登记、运行中、待启用、需关注、最近操作 | TCard、TStatistic、TTag、TTimeline |
| 已安装插件 | 摘要列表、生命周期主操作、查看详情 | TTable 或响应式 TCard、TDropdown |
| 运行概况 | 健康、端点、兼容性、活动 revision | TDescriptions、TProgress、TTag |
| 版本与升级 | revision、校验、升级包、回滚 | TTable、TUpload、TDialog |
| 配置 | 服务地址、菜单地址、敏感配置提示 | TForm、TInput、TAlert |
| 菜单接入 | 菜单声明、预览、应用 | TDescriptions、TDialog、TButton |
| 操作历史 | 当前插件或全局审计记录、详情 | TTable、TDrawer、TTag |
| 插件市场 | 受控索引、版本、兼容性、哈希、入库 | TCard、TTag、TButton |
现有接口保持不变:
GET /api/plugins
POST /api/plugins/upload
POST /api/plugins/:id/enable
POST /api/plugins/:id/disable
POST /api/plugins/:id/test
POST /api/plugins/:id/ui-session
DELETE /api/plugins/:id
GET/PUT /api/plugins/:id/config
GET /api/marketplace
GET /api/audit
3.2 订阅业务模块
入口:plugins/subscription-admin/ui/index.html、plugins/subscription-admin/ui/app.js
订阅管理是可选业务模块,由 Plugin Admin 安装、启用和卸载。它复用控制面的登录态、导航、CSRF 和管理员权限,不再出现第二个登录页。模块后端可以继续作为独立进程运行,但浏览器只访问控制面提供的同源模块路由。
#/modules/subscription/overview
#/modules/subscription/plans
#/modules/subscription/subscriptions
#/modules/subscription/audit
页面职责:
| 页面 | 主要内容 | TDesign 组件方向 |
|---|---|---|
| 概览 | Core 连接状态、套餐数量、订阅数量、余额查询 | TStatistic、TCard、TAlert |
| 套餐 | Core 返回的套餐目录和覆盖分组 | TTable、TTag、TEmpty |
| 用户订阅 | 用户、状态、分组、服务端分页和筛选 | TForm、TSelect、TTable、TPagination |
| 操作记录 | 插件会话和只读查询审计 | TTable、TDrawer |
| 模块设置 | 运行模式、allowlist、凭据状态 | 插件详情的“配置/运行概况”页,不重复做模块登录 |
订阅模块现有 Core 代理接口、分页参数、状态枚举和只读边界不变。余额购买、续费、撤销等后续能力仍应通过模块后端 API 增量加入,不能在此次 UI 换肤时偷偷改变业务语义。
4. 推荐前端目录
不要复用官方 Core 的 frontend/ 目录。建议在独立插件仓库新增一个统一 TDesign 控制面,并把订阅前端作为可挂载模块构建:
plugins/
├── plugin-admin/
│ ├── ui/ # 统一 TDesign 应用、登录、导航和模块路由
│ └── ui-modules/ # 订阅等业务模块的 Vue/TS 源码
└── subscription-admin/
├── service/ # 可继续独立运行的业务后端
└── ui-module/ # 被 plugin-admin 挂载的订阅模块,不包含登录页
订阅模块可以独立打包和回滚,但它的浏览器入口由 Plugin Admin 统一托管。Go 的 embed、静态文件路径和部署脚本必须在插件仓库内同步,不与 Core 构建耦合。
共享但不跨 Core 的内容:
- TDesign 主题 token、字体、间距、移动端断点
- 请求封装、插件会话/CSRF、错误提示
- ECharts 按需注册和 resize composable
- TDesign Icons 的图标命名约定
5. 不可改变的系统边界
浏览器
↓ 一次登录:Plugin Admin Session Cookie + CSRF
统一 Plugin Admin TDesign Shell
├─ 插件管理页面
└─ 订阅业务模块路由
↓ 控制面同源 BFF / 内部服务调用
独立插件 Go 服务(订阅模块)
↓ 服务端 allowlist + Bearer Core token
官方 Sub2API Core REST API
- 浏览器不能拿到 Core access token、refresh token、Admin Key 或服务密钥。
- 所有模块前端只能使用统一控制面的会话和模块 API,不能直连 Core API、PostgreSQL 或 Redis。
- 订阅模块不得再实现
/login、独立 Cookie 或第二套管理员会话。 custom_menu_items和 Core/custom/:idiframe 注入方式保持不变。- Plugin Admin 的配置 iframe
postMessagebridge、ui-session、step-up 和来源校验保持不变。 - Core 的源码仓库、版本文件、数据库迁移和前端页面不在本次改动范围内。
6. 分阶段实施
阶段 A:基座复制与边界固定
从 starter 复制应用骨架,替换 demo 路由、mock 数据、示例登录和品牌资源;保留 TDesign Layout、主题切换、Pinia、Vue Router、ECharts 基础能力。先让统一控制面独立构建,并定义模块注册契约。
阶段 B:Plugin Admin
先完成登录和应用壳,再按“概览 → 已安装 → 详情页签 → 市场 → 审计”迁移。所有 mutation 仍由现有 Go endpoint 执行,前端只负责表单、状态和操作确认。
阶段 C:订阅业务模块
订阅 UI 作为控制面的一个模块挂载,复用同一套会话、导航、视觉 token 和错误处理。先迁移概览、套餐、订阅列表和操作记录,服务端分页/筛选参数保持原样。订阅后端是否独立进程不影响前端只有一次登录。
阶段 D:图表与响应式
只在概览和需要趋势的页面引入 ECharts;图表容器使用固定最小高度、resize observer 和按需导入,避免页面被超长 canvas 撑开。列表在移动端只允许表格容器横向滚动,页面主体不得横向溢出。
阶段 E:接入验收
验证统一控制面一次登录后进入插件管理和订阅模块、Core 菜单 iframe、会话过期、CSRF、管理员权限、插件启停、配置 bridge、市场入库和审计链路。确认官方 Core 工作区没有任何变更。
7. 主要风险与处理
- starter 自带 mock/示例权限:全部删除,改为 Plugin Admin 会话和管理员权限;不把 starter 的演示用户带入生产。
- 旧 UI 是原生 HTML/JS:不要强行在同一页面混用原生模板和 TDesign;按应用整体迁移,减少样式优先级冲突。
- 配置 iframe bridge:只能替换外层视觉,消息名称、token、来源校验、超时和 step-up 语义不变。
- 表格移动端:使用固定列/可滚动列的明确容器,禁止给
body或整个页面设置横向滚动。 - 图标包选择:统一
tdesign-icons-vue-next;它提供线性图标,不再额外引入未知的line-icons包。 - 模块登录分裂:订阅模块不得复制登录页、Cookie 或权限判断;模块调用统一控制面 BFF,由控制面把管理员身份传给订阅服务。
- Core 更新兼容性:插件只依赖已声明的 HTTP allowlist 和响应 DTO,Core 更新时只做 API 契约兼容检查。
8. 第一版验收标准
- 官方 Core
/Users/qiu/Desktop/Sub2API保持干净,版本和源码不被修改。 - 统一 Plugin Admin 前端能独立
npm run build,不依赖 Core 的 Vite 配置;订阅模块以模块产物或受控动态入口挂载。 - 管理员只登录一次即可访问插件控制面和已启用订阅模块;直接刷新模块路由仍保持同一插件会话,不把凭据写入 URL。
- 425px、768px、1440px 下无页面级横向溢出;表格需要横向查看时只滚动表格容器。
- 所有管理员 mutation 仍经过插件后端的会话、CSRF、step-up 和幂等校验。
- DOM、网络响应、日志和 URL 不出现 Core token、Admin Key、密码或服务密钥。
- ECharts 图表只展示有数据的系列,容器尺寸稳定,窗口变化后可重绘。
9. 当前状态
已完成:
- 拉取官方 TDesign Vue Next starter。
- 固定 starter 基线和依赖版本。
- 完成 starter 基线构建检查。
- 完成独立插件页面、API、组件和迁移边界评估。
- 根据反馈修正页面边界:订阅从“独立后台”改为统一插件控制面内的业务模块,不再单独登录。
已完成第一版落地:
plugins/plugin-admin/ui-vue基于 TDesign Vue Next starter 建立独立 Vue 3/Vite 应用。- Plugin Admin 登录、统一 Shell、概览、插件列表/详情、市场和审计页面已迁移,图标统一使用
tdesign-icons-vue-next,概览趋势图使用 ECharts。 - 订阅作为 Shell 内的
/modules/subscription/*业务模块挂载,不再渲染第二个登录页;控制面新增同源、allowlist 约束的订阅只读 BFF。 - Go 静态资源支持挂载路径、SPA 回退和路径穿越拒绝;
build-ui.sh负责可重复构建并复制嵌入产物。 - 已完成 TypeScript/Vite、Go 单元、API 契约和 425/900/1440 多视口浏览器验收;下一轮可继续补充真实业务写操作,但不改变 Core 边界。