docs/ 下 14 个文档(缓存规范/规划设计/arch 架构决策/安全处置/审计报告)内 file:// 链接路径前缀漂移, 导致导航断链. 纯文档改动, 不影响容器镜像, 无需重建.
81 KiB
客服中心管理系统 规划设计
性质:需求(REQ) —— 系统总体设计与需求规划(v0.4)
版本:v0.4(运营看板多粒度 + Group/Specialty 双体系 + SCRM 同步 + 决策看板) · 日期:2026-08-17 状态:数据分析决策系统 + 日常工作流办公支撑系统 说明:v0.2 数据/视图/看板三层底座已落地;v0.3 补齐"报告→审计→措施→跟进→回看"管理闭环;v0.3.1 补齐数据同步与加工实现说明;v0.3.2 升级同步架构 + 看板组件化;v0.4 新增运营看板多粒度切换、Group/Specialty 双体系、SCRM 同步、OCR 自动登录、决策看板 6 大子菜单、人均效率算法、数据采集统一入口(SyncDashboard)、alembic migration 管理 版本演进:v0.1(初版)→ v0.2(审计确认,底座)→ v0.3(管理闭环)→ v0.3.1(数据加工实现补充)→ v0.3.2(同步架构升级 + 看板组件化);冲突时以更高版本为准 v0.3 新增章节:十一 管理理念与设计原则 / 十二 管理闭环模块设计 / 十三 下一步设计与开发规划 v0.3.1 新增章节:十四 数据同步与加工实现补充(含时区加工、去重策略、ai-acc 接入) v0.3.2 新增章节:十五 同步架构 v2(SyncTaskManager 异步任务体系 + 抓取/导入优化)+ 十六 看板组件库与复用体系 v0.3.1 配套说明文件:docs/standards/数据同步与加工说明.md(操作/实现细节,开发者参考) v0.3.2 配套说明文件:同上 v0.3.2 升级版
一、项目背景与定位
1.1 背景
公司有独立的系统运营平台(处理充值、退款、工单等核心业务),但对客户服务中心的日常工作管理支持不到位:事项跟进、紧急事情、绩效考核、排班、退款分析、投诉分析、工作成效等场景缺失。
本系统的定位是:客户服务中心内部的工作流与数据辅助管理系统。
- 数据来源:从公司系统运营平台导出业务数据(CSV/XLSX)→ 上传至本系统
- 不替代运营平台,只做"导出→分析→工作流管理"
- 本质:以设备为核心的「工作流 + 数据分析」平台
1.2 核心理念
- 设备(SN)是领域核心:贯穿退费单、退款工单、钱包提现、商户号退款,是天然主键
- 工作流驱动:借鉴项目/事务管理机制——专项执行、事项跟进
- 数据辅助决策:4 大分析看板服务于日常工作
二、整体架构
2.1 系统分层
┌─────────────────────────────────────────────────────────┐
│ Web管理端 (Vue3 + ElementPlus) 全功能操作(局域网内) │
├─────────────────────────────────────────────────────────┤
│ 后端 API (FastAPI + SQLAlchemy) │
│ ├─ 数据中心:上传解析/upsert/关联匹配 │
│ ├─ 分析服务:运营/现金流/退款分类/人员 │
│ ├─ 工作流:专项执行/事项跟进/设备标签 │
│ └─ 系统:用户/角色/账密登录 │
├─────────────────────────────────────────────────────────┤
│ PostgreSQL │ Redis(队列/缓存) │ 文件存储(上传临时) │
└─────────────────────────────────────────────────────────┘
【推迟】小程序端 (Taro+Vue3) 只读看板+推送:待局域网流程跑通后再开发
2.2 技术栈
| 层 | 技术 | 说明 |
|---|---|---|
| 后端 | Python 3.11 + FastAPI | 异步、自动 OpenAPI 文档、pandas 复用现有分析 |
| ORM/迁移 | SQLAlchemy 2.0 + Alembic | |
| 数据库 | PostgreSQL 15 | 支持窗口函数/JSONB/全文检索 |
| 缓存队列 | Redis 7 | 推送任务/缓存/会话 |
| 数据处理 | pandas + openpyxl | CSV/XLSX 解析,复用现有分析逻辑 |
| Web前端 | Vue3 + Vite + ElementPlus + ECharts + Pinia | |
| 小程序 | Taro4 + Vue3(推迟) | 待局域网流程跑通后开发 |
| 部署 | Docker Compose + Nginx(局域网单机起步) | 内网部署,数据不出内网 |
| 登录 | Web 账密登录 + JWT | 内部系统,小程序微信登录推迟 |
2.3 登录与权限
- Web端:账号密码登录(管理员创建账号)+ JWT Token
- 小程序:微信登录(推迟,待小程序启动时实现)
- 三级角色:
| 角色 | 数据范围 | 主要能力 |
|---|---|---|
| 管理员 | 全量 | 上传数据、配置标签/人员、查看全部分析、管理专项 |
| 主管 | 本组人员 | 查看本组分析、管理本组事项/专项、查看组员绩效 |
| 客服 | 仅本人 | 查看本人操作分析、处理指派给自己的事项/专项 |
三、数据模型设计
3.1 数据分层
第一层 业务原始数据(运营平台导入,增量upsert)
refunds / wallet_withdrawals / service_tickets / merchant_refunds
│
第二层 维度主数据(系统维护)
devices / device_tags / device_tag_rel / merchants / users
│
第三层 工作流数据(用户在系统内创建)
special_tasks / task_devices / task_followups / todo_items / todo_followups
│
第四层 关联与系统
data_match_relations / upload_records / push_messages
3.2 业务原始表(导入层)
refunds 退费单(主键:退费单号)
| 字段 | 类型 | 说明 |
|---|---|---|
| refund_no | varchar PK | 退费单号 RF... |
| platform_order_no | varchar | 平台订单号 SP/WS/WX...(去尾部\t) |
| third_order_no | varchar | 三方订单号 |
| device_sn | varchar FK→devices | 设备SN |
| refund_reason | varchar | 退费原因 |
| package_name | varchar | 套餐名称 |
| merchant_name | varchar FK→merchants | 商户名称 |
| refund_amount | numeric | 退费金额 |
| actual_amount | numeric | 实退金额 |
| status | varchar | 状态(申请中/已退款/无需退款...) |
| refund_method | varchar | 退款方式(线上/线下) |
| auditor | varchar | 审核人 |
| operator | varchar | 操作人(企微-XXX / sys / system / SYS / System) |
| created_at / updated_at | timestamp | 创建/更新时间 |
| raw_extra | jsonb | 原始冗余字段 |
关键业务规则:
operator为sys/system/SYS/System(4 种大小写写法,PostgreSQL 大小写敏感均需排除)表示退到会员钱包(非真实现金流出)。详见 数据时间字段使用规范.md
wallet_withdrawals 钱包提现操作(主键:复合/自增)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigserial PK | |
| account_id | varchar | 账户ID |
| wallet_balance | numeric | 钱包余额 |
| device_sn | varchar FK→devices | SN |
| op_type | varchar | 操作类型(用户提现/订单退费转入) |
| op_amount | numeric | 操作金额 |
| remark | text | 备注(含退费单号 RF...) |
| op_time | timestamp | 操作时间 |
| operator | varchar | 操作人员(SYS/用户提现) |
service_tickets 服务退款工单(主键:工单号)
| 字段 | 类型 | 说明 |
|---|---|---|
| ticket_no | varchar PK | 工单号 GDC/GD... |
| device_sn | varchar FK→devices | SN |
| device_type | varchar | 设备类型 |
| service_category | varchar | 服务类别(退款) |
| service_item | varchar | 服务项(网慢/网卡...) |
| priority | int | 优先级 |
| status | varchar | 状态(待处理/已完成) |
| register_time / active_time / dispatch_time / finish_time | timestamp | 各时间节点 |
| handle_duration | int | 处理时长 |
| registrant | varchar | 登记人 |
| handler | varchar | 处理人(人员绩效来源,企微-XXX) |
| channel | varchar | 录入渠道(H5) |
| order_no | varchar | 订单编号 |
| refund_amount | numeric | 退款金额 |
| estimated_amount | numeric | 预估可退金额 |
| is_appeal | varchar | 是否申诉 |
merchant_refunds 商户号退款(主键:微信退款单号)
| 字段 | 类型 | 说明 |
|---|---|---|
| wx_refund_no | varchar PK | 微信退款单号 |
| trade_time | timestamp | 交易时间 |
| merchant_id | varchar | 商户号 |
| merchant_order_no | varchar | 商户订单号(关联退费单.平台订单号) |
| device_no | varchar FK→devices | 设备号 |
| wx_order_no | varchar | 微信订单号 |
| trade_type / trade_status | varchar | 交易类型/状态 |
| refund_amount | numeric | 退款金额 |
| refund_type | varchar | 退款类型 |
| refund_status | varchar | 退款状态(SUCCESS) |
| settle_amount | numeric | 应结订单金额 |
| fee / rate | numeric | 手续费/费率 |
| order_amount | numeric | 订单金额 |
3.3 维度主数据
devices 设备主表(核心)
| 字段 | 说明 |
|---|---|
| sn PK | 设备SN |
| device_type | 设备类型 |
| device_type_remark | 设备类型备注 |
| active_time | 激活时间 |
| merchant_name | 所属商户 |
| last_refund_time | 最近退款时间(冗余加速) |
| status | 设备状态(正常/清退/涨价...) |
device_tags + device_tag_rel 标签
device_tags:tag_id、tag_name(预设:流量禁用清退/限速清退/限速涨价 + 自定义)、tag_type(预设/自定义)、colordevice_tag_rel:device_sn × tag_id(多对多)+ 打标时间 + 打标人
merchants 商户主数据(来自"各商户号退款数据明细表-商户名称")
子商户名称 / 主商户名称 / 商户号id / 法人 / 超级管理员
3.4 跨表关联关系(数据匹配)
service_tickets ─(device_sn)─────── refunds
service_tickets ─(order_no≈platform_order_no) refunds
refunds ─(refund_no 在 remark 中)── wallet_withdrawals
wallet_withdrawals ─(device_sn)──── refunds
merchant_refunds ─(merchant_order_no≈platform_order_no) refunds
merchant_refunds ─(device_no)────── refunds
refunds ─(merchant_name)────────── merchants
匹配机制(自动+人工补关联):
- 上传后系统按优先级自动匹配(先精确匹配订单号,再 SN,再备注含退费单号)
- 匹配结果写入
data_match_relations(src_table, src_id, dst_table, dst_id, match_type, confidence, matched_by, status) - 匹配不上的标记
status=待关联,在「待关联数据」页面人工补关联 - 后续上传新数据时,自动重新跑匹配,把之前未关联的尝试补全(持续对齐)
3.5 工作流数据
special_tasks 专项任务(项目式)
| 字段 | 说明 |
|---|---|
| id PK | |
| title | 专项名称 |
| task_type | 类型(清退/涨价/限速/其他) |
| operator_tag | 关联设备标签 |
| owner_id | 负责人(用户) |
| status | 待启动→执行中→跟进中→已完成→已归档 |
| deadline | 截止时间 |
| created_by / created_at |
task_devices 专项-设备批次
| 字段 | 说明 |
|---|---|
| id PK | |
| task_id FK | |
| device_sn FK→devices | 批量设备 |
| device_status | 该设备在本专项的进度(待执行/执行中/已完成/异常) |
| note | 单设备备注 |
task_followups 任务跟进记录
| 字段 | 说明 |
|---|---|
| id PK | |
| task_id FK | |
| author_id | 跟进人 |
| content | 跟进内容 |
| status_change | 状态变更记录 |
| created_at |
todo_items 事项/待办(工单式)
| 字段 | 说明 |
|---|---|
| id PK | |
| title | 事项标题 |
| source | 来源(手动/工单触发/专项触发/人工补关联) |
| priority | 优先级(紧急/高/中/低) |
| assignee_id | 负责人 |
| status | 待办/处理中/待确认/已完成 |
| deadline | 截止时间 |
| related_device_sn | 关联设备(可选) |
| related_task_id | 关联专项(可选) |
| created_at |
todo_followups 待办跟进记录(时间线)
id / todo_id / author_id / content / created_at
四、功能模块设计
4.1 模块总览
| 模块 | MVP | 后期 | 说明 |
|---|---|---|---|
| 数据中心-上传管理 | ✅ | CSV/XLSX 上传、解析、upsert | |
| 数据中心-待关联数据 | ✅ | 人工补关联 | |
| 数据中心-上传记录 | ✅ | 批次历史 | |
| 分析-运营分析 | ✅ | 退款趋势/笔数/原因分布 | |
| 分析-现金流分析 | ✅ | 真实提现/钱包余额/商户对账 | |
| 分析-退款分类分析 | ✅ | 降成清退/涨价/限速 | |
| 分析-人员操作分析 | ✅ | 处理量/时效/退金额 | |
| 设备管理 | ✅ | 设备列表、标签(预设) | |
| 事项跟进 | ✅ | 工单式待办+时间线 | |
| 用户/角色/登录 | ✅ | 三级角色+账密JWT | |
| 专项执行工作流 | ✅ | 项目式任务+设备批次+跟进 | |
| 小程序只读看板+推送 | ✅ | 推迟:局域网流程跑通后 | |
| 绩效考核 | ✅ | 指标配置+统计 | |
| 排班 | ✅ | 客服排班表 | |
| 投诉分析 | ✅ | 独立投诉工单分析 |
4.2 数据中心
上传管理
- 支持文件类型:CSV(utf-8/gbk 自动识别编码)、XLSX(多 sheet)
- 上传时选择「数据类型」(退费单/钱包提现/退款工单/商户号退款)
- 列名自动映射(系统预置模板),允许手动调整列对应关系
- 预览前 10 行 → 确认 → 执行导入
- 增量 upsert:按主键去重,已存在则更新状态/金额/时间字段,新增则插入
- 导入结果报告:新增 X 条 / 更新 Y 条 / 失败 Z 条(附错误明细)
待关联数据
- 列出自动匹配后
status=待关联的记录 - 支持按表、按时间筛选
- 人工选择匹配对象,确认后写入
data_match_relations - 显示「上次未关联现已自动补全」的记录数
4.3 四大分析看板
看板1:运营分析
| 指标 | 维度 | 图表 |
|---|---|---|
| 退款趋势 | 按日/周/月 | 折线图(退款金额+笔数双轴) |
| 充值vs退款 | 按日 | 柱状对比 + 退款率 |
| 笔均退款金额 | 按日 | 折线 |
| 退费状态分布 | 状态 | 饼图 |
| 退费原因 TOP10 | 原因 | 横向柱状 |
| 退款方式占比 | 线上/线下/钱包 | 饼图 |
看板2:现金流分析
| 指标 | 维度 | 图表 |
|---|---|---|
| 真实现金流出趋势 | 按日(商户号退款) | 折线 |
| 钱包余额分布 | 按账户 | 表格 |
| 退回钱包 vs 实际提现 | 按日 | 对比柱状(暴露提现缺口) |
| 商户号对账 | 按商户 | 表格(退款金额/笔数/费率) |
| 提现不受控预警 | 异常提现 | 列表 |
| 现金流净额 | 按日 | 面积图 |
看板3:退款分类分析
| 指标 | 维度 | 图表 |
|---|---|---|
| 降成分类汇总 | 清退/涨价/限速 | 饼图+金额 |
| 各分类趋势 | 按日 | 多折线 |
| 清退退款明细 | 设备级 | 表格 |
| 涨价前后对比 | 商户 | 对比 |
| 专项执行进度 | 按专项 | 进度条 |
看板4:人员操作分析
| 指标 | 维度 | 图表 |
|---|---|---|
| 处理工单量排名 | 按人(处理人) | 横向柱状 |
| 平均处理时效 | 按人 | 柱状 |
| 退款审批金额 | 按人(审核人) | 柱状 |
| 操作类型分布 | 按人 | 堆叠柱 |
| 操作时间热力 | 按人×时段 | 热力图 |
| 异常操作 | 高频/非工时 | 列表 |
4.4 设备管理
- 设备列表:搜索(SN/商户/标签)、筛选、详情(聚合该设备所有退费/工单/提现/现金流)
- 标签管理:预设标签 + 管理员新增自定义标签、颜色
- 设备打标:单个/批量打标
4.5 事项跟进(工单式)
- 待办列表:按状态(待办/处理中/待确认/已完成)、按负责人、按优先级筛选
- 待办详情:基本信息 + 跟进时间线(评论式)+ 状态流转 + 关联设备/专项
- 来源:手动新建 / 工单触发(紧急工单自动生成) / 专项触发
- 紧急事项标红 + 截止时间预警
4.6 小程序(只读)—— 推迟
待局域网流程跑通后再开发:
- 首页:核心指标卡片(今日退款额/待办数/紧急事项)
- 分析看板(精简版,复用 Web 接口)
- 待办列表(查看,不可操作)
- 消息推送(紧急工单/待办到期/专项进度)
- 微信登录(openid) + 绑定账号
五、技术方案
5.1 项目目录结构
csctalon/
├── 01样本数据/ # 样本数据(已存在)
├── docs/ # 文档
├── backend/ # FastAPI 后端
│ ├── app/
│ │ ├── api/v1/ # 路由(uploads/analytics/tasks/todos/users)
│ │ ├── core/ # 配置/安全/依赖
│ │ ├── models/ # SQLAlchemy 模型
│ │ ├── schemas/ # Pydantic 模型
│ │ ├── services/ # 业务逻辑
│ │ │ ├── data_parser.py # CSV/XLSX 解析+列映射
│ │ │ ├── upsert.py # 增量upsert
│ │ │ ├── matcher.py # 跨表关联匹配
│ │ │ └── analytics/ # 4大分析查询
│ │ └── main.py
│ ├── alembic/ # 数据库迁移
│ ├── tests/
│ └── pyproject.toml
├── web/ # Vue3 Web管理端
│ ├── src/
│ │ ├── views/ #数据中心/分析/设备/事项/系统
│ │ ├── components/
│ │ ├── api/
│ │ ├── stores/ # Pinia
│ │ └── router/
│ └── package.json
├── miniapp/ # Taro 小程序
│ ├── src/
│ └── config/
├── deploy/ # Docker Compose + Nginx
└── docker-compose.yml
5.2 数据上传处理流程
上传文件 → 识别编码/格式 → pandas读取 → 列名映射(模板)
→ 校验(必填/类型) → 预览 → 确认导入
→ 事务内 upsert(按主键 ON CONFLICT)
→ 触发关联匹配任务(异步)
→ 返回导入报告
5.3 关联匹配实现
- 匹配任务入 Redis 队列,worker 异步执行
- 匹配规则按优先级(订单号精确 → SN精确 → 备注正则提取退费单号)
- 增量更新后,对新数据 + 之前未关联数据重跑匹配
5.4 部署(局域网)
# docker-compose.yml 简述
services:
db: postgres:15 # 数据持久化挂载到宿主机卷
redis: redis:7
backend: python+fastapi (gunicorn+uvicorn) # 端口8000
web: nginx 静态托管 vue build # 端口80/443
# 部署在客服中心内网服务器,员工通过内网IP访问
# 数据不出内网;后续小程序启动时再加公网入口
六、开发路线图
第一期 MVP(本次目标,预计 4-6 周,局域网部署)
- 基础骨架:项目脚手架、Docker、数据库模型与迁移
- 用户/角色/登录:三级角色、Web 账密登录、JWT
- 数据上传:4 张表导入、列映射、upsert、导入报告
- 关联匹配:自动匹配 + 待关联数据页 + 人工补关联
- 设备管理:设备主数据、预设标签、设备打标
- 4 大分析看板:运营/现金流/退款分类/人员
- 事项跟进:工单式待办 + 时间线
第二期(局域网流程稳定后,1-2 月)
- 专项执行工作流(项目式任务+设备批次+跟进+状态流转)
- 自定义标签扩展、设备批量操作
- 数据关联规则可配置化
第三期(启动小程序,需公网入口)
- 小程序只读看板(Taro+Vue3)
- 微信登录(openid) + 绑定账号
- 推送消息(订阅消息、规则配置)
第四期(后续)
- 绩效考核(指标配置+周期统计+导出)
- 排班管理
- 投诉分析(独立投诉工单模块)
- 工作成效综合看板
七、关键决策记录(ADR)
| # | 决策 | 选择 | 理由 |
|---|---|---|---|
| 1 | 数据更新策略 | 增量 upsert | 支持状态变化,持续对齐关联 |
| 2 | 技术栈 | Python+FastAPI / Vue3 / Taro | 数据处理生态强,前后端技术栈统一 |
| 3 | 权限模型 | 三级角色(管理员/主管/客服) | 满足绩效与数据隔离 |
| 4 | 部署 | 局域网单机 Docker Compose | 内部系统,数据不出内网;小程序启动时再加公网 |
| 5 | 登录 | Web 账密 + JWT | 内部系统;小程序微信登录推迟 |
| 6 | 小程序 | 推迟到第三期 | 先确保局域网流程跑通再开发 |
| 7 | 关联匹配 | 自动+人工补关联 | 平衡自动化与准确性 |
| 8 | 专项任务 | 项目式生命周期 | 工作流管理核心 |
| 9 | 设备标签 | 预设+可扩展 | 兼顾现有分类与未来扩展 |
| 10 | 事项跟进 | 工单式 | 适合客服中心日常管理 |
| 11 | 分析维度 | 4 块看板 | 运营/现金流/退款分类/人员 |
| 12 | 领域核心 | 设备(SN) | 贯穿所有业务表 |
八、待确认事项(v0.2 更新)
| # | 事项 | 状态 | 结论 |
|---|---|---|---|
| 1 | 局域网服务器 IP/配置 | ✅ 已确认 | 配置充足,硬件非瓶颈;具体 IP/Nginx 部署时定 |
| 2 | 数据导出周期 | ✅ 已确认 | 每日导出(主要反映前一日),当日可补;去重/更新由导入预览页保障 |
| 3 | 绩效考核口径 | ✅ 已确认 | 不在本系统核算,有专门算法;本系统只做数据汇总,绩效口径手动配置解读 |
| 4 | 人员名单来源 | ✅ 已确认 | 本系统维护「辅助人员表 + 别名」统一人员,从各表提取候选别名,管理员确认归并 |
| 5 | 数据保留期 | ⏸ 暂缓 | 后续再定,不影响 MVP |
| 6 | 数据备份策略 | ⏸ 暂缓 | 后续再定 |
| 7 | 智能助手处理记录表结构 | ❓ 待补样本 | 需样本文件/字段清单才能定模型 |
| 8 | 自助分析引擎形态 | ✅ 已确认 | 可视化视图构建器(见 §1) |
| 9 | 跨表累加机制 | ✅ 已确认 | 分表聚合后相加,不 JOIN(见 §1) |
| 10 | 动态分类规则形态 | ✅ 已确认 | 条件规则引擎(见 §1) |
| 11 | 发布页(策略/规范)形态 | ✅ 已确认 | 策略规范文档+版本+必读回执(见 §6) |
| 12 | 领导报表导出形态 | ❓ 待拍板 | PDF/Excel/只读链接 三选一 |
小程序 AppID、公网域名等延后到第三期启动时再确认。
九、审计确认决议(v0.2)
基于 2026-07-26 的 50 题审计问答,确认以下 7 项架构级转向与具体口径。v0.1 与本节冲突处以本节为准。
§1 核心定位转向:自助式数据分析引擎(取代"4 大固定看板")
触发回答:A4 / A5 / E27 / E29
决议:
- 系统核心不再是 4 个硬编码看板,而是一个可配置的数据分析引擎:
- 数据全量导入后,用户在导入表上动态选择字段组合(维度+度量+筛选+时间)做聚合
- 支持跨表累加(如表 A 的某度量 + 表 B 的某度量)
- 支持动态分类/分组(如把清退/涨价/限速归为一类;把某几个人归为"投诉专项")
- 原 4 大看板降级为预设分析视图(运营/现金流/退款分类/人员),用户可克隆改写
- 架构含义:需要新增「数据源注册 + 字段元数据 + 分析视图定义 + 分类规则」四件套,使新表加入无需改代码
- 灵活性优先于角色:A5 明确——数据分析引擎+导入框架是地基,用户角色可后置
引擎形态(已确认):可视化视图构建器
- 图形化拖拽:选数据源 → 选维度(分组) → 选度量(sum/count/avg) → 设筛选 → 选时间字段+区间 → 选图表类型
- 视图可命名保存、克隆改写、设为预设
- 引擎按定义自动生成参数化 SQL,前端按图表类型渲染(折线/柱/饼/表/热力/面积)
跨表累加(已确认):分表聚合后相加,不 JOIN
- 「复合度量」定义 = 度量项列表:[(数据源, 字段, 聚合, 筛选), ...],各自 SUM 后相加
- 不要求行级对齐,不依赖关联匹配质量(与 §5 弱化匹配一致)
- 适用于汇总看板;单设备/单订单审计仍走关联视图(后续)
动态分类(已确认):条件规则引擎
- 规则结构:
if 字段 op 值 then 分组标签,可叠加多条 - 示例:
operator ∈ [张三,李四] → 清退专项;device 含标签=清退 → 清退类;refund_reason contains 网络 → 网络类 - 规则存库、可复用、可按视图挂载;聚合时按"分组标签"维度汇总
§2 数据导入升级:预览-复核-确认工作流(取代"直接 upsert")
触发回答:B8 / B9 / B12
决议:
- 导入流程改为:解析 → 临时预览表 → 复核 → 确认提交
- 已存在且一致的数据:折叠
- 新增数据:高亮"将新增"
- 异常/不一致数据:红色标注,可选更新/忽略/修复
- CSV 字段内换行导致拆行:在解析阶段检测并修复(引号包裹判定)
- 编码问题(GBK/UTF-8)由"解析一次+人工复核"兜底
- 原始文件按日期备份存档(uploads/yyyy-mm/)
- 导入失败明细支持 查看/修复/确认/忽略 闭环;系统快速迭代适配新问题
- 匹配关联在导入时执行并记日志(D25)
§3 人员统一化:辅助人员表 + 别名机制
触发回答:C13 / H42
决议:
- 新增
persons辅助人员表(本系统维护)+person_aliases别名表 - 各业务表中的
operator/auditor/handler/registrant等"人名"字段视为别名,映射到统一person_id sys/system/SYS/System(4 种大小写写法,均需排除)标记为系统自动操作,不归并到任何真人- 候选别名从导入数据中自动提取,管理员确认归并(同名区分、一人多别名)
- 人员离职/调岗:停用保留历史,不物理删除
§4 数据模型对齐原始表 + 数据源可扩展注册
触发回答:A5 / C17 / B6
决议:
- 业务表结构尽量与原始导出表一致,必要时仅增加索引字段;不擅自归一化平台字段(如商户订单号,C16)
- 新增
data_sources元数据表:注册每张业务表的字段、类型、语义角色(维度/度量/时间/金额/人员/SN/类别) - 新表加入只需注册元数据 + 建表迁移,分析引擎自动识别可用
- 新增数据源「智能助手处理记录」:客服接待/操作记录,用于退款挽回成功率、客服工作负荷、接待量、工作时段分布(15/30min 热力);可关联退款/接待/投诉/套餐专项
wallet_withdrawals业务唯一键需明确(C14:平台唯一即系统唯一,需定义去重键)service_tickets工单可流转(C15),handler 需支持历史记录
§5 关联匹配弱化:不强制匹配,允许空悬
触发回答:D23 / D24 / D25
决议:
- 匹配在导入时执行,写入
data_match_relations并记日志 - 匹配不上的记录空悬,不强求每笔订单/SN 都匹配
- 重点关注现金与经营分析,非逐单审计;数据完善后可对单 SN/订单追溯
- 待关联量级:千级封顶,随时间递减
- 匹配优先级:订单号精确 → SN 精确 → 备注(仅参考);不做模糊匹配
- 已人工确认的关联在重跑时是否锁定——待定(建议锁定)
§6 用户角色简化 + 事项体系统一
触发回答:H41-43 / J48 / F34-36 / G37-40
决议:
- 主要使用者:组长/主管/管理层;普通客服基本不用
- 普通客服仅访问**「发布页」**:查看当前在执行策略/规范/要求,统一发布统一跟进(政策常变,需一处保证全员一致)
- 三级角色简化为:管理员 / 主管 / 只读(客服)
- 专项执行 + 待办 统一为一个通用事项模块:分派、跟进、管理、统计
- 通用字段:标题、负责人、状态、截止、关联设备/专项、跟进时间线
- 专项是"项目式"事项,待办是"工单式"事项,同一套数据结构 + 类型区分
- 设备"打标"重新定义为「专项登记」:仅记录专项时间、SN 录入时间、处理完成时间(完成时间可由系统关联匹配)
- 不做"设备操作",设备页是分析视角的聚合展示
发布页(已确认):策略规范文档 + 版本 + 必读回执
- 管理员发布富文本策略/规范文档,支持版本号、置顶、必读标记
- 客服登录后看到未读策略列表,标记已读回执(可统计谁未跟进)
- 文档历史版本可追溯,政策变化时出新版本,旧版归档
- 与「通用事项」联动:重要策略可一键派发跟进事项
§7 口径确认清单
| 项 | 口径 |
|---|---|
| 真实现金流出(全域统一核算 v4 · 双视角) | 经营估算(经营侧四路登记出款) = A.退费单线上直退(refunds refund_method='线上')+ B.钱包用户取现(wallet_withdrawals op_type='用户提现')+ C.闪猫退款(shanmao_refunds 独立表,status=已退款)+ D.手动退款(manual_refunds 独立表,is_refunded=是,来源=商户号手机退款处理登记.xlsx);实际现金流(对账基准) = E.refund_record_reports WHERE refund_status IN ('退款成功','成功','SUCCESS') 合计(不分 ORIGINAL/BALANCE 桶,BMS 退款记录报表每天采集 + 文件导入补历史,不与四路累加;2026-09-05 起替代 merchant_refunds 快照);对账偏差 = 经营估算 − 实际现金流 = (A+B+C+D) − E。详见 数据时间字段使用规范.md §2.4 + .trae/documents/商户号现金流视图修正方案.md v1.1 |
| 退回钱包 vs 订单退费转入 | 退回钱包 ≥ 订单退费转入(部分金额如赠送不可提现);实际提现 = 用户提现 |
| 充值记录来源 | 商户现金流表(各商户号退款数据明细表中的现金流 sheet) |
| 金额精度 | 统一 2 位小数,直接 SUM |
| 时间口径 | 用原始表时间统计;本系统创建数据才记系统时间 |
| 商户号 vs 名称 | 基本 1:1,不归一化 |
| 看板时间粒度 | 日/周/月 + 同比环比 |
| 热力图粒度 | 15min 或 30min,用于排班参考 |
| 看板刷新 | 实时查询即可,频度低无需预聚合(暂) |
| 各商户号退款明细表 | 暂不考虑作为独立数据源,其中现金流 sheet 后续再议 |
| 退费汇总.xlsx | 仅汇总报表,不作为数据源 |
| 操作日志 | 落库可查 |
| 数据备份/保留 | 暂缓 |
§8 分析引擎数据模型骨架(落地核心)
这是 §1 引擎的落地表结构。4 张元数据表 + 1 张视图执行缓存,使"加新表/加新分析"零代码。
1) data_sources 数据源注册
| 字段 | 说明 |
|---|---|
| id PK | |
| code | 数据源代码(如 refunds / wallet_withdrawals / service_tickets / cs_records) |
| table_name | 实际物理表名 |
| name_cn | 中文名(退费单/钱包提现/...) |
| source_type | 业务原始/本系统创建 |
| time_field | 默认时间字段(用于按日/周/月聚合) |
| sn_field | SN 字段(用于设备维度关联) |
| status | 启用/停用 |
2) data_source_fields 字段元数据
| 字段 | 说明 |
|---|---|
| id PK | |
| source_id FK | |
| field_name | 物理字段名 |
| field_name_cn | 中文名 |
| data_type | string/numeric/timestamp/bool |
| semantic_role | dimension(维度) / measure(度量) / time / amount / person / sn / category |
| agg_func | 度量默认聚合 sum/count/avg(仅 measure 有) |
| is_filterable | 是否可在筛选器出现 |
| enum_values | 枚举值(如 refund_method: 线上/线下/钱包),可空 |
新表接入:建表迁移 → 在 data_sources 注册一行 → 在 data_source_fields 注册字段 → 引擎自动识别为可选数据源
3) analysis_views 分析视图定义(核心)
| 字段 | 说明 |
|---|---|
| id PK | |
| name | 视图名(如"运营-退款趋势") |
| category | 分组(运营/现金流/退款分类/人员/自定义) |
| chart_type | line/bar/pie/table/heatmap/area/composite |
| time_granularity | day/week/month |
| time_range | 默认时间区间或动态(近7日/本月) |
| yoy_mom | 是否含同比环比 |
| dimensions | JSONB:分组维度字段列表 [{source, field}] |
| measures | JSONB:度量列表 [{source, field, agg, filter}](多源即跨表累加) |
| filters | JSONB:全局筛选 [{source, field, op, value}] |
| classification_rule_ids | 挂载的分类规则(按规则结果做分组) |
| is_preset | 是否预设(4 大看板=预设) |
| owner_id | 创建人 |
| status | 草稿/启用/归档 |
4) classification_rules 分类规则
| 字段 | 说明 |
|---|---|
| id PK | |
| name | 规则名(如"清退专项人员") |
| target_source | 作用于哪张数据源 |
| target_field | 作用于哪个字段(如 operator) |
| conditions | JSONB:条件列表 [{field, op, value}](op: in/contains/eq/between) |
| group_label | 命中后归入的分组标签(如"清退专项") |
| priority | 多规则冲突时优先级 |
| enabled | 启用 |
5) view_results_cache 视图结果缓存(可选,频度低可先不做)
| 字段 | 说明 |
|---|---|
| view_id FK | |
| params_hash | 参数(时间区间+筛选)哈希 |
| result_json | 聚合结果 JSON |
| computed_at | 计算时间 |
| ttl | 缓存有效期 |
引擎执行流程
用户打开视图 → 读 analysis_views 定义
→ 按 measures/sources 拆分多个子查询
→ 每个子查询:SELECT dims, agg(measure) FROM table WHERE filters GROUP BY dims
→ 应用 classification_rules(CASE WHEN 注入到 SELECT/ GROUP BY)
→ 若跨表累加:各子查询 SUM 后按相同维度键相加
→ 合并结果 → 按时间维度填充空区间 → 计算同比环比
→ 返回前端按 chart_type 渲染
与现有代码的关系
- 现有 backend/app/api/v1/analytics.py 的硬编码看板接口 → 降级为 4 个预设视图的数据来源(首版可直接复用,逐步迁到引擎)
- 现有 web/src/views/analytics/ 4 个看板 → 首版保留,引擎稳定后改为「视图渲染器」统一承载
- 新增 backend/app/services/analytics/engine.py 引擎核心 + web/src/views/analytics/ViewBuilder.vue 视图构建器
十、v0.2 修订后的 MVP 范围(建议)
基于 §九 决议重排优先级。原 v0.1 路线图作废,以此为准。
| 优先级 | 模块 | 说明 |
|---|---|---|
| P0 | 数据源注册 + 字段元数据 | 引擎地基,4 张业务表先注册 |
| P0 | 导入预览-复核-确认工作流 | 含 CSV 换行修复、编码兜底、文件备份 |
| P0 | 辅助人员表 + 别名 | 人员统一,贯穿所有分析 |
| P0 | 分析引擎核心(视图构建器+执行器) | 含分类规则、跨表累加 |
| P0 | 4 个预设视图(运营/现金流/退款分类/人员) | 用引擎实现,复用现有口径 |
| P1 | 通用事项模块(待办+专项统一) | 含跟进时间线、状态流转 |
| P1 | 发布页(策略规范+版本+必读回执) | 客服只读入口 |
| P1 | 关联匹配(导入时执行+日志+空悬) | 弱化版,不做待关联页 |
| P1 | 操作日志落库 | 谁上传/改了什么 |
| P2 | 智能助手处理记录数据源 | 需补样本后设计 |
| P2 | 领导报表导出 | 待定形态 |
| P3 | 角色权限细化 | 引擎稳定后再做 |
| P3 | 小程序 / 绩效 / 排班 / 投诉 | 后续迭代 |
十一、管理理念与设计原则(v0.3)
v0.2 解决了"数据看得见",v0.3 要解决"管理管得成闭环"。以下原则来自部门管理视角的需求复核,贯穿后续所有模块设计。
11.1 追溯是为了预防
异常事件、审计结论的持续记录不是为留档而留档,而是构建"持续结论": 异常登记 → 与整体运营效果关联分析 → 形成可复用结论 → 作为跨部门协作的沟通抓手 → 推动上游/相关部门及时同步。
没有持续记录的结论,跨部门沟通就没有抓手,协调会变成"口头说一下"。
11.2 归因不归责
审计与周报是管理层内部分析与工作报告,目的是找问题、改流程,不是追究个人责任。
- 不回避问题:数据异常、措施失效必须如实呈现
- 不挂钩个人绩效扣分:审计结论不直接用于绩效扣罚
- 异常事件登记用于改进,瞒报才是问题
11.3 闭环验证(PDCA 的 C/A)
每条管理措施强制带三字段,到期回看,避免"措施发了就算完":
预期目标(量化指标或定性描述)验证时间(到期日)验证方式(看哪个视图/指标/抽查)
到期自动进入"待回看"队列,挂到下周周报/下次审计;周例会对到期措施做一次效果评估并记录结论(生效/部分生效/未生效/需调整)。未生效的转为新措施或升级处理。
只审到期措施,不每周重复审全部措施,控制会议成本。
11.4 分层审计
- 大项过会审:周报 10 项框架,每项在例会上审查评判、备注说明
- 子项抽查留档:工单/设备级颗粒度,会议存疑时由主管/专员/组长抽查部分内容审查并留档
- 组长自查:日常一笔带过,组长自行检查对应人员和记录,提交简单说明
避免逐单全审导致的会议膨胀。
11.5 日调整围绕统一目标
"每天调整措施"不是对同一规则反复改,而是各局部细节围绕同一目标多维优化:增人、优化话术、培训、分流等。日级调整限定在战术微调,战略级口径/权限不宜日变。每条日调整可追溯到周报,回答"这周改了几次、为什么改、改完见效没"。
11.6 占位预留(不过度建设)
以下模块第一版只占位,待条件成熟再扩充:
- 绩效考核:各项数据尚未完全入系统,算法政策未导入,预留接口与数据汇聚
- 数据真实性识别:异常数据模式识别(挽回率异常高、投诉分类集中不可考核类等),先留字段,后续扩充规则
- 考勤排班:依赖考勤数据源,整体规划后落地
11.7 员工赋能视角
系统不能只有管理者视角。客服员工登录后应看到:
- 我本周接待趋势、挽回率进步(纵向比自己,非横向排名)
- 我的待跟进事项
- 我该读的政策(未读策略)
把管理工具变赋能工具,提升接受度。
11.8 跨部门反向管理
客服是下游,很多问题根因在上游。系统帮客服部给上游"打分": 上游问题登记 → 派发对象 → 响应时长 → 解决率 → 闭环状态
让客服部有数据支撑去推动上游改进,不再只是"背锅的下水道"。
11.9 管理成本核算
每个管理动作(登记/审计/跟进/报表)都计入管理成本。原则:
- 砍掉没人看、不决策的报表
- 措施/审计/跟进的字段能简则简,抓核心
- 管理的目的是改进行动,不是生产文档
十二、管理闭环模块设计(v0.3)
闭环主线:动态数据 → 锁定生成报告 → 逐项审计 → 附注结论 → 输出管理措施 → 措施跟进 → 到期回看 → 时间序列回看运营。
12.1 异常事件登记(Incident)
定位:未通知的非预期事项,造成客服工作负荷突然激增。是周报"异常事故记录"、时间序列气泡图、跨部门协作的共同数据源。
| 字段 | 说明 |
|---|---|
| id PK | |
| title | 事项名 |
| subject | 主体(涉及的业务/设备/系统) |
| detail | 明细描述 |
| registrar_id | 登记人 |
| impact | 影响(量化:工单增量/涉及金额/影响人数) |
| occurred_at | 登记时间(发生时间) |
| duration | 持续时间(分钟/小时) |
| related_tickets | 关联工单号列表 |
| status | 登记/处理中/已平息/已复盘 |
| converted_to_expected | 是否转为预期事项(复盘后纳入提前部署) |
- 转化链路:异常发生→登记→复盘→转预期事项→下次提前部署(形成异常→预防的闭环)
- 自动识别(占位):某时段工单/投诉量超基线 N 倍,系统主动标记"疑似异常"触发登记;人从"登记员"变"确认员"
- 铁律:异常登记用于改进不用于问责,否则瞒报
12.2 管理措施(Measure)—— 独立一等公民
定位:审计/周报的输出物,持续跟进的对象。与"专项任务(外部协调执行)""事项跟进(日常待办)"职责分离。
| 字段 | 说明 |
|---|---|
| id PK | |
| title | 措施标题 |
| owner_id | 负责人 |
| measure_type | 内部管理 / 外部协调 |
| source | 来源:审计/周报/异常事件/手工 |
| related_report_id | 关联报告(来源追溯) |
| expected_goal | 预期目标(量化或定性) |
| verify_time | 验证时间(到期日) |
| verify_method | 验证方式(看哪个视图/指标/抽查) |
| status | 草稿/执行中/待回看/已生效/未生效/已归档 |
| valid_from / valid_to | 有效起止(措施也有生命周期) |
| review_result | 回看结论(生效/部分生效/未生效/需调整) |
| review_note | 回看备注 |
- 到期回看:verify_time 到期进"待回看"队列,挂下周周报/下次审计;支持手动触发 + 自动定时扫描双模式
- 生命周期:措施失效自动归档,避免堆积
- 与现有模块区分:SpecialTask=外部专项执行;TodoItem=日常事项跟进;Measure=管理措施(审计/周报输出物)
12.3 报告与审计(Report + Audit)
定位:需求核心——"只有报告才能审计""报告固化数据视图""报告与审计结果都要保存"。
Report 报告(数据快照)
| 字段 | 说明 |
|---|---|
| id PK | |
| name | 报告名(如"2026-W30 退款专项审计报告") |
| report_type | 周报/专项审计/自定义 |
| time_range | 锁定的时间区间 |
| filters | 锁定的筛选条件(JSONB) |
| snapshot | 视图配置 + 执行结果快照(JSONB,仅固化管理需用到的关键数据,不做全表数据快照;大部分源数据在库中不常变) |
| pdf_archive | 归档PDF(可选,正式归档时生成) |
| view_ids | 包含的视图列表 |
| status | 草稿/已确认/已归档 |
| created_by / created_at |
AuditNote 审计附注
| 字段 | 说明 |
|---|---|
| id PK | |
| report_id FK | 关联报告(只有报告才能审计) |
| target_view_id | 审计的对象视图/大项 |
| conclusion | 审计结论(附注) |
| judgment | 评判(正常/异常/需改进) |
| sampled_tickets | 抽检工单号列表(细化到工单级) |
| attachments | 贴图(聊天记录截图等) |
| output_measure_id | 输出的管理措施(关联 Measure) |
| author_id / created_at |
- 审计闭环:报告(快照)→ 审计附注(结论+贴图+抽检)→ 输出管理措施 → 措施到期回看 → 下次审计回头看
- 抽检:可按设备/工单号/套餐金额等筛选出具体工单审计
- 贴图:从接待聊天记录截图附件;内网本地目录存储(按报告/日期分目录),暂不上对象存储(文件量小、单机内网、无公网分发需求);存储层抽象接口,后续量大可平滑迁对象存储
12.4 周报(WeeklyReport)
定位:团队级报告 + 逐项审查 + 措施产出。复用报告/审计机制,不另起炉灶。
周报框架(10 项大项):
- 措施计划跟进(上周措施到期回看)
- 本周总体接待及人均趋势(接待量/日均/人均每天)
- 本周分项接待汇总(投诉/退款/套餐问题/其他)
- 各组接待量分析
- 退款挽回专项分析
- 投诉专项分析(内部投诉/商户号投诉/外部投诉三源 + 315·质量监督局/卡商归外部 + 投诉原因分析)
- 问题汇总
- 措施计划(输出下周)
- 跨部门信息协调(含上游打分)
- 异常事故记录
各项数据源映射:
| 大项 | 数据源 | 口径 |
|---|---|---|
| 1 措施计划跟进 | Measure | 当前所有激活状态(执行中/待回看)措施汇总说明 |
| 2 总体接待及人均趋势 | cs_records 智能助理记录 | 总体接待量/日均/人均每天 |
| 3 分项接待汇总 | cs_records | 投诉/退款/套餐问题/其他 分项 |
| 4 各组接待量分析 | cs_records + 人员职务/分组 | 结合人事资料做各组分项统计及趋势 |
| 5 退款挽回专项 | cs_records(退款项接待) − refunds(实际退款设备SN) | 集合差:涉及退款的接待设备SN 减去 实际退款设备SN = 挽回;产出统计/趋势/成功率 |
| 6 投诉专项分析 | service_tickets + 补充表 | 从服务工单筛选三源(内部/商户号/外部), 315·质量监督局与卡商归外部投诉 |
| 7 问题汇总 | 综合 | 各项问题归集 |
| 8 措施计划(输出下周) | Measure(新建) | 周报产出物直接进队列 |
| 9 跨部门信息协调 | UpstreamTicket | 登记记录 + 上游打分 |
| 10 异常事故记录 | Incident | 登记记录 |
核算维度说明:
- 退款挽回:按设备SN核算(集合差:涉及退款的接待设备SN − 实际退款设备SN = 挽回设备);产出挽回设备数/挽回率/趋势
- 接待绩效/接待评估:按接待单核算(每笔接待的处理质量/结果/时效);设备数量作为辅助评估维度(一人管多少设备)
两者维度不同:挽回看"设备最终是否退款"(结果导向),绩效看"每笔接待怎么处理"(过程导向)
- 逐项审查:大项过会审+评判备注;子项抽查留档
- 备注连接管理措施:审查备注可一键派生 Measure
- 输出下周措施计划:周报产出物直接进 Measure 队列
- 双轨节奏:周复盘 + 日微调,日调整可追溯到周报
12.5 跨部门反向管理(UpstreamTicket)
| 字段 | 说明 |
|---|---|
| id PK | |
| issue | 问题描述 |
| upstream_dept | 派发对象(上游部门) |
| dispatched_at | 派发时间 |
| responded_at | 上游响应时间 → 算响应时长 |
| resolved_at | 解决时间 → 算解决率 |
| status | 待响应/处理中/已解决/挂起 |
| source_report_id | 来源报告/周报 |
| score | 上游打分(响应/解决) |
- 汇总输出"上游部门响应时长/解决率"排行,作为客服部推动上游的抓手
12.6 员工视角(MyWorkspace)
客服登录后首页:
- 本周接待趋势(我的接待量折线)
- 挽回率进步(纵向比自己上周)
- 我的待跟进事项(TodoItem 过滤 assignee=我)
- 我该读的政策(未读 StrategyDoc)
12.7 时间序列气泡图(运营回看)
定位:管理复盘神器。横轴时间,主曲线为运营指标(接待量/投诉量/退款挽回金额单数),气泡叠加:异常事件、管理措施、当时人员数量,箭头对齐时间轴。
- 依赖:异常事件 + 管理措施 + 人员数量(考勤/排班)三类数据对齐时间轴
- 价值:回答"那周退款激增到底因为异常、人少、还是措施没落地"
12.8 报告索引与批注(ReportList + ReportComment)
定位:报告/周报不是一次性产物,而是可持续批注、评价、展示的"活文档"。生成后仍可被反复查阅、讨论、评价,批注可触发措施,强化闭环。
报告索引页
- 列表展示所有 Report + WeeklyReport
- 筛选:按类型(周报/专项审计/自定义)/时间范围/状态
- 每条显示:名称、类型、时间范围、状态、批注数、最近批注时间
- 点击进入报告详情页
报告详情页
- 顶部:报告元信息(时间范围、筛选条件、生成时间、状态)
- 主体:视图快照渲染(复用 ViewRender)
- 侧栏/底部:批注时间线(按时间累积)
ReportComment 报告批注
| 字段 | 说明 |
|---|---|
| id PK | |
| report_id FK | 关联报告 |
| target_type | 整体 / 视图级(第一版);数据点级(后续扩展) |
| target_view_id | 批注定位的视图(整体批注为空) |
| content | 批注内容 |
| author_id | 批注人 |
| output_measure_id | 派生的管理措施(可选,批注可触发措施) |
| created_at |
- 定位粒度:第一版支持报告整体 + 视图级批注;数据点级精细定位(类似文档批注定位到某数据点)后续扩展
- 与 AuditNote 的边界:
- AuditNote = 审计工作流的正式附注(结构化:结论/评判/抽检/贴图/输出措施),审计时一次性产生
- ReportComment = 报告作为活文档的持续批注(轻量:内容/定位/作者/时间),任何时候可加,时间线累积
- 闭环:批注可一键派生 Measure("这条评价提到的问题,跟进一个措施"),强化报告→措施闭环
12.9 占位模块
- 考勤排班:值班组长/值班专员/结合打卡实时在班;依赖考勤数据源,整体规划后落地
- 绩效考核:数据未全、算法未导入;系统只汇聚数据,预留接口
- 数据真实性识别:异常数据模式识别规则,先留字段后扩充
- 报告导出三件套:Excel/只读链接/PDF,依附报告实体,按既有路线图推进
十三、下一步设计与开发规划(v0.3 路线图)
v0.2 底座(数据源/视图/看板)已落地。v0.3 聚焦管理闭环主线,分三阶段推进。原则:先闭环可执行,再增强分析。
Phase 1 —— 管理闭环主线(优先级最高)
目标:跑通"数据→报告→审计→措施→回看"最小闭环。
| # | 模块 | 关键产出 | 依赖 |
|---|---|---|---|
| 1 | 管理措施 Measure | 独立模型 + 到期回看队列 | — |
| 2 | 异常事件 Incident | 登记 + 复盘转化链路 | — |
| 3 | 报告 Report | 视图快照 + 时间/条件锁定 | 分析视图(已就绪) |
| 4 | 审计 AuditNote | 结论+贴图+抽检工单+输出措施 | Report |
| 5 | 周报 WeeklyReport | 10项框架 + 逐项审查 + 产出措施 | Report/Audit/Measure |
| 6 | 报告索引页 | 报告/周报列表 + 详情(快照渲染) | Report |
Phase 2 —— 协作与赋能
| # | 模块 | 关键产出 |
|---|---|---|
| 7 | 跨部门反向管理 UpstreamTicket | 上游打分(响应/解决率) |
| 8 | 员工视角 MyWorkspace | 我的接待/进步/待办/政策 |
| 9 | 时间序列气泡图 | 运营+事件+措施+人头对齐时间轴 |
| 10 | 人员职务/分组维度 | 支撑"各组接待量分析" |
| 11 | 报告批注 ReportComment | 活文档批注时间线 + 派生措施 |
Phase 3 —— 增强与占位落地
| # | 模块 | 关键产出 |
|---|---|---|
| 12 | 报告导出三件套 | Excel/只读链接/PDF |
| 13 | 考勤 + 排班 + 实时在班 | 依赖考勤数据源 |
| 14 | 绩效考核 | 数据汇聚 + 算法对接 |
| 15 | 数据真实性识别 | 异常数据模式规则 |
| 16 | 异常自动识别 | 基线倍数预警 |
Phase 1 设计决策(已确认)
- Report 快照:不做全表数据快照;固化为「视图配置 + 执行结果(关键数据) JSONB + 可选PDF归档」。理由:大部分源数据在库中不常变,关键数据固化即可满足"报告固化数据视图"的审计要求
- 周报 10 项数据源映射:见 §12.4(措施=Measure / 接待=cs_records / 退款挽回=cs_records退款项 − refunds实际退款SN / 投诉=service_tickets / 跨部门=UpstreamTicket / 异常=Incident)
- Measure 到期回看调度:手动触发 + 自动定时扫描 双模式
- 审计贴图存储:内网本地目录(按报告/日期分目录),不上对象存储;存储层抽象接口备用
- 菜单归属:新建「管理闭环」菜单组(报告/审计/周报/措施/异常事件 入此),与「决策看板」「数据中心」并列
十四、数据同步与加工实现补充(v0.3.1)
本章为 v0.3.1 落地的数据同步链路实现说明。完整操作/实现细节见配套文档 docs/standards/数据同步与加工说明.md,本章只留索引与关键决策。
14.1 数据源与抓取分流
系统支持 5 个数据源,按 fetch_mode 分流到两条抓取链路:
| data_type | 名称 | fetch_mode | 抓取器 |
|---|---|---|---|
| refund / ticket / wallet / device_combo | BMS 业务表 | playwright(默认) | BmsFetcher(Playwright 浏览器自动化) |
| cs_record | 智能助手处理记录 | http | ai_acc_fetcher(httpx REST API,非浏览器) |
fetch_mode不在sync_source_configsDB 表里,由BMS_DATA_SOURCES种子在配置读取时合并,供bms_sync.sync_all分流。- 两条链路最终都产出本地 xlsx,统一走
_auto_import(parse → load → upsert)入库,抓取方式差异不渗透到导入层,所有数据源共用一套解析与加工口径。
14.2 ai-acc 智能助手处理记录接入(cs_record)
ai-acc 平台提供标准 REST API,无需 Playwright,适合服务器无人值守同步:
- 登录
POST /ai-acc/portal/v1/auth/login→{"token":...}⚠️ token 在 JSON 顶层(非 BMS 风格{data:{token}}),_login兼容两种结构。 - 导出
GET /ai-acc/cs/v1/assistant/handleRecord/export(Bearer token + session cookie)→ xlsx 文件流。 - ⚠️ 用户提供的
/admin/assistant/handle-record-export是前端路由,非 API 端点——接入新 REST API 前先用 curl 探测实际路径与响应结构。
14.3 时区加工(关键 bug 修复)
问题:BMS/ai-acc 导出时间为 naive 北京时间字符串,原 _to_datetime 用 pd.to_datetime 返回 naive,存入 timestamptz 列时被 DB(UTC)当 UTC 解释,按北京显示偏后 8 小时。
修复(upsert._to_datetime):naive 视为北京时间(UTC+8)→ tz_localize(_TZ_CN).tz_convert(utc) 后再存;aware 原样返回。影响所有导入路径(手动上传 / 一键同步 / 定时同步 / 两条抓取链路)。
存量迁移:对 7 张有数据的业务表(wallet/service_tickets/refunds/cs_records/device_combos/external_complaints/card_complaints,merchant_refunds 空表跳过)执行 col - INTERVAL '8 hours' 一次性 SQL 迁移。系统内部表(incidents/measures/reports 等服务器生成 UTC 时间)未动。
14.3.1 BMS 浏览器时区与时间窗口设置(2026-09-01 生产审计补充)
14.3 解决的是入库时间换算;本小节解决抓取端时间窗口设置——两者独立。
根因:BMS 页面日期时间框(Element UI DatePicker)由 Playwright 自动化填入,若填入不可靠,页面保留默认/上次时间范围 → ① 当前窗口增量漏掉 ② 拉到窗口外旧数据与库内已有记录冲突 → 统计负数。这不是删除数据,也不是 14.3 的 8 小时换算问题。
三层根因与修复(详见 数据同步与加工说明.md §4.5):
- 容器浏览器时区 = UTC:
new_context(timezone_id='Asia/Shanghai')+fill_utc=False(BMS 前端当前时刻=北京时间,填入串保持北京时间,与用户手动导出一致) - ticket 时间标签匹配失败:BMS 的"起始登记时间/结束登记时间"是 placeholder 而非 label 元素,且在高级筛选里默认折叠 → 改按 placeholder 精确匹配 + 先点
.show-more展开 + click 聚焦后再 fill(Element UI DatePicker 需先聚焦才可 fill,否则 fill 超时且 setter 不触发 Vue v-model) :visible非法选择器:page.evaluate内原生document.querySelectorAll('input.el-range-input:visible,...')直接抛 SyntaxError(:visible是 jQuery/Playwright 引擎伪类,原生 JS 不识别)→ 改按类名选中 + JS rect/computedStyle 过滤可见性
配套加固:upsert_wallet 负数"新增"改为 max(..,0) + WARNING 告警(窗口失败拉旧流水时 existing_count > unique_rows);wallet 导入输出实际 op_time 范围二次校验(对照「设置时间范围」日志);下载 response listener 后台任务追踪清理(防 asyncio 泄漏)。
14.4 7 天时间范围分片
ai-acc 导出接口限制单次时间范围不得超过 7 天(正好 7 天允许)。ai_acc_fetcher._chunk_time_range 对 >7 天区间切成 ≤7 天连续子区间(边界相接),逐片 GET 后用 pandas(dtype=str 读 + openpyxl 写,与 data_parser 解析口径一致)合并为单个 xlsx,drop_duplicates() 去除边界 inclusive 端点可能产生的重复行。
14.5 去重策略(pk_strategy)
各业务表按是否有天然唯一键分流:
| 策略 | 实现 | 适用表 |
|---|---|---|
| upsert(主键去重更新) | on_conflict_do_update |
refunds / tickets / merchant_refunds / merchants / device_combos / external_complaints(有编号) / manual_refunds(复合键) |
| none(无主键插入) | on_conflict_do_nothing 兜底 |
wallet / cs_record / card_complaint / external_complaints(无编号) |
| fallback 主键 | 构造 INIT::{sn}::{pkg}::{date} 合成主键再 upsert |
device_combos 初始套餐 |
- cs_record 无天然唯一键(同设备同时间可多次接待),走 none 策略不去重:正常增量同步(
last_end_time非重叠)无重复;⚠️ 手动重同步重叠范围会累计重复行。 - device_combo 初始套餐无充值订单号,生成
INIT::前缀 fallback 主键保证幂等。
14.6 凭证管理
- 各源账号密码独立,Fernet 加密存于
sync_source_configs表,.env的BMS_USERNAME/PASSWORD仅作 seed 初始值。 - ⚠️ 修改
.env的CONFIG_ENCRYPTION_KEY或JWT_SECRET_KEY会使现有凭证解密失败(现象:BMS 返回"用户密码错误"),必须在「同步设置」页重新写入所有数据源凭证。
14.7 定时同步硬约束
定时同步(8-23/0 每小时增量 + 5:00 前一天补跑 + 8:00 近 7 天全量兜底)的时间范围:白天增量=今天 0 点now;5 点补跑=前一天整天;8 点全量=近 7 天 0 点now。理由:upsert 幂等不产生重复,覆盖当天 0 点至今能补回上次失败漏掉的数据,防止无人值守误同步过多历史数据拖垮系统。
⚠️ 前提(2026-09-01 审计):上述时间范围约束的前提是 BMS 页面时间窗口被可靠设置。若
_set_time_range设置失败(页面保留默认/上次范围),实际拉取窗口 ≠ 期望窗口,增量数据会缺失、且会拉到旧流水产生负数"新增"。因此定时同步的可靠性还依赖 §14.3.1 的三层修复(浏览器时区、ticket 标签、:visible选择器)及负数/op_time 告警监控。
14.8 实现文件索引
| 文件 | 职责 |
|---|---|
backend/app/services/bms_fetcher.py |
BMS_DATA_SOURCES 种子 + BmsFetcher(Playwright) |
backend/app/services/ai_acc_fetcher.py |
ai-acc HTTP 抓取 + 7 天分片合并 |
backend/app/services/bms_sync.py |
同步编排(http/playwright 分流 + 自动导入 + 日志) |
backend/app/services/bms_scheduler.py |
定时调度(仅当天数据) |
backend/app/services/sync_source_config_service.py |
凭证加密存取 + fetch_mode 合并 |
backend/app/services/upsert.py |
类型转换(含时区加工 _to_datetime)+ 三种去重策略 |
backend/app/services/data_parser.py |
CSV/XLSX 解析 + 列映射建议 |
backend/app/core/crypto.py |
Fernet 加解密 |
十五、同步架构 v2(v0.3.2):SyncTaskManager 异步任务体系 + 抓取/导入优化
本章为 v0.3.2 新增设计,属于"数据同步"维度的架构升级(从同步阻塞式→异步可观测式;从每次独立登录→上下文复用;从抓取+导入串行→重叠并行)。对应实现细节见 docs/standards/数据同步与加工说明.md §八~§十。
15.1 设计背景:为什么要推翻 v1 同步交互方式
| 原 v1 方式 | 用户与系统痛点 | v2 决策 |
|---|---|---|
/sync-all POST 阻塞,同步全部完成才响应 |
用户浏览器转圈 3~8 分钟;Nginx/浏览器 1min 超时导致前端报错但后台实际执行成功 → 用户以为失败再点一次 → 并发两次抓取把 BMS 同账号多会话踢下线 | 改为异步提交 taskSubmit → 返回 task_id → 前端按秒轮询 taskStatus;HTTP 不阻塞,用户可切页面 |
| 无互斥概念,手动/定时可同时触发 | 后台启动 2 个 Playwright 浏览器实例;同一账号在两台浏览器里反复登录 → BMS 风控登录滑块频繁弹出;会话互踢 → 导出 5xx | 单例 SyncTaskManager 持有 asyncio.Lock 做全局互斥;任何触发路径 (manual/scheduled) 都先拿锁,拿不到立刻抛中文提示 |
每次默认从今日 0 点起抓(calculate_time_range) |
白天多次手动点,每 2~3 小时就把白天数据全量重抓一遍 → 服务器配额浪费 4×~6×;BMS 日志里满是重复请求 | 新增 compute_incremental_ranges,从 bms_sync_logs 取上次 SUCCESS 记录的 time_end 做起点;保证"已同步过的时段不再请求" |
| 无冷却机制,用户 30 秒内能点 N 次 | BMS 端 1 分钟内数据无任何差异 → 纯浪费 | DEFAULT_COOLDOWN_SECONDS = 300(5 分钟)冷却;force=true 可跳过(给手动指定范围场景) |
| 进度完全不可见 → 只有 shell 日志能看 | 运营不知道"现在卡在哪一步、还要多久、成功了几张表" → 反复询问开发者 | 每个任务挂 SyncTaskProgress,阶段 + 当前步骤 + 子百分比 + 步骤文案都通过 taskStatus 接口返回给前端,可直接渲染进度条和阶段卡片 |
| 每抓一张表都建一个新 Playwright Context + 重新登录 | 登录 5 次 = 5 × 滑块概率 + 5 × 服务器握手时间 → 30%~40% 时间花在登录上 | 按 base_url 分组,组内共享 Context;组首任务登录成功后,后续任务直接携带同一会话访问,登录次数从 5 次 → 2 次(wifi 域一组 + support 域一组) |
| 先全部抓完再全部开始导入 | 抓取每次等待 60 秒间隔时 DB/CPU 完全空转 → 总体端到端时间被人为拉长 30%~40% | 单张表 xlsx 落到本地后立刻把导入任务扔 asyncio.to_thread 线程池跑起来,与下一张表的抓取(+等待)重叠,互不阻塞 |
15.2 核心对象:SyncTaskManager(单例)
SyncTaskManager (进程级唯一)
├─ _lock: asyncio.Lock — 全局互斥锁(manual / scheduled 共用)
├─ _current_task: SyncTask | None — 当前在跑的任务引用
├─ _last_success_at: datetime | None — 上次成功结束时间 (cooldown 判断)
├─ submit(trigger_type, triggered_by, data_types, time_ranges, runner_coro, force, ignore_cooldown)
│ → 拿锁 → 检查 cooldown → 分配 task_id → 记录 SyncTask → asyncio.create_task(_run_background)
│ → 返回 (task_id, message) (HTTP 立刻响应)
├─ compute_incremental_ranges(data_types)
│ → 查 bms_sync_logs 最近 SUCCESS 的 time_end → 与今日 0 点比较取较大值 → 返回 {data_type: (start, end)}
├─ is_busy() / status(task_id) — 对外查询
└─ _run_background(task, runner, on_progress_cb)
→ 调用业务 runner (bms_sync 的同步主流程) → runner 通过 on_progress_cb 持续回填进度
→ 完成/失败后更新 SyncTaskProgress.finished_at / status / error
15.3 三 API 契约(推荐前端调用路径)
用户点击「开始同步」
│
▼
POST /task/preflight ──────► 返回 {
busy: true|false, current_task: {triggered_by, trigger_type, started_at},
cooldown_remaining: 41, cooldown_total: 300,
incremental_ranges: {refund: ['2026-08-02 14:23', '…'], ticket: […]}
}
│ 前端据此弹出确认框:"上次同步仅过 41 秒;本次增量从 14:23 起抓 5 张表"
▼
POST /task/submit (带 force=true|false, 以及 preflight 计算好的 incremental time_ranges)
返回 {task_id: 'sync_…', message: '任务已提交,可轮询 /task/status 查看进度'}
│
▼
GET /task/status?task_id=sync_… 按 1 秒间隔轮询
│ 返回 SyncTaskProgress(stage=fetching|importing|done, current_step/total_steps, sub_progress, message, results, error…)
│ 前端渲染进度条 + 每个 data_type 结果
▼
progress.status == 'success' → toast 成功 → 自动刷新当前分析图表
status == 'failed' → toast 错误信息(含 error 字段),允许用户再次点击重试
旧前端仍可继续调用
/sync-all:后端已做兼容,submit 成功则仍返回新格式;若 submit 失败则回落到旧的阻塞式同步,保证不破坏现有页面。
15.4 架构升级后三大约束不变(防退化)
- BMS 同一 Web 的两次下载请求 ≥1 分钟间隔 — 此规则在 fetcher 内部仍然保留(与登录复用无关),作为对 BMS 服务器方的礼貌保证;
- 定时同步只抓当天数据 — 不允许拖库;定时用的 runner 强制
time_ranges = today_start ~ now_cn,与手动提交的增量计算是两套路径(定时不需要"从上一次截止"续跑,因为 0 点至今很短 + upsert 幂等); - 所有导入仍走统一的 upsert 口径:解析 → 类型转换 → 时区加工 → 主键去重,保证抓取链路的任何优化不影响入库数据质量。
十六、看板组件化与复用体系(v0.3.2)
对应实现见 docs/standards/数据同步与加工说明.md §十一。今日看板 / 接待看板 / 工作台首页已完成改造。后续新增任何分析页,必须优先用本章 6 个组件拼装,禁止重复写 KPI / 图表卡 / 区块标题的内联 HTML 和 CSS。
16.1 组件库目录
web/src/components/dashboard/ 下 6 个:
| 组件名 | 主要 props | 应用场景 |
|---|---|---|
KpiCard |
label, value, unit/money, icon, bg, color, yoyPct + yoyValue + yoyKey(环比), deviceCount(接待人次数行), tip(tooltip), hideYoy(工作台简洁模式),#extra 插槽 | 所有"数字 + 图标 + 单位 + 环比标签"形式的指标卡 |
RouteSplit |
routes 对象(operational / actual_cashflow / diff / route_a / route_b / route_c / route_d),compact(紧凑单行),hideHeader(外层已有表头时用) | 现金流出四路线拆分 + 经营估算 vs 实际现金流 + 对账偏差三张合计;所有含 A/B/C/D 四路现金流分析的位置 |
ChartCard |
title(字符串),loading,#header extra 插槽,body-style | 把任意 BaseChart 包成统一的带标题、内边距一致的卡 |
SectionHeader |
title + sub(可选) | 替代 <h2 class="section-title"><span class="section-subtitle">…</span></h2>,保证所有看板左色条+排版一致 |
FilterBar |
v-model:modelValue(快捷下拉),v-model:range(自定义区间数组),quick-options,date-picker-type,@refresh 事件,#left 插槽 | 所有「快捷日期 + 自定义 + 刷新」顶部筛选条 |
QueuePanel |
三列 todos/tasks/incidents,列配置 + 行格式化函数 | 三列事务列表(今日看板的待办/专项/异常);点击行跳转详情,优先级颜色一致 |
16.2 设计原则:不要再造"第 N 份 KPI 卡"
- 新看板第一步:先写
<script import>把 6 个组件都引入,再用v-for把 KPI 数据写成数组(如Dashboard.vue的managerStatCards、Today.vue的kpiCards),禁止手写出el-card+div.stat-label+div.stat-value三重内联。 - 样式要调整:先改
components/dashboard/*.vue的 props 或内部样式,再批量同步到所有使用处;禁止在使用页私写.kpi-label/.kpi-value/.route-card等覆盖类名(与组件内同名会有作用域穿透冲突)。 - 组件新增 props 向后兼容:hideYoy / hideHeader 这类可选 prop 默认
false,保证今日看板 / 接待看板原有页面 0 修改继续运行。
16.3 现有 6 个页面看板的意义审计与后续处理建议
对 views/dashboards/ + 工作台首页 + analytics/ 分析页做了一轮存在价值审计,结论:
| 页面 (文件) | 是否"有意义"(★★★高 / ★★中 / ★低) | 角色与价值 | 评估结论 |
|---|---|---|---|
工作台首页 views/Dashboard.vue |
★★★ | 管理层登录第一屏:实时 7 项经营指标 + 四路现金对账 + 30 天退款趋势 + 未读策略/待办/最近操作;客服侧快捷入口 + 策略 | ✅ 必保留(v0.3.2 组件化改造完成,↓34% 代码) |
今日看板 dashboards/Today.vue |
★★★ | 单日切面:退款/现金/接待/工单/投诉 5 组 KPI + 双对比堆叠条 + 三列事务队列 + 全页日期水印(可直接截图流转) | ✅ 必保留(核心管理看板,↑使用频率最高) |
接待看板 dashboards/Reception.vue |
★★★ | 客服接待周报视角:1.总体接待量 → 2.分项(投诉/退款/其他) → 3.分项人均工作 → 4.各组人员日明细接待 | ✅ 必保留(主管看组内接待量+人均产能) |
退款与提现 dashboards/RefundWithdrawal.vue |
★★ | 出款业务流程视角(A/B 双路径 + 明细慢单 + 钱包沉淀);与 analytics/Cash 有部分重叠但视角不同——前者是"出款路径 & 慢单追踪"(执行视角),后者是"商户号现金流 vs 经营登记对账"(财务视角) | ✅ 保留;建议后续把顶部 4~5 张 KPI 卡替换成 KpiCard + FilterBar 组件,把四路拆分卡逐步迁移到 RouteSplit |
专项跟进 dashboards/Special.vue → DashboardView renderer |
★★★ | 自定义可配置看板运行时容器(用户在 Designer 配置好的专项看板在此执行);与 DashboardView/Designer 三件套绑定 | ✅ 必保留(用户自定义看板唯一入口,不可替代) |
| DashboardView + Designer(设计器 + 运行器) | ★★★ | 把「视图」组合成「看板」+ 可发布为专项,支撑非开发搭看板 | ✅ 必保留(平台能力) |
运营分析 analytics/Operation.vue |
★★★ | 退款趋势 / 笔均金额 / 原因分布 / 充值 vs 退款;管理层日常最常用 | ✅ 保留;可把顶部筛选条、KPI、图表外卡替换成 FilterBar + KpiCard + ChartCard(下次低优先级改造) |
现金流分析 analytics/Cash.vue |
★★★ | 商户号实际 vs 已登记估算 + 直接退款/提现分类 + 散点对账明细;财务对账最常用 | ✅ 保留;4 张对账 KPI 卡 → 后续可换 KpiCard;三路拆分可换 RouteSplit(与 Dashboard/Today 共用视觉口径) |
退款分类 analytics/Category.vue |
★★ | 工单类别 + 退款维度交叉分析;实际使用频率低于运营/现金流,但交叉维度是决策依据不可替代 | ✅ 保留 |
人员操作 analytics/Operator.vue |
★★★ | 坐席接待量 / 时效 / 退金额;客服绩效计算的唯一入口 | ✅ 必保留;若后续扩展,所有排名类 KPI 都应用 KpiCard 统一风格 |
| ViewList / ViewBuilder / ViewRender(视图三件套) | ★★★ | 分析视图自服务化,搭自定义看板的原材料 | ✅ 必保留 |
无意义 / 可合并:本轮审计未发现可直接删除的页面(6 类看板 + 4 类分析页都有明确使用人或明确唯一价值,不存在"与其他页完全重叠且使用频率为 0"的冗余项)。最低的是 ★★ 的 3 张,但都具有不可替代的视角,暂不建议合并或下线;后续改造优先级为:先把未组件化的 RefundWithdrawal / Cash / Operation 三张替换成公共组件(优先级:Cash > Operation > RefundWithdrawal,因使用频率更高),再视使用反馈决定是否把 Category 的部分视图并入 Operation 做 Tab 切换。
十七、运营看板多粒度切换(v0.4 新增)
17.1 设计目标
将"今日看板"升级为"运营看板",支持日/周/月/季/年 5 种时间粒度切换,从单日切面扩展到任意时间范围的运营数据分析。
17.2 时间粒度与聚合规则
| 粒度 | 快捷选择 | 聚合维度 | 后端参数 |
|---|---|---|---|
| 日视图 | 今日/昨日/更早日期 | 固定按小时聚合 | date=YYYY-MM-DD |
| 周视图 | 本周/上周/更早周 | 固定按日聚合 | start+end (7天范围) |
| 月视图 | 本月/上月/更早月 | 按日/周/月聚合(可选) | start+end |
| 季度视图 | 本季/上季/更早季 | 按日/周/月聚合(可选) | start+end |
| 年视图 | 今年/去年 | 按日/周/月聚合(可选) | start+end |
17.3 前端实现要点
- 粒度切换时动态生成时间参数:单日传
date,范围传start+end - 人均效率数据需处理两种响应格式:单日返回数组,范围返回
{date, date_end, data: [...]} - 快捷日期选择按钮组 + 自定义日期范围选择器
- 路由
/dashboards/today保持不变,URL 参数?granularity=week&date=2026-08-10支持刷新保留状态
17.4 后端适配
- 所有 analytics 函数接受
start和end参数支持多日范围查询 - 单日查询时
start == end,兼容旧逻辑 - 按小时聚合仅用于日视图;周/月/季/年视图按日或按周聚合
十八、Group/Specialty 双体系(v0.4 新增)
18.1 设计动机
客服中心存在两个正交的管理维度:
- 行政分组(Group):组织管理维度,如"董梦玲组""叶珍凤组",用于考勤、绩效、日常管理
- 业务专项(Specialty):业务内容维度,如"咨询接待""套餐专项""退款挽回",用于工作量统计、效率分析
同一人可能属于一个行政分组,但负责多个业务专项;同一专项可能跨多个分组的人员。
18.2 数据模型
6 张表:
| 表名 | 用途 |
|---|---|
groups |
行政分组定义 |
group_leadership_history |
组长/副主管变更历史(SCD Type 2) |
person_group_memberships |
人员分组归属历史(SCD Type 2) |
specialties |
业务专项定义(含难度系数) |
specialty_leadership_history |
专项负责人变更历史(SCD Type 2) |
person_specialty_assignments |
人员专项分配历史(SCD Type 2,支持主/辅专项) |
18.3 6 个标准专项与难度系数
| 专项 | 难度系数 | 说明 |
|---|---|---|
| 咨询接待 | ×1.0 | 常规咨询接待 |
| 套餐专项 | ×1.8 | 套餐相关问题 |
| 退款处理 | ×2.0 | 日常退款操作 |
| 退款挽回 | ×2.2 | 退款客户挽留 |
| 内部投诉 | ×3.0 | 企微/私域投诉 |
| 外部投诉 | ×5.0 | 12315/工信部等外部投诉 |
18.4 SCD Type 2 历史追溯
所有人员归属变更均采用 SCD Type 2 模式:
effective_from/effective_to:生效区间(NULL表示至今)is_current:是否当前有效(冗余字段,加速查询)change_reason:变更原因(入组/调组/离组/任命/免职)source:数据来源(manual / xlsx_import / sync)
十九、SCRM 同步体系(v0.4 新增)
19.1 数据源
SCRM(企业微信客服)系统通过 REST API 同步客服会话数据,包括:
scrm_operators:客服操作员scrm_sessions:客服会话(含质量指标:首次响应秒/平均响应秒/消息数/时长等)scrm_session_transfers:会话转接记录
19.2 同步策略
- 增量同步:从上次成功结束时间减 2 小时重叠开始,首次运行回溯 30 天
- 定时调度:与 BMS 共享调度(8-23/0 每小时 + 5:00 补跑),BMS 完成后串行执行 SCRM
- 全局互斥锁 + 冷却期:防止手动/定时冲突
- Token 自动刷新:提前 5 分钟刷新,asyncio.Lock 双重检查锁
- 401/403 自动重试:一次重试后仍失败才报错
19.3 数据处理规则
- 操作员全量 upsert(覆盖更新,不保留历史)
- 会话质量字段(first_response_sec 等)非空时不覆盖,防止回滚
- 会话转接先删后插,保证幂等
- SCRM 聊天记录不同步到本地(数据量过大)
19.4 凭证管理
SCRM 的 ClientId / ClientSecret 存储在 sync_source_configs 表,使用 Fernet 对称加密。
二十、决策看板 6 大子菜单(v0.4 新增)
20.1 设计目标
为管理层提供 6 个专项决策视角,从运营看板的"概览"下沉到"专项深度分析"。
20.2 子菜单清单
| 子菜单 | 路由 | 视图数 | 核心内容 |
|---|---|---|---|
| 退款看板 | /dashboards/refund |
多视图 | 退款趋势/原因/金额/商户号 |
| 投诉看板 | /dashboards/complaint |
多视图 | 投诉趋势/分类/处理时效/三表合一 |
| 接待看板 | /dashboards/reception |
8 视图 | 接待量/工作量/质量/响应/转接(含 SCRM 4 视图) |
| 退款-提现全链路 | /dashboards/refund-withdrawal |
多视图 | A/B 双路径/慢单/钱包沉淀 |
| 绩效看板 | /dashboards/performance |
9 视图 | 人均效率/工作量/专项分布(含 SCRM 6 视图) |
| 专项跟进 | /dashboards/special |
可配置 | 用户自定义看板运行时 |
20.3 权限
决策看板仅对管理层用户(isManager=true)可见。
二十一、OCR 自动登录(v0.4 新增)
21.1 应用场景
BMS 平台登录需输入图形验证码,使用 ddddocr 进行 OCR 自动识别。
21.2 置信度预检机制
- 单字符最低概率
_OCR_MIN_CHAR_PROB = 0.72:任一字符概率低于此值则刷新验证码 - 平均概率阈值
_OCR_AVG_PROB = 0.86:所有字符平均概率低于此值则刷新 - 最大刷新次数
_OCR_PRECHECK_MAX_REFRESH = 20:最多刷新 20 次 - 兜底置信度
_OCR_FALLBACK_CONFIDENCE = 0.70:ddddocr 不支持概率输出时使用
21.3 登录流程
- 内层预检循环:刷新验证码 → OCR 识别 → 检查置信度 → 不达标则重新刷新(不触发登录)
- 置信度达标后外层登录:输入用户名/密码/验证码 → 提交登录
- 遇到"用户名或密码错误"立即终止(不重试)
- 遇到"验证码错误"回到步骤 1
- 整体流程约 3 秒完成
21.4 Playwright 上下文复用
同域名数据源复用 Playwright 浏览器上下文,避免重复登录。BmsFetcher 对同 base_url 强制 65 秒等待,跨域名可立即切换。
二十二、人均效率算法(v0.4 新增)
22.1 两个合成指标
- 工作量分(会话次数维度):Σ(专项会话数 × 难度系数 × 本职系数)
- 效率分(SN 去重接待个数维度):Σ(接待个数 × 难度系数 × 本职系数)
22.2 核心设计
- 6 专项难度系数加权(见 §18.3)
- 按天加权:从
person_specialty_assignments(SCD Type 2) 取查询范围内每天的专项分配,按天数加权平均 - 本职/转接判定:管理岗跨类全系数豁免;本职专项系数 1.0,转接惩罚 0.2
- SN 跨表去重:6 个子查询 UNION ALL,handler 为空时关联 cs_record 补全
详见 人均效率算法说明.md。
二十三、数据采集统一入口 SyncDashboard(v0.4 新增)
23.1 设计目标
将分散的数据采集功能(BMS 同步、SCRM 同步、文件上传、采集记录、同步设置、数据源管理)合并为统一入口,Tab 切换。
23.2 界面布局
- 左右两栏:左侧主内容区,右侧 420px 固定实时日志面板
- 响应式:屏幕 <1200px 切换为上下布局
- 日志面板:自动滚动(上滑暂停/回底部恢复)、清空按钮、底部返回、彩色来源标签(BMS=蓝色/SCRM=绿色)、进度条 + 阶段标签
23.3 合并同步表单
- BMS + SCRM 数据源复选框统一选择
- 统一时间范围选择
- 同步任务串行执行(BMS 先、SCRM 后)
- 按钮动态显示选中源数(如"开始同步(共 7 个源 · BMS 3 + SCRM 4 · 增量接续)")
- 运行中任务进度条置顶通知
23.4 Tab 顺序
Data View → BMS Sync → SCRM Sync → File Upload → Collection Records → Sync Settings → Data Source Management
默认打开 BMS Sync Tab。Sync Settings 和 Data Source Management 仅管理员可见。
二十四、alembic migration 管理(v0.4 新增)
24.1 版本链状态
- 57 个 migration 文件,已合并为单一 head(
73a7922ec598,alembic heads实测) - 历史 2 个 head(
a2c4e6f8b0d2+aa11bb22cc33)通过 merge migrationm0a1b2c3d4e5合并
24.2 幂等升级
新增的 Group/Specialty migration 使用 _table_exists() 检查,对已有表环境幂等安全。