前端技术对比:qmtv(Vue3)vs pms web(React18+AntD5)
文档定位:回答"前端不改写是确定的,但两套前端技术各有什么优劣"。结论前置: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 的优势(在它的场景里)
- 极简依赖、零构建心智:6 个运行时依赖,13 行 vite 配置,单人可全栈维护;对 AI 辅助开发极友好(上下文小)。
- 前端对后端零耦合:相对路径 + 单一 fetch 封装,后端换语言零改动(本次移植的前提,已验证成立)。
- 产品形态匹配:C 端气质的创意工具(3D 分镜/主题切换/悬浮客服),手写组件的自由度比 AntD 中后台模板更贴合;AntD 反而会给它套上管理后台的壳。
- vue-router 的 meta 守卫与 SFC 单文件组织,样板代码比 React 集中路由少。
qmtv 的劣势(真实欠账)
- 无类型:9082 行 JS,接口契约只存在于约定;AdminView 14 个 Tab 1371 行单文件,回归靠人肉。
- 无服务端状态层:缓存/失效/重试每页手写——Dashboard/Workbench 类多数据源页面复杂度爆炸的根因。
- 零测试:239 个后端契约没有任何前端侧断言。
- 无 i18n:纯中文硬编码,产品出海需全量改造。
pms web 的优势(可迁移的经验)
- React Query 服务端状态模式是 pms 最值得移植的工程习惯——loading/缓存/失效全部声明式,191 处 useQuery 换来的是每个页面只剩"数据+渲染"。qmtv 若演进,@tanstack/vue-query 可等价获得,不必换 React。
- 测试文化:页面测试近 1:1、Playwright 断言册与截图册物理隔离、i18n coverage 双重防护——这些约定与框架无关,可原样移植到 vitest+vue。
- 类型收敛纪律:api 函数返回类型显式收敛、禁止
as any兜底(注释溯源)——qmtv 若加 TS,这条是第一规则。 - AntD5 中后台生态确实是复制式开发效率的根源;但注意 pms 实际只用了 ProLayout,ProTable/ProForm 红利并未吃到——“上了 AntD 就高效"要打折扣。
pms web 的劣势(对比中看到的税)
- axios 运行时解包与 TS 方法签名的断裂需要
UnwrappedClient类型修补层持续还债;Row 接口仍带[k:string]:any兜底。 - 110 条路由零懒加载,bundle 全量;qmtv 反而做了按页面 code-split。
- 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 冻结文案表 |