← 返回目录
第一章 快速开始(零基础)
1.1 打开系统并登录
操作步骤
打开电脑浏览器(推荐 Chrome 或 Edge)。统一使用公网地址 https://douxi.sdydcq.com (接口走同域 /api,无需额外配置);在服务器所在局域网内也可用备用地址 http://192.168.0.128:8080 。
在浏览器地址栏输入系统前端地址——公网 https://douxi.sdydcq.com ,按回车(局域网备用 http://192.168.0.128:8080 )。
公网地址由域名 + HTTPS(Let's Encrypt 证书) 提供,指向同一套系统(接口自动走同域 /api,无需任何配置),手机扫码即可打开。原「花生壳内网穿透」方案已停用,排障说明见 附录 E 。
页面自动进入登录页,如图 1-1。
在「用户名」输入框填写账号,在「密码」输入框填写密码。
点击蓝色的「登 录」按钮;也可以填好后直接按键盘回车键。
登录成功后自动进入系统「主面板」。
首次登录后,建议立即到「个人中心」修改密码,方法见 1.4。
图 1-1 登录页
表 1-1 系统默认账号
角色
用户名
初始密码
能做什么
管理员
admin
douxiadmin
拥有全部权限,管理用户、配置、上传、日志、报表
BOSS
boss001
boss123
全局查看与组织管理、审批
大区经理
sr_大区ID
123456
管理本大区的区域、计划、用户与审批
运营
op_区域ID
123456
管理本区域的门店与平台数据
游客
自行注册
自行设置
只读查看主面板
没有账号怎么办
游客账号可以自行注册:在登录页点击「没有账号?注册游客账号」。
依次填写用户名、姓名(选填)、密码(至少 6 位),点击「注册并登录」。
注册成功后自动以游客身份登录。
运营、大区经理、BOSS 账号不能自行注册,需要由管理员或上级创建,或由系统在新建区域 / 大区时自动生成。
登录常见问题
1.2 认识系统界面
登录后看到的整体布局如图 1-2。
图 1-2 系统主界面(左侧导航已展开)
界面分区说明
左侧导航栏:系统所有功能入口,默认收起为图标;点击顶栏左上角的折叠按钮可展开或收起。菜单较多时可上下滚动。
顶部标题栏:显示当前页面名称、当前时间、当前登录角色与姓名、深浅色切换按钮和「退出」按钮。
主体内容区:当前功能页面,包含筛选条件、数据表格、图表和操作按钮。
提示消息:操作成功或失败时,屏幕顶部会弹出短暂提示,请留意其中的文字说明。
通用操作约定
默认日期:天默认到昨天,月默认到昨天所在的月,年默认到昨天所在的财年,避免因当天数据不完整造成误判。
财年:每年 2 月到次年 1 月,2 月是财年第一个月,次年 1 月是最后一个月。
分页:列表底部可切换每页条数、上一页 / 下一页、跳转到指定页。
排序:可排序的表头点击后会循环切换升序、降序、恢复原顺序。
自动刷新:主面板、大区管理、汇总看板默认每 30 秒刷新一次,页面会显示倒计时与最近更新时间。
1.3 切换深色模式
点击顶栏右侧的月亮 / 太阳图标。
图标为月亮时表示当前是浅色模式,点击后切换为深色;图标为太阳时表示当前是深色模式,点击后切换为浅色。
系统会记住您的选择,下次打开自动沿用。
图 1-3 深色模式 · 主面板
图 1-4 深色模式 · 门店管理
1.4 修改个人密码
在左侧导航点击「个人中心」。
在「修改密码」区域依次填写旧密码、新密码、确认新密码。
新密码建议 8 位以上,包含字母与数字。
点击「保存」,看到成功提示即修改完成;下次登录请使用新密码。
1.5 忘记密码或账号被停用
忘记密码:请联系管理员,在「用户管理」中为您重置密码(方法见 7.1.3)。
账号被停用:登录时会提示无法登录,请联系管理员或本大区经理确认原因并重新启用。
想提升权限:在「个人中心」提交提权申请,等待管理员审批,方法见 3.3。
第二章 角色与权限
2.1 六种角色
系统共有六种角色,权限从低到高依次为:游客、运营 / 督导 、大区经理、BOSS、管理员。每名用户同一时间只有一个角色,高级别包含低级别的权限。
表 2-1 六种角色说明
角色
代码
级别
典型职责
游客
guest
0
只读查看主面板,可申请提权
运营
operator
1
维护本区域门店与平台数据
督导
supervisor
1
只看本人名下门店(数据范围由服务端强制),维护名下门店与平台数据(提交审批)
大区经理
senior
2
管理本大区的区域、督导、计划、用户与审批
BOSS
boss
3
全局查看与组织管理、审批
管理员
admin
4
全部权限:用户、配置、上传、日志、报表、导出
关于督导 :督导是「大区的下一级」(一个督导 ∈ 一个大区,一个大区有多个督导,n:1)。门店通过「督导」关联到督导记录;督导账号登录后:
「我的区域」菜单显示为「我的门店 」,门店数与本/本年营收只统计本人名下门店 ;
门店管理、门店每日数据、汇总看板、报表下载、CRM 关注等页面只返回本人名下门店 (服务端按 supervisor_id 强制过滤,前端无法绕过);
只能提交本人名下门店/平台门店的审批,且门店所属大区必须是自己所在大区。
2.2 权限速查表
表 2-2 功能与角色对照
功能
游客
运营
督导
大区经理
BOSS
管理员
主面板
只读全国
可筛选
可筛选(仅本人门店口径)
可筛选
可筛选
可筛选
个人中心 / 改密码
可以
可以
可以
可以
可以
可以
深色模式
可以
可以
可以
可以
可以
可以
提权申请
运营、大区经理
大区经理
大区经理
BOSS
不可以
不可以
我的区域 / 我的大区 / 我的门店
不可以
我的区域
我的门店
我的大区
不可以
不可以
门店每日数据
不可以
可以
仅本人门店
可以
可以
可以
汇总看板
不可以
可以
仅本人门店
可以
可以
可以
门店管理
不可以
本区域;新增/修改/闭店提交审批(不可删除)
仅本人门店 ;新增/修改/闭店提交审批(不可删除)
本大区;改动提交审批
直接生效
直接生效
平台管理
不可以
本区域;新增/修改/闭店提交审批(不可删除)
仅本人门店的平台;同上提交审批
本大区;改动提交审批
直接生效
直接生效
督导管理
不可以
不可以
不可以
本大区:直连增删改
可以,直接生效
可以,直接生效
区域管理
不可以
不可以
不可以
可以,直接生效
可以,直接生效
可以,直接生效
大区管理
不可以
不可以
不可以
本大区,改动提交审批
直接生效
直接生效
计划管理
不可以
不可以
不可以
本大区,保存提交审批
直接生效
直接生效
用户管理
不可以
不可以
不可以
本大区运营/督导,增删改提交审批
直接生效(运营 / 督导 / 大区经理)
全部角色,直接生效
审批中心
不可以
可看「我的审批进度」
可看「我的审批进度」
处理本大区(待我审批)
处理全部待审,可提前终审
处理全部,可提前终审
报表下载
不可以
可以
仅本人门店
可以
可以
可以
每日数据上传
不可以
不可以
不可以
不可以
不可以
可以
系统配置
不可以
不可以
不可以
不可以
不可以
可以
操作日志
不可以
不可以
不可以
不可以
不可以
可以
各管理页导出
不可以
门店、平台
门店(仅本人)
全部
全部
全部
2.3 什么是审批,什么时候需要审批
审批是为了保护影响面较大的数据:某些修改不立即生效,而是先生成一张「申请单」,交给更高一级确认,确认通过后系统自动执行。
运营维护门店、平台门店(新增 / 修改 / 闭店):不立即生效 ,先提交审批(限本区域);大区经理通过后转 BOSS / 管理员终审。
督导维护门店、平台门店(新增 / 修改 / 闭店):不立即生效 ,先提交审批;范围限本人名下门店 ,大区经理通过后转 BOSS / 管理员终审(新建门店自动归属本人)。
大区经理维护门店、平台门店、用户账号,以及修改大区、保存计划:不立即生效 ,提交后由 BOSS / 管理员终审。
删除门店 / 平台门店、用户账号增删改:仅大区经理可提交 ,BOSS / 管理员终审(运营不能删除)。
区域管理由大区经理及以上直接维护(不经过审批)。
用户提权(游客升运营、运营升大区经理等)统一由 BOSS / 管理员审批。
BOSS / 管理员的操作直接生效,无需审批;也可对任意待审单提前通过 / 驳回。
好处是每一步都有记录,谁在什么时间改了什么、审批意见是什么,都能在「审批中心」和「操作日志」中查到。
第三章 游客
3.1 游客能做什么
游客是权限最低的角色,只能查看主面板,不能查看门店明细、汇总看板,也不能修改任何数据。适合临时了解整体情况的人员。
3.2 查看主面板
以游客账号登录后,系统默认进入「主面板」,如图 3-1。
左侧导航点击「主面板」可随时返回。
主面板展示全国范围的重要指标与图表,只读,不能修改。
图 3-1 游客主面板(全国只读)
3.3 申请提升权限
在左侧导航点击「个人中心」。
找到「权限申请 / 提权申请」区域。
选择要申请的角色:游客可申请「运营」或「大区经理」。
在理由框中填写申请原因(例如所在区域、负责范围)。
点击「提交申请」,等待管理员审批;可在「个人中心」查看审批状态。
审批通过后,系统会自动创建对应账号权限,重新登录即可看到新菜单。
3.4 个人中心能做什么
修改姓名。
修改密码。
提交提权申请。
注销自己的账号(注销后不可恢复,请谨慎操作)。
第四章 运营
运营是最常用的角色,负责本区域门店与平台数据的日常维护。登录后左侧菜单可见:主面板、个人中心、我的区域、门店每日数据、汇总看板、审批中心、组织管理(门店管理、平台管理)。
重要:运营对门店 / 平台门店的新增、修改、闭店 都不会立即生效,而是提交审批(限本区域),由大区经理通过后转 BOSS / 管理员终审;运营不能删除 门店 / 平台门店。可在「审批中心 → 我的审批进度」查看进度、未完成前撤回(详见第 02 号「审批流程」页)。
4.1 查看我的区域
在左侧导航点击「我的区域」。
页面展示您所负责区域的门店清单与汇总数据,如图 4-1。
可切换门店属性(全量 / 存量 / 增量)查看不同口径。
图 4-1 我的区域
4.2 查看门店每日数据
在左侧导航点击「门店每日数据」,如图 4-2。
在顶部选择日期、区域等筛选条件。
表格展示每家门店的单量、收入、曝光、转化、评分、差评等明细。
点击「单量」「收入」「曝光」「评分」「差评」等表头可排序,方便找出异常门店。
注意:该页面只显示当前营业中、且能匹配到平台门店 ID 的门店;已闭店门店请到汇总看板查看。
图 4-2 门店每日数据
4.3 查看汇总看板
在左侧导航点击「区域汇总看板」或「大区汇总看板」,如图 4-3。
切换年 / 月维度查看累计目标、实际与达成率。
使用「门店属性」切换全量 / 存量 / 增量,「显示」切换实际值 / 百分比。
看板默认每 30 秒自动刷新。
图 4-3 区域汇总看板
4.4 维护门店
在左侧导航点击「组织管理 - 门店管理」,进入门店列表,如图 4-4。
顶部筛选:按大区、区域、门店名称、营业状态、门店属性筛选;右侧「GMV月份」可选择要展示的月份,门店GMV、月GMV、月营收三列会随所选月份变化。
点击「门店GMV / 月GMV / 月营收」表头可排序。
图 4-4 门店管理
4.4.1 新增门店
点击右上角「新增门店」按钮,弹出表单。
按下表填写;带星号的是必填项。运营的「所属区域」自动默认为本人所属区域并锁定 (不能改到其它区域)。
点击「保存」后运营不立即生效 ,会生成审批单提交本大区大区经理审核,提示「已提交审批,待上级审核」。
表 4-1 新增门店字段说明
字段
是否必填
填写说明
所属区域
必填
运营自动默认本人区域并锁定;大区经理 / BOSS / 管理员自行选择
门店名称
必填
填写门店全称
省份
必填
门店所在省份
开店日期
必填
决定门店属于存量还是增量
督导
选填
下拉选择该门店所属大区下的督导(在「组织管理 → 督导管理」中维护);也可留空表示未分配
门店编码
选填
内部编码,可留空
城市 / 区县
选填
门店所在地
门店类型
选填
按实际选择
闭店日期
选填
不填表示营业中
属性(自动)
自动
系统根据开店日期自动判定
状态(自动)
自动
系统根据闭店日期自动判定
详细地址
选填
门店详细地址
4.4.2 编辑门店
在目标门店行点击「编辑」(仅可编辑本区域门店)。
修改需要变更的字段。
点击「保存」后不立即生效 ,生成审批单提交本大区大区经理审核。
4.4.3 闭店与重新开业
闭店:在目标门店行点击「闭店」,选择「闭店日期」(必填),点击「确认闭店」;提交审批 ,待上级审核。
重新开业:对已闭店的门店点击「重新开业」,如需调整开店日期可填写「开店日期」,留空则保持原日期,点击「确认开业」;同样提交审批 。
4.4.4 删除门店(运营不可执行)
运营没有删除门店的权限 (前端不提供删除入口,服务端也会拒绝)。删除门店由大区经理 发起并提交审批,BOSS / 管理员终审;删除为逻辑删除,历史数据仍可在日志中追溯。
4.5 维护平台门店
平台门店是系统门店与美团 / 淘宝闪购 / 京东门店的对应关系,只有匹配上平台 ID,每日数据才能归集到门店。
在左侧导航点击「组织管理 - 平台管理」,如图 4-5。
顶部可按平台、门店、门店属性、营业状态筛选。
图 4-5 平台管理
4.5.1 新增平台门店
点击右上角「新增平台门店」。
填写「平台门店ID」(必填)、选择「平台」(必填)、选择「关联门店」(必填,须为本区域门店)。
按需填写平台门店名称、平台类型、开店日期、闭店日期。
点击「保存」后运营不立即生效 ,生成审批单提交本大区大区经理审核。
4.5.2 维护与闭店
点击行内「编辑」修改平台门店信息:提交审批 (限关联到本区域的平台门店)。
点击「闭店」并选择闭店日期:提交审批 (限本区域)。
点击「重新开业」:同样提交审批 。
删除平台门店:运营不可执行,由大区经理提交审批。
4.6 导出数据
在门店管理或平台管理页面,先设置好筛选条件与排序。
点击右上角「导出」按钮。
系统会按当前筛选与排序生成 Excel 文件,既自动下载到本机,也保存到服务器对应目录(门店:export/store/年-月/,平台:export/plat/年-月/)。
文件名中包含筛选条件、排序条件与时间戳,便于区分。
第五章 大区经理
大区经理(系统角色代码 senior)负责整个大区。登录后除运营的功能外,还能看到「我的大区」以及组织管理中的区域、计划、用户管理,并可处理审批。账号名形如 sr_大区ID。
5.1 查看我的大区
在左侧导航点击「我的大区」,如图 5-1。
查看本大区整体目标、实际、达成率与区域排名。
可切换门店属性与实际值 / 百分比口径。
图 5-1 我的大区
5.2 区域管理
在左侧导航点击「组织管理 - 区域管理」,如图 5-2。
顶部可按大区、区域名称筛选。
图 5-2 区域管理
5.2.1 新增区域
点击右上角「新增区域」。
选择「所属大区」(必填),填写「区域名称」(必填)。
点击「保存」。系统会自动为该区域创建一个运营账号,用户名形如 op_区域ID,初始密码 123456,并提示您。
请把该账号交给对应运营,并提醒其首次登录后修改密码。
5.2.2 编辑或删除区域
点击行内「编辑」可修改区域名称或所属大区。
点击「删除」并确认可删除区域;删除前请确认该区域下已无在营门店。
5.3 门店与平台管理
大区经理同样可以查看本大区下的门店、平台门店;但新增 / 修改 / 闭店 / 删除 均不立即生效 ,会提交审批,由 BOSS / 管理员终审(操作方法见第四章 4.4、4.5,把「保存」理解为「提交审批」)。
5.4 计划管理
计划管理用于设置本大区各月的目标占比,也就是把年度目标拆分到每个月。
在左侧导航点击「组织管理 - 计划管理」,如图 5-3。
在顶部选择要维护的大区。
表格按财年顺序列出 2 月到次年 1 月,逐月填写目标占比。
点击「保存」。大区经理保存的计划需要审批,提交后到审批中心等待 BOSS 或管理员确认;确认通过后自动生效。
图 5-3 计划管理
5.5 用户管理
在左侧导航点击「组织管理 - 用户管理」,如图 5-4。
大区经理只能管理本大区下的运营账号;新增 / 修改 / 删除均不立即生效 ,提交审批后由 BOSS / 管理员终审。
图 5-4 用户管理(仅本大区运营)
5.5.1 新增用户
点击「新增用户」。
填写「用户名」(必填,创建后不可修改)、「密码」(初始密码)、「姓名」。
选择「角色」(大区经理通常选择运营)。
如角色为运营,选择其「区域」(限本大区)。
点击「保存」后不立即生效 ,提交审批由 BOSS / 管理员终审。
5.5.2 编辑、停用、删除
「编辑」:可修改姓名、角色、绑定区域 / 大区;密码留空表示不修改。提交审批 。
「启用 / 停用」:停用后该账号无法登录,数据保留,可随时重新启用。提交审批 。
「删除」:提交审批 ,由 BOSS / 管理员终审,删除后账号不可恢复。
5.6 审批中心
审批中心用于处理下级提交的申请。大区经理主要处理本大区运营提交的申请。
在左侧导航点击「审批中心」,如图 5-5。
切换到「待我审批」页签,查看本大区待办申请(状态配色:待审批=橙、已通过=绿、已驳回=红、已撤回=灰)。
点击「详情」,弹出与「新增 / 修改」表单一致的内容,可直接「通过 / 驳回」;点空白区域关闭。同一目标同时只允许一张待审单。
运营提交的申请:大区经理通过后转 BOSS / 管理员终审 ;驳回即终止。
切换到「我提交的」页签,可查看自己提交的申请状态,必要时点击「撤回」。
图 5-5 审批中心
5.7 导出
区域管理、门店管理、平台管理页面均有「导出」按钮,按当前筛选与排序导出 Excel,存放于服务器 export/big_region、export/region、export/store、export/plat 对应的年-月目录下。
第六章 BOSS
BOSS 面向全局,账号名形如 boss001。除主面板、门店每日数据、汇总看板、门店管理、平台管理外,还能看到全部大区、区域、计划、用户管理,并可处理大区经理提交的审批。
6.1 全局视图
登录后默认进入「主面板」,可查看全国整体情况,如图 6-1。
可通过顶部筛选切换大区、区域、时间范围。
汇总看板、门店每日数据、门店与平台管理的用法与前面章节一致。
图 6-1 BOSS 主面板
6.2 组织管理
大区管理:可新增、编辑全部大区;直接生效 (无需审批)。
区域管理:可新增、编辑全部区域;直接生效 。
计划管理:可维护全部大区的月度目标;直接生效 。
用户管理:可创建运营与大区经理账号,并可维护其区域 / 大区归属;直接生效 。
6.3 审批
在左侧导航点击「审批中心」,如图 6-2。
处理全部待审申请(大区经理与运营提交的):通过后自动执行、驳回即终止;也可对运营提交的单提前终审 (跳过第一级)。
可查看全部大区待审单(不受范围限制)。
图 6-2 BOSS 审批中心
6.4 关于提权
BOSS 不能自行提升自己的权限;如需更高级别的能力,请联系管理员。BOSS 可以审批运营升大区经理的申请。
第七章 管理员
管理员拥有系统全部权限,账号 admin。除前面章节的所有功能外,还有用户管理、系统配置、每日数据上传、操作日志、报表下载,并且其组织管理操作直接生效、无需审批。
7.1 用户管理
在左侧导航点击「管理 - 用户管理」,如图 7-1。
页面列出所有账号,包含用户名、姓名、角色、绑定的区域 / 大区、启用状态。
顶部可按关键词筛选。
图 7-1 用户管理
7.1.1 新增用户
点击「新增用户」。
填写「用户名」(必填,创建后不可修改)、「密码」(初始密码,如不填系统会用默认值)、「姓名」。
选择「角色」(游客 / 运营 / 大区经理 / BOSS / 管理员)。
若角色为运营,选择其「区域」;若为大区经理,选择「大区」。
点击「保存」。
7.1.2 编辑、启用 / 停用、删除
「编辑」:修改姓名、角色、绑定区域 / 大区;「密码」留空表示不修改,填写则重置为新密码。
「启用 / 停用」:停用后该账号无法登录,但数据保留,可随时重新启用;用于离职或临时封停。
「删除」:删除账号不可恢复,请谨慎。
7.1.3 重置密码
找到目标用户,点击「编辑」。
在「密码」输入框填写新密码(留空则不修改)。
点击「保存」;随后把新密码告知该用户,并提醒其登录后自行修改。
7.1.4 回填账号
当已有区域 / 大区但缺少对应的运营 / 大区经理账号时,可使用「回填账号」:系统会按现有区域和大区补建账号,用户名形如 op_区域ID、sr_大区ID,初始密码 123456。
7.2 系统配置
在左侧导航点击「管理 - 系统配置」,如图 7-2。
列表会维护全部参数,常用包括:低分阈值、收入下滑阈值、低单均、GMV 权重、杭州店特例、淘宝闪购 CRM 年度目标 等;代码内置的默认值即使尚未写入数据库也会一并列出 (配置键后带灰色「默认 」标签),显示的就是当前生效值,点「保存」即写入数据库。
修改后点击「保存」。
注意:部分配置保存后需要重启对应服务才会生效,页面会有相应提示;重启方法见 7.8。
淘宝闪购 CRM 年度目标 (配置键 crm.yearly_aim):按「CRM 周期年度」(以 9 月 10 日 为界,2026 表示 2026-09-10 ~ 2027-09-10)配置每年的目标值与起止日期,例如 {"2025":{"aim":1080,"start":"2025-09-10","end":"2026-09-10"},"2026":{"aim":980,"start":"2026-09-10","end":"2027-09-10"}}。审批通过时按当时 配置写入目标,之后修改配置不会改变已生效的记录。详见 8.13。
图 7-2 系统配置
7.3 每日数据上传
上传是数据进入系统的第一步,分为「上传文件、比对差异、执行入库」三个阶段。务必记住:只上传文件不会立即改变看板数据,还需要执行一次「数据处理入库」。
在左侧导航点击「管理 - 每日数据上传」,如图 7-3。
页面按功能分为几个区域:单日上传、按时间范围上传、推广数据上传(按日期范围) 、数据处理入库、飞书表格同步(含系统初始化)。
图 7-3 每日数据上传
7.3.1 单日上传
选择数据所属日期。
选择数据类型(如美团 / 淘宝闪购 / 京东的 data、pin、remark、score 等)。
选择对应的本地文件。
点击上传,等待提示成功;如有格式或表头问题,卡片上会显示失败原因。
7.3.2 按时间范围上传
适合一次性补录多天数据。
选择一个日期范围,注意单次范围不超过 60 天。
选择数据类型并添加一个或多个文件。
点击「开始处理」。系统把文件按天/平台与数据库 operation_data 逐条对比:按「日期 + 平台 + 平台id」对齐;库里有、文件没有 → 不管 ;文件有、库里没有 → 提示「新增」 ;两边都有 → 只显示有差异的字段与值 ;且只比较该类型能提供的库字段 (如 mt_pin → 拼好饭收入/单量)。美团 :本次改动了「合计收入」或「拼好饭收入」时,系统会自动补上派生列 ——外卖收入 = 合计收入 − 拼好饭收入、外卖单量 = 有效订单 − 拼好饭单量,并在差异表里一并列出;勾选入库时一起写入,保证「外卖 + 拼好饭 = 合计」始终自洽。
页面表格按「日期 / 平台 / 平台id」一行、带勾选框,并生成差异报告 Excel 到 data/export/change/年-月/ 目录。
「开始处理」不改数据库 ;勾选要应用的行后点「入库」,仅把勾选行 的差异字段写入 operation_data(新增则插入),不删除、不覆盖原始文件 。
淘宝闪购 CRM 周期账单(tb_crm)走「直接入库」通道 (没有差异预览):系统按每行「账单日期」入库到 CRM 日表(tb_crm_daily_date_年_月,键 = 门店id + 账单日期),按所选范围过滤,并按账单日期把原始文件另存 raw/tb/<日期>/crm.xlsx;同一「门店id + 日期」只比较代运营收入——相同跳过、不同更新、没有新增 ,重复上传幂等。CRM 类型允许一次选多份账单 (一天一份)。
7.3.3 推广数据上传(按日期范围)
用于把门店推广花费 (推广消费、曝光提升、进店/订单提升等)入库。推广数据独立于运营数据,存放在按月分表 的 promo_data_年_月 中(与 operation_data 同构:每个自然月一张表,入库时自动建表)。
在「推广数据上传(按日期范围)」板块选择日期范围;文件里超出范围的天会被忽略。
选择推广数据类型并添加文件(每类一个文件):
美团门店推广 :美团「效果数据」导出,工作表「效果数据」,第 1 行为表头;
淘宝闪购门店推广 :淘宝闪购「门店维度分日期」导出,工作表「Sheet1」,第 1 行为表头。
工作表名不符时系统会退回读取第一个工作表。
点击「开始处理」:系统把文件按天拆分,与 promo_data 对应月份分表逐行对比 ,只显示有差异的字段 ,并生成差异报告 data/export/promo/年-月/promo_*.xlsx。
勾选要应用的行后点「入库」:只把勾选行 写入对应月份分表(表不存在则自动创建),只增改、不删除 ;同一批数据重复上传不会产生重复行。
点「导出」:按所选日期范围导出推广明细 Excel,并自动关联门店档案 ,带出 大区 / 区域 / 门店ID / 门店名称 / 省份 / 城市 / 区县 ;关联不到门店的行照常导出(门店列留空)。
对比粒度(唯一键):日期 + 平台 + 门店ID + 计划ID + 推广产品 + 营销场景 + 投放渠道 + 资金类型。
表 7-5 推广数据上传文件表头规则
数据类型
名称
文件格式
读取设置
必填列(原始表头名)
mt_promo
美团门店推广
XLSX
工作表「效果数据」,第 1 行为表头
日期、门店ID、门店名称、推广产品、投放系统、资金类型、营销场景、推广消费实付(元)、曝光提升数(次)、访问提升数(次) 等
tb_promo
淘宝闪购门店推广
XLSX
工作表「Sheet1」,第 1 行为表头
日期、门店ID、门店名称、计划ID、推广产品、资金来源、计划归属、推广消费(元)、曝光提升数、进店提升数、订单提升数、订单交易额(元) 等
7.3.4 肉片采购数据上传(按时间范围)
用于把肉片(调理牛肉片 / 调理鸡肉片)的采购明细 入库到独立表 fillet_data(与运营数据 operation_data_*、推广数据 promo_data_* 分开存放),供「采购额 · 采销比」页的下载肉片采购汇总 使用。
在「肉片采购数据上传」板块选择日期范围(按 支付时间 过滤,范围外的行忽略)。
选择文件:拼拼云导出的肉片采购明细 (24 列)或消耗量 (36 列)都可以,支持 .xlsx / .xls / .csv。
点「开始处理」:后端解析文件 → 用「收货人」关联拼拼云门店 → 直接幂等入库 (缺表自动创建)。
结果区显示:范围内行数、新增行数、表内合计、关联门店行数、未匹配收货人、月份分布,以及原始文件另存路径 data/raw/fillet/<开始>_<结束>/。
去重键 :支付时间 + 收货人 + 商品名称 + 订货数量 + 退货数量 + 金额(src_key 唯一索引)——同一笔采购在不同文件、不同批次里重复上传只会保留一行 ,不会重复计数。
件数口径 :实际数量(= 订货数量 − 退货数量)。
7.3.5 数据处理入库
在「数据处理入库」区域选择需要入库的日期(可先入库一天做验证)。
点击「执行数据处理入库」。
系统会清洗并合并当天数据,写入运营库;成功后再查看板 / 明细即可看到新数据。
若结果异常,请先检查上传文件与差异报告,再重新执行。
7.3.6 上传文件表头规则(重要)
每日上传的数据文件必须来自平台导出,且表头名与下表一致,系统才能正确识别。上传前请先用 Excel 打开文件确认表头。
通用规则
表头名必须与平台导出口径一致;系统会先去掉表头中的空格和不可见字符再匹配,因此列名带尾随空格也能识别。
列的顺序不限;系统只读取需要的列,未列出的列会被忽略。
每一行都必须有门店 id(门店id、门店编号、外卖门店ID、到家门店ID 等);没有 id 的行会被丢弃。
日期列会被自动归一化,支持 20260908、2026/09/08、2026-09-08 19:14:32、2026/09/08-2026/09/08 等写法;单日上传只会保留与所选日期相同的行。
比例类字段支持百分号或小数(例如 12% 与 0.12 等价);"-"、NaN 等按各类型规则填 0。
差评类文件用于统计差评数:美团差评只统计综合评分、商品评分、口味评分、包装评分中任意一项大于 0 且小于 3 的记录;淘宝闪购、京东差评按评价条数统计。
每种数据类型保存的文件名固定(见下表);同一日期重复上传会覆盖该日该类型的文件。
按时间范围上传要求文件内必须有日期列;京东评分类(jd_score)没有日期列,不能用范围上传,只能单日上传。
平台导出模板会变化:若某个非必需指标列缺失(如京东单店 2026-09-28 起去掉「曝光人数 / 入店转化率(人数) / 下单转化率(人数)」),该指标按 0 处理,不再导致整日/整平台入库失败。
若上传文件实际是 Excel 97-2003 的 .xls(OLE2 格式)而系统按固定名 xxx.xlsx 保存,系统会自动、安全地转成真正的 xlsx 再落盘;转换后逐 sheet 比对名称与行列数,异常则保留原文件不转换。
采购订单备注前缀 (2026-08 起统一):错单:xxx 表示整单不计入,换货:xxx / 退单:xxx 表示该行不计入。 另:补货:xxx 表示该单为补货/重新下单(与换货/退单一样,该行不计入采购额统计 );2026-10-09 已把 2~9 月采购表里 10 行「重新下单 / 米粉发霉补发」备注统一加上 补货: 前缀。
美团(平台代码 mt)
表 7-1 美团上传文件表头规则
数据类型
名称
文件格式
读取设置
必填列(原始表头名)
mt_data
美团外卖商家版
CSV(GBK)
第一行为表头,保存为 data.csv
日期、门店id、营业收入、有效订单、曝光人数、入店转化率、下单转化率、综合体验分
mt_pin
美团拼好饭
CSV(GBK)
第一行为表头,保存为 pin.csv
日期、门店名称、门店id、有效订单、营业收入
mt_sig
美团单店
XLSX
工作表「美团外卖门店明细」,第 2 行为表头,保存为 sig.xlsx
统计日期、外卖门店名称、外卖门店ID、有效订单、收入、曝光人数、入店转化率(人数)、下单转化率(人数)、门店评分/综合体验分(均值)
mt_remark
美团差评
CSV(GBK)
第一行为表头,保存为 remark.csv
日期、门店名称、门店id、总体评分、商品评分、口味评分、包装评分
淘宝闪购(平台代码 tb)
表 7-2 淘宝闪购上传文件表头规则
数据类型
名称
文件格式
读取设置
必填列(原始表头名)
tb_data
淘宝闪购
XLSX
工作表「data」,第 1 行为表头,保存为 data.xlsx
日期、门店名称、门店编号、省份、有效订单、收入、曝光人数、进店转化率、下单转化率、店铺评分
tb_remark
淘宝闪购差评
XLSX
工作表「sheet 1」,第 1 行为表头,保存为 remark.xlsx
创建评价时间、门店ID
京东秒送(平台代码 jd)
表 7-3 京东秒送上传文件表头规则
数据类型
名称
文件格式
读取设置
必填列(原始表头名)
jd_data
京东秒送
XLSX
工作表「数据」,第 1 行为表头,保存为 data.xlsx
日期、门店名称、门店id、城市、有效订单、收入、曝光人数、入店转化率、下单转化率
jd_sig
京东单店
XLSX
工作表「京东外卖门店明细」,第 2 行为表头,保存为 sig.xlsx
统计日期、外卖门店名称、外卖门店ID、有效订单、收入、曝光人数、入店转化率(人数)、下单转化率(人数)
jd_score
京东评分
XLSX
工作表「导出商品评价记录」,第 2 行为表头,保存为 score.xlsx
到家门店ID、门店名称、总体评分
jd_remark
京东差评
XLSX
工作表「导出京东商品评价记录」,第 2 行为表头,保存为 remark.xlsx
评价时间、门店ID
原始表头与系统字段对照
表 7-4 原始表头与系统字段对照
原始表头名
系统字段
含义
日期 / 统计日期 / 创建评价时间 / 评价时间
date
统计日期或评价时间
门店id / 门店编号 / 外卖门店ID / 到家门店ID / 门店ID
id
平台门店 ID
门店名称 / 外卖门店名称
name
门店名称
营业收入 / 收入
income
营业收入
有效订单
amount
有效订单量
曝光人数
exposure
曝光人数
进店人数 / 入店人数
entry_num
进店/入店人数(美团、京东取「入店人数」,淘宝闪购取「进店人数」;源文件缺该列时按 ceil(有效订单 ÷ 下单转化率) 推算)
入店转化率 / 进店转化率 / 入店转化率(人数)
entry_rate
入店转化率
下单转化率 / 下单转化率(人数)
order_rate
下单转化率
综合体验分 / 店铺评分 / 门店评分/综合体验分(均值) / 总体评分
score
门店评分
省份
province
省份
城市
city
城市
提示:若上传后提示表头映射失败,或入库后指标为 0,通常是表头名与平台导出口径不一致;请对照上表核对,或把文件样例发给管理员排查。
7.4 飞书表格同步
飞书同步用于把飞书表格里的门店信息与开业时间同步到系统数据库。
7.4.1 拉取最新飞书表格
点击「拉取最新飞书表格」,系统会从飞书拉取门店信息表、开业时间表并缓存到本地。拉取完成后页面会显示缓存时间与记录数。
7.4.2 同步飞书表格(逐项确认)
点击「同步飞书表格」。
系统会把飞书数据与数据库比对,弹出逐项确认窗口。
待修改项默认全部勾选,可按需取消;删除候选默认不勾选。
如需删除某条数据,请逐项勾选对应的删除候选。
确认后点击执行,系统按勾选结果应用修改与删除,并给出结果统计。
该设计可避免误删,请务必核对后再确认。
7.4.3 系统初始化
用于新环境一键初始化。
点击「系统初始化」。
系统先执行一次飞书层级同步(门店 / 区域 / 大区)。
然后载入 last_year.xlsx 中的 total 与 GMV 数据:按缺失才补的原则,写入大区基数与门店 GMV(门店 GMV 按“月平均值乘 12”计算)。
已在系统中的数据不会被覆盖。
完成后页面会给出同步与载入的统计信息。
7.5 操作日志(审计)
系统在数据库层面对所有数据表的增、删、改自动记录,包含谁在什么时间改了什么。日志表自身不记录。
在左侧导航点击「管理 - 操作日志」,如图 7-4。
可按时间范围、操作类型(新增 / 修改 / 删除)、操作用户、数据表、主键筛选。
列表可展开某一行,查看旧值与新值对比,便于追溯误操作。
日志用于审计与排障,不可修改或删除。
图 7-4 操作日志
图 7-5 操作日志筛选与明细展开
7.6 报表下载(除游客外均可使用)
在左侧导航点击「报表下载」,如图 7-6。
页面上方选择「统计日期」;下方按报表类型分成三块:已生成的日报(近一月) 、已生成的周报(今年) 、已生成的月报(今年) 。三块横向并排 显示,每块列表默认每页 20 条 (可选 20 / 50 / 100,支持翻页与「刷新」)。
生成日报 :点「生成并下载每日日报」,按所选日期生成并直接下载;生成结果同时出现在「已生成的日报」列表里,可再次下载。
生成周报 :点「生成并下载周报」,系统按下述口径生成 8 个页签的 Excel 并下载:
本期 = 本月 1 日 ~ 所选日期;对比期 = 上月 1 日 ~ 上月同日(上月没有该日时取到上月最后一天)。
同店对比 :对比期只统计本期出现过的门店 ,保证两期门店口径一致。
页签共 8 个 :汇总 / 美团 / 淘宝闪购 / 京东 / 美团推广 / 淘宝闪购推广 / 门店明细 / 门店推广明细 ;前 6 页按 全国 → 各大区(含「大区合计」行)→ 各区域 排列,第一列「大区」跨行合并、第二列「区域」;后 2 页为门店级明细 (一行一店,不做跨行合并);第 1 行为标题 + 日期(如 9.1-9.19),第 2 行为字段表头(汇总页与门店明细底色 #d4f4f1、平台/推广页用日报同款平台色)。
汇总页字段 :门店数、营业门店数、总单量、总收入、单均收入、单均差值、上周期单量、上周期收入、单量增长比、收入增长比、GMV目标、GMV达成率、增量GMV目标、新店GMV达成率、店均收入、店均单量。
平台页字段 :外卖收入 / 收入增长率、外卖单量 / 单量增长率、外卖客单 / 客单差值、曝光人数 / 曝光增长率、入店转化率 / 入店增长率、下单转化率 / 下单增长率、差评数、低于阈值门店数、平台占比。
推广页字段 :门店数、推广、推广差值、曝光提升、进店成本。
门店明细(一行一店,按本期收入降序,共 61 列) :仅含**本期收入或单量有值(非空、非 0)**的门店——本期收入与本期单量都为 0(空)的门店不导出、不计入统计 (因此行数与汇总页的「营业门店数」一致)。字段顺序:
维度:大区、区域、门店名称、美团ID、淘宝闪购ID、京东ID、门店属性(存量/增量);
本期合计 :本期单量、本期收入、单均收入、本期曝光人数、本期入店人数、本期入店转化率(=入店÷曝光)、本期下单转化率(=单量÷入店) ;
本期分平台 (美团 / 淘宝闪购 / 京东 各 6 列):收入、单量、曝光人数、入店人数、入店转化率、下单转化率 ;
上期合计 :上期单量、上期收入、上期曝光人数、上期入店人数、上期入店转化率、上期下单转化率 ;
上期分平台 (三平台各 6 列):收入、单量、曝光人数、入店人数、入店转化率、下单转化率 ;
对比与其它:单均差值、单量增长比、收入增长比、差评数、是否营业(本期是否有非零营收/单量)。
即「合计 + 每个平台」都有本期值与对比值 (收入/单量/曝光人数/入店人数/入店转化率/下单转化率),转化率按汇总口径计算;已校验「Σ平台 = 合计」(曝光/入店/单量/收入差均为 0);上期同样同店对齐 。
门店推广明细(一行一店,美团+淘宝闪购合计,按本期推广降序) :仅含本期推广(消费)不为空、非 0 的门店(本期推广为 0 的门店不导出、不计入统计);字段:大区、区域、门店名称、平台ID(有推广记录的平台的平台门店ID)、本期推广、上期推广、推广差值、曝光提升、进店提升、进店成本(本期推广 ÷ 进店提升);上期推广同样同店对齐 。
口径要点 :门店数 = 未闭店 + 有关联平台的门店(排除学校店);营业门店 = 周期内至少 1 天营收/单量不为 0;店均收入/店均单量分母都用营业门店数 ;增长率/转化增长率 = (本期−上期)÷上期,客单/单均/推广用差值 ;入店转化率 = 入店人数汇总 ÷ 曝光汇总(入店人数取运营数据新字段 entry_num);GMV目标全国/大区取 GMV 服务月度目标(与「月度详细」页一致),区域按各区域门店目标占比分摊(Σ区域 = 大区、Σ大区 = 全国),达成率 = 周期内收入 ÷ 整月目标;低于阈值门店数 = 周期内门店平均分(只统计非 0 评分)> 0 且低于阈值 的门店数(美团 4.7 / 淘宝闪购 4.8 / 京东 4.8,可在「系统配置」调整)。
列表中「统计日期」显示统计当日 (周报即本期截止日)。
该菜单除游客外所有角色均可使用 ;「门店每日数据」页的「导出」按当前用户范围(运营=本区域、大区经理=本大区)导出。
图 7-6 报表下载
7.7 导出
大区、区域、门店、平台四个管理页面均有「导出」按钮,按当前筛选与排序生成 Excel,保存到服务器 export/big_region、export/region、export/store、export/plat 的年-月目录,同时浏览器自动下载,如图 7-7。
图 7-7 大区管理导出
7.8 部署与运维
系统以 Docker 容器方式部署在云服务器:公网入口 https://douxi.sdydcq.com ,由宿主机 nginx 把 443 反代到前端 8080、网关 8081、文档 8090。
重新构建并启动某个服务后,查看容器状态与日志确认是否正常。
数据备份:数据库数据卷 pgdata,以及数据目录 data。
修改数据库初始化脚本后,需要重新初始化或手动应用。
详细的离线部署、文档服务部署与常用运维命令见附录 A。
第八章 功能详解
本章按页面逐个说明功能与关键操作,可作为速查手册使用。
8.1 主面板
展示关键指标卡片(月度 GMV、目标、完成率等)、月度累计进度趋势图、区域排名与平台分布。默认每 30 秒刷新,可切换实际值 / 百分比。
图 8-1 主面板
8.2 年度详细 / 月度详细 / 门店详细
年度详细:按财年查看全年目标、实际、达成率与存量 / 增量拆分,如图 8-2。
月度详细:按月查看目标与实际,支持切换月份与口径,如图 8-3。
门店详细:按门店维度查看目标与实际,如图 8-4。
图 8-2 年度详细
图 8-3 月度详细
图 8-4 门店详细
8.3 汇总看板(大区 / 区域)
按大区或区域聚合的年度 / 月度 / 每日视图,支持门店属性与实际值 / 百分比切换。
图 8-5 大区汇总看板
图 8-6 区域汇总看板
8.4 门店每日数据
按日期与区域筛选的门店明细,支持排序与分页。注意只显示营业中且能匹配平台 ID 的门店。
图 8-7 门店每日数据(支持表头排序)
8.5 门店管理
主表列:门店ID、门店名称、大区、所属运营、省份、城市、督导 、属性、状态、门店GMV、月GMV、月营收、操作。
顶部可按大区、区域、名称、营业状态、门店属性、督导 筛选;「GMV月份」下拉可切换月份,GMV 与营收列随之变化。
督导 在新增/编辑门店时为下拉选择,选项按「所选区域 → 大区」过滤;督导姓名在「督导管理」里维护,见 8.7。
支持排序、批量删除、导出。
点击 GMV 数值可打开明细弹窗,见 8.8。
申请淘宝闪购 CRM :门店已关联淘宝闪购平台门店(平台管理中存在 tb 平台门店)时,操作栏会多出「申请 」按钮;点击后填写开始日期、CRM 扣点(%)与备注并提交,按现行审批链路审批,通过后 写入 CRM 目标,详见 8.13。
图 8-8 门店管理(GMV / 月GMV / 月营收列)
8.6 平台管理
维护门店与美团 / 淘宝闪购 / 京东平台门店 ID 的映射,支持筛选、闭店 / 重新开业、导出。
图 8-9 平台管理(平台门店映射)
8.7 督导管理 / 区域管理 / 大区管理 / 计划管理
督导管理 (大区经理及以上,左侧「组织管理(高粒度) → 督导管理」):维护督导记录——督导姓名 + 所属大区(n:1)+ 备注 ,列表显示每个督导名下的门店数 ,支持按大区/姓名筛选、导出、批量删除;同一大区内督导姓名唯一 (允许跨大区同名),名下有门店的督导不允许删除 。大区经理只能维护本大区 的督导(服务端校验)。门店在弹出的下拉里选督导。
数据初始化时,系统已按历史「督导姓名 + 门店大区」自动生成督导记录(同名同大区只生成一条),并把门店关联到对应督导。
区域管理:维护区域及其所属大区。
大区管理:维护大区名称、GMV 月度基数、红线 GMV、采销比、存量 GMV、红线关店数等;大区经理改动提交审批,BOSS / 管理员直接生效 。
计划管理:维护各月目标占比,财年为 2 月到次年 1 月,如图 8-10。
图 8-10 计划管理(各月目标占比)
8.8 门店 GMV 明细弹窗
点击门店管理里的 GMV 数值打开,如图 8-11、图 8-12。
顶部两张卡片:门店年 GMV(左)与门店年度营收(右)。
月次表(2 月到次年 1 月):目标、实际营业额、单量、达成率、进度条、美团 / 淘宝闪购 / 京东收入与单量。
达成率等于实际营收除以目标;进度条达到 100% 显示整条绿色,未达则已达部分为蓝色、未达部分为红色。
点击某月行首的展开箭头,可查看该月每日曲线;展开某月会自动收起其他月;仅当月有日收入的行可展开。
展开区左侧为「月 GMV / 每日累计营收」对照,右侧为「三平台每日进度」。
图 8-11 门店 GMV 明细弹窗
图 8-12 GMV 明细(管理员视角)
8.9 报表中心
选择统计日期后按类型生成并下载 Excel,见 7.6:
每日日报 :单日 vs 前一日;
周报 :本期(本月 1 日 ~ 所选日期)vs 对比期(上月同期),对比期门店与本期同店对齐 ;共 8 个页签(汇总 / 美团 / 淘宝闪购 / 京东 / 美团推广 / 淘宝闪购推广 / 门店明细 / 门店推广明细);
三个列表(日报 / 周报 / 月报)横向并排 ,默认每页 20 条 分页,「统计日期」显示统计当日。
8.10 审批中心
除游客外所有角色可见:大区经理 / BOSS / admin 看「待我审批」,运营看「我的审批进度」。可通过、驳回、撤回;详情弹窗显示与新增/修改一致的字段;通过后系统自动执行,见 5.6 与「审批流程」页。
8.11 我的运营范围
运营显示「我的区域」,大区经理显示「我的大区」。
CRM 最近达标显著提示 :页面顶部会醒目展示最近 7 天 内完成淘宝闪购 CRM 扣点目标的门店(运营只看本区域、大区经理只看本大区),绿色提示卡内列出:门店名称、所属区域、淘宝闪购ID、达标日期、当前合计、目标值、差值(红色加粗)与 CRM 扣点,右侧「查看 CRM 详情」直达「淘宝闪购CRM扣点」页。
达标 = 「当前合计 − 目标值 > 0」,达标日期 即该差值首次转正 的当天(对应 CRM 页的「结束日期」)。
该提示不受 CRM 页「达标 3 天后隐藏」规则限制:已从 CRM 列表隐藏的近期达标记录,仍会在此提示。
最近 7 天无门店达标时不显示 该卡片;时间窗口由接口 /crm/achieved?days=N 控制(页面固定 7 天)。
CRM 预告(接近达标 / 进度领先) :紧随其后是一张橙色预告卡 ,列出「我的区域 / 我的大区」内未达标 门店中完成率最高 的 5 家,用进度条展示:
完成率 = 当前合计 ÷ 目标值;达到 80% (默认阈值)标记为「接近达标 」(橙色深底标签),其余标为「进度领先 」,并显示「还差」金额。
若已有 ≥80% 的门店,卡片标题为「完成率 ≥ 80% 的门店 N 家(接近达标)」;若暂无,则提示「暂无门店达到 80%,以下为进度领先门店」。
已达标门店由上方绿色卡负责,此处不重复 ;接口 /crm/near?ratio=0.8&limit=5(阈值/条数可调)。
8.12 个人中心
可修改姓名、修改密码、提交提权申请、注销账号,如图 8-13、图 8-14。
图 8-13 个人中心
图 8-14 个人中心(运营)
8.13 淘宝闪购 CRM 扣点
面向「淘宝闪购 CRM 代运营扣点」的目标达成跟踪:运营及以上角色在左侧导航点击「淘宝闪购CRM扣点 」进入。
列表字段 :大区、区域、门店ID、门店名、淘宝闪购ID、开始日期、前7日当日 … 昨天当日 (7 列)、当前合计 、目标值 、差值 、CRM扣点、结束日期。
口径说明 :
数据基准日 = 库内最新一天 CRM 数据(通常为昨天);7 列由基准日往前推 7 天逐日展示,缺失的天按 0 计。
当前合计 = 该门店从开始日期 起至基准日的「代运营收入」累计(上限为该 CRM 周期结束)。
目标值 = 该门店所在 CRM 周期 的年度目标;CRM 周期以 9 月 10 日 为界(如 2026 周期 = 2026-09-10 ~ 2027-09-10);申请的开始日期为 9 月 9 日 时归入当期(9/9 起算,周期起止仍按配置),用于把周期开始前的零星收入一并计入。
差值 = 当前合计 − 目标值 ;列表默认按差值降序 ,差值 > 0(已达成)的行高亮 ;达成后 3 天 (结束日期 + 3 < 当天)该行自动隐藏。
结束日期 = 该门店「累计 − 目标」首次大于 0 的日期,由系统随每日数据自动重算。
CRM扣点 :申请时填写,仅作记录展示,不参与上述计算。
筛选 / 搜索 / 导出 :顶部可按大区、区域筛选,按 门店ID / 门店名 / 淘宝闪购ID 搜索,「导出」按当前筛选条件导出 Excel(crm_overview_<数据基准日>.xlsx,工作表「CRM扣点关注」):
7 个日列 与页面一致逐日导出,列标题只显示日期 (2026-09-14 … 2026-09-20,即「前7日当日…昨天当日」对应的日期);
CRM扣点 为百分数格式 (Excel 单元格格式 0.0%,如 1.0% / 0.5%),金额/数量列为两位小数(#,##0.00);
所有列自适应列宽 ,数字列(日数据、当前合计、目标值、差值、扣点及两个ID列)居中 ,文本列左对齐;表头加粗、浅绿底并冻结首行。
筛选范围提示 :大区 / 区域下拉的括号里是该范围内有 CRM 目标记录 的门店数(如「华南大区(26)」)。若某区域显示(0),选中后列表为空是正常 的——CRM 列表只包含已申请(有目标记录)的门店 ,不是全部门店;列表为空时页面也会给出该提示。运营登录只能看到本区域、大区经理只能看到本大区,选到范围之外同样为空。
周期账单上传 (页面右上):
「选择周期账单」选择淘宝闪购 CRM 周期账单(.xlsx)。
选择「上传日期」,默认昨天 。
点「上传并入库」:系统将文件存到 raw/tb/<上传日期>/crm.xlsx,并按**门店id(淘宝闪购平台门店ID)**匹配系统门店后立即解析入库。
是否写库只看「代运营收入」有没有变 :同一「门店id + 日期 」的数据——代运营收入与库内相同则跳过不写 (计入「未变更 」),不同则更新整行 (「变更」),库内没有则「新增」。因此同一份账单重复上传是幂等的 ,只有真正变动的门店才会写库、刷新 update_time。
上传后页面提示会给出:文件行数 / 新增 / 变更 / 未变更 / 跳过;其中未能匹配到系统门店(plat_info 中 plat_tag='tb')的行会被跳过 ,并列出对应的平台ID。
申请 CRM 目标 (门店管理页):在「门店管理」操作栏点「申请 」,弹窗「申请淘宝闪购CRM系统」中填写开始日期 (必填,默认今天)、CRM扣点(%) (0 ~ 100,精确到 0.1%)与备注,提交后按现行审批链路审批,通过后 才写入 CRM 目标;同一门店的同一 CRM 周期 已有目标时不可重复申请(跨周期可以)。
按时间范围上传 (推荐,多天/多份账单):在「每日数据上传 → 按时间范围上传 」里选数据类型「淘宝闪购CRM周期账单 (tb_crm)」,可一次选多份账单 ,选择日期范围后点「开始处理」——
系统按每行「账单日期 」(缺失时退回「入账日期」,再缺失用范围结束日)入库,并只保留范围内的行;
直接写入 CRM 日表(tb_crm_daily_date_年_月,键 = 门店id + 账单日期),没有差异预览/勾选 ;同一「门店id + 日期」只比较代运营收入——相同跳过、不同更新、没有新增,重复上传幂等 ;
原始文件按账单日期另存 raw/tb/<日期>/crm.xlsx;结果区会显示每份账单的行数/天数与 CRM 的 行 / 新增 / 变更 / 未变更。
年度目标配置 :管理员在「系统配置」维护 crm.yearly_aim(见 7.2)。
图 8-15 淘宝闪购 CRM 扣点
8.14 采购额 · 采销比 与肉片采购汇总
采购额 · 采销比 (左侧「统计 - 采购额」):按年/月 + 督导 / 区域 / 大区分页查看采购额、收入与采销比,大区页另有采购额目标与达成率。采购额 = 白名单商品(product_list.is_static=1)的全部采购数据 (错单整单排除、换货/退单/补货行不计 、退货冲减;不再受「开始统计时间 start_static」影响);营业额(采销比分母)只统计合格门店 :① 统计区间内在营(开店日期 ≤ 区间末 且 闭店日期 > 区间初);② 当月单量不为 0;③ 非学校店;④ 三平台(美团/淘宝闪购/京东)至少开了一家——督导 / 区域 / 大区三个分页口径一致。采销比 = 采购额 ÷ 同月同门店收入。合计行 :金额列为各分页求和;采销比 = 合计采购额 ÷ 合计收入 、达成率 = 合计采购额 ÷ 合计目标 ——都按合计实际值 计算,不是各行百分比的算术平均(例 2026-09 大区页:合计采销比 48.00%、达成率 90.36%;按行平均则分别为 45.86% / 88.40%)。 改动即时生效 :在「商品列表」里取消/勾选 is_static(或改 start_static)后,服务会立即重算所有月度的采购额物化 (约 5 秒),采购额页 / 导出全年采购 / 肉片物品条件随即按新口径呈现。
下载肉片采购汇总 (本页「下载肉片采购汇总」按钮):点一下后端按规则生成 Excel(同时落盘 data/export/fillet/<年>/fillet_data_<月>_<时间戳>.xlsx)并直接下载,含 4 个工作表:
汇总 :大区 × 门店数 / 订货门店数 / 有效采购门店数 / 采购率 / 各月件数,最后一行合计;
门店明细 :每家订货门店的各月件数、两月合计、期间前是否采购过、采购月数、是否首次采购、是否有效;
未匹配门店 :收货人匹配不到门店的行(不计入任何大区);
口径说明 :本次生成使用的期间与口径。
口径:
选中月 M :页面上选择的年/月(默认数据里最新月)。统计按 M + 前月 M-1 两个月的件数计算订货门店数 / 有效采购门店数 ;门店数 / 采购率 按选中月 M;
地区(省份)过滤 :选包含所选 则只看所选省份的门店、选不含所选 则排除所选省份的门店(可多选,不选=全部地区);门店数 / 订货 / 有效 / 明细 都按过滤后的门店统计,导出「口径说明」会写明本次过滤方式与省份列表;
基数 (默认 5):所有单量梯度都不命中 时用基数作为件数阈值;
单量梯度(可多档,自助增删) :每档形如「当月单量 < 上限 → 件数阈值」;按上限升序取第一条命中 的档作为该店适用阈值(当月单量取该店选中月各平台 operation_data.amount 合计)。例如:单量 < 500 → 阈值 1;单量 < 1000 → 阈值 3;都不命中 → 基数 5;
物品条件(可选,可加多条) :每行按顺序「先选规则 (或/与)→ 再选/输入物品 (下拉来自「商品列表」里计入统计的商品)→ 选基准 (以物品为准 / 以肉片为准)→ 填数量阈值 ≥ 与/或 比例阈值 」;物品既可从下拉选择(精确匹配),也可直接输入 %表达式 (SQL LIKE 语义):%A% = 名称含 A、%A = 以 A 结尾、A% = 以 A 开头(不含 % 时按精确匹配);
基准与阈值(每条条件各自选) :以物品为准 → 「物品两月数量 ≥ 数量阈值」且 「比例 ≥ 比例阈值」;以肉片为准 → 「物品两月数量 ≥ 数量阈值」且 「比例 ≤ 比例阈值」;两个阈值可只填一个 (只填哪个就判哪个),都填时必须同时满足 ;比例 = 物品两月数量 ÷ 该店两月肉片件数 ,分母为 0(该店两月没买肉片)时比例那条不成立(数量那条仍可成立);
物品数量口径 :该店在选中月 M 与上一月 M-1 的采购数据 里该物品的数量 = 订单量 − 退货量 − 错单量 (「错单:」开头的行整笔不计);缺采购表的月份按 0(如选 9 月时采购表只到 8 月);
原始条件 = 肉片两月累计 ≥ 该店适用阈值,或 当月首次采购(M 月有采购且 M 之前从未买过肉片);
多个条件按顺序左结合 :(((原始条件) 逻辑1 (物品1)) 逻辑2 (物品2)) …;
逻辑为「或」时,只满足该物品条件(甚至没买肉片)的门店也会被计入;逻辑为「与」时两边必须同时成立;
件数 = 实际数量(订货数量 − 退货数量);表内列 M-1、M 两个月的件数;
门店数 = 当月内的有效门店:开店日期 ≤ 本月末 且(闭店日期为空 或 闭店日期 > 本月初) + 非学校店 + 有外卖平台账号(美团 / 淘宝闪购 / 京东任一)+ 当月营收与单量同时不为 0 (取自 operation_data_<年>_<月>,按平台账号关联门店后求和;任一为 0 都不计入);本月前就关店的、本月后才开业的 、学校店、没上外卖的店、当月没有营收或没有单量的店都不计入 ;
订货门店数 = 选中月 M 的有效门店中,M-1 或 M 两月内有肉片采购 的门店数;
有效采购门店 = 两月累计件数 ≥ 基数 ,或 首次采购(该店在 M 之前 的全部历史都没有肉片采购记录——如 M=9 月就看 2~8 月——且 M 月有采购);以前买过、中途暂停、M 月又买的不算首次 ,必须两月累计 ≥ 基数;
采购率 = 有效采购门店数 ÷ 门店数(分母为选中月 M 口径);
门店明细 列出选中月 M 的全部有效门店 (= 门店数口径,含没有任何数据、件数记 0 的门店),列出 M-1 / M 件数、两月合计、「两月≥基数」「M 是否采购」「M 前是否采购过」「是否首次采购」「是否有效」;
下载按钮 :点「下载肉片采购汇总」弹出参数窗——基数 / 地区过滤(包含或不含所选省份)/ 单量梯度(可加多档)/ 规则(或·与)/ 物品 / 物品数量阈值 ,全部默认填入上次输入的值,可先点「预览」看数字,确认后按页面选中的年/月生成并下载;导出「门店明细」在启用物品条件时会多出「物品数量 / 物品达标」两列;
收货人匹配不到门店的,不计入任何大区,单列在「未匹配门店」。
第九章 数据口径与名词
9.1 关键名词
表 9-1 常用名词解释
名词
含义
存量门店
开店较早、属于已有基础的门店
增量门店
开店较晚、属于新增的门店
财年
每年 2 月到次年 1 月
默认昨天
为避开当天数据不完整,默认统计到昨天
实际营收
门店真实收入合计,来自每日上传并入库的数据
GMV 目标
管理期望值,分存量 / 增量,按财年拆到每月
达成率
实际营收除以目标
入店人数
统计周期内进店的人数(entry_num);平台页的「入店转化率 = 入店人数汇总 ÷ 曝光汇总」
平台
美团、淘宝闪购、京东
平台 ID
平台给门店的编号,用于把平台数据对应到系统门店
逻辑删除
删除只打标记,历史仍可追溯
9.2 计算口径
存量与增量按开店时间划分;看板的门店属性可切换全量 / 存量 / 增量,实际值与目标值同步切换。
月度合计按门店营业窗口累计:开店当天算,闭店当天不算。
增量目标的基数来自大区的 increase_base,并按平台权重分摊。
9.3 为什么明细与汇总数字对不上
门店每日数据是明细,只包含营业中且能匹配平台 ID 的门店;看板月度合计按营业窗口累计。两者统计范围不同,数字存在差异属于正常现象。先确认口径(全量 / 存量 / 增量、时间范围),再核对数据是否已入库。
第十章 常见问题(FAQ)
看不到某个菜单?菜单按角色显示,请申请提权或联系管理员。
登录后频繁掉线?登录状态保存在浏览器本地,请检查是否禁用了本地存储或使用了无痕模式。
主面板没有更新?默认每 30 秒自动刷新,也可切换筛选触发;先确认数据是否已上传并入库。
门店每日数据查不到某家店?该页只显示营业中且能匹配平台 ID 的门店,已闭店门店请看汇总看板。
上传后看板仍无数据?上传只是第一步,还需要在「数据处理入库」选择日期执行入库。
上传失败怎么办?检查文件格式与表头是否符合平台导出要求,查看卡片上的失败原因。
飞书同步会误删数据吗?不会。删除候选默认不勾选,必须逐项勾选确认后才会删除。
改了系统配置为什么不生效?部分配置需要重启对应服务,见 7.8。
审批多久能通过?由对应上级处理:运营提交经大区经理 → BOSS/管理员终审;大区经理提交给 BOSS/管理员;提权提交给 BOSS/管理员。可在「审批中心 → 我的审批进度」查看状态,未完成前可撤回。
运营新增 / 修改门店后为什么没有立即生效?运营与大区经理对门店 / 平台 / 用户的改动都走审批,不立即生效;到「审批中心」查看进度,上级审核通过后自动生效。
忘记密码怎么办?联系管理员在用户管理中重置,见 7.1.3。
新建区域 / 大区后账号从哪来?系统自动创建:区域生成 op_区域ID,大区生成 sr_大区ID,初始密码 123456。
导出文件保存在哪里?服务器 export 目录下对应类型的年-月文件夹,同时浏览器已自动下载。
系统地址是什么?前端 https://douxi.sdydcq.com (接口经同域 /api 代理),接口网关 https://api.sdydcq.com ,用户手册 https://manual.sdydcq.com 。
外网穿透地址打不开怎么办?按 附录 E 的顺序自查:① 控制台映射开关为「生效」;② 服务器上只能运行一个花生壳客户端 (官方客户端 phddns_service 与 AppKey 模式的 hsk.service 不能同时开,否则互相抢转发,诊断会报「花生壳客户端连接花生壳转发服务器失败」);③ 用手机流量而不是服务器同网段的电脑测试(NAT 回环);④ 在控制台点「映射诊断」四项全绿即为正常。
附录 A 离线部署(运维 / 管理员)
A.1 准备
准备一台 Debian 或 Ubuntu 服务器,建议 4 核 8G 以上。
准备离线发布包 docker_bundle,内含镜像包、数据库数据卷、数据目录与部署脚本。
将发布包拷贝到服务器用户目录,例如 /home/douxi/docker_bundle。
A.2 一键部署
进入发布包目录,执行校验:sha256sum -c SHA256SUMS ,确认全部 OK。
执行部署脚本:sudo bash load_and_run.sh 。
若服务器尚未安装 Docker,脚本会自动安装并启动 Docker 服务。
脚本会加载镜像、恢复数据库与数据目录,并启动全部容器。
执行 docker compose ps 确认所有容器状态为 healthy。
浏览器访问 https://douxi.sdydcq.com ,使用管理员账号登录。
A.3 文档服务
本用户手册以 HTML 形式发布,运行在独立的文档容器中(容器端口 8090),公网地址 https://manual.sdydcq.com ,局域网备用 http://192.168.0.128:8090 。更新手册后,覆盖容器挂载目录即可;地址与排障见 附录 E 。
A.4 常用运维命令
表 A-1 常用命令
目的
命令
查看容器状态
docker compose ps
查看某服务日志
docker compose logs -f gateway
重启某服务
docker compose up -d --no-deps gateway
停止全部服务
docker compose down
查看数据卷
docker volume ls
附录 B 保持服务器长期开机(笔记本)
若服务器是一台笔记本,为避免熄屏或合盖导致挂起、关机,建议:
systemd-logind 忽略合盖、挂起键、电源键,空闲不动作。
屏蔽 sleep、suspend、hibernate、hybrid-sleep 等目标。
XFCE 电源管理设置为从不休眠、合盖不动作。
配置脚本见服务器上的 /home/douxi/_nosleep.sh 。
附录 C:修复日志(变更记录)
本节按日期记录系统的修复与变更,便于运维与用户追溯。
2026-09-16
修改
一、日报导出 · bug 修复
大区、区域表「美团外卖收入」「美团外卖单量」恒为 0。原因:生成代码写入的键名 mt_income / mt_amount 与表头列名 mt_income_out / mt_amount_out 不一致,取数时被补 0;修复:改为与表头列名对应的键。
大区、区域表「淘宝闪购客单价」「京东客单价」恒为 0。原因:写入键为 tb_unit_price_out / jd_unit_price_out,而表头列为 tb_unit_price / jd_unit_price;修复:改为与表头列名对应的键。
「门店数」口径偏大。原因:取的是 store_info 全部门店;修复:改为仅统计至少有一条平台映射(plat_info)的店铺。
增长率、转化率、平台占比显示为小数。原因:底层为 0~1 数值且未套用格式;修复:上述列套用 Excel 百分号格式(0.00%),底层数值不变,不影响计算。
门店明细、全国各门店简表缺少合计。修复:表尾新增 A 列名为「总计」的汇总行,可累加列求和,单价列按合计重算。
二、数据入库 · bug 修复
门店明细「京东评分」恒为 0。原因:合并时按字符串比较平台门店 ID,门店表的「门店id」为整数,评分的「到家门店ID」因含空行被读成浮点(多出 .0),始终匹配不上;修复:新增平台门店 ID 归一化,统一为不带小数点的字符串,并修正评分列类型。
处理结果:2026-09-15 已重算,门店明细京东评分非空 316 / 370,均值 3.904;此后新入库日期自动正确;如需回补 2026-09-15 之前的历史日期,可逐日重算。
三、新增功能
每日运营数据导出:运营可导出本区域、大区经理可导出本大区、BOSS/管理员可指定区域或大区;入口为「门店每日数据」页面的导出按钮;存放路径 export/daily///daily_op__.xlsx;单日返回 xlsx,多日返回 zip。
日报排序页:门店明细之后新增「按单量排序」「按营收排序」两个页,内容与门店明细完全一致,分别按「总单量」「总收入」降序,序号重排,末尾保留「总计」行。
门店管理 GMV 明细图表悬浮提示:两张展开图增加自定义 tooltip——左图(月GMV/每日累计营收)显示当前目标、当前日收入、当前累计收入、当前日目标完成率;右图(三平台每日进度)显示三平台分别收入(含累计与合计)。修复:EChart 组件此前用 ref 保存 ECharts 实例,被 Vue 包成响应式代理,导致悬浮无反应;已改为 shallowRef。
四、同步与配置
存量门店闭店日期:修复前存量门店闭店只写入状态、闭店日期为空;修复后存量门店仅忽略开业日期,闭店日期正常写入(2026-09-15 已验证)。
特殊平台注册表:新增「抖喜(济宁万达店)」tb 1342356044、mt 33315214、jd 23685638 三条特例平台,并把原属秀水店的对应平台移入该店;现役注册表为后台配置文件 special_plats.json(内置默认值同步更新)。
五、端口调整
前端保持 8080;网关由 8000 调整为 8081;微服务由 8010/8020/8030/8040/8050/8060 调整为 8082/8083/8084/8085/8086/8087。仅前端(8080)与网关(8081)对外,其余微服务仅容器内网;postgres(宿主 5433)与文档服务(8090)保持不变。同步更新了 docker-compose、各服务 Dockerfile、跨服务调用地址、网关路由与前端 nginx 代理。
六、日报格式(全国各门店简表)
第 1 行为合并单元格标题「抖喜{月}.{日}全国门店数据」(M.D 即报告月.日,如「抖喜9.15全国门店数据」);第 2-3 行为两行表头。
A-I 列(序号/省份/门店名称/总单量/总收入/前日单量/前日收入/单量增长率/收入增长率)纵向合并两行。
平台列按平台分组合并:美团 J-M、淘宝闪购 N-O、京东 P-Q;第一行显示平台名,第二行显示各子项。
平台表头填充:美团 #FFF2CC(淡黄)、淘宝闪购 #DAE3F5、京东 #EF949E。
单量增长率、收入增长率两列使用 Excel 数据条,量程固定为 -100%~+100%、0 居中:正值在 0 右侧(蓝,越向右越大)、负值在 0 左侧(红,越小越向左),±100% 封顶。(修复:x14 扩展此前被误插入 cfRule,Excel 回退为最左侧数据条;现改为写入 worksheet 级 extLst。)
数据行按「总单量 → 总收入 → 前日单量 → 前日收入」降序排列(多键,依次比较),序号重排为 1..N;「总计」行仍在末尾。
其他页(全国大盘、大区、区域、门店明细、按单量/按营收排序、两张异常明细)的增长率列同样使用上述 0 居中数据条(±100%、正蓝负红)。
所有页的这两个增长率列均按内容自适应列宽。
含合计行的页(门店明细、按单量/按营收排序、全国各门店简表):「总计」行整行红色加粗 ;其中非累加列(单均收入、各平台客单价、单量/收入增长比、各平台进店/下单转化率与评分)按合计结果算出。
全国/大区/区域三张表:「门店数」= 门店主数据中 closed=0 且已匹配平台的店铺;「营业门店数」= 门店数中当日总营收或总单量不为 0 的店铺。
七、飞书 ID 信息表 · 省份字段
飞书「ID 信息表」新增 D 列「省份」,原 D 列(店铺名称)起整体右移:A大区 / B运营 / C督导 / D省份 / E店铺名称 / F拼拼云门店名称 / G是否监管(预留) / H美团ID…… / S备注;同步读取范围由 R 列扩展到 S 列。
同步解析新增「省份」:飞书省份有值时写入门店的「省」字段,为空时跳过、不覆盖库内已有值(重复同步幂等)。2026-09-15 缓存验证:455 条门店记录,454 条省份有值并成功入库。
全国各门店简表在 B 列「区域」与 C 列「门店名称」之间新增 C 列「省份」,原列整体右移(见「六、日报格式」更新后的 A-J 合并与 K-N / O-P / Q-R 平台分组)。
八、前端 · 门店管理 GMV 明细图表悬浮提示
现象:门店管理页点击 GMV 数值弹出「门店GMV明细」,展开某月后两张图表(月GMV/每日累计营收、三平台每日进度)的鼠标悬浮提示有时显示、有时不显示。
原因:EChart 组件只在窗口 resize 时调用 chart.resize();图表挂载在弹窗/表格展开动画期间,容器尺寸在挂载后仍会变化(展开动画、flex 布局),ECharts 内部画布尺寸与实际不符,导致坐标命中失效;同时提示框默认渲染在图表容器内,会被表格滚动区的 overflow 裁剪。
修复:EChart 组件新增 ResizeObserver 监听容器尺寸变化(合并到同一帧执行 resize),挂载后用 requestAnimationFrame 校正一次尺寸,销毁时断开监听并 dispose;两张 GMV 图表的 tooltip 增加 appendToBody: true,避免被滚动区裁剪。
验证:Chrome 无头浏览器实测,展开月份后两张图表画布均为 753×260,左右两张图悬浮分别正常显示「当前日收入/当前累计收入」「三平台分别收入/合计」,无 ECharts 尺寸告警。
九、全国各门店简表 · 列宽与二级表头
「门店名称」列宽加宽为其他普通列的 1.5 倍(其他普通列 14,门店名称 21)。
三平台二级表头去掉平台前缀:美团下为「外卖收入 / 外卖单量 / 拼好饭收入 / 拼好饭单量」,淘宝闪购、京东下为「收入 / 单量」;平台名仍由第一行的分组合并单元格(美团 / 淘宝闪购 / 京东)标示。
十、全部报表页 · 数值/序号列居中
所有页面的数值列与序号列数据单元格居中显示;文本列(负责区域、区域、大区名、省份、门店名称)保持原有对齐不变。
实现按列数据自动判定:序号列恒居中,其余列的非空数据值全部可转为数值时该列居中,否则视为文本列不处理。
十一、全国各门店简表 · 去掉区域列
「全国各门店简表」去掉原 B 列「区域」,现共 17 列:A 序号 / B 省份 / C 门店名称 / D 总单量 / E 总收入 / F 前日单量 / G 前日收入 / H 单量增长率 / I 收入增长率 / J-M 美团 / N-O 淘宝闪购 / P-Q 京东。
随之调整:A-I 纵向合并两行,平台分组改为 J-M / N-O / P-Q,增长率数据条移到 H/I,标题合并区变为 A1:Q1;「门店名称」列宽仍为其他普通列的 1.5 倍(21)。
十二、全部报表页 · 统一两行表头与黑色边框
除全国简表外,其余 8 页也采用与简表一致的版式:第 1 行为合并标题「抖喜{月}.{日}{表名}」,第 2-3 行为两行表头,数据行从第 4 行开始。
非三平台列纵向合并第 2-3 行;三平台列(美团 / 淘宝闪购 / 京东)第 2 行按平台合并显示平台名,第 3 行只显示去掉平台前缀的子项(如「外卖收入」「拼好饭单量」「收入」「单量」)。
三平台表头配色与简表一致:美团 #FFF2CC、淘宝闪购 #DAE3F5、京东 #EF949E。
所有页面的表头与数据区域统一加黑色实线细边框(1 磅,thin);全国简表边框也由灰色改为黑色。
增长率数据条仍按「0 居中、正蓝负红、±100%」注入,起点随数据行改为第 4 行。
十三、全部报表页 · 数值列自适应列宽
所有页面的数值列(含序号列、增长率/转化率/占比等百分比列)按内容自动估算列宽(中文按 2 字符宽),取代原来的固定 14 / 15。
文本列宽度保持不变:全国简表文本列 14、门店名称 21;其余页文本列 15。
原「增长率列自适应」规则并入本规则,不再单独处理。
十四、按单量/营收排序页 · 标题与公式化
「按单量排序」「按营收排序」的大标题统一改为「抖喜{月}.{日}全国数据表」。
序号列改用 Excel 公式 =SUBTOTAL(103,$D$4:D{行}):按可见行(门店名称列)计数,筛选后自动重排为 1..N。
汇总行不再写死数值:可累加列用 =SUBTOTAL(109,数据区),只汇总筛选后可见行;单价、增长比用合计行单元格重算;进店/下单转化率、评分按可见行曝光加权(SUMPRODUCT + SUBTOTAL + OFFSET),随筛选自动变化。
已用 LibreOffice 无头重算验证:公式结果与静态合计一致;隐藏两行后序号自动变为 1,2,…,合计与单价随之变化。
说明:本次仅改动这两张排序页;门店明细/全国简表仍为静态序号与合计,如需一并公式化可再提出。
十五、含总计行页面 · 总计标签合并
「门店明细」「按单量排序」「按营收排序」的总计行:左侧连续的空白文本列(负责区域 / 地区 / 门店名称)与「总计」合并为一个单元格,并居中显示。
「全国各门店简表」的总计行:省份、门店名称与「总计」合并,居中显示。
数值列 / 平台列的总计单元格不受影响。
十六、同步 · 平台闭店日期修复
现象:飞书同步时,存量门店闭店后门店 closed_date 能更新,但对应平台(美团 / 淘宝闪购 / 京东)的 closed_date 一直为空。
原因:平台 diff 对存量店(property≠increment)同时忽略了 opened_date 与 closed_date(fields 过滤掉两者);门店侧此前已改为只忽略 opened_date,平台侧漏改。
修复:平台侧与门店侧对齐——存量店仅忽略 opened_date,closed_date 仍参与比对/更新。
处理结果:本地补齐 5 条平台记录(伊宁店 mt/tb、西二旗店 mt/tb/jd,closed_date 2026-09-01),服务器补齐 2 条(伊宁店 mt/tb,closed_date 2026-08-28);re-diff 全 0,库内「门店已闭店且有闭店日期但平台闭店日期为空」计数为 0。
十七、特殊平台注册表 · 回龙观店京东
新增特例平台:抖喜(回龙观店) 京东 plat_id 21498153,开店日期 2026-01-31,closed=0。
已同时写入内置默认(engine.py DEFAULT_SPECIAL_PLATS)与运行时配置 /data/sync/special_plats.json。
本地与服务器均已 apply:回龙观店现有 mt 13266092 / tb 2125975853 / jd 22036483 / jd 21498153 四条平台映射,re-diff 全 0。
十八、门店明细 / 按单量排序 / 按营收排序 · 客单价列
美团客单价拆分为两列:「美团外卖客单价」(= 美团外卖收入 ÷ 美团外卖单量)与「美团拼好饭客单价」(原「美团客单价」,= 美团拼好饭收入 ÷ 美团拼好饭单量)。
淘宝闪购客单价、京东客单价保持不变。
上述四个客单价列显示保留 1 位小数(number_format 0.0),底层数值不变;排序页总计行对应列仍为公式(如 =IF(M=0,0,L/M))。
列数由 37 增至 38;平台分组随之后移:美团 L-V、淘宝闪购 W-AD、京东 AE-AL。
说明:「单均收入」不在本次调整范围;如需一并保留 1 位小数可再提出。
十九、客单价 / 单均收入 · 全页保留 1 位小数
将客单价 1 位小数规则推广到所有含该类列的页面:全国大盘、大区、区域、门店明细、按单量排序、按营收排序、两张异常明细。
「单均收入」也一并保留 1 位小数(此前未处理)。
全国大盘 / 大区 / 区域补齐「美团拼好饭客单」列(= 美团拼好饭收入 ÷ 美团拼好饭单量),至此这三个页面的美团也同时有「美团外卖客单」与「美团拼好饭客单」;淘宝闪购、京东客单价不变。
统一保留 1 位小数的列:单均收入、美团外卖客单(价)、美团拼好饭客单(价)、淘宝闪购客单价、京东客单价,均 number_format=0.0,底层数值不变。
未受影响:店均单量 / 店均收入仍为常规格式;全国各门店简表无此类列,仍为 17 列。
2026-09-17
修改
一、同步 · 删除改为逻辑删除
背景:hierarchy 的普通删除接口(UI)一直是逻辑删除(deleted=1、delete_time),但同步服务删除门店/平台走的是物理删除。
修改:
sync /sync/apply:不再设置 force_delete,删除候选改走逻辑删除;
sync /sync/init:去掉「物理清空层级表」,改为逻辑删除后按确定性 id restore/新增;
hierarchy apply_diff:非 force_delete 分支改用 repo.soft_delete(不做子级保护,子级由同一批 deletes 一并软删)。
效果:同步删除后记录保留(deleted=1、delete_time),可恢复;确定性 id 复用(get_any + restore)不受影响;表上唯一索引 (store_name, delete_time) 本就为软删设计。
验证:本地与服务器实测——删除「带平台的门店」后 store/plat 均 deleted=1 且行仍在;本地 /sync/init 对 455 门店 + 1182 平台 + 17 区域 + 5 大区软删后全部正确重建,无残留。
说明:物理删除路径(force_delete=True / delete_entity_force)仍保留,供显式内部重建使用。
二、历史数据回补 · 京东负值归零
现象:部分京东门店「收入 / 单量」原始为负(退款 / 支出导致),但库内为 0。
根因:2–8 月历史装载脚本 backend_new/load_feb_aug.py 对京东做了 max(..., 0) 钳制(inc = max(jd_income - jd_income_2, 0)、amt 同理),负值入库即变 0;当前微服务流水线不做钳制。
对比基准:旧库 127.0.0.1:5432/youdao 的 operation_data_2026_02 ~ 09(截至 2026-09-12)。
处理:逐月按 (plat_id, plat_tag, static_date) 对比后回补——本地 36 条、服务器 38 条(服务器另有爱琴海 08-07 -6.01、张掖 08-04 -0.04 两条此前未修);本地与服务器 re-compare 均为 0 diff。
另:已移除 load_feb_aug.py 的 max(...,0) 钳制,避免重跑再次归零。
三、营收统计 · 统一门店营业窗口
口径:所有营收统计只统计数据日落在门店 [开店日期, 闭店日期) 内的记录——开店日期算当天(opened_date <= static_date),闭店日期不算当天(static_date < closed_date);开/闭店日期为空表示该侧无限制(区间内全部统计)。
已合规:/op/aggregate、/op/stats/daily|monthly|yearly|trend|comparison|average(此前已用 store_window)。
本次修正:
日报取数 _OP_STORE_SQL:由「平台窗口」改为门店窗口;
/reports/monthly-income:补上门店窗口(此前无任何窗口);
GMV 门店月度/每日营收(store_monthly、stores/monthly、store/{id}/daily):补上门店窗口;
/op/query:两个分支统一门店窗口;空开店日期不再被排除(drop_unopened=False)。
验证:2026-02 月度收入 /op/stats/monthly 与 /reports/monthly-income 均为 8,763,744.8;日报 2026-09-05 日收入与 /op/stats/daily 一致(434,620.58);开店前(承德医学院店 09-05)与闭店后(长葛店 09-04)门店已排除。
影响:修正后月度营收较修正前上升(此前平台窗口口径漏统计了部分开/闭店日期为空的门店,如 2026-02 +50.7 万),与运营统计口径一致。
四、同步 · 门店改名识别(避免新增 + 删除)
现象/需求:飞书表里门店改名时,原先会表现为「新增一家门店 + 删除一家门店」,门店数虚增、平台需重新挂接。现要求先判断是否为改名。
判定:diff 阶段取「新增门店」与「删除门店」,若两者平台ID存在交集(mt_id / tb_id / jd_id / mt_tg_id / dy_id 任一相同)则判为改名,取交集最大的配对(一对一)。
处理:仅对原门店执行一次 update(更新 store_name,沿用原门店 id),不新增门店、也不列入删除候选;被改名门店的平台键按新名重映射,原有平台保持挂接(plat_info.store_id 不变);飞书新增的平台以原门店 id 挂到该门店下。
实现:sync engine.py diff 增加改名识别与平台键重映射;plan.py store_of 识别「改名新名 → 原 id」,门店更新数据保留 store_name(hierarchy update_allowed 已含 store_name)。
验证:单元测试(改名 + 新增平台 → 1 条 store update、0 增删、1 条 plat add 且挂原 id);本地真实缓存链路(正镶白旗店改名 + 新增京东平台 → diff 1 update + 1 plat add、0 删除;apply 后门店名更新、新平台挂到原门店,已回滚)。
五、前端 · 图表加载动画修复
现象:数据图表的加载动画由平滑变为「突变」(直接定格到终态)。
根因:EChart 组件在 setOption 之后、以及每次 option 变化时都会调用 chart.resize();ECharts 的 resize() 会把正在运行的动画立即定格到终态,加载动画因此被打断。
修复:改为「仅当容器尺寸真正变化时才 resize」——init 时记录 echarts 已采用的尺寸,ResizeObserver / window.resize 触发时先比较宽高,尺寸未变则跳过;移除 setOption 后的多余 resize;resize 时禁用其自身动画(animation.duration=0)。
验证:无头浏览器回归——门店管理 GMV 明细两张图仍为 753×260、悬浮提示正常;已构建并部署到本地与服务器前端。
六、同步 · 特殊平台新增金科城店(美团 20531749)
背景:抖喜(金科城店)飞书登记的美团账号为 34450385,但该账号在 2026-08 无任何运营数据;实际在跑的美团账号是 20531749(2026-08 全月有数据:收入 1,401.97、单量 109),而该账号未登记在 plat_info,运营数据无法归属到门店。
处理:把「抖喜(金科城店) / mt / 20531749 / 开店 2026-01-31 / 未闭店」加入同步服务特殊平台注册表(engine.py 的 DEFAULT_SPECIAL_PLATS 与 data/sync/special_plats.json,共 11 条)。
部署:本地与服务器 sync 容器均已热更新并重启;两侧 /sync/diff 干跑结果一致——只多出 1 条 抖喜(金科城店)|mt|20531749 平台新增,无其它增删改。
说明:特殊平台只额外挂接、不删除飞书登记的 34450385;下次同步 apply / init 时会生成对应 plat_info 记录,运营数据随之归属到该门店。
七、同步 · 特殊平台新增良乡大学城店(美团 20354929)
背景:抖喜(良乡大学城店)飞书登记的美团账号为 34375747,但该账号在 2026-08 无任何运营数据;实际在跑的美团账号是 20354929(2026-08 收入 18,381.45、单量 1,214),该账号未登记在 plat_info。
处理:把「抖喜(良乡大学城店) / mt / 20354929 / 开店 2026-01-31 / 未闭店」加入特殊平台注册表(engine.py 的 DEFAULT_SPECIAL_PLATS 与 data/sync/special_plats.json,共 12 条)。
部署:本地与服务器 sync 容器均已热更新并重启。
验证:本地 /sync/diff 干跑多出 2 条待新增平台(金科城 20531749 + 良乡大学城 20354929);服务器干跑多出 1 条(良乡大学城 20354929)——服务器已在两次部署之间执行过一次同步 apply,金科城 20531749 的 plat_info 记录已生成(store=抖喜(金科城店)、deleted=0),良乡大学城 20354929 待其下次 apply 生成。
2026-09-18
修改
一、按时间范围上传 · 改为与数据库对比 + 勾选入库
需求:范围上传时要显示具体值;只比较「数据库 operation_data 与上传文件都有」的字段;按 日期/平台/平台id 对齐;库里有、文件没有不管;文件有、库里没有提示「新增」;结果可勾选,点「入库」只把勾选行写入 operation_data_YYYY_MM。
改动:
pipeline range_upload.py 重写:上传文件按天/平台映射为库字段(mt_pin → income_pin/amount_pin;*_data → income/amount/exposure/entry_rate/order_rate/score;京东无评分列;jd_score → score;remark 类没有可对比的库字段会提示「该类型没有可对比的数据库字段」),与 operation_data_YYYY_MM 按 (static_date, plat_tag, plat_id) 对比,只输出有差异的字段与值,「新增」行输出全部可比字段值。
「开始处理」不再覆盖 data/raw、不再重算入库;差异报告仍写到 data/export/change/YYYY-MM/report_{起}_{止}at {日期}.xlsx。
/upload/range/commit 改为接收勾选行 {date, plat, plat_id, status, values},经 operation 内部 reload-apply 以新 mode patch 写入:只更新已存在键的指定字段 + 插入新键,不做任何删除;插入时未提供的指标按库默认(当前库无默认,数字即为 0)。
operation reload.py 新增 mode patch(ins+upd,无 dels)。
前端 UploadV2:范围对比结果改为按 (日期,平台,平台id) 一行、带勾选框,展示「字段: 旧值 → 新值」,支持全选/全不选,入库只提交勾选行。
验证:本地与服务器均用「一条与库完全一致的 tb 行 + 一条改值行 + 一条新 plat_id」测试——一致行 0 差异、改值行显示 income 341.71→441.71、新 id 标「新增」;勾选新增行入库 patch 插入成功(inserted=1)并随后清理;本地/服务器文件 md5 一致。
二、平台管理 · 新增「按平台ID搜索」
在「平台管理」页筛选栏新增「按平台ID搜索」输入框,按平台门店ID(plat_id)包含匹配 ,输入即过滤当前列表并重置到第 1 页,可一键清空。
导出当前筛选结果时同样带上该条件(筛选说明追加「平台ID=xxx」)。
验证:本地构建并部署到本地与服务器前端,页面显示正常。
三、前端图表 · 三平台配色统一 + 「饿了么」改名「淘宝闪购」
三平台图表配色统一为后端导出表头同色相的加深版 :美团 #F5C242、淘宝闪购 #7FA8E6、京东 #E0666F(原色:美团 #FF9900、淘宝闪购 #E6A23C、京东 #409EFF)。
统一改 frontend_v2/src/utils/format.ts 的 PLATFORM_COLORS,覆盖首页趋势、月度详情、年度详情、门店详情、上传统计等图表;另单独改 StoreManage.vue GMV 明细折线里硬编码的三色。
说明:后端导出表头填充色为 美团 FFF2CC、淘宝闪购 DAE3F5、京东 EF949E;因直接用作折线/柱状在白底上过浅,采用同色相加深版(方案 B)。
「饿了么」显示名统一改为「淘宝闪购」,保留 ele_income 等键名与所有引用不变 :
MonthlyDetail.vue(frontend_v2 与 legacy frontend)列名「饿了么营收」→「淘宝闪购营收」(prop 仍为 ele_income);
注释:feishu_client.py(列说明)、backend_new/sql_data_add.py;
文案:docs/PRD.md、docs/项目介绍.md、交付汇报/汇报文稿_GMV运营系统建设.md。
验证:本地构建通过并部署到本地与 128 服务器前端;产物校验含新配色与「淘宝闪购营收」,代码区已无「饿了么」。
四、同步 · 特殊平台新增泸州店京东单店(15884279)
背景:泸州店飞书登记的京东账号为 24472243(已登记在 plat_info);另有一个**京东单店(sig)**账号 15884279(京东 sig 文件「抖喜新疆炒米粉(泸州店) 15884279」,8 月 31 行、9 月 1–15 有 10 行),未登记在 plat_info,需用特殊平台注册表挂接。
过程:最初误加的 24472243 与飞书 jd_id 同键,聚合按 (门店,平台,id) 去重保留飞书条目,属空操作 ;实测确认后改为 15884279(只有与飞书不同 id 的特殊条目才会新增平台)。
处理:把「抖喜(泸州店) / jd / 15884279 / 开店 2026-01-31 / 未闭店」加入特殊平台注册表(engine.py 的 DEFAULT_SPECIAL_PLATS 与 data/sync/special_plats.json,共 13 条)。
验证:本地用 09-16 飞书缓存跑聚合,新增一条 jd 15884279(opened 2026-01-31);服务器 /sync/diff 干跑只多出 1 条 抖喜(泸州店)|jd|15884279;本地与服务器 default=registry=13、文件 md5 一致。
2026-09-20
修改
一、ID 生成统一口径(消除同类型 ID 不一致)
问题:同一类实体的主键在不同入口生成规则不一致——hierarchy 手动创建(前端「新增门店/区域/大区」)走 DB 序列 BR/RG/ST + 6 位(如 ST000001、RG000001),而 sync 同步走 BR/SR/SS + md5[:10](如 SS1951000825);库内既有数据全部是后者。服务器上已实际存在按旧序列建出的不一致记录 BR000001(test_br)、RG000001(test_rg)。
处理:新增 commonlib/ids.py 作为唯一口径:
big_region = BR + md5(大区名);region = SR + md5(区域名|大区名);store = SS + md5(门店名);plat = {tag}_{plat_id}。
hierarchy _gen_id 改为调用它(store/big 用名称,region 先查大区名称再拼键);repo.plat_default_id 委托该模块。
sync 原有的两处重复 md5 逻辑 plan._sid 与 engine._sync_id 改为委托同一模块。
验证:本地对库内 455 门店 / 17 区域 / 5 大区逐一比对,ids.* 计算值与库内 ID 100% 一致 ;hierarchy _gen_id 现产出与库一致(store=SS1951000825、plat=mt_27281762)。服务器同样比对:store 0 条不符;region/big_region 各 1 条不符,均为上述测试记录(旧序列入口所建)。
清理:服务器上按旧序列建出的测试记录 RG000001(test_rg) / BR000001(test_br) 已逻辑删除,并按统一口径重建——新 test_br=BR2C39816682、新 test_rg=SREFB6AEEDF5(挂在新的 test_br 下,均与 commonlib.ids 计算值一致);本地库无这两条测试记录。
说明:ID 一经生成即身份,实体改名后不再等于新名称的 md5 属正常(身份稳定优先,不会因改名换主键)。
二、门店/平台手动创建 · 空日期导致入库失败修复
现象:运营在「门店管理 → 新增门店」手动建店失败。
根因:前端表单「开店日期 / 闭店日期」留空时传空字符串 '',而 store_info / plat_info 这两列是 date 类型,PostgreSQL 报 invalid input syntax for type date: "",插入被拒(与 ID 规则无关)。
修复:hierarchy repo.py 写库前把 date 列的空字符串归一化为 NULL(新增 _norm_empty_dates,作用于 insert / update / update_sync);平台门店创建同样受益。
验证:本地与服务器均用「开店/闭店日期留空」实测创建门店与平台门店成功(落库为 NULL),随后清理测试行;两侧文件 md5 一致。
三、软删除加固(大区/区域/门店/平台)
隐患:uk_* UNIQUE(名, delete_time) 里活动行 delete_time IS NULL,而 PostgreSQL 中 NULL 互不相等,活动同名行实际不受唯一约束保护 ;再叠加「门店主键 = SS + md5(门店名)」的确定性生成,同名重建会撞主键 。
修复:
索引改为活动行部分唯一索引 :uk_big_region_name_active UNIQUE(big_region_name) WHERE deleted=0、uk_region_name_active、uk_store_name_active、uk_plat_active (plat_id, plat_tag) WHERE deleted=0;删除旧 (名, delete_time) 索引。本地与服务器均已执行。
手动创建命中同名软删行时复活 :先清空 insert_allowed 各列,再按新提交内容赋值、deleted=0(新增 repo.revive);活动同名行仍被索引拒绝。
门店手动创建必填:区域 / 门店名 / 开店日期 (仅用户创建路径严格校验;同步初始化 apply_diff 仍宽松,避免历史无开店日期门店失败)。
验证:本地与服务器均实测——缺开店日期被拒(缺少必填字段: opened_date);门店软删后同名重建 = 同 ID 复活,且旧值被清空后按新值赋值(supervisor a→b、store_code X1→''、property stock→increment);两侧文件 md5 一致。
四、分级审批 + 服务端 RBAC(门店 / 平台门店 / 运营账号)
审批表修复:approval 补 method / path / review_chain / review_stage / scope_region / scope_big(原表只有 entity_key,而代码用 method/path,提交审批会直接报错、表内 0 行);本地与服务器均已迁移。
审批链路(E2):运营提交 → 大区经理(第一级)→ BOSS/admin 终审 ;大区经理提交 → BOSS/admin 单级终审 ;BOSS/admin 可对待审单提前通过/驳回 (提前结束)。
审批类型:新增 store / plat / user (门店、平台门店、运营账号的增改删),保留 plan / big-region / promotion。
范围校验:运营只能提交本区域 、大区经理只能提交本大区 ,越界 403;大区经理待审列表只显示本大区单据。
服务端 RBAC:hierarchy/manager_api 写接口仅放行 boss/admin/approval-system(导出等读操作不拦),运营/大区经理直连一律 403「请提交审批」;/users 增删改同样仅 BOSS/admin 可直连。同步仍走 /internal/hierarchy/apply-diff,不受影响;网关错误封套修正为透传下游 403/详情。
前端:门店管理 / 平台管理 / 用户管理对运营、大区经理改为提交审批 (提示「已提交审批,待上级审核」),BOSS/admin 保持直连;审批中心显示新类型与「两级进度」。
验证(本地 + 服务器,自签各角色 JWT 走网关):运营直连建店 403;运营提交→大区经理通过→BOSS 终审→门店实际建成;越界提交 403;BOSS 直连 200;大区经理直连建运营 403 →提交→BOSS 终审→账号建成。
五、报表下载开放至非访客 + 运营门店默认本区域
「报表下载」菜单由仅 admin 可见改为除访客外所有角色 可见(后端 resolve_scope 已按 运营=本区域 / 大区经理=本大区 / BOSS/admin=全部 解析范围)。
「门店管理」页:运营进入时默认按本人区域过滤 (仍可手动清除查看其它)。
服务端:_GUEST_ALLOW 已限制游客仅可访问主面板只读数据,游客访问 /reports/* 返回 403「游客仅可查看主面板数据」;运营及以上放行(POST /reports/daily 生成、日报/周报/月报列表、/reports/daily/op-export 导出均 200)。
另:前端 index.html 增加 Cache-Control: no-cache, no-store, must-revalidate,避免浏览器缓存旧入口导致新版本的菜单/功能显示不出来(本地与服务器 nginx 均已生效)。
验证:本地与服务器资源链均为 index.html → index-*.js → MainLayout-*(level>=1);运营身份实测各报表接口全部 200。
六、审批中心 · 详情弹窗(通过 / 驳回)
审批人在「待我审批」列表点「详情」,弹出与「新增/修改」表单字段一致 的只读内容:
门店:区域 / 门店名称 / 督导 / 门店编号 / 省份 / 门店类型 / 属性 / 开店日期 / 闭店日期 / 状态;
平台门店:平台门店ID / 平台 / 关联门店 / 平台门店名称 / 平台类型 / 开闭店日期 / 状态;
用户账号:用户名 / 姓名 / 角色 / 所属区域或大区 / 初始密码(掩码) / 状态;
计划、大区数据等其它类型:列出提交的原始字段。
弹窗底部可直接「通过 / 驳回」(通过即执行、驳回即终止);点「取消」或点击空白区域 关闭弹窗。
列表里的「通过 / 驳回」按钮保留二次确认;弹窗内的按钮视为已确认,直接执行。
验证:本地构建通过,ApprovalCenter 产物含「审批详情」;已部署到本地与 128 服务器前端。
七、门店新增 · 省份为必填项
手动新增门店的必填字段由「区域 / 门店名 / 开店日期」扩展为「区域 / 门店名 / 省份 / 开店日期」:
hierarchy _ensure_create_payload(strict)加入 province;
前端「新增门店」表单省份标必填,保存时校验(编辑同样适用);
网关审批提交对 store 新增校验 区域/门店名/省份/开店日期,缺一即 400(避免审批通过后回放才失败)。
同步初始化 apply_diff 仍走宽松校验(不受影响)。
验证:本地与服务器均实测——直连建店缺省份 400「缺少必填字段: province」、带省份 200;运营提交缺省份 400「缺少必填字段: 省份」、带省份提交→大区经理→BOSS 终审→门店带省份建成(province=河北省)。
八、审批 · 同一目标冲突保护
问题:同一家门店/平台门店/用户/大区可能同时存在多张待审批单(例如「修改」与「删除」并发),逐张通过时会出现「先删后改」回放失败、或结果不可预期。
修复:
提交时冲突拦截 :为每张单计算目标键(门店 = SS+md5(门店名) 或门店 id;平台 = {tag}_{plat_id};用户 = 用户名;大区 = BR+md5(大区名) 或大区 id;计划 = 计划 id),若该目标已有 status=pending 的单 ,直接 400「该目标已有待审批申请(单号…,提交人…),请先处理后再提交」;单被通过/驳回/撤回后锁自动释放。
执行前再校验目标 :终审执行前复核目标仍存在(store_info / plat_info / big_region_info 需 deleted=0、sys_user 需存在);若已被删除等导致失效,则自动作废 该单(status=rejected,备注「目标已变更:…」),不再回放。
验证(本地 + 服务器):operator 提交改店 → senior 对同店提交删除被 400 拦截;撤回改店后 senior 再提交成功;把目标门店直接删除后再审批 → 返回「目标已变更,申请已自动作废」,状态 rejected。
九、审批 · 提交人可撤回 + 运营可查看本人审批进度
提交人主动撤回 :「审批中心 → 我的审批进度 / 我提交的」里,状态为 pending 的单可点「撤回」(/approvals/{id}/withdraw 仅允许提交人撤回自己未完成的单);撤回后状态 withdrawn,不再继续审批。
运营可查看审批进度 :
「审批中心」菜单由「大区经理及以上」放开为除访客外所有角色 ;
运营进入后默认展示「我的审批进度」 (不再显示「待我审批」页签),可看到自己提交单的 类型 / 操作 / 变更内容 / 进度(stage/链路) / 当前审批角色 / 状态 / 提交时间,并可点「详情」查看字段内容;未完成前可自行撤回。
验证:运营提交改店 → GET /approvals?view=mine 返回该单(pending、进度 1/2、当前审批 senior)→ 撤回 200、状态 withdrawn。
十、审批中心 · 审批状态鲜明配色
状态标签改为深底白字 并按状态用鲜明色区分:待审批=橙 #F59E0B、已通过=绿 #16A34A、已驳回=红 #DC2626、已撤回=灰 #6B7280。
列表行背景辅助区分:待审批 行淡橙(#FFF7E6)、已驳回 行淡红(#FFF0F0)。
验证:本地构建通过(产物含 F59E0B)并部署到本地与 128 服务器前端(dist 包 md5 一致)。
十一、门店新增 · 运营默认选中所属区域
「新增门店」时,运营的「所属区域」字段自动默认选中其 sys_user.region_id ,且区域下拉锁定为本区域 (不能改到别区);大区经理 / BOSS / admin 仍可选全部区域。
运营进入门店管理默认只看本区域(见第五节),与本项配合,新增/编辑都限定在自己区域。
验证:本地构建通过并部署到本地与 128 服务器前端(dist 包 md5 一致)。
十二、文档 · 新增「审批流程」页 + 目录编号0 跳转
新增独立页面 approval.html(源 docs/审批流程.md),内容:审批链与入口、开店 、闭店 、数据修改 、状态配色、进度查看与撤回。
用户手册目录最前面新增编号 0 的「审批流程」跳转按钮(<li value="0">,蓝色按钮样式),点击跳转到该页;手册章节仍为 1~13。
构建:docs/build_html.cjs 改为同时生成 approval.html 与 index.html,两页共用 site/style.css;该页右上角有「返回用户手册」。
十三、文档 · 首页改为纯两级目录页(正文拆分)
首页 index.html 改为只显示目录 :一级(章)与二级(节)两级标题,全部可点击;
一级 → manual.html#ch*(该章标题处 );二级 → manual.html#sec*(对应小节);
目录顶部保留「编号 0」的「审批流程」跳转按钮。
正文拆分到 manual.html(封面 + 全部章节 + 附录),页面右上角有「← 返回目录」;approval.html 的返回链接也指向目录页。
构建:docs/build_html.cjs 同时生成 index.html(目录页)、manual.html(正文)、approval.html(审批流程),自动为 h2/h3 打锚点并生成两级目录(本次 13 章 / 60 节)。
验证:本地构建产物链接指向 ./manual.html#ch* / #sec*;已部署 8090。
十四、文档 · 审批流程加入流程图与界面截图
新增流程图 manual_images/approval_flow.svg:发起操作 → 提交审批 → 分级审批(运营→大区经理→BOSS/admin)→ 通过则自动执行 / 驳回则终止,并标注冲突保护与「提交人可查看进度、撤回」。
用无头 Chrome (CDP 注入登录态)抓取 5 张真实界面截图,放入 manual_images/appr_flow_*.png:门店管理(运营默认本区域)、新增门店表单(区域默认本区域、省份必填)、运营「我的审批进度」、大区经理「待我审批」(状态配色)、审批详情弹窗(可直接通过/驳回)。
docs/审批流程.md 以 Markdown 图片语法引用,构建时自动生成带图注的 <figure>(图 1~图 6)。
十五、权限修正 + 手册一至十章与系统对齐
回归修复 :manager_api 写接口 RBAC 之前把「区域管理」也挡住了;现放行 /regions 给大区经理及以上 (区域维护本就直接生效、不走审批)。
运营不能删除 门店 / 平台门店:网关对 operator 的 DELETE 提交返回 403「运营不能删除,删除需由大区经理提交审批」;前端对运营隐藏「删除 / 批量删除」入口。
手册第一~十章对齐当前系统 :
第二章:权限表与审批说明更新(报表下载除访客外可用;审批中心运营可看「我的审批进度」;门店/平台/用户改动需审批;BOSS/管理员直接生效;区域直接维护);
第四章:门店/平台 新增/修改/闭店 = 提交审批 ;必填「区域 / 门店名 / 省份 / 开店日期」;运营区域默认本人区域并锁定 ;运营不可删除 ;
第五 / 六 / 七 / 八 / 十章:大区经理改动提交审批、BOSS/管理员直接生效、审批中心页签「待我审批」与状态配色、按时间范围上传 改为与 operation_data 对比 + 勾选入库、报表下载对非访客开放、FAQ 补充「运营改动为何不立即生效」。
十六、入店人数(entry_num)字段全链路
取数规则 :美团(mt_data)/京东(jd_data)取源文件「入店人数」列、淘宝闪购(tb_data)取「进店人数」列;旧版导出缺该列时用 ceil(有效订单 ÷ 下单转化率) 推算;美团单店(mt_sig)同公式推算;京东单店(jd_sig)不推算,记 0。
入库校验 :|entry_num ÷ exposure − entry_rate| ≤ 5/1000(entry_rate / exposure 缺失或为 0 跳过、entry_num 为 0 跳过);不通过清单在接口返回 + 服务日志 + 报告 data/export/check/年-月/entry_check_*.xlsx 三处给出。
全链路落库 :pipeline 解析计算 → 整日重放 / 按范围上传 → operation_data 月表 → 明细查询 / 汇总聚合(/op/query 可按 entry_num 取列、/op/aggregate 返回 total_entry_num)。
历史回填 :脚本 app.backfill_entry_num(整表一次读出 → 每表一条批量 UPDATE ,避免逐行写;本地 215,690 行 / 18.5 万行更新 31 秒,服务器 222,126 行 / 18.97 万行 56 秒)。
顺带修复服务器源文件 :① mt/2026-09-14/pin.csv 实为「目标及进度」xlsx(错传),已用真实拼好饭文件替换(逐行核对 368/368 一致,原文件备份 /home/douxi/tmp/pin.csv.bad-bak);② tb 2026-08 的 31 天为 95 列旧格式(缺省份/店铺评分),已让代码容忍缺列且不把缺失列写成 0 (不覆盖库内既有评分),并删除这 31 个只有 1 行的空壳文件。
十七、推广数据(门店推广花费):上传 / 导出 / 按月分表
新表 :promo_data_年_月(按月分表 ,与 operation_data 同构:每张分表独立索引与部分唯一索引,入库时自动建表),字段取美团/淘宝闪购两平台并集,明细粒度 (保留 计划ID / 推广产品 / 投放渠道 / 资金类型 / 营销场景)。
上传 :「每日数据上传」页新增**推广数据上传(按日期范围)**板块——选范围 → 选类型(美团门店推广 / 淘宝闪购门店推广)→ 开始处理(与分表逐行对比)→ 勾选 → 入库(只增改、不删除,重复上传幂等);差异报告 data/export/promo/年-月/。
导出 :板块内「导出」按钮按所选日期范围导出明细,并关联门店档案 带出大区/区域/门店ID/门店名称/省份/城市/区县(关联不到的行照常导出)。
接口 :GET /upload/promo/types、POST /upload/promo/range、POST /upload/promo/range/commit、GET /upload/promo/export。
已导入 :美团 8/1-8/19 10,812 行、9/1-9/19 18,746 行;淘宝闪购 8/1-8/19 7,266 行(服务器迁移时发现 9 月美团推广数据,已拆到 promo_data_2026_09)。
周报的推广页与推广导出均已按此分表跨月读取。
十八、周报制作(6 个页签)
「报表下载」页新增**「生成并下载周报」**:选日期 → 一次点击生成并下载;同时复用已有周报列表(可再次下载)。
本期 = 本月 1 日 ~ 所选日期;对比期 = 上月 1 日 ~ 上月同日(上月无该日取上月最后一天)。
6 个页签:汇总 / 美团 / 淘宝闪购 / 京东 / 美团推广 / 淘宝闪购推广 ;每页 全国 → 大区(含「大区合计」)→ 区域 ,第一列「大区」跨行合并、第二列「区域」;第 1 行标题(合并 列数−2、字号 12 加粗)+ 日期,第 2 行字段表头(汇总页 #d4f4f1、平台页用日报同款平台色)。
接口 POST /reports/weekly(同步生成并直接下载),文件落盘 data/export/weekly/年-月/weekly_report_*.xlsx。
十九、周报口径修正(与系统/页面一致)
GMV目标口径 :全国/大区直接取 GMV 服务月度目标(monthly_stock_gmv + monthly_increment_gmv,与「月度详细」页默认总量模式 一致,含闭店门店与大区级分摊),区域按各区域门店目标占比分摊 ,保证 Σ区域 = 大区、Σ大区 = 全国;增量GMV目标取增量部分;达成率 = 周期内收入 ÷ 整月目标。
原因:原来按「未闭店门店目标」求和,比月GMV页少 367,481.12(其中 244,502.64 为闭店/无平台门店目标、122,978.48 为 gmv 大区级特殊处理)。验证:本地 14,241,521.95、服务器 14,253,957.63,与月GMV页一分不差 。
上一周期同店对齐 :对比期只统计「本期出现过的门店」,避免用已停业门店拉偏增长比。全国单量增长比由 -31.9% 修正为 -13.1% (服务器 -13.8%)。
低于阈值门店数 :改为只统计统计当日「有评分(score>0)且低于阈值 」的门店,修掉 score=0(当天无评分)被当成低分的问题 → 美团 216 / 淘宝闪购 215 / 京东 269,与库内一致。
列表统计日期 :报表列表的「统计日期」只显示统计当日 (周报即本期截止日),不再显示区间。
二十、周报新增两页:门店明细 / 门店推广明细
门店明细 (一行一店,按本期收入降序,共 61 列 ):仅含本期有运营数据的门店。字段:大区、区域、门店名称、美团ID、淘宝闪购ID、京东ID、门店属性、本期 单量/收入/单均收入 + 曝光人数/入店人数/入店转化率/下单转化率 、美团·淘宝闪购·京东 各出「收入/单量/曝光人数/入店人数/入店转化率/下单转化率」 、上期 单量/收入 + 同样 4 个指标、上期三平台各出同样 6 列 、单均差值、单量增长比、收入增长比、差评数、是否营业。合计与每个平台都有本期值与对比值 。上期同店对齐 。
门店推广明细 (一行一店,美团+淘宝闪购合计,按本期推广降序):仅含本期有推广记录的门店;字段:大区、区域、门店名称、平台ID、本期推广、上期推广、推广差值、曝光提升、进店提升、进店成本(本期推广 ÷ 进店提升)。上期推广同店对齐 。
两页为独立明细表,不做大区/区域的跨行合并,标题仍合并「列数−2」+ 日期。
验证:本地(8 月口径)门店明细 356 行 × 61 列 、门店推广明细 335 行 × 10 列;服务器(9/1-9/20)门店明细 371 行 × 61 列 、门店推广明细 353 行 × 10 列;两期「Σ平台 − 合计」在曝光人数 / 入店人数 / 单量 / 收入 四项上最大差均为 0 ;标题/合并/字段/排序均正确。
二十一、报表列表分页与横向并排
「报表下载」页的日报 / 周报 / 月报三个列表由垂直堆叠改为横向并排 (CSS Grid 三列等宽),表格列压缩、分页条可换行。
三个列表统一默认每页 20 条 分页(可选 20 / 50 / 100,支持翻页、刷新自动回到第 1 页)。
二十二、门店管理页新增「大区」列
「门店管理」列表在门店名称 与所属运营 之间新增一列「大区 」(列顺序:门店ID / 门店名称 / 大区 / 所属运营 / 省份 / 城市 / 督导 / 属性 / 状态 / 门店GMV / 月GMV / 月营收 / 操作)。
取值:按门店 region_id 找到所属区域,再取该区域的 big_region_id 对应的大区名(复用页面已加载的区域 / 大区字典,无额外请求)。
导出同步带上大区 :点「导出」生成的 Excel 也新增「大区」列,列顺序与页面一致(门店ID / 门店名称 / 大区 / 所属运营 / 省份 / 城市 / 督导 / 属性 / 状态 / 门店GMV / 月GMV / 月营收);导出仍按当前筛选与排序。
验证:本地与服务器前端产物一致(StoreManage-CQA0QAi-.js),线上包内页面列 渲染顺序为「门店名称 → 大区 → 所属运营」、导出列 定义为 门店名称 → 大区(big_region_name) → 所属运营,资源 200。
二十三、周报「低于阈值门店数」口径改为周期平均分
原口径:统计当日 (本期截止日)该平台「有评分且低于阈值」的门店数。
新口径 :周期内门店平均分(只统计非 0 评分)> 0 且低于阈值 的门店数——先按门店对周期内所有非 0 评分求平均,再判断是否低于阈值;平均分为 0(周期内全无评分)的门店不计入。
阈值仍按平台取配置(美团 4.7 / 淘宝闪购 4.8 / 京东 4.8)。
验证:服务器(9/1-9/20)报表 全国 美团 268 / 淘宝闪购 227 / 京东 271,与库内同口径(含开业/闭店过滤)独立复核完全一致 ,且 Σ大区 = 全国;本地(8 月口径)美团 241 与库内复核一致。
二十四、周报门店明细/门店推广明细:关键数据为空的门店不计入统计
门店明细 :本期收入与单量都为 0(空)的门店 不导出 (即「收入/单量等关键数据为空则不计入统计」);导出行数与汇总页的「营业门店数」一致。
门店推广明细 :本期推广(消费)为空/0 的门店不导出 。
汇总页与平台页的「门店数」「营业门店数」口径保持不变 (门店数仍为未闭店+有关联平台的门店数;营业门店数仍为周期内至少 1 天营收/单量不为 0)。
验证:本地(8 月口径)门店明细 356 → 344 行(= 汇总营业门店数 344)、门店推广明细 335 → 331 行,空值行均为 0;服务器(9/1-9/20)门店明细 371 → 364 行(= 汇总营业门店数 364)、门店推广明细 353 行(本期推广=0 的行 0)。
二十五、新增「淘宝闪购 CRM 扣点」模块
新增页面「淘宝闪购CRM扣点 」(运营及以上可见):大区 / 区域 / 门店ID / 门店名 / 淘宝闪购ID / 开始日期 / 前7日当日 … 昨天当日 / 当前合计 / 目标值 / 差值 / CRM扣点 / 结束日期;默认差值降序 ,差值 > 0 高亮 ,结束日期 + 3 天 < 今天 的行自动隐藏;支持大区 / 区域筛选、门店ID / 门店名 / 淘宝ID 搜索与 Excel 导出。
数据存储 :日数据按月分表 tb_crm_daily_date_YYYY_MM(键 tb_id + static_date,重复上传覆盖),目标表 tb_crm_aim(键 tb_id + cycle_year)。仅保留能匹配 plat_info(plat_tag='tb') 的淘宝闪购门店行,未匹配行跳过。
周期账单上传 :页面右上「选择周期账单」+ 上传日期(默认昨天)→ 文件存至 raw/tb/<日期>/crm.xlsx → 立即解析入库(上传接口 POST /upload/tb_crm)。
当前合计 = 开始日期起至最新数据日的「代运营收入」累计(周期内);目标值 = 该门店所在 CRM 周期(9/10 为界 )的年度目标;差值 = 当前合计 − 目标值 ;结束日期 = 累计 − 目标首次 > 0 的日期。
申请审批 :门店管理操作栏新增「申请 」按钮(仅门店已关联淘宝闪购平台门店时显示),弹窗填写开始日期 / CRM扣点(%) / 备注,走现行审批链路(运营→大区经理→BOSS,大区经理→BOSS),通过后 由网关回放写入 CRM 目标;同门店同周期 重复申请被拦截(返回「已存在 CRM 目标记录」)。
年度目标配置 :crm.yearly_aim(2025:1080、2026:980,含各自起止日期),可在「系统配置」中修改;审批通过时按当时配置取值,之后修改不影响已生效记录。
后端归属 :查询/目标/导出在 operation 服务(/crm/overview、/crm/config、/crm/export、/internal/crm/aim),上传解析在 pipeline 服务;审批新类型 crm 在 api-gateway 。
验证:本地 98 行样例 → tb_crm_daily_date_2026_09 98 行;/crm/overview 基准日 2026-09-20、7 列标签正确、按差值降序;重复上传返回 updated:98;审批回放写入目标并拦截同周期重复申请。
2026-09-21
一、淘宝闪购 CRM 跟踪数据初始化 + 周期界定宽限
周期界定日宽限 :cycle_year_of / 网关的周期年度判定由 9/10 调整为 9/9 及以后算当期 (周期起止仍取 crm.yearly_aim 配置),使「开始日期 = 9/9」的申请能按当期累计,而不是落到上一周期(上一周期窗口在 9/10 就结束,导致合计只算到 9/9 当天)。
数据初始化导入 :按《数据表汇总9.20》的「CRM扣点每日关注 」页导入系统(本地 + 服务器均已导入):
99 家门店 、984 条日数据 (2026-09-09 ~ 2026-09-20,取自表格 9/10 起的每日「代运营收入」列);
99 条 CRM 目标 :目标 1180 的 1 家(抖喜(南湖职院店),开始日期 2026-09-09 ,其表格「之前-9月9日」417.13 计在 9/9);其余 98 家 目标 980 、开始日期 2026-09-11 ;
开始日期之前的收入并入开始日期当天(仅「抖喜(财富广场店)」的 9/10 值 6.67 并入 9/11),保证「当前合计」与表格「合计」列一致;
校验:99 行全部 匹配 plat_info(tb);当前合计 / 目标值 / 差值 与表格逐行一致(0 处不一致);Σ当前合计 = 5732.85 = Σ表格合计;7 日列与表格 9/14~9/20 逐格一致。
CRM 扣点导入(飞书) :用系统已配置的飞书应用读取《2026饿了么会员系统采购名单》(wiki 地址,其 wiki token 即电子表格 token ,工作表「2026年会员系统采购名单」)的「crm扣点 」列,按 id(淘宝闪购ID) 写入 tb_crm_aim.rate:
表格 100 行 → 匹配到目标记录 98 行 (1% ×71、0.5% ×15、3% ×12;表格「0.50% / 0.5%」统一按 50%÷100 存为 0.5%);
未写入 2 行:「抖喜(良乡大学城店)」id 单元里标注「未上线」(富文本 514725392+未上线)、「抖喜(金科城店)」id 为「还未上线」——两者尚无目标记录;
「抖喜(南湖职院店)」不在该名单中,rate 保持 0 (其目标 1180 / 开始日期 9/9 不变)。
本地与服务器均已写入并通过接口复核(库内分布:1% ×71、0.5% ×15、3% ×12、0 ×1)。
二、我的区域 / 我的大区新增「CRM 最近达标」显著提示
operation 新增 GET /crm/achieved?days=7:返回最近达标 (达标日期在最近 N 天内)的 CRM 门店,按角色过滤范围(运营=本区域、大区经理=本大区、BOSS/管理员=全部),按达标日期倒序、同日期按差值倒序;该接口包含 已过 CRM 页 3 天隐藏期的记录(内部用 overview(include_hidden=True) 再做窗口过滤)。
「我的区域 / 我的大区」页顶部新增绿色醒目提示卡 :最近 7 天有门店达标时显示,含 门店名称 / 所属区域 / 淘宝闪购ID / 达标日期 / 当前合计 / 目标值 / 差值(红) / CRM扣点,并有「查看 CRM 详情」按钮跳转 CRM 页;无达标时不显示(不占用版面)。
验证(本地):临时将「抖喜(玉泉店)」目标改为 100 → 达标日期 2026-09-14,接口返回 1 条;另一家 9/11 达标的门店被 days=7 窗口正确排除;角色范围校验:本区域=1、本大区=1、其它区域=0;验证后已还原 目标与达标日期。本地与服务器 /crm/achieved 均返回 200、count=0(当前尚无门店达标)。
三、我的区域 / 我的大区新增「CRM 预告」(接近达标 / 进度领先)
operation 新增 GET /crm/near?ratio=0.8&limit=5:按完成率 (当前合计 ÷ 目标值)降序返回未达标 门店(已达标由「最近达标」负责,不重复),并给出 progress(完成率%)、gap(还差多少)、near(完成率 ≥ 阈值,默认 80%);同样按角色过滤范围(运营=本区域、大区经理=本大区)。
「我的区域 / 我的大区」页新增橙色预告卡 (绿色达标卡下方):进度条展示完成率,≥80% 显示「接近达标」标签、其余显示「进度领先」;标题区分「完成率 ≥ 80% 的门店 N 家(接近达标)」/「暂无门店达到 80%,以下为进度领先门店」;无未达标门店时不显示。
验证(本地):临时把最高累计门店目标改为 total÷0.85 → count_near=1、该店 progress=85.0 / near=true 且排第 1,其余按 23.86% / 22.37% / 16.78% / 16.03% 排序;ratio=0.95 → count_near=0;limit=2 → 2 条;角色范围(本区域/其它区域)正确;验证后已还原 目标与达标日期。本地与服务器 /crm/near 均 200(当前 count_near=0,进度前 5:37.13% / 23.86% / 22.37% / 16.78% / 16.03%),页面资源已同步(MyScope-BsBN1eku.js)。
四、CRM 日数据上传改为「只按代运营收入判断是否变更」
upsert_daily 不再对既有行无脑覆盖:同一「门店id(tb_id) + 日期(static_date) 」先取库内代运营收入 ——相同 → 跳过更新 (返回 unchanged)、不同 → 更新整行 (updated)、不存在 → 新增 (inserted)。因此同一份周期账单重复上传是幂等的 :只有真正变动的门店会写库、刷新 update_time。
上传结果提示改为:入库完成:文件 N 行,新增 X,变更 Y,未变更 Z;跳过 …(未关联系统门店)。
验证(本地,用 2026-09-20 样例周期账单 98 行):
首次上传:新增 0 / 变更 1 / 未变更 97 (97 家与 9/20 已导入数据完全一致,仅 1 家有差异);
原样再传:新增 0 / 变更 0 / 未变更 98 ;
把第 1 行「代运营收入」3.73 改为 4.96 后上传:变更 1 / 未变更 97;再传回原文件:变更 1 / 未变更 97;再传一次:未变更 98;库内总行数始终 984 不变,原始文件 md5 亦复原。
服务器(9/9~9/20 共 984 行)用库内已有行原值调用:unchanged=1;未知门店:skipped=1;行数不变(未向生产库写入任何数据 ),双端 md5 一致。
五、CRM 导出修复(前7日列全空)与表格格式优化
问题 :导出的 Excel 里 7 个日列(前7日当日…昨天当日)全是空值 。原因:表头列名带日期后缀(如 前7日当日(2026-09-14)),但构造行数据时用的键是不带日期的 前7日当日,再用 pd.DataFrame(data, columns=cols) 按列名取值 → 取不到,整列变成 NaN。
修复 :导出改为用 openpyxl 直接建表、逐格写入(不再用 pandas 拼列),7 日列与页面完全一致;同时按需求格式化:
CRM扣点 单元格设为百分数 0.0%(0.01 → 1.0%);
金额/数量列 #,##0.00(两位小数、千分位);
所有列自适应列宽 (按内容宽度,中文按 2 个字符计,范围 9~32);
数字列居中 (7 日列 + 当前合计/目标值/差值/扣点,以及 门店ID/淘宝闪购ID 两列),文本列左对齐;表头加粗 + 浅绿底 + 冻结首行。
验证:本地与服务器导出均为 100 行 × 18 列 ,7 日列空单元格 0 ,扣点 number_format=0.0%、合计列 #,##0.00,列宽 9.5~23.5,冻结 A2;南湖职院店 7 日列导出值与页面一致(1.78/1.6/2.22/3.72/0.9/1.41/1.34);双端 md5 一致(c8280117…)。
六、CRM 导出的 7 日列标题改为仅日期
导出 Excel 的 7 个日列标题由 前7日当日(2026-09-14) 改为仅日期 2026-09-14 … 2026-09-20(日期缺失时回退为原标签,如未取到数据基准日)。
验证:本地与服务器导出的表头为「大区 / 区域 / 门店ID / 门店名 / 淘宝闪购ID / 开始日期 / 2026-09-14 … 2026-09-20 / 当前合计 / 目标值 / 差值 / CRM扣点 / 结束日期」,100 行 × 18 列、7 日列空单元格 0、扣点仍为 0.0%、日列自适应列宽 12.5;双端 md5 一致(5191639970…)。
七、系统配置页看不到 CRM 配置(显示修复)
问题 :crm.yearly_aim 只存在于代码内置默认值(DEFAULT_SYS_CONFIG),并没有写入 sys_config 表;而「系统配置」页的列表接口只读表,所以页面上看不到任何 CRM 相关配置 (虽然运行时已按默认值生效)。
修复 :网关 GET /configs 现在会把内置默认值中未落库的键一并列出 (返回 is_default=true),页面在配置键后显示灰色「默认 」标签;显示的就是当前生效的默认值,点「保存」后即写入 sys_config 表。今后新增任何默认配置项都会自动出现在页面上 。
同时给 crm.yearly_aim 补了中文说明:「淘宝闪购 CRM 年度目标(按周期年度,9/10 为界; 含起止日期)」。
验证:本地与服务器「系统配置」列表均为 10 项 ,含 crm.yearly_aim(带「默认」标记,值 {"2025":{"aim":1080,…},"2026":{"aim":980,…}});配置页资源已更新(ConfigManage-COSCSa_S.js),双端 md5 一致(b9c554c0…)。
八、CRM 关注页「筛选后查不到数据」的原因与改进
现象 :在「淘宝闪购CRM扣点」页选择某个大区 / 区域后列表为空。
原因 :CRM 列表只包含在 tb_crm_aim 里有目标记录的门店 (首批 99 家),并非全部门店——库内 5 个大区 17 个区域中只有 11 个区域 有 CRM 门店;选到其余区域(或运营/大区经理选到自己范围之外)为空属正常,不是筛选坏了。
改进 :
GET /crm/overview 新增 counts(counts.big / counts.region):在应用「大区/区域筛选之前」、按当前角色可见范围统计各大区/区域的门店数;
页面下拉选项显示「大区 / 区域名(数量) 」,一眼看出哪些范围有数据(如「华南大区(26)」);
空表提示改为:「当前筛选下没有数据:CRM 列表只包含已申请(有目标记录)的门店,括号里的数字是该大区/区域的门店数」;
列表项同时返回 big_region_id / region_id,便于前端与排查。
验证:本地与服务器 counts.big = 外阜 12 / 晋冀 20 / 京津沪 25 / 华南 26 / 北方 16(合计 99),非 0 区域 11 个;选 0 数据区域(如 北方-殷成忠)返回 0、但 counts 仍返回全部 11 个非 0 区域(可继续切换);大区+区域组合(北方大区 + 北方-孙建鹏)返回 9;双端 md5 一致(d8fc8c87…),页面资源 CrmManage-DBx5RMmI.js。
九、特殊平台注册表新增「抖喜(怡华店)」三条
在特例平台注册表 (后台配置文件 special_plats.json,内置默认值 DEFAULT_SPECIAL_PLATS 同步更新)中为 抖喜(怡华店) 新增三条:mt 27748066、tb 534905057、jd 16138192,opened_date=2026-01-31、closed=0。
执行方式:更新注册表 → 飞书同步 pull → diff → apply(本次只应用这三条 plat 键 ,其余差异不动)→ 由 hierarchy 创建 plat_info 记录。
结果:本地与服务器 plat_info 均新增 3 行,门店 = 抖喜(怡华店)(SS5DBD726045,外阜-司道磊 / 外阜大区),opened_date=2026-01-31、closed=0,无错误。
说明:怡华店在飞书表里原有 mt 33770372 / tb 1349330884 / jd 24061389,本次是新增 三条特殊平台 ID(不是替换),现在该店每平台各 2 个 ID;其 CRM 目标记录仍挂在原 tb 1349330884(目标 980、扣点 1%、开始 2026-09-11),不受影响。
注册表条目格式:{"store_name","plat_tag","plat_id","opened_date","closed_date"?,"closed"};仅当门店名存在于飞书门店表时才会生效。
附带发现:本地库 与飞书仍有 11 条平台新增 + 3 条 opened_date 更新未同步(山丹路店、易县店等,与本次无关);服务器 已无其它差异。需要时可在「飞书表格同步」页一次性应用。
十、新增用户身份「督导」(n:1 大区)+ 独立督导表 + 门店督导改为关联
数据模型 :新增 supervisor_info(id, supervisor_name, big_region_id, remark, …)(db/init/003_supervisor.sql,幂等可重复执行);store_info 新增 supervisor_id 关联督导(旧 supervisor 文本列保留但不再写入 );sys_user 新增 supervisor_id(督导账号绑定督导记录)。迁移按「(督导姓名, 门店所在大区)」自动生成 11 条 督导记录、回填 392 家门店(65 家无督导留空,跨大区同名允许、同一大区内唯一)。
ID 口径 :SP + upper(md5('姓名|大区名')[:10])(SQL 与 commonlib.ids.supervisor_id 完全一致)。
新角色 :supervisor(督导,级别 1,与运营同级):网关 scope=read,write;登录 JWT/响应带 supervisor_id;网关透传 X-User-Supervisor;用户管理可创建/编辑督导账号(必须绑定督导记录 ,自动带出所属大区;大区经理只能建/改本大区督导账号);/users/backfill 会为每个督导补建 sp_<督导ID> 账号(默认密码 123456)——本次本地与服务器各创建 11 个 账号。
服务端范围强制 (前端参数无法绕过):operation 查询/汇总(build_where 强制加 s.supervisor_id=%s)、门店列表与计数(hierarchy)、CRM 关注(overview/achieved/near)、报表(日报/周报/推广/月度收入,新增 services/report/app/scoping.py)。
督导管理 :hierarchy 新增 /supervisors 全套接口(列表/详情/增/改/删/批量删/导出;列表附带 store_count);同一大区内姓名唯一、跨大区可同名、名下有门店禁止删除、大区经理只能维护本大区(403)。
审批 :新增 supervisor 链路(同运营:大区经理 → BOSS);可提交 门店/平台/CRM;范围校验为「本人名下门店 」;督导新建门店自动把 supervisor_id 置为本人,且门店区域必须在本大区。
前端 :菜单新增「督导管理」(大区经理及以上);新增 views/manage/SupervisorManage.vue;门店管理「督导」由输入框改为按大区过滤的下拉 并新增「按督导筛选」;用户管理新增「绑定督导」;审批详情显示督导姓名;「我的区域」对督导显示为「我的门店 」;roles/types/api/router 同步。
飞书同步 :飞书「门店信息表」C 列仍是督导姓名 ;同步时按「(姓名 + 门店大区)」解析为 supervisor_id,缺失的督导自动新建 (大区取该门店所在大区);门店快照改用 COALESCE(sup.supervisor_name, s.supervisor) 取值以便正确比对;若某新门店暂时无法定位大区(region 尚未回填),则不关联督导并记录告警 ,待下次同步带上大区后再自动关联(不阻塞整批同步)。
验证(本地) :/supervisors 11 条;CRUD/改名/跨大区同名/删除保护/大区经理范围均符合预期;/stores?supervisor_id=… 40 家且带姓名;督导登录后 /stores=40(BOSS=457)、/stats/count=40、/op/stats/daily 按督导=1 行(BOSS=12 行)、/crm/overview=9(BOSS=99)、/reports/monthly-income=1 个大区(BOSS=5)、周报门店明细 35 行(BOSS=362 行);审批:提交本人门店 200 → 大区经理 → BOSS「执行成功」并回放生效(测试值已还原)、提交同大区他人门店 403「只能操作本人名下的督导门店」、新建门店 payload 自动注入本人 supervisor_id;页面实测:督导管理 11 行、我的门店显示 身份/督导/所属大区、门店管理 20 行(本人 40 家)、CRM 9 行,无 console 报错 。
验证(服务器) :迁移得到 11 条督导 / 392 家门店关联、11 个 sp_* 账号;督导登录后范围校验全部通过(stores 40、op 1 行、CRM 9 行、monthly-income 1 个大区、/supervisors 11);越权提交被 403 拦截且测试审批单已撤回 (未改动生产数据 );前端资源已同步(SupervisorManage-9yajrffg.js)。
2026-09-24
一、门店管理新增「导出全年运营」(列名 / 空值 / 汇总口径调整)
功能 :门店管理新增绿色「导出全年运营」按钮;弹窗可选信息列(大区/区域/门店名/门店ID/门店属性/营业状态/开店日期/闭店日期/督导/省份/城市/区县/门店编码/门店类型/平台门店名/详细地址,支持「全选」),导出 2月~次年1月每月 营收/目标/进度差 + 年度 营收/目标/进度差 ,最后一行为汇总 。
列名 :原「xx月完成度 / 年完成度」统一改为 「xx月进度差 / 年进度差」 ,口径不变:进度差 =(营业额 − 目标)/ 目标。
空值与目标为 0 的规则 :所有数值空值以 0 补充(营业窗口 [开店日期, 闭店日期) 之外的月份也写 0,不再留空);目标 = 0 时:收入 = 0 记 0% ,收入 ≠ 0 记 100% 。
汇总行目标口径 :汇总行目标改为与看板 同源(/gmv/summary 大区口径,含红线对闭店 GMV 的再分配);门店行仍按各店营业窗口口径(两者不同,汇总行对齐看板)。范围规则:整大区/全国全部选中 → 用大区级口径;仅部分门店(按区域/名称/状态等筛选)→ 退化为所选门店年度目标之和。
格式 :进度差单元格带 0 居中数据条(负红正蓝),自适应列宽,汇总行加粗。
验证 :全国汇总年度目标 160,342,620.05 与看板一致;华南大区 29,426,582.51 一致;全国存量 137,815,571.77 、增量 22,527,048.29 均与看板一致。本地与服务器均已发版(StoreManage-NORgpx1M.js → StoreManage-Bxvu9LFt.js)。
二、大区 / 督导新增「采购额目标系数」并入库
字段 :big_region_info、supervisor_info 各新增 purchase_target_ratio DECIMAL(20,15),中文名「采购额目标系数」;与原有「采销比」purchase_sales_rate 独立并存 。
入库 :5 个大区 —— 晋冀 0.431766910608739、北方 0.449173701519684、华南 0.386895272830646、外阜 0.44313831936354、京津沪 0.358291395503057;督导 15 条 —— 已有 11 位按各自大区系数更新,另新建「晋冀其他 / 北方其他 / 外阜其他 / 华南其他」4 条(ID 口径 SP + md5(姓名|大区名)[:10])。
界面 :大区管理、督导管理新增该列与可编辑输入(0~1,15 位小数),导出列同步;新装初始化 db/init/001_init_pgsql.sql、db/init/003_supervisor.sql 同步,迁移 db/migrate_purchase_target_ratio.sql 幂等可重复执行。
验证 :本地与服务器逐行系数完全一致;PUT /supervisors/{id}、PUT /big-regions/{id} 往返写入生效(测试值已还原);双端页面均含「采购额目标系数」。
三、GMV 修复:红线关店数额度未扣减(超红线闭店门店 GMV 为 0)
问题 :存量门店闭店 GMV 默认记在「闭店(closing)」,只有大区红线用尽(red_line_close<=0 或红线 GMV<=0)才转回该店「在营」;移植时把 rlc -= 1(红线关店数额度 )只写进了 else 分支,导致「红线 GMV 足够覆盖闭店 GMV」时额度从不递减 ,本该判为「超过红线」的门店仍被全额抵扣,闭店后月份 GMV 为 0。
修复 :services/gmv/app/service.py 的 elif 分支补 rlc -= 1,与参考实现 backend_new/service/gmv_service.py 一致;重建 gmv 镜像并本地 + 服务器部署。
影响门店 :华南大区 抖喜(岗顶店) (第 6 家闭店,red_line_close=5)。修复后门店年度 GMV 370,893.32 → 845,991.62 ,闭店后月份(8月~次年1月)目标恢复非 0;华南红线余额 0 → 225,117.20 、now_close_gmv 25,406,019.35 → 25,180,902.15 ;华南年度总/存量不变,其余大区不变。
验证 :本地与服务器 /gmv/summary 逐大区字段 0 差异;岗顶店月度目标双端一致。
四、每日数据推送飞书电子表格(按月配置链接 / 表ID / 列字段)
入口 :「每日数据上传」页新增「飞书每日数据推送」卡片;「数据处理入库」区新增「推送到飞书表格」按钮与「入库后推送飞书」勾选;并支持按日期 / 日期范围批量推送(最多 60 天)。
数据口径 :按「门店×日」宽表(一行 = 日期 × 门店),三平台(美团 / 淘宝闪购 / 京东)拆列;来源 operation_data_{年}_{月},字段含 门店ID / 门店名称 / 大区 / 区域 / 督导 / 省份 / 城市、各平台ID、总收入 / 总单量、各平台 收入 / 单量 / 外卖收入 / 外卖单量 / 拼好饭(仅美团) / 曝光人数 / 入店人数 / 进店转化率 / 下单转化率 / 评分 / 差评数,以及派生字段 单均收入、各平台客单价、前日单量、前日收入、单量增长比、收入增长比 ;同门店同平台多条按 金额 / 单量 / 曝光 / 差评 求和,转化率与评分按单量加权(无单量取均值)。
配置 :按月存 sys_config 的 feishu.push.<YYYY-MM> = {link, sheet_id, columns, enabled};columns 每项为「目标列字母 + 目标列名 + 来源字段」,可跳列 / 留空 (留空按顺序补),第一列固定 A = static_date;界面提供「套用『每日数据源』预设 」(A..AM)。
写入 :只写配置的目标列 (未配置的列不触碰,避免误清);按 static_date 原位覆盖 该日期的行块并保持整表按日期有序:行数相同原位改写、变少则清掉多余行、变多则用飞书「插入行列」补行;新增日期按日期顺序插到合适位置;超出工作表网格时用「增加行列」扩容;只写数据行、不写表头。
门店范围 :推送卡片新增复选框「推送当天全部有数据的门店 」,默认不勾选 ——只推 static_date 落在门店 [开店时间, 闭店时间) 内的门店;勾选后推当天有数据的全部门店 (含已闭店 / 未开店)。已验证 2026-09-20:不勾选 370 家、勾选 409 家。
与「汇总页 / 全国页 / 概览页」对齐 :公式链为 概览页 → 全国所有门店 → 三平台汇总 → 每日数据源 (整列 SUMIF / VLOOKUP,写入后自动重算)。「每日数据源」被引用的列位固定:D=美团ID、E=饿了么ID、F=京东ID;N=美团外卖收入、O=美团外卖单量、P=拼好饭收入、Q=拼好饭单量;X=饿了么收入、Y=饿了么单量;AF=京东收入、AG=京东单量 (已用真实值逐列验证)。用「套用『每日数据源』预设」即按此对齐;汇总为月度累计 口径(SUMIF 无日期条件)。注意概览页「GMV目标」来自 存量目标源 / 存量数据明细,不随每日数据源更新。
后端 :sync 服务新增 GET /sync/push-daily/meta(字段目录 + 各月配置 + 预设)、PUT /sync/push-daily/config、POST /sync/push-daily/preview、POST /sync/push-daily/run(经网关 /sync,仅管理员)。
验证 :本地与服务器均已发版(sync e44c1f5fe66b、前端 UploadV2-ZLGX8duv.js);临时测试表验证:空表追加、等行覆盖(无重复)、扩容插入、收缩清行、乱序新增日期按序插入、多日推送,以及按目标列字母跳列写入 (A..AM 预设:D/E/F、N/O/P/Q、X/Y、AF/AG 全部正确,AN..AP 未触碰)。
2026-09-28
一、采购数据模块(按月分表 + 拼拼云门店映射 + 上传入库 + 对外 CRUD)
数据模型 :新建采购明细表,按月分表 purchase_data_YYYY_MM(如 purchase_data_2026_08),共 36 个业务字段 :订货单号 / 所属仓库 / 货主 / 货主编码 / 支付时间 / 收货人 / OMS门店编码 / 商品名称 / 商品分类 / 商品规格 / 单位 / 订货数量 / 销售单价(元) / 金额(元) / 出库状态 / 出库数量 / 发货状态 / 发货数量 / 退货数量 / 完结类型 / 来源 / 订货备注 / 自定义单号 / OMS门店订单号 / 出库单号 / 发货单号 / 商品ID / 商品编码 / 自定义编码 / 联系人 / 联系方式 / 地区 / 收货地址 / 收货人分组 / 配送方式 / 运费;另有 store_id(关联门店,可空)、static_date(= 支付时间日期)、逻辑删除 deleted 与创建/更新时间。
去重键 :(订货单号, 收货人, 货主, 支付时间, 商品编码) 的活动行唯一(WHERE deleted=0 的部分唯一索引),重复数据按该键幂等覆盖 (upsert),不产生重复行。
门店关联 :新建映射表 pinpinyun_store_map(拼拼云门店名 ↔ 门店 ),pinpinyun_name 唯一、store_id 可重复(n:1 ),支持备注;启动时从 store_info.pinpinyun_name 回填 (本地 456 条)。上传时以「收货人」按精确 / 归一化(全半角括号、空白等) 匹配拼拼云门店名得到 store_id,匹配不到则该行仍入库但 store_id 为空,并在预览中列出未匹配收货人 。2026-10-09 起 :映射表里「已登记但门店为空」的拼拼云名不再遮蔽 store_info.pinpinyun_name 的回退——只要门店档案里有同名拼拼云名,仍会自动关联到该门店并把历史行回填 store_id(修复「门店采购额一直是 0」)。
对外 CRUD 接口 (经网关 /purchase,需 read/write):GET /purchase/col-meta(列定义)、GET /purchase/tables(分表与行数)、POST /purchase/tables/{年}/{月}(建/补表并顺带加宽列宽)、POST /purchase/query(跨月 分页查询,支持日期区间 / 门店 / 是否已关联 / 订货单号 / 收货人 / 仓库 / 货主 / 商品编码 / 状态 / 来源 / 关键词 / 排序)、GET /purchase/{id}(详情)、POST /purchase(新增/覆盖,返回记录 id )、PUT /purchase/{id}(更新)、POST /purchase/delete(按 ids 或筛选条件逻辑删除)。
映射 CRUD :GET /purchase/map/list(含门店名 / 区域 / 大区)、POST /purchase/map(新增/覆盖)、PUT /purchase/map/{id}、DELETE /purchase/map/{id}、POST /purchase/map/seed(从门店表回填)。
上传入库 :「每日数据上传」页新增「采购数据上传 」卡片:选择日期范围 (按支付时间过滤)与采购明细 Excel(默认工作表「列表明细合并」),点「开始处理」→ 预览:按去重键与库内比对,仅比对数字字段 (订货数量 / 销售单价 / 金额 / 出库数量 / 发货数量 / 退货数量 / 运费),列出新增 / 修改 (含每字段旧值→新值)与未匹配收货人;勾选后点「入库」,调用内部接口 POST /internal/purchase/apply 写入对应月份分表(幂等 upsert)。不做阻断 :匹配不到门店、字段异常等一律照常入库。
跨月处理与自动建表 :采购上传不再限制 60 天 ——选择跨月范围时,后端按文件内实际出现的自然月逐月处理并合并结果 (单月窗口 ≤31 天),预览汇总新增 months 与 per_month(每月 行数/新增/修改)明细;入库按支付月份分组、组内每 5000 行分片 提交,数据库缺失的月份自动创建分表 后再写入(如一次上传 2026-02~08 会补齐 02~07 六个月表)。
列宽与健壮性 :发货单号 / 出库单号 / 自定义单号 / OMS门店订单号 / 自定义编码 等拼接类字段已加宽(发货单号 VARCHAR(2000)),并在建表/补表时对历史表执行幂等 ALTER 加宽 ,避免整块数据因单字段超长而写入失败。
验证(本地 + 服务器) :导入《2026.8月份采购数据.xlsx》「列表明细合并」7873 行全部入库 (purchase_data_2026_08 行数 7873),其中已关联门店 7769 行、未匹配收货人 9 个;CRUD 全链路(新增→详情→更新→删除→查询,新增返回 id)与映射 CRUD 均通过,删除后活动行数回到 7873。本地与服务器均已发版(operation 4bf0e632d68d、pipeline 545e1ce5d859、gateway ce603d427d3d、frontend aba683ecffb1);服务器 /upload/purchase/range 复核 8 月文件:解析 7873 行、新增 0 / 修改 0(幂等)、匹配 7769、未匹配 9,前端资源含「采购数据上传」。
验证(跨月 2026.2-8月) :一次上传《2026.2-8月采购数据.xlsx》「列表明细合并」共 40149 行 、跨 7 个自然月:2026-02 3271 、03 4828 、04 5590 、05 5578 、06 6129 、07 6880 、08 7873 ;其中 08 月已存在(0 新增 / 0 修改),其余 32276 行 全部新增,自动创建 purchase_data_2026_02..07 六张月表并使 purchase_data_% 共 7 张、合计 40149 行(关联门店 39852 行、未匹配收货人 9 个);本地与服务器行数逐月一致。
二、特殊拼拼云门店注册表(门店更名旧名)+ 特殊平台门店可视化维护
背景 :门店更名后,历史采购数据里的「收货人」仍是旧拼拼云门店名 ,旧数据无法再按门店关联/查询。
注册表文件 :/data/sync/special_pinpinyun.json(仿 special_plats.json),JSON 数组,条目仅需 store_name(门店名)与 pinpinyun_name(旧拼拼云门店名)两个字段 ;去重键为 pinpinyun_name,n:1(多个旧名可指向同一门店)。
接口 (经网关 /sync,仅管理员):GET /sync/special-pinpinyun(列表,附解析出的 store_id 与文件路径)、POST /sync/special-pinpinyun({items:[{store_name,pinpinyun_name}], action:add|remove})。
生效方式 :登记时立即把「旧名 → store_id」写入 pinpinyun_store_map(operation 的采购解析、/purchase/map/list、上传预览自动命中),并回填历史 purchase_data_* 中 store_id IS NULL 且收货人=旧名的行;移除时软删该旧名映射(不会误删门店当前 pinpinyun_name)。
同步联动 :/sync/apply(飞书同步)执行后会读取该文件 并同步映射 + 回填,返回体新增 pinpinyun_registry 统计(mapped/backfilled/unmatched)。
前端管理入口 :「每日数据上传」页新增「特殊门店注册表 」卡片,两个页签:特殊平台门店 (列表 + 门店名/平台ID 加入 + 移除,含开业/闭店日期与状态)与特殊拼拼云门店 (列表 + 门店名/旧拼拼云名 加入 + 移除,显示解析到的门店ID)。
验证(本地) :新增一条测试映射(抖喜(首经贸店) ← __测试旧名2__)→ mapped=1、backfilled=1,/purchase/query 该行 store_id 由空变为 SSCBE6F1DECF、/purchase/map/list 命中;移除 → map_deleted=1;/sync/special-plats 列表 52 条、增删校验(非法项返回 skipped)均正常;测试数据已清理。
三、ID信息表新增门店时自动关联拼拼云门店列表
触发时机 :飞书同步 /sync/apply 检测到新增门店 (store op=add,即实际提交的 payload.stores.adds)时自动执行;/sync/init 全量初始化时对全部门店执行。
规则 :用新店在 ID信息表 F 列「拼拼云门店名称」 (即 store_info.pinpinyun_name)检查「拼拼云门店列表」pinpinyun_store_map:
列表没有 该拼拼云门店名 → 新增 一条映射(关联到该新门店);
列表已有且绑定本店 → 视为已关联 ;
列表已有但绑定的是别的门店 → 不覆盖 ,记为冲突 并在同步结果中提示;
该店 F 列为空 → 跳过 并标记「缺拼拼云门店名」(等补全后下次同步自动补上)。
返回与提示 :/sync/apply、/sync/init 返回体新增 store_map(total/added/linked/conflicts/missing_name);「同步飞书表格」完成提示追加「新增拼拼云关联 N 家 / 已有关联 N 家 / 缺拼拼云门店名 N 家 / 同名冲突 N 家(未覆盖)」,出现冲突时弹警告,需人工到采购映射核对。
验证(本地) :取两家真实门店 + 临时拼拼云名逐项验证——新增 → added=1;再次执行同店同名 → linked=1;换另一家门店用同名 → conflicts=1(不覆盖);空名 → missing_name=1;测试映射已软删清理(活动行 0)。
四、修复「大量门店无开业日期」(存量门店 opened_date 默认值回归)
现象 :store_info 458 家中 343 家无 opened_date——stock 327 家中 325 家为空、increment 131 家中 18 家为空;plat_info 1228 条中仅 324 条有开店时间。
根因 :
飞书「开业时间表」new_store_opened_date.xlsx 只覆盖约 114~116 行 (新店/增量),存量门店根本不在表里;
移植到 sync/app/engine.py 时,aggregate() 的 od() 对「开业表无此店」返回 None,丢掉了参考实现 backend_new/service/info_service.py 与 sql_init3.py 的默认值:开业表无此店时存量门店 opened_date=2026-01-31、增量门店留空 ;平台开店时间应回退为门店开店时间;
叠加现有 diff 对存量门店故意忽略 opened_date(2026-09-15 为让闭店日期能写入),存量门店之后再也不会被更新,于是长期为空。
修复 :engine.aggregate 恢复「存量缺失→2026-01-31、增量留空」,且门店不在开业表时其平台 opened_date 回退为门店 opened_date;一次性回填 :store_info 存量 NULL→2026-01-31(325 行)、plat_info 存量门店平台 NULL→该门店 opened_date(895 行);增量 18 家保持留空等开业表补录。
验证(本地 + 服务器) :回填后本地 store_info 存量 327/327 有开业日期、plat_info 1219/1228 (仅剩 9 条增量平台为空);/gmv/summary 五大区逐字段 0 差异 (回填不影响 GMV);服务器执行同一回填并核对一致。
五、商品列表(统计口径):采购商品去重 + is_static/start_static + org_name
新表 :product_list(operation 库)——id、product_name(去重键)、org_name、product_spec、unit、product_category、product_code(取该商品最新出现月份的编码)、is_static(0=不计入统计 / 1=计入统计,默认 1)、start_static(仅统计该日期及之后的采购数据,默认 2026-01-31;is_static=0 时为空)、deleted 与创建/更新时间。
org_name :商品名遇到任一 ( ( 【 [ 即截断并去首尾空格(如「调理鸡肉片(抖喜定制,1千克*10包/箱)」→「调理鸡肉片」),用于搜索与索引。
去重入库 :遍历 purchase_data_*(升序),按 product_name 去重并取最新月份 的编码/规格/单位/分类;已存在只更新描述字段,保留 已设置的 is_static/start_static。operation 启动自动执行,POST /product/seed 可手动重跑。
改动即时生效(2026-10-09) :切换 is_static / 修改 start_static 后,PUT /product/{pid} 会自动调用 purchase_stats.recompute_all() 重算所有采购分表对应的月度物化 (约 5 秒,返回 recomputed.months);批量入口同样自动重算一次。此前只在「上传采购数据」时重算,所以在商品列表里取消勾选后采购额仍是旧值(看上去像「不生效」)。
名称清单 :POST /product/preview-names(xlsx,列 商品名称/商品规格/单位)先按商品名精确匹配 ;未命中项返回同 org_name 的候选 交前端人工选择;POST /product/apply-names 把指定商品置 is_static=0(start_static 清空)。
对外接口 (网关 /product):GET /product/meta、POST /product/query、GET /product/{id}、PUT /product/{id}、POST /product/seed、POST /product/preview-names、POST /product/apply-names。
今后新增商品自动补 :采购入库 POST /internal/purchase/apply 成功后自动把新商品补进列表(默认 is_static=1、start_static=2026-01-31)。
前端 :「每日数据上传」页新增「商品列表(统计口径) 」卡片:查询/分页、切换是否计入统计、编辑开始统计时间、一键「从采购数据去重入库」、上传名称清单预览并对未命中项选择同 org_name 候选后确认置 0。
本次数据(本地 + 服务器) :库内去重 76 个商品;上传《2026.9.28抖喜名称清单.xlsx》42 条 → 41 条精确命中 置 is_static=0(start_static 清空),1 条未命中(抖喜定制豆花布丁粉(下单后3-5天到货)1,库内无同名)已在前端给出同 org_name 候选供人工确认;最终 35 计入 / 41 不计入 。
六、商品列表增强:新品按财年自动入库 + 名称清单交互式处置
财年口径 :商品自动入库的 start_static 改为动态计算 ——取「当前财年第一天(2/1)的前一天」:现为 2026-01-31,2027-02-01 起自动变为 2027-01-31;已有商品不受财年切换影响 (保留入库时的值)。采购入库检测到新品仍自动补进列表(is_static=1)。
名称清单交互 :上传清单预览分两类交由用户处置——
库中已存在 :默认全部勾选=排除 (is_static=0),可逐条取消不想排除的;
库中不存在 :每条选择「直接添加为新商品 」或「选同 org_name 下的已有品类 」,不选=不处理。
记录(落库) :POST /product/apply-decisions,body {exclude:[已有商品名], add:[{product_name,product_spec,unit}]}——exclude 置 is_static=0、start_static 清空;add 新建商品行(org_name 自动计算,编码/分类留空)并置 is_static=0、start_static 空;返回 {excluded, added}。
前端 :商品列表卡片预览新增「已存在」勾选表与「库中不存在」处理方式下拉(直接添加 / 同 org_name 品类),底部「确认并记录」并显示将排除/新增数量。
验证(本地) :apply-decisions 新增 → 新行 org_name 正确、is_static=0、start_static 空;排除 → 已有商品置 0;GET /product/meta 的 start_default=2026-01-31;测试数据已清理,现状 76 个商品(35 计入 / 41 不计入)。
七、忽略品表格处理:只显示与库内不一致的项,交用户判断
双向差异 :上传《名称清单》后,与库内 product_list 比对,只返回不一致项 交用户判断:
① to_exclude:清单里有、库里尚未排除 (is_static=1) → 勾选=排除(默认全选,可取消);
② to_add:清单里有、库里没有 → 「直接添加为新商品」或「选同 org_name 下的已有品类」;
③ extra_excluded:库里已排除 (is_static=0)、本次清单没有 → 「重新计入统计」或「保持排除」(默认保持);
已一致 (清单有且库里已排除)只计数、不显示。
落库 :POST /product/apply-decisions 增加 reinclude 字段——exclude 置 0、add 新建并置 0、reinclude 置 1(start_static=财年前一天);返回 {excluded, added, reincluded}。
前端 :预览仅展示①②③三张差异表(①勾选排除、②直接添加/同 org_name 品类、③重新计入/保持排除),已一致的不显示;底部「确认并记录」显示将排除/新增/重新计入数量。
验证(本地 + 服务器) :用上次清单复核 → total=42、to_exclude=0、extra=0;服务器已在前端把未命中的 抖喜定制豆花布丁粉(下单后3-5天到货)1 直接添加为不计入商品(故该端 to_add=0、already=42),本地已同步该行;reinclude 往返(置 1 得 start_static=2026-01-31、再排除置 0)正确;现状双端 77 个(35 计入 / 42 不计入) 。
八、大区年度配置表 big_region_yearly_config(抽离 6 字段 + 月度计划)
新表 :big_region_yearly_config——id、big_region_id、cfg_year、cfg_name(varchar 50)、cfg_value(text,字符串存值)、cfg_type(varchar 20:int/float/bool/str/list/dict)、deleted 与时间戳;唯一键 (big_region_id, cfg_year, cfg_name) WHERE deleted=0。
迁移 (db/migrate_big_region_yearly_config.sql,幂等):big_region_info 的 increase_base / red_line_gmv / stock_gmv / purchase_sales_rate / purchase_target_ratio(cfg_type=float)与 red_line_close(int)→ cfg_year=2026;big_region_monthly_plan → gmv_plan_rate(按财年 聚合为 12 元素 list,顺序 [2,3,…,12,次年1月],元素为原精度字符串)。
读取切换 :gmv(base / 红线 / 存量 / 计划占比)、hierarchy 大区详情与列表、report /reports/org-gmv、pipeline 初始化 total 全部改从新表读取;旧列与旧表保留但停用 。
写入切换 :hierarchy 大区新增/更新、gmv /plans(对 gmv_plan_rate 列表读改写)、pipeline total 补齐均写新表;/plans 与 GET/PUT /big-regions/{id} 接口形状保持不变。
接口 :GET/PUT /big-regions/{big_region_id}/yearly-config(按 cfg_year 读/写 key-value)。
验证(本地,服务器暂未改动仅只读比对) :迁移得 5 大区 × 7 项 = 35 行;gmv_plan_rate 与旧月度计划逐值一致;/gmv/summary 重构前后逐字段 0 差异 ;大区 PUT 只改配置、旧列不变;/plans 返回 12 行、更新 2 月正确写回列表;本地新表 vs 服务器旧列/旧表 35 键 0 差异 。
九、门店/平台同步 + 大区年度配置改造上线服务器 + GMV 逐月校验
本地同步新门店 :把服务器 2026-09-27 飞书缓存复制到本地后执行 /sync/apply——新增门店 2 (赵县店 / 环县店)、更新门店 2(中牟店 / 朝阳山路店)、新增平台 5 、更新平台 4;本地门店 458→460 、平台 1228→1233 ,与服务器一致。
校验(同步后,本地新结构 vs 服务器旧结构) :大区年度配置 35 键 0 差异 ;GMV 存量逐月 0 差异 、增量逐月 0 差异 (此前 9 月起的增量差异已由门店/平台同步消除)。
上线(服务器) :发布 gmv / hierarchy / report / pipeline 镜像(gmv a6f5bc76d763、hierarchy 4cd34fcb5998、report 5534f1dcc42c、pipeline 864db596a52f),并执行迁移 db/migrate_big_region_yearly_config.sql(5 大区 × 7 项 = 35 行)。
上线后校验(本地 vs 服务器,均为新结构) :GMV 逐月(存量 + 增量)0 差异 、大区年度配置 35 键 0 差异 ;/big-regions、/plans、/big-regions/{id}/yearly-config、/reports/org-gmv 均正常。
十、服务器电池/电源实时监控(采集器每秒上报 → 系统配置页每秒展示)
采集器(服务器 systemd 常驻) :新增 gmvsys-battery-report.service(脚本 /usr/local/bin/gmvsys-battery-report.sh),每秒 读取 /sys/class/power_supply/BAT0(电池)与 ADP1(市电),POST 到 http://127.0.0.1:8080/api/battery/report(nginx:8080 → 网关);开机自启 ,异常自动重启。
接收与存储 :网关新增 POST /battery/report(需共享密钥头 X-Battery-Key)与 GET /battery/status;数据写入共享表 server_battery_status(单行 id=current),以兼容网关多 worker;/status 返回最近上报及 online(距最近上报 ≤ 5 秒判在线)。
前端展示 :「系统配置」页(ConfigManage.vue)顶部新增「服务器电源 / 电池监控 」卡片,每秒轮询 /api/battery/status,显示:采集时间 / 供电来源(市电|电池)/ 电池状态(充电|放电|已满)/ 电量% / 功率W / 满电Wh / 设计Wh / 健康% / 剩余或充满时长 / 采集器在线(离线置灰)。
部署 :网关与前端镜像发布本地 + 服务器,并执行迁移 db/migrate_server_battery_status.sql(新装见 db/init/001_init_pgsql.sql);采集器仅在服务器安装并启用。
验证(服务器) :systemctl is-active gmvsys-battery-report = active;/battery/status 每秒更新(实测 Charging、21%、23.3W、满电 43.3Wh / 设计 56.16Wh、健康 77%);前端资源含该卡片(ConfigManage-C1hS_j3o.js)。
十一、京东单店导出缺列致京东整天未入库 + 上传文件 OLE2(.xls) 安全转 xlsx
问题 :2026-09-28 正常上传京东评分(score)/差评(remark)后,日报「京东」8 列(收入/单量/客单价/曝光人数/进店转化/下单转化/差评/评分)全为 0。经比对,score/remark 文件本身与上传件 sha256 完全一致 (904bb9a3… / 01b0f6a1…),并未被清空;真正原因是同日上传的 京东单店 jd_sig 导出模板由 10 列变为 8 列 ,去掉了「曝光人数 / 入店转化率(人数) / 下单转化率(人数)」,preprocess_one 在 df[want] 处 KeyError,导致整个京东平台合并中断、京东一行未入库(operation_data_2026_09 09-28 只有 mt 679 / tb 420,缺 jd)。
修复(pipeline) :cfg.py 中 jd.sig 增加 optional=["exposure","entry_rate","order_rate"]、mt.sig 增加 ["exposure","entry_rate","order_rate","score"];service.py 新增 _pick(),sig 合并取值缺列按 0 ;_read_file 按文件头识别 OLE2 并显式用 xlrd 读取。
修复(上传) :upload_api.py 新增 _safe_xlsx()——上传内容若是老式 OLE2 .xls (京东常把这种内容命名为 .xls,系统按固定名存成 .xlsx),则逐 sheet 转成真正的 xlsx 再落盘;转换后比对 sheet 名与行列数,全部一致才替换,异常保留原字节。
数据修复(服务器) :raw 下 42 个 OLE2 文件(09-08~09-28 京东 score/remark)安全转换为真 xlsx(备份 /data/backup/raw_xls2xlsx_260929.012554.tar.gz,失败 0);重放 09-28 京东(POST /upload/replay {platforms:["jd"], mode:"patch"})补入 513 行;另重放 09-12~09-14 京东(patch 更新 1524 行 ),修复此前写入的全 0 评分(现评分非空 357/357/358)。
验证(本地 + 服务器) :09-28 京东 513 行、评分非空 366 、差评 10 ;重生成日报 09-28「京东」各列有值(收入合计 95076.0、单量 7678、评分合计 1464.25);pipeline 镜像本地 = 服务器 a4e39667…;本地 raw 16 个 OLE2 文件同样全部转换。
部署 :pipeline 镜像发布本地 + 服务器,服务器旧镜像回滚标签 gmvsys-pipeline:bak.260929.092451。
十二、采购额模块(备注前缀 + 品类映射 + 月度物化 + 采购额页)
统计口径 :白名单商品(is_static=1 且 支付日 ≥ start_static);下错单(备注含 错单:)整单排除;换货/退单(备注含 换货:/退单:)该行不单独计;退货冲减(实际数量 = 订货数量 − 退货数量,实际金额 = 销售单价 × 实际数量);未匹配门店单列。
备注规范化 :2~8 月旧备注按关键词补前缀(含"错"→错单:,含"换/补"→换货:),本地 + 服务器各 30 行;8 月起新数据统一写 退单:/换货:/错单:。
品类映射 :product_list 新增 static_category(餐盒/餐具包/无纺布袋/米粉/酱料/粉条/其它),77 个商品已归类,可在商品列表页修改。
月度物化 :新增 purchase_monthly_stats / purchase_monthly_category(db/migrate_purchase_stats.sql);采购上传后自动重算;2~8 月已物化(2026-02 3,087,298 → 2026-08 6,167,817.60)。
接口 :POST /purchase/summary(门店/督导/区域/大区 × 年/月,含收入与采销比、大区目标与达成率)、POST /purchase/store-amounts、POST /purchase/recompute。
目标 / 采销比 :采购额目标 = 该大区该月 GMV(/gmv/summary 口径:财月增量 + 存量)× 大区 purchase_target_ratio;采销比 = 采购额 ÷ 同月同门店收入(operation_data.income,按 opened_date/closed_date 过滤,与日报一致)。
前端 :新增「采购额」页(督导/区域/大区分页 + 年月筛选 + 合计行);门店管理新增「采购额」列(选中月)。
验证(本地 + 服务器) :2026-08 采购额 6,167,817.60、收入 13,730,501.42、目标 6,815,351.44;大区采销比 0.41~0.48。
部署 :operation / frontend 镜像发布双端(服务器回滚标签 gmvsys-operation:bak.260929.111822、gmvsys-frontend:bak.260929.111822)。
十三、门店管理「导出全年采购」
入口 :门店管理页「导出全年采购」(与「导出全年运营」并列,复用信息列勾选弹窗)。
列 :所选信息列(与运营导出一致)+ 财年 2月~次年1月每月 采购额 / 营业额 / 采销比 / 目标 / 完成差 + 年度汇总列(年度采购额/营业额/采销比/目标/完成差);最后一行为汇总行 。
口径 :采购额取 purchase_monthly_stats(白名单、错单/换货/退单、退货冲减后的实际金额);营业额=同月同门店收入(与日报一致,按开闭店窗口);采销比=采购额÷营业额;目标=门店该月 GMV 目标 × 该大区 purchase_target_ratio;完成差=(采购额−目标)/目标(目标=0 时采购额=0 记 0%、≠0 记 100%);空值/窗口外月份以 0 补充。
未关联门店(2026-10-09 起) :未匹配到门店的采购额不再隐藏 ——导出时按拼拼云门店名 追加行(门店名=拼拼云名、状态=「未关联门店」,每月采购额照常列出,营业额/目标/完成差为 0),并计入最后一行汇总;这些名字同时登记进拼拼云门店映射表(未绑定),待飞书 ID 信息表补建门店后自动关联(也可用 POST /purchase/re-resolve 手动一键回填 + 重算)。
接口 :POST /purchase/store-yearly(门店 12 个月采购额)、POST /purchase/unmatched-yearly(未匹配门店按拼拼云名 × 12 个月)。
验证 :本地=服务器;示例门店 2026 财年采购额 [13072,10167,14785,13296,15892,11794,20892,0,0,0,0,0]。
十四、日报「评分」改为取非零最大值(修复导出出现 2.x)
问题 :门店明细的「美团/淘宝闪购/京东评分」导出出现 2.x 。原因:同一门店同一平台可能存在多条平台账号行(其中一条无评分 = 0),日报按行平均 (sum/n)计算,把 0 与真实评分平均后约为真实值的一半。
修复 :评分改为取非零评分的最大值 (0/空视为无评分、不参与);门店级 = 该店各行的最高分;大区/区域/总计 = 多门店里的最高分(不再按曝光加权平均);Excel 总计行公式同步改为 =IF(COUNTIF(区间,">0")=0,0,MAX(区间))。
附带 :低分门店数(xx评分低于 4.7/4.8 门店数)同步改为「按门店取非零最高分 < 阈值」才计,避免 0 分账号被误判为低分。
验证(本地 + 服务器) :国贸店 美团 4.5 / 淘宝闪购 4.6 / 京东 4.4、下沙店 京东 4.5、周口五一广场 淘宝闪购 4.8(修复前为 2.x);总计行 4.9 / 5.0 / 5.0。
部署 :report 镜像双端发布(回滚标签 gmvsys-report:bak.260929.172758)。
十五、主面板「月度累计进度趋势」新增 累计/明细 切换
改动 :卡片标题右侧新增 累计 / 明细 切换按钮,默认明细 (不添加额外注释)。
口径 :明细=每日实际营收(与当日目标对比);累计=当月 1 号至当日的加和(与累计目标对比)。与页面既有「实际值 / 百分比」显示切换相互独立、可叠加。
验证 :前端本地构建通过,frontend 镜像双端一致(回滚标签 gmvsys-frontend:bak.260929.173335)。
十六、拼拼云门店映射:金科城店旧名登记(修复「无门店」采购额)
问题 :抖喜(金科城店) 2~8 月采购额在系统里全部落到 store_id 为空的行(2~7 月约 7.07 万),而飞书「采购额数据概览」归到金科城店。原因:采购数据的「收货人」是旧拼拼云名 抖喜济南财富壹号店,与 store_info.pinpinyun_name 不一致,入库时没解析出门店。
处理 :把该旧名登记进「特殊拼拼云门店注册表」(每日数据上传页 → 特殊门店注册表 → 特殊拼拼云门店),指向 抖喜(金科城店);同步写入 pinpinyun_store_map 并回填 purchase_data_2026_02~08 共 188 行 ,随后重算 2~8 月物化。
结果 :金科城店 2~8 月采购额由 0 变为 8,324 / 11,419 / 13,671 / 11,967 / 9,678 / 14,588 / 17,142(2/3/4/8 月与飞书完全一致);系统「无门店」桶由 129,562.40 降到 57,477.40;全国月度合计不变。本地=服务器。
十七、剩余未匹配收货人登记为「已登记未绑定」映射
处理 :把 2~8 月仍未匹配的 8 个收货人(河海大学 / 巴彦托海 / 西柏坡 / 内蒙古大学南校区 / 莱芜技师学院 / 鲁迅美术学院 / 辽宁科技大学 / 爱联,原始金额合计 71,995.40)登记进 pinpinyun_store_map,store_id 留空表示尚未绑定门店,便于后续人工补绑。
口径 :只登记、不改入库行为——采购入库仍按「未匹配」处理,「无门店」桶 57,477.40 与各月合计不变。
注意 :将来若某门店的拼拼云名与这 8 个重名,ID 信息表新增门店的自动关联会判为「同名冲突」而不自动绑定,需人工补绑。
十八、pinpinyun_store_map.store_id 改为可空(NULL=未绑定)+ 修复 NULL 被解析成 "None"
改动 :store_id 由 NOT NULL 改为可空(迁移 db/migrate_pinpinyun_store_id_nullable.sql),NULL 表示「已登记但未绑定门店」;此前用空串表示的 8 行统一改为 NULL。
隐患修复 :解析代码原为 str(store_id),NULL 会变成字符串 "None"(真值),采购入库会把门店记成 "None"、金额从「无门店」桶消失;已改为 COALESCE / or ""(operation 与 pipeline 两侧)。
代码 :operation purchase_repo.ensure_map_table、sync pinpinyun_registry._ensure_map_table 建表去掉 NOT NULL 并增加幂等 ALTER。
验证(本地 + 服务器) :is_nullable=YES;store_id IS NULL 8 行 / 空串 0 行;两侧解析返回 ''(非 "None");「无门店」桶仍 57,477.40;/purchase/summary 2026-08 采购额 6,167,817.60 不变。
部署 :operation / pipeline / sync 镜像双端发布(回滚标签 gmvsys-<svc>:bak.260930.110500)。
十九、门店管理页支持「按 ID 搜索」
改动 :门店管理页搜索框占位由「按门店名称搜索」改为「按门店名称/ID搜索」,匹配范围扩展为(大小写不敏感):门店名称 / 门店ID(SS…)/ 门店编号 / 拼拼云门店名 / 美团团购ID / 抖音ID / 平台账号ID(美团·淘宝闪购·京东,取自 plat_info)。
实现 :纯前端。StoreManage.vue 增加 store_id → 平台账号ID 索引(platStore 已在页面加载时全量拉取),导出与汇总里的过滤描述同步改为「名称/ID含…」;不涉及接口与数据。
验证(本地 + 服务器) :构建产物 chunk StoreManage-*.js 含新文案,两端 8080 均可取到;frontend 镜像双端一致(回滚标签 gmvsys-frontend:bak.260930.121800)。
二十、大区管理「当前闭店GMV / 当前关店数」改为门店级加和
改动 :大区管理页只读字段「当前闭店GMV」(now_close_gmv) 由「红线消费量(annual_stock_gmv − 最终红线余额,千万级)」改为 Σ 闭店门店的 annual_closing_gmv (闭店后未实现的 GMV);「当前关店数」(now_close) = 闭店(store_info.closed=1)且三平台ID不全为NULL (plat_info 中 mt/tb/jd 至少一个非空账号)的门店数。
实现 :gmv-service 的 _persist_meta;仍只在与表值不一致时经 hierarchy 内部接口写回 big_region_info,红线内部计算(__rlg/__rlc)不受影响。同步更新 PRD/Project/API 中的口径描述。
验证(本地 + 服务器,已对齐) :晋冀 6 / 882,450.05、北方 6 / 931,755.91、京津沪 10 / 2,875,727.38、华南 10 / 2,111,910.40、外阜 11 / 785,672.53;gmv 镜像双端一致(回滚标签 gmvsys-gmv:bak.260930.140000)。(当日后续调整:当前闭店GMV 改为仅存量、并在列表展示相关列与新增「红线剩余」,见二十一)
数据对齐 :服务器 store_info.closed 原比本地多 4 家关店(万通技工学院店 2026-04-01、棠下店/东莞店 2026-09-27、通州万达店 2026-09-22),已按服务器为准同步到本地并重算,双端一致。
二十一、大区管理:当前闭店GMV 改为仅存量 + 列表展示 + 新增「红线剩余」
当前闭店GMV :由「闭店门店(存量+增量)closing_gmv 之和」改为仅存量店 (Σ 闭店门店中 property=stock 的 annual_closing_gmv);「当前关店数」仍为「闭店(closed=1)且三平台ID不全为NULL」的门店数(含增量)。
列表展示 :大区管理列表新增 当前关店数 / 当前闭店GMV(元) / 红线剩余(元) 三列(原有 存量GMV、红线GMV、红线关店数 保留,其中「红线关店」改名「红线关店数」);编辑弹窗同步新增只读「红线剩余」,并给「当前闭店GMV」加注「仅存量店」。
红线剩余 = 存量GMV − 红线GMV − 闭店GMV(存量)(前端计算展示,不新增数据库字段 )。
验证(本地 + 服务器,数值一致) (依次为 当前关店数 / 当前闭店GMV / 红线剩余):京津沪 10 / 2,681,295.88 / 554,864.12;北方 6 / 815,870.91 / 219,789.09;华南 10 / 1,643,852.80 / 225,117.20;外阜 11 / 0.00 / 999,600.00;晋冀 6 / 686,572.55 / 390,457.45。镜像双端一致(回滚标签 gmvsys-gmv:bak.260930.150000、gmvsys-frontend:bak.260930.150000)。
2026-10-08
一、按时段上传:美团行同步维护派生列 income_out / amount_out
问题 :按时段上传只把勾选的差异字段 patch 进库;改了「拼好饭收入」(income_pin) 后「外卖收入」(income_out) 不会跟着变,出现「外卖 + 拼好饭 ≠ 合计」。
修复 :pipeline 新增 apply_derived_out —— 本次上传改动了 income 或 income_pin 的美团行,自动补写 income_out = income − income_pin、amount_out = amount − amount_pin;差异预览、导出报告与勾选入库都会带上这两列;库里没有的新行只有带 income 时才写派生列,避免出现负的外卖收入。
验证 :改通辽店 10-04 拼好饭收入为 500/45 → income_out 2776.88 → 2717.53、amount_out 160 → 155(与公式一致);拼好饭同值不产生改动;饿了么 / 京东不受影响。pipeline 镜像双端一致(回滚标签 gmvsys-pipeline:bak.261007.195039)。
二、抖喜(深圳南山店) 拼拼云更名(南油 → 深圳南山)+ 9-10 月数据同步到服务器
背景 :该店在拼拼云系统里的名称由「抖喜深圳南油店」改为「抖喜深圳南山店」。
处理 :store_info 的拼拼云门店名改为新名;旧名「抖喜深圳南油店」加入「特殊拼拼云门店注册表」(写入 data/sync/special_pinpinyun.json 并把 旧名→门店 写进 pinpinyun_store_map);新名由 operation seed 补进映射表。采购数据 2~8 月 202 行「收货人=抖喜深圳南油店」本来就已绑定该店,无需回填、无需重算。
9-10 月数据同步到服务器 :operation_data 9 月 48,487 行(含 1,869 插入 + 2,511 更新)/ 10 月 9,724 行(服务器原无 10 月表)、promo_data 9 月 36,928 行 / 10 月 2,808 行、淘宝闪购 CRM 9 月 1,178 行、主数据补 1 家门店(抖喜(泗洪店))与 3 条平台账号。
验证(本地 + 服务器) :两端逐项一致(行数 / 收入合计 / 单量合计 / 日期范围);新旧名解析都指向 SS4FB3FA7F01;该店 2~8 月采购额 349,952.01 不变。
三、肉片采购模块(独立表 + 汇总下载 + 按时间范围上传)
背景 :肉片(调理牛肉片 / 调理鸡肉片)要单独看「有效采购门店数 / 采购率」,而拼拼云导出的肉片明细不属于现有采购模块(采购分表只到 8 月),因此单独建表。
数据 :新建独立表 fillet_data(采购字段 + store_id / static_date + 去重键 src_key),装载 2~9 月肉片采购明细 1872 行 (关联门店 1821 行;收货人匹配不到门店的 51 行单列)。
汇总 :GET /fillet/summary(按大区)、GET /fillet/export(生成并下载 xlsx,落盘 data/export/fillet/<年>/)、GET /fillet/files;网关新增 /fillet 路由;「采购额 · 采销比」页新增下载肉片采购汇总 按钮(见 8.14)。
上传 :POST /upload/fillet/range +「每日数据上传」页新增肉片采购数据上传(按时间范围) 卡片(见 7.3.4);按 src_key 幂等入库,原始文件另存 data/raw/fillet/。
口径 :选中月 M 的前月+当月两月累计判定订货/有效(有效 = 两月累计 ≥ 基数[默认5,可改] 或 M 月首次采购);门店数 = 开店日期≤M月末 且 闭店日期>M月初 + 非学校店 + 有外卖平台账号 + M 月营收与单量都不为0;采购率 = 有效 ÷ 门店数。
验证(本地 + 服务器) :2~9 月 1872 行装载成功;同一批文件重复上传新增 0 行(幂等);两端同口径、逐大区结果完全一致 (门店数 / 订货门店数 / 有效采购门店数 / 采购率 / 各月件数均相同,具体数值以当次导出的 xlsx 为准)。门店主数据按服务器为准对齐(关店标记 + 补录门店 + 拼拼云映射),并把「收货人→门店」改为按当前映射兜底重解析。
四、淘宝闪购 CRM 周期账单:支持按时间范围上传(修复「范围上传失败: 'crm'」)
现象 :在「每日数据上传 → 按时间范围上传」里选「淘宝闪购CRM周期账单 (tb_crm)」,提交直接报错 500 范围上传失败: 'crm' (前端能看到该类型,但后端一提交就失败)。
原因 :范围上传只用 ROW_CFG 配置来认文件,而 ROW_CFG 的淘宝闪购段落只有 data / remark,没有 crm ;代码在取 ROW_CFG['tb']['crm'] 时抛 KeyError(发生在解析文件之前,所以任何账单都会失败)。另外 CRM 的单日入口会把整份账单统一压到一个日期 ,丢弃文件里已解析出的「账单日期」。
修复 :给范围上传加 CRM 分支——按每行「账单日期」(缺失退回入账日期,再缺失用范围结束日)入库,按所选范围过滤,直接写 CRM 日表(tb_crm_daily_date_年_月,键 = 门店id + 账单日期,只比较代运营收入:相同跳过/不同更新/没有新增,幂等),原始文件按账单日期另存 raw/tb/<日期>/crm.xlsx;前端允许 CRM 一次选多份账单,结果区显示 CRM 的 行/新增/变更/未变更。
验证(本地 + 服务器) :09-22 与 09-23 两份账单(97 / 96 行)一次上传 → 193 行全部「未变更」(幂等),行内 days_list 正确;只传范围外的一天 → 过滤为 0 行、不入库;单日入口行为不变。
五、GMV 红线抵扣顺序:同日多家闭店时按闭店 GMV 从大到小先抵扣
规则调整 :某大区当日出现多家存量门店闭店 、而红线额度(红线关店数 / 红线 GMV)不足以覆盖全部 时,按各店「闭店 GMV」(annual_closing_gmv) 从大到小依次抵扣红线 ;同日金额并列再按门店 id。此前同一日是按门店 id 排序(对齐参照项目并列序),会出现「小目标店先被覆盖、大目标店反而转入在营」的情况。
实现 :gmv-service _compute() 排序键由 (闭店日, 门店id) 改为 (闭店日, −闭店GMV, 门店id),在营门店仍排最后;其余红线逻辑(额度用尽转在营、lost_threshold 特例、杭州店特例)不变。
验证(本地 + 服务器) :晋冀大区 2026-09-01 同日闭店 3 家、红线关店数 5 已用满——改前覆盖 SS3A5894D474(闭店 8.23 万),改后覆盖 SSD5E252AEC8(闭店 8.23 万)、SS3A5894D474 转为在营;晋冀存量GMV 43,755,240.98 → 43,755,174.72、闭店GMV合计 924,488.66 → 924,554.92;华南/外阜/北方/京津沪无同日跨界组,数值不变。
六、GMV 红线抵扣不超过红线余额(大额闭店分支)
规则 :单店年闭店 GMV 超过阈值(默认 10 万)时,先用红线余额抵扣,抵扣额不得超过红线余额 ;只有超过红线的那部分 才按「闭店剩余月份的计划占比」分摊进大区在营 GMV。此前该分支把整笔闭店 GMV 都算作红线内抵扣并直接把红线余额清零(承接参照实现的 TODO 写法),会出现「抵扣超过红线」。
实现 :gmv-service _compute() 中该分支改为 within = min(剩余红线GMV, 单店闭店GMV)、over = 闭店GMV − within,红线扣 within、分摊 over(over>0 才分摊);同时杭州店特例的「红线关店数 −1」加了 max(…,0) 夹取,不再出现负数。
验证(本地 + 服务器) :当前数据下该大额分支与杭州店计数夹取都不会被触发 (外阜大区的杭州店特例已把红线 GMV 提前清零、其余门店要么在额度内、要么红线关店数先用完),因此五大区数值与前一版完全一致(京津沪 19,835,918.07 / 北方 28,939,212.98 / 华南 25,406,019.35 / 外阜 19,563,897.89 / 晋冀 43,755,174.72);规则生效于后续出现大额闭店的月份。gmv 镜像双端一致。
七、肉片汇总下载:自定义筛选(多档单量梯度 + 采购物品条件 + 或/与规则)
需求 :肉片汇总下载后可自定义判定条件——① 单量梯度可自行增加多档 ;② 增加「门店在采购数据 里某物品数量 > 阈值」也算有效;③ 组合方式可选或 或与 ;④ 交互顺序为「先选规则 → 再选物品 → 再填数量阈值」。
实现 :report 服务 /fillet/summary|export 新增 tiers(JSON 单量梯度)、rule(or/and)、item、item_qty 参数;新增 GET /fillet/items 返回「商品列表」白名单商品(35 个)。
条件A(肉片)= 两月累计 ≥ 该店适用阈值(按单量梯度升序取第一条命中,都不命中用基数),或 当月首次采购;
条件B(物品)= 该店 M-1 + M 采购数据里所选物品「订单量 − 退货量 − 错单量」(「错单:」开头整笔不计)> 阈值;缺采购表的月份按 0;
或 = A 或 B(只满足B、甚至没买肉片的门店也计入有效),与 = A 且 B。
前端 :采销比页下载弹窗改为「基数 + 单量梯度(可加/删多档)+ 规则(或·与) + 物品下拉 + 物品数量阈值」,全部记住上次输入;「预览」可先看数字;导出「门店明细」在启用物品条件时新增「物品数量 / 物品达标」两列。
验证(本地 + 服务器) :选 2026-09、基数 5、梯度 [单量<500→1、<1000→3]、物品「三件套餐具包(抖喜定制,100套*10包/件)」阈值 5 → 或规则 有效 128 / 采购率 34.69% (其中 13 家仅靠物品达标,11 家没买肉片);与规则 有效 7 / 1.90% ;缺采购表月份提示 2026-09(采购分表目前只到 8 月)。镜像双端一致。
八、肉片下载:物品条件可加多条,按顺序左结合
需求 :物品条件不止一条,且组合顺序固定为 (((原始条件) 逻辑1 (条件A)) 逻辑2 (条件B)) …——先算原始条件与第一条,再把结果与第二条运算,依此类推。
实现 :/fillet/summary|export 新增 conds 参数(JSON 数组),后端按数组顺序左结合求值(同物品只查一次采购数据);旧的单条 rule/item/item_qty 仍兼容(等价于一条)。
前端 :下载弹窗「物品条件」改为可增删的多行(每行:规则 / 物品 / 数量阈值),并提供「+ 添加物品条件」;导出「门店明细」按条件条数生成「物品N数量 / 物品N达标」列,「口径说明」写出完整条件链。
验证(本地 + 服务器) :选 2026-09、基数 5、梯度 [单量<500→1、<1000→3]、条件链 [或 三件套餐具包(抖喜定制) > 5] 且 [与 三件套餐具包(新疆炒米粉LOGO) > 1] → 有效 11 / 采购率 2.98%(单条情形分别 128 / 11);镜像双端一致。
九、肉片下载:物品支持 %表达式(LIKE 语义)
需求 :物品条件里的物品除了从下拉选,还能直接输入 %表达式——%A% 表示名称含 A、%A 表示以 A 结尾(对称地 A% 表示以 A 开头)。
实现 :fillet_service 里物品匹配改为——含 % 时用 product_name ILIKE %s(整串作为 LIKE 模式参数化传入,不拼 SQL),不含 % 时仍用 product_name = %s 精确匹配;前端物品下拉加 allow-create 允许直接输入,并给出 %表达式提示。
验证(本地 + 服务器) :选 2026-09、基数 5、条件「或 物品>5」——精确名「三件套餐具包(抖喜定制…)」有效 121(32.79%);%餐具包%、%10包/件)(结尾)、三件套餐具包%(开头)均为有效 130(35.23%);两端一致。镜像双端发布。
十、肉片下载:物品条件阈值支持「固定值 / 比例 + 最小物品量」
需求 :每条物品条件的阈值可选 固定值 或 比例 (= 两月选中物品数量 ÷ 两月肉片采购数量),比例型还要一个 最小物品量 兜底。
口径(用户确认) :
固定值 → 物品两月数量 > 阈值;
比例 → 物品两月数量 ÷ 该店两月肉片件数 ≥ 比例阈值 ,且 物品两月数量 > 最小物品量 ;
分母(两月肉片件数)为 0(该店两月没买肉片)→ 该条件不成立 ;类型是每条物品条件各自选 。
实现 :conds 数组每条增加 type(fixed/ratio)与 min_qty;后端求值时比例型用该店两月肉片件数作分母;「口径说明」按类型分别写成「物品数量 > 5」或「数量/肉片数量 ≥ 0.5 且物品数量 > 3」;前端每行新增「固定值/比例」下拉与「最小物品量」输入(比例时出现)。
验证(本地 + 服务器,2026-09、基数 5、条件「或 %餐具包%」) :固定值 >5 → 有效 130(35.23%) ;比例 ≥0.5 且物品>3 → 121(32.79%) ;比例 ≥0.1 且物品>0 → 166(44.99%) ;镜像双端一致。
十一、肉片下载:物品条件可选「以物品为准 / 以肉片为准」,数量与比例双阈值(都填时同时满足)
需求 :一条物品条件里可同时给「数量阈值」和「比例阈值」,都填时必须同时满足(且) ;比例方向可选——以物品为准 (比例 ≥ 阈值)或 以肉片为准 (比例 ≤ 阈值);比较符号统一为 ≥ / ≤ 。(当日后续调整:初版为「满足任一」,已按用户要求改为「同时满足」,见十二)
口径(用户确认) :条件成立 = 「物品两月数量 ≥ 数量阈值」且 「比例(= 物品两月数量 ÷ 该店两月肉片件数)满足 以物品为准≥ / 以肉片为准≤ 比例阈值」;两阈值可只填一个;分母为 0 时比例那条不成立。
实现 :conds 每条改为 {rule, item, basis: item|fillet, qty, ratio};后端按上述「或」求值,旧的 type/item_qty/min_qty 保持兼容;「口径说明」按基准写成「物品数量 >= 5 或 比例(物品数量/肉片数量)>= 0.5(以物品为准)」;前端每行新增「以物品为准 / 以肉片为准」下拉。
验证(本地 + 服务器,2026-09、基数 5、条件「或 %餐具包%」) :数量≥5 或 比例≥0.5(以物品为准)→ 有效 198(53.66%) ;比例≤0.1(以肉片为准)→ 116(31.44%) ;旧参数「固定值 >5」仍为 132(35.77%)。镜像双端一致。
十二、肉片下载:数量与比例两个阈值都填时改为「同时满足」
调整 :物品条件里「数量阈值」与「比例阈值」都填时,必须同时满足(且) 才成立;只填一个时按填的那个判定(初版为「满足任一即成立」)。
实现 :fillet_service 的 _cond_ok 由「或」改为「且」(比例型分母为 0 时比例那条不成立);「口径说明」连接词改为「且」;前端提示改为「填了的阈值都要满足」。
验证(本地 + 服务器,2026-09、基数 5、条件「或 %餐具包%」) :数量≥5 且 比例≥0.5(以物品为准)→ 有效 116(31.44%) ;仅数量≥5 → 149(40.38%);仅比例≥0.5 → 165(44.72%);数量≥5 且 比例≤0.1(以肉片为准)→ 108(29.27%)。镜像双端一致。
2026-10-09
修改
一、修复:采购数据按时间范围上传后「入库 0 行」(支付时间 ISO 格式解析失败)
现象 :采购数据按时间范围上传 → 预览正常(提示若干行「新增」)→ 点「入库」只提示「入库完成: 新增 0 行, 更新 0 行」,库里既没建表也没数据。
原因 :预览接口把「支付时间」序列化成 ISO 8601 (2026-09-01T00:29:41)返回给前端,入库时前端原样回传;而 pipeline 与 operation 两端的 _parse_dt 只认空格格式,带「T」的串解析成 None → 行被静默跳过 。
修复 :① 两端 _parse_dt 增加 ISO 8601 兜底(datetime.fromisoformat,兼容 T、微秒、时区后缀);② 入库把「被跳过行数」显式上报(operation 返回 skipped、pipeline 汇总,且一行都没写入时直接报错并说明原因 );③ 前端提示改为「新增 X 行, 更新 Y 行, 跳过 Z 行」/显示后端错误原文。
验证(本地 + 服务器) :用「2026.9月采购原始数据.xlsx」(6928 行)走真实 HTTP 链路 → 新增 6928 行、跳过 0 ;两端 purchase_data_2026_09 均 6928 行(2026-09-01 ~ 09-30)。
二、采购额口径:is_static=1 的品全部统计 + 营业额只算合格门店(督导 / 区域 / 大区一致)
采购数据 :白名单改为只按 product_list.is_static=1 判定 ——不再受 start_static(开始统计时间)影响,即 is_static=1 的商品全部统计 。
营业额(采销比分母) :只统计满足以下条件的门店——① 统计区间内在营:开店日期 ≤ 区间末 且 闭店日期 > 区间初 ;② 当月单量不为 0 ;③ 非学校店 ;④ 三平台(美团 / 淘宝闪购 / 京东)至少开了一家 ;金额本身仍按日报口径逐日过滤(开业日 ≤ 当日 < 闭店日)。
实现 :operation purchase_stats.py——_MATCH 去掉 start_static 条件;income_by_store 增加上述四项门店条件(学校店 / 平台账号 / 单量≠0 / 开闭店区间)。
验证(本地 = 服务器) :2026-09 三张分页合计一致(采购额 5,383,063.40 / 收入 11,214,349.33;大区目标 5,957,639.39),收入门店数 369(剔除 10 家学校店/无平台/单量 0 的门店,被剔除门店当月收入合计 0.00,故当前数字不变);2~9 月物化已按新白名单重算(stores 250/312/339/343/345/342/382/381)。
三、采购额合计行显示采销比与达成率(按合计实际值)
改动 :督导 / 区域 / 大区三页的合计行 不再留空——采销比 = 合计采购额 ÷ 合计收入 、达成率 = 合计采购额 ÷ 合计目标 (都按合计实际值算,不做各行百分比平均)。
验证 :2026-09 大区页合计 采销比 48.00% 、达成率 90.36% (若按行平均则为 45.86% / 88.40%);frontend 6cef73a13cce 双端一致。
四、手册(8090):附录 C 五十四条起缩进修复 + 编号重排为「每日自一起编」
缩进 :附录 C 五十三 / 五十六 / 五十七 / 五十八 四条各缺一个 </ul>(列表未闭合 → 后续条目被逐层嵌套缩进),7.3.2 另多一个 </ol>;补齐后全文件标签平衡(ul 161/161、ol 50/50、li 865/865),附录 C 20 个条目列表嵌套深度均为 0。
编号 :2026-09-20 起编号跨日累加(09-21 从二十六、09-24 从三十五、09-28 从三十九、10-08 从六十)且 09-20 内「二十/二十一」颠倒、09-21 重复「三十四」;已按每个日期块从「一」连续递增 重排,块内「见 X」引用同步重映射。
五、肉片汇总下载:新增按地区(省份)过滤(包含 / 不含)
功能 :下载弹窗新增「地区过滤」——方式可选 包含所选 (只看所选省份的门店)或 不含所选 (排除所选省份的门店),省份可多选(来自门店档案 province,共 26 个),不选=全部地区;参数与其它设置一起记住上次输入。
口径 :过滤作用于门店范围 ——门店数 / 订货门店数 / 有效采购门店数 / 采购率 / 门店明细 / 未匹配门店列表都按过滤后的门店统计;导出「口径说明」写明本次过滤方式与省份列表。
实现 :report 服务 /fillet/summary|export 新增 provinces(JSON 数组或逗号分隔)与 prov_mode(include/exclude);新增 GET /fillet/provinces 返回可选省份;_scoped_stores 增加省份 IN / NOT IN 条件。
验证(本地 + 服务器,2026-09、基数 5、无其它筛选) :无过滤 门店 369 / 订货 174 / 有效 108(29.27%);包含 河北+北京 → 136 / 51 / 28(20.59%);不含 河北+北京 → 233 / 123 / 80(34.33%,= 369−136);明细行数同步为 136 / 233;镜像双端一致。
六、采购表 2~9 月备注规范:补货类统一加「补货: 」前缀(仅标记,不影响统计)
范围与规则 :逐表检查 purchase_data_2026_02 ~ 2026_09 中有备注的行 (47,077 行里 2,012 行有备注、324 种写法);凡表明本单为补货/重新下单 的在备注前加 补货: ,表明下错单 的加 错单: ;已带前缀(错单:/换货:/退单:)的视为已处理跳过 ,配送时间/地址/日期/质量等其它备注不影响统计也跳过。
本次改动(本地 = 服务器,各 10 行) :4.12重新下单(2026-04,1 单 8 行)→ 补货: 4.12重新下单;9.4米粉发霉补发1袋、9.14米粉发霉,补发1袋(2026-09,各 1 行)→ 加 补货: 。全表前缀统计:补货 10 / 错单 7 / 换货 23 / 退单 0。
不影响统计 :统计口径只排除 错单:(整单)、换货:/退单:(该行),补货: 不排除 ——改动后 2026-04 采购额 4,569,469.80、2026-09 5,383,063.40 与改动前一致,两端一致。
七、采购额统计:补货: 前缀的行也不再计入
调整 :采购额统计的备注过滤由「错单: 整单排除 + 换货:/退单: 该行不计」扩为再加 补货: 该行不计 (粒度与换货/退单一致:只排除带前缀的那几行)。
实现 :operation purchase_stats 的 _FILTER/_filter_args 增加一个 NOT LIKE '补货:%';补货: 只在采购额统计 生效——肉片汇总的「物品条件数量」保持「订单量 − 退货量 − 错单量」不变。
重算与验证(本地 = 服务器) :2~9 月物化已重算;2026-04 采购额 4,569,469.80 → 4,563,681.80 (排除 6 行补货 5,788.00)、2026-09 5,383,063.40 → 5,382,669.40 (排除 2 行 394.00);其余月份不变,八个月两端逐月一致。镜像双端一致。
八、采购额归属修复:未绑定的拼拼云映射不再遮蔽门店回退(门店采购额一直是 0)
现象 :门店管理「导出全年采购」里,个别在营、有平台 的门店(如 抖喜(爱联店))采购额一直是 0。
根因 :pinpinyun_store_map 里存在「已登记但未绑定门店 」(store_id 为空)的拼拼云名;两个服务的 resolve_map 先写入该键(值为空串),再用 setdefault 回退 store_info.pinpinyun_name —— 键已存在,回退永不生效 ,于是这些收货人的采购行 store_id 一直为空,既不进任何门店、也不进门店行的采购额。
修复 :pipeline purchase_upload._resolve_map 与 operation purchase_repo.resolve_map 只登记已绑定 的映射;未绑定(NULL)的条目不再遮蔽 store_info 回退。pipeline/operation 双端已发布。
数据回填 :抖喜广东省深圳市龙岗区爱联店 的 23 行未匹配采购(08 月 7 行、09 月 16 行)回填 store_id=SS570DC0B6D7 并重算 2~9 月物化;爱联店采购额 0 → 8,412.00 (8 月 219.00 + 9 月 8,193.00);未匹配桶 240,155.00 → 231,743.00(总额不变,仅归属变化)。
同时核验 :2~9 月物化金额与「按口径直算」逐月一致,说明 is_static=1 的品已全部计入采购额。
待人工确认 :仍有 21 个收货人在门店档案里找不到对应门店(合计约 28.5 万元,多为学校店),其中 8 个为「已登记未绑定」,需补建门店或人工指定映射。
九、未匹配收货人登记为拼拼云门店名,并在全年数据中按拼拼云名呈现
背景 :21 个收货人(合计约 28.5 万元,多为学校店)在门店档案里没有对应门店——8 个是「已登记未绑定」,13 个未登记。
登记 :把这批收货人登记进 pinpinyun_store_map(store_id 为空 = 未绑定) ,备注「2026-10-09 由未匹配收货人登记(待 ID 信息表补建门店后自动关联)」;同时把爱联店映射改为已绑定。
呈现 :门店管理「导出全年采购」新增未关联门店行 ——按拼拼云门店名 列出每月采购额(状态=「未关联门店」,营业额/目标/完成差 0),并计入汇总行;新接口 POST /purchase/unmatched-yearly,与物化「未匹配空桶」逐月一致(2~9 月 231,715.00)。
后续自动关联 :飞书 ID 信息表补建门店后,新门店带 pinpinyun_name 同步进来 → 解析规则即可对应到门店;再跑 POST /purchase/re-resolve(回填 store_id + 重算受影响月份)完成历史归属。
顺带修复 :删除废弃且口径错误的 _month_bounds(排除月末最后一天),统一用 month_bounds([首日, 次月首日))。
十、为什么取消勾选 is_static 后还是统计上(已修复:改动即时重算)
现象 :在「商品列表(统计口径)」取消勾选某些商品的 is_static 后,采购额页/导出仍是旧数字,像「没生效」。
原因 :采购额取自物化表 purchase_monthly_stats / purchase_monthly_category,只有 recompute_month 会更新它;而 PUT /product/{pid} 改的只是 product_list.is_static,不触发重算 ——物化数据仍是上一次重算时的口径。此前触发重算的时机只有:上传采购数据、POST /purchase/recompute、POST /purchase/re-resolve。
修复 :PUT /product/{pid} 检测到 is_static/start_static 变化后立即 recompute_all()(遍历所有采购分表逐月重算,约 5 秒),响应回带 recomputed.months;批量入口同样重算一次。operation 双端发布。
验证 :把「一次性湿巾(抖喜定制,2000个/件)1」勾回 is_static=1 → 2026-09 采购额 5,382,669.40 → 5,390,131.40 (+7,462.00),再取消勾选即回到 5,382,669.40;本地=服务器。
当前分布 :80 个商品中 is_static=1 共 38 个、is_static=0 共 42 个 ;只有 is_static=1 的品计入采购额。
十一、上传页排版重构(阶段一~三)与商品列表「影响金额」
排版 (只改层次/间距/密度,不动信息架构与接口):加页头 、吸顶操作条 、4 个分区标题 (同步 / 01 今日平台数据 / 02 按时间范围补充 / 03 统计口径与配置);统一设计令牌(字号 24/16/14/13/12.5/12、4-8 间距基准、圆角 12px、阴影 4%/6%、统计数字等宽);类型卡片加状态点 与计数 chip ,文件行加左侧状态条 ,「清空」降级为文字按钮,「全部上传」右对齐强化为主 CTA;肉片入库结果改为 4 个等宽数字块 。
03 分区默认折叠 :点标题展开/收起,状态记 localStorage.upload_sec03_collapsed。
商品列表「采购额」列 :显示每个商品在最新有数据月份(当前 2026-09)的采购口径金额;接口 GET /purchase/products/amounts?year=&month=。金额列不套 is_static 白名单 ,「不计入」的品若有金额会显示 +金额(未计入),便于判断勾选影响;工具栏给出该月计入品合计。
验证 :2026-09 计入口径合计 5,382,669.40;本月「不计入」但有金额的品 23 个、合计 288,640.00(调理鸡肉片 127,125.00、调理牛肉片 92,340.00 等)。operation + frontend 双端发布。
十二、9 月采购对账:修正门头沟两行(错单 + 单价)
背景 :按用户提供的《9.1-9.30门店采销比(除).xlsx》(订货明细 6,275 行 / 402 家)对账,我们的计入口径 9 月合计比文件多 1,340.00 ,且只集中在 4 家;门头沟多 1,145.00 。
明细原因 :① DH-260912-001526(09-12 14:52:42 无纺布袋 -BJBY 1×665)在供应商当前 9 月明细里不存在 (同一时段只有 -B1JBY 那单)→ 备注加 错单: 前缀(整单不计入)→ −665;② DH-260911-001865(09-11 15:34:48 三件套餐具包)单价被写错 (665 是无纺布袋价格)→ 单价/金额改为 185 → −480。
处理 :本地 + 服务器同步执行同一批 SQL,并各自重算 2026-09。
结果(本地 = 服务器) :门头沟 9 月 13,248.80 → 12,103.80 (年度 95,159.20 → 94,014.20);9 月合计:本地 → 5,381,524.40、服务器 → 5,381,329.40(与用户文件完全一致) 。
仍余 3 家 +65.00 (甘肃金昌市金川店 / 中牟 / 盐山镇,共 +195.00):都是「抖喜定制长卫衣工服三件套1(M码)」这一行,用户文件里不计入 —— 与「两个工服品 is_static 两端不一致」同源(服务器已是 0、本地仍是 1)。
十三、补录:抖喜(自贡店) 京东 9 月 18–30 日营业额/单量
数据 :09-18~09-30 共 13 天的(营业额,单量),合计 收入 1,447.19 / 单量 184 。
落库 :写入 operation_data_2026_09,plat_id='14725728'(自贡店京东)、plat_tag='jd',填 income/amount,其余派生列按该店既有京东行置 0;用局部唯一键 (plat_id,plat_tag,static_date) WHERE deleted=0 幂等 upsert(重复执行只覆盖不新增)。本地 + 服务器同步执行。
结果(本地 = 服务器) :该店京东 9 月 17 天 → 30 天 ,收入 2,078.35 → 3,525.54 、单量 259 → 443 ;该店 9 月三平台收入合计 30,312.71 (jd 3,525.54 / mt 15,540.62 / tb 11,246.55)。
说明 :自贡店 9 月没有采购额 ,因此采购额页的「收入」合计(只汇总有采购额的门店)不变;补录数据在日报 / 门店每日数据 / GMV / 该店采销比 中即时生效(GMV 服务 9 月收入合计 11,511,676.73 已含本次补录)。
十四、修复「服务器飞书表格同步不了」:督导姓名被门店更新白名单拦掉
现象 :服务器点「同步飞书表格」能拉到新数据、diff 也列出待更新门店(8 家,变更字段全是 supervisor),但点「确认同步」后全部报 update 门店不存在或无可更新字段: SS…,门店督导不更新。
根因 :sync 按督导姓名 下发({"supervisor":"殷成忠"}),而 hierarchy 门店 update_allowed 只有 supervisor_id;/internal/hierarchy/apply-diff 的更新分支直接调 repo.update_sync(),绕过了 _norm_store_supervisor() (新建/编辑路径都会调用它做「姓名 → supervisor_id」归一化)→ 无可更新字段 → 报错。
修复 (hierarchy service.py::apply_diff):门店更新分支写库前先 _norm_store_supervisor(repo, data, store_id=pid),把姓名解析成 supervisor_id(按「姓名 + 大区」查 supervisor_info,缺失则按确定性 id 新建)再更新。hierarchy 双端发布。
验证 :本地 apply → store: {created:3, updated:13, deleted:0, errors:[]},再 diff 全 0 ;抽查督导正确(苏家屯/赤峰/赤峰新城=殷成忠,小寨/悠悦城=于丕岳);服务器执行同一批同步。
说明 :督导维度统计按 supervisor_id 分组,修复后与飞书表一致。
2026-10-12
一、门店管理页:两个月份控件合并为唯一「年月」控件
背景 :页面顶部原有 ①「GMV月份」下拉(2~12、1 月,只驱动「月GMV」「月营收」两列)②「采购额月份」年月选择器(驱动「采购额」列);要求删掉①,其关联处全部改用年月日期控件。
改动 (frontend_v2/src/views/manage/StoreManage.vue):删除 selectedMonth 下拉、fiscalMonths 下拉项与 currentMonth 状态;统一为唯一控件 selMonth(el-date-picker type="month" value-format="YYYY-MM",占位符「月份」),默认本月 ;@change → onMonthChange() 一次刷新「采购额 + 月GMV + 月营收」三列。
年月→财月换算 (fiscalMonthOf(ym)):按当前财年(2 月起算,现为 2026 财年 )映射 —— 2026-02~2026-12 → 财月 2~12、2027-01 → 财月 1;财年外或非法值返回 0,此时 GMV/营收两列清空(显示 0);因为 GMV 接口只认财月、无年份参数。
列头 :采购额 / GMV / 营收 三列改为「第一行年月、第二行列名」两行居中(header-align="center" + .mhead 样式);全年 GMV 列扩展为「2026财年GMV(元) 」(curFiscalYear() 动态计算)。
导出 :筛选说明改为「月份=2026-10」,导出列名同步为「2026-10 GMV(元)」「2026-10 营收(元)」「2026财年GMV(元)」。
发布 :frontend 镜像两端发布(附页面截图)。
二、plat_info 门店名(plat_name)空值回填:每日数据处理后自动按平台源文件查找
背景 :plat_info.plat_name(平台门店名)整表 1,247 行全为空 (该列此前只由飞书同步写入,实际一直没值);要求每日数据处理后检查该列空值,用对应平台的 data/sig 源文件按平台账号 id 查名回填,找不到就保持空 。
数据来源 :平台源文件(/data/raw/<平台>/<日期>/ 下的 data.csv|xlsx、sig.xlsx、pin.csv、remark.csv、score.xlsx),取 ROW_CFG 中映射为 name 的列(门店名称/外卖门店名称):美团 = pin/sig/remark、淘宝 = data、京东 = data/sig/score。DB 里并没有 mt_data/mt_sig 之类的表 ,源文件是文件形式落盘的。
实现 (新增 pipeline/app/plat_name.py):day_names(平台, 日期) 收集当日 {门店id: 门店名称} → _update() 用一条 UPDATE plat_info … WHERE plat_tag/plat_id 匹配 AND deleted=0 AND coalesce(plat_name,'')='' 批量写入(只填空值、绝不覆盖已有名字 );process_day() 在入库完成后自动调用 backfill_day(static_date),失败只记日志、不影响入库结果,返回体新增 plat_name_fill。
一次性维护脚本 (可重复执行):python -m app.plat_name [--dry-run] [--dates 2026-10-10,…] [--latest N](--latest N = 每平台最近 N 个有源文件的日期)。
结果 :本地执行 --latest 8 后,空值 1,247 → 60 (剩下 60 个是该平台账号在已扫的源文件里没出现,按要求保持空);抽样名称正确(如 mt 11593558 = 抖喜新疆炒米粉(右安门店))。pipeline 镜像两端发布。
三、新增月报导出(结构同周报,本期=所选月整月、对比期=上月整月)
需求 :报表下载中心新增月报导出,与周报结构一致 ,但对比「上月整月 vs 当月整月 」,并按所选日期取月份。
实现(后端) :report/weekly_service.py 新增 resolve_month_periods()(本期 = 所选日期所在月 1 日~月末 ;对比期 = 上月 1 日~上月末 );周报服务把「期间解析 / 落盘目录 / 标题」抽成类属性 PERIOD_RESOLVER / KIND / TITLE;新增 MonthlyReportService(WeeklyReportService)(KIND='monthly'、TITLE='抖喜月报')—— 8 个 sheet(汇总/美团/淘宝闪购/京东/美团推广/淘宝闪购推广/门店明细/门店推广明细)与列结构、算法完全复用 。
接口 :新增 POST /reports/monthly(body {report_date},缺省=昨天所在月),生成后直接下载;文件落 export/monthly/monthly_report_<本月1>_<本月末>_<时分秒>.xlsx,报表中心的「已生成的月报(今年)」列表与下载(GET /reports/monthly/list、GET /reports/files/download?kind=monthly)开箱可用 。
前端 :ReportCenter.vue 新增「每月月报」按钮(复用顶部「统计日期」选择器,按该日期的月份生成)+ genMonthly()。
验证 :report_date=2026-09-15 → 生成 monthly_report_2026-09-01_2026-09-30_*.xlsx,8 个 sheet,标题「抖喜月报汇总」;全国 797,863 单 / 11,511,676.73 元 vs 上期(8 月整月)967,634 单 / 13,979,698.70 元 → 单量增长 −17.54% 、收入增长 −17.65% (与库内 9 月/8 月口径一致)。
发布 :report + frontend 镜像两端发布。
四、周报/月报:「大区合计」行的区域单元格加淡灰底
需求 :周报、月报中当区域列 = 大区合计 (各大区的小计行)时,该单元格用淡灰色填充 。
实现 :report/weekly_service.py::_write 的数据行循环里,第 2 列(区域)值为「大区合计」时给该单元格 PatternFill("solid", fgColor="D9D9D9")。周报与月报共用同一个写盘函数 ,所以两类报表、以及每个 sheet(汇总/美团/淘宝闪购/京东/美团推广/淘宝闪购推广/门店明细)同时生效。
验证 :重新生成周报 weekly_report_2026-10-01_2026-10-11_*.xlsx 与月报 monthly_report_2026-09-01_2026-09-30_*.xlsx:汇总页与美团页各 5 个 「大区合计」行全部 为 D9D9D9,非合计行被误标的 0 个。
发布 :report 镜像两端发布。
2026-10-19
修改
一、采购额页收入拆两列:有采收入 / 全部收入 + 两个采销比
口径 :有采收入 = 有采购记录且满足合格门店条件的收入(原口径);全部收入 = 该维度下全部门店 收入(不排学校店、不看单量、不看开闭店,按 plat_info 归属)。两个采销比分别 = 采购额 ÷ 有采收入、采购额 ÷ 全部收入;合计行按合计实际值重算。
实现 :purchase_stats 新增 income_all_by_store;summary 第二轮把没有采购记录的门店 收入按维度归位(督导 / 区域 / 大区 / 门店),返回 all_income / ratio_all / total_all_income。
验证(2026-10) :本地 采购额 2,694,952.80 / 有采收入 5,290,783.99 / 全部收入 5,797,458.77;服务器 2,694,952.80 / 6,499,271.65 / 7,120,553.39 (全部收入 = 实际月收入)。未在 plat_info 登记的 6,189 行(合计 1,785.81)无法归属到门店,故不计入。
二、站点图标与侧边栏 Logo 换新
图标 :favicon.ico(256/128/64/48/32/16 六档)+ apple-touch-icon 180 + icon-512,侧边栏折叠态 logo 512;源图居中裁 660×660(原图四周留白过大,直接缩到 16px 会糊)。index.html 增加 png / apple-touch link 与 theme-color #d0111b。
验证 :本地与服务器 favicon sha256 a4a9931…、logo 1b933a3… 完全一致。
三、侧边栏选中态颜色对调
改动 :选中项由「深红底 + 白字」改为白底 + 侧边栏红字 (浅色 #96181d、深色模式 #6f1418),图标同色;子菜单选中时父级标题同步高亮。
2026-10-20
修改
一、平台门店新增状态 active_mode(活跃 / 单店 / 过时)
口径 :粒度 = 平台门店行 (plat_id + 平台)。active = 本次飞书 ID 信息表命中;sig = 未命中但最近 30 天该行有营收;old = 其余。每次同步飞书后自动重算,另有 POST /auth/sso/active-mode/recompute。
展示 :平台管理页新增「门店状态」列与筛选;导出映射为 活跃 / 单店 / 过时 ;门店分析的三列平台 ID 按 活跃 > 单店 > 过时 取一条(同优先级取开店时间最新)。
特殊门店注册表 :加入时该平台行固定为 old 并写进注册表,后续同步不再被营收规则改回。
验证 :本地 活跃 1,196 / 单店 3 / 过时 51,服务器 1,212 / 3 / 51;泸州店美团 34376062、京东 24472243(均取到活跃号)。
二、门店分析字段顺序调整
改动 :门店信息类字段整体移到基础数据之前 ,开业日期与闭店日期相邻;表格列、「字段」抽屉、导出统一按同一数组顺序。
三、审计降噪与历史清理
心跳表 :server_battery_status 改为 60 行环形 (hb-0…hb-59,按秒取模,每分钟每行更新一次);其审计改为固定 60 条环形覆盖 (负数 id −1…−60,约最近 1 分钟),操作日志页过滤该表。
物化表 :purchase_monthly_category、purchase_monthly_stats 不再记审计 (派生数据,原始采购数据仍有审计可追溯)。
清理 :10-01 前 734,952 / 647,425;10-10 前 519,653 / 442,682;心跳审计 830,129;品类物化表 1,002,479 / 393,058;门店物化表 178,658 / 69,611(左 = 本地、右 = 服务器)。
结果 :审计表本地剩 219,249 条、服务器剩 69,266 条,仅保留运营 / 采购 / 推广等真实业务变更。
2026-10-21
新增
一、飞书免登(P1–P5 全套)
免登 :/auth/sso/feishu/start → 飞书授权 → 回调换 token 取用户 → 查绑定 → 签发与密码登录完全相同 的 JWT → 一次性 ticket(60 秒)→ 前端 /sso/callback 换 token 进入系统。
通讯录同步 :从授权部门出发 BFS 拉全量部门 / 成员落镜像表;默认 600 秒 定时(最小 60 秒,可在个人中心调整);登录 / 换绑 / 审批前缓存超过 10 分钟强制同步 ;数据库时间戳锁防并发。
部门映射 :中台部 → 管理员 ;业务部负责人 → BOSS ;五大区负责人 → 大区经理 (京津沪大区 ↔ 京津沪区按去后缀归一化匹配);业务部普通成员 → 运营 (登录时三段式确认);其它部门 → 访客 ;系统里没有对应大区的部门先给访客,新建大区并同步后恢复。
身份确认与审批 :运营 → 督导 → 访客三级确认;选运营 / 督导后选大区提交审批,大区经理通过即建号 (运营自动建区域 SR+md5(区域|大区)、督导自动匹配督导档案);审批人可「修改后通过 」改角色 / 区域 / 督导 / 手机号 / 姓名;不能审批自己提交的申请 。
绑定变更 :个人中心可解绑 / 换绑(入口暂时隐藏);换绑后角色与大区一致直接生效 ,否则走审批;解绑唯一登录方式须先设置密码。
登录先匹配已有账号 :未绑定时按姓名匹配系统内手工运营 / 督导账号 (唯一命中才绑定),命中直接登录无需审批 ;王帅的两个账号已合并为 op_SR23883DD331。
二、真实客户端 IP 审计(公网 / 私网)
链路 :nginx X-Real-IP / X-Forwarded-For → 服务中间件解析 → 数据库事务 SET LOCAL app.client_ip_* → 审计触发器写 client_addr、ip_public、ip_private;飞书登录日志另存完整转发链路。
验证 :带 X-Forwarded-For: 8.8.8.8, 192.168.1.50 的请求 → 审计 client_addr=8.8.8.8 / ip_public=8.8.8.8 / ip_private=192.168.1.50;全部后端镜像已重建,所有服务生效。
三、报表保留策略
规则 :日报 / 周报 / 月报按「报表类型 + 统计日期 」分组,每组只保留最近生成的 3 份 ,生成后立即清理;只作用于 export/daily、export/weekly、export/monthly。
首次清理 :本地删 40 个、服务器删 210 个重复日报;报表中心现每个日期最多 3 条。
四、一批界面调整
全局 :日期 / 月份选择器中文化(显示「9 月」而不是 Sep);主面板大数字随卡片宽度自适应(clamp 18–34px)。
汇总看板 :改为纵向布局,图表在上占满宽度、明细在下。
门店分析 :「美团拆分」类标签加「美团」前缀;比较字段加(周 / 月 / 年)后缀,「上周期值」改名「对比值 」;修复对比值全空 (前端补传 compare / compare_base,后端默认周 / 月 / 年三窗口,对比窗口无数据时显示「-」);数值列可排序、文本列仅可搜索(选定字段后才出现搜索框);顶部卡片顺序 总收入 / 美团 / 淘宝 / 京东,收入与单量分行展示;修复按文本列排序返回 500。
采购分析 :首列收窄(约原来的 1/4)并停止自动拉伸,右侧留白待扩展。
大区 / 督导管理 :列表数值统一 2 位小数(金额 1,234.00、采销比 43.18%、目标系数 0.43),编辑弹窗保留完整精度;大区名称列收窄至约 3/5。
闪购扣点 :日期表头改为明确日期 MM-DD(10-14 … 10-20),不再用「前 N 日当日」。
附录 D:严重故障列表
本节按日期记录影响面较大的严重故障(服务中断、数据风险等),制式同 附录 C 修复日志 ,便于运维追溯与复盘。
五、周/月报「门店推广明细」:美团 / 淘宝闪购 分列
需求 :导出文件的「门店推广明细」页,淘宝闪购与美团的推广费要分开 看。
改动 (report/app/weekly_service.py):该页由「一行一店 + 美团淘宝合计」改为一行一店 + 分平台列 —— 美团本期推广 / 美团上期推广 / 美团推广差值 / 淘宝闪购本期推广 / 淘宝闪购上期推广 / 淘宝闪购推广差值 / 本期推广合计 / 上期推广合计 / 推广差值合计,其后接原有的 曝光提升 / 进店提升 / 进店成本(共 16 列)。
口径 :分平台金额 = promo_data_* 按 (store_id, plat_tag) 汇总(mt=美团、tb=淘宝闪购);合计与排序仍按两平台之和,所以数值与改动前完全一致,只是拆成两列 。
发布 :report 镜像两端 78f92d8ad631;周报与月报都已实际生成并核对表头 通过。
六、采购额新口径:商品「统计时间区间」+ 行级排除「不计入:」
需求 :采购额要能表达「某商品只在某些月份计入」,并在与飞书/对方文件对账时能逐行 排除。
实现 :新增表 product_static_period(id, product_id, seq, kind, static_date),kind ∈ start|stop,必须交替、第一条必须是开始统计、按日期升序 ;口径 = 采购行日期落在 [开始统计, 停止统计) 内才计入(最后一条是开始统计 → 一直统计到现在)。
派生状态 :「是否统计」= 今天是否落在某个区间内 ;is_static / start_static 自 2026-10-12 起不再参与任何计算 。
行级排除 :备注前缀新增 不计入:(只排该行,与 换货:/退单:/补货: 同级);错单: 仍是整单排除。
对账结果(本地=服务器,逐月精确相等) :2 月 = 「2月门店采销比(除汤粉等)」订货明细扣退货 净额 3,087,587.00;3-7 月与 9 月 = 飞书「存量目标源 + 增量目标源」采购额(4,404,725.40 / 4,562,302.80 / 4,609,261.40 / 4,992,934.20 / 5,536,635.80 / 5,381,329.40);8 月 = 「8.1-8.31门店订货明细」净额 6,169,870.60。
发布 :operation 镜像两端 b8f95fc909b4。
2026-09-28
严重故障
一、服务器充电器接口松动断联 · 笔记本电池耗尽自动关机(服务中断约 9 分钟)
故障时间(校正时钟后的真实时间) :2026-09-28 12:04:52 CST 市电丢失、转为电池供电;16:06:25 电池耗尽触发自动关机;16:15:47 市电恢复后开机。
现象 :本地对该服务器的 SSH / 部署 / API 请求全部超时(No route to host);8 个业务容器与网关随主机一起中断。
根因 :电源适配器摆放位置不当 ——适配器位于办公室饮水区 (人流量较大),且适配器/线缆长时间悬空 ,使供电接口受牵拉而松动、接触不良,最终断联断电 ;主机为联想 ThinkPad L540(20AVA023JP)笔记本 、自带电池,断电后靠电池运行约 4 小时(95%→0%)耗尽,触发系统低电关机(systemd-logind: The system will power off now!)。
伴随问题 :主机时钟比真实时间快 8 小时 ——硬件时钟(RTC)里存的是本地时间,却被系统当作 UTC,导致日志与记录时间整体偏移 8 小时,最初排查时所有时间点都需减 8 小时还原。
影响 :服务不可用约 9 分钟 (16:06:25–16:15:47);经检查数据库正常关闭、无数据损坏;中断期间无法上传/同步/推送。
处置 :① 恢复供电后主机重启,容器自动拉起(全部 healthy,网关 /health=200);② 校正时间——时区固定 Asia/Shanghai、系统时钟按真实时间重置、安装 util-linux-extra 并用 hwclock --systohc --utc 把 RTC 改存 UTC,避免重启后再次偏移 8 小时。
预防 :把电源适配器与插头移到人流少的固定位置并固定线缆,避免适配器悬空、接口受力松动 ;给该「服务器笔记本」接 UPS / 稳压电源;BIOS 开启「通电自动开机(AC Power On)」;建议启用 NTP 自动校时;继续沿用 /home/douxi/_nosleep.sh 的免休眠配置。
验证 :timedatectl 显示 Time zone: Asia/Shanghai (CST, +0800)、RTC time 等于系统 UTC;校正后本地时间 2026-09-28 16:26 CST ,与本地工作机一致。
附录 E:外网访问(域名 + HTTPS)与历史排障
2026-11 起变更: 系统已迁到云服务器,公网通过域名 + HTTPS 直接访问(douxi / api / manual 三个子域名),原「花生壳内网穿透」方案已停用 ;本节表格地址已更新为新域名,下文的花生壳排查步骤仅作历史参考。
普通用户只需使用下表地址,不需要在电脑上安装任何客户端 。
表 E-1 访问地址
E.1 使用注意
外网地址与局域网地址指向同一套系统 ,登录方式、账号、数据完全一致;接口自动走同域 /api,浏览器直接打开即可,无需任何配置。
手机可直接扫本手册封面的二维码打开(两个二维码分别对应上表两个地址)。
在服务器所在网络(同一出口 IP)内访问外网域名往往打不开 ,这是花生壳/路由的 NAT 回环现象,不是系统故障 ——请用手机流量 或其它外部网络验证。
免费线路带宽 1Mbps 、每月约 1GB 流量,适合外出应急查看;大批量导出请在局域网内操作。
外网域名只有在映射生效且设备在线 时才会解析;设备离线时域名会解析失败(NXDOMAIN)。
E.2 打不开时的自查顺序(管理员)
看映射 :登录 b.oray.com →「内网穿透」,两条映射(前端 → 192.168.0.128:8080、文档 → 192.168.0.128:8090)开关应为生效 ,且未超出映射数配额(体验版 2 条)。
看设备 :「设备列表」中承接映射的设备必须在线 ;登录控制台的账号必须与设备所属账号一致(否则设备列表为空、映射无人承接)。
只留一个客户端 :服务器上同时运行两个花生壳客户端会互相抢转发,这是最常见的故障原因。正确状态是官方客户端运行、AppKey 模式的 hsk 客户端停止并禁用:
systemctl status phddns_service # 应为 active
systemctl status hsk.service # 应为 inactive 且 disabled
若需要改回 AppKey 模式,则先停 phddns_service 再启 hsk.service,两者不要同时开 。
点诊断 :在控制台对该映射点「映射诊断」,「内网服务 / 花生壳客户端 / 花生壳服务器 / 域名解析」四项全绿即为正常。
查域名 :dig +short 666fe518ww51.vicp.fun @223.5.5.5 应返回花生壳中转 IP;若为 NXDOMAIN,说明映射未生效或设备不在线。
看日志 :官方客户端日志 /var/log/phddns/phtunnel.log,出现 create new forward tunnel(666fe518ww51.vicp.fun ...) 与 proxy(...) connecting 192.168.0.128:8080 即为正常转发;AppKey 模式客户端日志为 /home/douxi/hsk.log。
仍不通 :重启客户端 sudo systemctl restart phddns_service,然后重做第 4 步诊断。
E.3 外网地址变更时需同步修改
花生壳映射变更后,需同步更新:本手册封面(目录页二维码与地址)、1.1 步骤、第十章 FAQ、附录 A.3,以及封面二维码图片 docs/manual_images/qr-front-v2.png / qr-doc.png,再重新发布文档站点到服务器 /home/douxi/docs_site/(8090)。
二维码内容必须与实际外网地址一致;改地址时务必重新生成二维码 ,否则用户扫码会打开旧地址。
本手册随系统版本更新;如页面文字与手册不一致,以系统实际显示为准。仍有疑问请联系本大区经理或系统管理员。