# 人气前五 Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 在提交统计弹窗中新增"人气前五"区块,展示当前 task 下 view_count 最高的前 5 条提交,跟随班级筛选。 **Architecture:** 后端在现有 `get_task_stats` 端点中新增 `top_viewed` 查询,前端在 `TaskStatsModal` 底部新增对应 UI 区块。全程复用已有数据流,不新增 API 路由。 **Tech Stack:** Python/Django-Ninja (backend schema + query), TypeScript (type definition), Vue 3 + Naive UI (frontend component) --- ### Task 1: 后端 Schema — 新增 `TopViewedItem`,更新 `TaskStatsOut` **Files:** - Modify: `api/submission/schemas.py:134-151` - [ ] **Step 1: 在 `FlagStats` 之前插入 `TopViewedItem` class** 在 `api/submission/schemas.py` 第 134 行(`class FlagStats` 之前)插入: ```python class TopViewedItem(Schema): username: str classname: str view_count: int submission_id: str ``` - [ ] **Step 2: 在 `TaskStatsOut` 末尾新增 `top_viewed` 字段** 将 `TaskStatsOut`(当前第 141-151 行)更新为: ```python class TaskStatsOut(Schema): submitted_count: int unsubmitted_count: int average_score: Optional[float] unrated_count: int unsubmitted_users: list[UserTag] unrated_users: list[UserTag] submission_count_distribution: SubmissionCountBucket flag_stats: FlagStats classes: list[str] top_viewed: list[TopViewedItem] ``` - [ ] **Step 3: 验证 Schema 无语法错误** ```bash cd /home/xuyue/Projects/webpreview/api uv run python -c "from submission.schemas import TaskStatsOut, TopViewedItem; print('OK')" ``` Expected output: `OK` - [ ] **Step 4: Commit** ```bash git add api/submission/schemas.py git commit -m "feat: add TopViewedItem schema and top_viewed field to TaskStatsOut" ``` --- ### Task 2: 后端查询 — 在 `get_task_stats` 中计算并返回 `top_viewed` **Files:** - Modify: `api/submission/api.py:13-23` (imports) - Modify: `api/submission/api.py:306-330` (flag_stats 之后 → return 之前,以及 return 语句) - [ ] **Step 1: 在 import 中新增 `TopViewedItem`** 将 `api/submission/api.py` 顶部的 import(第 13-23 行)更新为: ```python from .schemas import ( FlagIn, FlagStats, SubmissionCountBucket, SubmissionFilter, SubmissionIn, SubmissionOut, RatingScoreIn, TaskStatsOut, TopViewedItem, UserTag, ) ``` - [ ] **Step 2: 在 `flag_stats =` 赋值之后、`return TaskStatsOut(...)` 之前插入 top_viewed 查询** 在 `api/submission/api.py` 第 318 行(`return TaskStatsOut(` 之前)插入: ```python # Top 5 submissions by view_count (within filtered student_ids) top_viewed_qs = ( Submission.objects .filter(task=task, user_id__in=student_ids) .select_related("user") .order_by("-view_count")[:5] ) top_viewed = [ TopViewedItem( username=s.user.username, classname=s.user.classname, view_count=s.view_count, submission_id=str(s.id), ) for s in top_viewed_qs ] ``` - [ ] **Step 3: 在 `return TaskStatsOut(...)` 中新增 `top_viewed=top_viewed`** 将返回语句(当前第 320-330 行)更新为: ```python return TaskStatsOut( submitted_count=submitted_count, unsubmitted_count=unsubmitted_count, average_score=average_score, unrated_count=unrated_count, unsubmitted_users=unsubmitted_users, unrated_users=unrated_users, submission_count_distribution=SubmissionCountBucket(**dist), flag_stats=flag_stats, classes=all_classes, top_viewed=top_viewed, ) ``` - [ ] **Step 4: 启动开发服务器,验证接口返回** ```bash cd /home/xuyue/Projects/webpreview/api uv run manage.py runserver ``` 另开终端,用已有管理员账号 cookie 或 session 测试(替换 `` 和 ``): ```bash curl -s -H "Cookie: sessionid=" \ http://127.0.0.1:8000/api/submission/stats/ \ | python3 -m json.tool | grep -A 20 '"top_viewed"' ``` Expected: 看到 `"top_viewed": [...]`,每项含 `username`、`classname`、`view_count`、`submission_id`。 - [ ] **Step 5: Commit** ```bash git add api/submission/api.py git commit -m "feat: query top 5 by view_count in get_task_stats" ``` --- ### Task 3: 前端类型 — 新增 `TopViewedItem` 接口,更新 `TaskStatsOut` **Files:** - Modify: `client/src/utils/type.ts:136-148` - [ ] **Step 1: 在 `TaskStatsOut` 之前插入 `TopViewedItem` 接口** 在 `client/src/utils/type.ts` 第 136 行(`export interface TaskStatsOut` 之前)插入: ```ts export interface TopViewedItem { username: string classname: string view_count: number submission_id: string } ``` - [ ] **Step 2: 在 `TaskStatsOut` 末尾新增 `top_viewed` 字段** 将 `TaskStatsOut`(当前第 137-148 行)更新为: ```ts export interface TaskStatsOut { submitted_count: number unsubmitted_count: number average_score: number | null unrated_count: number unsubmitted_users: UserTag[] unrated_users: UserTag[] submission_count_distribution: SubmissionCountBucket score_distribution: ScoreBucket flag_stats: FlagStats classes: string[] top_viewed: TopViewedItem[] } ``` - [ ] **Step 3: Commit** ```bash git add client/src/utils/type.ts git commit -m "feat: add TopViewedItem type and top_viewed to TaskStatsOut" ``` --- ### Task 4: 前端 UI — 在 `TaskStatsModal` 中新增"人气前五"区块 **Files:** - Modify: `client/src/components/TaskStatsModal.vue` - [ ] **Step 1: 在模板的"标记统计"区块(``,第 282 行附近)之后新增"人气前五"区块** 找到 `` 之前的 `` 区块末尾的 ``(第 325 行附近),在它后面、`` 之前插入: ```html
人气前五
暂无
{{ i + 1 }} {{ displayName(item.username, item.classname) }} {{ item.view_count }} 次
``` - [ ] **Step 2: 在 `