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:
@@ -11,10 +11,24 @@ from app.models.user import User
|
||||
from app.schemas.common import ApiResponse, success
|
||||
from app.schemas.company import (
|
||||
CompanyCreate,
|
||||
CompanyDetailResponse,
|
||||
CompanyListResponse,
|
||||
CompanyResponse,
|
||||
CompanyUpdate,
|
||||
AgreementBrief,
|
||||
BoardMeetingBrief,
|
||||
HealthScoreBrief,
|
||||
ReportBrief,
|
||||
RiskBrief,
|
||||
WeakSignalBrief,
|
||||
)
|
||||
from app.models.agreement import InvestmentAgreement
|
||||
from app.models.board import BoardMeeting
|
||||
from app.models.financial_data import FinancialData
|
||||
from app.models.health_score import HealthScore
|
||||
from app.models.report import MonthlyReport
|
||||
from app.models.risk import RiskEvent
|
||||
from app.models.weak_signal import WeakSignal
|
||||
|
||||
router = APIRouter(prefix="/companies", tags=["companies"])
|
||||
|
||||
@@ -76,6 +90,153 @@ async def get_company(
|
||||
return success(data=CompanyResponse.model_validate(company, from_attributes=True))
|
||||
|
||||
|
||||
@router.get("/{company_id}/detail", response_model=ApiResponse[CompanyDetailResponse])
|
||||
async def get_company_detail(
|
||||
company_id: str,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
user: User = Depends(get_current_user),
|
||||
):
|
||||
"""获取企业详情聚合数据 — 工作台使用。
|
||||
|
||||
聚合:企业基本信息 + 最新健康度 + 最近月报 + 未解决风险 + 弱信号 + 活跃协议 + 董事会会议 + 财务数据。
|
||||
"""
|
||||
# 企业基本信息
|
||||
result = await db.execute(
|
||||
select(Company).where(Company.id == company_id, Company.tenant_id == user.tenant_id)
|
||||
)
|
||||
company = result.scalar_one_or_none()
|
||||
if not company:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="企业不存在")
|
||||
|
||||
# 最新健康度评分
|
||||
health_result = await db.execute(
|
||||
select(HealthScore)
|
||||
.where(HealthScore.company_id == company_id)
|
||||
.order_by(HealthScore.calculated_at.desc())
|
||||
.limit(1)
|
||||
)
|
||||
health = health_result.scalar_one_or_none()
|
||||
health_brief = HealthScoreBrief(
|
||||
total_score=health.total_score,
|
||||
financial_score=health.financial_score,
|
||||
operational_score=health.operational_score,
|
||||
ai_commercial_score=health.ai_commercial_score,
|
||||
ai_cost_score=health.ai_cost_score,
|
||||
org_talent_score=getattr(health, "org_talent_score", None),
|
||||
product_tech_score=getattr(health, "product_tech_score", None),
|
||||
market_compete_score=getattr(health, "market_compete_score", None),
|
||||
governance_score=getattr(health, "governance_score", None),
|
||||
financing_score=getattr(health, "financing_score", None),
|
||||
synergy_score=getattr(health, "synergy_score", None),
|
||||
ai_model_product_score=getattr(health, "ai_model_product_score", None),
|
||||
data_compliance_score=getattr(health, "data_compliance_score", None),
|
||||
team_tech_score=getattr(health, "team_tech_score", None),
|
||||
customer_success_score=getattr(health, "customer_success_score", None),
|
||||
trend=health.trend,
|
||||
calculated_at=health.calculated_at,
|
||||
) if health else None
|
||||
|
||||
# 最近 5 条月报
|
||||
reports_result = await db.execute(
|
||||
select(MonthlyReport)
|
||||
.where(MonthlyReport.company_id == company_id)
|
||||
.order_by(MonthlyReport.period_year.desc(), MonthlyReport.period_month.desc())
|
||||
.limit(5)
|
||||
)
|
||||
reports = reports_result.scalars().all()
|
||||
report_briefs = [
|
||||
ReportBrief(
|
||||
id=r.id, period_year=r.period_year, period_month=r.period_month,
|
||||
status=r.status, ai_summary=r.ai_summary, submitted_at=r.submitted_at,
|
||||
) for r in reports
|
||||
]
|
||||
|
||||
# 未解决风险
|
||||
risks_result = await db.execute(
|
||||
select(RiskEvent)
|
||||
.where(RiskEvent.company_id == company_id, RiskEvent.status.in_(["open", "assigned", "in_progress"]))
|
||||
.order_by(RiskEvent.identified_at.desc())
|
||||
.limit(10)
|
||||
)
|
||||
risks = risks_result.scalars().all()
|
||||
risk_briefs = [
|
||||
RiskBrief(
|
||||
id=r.id, type=r.type, severity=r.severity, status=r.status,
|
||||
title=r.title, identified_at=r.identified_at,
|
||||
) for r in risks
|
||||
]
|
||||
|
||||
# 最近弱信号
|
||||
signals_result = await db.execute(
|
||||
select(WeakSignal)
|
||||
.where(WeakSignal.company_id == company_id)
|
||||
.order_by(WeakSignal.detected_at.desc())
|
||||
.limit(10)
|
||||
)
|
||||
signals = signals_result.scalars().all()
|
||||
signal_briefs = [
|
||||
WeakSignalBrief(
|
||||
id=s.id, signal_type=s.signal_type, content=s.content,
|
||||
confidence=s.confidence, risk_probability=s.risk_probability,
|
||||
status=s.status, detected_at=s.detected_at,
|
||||
) for s in signals
|
||||
]
|
||||
|
||||
# 活跃协议
|
||||
agreements_result = await db.execute(
|
||||
select(InvestmentAgreement)
|
||||
.where(InvestmentAgreement.company_id == company_id, InvestmentAgreement.status == "active")
|
||||
.order_by(InvestmentAgreement.created_at.desc())
|
||||
)
|
||||
agreements = agreements_result.scalars().all()
|
||||
agreement_briefs = [
|
||||
AgreementBrief(id=a.id, title=a.title, status=a.status, signed_at=a.signed_at)
|
||||
for a in agreements
|
||||
]
|
||||
|
||||
# 最近董事会会议
|
||||
board_result = await db.execute(
|
||||
select(BoardMeeting)
|
||||
.where(BoardMeeting.company_id == company_id)
|
||||
.order_by(BoardMeeting.created_at.desc())
|
||||
.limit(5)
|
||||
)
|
||||
meetings = board_result.scalars().all()
|
||||
meeting_briefs = [
|
||||
BoardMeetingBrief(id=m.id, title=m.title, status=m.status, meeting_at=m.meeting_at)
|
||||
for m in meetings
|
||||
]
|
||||
|
||||
# 财务数据统计
|
||||
fin_count_result = await db.execute(
|
||||
select(func.count()).select_from(
|
||||
select(FinancialData).where(FinancialData.company_id == company_id).subquery()
|
||||
)
|
||||
)
|
||||
fin_count = fin_count_result.scalar_one()
|
||||
|
||||
latest_fin_result = await db.execute(
|
||||
select(FinancialData)
|
||||
.where(FinancialData.company_id == company_id)
|
||||
.order_by(FinancialData.period_year.desc(), FinancialData.period_month.desc())
|
||||
.limit(1)
|
||||
)
|
||||
latest_fin = latest_fin_result.scalar_one_or_none()
|
||||
latest_financial = latest_fin.data_json if latest_fin else None
|
||||
|
||||
return success(data=CompanyDetailResponse(
|
||||
company=CompanyResponse.model_validate(company, from_attributes=True),
|
||||
health_score=health_brief,
|
||||
recent_reports=report_briefs,
|
||||
open_risks=risk_briefs,
|
||||
recent_weak_signals=signal_briefs,
|
||||
active_agreements=agreement_briefs,
|
||||
recent_board_meetings=meeting_briefs,
|
||||
financial_data_count=fin_count,
|
||||
latest_financial=latest_financial,
|
||||
))
|
||||
|
||||
|
||||
@router.post("", response_model=ApiResponse[CompanyResponse], status_code=status.HTTP_201_CREATED)
|
||||
async def create_company(
|
||||
req: CompanyCreate,
|
||||
|
||||
Reference in New Issue
Block a user