You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dianshang-qianduan/docs/superpowers/plans/2026-08-03-student-home-new...

161 lines
7.5 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 学生首页新版实训模块展示 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:** Replace every student-home module display with the current training-report modules and remove the legacy five-module dashboard.
**Architecture:** `src/views/student/index.vue` will request `GET /api/student/experiment-report/current` and derive the score chart, score table, and task-progress chart from its participating modules. The legacy study-time request remains only to show one aggregate effective-learning-time number; it supplies no module names, chart slices, or module rows.
**Tech Stack:** Vue 3 Composition API, Element Plus, ECharts 5, existing Axios request wrapper, Node `assert` static checks, Vite 3.
## Global Constraints
- The homepage must show only: 互联网产品开发基础认知、市场洞察与需求分析、产品规划与设计、产品开发与测试验证、产品上线与运营推广,以及已发布时的综合实训。
- `综合实训` is rendered only when the report module has `participating !== false`.
- No homepage component may call `getStuWeightScore`, `getRouters`, or use the old five-module field names for module-level display.
- Score, score share, and completion progress must derive from the same `getCurrentExperimentReport()` response.
- Preserve effective learning time only as a single aggregate number; do not map legacy time fields to new modules.
---
## File Structure
- `src/views/student/index.vue` — student-home dashboard; replaces hard-coded old modules with report-driven score and progress views.
- `tests/student-home-new-modules.static.test.cjs` — guards the report-data contract and prevents reintroduction of the old module dashboard.
### Task 1: Report-driven student-home dashboard
**Files:**
- Modify: `src/views/student/index.vue`
- Create: `tests/student-home-new-modules.static.test.cjs`
**Interfaces:**
- Consumes: `getCurrentExperimentReport(): Promise<{ data: { totalScore: number, modules: Array<{ moduleName: string, weight: number, score: number, participating: boolean, completedTaskCount: number, totalTaskCount: number }> } }>` from `src/api/index.js`.
- Consumes: `getStudyTime({ userId }): Promise<{ data: Record<string, number> }>` only to calculate a single aggregate duration.
- Produces: `participatingModules`, a computed list used by both ECharts options and the score/progress tables.
- [ ] **Step 1: Write the failing static contract test**
Create `tests/student-home-new-modules.static.test.cjs` with the following checks:
```js
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const root = path.resolve(__dirname, '..');
const page = fs.readFileSync(path.join(root, 'src/views/student/index.vue'), 'utf8');
assert(/getCurrentExperimentReport/.test(page));
assert(/participatingModules/.test(page));
assert(/completedTaskCount/.test(page));
assert(/totalTaskCount/.test(page));
assert(/moduleName/.test(page));
assert(!/getStuWeightScore\(/.test(page));
assert(!/getRouters\(/.test(page));
assert(!/市场需求挖掘|产品投放测试|供应渠道管理|产品评估与考核/.test(page));
console.log('student home new module static checks passed');
```
- [ ] **Step 2: Run the test to verify it fails**
Run: `node tests/student-home-new-modules.static.test.cjs`
Expected: failure because `src/views/student/index.vue` still uses `getStuWeightScore`, `getRouters`, and hard-coded old module labels.
- [ ] **Step 3: Replace the hard-coded dashboard with report data**
In `src/views/student/index.vue`:
```js
const report = ref({ totalScore: 0, modules: [] });
const loading = ref(true);
const loadError = ref('');
const participatingModules = computed(() =>
(report.value.modules || []).filter((module) => module.participating !== false)
);
const totalTime = computed(() =>
Object.values(studyTime.value || {}).reduce((total, value) => total + (Number(value) || 0), 0)
);
```
Replace the score pie data with:
```js
data: participatingModules.value.map((module, index) => ({
name: module.moduleName,
value: Number(module.score) || 0,
itemStyle: { color: MODULE_COLORS[index % MODULE_COLORS.length] }
}))
```
Render the score table with `v-for` rows from `participatingModules`, showing `moduleName`, `weight * 100`, `score`, and `completedTaskCount / totalTaskCount`. Replace the second legacy “我的成绩” card with “实训进度概览”: an ECharts bar chart whose series are `completedTaskCount` and remaining task count, plus a compact module-progress list. Keep the effective-learning-time card but remove the legacy doughnut chart and old five-row time list.
Load dashboard data through `getCurrentExperimentReport()` and `getStudyTime({ userId })`. On report failure, set `loadError` and render an `el-alert`; do not create old-module fallback rows. Create ECharts instances once, resize them through one lifecycle-managed listener, and dispose both in `onBeforeUnmount`.
- [ ] **Step 4: Run the static contract test to verify it passes**
Run: `node tests/student-home-new-modules.static.test.cjs`
Expected: `student home new module static checks passed`.
- [ ] **Step 5: Commit the dashboard change**
```bash
git add src/views/student/index.vue tests/student-home-new-modules.static.test.cjs
git commit -m "feat: show new training modules on student home"
```
### Task 2: Build and visual verification
**Files:**
- Verify: `src/views/student/index.vue`
- Verify: `tests/student-home-new-modules.static.test.cjs`
**Interfaces:**
- Consumes: Task 1s report-driven dashboard and static contract test.
- Produces: a production Vite bundle that contains no old-module dashboard source.
- [ ] **Step 1: Run all relevant static checks**
Run:
```bash
node tests/student-home-new-modules.static.test.cjs
node tests/student-experiment-report.static.test.cjs
```
Expected: both commands exit with status 0.
- [ ] **Step 2: Build the frontend production bundle**
Run: `npm run build:prod`
Expected: Vite completes successfully. Existing warnings about `::v-deep`, `top1.png`, or large chunks may be recorded but must not become build errors.
- [ ] **Step 3: Verify the rendered student homepage**
Run the local frontend and, with an authenticated student whose class has published comprehensive training, verify:
```text
成绩饼图、成绩表、实训进度概览都显示六个新版模块;
综合实训未发布时只显示前五个新版模块;
页面上不存在旧五模块名称或旧模块时间占比图。
```
- [ ] **Step 4: Commit verification-only changes if any**
If Step 13 created no source changes, do not create an empty commit. If a source correction was needed, add only that correction and commit it with:
```bash
git add src/views/student/index.vue tests/student-home-new-modules.static.test.cjs
git commit -m "fix: complete student home module dashboard"
```
## Self-Review
- Spec coverage: Task 1 replaces the legacy five-module score and time dashboard, filters unpublished comprehensive training, uses one report response for all module-level cards, retains only aggregate study time, and adds explicit load-error handling. Task 2 validates the contract, build, and both comprehensive-training visibility states.
- Placeholder scan: no deferred implementation markers or unspecified test steps remain.
- Type consistency: `participatingModules` is the shared source for score and progress visualizations; all module fields match `StudentExperimentReportModuleDTO`.