2024-11-24 23:28:56 +08:00
|
|
|
|
<template>
|
|
|
|
|
<div class="layout-pd">
|
|
|
|
|
<el-card v-loading="state.loading" shadow="hover" header="视频详情">
|
|
|
|
|
<el-form ref="videoFormRef" :model="state.data" :rules="state.rules" size="large" label-width="100px" class="mt20 mb20">
|
|
|
|
|
<el-row :gutter="35">
|
|
|
|
|
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
|
|
|
|
<el-form-item label="模块名称:" prop="moduleName">
|
|
|
|
|
<el-select size="default" @change="handleChangeModule" v-model="state.data.moduleName" placeholder="请选择模块" clearable>
|
|
|
|
|
<el-option
|
|
|
|
|
:data-op="item.id"
|
|
|
|
|
v-for="(item, index) in moduleList"
|
|
|
|
|
:key="index"
|
|
|
|
|
:label="item.moduleName"
|
|
|
|
|
:value="item.moduleName"
|
|
|
|
|
></el-option>
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
|
|
|
|
<el-form-item label="标签名称:" prop="labelName">
|
|
|
|
|
<el-select size="default" v-model="state.data.labelName" placeholder="请选择标签" clearable class="ml10">
|
|
|
|
|
<el-option v-for="(item, index) in labelList" :key="index" :label="item.name" :value="item.name"></el-option>
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
|
|
|
|
<el-form-item label="视频名称:" prop="name">
|
|
|
|
|
<el-input v-model="state.data.name" placeholder="请输入标题" clearable></el-input>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
|
|
|
|
<el-form-item label="视频:" prop="path" class="coverImg">
|
|
|
|
|
<!-- 上传文件 -->
|
|
|
|
|
<el-upload
|
|
|
|
|
ref="uploadRef"
|
|
|
|
|
class="h100 personal-user-left-upload"
|
|
|
|
|
action="#"
|
|
|
|
|
list-type="picture-card"
|
|
|
|
|
:file-list="state.fileArray"
|
|
|
|
|
:auto-upload="false"
|
|
|
|
|
:limit="1"
|
|
|
|
|
:class="{ hide: state.coverHide }"
|
|
|
|
|
@change="handleUploadChange"
|
|
|
|
|
accept="video/*"
|
|
|
|
|
>
|
|
|
|
|
<template #default>
|
|
|
|
|
<el-icon><Plus /></el-icon>
|
|
|
|
|
</template>
|
|
|
|
|
<template #file="{ file }">
|
|
|
|
|
<div>
|
|
|
|
|
<!-- class="el-upload-list__item-thumbnail" -->
|
|
|
|
|
<video style="width: 100%; height: auto; border-radius: 4px" :src="file.url"></video>
|
|
|
|
|
<span class="el-upload-list__item-actions">
|
|
|
|
|
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
|
|
|
|
|
<el-icon><zoom-in /></el-icon>
|
|
|
|
|
</span>
|
|
|
|
|
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file)">
|
|
|
|
|
<el-icon><Delete /></el-icon>
|
|
|
|
|
</span>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</el-upload>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<el-row class="flex mt15">
|
|
|
|
|
<div class="flex-margin" style="width: 100%; display: flex; justify-content: flex-end">
|
|
|
|
|
<el-button size="larger" type="info" @click="cancel">
|
|
|
|
|
<SvgIcon name="ele-RefreshLeft" />
|
|
|
|
|
取消
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-button size="larger" type="primary" @click="onSubmitForm">
|
|
|
|
|
<SvgIcon name="iconfont icon-shuxing" />
|
|
|
|
|
保存
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</el-row>
|
|
|
|
|
</el-form>
|
|
|
|
|
</el-card>
|
|
|
|
|
<!-- 视频预览弹窗 -->
|
|
|
|
|
<el-dialog v-model="dialogVisible">
|
|
|
|
|
<video style="width: 100%; height: auto; border-radius: 4px" :src="dialogVideoUrl" controls></video>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
2024-12-05 14:58:48 +08:00
|
|
|
|
<script setup lang="ts" name="editVideo">
|
2024-11-24 23:28:56 +08:00
|
|
|
|
import { onMounted, reactive, ref } from 'vue';
|
|
|
|
|
import { articleApi } from '/@/api/article';
|
|
|
|
|
import { videoApi } from '/@/api/video';
|
|
|
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
|
import { ElMessage, UploadFile, UploadFiles } from 'element-plus';
|
|
|
|
|
import { Delete, Plus, ZoomIn } from '@element-plus/icons-vue';
|
|
|
|
|
import mittBus from '/@/utils/mitt';
|
|
|
|
|
|
|
|
|
|
// 视频基本路径
|
|
|
|
|
const viteUrl = import.meta.env.VITE_API_URL;
|
|
|
|
|
|
|
|
|
|
// 引入 api 请求接口
|
|
|
|
|
const artApi = articleApi();
|
|
|
|
|
const vidApi = videoApi();
|
|
|
|
|
|
|
|
|
|
// 模块列表
|
|
|
|
|
const moduleList = ref<{ id: number; moduleName: string }[]>([]);
|
|
|
|
|
|
|
|
|
|
// 标签列表
|
|
|
|
|
const labelList = ref<{ name: string }[]>([]);
|
|
|
|
|
|
|
|
|
|
// 获取视频id
|
|
|
|
|
const route = useRoute();
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
const moduleName: any = route.query.moduleName;
|
|
|
|
|
const labelName: any = route.query.labelName;
|
|
|
|
|
const id: any = route.query.id;
|
|
|
|
|
|
|
|
|
|
const state = reactive({
|
|
|
|
|
data: {
|
|
|
|
|
labelName: '',
|
|
|
|
|
moduleName: '',
|
|
|
|
|
name: '',
|
|
|
|
|
path: '',
|
|
|
|
|
},
|
|
|
|
|
loading: false,
|
|
|
|
|
rules: {
|
|
|
|
|
moduleName: { required: true, message: '请选择模块', trigger: 'blur' },
|
|
|
|
|
labelName: { required: true, message: '请输入标签名称', trigger: 'blur' },
|
|
|
|
|
name: { required: true, message: '请输入标题', trigger: 'blur' },
|
|
|
|
|
path: { required: true, message: '请上传视频', trigger: 'blur' },
|
|
|
|
|
},
|
|
|
|
|
fileArray: [], // 编辑进来时,如果已经上传了视频,则保存视频地址
|
|
|
|
|
coverFile: {},
|
|
|
|
|
coverHide: false,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 模块选择
|
|
|
|
|
const handleChangeModule = async (val: any) => {
|
|
|
|
|
try {
|
|
|
|
|
state.data.labelName = '';
|
|
|
|
|
if (!val) {
|
|
|
|
|
labelList.value = [];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const op: any = event?.currentTarget;
|
|
|
|
|
let res = await artApi.getLabelList(op.dataset.op);
|
|
|
|
|
if (res?.success) {
|
|
|
|
|
labelList.value = res.data;
|
|
|
|
|
} else {
|
|
|
|
|
ElMessage.error('标签列表获取失败!');
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error('标签列表获取失败!');
|
|
|
|
|
} finally {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取视频详情
|
|
|
|
|
const getVideoDetail = async () => {
|
|
|
|
|
try {
|
|
|
|
|
state.loading = true;
|
|
|
|
|
let res = await vidApi.getVideoList({
|
|
|
|
|
moduleName: moduleName,
|
|
|
|
|
labelName: labelName,
|
|
|
|
|
size: 1,
|
|
|
|
|
current: 1,
|
|
|
|
|
});
|
|
|
|
|
if (res?.success) {
|
|
|
|
|
state.data = res.data.records[0];
|
|
|
|
|
// 下面这里处理一下,因为后端返回的是0和1,而前端需要的是true和false,到时候提交的时候再转换回来
|
|
|
|
|
// 这个报错没关系的,只是ts的语法检查,不影响运行
|
|
|
|
|
if (state.data.path) {
|
|
|
|
|
const never: any = [{ name: state.data.name, url: viteUrl + state.data.path }];
|
|
|
|
|
state.fileArray = never;
|
|
|
|
|
state.coverHide = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error('获取视频详情失败');
|
|
|
|
|
} finally {
|
|
|
|
|
state.loading = false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取视频详情-根据id
|
|
|
|
|
const getVideoDetailById = async (id: number) => {
|
|
|
|
|
try {
|
|
|
|
|
state.loading = true;
|
|
|
|
|
let res = await vidApi.getVideoDetail(id);
|
|
|
|
|
if (res?.success) {
|
|
|
|
|
state.data = res.data;
|
|
|
|
|
// 下面这里处理一下,因为后端返回的是0和1,而前端需要的是true和false,到时候提交的时候再转换回来
|
|
|
|
|
// 这个报错没关系的,只是ts的语法检查,不影响运行
|
|
|
|
|
state.data.moduleName = moduleName;
|
|
|
|
|
state.data.labelName = labelName;
|
|
|
|
|
if (state.data.path) {
|
|
|
|
|
const never: any = [{ name: state.data.name, url: viteUrl + state.data.path }];
|
|
|
|
|
state.fileArray = never;
|
|
|
|
|
state.coverHide = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error('获取视频详情失败');
|
|
|
|
|
} finally {
|
|
|
|
|
state.loading = false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取模块列表
|
|
|
|
|
const getModuleList = async () => {
|
|
|
|
|
try {
|
|
|
|
|
let res = await artApi.getModuleList();
|
|
|
|
|
if (res?.success) {
|
|
|
|
|
moduleList.value = res.data;
|
|
|
|
|
} else {
|
|
|
|
|
ElMessage.error('模块列表获取失败!');
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error('模块列表获取失败!');
|
|
|
|
|
} finally {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const videoFormRef = ref();
|
|
|
|
|
|
|
|
|
|
// 保存视频,在新增视频时不会调用以下函数
|
|
|
|
|
const onSubmitForm = () => {
|
|
|
|
|
videoFormRef.value.validate((valid: boolean) => {
|
|
|
|
|
if (valid && state.coverHide) {
|
|
|
|
|
const form = { ...state.data };
|
|
|
|
|
if (state.coverFile.type === undefined) {
|
|
|
|
|
realSubmit(form);
|
|
|
|
|
} else {
|
|
|
|
|
uploadFile(state.coverFile, form);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ElMessage.error('请完善信息!');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 返回
|
|
|
|
|
const cancel = () => {
|
|
|
|
|
mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
|
|
|
|
|
router.push('/video');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 上传文件
|
|
|
|
|
const uploadFile = async (file: any, form: any) => {
|
|
|
|
|
try {
|
|
|
|
|
state.loading = true;
|
|
|
|
|
const formdata = new FormData();
|
|
|
|
|
formdata.append('file', file);
|
|
|
|
|
formdata.append('type', 'video');
|
|
|
|
|
|
|
|
|
|
let res = await vidApi.uploadFileType(formdata);
|
|
|
|
|
if (res?.success) {
|
|
|
|
|
form.path = res.data;
|
|
|
|
|
realSubmit(form);
|
|
|
|
|
} else {
|
|
|
|
|
ElMessage.error('视频上传失败!');
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
state.loading = false;
|
|
|
|
|
ElMessage.error('视频上传失败!');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 视频上传-真正的上传操作
|
|
|
|
|
const realSubmit = async (form: any) => {
|
|
|
|
|
try {
|
|
|
|
|
state.loading = true;
|
|
|
|
|
let res = route.path == '/video/add' ? await vidApi.saveVideo(form) : await vidApi.updateVideo(form);
|
|
|
|
|
if (res?.success) {
|
|
|
|
|
ElMessage.success('视频保存成功!');
|
|
|
|
|
cancel();
|
|
|
|
|
} else {
|
|
|
|
|
ElMessage.error('视频保存失败!');
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error('处理失败!');
|
|
|
|
|
} finally {
|
|
|
|
|
state.loading = false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 视频上传禁用
|
|
|
|
|
const disabled = ref(false);
|
|
|
|
|
// 视频弹窗
|
|
|
|
|
const dialogVideoUrl = ref('');
|
|
|
|
|
const dialogVisible = ref(false);
|
|
|
|
|
|
|
|
|
|
const uploadRef = ref();
|
|
|
|
|
|
|
|
|
|
// 视频删除
|
|
|
|
|
const handleRemove = (file: UploadFile) => {
|
|
|
|
|
state.coverFile = {};
|
|
|
|
|
uploadRef.value.clearFiles();
|
|
|
|
|
state.coverHide = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 视频预览
|
|
|
|
|
const handlePictureCardPreview = (file: UploadFile) => {
|
|
|
|
|
dialogVideoUrl.value = file.url!;
|
|
|
|
|
dialogVisible.value = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 视频更改
|
|
|
|
|
const handleUploadChange = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
|
|
|
|
|
if (uploadFile.raw && uploadFile.raw.type.includes('video')) {
|
|
|
|
|
const file: any = uploadFile.raw;
|
|
|
|
|
state.coverFile = file;
|
|
|
|
|
state.data.path = file.name;
|
|
|
|
|
state.coverHide = true;
|
|
|
|
|
} else {
|
|
|
|
|
ElMessage.error('请上传视频文件!');
|
|
|
|
|
uploadRef.value.clearFiles();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
if (moduleName && labelName && route.path == '/video/edit') {
|
|
|
|
|
if (moduleName && moduleName !== '人才模块' && moduleName !== '简历模块') {
|
|
|
|
|
getVideoDetailById(id);
|
|
|
|
|
} else {
|
|
|
|
|
getVideoDetail();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
getModuleList();
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.coverImg :deep(.hide .el-upload--picture-card) {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.el-upload-list--picture-card .el-upload-list__item){
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|