213 lines
11 KiB
Markdown
213 lines
11 KiB
Markdown
# 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`
|
||
|
||
```text
|
||
仓库: 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.2`
|
||
- `tdesign-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`
|
||
|
||
这是通用插件控制面,不是订阅业务页面。现有职责应拆成以下路由:
|
||
|
||
```text
|
||
#/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` |
|
||
|
||
现有接口保持不变:
|
||
|
||
```text
|
||
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 和管理员权限,不再出现第二个登录页。模块后端可以继续作为独立进程运行,但浏览器只访问控制面提供的同源模块路由。
|
||
|
||
```text
|
||
#/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 控制面,并把订阅前端作为可挂载模块构建:
|
||
|
||
```text
|
||
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. 不可改变的系统边界
|
||
|
||
```text
|
||
浏览器
|
||
↓ 一次登录: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/:id` iframe 注入方式保持不变。
|
||
- Plugin Admin 的配置 iframe `postMessage` bridge、`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. 主要风险与处理
|
||
|
||
1. **starter 自带 mock/示例权限**:全部删除,改为 Plugin Admin 会话和管理员权限;不把 starter 的演示用户带入生产。
|
||
2. **旧 UI 是原生 HTML/JS**:不要强行在同一页面混用原生模板和 TDesign;按应用整体迁移,减少样式优先级冲突。
|
||
3. **配置 iframe bridge**:只能替换外层视觉,消息名称、token、来源校验、超时和 step-up 语义不变。
|
||
4. **表格移动端**:使用固定列/可滚动列的明确容器,禁止给 `body` 或整个页面设置横向滚动。
|
||
5. **图标包选择**:统一 `tdesign-icons-vue-next`;它提供线性图标,不再额外引入未知的 `line-icons` 包。
|
||
6. **模块登录分裂**:订阅模块不得复制登录页、Cookie 或权限判断;模块调用统一控制面 BFF,由控制面把管理员身份传给订阅服务。
|
||
7. **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 边界。
|