feat(course): 新增课程评估组件并完善相关功能

- 创建 AccessComp.vue 组件用于课程评估配置
- 在 createCourse.vue 中引入并注册评估组件
- 添加评估数据结构及默认内容
- 实现评估表单的展示与交互逻辑
- 增加 copyChooseItemData 用于取消操作时的数据恢复
- 修改取消按钮逻辑以支持数据回滚
- 调整组件间通信逻辑以适配新评估功能
This commit is contained in:
陈昱达
2025-11-25 18:14:56 +08:00
parent 13bfa1a58b
commit c6321027e1
2 changed files with 186 additions and 2 deletions

View File

@@ -0,0 +1,165 @@
<script setup>
import {
ElForm,
ElFormItem,
ElInput,
ElRadioButton,
ElRadioGroup,
} from "element-plus";
defineOptions({
resType: 62,
});
const props = defineProps({
dialogVideoForm: {
type: Object,
default: () => ({
name: "",
filePath: "",
isDrag: true,
completeSetup: 0,
setupTage: 0,
openType: "",
}),
},
isPreview: {
type: Boolean,
default: false,
},
});
import { useMediaComponent } from "@/hooks/useMediaComponent";
// Emit updates to parent component
const emit = defineEmits(["update:dialogVideoForm"]);
// 使用hook处理公共逻辑
const { localDialogVideoForm, updateFormValue, fileBaseUrl } =
useMediaComponent(props, emit);
const content = {
countType: "权重配置",
countText: "问题1*80%+问题2*10%+问题3*10%",
resultCount: "[q1]*0.8+[q2]*0.1+[q3]*0.1",
items: [
{
id: "1",
question: "您觉的课程对工作有帮助/启发呢?",
minText: "完全没用",
maxText: "非常有帮助/启发",
qType: 1,
answer: 10,
},
{
id: "2",
question: "您愿意推荐其它同事来上这门课程吗?",
minText: "不愿意",
maxText: "非常愿意",
qType: 1,
answer: 2,
},
{
id: "3",
question: "您愿意参加该教师开设的其它课程吗?",
minText: "不愿意",
maxText: "非常愿意",
qType: 1,
answer: 2,
},
{
id: "4",
question: "学员之声(写下您想说的话)",
minText: "",
maxText: "",
qType: 9,
answer: "",
},
],
};
localDialogVideoForm.value.content = Object.assign(
content,
localDialogVideoForm.value.content
);
updateFormValue("content", localDialogVideoForm.value.content);
</script>
<template>
<el-form ref="form" label-width="100px">
<el-form-item label="评估名称">
<el-input
v-model="localDialogVideoForm.name"
placeholder="请输入评估名称"
:disabled="isPreview"
@update:modelValue="(val) => updateFormValue('name', val)"
></el-input>
</el-form-item>
<div style="margin: 0 auto; width: 80%">
<div class="text-center mb10">京东方大学课程评估V2.0</div>
<div class="mb10">
课程满意度计算方式:{{ localDialogVideoForm.content.countType }}
</div>
<div>满意度:{{ localDialogVideoForm.content.countText }}</div>
<hr />
<div v-if="localDialogVideoForm.content.items">
<div
v-for="(ass, assIdx) in localDialogVideoForm.content.items"
:key="assIdx"
>
<div class="assess-info">{{ assIdx + 1 }}.{{ ass.question }}</div>
<div v-if="ass.qType === 1" class="assess-info" style="height: 20px">
<span style="float: left">{{ ass.minText }}</span>
<span style="float: right">{{ ass.maxText }}</span>
</div>
<div v-if="ass.qType === 1" class="assess-info">
<el-radio-group v-model="ass.answer" class="assessRadio1">
<el-radio-button :label="1">1</el-radio-button>
<el-radio-button :label="2">2</el-radio-button>
<el-radio-button :label="3">3</el-radio-button>
<el-radio-button :label="4">4</el-radio-button>
<el-radio-button :label="5">5</el-radio-button>
<el-radio-button :label="6">6</el-radio-button>
<el-radio-button :label="7">7</el-radio-button>
<el-radio-button :label="8">8</el-radio-button>
<el-radio-button :label="9">9</el-radio-button>
<el-radio-button :label="10">10</el-radio-button>
</el-radio-group>
</div>
<div v-if="ass.qType === 9" class="assess-info">
<el-input
type="textarea"
:rows="4"
v-model="ass.answer"
style="width: 100%"
placeholder=""
></el-input>
</div>
</div>
</div>
</div>
</el-form>
</template>
<style scoped lang="scss">
.assess-info {
margin-bottom: 10px;
}
.assessRadio1 {
.el-radio-button {
margin: 0 10px;
//outline: 1px solid #ecf5ff;
:deep(.el-radio-button__inner) {
border-width: 1px;
border-left: var(--el-border);
border-radius: 5px;
}
&.is-active {
:deep(.el-radio-button__inner) {
border-width: 1px;
border-left: var(--el-color-primary);
border-radius: 5px;
}
}
}
}
</style>

View File

@@ -16,6 +16,7 @@ import LinkComp from "@/components/CreatedCourse/preview/LinkComp.vue";
import ScormComp from "@/components/CreatedCourse/preview/ScormComp.vue";
import PaperComp from "@/components/CreatedCourse/preview/PaperComp.vue";
import HomeWorkComp from "@/components/CreatedCourse/preview/HomeWorkComp.vue";
import AccessComp from "@/components/CreatedCourse/preview/AccessComp.vue";
import { getType } from "@/hooks/useCreateCourseMaps";
const mapComponents = [
VideoComp,
@@ -26,6 +27,7 @@ const mapComponents = [
ScormComp,
PaperComp,
HomeWorkComp,
AccessComp,
];
// 使用课程数据hook
@@ -41,6 +43,8 @@ const showTablePreview = ref(false);
const showDialog = ref(false);
const classId = ref("");
const copyChooseItemData = ref({});
watch(
() => courseMetadata.chooseIndex,
(newVal) => {
@@ -93,13 +97,16 @@ const courseOperations = {
showSettingDialog.value = true;
},
addAssessment: () => {
console.log("添加评估功能调用");
courseMetadata.resType = 62;
chooseItemData.value.resType = 62;
showSettingDialog.value = true;
},
};
// 执行课程操作
const executeCourseOperation = (operationName, data) => {
courseMetadata.chooseIndex = data;
courseMetadata.selectionIndex = null;
copyChooseItemData.value = {};
isPreview.value = false;
isNext.value = true;
chooseItemData.value = {};
@@ -123,6 +130,16 @@ const choosePreviewItem = (data) => {
showSettingDialog.value = true;
isPreview.value = true;
};
const cancelSave = () => {
showSettingDialog.value = false;
chooseItemData.value = copyChooseItemData.value;
courseList.value[courseMetadata.chooseIndex].data[
courseMetadata.selectionIndex
] = chooseItemData.value;
console.log(chooseItemData);
};
// 保存
const saveContent = () => {
console.log(chooseItemData.value);
@@ -160,6 +177,7 @@ const settingRow = (data) => {
courseMetadata.chooseIndex = data.index;
courseMetadata.selectionIndex = data.selectionIndex;
chooseItemData.value = data.record;
copyChooseItemData.value = JSON.parse(JSON.stringify(data.record));
isPreview.value = false;
showSettingDialog.value = true;
};
@@ -167,6 +185,7 @@ const previewRow = (data) => {
courseMetadata.chooseIndex = data.index;
courseMetadata.selectionIndex = data.selectionIndex;
chooseItemData.value = data.record;
copyChooseItemData.value = JSON.parse(JSON.stringify(data.record));
isPreview.value = true;
showSettingDialog.value = true;
};
@@ -258,7 +277,7 @@ const chooseCusExam = (data) => {
<template #footer>
<div class="dialog-footer">
<el-button @click="showSettingDialog = false">取消</el-button>
<el-button @click="cancelSave()">取消</el-button>
<el-button type="primary" @click="saveContent()" v-if="!isPreview">
保存
</el-button>