13 KiB
十月第 1 批后台适配设计
Context
本仓库为 Vue 3/TypeScript 后台,HTTP 服务使用 BaseService 与 Axios,页面已有业务权限、状态映射、详情组件、异步导入导出任务。原范围排除 C 端;2026-10-14 用户追加代理扫码注册页及同一注册接口的密码校验,其余 C 端接口和页面仍排除。后台本人改密虽然使用 /api/auth/password,仍属于本次后台适配。
本设计依据十月第 1 批说明、用户最新确认和当前代码。用户确认不提供最新 OpenAPI;2026-10-14 修正为新密码允许特殊符号,恢复四类至少三类。实施已获批准,结果详见实施记录,没有调用真实后台写接口。
代码证据与修改路径
| 依据/代码证据 | 当前差异 | 修改路径 |
|---|---|---|
M3;src/types/api/order.ts、src/api/modules/order.ts |
详情与列表共用 Order,缺三项支付信息与支付记录 |
Order 补公共字段,另建 OrderDetail 与支付记录类型,详情服务改用详情类型 |
M8;employeeCollectionDisplay.ts、核销申请列表/详情 |
状态仅 0~3,可重提仅状态 2;提交状态只读名称 | 补终态 4、状态值映射与恢复/重提判断,覆盖账单关联申请 |
| M14;退款/充值/提现类型与状态映射 | 缺退款 7、充值 7、提现 5;旧重提及补发条件不认识终态 | 各业务独立扩展类型、筛选、标签和可执行操作 |
| M14;后台代理注册查询类型/详情 | 筛选仅 0~2,恢复操作仅看 recoverable |
补状态 3,并在业务终态下优先隐藏恢复 |
| M1;账号、客户账号、店铺、企业表单及本人改密弹窗 | 仍使用 8~32 或 6~20;旧密码也有长度规则 | 新密码使用专用校验,旧密码只保留必要输入校验 |
M1;AccountService.updateAccountPassword |
独立改密发送 { password },说明要求 { new_password } |
按第 1 批说明修正独立改密请求,不误改其他接口字段 |
M12;换货创建/确认完成、apiError.ts |
无 1202 定制反馈;错误归一化不暴露业务 data,换货 catch 可能输出错误对象 | 在换货操作定向提取 code/msg/message/data.phone,只在提示中展示号码,不记录完整错误对象 |
| M16;预警规则与记录类型/页面 | 规则依赖已删除的 real_data_mb;记录未定义三项 MB 字段 |
只移除规则响应引用,补记录快照并明确 MB 单位 |
| M2;业务员导入页 | 仍写「业务员登录账号」且未注明只填手机号 | 同步说明及已有前端模板,保留逐行失败明细 |
| M23;设备导入任务页 | IMEI 被列为可选,已支持 failed_items |
改说明,复用失败明细,不改 Excel 模板结构 |
Goals / Non-goals
- Goals:让后台显示、筛选、请求字段和可执行操作符合本批次说明;保留既有权限、表单内容、财务快照和导入导出流程。
- Non-goals:除代理扫码注册密码规则外的 C 端适配、后台接口实现、新审批机制、新页面架构、自动解绑手机号、前端重算预警或余额、替换设备导入模板、引入测试框架。
Decisions
1. 订单详情类型与支付状态隔离
公共 Order 接收三项字符串字段,列表与创建响应仍使用公共类型;详情增加独立 payments 数组。支付记录状态 0~3 与订单 PaymentStatus 的 1~4 含义不同,使用独立枚举/映射,不能复用。
支付记录使用后端顺序,不自行筛掉失败或待支付记录;金额用已有分转元格式化,paid_at、expire_at 空值显示 -。渠道码映射 wechat 为微信直连 v3、wechat_v2 为微信直连 v2、fuiou 为富友;支付方式微信/支付宝与技术渠道分开展示,未知非空渠道保留原值。公共字段为空串显示 -,不能据此虚构支付信息。
2. 业务终态优先于恢复标志
六个业务各自定义终态,禁止跨业务共用数值。恢复入口使用「不是本业务审批提交失败终态 + 后端允许恢复 + 原权限允许」共同判断;即使陈旧响应仍返回 recoverable=true,终态也不得显示恢复按钮。
「提交结果未知」不能只凭提交状态转换成业务失败,保留原后端恢复资格判断,不扩大恢复权限。终态下隐藏恢复/补发和不适用的审批操作,查看详情、凭证等只读操作保留。
重新发起复用既有表单和文档规定的接口:核销/退款/提现使用原业务重提接口,线下充值创建新单,提现资料提交新版本。代理注册仅提示申请人重新扫码,后台不调用 /api/c/v1、不补建后台代注册接口。涉及预占/冻结金额时重新加载账单或佣金概览,前端不乐观加减财务数据。
核销审批提交状态使用 approval_submission_status 的 0 待提交、1 提交中、2 已提交、3 提交失败、4 结果未知。名称字段存在时可使用后端名称,但字段为空时需按真实数值回退,0 不能因 falsy 判断显示成缺失。
3. 新密码校验专用化
使用新登录密码专用工具,避免影响通用校验与其他密码。按最新修正,长度 8~12,允许英文字母、数字及所有可打印半角 ASCII 符号,四类至少三类;空白、中文、emoji、控制字符和非 ASCII 字符拒绝。不静默 trim。
字符范围为 ASCII 0x21~0x7E,按大写、小写、数字和标点四类计数,至少三类。Admin@12345、ABC1234!、abc1234!、Abcdefg! 均有效;abcd1234、ABCDEF!! 仅两类无效。
顶栏 z-index:100、侧栏 z-index:101 导致嵌在顶栏内的改密遮罩被侧栏压住。仅给改密弹窗加 append-to-body,不全局提高顶栏层级或修改所有弹窗;由 Element Plus 管理完整遮罩、焦点和关闭行为。
新密码和确认密码统一长度限制、规则说明与一致性校验;本人改密 old_password 不设新规则的 maxlength 或类别限制,旧登录表单不收紧。账号编辑目前没有密码输入则不新增;若既有调用传递可选 password,仅非空新值需要校验,未修改密码时不发送空串。
后台七个契约:
| 场景 | 接口 | 新密码字段 |
|---|---|---|
| 本人修改 | PUT /api/auth/password |
new_password |
| 创建账号(含店铺/企业下的客户账号) | POST /api/admin/accounts |
password |
| 修改账号 | PUT /api/admin/accounts/{id} |
可选 password |
| 独立修改账号密码 | PUT /api/admin/accounts/{id}/password |
new_password |
| 创建店铺初始账号 | POST /api/admin/shops |
init_password |
| 创建企业 | POST /api/admin/enterprises |
password |
| 修改企业密码 | PUT /api/admin/enterprises/{id}/password |
password |
用户明确追加的公开代理注册使用原 POST /api/c/v1/agent-distribution-registrations 和 password 字段。表单复用 createNewLoginPasswordRule(),注册服务发送前复用 getNewLoginPasswordError();保留其他入参和 withToken: false。页面将输入上限改为 12,完整规则独立显示在输入框下,并关联 aria-describedby,避免移动端 placeholder 截断规则。强度反馈仅按共享校验判定合格/未合格,空格和中文不能被计作有效特殊符号;长错误文案参与正常布局,不覆盖下一个表单项。
用户进一步追加注册失败反馈:仅 registerAgent 请求设 errorMessageMode: 'none',页面处理非零业务响应与 HTTP 异常。1050/1001 不暴露企业微信模板配置细节,统一「注册失败, 请联系管理员」,其余错误保留具体业务原因或正常网络降级;不记录密码或完整错误对象。提交进行中阻止再次提交,失败保留表单。公共 HTTP、短信与其他服务的错误提示保持原状。
公共表头 Sortable 报错作为既有列设置功能的生命周期修复:改用 useDraggable(..., { immediate: false }) 和真实 HTMLElement ref,仅在列设置 Popover 已打开且进入后,目标仍连接文档时启动;关闭、卸载及 KeepAlive 停用销毁实例,晚到回调不得重新启动。列排序仍通过原 columns model 写回,勾选状态和其他表头功能不变。
错误消息兼容项目既有 msg 与说明中的 message,优先展示后端提供的可读字段级原因;不改变 401 等既有统一处理,不重复弹错、不输出密码值。
4. 换货 1202 定向错误处理
创建换货和确认完成同时覆盖 HTTP 200 的非零业务码与 Axios HTTP 错误响应,不假定只有一种承载形式。在受影响的两个服务调用范围关闭重复默认提示,局部共享处理器处理 1202,其余错误仍按既有统一错误分类/文案展示。
1202 弹窗原样使用业务 msg,不拼接号码或固定替换文案。只有响应明确带有效字符串 data.phone 时才允许带参跳转;data=null 的已换货等拒绝仅显示后端文案和「知道了」。只以文本渲染,不拼成 HTML。
手机号冲突且具备原关联页面查看权限时提供跳转;无权限或新资产标识缺失时仅提示,不扩大权限。禁止自动解绑。完整号码不额外写日志或本地存储;用户主动跳转的 query 参数是已明确授权的例外。
创建失败保留资产/原因等字段;完成失败重新加载换货单,保持后端「已发货待确认」事实,不乐观标记完成。解除后由用户再次提交。取消只关闭提示,不当作解绑或换货成功。
用户追加快捷定位:创建换货冻结当前新资产上下文,确认完成使用原单新资产标识;手机号只能取当前错误响应 data.phone,不得根据历史数组推断其他 1202 是手机号冲突。主动跳转通过 asset_identifier 和 phone query 传递目标。关联页按 1 页/20 条加载,仅选中精确匹配有效行,继续原原因和二次确认。
通过 ArtTable 透传清空/勾选方法,数据更新后 nextTick 完成实际选择。缓存重入和路由参数变更重置查询,请求序号防止过期响应覆盖;手工筛选/翻页、解绑后刷新清除旧选择。批量结果保持后端布尔契约,仅展示中文「解绑成功/解绑失败」。原查看与批量解绑权限不变。
5. 预警只展示快照,不重算阈值
删除 PackageTrafficAlertRuleItem.real_data_mb 与规则行/详情/列设置依赖。来自 /api/admin/packages 的套餐选项 real_data_mb 保留,套餐选择与规则参数校验不变。
记录列表/详情接收后端 threshold_mb、used_mb、limit_mb,用 MB 显示两位小数;0 显示 0.00,缺失/null 显示 -。标签分别为阈值流量、已用流量(含加油包)、总流量(含加油包)。不使用当前套餐额度重新计算历史 threshold_mb,不把新字段作为新的请求入参或筛选项。
6. 导入说明与后端结果保持一致
CSV 只同步新表头和手机号说明,不为旧表头做客户端转换、不将用户名转为手机号。发现内置模板时同步,否则仅改当前说明,任务明细保留原后端原因。
设备导入保持原下载文件与列序,将说明中的 IMEI 移到必填列;只把空值规则交给后端逐行处理,不为单行缺失拦截整个文件,不添加格式或去重限制。
Risks / Trade-offs
- 无最新 OpenAPI:按用户确认,以第 1 批说明实施,不要求补文件;联调发现真实接口与说明不符时先反馈,不自行猜测或声称已通过联调。
- 密码口径以最新修正为准:允许半角特殊符号并按四类至少三类校验;如后端字符集合仍有不同约束,联调时反馈用户。
- 恢复旧规范与新业务终态冲突:文档注明差异,实施时优先按本批次终态处理,结果未知继续守原恢复规则。
- 改错密码/流量范围:专用新密码工具和独立规则/套餐类型限制修改范围,回归旧密码、操作密码、WiFi 密码、套餐额度。
- 换货错误提示重复或泄漏号码:两个请求定向接管提示,共享处理器保留其他错误行为,删除受影响分支的完整错误输出。
- 财务状态不同步:重提和失败后重新拉取后端数据,不修改本地冻结金额来模拟后端效果。
- 仓库未配置可直接运行的单测脚本:先检查现有测试方式,以针对性逻辑检查、类型检查、编码检查和人工联调为验收,不自动引入新框架。
Migration plan
提案获批后,依据第 1 批说明和用户最新确认,依任务清单按公共类型/规则、各页面、联调顺序实施;前端与对应测试后端一起验收。无数据库迁移、权限迁移、历史导出重生成或自动数据修复。
回退只回退本次业务代码,不触及原有提案和用户改动;后端若仍保留新校验及终态,旧前端将重新出现展示与提交问题,因此上线/回退需确认前后端契约匹配。
已确认事项
- 没有最新
admin-openapi.yaml,不要求提供,以第 1 批说明实施。 - 新密码 8~12 位,大写、小写、数字、半角特殊符号至少三类,禁止空白和中文。
- 用户明确追加的代理扫码注册密码规则纳入;其他
/api/c/v1和 C 端页面排除。后台代理注册失败仍仅展示重新扫码申请指引,不代发 C 端申请。
当前没有待确认的需求问题。用户已批准实施,后台代码已适配;真实后端联调项继续在任务清单保留未完成状态。