const assert = require("assert"); const fs = require("fs"); const path = require("path"); const root = path.resolve(__dirname, ".."); const read = (file) => fs.readFileSync(path.join(root, file), "utf8"); const taskPage = read("src/views/teacherEnd/task/index.vue"); const sidebar = read("src/layout/components/Sidebar/index.vue"); const api = read("src/api/teacher.js"); assert(taskPage.includes('import { listClassTrainingTasks } from "@/api/trainingTask";'), "task allocation must import the class-scoped training task source"); assert(taskPage.includes("listClassTrainingTasks"), "task allocation must load training tasks for the selected teaching class"); assert(taskPage.includes("await listClassTrainingTasks(classId.value, { enabledOnly: false })"), "class task loading must request disabled and enabled tasks"); assert(/tasks\.value = \[\];\s+const res = await listClassTrainingTasks/.test(taskPage), "class task loading must clear prior class rows before requesting the selected class"); assert(taskPage.includes("function sortTasksWithComprehensiveLast(taskList)"), "task allocation must normalize task order after loading"); assert(taskPage.includes("tasks.value = sortTasksWithComprehensiveLast(res.data || []);"), "task allocation must render comprehensive training after every other task"); assert((taskPage.match(/const requestedClassId = classId\.value;/g) || []).length >= 2, "task and publication loading must capture the requested class"); assert((taskPage.match(/if \(!isActiveLoad\(requestedClassId, requestGeneration\)\) return/g) || []).length >= 2, "stale class requests must not update task rows or publication selection"); assert(taskPage.includes("let activeLoadGeneration = 0;"), "overlapping class loads must use a shared generation"); assert(taskPage.includes("const requestGeneration = ++activeLoadGeneration;"), "each class load must advance the active generation"); assert(taskPage.includes("if (requestGeneration === activeLoadGeneration) loading.value = false;"), "only the active class load may clear the loading indicator"); assert(taskPage.includes("let selectionSyncGeneration = -1;"), "programmatic selection synchronization must be tracked"); assert(taskPage.includes("if (selectionSyncGeneration === activeLoadGeneration) return;"), "programmatic table selection events must not overwrite task keys"); assert(taskPage.includes("getTaskPublication"), "task allocation must load the selected class publication state"); assert(/tasks\.value\s+\.filter\(\(task\) => task\.taskKey !== comprehensiveTaskKey\)\s+\.map\(\(task\) => task\.taskKey\)/.test(taskPage), "an unconfigured class must keep comprehensive training unpublished until the teacher explicitly selects it"); assert(taskPage.includes("保存发布配置"), "task allocation must require an explicit save"); assert(api.includes("selectTaskPublicationByClassId"), "publication API missing"); assert(sidebar.includes("buildStudentTaskSections"), "student menu must be generated from the published training task list"); assert(sidebar.includes("studentTaskSections"), "student menu must retain task-derived navigation sections"); console.log("task publication front-end contract passed");