|
|
@@ -0,0 +1,222 @@
|
|
|
+# CRM 客户域:列头漏斗整库服务端筛选(首批)
|
|
|
+
|
|
|
+**日期**:2026-09-06
|
|
|
+**状态**:待审阅
|
|
|
+**范围(首批)**:`web-admin` 客户管理 + 客户公海主列表;后端客户/公海 list 与 export 过滤扩展;`useServerColumnFilters` 通用化
|
|
|
+**后续**:线索/商机/产品/报价/合同等主列表 → 弹窗内列表(本文件仅锁定首批与模式)
|
|
|
+
|
|
|
+**对齐标杆**:`docs/superpowers/specs/2026-09-06-reimburse-apply-server-column-filters-design.md`(报销申请)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 1. 背景与目标
|
|
|
+
|
|
|
+报销申请已落地「列头漏斗 + 整库服务端筛」。CRM 菜单下列表/弹窗表需同一模式。范围大,**分批交付**;首批打通客户域并通用化 composable,再复制到其它 CRM 页。
|
|
|
+
|
|
|
+### 目标
|
|
|
+
|
|
|
+1. 客户管理、客户公海主列表:去掉顶部 `filter-block`,检索 = 列头漏斗 + 快捷搜索(客户页另保留 Tab)。
|
|
|
+2. 四类列交互与报销一致:日期段、数字运算/区间、字典枚举多选、其余文本模糊。
|
|
|
+3. 过滤打整库;`total`/换页/导出与列条件一致。
|
|
|
+4. 藏列清该列条件并重查。
|
|
|
+5. 将 `useServerColumnFilters.toQueryParams` 从「报销写死字段」升级为可配置 `queryKey`,报销页回归不破。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 2. 已确认产品决策
|
|
|
+
|
|
|
+| # | 决策 |
|
|
|
+|---|------|
|
|
|
+| D1 | 交付方式:分批;先主列表后弹窗内表 |
|
|
|
+| D2 | 首批:客户管理 + 客户公海主列表 |
|
|
|
+| D3 | 规则与报销申请完全一致:去顶部筛;保留 Tab/快捷搜索;四类漏斗整库;藏列清条件;默认值迁列漏斗 |
|
|
|
+| D4 | 原顶部有检索字段但无列 → 先补列;本批顶部字段均已有列 |
|
|
|
+| D5 | 架构:通用化 `ColumnFilterDef` + `toQueryParams`(方案 1),不复制 CRM 专用 composable |
|
|
|
+
|
|
|
+**本页默认值**:客户/公海 `searchForm` 初始均为空,无默认值可迁;规则保留供他页使用。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 3. 首批范围
|
|
|
+
|
|
|
+### 3.1 改造
|
|
|
+
|
|
|
+| 页面 | 路径 |
|
|
|
+|------|------|
|
|
|
+| 客户管理 | `web-admin/src/views/crm/customer/index.vue` |
|
|
|
+| 客户公海 | `web-admin/src/views/crm/customer/pool/index.vue` |
|
|
|
+| Composable | `web-admin/src/composables/useServerColumnFilters.ts` + `useClientColumnFilters.ts`(`ColumnFilterDef`) |
|
|
|
+| 报销回归 | `web-admin/src/views/bx/reimburse/apply/index.vue`(仅补 queryKey 配置) |
|
|
|
+| 后端 | `CustomerListBody` / `PoolCustomerListBody`、`list_customers` / 公海 list、对应 export |
|
|
|
+
|
|
|
+### 3.2 明确不做(首批)
|
|
|
+
|
|
|
+- 其它 CRM 主列表(线索、商机、产品、报价、合同等)
|
|
|
+- 客户详情/联系人/发票等弹窗内嵌表
|
|
|
+- 公海规则页、看板/漏斗/统计
|
|
|
+- OpenSpec 基线归档(标杆稳定后另开)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 4. 产品与交互
|
|
|
+
|
|
|
+### 4.1 布局
|
|
|
+
|
|
|
+- 删除顶部 `filter-block`。
|
|
|
+- **客户管理**:保留 Tab(全部 / 我的 / 待跟进 / 重点)→ 请求 `viewMode`;与列条件 **AND**。
|
|
|
+- 保留工具栏快捷搜索 → `keyword`(或现网等价字段);与列条件 **AND**。
|
|
|
+- 「清空列过滤」只清列条件,不清快捷搜索、不改 Tab。
|
|
|
+
|
|
|
+### 4.2 列头漏斗覆盖
|
|
|
+
|
|
|
+业务数据列全挂漏斗(不含勾选、序号)。覆盖 `listColumnDefs` + 固定列「客户编号」「客户名称」。
|
|
|
+
|
|
|
+| 类型 | 列(示意) |
|
|
|
+|------|------------|
|
|
|
+| enum | customerType、level、source、industry、parkArea、scale、status、dealStatus |
|
|
|
+| datetime | createTime、updateTime、lastTime、nextTime、dealTime、intoPoolTime、claimTime、protectTime |
|
|
|
+| number | dealAmount、followCount、contactCount、opportunityCount、contractCount |
|
|
|
+| text | customerNo、customerName、shortName、mobile、telephone、email、website、province、city、district、address、ownerUserName、createByName、updateByName、createDeptName、remark |
|
|
|
+
|
|
|
+公海列与客户高度同构;列表恒为公海范围(`status=pool` 或等价),列筛叠加 AND。
|
|
|
+
|
|
|
+### 4.3 藏列与默认值
|
|
|
+
|
|
|
+- 隐藏列 → 清空该列已生效条件 → 立即重查。
|
|
|
+- 再显示列 → 不自动恢复条件。
|
|
|
+- 「重置列显示」→ 恢复列可见性默认 + 列漏斗 `initialFilters`(本批为空)。
|
|
|
+- 他页若有顶部默认:仅当对应列默认可见时写入 initial。
|
|
|
+
|
|
|
+### 4.4 导出
|
|
|
+
|
|
|
+导出请求体与当前列表同一套:`keyword` + `viewMode`(若有)+ 列筛参数 + 选中 ids(若有)。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 5. 架构:Composable 通用化
|
|
|
+
|
|
|
+### 5.1 扩展 `ColumnFilterDef`
|
|
|
+
|
|
|
+```ts
|
|
|
+interface ColumnFilterDef {
|
|
|
+ prop: string
|
|
|
+ label: string
|
|
|
+ type: 'text' | 'enum' | 'number' | 'datetime'
|
|
|
+ enumOptions?: ColumnFilterEnumOption[]
|
|
|
+ getValue?: (row: any) => unknown
|
|
|
+ /** 文本主查询键;默认 prop。枚举多选默认 `${queryKey}In` */
|
|
|
+ queryKey?: string
|
|
|
+ /** datetime 起止;默认 `${queryKey}From` / `${queryKey}To` */
|
|
|
+ queryKeyFrom?: string
|
|
|
+ queryKeyTo?: string
|
|
|
+ /** number 键前缀;默认 queryKey → `${prefix}Op` / Min / Max / 单值键=prefix */
|
|
|
+ queryKeyPrefix?: string
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 5.2 `toQueryParams` 规则
|
|
|
+
|
|
|
+| type | 输出 |
|
|
|
+|------|------|
|
|
|
+| text | `q[queryKey] = text.trim()` |
|
|
|
+| enum | `q[`${queryKey}In`] = selected.join(',')` |
|
|
|
+| datetime | From/To 闭区间日期 |
|
|
|
+| number | Op + Min/Max 或单值 |
|
|
|
+
|
|
|
+报销申请页改为显式配置(如 `applyTime` → `applyDateFrom`/`applyDateTo`,`amount` → `amountOp`…,`status` → `statusIn`),行为与现网一致。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 6. API 约定(客户 / 公海)
|
|
|
+
|
|
|
+### 6.1 已有(客户 list)
|
|
|
+
|
|
|
+`POST /web/crm/customer/list`(`CustomerListBody`)已支持:
|
|
|
+`keyword`、`customerName`、`customerNo`、`customerType`、`level`、`source`、`industry`、`parkArea`、`status`、`dealStatus`、`ownerUserId`、`beginTime`/`endTime`(创建时间)、`viewMode`/`viewType` 等。
|
|
|
+
|
|
|
+### 6.2 首批扩展
|
|
|
+
|
|
|
+在 list / export 共用拼装中增加(命名 camelCase,与前端 `toQueryParams` 对齐):
|
|
|
+
|
|
|
+1. **枚举多选 `*In`**:如 `customerTypeIn`、`levelIn`、`sourceIn`、`statusIn`、`dealStatusIn`、`parkAreaIn`、`industryIn`、`scaleIn`;逗号分隔 → SQL `IN`。保留原单值字段兼容。
|
|
|
+2. **文本模糊**:对挂漏斗的 text 列补独立参数(如 `shortName`、`mobile`、`telephone`、`email`、`website`、`address`、`ownerUserName`、`remark`、`province`/`city`/`district`、`createByName` 等);`contains`/`like`。
|
|
|
+3. **其它日期**:`lastTimeFrom`/`To`、`nextTimeFrom`/`To`、`dealTimeFrom`/`To`、`intoPoolTimeFrom`/`To`、`claimTimeFrom`/`To`、`protectTimeFrom`/`To`、`updateTimeFrom`/`To`;创建时间可继续用 `beginTime`/`endTime`,或统一为 `createTimeFrom`/`To`(前端 queryKey 显式映射到现网键,避免双栈)。
|
|
|
+4. **数字**:`dealAmountOp` + `dealAmount`/`Min`/`Max`,以及 followCount、contactCount、opportunityCount、contractCount 同模式。
|
|
|
+
|
|
|
+### 6.3 公海
|
|
|
+
|
|
|
+`POST /web/crm/customer/pool/list`(及 export)扩展与公海表漏斗列对齐的参数;内部复用 `list_customers`(或同一过滤拼装),并固定公海范围,避免两套逻辑。
|
|
|
+
|
|
|
+### 6.4 语义
|
|
|
+
|
|
|
+- 多列 AND;`keyword` AND;`viewMode` AND。
|
|
|
+- 租户隔离、数据权限、软删与现网一致。
|
|
|
+- 非法数字/空 `*In`:忽略该维或 400(与报销一致,倾向忽略空维)。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 7. 数据流
|
|
|
+
|
|
|
+```text
|
|
|
+进入客户页
|
|
|
+ → Tab = viewMode;initialFilters(空)
|
|
|
+ → POST list (page, pageSize, viewMode, keyword?, column params?)
|
|
|
+
|
|
|
+列漏斗确定 → 合并 keyword + viewMode + toQueryParams → page=1 重查
|
|
|
+
|
|
|
+藏列 → 清该列条件 → 重查
|
|
|
+
|
|
|
+清空列过滤 → filters={} → 重查(保留 keyword、Tab)
|
|
|
+
|
|
|
+导出 → 与当前列表相同过滤字段
|
|
|
+```
|
|
|
+
|
|
|
+公海同理(无 Tab / 无 viewMode,或固定 pool)。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 8. 验收标准(首批)
|
|
|
+
|
|
|
+1. 客户、公海无顶部筛选区;有列头漏斗 + 快捷搜索;客户 Tab 可用。
|
|
|
+2. 四类漏斗行为正确,跨页、`total`、换 pageSize 条件保持。
|
|
|
+3. 藏带条件列 → 条件清除并刷新;再显示后漏斗空。
|
|
|
+4. 导出与当前筛选一致(权限范围内)。
|
|
|
+5. 报销申请列筛回归通过(日期/金额/状态/文本仍服务端生效)。
|
|
|
+6. 租户与数据权限不弱于改造前。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 9. 风险
|
|
|
+
|
|
|
+- 列多 → 参数多:过滤必须集中函数,禁止 list/export 各写一份。
|
|
|
+- Tab「重点」与 level 列筛可叠加。
|
|
|
+- Composable 通用化误伤报销:须显式 queryKey + 回归。
|
|
|
+- 公海参数今日偏少:扩展时勿破坏 `status=pool` 边界。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 10. 后续批次路线图
|
|
|
+
|
|
|
+| 批次 | 内容 |
|
|
|
+|------|------|
|
|
|
+| 1(本文) | 客户 + 公海 + composable 通用化 + 报销回归 |
|
|
|
+| 2 | 线索、商机主列表 |
|
|
|
+| 3 | 产品、报价/审批、合同/审批等主列表 |
|
|
|
+| 4 | 弹窗/详情内嵌表 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 11. 建议实现顺序
|
|
|
+
|
|
|
+1. 扩展 `ColumnFilterDef` / `toQueryParams`;报销页补配置并回归。
|
|
|
+2. 后端客户/公海 list+export 过滤扩展 + 必要单测。
|
|
|
+3. 改造客户、公海页面 UI 与接线。
|
|
|
+4. 手工验收 §8。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 12. 修订记录
|
|
|
+
|
|
|
+| 日期 | 说明 |
|
|
|
+|------|------|
|
|
|
+| 2026-09-06 | 初稿:CRM 首批客户+公海;规则对齐报销;composable 通用化;分批路线图 |
|