# 06 · 列偏好 scopeKey:客户 4 个 + 商机 3 个 + 平台 tags 双归属 - **Status:** resolved - **Type:** task - **Blocked by:** 01-ag-checklist ## 目标 字段设置(显隐列+顺序)后端接线,完全复刻线索模块范式(R5/R7):业务方只加 scopeKey 常量,存储走既有 `/api/preference/get|save` + `user_column_preference` 表,零新端点。 ## 做法 - crm-customer 常量(LeadConstants 同款注释块):`COLUMN_SCOPE_OVERVIEW/MINE/POOL/CONTACT` = `customer.overview/mine/pool`、`contact.list`; - crm-opportunity 常量:`opportunity.sales/manage/public_pool`; - `ColumnPreferenceController`(crm-preference)方法级 tags 补双归属: - 现状:仅 A2 线索四页; - 补:A4 客户四页(总览/我的客户/公海/联系人)+ A3 商机三页(销售机会/商机管理/商机公海); - 固定列校验(客户名称不可隐藏、勾选/序号/操作列不参与、重置默认)归**前端**,后端只存取(平台侧不校验,与线索一致——R5 拍板); - 注:lead 侧常量标注"预留,尚未接线"维持现状,本票不动线索。 ## 验收 - 三模块 mvn test 绿; - knife4j 上 `/api/preference/get|save` 出现在 A2/A3/A4 全部相关页面分组; - 常量注释引用 crm-preference/CONTEXT.md「scope」口径(同 LeadConstants L46-50 写法)。 ## Answer **常量块** — `CustomerConstants.COLUMN_SCOPE_OVERVIEW/MINE/POOL/CONTACT` = `customer.overview/mine/pool`、`contact.list`;`OpportunityConstants.COLUMN_SCOPE_SALES/MANAGE/PUBLIC_POOL` = `opportunity.sales/manage/public_pool`(与 saved-view / 形态偏好同码位)。注释块对称 LeadConstants L46-50 写法:引用 crm-preference/CONTEXT.md「scope」口径、crm-preference 不透明字符串存储不持语义、依赖方向单向防成环、固定列校验归前端(R5)。零新端点——存储走既有 `/api/preference/get|save` + `user_column_preference` 表。 **平台 tags 双归属 → 三域归属** — `ColumnPreferenceController` 两 @Operation tags 由 A2×4 扩为 **A2×4 + A4×4(总览/我的客户/公海/联系人)+ A3×3(销售机会/商机管理/商机公海)**,与票 05 形态偏好同套页面 tag 文本(ADR-0024 菜单粒度);knife4j 上 `/api/preference/get|save` 落 A2/A3/A4 全部相关页面分组。 **边界维持**:lead 侧常量"预留,尚未接线"未动;后端不做固定列校验(平台只存取,测试既有口径未变)。 **测试与验收**:`mvn test -pl crm-preference,crm-customer,crm-opportunity -am` 全绿(改动为纯常量+注解,preference 23 / customer 144 / opportunity 242 维持);BOM 扫描 clean。