前端验收清单(统一登录门户)
目的:把门户的每一个功能都走一遍,逐项对照"预期结果"判断是否符合预期。
被测对象:tools/portal.py(统一登录门户),默认 http://127.0.0.1:8101
时点:2026-09-12
证据口径:标 ✅实测 的项是本轮真实跑过并确认的;标 ⚠️按契约 的项是照接口定义推断的
(沙箱里不便反复写业务数据,留给你点的时候确认)。
0. 启动与前置
0.1 前置(不满足会直接显示原因,不会静默)
| # |
项 |
命令 / 检查 |
预期 |
| 0-1 |
依赖服务 |
MySQL、Redis 可用(Docker Desktop 要在跑,Milvus 才可用) |
门户顶部不出现"平台初始化失败"红条 |
| 0-2 |
演示账号 |
python tools/seed_test_rbac.py 然后 python tools/set_user_password.py |
五个账号都能登录;口令脚本非幂等,重复执行等于重设密码 |
| 0-3 |
停常驻 Worker |
确认没有 python -m app.worker 在跑 |
否则客服对话会被抢队列,页面一直转圈 |
0.2 启动
1. 登录与角色分流
五个演示账号(点"演示账号"按钮可自动填入):
| 账号 |
密码 |
角色 |
预期进入 |
预期权限数 |
cust_t |
123456 |
customer |
客服 |
20 |
risk_t |
666666 |
risk_operator |
风控工作台 |
10 |
offsite_t |
offsite123 |
operator |
运营工作台 |
2 |
admin_t |
88888888 |
admin |
权限管理 |
50 |
advisor_t |
abc12345 |
advisor |
投顾工作台 |
28 |
角色是每次请求现查库的(令牌里只有 sub)。改了库里角色,重新登录即生效,不用重启门户。
2. 客户 · 客服视图(cust_t)
| # |
操作 |
预期结果 |
| 2-1 |
输入"赎回基金多久到账?"发送 |
气泡里出现回答(如"货币基金T+0或T+1到账…QDII T+7、T+10"),下方标签显示意图(如 faq) ✅实测 |
| 2-2 |
看回答末尾 |
附合规提示:"本内容仅为投资风险参考,不构成任何直接投资建议…" ✅实测 |
| 2-3 |
问一个答不了的(如"帮我下单") |
Agent 引导拨打客服热线;若判定需人工,标签显示已转人工 ✅实测(问"赎回费怎么算"得到引导话术) |
| 2-4 |
点「我的画像」 |
返回当前客户的记忆画像(HTTP 200) ✅实测 |
| 2-5 |
点「我的画像候选」 |
返回候选列表;没有候选时显示"暂无候选(HTTP 200)"而不是报错 ⚠️按契约 |
| 2-6 |
候选里点「确认」/「拒绝」 |
HTTP 200,状态变更;再刷新列表状态已更新 ⚠️按契约(本机暂无候选数据) |
| 2-7 |
点「转人工」 |
弹出说明输入框 → 确认后 HTTP 202,返回 handover_id 与 status=pending ✅实测 |
| 2-8 |
转人工后,用管理员看"客服转人工工单" |
新工单出现在队列里 ✅实测(ticket-d8c526a9…) |
2-7 的实现细节:门户会先调 POST /api/v1/conversations 真实建会话(201)再转人工。
早期版本用自己编的 session id,会得到 404「会话不存在」。
3. 员工 · 风控工作台(risk_t)
| # |
操作 |
预期结果 |
| 3-1 |
进入即自动加载"总览" |
数字卡片;数据范围 all(能看全部客户的预警) ✅实测 |
| 3-2 |
点「刷新总览」 |
同上,HTTP 200 ✅实测 |
| 3-3 |
点「拉取预警列表」→ 看表格 |
预警号 / 客户 / 规则 / 等级 / 状态 / 操作;空库时提示"可先点触发一次扫描" ✅实测 |
| 3-4 |
点「触发一次扫描」 |
HTTP 200,body.code=0(这条以前会因缺幂等头报 422,已修) ✅实测 |
| 3-5 |
点「生成日报」 |
HTTP 200,返回日报内容 ⚠️按契约 |
| 3-6 |
对某条预警点「确认」 |
二次确认后 HTTP 200,状态变为已确认;审计里会留痕 ⚠️按契约(写操作) |
| 3-7 |
点「升级」/「解决」 |
同上,各自状态流转 ⚠️按契约 |
| 3-8 |
点某个默认不存在的预警号 |
404,提示资源不存在 —— 属正常 fail closed ⚠️按契约 |
| 3-9 |
用客户账号访问风控接口 |
403 缺少操作权限(risk_t 能看,cust_t 不能) ✅实测(客户访问 /admin/roles 为 403) |
⚠️ 注意:risk_t 有 audit:read,所以它访问 /api/v1/admin/roles 是 200 而不是 403 ——
这是种子设计如此,不是越权漏洞。
4. 员工 · 运营工作台(offsite_t)
| # |
操作 |
预期结果 |
| 4-1 |
进入即加载"邮箱状态" |
数字卡片,HTTP 200 ✅实测 |
| 4-2 |
点「拉取邮件列表」 |
表格(邮件 ID / 主题 / 状态 / 操作);邮箱未配置时返回空列表或错误说明,不是白屏 ✅实测(HTTP 200) |
| 4-3 |
点某封邮件的「识别字段」 |
返回识别结果 JSON ⚠️按契约(需库里有邮件数据) |
| 4-4 |
点「删除」邮件 |
二次确认后写操作;审计留痕 ⚠️按契约 |
| 4-5 |
点「触发邮箱恢复」 |
二次确认后 HTTP 200 ⚠️按契约 |
| 4-6 |
在"单据处理"填一个真实存在的 task_id,点「识别字段」「规则结果」 |
返回该单据的字段与规则判定 ⚠️按契约 |
| 4-7 |
填一个不存在的 task_id |
404 资源不存在,页面上原样显示 —— 正常 ⚠️按契约 |
| 4-8 |
点「确认单据」/「重试识别」/「创建通知」 |
二次确认后写操作;审计留痕 ⚠️按契约 |
| 4-9 |
点「重算结算统计」 |
二次确认后 HTTP 200 ⚠️按契约 |
运营为什么只有 2 项权限却能用:场外线的服务层用的是角色门槛
{"operator","risk_operator","admin","super_admin"}(offsite_fund_service.py:2600),
不是权限码。那 2 项是 offsite:write 和 financial:nl2sql:read。
换句话说:"看不到运营界面"以前是前端没做,不是权限问题。
5. 管理员 · 权限管理(admin_t)
5.1 角色与权限
| # |
操作 |
预期结果 |
| 5-1 |
进入即加载角色卡片 |
每个角色显示 权限数 / 角色名 / user_count ✅实测(GET /admin/roles 200) |
| 5-2 |
点任一角色卡片 |
列出该角色的权限码(药丸标签)+ 角色详情 ✅实测(customer 20 项) |
| 5-3 |
对照第 1 节的权限数 |
与登录时顶栏显示的权限数一致 |
| 5-4 |
输入 9001 点「查询该用户的角色」 |
返回 cust_t → customer 的解析结果 ✅实测 |
平台只提供只读查询:改权限要发布新的 config_release,没有直接写接口 ——
这是设计(配置受版本控制),不是功能没做完。页面上也这么写了。
5.2 审计与工单
| # |
操作 |
预期结果 |
| 5-5 |
点「刷新」审计流水 |
时间 / 动作 / 操作者 / 结果;做过写操作后能看到刚才那条 ✅实测(200) |
| 5-6 |
点「刷新工单」 |
客户在第 2-7 步建的工单出现在这里(工单号 / 来源 / 优先级 / 原因 / 状态)✅实测 |
| 5-7 |
点「列出知识文档」 |
文档清单(ID / 标题 / 状态)⚠️按契约(需 KB 有数据) |
5.3 推广材料审核
| # |
操作 |
预期结果 |
| 5-8 |
填投顾给你的任务单号,点「查任务」 |
返回任务详情,若已有 approved/sent 版本会自动填进版本号框 ✅实测 |
| 5-9 |
填 material_version_id,点「通过」 |
二次确认后 HTTP 200 code=0;此后投顾才能投递 ✅实测(版本 19 通过) |
| 5-10 |
点「退回修改」/「拒绝」 |
同样 200,状态流转 ⚠️按契约 |
6. 投顾 · 投顾工作台(advisor_t)
6.1 投资目标与方案
| # |
操作 |
预期结果 |
| 6-1 |
客户 ID 填 9001,点「查投资目标」 |
200,返回目标(目标区间、基准)—— 前提是 9001 在你名下且已建过目标 ✅实测(4.5000 - 8.0000、沪深300) |
| 6-2 |
改填一个不在你名下的客户 ID |
404「客户不可访问」 —— 最小权限,data_scope=own_customers 生效 ✅实测设计如此 |
| 6-3 |
点「已发布方案」 |
200,返回已发布方案列表 ✅实测 |
| 6-4 |
点「跑组合分析」 |
二次确认后 200(请求体是空对象 {},多传字段会 422)✅实测 |
| 6-5 |
点「生成资产配置」 |
同上 ✅实测 |
6.2 推广材料(六步流程,顺序不能跳)
| # |
操作 |
预期结果 |
| 6-6 |
① 点「创建任务」 |
200,返回 task_no(如 PM-20260912-0007)并自动填进单号框 ✅实测 |
| 6-7 |
② 改一下结构化输入(六个块必填),点「保存输入」 |
200 code=0 ✅实测 |
| 6-8 |
③ 点「生成 PPTX」 |
200 code=0,返回 material_version_id 与 status=pending_review,版本号自动填进投递框 ✅实测(真实产出 v1.pptx) |
| 6-9 |
若没填费率就点生成 |
body.code=422「材料内容未通过合规校验」,findings 里是 fee_structure.incomplete(severity=block),任务被置为 compliance_failed ✅实测 |
| 6-10 |
④ 让管理员在 5.3 审核通过 |
见 5-9 |
| 6-11 |
⑤ 点「投递」(投顾 id 填 9020) |
200 code=0 ✅实测 |
| 6-12 |
⑥ 点「查询任务」 |
200,status="sent",含 material_version(版本号、pptx 路径)✅实测 |
| 6-13 |
没投递就查询 |
404「该材料尚未发送给当前投顾」 —— 这是合规设计,不是故障;页面会追加提示告诉你怎么走完 ✅实测 |
| 6-14 |
点「合规检查结果」 |
列出 findings(通过的会显示 overall.pass)✅实测 |
⚠️ 两条必须知道的约定:
- 费率七项必须非空(
subscription_fee/purchase_fee/redemption_fee/sales_service_fee/
management_fee/custody_fee/client_maintenance_fee),否则合规规则阻断生成。
骨架里填的是「待填写」占位,真实材料必须换成真实费率。
- 骨架刻意不预填任何业绩数字:
performance_info 的业绩字段全部可选且带
show_product_performance 开关,关掉即可 —— 编造业绩是红线。
7. 通用行为预期(跨视图)
| # |
情形 |
预期表现 |
| 7-1 |
业务失败也返回 HTTP 200 |
本平台把业务错误放在 body.code(如生成失败 HTTP 200 + code=422)。门户按 body.code 判成败并标红 ✅实测 |
| 7-2 |
403 |
"当前角色权限不足(平台按设计 fail closed)",原样显示不隐藏 ✅实测 |
| 7-3 |
404 |
显示 message。注意 SESSION_NOT_FOUND 被三个异常类共用,可能是"会话不存在"、"客户不可访问"或"知识文档不存在",只能看 message 区分 ✅实测 |
| 7-4 |
422 |
报文格式问题,error.field_errors 会指出具体字段 ✅实测 |
| 7-5 |
写操作 |
一律二次确认(confirm),避免误点改数据 ✅实测 |
| 7-6 |
令牌 |
只存在服务端,浏览器拿不到;前端只有一个随机会话号 ✅设计 |
| 7-7 |
空数据 |
显示"暂无…(HTTP xxx)"或原始返回,不白屏 ✅实测 |
8. 已知限制(先说明,免得当成 bug)
- 权限界面只读 —— 平台没有写接口,改权限走
config_release 发布;
- 运营工作台的"单据处理"需要一个真实的 task_id —— 本机没有场外单据数据时,识别/确认/通知只能看到 404,属正常;
- 组合分析与资产配置只对空请求体有效(
{},additionalProperties:false);
- 风控日报/处置类写操作会在库里留数据与审计,验收时建议用专用库或事后清理;
- 门户是单进程工具:会话存内存,重启门户需要重新登录。
9. 验收记录表
| 章节 |
项数 |
通过 |
不符合预期 |
备注 |
| 0 启动与前置 |
4 |
|
|
|
| 1 登录与分流 |
3 |
|
|
|
| 2 客户 · 客服 |
8 |
|
|
|
| 3 员工 · 风控 |
9 |
|
|
|
| 4 员工 · 运营 |
9 |
|
|
|
| 5 管理员 · 权限 |
10 |
|
|
|
| 6 投顾 · 投顾台 |
14 |
|
|
|
| 7 通用行为 |
7 |
|
|
|
| 合计 |
64 |
|
|
|
发现不符合预期的项,记下章节号 + 当时的 trace_id(响应里带),可以直接定位到那一次请求。