PixelAI-admin/src/views/video/component/upload.vue
2024-12-05 14:58:48 +08:00

342 lines
9.8 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.

<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>
<script setup lang="ts" name="editVideo">
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>