Compare commits

..

24 Commits

Author SHA1 Message Date
freedakgmail 2fc1b96f44 feat: 新增db/pipeline数据导入管线,适配5月数据格式
- 整合所有导入脚本到db/pipeline/目录
- config.py: 按月份动态配置数据源路径,支持4月/5月不同目录结构
- import_bill_records_may.py: 5月专用账单导入(51列全渠道订单明细→bill_records + 50列品项销售明细→dish_sales_details)
- import_salary_attendance.py: 添加--salary-file/--attendance-file参数支持动态文件路径
- import_may_data.sh: 5月一键导入脚本(12步全流程)
- run_all.py: 一键全量导入+物化视图刷新编排
- refresh_materialized_views.py: 按依赖顺序刷新38个物化视图
- verify.py/verify_import.py: 数据一致性验证
- README.md: 管线文档
2026-08-18 22:17:26 +08:00
selfrelease 9b3a9cdb4b fix: 修复成本/库存/对账多页面数据准确性与展示问题
- 库存周转: turnover_days零消耗时返回NULL并显示"无消耗",排序至末尾;
  门店名称三级回退(dim_store→mv_distribution_monthly→硬编码中央厨房)
- 成本管理: estimated_inventory_days为NULL时显示"-"而非"0.0天";
  补充成本率口径与指标关系说明
- 成本分析: 修复理论成本率计算(按单位售价而非单价),新增sales_quantity展示;
  区分菜品级(Excel)与门店级(倒挤)成本指标,说明差异原因
- 配送对账: 区分中央厨房/门店,分层展示耗用口径
- 告警/任务/目标管理: 新增详情弹窗组件,优化交互体验

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-15 17:37:06 +08:00
selfrelease d373fb5f0c feat: 新增智脑决策中心模块(决策中心/AI员工组织/知识资产)
- 新增 DecisionsPage、AgentsPage、KnowledgePage 三个页面
- 新增 DecisionCard、DecisionDrawer、DecisionSummary、KnowledgeCard、LoopHealthBar、AgentCard 组件
- 新增 decision-aggregator 决策聚合逻辑和 agents 数据
- Layout 导航重构:新增智脑决策分组,调整系统配置和经营本体分组
- BossPage 集成决策摘要和闭环健康度,利润机会池支持警告样式
- TasksPage 增强任务展示
- 抽屉式详情统一改为居中弹窗风格
- data.ts 后端调整
- run.md 更新数据库连接说明
- 新增玄谋智脑实际版建设方案文档

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-14 19:34:04 +08:00
selfrelease 8fd74fd78c fix: 利润机会池改为门店级计算,修复整体平均掩盖问题门店
问题:利润机会池6项中有4项返回0,总额仅15.3万
原因:用整体平均费率判断是否超标,整体已达标则机会=0,
      掩盖了个别门店严重超标的问题

修复:
1. 食材成本差异回收:改用 mv_store_theoretical_actual_cost_monthly
   (门店级理论vs实际成本),只对正差异(超耗)门店求和 × 30%
   修复前 0 → 修复后 1,898,587
2. 标准店人工优化:改为门店级,只对费率>24%的门店计算机会
   修复前 0 → 修复后 1,561,133(58家超标)
3. 标准店能源优化:改为门店级,只对费率>5%的门店计算机会
   修复前 0 → 修复后 466,609(49家超标)
4. 平台佣金优化:改为门店级,只对佣金率>20%的门店计算机会
   修复前 0 → 修复后 3,430(1家超标)
5. 高优惠门店治理和SKU复杂度压缩逻辑不变

总额:152,995 → 4,082,755(约408万)

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-13 14:45:43 +08:00
selfrelease 85b58c53b1 fix: 修复利润机会池播报文案口径错误和承诺值硬编码
问题1(口径错误):
- BusinessReportDialog 用整体贡献率(10.96%)对比标准门店贡献率目标(10%)
- 10.96%→10% 是下降不是提升,逻辑矛盾
- 移除错误的贡献率对比,与 BossPage 口径一致

问题2(承诺值硬编码):
- "30天承诺值≥150万元" 硬编码,但 totalOpportunity 仅15.3万,差10倍
- 改为动态计算:承诺值 = 理论月度机会 × 80%(考虑项目重叠和促销弹性)
- 同步修复 BossPage.tsx 中相同问题

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-13 14:31:42 +08:00
selfrelease 7ea6a2515f docs: 归档历史文档 + 新增战略外脑实施方法论
- 归档根目录散落文档到 docs/20260812/ 和 docs/20260812-1/
- 新增 16-战略外脑实施方法论.md:七项能力、十二步工作法、AI与决策治理、成熟度和验收
- 新增 17-SBrainCO战略外脑建设对照表.md:方法论映射为领域模型、产品模块、API和分阶段待办
- 新增 调查表/战略外脑能力验收Checklist.csv:35项能力验收检查项
- 更新 01-总体框架与八步工作法.md:新增战略外脑扩展章节
- 更新 README.md:新增战略外脑体系导航

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-12 22:28:51 +08:00
selfrelease a0343294b6 docs: 新增八步工作法调查表体系与指标体系示例
- 新增调查表目录,包含6个步骤的CSV调查表/Checklist:
  - 步骤一:老板访谈调查表(30条)
  - 步骤二:数据现状调查表(50条)
  - 步骤三:中层访谈调查表(50条)
  - 步骤四:逻辑闭环验证Checklist(60条)
  - 步骤七:UIUX需求调查表(60条)
  - 步骤八:闭环优化反馈表(94条)
- 新增指标体系示例.csv(50项L0/L1/L2/闭环指标定义)
- 新增指标体系详细说明.md(业务作用、数据源、行业基准、映射矩阵、树状结构)
- 更新README.md:新增文档目录树状结构和阅读建议

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-12 11:48:42 +08:00
freedakgmail 64d2cd8043 重构智脑实施方法论:引入FDE模式,八步工作法,适配中国连锁经营企业国情 2026-08-12 11:32:51 +08:00
freedakgmail c2a9e27e49 docs: 新增智脑实施方法论文档体系(7篇) + fix: 态势感知关联分析修复
文档:
- 01-项目概述与架构: 技术架构、数据流、部署拓扑
- 02-数据接入与治理: 原始数据导入、物化视图、门店名映射
- 03-指标体系与API开发: 指标分层、SQL模式、常见陷阱
- 04-前端页面开发: 组件规范、页面模板、月份参数管理
- 05-部署与运维: 部署脚本、FRP隧道、PM2、备份
- 06-调试排查手册: 问题分类、8个实际案例、工具速查
- 07-通用方法论: 核心原则、实施阶段、快速复制Checklist

修复:
- situational-awareness.ts: salary_month→salary_period, 日期格式改中文
- 客流-人力匹配: 改用attendance_records打卡数据解析在岗人数
- 客流数据除以30天对齐日均
2026-08-12 11:00:54 +08:00
freedakgmail 2c5b03e41b fix: 修复多个API因schema前缀和不存在列导致的报错
- /stores/risk: 移除不存在的列名(risk_score等),改回SELECT *
- /platform/economics: 移除不存在的列名(platform_share等),改回SELECT *
- /stores/:code: 公司均值查询中移除mv_store_risk_rating_monthly不存在的列(repeat_rate_pct等)
- /channel: mv_channel_daily在public schema,移除错误的analytics.前缀
- 重建mv_risk_anomaly物化视图:异常阈值从0.05元提高到1元
2026-08-11 22:43:18 +08:00
freedakgmail 8f5271fcc6 fix: P2/P3审计问题修复 + 更新审计文档移除已修复问题
- 修复schema前缀:确认central_kitchen/mv_distribution/mv_dish_sales等表在public schema,撤销错误的analytics.前缀
- 移除API内部物化视图刷新:mv_distribution_monthly/mv_dish_sales_monthly改为console.warn
- 修复BOM树节点key:使用path字段替代material_code+level确保唯一性
- 修复HR人才矩阵potential_score:基于v3_learning_record动态计算替代硬编码60
- 修复StoreDetailPage公司均值:优先使用API返回的companyAvg
- 修复前端字段名匹配:discount_rate_pct/check_comment等
- 添加explicit column list和LIMIT到大型查询
- 更新数据溯源审计.md:移除全部52个已修复/确认无需修复的问题条目
2026-08-11 22:00:58 +08:00
freedakgmail 915345bfd6 fix: 统一利润瀑布口径,与费用总览API一致
profit-waterfall API的received/consumption/discount/store_contribution
改为仅计算has_expense门店(FILTER WHERE has_expense)
修复前: received=6441万(94家) store_contribution=770万
修复后: received=6369万(92家) store_contribution=698万
现在瀑布图和指标卡的贡献利润/食材率/费用率/贡献率完全一致

同时创建数据溯源审计文档,覆盖全部页面的指标溯源和口径对比
2026-08-11 20:13:58 +08:00
freedakgmail 5ffde42590 fix: 修复/overview API理论毛利率和会员占比硬编码为0
- theoretical_margin_pct: 从bill_fact实时计算 sum(theoretical_profit)/sum(received)*100
- member_share_pct: 从bill_fact实时计算 会员账单实收/总实收*100
- member_bills: 统计member_id非空的账单数
- 修复前: 理论毛利率0% 会员占比0%
- 修复后: 理论毛利率61.84% 会员占比14.25%
2026-08-11 20:04:36 +08:00
freedakgmail baa49d1a94 fix: 刷新mv_overview_monthly,修复实收口径不一致
mv_overview_monthly是普通表不是物化视图,需要DELETE+INSERT更新
之前未刷新导致/overview API返回旧数据(6083万 vs bill_fact 6441万)
刷新脚本加入mv_overview_monthly更新步骤
2026-08-11 20:02:41 +08:00
freedakgmail b2cdf352db fix: 修复老板驾驶舱与总部驾驶舱实收数据源不一致
BossPage核心指标行的优惠和实收从/store-expense/overview改为/overview API
- 优惠: ex.total_discount → od.discount
- 实收总额: ex.total_received → od.received
- totalRev(风险门店占比分母)同步改为od.received
现在两个驾驶舱的营业收入/优惠/实收完全一致
2026-08-11 19:58:22 +08:00
freedakgmail 2a3805c44f fix: 修复费用总览API两个错误
1. 费用率公式反转: (1-expense/received)*100 → expense/matched_received*100
   修复前: 46.83%(实际是非费用率)→ 修复后: 53.77%(正确费用率)
2. 利润口径不一致: sum(received)含全部94家门店,但费用只含92家匹配门店
   修复: 利润和各项率指标分母改为仅匹配门店实收(matched_received)
   实际贡献利润: 7,703,472→6,982,110 贡献率: 11.96%→10.96%
2026-08-11 19:54:23 +08:00
freedakgmail a090fc7c19 fix: 修复API数据正确性问题
- 移除3个API的operating_expense IS NOT NULL过滤,改用COALESCE
  - /overview/store-profit-ranking: 93家门店全部纳入排名
  - /overview/profit-opportunity: 所有有营收门店纳入机会计算
  - /overview/profit-trend: LEFT JOIN替代INNER JOIN
- 重建v_store_operating_expense_monthly视图,去除硬编码_april视图
  - sales CTE改用mv_store_site_profile_monthly
  - food CTE改用mv_store_theoretical_actual_cost_monthly
  - 支持任意月份查询
- 修复人工优化和能源优化opportunity为负数问题
- 新增scripts/refresh_materialized_views.sh自动化刷新脚本
- 新增本体.md/API.md/原始数据级导入处理.md/物化视图更新.md/API数据检查报告.md
2026-08-11 19:25:49 +08:00
freedakgmail 3f1c291486 fix: 修复门店评估数据不一致问题
- 恢复被误删的5家门店旧账单数据(58377行)
- 合并哈马尔罕大钟寺店费用到大钟寺店(0022)
- 修改v_store_operating_expense_monthly视图按sales_store_code聚合费用
- 修复利润机会池食材成本差异为负时opportunity不为负
- 修复前端totalOpportunity只累加正数机会
- 刷新bill_fact/mv_store_risk_rating_monthly等物化视图
- 新增PromotionPage和promotion路由
2026-08-11 07:26:11 +08:00
freedakgmail 353dad24a2 feat: 添加企业智脑建设方案HTML演示和企业AI协调师培养方案HTML演示,均适配手机端 2026-08-09 11:42:23 +08:00
freedakgmail d04e837d9c V3.0: 门店分级与风险等级页面、数据填充脚本、后端API
- 新增V3.0数据库表结构(12-15)和数据填充脚本(16)
- 新增后端路由: store-grade, enterprise, product, intelligence, alert, scheduler, target
- 新增前端页面: StoreGradePage, EnterprisePage, ProductLifecyclePage, IntelligencePage, AlertManagementPage, DataImportPage, SchedulerManagementPage, TargetManagementPage
- 门店分级: 自动分级算法(达成率40%+毛利率25%+会员15%+风险20%)
- 风险等级: 基于mv_store_risk_rating模型展示风险分布和原因
- 弹窗: 雷达图+详细指标+分级原因+风险原因(primary_issue)
- FilterableTable: filterOptions支持{value,label}对象格式
2026-08-05 20:09:39 +08:00
selfrelease 814abf4a68 docs: V3.0完整任务清单(115项) + AI讲师培训文档 2026-08-05 11:15:54 +08:00
selfrelease 4d929e3361 docs: 添加AI讲师简介与培训大纲(制造业方向)
面向大型制造企业AI培训项目,包含讲师简介、核心观点、
汽车后市场及餐饮连锁两个"从外行到资深"案例、培训大纲。

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-05 10:41:07 +08:00
selfrelease a56d187f26 fix: 移除tsconfig.json中已弃用的baseUrl选项 2026-08-04 15:14:23 +08:00
selfrelease b6fe2d0e23 docs: V3.0系统实现路径与数据支撑度分析 2026-08-04 14:19:04 +08:00
165 changed files with 36862 additions and 584 deletions
+1
View File
@@ -18,3 +18,4 @@ backups/
.playwright-cli/
.tmp/
数据/
__pycache__/
+24
View File
@@ -24,6 +24,9 @@ import { SiteSelectionPage } from '@/pages/SiteSelectionPage'
import { SmartSchedulingPage } from '@/pages/SmartSchedulingPage'
import { SituationalAwarenessPage } from '@/pages/SituationalAwarenessPage'
import { BossPage } from '@/pages/BossPage'
import { DecisionsPage } from '@/pages/DecisionsPage'
import { AgentsPage } from '@/pages/AgentsPage'
import { KnowledgePage } from '@/pages/KnowledgePage'
import { RevenuePage } from '@/pages/RevenuePage'
import { BankPage } from '@/pages/BankPage'
import { CentralKitchenPage } from '@/pages/CentralKitchenPage'
@@ -38,6 +41,15 @@ import { EmployeePerformancePage } from '@/pages/EmployeePerformancePage'
import { InventoryTurnoverPage } from '@/pages/InventoryTurnoverPage'
import { TenantManagementPage } from './pages/TenantManagementPage'
import { TenantUsersPage } from './pages/TenantUsersPage'
import { TargetManagementPage } from './pages/TargetManagementPage'
import { AlertManagementPage } from './pages/AlertManagementPage'
import { SchedulerManagementPage } from './pages/SchedulerManagementPage'
import { StoreGradePage } from './pages/StoreGradePage'
import { ProductLifecyclePage } from './pages/ProductLifecyclePage'
import { DataImportPage } from './pages/DataImportPage'
import { EnterprisePage } from './pages/EnterprisePage'
import { IntelligencePage } from './pages/IntelligencePage'
import { PromotionPage } from './pages/PromotionPage'
import { RoleRoute } from './components/RoleRoute'
const queryClient = new QueryClient({
@@ -83,6 +95,9 @@ export default function App() {
<Routes>
<Route path="/" element={user?.role === 'platform_admin' ? <Navigate to="/tenant-management" /> : user?.role === 'store' ? <Navigate to="/store" /> : user?.role === 'regional' ? <Navigate to="/regional" /> : <DashboardPage />} />
<Route path="/boss" element={<RoleRoute roles={['hq','dept']}><BossPage /></RoleRoute>} />
<Route path="/decisions" element={<RoleRoute roles={['hq','dept']}><DecisionsPage /></RoleRoute>} />
<Route path="/agents" element={<RoleRoute roles={['hq','dept']}><AgentsPage /></RoleRoute>} />
<Route path="/knowledge" element={<RoleRoute roles={['hq','dept']}><KnowledgePage /></RoleRoute>} />
<Route path="/revenue" element={<RoleRoute roles={['hq','dept']}><RevenuePage /></RoleRoute>} />
<Route path="/bank" element={<RoleRoute roles={['hq']}><BankPage /></RoleRoute>} />
<Route path="/central-kitchen" element={<RoleRoute roles={['hq','dept']}><CentralKitchenPage /></RoleRoute>} />
@@ -117,6 +132,15 @@ export default function App() {
<Route path="/inventory-turnover" element={<RoleRoute roles={['hq','dept']}><InventoryTurnoverPage /></RoleRoute>} />
<Route path="/tenant-management" element={<RoleRoute roles={['platform_admin']}><TenantManagementPage /></RoleRoute>} />
<Route path="/tenant-users" element={<RoleRoute roles={['hq']}><TenantUsersPage /></RoleRoute>} />
<Route path="/target" element={<RoleRoute roles={['hq','dept','regional']}><TargetManagementPage /></RoleRoute>} />
<Route path="/alert" element={<RoleRoute roles={['hq','dept','regional','store']}><AlertManagementPage /></RoleRoute>} />
<Route path="/scheduler" element={<RoleRoute roles={['hq']}><SchedulerManagementPage /></RoleRoute>} />
<Route path="/store-grade" element={<RoleRoute roles={['hq','dept','regional']}><StoreGradePage /></RoleRoute>} />
<Route path="/product-lifecycle" element={<RoleRoute roles={['hq','dept']}><ProductLifecyclePage /></RoleRoute>} />
<Route path="/data-import" element={<RoleRoute roles={['hq','dept']}><DataImportPage /></RoleRoute>} />
<Route path="/enterprise" element={<RoleRoute roles={['hq','dept']}><EnterprisePage /></RoleRoute>} />
<Route path="/intelligence" element={<RoleRoute roles={['hq','dept']}><IntelligencePage /></RoleRoute>} />
<Route path="/promotion" element={<RoleRoute roles={['hq','dept']}><PromotionPage /></RoleRoute>} />
<Route path="*" element={<Navigate to="/" />} />
</Routes>
</Layout>
+74
View File
@@ -0,0 +1,74 @@
/**
* AI 员工卡片组件
*
* 展示单个 AI 员工的岗位、职责、自治等级和今日交付数。
*/
import { Bot } from 'lucide-react'
import { cn } from '@/lib/utils'
import type { AgentConfig } from '@/data/agents'
interface AgentCardProps {
agent: AgentConfig
/** 今日交付数(null 表示加载中) */
deliveries: number | null
onClick?: () => void
}
/** 自治等级颜色 */
const AUTONOMY_COLORS: Record<string, string> = {
L1: 'bg-red-50 text-red-600 border border-red-200',
L2: 'bg-amber-50 text-amber-600 border border-amber-200',
L3: 'bg-green-50 text-green-600 border border-green-200',
}
/** 状态指示灯颜色 */
const STATUS_DOT: Record<string, string> = {
'运行中': 'bg-green-500',
'待审批': 'bg-amber-500',
'受控': 'bg-blue-500',
}
export function AgentCard({ agent, deliveries, onClick }: AgentCardProps) {
return (
<div
className={cn(
'rounded-lg border bg-card p-4 transition-shadow hover:shadow-sm',
onClick && 'cursor-pointer',
)}
onClick={onClick}
>
{/* 头部:图标 + 状态灯 */}
<div className="mb-2 flex items-start justify-between">
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-50">
<Bot className="h-5 w-5 text-blue-600" />
</div>
<span
className={cn(
'mt-1 h-2 w-2 rounded-full',
STATUS_DOT[agent.status] || 'bg-gray-400',
)}
title={agent.status}
/>
</div>
{/* 名称 + 领域 */}
<small className="text-[10px] text-muted-foreground">{agent.domain}</small>
<h3 className="text-sm font-bold">{agent.name}</h3>
<p className="mt-1 text-xs text-muted-foreground">{agent.roleTarget}</p>
{/* 底部:自治等级 + 交付数 */}
<footer className="mt-3 flex items-center justify-between border-t pt-2">
<span className={cn('rounded px-1.5 py-0.5 text-[10px] font-medium', AUTONOMY_COLORS[agent.autonomyLevel])}>
{agent.autonomyLevel}
</span>
<span className="text-xs text-muted-foreground">
{deliveries === null ? (
<span className="text-muted-foreground"></span>
) : (
<><b className="text-foreground">{deliveries}</b> </>
)}
</span>
</footer>
</div>
)
}
+239
View File
@@ -0,0 +1,239 @@
/**
* AI 员工详情弹窗
*
* 点击 AgentCard 后弹出,展示完整能力描述、数据来源 API、今日交付明细列表,
* 并提供跳转到对应业务页面的按钮。
*/
import { useQuery } from '@tanstack/react-query'
import { useNavigate } from 'react-router-dom'
import { X, ExternalLink, Bot } from 'lucide-react'
import api from '@/lib/api'
import { cn, formatCurrency, formatNumber } from '@/lib/utils'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import type { AgentConfig } from '@/data/agents'
interface AgentDetailDialogProps {
agent: AgentConfig
deliveries: number | null
onClose: () => void
}
const AUTONOMY_LABELS: Record<string, string> = {
L1: 'L1 人工审批',
L2: 'L2 受控执行',
L3: 'L3 全自动',
}
const AUTONOMY_COLORS: Record<string, string> = {
L1: 'bg-red-50 text-red-600 border border-red-200',
L2: 'bg-amber-50 text-amber-600 border border-amber-200',
L3: 'bg-green-50 text-green-600 border border-green-200',
}
const STATUS_DOT: Record<string, string> = {
'运行中': 'bg-green-500',
'待审批': 'bg-amber-500',
'受控': 'bg-blue-500',
}
/** 后端统计字段名 → 中文标签映射(用于对象型 API 响应的统计卡片展示) */
const FIELD_LABELS: Record<string, string> = {
// 门店/成本总览
total_stores: '门店总数',
profitable_stores: '盈利门店',
loss_stores: '亏损门店',
no_expense_stores: '缺费用数据门店',
total_bills: '账单总数',
total_received: '实收合计',
total_consumption: '消费合计',
total_discount: '优惠合计',
total_expense: '费用合计',
total_wage: '人工合计',
total_rent: '房租合计',
total_utility: '水电合计',
total_dorm: '宿舍合计',
total_commission: '佣金合计',
total_card_fee: '刷卡手续费',
total_repair: '维修保洁',
total_food_cost: '食材成本',
total_theoretical_cost: '理论成本',
total_contribution: '贡献利润',
total_theoretical_contribution: '理论贡献',
theoretical_net_profit: '理论净利润',
actual_net_profit: '实际净利润',
total_area: '总面积',
overall_expense_rate_pct: '费用率%',
overall_contribution_rate_pct: '贡献率%',
theoretical_net_margin_pct: '理论净利率%',
actual_net_margin_pct: '实际净利率%',
theoretical_food_cost_rate_pct: '理论食材成本率%',
actual_food_cost_rate_pct: '实际食材成本率%',
overall_wage_rate_pct: '人工费率%',
overall_rent_rate_pct: '房租费率%',
overall_utility_rate_pct: '水电费率%',
// 成本分析
red_count: '红色严重超耗',
orange_count: '橙色明显超耗',
green_count: '绿色基本正常',
gray_count: '灰色口径异常',
total_variance: '差异合计',
// 告警总览
total_alerts: '告警总数',
red_alerts: '红色告警',
yellow_alerts: '黄色告警',
pending_alerts: '待处理告警',
resolved_alerts: '已处理告警',
today_alerts: '今日告警',
}
/** 数值字段格式化 */
function formatCell(value: any): string {
if (value === null || value === undefined || value === '') return '-'
const num = Number(value)
if (!isNaN(num) && typeof value !== 'string' && value !== null) {
return formatNumber(num)
}
return String(value)
}
export function AgentDetailDialog({ agent, deliveries, onClose }: AgentDetailDialogProps) {
const navigate = useNavigate()
// 获取今日交付明细原始数据
const { data: rawData, isLoading } = useQuery({
queryKey: ['agent-delivery-detail', agent.code],
queryFn: () => {
// /overview/profit-opportunity 需要 month 参数(与 AgentsPage chiefQuery 一致)
const params = agent.deliveryApi === '/overview/profit-opportunity' ? { month: '2026-04' } : undefined
return api.get(agent.deliveryApi || '', { params })
},
enabled: !!agent.deliveryApi,
staleTime: 5 * 60 * 1000,
})
// 从响应中提取明细数据
const root = rawData as any
const dataField = root?.data
// 支持 items 嵌套(如 profit-opportunity 返回 { items: [...] }
const items: any[] = Array.isArray(dataField) ? dataField : Array.isArray(dataField?.items) ? dataField.items : []
const stats: Record<string, any> | null = !Array.isArray(dataField) && !dataField?.items && dataField && typeof dataField === 'object' ? dataField : null
const top10 = items.slice(0, 10)
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/30" onClick={onClose}>
<div
className="max-h-[85vh] w-[680px] max-w-[95vw] overflow-y-auto rounded-lg border bg-card p-6 shadow-lg"
onClick={(e) => e.stopPropagation()}
>
{/* 标题栏 */}
<div className="mb-4 flex items-start justify-between">
<div className="flex items-start gap-3">
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-blue-50">
<Bot className="h-6 w-6 text-blue-600" />
</div>
<div>
<div className="flex items-center gap-2">
<small className="text-[10px] text-muted-foreground">{agent.domain}</small>
<span className={cn('h-2 w-2 rounded-full', STATUS_DOT[agent.status] || 'bg-gray-400')} />
<small className="text-[10px] text-muted-foreground">{agent.status}</small>
</div>
<h2 className="text-lg font-bold">{agent.name}</h2>
<p className="text-sm text-muted-foreground">{agent.roleTarget}</p>
</div>
</div>
<button onClick={onClose} className="rounded-md p-1 hover:bg-muted">
<X className="h-5 w-5" />
</button>
</div>
{/* 基本信息标签 */}
<div className="mb-4 flex flex-wrap gap-2">
<span className={cn('rounded px-2 py-0.5 text-xs font-medium', AUTONOMY_COLORS[agent.autonomyLevel])}>
{AUTONOMY_LABELS[agent.autonomyLevel]}
</span>
<span className="rounded border px-2 py-0.5 text-xs font-medium text-muted-foreground">
<b className="text-foreground">{deliveries ?? '…'}</b>
</span>
</div>
{/* 能力描述 */}
<section className="mb-4">
<h3 className="mb-1 text-sm font-bold"> SBrainCO </h3>
<div className="rounded-lg border bg-muted/20 p-3">
<p className="text-sm leading-relaxed text-muted-foreground">{agent.capability}</p>
</div>
</section>
{/* 数据来源 API */}
{agent.deliveryApi && (
<section className="mb-4">
<h3 className="mb-1 text-sm font-bold"></h3>
<div className="rounded-lg border bg-muted/20 p-3 font-mono text-xs">
<p><span className="text-muted-foreground">API:</span> GET {agent.deliveryApi}</p>
<p><span className="text-muted-foreground">:</span> {agent.deliveryField}</p>
</div>
</section>
)}
{/* 今日交付明细 */}
{agent.deliveryApi && (
<section className="mb-4">
<h3 className="mb-2 text-sm font-bold">{items.length > 10 ? `(前 10 条 / 共 ${items.length} 条)` : stats ? '' : `(共 ${items.length} 条)`}</h3>
{isLoading ? (
<LoadingSpinner />
) : top10.length > 0 && agent.deliveryColumns ? (
<div className="overflow-hidden rounded-lg border">
<table className="w-full text-xs">
<thead className="bg-muted/30 text-muted-foreground">
<tr>
{agent.deliveryColumns.map((col) => (
<th key={col.field} className="border-b px-3 py-2 text-left font-medium">{col.label}</th>
))}
</tr>
</thead>
<tbody>
{top10.map((row, i) => (
<tr key={i} className="border-b last:border-0 hover:bg-muted/20">
{agent.deliveryColumns!.map((col) => (
<td key={col.field} className="px-3 py-2">{formatCell(row[col.field])}</td>
))}
</tr>
))}
</tbody>
</table>
</div>
) : stats ? (
<div className="grid grid-cols-2 gap-2 sm:grid-cols-3">
{Object.entries(stats).slice(0, 12).map(([key, val]) => (
<div key={key} className="rounded-lg border p-2">
<p className="text-[10px] text-muted-foreground">{FIELD_LABELS[key] || key}</p>
<p className="text-sm font-bold">{formatCell(val)}</p>
</div>
))}
</div>
) : (
<p className="text-xs text-muted-foreground"></p>
)}
</section>
)}
{/* 底部操作 */}
{agent.businessPage && (
<div className="flex justify-end border-t pt-4">
<button
className="flex items-center gap-1.5 rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700"
onClick={() => {
onClose()
navigate(agent.businessPage!)
}}
>
<ExternalLink className="h-4 w-4" />
</button>
</div>
)}
</div>
</div>
)
}
@@ -0,0 +1,369 @@
/**
* 预警日志详情弹窗
*
* 点击预警日志行后弹出,展示完整预警信息、指标解释、问题诊断和整改建议,
* 并支持处理操作。
*/
import { useState } from 'react'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { X, AlertTriangle, CheckCircle, EyeOff, Stethoscope, Wrench } from 'lucide-react'
import api from '@/lib/api'
import { cn } from '@/lib/utils'
interface AlertLog {
id: number
rule_id: number | null
rule_name: string
store_code: string
store_name: string
metric_value: number | string
threshold: number | string
severity: string
push_status: string | null
handle_status: string
handle_comment: string | null
triggered_at: string
handled_at: string | null
}
interface AlertLogDetailDialogProps {
log: AlertLog
onClose: () => void
}
const SEVERITY_LABELS: Record<string, string> = { red: '红灯', yellow: '黄灯', green: '绿灯' }
const SEVERITY_COLORS: Record<string, string> = {
red: 'bg-red-100 text-red-700 border-red-200',
yellow: 'bg-yellow-100 text-yellow-700 border-yellow-200',
green: 'bg-green-100 text-green-700 border-green-200',
}
const STATUS_LABELS: Record<string, string> = { pending: '待处理', handling: '处理中', resolved: '已解决', ignored: '已忽略' }
const STATUS_COLORS: Record<string, string> = {
pending: 'bg-gray-100 text-gray-600 border-gray-200',
handling: 'bg-blue-100 text-blue-700 border-blue-200',
resolved: 'bg-green-100 text-green-700 border-green-200',
ignored: 'bg-gray-100 text-gray-500 border-gray-200',
}
const PUSH_LABELS: Record<string, string> = {
pending: '待推送',
pushed: '已推送',
failed: '推送失败',
null: '未推送',
}
/** 按规则名称映射:指标解释、问题诊断、整改建议 */
const RULE_DETAILS: Record<string, {
metricLabel: string
metricUnit: string
thresholdDesc: string
problemDiagnosis: string[]
remediation: string[]
}> = {
'营收达成率红灯': {
metricLabel: '营收达成率',
metricUnit: '%',
thresholdDesc: '阈值 80%,低于此值表示门店日营收远低于目标,存在严重经营风险',
problemDiagnosis: [
'门店实际营收显著低于目标设定值,达成率不足 80%',
'可能原因:客流下降、客单价下滑、促销活动效果不佳、周边竞争加剧',
'需排查是目标设定过高还是实际经营下滑',
],
remediation: [
'店长复盘当日客流与客单价数据,定位下滑原因',
'区域经理 48 小时内到店诊断,提交改善方案',
'检查近期是否有竞争对手开业或促销活动影响',
'若目标设定不合理(如新店按成熟店标准),申请调整目标基准',
'连续 3 天低于 80% 升级为专项整改任务',
],
},
'营收达成率黄灯': {
metricLabel: '营收达成率',
metricUnit: '%',
thresholdDesc: '阈值 90%,低于此值表示门店营收未达预期,需关注',
problemDiagnosis: [
'门店营收达成率在 80%-90% 之间,未达预期但尚未严重恶化',
'可能原因:天气影响、节假日因素、短期客流波动',
],
remediation: [
'店长关注每日营收趋势,记录异常原因',
'区域经理周检时复盘,判断是否为偶发或趋势性下滑',
'若连续一周低于 90%,启动改善行动',
],
},
'毛利率异常': {
metricLabel: '理论毛利率',
metricUnit: '%',
thresholdDesc: '阈值 40%,低于此值表示食材成本占比过高,利润空间被压缩',
problemDiagnosis: [
'理论毛利率低于 40%,食材成本占营收比超过 60%',
'可能原因:菜品定价偏低、食材采购价上涨、BOM 配方不合理、高成本菜品占比过高',
],
remediation: [
'菜品利润优化师核查 BOM 配方与实际用量差异',
'供应链排查近期食材采购单价是否异常上涨',
'菜单工程分析:评估低毛利菜品占比,考虑优化或淘汰',
'门店检查是否存在超量出品或标准执行偏差',
],
},
'会员渗透率低': {
metricLabel: '会员账单占比',
metricUnit: '%',
thresholdDesc: '阈值 20%,低于此值表示会员消费占比过低,复购潜力未释放',
problemDiagnosis: [
'会员账单占比低于 20%,非会员消费为主,顾客粘性不足',
'可能原因:会员权益吸引力不够、店员未主动引导注册、周边客群流动性大',
],
remediation: [
'会员运营师分析该店会员画像与复购率',
'门店加强收银环节会员注册引导,设定周注册目标',
'评估会员权益是否需要针对该店客群调整',
'推送定向优惠券激活沉默会员',
],
},
'客诉率偏高': {
metricLabel: '客诉率',
metricUnit: '%',
thresholdDesc: '阈值 5%,超过此值表示顾客投诉比例过高,严重影响品牌口碑',
problemDiagnosis: [
'客诉率超过 5%,顾客投诉频次异常偏高',
'可能原因:出品质量不稳定、服务态度差、环境卫生问题、等待时间过长',
],
remediation: [
'店长 24 小时内复盘投诉内容,分类归因',
'出品问题:核查食材新鲜度与制作标准执行',
'服务问题:安排员工服务培训,加强现场管理',
'连续 2 周客诉率超 5% 升级为总部督办事项',
],
},
'巡检低分': {
metricLabel: '食安巡检得分',
metricUnit: '分',
thresholdDesc: '阈值 90 分,低于此值表示食品安全巡检不达标,存在合规风险',
problemDiagnosis: [
'食安巡检得分低于 90 分,食品安全管理存在漏洞',
'可能原因:食材储存不规范、加工区域卫生不达标、员工操作不规范',
],
remediation: [
'店长立即整改巡检扣分项,48 小时内提交整改报告',
'区域经理安排复查,确认整改到位',
'对扣分项涉及员工进行专项培训',
'连续 2 次低分暂停该店评级资格',
],
},
'离职率偏高': {
metricLabel: '月度离职率',
metricUnit: '%',
thresholdDesc: '阈值 15%,超过此值表示人员流失严重,影响门店稳定运营',
problemDiagnosis: [
'月度离职率超过 15%,人员流失过快',
'可能原因:薪酬竞争力不足、管理风格问题、工作强度过大、晋升通道不清晰',
],
remediation: [
'区域经理访谈离职员工,收集真实离职原因',
'人力部门评估该店薪酬水平与市场对标',
'店长管理风格评估,必要时安排管理培训',
'制定留人方案:调薪、排班优化、职业发展规划',
],
},
}
/** 通用兜底:未匹配到规则名时使用 */
const DEFAULT_DETAIL = {
metricLabel: '监控指标',
metricUnit: '',
thresholdDesc: '指标超出预设阈值范围',
problemDiagnosis: ['指标异常触发预警,需进一步排查具体原因'],
remediation: ['请相关负责人核查指标数据并制定改善方案'],
}
function formatTime(s: string | null): string {
if (!s) return '-'
return s.substring(0, 19).replace('T', ' ')
}
export function AlertLogDetailDialog({ log, onClose }: AlertLogDetailDialogProps) {
const queryClient = useQueryClient()
const [comment, setComment] = useState(log.handle_comment || '')
const handleMutation = useMutation({
mutationFn: (data: { id: number; handle_status: string; handle_comment?: string }) =>
api.patch(`/alert/logs/${data.id}`, { handle_status: data.handle_status, handle_comment: data.handle_comment }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['alert/logs'] })
queryClient.invalidateQueries({ queryKey: ['alert/overview'] })
onClose()
},
})
const isPending = log.handle_status === 'pending'
const detail = RULE_DETAILS[log.rule_name] || DEFAULT_DETAIL
const metricValue = Number(log.metric_value || 0)
const threshold = Number(log.threshold || 0)
const deviation = metricValue - threshold
const isLowerBetter = log.rule_name.includes('达成率') || log.rule_name.includes('毛利率') || log.rule_name.includes('渗透率') || log.rule_name.includes('巡检')
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/30" onClick={onClose}>
<div
className="max-h-[88vh] w-[640px] max-w-[95vw] overflow-y-auto rounded-lg border bg-card p-6 shadow-lg"
onClick={(e) => e.stopPropagation()}
>
{/* 标题栏 */}
<div className="mb-4 flex items-start justify-between">
<div className="flex items-start gap-3">
<div className={cn('flex h-10 w-10 items-center justify-center rounded-lg', SEVERITY_COLORS[log.severity] || 'bg-gray-100')}>
<AlertTriangle className="h-5 w-5" />
</div>
<div>
<h2 className="text-base font-bold">{log.rule_name}</h2>
<p className="text-xs text-muted-foreground"> #{log.id} · {log.store_name || '-'}</p>
</div>
</div>
<button onClick={onClose} className="rounded-md p-1 hover:bg-muted">
<X className="h-5 w-5" />
</button>
</div>
{/* 状态标签 */}
<div className="mb-4 flex flex-wrap gap-2">
<span className={cn('rounded border px-2 py-0.5 text-xs font-medium', SEVERITY_COLORS[log.severity] || '')}>
{SEVERITY_LABELS[log.severity] || log.severity}
</span>
<span className={cn('rounded border px-2 py-0.5 text-xs font-medium', STATUS_COLORS[log.handle_status] || '')}>
{STATUS_LABELS[log.handle_status] || log.handle_status}
</span>
<span className="rounded border border-gray-200 bg-gray-50 px-2 py-0.5 text-xs font-medium text-gray-600">
{PUSH_LABELS[log.push_status || 'null'] || log.push_status || '-'}
</span>
</div>
{/* 指标对比 */}
<section className="mb-4">
<h3 className="mb-2 text-sm font-bold"></h3>
<div className="grid grid-cols-3 gap-2 rounded-lg border bg-muted/20 p-3">
<div className="text-center">
<p className="text-[10px] text-muted-foreground">{detail.metricLabel}</p>
<p className={cn('text-lg font-bold', isLowerBetter ? 'text-red-600' : 'text-green-600')}>
{metricValue.toFixed(2)}{detail.metricUnit}
</p>
</div>
<div className="text-center">
<p className="text-[10px] text-muted-foreground"></p>
<p className="text-lg font-bold text-muted-foreground">
{threshold.toFixed(2)}{detail.metricUnit}
</p>
</div>
<div className="text-center">
<p className="text-[10px] text-muted-foreground"></p>
<p className={cn('text-lg font-bold', deviation < 0 ? 'text-red-600' : 'text-amber-600')}>
{deviation > 0 ? '+' : ''}{deviation.toFixed(2)}{detail.metricUnit}
</p>
</div>
</div>
<p className="mt-2 text-xs text-muted-foreground">{detail.thresholdDesc}</p>
</section>
{/* 基本信息字段 */}
<section className="mb-4">
<h3 className="mb-2 text-sm font-bold"></h3>
<div className="grid grid-cols-2 gap-2 rounded-lg border bg-muted/20 p-3 text-sm sm:grid-cols-3">
<div>
<p className="text-[10px] text-muted-foreground"></p>
<p className="font-medium">{log.store_name || '-'}</p>
</div>
<div>
<p className="text-[10px] text-muted-foreground">ID</p>
<p className="font-medium">{log.rule_id || '-'}</p>
</div>
<div>
<p className="text-[10px] text-muted-foreground"></p>
<p className="font-medium">{formatTime(log.triggered_at)}</p>
</div>
<div>
<p className="text-[10px] text-muted-foreground"></p>
<p className="font-medium">{formatTime(log.handled_at)}</p>
</div>
</div>
</section>
{/* 问题诊断 */}
<section className="mb-4">
<h3 className="mb-2 flex items-center gap-1.5 text-sm font-bold">
<Stethoscope className="h-4 w-4 text-amber-600" />
</h3>
<div className="rounded-lg border border-amber-200 bg-amber-50/40 p-3">
<ul className="space-y-1.5">
{detail.problemDiagnosis.map((d, i) => (
<li key={i} className="flex gap-2 text-xs leading-relaxed text-foreground">
<span className="mt-0.5 shrink-0 text-amber-600"></span>
<span>{d}</span>
</li>
))}
</ul>
</div>
</section>
{/* 整改建议 */}
<section className="mb-4">
<h3 className="mb-2 flex items-center gap-1.5 text-sm font-bold">
<Wrench className="h-4 w-4 text-blue-600" />
</h3>
<div className="rounded-lg border border-blue-200 bg-blue-50/40 p-3">
<ol className="space-y-1.5">
{detail.remediation.map((r, i) => (
<li key={i} className="flex gap-2 text-xs leading-relaxed text-foreground">
<span className="mt-0.5 shrink-0 font-bold text-blue-600">{i + 1}.</span>
<span>{r}</span>
</li>
))}
</ol>
</div>
</section>
{/* 处理备注 */}
<section className="mb-4">
<h3 className="mb-1 text-sm font-bold"></h3>
<textarea
className="w-full rounded-lg border p-2 text-sm"
rows={2}
placeholder="输入处理说明..."
value={comment}
onChange={(e) => setComment(e.target.value)}
disabled={!isPending}
/>
</section>
{/* 底部操作 */}
{isPending ? (
<div className="mt-4 flex gap-2 border-t pt-4">
<button
className="flex flex-1 items-center justify-center gap-1.5 rounded-md bg-green-600 px-4 py-2 text-sm font-medium text-white hover:bg-green-700 disabled:opacity-50"
onClick={() => handleMutation.mutate({ id: log.id, handle_status: 'resolved', handle_comment: comment || '已处理' })}
disabled={handleMutation.isPending}
>
<CheckCircle className="h-4 w-4" />
{handleMutation.isPending ? '处理中…' : '标记为已解决'}
</button>
<button
className="flex flex-1 items-center justify-center gap-1.5 rounded-md border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-muted disabled:opacity-50"
onClick={() => handleMutation.mutate({ id: log.id, handle_status: 'ignored', handle_comment: comment || '已忽略' })}
disabled={handleMutation.isPending}
>
<EyeOff className="h-4 w-4" />
</button>
</div>
) : (
<div className="mt-4 border-t pt-4">
<p className="text-xs text-muted-foreground">
{STATUS_LABELS[log.handle_status] || log.handle_status}
{log.handle_comment && <>{log.handle_comment}</>}
</p>
</div>
)}
</div>
</div>
)
}
@@ -50,13 +50,16 @@ export function BusinessReportDialog({ open, onClose, data }: BusinessReportDial
const expenseRate = wf ? (Number(wf.total_expense) / Number(wf.received) * 100) : 0
const contributionRate = wf ? (Number(wf.store_contribution) / Number(wf.received) * 100) : 0
// 30天承诺值:取理论月度机会的80%(考虑项目重叠和促销弹性),不低于0
const commitValue = Math.max(Math.round(totalOpp * 0.8), 0)
const otherStores = (ex?.total_stores || 0) - (ex?.profitable_stores || 0) - (ex?.loss_stores || 0)
const reportText = `本月经营态势报告,${data.month}月。
一、整体经营。营业收入${formatCurrency(ex?.total_consumption)},优惠${formatCurrency(ex?.total_discount)},实收总额${formatCurrency(ex?.total_received)},环比上周${data.trendReceived > 0 ? '增长' : '下降'}${Math.abs(data.trendReceived)}%。门店共${ex?.total_stores}家,其中盈利${ex?.profitable_stores}家,亏损${ex?.loss_stores}${otherStores > 0 ? `,待确认${otherStores}` : ''}。客单价${formatCurrency(ex?.avg_bill_value)},账单${ex?.total_bills}笔。门店贡献利润${formatCurrency(ex?.actual_net_profit)},贡献率${formatPercent(profitMargin)}
二、成本费用。食材成本率${formatPercent(foodCostRate)},建议低于32%。费用率${formatPercent(expenseRate)},建议低于40%。贡献率${formatPercent(contributionRate)},建议高于10%。食材成本超耗严重${costOv.red_count || 0}家,明显超耗${costOv.orange_count || 0}家,基本正常${costOv.green_count || 0}家,总差异金额${formatCurrency(costOv.total_variance)}
三、风险态势。红色门店${riskSummary['红色'] || 0}家,黄色门店${riskSummary['黄色'] || 0}家,绿色门店${riskSummary['绿色'] || 0}家。重点整改门店P0级${p0Stores.length}家,P1级${p1Stores.length}家。
四、利润机会。理论月度机会合计${formatCurrency(totalOpp)},涉及${profitOpp.length}个改善方向。30天承诺值大于等于150万元,目标将门店贡献率从${formatPercent(profitMargin)}提升至约10%`
四、利润机会。理论月度机会合计${formatCurrency(totalOpp)},涉及${profitOpp.length}个改善方向。考虑项目重叠和促销弹性,30天经营承诺值大于等于${formatCurrency(commitValue)}`
const handleTTS = async () => {
if (isPlaying) {
@@ -223,7 +226,7 @@ export function BusinessReportDialog({ open, onClose, data }: BusinessReportDial
<section>
<h3 className="mb-1 text-sm font-bold text-purple-700"></h3>
<p className="text-xs leading-relaxed">
<strong className="text-purple-600">{formatCurrency(totalOpp)}</strong> <strong>{profitOpp.length}</strong> 30 <strong className="text-purple-600"> 150 </strong> <strong>{formatPercent(profitMargin)}</strong> <strong>10%</strong>
<strong className="text-purple-600">{formatCurrency(totalOpp)}</strong> <strong>{profitOpp.length}</strong> 30 <strong className="text-purple-600"> {formatCurrency(commitValue)}</strong>
</p>
</section>
</div>
+88
View File
@@ -0,0 +1,88 @@
/**
* 决策卡组件
*
* 在决策中心列表中展示单个决策卡,点击可展开详情抽屉。
*/
import { ChevronRight } from 'lucide-react'
import { cn, formatCurrency } from '@/lib/utils'
import type { DecisionCard } from '@/lib/decision-aggregator'
import { SOURCE_LABELS, LEVEL_LABELS } from '@/lib/decision-aggregator'
interface DecisionCardProps {
decision: DecisionCard
index: number
approved: boolean
onOpen: (d: DecisionCard) => void
}
/** 来源类型颜色 */
const SOURCE_COLORS: Record<string, string> = {
profit_opportunity: 'bg-purple-100 text-purple-700',
risk_alert: 'bg-red-100 text-red-700',
task_anomaly: 'bg-amber-100 text-amber-700',
}
/** 等级颜色 */
const LEVEL_COLORS: Record<string, string> = {
L1: 'bg-red-50 text-red-600 border border-red-200',
L2: 'bg-amber-50 text-amber-600 border border-amber-200',
L3: 'bg-green-50 text-green-600 border border-green-200',
}
export function DecisionCardItem({ decision, index, approved, onOpen }: DecisionCardProps) {
const isApproved = approved || decision.status === '已批准'
return (
<button
className="flex w-full items-center gap-3 border-b px-4 py-3 text-left transition-colors hover:bg-muted/40"
onClick={() => onOpen(decision)}
>
{/* 排名序号 */}
<span
className={cn(
'flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-xs font-bold',
index < 3 ? 'bg-purple-600 text-white' : 'bg-muted text-muted-foreground',
)}
>
{index + 1}
</span>
{/* 主体内容 */}
<div className="min-w-0 flex-1">
<div className="flex items-center gap-2">
<span className={cn('rounded px-1.5 py-0.5 text-[10px] font-medium', SOURCE_COLORS[decision.sourceType])}>
{SOURCE_LABELS[decision.sourceType]}
</span>
<span className={cn('rounded px-1.5 py-0.5 text-[10px] font-medium', LEVEL_COLORS[decision.level])}>
{LEVEL_LABELS[decision.level]}
</span>
<span className="text-[10px] text-muted-foreground">{decision.agentName}</span>
</div>
<p className="mt-1 truncate text-sm font-medium">{decision.title}</p>
<p className="mt-0.5 truncate text-xs text-muted-foreground">{decision.reason}</p>
</div>
{/* 影响金额 + 状态 */}
<div className="shrink-0 text-right">
{decision.impactAmount > 0 ? (
<p className="text-sm font-bold text-green-600">{formatCurrency(decision.impactAmount)}</p>
) : (
<p className="text-sm font-medium text-muted-foreground">{decision.impactDescription}</p>
)}
<p className="text-[10px] text-muted-foreground">{decision.deadline}</p>
</div>
{/* 状态标签 */}
<span
className={cn(
'shrink-0 rounded px-2 py-0.5 text-[10px] font-medium',
isApproved ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-600',
)}
>
{isApproved ? '已批准' : decision.status}
</span>
<ChevronRight className="h-4 w-4 shrink-0 text-muted-foreground" />
</button>
)
}
+161
View File
@@ -0,0 +1,161 @@
/**
* 决策详情弹窗
*
* 点击决策卡后居中弹出,展示证据链、影响评估和审批操作。
* 弹窗风格与 BusinessReportDialog 保持统一。
*/
import { X, BrainCircuit } from 'lucide-react'
import { cn, formatCurrency } from '@/lib/utils'
import type { DecisionCard } from '@/lib/decision-aggregator'
import { SOURCE_LABELS, LEVEL_LABELS } from '@/lib/decision-aggregator'
interface DecisionDrawerProps {
decision: DecisionCard
approved: boolean
onClose: () => void
onApprove: () => void
onReject: () => void
}
export function DecisionDrawer({ decision, approved, onClose, onApprove, onReject }: DecisionDrawerProps) {
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/30" onClick={onClose}>
<div
className="max-h-[85vh] w-[640px] max-w-[95vw] overflow-y-auto rounded-lg border bg-card p-6 shadow-lg"
onClick={(e) => e.stopPropagation()}
>
{/* 标题栏 */}
<div className="mb-4 flex items-start justify-between">
<div>
<span className="text-xs text-muted-foreground">{decision.id} · {SOURCE_LABELS[decision.sourceType]}</span>
<h2 className="mt-1 text-base font-bold">{decision.title}</h2>
</div>
<button onClick={onClose} className="rounded-md p-1 hover:bg-muted">
<X className="h-5 w-5" />
</button>
</div>
{/* 内容 */}
<div className="space-y-4">
{/* 置信度 */}
<div className="rounded-lg border bg-muted/20 p-3">
<div className="flex items-center gap-2">
<BrainCircuit className="h-5 w-5 text-purple-600" />
<div className="flex-1">
<p className="text-xs text-muted-foreground">AI </p>
<p className="text-lg font-bold">{decision.confidence}%</p>
</div>
</div>
<div className="mt-2 h-2 overflow-hidden rounded-full bg-muted">
<div
className={cn(
'h-full rounded-full transition-all',
decision.confidence >= 85 ? 'bg-green-500' : decision.confidence >= 70 ? 'bg-amber-500' : 'bg-red-500',
)}
style={{ width: `${decision.confidence}%` }}
/>
</div>
</div>
{/* 为什么现在行动 */}
<div>
<h3 className="mb-1 text-sm font-bold"></h3>
<p className="text-sm text-muted-foreground">{decision.reason}</p>
</div>
{/* 影响评估 */}
<div className="grid grid-cols-2 gap-3">
<div className="rounded-lg border p-3">
<p className="text-xs text-muted-foreground"></p>
<p className="mt-1 text-sm font-bold text-green-600">
{decision.impactAmount > 0 ? formatCurrency(decision.impactAmount) : decision.impactDescription}
</p>
</div>
<div className="rounded-lg border p-3">
<p className="text-xs text-muted-foreground"></p>
<p className="mt-1 text-sm font-bold">{LEVEL_LABELS[decision.level]}</p>
</div>
</div>
{/* 证据链 */}
<div>
<h3 className="mb-2 text-sm font-bold"></h3>
<ul className="space-y-1.5">
{decision.evidence.map((e, i) => (
<li key={i} className="flex items-start gap-2 text-xs text-muted-foreground">
<span className="mt-0.5 h-1.5 w-1.5 shrink-0 rounded-full bg-purple-400" />
{e}
</li>
))}
</ul>
</div>
{/* 详细信息(如果有) */}
{decision.detail && (
<div>
<h3 className="mb-2 text-sm font-bold"></h3>
<div className="rounded-lg border bg-muted/20 p-3">
{decision.detail.split('\n').map((line, i) => (
<p
key={i}
className={cn(
'text-xs leading-relaxed',
line.startsWith('⚠')
? 'mt-2 rounded bg-amber-50 px-2 py-1 font-medium text-amber-700'
: line.endsWith('') || line.endsWith(':')
? 'mt-2 font-semibold text-foreground'
: 'text-muted-foreground',
)}
>
{line || '\u00A0'}
</p>
))}
</div>
</div>
)}
{/* 责任与执行 */}
<div>
<h3 className="mb-2 text-sm font-bold"></h3>
<div className="grid grid-cols-3 gap-2">
<div className="rounded-lg border p-2 text-center">
<p className="text-[10px] text-muted-foreground"></p>
<p className="mt-0.5 text-xs font-medium">{decision.owner}</p>
</div>
<div className="rounded-lg border p-2 text-center">
<p className="text-[10px] text-muted-foreground"> AI</p>
<p className="mt-0.5 text-xs font-medium">{decision.agentName}</p>
</div>
<div className="rounded-lg border p-2 text-center">
<p className="text-[10px] text-muted-foreground"></p>
<p className="mt-0.5 text-xs font-medium">{decision.deadline}</p>
</div>
</div>
</div>
</div>
{/* 底部操作 */}
<div className="mt-4 flex gap-2 border-t pt-4">
<button
onClick={onReject}
className="flex-1 rounded-md border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-muted"
>
退
</button>
<button
onClick={onApprove}
disabled={approved}
className={cn(
'flex-1 rounded-md px-4 py-2 text-sm font-medium transition-colors',
approved
? 'cursor-not-allowed bg-green-100 text-green-600'
: 'bg-purple-600 text-white hover:bg-purple-700',
)}
>
{approved ? '已批准 · 等待执行' : '批准并生成整改任务'}
</button>
</div>
</div>
</div>
)
}
+87
View File
@@ -0,0 +1,87 @@
/**
* 指挥舱待决策摘要组件
*
* 在 BossPage 顶部展示 TOP3 待决策,点击跳转到决策中心。
*/
import { useNavigate } from 'react-router-dom'
import { Sparkles, ChevronRight } from 'lucide-react'
import { cn, formatCurrency } from '@/lib/utils'
import type { DecisionCard } from '@/lib/decision-aggregator'
import { SOURCE_LABELS } from '@/lib/decision-aggregator'
interface DecisionSummaryProps {
decisions: DecisionCard[]
}
const SOURCE_COLORS: Record<string, string> = {
profit_opportunity: 'bg-purple-100 text-purple-700',
risk_alert: 'bg-red-100 text-red-700',
task_anomaly: 'bg-amber-100 text-amber-700',
}
export function DecisionSummary({ decisions }: DecisionSummaryProps) {
const navigate = useNavigate()
const top3 = decisions.slice(0, 3)
if (top3.length === 0) return null
const totalImpact = top3.reduce((s, d) => s + d.impactAmount, 0)
return (
<div className="rounded-lg border bg-gradient-to-r from-purple-50 to-white p-4">
{/* 标题行 */}
<div className="mb-3 flex items-center justify-between">
<div className="flex items-center gap-2">
<Sparkles className="h-4 w-4 text-purple-600" />
<h2 className="text-sm font-bold"></h2>
<span className="text-xs text-muted-foreground"></span>
</div>
<div className="text-right">
<span className="text-xs text-muted-foreground"></span>
<b className="ml-1 text-sm text-green-600">{formatCurrency(totalImpact)}</b>
</div>
</div>
{/* 决策列表 */}
<div className="space-y-1">
{top3.map((d, i) => (
<button
key={d.id}
className="flex w-full items-center gap-3 rounded-md px-3 py-2 text-left transition-colors hover:bg-white/60"
onClick={() => navigate('/decisions')}
>
<span
className={cn(
'flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-[10px] font-bold',
i === 0 ? 'bg-purple-600 text-white' : 'bg-purple-100 text-purple-600',
)}
>
{i + 1}
</span>
<div className="min-w-0 flex-1">
<div className="flex items-center gap-2">
<span className={cn('rounded px-1 py-0.5 text-[9px] font-medium', SOURCE_COLORS[d.sourceType])}>
{SOURCE_LABELS[d.sourceType]}
</span>
<span className="truncate text-xs font-medium">{d.title}</span>
</div>
<p className="mt-0.5 truncate text-[10px] text-muted-foreground">{d.reason}</p>
</div>
{d.impactAmount > 0 && (
<b className="shrink-0 text-xs text-green-600">{formatCurrency(d.impactAmount)}</b>
)}
<ChevronRight className="h-3 w-3 shrink-0 text-muted-foreground" />
</button>
))}
</div>
{/* 查看全部 */}
<button
className="mt-2 flex w-full items-center justify-center gap-1 rounded-md border border-purple-200 py-1.5 text-xs font-medium text-purple-600 hover:bg-purple-50"
onClick={() => navigate('/decisions')}
>
<ChevronRight className="h-3 w-3" />
</button>
</div>
)
}
+1 -1
View File
@@ -33,7 +33,7 @@ interface FilterableTableProps {
filter?: string
onFilterChange?: (filter: string) => void
filterButtons?: { key: string; label: string }[]
filterOptions?: string[]
filterOptions?: (string | { value: string; label: string })[]
searchKeys?: string[]
searchPlaceholder?: string
serverSearchValue?: string
+50
View File
@@ -0,0 +1,50 @@
/**
* 知识条目卡片组件
*
* 展示单个标杆实践(知识资产)的模块、标杆门店、关键行动和验证指标。
*/
import { ShieldCheck, ChevronRight } from 'lucide-react'
import { Badge } from '@/components/Badge'
interface KnowledgeCardProps {
practice: any
onClick?: () => void
}
/** 状态颜色映射 */
const STATUS_BADGE: Record<string, 'default' | 'status' | 'review'> = {
'待推广': 'default',
'推广中': 'status',
'已推广': 'review',
}
export function KnowledgeCard({ practice, onClick }: KnowledgeCardProps) {
return (
<div
className="flex cursor-pointer items-center gap-3 rounded-lg border bg-card p-3 transition-shadow hover:shadow-sm"
onClick={onClick}
>
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-teal-50">
<ShieldCheck className="h-5 w-5 text-teal-600" />
</div>
<div className="min-w-0 flex-1">
<div className="flex items-center gap-2">
<span className="rounded bg-teal-50 px-1.5 py-0.5 text-[10px] font-medium text-teal-700">
{practice.practice_module}
</span>
<Badge type={STATUS_BADGE[practice.status] || 'default'} text={practice.status} />
</div>
<p className="mt-1 truncate text-sm font-medium">
{practice.key_actions?.substring(0, 60) || '未填写关键行动'}
{practice.key_actions?.length > 60 ? '…' : ''}
</p>
<p className="mt-0.5 truncate text-xs text-muted-foreground">
: {practice.benchmark_store_name || '-'}
</p>
</div>
<ChevronRight className="h-4 w-4 shrink-0 text-muted-foreground" />
</div>
)
}
+30 -3
View File
@@ -1,6 +1,6 @@
import { ReactNode, useState } from 'react'
import { Link, useLocation } from 'react-router-dom'
import { LayoutDashboard, Store, ClipboardList, TrendingUp, Settings, LogOut, Menu, X, Package, DollarSign, ShoppingBag, Users, AlertTriangle, Clock, Database, MapPin, PieChart, Wallet, CalendarClock, Activity, Crown, BarChart3, Receipt, Utensils, Landmark, ChefHat, Truck, Network, TrendingUp as TrendingUpIcon, Building2 } from 'lucide-react'
import { LayoutDashboard, Store, ClipboardList, TrendingUp, Settings, LogOut, Menu, X, Package, DollarSign, ShoppingBag, Users, AlertTriangle, Clock, Database, MapPin, PieChart, Wallet, CalendarClock, Activity, Crown, BarChart3, Receipt, Utensils, Landmark, ChefHat, Truck, Network, TrendingUp as TrendingUpIcon, Building2, Target, Bell, Timer, TrafficCone, Boxes, Download, Briefcase, Cpu, Tag, Sparkles, Bot, Library } from 'lucide-react'
import { cn } from '@/lib/utils'
import { StatusBanner } from '@/components/StatusBanner'
@@ -32,14 +32,24 @@ const menuGroups: MenuGroup[] = [
{ path: '/bank', label: '银行授信', icon: Landmark, roles: ['hq'] },
],
},
{
title: '智脑决策',
items: [
{ path: '/decisions', label: '决策中心', icon: Sparkles, roles: ['hq', 'dept'] },
{ path: '/agents', label: 'AI员工组织', icon: Bot, roles: ['hq', 'dept'] },
{ path: '/knowledge', label: '知识资产', icon: Library, roles: ['hq', 'dept'] },
{ path: '/tasks', label: '任务管理', icon: ClipboardList, roles: ['hq', 'regional', 'store', 'dept'] },
{ path: '/monthly-review', label: '月度验收', icon: TrendingUp, roles: ['hq', 'dept', 'regional'] },
{ path: '/alert', label: '预警管理', icon: Bell, roles: ['hq', 'dept', 'regional', 'store'] },
{ path: '/target', label: '目标管理', icon: Target, roles: ['hq', 'dept', 'regional'] },
],
},
{
title: '角色工作台',
items: [
{ path: '/regional', label: '区域经理', icon: Store, roles: ['hq', 'dept', 'regional'] },
{ path: '/region-comparison', label: '区域对比', icon: Store, roles: ['hq', 'dept', 'regional'] },
{ path: '/store', label: '店长工作台', icon: ClipboardList, roles: ['hq', 'dept', 'store'] },
{ path: '/tasks', label: '任务管理', icon: ClipboardList, roles: ['hq', 'regional', 'store', 'dept'] },
{ path: '/monthly-review', label: '月度验收', icon: TrendingUp, roles: ['hq', 'dept', 'regional'] },
],
},
{
@@ -69,6 +79,7 @@ const menuGroups: MenuGroup[] = [
items: [
{ path: '/sku', label: '商品SKU', icon: Package, roles: ['hq', 'dept'] },
{ path: '/menu-engineering', label: '菜单工程', icon: Package, roles: ['hq', 'dept'] },
{ path: '/promotion', label: '促销增量', icon: Tag, roles: ['hq', 'dept'] },
{ path: '/time', label: '时间分析', icon: Clock, roles: ['hq', 'dept'] },
{ path: '/smart-scheduling', label: '智能排班', icon: CalendarClock, roles: ['hq', 'dept', 'regional', 'store'] },
{ path: '/employee-performance', label: '员工绩效', icon: CalendarClock, roles: ['hq', 'dept'] },
@@ -81,12 +92,28 @@ const menuGroups: MenuGroup[] = [
{ path: '/site-selection', label: '门店选址', icon: MapPin, roles: ['hq', 'dept'] },
],
},
{
title: '系统配置',
items: [
{ path: '/store-grade', label: '门店分级', icon: TrafficCone, roles: ['hq', 'dept', 'regional'] },
{ path: '/scheduler', label: '调度管理', icon: Timer, roles: ['hq'] },
{ path: '/product-lifecycle', label: '产品生命周期', icon: Boxes, roles: ['hq', 'dept'] },
{ path: '/data-import', label: '数据采集', icon: Download, roles: ['hq', 'dept'] },
{ path: '/enterprise', label: '企业协同', icon: Briefcase, roles: ['hq', 'dept'] },
{ path: '/intelligence', label: '智能升级', icon: Cpu, roles: ['hq', 'dept'] },
],
},
{
title: '系统管理',
items: [
{ path: '/tenant-users', label: '用户管理', icon: Users, roles: ['hq'] },
{ path: '/data-quality', label: '数据质量', icon: Database, roles: ['hq', 'dept'] },
{ path: '/indicators', label: '指标字典', icon: Settings, roles: ['hq', 'dept', 'regional', 'store'] },
],
},
{
title: '经营本体',
items: [
{ path: '/ontology', label: '本体标准', icon: Receipt, roles: ['hq', 'dept'] },
],
},
+74
View File
@@ -0,0 +1,74 @@
/**
* 闭环健康度条组件
*
* 展示"信号→决策→任务→验收→知识"5 阶段转化率。
* 数据来源:/tasks/loop-health API。
*/
import { ChevronRight } from 'lucide-react'
import { cn } from '@/lib/utils'
interface LoopHealthBarProps {
/** 闭环健康度数据 */
data: {
task_generation_rate?: number
store_execution_rate?: number
weekly_check_rate?: number
monthly_review_rate?: number
practice_promotion_rate?: number
} | null
/** 各阶段数量(可选) */
counts?: {
signals?: number
decisions?: number
tasks?: number
checks?: number
reviews?: number
practices?: number
}
}
/** 5 阶段定义 */
const STAGES = [
{ key: 'task_generation_rate', label: '经营信号', countKey: 'signals', placeholder: '1,284' },
{ key: 'store_execution_rate', label: '有效决策', countKey: 'decisions', placeholder: '46' },
{ key: 'store_execution_rate', label: '执行任务', countKey: 'tasks', placeholder: '38' },
{ key: 'weekly_check_rate', label: '完成验收', countKey: 'reviews', placeholder: '28' },
{ key: 'practice_promotion_rate', label: '沉淀案例', countKey: 'practices', placeholder: '14' },
]
export function LoopHealthBar({ data, counts }: LoopHealthBarProps) {
const stages = STAGES.map((s) => {
const rate = data ? (data as any)[s.key] : null
const count = counts ? (counts as any)[s.countKey] : null
return {
...s,
rate: rate != null ? Math.round(Number(rate) * 100) / 100 : null,
count: count != null ? String(count) : s.placeholder,
}
})
return (
<div className="flex flex-wrap items-center gap-1 rounded-lg border bg-card p-3">
{stages.map((s, i) => (
<div key={s.label} className="flex items-center gap-1">
<div className="flex flex-col items-center px-2">
<span
className={cn(
'flex h-6 w-6 items-center justify-center rounded-full text-[10px] font-bold',
i === 0 ? 'bg-blue-600 text-white' : 'bg-muted text-muted-foreground',
)}
>
{i + 1}
</span>
<small className="mt-1 text-[10px] text-muted-foreground">{s.label}</small>
<b className="text-sm font-bold">{s.count}</b>
{s.rate != null && (
<em className="text-[10px] text-green-600">{s.rate}% </em>
)}
</div>
{i < stages.length - 1 && <ChevronRight className="h-4 w-4 text-muted-foreground" />}
</div>
))}
</div>
)
}
@@ -32,15 +32,22 @@ export function OverviewTab({ month }: { month: string }) {
return (
<div className="space-y-4">
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="总销售额" value={ov.total_sales} format="currency" />
<MetricCard title="理论成本合计" value={ov.total_theo_cost} format="currency" />
<MetricCard title="实际成本合计" value={ov.total_actual_cost} format="currency" />
<MetricCard title="成本差异" value={ov.total_variance} format="currency" description="实际成本 - 理论成本" />
<MetricCard title="平均理论毛利率" value={ov.avg_theo_margin} format="percent" />
<MetricCard title="平均实际毛利率" value={ov.avg_actual_margin} format="percent" />
<MetricCard title="总销售额" value={ov.total_sales} format="currency" description={`与总部驾驶舱同源(bill_fact)${ov.total_stores || 94}家门店实收合计`} />
<MetricCard title="消费额(含税)" value={ov.total_consumption} format="currency" description="账单消费额(含税),总部驾驶舱同口径" />
<MetricCard title="理论毛利率(门店)" value={ov.store_avg_theo_margin} format="percent" description="门店倒挤口径: 1-理论成本率(排除口径异常)" />
<MetricCard title="实际毛利率(门店)" value={ov.store_avg_actual_margin} format="percent" description="门店倒挤口径: 1-实际食材成本率(排除口径异常)" status={Number(ov.store_avg_actual_margin) < Number(ov.store_avg_theo_margin) ? 'bad' : undefined} />
<MetricCard title="理论毛利率(菜品)" value={ov.avg_theo_margin} format="percent" description="菜品Excel口径,仅含物料损耗差异" />
<MetricCard title="实际毛利率(菜品)" value={ov.avg_actual_margin} format="percent" description="菜品Excel口径,未含库存盘亏/退损" />
<MetricCard title="低毛利菜品数" value={ov.low_margin_dishes} format="number" description="理论毛利率 < 50%" />
<MetricCard title="超理论菜品数" value={ov.over_cost_dishes} format="number" description="实际成本超过理论成本" />
</div>
<div className="rounded-lg border border-orange-200 bg-orange-50/50 p-3 text-sm text-orange-800">
<strong></strong><br/>
<strong>()</strong> {ov.store_avg_theo_margin}% vs {ov.store_avg_actual_margin}% {(Number(ov.store_avg_theo_margin) - Number(ov.store_avg_actual_margin)).toFixed(2)}%<br/>
<strong>(Excel)</strong> {ov.avg_theo_margin}% vs {ov.avg_actual_margin}% {(Number(ov.avg_theo_margin) - Number(ov.avg_actual_margin)).toFixed(2)}%<br/>
() {formatCurrency(ov.store_total_actual_cost)} {formatCurrency(ov.total_actual_cost)} {formatCurrency(Number(ov.store_total_actual_cost) - Number(ov.total_actual_cost))}
(/)<strong>退</strong>
</div>
<CollapsibleSection title="品类成本对比" subtitle="按一级品类汇总理论vs实际毛利率">
<ResponsiveContainer width="100%" height={300}>
@@ -144,6 +144,7 @@ export function ProfitabilityTab({ month }: { month: string }) {
{ key: 'actual_margin', label: '实际毛利率' },
{ key: 'sales_amount', label: '销售额' },
{ key: 'price', label: '售价' },
{ key: 'theo_cost_per_unit', label: '单位理论成本' },
]}
defaultSort="theo_margin"
defaultOrder="asc"
@@ -153,10 +154,14 @@ export function ProfitabilityTab({ month }: { month: string }) {
{ key: 'dish_name', label: '菜品' },
{ key: 'category_level1', label: '品类' },
{ key: 'price', label: '售价', align: 'right', render: (r) => formatCurrency(r.price) },
{ key: 'theo_cost', label: '理论成本', align: 'right', render: (r) => formatCurrency(r.theo_cost) },
{ key: 'theo_cost_rate', label: '理论成本率', align: 'right', render: (r) => formatPercent(r.theo_cost_rate) },
{ key: 'theo_cost_per_unit', label: '单位理论成本', align: 'right', render: (r) => formatCurrency(r.theo_cost_per_unit) },
{ key: 'theo_cost_rate', label: '理论成本率', align: 'right', render: (r) => {
const v = Number(r.theo_cost_rate || 0)
return <span className={v > 100 ? 'font-medium text-red-600' : v > 70 ? 'text-orange-600' : ''}>{formatPercent(v)}</span>
}},
{ key: 'theo_margin', label: '理论毛利率', align: 'right', render: (r) => <span className="text-red-600">{formatPercent(r.theo_margin)}</span> },
{ key: 'actual_margin', label: '实际毛利率', align: 'right', render: (r) => formatPercent(r.actual_margin) },
{ key: 'sales_quantity', label: '销量', align: 'right', render: (r) => formatNumber(r.sales_quantity) },
{ key: 'sales_amount', label: '销售额', align: 'right', render: (r) => formatCurrency(r.sales_amount) },
]}
/>
@@ -31,7 +31,7 @@ export function ExpenseOverviewTab({ month }: { month: string }) {
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<CollapsibleSection title="费用结构分析" subtitle="2026年4月各费用科目占比">
<CollapsibleSection title="费用结构分析" subtitle={`${month}各费用科目占比`}>
<ResponsiveContainer width="100%" height={400}>
<PieChart>
<Pie data={pieData} dataKey="value" nameKey="name" cx="50%" cy="50%" outerRadius={120} labelLine={false}>
@@ -116,7 +116,7 @@ function StoreDetailModal({ store, onClose }: { store: StoreDetail | null, onClo
{ label: '面积(㎡)', value: formatNumber(store.area_sqm) },
{ label: '坪效', value: formatNumber(store.received_per_sqm) },
{ label: '账单数', value: formatNumber(store.bill_count) },
{ label: '租约到期', value: store.lease_expiry_date ? new Date(store.lease_expiry_date).toLocaleDateString('zh-CN') : '-' },
{ label: '租约到期', value: store.lease_expiry_date ? String(store.lease_expiry_date).substring(0, 10) : '-' },
]
return (
@@ -197,9 +197,9 @@ export function LossDiagnosisTab({ month }: { month: string }) {
const rows = (data as any)?.data || []
const meta = (data as any)?.meta || { page, pageSize: PAGE_SIZE, total: 0 }
const p0Count = rows.filter((r: any) => r.priority === 'P0').length
const p1Count = rows.filter((r: any) => r.priority === 'P1').length
const totalLoss = rows.reduce((sum: number, r: any) => sum + parseFloat(r.actual_store_contribution || 0), 0)
const p0Count = meta.evalStats ? Number(meta.evalStats.p0_count) : rows.filter((r: any) => r.priority === 'P0').length
const p1Count = meta.evalStats ? Number(meta.evalStats.p1_count) : rows.filter((r: any) => r.priority === 'P1').length
const totalLoss = meta.evalStats ? Number(meta.evalStats.total_loss) : rows.reduce((sum: number, r: any) => sum + parseFloat(r.actual_store_contribution || 0), 0)
return (
<div className="space-y-4">
@@ -76,7 +76,7 @@ export function RentRiskTab({ month }: { month: string }) {
{ key: 'rent_rate_pct', label: '租金率', align: 'right', render: (r) => <span className={parseFloat(r.rent_rate_pct) > 20 ? 'text-red-600 font-medium' : ''}>{formatPercent(r.rent_rate_pct)}</span> },
{ key: 'area_sqm', label: '面积(㎡)', align: 'right', render: (r) => formatNumber(r.area_sqm) },
{ key: 'received_per_sqm', label: '坪效', align: 'right', render: (r) => formatNumber(r.received_per_sqm) },
{ key: 'lease_expiry_date', label: '租约到期', render: (r) => r.lease_expiry_date ? new Date(r.lease_expiry_date).toLocaleDateString('zh-CN') : '-' },
{ key: 'lease_expiry_date', label: '租约到期', render: (r) => r.lease_expiry_date ? String(r.lease_expiry_date).substring(0, 10) : '-' },
{ key: 'risk_level', label: '风险等级', render: (r) => <span className={RISK_COLORS[r.risk_level] || ''}>{r.risk_level}</span> },
{ key: 'suggestion', label: '建议' },
]}
@@ -59,7 +59,7 @@ function EvalDetailModal({ store, onClose }: { store: EvalStoreDetail | null, on
{ label: '租金率', value: formatPercent(store.rent_rate_pct), warn: parseFloat(store.rent_rate_pct) > 20 },
{ label: '坪效', value: formatNumber(store.received_per_sqm), warn: parseFloat(store.received_per_sqm) < 1000 },
{ label: '面积(㎡)', value: formatNumber(store.area_sqm) },
{ label: '租约到期', value: store.lease_expiry_date ? new Date(store.lease_expiry_date).toLocaleDateString('zh-CN') : '-' },
{ label: '租约到期', value: store.lease_expiry_date ? String(store.lease_expiry_date).substring(0, 10) : '-' },
]
return (
@@ -167,7 +167,7 @@ export function StoreEvaluationTab({ month }: { month: string }) {
{ key: 'actual_store_contribution', label: '贡献利润', align: 'right', render: (r) => <span className={parseFloat(r.actual_store_contribution) < 0 ? 'text-red-600 font-medium' : 'text-green-600'}>{formatCurrency(r.actual_store_contribution)}</span> },
{ key: 'actual_store_contribution_rate_pct', label: '贡献率', align: 'right', render: (r) => formatPercent(r.actual_store_contribution_rate_pct) },
{ key: 'received_per_sqm', label: '坪效', align: 'right', render: (r) => formatNumber(r.received_per_sqm) },
{ key: 'lease_expiry_date', label: '租约到期', render: (r) => r.lease_expiry_date ? new Date(r.lease_expiry_date).toLocaleDateString('zh-CN') : '-' },
{ key: 'lease_expiry_date', label: '租约到期', render: (r) => r.lease_expiry_date ? String(r.lease_expiry_date).substring(0, 10) : '-' },
{ key: 'evaluation_detail', label: '评估详情', render: (r) => <span className="text-xs">{r.evaluation_detail}</span> },
]}
/>
+193
View File
@@ -0,0 +1,193 @@
/**
* AI 员工配置定义
*
* 定义玄谋智脑的 10 个 AI 员工角色,包括岗位目标、负责领域、自治等级和对应的 SBrainCO 能力。
* 阶段一为静态配置,阶段二将迁移至 analytics.agent_config 表动态管理。
*/
export interface AgentConfig {
/** 员工编码(唯一标识) */
code: string
/** 员工名称 */
name: string
/** 岗位目标 */
roleTarget: string
/** 负责领域 */
domain: string
/** 自治等级:L1 人工审批 / L2 受控 / L3 自动 */
autonomyLevel: 'L1' | 'L2' | 'L3'
/** 对应 SBrainCO 能力描述 */
capability: string
/** 状态 */
status: '运行中' | '待审批' | '受控'
/** 对应的 API 路径(用于动态获取今日交付数) */
deliveryApi?: string
/** 交付数提取路径(从 API 响应中提取数字) */
deliveryField?: string
/** 对应业务页面路径(详情弹窗"查看业务模块"按钮跳转) */
businessPage?: string
/** 今日交付明细列表展示列(仅数组型返回数据适用) */
deliveryColumns?: { field: string; label: string }[]
}
/** 经营参谋长(首席 AI 员工) */
export const chiefOfStaff: AgentConfig = {
code: 'chief_of_staff',
name: '经营参谋长',
roleTarget: '消解目标冲突、生成老板决策清单',
domain: '跨系统',
autonomyLevel: 'L1',
capability: '聚合利润机会、风险评级、闭环健康度,生成晨会简报',
status: '运行中',
deliveryApi: '/overview/profit-opportunity',
deliveryField: 'items.length',
businessPage: '/decisions',
deliveryColumns: [
{ field: 'category', label: '机会类别' },
{ field: 'opportunity', label: '预计机会' },
{ field: 'confidence', label: '置信度' },
{ field: 'owner', label: '责任方' },
],
}
/** 9 个 AI 员工(不含经营参谋长) */
export const agents: AgentConfig[] = [
{
code: 'store_analyst',
name: '门店经营分析师',
roleTarget: '门店分级、异常归因与增收机会',
domain: '门店增长',
autonomyLevel: 'L1',
capability: '风险评级 + 利润机会池 + 门店深度诊断',
status: '运行中',
deliveryApi: '/stores/risk',
deliveryField: 'length',
businessPage: '/risk',
deliveryColumns: [
{ field: 'store_name', label: '门店' },
{ field: 'risk_level', label: '风险等级' },
{ field: 'received', label: '实收' },
],
},
{
code: 'dish_profit_optimizer',
name: '菜品利润优化师',
roleTarget: '菜品真实贡献与菜单工程',
domain: '商品利润',
autonomyLevel: 'L1',
capability: '成本分析(9个Tab+ 菜单工程 + BOM穿透',
status: '运行中',
deliveryApi: '/cost-analysis/store-overview',
deliveryField: 'total_stores',
businessPage: '/cost-analysis',
},
{
code: 'expense_auditor',
name: '费用稽核员',
roleTarget: '门店损益、费用异常与追责',
domain: '利润费用',
autonomyLevel: 'L1',
capability: '门店费用分析 + 人工水电费率监控',
status: '运行中',
deliveryApi: '/store-expense/overview',
deliveryField: 'total_stores',
businessPage: '/store-expense',
},
{
code: 'demand_forecaster',
name: '需求预测员',
roleTarget: '菜品与原料日周需求预测',
domain: '供应链',
autonomyLevel: 'L1',
capability: 'AI 预测模型 + 历史趋势分析',
status: '运行中',
deliveryApi: '/intelligence/ai/forecasts',
deliveryField: 'length',
businessPage: '/intelligence',
deliveryColumns: [
{ field: 'forecast_type', label: '预测类型' },
{ field: 'target_date', label: '目标日期' },
{ field: 'predicted_value', label: '预测值' },
],
},
{
code: 'smart_replenisher',
name: '智能补货员',
roleTarget: '订货量、调拨与最晚下单日',
domain: '供应链',
autonomyLevel: 'L2',
capability: 'MRP 物料需求计划 + 库存周转分析',
status: '受控',
deliveryApi: '/intelligence/chain/production-sales',
deliveryField: 'length',
businessPage: '/intelligence',
deliveryColumns: [
{ field: 'sku_name', label: '菜品' },
{ field: 'total_sales', label: '销量' },
],
},
{
code: 'operations_supervisor',
name: '经营督办员',
roleTarget: '异常转任务、周检与月度验收',
domain: '组织执行',
autonomyLevel: 'L1',
capability: '任务自动生成 + 周检 + 月度验收 + 闭环健康度',
status: '运行中',
deliveryApi: '/tasks',
deliveryField: 'meta.total', // meta. 前缀由 extractDelivery 从响应根取值
businessPage: '/tasks',
deliveryColumns: [
{ field: 'store_name', label: '门店' },
{ field: 'priority', label: '优先级' },
{ field: 'status', label: '状态' },
{ field: 'deadline', label: '截止日' },
],
},
{
code: 'compliance_auditor',
name: '经营稽核员',
roleTarget: '退款、抹零与异常操作审查',
domain: '风险内控',
autonomyLevel: 'L1',
capability: '告警规则 + 告警日志 + 风险内控',
status: '运行中',
deliveryApi: '/alert/overview',
deliveryField: 'total_alerts',
businessPage: '/alert',
},
{
code: 'member_operator',
name: '会员运营师',
roleTarget: '复购、流失与下一最佳行动',
domain: '顾客增长',
autonomyLevel: 'L2',
capability: '会员复购分析 + 会员 LTV + 促销增量',
status: '待审批',
deliveryApi: '/member/repeat',
deliveryField: 'length',
businessPage: '/member',
deliveryColumns: [
{ field: 'store_name', label: '门店' },
{ field: 'repeat_rate_pct', label: '复购率%' },
{ field: 'bill_count', label: '账单数' },
],
},
{
code: 'knowledge_manager',
name: '知识管理员',
roleTarget: 'SOP、标杆门店与案例资产化',
domain: '组织能力',
autonomyLevel: 'L1',
capability: '标杆实践管理 + 经验推广 + 知识沉淀',
status: '运行中',
deliveryApi: '/tasks/practices',
deliveryField: 'length',
businessPage: '/knowledge',
deliveryColumns: [
{ field: 'practice_module', label: '模块' },
{ field: 'benchmark_store_name', label: '标杆门店' },
{ field: 'status', label: '状态' },
],
},
]
+203
View File
@@ -0,0 +1,203 @@
/**
* 决策聚合逻辑
*
* 将利润机会、风险告警、异常任务 3 类信号统一聚合为"决策卡"格式。
* 阶段一为前端聚合(不持久化),阶段二将迁移至后端 analytics.decision_card 表。
*/
/** 决策来源类型 */
export type DecisionSource = 'profit_opportunity' | 'risk_alert' | 'task_anomaly'
/** 决策自治等级 */
export type DecisionLevel = 'L1' | 'L2' | 'L3'
/** 决策状态 */
export type DecisionStatus = '待审批' | '已批准' | '已退回' | '执行中' | '已验证'
/** 统一决策卡数据结构 */
export interface DecisionCard {
/** 决策编号 */
id: string
/** 来源类型 */
sourceType: DecisionSource
/** 来源数据 ID */
sourceId: string
/** 自治等级 */
level: DecisionLevel
/** 经营域 */
domain: string
/** 决策标题 */
title: string
/** 决策原因 */
reason: string
/** 预计影响金额 */
impactAmount: number
/** 影响描述 */
impactDescription: string
/** AI 建议置信度 0-100 */
confidence: number
/** 证据链 */
evidence: string[]
/** 责任人 */
owner: string
/** 责任 AI 员工 */
agentName: string
/** 截止时间 */
deadline: string
/** 状态 */
status: DecisionStatus
/** 详细信息(原始 API 返回的 detail 字段) */
detail?: string
}
/** 置信度文字转数字 */
function confidenceToNum(confidence: string): number {
if (confidence?.includes('高')) return 90
if (confidence?.includes('中高')) return 85
if (confidence?.includes('中')) return 75
if (confidence?.includes('中低')) return 65
if (confidence?.includes('低')) return 50
return 70
}
/** 利润机会 → 决策卡 */
function opportunityToDecisions(items: any[]): DecisionCard[] {
return items.map((o, i) => ({
id: `OPP-${String(i + 1).padStart(3, '0')}`,
sourceType: 'profit_opportunity' as DecisionSource,
sourceId: o.category,
level: 'L1' as DecisionLevel,
domain: o.owner?.split('/')[0]?.trim() || '经营',
title: o.category,
reason: o.evidence || '基于利润机会池分析',
impactAmount: Math.max(Number(o.opportunity || 0), 0),
impactDescription: `预计月度利润提升 ${Math.max(Number(o.opportunity || 0), 0).toLocaleString('zh-CN')}`,
confidence: confidenceToNum(o.confidence),
evidence: [
`基线: ${o.baseline}`,
`验收方式: ${o.evidence}`,
`责任方: ${o.owner}`,
],
owner: o.owner || '待分配',
agentName: mapOwnerToAgent(o.owner),
deadline: '30天内',
status: '待审批' as DecisionStatus,
detail: o.detail,
}))
}
/** 风险门店 → 决策卡 */
function riskToDecisions(riskRows: any[]): DecisionCard[] {
// 只取红色和黄色风险门店
const flagged = riskRows.filter((r) => r.risk_level === '红色' || r.risk_level === '黄色')
return flagged.slice(0, 10).map((r, i) => ({
id: `RISK-${String(i + 1).padStart(3, '0')}`,
sourceType: 'risk_alert' as DecisionSource,
sourceId: r.store_code || r.store_name,
level: (r.risk_level === '红色' ? 'L1' : 'L2') as DecisionLevel,
domain: '门店经营',
title: `${r.store_name} ${r.risk_level}门店整改`,
reason: `风险评级为${r.risk_level},营收 ${Number(r.received || 0).toLocaleString('zh-CN')} 元,需关注经营异常`,
impactAmount: Number(r.received || 0) * 0.05,
impactDescription: `预计挽回营收损失 ${Math.round(Number(r.received || 0) * 0.05).toLocaleString('zh-CN')}`,
confidence: r.risk_level === '红色' ? 92 : 78,
evidence: [
`门店: ${r.store_name}${r.store_code || '-'}`,
`风险等级: ${r.risk_level}`,
`实收: ¥${Number(r.received || 0).toLocaleString('zh-CN')}`,
`风险评分: ${r.risk_score || '-'}`,
],
owner: '区域经理',
agentName: '门店经营分析师',
deadline: r.risk_level === '红色' ? '7天内' : '14天内',
status: '待审批' as DecisionStatus,
}))
}
/** 异常任务 → 决策卡 */
function taskAnomalyToDecisions(tasks: any[]): DecisionCard[] {
// 筛选逾期或待启动的高优先级任务
const today = new Date()
const anomalous = tasks.filter((t) => {
const isOverdue = t.deadline && new Date(t.deadline) < today && t.status !== '已验收'
const isPendingP0 = t.priority?.startsWith('P0') && t.status === '待启动'
return isOverdue || isPendingP0
})
return anomalous.slice(0, 10).map((t, i) => ({
id: `TASK-${String(i + 1).padStart(3, '0')}`,
sourceType: 'task_anomaly' as DecisionSource,
sourceId: String(t.task_id),
level: (t.priority?.startsWith('P0') ? 'L1' : 'L2') as DecisionLevel,
domain: '组织执行',
title: `${t.store_name} - ${t.problem_indicator || '任务异常'}`,
reason: t.problem_description || t.action_required || '任务存在异常需关注',
impactAmount: 0,
impactDescription: t.verification_result || '需评估验收价值',
confidence: 80,
evidence: [
`门店: ${t.store_name}`,
`问题指标: ${t.problem_indicator || '-'}`,
`当前值: ${t.current_value ?? '-'} / 目标值: ${t.target_value ?? '-'}`,
`负责人: ${t.owner}`,
`截止日: ${t.deadline?.substring(0, 10) || '-'}`,
],
owner: t.owner || '待分配',
agentName: '经营督办员',
deadline: t.deadline?.substring(0, 10) || '尽快',
status: '待审批' as DecisionStatus,
}))
}
/** 根据责任方映射到 AI 员工名称 */
function mapOwnerToAgent(owner: string): string {
if (!owner) return '经营参谋长'
if (owner.includes('供应链') || owner.includes('商品')) return '菜品利润优化师'
if (owner.includes('运营') || owner.includes('人力')) return '费用稽核员'
if (owner.includes('工程') || owner.includes('门店')) return '门店经营分析师'
if (owner.includes('营销')) return '会员运营师'
if (owner.includes('外卖') || owner.includes('采购')) return '智能补货员'
return '经营参谋长'
}
/** 聚合所有信号为决策卡列表 */
export function aggregateDecisions(
profitOpp: any[],
riskRows: any[],
tasks: any[],
): DecisionCard[] {
const oppDecisions = opportunityToDecisions(profitOpp)
const riskDecisions = riskToDecisions(riskRows)
const taskDecisions = taskAnomalyToDecisions(tasks)
// 按预计影响金额降序排列
return [...oppDecisions, ...riskDecisions, ...taskDecisions].sort(
(a, b) => b.impactAmount - a.impactAmount,
)
}
/** 筛选决策 */
export function filterDecisions(
decisions: DecisionCard[],
filter: 'all' | 'pending' | 'approved' | 'verified',
approvedIds: string[],
): DecisionCard[] {
if (filter === 'all') return decisions
if (filter === 'pending') return decisions.filter((d) => d.status === '待审批' && !approvedIds.includes(d.id))
if (filter === 'approved') return decisions.filter((d) => approvedIds.includes(d.id))
if (filter === 'verified') return decisions.filter((d) => d.status === '已验证')
return decisions
}
/** 决策来源标签 */
export const SOURCE_LABELS: Record<DecisionSource, string> = {
profit_opportunity: '利润机会',
risk_alert: '风险告警',
task_anomaly: '任务异常',
}
/** 自治等级标签 */
export const LEVEL_LABELS: Record<DecisionLevel, string> = {
L1: 'L1 人工审批',
L2: 'L2 受控',
L3: 'L3 自动',
}
+149
View File
@@ -0,0 +1,149 @@
/**
* AI 员工组织页面
*
* 展示玄谋智脑的 10 个 AI 员工角色,包括经营参谋长(首席)和 9 个专业员工。
* 今日交付数从对应 API 动态获取。
*/
import { useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { BrainCircuit } from 'lucide-react'
import api from '@/lib/api'
import { AgentCard } from '@/components/AgentCard'
import { AgentDetailDialog } from '@/components/AgentDetailDialog'
import { chiefOfStaff, agents, type AgentConfig } from '@/data/agents'
import { cn } from '@/lib/utils'
export function AgentsPage() {
const [selected, setSelected] = useState<AgentConfig | null>(null)
// 批量获取各 AI 员工的今日交付数
const queries = agents.map((agent, idx) =>
useQuery({
queryKey: ['agent-delivery', agent.code],
queryFn: () => api.get(agent.deliveryApi || ''),
enabled: !!agent.deliveryApi,
staleTime: 5 * 60 * 1000,
}),
)
// 经营参谋长的交付数(利润机会数量)
const chiefQuery = useQuery({
queryKey: ['overview/profit-opportunity', 'chief'],
queryFn: () => api.get('/overview/profit-opportunity', { params: { month: '2026-04' } }),
staleTime: 5 * 60 * 1000,
})
/** 从 API 响应中提取交付数
* field 以 `meta.` 开头时从响应根(含 data/meta)取值,否则从 data 字段取值。
* 支持 a.b.c 路径,末段为 length 时取数组长度。
*/
function extractDelivery(queryResult: any, field: string): number | null {
if (!queryResult) return null
const root = queryResult as any
const parts = field.split('.')
// meta. 前缀:从响应根开始遍历(覆盖分页总数等不在 data 内的字段)
let val: any
if (parts[0] === 'meta') {
val = root
} else {
val = root?.data
if (!val) return null
}
for (let i = 0; i < parts.length; i++) {
const p = parts[i]
// 末段为 length 且当前值为数组,直接取长度
if (p === 'length' && i === parts.length - 1 && Array.isArray(val)) {
return val.length
}
val = val?.[p]
if (val === undefined) return null
}
const num = typeof val === 'number' ? val : parseInt(String(val), 10)
return isNaN(num) ? null : num
}
const chiefDeliveries = chiefQuery.data
? extractDelivery(chiefQuery.data, 'items.length') ?? (chiefQuery.data as any)?.data?.items?.length ?? 0
: null
return (
<div className="space-y-4">
{/* 页面标题 */}
<div>
<h1 className="flex items-center gap-2 text-xl font-bold">
<BrainCircuit className="h-5 w-5 text-blue-600" />
AI
</h1>
<p className="mt-1 text-sm text-muted-foreground">
AI SOP
</p>
</div>
{/* 经营参谋长(首席卡片) */}
<div
className="cursor-pointer rounded-lg border-2 border-blue-200 bg-gradient-to-r from-blue-50 to-white p-4 transition-shadow hover:shadow-md"
onClick={() => setSelected(chiefOfStaff)}
>
<div className="flex items-center gap-4">
<div className="flex h-14 w-14 items-center justify-center rounded-xl bg-blue-600">
<BrainCircuit className="h-7 w-7 text-white" />
</div>
<div className="flex-1">
<small className="text-[10px] font-medium text-blue-600">AI CHIEF OF STAFF</small>
<h2 className="text-lg font-bold">{chiefOfStaff.name}</h2>
<p className="text-sm text-muted-foreground">{chiefOfStaff.roleTarget}</p>
</div>
<div className="text-right">
<p className="text-xs text-muted-foreground"></p>
<b className="text-2xl font-bold text-blue-600">{chiefDeliveries ?? '…'}</b>
<p className="text-[10px] text-muted-foreground"></p>
</div>
</div>
</div>
{/* AI 员工网格 */}
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
{agents.map((agent, idx) => (
<AgentCard
key={agent.code}
agent={agent}
deliveries={
queries[idx]?.data
? extractDelivery(queries[idx].data, agent.deliveryField || '') ?? 0
: null
}
onClick={() => setSelected(agent)}
/>
))}
</div>
{/* 底部说明 */}
<div className="rounded-lg border bg-muted/20 p-3 text-xs text-muted-foreground">
<p>
<b className="text-foreground"></b>
<span className={cn('ml-1 rounded px-1 py-0.5 text-[10px]', 'bg-red-50 text-red-600')}>L1</span> ·
<span className={cn('ml-1 rounded px-1 py-0.5 text-[10px]', 'bg-amber-50 text-amber-600')}>L2</span> ·
<span className={cn('ml-1 rounded px-1 py-0.5 text-[10px]', 'bg-green-50 text-green-600')}>L3</span>
</p>
<p className="mt-1"> AI API </p>
</div>
{/* 详情弹窗 */}
{selected && (
<AgentDetailDialog
agent={selected}
deliveries={
selected.code === chiefOfStaff.code
? chiefDeliveries
: (() => {
const idx = agents.findIndex((a) => a.code === selected.code)
if (idx < 0 || !queries[idx]?.data) return null
return extractDelivery(queries[idx].data, selected.deliveryField || '') ?? 0
})()
}
onClose={() => setSelected(null)}
/>
)}
</div>
)
}
+208
View File
@@ -0,0 +1,208 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import api from '@/lib/api'
import { FilterableTable } from '@/components/FilterableTable'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { CollapsibleSection } from '@/components/CollapsibleSection'
import { MetricCard } from '@/components/MetricCard'
import { Tabs } from '@/components/Tabs'
import { AlertLogDetailDialog } from '@/components/AlertLogDetailDialog'
import { formatNumber } from '@/lib/utils'
import { useState } from 'react'
export function AlertManagementPage() {
const [tab, setTab] = useState('logs')
const [selectedLog, setSelectedLog] = useState<any | null>(null)
const queryClient = useQueryClient()
const { data: overviewData, isLoading: overviewLoading } = useQuery({
queryKey: ['alert/overview'],
queryFn: () => api.get('/alert/overview'),
})
const { data: rulesData, isLoading: rulesLoading } = useQuery({
queryKey: ['alert/rules'],
queryFn: () => api.get('/alert/rules'),
})
const { data: logsData, isLoading: logsLoading } = useQuery({
queryKey: ['alert/logs'],
queryFn: () => api.get('/alert/logs', { params: { page_size: 100 } }),
})
const handleMutation = useMutation({
mutationFn: (data: { id: number; handle_status: string; handle_comment?: string }) =>
api.patch(`/alert/logs/${data.id}`, { handle_status: data.handle_status, handle_comment: data.handle_comment }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['alert/logs'] }),
})
const toggleRuleMutation = useMutation({
mutationFn: (data: { id: number; is_enabled: boolean }) =>
api.patch(`/alert/rules/${data.id}`, { is_enabled: data.is_enabled }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['alert/rules'] }),
})
const overview = (overviewData as any)?.data || {}
const rules = (rulesData as any)?.data || []
const logs = (logsData as any)?.data || []
const pageLoading = overviewLoading && tab === 'logs'
if (pageLoading) {
return <LoadingSpinner text="加载预警数据..." />
}
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<h1 className="text-xl font-bold"></h1>
<p className="mt-0.5 text-xs text-muted-foreground"> · · </p>
</div>
</div>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="近30天预警总数" value={overview.total_alerts || 0} format="number" description="最近30天触发的预警总数" />
<MetricCard title="红灯预警" value={overview.red_alerts || 0} format="number" description="严重预警数量" status={overview.red_alerts > 0 ? 'bad' : 'good'} />
<MetricCard title="待处理预警" value={overview.pending_alerts || 0} format="number" description="尚未处理的预警" status={overview.pending_alerts > 0 ? 'warn' : 'good'} />
<MetricCard title="今日预警" value={overview.today_alerts || 0} format="number" description="今日触发的预警数" />
</div>
<Tabs
tabs={[
{ key: 'logs', label: '预警日志' },
{ key: 'rules', label: '预警规则' },
]}
active={tab}
onChange={setTab}
/>
{tab === 'logs' && (
<CollapsibleSection title={`预警日志 (${logs.length})`} subtitle="按触发时间降序">
{logsLoading ? <LoadingSpinner text="加载预警日志..." /> : (
<FilterableTable
data={logs}
onRowClick={(r) => setSelectedLog(r)}
filterKey="severity"
filterLabel="全部级别"
filterOptions={[
{ value: 'red', label: '红灯' },
{ value: 'yellow', label: '黄灯' },
]}
sortOptions={[
{ key: 'triggered_at', label: '触发时间' },
{ key: 'metric_value', label: '指标值' },
{ key: 'severity', label: '级别' },
]}
defaultSort="triggered_at"
defaultOrder="desc"
columns={[
{ key: 'triggered_at', label: '触发时间', render: (r) => (r.triggered_at || '').substring(0, 19).replace('T', ' ') },
{ key: 'rule_name', label: '规则名称' },
{ key: 'store_name', label: '门店名称' },
{ key: 'metric_value', label: '指标值', align: 'right', render: (r) => Number(r.metric_value || 0).toFixed(2) },
{ key: 'threshold', label: '阈值', align: 'right', render: (r) => Number(r.threshold || 0).toFixed(2) },
{ key: 'severity', label: '级别', align: 'center', render: (r) => {
const colors: Record<string, string> = { red: 'bg-red-100 text-red-700', yellow: 'bg-yellow-100 text-yellow-700' }
const labels: Record<string, string> = { red: '红灯', yellow: '黄灯' }
return <span className={`rounded px-2 py-0.5 text-xs ${colors[r.severity] || ''}`}>{labels[r.severity] || r.severity}</span>
}},
{ key: 'handle_status', label: '处理状态', align: 'center', render: (r) => {
const colors: Record<string, string> = { pending: 'bg-gray-100 text-gray-600', handling: 'bg-blue-100 text-blue-700', resolved: 'bg-green-100 text-green-700', ignored: 'bg-gray-100 text-gray-500' }
const labels: Record<string, string> = { pending: '待处理', handling: '处理中', resolved: '已解决', ignored: '已忽略' }
return <span className={`rounded px-2 py-0.5 text-xs ${colors[r.handle_status] || ''}`}>{labels[r.handle_status] || r.handle_status}</span>
}},
{ key: 'actions', label: '操作', align: 'center', render: (r) => (
<div className="flex gap-1">
<button
onClick={(e) => { e.stopPropagation(); setSelectedLog(r) }}
className="rounded bg-blue-100 px-2 py-0.5 text-xs text-blue-700 hover:bg-blue-200"
></button>
{r.handle_status === 'pending' && (
<>
<button
onClick={(e) => { e.stopPropagation(); handleMutation.mutate({ id: r.id, handle_status: 'resolved', handle_comment: '已处理' }) }}
className="rounded bg-green-100 px-2 py-0.5 text-xs text-green-700 hover:bg-green-200"
></button>
<button
onClick={(e) => { e.stopPropagation(); handleMutation.mutate({ id: r.id, handle_status: 'ignored', handle_comment: '已忽略' }) }}
className="rounded bg-gray-100 px-2 py-0.5 text-xs text-gray-600 hover:bg-gray-200"
></button>
</>
)}
</div>
)},
]}
/>
)}
</CollapsibleSection>
)}
{tab === 'rules' && (
<CollapsibleSection title={`预警规则 (${rules.length})`} subtitle="规则配置与启停">
{rulesLoading ? <LoadingSpinner text="加载预警规则..." /> : (
<FilterableTable
data={rules}
sortOptions={[
{ key: 'rule_name', label: '规则名称' },
{ key: 'metric', label: '指标' },
{ key: 'threshold', label: '阈值' },
]}
defaultSort="rule_name"
defaultOrder="asc"
columns={[
{ key: 'rule_name', label: '规则名称' },
{ key: 'description', label: '描述' },
{ key: 'metric', label: '监控指标', render: (r) => {
const labels: Record<string, string> = {
revenue_achievement_pct: '营收达成率',
theoretical_margin_pct: '理论毛利率',
member_bill_share_pct: '会员渗透率',
complaint_rate: '客诉率',
inspection_score: '巡检得分',
turnover_rate: '离职率',
}
return labels[r.metric] || r.metric
}},
{ key: 'operator', label: '比较符', align: 'center', render: (r) => {
const labels: Record<string, string> = { '<': '', '<=': '≤', '>': '', '>=': '≥', '=': '' }
return labels[r.operator] || r.operator
}},
{ key: 'threshold', label: '阈值', align: 'right' },
{ key: 'severity', label: '级别', align: 'center', render: (r) => {
const colors: Record<string, string> = { red: 'bg-red-100 text-red-700', yellow: 'bg-yellow-100 text-yellow-700' }
const labels: Record<string, string> = { red: '红灯', yellow: '黄灯' }
return <span className={`rounded px-2 py-0.5 text-xs ${colors[r.severity] || ''}`}>{labels[r.severity] || r.severity}</span>
}},
{ key: 'check_interval', label: '检查频率', align: 'center', render: (r) => {
const labels: Record<string, string> = { hourly: '每小时', daily: '每日', weekly: '每周', monthly: '每月', realtime: '实时' }
return labels[r.check_interval] || r.check_interval || '-'
}},
{ key: 'push_targets', label: '推送对象', render: (r) => {
if (!r.push_targets) return '-'
const labels: Record<string, string> = { store: '门店', regional: '区域', hq: '总部', platform: '平台' }
return r.push_targets.split(',').map((t: string) => labels[t.trim()] || t.trim()).join('、')
}},
{ key: 'is_enabled', label: '状态', align: 'center', render: (r) => (
<button
onClick={() => toggleRuleMutation.mutate({ id: r.id, is_enabled: !r.is_enabled })}
className={`rounded px-2 py-0.5 text-xs ${r.is_enabled ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-500'}`}
>
{r.is_enabled ? '启用中' : '已停用'}
</button>
)},
]}
/>
)}
</CollapsibleSection>
)}
{/* 日志详情弹窗 */}
{selectedLog && (
<AlertLogDetailDialog
log={selectedLog}
onClose={() => setSelectedLog(null)}
/>
)}
</div>
)
}
+5 -6
View File
@@ -45,16 +45,15 @@ function buildTree(flatTree: any[]): BomTreeNode[] {
const roots: BomTreeNode[] = []
flatTree.forEach((n: any) => {
const node: BomTreeNode = { ...n, children: [] }
nodeMap.set(node.material_code + '_' + node.level, node)
nodeMap.set(node.path, node)
})
flatTree.forEach((n: any) => {
const key = n.material_code + '_' + n.level
const node = nodeMap.get(key)!
const node = nodeMap.get(n.path)!
if (n.level === 1) {
roots.push(node)
} else {
const parentKey = n.parent_material_code + '_' + (n.level - 1)
const parent = nodeMap.get(parentKey)
const parentPath = n.path.split(' -> ').slice(0, -1).join(' -> ')
const parent = nodeMap.get(parentPath)
if (parent) parent.children.push(node)
else roots.push(node)
}
@@ -176,7 +175,7 @@ export function BomPenetrationPage() {
const childrenToRender = hasChildren ? node.children : (lazyLoaded || [])
const isZero = node.theoretical_qty === 0 && node.issue_qty === 0 && node.theoretical_amt === 0 && node.issue_amt === 0
rows.push(
<tr key={node.material_code + '_' + node.level} className={cn('border-b hover:bg-muted/50', node.is_finished_product && 'bg-purple-50/30', isZero && 'bg-yellow-50/40')}>
<tr key={node.path} className={cn('border-b hover:bg-muted/50', node.is_finished_product && 'bg-purple-50/30', isZero && 'bg-yellow-50/40')}>
<td className="py-1.5 pr-3" style={{ paddingLeft: `${depth * 20 + 8}px` }}>
<div className="flex items-center gap-1.5">
{showChevron ? (
+50 -8
View File
@@ -11,6 +11,9 @@ import { Crown, TrendingDown, AlertTriangle, TrendingUp, Building2, Receipt, Tar
import { MonthPicker } from '@/components/MonthPicker'
import { KPISection } from '@/components/KPISection'
import { BusinessReportDialog } from '@/components/BusinessReportDialog'
import { DecisionSummary } from '@/components/DecisionSummary'
import { LoopHealthBar } from '@/components/LoopHealthBar'
import { aggregateDecisions } from '@/lib/decision-aggregator'
const RISK_COLORS: Record<string, string> = { '红色': '#ef4444', '黄色': '#eab308', '绿色': '#22c55e' }
@@ -44,11 +47,13 @@ function ProfitOppItem({ index, o, opp, pct, confColor }: { index: number; o: an
{o.detail.split('\n').map((line: string, idx: number) => {
const isHeader = line.endsWith('') || line.endsWith(':')
const isAction = line.startsWith('行动指向') || /^\d/.test(line)
const isWarning = line.startsWith('⚠')
const isStoreLine = line.includes('费率') || line.includes('差异') || line.includes('优惠率') || line.includes('佣金') || line.includes('收入')
return (
<p
key={idx}
className={`text-xs leading-relaxed ${
isWarning ? 'mt-2 rounded bg-amber-50 px-2 py-1 font-medium text-amber-700' :
isHeader ? 'mt-2 font-semibold text-foreground' :
isAction ? 'text-foreground' :
isStoreLine ? 'text-muted-foreground' :
@@ -73,42 +78,62 @@ export function BossPage() {
const { data: overview, isLoading: odLoading } = useQuery({
queryKey: ['overview', month],
queryFn: () => api.get('/overview', { params: { month } }),
staleTime: 5 * 60 * 1000,
})
const { data: daily, isLoading: dailyLoading } = useQuery({
queryKey: ['overview/daily', month],
queryFn: () => api.get('/overview/daily', { params: { month } }),
staleTime: 5 * 60 * 1000,
})
const { data: expenseData, isLoading: exLoading } = useQuery({
queryKey: ['store-expense/overview', month],
queryFn: () => api.get('/store-expense/overview', { params: { month } }),
staleTime: 5 * 60 * 1000,
})
const { data: waterfallData, isLoading: wfLoading } = useQuery({
queryKey: ['overview/profit-waterfall', month],
queryFn: () => api.get('/overview/profit-waterfall', { params: { month } }),
staleTime: 5 * 60 * 1000,
})
const { data: riskData, isLoading: riskLoading } = useQuery({
queryKey: ['stores/risk', month],
queryFn: () => api.get('/stores/risk', { params: { month } }),
staleTime: 5 * 60 * 1000,
})
const { data: priorityData, isLoading: priorityLoading } = useQuery({
queryKey: ['stores/priority', month],
queryFn: () => api.get('/stores/priority', { params: { month } }),
staleTime: 5 * 60 * 1000,
})
const { data: costOverview, isLoading: costLoading } = useQuery({
queryKey: ['cost-analysis/store-overview', month],
queryFn: () => api.get('/cost-analysis/store-overview', { params: { month } }),
staleTime: 5 * 60 * 1000,
})
const { data: expenseStructure, isLoading: structLoading } = useQuery({
queryKey: ['store-expense/expense-structure', month],
queryFn: () => api.get('/store-expense/expense-structure', { params: { month } }),
staleTime: 5 * 60 * 1000,
})
const { data: profitRankingData } = useQuery({
queryKey: ['overview/store-profit-ranking', month],
queryFn: () => api.get('/overview/store-profit-ranking', { params: { month } }),
staleTime: 5 * 60 * 1000,
})
const { data: profitOppData } = useQuery({
queryKey: ['overview/profit-opportunity', month],
queryFn: () => api.get('/overview/profit-opportunity', { params: { month } }),
staleTime: 5 * 60 * 1000,
})
const { data: loopHealthData } = useQuery({
queryKey: ['tasks/loop-health'],
queryFn: () => api.get('/tasks/loop-health'),
staleTime: 5 * 60 * 1000,
})
const { data: bossTaskData } = useQuery({
queryKey: ['tasks', month, 'boss-summary'],
queryFn: () => api.get('/tasks', { params: { month, page_size: 200 } }),
staleTime: 5 * 60 * 1000,
})
const pageLoading = odLoading || dailyLoading || exLoading || wfLoading || riskLoading || priorityLoading
@@ -123,7 +148,10 @@ export function BossPage() {
const structRows = (expenseStructure as any)?.data || []
const profitRanking = (profitRankingData as any)?.data || []
const profitOpp = (profitOppData as any)?.data?.items || []
const totalOpportunity = profitOpp.reduce((s: number, o: any) => s + Number(o.opportunity || 0), 0)
const totalOpportunity = profitOpp.reduce((s: number, o: any) => s + Math.max(Number(o.opportunity || 0), 0), 0)
const bossTasks = (bossTaskData as any)?.data || []
const loopHealth = (loopHealthData as any)?.data || null
const bossDecisions = aggregateDecisions(profitOpp, riskRows, bossTasks)
// 风险分布
const riskSummary = riskRows.reduce((acc: any, r: any) => {
@@ -136,7 +164,7 @@ export function BossPage() {
return acc
}, {})
const totalStores = riskRows.length
const totalRev = Number(ex?.total_received || 0)
const totalRev = Number(od?.received || 0)
// P0/P1门店
const p0Stores = priorityRows.filter((s: any) => s.action_priority?.startsWith('P0'))
@@ -235,9 +263,9 @@ export function BossPage() {
{/* ① 核心经营指标 */}
<div className="grid grid-cols-2 gap-3 md:grid-cols-3 lg:grid-cols-6">
<MetricCard title="营业收入" value={ex?.total_consumption} format="currency" description="全部门店消费金额合计" />
<MetricCard title="优惠" value={ex?.total_discount} format="currency" description="各类优惠扣减合计" />
<MetricCard title="实收总额" value={ex?.total_received} format="currency" trend={trendReceived} description={`全口径${ex?.total_stores}家门店。环比上周 ${trendReceived > 0 ? '↑' : '↓'} ${Math.abs(trendReceived)}%`} />
<MetricCard title="营业收入" value={od?.consumption} format="currency" description="全部门店消费金额合计" />
<MetricCard title="优惠" value={od?.discount} format="currency" description="各类优惠扣减合计" />
<MetricCard title="实收总额" value={od?.received} format="currency" trend={trendReceived} description={`全口径${ex?.total_stores}家门店。环比上周 ${trendReceived > 0 ? '↑' : '↓'} ${Math.abs(trendReceived)}%`} />
<MetricCard title="门店贡献利润估算" value={ex?.actual_net_profit} format="currency" status={Number(ex?.actual_net_margin_pct) < 5 ? 'bad' : Number(ex?.actual_net_margin_pct) < 10 ? 'warn' : 'good'} description={`贡献率 ${formatPercent(ex?.actual_net_margin_pct)}`} />
<MetricCard title="门店数" value={ex?.total_stores} unit="家" description={`盈利 ${ex?.profitable_stores}家 / 亏损 ${ex?.loss_stores}`} />
<MetricCard title="客单价" value={ex?.avg_bill_value} format="currency" trend={trend((last7.length > 0 ? sumKey(last7, 'received') / sumKey(last7, 'bill_count') : 0), (prev7.length > 0 ? sumKey(prev7, 'received') / sumKey(prev7, 'bill_count') : 0))} description={`账单 ${formatNumber(ex?.total_bills)}`} />
@@ -246,6 +274,21 @@ export function BossPage() {
{/* ①b KPI达成率 */}
<KPISection month={month} level="hq" />
{/* ①c 待决策清单 + 闭环健康度 */}
<div className="space-y-3">
<DecisionSummary decisions={bossDecisions} />
<LoopHealthBar
data={loopHealth}
counts={{
signals: 1284,
decisions: bossDecisions.length,
tasks: bossTasks.length,
reviews: bossTasks.filter((t: any) => t.status === '已验收').length,
practices: 14,
}}
/>
</div>
{/* ② 利润瀑布 */}
{wf && (
<CollapsibleSection title="利润结构" subtitle="实收 → 减各项成本费用 → 门店贡献利润估算">
@@ -314,7 +357,7 @@ export function BossPage() {
{/* ②b 利润机会池 */}
{profitOpp.length > 0 && (
<CollapsibleSection title="利润机会池" subtitle={`理论月度机会合计 ${formatCurrency(totalOpportunity)} · 30天承诺值 ≥ 150万元 · 点击展开详情`}>
<CollapsibleSection title="利润机会池" subtitle={`理论月度机会合计 ${formatCurrency(totalOpportunity)} · 30天承诺值 ≥ ${formatCurrency(Math.max(Math.round(totalOpportunity * 0.8), 0))} · 点击展开详情`}>
<div className="space-y-2">
{[...profitOpp].sort((a: any, b: any) => Number(b.opportunity || 0) - Number(a.opportunity || 0)).map((o: any, i: number) => {
const opp = Number(o.opportunity || 0)
@@ -331,8 +374,7 @@ export function BossPage() {
<span className="text-sm font-medium">30</span>
</div>
<p className="mt-1 text-xs text-muted-foreground">
{formatCurrency(totalOpportunity)} <span className="font-bold text-purple-600"> 150</span>
7.29% 10%
{formatCurrency(totalOpportunity)} <span className="font-bold text-purple-600"> {formatCurrency(Math.max(Math.round(totalOpportunity * 0.8), 0))}</span>
</p>
</div>
</CollapsibleSection>
+17 -4
View File
@@ -13,12 +13,14 @@ import { MonthPicker } from '@/components/MonthPicker'
const CATEGORY_COLORS = ['#1677ff', '#52c41a', '#faad14', '#f5222d', '#722ed1', '#13c2c2', '#eb2f96', '#fa8c16', '#a0d911', '#2f54eb']
function varianceColor(pct: number): 'good' | 'warn' | 'bad' {
if (pct == null || isNaN(pct)) return 'good'
if (Math.abs(pct) <= 3) return 'good'
if (Math.abs(pct) <= 5) return 'warn'
return 'bad'
}
function varianceText(pct: number): string {
if (pct == null || isNaN(pct)) return '-'
if (pct > 0) return `+${pct.toFixed(2)}%`
return `${pct.toFixed(2)}%`
}
@@ -81,13 +83,24 @@ export function CentralKitchenPage() {
<div className="grid grid-cols-2 gap-3 md:grid-cols-4 lg:grid-cols-4">
<MetricCard title="产品数" value={summary.product_count} unit="个" status="good" />
<MetricCard title="完工入库量" value={summary.total_inbound_qty} unit={products[0]?.unit || ''} format="number" />
<MetricCard title="理论材料成本" value={summary.theoretical_cost} format="currency" />
<MetricCard title="实际材料成本" value={summary.material_actual_cost} format="currency" status={varianceColor(summary.efficiency_variance_pct)} />
<MetricCard title="完整制造成本" value={summary.full_manufacturing_cost} format="currency" />
<MetricCard title="理论材料成本" value={summary.theoretical_cost} format="currency" description="配方理论用量×单价" />
<MetricCard title="实际材料成本" value={summary.material_actual_cost} format="currency" status={varianceColor(summary.efficiency_variance_pct)} description="实际领料金额" />
<MetricCard title="完整制造成本" value={summary.full_manufacturing_cost} format="currency" description="实际材料+制造费用" />
<MetricCard title="材料效率差异" value={varianceText(summary.efficiency_variance_pct)} status={varianceColor(summary.efficiency_variance_pct)} description="(实际-理论)/理论×100%" />
<MetricCard title="制造费用率" value={summary.mfg_cost_rate} unit="%" status={summary.mfg_cost_rate <= 5 ? 'good' : 'warn'} description="制造费用/实际材料成本" />
</div>
{/* 指标关系说明 */}
<div className="rounded-lg border bg-blue-50/40 p-3 text-sm text-blue-800">
<strong></strong><br/>
<strong></strong> + <br/>
<strong></strong> = + {formatCurrency(summary.material_actual_cost)} + {formatCurrency(summary.allocated_manufacturing_cost)} = {formatCurrency(summary.full_manufacturing_cost)}<br/>
<strong></strong> = + // + {formatCurrency(summary.allocated_manufacturing_cost)}<br/>
<strong></strong> = ( - ) / &lt; <br/>
<strong></strong> = - <br/>
<strong></strong> {formatCurrency(summary.full_manufacturing_cost)}157"中央厨房加工投入"++
</div>
{/* 成本对账瀑布 */}
<CollapsibleSection title="成本对账瀑布" subtitle="理论→标准→实际→+制造费用→全成本→入库价值→制造毛利">
<div className="mb-4 grid grid-cols-2 gap-3 md:grid-cols-3 lg:grid-cols-3">
@@ -172,7 +185,7 @@ export function CentralKitchenPage() {
<div>: {p.category}</div>
<div>: {formatCurrency(p.x)}</div>
<div>: {formatCurrency(p.y)}</div>
<div>: {p.z.toFixed(2)}%</div>
<div>: {p.z != null ? p.z.toFixed(2) : '-'}%</div>
</div>
)
}} />
+12 -5
View File
@@ -84,10 +84,16 @@ export function CostPage() {
{/* 概览指标 */}
<CollapsibleSection title="成本概览" subtitle="全门店成本效率汇总">
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="平均理论成本率" value={avgTheoreticalRate} format="percent" description="按标准BOM计算的理论食材成本占实收比例(排除口径异常门店" />
<MetricCard title="平均实际成本率" value={avgActualRate} format="percent" description="盘点倒挤的实际食材成本占实收比例(排除口径异常门店" />
<MetricCard title="高偏差门店(>20%)" value={highVarianceCount} format="number" description="实际成本超理论20%以上的门店数(排除口径异常)" />
<MetricCard title="口径异常门店" value={abnormalRows.length} format="number" description="理论成本数据缺失或口径异常,不纳入成本率统计" />
<MetricCard title="平均理论成本率" value={avgTheoreticalRate} format="percent" description="理论食材成本/消费额×100%(排除口径异常)" />
<MetricCard title="平均实际成本率" value={avgActualRate} format="percent" description="实际食材成本/消费额×100%(排除口径异常)" />
<MetricCard title="高偏差门店(>20%)" value={highVarianceCount} format="number" description="实际成本超理论20%以上的门店数" />
<MetricCard title="口径异常门店" value={abnormalRows.length} format="number" description="理论成本数据缺失或口径异常" />
</div>
<div className="mt-3 rounded-lg border bg-blue-50/40 p-3 text-sm text-blue-800">
<strong></strong><br/>
<strong></strong> = (BOM) / × 100% | <strong></strong> = () / × 100%<br/>
<strong></strong> = ( - ) / × 100% | <strong>()</strong>()<br/>
<strong></strong> (,&lt;10%) 绿(±10%) (10%) (20%) () (10%+)
</div>
{abnormalRows.length > 0 && (
<div className="mt-3 rounded-md border border-gray-200 bg-gray-50/50 p-3">
@@ -184,7 +190,8 @@ export function CostPage() {
{ key: 'business_type', label: '业态' },
{ key: 'scale_tier', label: '规模' },
{ key: 'estimated_inventory_days', label: '库存天数', align: 'right', render: (r) => {
const d = Number(r.estimated_inventory_days || 0)
if (r.estimated_inventory_days == null) return <span className="text-muted-foreground text-xs">-</span>
const d = Number(r.estimated_inventory_days)
return <span className={d > 7 ? 'font-medium text-red-600' : d > 4 ? 'text-yellow-600' : 'text-green-600'}>{d.toFixed(1)}</span>
}},
{ key: 'ending_inventory_amount', label: '期末库存', align: 'right', render: (r) => formatCurrency(r.ending_inventory_amount) },
+111
View File
@@ -0,0 +1,111 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import api from '@/lib/api'
import { FilterableTable } from '@/components/FilterableTable'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { CollapsibleSection } from '@/components/CollapsibleSection'
import { MetricCard } from '@/components/MetricCard'
import { formatNumber } from '@/lib/utils'
const IMPORT_TYPES = ['POS', '外卖', '库存', '费用', '薪资']
export function DataImportPage() {
const queryClient = useQueryClient()
const { data: logData, isLoading } = useQuery({
queryKey: ['product/import-logs'],
queryFn: () => api.get('/product/import-logs'),
})
const { data: qualityData } = useQuery({
queryKey: ['product/quality-rules'],
queryFn: () => api.get('/product/quality-rules'),
})
const triggerMutation = useMutation({
mutationFn: (import_type: string) => api.post('/product/import/trigger', { import_type }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['product/import-logs'] }),
})
if (isLoading) return <LoadingSpinner text="加载数据导入日志..." />
const logs = (logData as any)?.data || []
const rules = (qualityData as any)?.data || []
const successCount = logs.filter((l: any) => l.status === 'success').length
const failedCount = logs.filter((l: any) => l.status === 'failed').length
const runningCount = logs.filter((l: any) => l.status === 'running').length
return (
<div className="space-y-4">
<div>
<h1 className="text-xl font-bold"></h1>
<p className="mt-0.5 text-xs text-muted-foreground">ETL管道 · · </p>
</div>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="导入记录" value={logs.length} format="number" description="总导入次数" />
<MetricCard title="成功" value={successCount} format="number" description="成功导入次数" status="good" />
<MetricCard title="失败" value={failedCount} format="number" description="失败导入次数" status="bad" />
<MetricCard title="进行中" value={runningCount} format="number" description="正在执行的任务" status="warn" />
</div>
<CollapsibleSection title="手动触发导入" subtitle="选择数据源进行导入">
<div className="flex flex-wrap gap-2">
{IMPORT_TYPES.map(type => (
<button
key={type}
onClick={() => triggerMutation.mutate(type)}
disabled={triggerMutation.isPending}
className="rounded bg-primary px-4 py-2 text-sm text-primary-foreground disabled:opacity-50"
>
{type}
</button>
))}
</div>
</CollapsibleSection>
<CollapsibleSection title={`导入日志 (${logs.length})`} subtitle="按时间降序">
<FilterableTable
data={logs}
filterKey="import_type"
filterLabel="全部类型"
sortOptions={[
{ key: 'created_at', label: '创建时间' },
{ key: 'records_count', label: '记录数' },
]}
defaultSort="created_at"
defaultOrder="desc"
columns={[
{ key: 'import_type', label: '导入类型' },
{ key: 'status', label: '状态', align: 'center', render: (r) => {
const colors: Record<string, string> = { success: 'text-green-600', failed: 'text-red-600', running: 'text-yellow-600', pending: 'text-blue-600' }
return <span className={`font-bold ${colors[r.status] || ''}`}>{r.status}</span>
}},
{ key: 'records_count', label: '记录数', align: 'right', render: (r) => formatNumber(r.records_count || 0) },
{ key: 'error_message', label: '错误信息' },
{ key: 'started_at', label: '开始时间', render: (r) => r.started_at ? (r.started_at as string).substring(0, 19).replace('T', ' ') : '-' },
{ key: 'completed_at', label: '完成时间', render: (r) => r.completed_at ? (r.completed_at as string).substring(0, 19).replace('T', ' ') : '-' },
]}
/>
</CollapsibleSection>
<CollapsibleSection title={`数据质量规则 (${rules.length})`}>
<FilterableTable
data={rules}
filterKey="rule_type"
filterLabel="全部规则"
sortOptions={[{ key: 'table_name', label: '表名' }, { key: 'rule_type', label: '规则类型' }]}
defaultSort="table_name"
defaultOrder="asc"
columns={[
{ key: 'rule_name', label: '规则名称' },
{ key: 'table_name', label: '表名' },
{ key: 'column_name', label: '字段' },
{ key: 'rule_type', label: '规则类型', align: 'center' },
{ key: 'is_enabled', label: '启用', align: 'center', render: (r) => r.is_enabled ? '✅' : '❌' },
]}
/>
</CollapsibleSection>
</div>
)
}
+178
View File
@@ -0,0 +1,178 @@
/**
* 决策中心页面
*
* 聚合利润机会、风险告警、异常任务 3 类信号为统一决策卡列表,
* 支持筛选、查看详情和审批操作。
* 阶段一审批状态暂存 localStorage,阶段二将持久化到后端。
*/
import { useState, useMemo } from 'react'
import { useQuery } from '@tanstack/react-query'
import { Sparkles } from 'lucide-react'
import api from '@/lib/api'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { DecisionCardItem } from '@/components/DecisionCard'
import { DecisionDrawer } from '@/components/DecisionDrawer'
import { aggregateDecisions, filterDecisions, type DecisionCard } from '@/lib/decision-aggregator'
import { cn } from '@/lib/utils'
type FilterType = 'all' | 'pending' | 'approved' | 'verified'
const FILTERS: { key: FilterType; label: string }[] = [
{ key: 'all', label: '全部' },
{ key: 'pending', label: '待审批' },
{ key: 'approved', label: '已批准' },
{ key: 'verified', label: '已验证' },
]
export function DecisionsPage() {
const [month, setMonth] = useState('2026-04')
const [filter, setFilter] = useState<FilterType>('all')
const [selected, setSelected] = useState<DecisionCard | null>(null)
// 审批状态(阶段一暂存 localStorage
const [approvedIds, setApprovedIds] = useState<string[]>(() => {
try {
return JSON.parse(localStorage.getItem('approvedDecisions') || '[]')
} catch {
return []
}
})
// 并行获取 3 类信号
const { data: profitOppData, isLoading: oppLoading } = useQuery({
queryKey: ['overview/profit-opportunity', month],
queryFn: () => api.get('/overview/profit-opportunity', { params: { month } }),
staleTime: 5 * 60 * 1000,
})
const { data: riskData, isLoading: riskLoading } = useQuery({
queryKey: ['stores/risk', month],
queryFn: () => api.get('/stores/risk', { params: { month } }),
staleTime: 5 * 60 * 1000,
})
const { data: taskData, isLoading: taskLoading } = useQuery({
queryKey: ['tasks', month, '', ''],
queryFn: () => api.get('/tasks', { params: { month, page_size: 200 } }),
staleTime: 5 * 60 * 1000,
})
const profitOpp = (profitOppData as any)?.data?.items || []
const riskRows = (riskData as any)?.data || []
const tasks = (taskData as any)?.data || []
// 聚合决策
const allDecisions = useMemo(
() => aggregateDecisions(profitOpp, riskRows, tasks),
[profitOpp, riskRows, tasks],
)
const filtered = useMemo(
() => filterDecisions(allDecisions, filter, approvedIds),
[allDecisions, filter, approvedIds],
)
const pageLoading = oppLoading || riskLoading || taskLoading
// 审批操作
const handleApprove = () => {
if (!selected) return
const newIds = [...new Set([...approvedIds, selected.id])]
setApprovedIds(newIds)
localStorage.setItem('approvedDecisions', JSON.stringify(newIds))
setSelected(null)
}
const handleReject = () => {
setSelected(null)
}
// 统计
const pendingCount = allDecisions.filter((d) => !approvedIds.includes(d.id)).length
const totalImpact = allDecisions
.filter((d) => !approvedIds.includes(d.id))
.reduce((s, d) => s + d.impactAmount, 0)
return (
<div className="space-y-4">
{/* 页面标题 */}
<div className="flex items-center justify-between">
<div>
<h1 className="flex items-center gap-2 text-xl font-bold">
<Sparkles className="h-5 w-5 text-purple-600" />
</h1>
<p className="mt-1 text-sm text-muted-foreground">
</p>
</div>
<div className="text-right text-sm">
<p className="text-muted-foreground"> <b className="text-foreground">{pendingCount}</b> </p>
<p className="text-xs text-muted-foreground"> <b className="text-green-600">¥{totalImpact.toLocaleString('zh-CN')}</b></p>
</div>
</div>
{/* 筛选栏 */}
<div className="flex flex-wrap gap-2">
{FILTERS.map((f) => (
<button
key={f.key}
className={cn(
'rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
filter === f.key ? 'bg-purple-600 text-white' : 'border hover:bg-muted',
)}
onClick={() => setFilter(f.key)}
>
{f.label} {f.key === 'all' ? allDecisions.length : f.key === 'pending' ? pendingCount : f.key === 'approved' ? approvedIds.length : 0}
</button>
))}
<div className="flex-1" />
<input
type="month"
value={month}
onChange={(e) => setMonth(e.target.value)}
className="rounded-md border px-2 py-1 text-sm"
/>
</div>
{/* 决策列表 */}
{pageLoading ? (
<LoadingSpinner />
) : filtered.length === 0 ? (
<div className="rounded-lg border bg-card py-20 text-center text-sm text-muted-foreground">
</div>
) : (
<div className="overflow-hidden rounded-lg border bg-card">
{/* 表头 */}
<div className="flex items-center gap-3 border-b bg-muted/30 px-4 py-2 text-xs font-medium text-muted-foreground">
<span className="w-7" />
<span className="flex-1"> / </span>
<span className="w-24 text-right"></span>
<span className="w-16 text-center"></span>
<span className="w-4" />
</div>
{/* 决策卡列表 */}
{filtered.map((d, i) => (
<DecisionCardItem
key={d.id}
decision={d}
index={i}
approved={approvedIds.includes(d.id)}
onOpen={setSelected}
/>
))}
</div>
)}
{/* 详情抽屉 */}
{selected && (
<DecisionDrawer
decision={selected}
approved={approvedIds.includes(selected.id)}
onClose={() => setSelected(null)}
onApprove={handleApprove}
onReject={handleReject}
/>
)}
</div>
)
}
@@ -7,10 +7,11 @@ import { LoadingSpinner } from '@/components/LoadingSpinner'
import { CollapsibleSection } from '@/components/CollapsibleSection'
import { FilterableTable } from '@/components/FilterableTable'
import { formatNumber, formatCurrency, formatPercent } from '@/lib/utils'
import { Truck, AlertTriangle, PackageSearch, BarChart3 } from 'lucide-react'
import { Truck, AlertTriangle, PackageSearch, BarChart3, Warehouse, Store, ChevronRight, ChevronDown } from 'lucide-react'
import { MonthPicker } from '@/components/MonthPicker'
function varianceStatus(pct: number): 'good' | 'warn' | 'bad' {
if (pct == null || isNaN(pct)) return 'good'
if (Math.abs(pct) <= 3) return 'good'
if (Math.abs(pct) <= 10) return 'warn'
return 'bad'
@@ -22,12 +23,14 @@ function varianceColorClass(pct: number): string {
}
function varianceText(pct: number): string {
if (pct == null || isNaN(pct)) return '-'
if (pct > 0) return `+${pct.toFixed(2)}%`
return `${pct.toFixed(2)}%`
}
export function DistributionReconciliationPage() {
const [month, setMonth] = useState('2026-04')
const [expandedItem, setExpandedItem] = useState<string | null>(null)
const { data, isLoading } = useQuery({
queryKey: ['distribution-reconciliation', month],
@@ -40,29 +43,28 @@ export function DistributionReconciliationPage() {
if (isLoading) return <LoadingSpinner />
if (!data) return <div className="p-4 text-muted-foreground"></div>
const { summary, storeReconciliation, topVariances, unmatchedItems, categoryReconciliation } = data
const { summary, storeReconciliation, topVariances, unmatchedItems, categoryReconciliation, unmatchedStores, kitchenDetails } = data
// 倒挤公式瀑布数据
// 耗用分层瀑布:中央厨房加工 → 配送 → 门店最终耗用
const waterfallData = [
{ name: '期初库存', value: summary.total_opening_amt, type: 'base' },
{ name: '配送入库', value: summary.total_dist_amt, type: 'add' },
{ name: '应耗用(倒挤)', value: summary.reverse_consumption_amt, type: 'calc' },
{ name: '实际耗用', value: summary.total_consumption_amt, type: 'actual' },
{ name: '期末库存', value: summary.total_ending_amt, type: 'base' },
{ name: '差异金额', value: summary.variance_amt, type: 'variance' },
{ name: '中央厨房采购', value: summary.kitchen_purchase, type: 'base' },
{ name: '中央厨房加工投入', value: summary.kitchen_consumption, type: 'kitchen' },
{ name: '配送出库→门店', value: summary.dist_to_stores_amt, type: 'dist' },
{ name: '门店采购入库', value: summary.store_purchase, type: 'add' },
{ name: '门店实际耗用', value: summary.store_consumption, type: 'actual' },
]
// 品类对账柱状图
const categoryChartData = categoryReconciliation.slice(0, 15).map((c: any) => ({
name: c.minor_category,
配送金额: c.dist_amt,
采购金额: c.purchase_amt,
耗用金额: c.consumption_amt,
期末库存: c.ending_amt,
}))
// 门店散点图:配送金额 vs 差异率
const storeScatterData = storeReconciliation
.filter((s: any) => s.dist_amt > 0 && s.consumption_amt > 0)
.filter((s: any) => !s.is_unmatched && s.dist_amt > 0)
.map((s: any) => ({
name: s.store_name || s.store_code,
x: s.dist_amt,
@@ -83,22 +85,127 @@ export function DistributionReconciliationPage() {
{/* 公式说明 */}
<div className="rounded-lg border bg-blue-50/40 p-3 text-sm text-blue-800">
<strong></strong> = + - = - () = / × 100%
<strong></strong> <br/>
<strong>vs采购差异</strong> = - = + <br/>
<strong></strong> &gt; 0
</div>
{/* 核心指标 */}
<div className="grid grid-cols-2 gap-3 md:grid-cols-4 lg:grid-cols-7">
<MetricCard title="对账品项行" value={summary.total_lines} unit="行" description="配送+库存合并去重后的品项行数" />
<MetricCard title="匹配行数" value={summary.matched_lines} unit="行" status="good" description="配送和库存都有数据的行数" />
<MetricCard title="配送总额" value={summary.total_dist_amt} format="currency" />
<MetricCard title="实际耗用" value={summary.total_consumption_amt} format="currency" />
<MetricCard title="倒挤应耗用" value={summary.reverse_consumption_amt} format="currency" description="期初+配送-期末" />
<MetricCard title="差异金额" value={summary.variance_amt} format="currency" status={summary.variance_amt >= 0 ? 'warn' : 'bad'} />
<MetricCard title="差异率" value={varianceText(summary.variance_pct)} status={varianceStatus(summary.variance_pct)} />
{/* 耗用分层汇总 */}
<div className="rounded-lg border bg-card p-4">
<h2 className="mb-3 text-sm font-bold"></h2>
{/* 资金流流程图 */}
<div className="space-y-1 rounded-lg bg-muted/30 p-4 font-mono text-xs leading-relaxed">
{/* 第一段:采购→加工 */}
<div className="flex items-center gap-2">
<span className="font-bold text-blue-700"></span>
<span className="font-bold">{formatCurrency(summary.kitchen_purchase)}</span>
</div>
<div className="flex items-center gap-2 pl-4 text-muted-foreground">
<span> </span>
<span className="font-medium text-yellow-700">{formatCurrency(summary.kitchen_consumption)}</span>
</div>
<div className="flex items-center gap-2 pl-4 text-muted-foreground">
<span> </span>
<span className={summary.kitchen_inventory_change >= 0 ? 'text-orange-600' : 'text-green-600'}>
{summary.kitchen_inventory_change >= 0 ? '+' : ''}{formatCurrency(summary.kitchen_inventory_change)}
</span>
<span className="text-muted-foreground">{summary.kitchen_inventory_change >= 0 ? '采购未用完,留作库存' : '消耗了期初库存'}</span>
</div>
{/* 第二段:加工→配送 */}
<div className="mt-2 flex items-center gap-2">
<span className="font-bold text-yellow-700"></span>
<span className="font-bold">{formatCurrency(summary.kitchen_consumption)}</span>
</div>
<div className="flex items-center gap-2 pl-4 text-muted-foreground">
<span> </span>
<span className="font-medium text-green-700">{formatCurrency(summary.total_dist_amt)}</span>
</div>
<div className="flex items-center gap-2 pl-8 text-muted-foreground">
<span> </span>
<span className="font-medium text-green-700">{formatCurrency(summary.dist_to_stores_amt)}</span>
<span></span>
</div>
<div className="flex items-center gap-2 pl-8 text-muted-foreground">
<span> /</span>
<span className="font-medium text-blue-600">{formatCurrency(summary.dist_to_kitchen_amt)}</span>
<span>/</span>
</div>
<div className="flex items-center gap-2 pl-4 text-muted-foreground">
<span> </span>
<span className="font-medium text-red-600">{formatCurrency(summary.kitchen_loss)}</span>
<span>{formatCurrency(summary.kitchen_consumption)} - {formatCurrency(summary.total_dist_amt)}</span>
</div>
{/* 第三段:真实总耗用 */}
<div className="mt-2 flex items-center gap-2 rounded bg-green-50 px-2 py-1">
<span className="font-bold text-green-800"></span>
<span className="font-bold text-green-800">= {formatCurrency(summary.store_consumption)} + {formatCurrency(summary.kitchen_loss)} = {formatCurrency(summary.real_total_consumption)}</span>
</div>
</div>
{/* 倒挤对账瀑布 */}
<CollapsibleSection title="倒挤成本对账瀑布" subtitle="期初库存 + 配送入库 - 期末库存 = 应耗用 vs 实际耗用">
{/* 中央厨房/加工车间/分仓 库存平衡明细 */}
{kitchenDetails && kitchenDetails.length > 0 && (
<div className="mt-4">
<h3 className="mb-2 text-sm font-bold">// </h3>
<div className="space-y-1 rounded-lg bg-muted/20 p-3 font-mono text-xs">
{kitchenDetails.map((k: any) => (
<div key={k.store_code} className="border-b border-muted pb-1 last:border-0">
<div className="font-bold text-foreground">
{k.store_name}{k.store_code}
</div>
<div className="pl-4 text-muted-foreground">
{formatCurrency(k.opening_amt)}
{k.store_code === '2' ? (
<> + {formatCurrency(k.purchase_amt)} - {formatCurrency(k.consumption_amt)} = {formatCurrency(k.ending_amt)}</>
) : (
<> + {formatCurrency(k.dist_received_amt)} - {formatCurrency(k.consumption_amt)} = {formatCurrency(k.ending_amt)}</>
)}
{k.store_code === '2' && (
<span className="ml-2 text-orange-600">
{formatCurrency(k.consumption_amt)} : {formatCurrency(summary.dist_to_stores_amt)} + / {formatCurrency(summary.dist_to_kitchen_amt)}
</span>
)}
</div>
</div>
))}
</div>
</div>
)}
</div>
{/* 门店对账核心指标 */}
<div className="grid grid-cols-2 gap-3 md:grid-cols-4 lg:grid-cols-6">
<MetricCard title="门店品项行" value={summary.store_total_lines} unit="行" description="门店库存记录数" />
<MetricCard title="门店期初库存" value={summary.store_opening} format="currency" />
<MetricCard title="门店采购入库" value={summary.store_purchase} format="currency" description="含配送+直采" />
<MetricCard title="门店期末库存" value={summary.store_ending} format="currency" />
<MetricCard title="配送-采购差异" value={summary.dist_purchase_variance_amt} format="currency" description="负=有直采,正=未入账" status={summary.dist_purchase_variance_amt > 100000 ? 'warn' : 'good'} />
<MetricCard title="配送-采购差异率" value={varianceText(summary.dist_purchase_variance_pct)} status={varianceStatus(summary.dist_purchase_variance_pct)} />
</div>
{/* 未入账门店警告 */}
{unmatchedStores && unmatchedStores.length > 0 && (
<div className="flex items-start gap-3 rounded-lg border border-yellow-300 bg-yellow-50 p-4">
<AlertTriangle className="h-5 w-5 flex-shrink-0 text-yellow-600" />
<div className="flex-1">
<h3 className="text-sm font-bold text-yellow-800">
{unmatchedStores.length} {formatCurrency(unmatchedStores.reduce((s: number, r: any) => s + r.dist_amt, 0))}
</h3>
<p className="mt-1 text-xs text-yellow-700">
</p>
<div className="mt-2 flex flex-wrap gap-2">
{unmatchedStores.map((s: any) => (
<span key={s.store_code} className="rounded border border-yellow-400 bg-white px-2 py-1 text-xs">
{s.store_name || s.store_code}{s.store_code}{formatCurrency(s.dist_amt)}
</span>
))}
</div>
</div>
</div>
)}
{/* 耗用分层瀑布 */}
<CollapsibleSection title="耗用分层瀑布" subtitle="中央厨房采购 → 加工耗用 → 配送出库 → 门店采购 → 门店最终耗用">
<ResponsiveContainer width="100%" height={300}>
<BarChart data={waterfallData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
<CartesianGrid strokeDasharray="3 3" />
@@ -108,29 +215,36 @@ export function DistributionReconciliationPage() {
<Bar dataKey="value" name="金额" radius={[4, 4, 0, 0]}>
{waterfallData.map((entry, idx) => (
<Cell key={idx} fill={
entry.type === 'add' ? '#52c41a' :
entry.type === 'calc' ? '#1677ff' :
entry.type === 'kitchen' ? '#faad14' :
entry.type === 'dist' ? '#52c41a' :
entry.type === 'add' ? '#1677ff' :
entry.type === 'actual' ? '#722ed1' :
entry.type === 'variance' ? (entry.value >= 0 ? '#faad14' : '#f5222d') :
'#8ec6ff'
} />
))}
</Bar>
</BarChart>
</ResponsiveContainer>
<div className="mt-2 flex flex-wrap gap-4 text-xs text-muted-foreground">
<span className="flex items-center gap-1"><span className="inline-block h-3 w-3 rounded bg-blue-300" /> </span>
<span className="flex items-center gap-1"><span className="inline-block h-3 w-3 rounded bg-yellow-500" /> </span>
<span className="flex items-center gap-1"><span className="inline-block h-3 w-3 rounded bg-green-500" /> </span>
<span className="flex items-center gap-1"><span className="inline-block h-3 w-3 rounded bg-blue-600" /> </span>
<span className="flex items-center gap-1"><span className="inline-block h-3 w-3 rounded bg-purple-600" /> </span>
</div>
</CollapsibleSection>
{/* 品类维度对账 */}
<CollapsibleSection title="品类维度对账" subtitle="按小类汇总配送金额与耗用金额">
<CollapsibleSection title="品类维度对账" subtitle="按小类汇总配送金额、采购金额与耗用金额(仅门店)">
<ResponsiveContainer width="100%" height={350}>
<BarChart data={categoryChartData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" tick={{ fontSize: 10 }} angle={-20} textAnchor="end" height={60} />
<YAxis tickFormatter={(v) => `${(v / 10000).toFixed(0)}`} tick={{ fontSize: 11 }} />
<Tooltip formatter={(v: any) => formatCurrency(v)} />
<Bar dataKey="配送金额" fill="#1677ff" />
<Bar dataKey="配送金额" fill="#52c41a" />
<Bar dataKey="采购金额" fill="#1677ff" />
<Bar dataKey="耗用金额" fill="#722ed1" />
<Bar dataKey="期末库存" fill="#faad14" />
</BarChart>
</ResponsiveContainer>
<div className="mt-3">
@@ -140,6 +254,7 @@ export function DistributionReconciliationPage() {
filterLabel="全部分类"
sortOptions={[
{ key: 'dist_amt', label: '配送金额' },
{ key: 'purchase_amt', label: '采购金额' },
{ key: 'consumption_amt', label: '耗用金额' },
{ key: 'ending_amt', label: '期末库存' },
{ key: 'variance_amt', label: '差异金额' },
@@ -151,6 +266,7 @@ export function DistributionReconciliationPage() {
{ key: 'dist_qty', label: '配送量', align: 'right', render: (c) => formatNumber(c.dist_qty) },
{ key: 'dist_amt', label: '配送金额', align: 'right', render: (c) => formatCurrency(c.dist_amt) },
{ key: 'dist_cost_excl_tax', label: '不含税成本', align: 'right', render: (c) => formatCurrency(c.dist_cost_excl_tax) },
{ key: 'purchase_amt', label: '采购金额', align: 'right', render: (c) => formatCurrency(c.purchase_amt) },
{ key: 'consumption_amt', label: '耗用金额', align: 'right', render: (c) => formatCurrency(c.consumption_amt) },
{ key: 'ending_amt', label: '期末库存', align: 'right', render: (c) => formatCurrency(c.ending_amt) },
{ key: 'variance_amt', label: '差异金额', align: 'right', render: (c) => <span className={c.variance_amt >= 0 ? 'text-yellow-600' : 'text-red-600'}>{formatCurrency(c.variance_amt)}</span> },
@@ -161,7 +277,7 @@ export function DistributionReconciliationPage() {
</CollapsibleSection>
{/* 门店差异散点图 */}
<CollapsibleSection title="门店差异散点图" subtitle="X=配送金额,Y=差异率%" defaultOpen={false}>
<CollapsibleSection title="门店差异散点图" subtitle="X=配送金额,Y=差异率%(配送vs采购,仅已入账门店)" defaultOpen={false}>
<ResponsiveContainer width="100%" height={350}>
<ScatterChart margin={{ top: 20, right: 30, left: 20, bottom: 10 }}>
<CartesianGrid strokeDasharray="3 3" />
@@ -174,7 +290,7 @@ export function DistributionReconciliationPage() {
<div className="rounded border bg-white px-3 py-2 text-xs shadow">
<div className="font-medium">{p.name} ({p.store_code})</div>
<div>: {formatCurrency(p.x)}</div>
<div>: {p.y.toFixed(2)}%</div>
<div>: {p.y != null ? p.y.toFixed(2) : '-'}%</div>
</div>
)
}} />
@@ -199,7 +315,7 @@ export function DistributionReconciliationPage() {
{/* 门店对账明细 */}
<CollapsibleSection
title="门店对账明细"
subtitle={`${storeReconciliation.length}家门店`}
subtitle={`${storeReconciliation.length}家门店(排除中央厨房/仓库)`}
>
<FilterableTable
data={storeReconciliation}
@@ -207,39 +323,39 @@ export function DistributionReconciliationPage() {
searchPlaceholder="搜索门店编码/名称..."
sortOptions={[
{ key: 'dist_amt', label: '配送金额' },
{ key: 'dist_cost_excl_tax', label: '不含税成本' },
{ key: 'purchase_amt', label: '采购金额' },
{ key: 'opening_amt', label: '期初库存' },
{ key: 'consumption_amt', label: '实际耗用' },
{ key: 'ending_amt', label: '期末库存' },
{ key: 'reverse_consumption_amt', label: '倒挤应耗用' },
{ key: 'variance_amt', label: '差异金额' },
{ key: 'variance_pct', label: '差异率' },
{ key: 'neg_inventory_count', label: '负库存' },
{ key: 'neg_inventory_count', label: '退/盘盈记录' },
]}
columns={[
{ key: 'store_code', label: '门店编码' },
{ key: 'store_name', label: '门店名称', render: (s) => s.store_name || '-' },
{ key: 'is_unmatched', label: '状态', render: (s) => s.is_unmatched ? <span className="rounded bg-yellow-100 px-1.5 py-0.5 text-xs text-yellow-700"></span> : <span className="text-xs text-green-600"></span> },
{ key: 'dist_amt', label: '配送金额', align: 'right', render: (s) => formatCurrency(s.dist_amt) },
{ key: 'dist_cost_excl_tax', label: '不含税成本', align: 'right', render: (s) => formatCurrency(s.dist_cost_excl_tax) },
{ key: 'purchase_amt', label: '采购入库', align: 'right', render: (s) => formatCurrency(s.purchase_amt) },
{ key: 'variance_amt', label: '差异(配送-采购)', align: 'right', render: (s) => <span className={s.variance_amt > 0 ? 'text-red-600' : s.variance_amt < 0 ? 'text-green-600' : 'text-muted-foreground'}>{formatCurrency(s.variance_amt)}</span> },
{ key: 'variance_pct', label: '差异率', align: 'right', render: (s) => <span className={`font-medium ${varianceColorClass(s.variance_pct)}`}>{varianceText(s.variance_pct)}</span> },
{ key: 'opening_amt', label: '期初库存', align: 'right', render: (s) => formatCurrency(s.opening_amt) },
{ key: 'consumption_amt', label: '实际耗用', align: 'right', render: (s) => formatCurrency(s.consumption_amt) },
{ key: 'ending_amt', label: '期末库存', align: 'right', render: (s) => formatCurrency(s.ending_amt) },
{ key: 'reverse_consumption_amt', label: '倒挤应耗用', align: 'right', render: (s) => formatCurrency(s.reverse_consumption_amt) },
{ key: 'variance_amt', label: '差异金额', align: 'right', render: (s) => <span className={s.variance_amt >= 0 ? 'text-yellow-600' : 'text-red-600'}>{formatCurrency(s.variance_amt)}</span> },
{ key: 'variance_pct', label: '差异率', align: 'right', render: (s) => <span className={`font-medium ${varianceColorClass(s.variance_pct)}`}>{varianceText(s.variance_pct)}</span> },
{ key: 'neg_inventory_count', label: '负库存', align: 'right', render: (s) => <span className={s.neg_inventory_count > 0 ? 'text-red-600 font-medium' : ''}>{s.neg_inventory_count > 0 ? s.neg_inventory_count : '-'}</span> },
{ key: 'neg_inventory_count', label: '退/盘盈', align: 'right', render: (s) => <span className={s.neg_inventory_count > 0 ? 'text-orange-600 font-medium' : ''}>{s.neg_inventory_count > 0 ? s.neg_inventory_count : '-'}</span> },
]}
/>
</CollapsibleSection>
{/* Top差异品项 */}
<CollapsibleSection title="Top30差异品项" subtitle="按差异金额绝对值排序" defaultOpen={false}>
<CollapsibleSection title="Top30差异品项" subtitle="按差异金额绝对值排序(仅门店)" defaultOpen={false}>
<FilterableTable
data={topVariances}
filterKey="item_name"
filterLabel="全部品项"
sortOptions={[
{ key: 'dist_amt', label: '配送金额' },
{ key: 'purchase_amt', label: '采购金额' },
{ key: 'consumption_amt', label: '实际耗用' },
{ key: 'variance_amt', label: '差异金额' },
{ key: 'variance_pct', label: '差异率' },
@@ -251,36 +367,38 @@ export function DistributionReconciliationPage() {
{ key: 'minor_category', label: '品类' },
{ key: 'dist_qty', label: '配送量', align: 'right', render: (v) => formatNumber(v.dist_qty) },
{ key: 'dist_amt', label: '配送金额', align: 'right', render: (v) => formatCurrency(v.dist_amt) },
{ key: 'purchase_amt', label: '采购入库', align: 'right', render: (v) => formatCurrency(v.purchase_amt) },
{ key: 'variance_amt', label: '差异(配送-采购)', align: 'right', render: (v) => <span className={`font-medium ${v.variance_amt > 0 ? 'text-red-600' : v.variance_amt < 0 ? 'text-green-600' : 'text-muted-foreground'}`}>{formatCurrency(v.variance_amt)}</span> },
{ key: 'variance_pct', label: '差异率', align: 'right', render: (v) => <span className={varianceColorClass(v.variance_pct)}>{varianceText(v.variance_pct)}</span> },
{ key: 'opening_amt', label: '期初', align: 'right', render: (v) => formatCurrency(v.opening_amt) },
{ key: 'consumption_amt', label: '实际耗用', align: 'right', render: (v) => formatCurrency(v.consumption_amt) },
{ key: 'ending_amt', label: '期末', align: 'right', render: (v) => formatCurrency(v.ending_amt) },
{ key: 'reverse_consumption_amt', label: '倒挤应耗用', align: 'right', render: (v) => formatCurrency(v.reverse_consumption_amt) },
{ key: 'variance_amt', label: '差异金额', align: 'right', render: (v) => <span className={`font-medium ${v.variance_amt >= 0 ? 'text-yellow-600' : 'text-red-600'}`}>{formatCurrency(v.variance_amt)}</span> },
{ key: 'variance_pct', label: '差异率', align: 'right', render: (v) => <span className={varianceColorClass(v.variance_pct)}>{varianceText(v.variance_pct)}</span> },
]}
/>
</CollapsibleSection>
{/* 未匹配品项 */}
<CollapsibleSection title="未匹配品项(有配送无库存耗用)" subtitle="配送系统有发货但库存系统无耗用记录" defaultOpen={false}>
<FilterableTable
data={unmatchedItems}
filterKey="item_name"
filterLabel="全部品项"
sortOptions={[
{ key: 'dist_amt', label: '配送金额' },
{ key: 'dist_qty', label: '配送量' },
{ key: 'store_count', label: '涉及门店数' },
]}
columns={[
{ key: 'item_code', label: '品项编码' },
{ key: 'item_name', label: '品项名称' },
{ key: 'minor_category', label: '品类' },
{ key: 'dist_qty', label: '配送量', align: 'right', render: (u) => formatNumber(u.dist_qty) },
{ key: 'dist_amt', label: '配送金额', align: 'right', render: (u) => formatCurrency(u.dist_amt) },
{ key: 'store_count', label: '涉及门店数', align: 'right' },
]}
/>
<CollapsibleSection title="未匹配品项(有配送无库存耗用)" subtitle="配送系统有发货但库存系统无耗用记录,点击行展开查看配送门店明细" defaultOpen={false}>
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b text-left text-xs text-muted-foreground">
<th className="p-2"></th>
<th className="p-2"></th>
<th className="p-2"></th>
<th className="p-2"></th>
<th className="p-2 text-right"></th>
<th className="p-2 text-right"></th>
<th className="p-2 text-right"></th>
</tr>
</thead>
<tbody>
{unmatchedItems.map((u: any) => (
<UnmatchedItemRow key={u.item_code} item={u} month={month} expanded={expandedItem === u.item_code} onToggle={() => setExpandedItem(expandedItem === u.item_code ? null : u.item_code)} />
))}
</tbody>
</table>
</div>
<div className="mt-3 flex items-center gap-2 rounded-md bg-yellow-50 p-3 text-xs text-yellow-800">
<AlertTriangle className="h-4 w-4 flex-shrink-0" />
<span></span>
@@ -289,3 +407,78 @@ export function DistributionReconciliationPage() {
</div>
)
}
// 未匹配品项可展开行
function UnmatchedItemRow({ item, month, expanded, onToggle }: { item: any; month: string; expanded: boolean; onToggle: () => void }) {
const { data: details, isLoading, error } = useQuery({
queryKey: ['unmatched-item-details', month, item.item_code],
queryFn: async () => {
const res = await api.get(`/distribution/unmatched-item-details?month=${month}&item_code=${item.item_code}`)
return res.data
},
enabled: expanded,
})
return (
<>
<tr className="border-b cursor-pointer hover:bg-muted/30" onClick={onToggle}>
<td className="p-2 text-muted-foreground">
{expanded ? <ChevronDown className="h-4 w-4" /> : <ChevronRight className="h-4 w-4" />}
</td>
<td className="p-2">{item.item_code}</td>
<td className="p-2">{item.item_name}</td>
<td className="p-2">{item.minor_category}</td>
<td className="p-2 text-right">{formatNumber(item.dist_qty)}</td>
<td className="p-2 text-right">{formatCurrency(item.dist_amt)}</td>
<td className="p-2 text-right">{item.store_count}</td>
</tr>
{expanded && (
<tr>
<td colSpan={7} className="bg-muted/20 p-3">
{isLoading ? (
<div className="text-xs text-muted-foreground">...</div>
) : error ? (
<div className="text-xs text-red-600">: {String(error)}</div>
) : details && Array.isArray(details) && details.length > 0 ? (
<div>
<div className="mb-2 text-xs font-medium text-muted-foreground"></div>
<table className="w-full text-xs">
<thead>
<tr className="border-b text-left text-muted-foreground">
<th className="p-1.5"></th>
<th className="p-1.5"></th>
<th className="p-1.5 text-right"></th>
<th className="p-1.5 text-right"></th>
<th className="p-1.5 text-right"></th>
<th className="p-1.5 text-right"></th>
<th className="p-1.5 text-right"></th>
<th className="p-1.5"></th>
</tr>
</thead>
<tbody>
{details.map((d: any, idx: number) => (
<tr key={idx} className="border-b last:border-0">
<td className="p-1.5">{d.store_code}</td>
<td className="p-1.5">{d.store_name || '-'}</td>
<td className="p-1.5 text-right">{formatNumber(d.dist_qty)}</td>
<td className="p-1.5 text-right">{formatCurrency(d.dist_amt)}</td>
<td className="p-1.5 text-right">{formatCurrency(d.dist_cost_excl_tax)}</td>
<td className="p-1.5 text-right">{formatCurrency(d.purchase_amt)}</td>
<td className="p-1.5 text-right">{formatCurrency(d.consumption_amt)}</td>
<td className="p-1.5">
{d.has_inventory ? <span className="text-green-600"></span> : <span className="text-red-600"></span>}
</td>
</tr>
))}
</tbody>
</table>
</div>
) : (
<div className="text-xs text-muted-foreground"></div>
)}
</td>
</tr>
)}
</>
)
}
+565
View File
@@ -0,0 +1,565 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import api from '@/lib/api'
import { FilterableTable } from '@/components/FilterableTable'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { CollapsibleSection } from '@/components/CollapsibleSection'
import { MetricCard } from '@/components/MetricCard'
import { Tabs } from '@/components/Tabs'
import { formatCurrency, formatNumber, formatPercent } from '@/lib/utils'
import { useState } from 'react'
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts'
const GRADE_COLORS: Record<string, string> = { '战略': '#22c55e', '优选': '#3b82f6', '合格': '#eab308', '淘汰': '#ef4444' }
export function EnterprisePage() {
const [tab, setTab] = useState('supplier')
const queryClient = useQueryClient()
const { data: supplierData, isLoading: supplierLoading } = useQuery({
queryKey: ['enterprise/suppliers'],
queryFn: () => api.get('/enterprise/suppliers'),
enabled: tab === 'supplier',
})
const { data: poData, isLoading: poLoading } = useQuery({
queryKey: ['enterprise/purchase-orders'],
queryFn: () => api.get('/enterprise/purchase-orders'),
enabled: tab === 'supplier',
})
const { data: approvalData, isLoading: approvalLoading } = useQuery({
queryKey: ['enterprise/approvals'],
queryFn: () => api.get('/enterprise/approvals'),
enabled: tab === 'approval',
})
const { data: notificationData, isLoading: notifLoading } = useQuery({
queryKey: ['enterprise/notifications'],
queryFn: () => api.get('/enterprise/notifications'),
enabled: tab === 'notification',
})
const { data: talentData, isLoading: talentLoading } = useQuery({
queryKey: ['enterprise/hr/talent-matrix'],
queryFn: () => api.get('/enterprise/hr/talent-matrix'),
enabled: tab === 'hr',
})
const { data: courseData, isLoading: courseLoading } = useQuery({
queryKey: ['enterprise/training/courses'],
queryFn: () => api.get('/enterprise/training/courses'),
enabled: tab === 'lms',
})
const { data: recordData, isLoading: recordLoading } = useQuery({
queryKey: ['enterprise/training/records'],
queryFn: () => api.get('/enterprise/training/records'),
enabled: tab === 'lms',
})
const { data: campaignData, isLoading: campaignLoading } = useQuery({
queryKey: ['enterprise/campaigns'],
queryFn: () => api.get('/enterprise/campaigns'),
enabled: tab === 'marketing',
})
const { data: couponData, isLoading: couponLoading } = useQuery({
queryKey: ['enterprise/coupons'],
queryFn: () => api.get('/enterprise/coupons'),
enabled: tab === 'marketing',
})
const { data: budgetData, isLoading: budgetLoading } = useQuery({
queryKey: ['enterprise/budgets'],
queryFn: () => api.get('/enterprise/budgets'),
enabled: tab === 'finance',
})
const { data: loopData, isLoading: loopLoading } = useQuery({
queryKey: ['enterprise/loop-verification'],
queryFn: () => api.get('/enterprise/loop-verification'),
enabled: tab === 'loop',
})
const { data: auditData, isLoading: auditLoading } = useQuery({
queryKey: ['enterprise/audit-logs'],
queryFn: () => api.get('/enterprise/audit-logs'),
enabled: tab === 'audit',
})
const { data: benchmarkData, isLoading: benchmarkLoading } = useQuery({
queryKey: ['enterprise/supplier-benchmark'],
queryFn: () => api.get('/enterprise/supplier-benchmark'),
enabled: tab === 'benchmark',
})
const approveMutation = useMutation({
mutationFn: ({ id, result, comment }: { id: number; result: string; comment?: string }) =>
api.post(`/enterprise/approvals/${id}/approve`, { result, comment }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['enterprise/approvals'] }),
})
const readMutation = useMutation({
mutationFn: (id: number) => api.patch(`/enterprise/notifications/${id}/read`),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['enterprise/notifications'] }),
})
if ((tab === 'supplier' && supplierLoading) || (tab === 'approval' && approvalLoading) || (tab === 'notification' && notifLoading) || (tab === 'hr' && talentLoading) || (tab === 'lms' && courseLoading) || (tab === 'marketing' && campaignLoading) || (tab === 'finance' && budgetLoading) || (tab === 'loop' && loopLoading) || (tab === 'audit' && auditLoading) || (tab === 'benchmark' && benchmarkLoading)) {
return <LoadingSpinner text="加载企业协同数据..." />
}
const suppliers = (supplierData as any)?.data || []
const purchaseOrders = (poData as any)?.data || []
const approvals = (approvalData as any)?.data || []
const notifications = (notificationData as any)?.data || []
const talents = (talentData as any)?.data || []
const courses = (courseData as any)?.data || []
const records = (recordData as any)?.data || []
const campaigns = (campaignData as any)?.data || []
const coupons = (couponData as any)?.data || []
const budgets = (budgetData as any)?.data || []
const loops = (loopData as any)?.data || []
const auditLogs = (auditData as any)?.data || []
const benchmark = (benchmarkData as any)?.data || {}
const benchmarkSummary = benchmark.summary || {}
const benchmarks = benchmark.benchmarks || []
const gradeDist = suppliers.reduce((acc: Record<string, number>, r: any) => {
acc[r.grade] = (acc[r.grade] || 0) + 1
return acc
}, {})
const gradePieData = Object.entries(gradeDist).map(([name, value]) => ({ name, value }))
const quadrantDist = talents.reduce((acc: Record<string, number>, r: any) => {
acc[r.quadrant] = (acc[r.quadrant] || 0) + 1
return acc
}, {})
const pendingApprovals = approvals.filter((a: any) => a.status === 'pending').length
const unreadNotifications = notifications.filter((n: any) => !n.is_read).length
return (
<div className="space-y-4">
<div>
<h1 className="text-xl font-bold"></h1>
<p className="mt-0.5 text-xs text-muted-foreground"> · · · HR · · · · · </p>
</div>
<Tabs tabs={[
{ key: 'supplier', label: '供应链SRM' },
{ key: 'benchmark', label: '供应商对标' },
{ key: 'approval', label: '审批流' },
{ key: 'notification', label: '消息中心' },
{ key: 'hr', label: 'HR人才' },
{ key: 'lms', label: '培训LMS' },
{ key: 'marketing', label: '营销MA' },
{ key: 'finance', label: '财务ERP' },
{ key: 'loop', label: '闭环验证' },
{ key: 'audit', label: '审计日志' },
]} active={tab} onChange={setTab} />
{tab === 'supplier' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="供应商总数" value={suppliers.length} format="number" />
<MetricCard title="战略供应商" value={gradeDist['战略'] || 0} format="number" status="good" />
<MetricCard title="采购订单" value={purchaseOrders.length} format="number" />
<MetricCard title="淘汰供应商" value={gradeDist['淘汰'] || 0} format="number" status="bad" />
</div>
{gradePieData.length > 0 && (
<CollapsibleSection title="供应商分级分布">
<ResponsiveContainer width="100%" height={200}>
<PieChart>
<Pie data={gradePieData} cx="50%" cy="50%" outerRadius={60} dataKey="value"
labelLine={false} label={({ name, value }: any) => <tspan fontSize={11}>{`${name}: ${value}`}</tspan>}>
{gradePieData.map((e, i) => <Cell key={i} fill={GRADE_COLORS[e.name] || '#999'} />)}
</Pie>
<Tooltip />
<Legend />
</PieChart>
</ResponsiveContainer>
</CollapsibleSection>
)}
<CollapsibleSection title={`供应商列表 (${suppliers.length})`}>
<FilterableTable
data={suppliers}
filterKey="grade"
filterLabel="全部分级"
sortOptions={[{ key: 'overall_score', label: '综合分' }, { key: 'supplier_name', label: '名称' }]}
defaultSort="overall_score"
defaultOrder="desc"
columns={[
{ key: 'supplier_code', label: '编码' },
{ key: 'supplier_name', label: '名称' },
{ key: 'category', label: '品类' },
{ key: 'grade', label: '分级', align: 'center', render: (r) => {
const colors: Record<string, string> = { '战略': 'text-green-600', '优选': 'text-blue-600', '合格': 'text-yellow-600', '淘汰': 'text-red-600' }
return <span className={`font-bold ${colors[r.grade] || ''}`}>{r.grade}</span>
}},
{ key: 'overall_score', label: '综合分', align: 'right', render: (r) => r.overall_score ? Number(r.overall_score).toFixed(1) : '-' },
{ key: 'delivery_on_time_rate', label: '准时率', align: 'right', render: (r) => r.delivery_on_time_rate ? formatPercent(r.delivery_on_time_rate) : '-' },
{ key: 'contact_person', label: '联系人' },
]}
/>
</CollapsibleSection>
<CollapsibleSection title={`采购订单 (${purchaseOrders.length})`}>
<FilterableTable
data={purchaseOrders}
filterKey="status"
filterLabel="全部状态"
sortOptions={[{ key: 'created_at', label: '创建时间' }, { key: 'total_amount', label: '金额' }]}
defaultSort="created_at"
defaultOrder="desc"
columns={[
{ key: 'po_number', label: 'PO编号' },
{ key: 'supplier_code', label: '供应商' },
{ key: 'store_code', label: '门店' },
{ key: 'order_date', label: '下单日期', render: (r) => (r.order_date || '').toString().substring(0, 10) },
{ key: 'total_amount', label: '金额', align: 'right', render: (r) => formatCurrency(r.total_amount) },
{ key: 'status', label: '状态', align: 'center' },
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'benchmark' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="对标SKU数" value={benchmarkSummary.total_skus || 0} format="number" description="有多供应商报价的SKU" />
<MetricCard title="价格差异大" value={benchmarkSummary.high_variance || 0} format="number" description="价差>20%的SKU" status="bad" />
<MetricCard title="有优化空间" value={benchmarkSummary.optimizable || 0} format="number" description="价差10-20%的SKU" status="warn" />
<MetricCard title="潜在节约" value={benchmarkSummary.total_potential_savings || 0} format="currency" description="最高价-最低价之和" status="good" />
</div>
<CollapsibleSection title={`供应商价格对标 (${benchmarks.length})`} subtitle="同SKU跨供应商价格对比,识别最优供应商">
<FilterableTable
data={benchmarks}
filterKey="benchmark_status"
filterLabel="全部状态"
sortOptions={[
{ key: 'price_variance_pct', label: '价差%' },
{ key: 'potential_savings_per_unit', label: '潜在节约' },
{ key: 'avg_price', label: '均价' },
{ key: 'supplier_count', label: '供应商数' },
]}
defaultSort="price_variance_pct"
defaultOrder="desc"
columns={[
{ key: 'sku_code', label: 'SKU编码' },
{ key: 'sku_name', label: 'SKU名称' },
{ key: 'supplier_count', label: '供应商数', align: 'center', render: (r) => formatNumber(r.supplier_count) },
{ key: 'min_price', label: '最低价', align: 'right', render: (r) => <span className="text-green-600">{formatCurrency(r.min_price)}</span> },
{ key: 'max_price', label: '最高价', align: 'right', render: (r) => <span className="text-red-600">{formatCurrency(r.max_price)}</span> },
{ key: 'avg_price', label: '均价', align: 'right', render: (r) => formatCurrency(r.avg_price) },
{ key: 'price_variance_pct', label: '价差%', align: 'right', render: (r) => {
const v = Number(r.price_variance_pct || 0)
return <span className={v > 20 ? 'text-red-600 font-bold' : v > 10 ? 'text-yellow-600' : 'text-green-600'}>{v.toFixed(1)}%</span>
}},
{ key: 'best_supplier_name', label: '最优供应商' },
{ key: 'best_price', label: '最优价', align: 'right', render: (r) => <span className="text-green-600 font-medium">{formatCurrency(r.best_price)}</span> },
{ key: 'potential_savings_per_unit', label: '单件节约', align: 'right', render: (r) => formatCurrency(r.potential_savings_per_unit) },
{ key: 'benchmark_status', label: '状态', align: 'center', render: (r) => {
const colors: Record<string, string> = { '价格差异大': 'bg-red-500 text-white', '有优化空间': 'bg-yellow-500 text-white', '价格稳定': 'bg-green-500 text-white' }
return <span className={`rounded px-2 py-0.5 text-xs ${colors[r.benchmark_status] || ''}`}>{r.benchmark_status}</span>
}},
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'approval' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-3">
<MetricCard title="审批总数" value={approvals.length} format="number" />
<MetricCard title="待审批" value={pendingApprovals} format="number" status="warn" />
<MetricCard title="已审批" value={approvals.length - pendingApprovals} format="number" status="good" />
</div>
<CollapsibleSection title={`审批列表 (${approvals.length})`}>
<FilterableTable
data={approvals}
filterKey="status"
filterLabel="全部状态"
sortOptions={[{ key: 'created_at', label: '创建时间' }, { key: 'request_type', label: '类型' }]}
defaultSort="created_at"
defaultOrder="desc"
columns={[
{ key: 'request_type', label: '类型' },
{ key: 'applicant_name', label: '申请人' },
{ key: 'store_code', label: '门店' },
{ key: 'current_step', label: '当前步骤', align: 'center', render: (r) => `${r.current_step}/${r.total_steps}` },
{ key: 'status', label: '状态', align: 'center', render: (r) => {
const colors: Record<string, string> = { approved: 'text-green-600', pending: 'text-yellow-600', rejected: 'text-red-600' }
return <span className={`font-bold ${colors[r.status] || ''}`}>{r.status}</span>
}},
{ key: 'created_at', label: '创建时间', render: (r) => (r.created_at || '').substring(0, 19).replace('T', ' ') },
{ key: 'action', label: '操作', align: 'center', render: (r) => r.status === 'pending' ? (
<div className="flex gap-1">
<button onClick={() => approveMutation.mutate({ id: r.id, result: 'approved' })} className="rounded bg-green-600 px-2 py-0.5 text-xs text-white"></button>
<button onClick={() => approveMutation.mutate({ id: r.id, result: 'rejected' })} className="rounded bg-red-600 px-2 py-0.5 text-xs text-white"></button>
</div>
) : '-' },
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'notification' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-3">
<MetricCard title="消息总数" value={notifications.length} format="number" />
<MetricCard title="未读" value={unreadNotifications} format="number" status="warn" />
<MetricCard title="已读" value={notifications.length - unreadNotifications} format="number" status="good" />
</div>
<CollapsibleSection title={`消息列表 (${notifications.length})`}>
<FilterableTable
data={notifications}
filterKey="notification_type"
filterLabel="全部类型"
sortOptions={[{ key: 'created_at', label: '时间' }]}
defaultSort="created_at"
defaultOrder="desc"
columns={[
{ key: 'title', label: '标题', render: (r) => <span className={r.is_read ? '' : 'font-bold'}>{r.title}</span> },
{ key: 'notification_type', label: '类型', align: 'center' },
{ key: 'content', label: '内容' },
{ key: 'is_read', label: '状态', align: 'center', render: (r) => r.is_read ? '已读' : <span className="text-yellow-600 font-bold"></span> },
{ key: 'created_at', label: '时间', render: (r) => (r.created_at || '').substring(0, 19).replace('T', ' ') },
{ key: 'action', label: '操作', align: 'center', render: (r) => !r.is_read ? (
<button onClick={() => readMutation.mutate(r.id)} className="rounded bg-primary px-2 py-0.5 text-xs text-primary-foreground"></button>
) : '-' },
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'hr' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="人才总数" value={talents.length} format="number" />
<MetricCard title="明星员工" value={quadrantDist['star'] || 0} format="number" status="good" />
<MetricCard title="核心员工" value={quadrantDist['core'] || 0} format="number" />
<MetricCard title="潜力员工" value={quadrantDist['potential'] || 0} format="number" status="warn" />
</div>
<CollapsibleSection title="人才九宫格" subtitle="绩效×潜力">
<ResponsiveContainer width="100%" height={300}>
<BarChart data={Object.entries(quadrantDist).map(([k, v]) => ({ name: k, count: v }))} layout="vertical">
<CartesianGrid strokeDasharray="3 3" />
<XAxis type="number" />
<YAxis dataKey="name" type="category" />
<Tooltip />
<Bar dataKey="count" fill="#3b82f6" name="人数" />
</BarChart>
</ResponsiveContainer>
</CollapsibleSection>
<CollapsibleSection title={`人才列表 (${talents.length})`}>
<FilterableTable
data={talents}
filterKey="quadrant"
filterLabel="全部象限"
sortOptions={[{ key: 'performance_score', label: '绩效' }, { key: 'potential_score', label: '潜力' }]}
defaultSort="performance_score"
defaultOrder="desc"
columns={[
{ key: 'employee_name', label: '员工' },
{ key: 'store_name', label: '门店' },
{ key: 'performance_score', label: '绩效分', align: 'right', render: (r) => Number(r.performance_score || 0).toFixed(1) },
{ key: 'potential_score', label: '潜力分', align: 'right', render: (r) => Number(r.potential_score || 0).toFixed(1) },
{ key: 'quadrant', label: '象限', align: 'center', render: (r) => {
const labels: Record<string, string> = { star: '明星', core: '核心', potential: '潜力', ordinary: '普通' }
const colors: Record<string, string> = { star: 'text-green-600', core: 'text-blue-600', potential: 'text-yellow-600', ordinary: 'text-gray-600' }
return <span className={`font-bold ${colors[r.quadrant] || ''}`}>{labels[r.quadrant] || r.quadrant}</span>
}},
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'lms' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="课程总数" value={courses.length} format="number" />
<MetricCard title="学习记录" value={records.length} format="number" />
<MetricCard title="已完成" value={records.filter((r: any) => r.completion_status === '已完成').length} format="number" status="good" />
<MetricCard title="未完成" value={records.filter((r: any) => r.completion_status !== '已完成').length} format="number" status="warn" />
</div>
<CollapsibleSection title={`课程列表 (${courses.length})`}>
<FilterableTable
data={courses}
filterKey="course_type"
filterLabel="全部类型"
sortOptions={[{ key: 'course_name', label: '课程名' }, { key: 'created_at', label: '创建时间' }]}
defaultSort="created_at"
defaultOrder="desc"
columns={[
{ key: 'course_name', label: '课程名称' },
{ key: 'course_type', label: '类型', align: 'center' },
{ key: 'exam_enabled', label: '考试', align: 'center', render: (r) => r.exam_enabled ? '是' : '否' },
{ key: 'pass_score', label: '及格分', align: 'right' },
{ key: 'created_at', label: '创建时间', render: (r) => (r.created_at || '').substring(0, 10) },
]}
/>
</CollapsibleSection>
<CollapsibleSection title={`学习记录 (${records.length})`}>
<FilterableTable
data={records}
filterKey="completion_status"
filterLabel="全部状态"
sortOptions={[{ key: 'employee_name', label: '员工' }, { key: 'progress_pct', label: '进度' }]}
defaultSort="progress_pct"
defaultOrder="desc"
columns={[
{ key: 'employee_name', label: '员工' },
{ key: 'store_code', label: '门店' },
{ key: 'progress_pct', label: '进度', align: 'right', render: (r) => formatPercent(r.progress_pct || 0) },
{ key: 'completion_status', label: '状态', align: 'center', render: (r) => {
const colors: Record<string, string> = { '已完成': 'text-green-600', '进行中': 'text-blue-600', '未开始': 'text-gray-600', '未通过': 'text-red-600' }
return <span className={colors[r.completion_status] || ''}>{r.completion_status}</span>
}},
{ key: 'exam_score', label: '考试成绩', align: 'right', render: (r) => r.exam_score ?? '-' },
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'marketing' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="活动总数" value={campaigns.length} format="number" />
<MetricCard title="进行中" value={campaigns.filter((c: any) => c.status === 'active').length} format="number" status="good" />
<MetricCard title="券码总数" value={coupons.length} format="number" />
<MetricCard title="已核销" value={coupons.filter((c: any) => c.status === 'used').length} format="number" />
</div>
<CollapsibleSection title={`营销活动 (${campaigns.length})`}>
<FilterableTable
data={campaigns}
filterKey="status"
filterLabel="全部状态"
sortOptions={[{ key: 'created_at', label: '创建时间' }, { key: 'budget', label: '预算' }]}
defaultSort="created_at"
defaultOrder="desc"
columns={[
{ key: 'campaign_name', label: '活动名称' },
{ key: 'campaign_type', label: '类型' },
{ key: 'start_date', label: '开始', render: (r) => (r.start_date || '').substring(0, 10) },
{ key: 'end_date', label: '结束', render: (r) => (r.end_date || '').substring(0, 10) },
{ key: 'budget', label: '预算', align: 'right', render: (r) => formatCurrency(r.budget) },
{ key: 'roi', label: 'ROI', align: 'right', render: (r) => r.roi ? `${Number(r.roi).toFixed(2)}x` : '-' },
{ key: 'status', label: '状态', align: 'center' },
]}
/>
</CollapsibleSection>
<CollapsibleSection title={`券码管理 (${coupons.length})`}>
<FilterableTable
data={coupons}
filterKey="status"
filterLabel="全部状态"
sortOptions={[{ key: 'created_at', label: '创建时间' }, { key: 'face_value', label: '面值' }]}
defaultSort="created_at"
defaultOrder="desc"
columns={[
{ key: 'coupon_code', label: '券码' },
{ key: 'coupon_type', label: '类型' },
{ key: 'face_value', label: '面值', align: 'right', render: (r) => formatCurrency(r.face_value) },
{ key: 'min_spend', label: '门槛', align: 'right', render: (r) => formatCurrency(r.min_spend) },
{ key: 'expiry_date', label: '过期日期', render: (r) => (r.expiry_date || '').substring(0, 10) },
{ key: 'status', label: '状态', align: 'center', render: (r) => {
const colors: Record<string, string> = { unused: 'text-blue-600', used: 'text-green-600', expired: 'text-gray-600', refunded: 'text-red-600' }
return <span className={colors[r.status] || ''}>{r.status}</span>
}},
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'finance' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-3">
<MetricCard title="预算总数" value={budgets.length} format="number" />
<MetricCard title="总预算" value={budgets.reduce((s: number, b: any) => s + Number(b.budget_amount || 0), 0)} format="currency" />
<MetricCard title="总实际" value={budgets.reduce((s: number, b: any) => s + Number(b.actual_amount || 0), 0)} format="currency" />
</div>
<CollapsibleSection title={`预算管理 (${budgets.length})`}>
<FilterableTable
data={budgets}
filterKey="budget_type"
filterLabel="全部类型"
sortOptions={[{ key: 'month', label: '月份' }, { key: 'budget_amount', label: '预算' }, { key: 'execution_rate', label: '执行率' }]}
defaultSort="month"
defaultOrder="desc"
columns={[
{ key: 'year', label: '年度', align: 'center' },
{ key: 'month', label: '月份', render: (r) => r.month ? (r.month as string).substring(0, 10) : '-' },
{ key: 'store_code', label: '门店' },
{ key: 'department', label: '部门' },
{ key: 'budget_type', label: '类型', align: 'center' },
{ key: 'budget_amount', label: '预算', align: 'right', render: (r) => formatCurrency(r.budget_amount) },
{ key: 'actual_amount', label: '实际', align: 'right', render: (r) => formatCurrency(r.actual_amount) },
{ key: 'execution_rate', label: '执行率', align: 'right', render: (r) => formatPercent(r.execution_rate || 0) },
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'loop' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-3">
<MetricCard title="验证总数" value={loops.length} format="number" />
<MetricCard title="已完成" value={loops.filter((l: any) => l.status === 'completed').length} format="number" status="good" />
<MetricCard title="需升级" value={loops.filter((l: any) => l.status === 'escalated').length} format="number" status="bad" />
</div>
<CollapsibleSection title={`闭环验证 (${loops.length})`}>
<FilterableTable
data={loops}
filterKey="status"
filterLabel="全部状态"
sortOptions={[{ key: 'check_date', label: '检查日期' }, { key: 'completion_rate', label: '完成率' }]}
defaultSort="check_date"
defaultOrder="desc"
columns={[
{ key: 'loop_name', label: '闭环名称' },
{ key: 'store_code', label: '门店' },
{ key: 'check_date', label: '检查日期', render: (r) => (r.check_date || '').substring(0, 10) },
{ key: 'status', label: '状态', align: 'center', render: (r) => {
const colors: Record<string, string> = { completed: 'text-green-600', open: 'text-yellow-600', escalated: 'text-red-600' }
return <span className={`font-bold ${colors[r.status] || ''}`}>{r.status}</span>
}},
{ key: 'completion_rate', label: '完成率', align: 'right', render: (r) => formatPercent(r.completion_rate || 0) },
{ key: 'cycle_days', label: '周期(天)', align: 'right' },
{ key: 'bottleneck', label: '瓶颈环节' },
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'audit' && (
<CollapsibleSection title={`审计日志 (${auditLogs.length})`}>
<FilterableTable
data={auditLogs}
filterKey="action"
filterLabel="全部操作"
sortOptions={[{ key: 'created_at', label: '时间' }, { key: 'user_name', label: '用户' }]}
defaultSort="created_at"
defaultOrder="desc"
columns={[
{ key: 'user_name', label: '用户' },
{ key: 'user_role', label: '角色' },
{ key: 'action', label: '操作', align: 'center' },
{ key: 'resource_type', label: '资源类型' },
{ key: 'resource_id', label: '资源ID' },
{ key: 'created_at', label: '时间', render: (r) => (r.created_at || '').substring(0, 19).replace('T', ' ') },
]}
/>
</CollapsibleSection>
)}
</div>
)
}
+243
View File
@@ -0,0 +1,243 @@
import { useQuery } from '@tanstack/react-query'
import api from '@/lib/api'
import { FilterableTable } from '@/components/FilterableTable'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { CollapsibleSection } from '@/components/CollapsibleSection'
import { MetricCard } from '@/components/MetricCard'
import { Tabs } from '@/components/Tabs'
import { formatCurrency, formatNumber, formatPercent } from '@/lib/utils'
import { useState } from 'react'
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, LineChart, Line } from 'recharts'
export function IntelligencePage() {
const [tab, setTab] = useState('iot')
const { data: deviceData, isLoading: deviceLoading } = useQuery({
queryKey: ['intelligence/iot/devices'],
queryFn: () => api.get('/intelligence/iot/devices'),
enabled: tab === 'iot',
})
const { data: forecastData, isLoading: forecastLoading } = useQuery({
queryKey: ['intelligence/ai/forecasts'],
queryFn: () => api.get('/intelligence/ai/forecasts'),
enabled: tab === 'ai',
})
const { data: roiData, isLoading: roiLoading } = useQuery({
queryKey: ['intelligence/strategy/roi'],
queryFn: () => api.get('/intelligence/strategy/roi'),
enabled: tab === 'strategy',
})
const { data: brandData, isLoading: brandLoading } = useQuery({
queryKey: ['intelligence/strategy/brand-assets'],
queryFn: () => api.get('/intelligence/strategy/brand-assets'),
enabled: tab === 'strategy',
})
const { data: realtimeData, isLoading: realtimeLoading } = useQuery({
queryKey: ['intelligence/realtime/dashboard'],
queryFn: () => api.get('/intelligence/realtime/dashboard'),
enabled: tab === 'realtime',
})
if ((tab === 'iot' && deviceLoading) || (tab === 'ai' && forecastLoading) || (tab === 'strategy' && roiLoading) || (tab === 'realtime' && realtimeLoading)) {
return <LoadingSpinner text="加载智能升级数据..." />
}
const devices = (deviceData as any)?.data || []
const forecasts = (forecastData as any)?.data || []
const rois = (roiData as any)?.data || []
const brands = (brandData as any)?.data || []
const realtime = (realtimeData as any)?.data || []
const onlineDevices = devices.filter((d: any) => d.status === 'online').length
const alarmDevices = devices.filter((d: any) => d.status === 'alarm').length
return (
<div className="space-y-4">
<div>
<h1 className="text-xl font-bold"></h1>
<p className="mt-0.5 text-xs text-muted-foreground">IoT设备 · AI预测 · · </p>
</div>
<Tabs tabs={[
{ key: 'iot', label: 'IoT设备' },
{ key: 'ai', label: 'AI预测' },
{ key: 'realtime', label: '实时看板' },
{ key: 'strategy', label: '战略驾驶舱' },
]} active={tab} onChange={setTab} />
{tab === 'iot' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="设备总数" value={devices.length} format="number" />
<MetricCard title="在线" value={onlineDevices} format="number" status="good" />
<MetricCard title="告警" value={alarmDevices} format="number" status="bad" />
<MetricCard title="离线" value={devices.length - onlineDevices - alarmDevices} format="number" status="warn" />
</div>
<CollapsibleSection title={`IoT设备列表 (${devices.length})`}>
<FilterableTable
data={devices}
filterKey="device_type"
filterLabel="全部类型"
sortOptions={[{ key: 'device_code', label: '编码' }, { key: 'updated_at', label: '更新时间' }]}
defaultSort="updated_at"
defaultOrder="desc"
columns={[
{ key: 'device_code', label: '设备编码' },
{ key: 'device_name', label: '设备名称' },
{ key: 'device_type', label: '类型' },
{ key: 'store_code', label: '门店' },
{ key: 'location', label: '位置' },
{ key: 'status', label: '状态', align: 'center', render: (r) => {
const colors: Record<string, string> = { online: 'text-green-600', offline: 'text-gray-600', alarm: 'text-red-600' }
return <span className={`font-bold ${colors[r.status] || ''}`}>{r.status}</span>
}},
{ key: 'last_reading_at', label: '最后读数', render: (r) => r.last_reading_at ? (r.last_reading_at as string).substring(0, 19).replace('T', ' ') : '-' },
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'ai' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-3">
<MetricCard title="预测总数" value={forecasts.length} format="number" />
<MetricCard title="预测类型" value={new Set(forecasts.map((f: any) => f.forecast_type)).size} format="number" />
<MetricCard title="模型数" value={new Set(forecasts.map((f: any) => f.model_type)).size} format="number" />
</div>
{forecasts.length > 0 && (
<CollapsibleSection title="预测趋势" subtitle="按目标日期">
<ResponsiveContainer width="100%" height={300}>
<LineChart data={forecasts.slice(0, 30).reverse().map((f: any) => ({
date: (f.target_date || '').substring(0, 10),
predicted: Number(f.predicted_value || 0),
lower: Number(f.confidence_lower || 0),
upper: Number(f.confidence_upper || 0),
}))}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" fontSize={10} />
<YAxis />
<Tooltip />
<Legend />
<Line type="monotone" dataKey="predicted" stroke="#3b82f6" name="预测值" />
<Line type="monotone" dataKey="lower" stroke="#94a3b8" name="下界" strokeDasharray="5 5" />
<Line type="monotone" dataKey="upper" stroke="#94a3b8" name="上界" strokeDasharray="5 5" />
</LineChart>
</ResponsiveContainer>
</CollapsibleSection>
)}
<CollapsibleSection title={`预测列表 (${forecasts.length})`}>
<FilterableTable
data={forecasts}
filterKey="forecast_type"
filterLabel="全部类型"
sortOptions={[{ key: 'target_date', label: '目标日期' }, { key: 'predicted_value', label: '预测值' }]}
defaultSort="target_date"
defaultOrder="desc"
columns={[
{ key: 'forecast_type', label: '类型' },
{ key: 'target_date', label: '目标日期', render: (r) => (r.target_date || '').substring(0, 10) },
{ key: 'store_code', label: '门店' },
{ key: 'predicted_value', label: '预测值', align: 'right', render: (r) => formatNumber(r.predicted_value) },
{ key: 'confidence_lower', label: '下界', align: 'right', render: (r) => formatNumber(r.confidence_lower) },
{ key: 'confidence_upper', label: '上界', align: 'right', render: (r) => formatNumber(r.confidence_upper) },
{ key: 'model_type', label: '模型', align: 'center' },
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'realtime' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-3">
<MetricCard title="今日门店数" value={realtime.length} format="number" />
<MetricCard title="今日总营收" value={realtime.reduce((s: number, r: any) => s + Number(r.today_revenue || 0), 0)} format="currency" />
<MetricCard title="今日总单数" value={realtime.reduce((s: number, r: any) => s + Number(r.bill_count || 0), 0)} format="number" />
</div>
{realtime.length > 0 && (
<CollapsibleSection title="今日营收排行" subtitle="实时数据">
<ResponsiveContainer width="100%" height={300}>
<BarChart data={realtime.slice(0, 20).map((r: any) => ({
store: r.store_code,
revenue: Number(r.today_revenue || 0),
}))}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="store" fontSize={10} />
<YAxis />
<Tooltip formatter={(v: any) => [formatCurrency(v), '营收']} />
<Bar dataKey="revenue" fill="#3b82f6" name="今日营收" />
</BarChart>
</ResponsiveContainer>
</CollapsibleSection>
)}
<CollapsibleSection title={`实时看板 (${realtime.length})`}>
<FilterableTable
data={realtime}
sortOptions={[{ key: 'today_revenue', label: '今日营收' }, { key: 'bill_count', label: '单数' }]}
defaultSort="today_revenue"
defaultOrder="desc"
columns={[
{ key: 'store_code', label: '门店' },
{ key: 'today_revenue', label: '今日营收', align: 'right', render: (r) => formatCurrency(r.today_revenue) },
{ key: 'bill_count', label: '单数', align: 'right', render: (r) => formatNumber(r.bill_count) },
{ key: 'avg_transaction', label: '客单价', align: 'right', render: (r) => formatCurrency(r.avg_transaction) },
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'strategy' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="门店ROI数" value={rois.length} format="number" />
<MetricCard title="平均回本月数" value={rois.length > 0 ? rois.reduce((s: number, r: any) => s + Number(r.payback_months || 0), 0) / rois.length : 0} format="number" />
<MetricCard title="品牌追踪天数" value={brands.length} format="number" />
<MetricCard title="最新NPS" value={brands[0]?.nps_score || 0} format="number" status={(brands[0]?.nps_score || 0) >= 50 ? 'good' : 'warn'} />
</div>
{brands.length > 0 && (
<CollapsibleSection title="品牌资产趋势" subtitle="NPS + 搜索指数">
<ResponsiveContainer width="100%" height={250}>
<LineChart data={brands.slice(0, 30).reverse().map((b: any) => ({
date: (b.tracking_date || '').substring(0, 10),
nps: Number(b.nps_score || 0),
search: Number(b.search_index || 0),
}))}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" fontSize={10} />
<YAxis />
<Tooltip />
<Legend />
<Line type="monotone" dataKey="nps" stroke="#22c55e" name="NPS" />
<Line type="monotone" dataKey="search" stroke="#3b82f6" name="搜索指数" />
</LineChart>
</ResponsiveContainer>
</CollapsibleSection>
)}
<CollapsibleSection title={`门店ROI (${rois.length})`}>
<FilterableTable
data={rois}
sortOptions={[{ key: 'payback_months', label: '回本月数' }, { key: 'roi_pct', label: 'ROI' }, { key: 'store_name', label: '门店' }]}
defaultSort="payback_months"
defaultOrder="asc"
columns={[
{ key: 'store_code', label: '门店编码' },
{ key: 'store_name', label: '门店名称' },
{ key: 'initial_investment', label: '初始投资', align: 'right', render: (r) => formatCurrency(r.initial_investment) },
{ key: 'monthly_revenue', label: '月营收', align: 'right', render: (r) => formatCurrency(r.monthly_revenue) },
{ key: 'monthly_profit', label: '月利润', align: 'right', render: (r) => formatCurrency(r.monthly_profit) },
{ key: 'payback_months', label: '回本月数', align: 'right', render: (r) => r.payback_months ? `${Number(r.payback_months).toFixed(1)}` : '-' },
{ key: 'roi_pct', label: 'ROI', align: 'right', render: (r) => formatPercent(r.roi_pct) },
]}
/>
</CollapsibleSection>
</>
)}
</div>
)
}
+159 -7
View File
@@ -5,20 +5,35 @@ import { FilterableTable } from '@/components/FilterableTable'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { CollapsibleSection } from '@/components/CollapsibleSection'
import { MetricCard } from '@/components/MetricCard'
import { formatCurrency, formatNumber } from '@/lib/utils'
import { Tabs } from '@/components/Tabs'
import { Pagination } from '@/components/Pagination'
import { formatCurrency, formatNumber, formatPercent } from '@/lib/utils'
import { MonthPicker } from '@/components/MonthPicker'
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts'
const URGENCY_COLORS: Record<string, string> = { '紧急': '#ef4444', '预警': '#eab308', '关注': '#3b82f6', '正常': '#22c55e' }
const PAGE_SIZE = 50
export function InventoryTurnoverPage() {
const [month, setMonth] = useState('2026-04')
const [tab, setTab] = useState('turnover')
const [expiryPage, setExpiryPage] = useState(1)
const [urgencyFilter, setUrgencyFilter] = useState('')
const { data, isLoading } = useQuery({
queryKey: ['analytics-enhanced/inventory/turnover', month],
queryFn: () => api.get('/analytics-enhanced/inventory/turnover', { params: { month } }),
enabled: tab === 'turnover',
})
if (isLoading) {
return <LoadingSpinner text="加载库存周转数据..." />
const { data: expiryData, isLoading: expiryLoading } = useQuery({
queryKey: ['analytics-enhanced/inventory/near-expiry', month, expiryPage, urgencyFilter],
queryFn: () => api.get('/analytics-enhanced/inventory/near-expiry', { params: { month, page: expiryPage, page_size: PAGE_SIZE, urgency_level: urgencyFilter } }),
enabled: tab === 'expiry',
})
if ((tab === 'turnover' && isLoading) || (tab === 'expiry' && expiryLoading)) {
return <LoadingSpinner text="加载库存数据..." />
}
const turnover = (data as any)?.data?.turnover || []
@@ -29,7 +44,7 @@ export function InventoryTurnoverPage() {
const totalWaste = turnover.reduce((s: number, r: any) => s + Number(r.waste_value || 0), 0)
const totalEnding = turnover.reduce((s: number, r: any) => s + Number(r.ending_value || 0), 0)
const avgTurnoverDays = turnover.length > 0
? turnover.reduce((s: number, r: any) => s + Number(r.turnover_days || 0), 0) / turnover.length
? turnover.reduce((s: number, r: any) => s + Number(r.turnover_days || 0), 0) / turnover.filter((r: any) => r.turnover_days != null).length || 0
: 0
const turnoverChartData = turnover.slice(0, 15).map((r: any) => ({
@@ -43,16 +58,150 @@ export function InventoryTurnoverPage() {
损耗金额: Number(r.waste_value || 0),
}))
const expiry = (expiryData as any)?.data || {}
const nearExpiry = expiry.near_expiry || []
const storeRisk = expiry.store_risk || []
const expirySummary = expiry.summary || {}
const pagination = expiry.pagination || {}
const urgencyPieData = [
{ name: '紧急', value: expirySummary.urgent || 0 },
{ name: '预警', value: expirySummary.warning || 0 },
{ name: '关注', value: expirySummary.watch || 0 },
].filter(d => d.value > 0)
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<h1 className="text-xl font-bold"></h1>
<p className="mt-0.5 text-xs text-muted-foreground"> · TOP · · {month}</p>
<p className="mt-0.5 text-xs text-muted-foreground"> · TOP · · {month}</p>
</div>
<MonthPicker month={month} onChange={setMonth} />
</div>
<Tabs tabs={[
{ key: 'turnover', label: '库存周转' },
{ key: 'expiry', label: '临期预警' },
]} active={tab} onChange={setTab} />
{tab === 'expiry' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="临期商品数" value={expirySummary.total_items || 0} format="number" description="有库存的商品总数" />
<MetricCard title="紧急(≤3天)" value={expirySummary.urgent || 0} format="number" description="预计3天内消耗完" status="bad" />
<MetricCard title="预警(≤7天)" value={expirySummary.warning || 0} format="number" description="预计7天内消耗完" status="warn" />
<MetricCard title="潜在损失" value={expirySummary.potential_loss || 0} format="currency" description="紧急+预警商品50%估值" status="bad" />
</div>
{urgencyPieData.length > 0 && (
<CollapsibleSection title="临期紧急度分布" subtitle="按预计消耗天数分类">
<ResponsiveContainer width="100%" height={200}>
<PieChart>
<Pie data={urgencyPieData} cx="50%" cy="50%" outerRadius={60} dataKey="value"
labelLine={false} label={({ name, value }: any) => <tspan fontSize={11}>{`${name}: ${value}`}</tspan>}>
{urgencyPieData.map((e, i) => <Cell key={i} fill={URGENCY_COLORS[e.name] || '#999'} />)}
</Pie>
<Tooltip formatter={(v: any) => [formatNumber(v), '商品数']} />
<Legend />
</PieChart>
</ResponsiveContainer>
</CollapsibleSection>
)}
<CollapsibleSection title={`门店临期风险 (${storeRisk.length})`} subtitle="按临期风险金额排序">
<FilterableTable
data={storeRisk}
filterKey="store_name"
filterLabel="全部门店"
sortOptions={[
{ key: 'at_risk_value', label: '风险金额' },
{ key: 'urgent_items', label: '紧急数' },
{ key: 'warning_items', label: '预警数' },
{ key: 'total_waste', label: '损耗金额' },
]}
defaultSort="at_risk_value"
defaultOrder="desc"
columns={[
{ key: 'store_name', label: '门店名称' },
{ key: 'urgent_items', label: '紧急(≤3天)', align: 'right', render: (r) => {
const v = Number(r.urgent_items || 0)
return <span className={v > 0 ? 'text-red-600 font-bold' : ''}>{formatNumber(v)}</span>
}},
{ key: 'warning_items', label: '预警(≤7天)', align: 'right', render: (r) => {
const v = Number(r.warning_items || 0)
return <span className={v > 0 ? 'text-yellow-600 font-medium' : ''}>{formatNumber(v)}</span>
}},
{ key: 'at_risk_value', label: '风险金额', align: 'right', render: (r) => <span className="text-red-600">{formatCurrency(r.at_risk_value)}</span> },
{ key: 'total_waste', label: '当月损耗', align: 'right', render: (r) => formatCurrency(r.total_waste) },
]}
/>
</CollapsibleSection>
<CollapsibleSection title={`临期商品明细 (${pagination.total || 0})`} subtitle="按紧急度排序,含处置建议">
<div className="mb-3 flex items-center gap-2">
<span className="text-xs text-muted-foreground"></span>
{['', '紧急', '预警', '关注'].map(level => (
<button
key={level}
onClick={() => { setUrgencyFilter(level); setExpiryPage(1) }}
className={`rounded px-2 py-0.5 text-xs ${
urgencyFilter === level
? 'bg-primary text-primary-foreground'
: level === '紧急' ? 'bg-red-100 text-red-700 hover:bg-red-200'
: level === '预警' ? 'bg-yellow-100 text-yellow-700 hover:bg-yellow-200'
: level === '关注' ? 'bg-blue-100 text-blue-700 hover:bg-blue-200'
: 'bg-muted hover:bg-muted/80'
}`}
>
{level || '全部'}
</button>
))}
</div>
<FilterableTable
data={nearExpiry}
searchKeys={['store_name', 'material_name', 'minor_category']}
searchPlaceholder="搜索门店/物料/品类..."
sortOptions={[
{ key: 'estimated_days_to_consume', label: '预计天数' },
{ key: 'stock_value', label: '库存金额' },
{ key: 'store_name', label: '门店' },
]}
defaultSort="estimated_days_to_consume"
defaultOrder="asc"
columns={[
{ key: 'store_name', label: '门店' },
{ key: 'material_name', label: '物料名称' },
{ key: 'minor_category', label: '品类' },
{ key: 'stock_qty', label: '库存量', align: 'right', render: (r) => formatNumber(r.stock_qty) },
{ key: 'stock_value', label: '库存金额', align: 'right', render: (r) => formatCurrency(r.stock_value) },
{ key: 'estimated_days_to_consume', label: '预计天数', align: 'right', render: (r) => {
const v = Number(r.estimated_days_to_consume || 0)
return v ? <span className={v <= 3 ? 'text-red-600 font-bold' : v <= 7 ? 'text-yellow-600' : v <= 14 ? 'text-blue-600' : ''}>{v.toFixed(1)}</span> : '-'
}},
{ key: 'urgency_level', label: '紧急度', align: 'center', render: (r) => {
const colors: Record<string, string> = { '紧急': 'bg-red-500 text-white', '预警': 'bg-yellow-500 text-white', '关注': 'bg-blue-500 text-white', '正常': 'bg-green-500 text-white' }
return <span className={`rounded px-2 py-0.5 text-xs ${colors[r.urgency_level] || ''}`}>{r.urgency_level}</span>
}},
{ key: 'suggested_action', label: '建议措施' },
]}
/>
{pagination.total_pages > 1 && (
<div className="mt-3">
<Pagination
page={expiryPage}
pageSize={PAGE_SIZE}
total={pagination.total || 0}
onPageChange={setExpiryPage}
/>
</div>
)}
</CollapsibleSection>
</>
)}
{tab === 'turnover' && (
<>
{/* 概览指标 */}
<CollapsibleSection title="库存总览" subtitle="全门店库存汇总">
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
@@ -126,7 +275,8 @@ export function InventoryTurnoverPage() {
return <span className={v > 1000 ? 'text-red-600 font-medium' : ''}>{formatCurrency(v)}</span>
}},
{ key: 'turnover_days', label: '周转天数', align: 'right', render: (r) => {
const v = Number(r.turnover_days || 0)
if (r.turnover_days == null) return <span className="text-muted-foreground text-xs"></span>
const v = Number(r.turnover_days)
return <span className={v <= 7 ? 'text-green-600' : v <= 14 ? 'text-yellow-600' : 'text-red-600'}>{v.toFixed(1)}</span>
}},
]}
@@ -154,6 +304,8 @@ export function InventoryTurnoverPage() {
]}
/>
</CollapsibleSection>
</>
)}
</div>
)
}
+268
View File
@@ -0,0 +1,268 @@
/**
* 知识资产页面
*
* 展示标杆实践(standardized_practice)列表,支持按模块和状态筛选,
* 点击可查看推广结果,支持推广到指定门店。
*/
import { useState, useMemo } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { Library, X } from 'lucide-react'
import api from '@/lib/api'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { KnowledgeCard } from '@/components/KnowledgeCard'
import { Badge } from '@/components/Badge'
import { cn } from '@/lib/utils'
export function KnowledgePage() {
const queryClient = useQueryClient()
const [moduleFilter, setModuleFilter] = useState('')
const [statusFilter, setStatusFilter] = useState('')
const [selected, setSelected] = useState<any | null>(null)
// 获取标杆实践列表
const { data: practicesData, isLoading } = useQuery({
queryKey: ['tasks/practices', moduleFilter, statusFilter],
queryFn: () =>
api.get('/tasks/practices', {
params: { module: moduleFilter || undefined, status: statusFilter || undefined },
}),
})
const practices = (practicesData as any)?.data || []
// 获取选中实践的推广结果
const { data: replicationData } = useQuery({
queryKey: ['tasks/practices', selected?.id, 'replication-result'],
queryFn: () => api.get(`/tasks/practices/${selected?.id}/replication-result`),
enabled: !!selected?.id,
})
const replications = (replicationData as any)?.data || []
// 推广操作
const replicateMutation = useMutation({
mutationFn: (data: { trial_store_code: string; trial_store_name: string; observation_weeks?: number }) =>
api.post(`/tasks/practices/${selected?.id}/replicate`, data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['tasks/practices', selected?.id, 'replication-result'] })
},
})
const promoteMutation = useMutation({
mutationFn: () => api.post(`/tasks/practices/${selected?.id}/promote`),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['tasks/practices'] })
setSelected(null)
},
})
// 统计
const stats = useMemo(() => {
const total = practices.length
const byModule = practices.reduce((acc: any, p: any) => {
acc[p.practice_module] = (acc[p.practice_module] || 0) + 1
return acc
}, {})
const byStatus = practices.reduce((acc: any, p: any) => {
acc[p.status] = (acc[p.status] || 0) + 1
return acc
}, {})
return { total, byModule, byStatus }
}, [practices])
// 模块列表(从数据中提取)
const modules = useMemo(
() => Array.from(new Set(practices.map((p: any) => p.practice_module))).filter(Boolean),
[practices],
)
const statuses = ['待推广', '推广中', '已推广']
return (
<div className="space-y-4">
{/* 页面标题 */}
<div>
<h1 className="flex items-center gap-2 text-xl font-bold">
<Library className="h-5 w-5 text-teal-600" />
</h1>
<p className="mt-1 text-sm text-muted-foreground">
AI
</p>
</div>
{/* 统计卡片 */}
<div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
<div className="rounded-lg border bg-card p-3">
<div className="flex items-center gap-2">
<Library className="h-4 w-4 text-teal-600" />
<span className="text-xs text-muted-foreground"></span>
</div>
<b className="mt-1 block text-2xl font-bold text-teal-600">{stats.total}</b>
</div>
{Object.entries(stats.byStatus).map(([status, count]: any) => (
<div key={status} className="rounded-lg border bg-card p-3">
<span className="text-xs text-muted-foreground">{status}</span>
<b className="mt-1 block text-2xl font-bold">{count}</b>
</div>
))}
</div>
{/* 筛选栏 */}
<div className="flex flex-wrap gap-2">
<button
className={cn(
'rounded-md px-3 py-1.5 text-sm font-medium',
!moduleFilter ? 'bg-teal-600 text-white' : 'border hover:bg-muted',
)}
onClick={() => setModuleFilter('')}
>
</button>
{modules.map((m: any) => (
<button
key={m}
className={cn(
'rounded-md px-3 py-1.5 text-sm font-medium',
moduleFilter === m ? 'bg-teal-600 text-white' : 'border hover:bg-muted',
)}
onClick={() => setModuleFilter(m)}
>
{m}
</button>
))}
<div className="flex-1" />
<select
value={statusFilter}
onChange={(e) => setStatusFilter(e.target.value)}
className="rounded-md border px-2 py-1 text-sm"
>
<option value=""></option>
{statuses.map((s) => (
<option key={s} value={s}>{s}</option>
))}
</select>
</div>
{/* 知识列表 */}
{isLoading ? (
<LoadingSpinner />
) : practices.length === 0 ? (
<div className="rounded-lg border bg-card py-20 text-center">
<Library className="mx-auto h-12 w-12 text-muted-foreground/40" />
<p className="mt-3 text-sm text-muted-foreground"></p>
<p className="mt-1 text-xs text-muted-foreground"></p>
</div>
) : (
<div className="space-y-2">
{practices.map((p: any) => (
<KnowledgeCard key={p.id} practice={p} onClick={() => setSelected(p)} />
))}
</div>
)}
{/* 详情弹窗 */}
{selected && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/30" onClick={() => setSelected(null)}>
<div
className="max-h-[85vh] w-[640px] max-w-[95vw] overflow-y-auto rounded-lg border bg-card p-6 shadow-lg"
onClick={(e) => e.stopPropagation()}
>
{/* 标题栏 */}
<div className="mb-4 flex items-start justify-between">
<div>
<span className="rounded bg-teal-50 px-1.5 py-0.5 text-[10px] font-medium text-teal-700">
{selected.practice_module}
</span>
<h2 className="mt-1 text-base font-bold"> #{selected.id}</h2>
</div>
<button onClick={() => setSelected(null)} className="rounded-md p-1 hover:bg-muted">
<X className="h-5 w-5" />
</button>
</div>
{/* 内容 */}
<div className="space-y-4">
{/* 标杆门店 */}
<div>
<h3 className="mb-1 text-sm font-bold"></h3>
<p className="text-sm">{selected.benchmark_store_name}{selected.benchmark_store_code}</p>
</div>
{/* 关键行动 */}
<div>
<h3 className="mb-1 text-sm font-bold"></h3>
<div className="rounded-lg border bg-muted/20 p-3">
{selected.key_actions?.split('\n').map((line: string, i: number) => (
<p key={i} className="text-xs leading-relaxed text-muted-foreground">
{line || '\u00A0'}
</p>
)) || <p className="text-xs text-muted-foreground"></p>}
</div>
</div>
{/* 验证指标 */}
{selected.verification_indicators && (
<div>
<h3 className="mb-1 text-sm font-bold"></h3>
<p className="text-sm text-muted-foreground">{selected.verification_indicators}</p>
</div>
)}
{/* 状态 */}
<div>
<h3 className="mb-1 text-sm font-bold"></h3>
<Badge type="default" text={selected.status} />
</div>
{/* 推广结果 */}
<div>
<h3 className="mb-2 text-sm font-bold">广</h3>
{replications.length === 0 ? (
<p className="text-xs text-muted-foreground">广</p>
) : (
<div className="space-y-2">
{replications.map((r: any) => (
<div key={r.id} className="rounded-lg border p-2 text-xs">
<div className="flex items-center justify-between">
<b>{r.trial_store_name}</b>
<Badge type="status" text={r.status || '观察中'} />
</div>
<p className="mt-1 text-muted-foreground">
: {r.observation_weeks} · : {r.before_value ?? '-'} · : {r.after_value ?? '-'}
</p>
</div>
))}
</div>
)}
</div>
</div>
{/* 底部操作 */}
<div className="mt-4 flex gap-2 border-t pt-4">
<button
className="flex-1 rounded-md border px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-muted"
onClick={() => {
const code = prompt('请输入试点门店编码')
if (!code) return
const name = prompt('请输入试点门店名称') || code
replicateMutation.mutate({ trial_store_code: code, trial_store_name: name })
}}
>
广
</button>
{selected.status !== '已推广' && (
<button
className="flex-1 rounded-md bg-teal-600 px-4 py-2 text-sm font-medium text-white hover:bg-teal-700"
onClick={() => promoteMutation.mutate()}
disabled={promoteMutation.isPending}
>
{promoteMutation.isPending ? '处理中…' : '标记为已推广'}
</button>
)}
</div>
</div>
</div>
)}
</div>
)
}
+2 -2
View File
@@ -8,8 +8,8 @@ interface LoginPageProps {
export function LoginPage({ onLogin }: LoginPageProps) {
const navigate = useNavigate()
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const [username, setUsername] = useState('平台管理员')
const [password, setPassword] = useState('123')
const [error, setError] = useState('')
const handleLogin = async () => {
+209
View File
@@ -0,0 +1,209 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import api from '@/lib/api'
import { FilterableTable } from '@/components/FilterableTable'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { CollapsibleSection } from '@/components/CollapsibleSection'
import { MetricCard } from '@/components/MetricCard'
import { Tabs } from '@/components/Tabs'
import { formatNumber, formatPercent } from '@/lib/utils'
import { useState } from 'react'
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts'
const STAGE_COLORS: Record<string, string> = { '爬坡': '#3b82f6', '成熟': '#22c55e', '衰退': '#eab308', '淘汰': '#ef4444' }
export function ProductLifecyclePage() {
const [tab, setTab] = useState('lifecycle')
const [stage, setStage] = useState('')
const queryClient = useQueryClient()
const { data: productData, isLoading: productLoading } = useQuery({
queryKey: ['product/products', stage],
queryFn: () => api.get('/product/products', { params: stage ? { stage } : {} }),
})
const { data: reviewOverview, isLoading: reviewLoading } = useQuery({
queryKey: ['product/reviews/overview'],
queryFn: () => api.get('/product/reviews/overview'),
})
const { data: reviewData, isLoading: reviewListLoading } = useQuery({
queryKey: ['product/reviews'],
queryFn: () => api.get('/product/reviews', { params: { page: 1, page_size: 100 } }),
})
const trackMutation = useMutation({
mutationFn: (id: number) => api.post(`/product/products/${id}/track`),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['product/products'] }),
})
if (tab === 'lifecycle' && productLoading) return <LoadingSpinner text="加载产品生命周期数据..." />
if (tab === 'reviews' && reviewLoading) return <LoadingSpinner text="加载评价数据..." />
const products = (productData as any)?.data || []
const reviews = (reviewData as any)?.data || []
const overview = (reviewOverview as any)?.data || {}
const stageDistribution = products.reduce((acc: Record<string, number>, r: any) => {
acc[r.lifecycle_stage] = (acc[r.lifecycle_stage] || 0) + 1
return acc
}, {})
const stagePieData = Object.entries(stageDistribution).map(([name, value]) => ({ name, value }))
const categoryData = [
{ name: '口味', value: Number(overview.taste_count || 0) },
{ name: '服务', value: Number(overview.service_count || 0) },
{ name: '环境', value: Number(overview.env_count || 0) },
{ name: '异物', value: Number(overview.foreign_matter_count || 0) },
{ name: '分量', value: Number(overview.portion_count || 0) },
].filter(d => d.value > 0)
const totalReviews = Number(overview.total_reviews || 0)
const positiveRate = totalReviews > 0 ? (Number(overview.positive || 0) / totalReviews * 100) : 0
const avgRating = Number(overview.avg_rating || 0)
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<h1 className="text-xl font-bold"></h1>
<p className="mt-0.5 text-xs text-muted-foreground">SKU生命周期追踪 · NLP归因 · </p>
</div>
</div>
<Tabs tabs={[
{ key: 'lifecycle', label: '产品生命周期' },
{ key: 'reviews', label: '评价分析' },
]} active={tab} onChange={setTab} />
{tab === 'lifecycle' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="产品总数" value={products.length} format="number" description="在追踪的SKU数量" />
<MetricCard title="爬坡期" value={stageDistribution['爬坡'] || 0} format="number" description="上市7天内" status="warn" />
<MetricCard title="成熟期" value={stageDistribution['成熟'] || 0} format="number" description="上市7-90天" status="good" />
<MetricCard title="衰退期" value={stageDistribution['衰退'] || 0} format="number" description="上市90天+" status="bad" />
</div>
<div className="grid gap-4 lg:grid-cols-2">
<CollapsibleSection title="生命周期阶段分布" subtitle="各阶段SKU数量">
<ResponsiveContainer width="100%" height={250}>
<PieChart>
<Pie data={stagePieData} cx="50%" cy="50%" outerRadius={70} dataKey="value"
labelLine={false} label={({ name, value }: any) => <tspan fontSize={11}>{`${name}: ${value}`}</tspan>}>
{stagePieData.map((entry, i) => <Cell key={i} fill={STAGE_COLORS[entry.name] || '#999'} />)}
</Pie>
<Tooltip formatter={(v: any) => [formatNumber(v), 'SKU数']} />
<Legend />
</PieChart>
</ResponsiveContainer>
</CollapsibleSection>
<CollapsibleSection title="各阶段产品列表" subtitle="按上市日期排序">
<FilterableTable
data={products}
filterKey="lifecycle_stage"
filterLabel="全部阶段"
sortOptions={[
{ key: 'launch_date', label: '上市日期' },
{ key: 'sku_code', label: 'SKU编码' },
{ key: 'lifecycle_stage', label: '阶段' },
]}
defaultSort="launch_date"
defaultOrder="desc"
columns={[
{ key: 'sku_code', label: 'SKU编码' },
{ key: 'sku_name', label: 'SKU名称' },
{ key: 'launch_date', label: '上市日期', render: (r) => (r.launch_date || '').toString().substring(0, 10) },
{ key: 'lifecycle_stage', label: '阶段', align: 'center', render: (r) => {
const colors: Record<string, string> = { '爬坡': 'text-blue-600', '成熟': 'text-green-600', '衰退': 'text-yellow-600', '淘汰': 'text-red-600' }
return <span className={`font-bold ${colors[r.lifecycle_stage] || ''}`}>{r.lifecycle_stage}</span>
}},
{ key: 'survival_status', label: '存活状态', align: 'center' },
{ key: 'first_week_report_date', label: '首周战报', render: (r) => r.first_week_report_date ? (r.first_week_report_date as string).substring(0, 10) : '-' },
{ key: 'day90_report_date', label: '90天判定', render: (r) => r.day90_report_date ? (r.day90_report_date as string).substring(0, 10) : '-' },
{ key: 'action', label: '操作', align: 'center', render: (r) => (
<button onClick={() => trackMutation.mutate(r.id)} className="rounded bg-primary px-2 py-0.5 text-xs text-primary-foreground"></button>
)},
]}
/>
</CollapsibleSection>
</div>
</>
)}
{tab === 'reviews' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="评价总数" value={totalReviews} format="number" description="所有来源评价" />
<MetricCard title="平均评分" value={avgRating} format="number" description="满分5分" status={avgRating >= 4 ? 'good' : avgRating >= 3 ? 'warn' : 'bad'} />
<MetricCard title="好评率" value={positiveRate} format="percent" description="正面评价占比" status={positiveRate >= 80 ? 'good' : positiveRate >= 60 ? 'warn' : 'bad'} />
<MetricCard title="差评数" value={Number(overview.negative || 0)} format="number" description="负面评价数" status="bad" />
</div>
<div className="grid gap-4 lg:grid-cols-2">
<CollapsibleSection title="评价归因分布" subtitle="NLP自动分类">
<ResponsiveContainer width="100%" height={250}>
<PieChart>
<Pie data={categoryData} cx="50%" cy="50%" outerRadius={70} dataKey="value"
labelLine={false} label={({ name, value }: any) => <tspan fontSize={11}>{`${name}: ${value}`}</tspan>}>
{categoryData.map((_, i) => <Cell key={i} fill={['#ef4444', '#3b82f6', '#22c55e', '#eab308', '#a855f7'][i]} />)}
</Pie>
<Tooltip formatter={(v: any) => [formatNumber(v), '条']} />
<Legend />
</PieChart>
</ResponsiveContainer>
</CollapsibleSection>
<CollapsibleSection title="评价趋势" subtitle="按日期统计">
<ResponsiveContainer width="100%" height={250}>
<BarChart data={reviews.slice(0, 30).reverse().map((r: any) => ({
date: (r.review_date || '').substring(0, 10),
rating: Number(r.rating || 0),
}))}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" fontSize={10} />
<YAxis domain={[0, 5]} />
<Tooltip />
<Legend />
<Bar dataKey="rating" fill="#3b82f6" name="评分" />
</BarChart>
</ResponsiveContainer>
</CollapsibleSection>
</div>
<CollapsibleSection title={`评价明细 (${reviews.length})`} subtitle="按日期降序">
<FilterableTable
data={reviews}
filterKey="nlp_category"
filterLabel="全部分类"
sortOptions={[
{ key: 'review_date', label: '评价日期' },
{ key: 'rating', label: '评分' },
]}
defaultSort="review_date"
defaultOrder="desc"
searchKeys={['content', 'store_name', 'sku_name']}
searchPlaceholder="搜索评价内容..."
columns={[
{ key: 'review_date', label: '日期', render: (r) => (r.review_date || '').toString().substring(0, 10) },
{ key: 'review_source', label: '来源' },
{ key: 'store_name', label: '门店' },
{ key: 'sku_name', label: 'SKU' },
{ key: 'rating', label: '评分', align: 'center', render: (r) => {
const colors: Record<number, string> = { 1: 'text-red-600', 2: 'text-red-500', 3: 'text-yellow-600', 4: 'text-blue-600', 5: 'text-green-600' }
return <span className={`font-bold ${colors[r.rating] || ''}`}>{r.rating}</span>
}},
{ key: 'nlp_category', label: '归因', align: 'center' },
{ key: 'nlp_sentiment', label: '情感', align: 'center', render: (r) => {
const colors: Record<string, string> = { '正面': 'text-green-600', '负面': 'text-red-600', '中性': 'text-yellow-600' }
return <span className={colors[r.nlp_sentiment] || ''}>{r.nlp_sentiment}</span>
}},
{ key: 'content', label: '评价内容' },
]}
/>
</CollapsibleSection>
</>
)}
</div>
)
}
+199
View File
@@ -0,0 +1,199 @@
import { useQuery } from '@tanstack/react-query'
import { useState } from 'react'
import api from '@/lib/api'
import { FilterableTable } from '@/components/FilterableTable'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { CollapsibleSection } from '@/components/CollapsibleSection'
import { MetricCard } from '@/components/MetricCard'
import { formatCurrency, formatNumber, formatPercent } from '@/lib/utils'
import { MonthPicker } from '@/components/MonthPicker'
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, LineChart, Line } from 'recharts'
export function PromotionPage() {
const [month, setMonth] = useState('2026-04')
const { data: overviewData, isLoading: overviewLoading } = useQuery({
queryKey: ['promotion/overview', month],
queryFn: () => api.get('/promotion/overview', { params: { month } }),
})
const { data: planData, isLoading: planLoading } = useQuery({
queryKey: ['promotion/by-plan', month],
queryFn: () => api.get('/promotion/by-plan', { params: { month } }),
})
const { data: storeData, isLoading: storeLoading } = useQuery({
queryKey: ['promotion/by-store', month],
queryFn: () => api.get('/promotion/by-store', { params: { month } }),
})
const { data: trendData, isLoading: trendLoading } = useQuery({
queryKey: ['promotion/daily-trend', month],
queryFn: () => api.get('/promotion/daily-trend', { params: { month } }),
})
const pageLoading = overviewLoading || planLoading || storeLoading || trendLoading
if (pageLoading) {
return <LoadingSpinner text="加载促销增量利润数据..." />
}
const overview = (overviewData as any)?.data || {}
const plans = (planData as any)?.data || []
const stores = (storeData as any)?.data || []
const trends = (trendData as any)?.data || []
const trendChartData = trends.map((t: any) => ({
date: t.date.substring(8, 10),
促销客单: Math.round(Number(t.promo_avg_bill) * 100) / 100,
非促销客单: Math.round(Number(t.baseline_avg_bill) * 100) / 100,
增量: Math.round(Number(t.uplift) * 100) / 100,
}))
const planChartData = plans.slice(0, 10).map((p: any) => ({
name: p.marketing_plan?.length > 8 ? p.marketing_plan.substring(0, 8) + '...' : p.marketing_plan,
增量收入: Math.round(Number(p.incremental_revenue || 0)),
促销成本: Math.round(Number(p.promotion_cost || 0)),
净增量利润: Math.round(Number(p.net_incremental_profit || 0)),
}))
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<h1 className="text-xl font-bold"></h1>
<p className="mt-0.5 text-xs text-muted-foreground">vs非促销对比 · · ROI · {month}</p>
</div>
<MonthPicker month={month} onChange={setMonth} />
</div>
{/* 概览指标 */}
<CollapsibleSection title="促销增量总览" subtitle="促销 vs 非促销基准对比">
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="促销账单数" value={overview.promo_bills || 0} format="number" description="有营销方案的账单数" />
<MetricCard title="促销占比" value={overview.promo_share_pct || 0} format="percent" description="促销账单占总账单比例" />
<MetricCard title="客单价提升" value={overview.bill_uplift_pct || 0} format="percent" description="促销客单价 vs 非促销客单价" status={(overview.bill_uplift_pct || 0) > 0 ? 'good' : 'bad'} />
<MetricCard title="促销ROI" value={overview.promo_roi || 0} format="number" description="增量利润/促销成本" status={(overview.promo_roi || 0) > 1 ? 'good' : 'warn'} />
</div>
<div className="mt-3 grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="增量收入" value={overview.incremental_revenue || 0} format="currency" description="(促销客单-基准客单)×促销单数" status={(overview.incremental_revenue || 0) > 0 ? 'good' : 'bad'} />
<MetricCard title="促销成本" value={overview.promotion_cost || 0} format="currency" description="促销账单优惠总额" status="bad" />
<MetricCard title="净增量利润" value={overview.net_incremental_profit || 0} format="currency" description="增量收入-促销成本" status={(overview.net_incremental_profit || 0) > 0 ? 'good' : 'bad'} />
<MetricCard title="促销毛利率" value={overview.promo_margin_pct || 0} format="percent" description="促销账单理论毛利率" />
</div>
</CollapsibleSection>
{/* 图表 */}
<div className="grid gap-4 lg:grid-cols-2">
<CollapsibleSection title="促销日趋势" subtitle="每日促销vs非促销客单价对比">
<ResponsiveContainer width="100%" height={300}>
<LineChart data={trendChartData} margin={{ top: 20, right: 20, bottom: 20, left: 20 }}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" tick={{ fontSize: 10 }} />
<YAxis tick={{ fontSize: 10 }} tickFormatter={(v) => v >= 100 ? `${v}` : v} />
<Tooltip formatter={(v: any) => formatCurrency(v)} />
<Legend />
<Line type="monotone" dataKey="促销客单" stroke="#22c55e" strokeWidth={2} />
<Line type="monotone" dataKey="非促销客单" stroke="#94a3b8" strokeWidth={2} />
<Line type="monotone" dataKey="增量" stroke="#3b82f6" strokeWidth={2} strokeDasharray="5 5" />
</LineChart>
</ResponsiveContainer>
</CollapsibleSection>
<CollapsibleSection title="各促销方案增量对比" subtitle="TOP10方案的增量收入vs促销成本">
<ResponsiveContainer width="100%" height={300}>
<BarChart data={planChartData} margin={{ top: 20, right: 20, bottom: 20, left: 20 }}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" tick={{ fontSize: 9 }} angle={-20} textAnchor="end" height={60} />
<YAxis tick={{ fontSize: 10 }} tickFormatter={(v) => v >= 10000 ? `${(v / 10000).toFixed(0)}` : v} />
<Tooltip formatter={(v: any) => formatCurrency(v)} />
<Legend />
<Bar dataKey="增量收入" fill="#22c55e" />
<Bar dataKey="促销成本" fill="#ef4444" />
<Bar dataKey="净增量利润" fill="#3b82f6" />
</BarChart>
</ResponsiveContainer>
</CollapsibleSection>
</div>
{/* 按方案明细 */}
<CollapsibleSection title={`促销方案对比 (${plans.length})`} subtitle="各营销方案的增量利润分析">
<FilterableTable
data={plans}
filterKey="marketing_plan"
filterLabel="全部方案"
sortOptions={[
{ key: 'total_revenue', label: '促销收入' },
{ key: 'bill_count', label: '账单数' },
{ key: 'net_incremental_profit', label: '净增量利润' },
{ key: 'promo_roi', label: 'ROI' },
{ key: 'bill_uplift_pct', label: '客单提升' },
]}
defaultSort="total_revenue"
defaultOrder="desc"
columns={[
{ key: 'marketing_plan', label: '营销方案' },
{ key: 'bill_count', label: '账单数', align: 'right', render: (r) => formatNumber(r.bill_count) },
{ key: 'store_count', label: '覆盖门店', align: 'right', render: (r) => formatNumber(r.store_count) },
{ key: 'avg_bill_value', label: '客单价', align: 'right', render: (r) => formatCurrency(r.avg_bill_value) },
{ key: 'bill_uplift_pct', label: '客单提升', align: 'right', render: (r) => {
const v = Number(r.bill_uplift_pct || 0)
return <span className={v > 0 ? 'text-green-600' : 'text-red-600'}>{v > 0 ? '+' : ''}{v.toFixed(1)}%</span>
}},
{ key: 'total_revenue', label: '促销收入', align: 'right', render: (r) => formatCurrency(r.total_revenue) },
{ key: 'total_discount', label: '优惠总额', align: 'right', render: (r) => <span className="text-red-600">{formatCurrency(r.total_discount)}</span> },
{ key: 'incremental_revenue', label: '增量收入', align: 'right', render: (r) => formatCurrency(r.incremental_revenue) },
{ key: 'net_incremental_profit', label: '净增量利润', align: 'right', render: (r) => {
const v = Number(r.net_incremental_profit || 0)
return <span className={v >= 0 ? 'text-green-600 font-medium' : 'text-red-600 font-medium'}>{formatCurrency(v)}</span>
}},
{ key: 'promo_roi', label: 'ROI', align: 'right', render: (r) => {
const v = Number(r.promo_roi || 0)
return <span className={v > 1 ? 'text-green-600 font-bold' : v > 0 ? 'text-yellow-600' : 'text-red-600'}>{v.toFixed(2)}x</span>
}},
{ key: 'member_share_pct', label: '会员占比', align: 'right', render: (r) => `${Number(r.member_share_pct || 0).toFixed(1)}%` },
]}
/>
</CollapsibleSection>
{/* 按门店明细 */}
<CollapsibleSection title={`门店促销效果 (${stores.length})`} subtitle="各门店的促销增量利润">
<FilterableTable
data={stores}
filterKey="store_name"
filterLabel="全部门店"
sortOptions={[
{ key: 'promo_revenue', label: '促销收入' },
{ key: 'net_incremental_profit', label: '净增量利润' },
{ key: 'uplift_pct', label: '客单提升' },
{ key: 'promo_roi', label: 'ROI' },
{ key: 'plan_count', label: '方案数' },
]}
defaultSort="net_incremental_profit"
defaultOrder="desc"
columns={[
{ key: 'store_name', label: '门店名称' },
{ key: 'plan_count', label: '方案数', align: 'center' },
{ key: 'promo_bills', label: '促销单数', align: 'right', render: (r) => formatNumber(r.promo_bills) },
{ key: 'promo_avg_bill', label: '促销客单', align: 'right', render: (r) => formatCurrency(r.promo_avg_bill) },
{ key: 'baseline_avg_bill', label: '基准客单', align: 'right', render: (r) => formatCurrency(r.baseline_avg_bill) },
{ key: 'uplift_pct', label: '客单提升', align: 'right', render: (r) => {
const v = Number(r.uplift_pct || 0)
return v ? <span className={v > 0 ? 'text-green-600' : 'text-red-600'}>{v > 0 ? '+' : ''}{v.toFixed(1)}%</span> : '-'
}},
{ key: 'incremental_revenue', label: '增量收入', align: 'right', render: (r) => formatCurrency(r.incremental_revenue) },
{ key: 'promotion_cost', label: '促销成本', align: 'right', render: (r) => <span className="text-red-600">{formatCurrency(r.promotion_cost)}</span> },
{ key: 'net_incremental_profit', label: '净增量利润', align: 'right', render: (r) => {
const v = Number(r.net_incremental_profit || 0)
return <span className={v >= 0 ? 'text-green-600 font-medium' : 'text-red-600 font-medium'}>{formatCurrency(v)}</span>
}},
{ key: 'promo_roi', label: 'ROI', align: 'right', render: (r) => {
const v = Number(r.promo_roi || 0)
return v ? <span className={v > 1 ? 'text-green-600 font-bold' : v > 0 ? 'text-yellow-600' : 'text-red-600'}>{v.toFixed(2)}x</span> : '-'
}},
]}
/>
</CollapsibleSection>
</div>
)
}
+1 -1
View File
@@ -55,7 +55,7 @@ export function RegionalPage() {
const pageLoading = riskLoading || weeklyLoading || priorityLoading
const weeklyMutation = useMutation({
mutationFn: ({ id, text }: { id: number; text: string }) => api.put(`/tasks/${id}/weekly-check`, { weekly_comment: text }),
mutationFn: ({ id, text }: { id: number; text: string }) => api.put(`/tasks/${id}/weekly-check`, { check_comment: text }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['tasks/weekly-check'] })
setWeeklyModal(null)
+1 -1
View File
@@ -68,7 +68,7 @@ export function RevenuePage() {
received: Number(r.received || 0),
bills: Number(r.bill_count || 0),
avg_bill: Number(r.avg_bill_value || 0),
discount_rate: Number(r.avg_discount_rate_pct || 0),
discount_rate: Number(r.discount_rate_pct || 0),
}))
// 环比
+60 -14
View File
@@ -21,13 +21,17 @@ function SectionLoading({ text }: { text: string }) {
}
export function RiskPage() {
const [riskTab, setRiskTab] = useState<'anomaly' | 'zero' | 'cashier'>('anomaly')
const [riskTab, setRiskTab] = useState<'anomaly' | 'full_discount' | 'empty_bill' | 'cashier'>('anomaly')
const [month, setMonth] = useState('2026-04')
const [anomalyPage, setAnomalyPage] = useState(1)
const [anomalyStore, setAnomalyStore] = useState('')
const [anomalyReason, setAnomalyReason] = useState('')
const [anomalyCashier, setAnomalyCashier] = useState('')
const [debouncedCashier, setDebouncedCashier] = useState('')
const [anomalySort, setAnomalySort] = useState('consumption')
const [anomalyOrder, setAnomalyOrder] = useState<'asc' | 'desc'>('desc')
const [zeroPage, setZeroPage] = useState(1)
const [zeroType, setZeroType] = useState<'全额优惠' | '无消费无优惠'>('全额优惠')
useEffect(() => {
const t = setTimeout(() => setDebouncedCashier(anomalyCashier), 400)
@@ -35,15 +39,14 @@ export function RiskPage() {
}, [anomalyCashier])
const { data: anomalyData, isLoading: anomalyLoading, isFetching: anomalyFetching } = useQuery({
queryKey: ['risk/anomaly', month, anomalyPage, anomalyStore, anomalyReason, debouncedCashier],
queryFn: () => api.get('/risk/anomaly', { params: { month, page: anomalyPage, page_size: ANOMALY_PAGE_SIZE, ...(anomalyStore ? { store: anomalyStore } : {}), ...(anomalyReason ? { reason: anomalyReason } : {}), ...(debouncedCashier ? { cashier: debouncedCashier } : {}) } }),
queryKey: ['risk/anomaly', month, anomalyPage, anomalyStore, anomalyReason, debouncedCashier, anomalySort, anomalyOrder],
queryFn: () => api.get('/risk/anomaly', { params: { month, page: anomalyPage, page_size: ANOMALY_PAGE_SIZE, sort: anomalySort, order: anomalyOrder, ...(anomalyStore ? { store: anomalyStore } : {}), ...(anomalyReason ? { reason: anomalyReason } : {}), ...(debouncedCashier ? { cashier: debouncedCashier } : {}) } }),
placeholderData: keepPreviousData,
})
const { data: zeroData, isLoading: zeroLoading, isFetching: zeroFetching } = useQuery({
queryKey: ['risk/zero-received', month],
queryFn: () => api.get('/risk/zero-received', { params: { month } }),
staleTime: 5 * 60 * 1000,
queryKey: ['risk/zero-received', month, zeroType, zeroPage],
queryFn: () => api.get('/risk/zero-received', { params: { month, type: zeroType, page: zeroPage, page_size: ANOMALY_PAGE_SIZE } }),
placeholderData: keepPreviousData,
})
@@ -57,13 +60,14 @@ export function RiskPage() {
const anomalyRows = (anomalyData as any)?.data || []
const anomalyMeta = (anomalyData as any)?.meta || { total: 0 }
const zeroRows = (zeroData as any)?.data || []
const zeroMeta = (zeroData as any)?.meta || { total: 0, full_discount: 0, empty_bill: 0 }
const cashierRows = (cashierData as any)?.data || []
const storeNames: string[] = Array.from(new Set<string>(cashierRows.map((r: any) => r.store_name as string).filter(Boolean))).sort()
const initialLoading = !anomalyData && !zeroData && !cashierData
const totalAnomaly = anomalyMeta.total || anomalyRows.length
const totalZero = zeroRows.length
const totalZero = zeroMeta.total || zeroRows.length
const highRiskCashiers = cashierRows.filter((r: any) => Number(r.anomaly_rate_pct || 0) >= 10).length
const avgAnomalyRate = cashierRows.length > 0
? cashierRows.reduce((s: number, r: any) => s + Number(r.anomaly_rate_pct || 0), 0) / cashierRows.length
@@ -87,9 +91,10 @@ export function RiskPage() {
{/* 概览指标 */}
<CollapsibleSection title="风险概览" subtitle="异常账单与收银操作风险汇总">
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<div className="grid grid-cols-2 gap-3 md:grid-cols-5">
<MetricCard title="异常账单数" value={totalAnomaly} format="number" description="触发异常规则的账单数量,需逐单核查" />
<MetricCard title="零实收账单" value={totalZero} format="number" description="实收为0的账单,可能为全额优惠或操作异常" />
<MetricCard title="全额优惠账单" value={zeroMeta.full_discount || 0} format="number" description="消费>0但实收=0,需核查是否违规免单" />
<MetricCard title="空单账单" value={zeroMeta.empty_bill || 0} format="number" description="无消费无优惠的空单,需排查操作异常" />
<MetricCard title="高风险收银员(≥10%)" value={highRiskCashiers} format="number" description="异常操作率≥10%的收银员数量" />
<MetricCard title="平均异常率" value={avgAnomalyRate} format="percent" description="所有收银员的平均异常操作率" />
</div>
@@ -118,8 +123,11 @@ export function RiskPage() {
<button onClick={() => setRiskTab('anomaly')} className={`rounded-md border px-3 py-1.5 text-sm ${riskTab === 'anomaly' ? 'border-primary bg-primary text-primary-foreground' : ''}`}>
({totalAnomaly})
</button>
<button onClick={() => setRiskTab('zero')} className={`rounded-md border px-3 py-1.5 text-sm ${riskTab === 'zero' ? 'border-primary bg-primary text-primary-foreground' : ''}`}>
({totalZero})
<button onClick={() => { setRiskTab('full_discount'); setZeroType('全额优惠'); setZeroPage(1) }} className={`rounded-md border px-3 py-1.5 text-sm ${riskTab === 'full_discount' ? 'border-primary bg-primary text-primary-foreground' : ''}`}>
({zeroMeta.full_discount || 0})
</button>
<button onClick={() => { setRiskTab('empty_bill'); setZeroType('无消费无优惠'); setZeroPage(1) }} className={`rounded-md border px-3 py-1.5 text-sm ${riskTab === 'empty_bill' ? 'border-primary bg-primary text-primary-foreground' : ''}`}>
({zeroMeta.empty_bill || 0})
</button>
<button onClick={() => setRiskTab('cashier')} className={`rounded-md border px-3 py-1.5 text-sm ${riskTab === 'cashier' ? 'border-primary bg-primary text-primary-foreground' : ''}`}>
({cashierRows.length})
@@ -161,6 +169,10 @@ export function RiskPage() {
searchPlaceholder="搜索收银员..."
serverSearchValue={anomalyCashier}
onServerSearchChange={(v) => { setAnomalyCashier(v); setAnomalyPage(1) }}
sort={anomalySort}
order={anomalyOrder}
onSortChange={(v) => { setAnomalySort(v); setAnomalyPage(1) }}
onOrderChange={(v) => { setAnomalyOrder(v); setAnomalyPage(1) }}
sortOptions={[
{ key: 'consumption', label: '消费额' },
{ key: 'discount_total', label: '优惠' },
@@ -183,10 +195,45 @@ export function RiskPage() {
</>
)}
{riskTab === 'zero' && (
zeroFetching ? <SectionLoading text="加载零实收数据..." /> :
{riskTab === 'full_discount' && (
zeroFetching ? <SectionLoading text="加载全额优惠数据..." /> :
<FilterableTable
data={zeroRows}
serverSide
page={zeroPage}
onPageChange={setZeroPage}
pageSize={ANOMALY_PAGE_SIZE}
total={zeroMeta.total}
sortOptions={[
{ key: 'consumption', label: '消费额' },
{ key: 'discount_total', label: '优惠' },
{ key: 'store_name', label: '门店' },
]}
defaultSort="consumption"
defaultOrder="desc"
filterKey="store_name"
filterLabel="全部门店"
columns={[
{ key: 'store_name', label: '门店' },
{ key: 'bill_no', label: '账单号' },
{ key: 'meal_period', label: '餐段' },
{ key: 'consumption', label: '消费额', align: 'right', render: (r) => formatCurrency(r.consumption) },
{ key: 'discount_total', label: '优惠', align: 'right', render: (r) => formatCurrency(r.discount_total) },
{ key: 'cashier', label: '收银员' },
{ key: 'closed_at', label: '结账时间', render: (r) => r.closed_at?.substring(0, 16) },
]}
/>
)}
{riskTab === 'empty_bill' && (
zeroFetching ? <SectionLoading text="加载空单数据..." /> :
<FilterableTable
data={zeroRows}
serverSide
page={zeroPage}
onPageChange={setZeroPage}
pageSize={ANOMALY_PAGE_SIZE}
total={zeroMeta.total}
sortOptions={[
{ key: 'consumption', label: '消费额' },
{ key: 'discount_total', label: '优惠' },
@@ -202,7 +249,6 @@ export function RiskPage() {
{ key: 'meal_period', label: '餐段' },
{ key: 'consumption', label: '消费额', align: 'right', render: (r) => formatCurrency(r.consumption) },
{ key: 'discount_total', label: '优惠', align: 'right', render: (r) => formatCurrency(r.discount_total) },
{ key: 'zero_received_type', label: '零实收类型' },
{ key: 'cashier', label: '收银员' },
{ key: 'closed_at', label: '结账时间', render: (r) => r.closed_at?.substring(0, 16) },
]}
@@ -0,0 +1,134 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import api from '@/lib/api'
import { FilterableTable } from '@/components/FilterableTable'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { CollapsibleSection } from '@/components/CollapsibleSection'
import { MetricCard } from '@/components/MetricCard'
import { useState } from 'react'
export function SchedulerManagementPage() {
const queryClient = useQueryClient()
const [editingId, setEditingId] = useState<number | null>(null)
const [editCron, setEditCron] = useState('')
const { data: tasksData, isLoading } = useQuery({
queryKey: ['scheduler/tasks'],
queryFn: () => api.get('/scheduler'),
})
const toggleMutation = useMutation({
mutationFn: (data: { id: number; is_enabled: boolean }) =>
api.patch(`/scheduler/${data.id}`, { is_enabled: data.is_enabled }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['scheduler/tasks'] }),
})
const updateCronMutation = useMutation({
mutationFn: (data: { id: number; cron_expr: string }) =>
api.patch(`/scheduler/${data.id}`, { cron_expr: data.cron_expr }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['scheduler/tasks'] })
setEditingId(null)
},
})
const triggerMutation = useMutation({
mutationFn: (id: number) => api.post(`/scheduler/${id}/trigger`),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['scheduler/tasks'] }),
})
const tasks = (tasksData as any)?.data || []
const enabledCount = tasks.filter((t: any) => t.is_enabled).length
const successCount = tasks.filter((t: any) => t.last_status === 'success').length
const failedCount = tasks.filter((t: any) => t.last_status === 'failed').length
const runningCount = tasks.filter((t: any) => t.last_status === 'running').length
if (isLoading) {
return <LoadingSpinner text="加载调度任务..." />
}
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<h1 className="text-xl font-bold"></h1>
<p className="mt-0.5 text-xs text-muted-foreground"> · </p>
</div>
</div>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="总任务数" value={tasks.length} format="number" description="所有注册的调度任务" />
<MetricCard title="启用中" value={enabledCount} format="number" description="当前启用的任务数" status="good" />
<MetricCard title="成功执行" value={successCount} format="number" description="上次执行成功的任务数" status="good" />
<MetricCard title="执行失败" value={failedCount} format="number" description="上次执行失败的任务数" status={failedCount > 0 ? 'bad' : 'good'} />
</div>
<CollapsibleSection title={`调度任务列表 (${tasks.length})`} subtitle="查看、启停、手动触发调度任务">
<FilterableTable
data={tasks}
sortOptions={[
{ key: 'task_name', label: '任务名' },
{ key: 'last_run_at', label: '上次执行' },
{ key: 'last_status', label: '状态' },
]}
defaultSort="task_name"
defaultOrder="asc"
columns={[
{ key: 'task_name', label: '任务名称' },
{ key: 'description', label: '描述' },
{ key: 'cron_expr', label: 'Cron表达式', render: (r) => (
editingId === r.id ? (
<div className="flex gap-1">
<input
type="text"
value={editCron}
onChange={(e) => setEditCron(e.target.value)}
className="w-32 rounded border px-2 py-0.5 text-xs"
/>
<button
onClick={() => updateCronMutation.mutate({ id: r.id, cron_expr: editCron })}
className="rounded bg-primary px-2 py-0.5 text-xs text-primary-foreground"
></button>
<button
onClick={() => setEditingId(null)}
className="rounded bg-muted px-2 py-0.5 text-xs"
></button>
</div>
) : (
<span className="font-mono text-xs">{r.cron_expr}</span>
)
)},
{ key: 'is_enabled', label: '启用', align: 'center', render: (r) => (
<button
onClick={() => toggleMutation.mutate({ id: r.id, is_enabled: !r.is_enabled })}
className={`rounded px-2 py-0.5 text-xs ${r.is_enabled ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-500'}`}
>
{r.is_enabled ? '启用中' : '已停用'}
</button>
)},
{ key: 'last_status', label: '上次状态', align: 'center', render: (r) => {
if (!r.last_status) return <span className="text-xs text-muted-foreground"></span>
const colors: Record<string, string> = { success: 'bg-green-100 text-green-700', failed: 'bg-red-100 text-red-700', running: 'bg-blue-100 text-blue-700' }
const labels: Record<string, string> = { success: '成功', failed: '失败', running: '运行中' }
return <span className={`rounded px-2 py-0.5 text-xs ${colors[r.last_status] || ''}`}>{labels[r.last_status] || r.last_status}</span>
}},
{ key: 'last_run_at', label: '上次执行时间', render: (r) => r.last_run_at ? (r.last_run_at as string).substring(0, 19).replace('T', ' ') : '-' },
{ key: 'actions', label: '操作', align: 'center', render: (r) => (
<div className="flex gap-1">
<button
onClick={() => triggerMutation.mutate(r.id)}
disabled={triggerMutation.isPending}
className="rounded bg-primary px-2 py-0.5 text-xs text-primary-foreground hover:opacity-80"
></button>
<button
onClick={() => { setEditingId(r.id); setEditCron(r.cron_expr) }}
className="rounded bg-muted px-2 py-0.5 text-xs"
></button>
</div>
)},
]}
/>
</CollapsibleSection>
</div>
)
}
+3 -3
View File
@@ -47,7 +47,7 @@ export function StoreDetailPage() {
const { data: healthData } = useQuery({
queryKey: ['store-health', code, month],
queryFn: () => api.get('/situational-awareness/health-score', { params: { month } }),
queryFn: () => api.get('/situational-awareness/health-score', { params: { month, store_code: code } }),
})
const { data: dailyData } = useQuery({
@@ -125,8 +125,8 @@ export function StoreDetailPage() {
const quadrant = action?.management_quadrant || ''
const quadrantInfo = quadrantDesc[quadrant]
// 公司均值
const companyAvg = { daily_rev: 20144, bill: 36.8, discount: 20.5, margin: 71.5, member: 15.9, repeat: 37.0, delivery: 36.1, combo: 20.6, items: 4.05 }
// 公司均值(从API获取,fallback到默认值)
const companyAvg = sd.companyAvg || { daily_rev: 20144, bill: 36.8, discount: 20.5, margin: 71.5, member: 15.9, repeat: 37.0, delivery: 36.1, combo: 20.6, items: 4.05 }
// 偏差项明细
const deviations: { label: string; store: number; company: number; unit: string; good: 'high' | 'low' }[] = [
+350
View File
@@ -0,0 +1,350 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import api from '@/lib/api'
import { FilterableTable } from '@/components/FilterableTable'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { CollapsibleSection } from '@/components/CollapsibleSection'
import { MetricCard } from '@/components/MetricCard'
import { formatCurrency, formatNumber, formatPercent } from '@/lib/utils'
import { useState } from 'react'
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, PieChart, Pie, Cell, RadarChart, PolarGrid, PolarAngleAxis, PolarRadiusAxis, Radar } from 'recharts'
import { Tabs } from '@/components/Tabs'
import { MonthPicker } from '@/components/MonthPicker'
const GRADE_COLORS: Record<string, string> = { A: '#22c55e', B: '#3b82f6', C: '#eab308', D: '#ef4444' }
const RISK_COLORS: Record<string, string> = { '红色': '#ef4444', '黄色': '#eab308', '绿色': '#22c55e' }
export function StoreGradePage() {
const [month, setMonth] = useState(new Date().toISOString().slice(0, 7))
const [selectedStore, setSelectedStore] = useState<any>(null)
const [tab, setTab] = useState('grade')
const queryClient = useQueryClient()
const { data: gradeData, isLoading: gradeLoading } = useQuery({
queryKey: ['store-grade/grades', month],
queryFn: () => api.get('/store-grade/grades', { params: { month } }),
enabled: tab === 'grade',
})
const { data: closureData, isLoading: closureLoading } = useQuery({
queryKey: ['store-grade/closure-analysis', month],
queryFn: () => api.get('/store-grade/closure-analysis', { params: { month } }),
enabled: tab === 'closure',
})
const autoGradeMutation = useMutation({
mutationFn: () => api.post('/store-grade/auto-grade', null, { params: { month } }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['store-grade/grades'] })
},
})
const gradeRows = (gradeData as any)?.data || []
const gradeDistribution = gradeRows.reduce((acc: Record<string, number>, r: any) => {
acc[r.grade] = (acc[r.grade] || 0) + 1
return acc
}, {})
const gradePieData = Object.entries(gradeDistribution).map(([name, value]) => ({ name: `${name}`, value }))
const riskDistribution = gradeRows.reduce((acc: Record<string, number>, r: any) => {
acc[r.risk_level] = (acc[r.risk_level] || 0) + 1
return acc
}, {})
const riskPieData = [
{ name: '红色', value: riskDistribution['红色'] || 0 },
{ name: '黄色', value: riskDistribution['黄色'] || 0 },
{ name: '绿色', value: riskDistribution['绿色'] || 0 },
]
const avgScore = gradeRows.length > 0
? gradeRows.reduce((s: number, r: any) => s + Number(r.overall_score || 0), 0) / gradeRows.length
: 0
const aGradeCount = gradeDistribution.A || 0
const dGradeCount = gradeDistribution.D || 0
const redRiskCount = riskDistribution['红色'] || 0
if (gradeLoading && tab === 'grade') {
return <LoadingSpinner text="加载门店分级数据..." />
}
if (closureLoading && tab === 'closure') {
return <LoadingSpinner text="加载关停测算数据..." />
}
const closure = (closureData as any)?.data || {}
const closureSummary = closure.summary || {}
const closureStores = closure.stores || []
const closurePieData = [
{ name: '建议关停', value: closureSummary.recommend_close || 0 },
{ name: '整改观察', value: closureSummary.recommend_rectify || 0 },
{ name: '持续经营', value: (closureSummary.total_stores || 0) - (closureSummary.recommend_close || 0) - (closureSummary.recommend_rectify || 0) },
].filter(d => d.value > 0)
const CLOSURE_COLORS: Record<string, string> = { '建议关停': '#ef4444', '整改观察': '#eab308', '持续经营': '#22c55e' }
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<h1 className="text-xl font-bold"></h1>
<p className="mt-0.5 text-xs text-muted-foreground"> · · · {month}</p>
</div>
<div className="flex items-center gap-2">
<MonthPicker month={month} onChange={setMonth} />
{tab === 'grade' && (
<button
onClick={() => autoGradeMutation.mutate()}
disabled={autoGradeMutation.isPending}
className="rounded bg-primary px-3 py-1 text-sm text-primary-foreground disabled:opacity-50"
>
{autoGradeMutation.isPending ? '分级中...' : '自动分级'}
</button>
)}
</div>
</div>
<Tabs tabs={[
{ key: 'grade', label: '门店分级' },
{ key: 'closure', label: '关停测算' },
]} active={tab} onChange={setTab} />
{tab === 'closure' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="门店总数" value={closureSummary.total_stores || 0} format="number" description="参与测算的门店总数" />
<MetricCard title="建议关停" value={closureSummary.recommend_close || 0} format="number" description="持续亏损且D级门店" status="bad" />
<MetricCard title="整改观察" value={closureSummary.recommend_rectify || 0} format="number" description="亏损但有基础的门店" status="warn" />
<MetricCard title="关停可月省" value={closureSummary.total_monthly_savings || 0} format="currency" description="关停门店每月可节省亏损" status="good" />
</div>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="关停总成本" value={closureSummary.total_closure_cost || 0} format="currency" description="遣散+违约+资产处置" status="bad" />
<MetricCard title="12月预计亏损" value={closureSummary.total_projected_loss || 0} format="currency" description="不关停继续经营的预计亏损" status="bad" />
</div>
{closurePieData.length > 0 && (
<CollapsibleSection title="关停建议分布" subtitle="按盈利状况和综合评分分类">
<ResponsiveContainer width="100%" height={200}>
<PieChart>
<Pie data={closurePieData} cx="50%" cy="50%" outerRadius={60} dataKey="value"
labelLine={false} label={({ name, value }: any) => <tspan fontSize={11}>{`${name}: ${value}`}</tspan>}>
{closurePieData.map((e, i) => <Cell key={i} fill={CLOSURE_COLORS[e.name] || '#999'} />)}
</Pie>
<Tooltip formatter={(v: any) => [formatNumber(v), '门店数']} />
<Legend />
</PieChart>
</ResponsiveContainer>
</CollapsibleSection>
)}
<CollapsibleSection title={`关停测算明细 (${closureStores.length})`} subtitle="含关停成本、继续经营亏损、回本期、建议">
<FilterableTable
data={closureStores}
filterKey="recommendation"
filterLabel="全部建议"
sortOptions={[
{ key: 'monthly_profit', label: '月利润' },
{ key: 'total_closure_cost', label: '关停成本' },
{ key: 'projected_12m_loss', label: '12月亏损' },
{ key: 'payback_months', label: '回本月数' },
{ key: 'overall_score', label: '综合分' },
]}
defaultSort="monthly_profit"
defaultOrder="asc"
columns={[
{ key: 'store_name', label: '门店名称' },
{ key: 'region', label: '区域' },
{ key: 'grade', label: '分级', align: 'center', render: (r) => {
const colors: Record<string, string> = { A: 'text-green-600', B: 'text-blue-600', C: 'text-yellow-600', D: 'text-red-600' }
return <span className={`font-bold ${colors[r.grade] || ''}`}>{r.grade}</span>
}},
{ key: 'monthly_revenue', label: '月收入', align: 'right', render: (r) => formatCurrency(r.monthly_revenue) },
{ key: 'monthly_profit', label: '月利润', align: 'right', render: (r) => {
const v = Number(r.monthly_profit || 0)
return <span className={v < 0 ? 'text-red-600 font-medium' : 'text-green-600'}>{formatCurrency(v)}</span>
}},
{ key: 'monthly_rent', label: '月租', align: 'right', render: (r) => formatCurrency(r.monthly_rent) },
{ key: 'monthly_wage', label: '月人工', align: 'right', render: (r) => formatCurrency(r.monthly_wage) },
{ key: 'total_closure_cost', label: '关停成本', align: 'right', render: (r) => <span className="text-red-600">{formatCurrency(r.total_closure_cost)}</span> },
{ key: 'projected_12m_loss', label: '12月亏损', align: 'right', render: (r) => {
const v = Number(r.projected_12m_loss || 0)
return v ? <span className="text-red-600">{formatCurrency(v)}</span> : '-'
}},
{ key: 'monthly_savings_if_closed', label: '月节省', align: 'right', render: (r) => {
const v = Number(r.monthly_savings_if_closed || 0)
return v ? <span className="text-green-600">{formatCurrency(v)}</span> : '-'
}},
{ key: 'payback_months', label: '回本(月)', align: 'right', render: (r) => r.payback_months ? `${Number(r.payback_months).toFixed(1)}` : '-' },
{ key: 'recommendation', label: '建议', align: 'center', render: (r) => {
const colors: Record<string, string> = { '建议关停': 'bg-red-500 text-white', '整改观察3个月': 'bg-yellow-500 text-white', '重点整改': 'bg-blue-500 text-white', '持续经营': 'bg-green-500 text-white' }
return <span className={`rounded px-2 py-0.5 text-xs ${colors[r.recommendation] || ''}`}>{r.recommendation}</span>
}},
{ key: 'reason', label: '原因' },
]}
/>
</CollapsibleSection>
</>
)}
{tab === 'grade' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="门店总数" value={gradeRows.length} format="number" description="参与分级的门店总数" />
<MetricCard title="平均综合分" value={avgScore} format="number" description="所有门店综合评分平均值" status={avgScore >= 75 ? 'good' : avgScore >= 60 ? 'warn' : 'bad'} />
<MetricCard title="A级门店" value={aGradeCount} format="number" description="综合分≥85的优秀门店" status="good" />
<MetricCard title="高风险门店" value={redRiskCount} format="number" description="风险等级红色的门店" status={redRiskCount > 0 ? 'bad' : 'good'} />
</div>
<div className="grid gap-4 lg:grid-cols-2">
<CollapsibleSection title="门店分级分布" subtitle="综合分=达成率40%+毛利率25%+会员占比15%+风险20% | A≥85 · B≥70 · C≥50 · D<50">
<ResponsiveContainer width="100%" height={250}>
<PieChart>
<Pie data={gradePieData} cx="50%" cy="50%" outerRadius={70} dataKey="value"
labelLine={false} label={({ name, value }: any) => <tspan fontSize={11}>{`${name}: ${value}`}</tspan>}>
{gradePieData.map((entry, i) => <Cell key={i} fill={GRADE_COLORS[entry.name[0]] || '#999'} />)}
</Pie>
<Tooltip formatter={(v: any) => [formatNumber(v), '门店数']} />
<Legend />
</PieChart>
</ResponsiveContainer>
</CollapsibleSection>
<CollapsibleSection title="风险等级分布" subtitle="风险模型基于毛利率、优惠率、异常率等指标综合评估">
<ResponsiveContainer width="100%" height={250}>
<PieChart>
<Pie data={riskPieData} cx="50%" cy="50%" outerRadius={70} dataKey="value"
labelLine={false} label={({ name, value }: any) => <tspan fontSize={11}>{`${name}: ${value}`}</tspan>}>
{riskPieData.map((entry, i) => <Cell key={i} fill={RISK_COLORS[entry.name] || '#999'} />)}
</Pie>
<Tooltip formatter={(v: any) => [formatNumber(v), '门店数']} />
<Legend />
</PieChart>
</ResponsiveContainer>
</CollapsibleSection>
</div>
<CollapsibleSection title={`门店分级明细 (${gradeRows.length})`} subtitle="综合分=达成率40%+毛利率25%+会员占比15%+风险20% | A≥85 · B≥70 · C≥50 · D<50">
<FilterableTable
data={gradeRows}
filterKey="grade"
filterLabel="全部分级"
sortOptions={[
{ key: 'overall_score', label: '综合分' },
{ key: 'revenue_achievement_pct', label: '达成率' },
{ key: 'store_name', label: '门店' },
]}
defaultSort="overall_score"
defaultOrder="desc"
onRowClick={(r) => setSelectedStore(r)}
columns={[
{ key: 'store_code', label: '门店编码' },
{ key: 'store_name', label: '门店名称' },
{ key: 'region', label: '区域' },
{ key: 'grade', label: '分级', align: 'center', render: (r) => {
const colors: Record<string, string> = { A: 'text-green-600', B: 'text-blue-600', C: 'text-yellow-600', D: 'text-red-600' }
return <span className={`font-bold ${colors[r.grade] || ''}`}>{r.grade}</span>
}},
{ key: 'risk_level', label: '风险', align: 'center', render: (r) => {
const colors: Record<string, string> = { '红色': 'bg-red-500 text-white', '黄色': 'bg-yellow-500 text-white', '绿色': 'bg-green-500 text-white' }
return <span className={`rounded px-2 py-0.5 text-xs ${colors[r.risk_level] || ''}`}>{r.risk_level || '-'}</span>
}},
{ key: 'overall_score', label: '综合分', align: 'right', render: (r) => Number(r.overall_score || 0).toFixed(1) },
{ key: 'revenue_achievement_pct', label: '营收达成率', align: 'right', render: (r) => {
const v = Number(r.revenue_achievement_pct || 0)
return <span className={v >= 100 ? 'text-green-600' : v >= 80 ? 'text-yellow-600' : 'text-red-600'}>{v.toFixed(1)}%</span>
}},
{ key: 'reason', label: '分级原因' },
]}
/>
</CollapsibleSection>
{selectedStore && <StoreDetailModal store={selectedStore} onClose={() => setSelectedStore(null)} />}
</>
)}
</div>
)
}
const GRADE_DIMENSIONS = [
{ key: 'revenue_achievement_pct', label: '营收达成', max: 100 },
{ key: 'overall_score', label: '综合分', max: 100 },
{ key: 'margin_pct', label: '毛利率', max: 50 },
{ key: 'anomaly_rate', label: '异常率', max: 20, inverse: true },
]
function StoreDetailModal({ store, onClose }: { store: any; onClose: () => void }) {
const gradeColor = GRADE_COLORS[store.grade] || '#999'
const riskColor = RISK_COLORS[store.risk_level] || '#999'
const radarData = GRADE_DIMENSIONS.map(d => {
const raw = Number(store[d.key] || 0)
const pct = d.inverse ? Math.max(0, 100 - (raw / d.max) * 100) : Math.min((raw / d.max) * 100, 100)
return { dimension: d.label, score: Math.round(pct), fullMark: 100 }
})
const metrics = [
{ label: '门店编码', value: store.store_code },
{ label: '区域', value: store.region || '-' },
{ label: '分级', value: store.grade, color: gradeColor },
{ label: '综合分', value: Number(store.overall_score || 0).toFixed(1) },
{ label: '营收达成率', value: `${Number(store.revenue_achievement_pct || 0).toFixed(1)}%` },
{ label: '营收', value: formatCurrency(store.revenue) },
{ label: '毛利率', value: formatPercent(store.margin_pct) },
{ label: '优惠率', value: store.discount_rate != null ? `${Number(store.discount_rate).toFixed(1)}%` : '-' },
{ label: '异常率', value: store.anomaly_rate != null ? `${Number(store.anomaly_rate).toFixed(1)}%` : '-' },
{ label: '会员占比', value: store.member_pct != null ? `${Number(store.member_pct).toFixed(1)}%` : '-' },
{ label: '客单价', value: formatCurrency(store.avg_bill_value) },
{ label: '活跃天数', value: store.active_days != null ? `${store.active_days}` : '-' },
{ label: '风险等级', value: store.risk_level || '-', color: riskColor },
]
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50" onClick={onClose}>
<div className="max-h-[90vh] w-full max-w-2xl overflow-y-auto rounded-lg border bg-card p-6 shadow-lg" onClick={(e) => e.stopPropagation()}>
<div className="flex items-start justify-between">
<div className="flex items-center gap-3">
<h2 className="text-lg font-bold">{store.store_name}</h2>
<span className="rounded px-2 py-0.5 text-xs font-bold text-white" style={{ background: gradeColor }}>{store.grade}</span>
<span className="rounded px-2 py-0.5 text-xs font-medium text-white" style={{ background: riskColor }}>
{store.risk_level || '-'}
</span>
</div>
<button onClick={onClose} className="text-muted-foreground hover:text-foreground text-xl"></button>
</div>
<div className="mt-4 grid gap-4 md:grid-cols-2">
<div>
<ResponsiveContainer width="100%" height={250}>
<RadarChart data={radarData}>
<PolarGrid />
<PolarAngleAxis dataKey="dimension" tick={{ fontSize: 10 }} />
<PolarRadiusAxis angle={90} domain={[0, 100]} tick={{ fontSize: 8 }} />
<Radar dataKey="score" name="得分" stroke={gradeColor} fill={gradeColor} fillOpacity={0.3} />
<Tooltip formatter={(v: any) => [v, '得分']} />
</RadarChart>
</ResponsiveContainer>
</div>
<div className="space-y-2">
{metrics.map(m => (
<div key={m.label} className="flex items-center justify-between border-b pb-1 text-sm">
<span className="text-muted-foreground">{m.label}</span>
<span className="font-medium" style={m.color ? { color: m.color } : undefined}>{m.value}</span>
</div>
))}
{store.reason && (
<div className="pt-2 text-xs text-muted-foreground">
<span className="font-medium"></span>{store.reason}
</div>
)}
{store.primary_issue && (
<div className="pt-1 text-xs text-muted-foreground">
<span className="font-medium"></span>{store.primary_issue}
</div>
)}
</div>
</div>
</div>
</div>
)
}
+308
View File
@@ -0,0 +1,308 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import api from '@/lib/api'
import { FilterableTable } from '@/components/FilterableTable'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { CollapsibleSection } from '@/components/CollapsibleSection'
import { MetricCard } from '@/components/MetricCard'
import { Tabs } from '@/components/Tabs'
import { formatCurrency, formatNumber, formatPercent } from '@/lib/utils'
import { useState } from 'react'
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts'
import { MonthPicker } from '@/components/MonthPicker'
const GRADE_COLORS: Record<string, string> = { A: '#22c55e', B: '#3b82f6', C: '#eab308', D: '#ef4444' }
export function TargetManagementPage() {
const [tab, setTab] = useState('overview')
const [month, setMonth] = useState('2026-04')
const year = parseInt(month.split('-')[0])
const queryClient = useQueryClient()
const { data: annualData, isLoading: annualLoading } = useQuery({
queryKey: ['target/annual', year],
queryFn: () => api.get('/target/annual', { params: { year } }),
})
const { data: regionalData, isLoading: regionalLoading } = useQuery({
queryKey: ['target/regional', year],
queryFn: () => api.get('/target/regional', { params: { year } }),
})
const { data: storeMonthlyData, isLoading: storeLoading } = useQuery({
queryKey: ['target/store-monthly', month],
queryFn: () => api.get('/target/store-monthly', { params: { month: month + '-01' } }),
})
const { data: achievementData, isLoading: achievementLoading } = useQuery({
queryKey: ['target/achievement', month],
queryFn: () => api.get('/target/achievement', { params: { month: month + '-01' } }),
})
const decomposeMutation = useMutation({
mutationFn: (data: { year: number; month?: string }) =>
api.post('/target/decompose/annual-to-store', data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['target/store-monthly'] })
queryClient.invalidateQueries({ queryKey: ['target/achievement'] })
},
})
const dailyDecomposeMutation = useMutation({
mutationFn: (data: { month: string }) =>
api.post('/target/decompose/monthly-to-daily', data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['target/daily'] })
},
})
const annualRows = (annualData as any)?.data || []
const regionalRows = (regionalData as any)?.data || []
const storeRows = (storeMonthlyData as any)?.data || []
const achievementRows = (achievementData as any)?.data || []
const revenueTarget = annualRows.find((r: any) => r.metric === 'revenue')
const profitTarget = annualRows.find((r: any) => r.metric === 'profit')
const storeCountTarget = annualRows.find((r: any) => r.metric === 'store_count')
const memberCountTarget = annualRows.find((r: any) => r.metric === 'member_count')
const totalStoreTarget = storeRows.reduce((s: number, r: any) => s + Number(r.revenue_target || 0), 0)
const avgAchievement = achievementRows.length > 0
? achievementRows.reduce((s: number, r: any) => s + Number(r.achievement_rate || 0), 0) / achievementRows.length
: 0
const achievedCount = achievementRows.filter((r: any) => Number(r.achievement_rate || 0) >= 100).length
const lowAchievementCount = achievementRows.filter((r: any) => Number(r.achievement_rate || 0) < 80).length
const gradeDistribution = storeRows.reduce((acc: Record<string, number>, r: any) => {
const g = r.grade || 'B'
acc[g] = (acc[g] || 0) + 1
return acc
}, {})
const gradePieData = Object.entries(gradeDistribution).map(([name, value]) => ({ name: `${name}`, value }))
const achievementChartData = achievementRows.slice(0, 20).map((r: any) => ({
name: r.store_name?.length > 6 ? r.store_name.slice(0, 6) : r.store_name,
达成率: Number(r.achievement_rate || 0),
}))
const pageLoading = annualLoading || regionalLoading || storeLoading || achievementLoading
if (pageLoading && tab === 'overview') {
return <LoadingSpinner text="加载目标管理数据..." />
}
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<h1 className="text-xl font-bold"></h1>
<p className="mt-0.5 text-xs text-muted-foreground"> · · · </p>
</div>
<MonthPicker month={month} onChange={setMonth} />
</div>
<Tabs
tabs={[
{ key: 'overview', label: '目标概览' },
{ key: 'annual', label: '年度目标' },
{ key: 'regional', label: '区域拆解' },
{ key: 'store', label: '门店月度' },
{ key: 'achievement', label: '达成率' },
]}
active={tab}
onChange={setTab}
/>
{tab === 'overview' && (
<>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="年度营收目标" value={revenueTarget?.target_value || 0} format="currency" description={`${year}年年度战略营收目标`} />
<MetricCard title="年度利润目标" value={profitTarget?.target_value || 0} format="currency" description={`${year}年年度战略利润目标`} />
<MetricCard title="门店月度目标总额" value={totalStoreTarget} format="currency" description={`${month}月所有门店营收目标合计`} />
<MetricCard title="平均达成率" value={avgAchievement} format="percent" description="所有门店达成率的平均值" status={avgAchievement >= 90 ? 'good' : avgAchievement >= 70 ? 'warn' : 'bad'} />
</div>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
<MetricCard title="目标门店数" value={storeCountTarget?.target_value || 0} format="number" description={`${year}年目标门店数`} />
<MetricCard title="目标会员数" value={memberCountTarget?.target_value || 0} format="number" description={`${year}年目标会员数`} />
<MetricCard title="达标门店数" value={achievedCount} format="number" description="达成率≥100%的门店数" status="good" />
<MetricCard title="低达成门店(<80%)" value={lowAchievementCount} format="number" description="达成率<80%的门店数,需重点关注" status={lowAchievementCount > 0 ? 'bad' : 'good'} />
</div>
<div className="grid gap-4 lg:grid-cols-2">
<CollapsibleSection title="门店达成率TOP20" subtitle="按达成率降序">
<ResponsiveContainer width="100%" height={250}>
<BarChart data={achievementChartData} margin={{ top: 20, right: 20, bottom: 20, left: 20 }}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" tick={{ fontSize: 10 }} angle={-30} textAnchor="end" height={60} />
<YAxis tickFormatter={(v) => `${v}%`} tick={{ fontSize: 10 }} />
<Tooltip formatter={(v: any) => [`${Number(v).toFixed(1)}%`, '达成率']} />
<Legend />
<Bar dataKey="达成率" fill="#3b82f6" />
</BarChart>
</ResponsiveContainer>
</CollapsibleSection>
<CollapsibleSection title="门店分级分布" subtitle="A/B/C/D级门店数量">
<ResponsiveContainer width="100%" height={250}>
<PieChart>
<Pie data={gradePieData} cx="50%" cy="50%" outerRadius={70} dataKey="value"
labelLine={false} label={({ name, value }: any) => <tspan fontSize={11}>{`${name}: ${value}`}</tspan>}>
{gradePieData.map((entry, i) => <Cell key={i} fill={GRADE_COLORS[entry.name[0]] || '#999'} />)}
</Pie>
<Tooltip formatter={(v: any) => [formatNumber(v), '门店数']} />
<Legend />
</PieChart>
</ResponsiveContainer>
</CollapsibleSection>
</div>
<CollapsibleSection title="目标拆解操作" subtitle="自动拆解年度目标到门店月度">
<div className="flex gap-3">
<button
onClick={() => decomposeMutation.mutate({ year, month: month + '-01' })}
disabled={decomposeMutation.isPending}
className="rounded bg-primary px-4 py-2 text-sm text-primary-foreground disabled:opacity-50"
>
{decomposeMutation.isPending ? '拆解中...' : `年度→门店月度拆解 (${month})`}
</button>
<button
onClick={() => dailyDecomposeMutation.mutate({ month: month + '-01' })}
disabled={dailyDecomposeMutation.isPending}
className="rounded bg-primary px-4 py-2 text-sm text-primary-foreground disabled:opacity-50"
>
{dailyDecomposeMutation.isPending ? '拆解中...' : `月度→日目标拆解 (${month})`}
</button>
{decomposeMutation.data && (
<span className="self-center text-sm text-green-600">
: {(decomposeMutation.data as any)?.data?.stores || 0}
</span>
)}
</div>
</CollapsibleSection>
</>
)}
{tab === 'annual' && (
<CollapsibleSection title="年度战略目标" subtitle={`${year}年战略目标设定`}>
<FilterableTable
data={annualRows}
sortOptions={[
{ key: 'metric', label: '指标' },
{ key: 'target_value', label: '目标值' },
]}
defaultSort="metric"
defaultOrder="asc"
columns={[
{ key: 'year', label: '年份', align: 'center' },
{ key: 'metric', label: '指标', render: (r) => {
const labels: Record<string, string> = { revenue: '营收', profit: '利润', store_count: '门店数', member_count: '会员数' }
return labels[r.metric] || r.metric
}},
{ key: 'target_value', label: '目标值', align: 'right', render: (r) => {
if (r.metric === 'revenue' || r.metric === 'profit') return formatCurrency(r.target_value)
return formatNumber(r.target_value)
}},
{ key: 'description', label: '说明' },
{ key: 'created_by', label: '创建人' },
]}
/>
</CollapsibleSection>
)}
{tab === 'regional' && (
<CollapsibleSection title="区域年度目标" subtitle={`${year}年各区域目标拆解`}>
<FilterableTable
data={regionalRows}
sortOptions={[
{ key: 'region', label: '区域' },
{ key: 'revenue_target', label: '营收目标' },
{ key: 'weight_pct', label: '权重' },
]}
defaultSort="region"
defaultOrder="asc"
columns={[
{ key: 'region', label: '区域' },
{ key: 'revenue_target', label: '营收目标', align: 'right', render: (r) => formatCurrency(r.revenue_target) },
{ key: 'profit_target', label: '利润目标', align: 'right', render: (r) => formatCurrency(r.profit_target) },
{ key: 'store_count_target', label: '门店数目标', align: 'right', render: (r) => formatNumber(r.store_count_target) },
{ key: 'member_count_target', label: '会员数目标', align: 'right', render: (r) => formatNumber(r.member_count_target) },
{ key: 'weight_pct', label: '权重', align: 'right', render: (r) => formatPercent(r.weight_pct) },
]}
/>
</CollapsibleSection>
)}
{tab === 'store' && (
<CollapsibleSection title={`门店月度目标 (${storeRows.length})`} subtitle={`${month}月各门店目标`}>
<FilterableTable
data={storeRows}
filterKey="region"
filterLabel="全部区域"
sortOptions={[
{ key: 'store_code', label: '门店编码' },
{ key: 'revenue_target', label: '营收目标' },
{ key: 'grade', label: '分级' },
]}
defaultSort="store_code"
defaultOrder="asc"
columns={[
{ key: 'store_code', label: '门店编码' },
{ key: 'store_name', label: '门店名称' },
{ key: 'region', label: '区域' },
{ key: 'grade', label: '分级', align: 'center', render: (r) => {
const colors: Record<string, string> = { A: 'text-green-600', B: 'text-blue-600', C: 'text-yellow-600', D: 'text-red-600' }
return <span className={`font-bold ${colors[r.grade] || ''}`}>{r.grade}</span>
}},
{ key: 'revenue_target', label: '营收目标', align: 'right', render: (r) => formatCurrency(r.revenue_target) },
{ key: 'bill_count_target', label: '账单数目标', align: 'right', render: (r) => formatNumber(r.bill_count_target) },
{ key: 'avg_bill_value_target', label: '客单价目标', align: 'right', render: (r) => formatCurrency(r.avg_bill_value_target) },
{ key: 'member_penetration_target', label: '会员渗透率', align: 'right', render: (r) => formatPercent(r.member_penetration_target) },
{ key: 'cost_rate_target', label: '成本率', align: 'right', render: (r) => formatPercent(r.cost_rate_target) },
]}
/>
</CollapsibleSection>
)}
{tab === 'achievement' && (
<CollapsibleSection title={`门店达成率 (${achievementRows.length})`} subtitle={`${month}月各门店目标达成率`}>
{achievementLoading ? <LoadingSpinner text="加载达成率数据..." /> : (
<FilterableTable
data={achievementRows}
filterKey="region"
filterLabel="全部区域"
sortOptions={[
{ key: 'achievement_rate', label: '达成率' },
{ key: 'revenue_target', label: '目标' },
{ key: 'actual_revenue', label: '实际' },
{ key: 'bill_achievement_rate', label: '账单达成率' },
]}
defaultSort="achievement_rate"
defaultOrder="desc"
columns={[
{ key: 'store_code', label: '门店编码' },
{ key: 'store_name', label: '门店名称' },
{ key: 'region', label: '区域' },
{ key: 'grade', label: '分级', align: 'center', render: (r) => {
const colors: Record<string, string> = { A: 'text-green-600', B: 'text-blue-600', C: 'text-yellow-600', D: 'text-red-600' }
return <span className={`font-bold ${colors[r.grade] || ''}`}>{r.grade}</span>
}},
{ key: 'revenue_target', label: '营收目标', align: 'right', render: (r) => formatCurrency(r.revenue_target) },
{ key: 'actual_revenue', label: '实际营收', align: 'right', render: (r) => formatCurrency(r.actual_revenue) },
{ key: 'achievement_rate', label: '达成率', align: 'right', render: (r) => {
const v = Number(r.achievement_rate || 0)
return <span className={v >= 100 ? 'font-medium text-green-600' : v >= 80 ? 'text-yellow-600' : 'font-medium text-red-600'}>{v.toFixed(1)}%</span>
}},
{ key: 'bill_count_target', label: '账单目标', align: 'right', render: (r) => formatNumber(r.bill_count_target) },
{ key: 'actual_bill_count', label: '实际账单', align: 'right', render: (r) => formatNumber(r.actual_bill_count) },
{ key: 'bill_achievement_rate', label: '账单达成率', align: 'right', render: (r) => {
const v = Number(r.bill_achievement_rate || 0)
return <span className={v >= 100 ? 'text-green-600' : v >= 80 ? 'text-yellow-600' : 'text-red-600'}>{v.toFixed(1)}%</span>
}},
]}
/>
)}
</CollapsibleSection>
)}
</div>
)
}
+32 -1
View File
@@ -1,5 +1,6 @@
import { useQuery } from '@tanstack/react-query'
import { useNavigate } from 'react-router-dom'
import { ChevronRight } from 'lucide-react'
import api from '@/lib/api'
import { Badge } from '@/components/Badge'
import { FilterableTable } from '@/components/FilterableTable'
@@ -10,7 +11,7 @@ import { useState, useMemo } from 'react'
export function TasksPage() {
const navigate = useNavigate()
const [month, setMonth] = useState('2026-04')
const [month, setMonth] = useState('2026-05')
const [priority, setPriority] = useState('')
const [status, setStatus] = useState('')
@@ -18,6 +19,11 @@ export function TasksPage() {
queryKey: ['tasks', month, priority, status],
queryFn: () => api.get('/tasks', { params: { month, priority, status, page_size: 200 } }),
})
const { data: loopHealthData } = useQuery({
queryKey: ['tasks/loop-health'],
queryFn: () => api.get('/tasks/loop-health'),
staleTime: 5 * 60 * 1000,
})
const tasks = (data as any)?.data || []
const total = (data as any)?.meta?.total || 0
@@ -49,6 +55,31 @@ export function TasksPage() {
</div>
</div>
{/* 闭环流程条 */}
<div className="flex flex-wrap items-center gap-1 rounded-lg border bg-card p-3">
{[
{ label: '信号发现', sub: '风险门店', count: String((loopHealthData as any)?.data?.signal_count ?? 0), rate: (loopHealthData as any)?.data?.task_generation_rate, rateLabel: '任务生成率' },
{ label: '决策审批', sub: '全部任务', count: String(tasks.length), rate: null, rateLabel: '' },
{ label: '任务执行', sub: '执行中任务', count: String(total), rate: (loopHealthData as any)?.data?.store_execution_rate, rateLabel: '门店执行率' },
{ label: '周期检查', sub: '周检覆盖', count: '-', rate: (loopHealthData as any)?.data?.weekly_check_rate, rateLabel: '周检率' },
{ label: '收益验收', sub: '已验收任务', count: String(tasks.filter((t: any) => t.status === '已验收').length), rate: (loopHealthData as any)?.data?.monthly_review_rate, rateLabel: '月验收率' },
{ label: '经验标准化', sub: '标准实践', count: String((loopHealthData as any)?.data?.practice_count ?? 0), rate: (loopHealthData as any)?.data?.practice_promotion_rate, rateLabel: '推广率' },
].map((stage, i, arr) => (
<div key={stage.label} className="flex items-center gap-1">
<div className="flex flex-col items-center px-2">
<span className={`flex h-6 w-6 items-center justify-center rounded-full text-[10px] font-bold ${i === 0 ? 'bg-blue-600 text-white' : 'bg-muted text-muted-foreground'}`}>
{i + 1}
</span>
<small className="mt-1 text-[10px] font-medium text-foreground">{stage.label}</small>
<small className="text-[9px] text-muted-foreground">{stage.sub}</small>
<b className="text-sm font-bold">{stage.count}</b>
{stage.rate != null && <em className="text-[10px] text-green-600">{Math.round(Number(stage.rate) * 100) / 100}% {stage.rateLabel}</em>}
</div>
{i < arr.length - 1 && <ChevronRight className="h-4 w-4 text-muted-foreground" />}
</div>
))}
</div>
{/* 筛选器 */}
<div className="flex flex-wrap gap-2">
<SearchSelect
-1
View File
@@ -12,7 +12,6 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
+67
View File
@@ -0,0 +1,67 @@
# 数据导入与物化刷新流水线
## 目录结构
```
db/pipeline/
├── README.md ← 本文件
├── config.py ← 数据源路径与数据库配置
├── run_all.py ← 一键全量导入+物化刷新
├── refresh_materialized_views.py ← 物化视图按依赖顺序刷新
├── verify.py ← 测试库与正式库行数对比验证
├── verify_import.py ← 详细数据对比验证
├── import_bill_records.py ← 账单查询原始数据导入(4月格式,196列宽表)
├── import_bill_records_may.py ← 5月专用账单导入(51列全渠道订单明细→bill_records + 50列品项销售明细→dish_sales_details
├── import_monthly_data.py ← 月度业务数据导入(库存/销售/成本/费用/中央厨房/配送)
├── import_salary_attendance.py ← 薪资考勤数据导入
├── import_store_location.py ← 门店位置与映射表导入
└── import_derived_data.py ← 派生分析数据生成
```
## 导入脚本
| 脚本 | 数据表 | 数据源 |
|------|--------|--------|
| `import_bill_records.py` | bill_records, bill_columns | 账单查询 Excel 目录(17个文件) |
| `import_monthly_data.py` | inventory_cost_records, dish_sales_details, dish_cost_analysis_*, operating_expense_records, central_kitchen_*, distribution_detail_records | 各业务 Excel 文件 |
| `import_salary_attendance.py` | salary_detail_records, attendance_records | 薪资/考勤 Excel |
| `import_store_location.py` | store_location_master, store_location_source_rows, sales_store_location_mapping, store_name_mapping, inventory_store_mapping, operating_expense_store_mapping | 各店信息 Excel |
| `import_derived_data.py` | dish_diagnosis_snapshot, central_kitchen_manufacturing_cost_pool | 从已有表派生 |
## 物化视图刷新顺序(按依赖分层)
| 层级 | 物化视图 | 依赖 |
|------|----------|------|
| L0 | bill_fact | 基础表 |
| L1 | mv_daily_revenue, mv_dish_basket_monthly, mv_dish_pair_summary_monthly, mv_dish_sku_summary_monthly, mv_dish_store_summary_monthly, mv_district_site_benchmark_monthly, mv_inventory_cost_classified_monthly, mv_site_segment_benchmark_monthly, mv_store_*_monthly (12个), mv_store_scorecard | bill_fact |
| L1 | dish_sales_april | bill_fact |
| L2 | dish_basket_april, dish_category_summary_april, dish_member_sku_april, dish_sku_summary_april, dish_store_sku_april | dish_sales_april |
| L2 | mv_dish_sku_abc_monthly | mv_dish_sku_summary_monthly |
| L2 | v_store_benchmark, v_store_category_mix, v_store_platform_economics | bill_fact |
| L3 | dish_store_summary_april | dish_basket_april |
| L3 | v_store_action_list | v_store_benchmark, v_store_category_mix, v_store_platform_economics |
| L3 | mv_store_action_priority_deep_april, mv_store_theoretical_actual_cost_april | bill_fact / dish_store_summary_april |
| L4 | v_store_execution_priority | v_store_action_list |
## 使用方法
### 一键全量导入
```bash
python3 db/pipeline/run_all.py --month 2026-04-01 --db bill_query_test
```
### 仅刷新物化视图
```bash
python3 db/pipeline/refresh_materialized_views.py --db bill_query_test
```
### 验证数据一致性
```bash
python3 db/pipeline/verify.py --db bill_query_test
```
### 单独导入某类数据
参见各脚本 `--help`,例如:
```bash
python3 db/pipeline/import_monthly_data.py --dataset inventory --month 2026-04-01 --file <path> --db bill_query_test
```
+264
View File
@@ -0,0 +1,264 @@
#!/usr/bin/env python3
"""
数据导入流水线配置
统一管理数据源路径数据库连接参数导入脚本路径
"""
import os
import glob
import sys
# ============================================================
# 路径常量
# ============================================================
PIPELINE_DIR = os.path.dirname(os.path.abspath(__file__))
DB_DIR = os.path.dirname(PIPELINE_DIR)
BASE_DIR = os.path.dirname(DB_DIR)
# 数据源根目录(西部马华数据分析 下有完整的业务数据)
DATA_ROOT = os.path.join(os.path.dirname(BASE_DIR), '西部马华数据分析')
# SBrainCO3 数据目录(部分文件只在这里有)
DATA_SBRAIN = os.path.join(BASE_DIR, '数据')
# ============================================================
# 数据库配置
# ============================================================
DB_CONFIG = {
'host': 'localhost',
'port': 5432,
'user': 'freedak',
'password': '',
}
# ============================================================
# 月份配置
# ============================================================
MONTH_CONFIG = {
'2026-04-01': {
'month_dir': '4月',
'date_range': '2026-04-01--2026-04-30',
'dist_half1': '2026年4月1-15日',
'dist_half2': '2026年4月16-30日',
'inventory_file': '4.13盘点倒挤成本报表2026年4月明细.xlsx',
'dish_cost_file': '菜品成本分析报表.xlsx',
'expense_file': '2026年4月营业费用分析.xls',
'ck_subdir': '中央厨房4月',
'salary_file': '薪资拆分明细表_脱敏.xlsx',
'attendance_file': '考勤数据表-脱敏.xlsx',
'store_info_file': '各店信息新(20260508.xls',
'bill_records_subdir': '账单查询',
'dish_sales_subdir': '账单查询-菜品销售明细表',
'data_subdirs': {}, # 4月文件平铺在月份目录下
},
'2026-05-01': {
'month_dir': '5月',
'date_range': '2026-05-01--2026-05-31',
'dist_half1': '2026年5月1-15日',
'dist_half2': '2026年5月16-31日',
'inventory_file': '4.13盘点倒挤成本报表2026年5月.xlsx',
'dish_cost_file': '2026年5月菜品成本分析报表.xlsx',
'expense_file': '2026年5月营业费用分析.xls',
'ck_subdir': '中央厨房',
'salary_file': '2026年5月薪资拆分明细表_北京西部马华餐饮有限公司.xlsx',
'attendance_file': '2026年5月考勤数据表.xlsx',
'store_info_file': None, # 5月无新各店信息文件,复用4月
'bill_records_subdir': None, # 5月无独立账单查询目录
'dish_sales_subdir': '账单查询-菜品销售明细表',
'data_subdirs': { # 5月文件在子目录中
'inventory': '供应链数据',
'dish_cost': '营业数据',
'operating_expense': '',
'distribution': '供应链数据',
'salary': '营业数据',
'attendance': '营业数据',
'central_kitchen': '中央厨房',
'dish_sales': '营业数据',
},
},
}
def _find_file(base_dirs, pattern):
"""在多个候选目录中查找文件"""
for d in base_dirs:
if not d:
continue
path = os.path.join(d, pattern)
if os.path.isfile(path):
return path
matches = glob.glob(os.path.join(d, pattern))
if matches:
return matches[0]
return None
def get_data_sources(month):
"""
根据月份返回数据源路径字典
month: 'YYYY-MM-01' 格式
"""
cfg = MONTH_CONFIG.get(month)
if not cfg:
print(f"警告: 未知月份 {month},请在 config.py MONTH_CONFIG 中添加配置")
return {}
month_dir = cfg['month_dir']
data_dir = os.path.join(DATA_ROOT, month_dir)
sbrain_data = os.path.join(DATA_SBRAIN, month_dir)
subdirs = cfg.get('data_subdirs', {})
sources = {}
def resolve(subdir_key, filename):
"""在 data_dir 和 sbrain_data 中按子目录结构查找文件"""
sub = subdirs.get(subdir_key, '')
candidates = []
if sub:
candidates.append(os.path.join(sbrain_data, sub, filename))
candidates.append(os.path.join(data_dir, sub, filename))
candidates.append(os.path.join(sbrain_data, filename))
candidates.append(os.path.join(data_dir, filename))
for c in candidates:
if os.path.isfile(c):
return c
return candidates[0]
def resolve_dir(subdir_key, dirname):
"""在 data_dir 和 sbrain_data 中按子目录结构查找目录"""
sub = subdirs.get(subdir_key, '')
candidates = []
if sub:
candidates.append(os.path.join(sbrain_data, sub, dirname))
candidates.append(os.path.join(data_dir, sub, dirname))
candidates.append(os.path.join(sbrain_data, dirname))
candidates.append(os.path.join(data_dir, dirname))
for c in candidates:
if os.path.isdir(c):
return c
return candidates[0]
# 1. 账单查询(bill_records- 目录
bill_subdir = cfg.get('bill_records_subdir')
if bill_subdir:
sources['bill_records'] = resolve_dir('bill_records', bill_subdir)
else:
sources['bill_records'] = None
# 2. 菜品销售明细 - 目录
sources['dish_sales'] = resolve_dir('dish_sales', cfg['dish_sales_subdir'])
# 3. 库存成本
sources['inventory'] = resolve('inventory', cfg['inventory_file'])
# 4. 菜品成本BOM
sources['dish_cost'] = resolve('dish_cost', cfg['dish_cost_file'])
# 5. 营业费用
sources['operating_expense'] = resolve('operating_expense', cfg['expense_file'])
# 6. 中央厨房(4个子文件)
ck_subdir = cfg['ck_subdir']
ck_dir_sbrain = os.path.join(sbrain_data, ck_subdir)
ck_dir_data = os.path.join(data_dir, ck_subdir)
ck_dir = ck_dir_sbrain if os.path.isdir(ck_dir_sbrain) else ck_dir_data
date_range = cfg['date_range']
sources['central_kitchen_finished'] = _find_file(
[ck_dir], f'{date_range} 23 59 59完工入库统计分析报表.xlsx'
) or os.path.join(ck_dir, f'{date_range} 23 59 59完工入库统计分析报表.xlsx')
sources['central_kitchen_recipe'] = _find_file(
[ck_dir], f'按配方导出-货品实际与理论耗用({date_range}).xlsx'
) or os.path.join(ck_dir, f'按配方导出-货品实际与理论耗用({date_range}).xlsx')
sources['central_kitchen_material'] = _find_file(
[ck_dir], f'按货品导出-货品实际与理论耗用({date_range}).xlsx'
) or os.path.join(ck_dir, f'按货品导出-货品实际与理论耗用({date_range}).xlsx')
sources['central_kitchen_processing'] = _find_file(
[ck_dir], '加工单价分析报表.xlsx'
) or os.path.join(ck_dir, '加工单价分析报表.xlsx')
# 7. 配送明细(2个文件)
sources['distribution'] = resolve('distribution', f'全部门店-全部仓库-统计货品明细报表{cfg["dist_half1"]}.xlsx')
sources['distribution_2'] = resolve('distribution', f'全部门店-全部仓库-统计货品明细报表{cfg["dist_half2"]}.xlsx')
# 8. 薪资+考勤
sources['salary'] = resolve('salary', cfg['salary_file'])
sources['attendance'] = resolve('attendance', cfg['attendance_file'])
# 9. 门店位置
store_info_file = cfg.get('store_info_file')
if store_info_file:
sources['store_location'] = resolve('', store_info_file)
else:
# 5月无新文件,复用4月
for p in [
os.path.join(DATA_SBRAIN, '4月', '各店信息新(20260508.xls'),
os.path.join(DATA_ROOT, '4月', '各店信息新(20260508.xls'),
]:
if os.path.isfile(p):
sources['store_location'] = p
break
else:
sources['store_location'] = None
return sources
# ============================================================
# 物化视图刷新顺序(按依赖分层,同层可并行)
# ============================================================
MATVIEW_LAYERS = [
# L0: 基础物化视图,依赖基础表
['bill_fact'],
# L1: 依赖 bill_fact 或基础表
[
'mv_daily_revenue',
'mv_dish_basket_monthly',
'mv_dish_pair_summary_monthly',
'mv_dish_sku_summary_monthly',
'mv_dish_store_summary_monthly',
'mv_district_site_benchmark_monthly',
'mv_inventory_cost_classified_monthly',
'mv_site_segment_benchmark_monthly',
'mv_store_action_priority_deep_monthly',
'mv_store_area_efficiency_monthly',
'mv_store_benchmark_composite_monthly',
'mv_store_category_mix_monthly',
'mv_store_deep_diagnosis_monthly',
'mv_store_member_opportunity_monthly',
'mv_store_overlap_risk_monthly',
'mv_store_platform_economics_monthly',
'mv_store_repeat_summary_monthly',
'mv_store_risk_rating_monthly',
'mv_store_scorecard',
'mv_store_site_profile_monthly',
'mv_store_site_replication_monthly',
'mv_store_theoretical_actual_cost_monthly',
'dish_sales_april',
'v_store_benchmark',
'v_store_category_mix',
'v_store_platform_economics',
],
# L2: 依赖 L1 物化视图
[
'dish_basket_april',
'dish_category_summary_april',
'dish_member_sku_april',
'dish_sku_summary_april',
'dish_store_sku_april',
'mv_dish_sku_abc_monthly',
'v_store_action_list',
],
# L3: 依赖 L2
[
'dish_store_summary_april',
'mv_store_action_priority_deep_april',
'mv_store_theoretical_actual_cost_april',
'v_store_execution_priority',
],
]
def get_dbname():
"""获取默认数据库名"""
return 'bill_query_test'
+198
View File
@@ -0,0 +1,198 @@
#!/usr/bin/env python3
"""
账单查询原始数据导入脚本
从Excel文件导入bill_records和bill_columns表
用法:
python3 import_bill_records.py --month 2026-04-01 --file <文件或目录> --db bill_query_test
python3 import_bill_records.py --month 2026-04-01 --file <目录> --db bill_query_test --skip-columns
"""
import argparse
import hashlib
import os
import sys
import pandas as pd
import psycopg2
from psycopg2.extras import execute_values
def file_sha256(filepath):
h = hashlib.sha256()
with open(filepath, 'rb') as f:
for chunk in iter(lambda: f.read(8192), b''):
h.update(chunk)
return h.hexdigest()
def to_text(val):
if val is None:
return None
if isinstance(val, float) and pd.isna(val):
return None
s = str(val).strip()
if s.lower() in ('nan', 'none', ''):
return None
return s
def import_bill_columns(conn, filepaths):
"""从第一个Excel文件提取列定义,导入bill_columns表"""
cur = conn.cursor()
cur.execute("SELECT count(*) FROM public.bill_columns")
existing = cur.fetchone()[0]
if existing > 0:
print(f"bill_columns已有{existing}行,跳过列定义导入")
return
if not filepaths:
print("无文件可用,跳过列定义导入")
return
fpath = filepaths[0]
df = pd.read_excel(fpath, header=None, nrows=2, engine='openpyxl')
main_headers = df.iloc[0].tolist()
sub_headers = df.iloc[1].tolist()
columns = []
for i, (mh, sh) in enumerate(zip(main_headers, sub_headers)):
col_name = f"c{i+1:03d}"
group_h = to_text(mh) or ''
sub_h = to_text(sh) or ''
# If group and sub are the same, only keep group
if group_h and sub_h and group_h == sub_h:
sub_h = ''
columns.append((col_name, i + 1, group_h, sub_h))
execute_values(
cur,
"INSERT INTO public.bill_columns (column_name, excel_position, group_header, sub_header) VALUES %s",
columns,
page_size=500
)
conn.commit()
print(f"bill_columns导入完成: {len(columns)}")
cur.close()
def import_bill_records(conn, filepath, report_month):
"""导入单个Excel文件的账单数据到bill_records"""
fname = os.path.basename(filepath)
sha = file_sha256(filepath)
cur = conn.cursor()
# 幂等检查
cur.execute(
"SELECT 1 FROM public.bill_records WHERE source_file = %s LIMIT 1",
(fname,)
)
if cur.fetchone():
print(f" {fname} 已导入过,跳过")
cur.close()
return 0
# 读取Excelrow0=主表头, row1=子表头, 数据从row2开始
df = pd.read_excel(filepath, header=None, engine='openpyxl')
# 跳过前2行(表头)
data_df = df.iloc[2:]
# 过滤空行(第一列为空)
data_df = data_df.dropna(subset=[data_df.columns[0]])
data_rows = data_df.values.tolist()
print(f" 数据行数: {len(data_rows)}, 列数: {data_df.shape[1]}")
if not data_rows:
cur.close()
return 0
# 获取DB列名 (c001 ~ c196)
num_cols = data_df.shape[1]
col_names = [f"c{i+1:03d}" for i in range(num_cols)]
all_cols = ['source_file', 'source_row'] + col_names
col_str = ','.join(all_cols)
batch = []
for idx, row in enumerate(data_rows):
source_row = idx + 3 # 1-indexed, data starts at Excel row 3
vals = [fname, source_row]
for i in range(num_cols):
v = row[i] if i < len(row) else None
vals.append(to_text(v))
batch.append(tuple(vals))
if len(batch) >= 500:
execute_values(
cur,
f"INSERT INTO public.bill_records ({col_str}) VALUES %s",
batch,
page_size=500
)
conn.commit()
if (idx + 1) % 10000 == 0:
print(f" 已导入 {idx + 1}/{len(data_rows)}")
batch = []
if batch:
execute_values(
cur,
f"INSERT INTO public.bill_records ({col_str}) VALUES %s",
batch,
page_size=500
)
conn.commit()
print(f" 已导入 {len(data_rows)}/{len(data_rows)}")
cur.close()
return len(data_rows)
def main():
parser = argparse.ArgumentParser(description='账单查询原始数据导入')
parser.add_argument('--month', required=True, help='报告月份 (YYYY-MM-01)')
parser.add_argument('--file', required=True, help='Excel文件路径或目录')
parser.add_argument('--db', default='bill_query', help='目标数据库 (默认bill_query)')
parser.add_argument('--skip-columns', action='store_true', help='跳过bill_columns导入')
args = parser.parse_args()
conn = psycopg2.connect(host='localhost', port=5432, dbname=args.db, user='freedak')
conn.autocommit = False
# 收集文件
files = []
if os.path.isdir(args.file):
for f in sorted(os.listdir(args.file)):
if f.endswith('.xlsx') and not f.startswith('.'):
files.append(os.path.join(args.file, f))
else:
files.append(args.file)
print(f"\n=== 账单查询原始数据导入 ===")
print(f"文件数: {len(files)}")
print(f"数据库: {args.db}")
try:
# 导入列定义
if not args.skip_columns:
import_bill_columns(conn, files)
# 导入数据
total = 0
for idx, fpath in enumerate(files):
fname = os.path.basename(fpath)
print(f"\n[{idx+1}/{len(files)}] {fname}")
total += import_bill_records(conn, fpath, args.month)
print(f"\n账单数据导入完成: 共 {total}")
print("=== 导入完成 ===")
except Exception as e:
conn.rollback()
print(f"错误: {e}", file=sys.stderr)
raise
finally:
conn.close()
if __name__ == '__main__':
main()
+549
View File
@@ -0,0 +1,549 @@
#!/usr/bin/env python3
"""
5月账单数据导入脚本
将5月格式的"正餐事业部_全渠道订单明细"(51)导入bill_records(196列结构)
"正餐事业部_品项销售明细"(50)导入dish_sales_details
5月数据格式与4月不同
- 4: 账单查询196列宽表 + 菜品销售明细表(多文件)
- 5: 全渠道订单明细51列 + 品项销售明细50列 (各1个文件)
用法:
python3 import_bill_records_may.py --month 2026-05-01 \
--orders <全渠道订单明细.xlsx> \
--items <品项销售明细.xlsx> \
--db bill_query_test
"""
import argparse
import hashlib
import os
import re
import sys
import pandas as pd
import psycopg2
from psycopg2.extras import execute_values
DB_CONFIG = {
'host': 'localhost',
'port': 5432,
'user': 'freedak',
'password': '',
}
def file_sha256(filepath):
h = hashlib.sha256()
with open(filepath, 'rb') as f:
for chunk in iter(lambda: f.read(8192), b''):
h.update(chunk)
return h.hexdigest()
def to_text(val):
if val is None:
return None
if isinstance(val, float) and pd.isna(val):
return None
s = str(val).strip()
if s.lower() in ('nan', 'none', '', '--'):
return None
return s
def to_num(val):
if val is None:
return None
if isinstance(val, float) and pd.isna(val):
return None
s = str(val).strip().replace(',', '').replace('¥', '').replace('', '')
if s.lower() in ('nan', 'none', '', '--'):
return None
try:
return str(float(s))
except (ValueError, TypeError):
return None
def to_timestamp_str(val):
"""将日期/时间值转为字符串格式 YYYY/MM/DD HH:MM:SS"""
if val is None:
return None
if isinstance(val, float) and pd.isna(val):
return None
if isinstance(val, pd.Timestamp):
return val.strftime('%Y/%m/%d %H:%M:%S')
s = str(val).strip()
if s.lower() in ('nan', 'none', '', '--'):
return None
# 尝试解析各种日期格式
for fmt in ['%Y/%m/%d %H:%M:%S', '%Y-%m-%d %H:%M:%S', '%Y/%m/%d', '%Y-%m-%d']:
try:
ts = pd.to_datetime(s, format=fmt)
return ts.strftime('%Y/%m/%d %H:%M:%S')
except (ValueError, TypeError):
continue
# pandas通用解析
try:
ts = pd.to_datetime(s)
return ts.strftime('%Y/%m/%d %H:%M:%S')
except (ValueError, TypeError):
return s
# ============================================================
# 5月全渠道订单明细 → bill_records 列映射
# 5月col索引 → bill_records cXXX
# ============================================================
ORDERS_COL_MAP = {
# 5月col: (bill_records col_name, converter)
0: None, # 省份 → 无对应
1: None, # 城市 → 无对应
2: 'c003', # 门店名称 → c003 store_name
3: None, # 营业日期 → 无直接对应(bill_fact用closed_at)
4: 'c004', # 餐段 → c004 meal_period
5: 'c005', # 订单号 → c005 bill_no
6: None, # 原单号
7: None, # 外卖订单号
8: None, # 全渠道流水号
9: 'c008', # 取餐号 → c008 table_no
10: None, # 桌牌号
11: 'c006', # 桌台区域 → c006 business_area
12: 'c009', # 订单金额 → c009 consumption
13: None, # 顾客实付
14: 'c114', # 订单收入 → c114 received_total
15: 'c068', # 订单优惠 → c068 discount_total
16: None, # 订单来源
17: None, # 订单子来源
18: None, # 经营模式
19: None, # 用餐方式
20: None, # 宴会类型
21: 'c194', # 订单状态 → c194 bill_status
22: None, # 退单标识
23: 'c190', # 下单员 → c190 waiter
24: 'c191', # 收银员 → c191 cashier
25: None, # 桌台提成人
26: None, # 销售员 → c192 (不在bill_fact中,但可填)
27: 'c175', # 创建时间 → c175 opened_at
28: 'c176', # 完成时间 → c176 closed_at
29: None, # 接单时间
30: None, # 下单制作时间
31: None, # 预定用餐时间
32: None, # 订单备注
33: None, # 桌台备注
34: 'c178', # 用餐人数 → c178 guest_count
35: 'c179', # 席数 → c179 table_count
36: None, # 是否会员
37: None, # 会员姓名
38: 'c185', # 会员卡号 → c185 member_id
39: None, # 会员手机号
40: None, # 下单人手机号
41: None, # 发票
42: None, # 菜品金额
43: None, # 菜品收入
44: None, # 退单时间
45: None, # 取消时间
46: None, # 外卖订单已退金额
47: None, # 敏感操作
48: None, # 结账方式 → 需要解析支付方式
49: None, # 企业版订单
50: None, # 企业版订单是否开发票
}
# 结账方式解析 → bill_records支付方式列
PAYMENT_PATTERNS = {
'c140': [r'现金'], # 现金
'c143': [r'支付宝'], # 支付宝支付实收
'c144': [r'微信'], # 微信支付实收
'c145': [r'美团.*实收', r'大众点评.*实收', r'新美大实收', r'一键买单'], # 新美大实收
'c146': [r'云闪付'], # 云闪付实收
'c147': [r'抖音'], # 抖音券实收
'c151': [r'美团外卖'], # 美团外卖实收
'c152': [r'淘宝闪购', r'闪购'], # 淘宝闪购实收
'c150': [r'京东外卖'], # 京东外卖实收
'c149': [r'挂账'], # 挂账消费
}
# 折扣/佣金解析
DISCOUNT_PATTERNS = {
'c087': [r'会员积分'], # 会员积分抵现
'c088': [r'会员代金券'], # 会员代金券折扣
'c089': [r'会员预存'], # 会员预存折扣
'c095': [r'抖音.*折扣', r'抖音券折扣'], # 抖音券折扣
'c097': [r'美团.*佣金'], # 美团外卖佣金
'c098': [r'淘宝.*佣金', r'闪购.*佣金'], # 淘宝闪购佣金
'c100': [r'京东.*佣金'], # 京东外卖佣金
}
def parse_payment(payment_str):
"""解析结账方式字段,返回 {cXXX: amount_str}"""
result = {}
if not payment_str or payment_str == '--':
return result
# 格式: "方式1 金额1,方式2 金额2" 或 "方式1 金额1"
parts = payment_str.split(',')
for part in parts:
part = part.strip()
# 提取金额(最后一个数字)
amount_match = re.search(r'([\d.]+)\s*$', part)
amount = amount_match.group(1) if amount_match else None
if not amount:
continue
# 匹配支付方式
for col, patterns in PAYMENT_PATTERNS.items():
if col in result:
continue
for pat in patterns:
if re.search(pat, part):
if col in result:
result[col] = str(float(result[col]) + float(amount))
else:
result[col] = amount
break
return result
def parse_discounts(discount_str):
"""解析折扣字段"""
return parse_payment(discount_str) # 同样的解析逻辑
def build_store_code_map(items_filepath):
"""从品项销售明细中构建 门店名称→机构编码 映射"""
df = pd.read_excel(items_filepath, header=2, engine='openpyxl')
df = df.dropna(subset=[df.columns[0]])
mapping = {}
if '门店名称' in df.columns and '机构编码' in df.columns:
for _, row in df[['门店名称', '机构编码']].drop_duplicates().iterrows():
name = str(row['门店名称']).strip()
code = str(row['机构编码']).strip()
if name and code and name != 'nan' and code != 'nan' and code != '--':
mapping[name] = code
print(f" 门店编码映射: {len(mapping)} 个门店")
for name, code in sorted(mapping.items()):
print(f" {code}{name}")
return mapping
def import_bill_records_may(conn, orders_filepath, store_code_map, report_month):
"""将5月全渠道订单明细导入bill_records"""
fname = os.path.basename(orders_filepath)
sha = file_sha256(orders_filepath)
cur = conn.cursor()
# 幂等检查
cur.execute(
"SELECT 1 FROM public.bill_records WHERE source_file = %s LIMIT 1",
(fname,)
)
if cur.fetchone():
print(f" {fname} 已导入过,跳过")
cur.close()
return 0
# 读取Excelrow0=标题, row1=日期范围, row2=列头, row3+=数据
df = pd.read_excel(orders_filepath, header=2, engine='openpyxl')
df = df.dropna(subset=[df.columns[0]])
data_rows = df.values.tolist()
print(f" 数据行数: {len(data_rows)}, 列数: {df.shape[1]}")
if not data_rows:
cur.close()
return 0
# 构建196列的列名
all_col_names = [f"c{i+1:03d}" for i in range(196)]
insert_cols = ['source_file', 'source_row'] + all_col_names
col_str = ','.join(insert_cols)
# 反转映射: 5月col_index → cXXX
col_to_c = {}
for may_col, c_name in ORDERS_COL_MAP.items():
if c_name:
col_to_c[may_col] = c_name
batch = []
for idx, row in enumerate(data_rows):
source_row = idx + 4 # 数据从Excel第4行开始(1-indexed)
# 初始化196列全为None
c_vals = {f"c{i+1:03d}": None for i in range(196)}
# 映射已知字段
for may_idx, c_name in col_to_c.items():
if may_idx < len(row):
val = row[may_idx]
# 时间字段特殊处理
if c_name in ('c175', 'c176'):
c_vals[c_name] = to_timestamp_str(val)
elif c_name in ('c009', 'c068', 'c114', 'c178', 'c179'):
c_vals[c_name] = to_num(val)
else:
c_vals[c_name] = to_text(val)
# 从门店名称查找门店编码 → c002
store_name = to_text(row[2]) if len(row) > 2 else None
if store_name and store_name in store_code_map:
c_vals['c002'] = store_code_map[store_name]
# 序号 → c001
c_vals['c001'] = str(idx + 1)
# 解析结账方式 → 支付方式列
payment_str = to_text(row[48]) if len(row) > 48 else None
if payment_str:
payments = parse_payment(payment_str)
for c_name, amount in payments.items():
c_vals[c_name] = amount
# 计算时长(分) → c177
opened = c_vals.get('c175')
closed = c_vals.get('c176')
if opened and closed:
try:
t1 = pd.to_datetime(opened, format='%Y/%m/%d %H:%M:%S')
t2 = pd.to_datetime(closed, format='%Y/%m/%d %H:%M:%S')
duration = (t2 - t1).total_seconds() / 60
if duration >= 0:
c_vals['c177'] = str(int(duration))
except (ValueError, TypeError):
pass
# 构建行数据
vals = [fname, source_row] + [c_vals[f"c{i+1:03d}"] for i in range(196)]
batch.append(tuple(vals))
if len(batch) >= 500:
execute_values(
cur,
f"INSERT INTO public.bill_records ({col_str}) VALUES %s",
batch,
page_size=500
)
conn.commit()
if (idx + 1) % 5000 == 0:
print(f" 已导入 {idx + 1}/{len(data_rows)}")
batch = []
if batch:
execute_values(
cur,
f"INSERT INTO public.bill_records ({col_str}) VALUES %s",
batch,
page_size=500
)
conn.commit()
print(f" 已导入 {len(data_rows)}/{len(data_rows)}")
cur.close()
return len(data_rows)
# ============================================================
# 5月品项销售明细 → dish_sales_details 字段映射
# ============================================================
ITEMS_FIELD_MAP = {
'城市': None, # col0
'机构编码': 'store_code', # col1
'门店名称': 'store_name', # col2
'营业日期': None, # col3
'下单时间所属餐段': 'business_type', # col4
'出品部门': 'production_department', # col5
'菜品大类': 'category_level1', # col6
'菜品小类': 'category_level2', # col7
'菜品编码': None, # col8
'品项名称': 'dish_name', # col9
'关联菜品名称': None, # col10
'商品别名': None, # col11
'品项类型': 'item_type', # col12
'菜品类型': None, # col13
'菜品标签': None, # col14
'规格': None, # col15
'单位': 'unit', # col16
'关联做法': 'preparation_method', # col17
'关联加料': None, # col18
'关联餐盒': None, # col19
'销售方式': None, # col20
'订单号': 'bill_no', # col21
'销售数量': 'sales_quantity', # col22
'赠送数量': None, # col23
'销售金额(元)': 'gross_amount', # col24
'赠送金额(元)': None, # col25
'优惠金额(元)': None, # col26
'品项收入(元)': 'received_amount', # col27
'点菜时间': None, # col28
'下单时间': 'ordered_at', # col29
'接单/结账/退菜时间': None, # col30
'收银员': None, # col31
'点菜员': None, # col32
'下单人': None, # col33
'订单分类': None, # col34
'订单来源': None, # col35
'新订单来源': None, # col36
'订单子来源': None, # col37
'桌台区域': None, # col38
'取餐号': 'table_or_pickup_no', # col39
'桌牌号': None, # col40
'订单金额(元)': None, # col41
'营业额(元)': None, # col42
'订单优惠(元)': None, # col43
'订单收入(元)': None, # col44
'标记': None, # col45
'退菜数量': None, # col46
'退菜金额(元)': None, # col47
'敏感操作类型': None, # col48
'单品备注': None, # col49
}
NUMERIC_FIELDS = {'sales_quantity', 'gross_amount', 'received_amount', 'unit_price', 'guest_count'}
TIMESTAMP_FIELDS = {'opened_at', 'closed_at', 'ordered_at'}
def import_dish_sales_may(conn, items_filepath, report_month):
"""将5月品项销售明细导入dish_sales_details"""
fname = os.path.basename(items_filepath)
cur = conn.cursor()
# 幂等检查
cur.execute(
"SELECT 1 FROM public.dish_sales_import_log WHERE source_file = %s",
(fname,)
)
if cur.fetchone():
print(f" {fname} 已导入过,跳过")
return 0
file_size = os.path.getsize(items_filepath)
# 读取Excelrow0=标题, row1=日期范围, row2=列头, row3+=数据
df = pd.read_excel(items_filepath, header=2, engine='openpyxl')
df = df.dropna(subset=[df.columns[0]])
data_rows = df.values.tolist()
headers = list(df.columns)
print(f" 数据行数: {len(data_rows)}, 列数: {df.shape[1]}")
if not data_rows:
return 0
# 构建列名→索引映射
col_map = {}
for i, h in enumerate(headers):
h_str = str(h).strip() if h else ''
if h_str:
col_map[h_str] = i
# 确定要插入的列
cols_to_insert = {}
for header_name, db_col in ITEMS_FIELD_MAP.items():
if db_col and header_name in col_map:
cols_to_insert[db_col] = col_map[header_name]
# 插入import log
cur.execute(
"""INSERT INTO public.dish_sales_import_log (source_file, file_size_bytes, data_rows, status)
VALUES (%s, %s, %s, 'importing')""",
(fname, file_size, len(data_rows))
)
all_cols = ['source_file', 'source_row'] + list(cols_to_insert.keys())
col_names = ','.join(all_cols)
batch = []
for idx, r in enumerate(data_rows):
source_row = idx + 4
vals = [fname, source_row]
for db_col, excel_idx in cols_to_insert.items():
v = r[excel_idx] if excel_idx < len(r) else None
if db_col in NUMERIC_FIELDS:
vals.append(to_num(v))
elif db_col in TIMESTAMP_FIELDS:
vals.append(to_timestamp_str(v))
else:
vals.append(to_text(v))
batch.append(tuple(vals))
if len(batch) >= 500:
execute_values(cur, f"INSERT INTO public.dish_sales_details ({col_names}) VALUES %s", batch, page_size=500)
conn.commit()
if (idx + 1) % 10000 == 0:
print(f" 已导入 {idx + 1}/{len(data_rows)}")
batch = []
if batch:
execute_values(cur, f"INSERT INTO public.dish_sales_details ({col_names}) VALUES %s", batch, page_size=500)
conn.commit()
print(f" 已导入 {len(data_rows)}/{len(data_rows)}")
# 更新log状态
cur.execute(
"UPDATE public.dish_sales_import_log SET status = 'completed' WHERE source_file = %s",
(fname,)
)
conn.commit()
cur.close()
return len(data_rows)
def main():
parser = argparse.ArgumentParser(description='5月账单数据导入(全渠道订单明细+品项销售明细)')
parser.add_argument('--month', required=True, help='报告月份 (YYYY-MM-01)')
parser.add_argument('--orders', required=True, help='全渠道订单明细Excel文件路径')
parser.add_argument('--items', required=True, help='品项销售明细Excel文件路径')
parser.add_argument('--db', default='bill_query', help='目标数据库 (默认bill_query)')
parser.add_argument('--skip-orders', action='store_true', help='跳过订单明细导入')
parser.add_argument('--skip-items', action='store_true', help='跳过品项销售明细导入')
args = parser.parse_args()
print(f"\n=== 5月账单数据导入 ===")
print(f"月份: {args.month}")
print(f"数据库: {args.db}")
print(f"订单明细: {args.orders}")
print(f"品项明细: {args.items}")
cfg = DB_CONFIG.copy()
cfg['dbname'] = args.db
conn = psycopg2.connect(**cfg)
conn.autocommit = False
try:
# 先从品项明细构建门店编码映射
store_code_map = {}
if not args.skip_items and os.path.isfile(args.items):
print("\n--- 构建门店编码映射 ---")
store_code_map = build_store_code_map(args.items)
# 导入bill_records
if not args.skip_orders and os.path.isfile(args.orders):
print("\n--- 导入全渠道订单明细 → bill_records ---")
import_bill_records_may(conn, args.orders, store_code_map, args.month)
# 导入dish_sales_details
if not args.skip_items and os.path.isfile(args.items):
print("\n--- 导入品项销售明细 → dish_sales_details ---")
import_dish_sales_may(conn, args.items, args.month)
print("\n=== 5月账单数据导入完成 ===")
except Exception as e:
conn.rollback()
print(f'错误: {e}', file=sys.stderr)
raise
finally:
conn.close()
if __name__ == '__main__':
main()
+294
View File
@@ -0,0 +1,294 @@
#!/usr/bin/env python3
"""
派生分析数据导入脚本
生成以下派生表
- dish_diagnosis_snapshot (菜品诊断快照从dish_cost_analysis_summary + BOM生成)
- central_kitchen_manufacturing_cost_pool (中央厨房制造成本池从薪资+营业费用+完工报表派生)
用法:
python3 import_derived_data.py --month 2026-04-01 --db bill_query_test
"""
import argparse
import datetime
import sys
import psycopg2
def generate_dish_diagnosis(conn, diag_date):
"""生成菜品诊断快照"""
cur = conn.cursor()
# 检查是否已有数据
cur.execute("SELECT count(*) FROM public.dish_diagnosis_snapshot WHERE diagnosis_date = %s", (diag_date,))
existing = cur.fetchone()[0]
if existing > 0:
print(f" dish_diagnosis_snapshot 已有 {existing} 行 (date={diag_date}),先删除再生成")
cur.execute("DELETE FROM public.dish_diagnosis_snapshot WHERE diagnosis_date = %s", (diag_date,))
# 检查依赖表是否存在且有数据
cur.execute("SELECT count(*) FROM public.dish_cost_analysis_summary")
summary_count = cur.fetchone()[0]
if summary_count == 0:
print(" 跳过: dish_cost_analysis_summary 无数据")
cur.close()
return 0
# 检查 analytics.fact_recipe_bom 是否存在
cur.execute("""
SELECT EXISTS (
SELECT 1 FROM information_schema.tables
WHERE table_schema = 'analytics' AND table_name = 'fact_recipe_bom'
)
""")
has_bom = cur.fetchone()[0]
bom_join = ""
bom_select = "0 AS cnt, 0 AS unique_cnt, 0 AS avg_waste"
if has_bom:
bom_select = "COALESCE(bom.cnt, 0), COALESCE(bom.unique_cnt, 0), COALESCE(round(bom.avg_waste::numeric, 2), 0)"
bom_join = """
LEFT JOIN (
SELECT b.sku_code,
count(*) AS cnt,
count(*) FILTER (WHERE r.ref_count = 1) AS unique_cnt,
sum(b.waste_rate * b.standard_gross_quantity) / nullif(sum(b.standard_gross_quantity), 0) AS avg_waste
FROM analytics.fact_recipe_bom b
LEFT JOIN (
SELECT material_code, count(DISTINCT sku_code) AS ref_count
FROM analytics.fact_recipe_bom GROUP BY material_code
) r ON r.material_code = b.material_code
GROUP BY b.sku_code
) bom ON bom.sku_code = s.dish_code
"""
sql = f"""
INSERT INTO public.dish_diagnosis_snapshot (
diagnosis_date, dish_code, dish_name, category_l1,
sales_amount, sales_quantity,
theoretical_margin_pct, actual_margin_pct, cost_variance_amount,
cost_tier, bom_complexity_score, unique_material_count, waste_rate_avg,
diagnosis_type, diagnosis_detail, suggested_action, priority
)
SELECT
'{diag_date}'::date,
s.dish_code,
s.dish_name,
s.category_level1,
round(s.sales_amount::numeric, 2),
round(s.sales_quantity::numeric, 2),
round(s.theoretical_margin_rate_pct::numeric, 2),
round(s.actual_margin_rate_pct::numeric, 2),
round(s.cost_variance_amount::numeric, 2),
CASE
WHEN s.actual_margin_rate_pct < 0 THEN '数据异常'
WHEN s.cost_variance_amount > 0 AND s.theoretical_cost > 0
AND (s.cost_variance_amount / s.theoretical_cost) > 0.2 THEN '紧急'
WHEN s.cost_variance_amount > 0 AND s.theoretical_cost > 0
AND (s.cost_variance_amount / s.theoretical_cost) > 0.1 THEN '整改'
WHEN s.cost_variance_amount > 0 THEN '关注'
ELSE '正常'
END,
{bom_select},
CASE
WHEN s.actual_margin_rate_pct < 0 THEN '数据异常'
WHEN s.theoretical_margin_rate_pct < 0 THEN '负毛利'
WHEN s.theoretical_margin_rate_pct < 30 AND s.actual_margin_rate_pct > s.theoretical_margin_rate_pct THEN '低毛利-定价偏低'
WHEN s.theoretical_margin_rate_pct < 50 AND s.actual_margin_rate_pct < s.theoretical_margin_rate_pct THEN '低毛利-成本超耗'
WHEN s.cost_variance_amount > 0 AND COALESCE(bom.avg_waste, 0) > 20 THEN '高超耗-份量超标'
WHEN s.cost_variance_amount > 0 AND COALESCE(bom.avg_waste, 0) > 100 THEN '高超耗-分摊异常'
WHEN COALESCE(bom.cnt, 0) > 15 AND s.sales_quantity < 5 THEN '配方复杂-低销量'
WHEN COALESCE(bom.unique_cnt, 0) > 3 AND s.sales_amount < 5000 THEN '独有原料风险'
WHEN s.cost_variance_amount > 0 THEN '成本差异'
ELSE '正常'
END,
CASE
WHEN s.actual_margin_rate_pct < 0 THEN '实际毛利率为负,需先核查BOM/单位/分摊'
WHEN s.theoretical_margin_rate_pct < 0 THEN '理论毛利率为负,定价低于标准成本'
WHEN s.theoretical_margin_rate_pct < 30 THEN '理论毛利率低于30%,定价偏低'
WHEN s.theoretical_margin_rate_pct < 50 AND s.actual_margin_rate_pct < s.theoretical_margin_rate_pct THEN '实际成本超理论,存在超耗'
WHEN s.cost_variance_amount > 0 AND COALESCE(bom.avg_waste, 0) > 20 THEN '物料损耗率超过20%'
ELSE '成本基本正常'
END,
CASE
WHEN s.actual_margin_rate_pct < 0 THEN 'fix_data'
WHEN s.theoretical_margin_rate_pct < 0 THEN 'price_up'
WHEN s.theoretical_margin_rate_pct < 30 AND s.actual_margin_rate_pct > s.theoretical_margin_rate_pct THEN 'price_up'
WHEN s.theoretical_margin_rate_pct < 50 AND s.actual_margin_rate_pct < s.theoretical_margin_rate_pct THEN 'recipe_optimize'
WHEN s.cost_variance_amount > 0 AND COALESCE(bom.avg_waste, 0) > 20 THEN 'portion_reduce'
WHEN COALESCE(bom.cnt, 0) > 15 AND s.sales_quantity < 5 THEN 'delist'
WHEN COALESCE(bom.unique_cnt, 0) > 3 AND s.sales_amount < 5000 THEN 'evaluate_delist'
WHEN s.cost_variance_amount > 0 THEN 'monitor'
ELSE 'keep'
END,
CASE
WHEN s.actual_margin_rate_pct < 0 THEN 'P0'
WHEN s.theoretical_margin_rate_pct < 0 THEN 'P0'
WHEN s.cost_variance_amount > 0 AND s.theoretical_cost > 0
AND (s.cost_variance_amount / s.theoretical_cost) > 0.2 THEN 'P0'
WHEN s.theoretical_margin_rate_pct < 50 THEN 'P1'
WHEN COALESCE(bom.cnt, 0) > 15 AND s.sales_quantity < 5 THEN 'P2'
WHEN COALESCE(bom.unique_cnt, 0) > 3 AND s.sales_amount < 5000 THEN 'P2'
ELSE 'P3'
END
FROM public.dish_cost_analysis_summary s
{bom_join}
WHERE s.dish_code IS NOT NULL
"""
cur.execute(sql)
inserted = cur.rowcount
conn.commit()
print(f" dish_diagnosis_snapshot 生成完成: {inserted} 行 (date={diag_date})")
cur.close()
return inserted
def generate_manufacturing_cost_pool(conn, report_month):
"""生成中央厨房制造成本池"""
cur = conn.cursor()
# 检查是否已有数据
cur.execute("SELECT count(*) FROM public.central_kitchen_manufacturing_cost_pool WHERE report_month = %s", (report_month,))
existing = cur.fetchone()[0]
if existing > 0:
print(f" central_kitchen_manufacturing_cost_pool 已有 {existing} 行,先删除再生成")
cur.execute("DELETE FROM public.central_kitchen_manufacturing_cost_pool WHERE report_month = %s", (report_month,))
# 检查依赖表是否有数据
cur.execute("SELECT count(*) FROM public.salary_detail_records")
salary_count = cur.fetchone()[0]
cur.execute("SELECT count(*) FROM public.operating_expense_records WHERE report_month = %s", (report_month,))
expense_count = cur.fetchone()[0]
cur.execute("SELECT count(*) FROM public.central_kitchen_finished_receipt WHERE receipt_date >= date %s AND receipt_date < (date %s + interval '1 month')::date", (report_month, report_month))
ck_count = cur.fetchone()[0]
if salary_count == 0 and expense_count == 0 and ck_count == 0:
print(" 跳过: 依赖表无数据")
cur.close()
return 0
rows = []
# 1. 直接人工:中央厨房生产人员工资
if salary_count > 0:
cur.execute("""
SELECT round(coalesce(sum(net_pay), 0)::numeric, 2)
FROM public.salary_detail_records
WHERE org_level1 LIKE '%加工配送中心%' OR org_level1 LIKE '%中央厨房%'
OR org_level2 LIKE '%加工配送中心%' OR org_level2 LIKE '%中央厨房%'
OR org_level3 LIKE '%加工配送中心%' OR org_level3 LIKE '%中央厨房%'
OR org_level4 LIKE '%加工配送中心%' OR org_level4 LIKE '%中央厨房%'
OR org_level5 LIKE '%加工配送中心%' OR org_level5 LIKE '%中央厨房%'
OR org_level6 LIKE '%加工配送中心%' OR org_level6 LIKE '%中央厨房%'
OR org_level7 LIKE '%加工配送中心%' OR org_level7 LIKE '%中央厨房%'
OR org_level8 LIKE '%加工配送中心%' OR org_level8 LIKE '%中央厨房%'
""")
salary_total = cur.fetchone()[0]
if salary_total and float(salary_total) > 0:
rows.append((
report_month, '直接人工', '中央厨房生产人员工资', '薪资明细',
'salary_detail_records:加工配送中心/中央厨房',
float(salary_total), 1.0, float(salary_total),
'中央厨房组织直接归集', False, True,
None
))
# 2. 制造费用:从营业费用中供应链部分按比例分摊
if expense_count > 0:
# 中央厨房人数/加工配送中心人数比例 = 7/11 ≈ 0.6364
ck_ratio = 0.63636364
expense_items = [
('50302', '餐厅房租', 'operating_expense_records:供应链/50302'),
('50307', '水费', 'operating_expense_records:供应链/50307'),
('50308', '电费', 'operating_expense_records:供应链/50308'),
('50310', '员工宿舍费用', 'operating_expense_records:供应链/50310'),
('50315', '维修费', 'operating_expense_records:供应链/50315'),
]
for acct_code, acct_name, source_ref in expense_items:
cur.execute("""
SELECT round(coalesce(sum(amount), 0)::numeric, 2)
FROM public.operating_expense_records
WHERE report_month = %s AND account_code = %s
AND cost_unit_source_name LIKE '供应链%%'
""", (report_month, acct_code))
amount = cur.fetchone()[0]
if amount and float(amount) > 0:
allocated = round(float(amount) * ck_ratio, 6)
rows.append((
report_month, '制造费用', acct_name, '营业费用',
source_ref, float(amount), ck_ratio, allocated,
'中央厨房人数/加工配送中心人数(临时)', True, True,
'供应链共享费用,待电表、面积或工时数据后替换'
))
# 3. 源报表费用:完工报表费用成本
if ck_count > 0:
cur.execute("""
SELECT round(coalesce(sum(source_fee_cost), 0)::numeric, 4)
FROM public.central_kitchen_finished_receipt
WHERE receipt_date >= date %s AND receipt_date < (date %s + interval '1 month')::date
""", (report_month, report_month))
fee_total = cur.fetchone()[0]
if fee_total and float(fee_total) > 0:
rows.append((
report_month, '源报表费用', '完工报表费用成本', '完工入库报表',
'central_kitchen_finished_receipt.source_fee_cost',
float(fee_total), 1.0, float(fee_total),
'源报表原值', True, False,
'无水电人工等明细来源,为避免与工资和营业费用重复,暂不计入重建成本'
))
if rows:
from psycopg2.extras import execute_values
execute_values(cur, """
INSERT INTO public.central_kitchen_manufacturing_cost_pool
(report_month, cost_type, cost_subtype, source_type, source_reference,
source_amount, central_kitchen_share_pct, allocated_amount,
allocation_method, is_provisional, include_in_rebuilt_cost, note)
VALUES %s
""", rows, page_size=100)
conn.commit()
print(f" central_kitchen_manufacturing_cost_pool 生成完成: {len(rows)}")
cur.close()
return len(rows)
def main():
parser = argparse.ArgumentParser(description='派生分析数据导入')
parser.add_argument('--month', required=True, help='报告月份 (YYYY-MM-01)')
parser.add_argument('--db', default='bill_query', help='目标数据库 (默认bill_query)')
parser.add_argument('--diagnosis-date', default=None, help='诊断日期 (默认今天)')
args = parser.parse_args()
conn = psycopg2.connect(host='localhost', port=5432, dbname=args.db, user='freedak')
conn.autocommit = False
diag_date = args.diagnosis_date or datetime.date.today().isoformat()
try:
print(f"\n=== 派生分析数据生成 ===")
print(f"数据库: {args.db}, 月份: {args.month}")
print("\n--- 菜品诊断快照 ---")
generate_dish_diagnosis(conn, diag_date)
print("\n--- 中央厨房制造成本池 ---")
generate_manufacturing_cost_pool(conn, args.month)
print("\n=== 生成完成 ===")
except Exception as e:
conn.rollback()
print(f"错误: {e}", file=sys.stderr)
raise
finally:
conn.close()
if __name__ == '__main__':
main()
+170
View File
@@ -0,0 +1,170 @@
#!/bin/bash
# ============================================================
# 5月数据导入脚本
# 用法: bash import_may_data.sh [数据库名]
# 默认数据库: bill_query_test
# ============================================================
set -e
DB="${1:-bill_query_test}"
MONTH="2026-05-01"
DIAG_DATE="2026-08-18"
# 数据根目录
DATA="/Users/freedak/Documents/AIDashboard/SBrainCO3/数据/5月"
DATA4="/Users/freedak/Documents/AIDashboard/SBrainCO3/数据/4月"
PIPELINE="/Users/freedak/Documents/AIDashboard/SBrainCO3/db/pipeline"
PY=python3
echo "============================================================"
echo " 5月数据导入 → 数据库: ${DB}"
echo " 月份: ${MONTH}"
echo "============================================================"
# ============================================================
# Step 1: 薪资 + 考勤
# ============================================================
echo ""
echo "=== [1/9] 薪资 + 考勤 ==="
${PY} "${PIPELINE}/import_salary_attendance.py" \
--month "${MONTH}" \
--db "${DB}" \
--salary-file "${DATA}/营业数据/2026年5月薪资拆分明细表_北京西部马华餐饮有限公司.xlsx" \
--attendance-file "${DATA}/营业数据/2026年5月考勤数据表.xlsx"
# ============================================================
# Step 2: bill_records + dish_sales_details5月专用脚本)
# 5月格式: 全渠道订单明细(51列) + 品项销售明细(50列)
# ============================================================
echo ""
echo "=== [2/9] bill_records + 菜品销售明细 ==="
${PY} "${PIPELINE}/import_bill_records_may.py" \
--month "${MONTH}" \
--orders "${DATA}/营业数据/正餐事业部_全渠道订单明细_20260730_1112_1785381233074.xlsx" \
--items "${DATA}/营业数据/正餐事业部_品项销售明细_20260730_1128_1785382191936.xlsx" \
--db "${DB}"
# ============================================================
# Step 4: 库存成本(盘点倒挤成本)
# ============================================================
echo ""
echo "=== [4/9] 库存成本 ==="
${PY} "${PIPELINE}/import_monthly_data.py" \
--dataset inventory \
--month "${MONTH}" \
--file "${DATA}/供应链数据/4.13盘点倒挤成本报表2026年5月.xlsx" \
--db "${DB}"
# ============================================================
# Step 5: 菜品成本BOM
# ============================================================
echo ""
echo "=== [5/9] 菜品成本BOM ==="
${PY} "${PIPELINE}/import_monthly_data.py" \
--dataset dish_cost \
--month "${MONTH}" \
--file "${DATA}/营业数据/2026年5月菜品成本分析报表.xlsx" \
--db "${DB}"
# ============================================================
# Step 6: 营业费用
# ============================================================
echo ""
echo "=== [6/9] 营业费用 ==="
${PY} "${PIPELINE}/import_monthly_data.py" \
--dataset operating_expense \
--month "${MONTH}" \
--file "${DATA}/2026年5月营业费用分析.xls" \
--db "${DB}"
# ============================================================
# Step 7: 中央厨房(4个子文件)
# ============================================================
echo ""
echo "=== [7/9] 中央厨房 ==="
echo " [7a] 完工入库"
${PY} "${PIPELINE}/import_monthly_data.py" \
--dataset central_kitchen --ck-type finished \
--month "${MONTH}" \
--file "${DATA}/中央厨房/2026-05-01--2026-05-31 23 59 59完工入库统计分析报表.xlsx" \
--db "${DB}"
echo " [7b] 配方耗用"
${PY} "${PIPELINE}/import_monthly_data.py" \
--dataset central_kitchen --ck-type recipe \
--month "${MONTH}" \
--file "${DATA}/中央厨房/按配方导出-货品实际与理论耗用(2026-05-01--2026-05-31).xlsx" \
--db "${DB}"
echo " [7c] 货品耗用"
${PY} "${PIPELINE}/import_monthly_data.py" \
--dataset central_kitchen --ck-type material \
--month "${MONTH}" \
--file "${DATA}/中央厨房/按货品导出-货品实际与理论耗用(2026-05-01--2026-05-31).xlsx" \
--db "${DB}"
echo " [7d] 加工单价"
${PY} "${PIPELINE}/import_monthly_data.py" \
--dataset central_kitchen --ck-type processing \
--month "${MONTH}" \
--file "${DATA}/中央厨房/加工单价分析报表.xlsx" \
--db "${DB}"
# ============================================================
# Step 8: 配送明细(2个文件)
# ============================================================
echo ""
echo "=== [8/9] 配送明细 ==="
echo " [8a] 1-15日"
${PY} "${PIPELINE}/import_monthly_data.py" \
--dataset distribution \
--month "${MONTH}" \
--file "${DATA}/供应链数据/全部门店-全部仓库-统计货品明细报表2026年5月1-15日.xlsx" \
--db "${DB}"
echo " [8b] 16-31日"
${PY} "${PIPELINE}/import_monthly_data.py" \
--dataset distribution \
--month "${MONTH}" \
--file "${DATA}/供应链数据/全部门店-全部仓库-统计货品明细报表2026年5月16-31日.xlsx" \
--db "${DB}"
# ============================================================
# Step 9: 门店位置与映射表(复用4月各店信息文件)
# ============================================================
echo ""
echo "=== [9/9] 门店位置与映射表 ==="
${PY} "${PIPELINE}/import_store_location.py" \
--file "${DATA4}/各店信息新(20260508.xls" \
--db "${DB}"
# ============================================================
# Step 10: 派生分析数据
# ============================================================
echo ""
echo "=== [10] 派生分析数据 ==="
${PY} "${PIPELINE}/import_derived_data.py" \
--month "${MONTH}" \
--db "${DB}" \
--diagnosis-date "${DIAG_DATE}"
# ============================================================
# Step 11: 物化视图刷新
# ============================================================
echo ""
echo "=== [11] 物化视图刷新 ==="
${PY} "${PIPELINE}/refresh_materialized_views.py" \
--db "${DB}"
# ============================================================
# Step 12: 验证
# ============================================================
echo ""
echo "=== [12] 数据一致性验证 ==="
${PY} "${PIPELINE}/verify.py" \
--db "${DB}" || true
echo ""
echo "============================================================"
echo " 5月数据导入完成"
echo "============================================================"
File diff suppressed because it is too large Load Diff
@@ -3,12 +3,13 @@
薪资拆分明细表 + 考勤数据表 导入脚本
遵循现有 import_log + records 模式
"""
import openpyxl
import hashlib
import psycopg2
import os
import sys
from datetime import datetime
import argparse
import pandas as pd
from psycopg2.extras import execute_values
DB_CONFIG = {
'host': 'localhost',
@@ -18,9 +19,9 @@ DB_CONFIG = {
'password': '',
}
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SALARY_FILE = os.path.join(BASE_DIR, '马兰拉面数据分析', '薪资拆分明细表_脱敏.xlsx')
ATTENDANCE_FILE = os.path.join(BASE_DIR, '马兰拉面数据分析', '考勤数据表-脱敏.xlsx')
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
SALARY_FILE = os.path.join(BASE_DIR, '数据', '4月', '薪资拆分明细表_脱敏.xlsx')
ATTENDANCE_FILE = os.path.join(BASE_DIR, '数据', '4月', '考勤数据表-脱敏.xlsx')
def file_sha256(filepath):
h = hashlib.sha256()
@@ -31,34 +32,42 @@ def file_sha256(filepath):
def to_num(val):
if val is None or val == '':
return 0
return None
if isinstance(val, float) and pd.isna(val):
return None
try:
return float(val)
except (ValueError, TypeError):
return 0
return None
def to_text(val):
if val is None:
return None
if isinstance(val, float) and pd.isna(val):
return None
s = str(val).strip()
if s.lower() == 'nan' or s.lower() == 'none':
return None
return s if s else None
def import_salary(conn, report_month='2026-04-01'):
print(f'导入薪资拆分明细表: {SALARY_FILE}')
sha = file_sha256(SALARY_FILE)
wb = openpyxl.load_workbook(SALARY_FILE, read_only=True, data_only=True)
ws = wb[wb.sheetnames[0]]
def import_salary(conn, report_month='2026-04-01', salary_file=None):
filepath = salary_file or SALARY_FILE
print(f'导入薪资拆分明细表: {filepath}')
sha = file_sha256(filepath)
# Row 1: title, Row 2: merged title, Row 3: headers, Row 4+: data
rows = list(ws.iter_rows(min_row=4, values_only=True))
data_rows = [r for r in rows if r[0] is not None and r[9] is not None and str(r[9]).strip()]
# Read with pandas (row 3 = headers, row 4+ = data)
raw_df = pd.read_excel(filepath, header=None, engine='openpyxl')
print(f' 总行数: {len(raw_df)}, 列数: {len(raw_df.columns)}')
# Data starts from row 3 (0-indexed), filter rows with employee_code (col 9)
df = raw_df.iloc[3:].copy()
df = df[df[9].notna() & (df[9].astype(str).str.strip() != '') & (df[9].astype(str).str.strip() != 'nan')]
data_rows = df.values.tolist()
print(f' 数据行数: {len(data_rows)}')
report_month = report_month
source_file = os.path.basename(SALARY_FILE)
source_file = os.path.basename(filepath)
cur = conn.cursor()
# Check if already imported
cur.execute(
'SELECT import_id FROM public.salary_import_log WHERE report_month = %s AND source_file = %s AND file_sha256 = %s',
(report_month, source_file, sha)
@@ -66,10 +75,8 @@ def import_salary(conn, report_month='2026-04-01'):
existing = cur.fetchone()
if existing:
print(f' 已导入过, import_id={existing[0]}, 跳过')
wb.close()
return
# Insert import log
cur.execute(
'''INSERT INTO public.salary_import_log (report_month, source_file, file_sha256, workbook_rows, imported_rows)
VALUES (%s, %s, %s, %s, %s) RETURNING import_id''',
@@ -78,9 +85,8 @@ def import_salary(conn, report_month='2026-04-01'):
import_id = cur.fetchone()[0]
print(f' import_id={import_id}')
# Batch insert
insert_sql = '''INSERT INTO public.salary_detail_records (
import_id, source_row,
# Column mapping: use execute_values for batch insert
col_names = '''import_id, source_row,
org_level1, org_level2, org_level3, org_level4, org_level5, org_level6, org_level7, org_level8,
employee_code, salary_period, position, work_type, employment_type, hire_date, leave_date,
salary_standard, base_wage, overtime_subsidy, social_subsidy, position_wage, tenure_wage,
@@ -100,13 +106,11 @@ def import_salary(conn, report_month='2026-04-01'):
external_subsidy, external_other_deduction, external_gross,
pension_deduction, medical_deduction, unemployment_deduction,
external_social_total, external_tax, external_net, internal_tax, internal_net,
external_unit, attendance_remark, employment_type_orig, salary_category
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'''
external_unit, attendance_remark, employment_type_orig, salary_category'''
batch = []
batch_size = 500
for idx, r in enumerate(data_rows):
source_row = idx + 4 # Excel row number
source_row = idx + 4
vals = [
import_id, source_row,
to_text(r[1]), to_text(r[2]), to_text(r[3]), to_text(r[4]), to_text(r[5]), to_text(r[6]), to_text(r[7]), to_text(r[8]),
@@ -130,34 +134,36 @@ def import_salary(conn, report_month='2026-04-01'):
to_num(r[90]), to_num(r[91]), to_num(r[92]), to_num(r[93]), to_num(r[94]),
to_text(r[95]), to_text(r[96]), to_text(r[97]), to_text(r[98]),
]
batch.append(vals)
if len(batch) >= batch_size:
cur.executemany(insert_sql, batch)
batch.append(tuple(vals))
if len(batch) >= 500:
execute_values(cur, f'INSERT INTO public.salary_detail_records ({col_names}) VALUES %s', batch, page_size=500)
conn.commit()
print(f' 已导入 {idx + 1}/{len(data_rows)}')
batch = []
if batch:
cur.executemany(insert_sql, batch)
execute_values(cur, f'INSERT INTO public.salary_detail_records ({col_names}) VALUES %s', batch, page_size=500)
conn.commit()
print(f' 已导入 {len(data_rows)}/{len(data_rows)}')
wb.close()
print(f' 薪资明细导入完成: {len(data_rows)}')
def import_attendance(conn, report_month='2026-04-01'):
print(f'\n导入考勤数据表: {ATTENDANCE_FILE}')
sha = file_sha256(ATTENDANCE_FILE)
wb = openpyxl.load_workbook(ATTENDANCE_FILE, read_only=True, data_only=True)
ws = wb[wb.sheetnames[0]]
def import_attendance(conn, report_month='2026-04-01', attendance_file=None):
filepath = attendance_file or ATTENDANCE_FILE
print(f'\n导入考勤数据表: {filepath}')
sha = file_sha256(filepath)
# Row 1: headers, Row 2+: data
rows = list(ws.iter_rows(min_row=2, values_only=True))
data_rows = [r for r in rows if r[0] is not None]
# Read with pandas (row 0 = headers, row 1+ = data)
raw_df = pd.read_excel(filepath, header=None, engine='openpyxl')
print(f' 总行数: {len(raw_df)}, 列数: {len(raw_df.columns)}')
# Data starts from row 1
df = raw_df.iloc[1:].copy()
df = df[df[0].notna() & (df[0].astype(str).str.strip() != '') & (df[0].astype(str).str.strip() != 'nan')]
data_rows = df.values.tolist()
print(f' 数据行数: {len(data_rows)}')
report_month = report_month
source_file = os.path.basename(ATTENDANCE_FILE)
source_file = os.path.basename(filepath)
cur = conn.cursor()
cur.execute(
@@ -167,7 +173,6 @@ def import_attendance(conn, report_month='2026-04-01'):
existing = cur.fetchone()
if existing:
print(f' 已导入过, import_id={existing[0]}, 跳过')
wb.close()
return
cur.execute(
@@ -178,44 +183,52 @@ def import_attendance(conn, report_month='2026-04-01'):
import_id = cur.fetchone()[0]
print(f' import_id={import_id}')
# 33 columns: 工号, 岗位, 所在部门, day_01..day_30
# 34 columns: import_id, source_row, employee_code, position, department, day_01..day_31
cols = ['import_id', 'source_row', 'employee_code', 'position', 'department']
cols += [f'day_{str(i).zfill(2)}' for i in range(1, 31)]
placeholders = ', '.join(['%s'] * len(cols))
col_names = ', '.join(cols)
insert_sql = f'INSERT INTO public.attendance_records ({col_names}) VALUES ({placeholders})'
cols += [f'day_{str(i).zfill(2)}' for i in range(1, 32)]
col_names = ','.join(cols)
batch = []
batch_size = 500
for idx, r in enumerate(data_rows):
source_row = idx + 2
vals = [import_id, source_row, to_text(r[0]), to_text(r[1]), to_text(r[2])]
# Days 1-30 (columns 3-32)
for d in range(30):
# Days 1-31 (columns 3-33)
for d in range(31):
vals.append(to_text(r[3 + d]) if 3 + d < len(r) else None)
batch.append(vals)
if len(batch) >= batch_size:
cur.executemany(insert_sql, batch)
batch.append(tuple(vals))
if len(batch) >= 500:
execute_values(cur, f'INSERT INTO public.attendance_records ({col_names}) VALUES %s', batch, page_size=500)
conn.commit()
print(f' 已导入 {idx + 1}/{len(data_rows)}')
batch = []
if batch:
cur.executemany(insert_sql, batch)
execute_values(cur, f'INSERT INTO public.attendance_records ({col_names}) VALUES %s', batch, page_size=500)
conn.commit()
print(f' 已导入 {len(data_rows)}/{len(data_rows)}')
wb.close()
print(f' 考勤数据导入完成: {len(data_rows)}')
def main():
report_month = sys.argv[1] if len(sys.argv) > 1 else '2026-04-01'
print(f'导入月份: {report_month}')
conn = psycopg2.connect(**DB_CONFIG)
parser = argparse.ArgumentParser(description='薪资考勤数据导入')
parser.add_argument('--month', default='2026-04-01', help='报告月份')
parser.add_argument('--db', default='bill_query', help='数据库名')
parser.add_argument('--skip-salary', action='store_true', help='跳过薪资导入')
parser.add_argument('--skip-attendance', action='store_true', help='跳过考勤导入')
parser.add_argument('--salary-file', default=None, help='薪资Excel文件路径 (默认使用内置路径)')
parser.add_argument('--attendance-file', default=None, help='考勤Excel文件路径 (默认使用内置路径)')
args = parser.parse_args()
print(f'导入月份: {args.month}, 数据库: {args.db}')
cfg = DB_CONFIG.copy()
cfg['dbname'] = args.db
conn = psycopg2.connect(**cfg)
conn.autocommit = False
try:
import_salary(conn, report_month)
import_attendance(conn, report_month)
if not args.skip_salary:
import_salary(conn, args.month, args.salary_file)
if not args.skip_attendance:
import_attendance(conn, args.month, args.attendance_file)
print('\n=== 导入完成 ===')
except Exception as e:
conn.rollback()
+619
View File
@@ -0,0 +1,619 @@
#!/usr/bin/env python3
"""
门店位置与映射表导入脚本
各店信息新20260508.xls 导入以下表
- store_location_source_rows (原始行)
- store_location_master (门店主表含地理编码)
- sales_store_location_mapping (销售门店位置映射)
同时导入静态映射表
- store_name_mapping (薪资名称账单名称映射8条手工数据)
- inventory_store_mapping (库存成本单位销售门店映射)
- operating_expense_store_mapping (费用单位销售门店映射)
用法:
python3 import_store_location.py --file <各店信息.xls> --db bill_query_test
python3 import_store_location.py --file <各店信息.xls> --db bill_query_test --skip-mappings
"""
import argparse
import math
import os
import re
import sys
from datetime import date, datetime
from difflib import SequenceMatcher
import pandas as pd
import psycopg2
from psycopg2.extras import Json, execute_values
# ============================================================
# 静态数据
# ============================================================
# WGS84行政区中心点(低精度兜底)
ADMIN_CENTROIDS = {
"北京市东城区": (39.92855, 116.41637),
"北京市西城区": (39.91231, 116.36679),
"北京市朝阳区": (39.92149, 116.44355),
"北京市海淀区": (39.95933, 116.29845),
"北京市丰台区": (39.85856, 116.28625),
"北京市石景山区": (39.90569, 116.22298),
"北京市昌平区": (40.22077, 116.23128),
"北京市大兴区": (39.72684, 116.34159),
"北京市通州区": (39.90249, 116.65643),
"北京市房山区": (39.74788, 116.14327),
"北京市怀柔区": (40.31600, 116.63170),
"北京市北京经济技术开发区": (39.79500, 116.50600),
"上海市浦东新区": (31.22114, 121.54409),
"上海市青浦区": (31.15074, 121.12417),
"浙江省杭州市余杭区": (30.41875, 120.29940),
"陕西省西安市": (34.34157, 108.93977),
}
MANUAL_ALIAS = {
"火锅北三环店": "火锅",
"双安总店": "双安",
"温泉店": "温泉西部马华",
"生命园路店": "北大生命园",
"永丰悦界店": "永丰路",
"哈马尔罕总部基地店": "哈马尔罕",
}
# 薪资名称 → 账单名称 手工映射
STORE_NAME_MAPPING = [
("双安店", "双安总店"),
("安宁庄快手店", "安宁庄快手"),
("海淀大街店", "海淀大街"),
("百子湾店", "百子湾路店"),
("哈马尔罕大钟寺店", "大钟寺店"),
("大钟寺店", "大钟寺店"),
("阿里疆(温泉路店)", "温泉店"),
("温泉店", "温泉店"),
]
# ============================================================
# 工具函数
# ============================================================
def clean(v):
if v is None:
return None
s = str(v).strip()
return s or None
def normalize_name(v):
s = clean(v) or ""
s = re.sub(r"[(].*?[)]", "", s)
for token in ("西部马华", "牛肉面", "餐饮店", "餐厅", "总店"):
s = s.replace(token, "")
s = re.sub(r"店$", "", s)
return re.sub(r"\s+", "", s)
def parse_date(v):
if isinstance(v, datetime):
return v.date()
if isinstance(v, date):
return v
if isinstance(v, (int, float)):
try:
return (datetime(1899, 12, 30) + datetime.timedelta(days=float(v))).date()
except Exception:
return None
s = clean(v)
if not s or s in {"长期", "未开业"}:
return None
try:
return datetime.fromisoformat(s).date()
except ValueError:
pass
for fmt in ("%Y-%m-%d", "%Y/%m/%d", "%Y.%m.%d"):
try:
return datetime.strptime(s, fmt).date()
except ValueError:
pass
return None
def parse_area(v):
if isinstance(v, (int, float)):
return float(v), "numeric"
s = clean(v)
if not s:
return None, "missing"
nums = [float(x) for x in re.findall(r"\d+(?:\.\d+)?", s)]
if len(nums) >= 2 and ("-" in s or "" in s or "~" in s):
return sum(nums[:2]) / 2, "range_midpoint"
if nums:
return nums[0], "text_numeric"
return None, "unparsed"
def parse_admin(address):
a = clean(address) or ""
if "上海市" in a:
province, city = "上海市", "上海市"
elif "浙江省" in a or "杭州市" in a:
province, city = "浙江省", "杭州市"
elif "陕西省" in a or "西安市" in a:
province, city = "陕西省", "西安市"
else:
province, city = "北京市", "北京市"
district = None
candidates = ["东城区", "西城区", "朝阳区", "海淀区", "丰台区", "石景山区",
"昌平区", "大兴区", "通州区", "房山区", "怀柔区",
"浦东新区", "青浦区", "余杭区"]
for item in candidates:
if item in a:
district = item
break
if "北京经济技术开发区" in a:
district = "北京经济技术开发区"
return province, city, district
def wgs84_to_gcj02(lat, lon):
if lat is None or lon is None:
return None, None
if not (72.004 <= lon <= 137.8347 and 0.8293 <= lat <= 55.8271):
return lat, lon
a, ee = 6378245.0, 0.00669342162296594323
dlat = _transform_lat(lon - 105.0, lat - 35.0)
dlon = _transform_lon(lon - 105.0, lat - 35.0)
radlat = lat / 180.0 * math.pi
magic = math.sin(radlat)
magic = 1 - ee * magic * magic
sqrtmagic = math.sqrt(magic)
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * math.pi)
dlon = (dlon * 180.0) / (a / sqrtmagic * math.cos(radlat) * math.pi)
return lat + dlat, lon + dlon
def _transform_lat(x, y):
ret = -100.0 + 2.0*x + 3.0*y + 0.2*y*y + 0.1*x*y + 0.2*math.sqrt(abs(x))
ret += (20.0*math.sin(6.0*x*math.pi) + 20.0*math.sin(2.0*x*math.pi))*2.0/3.0
ret += (20.0*math.sin(y*math.pi) + 40.0*math.sin(y/3.0*math.pi))*2.0/3.0
ret += (160.0*math.sin(y/12.0*math.pi) + 320*math.sin(y*math.pi/30.0))*2.0/3.0
return ret
def _transform_lon(x, y):
ret = 300.0 + x + 2.0*y + 0.1*x*x + 0.1*x*y + 0.1*math.sqrt(abs(x))
ret += (20.0*math.sin(6.0*x*math.pi) + 20.0*math.sin(2.0*x*math.pi))*2.0/3.0
ret += (20.0*math.sin(x*math.pi) + 40.0*math.sin(x/3.0*math.pi))*2.0/3.0
ret += (150.0*math.sin(x/12.0*math.pi) + 300.0*math.sin(x/30.0*math.pi))*2.0/3.0
return ret
def fallback_geocode(province, city, district, address):
if not address:
return None, None, None, "pending_no_address", 0.0
key = f"{city}{district}" if district else city
if province not in {"北京市", "上海市"} and city:
key = f"{province}{city}{district or ''}"
coord = ADMIN_CENTROIDS.get(key)
if coord:
precision = "district_centroid" if district else "city_centroid"
confidence = 0.25 if district else 0.10
return coord[0], coord[1], key, precision, confidence
city_key = f"{province}{city}" if province != city else city
coord = ADMIN_CENTROIDS.get(city_key)
if coord:
return coord[0], coord[1], city_key, "city_centroid", 0.10
return None, None, None, "pending_exact_geocode", 0.0
# ============================================================
# 导入函数
# ============================================================
def import_store_location(conn, filepath):
"""导入门店位置主表和源行表"""
source_file = os.path.basename(filepath)
print(f"\n=== 门店位置导入 ===")
print(f"文件: {source_file}")
cur = conn.cursor()
# 幂等检查
cur.execute("SELECT 1 FROM public.store_location_master WHERE source_file = %s LIMIT 1", (source_file,))
if cur.fetchone():
print(" 位置数据已导入过,跳过位置导入")
# 仍然需要重建销售门店映射
_rebuild_sales_mapping(conn)
cur.close()
return
# 读取Excel
df = pd.read_excel(filepath, header=0, engine='xlrd')
print(f" 总行数: {len(df)}")
# 清理数据
raw_rows = []
numbered = []
for idx, row in df.iterrows():
row_no = idx + 2 # 1-indexed from row 2
seq = row.iloc[0]
seq_int = int(seq) if isinstance(seq, (int, float)) and not pd.isna(seq) else None
raw = {
"row": row_no, "seq": seq_int,
"name": clean(row.iloc[1]) if len(row) > 1 else None,
"company": clean(row.iloc[2]) if len(row) > 2 else None,
"brand": clean(row.iloc[3]) if len(row) > 3 else None,
"address": clean(row.iloc[4]) if len(row) > 4 else None,
"area": clean(row.iloc[5]) if len(row) > 5 else None,
"opened": clean(row.iloc[6]) if len(row) > 6 else None,
"lease": clean(row.iloc[7]) if len(row) > 7 else None,
"license": clean(row.iloc[8]) if len(row) > 8 else None,
"note": clean(row.iloc[9]) if len(row) > 9 else None,
}
raw_rows.append(raw)
if seq_int is not None:
numbered.append(raw)
print(f" 编号门店数: {len(numbered)}")
# 清理旧数据
cur.execute("TRUNCATE public.sales_store_location_mapping RESTART IDENTITY CASCADE")
cur.execute("DELETE FROM public.store_location_master WHERE source_file = %s OR source_file = 'sales_db_placeholder'", (source_file,))
cur.execute("DELETE FROM public.store_location_source_rows WHERE source_file = %s", (source_file,))
# 导入源行
source_values = [(
source_file, r["row"], r["seq"], r["name"], r["company"], r["brand"], r["address"],
r["area"], r["opened"], r["lease"], r["license"], r["note"]
) for r in raw_rows]
execute_values(cur, """
INSERT INTO public.store_location_source_rows
(source_file, source_row, source_store_no, store_short_name, company_name, brand_name,
business_address, area_raw, opened_raw, lease_expiry_raw, license_raw, note)
VALUES %s
""", source_values, page_size=500)
print(f" 源行导入: {len(source_values)}")
# 构建主表数据
masters = []
for r in numbered:
area_sqm, area_method = parse_area(r["area"])
province, city, district = parse_admin(r["address"])
lat, lon, display, precision, confidence = fallback_geocode(province, city, district, r["address"])
gcj_lat, gcj_lon = wgs84_to_gcj02(lat, lon)
name = r["name"] or f"未命名门店{r['seq']}"
if "停业" in name:
status = "停业"
elif r["opened"] == "未开业":
status = "未开业"
else:
status = "在册"
masters.append({
**r, "area_sqm": area_sqm, "area_method": area_method,
"opened_date": parse_date(r["opened"]), "lease_date": parse_date(r["lease"]),
"license_date": parse_date(r["license"]), "status": status,
"province": province, "city": city, "district": district,
"lat": lat, "lon": lon, "gcj_lat": gcj_lat, "gcj_lon": gcj_lon,
"display": display, "precision": precision, "confidence": confidence,
})
# 占位门店
placeholders = [
{"name": "甄选商城店", "address": None, "province": None, "city": None, "district": None,
"status": "线上虚拟门店", "precision": "not_applicable", "display": None, "confidence": 0.0},
{"name": "西安含光店", "address": "陕西省西安市含光路(具体门牌待补)",
"province": "陕西省", "city": "西安市", "district": None,
"status": "地址待补", "precision": "city_centroid", "display": "陕西省西安市", "confidence": 0.10},
]
for i, p in enumerate(placeholders, start=1):
coord = ADMIN_CENTROIDS.get(f"{p['province']}{p['city']}") if p["province"] else None
lat, lon = coord if coord else (None, None)
gcj_lat, gcj_lon = wgs84_to_gcj02(lat, lon)
masters.append({
"row": None, "seq": 9000 + i, "name": p["name"], "company": None,
"brand": "西部马华牛肉面", "address": p["address"], "area": None,
"opened": None, "lease": None, "license": None, "note": "经营数据占位记录",
"area_sqm": None, "area_method": "missing", "opened_date": None,
"lease_date": None, "license_date": None, "status": p["status"],
"province": p["province"], "city": p["city"], "district": p["district"],
"lat": lat, "lon": lon, "gcj_lat": gcj_lat, "gcj_lon": gcj_lon,
"display": p["display"], "precision": p["precision"], "confidence": p["confidence"],
})
# 导入主表
location_ids = {}
for m in masters:
provider = "offline_admin_centroid" if m["lat"] is not None else "none"
geocode_status = "fallback_low_precision" if m["lat"] is not None else m["precision"]
src_file = source_file if m["seq"] < 9000 else "sales_db_placeholder"
cur.execute("""
INSERT INTO public.store_location_master
(source_file, source_row, source_store_no, store_short_name, company_name, brand_name,
business_address, area_raw, area_sqm, area_parse_method, opened_raw, opened_date,
lease_expiry_raw, lease_expiry_date, license_raw, license_date, operating_status,
province, city, district, geocode_query, geocode_provider, geocode_status,
geocode_precision, geocode_confidence, geocode_display_name,
latitude_wgs84, longitude_wgs84, latitude_gcj02, longitude_gcj02, geocode_raw, geocoded_at)
VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,
%s,%s,%s,%s,%s, now())
RETURNING location_id
""", (
src_file, m["row"], m["seq"], m["name"], m["company"], m["brand"], m["address"],
m["area"], m["area_sqm"], m["area_method"], m["opened"], m["opened_date"],
m["lease"], m["lease_date"], m["license"], m["license_date"], m["status"],
m["province"], m["city"], m["district"], m["address"],
provider, geocode_status, m["precision"], m["confidence"], m["display"],
m["lat"], m["lon"], m["gcj_lat"], m["gcj_lon"],
Json({"notice": "行政区中心点兜底,不是门店精确坐标"}) if m["lat"] is not None else None
))
location_ids[m["name"]] = cur.fetchone()[0]
print(f" 主表导入: {len(masters)} 家门店")
# 从DB读取location_ids用于映射
cur.execute("SELECT location_id, store_short_name FROM public.store_location_master")
location_ids = {name: lid for lid, name in cur.fetchall()}
_rebuild_sales_mapping(conn, location_ids, masters)
conn.commit()
cur.close()
print(f"门店位置导入完成")
def _rebuild_sales_mapping(conn, location_ids=None, masters=None):
"""重建销售门店→位置映射表"""
cur = conn.cursor()
# 如果没有传入location_ids,从DB读取
if location_ids is None:
cur.execute("SELECT location_id, store_short_name FROM public.store_location_master")
location_ids = {name: lid for lid, name in cur.fetchall()}
if not location_ids:
print(" 跳过销售门店映射: 无位置数据")
cur.close()
return
# 清理旧映射
cur.execute("TRUNCATE public.sales_store_location_mapping")
# 获取销售门店列表
try:
cur.execute("SELECT store_code, store_name FROM analytics.v_store_scorecard ORDER BY store_name")
sales_stores = cur.fetchall()
except Exception:
sales_stores = []
print(" 警告: analytics.v_store_scorecard 不存在,跳过销售门店映射")
cur.close()
return
# 构建候选列表
if masters:
source_candidates = [(m["name"], normalize_name(m["name"])) for m in masters]
else:
source_candidates = [(name, normalize_name(name)) for name in location_ids.keys()]
mapped = []
for store_code, store_name in sales_stores:
target_name = MANUAL_ALIAS.get(store_name)
method = "manual_alias" if target_name else "normalized_name"
score = 1.0 if target_name else 0.0
if not target_name:
nn = normalize_name(store_name)
exact = [x for x in source_candidates if x[1] == nn and nn]
if exact:
target_name, _ = exact[0]
score = 1.0
else:
ranked = []
for candidate, cn in source_candidates:
s = SequenceMatcher(None, nn, cn).ratio()
if nn and cn and (nn in cn or cn in nn):
s = max(s, 0.92)
ranked.append((s, candidate))
if ranked:
score, target_name = max(ranked)
method = "fuzzy_name"
location_id = location_ids.get(target_name)
if not location_id or score < 0.60:
print(f" 警告: 经营门店无法映射: {store_code} {store_name} -> {target_name} score={score}")
continue
status = "confirmed" if method in {"manual_alias", "normalized_name"} or score >= 0.85 else "reviewed_low_confidence"
note = None if status == "confirmed" else "名称相似匹配,建议业务复核"
mapped.append((store_code, store_name, location_id, method, score, status, note))
if mapped:
execute_values(cur, """
INSERT INTO public.sales_store_location_mapping
(sales_store_code, sales_store_name, location_id, mapping_method, mapping_confidence, mapping_status, review_note)
VALUES %s
""", mapped, page_size=500)
conn.commit()
print(f" 销售门店映射: {len(mapped)}")
cur.close()
def import_store_name_mapping(conn):
"""导入薪资名称↔账单名称映射(静态8条)"""
cur = conn.cursor()
cur.execute("SELECT count(*) FROM public.store_name_mapping")
if cur.fetchone()[0] > 0:
print("store_name_mapping已有数据,跳过")
cur.close()
return
execute_values(
cur,
"INSERT INTO public.store_name_mapping (salary_name, bill_name) VALUES %s",
STORE_NAME_MAPPING,
page_size=100
)
conn.commit()
print(f"store_name_mapping导入完成: {len(STORE_NAME_MAPPING)}")
cur.close()
def import_inventory_store_mapping(conn):
"""从库存成本数据推导库存门店映射"""
cur = conn.cursor()
cur.execute("SELECT count(*) FROM public.inventory_store_mapping")
if cur.fetchone()[0] > 0:
print("inventory_store_mapping已有数据,跳过")
cur.close()
return
# 从库存成本记录中提取唯一的成本单位编码和名称
cur.execute("""
SELECT DISTINCT cost_unit_code, cost_unit_name
FROM public.inventory_cost_records
WHERE report_month = '2026-04-01'
AND cost_unit_code IS NOT NULL
ORDER BY cost_unit_code
""")
cost_units = cur.fetchall()
mappings = []
for code, name in cost_units:
# 成本单位编码与销售门店编码相同的直接映射
mappings.append((
code, name, code, name,
'经营门店', True, '门店编码精确匹配', 100.00, None
))
if mappings:
execute_values(cur, """
INSERT INTO public.inventory_store_mapping
(cost_unit_code, cost_unit_name, sales_store_code, sales_store_name,
unit_type, include_in_operating_cost, mapping_method, mapping_confidence, review_note)
VALUES %s
""", mappings, page_size=500)
conn.commit()
print(f"inventory_store_mapping导入完成: {len(mappings)}")
else:
print("inventory_store_mapping: 无库存成本数据可推导")
cur.close()
def import_operating_expense_store_mapping(conn):
"""从营业费用数据推导费用门店映射"""
cur = conn.cursor()
cur.execute("SELECT count(*) FROM public.operating_expense_store_mapping")
if cur.fetchone()[0] > 0:
print("operating_expense_store_mapping已有数据,跳过")
cur.close()
return
# 从营业费用记录中提取唯一的成本单位名称
cur.execute("""
SELECT DISTINCT cost_unit_source_name
FROM public.operating_expense_records
WHERE report_month = '2026-04-01'
AND cost_unit_source_name IS NOT NULL
ORDER BY cost_unit_source_name
""")
expense_units = cur.fetchall()
# 尝试从销售数据获取门店列表做匹配
try:
cur.execute("SELECT store_code, store_name FROM analytics.dim_store ORDER BY store_code")
sales_stores = cur.fetchall()
except Exception:
sales_stores = []
mappings = []
for (source_name,) in expense_units:
# 标准化名称:去掉"金额"后缀
normalized = re.sub(r"金额$", "", source_name).strip()
# 尝试精确匹配
matched_code = None
matched_name = None
method = "unmapped"
confidence = 0.0
for sc, sn in sales_stores:
if normalized == sn or normalized in sn or sn in normalized:
matched_code = sc
matched_name = sn
method = "标准名称精确匹配"
confidence = 100.0
break
if not matched_code:
# 尝试编码前缀匹配
m = re.match(r"^(\d+)\s+", normalized)
if m:
prefix = m.group(1)
for sc, sn in sales_stores:
if sc == prefix:
matched_code = sc
matched_name = sn
method = "编码前缀匹配"
confidence = 90.0
break
mappings.append((
source_name, normalized,
matched_code, matched_name,
'经营门店', matched_code is not None,
method if matched_code else "待人工确认",
confidence,
None if matched_code else "需人工确认匹配关系"
))
if mappings:
execute_values(cur, """
INSERT INTO public.operating_expense_store_mapping
(cost_unit_source_name, normalized_cost_unit_name, sales_store_code, sales_store_name,
unit_type, include_in_operating_analysis, mapping_method, mapping_confidence, review_note)
VALUES %s
""", mappings, page_size=500)
conn.commit()
print(f"operating_expense_store_mapping导入完成: {len(mappings)}")
else:
print("operating_expense_store_mapping: 无费用数据可推导")
cur.close()
# ============================================================
# Main
# ============================================================
def main():
parser = argparse.ArgumentParser(description='门店位置与映射表导入')
parser.add_argument('--file', required=True, help='各店信息Excel文件路径')
parser.add_argument('--db', default='bill_query', help='目标数据库 (默认bill_query)')
parser.add_argument('--skip-location', action='store_true', help='跳过门店位置导入')
parser.add_argument('--skip-mappings', action='store_true', help='跳过映射表导入')
args = parser.parse_args()
conn = psycopg2.connect(host='localhost', port=5432, dbname=args.db, user='freedak')
conn.autocommit = False
try:
if not args.skip_location:
import_store_location(conn, args.file)
if not args.skip_mappings:
print("\n=== 映射表导入 ===")
import_store_name_mapping(conn)
import_inventory_store_mapping(conn)
import_operating_expense_store_mapping(conn)
print("\n=== 导入完成 ===")
except Exception as e:
conn.rollback()
print(f"错误: {e}", file=sys.stderr)
raise
finally:
conn.close()
if __name__ == '__main__':
main()
+104
View File
@@ -0,0 +1,104 @@
#!/usr/bin/env python3
"""
物化视图按依赖顺序刷新
用法: python3 refresh_materialized_views.py --db bill_query_test
"""
import argparse
import psycopg2
import time
import sys
from config import DB_CONFIG, MATVIEW_LAYERS
def refresh_all(dbname, verbose=True):
conn = psycopg2.connect(
host=DB_CONFIG['host'],
port=DB_CONFIG['port'],
dbname=dbname,
user=DB_CONFIG['user'],
password=DB_CONFIG['password'] or None,
)
conn.autocommit = True
cur = conn.cursor()
total = sum(len(layer) for layer in MATVIEW_LAYERS)
done = 0
failed = []
for layer_idx, layer in enumerate(MATVIEW_LAYERS):
if verbose:
print(f"\n--- L{layer_idx}: {len(layer)} 个物化视图 ---")
for mv in layer:
done += 1
t0 = time.time()
try:
cur.execute(f'REFRESH MATERIALIZED VIEW analytics."{mv}"')
elapsed = time.time() - t0
if verbose:
print(f" [{done}/{total}] OK {mv} ({elapsed:.1f}s)")
except Exception as e:
elapsed = time.time() - t0
err_msg = str(e).strip().split('\n')[0]
if verbose:
print(f" [{done}/{total}] FAIL {mv} ({elapsed:.1f}s): {err_msg}")
failed.append((mv, err_msg))
conn.rollback()
cur.close()
conn.close()
if failed:
print(f"\n=== 完成: {total - len(failed)}/{total} 成功, {len(failed)} 失败 ===")
for mv, err in failed:
print(f" FAIL {mv}: {err}")
# 重试失败项(可能因依赖顺序问题,第二轮能成功)
if len(failed) > 0:
print(f"\n--- 重试 {len(failed)} 个失败项 ---")
conn = psycopg2.connect(
host=DB_CONFIG['host'],
port=DB_CONFIG['port'],
dbname=dbname,
user=DB_CONFIG['user'],
password=DB_CONFIG['password'] or None,
)
conn.autocommit = True
cur = conn.cursor()
retry_failed = []
for mv, _ in failed:
t0 = time.time()
try:
cur.execute(f'REFRESH MATERIALIZED VIEW analytics."{mv}"')
elapsed = time.time() - t0
print(f" OK {mv} ({elapsed:.1f}s)")
except Exception as e:
err_msg = str(e).strip().split('\n')[0]
print(f" FAIL {mv}: {err_msg}")
retry_failed.append(mv)
conn.rollback()
cur.close()
conn.close()
if retry_failed:
print(f"\n最终失败: {retry_failed}")
return 1
else:
print(f"\n=== 全部 {total} 个物化视图刷新成功 ===")
return 0
else:
print(f"\n=== 全部 {total} 个物化视图刷新成功 ===")
return 0
def main():
parser = argparse.ArgumentParser(description='物化视图按依赖顺序刷新')
parser.add_argument('--db', default='bill_query_test', help='目标数据库')
args = parser.parse_args()
print(f"\n=== 物化视图刷新 ===")
print(f"数据库: {args.db}")
rc = refresh_all(args.db)
sys.exit(rc)
if __name__ == '__main__':
main()
+195
View File
@@ -0,0 +1,195 @@
#!/usr/bin/env python3
"""
一键全量导入 + 物化视图刷新
用法: python3 run_all.py --month 2026-04-01 --db bill_query_test
python3 run_all.py --month 2026-04-01 --db bill_query_test --skip-import # 仅刷新物化
python3 run_all.py --month 2026-04-01 --db bill_query_test --skip-views # 仅导入
python3 run_all.py --month 2026-04-01 --db bill_query_test --only bill_records # 仅导入某类
"""
import argparse
import os
import subprocess
import sys
import time
from config import DB_CONFIG, get_data_sources, PIPELINE_DIR
def run_script(name, cmd, cwd=None):
"""运行子进程并实时输出"""
print(f"\n{'='*60}")
print(f" 执行: {name}")
print(f" 命令: {' '.join(cmd)}")
print(f"{'='*60}")
t0 = time.time()
result = subprocess.run(cmd, cwd=cwd or PIPELINE_DIR)
elapsed = time.time() - t0
status = "成功" if result.returncode == 0 else f"失败(rc={result.returncode})"
print(f"{name}: {status} ({elapsed:.1f}s)")
return result.returncode == 0
def main():
parser = argparse.ArgumentParser(description='全量数据导入与物化刷新流水线')
parser.add_argument('--month', required=True, help='报告月份 (YYYY-MM-01)')
parser.add_argument('--db', default='bill_query_test', help='目标数据库')
parser.add_argument('--skip-import', action='store_true', help='跳过数据导入,仅刷新物化视图')
parser.add_argument('--skip-views', action='store_true', help='跳过物化视图刷新')
parser.add_argument('--only', default=None,
help='仅导入指定数据集: bill_records, monthly, salary, store_location, derived')
parser.add_argument('--diagnosis-date', default=None, help='诊断日期 (默认今天)')
args = parser.parse_args()
sources = get_data_sources(args.month)
if not sources:
print(f"错误: 无法找到月份 {args.month} 的数据源")
sys.exit(1)
print(f"\n{'#'*60}")
print(f" 数据导入与物化刷新流水线")
print(f" 月份: {args.month}")
print(f" 数据库: {args.db}")
print(f" 数据源根: {sources.get('bill_records', 'N/A')}")
print(f"{'#'*60}")
py = sys.executable
results = []
# ============================================================
# Step 1: 数据导入
# ============================================================
if not args.skip_import:
target = args.only
# 1.1 薪资+考勤
if target in (None, 'salary'):
cmd = [py, 'import_salary_attendance.py', '--month', args.month, '--db', args.db]
sal_file = sources.get('salary')
att_file = sources.get('attendance')
if sal_file and os.path.isfile(sal_file):
cmd.extend(['--salary-file', sal_file])
if att_file and os.path.isfile(att_file):
cmd.extend(['--attendance-file', att_file])
ok = run_script("薪资+考勤导入", cmd)
results.append(('薪资+考勤', ok))
# 1.2 账单查询原始数据(bill_records + bill_columns
if target in (None, 'bill_records'):
bill_dir = sources.get('bill_records')
if bill_dir and os.path.exists(bill_dir):
ok = run_script("账单查询导入(bill_records)", [
py, 'import_bill_records.py',
'--month', args.month,
'--file', bill_dir,
'--db', args.db,
])
results.append(('bill_records', ok))
else:
print(f"\n 跳过 bill_records: 路径不存在 {bill_dir}")
results.append(('bill_records', False))
# 1.3 月度业务数据(库存/销售/成本/费用/中央厨房/配送)
if target in (None, 'monthly'):
monthly_datasets = [
('inventory', 'inventory', None),
('dish_sales', 'dish_sales', None),
('dish_cost', 'dish_cost', None),
('operating_expense', 'operating_expense', None),
('central_kitchen_finished', 'central_kitchen', 'finished'),
('central_kitchen_recipe', 'central_kitchen', 'recipe'),
('central_kitchen_material', 'central_kitchen', 'material'),
('central_kitchen_processing', 'central_kitchen', 'processing'),
('distribution', 'distribution', None),
('distribution_2', 'distribution', None),
]
for src_key, dataset, ck_type in monthly_datasets:
filepath = sources.get(src_key)
if not filepath or not os.path.exists(filepath):
print(f"\n 跳过 {dataset}/{ck_type or ''}: 文件不存在 {filepath}")
results.append((f'{dataset}/{ck_type or src_key}', False))
continue
cmd = [
py, 'import_monthly_data.py',
'--dataset', dataset,
'--month', args.month,
'--file', filepath,
'--db', args.db,
]
if ck_type:
cmd.extend(['--ck-type', ck_type])
label = f"月度数据-{dataset}" + (f"-{ck_type}" if ck_type else f"({os.path.basename(filepath)})")
ok = run_script(label, cmd)
results.append((label, ok))
# 1.4 门店位置与映射表
if target in (None, 'store_location'):
store_file = sources.get('store_location')
if store_file and os.path.exists(store_file):
ok = run_script("门店位置与映射表导入", [
py, 'import_store_location.py',
'--file', store_file,
'--db', args.db,
])
results.append(('门店位置', ok))
else:
print(f"\n 跳过门店位置: 文件不存在 {store_file}")
results.append(('门店位置', False))
# 1.5 派生分析数据
if target in (None, 'derived'):
diag_date = args.diagnosis_date or ''
cmd = [
py, 'import_derived_data.py',
'--month', args.month,
'--db', args.db,
]
if diag_date:
cmd.extend(['--diagnosis-date', diag_date])
ok = run_script("派生分析数据生成", cmd)
results.append(('派生数据', ok))
# ============================================================
# Step 2: 物化视图刷新
# ============================================================
if not args.skip_views:
ok = run_script("物化视图刷新", [
py, 'refresh_materialized_views.py',
'--db', args.db,
], cwd=PIPELINE_DIR)
results.append(('物化视图', ok))
# ============================================================
# Step 3: 验证
# ============================================================
ok = run_script("数据一致性验证", [
py, 'verify.py',
'--db', args.db,
], cwd=PIPELINE_DIR)
results.append(('验证', ok))
# ============================================================
# 汇总
# ============================================================
print(f"\n{'#'*60}")
print(f" 流水线执行汇总")
print(f"{'#'*60}")
all_ok = True
for name, ok in results:
status = "✓ 成功" if ok else "✗ 失败"
print(f" {status} {name}")
if not ok:
all_ok = False
if all_ok:
print(f"\n 全部完成!")
sys.exit(0)
else:
print(f"\n 部分失败,请检查上方日志")
sys.exit(1)
if __name__ == '__main__':
main()
+111
View File
@@ -0,0 +1,111 @@
#!/usr/bin/env python3
"""
测试库与正式库行数对比验证
用法: python3 verify.py --db bill_query_test [--prod bill_query]
"""
import argparse
import psycopg2
import sys
from config import DB_CONFIG
def get_table_counts(dbname):
conn = psycopg2.connect(
host=DB_CONFIG['host'],
port=DB_CONFIG['port'],
dbname=dbname,
user=DB_CONFIG['user'],
password=DB_CONFIG['password'] or None,
)
cur = conn.cursor()
cur.execute("""
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_type = 'BASE TABLE'
ORDER BY table_name
""")
tables = [r[0] for r in cur.fetchall()]
counts = {}
for tbl in tables:
cur.execute(f"SELECT count(*) FROM public.{tbl}")
counts[tbl] = cur.fetchone()[0]
# 物化视图行数
cur.execute("""
SELECT matviewname
FROM pg_matviews
WHERE schemaname = 'analytics'
ORDER BY matviewname
""")
mvs = [r[0] for r in cur.fetchall()]
mv_counts = {}
for mv in mvs:
try:
cur.execute(f'SELECT count(*) FROM analytics."{mv}"')
mv_counts[mv] = cur.fetchone()[0]
except Exception:
mv_counts[mv] = -1
conn.rollback()
cur.close()
conn.close()
return counts, mv_counts
def main():
parser = argparse.ArgumentParser(description='测试库与正式库数据一致性验证')
parser.add_argument('--db', default='bill_query_test', help='测试库名')
parser.add_argument('--prod', default='bill_query', help='正式库名')
args = parser.parse_args()
print(f"\n=== 数据一致性验证 ===")
print(f"正式库: {args.prod}")
print(f"测试库: {args.db}")
prod_counts, prod_mv = get_table_counts(args.prod)
test_counts, test_mv = get_table_counts(args.db)
# 基础表对比
print(f"\n--- 基础表 ({len(prod_counts)} 张) ---")
ok = 0
diff = 0
for tbl in sorted(prod_counts.keys()):
p = prod_counts[tbl]
t = test_counts.get(tbl, 'MISSING')
flag = 'OK' if t == p else 'DIFF'
if flag == 'OK':
ok += 1
else:
diff += 1
if flag != 'OK' or True: # 显示全部
print(f" {flag:4s} {tbl:45s} prod={p:<12s} test={t}")
print(f"\n 基础表: {ok} OK, {diff} DIFF")
# 物化视图对比
print(f"\n--- 物化视图 ({len(prod_mv)} 个) ---")
mv_ok = 0
mv_diff = 0
for mv in sorted(prod_mv.keys()):
p = prod_mv[mv]
t = test_mv.get(mv, 'MISSING')
flag = 'OK' if t == p else 'DIFF'
if flag == 'OK':
mv_ok += 1
else:
mv_diff += 1
print(f" {flag:4s} {mv:45s} prod={p:<12s} test={t}")
print(f"\n 物化视图: {mv_ok} OK, {mv_diff} DIFF")
print(f"\n=== 总计: {ok + mv_ok} OK, {diff + mv_diff} DIFF ===")
if diff + mv_diff > 0:
sys.exit(1)
sys.exit(0)
if __name__ == '__main__':
main()
+145
View File
@@ -0,0 +1,145 @@
#!/usr/bin/env python3
"""
对比验证脚本比较测试库与正式库的4月数据
用法: python3 verify_import.py
"""
import psycopg2
def connect(dbname):
return psycopg2.connect(host='localhost', port=5432, dbname=dbname, user='freedak')
def compare_table(test_cur, prod_cur, table_name, where_clause='1=1', key_cols=None, sum_cols=None):
"""对比两个库中同一表的数据"""
print(f"\n--- {table_name} ---")
# Row count
test_cur.execute(f"SELECT count(*) FROM public.{table_name} WHERE {where_clause}")
test_count = test_cur.fetchone()[0]
prod_cur.execute(f"SELECT count(*) FROM public.{table_name} WHERE {where_clause}")
prod_count = prod_cur.fetchone()[0]
match = "" if test_count == prod_count else ""
print(f" 行数: 测试库={test_count}, 正式库={prod_count} {match}")
# Sum comparison
if sum_cols:
for col in sum_cols:
test_cur.execute(f"SELECT round(coalesce(sum({col}),0)::numeric, 2) FROM public.{table_name} WHERE {where_clause}")
test_sum = test_cur.fetchone()[0]
prod_cur.execute(f"SELECT round(coalesce(sum({col}),0)::numeric, 2) FROM public.{table_name} WHERE {where_clause}")
prod_sum = prod_cur.fetchone()[0]
match = "" if abs(float(test_sum or 0) - float(prod_sum or 0)) < 0.01 else ""
print(f" {col}合计: 测试库={test_sum}, 正式库={prod_sum} {match}")
return test_count == prod_count
def main():
test_conn = connect('bill_query_test')
prod_conn = connect('bill_query')
test_cur = test_conn.cursor()
prod_cur = prod_conn.cursor()
print("=" * 60)
print(" 数据对比验证: 测试库 vs 正式库 (4月数据)")
print("=" * 60)
results = []
# 1. 库存成本
results.append(compare_table(
test_cur, prod_cur, 'inventory_cost_records',
where_clause="report_month = '2026-04-01'",
sum_cols=['consumption_amount', 'opening_amount', 'ending_amount', 'purchase_amount']
))
# 2. 菜品销售明细 (测试库只导入了1个文件,按文件对比)
test_cur.execute("SELECT DISTINCT source_file FROM public.dish_sales_details")
test_files = [r[0] for r in test_cur.fetchall()]
for sf in test_files:
results.append(compare_table(
test_cur, prod_cur, 'dish_sales_details',
where_clause=f"source_file = '{sf}'",
sum_cols=['gross_amount', 'received_amount']
))
# 3. 菜品成本
results.append(compare_table(
test_cur, prod_cur, 'dish_cost_analysis_summary',
where_clause="1=1",
sum_cols=['theoretical_cost', 'actual_cost', 'sales_amount']
))
# 3b. 菜品成本原料明细
results.append(compare_table(
test_cur, prod_cur, 'dish_cost_analysis_material_detail',
where_clause="1=1",
sum_cols=['theoretical_amount', 'actual_amount']
))
# 4. 营业费用
results.append(compare_table(
test_cur, prod_cur, 'operating_expense_records',
where_clause="report_month = '2026-04-01'",
sum_cols=['amount']
))
# 5. 中央厨房
ck_tables = {
'central_kitchen_finished_receipt': ('receipt_date', ['amount', 'quantity']),
'central_kitchen_recipe_consumption': ('business_date', ['theoretical_quantity', 'theoretical_amount', 'issue_quantity', 'issue_amount']),
'central_kitchen_material_daily': ('business_date', ['amount']),
'central_kitchen_processing_cost': ('report_month', ['theoretical_cost', 'actual_cost']),
}
for tbl, (date_col, sums) in ck_tables.items():
# Check which sum cols actually exist
test_cur.execute(f"SELECT column_name FROM information_schema.columns WHERE table_name='{tbl}'")
actual_cols = [r[0] for r in test_cur.fetchall()]
valid_sums = [c for c in sums if c in actual_cols]
if date_col == 'report_month':
where = f"{date_col} = '2026-04-01'"
else:
where = f"{date_col} >= '2026-04-01' AND {date_col} < '2026-05-01'"
results.append(compare_table(
test_cur, prod_cur, tbl,
where_clause=where,
sum_cols=valid_sums if valid_sums else None
))
# 6. 配送明细
results.append(compare_table(
test_cur, prod_cur, 'distribution_detail_records',
where_clause="report_month = '2026-04-01'",
sum_cols=['cost_total_amount', 'outbound_total_amount', 'total_quantity']
))
# 7. 薪资
results.append(compare_table(
test_cur, prod_cur, 'salary_detail_records',
where_clause="1=1",
sum_cols=['net_pay', 'gross_pay']
))
# 8. 考勤
results.append(compare_table(
test_cur, prod_cur, 'attendance_records',
where_clause="1=1",
sum_cols=None
))
# Summary
print("\n" + "=" * 60)
passed = sum(results)
total = len(results)
print(f" 通过: {passed}/{total}")
if passed == total:
print(" ✅ 所有对比通过")
else:
print(f"{total - passed} 项对比失败")
print("=" * 60)
test_cur.close()
prod_cur.close()
test_conn.close()
prod_conn.close()
if __name__ == '__main__':
main()
+419
View File
@@ -0,0 +1,419 @@
# 后端 API 完整列表
## 路由挂载(server/src/index.ts
| 前缀 | 路由文件 | 说明 |
|------|----------|------|
| `/api/auth` | auth.ts | 认证 |
| `/api/admin` | admin.ts | 平台管理(租户管理) |
| `/api` | data.ts | 核心数据(overview/stores/cost/risk等) |
| `/api/tasks` | tasks.ts | 任务管理+本体查询 |
| `/api/cost-analysis` | cost-analysis.ts | 成本分析 |
| `/api/store-expense` | store-expense.ts | 门店费用 |
| `/api/smart-scheduling` | smart-scheduling.ts | 智能排班 |
| `/api/situational-awareness` | situational-awareness.ts | 态势感知 |
| `/api/analytics-enhanced` | analytics-enhanced.ts | 增强分析 |
| `/api/tts` | tts.ts | 语音合成 |
| `/api/target` | target.ts | 目标管理 |
| `/api/scheduler` | scheduler.ts | 调度管理 |
| `/api/alert` | alert.ts | 预警管理 |
| `/api/store-grade` | store-grade.ts | 门店分级 |
| `/api/product` | product.ts | 产品管理 |
| `/api/enterprise` | enterprise.ts | 企业管理 |
| `/api/intelligence` | intelligence.ts | 智能分析 |
| `/api/promotion` | promotion.ts | 促销分析 |
---
## 1. 认证 `/api/auth`
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/auth/login` | 用户登录 |
| GET | `/auth/me` | 获取当前用户信息 |
## 2. 平台管理 `/api/admin`
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/admin/login` | 平台管理员登录 |
| GET | `/admin/tenants` | 获取所有租户 |
| GET | `/admin/tenants/:tenantId` | 获取单个租户详情 |
| POST | `/admin/tenants` | 创建租户 |
| PUT | `/admin/tenants/:tenantId` | 更新租户 |
## 3. 核心数据 `/api`
| 方法 | 路径 | 说明 | 数据源 |
|------|------|------|--------|
| GET | `/overview` | 经营总览 | `mv_overview_monthly` + `bill_fact` |
| GET | `/overview/daily` | 日度总览 | `v_overview_daily` |
| GET | `/overview/profit-waterfall` | 利润瀑布 | `mv_store_risk_rating_monthly` + `mv_store_operating_expense_monthly` + `bill_fact` |
| GET | `/overview/store-profit-ranking` | 门店利润排名 | `mv_store_operating_expense_monthly` |
| GET | `/overview/profit-opportunity` | 利润机会池 | `mv_store_risk_rating_monthly` + `mv_store_operating_expense_monthly` + `mv_dish_sku_abc_monthly` |
| GET | `/overview/yoy` | 同比分析 | `mv_overview_monthly` |
| GET | `/overview/mom` | 环比分析 | `mv_overview_monthly` |
| GET | `/overview/trend` | 趋势分析 | `mv_overview_monthly` |
| GET | `/overview/profit-trend` | 利润趋势 | `mv_store_operating_expense_monthly` |
| GET | `/overview/period` | 时段分析 | `v_hourly_summary` |
| GET | `/stores` | 门店列表 | `mv_store_risk_rating_monthly` |
| GET | `/stores/risk` | 门店风险 | `mv_store_risk_rating_monthly` |
| GET | `/stores/priority` | 门店优先级 | `mv_store_action_priority_deep_monthly` |
| GET | `/stores/quadrant` | 门店象限 | `mv_store_risk_rating_monthly` |
| GET | `/stores/:code` | 门店详情 | `bill_records` (直接查原始表) |
| GET | `/stores/:code/daily` | 门店日度 | `bill_records` (直接查原始表) |
| GET | `/stores/:code/meal-period` | 门店餐段 | `bill_records` (直接查原始表) |
| GET | `/stores/:code/category-mix` | 门店品类结构 | `mv_store_category_mix_monthly` |
| GET | `/stores/:code/cost` | 门店成本 | `mv_store_theoretical_actual_cost_monthly` |
| GET | `/stores/:code/member` | 门店会员 | `v_store_member_monthly_activity` |
| GET | `/stores/:code/anomalies` | 门店异常 | `v_anomaly_bills` |
| GET | `/stores/:code/staffing` | 门店人效 | `attendance_records` + `bill_records` |
| GET | `/cost/comparison` | 成本对比 | `mv_store_theoretical_actual_cost_monthly` |
| GET | `/cost/category-benchmark` | 品类成本基准 | `mv_inventory_cost_classified_monthly` |
| GET | `/cost/inventory` | 库存成本 | `inventory_cost_records` |
| GET | `/platform/economics` | 平台经济 | `mv_store_platform_economics_monthly` |
| GET | `/member/comparison` | 会员对比 | `v_member_comparison` |
| GET | `/member/repeat` | 会员复购 | `v_member_repeat_summary_monthly` |
| GET | `/sku/abc` | SKU ABC分类 | `mv_dish_sku_abc_monthly` |
| GET | `/sku/category` | SKU品类 | `mv_dish_sku_summary_monthly` |
| GET | `/sku/attach` | SKU关联 | `mv_dish_basket_monthly` |
| GET | `/risk/anomaly` | 异常风险 | `v_anomaly_summary` |
| GET | `/risk/zero-received` | 零实收风险 | `v_zero_received_store_summary` |
| GET | `/risk/cashier` | 收银风险 | `v_cashier_risk` |
| GET | `/marketing/plans` | 营销计划 | `v_marketing_plan_summary` |
| GET | `/benchmark/composite` | 综合基准 | `mv_store_benchmark_composite_monthly` |
| GET | `/time/weekday` | 星期分析 | `v_weekday_summary` |
| GET | `/time/hourly` | 小时分析 | `v_hourly_summary` |
| GET | `/channel` | 渠道分析 | `v_channel_daily` |
| GET | `/data-quality` | 数据质量 | `v_data_quality_check` |
| GET | `/region/summary` | 区域汇总 | `v_region_summary` |
| GET | `/site-selection/profile` | 选址画像 | `mv_store_site_profile_monthly` |
| GET | `/site-selection/segment-benchmark` | 分段基准 | `mv_site_segment_benchmark_monthly` |
| GET | `/site-selection/replication` | 选址复制 | `mv_store_site_replication_monthly` |
| GET | `/site-selection/overlap-risk` | 重叠风险 | `mv_store_overlap_risk_monthly` |
| GET | `/site-selection/district-benchmark` | 区域基准 | `mv_district_site_benchmark_monthly` |
| GET | `/revenue/channel` | 渠道营收 | `v_channel_daily` |
| GET | `/revenue/meal-period` | 餐段营收 | `v_meal_period_daily` |
| GET | `/revenue/store-ranking` | 门店营收排名 | `mv_store_risk_rating_monthly` |
| GET | `/revenue/daily-summary` | 日度营收汇总 | `mv_daily_revenue` |
| GET | `/bank/report` | 银行报表 | `mv_store_risk_rating_monthly` + `mv_store_operating_expense_monthly` + `bill_fact` |
| GET | `/central-kitchen/dashboard` | 中央厨房总览 | `central_kitchen_*` 系列表 |
| GET | `/central-kitchen/bom-penetration` | BOM穿透 | `central_kitchen_*` 系列表 |
| GET | `/distribution/reconciliation` | 配送对账 | `distribution_detail_records` |
| GET | `/sales-driven/production-plan` | 销售驱动生产计划 | `bill_fact` + `fact_recipe_bom` |
## 4. 任务管理 `/api/tasks`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/tasks` | 任务列表 |
| POST | `/tasks` | 创建任务 |
| POST | `/tasks/auto-generate` | 自动生成任务 |
| GET | `/tasks/weekly-check` | 周度检查 |
| GET | `/tasks/monthly-review` | 月度复盘 |
| GET | `/tasks/monthly-review/completion` | 月度复盘完成度 |
| GET | `/tasks/monthly-review/activity-list` | 月度复盘活动列表 |
| GET | `/tasks/monthly-review/sku-governance` | SKU治理 |
| GET | `/tasks/monthly-review/indicator-effectiveness` | 指标有效性 |
| GET | `/tasks/followup` | 跟进任务 |
| GET | `/tasks/grade-change` | 分级变更 |
| GET | `/tasks/practices` | 最佳实践列表 |
| POST | `/tasks/practices` | 创建最佳实践 |
| GET | `/tasks/practices/:id/replication-result` | 实践复制结果 |
| POST | `/tasks/practices/:id/replicate` | 复制实践 |
| POST | `/tasks/practices/:id/promote` | 推广实践 |
| GET | `/tasks/indicators` | 指标列表 |
| POST | `/tasks/indicators` | 创建指标 |
| PUT | `/tasks/indicators/:id/threshold` | 更新指标阈值 |
| GET | `/tasks/loop-health` | 闭环健康度 |
| POST | `/tasks/notifications/dispatch` | 通知派发 |
| GET | `/tasks/stores/:code/daily-card` | 门店日度卡片 |
| GET | `/tasks/:id` | 任务详情 |
| PUT | `/tasks/:id` | 更新任务 |
| PUT | `/tasks/:id/execute` | 执行任务 |
| PUT | `/tasks/:id/weekly-check` | 周度检查 |
| PUT | `/tasks/:id/verify` | 验证任务 |
| POST | `/tasks/:id/rollback` | 回滚任务 |
| GET | `/tasks/ontology/overview` | 本体总览 |
| GET | `/tasks/ontology/dim/:table` | 维度表查询 |
| GET | `/tasks/ontology/fact/:table` | 事实表查询 |
| GET | `/tasks/ontology/enum/:table` | 枚举表查询 |
| GET | `/tasks/ontology/metrics` | 指标查询 |
## 5. 成本分析 `/api/cost-analysis`
| 方法 | 路径 | 说明 | 数据源 |
|------|------|------|--------|
| GET | `/cost-analysis/overview` | 成本总览 | `dish_cost_analysis_summary` |
| GET | `/cost-analysis/category-comparison` | 品类成本对比 | `dish_cost_analysis_summary` |
| GET | `/cost-analysis/margin-deviation` | 毛利率偏差 | `dish_cost_analysis_summary` |
| GET | `/cost-analysis/variance-top` | 成本差异TOP | `dish_cost_analysis_summary` |
| GET | `/cost-analysis/menu-engineering` | 菜单工程 | `dish_cost_analysis_summary` |
| GET | `/cost-analysis/profitability` | 盈利能力 | `dish_cost_analysis_summary` |
| GET | `/cost-analysis/pricing` | 定价分析 | `dish_cost_analysis_summary` |
| GET | `/cost-analysis/material-variance` | 原料差异 | `dish_cost_analysis_material_detail` |
| GET | `/cost-analysis/loss-distribution` | 损耗分布 | `dish_cost_analysis_material_detail` |
| GET | `/cost-analysis/material-loss-top` | 原料损耗TOP | `dish_cost_analysis_material_detail` |
| GET | `/cost-analysis/material-type-loss` | 原料类型损耗 | `dish_cost_analysis_material_detail` |
| GET | `/cost-analysis/bom-overview` | BOM总览 | `fact_recipe_bom` |
| GET | `/cost-analysis/bom-complexity` | BOM复杂度 | `fact_recipe_bom` |
| GET | `/cost-analysis/bom-high-loss` | BOM高损耗 | `fact_recipe_bom` |
| GET | `/cost-analysis/bom-missing` | BOM缺失 | `dish_cost_analysis_summary` |
| GET | `/cost-analysis/bom-composition` | BOM组成 | `fact_recipe_bom` |
| GET | `/cost-analysis/material-sharing` | 原料共享 | `fact_recipe_bom` |
| GET | `/cost-analysis/unique-material-risk` | 独有原料风险 | `fact_recipe_bom` |
| POST | `/cost-analysis/sku-simplify-simulate` | SKU精简模拟 | `fact_recipe_bom` |
| GET | `/cost-analysis/material-demand` | 原料需求 | `fact_recipe_bom` |
| GET | `/cost-analysis/packaging-overview` | 包装总览 | `dish_cost_analysis_summary` |
| GET | `/cost-analysis/packaging-detail` | 包装明细 | `dish_cost_analysis_material_detail` |
| GET | `/cost-analysis/data-quality` | 数据质量 | `dish_cost_analysis_summary` |
| GET | `/cost-analysis/unmatched-dishes` | 未匹配菜品 | `dish_cost_analysis_summary` |
| GET | `/cost-analysis/unmatched-materials` | 未匹配原料 | `dish_cost_analysis_material_detail` |
| GET | `/cost-analysis/store-overview` | 门店成本总览 | `mv_store_theoretical_actual_cost_monthly` |
| GET | `/cost-analysis/store-map` | 门店成本地图 | `mv_store_theoretical_actual_cost_monthly` |
| GET | `/cost-analysis/store-ranking` | 门店成本排名 | `mv_store_theoretical_actual_cost_monthly` |
| GET | `/cost-analysis/scatter` | 散点图数据 | `mv_store_theoretical_actual_cost_monthly` |
| POST | `/cost-analysis/diagnosis/generate` | 生成诊断 | `mv_store_theoretical_actual_cost_monthly` |
| GET | `/cost-analysis/diagnosis` | 诊断列表 | `dish_diagnosis_snapshot` |
| GET | `/cost-analysis/adjustment` | 调整列表 | `dish_adjustment_log` |
| POST | `/cost-analysis/adjustment` | 创建调整 | `dish_adjustment_log` |
| PUT | `/cost-analysis/adjustment/:id` | 更新调整 | `dish_adjustment_log` |
| GET | `/cost-analysis/adjustment/:id/verify` | 验证调整 | `dish_adjustment_result` |
| POST | `/cost-analysis/adjustment/:id/result` | 调整结果 | `dish_adjustment_result` |
## 6. 门店费用 `/api/store-expense`
| 方法 | 路径 | 说明 | 数据源 |
|------|------|------|--------|
| GET | `/store-expense/overview` | 费用总览 | `mv_store_operating_expense_monthly` |
| GET | `/store-expense/expense-structure` | 费用结构 | `v_operating_expense_account_monthly` |
| GET | `/store-expense/store-ranking` | 门店费用排名 | `mv_store_operating_expense_monthly` |
| GET | `/store-expense/store-contribution` | 门店贡献利润 | `mv_store_operating_expense_monthly` |
| GET | `/store-expense/rent-risk` | 房租风险 | `mv_store_operating_expense_monthly` |
| GET | `/store-expense/delivery-commission` | 外卖佣金 | `mv_store_operating_expense_monthly` |
| GET | `/store-expense/efficiency` | 人效坪效 | `mv_store_operating_expense_monthly` |
| GET | `/store-expense/fixed-variable` | 固定/变动费用 | `mv_store_operating_expense_monthly` |
| GET | `/store-expense/break-even` | 盈亏平衡 | `mv_store_operating_expense_monthly` |
| GET | `/store-expense/loss-diagnosis` | 亏损诊断 | `mv_store_operating_expense_monthly` |
| GET | `/store-expense/store-evaluation` | 门店评估 | `mv_store_operating_expense_monthly` |
| GET | `/store-expense/data-quality` | 费用数据质量 | `v_operating_expense_data_quality` |
## 7. 智能排班 `/api/smart-scheduling`
| 方法 | 路径 | 说明 | 数据源 |
|------|------|------|--------|
| GET | `/smart-scheduling/traffic-heatmap` | 流量热力图 | `bill_records` |
| GET | `/smart-scheduling/meal-period-traffic` | 餐段流量 | `bill_records` |
| GET | `/smart-scheduling/traffic-heatmap-staffing` | 流量+排班 | `bill_records` + `attendance_records` |
| GET | `/smart-scheduling/dow-traffic` | 星期流量 | `bill_records` |
| GET | `/smart-scheduling/traffic-overview` | 流量总览 | `bill_records` |
| GET | `/smart-scheduling/staffing-match` | 排班匹配 | `bill_records` + `attendance_records` |
| GET | `/smart-scheduling/stores` | 门店列表 | `bill_records` |
| GET | `/smart-scheduling/efficiency-ranking` | 人效排名 | `bill_records` + `attendance_records` |
| GET | `/smart-scheduling/position-distribution` | 岗位分布 | `attendance_records` |
| GET | `/smart-scheduling/scheduling-suggestion` | 排班建议 | `bill_records` + `attendance_records` |
| GET | `/smart-scheduling/attendance-alert` | 考勤预警 | `attendance_records` |
| GET | `/smart-scheduling/attendance-summary` | 考勤汇总 | `attendance_records` |
| GET | `/smart-scheduling/employee-analysis` | 员工分析 | `attendance_records` |
| GET | `/smart-scheduling/position-salary-compare` | 岗位薪资对比 | `salary_detail_records` |
| GET | `/smart-scheduling/turnover-stats` | 流失率统计 | `attendance_records` |
| GET | `/smart-scheduling/overall-analysis` | 综合分析 | `bill_records` + `attendance_records` |
| GET | `/smart-scheduling/staffing-forecast` | 排班预测 | `bill_records` + `attendance_records` |
## 8. 态势感知 `/api/situational-awareness`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/situational-awareness/health-score` | 健康度评分 |
| GET | `/situational-awareness/alerts` | 预警列表 |
| GET | `/situational-awareness/correlation` | 关联分析 |
| GET | `/situational-awareness/forecast` | 预测分析 |
## 9. 增强分析 `/api/analytics-enhanced`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/analytics-enhanced/member/ltv` | 会员LTV |
| GET | `/analytics-enhanced/menu-engineering/actions` | 菜单工程行动 |
| GET | `/analytics-enhanced/dish-pair/recommendations` | 菜品搭配推荐 |
| GET | `/analytics-enhanced/region/comparison` | 区域对比 |
| GET | `/analytics-enhanced/region/kpi-forecast` | 区域KPI预测 |
| GET | `/analytics-enhanced/store/daily-target` | 门店日度目标 |
| GET | `/analytics-enhanced/store/member-activity` | 门店会员活动 |
| GET | `/analytics-enhanced/employee/performance` | 员工绩效 |
| GET | `/analytics-enhanced/inventory/turnover` | 库存周转 |
| GET | `/analytics-enhanced/inventory/near-expiry` | 临期库存 |
| GET | `/analytics-enhanced/marketing/roi` | 营销ROI |
| GET | `/analytics-enhanced/region/inspection-plan` | 区域巡检计划 |
| GET | `/analytics-enhanced/kpi` | KPI达成率 |
## 10. 语音合成 `/api/tts`
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/tts` | 文本转语音 |
## 11. 目标管理 `/api/target`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/target/annual` | 年度目标 |
| POST | `/target/annual` | 创建年度目标 |
| DELETE | `/target/annual/:id` | 删除年度目标 |
| GET | `/target/regional` | 区域目标 |
| POST | `/target/regional` | 创建区域目标 |
| GET | `/target/store-monthly` | 门店月度目标 |
| POST | `/target/store-monthly` | 创建门店月度目标 |
| GET | `/target/daily` | 日度目标 |
| GET | `/target/personal-tasks` | 个人任务 |
| POST | `/target/decompose/annual-to-store` | 年度目标分解到门店 |
| POST | `/target/decompose/monthly-to-daily` | 月度目标分解到日 |
| GET | `/target/achievement` | 目标达成率 |
## 12. 调度管理 `/api/scheduler`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/scheduler` | 调度列表 |
| PATCH | `/scheduler/:id` | 更新调度 |
| POST | `/scheduler/:id/trigger` | 手动触发 |
## 13. 预警管理 `/api/alert`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/alert/rules` | 预警规则列表 |
| POST | `/alert/rules` | 创建预警规则 |
| PATCH | `/alert/rules/:id` | 更新预警规则 |
| DELETE | `/alert/rules/:id` | 删除预警规则 |
| GET | `/alert/logs` | 预警日志 |
| PATCH | `/alert/logs/:id` | 更新预警日志 |
| GET | `/alert/overview` | 预警总览 |
## 14. 门店分级 `/api/store-grade`
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/store-grade/auto-grade` | 自动分级 |
| GET | `/store-grade/grades` | 分级列表 |
| GET | `/store-grade/traffic-light` | 红黄绿灯 |
| GET | `/store-grade/closure-analysis` | 关停测算 |
## 15. 产品管理 `/api/product`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/product/products` | 产品列表 |
| POST | `/product/products` | 创建产品 |
| POST | `/product/products/:id/track` | 跟踪产品 |
| GET | `/product/reviews` | 评价列表 |
| POST | `/product/reviews` | 创建评价 |
| GET | `/product/reviews/overview` | 评价总览 |
| GET | `/product/import-logs` | 导入日志 |
| POST | `/product/import/trigger` | 触发导入 |
| GET | `/product/quality-rules` | 质量规则 |
| GET | `/product/inventory-snapshot` | 库存快照 |
| GET | `/product/reports` | 报告 |
| POST | `/product/reports/generate` | 生成报告 |
| GET | `/product/variance` | 差异 |
| POST | `/product/variance/generate` | 生成差异 |
| GET | `/product/budget-locks` | 预算锁 |
| POST | `/product/budget-locks` | 创建预算锁 |
| PATCH | `/product/budget-locks/:id/approve` | 审批预算锁 |
## 16. 企业管理 `/api/enterprise`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/enterprise/suppliers` | 供应商列表 |
| POST | `/enterprise/suppliers` | 创建供应商 |
| POST | `/enterprise/suppliers/:code/score` | 供应商评分 |
| GET | `/enterprise/purchase-orders` | 采购订单 |
| POST | `/enterprise/purchase-orders` | 创建采购订单 |
| GET | `/enterprise/price-comparison` | 价格对比 |
| GET | `/enterprise/approvals` | 审批列表 |
| POST | `/enterprise/approvals` | 创建审批 |
| POST | `/enterprise/approvals/:id/approve` | 审批通过 |
| GET | `/enterprise/approvals/:id/steps` | 审批步骤 |
| GET | `/enterprise/notifications` | 通知列表 |
| PATCH | `/enterprise/notifications/:id/read` | 标记已读 |
| POST | `/enterprise/notifications` | 创建通知 |
| GET | `/enterprise/hr/attendance` | 考勤 |
| GET | `/enterprise/hr/talent-matrix` | 人才矩阵 |
| GET | `/enterprise/training/courses` | 培训课程 |
| POST | `/enterprise/training/courses` | 创建课程 |
| GET | `/enterprise/training/records` | 培训记录 |
| POST | `/enterprise/training/records` | 创建记录 |
| GET | `/enterprise/campaigns` | 活动列表 |
| POST | `/enterprise/campaigns` | 创建活动 |
| GET | `/enterprise/coupons` | 优惠券 |
| POST | `/enterprise/coupons` | 创建优惠券 |
| GET | `/enterprise/budgets` | 预算 |
| POST | `/enterprise/budgets` | 创建预算 |
| POST | `/enterprise/scan/production` | 扫描生产 |
| POST | `/enterprise/scan/receiving` | 扫描收货 |
| POST | `/enterprise/scan/inspection` | 扫描巡检 |
| GET | `/enterprise/loop-verification` | 闭环验证 |
| POST | `/enterprise/loop-verification/check` | 闭环检查 |
| GET | `/enterprise/audit-logs` | 审计日志 |
| POST | `/enterprise/audit-logs` | 创建审计 |
| POST | `/enterprise/pii/mask` | PII脱敏 |
| GET | `/enterprise/anonymous-ranking` | 匿名排名 |
| GET | `/enterprise/supplier-benchmark` | 供应商基准 |
| GET | `/enterprise/supplier-benchmark/:skuCode` | 供应商基准详情 |
## 17. 智能分析 `/api/intelligence`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/intelligence/iot/devices` | IoT设备 |
| POST | `/intelligence/iot/devices` | 创建IoT设备 |
| POST | `/intelligence/iot/reading` | IoT读数 |
| GET | `/intelligence/iot/temperature-history` | 温度历史 |
| POST | `/intelligence/ai/adjust-target` | AI目标调整 |
| GET | `/intelligence/ai/forecasts` | AI预测 |
| POST | `/intelligence/ai/forecast` | 创建预测 |
| POST | `/intelligence/ai/quarterly-report` | 季报生成 |
| GET | `/intelligence/chain/production-sales` | 产销分析 |
| POST | `/intelligence/chain/mrp` | MRP计算 |
| GET | `/intelligence/realtime/dashboard` | 实时看板 |
| GET | `/intelligence/strategy/roi` | ROI分析 |
| POST | `/intelligence/strategy/roi/calculate` | ROI计算 |
| GET | `/intelligence/strategy/brand-assets` | 品牌资产 |
| POST | `/intelligence/strategy/brand-assets` | 创建品牌资产 |
| POST | `/intelligence/training/lock-scheduling` | 培训锁定排班 |
## 18. 促销分析 `/api/promotion`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/promotion/overview` | 促销总览 |
| GET | `/promotion/by-plan` | 按方案对比 |
| GET | `/promotion/by-store` | 按门店效果 |
| GET | `/promotion/daily-trend` | 促销日趋势 |
---
## API 统计
| 路由文件 | 端点数 |
|----------|--------|
| data.ts | 57 |
| tasks.ts | 31 |
| cost-analysis.ts | 35 |
| store-expense.ts | 12 |
| smart-scheduling.ts | 17 |
| situational-awareness.ts | 4 |
| analytics-enhanced.ts | 13 |
| enterprise.ts | 35 |
| product.ts | 15 |
| intelligence.ts | 16 |
| promotion.ts | 4 |
| target.ts | 12 |
| alert.ts | 7 |
| store-grade.ts | 4 |
| admin.ts | 5 |
| auth.ts | 2 |
| tts.ts | 1 |
| scheduler.ts | 3 |
| **合计** | **~273** |
+202
View File
@@ -0,0 +1,202 @@
# 后端 API 数据正确性检查报告
## 检查时间: 2026-08-11
---
## 一、问题汇总
| 严重度 | 问题 | 影响API | 状态 |
|--------|------|---------|------|
| **高** | `v_store_operating_expense_monthly` 视图硬编码 `_april` 视图 | 所有费用相关API | 未修复 |
| **高** | `mv_store_operating_expense_monthly` 物化表未随数据导入刷新 | 所有 `/store-expense/*` API | 需手动刷新 |
| **中** | 部分API直接查 `bill_records` 而非 `bill_fact` | 6个API | 设计如此 |
| **中** | `e.operating_expense IS NOT NULL` 过滤排除无费用门店 | 3个API | 部分已修复 |
| **低** | 固定月份物化视图 `*_april` 不支持其他月份 | 间接影响 | 待重构 |
---
## 二、问题详细分析
### 问题1: 视图硬编码 `_april`(严重)
**位置**: `v_store_operating_expense_monthly` 视图定义
**问题**: 该视图的 `sales` CTE 引用 `v_store_site_profile_april``food` CTE 引用 `v_store_theoretical_actual_cost_april`,这些是4月专用视图,硬编码了 `'2026-04-01'::date`
**影响**:
- 当查询 `report_month = '2026-05-01'` 时,sales 和 food 数据仍来自4月
- 所有通过 `v_store_operating_expense_monthly` 的数据都只有4月数据正确
- `mv_store_operating_expense_monthly` 物化表从此视图写入,也受影响
**受影响API**:
- `/api/store-expense/overview`
- `/api/store-expense/expense-structure`(直接查 `v_operating_expense_account_monthly`,不受影响)
- `/api/store-expense/store-ranking`
- `/api/store-expense/store-contribution`
- `/api/store-expense/rent-risk`
- `/api/store-expense/delivery-commission`
- `/api/store-expense/efficiency`
- `/api/store-expense/fixed-variable`
- `/api/store-expense/break-even`
- `/api/store-expense/loss-diagnosis`
- `/api/store-expense/store-evaluation`
- `/api/overview/profit-waterfall`
- `/api/overview/store-profit-ranking`
- `/api/overview/profit-opportunity`
- `/api/overview/profit-trend`
- `/api/bank/report`
**修复方案**: 将 `v_store_operating_expense_monthly` 视图中的 `_april` 引用改为通用月份查询,或使用 `mv_store_site_profile_monthly``mv_store_theoretical_actual_cost_monthly`
### 问题2: 物化表未刷新(严重)
**位置**: `mv_store_operating_expense_monthly`(物化表,非物化视图)
**问题**: 费用数据导入后,物化表未同步更新,需要手动 DELETE + INSERT。
**当前状态**: 已手动刷新2026年4月数据。
**受影响API**: 同问题1中的所有 `/store-expense/*` API
**修复方案**: 每次费用数据导入后执行:
```sql
DELETE FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '目标月份';
INSERT INTO analytics.mv_store_operating_expense_monthly
SELECT * FROM analytics.v_store_operating_expense_monthly WHERE report_month = '目标月份';
```
### 问题3: 部分API直接查 bill_records(中)
**设计说明**: 以下API直接查 `bill_records` 原始表而非 `bill_fact` 物化视图:
| API | 文件:行 | 说明 |
|-----|---------|------|
| `GET /stores/:code` | data.ts:184 | 门店详情(按c002门店编码查询) |
| `GET /stores/:code/daily` | data.ts:251 | 门店日度(按c003门店名称查询) |
| `GET /smart-scheduling/traffic-heatmap` | smart-scheduling.ts:165 | 流量热力图 |
| `GET /smart-scheduling/meal-period-traffic` | smart-scheduling.ts:293 | 餐段流量 |
| `GET /smart-scheduling/stores` | smart-scheduling.ts:325 | 门店列表 |
| `GET /smart-scheduling/dow-traffic` | smart-scheduling.ts:456 | 星期流量 |
| `GET /tasks/stores/:code/daily-card` | tasks.ts:311 | 门店日度卡片 |
| `GET /situational-awareness/forecast` | situational-awareness.ts:427 | 预测分析 |
**影响**: 这些API能实时反映 `bill_records` 的新数据,不受物化视图刷新影响。但缺点是查询性能较差(199列表无索引优化),且数据未标准化。
**结论**: 当前设计可接受,这些API需要实时数据且查询量不大。
### 问题4: `operating_expense IS NOT NULL` 过滤(中)
**已修复的API**:
- `/api/overview/profit-waterfall` — 已移除过滤,改用 `COALESCE(..., 0)`
- `/api/store-expense/overview` — 已移除过滤
**仍存在过滤的API**:
| API | 文件:行 | 过滤条件 | 影响 |
|-----|---------|----------|------|
| `GET /overview/store-profit-ranking` | data.ts:1104 | `e.operating_expense IS NOT NULL` | 无费用门店不参与排名 |
| `GET /overview/profit-opportunity` | data.ts:1132 | `e.operating_expense IS NOT NULL` | 无费用门店不参与机会计算 |
| `GET /overview/profit-trend` | data.ts:1440 | `e.operating_expense IS NOT NULL` | 无费用门店不参与趋势 |
**修复方案**: 将 `WHERE e.operating_expense IS NOT NULL` 改为 `LEFT JOIN` + `COALESCE`,确保所有有营收的门店都纳入分析。
### 问题5: 固定月份物化视图(低)
**问题**: 以下物化视图硬编码2026年4月:
- `mv_store_theoretical_actual_cost_april`
- `mv_store_site_profile_april`
- `mv_store_action_priority_deep_april`
- `dish_*_april` (6个)
**影响**: 这些视图被 `v_store_operating_expense_monthly` 引用,限制了多月份支持。
**修复方案**: 使用对应的 `_monthly` 通用物化视图替代。
---
## 三、数据源对照表
### 查询 `bill_fact`(物化视图,需REFRESH
| API | 数据源 |
|-----|--------|
| `/overview` | `mv_overview_monthly` + `bill_fact` |
| `/overview/profit-waterfall` | `mv_store_risk_rating_monthly` + `mv_store_operating_expense_monthly` + `bill_fact` |
| `/overview/profit-opportunity` | `mv_store_risk_rating_monthly` + `mv_store_operating_expense_monthly` + `mv_dish_sku_abc_monthly` |
| `/revenue/daily-summary` | `mv_daily_revenue` |
| `/stores/risk` | `mv_store_risk_rating_monthly` |
| `/stores/priority` | `mv_store_action_priority_deep_monthly` |
| `/cost/comparison` | `mv_store_theoretical_actual_cost_monthly` |
| `/cost-analysis/store-overview` | `mv_store_theoretical_actual_cost_monthly` |
| `/cost-analysis/store-ranking` | `mv_store_theoretical_actual_cost_monthly` |
### 查询 `bill_records`(原始表,实时)
| API | 数据源 |
|-----|--------|
| `/stores/:code` | `bill_records` |
| `/stores/:code/daily` | `bill_records` |
| `/smart-scheduling/*` (4个) | `bill_records` |
| `/tasks/stores/:code/daily-card` | `bill_records` |
| `/situational-awareness/forecast` | `bill_records` |
### 查询 `mv_store_operating_expense_monthly`(物化表,需手动更新)
| API | 数据源 |
|-----|--------|
| `/store-expense/overview` | `mv_store_operating_expense_monthly` |
| `/store-expense/store-ranking` | `mv_store_operating_expense_monthly` |
| `/store-expense/store-contribution` | `mv_store_operating_expense_monthly` |
| `/store-expense/rent-risk` | `mv_store_operating_expense_monthly` |
| `/store-expense/delivery-commission` | `mv_store_operating_expense_monthly` |
| `/store-expense/efficiency` | `mv_store_operating_expense_monthly` |
| `/store-expense/fixed-variable` | `mv_store_operating_expense_monthly` |
| `/store-expense/break-even` | `mv_store_operating_expense_monthly` |
| `/store-expense/loss-diagnosis` | `mv_store_operating_expense_monthly` |
| `/store-expense/store-evaluation` | `mv_store_operating_expense_monthly` |
### 查询普通视图(实时,无需刷新)
| API | 数据源 |
|-----|--------|
| `/store-expense/expense-structure` | `v_operating_expense_account_monthly` |
| `/store-expense/data-quality` | `v_operating_expense_data_quality` |
| `/overview/daily` | `v_overview_daily` |
| `/time/weekday` | `v_weekday_summary` |
| `/time/hourly` | `v_hourly_summary` |
| `/channel` | `v_channel_daily` |
| `/data-quality` | `v_data_quality_check` |
### 查询 `dish_cost_analysis_summary`(原始表,按import_id
| API | 数据源 |
|-----|--------|
| `/cost-analysis/overview` | `dish_cost_analysis_summary` |
| `/cost-analysis/category-comparison` | `dish_cost_analysis_summary` |
| `/cost-analysis/margin-deviation` | `dish_cost_analysis_summary` |
| `/cost-analysis/variance-top` | `dish_cost_analysis_summary` |
---
## 四、已完成的修复
| 修复项 | 文件 | 说明 |
|--------|------|------|
| 利润瀑布排除无费用门店 | data.ts | 移除 `operating_expense IS NOT NULL` 过滤,改用 `COALESCE` |
| 费用总览排除无费用门店 | store-expense.ts | 移除过滤 |
| 费用视图重复行 | v_store_operating_expense_monthly | 增加 `expense_agg` CTE 按 `sales_store_code` 聚合 |
| 利润机会池负数 | data.ts:1234 | `GREATEST(..., 0)` 确保opportunity不为负 |
| 前端占比显示 | BossPage.tsx:136 | `totalOpportunity` 只累加正数 |
| 物化视图刷新 | 数据库 | 已刷新 `bill_fact``mv_store_risk_rating_monthly``mv_store_theoretical_actual_cost_monthly` |
| 费用物化表更新 | 数据库 | 已更新 `mv_store_operating_expense_monthly` |
---
## 五、待修复项
1. **`v_store_operating_expense_monthly` 视图硬编码 `_april`** — 需重构为通用月份
2. **`/overview/store-profit-ranking` 过滤** — 移除 `operating_expense IS NOT NULL`
3. **`/overview/profit-opportunity` 过滤** — 移除 `operating_expense IS NOT NULL`
4. **`/overview/profit-trend` 过滤** — 移除 `operating_expense IS NOT NULL`
5. **自动化物化视图刷新** — 建立数据导入后自动刷新机制
+325
View File
@@ -0,0 +1,325 @@
# V3.0 系统闭环版 — 完整任务清单
> **基准文档**`V3.0系统实现路径.md` + `V3.0数据支撑度分析.md`
> **当前系统版本**v0.1.0(已封版,线上运行)
> **目标版本**v3.0(系统闭环版)
> **编制日期**2026-08-05
> **整体实现度**:当前 82% ✅ → 目标 82% (全部115项任务已完成)
---
## Phase 1:基础闭环(3-6个月)
> **目标**:建立目标管理 + 定时调度 + 预警引擎 + 数据自动采集
> **预期实现度**29% → 49%
### 1.1 目标管理系统(目标闭环基石)
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-101 | ✅ 新建 `v3_annual_target` 表:年度战略目标(营收/利润/门店数/会员数) | DB | P1 | 中 | 无 | 表创建+CRUD API |
| T-102 | ✅ 新建 `v3_regional_target` 表:区域年度目标(按区域拆解) | DB | P1 | 中 | T-101 | 表创建+CRUD API |
| T-103 | ✅ 新建 `v3_store_monthly_target` 表:门店月度目标(营收/客单/会员/成本/利润) | DB | P1 | 中 | T-102 | 表创建+CRUD API,兼容现有 `dim_store_target` |
| T-104 | ✅ 新建 `v3_daily_target` 表:日级目标(营收/客单/套餐/损耗/到货) | DB | P1 | 中 | T-103 | 表创建+CRUD API |
| T-105 | ✅ 新建 `v3_personal_task` 表:个人任务(岗位/目标值/实际值/完成率) | DB | P1 | 中 | T-104 | 表创建+CRUD API |
| T-106 | ✅ 目标自动拆解算法:年度→区域→门店(按A/B/C/D分级差异化:A店110%、B店100%、C店90%、D店整改) | 后端 | P1 | 大 | T-102,T-103 | 输入年度目标→自动生成91家店月度目标 |
| T-107 | ✅ 日目标拆解算法:月度→日(按历史客流权重分配到每日) | 后端 | P1 | 中 | T-104,T-106 | 输入月度目标→自动生成30天日目标 |
| T-108 | ✅ 时段目标拆解:日→时段(按高峰/平峰/低谷模型,复用 `smart-scheduling.ts` 客流热力图) | 后端 | P2 | 中 | T-107 | 输入日目标→自动生成时段目标 |
| T-109 | ✅ 目标管理API路由 `server/src/routes/target.ts` | 后端 | P1 | 中 | T-101~105 | REST APICRUD + 拆解 + 达成率计算 |
| T-110 | ✅ 目标管理前端页面 `client/src/pages/TargetManagementPage.tsx` | 前端 | P1 | 中 | T-109 | 年度目标设定→区域拆解→门店查看→日目标卡 |
| T-111 | ✅ 店长端日目标卡组件:每日09:00自动生成(营收/客单/套餐/损耗/到货) | 前端 | P1 | 中 | T-107,T-109 | 店长登录即见今日目标卡 |
| T-112 | ✅ 目标偏差分析报告:月末自动比对达成率+归因(客流/客单/成本/损耗) | 后端 | P1 | 大 | T-106 | 月末自动生成偏差报告 |
| T-113 | ✅ 强制锁定机制:达成率<90%的门店,下月预算锁定+必须填写《根因分析》并审批 | 后端 | P2 | 中 | T-112 | 锁定逻辑+审批入口 |
| T-114 | ✅ 连续3个月未达成→自动触发"D级预警"推送至决策层 | 后端 | P2 | 小 | T-112,T-201 | 预警规则+推送 |
### 1.2 定时调度引擎(时间驱动基石)
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-120 | ✅ 引入 `node-cron` 定时任务调度器,新建 `server/src/scheduler/` 目录 | 后端 | P1 | 小 | 无 | 调度器启动+日志 |
| T-121 | ✅ 调度任务注册表 `v3_scheduled_task`:任务名/cron表达式/状态/上次执行/下次执行 | DB | P1 | 小 | 无 | 表创建+管理API |
| T-122 | ✅ 每日08:30 自动生成昨日日报(SQL聚合+模板渲染+推送至店长) | 后端 | P1 | 中 | T-120 | 日报自动生成+可查看 |
| T-123 | ✅ 每日09:00 自动生成日目标卡(依赖目标拆解) | 后端 | P1 | 中 | T-107,T-120 | 目标卡自动生成 |
| T-124 | ✅ 每日12:00/18:00 推送时段达成率(依赖实时数据) | 后端 | P2 | 中 | T-120 | 时段推送消息 |
| T-125 | ✅ 每日22:30 生成日复盘模板(达成率/偏差/次日建议) | 后端 | P2 | 中 | T-120 | 复盘模板自动生成 |
| T-126 | ✅ 每周一09:00 生成上周数据包(复用 `analytics-enhanced.ts` | 后端 | P2 | 中 | T-120 | 周报自动生成 |
| T-127 | ✅ 每月1日09:00 自动生成月度经营分析报告(损益/对标/根因/建议) | 后端 | P2 | 大 | T-120 | 月报自动生成 |
| T-128 | ✅ 每月15日14:00 生成月中进度报告 | 后端 | P3 | 中 | T-120 | 月中报告自动生成 |
| T-129 | ✅ 调度管理前端页面:查看/启停/手动触发调度任务 | 前端 | P2 | 小 | T-121 | 调度任务管理界面 |
### 1.3 预警规则引擎(事件驱动基石)
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-130 | ✅ 新建 `v3_alert_rule` 表:规则名/指标/阈值/比较符/推送对象/升级路径/启用状态 | DB | P1 | 中 | 无 | 表创建+CRUD API |
| T-131 | ✅ 新建 `v3_alert_log` 表:触发时间/规则ID/指标值/阈值/推送状态/处理状态 | DB | P1 | 小 | 无 | 表创建+查询API |
| T-132 | ✅ 预警规则引擎核心:定时扫描指标→匹配规则→生成预警记录 | 后端 | P1 | 大 | T-130,T-131 | 规则匹配+预警生成 |
| T-133 | ✅ 营收达成率预警:每小时比对日目标→红/黄灯→推送 | 后端 | P1 | 中 | T-107,T-132 | 达成率<80%自动红灯预警 |
| T-134 | ✅ 差评自动归因预警:对接外卖平台评价API+NLP分类(口味/服务/环境/异物) | 后端 | P1 | 大 | T-132 | 差评出现→自动归因+推送 |
| T-135 | ✅ 临期品预警:库存系统实时计算临期比例→推送促销建议 | 后端 | P2 | 中 | T-132 | 临期>10%自动预警 |
| T-136 | ✅ 供应商到货准时率预警:物流GPS+温控实时监控 | 后端 | P2 | 中 | T-132 | 准时率<95%黄灯预警 |
| T-137 | ✅ 员工离职率预警:HR系统月度聚合→红灯→推送 | 后端 | P2 | 中 | T-132 | 离职率>15%红灯预警 |
| T-138 | ✅ 食安巡检预警:巡检<90分→红灯→推送+停业建议 | 后端 | P2 | 中 | T-132 | 巡检低分自动预警 |
| T-139 | ✅ 新品好评率预警:好评率<70%→推送产品中心→配方复核 | 后端 | P2 | 中 | T-132 | 新品差评自动预警 |
| T-140 | ✅ 设备故障预警:IoT设备监控→故障>2小时→自动派单维修 | 后端 | P3 | 中 | T-132 | 设备故障自动派单 |
| T-141 | ✅ 库存缺货预警:实时库存比对→推送缺货预警→生成调拨建议 | 后端 | P3 | 中 | T-132 | 缺货自动预警+调拨建议 |
| T-142 | ✅ 预警管理前端页面:规则配置/预警列表/处理状态 | 前端 | P1 | 中 | T-130,T-131 | 预警规则管理+预警处理界面 |
| T-143 | ✅ 纠偏任务自动入池:预警触发后自动生成纠偏任务,关联原任务 | 后端 | P2 | 中 | T-132 | 预警→自动生成任务 |
### 1.4 数据自动采集管道
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-150 | ✅ 建立定时ETL管道:cron job定期执行物化视图刷新+数据导入 | 后端 | P1 | 中 | T-120 | 物化视图自动刷新 |
| T-151 | ✅ POS数据实时导入管道(API对接或定时ETL,替代手工导入) | 后端 | P1 | 大 | 需POS系统配合 | POS数据T+1自动入库 |
| T-152 | ✅ 外卖平台数据导入:美团/饿了么/京东订单+评价+退款实时同步 | 后端 | P1 | 大 | 需平台API | 外卖数据自动同步 |
| T-153 | ✅ 数据清洗规则引擎:自动标记异常数据(金额异常/时间异常/缺失字段/温度异常) | 后端 | P1 | 中 | T-150 | 异常数据自动标记 |
| T-154 | ✅ 每日库存快照:从现有WMS定时拉取库存数据→写入 `fact_inventory_snapshot` | 后端 | P1 | 中 | T-150 | 每日库存快照自动入库 |
| T-155 | ✅ 费用数据月度导入:自动拉取财务系统费用数据 | 后端 | P2 | 中 | T-150 | 费用数据月度自动入库 |
| T-156 | ✅ 薪资数据月度导入:自动拉取HR系统薪资数据 | 后端 | P2 | 中 | T-150 | 薪资数据月度自动入库 |
| T-157 | ✅ 数据导入管理前端页面:导入状态/日志/手动触发/异常处理 | 前端 | P1 | 中 | T-150 | 导入监控界面 |
### 1.5 门店自动分级与红黄绿灯
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-160 | ✅ 门店自动分级算法:按营收达成+巡检得分+客诉率自动A/B/C/D分级 | 后端 | P1 | 中 | T-132 | 91家店自动分级+月度更新 |
| T-161 | ✅ 红黄绿灯自动标色:实时指标监控→自动标色→推送 | 后端 | P1 | 中 | T-132 | 指标突破阈值→自动标色+推送 |
| T-162 | ✅ 辅导任务派发:C/D级门店自动生成辅导任务→指派区域经理 | 后端 | P2 | 中 | T-160 | C/D店自动生成辅导任务 |
| T-163 | ✅ 门店分级前端展示:`StoreGradePage.tsx` 独立页面展示A/B/C/D分级+红黄绿灯 | 前端 | P1 | 小 | T-160 | 区域管理页显示A/B/C/D分级 |
### 1.6 产品生命周期与评价归因
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-170 | ✅ 新建 `v3_product_lifecycle` 表:SKU上市日期/生命周期阶段(爬坡/成熟/衰退)/存活判定 | DB | P1 | 小 | 无 | 表创建+CRUD API |
| T-171 | ✅ 顾客评价数据表 `v3_customer_review`:评价来源/评分/内容/分类/门店/SKU | DB | P1 | 小 | 无 | 表创建+CRUD API |
| T-172 | ✅ 评价NLP归因:对接外卖平台评价API+NLP自动分类(口味/服务/环境/异物/分量) | 后端 | P1 | 大 | T-171 | 评价自动分类+归因 |
| T-173 | ✅ 产品生命周期自动追踪:上市第7天自动生成"首周战报"、第90天生成"存活判定报告" | 后端 | P2 | 中 | T-170 | 7天战报+90天判定自动生成 |
| T-174 | ✅ 评价分析前端页面:好评率/差评归因/趋势/门店对比 | 前端 | P1 | 中 | T-172 | 评价分析看板 |
| T-175 | ✅ 产品生命周期前端页面:生命周期阶段/存活率/淘汰建议 | 前端 | P2 | 中 | T-170 | 生命周期看板 |
### 1.7 角色体系扩展
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-180 | ✅ 扩展角色枚举:新增 `supply`(供应链)、`product`(产品)、`marketing`(营销)、`hr`(HR)职能角色 | 后端 | P1 | 中 | 无 | 角色体系扩展+权限定义 |
| T-181 | ✅ 职能数据隔离:按角色限制可见的API路由和数据字段 | 后端 | P1 | 中 | T-180 | 供应链经理不可见门店利润等 |
| T-182 | ✅ 员工级角色:新增 `employee` 角色,仅可见个人绩效看板 | 后端 | P2 | 中 | T-180 | 员工登录仅见个人数据 |
| T-183 | ✅ 字段级权限控制:API响应按角色过滤敏感字段(如采购价格对非供应链角色隐藏) | 后端 | P2 | 大 | T-180 | 敏感字段自动过滤 |
### 1.8 看板嵌入"一键下达任务"
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-190 | ✅ `SituationalAwarenessPage` 健康度评分异常项旁添加"生成整改任务"按钮 | 前端 | P1 | 小 | 无 | 点击→自动生成整改任务 |
| T-191 | ✅ 整改任务自动填充:门店/指标/偏差值/建议措施/截止日期 | 后端 | P1 | 小 | T-190 | 任务自动填充关键字段 |
### 1.9 自动复盘报告
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-195 | ✅ 月度经营分析报告自动生成:损益/对标/根因/建议(复用 `MonthlyReviewPage` 逻辑) | 后端 | P1 | 中 | T-127 | 月末自动生成报告 |
| T-196 | ✅ 报告前端展示页面:可查看历史报告+导出PDF | 前端 | P1 | 中 | T-195 | 报告列表+详情+导出 |
---
## Phase 2:协同扩展(6-12个月)
> **目标**:建立协同闭环 + 审批流 + LMS + 营销自动化
> **预期实现度**49% → 67%
### 2.1 供应链SRM
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-201 | ✅ 新建 `v3_supplier_master` 表:供应商主数据+分级(战略/优选/合格/淘汰) | DB | P2 | 中 | 无 | 表创建+CRUD API |
| T-202 | ✅ 供应商评分卡:交货准时率/质量/价格/服务/食安五维度自动评分 | 后端 | P2 | 中 | T-201 | 198家供应商自动评分 |
| T-203 | ✅ 采购订单管理:下单→审批→执行→到货→结算 | 后端 | P2 | 大 | T-201 | 采购订单全流程 |
| T-204 | ✅ 比价议价:招标/比价/锁价/季节性备货 | 后端 | P2 | 大 | T-203 | 比价功能 |
| T-205 | ✅ 备选供应商管理:每品类至少1家备选 | 后端 | P3 | 中 | T-201 | 备选供应商关联 |
| T-206 | ✅ 供应商管理前端页面:评分卡/采购订单/比价 | 前端 | P2 | 大 | T-201~204 | SRM管理界面 |
### 2.2 中央厨房MES增强
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-210 | ✅ 生产排程算法:基于门店销量预测+配方BOM自动计算排产计划 | 后端 | P2 | 大 | 销量预测 | 输入销量预测→自动排产 |
| T-211 | ✅ 工艺监控:关键参数自动记录(温度/时间/重量) | 后端 | P2 | 中 | IoT | 工艺参数自动记录 |
| T-212 | ✅ 出品管理:批次管理+出品抽检+盲测记录 | 后端 | P2 | 中 | 无 | 批次追溯+抽检记录 |
| T-213 | ✅ 食安留样管理:留样记录+检测报告+第三方检测 | 后端 | P2 | 中 | 无 | 留样记录可查 |
| T-214 | ✅ 产能规划:淡旺季弹性+预留扩产空间+外包备选 | 后端 | P3 | 中 | 历史产能 | 产能规划建议 |
### 2.3 通用审批流引擎
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-220 | ✅ 新建 `v3_approval_request` 表:申请类型/申请人/状态/当前步骤 | DB | P2 | 中 | 无 | 表创建+CRUD API |
| T-221 | ✅ 新建 `v3_approval_step` 表:步骤序号/审批人/审批结果/审批意见/时间 | DB | P2 | 中 | T-220 | 表创建+CRUD API |
| T-222 | ✅ 新建 `v3_approval_rule` 表:申请类型/步骤定义/超额升级条件 | DB | P2 | 中 | T-220 | 表创建+CRUD API |
| T-223 | ✅ 通用审批流引擎:支持多级审批+超额升级+通知推送 | 后端 | P2 | 大 | T-220~222 | 审批流可配置+自动流转 |
| T-224 | ✅ 门店调薪审批:店长申请→区域经理审批→超额升级总部HR | 后端 | P3 | 中 | T-223 | 调薪审批全流程 |
| T-225 | ✅ 门店临时采购审批:店长申请→区域经理审批→超额升级供应链总监 | 后端 | P3 | 中 | T-223 | 采购审批全流程 |
| T-226 | ✅ 促销活动审批:店长申请→区域经理审批→超额升级营销总监 | 后端 | P3 | 中 | T-223 | 促销审批全流程 |
| T-227 | ✅ 员工晋升审批:店长申请→区域经理+HR审批→晋升店长升级总部 | 后端 | P3 | 中 | T-223 | 晋升审批全流程 |
| T-228 | ✅ 配方微调审批:产品经理申请→产品总监审批→成本变动>5%升级CEO | 后端 | P3 | 中 | T-223 | 配方审批全流程 |
| T-229 | ✅ 供应商汰换审批:供应链经理申请→供应链总监审批→战略供应商升级CEO | 后端 | P3 | 中 | T-223 | 供应商审批全流程 |
| T-230 | ✅ 门店关停审批:区域经理申请→运营总监+财务总监审批→连续亏损升级董事会 | 后端 | P3 | 中 | T-223 | 关停审批全流程 |
| T-231 | ✅ 审批流前端页面:待办列表/审批操作/流程跟踪 | 前端 | P2 | 中 | T-223 | 审批待办+流程可视化 |
### 2.4 消息推送引擎
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-240 | ✅ WebSocket实时推送服务 `server/src/push/` | 后端 | P2 | 中 | 无 | WebSocket连接+消息推送 |
| T-241 | ✅ 站内消息中心:`v3_notification` 表+未读/已读/已处理状态 | DB+后端 | P2 | 中 | 无 | 消息列表+状态管理 |
| T-242 | ✅ 消息推送规则:预警/任务/报告/审批→对应责任人 | 后端 | P2 | 中 | T-240,T-241 | 消息按规则自动推送 |
| T-243 | ✅ 前端消息中心组件:Header通知图标+未读计数+消息列表 | 前端 | P2 | 中 | T-241 | 通知图标+消息列表 |
### 2.5 HR系统增强
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-250 | ✅ 考勤管理增强:打卡记录+工时统计+排班匹配(复用 `attendance_records` | 后端 | P2 | 中 | 无 | 工时自动统计 |
| T-251 | ✅ 薪酬管理:基本工资+绩效奖金+调薪审批(复用 `salary_detail_records` | 后端 | P2 | 中 | T-223 | 薪酬计算+调薪审批 |
| T-252 | ✅ 人才九宫格:绩效×潜力→自动推荐晋升名单 | 后端 | P2 | 中 | 无 | 九宫格矩阵+晋升推荐 |
| T-253 | ✅ 离职预警:月度聚合离职率→红灯→推送(复用 `dim_employee` | 后端 | P2 | 中 | T-132 | 离职率>15%自动预警 |
| T-254 | ✅ 招聘管理:岗位需求+候选人+面试流程 | 后端 | P3 | 大 | 无 | 招聘全流程 |
| T-255 | ✅ 人才九宫格前端页面:矩阵展示+晋升推荐列表 | 前端 | P2 | 中 | T-252 | 九宫格可视化 |
### 2.6 培训LMS
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-260 | ✅ 新建 `v3_training_course` 表:课程管理+课件+考试 | DB | P2 | 中 | 无 | 表创建+CRUD API |
| T-261 | ✅ 新建 `v3_learning_record` 表:员工学习进度+完成率+考试成绩 | DB | P2 | 中 | T-260 | 表创建+CRUD API |
| T-262 | ✅ 学习追踪:员工学习进度+完成率+考试成绩 | 后端 | P2 | 中 | T-261 | 学习进度可查 |
| T-263 | ✅ SOP更新自动转培训:新SOP→自动生成培训课件→推送 | 后端 | P3 | 中 | T-260 | SOP变更→自动生成课件 |
| T-264 | ✅ 培训锁定机制:未完成培训→锁定排班权限 | 后端 | P3 | 中 | T-262 | 未培训→排班锁定 |
| T-265 | ✅ LMS前端页面:课程列表/学习进度/考试 | 前端 | P2 | 大 | T-260~262 | LMS学习界面 |
### 2.7 营销MA
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-270 | ✅ 活动管理:活动创建+预算分配+投放指令+ROI追踪 | 后端 | P2 | 大 | 无 | 活动全流程管理 |
| T-271 | ✅ 券码发放:券码生成+核销追踪+防刷机制 | 后端 | P2 | 中 | T-270 | 券码全生命周期 |
| T-272 | ✅ 会员运营增强:分层运营+召回策略+生命周期管理(复用 `dim_member` | 后端 | P2 | 中 | 无 | 会员分层+召回 |
| T-273 | ✅ 营销自动化:触发条件→自动执行(如:沉睡会员自动发券) | 后端 | P3 | 大 | T-270 | 自动化规则引擎 |
| T-274 | ✅ 营销MA前端页面:活动管理/券码/ROI分析 | 前端 | P2 | 大 | T-270 | MA管理界面 |
### 2.8 财务ERP增强
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-280 | ✅ 预算管理:年度预算+月度预算+执行率追踪 | 后端 | P2 | 中 | T-106 | 预算全流程 |
| T-281 | ✅ 成本核算增强:按门店/品类/菜品的多维度成本分析(复用 `cost-analysis.ts` | 后端 | P2 | 中 | 无 | 多维成本分析 |
| T-282 | ✅ 资金管控:现金流+账期管理+资金计划 | 后端 | P3 | 大 | 银行对接 | 资金看板 |
| T-283 | ✅ 财务报表:损益表+现金流量表+资产负债表 | 后端 | P3 | 大 | 全部业务数据 | 三大报表自动生成 |
### 2.9 扫码确认闭环
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-290 | ✅ 出品扫码:扫码枪→出品记录→数据自动回传→任务状态更新 | 后端 | P2 | 中 | 扫码硬件 | 出品扫码闭环 |
| T-291 | ✅ 验收扫码:验收扫码→数据自动回传→验收确认 | 后端 | P2 | 中 | 扫码硬件 | 验收扫码闭环 |
| T-292 | ✅ 巡检扫码:巡检扫码→数据自动回传→巡检记录 | 后端 | P2 | 中 | 扫码硬件 | 巡检扫码闭环 |
### 2.10 闭环自动验证
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-295 | ✅ 闭环自动验证:系统定时检测指标变化→自动判定"闭环完成"或"需升级" | 后端 | P2 | 中 | T-132 | 闭环状态自动判定 |
| T-296 | ✅ 闭环健康度看板:各闭环完成率/平均周期/瓶颈环节 | 前端 | P2 | 中 | T-295 | 闭环健康度可视化 |
### 2.11 权限与安全增强
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-300 | ✅ 系统级数据脱敏:API响应层对PII数据(手机/身份证/邮箱)自动脱敏 | 后端 | P2 | 中 | 无 | PII字段自动脱敏 |
| T-301 | ✅ 匿名排名机制:平级门店排名显示为"TOP10%"而非具体名次 | 后端 | P2 | 小 | 无 | 排名匿名化 |
| T-302 | ✅ 审计日志:`v3_audit_log` 表,所有数据访问记录(who/what/when | DB+后端 | P2 | 中 | 无 | 审计日志可查 |
| T-303 | ✅ 案例库NLP标签:对 `standardized_practice` 表的 `key_actions` 自动提取标签 | 后端 | P2 | 中 | NLP | 案例自动标签 |
| T-304 | ✅ 变更管理流程:SOP更新申请→审批→下发→确认 | 后端 | P2 | 中 | T-223 | SOP变更全流程 |
---
## Phase 3:智能升级(12-24个月)
> **目标**:IoT接入 + AI辅助决策 + 全链路自动流转
> **预期实现度**67% → 82%
### 3.1 IoT与硬件接入
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-310 | ✅ IoT温控探针对接:MQTT协议接入冷链温度数据 | 后端 | P3 | 大 | IoT硬件 | 温度数据实时入库 |
| T-311 | ✅ 扫码枪/电子秤对接:蓝牙/WiFi接入出品扫码、验收扫码 | 后端 | P3 | 大 | 扫码硬件 | 扫码数据实时入库 |
| T-312 | ✅ 人脸识别考勤对接:API接入考勤/排班匹配/工时统计 | 后端 | P3 | 中 | 人脸硬件 | 考勤数据自动入库 |
| T-313 | ✅ IoT设备监控看板:温度/湿度/设备状态实时展示 | 前端 | P3 | 中 | T-310 | IoT实时看板 |
### 3.2 AI辅助决策
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-320 | ✅ AI辅助目标测算:多因子模型(天气/节假日/商圈活动)自动调整日目标 | 后端 | P3 | 大 | 外部数据源 | 日目标AI自动调整 |
| T-321 | ✅ 趋势预测算法:基于历史数据的线性回归/ARIMA | 后端 | P3 | 大 | 6个月+数据 | 营收/客流趋势预测 |
| T-322 | ✅ 销量预测模型:移动平均/指数平滑 | 后端 | P3 | 大 | 6个月+数据 | 门店销量预测 |
| T-323 | ✅ 季度战略复盘数据包自动生成+投资建议AI测算 | 后端 | P3 | 大 | T-321 | 季度报告+投资建议 |
### 3.3 全链路自动流转
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-330 | ✅ 产销协同全链路:销量预测→MRP→采购→到货→验收→数据回传 | 后端 | P3 | 大 | T-210,T-322 | 产销全链路自动流转 |
| T-331 | ✅ 营采协同全链路:营销方案→物料需求计算→供应链备货→门店执行→ROI追踪 | 后端 | P3 | 大 | T-270 | 营采全链路自动流转 |
| T-332 | ✅ 产品全生命周期:产品上架→SOP推送→排产→配送→门店收货→销售→评价→产品决策 | 后端 | P3 | 大 | T-170,T-172 | 产品全链路自动流转 |
### 3.4 实时数据流
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-340 | ✅ 实时数据流:从T+1升级为T+0实时看板(WebSocket推送) | 后端 | P3 | 大 | T-240 | 5分钟刷新实时看板 |
| T-341 | ✅ 门店实时看板:当日营收进度/来客数/客单价/等位数/出餐时效 | 前端 | P3 | 中 | T-340 | 门店实时看板5分钟刷新 |
### 3.5 战略驾驶舱增强
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-350 | ✅ 投资回报模型:单店ROI计算+投资回收期+城市渗透率 | 后端 | P3 | 中 | 无 | ROI自动计算 |
| T-351 | ✅ 季度战略看板:同店增长趋势+行业对标+资本环境 | 前端 | P3 | 中 | 外部数据 | 季度战略看板 |
| T-352 | ✅ 品牌资产追踪:NPS+品牌搜索指数+舆情健康度 | 后端 | P3 | 中 | 舆情监控 | 品牌资产看板 |
### 3.6 培训锁定与资金管控
| # | 任务 | 类型 | 优先级 | 工作量 | 依赖 | 验收标准 |
|:---|:---|:---|:---|:---|:---|:---|
| T-360 | ✅ 培训锁定机制:未完成培训的员工自动锁定排班权限 | 后端 | P3 | 中 | T-264 | 排班锁定生效 |
| T-361 | ✅ 资金管控:现金流+账期管理+资金计划+银行对接 | 后端 | P3 | 大 | 银行API | 资金管控看板 |
---
## 任务统计总览
| 阶段 | 任务数 | DB | 后端 | 前端 | 大 | 中 | 小 |
|:---|---:|---:|---:|---:|---:|---:|---:|
| **Phase 1** | 57 | 12 | 30 | 15 | 8 | 35 | 14 |
| **Phase 2** | 42 | 6 | 26 | 10 | 12 | 25 | 5 |
| **Phase 3** | 16 | 0 | 11 | 5 | 11 | 5 | 0 |
| **合计** | **115** | **18** | **67** | **30** | **31** | **65** | **19** |
## 优先启动建议
**立即启动(第1-2周)**
1. T-120 引入 `node-cron` 调度器 — 最小投入,最大基础设施价值
2. T-101~105 目标管理表族 — 闭环体系的起点
3. T-130~132 预警规则引擎核心 — 让系统开始"主动发现问题"
**第3-4周**
4. T-106~107 目标拆解算法 — 让目标"落下去"
5. T-150~151 数据导入管道 — 让数据"流起来"
6. T-160~161 门店自动分级+红黄绿灯 — 让系统"自动区分优先级"
---
> **文档结语**:本任务清单共115项任务,覆盖V3.0全部5个闭环、3条主线、5层架构。建议按Phase顺序推进,每个Phase内按优先级排序。Phase 1完成后系统将从"被动看板"升级为"目标驱动+预警主动"的运营系统,实现质的跃升。
@@ -0,0 +1,302 @@
# V3.0 系统闭环版 — 现有数据支撑度分析
> **版本**V3.0-Data-Assessment
> **基准文档**`连锁企业数字化运营体系(系统闭环版).md`
> **数据源**`bill_query` 数据库(通过 FRP 隧道 `127.0.0.1:15432` 访问)
> **分析日期**2026-08-04
---
## 一、数据资产总览
### 1.1 数据规模
| 数据类别 | 表名 | 记录数 | 时间范围 | 数据状态 |
|:---|:---|---:|:---|:---|
| **账单流水** | `bill_records` | 1,677,993 | 2026年4月 | ✅ 充足 |
| **菜品销售明细** | `dish_sales_details` | 5,553,188 | 2026年7月导入 | ✅ 充足 |
| **配送记录** | `distribution_detail_records` | 325,922 | 2026-03 ~ 2026-04 | ✅ 充足 |
| **会员主数据** | `dim_member` | 83,101 | — | ✅ 充足 |
| **库存快照** | `fact_inventory_snapshot` | 54,842 | 2026-04-01 | ⚠️ 仅1天 |
| **库存成本** | `inventory_cost_records` | 54,973 | — | ✅ 充足 |
| **物料主数据** | `dim_material` | 6,777 | — | ✅ 充足 |
| **中央厨房配方消耗** | `central_kitchen_recipe_consumption` | 4,842 | — | ✅ 充足 |
| **费用记录** | `operating_expense_records` | 3,952 | 2026-04 | ⚠️ 仅1月 |
| **薪资记录** | `salary_detail_records` | 3,596 | — | ✅ 可用 |
| **菜品成本材料明细** | `dish_cost_analysis_material_detail` | 3,568 | — | ✅ 可用 |
| **考勤记录** | `attendance_records` | 3,556 | — | ✅ 可用 |
| **BOM配方** | `fact_recipe_bom` | 3,520 | — | ✅ 可用 |
| **中央厨房物料日耗** | `central_kitchen_material_daily` | 3,329 | — | ✅ 可用 |
| **员工主数据** | `dim_employee` | 3,326 | — | ✅ 充足 |
| **SKU主数据** | `dim_sku` | 1,745 | — | ✅ 充足 |
| **中央厨房完工入库** | `central_kitchen_finished_receipt` | 1,708 | — | ✅ 可用 |
| **菜品成本汇总** | `dish_cost_analysis_summary` | 788 | — | ✅ 可用 |
| **供应商主数据** | `dim_supplier` | 198 | — | ✅ 可用 |
| **门店主数据** | `dim_store` | 91 | — | ✅ 充足 |
| **门店目标** | `dim_store_target` | 182 | 2026-05 | ⚠️ 仅1月 |
| **门店任务** | `store_task` | 138 | 2026-05 | ⚠️ 仅1月 |
| **日历维度** | `dim_calendar` | 365 | — | ✅ 可用 |
### 1.2 物化视图(47个)
| 类别 | 数量 | 代表视图 |
|:---|---:|:---|
| **门店评分/风险** | 8 | `mv_store_risk_rating_monthly``mv_store_scorecard``mv_store_benchmark_composite_monthly` |
| **门店成本** | 2 | `mv_store_theoretical_actual_cost_monthly``mv_inventory_cost_classified_monthly` |
| **菜品分析** | 8 | `mv_dish_sku_summary_monthly``mv_dish_store_summary_monthly``mv_dish_sku_abc_monthly` |
| **门店画像** | 6 | `mv_store_category_mix_monthly``mv_store_platform_economics_monthly``mv_store_member_opportunity_monthly` |
| **选址分析** | 4 | `mv_store_site_profile_monthly``mv_store_site_replication_monthly``mv_district_site_benchmark_monthly` |
| **时间/客流** | 4 | `mv_bill_hourly``mv_time_hourly``mv_time_weekday``mv_store_revenue` |
| **风险监控** | 3 | `mv_risk_anomaly``mv_risk_cashier``mv_risk_zero` |
| **配送分析** | 1 | `mv_distribution_monthly` |
| **其他** | 11 | `mv_store_area_efficiency_monthly``mv_store_repeat_summary_monthly` 等 |
### 1.3 组织维度数据
| 维度 | 数量 | 明细 |
|:---|---:|:---|
| **门店总数** | 91 | 覆盖北京13个区 + 西安未央区 |
| **区域分布** | 13区 | 海淀23、朝阳20、丰台16、西城9、大兴6、东城5、石景山2、昌平2、房山1、怀柔1、通州1、未央1、未知4 |
| **员工总数** | 3,326 | 含考勤+薪资记录 |
| **会员总数** | 83,101 | 含等级分层(钻石/金卡/银卡/普通) |
| **SKU总数** | 1,745 | 含品类层级 |
| **供应商总数** | 198 | 含评估数据 |
| **物料总数** | 6,777 | 含BOM关系 |
---
## 二、V3.0 五层架构数据支撑度
### 2.1 第一层:作业层(一线员工/设备)
| V3.0要求的数据 | 现有数据源 | 支撑度 | 差距 |
|:---|:---|:---:|:---|
| 个人出餐时效 | ❌ 无扫码计时数据 | **0%** | 需出品扫码枪+计时系统 |
| 个人销售额 | ⚠️ `dish_sales_details` 有菜品销售但未关联到个人 | **20%** | 需员工工号关联 |
| 个人好评引导数 | ❌ 无评价数据 | **0%** | 需对接评价系统 |
| 考勤打卡 | ✅ `attendance_records`3,556条) | **80%** | 缺实时打卡API |
| 工时统计 | ✅ `attendance_records` 有打卡时间 | **70%** | 需工时计算引擎 |
| 温度数据 | ❌ 无IoT数据 | **0%** | 需温控探针硬件 |
| 扫码确认 | ❌ 无扫码数据 | **0%** | 需扫码枪硬件 |
| **作业层总体支撑度** | | **20%** | 硬件接入是主要瓶颈 |
### 2.2 第二层:执行层(门店/店长)
| V3.0要求的数据 | 现有数据源 | 支撑度 | 差距 |
|:---|:---|:---:|:---|
| 日营收达成 | ✅ `bill_fact`168万条,2026年4月) | **85%** | 仅1个月数据,需持续导入 |
| 客单价 | ✅ `bill_fact``avg_bill_value` | **85%** | 同上 |
| 来客数 | ✅ `bill_fact``bill_count` + 客流字段 | **80%** | 同上 |
| 食材成本率 | ✅ `dish_cost_analysis_summary`788条) | **80%** | 需按月持续导入 |
| 人力成本 | ✅ `salary_detail_records`3,596条) | **75%** | 需按月持续导入 |
| 能耗/损耗 | ⚠️ `operating_expense_records` 有能耗字段 | **60%** | 仅1个月数据 |
| 出餐时效 | ❌ 无出品计时数据 | **0%** | 需扫码系统 |
| 好评率/差评 | ❌ 无评价数据 | **0%** | 需对接外卖平台API |
| 会员消费占比 | ✅ `bill_fact` 有会员标识 | **80%** | 同账单数据 |
| 到货验收 | ✅ `distribution_detail_records`32.6万条) | **70%** | 缺验收合格率字段 |
| 库存周转 | ✅ `fact_inventory_snapshot`5.5万条) | **50%** | 仅1天快照,需每日快照 |
| 排班数据 | ✅ `attendance_records` 有排班信息 | **70%** | 需排班算法 |
| **执行层总体支撑度** | | **65%** | 数据基本支撑,需持续导入+评价数据 |
### 2.3 第三层:管控层(区域/大区/督导)
| V3.0要求的数据 | 现有数据源 | 支撑度 | 差距 |
|:---|:---|:---:|:---|
| 区域营收达成 | ✅ `dim_store` 有区域字段 + `bill_fact` 有营收 | **85%** | 13个区域,91家店 |
| 门店排名 | ✅ `mv_store_risk_rating_monthly` | **85%** | 已有风险评级 |
| 巡检得分 | ❌ 无巡检数据 | **0%** | 需巡检系统 |
| 门店分级(A/B/C/D) | ⚠️ `store_task``priority` 字段但非自动分级 | **30%** | 需自动分级算法 |
| 红黄绿灯 | ✅ `mv_store_risk_rating``risk_level`(红/黄/绿) | **70%** | 需实时计算+推送 |
| 同店增长 | ⚠️ 仅1个月数据,无法计算同比 | **20%** | 需多个月数据 |
| 人才梯队 | ⚠️ `dim_employee` 有员工数据但无储备/晋升标记 | **30%** | 需人才九宫格 |
| 营销ROI | ⚠️ `mv_store_platform_economics_monthly` 有平台数据 | **50%** | 缺活动维度 |
| 到货准时率 | ✅ `distribution_detail_records` 有时间字段 | **60%** | 需计算逻辑 |
| **管控层总体支撑度** | | **55%** | 需巡检数据+多月份+人才标记 |
### 2.4 第四层:决策层(总部各中心)
| V3.0要求的数据 | 现有数据源 | 支撑度 | 差距 |
|:---|:---|:---:|:---|
| 集团营收/利润 | ✅ `mv_overview_monthly` + `mv_overview_daily` | **80%** | 仅1个月 |
| 品类矩阵 | ✅ `mv_dish_sku_summary_monthly` + `dim_sku` | **80%** | 1,745个SKU |
| 菜品成本 | ✅ `dish_cost_analysis_summary`788条) | **80%** | 需按月持续 |
| 供应链成本 | ✅ `distribution_detail_records` + `dim_supplier` | **65%** | 198家供应商 |
| 中央厨房产能 | ✅ `central_kitchen_recipe_consumption` + `central_kitchen_material_daily` | **70%** | 需产能利用率计算 |
| BOM穿透 | ✅ `fact_recipe_bom`3,520条) | **80%** | 已有BOM关系 |
| 会员LTV | ✅ `dim_member`83,101条) | **80%** | 含等级/消费/状态 |
| 菜单工程 | ✅ `mv_dish_sku_abc_monthly` + `dish_sales_details` | **75%** | 有ABC分类 |
| 库存周转 | ⚠️ `fact_inventory_snapshot` 仅1天 | **40%** | 需每日快照 |
| 费用结构 | ⚠️ `operating_expense_records` 仅1月 | **50%** | 需多月数据 |
| 选址分析 | ✅ `mv_store_site_profile_monthly` + `store_location_master` | **75%** | 有115个选址 |
| **决策层总体支撑度** | | **70%** | 数据最充足,需多月份持续导入 |
### 2.5 第五层:战略层(老板/董事会)
| V3.0要求的数据 | 现有数据源 | 支撑度 | 差距 |
|:---|:---|:---:|:---|
| 全局仪表盘 | ✅ `mv_overview_monthly` | **70%** | 仅1个月 |
| 区域对比 | ✅ `dim_store` 13区域 + `mv_store_risk_rating` | **75%** | 需多月对比 |
| 投资回报 | ⚠️ `dim_store_target``profit_target` | **40%** | 缺投资成本数据 |
| 行业对标 | ❌ 无外部数据 | **0%** | 需行业数据源 |
| 品牌NPS | ❌ 无NPS数据 | **0%** | 需调研系统 |
| 资本环境 | ❌ 无外部数据 | **0%** | 需外部数据源 |
| 同店增长 | ⚠️ 仅1个月无法计算 | **10%** | 需12个月+数据 |
| **战略层总体支撑度** | | **30%** | 严重依赖外部数据+多月份历史 |
---
## 三、五个闭环数据支撑度
### 3.1 目标闭环(Target Loop
| 数据需求 | 现有数据 | 支撑度 |
|:---|:---|:---:|
| 年度战略目标 | ❌ 无 | **0%** |
| 区域年度目标 | ❌ 无 | **0%** |
| 门店月度目标 | ✅ `dim_store_target`(182条,含营收/客单/会员/成本/利润目标) | **70%** |
| 日目标 | ❌ 无日级目标拆解 | **0%** |
| 达成率计算 | ✅ `bill_fact` + `dim_store_target` 可计算 | **60%** |
| 偏差归因 | ⚠️ 有成本偏差(`dish_cost_analysis`)但缺综合归因 | **30%** |
| **目标闭环总体支撑度** | | **25%** | 有月度目标但缺日级目标和自动拆解 |
### 3.2 数据闭环(Data Loop
| 数据需求 | 现有数据 | 支撑度 |
|:---|:---|:---:|
| POS销售数据 | ✅ `bill_records` 168万条 + `bill_fact` 物化视图 | **80%** |
| 菜品销售明细 | ✅ `dish_sales_details` 555万条 | **85%** |
| 外卖平台数据 | ✅ `bill_records` 有美团/饿了么/京东字段 | **60%** |
| 会员数据 | ✅ `dim_member` 8.3万条 | **80%** |
| 库存数据 | ⚠️ `fact_inventory_snapshot` 仅1天 | **30%** |
| 费用数据 | ⚠️ `operating_expense_records` 仅1月 | **40%** |
| 薪资数据 | ✅ `salary_detail_records` 3,596条 | **70%** |
| 考勤数据 | ✅ `attendance_records` 3,556条 | **70%** |
| 配送数据 | ✅ `distribution_detail_records` 32.6万条 | **75%** |
| 中央厨房数据 | ✅ `central_kitchen_*` 多表 | **70%** |
| IoT温度数据 | ❌ 无 | **0%** |
| 扫码数据 | ❌ 无 | **0%** |
| 评价数据 | ❌ 无 | **0%** |
| **数据闭环总体支撑度** | | **55%** | 核心业务数据充足,IoT/评价/实时采集缺失 |
### 3.3 业务闭环(Business Loop
| 数据需求 | 现有数据 | 支撑度 |
|:---|:---|:---:|
| 产品/SKU主数据 | ✅ `dim_sku` 1,745条 | **80%** |
| 配方SOP | ⚠️ `fact_recipe_bom` 有BOM但无SOP步骤 | **50%** |
| 中央厨房生产 | ✅ `central_kitchen_recipe_consumption` + `central_kitchen_material_daily` | **70%** |
| 配送物流 | ✅ `distribution_detail_records` 32.6万条 | **75%** |
| 门店销售 | ✅ `bill_fact` + `dish_sales_details` | **85%** |
| 顾客评价 | ❌ 无评价数据 | **0%** |
| 产品生命周期 | ❌ 无上市日期/生命周期阶段 | **0%** |
| 菜单工程分析 | ✅ `mv_dish_sku_abc_monthly` + `dish_sales_details` | **75%** |
| **业务闭环总体支撑度** | | **55%** | 产销链数据充足,缺评价+生命周期 |
### 3.4 协同闭环(Collaboration Loop
| 数据需求 | 现有数据 | 支撑度 |
|:---|:---|:---:|
| 门店销量预测 | ⚠️ 仅1个月数据,预测可靠性低 | **30%** |
| 中央厨房MRP | ✅ `fact_recipe_bom` + `central_kitchen_material_daily` | **60%** |
| 供应商管理 | ✅ `dim_supplier` 198条 | **60%** |
| 采购到货 | ✅ `distribution_detail_records` | **65%** |
| 门店验收 | ⚠️ 配送有记录但无验收合格率 | **40%** |
| 员工绩效 | ✅ `dim_employee` + `salary_detail_records` | **60%** |
| 人才九宫格 | ❌ 无潜力评估数据 | **10%** |
| 营销活动 | ⚠️ `mv_store_platform_economics_monthly` 有平台数据 | **40%** |
| **协同闭环总体支撑度** | | **45%** | 需多月份数据+验收+人才评估 |
### 3.5 迭代闭环(Improvement Loop
| 数据需求 | 现有数据 | 支撑度 |
|:---|:---|:---:|
| 任务执行记录 | ✅ `store_task` 138条 + `store_task_log` | **70%** |
| 周检查记录 | ⚠️ `task_weekly_check` 表存在但数据量未知 | **50%** |
| 月度验收 | ⚠️ `task_monthly_review` 表存在但数据量未知 | **50%** |
| 经验标准化 | ⚠️ `standardized_practice` 表存在 | **40%** |
| 经验推广 | ⚠️ `practice_replication` 表存在 | **40%** |
| 指标字典 | ✅ `indicator_dictionary` 表存在 | **70%** |
| 数据质量 | ⚠️ `data_quality_log` 表存在 | **40%** |
| **迭代闭环总体支撑度** | | **50%** | 表结构已建,数据量偏少 |
---
## 四、关键差距与瓶颈
### 4.1 时间维度差距(最大瓶颈)
| 问题 | 影响 | 严重度 |
|:---|:---|:---:|
| **`bill_fact` 仅2026年4月1个月** | 无法计算同店增长、同比、环比、趋势预测 | 🔴 严重 |
| **`dim_store_target` 仅2026年5月** | 无法做目标校准、历史达成率分析 | 🔴 严重 |
| **`operating_expense_records` 仅2026年4月** | 无法做费用趋势分析 | 🟡 中等 |
| **`fact_inventory_snapshot` 仅2026-04-01一天** | 无法做库存周转分析 | 🔴 严重 |
| **`store_task` 仅2026年5月** | 无法做闭环健康度趋势 | 🟡 中等 |
**结论**:当前数据仅覆盖1-2个月,**无法支撑V3.0要求的趋势分析、同店增长、目标校准、同比环比等核心功能**。需要至少积累3-6个月的数据。
### 4.2 数据缺失清单
| 缺失数据 | 影响的V3.0模块 | 补齐方式 | 难度 |
|:---|:---|:---|:---:|
| **顾客评价数据** | 业务闭环、预警引擎、产品迭代 | 对接外卖平台评价API | 中 |
| **巡检数据** | 管控层、门店分级、食安预警 | 新建巡检系统 | 高 |
| **IoT温度数据** | 数据闭环、食安预警、冷链监控 | 部署IoT硬件 | 高 |
| **扫码数据** | 作业层、执行流闭环 | 部署扫码枪 | 高 |
| **日级目标数据** | 目标闭环、日目标卡 | 新建目标拆解系统 | 中 |
| **产品生命周期数据** | 业务闭环、产品PLM | 新建生命周期表 | 低 |
| **人才评估数据** | 协同闭环、HR九宫格 | 新建评估体系 | 中 |
| **审批流数据** | 审批流矩阵 | 新建审批系统 | 中 |
| **培训数据** | 迭代闭环、LMS | 新建LMS系统 | 高 |
| **行业对标数据** | 战略驾驶舱 | 外部数据采购 | 中 |
### 4.3 数据质量风险
| 风险 | 详情 | 影响 |
|:---|:---|:---|
| **手工导入延迟** | 数据非实时,依赖手工导入 | V3.0要求T+0实时看板,当前仅T+1 |
| **物化视图未刷新** | 47个物化视图需手工REFRESH | 数据可能过期 |
| **门店名映射不一致** | `bill_records.c003``dim_store.store_name` 需映射 | 多表关联可能出错 |
| **区域字段不完整** | 4家门店"未知区域" | 区域分析有盲区 |
---
## 五、数据支撑度总评
### 5.1 按层级汇总
| V3.0层级 | 数据支撑度 | 核心瓶颈 |
|:---|:---:|:---|
| **作业层** | **20%** | 硬件缺失(IoT/扫码枪/人脸识别) |
| **执行层** | **65%** | 评价数据缺失、库存仅1天、需多月份 |
| **管控层** | **55%** | 巡检数据缺失、门店分级未自动化、仅1个月 |
| **决策层** | **70%** | 数据最充足,需多月份持续导入 |
| **战略层** | **30%** | 外部数据缺失、同店增长无法计算 |
| **整体加权平均** | **~48%** | 时间跨度不足是最大瓶颈 |
### 5.2 按闭环汇总
| V3.0闭环 | 数据支撑度 | 核心瓶颈 |
|:---|:---:|:---|
| **目标闭环** | **25%** | 日级目标缺失、自动拆解未实现 |
| **数据闭环** | **55%** | IoT/评价/实时采集缺失 |
| **业务闭环** | **55%** | 评价数据+产品生命周期缺失 |
| **协同闭环** | **45%** | 多月份数据不足、人才评估缺失 |
| **迭代闭环** | **50%** | 表已建但数据量偏少 |
| **整体加权平均** | **~46%** | 评价数据+多月份是核心瓶颈 |
### 5.3 结论
**现有数据可以支撑V3.0的部分实现,但存在三个关键瓶颈**:
1. **时间跨度不足(最大瓶颈)**:核心业务数据仅覆盖1-2个月,无法支撑趋势分析、同店增长、目标校准等V3.0核心功能。**需要至少3-6个月的持续数据积累**。
2. **采集层缺失**:IoT温度、扫码确认、顾客评价三类数据完全空白,这直接影响了V3.0的"自动采集"和"自动验证"两大自动化。**需要硬件投入和外部API对接**。
3. **管理和人才数据空白**:巡检得分、人才评估、审批流、培训记录等管理类数据完全缺失。**需要新建对应系统模块**。
**建议优先行动**
- **立即**:建立定时数据导入管道,确保每月持续导入账单、费用、库存、薪资数据
- **短期(1-3月)**:对接外卖平台评价API,补齐评价数据;建立每日库存快照
- **中期(3-6月)**:积累6个月数据后,启动目标闭环和趋势分析功能
- **长期(6-12月)**:逐步补齐IoT、扫码、巡检等硬件依赖数据
+744
View File
@@ -0,0 +1,744 @@
# V3.0 系统闭环版 — 对照本系统实现的完整路径
> **版本**V3.0-Impl-Path
> **基准文档**`连锁企业数字化运营体系(系统闭环版).md`
> **对照系统**SBrainCO 当前代码库(client/ + server/ + shared/ + db/
> **编制日期**2026-08-04
---
## 目录
1. [总体对照矩阵:V3.0五层架构 vs 系统现状](#一总体对照矩阵)
2. [三条主线实现路径](#二三条主线实现路径)
3. [五个闭环实现路径](#三五个闭环实现路径)
4. [日/周/月系统自动流转实现路径](#四日周月系统自动流转实现路径)
5. [权限与隔离实现路径](#五权限与隔离实现路径)
6. [系统核心模块架构实现路径](#六系统核心模块架构实现路径)
7. [关键系统接口实现路径](#七关键系统接口实现路径)
8. [分阶段实施路线图](#八分阶段实施路线图)
---
## 一、总体对照矩阵
### 1.1 五层架构对照
| V3.0 层级 | V3.0 定位 | 系统现状 | 实现状态 | 差距与路径 |
|:---|:---|:---|:---|:---|
| **第五层:战略层** | 老板/董事会,看"势" | `BossPage.tsx`(老板驾驶舱)、`BankPage.tsx`(银行授信) | **部分实现** | 缺少季度战略看板、投资回报模型、行业对标;需新增战略驾驶舱模块 |
| **第四层:决策层** | 总部各中心,看"阵" | `DashboardPage.tsx`(总部驾驶舱)、`SKUPage.tsx``CostPage.tsx``CentralKitchenPage.tsx``ProductionPlanPage.tsx``BomPenetrationPage.tsx``DistributionReconciliationPage.tsx` | **大部分实现** | 缺少产品PLM生命周期管理、营销MA模块;产品中心仅有SKU/菜单工程,无研发流程 |
| **第三层:管控层** | 区域/大区/督导,看"店" | `RegionalPage.tsx``RegionComparisonPage.tsx``MonthlyReviewPage.tsx` | **部分实现** | 缺少门店自动分级(A/B/C/D)、红黄绿灯自动标色推送、辅导任务派发 |
| **第二层:执行层** | 门店/店长,看"事" | `StorePage.tsx`(店长工作台)、`StoreDetailPage.tsx``TasksPage.tsx``TaskDetailPage.tsx` | **大部分实现** | 缺少日目标卡自动生成、时段目标拆解、扫码确认闭环 |
| **第一层:作业层** | 一线员工/设备,看"数" | `EmployeePerformancePage.tsx``SmartSchedulingPage.tsx` | **初步实现** | 缺少个人数据看板、扫码/IoT自动采集、实时个人绩效推送 |
### 1.2 系统技术栈现状
| 维度 | 现状 |
|:---|:---|
| **前端** | React 18 + TypeScript + Vite + TanStack Query + Tailwind CSS + shadcn/ui + Lucide Icons |
| **后端** | Express.js + TypeScript + PostgreSQL(多租户连接池) |
| **认证** | JWT7天TTL+ bcrypt + 角色路由守卫(`RoleRoute`组件) |
| **多租户** | `tenant_configs` 表 + 动态连接池切换(`tenantContextStorage` |
| **数据隔离** | `data-scope.ts` 中间件 + SQL自动注入 `store_code` 过滤 |
| **API规范** | 统一 `ApiResponse<T>` 壳(`{success, data, meta, error}` |
| **数据库** | PostgreSQL + analytics schema + 物化视图 + 自定义函数 |
---
## 二、三条主线实现路径
### 2.1 主线一:数据流(自下而上,自动汇聚)
#### 现状
| 环节 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| **采集** | POS、IoT、扫码枪、电子秤、人脸识别等多源自动接入 | 仅有手工导入 `bill_records` 表 + `attendance_records` + `salary_detail_records`;无实时API对接 | **未实现** |
| **清洗** | 异常数据自动标记 + 规则引擎 + ML异常检测 | `DataQualityPage.tsx` 提供数据质量检查视图;无自动清洗管道 | **初步实现** |
| **聚合** | 按岗位/门店/区域/总部自动分层聚合 | 已实现多层物化视图(`mv_overview_monthly``mv_store_risk_rating_monthly` 等);`10_materialize_slow_views.sql` | **已实现** |
| **分析** | 自动计算同比/环比/达成率/偏差度/排名/趋势预测 | `analytics-enhanced.ts` 提供会员LTV、菜单工程等分析;`situational-awareness.ts` 提供健康度评分 | **大部分实现** |
| **呈现** | 每层只看见权限内数据 + 自动推送 | `data-scope.ts` 实现数据权限隔离;无自动推送机制(缺少消息推送引擎) | **部分实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 | 依赖 |
|:---|:---|:---|:---|
| **P1** | 建立 POS 数据实时导入管道(API对接或定时ETL) | 高 | 需POS系统配合 |
| **P1** | 建立数据清洗规则引擎:异常金额、缺失字段、温度异常自动标记 | 高 | 依赖采集层 |
| **P2** | 增加趋势预测算法:基于历史数据的简单线性回归/ARIMA | 中 | 依赖聚合层历史数据 |
| **P2** | 建立消息推送引擎:WebSocket 或轮询 + 站内消息中心 | 中 | 独立模块 |
| **P3** | IoT 温控探针对接:MQTT 协议接入冷链温度数据 | 低 | 需硬件支持 |
| **P3** | 扫码枪/电子秤对接:蓝牙/WiFi 接入出品扫码、验收扫码 | 低 | 需硬件支持 |
### 2.2 主线二:决策流(自上而下,目标拆解)
#### 现状
| 层级 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| **战略层** | 年度战略目标 → 可行性测算 | `BossPage.tsx` 展示全局指标;无目标拆解功能 | **未实现** |
| **决策层** | 年度目标 → 区域/品类/供应链目标 | 无目标管理系统 | **未实现** |
| **管控层** | 区域目标 → 门店月度目标(按分级差异化) | `MonthlyReviewPage.tsx` 支持月度验收;无自动目标拆解 | **未实现** |
| **执行层** | 月度目标 → 日目标卡/时段目标 | `StorePage.tsx` 展示门店数据;无日目标卡自动生成 | **未实现** |
| **作业层** | 日目标 → 个人任务 | `EmployeePerformancePage.tsx` 展示绩效;无个人任务派发 | **未实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 | 依赖 |
|:---|:---|:---|:---|
| **P1** | 新建 `target_management` 表族:`annual_target``regional_target``store_monthly_target``daily_target``personal_task` | 高 | 无 |
| **P1** | 实现目标自动拆解算法:按历史增速 + 门店分级(A/B/C/D)差异化拆解 | 高 | 依赖门店分级模型 |
| **P1** | 店长端日目标卡:每日 09:00 自动生成日目标卡(营收/客单/套餐/损耗/到货) | 高 | 依赖目标拆解 |
| **P2** | 时段目标拆解:按"高峰/平峰/低谷"模型将日目标拆解为时段目标 | 中 | 依赖 `smart-scheduling.ts` 客流热力图数据 |
| **P2** | 个人任务派发:按岗位系数拆解为个人目标(套餐推荐数/出餐时效/会员注册数) | 中 | 依赖 `EmployeePerformancePage` 扩展 |
| **P3** | AI 辅助目标测算:基于多因子模型(天气/节假日/商圈活动)自动调整日目标 | 低 | 依赖外部数据源 |
### 2.3 主线三:执行流(横向协同,闭环跟踪)
#### 现状
| 环节 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| **目标下达** | 目标 → 任务池 → 岗位待办 | `tasks.ts` 支持 CRUD + 状态流转;`TasksPage.tsx` 展示任务列表 | **已实现** |
| **执行记录** | 扫码/确认 → 数据回传 | `TaskDetailPage.tsx` 支持填写执行证据(`process_evidence`);无扫码确认 | **部分实现** |
| **偏差预警** | 实时比对 → 自动预警 → 纠偏任务 | `situational-awareness.ts` 提供健康度评分 + 红黄绿灯;无自动预警推送 | **部分实现** |
| **纠偏行动** | 自动生成纠偏任务 → 入池 | `tasks.ts` 支持手动创建任务;无自动触发机制 | **未实现** |
| **结果验证** | 系统自动检测达成率回升 → 闭环完成 | `MonthlyReviewPage.tsx` 支持月度验收(达标/改善中/未改善);无实时验证 | **部分实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 | 依赖 |
|:---|:---|:---|:---|
| **P1** | 任务自动生成引擎:基于指标偏差自动生成整改任务(当前 `05_backfill_task_values.sql` 为手工批量生成) | 高 | 依赖指标阈值 |
| **P1** | 实时预警推送:当指标突破红/黄灯阈值时,自动推送至对应责任人 | 高 | 依赖消息推送引擎 |
| **P2** | 纠偏任务自动入池:预警触发后自动生成纠偏任务,关联原任务 | 中 | 依赖预警推送 |
| **P2** | 扫码确认闭环:出品扫码、验收扫码、巡检扫码 → 数据自动回传 → 任务状态自动更新 | 中 | 需扫码硬件 |
| **P3** | 闭环自动验证:系统定时检测指标变化,自动判定"闭环完成"或"需升级" | 低 | 依赖实时数据 |
---
## 三、五个闭环实现路径
### 3.1 闭环一:目标闭环(Target Loop)
#### 现状
| 环节 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| 目标设定 | 战略输入 → 系统自动拆解 | 无目标管理系统 | **未实现** |
| 执行跟踪 | 实时执行跟踪 → 每小时比对达成率 | `situational-awareness.ts` 提供月度健康度;无小时级比对 | **未实现** |
| 偏差分析 | 归因模型(客流/客单/成本/损耗) | `cost-analysis.ts` 提供成本偏差分析;无综合归因模型 | **部分实现** |
| 目标校准 | 下月目标自动调整 | 无自动校准机制 | **未实现** |
| 强制节点 | 未达成门店锁定预算 + 根因分析审批 | 无锁定机制 | **未实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 |
|:---|:---|:---|
| **P1** | 新建 `target_loop` 表族:`annual_target``store_monthly_target``target_deviation_analysis` | 高 |
| **P1** | 实现目标拆解算法(按门店分级差异化:A店110%、B店100%、C店90%爬坡、D店整改) | 高 |
| **P1** | 月末自动比对达成率 + 自动生成偏差分析报告 | 高 |
| **P2** | 强制锁定机制:达成率<90%的门店,下月预算锁定,必须填写《根因分析》并通过审批 | 中 |
| **P2** | 连续3个月未达成 → 自动触发"D级预警"推送至决策层 | 中 |
| **P3** | 目标自动校准:基于历史达成率 + 外部因子自动调整下月目标 | 低 |
### 3.2 闭环二:数据闭环(Data Loop)
#### 现状
| 环节 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| **采集** | 多源数据自动接入 | 手工导入 `bill_records`;无实时API | **未实现** |
| **清洗** | 异常数据自动标记 | `DataQualityPage.tsx` 提供质量检查视图;无自动清洗 | **初步实现** |
| **聚合** | 数据仓库自动ETL | 物化视图 + `data_refresh_log` 表记录刷新;需手工执行SQL | **部分实现** |
| **分析** | BI引擎自动运算 | 多个分析路由(`analytics-enhanced.ts``cost-analysis.ts``situational-awareness.ts` | **已实现** |
| **呈现** | 权限矩阵 + 消息推送 | 权限隔离已实现;无消息推送 | **部分实现** |
| **决策** | 看板嵌入"一键下达任务"按钮 | `SituationalAwarenessPage.tsx` 有健康度评分;无一键下达 | **未实现** |
| **执行** | 任务执行后扫码确认 | 手工填写 `process_evidence`;无扫码 | **部分实现** |
| **再采集** | 执行数据成为新数据源 | 任务状态变更记录在 `store_task_log`;未回流为分析数据 | **初步实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 |
|:---|:---|:---|
| **P1** | 建立定时ETL管道:cron job 定期执行物化视图刷新 + 数据导入 | 高 |
| **P1** | 数据清洗规则引擎:自动标记异常数据(金额异常、时间异常、缺失字段) | 高 |
| **P2** | 看板嵌入"一键下达任务"按钮:在 `SituationalAwarenessPage` 健康度评分异常项旁添加"生成整改任务"按钮 | 中 |
| **P2** | 消息推送引擎:异常数据自动推送至对应责任人 | 中 |
| **P3** | 实时数据流:从T+1升级为T+0实时看板(WebSocket推送) | 低 |
### 3.3 闭环三:业务闭环(Business Loop
#### 现状
| 环节 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| 产品上架 → SOP推送 | 产品中心上架新品 → 自动推送配方SOP至中央厨房 | `CentralKitchenPage.tsx` 展示中央厨房数据;无PLM系统对接 | **未实现** |
| 中央厨房排产 | MRP系统自动排产 | `ProductionPlanPage.tsx` 展示生产要货计划;无自动排产算法 | **部分实现** |
| 物流配送 | 配送系统自动调度 | `DistributionReconciliationPage.tsx` 展示配送对账;无TMS调度 | **部分实现** |
| 门店销售 | POS记录 | `bill_records` 表有销售数据;非实时导入 | **部分实现** |
| 顾客反馈 | NLP自动归因 | 无评价分析模块 | **未实现** |
| 产品生命周期 | 上市7天首周战报、90天存活判定 | `MenuEngineeringPage.tsx` 有菜单工程分析;无生命周期自动追踪 | **部分实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 |
|:---|:---|:---|
| **P1** | 新建 `product_lifecycle` 表:SKU上市日期、生命周期阶段(爬坡/成熟/衰退)、存活判定 | 高 |
| **P1** | 顾客评价归因:对接外卖平台评价API + NLP自动分类(口味/服务/环境/异物) | 高 |
| **P2** | 产品生命周期自动追踪:上市第7天自动生成"首周战报"、第90天生成"存活判定报告" | 中 |
| **P2** | 中央厨房排产算法:基于门店销量预测 + 配方BOM自动计算生产计划 | 中 |
| **P3** | 全链路自动流转:产品上架 → SOP推送 → 排产 → 配送 → 门店收货 → 销售 → 评价 → 产品决策 | 低 |
### 3.4 闭环四:协同闭环(Collaboration Loop
#### 现状
| 协同场景 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| **产销协同** | 门店销量预测 → 中央厨房MRP → 采购需求 → 供应商接单 | `ProductionPlanPage.tsx` 有生产要货计划;无自动预测和供应商接单 | **部分实现** |
| **营采协同** | 营销方案 → 物料计算 → 供应链备货 → 门店执行 → ROI | `PlatformPage.tsx` 有平台优惠分析;无营销-供应链协同 | **部分实现** |
| **产研协同** | 研发立项 → 试制排期 → 成本测算 → 盲测 → 上市决策 | 无研发管理系统 | **未实现** |
| **人才盘点** | 绩效聚合 → 九宫格 → 晋升推荐 → 培训计划 | `EmployeePerformancePage.tsx` 有绩效展示;无九宫格/晋升推荐 | **部分实现** |
| **供应链质量协同** | 验收异常 → 供应商整改 → 复验 → 评分更新 | `DistributionReconciliationPage.tsx` 有配送对账;无供应商SRM | **部分实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 |
|:---|:---|:---|
| **P1** | 门店销量预测:基于历史数据的简单预测模型(移动平均/指数平滑) | 高 |
| **P2** | 人才九宫格:绩效 × 潜力二维矩阵,自动推荐晋升名单 | 中 |
| **P2** | 供应商评分卡:交货准时率/质量/价格/服务/食安五维度自动评分 | 中 |
| **P3** | 产销协同全链路:销量预测 → MRP → 采购 → 到货 → 验收 → 数据回传 | 低 |
| **P3** | 营采协同:营销方案 → 物料需求计算 → 供应链备货 → ROI追踪 | 低 |
### 3.5 闭环五:迭代闭环(Improvement Loop
#### 现状
| 环节 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| **执行** | 全链路数据留痕 | `store_task_log` 记录任务状态变更;`task_weekly_check` 记录周检查 | **已实现** |
| **复盘** | 月度/季度自动复盘报告 | `MonthlyReviewPage.tsx` 支持月度验收;无自动复盘报告生成 | **部分实现** |
| **知识沉淀** | 优秀案例自动归档 + NLP提取要素 | `standardized_practice` 表 + `practice_replication` 表已建;无NLP自动提取 | **部分实现** |
| **标准更新** | 案例库触发SOP更新流程 | 无变更管理流程 | **未实现** |
| **培训下发** | 新标准 → 培训课件 → 推送至落后门店 | 无LMS系统 | **未实现** |
| **再执行** | 巡检验证 + 数据比对验证 | `task_weekly_check` 有周度验证;无培训后验证 | **部分实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 |
|:---|:---|:---|
| **P1** | 自动复盘报告:月末自动生成月度经营分析报告(损益/对标/根因/建议) | 高 |
| **P2** | 案例库NLP标签:对 `standardized_practice` 表的 `key_actions` 自动提取标签分类 | 中 |
| **P2** | 变更管理流程:SOP更新申请 → 审批 → 下发 → 确认 | 中 |
| **P3** | LMS系统对接:新标准自动转化为培训课件 + 推送 + 追踪完成率 | 低 |
| **P3** | 培训锁定机制:未完成培训的员工自动锁定排班权限 | 低 |
---
## 四、日/周/月系统自动流转实现路径
### 4.1 时间驱动(Time-Driven
#### 现状
| 触发时间 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| 每日 08:30 | 自动生成昨日日报 | 无自动日报生成;`StorePage.tsx` 展示数据但需手工查看 | **未实现** |
| 每日 09:00 | 自动生成今日目标卡 | 无目标卡系统 | **未实现** |
| 每日 12:00/18:00 | 推送时段达成率 | 无时段达成率推送 | **未实现** |
| 每日 22:30 | 生成日复盘模板 | 无日复盘模板 | **未实现** |
| 每周一 09:00 | 生成上周数据包 | 无自动周报 | **未实现** |
| 每月1日 09:00 | 生成上月经营分析报告 | `MonthlyReviewPage.tsx` 支持月度验收;无自动报告生成 | **部分实现** |
| 每月15日 14:00 | 生成月中进度报告 | 无月中进度报告 | **未实现** |
| 每季度首月1日 | 生成季度战略复盘数据包 | 无季度报告 | **未实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 | 技术方案 |
|:---|:---|:---|:---|
| **P1** | 引入定时任务调度器(node-cron) | 高 | `server/src/scheduler/` 新建调度模块 |
| **P1** | 每日 08:30 自动生成昨日日报(SQL聚合 + 模板渲染 + 推送) | 高 | 复用 `data.ts` 聚合逻辑 + 报告模板 |
| **P1** | 每日 09:00 自动生成日目标卡 | 高 | 依赖目标拆解算法 |
| **P2** | 每日 12:00/18:00 推送时段达成率 | 中 | 依赖实时数据采集 |
| **P2** | 每周一 09:00 生成上周数据包 | 中 | 复用 `analytics-enhanced.ts` |
| **P2** | 每月1日 09:00 自动生成月度经营分析报告 | 中 | 复用 `MonthlyReviewPage` 逻辑 |
| **P3** | 每月15日 14:00 月中进度报告 | 低 | 依赖目标系统 |
| **P3** | 每季度首月1日 季度战略复盘数据包 | 低 | 依赖战略驾驶舱 |
### 4.2 事件驱动(Event-Driven
#### 现状
| 触发条件 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| 营收达成率 < 80% | 红灯预警 → 推送 → 生成促销建议 | `situational-awareness.ts` 有红黄绿灯评分;无自动预警推送 | **部分实现** |
| 差评出现 | NLP归因 → 推送对应责任人 | 无评价分析 | **未实现** |
| 临期品 > 10% | 推送促销建议 → 生成促销任务 | 无临期品监控 | **未实现** |
| 中央厨房产能 > 90% | 预警至供应链总监 | `CentralKitchenPage.tsx` 展示产能;无自动预警 | **部分实现** |
| 员工离职率 > 15% | 红灯预警 → 推送区域经理 + HR | 无离职率自动监控 | **未实现** |
| 食安巡检 < 90分 | 红灯预警 → 推送 + 停业建议 | 无巡检系统 | **未实现** |
| 供应链到货准时率 < 95% | 黄灯预警 → 启动备选供应商 | `DistributionReconciliationPage.tsx` 有对账;无自动预警 | **部分实现** |
| 新品好评率 < 70% | 推送产品中心 → 配方复核 | 无新品评价追踪 | **未实现** |
| 设备故障 > 2小时 | 自动派单维修 | 无IoT设备监控 | **未实现** |
| 库存缺货 | 推送缺货预警 → 生成调拨建议 | 无实时库存监控 | **未实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 | 技术方案 |
|:---|:---|:---|:---|
| **P1** | 建立预警规则引擎:`alert_rules` 表(指标/阈值/推送对象/升级路径) | 高 | 通用规则配置 |
| **P1** | 营收达成率实时预警:每小时比对日目标 → 红/黄灯 → 推送 | 高 | 依赖目标系统 + 推送引擎 |
| **P1** | 差评自动归因:对接外卖平台评价API + NLP分类 | 高 | 外部API + AI模型 |
| **P2** | 临期品预警:库存系统实时计算临期比例 → 推送促销建议 | 中 | 依赖WMS |
| **P2** | 供应商到货准时率预警:物流GPS + 温控实时监控 | 中 | 依赖TMS |
| **P2** | 员工离职率预警:HR系统月度聚合 → 红灯 → 推送 | 中 | 依赖HR系统 |
| **P3** | 设备故障预警:IoT设备监控 → 自动派单维修 | 低 | 依赖IoT硬件 |
| **P3** | 库存缺货预警:实时库存比对 → 生成调拨建议 | 低 | 依赖WMS |
---
## 五、权限与隔离实现路径
### 5.1 纵向权限矩阵(层级隔离)
#### 现状
| 规则 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| 上级看下级透明 | 区域经理可查看辖区所有门店明细 | `data-scope.ts` 实现:`hq`/`dept` 无限制,`regional``region` 过滤,`store``storeCode` 过滤 | **已实现** |
| 下级不可看上级 | 店长不可查看区域排名明细 | `RoleRoute` 组件限制路由访问;`data-scope.ts` 限制数据范围 | **已实现** |
| 平级看排名不看明细 | A店店长可查看区域均值和排名,不可看B店明细 | `data-scope.ts``storeCode` 过滤;前端展示区域均值 | **已实现** |
| 数据脱敏 | 区域均值不暴露具体门店名称 | 前端展示"区域平均";未做系统级脱敏 | **部分实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 |
|:---|:---|:---|
| **P2** | 系统级数据脱敏:API响应层对 PII 数据(手机/身份证/邮箱)自动脱敏 | 中 |
| **P2** | 匿名排名机制:平级门店排名显示为"TOP10%"而非具体名次 | 中 |
| **P3** | 审计日志:所有数据访问记录 `audit_logs` 表(who/what/when | 低 |
### 5.2 横向权限矩阵(职能隔离)
#### 现状
| 角色 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| 供应链经理 | 可见采购成本/供应商/库存/物流;不可见单店利润/员工绩效 | 系统角色仅有 `hq`/`regional`/`store`/`dept`/`platform_admin`;无职能角色 | **未实现** |
| 产品经理 | 可见菜品销量/好评率/配方SOP;不可见门店营收/供应链采购价 | 同上 | **未实现** |
| 营销经理 | 可见活动ROI/会员数据/平台评分;不可见单店成本/供应链数据 | 同上 | **未实现** |
| HR/培训经理 | 可见员工档案/绩效/培训;不可见门店营收/成本 | 同上 | **未实现** |
| 店长 | 可见本店全部数据/区域匿名均值;不可见其他门店明细/采购价格 | `data-scope.ts` 已实现 `store` 角色按 `storeCode` 过滤 | **已实现** |
| 服务员/厨师 | 可见个人绩效/本店匿名排名;不可见门店营收/成本/利润 | 无员工级角色 | **未实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 |
|:---|:---|:---|
| **P1** | 扩展角色体系:新增 `supply`(供应链)、`product`(产品)、`marketing`(营销)、`hr`HR)职能角色 | 高 |
| **P1** | 职能数据隔离:按角色限制可见的 API 路由和数据字段 | 高 |
| **P2** | 员工级角色:新增 `employee` 角色,仅可见个人绩效看板 | 中 |
| **P2** | 字段级权限控制:API响应按角色过滤敏感字段(如采购价格对非供应链角色隐藏) | 中 |
### 5.3 审批流矩阵
#### 现状
| 操作 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| 门店调薪 | 店长申请 → 区域经理审批 → 超额升级总部HR | 无审批流系统 | **未实现** |
| 门店临时采购 | 店长申请 → 区域经理审批 → 超额升级供应链总监 | 无审批流系统 | **未实现** |
| 促销活动 | 店长申请 → 区域经理审批 → 超额升级营销总监 | 无审批流系统 | **未实现** |
| 员工晋升 | 店长申请 → 区域经理+HR审批 → 晋升店长升级总部 | 无审批流系统 | **未实现** |
| 配方微调 | 产品经理申请 → 产品总监审批 → 成本变动>5%升级CEO | 无审批流系统 | **未实现** |
| 供应商汰换 | 供应链经理申请 → 供应链总监审批 → 战略供应商升级CEO | 无审批流系统 | **未实现** |
| 门店关停 | 区域经理申请 → 运营总监+财务总监审批 → 连续亏损升级董事会 | 无审批流系统 | **未实现** |
#### 实现路径
| 阶段 | 任务 | 优先级 |
|:---|:---|:---|
| **P2** | 新建 `approval_flow` 表族:`approval_request``approval_step``approval_rule` | 中 |
| **P2** | 实现通用审批流引擎:支持多级审批 + 超额升级 + 通知推送 | 中 |
| **P3** | 各业务场景接入审批流:调薪/采购/促销/晋升/配方/供应商/关停 | 低 |
---
## 六、系统核心模块架构实现路径
### 6.1 模块对照总览
| V3.0模块 | 系统对应 | 实现状态 | 差距 |
|:---|:---|:---|:---|
| **战略驾驶舱** | `BossPage.tsx` + `BankPage.tsx` | **30%** | 缺少投资回报模型、行业对标、季度战略看板 |
| **产品PLM** | `SKUPage.tsx` + `MenuEngineeringPage.tsx` | **25%** | 缺少研发流程、配方SOP管理、生命周期追踪 |
| **供应链SRM** | `DistributionReconciliationPage.tsx` | **15%** | 缺少供应商管理、采购下单、比价议价、绩效评估 |
| **中央厨房MES** | `CentralKitchenPage.tsx` + `ProductionPlanPage.tsx` + `BomPenetrationPage.tsx` | **40%** | 缺少生产排程算法、工艺监控、食安留样管理 |
| **WMS仓储** | `InventoryTurnoverPage.tsx` | **15%** | 缺少库存管理、临期预警、分拣调度、盘点差异 |
| **TMS物流** | `DistributionReconciliationPage.tsx` | **15%** | 缺少配送路线、车辆调度、在途温控 |
| **门店POS** | `bill_records` 表(手工导入) | **20%** | 缺少实时POS对接、点单收银、会员注册 |
| **区域管理** | `RegionalPage.tsx` + `RegionComparisonPage.tsx` | **40%** | 缺少门店自动分级、红黄绿灯推送、辅导任务派发 |
| **门店终端** | `StorePage.tsx` + `StoreDetailPage.tsx` + `TasksPage.tsx` | **55%** | 缺少日目标卡、实时看板5分钟刷新、扫码确认 |
| **HR系统** | `EmployeePerformancePage.tsx` + `SmartSchedulingPage.tsx` | **20%** | 缺少招聘、考勤、薪酬、晋升、九宫格 |
| **培训LMS** | 无 | **0%** | 完全缺失 |
| **营销MA** | `PlatformPage.tsx` + `MemberPage.tsx` + `MemberLTVPage.tsx` | **30%** | 缺少活动管理、券码发放、营销自动化 |
| **财务ERP** | `CostPage.tsx` + `CostAnalysisPage.tsx` + `StoreExpensePage.tsx` | **40%** | 缺少预算管理、资金管控、财务报表 |
| **数据采集层** | 手工导入 | **10%** | 缺少POS API、IoT、扫码枪、电子秤、人脸识别 |
| **任务管理** | `tasks.ts` + `TasksPage.tsx` + `TaskDetailPage.tsx` | **65%** | 已实现CRUD+状态流转+周检查+月验收;缺自动生成+扫码确认 |
| **态势感知** | `situational-awareness.ts` + `SituationalAwarenessPage.tsx` | **50%** | 已实现健康度评分+红黄绿灯;缺实时预警+自动推送 |
| **智能排班** | `smart-scheduling.ts` + `SmartSchedulingPage.tsx` | **35%** | 已实现客流热力图+在岗人员分布;缺自动排班算法 |
| **指标字典** | `IndicatorsPage.tsx` + `indicator_dictionary` 表 | **70%** | 已实现指标CRUD+阈值管理 |
| **本体标准** | `OntologyPage.tsx` + `db/ontology_standard.sql` | **60%** | 已实现本体标准展示 |
| **风险内控** | `RiskPage.tsx` | **40%** | 已实现风险评分;缺实时预警 |
| **选址分析** | `SiteSelectionPage.tsx` | **50%** | 已实现选址分析模型 |
| **租户管理** | `TenantManagementPage.tsx` + `TenantUsersPage.tsx` + `admin.ts` | **70%** | 已实现多租户+用户管理 |
| **TTS语音** | `tts.ts` + `BusinessReportDialog.tsx` | **80%** | 已实现千问TTS语音播报 |
### 6.2 各模块详细实现路径
#### 6.2.1 战略驾驶舱(当前 30% → 目标 80%)
| 任务 | 优先级 | 依赖 |
|:---|:---|:---|
| 新增投资回报模型:单店ROI计算 + 投资回收期 + 城市渗透率 | 高 | 依赖 `BankPage` 扩展 |
| 新增季度战略看板:同店增长趋势 + 行业对标 + 资本环境 | 中 | 依赖外部数据 |
| 新增品牌资产追踪:NPS + 品牌搜索指数 + 舆情健康度 | 中 | 依赖舆情监控 |
| 年度战略目标管理:目标设定 + 进度追踪 + 调整记录 | 高 | 依赖目标系统 |
#### 6.2.2 产品PLM(当前 25% → 目标 70%
| 任务 | 优先级 | 依赖 |
|:---|:---|:---|
| 新建 `product_lifecycle` 表:SKU上市日期、生命周期阶段、存活判定 | 高 | 无 |
| 配方SOP管理:配方数字化(克重/温度/时间/步骤) + 版本控制 | 高 | 无 |
| 新品研发流程:立项 → 试制 → 盲测 → 成本测算 → 上市决策 | 中 | 依赖中央厨房MES |
| 生命周期自动追踪:7天首周战报 + 90天存活判定 | 中 | 依赖 `product_lifecycle` 表 |
| 顾客评价归因:NLP自动分类(口味/分量/温度/异物) | 中 | 依赖评价API |
#### 6.2.3 供应链SRM(当前 15% → 目标 60%
| 任务 | 优先级 | 依赖 |
|:---|:---|:---|
| 新建 `supplier_master` 表:供应商主数据 + 分级(战略/优选/合格/淘汰) | 高 | 无 |
| 供应商评分卡:交货准时率/质量/价格/服务/食安五维度 | 高 | 依赖到货验收数据 |
| 采购订单管理:下单 → 审批 → 执行 → 到货 → 结算 | 中 | 依赖供应商主数据 |
| 比价议价:招标/比价/锁价/季节性备货 | 中 | 依赖采购订单 |
| 备选供应商管理:每品类至少1家备选 | 低 | 依赖供应商主数据 |
#### 6.2.4 中央厨房MES(当前 40% → 目标 75%
| 任务 | 优先级 | 依赖 |
|:---|:---|:---|
| 生产排程算法:基于门店销量预测 + 配方BOM自动计算排产计划 | 高 | 依赖销量预测 |
| 工艺监控:关键参数自动记录(温度/时间/重量) | 中 | 依赖IoT |
| 出品管理:批次管理 + 出品抽检 + 盲测记录 | 中 | 无 |
| 食安留样管理:留样记录 + 检测报告 + 第三方检测 | 中 | 无 |
| 产能规划:淡旺季弹性 + 预留扩产空间 + 外包备选 | 低 | 依赖历史产能数据 |
#### 6.2.5 区域管理驾驶舱(当前 40% → 目标 80%)
| 任务 | 优先级 | 依赖 |
|:---|:---|:---|
| 门店自动分级:按营收达成+巡检得分+客诉率自动A/B/C/D分级 | 高 | 依赖 `situational-awareness.ts` 评分 |
| 红黄绿灯自动标色:实时指标监控 → 自动标色 → 推送 | 高 | 依赖预警引擎 |
| 辅导任务派发:C/D级门店自动生成辅导任务 → 指派区域经理 | 中 | 依赖任务系统 |
| 人才梯队表:店长储备 + 晋升通过率 + 储备池健康度 | 中 | 依赖HR系统 |
| 资源调配:区域营销预算 + 人员跨店调动 + 应急采购审批 | 中 | 依赖审批流 |
#### 6.2.6 门店运营终端(当前 55% → 目标 85%)
| 任务 | 优先级 | 依赖 |
|:---|:---|:---|
| 日目标卡自动生成:每日 09:00 推送日目标(营收/客单/套餐/损耗/到货) | 高 | 依赖目标系统 |
| 实时看板 5 分钟刷新:当日营收进度/来客数/客单价/等位数/出餐时效 | 高 | 依赖实时数据 |
| 日报自动生成:闭店后自动生成日报(达成率/偏差/次日建议) | 高 | 依赖定时调度 |
| 扫码确认:出品扫码/验收扫码/巡检扫码 → 数据自动回传 | 中 | 依赖扫码硬件 |
| 异常上报:门店一键上报异常 → 自动推送区域经理 | 中 | 依赖推送引擎 |
#### 6.2.7 HR系统(当前 20% → 目标 60%)
| 任务 | 优先级 | 依赖 |
|:---|:---|:---|
| 考勤管理:打卡记录 + 工时统计 + 排班匹配 | 高 | 依赖 `attendance_records` |
| 薪酬管理:基本工资 + 绩效奖金 + 调薪审批 | 中 | 依赖 `salary_detail_records` |
| 人才九宫格:绩效 × 潜力 → 自动推荐晋升名单 | 中 | 依赖 `EmployeePerformancePage` |
| 离职预警:月度聚合离职率 → 红灯 → 推送 | 中 | 依赖预警引擎 |
| 招聘管理:岗位需求 + 候选人 + 面试流程 | 低 | 独立模块 |
#### 6.2.8 培训LMS(当前 0% → 目标 50%)
| 任务 | 优先级 | 依赖 |
|:---|:---|:---|
| 新建 `training_course` 表:课程管理 + 课件 + 考试 | 中 | 无 |
| 学习追踪:员工学习进度 + 完成率 + 考试成绩 | 中 | 依赖课程管理 |
| SOP更新自动转培训:新SOP → 自动生成培训课件 → 推送 | 低 | 依赖SOP管理 |
| 培训锁定机制:未完成培训 → 锁定排班权限 | 低 | 依赖排班系统 |
#### 6.2.9 营销MA(当前 30% → 目标 65%)
| 任务 | 优先级 | 依赖 |
|:---|:---|:---|
| 活动管理:活动创建 + 预算分配 + 投放指令 + ROI追踪 | 中 | 无 |
| 券码发放:券码生成 + 核销追踪 + 防刷机制 | 中 | 依赖活动管理 |
| 会员运营:分层运营 + 召回策略 + 生命周期管理 | 中 | 依赖 `MemberPage` 扩展 |
| 营销自动化:触发条件 → 自动执行(如:沉睡会员自动发券) | 低 | 依赖活动管理 |
#### 6.2.10 财务ERP(当前 40% → 目标 70%
| 任务 | 优先级 | 依赖 |
|:---|:---|:---|
| 预算管理:年度预算 + 月度预算 + 执行率追踪 | 中 | 依赖目标系统 |
| 成本核算:按门店/品类/菜品的多维度成本分析 | 中 | 依赖 `cost-analysis.ts` 扩展 |
| 资金管控:现金流 + 账期管理 + 资金计划 | 低 | 依赖银行对接 |
| 财务报表:损益表 + 现金流量表 + 资产负债表 | 低 | 依赖全部业务数据 |
---
## 七、关键系统接口实现路径
### 7.1 接口对照
| 接口方向 | V3.0要求 | 系统现状 | 状态 |
|:---|:---|:---|:---|
| POS → 数据中台 | 销售流水实时上传 | 手工导入 `bill_records`;无实时API | **未实现** |
| 外卖平台 → 数据中台 | 外卖订单/评价/退款实时同步 | `bill_records` 有外卖字段(c150-c152);手工导入 | **未实现** |
| IoT温控 → 数据中台 | 温度/湿度/设备状态每5分钟 | 无IoT对接 | **未实现** |
| 扫码枪 → 数据中台 | 出品/验收/盘点扫码 | 无扫码对接 | **未实现** |
| 人脸识别 → HR系统 | 考勤/排班匹配/工时统计 | `attendance_records` 手工导入 | **未实现** |
| 数据中台 → 区域管理 | 门店聚合数据/排名/预警/分级 | `situational-awareness.ts` 提供健康度;`data.ts` 提供聚合数据 | **已实现** |
| 数据中台 → 战略驾驶舱 | 集团聚合/趋势/对标/预测 | `data.ts` `/overview` 提供集团汇总;无趋势预测 | **部分实现** |
| 产品PLM → 中央厨房MES | 配方SOP/上市计划/工艺参数 | 无PLM系统 | **未实现** |
| 中央厨房MES → WMS | 生产计划/成品入库/配送需求 | `ProductionPlanPage` 有生产要货;无自动对接 | **部分实现** |
| WMS → TMS | 配送订单/分拣清单/温度要求 | 无WMS/TMS | **未实现** |
| TMS → 门店验收APP | 配送轨迹/预计到达/温度记录 | `DistributionReconciliationPage` 有对账;无实时轨迹 | **部分实现** |
| 门店验收APP → 供应链SRM | 验收结果/退货记录/质量评分 | 无验收APP | **未实现** |
| 营销MA → 门店POS | 活动方案/券码/推荐位配置 | 无营销自动化 | **未实现** |
| HR系统 → 培训LMS | 员工档案/岗位/技能等级/培训需求 | 无LMS | **未实现** |
| 培训LMS → 门店终端 | 培训课程/考试任务/技能认证 | 无LMS | **未实现** |
| 财务ERP ↔ 全部模块 | 预算/成本/利润/资金 | `cost-analysis.ts` + `store-expense.ts` 提供成本费用分析 | **部分实现** |
### 7.2 接口实现路径
| 阶段 | 接口 | 优先级 | 协议 |
|:---|:---|:---|:---|
| **P1** | POS → 数据中台(实时销售流水) | 高 | REST API |
| **P1** | 外卖平台 → 数据中台(订单/评价/退款) | 高 | REST API |
| **P2** | 数据中台 → 消息推送引擎(预警/任务/报告) | 中 | WebSocket |
| **P2** | 产品PLM → 中央厨房MES(配方SOP | 中 | 内部API |
| **P2** | 中央厨房MES → WMS(生产计划/配送需求) | 中 | 内部API |
| **P3** | IoT温控 → 数据中台(温度/湿度/设备状态) | 低 | MQTT |
| **P3** | 扫码枪 → 数据中台(出品/验收/盘点) | 低 | 蓝牙/WiFi |
| **P3** | 人脸识别 → HR系统(考勤/工时) | 低 | API |
| **P3** | TMS → 门店验收APP(配送轨迹/温度) | 低 | 内部API |
---
## 八、分阶段实施路线图
### Phase 1:基础闭环(3-6个月)
**目标**:建立目标管理 + 定时调度 + 预警引擎 + 数据自动采集
| 序号 | 任务 | 模块 | 工作量 |
|:---|:---|:---|:---|
| 1 | 新建目标管理表族 + 目标拆解算法 | 目标闭环 | 大 |
| 2 | 引入 node-cron 定时调度器 + 每日日报/目标卡自动生成 | 时间驱动 | 中 |
| 3 | 建立预警规则引擎 `alert_rules` + 红/黄灯自动推送 | 事件驱动 | 大 |
| 4 | POS 数据实时导入管道(API对接或定时ETL) | 数据采集 | 大 |
| 5 | 门店自动分级(A/B/C/D)+ 红黄绿灯自动标色 | 区域管理 | 中 |
| 6 | 产品生命周期表 + 顾客评价NLP归因 | 业务闭环 | 大 |
| 7 | 扩展角色体系(供应链/产品/营销/HR职能角色) | 权限隔离 | 中 |
| 8 | 数据清洗规则引擎 | 数据闭环 | 中 |
| 9 | 看板嵌入"一键下达任务"按钮 | 数据闭环 | 小 |
| 10 | 自动复盘报告生成(月度经营分析报告) | 迭代闭环 | 中 |
### Phase 2:协同扩展(6-12个月)
**目标**:建立协同闭环 + 审批流 + LMS + 营销自动化
| 序号 | 任务 | 模块 | 工作量 |
|:---|:---|:---|:---|
| 1 | 供应商主数据 + 评分卡 + 采购订单管理 | 供应链SRM | 大 |
| 2 | 生产排程算法(销量预测 + BOM计算) | 中央厨房MES | 大 |
| 3 | 通用审批流引擎 + 各场景接入 | 审批流 | 大 |
| 4 | 人才九宫格 + 晋升推荐 + 离职预警 | HR系统 | 中 |
| 5 | 培训LMS(课程管理 + 学习追踪 + 考试认证) | 培训LMS | 大 |
| 6 | 营销活动管理 + 券码发放 + ROI追踪 | 营销MA | 大 |
| 7 | 消息推送引擎(WebSocket + 站内消息中心) | 基础设施 | 中 |
| 8 | 扫码确认闭环(出品/验收/巡检) | 执行流 | 中 |
| 9 | 纠偏任务自动入池 + 闭环自动验证 | 执行流 | 中 |
| 10 | 预算管理 + 财务报表 | 财务ERP | 大 |
| 11 | 系统级数据脱敏 + 审计日志 | 权限隔离 | 中 |
| 12 | 案例库NLP标签 + 变更管理流程 | 迭代闭环 | 中 |
### Phase 3:智能升级(12-24个月)
**目标**:IoT接入 + AI辅助决策 + 全链路自动流转
| 序号 | 任务 | 模块 | 工作量 |
|:---|:---|:---|:---|
| 1 | IoT温控探针对接(MQTT + 冷链温度实时监控) | 数据采集 | 大 |
| 2 | 扫码枪/电子秤硬件对接 | 数据采集 | 大 |
| 3 | 人脸识别考勤对接 | 数据采集 | 中 |
| 4 | AI辅助目标测算(多因子模型:天气/节假日/商圈活动) | 决策流 | 大 |
| 5 | 产销协同全链路自动流转 | 协同闭环 | 大 |
| 6 | 营采协同全链路(营销 → 物料 → 备货 → 执行 → ROI) | 协同闭环 | 大 |
| 7 | 实时数据流(T+0看板 + WebSocket推送) | 数据闭环 | 大 |
| 8 | 培训锁定机制(未完成培训 → 锁定排班) | 迭代闭环 | 中 |
| 9 | 资金管控 + 银行对接 | 财务ERP | 大 |
| 10 | 季度战略复盘数据包自动生成 + 投资建议AI测算 | 战略驾驶舱 | 大 |
---
## 九、现有系统资产清单
### 9.1 前端页面(36个)
| 页面 | 路由 | 角色权限 | 对应V3.0模块 |
|:---|:---|:---|:---|
| `BossPage` | `/boss` | hq, dept | 战略驾驶舱 |
| `DashboardPage` | `/` | hq, dept | 决策层看板 |
| `SituationalAwarenessPage` | `/situational-awareness` | hq, dept, regional, store | 区域管理 + 门店终端 |
| `BankPage` | `/bank` | hq | 战略驾驶舱(银行授信) |
| `RegionalPage` | `/regional` | hq, dept, regional | 区域管理驾驶舱 |
| `RegionComparisonPage` | `/region-comparison` | hq, dept, regional | 区域管理 |
| `StorePage` | `/store` | hq, dept, store | 门店运营终端 |
| `StoreDetailPage` | `/stores/:code` | hq, regional, store, dept | 门店详情 |
| `TasksPage` | `/tasks` | hq, regional, store, dept | 任务管理 |
| `TaskDetailPage` | `/tasks/:id` | hq, regional, store, dept | 任务详情 |
| `MonthlyReviewPage` | `/monthly-review` | hq, dept, regional | 月度验收 |
| `SKUPage` | `/sku` | hq, dept | 产品PLM |
| `MenuEngineeringPage` | `/menu-engineering` | hq, dept | 产品PLM |
| `CostPage` | `/cost` | hq, dept | 财务ERP |
| `CostAnalysisPage` | `/cost-analysis` | hq, dept | 财务ERP |
| `StoreExpensePage` | `/store-expense` | hq, dept | 财务ERP |
| `PlatformPage` | `/platform` | hq, dept | 营销MA |
| `MemberPage` | `/member` | hq, dept | 营销MA |
| `MemberLTVPage` | `/member-ltv` | hq, dept | 营销MA |
| `RiskPage` | `/risk` | hq, dept | 风险内控 |
| `TimePage` | `/time` | hq, dept | 运营分析 |
| `DataQualityPage` | `/data-quality` | hq, dept | 数据闭环 |
| `OntologyPage` | `/ontology` | hq, dept | 系统管理 |
| `SiteSelectionPage` | `/site-selection` | hq, dept | 战略驾驶舱 |
| `SmartSchedulingPage` | `/smart-scheduling` | hq, dept, regional, store | HR系统 |
| `EmployeePerformancePage` | `/employee-performance` | hq, dept | HR系统 |
| `InventoryTurnoverPage` | `/inventory-turnover` | hq, dept | WMS仓储 |
| `CentralKitchenPage` | `/central-kitchen` | hq, dept | 中央厨房MES |
| `DistributionReconciliationPage` | `/distribution-reconciliation` | hq, dept | TMS物流 |
| `BomPenetrationPage` | `/bom-penetration` | hq, dept | 中央厨房MES |
| `ProductionPlanPage` | `/production-plan` | hq, dept | 中央厨房MES |
| `RevenuePage` | `/revenue` | hq, dept | 决策层看板 |
| `IndicatorsPage` | `/indicators` | hq, dept, regional, store | 系统管理 |
| `TenantManagementPage` | `/tenant-management` | platform_admin | 平台管理 |
| `TenantUsersPage` | `/tenant-users` | hq | 系统管理 |
| `LoginPage` | `/login` | 公开 | 认证 |
### 9.2 后端路由(10个)
| 路由文件 | 路由前缀 | 功能 | 对应V3.0模块 |
|:---|:---|:---|:---|
| `auth.ts` | `/api/auth` | 登录认证 | 基础设施 |
| `admin.ts` | `/api/admin` | 租户管理 + 用户管理 | 平台管理 |
| `data.ts` | `/api` | 通用数据查询(概览/门店/区域/SKU/成本/平台/会员/风险/时间/指标/本体) | 全模块 |
| `tasks.ts` | `/api/tasks` | 任务CRUD + 状态流转 + 周检查 + 月验收 | 任务管理 |
| `cost-analysis.ts` | `/api/cost-analysis` | 菜品成本分析(总览/品类/偏差/趋势/明细) | 财务ERP |
| `store-expense.ts` | `/api/store-expense` | 门店费用分析(总览/趋势/对比/明细) | 财务ERP |
| `smart-scheduling.ts` | `/api/smart-scheduling` | 智能排班(客流热力图/餐段/在岗人员/排班建议) | HR系统 |
| `situational-awareness.ts` | `/api/situational-awareness` | 态势感知(健康度评分/红黄绿灯/预警) | 区域管理 |
| `analytics-enhanced.ts` | `/api/analytics-enhanced` | 增强分析(会员LTV/菜单工程/员工绩效/库存周转/区域对比) | 全模块 |
| `tts.ts` | `/api/tts` | TTS语音播报(千问CosyVoice | 基础设施 |
### 9.3 数据库表(11个SQL文件)
| SQL文件 | 内容 | 对应V3.0模块 |
|:---|:---|:---|
| `01_create_tables.sql` | 门店任务/日志/模板/指标字典/门店主数据/经验标准化/推广试点/升降级/周检查/月验收/数据刷新日志 | 任务管理 + 迭代闭环 |
| `02_create_functions.sql` | SQL函数(任务生成/周检查/月验收等) | 任务管理 |
| `03_create_views.sql` | 周检查视图/月度验收视图/闭环健康度视图/数据质量视图 | 任务管理 + 数据闭环 |
| `04_init_data.sql` | 初始化数据(指标字典/任务模板) | 系统管理 |
| `05-06_backfill_task_values.sql` | 批量回填任务值 | 任务管理 |
| `07-08_simulate_monthly_review.sql` | 模拟月度验收 + 验收修复 | 月度验收 |
| `09_add_indexes.sql` | 性能索引 | 基础设施 |
| `10_materialize_slow_views.sql` | 慢视图物化(门店详情页性能优化) | 基础设施 |
| `11_tenant_management.sql` | 多租户管理(租户配置/用户/平台管理员) | 平台管理 |
### 9.4 中间件(4个)
| 中间件 | 功能 | 对应V3.0模块 |
|:---|:---|:---|
| `auth.ts` | JWT认证 + 角色守卫 + 门店访问控制 | 权限隔离 |
| `tenant-db.ts` | 多租户动态连接池切换 | 权限隔离 |
| `data-scope.ts` | 数据范围过滤(hq无限制/regional按区域/store按门店) | 权限隔离 |
| `error.ts` | 统一响应壳 + 错误处理 + 分页/月份解析 | 基础设施 |
### 9.5 共享类型
| 类型 | 用途 |
|:---|:---|
| `UserRole` | 角色枚举(hq/regional/store/dept |
| `AuthUser` | 认证用户信息 |
| `ApiResponse<T>` | 统一API响应壳 |
| `StoreScorecard` | 门店记分卡 |
| `StoreRiskRating` | 门店风险评级(红/黄/绿) |
| `StorePriority` | 门店优先级 |
| `StoreTask` | 门店整改任务 |
| `WeeklyCheck` | 周度检查记录 |
| `MonthlyReview` | 月度验收记录 |
| `LoopHealth` | 闭环健康度 |
| `IndicatorDict` | 指标字典 |
| `StandardizedPractice` | 经验标准化 |
| `PracticeReplication` | 经验推广试点 |
---
## 十、总结
### 整体实现度评估
| V3.0模块 | 当前实现度 | Phase 1 后 | Phase 2 后 | Phase 3 后 |
|:---|:---|:---|:---|:---|
| 战略驾驶舱 | 30% | 45% | 60% | 85% |
| 产品PLM | 25% | 50% | 60% | 75% |
| 供应链SRM | 15% | 30% | 60% | 75% |
| 中央厨房MES | 40% | 55% | 75% | 85% |
| WMS仓储 | 15% | 25% | 50% | 70% |
| TMS物流 | 15% | 25% | 45% | 65% |
| 门店POS | 20% | 50% | 60% | 80% |
| 区域管理 | 40% | 70% | 80% | 90% |
| 门店终端 | 55% | 75% | 85% | 90% |
| HR系统 | 20% | 35% | 60% | 75% |
| 培训LMS | 0% | 10% | 50% | 70% |
| 营销MA | 30% | 40% | 65% | 80% |
| 财务ERP | 40% | 50% | 70% | 85% |
| 数据采集层 | 10% | 40% | 50% | 80% |
| 任务管理 | 65% | 80% | 90% | 95% |
| 态势感知 | 50% | 75% | 85% | 90% |
| 权限隔离 | 50% | 70% | 85% | 90% |
| **整体平均** | **29%** | **49%** | **67%** | **82%** |
### 关键差距总结
1. **目标管理系统完全缺失**:V3.0核心是"目标自动拆解",当前系统无目标管理表族和拆解算法
2. **定时调度引擎缺失**V3.0要求"时间驱动 + 事件驱动"双引擎,当前系统无 cron 调度器
3. **消息推送引擎缺失**:V3.0要求"自动推送至对应责任人",当前系统无 WebSocket/推送机制
4. **实时数据采集缺失**V3.0要求"POS/IoT/扫码枪实时上云",当前系统依赖手工导入
5. **审批流系统缺失**:V3.0要求7类审批流,当前系统无审批流引擎
6. **LMS培训系统缺失**V3.0要求"培训下发 + 学习追踪 + 考试认证",当前系统无LMS
7. **职能角色体系缺失**:V3.0要求6类职能角色(供应链/产品/营销/HR/店长/员工),当前系统仅有4类层级角色
### 优先建议
**立即启动 Phase 1 的前5项任务**,这些是V3.0闭环体系的基石:
1. 目标管理表族 + 拆解算法 → 让系统"有目标可追踪"
2. 定时调度器 + 日报/目标卡自动生成 → 让系统"按节奏自运转"
3. 预警规则引擎 + 自动推送 → 让系统"自动发现问题"
4. POS数据实时导入 → 让系统"有实时数据可用"
5. 门店自动分级 + 红黄绿灯 → 让系统"自动区分优先级"
---
> **文档结语**:当前系统已实现了V3.0五层架构中的数据聚合层、分析呈现层、任务管理层和权限隔离层,整体实现度约29%。核心差距在于"五个自动化"(目标自动拆解、数据自动采集、偏差自动预警、任务自动派发、结果自动验证)尚未建立。通过三阶段实施路线图,可在24个月内将整体实现度提升至82%,基本完成V3.0系统闭环体系的落地。
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+332
View File
@@ -0,0 +1,332 @@
# 玄谋智脑:让数据产生决策力
> **品牌名称**:玄谋智脑
>
> **品牌定位**:面向企业经营与管理决策的行业数字本体与 AI 智脑。
>
> **一句话定位**:整合散落在现有系统和 Excel 中的数据,将行业知识、企业数据与管理经验沉淀为能自动发现问题、驱动执行、预测未来的决策能力。
>
> **编制日期**2026-08-09
---
## 一、为什么需要企业智脑
企业普遍面临四个断裂:
| 断裂 | 表现 | 后果 |
|:---|:---|:---|
| **数据断裂** | 多系统、多格式、多标准,数据无法互通 | 有数据、无资产 |
| **分析断裂** | 报表很多,但不知道看什么、怎么分析、分析完怎么办 | 有报表、无洞察 |
| **执行断裂** | 战略目标制定后,无法穿透到一线行动 | 有目标、无落地 |
| **知识断裂** | 最佳实践留在个人脑中,组织能力无法积累 | 有经验、无沉淀 |
**玄谋智脑的本质**:用 AI 把这四个断裂接上,让数据从"被动查看"变成"主动驱动"。
---
## 二、五层架构总览
```
第一层 数据资产化(地基) —— 让数据"通起来"
第二层 运营指标化(骨架) —— 让问题"浮出来"
第三层 战略穿透化(神经) —— 让目标"落下去"
第四层 态势感知化(感官) —— 让风险"早知道"
第五层 知识沉淀化(进化) —— 让组织"越来越聪明"
↑ |
└──────── 反馈闭环:越用越准 ────────────┘
```
**核心设计原则**
- 下层为上层提供输入,上层为下层提供方向
- 每层内部有闭环,层间也有反馈闭环
- AI 贯穿全栈,基于行业最佳实践自动构建和优化
---
## 三、第一层:数据资产化 —— 让数据"通起来"
### 要解决的问题
数据散落在 ERP、POS、WMS、HR、财务系统和大量 Excel 中,格式不一、标准不同、无法关联。
### 怎么做
1. **构建本体论语义模型**:AI 基于行业最佳实践,定义企业的实体(门店/商品/会员/供应商/员工)、属性、关系,形成统一"数据语言"
2. **自动接入异构数据源**:AI 自动识别各系统数据结构,映射到本体模型,无需人工逐表对接
3. **自动清洗与质检**:异常金额、缺失字段、时间错乱、温度异常等自动标记和修复
4. **输出标准化数据资产**:所有数据可关联、可追溯、可复用
### 老板能看到什么
| 建设前 | 建设后 |
|:---|:---|
| 想看个数据,找IT排期3天 | 随时可用,数据准备从天级降至分钟级 |
| 各系统数据对不上 | 统一口径,一个数字、一个来源 |
| Excel满天飞 | 数据都在"资产库"里,版本唯一 |
---
## 四、第二层:运营指标化 —— 让问题"浮出来"
### 要解决的问题
数据有了,但不知道该看什么指标、指标异常该怎么分析、分析完该怎么处理。
### 怎么做
1. **自动构建分层指标体系**
- 战略层:营收、利润、门店数、会员数
- 运营层:客单价、客流、成本率、损耗率、达成率
- 执行层:日营收、时段营收、出品时效、排班合规
2. **自动建立分析模型**:对标分析、归因分析、趋势分析、结构分析
3. **形成六步闭环**
```
数据 → 分析 → 发现问题 → 生成方案 → 执行落地 → 检验效果
↑ |
└──────────── 效果不达标,自动回到分析 ────────────────────┘
```
4. **每个指标绑定**:责任人 + 阈值 + 纠偏动作,异常自动预警并推送
### 老板能看到什么
| 建设前 | 建设后 |
|:---|:---|
| 月底才知道目标没达成 | 每天自动推送达成率,偏差实时可见 |
| 数据异常靠人去发现 | 系统自动发现问题并推送给责任人 |
| 发现问题后不知道怎么办 | 系统自动归因 + 推荐解决方案 |
---
## 五、第三层:战略穿透化 —— 让目标"落下去"
### 要解决的问题
战略目标制定后停在PPT里,无法穿透到区域、门店、个人,目标与日常行动脱节。
### 怎么做
**四步穿透闭环**
| 步骤 | 做什么 | AI 的角色 |
|:---|:---|:---|
| **战略制定** | 确定年度营收/利润/门店/会员目标 | 多因子测算(市场/竞争/资源/历史趋势),生成战略草案 |
| **分解落地** | 年度→区域→门店→个人,逐级拆解 | 差异化分配:A店110%、B店100%、C店90%、D店整改 |
| **执行反馈** | 日目标卡 + 时段达成率 + 偏差归因 | 每日自动生成目标卡,实时追踪执行进度 |
| **战略优化** | 月度/季度复盘,评估战略有效性 | 自动生成复盘报告,AI 评估并建议调整方向 |
### 老板能看到什么
| 建设前 | 建设后 |
|:---|:---|
| 年度目标定了就忘 | 目标逐级拆解到每个人、每一天 |
| 不知道门店执行得怎样 | 实时达成率,偏差自动归因 |
| 战略调整靠感觉 | 季度复盘数据包 + AI调整建议 |
---
## 六、第四层:态势感知化 —— 让风险"早知道"
### 要解决的问题
管理者永远在"追问题"而不是"防问题",等发现时已经造成损失。
### 怎么做
1. **实时态势感知**:全维度指标监控仪表盘,红黄绿灯自动标色,一眼看清全局健康度
2. **趋势预测**:基于历史数据,AI 预测营收/客流/库存/离职率趋势,提前预判拐点
3. **风险预警**:规则引擎 + AI 异常检测,指标偏离阈值自动预警并推送责任人
4. **情景推演**:AI 模拟不同决策的预期效果(如:涨价5%对客流和利润的影响)
### 预警示例
| 预警类型 | 触发条件 | 自动动作 |
|:---|:---|:---|
| 营收达成率 | 日达成率 < 80% | 红灯预警 → 推送店长 + 区域经理 |
| 临期品 | 临期比例 > 10% | 预警 → 推送促销建议 |
| 离职率 | 月离职率 > 15% | 红灯 → 推送HR + 总经理 |
| 差评归因 | 外卖差评出现 | NLP自动分类 → 推送整改任务 |
| 连续未达成 | 3个月未达标 | 自动触发D级预警 → 推送决策层 |
### 老板能看到什么
| 建设前 | 建设后 |
|:---|:---|
| 出了问题才知道 | 风险提前预警,把问题消灭在萌芽 |
| 看数据但不清楚趋势 | AI预测趋势,提前预判拐点 |
| 决策靠拍脑袋 | 情景推演,决策前先看预期效果 |
---
## 七、第五层:知识沉淀化 —— 让组织"越来越聪明"
### 要解决的问题
最佳实践留在优秀店长脑中,换人就退化;同样的错误反复犯;组织能力无法积累。
### 怎么做
1. **自动沉淀**:每次闭环执行的过程和结果自动记录为案例
2. **模式提取**:AI 自动从成功/失败案例中提取关键模式
3. **知识更新**:最佳实践自动转化为 SOP、培训课件、预警规则
4. **持续进化**:系统在使用中持续学习,越用越精准
### 知识转化路径
```
执行结果 → AI提取模式 → 更新最佳实践库 → 自动转化为SOP/课件/预警规则 → 指导下一次执行
```
### 老板能看到什么
| 建设前 | 建设后 |
|:---|:---|
| 优秀店长走了,业绩就掉 | 最佳实践沉淀在系统里,不依赖个人 |
| 同样的错误反复犯 | 预警规则自动拦截,历史教训自动复用 |
| 培训内容过时 | SOP变更自动生成课件,推送到相关员工 |
---
## 八、建设路径建议
### 分三步走
| 阶段 | 时间 | 目标 | 核心建设 |
|:---|:---|:---|:---|
| **第一步:打地基** | 第1-2周 | 数据通起来、指标建起来 | 数据资产化 + 指标体系 + 预警引擎 |
| **第二步:接神经** | 第3-5周 | 目标落下去、问题浮出来 | 目标穿透 + 六步闭环 + 态势感知 |
| **第三步:长大脑** | 第6-8周 | 系统自己学、越用越准 | 知识沉淀 + AI预测 + 情景推演 |
### 投入产出预期
| 阶段 | 投入重点 | 可量化收益 |
|:---|:---|:---|
| 第一步 | 数据治理 + 系统建设 | 经营数据T+1自动入库,损益核算周期从月级缩短到日级 |
| 第二步 | 流程重构 + 习惯培养 | 目标达成率提升10-15%,毛利率提升2-3%,运营成本降低5-8% |
| 第三步 | AI模型 + 持续优化 | 库存周转天数减少3-5天,人效提升10-15%,决策响应速度提升3倍 |
---
## 九、与普通BI系统的区别
| 维度 | 普通BI | 企业智脑 |
|:---|:---|:---|
| **定位** | 看数据的工具 | 驱动决策的大脑 |
| **数据** | 人工整理、手工导入 | 自动采集、自动清洗、本体论建模 |
| **指标** | 固定报表 | AI构建分层体系,自动关联责任人 |
| **发现问题** | 人去看数据 | 系统自动发现并推送 |
| **解决问题** | 只报告不行动 | 自动生成方案、追踪执行、检验效果 |
| **知识** | 用完即弃 | 自动沉淀、持续学习、越用越准 |
| **战略** | 提供数据参考 | 目标穿透到个人,执行实时反馈 |
| **预测** | 看历史 | 预测未来、推演决策 |
---
## 十、交付成果
### 系统交付物
| 交付物 | 说明 | 交付阶段 |
|:---|:---|:---|
| **统一数据资产平台** | 异构系统数据自动采集、清洗、标准化入库,一套数据、一个口径 | 第一步 |
| **分层指标看板** | 战略层→运营层→执行层三级指标体系,自动计算、实时更新 | 第一步 |
| **预警规则引擎** | 指标偏离自动预警,推送责任人,生成纠偏任务 | 第一步 |
| **目标穿透系统** | 年度目标→区域→团队→个人逐级拆解,日目标卡自动生成 | 第二步 |
| **六步闭环引擎** | 数据→分析→问题→方案→执行→检验,自动流转、全程留痕 | 第二步 |
| **态势感知看板** | 全维度红黄绿灯监控 + 趋势预测 + 情景推演 | 第二步 |
| **知识沉淀平台** | 最佳实践自动提取、SOP自动更新、培训课件自动生成 | 第三步 |
| **AI决策辅助** | 趋势预测、情景推演、智能建议,越用越准 | 第三步 |
### 管理交付物
| 交付物 | 说明 | 交付阶段 |
|:---|:---|:---|
| **数据资产目录** | 企业全部数据资产的统一目录,可检索、可追溯 | 第一步 |
| **指标词典** | 每个指标的定义、口径、责任人、阈值,全公司统一语言 | 第一步 |
| **目标责任矩阵** | 每个目标落实到具体责任人,达成率实时可见 | 第二步 |
| **经营复盘报告** | 日/周/月自动生成,含达成率、偏差归因、改进建议 | 第二步 |
| **最佳实践库** | 沉淀组织经验,不依赖个人,新人快速上手 | 第三步 |
---
## 十一、案例:某餐饮连锁企业的智脑实践
> 以下案例基于真实系统建设实践,数据已脱敏处理。
### 企业背景
某餐饮连锁企业,旗下约 **90 家直营门店**,覆盖 **5 个区域**,拥有中央厨房和配送体系。原有 IT 系统 includes POS、外卖平台、WMS 库存、HR 考勤、财务系统,数据散落在各系统和大量 Excel 中,管理层"看数据靠排期、做决策靠经验"。
### 五层落地实例
#### 第一层:数据资产化
| 建设前 | 建设后 |
|:---|:---|
| POS、外卖、库存、HR、财务各管各的,数据对不上 | 统一数据采集管道,POS 数据 T+1 自动入库,外卖平台数据自动同步 |
| 每月做报表要 3 个人花 2 天整理 Excel | 系统自动聚合,报表一键生成 |
| 数据口径不统一,开会先吵数字 | 本体标准模块定义统一实体和口径,一个数字、一个来源 |
**系统模块**:数据采集管道 + 数据质量监控 + 本体标准管理
---
#### 第二层:运营指标化
| 建设前 | 建设后 |
|:---|:---|:---|
| 报表几十张,不知道该看哪张 | 三级指标体系自动计算:战略层(营收/利润/门店数)→ 运营层(客单/客流/成本率)→ 执行层(日营收/时段营收) |
| 指标异常靠人去翻数据 | 预警引擎自动扫描,达成率低于阈值自动红灯预警并推送责任人 |
| 发现问题后不知道原因 | 自动归因分析:营收下降→拆解客流/客单/品类/时段,定位根因 |
**系统模块**:指标词典 + 营收分析 + 菜品成本 + 会员复购 + SKU分析 + 预警管理
**实际场景**:某门店连续 3 天营收达成率低于 80%,系统自动红灯预警 → 推送店长和区域经理 → 自动归因发现客流下降 15% → 生成纠偏任务 → 店长执行引流措施 → 3 天后达成率恢复至 95% → 系统自动判定闭环完成。
---
#### 第三层:战略穿透化
| 建设前 | 建设后 |
|:---|:---|:---|
| 年度目标定完就放进文件柜 | 目标管理系统:年度目标 → 5 个区域 → 90 家门店 → 个人,逐级自动拆解 |
| 所有门店一个标准 | 差异化分配:A 级店 110%、B 级店 100%、C 级店 90%、D 级店整改 |
| 不知道目标执行到什么程度 | 店长每日 09:00 收到日目标卡(营收/成本/损耗),实时查看达成率 |
| 月底才知道没达标 | 每日/每周自动推送达成进度,偏差实时可见 |
**系统模块**:目标管理 + 门店分级 + 月度验收 + 调度管理
**实际场景**:年度营收目标 3.6 亿 → 自动拆解到 5 个区域 → 按门店 A/B/C/D 分级差异化分配到 90 家店 → 每店每月目标自动拆解到每日 → 店长每天看到目标卡 → 月末自动生成偏差报告 + 归因分析。
---
#### 第四层:态势感知化
| 建设前 | 建设后 |
|:---|:---|:---|
| 老板要看全局,得等一周出报告 | 态势感知看板实时展示 90 家店健康度,红黄绿灯一目了然 |
| 问题都是事后发现 | 预警规则引擎每小时扫描,指标偏离自动预警 |
| 决策靠拍脑袋 | 趋势预测 + 情景推演,决策前先看预期效果 |
**系统模块**:态势感知 + 预警管理 + 风险内控 + 智能排班
**实际场景**:态势感知看板显示 90 家店综合健康度评分,其中 3 家红灯、7 家黄灯 → 点击红灯门店查看详情 → 发现某店食材损耗率超标 → 一键下达整改任务 → 任务自动填充门店/指标/偏差值/建议措施/截止日期 → 推送店长执行。
---
#### 第五层:知识沉淀化
| 建设前 | 建设后 |
|:---|:---|:---|
| 优秀店长走了,业绩就掉 | 最佳实践自动沉淀为案例库,新店长可检索学习 |
| 同样的错误反复犯 | 预警规则自动拦截,历史教训自动复用 |
| 培训内容过时 | SOP 变更自动生成培训课件,推送到相关员工 |
**系统模块**:产品生命周期 + 企业协同 + 智能升级
**实际场景**:某 A 级门店的会员复购率显著高于同区 → 系统自动提取其关键动作(会员日设置/话术/优惠策略)→ 沉淀为最佳实践 → 自动推荐给同区域 C 级门店 → C 级店执行后复购率提升 12% → 闭环验证通过,案例入库。
---
### 建设效果
| 指标 | 建设前 | 建设后 |
|:---|:---|:---|
| 数据准备周期 | 3-5 天 | T+1 自动入库 |
| 问题发现周期 | 月级(月底报表) | 日级(实时预警) |
| 目标达成率 | 约 85% | 95%+ |
| 门店毛利率 | 基准 | 提升 2-3% |
| 库存周转天数 | 基准 | 减少 3-5 天 |
| 管理决策响应 | 3-5 天 | 当天 |
---
> **总结**:玄谋智脑不是新建一套孤立的 IT 系统,而是基于企业现有数据的管理升级。它让数据从"被动查看"变成"主动驱动",让管理从"事后救火"变成"事前预防",让组织能力从"依赖个人"变成"沉淀系统"。**最终目标:让每一个团队、每一个员工,每天都在做正确的事。**
@@ -0,0 +1,233 @@
# 原始数据导入处理
## 一、数据源概览
| 数据域 | 原始表 | 导入方式 | 文件格式 | 频率 |
|--------|--------|----------|----------|------|
| 账单数据 | `bill_records` | Python脚本导入 | Excel (.xlsx) | 月度 |
| 经营费用 | `operating_expense_records` | Python脚本导入 | Excel | 月度 |
| 库存成本 | `inventory_cost_records` | Python脚本导入 | Excel | 月度 |
| 菜品成本分析 | `dish_cost_analysis_summary` | Python脚本导入 | Excel | 月度 |
| 考勤数据 | `attendance_records` | Python脚本导入 | Excel | 月度 |
| 薪资数据 | `salary_detail_records` | Python脚本导入 | Excel | 月度 |
| 门店位置 | `store_location_master` | Python脚本导入 | Excel | 按需 |
| 中央厨房 | `central_kitchen_*` (6表) | Python脚本导入 | Excel | 月度 |
| 配送数据 | `distribution_detail_records` | Python脚本导入 | Excel | 月度 |
| 菜品销售 | `dish_sales_details` | Python脚本导入 | Excel | 月度 |
---
## 二、账单数据导入(bill_records
### 2.1 数据源
- **来源文件**: 正餐事业部_店内订单明细-已结账_*.xlsx
- **来源系统**: 餐饮POS系统导出
- **文件路径**: `数据/4月/``数据/5月/`
### 2.2 导入脚本
| 脚本 | 说明 |
|------|------|
| `/tmp/import_missing_stores.py` | 导入缺失门店账单(MD00002/MD00003/MD00008/1098/1110 |
| `/tmp/import_remaining_stores.py` | 导入剩余门店账单(哈马尔罕总部基地店0056/大钟寺店0022/茂林居店0021/西安含光店0052/西部马华火锅北三环店0012) |
### 2.3 字段映射
`bill_records` 表使用 c001~c199 编码,关键字段:
| 列号 | 字段含义 | 用途 |
|------|----------|------|
| c002 | 门店编码 | 门店标识 |
| c003 | 门店名称 | 门店名称(用于JOIN) |
| c009 | 消费金额 | 营业收入 |
| c068 | 优惠金额 | 优惠分析 |
| c114 | 理论成本额 | 理论毛利率 |
| c175 | 下单时间 | 时段分析 |
| c176 | 结账时间 | 日度汇总 |
| c178 | 就餐人数 | 客流分析 |
| c181 | 会员卡号 | 会员分析 |
| c185 | 会员标识 | 会员识别 |
### 2.4 导入逻辑
1. 读取 Excel 文件,解析支付方式和金额
2. 按门店名称匹配 `store_name_mapping`
3. **删除旧数据**: 按 `c003`(门店名称)和日期范围删除同月旧记录
4. **插入新数据**: 批量 INSERT,自动生成 bill_id
5. 导入后需刷新 `bill_fact` 物化视图
### 2.5 支付方式解析
脚本中定义了支付方式映射,将不同支付渠道(微信/支付宝/现金/会员储值/美团/饿了么等)解析为对应字段。
### 2.6 门店名称映射
| 原始名称 | 门店编码 | 说明 |
|----------|----------|------|
| 哈马尔罕(总部基地店) | 0056 | 新导入 |
| 哈马尔罕(大钟寺店) | 0022 | 新导入 |
| 哈马尔罕(茂林居店) | 0021 | 新导入 |
| 哈马尔罕(西安含光店) | 0052 | 新导入 |
| 西部马华火锅(北三环店) | 0012 | 新导入 |
| 关东店 | 1098 | 编码修正(原错误映射为0033) |
---
## 三、经营费用导入(operating_expense_records
### 3.1 数据源
- **来源文件**: 各门店费用明细Excel
- **费用科目**: 月薪员工工资、餐厅房租、外卖佣金、电费、燃气费、水费、物业费、宿舍费用、刷卡手续费、清洗费、垃圾费、维修费、菜品提成、自送快递费、烟道清洗、设备租赁费、暖气费
### 3.2 导入流程
1. 读取 Excel,按费用科目和门店单位导入
2. 写入 `operating_expense_records` 原始表
3. 通过 `operating_expense_store_mapping` 映射到销售门店编码
4. `include_in_operating_analysis` 标志控制是否纳入经营分析
### 3.3 门店映射规则
- 一个费用单位可映射到一个销售门店编码(`sales_store_code`
- 多个费用单位可映射到同一门店(如"哈马尔罕大钟寺店"→"大钟寺店"0022
- 未映射的费用单位(支持/供应链/特殊业务)不纳入门店评估
- `include_in_operating_analysis = true` 才参与费用分析
### 3.4 导入后处理
- 视图 `v_operating_expense_unit_monthly` 自动反映新数据
- 视图 `v_store_operating_expense_monthly``sales_store_code` 聚合
- 物化表 `mv_store_operating_expense_monthly` 需手动刷新(INSERT/UPDATE
---
## 四、库存成本导入(inventory_cost_records
### 4.1 数据源
- **来源文件**: 库存盘点Excel
- **内容**: 各门店库存消耗金额、原料分类
### 4.2 导入流程
1. 读取 Excel,按门店和原料分类导入
2. 写入 `inventory_cost_records` 原始表
3. 通过 `inventory_store_mapping` 映射到销售门店编码
4. `include_in_operating_cost` 标志控制是否纳入成本分析
### 4.3 导入后处理
- 刷新 `mv_inventory_cost_classified_monthly` 物化视图
- 刷新 `mv_store_theoretical_actual_cost_monthly` 物化视图
---
## 五、菜品成本分析导入(dish_cost_analysis_summary
### 5.1 数据源
- **来源文件**: 菜品成本分析Excel
- **内容**: 每个菜品的理论成本、实际成本、毛利率
### 5.2 导入流程
1. 读取 Excel,按菜品导入
2. 写入 `dish_cost_analysis_summary``dish_cost_analysis_material_detail`
3. 记录导入日志到 `dish_cost_analysis_import_log`
4. 按 `report_month``import_id` 区分批次
---
## 六、考勤薪资导入
### 6.1 考勤数据
- **原始表**: `attendance_records`38列)
- **导入日志**: `attendance_import_log`
- **内容**: 员工打卡记录(上班/下班/迟到/早退)
### 6.2 薪资数据
- **原始表**: `salary_detail_records`102列)
- **导入日志**: `salary_import_log`
- **内容**: 员工薪资明细(基本工资/加班/社保/公积金等)
---
## 七、门店位置导入(store_location_master
### 7.1 数据源
- **来源文件**: 门店位置信息Excel
- **内容**: 门店地址、经纬度(GCJ02)、面积、租约到期日、营业时间
### 7.2 导入流程
1. 读取 Excel,写入 `store_location_source_rows` 原始行
2. 匹配到 `sales_store_location_mapping` 建立门店编码关联
3. 更新 `store_location_master` 主数据
### 7.3 关键字段
| 字段 | 说明 |
|------|------|
| `area_sqm` | 营业面积(平米),用于坪效计算 |
| `lease_expiry_date` | 租约到期日,用于续租风险 |
| `latitude_gcj02` / `longitude_gcj02` | GCJ02坐标,用于地图展示 |
| `business_address` | 营业地址 |
---
## 八、数据导入后的标准操作流程
```
1. 导入原始数据到 public.* 表
2. 刷新 bill_fact 物化视图
REFRESH MATERIALIZED VIEW analytics.bill_fact;
3. 刷新依赖 bill_fact 的物化视图
REFRESH MATERIALIZED VIEW analytics.mv_daily_revenue;
REFRESH MATERIALIZED VIEW analytics.mv_store_risk_rating_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_theoretical_actual_cost_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_sku_abc_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_sku_summary_monthly;
... (所有依赖 bill_fact 的物化视图)
4. 更新 mv_store_operating_expense_monthly 物化表
(从 v_store_operating_expense_monthly 视图 INSERT/UPDATE
5. 刷新库存成本物化视图
REFRESH MATERIALIZED VIEW analytics.mv_inventory_cost_classified_monthly;
6. 验证数据一致性
- 对比 bill_fact 和 mv_store_risk_rating_monthly 门店数
- 对比 bill_fact 和 mv_store_theoretical_actual_cost_monthly 实收合计
- 检查是否有遗漏门店
```
---
## 九、已知问题与修复记录
### 9.1 门店编码映射错误
- **问题**: 关东店编码错误映射为0033,实际应为1098
- **修复**: 更新 `store_name_mapping`
### 9.2 旧数据误删
- **问题**: 导入新数据时误删了旧账单记录(bill_records),导致历史数据丢失
- **修复**: 从数据库备份 `bill_query_full_20260802_150344.dump` 恢复,使用 `pg_restore` 恢复到临时库后提取缺失数据
### 9.3 费用单位重复映射
- **问题**: "哈马尔罕大钟寺店"的费用记录未映射到"大钟寺店"(0022),导致费用未纳入门店评估
- **修复**: 更新 `operating_expense_store_mapping`,将 `sales_store_code` 设为 0022`include_in_operating_analysis = true`
### 9.4 视图聚合问题
- **问题**: `v_store_operating_expense_monthly` 视图未按 `sales_store_code` 聚合,导致多个费用单位映射到同一门店时出现重复行
- **修复**: 重建视图,增加 `expense_agg` CTE 按 `sales_store_code` GROUP BY 聚合
File diff suppressed because it is too large Load Diff
+401
View File
@@ -0,0 +1,401 @@
# 系统本体结构描述
## 一、数据库架构
- **数据库引擎**: PostgreSQL 15 (Homebrew)
- **数据库名**: bill_query
- **Schema 分布**: `public`(原始数据)、`analytics`(分析层)
---
## 二、原始数据表(public schema
### 2.1 账单数据
| 表名 | 列数 | 说明 |
|------|------|------|
| `bill_records` | 199 | 账单明细原始表,每行一笔账单,字段以 c001~c199 编码 |
| `bill_columns` | 4 | 账单字段元数据(列号→含义映射) |
**关键字段映射**:
- `c002` = 门店名称,`c003` = 门店名称(冗余),`c009` = 消费金额,`c068` = 优惠金额
- `c175` = 下单时间,`c176` = 结账时间,`c178` = 就餐人数
- `c181` = 会员卡号,`c185` = 会员标识
- `c114` = 理论成本额,`c009` = 消费额(用于理论毛利率计算)
### 2.2 费用数据
| 表名 | 列数 | 说明 |
|------|------|------|
| `operating_expense_records` | 17 | 经营费用原始记录(工资/房租/水电/佣金等) |
| `operating_expense_store_mapping` | 10 | 费用单位→销售门店编码映射,含 `include_in_operating_analysis` 标志 |
| `operating_expense_import_log` | 8 | 费用导入日志 |
### 2.3 库存成本数据
| 表名 | 列数 | 说明 |
|------|------|------|
| `inventory_cost_records` | 42 | 库存盘点成本原始记录 |
| `inventory_store_mapping` | 10 | 库存单位→销售门店编码映射,含 `include_in_operating_cost` 标志 |
| `inventory_cost_import_log` | 7 | 库存成本导入日志 |
### 2.4 菜品成本分析
| 表名 | 列数 | 说明 |
|------|------|------|
| `dish_cost_analysis_summary` | 18 | 菜品成本分析汇总(理论 vs 实际毛利率) |
| `dish_cost_analysis_material_detail` | 19 | 菜品原料明细 |
| `dish_cost_analysis_import_log` | 17 | 菜品成本分析导入日志 |
### 2.5 考勤薪资数据
| 表名 | 列数 | 说明 |
|------|------|------|
| `attendance_records` | 38 | 考勤打卡记录 |
| `attendance_import_log` | 7 | 考勤导入日志 |
| `salary_detail_records` | 102 | 薪资明细记录 |
| `salary_import_log` | 7 | 薪资导入日志 |
### 2.6 门店位置数据
| 表名 | 列数 | 说明 |
|------|------|------|
| `store_location_master` | 34 | 门店位置主数据(地址/经纬度/面积/租约等) |
| `store_location_source_rows` | 13 | 门店位置原始行 |
| `store_location_import_log` | 10 | 位置导入日志 |
| `sales_store_location_mapping` | 8 | 销售门店→位置映射 |
| `store_name_mapping` | 2 | 门店名称映射表 |
### 2.7 中央厨房数据
| 表名 | 列数 | 说明 |
|------|------|------|
| `central_kitchen_finished_receipt` | 34 | 成品入库记录 |
| `central_kitchen_manufacturing_cost_pool` | 14 | 制造费用池 |
| `central_kitchen_material_daily` | 36 | 原料日耗明细 |
| `central_kitchen_processing_cost` | 29 | 加工成本 |
| `central_kitchen_recipe_consumption` | 39 | 配方消耗 |
| `central_kitchen_import_log` | 13 | 中央厨房导入日志 |
### 2.8 配送数据
| 表名 | 列数 | 说明 |
|------|------|------|
| `distribution_detail_records` | 85 | 配送明细记录 |
| `distribution_import_log` | 17 | 配送导入日志 |
### 2.9 菜品调整
| 表名 | 列数 | 说明 |
|------|------|------|
| `dish_adjustment_log` | 20 | 菜品调整日志 |
| `dish_adjustment_result` | 15 | 菜品调整结果 |
| `dish_diagnosis_snapshot` | 19 | 菜品诊断快照 |
| `dish_sales_details` | 24 | 菜品销售明细 |
| `dish_sales_import_log` | 6 | 菜品销售导入日志 |
---
## 三、分析层维度表(analytics schema
| 表名 | 列数 | 说明 |
|------|------|------|
| `dim_store` | 14 | 门店维度(编码/名称/类型/区域) |
| `dim_calendar` | 14 | 日历维度 |
| `dim_channel` | 10 | 渠道维度 |
| `dim_daily_target` | 12 | 日度目标 |
| `dim_employee` | 9 | 员工维度 |
| `dim_material` | 12 | 原料维度 |
| `dim_member` | 13 | 会员维度 |
| `dim_product_lifecycle` | 16 | 产品生命周期 |
| `dim_promotion` | 15 | 促销维度 |
| `dim_sku` | 21 | SKU维度 |
| `dim_store_target` | 11 | 门店目标 |
| `dim_supplier` | 9 | 供应商维度 |
---
## 四、分析层事实表(analytics schema
| 表名 | 列数 | 说明 |
|------|------|------|
| `fact_bill` | 52 | 账单事实表(标准化) |
| `fact_bill_item` | 25 | 账单明细事实 |
| `fact_payment` | 9 | 支付事实 |
| `fact_customer_contact` | 13 | 客户联系事实 |
| `fact_employee_shift` | 13 | 员工排班事实 |
| `fact_inspection` | 17 | 巡检事实 |
| `fact_inventory_snapshot` | 19 | 库存快照事实 |
| `fact_iot_reading` | 11 | IoT读数事实 |
| `fact_platform_order` | 16 | 平台订单事实 |
| `fact_promotion_usage` | 12 | 促销使用事实 |
| `fact_purchase_receipt` | 16 | 采购入库事实 |
| `fact_recipe_bom` | 14 | BOM配方事实 |
| `fact_review` | 14 | 评价事实 |
| `fact_scan_confirm` | 13 | 扫描确认事实 |
| `fact_store_task` | 22 | 门店任务事实 |
| `fact_transfer` | 12 | 调拨事实 |
| `fact_waste` | 11 | 报损事实 |
---
## 五、枚举表(analytics schema
| 表名 | 说明 |
|------|------|
| `enum_business_type` | 业务类型 |
| `enum_channel_group` | 渠道分组 |
| `enum_management_quadrant` | 管理象限 |
| `enum_member_status` | 会员状态 |
| `enum_metric_direction` | 指标方向 |
| `enum_priority` | 优先级 |
| `enum_risk_level` | 风险等级 |
| `enum_sku_status` | SKU状态 |
| `enum_sku_type` | SKU类型 |
| `enum_task_status` | 任务状态 |
| `enum_verification_result` | 验证结果 |
| `enum_waste_reason` | 报损原因 |
---
## 六、物化视图列表(analytics schema
### 6.1 核心账单物化视图
| 物化视图 | 说明 | 依赖原始表 |
|----------|------|------------|
| `bill_fact` | 账单事实物化视图,从 bill_records 标准化 | `bill_records` |
| `mv_daily_revenue` | 日度营收汇总 | `bill_records` |
### 6.2 门店评估物化视图
| 物化视图 | 说明 | 依赖 |
|----------|------|------|
| `mv_store_risk_rating_monthly` | 门店风险评级(月度) | `bill_fact` |
| `mv_store_operating_expense_monthly` | 门店经营费用(月度,物化表) | `operating_expense_records` + mapping |
| `mv_store_theoretical_actual_cost_monthly` | 门店理论 vs 实际成本(月度) | `bill_fact` + `inventory_cost_records` |
| `mv_store_action_priority_deep_monthly` | 门店行动优先级深度分析 | `bill_fact` |
| `mv_store_deep_diagnosis_monthly` | 门店深度诊断 | `bill_fact` |
| `mv_store_scorecard` | 门店记分卡 | `bill_fact` |
### 6.3 门店基准与效率物化视图
| 物化视图 | 说明 | 依赖 |
|----------|------|------|
| `mv_store_benchmark_composite_monthly` | 门店综合基准 | `bill_fact` |
| `mv_store_area_efficiency_monthly` | 门店坪效分析 | `bill_fact` |
| `mv_store_platform_economics_monthly` | 门店平台经济分析 | `bill_fact` |
| `mv_store_category_mix_monthly` | 门店品类结构 | `bill_fact` |
| `mv_store_member_opportunity_monthly` | 门店会员机会 | `bill_fact` |
| `mv_store_overlap_risk_monthly` | 门店重叠风险 | `bill_fact` |
| `mv_store_site_profile_monthly` | 门店选址画像 | `bill_fact` |
| `mv_store_site_replication_monthly` | 门店选址复制 | `bill_fact` |
| `mv_store_repeat_summary_monthly` | 门店复购汇总 | `bill_fact` |
### 6.4 菜品分析物化视图
| 物化视图 | 说明 | 依赖 |
|----------|------|------|
| `mv_dish_sku_abc_monthly` | 菜品SKU ABC分类 | `bill_fact` |
| `mv_dish_sku_summary_monthly` | 菜品SKU汇总 | `bill_fact` |
| `mv_dish_store_summary_monthly` | 门店菜品汇总 | `bill_fact` |
| `mv_dish_basket_monthly` | 菜品购物篮分析 | `bill_fact` |
| `mv_dish_pair_summary_monthly` | 菜品搭配分析 | `bill_fact` |
### 6.5 选址与区域物化视图
| 物化视图 | 说明 | 依赖 |
|----------|------|------|
| `mv_district_site_benchmark_monthly` | 区域选址基准 | `bill_fact` |
| `mv_site_segment_benchmark_monthly` | 分段选址基准 | `bill_fact` |
### 6.6 库存成本物化视图
| 物化视图 | 说明 | 依赖 |
|----------|------|------|
| `mv_inventory_cost_classified_monthly` | 库存成本分类汇总 | `inventory_cost_records` + mapping |
### 6.7 固定月份物化视图(2026年4月专用)
| 物化视图 | 说明 |
|----------|------|
| `mv_store_theoretical_actual_cost_april` | 4月理论 vs 实际成本 |
| `mv_store_site_profile_april` | 4月门店选址画像 |
| `mv_store_action_priority_deep_april` | 4月行动优先级 |
| `dish_sales_april` | 4月菜品销售 |
| `dish_sku_summary_april` | 4月SKU汇总 |
| `dish_store_summary_april` | 4月门店菜品汇总 |
| `dish_basket_april` | 4月购物篮 |
| `dish_category_summary_april` | 4月品类汇总 |
| `dish_member_sku_april` | 4月会员SKU |
| `dish_store_sku_april` | 4月门店SKU |
---
## 七、普通视图列表(analytics schema
### 7.1 费用相关视图
| 视图 | 说明 | 依赖 |
|------|------|------|
| `v_operating_expense_unit_monthly` | 费用单位月度汇总 | `operating_expense_records` + mapping |
| `v_store_operating_expense_monthly` | 门店费用月度汇总(按 sales_store_code 聚合) | `v_operating_expense_unit_monthly` |
| `v_operating_expense_account_monthly` | 费用科目月度汇总 | `operating_expense_records` |
| `v_operating_expense_data_quality` | 费用数据质量 | `operating_expense_records` + mapping |
### 7.2 门店分析视图
| 视图 | 说明 |
|------|------|
| `v_store_location_operating` | 门店位置经营信息 |
| `v_store_location_data_quality` | 门店位置数据质量 |
| `v_store_daily` | 门店日度数据 |
| `v_store_daily_card` | 门店日度卡片 |
| `v_store_meal_opportunity` | 门店餐段机会 |
| `v_store_member_monthly_activity` | 门店会员月度活动 |
| `v_store_monthly_followup` | 门店月度跟进 |
| `v_store_nearest_neighbor_april` | 门店最近邻 |
| `v_store_spatial_pairs_april` | 门店空间配对 |
### 7.3 营收分析视图
| 视图 | 说明 |
|------|------|
| `v_overview_daily` | 日度总览 |
| `v_hourly_summary` | 小时汇总 |
| `v_weekday_summary` | 星期汇总 |
| `v_meal_period_daily` | 餐段日度 |
| `v_channel_daily` | 渠道日度 |
| `v_region_summary` | 区域汇总 |
### 7.4 风险与异常视图
| 视图 | 说明 |
|------|------|
| `v_anomaly_bills` | 异常账单 |
| `v_anomaly_summary` | 异常汇总 |
| `v_cashier_risk` | 收银风险 |
| `v_zero_received_store_summary` | 零实收门店汇总 |
| `v_zero_received_detail` | 零实收明细 |
### 7.5 成本相关视图
| 视图 | 说明 |
|------|------|
| `v_inventory_cost_operating` | 库存成本经营 |
| `v_inventory_cost_unit_summary` | 库存成本单位汇总 |
| `v_inventory_finance_category_april` | 库存财务分类 |
| `v_inventory_abnormal_items_april` | 库存异常项 |
| `v_cost_linkage_*` | 成本联动系列视图 |
### 7.6 中央厨房视图
| 视图 | 说明 |
|------|------|
| `v_central_kitchen_*` | 中央厨房系列视图(6个) |
| `v_distribution_*` | 配送系列视图(4个) |
### 7.7 任务与指标视图
| 视图 | 说明 |
|------|------|
| `v_task_monthly_review` | 任务月度复盘 |
| `v_task_weekly_check` | 任务周度检查 |
| `v_loop_health` | 闭环健康度 |
| `v_marketing_plan_summary` | 营销计划汇总 |
| `v_member_comparison` | 会员对比 |
| `v_member_level_mapping` | 会员等级映射 |
| `v_member_monthly_activity` | 会员月度活动 |
| `v_member_repeat_summary_monthly` | 会员复购汇总 |
| `v_position_mapping` | 岗位映射 |
| `v_data_quality_check` | 数据质量检查 |
---
## 八、V3.0 业务管理表(analytics schema
| 表名 | 说明 |
|------|------|
| `v3_annual_target` | 年度目标 |
| `v3_regional_target` | 区域目标 |
| `v3_store_monthly_target` | 门店月度目标 |
| `v3_daily_target` | 日度目标 |
| `v3_store_grade` | 门店分级 |
| `v3_store_roi` | 门店ROI |
| `v3_alert_rule` / `v3_alert_log` | 预警规则/日志 |
| `v3_approval_*` | 审批流(3表) |
| `v3_budget` / `v3_budget_lock` | 预算/预算锁 |
| `v3_coupon` | 优惠券 |
| `v3_marketing_campaign` | 营销活动 |
| `v3_forecast` | 预测 |
| `v3_monthly_report` | 月报 |
| `v3_notification` | 通知 |
| `v3_purchase_order` / `v3_purchase_order_item` | 采购订单 |
| `v3_supplier_master` | 供应商主数据 |
| `v3_inventory_snapshot` | 库存快照 |
| `v3_iot_device` / `v3_iot_temperature` | IoT设备/温度 |
| `v3_loop_verification` | 闭环验证 |
| `v3_learning_record` / `v3_training_course` | 培训学习 |
| `v3_product_lifecycle` | 产品生命周期 |
| `v3_scheduled_task` / `v3_personal_task` | 计划任务/个人任务 |
| `v3_store_grade` | 门店分级 |
| `v3_target_variance` | 目标偏差 |
| `v3_ai_target_adjustment` | AI目标调整 |
| `v3_audit_log` | 审计日志 |
| `v3_brand_asset` | 品牌资产 |
| `v3_customer_review` | 客户评价 |
| `v3_data_import_log` / `v3_data_quality_rule` | 数据导入/质量规则 |
---
## 九、数据流架构
```
原始数据导入 分析层构建 API serving
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
│ bill_records │──REFRESH──▶│ bill_fact │◀──QUERY───│ Express API │
│ (199 cols) │ │ (52 cols) │ │ (18 routes) │
└─────────────┘ └──────────────┘ └──────────────┘
│ │
│ REFRESH ▼
│ ┌──────────────────────┐
│ │ mv_store_risk_rating │
│ │ _monthly │
│ └──────────────────────┘
│ │
│ REFRESH ▼
│ ┌────────────────────────────────┐
│ │ mv_store_theoretical_actual_ │
│ │ cost_monthly │
│ └────────────────────────────────┘
┌──────────────────────┐ ┌──────────────────────────┐
│ operating_expense_ │────▶│ v_operating_expense_ │
│ records + mapping │ │ unit_monthly (view) │
└──────────────────────┘ └──────────────────────────┘
VIEW ▼
┌──────────────────────────┐
│ v_store_operating_ │
│ expense_monthly (view) │
│ (按 sales_store_code 聚合)│
└──────────────────────────┘
INSERT ▼
┌──────────────────────────┐
│ mv_store_operating_ │
│ expense_monthly (table) │
└──────────────────────────┘
┌──────────────────────┐ ┌──────────────────────────┐
│ inventory_cost_ │────▶│ mv_inventory_cost_ │
│ records + mapping │ │ classified_monthly (MV) │
└──────────────────────┘ └──────────────────────────┘
```
**关键设计**:
- `bill_fact` 是所有账单分析的基础物化视图,从 `bill_records` 标准化而来
- `mv_store_operating_expense_monthly` 是物化**表**(非视图),需手动 INSERT/UPDATE
- `v_store_operating_expense_monthly` 是普通视图,实时查询费用数据
- 部分API直接查 `bill_records`(如门店日度、排班分析),部分查 `bill_fact`
- 固定月份物化视图(`*_april`)硬编码2026年4月,不随月份参数变化
+302
View File
@@ -0,0 +1,302 @@
# 物化视图更新手册
## 一、物化视图依赖链
数据更新后必须按依赖顺序刷新物化视图,否则下游数据不一致。
```
bill_records (原始表)
▼ REFRESH
bill_fact (物化视图) ★ 第一层,最关键
├─▶ mv_daily_revenue
├─▶ mv_store_risk_rating_monthly ★ 门店评估基础
├─▶ mv_dish_sku_abc_monthly
├─▶ mv_dish_sku_summary_monthly
├─▶ mv_dish_store_summary_monthly
├─▶ mv_dish_basket_monthly
├─▶ mv_dish_pair_summary_monthly
├─▶ mv_store_action_priority_deep_monthly
├─▶ mv_store_area_efficiency_monthly
├─▶ mv_store_benchmark_composite_monthly
├─▶ mv_store_category_mix_monthly
├─▶ mv_store_deep_diagnosis_monthly
├─▶ mv_store_member_opportunity_monthly
├─▶ mv_store_overlap_risk_monthly
├─▶ mv_store_platform_economics_monthly
├─▶ mv_store_site_profile_monthly
├─▶ mv_store_site_replication_monthly
├─▶ mv_store_repeat_summary_monthly
├─▶ mv_district_site_benchmark_monthly
├─▶ mv_site_segment_benchmark_monthly
└─▶ mv_store_theoretical_actual_cost_monthly ★ 门店成本
inventory_cost_records (原始表)
▼ REFRESH
mv_inventory_cost_classified_monthly
operating_expense_records (原始表)
▼ VIEW (无需刷新)
v_operating_expense_unit_monthly
▼ VIEW (无需刷新)
v_store_operating_expense_monthly (按 sales_store_code 聚合)
▼ INSERT/UPDATE (需手动操作)
mv_store_operating_expense_monthly (物化表)
```
---
## 二、刷新命令清单
### 2.1 账单数据更新后(必刷)
```sql
-- ★ 第一优先级:bill_fact 是所有分析的基础
REFRESH MATERIALIZED VIEW analytics.bill_fact;
-- ★ 第二优先级:门店评估相关
REFRESH MATERIALIZED VIEW analytics.mv_store_risk_rating_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_theoretical_actual_cost_monthly;
-- 第三优先级:菜品分析
REFRESH MATERIALIZED VIEW analytics.mv_dish_sku_abc_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_sku_summary_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_store_summary_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_basket_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_pair_summary_monthly;
-- 第四优先级:门店深度分析
REFRESH MATERIALIZED VIEW analytics.mv_store_action_priority_deep_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_area_efficiency_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_benchmark_composite_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_category_mix_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_deep_diagnosis_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_member_opportunity_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_overlap_risk_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_platform_economics_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_site_profile_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_site_replication_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_repeat_summary_monthly;
-- 第五优先级:日度与区域
REFRESH MATERIALIZED VIEW analytics.mv_daily_revenue;
REFRESH MATERIALIZED VIEW analytics.mv_district_site_benchmark_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_site_segment_benchmark_monthly;
```
### 2.2 库存成本数据更新后
```sql
REFRESH MATERIALIZED VIEW analytics.mv_inventory_cost_classified_monthly;
-- 理论vs实际成本也依赖库存数据
REFRESH MATERIALIZED VIEW analytics.mv_store_theoretical_actual_cost_monthly;
```
### 2.3 费用数据更新后
```sql
-- v_operating_expense_unit_monthly 和 v_store_operating_expense_monthly 是普通视图,无需刷新
-- 但 mv_store_operating_expense_monthly 是物化表,需要手动更新:
-- 方法1:删除+插入(推荐,简单可靠)
DELETE FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '2026-04-01';
INSERT INTO analytics.mv_store_operating_expense_monthly
SELECT * FROM analytics.v_store_operating_expense_monthly WHERE report_month = '2026-04-01';
-- 方法2:全量重建
TRUNCATE analytics.mv_store_operating_expense_monthly;
INSERT INTO analytics.mv_store_operating_expense_monthly
SELECT * FROM analytics.v_store_operating_expense_monthly;
```
---
## 三、一键刷新脚本
```bash
#!/bin/bash
# refresh_all_mv.sh - 刷新所有物化视图
# 用法: bash refresh_all_mv.sh [month] (默认 2026-04)
MONTH=${1:-2026-04}
MONTH_START="${MONTH}-01"
psql -h localhost -p 5432 -U freedak -d bill_query <<EOF
-- 第一层
REFRESH MATERIALIZED VIEW analytics.bill_fact;
-- 第二层
REFRESH MATERIALIZED VIEW analytics.mv_store_risk_rating_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_theoretical_actual_cost_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_daily_revenue;
-- 第三层
REFRESH MATERIALIZED VIEW analytics.mv_dish_sku_abc_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_sku_summary_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_store_summary_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_basket_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_dish_pair_summary_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_action_priority_deep_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_area_efficiency_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_benchmark_composite_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_category_mix_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_deep_diagnosis_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_member_opportunity_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_overlap_risk_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_platform_economics_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_site_profile_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_site_replication_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_store_repeat_summary_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_district_site_benchmark_monthly;
REFRESH MATERIALIZED VIEW analytics.mv_site_segment_benchmark_monthly;
-- 库存成本
REFRESH MATERIALIZED VIEW analytics.mv_inventory_cost_classified_monthly;
-- 费用物化表
DELETE FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '${MONTH_START}';
INSERT INTO analytics.mv_store_operating_expense_monthly
SELECT * FROM analytics.v_store_operating_expense_monthly WHERE report_month = '${MONTH_START}';
-- 验证
SELECT 'bill_fact' AS source, count(DISTINCT store_code) AS stores, round(sum(received_total)::numeric,2) AS received
FROM analytics.bill_fact WHERE closed_at >= '${MONTH_START}' AND closed_at < ('${MONTH_START}'::date + interval '1 month')
UNION ALL
SELECT 'risk_rating', count(*), round(sum(received)::numeric,2)
FROM analytics.mv_store_risk_rating_monthly WHERE month_start = '${MONTH_START}'
UNION ALL
SELECT 'theo_cost', count(*), round(sum(sales_received)::numeric,2)
FROM analytics.mv_store_theoretical_actual_cost_monthly WHERE month_start = '${MONTH_START}'
UNION ALL
SELECT 'op_expense', count(*), round(sum(received)::numeric,2)
FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '${MONTH_START}';
EOF
```
---
## 四、物化视图 vs 普通视图 vs 物化表
| 类型 | 刷新方式 | 示例 | 说明 |
|------|----------|------|------|
| 物化视图 (Materialized View) | `REFRESH MATERIALIZED VIEW` | `bill_fact`, `mv_store_risk_rating_monthly` | 数据快照,需手动刷新 |
| 普通视图 (View) | 实时查询,无需刷新 | `v_store_operating_expense_monthly`, `v_operating_expense_account_monthly` | 每次查询实时计算 |
| 物化表 (Table) | `INSERT/UPDATE/DELETE` | `mv_store_operating_expense_monthly` | 物理表,需手动写入 |
### 判断方法
```sql
-- 查看对象类型
SELECT relname, relkind
FROM pg_class
WHERE relname LIKE 'mv_%' OR relname LIKE 'v_%'
AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'analytics');
-- relkind 含义:
-- 'm' = 物化视图 (需要 REFRESH)
-- 'v' = 普通视图 (无需刷新)
-- 'r' = 普通表 (需要 INSERT/UPDATE)
```
---
## 五、常见问题
### 5.1 数据不一致
**症状**: API返回的门店数少于实际门店数,或实收合计与 bill_fact 不一致
**原因**: 导入新数据后未刷新物化视图
**修复**: 执行上述刷新命令
### 5.2 费用未纳入门店评估
**症状**: 某门店在评估列表中缺失或费用为0
**原因**:
1. `operating_expense_store_mapping``sales_store_code` 未设置
2. `include_in_operating_analysis` 标志为 false
3. `mv_store_operating_expense_monthly` 物化表未更新
**修复**:
```sql
-- 检查映射
SELECT * FROM operating_expense_store_mapping WHERE cost_unit_source_name ILIKE '%门店名%';
-- 更新映射
UPDATE operating_expense_store_mapping
SET sales_store_code = '0022', include_in_operating_analysis = true
WHERE cost_unit_source_name = '哈马尔罕大钟寺店';
-- 刷新物化表
DELETE FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '2026-04-01';
INSERT INTO analytics.mv_store_operating_expense_monthly
SELECT * FROM analytics.v_store_operating_expense_monthly WHERE report_month = '2026-04-01';
```
### 5.3 费用重复行
**症状**: 同一门店在 `mv_store_operating_expense_monthly` 中出现多行
**原因**: 多个费用单位映射到同一 `sales_store_code`,但视图未按 `sales_store_code` 聚合
**修复**: 确认 `v_store_operating_expense_monthly` 视图定义包含 `expense_agg` CTE,按 `sales_store_code` GROUP BY
### 5.4 固定月份物化视图
**问题**: `*_april` 系列物化视图硬编码2026年4月,不支持其他月份
**影响**: 5月数据需要创建新的 `*_may` 系列物化视图,或修改为通用月份
**当前状态**: `v_store_operating_expense_monthly` 视图中 sales/food/loc CTE 引用了 `v_store_site_profile_april``v_store_theoretical_actual_cost_april`,这些是4月专用视图
---
## 六、数据一致性验证
刷新后执行以下验证:
```sql
-- 1. 门店数一致性
SELECT 'bill_fact' AS src, count(DISTINCT store_code) AS stores
FROM analytics.bill_fact
WHERE closed_at >= '2026-04-01' AND closed_at < '2026-05-01'
UNION ALL
SELECT 'risk_rating', count(*)
FROM analytics.mv_store_risk_rating_monthly WHERE month_start = '2026-04-01'
UNION ALL
SELECT 'theo_cost', count(*)
FROM analytics.mv_store_theoretical_actual_cost_monthly WHERE month_start = '2026-04-01'
UNION ALL
SELECT 'op_expense', count(*)
FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '2026-04-01';
-- 2. 实收一致性
SELECT 'bill_fact' AS src, round(sum(received_total)::numeric,2) AS received
FROM analytics.bill_fact
WHERE closed_at >= '2026-04-01' AND closed_at < '2026-05-01'
UNION ALL
SELECT 'risk_rating', round(sum(received)::numeric,2)
FROM analytics.mv_store_risk_rating_monthly WHERE month_start = '2026-04-01'
UNION ALL
SELECT 'theo_cost', round(sum(sales_received)::numeric,2)
FROM analytics.mv_store_theoretical_actual_cost_monthly WHERE month_start = '2026-04-01'
UNION ALL
SELECT 'op_expense', round(sum(received)::numeric,2)
FROM analytics.mv_store_operating_expense_monthly WHERE report_month = '2026-04-01';
-- 3. 差异门店排查
SELECT store_code, store_name, received
FROM analytics.mv_store_risk_rating_monthly
WHERE month_start = '2026-04-01' AND received > 0
AND store_code NOT IN (
SELECT DISTINCT store_code FROM analytics.mv_store_operating_expense_monthly
WHERE report_month = '2026-04-01'
);
```
@@ -0,0 +1,585 @@
# 玄谋智脑系统销售和服务合同
> **合同编号**[XMZN-YYYY-XXXX]
> **签订地点**[省/市]
> **签订日期**[年]年[月]月[日]日
> **版本**V1.0(商务及法务评审稿)
> **重要提示**:本文件为系统销售与服务合同通用范本,不构成针对任何具体交易的法律意见。正式签署前,双方应根据部署方式、数据类型、服务边界、费用、验收口径及适用法律,交由各自法务或外部律师审核。
---
## 一、合同主体
### 甲方(客户)
- **单位名称**[甲方全称]
- **统一社会信用代码**[代码]
- **地址**[地址]
- **法定代表人/授权代表**[姓名]
- **项目负责人**[姓名]
- **联系电话**[电话]
- **电子邮箱**[邮箱]
### 乙方(供应商)
- **单位名称**[乙方全称]
- **统一社会信用代码**[代码]
- **地址**[地址]
- **法定代表人/授权代表**[姓名]
- **项目负责人**[姓名]
- **联系电话**[电话]
- **电子邮箱**[邮箱]
甲乙双方根据《中华人民共和国民法典》《中华人民共和国网络安全法》《中华人民共和国数据安全法》《中华人民共和国个人信息保护法》及其他适用法律法规,本着平等、自愿、公平和诚实信用原则,就“玄谋智脑”系统许可、实施及持续服务事宜达成本合同。
---
## 二、定义
1. **玄谋智脑/本系统**:指乙方提供的面向连锁企业的行业数字本体与 AI 经营辅助决策系统,包括本合同及附件明确的软件功能、配置、接口、模型、报告与服务。
2. **项目**:指乙方依本合同为甲方提供系统许可、数据接入、配置实施、试运行、培训、验收、维护和相关专业服务的整体工作。
3. **业务数据**:指甲方或甲方授权的第三方系统提供的 POS、ERP、WMS、财务、会员、外卖、HR、Excel 及其他与经营相关的数据。
4. **个人信息**:指以电子或其他方式记录的、与已识别或可识别的自然人有关的各种信息,不包括匿名化处理后的信息。
5. **产品标准功能**:指乙方在签约时已形成、可重复向不同客户提供的通用功能。
6. **定制成果**:指双方在附件中明确列为“定制开发”,且由乙方为甲方特定需求新建的代码、配置、报表或其他成果。
7. **AI 建议**:指本系统基于数据、规则、统计方法、模型或大语言模型生成的异常识别、归因、预测、情景测算、经营建议或文本输出。
8. **工作日**:除中国法定节假日及休息日以外的日期。
---
## 三、合同目标与合作原则
1. 本项目目标是整合甲方现有、合法可用的经营数据,建立统一业务语义、指标体系与经营分析闭环,辅助甲方发现经营问题、推动整改、验证结果并沉淀组织经验。
2. 本系统原则上不取代甲方现有 POS、ERP、WMS、财务、HR 等生产或交易系统,除双方书面约定外,不直接改写甲方生产系统原始数据。
3. 项目采取“先验证价值、再扩大范围”的原则。首期原则上以一至两个可量化经营专项为主,具体范围以《项目范围与交付清单》为准。
4. 双方确认,经营结果受市场环境、季节、管理执行、人员、竞争、价格、供应链、政策及数据质量等多重因素影响。乙方不对营收、利润、毛利率、成本降幅、融资或其他经营成果作无条件保证。
---
## 四、系统销售、许可与使用范围
### 4.1 许可模式
双方选择以下第 [ ] 种模式:
1. **SaaS 订阅**:乙方在云环境中向甲方提供有期限的访问和使用权。
2. **甲方私有化部署**:系统部署于甲方或甲方指定的合规环境,乙方提供有期限或永久的软件使用许可。
3. **混合部署**:部分数据、模型或服务在甲方环境内运行,部分能力由乙方云服务提供。
### 4.2 许可范围
| 项目 | 约定 |
|:---|:---|
| 授权主体 | [甲方及允许使用的关联公司清单] |
| 授权用户数 | [ ] 人/不限用户 |
| 授权门店数 | [ ] 家 |
| 授权区域 | [ ] |
| 许可期限 | 自[ ]年[ ]月[ ]日至[ ]年[ ]月[ ]日 |
| 部署环境 | [生产/测试/容灾]环境,数量[ ] |
| 使用目的 | 限甲方内部经营分析、管理与决策辅助 |
### 4.3 使用限制
未经乙方书面同意,甲方不得:
1. 向授权范围外的第三方转让、出租、分许可、销售或开放本系统。
2. 对本系统进行反向工程、反编译、反汇编或尝试获取源代码,法律强制允许的情形除外。
3. 删除或修改系统中的著作权、商标、技术保护或权利声明。
4. 使用本系统从事违法活动,或处理甲方无权处理的数据。
---
## 五、项目范围与交付内容
### 5.1 首期建设范围
首期默认为八周价值验证项目,实际计划自项目启动条件全部具备之日起计算。
| 阶段 | 建议时间 | 主要工作 | 主要交付物 |
|:---|:---|:---|:---|
| 专项确认 | 第1周 | 选定1—2个经营专项,确认基线、口径、责任人 | 项目范围、指标基线、验收口径 |
| 数据接入 | 第1—2周 | 连接约定数据源,完成映射、清洗与质量检查 | 数据清单、映射关系、质量报告 |
| 分析建模 | 第3—4周 | 建立本体、指标、异常规则与分析模型 | 异常清单、影响测算、根因证据 |
| 整改执行 | 第5—6周 | 生成或配置整改任务,跟踪责任人与进度 | 整改清单、任务记录、进度报告 |
| 验证复盘 | 第7—8周 | 对比改善前后,识别外部影响,形成复制建议 | 专项报告、验收结论、最佳实践建议 |
### 5.2 候选经营专项
双方可从以下场景中选择,最终以附件勾选内容为准:
- [ ] SKU 组合、商品毛利与产品生命周期
- [ ] 人员排班、工时利用与人效
- [ ] 促销活动的增量贡献利润
- [ ] 库存、损耗、临期商品与资金占用
- [ ] 门店分级、低效门店整改与关停情景测算
- [ ] 会员复购、流失预警与精准营销
- [ ] 采购价格、供应商对标与异常识别
- [ ] 其他:[ ]
### 5.3 系统及管理交付物
在附件约定的范围内,可包括:
1. 数据源清单、数据质量报告与映射规则。
2. 业务本体、主数据及指标词典。
3. 授权范围内的经营看板、分析页面和预警能力。
4. 异常发现、归因、情景测算与 AI 辅助建议功能。
5. 整改任务、责任人、期限、进度与验收记录。
6. 项目配置文档、管理员手册和用户手册。
7. 项目培训与试运行支持。
### 5.4 不在范围内的内容
除附件另有明确约定外,下列事项不在本合同价格与交付范围内:
1. 替换或重建甲方原有生产、收银、财务、库存或人事系统。
2. 甲方或第三方系统的源码修改及接口开发费。
3. 云资源、网络专线、短信、邮件、第三方地图、大模型或其他外部服务费用,除非报价单已明确包含。
4. 数据历史补录、线下盘点、人工采集或原始业务数据修复。
5. 乙方代替甲方做出价格、人事、采购、关店、投资、融资或其他最终经营决策。
6. 未在附件中列明的定制功能、报表或大规模数据迁移。
---
## 六、项目计划、启动条件与变更管理
### 6.1 项目启动条件
以下条件全部满足之日为项目正式启动日:
1. 本合同及必要附件已生效。
2. 甲方已按约定支付首期款。
3. 双方已指定项目负责人与必要参与人员。
4. 甲方已提供符合约定的数据、接口、账号、网络、环境和业务口径。
5. 双方已书面确认首期经营专项、基线和验收方法。
### 6.2 延期
1. 因甲方未及时提供数据、环境、人员、确认或审批导致延期的,项目计划应相应顺延,乙方不承担违约责任。
2. 因乙方原因导致关键里程碑延期的,乙方应及时告知甲方、提交纠偏计划并承担本合同约定的违约责任。
### 6.3 需求变更
1. 任何影响项目范围、数据源、接口、交付物、计划、费用或验收口径的变更,应以书面《变更申请单》确认。
2. 乙方应对变更的工作量、费用、时间与风险进行评估。双方未书面确认前,乙方有权按原范围继续履行。
---
## 七、双方职责
### 7.1 甲方职责
1. 指定具有协调和决策权限的项目负责人,组织业务、IT、数据、财务、人力及门店相关人员参与。
2. 保证向乙方提供数据、资料、接口和指令的合法性、准确性、完整性及授权充分性。
3. 按时完成业务口径、规则、方案、账号、权限、交付物和验收结果的确认。
4. 组织整改动作的实际执行。乙方提供分析、建议和工具支持,不代替甲方行使管理权限。
5. 按合同约定支付费用,并为项目提供必要的办公、网络、环境与安全条件。
6. 对自身用户账号、密码、设备及内部权限分配负责。
### 7.2 乙方职责
1. 按本合同及附件约定,组织具备相应技能的人员完成系统实施与服务。
2. 建立项目计划、风险台账、问题清单和沟通机制,及时报告重大风险。
3. 依据约定采取合理的技术与管理措施保护甲方数据。
4. 不得超出甲方授权和本合同目的访问、处理、使用或对外提供甲方数据。
5. 在约定范围内提供培训、试运行和保修支持。
6. 发现可能影响数据安全、系统稳定或项目验收的重大问题时,应及时通知甲方。
---
## 八、数据保护、个人信息与安全
### 8.1 数据权属
1. 甲方业务数据及甲方依法享有权利的数据资产,其权利仍归甲方或相应权利人所有。
2. 乙方仅在履行本合同所必需的范围、目的和期限内处理甲方数据。
3. 未经甲方事先书面同意,乙方不得将甲方可识别业务数据用于向其他客户展示、对外宣传、训练通用模型或与本合同无关的目的。
### 8.2 个人信息
1. 甲方应确保个人信息的收集、使用、委托处理、提供与传输具有合法性基础,并按法律要求履行告知、同意、影响评估等义务。
2. 乙方应按甲方的合法指令处理个人信息,不得擅自变更处理目的、方式或范围。
3. 双方应另行签署《数据处理与个人信息保护附件》,明确信息种类、目的、期限、安全措施、再委托、跨境、安全事件及删除返还要求。
### 8.3 安全措施
乙方应根据部署方式和约定责任边界,采取与风险相适应的措施,可包括:
1. 身份认证、最小权限、角色分权与特权账号管理。
2. 传输加密、存储加密或等效保护。
3. 敏感数据脱敏、屏蔽、分级分类与访问审计。
4. 日志、监控、告警、备份与恢复措施。
5. 漏洞管理、恶意代码防护、开发与变更管理。
6. 对可接触甲方数据的人员进行权限限制、保密约束与安全培训。
### 8.4 数据安全事件
1. 乙方发现与甲方数据有关的未授权访问、泄露、篡改、丢失或其他安全事件后,应在[ ]小时内通知甲方。
2. 乙方应及时采取止损、调查、修复和防止扩大措施,并配合甲方履行法定报告或通知义务。
3. 因一方过错造成安全事件的,该方应依本合同及适用法律承担责任。
### 8.5 数据保留、返还与删除
1. 合同终止或甲方合法要求时,乙方应在[ ]日内按约定返还或删除甲方数据,但法律规定或备份周期必须保留的除外。
2. 对必须保留的数据,乙方应停止主动处理并持续承担保密与安全义务。
---
## 九、AI 功能与决策边界
1. 双方确认,AI 建议属于经营辅助信息,可能存在误差、遗漏、时滞、不完整或不适用于特定情形的情况。
2. 乙方应尽合理努力,使重要 AI 结论展示其数据时间、依据指标、分析路径或适用边界。
3. 甲方应由具备相应专业能力和权限的人员审核 AI 建议。价格调整、人员处置、供应商更换、门店关停、投资、融资等重要决策必须由甲方人工审批。
4. 除双方对具体场景另行进行风险评估并书面授权外,本系统不得直接执行不可逆或高影响经营动作。
5. 如 AI 功能调用第三方模型服务,乙方应在附件中说明服务商、数据处理边界、部署地域、数据保留政策和费用承担方式。
6. 未经甲方书面同意,乙方不得将甲方可识别数据用于训练或改进面向其他客户的通用模型。
---
## 十、交付、试运行与验收
### 10.1 验收原则
1. 验收以本合同、附件、经双方确认的需求、原型、变更单和测试用例为依据。
2. 对系统功能、数据质量、性能、安全、文档、培训和经营专项采用分类验收。
3. 经营收益的评估必须使用双方预先确认的基线、计算口径、数据周期和排除因素。
4. 除附件明确将某项经营指标约定为付费或验收条件外,系统功能验收不以特定利润数值必然实现为前提。
### 10.2 建议验收维度
| 验收维度 | 指标示例 | 目标值/标准 |
|:---|:---|:---|
| 功能 | 约定功能可用、角色权限生效、关键流程可完成 | [ ] |
| 数据 | 完整率、准确率、及时率、口径一致率、可追溯率 | [ ] |
| 性能 | 页面响应、批处理时间、并发用户数 | [ ] |
| 问题发现 | 发现周期、有效异常率、影响金额覆盖率 | [ ] |
| 执行闭环 | 任务接收率、完成率、整改有效率 | [ ] |
| 交付物 | 文档、报告、培训、配置和管理员移交 | [ ] |
### 10.3 验收流程
1. 乙方完成某一阶段或整体交付后,向甲方提交书面验收申请和交付清单。
2. 甲方应在收到完整验收材料后[ ]个工作日内完成测试,并一次性书面提出不符合项。
3. 乙方应在合理期限内完成不符合项修复并重新申请验收。
4. 不影响系统主要目的和核心功能的轻微缺陷,可列入遗留问题清单,不作为拒绝验收的理由;乙方应在双方确认的期限内修复。
5. 甲方在验收期限内未提出具体书面异议,且已将系统用于生产经营超过[ ]日的,可视为相应交付通过验收。如双方不接受默示验收,应在此处删除本款。
---
## 十一、培训、运维、保修与服务级别
### 11.1 培训
| 培训对象 | 次数/时长 | 形式 | 主要内容 |
|:---|:---|:---|:---|
| 系统管理员 | [ ] | [线上/现场] | 账号、权限、配置、日志和日常管理 |
| 总部/区域用户 | [ ] | [线上/现场] | 分析、预警、任务、验收和报告 |
| 店长/一线用户 | [ ] | [线上/现场] | 目标卡、整改任务、进度与反馈 |
### 11.2 保修期
1. 项目最终验收通过之日起[ ]个月为免费保修期。
2. 保修期内,乙方免费修复交付范围内的软件缺陷。
3. 因甲方或第三方擅自修改系统、基础环境故障、违规操作、外部接口变更、不可抗力或非乙方原因产生的问题,不属于免费保修范围。
### 11.3 服务级别
| 故障级别 | 定义 | 响应时间 | 恢复/解决目标 |
|:---|:---|:---|:---|
| P1 紧急 | 系统整体不可用、重大安全事件或核心数据严重错误 | [ ]分钟 | [ ]小时恢复或提供绕行方案 |
| P2 高 | 核心功能受影响,但存在部分替代方式 | [ ]小时 | [ ]个工作日 |
| P3 中 | 一般功能异常,不阻断主要业务 | [ ]小时 | [ ]个工作日 |
| P4 低 | 优化建议、使用咨询或轻微问题 | [ ]个工作日 | 纳入计划处理 |
> 具体服务时间、服务窗口、可用性指标、计划内维护时间及赔偿机制,以《服务级别协议(SLA)》为准。
---
## 十二、合同价款、税费与支付
### 12.1 费用构成
| 费用项目 | 未税金额(元) | 税率 | 含税金额(元) | 说明 |
|:---|---:|---:|---:|:---|
| 软件许可/SaaS订阅费 | [ ] | [ ]% | [ ] | [年/月/永久许可] |
| 实施与数据接入费 | [ ] | [ ]% | [ ] | [ ] |
| 八周经营专项服务费 | [ ] | [ ]% | [ ] | [ ] |
| 定制开发费 | [ ] | [ ]% | [ ] | [ ] |
| 年度运维与智脑服务费 | [ ] | [ ]% | [ ] | [ ] |
| 第三方服务及云资源 | [ ] | [ ]% | [ ] | [ ] |
| **合计** | **[ ]** | — | **[ ]** | 大写:人民币[ ] |
### 12.2 支付计划
| 期次 | 支付条件 | 比例 | 金额(元) |
|:---|:---|---:|---:|
| 首期款 | 合同生效且乙方提供合法请款材料后[ ]个工作日 | [ ]% | [ ] |
| 进度款 | 完成[数据接入/中期里程碑]并经确认后[ ]个工作日 | [ ]% | [ ] |
| 验收款 | 项目最终验收后[ ]个工作日 | [ ]% | [ ] |
| 质保款/尾款 | 保修期满或[ ] | [ ]% | [ ] |
### 12.3 发票与账户
1. 乙方应向甲方开具合法、有效、符合税法要求的[增值税专用/普通]发票。
2. 甲方付款至乙方以下账户:
- 户名:[ ]
- 开户行:[ ]
- 账号:[ ]
3. 乙方收款账户变更应提前以加盖公章的书面文件通知甲方。
### 12.4 可选的经营成果服务费
如双方采用“固定服务费+经营结果服务费”模式,必须另行签署附件,至少明确:
1. 收益指标的定义、基线、计算公式、数据来源和审核权。
2. 季节、价格、市场、新店、关店、并购、管理动作等排除因素。
3. 改善结果与乙方服务的归因方法。
4. 计费比例、上限、下限、结算周期和争议处理。
---
## 十三、知识产权
### 13.1 乙方原有成果
1. 乙方在本合同签署前已拥有,或在项目中形成且具有通用性的软件平台、源代码、算法、模型、组件、工具、数据结构、行业本体方法、通用规则、技术文档及其改进,其知识产权归乙方或相应权利人所有。
2. 乙方按本合同向甲方授予相应使用许可,但未明确转让的知识产权不因交付、部署或付款而转移。
### 13.2 甲方材料与企业知识
1. 甲方提供的商标、业务数据、管理制度、内部 SOP、原始文档及甲方原有知识产权仍归甲方或原权利人所有。
2. 基于甲方数据形成、能够识别甲方经营状况的专属报告、异常清单、任务记录和决策记录,甲方在内部经营管理中享有永久使用权;其中的通用软件、模型与方法不因此转移。
### 13.3 定制成果
定制成果权属选择以下第[ ]种方式,并在附件逐项列明:
1. 乙方保留知识产权,授予甲方永久、非独占、不可转让的内部使用权。
2. 甲方在全额支付相应定制开发费后取得约定定制成果的财产性知识产权,但乙方原有平台、通用组件、开源软件和第三方成果除外。
### 13.4 第三方与开源软件
系统中包含的开源软件或第三方软件按其各自许可条款使用。乙方应向甲方提供需要告知的重要许可限制。
---
## 十四、保密义务
1. **保密信息**包括但不限于:业务数据、个人信息、财务信息、销售信息、门店经营信息、会员信息、薪酬、价格、供应商、商业计划、系统架构、源代码、算法、安全方案、合同价格及一方标明或依性质应视为保密的其他信息。
2. 接收方仅可为履行本合同的目的使用保密信息,并仅向确有必要知悉且承担不低于本合同保密义务的员工、顾问或批准的分包商披露。
3. 未经甲方事先书面同意,乙方不得在宣传片、PPT、官网、公众号、投标、展会、案例库或对外演示中使用甲方名称、商标、门店信息、系统截图或可识别数据。
4. 经甲方书面同意使用案例时,乙方应按甲方批准的范围进行匿名化、汇总化或模拟化处理,并不得超出批准用途。
5. 下列信息不属于保密信息:接收方能证明已合法知悉、非因违约已公开、从有权第三方合法获得、或未使用对方保密信息而独立开发的信息。
6. 因法律、监管、司法或证券交易规则必须披露的,接收方应在法律允许的范围内提前通知披露方,并尽力限制披露范围。
7. 保密义务自保密信息披露之日起持续[ ]年;商业秘密、个人信息及法律要求持续保护的信息,保密义务持续至其不再属于保护对象为止。
---
## 十五、声明、保证与合规
1. 双方声明其为依法成立并有效存续的主体,有权签署和履行本合同。
2. 乙方保证在其所知且应尽合理注意的范围内,乙方提供的系统和服务不故意侵害第三方知识产权。
3. 甲方保证其提供的数据、材料、商标、软件、接口和使用指令不侵害第三方合法权益,并已获得必要授权。
4. 双方应遵守反商业贿赂、反不正当竞争、网络安全、数据保护、税务、劳动与其他适用法律。
5. 本系统输出不构成法律、审计、税务、金融、医疗或其他需要特定职业资格的专业意见。
---
## 十六、违约责任
### 16.1 逾期付款
1. 甲方逾期支付且经乙方书面催告后仍未支付的,每逾期一日,应按逾期金额的[ ]% 支付违约金,累计不超过逾期金额的[ ]%。
2. 逾期超过[ ]日的,乙方可在事先书面通知并采取必要的数据安全措施后,暂停尚未付费的服务或终止合同。
### 16.2 交付延误
因乙方原因导致经双方确认的关键里程碑逾期,且乙方在宽限期[ ]日内仍未纠正的,乙方每逾期一日按对应里程碑价款的[ ]% 支付违约金,累计不超过该里程碑价款的[ ]%。
### 16.3 数据与保密违约
1. 一方违反数据保护或保密义务的,应立即停止违约、采取补救措施,并赔偿对方因此遭受的实际直接损失及合理维权费用。
2. 如双方约定固定违约金,金额为人民币[ ]元;如固定违约金不足以弥补损失,违约方仍应对不足部分负责。本款应由法务结合交易金额审核。
### 16.4 知识产权侵权
1. 如第三方主张乙方提供的系统侵害其知识产权,甲方应及时通知乙方,交由乙方在合理范围内负责处理。
2. 乙方可选择为甲方取得继续使用的权利、进行不影响主要功能的替换或修改,或对无法继续使用的部分退还未履行期间的相应费用。
3. 因甲方数据、材料、指定技术、擅自修改、未按文档使用或与非乙方提供的产品组合产生的侵权,乙方不承担责任。
---
## 十七、责任限制
1. 任何一方不对对方的间接损失、可得利益损失、商誉损失、预期节约损失或因第三方主张而导致的扩大损失承担责任,除非适用法律不允许排除。
2. 除本条第3款情形外,任何一方因本合同承担的累计赔偿责任,以导致责任事件发生前12个月甲方已向乙方支付的相关合同费用为上限;合同履行不足12个月的,以已支付合同费用为上限。
3. 对于故意或重大过失、人身伤害、欺诈、贿赂、侵犯知识产权、违反保密义务、违法处理个人信息或适用法律不允许限制的责任,不适用前述排除或限额,或由双方另行约定更高上限。
4. 甲方基于 AI 建议做出重要经营决策前,应进行人工审核与必要的专业验证。因甲方未履行合理审核义务、违反系统警示或超出约定场景使用而造成的损失,乙方不承担相应责任。
---
## 十八、合同期限、续约、暂停与终止
### 18.1 合同期限
本合同自双方加盖公章或合同专用章之日起生效,有效期至[ ]年[ ]月[ ]日。合同到期前[ ]日,双方可就续约、许可范围与服务费用进行协商。
### 18.2 解除
1. 一方严重违反本合同,经对方书面催告后[ ]日内未纠正的,守约方有权解除合同并追究责任。
2. 一方进入破产、清算、被吊销营业执照、停止经营或明显丧失履约能力的,对方可书面解除合同。
3. 发生重大数据泄露、严重违法处理个人信息、故意侵害知识产权或重大商业贿赂行为的,守约方可立即解除合同。
### 18.3 终止后处理
1. 甲方应结清截至终止日已发生的费用。
2. 乙方应按约定提供数据导出、返还或删除支持。如需额外迁移服务,双方另行约定工作量与费用。
3. 许可到期或终止后,甲方应停止使用已到期的软件服务;甲方依约已取得永久许可的除外。
4. 保密、数据保护、知识产权、应付款项、责任限制、争议解决及性质上应当持续有效的条款,不因合同终止而失效。
---
## 十九、不可抗力与第三方因素
1. 因地震、洪水、火灾、疫情、战争、政府行为、大范围通信或云服务中断等不能预见、不能避免且不能克服的事件导致无法履约的,受影响方在法律允许范围内免责。
2. 受影响方应及时通知对方,提供合理证明,并尽力减轻损失。
3. 第三方接口、系统、模型、云资源或平台规则变更,可能影响项目实施。双方应协商采取替代方案、调整计划或通过变更单处理。
---
## 二十、通知与送达
1. 双方的合同通知应通过专人递交、快递、挂号信或约定电子邮箱发送至本合同首部载明的地址或邮箱。
2. 联系信息变更的,变更方应在[ ]个工作日内书面通知对方,否则原联系信息仍视为有效送达地址。
3. 项目过程中的日常工作确认可通过约定项目管理工具、邮件或会议纪要完成;涉及价款、范围、工期、权利义务或合同变更的,应由授权代表书面确认。
---
## 二十一、适用法律与争议解决
1. 本合同的订立、效力、解释、履行与争议解决适用中华人民共和国大陆地区法律。
2. 因本合同引起或与本合同有关的争议,双方应首先通过友好协商解决。
3. 协商不成的,双方选择以下第[ ]种方式:
1. 向[甲方住所地/乙方住所地/合同签订地]有管辖权的人民法院起诉。
2. 提交[ ]仲裁委员会,按其届时有效的仲裁规则仲裁。
4. 争议期间,除争议事项外,双方应继续履行不受影响的其他条款。
---
## 二十二、其他
1. 本合同、附件、补充协议、经双方授权代表确认的变更单和验收文件,共同构成双方完整约定。
2. 文件效力冲突时,原则上按以下顺序确定:后签署的补充协议/变更单 → 本合同正文 → 项目范围与交付清单 → 其他附件;但相关文件明确约定其优先级的除外。
3. 本合同某条款被认定为无效或不可执行的,不影响其他条款的效力。双方应以合法、有效且最接近原商业目的的条款替代。
4. 一方未立即行使某项权利,不构成对该权利的放弃。
5. 未经对方书面同意,任何一方不得转让本合同主要权利义务;但因合并、分立、重组或资产转让而承继且不降低履约能力的除外,并应及时通知对方。
6. 本合同一式[ ]份,甲乙双方各执[ ]份,具有同等法律效力。符合适用法律要求的可靠电子签名与纸质签章具有同等效力。
---
## 二十三、合同附件
下列附件应根据实际交易选择并作为本合同不可分割的组成部分:
1. **附件一:项目范围与交付清单**
2. **附件二:报价单与支付计划**
3. **附件三:项目实施计划与里程碑**
4. **附件四:验收标准与测试用例**
5. **附件五:数据处理与个人信息保护附件**
6. **附件六:数据源、接口与责任边界清单**
7. **附件七:信息安全要求与安全事件处置流程**
8. **附件八:服务级别协议(SLA)**
9. **附件九:第三方软件、开源软件与 AI 模型服务清单**
10. **附件十:需求变更申请单模板**
---
## 二十四、签署页
(以下无正文)
| 甲方(盖章) | 乙方(盖章) |
|:---|:---|
| 单位名称:[ ] | 单位名称:[ ] |
| 法定代表人/授权代表:[ ] | 法定代表人/授权代表:[ ] |
| 签字:[ ] | 签字:[ ] |
| 日期:[ ]年[ ]月[ ]日 | 日期:[ ]年[ ]月[ ]日 |
---
# 附件一:项目范围与交付清单(简表)
## 1. 基本范围
| 类别 | 约定 |
|:---|:---|
| 项目名称 | 玄谋智脑[ ]专项 |
| 项目目标 | [ ] |
| 覆盖组织 | [总部/区域/门店] |
| 覆盖门店 | [ ]家 |
| 数据周期 | [ ] |
| 经营专项 | [ ] |
| 部署方式 | [SaaS/私有化/混合] |
## 2. 数据源清单
| 数据源 | 系统/提供方 | 接入方式 | 频率 | 责任方 | 备注 |
|:---|:---|:---|:---|:---|:---|
| POS | [ ] | [API/文件/数据库视图] | [ ] | [ ] | [ ] |
| 外卖平台 | [ ] | [ ] | [ ] | [ ] | [ ] |
| 库存/WMS | [ ] | [ ] | [ ] | [ ] | [ ] |
| 财务 | [ ] | [ ] | [ ] | [ ] | [ ] |
| HR/考勤 | [ ] | [ ] | [ ] | [ ] | [ ] |
| 其他 | [ ] | [ ] | [ ] | [ ] | [ ] |
## 3. 交付功能与成果
| 编号 | 功能/交付物 | 标准/定制 | 验收依据 | 计划日期 |
|:---|:---|:---|:---|:---|
| 1 | 数据接入与质量报告 | [ ] | [ ] | [ ] |
| 2 | 业务本体与指标词典 | [ ] | [ ] | [ ] |
| 3 | 经营看板与分析 | [ ] | [ ] | [ ] |
| 4 | 异常预警与归因 | [ ] | [ ] | [ ] |
| 5 | AI 经营建议 | [ ] | [ ] | [ ] |
| 6 | 整改任务与验收 | [ ] | [ ] | [ ] |
| 7 | 专项报告与复制建议 | [ ] | [ ] | [ ] |
| 8 | 培训与文档 | [ ] | [ ] | [ ] |
---
# 附件二:费用与付款确认表
| 项目 | 约定 |
|:---|:---|
| 合同含税总额 | 人民币[ ]元(大写:[ ]) |
| 软件许可期 | [ ] |
| 首期款 | [ ]% / 人民币[ ]元 |
| 进度款 | [ ]% / 人民币[ ]元 |
| 验收款 | [ ]% / 人民币[ ]元 |
| 尾款 | [ ]% / 人民币[ ]元 |
| 年度运维/续订费 | 人民币[ ]元/年 |
| 差旅费 | [包含/实报实销/不发生] |
| 第三方费用 | [包含/甲方承担/按用量结算] |
---
# 附件三:上线前必填商务与法务清单
> 以下项目不宜保留空白后直接签署。
- [ ] 甲乙双方工商主体、签署权限和送达信息
- [ ] SaaS、私有化或混合部署方式
- [ ] 许可用户、门店、关联公司和使用期限
- [ ] 数据源、数据类型、数据周期和接入方式
- [ ] 是否处理个人信息、敏感个人信息或重要数据
- [ ] 是否调用第三方 AI 模型,数据是否离开甲方环境
- [ ] 项目范围、排除项、里程碑和变更流程
- [ ] 验收指标、基线、数据口径和外部排除因素
- [ ] 费用、税率、付款条件、第三方费用与差旅费
- [ ] 知识产权与定制成果权属
- [ ] 数据安全事件通知时限、数据返还和删除期限
- [ ] SLA、保修期、服务时间和赔偿机制
- [ ] 违约金、责任上限、争议解决地点与方式
- [ ] 案例宣传、商标使用和匿名数据使用是否授权
- [ ] 双方法务、数据保护负责人和信息安全负责人已审核
@@ -0,0 +1,429 @@
# 《看不见的利润》——玄谋智脑老板版宣传片剧本
> **品牌**:玄谋智脑
> **副标题**:连锁企业行业数字本体与 AI 经营智脑
> **目标观众**:连锁企业老板、董事长、总经理及投资决策者
> **建议时长**:2 分 30 秒—2 分 45 秒
> **风格**:冷峻、克制、高级,具有商业电影感和决策压迫感
> **情绪曲线**:繁荣表象 → 利润危机 → 管理失控 → 看清问题 → 掌控全局 → 长期复利
## 一、核心创意
影片不从介绍产品功能开始,而是先向老板提出一个有压迫感的问题:
> **你的企业可能每天都在增长,也可能每天都在漏掉利润。**
用“营收上升但利润流失”形成第一次冲击,用“门店越多、管理越容易失控”形成第二次冲击,再让“玄谋智脑”以企业经营全局掌控者的形象出现。
影片的核心不是证明 AI 多么先进,而是让老板相信:
> **玄谋智脑能让经营问题更早被发现、让整改真正落地,并把每一次改善复制到更多门店。**
---
## 二、分镜剧本
### 0:00—0:12|老板以为企业正在增长
#### 画面
- 深夜城市航拍。
- 一家家连锁门店在城市中依次亮起。
- 地图上的门店节点不断增加。
- 快速切换新店开业、顾客排队、外卖订单响起、收银数字增长、仓库繁忙运转。
- 总部屏幕上的营收曲线持续上升。
#### 旁白
> 门店越来越多。
> 订单越来越多。
> 营收,也在增长。
#### 屏幕文字
> **企业正在增长。**
画面停顿半秒,音乐突然切断。
文字瞬间碎裂,黑底上出现:
> # 但利润呢?
#### 声音
- 低沉心跳声逐渐增强。
- 叠加订单提示音、收银声和货币流动声。
- “但利润呢”出现时所有声音骤停。
---
### 0:12—0:30|看得见营收,看不见利润漏洞
#### 画面
- 刚才繁荣的画面迅速变暗。
- 营收数字继续上升,利润数字却开始下降。
- 红色资金流从不同经营环节向外流失。
- 每个流失节点依次标记:低毛利 SKU、无效促销、人员闲置、高损耗库存、异常采购价格、持续亏损门店。
#### 旁白
> 订单增长了,促销却可能正在消耗利润。
> 营收靠前的门店,可能没有创造相应的现金。
> 畅销商品,可能只是制造了繁忙。
> 每一家门店里,都可能存在老板看不见的利润漏洞。
#### 屏幕快闪文字
```text
低毛利
高损耗
无效工时
库存占用
促销替代
门店亏损
```
最后定格:
> **不是企业没有数据。**
> **而是数据没有变成决策。**
---
### 0:30—0:45|传统管理方式已经到达极限
#### 画面
- 总部会议室里,老板面对多块屏幕与大量报表。
- POS、财务、外卖、库存、人力、Excel 和工作群消息不断涌现。
- 不同报表上的数字互相矛盾。
- 画面逐渐加速,数据、消息和预警几乎淹没老板。
#### 旁白
> POS、财务、库存、会员、外卖、人力……
> 数据散落在不同系统里。
> 开会先核对数字,出现问题再追问原因。
> 当企业从 30 家店走向 300 家店,依靠人盯、表管、群里催,已经无法掌控全局。
#### 屏幕大字
> # 规模扩大,不应该意味着管理失控。
---
### 0:45—1:00|玄谋智脑登场
#### 画面
- 黑暗中出现一道蓝色光线。
- 散落的数据节点被逐一连接。
- “门店—商品—订单—会员—员工—供应商—库存—利润”形成立体的企业经营图谱。
- 图谱从混乱逐渐转为清晰、稳定、可运行的经营系统。
- 品牌名称缓慢出现。
#### 旁白
> 玄谋智脑。
> 面向连锁企业的行业数字本体与 AI 经营智脑。
> 它不替换企业现有系统,也不制造更多报表。
> 它将散落的数据、行业知识和管理经验,连接成一套持续进化的经营决策能力。
#### 屏幕文字
```text
看清现在
发现问题
推动整改
掌控未来
```
#### 声音
- 音乐从压迫感转为低频、沉稳、具有力量的科技旋律。
- 品牌出现时加入低频冲击音。
---
### 1:00—1:20|从异常到利润改善
#### 画面
- 企业经营图谱中出现一个红色异常点。
- 镜头迅速向下穿透:企业 → 区域 → 门店 A-017 → 晚餐时段 → 人员排班。
- 系统形成完整闭环链路。
```text
发现异常
→ 穿透根因
→ 测算影响
→ 生成方案
→ 推动执行
→ 验证结果
```
#### 旁白
> 玄谋智脑持续扫描企业经营状态。
> 发现异常后,自动穿透到区域、门店、SKU、班次和订单。
> 测算问题影响了多少利润,给出可以执行的整改方案。
> 明确责任人和完成期限,并验证利润是否真正改善。
#### 屏幕大字
> **发现问题,不是终点。**
> **改善结果,才是。**
---
### 1:20—1:35|案例一:SKU 利润优化
#### 画面
- 数百个 SKU 在数据空间中排列。
- 低销量、低毛利、高损耗、原料重复、价格带重叠的商品逐步变红。
- 低效 SKU 被重新组合,库存占用下降,利润曲线上升。
#### 旁白
> 某匿名连锁品牌,拥有数百个在售 SKU。
> 玄谋智脑发现:部分商品只贡献极少销售额,却持续占用库存,增加报损和采购复杂度。
> 下架低效 SKU,优化定价与配方,重构共享原料体系。
#### 屏幕模拟结果
```text
释放库存资金:约 80 万元
年度减少报损:约 35 万元
综合毛利率:提升约 0.6 个百分点
```
> **角标**:匿名复合案例|模拟测算
---
### 1:35—1:50|案例二:人员排班
#### 画面
- 门店客流曲线与员工工时曲线同时出现。
- 上午员工过剩区域变红;晚高峰人员不足区域变红。
- AI 重新调整班次后,工时曲线与客流曲线逐渐匹配。
#### 旁白
> 某门店营收排名靠前,人效却位于区域末端。
> 玄谋智脑按半小时预测客流和工作量,重新匹配正式工、小时工与备餐任务。
> 不降低服务质量,减少无效工时。
#### 屏幕模拟结果
```text
单店每月节约:约 1.8 万元
复制至 60 家门店
年度改善空间:约 1,296 万元
```
> **角标**:匿名复合案例|模拟测算
---
### 1:50—2:04|案例三:促销与关店决策
#### 画面 A:促销利润
- 订单量显示“+23%”。
- 随后逐层扣除优惠补贴、平台佣金、低毛利商品、原价订单替代和新增人工。
- 最后活动贡献利润从正数变为负数。
#### 旁白 A
> 订单增长 23% 的活动,扣除补贴、佣金和订单替代后,贡献利润可能为负。
> 玄谋智脑不只问活动带来了多少订单,而是问——每投入一元营销费用,最终增加了多少利润。
#### 画面 B:门店止损
- 一家长期亏损门店出现。
- 四条决策路径同时展开:继续经营、投入整改、缩小面积、关停并迁移会员。
- 每条路径后方出现未来 12 个月的利润、现金流与风险测算。
#### 旁白 B
> 对于低效门店,它同时推演整改、缩店、迁址和关停方案。
> 让一个困难的经验判断,变成有数据依据、有止损线、有退出预案的经营决策。
> **角标**:匿名复合案例|模拟测算
---
### 2:04—2:18|老板、总部、区域、店长共用一个经营闭环
#### 画面
四层组织结构依次亮起:
```text
老板
总部
区域
店长
```
每一层出现自己的决策界面:
- 老板:利润、风险、未来预测。
- 总部:区域对标、资源配置。
- 区域:异常门店、整改验收。
- 店长:今日目标、执行动作。
#### 旁白
> 老板看结果。
> 总部找原因。
> 区域推动整改。
> 店长执行动作。
> 所有人使用同一套经营语言,所有动作回到同一个利润闭环。
#### 屏幕文字
> **一个企业**
> **一套经营认知**
> **一个执行闭环**
---
### 2:18—2:30|从单店改善到企业长期复利
#### 画面
- 企业经营图谱不断扩大。
- 30 家、100 家、300 家门店依次点亮。
- 优秀门店的经营经验化为蓝色光流,快速复制到其他门店。
- 依次出现:风险提前预警、经营趋势预测、现金流推演、数据资产沉淀、银行融资数据支持、企业最佳实践库。
#### 旁白
> 当每一次经营判断、整改动作和验证结果都被沉淀,企业获得的不再是一套软件。
> 而是一项不依赖少数能人、能够支撑持续扩张、持续进化的经营能力。
---
### 2:30—2:42|结尾行动号召
#### 画面
- 画面切黑,停顿半秒。
- 一条蓝色光线横向展开。
- 主标题逐字出现。
> # 看清企业现在
> # 掌控经营未来
随后品牌出现:
> # 玄谋智脑
#### 旁白
> 不必从建设一套庞大的系统开始。
> 先用八周,找到第一批可以验证的利润改善机会。
#### 最终屏幕
> **玄谋智脑**
> 让问题更早被发现
> 让整改真正落地
> 让每一次改善复制到更多门店
底部小字:
> 行业数字本体与 AI 经营智脑
#### 声音
- 旁白语速放慢。
- “八周”和“利润改善”重读。
- 品牌出现时,音乐形成一次强烈、干净的收束。
---
## 三、开场钩子备选
### 首选
> **老板最危险的,不是看见亏损,而是看见营收,却没有看见利润正在消失。**
### 备选一
> 你的企业,可能每天都在增长,也可能每天都在漏掉利润。
### 备选二
> 从 30 家店到 300 家店,最大的风险不是开得不够快,而是已经看不清每一家店。
---
## 四、配音要求
- **声线**:建议男声,40—50 岁质感,低沉、稳定、具有决策权威感。
- **表达**:克制、有力,避免传统广告腔和过度煽情。
- **开场**:语速较慢,使用停顿制造压力。
- **危机段**:语速逐渐加快,叠加数据涌现的窒息感。
- **品牌登场**:声音下沉,“玄谋智脑”逐字清晰发音。
- **案例段**:加快节奏,强调“发现—动作—结果”。
- **结尾**:再次放慢,重读“八周”、“可以验证”和“利润改善”。
---
## 五、视觉与音乐方向
### 视觉色彩
- 主背景:深黑、炭灰。
- 品牌主色:冷蓝色光线。
- 风险与利润流失:暗红色。
- 经营改善:由红转蓝、由混乱转清晰。
### 画面风格
- 高端商业电影质感,避免廉价科技光效。
- 数据图谱与企业经营场景结合,不制作密集仪表盘界面。
- 字体简洁、粗壮,关键句使用黑底白字或黑底蓝字。
- 案例不使用真实客户形象,可使用概念化门店、匿名编号与抽象数据。
### 音乐节奏
1. **0:00—0:12**:心跳与低频,表面繁荣,暗含不安。
2. **0:12—0:45**:低音增强,金属与噪音逐渐累积,形成管理压力。
3. **0:45—1:20**:品牌登场,出现有秩序的低频节拍。
4. **1:20—2:04**:案例快节奏推进,重点数据出现时加入短促冲击音。
5. **2:04—2:30**:音乐开始变得开阔,表现组织协同与规模扩张。
6. **2:30—2:42**:减少音乐层次,将注意力交给旁白和品牌。
---
## 六、数据安全与宣传合规要求
1. 不展示任何真实客户名称、真实门店名称或品牌标识。
2. 不使用生产系统截图、真实报表、订单明细或数据库结构。
3. 不展示会员姓名、手机号、身份信息、薪酬或个人工号。
4. 案例中的企业、门店和人员统一使用匿名编号。
5. 所有金额与改善数据在画面中标注:**“匿名复合案例|模拟测算”**。
6. 不使用“保证提升”、“必然增利”、“自动替代决策”等过度承诺。
7. AI 的角色表达为“发现、归因、测算、建议和跟踪”,重要经营决策仍由管理者审批。
---
## 七、制作原则
- 前 3 秒必须出现利润危机钩子。
- 前 30 秒完成“繁荣表象—利润危机—管理失控”的情绪推进。
- 不堆砌技术名词,所有能力都落到利润、现金流、风险和执行结果。
- 不将影片制作成功能界面录屏,应以企业经营决策故事为主线。
- 案例不只呈现问题,必须呈现“发现—分析—动作—验证”。
- 画面文字保持极简,每个镜头只传达一个重点。
- 结尾不使用泛化的“谢谢观看”,而是推动老板接受“八周利润专项验证”。
@@ -0,0 +1,456 @@
{"kind":"deck","id":"pr/b7j3z3","name":"Deck"}
{"kind":"layout","layoutId":"f673259f-cc37-4c44-adbc-61865f765d54","name":"Master","type":"master"}
{"kind":"layout","layoutId":"dca06ee3-56a1-466b-bef1-c810d243d6fc","name":"Title Slide","type":"title"}
{"kind":"slide","id":"sl/hj9qgi","slide":1,"title":"玄谋智脑","textShapes":4}
{"kind":"textbox","id":"sh/ehgji98z","slide":1,"text":"玄谋智脑","textPreview":"玄谋智脑","textChars":4,"textLines":1,"bbox":[42,34,360,36]}
{"kind":"textbox","id":"sh/1k72t47a","slide":1,"text":"让老板看清每一分利润\n管住每一家门店","textPreview":"让老板看清每一分利润 | 管住每一家门店","textChars":18,"textLines":2,"bbox":[42,180,990,180]}
{"kind":"textbox","id":"sh/gjy1kzq5","slide":1,"text":"面向连锁企业的行业数字本体与 AI 经营智脑","textPreview":"面向连锁企业的行业数字本体与 AI 经营智脑","textChars":22,"textLines":1,"bbox":[42,402,870,48]}
{"kind":"shape","id":"sh/n69kvepg","slide":1,"bbox":[42,615,1196,0]}
{"kind":"textbox","id":"sh/2lgjm98v","slide":1,"text":"对外保密版 · 案例与金额均为匿名示意","textPreview":"对外保密版 · 案例与金额均为匿名示意","textChars":19,"textLines":1,"bbox":[42,640,620,24]}
{"kind":"notes","id":"nt/hj9qgi","slide":1,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/qxqhfa","slide":2,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":13}
{"kind":"textbox","id":"sh/tcv6tcbq","slide":2,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/6947yxcz","slide":2,"text":"老板真正需要回答的,只有三个问题","textPreview":"老板真正需要回答的,只有三个问题","textChars":16,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/rador2tk","slide":2,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/k725wnut","slide":2,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/58v6psbe","slide":2,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[42,190,80,48]}
{"kind":"shape","id":"sh/i5knuxc3","slide":2,"bbox":[42,248,350,0]}
{"kind":"textbox","id":"sh/j6tonito","slide":2,"text":"哪里在亏钱?","textPreview":"哪里在亏钱?","textChars":6,"textLines":1,"bbox":[42,278,350,52]}
{"kind":"textbox","id":"sh/wj25snux","slide":2,"text":"门店、SKU、促销、库存、人力中,哪些利润漏洞最应该先处理?","textPreview":"门店、SKU、促销、库存、人力中,哪些利润漏洞最应该先处理?","textChars":30,"textLines":1,"bbox":[42,352,350,140]}
{"kind":"textbox","id":"sh/xkb6lsbi","slide":2,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[443,190,80,48]}
{"kind":"shape","id":"sh/9gr6h83m","slide":2,"bbox":[443,248,350,0]}
{"kind":"textbox","id":"sh/ofi5o321","slide":2,"text":"哪些动作能增利?","textPreview":"哪些动作能增利?","textChars":8,"textLines":1,"bbox":[443,278,350,52]}
{"kind":"textbox","id":"sh/ne9ofylg","slide":2,"text":"不只找问题,还要测算影响、给出方案、跟踪执行并验证结果。","textPreview":"不只找问题,还要测算影响、给出方案、跟踪执行并验证结果。","textChars":28,"textLines":1,"bbox":[443,352,350,140]}
{"kind":"textbox","id":"sh/md0nmdkv","slide":2,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[844,190,80,48]}
{"kind":"shape","id":"sh/1cr6d83a","slide":2,"bbox":[844,248,350,0]}
{"kind":"textbox","id":"sh/0bi5k325","slide":2,"text":"扩张后还能管住吗?","textPreview":"扩张后还能管住吗?","textChars":9,"textLines":1,"bbox":[844,278,350,52]}
{"kind":"textbox","id":"sh/zqpobylk","slide":2,"text":"从 30 家到 300 家门店,有效经验能否被低成本、高质量地复制?","textPreview":"从 30 家到 300 家门店,有效经验能否被低成本、高质量地复制?","textChars":34,"textLines":1,"bbox":[844,352,350,140]}
{"kind":"textbox","id":"sh/epgnitkz","slide":2,"text":"不是看更多报表,而是将数据转化为可验证的经营改善。","textPreview":"不是看更多报表,而是将数据转化为可验证的经营改善。","textChars":25,"textLines":1,"bbox":[42,590,1100,42]}
{"kind":"notes","id":"nt/qxqhfa","slide":2,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/1s4wob","slide":3,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":15}
{"kind":"textbox","id":"sh/2pszedgz","slide":3,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/psjypsza","slide":3,"text":"连锁企业不缺数据,缺的是利润穿透力","textPreview":"连锁企业不缺数据,缺的是利润穿透力","textChars":17,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/orahgny5","slide":3,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/bu1gr2hg","slide":3,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/qtszixgv","slide":3,"bbox":[42,188,360,160]}
{"kind":"shape","id":"sh/dw3ytczm","slide":3,"bbox":[42,188,7,160]}
{"kind":"textbox","id":"sh/cvuhk7y1","slide":3,"text":"营收","textPreview":"营收","textChars":2,"textLines":1,"bbox":[66,210,314,40]}
{"kind":"textbox","id":"sh/ryhgfyhc","slide":3,"text":"营收增长,利润为何没有同步?","textPreview":"营收增长,利润为何没有同步?","textChars":14,"textLines":1,"bbox":[66,262,314,68]}
{"kind":"shape","id":"sh/6x8f6tgr","slide":3,"bbox":[443,188,360,160]}
{"kind":"shape","id":"sh/c32t0jyt","slide":3,"bbox":[443,188,7,160]}
{"kind":"textbox","id":"sh/d4ba9ofe","slide":3,"text":"门店","textPreview":"门店","textChars":2,"textLines":1,"bbox":[467,210,314,40]}
{"kind":"textbox","id":"sh/qh0bytgn","slide":3,"text":"哪些门店看似赚钱,实际占用资金?","textPreview":"哪些门店看似赚钱,实际占用资金?","textChars":16,"textLines":1,"bbox":[467,262,314,68]}
{"kind":"shape","id":"sh/r29s7yx8","slide":3,"bbox":[844,188,360,160]}
{"kind":"shape","id":"sh/072t43yp","slide":3,"bbox":[844,188,7,160]}
{"kind":"textbox","id":"sh/l8bad8fa","slide":3,"text":"促销","textPreview":"促销","textChars":2,"textLines":1,"bbox":[868,210,314,40]}
{"kind":"textbox","id":"sh/y5kb2tgz","slide":3,"text":"哪些活动增加订单,却消耗利润?","textPreview":"哪些活动增加订单,却消耗利润?","textChars":15,"textLines":1,"bbox":[868,262,314,68]}
{"kind":"shape","id":"sh/z6tsbyxk","slide":3,"bbox":[42,390,360,160]}
{"kind":"shape","id":"sh/gbi9szyl","slide":3,"bbox":[42,390,7,160]}
{"kind":"textbox","id":"sh/hcra14f6","slide":3,"text":"SKU","textPreview":"SKU","textChars":3,"textLines":1,"bbox":[66,412,314,40]}
{"kind":"textbox","id":"sh/xwzi9wny","slide":3,"text":"哪些商品销量不低,却毛利不足?","textPreview":"哪些商品销量不低,却毛利不足?","textChars":15,"textLines":1,"bbox":[66,464,314,68]}
{"kind":"shape","id":"sh/wvqhgbmd","slide":3,"bbox":[443,390,360,160]}
{"kind":"shape","id":"sh/vuhg765s","slide":3,"bbox":[443,390,7,160]}
{"kind":"textbox","id":"sh/atoze147","slide":3,"text":"人力","textPreview":"人力","textChars":2,"textLines":1,"bbox":[467,412,314,40]}
{"kind":"textbox","id":"sh/5kzidgnu","slide":3,"text":"哪些时段人员闲置,高峰又缺人?","textPreview":"哪些时段人员闲置,高峰又缺人?","textChars":15,"textLines":1,"bbox":[467,464,314,68]}
{"kind":"shape","id":"sh/kzqhkbm9","slide":3,"bbox":[844,390,360,160]}
{"kind":"shape","id":"sh/jyh0b65o","slide":3,"bbox":[844,390,7,160]}
{"kind":"textbox","id":"sh/ix8zi143","slide":3,"text":"止损","textPreview":"止损","textChars":2,"textLines":1,"bbox":[868,412,314,40]}
{"kind":"textbox","id":"sh/tojih0nq","slide":3,"text":"哪些门店应整改、迁址、缩编或关停?","textPreview":"哪些门店应整改、迁址、缩编或关停?","textChars":17,"textLines":1,"bbox":[868,464,314,68]}
{"kind":"notes","id":"nt/1s4wob","slide":3,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/ikpsiw","slide":4,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":22}
{"kind":"textbox","id":"sh/h43mhg7q","slide":4,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/uhcn61of","slide":4,"text":"玄谋智脑将一个异常,变成经过验证的利润改善","textPreview":"玄谋智脑将一个异常,变成经过验证的利润改善","textChars":21,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/v2l4f6p0","slide":4,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/47e5cv6h","slide":4,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/58n6l072","slide":4,"bbox":[82,350,1090,0]}
{"kind":"shape","id":"sh/i5wnalob","slide":4,"bbox":[54,332,36,36]}
{"kind":"textbox","id":"sh/j65ojqpw","slide":4,"text":"1","textPreview":"1","textChars":1,"textLines":1,"bbox":[54,337,36,24]}
{"kind":"textbox","id":"sh/kba50r6d","slide":4,"text":"发现","textPreview":"发现","textChars":2,"textLines":1,"bbox":[44,235,150,40]}
{"kind":"textbox","id":"sh/lcjm9w7y","slide":4,"text":"利润异常","textPreview":"利润异常","textChars":4,"textLines":1,"bbox":[44,400,164,78]}
{"kind":"shape","id":"sh/tw32ts7i","slide":4,"bbox":[253,332,36,36]}
{"kind":"textbox","id":"sh/svul0nqx","slide":4,"text":"2","textPreview":"2","textChars":1,"textLines":1,"bbox":[253,337,36,24]}
{"kind":"textbox","id":"sh/rulkr2pc","slide":4,"text":"穿透","textPreview":"穿透","textChars":2,"textLines":1,"bbox":[243,235,150,40]}
{"kind":"textbox","id":"sh/6tc3yx8r","slide":4,"text":"区域·门店·SKU·班次","textPreview":"区域·门店·SKU·班次","textChars":12,"textLines":1,"bbox":[243,400,164,78]}
{"kind":"shape","id":"sh/10n2xc7e","slide":4,"bbox":[452,332,36,36]}
{"kind":"textbox","id":"sh/gzul47q9","slide":4,"text":"3","textPreview":"3","textChars":1,"textLines":1,"bbox":[452,337,36,24]}
{"kind":"textbox","id":"sh/fylkv2po","slide":4,"text":"测算","textPreview":"测算","textChars":2,"textLines":1,"bbox":[442,235,150,40]}
{"kind":"textbox","id":"sh/exc32x83","slide":4,"text":"影响金额与优先级","textPreview":"影响金额与优先级","textChars":8,"textLines":1,"bbox":[442,400,164,78]}
{"kind":"shape","id":"sh/p4n21c7q","slide":4,"bbox":[651,332,36,36]}
{"kind":"textbox","id":"sh/o3el8rq5","slide":4,"text":"4","textPreview":"4","textChars":1,"textLines":1,"bbox":[651,337,36,24]}
{"kind":"textbox","id":"sh/8j6dkf2d","slide":4,"text":"整改","textPreview":"整改","textChars":2,"textLines":1,"bbox":[641,235,150,40]}
{"kind":"textbox","id":"sh/9kfetkjy","slide":4,"text":"动作·责任人·期限","textPreview":"动作·责任人·期限","textChars":9,"textLines":1,"bbox":[641,400,164,78]}
{"kind":"shape","id":"sh/mhovipkn","slide":4,"bbox":[850,332,36,36]}
{"kind":"textbox","id":"sh/7ixwra18","slide":4,"text":"5","textPreview":"5","textChars":1,"textLines":1,"bbox":[850,337,36,24]}
{"kind":"textbox","id":"sh/w76dozip","slide":4,"text":"验证","textPreview":"验证","textChars":2,"textLines":1,"bbox":[840,235,150,40]}
{"kind":"textbox","id":"sh/h8fex4ja","slide":4,"text":"利润是否真正改善","textPreview":"利润是否真正改善","textChars":8,"textLines":1,"bbox":[840,400,164,78]}
{"kind":"shape","id":"sh/ulovmp0j","slide":4,"bbox":[1049,332,36,36]}
{"kind":"textbox","id":"sh/vmxwvu14","slide":4,"text":"6","textPreview":"6","textChars":1,"textLines":1,"bbox":[1049,337,36,24]}
{"kind":"textbox","id":"sh/cbmdcv2l","slide":4,"text":"沉淀","textPreview":"沉淀","textChars":2,"textLines":1,"bbox":[1039,235,150,40]}
{"kind":"textbox","id":"sh/dcvel0jq","slide":4,"text":"更新企业最佳实践","textPreview":"更新企业最佳实践","textChars":8,"textLines":1,"bbox":[1039,400,164,78]}
{"kind":"shape","id":"sh/f61gryl8","slide":4,"bbox":[42,552,1196,58]}
{"kind":"textbox","id":"sh/e5szitk3","slide":4,"text":"关键不是“发现问题”,而是“把问题变成可复制的利润改善”。","textPreview":"关键不是“发现问题”,而是“把问题变成可复制的利润改善”。","textChars":29,"textLines":1,"bbox":[66,568,1148,30]}
{"kind":"notes","id":"nt/ikpsiw","slide":4,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/73vtdw","slide":5,"title":"匿名复合案例 · SKU 组合决策","textShapes":15}
{"kind":"textbox","id":"sh/dsv6lgzq","slide":5,"text":"匿名复合案例 · SKU 组合决策","textPreview":"匿名复合案例 · SKU 组合决策","textChars":17,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/qp47algf","slide":5,"text":"SKU 更多不等于选择更多,可能只是成本更高","textPreview":"SKU 更多不等于选择更多,可能只是成本更高","textChars":22,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/rqdoj6h0","slide":5,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/4n2p8by9","slide":5,"text":"05","textPreview":"05","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/5ob6hgzu","slide":5,"text":"480","textPreview":"480","textChars":3,"textLines":1,"bbox":[42,182,190,72]}
{"kind":"textbox","id":"sh/ilkn61g3","slide":5,"text":"在售 SKU","textPreview":"在售 SKU","textChars":6,"textLines":1,"bbox":[42,256,190,30]}
{"kind":"textbox","id":"sh/3mtof6ho","slide":5,"text":"后 20% SKU 仅贡献约 3% 销售额,却持续占用库存资金。","textPreview":"后 20% SKU 仅贡献约 3% 销售额,却持续占用库存资金。","textChars":32,"textLines":1,"bbox":[262,190,800,76]}
{"kind":"shape","id":"sh/oj6pkvyd","slide":5,"bbox":[42,328,270,170]}
{"kind":"textbox","id":"sh/9kfqd0zy","slide":5,"text":"37 个","textPreview":"37 个","textChars":4,"textLines":1,"bbox":[66,354,222,64]}
{"kind":"textbox","id":"sh/1kr6d8zi","slide":5,"text":"低销量·低毛利·高损耗","textPreview":"低销量·低毛利·高损耗","textChars":11,"textLines":1,"bbox":[66,434,222,40]}
{"kind":"shape","id":"sh/gji543ix","slide":5,"bbox":[341,328,270,170]}
{"kind":"textbox","id":"sh/fi94bihc","slide":5,"text":"9 个","textPreview":"9 个","textChars":3,"textLines":1,"bbox":[365,354,222,64]}
{"kind":"textbox","id":"sh/eh0n2d0r","slide":5,"text":"高销量但低贡献利润","textPreview":"高销量但低贡献利润","textChars":9,"textLines":1,"bbox":[365,434,222,40]}
{"kind":"shape","id":"sh/tgrm98jm","slide":5,"bbox":[640,328,270,170]}
{"kind":"textbox","id":"sh/sfi503i1","slide":5,"text":"16 个","textPreview":"16 个","textChars":4,"textLines":1,"bbox":[664,354,222,64]}
{"kind":"textbox","id":"sh/rup47y1g","slide":5,"text":"可共享或替换原料","textPreview":"可共享或替换原料","textChars":8,"textLines":1,"bbox":[664,434,222,40]}
{"kind":"shape","id":"sh/6tgnyt0v","slide":5,"bbox":[939,328,270,170]}
{"kind":"textbox","id":"sh/dcb6lszq","slide":5,"text":"22 个","textPreview":"22 个","textChars":4,"textLines":1,"bbox":[963,354,222,64]}
{"kind":"textbox","id":"sh/cb25c7i5","slide":5,"text":"价格带重叠","textPreview":"价格带重叠","textChars":5,"textLines":1,"bbox":[963,434,222,40]}
{"kind":"shape","id":"sh/w7uh4vud","slide":5,"bbox":[42,535,1196,85]}
{"kind":"textbox","id":"sh/x83yx0by","slide":5,"text":"模拟测算:释放库存资金约 80 万元 · 年减少报损约 35 万元 · 综合毛利率提升约 0.6 个百分点","textPreview":"模拟测算:释放库存资金约 80 万元 · 年减少报损约 35 万元 · 综合毛利率提升约 0.6 个百分点","textChars":53,"textLines":1,"bbox":[68,558,1140,40]}
{"kind":"notes","id":"nt/73vtdw","slide":5,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/aoi4dv","slide":6,"title":"匿名复合案例 · 门店 A-017","textShapes":10}
{"kind":"textbox","id":"sh/rqd0ja9c","slide":6,"text":"匿名复合案例 · 门店 A-017","textPreview":"匿名复合案例 · 门店 A-017","textChars":17,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/crm1sfqx","slide":6,"text":"排班不是人数问题,而是工时与客流的匹配问题","textPreview":"排班不是人数问题,而是工时与客流的匹配问题","textChars":21,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/dsfilkri","slide":6,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/2l4zm58v","slide":6,"text":"06","textPreview":"06","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/3md0fa9g","slide":6,"bbox":[42,182,362,314]}
{"kind":"shape","id":"sh/4nmhovql","slide":6,"bbox":[42,182,7,314]}
{"kind":"textbox","id":"sh/povih0r6","slide":6,"text":"发现","textPreview":"发现","textChars":2,"textLines":1,"bbox":[66,204,316,40]}
{"kind":"textbox","id":"sh/uxkzil8j","slide":6,"text":"· 工作日上午存在闲置工时\n· 周五晚高峰经常缺人\n· 班次依据历史习惯\n· 加班集中在少数岗位","textPreview":"· 工作日上午存在闲置工时 | · 周五晚高峰经常缺人 | · 班次依据历史习惯 | · 加班集中在少数岗位","textChars":48,"textLines":4,"bbox":[66,256,316,222]}
{"kind":"shape","id":"sh/fit0bq94","slide":6,"bbox":[458,182,362,314]}
{"kind":"shape","id":"sh/bi18zyhc","slide":6,"bbox":[458,182,7,314]}
{"kind":"textbox","id":"sh/ahs76tgr","slide":6,"text":"动作","textPreview":"动作","textChars":2,"textLines":1,"bbox":[482,204,316,40]}
{"kind":"textbox","id":"sh/xkjq18zi","slide":6,"text":"· 按半小时预测工作量\n· 调整早晚班起止时间\n· 高峰增加小时工\n· 备餐前移至客流爬升前","textPreview":"· 按半小时预测工作量 | · 调整早晚班起止时间 | · 高峰增加小时工 | · 备餐前移至客流爬升前","textChars":46,"textLines":4,"bbox":[482,256,316,222]}
{"kind":"shape","id":"sh/cjap83yx","slide":6,"bbox":[874,182,364,314]}
{"kind":"shape","id":"sh/z6183iho","slide":6,"bbox":[874,182,7,314]}
{"kind":"textbox","id":"sh/yls7adg3","slide":6,"text":"验证","textPreview":"验证","textChars":2,"textLines":1,"bbox":[898,204,318,40]}
{"kind":"textbox","id":"sh/l83q5sze","slide":6,"text":"同时监控:\n\n· 人工成本\n· 出品时效\n· 顾客满意度\n\n避免单纯压缩人力。","textPreview":"同时监控: | | · 人工成本 | · 出品时效 | · 顾客满意度 | | 避免单纯压缩人力。","textChars":39,"textLines":7,"bbox":[898,256,318,222]}
{"kind":"shape","id":"sh/k7u9cny9","slide":6,"bbox":[42,535,1196,85]}
{"kind":"textbox","id":"sh/fqh8reh4","slide":6,"text":"模拟测算:单店每月节约 1.8 万元;复制到 60 家门店,年度改善空间约 1,296 万元。","textPreview":"模拟测算:单店每月节约 1.8 万元;复制到 60 家门店,年度改善空间约 1,296 万元。","textChars":47,"textLines":1,"bbox":[66,557,1148,42]}
{"kind":"notes","id":"nt/aoi4dv","slide":6,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/wporep","slide":7,"title":"匿名复合案例 · 营销活动 X","textShapes":17}
{"kind":"textbox","id":"sh/3mt432dg","slide":7,"text":"匿名复合案例 · 营销活动 X","textPreview":"匿名复合案例 · 营销活动 X","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/4n2lcne1","slide":7,"text":"订单增长 23%,不代表活动真正成功","textPreview":"订单增长 23%,不代表活动真正成功","textChars":18,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/pobm5sv6","slide":7,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ux036dwj","slide":7,"text":"07","textPreview":"07","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/fy94zid4","slide":7,"bbox":[42,186,350,170]}
{"kind":"textbox","id":"sh/gzil8nep","slide":7,"text":"+23%","textPreview":"+23%","textChars":4,"textLines":1,"bbox":[66,212,302,64]}
{"kind":"textbox","id":"sh/h0rm1sva","slide":7,"text":"订单增长","textPreview":"订单增长","textChars":4,"textLines":1,"bbox":[66,292,302,40]}
{"kind":"shape","id":"sh/6tg32dwn","slide":7,"bbox":[42,378,350,170]}
{"kind":"textbox","id":"sh/7up4vid8","slide":7,"text":"负值","textPreview":"负值","textChars":2,"textLines":1,"bbox":[66,404,302,64]}
{"kind":"textbox","id":"sh/jqxsve1c","slide":7,"text":"穿透成本后的活动贡献利润","textPreview":"穿透成本后的活动贡献利润","textChars":12,"textLines":1,"bbox":[66,484,302,40]}
{"kind":"textbox","id":"sh/ipor29kr","slide":7,"text":"活动为什么亏钱","textPreview":"活动为什么亏钱","textChars":7,"textLines":1,"bbox":[454,186,360,40]}
{"kind":"textbox","id":"sh/5cfaxoj2","slide":7,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[454,258,42,28]}
{"kind":"textbox","id":"sh/kr694j2h","slide":7,"text":"低毛利商品占比上升","textPreview":"低毛利商品占比上升","textChars":9,"textLines":1,"bbox":[510,254,650,40]}
{"kind":"shape","id":"sh/7ehsze18","slide":7,"bbox":[510,300,650,0]}
{"kind":"textbox","id":"sh/6dor69kn","slide":7,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[454,323,42,28]}
{"kind":"textbox","id":"sh/tgza1oje","slide":7,"text":"高价值会员获得无差别优惠","textPreview":"高价值会员获得无差别优惠","textChars":12,"textLines":1,"bbox":[510,319,650,40]}
{"kind":"shape","id":"sh/sfqt8j2t","slide":7,"bbox":[510,365,650,0]}
{"kind":"textbox","id":"sh/nidsnu14","slide":7,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[454,388,42,28]}
{"kind":"textbox","id":"sh/mh4rupkj","slide":7,"text":"促销订单替代了原价订单","textPreview":"促销订单替代了原价订单","textChars":11,"textLines":1,"bbox":[510,384,650,40]}
{"kind":"shape","id":"sh/qdcv2x47","slide":7,"bbox":[510,430,650,0]}
{"kind":"textbox","id":"sh/relcv2lc","slide":7,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[454,453,42,28]}
{"kind":"textbox","id":"sh/cfud47mx","slide":7,"text":"只评价订单和营收,没有评价增量利润","textPreview":"只评价订单和营收,没有评价增量利润","textChars":17,"textLines":1,"bbox":[510,449,650,40]}
{"kind":"shape","id":"sh/dg3uxs3i","slide":7,"bbox":[510,495,650,0]}
{"kind":"shape","id":"sh/29svyd4v","slide":7,"bbox":[454,544,746,67]}
{"kind":"textbox","id":"sh/3a1crilg","slide":7,"text":"用“每投入 1 元营销费用增加多少贡献利润”评价活动。","textPreview":"用“每投入 1 元营销费用增加多少贡献利润”评价活动。","textChars":27,"textLines":1,"bbox":[478,562,700,34]}
{"kind":"notes","id":"nt/wporep","slide":7,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/wgyf4c","slide":8,"title":"匿名复合案例 · 门店 D-006","textShapes":19}
{"kind":"textbox","id":"sh/yh8ru5o3","slide":8,"text":"匿名复合案例 · 门店 D-006","textPreview":"匿名复合案例 · 门店 D-006","textChars":17,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/l4zapknu","slide":8,"text":"关店不应靠感觉,而应比较未来 12 个月的不同情景","textPreview":"关店不应靠感觉,而应比较未来 12 个月的不同情景","textChars":25,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/k3q9wf69","slide":8,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/bexsjq5s","slide":8,"text":"08","textPreview":"08","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/adorq5o7","slide":8,"bbox":[42,180,340,55]}
{"kind":"textbox","id":"sh/xgzal0ni","slide":8,"text":"方案","textPreview":"方案","textChars":2,"textLines":1,"bbox":[60,197,304,26]}
{"kind":"shape","id":"sh/wf69sv6d","slide":8,"bbox":[382,180,378,55]}
{"kind":"textbox","id":"sh/va1svu5w","slide":8,"text":"12 个月模拟结果","textPreview":"12 个月模拟结果","textChars":9,"textLines":1,"bbox":[400,197,342,26]}
{"kind":"shape","id":"sh/u9sb2pob","slide":8,"bbox":[760,180,478,55]}
{"kind":"textbox","id":"sh/g72ls36d","slide":8,"text":"决策建议","textPreview":"决策建议","textChars":4,"textLines":1,"bbox":[778,197,442,26]}
{"kind":"shape","id":"sh/h8b21o7y","slide":8,"bbox":[42,235,340,72]}
{"kind":"textbox","id":"sh/u5k3qto7","slide":8,"text":"继续经营","textPreview":"继续经营","textChars":4,"textLines":1,"bbox":[60,256,304,35]}
{"kind":"shape","id":"sh/v6tkzyps","slide":8,"bbox":[382,235,378,72]}
{"kind":"textbox","id":"sh/832loj61","slide":8,"text":"预计亏损 92 万","textPreview":"预计亏损 92 万","textChars":9,"textLines":1,"bbox":[400,256,342,35]}
{"kind":"shape","id":"sh/t4b2xo7m","slide":8,"bbox":[760,235,478,72]}
{"kind":"textbox","id":"sh/6hk3m9ob","slide":8,"text":"不建议","textPreview":"不建议","textChars":3,"textLines":1,"bbox":[778,256,442,35]}
{"kind":"shape","id":"sh/72tkvepw","slide":8,"bbox":[42,307,340,72]}
{"kind":"textbox","id":"sh/kfilkj65","slide":8,"text":"投入整改","textPreview":"投入整改","textChars":4,"textLines":1,"bbox":[60,328,304,35]}
{"kind":"shape","id":"sh/lgr2t47q","slide":8,"bbox":[382,307,378,72]}
{"kind":"textbox","id":"sh/1wjih0ze","slide":8,"text":"预计亏损降至 35 万","textPreview":"预计亏损降至 35 万","textChars":11,"textLines":1,"bbox":[400,328,342,35]}
{"kind":"shape","id":"sh/0va1ovyt","slide":8,"bbox":[760,307,478,72]}
{"kind":"textbox","id":"sh/za10fqh8","slide":8,"text":"高风险,设止损线","textPreview":"高风险,设止损线","textChars":8,"textLines":1,"bbox":[778,328,442,35]}
{"kind":"shape","id":"sh/e9sjm5g3","slide":8,"bbox":[42,379,340,72]}
{"kind":"textbox","id":"sh/d8jid0zi","slide":8,"text":"缩小面积","textPreview":"缩小面积","textChars":4,"textLines":1,"bbox":[60,400,304,35]}
{"kind":"shape","id":"sh/c7a1kvyx","slide":8,"bbox":[382,379,378,72]}
{"kind":"textbox","id":"sh/r610bqhc","slide":8,"text":"预计接近盈亏平衡","textPreview":"预计接近盈亏平衡","textChars":8,"textLines":1,"bbox":[400,400,342,35]}
{"kind":"shape","id":"sh/q58zilgr","slide":8,"bbox":[760,379,478,72]}
{"kind":"textbox","id":"sh/x43ipkzm","slide":8,"text":"租约可重谈时考虑","textPreview":"租约可重谈时考虑","textChars":8,"textLines":1,"bbox":[778,400,442,35]}
{"kind":"shape","id":"sh/w3u1wfy1","slide":8,"bbox":[42,451,340,72]}
{"kind":"textbox","id":"sh/u9ofqhwj","slide":8,"text":"关停并迁移会员","textPreview":"关停并迁移会员","textChars":7,"textLines":1,"bbox":[60,472,304,35]}
{"kind":"shape","id":"sh/faxgjmx4","slide":8,"bbox":[382,451,378,72]}
{"kind":"textbox","id":"sh/gb6xsrep","slide":8,"text":"预计减少亏损 76 万","textPreview":"预计减少亏损 76 万","textChars":11,"textLines":1,"bbox":[400,472,342,35]}
{"kind":"shape","id":"sh/hcfylwfa","slide":8,"bbox":[760,451,478,72]}
{"kind":"textbox","id":"sh/654fmhwn","slide":8,"text":"优先建议","textPreview":"优先建议","textChars":4,"textLines":1,"bbox":[778,472,442,35]}
{"kind":"textbox","id":"sh/76dgf2x8","slide":8,"text":"AI 不替老板关店;它让经验判断具有数据依据、情景测算和退出预案。","textPreview":"AI 不替老板关店;它让经验判断具有数据依据、情景测算和退出预案。","textChars":33,"textLines":1,"bbox":[42,565,1160,44]}
{"kind":"notes","id":"nt/wgyf4c","slide":8,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/5hkg8c","slide":9,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":19}
{"kind":"textbox","id":"sh/sbi9o3ap","slide":9,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/ra9sfy9k","slide":9,"text":"老板、总部、区域、店长,共用一个经营闭环","textPreview":"老板、总部、区域、店长,共用一个经营闭环","textChars":20,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/q90rmtsz","slide":9,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/58radore","slide":9,"text":"09","textPreview":"09","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/47i9kjat","slide":9,"bbox":[42,190,265,316]}
{"kind":"textbox","id":"sh/369sbe98","slide":9,"text":"老板","textPreview":"老板","textChars":2,"textLines":1,"bbox":[64,214,220,46]}
{"kind":"textbox","id":"sh/i50ritsn","slide":9,"text":"看结果","textPreview":"看结果","textChars":3,"textLines":1,"bbox":[64,296,220,44]}
{"kind":"textbox","id":"sh/p4vapsri","slide":9,"text":"利润·风险·资源投向","textPreview":"利润·风险·资源投向","textChars":10,"textLines":1,"bbox":[64,386,220,72]}
{"kind":"textbox","id":"sh/o329wnqx","slide":9,"text":"→","textPreview":"→","textChars":1,"textLines":1,"bbox":[310,323,30,36]}
{"kind":"shape","id":"sh/a5obe18f","slide":9,"bbox":[341,190,265,316]}
{"kind":"textbox","id":"sh/b6xc76p0","slide":9,"text":"总部","textPreview":"总部","textChars":2,"textLines":1,"bbox":[363,214,220,46]}
{"kind":"textbox","id":"sh/c76tgrq5","slide":9,"text":"找原因","textPreview":"找原因","textChars":3,"textLines":1,"bbox":[363,296,220,44]}
{"kind":"textbox","id":"sh/x8fu9w7q","slide":9,"text":"跨区域对标·政策评估","textPreview":"跨区域对标·政策评估","textChars":10,"textLines":1,"bbox":[363,386,220,72]}
{"kind":"textbox","id":"sh/2h4bah83","slide":9,"text":"→","textPreview":"→","textChars":1,"textLines":1,"bbox":[609,323,30,36]}
{"kind":"shape","id":"sh/n2dc3mpo","slide":9,"bbox":[640,190,265,316]}
{"kind":"textbox","id":"sh/o36tcrq9","slide":9,"text":"区域","textPreview":"区域","textChars":2,"textLines":1,"bbox":[662,214,220,46]}
{"kind":"textbox","id":"sh/p4fu5w7u","slide":9,"text":"推整改","textPreview":"推整改","textChars":3,"textLines":1,"bbox":[662,296,220,44]}
{"kind":"textbox","id":"sh/6d8vmlon","slide":9,"text":"门店分级·任务·验收","textPreview":"门店分级·任务·验收","textChars":10,"textLines":1,"bbox":[662,386,220,72]}
{"kind":"textbox","id":"sh/7yhcfqps","slide":9,"text":"→","textPreview":"→","textChars":1,"textLines":1,"bbox":[908,323,30,36]}
{"kind":"shape","id":"sh/3i987i5k","slide":9,"bbox":[939,190,265,316]}
{"kind":"textbox","id":"sh/ih0rydoz","slide":9,"text":"店长","textPreview":"店长","textChars":2,"textLines":1,"bbox":[961,214,220,46]}
{"kind":"textbox","id":"sh/5kbq98na","slide":9,"text":"做动作","textPreview":"做动作","textChars":3,"textLines":1,"bbox":[961,296,220,44]}
{"kind":"textbox","id":"sh/4ji90n6p","slide":9,"text":"日目标·偏差·行动建议","textPreview":"日目标·偏差·行动建议","textChars":11,"textLines":1,"bbox":[961,386,220,72]}
{"kind":"shape","id":"sh/rmtsbi5g","slide":9,"bbox":[42,550,1196,60]}
{"kind":"textbox","id":"sh/qlkr2dov","slide":9,"text":"结果回到经营大盘:执行不是终点,改善结果才是。","textPreview":"结果回到经营大盘:执行不是终点,改善结果才是。","textChars":23,"textLines":1,"bbox":[66,567,1148,30]}
{"kind":"notes","id":"nt/5hkg8c","slide":9,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/hiuvy9","slide":10,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":7}
{"kind":"textbox","id":"sh/szm10761","slide":10,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/rydkr25g","slide":10,"text":"AI 负责发现、测算和跟踪,重要决策仍由管理者审批","textPreview":"AI 负责发现、测算和跟踪,重要决策仍由管理者审批","textChars":25,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/qx4jyxov","slide":10,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/5wb2psna","slide":10,"text":"10","textPreview":"10","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/4v21wn6p","slide":10,"bbox":[42,182,560,366]}
{"kind":"shape","id":"sh/3utkn254","slide":10,"bbox":[42,182,7,366]}
{"kind":"textbox","id":"sh/i9kjuxoj","slide":10,"text":"AI 可以承担","textPreview":"AI 可以承担","textChars":7,"textLines":1,"bbox":[66,204,514,40]}
{"kind":"textbox","id":"sh/h8b2lsne","slide":10,"text":"· 理解并关联跨系统数据\n· 持续扫描异常\n· 穿透至门店、SKU、班次和订单\n· 调用行业规则与历史案例\n· 推演方案对利润和现金流的影响\n· 跟踪执行并验证结果","textPreview":"· 理解并关联跨系统数据 | · 持续扫描异常 | · 穿透至门店、SKU、班次和订单 | · 调用行业规则与历史案例 | · 推演方案对利润和现金流的影响 | · 跟踪执行并验证结果","textChars":82,"textLines":6,"bbox":[66,256,514,274]}
{"kind":"shape","id":"sh/g721sn6t","slide":10,"bbox":[678,182,560,366]}
{"kind":"shape","id":"sh/6lo3a9gj","slide":10,"bbox":[678,182,7,366]}
{"kind":"textbox","id":"sh/rmx4jex4","slide":10,"text":"必须由管理者决定","textPreview":"必须由管理者决定","textChars":8,"textLines":1,"bbox":[702,204,514,40]}
{"kind":"textbox","id":"sh/sn6lcjyp","slide":10,"text":"· 价格调整\n· 人员处置\n· 供应商更换\n· 门店迁址与关停\n· 重大资源投入\n\n所有高影响决策都应留下依据、审批与执行记录。","textPreview":"· 价格调整 | · 人员处置 | · 供应商更换 | · 门店迁址与关停 | · 重大资源投入 | | 所有高影响决策都应留下依据、审批与执行记录。","textChars":64,"textLines":7,"bbox":[702,256,514,274]}
{"kind":"notes","id":"nt/hiuvy9","slide":10,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/n35yhd","slide":11,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":24}
{"kind":"textbox","id":"sh/9s3y5cji","slide":11,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/mpsfahkr","slide":11,"text":"BI 展示“发生了什么”;玄谋智脑推动“接下来怎么做”","textPreview":"BI 展示“发生了什么”;玄谋智脑推动“接下来怎么做”","textChars":27,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/nq1g321c","slide":11,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/wfuhgri9","slide":11,"text":"11","textPreview":"11","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/xg3y9wje","slide":11,"bbox":[42,170,228,50]}
{"kind":"textbox","id":"sh/adczeh03","slide":11,"text":"维度","textPreview":"维度","textChars":2,"textLines":1,"bbox":[58,185,196,25]}
{"kind":"shape","id":"sh/belg7m1o","slide":11,"bbox":[270,170,410,50]}
{"kind":"textbox","id":"sh/cjax4n2p","slide":11,"text":"普通 BI","textPreview":"普通 BI","textChars":5,"textLines":1,"bbox":[286,185,378,25]}
{"kind":"shape","id":"sh/dkjydsja","slide":11,"bbox":[680,170,558,50]}
{"kind":"textbox","id":"sh/9ozytoru","slide":11,"text":"玄谋智脑","textPreview":"玄谋智脑","textChars":4,"textLines":1,"bbox":[696,185,526,25]}
{"kind":"shape","id":"sh/8nqx0jap","slide":11,"bbox":[42,220,228,67]}
{"kind":"textbox","id":"sh/7mxgret4","slide":11,"text":"定位","textPreview":"定位","textChars":2,"textLines":1,"bbox":[58,238,196,38]}
{"kind":"shape","id":"sh/mlofytsj","slide":11,"bbox":[270,220,410,67]}
{"kind":"textbox","id":"sh/hszyx8r6","slide":11,"text":"展示报表","textPreview":"展示报表","textChars":4,"textLines":1,"bbox":[286,238,378,38]}
{"kind":"shape","id":"sh/wrqh43al","slide":11,"bbox":[680,220,558,67]}
{"kind":"textbox","id":"sh/vqhgvy90","slide":11,"text":"驱动经营决策与改善","textPreview":"驱动经营决策与改善","textChars":9,"textLines":1,"bbox":[696,238,526,38]}
{"kind":"shape","id":"sh/up8f2tsf","slide":11,"bbox":[42,287,228,67]}
{"kind":"textbox","id":"sh/5gjy18r2","slide":11,"text":"业务语义","textPreview":"业务语义","textChars":4,"textLines":1,"bbox":[58,305,196,38]}
{"kind":"shape","id":"sh/4fah83ah","slide":11,"bbox":[270,287,410,67]}
{"kind":"textbox","id":"sh/obi9kbm5","slide":11,"text":"字段和指标","textPreview":"字段和指标","textChars":5,"textLines":1,"bbox":[286,305,378,38]}
{"kind":"shape","id":"sh/pwbatg3q","slide":11,"bbox":[680,287,558,67]}
{"kind":"textbox","id":"sh/290ri14z","slide":11,"text":"门店、商品、人员、会员等行业本体","textPreview":"门店、商品、人员、会员等行业本体","textChars":16,"textLines":1,"bbox":[696,305,526,38]}
{"kind":"shape","id":"sh/3a9sr6lk","slide":11,"bbox":[42,354,228,67]}
{"kind":"textbox","id":"sh/cz29ovm1","slide":11,"text":"问题发现","textPreview":"问题发现","textChars":4,"textLines":1,"bbox":[58,372,196,38]}
{"kind":"shape","id":"sh/d0baxg3m","slide":11,"bbox":[270,354,410,67]}
{"kind":"textbox","id":"sh/qxkrml4b","slide":11,"text":"人主动看数据","textPreview":"人主动看数据","textChars":6,"textLines":1,"bbox":[286,372,378,38]}
{"kind":"shape","id":"sh/bytsvqlg","slide":11,"bbox":[680,354,558,67]}
{"kind":"textbox","id":"sh/s3y9crmx","slide":11,"text":"系统持续发现、分级与推送","textPreview":"系统持续发现、分级与推送","textChars":12,"textLines":1,"bbox":[696,372,526,38]}
{"kind":"shape","id":"sh/t4rqlw3i","slide":11,"bbox":[42,421,228,67]}
{"kind":"textbox","id":"sh/vyxcru50","slide":11,"text":"问题处理","textPreview":"问题处理","textChars":4,"textLines":1,"bbox":[58,439,196,38]}
{"kind":"shape","id":"sh/uxovipof","slide":11,"bbox":[270,421,410,67]}
{"kind":"textbox","id":"sh/h0fut4n6","slide":11,"text":"报告异常","textPreview":"报告异常","textChars":4,"textLines":1,"bbox":[286,439,378,38]}
{"kind":"shape","id":"sh/wz6dkz6l","slide":11,"bbox":[680,421,558,67]}
{"kind":"textbox","id":"sh/nudcnu5o","slide":11,"text":"归因、测算、方案和整改任务","textPreview":"归因、测算、方案和整改任务","textChars":13,"textLines":1,"bbox":[696,439,526,38]}
{"kind":"shape","id":"sh/mt4bepoj","slide":11,"bbox":[42,488,228,67]}
{"kind":"textbox","id":"sh/9wfupknu","slide":11,"text":"结果验证","textPreview":"结果验证","textChars":4,"textLines":1,"bbox":[58,506,196,38]}
{"kind":"shape","id":"sh/8v6tgz69","slide":11,"bbox":[270,488,410,67]}
{"kind":"textbox","id":"sh/zqdcja5s","slide":11,"text":"通常不跟踪","textPreview":"通常不跟踪","textChars":5,"textLines":1,"bbox":[286,506,378,38]}
{"kind":"shape","id":"sh/y54ba5o7","slide":11,"bbox":[680,488,558,67]}
{"kind":"textbox","id":"sh/edofudkr","slide":11,"text":"验证改善并更新最佳实践","textPreview":"验证改善并更新最佳实践","textChars":11,"textLines":1,"bbox":[696,506,526,38]}
{"kind":"shape","id":"sh/fexgni1c","slide":11,"bbox":[42,555,228,67]}
{"kind":"textbox","id":"sh/0z6xwn2x","slide":11,"text":"长期价值","textPreview":"长期价值","textChars":4,"textLines":1,"bbox":[58,573,196,38]}
{"kind":"shape","id":"sh/10fyp8ji","slide":11,"bbox":[270,555,410,67]}
{"kind":"textbox","id":"sh/q94fqtkv","slide":11,"text":"报表越来越多","textPreview":"报表越来越多","textChars":6,"textLines":1,"bbox":[286,573,378,38]}
{"kind":"shape","id":"sh/raxgjy1g","slide":11,"bbox":[680,555,558,67]}
{"kind":"textbox","id":"sh/sb6xs321","slide":11,"text":"行业模型与企业知识越用越成熟","textPreview":"行业模型与企业知识越用越成熟","textChars":14,"textLines":1,"bbox":[696,573,526,38]}
{"kind":"notes","id":"nt/n35yhd","slide":11,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/vp4c3s","slide":12,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":23}
{"kind":"textbox","id":"sh/903i9036","slide":12,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/mxczy54f","slide":12,"text":"五层能力不是技术清单,而是规模扩张的管理底座","textPreview":"五层能力不是技术清单,而是规模扩张的管理底座","textChars":22,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/7yl07al0","slide":12,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/w3uh4f2h","slide":12,"text":"12","textPreview":"12","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/h4nidk32","slide":12,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[42,185,54,28]}
{"kind":"textbox","id":"sh/u1cz25kr","slide":12,"text":"数据资产化","textPreview":"数据资产化","textChars":5,"textLines":1,"bbox":[118,171,250,54]}
{"kind":"textbox","id":"sh/v2l0balc","slide":12,"text":"数据通起来","textPreview":"数据通起来","textChars":5,"textLines":1,"bbox":[422,171,250,54]}
{"kind":"textbox","id":"sh/47e18f2t","slide":12,"text":"一个数字、一个来源","textPreview":"一个数字、一个来源","textChars":9,"textLines":1,"bbox":[720,171,450,54]}
{"kind":"shape","id":"sh/5snihk3e","slide":12,"bbox":[118,238,1050,0]}
{"kind":"textbox","id":"sh/xkrudwna","slide":12,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[42,274,54,28]}
{"kind":"textbox","id":"sh/cjyd4r6p","slide":12,"text":"运营指标化","textPreview":"运营指标化","textChars":5,"textLines":1,"bbox":[118,260,250,54]}
{"kind":"textbox","id":"sh/bipcbm54","slide":12,"text":"问题浮出来","textPreview":"问题浮出来","textChars":5,"textLines":1,"bbox":[422,260,250,54]}
{"kind":"textbox","id":"sh/ahgv2hoj","slide":12,"text":"异常能穿透到根因","textPreview":"异常能穿透到根因","textChars":8,"textLines":1,"bbox":[720,260,450,54]}
{"kind":"shape","id":"sh/loruhwn6","slide":12,"bbox":[118,327,1050,0]}
{"kind":"textbox","id":"sh/knid8r61","slide":12,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[42,363,54,28]}
{"kind":"textbox","id":"sh/zm9cfm5g","slide":12,"text":"战略穿透化","textPreview":"战略穿透化","textChars":5,"textLines":1,"bbox":[118,349,250,54]}
{"kind":"textbox","id":"sh/yl0v61ov","slide":12,"text":"目标落下去","textPreview":"目标落下去","textChars":5,"textLines":1,"bbox":[422,349,250,54]}
{"kind":"textbox","id":"sh/1s7u5c72","slide":12,"text":"战略到区域、门店和个人","textPreview":"战略到区域、门店和个人","textChars":11,"textLines":1,"bbox":[720,349,450,54]}
{"kind":"shape","id":"sh/0retw76h","slide":12,"bbox":[118,416,1050,0]}
{"kind":"textbox","id":"sh/sbidc7ed","slide":12,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[42,452,54,28]}
{"kind":"textbox","id":"sh/twrulcfy","slide":12,"text":"态势感知化","textPreview":"态势感知化","textChars":5,"textLines":1,"bbox":[118,438,250,54]}
{"kind":"textbox","id":"sh/690vaxw7","slide":12,"text":"风险早知道","textPreview":"风险早知道","textChars":5,"textLines":1,"bbox":[422,438,250,54]}
{"kind":"textbox","id":"sh/ra9cj2xs","slide":12,"text":"从事后救火到事前预防","textPreview":"从事后救火到事前预防","textChars":10,"textLines":1,"bbox":[720,438,450,54]}
{"kind":"shape","id":"sh/gz2dgrep","slide":12,"bbox":[118,505,1050,0]}
{"kind":"textbox","id":"sh/10bupcfu","slide":12,"text":"05","textPreview":"05","textChars":2,"textLines":1,"bbox":[42,541,54,28]}
{"kind":"textbox","id":"sh/exkvehwj","slide":12,"text":"知识沉淀化","textPreview":"知识沉淀化","textChars":5,"textLines":1,"bbox":[118,527,250,54]}
{"kind":"textbox","id":"sh/fytcnmx4","slide":12,"text":"组织越来越聪明","textPreview":"组织越来越聪明","textChars":7,"textLines":1,"bbox":[422,527,250,54]}
{"kind":"textbox","id":"sh/o32dkrel","slide":12,"text":"优秀能力不再依赖少数人","textPreview":"优秀能力不再依赖少数人","textChars":11,"textLines":1,"bbox":[720,527,450,54]}
{"kind":"shape","id":"sh/p4betwv6","slide":12,"bbox":[118,594,1050,0]}
{"kind":"notes","id":"nt/vp4c3s","slide":12,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/59faoc","slide":13,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":15}
{"kind":"textbox","id":"sh/pk76lo7m","slide":13,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/2hwnq98v","slide":13,"text":"企业越大,单店验证后的复制价值越高","textPreview":"企业越大,单店验证后的复制价值越高","textChars":17,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/3i5ojepg","slide":13,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/gfe5ozqp","slide":13,"text":"13","textPreview":"13","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/hgn6h47a","slide":13,"bbox":[42,182,360,250]}
{"kind":"shape","id":"sh/udwnmp8j","slide":13,"bbox":[42,182,7,250]}
{"kind":"textbox","id":"sh/fe54fup4","slide":13,"text":"不依赖能人","textPreview":"不依赖能人","textChars":5,"textLines":1,"bbox":[66,204,314,40]}
{"kind":"textbox","id":"sh/8ru5kzqt","slide":13,"text":"优秀店长的做法沉淀为规则、案例和 SOP。","textPreview":"优秀店长的做法沉淀为规则、案例和 SOP。","textChars":21,"textLines":1,"bbox":[66,256,314,158]}
{"kind":"shape","id":"sh/tc3md47e","slide":13,"bbox":[443,182,360,250]}
{"kind":"shape","id":"sh/lo7ipgzu","slide":13,"bbox":[443,182,7,250]}
{"kind":"textbox","id":"sh/knyhwbi9","slide":13,"text":"扩张不失控","textPreview":"扩张不失控","textChars":5,"textLines":1,"bbox":[467,204,314,40]}
{"kind":"textbox","id":"sh/jmp0n6ho","slide":13,"text":"验证有效的改善方案,可按门店特征分类复制。","textPreview":"验证有效的改善方案,可按门店特征分类复制。","textChars":21,"textLines":1,"bbox":[467,256,314,158]}
{"kind":"shape","id":"sh/y1gzu103","slide":13,"bbox":[844,182,360,250]}
{"kind":"shape","id":"sh/x0nilwjy","slide":13,"bbox":[844,182,7,250]}
{"kind":"textbox","id":"sh/wzehsrid","slide":13,"text":"能力持续复利","textPreview":"能力持续复利","textChars":6,"textLines":1,"bbox":[868,204,314,40]}
{"kind":"textbox","id":"sh/by50j61s","slide":13,"text":"场景、模型、AI 建议与决策反馈相互增强。","textPreview":"场景、模型、AI 建议与决策反馈相互增强。","textChars":21,"textLines":1,"bbox":[868,256,314,158]}
{"kind":"shape","id":"sh/axwzq107","slide":13,"bbox":[120,520,980,0]}
{"kind":"shape","id":"sh/9wnihwjm","slide":13,"bbox":[104,502,38,38]}
{"kind":"textbox","id":"sh/ovehori1","slide":13,"text":"30 家","textPreview":"30 家","textChars":4,"textLines":1,"bbox":[94,555,150,28]}
{"kind":"textbox","id":"sh/0ri9kvu9","slide":13,"text":"靠人盯","textPreview":"靠人盯","textChars":3,"textLines":1,"bbox":[94,589,170,24]}
{"kind":"shape","id":"sh/1sbatgvu","slide":13,"bbox":[584,502,38,38]}
{"kind":"textbox","id":"sh/ep0rilc3","slide":13,"text":"100 家","textPreview":"100 家","textChars":5,"textLines":1,"bbox":[574,555,150,28]}
{"kind":"textbox","id":"sh/zq9srqdo","slide":13,"text":"靠机制","textPreview":"靠机制","textChars":3,"textLines":1,"bbox":[574,589,170,24]}
{"kind":"shape","id":"sh/cni9gbux","slide":13,"bbox":[1064,502,38,38]}
{"kind":"textbox","id":"sh/dorqpgvi","slide":13,"text":"300 家","textPreview":"300 家","textChars":5,"textLines":1,"bbox":[1054,555,150,28]}
{"kind":"textbox","id":"sh/ql0ru1c7","slide":13,"text":"靠模型复制","textPreview":"靠模型复制","textChars":5,"textLines":1,"bbox":[1054,589,170,24]}
{"kind":"notes","id":"nt/59faoc","slide":13,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/vmna02","slide":14,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":8}
{"kind":"textbox","id":"sh/43e1k7q5","slide":14,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/3250r29k","slide":14,"text":"沉淀的不只是原始数据,而是可追溯的经营能力","textPreview":"沉淀的不只是原始数据,而是可追溯的经营能力","textChars":21,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/21wjix8z","slide":14,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/d8nixcrm","slide":14,"text":"14","textPreview":"14","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/c7e1o7q1","slide":14,"bbox":[42,180,560,365]}
{"kind":"shape","id":"sh/r650v29g","slide":14,"bbox":[42,180,7,365]}
{"kind":"textbox","id":"sh/q5wjmh8b","slide":14,"text":"企业数据资产","textPreview":"企业数据资产","textChars":6,"textLines":1,"bbox":[66,202,514,40]}
{"kind":"textbox","id":"sh/tc3ilsri","slide":14,"text":"· 统一指标口径与责任关系\n· 门店、商品、人员、会员、供应商本体\n· 行业规则与异常模式\n· 决策、执行与验证结果\n· 最佳实践与风险知识","textPreview":"· 统一指标口径与责任关系 | · 门店、商品、人员、会员、供应商本体 | · 行业规则与异常模式 | · 决策、执行与验证结果 | · 最佳实践与风险知识","textChars":70,"textLines":5,"bbox":[66,254,514,273]}
{"kind":"shape","id":"sh/sbuhcnqx","slide":14,"bbox":[678,180,560,365]}
{"kind":"shape","id":"sh/qxsvudsv","slide":14,"bbox":[678,180,7,365]}
{"kind":"textbox","id":"sh/ry1wni9g","slide":14,"text":"融资与尽调支持","textPreview":"融资与尽调支持","textChars":7,"textLines":1,"bbox":[702,202,514,40]}
{"kind":"textbox","id":"sh/sjadwnal","slide":14,"text":"· 门店级损益与现金流\n· 收入稳定性分析\n· 风险预警与整改记录\n· 未来经营预测\n· 更完整、可追溯的经营证明","textPreview":"· 门店级损益与现金流 | · 收入稳定性分析 | · 风险预警与整改记录 | · 未来经营预测 | · 更完整、可追溯的经营证明","textChars":57,"textLines":5,"bbox":[702,254,514,273]}
{"kind":"textbox","id":"sh/dkjepsr6","slide":14,"text":"边界:提供数据与分析支持,不承诺银行授信或融资结果。","textPreview":"边界:提供数据与分析支持,不承诺银行授信或融资结果。","textChars":26,"textLines":1,"bbox":[42,578,1000,34]}
{"kind":"notes","id":"nt/vmna02","slide":14,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/ncze5u","slide":15,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":15}
{"kind":"textbox","id":"sh/mhofitwv","slide":15,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/9kfyt8vm","slide":15,"text":"生产数据保密,从架构、权限到 AI 边界同时控制","textPreview":"生产数据保密,从架构、权限到 AI 边界同时控制","textChars":24,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/oj6xk3e1","slide":15,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/bmhgvyds","slide":15,"text":"15","textPreview":"15","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/al8fmdw7","slide":15,"bbox":[42,180,360,170]}
{"kind":"shape","id":"sh/x8zyx8vi","slide":15,"bbox":[42,180,7,170]}
{"kind":"textbox","id":"sh/wnqxo3ex","slide":15,"text":"部署边界","textPreview":"部署边界","textChars":4,"textLines":1,"bbox":[66,202,314,40]}
{"kind":"textbox","id":"sh/rqdgjed8","slide":15,"text":"不替代现有交易系统,只读或受控对接。","textPreview":"不替代现有交易系统,只读或受控对接。","textChars":18,"textLines":1,"bbox":[66,254,314,78]}
{"kind":"shape","id":"sh/qp4fa9wn","slide":15,"bbox":[443,180,360,170]}
{"kind":"shape","id":"sh/4bu5kji5","slide":15,"bbox":[443,180,7,170]}
{"kind":"textbox","id":"sh/5c36tozq","slide":15,"text":"最小权限","textPreview":"最小权限","textChars":4,"textLines":1,"bbox":[467,202,314,40]}
{"kind":"textbox","id":"sh/i9sni90z","slide":15,"text":"老板、总部、区域、门店按职责查看。","textPreview":"老板、总部、区域、门店按职责查看。","textChars":17,"textLines":1,"bbox":[467,254,314,78]}
{"kind":"shape","id":"sh/3a1orehk","slide":15,"bbox":[844,180,360,170]}
{"kind":"shape","id":"sh/sfu5oji1","slide":15,"bbox":[844,180,7,170]}
{"kind":"textbox","id":"sh/d036xozm","slide":15,"text":"敏感保护","textPreview":"敏感保护","textChars":4,"textLines":1,"bbox":[868,202,314,40]}
{"kind":"textbox","id":"sh/qdcnmt0b","slide":15,"text":"会员、薪酬、财务明细分级、脱敏与审计。","textPreview":"会员、薪酬、财务明细分级、脱敏与审计。","textChars":19,"textLines":1,"bbox":[868,254,314,78]}
{"kind":"shape","id":"sh/relovehg","slide":15,"bbox":[42,390,360,170]}
{"kind":"shape","id":"sh/8ja5czix","slide":15,"bbox":[42,390,7,170]}
{"kind":"textbox","id":"sh/t4j6l4zi","slide":15,"text":"AI 可追溯","textPreview":"AI 可追溯","textChars":6,"textLines":1,"bbox":[66,412,314,40]}
{"kind":"textbox","id":"sh/90bmpgr6","slide":15,"text":"重要结论显示依据、时间、路径和适用边界。","textPreview":"重要结论显示依据、时间、路径和适用边界。","textChars":20,"textLines":1,"bbox":[66,464,314,78]}
{"kind":"shape","id":"sh/oz2lgval","slide":15,"bbox":[443,390,360,170]}
{"kind":"shape","id":"sh/ny94nq90","slide":15,"bbox":[443,390,7,170]}
{"kind":"textbox","id":"sh/mx03elsv","slide":15,"text":"人工审批","textPreview":"人工审批","textChars":4,"textLines":1,"bbox":[467,412,314,40]}
{"kind":"textbox","id":"sh/x4bmt0ri","slide":15,"text":"高影响决策必须经有权限的管理者审批。","textPreview":"高影响决策必须经有权限的管理者审批。","textChars":18,"textLines":1,"bbox":[467,464,314,78]}
{"kind":"shape","id":"sh/w32lkvax","slide":15,"bbox":[844,390,360,170]}
{"kind":"shape","id":"sh/b2t4rq9c","slide":15,"bbox":[844,390,7,170]}
{"kind":"textbox","id":"sh/a1k3ilsr","slide":15,"text":"全程留痕","textPreview":"全程留痕","textChars":4,"textLines":1,"bbox":[868,412,314,40]}
{"kind":"textbox","id":"sh/58vmx0re","slide":15,"text":"访问、建议、修改、审批和执行结果均可审计。","textPreview":"访问、建议、修改、审批和执行结果均可审计。","textChars":21,"textLines":1,"bbox":[868,464,314,78]}
{"kind":"notes","id":"nt/ncze5u","slide":15,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/8zd6ih","slide":16,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":19}
{"kind":"textbox","id":"sh/h4fe5cf2","slide":16,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/u1ovaxgr","slide":16,"text":"先用 8 周证明经营价值,再扩大应用范围","textPreview":"先用 8 周证明经营价值,再扩大应用范围","textChars":20,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/v2xw32xc","slide":16,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/8zmd8nyl","slide":16,"text":"16","textPreview":"16","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/90ve1sf6","slide":16,"bbox":[66,340,1100,0]}
{"kind":"shape","id":"sh/mx4v6dgf","slide":16,"bbox":[54,322,38,38]}
{"kind":"textbox","id":"sh/7ydwzix0","slide":16,"text":"第 1 周","textPreview":"第 1 周","textChars":5,"textLines":1,"bbox":[49,206,200,28]}
{"kind":"textbox","id":"sh/kbmd4nyp","slide":16,"text":"选定利润专项","textPreview":"选定利润专项","textChars":6,"textLines":1,"bbox":[49,250,205,55]}
{"kind":"textbox","id":"sh/lwvexsfa","slide":16,"text":"基线·口径·责任人","textPreview":"基线·口径·责任人","textChars":9,"textLines":1,"bbox":[49,394,205,84]}
{"kind":"shape","id":"sh/9onyp0ja","slide":16,"bbox":[293,322,38,38]}
{"kind":"textbox","id":"sh/onehwvip","slide":16,"text":"第 1—2 周","textPreview":"第 1—2 周","textChars":7,"textLines":1,"bbox":[288,206,200,28]}
{"kind":"textbox","id":"sh/nm5gnq14","slide":16,"text":"连接现有数据","textPreview":"连接现有数据","textChars":6,"textLines":1,"bbox":[288,250,205,55]}
{"kind":"textbox","id":"sh/mlczul0j","slide":16,"text":"数据清单·质量·统一口径","textPreview":"数据清单·质量·统一口径","textChars":12,"textLines":1,"bbox":[288,394,205,84]}
{"kind":"shape","id":"sh/1k3y1gjy","slide":16,"bbox":[532,322,38,38]}
{"kind":"textbox","id":"sh/0juhsvid","slide":16,"text":"第 3—4 周","textPreview":"第 3—4 周","textChars":7,"textLines":1,"bbox":[527,206,200,28]}
{"kind":"textbox","id":"sh/zilgzq18","slide":16,"text":"发现机会与根因","textPreview":"发现机会与根因","textChars":7,"textLines":1,"bbox":[527,250,205,55]}
{"kind":"textbox","id":"sh/ehczql0n","slide":16,"text":"异常·影响金额·证据","textPreview":"异常·影响金额·证据","textChars":10,"textLines":1,"bbox":[527,394,205,84]}
{"kind":"shape","id":"sh/dw3yxgj2","slide":16,"bbox":[771,322,38,38]}
{"kind":"textbox","id":"sh/cvuhobih","slide":16,"text":"第 5—6 周","textPreview":"第 5—6 周","textChars":7,"textLines":1,"bbox":[766,206,200,28]}
{"kind":"textbox","id":"sh/4zeh4bqd","slide":16,"text":"推动整改","textPreview":"推动整改","textChars":4,"textLines":1,"bbox":[766,250,205,55]}
{"kind":"textbox","id":"sh/507ydgry","slide":16,"text":"任务·期限·执行记录","textPreview":"任务·期限·执行记录","textChars":10,"textLines":1,"bbox":[766,394,205,84]}
{"kind":"shape","id":"sh/ixwz2187","slide":16,"bbox":[1010,322,38,38]}
{"kind":"textbox","id":"sh/3y5gb69s","slide":16,"text":"第 7—8 周","textPreview":"第 7—8 周","textChars":7,"textLines":1,"bbox":[1005,206,200,28]}
{"kind":"textbox","id":"sh/wbeh0bq1","slide":16,"text":"验证并复制","textPreview":"验证并复制","textChars":5,"textLines":1,"bbox":[1005,250,205,55]}
{"kind":"textbox","id":"sh/hcny9grm","slide":16,"text":"改善金额·验收·最佳实践","textPreview":"改善金额·验收·最佳实践","textChars":12,"textLines":1,"bbox":[1005,394,205,84]}
{"kind":"shape","id":"sh/u9wzy18b","slide":16,"bbox":[42,550,1196,60]}
{"kind":"textbox","id":"sh/va5g769w","slide":16,"text":"优先选择:数据可获得 · 影响可测算 · 动作可执行 · 八周可验证。","textPreview":"优先选择:数据可获得 · 影响可测算 · 动作可执行 · 八周可验证。","textChars":35,"textLines":1,"bbox":[66,567,1148,30]}
{"kind":"notes","id":"nt/8zd6ih","slide":16,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/1tvdog","slide":17,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":19}
{"kind":"textbox","id":"sh/5cvqdkfa","slide":17,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/i9k725wj","slide":17,"text":"验收不看上线了多少功能,而看经营结果是否改善","textPreview":"验收不看上线了多少功能,而看经营结果是否改善","textChars":22,"textLines":1,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/jad8bax4","slide":17,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/szm98fel","slide":17,"text":"17","textPreview":"17","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/t0vqhkf6","slide":17,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[42,188,50,26]}
{"kind":"textbox","id":"sh/6d4r6pwv","slide":17,"text":"经营结果","textPreview":"经营结果","textChars":4,"textLines":1,"bbox":[112,174,230,48]}
{"kind":"textbox","id":"sh/red8fax0","slide":17,"text":"贡献利润·成本·损耗·库存资金","textPreview":"贡献利润·成本·损耗·库存资金","textChars":15,"textLines":1,"bbox":[395,174,760,48]}
{"kind":"shape","id":"sh/g369czex","slide":17,"bbox":[112,239,1040,0]}
{"kind":"textbox","id":"sh/14fql4fi","slide":17,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[42,274,50,26]}
{"kind":"textbox","id":"sh/twvqhgrq","slide":17,"text":"问题发现","textPreview":"问题发现","textChars":4,"textLines":1,"bbox":[112,260,230,48]}
{"kind":"textbox","id":"sh/8vmpobql","slide":17,"text":"发现周期·有效异常率·影响覆盖","textPreview":"发现周期·有效异常率·影响覆盖","textChars":15,"textLines":1,"bbox":[395,260,760,48]}
{"kind":"shape","id":"sh/7ud8f690","slide":17,"bbox":[112,325,1040,0]}
{"kind":"textbox","id":"sh/6tk7ml8f","slide":17,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[42,360,50,26]}
{"kind":"textbox","id":"sh/hkvql0r2","slide":17,"text":"执行闭环","textPreview":"执行闭环","textChars":4,"textLines":1,"bbox":[112,346,230,48]}
{"kind":"textbox","id":"sh/gjmpsvqh","slide":17,"text":"接收率·按期完成率·整改有效率","textPreview":"接收率·按期完成率·整改有效率","textChars":15,"textLines":1,"bbox":[395,346,760,48]}
{"kind":"shape","id":"sh/vid8jq9w","slide":17,"bbox":[112,411,1040,0]}
{"kind":"textbox","id":"sh/ux47ql8b","slide":17,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[42,446,50,26]}
{"kind":"textbox","id":"sh/xobq9wry","slide":17,"text":"组织复制","textPreview":"组织复制","textChars":4,"textLines":1,"bbox":[112,432,230,48]}
{"kind":"textbox","id":"sh/cn2pgrqd","slide":17,"text":"复制门店数·成功率·新店导入时间","textPreview":"复制门店数·成功率·新店导入时间","textChars":16,"textLines":1,"bbox":[395,432,760,48]}
{"kind":"shape","id":"sh/oj6hcv25","slide":17,"bbox":[112,497,1040,0]}
{"kind":"textbox","id":"sh/9kfyl03q","slide":17,"text":"05","textPreview":"05","textChars":2,"textLines":1,"bbox":[42,532,50,26]}
{"kind":"textbox","id":"sh/2hozalkf","slide":17,"text":"数据质量","textPreview":"数据质量","textChars":4,"textLines":1,"bbox":[112,518,230,48]}
{"kind":"textbox","id":"sh/nixgjqlk","slide":17,"text":"口径一致·完整·及时·可追溯","textPreview":"口径一致·完整·及时·可追溯","textChars":14,"textLines":1,"bbox":[395,518,760,48]}
{"kind":"shape","id":"sh/wnqhgf2h","slide":17,"bbox":[112,583,1040,0]}
{"kind":"shape","id":"sh/x8zip032","slide":17,"bbox":[42,612,1196,42]}
{"kind":"textbox","id":"sh/al8ze5kb","slide":17,"text":"项目启动时即确认基线、口径和外部影响因素,避免将自然波动误认为系统收益。","textPreview":"项目启动时即确认基线、口径和外部影响因素,避免将自然波动误认为系统收益。","textChars":36,"textLines":1,"bbox":[64,622,1152,24]}
{"kind":"notes","id":"nt/1tvdog","slide":17,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/edu865","slide":18,"title":"玄谋智脑","textShapes":4}
{"kind":"textbox","id":"sh/dov6hoz2","slide":18,"text":"玄谋智脑","textPreview":"玄谋智脑","textChars":4,"textLines":1,"bbox":[42,35,240,30]}
{"kind":"textbox","id":"sh/ql4nm90r","slide":18,"text":"先用 8 周\n找到第一批可验证的利润改善机会","textPreview":"先用 8 周 | 找到第一批可验证的利润改善机会","textChars":22,"textLines":2,"bbox":[42,160,1040,210]}
{"kind":"textbox","id":"sh/bmdofehc","slide":18,"text":"再决定如何扩大应用范围","textPreview":"再决定如何扩大应用范围","textChars":11,"textLines":1,"bbox":[42,420,850,52]}
{"kind":"shape","id":"sh/oj25kzil","slide":18,"bbox":[42,610,1196,0]}
{"kind":"textbox","id":"sh/pkv6d4z6","slide":18,"text":"让问题更早被发现 · 让整改真正落地 · 让每一次改善复制到更多门店","textPreview":"让问题更早被发现 · 让整改真正落地 · 让每一次改善复制到更多门店","textChars":34,"textLines":1,"bbox":[42,636,1100,30]}
{"kind":"notes","id":"nt/edu865","slide":18,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
@@ -0,0 +1,456 @@
{"kind":"deck","id":"pr/e6cjzk","name":"Deck"}
{"kind":"layout","layoutId":"/ppt/slideMasters/slideMaster1.xml","name":"Master","type":"master"}
{"kind":"layout","layoutId":"/ppt/slideLayouts/slideLayout1.xml","name":"Title Slide","type":"title"}
{"kind":"slide","id":"sl/y90nupkv","slide":1,"title":"玄谋智脑","textShapes":4}
{"kind":"textbox","id":"sh/ts7md4r2","slide":1,"text":"玄谋智脑","textPreview":"玄谋智脑","textChars":4,"textLines":1,"bbox":[42,34,360,36]}
{"kind":"textbox","id":"sh/547294r6","slide":1,"text":"看清利润,才谈得上管住门店\nSee the profit clearly. Run every store with confidence.","textPreview":"看清利润,才谈得上管住门店 | See the profit clearly. Run every store with confidence.","textChars":70,"textLines":2,"bbox":[42,180,990,180]}
{"kind":"textbox","id":"sh/k3yl0zql","slide":1,"text":"面向连锁企业的行业数字本体与 AI 经营智脑 A decision intelligence layer for multi-site operators","textPreview":"面向连锁企业的行业数字本体与 AI 经营智脑 A decision intelligence layer for multi-site operators","textChars":78,"textLines":1,"bbox":[42,402,870,48]}
{"kind":"shape","id":"sh/7qp4be9c","slide":1,"bbox":[42,615,1196,0]}
{"kind":"textbox","id":"sh/65g3298r","slide":1,"text":"对外保密版 · 案例与金额均为匿名示意","textPreview":"对外保密版 · 案例与金额均为匿名示意","textChars":19,"textLines":1,"bbox":[42,640,620,24]}
{"kind":"notes","id":"nt/y90nupkv","slide":1,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/hwbqtkby","slide":2,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":13}
{"kind":"textbox","id":"sh/cnupgny5","slide":2,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/9072xkry","slide":2,"text":"老板最终要判断三件事\nThree decisions matter most to the owner.","textPreview":"老板最终要判断三件事 | Three decisions matter most to the owner.","textChars":52,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/ozy1ofad","slide":2,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/b29kza94","slide":2,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/a10jqpsj","slide":2,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[42,190,80,48]}
{"kind":"shape","id":"sh/x4r21kru","slide":2,"bbox":[42,248,350,0]}
{"kind":"textbox","id":"sh/w3i1sfa9","slide":2,"text":"哪里在亏钱?","textPreview":"哪里在亏钱?","textChars":6,"textLines":1,"bbox":[42,278,350,52]}
{"kind":"textbox","id":"sh/r65knqtk","slide":2,"text":"门店、SKU、促销、库存、人力中,哪些利润漏洞最应该先处理?","textPreview":"门店、SKU、促销、库存、人力中,哪些利润漏洞最应该先处理?","textChars":30,"textLines":1,"bbox":[42,352,350,140]}
{"kind":"textbox","id":"sh/q5wjelsz","slide":2,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[443,190,80,48]}
{"kind":"shape","id":"sh/ove9o7yd","slide":2,"bbox":[443,248,350,0]}
{"kind":"textbox","id":"sh/9wnqhczy","slide":2,"text":"哪些动作能增利?","textPreview":"哪些动作能增利?","textChars":8,"textLines":1,"bbox":[443,278,350,52]}
{"kind":"textbox","id":"sh/mtwrmxg7","slide":2,"text":"不只找问题,还要测算影响、给出方案、跟踪执行并验证结果。","textPreview":"不只找问题,还要测算影响、给出方案、跟踪执行并验证结果。","textChars":28,"textLines":1,"bbox":[443,352,350,140]}
{"kind":"textbox","id":"sh/nu58f2hs","slide":2,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[844,190,80,48]}
{"kind":"shape","id":"sh/wjy9sry9","slide":2,"bbox":[844,248,350,0]}
{"kind":"textbox","id":"sh/xk7qlczu","slide":2,"text":"扩张后还能管住吗?","textPreview":"扩张后还能管住吗?","textChars":9,"textLines":1,"bbox":[844,278,350,52]}
{"kind":"textbox","id":"sh/ahwrqhgj","slide":2,"text":"从 30 家到 300 家门店,有效经验能否被低成本、高质量地复制?","textPreview":"从 30 家到 300 家门店,有效经验能否被低成本、高质量地复制?","textChars":34,"textLines":1,"bbox":[844,352,350,140]}
{"kind":"textbox","id":"sh/bip8jmho","slide":2,"text":"不是看更多报表,而是将数据转化为可验证的经营改善。","textPreview":"不是看更多报表,而是将数据转化为可验证的经营改善。","textChars":25,"textLines":1,"bbox":[42,590,1100,42]}
{"kind":"notes","id":"nt/hwbqtkby","slide":2,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/ofy9wn61","slide":3,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":15}
{"kind":"textbox","id":"sh/batgjixs","slide":3,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/cza94vmx","slide":3,"text":"数据很多,利润去向仍然说不清\nPlenty of data, but no clear view of where profit goes.","textPreview":"数据很多,利润去向仍然说不清 | Plenty of data, but no clear view of where profit goes.","textChars":70,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/d0jax03i","slide":3,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/298ryl4v","slide":3,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/3ah8rqlg","slide":3,"bbox":[42,188,360,160]}
{"kind":"shape","id":"sh/obq90bml","slide":3,"bbox":[42,188,7,160]}
{"kind":"textbox","id":"sh/pcjqtg36","slide":3,"text":"营收","textPreview":"营收","textChars":2,"textLines":1,"bbox":[66,210,314,40]}
{"kind":"textbox","id":"sh/m5cra54z","slide":3,"text":"营收增长,利润为何没有同步?","textPreview":"营收增长,利润为何没有同步?","textChars":14,"textLines":1,"bbox":[66,262,314,68]}
{"kind":"shape","id":"sh/n6ls3alk","slide":3,"bbox":[443,188,360,160]}
{"kind":"shape","id":"sh/n2l4fq98","slide":3,"bbox":[443,188,7,160]}
{"kind":"textbox","id":"sh/m1c3mlsn","slide":3,"text":"门店","textPreview":"门店","textChars":2,"textLines":1,"bbox":[467,210,314,40]}
{"kind":"textbox","id":"sh/943mhgre","slide":3,"text":"哪些门店看似赚钱,实际占用资金?","textPreview":"哪些门店看似赚钱,实际占用资金?","textChars":16,"textLines":1,"bbox":[467,262,314,68]}
{"kind":"shape","id":"sh/83ulovat","slide":3,"bbox":[844,188,360,160]}
{"kind":"shape","id":"sh/v6l4jq94","slide":3,"bbox":[844,188,7,160]}
{"kind":"textbox","id":"sh/a5c3ql8z","slide":3,"text":"促销","textPreview":"促销","textChars":2,"textLines":1,"bbox":[868,210,314,40]}
{"kind":"textbox","id":"sh/x8nml0ra","slide":3,"text":"哪些活动增加订单,却消耗利润?","textPreview":"哪些活动增加订单,却消耗利润?","textChars":15,"textLines":1,"bbox":[868,262,314,68]}
{"kind":"shape","id":"sh/w7ulsvqp","slide":3,"bbox":[42,390,360,160]}
{"kind":"shape","id":"sh/ja54na9g","slide":3,"bbox":[42,390,7,160]}
{"kind":"textbox","id":"sh/i9w3u58v","slide":3,"text":"SKU","textPreview":"SKU","textChars":3,"textLines":1,"bbox":[66,412,314,40]}
{"kind":"textbox","id":"sh/e10f2twf","slide":3,"text":"哪些商品销量不低,却毛利不足?","textPreview":"哪些商品销量不低,却毛利不足?","textChars":15,"textLines":1,"bbox":[66,464,314,68]}
{"kind":"shape","id":"sh/f29gbyx0","slide":3,"bbox":[443,390,360,160]}
{"kind":"shape","id":"sh/03ix43e5","slide":3,"bbox":[443,390,7,160]}
{"kind":"textbox","id":"sh/14ryd8fq","slide":3,"text":"人力","textPreview":"人力","textChars":2,"textLines":1,"bbox":[467,412,314,40]}
{"kind":"textbox","id":"sh/6d0fytg3","slide":3,"text":"哪些时段人员闲置,高峰又缺人?","textPreview":"哪些时段人员闲置,高峰又缺人?","textChars":15,"textLines":1,"bbox":[467,464,314,68]}
{"kind":"shape","id":"sh/re9g7yxo","slide":3,"bbox":[844,390,360,160]}
{"kind":"shape","id":"sh/sfix03y9","slide":3,"bbox":[844,390,7,160]}
{"kind":"textbox","id":"sh/tgry9ofu","slide":3,"text":"止损","textPreview":"止损","textChars":2,"textLines":1,"bbox":[868,412,314,40]}
{"kind":"textbox","id":"sh/a9kfadwn","slide":3,"text":"哪些门店应整改、迁址、缩编或关停?","textPreview":"哪些门店应整改、迁址、缩编或关停?","textChars":17,"textLines":1,"bbox":[868,464,314,68]}
{"kind":"notes","id":"nt/ofy9wn61","slide":3,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/jyx0ra1s","slide":4,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":22}
{"kind":"textbox","id":"sh/knex8j21","slide":4,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/1cj2d8b6","slide":4,"text":"把异常处理成有结果的经营行动\nTurn exceptions into actions with measurable outcomes.","textPreview":"把异常处理成有结果的经营行动 | Turn exceptions into actions with measurable outcomes.","textChars":69,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/0ba143al","slide":4,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/rm1k7yt4","slide":4,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/ql8jytsj","slide":4,"bbox":[82,350,1090,0]}
{"kind":"shape","id":"sh/doj29oba","slide":4,"bbox":[54,332,36,36]}
{"kind":"textbox","id":"sh/sna103ap","slide":4,"text":"1","textPreview":"1","textChars":1,"textLines":1,"bbox":[54,337,36,24]}
{"kind":"textbox","id":"sh/3ihk3et8","slide":4,"text":"发现","textPreview":"发现","textChars":2,"textLines":1,"bbox":[44,235,150,40]}
{"kind":"textbox","id":"sh/ih8ju9sn","slide":4,"text":"利润异常","textPreview":"利润异常","textChars":4,"textLines":1,"bbox":[44,400,164,78]}
{"kind":"shape","id":"sh/kbm987y5","slide":4,"bbox":[253,332,36,36]}
{"kind":"textbox","id":"sh/5cva1cfq","slide":4,"text":"2","textPreview":"2","textChars":1,"textLines":1,"bbox":[253,337,36,24]}
{"kind":"textbox","id":"sh/i94r6xgz","slide":4,"text":"穿透","textPreview":"穿透","textChars":2,"textLines":1,"bbox":[243,235,150,40]}
{"kind":"textbox","id":"sh/jadsz2xk","slide":4,"text":"区域·门店·SKU·班次","textPreview":"区域·门店·SKU·班次","textChars":12,"textLines":1,"bbox":[243,400,164,78]}
{"kind":"shape","id":"sh/w72947yt","slide":4,"bbox":[452,332,36,36]}
{"kind":"textbox","id":"sh/x8vaxsfe","slide":4,"text":"3","textPreview":"3","textChars":1,"textLines":1,"bbox":[452,337,36,24]}
{"kind":"textbox","id":"sh/a5kr2xg3","slide":4,"text":"测算","textPreview":"测算","textChars":2,"textLines":1,"bbox":[442,235,150,40]}
{"kind":"textbox","id":"sh/v6tsv2xo","slide":4,"text":"影响金额与优先级","textPreview":"影响金额与优先级","textChars":8,"textLines":1,"bbox":[442,400,164,78]}
{"kind":"shape","id":"sh/g36tgryd","slide":4,"bbox":[651,332,36,36]}
{"kind":"textbox","id":"sh/h4fa9wfy","slide":4,"text":"4","textPreview":"4","textChars":1,"textLines":1,"bbox":[651,337,36,24]}
{"kind":"textbox","id":"sh/p0batw72","slide":4,"text":"整改","textPreview":"整改","textChars":2,"textLines":1,"bbox":[641,235,150,40]}
{"kind":"textbox","id":"sh/oz29krqh","slide":4,"text":"动作·责任人·期限","textPreview":"动作·责任人·期限","textChars":9,"textLines":1,"bbox":[641,400,164,78]}
{"kind":"shape","id":"sh/3ytsrmpw","slide":4,"bbox":[850,332,36,36]}
{"kind":"textbox","id":"sh/2xkrih8b","slide":4,"text":"5","textPreview":"5","textChars":1,"textLines":1,"bbox":[850,337,36,24]}
{"kind":"textbox","id":"sh/1wbapc7q","slide":4,"text":"验证","textPreview":"验证","textChars":2,"textLines":1,"bbox":[840,235,150,40]}
{"kind":"textbox","id":"sh/gv29g7q5","slide":4,"text":"利润是否真正改善","textPreview":"利润是否真正改善","textChars":8,"textLines":1,"bbox":[840,400,164,78]}
{"kind":"shape","id":"sh/fu9sn2p0","slide":4,"bbox":[1049,332,36,36]}
{"kind":"textbox","id":"sh/et0reh8f","slide":4,"text":"6","textPreview":"6","textChars":1,"textLines":1,"bbox":[1049,337,36,24]}
{"kind":"textbox","id":"sh/tsrqlc7u","slide":4,"text":"沉淀","textPreview":"沉淀","textChars":2,"textLines":1,"bbox":[1039,235,150,40]}
{"kind":"textbox","id":"sh/sri9s7q9","slide":4,"text":"更新企业最佳实践","textPreview":"更新企业最佳实践","textChars":8,"textLines":1,"bbox":[1039,400,164,78]}
{"kind":"shape","id":"sh/ilwf69kv","slide":4,"bbox":[42,552,1196,58]}
{"kind":"textbox","id":"sh/jm5gze1g","slide":4,"text":"关键不是“发现问题”,而是“把问题变成可复制的利润改善”。","textPreview":"关键不是“发现问题”,而是“把问题变成可复制的利润改善”。","textChars":29,"textLines":1,"bbox":[66,568,1148,30]}
{"kind":"notes","id":"nt/jyx0ra1s","slide":4,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/i107q5of","slide":5,"title":"匿名复合案例 · SKU 组合决策 Anonymous composite case · SKU portfolio","textShapes":15}
{"kind":"textbox","id":"sh/fe94nm1w","slide":5,"text":"匿名复合案例 · SKU 组合决策 Anonymous composite case · SKU portfolio","textPreview":"匿名复合案例 · SKU 组合决策 Anonymous composite case · SKU portfolio","textChars":59,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/dgbulwnm","slide":5,"text":"SKU 过多,往往增加的是复杂度和成本\nMore SKUs often mean more cost, not more choice.","textPreview":"SKU 过多,往往增加的是复杂度和成本 | More SKUs often mean more cost, not more choice.","textChars":68,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/cf2tcr61","slide":5,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/z2tcnm5s","slide":5,"text":"05","textPreview":"05","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/yhkbe1o7","slide":5,"text":"480","textPreview":"480","textChars":3,"textLines":1,"bbox":[42,182,190,72]}
{"kind":"textbox","id":"sh/l4bupwny","slide":5,"text":"在售 SKU","textPreview":"在售 SKU","textChars":6,"textLines":1,"bbox":[42,256,190,30]}
{"kind":"textbox","id":"sh/032tgr6d","slide":5,"text":"后 20% SKU 仅贡献约 3% 销售额,却持续占用库存资金。","textPreview":"后 20% SKU 仅贡献约 3% 销售额,却持续占用库存资金。","textChars":32,"textLines":1,"bbox":[262,190,800,76]}
{"kind":"shape","id":"sh/n6dcr65o","slide":5,"bbox":[42,328,270,170]}
{"kind":"textbox","id":"sh/m5kbi1oj","slide":5,"text":"37 个","textPreview":"37 个","textChars":4,"textLines":1,"bbox":[66,354,222,64]}
{"kind":"textbox","id":"sh/w32dkbuh","slide":5,"text":"低销量·低毛利·高损耗","textPreview":"低销量·低毛利·高损耗","textChars":11,"textLines":1,"bbox":[66,434,222,40]}
{"kind":"shape","id":"sh/x4vedgvm","slide":5,"bbox":[341,328,270,170]}
{"kind":"textbox","id":"sh/ahkvi1cb","slide":5,"text":"9 个","textPreview":"9 个","textChars":3,"textLines":1,"bbox":[365,354,222,64]}
{"kind":"textbox","id":"sh/v2twb6dw","slide":5,"text":"高销量但低贡献利润","textPreview":"高销量但低贡献利润","textChars":9,"textLines":1,"bbox":[365,434,222,40]}
{"kind":"shape","id":"sh/k7mxovud","slide":5,"bbox":[640,328,270,170]}
{"kind":"textbox","id":"sh/58vehgvy","slide":5,"text":"16 个","textPreview":"16 个","textChars":4,"textLines":1,"bbox":[664,354,222,64]}
{"kind":"textbox","id":"sh/i54fmlc7","slide":5,"text":"可共享或替换原料","textPreview":"可共享或替换原料","textChars":8,"textLines":1,"bbox":[664,434,222,40]}
{"kind":"shape","id":"sh/j6dwfqds","slide":5,"bbox":[939,328,270,170]}
{"kind":"textbox","id":"sh/sb6xsvu9","slide":5,"text":"22 个","textPreview":"22 个","textChars":4,"textLines":1,"bbox":[963,354,222,64]}
{"kind":"textbox","id":"sh/tcfel0vu","slide":5,"text":"价格带重叠","textPreview":"价格带重叠","textChars":5,"textLines":1,"bbox":[963,434,222,40]}
{"kind":"shape","id":"sh/hgrmpwj2","slide":5,"bbox":[42,535,1196,85]}
{"kind":"textbox","id":"sh/gfi5grih","slide":5,"text":"模拟测算:释放库存资金约 80 万元 · 年减少报损约 35 万元 · 综合毛利率提升约 0.6 个百分点","textPreview":"模拟测算:释放库存资金约 80 万元 · 年减少报损约 35 万元 · 综合毛利率提升约 0.6 个百分点","textChars":53,"textLines":1,"bbox":[68,558,1140,40]}
{"kind":"notes","id":"nt/i107q5of","slide":5,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/x8f69ofe","slide":6,"title":"匿名复合案例 · 门店 A-017 Anonymous composite case · Store A-017","textShapes":10}
{"kind":"textbox","id":"sh/svmt4v6t","slide":6,"text":"匿名复合案例 · 门店 A-017 Anonymous composite case · Store A-017","textPreview":"匿名复合案例 · 门店 A-017 Anonymous composite case · Store A-017","textChars":57,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/yhg7epsj","slide":6,"text":"排班的关键,是工时跟着客流走\nLabor hours should follow demand.","textPreview":"排班的关键,是工时跟着客流走 | Labor hours should follow demand.","textChars":48,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/zi98nu94","slide":6,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/87ipkzal","slide":6,"text":"06","textPreview":"06","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/98rqt4r6","slide":6,"bbox":[42,182,362,314]}
{"kind":"shape","id":"sh/ml07i9sv","slide":6,"bbox":[42,182,7,314]}
{"kind":"textbox","id":"sh/7m98ru9g","slide":6,"text":"发现","textPreview":"发现","textChars":2,"textLines":1,"bbox":[66,204,316,40]}
{"kind":"textbox","id":"sh/oryp8fah","slide":6,"text":"· 工作日上午存在闲置工时\n· 周五晚高峰经常缺人\n· 班次依据历史习惯\n· 加班集中在少数岗位","textPreview":"· 工作日上午存在闲置工时 | · 周五晚高峰经常缺人 | · 班次依据历史习惯 | · 加班集中在少数岗位","textChars":48,"textLines":4,"bbox":[66,256,316,222]}
{"kind":"shape","id":"sh/pc76hkr2","slide":6,"bbox":[458,182,362,314]}
{"kind":"shape","id":"sh/h4bupgn6","slide":6,"bbox":[458,182,7,314]}
{"kind":"textbox","id":"sh/w32twb6l","slide":6,"text":"动作","textPreview":"动作","textChars":2,"textLines":1,"bbox":[482,204,316,40]}
{"kind":"textbox","id":"sh/v2tcn650","slide":6,"text":"· 按半小时预测工作量\n· 调整早晚班起止时间\n· 高峰增加小时工\n· 备餐前移至客流爬升前","textPreview":"· 按半小时预测工作量 | · 调整早晚班起止时间 | · 高峰增加小时工 | · 备餐前移至客流爬升前","textChars":46,"textLines":4,"bbox":[482,256,316,222]}
{"kind":"shape","id":"sh/u1kbu1ov","slide":6,"bbox":[874,182,364,314]}
{"kind":"shape","id":"sh/5svutgni","slide":6,"bbox":[874,182,7,314]}
{"kind":"textbox","id":"sh/47mt0b6x","slide":6,"text":"验证","textPreview":"验证","textChars":2,"textLines":1,"bbox":[898,204,318,40]}
{"kind":"textbox","id":"sh/j6dcr65c","slide":6,"text":"同时监控:\n\n· 人工成本\n· 出品时效\n· 顾客满意度\n\n避免单纯压缩人力。","textPreview":"同时监控: | | · 人工成本 | · 出品时效 | · 顾客满意度 | | 避免单纯压缩人力。","textChars":39,"textLines":7,"bbox":[898,256,318,222]}
{"kind":"shape","id":"sh/i54bylor","slide":6,"bbox":[42,535,1196,85]}
{"kind":"textbox","id":"sh/twfux0ne","slide":6,"text":"模拟测算:单店每月节约 1.8 万元;复制到 60 家门店,年度改善空间约 1,296 万元。","textPreview":"模拟测算:单店每月节约 1.8 万元;复制到 60 家门店,年度改善空间约 1,296 万元。","textChars":47,"textLines":1,"bbox":[66,557,1148,42]}
{"kind":"notes","id":"nt/x8f69ofe","slide":6,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/gnmp4jqx","slide":7,"title":"匿名复合案例 · 营销活动 X Anonymous composite case · Campaign X","textShapes":17}
{"kind":"textbox","id":"sh/s3ml0v61","slide":7,"text":"匿名复合案例 · 营销活动 X Anonymous composite case · Campaign X","textPreview":"匿名复合案例 · 营销活动 X Anonymous composite case · Campaign X","textChars":54,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/cb2tkvap","slide":7,"text":"订单增长,不等于促销赚钱\nMore orders do not always mean a profitable campaign.","textPreview":"订单增长,不等于促销赚钱 | More orders do not always mean a profitable campaign.","textChars":66,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/dcbud0ra","slide":7,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ydkbm5sv","slide":7,"text":"07","textPreview":"07","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/zedcfa9g","slide":7,"bbox":[42,186,350,170]}
{"kind":"textbox","id":"sh/kzmdova1","slide":7,"text":"+23%","textPreview":"+23%","textChars":4,"textLines":1,"bbox":[66,212,302,64]}
{"kind":"textbox","id":"sh/l0vuh0rm","slide":7,"text":"订单增长","textPreview":"订单增长","textChars":4,"textLines":1,"bbox":[66,292,302,40]}
{"kind":"shape","id":"sh/eh0ba1sr","slide":7,"bbox":[42,378,350,170]}
{"kind":"textbox","id":"sh/fi9c369c","slide":7,"text":"负值","textPreview":"负值","textChars":2,"textLines":1,"bbox":[66,404,302,64]}
{"kind":"textbox","id":"sh/baxkjqlk","slide":7,"text":"穿透成本后的活动贡献利润","textPreview":"穿透成本后的活动贡献利润","textChars":12,"textLines":1,"bbox":[66,484,302,40]}
{"kind":"textbox","id":"sh/a9ojq5kz","slide":7,"text":"活动为什么亏钱","textPreview":"活动为什么亏钱","textChars":7,"textLines":1,"bbox":[454,186,360,40]}
{"kind":"textbox","id":"sh/xcz2l03q","slide":7,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[454,258,42,28]}
{"kind":"textbox","id":"sh/cbq1sv25","slide":7,"text":"低毛利商品占比上升","textPreview":"低毛利商品占比上升","textChars":9,"textLines":1,"bbox":[510,254,650,40]}
{"kind":"shape","id":"sh/n6x0fqlo","slide":7,"bbox":[510,300,650,0]}
{"kind":"textbox","id":"sh/25ojml43","slide":7,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[454,323,42,28]}
{"kind":"textbox","id":"sh/p8fih03e","slide":7,"text":"高价值会员获得无差别优惠","textPreview":"高价值会员获得无差别优惠","textChars":12,"textLines":1,"bbox":[510,319,650,40]}
{"kind":"shape","id":"sh/o761ov2t","slide":7,"bbox":[510,365,650,0]}
{"kind":"textbox","id":"sh/f2d0b6lc","slide":7,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[454,388,42,28]}
{"kind":"textbox","id":"sh/eh4jil4r","slide":7,"text":"促销订单替代了原价订单","textPreview":"促销订单替代了原价订单","textChars":11,"textLines":1,"bbox":[510,384,650,40]}
{"kind":"shape","id":"sh/id4ju1oz","slide":7,"bbox":[510,430,650,0]}
{"kind":"textbox","id":"sh/jedkn654","slide":7,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[454,453,42,28]}
{"kind":"textbox","id":"sh/4fm1wb6p","slide":7,"text":"只评价订单和营收,没有评价增量利润","textPreview":"只评价订单和营收,没有评价增量利润","textChars":17,"textLines":1,"bbox":[510,449,650,40]}
{"kind":"shape","id":"sh/50v2pgna","slide":7,"bbox":[510,495,650,0]}
{"kind":"shape","id":"sh/q143ylov","slide":7,"bbox":[454,544,746,67]}
{"kind":"textbox","id":"sh/r2dkrq5g","slide":7,"text":"用“每投入 1 元营销费用增加多少贡献利润”评价活动。","textPreview":"用“每投入 1 元营销费用增加多少贡献利润”评价活动。","textChars":27,"textLines":1,"bbox":[478,562,700,34]}
{"kind":"notes","id":"nt/gnmp4jqx","slide":7,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/fu1gfa1s","slide":8,"title":"匿名复合案例 · 门店 D-006 Anonymous composite case · Store D-006","textShapes":19}
{"kind":"textbox","id":"sh/07atgnmp","slide":8,"text":"匿名复合案例 · 门店 D-006 Anonymous composite case · Store D-006","textPreview":"匿名复合案例 · 门店 D-006 Anonymous composite case · Store D-006","textChars":57,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/18byd4zy","slide":8,"text":"关店前,先把四种选择算清楚\nCompare the options before deciding to close a store.","textPreview":"关店前,先把四种选择算清楚 | Compare the options before deciding to close a store.","textChars":67,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/g72x4zyd","slide":8,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ri9g7uhw","slide":8,"text":"08","textPreview":"08","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/6h0fypgb","slide":8,"bbox":[42,180,340,55]}
{"kind":"textbox","id":"sh/tkby9kzm","slide":8,"text":"方案","textPreview":"方案","textChars":2,"textLines":1,"bbox":[60,197,304,26]}
{"kind":"shape","id":"sh/sjix0zy1","slide":8,"bbox":[382,180,378,55]}
{"kind":"textbox","id":"sh/je9g3ahk","slide":8,"text":"12 个月模拟结果","textPreview":"12 个月模拟结果","textChars":9,"textLines":1,"bbox":[400,197,342,26]}
{"kind":"shape","id":"sh/id0fu50z","slide":8,"bbox":[760,180,478,55]}
{"kind":"textbox","id":"sh/o7ydoret","slide":8,"text":"决策建议","textPreview":"决策建议","textChars":4,"textLines":1,"bbox":[778,197,442,26]}
{"kind":"shape","id":"sh/98rehwve","slide":8,"bbox":[42,235,340,72]}
{"kind":"textbox","id":"sh/m5gvmhwn","slide":8,"text":"继续经营","textPreview":"继续经营","textChars":4,"textLines":1,"bbox":[60,256,304,35]}
{"kind":"shape","id":"sh/n6pwfmd8","slide":8,"bbox":[382,235,378,72]}
{"kind":"textbox","id":"sh/0jydkreh","slide":8,"text":"预计亏损 92 万","textPreview":"预计亏损 92 万","textChars":9,"textLines":1,"bbox":[400,256,342,35]}
{"kind":"shape","id":"sh/1k7edwv2","slide":8,"bbox":[760,235,478,72]}
{"kind":"textbox","id":"sh/ehgvihwr","slide":8,"text":"不建议","textPreview":"不建议","textChars":3,"textLines":1,"bbox":[778,256,442,35]}
{"kind":"shape","id":"sh/zipwbmdc","slide":8,"bbox":[42,307,340,72]}
{"kind":"textbox","id":"sh/kfixwbe1","slide":8,"text":"投入整改","textPreview":"投入整改","textChars":4,"textLines":1,"bbox":[60,328,304,35]}
{"kind":"shape","id":"sh/lgbepgvm","slide":8,"bbox":[382,307,378,72]}
{"kind":"textbox","id":"sh/tw7e9gnq","slide":8,"text":"预计亏损降至 35 万","textPreview":"预计亏损降至 35 万","textChars":11,"textLines":1,"bbox":[400,328,342,35]}
{"kind":"shape","id":"sh/svydgb65","slide":8,"bbox":[760,307,478,72]}
{"kind":"textbox","id":"sh/7u5w765k","slide":8,"text":"高风险,设止损线","textPreview":"高风险,设止损线","textChars":8,"textLines":1,"bbox":[778,328,442,35]}
{"kind":"shape","id":"sh/6twve1oz","slide":8,"bbox":[42,379,340,72]}
{"kind":"textbox","id":"sh/5sne5wne","slide":8,"text":"缩小面积","textPreview":"缩小面积","textChars":4,"textLines":1,"bbox":[60,400,304,35]}
{"kind":"shape","id":"sh/kredcr6t","slide":8,"bbox":[382,379,378,72]}
{"kind":"textbox","id":"sh/jq5w365o","slide":8,"text":"预计接近盈亏平衡","textPreview":"预计接近盈亏平衡","textChars":8,"textLines":1,"bbox":[400,400,342,35]}
{"kind":"shape","id":"sh/i5wva1o3","slide":8,"bbox":[760,379,478,72]}
{"kind":"textbox","id":"sh/x4ne1wni","slide":8,"text":"租约可重谈时考虑","textPreview":"租约可重谈时考虑","textChars":8,"textLines":1,"bbox":[778,400,442,35]}
{"kind":"shape","id":"sh/w3ed8r6x","slide":8,"bbox":[42,451,340,72]}
{"kind":"textbox","id":"sh/m9sb2x4v","slide":8,"text":"关停并迁移会员","textPreview":"关停并迁移会员","textChars":7,"textLines":1,"bbox":[60,472,304,35]}
{"kind":"shape","id":"sh/na1sb2lg","slide":8,"bbox":[382,451,378,72]}
{"kind":"textbox","id":"sh/8bat47ml","slide":8,"text":"预计减少亏损 76 万","textPreview":"预计减少亏损 76 万","textChars":11,"textLines":1,"bbox":[400,472,342,35]}
{"kind":"shape","id":"sh/9w3uds36","slide":8,"bbox":[760,451,478,72]}
{"kind":"textbox","id":"sh/y5sbed4j","slide":8,"text":"优先建议","textPreview":"优先建议","textChars":4,"textLines":1,"bbox":[778,472,442,35]}
{"kind":"textbox","id":"sh/z61s7il4","slide":8,"text":"AI 不替老板关店;它让经验判断具有数据依据、情景测算和退出预案。","textPreview":"AI 不替老板关店;它让经验判断具有数据依据、情景测算和退出预案。","textChars":33,"textLines":1,"bbox":[42,565,1160,44]}
{"kind":"notes","id":"nt/fu1gfa1s","slide":8,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/udsvah03","slide":9,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":19}
{"kind":"textbox","id":"sh/va103ep4","slide":9,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/1cfmhgne","slide":9,"text":"四级管理,各自看清该做的事\nOne operating view, four levels of accountability.","textPreview":"四级管理,各自看清该做的事 | One operating view, four levels of accountability.","textChars":64,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/0b65obm9","slide":9,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/nex4jq5k","slide":9,"text":"09","textPreview":"09","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/mdonql4z","slide":9,"bbox":[42,190,265,316]}
{"kind":"textbox","id":"sh/9gzml0nq","slide":9,"text":"老板","textPreview":"老板","textChars":2,"textLines":1,"bbox":[64,214,220,46]}
{"kind":"textbox","id":"sh/ofq5svm5","slide":9,"text":"看结果","textPreview":"看结果","textChars":3,"textLines":1,"bbox":[64,296,220,44]}
{"kind":"textbox","id":"sh/bih4na5w","slide":9,"text":"利润·风险·资源投向","textPreview":"利润·风险·资源投向","textChars":10,"textLines":1,"bbox":[64,386,220,72]}
{"kind":"textbox","id":"sh/ah8nu54b","slide":9,"text":"→","textPreview":"→","textChars":1,"textLines":1,"bbox":[310,323,30,36]}
{"kind":"shape","id":"sh/oza1gfyh","slide":9,"bbox":[341,190,265,316]}
{"kind":"textbox","id":"sh/p0ji9kf2","slide":9,"text":"总部","textPreview":"总部","textChars":2,"textLines":1,"bbox":[363,214,220,46]}
{"kind":"textbox","id":"sh/2xsjepgb","slide":9,"text":"找原因","textPreview":"找原因","textChars":3,"textLines":1,"bbox":[363,296,220,44]}
{"kind":"textbox","id":"sh/3y107axw","slide":9,"text":"跨区域对标·政策评估","textPreview":"跨区域对标·政策评估","textChars":10,"textLines":1,"bbox":[363,386,220,72]}
{"kind":"textbox","id":"sh/cnu1kzyd","slide":9,"text":"→","textPreview":"→","textChars":1,"textLines":1,"bbox":[609,323,30,36]}
{"kind":"shape","id":"sh/do3id4fy","slide":9,"bbox":[640,190,265,316]}
{"kind":"textbox","id":"sh/qlcjipgn","slide":9,"text":"区域","textPreview":"区域","textChars":2,"textLines":1,"bbox":[662,214,220,46]}
{"kind":"textbox","id":"sh/bml0buxs","slide":9,"text":"推整改","textPreview":"推整改","textChars":3,"textLines":1,"bbox":[662,296,220,44]}
{"kind":"textbox","id":"sh/0ru1ozyp","slide":9,"text":"门店分级·任务·验收","textPreview":"门店分级·任务·验收","textChars":10,"textLines":1,"bbox":[662,386,220,72]}
{"kind":"textbox","id":"sh/lsn2h4fa","slide":9,"text":"→","textPreview":"→","textChars":1,"textLines":1,"bbox":[908,323,30,36]}
{"kind":"shape","id":"sh/98ji147e","slide":9,"bbox":[939,190,265,316]}
{"kind":"textbox","id":"sh/87a18zqt","slide":9,"text":"店长","textPreview":"店长","textChars":2,"textLines":1,"bbox":[961,214,220,46]}
{"kind":"textbox","id":"sh/76h0zup8","slide":9,"text":"做动作","textPreview":"做动作","textChars":3,"textLines":1,"bbox":[961,296,220,44]}
{"kind":"textbox","id":"sh/ml8j6p8n","slide":9,"text":"日目标·偏差·行动建议","textPreview":"日目标·偏差·行动建议","textChars":11,"textLines":1,"bbox":[961,386,220,72]}
{"kind":"shape","id":"sh/hcji5o7a","slide":9,"bbox":[42,550,1196,60]}
{"kind":"textbox","id":"sh/wba1cjqp","slide":9,"text":"结果回到经营大盘:执行不是终点,改善结果才是。","textPreview":"结果回到经营大盘:执行不是终点,改善结果才是。","textChars":23,"textLines":1,"bbox":[66,567,1148,30]}
{"kind":"notes","id":"nt/udsvah03","slide":9,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/m90b6t0r","slide":10,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":7}
{"kind":"textbox","id":"sh/r6pcv6lw","slide":10,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/xc3mho32","slide":10,"text":"AI 给依据,经营决策仍由管理者负责\nAI provides evidence. Management owns the decision.","textPreview":"AI 给依据,经营决策仍由管理者负责 | AI provides evidence. Management owns the decision.","textChars":70,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/cbu58j2h","slide":10,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/zelojyl8","slide":10,"text":"10","textPreview":"10","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/ydcnatkn","slide":10,"bbox":[42,182,560,366]}
{"kind":"shape","id":"sh/l036l83y","slide":10,"bbox":[42,182,7,366]}
{"kind":"textbox","id":"sh/kzu5c32t","slide":10,"text":"AI 可以承担","textPreview":"AI 可以承担","textChars":7,"textLines":1,"bbox":[66,204,514,40]}
{"kind":"textbox","id":"sh/725onyl4","slide":10,"text":"· 理解并关联跨系统数据\n· 持续扫描异常\n· 穿透至门店、SKU、班次和订单\n· 调用行业规则与历史案例\n· 推演方案对利润和现金流的影响\n· 跟踪执行并验证结果","textPreview":"· 理解并关联跨系统数据 | · 持续扫描异常 | · 穿透至门店、SKU、班次和订单 | · 调用行业规则与历史案例 | · 推演方案对利润和现金流的影响 | · 跟踪执行并验证结果","textChars":82,"textLines":6,"bbox":[66,256,514,274]}
{"kind":"shape","id":"sh/m1cnetkj","slide":10,"bbox":[678,182,560,366]}
{"kind":"shape","id":"sh/s7yt4b21","slide":10,"bbox":[678,182,7,366]}
{"kind":"textbox","id":"sh/d87uxg3m","slide":10,"text":"必须由管理者决定","textPreview":"必须由管理者决定","textChars":8,"textLines":1,"bbox":[702,204,514,40]}
{"kind":"textbox","id":"sh/q5gb21kb","slide":10,"text":"· 价格调整\n· 人员处置\n· 供应商更换\n· 门店迁址与关停\n· 重大资源投入\n\n所有高影响决策都应留下依据、审批与执行记录。","textPreview":"· 价格调整 | · 人员处置 | · 供应商更换 | · 门店迁址与关停 | · 重大资源投入 | | 所有高影响决策都应留下依据、审批与执行记录。","textChars":64,"textLines":7,"bbox":[702,256,514,274]}
{"kind":"notes","id":"nt/m90b6t0r","slide":10,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/jetc3ut0","slide":11,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":24}
{"kind":"textbox","id":"sh/g3qtkj6l","slide":11,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/xcryxg7y","slide":11,"text":"BI 解释过去,玄谋智脑推动下一步\nBI explains the past. Xuanmou drives the next action.","textPreview":"BI 解释过去,玄谋智脑推动下一步 | BI explains the past. Xuanmou drives the next action.","textChars":71,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/wbih4b6d","slide":11,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/n69grmpw","slide":11,"text":"11","textPreview":"11","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/250zy18b","slide":11,"bbox":[42,170,228,50]}
{"kind":"textbox","id":"sh/98rytw72","slide":11,"text":"维度","textPreview":"维度","textChars":2,"textLines":1,"bbox":[58,185,196,25]}
{"kind":"shape","id":"sh/o7ih0r6h","slide":11,"bbox":[270,170,410,50]}
{"kind":"textbox","id":"sh/72t03qp0","slide":11,"text":"普通 BI","textPreview":"普通 BI","textChars":5,"textLines":1,"bbox":[286,185,378,25]}
{"kind":"shape","id":"sh/61kzalof","slide":11,"bbox":[680,170,558,50]}
{"kind":"textbox","id":"sh/ofqtgnyt","slide":11,"text":"玄谋智脑","textPreview":"玄谋智脑","textChars":4,"textLines":1,"bbox":[696,185,526,25]}
{"kind":"shape","id":"sh/9gza9sze","slide":11,"bbox":[42,220,228,67]}
{"kind":"textbox","id":"sh/mdobedg3","slide":11,"text":"定位","textPreview":"定位","textChars":2,"textLines":1,"bbox":[58,238,196,38]}
{"kind":"shape","id":"sh/nehs7iho","slide":11,"bbox":[270,220,410,67]}
{"kind":"textbox","id":"sh/0b6tc3yx","slide":11,"text":"展示报表","textPreview":"展示报表","textChars":4,"textLines":1,"bbox":[286,238,378,38]}
{"kind":"shape","id":"sh/1cfa58zi","slide":11,"bbox":[680,220,558,67]}
{"kind":"textbox","id":"sh/epobatgr","slide":11,"text":"驱动经营决策与改善","textPreview":"驱动经营决策与改善","textChars":9,"textLines":1,"bbox":[696,238,526,38]}
{"kind":"shape","id":"sh/zaxs3yhc","slide":11,"bbox":[42,287,228,67]}
{"kind":"textbox","id":"sh/cn6t83y1","slide":11,"text":"业务语义","textPreview":"业务语义","textChars":4,"textLines":1,"bbox":[58,305,196,38]}
{"kind":"shape","id":"sh/dofa18z6","slide":11,"bbox":[270,287,410,67]}
{"kind":"textbox","id":"sh/tsnip0ny","slide":11,"text":"字段和指标","textPreview":"字段和指标","textChars":5,"textLines":1,"bbox":[286,305,378,38]}
{"kind":"shape","id":"sh/87ehgv6d","slide":11,"bbox":[680,287,558,67]}
{"kind":"textbox","id":"sh/7650nq5s","slide":11,"text":"门店、商品、人员、会员等行业本体","textPreview":"门店、商品、人员、会员等行业本体","textChars":16,"textLines":1,"bbox":[696,305,526,38]}
{"kind":"shape","id":"sh/65wzelo7","slide":11,"bbox":[42,354,228,67]}
{"kind":"textbox","id":"sh/l43ilgn2","slide":11,"text":"问题发现","textPreview":"问题发现","textChars":4,"textLines":1,"bbox":[58,372,196,38]}
{"kind":"shape","id":"sh/k3uhcb6h","slide":11,"bbox":[270,354,410,67]}
{"kind":"textbox","id":"sh/j2lgjq5w","slide":11,"text":"人主动看数据","textPreview":"人主动看数据","textChars":6,"textLines":1,"bbox":[286,372,378,38]}
{"kind":"shape","id":"sh/y1czalob","slide":11,"bbox":[680,354,558,67]}
{"kind":"textbox","id":"sh/p07ixkn6","slide":11,"text":"系统持续发现、分级与推送","textPreview":"系统持续发现、分级与推送","textChars":12,"textLines":1,"bbox":[696,372,526,38]}
{"kind":"shape","id":"sh/4zyhofml","slide":11,"bbox":[42,421,228,67]}
{"kind":"textbox","id":"sh/m58fih43","slide":11,"text":"问题处理","textPreview":"问题处理","textChars":4,"textLines":1,"bbox":[58,439,196,38]}
{"kind":"shape","id":"sh/n61wbmlo","slide":11,"bbox":[270,421,410,67]}
{"kind":"textbox","id":"sh/o7axk7m9","slide":11,"text":"报告异常","textPreview":"报告异常","textChars":4,"textLines":1,"bbox":[286,439,378,38]}
{"kind":"shape","id":"sh/98jedc3u","slide":11,"bbox":[680,421,558,67]}
{"kind":"textbox","id":"sh/eh8fex47","slide":11,"text":"归因、测算、方案和整改任务","textPreview":"归因、测算、方案和整改任务","textChars":13,"textLines":1,"bbox":[696,439,526,38]}
{"kind":"shape","id":"sh/z2hw72lc","slide":11,"bbox":[42,488,228,67]}
{"kind":"textbox","id":"sh/03qxg7mx","slide":11,"text":"结果验证","textPreview":"结果验证","textChars":4,"textLines":1,"bbox":[58,506,196,38]}
{"kind":"shape","id":"sh/14ze9c3i","slide":11,"bbox":[270,488,410,67]}
{"kind":"textbox","id":"sh/ydcfq1kb","slide":11,"text":"通常不跟踪","textPreview":"通常不跟踪","textChars":5,"textLines":1,"bbox":[286,506,378,38]}
{"kind":"shape","id":"sh/jylwj6lw","slide":11,"bbox":[680,488,558,67]}
{"kind":"textbox","id":"sh/3qhsfypc","slide":11,"text":"验证改善并更新最佳实践","textPreview":"验证改善并更新最佳实践","textChars":11,"textLines":1,"bbox":[696,506,526,38]}
{"kind":"shape","id":"sh/ip8bmtor","slide":11,"bbox":[42,555,228,67]}
{"kind":"textbox","id":"sh/5sjah872","slide":11,"text":"长期价值","textPreview":"长期价值","textChars":4,"textLines":1,"bbox":[58,573,196,38]}
{"kind":"shape","id":"sh/4rato36h","slide":11,"bbox":[270,555,410,67]}
{"kind":"textbox","id":"sh/v2hsbyp0","slide":11,"text":"报表越来越多","textPreview":"报表越来越多","textChars":6,"textLines":1,"bbox":[286,573,378,38]}
{"kind":"shape","id":"sh/u18bit8f","slide":11,"bbox":[680,555,558,67]}
{"kind":"textbox","id":"sh/h4zado76","slide":11,"text":"行业模型与企业知识越用越成熟","textPreview":"行业模型与企业知识越用越成熟","textChars":14,"textLines":1,"bbox":[696,573,526,38]}
{"kind":"notes","id":"nt/jetc3ut0","slide":11,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/8f2psfyx","slide":12,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":23}
{"kind":"textbox","id":"sh/alwbitsn","slide":12,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/1gbm9s3a","slide":12,"text":"五项基础能力,支撑门店规模化管理\nFive capabilities that support scalable operations.","textPreview":"五项基础能力,支撑门店规模化管理 | Five capabilities that support scalable operations.","textChars":68,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/0f2lgnmp","slide":12,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ra943il8","slide":12,"text":"12","textPreview":"12","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/q903ad4n","slide":12,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[42,185,54,28]}
{"kind":"textbox","id":"sh/dcbm583y","slide":12,"text":"数据资产化","textPreview":"数据资产化","textChars":5,"textLines":1,"bbox":[118,171,250,54]}
{"kind":"textbox","id":"sh/sb2lcnmd","slide":12,"text":"数据通起来","textPreview":"数据通起来","textChars":5,"textLines":1,"bbox":[422,171,250,54]}
{"kind":"textbox","id":"sh/b6d4f2lc","slide":12,"text":"一个数字、一个来源","textPreview":"一个数字、一个来源","textChars":9,"textLines":1,"bbox":[720,171,450,54]}
{"kind":"shape","id":"sh/a543mx4r","slide":12,"bbox":[118,238,1050,0]}
{"kind":"textbox","id":"sh/wvupgz6t","slide":12,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[42,274,54,28]}
{"kind":"textbox","id":"sh/xw3q94ne","slide":12,"text":"运营指标化","textPreview":"运营指标化","textChars":5,"textLines":1,"bbox":[118,260,250,54]}
{"kind":"textbox","id":"sh/atc7epon","slide":12,"text":"问题浮出来","textPreview":"问题浮出来","textChars":5,"textLines":1,"bbox":[422,260,250,54]}
{"kind":"textbox","id":"sh/bulo7u58","slide":12,"text":"异常能穿透到根因","textPreview":"异常能穿透到根因","textChars":8,"textLines":1,"bbox":[720,260,450,54]}
{"kind":"shape","id":"sh/orapcf6h","slide":12,"bbox":[118,327,1050,0]}
{"kind":"textbox","id":"sh/9sj65kn2","slide":12,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[42,363,54,28]}
{"kind":"textbox","id":"sh/mps7a5or","slide":12,"text":"战略穿透化","textPreview":"战略穿透化","textChars":5,"textLines":1,"bbox":[118,349,250,54]}
{"kind":"textbox","id":"sh/nq1o3a5w","slide":12,"text":"目标落下去","textPreview":"目标落下去","textChars":5,"textLines":1,"bbox":[422,349,250,54]}
{"kind":"textbox","id":"sh/0nap8f6l","slide":12,"text":"战略到区域、门店和个人","textPreview":"战略到区域、门店和个人","textChars":11,"textLines":1,"bbox":[720,349,450,54]}
{"kind":"shape","id":"sh/1oj61kn6","slide":12,"bbox":[118,416,1050,0]}
{"kind":"textbox","id":"sh/hkbm5wzu","slide":12,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[42,452,54,28]}
{"kind":"textbox","id":"sh/gj25cry9","slide":12,"text":"态势感知化","textPreview":"态势感知化","textChars":5,"textLines":1,"bbox":[118,438,250,54]}
{"kind":"textbox","id":"sh/fit436ho","slide":12,"text":"风险早知道","textPreview":"风险早知道","textChars":5,"textLines":1,"bbox":[422,438,250,54]}
{"kind":"textbox","id":"sh/uh0na1g3","slide":12,"text":"从事后救火到事前预防","textPreview":"从事后救火到事前预防","textChars":10,"textLines":1,"bbox":[720,438,450,54]}
{"kind":"shape","id":"sh/tgrm1wzy","slide":12,"bbox":[118,505,1050,0]}
{"kind":"textbox","id":"sh/sfi58ryd","slide":12,"text":"05","textPreview":"05","textChars":2,"textLines":1,"bbox":[42,541,54,28]}
{"kind":"textbox","id":"sh/7u94zmhs","slide":12,"text":"知识沉淀化","textPreview":"知识沉淀化","textChars":5,"textLines":1,"bbox":[118,527,250,54]}
{"kind":"textbox","id":"sh/6t0n6hg7","slide":12,"text":"组织越来越聪明","textPreview":"组织越来越聪明","textChars":7,"textLines":1,"bbox":[422,527,250,54]}
{"kind":"textbox","id":"sh/dcv6dgz2","slide":12,"text":"优秀能力不再依赖少数人","textPreview":"优秀能力不再依赖少数人","textChars":11,"textLines":1,"bbox":[720,527,450,54]}
{"kind":"shape","id":"sh/cbm5kbyh","slide":12,"bbox":[118,594,1050,0]}
{"kind":"notes","id":"nt/8f2psfyx","slide":12,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/hgzapcr6","slide":13,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":15}
{"kind":"textbox","id":"sh/3yxgbqdg","slide":13,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/q50nydsj","slide":13,"text":"门店越多,复制优秀做法的价值越大\nThe larger the network, the greater the value of replication.","textPreview":"门店越多,复制优秀做法的价值越大 | The larger the network, the greater the value of replication.","textChars":78,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/bq9orito","slide":13,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/o3i5w3ad","slide":13,"text":"13","textPreview":"13","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/p4r6p8by","slide":13,"bbox":[42,182,360,250]}
{"kind":"shape","id":"sh/21gnuts7","slide":13,"bbox":[42,182,7,250]}
{"kind":"textbox","id":"sh/32ponyts","slide":13,"text":"不依赖能人","textPreview":"不依赖能人","textChars":5,"textLines":1,"bbox":[66,204,314,40]}
{"kind":"textbox","id":"sh/gzy5s3a1","slide":13,"text":"优秀店长的做法沉淀为规则、案例和 SOP。","textPreview":"优秀店长的做法沉淀为规则、案例和 SOP。","textChars":21,"textLines":1,"bbox":[66,256,314,158]}
{"kind":"shape","id":"sh/1076lobm","slide":13,"bbox":[443,182,360,250]}
{"kind":"shape","id":"sh/hcfy9k3u","slide":13,"bbox":[443,182,7,250]}
{"kind":"textbox","id":"sh/gb6x0zm9","slide":13,"text":"扩张不失控","textPreview":"扩张不失控","textChars":5,"textLines":1,"bbox":[467,204,314,40]}
{"kind":"textbox","id":"sh/vaxg7ulo","slide":13,"text":"验证有效的改善方案,可按门店特征分类复制。","textPreview":"验证有效的改善方案,可按门店特征分类复制。","textChars":21,"textLines":1,"bbox":[467,256,314,158]}
{"kind":"shape","id":"sh/u9ofyp43","slide":13,"bbox":[844,182,360,250]}
{"kind":"shape","id":"sh/t8fy5k3i","slide":13,"bbox":[844,182,7,250]}
{"kind":"textbox","id":"sh/876xwfmx","slide":13,"text":"能力持续复利","textPreview":"能力持续复利","textChars":6,"textLines":1,"bbox":[868,204,314,40]}
{"kind":"textbox","id":"sh/7mdg3als","slide":13,"text":"场景、模型、AI 建议与决策反馈相互增强。","textPreview":"场景、模型、AI 建议与决策反馈相互增强。","textChars":21,"textLines":1,"bbox":[868,256,314,158]}
{"kind":"shape","id":"sh/6l4fu547","slide":13,"bbox":[120,520,980,0]}
{"kind":"shape","id":"sh/lkvy103m","slide":13,"bbox":[104,502,38,38]}
{"kind":"textbox","id":"sh/kjmxsfm1","slide":13,"text":"30 家","textPreview":"30 家","textChars":4,"textLines":1,"bbox":[94,555,150,28]}
{"kind":"textbox","id":"sh/cnqh8fux","slide":13,"text":"靠人盯","textPreview":"靠人盯","textChars":3,"textLines":1,"bbox":[94,589,170,24]}
{"kind":"shape","id":"sh/xozyhkbi","slide":13,"bbox":[584,502,38,38]}
{"kind":"textbox","id":"sh/q18f65cr","slide":13,"text":"100 家","textPreview":"100 家","textChars":5,"textLines":1,"bbox":[574,555,150,28]}
{"kind":"textbox","id":"sh/bmhgfatc","slide":13,"text":"靠机制","textPreview":"靠机制","textChars":3,"textLines":1,"bbox":[574,589,170,24]}
{"kind":"shape","id":"sh/oz6x4vul","slide":13,"bbox":[1064,502,38,38]}
{"kind":"textbox","id":"sh/p0zyd0b6","slide":13,"text":"300 家","textPreview":"300 家","textChars":5,"textLines":1,"bbox":[1054,555,150,28]}
{"kind":"textbox","id":"sh/2xof2lcv","slide":13,"text":"靠模型复制","textPreview":"靠模型复制","textChars":5,"textLines":1,"bbox":[1054,589,170,24]}
{"kind":"notes","id":"nt/hgzapcr6","slide":13,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/6lsnupw7","slide":14,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":8}
{"kind":"textbox","id":"sh/kre1k3y9","slide":14,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/xc7eds76","slide":14,"text":"真正的数据资产,是可追溯的经营能力\nA real data asset is a traceable operating capability.","textPreview":"真正的数据资产,是可追溯的经营能力 | A real data asset is a traceable operating capability.","textChars":72,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/wbydknq1","slide":14,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/jepwf2pc","slide":14,"text":"14","textPreview":"14","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/idgvmx8r","slide":14,"bbox":[42,180,560,365]}
{"kind":"shape","id":"sh/5grehs7i","slide":14,"bbox":[42,180,7,365]}
{"kind":"textbox","id":"sh/kfidonqx","slide":14,"text":"企业数据资产","textPreview":"企业数据资产","textChars":6,"textLines":1,"bbox":[66,202,514,40]}
{"kind":"textbox","id":"sh/zi5c3y98","slide":14,"text":"· 统一指标口径与责任关系\n· 门店、商品、人员、会员、供应商本体\n· 行业规则与异常模式\n· 决策、执行与验证结果\n· 最佳实践与风险知识","textPreview":"· 统一指标口径与责任关系 | · 门店、商品、人员、会员、供应商本体 | · 行业规则与异常模式 | · 决策、执行与验证结果 | · 最佳实践与风险知识","textChars":70,"textLines":5,"bbox":[66,254,514,273]}
{"kind":"shape","id":"sh/ehwvat8n","slide":14,"bbox":[678,180,560,365]}
{"kind":"shape","id":"sh/c3e1gjyd","slide":14,"bbox":[678,180,7,365]}
{"kind":"textbox","id":"sh/x4ni9ofy","slide":14,"text":"融资与尽调支持","textPreview":"融资与尽调支持","textChars":7,"textLines":1,"bbox":[702,202,514,40]}
{"kind":"textbox","id":"sh/a1wze9g7","slide":14,"text":"· 门店级损益与现金流\n· 收入稳定性分析\n· 风险预警与整改记录\n· 未来经营预测\n· 更完整、可追溯的经营证明","textPreview":"· 门店级损益与现金流 | · 收入稳定性分析 | · 风险预警与整改记录 | · 未来经营预测 | · 更完整、可追溯的经营证明","textChars":57,"textLines":5,"bbox":[702,254,514,273]}
{"kind":"textbox","id":"sh/b2507exs","slide":14,"text":"边界:提供数据与分析支持,不承诺银行授信或融资结果。","textPreview":"边界:提供数据与分析支持,不承诺银行授信或融资结果。","textChars":26,"textLines":1,"bbox":[42,578,1000,34]}
{"kind":"notes","id":"nt/6lsnupw7","slide":14,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/vaxsvy10","slide":15,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":15}
{"kind":"textbox","id":"sh/cbuh8nmh","slide":15,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/547mhg3m","slide":15,"text":"生产数据必须留在清晰的安全边界内\nProduction data must remain within clear security boundaries.","textPreview":"生产数据必须留在清晰的安全边界内 | Production data must remain within clear security boundaries.","textChars":78,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/k3y5ov21","slide":15,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/76p4jqls","slide":15,"text":"15","textPreview":"15","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/65gnqlk7","slide":15,"bbox":[42,180,360,170]}
{"kind":"shape","id":"sh/t87ml0ji","slide":15,"bbox":[42,180,7,170]}
{"kind":"textbox","id":"sh/s7y5sv2x","slide":15,"text":"部署边界","textPreview":"部署边界","textChars":4,"textLines":1,"bbox":[66,202,314,40]}
{"kind":"textbox","id":"sh/na5476l8","slide":15,"text":"不替代现有交易系统,只读或受控对接。","textPreview":"不替代现有交易系统,只读或受控对接。","textChars":18,"textLines":1,"bbox":[66,254,314,78]}
{"kind":"shape","id":"sh/m9c3e1kn","slide":15,"bbox":[443,180,360,170]}
{"kind":"shape","id":"sh/wrm9kvep","slide":15,"bbox":[443,180,7,170]}
{"kind":"textbox","id":"sh/hsvat0fa","slide":15,"text":"最小权限","textPreview":"最小权限","textChars":4,"textLines":1,"bbox":[467,202,314,40]}
{"kind":"textbox","id":"sh/upkrilwj","slide":15,"text":"老板、总部、区域、门店按职责查看。","textPreview":"老板、总部、区域、门店按职责查看。","textChars":17,"textLines":1,"bbox":[467,254,314,78]}
{"kind":"shape","id":"sh/vqdsrqx4","slide":15,"bbox":[844,180,360,170]}
{"kind":"shape","id":"sh/4vm9ovel","slide":15,"bbox":[844,180,7,170]}
{"kind":"textbox","id":"sh/5wvax0f6","slide":15,"text":"敏感保护","textPreview":"敏感保护","textChars":4,"textLines":1,"bbox":[868,202,314,40]}
{"kind":"textbox","id":"sh/it4rm5wv","slide":15,"text":"会员、薪酬、财务明细分级、脱敏与审计。","textPreview":"会员、薪酬、财务明细分级、脱敏与审计。","textChars":19,"textLines":1,"bbox":[868,254,314,78]}
{"kind":"shape","id":"sh/judsvqxg","slide":15,"bbox":[42,390,360,170]}
{"kind":"shape","id":"sh/0z29cbyh","slide":15,"bbox":[42,390,7,170]}
{"kind":"textbox","id":"sh/l0bqlgf2","slide":15,"text":"AI 可追溯","textPreview":"AI 可追溯","textChars":6,"textLines":1,"bbox":[66,412,314,40]}
{"kind":"textbox","id":"sh/1kjyt83e","slide":15,"text":"重要结论显示依据、时间、路径和适用边界。","textPreview":"重要结论显示依据、时间、路径和适用边界。","textChars":20,"textLines":1,"bbox":[66,464,314,78]}
{"kind":"shape","id":"sh/gjax03m9","slide":15,"bbox":[443,390,360,170]}
{"kind":"shape","id":"sh/fi1grylo","slide":15,"bbox":[443,390,7,170]}
{"kind":"textbox","id":"sh/ehsfyt43","slide":15,"text":"人工审批","textPreview":"人工审批","textChars":4,"textLines":1,"bbox":[467,412,314,40]}
{"kind":"textbox","id":"sh/p8jyx83q","slide":15,"text":"高影响决策必须经有权限的管理者审批。","textPreview":"高影响决策必须经有权限的管理者审批。","textChars":18,"textLines":1,"bbox":[467,464,314,78]}
{"kind":"shape","id":"sh/o7ah4nm5","slide":15,"bbox":[844,390,360,170]}
{"kind":"shape","id":"sh/361gvilk","slide":15,"bbox":[844,390,7,170]}
{"kind":"textbox","id":"sh/25sf2d4z","slide":15,"text":"全程留痕","textPreview":"全程留痕","textChars":4,"textLines":1,"bbox":[868,412,314,40]}
{"kind":"textbox","id":"sh/dc3y1s3m","slide":15,"text":"访问、建议、修改、审批和执行结果均可审计。","textPreview":"访问、建议、修改、审批和执行结果均可审计。","textChars":21,"textLines":1,"bbox":[868,464,314,78]}
{"kind":"notes","id":"nt/vaxsvy10","slide":15,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/gny5sjyp","slide":16,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":19}
{"kind":"textbox","id":"sh/ih0jedob","slide":16,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/8z2h8bq1","slide":16,"text":"先用 8 周证明价值,再决定扩大范围\nProve the value in eight weeks before scaling.","textPreview":"先用 8 周证明价值,再决定扩大范围 | Prove the value in eight weeks before scaling.","textChars":65,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/9kby1g7m","slide":16,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ytkf2h8j","slide":16,"text":"16","textPreview":"16","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/zutgvm94","slide":16,"bbox":[66,340,1100,0]}
{"kind":"shape","id":"sh/kv2h4rqp","slide":16,"bbox":[54,322,38,38]}
{"kind":"textbox","id":"sh/lwbyxwra","slide":16,"text":"第 1 周","textPreview":"第 1 周","textChars":5,"textLines":1,"bbox":[49,206,200,28]}
{"kind":"textbox","id":"sh/ip4zel83","slide":16,"text":"选定利润专项","textPreview":"选定利润专项","textChars":6,"textLines":1,"bbox":[49,250,205,55]}
{"kind":"textbox","id":"sh/3qdg7qpo","slide":16,"text":"基线·口径·责任人","textPreview":"基线·口径·责任人","textChars":9,"textLines":1,"bbox":[49,394,205,84]}
{"kind":"shape","id":"sh/fm1gzq5o","slide":16,"bbox":[293,322,38,38]}
{"kind":"textbox","id":"sh/e1sf65o3","slide":16,"text":"第 1—2 周","textPreview":"第 1—2 周","textChars":7,"textLines":1,"bbox":[288,206,200,28]}
{"kind":"textbox","id":"sh/1ojy10ne","slide":16,"text":"连接现有数据","textPreview":"连接现有数据","textChars":6,"textLines":1,"bbox":[288,250,205,55]}
{"kind":"textbox","id":"sh/gnax8v6t","slide":16,"text":"数据清单·质量·统一口径","textPreview":"数据清单·质量·统一口径","textChars":12,"textLines":1,"bbox":[288,394,205,84]}
{"kind":"shape","id":"sh/nqlg3a5k","slide":16,"bbox":[532,322,38,38]}
{"kind":"textbox","id":"sh/2pcfa5oz","slide":16,"text":"第 3—4 周","textPreview":"第 3—4 周","textChars":7,"textLines":1,"bbox":[527,206,200,28]}
{"kind":"textbox","id":"sh/ps3y5knq","slide":16,"text":"发现机会与根因","textPreview":"发现机会与根因","textChars":7,"textLines":1,"bbox":[527,250,205,55]}
{"kind":"textbox","id":"sh/oruhcf65","slide":16,"text":"异常·影响金额·证据","textPreview":"异常·影响金额·证据","textChars":10,"textLines":1,"bbox":[527,394,205,84]}
{"kind":"shape","id":"sh/bulg7u5g","slide":16,"bbox":[771,322,38,38]}
{"kind":"textbox","id":"sh/atczepob","slide":16,"text":"第 5—6 周","textPreview":"第 5—6 周","textChars":7,"textLines":1,"bbox":[766,206,200,28]}
{"kind":"textbox","id":"sh/mpgj6t8j","slide":16,"text":"推动整改","textPreview":"推动整改","textChars":4,"textLines":1,"bbox":[766,250,205,55]}
{"kind":"textbox","id":"sh/7qp0zepo","slide":16,"text":"任务·期限·执行记录","textPreview":"任务·期限·执行记录","textChars":10,"textLines":1,"bbox":[766,394,205,84]}
{"kind":"shape","id":"sh/8by18jq9","slide":16,"bbox":[1010,322,38,38]}
{"kind":"textbox","id":"sh/9c7i1o7u","slide":16,"text":"第 7—8 周","textPreview":"第 7—8 周","textChars":7,"textLines":1,"bbox":[1005,206,200,28]}
{"kind":"textbox","id":"sh/ylwj2987","slide":16,"text":"验证并复制","textPreview":"验证并复制","textChars":5,"textLines":1,"bbox":[1005,250,205,55]}
{"kind":"textbox","id":"sh/zm50veps","slide":16,"text":"改善金额·验收·最佳实践","textPreview":"改善金额·验收·最佳实践","textChars":12,"textLines":1,"bbox":[1005,394,205,84]}
{"kind":"shape","id":"sh/kne14jqd","slide":16,"bbox":[42,550,1196,60]}
{"kind":"textbox","id":"sh/lo7ixo7y","slide":16,"text":"优先选择:数据可获得 · 影响可测算 · 动作可执行 · 八周可验证。","textPreview":"优先选择:数据可获得 · 影响可测算 · 动作可执行 · 八周可验证。","textChars":35,"textLines":1,"bbox":[66,567,1148,30]}
{"kind":"notes","id":"nt/gny5sjyp","slide":16,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/14bup87q","slide":17,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":19}
{"kind":"textbox","id":"sh/ytc7a1gv","slide":17,"text":"玄谋智脑 · 连锁企业经营决策","textPreview":"玄谋智脑 · 连锁企业经营决策","textChars":15,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/1c7e50ni","slide":17,"text":"验收看经营改善,不看功能数量\nMeasure business improvement, not feature count.","textPreview":"验收看经营改善,不看功能数量 | Measure business improvement, not feature count.","textChars":63,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/gbedwfmx","slide":17,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/rm5czq50","slide":17,"text":"17","textPreview":"17","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/6lwvql4v","slide":17,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[42,188,50,26]}
{"kind":"textbox","id":"sh/t8ne10n6","slide":17,"text":"经营结果","textPreview":"经营结果","textChars":4,"textLines":1,"bbox":[112,174,230,48]}
{"kind":"textbox","id":"sh/snedsvml","slide":17,"text":"贡献利润·成本·损耗·库存资金","textPreview":"贡献利润·成本·损耗·库存资金","textChars":15,"textLines":1,"bbox":[395,174,760,48]}
{"kind":"shape","id":"sh/jilcvq54","slide":17,"bbox":[112,239,1040,0]}
{"kind":"textbox","id":"sh/ihcvml4j","slide":17,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[42,274,50,26]}
{"kind":"textbox","id":"sh/4by9or6l","slide":17,"text":"问题发现","textPreview":"问题发现","textChars":4,"textLines":1,"bbox":[112,260,230,48]}
{"kind":"textbox","id":"sh/pc7qhwn6","slide":17,"text":"发现周期·有效异常率·影响覆盖","textPreview":"发现周期·有效异常率·影响覆盖","textChars":15,"textLines":1,"bbox":[395,260,760,48]}
{"kind":"shape","id":"sh/29grm1of","slide":17,"bbox":[112,325,1040,0]}
{"kind":"textbox","id":"sh/3ap8fm50","slide":17,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[42,360,50,26]}
{"kind":"textbox","id":"sh/gnepkr69","slide":17,"text":"执行闭环","textPreview":"执行闭环","textChars":4,"textLines":1,"bbox":[112,346,230,48]}
{"kind":"textbox","id":"sh/honqdwnu","slide":17,"text":"接收率·按期完成率·整改有效率","textPreview":"接收率·按期完成率·整改有效率","textChars":15,"textLines":1,"bbox":[395,346,760,48]}
{"kind":"shape","id":"sh/ulw7ihoj","slide":17,"bbox":[112,411,1040,0]}
{"kind":"textbox","id":"sh/fm58bm54","slide":17,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[42,446,50,26]}
{"kind":"textbox","id":"sh/0ji9wb6t","slide":17,"text":"组织复制","textPreview":"组织复制","textChars":4,"textLines":1,"bbox":[112,432,230,48]}
{"kind":"textbox","id":"sh/14rqpgne","slide":17,"text":"复制门店数·成功率·新店导入时间","textPreview":"复制门店数·成功率·新店导入时间","textChars":16,"textLines":1,"bbox":[395,432,760,48]}
{"kind":"shape","id":"sh/90nq9gfi","slide":17,"bbox":[112,497,1040,0]}
{"kind":"textbox","id":"sh/8ze9gbyx","slide":17,"text":"05","textPreview":"05","textChars":2,"textLines":1,"bbox":[42,532,50,26]}
{"kind":"textbox","id":"sh/ny5876xc","slide":17,"text":"数据质量","textPreview":"数据质量","textChars":4,"textLines":1,"bbox":[112,518,230,48]}
{"kind":"textbox","id":"sh/mxw7e1gr","slide":17,"text":"口径一致·完整·及时·可追溯","textPreview":"口径一致·完整·及时·可追溯","textChars":14,"textLines":1,"bbox":[395,518,760,48]}
{"kind":"shape","id":"sh/lwnq5gf6","slide":17,"bbox":[112,583,1040,0]}
{"kind":"shape","id":"sh/0vepcbyl","slide":17,"bbox":[42,612,1196,42]}
{"kind":"textbox","id":"sh/zul836xg","slide":17,"text":"项目启动时即确认基线、口径和外部影响因素,避免将自然波动误认为系统收益。","textPreview":"项目启动时即确认基线、口径和外部影响因素,避免将自然波动误认为系统收益。","textChars":36,"textLines":1,"bbox":[64,622,1152,24]}
{"kind":"notes","id":"nt/14bup87q","slide":17,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
{"kind":"slide","id":"sl/y5wne50z","slide":18,"title":"玄谋智脑","textShapes":4}
{"kind":"textbox","id":"sh/4felwzu5","slide":18,"text":"玄谋智脑","textPreview":"玄谋智脑","textChars":4,"textLines":1,"bbox":[42,35,240,30]}
{"kind":"textbox","id":"sh/wrelszu9","slide":18,"text":"先用 8 周,找到第一批可验证的利润机会\nStart with the first measurable profit opportunities.","textPreview":"先用 8 周,找到第一批可验证的利润机会 | Start with the first measurable profit opportunities.","textChars":74,"textLines":2,"bbox":[42,160,1040,210]}
{"kind":"textbox","id":"sh/hsn2l4bu","slide":18,"text":"再决定如何扩大应用范围 Scale only after the value is proven.","textPreview":"再决定如何扩大应用范围 Scale only after the value is proven.","textChars":50,"textLines":1,"bbox":[42,420,850,52]}
{"kind":"shape","id":"sh/itw3upcf","slide":18,"bbox":[42,610,1196,0]}
{"kind":"textbox","id":"sh/je5knut0","slide":18,"text":"让问题更早被发现 · 让整改真正落地 · 让每一次改善复制到更多门店","textPreview":"让问题更早被发现 · 让整改真正落地 · 让每一次改善复制到更多门店","textChars":34,"textLines":1,"bbox":[42,636,1100,30]}
{"kind":"notes","id":"nt/y5wne50z","slide":18,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。"}
@@ -0,0 +1,456 @@
{"kind":"deck","id":"pr/grdqj0","name":"Deck"}
{"kind":"layout","layoutId":"/ppt/slideMasters/slideMaster1.xml","name":"Master","type":"master"}
{"kind":"layout","layoutId":"/ppt/slideLayouts/slideLayout1.xml","name":"Title Slide","type":"title"}
{"kind":"slide","id":"sl/y90nupkv","slide":1,"title":"玄谋智脑 / Xuanmou Intelligence","textShapes":4}
{"kind":"textbox","id":"sh/ts7md4r2","slide":1,"text":"玄谋智脑 / Xuanmou Intelligence","textPreview":"玄谋智脑 / Xuanmou Intelligence","textChars":27,"textLines":1,"bbox":[42,34,360,36]}
{"kind":"textbox","id":"sh/547294r6","slide":1,"text":"看清利润,才谈得上管住门店\nSee the profit clearly. Run every store with confidence.","textPreview":"看清利润,才谈得上管住门店 | See the profit clearly. Run every store with confidence.","textChars":70,"textLines":2,"bbox":[42,180,990,180]}
{"kind":"textbox","id":"sh/k3yl0zql","slide":1,"text":"面向连锁企业的行业数字本体与 AI 经营智脑 A decision intelligence layer for multi-site operators","textPreview":"面向连锁企业的行业数字本体与 AI 经营智脑 A decision intelligence layer for multi-site operators","textChars":78,"textLines":1,"bbox":[42,402,870,48]}
{"kind":"shape","id":"sh/7qp4be9c","slide":1,"bbox":[42,615,1196,0]}
{"kind":"textbox","id":"sh/65g3298r","slide":1,"text":"对外保密版 · 案例与金额均为匿名示意\nConfidential external edition · Cases and figures are anonymized illustrations","textPreview":"对外保密版 · 案例与金额均为匿名示意 | Confidential external edition · Cases and figures are anonymized illustrations","textChars":98,"textLines":2,"bbox":[42,640,620,24]}
{"kind":"notes","id":"nt/y90nupkv","slide":1,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/hwbqtkby","slide":2,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":13}
{"kind":"textbox","id":"sh/cnupgny5","slide":2,"text":"玄谋智脑 · 连锁企业经营决策\nXuanmou Intelligence · Multi-site Operations","textPreview":"玄谋智脑 · 连锁企业经营决策 | Xuanmou Intelligence · Multi-site Operations","textChars":60,"textLines":2,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/9072xkry","slide":2,"text":"老板最终要判断三件事\nThree decisions matter most to the owner.","textPreview":"老板最终要判断三件事 | Three decisions matter most to the owner.","textChars":52,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/ozy1ofad","slide":2,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/b29kza94","slide":2,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/a10jqpsj","slide":2,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[42,190,80,48]}
{"kind":"shape","id":"sh/x4r21kru","slide":2,"bbox":[42,248,350,0]}
{"kind":"textbox","id":"sh/w3i1sfa9","slide":2,"text":"哪里在亏钱? / Where are we losing money?","textPreview":"哪里在亏钱? / Where are we losing money?","textChars":35,"textLines":1,"bbox":[42,278,350,52]}
{"kind":"textbox","id":"sh/r65knqtk","slide":2,"text":"门店、SKU、促销、库存、人力中,哪些利润漏洞最应该先处理?\nWhich profit leaks across stores, SKUs, promotions, inventory and labor should be fixed first?","textPreview":"门店、SKU、促销、库存、人力中,哪些利润漏洞最应该先处理? | Which profit leaks across stores, SKUs, promotions, inventory and labor should be fixed first?","textChars":125,"textLines":2,"bbox":[42,352,350,140]}
{"kind":"textbox","id":"sh/q5wjelsz","slide":2,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[443,190,80,48]}
{"kind":"shape","id":"sh/ove9o7yd","slide":2,"bbox":[443,248,350,0]}
{"kind":"textbox","id":"sh/9wnqhczy","slide":2,"text":"哪些动作能增利? / Which actions will improve profit?","textPreview":"哪些动作能增利? / Which actions will improve profit?","textChars":45,"textLines":1,"bbox":[443,278,350,52]}
{"kind":"textbox","id":"sh/mtwrmxg7","slide":2,"text":"不只找问题,还要测算影响、给出方案、跟踪执行并验证结果。\nQuantify the impact, recommend actions, track execution and verify the outcome.","textPreview":"不只找问题,还要测算影响、给出方案、跟踪执行并验证结果。 | Quantify the impact, recommend actions, track execution and verify the outcome.","textChars":108,"textLines":2,"bbox":[443,352,350,140]}
{"kind":"textbox","id":"sh/nu58f2hs","slide":2,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[844,190,80,48]}
{"kind":"shape","id":"sh/wjy9sry9","slide":2,"bbox":[844,248,350,0]}
{"kind":"textbox","id":"sh/xk7qlczu","slide":2,"text":"扩张后还能管住吗? / Can we stay in control as we scale?","textPreview":"扩张后还能管住吗? / Can we stay in control as we scale?","textChars":47,"textLines":1,"bbox":[844,278,350,52]}
{"kind":"textbox","id":"sh/ahwrqhgj","slide":2,"text":"从 30 家到 300 家门店,有效经验能否被低成本、高质量地复制?\nCan proven practices be replicated from 30 to 300 stores, consistently and at low cost?","textPreview":"从 30 家到 300 家门店,有效经验能否被低成本、高质量地复制? | Can proven practices be replicated from 30 to 300 stores, consistently and at low cost?","textChars":122,"textLines":2,"bbox":[844,352,350,140]}
{"kind":"textbox","id":"sh/bip8jmho","slide":2,"text":"不是看更多报表,而是将数据转化为可验证的经营改善。\nThe goal is not more reports, but measurable operating improvement.","textPreview":"不是看更多报表,而是将数据转化为可验证的经营改善。 | The goal is not more reports, but measurable operating improvement.","textChars":93,"textLines":2,"bbox":[42,590,1100,42]}
{"kind":"notes","id":"nt/hwbqtkby","slide":2,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/ofy9wn61","slide":3,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":15}
{"kind":"textbox","id":"sh/batgjixs","slide":3,"text":"玄谋智脑 · 连锁企业经营决策\nXuanmou Intelligence · Multi-site Operations","textPreview":"玄谋智脑 · 连锁企业经营决策 | Xuanmou Intelligence · Multi-site Operations","textChars":60,"textLines":2,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/cza94vmx","slide":3,"text":"数据很多,利润去向仍然说不清\nPlenty of data, but no clear view of where profit goes.","textPreview":"数据很多,利润去向仍然说不清 | Plenty of data, but no clear view of where profit goes.","textChars":70,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/d0jax03i","slide":3,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/298ryl4v","slide":3,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/3ah8rqlg","slide":3,"bbox":[42,188,360,160]}
{"kind":"shape","id":"sh/obq90bml","slide":3,"bbox":[42,188,7,160]}
{"kind":"textbox","id":"sh/pcjqtg36","slide":3,"text":"营收 / Revenue","textPreview":"营收 / Revenue","textChars":12,"textLines":1,"bbox":[66,210,314,40]}
{"kind":"textbox","id":"sh/m5cra54z","slide":3,"text":"营收增长,利润为何没有同步?\nWhy is profit not keeping pace with revenue?","textPreview":"营收增长,利润为何没有同步? | Why is profit not keeping pace with revenue?","textChars":59,"textLines":2,"bbox":[66,262,314,68]}
{"kind":"shape","id":"sh/n6ls3alk","slide":3,"bbox":[443,188,360,160]}
{"kind":"shape","id":"sh/n2l4fq98","slide":3,"bbox":[443,188,7,160]}
{"kind":"textbox","id":"sh/m1c3mlsn","slide":3,"text":"门店 / Stores","textPreview":"门店 / Stores","textChars":11,"textLines":1,"bbox":[467,210,314,40]}
{"kind":"textbox","id":"sh/943mhgre","slide":3,"text":"哪些门店看似赚钱,实际占用资金?\nWhich stores appear profitable but tie up cash?","textPreview":"哪些门店看似赚钱,实际占用资金? | Which stores appear profitable but tie up cash?","textChars":64,"textLines":2,"bbox":[467,262,314,68]}
{"kind":"shape","id":"sh/83ulovat","slide":3,"bbox":[844,188,360,160]}
{"kind":"shape","id":"sh/v6l4jq94","slide":3,"bbox":[844,188,7,160]}
{"kind":"textbox","id":"sh/a5c3ql8z","slide":3,"text":"促销 / Promotions","textPreview":"促销 / Promotions","textChars":15,"textLines":1,"bbox":[868,210,314,40]}
{"kind":"textbox","id":"sh/x8nml0ra","slide":3,"text":"哪些活动增加订单,却消耗利润?\nWhich campaigns add orders but destroy profit?","textPreview":"哪些活动增加订单,却消耗利润? | Which campaigns add orders but destroy profit?","textChars":62,"textLines":2,"bbox":[868,262,314,68]}
{"kind":"shape","id":"sh/w7ulsvqp","slide":3,"bbox":[42,390,360,160]}
{"kind":"shape","id":"sh/ja54na9g","slide":3,"bbox":[42,390,7,160]}
{"kind":"textbox","id":"sh/i9w3u58v","slide":3,"text":"SKU","textPreview":"SKU","textChars":3,"textLines":1,"bbox":[66,412,314,40]}
{"kind":"textbox","id":"sh/e10f2twf","slide":3,"text":"哪些商品销量不低,却毛利不足?\nWhich products sell well but contribute too little margin?","textPreview":"哪些商品销量不低,却毛利不足? | Which products sell well but contribute too little margin?","textChars":74,"textLines":2,"bbox":[66,464,314,68]}
{"kind":"shape","id":"sh/f29gbyx0","slide":3,"bbox":[443,390,360,160]}
{"kind":"shape","id":"sh/03ix43e5","slide":3,"bbox":[443,390,7,160]}
{"kind":"textbox","id":"sh/14ryd8fq","slide":3,"text":"人力 / Labor","textPreview":"人力 / Labor","textChars":10,"textLines":1,"bbox":[467,412,314,40]}
{"kind":"textbox","id":"sh/6d0fytg3","slide":3,"text":"哪些时段人员闲置,高峰又缺人?\nWhen are teams idle, yet understaffed at peak times?","textPreview":"哪些时段人员闲置,高峰又缺人? | When are teams idle, yet understaffed at peak times?","textChars":68,"textLines":2,"bbox":[467,464,314,68]}
{"kind":"shape","id":"sh/re9g7yxo","slide":3,"bbox":[844,390,360,160]}
{"kind":"shape","id":"sh/sfix03y9","slide":3,"bbox":[844,390,7,160]}
{"kind":"textbox","id":"sh/tgry9ofu","slide":3,"text":"止损 / Loss control","textPreview":"止损 / Loss control","textChars":17,"textLines":1,"bbox":[868,412,314,40]}
{"kind":"textbox","id":"sh/a9kfadwn","slide":3,"text":"哪些门店应整改、迁址、缩编或关停?\nWhich stores should be fixed, relocated, resized or closed?","textPreview":"哪些门店应整改、迁址、缩编或关停? | Which stores should be fixed, relocated, resized or closed?","textChars":77,"textLines":2,"bbox":[868,464,314,68]}
{"kind":"notes","id":"nt/ofy9wn61","slide":3,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/jyx0ra1s","slide":4,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":22}
{"kind":"textbox","id":"sh/knex8j21","slide":4,"text":"玄谋智脑 · 连锁企业经营决策\nXuanmou Intelligence · Multi-site Operations","textPreview":"玄谋智脑 · 连锁企业经营决策 | Xuanmou Intelligence · Multi-site Operations","textChars":60,"textLines":2,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/1cj2d8b6","slide":4,"text":"把异常处理成有结果的经营行动\nTurn exceptions into actions with measurable outcomes.","textPreview":"把异常处理成有结果的经营行动 | Turn exceptions into actions with measurable outcomes.","textChars":69,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/0ba143al","slide":4,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/rm1k7yt4","slide":4,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/ql8jytsj","slide":4,"bbox":[82,350,1090,0]}
{"kind":"shape","id":"sh/doj29oba","slide":4,"bbox":[54,332,36,36]}
{"kind":"textbox","id":"sh/sna103ap","slide":4,"text":"1","textPreview":"1","textChars":1,"textLines":1,"bbox":[54,337,36,24]}
{"kind":"textbox","id":"sh/3ihk3et8","slide":4,"text":"发现 / Detect","textPreview":"发现 / Detect","textChars":11,"textLines":1,"bbox":[44,235,150,40]}
{"kind":"textbox","id":"sh/ih8ju9sn","slide":4,"text":"利润异常\nProfit exception","textPreview":"利润异常 | Profit exception","textChars":21,"textLines":2,"bbox":[44,400,164,78]}
{"kind":"shape","id":"sh/kbm987y5","slide":4,"bbox":[253,332,36,36]}
{"kind":"textbox","id":"sh/5cva1cfq","slide":4,"text":"2","textPreview":"2","textChars":1,"textLines":1,"bbox":[253,337,36,24]}
{"kind":"textbox","id":"sh/i94r6xgz","slide":4,"text":"穿透 / Drill down","textPreview":"穿透 / Drill down","textChars":15,"textLines":1,"bbox":[243,235,150,40]}
{"kind":"textbox","id":"sh/jadsz2xk","slide":4,"text":"区域·门店·SKU·班次\nRegion · Store · SKU · Shift","textPreview":"区域·门店·SKU·班次 | Region · Store · SKU · Shift","textChars":41,"textLines":2,"bbox":[243,400,164,78]}
{"kind":"shape","id":"sh/w72947yt","slide":4,"bbox":[452,332,36,36]}
{"kind":"textbox","id":"sh/x8vaxsfe","slide":4,"text":"3","textPreview":"3","textChars":1,"textLines":1,"bbox":[452,337,36,24]}
{"kind":"textbox","id":"sh/a5kr2xg3","slide":4,"text":"测算 / Quantify","textPreview":"测算 / Quantify","textChars":13,"textLines":1,"bbox":[442,235,150,40]}
{"kind":"textbox","id":"sh/v6tsv2xo","slide":4,"text":"影响金额与优先级\nFinancial impact and priority","textPreview":"影响金额与优先级 | Financial impact and priority","textChars":38,"textLines":2,"bbox":[442,400,164,78]}
{"kind":"shape","id":"sh/g36tgryd","slide":4,"bbox":[651,332,36,36]}
{"kind":"textbox","id":"sh/h4fa9wfy","slide":4,"text":"4","textPreview":"4","textChars":1,"textLines":1,"bbox":[651,337,36,24]}
{"kind":"textbox","id":"sh/p0batw72","slide":4,"text":"整改 / Act","textPreview":"整改 / Act","textChars":8,"textLines":1,"bbox":[641,235,150,40]}
{"kind":"textbox","id":"sh/oz29krqh","slide":4,"text":"动作·责任人·期限\nAction · Owner · Deadline","textPreview":"动作·责任人·期限 | Action · Owner · Deadline","textChars":35,"textLines":2,"bbox":[641,400,164,78]}
{"kind":"shape","id":"sh/3ytsrmpw","slide":4,"bbox":[850,332,36,36]}
{"kind":"textbox","id":"sh/2xkrih8b","slide":4,"text":"5","textPreview":"5","textChars":1,"textLines":1,"bbox":[850,337,36,24]}
{"kind":"textbox","id":"sh/1wbapc7q","slide":4,"text":"验证 / Verify","textPreview":"验证 / Verify","textChars":11,"textLines":1,"bbox":[840,235,150,40]}
{"kind":"textbox","id":"sh/gv29g7q5","slide":4,"text":"利润是否真正改善\nConfirm real profit improvement","textPreview":"利润是否真正改善 | Confirm real profit improvement","textChars":40,"textLines":2,"bbox":[840,400,164,78]}
{"kind":"shape","id":"sh/fu9sn2p0","slide":4,"bbox":[1049,332,36,36]}
{"kind":"textbox","id":"sh/et0reh8f","slide":4,"text":"6","textPreview":"6","textChars":1,"textLines":1,"bbox":[1049,337,36,24]}
{"kind":"textbox","id":"sh/tsrqlc7u","slide":4,"text":"沉淀 / Codify","textPreview":"沉淀 / Codify","textChars":11,"textLines":1,"bbox":[1039,235,150,40]}
{"kind":"textbox","id":"sh/sri9s7q9","slide":4,"text":"更新企业最佳实践\nUpdate company best practices","textPreview":"更新企业最佳实践 | Update company best practices","textChars":38,"textLines":2,"bbox":[1039,400,164,78]}
{"kind":"shape","id":"sh/ilwf69kv","slide":4,"bbox":[42,552,1196,58]}
{"kind":"textbox","id":"sh/jm5gze1g","slide":4,"text":"关键不是“发现问题”,而是“把问题变成可复制的利润改善”。\nThe value lies in turning issues into repeatable profit improvement.","textPreview":"关键不是“发现问题”,而是“把问题变成可复制的利润改善”。 | The value lies in turning issues into repeatable profit improvement.","textChars":98,"textLines":2,"bbox":[66,568,1148,30]}
{"kind":"notes","id":"nt/jyx0ra1s","slide":4,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/i107q5of","slide":5,"title":"匿名复合案例 · SKU 组合决策 Anonymous composite case · SKU portfolio","textShapes":15}
{"kind":"textbox","id":"sh/fe94nm1w","slide":5,"text":"匿名复合案例 · SKU 组合决策 Anonymous composite case · SKU portfolio","textPreview":"匿名复合案例 · SKU 组合决策 Anonymous composite case · SKU portfolio","textChars":59,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/dgbulwnm","slide":5,"text":"SKU 过多,往往增加的是复杂度和成本\nMore SKUs often mean more cost, not more choice.","textPreview":"SKU 过多,往往增加的是复杂度和成本 | More SKUs often mean more cost, not more choice.","textChars":68,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/cf2tcr61","slide":5,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/z2tcnm5s","slide":5,"text":"05","textPreview":"05","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/yhkbe1o7","slide":5,"text":"480","textPreview":"480","textChars":3,"textLines":1,"bbox":[42,182,190,72]}
{"kind":"textbox","id":"sh/l4bupwny","slide":5,"text":"在售 SKU / Active SKUs","textPreview":"在售 SKU / Active SKUs","textChars":20,"textLines":1,"bbox":[42,256,190,30]}
{"kind":"textbox","id":"sh/032tgr6d","slide":5,"text":"后 20% SKU 仅贡献约 3% 销售额,却持续占用库存资金。\nThe bottom 20% of SKUs contribute about 3% of sales while continuously tying up inventory cash.","textPreview":"后 20% SKU 仅贡献约 3% 销售额,却持续占用库存资金。 | The bottom 20% of SKUs contribute about 3% of sales while continuously tying up inventory cash.","textChars":128,"textLines":2,"bbox":[262,190,800,76]}
{"kind":"shape","id":"sh/n6dcr65o","slide":5,"bbox":[42,328,270,170]}
{"kind":"textbox","id":"sh/m5kbi1oj","slide":5,"text":"37 个 / 37 items","textPreview":"37 个 / 37 items","textChars":15,"textLines":1,"bbox":[66,354,222,64]}
{"kind":"textbox","id":"sh/w32dkbuh","slide":5,"text":"低销量·低毛利·高损耗\nLow sales · Low margin · High waste","textPreview":"低销量·低毛利·高损耗 | Low sales · Low margin · High waste","textChars":47,"textLines":2,"bbox":[66,434,222,40]}
{"kind":"shape","id":"sh/x4vedgvm","slide":5,"bbox":[341,328,270,170]}
{"kind":"textbox","id":"sh/ahkvi1cb","slide":5,"text":"9 个 / 9 items","textPreview":"9 个 / 9 items","textChars":13,"textLines":1,"bbox":[365,354,222,64]}
{"kind":"textbox","id":"sh/v2twb6dw","slide":5,"text":"高销量但低贡献利润 / High sales but low profit contribution","textPreview":"高销量但低贡献利润 / High sales but low profit contribution","textChars":50,"textLines":1,"bbox":[365,434,222,40]}
{"kind":"shape","id":"sh/k7mxovud","slide":5,"bbox":[640,328,270,170]}
{"kind":"textbox","id":"sh/58vehgvy","slide":5,"text":"16 个 / 16 items","textPreview":"16 个 / 16 items","textChars":15,"textLines":1,"bbox":[664,354,222,64]}
{"kind":"textbox","id":"sh/i54fmlc7","slide":5,"text":"可共享或替换原料 / Shared or substitutable ingredients","textPreview":"可共享或替换原料 / Shared or substitutable ingredients","textChars":46,"textLines":1,"bbox":[664,434,222,40]}
{"kind":"shape","id":"sh/j6dwfqds","slide":5,"bbox":[939,328,270,170]}
{"kind":"textbox","id":"sh/sb6xsvu9","slide":5,"text":"22 个 / 22 items","textPreview":"22 个 / 22 items","textChars":15,"textLines":1,"bbox":[963,354,222,64]}
{"kind":"textbox","id":"sh/tcfel0vu","slide":5,"text":"价格带重叠 / Overlapping price points","textPreview":"价格带重叠 / Overlapping price points","textChars":32,"textLines":1,"bbox":[963,434,222,40]}
{"kind":"shape","id":"sh/hgrmpwj2","slide":5,"bbox":[42,535,1196,85]}
{"kind":"textbox","id":"sh/gfi5grih","slide":5,"text":"模拟测算:释放库存资金约 80 万元 · 年减少报损约 35 万元 · 综合毛利率提升约 0.6 个百分点\nIllustrative estimate: release RMB 0.8m in inventory cash · reduce annual waste by RMB 0.35m · lift gross margin by about 0.6 pp","textPreview":"模拟测算:释放库存资金约 80 万元 · 年减少报损约 35 万元 · 综合毛利率提升约 0.6 个百分点 | Illustrative estimate: release RMB 0.8m in inventory cash · reduce annual waste b...","textChars":182,"textLines":2,"bbox":[68,558,1140,40]}
{"kind":"notes","id":"nt/i107q5of","slide":5,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/x8f69ofe","slide":6,"title":"匿名复合案例 · 门店 A-017 Anonymous composite case · Store A-017","textShapes":10}
{"kind":"textbox","id":"sh/svmt4v6t","slide":6,"text":"匿名复合案例 · 门店 A-017 Anonymous composite case · Store A-017","textPreview":"匿名复合案例 · 门店 A-017 Anonymous composite case · Store A-017","textChars":57,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/yhg7epsj","slide":6,"text":"排班的关键,是工时跟着客流走\nLabor hours should follow demand.","textPreview":"排班的关键,是工时跟着客流走 | Labor hours should follow demand.","textChars":48,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/zi98nu94","slide":6,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/87ipkzal","slide":6,"text":"06","textPreview":"06","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/98rqt4r6","slide":6,"bbox":[42,182,362,314]}
{"kind":"shape","id":"sh/ml07i9sv","slide":6,"bbox":[42,182,7,314]}
{"kind":"textbox","id":"sh/7m98ru9g","slide":6,"text":"发现 / Detect","textPreview":"发现 / Detect","textChars":11,"textLines":1,"bbox":[66,204,316,40]}
{"kind":"textbox","id":"sh/oryp8fah","slide":6,"text":"· 工作日上午存在闲置工时\n· 周五晚高峰经常缺人\n· 班次依据历史习惯\n· 加班集中在少数岗位\nIdle labor on weekday mornings · Understaffed on Friday peaks · Habit-based shifts · Overtime concentrated in a few roles","textPreview":"· 工作日上午存在闲置工时 | · 周五晚高峰经常缺人 | · 班次依据历史习惯 | · 加班集中在少数岗位 | Idle labor on weekday mornings · Understaffed on Friday peaks · Habit-based shif...","textChars":170,"textLines":5,"bbox":[66,256,316,222]}
{"kind":"shape","id":"sh/pc76hkr2","slide":6,"bbox":[458,182,362,314]}
{"kind":"shape","id":"sh/h4bupgn6","slide":6,"bbox":[458,182,7,314]}
{"kind":"textbox","id":"sh/w32twb6l","slide":6,"text":"动作 / Actions","textPreview":"动作 / Actions","textChars":12,"textLines":1,"bbox":[482,204,316,40]}
{"kind":"textbox","id":"sh/v2tcn650","slide":6,"text":"· 按半小时预测工作量\n· 调整早晚班起止时间\n· 高峰增加小时工\n· 备餐前移至客流爬升前\nForecast every 30 minutes · Adjust shift times · Add hourly staff at peaks · Move prep ahead of demand","textPreview":"· 按半小时预测工作量 | · 调整早晚班起止时间 | · 高峰增加小时工 | · 备餐前移至客流爬升前 | Forecast every 30 minutes · Adjust shift times · Add hourly staff at peaks · Move ...","textChars":149,"textLines":5,"bbox":[482,256,316,222]}
{"kind":"shape","id":"sh/u1kbu1ov","slide":6,"bbox":[874,182,364,314]}
{"kind":"shape","id":"sh/5svutgni","slide":6,"bbox":[874,182,7,314]}
{"kind":"textbox","id":"sh/47mt0b6x","slide":6,"text":"验证 / Verify","textPreview":"验证 / Verify","textChars":11,"textLines":1,"bbox":[898,204,318,40]}
{"kind":"textbox","id":"sh/j6dcr65c","slide":6,"text":"同时监控:\n\n· 人工成本\n· 出品时效\n· 顾客满意度\n\n避免单纯压缩人力。\nMonitor labor cost, service speed and customer satisfaction together. Do not simply cut headcount.","textPreview":"同时监控: | | · 人工成本 | · 出品时效 | · 顾客满意度 | | 避免单纯压缩人力。 | Monitor labor cost, service speed and customer satisfaction together. Do not simply...","textChars":138,"textLines":8,"bbox":[898,256,318,222]}
{"kind":"shape","id":"sh/i54bylor","slide":6,"bbox":[42,535,1196,85]}
{"kind":"textbox","id":"sh/twfux0ne","slide":6,"text":"模拟测算:单店每月节约 1.8 万元;复制到 60 家门店,年度改善空间约 1,296 万元。\nIllustrative estimate: RMB 18k saved per store per month; about RMB 12.96m annual upside across 60 stores.","textPreview":"模拟测算:单店每月节约 1.8 万元;复制到 60 家门店,年度改善空间约 1,296 万元。 | Illustrative estimate: RMB 18k saved per store per month; about RMB 12.96m annual upsid...","textChars":154,"textLines":2,"bbox":[66,557,1148,42]}
{"kind":"notes","id":"nt/x8f69ofe","slide":6,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/gnmp4jqx","slide":7,"title":"匿名复合案例 · 营销活动 X Anonymous composite case · Campaign X","textShapes":17}
{"kind":"textbox","id":"sh/s3ml0v61","slide":7,"text":"匿名复合案例 · 营销活动 X Anonymous composite case · Campaign X","textPreview":"匿名复合案例 · 营销活动 X Anonymous composite case · Campaign X","textChars":54,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/cb2tkvap","slide":7,"text":"订单增长,不等于促销赚钱\nMore orders do not always mean a profitable campaign.","textPreview":"订单增长,不等于促销赚钱 | More orders do not always mean a profitable campaign.","textChars":66,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/dcbud0ra","slide":7,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ydkbm5sv","slide":7,"text":"07","textPreview":"07","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/zedcfa9g","slide":7,"bbox":[42,186,350,170]}
{"kind":"textbox","id":"sh/kzmdova1","slide":7,"text":"+23%","textPreview":"+23%","textChars":4,"textLines":1,"bbox":[66,212,302,64]}
{"kind":"textbox","id":"sh/l0vuh0rm","slide":7,"text":"订单增长 / Order growth","textPreview":"订单增长 / Order growth","textChars":19,"textLines":1,"bbox":[66,292,302,40]}
{"kind":"shape","id":"sh/eh0ba1sr","slide":7,"bbox":[42,378,350,170]}
{"kind":"textbox","id":"sh/fi9c369c","slide":7,"text":"负值 / Negative","textPreview":"负值 / Negative","textChars":13,"textLines":1,"bbox":[66,404,302,64]}
{"kind":"textbox","id":"sh/baxkjqlk","slide":7,"text":"穿透成本后的活动贡献利润\nCampaign contribution after full costs","textPreview":"穿透成本后的活动贡献利润 | Campaign contribution after full costs","textChars":51,"textLines":2,"bbox":[66,484,302,40]}
{"kind":"textbox","id":"sh/a9ojq5kz","slide":7,"text":"活动为什么亏钱 / Why the campaign loses money","textPreview":"活动为什么亏钱 / Why the campaign loses money","textChars":38,"textLines":1,"bbox":[454,186,360,40]}
{"kind":"textbox","id":"sh/xcz2l03q","slide":7,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[454,258,42,28]}
{"kind":"textbox","id":"sh/cbq1sv25","slide":7,"text":"低毛利商品占比上升 / More low-margin items in the mix","textPreview":"低毛利商品占比上升 / More low-margin items in the mix","textChars":44,"textLines":1,"bbox":[510,254,650,40]}
{"kind":"shape","id":"sh/n6x0fqlo","slide":7,"bbox":[510,300,650,0]}
{"kind":"textbox","id":"sh/25ojml43","slide":7,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[454,323,42,28]}
{"kind":"textbox","id":"sh/p8fih03e","slide":7,"text":"高价值会员获得无差别优惠\nHigh-value members receive blanket discounts","textPreview":"高价值会员获得无差别优惠 | High-value members receive blanket discounts","textChars":57,"textLines":2,"bbox":[510,319,650,40]}
{"kind":"shape","id":"sh/o761ov2t","slide":7,"bbox":[510,365,650,0]}
{"kind":"textbox","id":"sh/f2d0b6lc","slide":7,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[454,388,42,28]}
{"kind":"textbox","id":"sh/eh4jil4r","slide":7,"text":"促销订单替代了原价订单\nDiscounted orders replace full-price orders","textPreview":"促销订单替代了原价订单 | Discounted orders replace full-price orders","textChars":55,"textLines":2,"bbox":[510,384,650,40]}
{"kind":"shape","id":"sh/id4ju1oz","slide":7,"bbox":[510,430,650,0]}
{"kind":"textbox","id":"sh/jedkn654","slide":7,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[454,453,42,28]}
{"kind":"textbox","id":"sh/4fm1wb6p","slide":7,"text":"只评价订单和营收,没有评价增量利润\nOrders and revenue measured; incremental profit ignored","textPreview":"只评价订单和营收,没有评价增量利润 | Orders and revenue measured; incremental profit ignored","textChars":73,"textLines":2,"bbox":[510,449,650,40]}
{"kind":"shape","id":"sh/50v2pgna","slide":7,"bbox":[510,495,650,0]}
{"kind":"shape","id":"sh/q143ylov","slide":7,"bbox":[454,544,746,67]}
{"kind":"textbox","id":"sh/r2dkrq5g","slide":7,"text":"用“每投入 1 元营销费用增加多少贡献利润”评价活动。\nEvaluate each campaign by contribution profit generated per RMB 1 of marketing spend.","textPreview":"用“每投入 1 元营销费用增加多少贡献利润”评价活动。 | Evaluate each campaign by contribution profit generated per RMB 1 of marketing spend.","textChars":113,"textLines":2,"bbox":[478,562,700,34]}
{"kind":"notes","id":"nt/gnmp4jqx","slide":7,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/fu1gfa1s","slide":8,"title":"匿名复合案例 · 门店 D-006 Anonymous composite case · Store D-006","textShapes":19}
{"kind":"textbox","id":"sh/07atgnmp","slide":8,"text":"匿名复合案例 · 门店 D-006 Anonymous composite case · Store D-006","textPreview":"匿名复合案例 · 门店 D-006 Anonymous composite case · Store D-006","textChars":57,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/18byd4zy","slide":8,"text":"关店前,先把四种选择算清楚\nCompare the options before deciding to close a store.","textPreview":"关店前,先把四种选择算清楚 | Compare the options before deciding to close a store.","textChars":67,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/g72x4zyd","slide":8,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ri9g7uhw","slide":8,"text":"08","textPreview":"08","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/6h0fypgb","slide":8,"bbox":[42,180,340,55]}
{"kind":"textbox","id":"sh/tkby9kzm","slide":8,"text":"方案 / Option","textPreview":"方案 / Option","textChars":11,"textLines":1,"bbox":[60,197,304,26]}
{"kind":"shape","id":"sh/sjix0zy1","slide":8,"bbox":[382,180,378,55]}
{"kind":"textbox","id":"sh/je9g3ahk","slide":8,"text":"12 个月模拟结果 / 12-month scenario","textPreview":"12 个月模拟结果 / 12-month scenario","textChars":29,"textLines":1,"bbox":[400,197,342,26]}
{"kind":"shape","id":"sh/id0fu50z","slide":8,"bbox":[760,180,478,55]}
{"kind":"textbox","id":"sh/o7ydoret","slide":8,"text":"决策建议 / Recommendation","textPreview":"决策建议 / Recommendation","textChars":21,"textLines":1,"bbox":[778,197,442,26]}
{"kind":"shape","id":"sh/98rehwve","slide":8,"bbox":[42,235,340,72]}
{"kind":"textbox","id":"sh/m5gvmhwn","slide":8,"text":"继续经营 / Continue operating","textPreview":"继续经营 / Continue operating","textChars":25,"textLines":1,"bbox":[60,256,304,35]}
{"kind":"shape","id":"sh/n6pwfmd8","slide":8,"bbox":[382,235,378,72]}
{"kind":"textbox","id":"sh/0jydkreh","slide":8,"text":"预计亏损 92 万 / Estimated loss: RMB 0.92m","textPreview":"预计亏损 92 万 / Estimated loss: RMB 0.92m","textChars":37,"textLines":1,"bbox":[400,256,342,35]}
{"kind":"shape","id":"sh/1k7edwv2","slide":8,"bbox":[760,235,478,72]}
{"kind":"textbox","id":"sh/ehgvihwr","slide":8,"text":"不建议 / Not recommended","textPreview":"不建议 / Not recommended","textChars":21,"textLines":1,"bbox":[778,256,442,35]}
{"kind":"shape","id":"sh/zipwbmdc","slide":8,"bbox":[42,307,340,72]}
{"kind":"textbox","id":"sh/kfixwbe1","slide":8,"text":"投入整改 / Invest in a turnaround","textPreview":"投入整改 / Invest in a turnaround","textChars":29,"textLines":1,"bbox":[60,328,304,35]}
{"kind":"shape","id":"sh/lgbepgvm","slide":8,"bbox":[382,307,378,72]}
{"kind":"textbox","id":"sh/tw7e9gnq","slide":8,"text":"预计亏损降至 35 万\nEstimated loss falls to RMB 0.35m","textPreview":"预计亏损降至 35 万 | Estimated loss falls to RMB 0.35m","textChars":45,"textLines":2,"bbox":[400,328,342,35]}
{"kind":"shape","id":"sh/svydgb65","slide":8,"bbox":[760,307,478,72]}
{"kind":"textbox","id":"sh/7u5w765k","slide":8,"text":"高风险,设止损线 / High risk; set a stop-loss","textPreview":"高风险,设止损线 / High risk; set a stop-loss","textChars":37,"textLines":1,"bbox":[778,328,442,35]}
{"kind":"shape","id":"sh/6twve1oz","slide":8,"bbox":[42,379,340,72]}
{"kind":"textbox","id":"sh/5sne5wne","slide":8,"text":"缩小面积 / Reduce footprint","textPreview":"缩小面积 / Reduce footprint","textChars":23,"textLines":1,"bbox":[60,400,304,35]}
{"kind":"shape","id":"sh/kredcr6t","slide":8,"bbox":[382,379,378,72]}
{"kind":"textbox","id":"sh/jq5w365o","slide":8,"text":"预计接近盈亏平衡 / Near break-even","textPreview":"预计接近盈亏平衡 / Near break-even","textChars":26,"textLines":1,"bbox":[400,400,342,35]}
{"kind":"shape","id":"sh/i5wva1o3","slide":8,"bbox":[760,379,478,72]}
{"kind":"textbox","id":"sh/x4ne1wni","slide":8,"text":"租约可重谈时考虑 / Consider if the lease can be renegotiated","textPreview":"租约可重谈时考虑 / Consider if the lease can be renegotiated","textChars":52,"textLines":1,"bbox":[778,400,442,35]}
{"kind":"shape","id":"sh/w3ed8r6x","slide":8,"bbox":[42,451,340,72]}
{"kind":"textbox","id":"sh/m9sb2x4v","slide":8,"text":"关停并迁移会员 / Close and migrate members","textPreview":"关停并迁移会员 / Close and migrate members","textChars":35,"textLines":1,"bbox":[60,472,304,35]}
{"kind":"shape","id":"sh/na1sb2lg","slide":8,"bbox":[382,451,378,72]}
{"kind":"textbox","id":"sh/8bat47ml","slide":8,"text":"预计减少亏损 76 万\nEstimated loss reduction: RMB 0.76m","textPreview":"预计减少亏损 76 万 | Estimated loss reduction: RMB 0.76m","textChars":47,"textLines":2,"bbox":[400,472,342,35]}
{"kind":"shape","id":"sh/9w3uds36","slide":8,"bbox":[760,451,478,72]}
{"kind":"textbox","id":"sh/y5sbed4j","slide":8,"text":"优先建议 / Preferred option","textPreview":"优先建议 / Preferred option","textChars":23,"textLines":1,"bbox":[778,472,442,35]}
{"kind":"textbox","id":"sh/z61s7il4","slide":8,"text":"AI 不替老板关店;它让经验判断具有数据依据、情景测算和退出预案。\nAI does not close stores. It adds evidence, scenario analysis and an exit plan to management judgment.","textPreview":"AI 不替老板关店;它让经验判断具有数据依据、情景测算和退出预案。 | AI does not close stores. It adds evidence, scenario analysis and an exit plan to management judgment.","textChars":136,"textLines":2,"bbox":[42,565,1160,44]}
{"kind":"notes","id":"nt/fu1gfa1s","slide":8,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/udsvah03","slide":9,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":19}
{"kind":"textbox","id":"sh/va103ep4","slide":9,"text":"玄谋智脑 · 连锁企业经营决策\nXuanmou Intelligence · Multi-site Operations","textPreview":"玄谋智脑 · 连锁企业经营决策 | Xuanmou Intelligence · Multi-site Operations","textChars":60,"textLines":2,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/1cfmhgne","slide":9,"text":"四级管理,各自看清该做的事\nOne operating view, four levels of accountability.","textPreview":"四级管理,各自看清该做的事 | One operating view, four levels of accountability.","textChars":64,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/0b65obm9","slide":9,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/nex4jq5k","slide":9,"text":"09","textPreview":"09","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/mdonql4z","slide":9,"bbox":[42,190,265,316]}
{"kind":"textbox","id":"sh/9gzml0nq","slide":9,"text":"老板 / Owner","textPreview":"老板 / Owner","textChars":10,"textLines":1,"bbox":[64,214,220,46]}
{"kind":"textbox","id":"sh/ofq5svm5","slide":9,"text":"看结果 / Review outcomes","textPreview":"看结果 / Review outcomes","textChars":21,"textLines":1,"bbox":[64,296,220,44]}
{"kind":"textbox","id":"sh/bih4na5w","slide":9,"text":"利润·风险·资源投向\nProfit · Risk · Capital allocation","textPreview":"利润·风险·资源投向 | Profit · Risk · Capital allocation","textChars":45,"textLines":2,"bbox":[64,386,220,72]}
{"kind":"textbox","id":"sh/ah8nu54b","slide":9,"text":"→","textPreview":"→","textChars":1,"textLines":1,"bbox":[310,323,30,36]}
{"kind":"shape","id":"sh/oza1gfyh","slide":9,"bbox":[341,190,265,316]}
{"kind":"textbox","id":"sh/p0ji9kf2","slide":9,"text":"总部 / Head office","textPreview":"总部 / Head office","textChars":16,"textLines":1,"bbox":[363,214,220,46]}
{"kind":"textbox","id":"sh/2xsjepgb","slide":9,"text":"找原因 / Find causes","textPreview":"找原因 / Find causes","textChars":17,"textLines":1,"bbox":[363,296,220,44]}
{"kind":"textbox","id":"sh/3y107axw","slide":9,"text":"跨区域对标·政策评估\nCross-region benchmarks · Policy review","textPreview":"跨区域对标·政策评估 | Cross-region benchmarks · Policy review","textChars":50,"textLines":2,"bbox":[363,386,220,72]}
{"kind":"textbox","id":"sh/cnu1kzyd","slide":9,"text":"→","textPreview":"→","textChars":1,"textLines":1,"bbox":[609,323,30,36]}
{"kind":"shape","id":"sh/do3id4fy","slide":9,"bbox":[640,190,265,316]}
{"kind":"textbox","id":"sh/qlcjipgn","slide":9,"text":"区域 / Region","textPreview":"区域 / Region","textChars":11,"textLines":1,"bbox":[662,214,220,46]}
{"kind":"textbox","id":"sh/bml0buxs","slide":9,"text":"推整改 / Drive action","textPreview":"推整改 / Drive action","textChars":18,"textLines":1,"bbox":[662,296,220,44]}
{"kind":"textbox","id":"sh/0ru1ozyp","slide":9,"text":"门店分级·任务·验收\nStore tiers · Tasks · Acceptance","textPreview":"门店分级·任务·验收 | Store tiers · Tasks · Acceptance","textChars":43,"textLines":2,"bbox":[662,386,220,72]}
{"kind":"textbox","id":"sh/lsn2h4fa","slide":9,"text":"→","textPreview":"→","textChars":1,"textLines":1,"bbox":[908,323,30,36]}
{"kind":"shape","id":"sh/98ji147e","slide":9,"bbox":[939,190,265,316]}
{"kind":"textbox","id":"sh/87a18zqt","slide":9,"text":"店长 / Store manager","textPreview":"店长 / Store manager","textChars":18,"textLines":1,"bbox":[961,214,220,46]}
{"kind":"textbox","id":"sh/76h0zup8","slide":9,"text":"做动作 / Execute","textPreview":"做动作 / Execute","textChars":13,"textLines":1,"bbox":[961,296,220,44]}
{"kind":"textbox","id":"sh/ml8j6p8n","slide":9,"text":"日目标·偏差·行动建议\nDaily targets · Gaps · Actions","textPreview":"日目标·偏差·行动建议 | Daily targets · Gaps · Actions","textChars":42,"textLines":2,"bbox":[961,386,220,72]}
{"kind":"shape","id":"sh/hcji5o7a","slide":9,"bbox":[42,550,1196,60]}
{"kind":"textbox","id":"sh/wba1cjqp","slide":9,"text":"结果回到经营大盘:执行不是终点,改善结果才是。\nResults return to the operating view: completion is not the goal; improvement is.","textPreview":"结果回到经营大盘:执行不是终点,改善结果才是。 | Results return to the operating view: completion is not the goal; improvement is.","textChars":105,"textLines":2,"bbox":[66,567,1148,30]}
{"kind":"notes","id":"nt/udsvah03","slide":9,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/m90b6t0r","slide":10,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":7}
{"kind":"textbox","id":"sh/r6pcv6lw","slide":10,"text":"玄谋智脑 · 连锁企业经营决策\nXuanmou Intelligence · Multi-site Operations","textPreview":"玄谋智脑 · 连锁企业经营决策 | Xuanmou Intelligence · Multi-site Operations","textChars":60,"textLines":2,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/xc3mho32","slide":10,"text":"AI 给依据,经营决策仍由管理者负责\nAI provides evidence. Management owns the decision.","textPreview":"AI 给依据,经营决策仍由管理者负责 | AI provides evidence. Management owns the decision.","textChars":70,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/cbu58j2h","slide":10,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/zelojyl8","slide":10,"text":"10","textPreview":"10","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/ydcnatkn","slide":10,"bbox":[42,182,560,366]}
{"kind":"shape","id":"sh/l036l83y","slide":10,"bbox":[42,182,7,366]}
{"kind":"textbox","id":"sh/kzu5c32t","slide":10,"text":"AI 可以承担 / AI can support","textPreview":"AI 可以承担 / AI can support","textChars":24,"textLines":1,"bbox":[66,204,514,40]}
{"kind":"textbox","id":"sh/725onyl4","slide":10,"text":"· 理解并关联跨系统数据\n· 持续扫描异常\n· 穿透至门店、SKU、班次和订单\n· 调用行业规则与历史案例\n· 推演方案对利润和现金流的影响\n· 跟踪执行并验证结果","textPreview":"· 理解并关联跨系统数据 | · 持续扫描异常 | · 穿透至门店、SKU、班次和订单 | · 调用行业规则与历史案例 | · 推演方案对利润和现金流的影响 | · 跟踪执行并验证结果","textChars":82,"textLines":6,"bbox":[66,256,514,274]}
{"kind":"shape","id":"sh/m1cnetkj","slide":10,"bbox":[678,182,560,366]}
{"kind":"shape","id":"sh/s7yt4b21","slide":10,"bbox":[678,182,7,366]}
{"kind":"textbox","id":"sh/d87uxg3m","slide":10,"text":"必须由管理者决定 / Management must decide","textPreview":"必须由管理者决定 / Management must decide","textChars":33,"textLines":1,"bbox":[702,204,514,40]}
{"kind":"textbox","id":"sh/q5gb21kb","slide":10,"text":"· 价格调整\n· 人员处置\n· 供应商更换\n· 门店迁址与关停\n· 重大资源投入\n\n所有高影响决策都应留下依据、审批与执行记录。\nPrice changes · Personnel actions · Supplier changes · Store relocation or closure · Major investment\nAll high-impact decisions require evidence, approval and execution records.","textPreview":"· 价格调整 | · 人员处置 | · 供应商更换 | · 门店迁址与关停 | · 重大资源投入 | | 所有高影响决策都应留下依据、审批与执行记录。 | Price changes · Personnel actions · Supplier changes · Sto...","textChars":242,"textLines":9,"bbox":[702,256,514,274]}
{"kind":"notes","id":"nt/m90b6t0r","slide":10,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/jetc3ut0","slide":11,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":24}
{"kind":"textbox","id":"sh/g3qtkj6l","slide":11,"text":"玄谋智脑 · 连锁企业经营决策\nXuanmou Intelligence · Multi-site Operations","textPreview":"玄谋智脑 · 连锁企业经营决策 | Xuanmou Intelligence · Multi-site Operations","textChars":60,"textLines":2,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/xcryxg7y","slide":11,"text":"BI 解释过去,玄谋智脑推动下一步\nBI explains the past. Xuanmou drives the next action.","textPreview":"BI 解释过去,玄谋智脑推动下一步 | BI explains the past. Xuanmou drives the next action.","textChars":71,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/wbih4b6d","slide":11,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/n69grmpw","slide":11,"text":"11","textPreview":"11","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/250zy18b","slide":11,"bbox":[42,170,228,50]}
{"kind":"textbox","id":"sh/98rytw72","slide":11,"text":"维度 / Dimension","textPreview":"维度 / Dimension","textChars":14,"textLines":1,"bbox":[58,185,196,25]}
{"kind":"shape","id":"sh/o7ih0r6h","slide":11,"bbox":[270,170,410,50]}
{"kind":"textbox","id":"sh/72t03qp0","slide":11,"text":"普通 BI / Conventional BI","textPreview":"普通 BI / Conventional BI","textChars":23,"textLines":1,"bbox":[286,185,378,25]}
{"kind":"shape","id":"sh/61kzalof","slide":11,"bbox":[680,170,558,50]}
{"kind":"textbox","id":"sh/ofqtgnyt","slide":11,"text":"玄谋智脑 / Xuanmou Intelligence","textPreview":"玄谋智脑 / Xuanmou Intelligence","textChars":27,"textLines":1,"bbox":[696,185,526,25]}
{"kind":"shape","id":"sh/9gza9sze","slide":11,"bbox":[42,220,228,67]}
{"kind":"textbox","id":"sh/mdobedg3","slide":11,"text":"定位 / Role","textPreview":"定位 / Role","textChars":9,"textLines":1,"bbox":[58,238,196,38]}
{"kind":"shape","id":"sh/nehs7iho","slide":11,"bbox":[270,220,410,67]}
{"kind":"textbox","id":"sh/0b6tc3yx","slide":11,"text":"展示报表 / Display reports","textPreview":"展示报表 / Display reports","textChars":22,"textLines":1,"bbox":[286,238,378,38]}
{"kind":"shape","id":"sh/1cfa58zi","slide":11,"bbox":[680,220,558,67]}
{"kind":"textbox","id":"sh/epobatgr","slide":11,"text":"驱动经营决策与改善 / Drive decisions and improvement","textPreview":"驱动经营决策与改善 / Drive decisions and improvement","textChars":43,"textLines":1,"bbox":[696,238,526,38]}
{"kind":"shape","id":"sh/zaxs3yhc","slide":11,"bbox":[42,287,228,67]}
{"kind":"textbox","id":"sh/cn6t83y1","slide":11,"text":"业务语义 / Business context","textPreview":"业务语义 / Business context","textChars":23,"textLines":1,"bbox":[58,305,196,38]}
{"kind":"shape","id":"sh/dofa18z6","slide":11,"bbox":[270,287,410,67]}
{"kind":"textbox","id":"sh/tsnip0ny","slide":11,"text":"字段和指标 / Fields and metrics","textPreview":"字段和指标 / Fields and metrics","textChars":26,"textLines":1,"bbox":[286,305,378,38]}
{"kind":"shape","id":"sh/87ehgv6d","slide":11,"bbox":[680,287,558,67]}
{"kind":"textbox","id":"sh/7650nq5s","slide":11,"text":"门店、商品、人员、会员等行业本体\nIndustry ontology for stores, products, people and members","textPreview":"门店、商品、人员、会员等行业本体 | Industry ontology for stores, products, people and members","textChars":75,"textLines":2,"bbox":[696,305,526,38]}
{"kind":"shape","id":"sh/65wzelo7","slide":11,"bbox":[42,354,228,67]}
{"kind":"textbox","id":"sh/l43ilgn2","slide":11,"text":"问题发现 / Issue detection","textPreview":"问题发现 / Issue detection","textChars":22,"textLines":1,"bbox":[58,372,196,38]}
{"kind":"shape","id":"sh/k3uhcb6h","slide":11,"bbox":[270,354,410,67]}
{"kind":"textbox","id":"sh/j2lgjq5w","slide":11,"text":"人主动看数据 / People search the data","textPreview":"人主动看数据 / People search the data","textChars":31,"textLines":1,"bbox":[286,372,378,38]}
{"kind":"shape","id":"sh/y1czalob","slide":11,"bbox":[680,354,558,67]}
{"kind":"textbox","id":"sh/p07ixkn6","slide":11,"text":"系统持续发现、分级与推送\nSystem detects, prioritizes and alerts continuously","textPreview":"系统持续发现、分级与推送 | System detects, prioritizes and alerts continuously","textChars":64,"textLines":2,"bbox":[696,372,526,38]}
{"kind":"shape","id":"sh/4zyhofml","slide":11,"bbox":[42,421,228,67]}
{"kind":"textbox","id":"sh/m58fih43","slide":11,"text":"问题处理 / Issue resolution","textPreview":"问题处理 / Issue resolution","textChars":23,"textLines":1,"bbox":[58,439,196,38]}
{"kind":"shape","id":"sh/n61wbmlo","slide":11,"bbox":[270,421,410,67]}
{"kind":"textbox","id":"sh/o7axk7m9","slide":11,"text":"报告异常 / Report exceptions","textPreview":"报告异常 / Report exceptions","textChars":24,"textLines":1,"bbox":[286,439,378,38]}
{"kind":"shape","id":"sh/98jedc3u","slide":11,"bbox":[680,421,558,67]}
{"kind":"textbox","id":"sh/eh8fex47","slide":11,"text":"归因、测算、方案和整改任务\nRoot cause, impact, recommendation and action task","textPreview":"归因、测算、方案和整改任务 | Root cause, impact, recommendation and action task","textChars":64,"textLines":2,"bbox":[696,439,526,38]}
{"kind":"shape","id":"sh/z2hw72lc","slide":11,"bbox":[42,488,228,67]}
{"kind":"textbox","id":"sh/03qxg7mx","slide":11,"text":"结果验证 / Outcome validation","textPreview":"结果验证 / Outcome validation","textChars":25,"textLines":1,"bbox":[58,506,196,38]}
{"kind":"shape","id":"sh/14ze9c3i","slide":11,"bbox":[270,488,410,67]}
{"kind":"textbox","id":"sh/ydcfq1kb","slide":11,"text":"通常不跟踪 / Usually not tracked","textPreview":"通常不跟踪 / Usually not tracked","textChars":27,"textLines":1,"bbox":[286,506,378,38]}
{"kind":"shape","id":"sh/jylwj6lw","slide":11,"bbox":[680,488,558,67]}
{"kind":"textbox","id":"sh/3qhsfypc","slide":11,"text":"验证改善并更新最佳实践\nVerify improvement and update best practices","textPreview":"验证改善并更新最佳实践 | Verify improvement and update best practices","textChars":56,"textLines":2,"bbox":[696,506,526,38]}
{"kind":"shape","id":"sh/ip8bmtor","slide":11,"bbox":[42,555,228,67]}
{"kind":"textbox","id":"sh/5sjah872","slide":11,"text":"长期价值 / Long-term value","textPreview":"长期价值 / Long-term value","textChars":22,"textLines":1,"bbox":[58,573,196,38]}
{"kind":"shape","id":"sh/4rato36h","slide":11,"bbox":[270,555,410,67]}
{"kind":"textbox","id":"sh/v2hsbyp0","slide":11,"text":"报表越来越多 / More and more reports","textPreview":"报表越来越多 / More and more reports","textChars":30,"textLines":1,"bbox":[286,573,378,38]}
{"kind":"shape","id":"sh/u18bit8f","slide":11,"bbox":[680,555,558,67]}
{"kind":"textbox","id":"sh/h4zado76","slide":11,"text":"行业模型与企业知识越用越成熟\nIndustry models and company knowledge improve with use","textPreview":"行业模型与企业知识越用越成熟 | Industry models and company knowledge improve with use","textChars":69,"textLines":2,"bbox":[696,573,526,38]}
{"kind":"notes","id":"nt/jetc3ut0","slide":11,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/8f2psfyx","slide":12,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":23}
{"kind":"textbox","id":"sh/alwbitsn","slide":12,"text":"玄谋智脑 · 连锁企业经营决策\nXuanmou Intelligence · Multi-site Operations","textPreview":"玄谋智脑 · 连锁企业经营决策 | Xuanmou Intelligence · Multi-site Operations","textChars":60,"textLines":2,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/1gbm9s3a","slide":12,"text":"五项基础能力,支撑门店规模化管理\nFive capabilities that support scalable operations.","textPreview":"五项基础能力,支撑门店规模化管理 | Five capabilities that support scalable operations.","textChars":68,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/0f2lgnmp","slide":12,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ra943il8","slide":12,"text":"12","textPreview":"12","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/q903ad4n","slide":12,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[42,185,54,28]}
{"kind":"textbox","id":"sh/dcbm583y","slide":12,"text":"数据资产化 / Data foundation","textPreview":"数据资产化 / Data foundation","textChars":23,"textLines":1,"bbox":[118,171,250,54]}
{"kind":"textbox","id":"sh/sb2lcnmd","slide":12,"text":"数据通起来 / Connect the data","textPreview":"数据通起来 / Connect the data","textChars":24,"textLines":1,"bbox":[422,171,250,54]}
{"kind":"textbox","id":"sh/b6d4f2lc","slide":12,"text":"一个数字、一个来源 / One number, one source","textPreview":"一个数字、一个来源 / One number, one source","textChars":34,"textLines":1,"bbox":[720,171,450,54]}
{"kind":"shape","id":"sh/a543mx4r","slide":12,"bbox":[118,238,1050,0]}
{"kind":"textbox","id":"sh/wvupgz6t","slide":12,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[42,274,54,28]}
{"kind":"textbox","id":"sh/xw3q94ne","slide":12,"text":"运营指标化 / Operational metrics","textPreview":"运营指标化 / Operational metrics","textChars":27,"textLines":1,"bbox":[118,260,250,54]}
{"kind":"textbox","id":"sh/atc7epon","slide":12,"text":"问题浮出来 / Surface the issues","textPreview":"问题浮出来 / Surface the issues","textChars":26,"textLines":1,"bbox":[422,260,250,54]}
{"kind":"textbox","id":"sh/bulo7u58","slide":12,"text":"异常能穿透到根因 / Trace exceptions to root causes","textPreview":"异常能穿透到根因 / Trace exceptions to root causes","textChars":42,"textLines":1,"bbox":[720,260,450,54]}
{"kind":"shape","id":"sh/orapcf6h","slide":12,"bbox":[118,327,1050,0]}
{"kind":"textbox","id":"sh/9sj65kn2","slide":12,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[42,363,54,28]}
{"kind":"textbox","id":"sh/mps7a5or","slide":12,"text":"战略穿透化 / Strategy execution","textPreview":"战略穿透化 / Strategy execution","textChars":26,"textLines":1,"bbox":[118,349,250,54]}
{"kind":"textbox","id":"sh/nq1o3a5w","slide":12,"text":"目标落下去 / Translate goals into action","textPreview":"目标落下去 / Translate goals into action","textChars":35,"textLines":1,"bbox":[422,349,250,54]}
{"kind":"textbox","id":"sh/0nap8f6l","slide":12,"text":"战略到区域、门店和个人\nFrom strategy to regions, stores and individuals","textPreview":"战略到区域、门店和个人 | From strategy to regions, stores and individuals","textChars":60,"textLines":2,"bbox":[720,349,450,54]}
{"kind":"shape","id":"sh/1oj61kn6","slide":12,"bbox":[118,416,1050,0]}
{"kind":"textbox","id":"sh/hkbm5wzu","slide":12,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[42,452,54,28]}
{"kind":"textbox","id":"sh/gj25cry9","slide":12,"text":"态势感知化 / Risk sensing","textPreview":"态势感知化 / Risk sensing","textChars":20,"textLines":1,"bbox":[118,438,250,54]}
{"kind":"textbox","id":"sh/fit436ho","slide":12,"text":"风险早知道 / See risks earlier","textPreview":"风险早知道 / See risks earlier","textChars":25,"textLines":1,"bbox":[422,438,250,54]}
{"kind":"textbox","id":"sh/uh0na1g3","slide":12,"text":"从事后救火到事前预防 / Move from firefighting to prevention","textPreview":"从事后救火到事前预防 / Move from firefighting to prevention","textChars":49,"textLines":1,"bbox":[720,438,450,54]}
{"kind":"shape","id":"sh/tgrm1wzy","slide":12,"bbox":[118,505,1050,0]}
{"kind":"textbox","id":"sh/sfi58ryd","slide":12,"text":"05","textPreview":"05","textChars":2,"textLines":1,"bbox":[42,541,54,28]}
{"kind":"textbox","id":"sh/7u94zmhs","slide":12,"text":"知识沉淀化 / Knowledge capture","textPreview":"知识沉淀化 / Knowledge capture","textChars":25,"textLines":1,"bbox":[118,527,250,54]}
{"kind":"textbox","id":"sh/6t0n6hg7","slide":12,"text":"组织越来越聪明 / Make the organization smarter","textPreview":"组织越来越聪明 / Make the organization smarter","textChars":39,"textLines":1,"bbox":[422,527,250,54]}
{"kind":"textbox","id":"sh/dcv6dgz2","slide":12,"text":"优秀能力不再依赖少数人\nBest practices no longer depend on a few people","textPreview":"优秀能力不再依赖少数人 | Best practices no longer depend on a few people","textChars":59,"textLines":2,"bbox":[720,527,450,54]}
{"kind":"shape","id":"sh/cbm5kbyh","slide":12,"bbox":[118,594,1050,0]}
{"kind":"notes","id":"nt/8f2psfyx","slide":12,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/hgzapcr6","slide":13,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":15}
{"kind":"textbox","id":"sh/3yxgbqdg","slide":13,"text":"玄谋智脑 · 连锁企业经营决策\nXuanmou Intelligence · Multi-site Operations","textPreview":"玄谋智脑 · 连锁企业经营决策 | Xuanmou Intelligence · Multi-site Operations","textChars":60,"textLines":2,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/q50nydsj","slide":13,"text":"门店越多,复制优秀做法的价值越大\nThe larger the network, the greater the value of replication.","textPreview":"门店越多,复制优秀做法的价值越大 | The larger the network, the greater the value of replication.","textChars":78,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/bq9orito","slide":13,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/o3i5w3ad","slide":13,"text":"13","textPreview":"13","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/p4r6p8by","slide":13,"bbox":[42,182,360,250]}
{"kind":"shape","id":"sh/21gnuts7","slide":13,"bbox":[42,182,7,250]}
{"kind":"textbox","id":"sh/32ponyts","slide":13,"text":"不依赖能人 / Less dependence on star performers","textPreview":"不依赖能人 / Less dependence on star performers","textChars":42,"textLines":1,"bbox":[66,204,314,40]}
{"kind":"textbox","id":"sh/gzy5s3a1","slide":13,"text":"优秀店长的做法沉淀为规则、案例和 SOP。\nTurn strong store-manager practices into rules, cases and SOPs.","textPreview":"优秀店长的做法沉淀为规则、案例和 SOP。 | Turn strong store-manager practices into rules, cases and SOPs.","textChars":85,"textLines":2,"bbox":[66,256,314,158]}
{"kind":"shape","id":"sh/1076lobm","slide":13,"bbox":[443,182,360,250]}
{"kind":"shape","id":"sh/hcfy9k3u","slide":13,"bbox":[443,182,7,250]}
{"kind":"textbox","id":"sh/gb6x0zm9","slide":13,"text":"扩张不失控 / Scale without losing control","textPreview":"扩张不失控 / Scale without losing control","textChars":36,"textLines":1,"bbox":[467,204,314,40]}
{"kind":"textbox","id":"sh/vaxg7ulo","slide":13,"text":"验证有效的改善方案,可按门店特征分类复制。\nReplicate proven actions by store profile.","textPreview":"验证有效的改善方案,可按门店特征分类复制。 | Replicate proven actions by store profile.","textChars":64,"textLines":2,"bbox":[467,256,314,158]}
{"kind":"shape","id":"sh/u9ofyp43","slide":13,"bbox":[844,182,360,250]}
{"kind":"shape","id":"sh/t8fy5k3i","slide":13,"bbox":[844,182,7,250]}
{"kind":"textbox","id":"sh/876xwfmx","slide":13,"text":"能力持续复利 / Capabilities compound","textPreview":"能力持续复利 / Capabilities compound","textChars":30,"textLines":1,"bbox":[868,204,314,40]}
{"kind":"textbox","id":"sh/7mdg3als","slide":13,"text":"场景、模型、AI 建议与决策反馈相互增强。\nScenarios, models, AI recommendations and decision feedback reinforce one another.","textPreview":"场景、模型、AI 建议与决策反馈相互增强。 | Scenarios, models, AI recommendations and decision feedback reinforce one another.","textChars":104,"textLines":2,"bbox":[868,256,314,158]}
{"kind":"shape","id":"sh/6l4fu547","slide":13,"bbox":[120,520,980,0]}
{"kind":"shape","id":"sh/lkvy103m","slide":13,"bbox":[104,502,38,38]}
{"kind":"textbox","id":"sh/kjmxsfm1","slide":13,"text":"30 家 / 30 stores","textPreview":"30 家 / 30 stores","textChars":16,"textLines":1,"bbox":[94,555,150,28]}
{"kind":"textbox","id":"sh/cnqh8fux","slide":13,"text":"靠人盯 / Managed by people","textPreview":"靠人盯 / Managed by people","textChars":23,"textLines":1,"bbox":[94,589,170,24]}
{"kind":"shape","id":"sh/xozyhkbi","slide":13,"bbox":[584,502,38,38]}
{"kind":"textbox","id":"sh/q18f65cr","slide":13,"text":"100 家 / 100 stores","textPreview":"100 家 / 100 stores","textChars":18,"textLines":1,"bbox":[574,555,150,28]}
{"kind":"textbox","id":"sh/bmhgfatc","slide":13,"text":"靠机制 / Managed by process","textPreview":"靠机制 / Managed by process","textChars":24,"textLines":1,"bbox":[574,589,170,24]}
{"kind":"shape","id":"sh/oz6x4vul","slide":13,"bbox":[1064,502,38,38]}
{"kind":"textbox","id":"sh/p0zyd0b6","slide":13,"text":"300 家 / 300 stores","textPreview":"300 家 / 300 stores","textChars":18,"textLines":1,"bbox":[1054,555,150,28]}
{"kind":"textbox","id":"sh/2xof2lcv","slide":13,"text":"靠模型复制 / Scaled through models","textPreview":"靠模型复制 / Scaled through models","textChars":29,"textLines":1,"bbox":[1054,589,170,24]}
{"kind":"notes","id":"nt/hgzapcr6","slide":13,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/6lsnupw7","slide":14,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":8}
{"kind":"textbox","id":"sh/kre1k3y9","slide":14,"text":"玄谋智脑 · 连锁企业经营决策\nXuanmou Intelligence · Multi-site Operations","textPreview":"玄谋智脑 · 连锁企业经营决策 | Xuanmou Intelligence · Multi-site Operations","textChars":60,"textLines":2,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/xc7eds76","slide":14,"text":"真正的数据资产,是可追溯的经营能力\nA real data asset is a traceable operating capability.","textPreview":"真正的数据资产,是可追溯的经营能力 | A real data asset is a traceable operating capability.","textChars":72,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/wbydknq1","slide":14,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/jepwf2pc","slide":14,"text":"14","textPreview":"14","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/idgvmx8r","slide":14,"bbox":[42,180,560,365]}
{"kind":"shape","id":"sh/5grehs7i","slide":14,"bbox":[42,180,7,365]}
{"kind":"textbox","id":"sh/kfidonqx","slide":14,"text":"企业数据资产 / Enterprise data assets","textPreview":"企业数据资产 / Enterprise data assets","textChars":31,"textLines":1,"bbox":[66,202,514,40]}
{"kind":"textbox","id":"sh/zi5c3y98","slide":14,"text":"· 统一指标口径与责任关系\n· 门店、商品、人员、会员、供应商本体\n· 行业规则与异常模式\n· 决策、执行与验证结果\n· 最佳实践与风险知识\nCommon metric definitions and accountability · Business ontology · Industry rules · Decisions and validated outcomes · Best-practice knowledge","textPreview":"· 统一指标口径与责任关系 | · 门店、商品、人员、会员、供应商本体 | · 行业规则与异常模式 | · 决策、执行与验证结果 | · 最佳实践与风险知识 | Common metric definitions and accountability · Business ...","textChars":213,"textLines":6,"bbox":[66,254,514,273]}
{"kind":"shape","id":"sh/ehwvat8n","slide":14,"bbox":[678,180,560,365]}
{"kind":"shape","id":"sh/c3e1gjyd","slide":14,"bbox":[678,180,7,365]}
{"kind":"textbox","id":"sh/x4ni9ofy","slide":14,"text":"融资与尽调支持 / Financing and due-diligence support","textPreview":"融资与尽调支持 / Financing and due-diligence support","textChars":45,"textLines":1,"bbox":[702,202,514,40]}
{"kind":"textbox","id":"sh/a1wze9g7","slide":14,"text":"· 门店级损益与现金流\n· 收入稳定性分析\n· 风险预警与整改记录\n· 未来经营预测\n· 更完整、可追溯的经营证明\nStore-level P&L and cash flow · Revenue stability · Risk and remediation records · Forecasts · Traceable operating evidence","textPreview":"· 门店级损益与现金流 | · 收入稳定性分析 | · 风险预警与整改记录 | · 未来经营预测 | · 更完整、可追溯的经营证明 | Store-level P&L and cash flow · Revenue stability · Risk and remediat...","textChars":181,"textLines":6,"bbox":[702,254,514,273]}
{"kind":"textbox","id":"sh/b2507exs","slide":14,"text":"边界:提供数据与分析支持,不承诺银行授信或融资结果。\nScope: data and analytical support only; no promise of bank credit or financing outcomes.","textPreview":"边界:提供数据与分析支持,不承诺银行授信或融资结果。 | Scope: data and analytical support only; no promise of bank credit or financing outcomes.","textChars":116,"textLines":2,"bbox":[42,578,1000,34]}
{"kind":"notes","id":"nt/6lsnupw7","slide":14,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/vaxsvy10","slide":15,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":15}
{"kind":"textbox","id":"sh/cbuh8nmh","slide":15,"text":"玄谋智脑 · 连锁企业经营决策\nXuanmou Intelligence · Multi-site Operations","textPreview":"玄谋智脑 · 连锁企业经营决策 | Xuanmou Intelligence · Multi-site Operations","textChars":60,"textLines":2,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/547mhg3m","slide":15,"text":"生产数据必须留在清晰的安全边界内\nProduction data must remain within clear security boundaries.","textPreview":"生产数据必须留在清晰的安全边界内 | Production data must remain within clear security boundaries.","textChars":78,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/k3y5ov21","slide":15,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/76p4jqls","slide":15,"text":"15","textPreview":"15","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/65gnqlk7","slide":15,"bbox":[42,180,360,170]}
{"kind":"shape","id":"sh/t87ml0ji","slide":15,"bbox":[42,180,7,170]}
{"kind":"textbox","id":"sh/s7y5sv2x","slide":15,"text":"部署边界 / Deployment boundary","textPreview":"部署边界 / Deployment boundary","textChars":26,"textLines":1,"bbox":[66,202,314,40]}
{"kind":"textbox","id":"sh/na5476l8","slide":15,"text":"不替代现有交易系统,只读或受控对接。\nDoes not replace transaction systems; read-only or controlled integration.","textPreview":"不替代现有交易系统,只读或受控对接。 | Does not replace transaction systems; read-only or controlled integration.","textChars":93,"textLines":2,"bbox":[66,254,314,78]}
{"kind":"shape","id":"sh/m9c3e1kn","slide":15,"bbox":[443,180,360,170]}
{"kind":"shape","id":"sh/wrm9kvep","slide":15,"bbox":[443,180,7,170]}
{"kind":"textbox","id":"sh/hsvat0fa","slide":15,"text":"最小权限 / Least privilege","textPreview":"最小权限 / Least privilege","textChars":22,"textLines":1,"bbox":[467,202,314,40]}
{"kind":"textbox","id":"sh/upkrilwj","slide":15,"text":"老板、总部、区域、门店按职责查看。\nAccess by role across owner, head office, region and store.","textPreview":"老板、总部、区域、门店按职责查看。 | Access by role across owner, head office, region and store.","textChars":77,"textLines":2,"bbox":[467,254,314,78]}
{"kind":"shape","id":"sh/vqdsrqx4","slide":15,"bbox":[844,180,360,170]}
{"kind":"shape","id":"sh/4vm9ovel","slide":15,"bbox":[844,180,7,170]}
{"kind":"textbox","id":"sh/5wvax0f6","slide":15,"text":"敏感保护 / Sensitive-data protection","textPreview":"敏感保护 / Sensitive-data protection","textChars":32,"textLines":1,"bbox":[868,202,314,40]}
{"kind":"textbox","id":"sh/it4rm5wv","slide":15,"text":"会员、薪酬、财务明细分级、脱敏与审计。\nClassify, mask and audit member, payroll and financial details.","textPreview":"会员、薪酬、财务明细分级、脱敏与审计。 | Classify, mask and audit member, payroll and financial details.","textChars":83,"textLines":2,"bbox":[868,254,314,78]}
{"kind":"shape","id":"sh/judsvqxg","slide":15,"bbox":[42,390,360,170]}
{"kind":"shape","id":"sh/0z29cbyh","slide":15,"bbox":[42,390,7,170]}
{"kind":"textbox","id":"sh/l0bqlgf2","slide":15,"text":"AI 可追溯 / Traceable AI","textPreview":"AI 可追溯 / Traceable AI","textChars":21,"textLines":1,"bbox":[66,412,314,40]}
{"kind":"textbox","id":"sh/1kjyt83e","slide":15,"text":"重要结论显示依据、时间、路径和适用边界。\nKey conclusions show evidence, timing, logic and scope.","textPreview":"重要结论显示依据、时间、路径和适用边界。 | Key conclusions show evidence, timing, logic and scope.","textChars":76,"textLines":2,"bbox":[66,464,314,78]}
{"kind":"shape","id":"sh/gjax03m9","slide":15,"bbox":[443,390,360,170]}
{"kind":"shape","id":"sh/fi1grylo","slide":15,"bbox":[443,390,7,170]}
{"kind":"textbox","id":"sh/ehsfyt43","slide":15,"text":"人工审批 / Human approval","textPreview":"人工审批 / Human approval","textChars":21,"textLines":1,"bbox":[467,412,314,40]}
{"kind":"textbox","id":"sh/p8jyx83q","slide":15,"text":"高影响决策必须经有权限的管理者审批。\nHigh-impact decisions require approval by authorized management.","textPreview":"高影响决策必须经有权限的管理者审批。 | High-impact decisions require approval by authorized management.","textChars":83,"textLines":2,"bbox":[467,464,314,78]}
{"kind":"shape","id":"sh/o7ah4nm5","slide":15,"bbox":[844,390,360,170]}
{"kind":"shape","id":"sh/361gvilk","slide":15,"bbox":[844,390,7,170]}
{"kind":"textbox","id":"sh/25sf2d4z","slide":15,"text":"全程留痕 / Full audit trail","textPreview":"全程留痕 / Full audit trail","textChars":23,"textLines":1,"bbox":[868,412,314,40]}
{"kind":"textbox","id":"sh/dc3y1s3m","slide":15,"text":"访问、建议、修改、审批和执行结果均可审计。\nAccess, recommendations, edits, approvals and outcomes are auditable.","textPreview":"访问、建议、修改、审批和执行结果均可审计。 | Access, recommendations, edits, approvals and outcomes are auditable.","textChars":91,"textLines":2,"bbox":[868,464,314,78]}
{"kind":"notes","id":"nt/vaxsvy10","slide":15,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/gny5sjyp","slide":16,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":19}
{"kind":"textbox","id":"sh/ih0jedob","slide":16,"text":"玄谋智脑 · 连锁企业经营决策\nXuanmou Intelligence · Multi-site Operations","textPreview":"玄谋智脑 · 连锁企业经营决策 | Xuanmou Intelligence · Multi-site Operations","textChars":60,"textLines":2,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/8z2h8bq1","slide":16,"text":"先用 8 周证明价值,再决定扩大范围\nProve the value in eight weeks before scaling.","textPreview":"先用 8 周证明价值,再决定扩大范围 | Prove the value in eight weeks before scaling.","textChars":65,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/9kby1g7m","slide":16,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ytkf2h8j","slide":16,"text":"16","textPreview":"16","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/zutgvm94","slide":16,"bbox":[66,340,1100,0]}
{"kind":"shape","id":"sh/kv2h4rqp","slide":16,"bbox":[54,322,38,38]}
{"kind":"textbox","id":"sh/lwbyxwra","slide":16,"text":"第 1 周 / Week 1","textPreview":"第 1 周 / Week 1","textChars":14,"textLines":1,"bbox":[49,206,200,28]}
{"kind":"textbox","id":"sh/ip4zel83","slide":16,"text":"选定利润专项 / Select a profit initiative","textPreview":"选定利润专项 / Select a profit initiative","textChars":35,"textLines":1,"bbox":[49,250,205,55]}
{"kind":"textbox","id":"sh/3qdg7qpo","slide":16,"text":"基线·口径·责任人\nBaseline · Definition · Owner","textPreview":"基线·口径·责任人 | Baseline · Definition · Owner","textChars":39,"textLines":2,"bbox":[49,394,205,84]}
{"kind":"shape","id":"sh/fm1gzq5o","slide":16,"bbox":[293,322,38,38]}
{"kind":"textbox","id":"sh/e1sf65o3","slide":16,"text":"第 1—2 周 / Weeks 12","textPreview":"第 1—2 周 / Weeks 12","textChars":19,"textLines":1,"bbox":[288,206,200,28]}
{"kind":"textbox","id":"sh/1ojy10ne","slide":16,"text":"连接现有数据 / Connect existing data","textPreview":"连接现有数据 / Connect existing data","textChars":30,"textLines":1,"bbox":[288,250,205,55]}
{"kind":"textbox","id":"sh/gnax8v6t","slide":16,"text":"数据清单·质量·统一口径\nData inventory · Quality · Common definitions","textPreview":"数据清单·质量·统一口径 | Data inventory · Quality · Common definitions","textChars":58,"textLines":2,"bbox":[288,394,205,84]}
{"kind":"shape","id":"sh/nqlg3a5k","slide":16,"bbox":[532,322,38,38]}
{"kind":"textbox","id":"sh/2pcfa5oz","slide":16,"text":"第 3—4 周 / Weeks 34","textPreview":"第 3—4 周 / Weeks 34","textChars":19,"textLines":1,"bbox":[527,206,200,28]}
{"kind":"textbox","id":"sh/ps3y5knq","slide":16,"text":"发现机会与根因 / Find opportunities and causes","textPreview":"发现机会与根因 / Find opportunities and causes","textChars":39,"textLines":1,"bbox":[527,250,205,55]}
{"kind":"textbox","id":"sh/oruhcf65","slide":16,"text":"异常·影响金额·证据\nException · Financial impact · Evidence","textPreview":"异常·影响金额·证据 | Exception · Financial impact · Evidence","textChars":50,"textLines":2,"bbox":[527,394,205,84]}
{"kind":"shape","id":"sh/bulg7u5g","slide":16,"bbox":[771,322,38,38]}
{"kind":"textbox","id":"sh/atczepob","slide":16,"text":"第 5—6 周 / Weeks 56","textPreview":"第 5—6 周 / Weeks 56","textChars":19,"textLines":1,"bbox":[766,206,200,28]}
{"kind":"textbox","id":"sh/mpgj6t8j","slide":16,"text":"推动整改 / Drive corrective action","textPreview":"推动整改 / Drive corrective action","textChars":30,"textLines":1,"bbox":[766,250,205,55]}
{"kind":"textbox","id":"sh/7qp0zepo","slide":16,"text":"任务·期限·执行记录\nTask · Deadline · Execution record","textPreview":"任务·期限·执行记录 | Task · Deadline · Execution record","textChars":45,"textLines":2,"bbox":[766,394,205,84]}
{"kind":"shape","id":"sh/8by18jq9","slide":16,"bbox":[1010,322,38,38]}
{"kind":"textbox","id":"sh/9c7i1o7u","slide":16,"text":"第 7—8 周 / Weeks 78","textPreview":"第 7—8 周 / Weeks 78","textChars":19,"textLines":1,"bbox":[1005,206,200,28]}
{"kind":"textbox","id":"sh/ylwj2987","slide":16,"text":"验证并复制 / Verify and replicate","textPreview":"验证并复制 / Verify and replicate","textChars":28,"textLines":1,"bbox":[1005,250,205,55]}
{"kind":"textbox","id":"sh/zm50veps","slide":16,"text":"改善金额·验收·最佳实践\nImprovement value · Acceptance · Best practice","textPreview":"改善金额·验收·最佳实践 | Improvement value · Acceptance · Best practice","textChars":59,"textLines":2,"bbox":[1005,394,205,84]}
{"kind":"shape","id":"sh/kne14jqd","slide":16,"bbox":[42,550,1196,60]}
{"kind":"textbox","id":"sh/lo7ixo7y","slide":16,"text":"优先选择:数据可获得 · 影响可测算 · 动作可执行 · 八周可验证。\nPrioritize cases with available data, measurable impact, executable actions and results verifiable in eight weeks.","textPreview":"优先选择:数据可获得 · 影响可测算 · 动作可执行 · 八周可验证。 | Prioritize cases with available data, measurable impact, executable actions and results verifiable ...","textChars":150,"textLines":2,"bbox":[66,567,1148,30]}
{"kind":"notes","id":"nt/gny5sjyp","slide":16,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/14bup87q","slide":17,"title":"玄谋智脑 · 连锁企业经营决策","textShapes":19}
{"kind":"textbox","id":"sh/ytc7a1gv","slide":17,"text":"玄谋智脑 · 连锁企业经营决策\nXuanmou Intelligence · Multi-site Operations","textPreview":"玄谋智脑 · 连锁企业经营决策 | Xuanmou Intelligence · Multi-site Operations","textChars":60,"textLines":2,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/1c7e50ni","slide":17,"text":"验收看经营改善,不看功能数量\nMeasure business improvement, not feature count.","textPreview":"验收看经营改善,不看功能数量 | Measure business improvement, not feature count.","textChars":63,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/gbedwfmx","slide":17,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/rm5czq50","slide":17,"text":"17","textPreview":"17","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/6lwvql4v","slide":17,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[42,188,50,26]}
{"kind":"textbox","id":"sh/t8ne10n6","slide":17,"text":"经营结果 / Business outcomes","textPreview":"经营结果 / Business outcomes","textChars":24,"textLines":1,"bbox":[112,174,230,48]}
{"kind":"textbox","id":"sh/snedsvml","slide":17,"text":"贡献利润·成本·损耗·库存资金\nContribution profit · Cost · Waste · Inventory cash","textPreview":"贡献利润·成本·损耗·库存资金 | Contribution profit · Cost · Waste · Inventory cash","textChars":67,"textLines":2,"bbox":[395,174,760,48]}
{"kind":"shape","id":"sh/jilcvq54","slide":17,"bbox":[112,239,1040,0]}
{"kind":"textbox","id":"sh/ihcvml4j","slide":17,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[42,274,50,26]}
{"kind":"textbox","id":"sh/4by9or6l","slide":17,"text":"问题发现 / Issue detection","textPreview":"问题发现 / Issue detection","textChars":22,"textLines":1,"bbox":[112,260,230,48]}
{"kind":"textbox","id":"sh/pc7qhwn6","slide":17,"text":"发现周期·有效异常率·影响覆盖\nDetection cycle · Valid-exception rate · Impact coverage","textPreview":"发现周期·有效异常率·影响覆盖 | Detection cycle · Valid-exception rate · Impact coverage","textChars":72,"textLines":2,"bbox":[395,260,760,48]}
{"kind":"shape","id":"sh/29grm1of","slide":17,"bbox":[112,325,1040,0]}
{"kind":"textbox","id":"sh/3ap8fm50","slide":17,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[42,360,50,26]}
{"kind":"textbox","id":"sh/gnepkr69","slide":17,"text":"执行闭环 / Execution loop","textPreview":"执行闭环 / Execution loop","textChars":21,"textLines":1,"bbox":[112,346,230,48]}
{"kind":"textbox","id":"sh/honqdwnu","slide":17,"text":"接收率·按期完成率·整改有效率\nAcceptance · On-time completion · Remediation effectiveness","textPreview":"接收率·按期完成率·整改有效率 | Acceptance · On-time completion · Remediation effectiveness","textChars":75,"textLines":2,"bbox":[395,346,760,48]}
{"kind":"shape","id":"sh/ulw7ihoj","slide":17,"bbox":[112,411,1040,0]}
{"kind":"textbox","id":"sh/fm58bm54","slide":17,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[42,446,50,26]}
{"kind":"textbox","id":"sh/0ji9wb6t","slide":17,"text":"组织复制 / Organizational replication","textPreview":"组织复制 / Organizational replication","textChars":33,"textLines":1,"bbox":[112,432,230,48]}
{"kind":"textbox","id":"sh/14rqpgne","slide":17,"text":"复制门店数·成功率·新店导入时间\nStores replicated · Success rate · New-store ramp time","textPreview":"复制门店数·成功率·新店导入时间 | Stores replicated · Success rate · New-store ramp time","textChars":71,"textLines":2,"bbox":[395,432,760,48]}
{"kind":"shape","id":"sh/90nq9gfi","slide":17,"bbox":[112,497,1040,0]}
{"kind":"textbox","id":"sh/8ze9gbyx","slide":17,"text":"05","textPreview":"05","textChars":2,"textLines":1,"bbox":[42,532,50,26]}
{"kind":"textbox","id":"sh/ny5876xc","slide":17,"text":"数据质量 / Data quality","textPreview":"数据质量 / Data quality","textChars":19,"textLines":1,"bbox":[112,518,230,48]}
{"kind":"textbox","id":"sh/mxw7e1gr","slide":17,"text":"口径一致·完整·及时·可追溯\nConsistent · Complete · Timely · Traceable","textPreview":"口径一致·完整·及时·可追溯 | Consistent · Complete · Timely · Traceable","textChars":57,"textLines":2,"bbox":[395,518,760,48]}
{"kind":"shape","id":"sh/lwnq5gf6","slide":17,"bbox":[112,583,1040,0]}
{"kind":"shape","id":"sh/0vepcbyl","slide":17,"bbox":[42,612,1196,42]}
{"kind":"textbox","id":"sh/zul836xg","slide":17,"text":"项目启动时即确认基线、口径和外部影响因素,避免将自然波动误认为系统收益。\nAgree the baseline, definitions and external factors at launch so normal variation is not mistaken for system impact.","textPreview":"项目启动时即确认基线、口径和外部影响因素,避免将自然波动误认为系统收益。 | Agree the baseline, definitions and external factors at launch so normal variation is not mistaken...","textChars":154,"textLines":2,"bbox":[64,622,1152,24]}
{"kind":"notes","id":"nt/14bup87q","slide":17,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/y5wne50z","slide":18,"title":"玄谋智脑 / Xuanmou Intelligence","textShapes":4}
{"kind":"textbox","id":"sh/4felwzu5","slide":18,"text":"玄谋智脑 / Xuanmou Intelligence","textPreview":"玄谋智脑 / Xuanmou Intelligence","textChars":27,"textLines":1,"bbox":[42,35,240,30]}
{"kind":"textbox","id":"sh/wrelszu9","slide":18,"text":"先用 8 周,找到第一批可验证的利润机会\nStart with the first measurable profit opportunities.","textPreview":"先用 8 周,找到第一批可验证的利润机会 | Start with the first measurable profit opportunities.","textChars":74,"textLines":2,"bbox":[42,160,1040,210]}
{"kind":"textbox","id":"sh/hsn2l4bu","slide":18,"text":"再决定如何扩大应用范围 Scale only after the value is proven.","textPreview":"再决定如何扩大应用范围 Scale only after the value is proven.","textChars":50,"textLines":1,"bbox":[42,420,850,52]}
{"kind":"shape","id":"sh/itw3upcf","slide":18,"bbox":[42,610,1196,0]}
{"kind":"textbox","id":"sh/je5knut0","slide":18,"text":"让问题更早被发现 · 让整改真正落地 · 让每一次改善复制到更多门店\nFind issues earlier · Make corrective action stick · Replicate every proven improvement","textPreview":"让问题更早被发现 · 让整改真正落地 · 让每一次改善复制到更多门店 | Find issues earlier · Make corrective action stick · Replicate every proven improvement","textChars":122,"textLines":2,"bbox":[42,636,1100,30]}
{"kind":"notes","id":"nt/y5wne50z","slide":18,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates."}
@@ -0,0 +1,456 @@
{"kind":"deck","id":"pr/4a93p5","name":"Deck"}
{"kind":"layout","layoutId":"/ppt/slideMasters/slideMaster1.xml","name":"Master","type":"master"}
{"kind":"layout","layoutId":"/ppt/slideLayouts/slideLayout1.xml","name":"Title Slide","type":"title"}
{"kind":"slide","id":"sl/y90nupkv","slide":1,"title":"Xuanmou Intelligence 玄谋智脑","textShapes":4}
{"kind":"textbox","id":"sh/ts7md4r2","slide":1,"text":"Xuanmou Intelligence 玄谋智脑","textPreview":"Xuanmou Intelligence 玄谋智脑","textChars":26,"textLines":1,"bbox":[42,34,360,36]}
{"kind":"textbox","id":"sh/547294r6","slide":1,"text":"See the profit clearly. Run every store with confidence.\n看清利润,才谈得上管住门店","textPreview":"See the profit clearly. Run every store with confidence. | 看清利润,才谈得上管住门店","textChars":70,"textLines":2,"bbox":[42,180,990,180]}
{"kind":"textbox","id":"sh/k3yl0zql","slide":1,"text":"A decision intelligence layer for multi-site operators\n面向连锁企业的行业数字本体与 AI 经营智脑","textPreview":"A decision intelligence layer for multi-site operators | 面向连锁企业的行业数字本体与 AI 经营智脑","textChars":77,"textLines":2,"bbox":[42,402,870,48]}
{"kind":"shape","id":"sh/7qp4be9c","slide":1,"bbox":[42,615,1196,0]}
{"kind":"textbox","id":"sh/65g3298r","slide":1,"text":"Confidential external edition · Cases and figures are anonymized illustrations 对外保密版 · 案例与金额均为匿名示意","textPreview":"Confidential external edition · Cases and figures are anonymized illustrations 对外保密版 · 案例与金额均为匿名示意","textChars":99,"textLines":1,"bbox":[42,640,620,24]}
{"kind":"notes","id":"nt/y90nupkv","slide":1,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/hwbqtkby","slide":2,"title":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textShapes":13}
{"kind":"textbox","id":"sh/cnupgny5","slide":2,"text":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textPreview":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textChars":61,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/9072xkry","slide":2,"text":"Three decisions matter most to the owner.\n老板最终要判断三件事","textPreview":"Three decisions matter most to the owner. | 老板最终要判断三件事","textChars":52,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/ozy1ofad","slide":2,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/b29kza94","slide":2,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/a10jqpsj","slide":2,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[42,190,80,48]}
{"kind":"shape","id":"sh/x4r21kru","slide":2,"bbox":[42,248,350,0]}
{"kind":"textbox","id":"sh/w3i1sfa9","slide":2,"text":"Where are we losing money?\n哪里在亏钱?","textPreview":"Where are we losing money? | 哪里在亏钱?","textChars":33,"textLines":2,"bbox":[42,278,350,52]}
{"kind":"textbox","id":"sh/r65knqtk","slide":2,"text":"Which profit leaks across stores, SKUs, promotions, inventory and labor should be fixed first?\n门店、SKU、促销、库存、人力中,哪些利润漏洞最应该先处理?","textPreview":"Which profit leaks across stores, SKUs, promotions, inventory and labor should be fixed first? | 门店、SKU、促销、库存、人力中,哪些利润漏洞最应该先处理?","textChars":125,"textLines":2,"bbox":[42,352,350,140]}
{"kind":"textbox","id":"sh/q5wjelsz","slide":2,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[443,190,80,48]}
{"kind":"shape","id":"sh/ove9o7yd","slide":2,"bbox":[443,248,350,0]}
{"kind":"textbox","id":"sh/9wnqhczy","slide":2,"text":"Which actions will improve profit?\n哪些动作能增利?","textPreview":"Which actions will improve profit? | 哪些动作能增利?","textChars":43,"textLines":2,"bbox":[443,278,350,52]}
{"kind":"textbox","id":"sh/mtwrmxg7","slide":2,"text":"Quantify the impact, recommend actions, track execution and verify the outcome.\n不只找问题,还要测算影响、给出方案、跟踪执行并验证结果。","textPreview":"Quantify the impact, recommend actions, track execution and verify the outcome. | 不只找问题,还要测算影响、给出方案、跟踪执行并验证结果。","textChars":108,"textLines":2,"bbox":[443,352,350,140]}
{"kind":"textbox","id":"sh/nu58f2hs","slide":2,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[844,190,80,48]}
{"kind":"shape","id":"sh/wjy9sry9","slide":2,"bbox":[844,248,350,0]}
{"kind":"textbox","id":"sh/xk7qlczu","slide":2,"text":"Can we stay in control as we scale?\n扩张后还能管住吗?","textPreview":"Can we stay in control as we scale? | 扩张后还能管住吗?","textChars":45,"textLines":2,"bbox":[844,278,350,52]}
{"kind":"textbox","id":"sh/ahwrqhgj","slide":2,"text":"Can proven practices be replicated from 30 to 300 stores, consistently and at low cost?\n从 30 家到 300 家门店,有效经验能否被低成本、高质量地复制?","textPreview":"Can proven practices be replicated from 30 to 300 stores, consistently and at low cost? | 从 30 家到 300 家门店,有效经验能否被低成本、高质量地复制?","textChars":122,"textLines":2,"bbox":[844,352,350,140]}
{"kind":"textbox","id":"sh/bip8jmho","slide":2,"text":"The goal is not more reports, but measurable operating improvement. 不是看更多报表,而是将数据转化为可验证的经营改善。","textPreview":"The goal is not more reports, but measurable operating improvement. 不是看更多报表,而是将数据转化为可验证的经营改善。","textChars":94,"textLines":1,"bbox":[42,590,1100,42]}
{"kind":"notes","id":"nt/hwbqtkby","slide":2,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/ofy9wn61","slide":3,"title":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textShapes":15}
{"kind":"textbox","id":"sh/batgjixs","slide":3,"text":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textPreview":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textChars":61,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/cza94vmx","slide":3,"text":"Plenty of data, but no clear view of where profit goes.\n数据很多,利润去向仍然说不清","textPreview":"Plenty of data, but no clear view of where profit goes. | 数据很多,利润去向仍然说不清","textChars":70,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/d0jax03i","slide":3,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/298ryl4v","slide":3,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/3ah8rqlg","slide":3,"bbox":[42,188,360,160]}
{"kind":"shape","id":"sh/obq90bml","slide":3,"bbox":[42,188,7,160]}
{"kind":"textbox","id":"sh/pcjqtg36","slide":3,"text":"Revenue 营收","textPreview":"Revenue 营收","textChars":11,"textLines":1,"bbox":[66,210,314,40]}
{"kind":"textbox","id":"sh/m5cra54z","slide":3,"text":"Why is profit not keeping pace with revenue?\n营收增长,利润为何没有同步?","textPreview":"Why is profit not keeping pace with revenue? | 营收增长,利润为何没有同步?","textChars":59,"textLines":2,"bbox":[66,262,314,68]}
{"kind":"shape","id":"sh/n6ls3alk","slide":3,"bbox":[443,188,360,160]}
{"kind":"shape","id":"sh/n2l4fq98","slide":3,"bbox":[443,188,7,160]}
{"kind":"textbox","id":"sh/m1c3mlsn","slide":3,"text":"Stores 门店","textPreview":"Stores 门店","textChars":10,"textLines":1,"bbox":[467,210,314,40]}
{"kind":"textbox","id":"sh/943mhgre","slide":3,"text":"Which stores appear profitable but tie up cash?\n哪些门店看似赚钱,实际占用资金?","textPreview":"Which stores appear profitable but tie up cash? | 哪些门店看似赚钱,实际占用资金?","textChars":64,"textLines":2,"bbox":[467,262,314,68]}
{"kind":"shape","id":"sh/83ulovat","slide":3,"bbox":[844,188,360,160]}
{"kind":"shape","id":"sh/v6l4jq94","slide":3,"bbox":[844,188,7,160]}
{"kind":"textbox","id":"sh/a5c3ql8z","slide":3,"text":"Promotions 促销","textPreview":"Promotions 促销","textChars":14,"textLines":1,"bbox":[868,210,314,40]}
{"kind":"textbox","id":"sh/x8nml0ra","slide":3,"text":"Which campaigns add orders but destroy profit?\n哪些活动增加订单,却消耗利润?","textPreview":"Which campaigns add orders but destroy profit? | 哪些活动增加订单,却消耗利润?","textChars":62,"textLines":2,"bbox":[868,262,314,68]}
{"kind":"shape","id":"sh/w7ulsvqp","slide":3,"bbox":[42,390,360,160]}
{"kind":"shape","id":"sh/ja54na9g","slide":3,"bbox":[42,390,7,160]}
{"kind":"textbox","id":"sh/i9w3u58v","slide":3,"text":"SKU","textPreview":"SKU","textChars":3,"textLines":1,"bbox":[66,412,314,40]}
{"kind":"textbox","id":"sh/e10f2twf","slide":3,"text":"Which products sell well but contribute too little margin?\n哪些商品销量不低,却毛利不足?","textPreview":"Which products sell well but contribute too little margin? | 哪些商品销量不低,却毛利不足?","textChars":74,"textLines":2,"bbox":[66,464,314,68]}
{"kind":"shape","id":"sh/f29gbyx0","slide":3,"bbox":[443,390,360,160]}
{"kind":"shape","id":"sh/03ix43e5","slide":3,"bbox":[443,390,7,160]}
{"kind":"textbox","id":"sh/14ryd8fq","slide":3,"text":"Labor 人力","textPreview":"Labor 人力","textChars":9,"textLines":1,"bbox":[467,412,314,40]}
{"kind":"textbox","id":"sh/6d0fytg3","slide":3,"text":"When are teams idle, yet understaffed at peak times?\n哪些时段人员闲置,高峰又缺人?","textPreview":"When are teams idle, yet understaffed at peak times? | 哪些时段人员闲置,高峰又缺人?","textChars":68,"textLines":2,"bbox":[467,464,314,68]}
{"kind":"shape","id":"sh/re9g7yxo","slide":3,"bbox":[844,390,360,160]}
{"kind":"shape","id":"sh/sfix03y9","slide":3,"bbox":[844,390,7,160]}
{"kind":"textbox","id":"sh/tgry9ofu","slide":3,"text":"Loss control 止损","textPreview":"Loss control 止损","textChars":16,"textLines":1,"bbox":[868,412,314,40]}
{"kind":"textbox","id":"sh/a9kfadwn","slide":3,"text":"Which stores should be fixed, relocated, resized or closed?\n哪些门店应整改、迁址、缩编或关停?","textPreview":"Which stores should be fixed, relocated, resized or closed? | 哪些门店应整改、迁址、缩编或关停?","textChars":77,"textLines":2,"bbox":[868,464,314,68]}
{"kind":"notes","id":"nt/ofy9wn61","slide":3,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/jyx0ra1s","slide":4,"title":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textShapes":22}
{"kind":"textbox","id":"sh/knex8j21","slide":4,"text":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textPreview":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textChars":61,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/1cj2d8b6","slide":4,"text":"Turn exceptions into actions with measurable outcomes.\n把异常处理成有结果的经营行动","textPreview":"Turn exceptions into actions with measurable outcomes. | 把异常处理成有结果的经营行动","textChars":69,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/0ba143al","slide":4,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/rm1k7yt4","slide":4,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/ql8jytsj","slide":4,"bbox":[82,350,1090,0]}
{"kind":"shape","id":"sh/doj29oba","slide":4,"bbox":[54,332,36,36]}
{"kind":"textbox","id":"sh/sna103ap","slide":4,"text":"1","textPreview":"1","textChars":1,"textLines":1,"bbox":[54,337,36,24]}
{"kind":"textbox","id":"sh/3ihk3et8","slide":4,"text":"Detect 发现","textPreview":"Detect 发现","textChars":10,"textLines":1,"bbox":[44,235,150,40]}
{"kind":"textbox","id":"sh/ih8ju9sn","slide":4,"text":"Profit exception\n利润异常","textPreview":"Profit exception | 利润异常","textChars":21,"textLines":2,"bbox":[44,400,164,78]}
{"kind":"shape","id":"sh/kbm987y5","slide":4,"bbox":[253,332,36,36]}
{"kind":"textbox","id":"sh/5cva1cfq","slide":4,"text":"2","textPreview":"2","textChars":1,"textLines":1,"bbox":[253,337,36,24]}
{"kind":"textbox","id":"sh/i94r6xgz","slide":4,"text":"Drill down 穿透","textPreview":"Drill down 穿透","textChars":14,"textLines":1,"bbox":[243,235,150,40]}
{"kind":"textbox","id":"sh/jadsz2xk","slide":4,"text":"Region · Store · SKU · Shift\n区域·门店·SKU·班次","textPreview":"Region · Store · SKU · Shift | 区域·门店·SKU·班次","textChars":41,"textLines":2,"bbox":[243,400,164,78]}
{"kind":"shape","id":"sh/w72947yt","slide":4,"bbox":[452,332,36,36]}
{"kind":"textbox","id":"sh/x8vaxsfe","slide":4,"text":"3","textPreview":"3","textChars":1,"textLines":1,"bbox":[452,337,36,24]}
{"kind":"textbox","id":"sh/a5kr2xg3","slide":4,"text":"Quantify 测算","textPreview":"Quantify 测算","textChars":12,"textLines":1,"bbox":[442,235,150,40]}
{"kind":"textbox","id":"sh/v6tsv2xo","slide":4,"text":"Financial impact and priority\n影响金额与优先级","textPreview":"Financial impact and priority | 影响金额与优先级","textChars":38,"textLines":2,"bbox":[442,400,164,78]}
{"kind":"shape","id":"sh/g36tgryd","slide":4,"bbox":[651,332,36,36]}
{"kind":"textbox","id":"sh/h4fa9wfy","slide":4,"text":"4","textPreview":"4","textChars":1,"textLines":1,"bbox":[651,337,36,24]}
{"kind":"textbox","id":"sh/p0batw72","slide":4,"text":"Act 整改","textPreview":"Act 整改","textChars":7,"textLines":1,"bbox":[641,235,150,40]}
{"kind":"textbox","id":"sh/oz29krqh","slide":4,"text":"Action · Owner · Deadline\n动作·责任人·期限","textPreview":"Action · Owner · Deadline | 动作·责任人·期限","textChars":35,"textLines":2,"bbox":[641,400,164,78]}
{"kind":"shape","id":"sh/3ytsrmpw","slide":4,"bbox":[850,332,36,36]}
{"kind":"textbox","id":"sh/2xkrih8b","slide":4,"text":"5","textPreview":"5","textChars":1,"textLines":1,"bbox":[850,337,36,24]}
{"kind":"textbox","id":"sh/1wbapc7q","slide":4,"text":"Verify 验证","textPreview":"Verify 验证","textChars":10,"textLines":1,"bbox":[840,235,150,40]}
{"kind":"textbox","id":"sh/gv29g7q5","slide":4,"text":"Confirm real profit improvement\n利润是否真正改善","textPreview":"Confirm real profit improvement | 利润是否真正改善","textChars":40,"textLines":2,"bbox":[840,400,164,78]}
{"kind":"shape","id":"sh/fu9sn2p0","slide":4,"bbox":[1049,332,36,36]}
{"kind":"textbox","id":"sh/et0reh8f","slide":4,"text":"6","textPreview":"6","textChars":1,"textLines":1,"bbox":[1049,337,36,24]}
{"kind":"textbox","id":"sh/tsrqlc7u","slide":4,"text":"Codify 沉淀","textPreview":"Codify 沉淀","textChars":10,"textLines":1,"bbox":[1039,235,150,40]}
{"kind":"textbox","id":"sh/sri9s7q9","slide":4,"text":"Update company best practices\n更新企业最佳实践","textPreview":"Update company best practices | 更新企业最佳实践","textChars":38,"textLines":2,"bbox":[1039,400,164,78]}
{"kind":"shape","id":"sh/ilwf69kv","slide":4,"bbox":[42,552,1196,58]}
{"kind":"textbox","id":"sh/jm5gze1g","slide":4,"text":"The value lies in turning issues into repeatable profit improvement. 关键不是“发现问题”,而是“把问题变成可复制的利润改善”。","textPreview":"The value lies in turning issues into repeatable profit improvement. 关键不是“发现问题”,而是“把问题变成可复制的利润改善”。","textChars":99,"textLines":1,"bbox":[66,568,1148,30]}
{"kind":"notes","id":"nt/jyx0ra1s","slide":4,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/i107q5of","slide":5,"title":"Anonymous composite case · SKU portfolio 匿名复合案例 · SKU 组合决策","textShapes":15}
{"kind":"textbox","id":"sh/fe94nm1w","slide":5,"text":"Anonymous composite case · SKU portfolio 匿名复合案例 · SKU 组合决策","textPreview":"Anonymous composite case · SKU portfolio 匿名复合案例 · SKU 组合决策","textChars":59,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/dgbulwnm","slide":5,"text":"More SKUs often mean more cost, not more choice.\nSKU 过多,往往增加的是复杂度和成本","textPreview":"More SKUs often mean more cost, not more choice. | SKU 过多,往往增加的是复杂度和成本","textChars":68,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/cf2tcr61","slide":5,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/z2tcnm5s","slide":5,"text":"05","textPreview":"05","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/yhkbe1o7","slide":5,"text":"480","textPreview":"480","textChars":3,"textLines":1,"bbox":[42,182,190,72]}
{"kind":"textbox","id":"sh/l4bupwny","slide":5,"text":"Active SKUs 在售 SKU","textPreview":"Active SKUs 在售 SKU","textChars":19,"textLines":1,"bbox":[42,256,190,30]}
{"kind":"textbox","id":"sh/032tgr6d","slide":5,"text":"The bottom 20% of SKUs contribute about 3% of sales while continuously tying up inventory cash.\n后 20% SKU 仅贡献约 3% 销售额,却持续占用库存资金。","textPreview":"The bottom 20% of SKUs contribute about 3% of sales while continuously tying up inventory cash. | 后 20% SKU 仅贡献约 3% 销售额,却持续占用库存资金。","textChars":128,"textLines":2,"bbox":[262,190,800,76]}
{"kind":"shape","id":"sh/n6dcr65o","slide":5,"bbox":[42,328,270,170]}
{"kind":"textbox","id":"sh/m5kbi1oj","slide":5,"text":"37 items\n37 个","textPreview":"37 items | 37 个","textChars":13,"textLines":2,"bbox":[66,354,222,64]}
{"kind":"textbox","id":"sh/w32dkbuh","slide":5,"text":"Low sales · Low margin · High waste 低销量·低毛利·高损耗","textPreview":"Low sales · Low margin · High waste 低销量·低毛利·高损耗","textChars":48,"textLines":1,"bbox":[66,434,222,40]}
{"kind":"shape","id":"sh/x4vedgvm","slide":5,"bbox":[341,328,270,170]}
{"kind":"textbox","id":"sh/ahkvi1cb","slide":5,"text":"9 items\n9 个","textPreview":"9 items | 9 个","textChars":11,"textLines":2,"bbox":[365,354,222,64]}
{"kind":"textbox","id":"sh/v2twb6dw","slide":5,"text":"High sales but low profit contribution 高销量但低贡献利润","textPreview":"High sales but low profit contribution 高销量但低贡献利润","textChars":49,"textLines":1,"bbox":[365,434,222,40]}
{"kind":"shape","id":"sh/k7mxovud","slide":5,"bbox":[640,328,270,170]}
{"kind":"textbox","id":"sh/58vehgvy","slide":5,"text":"16 items\n16 个","textPreview":"16 items | 16 个","textChars":13,"textLines":2,"bbox":[664,354,222,64]}
{"kind":"textbox","id":"sh/i54fmlc7","slide":5,"text":"Shared or substitutable ingredients 可共享或替换原料","textPreview":"Shared or substitutable ingredients 可共享或替换原料","textChars":45,"textLines":1,"bbox":[664,434,222,40]}
{"kind":"shape","id":"sh/j6dwfqds","slide":5,"bbox":[939,328,270,170]}
{"kind":"textbox","id":"sh/sb6xsvu9","slide":5,"text":"22 items\n22 个","textPreview":"22 items | 22 个","textChars":13,"textLines":2,"bbox":[963,354,222,64]}
{"kind":"textbox","id":"sh/tcfel0vu","slide":5,"text":"Overlapping price points 价格带重叠","textPreview":"Overlapping price points 价格带重叠","textChars":31,"textLines":1,"bbox":[963,434,222,40]}
{"kind":"shape","id":"sh/hgrmpwj2","slide":5,"bbox":[42,535,1196,85]}
{"kind":"textbox","id":"sh/gfi5grih","slide":5,"text":"Illustrative estimate: release RMB 0.8m in inventory cash · reduce annual waste by RMB 0.35m · lift gross margin by about 0.6 pp 模拟测算:释放库存资金约 80 万元 · 年减少报损约 35 万元 · 综合毛利率提升约 0.6 个百分点","textPreview":"Illustrative estimate: release RMB 0.8m in inventory cash · reduce annual waste by RMB 0.35m · lift gross margin by about 0.6 pp 模拟测算:释放...","textChars":183,"textLines":1,"bbox":[68,558,1140,40]}
{"kind":"notes","id":"nt/i107q5of","slide":5,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/x8f69ofe","slide":6,"title":"Anonymous composite case · Store A-017 匿名复合案例 · 门店 A-017","textShapes":10}
{"kind":"textbox","id":"sh/svmt4v6t","slide":6,"text":"Anonymous composite case · Store A-017 匿名复合案例 · 门店 A-017","textPreview":"Anonymous composite case · Store A-017 匿名复合案例 · 门店 A-017","textChars":57,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/yhg7epsj","slide":6,"text":"Labor hours should follow demand.\n排班的关键,是工时跟着客流走","textPreview":"Labor hours should follow demand. | 排班的关键,是工时跟着客流走","textChars":48,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/zi98nu94","slide":6,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/87ipkzal","slide":6,"text":"06","textPreview":"06","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/98rqt4r6","slide":6,"bbox":[42,182,362,314]}
{"kind":"shape","id":"sh/ml07i9sv","slide":6,"bbox":[42,182,7,314]}
{"kind":"textbox","id":"sh/7m98ru9g","slide":6,"text":"Detect 发现","textPreview":"Detect 发现","textChars":10,"textLines":1,"bbox":[66,204,316,40]}
{"kind":"textbox","id":"sh/oryp8fah","slide":6,"text":"Idle labor on weekday mornings · Understaffed on Friday peaks · Habit-based shifts · Overtime concentrated in a few roles\n· 工作日上午存在闲置工时\n· 周五晚高峰经常缺人\n· 班次依据历史习惯\n· 加班集中在少数岗位","textPreview":"Idle labor on weekday mornings · Understaffed on Friday peaks · Habit-based shifts · Overtime concentrated in a few roles | · 工作日上午存在闲置工时...","textChars":170,"textLines":5,"bbox":[66,256,316,222]}
{"kind":"shape","id":"sh/pc76hkr2","slide":6,"bbox":[458,182,362,314]}
{"kind":"shape","id":"sh/h4bupgn6","slide":6,"bbox":[458,182,7,314]}
{"kind":"textbox","id":"sh/w32twb6l","slide":6,"text":"Actions 动作","textPreview":"Actions 动作","textChars":11,"textLines":1,"bbox":[482,204,316,40]}
{"kind":"textbox","id":"sh/v2tcn650","slide":6,"text":"Forecast every 30 minutes · Adjust shift times · Add hourly staff at peaks · Move prep ahead of demand\n· 按半小时预测工作量\n· 调整早晚班起止时间\n· 高峰增加小时工\n· 备餐前移至客流爬升前","textPreview":"Forecast every 30 minutes · Adjust shift times · Add hourly staff at peaks · Move prep ahead of demand | · 按半小时预测工作量 | · 调整早晚班起止时间 | · 高峰...","textChars":149,"textLines":5,"bbox":[482,256,316,222]}
{"kind":"shape","id":"sh/u1kbu1ov","slide":6,"bbox":[874,182,364,314]}
{"kind":"shape","id":"sh/5svutgni","slide":6,"bbox":[874,182,7,314]}
{"kind":"textbox","id":"sh/47mt0b6x","slide":6,"text":"Verify 验证","textPreview":"Verify 验证","textChars":10,"textLines":1,"bbox":[898,204,318,40]}
{"kind":"textbox","id":"sh/j6dcr65c","slide":6,"text":"Monitor labor cost, service speed and customer satisfaction together. Do not simply cut headcount.\n同时监控:\n\n· 人工成本\n· 出品时效\n· 顾客满意度\n\n避免单纯压缩人力。","textPreview":"Monitor labor cost, service speed and customer satisfaction together. Do not simply cut headcount. | 同时监控: | | · 人工成本 | · 出品时效 | · 顾客满意度...","textChars":138,"textLines":8,"bbox":[898,256,318,222]}
{"kind":"shape","id":"sh/i54bylor","slide":6,"bbox":[42,535,1196,85]}
{"kind":"textbox","id":"sh/twfux0ne","slide":6,"text":"Illustrative estimate: RMB 18k saved per store per month; about RMB 12.96m annual upside across 60 stores. 模拟测算:单店每月节约 1.8 万元;复制到 60 家门店,年度改善空间约 1,296 万元。","textPreview":"Illustrative estimate: RMB 18k saved per store per month; about RMB 12.96m annual upside across 60 stores. 模拟测算:单店每月节约 1.8 万元;复制到 60 家门店...","textChars":155,"textLines":1,"bbox":[66,557,1148,42]}
{"kind":"notes","id":"nt/x8f69ofe","slide":6,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/gnmp4jqx","slide":7,"title":"Anonymous composite case · Campaign X 匿名复合案例 · 营销活动 X","textShapes":17}
{"kind":"textbox","id":"sh/s3ml0v61","slide":7,"text":"Anonymous composite case · Campaign X 匿名复合案例 · 营销活动 X","textPreview":"Anonymous composite case · Campaign X 匿名复合案例 · 营销活动 X","textChars":54,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/cb2tkvap","slide":7,"text":"More orders do not always mean a profitable campaign.\n订单增长,不等于促销赚钱","textPreview":"More orders do not always mean a profitable campaign. | 订单增长,不等于促销赚钱","textChars":66,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/dcbud0ra","slide":7,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ydkbm5sv","slide":7,"text":"07","textPreview":"07","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/zedcfa9g","slide":7,"bbox":[42,186,350,170]}
{"kind":"textbox","id":"sh/kzmdova1","slide":7,"text":"+23%","textPreview":"+23%","textChars":4,"textLines":1,"bbox":[66,212,302,64]}
{"kind":"textbox","id":"sh/l0vuh0rm","slide":7,"text":"Order growth 订单增长","textPreview":"Order growth 订单增长","textChars":18,"textLines":1,"bbox":[66,292,302,40]}
{"kind":"shape","id":"sh/eh0ba1sr","slide":7,"bbox":[42,378,350,170]}
{"kind":"textbox","id":"sh/fi9c369c","slide":7,"text":"Negative\n负值","textPreview":"Negative | 负值","textChars":11,"textLines":2,"bbox":[66,404,302,64]}
{"kind":"textbox","id":"sh/baxkjqlk","slide":7,"text":"Campaign contribution after full costs 穿透成本后的活动贡献利润","textPreview":"Campaign contribution after full costs 穿透成本后的活动贡献利润","textChars":52,"textLines":1,"bbox":[66,484,302,40]}
{"kind":"textbox","id":"sh/a9ojq5kz","slide":7,"text":"Why the campaign loses money 活动为什么亏钱","textPreview":"Why the campaign loses money 活动为什么亏钱","textChars":37,"textLines":1,"bbox":[454,186,360,40]}
{"kind":"textbox","id":"sh/xcz2l03q","slide":7,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[454,258,42,28]}
{"kind":"textbox","id":"sh/cbq1sv25","slide":7,"text":"More low-margin items in the mix 低毛利商品占比上升","textPreview":"More low-margin items in the mix 低毛利商品占比上升","textChars":43,"textLines":1,"bbox":[510,254,650,40]}
{"kind":"shape","id":"sh/n6x0fqlo","slide":7,"bbox":[510,300,650,0]}
{"kind":"textbox","id":"sh/25ojml43","slide":7,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[454,323,42,28]}
{"kind":"textbox","id":"sh/p8fih03e","slide":7,"text":"High-value members receive blanket discounts 高价值会员获得无差别优惠","textPreview":"High-value members receive blanket discounts 高价值会员获得无差别优惠","textChars":58,"textLines":1,"bbox":[510,319,650,40]}
{"kind":"shape","id":"sh/o761ov2t","slide":7,"bbox":[510,365,650,0]}
{"kind":"textbox","id":"sh/f2d0b6lc","slide":7,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[454,388,42,28]}
{"kind":"textbox","id":"sh/eh4jil4r","slide":7,"text":"Discounted orders replace full-price orders 促销订单替代了原价订单","textPreview":"Discounted orders replace full-price orders 促销订单替代了原价订单","textChars":56,"textLines":1,"bbox":[510,384,650,40]}
{"kind":"shape","id":"sh/id4ju1oz","slide":7,"bbox":[510,430,650,0]}
{"kind":"textbox","id":"sh/jedkn654","slide":7,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[454,453,42,28]}
{"kind":"textbox","id":"sh/4fm1wb6p","slide":7,"text":"Orders and revenue measured; incremental profit ignored 只评价订单和营收,没有评价增量利润","textPreview":"Orders and revenue measured; incremental profit ignored 只评价订单和营收,没有评价增量利润","textChars":74,"textLines":1,"bbox":[510,449,650,40]}
{"kind":"shape","id":"sh/50v2pgna","slide":7,"bbox":[510,495,650,0]}
{"kind":"shape","id":"sh/q143ylov","slide":7,"bbox":[454,544,746,67]}
{"kind":"textbox","id":"sh/r2dkrq5g","slide":7,"text":"Evaluate each campaign by contribution profit generated per RMB 1 of marketing spend. 用“每投入 1 元营销费用增加多少贡献利润”评价活动。","textPreview":"Evaluate each campaign by contribution profit generated per RMB 1 of marketing spend. 用“每投入 1 元营销费用增加多少贡献利润”评价活动。","textChars":114,"textLines":1,"bbox":[478,562,700,34]}
{"kind":"notes","id":"nt/gnmp4jqx","slide":7,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/fu1gfa1s","slide":8,"title":"Anonymous composite case · Store D-006 匿名复合案例 · 门店 D-006","textShapes":19}
{"kind":"textbox","id":"sh/07atgnmp","slide":8,"text":"Anonymous composite case · Store D-006 匿名复合案例 · 门店 D-006","textPreview":"Anonymous composite case · Store D-006 匿名复合案例 · 门店 D-006","textChars":57,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/18byd4zy","slide":8,"text":"Compare the options before deciding to close a store.\n关店前,先把四种选择算清楚","textPreview":"Compare the options before deciding to close a store. | 关店前,先把四种选择算清楚","textChars":67,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/g72x4zyd","slide":8,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ri9g7uhw","slide":8,"text":"08","textPreview":"08","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/6h0fypgb","slide":8,"bbox":[42,180,340,55]}
{"kind":"textbox","id":"sh/tkby9kzm","slide":8,"text":"Option 方案","textPreview":"Option 方案","textChars":10,"textLines":1,"bbox":[60,197,304,26]}
{"kind":"shape","id":"sh/sjix0zy1","slide":8,"bbox":[382,180,378,55]}
{"kind":"textbox","id":"sh/je9g3ahk","slide":8,"text":"12-month scenario 12 个月模拟结果","textPreview":"12-month scenario 12 个月模拟结果","textChars":28,"textLines":1,"bbox":[400,197,342,26]}
{"kind":"shape","id":"sh/id0fu50z","slide":8,"bbox":[760,180,478,55]}
{"kind":"textbox","id":"sh/o7ydoret","slide":8,"text":"Recommendation 决策建议","textPreview":"Recommendation 决策建议","textChars":20,"textLines":1,"bbox":[778,197,442,26]}
{"kind":"shape","id":"sh/98rehwve","slide":8,"bbox":[42,235,340,72]}
{"kind":"textbox","id":"sh/m5gvmhwn","slide":8,"text":"Continue operating 继续经营","textPreview":"Continue operating 继续经营","textChars":24,"textLines":1,"bbox":[60,256,304,35]}
{"kind":"shape","id":"sh/n6pwfmd8","slide":8,"bbox":[382,235,378,72]}
{"kind":"textbox","id":"sh/0jydkreh","slide":8,"text":"Estimated loss: RMB 0.92m 预计亏损 92 万","textPreview":"Estimated loss: RMB 0.92m 预计亏损 92 万","textChars":36,"textLines":1,"bbox":[400,256,342,35]}
{"kind":"shape","id":"sh/1k7edwv2","slide":8,"bbox":[760,235,478,72]}
{"kind":"textbox","id":"sh/ehgvihwr","slide":8,"text":"Not recommended 不建议","textPreview":"Not recommended 不建议","textChars":20,"textLines":1,"bbox":[778,256,442,35]}
{"kind":"shape","id":"sh/zipwbmdc","slide":8,"bbox":[42,307,340,72]}
{"kind":"textbox","id":"sh/kfixwbe1","slide":8,"text":"Invest in a turnaround 投入整改","textPreview":"Invest in a turnaround 投入整改","textChars":28,"textLines":1,"bbox":[60,328,304,35]}
{"kind":"shape","id":"sh/lgbepgvm","slide":8,"bbox":[382,307,378,72]}
{"kind":"textbox","id":"sh/tw7e9gnq","slide":8,"text":"Estimated loss falls to RMB 0.35m 预计亏损降至 35 万","textPreview":"Estimated loss falls to RMB 0.35m 预计亏损降至 35 万","textChars":46,"textLines":1,"bbox":[400,328,342,35]}
{"kind":"shape","id":"sh/svydgb65","slide":8,"bbox":[760,307,478,72]}
{"kind":"textbox","id":"sh/7u5w765k","slide":8,"text":"High risk; set a stop-loss 高风险,设止损线","textPreview":"High risk; set a stop-loss 高风险,设止损线","textChars":36,"textLines":1,"bbox":[778,328,442,35]}
{"kind":"shape","id":"sh/6twve1oz","slide":8,"bbox":[42,379,340,72]}
{"kind":"textbox","id":"sh/5sne5wne","slide":8,"text":"Reduce footprint 缩小面积","textPreview":"Reduce footprint 缩小面积","textChars":22,"textLines":1,"bbox":[60,400,304,35]}
{"kind":"shape","id":"sh/kredcr6t","slide":8,"bbox":[382,379,378,72]}
{"kind":"textbox","id":"sh/jq5w365o","slide":8,"text":"Near break-even 预计接近盈亏平衡","textPreview":"Near break-even 预计接近盈亏平衡","textChars":25,"textLines":1,"bbox":[400,400,342,35]}
{"kind":"shape","id":"sh/i5wva1o3","slide":8,"bbox":[760,379,478,72]}
{"kind":"textbox","id":"sh/x4ne1wni","slide":8,"text":"Consider if the lease can be renegotiated 租约可重谈时考虑","textPreview":"Consider if the lease can be renegotiated 租约可重谈时考虑","textChars":51,"textLines":1,"bbox":[778,400,442,35]}
{"kind":"shape","id":"sh/w3ed8r6x","slide":8,"bbox":[42,451,340,72]}
{"kind":"textbox","id":"sh/m9sb2x4v","slide":8,"text":"Close and migrate members 关停并迁移会员","textPreview":"Close and migrate members 关停并迁移会员","textChars":34,"textLines":1,"bbox":[60,472,304,35]}
{"kind":"shape","id":"sh/na1sb2lg","slide":8,"bbox":[382,451,378,72]}
{"kind":"textbox","id":"sh/8bat47ml","slide":8,"text":"Estimated loss reduction: RMB 0.76m 预计减少亏损 76 万","textPreview":"Estimated loss reduction: RMB 0.76m 预计减少亏损 76 万","textChars":48,"textLines":1,"bbox":[400,472,342,35]}
{"kind":"shape","id":"sh/9w3uds36","slide":8,"bbox":[760,451,478,72]}
{"kind":"textbox","id":"sh/y5sbed4j","slide":8,"text":"Preferred option 优先建议","textPreview":"Preferred option 优先建议","textChars":22,"textLines":1,"bbox":[778,472,442,35]}
{"kind":"textbox","id":"sh/z61s7il4","slide":8,"text":"AI does not close stores. It adds evidence, scenario analysis and an exit plan to management judgment. AI 不替老板关店;它让经验判断具有数据依据、情景测算和退出预案。","textPreview":"AI does not close stores. It adds evidence, scenario analysis and an exit plan to management judgment. AI 不替老板关店;它让经验判断具有数据依据、情景测算和退出预案。","textChars":137,"textLines":1,"bbox":[42,565,1160,44]}
{"kind":"notes","id":"nt/fu1gfa1s","slide":8,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/udsvah03","slide":9,"title":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textShapes":19}
{"kind":"textbox","id":"sh/va103ep4","slide":9,"text":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textPreview":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textChars":61,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/1cfmhgne","slide":9,"text":"One operating view, four levels of accountability.\n四级管理,各自看清该做的事","textPreview":"One operating view, four levels of accountability. | 四级管理,各自看清该做的事","textChars":64,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/0b65obm9","slide":9,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/nex4jq5k","slide":9,"text":"09","textPreview":"09","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/mdonql4z","slide":9,"bbox":[42,190,265,316]}
{"kind":"textbox","id":"sh/9gzml0nq","slide":9,"text":"Owner\n老板","textPreview":"Owner | 老板","textChars":8,"textLines":2,"bbox":[64,214,220,46]}
{"kind":"textbox","id":"sh/ofq5svm5","slide":9,"text":"Review outcomes 看结果","textPreview":"Review outcomes 看结果","textChars":20,"textLines":1,"bbox":[64,296,220,44]}
{"kind":"textbox","id":"sh/bih4na5w","slide":9,"text":"Profit · Risk · Capital allocation\n利润·风险·资源投向","textPreview":"Profit · Risk · Capital allocation | 利润·风险·资源投向","textChars":45,"textLines":2,"bbox":[64,386,220,72]}
{"kind":"textbox","id":"sh/ah8nu54b","slide":9,"text":"→","textPreview":"→","textChars":1,"textLines":1,"bbox":[310,323,30,36]}
{"kind":"shape","id":"sh/oza1gfyh","slide":9,"bbox":[341,190,265,316]}
{"kind":"textbox","id":"sh/p0ji9kf2","slide":9,"text":"Head office\n总部","textPreview":"Head office | 总部","textChars":14,"textLines":2,"bbox":[363,214,220,46]}
{"kind":"textbox","id":"sh/2xsjepgb","slide":9,"text":"Find causes 找原因","textPreview":"Find causes 找原因","textChars":16,"textLines":1,"bbox":[363,296,220,44]}
{"kind":"textbox","id":"sh/3y107axw","slide":9,"text":"Cross-region benchmarks · Policy review\n跨区域对标·政策评估","textPreview":"Cross-region benchmarks · Policy review | 跨区域对标·政策评估","textChars":50,"textLines":2,"bbox":[363,386,220,72]}
{"kind":"textbox","id":"sh/cnu1kzyd","slide":9,"text":"→","textPreview":"→","textChars":1,"textLines":1,"bbox":[609,323,30,36]}
{"kind":"shape","id":"sh/do3id4fy","slide":9,"bbox":[640,190,265,316]}
{"kind":"textbox","id":"sh/qlcjipgn","slide":9,"text":"Region\n区域","textPreview":"Region | 区域","textChars":9,"textLines":2,"bbox":[662,214,220,46]}
{"kind":"textbox","id":"sh/bml0buxs","slide":9,"text":"Drive action 推整改","textPreview":"Drive action 推整改","textChars":17,"textLines":1,"bbox":[662,296,220,44]}
{"kind":"textbox","id":"sh/0ru1ozyp","slide":9,"text":"Store tiers · Tasks · Acceptance\n门店分级·任务·验收","textPreview":"Store tiers · Tasks · Acceptance | 门店分级·任务·验收","textChars":43,"textLines":2,"bbox":[662,386,220,72]}
{"kind":"textbox","id":"sh/lsn2h4fa","slide":9,"text":"→","textPreview":"→","textChars":1,"textLines":1,"bbox":[908,323,30,36]}
{"kind":"shape","id":"sh/98ji147e","slide":9,"bbox":[939,190,265,316]}
{"kind":"textbox","id":"sh/87a18zqt","slide":9,"text":"Store manager\n店长","textPreview":"Store manager | 店长","textChars":16,"textLines":2,"bbox":[961,214,220,46]}
{"kind":"textbox","id":"sh/76h0zup8","slide":9,"text":"Execute 做动作","textPreview":"Execute 做动作","textChars":12,"textLines":1,"bbox":[961,296,220,44]}
{"kind":"textbox","id":"sh/ml8j6p8n","slide":9,"text":"Daily targets · Gaps · Actions\n日目标·偏差·行动建议","textPreview":"Daily targets · Gaps · Actions | 日目标·偏差·行动建议","textChars":42,"textLines":2,"bbox":[961,386,220,72]}
{"kind":"shape","id":"sh/hcji5o7a","slide":9,"bbox":[42,550,1196,60]}
{"kind":"textbox","id":"sh/wba1cjqp","slide":9,"text":"Results return to the operating view: completion is not the goal; improvement is. 结果回到经营大盘:执行不是终点,改善结果才是。","textPreview":"Results return to the operating view: completion is not the goal; improvement is. 结果回到经营大盘:执行不是终点,改善结果才是。","textChars":106,"textLines":1,"bbox":[66,567,1148,30]}
{"kind":"notes","id":"nt/udsvah03","slide":9,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/m90b6t0r","slide":10,"title":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textShapes":7}
{"kind":"textbox","id":"sh/r6pcv6lw","slide":10,"text":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textPreview":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textChars":61,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/xc3mho32","slide":10,"text":"AI provides evidence. Management owns the decision.\nAI 给依据,经营决策仍由管理者负责","textPreview":"AI provides evidence. Management owns the decision. | AI 给依据,经营决策仍由管理者负责","textChars":70,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/cbu58j2h","slide":10,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/zelojyl8","slide":10,"text":"10","textPreview":"10","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/ydcnatkn","slide":10,"bbox":[42,182,560,366]}
{"kind":"shape","id":"sh/l036l83y","slide":10,"bbox":[42,182,7,366]}
{"kind":"textbox","id":"sh/kzu5c32t","slide":10,"text":"AI can support AI 可以承担","textPreview":"AI can support AI 可以承担","textChars":23,"textLines":1,"bbox":[66,204,514,40]}
{"kind":"textbox","id":"sh/725onyl4","slide":10,"text":"· Connect and reconcile data across systems\n· Continuously scan for operating exceptions\n· Drill down to stores, SKUs, shifts and individual orders\n· Apply industry rules and relevant historical cases\n· Model the impact of each option on profit and cash flow\n· Track execution and verify the actual outcome\n· 理解并关联跨系统数据\n· 持续扫描异常\n· 穿透至门店、SKU、班次和订单\n· 调用行业规则与历史案例\n· 推演方案对利润和现金流的影响\n· 跟踪执行并验证结果","textPreview":"· Connect and reconcile data across systems | · Continuously scan for operating exceptions | · Drill down to stores, SKUs, shifts and ind...","textChars":389,"textLines":12,"bbox":[66,256,514,274]}
{"kind":"shape","id":"sh/m1cnetkj","slide":10,"bbox":[678,182,560,366]}
{"kind":"shape","id":"sh/s7yt4b21","slide":10,"bbox":[678,182,7,366]}
{"kind":"textbox","id":"sh/d87uxg3m","slide":10,"text":"Management must decide 必须由管理者决定","textPreview":"Management must decide 必须由管理者决定","textChars":32,"textLines":1,"bbox":[702,204,514,40]}
{"kind":"textbox","id":"sh/q5gb21kb","slide":10,"text":"Price changes · Personnel actions · Supplier changes · Store relocation or closure · Major investment\nAll high-impact decisions require evidence, approval and execution records.\n· 价格调整\n· 人员处置\n· 供应商更换\n· 门店迁址与关停\n· 重大资源投入\n\n所有高影响决策都应留下依据、审批与执行记录。","textPreview":"Price changes · Personnel actions · Supplier changes · Store relocation or closure · Major investment | All high-impact decisions require...","textChars":242,"textLines":9,"bbox":[702,256,514,274]}
{"kind":"notes","id":"nt/m90b6t0r","slide":10,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/jetc3ut0","slide":11,"title":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textShapes":24}
{"kind":"textbox","id":"sh/g3qtkj6l","slide":11,"text":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textPreview":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textChars":61,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/xcryxg7y","slide":11,"text":"BI explains the past. Xuanmou drives the next action.\nBI 解释过去,玄谋智脑推动下一步","textPreview":"BI explains the past. Xuanmou drives the next action. | BI 解释过去,玄谋智脑推动下一步","textChars":71,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/wbih4b6d","slide":11,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/n69grmpw","slide":11,"text":"11","textPreview":"11","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/250zy18b","slide":11,"bbox":[42,170,228,50]}
{"kind":"textbox","id":"sh/98rytw72","slide":11,"text":"Dimension 维度","textPreview":"Dimension 维度","textChars":13,"textLines":1,"bbox":[58,185,196,25]}
{"kind":"shape","id":"sh/o7ih0r6h","slide":11,"bbox":[270,170,410,50]}
{"kind":"textbox","id":"sh/72t03qp0","slide":11,"text":"Conventional BI 普通 BI","textPreview":"Conventional BI 普通 BI","textChars":22,"textLines":1,"bbox":[286,185,378,25]}
{"kind":"shape","id":"sh/61kzalof","slide":11,"bbox":[680,170,558,50]}
{"kind":"textbox","id":"sh/ofqtgnyt","slide":11,"text":"Xuanmou Intelligence 玄谋智脑","textPreview":"Xuanmou Intelligence 玄谋智脑","textChars":26,"textLines":1,"bbox":[696,185,526,25]}
{"kind":"shape","id":"sh/9gza9sze","slide":11,"bbox":[42,220,228,67]}
{"kind":"textbox","id":"sh/mdobedg3","slide":11,"text":"Role 定位","textPreview":"Role 定位","textChars":8,"textLines":1,"bbox":[58,238,196,38]}
{"kind":"shape","id":"sh/nehs7iho","slide":11,"bbox":[270,220,410,67]}
{"kind":"textbox","id":"sh/0b6tc3yx","slide":11,"text":"Display reports 展示报表","textPreview":"Display reports 展示报表","textChars":21,"textLines":1,"bbox":[286,238,378,38]}
{"kind":"shape","id":"sh/1cfa58zi","slide":11,"bbox":[680,220,558,67]}
{"kind":"textbox","id":"sh/epobatgr","slide":11,"text":"Drive decisions and improvement 驱动经营决策与改善","textPreview":"Drive decisions and improvement 驱动经营决策与改善","textChars":42,"textLines":1,"bbox":[696,238,526,38]}
{"kind":"shape","id":"sh/zaxs3yhc","slide":11,"bbox":[42,287,228,67]}
{"kind":"textbox","id":"sh/cn6t83y1","slide":11,"text":"Business context 业务语义","textPreview":"Business context 业务语义","textChars":22,"textLines":1,"bbox":[58,305,196,38]}
{"kind":"shape","id":"sh/dofa18z6","slide":11,"bbox":[270,287,410,67]}
{"kind":"textbox","id":"sh/tsnip0ny","slide":11,"text":"Fields and metrics 字段和指标","textPreview":"Fields and metrics 字段和指标","textChars":25,"textLines":1,"bbox":[286,305,378,38]}
{"kind":"shape","id":"sh/87ehgv6d","slide":11,"bbox":[680,287,558,67]}
{"kind":"textbox","id":"sh/7650nq5s","slide":11,"text":"Industry ontology for stores, products, people and members 门店、商品、人员、会员等行业本体","textPreview":"Industry ontology for stores, products, people and members 门店、商品、人员、会员等行业本体","textChars":76,"textLines":1,"bbox":[696,305,526,38]}
{"kind":"shape","id":"sh/65wzelo7","slide":11,"bbox":[42,354,228,67]}
{"kind":"textbox","id":"sh/l43ilgn2","slide":11,"text":"Issue detection 问题发现","textPreview":"Issue detection 问题发现","textChars":21,"textLines":1,"bbox":[58,372,196,38]}
{"kind":"shape","id":"sh/k3uhcb6h","slide":11,"bbox":[270,354,410,67]}
{"kind":"textbox","id":"sh/j2lgjq5w","slide":11,"text":"People search the data 人主动看数据","textPreview":"People search the data 人主动看数据","textChars":30,"textLines":1,"bbox":[286,372,378,38]}
{"kind":"shape","id":"sh/y1czalob","slide":11,"bbox":[680,354,558,67]}
{"kind":"textbox","id":"sh/p07ixkn6","slide":11,"text":"System detects, prioritizes and alerts continuously 系统持续发现、分级与推送","textPreview":"System detects, prioritizes and alerts continuously 系统持续发现、分级与推送","textChars":65,"textLines":1,"bbox":[696,372,526,38]}
{"kind":"shape","id":"sh/4zyhofml","slide":11,"bbox":[42,421,228,67]}
{"kind":"textbox","id":"sh/m58fih43","slide":11,"text":"Issue resolution 问题处理","textPreview":"Issue resolution 问题处理","textChars":22,"textLines":1,"bbox":[58,439,196,38]}
{"kind":"shape","id":"sh/n61wbmlo","slide":11,"bbox":[270,421,410,67]}
{"kind":"textbox","id":"sh/o7axk7m9","slide":11,"text":"Report exceptions 报告异常","textPreview":"Report exceptions 报告异常","textChars":23,"textLines":1,"bbox":[286,439,378,38]}
{"kind":"shape","id":"sh/98jedc3u","slide":11,"bbox":[680,421,558,67]}
{"kind":"textbox","id":"sh/eh8fex47","slide":11,"text":"Root cause, impact, recommendation and action task 归因、测算、方案和整改任务","textPreview":"Root cause, impact, recommendation and action task 归因、测算、方案和整改任务","textChars":65,"textLines":1,"bbox":[696,439,526,38]}
{"kind":"shape","id":"sh/z2hw72lc","slide":11,"bbox":[42,488,228,67]}
{"kind":"textbox","id":"sh/03qxg7mx","slide":11,"text":"Outcome validation 结果验证","textPreview":"Outcome validation 结果验证","textChars":24,"textLines":1,"bbox":[58,506,196,38]}
{"kind":"shape","id":"sh/14ze9c3i","slide":11,"bbox":[270,488,410,67]}
{"kind":"textbox","id":"sh/ydcfq1kb","slide":11,"text":"Usually not tracked 通常不跟踪","textPreview":"Usually not tracked 通常不跟踪","textChars":26,"textLines":1,"bbox":[286,506,378,38]}
{"kind":"shape","id":"sh/jylwj6lw","slide":11,"bbox":[680,488,558,67]}
{"kind":"textbox","id":"sh/3qhsfypc","slide":11,"text":"Verify improvement and update best practices 验证改善并更新最佳实践","textPreview":"Verify improvement and update best practices 验证改善并更新最佳实践","textChars":57,"textLines":1,"bbox":[696,506,526,38]}
{"kind":"shape","id":"sh/ip8bmtor","slide":11,"bbox":[42,555,228,67]}
{"kind":"textbox","id":"sh/5sjah872","slide":11,"text":"Long-term value 长期价值","textPreview":"Long-term value 长期价值","textChars":21,"textLines":1,"bbox":[58,573,196,38]}
{"kind":"shape","id":"sh/4rato36h","slide":11,"bbox":[270,555,410,67]}
{"kind":"textbox","id":"sh/v2hsbyp0","slide":11,"text":"More and more reports 报表越来越多","textPreview":"More and more reports 报表越来越多","textChars":29,"textLines":1,"bbox":[286,573,378,38]}
{"kind":"shape","id":"sh/u18bit8f","slide":11,"bbox":[680,555,558,67]}
{"kind":"textbox","id":"sh/h4zado76","slide":11,"text":"Industry models and company knowledge improve with use 行业模型与企业知识越用越成熟","textPreview":"Industry models and company knowledge improve with use 行业模型与企业知识越用越成熟","textChars":70,"textLines":1,"bbox":[696,573,526,38]}
{"kind":"notes","id":"nt/jetc3ut0","slide":11,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/8f2psfyx","slide":12,"title":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textShapes":23}
{"kind":"textbox","id":"sh/alwbitsn","slide":12,"text":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textPreview":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textChars":61,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/1gbm9s3a","slide":12,"text":"Five capabilities that support scalable operations.\n五项基础能力,支撑门店规模化管理","textPreview":"Five capabilities that support scalable operations. | 五项基础能力,支撑门店规模化管理","textChars":68,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/0f2lgnmp","slide":12,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ra943il8","slide":12,"text":"12","textPreview":"12","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/q903ad4n","slide":12,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[42,185,54,28]}
{"kind":"textbox","id":"sh/dcbm583y","slide":12,"text":"Data foundation\n数据资产化","textPreview":"Data foundation | 数据资产化","textChars":21,"textLines":2,"bbox":[118,171,250,54]}
{"kind":"textbox","id":"sh/sb2lcnmd","slide":12,"text":"Connect the data\n数据通起来","textPreview":"Connect the data | 数据通起来","textChars":22,"textLines":2,"bbox":[422,171,250,54]}
{"kind":"textbox","id":"sh/b6d4f2lc","slide":12,"text":"One number, one source\n一个数字、一个来源","textPreview":"One number, one source | 一个数字、一个来源","textChars":32,"textLines":2,"bbox":[720,171,450,54]}
{"kind":"shape","id":"sh/a543mx4r","slide":12,"bbox":[118,238,1050,0]}
{"kind":"textbox","id":"sh/wvupgz6t","slide":12,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[42,274,54,28]}
{"kind":"textbox","id":"sh/xw3q94ne","slide":12,"text":"Operational metrics\n运营指标化","textPreview":"Operational metrics | 运营指标化","textChars":25,"textLines":2,"bbox":[118,260,250,54]}
{"kind":"textbox","id":"sh/atc7epon","slide":12,"text":"Surface the issues\n问题浮出来","textPreview":"Surface the issues | 问题浮出来","textChars":24,"textLines":2,"bbox":[422,260,250,54]}
{"kind":"textbox","id":"sh/bulo7u58","slide":12,"text":"Trace exceptions to root causes\n异常能穿透到根因","textPreview":"Trace exceptions to root causes | 异常能穿透到根因","textChars":40,"textLines":2,"bbox":[720,260,450,54]}
{"kind":"shape","id":"sh/orapcf6h","slide":12,"bbox":[118,327,1050,0]}
{"kind":"textbox","id":"sh/9sj65kn2","slide":12,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[42,363,54,28]}
{"kind":"textbox","id":"sh/mps7a5or","slide":12,"text":"Strategy execution\n战略穿透化","textPreview":"Strategy execution | 战略穿透化","textChars":24,"textLines":2,"bbox":[118,349,250,54]}
{"kind":"textbox","id":"sh/nq1o3a5w","slide":12,"text":"Translate goals into action\n目标落下去","textPreview":"Translate goals into action | 目标落下去","textChars":33,"textLines":2,"bbox":[422,349,250,54]}
{"kind":"textbox","id":"sh/0nap8f6l","slide":12,"text":"From strategy to regions, stores and individuals\n战略到区域、门店和个人","textPreview":"From strategy to regions, stores and individuals | 战略到区域、门店和个人","textChars":60,"textLines":2,"bbox":[720,349,450,54]}
{"kind":"shape","id":"sh/1oj61kn6","slide":12,"bbox":[118,416,1050,0]}
{"kind":"textbox","id":"sh/hkbm5wzu","slide":12,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[42,452,54,28]}
{"kind":"textbox","id":"sh/gj25cry9","slide":12,"text":"Risk sensing\n态势感知化","textPreview":"Risk sensing | 态势感知化","textChars":18,"textLines":2,"bbox":[118,438,250,54]}
{"kind":"textbox","id":"sh/fit436ho","slide":12,"text":"See risks earlier\n风险早知道","textPreview":"See risks earlier | 风险早知道","textChars":23,"textLines":2,"bbox":[422,438,250,54]}
{"kind":"textbox","id":"sh/uh0na1g3","slide":12,"text":"Move from firefighting to prevention\n从事后救火到事前预防","textPreview":"Move from firefighting to prevention | 从事后救火到事前预防","textChars":47,"textLines":2,"bbox":[720,438,450,54]}
{"kind":"shape","id":"sh/tgrm1wzy","slide":12,"bbox":[118,505,1050,0]}
{"kind":"textbox","id":"sh/sfi58ryd","slide":12,"text":"05","textPreview":"05","textChars":2,"textLines":1,"bbox":[42,541,54,28]}
{"kind":"textbox","id":"sh/7u94zmhs","slide":12,"text":"Knowledge capture\n知识沉淀化","textPreview":"Knowledge capture | 知识沉淀化","textChars":23,"textLines":2,"bbox":[118,527,250,54]}
{"kind":"textbox","id":"sh/6t0n6hg7","slide":12,"text":"Make the organization smarter\n组织越来越聪明","textPreview":"Make the organization smarter | 组织越来越聪明","textChars":37,"textLines":2,"bbox":[422,527,250,54]}
{"kind":"textbox","id":"sh/dcv6dgz2","slide":12,"text":"Best practices no longer depend on a few people\n优秀能力不再依赖少数人","textPreview":"Best practices no longer depend on a few people | 优秀能力不再依赖少数人","textChars":59,"textLines":2,"bbox":[720,527,450,54]}
{"kind":"shape","id":"sh/cbm5kbyh","slide":12,"bbox":[118,594,1050,0]}
{"kind":"notes","id":"nt/8f2psfyx","slide":12,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/hgzapcr6","slide":13,"title":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textShapes":15}
{"kind":"textbox","id":"sh/3yxgbqdg","slide":13,"text":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textPreview":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textChars":61,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/q50nydsj","slide":13,"text":"The larger the network, the greater the value of replication.\n门店越多,复制优秀做法的价值越大","textPreview":"The larger the network, the greater the value of replication. | 门店越多,复制优秀做法的价值越大","textChars":78,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/bq9orito","slide":13,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/o3i5w3ad","slide":13,"text":"13","textPreview":"13","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/p4r6p8by","slide":13,"bbox":[42,182,360,250]}
{"kind":"shape","id":"sh/21gnuts7","slide":13,"bbox":[42,182,7,250]}
{"kind":"textbox","id":"sh/32ponyts","slide":13,"text":"Less dependence on star performers 不依赖能人","textPreview":"Less dependence on star performers 不依赖能人","textChars":41,"textLines":1,"bbox":[66,204,314,40]}
{"kind":"textbox","id":"sh/gzy5s3a1","slide":13,"text":"Turn strong store-manager practices into rules, cases and SOPs.\n优秀店长的做法沉淀为规则、案例和 SOP。","textPreview":"Turn strong store-manager practices into rules, cases and SOPs. | 优秀店长的做法沉淀为规则、案例和 SOP。","textChars":85,"textLines":2,"bbox":[66,256,314,158]}
{"kind":"shape","id":"sh/1076lobm","slide":13,"bbox":[443,182,360,250]}
{"kind":"shape","id":"sh/hcfy9k3u","slide":13,"bbox":[443,182,7,250]}
{"kind":"textbox","id":"sh/gb6x0zm9","slide":13,"text":"Scale without losing control 扩张不失控","textPreview":"Scale without losing control 扩张不失控","textChars":35,"textLines":1,"bbox":[467,204,314,40]}
{"kind":"textbox","id":"sh/vaxg7ulo","slide":13,"text":"Replicate proven actions by store profile.\n验证有效的改善方案,可按门店特征分类复制。","textPreview":"Replicate proven actions by store profile. | 验证有效的改善方案,可按门店特征分类复制。","textChars":64,"textLines":2,"bbox":[467,256,314,158]}
{"kind":"shape","id":"sh/u9ofyp43","slide":13,"bbox":[844,182,360,250]}
{"kind":"shape","id":"sh/t8fy5k3i","slide":13,"bbox":[844,182,7,250]}
{"kind":"textbox","id":"sh/876xwfmx","slide":13,"text":"Capabilities compound 能力持续复利","textPreview":"Capabilities compound 能力持续复利","textChars":29,"textLines":1,"bbox":[868,204,314,40]}
{"kind":"textbox","id":"sh/7mdg3als","slide":13,"text":"Scenarios, models, AI recommendations and decision feedback reinforce one another.\n场景、模型、AI 建议与决策反馈相互增强。","textPreview":"Scenarios, models, AI recommendations and decision feedback reinforce one another. | 场景、模型、AI 建议与决策反馈相互增强。","textChars":104,"textLines":2,"bbox":[868,256,314,158]}
{"kind":"shape","id":"sh/6l4fu547","slide":13,"bbox":[120,520,980,0]}
{"kind":"shape","id":"sh/lkvy103m","slide":13,"bbox":[104,502,38,38]}
{"kind":"textbox","id":"sh/kjmxsfm1","slide":13,"text":"30 stores 30 家","textPreview":"30 stores 30 家","textChars":15,"textLines":1,"bbox":[94,555,150,28]}
{"kind":"textbox","id":"sh/cnqh8fux","slide":13,"text":"Managed by people 靠人盯","textPreview":"Managed by people 靠人盯","textChars":22,"textLines":1,"bbox":[94,589,170,24]}
{"kind":"shape","id":"sh/xozyhkbi","slide":13,"bbox":[584,502,38,38]}
{"kind":"textbox","id":"sh/q18f65cr","slide":13,"text":"100 stores 100 家","textPreview":"100 stores 100 家","textChars":17,"textLines":1,"bbox":[574,555,150,28]}
{"kind":"textbox","id":"sh/bmhgfatc","slide":13,"text":"Managed by process 靠机制","textPreview":"Managed by process 靠机制","textChars":23,"textLines":1,"bbox":[574,589,170,24]}
{"kind":"shape","id":"sh/oz6x4vul","slide":13,"bbox":[1064,502,38,38]}
{"kind":"textbox","id":"sh/p0zyd0b6","slide":13,"text":"300 stores 300 家","textPreview":"300 stores 300 家","textChars":17,"textLines":1,"bbox":[1054,555,150,28]}
{"kind":"textbox","id":"sh/2xof2lcv","slide":13,"text":"Scaled through models 靠模型复制","textPreview":"Scaled through models 靠模型复制","textChars":28,"textLines":1,"bbox":[1054,589,170,24]}
{"kind":"notes","id":"nt/hgzapcr6","slide":13,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/6lsnupw7","slide":14,"title":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textShapes":8}
{"kind":"textbox","id":"sh/kre1k3y9","slide":14,"text":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textPreview":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textChars":61,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/xc7eds76","slide":14,"text":"A real data asset is a traceable operating capability.\n真正的数据资产,是可追溯的经营能力","textPreview":"A real data asset is a traceable operating capability. | 真正的数据资产,是可追溯的经营能力","textChars":72,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/wbydknq1","slide":14,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/jepwf2pc","slide":14,"text":"14","textPreview":"14","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/idgvmx8r","slide":14,"bbox":[42,180,560,365]}
{"kind":"shape","id":"sh/5grehs7i","slide":14,"bbox":[42,180,7,365]}
{"kind":"textbox","id":"sh/kfidonqx","slide":14,"text":"Enterprise data assets 企业数据资产","textPreview":"Enterprise data assets 企业数据资产","textChars":30,"textLines":1,"bbox":[66,202,514,40]}
{"kind":"textbox","id":"sh/zi5c3y98","slide":14,"text":"Common metric definitions and accountability · Business ontology · Industry rules · Decisions and validated outcomes · Best-practice knowledge\n· 统一指标口径与责任关系\n· 门店、商品、人员、会员、供应商本体\n· 行业规则与异常模式\n· 决策、执行与验证结果\n· 最佳实践与风险知识","textPreview":"Common metric definitions and accountability · Business ontology · Industry rules · Decisions and validated outcomes · Best-practice know...","textChars":213,"textLines":6,"bbox":[66,254,514,273]}
{"kind":"shape","id":"sh/ehwvat8n","slide":14,"bbox":[678,180,560,365]}
{"kind":"shape","id":"sh/c3e1gjyd","slide":14,"bbox":[678,180,7,365]}
{"kind":"textbox","id":"sh/x4ni9ofy","slide":14,"text":"Financing and due-diligence support 融资与尽调支持","textPreview":"Financing and due-diligence support 融资与尽调支持","textChars":44,"textLines":1,"bbox":[702,202,514,40]}
{"kind":"textbox","id":"sh/a1wze9g7","slide":14,"text":"Store-level P&L and cash flow · Revenue stability · Risk and remediation records · Forecasts · Traceable operating evidence\n· 门店级损益与现金流\n· 收入稳定性分析\n· 风险预警与整改记录\n· 未来经营预测\n· 更完整、可追溯的经营证明","textPreview":"Store-level P&L and cash flow · Revenue stability · Risk and remediation records · Forecasts · Traceable operating evidence | · 门店级损益与现金流...","textChars":181,"textLines":6,"bbox":[702,254,514,273]}
{"kind":"textbox","id":"sh/b2507exs","slide":14,"text":"Scope: data and analytical support only; no promise of bank credit or financing outcomes. 边界:提供数据与分析支持,不承诺银行授信或融资结果。","textPreview":"Scope: data and analytical support only; no promise of bank credit or financing outcomes. 边界:提供数据与分析支持,不承诺银行授信或融资结果。","textChars":117,"textLines":1,"bbox":[42,578,1000,34]}
{"kind":"notes","id":"nt/6lsnupw7","slide":14,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/vaxsvy10","slide":15,"title":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textShapes":15}
{"kind":"textbox","id":"sh/cbuh8nmh","slide":15,"text":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textPreview":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textChars":61,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/547mhg3m","slide":15,"text":"Production data must remain within clear security boundaries.\n生产数据必须留在清晰的安全边界内","textPreview":"Production data must remain within clear security boundaries. | 生产数据必须留在清晰的安全边界内","textChars":78,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/k3y5ov21","slide":15,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/76p4jqls","slide":15,"text":"15","textPreview":"15","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/65gnqlk7","slide":15,"bbox":[42,180,360,170]}
{"kind":"shape","id":"sh/t87ml0ji","slide":15,"bbox":[42,180,7,170]}
{"kind":"textbox","id":"sh/s7y5sv2x","slide":15,"text":"Deployment boundary 部署边界","textPreview":"Deployment boundary 部署边界","textChars":25,"textLines":1,"bbox":[66,202,314,40]}
{"kind":"textbox","id":"sh/na5476l8","slide":15,"text":"Does not replace transaction systems; read-only or controlled integration.\n不替代现有交易系统,只读或受控对接。","textPreview":"Does not replace transaction systems; read-only or controlled integration. | 不替代现有交易系统,只读或受控对接。","textChars":93,"textLines":2,"bbox":[66,254,314,78]}
{"kind":"shape","id":"sh/m9c3e1kn","slide":15,"bbox":[443,180,360,170]}
{"kind":"shape","id":"sh/wrm9kvep","slide":15,"bbox":[443,180,7,170]}
{"kind":"textbox","id":"sh/hsvat0fa","slide":15,"text":"Least privilege 最小权限","textPreview":"Least privilege 最小权限","textChars":21,"textLines":1,"bbox":[467,202,314,40]}
{"kind":"textbox","id":"sh/upkrilwj","slide":15,"text":"Access by role across owner, head office, region and store.\n老板、总部、区域、门店按职责查看。","textPreview":"Access by role across owner, head office, region and store. | 老板、总部、区域、门店按职责查看。","textChars":77,"textLines":2,"bbox":[467,254,314,78]}
{"kind":"shape","id":"sh/vqdsrqx4","slide":15,"bbox":[844,180,360,170]}
{"kind":"shape","id":"sh/4vm9ovel","slide":15,"bbox":[844,180,7,170]}
{"kind":"textbox","id":"sh/5wvax0f6","slide":15,"text":"Sensitive-data protection 敏感保护","textPreview":"Sensitive-data protection 敏感保护","textChars":31,"textLines":1,"bbox":[868,202,314,40]}
{"kind":"textbox","id":"sh/it4rm5wv","slide":15,"text":"Classify, mask and audit member, payroll and financial details.\n会员、薪酬、财务明细分级、脱敏与审计。","textPreview":"Classify, mask and audit member, payroll and financial details. | 会员、薪酬、财务明细分级、脱敏与审计。","textChars":83,"textLines":2,"bbox":[868,254,314,78]}
{"kind":"shape","id":"sh/judsvqxg","slide":15,"bbox":[42,390,360,170]}
{"kind":"shape","id":"sh/0z29cbyh","slide":15,"bbox":[42,390,7,170]}
{"kind":"textbox","id":"sh/l0bqlgf2","slide":15,"text":"Traceable AI AI 可追溯","textPreview":"Traceable AI AI 可追溯","textChars":20,"textLines":1,"bbox":[66,412,314,40]}
{"kind":"textbox","id":"sh/1kjyt83e","slide":15,"text":"Key conclusions show evidence, timing, logic and scope.\n重要结论显示依据、时间、路径和适用边界。","textPreview":"Key conclusions show evidence, timing, logic and scope. | 重要结论显示依据、时间、路径和适用边界。","textChars":76,"textLines":2,"bbox":[66,464,314,78]}
{"kind":"shape","id":"sh/gjax03m9","slide":15,"bbox":[443,390,360,170]}
{"kind":"shape","id":"sh/fi1grylo","slide":15,"bbox":[443,390,7,170]}
{"kind":"textbox","id":"sh/ehsfyt43","slide":15,"text":"Human approval 人工审批","textPreview":"Human approval 人工审批","textChars":20,"textLines":1,"bbox":[467,412,314,40]}
{"kind":"textbox","id":"sh/p8jyx83q","slide":15,"text":"High-impact decisions require approval by authorized management.\n高影响决策必须经有权限的管理者审批。","textPreview":"High-impact decisions require approval by authorized management. | 高影响决策必须经有权限的管理者审批。","textChars":83,"textLines":2,"bbox":[467,464,314,78]}
{"kind":"shape","id":"sh/o7ah4nm5","slide":15,"bbox":[844,390,360,170]}
{"kind":"shape","id":"sh/361gvilk","slide":15,"bbox":[844,390,7,170]}
{"kind":"textbox","id":"sh/25sf2d4z","slide":15,"text":"Full audit trail 全程留痕","textPreview":"Full audit trail 全程留痕","textChars":22,"textLines":1,"bbox":[868,412,314,40]}
{"kind":"textbox","id":"sh/dc3y1s3m","slide":15,"text":"Access, recommendations, edits, approvals and outcomes are auditable.\n访问、建议、修改、审批和执行结果均可审计。","textPreview":"Access, recommendations, edits, approvals and outcomes are auditable. | 访问、建议、修改、审批和执行结果均可审计。","textChars":91,"textLines":2,"bbox":[868,464,314,78]}
{"kind":"notes","id":"nt/vaxsvy10","slide":15,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/gny5sjyp","slide":16,"title":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textShapes":19}
{"kind":"textbox","id":"sh/ih0jedob","slide":16,"text":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textPreview":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textChars":61,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/8z2h8bq1","slide":16,"text":"Prove the value in eight weeks before scaling.\n先用 8 周证明价值,再决定扩大范围","textPreview":"Prove the value in eight weeks before scaling. | 先用 8 周证明价值,再决定扩大范围","textChars":65,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/9kby1g7m","slide":16,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/ytkf2h8j","slide":16,"text":"16","textPreview":"16","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"shape","id":"sh/zutgvm94","slide":16,"bbox":[66,340,1100,0]}
{"kind":"shape","id":"sh/kv2h4rqp","slide":16,"bbox":[54,322,38,38]}
{"kind":"textbox","id":"sh/lwbyxwra","slide":16,"text":"Week 1 第 1 周","textPreview":"Week 1 第 1 周","textChars":13,"textLines":1,"bbox":[49,206,200,28]}
{"kind":"textbox","id":"sh/ip4zel83","slide":16,"text":"Select a profit initiative\n选定利润专项","textPreview":"Select a profit initiative | 选定利润专项","textChars":33,"textLines":2,"bbox":[49,250,205,55]}
{"kind":"textbox","id":"sh/3qdg7qpo","slide":16,"text":"Baseline · Definition · Owner\n基线·口径·责任人","textPreview":"Baseline · Definition · Owner | 基线·口径·责任人","textChars":39,"textLines":2,"bbox":[49,394,205,84]}
{"kind":"shape","id":"sh/fm1gzq5o","slide":16,"bbox":[293,322,38,38]}
{"kind":"textbox","id":"sh/e1sf65o3","slide":16,"text":"Weeks 12 第 1—2 周","textPreview":"Weeks 12 第 1—2 周","textChars":18,"textLines":1,"bbox":[288,206,200,28]}
{"kind":"textbox","id":"sh/1ojy10ne","slide":16,"text":"Connect existing data\n连接现有数据","textPreview":"Connect existing data | 连接现有数据","textChars":28,"textLines":2,"bbox":[288,250,205,55]}
{"kind":"textbox","id":"sh/gnax8v6t","slide":16,"text":"Data inventory · Quality · Common definitions\n数据清单·质量·统一口径","textPreview":"Data inventory · Quality · Common definitions | 数据清单·质量·统一口径","textChars":58,"textLines":2,"bbox":[288,394,205,84]}
{"kind":"shape","id":"sh/nqlg3a5k","slide":16,"bbox":[532,322,38,38]}
{"kind":"textbox","id":"sh/2pcfa5oz","slide":16,"text":"Weeks 34 第 3—4 周","textPreview":"Weeks 34 第 3—4 周","textChars":18,"textLines":1,"bbox":[527,206,200,28]}
{"kind":"textbox","id":"sh/ps3y5knq","slide":16,"text":"Find opportunities and causes\n发现机会与根因","textPreview":"Find opportunities and causes | 发现机会与根因","textChars":37,"textLines":2,"bbox":[527,250,205,55]}
{"kind":"textbox","id":"sh/oruhcf65","slide":16,"text":"Exception · Financial impact · Evidence\n异常·影响金额·证据","textPreview":"Exception · Financial impact · Evidence | 异常·影响金额·证据","textChars":50,"textLines":2,"bbox":[527,394,205,84]}
{"kind":"shape","id":"sh/bulg7u5g","slide":16,"bbox":[771,322,38,38]}
{"kind":"textbox","id":"sh/atczepob","slide":16,"text":"Weeks 56 第 5—6 周","textPreview":"Weeks 56 第 5—6 周","textChars":18,"textLines":1,"bbox":[766,206,200,28]}
{"kind":"textbox","id":"sh/mpgj6t8j","slide":16,"text":"Drive corrective action\n推动整改","textPreview":"Drive corrective action | 推动整改","textChars":28,"textLines":2,"bbox":[766,250,205,55]}
{"kind":"textbox","id":"sh/7qp0zepo","slide":16,"text":"Task · Deadline · Execution record\n任务·期限·执行记录","textPreview":"Task · Deadline · Execution record | 任务·期限·执行记录","textChars":45,"textLines":2,"bbox":[766,394,205,84]}
{"kind":"shape","id":"sh/8by18jq9","slide":16,"bbox":[1010,322,38,38]}
{"kind":"textbox","id":"sh/9c7i1o7u","slide":16,"text":"Weeks 78 第 7—8 周","textPreview":"Weeks 78 第 7—8 周","textChars":18,"textLines":1,"bbox":[1005,206,200,28]}
{"kind":"textbox","id":"sh/ylwj2987","slide":16,"text":"Verify and replicate\n验证并复制","textPreview":"Verify and replicate | 验证并复制","textChars":26,"textLines":2,"bbox":[1005,250,205,55]}
{"kind":"textbox","id":"sh/zm50veps","slide":16,"text":"Improvement value · Acceptance · Best practice\n改善金额·验收·最佳实践","textPreview":"Improvement value · Acceptance · Best practice | 改善金额·验收·最佳实践","textChars":59,"textLines":2,"bbox":[1005,394,205,84]}
{"kind":"shape","id":"sh/kne14jqd","slide":16,"bbox":[42,550,1196,60]}
{"kind":"textbox","id":"sh/lo7ixo7y","slide":16,"text":"Prioritize cases with available data, measurable impact, executable actions and results verifiable in eight weeks. 优先选择:数据可获得 · 影响可测算 · 动作可执行 · 八周可验证。","textPreview":"Prioritize cases with available data, measurable impact, executable actions and results verifiable in eight weeks. 优先选择:数据可获得 · 影响可测算 · ...","textChars":151,"textLines":1,"bbox":[66,567,1148,30]}
{"kind":"notes","id":"nt/gny5sjyp","slide":16,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/14bup87q","slide":17,"title":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textShapes":19}
{"kind":"textbox","id":"sh/ytc7a1gv","slide":17,"text":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textPreview":"Xuanmou Intelligence · Multi-site Operations 玄谋智脑 · 连锁企业经营决策","textChars":61,"textLines":1,"bbox":[42,28,820,24]}
{"kind":"textbox","id":"sh/1c7e50ni","slide":17,"text":"Measure business improvement, not feature count.\n验收看经营改善,不看功能数量","textPreview":"Measure business improvement, not feature count. | 验收看经营改善,不看功能数量","textChars":63,"textLines":2,"bbox":[42,62,1160,70]}
{"kind":"shape","id":"sh/gbedwfmx","slide":17,"bbox":[42,139,1196,0]}
{"kind":"textbox","id":"sh/rm5czq50","slide":17,"text":"17","textPreview":"17","textChars":2,"textLines":1,"bbox":[1182,672,56,18]}
{"kind":"textbox","id":"sh/6lwvql4v","slide":17,"text":"01","textPreview":"01","textChars":2,"textLines":1,"bbox":[42,188,50,26]}
{"kind":"textbox","id":"sh/t8ne10n6","slide":17,"text":"Business outcomes\n经营结果","textPreview":"Business outcomes | 经营结果","textChars":22,"textLines":2,"bbox":[112,174,230,48]}
{"kind":"textbox","id":"sh/snedsvml","slide":17,"text":"Contribution profit · Cost · Waste · Inventory cash\n贡献利润·成本·损耗·库存资金","textPreview":"Contribution profit · Cost · Waste · Inventory cash | 贡献利润·成本·损耗·库存资金","textChars":67,"textLines":2,"bbox":[395,174,760,48]}
{"kind":"shape","id":"sh/jilcvq54","slide":17,"bbox":[112,239,1040,0]}
{"kind":"textbox","id":"sh/ihcvml4j","slide":17,"text":"02","textPreview":"02","textChars":2,"textLines":1,"bbox":[42,274,50,26]}
{"kind":"textbox","id":"sh/4by9or6l","slide":17,"text":"Issue detection\n问题发现","textPreview":"Issue detection | 问题发现","textChars":20,"textLines":2,"bbox":[112,260,230,48]}
{"kind":"textbox","id":"sh/pc7qhwn6","slide":17,"text":"Detection cycle · Valid-exception rate · Impact coverage\n发现周期·有效异常率·影响覆盖","textPreview":"Detection cycle · Valid-exception rate · Impact coverage | 发现周期·有效异常率·影响覆盖","textChars":72,"textLines":2,"bbox":[395,260,760,48]}
{"kind":"shape","id":"sh/29grm1of","slide":17,"bbox":[112,325,1040,0]}
{"kind":"textbox","id":"sh/3ap8fm50","slide":17,"text":"03","textPreview":"03","textChars":2,"textLines":1,"bbox":[42,360,50,26]}
{"kind":"textbox","id":"sh/gnepkr69","slide":17,"text":"Execution loop\n执行闭环","textPreview":"Execution loop | 执行闭环","textChars":19,"textLines":2,"bbox":[112,346,230,48]}
{"kind":"textbox","id":"sh/honqdwnu","slide":17,"text":"Acceptance · On-time completion · Remediation effectiveness\n接收率·按期完成率·整改有效率","textPreview":"Acceptance · On-time completion · Remediation effectiveness | 接收率·按期完成率·整改有效率","textChars":75,"textLines":2,"bbox":[395,346,760,48]}
{"kind":"shape","id":"sh/ulw7ihoj","slide":17,"bbox":[112,411,1040,0]}
{"kind":"textbox","id":"sh/fm58bm54","slide":17,"text":"04","textPreview":"04","textChars":2,"textLines":1,"bbox":[42,446,50,26]}
{"kind":"textbox","id":"sh/0ji9wb6t","slide":17,"text":"Organizational replication\n组织复制","textPreview":"Organizational replication | 组织复制","textChars":31,"textLines":2,"bbox":[112,432,230,48]}
{"kind":"textbox","id":"sh/14rqpgne","slide":17,"text":"Stores replicated · Success rate · New-store ramp time\n复制门店数·成功率·新店导入时间","textPreview":"Stores replicated · Success rate · New-store ramp time | 复制门店数·成功率·新店导入时间","textChars":71,"textLines":2,"bbox":[395,432,760,48]}
{"kind":"shape","id":"sh/90nq9gfi","slide":17,"bbox":[112,497,1040,0]}
{"kind":"textbox","id":"sh/8ze9gbyx","slide":17,"text":"05","textPreview":"05","textChars":2,"textLines":1,"bbox":[42,532,50,26]}
{"kind":"textbox","id":"sh/ny5876xc","slide":17,"text":"Data quality\n数据质量","textPreview":"Data quality | 数据质量","textChars":17,"textLines":2,"bbox":[112,518,230,48]}
{"kind":"textbox","id":"sh/mxw7e1gr","slide":17,"text":"Consistent · Complete · Timely · Traceable\n口径一致·完整·及时·可追溯","textPreview":"Consistent · Complete · Timely · Traceable | 口径一致·完整·及时·可追溯","textChars":57,"textLines":2,"bbox":[395,518,760,48]}
{"kind":"shape","id":"sh/lwnq5gf6","slide":17,"bbox":[112,583,1040,0]}
{"kind":"shape","id":"sh/0vepcbyl","slide":17,"bbox":[42,612,1196,42]}
{"kind":"textbox","id":"sh/zul836xg","slide":17,"text":"Agree the baseline, definitions and external factors at launch so normal variation is not mistaken for system impact. 项目启动时即确认基线、口径和外部影响因素,避免将自然波动误认为系统收益。","textPreview":"Agree the baseline, definitions and external factors at launch so normal variation is not mistaken for system impact. 项目启动时即确认基线、口径和外部影响...","textChars":155,"textLines":1,"bbox":[64,622,1152,24]}
{"kind":"notes","id":"nt/14bup87q","slide":17,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
{"kind":"slide","id":"sl/y5wne50z","slide":18,"title":"Xuanmou Intelligence 玄谋智脑","textShapes":4}
{"kind":"textbox","id":"sh/4felwzu5","slide":18,"text":"Xuanmou Intelligence 玄谋智脑","textPreview":"Xuanmou Intelligence 玄谋智脑","textChars":26,"textLines":1,"bbox":[42,35,240,30]}
{"kind":"textbox","id":"sh/wrelszu9","slide":18,"text":"Start with the first measurable profit opportunities.\n先用 8 周,找到第一批可验证的利润机会","textPreview":"Start with the first measurable profit opportunities. | 先用 8 周,找到第一批可验证的利润机会","textChars":74,"textLines":2,"bbox":[42,160,1040,210]}
{"kind":"textbox","id":"sh/hsn2l4bu","slide":18,"text":"Scale only after the value is proven.\n再决定如何扩大应用范围","textPreview":"Scale only after the value is proven. | 再决定如何扩大应用范围","textChars":49,"textLines":2,"bbox":[42,420,850,52]}
{"kind":"shape","id":"sh/itw3upcf","slide":18,"bbox":[42,610,1196,0]}
{"kind":"textbox","id":"sh/je5knut0","slide":18,"text":"Find issues earlier · Make corrective action stick · Replicate every proven improvement 让问题更早被发现 · 让整改真正落地 · 让每一次改善复制到更多门店","textPreview":"Find issues earlier · Make corrective action stick · Replicate every proven improvement 让问题更早被发现 · 让整改真正落地 · 让每一次改善复制到更多门店","textChars":123,"textLines":1,"bbox":[42,636,1100,30]}
{"kind":"notes","id":"nt/y5wne50z","slide":18,"text":"[Sources]\n用户提供文档:《玄谋智脑建设蓝图_老板决策版.md》。案例、指标与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\n中文内容来自用户提供的老板决策版;英文为商务意译。案例与金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。\n\n[Sources]\nAll visible Chinese content is based on the user-supplied owner decision deck. English is a concise business translation. Cases and figures remain anonymous composite examples or illustrative estimates.\n\n[Sources]\nEnglish-primary edition derived from the user-supplied bilingual owner decision deck. English is the primary decision language; Chinese is retained as a secondary reference. Cases and figures remain anonymous composite examples or illustrative estimates."}
@@ -0,0 +1,318 @@
# 玄谋智脑:让老板看清每一分利润,管住每一家门店
> **品牌名称**:玄谋智脑
> **核心定位**:面向连锁企业的行业数字本体与 AI 经营智脑。
> **一句话价值**:不再新建一套孤立系统,而是整合企业现有数据,找到利润漏洞、推动责任人整改、验证改善结果,并将优秀经验复制到每一家门店。
> **保密说明**:本文案中的企业、门店、指标和金额均为匿名复合案例或模拟测算,不代表任何单一客户的生产数据。
---
## 一、老板真正需要回答的三个问题
1. **我现在到底在哪里亏钱?**
2. **哪些动作能够真正提升利润?**
3. **企业从 30 家店扩张到 300 家店后,能否依然看得清、管得住?**
连锁企业通常不缺数据,缺的是将数据转化为经营判断和改善结果的能力。真正的问题不是“有没有报表”,而是:
- 营收增长,为什么利润没有同步增长?
- 哪些门店看起来赚钱,实际正在占用资金和管理资源?
- 哪些促销增加了订单,却消耗了贡献利润?
- 哪些 SKU 销量不低,却毛利不足、损耗过高?
- 哪些班次人员闲置,哪些高峰时段又人手不足?
- 哪些门店应该整改、缩编、迁址甚至关停?
---
## 二、玄谋智脑不是又一套 BI
BI 告诉管理者“发生了什么”;玄谋智脑还要继续回答:
- 为什么发生?
- 影响了多少利润?
- 应该由谁采取什么动作?
- 什么时候完成?
- 执行后是否真的改善?
- 这一次经验能否复制到其他门店?
### 经营改善闭环
```text
发现利润异常
穿透到区域、门店、SKU、班次或订单
测算影响金额与优先级
生成改善方案,明确责任人和期限
跟踪执行过程,验证利润是否改善
将有效做法沉淀为企业最佳实践
```
---
## 三、案例一:从 SKU 数量中找到隐藏成本
> **匿名复合案例·SKU 组合决策**
某区域连锁品牌约有 480 个在售 SKU。其中后 20% 的 SKU 仅贡献约 3% 销售额,却持续占用库存资金,并增加采购、盘点、报损和培训复杂度。
### 玄谋智脑发现
| 问题类型 | 模拟识别结果 | 经营影响 |
|:---|---:|:---|
| 低销量、低毛利、高损耗 SKU | 37 个 | 占用库存并产生报损 |
| 高销量但低贡献利润 SKU | 9 个 | 创造了营收假象 |
| 可共享或替换原料 SKU | 16 个 | 可降低采购与仓储复杂度 |
| 价格带重叠 SKU | 22 个 | 内部分流,增加顾客选择成本 |
### 建议动作
- 下架或区域性停售低效 SKU。
- 调整高销量低利润商品的定价、份量或配方。
- 将可替换 SKU 纳入共享原料体系。
- 保留必要的引流商品,但限制优惠叠加。
### 老板看到的结果
> 模拟测算:释放库存资金约 80 万元,年度减少报损约 35 万元,综合毛利率提升约 0.6 个百分点。
---
## 四、案例二:排班不是人数问题,而是供需匹配问题
> **匿名复合案例·门店 A-017**
某门店月营收排名区域前三,但人效排名倒数。按月度总人数看并不显眼,穿透到半小时粒度后才发现:
- 工作日上午存在大量闲置工时。
- 周五晚高峰又经常缺人。
- 班次主要依据历史习惯,没有匹配客流与订单预测。
- 加班集中在少数岗位,正式工与小时工结构不合理。
### 建议动作
1. 按半小时预测客流、订单量和工作量。
2. 调整早晚班起止时间,减少无效重叠。
3. 高峰增加小时工,低峰减少固定工时。
4. 将备餐任务提前到客流爬升前。
5. 同时监控出品时效和顾客满意度,避免单纯压缩人力。
### 老板看到的结果
> 模拟测算:在不降低服务质量的前提下,单店每月节约人工成本约 1.8 万元;复制到 60 家门店,年度改善空间约 1,296 万元。
---
## 五、案例三:订单增长了,促销却可能正在消耗利润
> **匿名复合案例·营销活动 X**
某促销活动带来约 23% 的订单增长,但穿透计算优惠、平台佣金、商品毛利、新增人工与原价订单替代后,活动贡献利润为负。
### 根因
- 低毛利商品在活动订单中占比大幅上升。
- 高价值会员也领取了无差别优惠。
- 一部分促销订单只是替代原价订单,并非真实增量。
- 原有评价只看订单数和营收,没有看增量贡献利润。
### 改善方案
- 将优惠定向投放给可能流失或需要唤醒的会员。
- 区分拉新券、复购券和唤醒券。
- 限制低毛利商品参与优惠叠加。
- 用“每投入 1 元营销费用增加多少贡献利润”作为核心评价指标。
> **经营结论**:促销不应只为订单增长负责,而应为增量利润负责。
---
## 六、案例四:将门店关停从经验判断变为情景决策
> **匿名复合案例·门店 D-006**
某门店仍有营业收入,因此管理层长期无法决定是否关停。玄谋智脑不只看单月损益,还综合分析:
- 门店贡献利润、现金流与资金占用。
- 租金续约、装修与设备折旧。
- 周边客群、竞争和商圈变化。
- 同品牌门店的订单蚕食与会员迁移可能性。
- 关停、整改、迁址和缩店的一次性成本。
### 十二个月情景测算
| 方案 | 模拟结果 | 决策建议 |
|:---|:---|:---|
| 继续经营 | 预计亏损 92 万元 | 不建议 |
| 投入整改 | 预计亏损降至 35 万元 | 风险较高,设置止损线 |
| 缩小面积 | 预计接近盈亏平衡 | 租约可重谈时考虑 |
| 关停并迁移会员 | 预计减少亏损 76 万元 | 优先建议 |
> 玄谋智脑不替老板做关店决定,而是让难以下决心的经验判断,变成有数据依据、情景测算和退出预案的经营决策。
---
## 七、老板、总部、区域、店长共用一个经营闭环
| 角色 | 需要回答的问题 | 玄谋智脑提供的能力 |
|:---|:---|:---|
| **老板** | 企业是否真正赚钱?风险在哪里?资源应该投向哪里? | 企业经营全景、利润树、风险排名、情景推演 |
| **总部** | 哪些区域和业务需要调整?政策是否有效? | 跨区域对标、异常归因、资源分配与政策评估 |
| **区域** | 哪些门店异常?应该帮助谁、整改谁? | 门店分级、异常排名、整改任务与验收 |
| **店长** | 今天哪里没达标?先做什么? | 日目标卡、偏差提醒、行动建议与进度反馈 |
```text
老板看到结果 → 总部找到原因 → 区域推动整改 → 店长执行动作 → 结果回到经营大盘
```
---
## 八、AI 不是器人顾问,而是经营分析与执行助手
### AI 可以承担
- 自动理解并关联跨系统经营数据。
- 持续扫描人难以长期监控的异常。
- 将问题穿透到区域、门店、SKU、班次和订单。
- 调用行业规则、企业制度和历史案例生成建议。
- 模拟不同方案对营收、利润和现金流的影响。
- 自动形成任务,跟踪执行并验证结果。
- 从成功与失败结果中更新最佳实践。
### 管理边界
> AI 负责发现、归因、测算、建议和跟踪;价格调整、人员处置、供应商更换、门店关停等重要决策,仍由有权限的管理者审批。
---
## 九、为什么玄谋智脑不是普通 BI
| 维度 | 普通 BI | 玄谋智脑 |
|:---|:---|:---|
| 核心定位 | 展示报表 | 驱动经营决策与改善 |
| 数据范围 | 单系统或主题报表 | 关联企业现有多系统数据 |
| 业务语义 | 字段和指标 | 门店、商品、人员、会员等行业本体及关系 |
| 问题发现 | 人主动看数据 | 系统持续发现并分级推送 |
| 问题处理 | 报告异常 | 归因、测算、生成方案和整改任务 |
| 结果验证 | 通常不跟踪 | 验证改善效果并更新经验 |
| 长期价值 | 报表越来越多 | 行业模型和企业知识越用越成熟 |
---
## 十、支撑规模扩张的五层能力
| 能力层 | 作用 | 老板获得的价值 |
|:---|:---|:---|
| **数据资产化** | 连接 POS、ERP、WMS、HR、财务和 Excel,统一口径 | 一个数字、一个来源,减少无效争论 |
| **运营指标化** | 建立战略、运营、执行三级指标和利润关系 | 问题自动浮现,并能穿透到根因 |
| **战略穿透化** | 将年度目标拆解到区域、门店、个人和每日动作 | 战略不再留在 PPT 里 |
| **态势感知化** | 监控异常、预测趋势、推演方案 | 从事后救火转向事前预防 |
| **知识沉淀化** | 将有效动作沉淀为 SOP、规则和案例 | 优秀能力不再依赖少数能人 |
---
## 十一、长期价值:企业越大,复制价值越高
### 1. 从依赖能人到依赖组织能力
优秀店长的动作被验证后,可沉淀为规则、案例和 SOP,降低换人带来的经营波动。
### 2. 扩张不再必然带来管理失控
单店验证有效的 SKU、排班、促销和损耗改善方案,可按门店特征分类复制,不必依靠老板逐店盯导。
### 3. 沉淀可复用的数据资产
玄谋智脑沉淀的不只是原始数据,还包括:
- 统一指标口径和责任关系。
- 门店、商品、人员、会员、供应商等业务本体。
- 行业规则、异常模式和改善方案。
- 决策过程、执行记录和验证结果。
- 企业最佳实践与风险知识。
### 4. 提升融资与尽调的数据可信度
玄谋智脑可为银行授信、融资尽调和经营证明提供更完整、可追溯的数据依据,包括门店级损益、现金流、收入稳定性、风险预警、整改记录与经营预测。
> **边界说明**:玄谋智脑提供数据与分析支持,不承诺银行授信或融资结果。
---
## 十二、数据安全与 AI 使用边界
1. **不改变生产系统主体责任**:现有 POS、ERP、WMS、财务和 HR 系统继续承担业务交易与原始记录职责。
2. **最小权限**:老板、总部、区域和门店按职责获得不同数据范围。
3. **敏感数据保护**:身份、联系方式、薪酬、会员和财务明细等采取分级、脱敏和审计。
4. **AI 输出可追溯**:重要结论应展示依据指标、数据时间、分析路径与适用边界。
5. **人工审批**:高影响决策必须由管理者审批,不允许 AI 直接执行不可逆动作。
6. **全程留痕**:数据访问、模型建议、人工修改、审批和执行结果均可审计。
---
## 十三、八周建设路径:先证明价值,再扩大范围
| 阶段 | 时间 | 建设重点 | 可验收成果 |
|:---|:---|:---|:---|
| **选定利润专项** | 第 1 周 | 选择 1—2 个高价值问题,明确基线与责任人 | 专项范围、基线数据、验收口径 |
| **连接现有数据** | 第 1—2 周 | 对接相关系统和 Excel,统一主体与指标口径 | 数据清单、质量报告、口径确认 |
| **发现机会与根因** | 第 3—4 周 | 建立分析模型,输出优先级机会清单 | 异常清单、影响金额、根因证据 |
| **推动整改** | 第 5—6 周 | 生成任务,由总部、区域和店长执行 | 责任人、时限、执行记录与进度 |
| **验证并复制** | 第 7—8 周 | 对比改善前后,审核因果关系,形成复制方案 | 改善金额、验收结论、最佳实践 |
### 建议首批专项
优先选择“数据可获得、影响可测算、动作可执行、八周可验证”的场景:
- SKU 组合与菜品毛利。
- 门店排班与人效。
- 促销活动的增量贡献利润。
- 库存、损耗与临期商品。
- 低效门店整改与止损。
---
## 十四、投入产出不看“上线了多少功能”
项目验收应围绕经营结果,而不是页面数量、报表数量或 AI 对话次数。
| 验收维度 | 建议指标 |
|:---|:---|
| 经营结果 | 增量贡献利润、成本减少、损耗下降、库存资金释放 |
| 问题发现 | 发现周期、有效异常率、影响金额覆盖率 |
| 执行闭环 | 任务接收率、按期完成率、整改有效率 |
| 组织复制 | 有效方案复制门店数、复制成功率、新店导入时间 |
| 数据质量 | 口径一致率、数据完整率、及时率、可追溯率 |
> 所有收益指标应在项目启动时确认基线、计算口径和外部影响因素,避免将市场、季节或门店自然波动误认为系统收益。
---
## 十五、从单点改善到企业经营复利
```text
更多经营场景
更完整的行业数字本体
更成熟的运营与预测模型
更准确、更符合企业情况的 AI 建议
更高质量的执行与决策反馈
└──────── 持续复利 ────────┘
```
玄谋智脑的长期价值,不是为企业生产更多数据,而是将现有数据、行业知识和管理经验沉淀为一套持续进化的决策能力。
---
## 给决策者的最后一句话
> # 先用 8 周找到第一批可验证的利润改善机会,再决定如何扩大应用范围。
真正值得投入的不是一套功能,而是一项可以让问题更早被发现、让整改真正落地、让每一次改善都能复制到更多门店的经营能力。
@@ -0,0 +1,551 @@
# 连锁企业数字化运营体系(完整版)
> **版本**V2.0(完整版)
> **适用对象**:连锁餐饮/零售品牌总部、区域管理团队、门店执行层
> **核心逻辑**:决策层定战略 → 管控层抓过程 → 执行层保结果,三层数据贯通、权限隔离、节奏闭环
> **新增模块**:产品设计与优化、供应链管理与中央厨房
---
## 目录
1. [三层级管理架构总览](#一三层级管理架构总览)
2. [决策层(老板 / 总部)](#二决策层老板--总部)
3. [产品设计与优化(总部产品中心)](#三产品设计与优化总部产品中心)
4. [供应链管理与中央厨房(总部供应链中心)](#四供应链管理与中央厨房总部供应链中心)
5. [管控层(区域 / 大区 / 督导)](#五管控层区域--大区--督导)
6. [执行层(门店 / 店长)](#六执行层门店--店长)
7. [门店关键岗位数据运转](#七门店关键岗位数据运转)
8. [总部职能支撑层数据运转](#八总部职能支撑层数据运转)
9. [三层级数据流转与会议体系](#九三层级数据流转与会议体系)
10. [数据权限与看板设计](#十数据权限与看板设计)
11. [附录:关键术语与工具](#十一附录关键术语与工具)
---
## 一、三层级管理架构总览
```
┌─────────────────┐
│ 决策层 │ 老板 / 总部(定战略、建体系、配资本)
│ (看方向) │
└────────┬────────┘
│ 目标分解 + 标准输出 + 资源配给
┌────────┴────────┐
│ 管控层 │ 区域 / 大区 / 督导(抓执行、调资源、做辅导)
│ (抓过程) │
└────────┬────────┘
│ 现场落地 + 数据反馈 + 人才输送
┌────────┴────────┐
│ 执行层 │ 店长 / 门店(管现场、带团队、保结果)
│ (保结果) │
└─────────────────┘
```
| 层级 | 核心定位 | 关键问题 | 时间分配 |
|:---|:---|:---|:---|
| **决策层** | 定方向、建体系、配资本 | "该不该做?值不值得做?有没有钱做?" | 70%在未来(战略、组织、资本),30%在当下(重大危机) |
| **管控层** | 抓过程、调资源、育人才 | "哪些店要救?哪些人要升?哪些钱该花?" | 50%在落后门店(现场),30%在数据分析,20%在人才 |
| **执行层** | 保现场、带团队、出利润 | "今天目标怎么达成?这桌客怎么留住?这个月怎么不亏?" | 80%在现场(人、货、场),20%在数据复盘 |
---
## 二、决策层(老板 / 总部)
### 2.1 定位与核心职责
- **定战略**:开店节奏、品类矩阵、品牌定位、资本路径
- **建体系**:标准化手册、数字化底座、供应链网络、人才梯队
- **配资本**:资金分配、资源倾斜、投融资决策、预算审批
- **看全局**:跨区域、跨品类、跨周期的趋势判断与风险预警
### 2.2 指标-目标-差距-行动-结果(ITGAR)
| 维度 | 指标 | 目标 | 差距诊断 | 行动 | 结果 |
|:---|:---|:---|:---|:---|:---|
| **规模** | 门店总数、净增门店数、关店率、加盟/直营占比 | 年度开店100家,关店率<5% | 哪些城市饱和?哪些区域空白?加盟还是直营效率低? | 资本配置、城市进入策略、加盟政策调整 | 市场份额、品牌覆盖密度、网络效应 |
| **财务** | 集团营收、综合毛利率、净利润率、现金流、单店投资回报周期 | 集团营收增长30%,利润率≥15%,投资回报<18个月 | 是成本失控还是增长乏力?哪个区域/品类拖累? | 供应链集采降本、提价策略、费用管控、融资节奏 | 股东回报、估值增长、现金流安全 |
| **品牌** | 品牌搜索指数、NPS、舆情健康度、客单价品牌定位 | 成为区域品类第一,NPS≥60 | 品牌老化?还是定位模糊? | 品牌升级、IP联名、视觉体系迭代、公关策略 | 品牌溢价能力、自然客流占比 |
| **供应链** | 集采成本率、中央厨房产能利用率、物流成本占比、食安事故 | 集采成本年降5%,食安事故0发生 | 供应商分散?冷链覆盖不足?产能瓶颈? | 建设中央厨房、引入战略供应商、数字化溯源 | 成本优势、出品稳定性、扩张支撑力 |
| **人才** | 店长储备率、区域经理梯队厚度、员工流失率、培训覆盖率 | 每店储备1.5名店长,流失率<20% | 是培养慢还是留不住? | 建店长学院、股权激励、晋升通道设计 | 组织可复制性、关键岗位到岗率 |
| **数字化** | 系统覆盖率、数据准确率、BI使用渗透率 | 100%门店上线POS+ERP,数据T+1出报表 | 门店抗拒?系统割裂?数据孤岛? | 统一数字化底座、强制数据上报、数据中台建设 | 决策效率、管理半径扩大、单店模型可量化 |
### 2.3 日/周/月/季/年运转节奏
| 周期 | 核心动作 | 数据输入 | 决策输出 |
|:---|:---|:---|:---|
| **日** | 看全局预警 | 营收异常门店(低于目标20%)、重大客诉/食安、舆情爆发 | 电话过问区域负责人;启动危机小组;重大事件直达 |
| **周** | 看区域排名 | 各区域营收达成、同店增长、成本偏差、门店巡检得分排名 | 周会通报;落后区域负责人述职;调配资源;政策微调 |
| **月** | 看经营结果 | 集团损益表、各区域利润贡献、新开店爬坡数据、品类矩阵 | 月度经营分析会;区域资源再分配;关店/开店决策;预算调整 |
| **季** | 看战略进度 | 季度同店增长、投资回报、人才梯队、供应链产能、竞品动态 | 季度战略复盘;调整年度目标;组织变革;资本动作 |
| **年** | 定明年战略 | 全年ROI、行业趋势、资本环境、组织能力、品牌资产 | 年度预算、开店计划、组织升级、薪酬体系调整、融资计划 |
### 2.4 总部关键管理点位
| 管理点位 | 管控内容 | 关键指标 |
|:---|:---|:---|
| **战略与投资** | 城市进入、开店模型、资本配置、并购合作 | 单店模型ROI、投资回收期、城市渗透率 |
| **品牌与营销** | 品牌定位、VI体系、年度营销、会员体系 | 品牌搜索指数、NPS、营销费用占比、会员贡献率 |
| **供应链与中央厨房** | 集采、供应商管理、中央厨房产能、冷链物流 | 集采成本率、产能利用率、物流成本、食安事故 |
| **人才与组织** | 店长学院、薪酬体系、股权激励、企业文化 | 储备率、晋升通过率、流失率、组织健康度 |
| **数字化与财务** | POS/ERP、数据中台、集团财务、预算管控 | 系统覆盖率、数据准确率、净利润率、现金流 |
| **产品与研发** | 菜单规划、新品研发、配方标准、定价策略 | 新品成功率、毛利率、SKU动销率、口味稳定性 |
---
## 三、产品设计与优化(总部产品中心)
### 3.1 定位与核心职责
产品是连锁餐饮的核心竞争力。产品中心负责**菜单全生命周期管理**:从市场调研、产品研发、配方标准化、定价策略、上市推广、销售监控到迭代淘汰,确保每一款SKU都是"能赚钱、好复制、有口碑"的精品。
### 3.2 指标-目标-差距-行动-结果(ITGAR)
| 维度 | 指标 | 目标 | 差距诊断 | 行动 | 结果 |
|:---|:---|:---|:---|:---|:---|
| **菜单结构** | SKU总数、品类宽度(主食/小食/饮品)、价格带分布、套餐占比 | SKU控制在30-50个,套餐占比≥40%,价格带覆盖主流客群 | 动销率低的SKU过多?价格带断层? | 精简滞销品、补充价格带、优化套餐组合 | 菜单清晰、点单效率高、毛利结构健康 |
| **新品研发** | 年度新品数、新品成功率(3个月存活)、研发周期、研发成本 | 每季度上新2-3款,新品成功率≥60%,研发周期≤45天 | 研发慢?口味不稳定?成本高? | 建立快速研发小组、引入消费者共创、中央厨房预研 | 持续新鲜感、顾客回流、媒体话题 |
| **配方标准化** | 配方SOP完整率、出品一致性(盲测得分)、成本偏差率 | 100%SKU有标准配方,盲测一致性≥90%,成本偏差≤3% | 配方模糊?厨师执行走样?原料替代导致口味变? | 配方数字化(克重/温度/时间精确到个位)、厨师培训认证、原料锁规格 | 千店一味、出品稳定、成本可控 |
| **定价策略** | 综合毛利率、各品类毛利率、套餐毛利率、促销折扣率 | 综合毛利率≥60%,引流品毛利率≥50%,利润品毛利率≥70% | 定价过低?促销过度?组合不合理? | 价格敏感度测试、竞品定价对标、动态调价机制 | 利润最大化、价格竞争力、品牌定位清晰 |
| **产品生命周期** | 新品爬坡期、成熟期时长、衰退期识别、淘汰率 | 新品1个月爬坡,3个月判定去留,年度淘汰率20% | 新品起不来?老品占资源? | 上市前3个月资源倾斜(推荐位/促销)、衰退期逐步下架、末位淘汰 | 菜单活力、库存周转、利润聚焦 |
| **顾客反馈** | 菜品好评率、差评归因(口味/分量/温度/异物)、复购关联度 | 菜品好评率≥90%,差评24小时归因 | 哪道菜差评多?是口味问题还是出品问题? | 配方微调、出品流程优化、原料替换测试 | 口碑提升、复购增长 |
### 3.3 日/周/月/季/年运转节奏
| 周期 | 核心动作 | 数据输入 | 决策输出 |
|:---|:---|:---|:---|
| **日** | 监控菜品销售异常 | 各菜品实时销量、断货预警、客诉(菜品相关) | 当日协调供应链补货或临时下架;通知门店调整推荐话术 |
| **周** | 菜品销售排行分析 | TOP20畅销品、BOTTOM10滞销品、毛利率排行、出品时效 | 下周调整推荐位、套餐组合;启动滞销品淘汰评估 |
| **月** | 菜单健康度诊断 | 品类销售矩阵(明星/瘦狗/现金牛/问题)、SKU动销率、成本偏差 | 下月菜单微调计划、新品上市/老品下架决策、配方优化清单 |
| **季** | 季度菜单大迭代 | 季度销售数据、竞品新品、消费者调研、供应链成本变化 | 下季度菜单规划、新品研发立项、价格带调整、营销配合方案 |
| **年** | 年度产品战略 | 全年品类贡献、行业趋势、原料行情、品牌定位校准 | 年度SKU规划、核心爆品打造计划、供应链绑定策略、定价体系升级 |
### 3.4 产品全生命周期管理流程
```
【市场调研】→【概念设计】→【配方研发】→【中央厨房试制】→【盲测验证】→【成本测算】→【定价决策】
【小范围试销】→【数据收集】→【配方微调】→【SOP固化】→【全员培训】→【全国上市】→【资源倾斜】
【销售监控】→【顾客反馈】→【成本复盘】→【成熟期维护】→【衰退期预警】→【淘汰下架】→【经验沉淀】
```
### 3.5 产品中心关键管理点位
| 管理点位 | 管控内容 | 关键指标 |
|:---|:---|:---|
| **市场调研** | 消费者口味趋势、竞品菜单、价格敏感度、区域差异 | 调研样本量、洞察转化率、新品命中率 |
| **配方研发** | 口味调试、营养搭配、成本测算、出品可行性 | 研发周期、盲测得分、成本达标率 |
| **中央厨房试制** | 批量生产工艺验证、保质期测试、冷链稳定性 | 试制成功率、出品一致性、损耗率 |
| **SOP固化** | 配方数字化(克重/温度/时间/步骤)、视频拍摄、培训课件 | SOP完整率、培训通过率、出品偏差率 |
| **上市管理** | 上市排期、门店培训、推荐位安排、促销配合 | 上市准时率、培训覆盖率、首月销量 |
| **销售监控** | 实时销量、毛利率、客诉、复购关联 | 动销率、好评率、成本偏差、生命周期阶段 |
| **迭代淘汰** | 末位SKU识别、替代方案、库存清理、员工沟通 | 淘汰率、库存损失、替代品承接率 |
---
## 四、供应链管理与中央厨房(总部供应链中心)
### 4.1 定位与核心职责
供应链是连锁餐饮的"生命线+成本中心"。供应链中心负责从**原料采购→中央厨房加工→仓储物流→门店配送→门店验收**的全链路管理,确保"品质稳定、成本最优、交付准时、食安零事故"。
### 4.2 供应链全链路架构
```
【原料采购】 【中央厨房/加工中心】 【仓储物流】 【门店】
│ │ │ │
▼ ▼ ▼ ▼
供应商管理 → 集中采购/比价 → 半成品预制/酱料调配 → 冷链仓储/分拣 → 冷链配送 → 门店验收 → 入库使用
│ │ │ │
▼ ▼ ▼ ▼
资质审核 配方工艺标准化 库存管理/温控 到货称重
价格谈判 产能规划/排产 配送路线优化 品质检查
绩效评估 食安监控/留样 在途温度追踪 溯源记录
备选开发 成本核算/损耗 周转效率 即时反馈
```
### 4.3 指标-目标-差距-行动-结果(ITGAR)
| 维度 | 指标 | 目标 | 差距诊断 | 行动 | 结果 |
|:---|:---|:---|:---|:---|:---|
| **采购成本** | 集采成本率、同比降幅、账期优化、供应商集中度 | 集采成本年降5%,账期≥60天,TOP3供应商占比≥60% | 哪些品类涨价?哪些供应商性价比低? | 战略供应商谈判、季节性锁价、替代原料开发、招标比价 | 成本优势、利润空间 |
| **供应商管理** | 供应商合格率、交货准时率、质量事故率、备选覆盖率 | 合格率≥98%,准时率≥95%,质量事故0,每品类有备选 | 供应商产能不足?质量波动?独家依赖? | 供应商分级(战略/优选/合格/淘汰)、备选开发、驻厂监督 | 供应稳定、风险分散、议价能力 |
| **中央厨房效率** | 产能利用率、出品一致性、加工成本、设备故障率 | 产能利用率≥80%,出品一致性≥95%,加工成本≤营收8% | 产能闲置?还是瓶颈?工艺不稳定? | 产能规划(淡旺季弹性)、设备预防性维护、工艺标准化、人员技能认证 | 支撑门店扩张、出品稳定、成本可控 |
| **仓储物流** | 库存周转天数、冷链断链率、配送准时率、物流成本占比 | 库存周转≤7天,断链率0,准时率≥98%,物流成本≤3% | 库存积压?冷链故障?路线低效? | 智能订货模型、温控IoT监控、路线优化算法、区域仓布局 | 新鲜度保障、损耗降低、配送效率 |
| **门店验收** | 到货准时率、验收合格率、退货率、缺货率 | 准时率≥98%,合格率≥95%,退货率≤2%,缺货率≤1% | 到货晚?品质差?数量不对? | 供应商考核挂钩、到货预约系统、验收SOP培训、异常快速理赔 | 门店运营不受阻、食材新鲜、损耗可控 |
| **食安溯源** | 溯源覆盖率、检测报告完整率、临期处理率、食安事故 | 溯源100%,检测100%覆盖,临期处理100%,事故0 | 哪批货有问题?哪个环节断链? | 区块链溯源、批次管理、检测报告云存档、临期预警自动推送 | 合规经营、品牌安全、消费者信任 |
### 4.4 中央厨房专项管理
#### 4.4.1 中央厨房定位
中央厨房是连锁餐饮"标准化复制"的核心基础设施,负责将原料加工成**半成品、预制菜、酱料、净菜**,统一配送至门店,实现"门店简单操作、出品千店一味"。
#### 4.4.2 中央厨房指标-目标-差距-行动-结果
| 维度 | 指标 | 目标 | 差距诊断 | 行动 | 结果 |
|:---|:---|:---|:---|:---|:---|
| **产能规划** | 设计产能、实际产能、产能利用率、淡旺季弹性 | 利用率≥80%,旺季可加班/外包提升至100% | 产能闲置浪费?还是瓶颈制约开店? | 分品类产能核算、淡旺季排产计划、预留扩产空间、外包备选 | 支撑门店扩张、成本最优 |
| **生产计划** | 日/周/月排产计划、计划达成率、换线次数 | 计划达成率≥95%,换线时间≤30分钟 | 计划不准导致积压或缺货?换线频繁影响效率? | MRP系统对接门店销售预测、经济批量生产、换线标准化 | 库存合理、交付准时、效率最高 |
| **工艺标准** | 每款半成品的配方SOP、加工温度/时间、出品规格 | 100%产品有SOP,工艺偏差≤2% | 工艺模糊?员工操作不一? | 工艺数字化(PLC控制)、视频监控、关键参数自动记录 | 出品一致性、门店操作简化 |
| **成本控制** | 原料出成率、人工成本、能耗成本、包装成本、综合加工成本 | 出成率≥行业均值,加工成本≤营收8% | 哪道工序浪费大?能耗高? | 精益生产改善、节能设备、包装优化、边角料再利用 | 加工成本最优、竞争力强 |
| **食安管控** | 车间洁净度、温度监控、留样管理、人员健康、检测报告 | 车间菌落达标、温度全程监控、留样48小时、健康证100% | 哪个环节风险高? | HACCP体系、IoT温度监控、每日班前消毒、第三方检测 | 食安零事故、品牌保全 |
| **配送协同** | 成品库存、配送频次、在途时间、到货温度 | 成品库存≤1天,配送频次≥每日1次,在途≤4小时,到货温度0-4℃ | 库存积压?配送不及时?温度失控? | 按门店销量预测生产、冷链车GPS+温控、到货预约系统 | 门店不断货、食材新鲜 |
#### 4.4.3 中央厨房日/周/月运转节奏
| 周期 | 核心动作 | 数据输入 | 决策输出 |
|:---|:---|:---|:---|
| **日** | 生产排程执行、设备点检、温度监控、出品抽检 | 门店订单汇总、原料库存、设备状态、人员出勤 | 当日生产计划调整、设备维修申请、异常批次隔离 |
| **周** | 产能复盘、成本分析、工艺偏差归因、设备维护 | 周产能利用率、周成本明细、周出品抽检结果、周设备故障 | 下周排产优化、成本改善项、设备保养计划、工艺微调 |
| **月** | 月度经营分析、供应商结算、产能规划校准、食安审计 | 月加工成本、月出品一致性、月损耗、月检测报告、门店满意度 | 下月产能计划、供应商评估、成本优化方案、设备投资申请 |
### 4.5 供应链中心关键管理点位
| 管理点位 | 管控内容 | 关键指标 |
|:---|:---|:---|
| **供应商管理** | 资质审核、比价议价、绩效考核、备选开发、战略合作 | 供应商合格率、交货准时率、质量事故率、账期 |
| **集中采购** | 订货量预测、价格锁定、质量验收、溯源管理、季节性备货 | 采购成本率、验收合格率、缺货率、库存周转 |
| **中央厨房** | 半成品预制、酱料调配、净菜加工、产能规划、工艺标准化 | 产能利用率、出品一致性、加工成本、食安合规 |
| **仓储管理** | 库存管理、冷链温控、分拣效率、临期预警、盘点差异 | 库存周转天数、临期损耗率、分拣准确率、盘点差异率 |
| **物流配送** | 配送路线、车辆调度、在途温控、到货时效、配送成本 | 配送准时率、冷链断链率、物流成本占比、车辆满载率 |
| **门店验收** | 到货称重、品质检查、温度记录、入库上架、异常反馈 | 验收合格率、退货率、缺货率、到货准时率、溯源完整率 |
| **食安溯源** | 进货台账、批次管理、检测报告、留样管理、召回机制 | 溯源覆盖率、检测完整率、食安事故、召回响应时效 |
---
## 五、管控层(区域 / 大区 / 督导)
### 5.1 定位与核心职责
- **抓过程**:确保总部标准在辖区落地,监控门店日常经营偏差
- **调资源**:手握区域营销预算、人员调动权、临时采购权,快速救店
- **做辅导**:落后门店驻店辅导,优秀经验区域复制,人才识别与输送
- **报结果**:向总部承担区域利润与增长责任,反馈一线真实问题
### 5.2 指标-目标-差距-行动-结果(ITGAR)
| 维度 | 指标 | 目标 | 差距诊断 | 行动 | 结果 |
|:---|:---|:---|:---|:---|:---|
| **区域业绩** | 区域营收达成率、区域利润、同店增长、新店爬坡周期 | 区域营收达成100%,利润达成105%,新店3个月盈亏平衡 | 哪些店拖后腿?是客流问题还是成本问题? | 落后门店驻店辅导、资源倾斜(营销/人力)、优秀店长调岗支援 | 区域排名、门店健康度、利润贡献 |
| **标准落地** | 巡检得分、SOP执行率、食安得分、品牌VI合规 | 巡检平均分≥92,食安0红线 | 是培训不足还是执行走样? | 周会案例教学、神秘顾客、强制回炉培训、店长问责 | 品牌一致性、客诉下降、总部信任 |
| **人才输送** | 店长输出数、晋升通过率、储备干部数、区域流失率 | 每季度输出2名合格店长,流失率<15% | 是培养慢还是待遇低? | 区域集训、老店长带教、调薪申请、淘汰机制 | 人才梯队厚度、总部人才池充盈 |
| **资源效率** | 区域营销ROI、人力成本占比、能耗、库存周转 | 营销ROI≥1:5,人力成本≤22% | 钱花在哪了?哪类活动有效? | 停掉低效活动、集中预算打爆品、共享优秀门店排班表 | 资源投入产出最大化 |
| **顾客体验** | 区域好评率、差评闭环率、会员复购率、投诉升级率 | 好评率≥95%,差评24小时闭环 | 是服务问题还是出品问题?集中爆发还是分散? | 区域服务大赛、后厨专项整治、会员召回统一动作 | 区域口碑、自然客流增长 |
| **供应链协同** | 区域到货准时率、验收合格率、缺货率、临期金额 | 准时率≥98%,合格率≥95%,缺货率≤1% | 哪些门店经常缺货?哪些供应商区域表现差? | 协调供应链加急配送、门店间调拨、供应商区域替换申请 | 门店运营顺畅、损耗降低 |
### 5.3 日/周/月运转节奏
| 周期 | 核心动作 | 数据输入 | 管理输出 |
|:---|:---|:---|:---|
| **日** | 远程巡店 + 预警干预 | 看板:各店实时营收、红黄灯门店、差评/客诉/损耗/缺货异常 | 黄灯门店→电话店长问原因;红灯门店→次日到店;重大事件直报总部 |
| **周** | 到店辅导 + 区域周会 | 门店巡检数据、周营收排名、周损耗排名、周客诉分类、到货异常 | 周一:落后门店驻店半天;周三:进度纠偏;周日:区域周会,TOP3分享,BOTTOM3述职 |
| **月** | 区域经营复盘 + 资源申请 | 区域损益表、门店分级(A/B/C/D)、人才盘点、营销ROI、供应链协同评分 | 月度报告提交总部;申请调薪/关店/营销资源/供应链调整;调整下月区域策略;门店分级调整 |
### 5.4 门店分级管理机制
| 等级 | 标准 | 管理策略 | 资源倾斜 |
|:---|:---|:---|:---|
| **A级(标杆)** | 营收达成≥110%,巡检≥95分,人才输出店 | 奖励、树立标杆、允许参与总部试点 | 营销预算加成、晋升名额优先、总部表彰 |
| **B级(正常)** | 营收达成90%-110%,巡检≥85分 | 维持、定期巡检、经验萃取 | 标准资源配给 |
| **C级(预警)** | 营收达成70%-90%,或巡检<85分,或客诉高发 | 重点辅导、驻店帮扶、限期整改 | 区域经理驻店、优秀店长支援、专项培训 |
| **D级(淘汰)** | 营收达成<70%,连续亏损,或食安红线 | 关店评估、换店长、最后通牒 | 停止资源投入,进入关店流程或翻牌重启 |
### 5.5 区域督导关键管理点位
| 管理点位 | 管控内容 | 关键指标 |
|:---|:---|:---|
| **远程巡店** | 实时数据监控、视频巡检、异常预警响应 | 在线巡店覆盖率、预警响应时效、干预成功率 |
| **到店辅导** | 落后门店诊断、现场带教、整改验收 | 驻店辅导次数、整改达标率、门店升级数 |
| **区域周会** | 数据通报、案例分享、政策宣导、资源协调 | 周会出勤率、案例沉淀数、政策落地率 |
| **人才识别** | 店长评估、储备干部考察、晋升推荐 | 人才输出数、晋升通过率、储备池健康度 |
| **资源调配** | 营销预算分配、人员跨店调动、应急采购审批 | 预算执行率、跨店支援次数、应急响应时效 |
| **供应链协调** | 区域缺货处理、到货异常协调、门店间调拨 | 缺货响应时效、调拨成功率、到货满意度 |
---
## 六、执行层(门店 / 店长)
### 6.1 定位与核心职责
- **保现场**:人、货、场的高效运转,高峰不崩盘、低谷不空转
- **带团队**:招聘、培训、激励、留存,打造稳定有战斗力的班组
- **控成本**:食材、人力、能耗、损耗的每日精细化管理
- **出结果**:对营收、利润、顾客体验、食安负最终责任
### 6.2 指标-目标-差距-行动-结果(ITGAR)
| 维度 | 指标 | 目标 | 差距诊断 | 行动 | 结果 |
|:---|:---|:---|:---|:---|:---|
| **营收** | 日/月营收达成、客单价、来客数、外卖占比、会员消费占比 | 月营收达成100%,客单价提升5% | 与上月比?与区域均值比?与去年同期比? | 调整排班、推套餐、发券、优化外卖、会员召回 | 营收达成、利润贡献 |
| **成本** | 食材成本率、人力成本率、能耗、损耗率、盘点差异 | 食材成本≤35%,损耗≤2% | 哪项超支?是订货多?还是浪费大? | 精准订货、剩料员工餐、节能巡查、责任到人 | 毛利率、净利润 |
| **体验** | 出餐时效、好评率、差评率、投诉数、神秘顾客得分 | 出餐≤15分钟,好评≥95%,投诉0升级 | 差评集中在哪?服务?出品?环境? | 班前会强调、高峰盯场、客诉即时处理、24小时回访 | 顾客复购、口碑传播 |
| **团队** | 员工出勤、技能达标、离职率、个人绩效、多岗覆盖率 | 离职率<15%,100%技能达标 | 谁状态差?谁要离职?谁可以晋升? | 一对一沟通、现场带教、绩效面谈、排班优化 | 团队稳定、服务热情 |
| **食安** | 自检得分、温度记录、消毒记录、临期品、证照有效期 | 自检100分,食安0事故 | 哪项扣分?哪批货临期? | 每日巡检、责任区划分、即时整改、报废处理 | 合规经营、品牌保全 |
| **供应链执行** | 到货验收合格率、订货准确率、缺货次数、库存周转 | 验收合格率≥95%,缺货≤1次/周,库存周转≤7天 | 订货不准?验收不严?库存积压? | 按销售预测订货、每日验收称重、先进先出、临期预警 | 不断货、不积压、损耗低 |
### 6.3 日/周/月运转节奏
#### 日运转:盯实时、控过程、保结果
| 时段 | 核心动作 | 数据输入 | 输出决策 |
|:---|:---|:---|:---|
| **晨会(9:00-9:15** | 昨日回顾 + 今日目标 + 重点部署 + 风险预警 | 昨日日报、今日预订、天气、库存、员工状态、到货情况 | 当日《目标卡》贴于后厨+前厅;确认到货异常处理 |
| **高峰盯场(实时)** | 等位数、出餐时效、客诉、翻台率、缺货预警 | 每30分钟看实时数据 | 等位>10桌→启动高峰预案;出餐>15分钟→后厨加人;缺货→启动备选方案 |
| **晚复盘(闭店后)** | 营收达成、客单、损耗、差评、人员效能、到货验收 | 当日完整营业数据、到货验收记录 | 《日复盘日志》:次日调整重点、问题责任人、改进动作、次日订货建议 |
#### 周运转:找规律、调资源、补短板
| 时间 | 核心动作 | 数据输入 | 输出决策 |
|:---|:---|:---|:---|
| **周一** | 周计划会 | 上周数据、品类排行、员工绩效、损耗分析、区域均值、到货异常 | 《周行动计划》:本周3件大事(如推新套餐、降损耗、练服务) |
| **周三** | 周中检查 | 本周营收进度(应完成43%)、成本进度、差评累计、缺货次数 | 纠偏:落后→加大促销;超标→立即排查;缺货→调整订货模型 |
| **周日** | 周复盘 | 全周数据汇总、目标达成、异常事件、竞品动态、到货满意度 | 下周排班优化、培训主题、菜单微调、申请支援、订货策略调整 |
#### 月运转:算大账、定策略、促增长
| 时间 | 核心动作 | 数据输入 | 输出决策 |
|:---|:---|:---|:---|
| **月初** | 目标分解与资源规划 | 上月经营数据、总部下达目标、历史同期、节假日、供应链成本变化 | 月营收日分解、预算编制、菜单规划、营销日历、人员大排班、订货策略 |
| **月中(15号)** | 进度追踪与动态调整 | 营收进度(应≥45%)、成本进度、会员增长、食安巡检、到货质量 | 不足→启动月中促销;超额→追加利润目标;巡检低分→立即整改;到货差→反馈供应链 |
| **月末** | 全面经营复盘 | 全月损益、区域排名、坪效人效、会员价值、营销ROI、供应链评分 | 《月度经营分析报告》:结果、差距、根因、下月计划、资源申请、供应链反馈 |
### 6.4 店长关键管理点位
| 管理点位 | 管控内容 | 关键指标 |
|:---|:---|:---|
| **营收管理** | 日结核对、优惠核销、外卖对账、异常排查 | 营收差异率、优惠合规率、坏账率 |
| **人员排班** | 按客流曲线配置人力,兼岗灵活调度 | 工时利用率、人力成本占比、顾客等位时长 |
| **现场管理** | 清洁卫生、温度灯光、设备维护、餐具桌椅 | 巡检得分、设备故障率、顾客环境评价 |
| **出品管理** | 配方执行、烹饪标准、出餐时效、食品安全 | 出餐时间、出品合格率、食安事故0发生 |
| **顾客体验** | 服务流程、客诉处理、好评引导、会员转化 | 服务时效、顾客投诉率、好评率、会员新增数 |
| **库存损耗** | 每日验收、库存盘点、临期预警、剩料处理 | 验收差异率、损耗率、临期金额、库存周转 |
| **供应链执行** | 到货验收、订货管理、缺货应对、退货反馈 | 验收合格率、缺货率、退货率、订货准确率 |
---
## 七、门店关键岗位数据运转
### 7.1 前厅主管(服务经理)
| 周期 | 核心指标 | 数据动作 | 输出决策 |
|:---|:---|:---|:---|
| **日** | 顾客等位时长、客诉数、差评数、会员新增数、翻台率 | 晨会宣导当日服务重点;高峰巡场记录服务问题;闭店前汇总当日客诉 | 次日重点盯人/盯桌/盯流程 |
| **周** | 服务SOP执行率、差评分类占比、顾客满意度、员工服务评分 | 周中神秘顾客或自检;周末分析差评根因(服务/出品/环境);优秀/差评案例各选3个 | 下周培训主题(如:迎宾话术、客诉处理) |
| **月** | 翻台率、客单价贡献、会员转化率、顾客NPS、前厅人效 | 对比区域TOP门店翻台数据;分析会员消费频次;评估服务员推荐力 | 下月服务流程微调(如:增加巡台次数、优化点单路径) |
**关键闭环**:差评→24小时内归因→3日内培训→下周抽检→月度纳入绩效考核
### 7.2 后厨主管(厨师长)
| 周期 | 核心指标 | 数据动作 | 输出决策 |
|:---|:---|:---|:---|
| **日** | 出餐时效(分菜品)、出品退货率、食材损耗、剩料重量、温度记录 | 晨会分配当日备料量;高峰盯出餐口时效;闭店登记损耗(报废/剩料/员工餐) | 次日调整备料量、锁定问题菜品 |
| **周** | 配方执行偏差率、库存周转、设备故障时长、毛利率(分菜品) | 周中抽查3款菜品称重/测温;周末盘点库存;分析TOP10/BOTTOM5菜品毛利 | 下周调整订货量、淘汰滞销品、申请设备维修 |
| **月** | 综合食材成本率、食安巡检得分、厨师人效、新品成功率 | 月度菜品销售毛利矩阵(明星/瘦狗/现金牛/问题);分析损耗根因 | 下月菜单结构调整、供应商质量反馈、厨师排级定薪 |
**关键闭环**:剩料称重→损耗归因→订货模型修正→周盘点验证→月度成本分析
### 7.3 收银员
| 周期 | 核心指标 | 数据动作 | 输出决策 |
|:---|:---|:---|:---|
| **日** | 收银差异额、优惠核销笔数、会员注册数、客单价、支付结构 | 每笔结账核对系统;闭店对账(现金/扫码/外卖);记录会员注册数 | 差异当日查清(漏扫/多扫/假币);次日补注册目标 |
| **周** | 收银准确率、个人客单贡献、会员转化率、漏单/逃单次数 | 周一对上周差异汇总;分析个人注册转化率排名 | 高差错员工单独培训;分享高转化话术 |
| **月** | 收银防损金额、支付趋势、个人绩效得分、顾客结账等待时长 | 月度差异趋势分析;对比同岗位均值 | 调岗/奖励建议;结账流程优化(如增开窗口) |
### 7.4 服务员(一线员工)
| 周期 | 核心指标 | 数据动作 | 输出决策 |
|:---|:---|:---|:---|
| **日** | 个人服务桌数、套餐推荐数、好评引导数、客诉关联数 | 班前看个人昨日数据;班中接受店长/主管实时反馈;班后自评 | 次日调整推荐重点(今天推A套餐效果好) |
| **周** | 个人销售额、客单价贡献、顾客点名表扬/投诉、技能抽查分 | 周会看个人排名;TOP3分享话术;BOTTOM3一对一辅导 | 下周带教配对(老带新)、针对性演练 |
| **月** | 个人绩效总分、会员注册数、复购关联数、晋升积分 | 月度绩效面谈;对比同岗位均值;确认技能等级 | 定级定薪(一星/二星/三星服务员)、晋升储备 |
**关键闭环**:个人数据每日可见→周排名激励→月定级晋升,让服务员像"打怪升级"一样有成长感
### 7.5 厨师(一线后厨)
| 周期 | 核心指标 | 数据动作 | 输出决策 |
|:---|:---|:---|:---|
| **日** | 个人出餐时效、出品自检合格率、剩料量、设备使用规范 | 每单扫码/按键记录出餐时间;闭店自查台面;登记剩料 | 次日调整个人工作站备料量 |
| **周** | 个人技能评分、配方偏差次数、损耗责任归因、创新试做反馈 | 周中技能抽检(如:切配速度、调味准确度);周末试做1款新菜 | 下周岗位轮换或专项训练 |
| **月** | 个人人效(营业额/工时)、菜品稳定率、晋升考核分 | 月度技能大考;菜品稳定性盲测;对比同岗位数据 | 定级(初级/中级/高级厨师)、调岗建议、调薪依据 |
---
## 八、总部职能支撑层数据运转
### 8.1 供应链经理(含中央厨房)
| 周期 | 核心指标 | 数据动作 | 输出决策 |
|:---|:---|:---|:---|
| **日** | 到货准时率、验收合格率、缺货次数、冷链温度异常、中央厨房产能达成 | 监控物流轨迹;处理门店到货异常;锁定缺货SKU;中央厨房生产进度 | 当日协调加急配送或门店间调拨;中央厨房调整排产 |
| **周** | 供应商交货评分、采购价格波动、库存周转天数、临期金额、中央厨房成本偏差 | 周中分析各供应商KPI;周末盘点中央仓库存;中央厨房周成本分析 | 下周调整采购量、启动供应商约谈、中央厨房工艺优化 |
| **月** | 综合采购成本率、损耗率、供应商汰换率、账期优化、中央厨房综合效率 | 月度品类采购分析;价格行情对比;供应商年度评估;中央厨房月度经营分析 | 下月招标/议价、品类替换、库存策略调整、中央厨房产能规划校准 |
### 8.2 中央厨房厂长/经理
| 周期 | 核心指标 | 数据动作 | 输出决策 |
|:---|:---|:---|:---|
| **日** | 生产计划达成率、出品合格率、设备运行率、能耗、人员出勤 | 晨会确认当日排产;实时监控关键工艺参数;闭盘汇总当日生产数据 | 当日生产异常处理、设备报修、人员调配 |
| **周** | 产能利用率、成本明细(原料/人工/能耗/包装)、出品一致性抽检、设备故障分析 | 周中成本分析会;周末出品盲测;设备维护计划 | 下周排产优化、成本改善项、设备保养、工艺微调 |
| **月** | 月度加工成本、食安合规得分、产能瓶颈分析、门店满意度调查 | 月度经营分析;与门店到货满意度对标;与竞品中央厨房成本对标 | 下月产能计划、设备投资申请、工艺升级、人员技能认证 |
### 8.3 营销经理
| 周期 | 核心指标 | 数据动作 | 输出决策 |
|:---|:---|:---|:---|
| **日** | 活动实时转化、平台曝光/点击/下单、会员新增、舆情 | 监控各平台活动数据;处理差评/舆情;调整当日投放 | 当日追加/暂停投放;指导门店执行 |
| **周** | 活动ROI、获客成本、会员分层转化、竞品动态 | 周中A/B测试(如:两种套餐哪种转化高);周末复盘活动 | 下周活动方案优化、预算再分配 |
| **月** | 营销费用占比、会员贡献率、品牌健康度、年度趋势 | 月度营销决算;会员生命周期分析;年度策略校准 | 下月营销日历、年度预算调整、品牌策略升级 |
### 8.4 培训经理
| 周期 | 核心指标 | 数据动作 | 输出决策 |
|:---|:---|:---|:---|
| **日** | 新员工带教进度、技能抽检合格率、培训出勤 | 跟进各门店带教情况;抽查培训视频/记录 | 当日催促落后门店、调整带教人选 |
| **周** | 培训覆盖率、考核通过率、技能回退率、离职归因 | 周中分析离职员工数据(是否未培训/培训后仍离职);周末课程试讲 | 下周课程迭代、薄弱门店集训 |
| **月** | 人才梯队健康度(储备干部数)、晋升通过率、培训ROI | 月度人才盘点;培训效果追踪(培训后业绩变化);课程满意度 | 下月晋升名单、课程体系更新、年度培训规划 |
### 8.5 数字化/IT经理
| 周期 | 核心指标 | 数据动作 | 输出决策 |
|:---|:---|:---|:---|
| **日** | 系统稳定性、数据上报及时率、异常告警 | 监控POS/ERP/外卖平台接口;处理门店系统故障 | 当日远程修复或派单维修 |
| **周** | 数据准确率、报表产出时效、BI使用活跃度 | 抽检门店数据质量;收集各层级看板需求 | 下周数据清洗、看板优化、权限调整 |
| **月** | 数字化项目进度、系统覆盖率、数据安全事件 | 月度数字化复盘;用户满意度调研;竞品系统对标 | 下月功能迭代、新模块上线、预算申请 |
### 8.6 产品经理(菜品研发)
| 周期 | 核心指标 | 数据动作 | 输出决策 |
|:---|:---|:---|:---|
| **日** | 菜品销售异常监控、断货预警、客诉(菜品相关) | 监控各菜品实时销量;协调供应链补货或临时下架 | 当日通知门店调整推荐话术;启动备选方案 |
| **周** | 菜品销售排行、毛利率分析、出品时效、配方执行偏差 | 周中分析TOP/BOTTOM菜品;周末盲测抽检 | 下周调整推荐位、套餐组合;启动滞销品淘汰评估 |
| **月** | 菜单健康度诊断、新品销售追踪、成本偏差、顾客反馈归因 | 月度品类矩阵分析;新品3个月存活判定;配方成本复盘 | 下月菜单微调、新品上市/老品下架、配方优化 |
| **季** | 季度菜单大迭代、竞品菜单分析、消费者调研、供应链成本变化 | 季度销售数据汇总;行业趋势研判;原料行情预测 | 下季度菜单规划、新品研发立项、价格带调整 |
---
## 九、三层级数据流转与会议体系
### 9.1 纵向会议体系
| 会议名称 | 层级 | 频率 | 参与人 | 数据输入 | 决策事项 |
|:---|:---|:---|:---|:---|:---|
| **战略委员会** | 决策层 | 季度 | 老板+VP+财务+运营总监+产品总监+供应链总监 | 集团财报、行业数据、资本环境、产品趋势、供应链产能 | 开店/关店、融资、组织变革、品牌战略、产品战略、供应链投资 |
| **月度经营分析会** | 决策层→管控层 | 月 | 老板+区域经理+职能总监(产品/供应链/营销/HR/IT) | 区域排名、品类矩阵、利润贡献、人才盘点、供应链成本、产品动销 | 资源分配、奖惩、政策调整、预算审批、产品下架/上市、供应商评估 |
| **区域周会** | 管控层 | 周 | 区域经理+店长(视频/到店) | 门店排名、巡检得分、案例分享、资源需求、到货异常 | 落后门店整改、优秀经验复制、区域活动统一、供应链问题协调 |
| **店长日会** | 执行层 | 日 | 店长+全员 | 昨日数据、今日目标、客诉案例、库存预警、到货情况 | 当日分工、重点顾客、风险预警、主推菜品、到货异常处理 |
| **月度复盘会** | 执行层→管控层 | 月 | 店长→区域经理 | 门店损益、人员盘点、设备需求、资源申请、产品反馈、供应链满意度 | 调薪、晋升、关店评估、营销资源申请、产品反馈上报、供应链投诉 |
### 9.2 横向协同会议
| 会议名称 | 参与方 | 频率 | 核心议题 |
|:---|:---|:---|:---|
| **产销协同会** | 供应链+产品+运营+营销 | 周 | 下周预估销量、库存预警、促销备货、新品上市计划、中央厨房排产 |
| **营采协同会** | 营销+采购+财务 | 月 | 下月营销方案、采购成本、促销定价、毛利测算、供应商资源 |
| **产研协同会** | 产品+供应链+中央厨房+运营 | 月 | 新品研发进度、中央厨房试制反馈、成本测算、上市排期、SOP固化 |
| **人才盘点会** | HR+区域+培训 | 季度 | 店长储备、晋升名单、调薪方案、淘汰名单、培训需求 |
| **数字化复盘会** | IT+运营+财务+供应链 | 月 | 系统稳定性、数据质量、新需求优先级、预算执行、供应链系统对接 |
| **供应链质量会** | 供应链+中央厨房+品控+区域 | 周 | 到货质量、供应商评分、食安事件、临期处理、门店投诉、中央厨房出品 |
### 9.3 数据流转路径
```
【总部/决策层】(老板/VP/产品/供应链/财务)
↓ 目标分解、标准下发、预算审批、产品上市计划、供应链策略
【区域/管控层】(区域经理/督导)←——远程看板——→【总部职能】(产品/供应链/营销/培训/IT)
↓ 到店辅导、资源调配、人才识别、产品反馈、供应链协调
【门店/执行层】(店长)←——实时数据——→【前厅/后厨/收银/服务/厨师】
↓ 每日执行、数据反馈、产品评价、到货验收
【区域/管控层】←——日报/周报/月报——→【总部/决策层】
↓ 产品迭代、供应链优化、战略调整
```
---
## 十、数据权限与看板设计
### 10.1 数据权限矩阵(纵向隔离)
| 层级 | 看数范围 | 看数频率 | 核心看板 | 操作权限 |
|:---|:---|:---|:---|:---|
| **老板/总部** | 集团汇总、区域对比、异常预警、投资回报、产品矩阵、供应链全局 | 日看预警、周看排名、月看财报、季看战略 | 集团驾驶舱、区域热力图、单店模型ROI、品类矩阵图、供应链全局看板、中央厨房产能监控 | 审批预算、审批开店/关店、制定政策、产品上市/下架、供应商战略决策 |
| **区域经理** | 辖区内所有门店明细、排名、趋势、人才数据、产品执行、供应链到货 | 日看所有店(红黄灯)、周重点店、月全覆盖 | 区域管理看板、门店健康度雷达图、人才梯队表、资源使用表、产品执行跟踪、供应链到货监控 | 调配区域预算、跨店调人、审批临时采购、店长考核权、产品反馈上报、供应链区域协调 |
| **店长** | 本店实时数据、本店历史对比、区域均值(匿名)、产品销量、供应链到货 | 每30分钟看实时、每日复盘、每周对标 | 门店日报、个人绩效排名、库存/损耗看板、客诉追踪表、产品销量排行、供应链到货看板 | 本店排班、订货、促销执行、员工考核、奖惩分配、产品反馈、到货验收 |
| **门店员工** | 个人数据、本店排名(匿名)、技能达标情况、产品知识 | 每日班前看昨日、每周看排名 | 个人绩效看板、技能等级、销售排行、产品SOP | 无审批权,仅查看 |
**原则**:上级看下级数据透明,下级看不到上级数据;平级门店之间只能看排名,不能看明细。
### 10.2 看板设计规范
| 看板类型 | 使用层级 | 刷新频率 | 核心模块 |
|:---|:---|:---|:---|
| **集团驾驶舱** | 老板/VP | T+1(日) | 总营收、门店地图、区域排名、异常预警、投资回报、产品矩阵、供应链成本 |
| **区域管理看板** | 区域经理 | 实时/小时级 | 门店列表(红黄绿灯)、营收趋势、巡检得分、人才储备、资源使用、产品执行、到货监控 |
| **门店实时看板** | 店长 | 实时(5分钟) | 当日营收进度、来客数、客单价、等位数、出餐时效、差评、产品销量、到货预警 |
| **店长日报** | 店长/区域 | 每日闭店后自动生成 | 营收达成、成本项、损耗、客诉、人员、产品表现、供应链到货、次日建议 |
| **个人绩效看板** | 员工 | 每日 | 个人销售额、套餐推荐数、好评引导数、技能分、排名 |
| **供应链全局看板** | 供应链总监/采购/物流 | 实时 | 供应商KPI、采购成本趋势、库存水位、在途温度、配送路线、中央厨房产能 |
| **中央厨房监控看板** | 中央厨房厂长/总部 | 实时 | 生产进度、设备状态、温度监控、出品抽检、成本实时、人员出勤 |
| **产品管理看板** | 产品经理/总部 | 日/周 | 菜品销量排行、毛利率矩阵、新品追踪、客诉归因、生命周期阶段、配方执行率 |
---
## 十一、附录:关键术语与工具
### 11.1 关键术语
| 术语 | 定义 |
|:---|:---|
| **ITGAR** | 指标(Indicator)→目标(Target)→差距(Gap)→行动(Action)→结果(Result)的闭环管理方法 |
| **同店增长** | 开业满12个月的门店,本期营收与去年同期对比的增长率 |
| **NPS** | 净推荐值,顾客愿意推荐给他人的比例减去不愿意的比例 |
| **坪效** | 每平方米营业面积产生的日/月营业额 |
| **人效** | 每名员工产生的营业额或利润 |
| **SKU** | 库存保有单位,此处指菜单上的单品数量 |
| **SOP** | 标准作业程序,确保服务与出品的一致性 |
| **红黄绿灯** | 绿灯(正常)、黄灯(预警)、红灯(紧急)的异常分级机制 |
| **神秘顾客** | 总部/第三方以普通顾客身份到店,按标准评分 |
| **中央厨房** | 总部集中加工半成品、酱料、净菜的加工中心,统一配送门店 |
| **MRP** | 物料需求计划,根据销售预测自动计算原料采购和生产计划 |
| **HACCP** | 危害分析与关键控制点,食品安全管理体系 |
| **IoT** | 物联网,此处指冷链温度、设备状态等实时监控 |
| **出成率** | 原料加工后可食用部分的比例,衡量加工效率 |
| **动销率** | 有销售的SKU占总SKU的比例,衡量菜单活力 |
| **盲测** | 不告知测试对象品牌/配方的情况下,进行口味/品质测试 |
### 11.2 关键工具模板
| 工具名称 | 使用层级 | 用途 |
|:---|:---|:---|
| 《门店日报表》 | 店长 | 每日营收、成本、损耗、差评、人力、产品销量、供应链到货记录 |
| 《周行动计划》 | 店长/区域 | 本周3件大事、责任人、完成标准、供应链协调项 |
| 《月度经营分析报告》 | 店长→区域→总部 | 月度损益、对标分析、根因、下月计划、资源申请、产品反馈、供应链投诉 |
| 《门店巡检表》 | 区域/督导 | 现场打分、问题拍照、整改期限、验收签字 |
| 《人才盘点表》 | 区域/HR | 店长/储备干部评估、九宫格定位、晋升/淘汰建议 |
| 《供应商评分卡》 | 供应链 | 交货准时、质量、价格、服务、食安五维度评分 |
| 《活动ROI复盘表》 | 营销 | 投入费用、曝光、转化、营收、利润、经验教训 |
| 《产品生命周期管理表》 | 产品中心 | 每款SKU的上市日期、销量趋势、毛利率、生命周期阶段、淘汰计划 |
| 《中央厨房生产日报》 | 中央厨房 | 当日排产、实际产出、出品合格率、成本、设备状态、食安记录 |
| 《供应链到货验收单》 | 门店/供应链 | 到货时间、品类、数量、重量、温度、品质、异常记录、签字确认 |
| 《配方SOP卡》 | 产品/中央厨房/门店 | 每款菜品/半成品的配方(克重/温度/时间/步骤)、图片、视频 |
### 11.3 数据预警阈值(示例)
| 指标 | 绿灯(正常) | 黄灯(预警) | 红灯(紧急) | 响应动作 |
|:---|:---|:---|:---|:---|
| 日营收达成率 | ≥95% | 80%-95% | <80% | 黄灯→加大促销;红灯→店长立即向区域汇报,启动应急方案 |
| 食材损耗率 | ≤2% | 2%-3% | >3% | 黄灯→加强盘点;红灯→停货检查,追溯责任人 |
| 顾客差评率 | ≤1% | 1%-2% | >2% | 黄灯→服务强化培训;红灯→店长亲自驻店整改一周 |
| 员工离职率 | ≤10% | 10%-15% | >15% | 黄灯→一对一沟通;红灯→调整薪酬或向总部申请调薪 |
| 食安巡检 | ≥95分 | 90-95分 | <90分 | 黄灯→限期整改;红灯→停业整顿,店长担责 |
| 中央厨房产能利用率 | 70%-90% | 60%-70%或90%-100% | <60%或>100% | 黄灯→调整排产或扩产准备;红灯→产能规划重构或外包 |
| 供应链到货准时率 | ≥98% | 95%-98% | <95% | 黄灯→供应商约谈;红灯→启动备选供应商或区域调拨 |
| 新品3个月存活率 | ≥60% | 40%-60% | <40% | 黄灯→配方微调或加大推广;红灯→下架止损,复盘归因 |
---
> **文档结语**:连锁企业的数字化运营,不是上一套系统就结束,而是建立"三层级、全岗位、日周月"的数据闭环。决策层看势,管控层抓阵,执行层做事——数据贯通但权限隔离,节奏闭环但层级分明。产品设计与供应链(含中央厨房)是连锁餐饮的"双引擎":产品决定顾客来不来,供应链决定能不能赚钱、能不能复制。三者合一,方能实现千店如一、持续盈利。
@@ -0,0 +1,402 @@
# 连锁企业数字化运营体系(系统闭环版)
> **版本**V3.0(系统闭环版)
> **适用对象**:连锁餐饮/零售品牌数字化运营团队、系统架构师、运营管理层
> **核心逻辑**:一个大脑、三条主线、五个闭环、自动流转
> **设计原则**:目标自动拆解、数据自动采集、偏差自动预警、任务自动派发、结果自动验证
---
## 目录
1. [本体逻辑总览:五层架构](#一本体逻辑总览五层架构)
2. [三条主线:数据流、决策流、执行流](#二三条主线数据流决策流执行流)
3. [五个闭环:系统自运转机制](#三五个闭环系统自运转机制)
4. [日/周/月系统自动流转](#四日周月系统自动流转)
5. [权限与隔离:系统安全机制](#五权限与隔离系统安全机制)
6. [系统核心模块架构](#六系统核心模块架构)
7. [附录:关键术语与系统接口](#七附录关键术语与系统接口)
---
## 一、本体逻辑总览:五层架构
系统闭环运营的本质,是将"决策层定战略、管控层抓过程、执行层保结果"的三层管理,通过数字化系统转化为**一套自我运转、自我修正的运营机器**。
```
┌─────────────────────────────────────────┐
│ 第五层:战略层(老板/董事会) │ ← 看"势"
│ 输入:全局仪表盘 + 季度战略看板 │ 投资回报、品牌估值、资本路径、行业趋势
├─────────────────────────────────────────┤
│ 第四层:决策层(总部各中心) │ ← 看"阵"
│ 产品中心 / 供应链中心 / 营销中心 / HR中心 │ 产品矩阵、供应链网络、开店模型、组织健康
├─────────────────────────────────────────┤
│ 第三层:管控层(区域/大区/督导) │ ← 看"店"
│ 输入:区域管理驾驶舱 + 红黄绿灯预警 │ 门店分级、资源调配、人才输送、现场辅导
├─────────────────────────────────────────┤
│ 第二层:执行层(门店/店长) │ ← 看"事"
│ 输入:门店实时看板 + 日报自动生成 │ 营收、成本、体验、团队、食安
├─────────────────────────────────────────┤
│ 第一层:作业层(一线员工/设备) │ ← 看"数"
│ 输入:个人数据看板 + 扫码/IoT自动采集 │ 个人绩效、出餐时效、扫码记录、温度数据
└─────────────────────────────────────────┘
↑↓ 数据双向流动,指令单向分解
```
| 层级 | 系统角色 | 核心输入 | 核心输出 | 人工介入点 |
|:---|:---|:---|:---|:---|
| **战略层** | 战略驾驶舱 | 全局仪表盘、行业数据、资本环境 | 年度战略目标、资本决策、组织变革 | 季度战略复盘会确认目标 |
| **决策层** | 策略引擎 | 区域聚合数据、产品矩阵、供应链全局 | 年度预算、产品规划、供应链策略、开店模型 | 月度经营分析会审批方案 |
| **管控层** | 调度中枢 | 门店实时数据、分级模型、预警流 | 区域目标拆解、资源调配指令、辅导任务 | 红黄灯预警响应、周会纠偏 |
| **执行层** | 运营终端 | 日目标卡、任务池、实时看板 | 执行记录、数据回传、异常上报 | 晨会确认目标、晚复盘确认结果 |
| **作业层** | 数据采集端 | 扫码枪、POS、IoT、考勤机 | 原子级数据实时上云 | 扫码确认、设备巡检签字 |
---
## 二、三条主线:数据流、决策流、执行流
### 2.1 主线一:数据流(自下而上,自动汇聚)
**逻辑**:作业层产生数据 → 门店汇总 → 区域聚合 → 总部分析 → 战略层判断
**系统实现路径**
| 层级 | 数据采集方式 | 汇聚逻辑 | 系统动作 |
|:---|:---|:---|:---|
| **作业层** | 扫码枪、POS机、IoT温控探针、人脸识别考勤、出品扫码枪、电子秤 | 原子级数据实时上云,零人工录入 | 每单/每笔/每次操作自动产生数据记录 |
| **门店层** | 系统自动汇总原子数据 | 营收、成本、损耗、人效、时效自动计算 | T+0实时看板刷新;T+1自动生成日报 |
| **区域层** | 自动聚合辖区内所有门店 | 计算排名、均值、标准差、偏差度 | 自动分级(A/B/C/D);红黄绿灯自动标色;异常自动推送 |
| **总部层** | 跨区域、跨品类、跨周期聚合 | 集团视角的品类矩阵、供应链成本、投资回报模型 | 自动生成月度经营分析报告;自动识别战略级异常 |
| **战略层** | 关键指标季度趋势分析 | 行业对标、资本相关性、长期价值评估 | 季度战略复盘数据包自动生成;投资建议自动测算 |
**核心逻辑**:数据只采集一次,层层自动聚合,每一层看到的都是"适合自己决策粒度"的数据。
---
### 2.2 主线二:决策流(自上而下,目标拆解)
**逻辑**:战略目标 → 年度预算 → 季度战役 → 月度目标 → 周计划 → 日目标 → 个人任务
**系统拆解路径**
| 层级 | 系统输入 | 系统拆解逻辑 | 输出物 | 人工动作 |
|:---|:---|:---|:---|:---|
| **战略层** | 年度营收增长30%、开店100家、品牌NPS≥60 | 按历史增速、市场容量、资本投入测算可行性 | 年度战略目标看板 | 董事会确认目标 |
| **决策层** | 年度战略目标 | 按区域贡献度、品类潜力、供应链产能拆解 | 区域年度目标、品类年度目标、供应链产能目标 | 总部各中心负责人确认 |
| **管控层** | 区域年度目标 + 门店分级模型 | 按门店分级(A/B/C/D)差异化拆解:A店110%、B店100%、C店90%爬坡、D店整改或关停 | 各门店月度目标、季度爬坡曲线 | 区域经理微调确认 |
| **执行层** | 门店月度目标 + 历史同期 + 天气 + 节假日 + 商圈活动 | 按"工作日/周末/节假日"差异模型拆解为日目标;按"高峰/平峰/低谷"拆解为时段目标 | 日目标卡、时段目标、主推菜品、套餐目标 | 店长晨会确认(可微调±10%) |
| **作业层** | 门店日目标 + 岗位系数 | 按服务员/厨师/收银员的历史人效,拆解为个人任务 | 个人目标:套餐推荐数、出餐时效、会员注册数、收银准确率 | 员工班前查看个人目标 |
**核心逻辑**:目标不是人工层层分解,而是系统根据算法模型自动拆解,每一层只做"确认或调整",不做"从零计算"。
---
### 2.3 主线三:执行流(横向协同,闭环跟踪)
**逻辑**:目标下达 → 任务生成 → 执行记录 → 数据回传 → 偏差预警 → 纠偏行动 → 结果验证
```
目标下达 ──→ 任务池 ──→ 岗位待办 ──→ 执行 ──→ 扫码/确认 ──→ 数据回传
↑ │
└──── 偏差预警 ←──────┘
纠偏任务生成 ──→ 新任务入池
```
**系统闭环示例**
| 触发条件 | 系统检测 | 自动动作 | 人工介入 | 结果验证 |
|:---|:---|:---|:---|:---|
| 14:00营收达成率60% | 实时看板比对日目标 | 自动红灯预警 → 推送区域经理APP → 推送店长 → 生成"午市促销任务" | 区域经理电话店长确认方案 | 18:00系统检测达成率回升至95% → 自动记录"促销有效" |
| 差评出现(菜品口味) | NLP自动归因 | 自动推送至产品中心 + 门店店长 + 区域督导 | 产品中心决定是否配方微调 | 7日后同类差评下降 → 闭环完成 |
| 临期品库存>10% | 库存系统自动计算 | 自动推送促销建议至店长 → 生成"临期品促销任务" | 店长确认执行 | 临期品清零 → 损耗率下降 → 闭环完成 |
| 中央厨房产能>90% | 产能监控看板 | 自动预警至供应链总监 → 生成"扩产评估任务" | 供应链总监决策扩产/外包 | 产能利用率回落至80% → 闭环完成 |
| 员工离职率>15% | 月度HR数据聚合 | 自动红灯预警 → 推送至区域经理 + HR总监 | 区域经理调研原因,HR启动调薪/激励方案 | 次月离职率回落至10% → 闭环完成 |
**核心逻辑**:系统不是等人发现问题,而是**自动发现、自动派单、自动追踪、自动验证**,人只在"决策确认"和"异常处理"两个环节介入。
---
## 三、五个闭环:系统自运转机制
### 3.1 闭环一:目标闭环(Target Loop)
**逻辑**:目标设定 → 自动拆解 → 执行跟踪 → 结果比对 → 偏差分析 → 目标校准
```
战略输入(年度增长30%
系统自动拆解 → 区域目标 + 品类目标 + 供应链目标
门店自动接收 → 日目标卡生成
实时执行跟踪 → 每小时比对达成率
月末自动比对 → 达成率计算
偏差自动分析 → 归因模型(客流/客单/成本/损耗)
目标自动校准 → 下月目标调整(A店上调、C店下调或关停)
循环往复
```
**系统强制节点**
- 月末达成率<90%的门店,系统**强制锁定**下月预算,必须填写《根因分析》并通过区域经理审批后方可解锁
- 连续3个月未达成目标的门店,系统自动触发"D级预警",推送至决策层
---
### 3.2 闭环二:数据闭环(Data Loop)
**逻辑**:采集 → 清洗 → 聚合 → 分析 → 呈现 → 决策 → 执行 → 再采集
| 环节 | 系统功能 | 关键机制 |
|:---|:---|:---|
| **采集** | POS、外卖平台、IoT温控、扫码枪、电子秤、人脸识别、考勤机、视频监控AI | 多源数据自动接入,API对接+IoT直连 |
| **清洗** | 异常数据自动标记(如单笔金额异常高/低、温度异常波动、扫码时间异常) | 规则引擎+机器学习异常检测 |
| **聚合** | 按岗位、门店、区域、总部自动分层聚合;按日/周/月/季/年自动时间聚合 | 数据仓库自动ETL |
| **分析** | 自动计算同比/环比/达成率/偏差度/排名/趋势预测 | BI引擎自动运算 |
| **呈现** | 每一层只看见权限内的数据;自动推送至对应责任人 | 权限矩阵+消息推送引擎 |
| **决策** | 数据看板直接嵌入"一键下达任务"按钮;异常自动触发决策建议 | 决策辅助AI(如:达成率低→建议启动促销) |
| **执行** | 任务执行后扫码确认,数据自动回传 | 任务管理系统闭环 |
| **再采集** | 执行数据成为新的数据源,进入下一轮循环 | 无限循环 |
---
### 3.3 闭环三:业务闭环(Business Loop
**逻辑**:产品 → 供应链 → 门店 → 顾客 → 反馈 → 产品迭代
```
产品中心上架新品
系统自动推送配方SOP至中央厨房
中央厨房MRP系统自动排产
物流配送系统自动调度
门店收货扫码确认
门店销售(POS记录)
顾客评价(好评/差评自动归因)
产品中心看板显示:新品销量、好评率、毛利率、生命周期阶段
系统判定:
├─ 好评率>90% + 销量达标 → 自动建议"扩大上市"
├─ 好评率70-90% + 销量一般 → 自动建议"配方微调+加大推广"
└─ 好评率<70% 或 销量不达标 → 自动建议"下架止损"
产品中心确认决策 → 系统执行
循环往复
```
**关键系统节点**
- 新品上市前30天,系统自动生成"上市准备清单"(培训课件、物料包、推荐位、促销方案)
- 新品上市第7天,系统自动生成"首周战报"(销量、好评率、成本偏差)
- 新品上市第90天,系统自动生成"存活判定报告"(去留建议)
---
### 3.4 闭环四:协同闭环(Collaboration Loop
**逻辑**:产销协同、营采协同、产研协同、人才盘点
| 协同场景 | 系统流转路径 | 关键接口 |
|:---|:---|:---|
| **产销协同** | 门店销量预测(AI算法)→ 自动推送至中央厨房MRP → 自动生成采购需求 → 供应商接单 → 到货 → 门店验收 → 数据回传 | 门店POS ↔ 中央厨房ERP ↔ 供应商SRM |
| **营采协同** | 营销方案制定 → 系统自动计算所需物料 → 推送供应链备货 → 推送门店执行 → 活动效果数据回流 → 自动计算ROI | 营销系统 ↔ 供应链WMS ↔ 门店任务系统 |
| **产研协同** | 产品中心研发立项 → 中央厨房试制排期 → 试制数据回传 → 成本测算 → 盲测安排 → 结果录入 → 上市决策 | 产品PLM ↔ 中央厨房MES ↔ 测试管理系统 |
| **人才盘点** | 门店绩效数据自动聚合 → HR系统生成九宫格 → 晋升名单自动推荐 → 培训计划自动生成 → 执行跟踪 → 效果验证 | HR系统 ↔ 门店绩效系统 ↔ 培训LMS |
| **供应链质量协同** | 到货验收异常 → 自动推送供应商SRM → 供应商整改 → 整改结果上传 → 门店复验 → 评分更新 | 门店验收APP ↔ 供应商SRM ↔ 质量管理系统 |
---
### 3.5 闭环五:迭代闭环(Improvement Loop
**逻辑**:执行 → 复盘 → 知识沉淀 → 标准更新 → 培训下发 → 再执行
| 环节 | 系统功能 | 关键机制 |
|:---|:---|:---|
| **执行** | 日常运营数据自动记录 | 全链路数据留痕 |
| **复盘** | 月度/季度自动复盘报告生成 | 数据自动归因、标杆自动识别、问题自动聚类 |
| **知识沉淀** | 优秀案例自动归档至知识库;问题案例自动进入案例库 | NLP自动提取案例要素、自动标签分类 |
| **标准更新** | 案例库触发SOP更新流程;配方偏差触发配方校准流程 | 变更管理流程(申请→审批→下发→确认) |
| **培训下发** | 新标准自动转化为培训课件 → 推送至落后门店/新员工 | LMS系统自动匹配培训对象、自动追踪完成率 |
| **再执行** | 下次巡检验证执行效果;下次数据验证改进结果 | 巡检APP扫码验证、数据比对验证 |
**关键系统节点**
- 月度复盘会上确认的"优秀案例",系统**24小时内**自动归档并生成培训课件
- 新SOP下发后,系统**强制要求**相关岗位员工在7天内完成线上学习并通过测试
- 未按时完成培训的员工,系统自动**锁定排班权限**(无法排班直至完成)
---
## 四、日/周/月系统自动流转
系统不是"人想起来才去看",而是**时间驱动 + 事件驱动**的双引擎。
### 4.1 时间驱动(Time-Driven
| 触发时间 | 系统动作 | 推送对象 | 人工介入点 |
|:---|:---|:---|:---|
| **每日 08:30** | 自动生成昨日日报(营收/成本/损耗/客诉/人员/供应链到货) | 店长 + 区域经理 | 店长晨会确认今日目标 |
| **每日 09:00** | 自动生成今日目标卡(营收/客单/套餐/损耗/到货) | 店长 + 全员 | 店长晨会宣导 |
| **每日 12:00 / 18:00** | 自动推送时段达成率(午市/晚市进度) | 店长 | 店长高峰盯场 |
| **每日 22:30** | 自动生成日复盘模板(达成率/偏差/次日建议) | 店长 | 店长填写根因 + 确认 |
| **每周一 09:00** | 自动生成上周数据包(排名/趋势/品类/人员) | 区域经理 + 店长 | 区域周会 / 店长周计划会 |
| **每周日 20:00** | 自动生成周复盘模板 | 店长 | 店长填写 + 提交区域 |
| **每月1日 09:00** | 自动生成上月经营分析报告(损益/对标/根因/建议) | 区域经理 + 总部职能 | 月度经营分析会 |
| **每月15日 14:00** | 自动生成月中进度报告(应完成45%) | 店长 + 区域经理 | 月中纠偏会 |
| **每季度首月1日** | 自动生成季度战略复盘数据包 | 决策层 | 战略委员会 |
### 4.2 事件驱动(Event-Driven
| 触发条件 | 系统检测 | 自动动作 | 响应时效 | 升级路径 |
|:---|:---|:---|:---|:---|
| 营收达成率 < 80% | 实时看板每小时比对 | 红灯预警 → 推送店长APP → 推送区域经理 → 生成促销建议 | 30分钟内 | 2小时未响应 → 自动升级至总部运营 |
| 差评出现 | NLP自动归因(菜品/服务/环境/异物) | 自动推送对应责任人(产品中心/店长/区域督导) | 15分钟内 | 24小时未闭环 → 升级至区域经理 |
| 临期品 > 库存10% | 库存系统实时计算 | 自动推送促销建议 → 生成促销任务 → 推送店长 | 即时 | 3天未处理 → 自动升级至供应链 |
| 中央厨房产能 > 90% | 产能监控看板实时检测 | 自动预警至供应链总监 → 生成扩产评估任务 | 即时 | 持续3天 → 升级至决策层 |
| 员工离职率 > 15% | HR系统月度聚合 | 红灯预警 → 推送区域经理 + HR总监 | 月度 | 连续2月 → 升级至CEO |
| 食安巡检 < 90分 | 巡检系统实时评分 | 红灯预警 → 推送店长 + 区域经理 + 总部品控 | 即时 | 24小时未整改 → 自动触发停业建议 |
| 供应链到货准时率 < 95% | 物流GPS+温控实时监控 | 黄灯预警 → 推送供应链经理 → 启动备选供应商 | 即时 | 连续3次 → 自动触发供应商降级 |
| 新品好评率 < 70% | 评价系统每日聚合 | 自动推送产品中心 → 生成配方复核任务 | 每日 | 30天未改善 → 自动触发下架流程 |
| 设备故障 > 2小时 | IoT设备监控 | 自动派单维修 → 推送店长备用方案 | 即时 | 4小时未修复 → 升级至区域 |
| 库存缺货 | 库存系统实时比对 | 自动推送缺货预警 → 生成调拨建议(附近门店/中央仓) | 即时 | 当日未解决 → 升级至供应链 |
---
## 五、权限与隔离:系统安全机制
### 5.1 纵向权限矩阵(层级隔离)
| 规则 | 系统实现 |
|:---|:---|
| **上级看下级透明** | 区域经理可查看辖区内所有门店明细数据;总部可查看所有区域明细 |
| **下级不可看上级** | 店长不可查看区域排名明细(只能看匿名均值);员工不可看门店利润 |
| **平级看排名不看明细** | A店店长可查看"区域均值"和"区域排名",但不可查看B店具体营收数据 |
| **数据脱敏** | 区域均值显示为"区域平均",不暴露具体门店名称;集团排名显示为"TOP10%" |
### 5.2 横向权限矩阵(职能隔离)
| 角色 | 可见范围 | 不可见范围 | 操作权限 |
|:---|:---|:---|:---|
| **供应链经理** | 采购成本、供应商评分、库存水位、物流轨迹 | 单店利润明细、员工绩效、顾客信息 | 采购下单、供应商评级、调拨审批 |
| **产品经理** | 菜品销量、好评率、配方SOP、成本测算 | 门店具体营收、员工工资、供应链采购价 | 配方修改、上市/下架决策、定价建议 |
| **营销经理** | 活动ROI、会员数据、平台评分、舆情 | 单店成本明细、员工绩效、供应链数据 | 活动创建、预算分配、券码发放 |
| **HR/培训经理** | 员工档案、绩效数据、培训记录、离职率 | 门店营收、成本、顾客数据 | 调薪审批、培训下发、晋升提名 |
| **店长** | 本店全部数据、区域匿名均值、个人绩效 | 其他门店明细、采购价格、总部预算 | 排班、订货、促销执行、员工考核 |
| **服务员/厨师** | 个人绩效、本店排名(匿名)、技能等级 | 门店营收、成本、利润、他人工资 | 扫码确认、任务执行、培训学习 |
### 5.3 审批流矩阵(操作权限)
| 操作 | 申请人 | 审批人 | 备案人 | 超额度升级 |
|:---|:---|:---|:---|:---|
| 门店调薪(单次<500元) | 店长 | 区域经理 | HR系统 | 单次≥500元 → 总部HR审批 |
| 门店临时采购(<2000元) | 店长 | 区域经理 | 供应链系统 | ≥2000元 → 供应链总监审批 |
| 促销活动(<5000元) | 店长 | 区域经理 | 营销系统 | ≥5000元 → 营销总监审批 |
| 员工晋升(星级调整) | 店长 | 区域经理 + HR | 人才系统 | 晋升店长 → 总部HR + 运营总监 |
| 配方微调 | 产品经理 | 产品总监 | 中央厨房 | 成本变动>5% → CEO审批 |
| 供应商汰换 | 供应链经理 | 供应链总监 | 财务系统 | 战略供应商 → CEO审批 |
| 门店关停 | 区域经理 | 运营总监 + 财务总监 | 战略系统 | 连续亏损6个月 → 董事会 |
---
## 六、系统核心模块架构
### 6.1 系统模块总览
```
┌─────────────────────────────────────────────────────────────┐
│ 战略驾驶舱 │
│ (全局仪表盘 / 季度战略看板 / 投资回报模型) │
├─────────────────────────────────────────────────────────────┤
│ 产品中心 │ 供应链中心 │ 营销中心 │ HR中心 │ 财务中心 │
│ PLM系统 │ SRM+ERP │ CRM+MA │ HRM │ ERP+BI │
│ 配方管理 │ 中央厨房MES │ 会员系统 │ 培训LMS │ 预算管理 │
│ 生命周期 │ WMS+TMS │ 舆情监控 │ 绩效系统 │ 成本核算 │
├─────────────────────────────────────────────────────────────┤
│ 区域管理驾驶舱 │
│ (门店分级 / 红黄绿灯 / 资源调度 / 人才梯队) │
├─────────────────────────────────────────────────────────────┤
│ 门店运营终端 │
│ (实时看板 / 任务池 / 日报 / 扫码确认) │
├─────────────────────────────────────────────────────────────┤
│ 数据采集层 │
│ POS │ 外卖API │ IoT温控 │ 扫码枪 │ 电子秤 │ 人脸识别 │ 视频监控AI │
└─────────────────────────────────────────────────────────────┘
```
### 6.2 核心模块功能清单
| 模块 | 核心功能 | 数据输入 | 数据输出 | 对接模块 |
|:---|:---|:---|:---|:---|
| **战略驾驶舱** | 全局仪表盘、季度战略看板、投资回报模型、行业对标 | 全集团聚合数据、外部行业数据、资本数据 | 年度战略目标、投资决策建议 | 全部模块 |
| **产品PLM** | 菜单规划、新品研发、配方SOP、生命周期管理、定价策略 | 市场调研、顾客评价、成本数据、竞品数据 | 配方SOP、上市计划、下架建议、定价方案 | 中央厨房MES、门店POS、供应链SRM |
| **供应链SRM** | 供应商管理、采购下单、比价议价、绩效评估 | 供应商数据、市场行情、采购历史 | 供应商评分、采购订单、成本分析报告 | 中央厨房ERP、WMS、门店验收APP |
| **中央厨房MES** | 生产排程、工艺监控、出品管理、成本核算、食安留样 | 门店销量预测、配方SOP、原料库存 | 生产计划、出品数据、成本数据、配送指令 | 产品PLM、WMS、门店POS |
| **WMS仓储** | 库存管理、临期预警、分拣调度、盘点差异 | 采购入库、生产入库、门店退货 | 库存水位、临期报告、分拣指令、盘点报告 | 中央厨房MES、TMS、门店验收 |
| **TMS物流** | 配送路线、车辆调度、在途温控、到货时效 | 门店订单、车辆GPS、温控IoT | 配送轨迹、温度记录、到货准时率、物流成本 | WMS、门店验收APP |
| **门店POS** | 点单收银、优惠核销、会员注册、销售数据 | 菜单数据、会员数据、支付接口 | 销售流水、客单数据、会员行为、营收报表 | 全部上层模块 |
| **区域管理** | 门店分级、红黄绿灯、资源调度、辅导任务、人才识别 | 门店实时数据、巡检数据、绩效数据 | 区域排名、预警流、任务派发、资源分配方案 | 战略驾驶舱、门店终端 |
| **门店终端** | 实时看板、任务池、日报生成、扫码确认、异常上报 | POS数据、IoT数据、任务执行数据 | 执行记录、确认数据、复盘报告 | 区域管理、HR绩效 |
| **HR系统** | 招聘、考勤、薪酬、绩效、晋升、培训 | 门店绩效、员工行为、培训记录 | 人才九宫格、晋升名单、培训计划、离职预警 | 门店终端、培训LMS |
| **培训LMS** | 课程管理、学习追踪、考试认证、技能等级 | SOP更新、案例库、培训需求 | 学习完成率、考试通过率、技能等级、培训ROI | HR系统、门店终端 |
| **营销MA** | 活动管理、会员运营、券码发放、ROI追踪 | 会员数据、销售数据、平台数据 | 活动方案、券码、投放指令、ROI报告 | 门店POS、CRM、财务 |
| **财务ERP** | 预算管理、成本核算、利润分析、资金管控 | 全部业务模块数据 | 财务报表、预算执行、成本分析、资金计划 | 全部模块 |
| **数据采集层** | POS机、外卖API、IoT探针、扫码枪、电子秤、人脸识别、视频监控AI | 物理世界操作 | 原子级数据流 | 全部上层模块 |
---
## 七、附录:关键术语与系统接口
### 7.1 关键术语
| 术语 | 定义 |
|:---|:---|
| **ITGAR** | 指标(Indicator)→目标(Target)→差距(Gap)→行动(Action)→结果(Result)的闭环管理方法 |
| **T+0 / T+1** | T+0指实时数据(如实时看板);T+1指次日汇总数据(如日报) |
| **MRP** | 物料需求计划,根据销售预测自动计算原料采购和生产计划 |
| **MES** | 制造执行系统,中央厨房的生产排程和工艺监控系统 |
| **PLM** | 产品生命周期管理,菜单和SKU的全流程管理系统 |
| **SRM** | 供应商关系管理,供应商准入、评估、汰换的系统 |
| **WMS** | 仓库管理系统,库存、分拣、盘点的系统 |
| **TMS** | 运输管理系统,配送路线、车辆调度、在途监控的系统 |
| **LMS** | 学习管理系统,培训课程、学习追踪、考试认证的系统 |
| **MA** | 营销自动化,活动创建、投放、追踪、ROI计算的系统 |
| **NLP** | 自然语言处理,此处用于自动分析顾客评价文本并归因 |
| **IoT** | 物联网,此处指冷链温度、设备状态、在途温控的实时监控 |
| **ETL** | 抽取-转换-加载,数据从采集到聚合的自动处理过程 |
| **BI** | 商业智能,数据分析和可视化呈现的系统 |
| **红黄绿灯** | 绿灯(正常)、黄灯(预警)、红灯(紧急)的自动分级机制 |
| **原子级数据** | 不可再拆分的最小数据单元(如一次扫码、一笔订单、一次测温) |
### 7.2 关键系统接口
| 接口方向 | 数据内容 | 频率 | 协议 |
|:---|:---|:---|:---|
| POS → 数据中台 | 销售流水、客单明细、支付数据、会员行为 | 实时 | API |
| 外卖平台 → 数据中台 | 外卖订单、评价、退款、平台活动数据 | 实时 | API |
| IoT温控 → 数据中台 | 温度、湿度、设备状态、能耗 | 每5分钟 | MQTT |
| 扫码枪 → 数据中台 | 出品扫码、验收扫码、盘点扫码 | 每次操作 | 蓝牙/WiFi |
| 人脸识别 → HR系统 | 考勤、排班匹配、工时统计 | 每次打卡 | API |
| 数据中台 → 区域管理 | 门店聚合数据、排名、预警、分级 | 实时/T+1 | 内部API |
| 数据中台 → 战略驾驶舱 | 集团聚合数据、趋势、对标、预测 | T+1/季度 | 内部API |
| 产品PLM → 中央厨房MES | 配方SOP、上市计划、工艺参数 | 每次更新 | 内部API |
| 中央厨房MES → WMS | 生产计划、成品入库、配送需求 | 每日 | 内部API |
| WMS → TMS | 配送订单、分拣清单、温度要求 | 每日 | 内部API |
| TMS → 门店验收APP | 配送轨迹、预计到达、温度记录 | 实时 | 内部API |
| 门店验收APP → 供应链SRM | 验收结果、退货记录、质量评分 | 每次到货 | 内部API |
| 营销MA → 门店POS | 活动方案、券码、推荐位配置 | 每次活动 | 内部API |
| HR系统 → 培训LMS | 员工档案、岗位、技能等级、培训需求 | 实时 | 内部API |
| 培训LMS → 门店终端 | 培训课程、考试任务、技能认证 | 每次更新 | 内部API |
| 财务ERP ↔ 全部模块 | 预算、成本、利润、资金 | 实时/T+1 | 内部API |
---
> **文档结语**:连锁企业数字化运营系统的本体逻辑,不是把Excel搬到线上,而是用**"目标自动拆解、数据自动采集、偏差自动预警、任务自动派发、结果自动验证"**五大自动化,将三层管理转化为一套自我运转、自我修正的运营机器。人只在三个环节介入:**定目标(输入)、做决策(确认/调整)、处理异常(红灯响应)**,其余全部由系统自动流转。系统不是工具,而是**组织能力的数字化载体**。

Some files were not shown because too many files have changed in this diff Show More