# 门店检测工作台(本地版 · 前后端分离) 怡呵美门店数据检测工作台。每天把门店后台导出的数据丢进来,工作台自动算出 「哪些门店超违规线 / 低于考核基准 / 零核销」,并给出整改建议与反馈文案。 ## 目录结构 ``` store-ops/ ├── backend/ 后端(Python 标准库,零依赖) │ ├── server.py HTTP 服务 + API 路由 + 收件箱自动导入 │ ├── db.py SQLite 存储与月度聚合 │ ├── ingest.py 数据导入 CSV / Excel(编码自适应 / 表头别名 / 日·月双粒度) │ ├── xlsx.py .xlsx 解析(标准库 zipfile+XML,无需 openpyxl) │ └── rules.py 考核指标默认值 + 检测规则(唯一规则源) ├── frontend/ 前端(原生 HTML/CSS/JS + 本地 ECharts) │ ├── index.html │ ├── style.css 工作台主样式 │ ├── report.css 单店分析报告样式(A4 打印 + 移动端) │ ├── app.js │ └── vendor/echarts.min.js ├── data/ │ ├── app.db SQLite 数据库(自动生成) │ ├── inbox/ ★ 收件箱:CSV / Excel 丢进这里,20 秒内自动导入 │ └── processed/ 已处理的文件(按时间戳归档) ├── 启动工作台.bat 双击启动(Windows) ├── 启动工作台.command 双击启动(macOS / Linux) └── 开放局域网访问.bat 放行防火墙(Windows 管理员) ``` ## 启动 **Windows**:双击 `启动工作台.bat`。 **macOS / Linux**:双击 `启动工作台.command`(首次若被系统拦下,右键 → 打开)。 或者终端里: ```bash ./启动工作台.command # 默认 8787 端口并自动开浏览器 ./启动工作台.command 9000 # 换端口 ./启动工作台.command --local # 只允许本机访问 ./启动工作台.command --no-open # 不自动开浏览器 ``` 任何系统都可以直接调后端: ```bash python3 backend/server.py # 默认监听 0.0.0.0:8787(本机 + 局域网都能访问) python3 backend/server.py --local # 只允许本机访问(127.0.0.1) python3 backend/server.py --port 9000 --open # 换端口并自动开浏览器 ``` ## 同一局域网的其他电脑 / 手机怎么访问 启动窗口会打印两行地址,把「局域网访问」那一行发给同事即可: ``` 本机访问 : http://127.0.0.1:8787 局域网访问: http://192.168.10.232:8787 ``` **前提**:两台设备连同一个 WiFi / 同一个路由器,并且本机防火墙放行 8787 端口。 - 第一次用:双击 `开放局域网访问.bat`(会弹管理员授权,点「是」),只需做一次,之后一直有效。 - 仍然打不开时排查:① 本机网络是否被识别为「公用网络」(服务端已按端口放行,不受影响); ② 公司 WiFi 是否开启了「AP 隔离 / 客户端隔离」(开了就无法互访,需找网管); ③ 手机用流量、或连的是另一个网段(如 5G 频段不同路由器)也不行。 ⚠️ 该服务没有登录验证,同一内网内任何人打开链接都能看数据和改配置,**只在公司办公网络内使用,不要在公共 WiFi(咖啡馆、酒店)上开放**。想关闭局域网访问就用 `--local` 启动。 ## 每天怎么用 1. 从抖音来客后台导出门店数据(CSV 或 Excel .xlsx,日数据带「日期」列最好) 2. 工作台左侧【导入数据】选文件导入(支持 .csv / .xlsx);**或者**直接把文件丢进 `data/inbox/`,后台自动导入 3. 打开 http://127.0.0.1:8787 看 KPI、排查门店、点开详情、复制反馈文案给督导 ## 数据口径 - 核销率 = 核销券数 ÷ **门店页成交券数**(分母为 0 时不判定)。2026-11-01 起统一用门店页成交券数,不再用意向成交券数 - 差评率:新增评价 ≥10 用新增口径;否则累计评价 ≥20 用累计口径; 两者都不足时仍用累计口径判定,但**最高只判到「预警线」**,不会因一两条差评判成「非常严重」 - 评分取周期内最近一次有值的数据;**评分为 0 = 未开分**,文案单独显示「未开分」,仍计入评分不达标的 KPI - 评价回复率:只在有新增评价时判定(没有新评价就没有回复义务) - 「待核销」是**估算值**(门店页成交券数 − 核销券数,未扣退款),只能作邀约优先级参考,不是后台真实未核销订单数 - 同一文件内门店+日期重复的行只保留首行(其余跳过并提示) - 重复导入同门店同日期会覆盖,不会翻倍 - 同一月份同时有日数据和月汇总时:日数据覆盖 ≥15 天才按日聚合,否则用月汇总 ## 账号与权限 打开工作台需要登录。首次启动会自动创建管理员账号: | 账号 | 初始密码 | |---|---| | `admin` | `admin123` | **登录后会强制要求修改密码**,改完才能正常使用。 ### 三级角色 | 角色 | 查看 | 导出 | 导入 | 同步 | 改阈值/文案 | 账号管理 | |---|---|---|---|---|---|---| | 管理员 admin | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | 运营 editor | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | | 查看 viewer | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | - 左侧栏【账号管理】可以新建账号、改角色、停用、重置密码、删除 - 权限在前端隐藏入口,**后端接口也会校验**,直接调接口同样会被拒绝(403) - 会话有效期 30 天,Cookie 为 HttpOnly;密码用 PBKDF2-SHA256(12 万次迭代)加盐存储 - 改密码或重置密码后,该账号的已有会话会失效 ### 忘记密码怎么办 用另一个管理员账号重置。如果**所有**管理员都进不去: ```bash cd store-ops python3 - <<'EOF' import sys; sys.path.insert(0, 'backend') import db, auth db.set_password(1, 'newpass123', must_change=1) print('admin 密码已重置为 newpass123') EOF ``` ## 导出 导出入口统一在左侧栏【导入数据】面板里: - **下载当前周期最新一份** = 当前周期最近一次导入的原始文件 - **每条历史记录右侧的【原始文件】** = 那一次导入的原件(同一周期导过多次时用来区分) 导出的都是生意经给的 xlsx 原件,40 列,不含任何计算。 - 原始文件存放在 `data/processed/`,批次表用 `file_path` 记住对应关系 - 早期从 Windows 迁过来的 CSV 批次没有留存原件,按钮置灰 - 想按筛选条件导出一张表(含核销率等计算列),可以用 `/api/export.csv` ## 近30天数据自动同步 分析口径是**近30天滚动窗口**(今天往前 29 天到今天),不是自然月。数据每天自动从生意经拉取。 ### 自动跑 - 服务启动后内置调度:**每天 01:00** 自动同步 - 启动补跑:距上次成功超过 20 小时,服务启动 90 秒后自动补一次 - 服务窗口会打印「下次自动同步:2026-11-02 01:00」 ### 手动跑 - 工作台左侧 **【同步数据】** 按钮 - 或 `curl -X POST http://127.0.0.1:8787/api/sync` - 查状态:`GET /api/sync/status` ### 它做了什么 1. 用 ego 浏览器打开生意经(复用登录态) 2. 调接口建「近30天、全部门店、41 个指标、按统计周期聚合」的导出任务 3. 轮询约 3.5 分钟拿到签名下载地址 4. 下载 xlsx 到 `data/inbox/门店数据_<起>_<止>.xlsx` 5. 收件箱 20 秒内自动导入,文件名里的日期区间决定快照窗口 ### 存成什么样 快照写入 `metrics`,`granularity='snapshot'`,`period` 记「截至日」, `window_start` / `window_end` 记统计区间。周期下拉显示「近30天 · 截至 11-01」。 月汇总数据与快照共存,互不覆盖。 ### 依赖与限制 - **需要 ego 浏览器且生意经已登录**(登录态通常几周过期,过期后需在 ego 里重新登录一次) - 同步期间会弹一下浏览器窗口,约 3-5 分钟 - 生意经建任务**有每日次数上限**(一般在 30 次左右),脚本会先查剩余次数 - **为什么不用 launchd**:macOS 的 TCC 保护 `~/Documents`,系统级定时任务读不到这个目录里的文件 (实测 `head` 都被拒)。所以定时器放在服务进程里,服务从终端启动时是有的权限。 `sync/com.yhm.lifesync.plist` 保留作参考,若要启用需在「系统设置 → 隐私与安全性 → 完全磁盘访问」 里把 `/bin/bash` 加进去。 ## 诊断逻辑(v2) 规则唯一源是 `backend/rules.py`,设计依据见 `项目记录/规则设计_v2_思维导图.html`。 - **4 层并行**:流量 / 转化 / 履约 / 口碑各自独立判定、互不压制(共 17 条规则); 只有履约层内部「成交未核销 → 核销率低」按根因去重 - **5 档**:R 违规红线 / B 考核未达标 / T 运营提升 / N 样本不足 - **核销链内部去重**:零成交 > 成交未核销 > 核销率低,只报最上游一条 - **核销金额独立判定**:只要金额 < 基准就报,不受核销率约束(2026-11-01 定) - **诊断树选主因**:按层级顺序取第一个命中,只用于生成「一句话结论」,不影响问题清单 - **问题全列、每条给动作**:命中几个问题就列几个,每个问题对应一条整改动作,不做截断 - 每家门店输出:一句话结论 + 全部命中问题 + 对应整改动作 ## 考核指标(可自定义) 默认值来自飞书《门店考核指标》官方基准线。左侧【指标配置】面板可改, 改完点【应用到工作台】即可生效。 ### 改面板 = 直接改代码 改完不只是存库,还会**同步写回 `backend/rules.py` 的 `DEFAULT_THRESHOLDS`**, 所以不会出现「界面上是 10、代码里还是 30」这种两套数字打架: | 场景 | 结果 | |---|---| | 面板改完保存 | 立即生效 + 写回代码默认值 + 重新加载 | | 复制整个文件夹到别的电脑 | 改过的值跟着走 | | 【恢复默认】 | 回到**出厂值**(首次运行时快照在 `data/factory_thresholds.json`),并同样写回代码 | | 面板右上角标签 | 显示「出厂值」或「已自定义」(对照出厂值判断) | 写回时只替换阈值数值,保留键名、缩进和行尾注释;写入前会生成 `rules.py.bak` 备份, 写入后清字节码缓存并重新加载模块。 > 注意:因为会改源码,如果这个目录放在 git 里,改阈值会产生一次文件变更。 除了官方基准线,面板里还能调这几条 v2 新增的判定门槛: | 参数 | 默认 | 作用 | |---|---|---| | 访问过低线 | 100 次 | 低于此值判「访问过低」 | | 成交转化率过低线 | 10% | 成交人数 ÷ 访问 低于此值 → 「转化率低」 | | 视频数下限 | 10 条 | 新发布视频少于此数 → 「视频量少」 | | 点亮数下限 | 10 次 | 门店点亮少于此数 → 「点亮偏低」 | | 新增评价数下限 | 10 条 | 新增评价少于此数 → 「新增评价少」 | | 未核销积压提醒线 | 30 张 | 估算未核销券达到此数 → 提示集中邀约 | | 核销率最小成交券数 | 5 张 | 成交券太少时核销率不稳定,不判定 | | 客单价最小核销券数 | 5 张 | 核销券太少时不算客单价 | | 差评率最小样本(新增/累计) | 10 / 20 条 | 样本不足最高只判预警线 | | 回复率最小新增评价数 | 1 条 | 没有新评价就不判回复率 | ## API 一览(给后续自动化用) | 方法 | 路径 | 说明 | |---|---|---| | GET | /api/meta | 周期列表、阈值、导入历史、统计 | | GET | /api/dashboard?period=2026-10 | 工作台全量数据 | | PUT | /api/thresholds | 保存自定义阈值 | | POST | /api/thresholds/reset | 恢复官方默认 | | POST | /api/import?filename=&period=&date= | 导入 CSV / Excel(body=文件字节) | | GET | /api/export.file?period= | **导出原始文件**(该周期最近一次导入的 xlsx/csv 原件) | | GET | /api/batch/\/file | 导出指定批次的原始文件 | | GET | /api/export.csv?period=&kpi=&city=&cat=&q= | 筛选结果导出为 CSV(含核销率/待核销等计算列) | | GET | /api/history | 导入批次 | ## 深链接 - `/#TH` 直达考核指标面板 - `/#IM` 直达导入面板 - `/#<门店ID>` 直达该店详情抽屉 ## 单店分析报告 点开任一门店的详情抽屉,底部两个按钮: - **【预览分析结果】** —— 按文案模板生成的反馈短文,可改完直接复制发给督导 - **【导出报告】** —— 生成一页 A4 的门店检测分析报告 报告包含五段:关键指标(带基准/目标刻度的指标条)→ 风险与限流因素(问题 + 建议动作)→ 经营数据(客资 / 核销 / 退单 / 待核销 / 访问 / 成交 / 流失)→ 分析洞察 → 门店调整动作。 报告顶部有两个操作: | 按钮 | 得到什么 | |---|---| | 打印 / 另存为 PDF | 走系统打印对话框,目标选「另存为 PDF」即得 PDF 文件(macOS 选「存储为 PDF」) | | 下载 HTML | 下载一个**自包含**的单文件 HTML(样式内联,不依赖服务),可直接发微信或存档 | - 报告内容全部来自当前【文案配置】的模板,改了文案报告跟着变,不用改代码 - 手机宽度(375px)下报告自动改为单列排版,督导可以直接在手机上看 - 报告里不出现「同城竞对」数据——那部分属于「对标试点」轨道 B,目前未接入本工作台 ## 后续可做 - 自动下载:接抖音来客/服务商 API 定时拉数,替代手动导出 - 处理闭环:异常门店的整改动作记录与回填 - 权限分层:区域经理/督导只看自己片区 - 报告批量导出:按城市/督导一次导出多店 PDF ## 文案配置 左侧菜单【文案配置】可自定义门店分析反馈文案:反馈文案结构、问题文案、整改建议、严重档位名称。大括号变量生成时自动替换({门店名} {周期} {访问} {金额} {评分} {v} {base} {口径} {档} 等),未知变量原样保留。修改存库、立即对全部门店生效,【恢复默认】可一键还原。 每个字段右侧有「+ 变量」按钮,点开可点选变量直接插入,避免手写变量名出错。写错的变量会标红并在预览区顶部提示,不会静默原样输出。 ### 反馈文案可用变量 | 短名 | 含义 | 等价的数据表列名(别名,可直接写) | |---|---|---| | {客资} | 门店意向成交券数 | {门店意向成交券数} | | {核销} | 核销券数 | | | {核销券数} | 核销券数 | {门店核销券数} | | {成交券数} | 意向成交券数 | | | {退单} | 门店意向退款券数 | {门店意向退款券数} {退款券数} | | {访问} | 门店页访问次数 | {门店页访问次数} {门店页有效人数} {访问次数} | | {成交} | 实际成交人数 | {门店实际成交人数} {成交人数} | | {流失} | 访问-成交 | {流失人数} | | {成交占比} {流失占比} | 占访问比例 | {流失人数占比} | | {待核销} | 成交券-核销券 | {待核销订单数} {后台待核销订单} | | {金额} | 核销金额(元) | {核销金额} | | {评分} | 团购评分 | {门店评分} {团购评分} | | {评分基准} {核销率} {核销目标} {回复率} {回复基准} {核销金额基准} | 指标与基准值 | {评价回复率} {核销率基准} | | {门店名} {门店ID} {城市} {周期} | 门店与周期 | {门店名称} {门店城市} {统计周期} | 问题文案另可用:`{v}` 实际值、`{base}` 基准值、`{口径}` 新增/累计、`{档}` 档位名;条目格式可用 `{i}` 序号、`{问题}`/`{建议}`/`{洞察}` 内容。