fix(dashboard): trends per-company lines instead of meaningless average

This commit is contained in:
selfrelease
2026-07-19 21:47:19 +08:00
parent 7b0b538b37
commit a24ccd01c7
2 changed files with 166 additions and 142 deletions
+27 -25
View File
@@ -166,50 +166,52 @@ async def get_health_heatmap(
@router.get("/trends", response_model=ApiResponse[list[dict]])
async def get_health_trends(
company_id: str | None = Query(default=None, description="指定企业 ID,不传则汇总"),
company_id: str | None = Query(default=None, description="指定企业 ID,不传则返回全部企业"),
months: int = Query(default=6, ge=1, le=24, description="趋势月数"),
db: AsyncSession = Depends(get_db),
user: User = Depends(get_current_user),
):
"""获取健康度趋势对比数据 — 按月汇总评分变化
"""获取健康度趋势数据 — 按企业分组,每家企业一条折线
返回格式:[{ period, avg_score, company_count, dimension_avgs: { dimension: avg } }]
返回格式:[{ company_id, company_name, data: [{ period, score }] }]
"""
query = (
select(HealthScore)
select(HealthScore, Company.name.label("company_name"))
.join(Company, HealthScore.company_id == Company.id)
.where(Company.tenant_id == user.tenant_id)
)
if company_id:
query = query.where(HealthScore.company_id == company_id)
query = query.order_by(HealthScore.calculated_at.desc()).limit(months * 50)
query = query.order_by(HealthScore.calculated_at.asc()).limit(months * 100)
result = await db.execute(query)
scores = result.scalars().all()
# 按分组
monthly: dict[str, list[HealthScore]] = {}
for s in scores:
period = s.calculated_at.strftime("%Y-%m")
monthly.setdefault(period, []).append(s)
# 按企业分组
by_company: dict[str, dict[str, list]] = {}
for row in result.all():
score = row[0]
cname = row[1]
cid = str(score.company_id)
if cid not in by_company:
by_company[cid] = {"company_name": cname, "scores": []}
by_company[cid]["scores"].append(score)
trends = []
for period in sorted(monthly.keys()):
month_scores = monthly[period]
count = len(month_scores)
avg_total = sum(s.total_score for s in month_scores) / count if count else 0
dim_avgs = {}
for dim_key in _DIMENSION_KEYS:
vals = [getattr(s, dim_key) for s in month_scores if getattr(s, dim_key) is not None]
if vals:
dim_avgs[dim_key] = round(sum(vals) / len(vals), 1)
for cid, info in by_company.items():
# 每月取最新一条
monthly: dict[str, float] = {}
for s in info["scores"]:
period = s.calculated_at.strftime("%Y-%m")
monthly[period] = s.total_score
data_points = [
{"period": p, "score": round(v, 1)}
for p, v in sorted(monthly.items())
]
trends.append({
"period": period,
"avg_score": round(avg_total, 1),
"company_count": count,
"dimension_avgs": dim_avgs,
"company_id": cid,
"company_name": info["company_name"],
"data": data_points,
})
return success(data=trends)