You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
16 KiB

6 days ago
# 商机模块前置客户接口依赖分析报告
> **生成日期**:2026-08-31
> **原型基准**:蓝湖 Axure「itc信息化业务中台web端 V1.0」**v29**(2026-08-28 14:39 GMT 最新版),OSS 公开直拉一手提取(非 MCP、非旧缓存)
> **分析焦点**:**A3-1-1-2-1 新增/编辑商机**页「客户信息」区(用户指定页,pageId `926458f1...`),辅证同族页 A3-1-1-2-4 添加关联客户弹窗、A3-1-1-1-2 客户信息 Tab
> **目的**:客户模块(A4,未建)开发**提前排期**,保证商机模块工程师**可正常联调**后端接口
> **范围纪律**:仅覆盖商机模块实际用到的客户能力,A4 完整功能(公海/总览/导入/合并/交割等 30+ 页)不在本报告
---
## 0. 结论速览
| 优先级 | 接口 | 一句话用途 |
|---|---|---|
| **P0** | `POST /api/customer/search` | 新增商机「关联客户*」搜索选择框的数据源(弹窗四维查询同源) |
| **P0** | `GET /api/customer/{id}/contacts` | 选中客户后「客户联系人」候选列表(按客户筛选) |
| **P0** | `GET /api/customer/{id}` | 选中客户/编辑回显时的客户基础信息带出 |
| **P1** | `GET /api/customer/contact/search` | 「商机关键联系人」全局搜索(带出所属公司) |
| **P1** | `POST /api/customer/quick-create` | 弹窗「+ 快速创建客户」入口 |
| **P2** | `GET /api/customer/{id}/detail` | 客户信息 Tab「查看客户详情」新窗口跳转 |
| 配套 | crm-dict 两个分组:`客户类型` / `客户角色` | 下拉选项数据(语义不同,勿合并) |
**P0 三件 = 新增商机表单提交主链路的硬依赖**:缺一,商机工程师无法走通「选客户 → 选联系人 → 提交」联调闭环。
---
## 1. 原型解析(一手证据)
### 1.1 A3-1-1-2-1 新增/编辑商机 · 客户信息区(用户指定页)
表单共 18 个字段(原型自带需求批注「3、字段说明」逐条登记),其中**客户信息区占 6 个**:
| # | 原型字段 | 控件类型 | 原型规则(批注原文摘要) | 依赖客户模块? |
|---|---|---|---|---|
| 13 | **商机关联联系人** | 搜索选择框 | 搜索并选择与当前商机相关的联系人;**选择后自动带出联系人所属公司等信息** | ✅ 联系人全局搜索 |
| 14 | **关联人所在公司** | 自动带出字段 | 展示已选联系人的所属公司;原则上不可手动修改 | ✅(随 13 带出) |
| 15 | **关联客户** | 搜索选择框 | **必填\***,「数据来源于客户管理模块」 | ✅ 客户搜索 ★核心 |
| 16 | **客户角色**(表单 label 写「客户类型」) | 下拉选择框 | **必填\***,选项来源于**客户角色字典** | ✅ 字典(crm-dict) |
| 17 | **客户联系人** | 搜索选择框 | 「候选联系人需**根据已选客户筛选**」 | ✅ 按客户查联系人 |
| 18 | **是否主要客户** | 下拉选择框 | **必填\***(是/否);同一商机原则上只能存在一个主要客户 | ✗ 商机侧逻辑 |
> 字段 12「甲方名称」为纯文本框(甲方是否明确=是时必填),**不依赖**客户模块,不入清单。
**交互联动**(批注「4、交互说明」):
- 交互 6「联系人搜索」:点击搜索打开联系人选择窗口,确认后自动回填**联系人、联系方式及所属公司**(服务字段 13/14)
- 交互 7「关联客户搜索」:点击搜索打开客户选择窗口,确认后回填客户名称,**并刷新客户联系人候选范围**(服务字段 15→17 级联)
**业务规则**(批注「5、业务规则&功能逻辑」):
- 规则 6:新增商机**至少关联一个客户**;编辑时可调整,需保证客户与联系人归属关系一致
- 规则 7:同一商机只能存在一个主要客户;修改后原主要客户自动降为普通关联
- 规则 9:重复商机校验可依据商机名称、**关联客户**、项目区域(商机侧逻辑,消费客户名)
**验收标准**(批注「6、原型体验及验收标准」):7「选择联系人后,联系方式及所属公司需正确带出」;8「选择关联客户后,客户联系人范围需同步更新」。
### 1.2 A3-1-1-2-4 添加关联客户弹窗(同族复用场景,商机详情·客户信息 Tab 入口)
与新增商机表单共用同一组客户接口,但查询维度更宽:
- **客户查询区**:客户名称 / 联系人 / 联系电话(模糊)+ 客户类型下拉(选项:全部客户类型/总包/工程商/投资方/设计院/集成商/投标公司,来源于**客户类型字典**)
- **搜索结果表 7 列**:选择(单选) / 客户名称 / 客户类型 / 地区(省市区) / 联系人(默认或主要联系人) / 联系电话(**按权限脱敏**) / 客户负责人
- **关联信息设置区**:客户角色\*(客户角色字典)/ 客户联系人(下拉,候选=**当前选中客户下的联系人**,切换客户后清空重选)/ 是否主要客户\*
- **「+ 快速创建客户」**:客户库不存在目标客户时进入快速创建流程,**创建成功后返回当前页并自动选中新建客户**(规则 7:快速创建的客户需**先写入客户管理模块**,再与商机建立关联)
- 规则 3:同一客户不得重复关联同一商机(商机侧已有错误码 66011 拦截)
### 1.3 A3-1-1-1-2 客户信息 Tab(展示场景,佐证出参列)
列:客户名称 / 客户类型 / 关键联系人 / 联系方式(脱敏) / 联系人职务 / 关系标记(主要意向客户/普通关联) / 操作(**查看客户详情**〔新窗口跳转〕/ 设为主要)。
---
## 2. 依赖识别汇总
| 商机侧触点 | 需要的客户模块能力 |
|---|---|
| 新增商机字段 15「关联客户\*」搜索 | 客户搜索(名称模糊,P0) |
| 新增商机字段 17「客户联系人」按客户筛选 | 按客户查联系人(P0) |
| 新增商机字段 13/14「商机关键联系人/关联人所在公司」 | 联系人全局搜索 + 带出公司(P1) |
| 弹窗查询区四维搜索(名/联系人/电话/类型) | 客户搜索扩展参数(并入 P0 接口) |
| 弹窗「+ 快速创建客户」 | 客户快速创建(P1) |
| Tab「查看客户详情」跳转 | 客户详情(P2) |
| 字段 16 + 弹窗「客户角色\*」 | crm-dict「客户角色」分组 |
| 弹窗「客户类型」筛选 + 结果列 | crm-dict「客户类型」分组 + 客户主数据属性 |
> **两个字典勿混淆**(原型即分开建模):**客户类型** = A4 客户主数据属性(客户是什么);**客户角色** = 客户在某个商机中的业务身份(客户在这个单子里干什么)。商机侧 `OpportunityCustomer.customerRole` 已建模为字典 code,选项值由产品录入。
---
## 3. 客户模块接口清单(提前开发项)
> 路径风格对齐现有工程(`/api/dict/group`、`/api/opportunity/customer` 均为 `/api/<域>/<资源>`);最终路径以客户模块立项时平台规范为准。
### P0-1 客户搜索(分页)
| 项 | 内容 |
|---|---|
| 接口 | `POST /api/customer/search` |
| 入参 | `keyword`(客户名称/联系人/联系电话,模糊,弹窗查询区三输入合一或拆分均可)、`customerType`(客户类型字典 code,筛选)、`page`/`size` |
| 出参 | `customerId`、`customerName`、`customerType`(code+名)、`regionName`(省市区拼接)、`contactName`(默认/主要联系人)、`contactPhone`(**按权限脱敏**)、`ownerName`(客户负责人)、`total` |
| 场景来源 | ① A3-1-1-2-1 字段 15「关联客户\*」搜索选择框(必填,批注明写「数据来源于客户管理模块」);② A3-1-1-2-4 弹窗客户查询区 + 搜索结果表 7 列 |
| 联调说明 | 商机侧现有 `POST /api/opportunity/customer/search` 为**快照池降级实现**(A4 未建,仅返回 customerId+customerName,SQL 从 opportunity_customer 自身去重取数,见 `OpportunityCustomerMapper.searchCandidatePool`)。客户模块本接口就位后商机侧**切真源、接口签名不变、出参列补齐**(代码注释已预留该口径,20260829 拍板)——前端联调路径不变 |
### P0-2 按客户查联系人
| 项 | 内容 |
|---|---|
| 接口 | `GET /api/customer/{customerId}/contacts` |
| 入参 | 路径参数 customerId |
| 出参 | 列表:`contactId`、`name`、`phone`(按权限脱敏)、`company`(所属公司)、`position`(职务,客户信息 Tab 有「联系人职务」列) |
| 场景来源 | ① A3-1-1-2-1 字段 17「客户联系人」——「候选联系人需根据已选客户筛选」+ 交互 7「选关联客户后刷新客户联系人候选范围」;② A3-1-1-2-4 弹窗「客户联系人」下拉——「候选范围为当前选中客户下的联系人」「切换客户后原客户联系人需清空并重新选择」 |
| 联调说明 | 空客户时前端不发请求(字段 17 依赖字段 15 先选中);返回的 `company` 同时可服务字段 14 的展示 |
### P0-3 客户基础信息查询
| 项 | 内容 |
|---|---|
| 接口 | `GET /api/customer/{customerId}` |
| 入参 | 路径参数 customerId |
| 出参 | `customerId`、`customerName`、`customerType`(code+名)、`regionName`、`defaultContactName`、`defaultContactPhone`(脱敏) |
| 场景来源 | ① A3-1-1-2-1 选中关联客户后带出客户维度(类型/地区回显);② **编辑回显**——批注交互 2「系统自动加载当前商机已有数据并回填至对应字段」;③ 商机侧 `customer/add` 服务端校验 customerId 有效性(快照池模式下无校验对象,A4 后补强校验) |
| 联调说明 | 出参最小集 = 新增商机客户信息区需要带出的全部客户维度;不必返回 A4 全量 9-tab 详情 |
### P1-1 联系人全局搜索
| 项 | 内容 |
|---|---|
| 接口 | `GET /api/customer/contact/search?keyword=` |
| 入参 | `keyword`(联系人姓名/电话模糊) |
| 出参 | 列表:`contactId`、`name`、`phone`(脱敏)、`company`(所属公司名)、`customerId` |
| 场景来源 | A3-1-1-2-1 字段 13「商机关联联系人」搜索选择框——**不依赖先选客户**,独立搜索;批注「选择后自动带出联系人所属公司等信息」+ 交互 6「确认后自动回填联系人、联系方式及所属公司」+ 字段 14「关联人所在公司」自动带出不可手改 |
| 备注 | 该字段为 **v29 原型新增,PRD(基于旧版)无对应物**——商机主表也需补建模(见附录 A-3),客户模块侧仅保证接口可查 |
| 定级理由 | 新增商机主链路(选客户→选客户联系人→提交)不含此字段也走得通(非必填),完整交互需要,故 P1 |
### P1-2 快速创建客户
| 项 | 内容 |
|---|---|
| 接口 | `POST /api/customer/quick-create` |
| 入参 | `customerName`\*、`customerType`\*(字典 code)、`contactName`?、`contactPhone`?、`regionCode`? |
| 出参 | `customerId`、`customerName`(供弹窗自动选中并回填) |
| 场景来源 | A3-1-1-2-4 弹窗「+ 快速创建客户」——批注字段 3「当客户库中不存在目标客户时,用于进入客户快速创建流程」、交互 8「创建成功后可返回当前页面并自动选中新建客户」、规则 7「快速创建的客户需先写入客户管理模块,再与当前商机建立关联」 |
| 定级理由 | 新增商机**表单本身无快速创建入口**(仅弹窗有),不阻塞表单联调,故 P1。注意是最小字段集,**不要**实现成 A4 完整新增客户表单(a4-3-3-1,那套含查重/地区/行业等全量字段) |
### P2-1 客户详情(跳转目标)
| 项 | 内容 |
|---|---|
| 接口 | `GET /api/customer/{customerId}/detail`(或前端路由直达 A4 页面,后端出数据) |
| 场景来源 | A3-1-1-1-2 客户信息 Tab 操作列「查看客户详情」——批注明写「1、查看详情:新窗口,跳转客户详情」 |
| 定级理由 | 展示增强,不阻塞任何商机写链路联调,P2。可先用 P0-3 基础信息接口顶替过渡 |
### 配套字典(crm-dict 侧,非客户模块接口但联调必需)
| 字典分组 | 建议编码 | 选项(原型实样) | 消费方 |
|---|---|---|---|
| 客户类型 | `customer_type` | 总包 / 工程商 / 投资方 / 设计院 / 集成商 / 投标公司 | 弹窗客户类型筛选;客户主数据属性;客户信息 Tab「客户类型」列 |
| 客户角色 | `customer_role` | 投标公司 / 总包 / 工程商…(产品定) | 新增商机字段 16;弹窗「客户角色\*」;商机侧 `opportunity_customer.customer_role` 已建列 |
---
## 4. 优先级总表
| 优先级 | 接口 | 判定依据 |
|---|---|---|
| **P0** | `POST /api/customer/search` | 新增商机表单必填项(关联客户\*)唯一数据源;无此接口表单无法提交 |
| **P0** | `GET /api/customer/{id}/contacts` | 字段 17 级联数据源(选客户后刷新联系人范围);验收标准 8 |
| **P0** | `GET /api/customer/{id}` | 选中回显 + 编辑回显 + 服务端 id 校验 |
| **P1** | `GET /api/customer/contact/search` | 字段 13/14(v29 增量,非必填)完整交互 |
| **P1** | `POST /api/customer/quick-create` | 弹窗快速创建入口(表单无此入口,不阻塞) |
| **P2** | `GET /api/customer/{id}/detail` | Tab 跳转详情,展示增强 |
| **P0\*** | crm-dict `customer_type` + `customer_role` 分组 | 字典无数据 = 必填下拉开天窗,与 P0 接口同批就位 |
---
## 5. 商机侧配套缺口(联调双向对齐,附录)
客户模块提前开发的同时,商机侧需同步对齐以下缺口(均为商机模块工作项,不占客户模块排期):
1. **`POST /api/opportunity`(新增商机)入参扩展**:v29 表单要求客户族字段(customerId\* / customerRole\* / isPrimaryIntended\* / customerContactId / keyContact 相关);PRD §2.1 仅拍板「意向客户必填落 opportunity_customer 首条」,需按 v29 对齐入参契约。
2. **`OpportunityCustomer` 子表/DTO 补「客户联系人」**:表单字段 17、弹窗字段 12 均选客户联系人;当前 `OpportunityCustomerAddDTO` 注释明写「客户联系人候选归客户域(A4 未建,暂不收)」——A4 就位后补 `customer_contact_id` + 快照列并收参。
3. **「商机关键联系人/关联人所在公司」建模**(v29 增量,PRD 无):字段 13/14 在商机主表无对应列,需产品拍板落主表(key_contact_id + 公司快照)或独立子表。
4. **快照池切真源**:`OpportunityCustomerMapper.searchCandidatePool` 切 `customer` 真表,接口签名不变(已拍板口径)。
5. 线索→商机 port(`CreateOpportunityCmd.customerId`)已就位,无缺口。
## 6. 待确认项(⚠ 不阻塞接口排期)
1. 字段 13「商机关联联系人」是否要求归属关联客户?(批注独立搜索框 vs 规则 6「客户与联系人归属关系一致」语义有歧义,建议按独立全局联系人实现,产品终审)
2. 客户联系人是否允许暂缺?(字段 17 及弹窗字段 12 均无必填红星,倾向可后补)
3. 电话脱敏口径:后端按权限出参脱敏 vs 出明文前端按权限脱敏(弹窗规则 8「根据当前用户权限展示完整号码或脱敏号码」)——建议后端出参脱敏(对齐现有工程联系方式脱敏惯例),需拍板
4. 重复商机校验(规则 9)的触发时机与阈值(商机侧逻辑,联调时对齐)
---
## 附:证据资产索引
| 资产 | 位置 |
|---|---|
| v29 清单(182 页) | `.scratch/lanhu-latest/axure-v29.json` |
| 新增/编辑商机页文本提取 | `.scratch/lanhu-latest/v29-customer-pages/a3-1-1-2-1__新增_编辑商机.txt` |
| 新增/编辑商机页原始 HTML + 需求批注全文 | `.scratch/lanhu-latest/v29-customer-pages/a3-1-1-2-1_raw.html`(批注提取脚本 `extract-annotations.mjs`) |
| 添加关联客户弹窗文本 + 原始 HTML + 批注全文 | `.scratch/lanhu-latest/v29-customer-pages/a3-1-1-2-4________.txt` / `a3-1-1-2-4_raw.html`(`extract-2-4-annotations.mjs`) |
| 客户信息 Tab / 其余 8 页文本 | `.scratch/lanhu-latest/v29-customer-pages/` |
| 批量拉取脚本(可复跑) | `.scratch/lanhu-latest/fetch-v29-customer-pages.mjs` |
| 商机侧现状代码 | `crm-opportunity/.../OpportunitySubController.java`、`OpportunityCustomerAddDTO.java`、`OpportunityCustomerMapper.java` |
_报告基于 v29 原型一手提取 + 商机 PRD(冻结版)+ crm-opportunity 现状代码三方交叉核对;如原型再更新,重跑 `fetch-v29-customer-pages.mjs` 刷新证据。_