# 前端技术对比：qmtv（Vue3）vs pms web（React18+AntD5）

LLMS 索引： [llms.txt](/llms.txt)

---

> **文档定位**：回答"前端不改写是确定的，但两套前端技术各有什么优劣"。结论前置：**qmtv 前端零改动（已裁决）**；本文是选型对比存档 + 为 Go 移植钉住前端兼容面 + 沉淀"若未来前端演进，哪些 pms 经验值得吸收"。事实基线：2026-10-17 双仓库实测。
>
> **修订（2026-10-17，PRD v1.1）**：§3 结论「前端不动」已被新裁决取代——**新建 `frontend/` 独立前端项目（初始复制 qmtv 前端）+ 演进三件**（@tanstack/vue-query / vitest+vue / TS 渐进），详见 `prd-qmtv-v1.md` §7。本文 §1/§2 事实对照、§2.3 可迁移经验（vue-query 等价获得、测试文化、类型收敛纪律）与 §5 钉子表**全部继续有效**；原文保留存档不改。

## 1. 两套技术栈事实对照

| 维度 | qmtv（Vue3 单体） | pms web（React 中后台） |
|------|-------------------|------------------------|
| 框架/语言 | Vue 3.5 + vue-router 4，**纯 JS 无 TS** | React 18.3 + TS 5.6（strict:true，关 noUnusedLocals） |
| 构建 | Vite 8（vite.config 13 行，proxy /api /files） | Vite 5（tsc -b 前置 + vite build） |
| UI 库 | **无**——全部手写组件 + 自定义指令（v-tilt 3D 倾斜）+ CSS 三主题（dark/light/gae） | AntD 5.22 + ProComponents（实际只用 ProLayout 布局壳，ProTable/ProForm 未用） |
| 请求层 | `src/api.js` 46 行：fetch 相对路径 `/api`、401 自动 refresh 重试一次、localStorage 存 token | axios + 拦截器；`UnwrappedClient` 双泛型修补运行时解包与 TS 签名的断裂 |
| 服务端状态 | **无**——各页面自管 loading/缓存（Dashboard 1328 行单文件是代价） | TanStack Query 重度：191 useQuery / 86 useMutation / 363 queryKey + 自研 QueryTable 封装 |
| 客户端状态 | router.js 内轻量 reactive store（user/notifications） | Zustand 4 个极小 store（<100 行） |
| i18n | 无（纯中文） | react-i18next 四语 1750 key/语言 + coverage.test 双重防护（语言间 parity + t() 字面键扫描） |
| 测试 | **零**（仅根目录 4 个 verify_*.js API 冒烟脚本） | vitest 142 文件 639 例（页面测试与源文件近 1:1）+ Playwright 双册（断言册 API-first 25 例与截图册物理隔离） |
| 路由 | 集中 24 条 + meta.admin 守卫 + 全局 beforeEach | 集中 110 Route、零懒加载、组件包裹式守卫 |
| 规模 | 24 页面 9082 行（最大 AdminView 1371 行/Dashboard 1328 行单文件） | 104 页面 + 20 封装组件 + 96 测试文件 |
| 实时 | 原生 EventSource（/api/events?token=）+ 每分钟轮询补偿 | SSE/轮询按需（生命周期时间线组件） |

## 2. 优劣分析

### qmtv Vue3 的优势（在它的场景里）

1. **极简依赖、零构建心智**：6 个运行时依赖，13 行 vite 配置，单人可全栈维护；对 AI 辅助开发极友好（上下文小）。
2. **前端对后端零耦合**：相对路径 + 单一 fetch 封装，后端换语言零改动（本次移植的前提，已验证成立）。
3. **产品形态匹配**：C 端气质的创意工具（3D 分镜/主题切换/悬浮客服），手写组件的自由度比 AntD 中后台模板更贴合；AntD 反而会给它套上管理后台的壳。
4. vue-router 的 meta 守卫与 SFC 单文件组织，样板代码比 React 集中路由少。

### qmtv 的劣势（真实欠账）

1. **无类型**：9082 行 JS，接口契约只存在于约定；AdminView 14 个 Tab 1371 行单文件，回归靠人肉。
2. **无服务端状态层**：缓存/失效/重试每页手写——Dashboard/Workbench 类多数据源页面复杂度爆炸的根因。
3. **零测试**：239 个后端契约没有任何前端侧断言。
4. **无 i18n**：纯中文硬编码，产品出海需全量改造。

### pms web 的优势（可迁移的经验）

1. **React Query 服务端状态模式**是 pms 最值得移植的工程习惯——loading/缓存/失效全部声明式，191 处 useQuery 换来的是每个页面只剩"数据+渲染"。qmtv 若演进，**@tanstack/vue-query 可等价获得，不必换 React**。
2. **测试文化**：页面测试近 1:1、Playwright 断言册与截图册物理隔离、i18n coverage 双重防护——这些约定与框架无关，可原样移植到 vitest+vue。
3. **类型收敛纪律**：api 函数返回类型显式收敛、禁止 `as any` 兜底（注释溯源）——qmtv 若加 TS，这条是第一规则。
4. AntD5 中后台生态确实是复制式开发效率的根源；但注意 pms 实际只用了 ProLayout，ProTable/ProForm 红利并未吃到——"上了 AntD 就高效"要打折扣。

### pms web 的劣势（对比中看到的税）

1. axios 运行时解包与 TS 方法签名的断裂需要 `UnwrappedClient` 类型修补层持续还债；Row 接口仍带 `[k:string]:any` 兜底。
2. 110 条路由零懒加载，bundle 全量；qmtv 反而做了按页面 code-split。
3. ProComponents 引入而未深度使用，依赖面大于收益面。

## 3. 结论

| 问题 | 结论 |
|------|------|
| 现在要不要动 qmtv 前端 | **不动**。它与 Go 后端的耦合面只有 8 条契约（§5），Go 版逐条钉住即可；产品已建成，重写无动机 |
| 若未来前端演进，选什么 | 沿 Vue3 生态增量演进：加 TS（渐进）+ @tanstack/vue-query（服务端状态）+ vitest（补测试）——吸收 pms 的**模式**而非换框架 |
| 对 Go 移植的输入 | §5 的 8 条契约钉子进 PRD（已完成）与 TECH.md；SSE/token query/时间格式三处最易破 |

## 4. 迁移成本对照（假设反向迁移，仅作存档论证）

qmtv→pms 栈重写 ≈ 24 页面×(组件重写+React Query 接线+测试补齐) ≈ 与后端 Go 移植同量级的工程；而它解决的三个痛点（类型/服务端状态/测试）都能在 Vue 生态内补齐。**重写框架 = 高成本解决低价值问题**，此结论与"后端为何值得重写"（生产化运营的并发/部署/一致性硬需求）不同质。

## 5. Go 侧 8 条逐字节兼容约束（钉子表，PRD §2 已契约化）

| # | 契约 | 前端依赖点 | Go 版钉子 |
|---|------|-----------|----------|
| 1 | 响应信封 `{ok,data}` / `{error}` | api.js:37 解包 `.data`、抛 `{status,message}` | gateway.OK/Err helper 全局唯一出口 |
| 2 | `/api/health` 裸 `{ok:true,name:"QMTV"}` | DEPLOY.md 监控/冒烟 | 不走信封 |
| 3 | token query 双通道 | EventSource/img 标签无法带 header | auth 中间件白名单 |
| 4 | SSE 帧格式+25s 心跳 | App.vue addEventListener 四类事件 | SSE hub 逐字节对齐 |
| 5 | uid 前缀+UUIDv4 格式 | `slice` 截取（routes2.js:368/enterprise.js:40 同语义前端存在） | infra/ids 前缀常量表 |
| 6 | scrypt N=16384/r=8/p=1 `salt:hash` | 登录面（种子账号兼容） | infra/crypto 参数显式 |
| 7 | 时间 `YYYY-MM-DD HH:MM:SS` 字符串 | 直接渲染不解析 | LocalTime 类型，禁 RFC3339 |
| 8 | 中文错误文案+错误码面 | 前端正则匹配（`/所有者/`、`/密码/`、429 文案） | PRD C9 冻结文案表 |

---

反链：

- [产品](/qmtv/product/)
