2026-10-13-mobile-protocol-customer-search-design.md 4.8 KB

移动端协议单:客户档案检索 + 身份证出生年月联动 — 设计说明

日期: 2026-10-13
状态: 已确认(P2-A)
范围: mobile-oa-h5 协议单新增/编辑;backend 市场移动端只读客户检索;对齐 Web ProtocolFormDialog 母亲/父亲姓名检索与母亲身份证→出生年月

1. 背景与目标

Web 采集协议单支持:

  1. 母亲/父亲姓名输入时检索客户档案(fetchCustomerList,keyword 匹配姓名/电话/身份证/标签)。
  2. 选中档案后回填姓名、电话、身份证,并写入 customerId / fatherCustomerId;母亲侧对出生年月/民族/邮箱/住址仅在当前为空时回填。
  3. 母亲身份证号合法时自动推导 motherBirthYm(18 位或 15 位);手工改名若与已关联档案不一致则清空关联 id。

移动端协议单客户区目前为普通文本框,无检索、无 customerId、无身份证联动,与 Web 不一致。

目标: 移动端协议单客户信息区达到与 Web 同等的检索回填与身份证联动行为(不含新建客户档案、不含管理员审核动作)。

2. 决策摘要

项 决策
数据源 新增市场移动端只读检索 API,不复用管理端 biz:customer:list
权限 与协议菜单一致:mini:market:{specialist\|manager}:protocol
检索字段 与 Web 一致:姓名 / 电话 / 身份证 / 标签模糊匹配
UI 姓名字段改为可远程检索的选择器(底部弹层 + 搜索);仍允许不选档案、纯手填
回填策略 与 Web 一致:姓名/电话/身份证覆盖;母亲出生年月/民族/邮箱/住址仅空则填
关联 id 不改挂:移动端既有 _assert_customer_link_policy 禁止创建指定/更新改挂客户主档;检索仅回填单据字段,不写入 customerId/fatherCustomerId
身份证联动 纯函数 calcBirthYmFromIdCard;监听母亲身份证变化写 motherBirthYm
非目标 不新建客户档案;不放开客户改挂策略;不改列表卡片;不做父亲身份证→出生年月;不做 P2-B 金额联动

3. 后端

3.1 路由

在 _register_protocol_routes 下增加:

GET /mini/market/{scope_kind}/protocols/customers
  ?keyword=&page=1&pageSize=20
  • scope_kind: specialist | manager
  • 鉴权:require_market_menu_code(f'mini:market:{scope_kind}:protocol')
  • 租户:当前用户 tenant_no
  • 数据范围:对 BizCustomer 应用与业务列表一致的 apply_data_scope(与管理端客户列表同语义)
  • 空 keyword:返回空列表(与 Web queryPartyCustomers 一致,避免全量拉取)
  • 响应:{ list, total, page, pageSize },list 项字段与 customer._row_to_dict 对齐(至少含 id/customerName/phoneNo/idCardNo/birthYm/ethnic/email/address)

3.2 实现要点

  • 复用 app.crud.customer 的过滤语义;或在 market_support / 薄封装中调用同一 _row_to_dict,避免字段漂移。
  • 不新增写接口。

4. 移动端

4.1 API

mobile-oa-h5/src/api/market.js 增加 fetchMarketProtocolCustomers(context, { keyword, page, pageSize }),路径拼到当前 scope 的 protocols/customers。

4.2 纯函数

新增 protocol-customer-link.js(及测试):

  • calcBirthYmFromIdCard(idCard) → YYYYMM 或 ''(规则同 Web)
  • applyCustomerSelect(formSlice, customer, role):role 为 mother | father;返回需合并的单据字段(不含客户主档 id)

4.3 UI

  • 协议 formSections.customer:motherName / fatherName 使用新字段类型 customerSearch(或专用组件挂在 MarketModuleForm / MarketFormField)。
  • 交互:姓名旁提供「从档案选」入口(或字段可点开弹层)→ van-search 防抖远程检索 → 列表展示「姓名 · 电话」→ 选中回填并关闭;姓名本身仍可手填。
  • 母亲 motherIdCard 变更时调用 calcBirthYmFromIdCard 更新 motherBirthYm(含清空身份证时清空出生年月)。
  • 表单 payload:不主动提交 customerId/fatherCustomerId(避免触发移动端改挂校验);若详情原有关联由后端 partial update 保留。

5. 测试要点

  • 后端:有权限可按 keyword 检索;空 keyword 空列表;租户隔离;无协议菜单 403。
  • 纯函数:18/15 位身份证、非法号、清空;选中母亲空字段回填与已有字段不覆盖。
  • 契约:formSections 含 customerSearch;payload 不含新建时的 customerId。
  • 手工:选档案回填 → 改身份证出生年月变 → 保存成功。

6. 非目标

  • P2-B 优惠价/合同金额/协议总金额联动。
  • 意向金、列表卡片字段调整。
  • Web 端改动。
  • 客户档案 CRUD;放开移动端客户改挂策略(若产品后续要求与 Web 完全一致再单独立项)。