library-picturebook-activity/docs/design/org-admin/analytics-dashboard-mockup.html
aid 9215465bd5 Day5: 租户端全面优化 + 数据统计看板 + 成果发布完善
租户端基础设施:
- 新增工作台首页(欢迎信息/统计/待办/快捷操作/新手引导)
- 新增机构信息管理页(自助查看编辑机构信息)
- 修复403报错(fetchTenants加超管守卫)
- 修复权限(log:read/notice:update/notice:delete/contest:work:read)
- 修复评审规则组件映射

活动管理全模块优化(机构端视角):
- 活动列表:加统计概览+精简列+筛选自动查询+发布弹窗修复+操作逻辑优化
- 创建/编辑活动:重构布局(去card嵌套+栅格响应式+分区卡片)
- 评委管理:统一主色调+冻结确认+导入导出disabled
- 报名管理:去Tab+统计+审核状态列+批量审核接口
- 报名记录:统计概览+去机构列+撤销审核+返回按钮+去参与方式列
- 作品管理:去Tab+统计+递交进度彩色+筛选修复(assignStatus/submitTime)
- 评审进度:去Tab+统计+实际完成率状态+筛选修复
- 评审规则:表格加评委数/计算方式+描述列修复+删除保护
- 成果发布:去Tab+统计+操作文案优化
- 通知公告:统一主色调+发布确认+操作逻辑+状态筛选+时间范围

成果发布详情功能补全:
- 计算得分/排名/设置奖项三步操作流程
- 排名列(金银铜徽章)+奖项列+奖项筛选
- 自定义奖项(动态添加行替代硬编码一二三等奖)
- 后端AutoSetAwardsDto改为awards数组格式

数据统计看板(新模块):
- 后端analytics module(overview+review两个接口)
- 运营概览:6指标卡片+报名转化漏斗+ECharts月度趋势+活动对比表
- 评审分析:4效率卡片+评委工作量表+ECharts奖项分布饼图
- 菜单注册:数据统计→运营概览+评审分析

Bug修复:
- 超管重置其他租户用户密码报"用户不存在"
- gdlib登录快捷标签密码不一致
- 分配评委去掉评审时间限制

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 20:02:24 +08:00

446 lines
28 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据统计 — 活动管理平台</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,500;0,9..40,700;1,9..40,400&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: { 50: '#eef2ff', 100: '#e0e7ff', 200: '#c7d2fe', 300: '#a5b4fc', 400: '#818cf8', 500: '#6366f1', 600: '#4f46e5', 700: '#4338ca' },
surface: '#f8f7fc',
card: '#ffffff',
},
fontFamily: {
display: ['"DM Sans"', '"Noto Sans SC"', 'system-ui'],
body: ['"Noto Sans SC"', '"DM Sans"', 'system-ui'],
mono: ['"DM Sans"', 'monospace'],
},
borderRadius: { 'card': '12px' },
boxShadow: {
'card': '0 2px 12px rgba(0,0,0,0.06)',
'card-hover': '0 8px 24px rgba(99,102,241,0.12)',
}
}
}
}
</script>
<style>
body { background: #f8f7fc; }
.tab-active { color: #6366f1; border-bottom: 2px solid #6366f1; font-weight: 700; }
.tab-inactive { color: #9ca3af; border-bottom: 2px solid transparent; }
.tab-inactive:hover { color: #6b7280; }
.stat-card { transition: all 0.25s cubic-bezier(0.4,0,0.2,1); }
.stat-card:hover { transform: translateY(-3px); box-shadow: 0 8px 24px rgba(99,102,241,0.12); }
.funnel-bar { transition: width 0.8s cubic-bezier(0.4,0,0.2,1); }
.fade-in { animation: fadeIn 0.5s ease both; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
.stagger-1 { animation-delay: 0.05s; }
.stagger-2 { animation-delay: 0.1s; }
.stagger-3 { animation-delay: 0.15s; }
.stagger-4 { animation-delay: 0.2s; }
.stagger-5 { animation-delay: 0.25s; }
.stagger-6 { animation-delay: 0.3s; }
table th { font-weight: 600; font-size: 13px; color: #6b7280; text-transform: uppercase; letter-spacing: 0.03em; }
table td { font-size: 14px; }
.rate-pill { display: inline-flex; padding: 2px 10px; border-radius: 20px; font-size: 12px; font-weight: 600; }
select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 5l3 3 3-3' fill='none' stroke='%239ca3af' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 12px center; padding-right: 32px; }
</style>
</head>
<body class="font-body text-gray-800 min-h-screen">
<!-- Header -->
<div class="max-w-[1280px] mx-auto px-6 pt-6">
<!-- Title -->
<div class="bg-white rounded-card shadow-card px-6 py-4 mb-5 flex items-center justify-between">
<h1 class="text-xl font-display font-bold text-gray-900 tracking-tight">数据统计</h1>
<div class="flex items-center gap-3">
<button onclick="exportPDF()" class="flex items-center gap-2 px-4 py-2 rounded-lg border border-gray-200 text-sm font-medium text-gray-600 hover:bg-gray-50 transition">
<svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path d="M12 16V4m0 12l-4-4m4 4l4-4M4 20h16"/></svg>
导出 PDF
</button>
<button onclick="exportExcel()" class="flex items-center gap-2 px-4 py-2 rounded-lg border border-gray-200 text-sm font-medium text-gray-600 hover:bg-gray-50 transition">
<svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path d="M9 17H5a2 2 0 01-2-2V5a2 2 0 012-2h4m6 0h4a2 2 0 012 2v10a2 2 0 01-2 2h-4m-6-8l6 6m0-6l-6 6"/></svg>
导出 Excel
</button>
</div>
</div>
<!-- Tabs + Filters -->
<div class="bg-white rounded-card shadow-card px-6 py-0 mb-5 flex items-center justify-between">
<div class="flex gap-6">
<button id="tab-overview" onclick="switchTab('overview')" class="tab-active py-4 text-sm font-display cursor-pointer transition-colors">运营概览</button>
<button id="tab-review" onclick="switchTab('review')" class="tab-inactive py-4 text-sm font-display cursor-pointer transition-colors">评审分析</button>
</div>
<div class="flex items-center gap-3">
<select class="text-sm border border-gray-200 rounded-lg px-3 py-2 bg-white text-gray-700 font-medium focus:outline-none focus:ring-2 focus:ring-primary-200">
<option>本月</option><option>本季度</option><option>本年</option><option>全部</option>
</select>
<select class="text-sm border border-gray-200 rounded-lg px-3 py-2 bg-white text-gray-700 font-medium focus:outline-none focus:ring-2 focus:ring-primary-200">
<option>全部活动</option><option>2026年少儿绘本创作大赛</option><option>第三届亲子阅读绘画展</option><option>寒假绘本阅读打卡活动</option>
</select>
</div>
</div>
<!-- Tab Content: Overview -->
<div id="content-overview">
<!-- Stat Cards -->
<div class="grid grid-cols-6 gap-4 mb-5">
<div class="stat-card fade-in stagger-1 bg-white rounded-card shadow-card p-4 cursor-pointer">
<div class="flex items-center gap-3">
<div class="w-10 h-10 rounded-xl flex items-center justify-center text-lg" style="background:rgba(99,102,241,0.1);color:#6366f1">
<svg width="20" height="20" fill="currentColor" viewBox="0 0 20 20"><path d="M6 2a2 2 0 00-2 2v12a2 2 0 002 2h8a2 2 0 002-2V7.414A2 2 0 0015.414 6L12 2.586A2 2 0 0010.586 2H6z"/></svg>
</div>
<div>
<div class="text-2xl font-display font-bold text-gray-900 leading-none">6</div>
<div class="text-xs text-gray-400 mt-0.5">活动总数</div>
</div>
</div>
</div>
<div class="stat-card fade-in stagger-2 bg-white rounded-card shadow-card p-4 cursor-pointer">
<div class="flex items-center gap-3">
<div class="w-10 h-10 rounded-xl flex items-center justify-center" style="background:rgba(59,130,246,0.1);color:#3b82f6">
<svg width="20" height="20" fill="currentColor" viewBox="0 0 20 20"><path d="M9 6a3 3 0 11-6 0 3 3 0 016 0zM17 6a3 3 0 11-6 0 3 3 0 016 0zM12.93 17c.046-.327.07-.66.07-1a6.97 6.97 0 00-1.5-4.33A5 5 0 0119 16v1h-6.07zM6 11a5 5 0 015 5v1H1v-1a5 5 0 015-5z"/></svg>
</div>
<div>
<div class="text-2xl font-display font-bold text-gray-900 leading-none">12</div>
<div class="text-xs text-gray-400 mt-0.5">累计报名</div>
</div>
</div>
</div>
<div class="stat-card fade-in stagger-3 bg-white rounded-card shadow-card p-4 cursor-pointer">
<div class="flex items-center gap-3">
<div class="w-10 h-10 rounded-xl flex items-center justify-center" style="background:rgba(16,185,129,0.1);color:#10b981">
<svg width="20" height="20" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg>
</div>
<div>
<div class="text-2xl font-display font-bold text-gray-900 leading-none">10</div>
<div class="text-xs text-gray-400 mt-0.5">报名通过</div>
</div>
</div>
</div>
<div class="stat-card fade-in stagger-4 bg-white rounded-card shadow-card p-4 cursor-pointer">
<div class="flex items-center gap-3">
<div class="w-10 h-10 rounded-xl flex items-center justify-center" style="background:rgba(245,158,11,0.1);color:#f59e0b">
<svg width="20" height="20" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M4 3a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4zm12 12H4l4-8 3 6 2-4 3 6z" clip-rule="evenodd"/></svg>
</div>
<div>
<div class="text-2xl font-display font-bold text-gray-900 leading-none">8</div>
<div class="text-xs text-gray-400 mt-0.5">作品总数</div>
</div>
</div>
</div>
<div class="stat-card fade-in stagger-5 bg-white rounded-card shadow-card p-4 cursor-pointer">
<div class="flex items-center gap-3">
<div class="w-10 h-10 rounded-xl flex items-center justify-center" style="background:rgba(20,184,166,0.1);color:#14b8a6">
<svg width="20" height="20" fill="currentColor" viewBox="0 0 20 20"><path d="M9 2a1 1 0 000 2h2a1 1 0 100-2H9z"/><path fill-rule="evenodd" d="M4 5a2 2 0 012-2 3 3 0 003 3h2a3 3 0 003-3 2 2 0 012 2v11a2 2 0 01-2 2H6a2 2 0 01-2-2V5zm9.707 5.707a1 1 0 00-1.414-1.414L9 12.586l-1.293-1.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg>
</div>
<div>
<div class="text-2xl font-display font-bold text-gray-900 leading-none">5</div>
<div class="text-xs text-gray-400 mt-0.5">已完成评审</div>
</div>
</div>
</div>
<div class="stat-card fade-in stagger-6 bg-white rounded-card shadow-card p-4 cursor-pointer">
<div class="flex items-center gap-3">
<div class="w-10 h-10 rounded-xl flex items-center justify-center" style="background:rgba(239,68,68,0.1);color:#ef4444">
<svg width="20" height="20" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5 2a2 2 0 00-2 2v14l3.5-2 3.5 2 3.5-2 3.5 2V4a2 2 0 00-2-2H5zm2.5 3a1.5 1.5 0 100 3 1.5 1.5 0 000-3zm6.207.293a1 1 0 00-1.414 0l-6 6a1 1 0 101.414 1.414l6-6a1 1 0 000-1.414zM12.5 10a1.5 1.5 0 100 3 1.5 1.5 0 000-3z" clip-rule="evenodd"/></svg>
</div>
<div>
<div class="text-2xl font-display font-bold text-gray-900 leading-none">3</div>
<div class="text-xs text-gray-400 mt-0.5">获奖作品</div>
</div>
</div>
</div>
</div>
<!-- Funnel + Trend -->
<div class="grid grid-cols-2 gap-5 mb-5">
<!-- Funnel -->
<div class="bg-white rounded-card shadow-card p-6 fade-in" style="animation-delay:0.35s">
<h3 class="text-sm font-display font-bold text-gray-900 mb-5 tracking-tight">报名转化漏斗</h3>
<div class="space-y-3">
<div>
<div class="flex items-center justify-between mb-1.5">
<span class="text-sm font-medium text-gray-700">报名</span>
<span class="text-sm font-display font-bold text-gray-900">12</span>
</div>
<div class="h-8 bg-gray-100 rounded-lg overflow-hidden"><div class="funnel-bar h-full rounded-lg" style="width:100%;background:linear-gradient(90deg,#6366f1,#818cf8)"></div></div>
</div>
<div>
<div class="flex items-center justify-between mb-1.5">
<span class="text-sm font-medium text-gray-700">通过审核</span>
<div class="flex items-center gap-2"><span class="rate-pill bg-green-50 text-green-600">83.3%</span><span class="text-sm font-display font-bold text-gray-900">10</span></div>
</div>
<div class="h-8 bg-gray-100 rounded-lg overflow-hidden"><div class="funnel-bar h-full rounded-lg" style="width:83.3%;background:linear-gradient(90deg,#10b981,#34d399)"></div></div>
</div>
<div>
<div class="flex items-center justify-between mb-1.5">
<span class="text-sm font-medium text-gray-700">提交作品</span>
<div class="flex items-center gap-2"><span class="rate-pill bg-blue-50 text-blue-600">80.0%</span><span class="text-sm font-display font-bold text-gray-900">8</span></div>
</div>
<div class="h-8 bg-gray-100 rounded-lg overflow-hidden"><div class="funnel-bar h-full rounded-lg" style="width:66.7%;background:linear-gradient(90deg,#3b82f6,#60a5fa)"></div></div>
</div>
<div>
<div class="flex items-center justify-between mb-1.5">
<span class="text-sm font-medium text-gray-700">评审完成</span>
<div class="flex items-center gap-2"><span class="rate-pill bg-amber-50 text-amber-600">62.5%</span><span class="text-sm font-display font-bold text-gray-900">5</span></div>
</div>
<div class="h-8 bg-gray-100 rounded-lg overflow-hidden"><div class="funnel-bar h-full rounded-lg" style="width:41.7%;background:linear-gradient(90deg,#f59e0b,#fbbf24)"></div></div>
</div>
<div>
<div class="flex items-center justify-between mb-1.5">
<span class="text-sm font-medium text-gray-700">获奖</span>
<div class="flex items-center gap-2"><span class="rate-pill bg-red-50 text-red-500">60.0%</span><span class="text-sm font-display font-bold text-gray-900">3</span></div>
</div>
<div class="h-8 bg-gray-100 rounded-lg overflow-hidden"><div class="funnel-bar h-full rounded-lg" style="width:25%;background:linear-gradient(90deg,#ef4444,#f87171)"></div></div>
</div>
</div>
</div>
<!-- Trend Chart -->
<div class="bg-white rounded-card shadow-card p-6 fade-in" style="animation-delay:0.4s">
<h3 class="text-sm font-display font-bold text-gray-900 mb-4 tracking-tight">月度趋势</h3>
<div id="trendChart" style="height:280px"></div>
</div>
</div>
<!-- Contest Comparison Table -->
<div class="bg-white rounded-card shadow-card p-6 fade-in" style="animation-delay:0.45s">
<h3 class="text-sm font-display font-bold text-gray-900 mb-4 tracking-tight">活动对比</h3>
<div class="overflow-x-auto">
<table class="w-full text-left">
<thead>
<tr class="border-b border-gray-100">
<th class="py-3 px-4">活动名称</th>
<th class="py-3 px-4 text-center">报名数</th>
<th class="py-3 px-4 text-center">通过率</th>
<th class="py-3 px-4 text-center">提交率</th>
<th class="py-3 px-4 text-center">评审完成率</th>
<th class="py-3 px-4 text-center">获奖率</th>
<th class="py-3 px-4 text-center">平均分</th>
</tr>
</thead>
<tbody>
<tr class="border-b border-gray-50 hover:bg-primary-50/30 transition-colors">
<td class="py-3.5 px-4 font-medium text-gray-900">2026年少儿绘本创作大赛</td>
<td class="py-3.5 px-4 text-center font-display font-bold">5</td>
<td class="py-3.5 px-4 text-center"><span class="rate-pill bg-amber-50 text-amber-600">60%</span></td>
<td class="py-3.5 px-4 text-center"><span class="rate-pill bg-green-50 text-green-600">100%</span></td>
<td class="py-3.5 px-4 text-center"><span class="rate-pill bg-green-50 text-green-600">100%</span></td>
<td class="py-3.5 px-4 text-center"><span class="rate-pill bg-green-50 text-green-600">100%</span></td>
<td class="py-3.5 px-4 text-center font-display font-bold text-primary-500">84.89</td>
</tr>
<tr class="border-b border-gray-50 hover:bg-primary-50/30 transition-colors">
<td class="py-3.5 px-4 font-medium text-gray-900">第三届亲子阅读绘画展</td>
<td class="py-3.5 px-4 text-center font-display font-bold">4</td>
<td class="py-3.5 px-4 text-center"><span class="rate-pill bg-green-50 text-green-600">100%</span></td>
<td class="py-3.5 px-4 text-center"><span class="rate-pill bg-amber-50 text-amber-600">75%</span></td>
<td class="py-3.5 px-4 text-center"><span class="rate-pill bg-gray-100 text-gray-400">0%</span></td>
<td class="py-3.5 px-4 text-center"><span class="rate-pill bg-gray-100 text-gray-400">0%</span></td>
<td class="py-3.5 px-4 text-center text-gray-300">-</td>
</tr>
<tr class="hover:bg-primary-50/30 transition-colors">
<td class="py-3.5 px-4 font-medium text-gray-900">寒假绘本阅读打卡活动</td>
<td class="py-3.5 px-4 text-center font-display font-bold">3</td>
<td class="py-3.5 px-4 text-center"><span class="rate-pill bg-green-50 text-green-600">100%</span></td>
<td class="py-3.5 px-4 text-center"><span class="rate-pill bg-amber-50 text-amber-600">67%</span></td>
<td class="py-3.5 px-4 text-center"><span class="rate-pill bg-green-50 text-green-600">100%</span></td>
<td class="py-3.5 px-4 text-center"><span class="rate-pill bg-gray-100 text-gray-400">0%</span></td>
<td class="py-3.5 px-4 text-center font-display font-bold text-primary-500">85.33</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- Tab Content: Review Analysis -->
<div id="content-review" class="hidden">
<!-- Review Efficiency Cards -->
<div class="grid grid-cols-4 gap-4 mb-5">
<div class="stat-card fade-in stagger-1 bg-white rounded-card shadow-card p-5">
<div class="flex items-center gap-3">
<div class="w-11 h-11 rounded-xl flex items-center justify-center" style="background:rgba(59,130,246,0.1);color:#3b82f6">
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
</div>
<div>
<div class="text-2xl font-display font-bold text-gray-900 leading-none">3.2<span class="text-sm font-normal text-gray-400 ml-0.5"></span></div>
<div class="text-xs text-gray-400 mt-1">平均评审周期</div>
</div>
</div>
</div>
<div class="stat-card fade-in stagger-2 bg-white rounded-card shadow-card p-5">
<div class="flex items-center gap-3">
<div class="w-11 h-11 rounded-xl flex items-center justify-center" style="background:rgba(16,185,129,0.1);color:#10b981">
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>
</div>
<div>
<div class="text-2xl font-display font-bold text-gray-900 leading-none">1.5<span class="text-sm font-normal text-gray-400 ml-0.5">个/日</span></div>
<div class="text-xs text-gray-400 mt-1">日均评审量</div>
</div>
</div>
</div>
<div class="stat-card fade-in stagger-3 bg-white rounded-card shadow-card p-5">
<div class="flex items-center gap-3">
<div class="w-11 h-11 rounded-xl flex items-center justify-center" style="background:rgba(239,68,68,0.1);color:#ef4444">
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path d="M12 9v2m0 4h.01M5.07 19H19a2.18 2.18 0 001.9-3.2L13.9 4a2.18 2.18 0 00-3.8 0L3.17 15.8A2.18 2.18 0 005.07 19z"/></svg>
</div>
<div>
<div class="text-2xl font-display font-bold text-gray-900 leading-none">2<span class="text-sm font-normal text-gray-400 ml-0.5"></span></div>
<div class="text-xs text-gray-400 mt-1">待评审积压</div>
</div>
</div>
</div>
<div class="stat-card fade-in stagger-4 bg-white rounded-card shadow-card p-5">
<div class="flex items-center gap-3">
<div class="w-11 h-11 rounded-xl flex items-center justify-center" style="background:rgba(99,102,241,0.1);color:#6366f1">
<svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/></svg>
</div>
<div>
<div class="text-2xl font-display font-bold text-gray-900 leading-none">2.8<span class="text-sm font-normal text-gray-400 ml-0.5"></span></div>
<div class="text-xs text-gray-400 mt-1">评分一致性</div>
<div class="text-[10px] text-gray-300 mt-0.5">标准差越小越好</div>
</div>
</div>
</div>
</div>
<!-- Judge Workload + Award Distribution -->
<div class="grid grid-cols-5 gap-5 mb-5">
<!-- Judge Table -->
<div class="col-span-3 bg-white rounded-card shadow-card p-6 fade-in" style="animation-delay:0.25s">
<h3 class="text-sm font-display font-bold text-gray-900 mb-4 tracking-tight">评委工作量</h3>
<table class="w-full text-left">
<thead>
<tr class="border-b border-gray-100">
<th class="py-3 px-3">评委姓名</th>
<th class="py-3 px-3 text-center">关联活动</th>
<th class="py-3 px-3 text-center">已分配</th>
<th class="py-3 px-3 text-center">已评分</th>
<th class="py-3 px-3 text-center">完成率</th>
<th class="py-3 px-3 text-center">平均分</th>
<th class="py-3 px-3 text-center">标准差</th>
</tr>
</thead>
<tbody>
<tr class="border-b border-gray-50 hover:bg-primary-50/30 transition-colors">
<td class="py-3.5 px-3">
<div class="flex items-center gap-2.5">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-primary-400 to-primary-600 flex items-center justify-center text-white text-xs font-bold"></div>
<span class="font-medium text-gray-900">陈评委</span>
</div>
</td>
<td class="py-3.5 px-3 text-center font-display">2</td>
<td class="py-3.5 px-3 text-center font-display">6</td>
<td class="py-3.5 px-3 text-center font-display">6</td>
<td class="py-3.5 px-3 text-center"><span class="rate-pill bg-green-50 text-green-600">100%</span></td>
<td class="py-3.5 px-3 text-center font-display font-bold text-primary-500">85.67</td>
<td class="py-3.5 px-3 text-center"><span class="text-sm text-amber-500 font-medium">5.89</span></td>
</tr>
<tr class="border-b border-gray-50 hover:bg-primary-50/30 transition-colors">
<td class="py-3.5 px-3">
<div class="flex items-center gap-2.5">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-blue-400 to-blue-600 flex items-center justify-center text-white text-xs font-bold"></div>
<span class="font-medium text-gray-900">李评委</span>
</div>
</td>
<td class="py-3.5 px-3 text-center font-display">2</td>
<td class="py-3.5 px-3 text-center font-display">6</td>
<td class="py-3.5 px-3 text-center font-display">6</td>
<td class="py-3.5 px-3 text-center"><span class="rate-pill bg-green-50 text-green-600">100%</span></td>
<td class="py-3.5 px-3 text-center font-display font-bold text-primary-500">83.00</td>
<td class="py-3.5 px-3 text-center"><span class="text-sm text-green-500 font-medium">5.10</span></td>
</tr>
<tr class="hover:bg-primary-50/30 transition-colors">
<td class="py-3.5 px-3">
<div class="flex items-center gap-2.5">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-emerald-400 to-emerald-600 flex items-center justify-center text-white text-xs font-bold"></div>
<span class="font-medium text-gray-900">王评委</span>
</div>
</td>
<td class="py-3.5 px-3 text-center font-display">2</td>
<td class="py-3.5 px-3 text-center font-display">6</td>
<td class="py-3.5 px-3 text-center font-display">6</td>
<td class="py-3.5 px-3 text-center"><span class="rate-pill bg-green-50 text-green-600">100%</span></td>
<td class="py-3.5 px-3 text-center font-display font-bold text-primary-500">86.00</td>
<td class="py-3.5 px-3 text-center"><span class="text-sm text-green-500 font-medium">3.27</span></td>
</tr>
</tbody>
</table>
</div>
<!-- Award Distribution -->
<div class="col-span-2 bg-white rounded-card shadow-card p-6 fade-in" style="animation-delay:0.3s">
<h3 class="text-sm font-display font-bold text-gray-900 mb-4 tracking-tight">奖项分布</h3>
<div id="awardChart" style="height:260px"></div>
</div>
</div>
</div>
<div class="h-8"></div>
</div>
<script>
// Tab switching
function switchTab(tab) {
document.getElementById('content-overview').classList.toggle('hidden', tab !== 'overview');
document.getElementById('content-review').classList.toggle('hidden', tab !== 'review');
document.getElementById('tab-overview').className = tab === 'overview' ? 'tab-active py-4 text-sm font-display cursor-pointer transition-colors' : 'tab-inactive py-4 text-sm font-display cursor-pointer transition-colors';
document.getElementById('tab-review').className = tab === 'review' ? 'tab-active py-4 text-sm font-display cursor-pointer transition-colors' : 'tab-inactive py-4 text-sm font-display cursor-pointer transition-colors';
if (tab === 'review') { initAwardChart(); }
}
// Trend Chart
const trendChart = echarts.init(document.getElementById('trendChart'));
trendChart.setOption({
tooltip: { trigger: 'axis', backgroundColor: '#fff', borderColor: '#e5e7eb', borderWidth: 1, textStyle: { color: '#374151', fontSize: 13, fontFamily: 'DM Sans, Noto Sans SC' }, boxShadow: '0 4px 12px rgba(0,0,0,0.08)' },
legend: { data: ['报名量', '作品量'], bottom: 0, textStyle: { fontSize: 12, color: '#9ca3af', fontFamily: 'Noto Sans SC' }, itemWidth: 16, itemHeight: 3, itemGap: 24 },
grid: { left: 40, right: 16, top: 16, bottom: 40 },
xAxis: { type: 'category', data: ['10月', '11月', '12月', '1月', '2月', '3月'], axisLine: { lineStyle: { color: '#e5e7eb' } }, axisLabel: { color: '#9ca3af', fontSize: 12 }, axisTick: { show: false } },
yAxis: { type: 'value', axisLine: { show: false }, axisTick: { show: false }, splitLine: { lineStyle: { color: '#f3f4f6', type: 'dashed' } }, axisLabel: { color: '#9ca3af', fontSize: 12 } },
series: [
{ name: '报名量', type: 'line', data: [3, 5, 8, 6, 12, 15], smooth: true, symbol: 'circle', symbolSize: 6, lineStyle: { width: 3, color: '#6366f1' }, itemStyle: { color: '#6366f1', borderWidth: 2, borderColor: '#fff' }, areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: 'rgba(99,102,241,0.15)' }, { offset: 1, color: 'rgba(99,102,241,0)' }]) } },
{ name: '作品量', type: 'line', data: [1, 3, 5, 4, 8, 10], smooth: true, symbol: 'circle', symbolSize: 6, lineStyle: { width: 3, color: '#f59e0b' }, itemStyle: { color: '#f59e0b', borderWidth: 2, borderColor: '#fff' }, areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: 'rgba(245,158,11,0.12)' }, { offset: 1, color: 'rgba(245,158,11,0)' }]) } }
]
});
// Award Chart
function initAwardChart() {
const el = document.getElementById('awardChart');
if (!el) return;
const chart = echarts.init(el);
chart.setOption({
tooltip: { trigger: 'item', backgroundColor: '#fff', borderColor: '#e5e7eb', borderWidth: 1, textStyle: { color: '#374151', fontSize: 13 } },
legend: { bottom: 0, textStyle: { fontSize: 12, color: '#9ca3af' }, itemWidth: 12, itemHeight: 12, itemGap: 16 },
series: [{
type: 'pie', radius: ['45%', '72%'], center: ['50%', '45%'],
label: { show: true, formatter: '{b}\n{d}%', fontSize: 12, color: '#6b7280', lineHeight: 18 },
labelLine: { length: 12, length2: 8 },
itemStyle: { borderRadius: 6, borderColor: '#fff', borderWidth: 3 },
data: [
{ value: 1, name: '一等奖', itemStyle: { color: '#ef4444' } },
{ value: 1, name: '二等奖', itemStyle: { color: '#f59e0b' } },
{ value: 1, name: '三等奖', itemStyle: { color: '#3b82f6' } }
],
emphasis: { itemStyle: { shadowBlur: 12, shadowColor: 'rgba(0,0,0,0.12)' } }
}]
});
}
// Resize
window.addEventListener('resize', () => { trendChart.resize(); });
// Export placeholders
function exportPDF() { alert('PDF 导出功能将在开发时实现'); }
function exportExcel() { alert('Excel 导出功能将在开发时实现'); }
</script>
</body>
</html>