docs(uiux): UIUX 设计方案大改 + 5 份作业指导书对齐 + 开发任务文档

- UIUX 文档:填充 19 个缺口(多主体画像/健康度/AI+看板/增长域/洞察域/创始人端/OODA/助推/商密)
- UIUX 文档:插入 6 个新章节(十四~十九),旧章节重编号为二十~三十一,更新目录和交叉引用
- 作业指导书 x5:导航改为 6 域分组,新增 Context Bar/工作模式/Insight Rail/决策线程/多工作区等 UI 概念
- 新建 docs/2-task-uiux.md:50 个代码落地开发任务,按 P0-P6 分优先级 + 8 Sprint 规划
- 后端/前端:大量新增模型、路由、组件(来自之前 Phase 开发)
This commit is contained in:
selfrelease
2026-07-19 11:53:38 +08:00
parent 734a16a7f3
commit fad458b2a7
243 changed files with 19898 additions and 658 deletions
+63
View File
@@ -3,20 +3,83 @@
导入所有模型以便 Alembic 自动发现。
"""
from app.models.aar import AARRecord
from app.models.agent_execution import AgentExecution
from app.models.agreement import InvestmentAgreement
from app.models.audit import AuditLog
from app.models.board import BoardMeeting
from app.models.company import Company
from app.models.customer_plan import CustomerAcquisitionPlan
from app.models.data_source import DataSource
from app.models.decision_sentinel import DecisionSentinel
from app.models.digital_twin import DigitalTwinModel
from app.models.exit_prediction import ExitPrediction
from app.models.financial_data import FinancialData
from app.models.health_score import HealthScore
from app.models.hypothesis import Hypothesis
from app.models.inquiry import InquiryList
from app.models.intervention import InterventionEvent, InterventionResult
from app.models.knowledge import KnowledgeChunk
from app.models.knowledge_graph import KnowledgeNode
from app.models.major_event import MajorEvent
from app.models.milestone import MilestoneTree
from app.models.nudge import NudgeRecord
from app.models.okr import OKR
from app.models.peer_circle import PeerLearningCircle
from app.models.portfolio_simulation import MonteCarloSimulation, PortfolioRebalancing
from app.models.pre_mortem import PreMortemRecord, RedTeamRecord
from app.models.product_diagnostic import ProductDiagnostic
from app.models.profile import FirmProfile, FundProfile, ManagerProfile
from app.models.report import MonthlyReport
from app.models.risk import RiskEvent
from app.models.synergy import SynergyOpportunity
from app.models.talent import TalentProfile, TeamMember
from app.models.task import Comment, Task
from app.models.tenant import Tenant
from app.models.user import User
from app.models.weak_signal import WeakSignal
__all__ = [
"AARRecord",
"AgentExecution",
"AuditLog",
"BoardMeeting",
"Comment",
"Company",
"CustomerAcquisitionPlan",
"DataSource",
"DecisionSentinel",
"DigitalTwinModel",
"ExitPrediction",
"FinancialData",
"FirmProfile",
"FundProfile",
"HealthScore",
"Hypothesis",
"InquiryList",
"InterventionEvent",
"InterventionResult",
"InvestmentAgreement",
"KnowledgeChunk",
"KnowledgeNode",
"MajorEvent",
"ManagerProfile",
"MilestoneTree",
"MonteCarloSimulation",
"MonthlyReport",
"NudgeRecord",
"OKR",
"PeerLearningCircle",
"PortfolioRebalancing",
"PreMortemRecord",
"ProductDiagnostic",
"RedTeamRecord",
"RiskEvent",
"SynergyOpportunity",
"TalentProfile",
"Task",
"TeamMember",
"Tenant",
"User",
"WeakSignal",
]
+29
View File
@@ -0,0 +1,29 @@
"""AAR 系统化复盘模型。"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class AARRecord(Base):
"""AAR 复盘记录。"""
__tablename__ = "aar_records"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
trigger_event: Mapped[str] = mapped_column(String(200), nullable=False, comment="触发事件")
original_plan: Mapped[str | None] = mapped_column(Text, nullable=True, comment="原计划")
actual_result: Mapped[str | None] = mapped_column(Text, nullable=True, comment="实际结果")
gap_analysis: Mapped[str | None] = mapped_column(Text, nullable=True, comment="差异分析")
lessons: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="五问复盘结论")
improvements: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="改进措施 + 执行追踪")
knowledge_graph_ref: Mapped[str | None] = mapped_column(String(36), nullable=True, comment="知识图谱节点 ID")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+35
View File
@@ -0,0 +1,35 @@
"""Agent 执行记录模型。
L1-L4 分级自治执行。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class AgentExecution(Base):
"""Agent 执行记录。"""
__tablename__ = "agent_executions"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
tenant_id: Mapped[str] = mapped_column(String(36), ForeignKey("tenants.id"), nullable=False, index=True)
agent_name: Mapped[str] = mapped_column(String(100), nullable=False, comment="Agent 名称")
autonomy_level: Mapped[str] = mapped_column(String(10), nullable=False, comment="L1/L2/L3/L4")
input_summary: Mapped[str | None] = mapped_column(Text, nullable=True, comment="输入摘要")
output_summary: Mapped[str | None] = mapped_column(Text, nullable=True, comment="输出摘要")
output_detail: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="输出详情")
review_status: Mapped[str] = mapped_column(String(20), nullable=False, default="pending", comment="pending/approved/rejected/auto_approved")
reviewer_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("users.id"), nullable=True)
reviewed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
model_version: Mapped[str | None] = mapped_column(String(50), nullable=True)
duration_ms: Mapped[int | None] = mapped_column(nullable=True, comment="执行耗时")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+36
View File
@@ -0,0 +1,36 @@
"""投资协议模型。
协议条款提取与持续监控。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class InvestmentAgreement(Base):
"""投资协议。"""
__tablename__ = "investment_agreements"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
title: Mapped[str] = mapped_column(String(200), nullable=False, comment="协议名称")
signed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, comment="签署日期")
file_url: Mapped[str | None] = mapped_column(String(500), nullable=True, comment="文件 URL")
key_clauses: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="关键条款 JSON")
monitoring_rules: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="监控规则")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="active", comment="active/expired/terminated")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+38
View File
@@ -0,0 +1,38 @@
"""董事会会议模型。
议程、纪要、决议追踪。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class BoardMeeting(Base):
"""董事会会议。"""
__tablename__ = "board_meetings"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
title: Mapped[str] = mapped_column(String(200), nullable=False, comment="会议主题")
meeting_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, comment="会议时间")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="scheduled", comment="scheduled/in_progress/completed")
agenda: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="议程列表")
materials_summary: Mapped[str | None] = mapped_column(Text, nullable=True, comment="AI 会前材料摘要")
minutes: Mapped[str | None] = mapped_column(Text, nullable=True, comment="会议纪要")
resolutions: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="决议列表 — 含状态追踪")
questions: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="AI 提问清单")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+38
View File
@@ -0,0 +1,38 @@
"""客户获取计划模型。
AI 客户增长引擎 — LP 资源匹配 + 客户获取方案。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class CustomerAcquisitionPlan(Base):
"""客户获取计划。"""
__tablename__ = "customer_acquisition_plans"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
target_customer: Mapped[str | None] = mapped_column(Text, nullable=True, comment="目标客户画像")
entry_angle: Mapped[str | None] = mapped_column(Text, nullable=True, comment="切入角度")
decision_chain: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="决策链分析")
pricing_strategy: Mapped[str | None] = mapped_column(Text, nullable=True, comment="定价策略")
competitive_analysis: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="竞争分析")
lp_resources: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="可利用 LP 资源")
execution_status: Mapped[str] = mapped_column(String(20), nullable=False, default="planned", comment="planned/executing/completed/failed")
result: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="执行结果")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+35
View File
@@ -0,0 +1,35 @@
"""数据源模型。"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class DataSource(Base):
"""外部数据源配置。"""
__tablename__ = "data_sources"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("companies.id"), nullable=True, index=True)
tenant_id: Mapped[str] = mapped_column(String(36), ForeignKey("tenants.id"), nullable=False, index=True)
source_type: Mapped[str] = mapped_column(String(50), nullable=False, comment="crunchbase/business_registry/github/custom")
name: Mapped[str] = mapped_column(String(200), nullable=False)
api_endpoint: Mapped[str | None] = mapped_column(String(500), nullable=True)
api_key_encrypted: Mapped[str | None] = mapped_column(Text, nullable=True, comment="加密后的 API Key")
config: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="配置参数")
last_synced_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
status: Mapped[str] = mapped_column(String(20), nullable=False, default="inactive", comment="active/inactive/error")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+39
View File
@@ -0,0 +1,39 @@
"""决策前哨模型。
识别企业关键决策岔路口,AI 提前生成场景分析。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class DecisionSentinel(Base):
"""决策前哨。"""
__tablename__ = "decision_sentinels"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
decision_type: Mapped[str] = mapped_column(String(50), nullable=False, comment="pivot/hiring/funding/product/org")
title: Mapped[str] = mapped_column(String(200), nullable=False, comment="决策标题")
description: Mapped[str | None] = mapped_column(Text, nullable=True)
signals: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="触发信号列表")
scenarios: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="场景分析 — A 路线 vs B 路线")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="identified", comment="identified/analyzed/acted/dismissed")
identified_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+31
View File
@@ -0,0 +1,31 @@
"""数字孪生模型。"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, Float, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class DigitalTwinModel(Base):
"""数字孪生。"""
__tablename__ = "digital_twins"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
model_params: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="模型参数")
scenarios: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="模拟场景列表")
accuracy_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="精度评分(0-1")
last_calibrated_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+29
View File
@@ -0,0 +1,29 @@
"""退出预测模型。"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, Float, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class ExitPrediction(Base):
"""退出时机预测。"""
__tablename__ = "exit_predictions"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
exit_path: Mapped[str | None] = mapped_column(String(50), nullable=True, comment="ipo/acquisition/secondary/merger")
timing_window: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="时机窗口 — 起止时间")
expected_return: Mapped[float | None] = mapped_column(Float, nullable=True, comment="期望收益率")
hold_return: Mapped[float | None] = mapped_column(Float, nullable=True, comment="继续持有预期收益率")
confidence: Mapped[float | None] = mapped_column(Float, nullable=True, comment="置信度")
signals: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="退出信号")
recommendation: Mapped[str | None] = mapped_column(Text, nullable=True, comment="退出建议")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+37
View File
@@ -0,0 +1,37 @@
"""财务数据模型。
资产负债表、利润表、现金流量表、科目余额。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, Float, ForeignKey, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class FinancialData(Base):
"""财务数据。"""
__tablename__ = "financial_data"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
period_year: Mapped[int] = mapped_column(Integer, nullable=False, comment="年份")
period_month: Mapped[int] = mapped_column(Integer, nullable=False, comment="月份")
statement_type: Mapped[str] = mapped_column(String(50), nullable=False, comment="balance_sheet/income/cash_flow")
data_json: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="财务数据 JSON")
source: Mapped[str | None] = mapped_column(String(100), nullable=True, comment="数据来源")
credibility_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="可信度评分(0-100")
validation_result: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="校验结果")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+17 -1
View File
@@ -1,6 +1,8 @@
"""健康度评分模型。
多维度评分:财务、经营、AI+ 商业化、AI+ 成本。
多维度评分:财务、经营、AI+ 商业化、AI+ 成本(基础 4 维度)
T2.9 扩展:组织人才、产品技术、市场竞争、治理合规、融资资本(9 维度)。
T3.11 扩展:协同赋能、AI 模型产品、数据合规、团队技术、客户成功(14 维度)。
"""
import uuid
@@ -21,10 +23,24 @@ class HealthScore(Base):
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
total_score: Mapped[float] = mapped_column(Float, nullable=False, comment="总分(0-100")
# 基础 4 维度
financial_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="财务健康度")
operational_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="经营健康度")
ai_commercial_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="AI+ 商业化健康度")
ai_cost_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="AI+ 成本健康度")
# T2.9 扩展 5 维度
org_talent_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="组织人才健康度")
product_tech_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="产品技术健康度")
market_compete_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="市场竞争健康度")
governance_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="治理合规健康度")
financing_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="融资资本健康度")
# T3.11 扩展 5 维度
synergy_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="协同赋能健康度")
ai_model_product_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="AI 模型产品健康度")
data_compliance_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="数据合规健康度")
team_tech_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="团队技术健康度")
customer_success_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="客户成功健康度")
# 元数据
trend: Mapped[str | None] = mapped_column(String(20), nullable=True, comment="趋势:up/stable/down")
evidence_json: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="评分依据")
recommendations_json: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="建议动作")
+35
View File
@@ -0,0 +1,35 @@
"""BML 认知追踪模型。
假设/实验/数据/结论 — Build-Measure-Learn 循环。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class Hypothesis(Base):
"""BML 认知追踪 — 假设记录。"""
__tablename__ = "hypotheses"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
hypothesis: Mapped[str] = mapped_column(Text, nullable=False, comment="假设")
experiment: Mapped[str | None] = mapped_column(Text, nullable=True, comment="验证实验")
data: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="实验数据")
conclusion: Mapped[str | None] = mapped_column(Text, nullable=True, comment="结论")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="building", comment="building/measuring/learning/validated/invalidated")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+37
View File
@@ -0,0 +1,37 @@
"""追问清单模型。
AI 根据月报数据生成补充问题,企业可回复。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class InquiryList(Base):
"""追问清单。"""
__tablename__ = "inquiry_lists"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
report_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("monthly_reports.id"), nullable=True)
questions: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="问题列表 — 含问题和回答")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="sent", comment="sent/answered/closed")
sent_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
answered_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+49
View File
@@ -0,0 +1,49 @@
"""干预事件与结果模型。
投后管理 Alpha 归因 — 干预事件 → 指标变化 → 估值影响 → 回报贡献。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, Float, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class InterventionEvent(Base):
"""干预事件。"""
__tablename__ = "intervention_events"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
intervention_type: Mapped[str] = mapped_column(String(50), nullable=False, comment="recruitment/customer_intro/strategy/governance/crisis/funding")
title: Mapped[str] = mapped_column(String(200), nullable=False)
description: Mapped[str | None] = mapped_column(Text, nullable=True)
executed_by: Mapped[str | None] = mapped_column(String(36), ForeignKey("users.id"), nullable=True)
executed_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
class InterventionResult(Base):
"""干预结果。"""
__tablename__ = "intervention_results"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
intervention_id: Mapped[str] = mapped_column(String(36), ForeignKey("intervention_events.id"), nullable=False, index=True)
metric_changes: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="指标变化")
valuation_impact: Mapped[float | None] = mapped_column(Float, nullable=True, comment="估值影响")
return_contribution: Mapped[float | None] = mapped_column(Float, nullable=True, comment="回报贡献")
alpha_score: Mapped[float | None] = mapped_column(Float, nullable=True, comment="Alpha 归因评分")
evidence: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="证据链")
measured_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+27
View File
@@ -0,0 +1,27 @@
"""RAG 知识库模型。"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import JSON, DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
class KnowledgeChunk(Base):
"""知识库分块 — 向量化的月报/报告片段。"""
__tablename__ = "knowledge_chunks"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
tenant_id: Mapped[str] = mapped_column(String(36), ForeignKey("tenants.id"), nullable=False, index=True)
source_type: Mapped[str] = mapped_column(String(50), nullable=False, comment="report/agreement/board/aar/knowledge_graph")
source_id: Mapped[str | None] = mapped_column(String(36), nullable=True, comment="来源记录 ID")
company_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("companies.id"), nullable=True, index=True)
content: Mapped[str] = mapped_column(Text, nullable=False, comment="文本内容")
embedding: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="向量嵌入")
metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="元数据")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+30
View File
@@ -0,0 +1,30 @@
"""知识图谱模型。
企业特征 + 管理动作 + 环境上下文 → 结果 → 回报影响。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import JSON, DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class KnowledgeNode(Base):
"""知识图谱节点。"""
__tablename__ = "knowledge_nodes"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
tenant_id: Mapped[str] = mapped_column(String(36), ForeignKey("tenants.id"), nullable=False, index=True)
entity_type: Mapped[str] = mapped_column(String(50), nullable=False, comment="company/action/context/result/return")
entity_id: Mapped[str | None] = mapped_column(String(36), nullable=True, comment="关联实体 ID")
attributes: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="实体属性")
relations: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="关系列表 — target_id + relation_type")
embedding: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="向量嵌入")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+34
View File
@@ -0,0 +1,34 @@
"""重大事项模型。
AI 从月报/弱信号中自动识别重大事项。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class MajorEvent(Base):
"""重大事项。"""
__tablename__ = "major_events"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
event_type: Mapped[str] = mapped_column(String(50), nullable=False, comment="funding/personnel/product/legal/market/org")
title: Mapped[str] = mapped_column(String(200), nullable=False)
description: Mapped[str | None] = mapped_column(Text, nullable=True)
severity: Mapped[str] = mapped_column(String(20), nullable=False, default="medium", comment="low/medium/high/critical")
source: Mapped[str | None] = mapped_column(String(100), nullable=True, comment="来源:monthly_report/weak_signal/manual")
source_ref: Mapped[str | None] = mapped_column(String(36), nullable=True, comment="来源记录 ID")
evidence: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="证据链")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="identified", comment="identified/confirmed/addressed")
occurred_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+38
View File
@@ -0,0 +1,38 @@
"""里程碑树模型。
分支路径管理 + 环境变化时 AI 建议路径切换。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class MilestoneTree(Base):
"""里程碑树。"""
__tablename__ = "milestone_trees"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
name: Mapped[str] = mapped_column(String(200), nullable=False, comment="里程碑名称")
parent_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("milestone_trees.id"), nullable=True, comment="父节点")
is_current: Mapped[bool] = mapped_column(default=False, comment="是否当前路径")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="planned", comment="planned/in_progress/completed/abandoned")
target_date: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
actual_date: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
description: Mapped[str | None] = mapped_column(Text, nullable=True)
ai_analysis: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="AI 路径分析")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+31
View File
@@ -0,0 +1,31 @@
"""行为助推记录模型。
时机判断 + 策略选择 + 效果追踪。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class NudgeRecord(Base):
"""行为助推记录。"""
__tablename__ = "nudge_records"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
nudge_type: Mapped[str] = mapped_column(String(50), nullable=False, comment="anchoring/loss_aversion/social_proof/default/timing")
context: Mapped[str | None] = mapped_column(Text, nullable=True, comment="助推上下文")
message: Mapped[str] = mapped_column(Text, nullable=False, comment="助推内容")
target_user_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("users.id"), nullable=True)
accepted: Mapped[bool | None] = mapped_column(nullable=True, comment="是否接受")
effect_result: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="效果追踪")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+37
View File
@@ -0,0 +1,37 @@
"""OKR 模型。
投资人与创始人共同制定 OKR + AI 对齐度评分。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class OKR(Base):
"""OKR。"""
__tablename__ = "okrs"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
quarter: Mapped[str] = mapped_column(String(10), nullable=False, comment="如 2025-Q1")
objective: Mapped[str] = mapped_column(Text, nullable=False, comment="目标")
key_results: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="关键结果列表 — 含进度")
alignment_score: Mapped[float | None] = mapped_column(nullable=True, comment="对齐度评分(0-100")
deviation_alerts: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="偏差预警")
review_notes: Mapped[str | None] = mapped_column(Text, nullable=True, comment="复盘记录")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="active", comment="active/completed/archived")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+37
View File
@@ -0,0 +1,37 @@
"""同行学习圈模型。
AI 匹配面临类似挑战的创始人,结构化讨论。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class PeerLearningCircle(Base):
"""同行学习圈。"""
__tablename__ = "peer_learning_circles"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
tenant_id: Mapped[str] = mapped_column(String(36), ForeignKey("tenants.id"), nullable=False, index=True)
topic: Mapped[str] = mapped_column(String(200), nullable=False, comment="讨论话题")
description: Mapped[str | None] = mapped_column(Text, nullable=True)
members: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="成员列表 — 创始人 ID + 企业 ID")
discussion_framework: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="结构化讨论框架")
conclusions: Mapped[str | None] = mapped_column(Text, nullable=True, comment="讨论结论")
action_commitments: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="行动承诺")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="matching", comment="matching/active/completed")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
@@ -0,0 +1,45 @@
"""组合再平衡 + Monte Carlo 模拟模型。"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, Float, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class PortfolioRebalancing(Base):
"""组合再平衡建议。"""
__tablename__ = "portfolio_rebalancings"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
tenant_id: Mapped[str] = mapped_column(String(36), ForeignKey("tenants.id"), nullable=False, index=True)
marginal_returns: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="各企业边际回报率")
reallocation_plan: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="再平衡方案")
irr_impact: Mapped[float | None] = mapped_column(Float, nullable=True, comment="IRR 影响")
dpi_impact: Mapped[float | None] = mapped_column(Float, nullable=True, comment="DPI 影响")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="proposed", comment="proposed/approved/executed")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
class MonteCarloSimulation(Base):
"""Monte Carlo 模拟结果。"""
__tablename__ = "monte_carlo_simulations"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
tenant_id: Mapped[str] = mapped_column(String(36), ForeignKey("tenants.id"), nullable=False, index=True)
iterations: Mapped[int] = mapped_column(nullable=False, default=10000, comment="模拟次数")
irr_distribution: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="IRR 概率分布")
dpi_distribution: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="DPI 概率分布")
percentile_p5: Mapped[float | None] = mapped_column(Float, nullable=True)
percentile_p50: Mapped[float | None] = mapped_column(Float, nullable=True)
percentile_p95: Mapped[float | None] = mapped_column(Float, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+42
View File
@@ -0,0 +1,42 @@
"""Pre-mortem + Red Team 模型。"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class PreMortemRecord(Base):
"""Pre-mortem 失败推演。"""
__tablename__ = "pre_mortem_records"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
decision_context: Mapped[str | None] = mapped_column(Text, nullable=True, comment="决策上下文")
failure_paths: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="失败路径列表")
risk_checklist: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="风险清单")
mitigations: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="缓解措施")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
class RedTeamRecord(Base):
"""Red Team 对抗分析。"""
__tablename__ = "red_team_records"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
perspective: Mapped[str] = mapped_column(String(50), nullable=False, comment="competitor/pessimistic_investor/devils_advocate")
analysis: Mapped[str | None] = mapped_column(Text, nullable=True, comment="对抗分析内容")
vulnerabilities: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="发现的漏洞")
counterarguments: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="反驳论点")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+30
View File
@@ -0,0 +1,30 @@
"""产品竞争力诊断模型。
AI 体验产品 + 竞品对比 + 热力图。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class ProductDiagnostic(Base):
"""产品竞争力诊断。"""
__tablename__ = "product_diagnostics"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
product_name: Mapped[str | None] = mapped_column(String(200), nullable=True)
dimensions: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="竞争力维度评分")
heatmap_data: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="热力图数据")
competitors: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="竞品对比")
roadmap_suggestions: Mapped[str | None] = mapped_column(Text, nullable=True, comment="路线图建议")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+79
View File
@@ -0,0 +1,79 @@
"""多主体画像模型。
投资机构、基金、投资经理画像。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class FirmProfile(Base):
"""投资机构画像。"""
__tablename__ = "firm_profiles"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
tenant_id: Mapped[str] = mapped_column(String(36), ForeignKey("tenants.id"), nullable=False, index=True)
name: Mapped[str] = mapped_column(String(200), nullable=False, comment="机构名称")
focus_areas: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="投资领域")
stage_preference: Mapped[str | None] = mapped_column(String(200), nullable=True, comment="阶段偏好")
description: Mapped[str | None] = mapped_column(Text, nullable=True)
extra_json: Mapped[dict | None] = mapped_column(JSONBType, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
class FundProfile(Base):
"""基金画像。"""
__tablename__ = "fund_profiles"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
firm_id: Mapped[str] = mapped_column(String(36), ForeignKey("firm_profiles.id"), nullable=False, index=True)
name: Mapped[str] = mapped_column(String(200), nullable=False, comment="基金名称")
fund_size: Mapped[str | None] = mapped_column(String(100), nullable=True, comment="基金规模")
vintage_year: Mapped[int | None] = mapped_column(nullable=True, comment="成立年份")
strategy: Mapped[str | None] = mapped_column(Text, nullable=True, comment="投资策略")
extra_json: Mapped[dict | None] = mapped_column(JSONBType, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
class ManagerProfile(Base):
"""投资经理画像。"""
__tablename__ = "manager_profiles"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
firm_id: Mapped[str] = mapped_column(String(36), ForeignKey("firm_profiles.id"), nullable=False, index=True)
user_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("users.id"), nullable=True)
name: Mapped[str] = mapped_column(String(100), nullable=False, comment="投资经理姓名")
focus_areas: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="关注领域")
portfolio_count: Mapped[int | None] = mapped_column(nullable=True, comment="在管企业数")
extra_json: Mapped[dict | None] = mapped_column(JSONBType, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+39
View File
@@ -0,0 +1,39 @@
"""协同机会模型。
Portfolio 内部协同匹配与效果追踪。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class SynergyOpportunity(Base):
"""协同机会。"""
__tablename__ = "synergy_opportunities"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
tenant_id: Mapped[str] = mapped_column(String(36), ForeignKey("tenants.id"), nullable=False, index=True)
type: Mapped[str] = mapped_column(String(50), nullable=False, comment="customer/talent/funding/supply_chain/tech")
company_a_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
company_b_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("companies.id"), nullable=True)
title: Mapped[str] = mapped_column(String(200), nullable=False)
description: Mapped[str | None] = mapped_column(Text, nullable=True)
match_reason: Mapped[str | None] = mapped_column(Text, nullable=True, comment="AI 匹配理由")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="discovered", comment="discovered/confirmed/authorized/executing/completed/declined")
authorized: Mapped[bool] = mapped_column(default=False, comment="双方是否授权")
effect_result: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="效果评估")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
+59
View File
@@ -0,0 +1,59 @@
"""人才模型。
核心人才画像 + 团队成员 + 9-Box 矩阵 + 流动预测。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class TalentProfile(Base):
"""人才画像。"""
__tablename__ = "talent_profiles"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
tenant_id: Mapped[str] = mapped_column(String(36), ForeignKey("tenants.id"), nullable=False, index=True)
name: Mapped[str] = mapped_column(String(100), nullable=False)
current_role: Mapped[str | None] = mapped_column(String(200), nullable=True, comment="当前职位")
current_company: Mapped[str | None] = mapped_column(String(200), nullable=True)
skills: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="技能标签")
experience_years: Mapped[int | None] = mapped_column(Integer, nullable=True)
performance_rating: Mapped[float | None] = mapped_column(nullable=True, comment="绩效评分(1-5")
potential_rating: Mapped[float | None] = mapped_column(nullable=True, comment="潜力评分(1-5")
nine_box: Mapped[str | None] = mapped_column(String(50), nullable=True, comment="9-Box 象限")
flow_prediction: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="流动预测")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="active", comment="active/flowed/inactive")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
class TeamMember(Base):
"""团队成员。"""
__tablename__ = "team_members"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
name: Mapped[str] = mapped_column(String(100), nullable=False)
role: Mapped[str | None] = mapped_column(String(200), nullable=True, comment="职位")
is_key_person: Mapped[bool] = mapped_column(default=False, comment="是否核心人员")
joined_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
left_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
stability_score: Mapped[float | None] = mapped_column(nullable=True, comment="稳定性评分(0-1")
extra_json: Mapped[dict | None] = mapped_column(JSONBType, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+57
View File
@@ -0,0 +1,57 @@
"""任务与评论模型。
投后任务管理 + 评论协作。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class Task(Base):
"""投后任务。"""
__tablename__ = "tasks"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
tenant_id: Mapped[str] = mapped_column(String(36), ForeignKey("tenants.id"), nullable=False, index=True)
company_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("companies.id"), nullable=True, index=True)
title: Mapped[str] = mapped_column(String(200), nullable=False)
description: Mapped[str | None] = mapped_column(Text, nullable=True)
status: Mapped[str] = mapped_column(String(20), nullable=False, default="todo", comment="todo/in_progress/done/cancelled")
priority: Mapped[str] = mapped_column(String(20), nullable=False, default="medium", comment="low/medium/high/urgent")
assigned_to: Mapped[str | None] = mapped_column(String(36), ForeignKey("users.id"), nullable=True)
source_type: Mapped[str | None] = mapped_column(String(50), nullable=True, comment="来源:risk/report/synergy/manual")
source_ref: Mapped[str | None] = mapped_column(String(36), nullable=True, comment="来源记录 ID")
due_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
class Comment(Base):
"""评论。"""
__tablename__ = "comments"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
tenant_id: Mapped[str] = mapped_column(String(36), ForeignKey("tenants.id"), nullable=False, index=True)
target_type: Mapped[str] = mapped_column(String(50), nullable=False, comment="report/risk/company/task")
target_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True, comment="目标记录 ID")
user_id: Mapped[str] = mapped_column(String(36), ForeignKey("users.id"), nullable=False)
content: Mapped[str] = mapped_column(Text, nullable=False)
parent_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("comments.id"), nullable=True, comment="父评论 ID")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
+36
View File
@@ -0,0 +1,36 @@
"""弱信号模型。
技术/情绪/组织/市场四类弱信号采集与关联。
"""
import uuid
from datetime import datetime, timezone
from sqlalchemy import DateTime, Float, ForeignKey, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
from app.core.types import JSONBType
class WeakSignal(Base):
"""弱信号。"""
__tablename__ = "weak_signals"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
company_id: Mapped[str] = mapped_column(String(36), ForeignKey("companies.id"), nullable=False, index=True)
signal_type: Mapped[str] = mapped_column(String(50), nullable=False, comment="technical/sentiment/org/market")
source: Mapped[str | None] = mapped_column(String(200), nullable=True, comment="信号来源")
content: Mapped[str] = mapped_column(Text, nullable=False, comment="信号内容")
confidence: Mapped[float] = mapped_column(Float, nullable=False, default=0.5, comment="置信度(0-1")
correlation_id: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True, comment="关联组 ID")
correlation_result: Mapped[dict | None] = mapped_column(JSONBType, nullable=True, comment="关联分析结果")
risk_probability: Mapped[float | None] = mapped_column(Float, nullable=True, comment="风险概率(0-1")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="new", comment="new/correlated/alerted/dismissed")
detected_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)