feat: add school default task configuration page

dev-QQq
chenyuan 1 month ago
parent bad2437914
commit 2ad3ee929e

@ -552,6 +552,26 @@ export function addTask(data) {
},
});
}
// 学校默认实训任务(仅管理员教师)
export function getSchoolDefaultTasks() {
return request({
url: "/api/school-default-tasks",
method: "GET",
});
}
export function saveSchoolDefaultTasks(data) {
return request({
url: "/api/school-default-tasks",
method: "PUT",
data,
});
}
export function retrySchoolDefaultTaskInitialization() {
return request({
url: "/api/school-default-tasks/retry",
method: "POST",
});
}
// 成绩中心-查询成绩列表
export function getScoreList(params) {
return request({

@ -586,6 +586,7 @@ function filterRoutesByOrganizationMode(routes) {
const majorEnabled = config?.majorManagementEnabled ?? legacyAdminEnabled;
const adminClassEnabled = config?.adminClassManagementEnabled ?? legacyAdminEnabled;
return routes.filter((route) => {
if (route.meta?.requiresManagerTeacher && userStore.userInfo.teacherAdmin !== true) return false;
if (route.meta?.requiresFacultyManagement && !facultyEnabled) return false;
if (route.meta?.requiresMajorManagement && !majorEnabled) return false;
if (route.meta?.requiresAdminClass && !adminClassEnabled) return false;

@ -551,6 +551,21 @@ export const teacherRoutes = [
],
},
// 任务分配
{
path: "/default-task",
component: Layout,
redirect: "/default-task/index",
roles: ["teacher"],
meta: { title: "默认实训任务配置", icon: "任务分配", affix: true, requiresManagerTeacher: true },
children: [
{
path: "index",
component: () => import("@/views/teacherEnd/defaultTask/index.vue"),
name: "defaultTask",
meta: { title: "默认实训任务配置", icon: "任务分配", affix: true, requiresManagerTeacher: true },
},
],
},
{
path: "/task",
component: Layout,

@ -0,0 +1,108 @@
<template>
<div class="app-container default-task-page">
<el-alert
v-if="!isReady"
:title="statusTitle"
:description="lastError || '正在初始化,稍后刷新。初始化完成前暂以平台基线任务只读展示。'"
:type="status === 'FAILED' ? 'error' : 'warning'"
:closable="false"
show-icon
class="mb16"
/>
<div class="task-toolbar">
<div>
<h3>默认实训任务配置</h3>
<p>为本校教学班尚未单独配置任务时提供默认任务教学班已配置的任务不受这里改动影响</p>
</div>
<div class="toolbar-actions">
<el-button :loading="loading" @click="loadTasks"></el-button>
<el-button v-if="!isReady" type="warning" :loading="retrying" @click="retryInitialization"></el-button>
<el-button type="primary" :disabled="!isReady" :loading="saving" @click="saveTasks"></el-button>
</div>
</div>
<el-table v-loading="loading" :data="tasks" border row-key="id" class="task-table">
<el-table-column label="实训任务" prop="module" min-width="260" />
<el-table-column label="是否启用" width="180" align="center">
<template #default="{ row }">
<el-switch
v-model="row.disabledStatus"
:active-value="0"
:inactive-value="1"
active-text="启用"
inactive-text="停用"
:disabled="!isReady"
/>
</template>
</el-table-column>
<el-table-column label="排序" prop="sort" width="100" align="center" />
</el-table>
</div>
</template>
<script setup>
import { computed, getCurrentInstance, onMounted, ref } from "vue";
import * as teacherApi from "@/api/teacher";
import useUserStore from "@/store/modules/user";
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
const tasks = ref([]);
const status = ref("INITIALIZING");
const lastError = ref("");
const loading = ref(false);
const saving = ref(false);
const retrying = ref(false);
const isManagerTeacher = computed(() => userStore.userInfo.teacherAdmin === true);
const isReady = computed(() => status.value === "READY");
const statusTitle = computed(() => (status.value === "FAILED" ? "默认任务初始化失败" : "默认任务正在初始化"));
const loadTasks = async () => {
if (!isManagerTeacher.value) {
proxy.$modal.msgError("仅管理员教师可访问默认实训任务配置");
proxy.$router.replace("/index");
return;
}
loading.value = true;
try {
const res = await teacherApi.getSchoolDefaultTasks();
status.value = res.data?.status || "INITIALIZING";
lastError.value = res.data?.lastError || "";
tasks.value = res.data?.tasks || [];
} finally {
loading.value = false;
}
};
const saveTasks = async () => {
saving.value = true;
try {
await teacherApi.saveSchoolDefaultTasks(tasks.value);
proxy.$modal.msgSuccess("默认实训任务已保存");
await loadTasks();
} finally {
saving.value = false;
}
};
const retryInitialization = async () => {
retrying.value = true;
try {
await teacherApi.retrySchoolDefaultTaskInitialization();
proxy.$modal.msgSuccess("已提交初始化任务,请稍后刷新");
await loadTasks();
} finally {
retrying.value = false;
}
};
onMounted(loadTasks);
</script>
<style scoped>
.default-task-page { min-height: 640px; }
.task-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 24px; margin-bottom: 16px; }
.task-toolbar h3 { margin: 0 0 8px; }
.task-toolbar p { margin: 0; color: var(--el-text-color-secondary); }
.toolbar-actions { display: flex; gap: 10px; flex-shrink: 0; }
.task-table { width: 100%; }
</style>

@ -0,0 +1,20 @@
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 routerSource = read("src/router/index.js");
const sidebarSource = read("src/layout/components/Sidebar/index.vue");
const apiSource = read("src/api/teacher.js");
const pageSource = read("src/views/teacherEnd/defaultTask/index.vue");
assert.match(routerSource, /requiresManagerTeacher:\s*true/);
assert.match(sidebarSource, /route\.meta\?\.requiresManagerTeacher/);
assert.match(apiSource, /\/api\/school-default-tasks/);
assert.match(pageSource, /正在初始化,稍后刷新/);
assert.match(pageSource, /立即重试/);
assert.match(pageSource, /:disabled="!isReady"/);
console.log("school default task front-end contract passed");
Loading…
Cancel
Save