Commit Graph
14 Commits
Author SHA1 Message Date
lzf_0626 ae7a89f33d 投顾工作台:修推荐结果渲染(幂等响应形状归一)+ 对齐门户版式规范
投顾页「生成推荐方案」拿不到产品的根因:该端点标了 idempotent,浏览器必带
Idempotency-Key,而后端此时返回的是 {data:{content_id, status, plan:{...}}, meta}
—— 真正的文档嵌在 data.plan 里。此前前端只处理了不带键时的裸文档形状。

- api-client:ADVISOR_RECOMMEND 撤掉 raw(带幂等键时确为信封,需正常解包);
  ADVISOR_ALLOCATION / ADVISOR_ANALYSIS 保留 raw(不标幂等,返回裸文档)
- actions-module:新增 normalizeRecommend(),把「信封 + plan 嵌套」与「裸文档」
  两种响应归一成一种形状;结果卡片显示方案编号与待审核状态
- 投顾页:hero 大图 + 4 张概览指标卡 + 左栏/主区两栏构图
- 投顾页:页头常显「退出登录」按钮;新增风评预警数、快捷问句按钮
- 投顾页:动作名统一为「生成推荐方案」(对齐软件需求文档 5.4 ⑦)
- 管理台「待审投顾内容」空态文案同步改名
- 前端模块相对 import 加 ?v= 版本号:改文件内容而 URL 不变会被浏览器缓存挡住
2026-09-14 22:17:39 +08:00
yuancong_0626 14e027f781 合并yy与远程qyqy_develop并保留业务优先级 2026-09-14 18:16:33 +08:00
yuancong_0626 2548c39c6b 袁聪的最后一次完善更新 2026-09-14 18:13:10 +08:00
lzf_0626 e6d74059f2 修复员工工作台顶部导航重复(入口 JS 被引两次)
## 现象

打开 `employee-console/workspace`(平台治理),页面上出现**两份一模一样的顶部栏**:
南方财富 / 模拟基金服务 / 平台治理 / 风控中心 / admin_t 管理员 —— 连同页脚一起各两份。

## 根因:同一个入口 JS 被引了两次,且 `?v=` 不同

`app/static/portal/employee-console/workspace/index.html` 里曾同时存在:

    <script type="module" src=".../workspace.js?v=20260913-3"></script>
    <script type="module" src=".../workspace.js?v=20260914"></script>

浏览器按**完整 URL** 去重,两条不同 query 被当成**两个模块**、**各执行一次**。
入口里的 `mountShell()` 因此跑了两次,而它当时是
`document.body.insertAdjacentHTML('afterbegin', ...)` —— **无条件插入**,
于是 header 与 footer 各插两份。

来源是合并事故(`git blame` 定位):

| 行 | 提交 | 作者 |
|---|---|---|
| 旧 | `e31420df` | 卿云秋月(把版本号改成 `20260913-3`)|
| 新 | `f5d1b246` | 张胜宇(把版本号改成 `20260914`)|

两人各自把**同一行**的版本号换成新的,合并时两边都被保留,成了两行。
那个提交的信息是 "merge ... and retain risk review updates" ——
"retain" 在这里保留错了地方。

## 修法(两侧都堵)

1. **HTML 收敛成一行**(保留较新的 `?v=20260914`,与 `workspace.js` 内部
   `api-client.js?v=20260914` 一致),并就地写明"改版本号是替换这一行、不是新增一行"。
2. **`mountShell` 加幂等保护**:已有 `.site-header` 就直接 return。
   之所以不满足于只修那个 HTML —— 这个 bug 的症状很难反推到原因
   (页面看起来只是"多了一块"),而以后谁加缓存版本号时很容易再犯一次。

## 防回归(两条测试,都做过负面验证)

- `test_no_portal_page_includes_the_same_script_twice`:扫 `app/static/portal` 下
  **19 个页面**,把 `<script src>` 去掉 query 后比对,同一入口出现多次即失败。
  负面验证:把重复行临时放回去,测试**精确报出**
  `employee-console\workspace\index.html: ['/static/portal/employee-console/workspace/workspace.js']`,
  恢复后通过。
- `test_mount_shell_is_idempotent`:断言 `app-shell.js` 里有那句幂等判断。

全站扫描确认**只有这一处**,不是批量问题。

## 实测

- `GET /portal/employee-console/workspace/` -> 200,页面里 `workspace.js` **只出现一次**
  (`?v=20260914`);静态 HTML 中 `site-header` 出现 **0 次**(确认由 JS 注入,
  所以 JS 执行一次就只插一份)
- `pytest tests/unit/api/test_portal_frontend.py` -> **43 passed**(41 + 新增 2 条)
- `ruff check` -> All checks passed

## 一点说明

这次是"改同一个版本号"的合并冲突处理失误,属于**流程问题**而非个人疏忽:
两边都想把缓存版本号推新,冲突解决时很容易两边都留下。
测试补上之后,这类错误会在 `pytest tests/unit` 里当场暴露。
2026-09-14 12:06:38 +08:00
zhangshy 4b7ee13cf5 修复管理员工作台函数缺少闭合大括号 2026-09-14 10:56:45 +08:00
zhangshy baecb89bd4 预警队列调整为每页十条 2026-09-14 10:40:41 +08:00
lzf_0626 e096ffab22 修复投顾工作台白板:补上模块拆分时漏掉的 import
## 问题(合并进来的故障,不是本次会话改坏的)

合并 `origin/qyqy_develop`(f5d1b24 / 3134fe5)后 `pytest` 红了一条:
`test_advisor_dashboard_is_composed_from_feature_modules`。

查下去发现是**拆分做了一半**:

- 新建了 `advisor-config.js` / `actions-module.js` / `published-module.js`
- 把 `CONTENT_TYPE_LABELS`、`actionLabels`、`resultMessages` 从 `dashboard.js` 删掉了
- **但没有在 `dashboard.js` 里 import 它们**,`dashboard.js` 仍是拆分前的内联版本,
  第 39 行还在用 `CONTENT_TYPE_LABELS`

后果不只是测试红:投顾工作台一打开就 `ReferenceError: CONTENT_TYPE_LABELS is not defined`,
页面渲染不出来;同时那两个新模块是**死代码**(没有任何地方 import 它们)。
`index.html` 是单入口(只加载 `dashboard.js`),所以模块必须由它 import。

## 修法:把重构接完,而不是把测试改掉

- `dashboard.js` 变成薄组合层:挂 shell、取 DOM、组合两个模块,其余逻辑不再内联
- `advisor-config.js` 收拢 `GOAL_STATUS_LABELS` / `BOOK_STATUS_LABELS`(原来内联在 dashboard.js)
- `actions-module.js` 接管「目标确认与方案书」
- `published-module.js` 直接可用

⚠️ 关键点:`bind()` 会给**所有** `[data-action]` 按钮挂 `open()`,而 `actions-module.js`
原先不认识 `goal-status` —— 直接接线会让它掉到最后一行的兜底分支、被当成
「资产配置」发出去(点"目标确认与方案书"却收到一份配置建议)。
所以把「目标确认与方案书」一并做进 `open()` 的分支里,并在两处留了注释说明这个约束。

「目标确认与方案书」这条功能本身要保留:此前工作台只有 4 个"生成草案"操作 + 1 个只读列表,
而确认目标与查看方案书这两个端点**有接口没入口**,导致目标永远停在 `pending_confirmation`、
方案书永远停在 `pending`(实测客户 9001 正是如此)。

## 防回归:tools/check_portal_modules.py(新)

上面那个 bug **不能靠现有断言发现** —— 那些测试断言的是"某个字符串在文件里出现",
而这里的问题是"定义搬走了、使用处还在",浏览器里才炸,Python 测试全绿。

新检查做四件事:`node --check` 按 ES module 解析语法、相对 import 的目标文件存在、
import 的名字在目标文件里真有 `export`、**用到的全大写常量必须有来源**。

第 4 条是抓这个 bug 的关键。写的时候踩了两次坑,都已修正并记录在文件里:

1. 第一版用 `(?<![\w.$])` 排除属性访问、却把**模板字符串整体**当字符串剔除了 ——
   而 `CONTENT_TYPE_LABELS[row.content_type]` 恰好写在模板字符串里,
   于是漏报、检查全绿。现在只剔除单双引号字符串,模板字符串保留(`${}` 里是真代码)。
2. 用负面验证确认它真的有效:把 `published-module.js` 的 import 拿掉后,
   检查精确报出 `使用了 'CONTENT_TYPE_LABELS',但既没 import 也没在本文件声明`(exit 1);
   恢复后 exit 0。没有这一步,这个检查就是个摆设。

同时接进测试:`test_portal_feature_modules_have_consistent_imports` 调用它,
保证以后每次 `pytest tests/unit` 都会执行。

## 实测

- `pytest tests/unit tests/contract` -> **1400 passed, 2 skipped, 0 failed**
  (合并后未修时是 1399 passed + 1 failed)
- `pytest tests/unit/api/test_portal_frontend.py` -> 39 passed(38 + 新增 1 条)
- `python tools/check_portal_modules.py` -> 全部通过;负面验证 exit 1
- `ruff check app tests tools alembic hq.py` -> All checks passed
2026-09-14 02:07:44 +08:00
张胜宇 f5d1b24618 merge qyqy_develop and retain risk review updates 2026-09-14 01:41:02 +08:00
zhangshy 2a3146e050 增加风控列表总数并优化站内提醒 2026-09-13 23:51:45 +08:00
zhangshy 38fe6f3689 合并主项目最新改动并解决风控前端冲突 2026-09-13 23:22:12 +08:00
zhangshy 4f75d32ea1 优化风控详情展示与前端交互 2026-09-13 23:19:52 +08:00
张胜宇 3325232e2a feat(portal): complete advisor workspace operations 2026-09-13 23:04:35 +08:00
zhangshy 09c80575b7 延长风控手动扫描前端超时 2026-09-13 21:08:57 +08:00
张胜宇 e38ece32bf 前端提交 2026-09-13 15:56:54 +08:00