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.

99 lines
7.0 KiB

2 weeks ago
<!-- wayfinder:grilling -->
# 四视图卡片口径映射表定稿
Type: grilling
Status: resolved
Blocked by: 04
## Question
原问题:
产出一张权威的「视图 × 卡片 → 口径」映射表,作为 spec 的核心。每格给出 status 集合或派生条件(含今日新增的时间口径、销售持有的合并口径)。初稿如下,需逐格确认/修订:
| 卡片 | 口径 | 公海 | 我的线索 | 我的关注 | 线索管理 |
|---|---|---|---|---|---|
| 线索总量 | 视图内 count(*) | ✓ | ✓ | ✓ | ✓ |
| 待领取 | status=2 | ✓ | | ✓ | ✓ |
| 今日新增 | DATE(create_time)=今天 | ✓ | | | ✓ |
| 已领取 | status=3 | | ✓ | ✓ | |
| 跟进中 | status=4 | | ✓ | ✓ | |
| 已转商机 | status=5 | | ✓ | ✓ | ✓ |
| 线索作废 | status=7(口径见 #01) | | ✓ | ✓ | |
| 过期失效 | status=6 | | ✓ | ✓ | ✓ |
| 未分发 | status=1 | | | | ✓ |
| 销售持有 | status IN (3,4) | | | | ✓ |
待确认要点:
- 「线索总量」在各视图分母是什么?是视图内全部可见线索,还是全部 7 态?(尤其 公海 现只见 2/3/4,我的线索 只见有 owner 的)——直接受 #01 结论影响。
- 各卡片口径是否要吃 `/page` 的动态筛选(keyword/channel/…),还是固定视图口径?
- 「销售持有」= 已领取 + 跟进中,与 我的线索/我的关注 里的拆分字段是同源计算。
## Answer
### 核心口径公式
**所有分卡口径 = `applyViewFilters(viewType, param, currentUserId)` + 该 status 条件**。无逐格特判、无额外 owner 断言。
其中 `applyViewFilters` 保持现状语义(不改):
- `PUBLIC_POOL`:`status IN (2,3,4)`
- `MY_LEAD`:`owner_user_id = 当前用户`(不加 status 过滤,天然含作废 owner=我 —— 由 ticket 01/04 保证)
- `MY_FOLLOW`:`id IN (SELECT lead_id FROM lead_follow WHERE user_id = 当前用户)`(不看 owner、不看 status)
- `MANAGE`:无业务过滤,仅靠 `@DataScope` 注入部门/OWNER 天花板
`@DataScope` 由 MyBatis 拦截器自动叠加在同一 wrapper 上(`Lead` 实体注解),四视图 stats 天然吃到。
### 视图 × 卡片 → 口径映射表(权威定稿)
| 卡片 | 口径(在 `applyViewFilters` 之上再叠加) | 公海 | 我的线索 | 我的关注 | 线索管理 |
|---|---|---|---|---|---|
| 线索总量 | `count(*)`(视图内全部可见) | ✓ | ✓ | ✓ | ✓ |
| 今日新增 | `create_time >= todayStart AND create_time < tomorrowStart` | ✓ | ✗ | ✗ | ✓ |
| 待领取 | `status = 2` | ✓ | ✗ | ✓ | ✓ |
| 未分发 | `status = 1` | ✗ | ✗ | ✗ | ✓ |
| 已领取 | `status = 3` | ✗ | ✓ | ✓ | ✗ |
| 跟进中 | `status = 4` | ✗ | ✓ | ✓ | ✗ |
| 销售持有 | `status IN (3, 4)` | ✗ | ✗ | ✗ | ✓ |
| 已转商机 | `status = 5` | ✗ | ✓ | ✓ | ✓ |
| 过期失效 | `status = 6` | ✗ | ✓ | ✓ | ✓ |
| 线索作废 | `status = 7` | ✗ | ✓ | ✓ | ✗ |
### 决策来源(7 格 grilling 结论)
1. **总量分母(Grill 1,甲)**:「线索总量」= 视图 `applyViewFilters` 之后 `count(*)`,四视图一致。允许“分卡覆盖不全 7 态、之和 ≠ 总量”(如「我的关注」缺 status=1 分卡是允许的)。
2. **动态筛选吃不吃(Grill 2,甲)**:卡片吃 `/page` 全部动态筛选(keyword/channel/brand/product/province/statusIn/poolId/deptId/isUrgent/feedbackStatus)。现状 `countStats` 复用完整 `applyViewFilters`,零改动。
- **副作用(留给 03 前端契约处理)**:若用户传 `statusIn=[3]`,则「已领取」=「线索总量」、其他分卡=0。这是甲的必然、非 bug;前端是否把 `statusIn` 从卡片计算里剔除属于 03 决策。
3. **今日新增时间口径(Grill 3,甲)**
- 时区 = JVM 本地 `LocalDate.now()`(与 `ClaimLimitChecker` 同源)。
- SQL 用范围条件 `create_time >= todayStart AND create_time < tomorrowStart`(索引友好),**不再用** `DATE(create_time) = CURRENT_DATE`
- 时间字段 = `create_time`(入库时间)。**不看当前 status**——今日入库又今日作废也算 1 条。
4. **销售持有(Grill 4,甲)**:`status IN (3,4)`,纯 status 判据。与 `ClaimLimitChecker`/`ConvertibleLeadCatalogPortImpl` 同源。不加 `owner IS NOT NULL` 防御——状态机不变式(status ∈ {3,4} ⇒ owner 非空)由状态机保证,统计层不重复兜底。加法关系:`销售持有 = 已领取 + 跟进中`。
5. **「我的关注」的分卡是否叠 owner(Grill 5,甲)**:不叠。所有分卡 = `follow` 表内 + 该 status。产品语义支持——“关注 = 盯着这条线索的动向”,别人 owner 的线索被作废,也要计入「我的关注」→「线索作废」。
6. **MANAGE 视图数据范围(Grill 6,甲)**:MANAGE 无业务过滤 + `@DataScope` 天花板。数字随角色变化(ALL_VISIBLE / DEPT / OWNER),入口权限由 `LeadPermissionInitializer` 的 catalog 权限点控制,spec 里注明此点。
7. **需求✗格严格按原清单(Grill 7,甲)**:✗ 就是 ✗,不向产品发起补卡建议。以下三处✗ **不追问**,按需求原样交付:
- 「我的线索」/「我的关注」无「今日新增」。
- 「线索管理」无「已领取(3)」「跟进中(4)」独立卡,只有合并的「销售持有」。
- 「线索管理」无「线索作废(7)」卡。
### 交付给 03 的接力
03(DTO 字段形态与前端契约)需要处理:
- **DTO 字段命名**:
- 新增 `following`(跟进中 status=4)、`expired`(过期失效 status=6)、`voided` 或类似(作废 status=7,`void` 是 Java 关键字禁用)。
- 现有 `claimed` 语义歧义(当前 =3+4)——建议改名 `sellerHolding`(对应「销售持有」),或将 `claimed` 收窄为仅 status=3、另增 `sellerHolding` 字段。由 03 定。
- **DTO 是否全量返回**:后端一次算 `total/undistributed/waiting/claimed/following/converted/expired/voided/todayNew/sellerHolding` 全套,前端按视图渲染 —— 还是按 `viewType` 裁剪只返回该视图卡片对应字段?现状「全量返回」;由 03 定。
- **`statusIn` 与卡片的交互**:如 Grill 2 副作用所述,前端点卡片下钻 = 加 `statusIn` 筛选;若卡片本身又吃 `statusIn`,会出现“点了「已领取」后所有其他卡=0”的观感—— 03 定前端在卡片计算的 payload 里是否剔除 `statusIn`
- **测试口径重写**:`LeadViewQueryImplTest#countStats_*` 全部按上表重写。断言矩阵 = 4 视图 × 上表勾选卡片,覆盖:
- 视图 filter 生效
- `@DataScope` 生效(OWNER/DEPT/ALL_VISIBLE 三档)
- 今日新增按 JVM 时区、范围条件
- 「我的关注」含别人 owner 的作废/过期(Grill 5)
- 加法关系:`sellerHolding = claimed(3) + following(4)`(若 DTO 拆到这个粒度)
### 明确不属于本 ticket 的
- DTO 字段名 & 数量(03)。
- 前端契约(03)。
- 后端实现改动(新起 session)。
- 需求✗格是否补卡(甲:不追问)。