mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/fe-manage.git
synced 2025-12-09 19:06:45 +08:00
feat(hooks): 添加媒体组件通用hook
- 创建 useMediaComponent hook 处理媒体组件公共逻辑 - 实现本地表单数据响应式拷贝与深度监听更新 - 提供表单字段更新方法并触发事件通知 - 定义文件基础URL常量便于统一管理 - 支持 dialogVideoForm 属性的双向绑定更新 - 集成 Vue Composition API 的 ref 和 watch 功能
This commit is contained in:
@@ -1,10 +1,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, onMounted, ref, h, watch } from "vue";
|
import { reactive, onMounted, ref, h } from "vue";
|
||||||
import { ElButton, ElInput, ElUpload } from "element-plus";
|
import { ElButton, ElInput, ElUpload, ElMessage } from "element-plus";
|
||||||
import BasicTable from "@/components/BasicElTable/BasicTable.vue";
|
import BasicTable from "@/components/BasicElTable/BasicTable.vue";
|
||||||
import { getPageListByType } from "@/hooks/useCreateCourseMaps";
|
import { getPageListByType, getType, getMapsItem } from "@/hooks/useCreateCourseMaps";
|
||||||
import { getType, getMapsItem } from "@/hooks/useCreateCourseMaps";
|
import apiCourseFile from "@/api/modules/courseFile";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
import Cookies from "vue-cookies";
|
import Cookies from "vue-cookies";
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
resType: {
|
resType: {
|
||||||
type: Number,
|
type: Number,
|
||||||
@@ -12,25 +15,45 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 响应式数据
|
||||||
const tableData = ref([]);
|
const tableData = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
const showDialog = ref(false);
|
||||||
|
const fileList = ref([]);
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
name: "",
|
name: "",
|
||||||
resType: props.resType,
|
resType: props.resType,
|
||||||
});
|
});
|
||||||
let pagination = reactive({
|
|
||||||
|
// 分页配置
|
||||||
|
const pagination = reactive({
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
current: 1,
|
current: 1,
|
||||||
total: 0,
|
total: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 视频表单数据
|
||||||
const dialogVideoForm = reactive({
|
const dialogVideoForm = reactive({
|
||||||
name: "",
|
name: "",
|
||||||
isDrag: false,
|
isDrag: false,
|
||||||
completeSetup: 0,
|
completeSetup: 0,
|
||||||
setupTage: "",
|
setupTage: "",
|
||||||
});
|
});
|
||||||
const loading = ref(false);
|
|
||||||
const showDialog = ref(false);
|
// 上传配置
|
||||||
const emit = defineEmits(["chooseItem"]);
|
const uploadData = reactive({
|
||||||
|
headers: {
|
||||||
|
"XBOE-Access-Token": Cookies.get("token"),
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
dir: "course",
|
||||||
|
},
|
||||||
|
actionUrl: process.env.VUE_APP_SYS_API + "/xboe/sys/xuploader/file/upload",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: "序号",
|
title: "序号",
|
||||||
@@ -66,13 +89,7 @@ const columns = [
|
|||||||
type: "primary",
|
type: "primary",
|
||||||
size: "small",
|
size: "small",
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
emit("chooseItem", {
|
handleChooseItem(params.row);
|
||||||
...params.row,
|
|
||||||
isDrag: false,
|
|
||||||
completeSetup: 0,
|
|
||||||
setupTage: "",
|
|
||||||
resType: props.resType,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"选择"
|
"选择"
|
||||||
@@ -82,18 +99,36 @@ const columns = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// 事件发射
|
||||||
|
const emit = defineEmits(["chooseItem"]);
|
||||||
|
|
||||||
|
// 处理选择项目
|
||||||
|
const handleChooseItem = (row) => {
|
||||||
|
emit("chooseItem", {
|
||||||
|
...row,
|
||||||
|
isDrag: false,
|
||||||
|
completeSetup: 0,
|
||||||
|
setupTage: "",
|
||||||
|
resType: props.resType,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页改变处理
|
||||||
const changePagination = (PAGINATION) => {
|
const changePagination = (PAGINATION) => {
|
||||||
pagination = PAGINATION;
|
Object.assign(pagination, PAGINATION);
|
||||||
getVideoList();
|
getVideoList();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取视频列表
|
||||||
const getVideoList = () => {
|
const getVideoList = () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
let paramsData = {
|
const paramsData = {
|
||||||
...form,
|
...form,
|
||||||
pageSize: pagination.pageSize,
|
pageSize: pagination.pageSize,
|
||||||
pageIndex: pagination.current,
|
pageIndex: pagination.current,
|
||||||
self: true,
|
self: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
getPageListByType(paramsData).then((res) => {
|
getPageListByType(paramsData).then((res) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
tableData.value = res.result.list;
|
tableData.value = res.result.list;
|
||||||
@@ -101,7 +136,8 @@ const getVideoList = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const chooseItem = (type) => {
|
// 选择项目处理
|
||||||
|
const chooseItem = () => {
|
||||||
showDialog.value = false;
|
showDialog.value = false;
|
||||||
emit("chooseItem", {
|
emit("chooseItem", {
|
||||||
...dialogVideoForm,
|
...dialogVideoForm,
|
||||||
@@ -109,29 +145,81 @@ const chooseItem = (type) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const uploadData = reactive({
|
// 上传成功处理
|
||||||
headers: {
|
const handleUploadSuccess = (res, file) => {
|
||||||
"XBOE-Access-Token": Cookies.get("token"),
|
if (res.status === 200) {
|
||||||
},
|
// 上传到课件库
|
||||||
data: {
|
const routeQuery = route.query;
|
||||||
dir: "course",
|
const courseWare = {
|
||||||
},
|
fileName: res.result.displayName,
|
||||||
actionUrl: process.env.VUE_APP_SYS_API + "/xboe/sys/xuploader/file/upload",
|
fileType: res.result.fileType,
|
||||||
});
|
filePath: res.result.filePath,
|
||||||
|
resType: props.resType,
|
||||||
|
orgId: routeQuery.orgId,
|
||||||
|
orgName: routeQuery.orgName,
|
||||||
|
duration: routeQuery.duration,
|
||||||
|
remark: "课程中直接上传",
|
||||||
|
};
|
||||||
|
|
||||||
const fileList = ref([]);
|
apiCourseFile.saveUpload(courseWare).then((rs) => {
|
||||||
const uploadSuccess = (result) => {
|
if (rs.status === 200) {
|
||||||
if (result.status === 200) {
|
|
||||||
emit("chooseItem", {
|
emit("chooseItem", {
|
||||||
...dialogVideoForm,
|
...dialogVideoForm,
|
||||||
name: result.result.displayName,
|
name: res.result.displayName,
|
||||||
resType: props.resType,
|
resType: props.resType,
|
||||||
...result.result,
|
...rs.result,
|
||||||
});
|
});
|
||||||
fileList.value = [];
|
fileList.value = [];
|
||||||
|
} else {
|
||||||
|
ElMessage.error(rs.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 上传前处理
|
||||||
|
const handleBeforeUpload = (file) => {
|
||||||
|
if (file.name.lastIndexOf(".") === -1) {
|
||||||
|
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) {
|
||||||
|
ElMessage({
|
||||||
|
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;
|
||||||
|
if (!isLt) {
|
||||||
|
ElMessage({
|
||||||
|
message: `上传文件大小不能超过 ${getMapsItem(props.resType).uploadSize} !`,
|
||||||
|
type: "error",
|
||||||
|
offset: 100,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.resType === 50) {
|
||||||
|
dialogVideoForm.dir = "scorm";
|
||||||
|
} else {
|
||||||
|
dialogVideoForm.dir = "course";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 生命周期
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getVideoList();
|
getVideoList();
|
||||||
});
|
});
|
||||||
@@ -145,8 +233,9 @@ onMounted(() => {
|
|||||||
:action="uploadData.actionUrl"
|
:action="uploadData.actionUrl"
|
||||||
:headers="uploadData.headers"
|
:headers="uploadData.headers"
|
||||||
:data="uploadData.data"
|
:data="uploadData.data"
|
||||||
:on-success="uploadSuccess"
|
:on-success="handleUploadSuccess"
|
||||||
:file-list="fileList"
|
: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].includes(props.resType)" type="primary"
|
||||||
>上传新{{ getType(props.resType) }}</el-button
|
>上传新{{ getType(props.resType) }}</el-button
|
||||||
|
|||||||
34
src/hooks/useMediaComponent.js
Normal file
34
src/hooks/useMediaComponent.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { ref, watch } from "vue";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用媒体组件hook,用于处理媒体组件的公共逻辑
|
||||||
|
* @param {Object} props - 组件props
|
||||||
|
* @param {Function} emit - 组件emit函数
|
||||||
|
*/
|
||||||
|
export function useMediaComponent(props, emit) {
|
||||||
|
// Create a reactive copy of the prop for local modifications
|
||||||
|
const localDialogVideoForm = ref({ ...props.dialogVideoForm });
|
||||||
|
|
||||||
|
// Watch for changes in the prop and update the local copy
|
||||||
|
watch(
|
||||||
|
() => props.dialogVideoForm,
|
||||||
|
(newVal) => {
|
||||||
|
Object.assign(localDialogVideoForm.value, newVal);
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update form values and emit changes
|
||||||
|
const updateFormValue = (field, value) => {
|
||||||
|
localDialogVideoForm.value[field] = value;
|
||||||
|
emit("update:dialogVideoForm", { ...localDialogVideoForm.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
const fileBaseUrl = "http://home.hzer.xyz:9960/upload";
|
||||||
|
|
||||||
|
return {
|
||||||
|
localDialogVideoForm,
|
||||||
|
updateFormValue,
|
||||||
|
fileBaseUrl,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -66,6 +66,7 @@ const executeCourseOperation = (operationName, data) => {
|
|||||||
courseMetadata.chooseIndex = data;
|
courseMetadata.chooseIndex = data;
|
||||||
courseMetadata.selectionIndex = null;
|
courseMetadata.selectionIndex = null;
|
||||||
isPreview.value = false;
|
isPreview.value = false;
|
||||||
|
chooseItemData.value = {};
|
||||||
if (courseOperations[operationName]) {
|
if (courseOperations[operationName]) {
|
||||||
courseOperations[operationName](data);
|
courseOperations[operationName](data);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -149,7 +149,6 @@ const renderIndexColumn = () => {
|
|||||||
// 渲染名称列
|
// 渲染名称列
|
||||||
const renderNameColumn = () => {
|
const renderNameColumn = () => {
|
||||||
return ({ record }) => {
|
return ({ record }) => {
|
||||||
console.log(record);
|
|
||||||
// 如果处于编辑状态,显示输入框和确认按钮
|
// 如果处于编辑状态,显示输入框和确认按钮
|
||||||
if (record.isEdit) {
|
if (record.isEdit) {
|
||||||
return h(
|
return h(
|
||||||
|
|||||||
Reference in New Issue
Block a user