浏览代码

培训管理-添加编辑视频 暂存

cxmo 10 月之前
父节点
当前提交
a4c2da8a07

+ 28 - 1
src/views/training_manage/hooks/use-video.js

@@ -25,6 +25,14 @@ export function useVideo(){
         })
         return arr
     }
+    //获取视频分类路径
+    function getDataClassify(classify,classifyArr=[]){
+        classifyArr.push(classify.ClassifyName)
+        if(classify.Children&&classify.Children.length){
+            return getDataClassify(classify.Children[0],classifyArr)
+        }
+        return classifyArr
+    }
 
     let tagList = ref([])
     function getTagList(keyword=''){
@@ -38,8 +46,27 @@ export function useVideo(){
         })
     }
 
+    let previewPop = ref(false)
+    let previewVideo = ref(null)
+    let previewVideoUrl = ref('')
+    let previewPopTitle = ref('')
+    function handlePreviewVideo(data){
+        if(!data.VideoUrl) return
+        previewVideo.value?.play()
+        previewPopTitle.value = data.Title||'暂无标题'
+        previewVideoUrl.value = data.VideoUrl
+        previewPop.value = true
+    }
+    // 结束预览弹窗关闭回调 -- 暂停视频
+    function endingPreview(){
+        previewVideo.value?.pause()
+    }
+
     return {
         classifyList,getClassifyList,
-        tagList,getTagList
+        tagList,getTagList,
+        getDataClassify,
+        previewPop,previewVideo,previewVideoUrl,previewPopTitle,
+        handlePreviewVideo,endingPreview
     }
 }

+ 253 - 266
src/views/training_manage/modifyVideoPage.vue

@@ -1,7 +1,247 @@
+<script setup>
+import MD5 from 'js-md5'
+import {getOSSSign,bannerupload} from '@/api/api.js'
+import {VideoInterface} from '@/api/modules/trainingApi'
+import AddTags from './components/addTags.vue'
+import {useVideo} from './hooks/use-video'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { ref, reactive } from 'vue'
+import { useRoute, useRouter } from "vue-router"
+
+const route = useRoute()
+const router = useRouter()
+const {
+    classifyList,getClassifyList,
+    tagList,getTagList,
+    getDataClassify,
+    previewPop,previewVideo,previewVideoUrl,previewPopTitle,
+    handlePreviewVideo,endingPreview
+} = useVideo()
+getClassifyList()
+
+let form = reactive({
+    Title: '',
+    Introduce: '',
+    ClassifyId: '',
+    TagIds: [],
+    CoverImg: '',
+    VideoUrl: ''
+})
+const formRef = ref(null)
+const rules = reactive({
+    ClassifyId:[{required:true,message:'请选择所属分类'}],
+    Title:[{required:true,message:'请输入视频名称'}],
+    CoverImg:[{required:true,message:'请选择视频封面'}],
+    VideoUrl:[{required:true,message:'请上传视频'}],
+    TagIds:[{required:true,validator:(rule,value,callback)=>{
+        if(!value.length){
+            return callback(new Error("请至少选择一个标签"))
+        }else{
+            return callback()
+        }
+    }}]
+})
+
+let tagIdKey = ref(0)
+let isModifyDialogShow = ref(false)
+let isImageUploading = ref(false)
+//检查图片是否合法
+function handleUploadImg(file){
+    isImageUploading.value = true;
+    //图片格式限制
+    const { type } = file.file;
+    if (!['image/png', 'image/jpeg'].includes(type)) {
+        ElMessage.warning('仅支持png、jpg格式的图片');
+        isImageUploading.value = false;
+        return;
+    }
+    uploadImg(file);
+}
+//上传图片
+function uploadImg(file) {
+    let form = new FormData();
+    form.append('file', file.file);
+    bannerupload(form).then(res => {
+        isImageUploading.value = false;
+        if (res.Ret !== 200)
+            return;
+        form.CoverImg = res.Data.ResourceUrl;
+    });
+}
+let isVideoUploading = ref(false)
+let percentage = ref(0)
+let timeDuration = ref('')
+//检查视频是否合法,并获取视频时长
+async function handleUploadVideo(file) {
+    if(file.file.type!='video/mp4'){
+        ElMessage.warning('上传失败,上传视频格式不正确');
+        return
+    }
+    const duration=await handleGetDuration(file.file);
+    timeDuration.value = `${String(parseInt(duration/60)).padStart(2,'0')}:${String(parseInt(duration%60)).padStart(2,'0')}`;
+    uploadVideo(file.file);
+    isVideoUploading.value = true;
+}
+//获取视频时长的promise
+async function handleGetDuration(file){
+    return new Promise((resolve,reject)=>{
+        const fileUrl=URL.createObjectURL(file);
+        const audioEl=new Audio(fileUrl);
+        audioEl.addEventListener('loadedmetadata',(e)=>{
+            const t=e.composedPath()[0].duration;
+            resolve(t);
+        })
+    })
+}
+//上传视频
+async function uploadVideo(file) {
+    const res = await getOSSSign();
+    if(res.Ret===200){
+        handleUploadToOSS(file,res.Data);
+    }
+}
+//上传到阿里云
+let ALOSSINS=null //阿里云上传实例
+let ALOSSAbortCheckpoint=null //阿里云上传实例中断点
+async function handleUploadToOSS(file,{AccessKeyId,AccessKeySecret,SecurityToken}){
+    ALOSSINS=new OSS({
+        // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
+        region: "oss-cn-shanghai",
+        // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
+        accessKeyId: AccessKeyId,
+        accessKeySecret: AccessKeySecret,
+        // 从STS服务获取的安全令牌(SecurityToken)。
+        stsToken: SecurityToken,
+        // 填写Bucket名称,例如examplebucket。
+        bucket: "hzchart",
+        endpoint:'hzstatic.hzinsights.com',
+        cname:true,
+        timeout:600000000000
+    });
+    // 生成文件名
+    const t=new Date().getTime().toString();
+    const temName=`static/yb/video/${MD5(t)}.${file.type.split('/')[1]}`;
+    const options = {
+        // 获取分片上传进度、断点和返回值。
+        progress: (p, cpt, res) => {
+            ALOSSAbortCheckpoint=cpt;
+            percentage.value=parseInt(p*100);
+        },
+        // 设置并发上传的分片数量。
+        parallel: 10,
+        // 设置分片大小。默认值为1 MB,最小值为100 KB。
+        partSize: 1024 * 1024 * 10, // 10MB
+    };
+    try {
+        const res=await ALOSSINS.multipartUpload(temName,file,{...options});
+        console.log('上传结果',res);
+        if(res.res.status===200){
+            form.VideoUrl='https://hzstatic.hzinsights.com/'+res.name;
+            percentage.value=0;
+            ALOSSAbortCheckpoint=null;
+            isVideoUploading.value = false;
+        }
+    } catch (error) {
+        console.log('上传到阿里云失败',error);
+        if(error.name!=="cancel"){//不是取消上传的则给错误提示
+            ElMessage.warning('上传失败,请刷新重试');
+        }
+        percentage.value=0;
+        ALOSSAbortCheckpoint=null;
+        isVideoUploading.value = false;
+    }
+}
+//预览视频
+function handleOpenPreviewDialog(){
+    if(isVideoUploading.value||!form.VideoUrl) return
+    const data = {
+        Title:form.Title||'暂无标题',
+        VideoUrl:form.VideoUrl
+    }
+    handlePreviewVideo(data)
+
+}
+//删除所选标签
+function removeTag(tag) {
+    const index = form.TagIds.findIndex(i => i.TagId === tag.TagId);
+    index !== -1 && (form.TagIds.splice(index, 1));
+    tagIdKey++;
+}
+//改变所选标签
+function modifyTags(tags) {
+    form.TagIds = _.cloneDeep(tags);
+    isModifyDialogShow = false;
+}
+//编辑视频-获取视频信息
+function getVideoDetail() {
+    const { VideoId } = route.query;
+    if (!Number(VideoId)) return;
+    VideoInterface.getVideoDetail({
+        VideoId: Number(VideoId)
+    }).then(res => {
+        if (res.Ret !== 200)
+            return;
+        form = reactive(
+            ...res.Data||{}
+        )
+        if (form.Classify) {
+            const { Classify } = this.form;
+            const classifyArr = this.getDataClassify(Classify);
+            form.ClassifyId = classifyArr[classifyArr.length - 1];
+            delete form.Classify;
+        }
+        if (form.Tags) {
+            form.TagIds = form.Tags;
+            delete form.Tags;
+        }
+    });
+}
+getVideoDetail()
+//添加/编辑视频
+async function modifyVideo(type='modify') {
+    try{
+        await formRef?.validate()
+    }catch(e){
+        console.log(e)
+        return 
+    }
+    let res = null;
+    let params = { ...form, ...{ TagIds: form.TagIds.map(t => t.TagId) } };
+    if (!form.VideoId) {
+        res = await VideoInterface.addVideo(params);
+    }
+    else {
+        res = await VideoInterface.editVideo(params);
+    }
+    if (res.Ret !== 200)
+        return;
+    type!=='publish'&&ElMessage.success(`${form.VideoId ? '编辑' : '添加'}成功`);
+    type!=='publish'&&changeRoute();
+    !form.VideoId&&(form.VideoId = res.Data?res.Data:'');
+}
+//发布视频
+async function publishVideo(){
+    let res = {}
+    await modifyVideo('publish');
+    if(form.VideoId){
+        res = await VideoInterface.publishVideo({VideoId:Number(form.VideoId),PublishState:1})
+        if(res.Ret!==200) return;
+        ElMessage.success("发布成功");
+    }
+    changeRoute();
+}
+function changeRoute(){
+    if(ALOSSAbortCheckpoint){
+        console.log('终止上传');
+        ALOSSINS.abortMultipartUpload(ALOSSAbortCheckpoint.name,ALOSSAbortCheckpoint.uploadId)
+    }
+    router.push('/trainingVideo');
+}
+</script>
 <template>
     <!-- 新增编辑视频 -->
     <div class="modify-video-page-wrap">
-        <el-form :model="form" :rules="rules" ref="form">
+        <el-form :model="form" :rules="rules" ref="formRef">
             <el-form-item label="所属分类" prop="ClassifyId">
                 <el-cascader placeholder="选择所属分类" 
                     v-model="form.ClassifyId"
@@ -43,7 +283,7 @@
                 <div class="img-box">
                     <el-progress type="circle" :percentage="percentage" width="40" v-if="isVideoUploading"></el-progress>
                     <span v-if="form.VideoUrl&&!form.VideoId" class="duration">{{timeDuration}}</span>
-                    <img :src="form.CoverImg" v-if="form.VideoUrl" @click="handlePreviewVideo">
+                    <img :src="form.CoverImg" v-if="form.VideoUrl" @click="handleOpenPreviewDialog">
                     <span v-else style="color:#999999;line-height: 100px;">请上传视频</span>
                 </div>
             </el-form-item>
@@ -73,9 +313,8 @@
         />
         <!-- 预览视频弹窗 -->
         <el-dialog
-            :visible.sync="previewPop"
+            v-model="previewPop"
             :modal-append-to-body='false'
-            v-dialogDrag
             width="60vw"
             :title="previewPopTitle"
             @close="endingPreview"
@@ -88,268 +327,6 @@
     </div>
 </template>
 
-<script>
-import MD5 from 'js-md5'
-import {getOSSSign} from '@/api/api.js'
-import {bannerupload} from '@/api/api.js'
-import {VideoInterface} from '@/api/modules/trainingApi'
-import AddTags from './components/addTags.vue'
-import mixin from './mixins/videoMixins'
-let ALOSSINS=null //阿里云上传实例
-let ALOSSAbortCheckpoint=null //阿里云上传实例中断点
-export default {
-    mixins: [mixin],
-    data() {
-        return {
-            form: {
-                Title: '',
-                Introduce: '',
-                ClassifyId: '',
-                TagIds: [],
-                CoverImg: '',
-                VideoUrl: ''
-            },
-            rules:{
-                ClassifyId:[{required:true,message:'请选择所属分类'}],
-                Title:[{required:true,message:'请输入视频名称'}],
-                CoverImg:[{required:true,message:'请选择视频封面'}],
-                VideoUrl:[{required:true,message:'请上传视频'}],
-                TagIds:[{required:true,validator:(rule,value,callback)=>{
-                    if(!value.length){
-                        return callback(new Error("请至少选择一个标签"))
-                    }else{
-                        return callback()
-                    }
-                }}]
-            },
-            tagIdKey: 0,
-            isModifyDialogShow: false,
-
-            isImageUploading: false,
-
-            isVideoUploading: false,
-            percentage:0,
-            timeDuration:'',
-            previewVideoUrl:'',
-            previewPop:false,
-            previewPopTitle:''
-            
-        };
-    },
-    methods: {
-        //检查图片是否合法
-        handleUploadImg(file) {
-            this.isImageUploading = true;
-            //图片格式限制
-            const { type } = file.file;
-            if (!['image/png', 'image/jpeg'].includes(type)) {
-                this.$message.warning('仅支持png、jpg格式的图片');
-                this.isImageUploading = false;
-                return;
-            }
-            this.uploadImg(file);
-        },
-        //上传图片
-        uploadImg(file) {
-            let form = new FormData();
-            form.append('file', file.file);
-            bannerupload(form).then(res => {
-                this.isImageUploading = false;
-                if (res.Ret !== 200)
-                    return;
-                this.form.CoverImg = res.Data.ResourceUrl;
-            });
-        },
-        //检查视频是否合法,并获取视频时长
-        async handleUploadVideo(file) {
-            if(file.file.type!='video/mp4'){
-                this.$message.warning('上传失败,上传视频格式不正确');
-                return
-            }
-            const duration=await this.handleGetDuration(file.file);
-            this.timeDuration = `${String(parseInt(duration/60)).padStart(2,'0')}:${String(parseInt(duration%60)).padStart(2,'0')}`;
-            this.uploadVideo(file.file);
-            this.isVideoUploading = true;
-        },
-        //获取视频时长的promise
-        async handleGetDuration(file){
-            return new Promise((resolve,reject)=>{
-                const fileUrl=URL.createObjectURL(file);
-                const audioEl=new Audio(fileUrl);
-                audioEl.addEventListener('loadedmetadata',(e)=>{
-                    const t=e.composedPath()[0].duration;
-                    resolve(t);
-                })
-            })
-        },
-        //上传视频
-        async uploadVideo(file) {
-            const res = await getOSSSign();
-            if(res.Ret===200){
-                this.handleUploadToOSS(file,res.Data);
-            }
-        },
-        //上传到阿里云
-        async handleUploadToOSS(file,{AccessKeyId,AccessKeySecret,SecurityToken}){
-            ALOSSINS=new OSS({
-                // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
-                region: "oss-cn-shanghai",
-                // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
-                accessKeyId: AccessKeyId,
-                accessKeySecret: AccessKeySecret,
-                // 从STS服务获取的安全令牌(SecurityToken)。
-                stsToken: SecurityToken,
-                // 填写Bucket名称,例如examplebucket。
-                bucket: "hzchart",
-                endpoint:'hzstatic.hzinsights.com',
-                cname:true,
-                timeout:600000000000
-            });
-            // 生成文件名
-            const t=new Date().getTime().toString();
-            const temName=`static/yb/video/${MD5(t)}.${file.type.split('/')[1]}`;
-            const options = {
-                // 获取分片上传进度、断点和返回值。
-                progress: (p, cpt, res) => {
-                    ALOSSAbortCheckpoint=cpt;
-                    this.percentage=parseInt(p*100);
-                },
-                // 设置并发上传的分片数量。
-                parallel: 10,
-                // 设置分片大小。默认值为1 MB,最小值为100 KB。
-                partSize: 1024 * 1024 * 10, // 10MB
-            };
-            try {
-                const res=await ALOSSINS.multipartUpload(temName,file,{...options});
-                console.log('上传结果',res);
-                if(res.res.status===200){
-                    this.form.VideoUrl='https://hzstatic.hzinsights.com/'+res.name;
-                    this.percentage=0;
-                    ALOSSAbortCheckpoint=null;
-                    this.isVideoUploading = false;
-                }
-            } catch (error) {
-                console.log('上传到阿里云失败',error);
-                if(error.name!=="cancel"){//不是取消上传的则给错误提示
-                    this.$message.warning('上传失败,请刷新重试');
-                }
-                this.percentage=0;
-                ALOSSAbortCheckpoint=null;
-                this.isVideoUploading = false;
-            }
-        },
-        //删除所选标签
-        removeTag(tag) {
-            const index = this.form.TagIds.findIndex(i => i.TagId === tag.TagId);
-            index !== -1 && (this.form.TagIds.splice(index, 1));
-            this.tagIdKey++;
-        },
-        //改变所选标签
-        modifyTags(tags) {
-            this.form.TagIds = _.cloneDeep(tags);
-            this.isModifyDialogShow = false;
-        },
-        //获取视频信息
-        getVideoDetail() {
-            const { VideoId } = this.$route.query;
-            if (!VideoId)
-                return;
-            VideoInterface.getVideoDetail({
-                VideoId: Number(VideoId)
-            }).then(res => {
-                if (res.Ret !== 200)
-                    return;
-                this.form = res.Data || {};
-                if (this.form.Classify) {
-                    const { Classify } = this.form;
-                    const classifyArr = this.getDataClassify(Classify);
-                    this.form.ClassifyId = classifyArr[classifyArr.length - 1];
-                    delete this.form.Classify;
-                }
-                if (this.form.Tags) {
-                    this.form.TagIds = this.form.Tags;
-                    delete this.form.Tags;
-                }
-            });
-        },
-        //获取视频分类路径
-        getDataClassify(classify, classifyArr = []) {
-            classifyArr.push(classify.ClassifyId);
-            if (classify.Children && classify.Children.length) {
-                return this.getDataClassify(classify.Children[0], classifyArr);
-            }
-            return classifyArr;
-        },
-        //添加/编辑视频
-        async modifyVideo(type='modify') {
-            await this.$refs.form.validate()
-            let res = null;
-            let params = { ...this.form, ...{ TagIds: this.form.TagIds.map(t => t.TagId) } };
-            if (!this.form.VideoId) {
-                res = await VideoInterface.addVideo(params);
-            }
-            else {
-                res = await VideoInterface.editVideo(params);
-            }
-            if (res.Ret !== 200)
-                return;
-            type!=='publish'&&this.$message.success(`${this.form.VideoId ? '编辑' : '添加'}成功`);
-            type!=='publish'&&this.changeRoute();
-            !this.form.VideoId&&(this.form.VideoId = res.Data?res.Data:'');
-        },
-        //发布视频
-        async publishVideo(){
-            let res = {}
-            await this.modifyVideo('publish');
-            if(this.form.VideoId){
-                res = await VideoInterface.publishVideo({VideoId:Number(this.form.VideoId),PublishState:1})
-                if(res.Ret!==200) return;
-                this.$message.success("发布成功");
-            }
-            this.changeRoute();
-        },
-        changeRoute(){
-            if(ALOSSAbortCheckpoint){
-                console.log('终止上传');
-                ALOSSINS.abortMultipartUpload(ALOSSAbortCheckpoint.name,ALOSSAbortCheckpoint.uploadId)
-            }
-            this.$router.push('/trainingVideo');
-        },
-        // 预览视频
-        handlePreviewVideo(){
-            if(this.isVideoUploading||!this.form.VideoUrl) return
-            this.$refs.previewVideo && this.$refs.previewVideo.play()
-            this.previewPopTitle = this.form.Title||'暂无标题'
-            this.previewVideoUrl = this.form.VideoUrl
-            this.previewPop = true
-        },
-        // 结束预览弹窗关闭回调 -- 暂停视频
-        endingPreview(){
-            this.$refs.previewVideo && this.$refs.previewVideo.pause()
-        },
-    },
-    mounted() {
-        this.getClassifyList('leaf');
-        //this.getTagList();
-        this.getVideoDetail();
-    },
-    components: { AddTags }
-};
-</script>
-<style lang="scss">
-.modify-video-page-wrap{
-    .el-textarea__inner{
-        resize: none;
-    }
-    .el-form-item{
-            .el-form-item__content{
-                display: flex;
-                flex-direction: column;
-                align-items:flex-start;
-            }
-        }
-}
-</style>
 <style scoped lang="scss">
 .modify-video-page-wrap{
     box-sizing: border-box;
@@ -406,6 +383,16 @@ export default {
                 border-radius: 2px;
             }
         }
+        :deep(.el-textarea__inner){
+            resize: none;
+        }
+        .el-form-item{
+            :deep(.el-form-item__content){
+                display: flex;
+                flex-direction: column;
+                align-items:flex-start;
+            }
+        }
     }
     .btn-box{
         text-align: center;

+ 7 - 26
src/views/training_manage/videoManage.vue

@@ -9,7 +9,13 @@ import { ElMessage, ElMessageBox } from 'element-plus'
 
 
 const router = useRouter()
-const {classifyList,getClassifyList,tagList,getTagList} = useVideo()
+const {
+    classifyList,getClassifyList,
+    tagList,getTagList,
+    getDataClassify,
+    previewPop,previewVideo,previewVideoUrl,previewPopTitle,
+    handlePreviewVideo,endingPreview
+} = useVideo()
 getClassifyList()
 getTagList()
 
@@ -29,7 +35,6 @@ let tableParams = reactive({
 })
 let tableData = ref([])
 const tableColumn = videoTableColumn
-let tableLoading = ref(false)
 function getTableData(){
     VideoInterface.getVideoList({
         PageSize:tableParams.pageSize,
@@ -56,14 +61,6 @@ function handleCurrentChange(page){
     tableParams.currentPage = page
     getTableData()
 }
-//获取视频分类路径
-function getDataClassify(classify,classifyArr=[]){
-    classifyArr.push(classify.ClassifyName)
-    if(classify.Children&&classify.Children.length){
-        return getDataClassify(classify.Children[0],classifyArr)
-    }
-    return classifyArr
-}
 
 function handleModifyVideo(VideoId){
     router.push({path:'/modifyVideo',query:{VideoId}})
@@ -109,22 +106,6 @@ function publishVideo(data){
         })
     })
 }
-
-let previewPop = ref(false)
-let previewVideo = ref(null)
-let previewVideoUrl = ref('')
-let previewPopTitle = ref('')
-function handlePreviewVideo(data){
-    if(!data.VideoUrl) return
-    previewVideo.value?.play()
-    previewPopTitle.value = data.Title||'暂无标题'
-    previewVideoUrl.value = data.VideoUrl
-    previewPop.value = true
-}
-// 结束预览弹窗关闭回调 -- 暂停视频
-function endingPreview(){
-    previewVideo.value?.pause()
-}
 </script>
 <template>
     <div class="video-manage-wrap traing-manage">