887 lines
29 KiB
Markdown
887 lines
29 KiB
Markdown
|
|
# Admin 前端唯一执行方案
|
|||
|
|
|
|||
|
|
更新时间:2026-03-19
|
|||
|
|
|
|||
|
|
## 1. 文档定位
|
|||
|
|
|
|||
|
|
本文是当前唯一有效的 Admin 前端执行方案,后续前端实现、拆分任务、接口联调、验收都以本文为准。
|
|||
|
|
|
|||
|
|
事实来源仅限以下文件:
|
|||
|
|
|
|||
|
|
- `docs/API.md`
|
|||
|
|
- `internal/api/router/router.go`
|
|||
|
|
- `docs/status/REAL_PROJECT_STATUS.md`
|
|||
|
|
- `docs/PROJECT_REVIEW_REPORT.md`
|
|||
|
|
|
|||
|
|
约束原则:
|
|||
|
|
|
|||
|
|
1. 只实现仓库内已经真实接线、可以联调的 API。
|
|||
|
|
2. PRD 与当前后端实现不一致时,以当前后端事实为准,缺口明确列为延期项或前置依赖。
|
|||
|
|
3. 页面、类型、认证流、API 服务层必须统一,不再允许文档内同时存在 Vue / React、Axios / Fetch、假接口 / 真接口两套口径。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 当前真实约束
|
|||
|
|
|
|||
|
|
### 2.1 项目现状
|
|||
|
|
|
|||
|
|
- 仓库中目前没有真实前端项目,Admin 前端尚未开始。
|
|||
|
|
- 后端当前已经通过 `go build ./...`、`go vet ./...`、`go test ./...`。
|
|||
|
|
- 当前项目真实状态是“后端核心链路可用,前端未开始,PRD 仍有未完成范围”。
|
|||
|
|
|
|||
|
|
### 2.2 必须接受的后端事实
|
|||
|
|
|
|||
|
|
- 用户管理没有 `POST /api/v1/users`,因此当前不支持“管理员单个创建用户”页面。
|
|||
|
|
- 没有批量启用、批量禁用、批量删除接口,因此不做批量用户操作。
|
|||
|
|
- `PUT /api/v1/users/:id/password` 当前只允许本人改自己的密码,不支持管理员重置他人密码。
|
|||
|
|
- `/api/v1/users/:id/avatar` 的处理逻辑实际上只更新当前登录用户头像,因此头像上传只放到“个人中心”,不放到用户管理页。
|
|||
|
|
- 仪表盘统计只提供:
|
|||
|
|
- 用户总数、各状态人数
|
|||
|
|
- 今日 / 本周 / 本月新增用户
|
|||
|
|
- 今日成功 / 失败登录数
|
|||
|
|
- 本周成功登录数
|
|||
|
|
- 没有系统设置配置接口,因此不做 `/settings` 页面。
|
|||
|
|
- 没有“当前用户权限快照”接口。前端可稳定获取的是:
|
|||
|
|
- `GET /api/v1/auth/userinfo`
|
|||
|
|
- `GET /api/v1/users/:id/roles`
|
|||
|
|
- OAuth 回调当前由后端直接返回 JSON,不是标准 SPA redirect 完成态,因此社交登录 / 绑定不纳入当前 MVP。
|
|||
|
|
- 设备接口没有“全局设备列表”,只有:
|
|||
|
|
- `GET /api/v1/devices` 当前用户设备
|
|||
|
|
- `GET /api/v1/devices/users/:id` 指定用户设备
|
|||
|
|
因此前端不做全局设备管理页面。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 单一技术栈
|
|||
|
|
|
|||
|
|
当前只接受以下一套前端技术栈:
|
|||
|
|
|
|||
|
|
| 关注点 | 统一方案 | 说明 |
|
|||
|
|
|--------|----------|------|
|
|||
|
|
| 框架 | React 18 + TypeScript | 统一组件模型和类型系统 |
|
|||
|
|
| 构建工具 | Vite | 快速启动,适合从零搭建 |
|
|||
|
|
| 路由 | React Router 6 | 足够覆盖登录、后台布局、受保护路由 |
|
|||
|
|
| UI 组件 | Ant Design 5 | 后台场景成熟,减少重复造轮子 |
|
|||
|
|
| 请求层 | 浏览器原生 `fetch` + 自建请求客户端 | 避免 Axios 二次封装分叉 |
|
|||
|
|
| 状态管理 | React Context 仅管理会话态 | 不引入 Redux / Zustand / Pinia |
|
|||
|
|
| 页面数据 | 页面局部状态 + 受控请求 | 首版不引入 React Query |
|
|||
|
|
| 表单 | Ant Design Form | 与 UI 组件一致 |
|
|||
|
|
| 样式 | CSS Modules + CSS Variables + AntD Theme Token | 不引入 `styled-components` |
|
|||
|
|
| 图表 | MVP 不引入额外图表库 | 当前统计接口不足以支撑复杂图表 |
|
|||
|
|
|
|||
|
|
明确不采用:
|
|||
|
|
|
|||
|
|
- Vue 3
|
|||
|
|
- Pinia
|
|||
|
|
- Axios
|
|||
|
|
- styled-components
|
|||
|
|
- React Query
|
|||
|
|
- “HTML + CSS + JavaScript 手写管理后台”
|
|||
|
|
|
|||
|
|
### 3.1 前端技术架构总览
|
|||
|
|
|
|||
|
|
前端统一采用单体 SPA 架构,不拆微前端,不做 SSR,不做多应用并行。
|
|||
|
|
|
|||
|
|
运行时分层固定为:
|
|||
|
|
|
|||
|
|
1. `App Shell`
|
|||
|
|
- 应用启动、主题、路由挂载、全局异常边界
|
|||
|
|
2. `Session Layer`
|
|||
|
|
- 会话恢复、刷新令牌、登录态广播、路由准入
|
|||
|
|
3. `HTTP Client Layer`
|
|||
|
|
- 鉴权头注入、统一解包、401 重试、下载上传
|
|||
|
|
4. `Service Layer`
|
|||
|
|
- 按资源拆分 API 方法,不放 UI 逻辑
|
|||
|
|
5. `Page / Feature Layer`
|
|||
|
|
- 页面编排、表格、表单、弹窗、抽屉
|
|||
|
|
6. `Shared UI Layer`
|
|||
|
|
- 布局、通用表格状态、空态、错误态、确认弹窗
|
|||
|
|
|
|||
|
|
数据流固定为:
|
|||
|
|
|
|||
|
|
`Page -> Service -> HTTP Client -> API`
|
|||
|
|
|
|||
|
|
禁止反向依赖:
|
|||
|
|
|
|||
|
|
- `services` 依赖页面组件
|
|||
|
|
- 页面直接拼接 URL 自己发请求
|
|||
|
|
- 多套 token 管理并存
|
|||
|
|
- 多套类型定义并存
|
|||
|
|
|
|||
|
|
### 3.2 项目目录架构
|
|||
|
|
|
|||
|
|
前端项目统一新建在:
|
|||
|
|
|
|||
|
|
- `frontend/admin`
|
|||
|
|
|
|||
|
|
目录结构固定为:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
frontend/admin/
|
|||
|
|
package.json
|
|||
|
|
tsconfig.json
|
|||
|
|
vite.config.ts
|
|||
|
|
.env.example
|
|||
|
|
src/
|
|||
|
|
app/
|
|||
|
|
App.tsx
|
|||
|
|
main.tsx
|
|||
|
|
router.tsx
|
|||
|
|
providers/
|
|||
|
|
AuthProvider.tsx
|
|||
|
|
ThemeProvider.tsx
|
|||
|
|
layouts/
|
|||
|
|
AdminLayout/
|
|||
|
|
AuthLayout/
|
|||
|
|
pages/
|
|||
|
|
auth/
|
|||
|
|
LoginPage/
|
|||
|
|
ForgotPasswordPage/
|
|||
|
|
ResetPasswordPage/
|
|||
|
|
admin/
|
|||
|
|
DashboardPage/
|
|||
|
|
UsersPage/
|
|||
|
|
RolesPage/
|
|||
|
|
PermissionsPage/
|
|||
|
|
LoginLogsPage/
|
|||
|
|
OperationLogsPage/
|
|||
|
|
WebhooksPage/
|
|||
|
|
ImportExportPage/
|
|||
|
|
ProfilePage/
|
|||
|
|
ProfileSecurityPage/
|
|||
|
|
features/
|
|||
|
|
auth/
|
|||
|
|
users/
|
|||
|
|
roles/
|
|||
|
|
permissions/
|
|||
|
|
logs/
|
|||
|
|
webhooks/
|
|||
|
|
profile/
|
|||
|
|
import-export/
|
|||
|
|
devices/
|
|||
|
|
totp/
|
|||
|
|
services/
|
|||
|
|
auth.ts
|
|||
|
|
users.ts
|
|||
|
|
roles.ts
|
|||
|
|
permissions.ts
|
|||
|
|
stats.ts
|
|||
|
|
logs.ts
|
|||
|
|
webhooks.ts
|
|||
|
|
import-export.ts
|
|||
|
|
profile.ts
|
|||
|
|
devices.ts
|
|||
|
|
lib/
|
|||
|
|
http/
|
|||
|
|
client.ts
|
|||
|
|
auth-session.ts
|
|||
|
|
errors.ts
|
|||
|
|
storage/
|
|||
|
|
token-storage.ts
|
|||
|
|
components/
|
|||
|
|
common/
|
|||
|
|
feedback/
|
|||
|
|
forms/
|
|||
|
|
types/
|
|||
|
|
http.ts
|
|||
|
|
auth.ts
|
|||
|
|
user.ts
|
|||
|
|
role.ts
|
|||
|
|
permission.ts
|
|||
|
|
device.ts
|
|||
|
|
log.ts
|
|||
|
|
webhook.ts
|
|||
|
|
stats.ts
|
|||
|
|
styles/
|
|||
|
|
tokens.css
|
|||
|
|
global.css
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
目录原则:
|
|||
|
|
|
|||
|
|
- `pages` 只放路由页面,不放复用业务组件
|
|||
|
|
- `features` 放页面内复用的业务组件与交互逻辑
|
|||
|
|
- `services` 只放接口调用
|
|||
|
|
- `types` 只放接口类型与领域类型
|
|||
|
|
- `components/common` 只放通用 UI,不感知业务资源
|
|||
|
|
|
|||
|
|
### 3.3 依赖白名单
|
|||
|
|
|
|||
|
|
首版允许引入的前端运行时依赖只保留:
|
|||
|
|
|
|||
|
|
- `react`
|
|||
|
|
- `react-dom`
|
|||
|
|
- `react-router-dom`
|
|||
|
|
- `antd`
|
|||
|
|
- `@ant-design/icons`
|
|||
|
|
- `dayjs`
|
|||
|
|
|
|||
|
|
首版允许引入的开发依赖只保留:
|
|||
|
|
|
|||
|
|
- `typescript`
|
|||
|
|
- `vite`
|
|||
|
|
- `@vitejs/plugin-react`
|
|||
|
|
- `eslint`
|
|||
|
|
- `@types/react`
|
|||
|
|
- `@types/react-dom`
|
|||
|
|
- `vitest`
|
|||
|
|
|
|||
|
|
依赖准入规则:
|
|||
|
|
|
|||
|
|
1. 没有明确解决当前问题的依赖,不引入。
|
|||
|
|
2. 能用浏览器原生能力解决的问题,不引入包装库。
|
|||
|
|
3. 同类库只保留一套。
|
|||
|
|
|
|||
|
|
### 3.4 技术简化结论
|
|||
|
|
|
|||
|
|
这版前端技术架构刻意做了收缩,最终结论如下:
|
|||
|
|
|
|||
|
|
- 不做微前端
|
|||
|
|
- 不做 monorepo 拆分
|
|||
|
|
- 不做 SSR / SSG
|
|||
|
|
- 不做 Redux / Zustand / Pinia
|
|||
|
|
- 不做 React Query
|
|||
|
|
- 不做 Axios
|
|||
|
|
- 不做 CSS-in-JS
|
|||
|
|
- 不做图表库优先接入
|
|||
|
|
- 不做权限码驱动的复杂前端元编程
|
|||
|
|
|
|||
|
|
首版只保留四个必须的技术支点:
|
|||
|
|
|
|||
|
|
1. React 页面和路由
|
|||
|
|
2. Context 会话管理
|
|||
|
|
3. `fetch` 请求客户端
|
|||
|
|
4. Ant Design 后台组件
|
|||
|
|
|
|||
|
|
### 3.5 工程准则
|
|||
|
|
|
|||
|
|
前端开发时必须遵守以下准则:
|
|||
|
|
|
|||
|
|
1. 一个 API 资源对应一个 service 文件。
|
|||
|
|
2. 一个路由页面对应一个 page 目录。
|
|||
|
|
3. 一个复杂弹窗 / 抽屉对应一个独立 feature 组件。
|
|||
|
|
4. 一个任务只解决一类问题,不混做“页面 + 所有依赖 + 所有接口”。
|
|||
|
|
5. 所有新代码默认 TypeScript 严格模式。
|
|||
|
|
6. 所有请求先写类型,再写 service,再接页面。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 页面与路由范围
|
|||
|
|
|
|||
|
|
### 4.1 MVP 页面
|
|||
|
|
|
|||
|
|
| 路由 | 访问级别 | 页面范围 | 对应 API |
|
|||
|
|
|------|----------|----------|----------|
|
|||
|
|
| `/login` | 公开 | 账号密码登录、邮箱验证码登录、短信验证码登录 | `/auth/login` `/auth/send-email-code` `/auth/login/email-code` `/auth/send-code` `/auth/login/code` |
|
|||
|
|
| `/forgot-password` | 公开 | 发起密码重置 | `/auth/forgot-password` |
|
|||
|
|
| `/reset-password` | 公开 | 校验重置 token、提交新密码 | `/auth/reset-password` |
|
|||
|
|
| `/dashboard` | 管理员 | 统计卡片与简表,不做假趋势图 | `/admin/stats/dashboard` `/admin/stats/users` |
|
|||
|
|
| `/users` | 管理员 | 用户列表、筛选、详情抽屉、编辑、状态切换、删除、分配角色 | `/users` `/users/:id` `/users/:id` `/users/:id/status` `/users/:id/roles` `/users/:id` |
|
|||
|
|
| `/roles` | 管理员 | 角色列表、创建、编辑、删除、启停、分配权限 | `/roles` `/roles/:id` `/roles/:id/status` `/roles/:id/permissions` |
|
|||
|
|
| `/permissions` | 管理员 | 权限列表、树、创建、编辑、删除、启停 | `/permissions` `/permissions/tree` `/permissions/:id/status` |
|
|||
|
|
| `/logs/login` | 管理员 | 登录日志列表 | `/logs/login` |
|
|||
|
|
| `/logs/operation` | 管理员 | 操作日志列表 | `/logs/operation` |
|
|||
|
|
| `/webhooks` | 已登录 | Webhook 列表、创建、编辑、删除、投递记录 | `/webhooks` `/webhooks/:id/deliveries` |
|
|||
|
|
| `/import-export` | 管理员 | 导入、导出、模板下载 | `/admin/users/import` `/admin/users/export` `/admin/users/import/template` |
|
|||
|
|
| `/profile` | 已登录 | 个人资料查看与编辑 | `/auth/userinfo` `/users/:id` |
|
|||
|
|
| `/profile/security` | 已登录 | 修改密码、TOTP、头像上传、本人设备、本人日志 | `/users/:id/password` `/auth/2fa/*` `/users/:id/avatar` `/devices` `/logs/login/me` `/logs/operation/me` |
|
|||
|
|
|
|||
|
|
### 4.2 页面能力边界
|
|||
|
|
|
|||
|
|
`/users` 当前只允许实现:
|
|||
|
|
|
|||
|
|
- 列表分页、关键字筛选、状态筛选、角色筛选、时间筛选、排序
|
|||
|
|
- 查看用户详情
|
|||
|
|
- 编辑用户资料
|
|||
|
|
- 删除用户
|
|||
|
|
- 修改用户状态
|
|||
|
|
- 分配角色
|
|||
|
|
|
|||
|
|
`/users` 当前明确不做:
|
|||
|
|
|
|||
|
|
- 新建用户
|
|||
|
|
- 批量操作
|
|||
|
|
- 管理员代改他人密码
|
|||
|
|
- 为其他用户上传头像
|
|||
|
|
|
|||
|
|
`/dashboard` 当前只允许展示真实统计字段,不做以下伪需求:
|
|||
|
|
|
|||
|
|
- 在线用户
|
|||
|
|
- 近 7 / 30 天时序趋势图
|
|||
|
|
- 地域分布图
|
|||
|
|
- 最近注册用户
|
|||
|
|
- 最近登录用户
|
|||
|
|
|
|||
|
|
### 4.3 延期或阻塞页面
|
|||
|
|
|
|||
|
|
以下页面或功能不进入当前前端实施范围:
|
|||
|
|
|
|||
|
|
- `/settings`
|
|||
|
|
- 全局 `/devices` 管理页
|
|||
|
|
- 用户创建页
|
|||
|
|
- 用户批量操作
|
|||
|
|
- 管理员重置他人密码
|
|||
|
|
- “记住我 / 记住设备”
|
|||
|
|
- 社交登录回调页
|
|||
|
|
- 社交账号绑定页
|
|||
|
|
- 依赖权限码的细粒度按钮控制
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 统一类型模型
|
|||
|
|
|
|||
|
|
### 5.1 基础响应模型
|
|||
|
|
|
|||
|
|
所有请求统一先经过响应解包,禁止页面直接假定不同接口的 `data` 结构。
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
export interface ApiResponse<T> {
|
|||
|
|
code: number;
|
|||
|
|
message: string;
|
|||
|
|
data: T;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface PaginatedData<T> {
|
|||
|
|
items: T[];
|
|||
|
|
total: number;
|
|||
|
|
page: number;
|
|||
|
|
page_size: number;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
注意:
|
|||
|
|
|
|||
|
|
- 分页列表真实格式是 `data.items + total + page + page_size`。
|
|||
|
|
- 不是所有列表都是分页返回。
|
|||
|
|
- `GET /webhooks`、`GET /users/:id/roles`、`GET /roles/:id/permissions`、`GET /permissions/tree` 等接口返回的不是 `PaginatedData<T>`。
|
|||
|
|
|
|||
|
|
### 5.2 会话与认证类型
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
export interface SessionUser {
|
|||
|
|
id: number;
|
|||
|
|
username: string;
|
|||
|
|
email: string;
|
|||
|
|
phone: string;
|
|||
|
|
nickname: string;
|
|||
|
|
avatar: string;
|
|||
|
|
status: 0 | 1 | 2 | 3;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface TokenBundle {
|
|||
|
|
access_token: string;
|
|||
|
|
refresh_token: string;
|
|||
|
|
expires_in: number;
|
|||
|
|
user: SessionUser;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
关键约束:
|
|||
|
|
|
|||
|
|
- `POST /auth/login` 返回 `TokenBundle`
|
|||
|
|
- `POST /auth/refresh` 也返回 `TokenBundle`
|
|||
|
|
- 不允许再定义“刷新后只返回 access_token”的前端假类型
|
|||
|
|
|
|||
|
|
### 5.3 领域类型
|
|||
|
|
|
|||
|
|
前端类型定义以当前后端 JSON 字段为准,至少包含以下文件:
|
|||
|
|
|
|||
|
|
- `src/types/http.ts`
|
|||
|
|
- `src/types/auth.ts`
|
|||
|
|
- `src/types/user.ts`
|
|||
|
|
- `src/types/role.ts`
|
|||
|
|
- `src/types/permission.ts`
|
|||
|
|
- `src/types/device.ts`
|
|||
|
|
- `src/types/log.ts`
|
|||
|
|
- `src/types/webhook.ts`
|
|||
|
|
- `src/types/stats.ts`
|
|||
|
|
|
|||
|
|
必须保留的真实枚举约束:
|
|||
|
|
|
|||
|
|
- `UserStatus`: `0 | 1 | 2 | 3`
|
|||
|
|
- `RoleStatus`: `0 | 1`
|
|||
|
|
- `PermissionStatus`: `0 | 1`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. 认证与会话流
|
|||
|
|
|
|||
|
|
### 6.1 统一会话策略
|
|||
|
|
|
|||
|
|
采用以下单一策略:
|
|||
|
|
|
|||
|
|
1. `refresh_token` 持久化到 `localStorage`
|
|||
|
|
2. `access_token` 保存在内存态
|
|||
|
|
3. 应用启动时优先尝试用 `refresh_token` 换取新的 `TokenBundle`
|
|||
|
|
4. 刷新成功后再加载角色信息
|
|||
|
|
5. 刷新失败则清空会话并回到登录页
|
|||
|
|
|
|||
|
|
这样做的原因:
|
|||
|
|
|
|||
|
|
- 当前后端刷新接口已经返回完整 `TokenBundle`
|
|||
|
|
- 可以避免前端长期持久化过期 `access_token`
|
|||
|
|
- 页面刷新后可以稳定恢复登录态
|
|||
|
|
|
|||
|
|
### 6.2 启动流程
|
|||
|
|
|
|||
|
|
应用启动流程固定如下:
|
|||
|
|
|
|||
|
|
1. 读取本地 `refresh_token`
|
|||
|
|
2. 若存在,则调用 `POST /api/v1/auth/refresh`
|
|||
|
|
3. 刷新成功后,拿到新的 `access_token`、`refresh_token`、`user`
|
|||
|
|
4. 调用 `GET /api/v1/users/{user.id}/roles`
|
|||
|
|
5. 从角色列表中推导:
|
|||
|
|
- `roleCodes`
|
|||
|
|
- `isAdmin = roleCodes.includes("admin")`
|
|||
|
|
6. 会话完成后才渲染受保护路由
|
|||
|
|
|
|||
|
|
补充规则:
|
|||
|
|
|
|||
|
|
- 不以 `GET /auth/userinfo` 作为唯一启动入口,避免浪费一次可能会被 401 的请求
|
|||
|
|
- `GET /auth/userinfo` 作为“刷新当前资料”能力保留给 Profile 页面或手动重载
|
|||
|
|
|
|||
|
|
### 6.3 登录与登出流
|
|||
|
|
|
|||
|
|
登录页支持三种真实入口:
|
|||
|
|
|
|||
|
|
- 账号密码登录
|
|||
|
|
- 邮箱验证码登录
|
|||
|
|
- 短信验证码登录
|
|||
|
|
|
|||
|
|
登录成功后统一执行:
|
|||
|
|
|
|||
|
|
1. 写入新的 `refresh_token`
|
|||
|
|
2. 将新的 `access_token` 放入内存
|
|||
|
|
3. 直接使用返回体中的 `user`
|
|||
|
|
4. 再请求当前用户角色
|
|||
|
|
5. 完成后跳转后台首页
|
|||
|
|
|
|||
|
|
登出统一执行:
|
|||
|
|
|
|||
|
|
1. 调用 `POST /api/v1/auth/logout`
|
|||
|
|
2. 请求体优先带上当前 `access_token` 和 `refresh_token`
|
|||
|
|
3. 无论接口成功与否,都清空本地会话
|
|||
|
|
4. 跳回 `/login`
|
|||
|
|
|
|||
|
|
### 6.4 401 处理
|
|||
|
|
|
|||
|
|
请求客户端必须实现单次刷新机制:
|
|||
|
|
|
|||
|
|
1. 普通业务请求收到 `401`
|
|||
|
|
2. 若当前存在 `refresh_token`,触发一次全局中的刷新流程
|
|||
|
|
3. 刷新成功后重放原请求
|
|||
|
|
4. 刷新失败则清会话并跳转 `/login`
|
|||
|
|
|
|||
|
|
禁止旧方案中的以下行为:
|
|||
|
|
|
|||
|
|
- 收到 `401` 直接跳登录,不尝试刷新
|
|||
|
|
- 刷新后只更新 `access_token`,不更新 `refresh_token`
|
|||
|
|
|
|||
|
|
### 6.5 暂不纳入 MVP 的认证能力
|
|||
|
|
|
|||
|
|
以下能力有 API,但当前不纳入首版登录流:
|
|||
|
|
|
|||
|
|
- 社交登录按钮直连回调完成登录
|
|||
|
|
- 社交账号绑定
|
|||
|
|
- remember me
|
|||
|
|
|
|||
|
|
原因不是“前端不做”,而是“当前后端协议不适合 SPA 稳定落地”。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. API 服务层统一方案
|
|||
|
|
|
|||
|
|
### 7.1 目录结构
|
|||
|
|
|
|||
|
|
目录结构以 `3.2 项目目录架构` 为准。
|
|||
|
|
|
|||
|
|
本节只强调 service / lib / types 三层在该目录中的职责:
|
|||
|
|
|
|||
|
|
- `lib/http`
|
|||
|
|
- 统一请求客户端、会话刷新、错误模型
|
|||
|
|
- `services`
|
|||
|
|
- 资源级 API 访问层
|
|||
|
|
- `types`
|
|||
|
|
- 统一接口类型和领域类型
|
|||
|
|
|
|||
|
|
### 7.2 请求客户端职责
|
|||
|
|
|
|||
|
|
`lib/http/client.ts` 只做以下事情:
|
|||
|
|
|
|||
|
|
- 拼接基础 URL
|
|||
|
|
- 注入 `Authorization: Bearer <access_token>`
|
|||
|
|
- 统一解包 `ApiResponse<T>`
|
|||
|
|
- 统一处理 `401`
|
|||
|
|
- 统一处理 `Blob` 下载和 `FormData` 上传
|
|||
|
|
- 将后端业务错误统一转成前端可消费的 `AppError`
|
|||
|
|
|
|||
|
|
禁止:
|
|||
|
|
|
|||
|
|
- 页面组件内手写 `fetch("/api/v1/...")`
|
|||
|
|
- 每个页面自己处理 token 注入与刷新
|
|||
|
|
- 把分页响应和普通响应混成一个类型
|
|||
|
|
|
|||
|
|
### 7.3 服务层模块边界
|
|||
|
|
|
|||
|
|
`services/auth.ts`
|
|||
|
|
|
|||
|
|
- `loginByPassword`
|
|||
|
|
- `sendEmailCode`
|
|||
|
|
- `loginByEmailCode`
|
|||
|
|
- `sendSmsCode`
|
|||
|
|
- `loginBySmsCode`
|
|||
|
|
- `refreshSession`
|
|||
|
|
- `logout`
|
|||
|
|
- `forgotPassword`
|
|||
|
|
- `validateResetToken`
|
|||
|
|
- `resetPassword`
|
|||
|
|
- `getUserInfo`
|
|||
|
|
- `getTwoFactorStatus`
|
|||
|
|
- `setupTwoFactor`
|
|||
|
|
- `enableTwoFactor`
|
|||
|
|
- `disableTwoFactor`
|
|||
|
|
- `verifyTwoFactor`
|
|||
|
|
|
|||
|
|
`services/users.ts`
|
|||
|
|
|
|||
|
|
- `listUsers`
|
|||
|
|
- `getUser`
|
|||
|
|
- `updateUser`
|
|||
|
|
- `deleteUser`
|
|||
|
|
- `updateUserStatus`
|
|||
|
|
- `getUserRoles`
|
|||
|
|
- `assignUserRoles`
|
|||
|
|
|
|||
|
|
`services/profile.ts`
|
|||
|
|
|
|||
|
|
- `getMyProfile`
|
|||
|
|
- `updateMyProfile`
|
|||
|
|
- `changeMyPassword`
|
|||
|
|
- `uploadMyAvatar`
|
|||
|
|
- `getMyLoginLogs`
|
|||
|
|
- `getMyOperationLogs`
|
|||
|
|
|
|||
|
|
`services/roles.ts`
|
|||
|
|
|
|||
|
|
- `listRoles`
|
|||
|
|
- `createRole`
|
|||
|
|
- `getRole`
|
|||
|
|
- `updateRole`
|
|||
|
|
- `deleteRole`
|
|||
|
|
- `updateRoleStatus`
|
|||
|
|
- `getRolePermissions`
|
|||
|
|
- `assignRolePermissions`
|
|||
|
|
|
|||
|
|
`services/permissions.ts`
|
|||
|
|
|
|||
|
|
- `listPermissions`
|
|||
|
|
- `getPermissionTree`
|
|||
|
|
- `createPermission`
|
|||
|
|
- `getPermission`
|
|||
|
|
- `updatePermission`
|
|||
|
|
- `deletePermission`
|
|||
|
|
- `updatePermissionStatus`
|
|||
|
|
|
|||
|
|
`services/stats.ts`
|
|||
|
|
|
|||
|
|
- `getDashboardStats`
|
|||
|
|
- `getUserStats`
|
|||
|
|
|
|||
|
|
`services/logs.ts`
|
|||
|
|
|
|||
|
|
- `getLoginLogs`
|
|||
|
|
- `getOperationLogs`
|
|||
|
|
|
|||
|
|
`services/webhooks.ts`
|
|||
|
|
|
|||
|
|
- `listWebhooks`
|
|||
|
|
- `createWebhook`
|
|||
|
|
- `updateWebhook`
|
|||
|
|
- `deleteWebhook`
|
|||
|
|
- `getWebhookDeliveries`
|
|||
|
|
|
|||
|
|
`services/import-export.ts`
|
|||
|
|
|
|||
|
|
- `downloadUserExport`
|
|||
|
|
- `uploadUserImport`
|
|||
|
|
- `downloadImportTemplate`
|
|||
|
|
|
|||
|
|
`services/devices.ts`
|
|||
|
|
|
|||
|
|
- `getMyDevices`
|
|||
|
|
- `getUserDevices`
|
|||
|
|
- `getDevice`
|
|||
|
|
- `createDevice`
|
|||
|
|
- `updateDevice`
|
|||
|
|
- `deleteDevice`
|
|||
|
|
- `updateDeviceStatus`
|
|||
|
|
|
|||
|
|
### 7.4 下载与上传约束
|
|||
|
|
|
|||
|
|
- 用户导出必须走 `Blob` 下载
|
|||
|
|
- 导入必须走 `multipart/form-data`
|
|||
|
|
- 头像上传必须走 `multipart/form-data`
|
|||
|
|
- 头像上传虽然路径是 `/users/:id/avatar`,但前端只允许传当前用户 ID
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. 权限与路由守卫
|
|||
|
|
|
|||
|
|
### 8.1 现阶段只做两级守卫
|
|||
|
|
|
|||
|
|
当前前端守卫只做:
|
|||
|
|
|
|||
|
|
- `RequireAuth`
|
|||
|
|
- `RequireAdmin`
|
|||
|
|
|
|||
|
|
判断依据:
|
|||
|
|
|
|||
|
|
1. 会话中必须有有效 `access_token`
|
|||
|
|
2. 启动后必须已成功拉到当前用户角色
|
|||
|
|
3. `role.code === "admin"` 视为管理员
|
|||
|
|
|
|||
|
|
### 8.2 当前不做权限码按钮系统
|
|||
|
|
|
|||
|
|
原因:
|
|||
|
|
|
|||
|
|
- 后端没有“当前用户权限快照”公开接口
|
|||
|
|
- 中间件中的 `permission_codes` 仅存在于服务端请求上下文,不会自动返回给前端
|
|||
|
|
|
|||
|
|
因此当前只允许:
|
|||
|
|
|
|||
|
|
- 管理员页面用 `RequireAdmin`
|
|||
|
|
- 用户自己的页面按“本人”场景控制
|
|||
|
|
|
|||
|
|
当前不允许:
|
|||
|
|
|
|||
|
|
- 以前端硬编码方式伪造整套按钮级 `permission code` 控制体系
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. 实施阶段与最小任务拆解
|
|||
|
|
|
|||
|
|
### 9.1 交付顺序
|
|||
|
|
|
|||
|
|
前端按以下顺序交付,不允许跳步:
|
|||
|
|
|
|||
|
|
1. 工程骨架
|
|||
|
|
2. 会话与请求底座
|
|||
|
|
3. 认证页面
|
|||
|
|
4. 管理后台框架
|
|||
|
|
5. 核心管理页
|
|||
|
|
6. 运营与个人安全页
|
|||
|
|
7. 收尾验证
|
|||
|
|
|
|||
|
|
### 9.2 任务拆解规则
|
|||
|
|
|
|||
|
|
最小任务定义:
|
|||
|
|
|
|||
|
|
- 一个任务只产出一个明确可验证的结果
|
|||
|
|
- 一个任务的完成标准必须能被构建、页面行为或接口联调验证
|
|||
|
|
- 一个任务不能横跨多个资源域
|
|||
|
|
|
|||
|
|
任务粒度控制:
|
|||
|
|
|
|||
|
|
- 基础设施任务:一个文件组或一个运行能力
|
|||
|
|
- 服务层任务:一个资源服务文件
|
|||
|
|
- 页面任务:一个路由页面
|
|||
|
|
- 复杂交互任务:一个弹窗、一个抽屉、一个上传、一个下载流
|
|||
|
|
|
|||
|
|
### 9.3 M0 工程骨架
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M0-01 | 初始化 `frontend/admin` Vite 项目 | 基础工程目录 | 能本地启动空白 React 页面 |
|
|||
|
|
| M0-02 | 建立 `tsconfig` 路径别名 | `@/` 别名 | 导入路径不再依赖相对路径层层回退 |
|
|||
|
|
| M0-03 | 建立 `.env.example` | `VITE_API_BASE_URL` 规范 | 请求基地址可配置 |
|
|||
|
|
| M0-04 | 接入 Ant Design 5 和全局样式 | `global.css` / `tokens.css` | 页面样式正常加载 |
|
|||
|
|
| M0-05 | 建立 `AuthLayout` 与 `AdminLayout` 骨架 | 两套布局组件 | 登录页和后台页布局可区分 |
|
|||
|
|
| M0-06 | 建立应用路由骨架 | `router.tsx` | 公开页和受保护页都可访问 |
|
|||
|
|
| M0-07 | 建立错误页与 404 页 | 错误反馈页面 | 未匹配路由可落到 404 |
|
|||
|
|
| M0-08 | 建立全局 `AppError` 模型 | 统一错误结构 | 页面可接收统一错误对象 |
|
|||
|
|
|
|||
|
|
### 9.4 M1 会话与请求底座
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M1-01 | 实现 `token-storage.ts` | 刷新令牌读写封装 | `refresh_token` 可稳定存取 |
|
|||
|
|
| M1-02 | 实现 `auth-session.ts` | 内存态 access token 管理 | 页内请求可拿到当前 access token |
|
|||
|
|
| M1-03 | 实现 `client.ts` 基础请求能力 | `GET/POST/PUT/DELETE` 封装 | 页面不再手写原生请求细节 |
|
|||
|
|
| M1-04 | 实现统一响应解包 | `ApiResponse<T>` 解包 | service 可直接返回业务数据 |
|
|||
|
|
| M1-05 | 实现统一业务错误映射 | 后端错误转 `AppError` | 页面可稳定提示错误信息 |
|
|||
|
|
| M1-06 | 实现 401 单次刷新机制 | 请求重试逻辑 | access token 过期后可自动刷新一次 |
|
|||
|
|
| M1-07 | 实现并发刷新锁 | 单飞刷新 | 多请求 401 时只触发一次刷新 |
|
|||
|
|
| M1-08 | 实现 `AuthProvider` | 全局会话上下文 | 页面可读取用户、角色、登录状态 |
|
|||
|
|
| M1-09 | 实现应用启动会话恢复 | 启动自动 refresh | 刷新页面后能恢复登录态 |
|
|||
|
|
| M1-10 | 实现 `RequireAuth` | 登录守卫 | 未登录不可进入受保护页面 |
|
|||
|
|
| M1-11 | 实现 `RequireAdmin` | 管理员守卫 | 非 admin 不可进入后台管理页 |
|
|||
|
|
| M1-12 | 定义 `http.ts` / `auth.ts` / `user.ts` 基础类型 | 通用类型文件 | 认证和用户请求不再使用 `any` |
|
|||
|
|
|
|||
|
|
### 9.5 M2 认证页
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M2-01 | 实现 `services/auth.ts` | 认证 service | 登录、刷新、登出、密码重置接口可调用 |
|
|||
|
|
| M2-02 | 实现密码登录表单 | 登录页密码 Tab | 可调用 `/auth/login` 并进入后台 |
|
|||
|
|
| M2-03 | 实现邮箱验证码发送 | 邮箱验证码发送流程 | 可调用 `/auth/send-email-code` |
|
|||
|
|
| M2-04 | 实现邮箱验证码登录表单 | 邮箱验证码登录 Tab | 可调用 `/auth/login/email-code` |
|
|||
|
|
| M2-05 | 实现短信验证码发送 | 短信验证码发送流程 | 可调用 `/auth/send-code` |
|
|||
|
|
| M2-06 | 实现短信验证码登录表单 | 短信验证码登录 Tab | 可调用 `/auth/login/code` |
|
|||
|
|
| M2-07 | 实现忘记密码页 | `ForgotPasswordPage` | 可调用 `/auth/forgot-password` |
|
|||
|
|
| M2-08 | 实现重置密码页 | `ResetPasswordPage` | 可校验并提交重置密码 |
|
|||
|
|
| M2-09 | 实现登出动作 | 退出登录入口 | 退出后会话被清空并跳转登录页 |
|
|||
|
|
| M2-10 | 实现会话启动加载态 | 启动屏 / 骨架态 | 启动恢复期间不闪跳错误页面 |
|
|||
|
|
|
|||
|
|
### 9.6 M3 后台框架
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M3-01 | 实现后台菜单配置 | 路由与菜单映射 | 菜单只出现当前方案允许的页面 |
|
|||
|
|
| M3-02 | 实现后台头部区域 | 顶栏组件 | 能展示当前用户和退出入口 |
|
|||
|
|
| M3-03 | 实现侧边栏导航 | 菜单导航 | 页面间可跳转 |
|
|||
|
|
| M3-04 | 实现面包屑和页面容器 | 页面框架组件 | 后台页面布局一致 |
|
|||
|
|
| M3-05 | 实现页面级加载 / 空态 / 错误态组件 | 反馈组件 | 所有列表页使用统一反馈模式 |
|
|||
|
|
|
|||
|
|
### 9.7 M4 Dashboard
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M4-01 | 定义 `stats.ts` 类型 | 统计类型文件 | 用户统计和登录统计字段齐全 |
|
|||
|
|
| M4-02 | 实现 `services/stats.ts` | 统计 service | 可请求 dashboard / users stats |
|
|||
|
|
| M4-03 | 实现 Dashboard 统计卡片 | Dashboard 页面基础版 | 展示真实统计卡片 |
|
|||
|
|
| M4-04 | 实现 Dashboard 简表区块 | 简单文本 / 数字区块 | 不引入假图表但信息完整 |
|
|||
|
|
|
|||
|
|
### 9.8 M5 Users
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M5-01 | 完成 `user.ts` 领域类型 | 用户列表 / 详情类型 | 用户页所有字段有类型约束 |
|
|||
|
|
| M5-02 | 实现 `services/users.ts` | 用户 service | 列表、详情、编辑、状态、角色分配可调用 |
|
|||
|
|
| M5-03 | 实现用户筛选表单 | UsersFilter | 支持关键字、状态、角色、时间、排序 |
|
|||
|
|
| M5-04 | 实现用户列表表格 | UsersTable | 分页和列表展示正常 |
|
|||
|
|
| M5-05 | 实现用户详情抽屉 | UserDetailDrawer | 可查看用户详情 |
|
|||
|
|
| M5-06 | 实现编辑用户抽屉 | UserEditDrawer | 可提交 `/users/:id` 更新 |
|
|||
|
|
| M5-07 | 实现用户状态切换动作 | 状态更新交互 | 可提交 `/users/:id/status` |
|
|||
|
|
| M5-08 | 实现用户删除动作 | 删除确认流 | 可提交 `/users/:id` 删除 |
|
|||
|
|
| M5-09 | 实现用户角色分配弹窗 | AssignRolesModal | 可提交 `/users/:id/roles` |
|
|||
|
|
|
|||
|
|
### 9.9 M6 Roles
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M6-01 | 定义 `role.ts` 类型 | 角色类型文件 | 列表、详情、权限关联字段齐全 |
|
|||
|
|
| M6-02 | 实现 `services/roles.ts` | 角色 service | 增删改查、启停、权限分配可调用 |
|
|||
|
|
| M6-03 | 实现角色列表页 | RolesPage | 列表、分页、状态展示正常 |
|
|||
|
|
| M6-04 | 实现创建 / 编辑角色弹窗 | RoleFormModal | 可提交创建和更新 |
|
|||
|
|
| M6-05 | 实现角色状态切换 | 状态操作 | 可提交 `/roles/:id/status` |
|
|||
|
|
| M6-06 | 实现角色删除动作 | 删除确认流 | 可删除角色 |
|
|||
|
|
| M6-07 | 实现角色权限分配弹窗 | RolePermissionsModal | 可读取并提交角色权限 |
|
|||
|
|
|
|||
|
|
### 9.10 M7 Permissions
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M7-01 | 定义 `permission.ts` 类型 | 权限类型文件 | 权限树和列表字段齐全 |
|
|||
|
|
| M7-02 | 实现 `services/permissions.ts` | 权限 service | 列表、树、增删改查、启停可调用 |
|
|||
|
|
| M7-03 | 实现权限列表页 | PermissionsPage | 列表和树切换正常 |
|
|||
|
|
| M7-04 | 实现创建 / 编辑权限弹窗 | PermissionFormModal | 可提交创建和更新 |
|
|||
|
|
| M7-05 | 实现权限状态切换 | 状态操作 | 可提交 `/permissions/:id/status` |
|
|||
|
|
| M7-06 | 实现权限删除动作 | 删除确认流 | 可删除权限 |
|
|||
|
|
|
|||
|
|
### 9.11 M8 Logs
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M8-01 | 定义 `log.ts` 类型 | 日志类型文件 | 登录日志和操作日志字段齐全 |
|
|||
|
|
| M8-02 | 实现 `services/logs.ts` | 日志 service | 登录日志、操作日志接口可调用 |
|
|||
|
|
| M8-03 | 实现登录日志页 | LoginLogsPage | 列表、分页、筛选正常 |
|
|||
|
|
| M8-04 | 实现操作日志页 | OperationLogsPage | 列表、分页、筛选正常 |
|
|||
|
|
|
|||
|
|
### 9.12 M9 Webhooks
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M9-01 | 定义 `webhook.ts` 类型 | Webhook 类型文件 | 列表和投递记录字段齐全 |
|
|||
|
|
| M9-02 | 实现 `services/webhooks.ts` | Webhook service | 列表、增删改、投递记录可调用 |
|
|||
|
|
| M9-03 | 实现 Webhook 列表页 | WebhooksPage | 列表可展示 |
|
|||
|
|
| M9-04 | 实现创建 / 编辑 Webhook 弹窗 | WebhookFormModal | 可提交创建和更新 |
|
|||
|
|
| M9-05 | 实现删除 Webhook 动作 | 删除确认流 | 可删除 Webhook |
|
|||
|
|
| M9-06 | 实现投递记录抽屉 | DeliveriesDrawer | 可查看 `/webhooks/:id/deliveries` |
|
|||
|
|
|
|||
|
|
### 9.13 M10 Import / Export
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M10-01 | 实现 `services/import-export.ts` | 导入导出 service | 下载模板、上传导入、导出下载可调用 |
|
|||
|
|
| M10-02 | 实现导出表单 | ExportPanel | 可设置格式和筛选条件 |
|
|||
|
|
| M10-03 | 实现导出下载流 | Blob 下载 | CSV / XLSX 文件可正常下载 |
|
|||
|
|
| M10-04 | 实现导入上传表单 | ImportPanel | 可上传 `.csv` / `.xlsx` |
|
|||
|
|
| M10-05 | 实现模板下载动作 | TemplateDownload | 可下载导入模板 |
|
|||
|
|
|
|||
|
|
### 9.14 M11 Profile / Security
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M11-01 | 实现 `services/profile.ts` | 个人中心 service | 当前用户资料与安全接口可调用 |
|
|||
|
|
| M11-02 | 实现 `services/devices.ts` | 设备 service | 本人设备接口可调用 |
|
|||
|
|
| M11-03 | 实现个人资料页 | ProfilePage | 可查看并编辑个人资料 |
|
|||
|
|
| M11-04 | 实现修改密码表单 | ChangePasswordForm | 可提交本人密码修改 |
|
|||
|
|
| M11-05 | 实现 TOTP 状态与 setup 流程 | TOTPSetupPanel | 可拉取状态并展示 setup 信息 |
|
|||
|
|
| M11-06 | 实现 TOTP 启用 / 关闭 / 验证 | TOTPActionPanel | 可完整跑通 2FA 管理流 |
|
|||
|
|
| M11-07 | 实现头像上传 | AvatarUploadPanel | 可上传并刷新当前头像 |
|
|||
|
|
| M11-08 | 实现本人设备列表 | MyDevicesPanel | 可展示和操作 `/devices` |
|
|||
|
|
| M11-09 | 实现本人登录日志 | MyLoginLogsPanel | 可展示 `/logs/login/me` |
|
|||
|
|
| M11-10 | 实现本人操作日志 | MyOperationLogsPanel | 可展示 `/logs/operation/me` |
|
|||
|
|
|
|||
|
|
### 9.15 M12 收尾与验证
|
|||
|
|
|
|||
|
|
| ID | 任务 | 产出 | 完成定义 |
|
|||
|
|
|----|------|------|----------|
|
|||
|
|
| M12-01 | 统一菜单权限与路由准入复核 | 菜单守卫检查 | 管理页不会暴露给非 admin |
|
|||
|
|
| M12-02 | 统一分页交互复核 | 分页行为检查 | 所有分页页都按真实结构工作 |
|
|||
|
|
| M12-03 | 统一错误提示与空态复核 | 反馈体验检查 | 页面失败时不出现白屏 |
|
|||
|
|
| M12-04 | 添加关键基础测试 | `vitest` 用例 | 至少覆盖请求客户端和会话恢复逻辑 |
|
|||
|
|
| M12-05 | 执行前端构建验证 | `npm run build` | 生产构建通过 |
|
|||
|
|
| M12-06 | 执行联调烟雾验证 | 手工联调清单 | 每个已纳入页面至少完成一次真实接口验证 |
|
|||
|
|
|
|||
|
|
### 9.16 当前不拆解的延期项
|
|||
|
|
|
|||
|
|
以下项在后端前置条件未补齐前,不进入任务拆解:
|
|||
|
|
|
|||
|
|
- 社交登录 / 绑定
|
|||
|
|
- 系统设置
|
|||
|
|
- 全局设备管理
|
|||
|
|
- 用户创建
|
|||
|
|
- 批量操作
|
|||
|
|
- 细粒度权限码前端控制
|
|||
|
|
- 富图表仪表盘
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 10. 后端补齐前置依赖
|
|||
|
|
|
|||
|
|
以下接口或协议补齐后,前端范围才能继续扩张:
|
|||
|
|
|
|||
|
|
1. `POST /api/v1/users`,用于管理员单个创建用户
|
|||
|
|
2. 用户批量操作接口
|
|||
|
|
3. 当前用户角色码 / 权限码快照接口
|
|||
|
|
4. SPA 友好的 OAuth callback redirect 协议
|
|||
|
|
5. 社交账号绑定握手协议,而不是直接要求前端提交 `open_id`
|
|||
|
|
6. 系统设置读写接口
|
|||
|
|
7. 全局设备列表与检索接口
|
|||
|
|
8. 时间序列统计、最近活动、地域分布等仪表盘接口
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 11. 验收基线
|
|||
|
|
|
|||
|
|
后续前端实现必须满足以下验收条件:
|
|||
|
|
|
|||
|
|
1. 每个页面都能映射到当前真实后端 API,不出现“文档有、后端无”的按钮。
|
|||
|
|
2. 所有分页页都按真实结构处理 `items / total / page / page_size`。
|
|||
|
|
3. 刷新会话必须轮换 `refresh_token`,不能只更新 `access_token`。
|
|||
|
|
4. Admin 页面必须以当前用户角色中的 `admin` 作为准入条件。
|
|||
|
|
5. 个人头像上传只能从个人中心进入,不能放进用户管理页。
|
|||
|
|
6. Dashboard 只展示当前统计接口真实提供的数据。
|
|||
|
|
7. 不新增任何与本文冲突的前端栈或页面规划文档。
|