用户: 「有的是需求,有的是需求的需求,都需要打上不同的标记」 ## 核心洞察 三类文档(META/REQ/REF)长期混用同一套审查标准 → 用错标准 = 审查失效。 ## 新增规范 docs/standards/文档性质标记规范.md (v1.0) - 三分类定义 + 判定判据(判据是「约束范围」,不是文件名) - ★ 三类规则差异表: | | META | REQ | REF | |审查标准| 能否约束住别人 | 验收标准达成 | 与代码一致 | |变更成本| 高(全仓) | 中(局部) | 低(同步) | |架构锁定| ❌ | ✅ | ❌ | - 三层落地:① 文档头标性质 ② README §六 索引 ③ META 强制类挂 AGENTS ## 全量打标 25/25 META 13 · REQ 5 · REF 7 ## ★ 盘点发现(已修复) - **11 份 META 中曾仅 4 份有强制入口** → 7 份「标记了但约束不住」 - docs/standards/ 目录名误导:18 份混着 4 REF + 3 REQ - 易错点:名为"XX接入规范"但只约束一个集成 → 是 REQ 不是 META ## 强制链补齐(AGENTS.md 绝对禁止 8~11) 新增 4 条,把"待挂"META 接入强制链: - 8. error-code.md 响应格式(成功 {code,data,message} / 错误走 HTTPException) - 9. 数据采集合并去重机制 所有采集通道的去重键 - 10. 投诉渠道口径与对账 渠道口径权威定义(改动影响全部投诉数字) - 11. 数据源接入与缓存加速 缓存铁律(写入后必须失效 pattern) ## 其它 - docs/README.md 新增 §六 文档性质索引(单一事实来源);修复历史表格粘连缺陷 - AGENTS.md 新增「文档性质纪律(强制)」章 - review-checklist.md 新增「文档性质」检查项(6 条子项) - .github/instructions/doc-class-rationale.instructions.md(applyTo: docs/**) --- ## 附带修复:前端构建/编辑器报错(真实问题) ### ① Vue 3 模板被误报 compileError(根因:仓库根无 ESLint 配置) 现象:`v-model:preset="..."` 被编辑器标 [vue/no-v-model-argument] compileError 实测澄清:vite build / docker build / 命令行 eslint **全部通过** 根因:VS Code ESLint 扩展以**工作区根**为 cwd 启动;根目录无任何 ESLint 配置 → 回退内置默认规则集(含 Vue 2 遗留规则 vue/no-v-model-argument) 修复: - 新增 eslint.config.mjs(根级**桥接**文件,转发 web/eslint.config.js,单一事实来源) - 新增 web/jsconfig.json(声明 vueCompilerOptions.target=3,Vue 语言服务) - 新增 .vscode/settings.json(eslint.useFlatConfig=true 等) - web/eslint.config.js 显式关闭 vue/no-v-model-argument 并注明原因 验证:两个 cwd 均解析出 118 条规则、该规则 = [0](一致) ### ② el-radio-button label → value 迁移(Element Plus 2.14 弃用) 实测告警:[el-radio] label act as value is about to be deprecated (3.0.0 移除) 项目实际装 element-plus 2.14.4(package.json 写 ^2.6.2)→ 告警真实存在 迁移 28 文件 / 158 处(脚本 scripts/migrate_radio_label_to_value.py,可复现) 验证:浏览器实测 el-radio 弃用告警**归零** ## 验证 - 前端 eslint 0 error(5 warning 均为既有 v-html)· vitest 52 例全绿 - vite build 成功 · docker compose build --no-cache 成功 - 文档性质标记覆盖 25/25 · AGENTS 强制链 9 份 META 关联工单: #71
8.2 KiB
人均效率算法说明
性质:参考(REF) —— 记录效率算法现状;⚠️ 内含业务口径(难度系数),存疑待定
版本:v1.0 · 日期:2026-08-17 关联代码:analytics.py
today_staff_efficiency函数(约 L4219) 关联模型:person.py / specialty.py
一、算法概述
人均效率是运营看板的核心指标,通过两个合成指标量化每个客服人员的产出:
| 指标 | 维度 | 含义 | 公式 |
|---|---|---|---|
| 工作量分 | 会话次数 | 反映忙闲强度(接了多少次) | Σ(专项会话数 × 难度系数 × 本职系数) |
| 效率分 | SN 去重接待个数 | 反映服务覆盖面(接待了多少个不同客户) | Σ(接待个数 × 难度系数 × 本职系数) |
两个指标的差异:同一客户多次咨询算 1 个效率分但多次工作量分。
二、6 专项难度系数
| 专项 | 系数 | 数据来源表 | 匹配规则 |
|---|---|---|---|
| 咨询接待 | ×1.0 | cs_record + service_tickets | problem_category 含 咨询/其他/综合;service_category = 咨询接待 |
| 套餐专项 | ×1.8 | cs_record + service_tickets | problem_category 含 套餐/降成;service_category = 套餐疑问 |
| 退款处理 | ×2.0 | refunds + service_tickets | refunds 表全部;service_category = 退款 |
| 退款挽回 | ×2.2 | cs_record | problem_category 含 退款类接待(沟通挽留) |
| 内部投诉 | ×3.0 | cs_record + service_tickets | problem_category 含 投诉;service_category 含 商品/服务投诉 |
| 外部投诉 | ×5.0 | service_tickets + external_complaints + card_complaints | service_item 含 12315/工信部/消协等外部关键词 |
设计原则:难度系数反映处理复杂度和客户情绪烈度。退款金额不计入工作量分,只计退款操作笔数。
三、本职/转接判定
3.1 判定逻辑
if 人员是管理岗 (主管/组长/副主管):
所有专项系数 = 1.0 (管理岗跨类全系数豁免)
elif 该专项是该人员的本职专项 (从 person_specialty_assignments SCD Type 2 查询):
本职系数 = 1.0
else:
转接系数 = 0.2 (固定惩罚,不再乘以专项难度系数)
3.2 按天加权
查询范围为多日时,从 person_specialty_assignments (SCD Type 2) 取每天的专项分配,按天数加权平均:
# 示例:查询 8月10日-8月16日(7天)
# 8月10-12日:本职=咨询接待
# 8月13-16日:本职=套餐专项(调岗)
# 加权本职系数:
# 咨询接待本职:3/7天 = 0.429
# 套餐专项本职:4/7天 = 0.571
3.3 SCD 无数据回退
当 person_specialty_assignments 无记录时,回退到 Person.specialty 字段作为默认全天专项。
四、SN 跨表去重
4.1 设计目标
效率分按 SN(设备序列号/订单号)去重统计接待个数。同一客户多个渠道的记录需合并。
4.2 6 个子查询 UNION ALL
| 子查询 | 来源表 | 分类逻辑 |
|---|---|---|
cs_sns |
cs_record | 按 problem_category 分 6 桶 |
rf_sns |
refunds | → 退款处理 |
cm_ext_sns |
service_tickets | 外部投诉(service_item 含外部关键词) |
cm_int_sns |
service_tickets | 内部投诉(其余投诉) |
tk_sns |
service_tickets(非投诉) | 按 service_category 分桶 |
tk_sns_linked |
service_tickets(handler 为空) | SN 关联 cs_record 找最近操作人 |
4.3 handler 空值补全
工单的 handler 字段为空或为 SYS 时,通过 SN 关联 cs_record 表找最近一次操作人:
-- 使用 DISTINCT ON 替代 LATERAL JOIN(性能提升 115 倍)
SELECT DISTINCT ON (sn) sn, operator, ...
FROM cs_record
WHERE sn = ticket.sn
ORDER BY sn, create_time DESC
五、投诉分类逻辑
5.1 分类决策树
⚠️ 本决策树是绩效专项口径(用于给工作量算难度系数)。其中"微信投诉"在绩效专项里归入"内部投诉专项",但这不代表三源归类——在三源归类口径中微信投诉 = 商户号投诉(见下方注记)。
service_category 为空
→ 100% 投诉(已验证 7.30-8.1 共 883 条空类别,投诉占比 100%)
service_category 含 "投诉"
→ 投诉,再细分:
service_item 含外部关键词 (12315/工信部/消协/监督局/公共服务平台等)
→ 外部投诉(绩效专项)
service_item = 微信投诉
→ 绩效专项归「内部投诉专项」;⚠️ 三源归类中为「商户号投诉」
service_item 含内部关键词 (商品投诉/服务投诉)
→ 内部投诉
其余 → 内部投诉(默认)
service_category 不含 "投诉"
→ 保持原值(退款/套餐疑问/其他/换货/设备故障/网络故障等)
5.2 投诉来源三表合一
| 表 | 覆盖范围 | 时间字段 |
|---|---|---|
service_tickets |
BMS 工单,内部投诉+商户号投诉+部分外部 | create_time / finish_time |
external_complaints |
12315/工信部/监督局等独立投诉 | complaint_time / close_time |
card_complaints |
卡商群投诉 | create_time |
注(2026-09-01): 本算法为绩效专项口径(内部投诉专项 ×3.0 / 外部投诉专项 ×5.0), 与看板三源归类口径(内部/商户号/外部)是两套独立体系, 勿混用:
- 绩效专项: 微信投诉归"内部投诉专项"; 卡商/315 归"外部投诉专项"数据源。
- 三源归类: 微信投诉 = 商户号投诉; 卡商/315 = 外部投诉桶。
5.3 未闭环投诉列表
- 先过滤已完成投诉(Python 层),再统一 LIMIT 200
- SQL 不预先 LIMIT(避免过滤前被截断)
- 微信商户投诉(service_item='微信投诉')单独统计
六、operator → person 匹配
6.1 三层匹配
| 层级 | 匹配方式 | 示例 |
|---|---|---|
| 1. 精确匹配 | PersonAlias.alias = operator | alias='刘思敏' = operator='刘思敏' |
| 2. 前缀兜底 | alias 去前缀后 = operator | alias='生产-刘思敏' → '刘思敏' = operator |
| 3. 部门前缀推断 | 从 alias 前缀推断部门 | '企微-' → 企微, '店铺-' → 店铺, '研发-' → 研发 |
6.2 别名来源
PersonAlias 记录一个人的所有可能的操作员名称(BMS 账号名、SCRM 操作员名、工单处理人名等),用于跨表关联。
七、退款挽回分析
7.1 SN 级别追踪
- 退款挽回团队处理的 SN → 有退款倾向
- 该 SN 后续出现退款工单 → 挽回失败
- 该 SN 被组长/主管处理 → 视为挽回失败
7.2 判定规则
SN 被退款挽回团队成员处理 → 标记为"有挽回处理"
↓
该 SN 是否出现在退款工单中?
是 → 挽回失败
否 → 挽回成功
↓
该 SN 是否被组长/主管处理?
是 → 视为挽回失败(升级处理说明挽回未成功)
同一 SN 可同时计入挽回处理人和退款操作人的工作量(双重计入),用于绩效评估。
八、前端推断逻辑(inferSpecialty)
当后端返回的 current_specialty 为空时,前端按工作量自动推断主专项显示:
8.1 优先级
- 维表登记值:
current_specialty/hr_category有值 → 100% 信任,即使当天全是跨专项 - 工作量推断:合并投诉桶(内部+外部)后与其他 4 专项平级比较,最大桶胜出
- 管理岗兜底:position 含 组长/主管/副主管 → 显示"管理岗"
- 最终兜底:未分组显示"—",其他显示"综合"
8.2 投诉合并桶设计
避免投诉专员因转接了几笔咨询就被误判为"咨询接待":
- 先把
内部投诉 + 外部投诉合并成"投诉"桶 - 与咨询/套餐/退款挽回/退款处理 4 桶平级比较
- 投诉桶胜出后再细分内/外诉
8.3 双标签比例控制
- 第二名工作量 ≥ 第一名的 40% → 显示"主专项+次专项"(如"咨询接待+内部投诉")
- 否则只显示主专项
九、性能优化记录
| 优化点 | 原方案 | 优化后 | 效果 |
|---|---|---|---|
| handler 空值补全 | LATERAL JOIN | DISTINCT ON | 查询时间 115 倍提升 |
| 未闭环投诉 | SQL LIMIT 后过滤 | Python 先过滤再 LIMIT | 避免微信投诉被截断 |
| 按天加权 | 子查询逐天 | CTE 一次查询 | 减少 70% DB 往返 |