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>
This commit is contained in:
selfrelease
2026-08-14 19:34:04 +08:00
parent 8fd74fd78c
commit d373fb5f0c
19 changed files with 2231 additions and 22 deletions
+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 自动',
}