All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 1m8s
214 lines
7.6 KiB
Markdown
214 lines
7.6 KiB
Markdown
# 前端选型与代码组织
|
||
|
||
> 状态:推荐方案,尚未创建脚手架或安装依赖。
|
||
|
||
## 一、推荐结论
|
||
|
||
推荐使用 Vue 3 + TypeScript + Vite,并采用 pnpm workspace 单仓库、三个独立应用:
|
||
|
||
```text
|
||
frontend/
|
||
├── apps/
|
||
│ ├── admin-web/ # 管理 Web
|
||
│ ├── admin-h5/ # 管理 H5
|
||
│ └── client-h5/ # 独立 C 端 H5
|
||
└── packages/
|
||
└── api/ # OpenAPI 生成类型和请求客户端
|
||
```
|
||
|
||
推荐组合:
|
||
|
||
| 领域 | 选择 | 理由 |
|
||
| --- | --- | --- |
|
||
| 框架 | Vue 3 + TypeScript | 管理后台和 H5 生态成熟,单文件组件适合页面型业务 |
|
||
| 构建 | Vite | 配置少,三应用可独立构建和发布 |
|
||
| 工作区 | pnpm workspace | 只解决多应用依赖和共享 API 包,不引入额外编排平台 |
|
||
| 管理 Web UI | Element Plus | 表格、表单、树、分页、弹窗等后台能力完整 |
|
||
| 管理 H5/C 端 UI | Vant | 移动表单、列表、弹层、支付结果页等 H5 交互成熟 |
|
||
| 路由 | Vue Router | 三个应用分别维护静态路由表 |
|
||
| 客户端状态 | Pinia | 只保存登录态、当前用户、菜单和按钮权限 |
|
||
| 接口类型 | openapi-typescript | 从现有 OpenAPI 生成 TypeScript 类型 |
|
||
| 请求客户端 | openapi-fetch + 原生 fetch | 类型直接复用,减少手写接口和额外封装 |
|
||
|
||
不在首期引入:Nx、Turborepo、大型后台模板、服务端状态缓存库、自研组件库、微前端。
|
||
|
||
## 二、为什么建议三个应用
|
||
|
||
管理 Web 和管理 H5 使用同一套后端业务与权限,但它们是两个真实的交互界面:
|
||
|
||
- Web 以高密度表格、批量操作、复杂配置为主。
|
||
- 管理 H5 以资产查询、现场操作、审批、资金和通知为主。
|
||
- 两端登录分别传 `device=web` 和 `device=h5`,后端会返回不同菜单。
|
||
- Element Plus 和 Vant 的布局与交互模型不同,强行在一个应用混用会增加条件渲染和包体积。
|
||
- C 端 H5 使用完全不同的个人客户认证、微信 OAuth、支付回跳和资产绑定流程,必须独立。
|
||
|
||
三个应用放在同一仓库,可以统一 TypeScript、Lint、构建和 OpenAPI 类型,又不会把三种页面体验绑在一个发布包中。
|
||
|
||
## 三、何时可以改成两个应用
|
||
|
||
如果管理 H5 最终只保留以下少量页面,可以使用“自适应管理端 + C 端 H5”两应用方案:
|
||
|
||
- 登录和个人中心。
|
||
- 通知。
|
||
- 统一资产搜索和只读详情。
|
||
- 少量订单、退款、换货审批。
|
||
|
||
一旦管理 H5 需要独立导航、设备控制、企业授权、资金、上传或大量移动表单,就应使用独立 `admin-h5`。当前页面矩阵已经超过纯只读壳层,因此默认采用三个应用。
|
||
|
||
## 四、共享边界
|
||
|
||
首期只共享 `packages/api`:
|
||
|
||
```text
|
||
Go 路由和 DTO
|
||
↓
|
||
docs/admin-openapi.yaml
|
||
↓
|
||
openapi-typescript
|
||
↓
|
||
packages/api 类型与客户端
|
||
↓
|
||
admin-web / admin-h5 / client-h5
|
||
```
|
||
|
||
暂不共享:
|
||
|
||
- 页面组件。
|
||
- 登录页面。
|
||
- 业务状态管理。
|
||
- Web/H5 表单组件。
|
||
- 业务流程组合函数。
|
||
|
||
等两个应用出现真实、稳定、完全相同的重复后再提取。不要先创建 `shared-business`、`shared-components` 等空泛包。
|
||
|
||
## 五、推荐仓库结构
|
||
|
||
```text
|
||
frontend/
|
||
├── apps/
|
||
│ ├── admin-web/
|
||
│ │ └── src/
|
||
│ │ ├── app/
|
||
│ │ ├── pages/
|
||
│ │ ├── routes/
|
||
│ │ └── stores/
|
||
│ ├── admin-h5/
|
||
│ │ └── src/
|
||
│ │ ├── app/
|
||
│ │ ├── pages/
|
||
│ │ ├── routes/
|
||
│ │ └── stores/
|
||
│ └── client-h5/
|
||
│ └── src/
|
||
│ ├── app/
|
||
│ ├── pages/
|
||
│ ├── routes/
|
||
│ └── stores/
|
||
├── packages/
|
||
│ └── api/
|
||
│ ├── generated/
|
||
│ ├── client.ts
|
||
│ └── index.ts
|
||
├── package.json
|
||
├── pnpm-workspace.yaml
|
||
└── tsconfig.base.json
|
||
```
|
||
|
||
目录保持扁平。页面内部先就近放置组件,不按 `api/service/model/controller` 重建一套前端分层。
|
||
|
||
## 六、请求模块的唯一职责
|
||
|
||
`packages/api` 只负责:
|
||
|
||
1. OpenAPI 生成类型。
|
||
2. Base URL。
|
||
3. Bearer Token 注入。
|
||
4. 管理端 Refresh Token 单次刷新队列。
|
||
5. `{code,msg,data,timestamp}` 解包。
|
||
6. 401、403、429、5xx 统一错误事件。
|
||
7. Request ID 提取。
|
||
|
||
它不负责:
|
||
|
||
- 页面跳转。
|
||
- Toast 文案拼接。
|
||
- 将订单状态改成本地状态机。
|
||
- 缓存所有列表和详情。
|
||
- 替页面吞掉错误。
|
||
|
||
这使请求模块保持为一个小接口、深实现的公共模块,三应用只需要学习同一套调用方式。
|
||
|
||
## 七、动态菜单实现
|
||
|
||
后端菜单只决定“哪些本地路由可见和可进入”,不能直接决定加载哪个源代码文件。
|
||
|
||
正确方式:
|
||
|
||
1. 每个管理应用维护静态路由表:`routeKey/url → 页面组件`。
|
||
2. 登录后读取 `menus`。
|
||
3. 将后端菜单与本地静态路由表求交集。
|
||
4. 生成导航和路由白名单。
|
||
5. 未匹配到本地页面时记录告警并隐藏,不允许字符串动态 import 任意组件。
|
||
6. 使用 `buttons` 控制操作按钮。
|
||
|
||
## 八、状态管理边界
|
||
|
||
Pinia 首期只保存:
|
||
|
||
- Access Token、Refresh Token。
|
||
- 当前用户。
|
||
- 菜单、按钮和权限码。
|
||
- 当前终端类型。
|
||
- 少量跨页面 UI 状态。
|
||
|
||
订单列表、资产详情、套餐列表等服务端数据由页面直接请求并局部刷新。等出现跨页面共享缓存、复杂失效和后台自动刷新需求后,再评估服务端状态库。
|
||
|
||
## 九、OpenAPI 工作流
|
||
|
||
建议建立固定流水线:
|
||
|
||
```text
|
||
go run ./cmd/gendocs
|
||
↓
|
||
更新 docs/admin-openapi.yaml
|
||
↓
|
||
生成 packages/api/generated
|
||
↓
|
||
TypeScript 类型检查
|
||
↓
|
||
构建三个应用
|
||
```
|
||
|
||
生成文件不手改。字段不正确时修改 Go DTO、RouteSpec 或文档生成器,然后重新生成。
|
||
|
||
当前 `admin-openapi.yaml` 同时包含管理端、C 端、开放接口和回调,文件名虽然偏旧,但首期无需为前端拆分多份 OpenAPI。
|
||
|
||
## 十、方案对比
|
||
|
||
| 方案 | 优点 | 风险 | 结论 |
|
||
| --- | --- | --- | --- |
|
||
| Vue 三应用单仓库 | Web/H5 体验清晰;共享接口类型;独立发布 | 有少量工程重复 | 推荐 |
|
||
| Vue 自适应管理端 + C端H5 | 少一个应用,首期代码更少 | Web/H5 组件混用、条件页面和包体增长 | 仅管理 H5 很小时使用 |
|
||
| React 三应用 | 也能满足需求,团队成熟时可选 | 当前没有团队技术偏好,初始约定和库选择更多 | 团队明显更熟 React 时替换推荐方案 |
|
||
|
||
如果实施团队已有稳定 React 经验,应优先服从团队能力,使用 React + TypeScript + Vite、Ant Design、Ant Design Mobile,仍保持“三应用单仓库+只共享 OpenAPI 包”的结构,不必为追求 Vue 统一而增加学习成本。
|
||
|
||
## 十一、创建脚手架前需要确认
|
||
|
||
1. 前端团队更熟 Vue 还是 React。
|
||
2. 管理 H5 是否作为独立正式产品发布。
|
||
3. 三个应用的域名、Base URL 和环境配置。
|
||
4. 微信公众号 OAuth 回调域名和支付回跳地址。
|
||
5. 首期页面范围及权限种子数据。
|
||
6. 后端企业数据范围和逐接口权限门禁是否完成验证。
|
||
|
||
## 十二、参考资料
|
||
|
||
- [Vue TypeScript](https://vuejs.org/guide/typescript/overview.html)
|
||
- [Pinia](https://pinia.vuejs.org/)
|
||
- [Element Plus](https://element-plus.org/)
|
||
- [Vant](https://vant-ui.github.io/vant/)
|
||
- [openapi-typescript](https://openapi-ts.dev/introduction)
|
||
- [openapi-fetch](https://openapi-ts.dev/openapi-fetch/)
|
||
- [pnpm Workspace](https://pnpm.io/workspaces)
|