2026-10-17-mp-crm-customer-existing-issues.md 3.8 KB

客户管理移动迁移:原有问题记录

记录日期:2026-10-17。迁移阶段仅记录以下原有问题。后续用户明确授权修复 1、2、3,现已完成 Web 前端修复;未修改后端业务。

1. Web 客户跟进弹窗的联系人选项为空(已修复)

  • 位置:web-admin/src/views/crm/customer/FollowFormDialog.vue,loadContactList。
  • 证据:调用 fetchContactByCustomerId 后读取 res.data || [];该 API 直接使用统一 request.post,HTTP 包装层已经返回 res.data.data;后端 byCustomer 返回数组。因此正常数组响应会被错误替换为空数组。
  • 复现:客户有联系人时,在 Web 客户详情点击添加跟进,展开关联联系人下拉。
  • 影响:不能选择已存在的关联联系人。
  • 修复:读取已解包数组,同时兼容旧 { data: [...] } 响应;空响应或请求失败时清空列表。customer/components/ContactList.vue 使用的 API 同样返回已解包数组,已修复同类解析问题。

2. Web 客户操作日志详情直接插入 HTML(已修复)

  • 位置:web-admin/src/views/crm/customer/CustomerDetailDialog.vue,handleViewLogDetail。
  • 证据:模板字符串直接插入 row.operParam 等值,并启用 dangerouslyUseHTMLString: true,未见相应 HTML 转义。
  • 风险:含 HTML 的业务参数可能被作为标签解释,存在注入风险。此结论来自代码检查,未向真实业务库写入攻击样本。
  • 修复:弹窗改用 Vue VNode 与文本子节点,移除 dangerouslyUseHTMLString。模块、人员、时间、URL 和请求参数均不再按 HTML 解释;保留分段、参数换行和滚动展示。

3. Web 新增商机跟进的自动默认时间使用 UTC(已修复)

  • 位置:web-admin/src/views/crm/opportunity/components/FollowDialog.vue,打开新增弹窗时的 new Date().toISOString().slice(0, 19).replace('T', ' ')。
  • 证据:toISOString() 输出 UTC,截去时区标记后又作为本地日期显示/提交。在 Asia/Shanghai 中比本地时间早 8 小时。
  • 复现:北京时间 10:00 打开新增商机跟进,检查默认跟进时间(该表达式得到 02:00)。
  • 范围澄清:只针对“商机 → 添加跟进”的 followTime 自动默认值,不是客户跟进卡片顶部的 createTime,也不影响手动选择的“下次联系时间” nextTime。
  • 修复:复用现有 parseTime(new Date()) 生成本地时间。编辑已有记录的跟进时间与下次联系时间不变。

修复回归

  • pnpm exec tsx --test scripts/crm-existing-issues.test.ts:6 项通过。修复前 4 项失败,覆盖两个联系人入口、失败清空、全部日志字段的 HTML 转义、本地时间跨日、编辑时间不覆盖。
  • 测试直接执行组件中的真实处理函数;网络/弹窗仅在边界替换,不写入真实业务库。日志使用真实 Vue SSR 渲染验证,不执行恶意标签。
  • 连同移动客户模块测试共 11 项通过,pnpm build 通过;全量 vue-tsc 与修复前 675 条错误基线对比无新增。已同步代码图谱,尚未发布生产。

验证环境的原有限制

  • 全量 vue-tsc --noEmit 基线已有 675 条错误(输出 1514 行);本次新增客户模块的最终检查必须与基线比较,不能将全项目类型检查描述为通过。
  • AGENTS 要求的 scripts/check_field_consistency.py 在仓库中不存在;使用可用 Python 执行得到文件不存在错误。此次未新增/修改后端 CRUD、Pydantic 或业务表字段,因此通过逐项核对既有 schema 与新移动 payload 补充检查,但不宣称该脚本通过。
  • 本次浏览器回归使用隔离模拟 API,不写真实业务库。微信真机的 WebView 文件选择、预览/下载、业务域名、登录票据与真实角色权限仍需在发布环境验收。