diff --git a/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue
index d7ea4d7..378e31d 100644
--- a/src/layout/components/AppMain.vue
+++ b/src/layout/components/AppMain.vue
@@ -14,14 +14,16 @@
-
+
+
+
+
diff --git a/src/views/schoolAdmin/trainingTask/index.vue b/src/views/schoolAdmin/trainingTask/index.vue
index 7d09033..a03e5fb 100644
--- a/src/views/schoolAdmin/trainingTask/index.vue
+++ b/src/views/schoolAdmin/trainingTask/index.vue
@@ -168,10 +168,14 @@
-
-
+
+
+
+ 删除
+
>>>
+ 新增步骤
@@ -293,7 +297,7 @@ function createEmptyTask() {
requirements: "",
materialName: "",
materialUrl: "",
- steps: ["", "", "", ""],
+ steps: createBuiltinSteps(),
sort: 0,
enabled: true,
};
@@ -311,7 +315,7 @@ function normalizeTask(task) {
requirements: task.requirements || "",
materialName: material.name,
materialUrl: material.url,
- steps: normalizeSteps(parseArray(task.steps, ["", "", "", ""])),
+ steps: normalizeSteps(parseArray(task.steps, createBuiltinSteps())),
sort: task.sort || 0,
enabled: task.enabled !== false,
};
@@ -351,11 +355,28 @@ function parseArray(value, fallback) {
}
function normalizeSteps(steps) {
- const result = steps.filter((item) => String(item || "").trim()).slice(0, 4);
- while (result.length < 4) {
- result.push("");
- }
- return result;
+ const source = Array.isArray(steps) ? steps : [];
+ const result = source
+ .map((item, index) => {
+ const raw = item && typeof item === "object" ? item : {};
+ const name = typeof item === "object" ? String(raw.name || "").trim() : String(item || "").trim();
+ const kind = raw.kind === "custom" ? "custom" : index < 4 ? "builtin" : "custom";
+ return createStep(name, kind, raw.id);
+ })
+ .filter((item) => item.name);
+ return result.length ? result : [createStep()];
+}
+
+function createBuiltinSteps() {
+ return [1, 2, 3, 4].map((index) => createStep("", "builtin", `builtin-${index}`));
+}
+
+function createStep(name = "", kind = "custom", id = "") {
+ return {
+ id: id || `custom-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
+ name,
+ kind,
+ };
}
function openTaskDialog(task, mode) {
@@ -369,7 +390,7 @@ function cloneTask(task) {
return {
...task,
objectives: [...(task.objectives?.length ? task.objectives : [""])],
- steps: normalizeSteps(task.steps?.length ? task.steps : ["", "", "", ""]),
+ steps: normalizeSteps(task.steps?.length ? task.steps : createBuiltinSteps()),
};
}
@@ -382,6 +403,15 @@ function removeObjective(index) {
taskForm.objectives.splice(index, 1);
}
+function addStep() {
+ taskForm.steps.push(createStep());
+}
+
+function removeStep(index) {
+ if (taskForm.steps.length <= 1) return;
+ taskForm.steps.splice(index, 1);
+}
+
async function handleImportChange(file) {
if (!file?.raw) return;
await importTrainingTasks(file.raw);
@@ -443,7 +473,7 @@ function buildPayload() {
background: taskForm.background,
objectives: JSON.stringify(taskForm.objectives.map((item) => item.trim()).filter(Boolean)),
requirements: taskForm.requirements,
- steps: JSON.stringify(taskForm.steps.map((item) => item.trim()).filter(Boolean)),
+ steps: JSON.stringify(taskForm.steps.map((item) => ({ ...item, name: item.name.trim() })).filter((item) => item.name)),
materialName: taskForm.materialName,
materialUrl: taskForm.materialUrl,
sort: taskForm.sort,
@@ -1150,13 +1180,25 @@ function buildPayload() {
}
.step-row {
- display: grid;
- grid-template-columns: 1fr auto 1fr auto 1fr auto 1fr;
+ display: flex;
+ flex-wrap: wrap;
gap: 12px;
align-items: center;
width: 100%;
}
+ .step-item {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 230px;
+ flex: 1 1 260px;
+ }
+
+ .add-step-button {
+ border-style: dashed;
+ }
+
.step-arrow {
color: #7ddaff;
font-weight: 800;
@@ -1213,7 +1255,7 @@ function buildPayload() {
}
.step-row {
- grid-template-columns: 1fr;
+ align-items: stretch;
}
.step-arrow {
diff --git a/src/views/teacherEnd/trainingTask/index.vue b/src/views/teacherEnd/trainingTask/index.vue
index fd81a9e..1573ae3 100644
--- a/src/views/teacherEnd/trainingTask/index.vue
+++ b/src/views/teacherEnd/trainingTask/index.vue
@@ -104,7 +104,7 @@
{{ dialogMode === "view" ? "Training Task Preview" : "Training Task Editor" }}
{{ dialogMode === "view" ? "查看实训任务" : "编辑实训任务" }}
-
任务数量与步骤数量由系统固定,老师可维护任务显示名称、实训说明、目标、要求和步骤名称。
+
老师可维护任务显示名称、实训说明、目标、要求和步骤,并可新增或删除步骤。