Parcourir la source

docs(spec): 报告上传页关联商品卡片区(去重可购买)+ 成员4列核验 任务书

Agnes Agent il y a 6 jours
Parent
commit
896fbabb59

+ 79 - 0
docs/superpowers/specs/2026-11-06-report-upload-product-cards.md

@@ -0,0 +1,79 @@
+# 报告上传页:下方新增「关联商品」卡片区(去重,可点击购买)+ 成员选择固定四列
+
+> 任务编号:待派发(cfc-frontend)
+> 日期:2026-11-06
+> 触发:用户 `@skill:tdd-orchestrator` "小程序上传报告页面下面,增加关联的商品,可直接点击购买。注意报告对应的商品可能会有重复。报告上传页面的成员选择,固定为四列"
+
+## 一、需求
+
+1. **报告上传页下方增加「关联的商品」,可直接点击购买**
+   - 报告类型(菌群检测报告 / 素质测评等)已在后台 `ReportTypeManagement.vue` 配置「关联商品」(`report_type_registry.linked_product_id`,10 个类型)
+   - 页面上要新增一个商品卡片区,展示**已配置关联商品**的报告类型对应的商品,点击可购买
+   - **注意:报告对应的商品可能会有重复** —— 多个报告类型可能关联到同一个商品(如 id 17 肠道菌群检测套装可同时挂 gut_flora 与某报告类型),商品卡片区展示时**必须按商品 id 去重**,同一商品只出现一次
+2. **报告上传页面成员选择固定为四列**
+   - 已知修复 `750f3d8b2` 已入 cfclub:`.member-item` 改为 `width: calc((100% - 48rpx) / 4)`(去掉 min-width:120rpx)
+   - 本任务**核验该修复在当前 cfclub 是否仍生效**(未被后续提交回退);若已生效,仅需确认,无需改动
+
+## 二、现状(cfclub @ origin 2026-11-06)
+
+- **前端** `cfc-frontend/pages/health/report-upload.vue`(约 931 行):
+  - L86-135 `guide-section`「支持的报告类型」:菌群检测报告 / 素质测评 / 体检报告 / 舌象照片 / 体脂秤报告,其中菌群(`getTypeLink('gut_flora')`)、素质测评(`getTypeLink('dan_a1')`)各有「查看商品」小链接(`guide-link`,`v-if` 条件渲染)
+  - L172 `reportTypeLinks: []`(报告类型→商城商品链接配置)
+  - L248-256 `loadReportTypeLinks()`:`getReportTypeLinks()` → `/api/report-parser/types/links` → `[{typeId, linkedProductId, productName}]`(is_active=1 且 linked_product_id 非空)
+  - L258-264 `getTypeLink(typeId)`:type→link 查找
+  - L266-271 `goProductDetail(typeId)`:跳 `/pages/discover-detail/product-detail/product-detail?id=<linkedProductId>`
+  - L151 import 已有 `getReportTypeLinks`;未 import `productDetail`
+- **后端**:
+  - `ReportParserController.java` L57-92 `POST /api/report-parser/types/links`:仅返回 is_active=1 AND linked_product_id IS NOT NULL,带 productName 批量回填;返回体 item = `{typeId, linkedProductId, productName}`
+  - `ProductController.java` L63-74 `POST /api/product/detail`:入参 `{id}`,返回 `Result<ProductDTO>`(含名称/价格/图)——**已有,可复用**
+- **商品详情页路由**(已有):`/pages/discover-detail/product-detail/product-detail?id=<productId>`(详情页含购买/加购入口)
+- **成员 4 列**:`750f3d8b2`(2026-11-05 21:56,E2E Test Bot)已改 `.member-item` → `width: calc((100% - 48rpx) / 4)`,已入 cfclub;L551 `.member-list` flex-wrap,L557 `.member-item`
+
+## 三、方案(仅改前端,后端零改动)
+
+**仅改 `cfc-frontend/pages/health/report-upload.vue`**(复用既有 API,不新增后端接口):
+
+### 3.1 去重商品卡片区(需求 1)
+
+1. **computed `linkedProducts`**:遍历 `reportTypeLinks`,收集 `linkedProductId`,**用 Set 按商品 id 去重**,返回 `[{productId, productName}]`(同商品多个报告类型只保留一条,productName 取首个匹配;接口失败/未配置时返回 `[]`)
+2. **模板**:在 `guide-section` **之后**新增 `<view class="linked-products-section" v-if="linkedProducts.length > 0">`
+   - 标题「关联商品」+ 说明「以下商品与您的报告类型对应,点击可查看并购买」
+   - 商品卡片列表(网格 2 列 或 横向滚动,参考页面既有卡片风格),每卡片:商品名 + 「查看 / 购买」按钮
+   - 点击卡片或按钮 → `goProductDetailByProduct(productId)` → `uni.navigateTo('/pages/discover-detail/product-detail/product-detail?id=' + productId)`
+3. **脚本**:新增 `goProductDetailByProduct(productId)`(复用现有商品详情页路由;不依赖 typeId,直接按 productId 跳转)
+4. **样式**:`linked-products-section` 卡片样式,保持页面既有视觉(圆角/背景色与 guide-section 一致,使用页面已有 CSS 变量/令牌)
+5. **可选增强(卡片更饱满)**:`linkedProducts` 内再对每个商品 id 调 `productDetail({ id })` 填充价格/主图(`import { productDetail } from api.js`)。**若成本可控建议做**,否则仅展示商品名 + 购买按钮也可接受(产品决策点:卡片信息密度)
+
+### 3.2 成员 4 列核验(需求 2)
+
+- **核验**:确认当前 cfclub `.member-item` 样式 = `width: calc((100% - 48rpx) / 4)` 且无 `min-width:120rpx` 残留;若被回退/覆盖则恢复为固定 4 列
+- **说明**:`750f3d8b2` 已合入,本项以**核验为主**,改动只在「被回退」时才发生
+
+## 四、验收标准
+
+1. 后台为某报告类型配置关联商品后,报告上传页下方出现「关联商品」卡片区,展示该商品,点击可进入商品详情页购买
+2. **去重生效**:两个报告类型关联同一商品 id 时,卡片区只显示该商品一次(不重复)
+3. 未配置任何关联商品 / 接口失败时,卡片区**不显示**(静默回退,不报错、不占位)
+4. 成员选择区域 4 列固定排列(`.member-item` width calc((100% - 48rpx)/4))
+5. 仅改 `cfc-frontend/pages/health/report-upload.vue`(若 4 列被回退,允许该文件内恢复;**不得改后端/其他前端文件**)
+6. 构建通过:`npm run build:mp-weixin` exit 0
+
+## 五、硬约束
+
+- 只改 `cfc-frontend/pages/health/report-upload.vue`;不改 `api.js`(除非确需新增 import,仅加 import 语句)、不改后端、不改 pages.json
+- 不破坏现有「查看商品」小链接(guide-link)与上传流程
+- 去重必须按**商品 id**(linkedProductId),非报告类型 id
+- 未配置商品时静默隐藏卡片区,不得出现空白占位或控制台报错
+- 遵循 CFC 纪律:基于 `origin/cfclub` 建 `feature/` 分支,完成后 `commit` + `push`,**不自行合入 cfclub**(由主理人安排核验后合入)
+
+## 六、风险
+
+- `getReportTypeLinks` 返回体可能因后端版本差异无 `linkedProductId` 字段 → 前端做空值防护(`link && link.linkedProductId`)
+- 商品详情页 `product-detail` 路由若需登录态才能购买,跳转后由详情页自身处理登录引导(不在此页处理)
+- 商品卡片区若 `reportTypeLinks` 含无效条目(linkedProductId 为 null/0)→ 过滤掉,不入去重结果
+
+## 七、验证数据(供开发/核验参考)
+
+- 直查 MySQL `192.168.16.251:3306/zxyj`(zxyj/zxyj@123):`report_type_registry` 目前 10 类型 `linked_product_id` 全 NULL
+- 候选商品:id 17「肠道菌群检测套装」、id 18「儿童多模态认知测评」(on_shelf)
+- 核验去重可用测试数据:后台将 gut_flora 与 dan_a1 都挂 id 17 → 卡片区应只显示「肠道菌群检测套装」一次