Files
fe-manage/src/views/courselibrary/components/createCourse.vue
陈昱达 10a6028246 fix(courselibrary): 优化删除确认弹窗及调试信息
- 统一使用 $messageBox 替代 ElMessageBox
- 修改确认按钮文字为"确认"
- 删除无用的调试信息展示
- 优化删除提示文案格式
2025-12-12 18:03:00 +08:00

402 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import dragCollapse from "./dragCollapse.vue";
import { ElButton, ElCheckbox, ElDialog } from "element-plus";
import { $message, $messageBox } from "@/utils/useMessage";
import dragTable from "./dragTable.vue";
import { ref, watch } from "vue";
import { getType } from "@/hooks/useCreateCourseMaps";
import { useCourseData } from "@/hooks/useCourseData";
import chooseFileList from "@/components/CreatedCourse/chooseFileList.vue";
import VideoComp from "@/components/CreatedCourse/preview/VideoComp.vue";
import AudioComp from "@/components/CreatedCourse/preview/AudioComp.vue";
import EditorComp from "@/components/CreatedCourse/preview/EditorComp.vue";
import DocComp from "@/components/CreatedCourse/preview/DocComp.vue";
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 SvgIcon from "@/components/SvgIcon.vue";
import { Plus } from "@element-plus/icons-vue";
defineOptions({
name: "CreateCourse",
});
// 组件映射
const mapComponents = [
VideoComp,
AudioComp,
EditorComp,
DocComp,
LinkComp,
ScormComp,
PaperComp,
HomeWorkComp,
AccessComp,
];
// 使用课程数据hook
const { courseMetadata, courseList, courseActionButtons, addChapter } =
useCourseData();
const chooseItemData = ref({});
const copyChooseItemData = ref({});
// 监听课程索引变化更新classId
watch(
() => courseMetadata.chooseIndex,
(newVal) => {
if (courseList.value[newVal]) {
courseMetadata.classId = courseList.value[newVal].id || "";
}
}
);
// 课程操作映射
const courseOperations = {
addVideo: () => {
courseMetadata.resType = 10;
courseMetadata.showDialog = true;
},
addAudio: () => {
courseMetadata.resType = 20;
courseMetadata.showDialog = true;
},
addDocument: () => {
courseMetadata.resType = 40;
courseMetadata.showDialog = true;
courseMetadata.isNext = false;
},
addImageText: () => {
courseMetadata.resType = 41;
chooseItemData.value.resType = 41;
courseMetadata.showSettingDialog = true;
},
addExternalLink: () => {
courseMetadata.resType = 52;
chooseItemData.value.resType = 52;
courseMetadata.showSettingDialog = true;
},
addScorm: () => {
courseMetadata.resType = 50;
courseMetadata.showDialog = true;
courseMetadata.isNext = false;
},
addExam: () => {
courseMetadata.resType = 61;
courseMetadata.showDialog = true;
courseMetadata.isNext = false;
},
addHomework: () => {
courseMetadata.resType = 60;
chooseItemData.value.resType = 60;
courseMetadata.showSettingDialog = true;
},
addAssessment: () => {
courseMetadata.resType = 62;
chooseItemData.value.resType = 62;
courseMetadata.showSettingDialog = true;
},
};
// 执行课程操作
const executeCourseOperation = (operationName, data) => {
courseMetadata.chooseIndex = data;
courseMetadata.selectionIndex = null;
copyChooseItemData.value = {};
courseMetadata.isPreview = false;
courseMetadata.isNext = true;
chooseItemData.value = {};
if (courseOperations[operationName]) {
courseOperations[operationName](data);
} else {
console.warn(`未找到操作: ${operationName}`);
}
};
// 选择项目处理
const chooseItem = (data) => {
chooseItemData.value = data;
// 如果不需要下一步,则直接保存
if (!courseMetadata.isNext) {
saveContent();
return;
}
courseMetadata.showSettingDialog = true;
};
// 预览项目处理
const choosePreviewItem = (data) => {
chooseItemData.value = data;
courseMetadata.showSettingDialog = true;
courseMetadata.isPreview = true;
};
// 取消保存
const cancelSave = () => {
courseMetadata.showSettingDialog = false;
// 恢复原始数据
chooseItemData.value = copyChooseItemData.value;
if (
courseMetadata.chooseIndex !== null &&
courseMetadata.selectionIndex !== null &&
courseList.value[courseMetadata.chooseIndex] &&
courseList.value[courseMetadata.chooseIndex].data[
courseMetadata.selectionIndex
]
) {
courseList.value[courseMetadata.chooseIndex].data[
courseMetadata.selectionIndex
] = chooseItemData.value;
}
};
// 保存内容
const saveContent = () => {
if (courseMetadata.selectionIndex !== null) {
// 更新已有项
if (
courseList.value[courseMetadata.chooseIndex] &&
courseList.value[courseMetadata.chooseIndex].data[
courseMetadata.selectionIndex
]
) {
courseList.value[courseMetadata.chooseIndex].data[
courseMetadata.selectionIndex
] = {
...courseList.value[courseMetadata.chooseIndex].data[
courseMetadata.selectionIndex
],
...chooseItemData.value,
};
}
} else {
// 添加新项
if (courseList.value[courseMetadata.chooseIndex]) {
courseList.value[courseMetadata.chooseIndex].data.push({
resType: courseMetadata.resType,
...chooseItemData.value,
});
}
}
courseMetadata.showDialog = false;
courseMetadata.showSettingDialog = false;
};
// 删除行
const deleteRow = (data) => {
courseMetadata.chooseIndex = data.index;
courseMetadata.selectionIndex = data.selectionIndex;
$messageBox
.confirm(`确定删除【${data.record.name}】吗?`, "删除确认", {
confirmButtonText: "确认",
cancelButtonText: "取消",
type: "error",
})
.then(() => {
$message.success("删除成功");
if (
courseList.value[courseMetadata.chooseIndex] &&
courseList.value[courseMetadata.chooseIndex].data
) {
courseList.value[courseMetadata.chooseIndex].data.splice(
courseMetadata.selectionIndex,
1
);
}
})
.catch(() => {
// 用户取消删除
});
};
// 设置行
const settingRow = (data) => {
courseMetadata.chooseIndex = data.index;
courseMetadata.selectionIndex = data.selectionIndex;
chooseItemData.value = { ...data.record }; // 创建副本避免直接引用
copyChooseItemData.value = JSON.parse(JSON.stringify(data.record));
courseMetadata.isPreview = false;
courseMetadata.showSettingDialog = true;
};
// 预览行
const previewRow = (data) => {
courseMetadata.chooseIndex = data.index;
courseMetadata.selectionIndex = data.selectionIndex;
chooseItemData.value = { ...data.record }; // 创建副本避免直接引用
copyChooseItemData.value = JSON.parse(JSON.stringify(data.record));
courseMetadata.isPreview = true;
courseMetadata.showSettingDialog = true;
};
// 自定义考试
const chooseCusExam = (data) => {
chooseItemData.value = data;
courseMetadata.showSettingDialog = true;
};
// 下一步处理
const handleNext = () => {
$message.success("213");
};
</script>
<template>
<div class="create-course">
<div class="course-header">
<div class="title ml18">课程名称</div>
<span>创建时间{{ courseMetadata.createTime }}</span>
</div>
<div class="course-content">
<div class="course-actions">
<el-button @click="addChapter" :icon="Plus">添加章</el-button>
<el-checkbox class="ml10">顺序学习</el-checkbox>
</div>
<div>
<dragCollapse
v-model:courseList="courseList"
titleKey="title"
:isEdit="true"
>
<!-- <template #title="{ course }">{{ course.title }}</template>-->
<template #desc="{ course }">
若课程只有一个章节将不在学员端显示该章节名称
</template>
<template #default="{ course, index }">
<div class="drag-course-btn-content">
<el-button
v-for="btn in courseActionButtons"
:key="btn.fun"
type="primary"
class="btn-item"
plain
@click="executeCourseOperation(btn.fun, index)"
>
<svg-icon :icon-class="btn.icon" class="mr10"></svg-icon>
{{ btn.label }}
</el-button>
</div>
<div>
<!-- 添加 groupId tableId 属性以支持跨表格拖拽 -->
<dragTable
:data="course.data"
group-id="course-chapters"
:table-id="'chapter-' + index"
:index="index"
@delete="deleteRow"
@setting="settingRow"
@preview="previewRow"
/>
</div>
</template>
</dragCollapse>
</div>
</div>
<!-- 选择文件列表 -->
<el-dialog
v-model="courseMetadata.showDialog"
:title="getType(courseMetadata.resType)"
>
<chooseFileList
v-if="courseMetadata.showDialog"
@chooseItem="chooseItem"
@choosePreviewItem="choosePreviewItem"
:resType="courseMetadata.resType"
:showTablePreview="courseMetadata.showTablePreview"
@chooseCusExam="chooseCusExam"
/>
</el-dialog>
<!-- 设置预览弹窗 -->
<!-- :fullscreen="chooseItemData.resType === 41"-->
<el-dialog
v-model="courseMetadata.showSettingDialog"
:title="
courseMetadata.isPreview ? '预览' : getType(chooseItemData.resType)
"
>
<div class="component-preview">
<template v-for="item in mapComponents" :key="item.name">
<component
v-if="
Number(chooseItemData.resType) === item.resType &&
courseMetadata.showSettingDialog
"
:is="item"
v-model:dialogVideoForm="chooseItemData"
:isPreview="courseMetadata.isPreview"
:classId="courseMetadata.classId"
/>
</template>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancelSave()">取消</el-button>
<el-button
type="primary"
@click="saveContent()"
v-if="!courseMetadata.isPreview"
>
保存
</el-button>
</div>
</template>
</el-dialog>
<div class="p10 pst-s bg-w bottom0">
<el-button>取消</el-button>
<el-button type="primary">存草稿</el-button>
<el-button @click="handleNext" type="primary">下一步</el-button>
</div>
</div>
</template>
<style scoped lang="scss">
.create-course {
width: 100%;
padding: 27px 20px;
.course-header {
display: flex;
justify-content: space-between;
.title {
font-size: 16px;
font-weight: 600;
}
}
.course-actions {
padding: 10px;
display: flex;
align-items: center;
}
.drag-course-btn-content {
padding: 0 10px;
.btn-item + .btn-item {
margin-left: 10px;
}
.btn-item {
background-color: #fff;
border-color: #fff;
color: #639afa;
&:hover {
background-color: #d9ecff;
border-color: #d9ecff;
}
}
}
.component-preview {
max-height: 600px;
overflow: auto;
}
}
</style>