# 7月迭代前端技术方案

> 历史状态：共性前端来源稿；本地审批交互已废弃，最终以前端标准章节和各独立方案为准。
> 当前方案：[标准评审稿](../../7月迭代技术方案-标准评审稿.md)。
> 适用端：后台管理端、代理端、C 端 H5/公众号
> 最后更新：2026-07-14
> 说明：当前仓库不包含前端源码，本文定义页面、交互和接口契约；实际目录、状态库和组件名称由前端仓库现状映射，禁止据此凭空更换前端技术栈。

---

## 一、目标与边界

本方案解决七月迭代中跨需求的前端共性问题：

- 审批任务、退款和充值使用同一套动态审批展示。
- Excel 导入、批量订购和导出使用统一的异步任务交互。
- 站内消息统一未读数、列表、已读和业务跳转。
- 配置类页面不让用户直接编辑 JSON 或依赖前端自行校验业务规则。
- 金额、状态、时间、权限和错误展示使用统一口径。

本文不指定 Vue、React、Pinia、Redux 或具体 UI 组件库。实现时必须优先复用前端仓库现有的请求封装、权限指令、上传组件、表格和轮询 Hook。

---

## 二、系统上下文

```mermaid
flowchart LR
    AdminUser[平台/代理后台用户] --> AdminWeb[后台管理前端]
    Customer[C端客户] --> ClientWeb[C端 H5/公众号]
    AdminWeb -->|/api/admin/*| API[Junhong API]
    ClientWeb -->|/api/c/v1/*| API
    API --> DB[(PostgreSQL)]
    API --> Redis[(Redis)]
    API --> Queue[Asynq]
    Queue --> Worker[Worker]
    Worker --> APIData[业务数据/对象存储/Gateway]
    AdminWeb -->|轮询未读数、任务状态| API
```

前端只根据 API 返回的权限、状态和可操作项渲染，不自行推导“谁能审批”“是否允许扣款”或“当前流程下一步是谁”。

---

## 三、模块边界

建议在现有前端目录结构中映射以下模块，不要求创建新的全局架构：

| 模块 | 负责内容 | 不负责内容 |
|------|----------|------------|
| Approval | 待办列表、流程详情、流程定义配置、审批动作 | 退款或充值的业务表单 |
| Notification | 未读数、通知列表、标记已读、业务跳转 | 审批状态计算 |
| AsyncTask | 导入、批量订购、导出的轮询与结果展示 | 各业务文件解析 |
| Refund | 退款申请、编辑、重新提交、业务处理状态 | 动态审批节点渲染的内部规则 |
| Recharge | 代理在线充值、员工线下代充值、重新提交 | 钱包入账和审批人判断 |
| SystemConfig | 配置表单和版本刷新 | 直接编辑任意 JSON |

全局状态只保留跨页面共享的数据：登录用户、菜单/按钮权限、通知未读数。列表数据、详情数据和表单草稿默认留在页面或模块级状态，避免把服务端状态复制到全局 Store 后长期失真。

---

## 四、接口与类型约定

### 4.1 路径前缀

- 后台管理：`/api/admin/*`
- C 端：`/api/c/v1/*`
- 回调接口不由前端调用。

专项文档出现省略 `/api` 的路径时，以本节和真实路由注册为准，并应在评审前修正。

### 4.2 枚举和显示

- 生命周期状态使用后端返回的 `status` 做逻辑判断，使用 `status_name` 做中文展示。
- 前端不得维护另一份与后端重复的中文状态映射；只有颜色、图标等纯展示映射可以留在前端。
- 金额 API 统一使用“分”，输入组件展示“元”，提交前做整数转换，禁止浮点数直接乘除后提交。
- 时间统一使用后端 ISO 8601 值，展示层按现有项目时区和格式化工具处理。

### 4.3 请求幂等

审批等敏感写操作由前端生成 `request_id`。一次用户操作从首次提交到网络重试必须复用同一个值；用户明确重新发起操作时才生成新值。

按钮提交后进入 loading 并禁止重复点击。前端防重只是体验控制，后端仍必须执行状态条件更新和唯一约束。

---

## 五、统一异步任务交互

适用：设备批量分配、批量订购、导出任务。

不适用于临期状态：临期列表、详情和首页数量由接口实时 SQL 计算；每日任务只生成 15/7/3 天通知，前端不轮询或维护临期快照。

```mermaid
stateDiagram-v2
    [*] --> Editing: 填写参数/选择文件
    Editing --> Submitting: 提交
    Submitting --> Processing: 创建任务成功
    Submitting --> Editing: 参数或上传失败
    Processing --> Processing: 轮询进度
    Processing --> Completed: 全部或部分完成
    Processing --> Failed: 任务失败
    Processing --> Cancelled: 用户取消且后端确认
    Completed --> [*]
    Failed --> Editing: 修正后重新提交
    Cancelled --> [*]
```

### 5.1 轮询规则

- 创建成功后立即请求一次详情，再按 2 秒、3 秒、5 秒逐步退避，最大间隔 10 秒。
- 页面不可见时暂停轮询，恢复可见时立即刷新。
- 达到终态、离开页面或组件销毁时停止轮询。
- 连续网络失败不把业务任务标记为失败，展示“状态获取失败，点击重试”。
- 服务端返回 `retry_after_seconds` 时优先采用服务端建议。

### 5.2 结果展示

- 必须同时展示总数、成功数、失败数和任务状态。
- 部分成功不能只弹一个成功 Toast；失败明细要留在页面，并支持下载或复制，具体能力按专项方案。
- 导出任务完成后展示下载按钮和链接过期时间；链接过期时重新获取任务详情，不重新创建导出任务。

### 5.3 Excel 模板

- 设备批量分配、批量订购等 Excel 模板由前端作为静态资源维护，后端不提供模板下载 API。
- 模板文件名包含版本号，下载入口与对应上传表单放在同一页面。
- 后端仍必须严格校验表头和内容，不能因为模板由前端提供就信任文件结构。
- 模板字段变更需要前后端同批发布，并保留对用户本地旧模板的可理解错误提示。

---

## 六、统一审批交互

```mermaid
stateDiagram-v2
    [*] --> Loading
    Loading --> ReadOnly: 当前用户无待处理资格
    Loading --> Actionable: 当前用户是待处理审批人
    Actionable --> EditingAction: 打开通过/驳回/退回弹框
    EditingAction --> Uploading: 上传附件
    Uploading --> EditingAction: 上传成功或失败后返回
    EditingAction --> Submitting: 意见和附件校验通过
    Submitting --> EditingAction: 请求失败且任务仍可操作
    Submitting --> ReadOnly: 操作成功或状态已被他人改变
    ReadOnly --> [*]
```

### 6.1 页面建议

| 页面 | 建议路由 | 主要能力 |
|------|----------|----------|
| 待我审批 | `/approvals/tasks` | 状态、业务类型、提交人、当前节点、提交时间筛选 |
| 审批详情 | `/approvals/instances/:instance_id` | 业务快照、业务资料、动态节点时间线、审批人和意见、当前可操作按钮 |
| 流程定义 | `/settings/approval-flows` | 草稿、发布版本、停用、业务绑定 |
| 流程定义编辑 | `/settings/approval-flows/:id` | 串行节点配置、角色/账号选择、或签/会签、发布前校验 |

第一版只支持串行节点，前端使用“有序节点列表编辑器”，不建设拖拽 DAG/BPMN 设计器。节点可上移、下移、增加和删除；开始、结束节点由系统生成且不可删除。

### 6.2 动态详情

审批详情按接口返回的 `tasks[]` 和 `assignees[]` 渲染，禁止写死“部门领导”和“财务”两个字段。

详情首屏必须先渲染 `business_snapshot`：业务标题、业务单号、提交人、审批关键字段和业务资料。业务资料来自发起时快照，审批附件来自某位审批人的操作记录，页面用两个区域展示；审批人不需要跳转到实时业务页才能知道正在审批什么。

操作按钮显示条件同时满足：

- 流程状态为审批中。
- 当前任务状态为待审批。
- 当前账号对应的审批人状态为待处理。
- 接口返回相应操作权限。

操作成功后重新请求审批实例和关联业务详情，不做乐观状态推进。

审批详情可返回 `action_form.fields`。前端只渲染后端声明的受控字段类型；退款金额和操作密码均由流程节点配置决定，且只有当前动作会完成该节点时才出现。金额展示元、提交分；操作密码不写入全局 Store、本地存储或重试缓存，请求结束立即清空。节点没有动作字段时不显示额外表单，禁止根据“财务审核”等节点名称自行添加输入项。

每个通过、驳回、退回弹框统一包含“审批意见”和“附件”：

- 通过意见可选；驳回、退回意见必填，最多 1000 字。
- 意见使用普通多行文本框，不提供富文本编辑器。
- 附件最多 5 个、单个默认不超过 20MB，允许图片、PDF、Word、Excel；打开动作弹框时先生成 `request_id`，申请 `purpose=approval_attachment` 且绑定该 `request_id` 的上传凭证，上传完成后提交 `file_key + file_name`。前端校验只用于体验，最终以后端对象元数据和上传归属校验为准。
- 文件仍在上传时禁止提交审批；删除尚未提交的附件只影响本地表单，不调用删除历史审批附件。
- 网络重试复用原 `request_id`、意见和附件集合；操作成功后清空本地表单。
- 时间线按审批人展示各自意见和附件。审批附件和业务资料分别通过审批实例权限校验接口换取短期 URL，不直接拼对象存储地址。

### 6.3 业务处理中的展示

审批通过与退款到账、钱包入账不是同一时刻。退款和充值详情必须同时展示：

- 审批状态。
- 业务处理状态。
- 业务处理失败原因和“系统重试中/联系管理员”的提示；非代理钱包退款审批通过后显示“待人工退款”，仅财务确认权限可见确认完成入口。

不能仅根据业务单原状态显示“待审批”。

### 6.4 存量历史记录

业务详情接口增加 `approval_source`：

- `none`：当前业务不需要审批，例如代理在线充值；隐藏审批区域。
- `workflow`：存在通用审批实例，展示动态时间线和 `available_actions`。
- `legacy`：发布前已经结束的历史记录，没有完整流程实例；只读展示原业务状态、旧审批摘要和审计信息，不生成虚假节点。

如果一条仍需审批的退款或员工线下充值返回 `approval_instance_id=null`，前端按数据迁移异常展示并禁止任何审批操作，不能退回旧业务单审批接口。

---

## 七、页面与需求映射

| 需求 | 端 | 页面/入口 | 关键交互 |
|------|----|-----------|----------|
| 01 | 后台 | 资产详情复机操作 | 界面不变，展示后端真实结果 |
| 02 | 后台 + C端 | 卡/设备列表实名策略；C端流程页 | 单条/批量设置，C端按接口策略跳转 |
| 03/07/11/12/13 | 后台 | 原有列表和详情 | 新筛选、新字段、动态审批摘要 |
| 05 | 后台 | 套餐分配弹框、已分配列表 | 生效条件覆盖和修改提示 |
| 08 | 后台 | 设备管理批量操作 | “批量分配代理”和“批量分配套餐系列”两个入口，上传、任务轮询、失败明细 |
| 09 | 后台 + C端 | 系统配置；支付页 | 后台配置支付方式，C端隐藏并由后端兜底拦截 |
| 10 | 后台 | 卡/设备资产详情 | 手动设置或取消当前卡限速，单位 `kbps`，不提供套餐限速配置 |
| 14 | 后台 | 各业务列表导出 | 字段选择、权限过滤、统一导出任务 |
| 15 | C端 + 后台 | 当前套餐卡片、后台代购 | 当前套餐旁“续费”复用购买流程；下架套餐仅在合法续费入口展示 |
| 16 | - | 已移出 7 月迭代 | 不建设分销码、代理申请、提现材料和相关审批页面 |
| 17 | 后台/代理端 | 代理信用、钱包详情 | 元/分转换、欠款状态、额度权限 |
| 18/20/21 | 后台 | 待办、退款、充值详情 | 动态审批时间线、处理状态、退回重提 |
| 19 | 后台 | 批量订购 | 参数确认、上传、逐行结果和金额汇总 |
| 22 | 后台 + 代理端 + C端 | 临期列表、首页提醒 | 15/7/3 天分级、续费跳转、到期后自动消失 |

---

## 八、站内消息

- 登录后和进入后台布局时立即获取未读数，之后每 30 秒轮询。
- 页面不可见时暂停，恢复时立即刷新。
- 铃铛数字超过 99 显示 `99+`。
- 通知点击只按受控的 `ref_type + ref_id` 路由表跳转，不接受后端返回任意 URL。
- 标记已读失败不阻止查看业务详情，但需要在下次轮询时恢复真实未读状态。
- 通知正文按纯文本展示；若未来支持富文本，必须使用受控模板和统一净化，不直接渲染任意 HTML。

---

## 九、权限与敏感数据

- 菜单和按钮根据登录返回的权限控制可见性，但后端权限校验是最终依据。
- 审批人资格由任务接口返回，前端不根据角色名称推导。
- 导出字段由后端返回允许字段集合；前端只能在允许集合中选择。
- 退款凭证、充值凭证、身份证、营业执照和审批附件使用现有对象存储上传流程，不提交本地路径或长期公开 URL。审批附件额外提交清理后的原文件名作为展示快照。
- 列表和详情对无权限与不存在统一展示，避免通过前端文案泄露资源存在性。

---

## 十、停机发布

1. 发布前进入维护模式，前端统一展示维护页并停止提交写请求。
2. 维护窗口内执行数据库迁移，同时发布 API、Worker/Relay 和前端静态资源。
3. 初始化并启用退款、充值流程定义和业务绑定，执行存量待审批单回填。
4. 前端只调用任务级审批 API，不保留退款或线下充值的业务单级通过/驳回按钮，也不保留线下充值“确认入账”按钮。
5. 人工验证登录、菜单权限、流程发起、存量历史展示、待办、审批详情、退回重提和业务处理状态。
6. 验证通过后解除维护模式；失败则在开放访问前回滚整套应用版本。

前端必须容忍新增响应字段且不依赖字段顺序，但本次不要求支持旧后端与新前端或新后端与旧前端交叉运行。

---

## 十一、待前端仓库确认

以下内容不影响当前接口和交互评审，但实施前必须在前端仓库确认：

- 后台、代理端和 C 端分别使用的框架版本与目录结构。
- 现有权限指令、请求封装、上传组件和导出 Hook 的真实名称。
- 是否已有通用任务轮询组件和流程时间线组件。
- 实际菜单路由和按钮权限编码。
- 表格是否支持服务端返回的动态导出字段配置。

确认后只补充实现映射，不改变本文已经评审通过的业务状态和 API 契约。
