Procházet zdrojové kódy

添加创建视频

aaa před 3 roky
rodič
revize
b1e72aca57

+ 1 - 1
src/router/menu.js

@@ -30,7 +30,7 @@ export default [
         meta: { title: '新建文章' },
       },
       {
-        path: '/articleManagement/videCreate',
+        path: '/articleManagement/videoCreate',
         meta: { title: '新建视频' },
       },
       {

+ 52 - 36
src/views/articleManagement/articleList.vue

@@ -75,9 +75,16 @@
         >
           <div class="article-list-item-title">{{ item.name }}</div>
           <div class="article-list-item-contgents">
-            <p class="p-content" v-html="item.contentsShow">
+            <p
+              v-if="item.type == 'ARTICLE'"
+              class="p-content"
+              v-html="item.contentsShow"
+            >
               {{ item.contentsShow }}
             </p>
+            <div v-if="item.type == 'VIDEO'">
+              <img :src="getContentObj(item.contents).faceUrl" />
+            </div>
           </div>
           <div class="article-list-item-createtime">
             {{ item.createdTime | formatDateTime }}
@@ -146,28 +153,28 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex';
-import { formatePathParams, formateEngineeringWork } from '@/filters';
+import { mapGetters } from "vuex";
+import { formatePathParams, formateEngineeringWork } from "@/filters";
 export default {
-  name: 'articleCreate',
+  name: "articleCreate",
   props: {},
   components: {},
   data() {
     return {
       loading: false, // 是否展示加载动画
       articleTypeList: [], // 文章类型列表
-      articleArticleType: '', // 所选文章类型
+      articleArticleType: "", // 所选文章类型
       articleTypeChildrenList: [], // 所属子类
-      checkedArticleTypeChildren: '', // 所选试题类型
+      checkedArticleTypeChildren: "", // 所选试题类型
       engineeringWorkList: [], // 工种数据列表
-      engineeringWorkChooseValue: '', // 所选工种
+      engineeringWorkChooseValue: "", // 所选工种
       articleList: [], // 文章列表数据
       pagination: {
         pageSize: 7,
         current: 1,
-        total: 0,
+        total: 0
       }, // 分页参数
-      searchInputVal: '', // 搜索name
+      searchInputVal: "" // 搜索name
     };
   },
   created() {},
@@ -178,17 +185,17 @@ export default {
   watch: {},
   computed: {
     ...mapGetters([
-      'GET_ENGINEERING_WORK_LIST',
-      'GET_EXAM_QUESTION_TYPE_CONDITION_PARENT',
-    ]),
+      "GET_ENGINEERING_WORK_LIST",
+      "GET_EXAM_QUESTION_TYPE_CONDITION_PARENT"
+    ])
   },
   methods: {
     //初始化数据
     initDataFun() {
       // 工种类别
       this.engineeringWorkList = [
-        { name: '全部', id: '' },
-        ...this.GET_ENGINEERING_WORK_LIST,
+        { name: "全部", id: "" },
+        ...this.GET_ENGINEERING_WORK_LIST
       ];
       this.engineeringWorkChooseValue = this.engineeringWorkList[0].id;
       this.getArticleTypeFun(); // 查询:文章分类-父类
@@ -196,16 +203,16 @@ export default {
     },
     // 查询:文章分类-父类
     getArticleTypeFun() {
-      this.$_http.get(this.$_API.INTERFACE_GET_CATEGORIES).then((res) => {
-        this.articleTypeList = [{ name: '全部', id: '' }, ...res.data];
+      this.$_http.get(this.$_API.INTERFACE_GET_CATEGORIES).then(res => {
+        this.articleTypeList = [{ name: "全部", id: "" }, ...res.data];
         this.articleArticleType = this.articleTypeList[0].id;
-        this.articleTypeChildrenList = [{ name: '全部', id: '' }];
+        this.articleTypeChildrenList = [{ name: "全部", id: "" }];
       });
     },
     // 查询:文章分类-子类
     getArticleTypeChildrenFun() {
       if (!this.articleArticleType) {
-        this.articleTypeChildrenList = [{ name: '全部', id: '' }];
+        this.articleTypeChildrenList = [{ name: "全部", id: "" }];
         this.checkedArticleTypeChildren = this.articleTypeChildrenList[0].id;
         this.initPagination(); // 初始化分页参数
         this.getArticleListFun(); // 查询:文章列表数据
@@ -219,7 +226,7 @@ export default {
             params
           )
         )
-        .then((res) => {
+        .then(res => {
           this.articleTypeChildrenList = res.data;
           this.checkedArticleTypeChildren = this.articleTypeChildrenList[0].id;
           this.loading = false;
@@ -243,14 +250,14 @@ export default {
         engineertypeid: this.engineeringWorkChooseValue, // 工种ID
         page: this.pagination.current - 1,
         size: this.pagination.pageSize,
-        materialtitle: this.searchInputVal,
+        materialtitle: this.searchInputVal
       };
       this.$_http
         .get(this.$_API.INTERFACE_GET_ARTICLE_LIST, { params })
-        .then((res) => {
+        .then(res => {
           let resData = res.data.content;
-          resData.forEach((item) => {
-            this.GET_ENGINEERING_WORK_LIST.forEach((it) => {
+          resData.forEach(item => {
+            this.GET_ENGINEERING_WORK_LIST.forEach(it => {
               if (item.id === it.id) {
                 item.engineeringWorkTxt = it.name;
               }
@@ -261,12 +268,12 @@ export default {
                 this.engineeringWorkList,
                 item.engineerTypes[0]
               );
-              item.engineerTypeTxt = findItem ? findItem.name : '';
+              item.engineerTypeTxt = findItem ? findItem.name : "";
             } else {
-              item.engineerTypeTxt = '不限';
+              item.engineerTypeTxt = "不限";
             }
             if (item.contents && item.contents.length > 200) {
-              item.contentsShow = item.contents.slice(0, 199) + '...';
+              item.contentsShow = item.contents.slice(0, 199) + "...";
             } else {
               item.contentsShow = item.contents;
             }
@@ -311,14 +318,14 @@ export default {
     handleDeleteArticleItem(item) {
       let that = this;
       this.$confirm({
-        title: '删除文章',
+        title: "删除文章",
         content: `确认删除文章 ${item.name} 吗?`,
-        okText: '确认',
-        cancelText: '取消',
+        okText: "确认",
+        cancelText: "取消",
         onOk() {
           that.loading = true;
           let params = {
-            materialId: item.id,
+            materialId: item.id
           };
           that.$_http
             .delete(
@@ -328,7 +335,7 @@ export default {
               )
             )
             .then(() => {
-              that.$message.success('删除文章成功');
+              that.$message.success("删除文章成功");
               that.loading = false;
               that.initPagination(); // 初始化分页参数
               that.getArticleListFun(); // 查询:文章列表数据
@@ -337,7 +344,7 @@ export default {
               that.loading = false;
             });
         },
-        onCancel() {},
+        onCancel() {}
       });
     },
     // 操作:编辑文章
@@ -346,8 +353,8 @@ export default {
         return;
       }
       this.$router.push({
-        path: '/articleManagement/create',
-        query: { id: item.id, type: 'edit' },
+        path: "/articleManagement/create",
+        query: { id: item.id, type: "edit" }
       });
     },
     //  // 操作:编辑文章
@@ -361,7 +368,11 @@ export default {
     onChangePagesize() {
       this.getArticleListFun(); // 查询:文章列表数据
     },
-  },
+    getContentObj(content) {
+      console.log("---" + content);
+      return JSON.parse(content);
+    }
+  }
 };
 </script>
 
@@ -374,7 +385,7 @@ export default {
 </style>
 
 <style lang="less" scoped>
-@import '~@/styles/common/variable.less';
+@import "~@/styles/common/variable.less";
 .app-container {
   .article-list-item {
     width: 100%;
@@ -389,6 +400,11 @@ export default {
       padding: 0 @paddingMarginVal;
       font-size: 16px;
       color: @mainColorBlack65;
+      img {
+        max-width: 100%;
+        width: auto;
+        height: auto;
+      }
     }
     .article-list-item-createtime {
       margin-top: @paddingMarginVal;

+ 154 - 70
src/views/articleManagement/videoCreate.vue

@@ -56,7 +56,8 @@
               <a-select-option
                 v-for="(item, index) in articleParentClassArr"
                 :key="index"
-              >{{ articleParentClassArr[index].name }}</a-select-option>
+                >{{ articleParentClassArr[index].name }}</a-select-option
+              >
             </a-select>
           </a-form-item>
           <a-form-item label="文章子类">
@@ -80,7 +81,8 @@
               <a-select-option
                 v-for="(item, index) in articleChildClassArr"
                 :key="index"
-              >{{ articleChildClassArr[index].name }}</a-select-option>
+                >{{ articleChildClassArr[index].name }}</a-select-option
+              >
             </a-select>
           </a-form-item>
           <a-form-item label="工种类别">
@@ -97,7 +99,8 @@
               <a-select-option
                 v-for="(item, index) in engineerTypeArray"
                 :key="index"
-              >{{ engineerTypeArray[index].name }}</a-select-option>
+                >{{ engineerTypeArray[index].name }}</a-select-option
+              >
             </a-select>
           </a-form-item>
           <a-form-item label="必学日期:">
@@ -119,7 +122,9 @@
             />
           </a-form-item>
           <a-form-item v-show="false" :wrapper-col="{ span: 20, offset: 10 }">
-            <a-button id="articleCreateSubmit" type="primary" html-type="submit">提交</a-button>
+            <a-button id="articleCreateSubmit" type="primary" html-type="submit"
+              >提交</a-button
+            >
           </a-form-item>
         </a-form>
       </div>
@@ -130,31 +135,30 @@
       <div>
         <a-upload
           :customRequest="uploadOssVideoFile"
-          :previewFile="previewVideoFile"
+          list-type="picture"
           :default-file-list="defaultVideoFileList"
         >
-          <a-button>
-            <a-icon type="upload" />Upload
-          </a-button>
+          <a-button> <a-icon type="upload" />Upload </a-button>
         </a-upload>
       </div>
       <div>上传封面</div>
       <div>
         <a-upload
           :customRequest="uploadOssImageFile"
-          :previewFile="previewImageFile"
+          list-type="picture"
           :default-file-list="defaultImageFileList"
         >
-          <a-button>
-            <a-icon type="upload" />Upload
-          </a-button>
+          <a-button> <a-icon type="upload" />Upload </a-button>
         </a-upload>
       </div>
       <div class="submit-row">
         <a-button type="primary" @click="handleSubmitBtnFun">提交</a-button>
-        <a-button :style="{ marginLeft: '160px' }" @click="preview">预览</a-button>
+        <a-button :style="{ marginLeft: '160px' }" @click="preview"
+          >预览</a-button
+        >
       </div>
     </div>
+
     <!-- 预览弹出框 -->
     <a-drawer
       title
@@ -165,7 +169,15 @@
       @close="closepreview"
       width="30%"
     >
-      <p class="p-content" v-html="content">{{ content }}</p>
+      <video
+        v-if="videoUrl"
+        :poster="faceUrl"
+        :src="videoUrl"
+        controls="controls"
+      >
+        您的浏览器不支持 video 标签。
+      </video>
+      <div v-else>暂未上传视频</div>
     </a-drawer>
   </div>
 </template>
@@ -183,9 +195,10 @@ export default {
   components: {},
   data() {
     return {
-      content: "",
-      //   展示预览
       previewVisible: false,
+      videoUrl: "",
+      faceUrl: "",
+      content: "",
       form: this.$form.createForm(this, { name: "articleCreate" }),
       articleParentClassArr: [],
       articleChildClassArr: [],
@@ -197,7 +210,8 @@ export default {
       optionType: "",
       description: "",
       bodyStyle: {
-        img: "{max-width:100%;}",
+        img: "{max-width:100%;width: auto;height: auto;}",
+        video: "{max-width:100%;width: auto;height: auto;}",
         color: "red"
       },
       defaultVideoFileList: [],
@@ -385,14 +399,15 @@ export default {
               };
               let tag = formateDateToString(that.learnDate);
               let links = [];
-              that.defaultFileList.forEach(element => {
-                links.push(element.url);
-              });
+              let contentObj = {
+                faceUrl: that.faceUrl,
+                videoUrl: that.videoUrl
+              };
               let bodyParams = {
                 name: values.name,
                 description: values.description,
-                type: "ARTICLE",
-                contents: that.content,
+                type: "VIDEO",
+                contents: JSON.stringify(contentObj),
                 tags: tag ? [tag] : [],
                 engineerTypes: [that.engineerType.id],
                 links: links
@@ -429,15 +444,16 @@ export default {
               };
               let tag = formateDateToString(that.learnDate);
               let links = [];
-              that.defaultFileList.forEach(element => {
-                links.push(element.url);
-              });
+              let contentObj = {
+                faceUrl: that.faceUrl,
+                videoUrl: that.videoUrl
+              };
               let bodyParams = {
                 id: that.$route.query.id,
                 name: values.name,
                 description: values.description,
-                type: "ARTICLE",
-                contents: that.content,
+                type: "VIDEO",
+                contents: JSON.stringify(contentObj),
                 tags: tag ? [tag] : [],
                 engineerTypes: [that.engineerType.id],
                 links: links
@@ -467,55 +483,123 @@ export default {
         }
       });
     },
-    uploadOssVideoFile(fileData) {
-      this.uploadOssFile(fileData);
-    },
-    uploadOssImageFile(fileData) {
-      this.uploadOssFile(fileData);
-    },
-
-    uploadOssFile(fileData, defaultFileList) {
-      let file = fileData.file;
+    async uploadOssVideoFile(fileData) {
       let that = this;
+      let file = fileData.file;
+
+      var index = file.name.indexOf("."); //(考虑严谨用lastIndexOf(".")得到)得到"."在第几位
+      var subfix = file.name.substring(index); //截断"."之前的,得到后缀
+      if (subfix != ".mp4") {
+        fileData.onError();
+        this.$message.error("只能上传mp4格式的文件");
+        return;
+      }
+
       let bucket = "jtxt-file-public";
-      // let filetype =
-      //   ".pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx";
       let ossPath = "file/";
-      that.$_http.get(that.$_API.INTERFACE_GET_ASSUME_OSS_WRITER).then(res => {
-        console.log("--oss-writer--" + JSON.stringify(res));
-        const client = new OSS({
-          // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
-          region: "oss-cn-beijing",
-          // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
-          accessKeyId: res.data.accessKeyId,
-          accessKeySecret: res.data.accessKeySecret,
-          // 从STS服务获取的安全令牌(SecurityToken)。
-          stsToken: res.data.securityToken,
-          // 填写Bucket名称。
-          bucket: bucket
+      let res = await that.$_http.get(
+        that.$_API.INTERFACE_GET_ASSUME_OSS_WRITER
+      );
+      console.log("--oss-writer--" + JSON.stringify(res));
+      const client = new OSS({
+        // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
+        region: "oss-cn-beijing",
+        // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
+        accessKeyId: res.data.accessKeyId,
+        accessKeySecret: res.data.accessKeySecret,
+        // 从STS服务获取的安全令牌(SecurityToken)。
+        stsToken: res.data.securityToken,
+        // 填写Bucket名称。
+        bucket: bucket
+      });
+      try {
+        client.put(ossPath + file.name, file).then(res => {
+          console.log(res);
+          let upFile = {
+            uid: that.defaultVideoFileList.length + 1,
+            name: file.name,
+            status: "done",
+            url: res.url
+          };
+          that.videoUrl = res.url;
+          that.defaultVideoFileList.push(upFile);
+          fileData.onSuccess();
         });
-        try {
-          client.put(ossPath + file.name, file).then(res => {
-            console.log(res);
-            let upFile = {
-              uid: defaultFileList.length + 1,
-              name: file.name,
-              status: "done",
-              url: res.url
-            };
-            defaultFileList.push(upFile);
-            fileData.onSuccess();
-          });
-        } catch (e) {
-          fileData.onError();
-          console.error(e);
-        }
+      } catch (e) {
+        fileData.onError();
+        console.error(e);
+      }
+
+      //   var index = file.name.indexOf("."); //(考虑严谨用lastIndexOf(".")得到)得到"."在第几位
+      //   var tv_id = file.name.substring(index); //截断"."之前的,得到后缀
+      //   //如果是视频截取第一个作为图片展示出来
+      //   if (tv_id == ".mp4") {
+      //     //根据后缀,判断是否符合视频格式
+      //     this.findvideocover(file);
+      //   }
+    },
+    async uploadOssImageFile(fileData) {
+      let that = this;
+      let file = fileData.file;
+      let bucket = "jtxt-file-public";
+      let ossPath = "file/";
+      let res = await that.$_http.get(
+        that.$_API.INTERFACE_GET_ASSUME_OSS_WRITER
+      );
+      console.log("--oss-writer--" + JSON.stringify(res));
+      const client = new OSS({
+        // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
+        region: "oss-cn-beijing",
+        // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
+        accessKeyId: res.data.accessKeyId,
+        accessKeySecret: res.data.accessKeySecret,
+        // 从STS服务获取的安全令牌(SecurityToken)。
+        stsToken: res.data.securityToken,
+        // 填写Bucket名称。
+        bucket: bucket
       });
+      try {
+        client.put(ossPath + file.name, file).then(res => {
+          console.log(res);
+          let upFile = {
+            uid: that.defaultImageFileList.length + 1,
+            name: file.name,
+            status: "done",
+            url: res.url
+          };
+          that.faceUrl = res.url;
+          that.defaultImageFileList.push(upFile);
+          fileData.onSuccess();
+        });
+      } catch (e) {
+        fileData.onError();
+        console.error(e);
+      }
+    },
+
+    // 截取视频第一帧
+    findvideocover(file) {
+      file.src = file.url; // url地址 url跟 视频流是一样的
+      console.log("-----filesrc-" + file.src);
+      var canvas = document.createElement("canvas"); // 获取 canvas 对象
+      const ctx = canvas.getContext("2d"); // 绘制2d
+      file.crossOrigin = "anonymous"; // 解决跨域问题,也就是提示污染资源无法转换视频
+      file.currentTime = 1; // 第一帧
+      file.oncanplay = () => {
+        canvas.width = file.clientWidth; // 获取视频宽度
+        canvas.height = file.clientHeight; //获取视频高度
+        // 利用canvas对象方法绘图
+        ctx.drawImage(file, 0, 0, file.clientWidth, file.clientHeight);
+        // 转换成base64形式
+        this.faceUrl = canvas.toDataURL("image/png"); // 截取后的视频封面
+        console.log("----faceUrl--" + this.faceUrl);
+        // file.url = this.imgsrc;
+      };
+    },
+    // 预览
+    preview() {
+      this.previewVisible = true;
     },
-    //视频预览
-    previewVideoFile() {},
-    //图片预览
-    previewImageFile() {},
     // 关闭预览
     closepreview() {
       this.previewVisible = false;