feat: P0/P1/P2全部功能 — 四层泳道/视角切换/KPI看板/预警/差异反打/预算/知识面板/回顾会/情景预测/Excel导入/角色权限

This commit is contained in:
Hermes CI Fix
2026-07-12 17:46:08 +08:00
parent cdf00efd69
commit ee25d5fa1d
8871 changed files with 1778433 additions and 0 deletions
+4
View File
@@ -212,3 +212,7 @@ class MapObjective(Base):
sort_order = Column(Integer, default=0, comment="排序")
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
# 兼容性: P2开发新增的模板API需要的模型
# KPIDefinition 已存在,KPITemplate映射到同一定义
KPITemplate = KPIDefinition
+69
View File
@@ -0,0 +1,69 @@
"""管理会计OS — 知识摘要模块
仿 OpenCode 的持久记忆机制(summarizer + SummaryMessageID),但做了三处改进:
1. 分层压缩(日→周→月→全部),不是一次性全量压缩
2. 结构化存储(MySQL 关系表),不是 SQLite JSON 消息
3. 保留版本链,不是覆盖式压缩
参考:OpenCode SummarizeProvider 的 prompt 框架 + CMA OperationLog 的审计日志
"""
from sqlalchemy import Column, Integer, String, Text, DateTime, JSON, ForeignKey, Float, func
from app.database import Base
class KnowledgeEvent(Base):
"""关键事件记录
自动从 OperationLog 和其他数据源抽取的"值得记住"的事件。
每个事件是一个结构化记录,包含类型、级别、关联对象、摘要描述。
这是增量压缩的输入——摘要 agent 只处理"未摘要过"的新事件。
"""
__tablename__ = "knowledge_events"
id = Column(Integer, primary_key=True, index=True)
event_type = Column(String(30), nullable=False, comment="事件类型: kpi_change/alert/decision/plan/map/import/user_action")
event_level = Column(String(20), default="info", comment="info/warning/important/critical")
source = Column(String(50), nullable=True, comment="来源: operation_log/api/erp_sync/manual")
source_id = Column(Integer, nullable=True, comment="源记录ID(如 operation_log.id")
target_type = Column(String(50), nullable=True, comment="关联对象类型: kpi/map/budget/alert/plan")
target_id = Column(Integer, nullable=True, comment="关联对象ID")
title = Column(String(300), nullable=False, comment="事件标题(一句话概括)")
description = Column(Text, nullable=True, comment="事件详细描述")
delta = Column(JSON, nullable=True, comment="变更字段和前后值: {field: {old: X, new: Y}}")
occurred_at = Column(DateTime, nullable=False, comment="事件发生时间")
created_at = Column(DateTime, server_default=func.now())
# 摘要追踪——记录该事件被哪些摘要(id列表)包含
summarized_in = Column(JSON, nullable=True, comment="包含此事件的摘要ID列表")
class KnowledgeSummary(Base):
"""知识摘要
分层存储:daily/weekly/monthly/cumulative
参考 OpenCode 的 summary_message_id 机制,但用结构化字段代替 message 指针。
"""
__tablename__ = "knowledge_summaries"
id = Column(Integer, primary_key=True, index=True)
level = Column(String(20), nullable=False, comment="摘要层级: daily/weekly/monthly/cumulative")
period_key = Column(String(20), nullable=False, comment="期间标识: 2026-06-12 / 2026-W24 / 2026-06 / cumulative")
title = Column(String(300), nullable=False, comment="摘要标题")
content = Column(Text, nullable=False, comment="摘要正文(纯文本/Markdown")
event_ids = Column(JSON, nullable=True, comment="包含的事件ID列表")
# 核心指标变化(精简提取,用于快速问答)
kpi_changes = Column(JSON, nullable=True, comment="摘要期内的KPI变化统计: [{kpi_code, kpi_name, old_value, new_value, direction, alert_level}]")
decision_points = Column(JSON, nullable=True, comment="决策点: [{time, action, actor, result}]")
key_metrics = Column(JSON, nullable=True, comment="摘要期内的关键指标快照: {kpi_code: value}")
# 元信息
prev_summary_id = Column(Integer, nullable=True, comment="上一级摘要ID(如 daily→weekly 的链路)")
next_compressed_by = Column(Integer, nullable=True, comment="被哪个更高层摘要包含")
token_estimate = Column(Integer, default=0, comment="估算token数(用于触发压缩阈值判断)")
model = Column(String(50), nullable=True, comment="生成摘要使用的模型名")
generated_by = Column(String(100), nullable=True, comment="生成方式: auto_scheduler/manual_trigger")
is_stale = Column(Integer, default=0, comment="0=最新 1=已被上层摘要覆盖")
created_at = Column(DateTime, server_default=func.now())
+23
View File
@@ -0,0 +1,23 @@
"""管理会计OS — 知识库文章(P1-3 嵌入功能模块用)
与 KnowledgeSummary/KnowledgeEventAI摘要系统)不同,此表存储静态的CMA知识文章,
用于在功能模块右侧/底部嵌入展示。
"""
from sqlalchemy import Column, Integer, String, Text, DateTime, func
from app.database import Base
class KnowledgeArticle(Base):
"""知识库文章"""
__tablename__ = "knowledge_articles"
id = Column(Integer, primary_key=True, index=True)
title = Column(String(200), nullable=False, comment="文章标题")
summary = Column(String(500), nullable=True, comment="一句话摘要")
content = Column(Text, nullable=False, comment="文章正文(支持Markdown")
category = Column(String(50), nullable=True, comment="分类: term/formula/practice/faq")
icon = Column(String(10), default="📖", comment="图标")
related_page = Column(String(200), nullable=True, comment="关联页面路由,如 /maps/canvas/:id, /kpis, /budget, /deviations, /predict, /maps-review")
sort_order = Column(Integer, default=0, comment="排序")
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())