소스 검색

品牌视频剪辑功能

lushixing 1 주 전
부모
커밋
f34992106c

+ 1 - 0
.env.development

@@ -6,6 +6,7 @@ ENV = 'development'
 VUE_APP_OAUTH_API = '/app/backstage/auth/'
 VUE_APP_SYSTEM_API = '/app/sys/'
 VUE_APP_AI_API = '/app/ai/'
+VUE_APP_API = '/app/'
 
 
 # 静态资源

+ 1 - 0
.env.production

@@ -5,6 +5,7 @@ ENV = 'production'
 VUE_APP_OAUTH_API = '/app/backstage/auth/'
 VUE_APP_SYSTEM_API = '/app/sys/'
 VUE_APP_AI_API = '/app/ai/'
+VUE_APP_API = '/app/'
 
 #静态资源
 VUE_APP_RESOURCE_URL = ''

+ 3 - 0
src/api/api.js

@@ -0,0 +1,3 @@
+export const api = {
+  fileUrl: process.env.VUE_APP_API + '/file/viUpload'
+}

+ 0 - 18
src/api/catwalkVideo.js

@@ -1,18 +0,0 @@
-import request from '@/utils/request'
-
-//查看
-export function fetchSuggestionList(params) {
-  return request({
-    url: '/videoInfo/page',
-    method: 'get',
-    params
-  })
-}
-// 编辑优化建议
-export function editSuggestion(data) {
-  return request({
-    url: '/videoInfo/delete',
-    method: 'post',
-    data
-  })
-}

+ 50 - 0
src/api/musicLibraryManager.js

@@ -0,0 +1,50 @@
+import request from '@/utils/request'
+
+//查看
+export function fetchMusicConfigList(params) {
+  return request({
+    url: '/musicConfig/page',
+    method: 'get',
+    params
+  })
+}
+// 删除
+export function deteleMusicConfig(data) {
+  return request({
+    url: '/musicConfig/delete',
+    method: 'post',
+    data
+  })
+}
+// add
+export function addMusicConfig(data) {
+  return request({
+    url: '/musicCategoryInfo/add',
+    method: 'post',
+    data
+  })
+}
+// 编辑
+export function editMusicConfig(data) {
+  return request({
+    url: '/musicCategoryInfo/edit',
+    method: 'post',
+    data
+  })
+}
+// add 音乐库
+export function addMusicConfigInfo(data) {
+  return request({
+    url: '/musicConfigInfo/add',
+    method: 'post',
+    data
+  })
+}
+// 编辑音乐库
+export function editMusicConfigInfo(data) {
+  return request({
+    url: '/musicConfigInfo/edit',
+    method: 'post',
+    data
+  })
+}

+ 38 - 0
src/api/videoCoverManager.js

@@ -0,0 +1,38 @@
+import request from '@/utils/request'
+
+//列表
+export function shopConfigInfoList(params) {
+  return request({
+    url: '/shopConfigInfo/page',
+    method: 'get',
+    params,
+    customApi: 'api'
+  })
+}
+// 删除
+export function deteleShopConfigInfo(data) {
+  return request({
+    url: '/shopConfigInfo/delete',
+    method: 'post',
+    data,
+    customApi: 'api'
+  })
+}
+// add
+export function addShopConfigInfo(data) {
+  return request({
+    url: '/shopConfigInfo/add',
+    method: 'post',
+    data,
+    customApi: 'api'
+  })
+}
+// 编辑
+export function editShopConfigInfo(data) {
+  return request({
+    url: '/shopConfigInfo/edit',
+    method: 'post',
+    data,
+    customApi: 'api'
+  })
+}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
src/assets/image/file-icon.svg


BIN
src/assets/image/help.png


BIN
src/assets/image/logo.jpg


BIN
src/assets/image/play.png


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
src/assets/image/upload-icon.svg


BIN
src/assets/image/user.png


BIN
src/assets/menu/nav_icon_1.png


BIN
src/assets/menu/nav_icon_2.png


BIN
src/assets/menu/nav_icon_3.png


BIN
src/assets/menu/nav_icon_4.png


BIN
src/assets/menu/nav_icon_5.png


BIN
src/assets/menu/nav_icon_6.png


BIN
src/assets/menu/nav_icon_7.png


BIN
src/assets/menu/nav_icon_8.png


+ 7 - 0
src/permission.js

@@ -44,6 +44,13 @@ router.beforeEach(async (to, from, next) => {
             { routerPath: "/catwalkVideo" },
             { routerPath: "/catwalkVideo/catwalkVideoIndex" },
             { routerPath: "/catwalkVideo/catwalkVideoTool" },
+            { routerPath: "/catwalkVideo/brandVideoEditor" },
+            { routerPath: "/videoCoverManager" },
+            { routerPath: "/videoCoverManager/videoCoverIndex" },
+            { routerPath: "/videoCoverManager/faceSwapVideoIndex" },
+            { routerPath: "/musicLibraryManager" },
+            { routerPath: "/musicLibraryManager/musicCategoryIndex" },
+            { routerPath: "/musicLibraryManager/musicLibrary" },
             { routerPath: "/faceSwapVideo" },
             { routerPath: "/faceSwapVideo/faceSwapVideoIndex" },
             { routerPath: "/faceSwapVideo/faceSwapVideoTool" },

+ 4 - 0
src/router/index.js

@@ -35,12 +35,16 @@ export const constantRoutes = [
 ];
 // import userAuthRouter from "./modules/userAuth";
 import oralVideoRouter from "./modules/oralVideo";
+import videoCoverManagerRouter from "./modules/videoCoverManager";
+import musicLibraryManager from "./modules/musicLibraryManager";
 import catwalkVideoRouter from "./modules/catwalkVideo";
 import faceSwapVideoRouter from "./modules/faceSwapVideo";
 export const asyncRoutes = [
   oralVideoRouter,
   catwalkVideoRouter,
   faceSwapVideoRouter,
+  videoCoverManagerRouter,
+  musicLibraryManager
   // userAuthRouter,
 ];
 

+ 6 - 0
src/router/modules/catwalkVideo.js

@@ -21,6 +21,12 @@ const catwalkVideoRouter = {
       name: "AI走秀视频剪辑",
       meta: { title: "AI走秀视频剪辑" }
     },
+    {
+      path: "brandVideoEditor",
+      component: () => import("@/views/catwalk-video/brandVideoEditor"),
+      name: "品牌视频剪辑",
+      meta: { title: "品牌视频剪辑" }
+    },
   ]
 };
 export default catwalkVideoRouter;

+ 26 - 0
src/router/modules/musicLibraryManager.js

@@ -0,0 +1,26 @@
+/** When your routing table is too long, you can split it into small modules **/
+
+import Layout from "@/layout";
+
+const musicLibraryManagerRouter = {
+  path: "/musicLibraryManager",
+  component: Layout,
+  redirect: "/musicLibraryManager/musicLibraryIndex",
+  name: "音乐库管理",
+  meta: { title: "音乐库管理", icon: "el-icon-camera-solid" },
+  children: [
+    {
+      path: "musicCategoryIndex",
+      component: () => import("@/views/music-library-manager/index"),
+      name: "音乐类目列表",
+      meta: { title: "音乐类目列表" }
+    },
+    {
+      path: "musicLibrary",
+      component: () => import("@/views/music-library-manager/musicLibrary"),
+      name: "音乐库列表",
+      meta: { title: "音乐库列表" }
+    }
+  ]
+};
+export default musicLibraryManagerRouter;

+ 20 - 0
src/router/modules/videoCoverManager.js

@@ -0,0 +1,20 @@
+/** When your routing table is too long, you can split it into small modules **/
+
+import Layout from "@/layout";
+
+const videoCoverManagerRouter = {
+  path: "/videoCoverManager",
+  component: Layout,
+  redirect: "/videoCoverManager/videoCoverIndex",
+  name: "视频封面管理",
+  meta: { title: "视频封面管理", icon: "el-icon-camera-solid" },
+  children: [
+    {
+      path: "videoCoverIndex",
+      component: () => import("@/views/video-cover-manager/index"),
+      name: "视频封面列表",
+      meta: { title: "视频封面列表" }
+    }
+  ]
+};
+export default videoCoverManagerRouter;

+ 4 - 1
src/utils/request.js

@@ -13,6 +13,9 @@ const service = axios.create({
 // request拦截器
 service.interceptors.request.use(
   config => {
+    if (config.customApi === 'api') {
+      config.baseURL = process.env.VUE_APP_API;
+    }
     if (store.getters.token) {
       config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
     }
@@ -70,4 +73,4 @@ service.interceptors.response.use(
   }
 );
 
-export default service
+export default service

+ 194 - 0
src/views/catwalk-video/brandVideoEditor.vue

@@ -0,0 +1,194 @@
+<template>
+  <div class="brand-video-editor">
+    <div class="brand-video-editor__top">
+      <div class="video-upload">
+        <div class="head"><span class="title">上传视频:</span></div>
+        <div class="upload-black">
+          <!-- action必选参数, 上传的地址 -->
+          <el-upload class="avatar-uploader el-upload--text" :action="uploadUrl" :show-file-list="false" :on-success="handleVideoSuccess" :before-upload="beforeUploadVideo" :on-progress="uploadVideoProcess">
+            <video v-if="videoForm.Video !='' && videoFlag == false" :src="videoForm.Video" class="avatar" controls="controls">您的浏览器不支持视频播放</video>
+            <p class="text-black" v-else-if="videoForm.Video =='' && videoFlag == false">
+              <span class="upload-icon"></span>
+              <span class="text">选择文件或者拖拽上传视频</span>
+              <span class="subtext">MP4 文件 最大50MB</span>
+              <a href="javascript:;" class="file-btns">浏览文件</a>
+            </p>
+            <el-progress v-if="videoFlag == true" type="circle" :percentage="videoUploadPercent" style="margin-top:30px;"></el-progress>
+          </el-upload>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+
+export default {
+  name: "BrandVideoEditor",
+  components: {
+    
+  },
+  computed: {
+   
+  },
+  data() {
+    return {
+      uploadUrl: '',
+      videoFlag: false,
+      videoUploadPercent: 0,
+      videoForm: {
+        Video: ''
+      }
+    };
+  },
+  //页面创建的时候执行
+  created() {
+   
+  },
+  methods: {
+    beforeUploadVideo(file) {
+      const isLt10M = file.size / 1024 / 1024 < 10;
+      if (['video/mp4', 'video/ogg', 'video/flv','video/avi','video/wmv','video/rmvb'].indexOf(file.type) == -1) {
+        this.$message.error('请上传正确的视频格式');
+        return false;
+      }
+      if (!isLt10M) {
+        this.$message.error('上传视频大小不能超过10MB哦!');
+        return false;
+      }
+    },
+    uploadVideoProcess(event, file, fileList) {
+      this.videoFlag = true;
+      this.videoUploadPercent = file.percentage.toFixed(0);
+    },
+    handleVideoSuccess(res, file) {
+      this.videoFlag = false;
+      this.videoUploadPercent = 0;
+      if (res.status == 200) {
+        this.videoForm.videoUploadId = res.data.uploadId;
+        this.videoForm.Video = res.data.uploadUrl;
+      } else {
+        this.$message.error('视频上传失败,请重新上传!');
+      }
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+  .brand-video-editor {
+    padding: 40px 65px 65px 30px;
+
+    .brand-video-editor__top {
+      display: flex;
+      justify-content: space-between;
+      gap: 3.6vw;
+
+      .video-upload {
+        flex: 1;
+      }
+      .processed-video {
+        flex: 1;
+      }
+
+      .head {
+        display: flex;
+        justify-content: space-between;
+        font-size: 24px;
+        height: 48px;
+        line-height: 48px;
+        color: #444444;
+        margin-bottom: 20px;
+
+        .download-video {
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          border-radius: 2px;
+          border: 1px solid #CBCBCB;
+          height: 48px;
+          font-size: 18px;
+          color: #666666;
+          padding: 0 20px;
+          background: linear-gradient(180deg, #FFFFFF 9%, #FAFAFA 100%);
+        }
+      }
+
+      .upload-black {
+        width: 100%;
+        height: 420px;
+        border: 2px dashed #BABABA;
+        border-radius: 20px;
+
+        .avatar-uploader {
+          display: block;
+          width: 100%;
+          height: 100%;
+
+          /deep/ .el-upload {
+            display: flex;
+            width: 100%;
+            height: 100%;
+            justify-content: center;
+            align-items: center;
+          }
+        }
+        .text-black {
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          margin: 0;
+
+          .upload-icon {
+            width: 48px;
+            height: 48px;
+            background: pink;
+            margin-bottom: 48px;
+          }
+          .text {
+            font-size: 30px;
+            color: #292D32;
+            line-height: 1.5;
+          }
+          .subtext {
+            font-size: 26px;
+            color: #A9ACB4;
+            line-height: 1.5;
+          }
+
+          a.file-btns {
+            display: flex;
+            font-size: 30px;
+            justify-content: center;
+            align-items: center;
+            height: 68px;
+            border-radius: 10px;
+            border: 2px solid #CBD0DC;
+            padding: 0 50px;
+            color: #54575C;
+            margin-top: 30px;
+          }
+        }
+      }
+      .video-result {
+        width: 100%;
+        height: 420px;
+        border: 2px dashed #BABABA;
+        border-radius: 20px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+
+        .video-result__empty {
+          width: 168px;
+          height: 198px;
+
+          img {
+            display: block;
+            height: 100%;
+          }
+        }
+      }
+    }
+  }
+</style>

+ 167 - 0
src/views/music-library-manager/components/MusicLibraryFormModal.vue

@@ -0,0 +1,167 @@
+<template>
+  <el-dialog :title="(modelType == 'add' ? '添加' : '编辑') + '音乐类目信息'" width="800px" :visible.sync="dialogVisible">
+    <el-form :model="form" :rules="rules" ref="MusicLibraryForm" label-width="150px">
+      <el-form-item prop="musicCategoryName" label="音乐类目名称:">
+        <el-input placeholder="请输入音乐类目名称" v-model="form.musicCategoryName"></el-input>
+      </el-form-item>
+      <el-form-item prop="musicCategorySort" label="类目排序:">
+        <el-input-number v-model="form.musicCategorySort" controls-position="right" :min="0"></el-input-number>
+      </el-form-item>
+    </el-form>
+
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="dialogVisible = false">取消</el-button>
+      <el-button type="primary" :loading="comfirmLoading" @click="handleConfirm">确定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import { addMusicConfig, editMusicConfig } from "@/api/musicLibraryManager";
+export default {
+  name: "MusicLibraryFormModal",
+  props: {
+  },
+  data() {
+    return {
+      form: {
+        musicCategoryName: '',
+        musicCategorySort: ''
+      },
+      modelType: 'add',
+      dialogVisible: false,
+      comfirmLoading: false,
+      editId: '',
+      rules: {
+        musicCategoryName: [
+          { required: true, message: "请输入音乐类目名称", trigger: "blur" }
+        ],
+        musicCategorySort: [
+          { required: true, message: "请输入类目排序", trigger: "blur" }
+        ]
+      }
+    };
+  },
+  watch: {
+    dialogVisible(val) {
+      if (!val) {
+        this.form = {
+          musicCategoryName: '',
+          musicCategorySort: ''
+        }
+        this.modelType =  'add';
+        this.comfirmLoading = false;
+        this.editId = '';
+      }
+    }
+  },
+  methods: {
+    show(rows, type) {
+      this.dialogVisible = true;
+      this.comfirmLoading = false;
+      this.modelType = type;
+      if (type == 'edit') {
+        this.editId = rows.id;
+      }
+      this.$nextTick(() => {
+        this.form = type == 'edit' ? {
+          musicCategoryName: rows.musicCategoryName,
+          musicCategorySort: rows.musicCategorySort
+        } : {
+          musicCategoryName: '',
+          musicCategorySort: ''
+        }
+        this.$refs.MusicLibraryForm.resetFields()
+      })
+    },
+    handleConfirm() {
+      this.$refs.MusicLibraryForm.validate(valid => {
+        if (valid) {
+          this.comfirmLoading = true;
+          const params = this.form;
+          if (this.modelType == 'add') {
+            addMusicConfig(params).then(res =>{
+              this.dialogVisible = false;
+              if(res.code == 200){
+                this.$message.success(res.msg || "操作成功");
+                this.$emit("confirm");
+              }
+            }).finally(()=>{
+              this.comfirmLoading = false;
+            })
+          } else {
+            params.id = this.editId;
+            editMusicConfig(params).then(res =>{
+              this.dialogVisible = false;
+              if(res.code == 200){
+                this.$message.success(res.msg || "操作成功");
+                this.$emit("confirm");
+              }
+            }).finally(()=>{
+              this.comfirmLoading = false;
+            })
+          }
+          
+        } else {
+          return false;
+        }
+      });
+    }
+  }
+};
+</script>
+<style lang="scss">
+  .avatar-uploader .el-upload {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+  }
+  .avatar-uploader .el-upload:hover {
+    border-color: #409EFF;
+  }
+  .avatar-uploader-icon {
+    font-size: 28px;
+    color: #8c939d;
+    width: 178px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+  }
+  .avatar {
+    display: block;
+  }
+  .avatar-black {
+    width: 180px;
+    height: 180px;
+    position: relative;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    i {
+      position: absolute;
+      top: -10px;
+      right: -10px;
+      cursor: pointer;
+      z-index: 999999;
+      color: red;
+      background-color: #fff;
+      font-size: 30px;
+      border-radius: 50%;
+      outline: none;
+      width: 28px;
+      height: 28px;
+      line-height: 28px;
+      font-size: 28px;
+      color: #8c939d;
+      display: block;
+      text-align: center;
+    }
+    img {
+      max-height: 100%;
+      vertical-align: middle;
+    }
+  }
+</style>
+
+

+ 153 - 0
src/views/music-library-manager/index.vue

@@ -0,0 +1,153 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="filter-container-lt">
+        <el-form :inline="true" label-position="left" :model="listQuery">
+          <el-form-item>
+            <el-input clearable v-model="listQuery.musicCategoryName" placeholder="音乐类目名称"
+            ></el-input>
+          </el-form-item>
+          <el-button type="primary" @click="getList()">搜索</el-button >
+            <el-button type="primary" @click="add()">新增</el-button >
+        </el-form>
+      </div>
+    </div>
+    <div class="table-container">
+      <el-table  style="width: 100%" v-loading="listLoading" :key="tableKey" :data="list" row-key="id"
+        stripe border fit highlight-current-row>
+        <el-table-column label="序号" type="index" width="60" align="center" />
+        <el-table-column label="音乐类目名称" min-width="100" align="center" prop="musicCategoryName" />
+        <el-table-column label="音乐分类" min-width="130" align="center">
+          <template slot-scope="scope">
+            {{  scope.row.type == 0 ? '类目' : '音乐' }}
+          </template>
+        </el-table-column>
+        <el-table-column label="类目排序" min-width="100" align="center" prop="musicCategorySort" />
+        <el-table-column label="操作" align="center" width="160">
+          <template slot-scope="scope">
+            <el-tooltip class="item" effect="dark" content="编辑" placement="top">
+              <el-button type="success" size="mini" icon="el-icon-edit" circle @click="handleEdit(scope.row)" />
+            </el-tooltip>
+            <el-tooltip class="more" effect="dark" content="删除" placement="top">
+              <el-button type="danger" size="mini" icon="el-icon-delete-solid" circle
+                @click="handleDelete(scope.row)" />
+            </el-tooltip>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <!-- 分页 -->
+    <swPage v-if="total > 0" key="2" :listQuery="listQuery" :total="total" pos="btmRight" @retPage="retPage" />
+    <MusicLibraryFormModal ref="MusicLibraryFormModal" @confirm="retPage"></MusicLibraryFormModal>
+  </div>
+</template>
+
+<script>
+import waves from "@/directive/waves";
+import swPage from "@/views/common/swPage";
+import { auditStatus } from "@/constants/index";
+import { getValueByKey } from "@/utils/index";
+import { fetchMusicConfigList, deteleMusicConfig } from "@/api/musicLibraryManager";
+import permission from "@/directive/permission";
+import MusicLibraryFormModal from "./components/MusicLibraryFormModal";
+
+export default {
+  name: "videoCoverManager",
+  directives: {
+    waves,
+    permission
+  },
+  components: {
+    swPage,
+    MusicLibraryFormModal
+  },
+  computed: {
+  },
+  data() {
+    return {
+      auditStatus,
+      tableKey: 0,
+      list: [],
+      total: 0,
+      listLoading: false,
+      downloadingRows: {},
+      listQuery: {
+        currentPage: 1,
+        pageSize: 10,
+        type: 0,
+        musicCategoryName: null
+      }
+    };
+  },
+  //页面创建的时候执行
+  created() {
+    this.getList();
+  },
+  methods: {
+    getValueByKey,
+    getList() {
+      this.listLoading = true;
+      const params = this.listQuery
+      if (!this.listQuery.musicCategoryName) {
+        delete params.musicCategoryName
+      }
+      fetchMusicConfigList(params).then(res => {
+        if (200 == res.code) {
+          this.total = res.data.total;
+          this.list = res.data.rows;
+        }
+        this.listLoading = false;
+      });
+    },
+    retPage() {
+      //分页
+      this.getList();
+    },
+    handleFilter() {
+      this.listQuery.page = 1;
+      this.getList();
+    },
+    handleEdit(row) {
+      this.$refs.MusicLibraryFormModal.show(row, 'edit');
+    },
+    add() {
+      this.$refs.MusicLibraryFormModal.show(null, 'add');
+    },
+    handleDelete(row) {
+      //删除
+      this.$confirm("确定要删除吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        const { id } = row;
+        deteleMusicConfig([id]).then(() => {
+          this.$notify({
+            title: "成功",
+            message: "删除成功",
+            type: "success",
+            duration: 3000
+          });
+          const index = this.list.indexOf(row);
+          this.list.splice(index, 1);
+        });
+      });
+    }
+  }
+};
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+@import "@/styles/layout.scss";
+
+.button {
+  .el-button {
+    margin-bottom: 10px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+}
+</style>

+ 180 - 0
src/views/music-library-manager/musicLibrary.vue

@@ -0,0 +1,180 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="filter-container-lt">
+        <el-form :inline="true" label-position="left" :model="listQuery">
+          <el-form-item>
+            <el-input clearable v-model="listQuery.musicName" placeholder="音乐库名称"
+            ></el-input>
+          </el-form-item>
+          <el-form-item>
+            <el-select v-model="listQuery.parentId" clearable filterable placeholder="音乐类目">
+              <el-option
+                v-for="item in musicOptions"
+                :key="item.id"
+                :label="item.musicCategoryName"
+                :value="item.id">
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-button type="primary" @click="getList()">搜索</el-button >
+            <el-button type="primary" @click="add()">新增</el-button >
+        </el-form>
+      </div>
+    </div>
+    <div class="table-container">
+      <el-table  style="width: 100%" v-loading="listLoading" :key="tableKey" :data="list" row-key="id"
+        stripe border fit highlight-current-row>
+        <el-table-column label="序号" type="index" width="60" align="center" />
+        <el-table-column label="音乐名称" min-width="100" align="center" prop="musicName" />
+        <el-table-column label="音乐分类" min-width="130" align="center">
+          <template slot-scope="scope">
+            {{  scope.row.type == 0 ? '类目' : '音乐' }}
+          </template>
+        </el-table-column>
+        <el-table-column label="音乐时长" min-width="100" align="center" prop="musicDuration" />
+        <el-table-column label="音乐地址" min-width="100" align="center" prop="musicUrl" />
+        <el-table-column label="操作" align="center" width="160">
+          <template slot-scope="scope">
+            <el-tooltip class="item" effect="dark" content="编辑" placement="top">
+              <el-button type="success" size="mini" icon="el-icon-edit" circle @click="handleEdit(scope.row)" />
+            </el-tooltip>
+            <el-tooltip class="more" effect="dark" content="删除" placement="top">
+              <el-button type="danger" size="mini" icon="el-icon-delete-solid" circle
+                @click="handleDelete(scope.row)" />
+            </el-tooltip>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <!-- 分页 -->
+    <swPage v-if="total > 0" key="2" :listQuery="listQuery" :total="total" pos="btmRight" @retPage="retPage" />
+    <musicLibraryUpdater ref="musicLibraryUpdater" @confirm="retPage"></musicLibraryUpdater>
+  </div>
+</template>
+
+<script>
+import waves from "@/directive/waves";
+import swPage from "@/views/common/swPage";
+import { auditStatus } from "@/constants/index";
+import { getValueByKey } from "@/utils/index";
+import { fetchMusicConfigList, deteleMusicConfig } from "@/api/musicLibraryManager";
+import permission from "@/directive/permission";
+import musicLibraryUpdater from "./musicLibraryUpdater";
+
+export default {
+  name: "videoCoverManager",
+  directives: {
+    waves,
+    permission
+  },
+  components: {
+    swPage,
+    musicLibraryUpdater
+  },
+  computed: {
+  },
+  data() {
+    return {
+      auditStatus,
+      tableKey: 0,
+      list: [],
+      total: 0,
+      listLoading: false,
+      downloadingRows: {},
+      listQuery: {
+        currentPage: 1,
+        pageSize: 10,
+        type: 1,
+        musicName: null,
+        parentId: null
+      },
+      musicOptions: []
+    };
+  },
+  //页面创建的时候执行
+  created() {
+    this.getMusicCategory()
+    this.getList();
+  },
+  methods: {
+    getValueByKey,
+    getMusicCategory() {
+      const params = {
+        type: 0
+      }
+      fetchMusicConfigList(params).then(res => {
+        if (res.code == 200) {
+          this.musicOptions = res.data.rows;
+        }
+      });
+    },
+    getList() {
+      this.listLoading = true;
+      const params = this.listQuery
+      if (!this.listQuery.musicName) {
+        delete params.musicName
+      }
+      if (!this.listQuery.parentId) {
+        delete params.parentId
+      }
+      fetchMusicConfigList(params).then(res => {
+        if (res.code == 200) {
+          this.total = res.data.total;
+          this.list = res.data.rows;
+        }
+        this.listLoading = false;
+      });
+    },
+    retPage() {
+      //分页
+      this.getList();
+    },
+    handleFilter() {
+      this.listQuery.page = 1;
+      this.getList();
+    },
+    handleEdit(row) {
+      this.$refs.musicLibraryUpdater.show(row, 'edit', this.musicOptions);
+    },
+    add() {
+      this.$refs.musicLibraryUpdater.show(null, 'add', this.musicOptions);
+    },
+    handleDelete(row) {
+      //删除
+      this.$confirm("确定要删除吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        const { id } = row;
+        deteleMusicConfig([id]).then(() => {
+          this.$notify({
+            title: "成功",
+            message: "删除成功",
+            type: "success",
+            duration: 3000
+          });
+          const index = this.list.indexOf(row);
+          this.list.splice(index, 1);
+        });
+      });
+    }
+  }
+};
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+@import "@/styles/layout.scss";
+
+.button {
+  .el-button {
+    margin-bottom: 10px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+}
+</style>

+ 457 - 0
src/views/music-library-manager/musicLibraryUpdater.vue

@@ -0,0 +1,457 @@
+<template>
+  <el-dialog :title="(modelType == 'add' ? '添加' : '编辑') + '音乐库'" width="1000px" :visible.sync="dialogVisible">
+    <div class="brand-video-editor">
+      <el-form :model="form" :rules="rules" ref="MusicLibraryForm">
+        <div class="brand-video-editor__top">
+          <div class="type-black">
+            <div class="type-black__ul">
+              <ul>
+                <li>
+                  <el-form-item prop="parentId" label="选择现有音乐类型:">
+                    <div class="type-black__select">
+                      <el-select v-model="form.parentId" placeholder="请选择音乐类型">
+                        <el-option
+                          v-for="item in musicTypes"
+                          :key="item.id"
+                          :label="item.musicCategoryName"
+                          :value="item.id">
+                        </el-option>
+                      </el-select>
+                    </div>
+                  </el-form-item>
+                </li>
+                <li>
+                  <el-form-item prop="musicName" label="音乐库名称:">
+                    <div class="type-black__input">
+                      <el-input v-model="form.musicName" placeholder="音乐库名称"></el-input>
+                    </div>
+                  </el-form-item>
+                </li>
+              </ul>
+            </div>
+          </div>
+          <div class="video-upload">
+            <el-form-item prop="musicUrl" label="上传视频/音频文件:" required>
+              <div class="upload-black">
+                <!-- action必选参数, 上传的地址 -->
+                <el-upload class="avatar-uploader el-upload--text" 
+                  :action="action" 
+                  :show-file-list="false" 
+                  :headers="{
+                    'Authorization': 'Bearer ' + token
+                  }"
+                  :disabled="videoFlag"
+                  accept="video/*,audio/*"
+                  :on-success="handleVideoSuccess" 
+                  :before-upload="beforeUploadVideo" 
+                  :on-progress="uploadVideoProcess">
+                  <div class="video-black__warp">
+                    <div class="music--black" v-if="form.musicUrl && !videoFlag">
+                      <span class="music--icon"><img src="../../assets/image/file-icon.svg" alt=""></span>
+                      <span class="music--title">{{ musicFile.title }}</span>
+                      <span class="music--size">{{ musicFile.size }}</span>
+                      <el-tooltip
+                        class="item"
+                        effect="dark"
+                        content="删除"
+                        placement="bottom-end">
+                          <i class="close el-icon-circle-close"
+                          @click.stop="imgUploadDel()"></i>
+                      </el-tooltip>
+                    </div>
+                    <p class="text-black" v-else-if="!form.musicUrl && !videoFlag">
+                      <span class="upload-icon"><img src="../../assets/image/upload-icon.svg" alt=""></span>
+                      <span class="_text_">选择文件或者拖拽上传视频/音频</span>
+                      <span class="subtext">支持MP4、MP3文件,最大200MB</span>
+                      <a href="javascript:;" class="file-btns">浏览文件</a>
+                    </p>
+                    <div class="progress-black" v-if="videoFlag">
+                      <div class="progress--text">上传中...</div>
+                      <el-progress color="#ae8877" :stroke-width="10" :percentage="videoUploadPercent" :show-text="false"></el-progress>
+                    </div>
+                    
+                  </div>
+                </el-upload>
+              </div>
+            </el-form-item>
+          </div>
+        </div>
+        <div class="music-library-btns">
+          <el-button type="primary" class="music-library__a" :loading="comfirmLoading" @click="handleConfirm">更新音乐库</el-button>
+        </div>
+      </el-form>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { api } from "@/api/api";
+import { getToken } from '@/utils/auth'
+export default {
+  name: "MusicLibraryUpdater",
+  components: {
+    
+  },
+  computed: {
+    token() {
+      return getToken();
+    }
+  },
+  data() {
+    var checkMusicUrl = (rule, value, callback) => {
+      if (!value) {
+        callback(new Error('请上传视频/音频文件'));
+      } else {
+        callback();
+      }
+    };
+    return {
+      action: api.fileUrl,
+      form: {
+        musicName: '',
+        musicUrl: '',
+        parentId: ''
+      },
+      modelType: 'add',
+      dialogVisible: false,
+      comfirmLoading: false,
+      editId: '',
+      videoFlag: false,
+      videoUploadPercent: 0,
+      musicTypes: [],
+      musicFile: {
+        title: '官方剪辑.MP4',
+        size: '4.8 MB'
+      },
+      rules: {
+        musicName: [
+          { required: true, message: "请输入音乐库名称", trigger: "blur" }
+        ],
+        parentId: [
+          { required: true, message: "请选择音乐类目", trigger: "change" }
+        ],
+        musicUrl: [
+          { validator: checkMusicUrl, trigger: "change" }
+        ]
+      },
+      progressTimer: null
+    };
+  },
+  watch: {
+    dialogVisible(val) {
+      if (!val) {
+        this.form = {
+          musicName: '',
+          musicUrl: '',
+          parentId: ''
+        }
+        this.modelType =  'add';
+        this.comfirmLoading = false;
+        this.editId = '';
+        this.musicFile = {
+          title: '',
+          size: ''
+        }
+      }
+    }
+  },
+  methods: {
+    show(rows, type, musicOptions) {
+      this.dialogVisible = true;
+      this.comfirmLoading = false;
+      this.modelType = type;
+      this.musicTypes = musicOptions;
+      if (type == 'edit') {
+        this.editId = rows.id;
+      }
+      this.$nextTick(() => {
+        this.form = type == 'edit' ? {
+          musicName: rows.musicName,
+          musicUrl: rows.musicUrl,
+          parentId: rows.parentId
+        } : {
+          musicName: '',
+          musicUrl: '',
+          parentId: ''
+        }
+        this.$refs.MusicLibraryForm.resetFields()
+      })
+    },
+    handleConfirm() {
+      this.$refs.MusicLibraryForm.validate(valid => {
+        if (valid) {
+          this.comfirmLoading = true;
+          const params = this.form;
+          if (this.modelType == 'add') {
+            addMusicConfig(params).then(res =>{
+              this.dialogVisible = false;
+              if(res.code == 200){
+                this.$message.success(res.msg || "操作成功");
+                this.$emit("confirm");
+              }
+            }).finally(()=>{
+              this.comfirmLoading = false;
+            })
+          } else {
+            params.id = this.editId;
+            editMusicConfig(params).then(res =>{
+              this.dialogVisible = false;
+              if(res.code == 200){
+                this.$message.success(res.msg || "操作成功");
+                this.$emit("confirm");
+              }
+            }).finally(()=>{
+              this.comfirmLoading = false;
+            })
+          }
+          
+        } else {
+          return false;
+        }
+      });
+    },
+    beforeUploadVideo(file) {
+      const isLt10M = file.size / 1024 / 1024 < 200;
+      const allowedTypes = [
+        'video/mp4', 'video/ogg', 'video/flv', 'video/avi', 'video/wmv', 'video/rmvb',
+        'audio/mp3', 'audio/mpeg', 'audio/wav', 'audio/ogg', 'audio/x-m4a'
+      ];
+      if (!allowedTypes.includes(file.type)) {
+        this.$message.error('请上传正确的视频或音频格式');
+        return false;
+      }
+      if (!isLt10M) {
+        this.$message.error('上传文件大小不能超过200MB哦!');
+        return false;
+      }
+      this.progressTimer = setInterval(() => {
+        if (this.videoUploadPercent < 98) {
+          this.videoUploadPercent += 5;
+        } else {
+          clearInterval(this.progressTimer);
+        }
+      }, 200);
+    },
+    uploadVideoProcess(event, file, fileList) {
+      this.videoFlag = true;
+      // this.videoUploadPercent = file.percentage;
+    },
+    handleVideoSuccess(res, file) {
+      clearInterval(this.progressTimer);
+      this.videoFlag = false;
+      this.videoUploadPercent = 0;
+      this.$refs.MusicLibraryForm.clearValidate(['musicUrl']);
+      if (res.code == 200) {
+        this.musicFile = {
+          title: res.data.fileName,
+          size: res.data.size
+        }
+        this.form.musicUrl = res.data.url;
+      } else {
+        this.$message.error('上传失败,请重新上传!');
+      }
+    },
+    imgUploadDel() {
+      //删除
+      this.$confirm("确定要删除吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.form.musicUrl = '';
+        this.musicFile = {
+          title: '',
+          size: ''
+        }
+        this.$notify({
+          title: "成功",
+          message: "删除成功",
+          type: "success",
+          duration: 3000
+        });
+      });
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+  .brand-video-editor {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    height: 100%;
+    padding: 20px;
+
+    .brand-video-editor__top {
+      display: flex;
+      justify-content: space-between;
+      gap: 3.6vw;
+      align-items: stretch;
+
+      .video-upload {
+        flex: 1;
+        max-width: 700px;
+      }
+
+      .video-black__warp {
+        width: 100%;
+        max-width: 70%;
+        display: flex;
+        justify-content: center;
+
+        .progress-black {
+          width: 100%;
+        }
+
+        .music--black {
+          position: relative;
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          width: 110px;
+
+          .music--icon {
+            width: 80px;
+
+            img {
+              display: block;
+              max-width: 100%;
+            }
+          }
+          .music--title {
+            font-size: 14px;
+            color: #232323;
+            font-weight: bold;
+            line-height: 1.5;
+            margin: 10px 0;
+            white-space: nowrap;
+            overflow: hidden;
+            max-width: 100%;
+            text-overflow: ellipsis;
+          }
+          .music--size {
+            font-size: 14px;
+            font-weight: bold;
+            color: #ae8877;
+            line-height: 1.5;
+          }
+          .close {
+            position: absolute;
+            top: -20px;
+            right: -20px;
+            cursor: pointer;
+            z-index: 999999;
+            color: red;
+            background-color: #fff;
+            font-size: 30px;
+            border-radius: 50%;
+            outline: none;
+            width: 20px;
+            height: 20px;
+            line-height: 20px;
+            font-size: 20px;
+            color: #8c939d;
+            display: block;
+            text-align: center;
+          }
+        }
+      }
+
+      .upload-black {
+        width: 100%;
+
+        .avatar-uploader {
+          display: block;
+          width: 100%;
+          height: 100%;
+
+          /deep/ .el-upload {
+            display: flex;
+            width: 100%;
+            height: 100%;
+            justify-content: center;
+            align-items: center;
+            padding: 50px 0;
+            border: 1px dashed #d9d9d9;
+            border-radius: 10px;
+            min-height: 280px;
+          }
+        }
+        .text-black {
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          margin: 0;
+          gap: 10px;
+
+          .upload-icon {
+            width: 48px;
+            height: 48px;
+
+            img {
+              display: block;
+              width: 100%;
+            }
+          }
+          ._text_ {
+            font-size: 18px;
+            color: #292D32;
+            line-height: 1.5;
+          }
+          .subtext {
+            font-size: 16px;
+            color: #A9ACB4;
+            line-height: 1.5;
+          }
+
+          a.file-btns {
+            display: flex;
+            font-size: 16px;
+            justify-content: center;
+            align-items: center;
+            height: 40px;
+            border-radius: 4px;
+            border: 1px solid #CBD0DC;
+            padding: 0 30px;
+            color: #54575C;
+          }
+        }
+      }
+
+      .type-black {
+        flex: 1;
+
+        ul {
+          padding: 0;
+          margin: 0;
+        }
+
+        li {
+          list-style: none;
+
+          /deep/ .el-select {
+            width: 100%;
+          }
+        }
+        li + li {
+          margin-top: 30px;
+        }
+      }
+    }
+    .music-library-btns {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      margin-top: 50px;
+
+      /deep/ .music-library__a {
+        font-size: 16px;
+        background: #ae8877;
+        color: #fff;
+        padding: 15px 80px;
+        border-radius: 4px;
+      }
+    }
+  }
+</style>

+ 270 - 0
src/views/video-cover-manager/components/VideoCoverFormModal.vue

@@ -0,0 +1,270 @@
+<template>
+  <el-dialog :title="(modelType == 'add' ? '添加' : '编辑') + '店铺信息'" width="800px" :visible.sync="dialogVisible">
+    <el-form :model="form" :rules="rules" ref="VideoCoverFormForm" label-width="100px">
+      <el-form-item prop="shopName" label="店铺名称:">
+        <el-input placeholder="请输入店铺名称" v-model="form.shopName"></el-input>
+      </el-form-item>
+      <el-form-item prop="coverPicture" label="封面图:" required>
+        <el-upload
+          class="avatar-uploader"
+          :action="action"
+          accept="image/*"
+          :show-file-list="false"
+          :headers="{
+            'Authorization': 'Bearer ' + token
+          }"
+          :on-success="handleAvatarSuccess"
+          :before-upload="beforeAvatarUpload">
+          <div v-loading="uploading">
+            <div v-if="form.coverPicture" class="avatar-black">
+              <img :src="form.coverPicture" class="avatar">
+              <el-tooltip
+                class="item"
+                effect="dark"
+                content="删除"
+                placement="bottom-end">
+                  <i class="close el-icon-circle-close"
+                  @click.stop="imgUploadDel()"></i>
+              </el-tooltip>
+            </div>
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+          </div>
+        </el-upload>
+      </el-form-item>
+      <el-form-item prop="coverText" label="封面文字:">
+        <el-input placeholder="请输入封面文字" v-model="form.coverText"></el-input>
+      </el-form-item>
+      <el-form-item label="平台类型:" required>
+        <el-radio-group v-model="form.type">
+          <el-radio :label="0">品牌(国内)</el-radio>
+          <el-radio :label="1">海外</el-radio>
+        </el-radio-group>
+      </el-form-item>
+    </el-form>
+
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="dialogVisible = false">取消</el-button>
+      <el-button type="primary" :loading="comfirmLoading" @click="handleConfirm">确定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import { addShopConfigInfo, editShopConfigInfo } from "@/api/videoCoverManager";
+import { api } from "@/api/api";
+import { getToken } from '@/utils/auth'
+export default {
+  name: "VideoCoverFormModal",
+  props: {
+  },
+  data() {
+    var checkCoverPicture = (rule, value, callback) => {
+      if (!value) {
+        callback(new Error('请上传封面图'));
+      } else {
+        callback();
+      }
+    };
+    return {
+      action: api.fileUrl,
+      uploading: false,
+      form: {
+        shopName: '',
+        coverPicture: '',
+        coverText: '',
+        type: 0
+      },
+      modelType: 'add',
+      dialogVisible: false,
+      comfirmLoading: false,
+      editId: '',
+      shopName: '', // 店铺名称不能重复
+      rules: {
+        shopName: [
+          { required: true, message: "请输入店铺名称", trigger: "blur" }
+        ],
+        coverText: [
+          { required: true, message: "请输入封面文字", trigger: "blur" }
+        ],
+        coverPicture: [
+          { validator: checkCoverPicture, trigger: "change" }
+        ]
+      }
+    };
+  },
+  computed: {
+    token() {
+      return getToken();
+    }
+  },
+  watch: {
+    dialogVisible(val) {
+      if (!val) {
+        this.uploading = false;
+        this.form = {
+          shopName: '',
+          coverPicture: '',
+          coverText: '',
+          type: 0
+        }
+        this.modelType =  'add';
+        this.comfirmLoading = false;
+        this.editId = '';
+      }
+    }
+  },
+  methods: {
+    show(rows, type) {
+      this.dialogVisible = true;
+      this.comfirmLoading = false;
+      this.modelType = type;
+      if (type == 'edit') {
+        this.editId = rows.id;
+        this.shopName = rows.shopName;
+      }
+      this.$nextTick(() => {
+        this.form = type == 'edit' ? {
+          shopName: rows.shopName,
+          coverPicture: rows.coverPicture,
+          coverText: rows.coverText,
+          type: rows.type
+        } : {
+          shopName: '',
+          coverPicture: '',
+          coverText: '',
+          type: 0
+        }
+        this.$refs.VideoCoverFormForm.resetFields()
+      })
+    },
+    handleAvatarSuccess(res) {
+      this.uploading = false
+      this.$refs.VideoCoverFormForm.clearValidate(['coverPicture']);
+      if (res.code == 200) {
+        this.form.coverPicture = res.data.url;
+      } else {
+        this.$message.error('上传出错,请重试!');
+      }
+    },
+    beforeAvatarUpload(file) {
+      this.uploading = true;
+      const imagesTypes = ['image/png','image/gif','image/jpeg']
+      const isImages = imagesTypes.includes(file.type)
+
+      if (!isImages) {
+        this.uploading = false;
+        this.$message.error('图片只能是JPG、PNG、GIF格式!');
+      }
+      return isImages;
+    },
+    imgUploadDel() {
+      //删除
+      this.$confirm("确定要删除吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.form.coverPicture = '';
+        this.$notify({
+          title: "成功",
+          message: "删除成功",
+          type: "success",
+          duration: 3000
+        });
+      });
+    },
+    handleConfirm() {
+      this.$refs.VideoCoverFormForm.validate(valid => {
+        if (valid) {
+          this.comfirmLoading = true;
+          const params = this.form;
+          if (this.modelType == 'add') {
+            addShopConfigInfo(params).then(res =>{
+              this.dialogVisible = false;
+              if(res.code == 200){
+                this.$message.success(res.msg || "操作成功");
+                this.$emit("confirm");
+              }
+            }).finally(()=>{
+              this.comfirmLoading = false;
+            })
+          } else {
+            params.id = this.editId;
+            if (this.shopName == this.form.shopName) {
+              // 说明没有更新店铺名,店铺名必须唯一
+              delete params.shopName;
+            }
+            editShopConfigInfo(params).then(res =>{
+              this.dialogVisible = false;
+              if(res.code == 200){
+                this.$message.success(res.msg || "操作成功");
+                this.$emit("confirm");
+              }
+            }).finally(()=>{
+              this.comfirmLoading = false;
+            })
+          }
+          
+        } else {
+          return false;
+        }
+      });
+    }
+  }
+};
+</script>
+<style lang="scss">
+  .avatar-uploader .el-upload {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+  }
+  .avatar-uploader .el-upload:hover {
+    border-color: #409EFF;
+  }
+  .avatar-uploader-icon {
+    font-size: 28px;
+    color: #8c939d;
+    width: 178px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+  }
+  .avatar {
+    display: block;
+  }
+  .avatar-black {
+    width: 180px;
+    height: 180px;
+    position: relative;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    i {
+      position: absolute;
+      top: -10px;
+      right: -10px;
+      cursor: pointer;
+      z-index: 999999;
+      color: red;
+      background-color: #fff;
+      font-size: 30px;
+      border-radius: 50%;
+      outline: none;
+      width: 28px;
+      height: 28px;
+      line-height: 28px;
+      font-size: 28px;
+      color: #8c939d;
+      display: block;
+      text-align: center;
+    }
+    img {
+      max-height: 100%;
+      vertical-align: middle;
+    }
+  }
+</style>
+
+

+ 179 - 0
src/views/video-cover-manager/index.vue

@@ -0,0 +1,179 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="filter-container-lt">
+        <el-form :inline="true" label-position="left" :model="listQuery">
+          <el-form-item>
+            <el-input clearable v-model="listQuery.shopName" placeholder="店铺名称"
+            ></el-input>
+          </el-form-item>
+          <el-form-item>
+            <el-select v-model="listQuery.type" clearable filterable placeholder="平台类型">
+              <el-option
+                v-for="item in typesOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value">
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-button type="primary" @click="getList()">搜索</el-button >
+            <el-button type="primary" @click="add()">新增</el-button >
+        </el-form>
+      </div>
+    </div>
+    <div class="table-container">
+      <el-table  style="width: 100%" v-loading="listLoading" :key="tableKey" :data="list" row-key="id"
+        stripe border fit highlight-current-row>
+        <el-table-column label="序号" type="index" width="60" align="center" />
+        <el-table-column label="店铺名" min-width="100" align="center" prop="shopName" />
+        <el-table-column label="封面图" min-width="130" align="center">
+          <template slot-scope="scope">
+            <el-image 
+              style="width: 100px;"
+              :src="scope.row.coverPicture" 
+              :preview-src-list="[scope.row.coverPicture]">
+            </el-image>
+          </template>
+        </el-table-column>
+        <el-table-column label="封面文字" min-width="100" align="center" prop="coverText" />
+        <el-table-column label="平台类型" min-width="130" align="center">
+          <template slot-scope="scope">
+            {{  scope.row.type == 0 ? '品牌(国内)' : '海外' }}
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center" width="160">
+          <template slot-scope="scope">
+            <el-tooltip class="item" effect="dark" content="编辑" placement="top">
+              <el-button type="success" size="mini" icon="el-icon-edit" circle @click="handleEdit(scope.row)" />
+            </el-tooltip>
+            <el-tooltip class="more" effect="dark" content="删除" placement="top">
+              <el-button type="danger" size="mini" icon="el-icon-delete-solid" circle
+                @click="handleDelete(scope.row)" />
+            </el-tooltip>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <!-- 分页 -->
+    <swPage v-if="total > 0" key="2" :listQuery="listQuery" :total="total" pos="btmRight" @retPage="retPage" />
+    <VideoCoverFormModal ref="VideoCoverFormModal" @confirm="retPage"></VideoCoverFormModal>
+  </div>
+</template>
+
+<script>
+import waves from "@/directive/waves";
+import swPage from "@/views/common/swPage";
+import { auditStatus } from "@/constants/index";
+import { getValueByKey } from "@/utils/index";
+import { shopConfigInfoList, deteleShopConfigInfo } from "@/api/videoCoverManager";
+import { mapGetters } from "vuex";
+import permission from "@/directive/permission";
+import VideoCoverFormModal from "./components/VideoCoverFormModal";
+
+
+export default {
+  name: "videoCoverManager",
+  directives: {
+    waves,
+    permission
+  },
+  components: {
+    swPage,
+    VideoCoverFormModal
+  },
+  computed: {
+    
+  },
+  data() {
+    return {
+      auditStatus,
+      tableKey: 0,
+      list: [],
+      total: 0,
+      listLoading: false,
+      downloadingRows: {},
+      listQuery: {
+        currentPage: 1,
+        pageSize: 10,
+        shopName: null,
+        type: null //平台类型 0:品牌 1:海外
+      }
+    };
+  },
+  //页面创建的时候执行
+  created() {
+    this.getList();
+  },
+  computed: {
+    typesOptions() {
+      return [
+        {value: '0', label: '品牌(国内)'},
+        {value: '1', label: '海外'}
+      ]
+    }
+  },
+  methods: {
+    getValueByKey,
+    getList() {
+      this.listLoading = true;
+      shopConfigInfoList(this.listQuery).then(res => {
+        if (200 == res.code) {
+          this.total = res.data.total;
+          this.list = res.data.rows;
+        }
+        this.listLoading = false;
+      });
+    },
+    retPage() {
+      //分页
+      this.getList();
+    },
+    handleFilter() {
+      this.listQuery.page = 1;
+      this.getList();
+    },
+    handleEdit(row) {
+      this.$refs.VideoCoverFormModal.show(row, 'edit');
+    },
+    add() {
+      this.$refs.VideoCoverFormModal.show(null, 'add');
+    },
+    handleDelete(row) {
+      //删除
+      this.$confirm("确定要删除吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        const { id } = row;
+        deteleShopConfigInfo([id]).then(() => {
+          this.$notify({
+            title: "成功",
+            message: "删除成功",
+            type: "success",
+            duration: 3000
+          });
+          const index = this.list.indexOf(row);
+          this.list.splice(index, 1);
+        });
+      });
+    }
+  }
+};
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+@import "@/styles/layout.scss";
+
+.button {
+  .el-button {
+    margin-bottom: 10px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+}
+</style>

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.