开发日志_2026-10-31.md 6.3 KB

2026-10-31 迁移到 macOS + 验收修复

背景

从 Windows(Workbuddy 环境,D:\WorkbuddySpace\门店检测工具\)迁到 macOS。 迁移包 门店检测工作台_迁移包_20261030.zip 解压到本机后接续开发。

环境

  • macOS,系统自带 Python 3.9.6(/usr/bin/python3),零第三方依赖,符合原设计
  • 项目路径:门店检测工作台/store-ops/
  • 服务默认 127.0.0.1:8787

安装验收结果(全部 PASS)

  • data/app.db 完好:1409 家门店、1 个导入批次、2026-10 周期
  • KPI 与迁移说明自检值一致:1409 / 469 / 323 / 929 / 276
  • 用户自定义阈值保留:hx_amt_base = 10000(默认 12000),面板标「自定义」
  • 用户自定义文案保留:43 个模板字段,其中 3 个为自定义,概览行变量别名正常渲染(无残留花括号)
  • 详情抽屉:7 条指标条 / 17 个基准刻度 / 5 个问题项 / 预览按钮
  • 预览弹窗:按模板生成 698 字反馈文案,badvars=0
  • 文案配置面板:8 组、43 字段、43 个「+ 变量」按钮,实时预览正常
  • 指标配置面板:8 组、16 个输入框
  • 导入面板:导入历史正常
  • 导出 CSV:零核销筛选 276 家 + 表头,BOM 与中文列名正常
  • 收件箱 watcher(隔离副本验证):丢入 CSV → 20 秒内入库并归档到 processed/

新增:macOS 启动器

  • store-ops/启动工作台.command(可执行)
    • 自动探测 Python 3.7+,版本不够给安装指引
    • 参数:[端口] --local --no-open
    • 启动前检查端口占用,占用时提示已有实例
    • 默认 --open 自动开浏览器
  • README「启动」与「目录结构」、迁移说明第二节补 macOS 用法
  • 注意:开放局域网访问.bat 是 Windows 专用;macOS 首次运行在系统弹窗里点「允许」即可

修复:文件名日期解析把「年月」误读成「年月日」(严重,会写错月份)

  • 现象:导入 门店数据_2026-10.xlsx(无日期列、整月汇总)→ 周期被写成 2026-01, 且被当成 日粒度、日期 2026-01-00(非法日期)
  • 根因:旧正则 (20\d{2})[-_.]?(\d{1,2})[-_.]?(\d{1,2}) 三段全可选分隔符, 2026-10.xlsx 被回溯匹配成 2026 + 1 + 0
  • 修复 ingest.guess_period_date 重写,按「完整日期 → 年月 → 仅月份」优先级,且逐级校验合法性:
    • 日粒度只认分隔符齐全且年月日合法的写法:2026-10-30 / 2026/10/30 / 2026.10.30 / 2026年10月30日 / 20261030 / 10.28
    • 年月:2026-10 / 2026.10 / 2026年10月 / 202610 / 10月
    • 月/日非法(如 13 月、0 日)自动退回上一级,不再产生 2026-01-00
    • 回归测试 16 个文件名用例全 PASS
  • 连带修复:导入回包的 granularity / period 改为按实际入库行统计
    • 原来 granularity 只看传入的 date 参数,带「日期」列的 CSV 会误报成 period
    • 跨月文件现在回包 periods 明细,period 取行数最多的月份(前端按它刷新视图)

验证(隔离副本 /tmp/storeops_test,不动真实数据)

  • 月汇总 CSV / 月汇总 XLSX / 日数据 CSV(含重复行)/ 跨月 CSV / 重复导入幂等 —— 全部符合预期
  • 真实库 KPI 重启后无回归:469/323/929/276
  • 测试文件与进程已清理

环境备注(与 Windows 时代的差异)

  • 原记录「Chrome headless 会卡死」「Edge headless 截图」都是 Windows 结论;本机用 ego 浏览器(Chromium)验证,正常
  • 启动工作台.bat / 开放局域网访问.bat 仅 Windows 可用,保留不删(团队里可能还有 Windows 机器)

新增:单店分析报告(可打印 A4 / 可下载单文件 HTML)

  • 需求:用户选择优先做「单店分析报告导出」,使用场景桌面优先、手机随后
  • 入口:详情抽屉底部按钮行(预览分析结果 金色主按钮 + 导出报告 白色次按钮),Esc 先关报告再关抽屉
  • 报告五段:01 关键指标(复用 metricsOf/barColor 的指标条,带基准/目标/三级违规线刻度)→ 02 风险与限流因素(问题 + 建议动作表)→ 03 经营数据(8 张数据卡)→ 04 分析洞察 → 05 门店调整动作
  • 顶部操作:【打印 / 另存为 PDF】(window.print(),走系统打印)与【下载 HTML】(自包含单文件,样式内联)
  • 新文件 frontend/report.css:报告专属样式,自带全部依赖(不依赖 style.css), 这样下载出去的单文件 HTML 与工作台内看到的长相完全一致
  • 打印:@page A4 + body.rp-on 作用域下隐藏工作台外壳,普通页面按 Cmd+P 不受影响; -webkit-print-color-adjust:exact 保证金色/语义色打出来
  • 手机:max-width:640px 下指标单列、数据卡两列,375px 实测无横向溢出

关键设计决定

  • 报告不新增后端接口:检测规则在后端(rules.py),文案渲染在前端(fbVars/fmtTpl), 报告属于「渲染层」,所以放在前端生成,避免把变量替换逻辑再抄一份到后端
  • 为让报告与反馈文案共用同一套洞察条件,把 renderFeedback 里的洞察段抽成 insightTexts(s, X, flags)
  • 回归验证:抽函数前后对全部 1409 家门店的 feedbackText() 做稳定哈希比对, 汇总哈希 e86ee9 完全一致、逐店差异 0 —— 重构对外零变化

踩坑

  • .rphead 是 <header>,被 style.css 的全局 header{display:flex;justify-content:space-between} 命中,标题被挤到右侧;显式 display:block 并关掉 header::after 的装饰线
  • 全局 th{background:#fdf9ee} 等表格样式会串到报告表头;report.css 里把表头样式写全, 否则「工作台内预览」和「下载的 HTML」会长得不一样
  • A4 分页:h2 加 page-break-after:avoid + h2 + *{break-before:avoid},避免章节标题孤零零留在页尾
  • 空态文案曾重复成「本期无明显异常,本期无风险项。」—— 直接渲染 fb_no_issue 模板,不再拼后缀

待办(沿原 README「后续可做」)

  • 自动下载:接抖音来客/服务商 API 定时拉数,替代手动导出
  • 处理闭环:异常门店的整改动作记录与回填
  • 权限分层:区域经理/督导只看自己片区
  • 报告批量导出:按城市/督导一次导出多店 PDF