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