mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/fe-manage.git
synced 2025-12-06 09:26:44 +08:00
feat(course): 添加SCORM文件预览功能
- 在chooseFileList组件中增加SCORM文件的预览按钮及逻辑处理 - 新增ScormComp.vue组件用于展示SCORM内容 - 更新createCourse.vue以支持SCORM类型的添加与预览操作 - 调整dragTable.vue中的显示控制逻辑,适配SCORM类型 - 修改useCreateCourseMaps.js中SCORM类型的名称为大写格式 - 扩展上传文件类型判断和相关参数传递逻辑 - 优化代码结构和可读性,确保SCORM资源正确加载和显示
This commit is contained in:
@@ -2,7 +2,11 @@
|
||||
import { reactive, onMounted, ref, h } from "vue";
|
||||
import { ElButton, ElInput, ElUpload, ElMessage } from "element-plus";
|
||||
import BasicTable from "@/components/BasicElTable/BasicTable.vue";
|
||||
import { getPageListByType, getType, getMapsItem } from "@/hooks/useCreateCourseMaps";
|
||||
import {
|
||||
getPageListByType,
|
||||
getType,
|
||||
getMapsItem,
|
||||
} from "@/hooks/useCreateCourseMaps";
|
||||
import apiCourseFile from "@/api/modules/courseFile";
|
||||
import { useRoute } from "vue-router";
|
||||
import Cookies from "vue-cookies";
|
||||
@@ -83,6 +87,20 @@ const columns = [
|
||||
width: 150,
|
||||
render: (params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
ElButton,
|
||||
{
|
||||
type: "primary",
|
||||
size: "small",
|
||||
style: {
|
||||
display: [40, 50, 62].includes(props.resType) ? "" : "none",
|
||||
},
|
||||
onClick: () => {
|
||||
handlePreviewItem(params.row);
|
||||
},
|
||||
},
|
||||
"预览"
|
||||
),
|
||||
h(
|
||||
ElButton,
|
||||
{
|
||||
@@ -100,7 +118,7 @@ const columns = [
|
||||
];
|
||||
|
||||
// 事件发射
|
||||
const emit = defineEmits(["chooseItem"]);
|
||||
const emit = defineEmits(["chooseItem", "choosePreviewItem"]);
|
||||
|
||||
// 处理选择项目
|
||||
const handleChooseItem = (row) => {
|
||||
@@ -110,9 +128,20 @@ const handleChooseItem = (row) => {
|
||||
completeSetup: 0,
|
||||
setupTage: "",
|
||||
resType: props.resType,
|
||||
dir: props.resType === 50 ? "scorm" : "course",
|
||||
});
|
||||
};
|
||||
|
||||
const handlePreviewItem = (row) => {
|
||||
emit("choosePreviewItem", {
|
||||
...row,
|
||||
isDrag: false,
|
||||
completeSetup: 0,
|
||||
setupTage: "",
|
||||
resType: props.resType,
|
||||
dir: props.resType === 50 ? "scorm" : "course",
|
||||
});
|
||||
};
|
||||
// 分页改变处理
|
||||
const changePagination = (PAGINATION) => {
|
||||
Object.assign(pagination, PAGINATION);
|
||||
@@ -128,7 +157,7 @@ const getVideoList = () => {
|
||||
pageIndex: pagination.current,
|
||||
self: true,
|
||||
};
|
||||
|
||||
|
||||
getPageListByType(paramsData).then((res) => {
|
||||
loading.value = false;
|
||||
tableData.value = res.result.list;
|
||||
@@ -136,15 +165,6 @@ const getVideoList = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// 选择项目处理
|
||||
const chooseItem = () => {
|
||||
showDialog.value = false;
|
||||
emit("chooseItem", {
|
||||
...dialogVideoForm,
|
||||
type: props.resType,
|
||||
});
|
||||
};
|
||||
|
||||
// 上传成功处理
|
||||
const handleUploadSuccess = (res, file) => {
|
||||
if (res.status === 200) {
|
||||
@@ -160,7 +180,7 @@ const handleUploadSuccess = (res, file) => {
|
||||
duration: routeQuery.duration,
|
||||
remark: "课程中直接上传",
|
||||
};
|
||||
|
||||
|
||||
apiCourseFile.saveUpload(courseWare).then((rs) => {
|
||||
if (rs.status === 200) {
|
||||
emit("chooseItem", {
|
||||
@@ -183,39 +203,46 @@ const handleBeforeUpload = (file) => {
|
||||
ElMessage({ message: `文件格式不正确!`, type: "error", offset: 100 });
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
let fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
|
||||
fileExtension = fileExtension.toLowerCase();
|
||||
|
||||
|
||||
// 校检文件类型
|
||||
if (getMapsItem(props.resType).fileType.join(",").indexOf(fileExtension) === -1) {
|
||||
if (
|
||||
getMapsItem(props.resType).fileType.join(",").indexOf(fileExtension) === -1
|
||||
) {
|
||||
ElMessage({
|
||||
message: `文件格式不正确, 请上传正确格式的${getMapsItem(props.resType).name}文件!`,
|
||||
message: `文件格式不正确, 请上传正确格式的${
|
||||
getMapsItem(props.resType).name
|
||||
}文件!`,
|
||||
type: "error",
|
||||
offset: 100,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 校检文件大小
|
||||
if (getMapsItem(props.resType).uploadSize) {
|
||||
const isLt = file.size / 1024 / 1024 < getMapsItem(props.resType).uploadSize;
|
||||
const isLt =
|
||||
file.size / 1024 / 1024 < getMapsItem(props.resType).uploadSize;
|
||||
if (!isLt) {
|
||||
ElMessage({
|
||||
message: `上传文件大小不能超过 ${getMapsItem(props.resType).uploadSize} !`,
|
||||
message: `上传文件大小不能超过 ${
|
||||
getMapsItem(props.resType).uploadSize
|
||||
} !`,
|
||||
type: "error",
|
||||
offset: 100,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (props.resType === 50) {
|
||||
dialogVideoForm.dir = "scorm";
|
||||
} else {
|
||||
dialogVideoForm.dir = "course";
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -237,7 +264,9 @@ onMounted(() => {
|
||||
:file-list="fileList"
|
||||
:before-upload="handleBeforeUpload"
|
||||
>
|
||||
<el-button v-if="[10, 20, 40].includes(props.resType)" type="primary"
|
||||
<el-button
|
||||
v-if="[10, 20, 40, 50].includes(props.resType)"
|
||||
type="primary"
|
||||
>上传新{{ getType(props.resType) }}</el-button
|
||||
>
|
||||
</el-upload>
|
||||
@@ -282,4 +311,4 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
70
src/components/CreatedCourse/preview/ScormComp.vue
Normal file
70
src/components/CreatedCourse/preview/ScormComp.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<script setup>
|
||||
import { ElForm, ElFormItem, ElInput } from "element-plus";
|
||||
import { onMounted, ref } from "vue";
|
||||
import apiCourseFile from "@/api/modules/courseFile";
|
||||
defineOptions({
|
||||
resType: 50,
|
||||
});
|
||||
const props = defineProps({
|
||||
dialogVideoForm: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
name: "",
|
||||
filePath: "",
|
||||
isDrag: true,
|
||||
completeSetup: 0,
|
||||
setupTage: 0,
|
||||
openType: "",
|
||||
}),
|
||||
},
|
||||
isPreview: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const path = process.env.VUE_APP_BOE_API_URL;
|
||||
const scormUrl = ref("");
|
||||
|
||||
import { useMediaComponent } from "@/hooks/useMediaComponent";
|
||||
// Emit updates to parent component
|
||||
const emit = defineEmits(["update:dialogVideoForm"]);
|
||||
|
||||
// 使用hook处理公共逻辑
|
||||
const { localDialogVideoForm, updateFormValue, fileBaseUrl } =
|
||||
useMediaComponent(props, emit);
|
||||
|
||||
const loadScormFile = () => {
|
||||
console.log(localDialogVideoForm.value);
|
||||
apiCourseFile.detail(localDialogVideoForm.value.id).then((rs) => {
|
||||
if (rs.status === 200) {
|
||||
localDialogVideoForm.value.dir = "scorm";
|
||||
let urlPre = window.location.protocol;
|
||||
let configUrl = `https:${path}/newscorm/scorm-player`;
|
||||
configUrl = urlPre + configUrl.substring(configUrl.indexOf(":") + 1);
|
||||
scormUrl.value = configUrl + "?r=1&mode=preview&scormId=" + rs.result.id;
|
||||
}
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
loadScormFile();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-form label-position="right" label-width="100px">
|
||||
<el-form-item label="名称">
|
||||
<el-input
|
||||
v-model="localDialogVideoForm.name"
|
||||
:disabled="isPreview"
|
||||
@update:modelValue="(val) => updateFormValue('name', val)"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<iframe
|
||||
style="width: 100%; max-height: 500px; overflow: auto"
|
||||
:src="scormUrl"
|
||||
frameborder="0"
|
||||
></iframe>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -67,7 +67,7 @@ const contentTypeMaps = [
|
||||
},
|
||||
{
|
||||
type: 50,
|
||||
name: "scorm",
|
||||
name: "SCORM",
|
||||
icon: "icon-file",
|
||||
// 1G B
|
||||
uploadSize: 1024 * 1024 * 1024,
|
||||
|
||||
@@ -13,8 +13,16 @@ 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 { getType } from "@/hooks/useCreateCourseMaps";
|
||||
const mapComponents = [VideoComp, AudioComp, EditorComp, DocComp, LinkComp];
|
||||
const mapComponents = [
|
||||
VideoComp,
|
||||
AudioComp,
|
||||
EditorComp,
|
||||
DocComp,
|
||||
LinkComp,
|
||||
ScormComp,
|
||||
];
|
||||
|
||||
// 使用课程数据hook
|
||||
const { courseMetadata, courseList, courseActionButtons, addChapter } =
|
||||
@@ -52,7 +60,9 @@ const courseOperations = {
|
||||
showSettingDialog.value = true;
|
||||
},
|
||||
addScorm: () => {
|
||||
console.log("添加SCORM功能调用");
|
||||
courseMetadata.resType = 50;
|
||||
showDialog.value = true;
|
||||
isNext.value = false;
|
||||
},
|
||||
addExam: () => {
|
||||
console.log("添加考试功能调用");
|
||||
@@ -69,6 +79,7 @@ const executeCourseOperation = (operationName, data) => {
|
||||
courseMetadata.chooseIndex = data;
|
||||
courseMetadata.selectionIndex = null;
|
||||
isPreview.value = false;
|
||||
isNext.value = true;
|
||||
chooseItemData.value = {};
|
||||
if (courseOperations[operationName]) {
|
||||
courseOperations[operationName](data);
|
||||
@@ -77,6 +88,7 @@ const executeCourseOperation = (operationName, data) => {
|
||||
}
|
||||
};
|
||||
const chooseItem = (data) => {
|
||||
console.log(data);
|
||||
chooseItemData.value = data;
|
||||
if (!isNext.value) {
|
||||
saveContent();
|
||||
@@ -84,6 +96,11 @@ const chooseItem = (data) => {
|
||||
}
|
||||
showSettingDialog.value = true;
|
||||
};
|
||||
const choosePreviewItem = (data) => {
|
||||
chooseItemData.value = data;
|
||||
showSettingDialog.value = true;
|
||||
isPreview.value = true;
|
||||
};
|
||||
// 保存
|
||||
const saveContent = () => {
|
||||
if (courseMetadata.selectionIndex !== null) {
|
||||
@@ -180,6 +197,7 @@ const previewRow = (data) => {
|
||||
<chooseFileList
|
||||
v-if="showDialog"
|
||||
@chooseItem="chooseItem"
|
||||
@choosePreviewItem="choosePreviewItem"
|
||||
:resType="courseMetadata.resType"
|
||||
:showTablePreview="showTablePreview"
|
||||
></chooseFileList>
|
||||
|
||||
@@ -239,7 +239,7 @@ const renderActionColumn = () => {
|
||||
href: "javascript:void(0)",
|
||||
onClick: () => handleSetting(index, record),
|
||||
style: {
|
||||
display: [40].includes(record.resType) ? "none" : "",
|
||||
display: [40, 50].includes(record.resType) ? "none" : "",
|
||||
},
|
||||
},
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user