library-picturebook-activity/docs/design/org-admin/data-analytics-dashboard.md

252 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 租户端数据统计分析看板 — 设计方案
> 所属端:租户端(机构管理端)
> 状态:已实现(后端契约与租户过滤已对齐 [2026-04-09]
> 创建日期2026-03-31
> 最后更新2026-04-09
---
## 1. 需求背景
机构领导需要一个数据统计看板来了解:
- 活动运营情况:活动办得怎么样,报名和参赛情况
- 运营效率:审核速度、评审进度、整体运营时效
- 评委工作量:每位评委评了多少作品、评分质量
## 2. 数据来源盘点
基于现有系统已实现的功能,可用的数据表和字段:
| 数据表 | 可用维度 | 可用指标 |
|--------|----------|----------|
| t_contest | 活动名称、类型、状态(ongoing/finished)、发布状态、各时间节点 | 活动数量、阶段分布 |
| t_contest_registration | 活动ID、审核状态(pending/passed/rejected)、报名时间 | 报名数、通过率、时间分布 |
| t_contest_work | 活动ID、状态(submitted/reviewing/accepted/awarded)、提交时间、最终得分、排名、奖项 | 作品数、评审状态分布、得分分布、获奖分布 |
| t_contest_work_score | 作品ID、评委ID、分数、评分时间 | 评委评分量、评分时间分布 |
| t_contest_work_judge_assignment | 作品ID、评委ID、状态 | 分配完成率 |
| t_contest_judge | 活动ID、评委ID | 评委数量、评委-活动关联 |
| t_contest_notice | 活动ID、发布时间 | 公告数量 |
## 3. 看板设计
### 3.1 整体结构
```
┌──────────────────────────────────────────────────────────────┐
│ 数据统计 时间范围: [本月▾] [活动▾] │
├──────────────────────────────────────────────────────────────┤
│ │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │活动数│ │报名数│ │通过数│ │作品数│ │已评审│ │获奖数│ │
│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
│ │
│ ┌───── 报名转化漏斗 ─────┐ ┌────── 月度趋势 ──────────┐ │
│ │ 报名 → 通过 → 提交 │ │ 📈 报名量/作品量折线图 │ │
│ │ → 评审完成 → 获奖 │ │ │ │
│ └────────────────────────┘ └──────────────────────────┘ │
│ │
│ ┌───── 活动对比 ─────────────────────────────────────────┐ │
│ │ 表格:各活动 报名/通过率/作品提交率/评审完成率/获奖率 │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌──── 评委工作量 ────────┐ ┌────── 奖项分布 ──────────┐ │
│ │ 表格:评委 评审量/均分 │ │ 🥧 饼图:各奖项占比 │ │
│ └────────────────────────┘ └──────────────────────────┘ │
│ │
│ ┌──── 评审效率 ──────────────────────────────────────────┐ │
│ │ 平均评审周期 │ 日均评审量 │ 待评审积压 │ 评分标准差 │ │
│ └───────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
```
### 3.2 模块详细设计
#### 模块A核心指标卡片顶部
6 个数字卡片,一行排列:
| 指标 | 数据来源 | 计算方式 |
|------|----------|----------|
| 活动总数 | t_contest | COUNT WHERE tenant 可见 |
| 累计报名 | t_contest_registration | COUNT WHERE tenant_id |
| 报名通过 | t_contest_registration | COUNT WHERE registration_state='passed' |
| 作品总数 | t_contest_work | COUNT WHERE valid_state=1 |
| 已完成评审 | t_contest_work | COUNT WHERE status IN ('accepted','awarded') |
| 获奖作品 | t_contest_work | COUNT WHERE award_level IS NOT NULL AND award_level != 'none' |
#### 模块B报名转化漏斗
展示从报名到获奖的转化路径和各环节转化率:
```
报名人数 (12) → 通过审核 (10) → 提交作品 (8) → 评审完成 (5) → 获奖 (3)
83.3% 80.0% 62.5% 60.0%
```
数据来源:
- 报名人数registration COUNT
- 通过审核registration COUNT WHERE state='passed'
- 提交作品work COUNT WHERE valid_state=1
- 评审完成work COUNT WHERE status IN ('accepted','awarded')
- 获奖work COUNT WHERE award_name IS NOT NULL
#### 模块C月度趋势图
折线图X轴为月份Y轴双轴
- 左轴:报名数量(按 registration_time 月份分组)
- 右轴:作品数量(按 submit_time 月份分组)
时间范围最近6个月
数据来源:
```sql
-- 月度报名
SELECT DATE_FORMAT(registration_time, '%Y-%m') as month, COUNT(*)
FROM t_contest_registration WHERE tenant_id=?
GROUP BY month ORDER BY month
-- 月度作品
SELECT DATE_FORMAT(submit_time, '%Y-%m') as month, COUNT(*)
FROM t_contest_work WHERE tenant_id=? AND valid_state=1
GROUP BY month ORDER BY month
```
#### 模块D活动对比表
表格形式,每行一个活动:
| 列 | 数据来源 |
|----|----------|
| 活动名称 | t_contest.contest_name |
| 报名数 | registration COUNT |
| 通过率 | passed COUNT / total COUNT × 100% |
| 作品提交率 | work COUNT / passed registration COUNT × 100% |
| 评审完成率 | (accepted+awarded) COUNT / work COUNT × 100% |
| 获奖率 | awarded COUNT / work COUNT × 100% |
| 平均得分 | AVG(final_score) |
#### 模块E评委工作量
表格形式,每行一个评委:
| 列 | 数据来源 |
|----|----------|
| 评委姓名 | users.nickname via t_contest_judge |
| 关联活动数 | t_contest_judge COUNT DISTINCT contest_id |
| 已分配作品数 | t_contest_work_judge_assignment COUNT |
| 已评分作品数 | t_contest_work_score COUNT |
| 评分完成率 | scored / assigned × 100% |
| 平均打分 | AVG(total_score) |
| 评分标准差 | STDDEV(total_score)(衡量评分一致性,越小越一致) |
#### 模块F奖项分布
饼图/环形图,展示获奖作品中各奖项的占比:
数据来源:
```sql
SELECT award_name, COUNT(*)
FROM t_contest_work
WHERE tenant_id=? AND award_name IS NOT NULL AND valid_state=1
GROUP BY award_name
```
#### 模块G评审效率指标
4 个数字卡片:
| 指标 | 计算方式 |
|------|----------|
| 平均评审周期 | AVG(score_time - submit_time),从作品提交到第一次评分的平均天数 |
| 日均评审量 | 最近30天 score COUNT / 30 |
| 待评审积压 | assignment COUNT WHERE status='assigned'(已分配未评分) |
| 评分一致性 | 所有作品的评委间评分标准差的平均值(越小越好) |
### 3.3 筛选条件
顶部全局筛选栏:
| 筛选 | 类型 | 说明 |
|------|------|------|
| 时间范围 | 下拉 | 本月/本季度/本年/全部/自定义时间段 |
| 指定活动 | 下拉 | 全部活动 / 选择特定活动(切换后所有模块联动) |
### 3.4 交互设计
- 数字卡片可点击,跳转到对应管理页面(如点击「累计报名」跳到报名管理)
- 活动对比表的活动名称可点击,切换筛选到该活动
- 评委工作量表的评委名可点击查看评分明细
- 所有图表支持 hover 显示详细数据
- 支持将看板数据导出为 PDF/Excel
## 4. 菜单位置
新增一级菜单「数据统计」,放在「活动管理」之后:
```
工作台
活动管理
├── ...
数据统计(新增)
├── 运营概览 — 核心卡片 + 漏斗 + 趋势 + 活动对比
└── 评审分析 — 评委工作量 + 评审效率 + 奖项分布
系统设置
├── ...
```
## 5. 后端 API 设计
上下文路径以部署为准(开发环境一般为 `/api`)。实现类:`AnalyticsController` / `AnalyticsService` / `AnalyticsMapper`
**多租户**:非超级租户时,活动范围由 `t_biz_contest.contest_tenants`JSON 授权)限定;报名/作品/评分等子表再按 `tenant_id` 过滤。超级租户不按 `contest_tenants` 限活动。
### 5.1 运营概览
```
GET /analytics/overview
参数:
timeRange: 可选。month | quarter | year不传或 all 表示不限时间。
作用于 summary、funnel、contestComparison 的时间过滤(报名按 registration_time作品按 submit_time
contestId: 可选。指定单个活动;须属于当前租户可见活动。
返回:
{
summary: { totalContests, totalRegistrations, passedRegistrations, totalWorks, reviewedWorks, awardedWorks },
funnel: { registered, passed, submitted, reviewed, awarded }, // 对象,非数组
monthlyTrend: [{ month: 'YYYY-MM', registrations, works }], // 最近 6 个自然月,与 timeRange 独立
contestComparison: [{
contestId, contestName,
registrations, passRate, submitRate, reviewRate, awardRate, avgScore
}]
}
```
指标口径简述:`reviewedWorks` / 漏斗 `reviewed` 为作品 `status IN ('accepted','awarded')``awardedWorks` 为 `award_level` 非空且不为 `none`
### 5.2 评审分析
```
GET /analytics/review
参数:
contestId: 可选,同上。
timeRange: 可传(与前端下拉一致);当前实现中评审分析各模块为「可见活动」全量统计,该参数预留,不参与过滤。
返回:
{
efficiency: { avgReviewDays, dailyReviewCount, pendingAssignments, avgScoreStddev },
judgeWorkload: [{
judgeId, judgeName,
contestCount, assignedCount, scoredCount, completionRate, avgScore, scoreStddev
}],
awardDistribution: [{ awardName, count, percentage }]
}
```
`efficiency``avgReviewDays` 为作品提交至首次评分的平均天数;`dailyReviewCount` 为近 30 天评分条数 / 30`pendingAssignments` 为分配状态 `assigned` 的条数;`avgScoreStddev` 为「多评委作品」分数标准差再对作品取平均。
## 6. 技术方案
- 前端图表库:使用 ECharts 或 Ant Design Charts@ant-design/charts
- 数据缓存:统计数据变化不频繁,后端可加 5 分钟缓存
- 大数据量:月度趋势等聚合查询用 GROUP BY + 索引优化
- 导出:前端生成 PDFhtml2canvas + jsPDF或 CSV