|
|
|
|
@ -344,6 +344,28 @@
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 第一步选择题:仅三个白名单任务可配置,复用统一编辑器 -->
|
|
|
|
|
<div v-if="supportsStepOneChoice(taskForm.taskKey)" class="material-row">
|
|
|
|
|
<div class="material-info">
|
|
|
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
|
|
|
stroke-width="2">
|
|
|
|
|
<path d="M9 11l3 3L22 4" />
|
|
|
|
|
<path d="M21 12v7a2 2 0 01-2 2H5a2 2 0 01-2-2V5a2 2 0 012-2h11" />
|
|
|
|
|
</svg>
|
|
|
|
|
<div class="material-text">
|
|
|
|
|
<span class="material-label">第一步选择题</span>
|
|
|
|
|
<span v-if="stepOneQuestionCount" class="material-link">已配置 {{ stepOneQuestionCount }} 道题</span>
|
|
|
|
|
<span v-else class="material-placeholder">暂未配置,学生端第一步将不显示选择题</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="material-ops">
|
|
|
|
|
<el-button v-if="!isReadonly" type="primary" class="upload-btn" @click="choiceEditorVisible = true">
|
|
|
|
|
设置选择题
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<StepOneChoiceQuestionEditor v-model:visible="choiceEditorVisible" v-model="taskForm.stepOneQuestions" :task-name="taskForm.title" />
|
|
|
|
|
|
|
|
|
|
<!-- 步骤数量与顺序固定,仅允许修改名称 -->
|
|
|
|
|
<el-form-item label="步骤名称:">
|
|
|
|
|
<div class="step-list">
|
|
|
|
|
@ -397,6 +419,8 @@ import { listTrainingTasks, listClassTrainingTasks, saveClassTrainingTask, resto
|
|
|
|
|
import { createStudentDemoSession } from "@/api/studentDemo"
|
|
|
|
|
import * as indexApi from "@/api/teacher"
|
|
|
|
|
import useUserStore from "@/store/modules/user"
|
|
|
|
|
import StepOneChoiceQuestionEditor from "@/views/components/StepOneChoiceQuestionEditor.vue"
|
|
|
|
|
import { parseStepOneChoiceQuestions, supportsStepOneChoiceQuestions } from "@/utils/stepOneChoiceQuestions"
|
|
|
|
|
|
|
|
|
|
const { proxy } = getCurrentInstance()
|
|
|
|
|
const userStore = useUserStore()
|
|
|
|
|
@ -408,6 +432,7 @@ const classesLoading = ref(false)
|
|
|
|
|
const saving = ref(false)
|
|
|
|
|
const restoring = ref(false)
|
|
|
|
|
const uploadingField = ref("")
|
|
|
|
|
const choiceEditorVisible = ref(false)
|
|
|
|
|
// 四类资料槽位:key 对应 taskForm 的 `${key}Name` / `${key}Url` 字段
|
|
|
|
|
const materialSlots = [
|
|
|
|
|
{ key: "material", label: "案例资料" },
|
|
|
|
|
@ -423,6 +448,7 @@ const dialogMode = ref("view")
|
|
|
|
|
const taskForm = reactive(createEmptyTask())
|
|
|
|
|
const currentUserId = computed(() => userStore.userInfo.userId)
|
|
|
|
|
const isReadonly = computed(() => dialogMode.value === "view")
|
|
|
|
|
const stepOneQuestionCount = computed(() => taskForm.stepOneQuestions?.length || 0)
|
|
|
|
|
const projects = computed(() => [...new Set(tasks.value.map((task) => task.project).filter(Boolean))])
|
|
|
|
|
const projectOptions = computed(() => {
|
|
|
|
|
return projects.value.map((project) => ({
|
|
|
|
|
@ -566,12 +592,17 @@ function createEmptyTask() {
|
|
|
|
|
guideManualUrl: "",
|
|
|
|
|
aiManualName: "",
|
|
|
|
|
aiManualUrl: "",
|
|
|
|
|
stepOneQuestions: [],
|
|
|
|
|
steps: createBuiltinSteps(),
|
|
|
|
|
sort: 0,
|
|
|
|
|
enabled: true,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function supportsStepOneChoice(taskKey) {
|
|
|
|
|
return supportsStepOneChoiceQuestions(taskKey)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function hasMaterial(slotKey) {
|
|
|
|
|
return isRealMaterial(taskForm[`${slotKey}Name`], taskForm[`${slotKey}Url`])
|
|
|
|
|
}
|
|
|
|
|
@ -601,6 +632,7 @@ function normalizeTask(task) {
|
|
|
|
|
guideManualUrl: guideManual.url,
|
|
|
|
|
aiManualName: aiManual.name,
|
|
|
|
|
aiManualUrl: aiManual.url,
|
|
|
|
|
stepOneQuestions: parseStepOneChoiceQuestions(task.stepOneQuestions),
|
|
|
|
|
steps: normalizeSteps(parseArray(task.steps, createBuiltinSteps())),
|
|
|
|
|
sort: task.sort || 0,
|
|
|
|
|
enabled: task.enabled !== false,
|
|
|
|
|
@ -833,6 +865,7 @@ function buildPayload() {
|
|
|
|
|
guideManualUrl: taskForm.guideManualUrl,
|
|
|
|
|
aiManualName: taskForm.aiManualName,
|
|
|
|
|
aiManualUrl: taskForm.aiManualUrl,
|
|
|
|
|
stepOneQuestions: JSON.stringify(taskForm.stepOneQuestions || []),
|
|
|
|
|
sort: taskForm.sort,
|
|
|
|
|
enabled: taskForm.enabled,
|
|
|
|
|
}
|
|
|
|
|
|