From 16d382e6aa8155f243e491d4f5a712cb20007fff Mon Sep 17 00:00:00 2001 From: zlwu Date: Sun, 6 Sep 2026 08:13:48 +0800 Subject: [PATCH] docs: add design for CRM customer server-side column filters. Co-authored-by: Cursor --- ...m-customer-server-column-filters-design.md | 222 ++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 docs/superpowers/specs/2026-09-06-crm-customer-server-column-filters-design.md diff --git a/docs/superpowers/specs/2026-09-06-crm-customer-server-column-filters-design.md b/docs/superpowers/specs/2026-09-06-crm-customer-server-column-filters-design.md new file mode 100644 index 000000000..d5d17058a --- /dev/null +++ b/docs/superpowers/specs/2026-09-06-crm-customer-server-column-filters-design.md @@ -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 通用化;分批路线图 |