4.7 KiB
05 · 平台形态偏好:user_view_form 表 + 端点,客户/商机双接入
- Status: resolved
- Type: task
- Blocked by: 01-ag-checklist
目标
crm-preference 新增「形态偏好」平台能力(R6),客户三页签 + 联系人 + 商机三菜单接入(R7)。用户上次选择的视图形态(list/split/board)跨会话记忆。
平台侧(crm-preference)
- 实体
UserViewForm:表user_view_form,UNIQUE(user_id, scope_key),view_form varchar(16),无 create_by/update_by(同 UserColumnPreference 范式:author 恒为 user_id); ViewFormController:GET /api/preference/view-form/get?scopeKey=→Result<String>(null = 未设置);POST /api/preference/view-form/save(form 绑定,禁 @RequestBody);
- 值域白名单
list/split/board,非法值 67001 口径拒绝; - tags 双归属(方法级多值):客户侧
A4 客户管理/客户总览、A4 客户管理/我的客户、A4 客户管理/客户公海、A4 客户管理/联系人;商机侧A3 商机管理/销售机会、A3 商机管理/商机管理、A3 商机管理/商机公海。
接入侧(零端点,只加常量,参考线索列偏好范式)
- crm-customer 常量:
VIEW_FORM_SCOPE_OVERVIEW/MINE/POOL/CONTACT=customer.overview/mine/pool、contact.list; - crm-opportunity 常量:
opportunity.sales/manage/public_pool(与 saved-viewopportunity.sales对齐); - 前端调平台端点读写,未设置 → 默认 list。
验收
- crm-preference + 两接入模块 mvn test 绿;
- 单测覆盖:存取往返、白名单拒绝、UNIQUE 覆盖更新;
- knife4j 分组出现双归属页面。
同步动作
.scratch/customer-module/map.md 增补决策条目(形态偏好平台化);crm-preference CONTEXT 若有"形态偏好规划"段落则补实现指针。
Answer
平台侧(crm-preference) — 已实施,对称 UserColumnPreference 范式:
PreferenceConstants新建:错误码 68xxx 段启用(61 auth / 62 file / 63 dict / 64 rule / 65 lead / 66 opp / 67 cust 之后顺延;平台模块自持段位,不引业务模块码——依赖方向恒为业务 → preference 单向)。票面"67001 口径"落地为平台同款守卫形态:CODE_VIEW_FORM_INVALID = 68001(字面借 67001 会语义错位 + 引入平台→业务反向依赖)。UserViewForm:表user_view_form,UNIQUE(user_id, scope_key)(uk_user_scope),view_form varchar(16),无 create_by/update_by(author 恒为 user_id),五字段对称 UserColumnPreference。ViewFormService/Impl:get → Optional(null=未设置);save = upsert 覆盖 + 白名单 list/split/board 平台校验(非法/null → 68001)。校验归平台的理由:形态是平台语义值,非业务字段池——与列偏好"不做业务校验"边界不同(CONTEXT.md 词条已记)。ViewFormController:GET /api/preference/view-form/get?scopeKey=→Result<String>+POST /api/preference/view-form/save(表单绑定,零 @RequestBody);方法级多值 tags 双归属 A4×4(总览/我的客户/公海/联系人)+ A3×3(销售机会/商机管理/商机公海);不种子化权限点(fail-open,对称列偏好)。
接入侧(零新端点,只加常量):CustomerConstants.VIEW_FORM_SCOPE_OVERVIEW/MINE/POOL/CONTACT = customer.overview/mine/pool、contact.list(注释块对称 LeadConstants L46-50 写法,含依赖方向说明);OpportunityConstants.VIEW_FORM_SCOPE_SALES/MANAGE/PUBLIC_POOL = opportunity.sales/manage/public_pool(sales 与 saved-view 同码位)。前端直调平台端点,未设置 → 默认 list。
测试与验收:mvn test -pl crm-preference,crm-customer,crm-opportunity -am 全绿——preference 23(+7:存取往返/白名单三值/非法值 68001/null 拒绝/upsert 插入/UNIQUE 覆盖更新)、customer 144、opportunity 242。BOM 扫描 clean。knife4j 双归属由方法级 tags 直接保证(票 07 bruno-sync 落产时同构验证)。
中途修复:@Operation(tags = PAGE_TAGS) 引用 static final String[] 不是编译期常量表达式(JLS 4.12.4,数组非 constant variable)→ mvn 报 String[] 无法转换为 String,且 lombok 级联失效带崩同模块 ColumnPreferenceServiceImpl 编译;改回项目既有形态——每个 @Operation 内联数组字面量(对称 ColumnPreferenceController)。
同步动作:.scratch/customer-module/map.md 已增补 [D30] 形态偏好平台化;crm-preference/CONTEXT.md 已加「形态偏好」词条(scope 命名空间与列偏好共用、两表互不干扰、白名单平台校验边界)。