几何鸟营销中心
v3.12.0 feedback
expand_more

更新日志

几何鸟营销中心版本发布记录

v3.12.0 2026-04-18 当前版本
🆕 新增 wechat_status 第 6 档: `ever_in_room` + 📝 改动清单 + ✅ 测试
  • no_room — 纯原始进线(从未进过群), 保留原绿色
  • ever_in_room(新) — 好友 active + 无 active 群 + 历史进过群, 灰绿色 + 中划线
  • app/shared_templates.py::_load_qbh_cache — 加 ever_qbh 集合 + 分档逻辑,
  • app/templates/_macros/components.html::qbh_chip — 新增 ever_in_room 参数
  • 10 个调用 qbh_chip 的模板统一加传 ever_in_room(qbh) 参数
  • app/merge_contact.py::recommend_keeper — ws_rank 权重:
  • app/routers/ai.py — AI 搜索 prompt 加 ever_in_room 枚举值 + 中文触发词
  • app/templates/_includes/batch_actions.html — 合并卡片中文映射加 "曾入群"
  • test_merge_contact.py::TestRecommendKeeper 新增 2 条: no_room > ever_in_room,
  • 全量 917 passed, 61 skipped (比 v3.11.1 +2)
v3.11.1 2026-04-17
✅ Fix + 🧹 Backfill
  • app/routers/weiling_callback.py::_download_customer_avatar:
  • one_off_scripts/20260417_backfill_avatar_local_path.py:
v3.11.0 2026-04-17
🎯 核心改变 + ✨ 新增 (net +1100 行, 含测试) + 🗑 删除 (净减 1600 行产品代码) + 📊 测试基线 + 🔬 demo 验收
  • 所有进线走 `services.intake.worker` — (单线程 Queue 消费) — race condition
  • contact_id 本地 UUID hex — , 和任何外部 ID 解耦 — 不再随事件变, `_migrate_contact_id` 废除
  • 字段权威来源矩阵 — (`schema_policy.py`) — 每字段只 1 个权威源, 企微/卫瓴/手机号
  • Identity Resolution 6 级 — wm_id → customer_id → unionid → weiling_cid
  • 通用 CRM — 支持无企微的客户 (手机号进线 / 熟人介绍 / 手动新建), `has_wecom=0`
  • ecs_snapshot 软删除 — (migration 019) — `status + deleted_at` 字段, 好友关系真相 per 员工-客户
  • 无任何身份线索事件 reject — 1393 类孤儿直接拒绝, 不污染 DB
  • app/services/intake/ 5 个模块:
  • migrations/019_ecs_snapshot_status.py — ecs_snapshot 加 status + deleted_at
  • 新测试 (150+):
  • app/routers/weiling_callback.py: 1323 → 569 行 (-754)
  • src/wecom_group_callback.py: 923 → 515 行 (-408)
  • 测试清理 (-3000 行):
  • 重构前 816 passed, 70 skipped (9 个 @_SKIP_OLD_CONTRACT + 61 consistency)
  • 重构后 915 passed, **61 skipped (仅 consistency)**, 0 failed
  • 真 skip 清零: 9 个老契约 skip 不再存在 (对应测试已彻底删除)
  • 1000 次并发 race 循环 0 失败 (unit + demo 真实 schema 双重验证)
  • A 企微先+卫瓴后合并 ✓
  • B 卫瓴先+企微后合并 (1394 反向) ✓
  • C 手机号进线 has_wecom=0 ✓
  • D 孤儿事件 reject ✓
  • E 1000 次 race 0 失败 ✓
v3.10.1 2026-04-17
🗑 删除 + 🛡 防回归
  • `src/wecom_group_callback.py::_sync_qbh_to_weiling` — 每次企微加好友后
  • 对应的 3 处测试 mock (patch("wecom_group_callback._sync_qbh_to_weiling")).
  • tests/unit/test_no_weiling_writeback.py (2 个测试):
v3.10.0 2026-04-17
🚀 新增: 群发助手服务层 (app/services/mass_send/) + 解散群 MVP (FlowBot type=50008) + 🔧 群成员管理页修复 (/system/groups) + 一次性排查脚本 (one_off_scripts/ 留档) + 测试
  • migration 018 — 6 张 `mass_*` 表 (lists/templates/tasks/recipients/
  • audit.py — 操作日志薄封装 (复用 app/oplog.py)
  • contacts.py — 客户快照辅助 (从 crm_contacts + external_contacts_snapshot 抽取)
  • lists.py — 群发列表 CRUD + 成员管理
  • templates.py — + **rendering.py**: 内容模板 + 变量渲染 ({customer_name}/{qbh}/
  • routing.py — 发送人四级兜底路由 (snapshot → crm_owner → task_creator → flowbot_fixed)
  • quota.py — 月限额本地记账 (企微无查询 API, 本地追踪 sent_count)
  • channels/base.py — + **wecom_api.py**: 企微通道适配器
  • tasks.py — 任务生命周期
  • 用 services 层真实发送给 2 个公海客户 (Christine 0729 + 猛子 0731)
  • API 返回 msgid 完整, operation_log 3 条 (created/executed/completed),
  • 单群解散验证 (qbh=1146 郭郭女士): chat_merged 1 条消息解散后保留
  • 批量解散 7 个无客户群 (111/1169/1186/1217/1305/1343/1374)
  • 企微 webhook 自动更新 map_room.status='dissolved'
  • 75 条历史消息完整保留, 可继续查询
  • 路径写死 /opt/sales-center/src/sync_group_members.py 跨 demo/prod 部署不通 →
  • subprocess exit code 不检查, 失败也返 ok: True 骗前端 → 检查 returncode
  • 只跑 sync_group_members.py, 漏了 sync_group_qbh.py (元数据) → 按序跑两个
  • 超时 120s 太短 (两个脚本串行 3-5 分钟) → 每个 180s
  • "数据异常" tab 角标计数错 — 1 if list else 0 改为 len(), 真实反映条数
  • "无客户群" tab 孤儿过滤 — qbh=1169 甘先生 chat_id='' 历史脏数据, SQL 加
  • 脚本归位 — `sync_group_{members,qbh}.py` 从 `one_off_scripts/` 搬到 `src/`
  • 20260417_dissolve_group_mvp.py — 单群解散 MVP
  • 20260417_batch_dissolve_groups.py — 批量解散
  • 20260417_scan_lost_friends.py — 好友漂移扫描 (v1 逻辑有 bug, 已废)
  • 20260417_generate_drift_report_md.py — 漂移报告 Markdown 生成
  • 20260417_mass_send_v2_services.py — services 层发送 MVP
  • 20260416_mass_send_mvp.py — 4.16 原版 MVP
  • 新增 155 个 mass_send 单元测试
  • 全量: 806 passed, 80 skipped
v3.9.7 2026-04-17
🔴 数据架构修复 + 测试 + 数据清理 (分步执行, 部署后跟进)
  • 卫瓴回调双写 map_external 根治 — `_handle_customer_add` 之前把卫瓴自家 ID
  • 新增 4 个 TestCustomerAddNewContract 测试验证新契约
  • 旧 9 个 TestAddCustomerHandler/TestCustomerUpdateAsAddCustomerFallback/
  • test_A_typical_intake_end_to_end 断言从 "2 条 map_external" 改为 "1 条 wm88"
  • 全量: 661 passed, 70 skipped
  • 存量 21 条 method='weiling_add_customer' 记录待删除
  • 4 个 "只有卫瓴 wm_id 没企微原生" 的客户(0716/1361/1369/1374)单独处理
  • 4 条 crm_contacts.wm_id 存了卫瓴格式的改回企微原生
v3.9.6 2026-04-17
补齐归档 + 测试 + 未做 (按用户决定延后)
  • `_handle_contact_add` — 末尾调 `log_webhook_event(event_type='contact_add')`,
  • `_handle_contact_update` — 两条路径 (backfill / IGNORED) 都归档,
  • `app/routers/wecom_callback.py /wecom/callback` endpoint — 加归档,
  • log_webhook_event 从函数内 import 提到模块顶部 (避免重复 import)
  • T10: contact_add 归档 payload 可查
  • T11: contact_update 两路径 (backfill + IGNORED) 都归档 summary 区分
  • 基线: 664 → 666 passed (+2)
  • 30 天外自动清理: 等积累 90 天数据再考虑 (纯文本 payload, 估算月增量
  • ops/export_intake_fixtures.py 脱敏导出工具 (v3.9.7+ 做, 这样才能用真实
v3.9.5 2026-04-17
Mock 工具库 (新) + Demo seed 重写 + 扩展场景测试 + R3 保护扩展到企微侧 (被 mock 重写暴露的 bug) + 测试
  • `tests/helpers/weiling_mock.py` — 卫瓴回调 payload 工厂 + 进线事件序列模拟器
  • `tests/unit/test_weiling_mock.py` — 14 个工厂输出 vs 黄金样本一致性测试
  • 归档 — `one_off_scripts/seed_demo_contacts.py` (v1, 旧版 700+ 行)
  • 新版 — `one_off_scripts/seed_demo_contacts.py` (v2, 100 行)
  • `tests/integration/test_intake_scenarios.py` — 7 个端到端场景测试
  • G_same_name 场景的 R3 保护由 test_contact_onboard.py::T8 单元级守护
  • `src/wecom_group_callback.py::_find_contact_id` 策略 3 — 原 `WHERE user_name=?`
  • 基线: 643 → 664 passed (+21)
v3.9.4 2026-04-17
修复 + 测试
  • crm_progress 迁移 — v3.9.0~v3.9.2 原代码写 `UPDATE crm_progress SET contact_id=?`
  • obj_type=0 是客户跟进 (related_id = contact_id), obj_type>0 (如会议纪要=7)
  • 生产实测零断链, 改动作为防御性补全
  • T9: crm_progress obj_type=0 迁移 + obj_type=7 保护 (643 passed, +1)
  • onboard_db fixture schema 补 crm_progress 表
v3.9.3 2026-04-17
修复 (R1-R4) + 测试
  • R1 删死代码 — 官方 contact_add payload 无 `contact_custom` / `external_userid`
  • R2 迁移补全 — contact_id 从企微 uuid 迁移到卫瓴 cid 时, `_migrate_contact_id`
  • R3 同名客户保护 — `_handle_contact_add` 两处 by_name 模糊匹配 (L702 缺 qbh
  • R4 方式 1 验证失败 fall through (双保险) — v3.9.1 路线 B 从源头阻止悬空映射
  • TestV393MigrationCompleteness 新增 T5-T8 (642 passed, +4)
  • T4 改为反映真实生产路径 (方式 3 by qbh 兜底, 不再依赖已删除的方式 2b)
  • test_contact_add_event (HTTP 端点测试) 前置补 map_external 让 qbh 从兜底链捞回,
  • 测试 fixture crm_contacts schema 补齐 wm_id/avatar/unionid 列
v3.9.2 2026-04-17
修复
  • 监控误报 — `/api/health` 的 `archive` 检查查的是 2026-04-11 已停机的 `wecom-archive/data/archive.db`,永远 critical;`sync` 检查查的 `sync_log.chat_auto` 也是同期停的老同步类型。v5 事件驱动链路(`wecom_msg_fetch_v5.py`)不写这两处
  • archive → 消息链路 — 改看 `chat_merged.MAX(send_time)`,24h 内有消息 ok / 48h warning / 更久 critical(业务非 24/7,夜间无消息正常)
  • sync → 小红书同步 — 改看 `xhs_sync_30d`(仍活跃的 cron 类型,每天 4:00/12:00 跑)
v3.9.1 2026-04-17
修复 + 测试
  • 1389 重复记录根因 — `_customer_update_wrapped` 调 4.10 contact/query API 拿到卫瓴 cid 后,会无条件写入 `map_external.contact_id`。若此时 `crm_contacts` 里还没有这条记录(首次进线常态),就产生"悬空映射",让随后到达的 `_handle_contact_add` 方式 1 误命中后验证失败、跳过方式 2/3 兜底、直接创建第二条 crm_contacts → 重复
  • 源头阻断 — 写入 `map_external.contact_id` 前先校验 `crm_contacts` 存在;不存在则跳过绑定,等 `contact_add` 事件到达时由方式 2(customer_id 链桥接)或方式 3(qbh 匹配)自然完成关联
  • 1389 🍂 合并 — 将 `7cef...`(企微 uuid)并入 `9gay...`(卫瓴 cid),wm_id 改为 wm88(企微正确的),chat_merged 4 条改指向
  • TestIntake1389OrphanMappingFix 新增 T1-T4 4 个防回归测试(633 passed, +4)
  • test_customer_update_fills_contact_id_via_query_api 前置加 crm_contacts 以匹配新行为
v3.9.0 2026-04-16
架构变更 + 修复
  • 企微回调自闭环 — 客户加好友时企微回调立即创建 crm_contacts(含 name/qbh/wm_id/avatar/unionid/owner),不再依赖卫瓴推送
  • 卫瓴回调补写模式 — 通过 wm_id 链查找已有记录,只补写 raw_json + 渠道信息,不覆盖企微写好的 wm_id/qbh/owner
  • wm_id 优先企微原始 — 回写 crm_contacts.wm_id 时优先取 method='callback' 的企微 ID,避免用卫瓴内部 ID
  • 1387/1388 事故根因(卫瓴延迟 24 分钟导致客户不可见、调研无法关联、聊天断裂)
v3.8.3 2026-04-16
修复
  • 群名 qbh 提取 — 正则放宽,支持无括号格式(如"1387 几何鸟 王女士对接群")
  • map_bind 去重 — 同一客户进线只写 1 条业务日志,技术日志走 webhook_event_log
  • 操作日志登录/合并显示 — 登录显示角色标签,合并客户显示中文摘要
v3.8.2 2026-04-16
写入层合并 + 展示层中文化 + Map_bind 去重 + 数据层
  • 客户编辑 — 一次保存多字段变更从 N 行日志合并为 1 行 `contact_update`,detail 含 changes 数组
  • 商机编辑 — 同上合并为 `business_update`,阶段变更保持独立 `business_stage_change`
  • action 名修正 — 阶段变更/创建商机联动全部使用 catalog 注册的 action 名,代码中不再有 `update_field`
  • 字段名翻译 — `FIELD_LABELS` 55 项字段中文字典,替代模板 45 行硬编码;area→面积、attr_budget→预算区间
  • 变更列优化 — 合并日志显示"面积 →65,预算区间 →25万";登录行显示角色标签;合并客户显示中文摘要
  • 通知/映射 — notify_send 显示事件名,map_bind 显示"绑定 客户名",不再 dump raw JSON
  • 两层日志分流 — 每次回调写 `webhook_event_log`(技术审计),只有首次绑定写 `operation_log`(业务日志)
  • 效果:同一客户进线从 3-4 条 map_bind → 1 条
  • migration 017 — 清理 016 之后残留的 `update_field` 行
v3.8.1 2026-04-16
修复
  • 客户头像时序竞态 — `_download_customer_avatar` 下载头像成功后回写 `crm_contacts.avatar`,修复进线时 snapshot 晚于 contact_add 导致 avatar 字段永远为空的问题(巡检 R03 报"田野"触发)
v3.8.0 2026-04-16
P3 — action 名规范化 + P4 — UI 改造 + 遗留(留给将来优化)
  • 中文 action → 英文:客户添加企微/群成员加入退出/登录登出/启用禁用用户 等 23 项一对一映射
  • create + target_type 拆分 → contact_intake / contact_create / business_create / progress_create
  • delete + target_type 拆分 → progress_delete / contact_delete / business_delete
  • update_field + field_name 拆分:
  • update_crm → contact_update(49 行)
  • ignored / unknown_event_sample → **直接 DELETE**(P4 会让 weiling_callback 直接写 webhook_event_log)
  • 标题从"操作日志"改为"**活动日志**"(语义对得上)
  • 顶部加 **4 个 Tab**(全部/人员操作/客户生命周期/系统自动),靠 actor_type 字段区分
  • action 下拉按 **业务域分组**(客户/商机/跟进/企微群/问卷/交付/系统/系统自动)
  • badge 颜色按 **domain 统一着色**(原来按 action 散着色,现在按业务域)
  • 删掉硬编码的 action_cn 字典,完全走 oplog_catalog.ACTION_CATALOG
  • 开发调试用,展示 webhook_event_log 表
  • 列:时间/事件/来源/客户标识/摘要/Handler/耗时
  • 筛选:event_type / source / 未处理筛选 / 关键字搜索
  • 点行展开 raw_payload
  • weiling_callback._handle_event 还没接入 webhook_event_log 写入(P1/P2/P3 只迁了历史 95 条 legacy 数据,新事件目前还不进 webhook_event_log)。需要独立任务做,不急。
  • batch_sea / batch_owner / batch_claim / batch_stage / batch_contact_type 保持聚合写入,拆多条的方案 B 留作下次重构。
v3.7.4 2026-04-16
改造 + 测试
  • L236 群名称变更
  • L255 群成员加入/退出(动态 action_text)
  • L303 客户群创建
  • L351 update_field qbh 回填(群 1:1 场景)
  • L442 客户群解散
  • L622 ensure_customer_number 分配客户编号
  • L774 客户添加企微
  • L848 update_field qbh 回填(add-contact 场景)
  • 615 passed(原 613 + 2 个新 P2c 测试)
  • TestSrcWecomGroupCallbackImport: 验证模块可 import + log_op_raw 可从 src/ 风格调用
  • 全量测试通过,无回归
v3.7.3 2026-04-16
P2a 补 5 个真漏写点 + 测试 + 留给 P2c(下次)
  • 商机阶段联动变更 — 客户阶段变更触发 → `business_stage_change`
  • 客户阶段联动变更 — 商机阶段变更触发 → `contact_stage_change`
  • 商机作废 — 从原 `ignored` 改为 `business_lost`,actor_type=callback
  • 生成合同 — `contract_generate`,记合同号/金额/模板类型
  • 上传合同模板 — `contract_template_upload`
  • 613 passed(原 605 + 新增 8 个 P2a 覆盖测试)
  • 修复 tests/integration/test_merge_contact.py 独立 schema 没跟上 P1 的 actor_type
  • src/wecom_group_callback.py 8 处 INSERT 改造(需 sys.path 插入 app/,涉及 cron 生产环境)
v3.7.2 2026-04-16
基础设施 + 兼容性 + 测试 + 下一步(P2-P4 规划)
  • migration 015 — operation_log 加 `actor_type` 字段(user/system/callback),
  • app/oplog_catalog.py — 44 个业务 action 的中英文字典 + domain 分组
  • app/oplog.py — `log_op` 增加 actor_type 参数(不传自动推断: 有 request → user,
  • 不改任何业务代码,所有现有写入点照常工作
  • actor_type 字段有默认值 'user',旧写入不改也能 INSERT
  • UI /system/oplog 页面零变化
  • 605 passed (原 591 + 14 个 P1 新测试覆盖 log_op_raw / log_webhook_event / oplog_catalog)
  • P2: 补 5 个漏写点(进线/商机阶段/商机流失/合同生成/合同模板) + 统一 10 个写入入口
  • P3: action 名统一规范化 + 历史数据改写
  • P4: /system/oplog 加 Tab + /system/webhook_log 开发调试页
v3.7.1 2026-04-15
背景 + 修复 + 测试
  • R04 qbh=1094 / qbh=1120 — **误报**,夫妻共用 qbh 的历史客户被 v3.6.7 夜间回填
  • R05 "宝哥来啦" — **真 bug**,v3.6.3 只在 customer_update handler 加了
  • add_customer handler 加本地桥接 — (`app/routers/weiling_callback.py`)
  • R04 改 JOIN crm_contacts.created_at — (`tests/consistency/test_recent_intake.py`)
  • 手动修宝哥来啦历史数据 — wmW2WmDAAAVxzfpUqQHVhfajtRB10vmg 这条补
  • 新增 2 个集成测试 TestAddCustomerHandler:
  • 基线: 512 passed, 10 skipped, 0 failed
v3.7.0 2026-04-15
新增功能 + 去重机制 + 测试
  • R01–R06 巡检项 — (`tests/consistency/test_recent_intake.py`)
  • 薄壳脚本 — `src/recent_intake_audit.py`:跑 pytest → 解析 → 与上次 diff → 仅变化时推送
  • cron wrapper — `ops/recent_intake_audit.sh`,计划 `17 9-23 * * *`(15 次/天,秒级耗时)
  • 企微销售助手告警 — (migration 013 插 `recent_intake_alert` 规则,agent_id=1000012)
  • data/recent_intake_last.json 记上次 fail 集合
  • 下次只推"新增 / 恢复"项,稳定状态完全静默,避免小时级刷屏
  • 新增 12 个单测(diff_states / _parse_json_report / state 往返)
  • 新增 4 个 migration 013 集成测试(插入 / 幂等 / 缺表跳过 / 模板占位符)
  • 新增 6 个巡检测试(R01–R06 本机 snapshot 全过)
  • 测试基线:+16(480 passed → 496 passed,另含 consistency 35 skipped)
v3.6.7 2026-04-15
  • 桥接双 wm_id — contact_add handler 交叉回填 contact_id ↔ qbh
  • 头像同步 — 从 external_contacts_snapshot 自动同步头像到 crm_contacts
  • 消息数修复 — refresh_contact_link 支持多 wm_id, msg_utils fallback 按 qbh 查
  • 历史修复脚本 — one_off_scripts/20260415_bridge_map_external.py
v3.6.6 2026-04-15
  • unknown_event_sample (12 条) — 卫瓴推送但我们没写 handler 的事件
  • ignored (110 条) — 按解耦原则忽略的事件
  • 后端 /system/oplog 加 show_tech 参数(默认 false),关闭时 SQL 排除这两类
  • 前端加"显示技术事件"checkbox 开关(默认未选),勾选后自动刷新页面
  • 尊重用户意图:明确筛选了某个 action 时不再强制过滤(方便开发调试)
v3.6.5 2026-04-15
  • action_cn['unknown_event_sample'] 从 "未识别事件" → "未处理事件"
  • weiling_callback 新增 EVENT_LABEL_ZH 字典(23 个常见卫瓴事件的中文名)
  • 采样日志的 target_name 从技术标签 "sample#1" 改为 "素材浏览 采样#1" 等,
v3.6.4 2026-04-15
  • ignored → 已忽略
  • unknown_event_sample → 未识别事件
  • map_bind → 绑定企微好友
  • batch_sea / batch_owner → 批量公海 / 批量归属
v3.6.3 2026-04-15
核心问题(v3.6.2 修一半的根源) + 根治方案 + 测试增强 + 回填脚本升级 + 明天的保证
  • related_customer[0].id = 卫瓴内部雪花整数(2043894872485818368)
  • customer_update.customer_id = 外部 base64 字符串(hPrR2Ix8PWv...)
  • 同一"企微好友"的两种 ID 表达,不能直接互查
  • jiayao 1373 实际是被 --fix-triangle 脚本(staff+时间窗口)手动修的,不是 customer_id 匹配
  • query_contacts_by_customer_ids() — 4.10 contact/query API 按 customer_id 反查 contact
  • 步骤 1(v3.6.2 已做):UPSERT map_external(wm_id, customer_id, user_name)
  • 步骤 2(v3.6.3 新加) — 主动调 4.10 API 拿 contact_id,UPDATE map_external.contact_id
  • API 失败时降级(第 1 步已做,不影响事件处理)
  • 删除 — 永远不工作的兜底 0(related_customer 整数匹配字符串)
  • 兜底 2(by contact_id) 成为主力 — 现在由 customer_update 提前把 contact_id 填进 map_external
  • 兜底 3(by_name) 仅作最终兜底(API 挂/未及时收到 customer_update 时)
  • 正常流:4.10 返回 contact_id → map_external.contact_id 被填入
  • API 异常:降级保护 — UPSERT 已做,contact_id 留空不致命
  • 线索阶段:4.10 返回空 contact_list → 不报错
  • Phase 1: 批量 wm_id → customer_id(convert API,50 条/批)
  • Phase 2: 逐条 customer_id → contact_id(4.10 API,每条间隔 0.2s)
  • 新客户任意时序进线 → customer_update handler 自动建立 wm_id + customer_id + contact_id 三元映射
  • contact_add 到达时,兜底 2 (by contact_id) 精准命中,不分裂 qbh,不需要 by_name 兜底
  • 即使是异步渠道(type=102 name 空),也能正确复用企微已分配的 qbh
v3.6.2 2026-04-15
问题根因 + 修复 + 影响 + 顺带归档(docs/memory)
  • customer_update × 3(第 3 次含 external_userid)
  • history_add × 2
  • clue_add × 1
  • 新增 `@handler("customer_update")` — payload 结构与 add_customer 几乎完全相同(name/type/customer_id/external_userid/userid/gender/lost_state),复用 `_handle_customer_add` 的 UPSERT map_external 逻辑
  • 只在 external_userid 非空时写入(前 2 次没 wm_id,安全跳过)
  • 幂等设计:UPSERT + 非空优先,重复事件不会破坏数据
  • 3 个新集成测试守护(TestCustomerUpdateAsAddCustomerFallback),覆盖单次/无 wm_id 跳过/3 次时序 e2e
  • 明天客户进线时,map_external.customer_id 将被自然填充(不再等废弃事件)
  • contact_add 的 customer_id 精准匹配兜底生效,双号分裂不再发生
  • 历史 507 条 map_external.customer_id 仍为空(下一步用一次性脚本 + convert API 回填)
  • docs/design/design_id_ecosystem_audit_2026-04-14.md — ID 生态 + schema + 代码盘点,带勘误记录
  • 归档 src/db_schema.py + one_off_scripts/crm_sync.py + sync_weiling_staff.py 3 个废弃 schema 文件(Agent 误导源)
v3.6.1 2026-04-14
pre-push hook 修复(Windows 环境 bug)
  • python3 空壳子问题 — Windows 上 `command -v python3` 会优先挑到 Microsoft Store 的空壳子(WindowsApps/python3),导致 pytest 无法启动,push master 永久失败。改为"先 `-c "import sys"` 自检再使用"
  • --delete 操作跳过测试 — 纯删除远程分支时(stdin 里 local_sha 全零)无代码变更,直接通过,不再白跑全量测试
v3.6.0 2026-04-14
卫瓴进线链路修复(jiayao 案例全面挖掘) + 合并引擎修复(双 bug) + 数据一致性巡检加强(51 → 55 项) + 推送通道统一 + 数据修复(prod 执行) + Schema + 其他 + 测试
  • 3 处事件名拼错修复 — 历史 AI 拼错的 `customer_add`→`add_customer`、`opportunity_void`→`opportunity_delete`、`opportunity_add` 未注册,17 天 silent 丢事件(约 104 次/周)
  • 装饰器注册制 + 启动清单 + 未识别事件计数器 — (UNKNOWN_EVENTS):防同类拼错 bug 回归
  • add_customer handler 启用业务逻辑 — 写入 `map_external(wm_id, customer_id, user_name)`,建立卫瓴-企微跨系统映射
  • contact_add 顶级兜底 — 通过 `related_customer[0].id → map_external.customer_id` 精准匹配,复用企微侧分配的 qbh,彻底修复官网智能码(type=102)等异步渠道的双号分裂 bug
  • contact_update 窄口子 — 解耦原则下仅对 user_name 空→非空开口,补名后联合触发头像下载 + 消息关联刷新
  • intake_channels.py 渠道字典 — 35 个 source_type 归类,五大 category,含 variants(小红书/抖音/官网智能码),激活 `crm_contacts.source_type/source_name/platform_source` 三字段写入
  • merge_contact latent bug — `execute_merge` 历史上不处理 `map_external`,改加 `UPDATE map_external SET contact_id=keeper_id, qbh=keeper_qbh WHERE contact_id=loser_id`,防将来 loser 是企微好友时留孤儿
  • plan_merge 预存 bug — `demand_note` 拼接时引用未定义的 `loser_qbh`,两边都有 demand_note 时触发 500 错误,UI 显示 `SyntaxError`
  • H08d — map_external 孤儿号(qbh 在 crm_contacts 找不到)
  • H08f — 最近 7 天新客户 source_type 必须非零(仅对 raw_json 非空的客户)
  • H12 — 在库客户空名/占位数量阈值
  • H10j — platform_source 必须用 intake_channels 标准 code
  • migration 012 — `notify_rules` 加 `consistency_alert` 规则
  • health_check.py 改走 notify 引擎 → 企微销售助手 — (原飞书直推):跟 nightly_report 同渠道
  • 保留"全绿静默,只推异常"设计
  • 1373 jiayao — (4 月 14 日今日进线):qbh 双号(1372/1373)合并 + 名字 `--`→`jiayao` + 头像下载 + 5 条消息关联
  • 1311 汪承勇 — (4 月 8 日历史同类 bug):qbh 双号(1312/1311)合并 + 名字补齐 + 头像
  • 1361 张艺瑾 — 归属人空修复
  • 98 条老客户 source 字段 — 从 raw_json 回填(延后·4 完成)
  • migration 011 — `map_external` 加 `customer_id TEXT` 字段 + 部分索引
  • migration 012 — `notify_rules` 加 `consistency_alert` 规则
  • 一次性脚本 one_off_scripts/20260414_backfill_customer_ids.py,五种模式(scan/fix-orphans/fix-names/fix-triangle/fix-source-type),dry-run 默认
  • 设计文档 [docs/design/design_intake_repair_2026-04-14.md](docs/design/design_intake_repair_2026-04-14.md)
  • Session handoff [docs/SESSIONS/active/20260414-weiling-intake-repair.md](docs/SESSIONS/active/20260414-weiling-intake-repair.md)
  • 卫瓴 API 速查手册 [docs/integrations/weiling/](docs/integrations/weiling/)(89 API + 40 doc 从 apifox 抓取)
  • 508 → 550 passed — / 0 failed(+42 新 case)
v3.5.0 2026-04-08
卫瓴彻底解耦(业务数据本地为权威) + 角色识别改进 + 归属人批量转移联动 + 商机列表性能优化(13 倍加速) + 权限管理按钮可点击 + 数据修复(已在正式库执行) + 新增 TODO
  • contact_add — owner_id 不再从卫瓴推送字段取,改为通过 wm_id/name 反查 external_contacts_snapshot.staff_userid("加了谁的企微就是谁的")
  • contact_update / opportunity_update / opportunity_void / customer_add — 全部降级为只记日志,不再写本地表
  • opportunity_void 危险炸弹修复 — 之前会 DELETE 本地商机,现已禁用(只记日志)
  • 死代码清理 — 删除 db.py 里 sync_contact_custom_to_crm 和 sync_contact_field_to_crm 函数,清理 crm.py 4 处调用、system.py update_contact_remark、payment_callback.py 中所有卫瓴写入代码
  • payment 回调 bug — 之前因 `crm_ok` 永假导致本地 crm_businesses.xdjfj 从不更新,现改为直接写本地
  • analyze_handoff.load_roles 并集读取 — user_permissions.roles + staff_schedule.role_type — 新员工只要在权限管理页勾选角色就自动生效,无需再配排班表
  • batch_owner 修复 — 客户运营页批量转移归属人时,现会**联动更新**该客户名下所有商机的 owner_id(之前只改 crm_contacts,漏了 crm_businesses)
  • 商机列表显示归属人 — business_list 页面的"商机负责人"列现在始终显示客户归属人(实现"商机归属人强制跟随客户归属人"的业务规则)
  • 历史数据修复:4 个唐秋姣 → 李凤伟的商机 owner_id 已批量修正(正式库)
  • _enrich_businesses 函数从 ~740ms → **~57ms**
  • 把 chat_merged 最后消息查询从 N+1 改为批量 JOIN+GROUP BY(省 ~700ms)
  • room_map / progress_count / contact_custom 全部批量预加载
  • 权限管理页"在职/停用"开关之前点了没反应(CSS pointer-events 问题),改为简单 button 样式
  • 陈晓曼名下 4 个孤儿客户(1307/1308/1309/1310)owner_id 从卫瓴 ID 修正为企微 userid
  • 陈晓曼 staff_schedule 补齐 7 天 kefu 排班(使得她加的客户首响时长可正常计算)
  • 角色体系与员工生命周期三层计划:存量权限代码审计 → user_permissions.roles 作为唯一真相源 → 入职/离职流程
v3.4.2 2026-04-08
修复 + 数据接入改进 + 调查问卷
  • 新建商机 NameError — `create_business` 引用未定义的 `sales_owner_id` 导致弹"name 'sales_owner_id' is not defined"。临时从 body 解析此字段(当前设计强制商机归属人=客户归属人,该字段实际不生效,留待后续清理)
  • STAFF_IDS 动态化 — `build_contact_wm_map.py` 不再硬编码 4 个员工,改为运行时从 `user_permissions` 读取所有 `is_enabled=1 AND can_own_customer=1` 的员工。新增员工自动纳入扫描
  • map_userid 懒加载补全 — `sync_archive_to_center.py` 同步消息时,遇到 `user_permissions` 有但 `map_userid` 缺的员工自动补一行,新员工开通存档当天就显示中文名
  • 后台显示优化 — 支持展示未完成作答的记录
v3.4.1 2026-04-07
修复 + 操作日志增强 + 测试基建
  • 企微私聊打不开 — `/open-dm/` 调用了不存在的 JSAPI `openExternalContact`,统一改为 `openEnterpriseChat({externalUserIds, groupName:''})`,列表绿色客户编号点击后能正常拉起企微单聊
  • 客户详情页打开私聊按钮失效 — v3.3.0 重构后 endpoint 路径参数从 `{contact_id}` 改为 `{qbh}`,但模板 href 未同步,修复后恢复
  • 企微 JSAPI 失败提示 — fail 回调显示真实 err_msg,不再笼统报"不是你的联系人"误导排查
  • 跟进类型显示 — 新建跟进的操作日志列表展示跟进类型蓝色小标签(微信/电话/视频/到店/量尺/设计方案/报价),与客户详情页样式一致
  • 写入端补 wechat 标签 — POST 接口的 MS_LABELS 补全 `wechat:微信`,自动生成 content fallback 时不再显示英文 key
  • config.py 增加 Darwin 分支 — Mac 本地用 `~/.sales-center-data` 作为运行时目录,SHARED_DIR 指向项目自带的 shared/ 避免 iCloud 老 llm_client 污染
  • conftest.py 补三张表 — survey_submissions / group_members / external_contacts_snapshot,让测试 DB 能跑通客户列表/详情/商机端点
  • test_default_30d → test_default_90d — 默认值早就改成 90 天但测试没同步;同时 mock cookies 避免 MagicMock 污染
  • test_column_config_render_types 同步集合 — link_detail → link_detail_avatar,加 staff_card
v3.4.0 2026-04-07
客户运营增强 + AI 智能搜索 + 日期范围偏好 + 菜单整理 + 其他
  • 非客户过滤 — 在库/全部/公海三个视图排除合作伙伴、外协等非"客户"类型联系人
  • 微信状态持久化 — wechat_status 字段写入 crm_contacts,60秒增量同步,支持 AI 搜索
  • 状态判定修复 — 已删除微信的客户不再误显示为"手机线索"
  • 搜索框修正 — 客户运营页搜索不再跳转到客户列表
  • 去除结果上限 — 移除 LIMIT 50 限制,返回全量匹配结果
  • 搜索历史修复 — 辅助搜索和深度搜索完成后正确保存历史记录
  • 翻页参数保持 — 翻页时保留 AI 搜索上下文,不再跳回全量列表
  • 日期范围修正 — AI 搜索结果自动使用"全部"时间范围
  • 微信状态查询 — 支持"查只有手机号的客户""没拉群的客户""已流失客户"等自然语言搜索
  • Cookie 持久化 — 用户选择 7d/30d/90d/全部后跨页面保持,无需每次重选
  • 默认值改为 90 天 — 客户列表、客户运营、商机管理、公海客户统一生效
  • 新增废弃功能页 — 客户数据同步、退群客户查询、同步日志移入待删除区
  • 排班管理 — 移入内测功能,**群成员管理**移入数据管理正式上线
  • 分类管理 — 移入系统设置页,系统设置精简为认证+分类
  • 数据管理 — 卡片改为紧凑横排样式,移除重复的审计日志入口
  • 批量变更阶段功能(前端)
  • 日期筛选链接透传 view 参数
  • 商机页日期解析统一复用 _parse_date_range
v3.3.0 2026-04-04
map_external.qbh 重构 + 客户编号芯片 5 种状态 + 企微跳转统一 + 消息同步修复 + 调研提交修复 + 消息推送规则 + 外部联系人管理 + 其他
  • 废弃 map_external.qbh 字段 — 所有 qbh 读取改为 JOIN crm_contacts,消除数据不一致根源
  • 涉及 15 个文件 30 处改动,缓存查询、回调处理、脚本同步全部改为 JOIN 关联
  • 244 条 map_external.qbh 为空导致的客户状态误判已根治
  • 有群 — (蓝色 group):客户在群中,可点击打开群聊
  • 客户离群 — (红色 person_off):群存在但客户已退出
  • 有微信未建群 — (绿色 person_add):有好友关系但未建群,可点击打开单聊
  • 手机线索 — (黄色 phone_iphone):仅有手机号,未加微信
  • 已流失 — (灰色 delete):好友关系已删除
  • 芯片样式优化:圆角长方形、紧凑布局(4px radius / 18px 行高)
  • 合并中间页 — open_chat + open_dm → 统一 open_wecom.html,通过 mode 区分
  • 失败自动返回 + toast 提示(1.5秒),不再卡在中间页
  • 浅绿色"有微信未建群"芯片可点击打开单聊
  • sender_name 修复 — 252 条显示为 wm_id 的消息修正为客户名(通过群成员/客户名 fallback)
  • sender_type 修正 — 1333 条 wm 开头的客户消息从"员工"改为"客户"
  • CSV+API 去重 — 380 条重复消息清理
  • 代码修复 — sync_archive_to_center.py 加三层 sender 识别 fallback
  • database locked 防护 — INSERT 加 3 次重试(间隔 0.5 秒)+ get_db timeout 10 秒
  • 发起人记录 — survey_submissions 新增 sender_userid 字段,记录谁发送的问卷
  • 销售工具认证 — 从免登录改为需登录(企微 OAuth 静默授权),确保有员工身份
  • wx-service 群通知关闭 — 通知统一走 notify 引擎(销售助手→归属人)
  • 管理页面 — 内测功能新增"消息推送规则",配置事件→机器人→接收人
  • 双机器人支持 — 销售助手(1000012) / 营销中心(1000013) 可选
  • 接收人三维度 — 发起人 + 归属人 + 额外人员,可叠加去重
  • 第一条规则 — 客户完成需求调研 → 销售助手通知归属人
  • 快照页面 — 624 条外部联系人完整记录,按员工/匹配状态筛选
  • 公海客户映射 — 137 条公海客户 vs 外部联系人交叉比对,标注好友状态
  • 商机阶段显示名统一(商机确认→商机客户、缴纳定金→定金客户、赢单→成交客户)
  • 全局字段名调整(互动会话数→会话段落、跟进记录→跟进)
  • 全局字号调整(客户编号/名片/金额/手机号/员工名片统一缩小)
  • 群成员管理"无客户群"合并为 Tab
  • 操作日志增强(建群日志完善、login 红色标签、群成员人名修正)
  • 公海领取按钮(客户详情页)+ sea_pool_name 清空修复
  • 健康检查修正(删 H19/H24、修 H20、新增快照/推送/锁冲突检查)
  • 客户头像下载修复(CORP_ID 未定义 + wm_id 直传)
  • 非微信客户自动编号 + 默认名称"手机客户"
v3.2.5 2026-04-04
调研模块重构 + 小红书聚光线索对接 + 操作日志增强 + 收款系统优化 + 非微信客户支持 + UI / 配置修复
  • 评分引擎 v2 — 混合架构 — 业务价值(50分)纯规则引擎 + 填写质量(25分)/信息真实性(25分)由 AI 评判
  • AI 摘要 — Qwen Turbo 生成 150-200 字结构化摘要(客户画像→装修需求→填写质量→跟进建议)
  • 调研结果页重做 — 绿色客户卡 + 白色评分环形图 + 黄色需求卡 + 紫色进阶卡 + 蓝色行为卡
  • 调研管理页重做 — 卡片布局替代表格,评分色块(A绿/B蓝/C黄/D灰) + 三维度进度条 + AI 摘要预览
  • 客户详情页调研入口 — 价值评分旁增加调研芯片(绿色=有调研,灰色=未调研),点击跳转结果页
  • 新增字段迁移:score / score_detail / ai_summary / survey_type / has_survey
  • Webhook 接收 — `POST /api/xhs/leads`,HMAC-SHA1 签名验证,自动入库 xhs_leads 表
  • 线索查看页 — `/system/xhs-leads`,展示线索基本信息
  • 归因分析页 — `/system/xhs-analysis`,KPI 卡片 + 转化漏斗 + CRM 匹配(手机→微信→昵称三级匹配)
  • 客户头像+名称 — 日志关联客户信息,显示头像和可点击客户名
  • 商机关联客户 — 通过 raw_json.customer_list 反查客户,商机日志显示"客户/商机名"
  • 编号列 — 新增 qbh 列,群事件点击打开群聊,其他点击跳转客户详情
  • 字段翻译扩充 — 30+ 新字段中文名(里程碑/交付/商机/收款等)
  • 分页居中 — 翻页按钮和统计信息垂直排列居中
  • 群成员变动人名 — 回调记录具体谁加入/退出(diff API vs 本地成员表)
  • 分页拉取 — 支持超过 100 条账单的分页查询
  • 去重入库 — payment_bills 表持久化,transaction_id 去重
  • 手动触发支持时间范围 — `POST /api/payment/poll` 可指定 hours 参数
  • 自动分配客户编号 — 卫瓴回调创建客户时,qbh 为空则立即从 customer_seq 分配
  • 默认名称"手机客户" — user_name 为空时自动写入,替代"未命名"
  • 公共编号函数 — `allocate_customer_number()` + `ensure_customer_number()` 提取到 db.py
  • 列配置 display_name 不再被重启覆盖 — 启动同步仅更新 is_sortable,保留用户自定义名称
  • 客户昵称截断 — 全局 NICK_MAX_LEN=10,超长昵称显示前10字+".."
  • 头像注入统一 — 客户列表/商机列表/交付列表统一使用 enrich_avatars(),消除重复代码
  • 客户编号跳转路由 — `/crm/customer/{qbh}` → 302 到客户详情页
  • 客户详情页去除报价单按钮
v3.2.0 2026-04-03
数据库审计系统 + Bug 修复 + UI 组件系统 + 全局字段命名统一 + 头像系统 + 内测功能 + 其他
  • SQLite 触发器审计 — 24 个触发器覆盖 11 张核心表,自动捕获所有 INSERT/UPDATE/DELETE
  • _audit_ctx 上下文标识 — 区分操作来源(web/crm_sync/weiling_cb/未知)和操作人
  • 审计日志页面 — 按表/操作/来源/时间筛选,变更对比(old_data vs new_data JSON diff)
  • 跟进记录删除 500 错误 — 后端 crm_result 未定义导致删除成功但返回 500,前端 Promise 无 catch 导致按钮卡死
  • 下拉框数据丢失 — 装修状态/预算区间选项不包含 CRM 同步值(精装改造/在住翻新/待交房/中/高等),打开页面即被覆盖为空。已恢复 34 条误清空数据(20 个客户)
  • 关闭卫瓴回写 — 新增 WEILING_WRITE_ENABLED 开关(默认 False),关闭 6 个往卫瓴写数据的入口
  • OAuth 登录失败友好页 — 替代白屏,显示重试按钮
  • 13 个全局 macro 组件 — 客户芯片/名片/员工名片/阶段标签/状态标签/来源标签/金额/时间戳/手机号/价值评分/里程碑/消息统计/最后聊天
  • column_render 组件化 — 列表内联样式替换为 macro 调用,新增 render_type(link_detail_avatar/staff_card/phone/phone_full)
  • 客户列表+商机列表 — 头像名片(24px 圆角方形)、员工名片(22px 圆形+个人配色)、DM Sans 数字字体
  • 列配置页面增强 — 渲染样式标签(增强紫/普通灰)、下拉切换、iframe 真实预览
  • UI 组件规范展示页 — 真实数据渲染,修改 components.html 刷新即见
  • field_dict.py — 90+ 字段中文别名,全站统一引用
  • 统一命名:微信昵称/真实姓名/客户编号/归属人/互动会话数/活跃天数/跟进跨度/综合 QME 等
  • 手机号统一从 mobile 字段读取,废弃 phone 字段
  • 手机号默认不脱敏(phone_full),可切换脱敏(phone)
  • 客户头像自动下载 — 卫瓴回调 contact_add/update 时自动下载+生成 96x96 缩略图
  • 员工头像 OAuth 采集 — scope 改为 snsapi_privateinfo,员工首次登录自动下载头像
  • 头像压缩 — 客户 39.5MB → 1.1MB,员工 431KB → 2.8KB
  • 合同管理 — 成交客户合同生成与下载,内置模板+自定义模板切换
  • 客户生命周期原型 — 聚合 audit_log+operation_log+crm_progress+group_members 时间线
  • 内测功能页面 — 7 张功能卡片集中入口
  • 通讯录同步回调 — 企微通讯录变更事件接收(凭证已配置)
  • 侧边栏精简,报价系统移到外部系统
  • 企微群变更回调凭证新增通讯录同步
v3.1.0 2026-04-02
数据体系统一(脱离卫瓴) + 商机管理重构 + 调研问卷 CRM 集成 + 销售工具 + 全流程操作日志 + 数据一致性保障 + UI 优化 + 测试
  • owner_id 统一为企微 userid — 全量清洗 450 条客户 + 56 条商机,不再使用卫瓴 ID
  • 公海脱离卫瓴 — 退回公海/认领客户改为纯本地操作,不再调用卫瓴 API
  • 公海池本地化 — 公海池列表改为本地配置(7 个池,沿用卫瓴分组)
  • 卫瓴回调/同步仍保留,但 owner_id 入库前自动转换为企微 userid
  • 商机负责人强制绑定客户归属人 — 创建商机自动继承客户归属,编辑商机不可修改负责人,修改客户归属时商机联动更新
  • 客户阶段×商机阶段强制绑定 — 商机客户↔商机确认、定金客户↔缴纳定金、成交客户↔赢单
  • 自动创建商机 — 客户升到商机阶段及之后时,无商机则自动创建
  • 允许跳级 — 前三阶段可直接升到定金客户/成交客户
  • 不允许降级 — 商机阶段及之后不可回退,需退回公海
  • 删除丢单 — 移除丢单概念和所有相关 UI,用退回公海替代
  • 商机统计排除公海客户 — Tab 数字与列表完全一致
  • 赢单日期 — 创建/编辑赢单商机必须填写赢单日期
  • 问卷 H5 新增投影面积预估、户型图 2 个问题 + JS 显隐开关
  • 品牌故事重写 + 6 个介绍要点穿插问卷各阶段
  • 图片全量压缩(总计 11MB → 1.1MB)
  • 手机号内联校验(11 位数字,红色提示,不弹窗)
  • 浏览器返回键支持(history.pushState)
  • 提交数据关联客户编号(qbh)和 contact_id
  • 后台调研管理页面(数据管理→调研记录)
  • 详情页:客户信息/联系方式/调研回答分离
  • 新增销售工具入口页(需求调研 + 话术库)
  • 需求调研:自动检测当前客户(单聊 + 群聊),发送带 qbh 的问卷卡片
  • 已填写客户显示"查看调研结果"按钮
  • 话术库 API 代理(/wecom-api/ → 5066 端口)
  • 登录/登出记录(含 roles、UA)
  • 客户添加企微、删除好友
  • 群创建、群名变更、群成员变动、群解散
  • 客户提交调研问卷
  • 图片撤回标记(is_recalled)
  • 健康检查新增 8 项 — (H10b~H10h):customer_tags 覆盖率、owner_id 格式、商机归属一致性、孤立商机、商机阶段无商机、赢单缺日期等
  • 飞书通知 — 异常时自动发卡片消息给卓光
  • 定时检查 — 每天 9/14/21 点运行
  • 评分脚本修复 — INSERT OR IGNORE 确保新客户有 customer_tags 记录
  • ID 匹配改进 — 所有名字匹配改为 ID 优先 + 名字兜底 + 重名警告
  • 客户详情页阶段标签跟随统一配色
  • 跟进标签紧凑化(删"标记"二字,缩小间距)
  • 跟进记录空内容拦截
  • 创建跟进时自动更新 last_follow_time
  • 列配置:zsxm 改名"客户姓名",user_name 改名"微信名"
  • 资料库访问记录菜单移除
  • 15 项阶段绑定单元测试
  • 13 项生产数据一致性测试
  • 全部 210 项测试通过
v3.0.0 2026-04-01
权限管理系统 + 回声防护(F 方案) + 操作日志完善 + 开发测试 + 其他修复
  • 角色模板 — 8 个预设角色(超级管理员/系统管理员/销售总监/运营总监/销售/运营/设计师/客服),支持自定义新增
  • 一人多角色 — 一个用户可分配多个角色,权限取并集
  • 页面级权限 — 13 个菜单权限项,中间件统一拦截,侧栏按权限条件渲染
  • 数据级隔离 — 销售/客服/设计师只看归属自己的客户和商机,统计数字同步过滤
  • 可见性规则 — 可配置的数据放行规则(原始线索公开、客服线索公开、协作人可查看)
  • 人员管理 — 从企微 API 导入全员(含部门/手机/邮箱),启用/禁用开关,公司员工/外协标记
  • 归属人配置 — 客户归属人/商机归属人/协作人员三个独立开关,替代旧的 sales_staff.show_in_list
  • 未授权用户 — 显示"欢迎加入几何鸟,请联系管理员授权"页面
  • 无权限页面 — 统一 403 页面样式,提示"请联系管理员授权"
  • 卫瓴回调回声拦截 — 回调试图把字段改回 web 修改前的值时自动识别并拦截
  • 商机 owner_id 同步修复 — INSERT/UPDATE 均写入 owner_id 列,防止表字段与 raw_json 不一致
  • crm_sync 保护增强 — 批量同步时保留本地修改过的 owner_id
  • 全模块覆盖 — 卫瓴回调、企微回调、交付中心、权限管理、可见性规则、归属人开关均记录日志
  • 中文化 — 操作日志显示中文角色名和操作类型
  • 回声修复记录 — 数据恢复操作标记为 source=fix
  • 模拟身份 — 开发环境下可切换用户测试不同角色的菜单和数据隔离效果
  • 67 个权限测试 — 覆盖角色合并、数据隔离、API CRUD、中间件拦截、可见性规则
  • 商机列表 SQL — 补全 b.owner_id 字段,归属人筛选时统计数字同步更新
  • 配置列按钮 — 商机管理和公海客户的"配置列"仅管理员可见
  • logout 修复 — 修正 auth._sessions → auth._session_cache 引用错误
v2.5.0 2026-03-31
界面简化与优化 + 客户详情页移动端优化 + 商机管理增强 + 企微回调修复 + 数据一致性修复 + 巡检与监控 + 企微卡片优化 + 测试
  • 导航重构 — 总览改为导航页(纯卡片入口,去掉 KPI 数字),侧边栏精简(删除会话分析、数据大盘、安装售后跟踪)
  • 外部系统 — 聚光投放看板、CRM系统、老版看板统一到独立卡片页面
  • 菜单调整 — 营销决策下"跟进督办"改名"任务看板",数据管理移入系统管理
  • 客户列表 — 去掉联系人统计小字和配置列按钮,三个 AI 按钮合为一个"AI搜索"
  • 响应式布局 — 跟进记录优先展示,商机/聊天/图册默认折叠点击展开
  • 底部操作栏 — 写跟进、改商机/填商机、退公海固定底部,发企微保留右上角
  • 性能优化 — JS-SDK 和 Chart.js 按需加载,禁止 iOS 输入框缩放
  • 行距优化 — 区块间距加大,手机端阅读更舒适
  • 排序支持 — 除创建时间外所有字段支持正序/倒序排序(群消息、最后沟通等复合字段修复)
  • 列表修改按钮 — 每行末尾绿色"修改"按钮,实时加载数据弹窗编辑(方案B)
  • 字段补充 — 新增客户归属销售、客户阶段、进线渠道、私聊消息、QME评分、价值评分等20+可选字段
  • 字段修正 — "商机归属"重名消除(商机负责人 + 协作人),display_name 自动同步
  • 弹窗复用 — 商机编辑弹窗抽取为公共组件,商机列表和客户详情共用同一份代码
  • 多凭证支持 — 同一回调 URL 自动匹配会话存档和自建应用两套凭证,联系人事件不再被静默丢弃
  • 编号即时分配 — 企微回调到达后立即分配编号写入 map_external,不再等待卫瓴 CRM
  • 消息关联联动 — 编号分配/map_external 变更后自动刷新 chat_merged 的 contact_id、scope、sender_name 和统计
  • map_external 同步 — CRM 同步 sweep 和卫瓴 contact_add 均同步 map_external(qbh + contact_id)
  • 跟进记录去重 — CRM 同步写入 progress 时按 content+时间去重,防止回弹产生重复记录
  • owner_name 回填 — 修复 owner_name 为空但 owner_id 有值的 4 条客户记录
  • H08b — map_external 有编号但无 contact_id(编号已分配但未关联)
  • H08c — crm_contacts 有编号但无 map_external 记录
  • H08d — 客户私聊消息 scope=internal(消息关联未刷新)
  • 发送人标识 — 客户卡片和跟进提示显示发送人(操作人)
  • 客户信息 — 卡片增加真实姓名和电话
  • 预览框精简 — 客户卡片和跟进提示去掉编辑预览框,自定义内容保留输入框
  • HTTP 端点测试 71 项 — TestClient 覆盖认证中间件、CRM API、公海 API、企微/卫瓴回调
  • 消息关联测试 5 项 — refresh_contact_link 的 contact_id 回填、scope 修正、统计刷新
  • 数据一致性测试 — map_external 同步、跟进记录去重、编号连续性
  • 总计 308 项测试全部通过
v2.4.0 2026-03-30
公海管理 + 公海同步机制 + 客户编号自动分配重构 + 数据修复
  • 公海客户列表 — 独立页面,支持配置列、时间范围筛选、阶段/归属人筛选
  • 列配置系统 — 默认视图 + 复盘分析两个预置模板,可自由增删评分/消息统计列
  • 退回公海 — 客户详情页橙色按钮,实时拉取卫瓴公海池列表,支持选择公海池 + 填写原因
  • 公海提示条 — 公海客户详情页顶部红色提示
  • 客户列表隔离 — 客户列表自动过滤公海客户,阶段统计不含公海
  • CRM同步公海检测 — 每小时自动检测进出公海的客户(batch API)
  • 卫瓴回调检测 — contact_update 实时检测 status 变化
  • 数据完整性 — 公海客户的跟进记录、聊天记录、历史数据全部保留
  • 企微回调自闭环 — 调企微API拿客户名 → 写 map_external → 多策略匹配 → 分配编号
  • CRM同步兜底扫描 — sync_all 末尾扫描无编号联系人,自动分配
  • 不依赖定时任务 — 不再依赖已停用的 sync_group_qbh.py
  • owner_name 解析 — CRM同步兼容 weiling_id 格式,INSERT/UPDATE 均写入 owner_name
  • 企微回调 weiling 同步 — 修复引用未定义 BASE/SSL_CTX 的 bug,改用 requests
v2.3.0 2026-03-30
客户编号系统 + 企微回调升级 + 图片缩略图 + 定时任务优化 + CRM 同步安全加固 + Bug 修复
  • 全量覆盖 — 453 个客户 100% 有编号(存量 709-999,新客户 1255 起自增)
  • 自动分配 — 企微加好友回调自动分配编号,不依赖卫瓴
  • 界面更新 — 全站 21 个文件"群编号"改为"客户编号"
  • 有群/无群区分 — 有群蓝色可点击跳群聊,无群灰色纯展示
  • 全局 has_room — Jinja2 全局函数,缓存 60 秒,所有模板可用
  • 群变更回调 — 建群/改群自动获取群详情、提取编号、写 map_room
  • 加好友回调 — 自动分配客户编号 + 同步卫瓴
  • 回调分发 — vps_service.py 解析 XML 事件体,区分群事件/联系人事件/消息通知
  • 下载自动生成 — media_download_recent.py 下载后生成 thumb_xxx.jpg(800px, q=80)
  • 存量批量压缩 — 649 张图片 254MB → 36MB 缩略图(压缩 86%)
  • CRM 全量同步停用 — 本地数据自建,全量同步有覆盖风险
  • AI 画像 + 向量库停用 — 本地 ChromaDB 暂无人用
  • sync_group_qbh 停用 — 改由企微回调 + sync_qbh_to_weiling 替代
  • sync_archive_to_center 精简 — 删除 map_room/map_external/图片触发(改由回调)
  • 聚光同步独立 — 从 cron_sync.sh 拆出 cron_xhs.sh,每天 4:00+12:00
  • 新增 sync_qbh_to_weiling — 每小时回填卫瓴客户编号
  • contact_custom 本地优先合并 — 卫瓴只补充本地为空的字段,不覆盖
  • crm_users 安全更新 — 从 INSERT OR REPLACE 改为逐字段 UPDATE,不冲 weiling_id
  • 客户列表"全部"按钮 — 时间筛选改为 range=all,不再 fallback 到 30 天
  • 客户列表归属人统计 — 跟随阶段+日期筛选
  • 客户详情页 conn.close 顺序 — login_weiling_id 查询移到 close 之前
v2.2.0 2026-03-29
创建商机 + 编辑商机 + 销售人员管理 + 商机列表增强 + 版本管理自动化 + 数据清理 + Bug 修复
  • 新建商机弹窗 — 客户详情页右上角入口,窄屏单列布局适配企微侧边栏和手机端
  • 阶段联动字段 — 商机确认→预计金额,缴纳定金→定金,赢单→全部金额+合同编号
  • 客户阶段自动同步 — 商机确认→商机客户,缴纳定金→定金客户,赢单→成交客户
  • 阶段变更拦截 — 无商机时变更到商机客户/定金客户/成交客户,强制先创建商机
  • 按钮自动切换 — 有商机显示"修改商机",无商机显示"新建商机"
  • 防重复 — 同一客户不允许创建第二个商机
  • 弹窗重做 — 与创建商机样式完全一致,单列长条形,阶段联动
  • 编辑增加丢单 — 创建时不可选丢单,编辑时可选
  • sales_staff 表 — 从卫瓴 API 同步 24 人,归属人下拉 9 人(含卓光)
  • weiling_id 全量补全 — crm_users 从 5/17 提升到 16/18
  • owner_name 回填 — 353 个客户归属人姓名补齐
  • 商机归属人独立存储 — crm_businesses.owner_id,与客户归属人分开
  • 4 阶段模板 — 商机确认/缴纳定金/赢单/丢单,切换自动套用
  • 表头排序 — 点击倒序,再点正序,默认创建时间倒序
  • 阶段统计跟随筛选 — 日期+阶段筛选后数字同步更新
  • 归属人修正 — 从协作人改为商机归属人
  • 顶栏 tab 移除 — 改由阶段按钮直接联动
  • version.py — 版本号唯一来源,模板自动读取
  • changelog 动态渲染 — 从 CHANGELOG.md 解析,不再维护两份
  • shared_templates — 13 个 router 统一 Jinja2Templates 实例
  • 重复商机作废 — 7 条重复商机通过卫瓴 API 作废并删除本地
  • 商机备注迁移 — 44 条 bzsm 追加到联系人客户需求字段
  • map_external API 补映射 — 20 个无群客户通过 customer/get 补上 wm_id
  • 商机关联客户 — 改用 customer_list.id,不再依赖群编号
  • STAGE_CODE_MAP — 缴纳定金从 3 修正为 9
  • 客户列表归属人统计 — 跟随阶段+日期筛选
  • 客户列表全部按钮 — 保留当前阶段筛选参数
  • 操作日志 — 新建跟进显示优化,解析 JSON 内容
v2.1.0 2026-03-29
列表字段自定义配置 + 模板系统 + 商机管理合并 + 跟进记录增强 + 回调防回弹 + QME 百分比化 + Bug 修复
  • 新增 column_templates 表 + list_column_config 重建(加 template_id)
  • 客户列表 53 个可选字段,13+ 渲染类型
  • 配置页面三区布局:横向字段条 + 数据预览 + Tab 分组配置
  • 自定义样式:颜色/字体/字号
  • 共享渲染宏 _macros/column_render.html
  • 模板增删改查 API + 复制
  • 客户列表和商机列表顶部模板下拉选择器
  • 客户预置 3 个模板:默认视图 / 销售跟进 / 数据分析
  • 三个页面合并为统一 /crm/businesses
  • 阶段筛选(全部/商机确认/缴纳定金/赢单/丢单)
  • 日期筛选 + 归属人筛选 + 自定义时间段
  • 复合渲染类型:composite_last_chat / composite_remark / money_highlight
  • 旧 URL 自动重定向
  • 里程碑标签:微信(默认)/电话/视频/到店/量尺/设计方案/报价
  • crm_progress 新增 progress_type + extra_json
  • 标签多选 + 时长记录
  • 回填卫瓴带标签前缀(如 [电话联系] 15分钟 ...)
  • 撰写人改为当前登录人(原来固定用客户归属人)
  • 批量删除(标记后统一提交,联动卫瓴废弃 API)
  • _is_echo_callback() 时间戳比对
  • contact_update / opportunity_update 自动跳过自身触发的回弹
  • compute_qme.py 归一化为 0-100%
  • contact_source 为 dict 时导致 last_follow 等字段解析失败
  • 何紫桐 weiling_id 缺失导致归属人为空
v2.0.0 2026-03-28
客户详情页全面改版 + 卫瓴CRM双向同步 + 性能优化 + 企微通讯录集成 + 图片自动下载 + CSV数据管理 + 操作日志优化 + Bug修复 + 数据库与备份 + 新增脚本
  • 四栏信息架构 — 基本信息(只读) / 客户信息(可编辑) / 装修情况(可编辑) / 需求备注
  • 客户阶段可点击变更 — 点击生命周期节点弹出确认窗,支持阶段升降级,手机端适配横条+变更按钮
  • 跟进记录输入 — 右侧跟进区顶部新增文本输入框+提交按钮,纯文本最多1000字
  • 商机编辑弹窗 — 点击商机行打开编辑弹窗,包含6格金额网格(预计赢单/定金/首付/成交/余货尾款/交付尾款)、阶段选择、协作人、备注
  • 归属销售可编辑 — 下拉选择框,数据从企微通讯录自动获取,只显示销售部/设计部/运营部在职人员
  • 进线溯源选择器 — 卡片式渠道分组(投放笔记/自然流量/转介绍/其他),笔记数据从聚光API动态查询(72篇,按消耗排序),支持手动输入,先选后存
  • 群编号打开群聊 — 深蓝醒目标签,PC和手机统一点击打开群聊
  • 私聊按钮 — 客户名旁绿色图标,点击打开与客户的私聊窗口
  • 手机端适配 — 生命周期横条、商机卡片布局、4tab横滑、弹窗底部全屏、右上角按钮精简
  • AI客户画像 — 移至关联商机下方展示
  • AI智能摘要 — 从客户详情页移除(独立功能后续规划)
  • 基本信息扩充 — 评分行(互动/QME/工时/价值等级)、地区(自动)、手机号(可复制)
  • 回调全字段补齐 — contact_add/update 补齐 jxsy/mobile/owner_name/created_at,opportunity_update 补齐 staff_list/created_at,customer_add 写入 crm_customers 表
  • 回调空值保护 — UPSERT 每个字段加 `CASE WHEN excluded.xxx != '' THEN ... ELSE 保留本地 END`,防止回调推送空值覆盖本地数据
  • 全场景自动回填 — 阶段变更→contact/edit、进线溯源→contact_custom.jxsy、客户信息(真实姓名/地址/房屋类别/面积)→contact_custom、性别→contact/edit gender(int)、商机编辑→business/edit、跟进记录→progress/create(成功后替换local_ID为卫瓴真实ID)
  • CRM同步保护 — crm_sync.py 从 INSERT OR REPLACE 改为逐字段 UPDATE,查 operation_log 判断哪些字段被本地修改过,本地修改过的不被覆盖
  • 历史回填补回 — 21条未回填记录全部补回(阶段6条/归属8条/性别2条/溯源1条/跟进4条),0条剩余
  • 字段回填能力清单 — customer_stage/owner_id/gender/jxsy/contact_custom全部可写,mobile/contact_ways不可写
  • chat_merged 物化消息表 — 取代 chat_unified 视图的4段UNION查询,页面加载从1.5秒降至0.1毫秒(提升15000倍)
  • 全项目迁移 — crm.py/chat.py/followup.py/dashboard.py/ai.py/admin.py 共11处查询全部迁移到 chat_merged
  • scope字段 — customer/internal/system 区分消息范围,客户详情页只显示customer消息
  • 7个索引 — send_date/qbh/contact_id/scope/chat_type/qbh+date/contact_id+date
  • stats刷新 — refresh_stats_v2.py 从复杂去重改为统一查 chat_merged,耗时从数十秒降至0秒
  • 自动同步 — sync_wecom_staff.py 从企微原生API(qyapi.weixin.qq.com)获取部门+员工列表,写入crm_users
  • 一人一条 — 同时存企微userid和卫瓴weiling_id,get_staff_name()统一查表
  • OWNER_MAP删除 — 4个文件16处硬编码全部删除,以后新增员工只需企微通讯录添加
  • 在职/离职 — status字段,离职员工不显示在下拉框中
  • XiaoLi映射修正 — 企微userid XiaoLi 显示名从"小李"修正为"李晓明"
  • 实时触发 — 消息同步完成后自动调用 media_download_recent.py 下载最近图片
  • crontab兜底 — 每小时15分运行一次,扫描最近70分钟的消息
  • 私聊图片 — 和群聊图片统一处理,按客户qbh归档到files/{qbh}/
  • 积压补回 — 224张图片补回成功,88张因sdkfileid过期无法恢复
  • 导入脚本 — import_csv_export.py,导入卫瓴CSV到chat_csv_messages + 自动重建chat_merged
  • 3月22-28日数据 — 4199条新消息入库,327条去重跳过
  • contact_id修补 — 7种策略补全空contact_id(API sender_id匹配/msg_id反查to_list/CSV客户名匹配/目标名匹配等)
  • 增量同步顺序修正 — 先补全map_room/map_external映射,再写chat_merged
  • 操作人区分 — 卫瓴CRM回调→"卫瓴CRM"、登录用户→真实姓名、营销中心API→"营销中心"、定时任务→"定时同步"
  • 全中文化 — 操作类型(修改字段/新建/数据同步等)、字段名(客户阶段/归属销售/进线溯源等30+字段)
  • 认证修复 — /api/contact/ 从认证白名单移除,操作日志正确记录真实操作人
  • 回调覆盖事故 — 卫瓴回调推送部分字段导致qbh/jxsy/contact_custom被冲成空值,UPSERT加空值保护
  • 客户列表归属销售不更新 — 列表SQL漏了c.owner_name字段
  • owner_userid从raw_json取导致不一致 — 改为优先从crm_contacts.owner_id取
  • sqlite3.Row不支持.get() — 跟进记录创建人取值方式修正
  • 阶段变更失败"无效阶段" — 前端传stage后端期望new_stage,字段名不一致
  • crm_users李凤伟ID截断 — 旧记录和新记录ID不同导致下拉匹配不上
  • 重复客户清理 — 大萌砸和苹果各删除1条卫瓴已合并的失效记录
  • gender回填失败 — 传中文"男"/"女"改为传int(1/2)
  • 私聊按钮空白页 — 非企微环境增加唤起企微+返回链接
  • 手动备份 — /opt/backups/manual/ 目录,重要操作前自动备份
  • 自动备份 — 每天凌晨3:30,按星期轮替+周日压缩周备份
  • chat_merged表 — 25628条消息(API 5665 + CSV 19962)
  • src/build_chat_merged.py — chat_merged 全量构建
  • src/media_download_recent.py — 增量图片下载
  • src/sync_wecom_staff.py — 企微通讯录同步
  • src/import_csv_export.py — CSV导入+重建chat_merged
  • src/backfill_crm.py — 历史未回填记录批量补回
  • src/fix_owner_names.py — owner_name 回填
  • prototype/customer-detail-v2.html — 客户详情页原型
  • prototype/source-picker-v1.html — 进线溯源选择器原型
v1.3.0 2026-03-23
商机管理 + 客户图册 + 企微深度集成
  • 商机管理重做 — 三页签(跟踪中/赢单/丢单),群编号可点击跳群聊,最后沟通时间颜色预警(7天绿/14天红),跟进记录数绿色徽章,备注说明点击弹窗编辑+保存到卫瓴CRM
  • 客户图册 — 企微SDK自动下载聊天图片(141张),缩略图加速加载,分类标签(客户/销售/设计),手动上传支持
  • 企微消息推送 — 发送客户卡片+跟进提示到营销沟通群,@归属销售提醒,发送目标支持群/个人切换
  • 打开群聊 — JS-SDK集成,客户详情页/商机页群编号点击直接跳转企微群聊,极简白色跳转页秒开
  • 聊天工具栏 — 企微群聊侧边栏接入,自动识别当前群跳转客户详情
  • 客户详情页重构 — 信息三合一卡片(基本信息/客户信息/需求备注),补充信息可编辑+保存,需求备注有内容圆点标识,手机竖屏适配
  • 客户列表增强 — 群编号移至首列可跳群聊,消息数拆分客户/员工(5/8格式),日期筛选联动阶段和归属人统计
  • 卫瓴CRM写入 — contact/edit接口打通,补充信息+需求备注可保存
  • 会话同步优化 — stats刷新改逐条更新避免锁表,CRM同步后自动补缺失stats,map_room通过企微API补全145个群
  • map_external全量映射 — 企微API按名字匹配315/378联系人,新客户10分钟内自动关联
  • 认证持久化 — 开关状态存文件,重启不丢失
v1.2.0 2026-03-22
会话数据全链路打通 + 系统健壮性升级
  • 企微会话存档实时接入 — wecom-archive 注册为 systemd 服务(自动重启+开机自启),每5分钟增量同步到营销中心
  • CRM联系人与企微ID映射 — 通过企微API按名字匹配,307/369联系人已关联(83%),单聊消息可正确归属到客户
  • 客户列表消息列拆分 — 原"消息数"拆为"客服消息"(单聊/私信)+"群消息"(VIP群聊),均可排序
  • CSV/API消息去重 — CSV优先策略,同一天有CSV数据时不显示API消息,避免详情页重复
  • API消息内容格式化 — 原始JSON自动解析为可读文本:文本/[图片]/[语音 Xs]/[链接]/[小程序]/[文件]等
  • 系统健康监控 — /api/health 端点检查三项(会话采集/数据库/同步管道),数据管理页顶部绿/黄/红指示灯
  • 同步错误处理 — 消息同步不再静默吞错,每次都写日志,三级状态(success/warning/failed)
  • 定时任务体系 — 凌晨4点:CRM增量+聚光30天+联系人映射;每5分钟:会话同步+map_room补全+map_external推断+stats刷新
  • 数据管理页改版 — 三卡片布局(CRM/聚光/会话CSV上传),聚光分快速30天/完整90天,同步读秒计时,日志分页
  • 反馈系统增强 — 查看历史按钮(显示所有人提交的反馈),自动关联企微用户名
v1.1.0 2026-03-22
营销渠道分析大版本
  • 营销渠道分析(新模块) — 三视图:投放明细 / 渠道大盘 / 进线方式,全生命周期ROI表
  • 时间范围筛选 — 支持7天/30天/90天快捷选择和自定义日期,花费+客户同步筛选
  • 聚光数据全量同步 — 90天笔记按天花费数据导入
  • 渠道自动映射 — AI自动匹配CRM进线溯源到聚光笔记,34/35条自动确认(覆盖率99%)
  • 聚光数据一键同步 — 数据管理页新增同步按钮
  • 品牌登录页 — 几何鸟家居logo+渐变背景+企微扫码
  • 侧栏折叠 — 收起扩大可视面积
v1.0.0 2026-03-17
初版上线
  • FastAPI + Jinja2 + HTMX — 架构搭建
  • 企业微信扫码登录 — 认证系统
  • CRM客户列表 — 排序、筛选、分页、阶段标签
  • 客户详情页 — 生命周期图、聊天记录、AI分析
  • AI辅助搜索 — ChromaDB向量检索 + bge-small-zh向量索引
  • 漏斗分析、商机管理 — 基础功能
  • 聚光投放看板 — 嵌入展示
  • 一键部署脚本 — deploy.sh + Git版本管理
analytics 评分明细