feat: add AI training evaluation frontend
parent
6fb30dcb6b
commit
d731aa1614
@ -0,0 +1,15 @@
|
|||||||
|
# Task 4: AI training evaluation frontend
|
||||||
|
|
||||||
|
## Delivered
|
||||||
|
|
||||||
|
- Added the AI training evaluation API client for status, help, and assessment operations.
|
||||||
|
- Added `TrainingAiEvaluation.vue` with distinct AI助学 and AI助评 controls, backend status display, confirmation before assessment, retryable errors, safe interpolated report rendering, and score criteria.
|
||||||
|
- Integrated the component into `GenericTrainingPage.vue` before the legacy AI sidebar and derived `hasAnyAnswer` from form fields, work rows, and process rows.
|
||||||
|
- Added a static contract test for this integration.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
- `node tests/ai-training-evaluation.static.test.cjs`
|
||||||
|
- `npm run build:prod`
|
||||||
|
|
||||||
|
The production build emits pre-existing warnings for deprecated `::v-deep` syntax, a runtime-resolved navbar image, and oversized chunks; it exits successfully.
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
import request from "@/utils/request";
|
||||||
|
|
||||||
|
export function getAiTrainingEvaluation(taskKey) {
|
||||||
|
return request({
|
||||||
|
url: `/api/student/training-tasks/${taskKey}/ai-evaluation`,
|
||||||
|
method: "get",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function requestAiTrainingHelp(taskKey) {
|
||||||
|
return request({
|
||||||
|
url: `/api/student/training-tasks/${taskKey}/ai-evaluation/help`,
|
||||||
|
method: "post",
|
||||||
|
headers: { repeatSubmit: false },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function requestAiTrainingAssessment(taskKey) {
|
||||||
|
return request({
|
||||||
|
url: `/api/student/training-tasks/${taskKey}/ai-evaluation/assessment`,
|
||||||
|
method: "post",
|
||||||
|
headers: { repeatSubmit: false },
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
const assert = require("assert");
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const root = path.resolve(__dirname, "..");
|
||||||
|
const api = fs.readFileSync(path.join(root, "src/api/aiTrainingEvaluation.js"), "utf8");
|
||||||
|
const component = fs.readFileSync(path.join(root, "src/views/components/TrainingAiEvaluation.vue"), "utf8");
|
||||||
|
const page = fs.readFileSync(path.join(root, "src/views/training/GenericTrainingPage.vue"), "utf8");
|
||||||
|
|
||||||
|
assert(/`\/api\/student\/training-tasks\/\$\{taskKey\}\/ai-evaluation`/.test(api), "evaluation API should use the student task endpoint");
|
||||||
|
assert(/\/help/.test(api) && /\/assessment/.test(api), "evaluation API should expose help and assessment operations");
|
||||||
|
assert(/TrainingAiEvaluation/.test(page) && /:has-any-answer="hasAnyAnswer"/.test(page), "generic training page should pass meaningful answer state to AI evaluation");
|
||||||
|
assert(/form\.value/.test(page) && /workRows\.value/.test(page) && /processRows\.value/.test(page), "hasAnyAnswer should inspect all supported answer shapes");
|
||||||
|
assert(/<TrainingAiEvaluation[\s\S]*<TrainingAiSidebar/.test(page), "AI evaluation should render before the existing AI sidebar");
|
||||||
|
|
||||||
|
assert(/onMounted\(/.test(component) && /watch\(\s*\(\)\s*=>\s*props\.taskKey/.test(component), "AI evaluation should load on mount and task changes");
|
||||||
|
assert(/AI助学/.test(component) && /AI助评/.test(component), "AI evaluation should offer separate help and assessment controls");
|
||||||
|
assert(/PROCESSING/.test(component) && /SUCCEEDED/.test(component), "AI evaluation should surface backend statuses");
|
||||||
|
assert(/!props\.hasAnyAnswer/.test(component), "AI actions should disable when no answer is available");
|
||||||
|
assert(/proxy\?\.\$modal\?\.confirm/.test(component), "assessment should request confirmation through the modal proxy");
|
||||||
|
assert(!/v-html/.test(component), "AI reports must be rendered as interpolated text, never v-html");
|
||||||
|
assert(/scoreCriteria/.test(component), "assessment should display score criteria");
|
||||||
|
assert(/retry/.test(component) || /重试/.test(component), "failed AI operations should expose a retry action");
|
||||||
Loading…
Reference in New Issue