Просмотр исходного кода

1、语音卡
2、博主企微备注+拉黑

huangmp 2 лет назад
Родитель
Сommit
d006dd1c68

+ 998 - 0
src/components/AudioBox/index.vue

@@ -0,0 +1,998 @@
+<template>
+  <div class="elx-imgbox">
+    <el-dialog
+      title="音频管理器"
+      :visible.sync="visible"
+      class="elx-imgbox-dialog"
+      @close="handleDialogClose"
+      width="900px"
+      :append-to-body="visible"
+    >
+      <el-tabs v-model="options.activeTab" tab-position="top" @tab-click="tabClick">
+        <el-tab-pane
+          label="选择音频"
+          name="pick"
+          class="pick-block"
+        >
+          <div class="elx-img-list-loading" v-if="isLoading">
+            <div class="el-icon-loading"></div>
+          </div>
+          <el-form :inline="true" :model="dataForm" class="demo-form-inline form">
+            <el-form-item>
+              <el-input
+                v-model="fileName"
+                size="medium"
+                :placeholder="this.$i18n.t('videoManager.videoName')"
+                clearable
+              ></el-input>
+            </el-form-item>
+            <el-form-item>
+              <div
+                @click="searchImg"
+                class="primary-btn default-btn"
+              >{{$t("videoManager.query")}}</div>
+              <div
+                class="default-btn primary-btn"
+                @click="options.activeTab='upload'"
+                plain
+                v-if="options.enableUpload"
+                style="margin-left:10px"
+              >上传音频</div>
+            </el-form-item>
+            <!-- <el-form-item>
+              <el-button type="primary" @click="clean">清空</el-button>
+            </el-form-item>-->
+          </el-form>
+          <div class="box">
+            <div class="group">
+              <div :class="['group-item',groupId === 0 ?'active': '']"  @click="clickGroup(0)">
+                <span class="group-name">全部音频</span>
+              </div>
+              <div :class="['group-item',groupId === item.attachFileGroupId ?'active': '']" v-for="(item,index) in groupList" :key="item.attachFileGroupId">
+                <span class="group-name" @click="clickGroup(item.attachFileGroupId)">{{ item.name }}</span>
+              </div>
+            </div>
+            <div class="img-list">
+              <div class="elx-main elx-img-list">
+                <div v-for="(img, itemIndex) in imgRes.records" :key="itemIndex" class="img-item">
+                  <div class="thumb-wp" @click="onClickListImage(img)">
+                    <!-- <img v-if="img.filePath" :src="(img.filePath).indexOf('http')===-1 ? resourcesUrl + img.filePath : img.filePath" alt="img.name" /> -->
+                    <video
+                      :src="resourcesUrl + img.filePath"
+                      controls="controls"
+                      class="showVideo"
+                      style="width:175px;height:87.5px;"
+                    />
+                    </div>
+                    <div class="title" @click="onClickListImage(img)">{{ img.fileName }}</div>
+                    <!-- <div class="label" v-if="img.label">{{img.label}}</div> -->
+                    <span v-if="img.selected" class="selected" @click="onClickListImage(img)">
+                      <span class="icon el-icon-check" />
+                    </span>
+                  </div>
+                </div>
+                <div class="data-tips" v-if="!imgRes.records.length">{{$t("order.noData")}}</div>
+                <el-pagination
+                    layout="total, prev, pager, next"
+                    :current-page="imgRes.current"
+                    :page-size="imgRes.size"
+                    :total="imgRes.total"
+                    @current-change="onPageNumChange"
+                ></el-pagination>
+            </div>
+          </div>
+          <div class="elx-foot">
+            <el-badge :value="images.length" class="item" v-if="!type">
+              <div class="default-btn" @click="visible = false">{{$t("resource.cancel")}}</div>
+              <div
+                :class="[images.length == 0?'disabled-btn':'','default-btn primary-btn']"
+                :disabled="images.length == 0"
+                @click="onConfirm"
+                style="margin-right:3px;"
+              >{{$t("resource.confirm")}}</div>
+            </el-badge>
+            <div
+              :class="[images.length == 0?'disabled-btn':'','default-btn primary-btn']"
+              :disabled="disabled"
+              @click="onConfirm"
+              v-else
+            >{{$t("resource.confirm")}}</div>
+          </div>
+        </el-tab-pane>
+
+        <el-tab-pane
+          label="上传音频"
+          name="upload"
+          class="upload-block"
+          v-if="options.enableUpload"
+        >
+          <div class="elx-upload-main">
+            <div class="upload-title">{{$t("resource.selectGroup")}}:</div>
+            <div class="select-group-box">
+              <div class="select-group-box-item">{{$t("resource.group")}}:</div>
+              <el-select size="small" v-model="selectGroup" clearable :placeholder="$t('resource.selectGroup')" class="select-group-box-item">
+                <el-option
+                  v-for="item in groupList"
+                  :key="item.attachFileGroupId"
+                  :label="item.name"
+                  :value="item.attachFileGroupId">
+                </el-option>
+              </el-select>
+            </div>
+            <div class="upload-title">选择本地音频</div>
+            <!-- 视频预览 -->
+              <div class="upload-video-box">
+                <div v-for="(item, index) in videoList" :key="index" class="video-preview">
+                <video
+                  v-if="item.url"
+                  class="upShowVideo"
+                  :src="item.url"
+                  controls="controls"
+                  style="width:175px;height:87.5px;"
+                />
+                <!-- 显示查看和删除的按钮弹窗 -->
+                <div
+                  class="avatar-uploader-popup"
+                >
+                  <i class="el-icon-delete" @click="preDeleteVideo(index)" />
+                </div>
+              </div>
+            </div>
+            <el-upload
+              ref="upload"
+              class="upload-img-preview"
+              list-type="picture-card"
+              action=""
+              :headers="{Authorization: $cookie.get('Authorization_vs'),locale:lang}"
+              :multiple="true"
+              accept="audio/*"
+              :auto-upload="false"
+              :show-file-list="false"
+              :limit="options.limit"
+              :before-upload="beforeUploadVideo"
+              :http-request="httpRequest"
+              :on-change="onUploadChange"
+              :on-progress="onUploadProgress"
+              :on-success="onUploadSuccess"
+              :on-error="onUploadError"
+              :on-exceed="onUploadExceedTip"
+            >
+              <i class="el-icon-plus"></i>
+            </el-upload>
+
+            <div class="upload-tip">{{ uploadTips() }}</div>
+
+            <div class="elx-upload-foot">
+              <div @click="options.activeTab = 'pick'" class="default-btn">{{$t("shopFeature.edit.back")}}</div>
+              <div
+                class="primary-btn default-btn"
+                @click="onUploadConfirm"
+              >{{$t("videoManager.confirmUpload")}}</div>
+            </div>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </el-dialog>
+  </div>
+</template>
+
+<script type="text/babel">
+export default {
+  name: 'ElxVideobox',
+  data () {
+    return {
+      lang: localStorage.getItem('lang') || 'zh_CN',
+      images: [], // 已选视频
+      fileIds: [], // 已选视频的fileId
+      dataForm: {},
+      uploadFileNum: 0,
+      groupVisible: false,
+      showBatchMove: false,
+      options: {
+        multiple: true, // 是否支持选取多个视频
+        limit: 20, // 最多可选择视频数量
+        maxSize: 2, // 最大尺寸(M)
+        activeTab: 'pick',
+        enableUpload: true, // 是否启用视频上传
+        callback: null
+      },
+      groupList: [], // 分组列表
+      selectGroup: '',
+      showGroupType: 0, // 0:新建分组 1:修改分组
+      newImgName: '',
+      isTrue: true,
+      imageObject: null,
+      errShow: false,
+      picNum: 0,
+      resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+      changeNameVisible: false,
+      type: 4,
+      fileName: '',
+      isLoading: true,
+      visible: false,
+      disabled: false,
+      notImg: false,
+      uploadSuccessCount: 0,
+      imgRes: {
+        current: 1
+      },
+      videoList: [],
+      isSubmit: false,
+      uploadFlag: 0,
+      selectAll: false,
+      groupId: 0 // 点击分组
+    }
+  },
+
+  methods: {
+    /**
+     * 初始化
+     * type 1:单  2:多
+     */
+    init (type, limit) {
+      this.visible = true
+      this.isLoading = false
+      this.images = []
+      this.fileIds = []
+      this.type = type
+      if (type === 1) {
+        this.type = true
+        this.disabled = true
+      } else {
+        this.type = false
+        this.limit = limit
+      }
+      if (this.$refs.upload) {
+        this.$refs.upload.uploadFiles = []
+      }
+      // 获取产品数据 - 第一页的数据
+      this.loadListImage(1)
+      this.getGroupList()
+    },
+    show () {
+      this.visible = true
+    },
+
+    hide () {
+      this.visible = false
+    },
+
+    onConfirm () {
+      if (this.type) {
+        this.$emit('refreshPic', this.images[0].filePath)
+      } else {
+        let imgPaths = this.images.map(file => {
+          return file.filePath
+        }).join(',')
+        this.$emit('refreshPic', imgPaths)
+      }
+      this.visible = false
+    },
+    /**
+     * 提交修改后的视频名称
+     */
+    submitImgName () {
+      if (!this.isTrue) {
+        return false
+      }
+      this.isTrue = false
+      this.$http({
+        url: this.$http.adornUrl('/admin/file/updateFile'),
+        method: 'put',
+        data: this.$http.adornData({
+          fileId: this.imageObject.fileId,
+          fileName: this.newImgName,
+          attachFileGroupId: this.selectGroup,
+          type: 4
+        })
+      }).then(({ data }) => {
+        this.newImgName = ''
+        this.isTrue = true
+        this.selectGroup = ''
+        this.changeNameVisible = false
+        this.loadListImage(this.imgRes.current)
+      }).catch(({ e }) => {
+        this.isTrue = true
+      })
+    },
+    submitBatchMove () {
+      if (!this.selectGroup) {
+        return
+      }
+      this.$http({
+        url: this.$http.adornUrl('/admin/file/batchMove'),
+        method: 'put',
+        data: this.fileIds,
+        params: {
+          groupId: this.selectGroup
+        }
+      }).then(({ data }) => {
+        this.images = []
+        this.fileIds = []
+        this.showBatchMove = false
+        this.selectAll = false
+        this.loadListImage()
+      })
+    },
+    /**
+     * 点击视频时选中或取消选中视频
+     * @param img object
+     */
+    onClickListImage (img) {
+      // if(!this.uploadNumberLimit()) {
+      //   return this.onUploadExceedTip()
+      // }
+      // 单选图片
+      if (this.type) {
+        this.clearListSelected()
+        this.images = []
+        this.fileIds = []
+        this.disabled = false
+      } else {
+        // 多选图片-如果已选中则取消选中
+        var imgIndex = this.selectedImageIndex(img)
+        if (imgIndex >= 0) {
+          // 取消图片已选状态
+          img.selected = false
+          this.images.splice(imgIndex, 1)
+          this.fileIds.splice(imgIndex, 1)
+          return
+        }
+      }
+      if (this.type && !this.uploadNumberLimit()) {
+        this.message(this.$i18n.t('pictureManager.superiorLimit'))
+        return false
+      }
+      this.images.push(JSON.parse(JSON.stringify(img)))
+      this.fileIds.push(img.fileId)
+      img.selected = true
+    },
+    /**
+     * 清除所有已点击视频样式
+     */
+    clearListSelected () {
+      if (this.type) {
+        let list = this.imgRes.records
+        list.forEach(element => {
+          element.selected = false
+        })
+      }
+    },
+    /**
+         * 按视频名称搜索视频
+         */
+    searchImg () {
+      this.loadListImage(1)
+    },
+    /**
+     * 加载视频列表数据
+     * @param page
+     */
+    loadListImage (current) {
+      this.isLoading = true
+      this.$http({
+        url: this.$http.adornUrl('/admin/file/attachFilePage'),
+        method: 'get',
+        params: this.$http.adornParams({
+          current: current,
+          size: 9,
+          fileName: this.fileName ? this.fileName : null,
+          attachFileGroupId: this.groupId,
+          type: 4
+        })
+      }).then(({ data }) => {
+        this.imgRes = data
+        this.imgRes.records.forEach(img => {
+          img.selected = false
+        })
+        this.isLoading = false
+      })
+    },
+
+    /**
+     * 视频已选则返回下标,未选则返回-1
+     */
+    selectedImageIndex (img) {
+      for (let i = 0; i < this.images.length; i++) {
+        var selectedImg = this.images[i]
+        if (selectedImg.fileId === img.fileId) {
+          return i
+        }
+      }
+      return -1
+    },
+
+    /**
+     * 分页页面变化时刷新数据
+     * @param page
+     */
+    onPageNumChange (page) {
+      this.loadListImage(page)
+    },
+    /**
+     * 获取分组列表
+     */
+    getGroupList () {
+      this.$http({
+        url: this.$http.adornUrl('/admin/fileGroup/list'),
+        method: 'get',
+        params: {
+          type: 4 // 1、视频 2、视频 3、文件 4、音频
+        }
+      }).then(res => {
+        this.groupList = res.data
+      })
+    },
+    /**
+     * 点击分组
+     */
+    clickGroup (id) {
+      this.groupId = id
+      this.loadListImage(1)
+    },
+    /**
+     * 提交上传
+     */
+    onUploadConfirm () {
+      this.notImg = true
+      this.isSubmit = true
+      this.fileIds = []
+      this.uploadFlag = 0
+      this.$refs.upload.submit()
+    },
+
+    onUploadProgress (event, file, fileList) {
+
+    },
+    /**
+     * 上传视频
+     */
+    httpRequest (event) {
+      this.videoList.forEach(item => {
+        if (item.uid === event.file.uid) {
+          this.uploadFile(event)
+          this.notImg = true
+        }
+      })
+    },
+    uploadFile (event) {
+      const file = event.file
+      // 获取本次上传文件的位置
+      const formdata = new FormData()
+      formdata.append('FileName', file.name)
+      formdata.append('file', file)
+      this.$http({
+        url: this.$http.adornUrl('/admin/file/upload/element'),
+        method: 'post',
+        headers: {
+          'Content-Type': file.type
+        },
+        data: formdata
+      }).then(res => {
+        event.onSuccess(res.data)
+      })
+    },
+    // 视频预上传
+    onUploadChange (file, fileList) {
+      let extend = file.raw.name.split(".")[1]
+      if (["wav", "mp3", "ogg", "acc", "webm", "amr"].indexOf(extend) === -1) {
+        this.$newMessage.error(this.$i18n.t('videoManager.tips2'))
+        return false
+      }
+      if (this.isSubmit) {
+        return
+      }
+      const showVideoList = document.getElementsByClassName('upShowVideo')
+      showVideoList.forEach((item) => {
+        if (!item.paused) { item.pause() }
+      })
+      const videoSrc = URL.createObjectURL(file.raw)
+      this.videoList.push({ url: videoSrc, uid: file.uid })
+    },
+    // 删除预览视频
+    preDeleteVideo (index) {
+      this.videoList.splice(index, 1)
+    },
+    errMsg () {
+      if (this.errShow && this.uploadFileNum === this.picNum) {
+        this.picNum = 0
+        this.message(this.$i18n.t('videoManager.onlyPictures'), true)
+        this.notImg = false
+      }
+    },
+    /**
+     * 上传视频前检查合法性
+     * @param file
+     * @returns {boolean}
+     */
+    beforeUploadVideo (file) {
+      const isLt5M = file.size / 1024 / 1024 < 5
+      if (!isLt5M) {
+        this.$message.error('上传音频大小不能超过5MB哦!')
+        return false
+      }
+      return true
+    },
+
+    uploadNumberLimit () {
+      if (!this.options.multiple) {
+        return 1
+      }
+      return this.options.limit - this.images.length - this.uploadFileNum
+    },
+
+    uploadTypeTip () {
+      return this.$i18n.t('videoManager.onlySupported') + 'wav, mp3, ogg, acc, webm, amr ' + '音频'
+    },
+
+    uploadSizeTip () {
+      return this.$i18n.t('videoManager.notExceed') + '5M'
+    },
+
+    uploadTips () {
+      let tips = [this.uploadTypeTip(), this.uploadSizeTip()]
+
+      if (!this.options.multiple) {
+        return tips.join(',')
+      }
+
+      if (this.images.length > 0) {
+        tips.push(this.$i18n.t('videoManager.alreadyExist') + this.images.length + this.$i18n.t('videoManager.unit'))
+      }
+
+      const uploadFileNum = this.videoList.length
+      if (uploadFileNum > 0) {
+        tips.push(this.$i18n.t('videoManager.soonUpload') + uploadFileNum + this.$i18n.t('videoManager.unit'))
+      }
+      this.uploadFileNum = uploadFileNum
+      tips.push(this.$i18n.t('videoManager.remainder') + (this.options.limit - this.images.length - uploadFileNum) + "个音频" + this.$i18n.t('videoManager.upload'))
+
+      return tips.join(',')
+    },
+
+    /**
+     * 上传错误处理
+     * @param err
+     * @param file
+     * @param fileList
+     */
+    onUploadError (err, file, fileList) {
+      this.message(this.$i18n.t('videoManager.requestError'), true)
+      // console.log(err)
+      throw err
+    },
+
+    /**
+     * 上传成功处理s
+     * @param response
+     * @param file
+     * @param fileList
+     * @returns {boolean}
+     */
+    onUploadSuccess (fileId, file, fileList) {
+      this.uploadFlag ++
+      this.fileIds.push(fileId)
+      if (this.videoList.length === this.uploadFlag) {
+        this.disabled = true
+        this.$refs.upload.uploadFiles = []
+        if (this.selectGroup) {
+          this.submitBatchMove()
+        }
+        this.options.activeTab = 'pick'
+        setTimeout(() => {
+          this.isSubmit = false
+          this.videoList = []
+        })
+        this.loadListImage(1)
+      }
+    },
+
+    /**
+     * 选择上传文件超过限制文件个数提示
+     */
+    onUploadExceedTip () {
+      this.message(this.$i18n.t('videoManager.maxSelect') + this.uploadNumberLimit() + this.$i18n.t('videoManager.unit') + this.$i18n.t('videoManager.upload'))
+    },
+    message (msg, isInfo) {
+      var type = 'error'
+      if (isInfo) {
+        type = 'info'
+      }
+      this.$message({
+        message: msg,
+        type: type,
+        duration: 1500
+      })
+    },
+
+    /**
+     * tab切换事件
+     */
+    tabClick (tab) {
+      this.fileName = ''
+      if (tab.name === 'pick') {
+        this.loadListImage(1)
+      }
+    },
+    /**
+     * 关闭回调
+     */
+    handleDialogClose () {
+      this.fileName = ''
+    }
+  },
+
+  mounted () {
+    this.getGroupList()
+    this.loadListImage()
+  },
+
+  computed: {
+
+  }
+}
+</script>
+
+<style lang="scss">
+.elx-images {
+  .el-upload-list__item,
+  .el-upload--picture-card {
+    width: 78px;
+    height: 78px;
+    line-height: 82px;
+    border-radius: 5px;
+  }
+}
+.elx-head {
+  background: #F7F7F7;
+  height: 40px;
+  width: 100%;
+  line-height: 40px;
+  .text {
+    color: #606266;
+    font-size: 14px;
+    margin-left: 7px;
+    cursor:pointer;
+  }
+}
+.elx-imgbox-dialog {
+  $bg: #f6f6f6;
+  height: 100% !important;
+  .el-badge {
+    vertical-align: bottom;
+  }
+
+  .el-dialog {
+    width: 820px;
+    .el-dialog__header {
+      border-bottom: 1px solid #e8e8e8;
+    }
+
+    .el-dialog__body {
+      padding: 0;
+      background: $bg;
+    }
+  }
+
+  .el-tabs {
+    .el-tabs__header {
+      margin-right: 0;
+      margin-top: 5px;
+      .el-tabs__nav-wrap::after {
+        background: $bg;
+      }
+    }
+    .el-tabs__item.is-active {
+      background: #fff;
+    }
+    .el-tabs--left .el-tabs__nav-wrap {
+      padding-top: 15px;
+    }
+
+    .el-tabs__content {
+      min-height: 740px;
+      // 弹窗高度
+      background: #fff;
+    }
+  }
+
+  .elx-foot {
+    padding: 15px 0 0 10px;
+    text-align: right;
+    margin-right: 30px;
+    .el-button {
+      margin: 0 0 0 10px;
+    }
+  }
+.upload-block {
+    .upload-img-preview {
+      padding: 20px;
+
+      /* 上传视频预览改为使用背景视频按比例缩放方式 */
+      .el-upload--picture-card,
+      .el-upload-list--picture-card .el-upload-list__item,
+      .el-upload-list--picture-card .el-upload-list__item .wp {
+        width: 90px;
+        height: 90px;
+        line-height: 98px;
+        background-size: cover;
+        background-position: 50% 50%;
+      }
+
+      .el-upload-list--picture-card .el-upload-list__item-status-label i {
+        margin-top: 12px;
+        vertical-align: top;
+      }
+    }
+
+    .upload-tip {
+      padding: 0 20px;
+      font-size: 13px;
+      color: #999;
+    }
+
+    .upload-title {
+      font-size: 16px;
+      color: #666;
+      padding: 20px 0 0 20px;
+    }
+  }
+}
+
+.form {
+  padding: 15px 0px 0px 20px;
+}
+
+.el-upload-list__item-actions {
+  a {
+    i {
+      color: #fff;
+    }
+  }
+}
+</style>
+<style lang="scss" scoped>
+.upload-video-box {
+  .video-preview {
+    width: 175px;
+    height: 100px;
+    display: inline-block;
+    text-align: center;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    margin-right: 8px;
+    margin-bottom: 5px;
+    margin-top: 20px;
+}
+.avatar-uploader-popup{
+  width: 100%;
+  background: #f6f6f6;
+  height: 18px;
+}
+}
+.group-box {
+  height: 600px;
+  min-width: 200px;
+  overflow:auto;
+}
+.select-group-box {
+  padding: 20px 0 0 20px;
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  .select-group-box-item {
+    margin-right: 10px;
+  }
+}
+.box {
+  display: flex;
+  justify-content: flex-start;
+  .group {
+    min-width: 200px;
+    padding: 10px;
+    .group-item {
+      height: 38px;
+      line-height: 38px;
+      padding: 0 10px;
+      display: flex;
+      justify-content: space-between;
+      cursor:pointer;
+
+      .group-name {
+        width: 180px;
+      }
+      .sidebar-operate {
+        .el-icon-delete,
+        .el-icon-edit {
+          margin-left: 10px;
+          cursor: pointer;
+        }
+      }
+    }
+    .group-item:hover{
+      background: #F7F7F7;
+    }
+    .active {
+      background: #F7F7F7;
+    }
+  }
+  .img-list {
+    width: 1100px;
+    position: relative;
+    .data-tips {
+      position: absolute;
+      top: 30%;
+      left: 38%;
+    }
+  }
+}
+.pick-block {
+    position: relative;
+    $bg: #f6f6f6;
+    .elx-img-list-loading {
+      position: absolute;
+      top: 60px;
+      z-index: 9;
+      left: 0;
+      right: 0;
+      width: 100%;
+      height: 520px;
+      // 加载层高度
+      background: #fff;
+      text-align: center;
+
+      .el-icon-loading {
+        font-size: 50px;
+        color: #409eff;
+        line-height: 460px;
+      }
+    }
+
+    .elx-img-list {
+      padding: 10px;
+      min-height: 530px;
+      // 视频列表高度
+
+      .img-item {
+        $imgSize: 175px;
+        $size: 179px;
+        float: left;
+        margin: 10px;
+        margin-bottom: 20px;
+        margin-right: 20px;
+        width: $imgSize;
+        cursor: pointer;
+        position: relative;
+        font-size: 12px;
+
+        img {
+          width: $imgSize;
+          height: $imgSize;
+          display: block;
+          object-fit: contain
+        }
+
+        .title {
+          line-height: 24px;
+          height: 24px;
+          display: block;
+          overflow: hidden;
+          background: $bg;
+          padding: 0 5px;
+        }
+
+        .title {
+          line-height: 24px;
+          height: 24px;
+          display: block;
+          overflow: hidden;
+          background: $bg;
+          padding: 0 5px;
+        }
+        .operate {
+          line-height: 24px;
+          height: 24px;
+          display: block;
+          overflow: hidden;
+          // background: $bg;
+          margin-top: 2px;
+          padding: 0 5px;
+          .edit {
+            float: left;
+            padding-left: 5px;
+          }
+          .del {
+            float: right;
+            padding-right: 5px;
+          }
+        }
+
+        .label {
+          position: absolute;
+          z-index: 9;
+          left: 0;
+          bottom: 24px;
+          width: 100%;
+          height: 21px;
+          line-height: 21px;
+          text-align: center;
+          color: #fff;
+
+          &:after {
+            content: " ";
+            position: absolute;
+            left: 0;
+            bottom: 0;
+            width: 100%;
+            height: 21px;
+            background: #000;
+            opacity: 0.3;
+            z-index: -1;
+          }
+        }
+
+        .selected {
+          position: absolute;
+          right: -3px;
+          top: -3px;
+          width: $size;
+          height: 143px;
+          border: 3px solid #409eff;
+          border-radius: 3px;
+          text-align: right;
+          .icon {
+            background: #409eff;
+            text-align: center;
+            height: 24px;
+            width: 24px;
+            line-height: 24px;
+            display: inline-block;
+            font-size: 16px;
+            color: #fff;
+            border-radius: 0 0 0 3px;
+            position: absolute;
+            right: 0;
+            top: 0;
+          }
+        }
+      }
+
+      &::after {
+        content: " ";
+        display: table;
+        height: 0;
+        clear: both;
+        visibility: hidden;
+      }
+    }
+
+    .el-pagination {
+      background: #f9f9f9;
+      position: relative;
+      padding: 5px;
+      // margin: 0 24px 0 20px;
+      text-align: right;
+      float: none;
+
+      * {
+        background: none;
+      }
+    }
+  }
+.elx-upload-main {
+  padding-left: 70px;
+  .elx-upload-foot {
+    padding: 15px 0 0 10px;
+    text-align: left;
+    .el-button {
+      margin: 0 0 0 10px;
+    }
+  }
+}
+
+</style>
+<style scoped>
+div >>> .el-tabs__header{
+  display: none !important;
+}
+</style>

+ 125 - 0
src/components/audio-upload/index.vue

@@ -0,0 +1,125 @@
+<template>
+  <div class="upload-video-box">
+    <div class="plugin-video">
+      <div tabindex="0" class="el-upload el-upload--text" @click.prevent.stop="videoboxHandle">
+        <video v-if="value" ref="myVideo" class="video" :src="getImgSrc()" controls="controls"></video>
+
+        <i v-else class="el-icon-plus pic-uploader-icon"></i>
+      </div>
+    </div>
+    <!-- <p></p> -->
+    <div v-if="value" class="default-btn" @click="deleteImg">{{ $t("resource.Delete") }}</div>
+    <!-- 弹窗, 新增视频 -->
+
+    <audio-box v-if="videoboxVisible" ref="videobox" @refreshPic="refreshPic"></audio-box>
+    <el-dialog :visible.sync="visible" :append-to-body="visible">
+      <!-- <img width="100%" :src="getImgSrc()" alt /> -->
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import AudioBox from '@/components/AudioBox'
+export default {
+  data () {
+    return {
+      resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+      videoboxVisible: false,
+      visible: false
+    }
+  },
+  props: {
+    value: {
+      default: '',
+      type: String
+    },
+    disabled: {
+      default: false,
+      type: Boolean
+    }
+  },
+  components: {
+    AudioBox
+  },
+  methods: {
+    // 打开视频选择窗
+    videoboxHandle () {
+      if (this.disabled) {
+        this.openImg()
+        return false
+      }
+      this.videoboxVisible = true
+      this.$nextTick(() => {
+        this.$refs.videobox.init(1)
+      })
+    },
+
+    /**
+     * 获取视频路径
+     */
+    getImgSrc () {
+      if (!this.value) {
+        return ''
+      }
+      if (this.value.indexOf('http://') === 0 || this.value.indexOf('https://') === 0) {
+        return this.value
+      }
+      return this.resourcesUrl + this.value
+    },
+    openImg () {
+      this.visible = true
+    },
+    refreshPic (imagePath) {
+      this.$emit('input', imagePath)
+    },
+    deleteImg () {
+      this.$emit('input', '')
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+.plugin-video {
+  display: inline-block;
+  width: auto;
+  vertical-align: bottom;
+  .el-upload {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: auto;
+    min-width: 120px;
+    max-width: 300px;
+    height: auto;
+    min-height: 120px;
+    max-height: 250px;
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+    .pic-uploader-icon {
+      font-size: 28px;
+      color: #8c939d;
+      width: auto;
+      height: auto;
+      // width: 120px;
+      // height: 120px;
+      // line-height: 120px;
+      text-align: center;
+    }
+    .video {
+      width: auto;
+      max-width: 300px;
+      // height: 120px;
+      height: auto;
+      max-height: 250px;
+      display: block;
+    }
+    .el-upload:hover {
+      border-color: #409eff;
+    }
+  }
+}
+</style>

+ 1 - 0
src/views/modules/order/order.vue

@@ -29,6 +29,7 @@
                 <el-option key="wxzj" label="无双直角小卡" value="无双直角小卡"></el-option>
                 <el-option key="yjxk" label="典藏圆角小卡" value="典藏圆角小卡"></el-option>
                 <el-option key="zjxk" label="典藏直角小卡" value="典藏直角小卡"></el-option>
+                <el-option key="gg" label="宫格" value="宫格"></el-option>
                 <el-option key="pld" label="拍立得" value="拍立得"></el-option>
                 <el-option key="zpfm" label="直拍封面" value="直拍封面"></el-option>
                 <el-option key="pg" label="票根" value="票根"></el-option>

+ 2 - 1
src/views/modules/order/orderInfo.vue

@@ -587,7 +587,8 @@
                 <el-row>
                   <el-col :span="24">
                     <div class="item">
-                      <div class="item" style="width:360px;">物流信息:{{printOrder.deliveryName}} | {{printOrder.deliveryNo}}</div>
+                      <div class="item" style="width:360px;" v-if="printOrder.status === 3">物流信息:{{printOrder.deliveryName}} | {{printOrder.deliveryNo}}</div>
+                      <div class="item" style="width:360px;" v-else>物流信息</div>
                       <el-button type="primary" size="mini" v-if="orderStatus == 2" @click="openDeliveryDialog">发货</el-button>
                     </div>
                   </el-col>

+ 1 - 2
src/views/modules/prod/prodTemplate.vue

@@ -264,7 +264,7 @@ export default {
           this.$message({
             message: this.$i18n.t('publics.operation'),
             type: 'success',
-            duration: 1500,
+            duration: 100,
             onClose: () => {
               this.refreshChange()
             }
@@ -280,7 +280,6 @@ export default {
     },
     // 刷新回调
     refreshChange () {
-      this.page.currentPage = 1
       this.getDataList(this.page)
     },
     searchChange () {

+ 124 - 0
src/views/modules/prod/qrCodeTemplate-add-or-update.vue

@@ -0,0 +1,124 @@
+<template>
+  <el-dialog
+    :title="!dataForm.templateId ? this.$i18n.t('crud.addTitle') : this.$i18n.t('temp.modify')"
+    :close-on-click-modal="false"
+    :visible.sync="visible">
+    <el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" label-width="100px">
+      <el-form-item label="小程序模板" prop="templateUrl">
+        <img-upload v-model="dataForm.templateUrl" :limit="20"></img-upload>
+      </el-form-item>
+      <el-form-item label="生成用模板" prop="templateUseUrl" v-if="dataForm.templateId">
+        <img-upload v-model="dataForm.templateUseUrl" :limit="20"></img-upload>
+      </el-form-item>
+      <el-form-item label="着色值" prop="startX">
+        <el-input size="small" v-model="dataForm.colorHex" placeholder="例如:#000000"></el-input>
+      </el-form-item>
+      <el-form-item label="起始X轴(PX)" prop="startX">
+        <el-input type="number" size="small" v-model="dataForm.startX"></el-input>
+      </el-form-item>
+      <el-form-item label="起始Y轴(PX)" prop="startY">
+        <el-input type="number" size="small" v-model="dataForm.startY"></el-input>
+      </el-form-item>
+      <el-form-item label="二维码宽度" prop="startX">
+        <el-input type="number" size="small" v-model="dataForm.width"></el-input>
+      </el-form-item>
+      <el-form-item label="排序" prop="seq">
+        <el-input v-model="dataForm.seq" type="number"/>
+      </el-form-item>
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+      <el-button class="default-btn" @click="visible = false">{{$t("crud.filter.cancelBtn")}}</el-button>
+      <el-button class="default-btn primary-btn" type="primary" @click="dataFormSubmit()">{{$t("crud.filter.submitBtn")}}</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+  import ImgUpload from '@/components/imgs-upload'
+  // import uploadPic from './upload-pic.vue'
+export default {
+  components: {
+    ImgUpload
+  },
+  data () {
+    return {
+      visible: false,
+      dataForm: {
+        templateId: null,
+        colorHex: null,
+        seq: 1,
+        templateUrl: null,
+        templateUseUrl: null,
+        startX: null,
+        startY: null,
+        shopId: this.$store.state.user.shopId,
+      },
+      resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+      dataRule: {
+      }
+    }
+  },
+  created () {
+
+  },
+  methods: {
+    init (templateId) {
+      this.dataForm.templateId = templateId || 0
+      this.visible = true
+      this.$nextTick(() => {
+        this.$refs['dataForm'].resetFields()
+        if (this.dataForm.templateId) {
+          this.$http({
+            url: this.$http.adornUrl('/prod/qrCodeTemplate/info/' + this.dataForm.templateId),
+            method: 'get',
+            params: this.$http.adornParams()
+          }).then(({data}) => {
+            this.dataForm = data;
+          })
+        }
+      })
+    },
+    //验证图片尺寸
+    checkImageSize(imageStr, index) {
+      return new Promise((resolve, reject) => {
+        let image = new Image();
+        image.onload = function() {
+          let imageFormat = imageStr.split('.').pop();
+          if(imageFormat !== 'png'){
+            reject(index);
+          }else{
+            resolve();
+          }
+        };
+        image.src = this.resourcesUrl + imageStr;
+      });
+    },
+    // 表单提交
+    async dataFormSubmit () {
+      try{
+        let imgUrlArr = this.dataForm.templateUrl.split(",");
+        let imgUrlArr2 = this.dataForm.templateUseUrl.split(",");
+        await Promise.all(imgUrlArr.map(this.checkImageSize));
+        await Promise.all(imgUrlArr2.map(this.checkImageSize));
+        this.$http({
+          url: this.$http.adornUrl('/prod/qrCodeTemplate'),
+          method: this.dataForm.templateId ? 'put' : 'post',
+          data: this.$http.adornData(this.dataForm)
+        }).then(({data}) => {
+          this.$message({
+            message: this.$i18n.t('publics.operation'),
+            type: 'success',
+            duration: 100,
+            onClose: () => {
+              this.visible = false;
+              this.$emit('refreshDataList')
+            }
+          })
+        })
+      }catch (error) {
+        this.$message.error(error);
+      }
+    },
+  }
+}
+</script>

+ 255 - 0
src/views/modules/prod/qrCodeTemplate.vue

@@ -0,0 +1,255 @@
+<template>
+  <div class="mod-prod-prodTemplate">
+    <!-- 搜索相关区域 -->
+    <div class="search-bar">
+      <el-form :inline="true" class="search-form" ref="searchForm" :model="searchForm" label-width="auto" size="small">
+        <!-- 表单项 -->
+        <div class="input-row">
+          <el-form-item prop="colorHex" label="着色值">
+           <el-input size="small" v-model="searchForm.colorHex"></el-input>
+          </el-form-item>
+          <el-form-item>
+            <div class="default-btn primary-btn" @click="searchChange()">{{ $t('crud.searchBtn') }}</div>
+            <div class="default-btn" @click="resetForm()">{{ $t('shop.resetMap') }}</div>
+          </el-form-item>
+        </div>
+      </el-form>
+    </div>
+    <!-- 列表相关区域 -->
+    <div class="main-container">
+      <div class="operation-bar">
+        <div class="default-btn primary-btn" @click="addOrUpdateHandle()"
+             >{{$t("crud.addTitle")}}</div>
+      </div>
+      <div class="table-con spec-table">
+        <el-table
+          ref="specListTable"
+          :data="dataList"
+          header-cell-class-name="table-header"
+          row-class-name="table-row"
+          style="width: 100%">
+          <!-- 模板图片地址 -->
+          <!--<el-table-column :label="$t('prodTemplate.templatePic')" prop="templatePic" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.templatePic}}</span>
+            </template>
+          </el-table-column>-->
+          <el-table-column
+                  align="center"
+                  prop="templateUrl"
+                  label="小程序模板">
+            <template slot-scope="scope">
+              <el-image
+                  style="width: 100px; height: 100px"
+                  :src="resourcesUrl + scope.row.templateUrl"
+                  v-if="scope.row.templateUrl"
+                  fit="fill"
+                  @click="previewPic(scope.row)"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column
+            align="center"
+            prop="templateUrl"
+            label="生成用模板">
+            <template slot-scope="scope">
+              <el-image
+                style="width: 100px; height: 100px"
+                :src="resourcesUrl + scope.row.templateUseUrl"
+                v-if="scope.row.templateUseUrl"
+                fit="fill"
+                @click="previewPic(scope.row)"
+              />
+            </template>
+          </el-table-column>
+          <!-- 着色值 -->
+          <el-table-column label="着色值" prop="colorHex" align="center">
+            <template slot-scope="scope">
+              <div :style="{'margin-left': '35px','background-color': scope.row.colorHex, 'width': '100px', 'height': '100px', 'line-height':'100px'}">{{ scope.row.colorHex}}</div>
+            </template>
+          </el-table-column>
+          <el-table-column label="起始X像素(PX)" prop="startX" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.startX}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="起始Y像素(PX)" prop="startY" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.startY}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="二维码宽度" prop="width" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.width}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="状态" prop="status" align="center">
+            <template slot-scope="scope">
+              <el-tag type="success" v-if="scope.row.status === 1">启用</el-tag>
+              <el-tag type="danger" v-if="scope.row.status === -1">禁用</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="排序" prop="seq" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.seq}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" fixed="right" :label="$t('publics.operating')" width="auto">
+            <template slot-scope="scope">
+              <div class="text-btn-con">
+                <div class="default-btn text-btn" @click="addOrUpdateHandle(scope.row.templateId)">{{$t("crud.updateBtn")}}</div>
+                <div class="default-btn text-btn" @click.stop="deleteHandle(scope.row.templateId)">{{$t("text.delBtn")}}</div>
+                <div class="default-btn text-btn" @click.stop="previewHandle(scope.row.templateId)">查看预览</div>
+                </div>
+
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+        <el-pagination
+          v-if="dataList.length"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          :current-page="page.currentPage"
+          :page-sizes="[10, 20, 50, 100]"
+          :page-size="page.pageSize"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="page.total">
+        </el-pagination>
+      </div>
+    <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="refreshChange"></add-or-update>
+    <el-dialog :visible.sync="previewPicDialogVisible" :modal="false" title="图片预览" width="30%" top="3vh">
+      <el-image :src="previewPicUrl" alt=""  style="width: 100%; height: 100%"/>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import AddOrUpdate from './qrCodeTemplate-add-or-update'
+export default {
+  data () {
+    return {
+      dataList: [],
+      page: {
+        total: 0, // 总页数
+        currentPage: 1, // 当前页数
+        pageSize: 10 // 每页显示多少条
+      },
+      searchForm: {
+        colorHex: null,
+
+      }, // 搜索
+      dataListLoading: false,
+      addOrUpdateVisible: false,
+      resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+      previewPicUrl: null,
+      previewPicDialogVisible: false,
+    }
+  },
+  components: {
+    AddOrUpdate
+  },
+  created () {
+    this.getDataList()
+  },
+  mounted () {
+  },
+  methods: {
+    //二维码生成预览
+    previewHandle(templateId){
+      this.$http({
+        url: this.$http.adornUrl('/prod/qrCodeTemplate/createQrNoteCode'),
+        method: 'post',
+        data: this.$http.adornData({qrCodeTemplateId: templateId})
+      }).then(({data}) => {
+        this.$message({
+          message: this.$i18n.t('publics.operation'),
+          type: 'success',
+          duration: 100,
+          onClose: () => {
+            this.visible = false;
+            this.previewPic({templateUrl: data.qrCodeUrl})
+          }
+        })
+      })
+    },
+    previewPic(row){
+      this.previewPicUrl = this.resourcesUrl + row.templateUrl
+      this.previewPicDialogVisible = true;
+    },
+    getDataList (page) {
+      this.dataListLoading = true
+      this.$http({
+        url: this.$http.adornUrl('/prod/qrCodeTemplate/page'),
+        method: 'get',
+        params: this.$http.adornParams(
+          Object.assign({
+            current: page == null ? this.page.currentPage : page.currentPage,
+            size: page == null ? this.page.pageSize : page.pageSize,
+            shopId: this.$store.state.user.shopId,
+          },
+            this.searchForm
+          )
+        )
+      }).then(({data}) => {
+        this.dataList = data.records
+        this.page.total = data.total
+        this.dataListLoading = false
+      })
+    },
+    // 新增 / 修改
+    addOrUpdateHandle (id) {
+      this.addOrUpdateVisible = true
+      this.$nextTick(() => {
+        this.$refs.addOrUpdate.init(id)
+      })
+    },
+    deleteHandle (id) {
+      this.$confirm(this.$i18n.t('admin.isDeleOper') + '?', this.$i18n.t('text.tips'), {
+        confirmButtonText: this.$i18n.t('crud.filter.submitBtn'),
+        cancelButtonText: this.$i18n.t('crud.filter.cancelBtn'),
+        type: 'warning'
+      }).then(() => {
+        this.$http({
+          url: this.$http.adornUrl('/prod/qrCodeTemplate/' + id),
+          method: 'delete',
+          data: this.$http.adornData({})
+        }).then(({ data }) => {
+          this.$message({
+            message: this.$i18n.t('publics.operation'),
+            type: 'success',
+            duration: 100,
+            onClose: () => {
+              this.refreshChange()
+            }
+          })
+        })
+      }).catch(() => { })
+    },
+    resetForm () {
+      this.searchForm = {
+        colorHex: null,
+      }
+    },
+    // 刷新回调
+    refreshChange () {
+      this.getDataList(this.page)
+    },
+    searchChange () {
+      this.getDataList(this.page)
+    },
+    handleSizeChange (val) {
+      this.page.pageSize = val
+      this.getDataList()
+    },
+    handleCurrentChange (val) {
+      this.page.currentPage = val
+      this.getDataList()
+    }
+  }
+}
+</script>
+<style lang="scss">
+.mod-prod-prodTemplate {
+}
+</style>

+ 132 - 0
src/views/modules/prod/voiceTemplate-add-or-update.vue

@@ -0,0 +1,132 @@
+<template>
+  <el-dialog
+    :title="!dataForm.templateId ? this.$i18n.t('crud.addTitle') : this.$i18n.t('temp.modify')"
+    :close-on-click-modal="false"
+    :visible.sync="visible">
+    <el-form :model="dataForm" :rules="dataRule" ref="dataForm" label-width="100px">
+      <el-form-item label="模板系列" prop="templateSeries">
+        <el-select v-model="dataForm.templateSeriesId" clearable filterable>
+          <el-option
+                  v-for="node in seriesList"
+                  :key="node.seriesId"
+                  :label="node.seriesName"
+                  :value="node.seriesId"
+          ></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="语音地址" prop="templateUrl">
+        <audio-upload v-model="dataForm.templateUrl" :limit="20"></audio-upload>
+      </el-form-item>
+      <el-form-item label="是否禁用" prop="status">
+        <el-select v-model="dataForm.status" clearable filterable>
+          <el-option key="1" label="启用" :value=1 ></el-option>
+          <el-option key="0" label="禁用" :value=-1></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="排序" prop="seq">
+        <el-input v-model="dataForm.seq" type="number"/>
+      </el-form-item>
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+      <el-button class="default-btn" @click="visible = false">{{$t("crud.filter.cancelBtn")}}</el-button>
+      <el-button class="default-btn primary-btn" type="primary" @click="dataFormSubmit()">{{$t("crud.filter.submitBtn")}}</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+  import AudioUpload from '@/components/audio-upload'
+  // import uploadPic from './upload-pic.vue'
+export default {
+  components: {
+    AudioUpload
+  },
+  data () {
+    return {
+      visible: false,
+      dataForm: {
+        templateId: null,
+        templateSeriesId: null,
+        templateSeries: null,
+        templateUrl: null,
+        shopId: this.$store.state.user.shopId,
+        status: 1,
+        createTime: null,
+        templateUsage: null,
+        seq: 1
+      },
+      resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+      seriesList: [],
+      dataRule: {
+      }
+    }
+  },
+  created () {
+    this.getSeriesList()
+  },
+  methods: {
+    init (templateId) {
+      this.dataForm.templateId = templateId || 0
+      this.visible = true
+      this.$nextTick(() => {
+        this.$refs['dataForm'].resetFields()
+        if (this.dataForm.templateId) {
+          this.$http({
+            url: this.$http.adornUrl('/prod/voiceTemplate/info/' + this.dataForm.templateId),
+            method: 'get',
+            params: this.$http.adornParams()
+          }).then(({data}) => {
+            this.dataForm = data;
+            this.usageList = data.templateUsage.split(",");
+          })
+        }
+      })
+    },
+    // 表单提交
+    async dataFormSubmit () {
+      try{
+        this.handleSeriesName(this.dataForm.templateSeriesId);
+        this.$http({
+          url: this.$http.adornUrl('/prod/voiceTemplate'),
+          method: this.dataForm.templateId ? 'put' : 'post',
+          data: this.$http.adornData(this.dataForm)
+        }).then(({data}) => {
+          this.$message({
+            message: this.$i18n.t('publics.operation'),
+            type: 'success',
+            duration: 100,
+            onClose: () => {
+              this.visible = false;
+              this.$emit('refreshDataList')
+            }
+          })
+        })
+      }catch (error) {
+
+      }
+    },
+    getSeriesList () {
+      this.$http({
+        url: this.$http.adornUrl('/prod/prodTemplateSeries/page'),
+        method: 'get',
+        params: this.$http.adornParams(
+                Object.assign({
+                  size: 100,
+                  shopId: this.$store.state.user.shopId
+                }
+                )
+        )
+      }).then(({data}) => {
+        this.seriesList = data.records
+      })
+    },
+    handleSeriesName (seriesId) {
+      this.seriesList.forEach(series =>{
+        if (series.seriesId == seriesId) {
+          this.dataForm.templateSeries = series.seriesName
+        }
+      })
+    },
+  }
+}
+</script>

+ 226 - 0
src/views/modules/prod/voiceTemplate.vue

@@ -0,0 +1,226 @@
+<template>
+  <div class="mod-prod-prodTemplate">
+    <!-- 搜索相关区域 -->
+    <div class="search-bar">
+      <el-form :inline="true" class="search-form" ref="searchForm" :model="searchForm" label-width="auto" size="small">
+        <!-- 表单项 -->
+        <div class="input-row">
+          <el-form-item prop="templateSeriesId" label="模板系列:">
+            <el-select v-model="searchForm.templateSeriesId" clearable filterable>
+              <el-option
+                      v-for="node in seriesList"
+                      :key="node.seriesId"
+                      :label="node.seriesName"
+                      :value="node.seriesId"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <div class="default-btn primary-btn" @click="searchChange()">{{ $t('crud.searchBtn') }}</div>
+            <div class="default-btn" @click="resetForm()">{{ $t('shop.resetMap') }}</div>
+          </el-form-item>
+        </div>
+      </el-form>
+    </div>
+    <!-- 列表相关区域 -->
+    <div class="main-container">
+      <div class="operation-bar">
+        <div class="default-btn primary-btn" @click="addOrUpdateHandle()"
+             >{{$t("crud.addTitle")}}</div>
+      </div>
+      <div class="table-con spec-table">
+        <el-table
+          ref="specListTable"
+          :data="dataList"
+          header-cell-class-name="table-header"
+          row-class-name="table-row"
+          style="width: 100%">
+          <el-table-column
+                  align="center"
+                  prop="templateUrl"
+                  label="语音地址"
+                  width="300">
+            <template slot-scope="scope">
+              <video
+                  :src="resourcesUrl + scope.row.templateUrl"
+                  v-if="scope.row.templateUrl"
+                  controls="controls"
+                  style="width:260px;height:87.5px;"
+              />
+            </template>
+          </el-table-column>
+
+          <el-table-column label="模版系列" prop="templateSeries" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.templateSeries}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column :label="$t('prodTemplate.status')" prop="status" align="center">
+            <template slot-scope="scope">
+              <el-tag type="success" v-if="scope.row.status === 1">启用</el-tag>
+              <el-tag type="danger" v-if="scope.row.status === -1">禁用</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="排序" prop="seq" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.seq}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" fixed="right" :label="$t('publics.operating')" width="auto">
+            <template slot-scope="scope">
+              <div class="text-btn-con">
+                <div class="default-btn text-btn" @click="addOrUpdateHandle(scope.row.templateId)"
+                     >{{$t("crud.updateBtn")}}</div>
+                <div class="default-btn text-btn" @click.stop="deleteHandle(scope.row.templateId)"
+                     >{{$t("text.delBtn")}}</div>
+                </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+        <el-pagination
+          v-if="dataList.length"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+          :current-page="page.currentPage"
+          :page-sizes="[10, 20, 50, 100]"
+          :page-size="page.pageSize"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="page.total">
+        </el-pagination>
+      </div>
+    <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="refreshChange"></add-or-update>
+    <el-dialog :visible.sync="previewPicDialogVisible" :modal="false" title="图片预览" width="30%" top="3vh">
+      <el-image :src="previewPicUrl" alt=""  style="width: 100%; height: 100%"/>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import AddOrUpdate from './voiceTemplate-add-or-update'
+export default {
+  data () {
+    return {
+      dataList: [],
+      page: {
+        total: 0, // 总页数
+        currentPage: 1, // 当前页数
+        pageSize: 10 // 每页显示多少条
+      },
+      searchForm: {
+        templateSeriesId: null,
+      }, // 搜索
+      dataListLoading: false,
+      addOrUpdateVisible: false,
+      seriesList: [],
+      resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+      previewPicUrl: null,
+      previewPicDialogVisible: false,
+    }
+  },
+  components: {
+    AddOrUpdate
+  },
+  created () {
+    this.getDataList()
+    this.getSeriesList()
+  },
+  mounted () {
+  },
+  methods: {
+    previewPic(row){
+      this.previewPicUrl = this.resourcesUrl + row.templateUrl
+      this.previewPicDialogVisible = true;
+    },
+    getSeriesList () {
+      this.$http({
+        url: this.$http.adornUrl('/prod/prodTemplateSeries/page'),
+        method: 'get',
+        params: this.$http.adornParams(
+                Object.assign({
+                          size: 100,
+                          shopId: this.$store.state.user.shopId
+                        },
+                )
+        )
+      }).then(({data}) => {
+        this.seriesList = data.records
+      })
+    },
+    getDataList (page) {
+      this.dataListLoading = true
+      this.$http({
+        url: this.$http.adornUrl('/prod/voiceTemplate/page'),
+        method: 'get',
+        params: this.$http.adornParams(
+          Object.assign({
+            current: page == null ? this.page.currentPage : page.currentPage,
+            size: page == null ? this.page.pageSize : page.pageSize,
+            shopId: this.$store.state.user.shopId,
+          },
+            this.searchForm
+          )
+        )
+      }).then(({data}) => {
+        this.dataList = data.records
+        this.page.total = data.total
+        this.dataListLoading = false
+      })
+    },
+    // 新增 / 修改
+    addOrUpdateHandle (id) {
+      this.addOrUpdateVisible = true
+      this.$nextTick(() => {
+        this.$refs.addOrUpdate.init(id)
+      })
+    },
+    deleteHandle (id) {
+      this.$confirm(this.$i18n.t('admin.isDeleOper') + '?', this.$i18n.t('text.tips'), {
+        confirmButtonText: this.$i18n.t('crud.filter.submitBtn'),
+        cancelButtonText: this.$i18n.t('crud.filter.cancelBtn'),
+        type: 'warning'
+      }).then(() => {
+        this.$http({
+          url: this.$http.adornUrl('/prod/voiceTemplate/' + id),
+          method: 'delete',
+          data: this.$http.adornData({})
+        }).then(({ data }) => {
+          this.$message({
+            message: this.$i18n.t('publics.operation'),
+            type: 'success',
+            duration: 100,
+            onClose: () => {
+              this.refreshChange()
+            }
+          })
+        })
+      }).catch(() => { })
+    },
+    resetForm () {
+      this.searchForm = {
+        templateSeriesId: null
+      }
+    },
+    // 刷新回调
+    refreshChange () {
+      this.getDataList(this.page)
+    },
+    searchChange () {
+      // this.searchForm = params
+      this.getDataList(this.page)
+    },
+    handleSizeChange (val) {
+      this.page.pageSize = val
+      this.getDataList()
+    },
+    handleCurrentChange (val) {
+      this.page.currentPage = val
+      this.getDataList()
+    }
+  }
+}
+</script>
+<style lang="scss">
+.mod-prod-prodTemplate {
+}
+</style>

+ 21 - 1
src/views/modules/promotion/promotionUp-add-or-update.vue

@@ -53,6 +53,26 @@
           </el-form-item>
         </el-col>
       </el-row>
+      <el-row>
+        <el-col :span="10">
+          <el-form-item label="是否拉黑" prop="isBlack" size="small">
+            <el-select v-model="dataForm.isBlack" clearable style="width: 330px">
+              <el-option label="拉黑" :value="1"></el-option>
+              <el-option label="正常" :value="0"></el-option>
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="10" :offset="1">
+          <el-form-item label="备注" prop="remark" size="small">
+            <el-input v-model="dataForm.remark" type="textarea"></el-input>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-col :span="10">
+        <el-form-item label="企微备注" prop="qwRemark" size="small">
+          <el-input v-model="dataForm.qwRemark"></el-input>
+        </el-form-item>
+      </el-col>
     </el-form>
     <span slot="footer" class="dialog-footer">
       <el-button class="default-btn" @click="visible = false">{{$t("crud.filter.cancelBtn")}}</el-button>
@@ -115,7 +135,7 @@ export default {
       this.$http({
         url: this.$http.adornUrl('/shop/shopDetail/getShopList'),
         method: 'get',
-        params: this.$http.adornParams({shopId: this.shopId})
+        params: this.$http.adornParams({shopId: this.dataForm.shopId})
       }).then(({ data }) => {
         if (data) {
           this.shopList = data

+ 48 - 1
src/views/modules/promotion/promotionUp.vue

@@ -2,7 +2,7 @@
   <div class="mod-print-promotionOrder">
     <!-- 搜索相关区域 -->
     <div class="search-bar">
-      <el-form :inline="true" :model="searchForm" @keyup.enter.native="getDataList(this.page)" size="small">
+      <el-form :inline="true" :model="searchForm" size="small">
         <div class="input-row">
           <el-form-item label="推广人" prop="tgUserName">
             <el-input v-model="searchForm.tgUserName" :clearable="true"></el-input>
@@ -13,6 +13,15 @@
           <el-form-item label="博主名称" prop="upName">
             <el-input v-model="searchForm.upName" :clearable="true"></el-input>
           </el-form-item>
+          <el-form-item label="是否拉黑" prop="isBlack">
+            <el-select v-model="searchForm.isBlack" clearable>
+              <el-option label="拉黑" :value="1"></el-option>
+              <el-option label="正常" :value="0"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="企微备注" prop="qwRemark">
+            <el-input v-model="searchForm.qwRemark" :clearable="true"></el-input>
+          </el-form-item>
           <el-form-item label="视频平台" prop="publishPlatform">
             <el-select v-model="searchForm.publishPlatform" filterable placeholder="请选择" :clearable="true">
               <el-option
@@ -30,6 +39,18 @@
               </el-option>
             </el-select>
           </el-form-item>
+          <el-form-item label="登记时间" prop="orderTime">
+            <el-date-picker
+              :clearable="true"
+              v-model="createTimeRange"
+              type="datetimerange"
+              align="right"
+              value-format="yyyy-MM-dd HH:mm:ss"
+              start-placeholder="开始时间"
+              end-placeholder="结束时间"
+              :default-time="['00:00:00', '23:59:59']">
+            </el-date-picker>
+          </el-form-item>
           <el-form-item>
             <div class="default-btn primary-btn" @click="searchChange()">{{$t("crud.searchBtn")}}</div>
             <div class="default-btn" @click="clear()">重置</div>
@@ -67,6 +88,17 @@
               <span>{{ scope.row.upName}}</span>
             </template>
           </el-table-column>
+          <el-table-column label="是否拉黑" prop="isBlack" align="center">
+            <template slot-scope="scope">
+              <el-tag v-if="scope.row.isBlack === 1" type="danger">拉黑</el-tag>
+              <!--              <el-tag v-if="scope.row.isBlack === 0" type="success"></el-tag>-->
+            </template>
+          </el-table-column>
+          <el-table-column label="企微备注" prop="qwRemark" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.qwRemark}}</span>
+            </template>
+          </el-table-column>
           <!-- 博主粉丝 -->
           <el-table-column label="博主粉丝" prop="fansNum" align="center">
             <template slot-scope="scope">
@@ -79,6 +111,18 @@
               <span>{{ scope.row.shopName}}</span>
             </template>
           </el-table-column>
+          <!-- 登记时间 -->
+          <el-table-column label="登记时间" prop="createTime" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.createTime}}</span>
+            </template>
+          </el-table-column>
+          <!-- 备注 -->
+          <el-table-column label="备注" prop="createTime" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.remark}}</span>
+            </template>
+          </el-table-column>
           <el-table-column align="center" fixed="right" :label="$t('publics.operating')" width="auto">
             <template slot-scope="scope">
               <div class="text-btn-con">
@@ -129,6 +173,7 @@ export default {
         {value: '快手', label: '快手'},
         {value: 'B站', label: 'B站'},
       ],
+      createTimeRange:[],
     }
   },
   components: {
@@ -187,6 +232,8 @@ export default {
           Object.assign({
             current: page == null ? this.page.currentPage : page.currentPage,
             size: page == null ? this.page.pageSize : page.pageSize,
+              startTime: this.createTimeRange == null ? null : this.createTimeRange[0] ? this.createTimeRange[0] : null,
+              endTime: this.createTimeRange == null ? null : this.createTimeRange[1] ? this.createTimeRange[1] : null,
           },
             this.searchForm
           )

+ 1025 - 0
src/views/modules/resource/audio-store/audio-store.vue

@@ -0,0 +1,1025 @@
+<template>
+  <div class="elx-imgbox">
+    <div class="elx-imgbox-dialog">
+        <div
+          class="pick-block"
+        >
+          <div class="elx-img-list-loading" v-if="isLoading">
+            <div class="el-icon-loading"></div>
+          </div>
+          <div class="search-bar">
+            <el-form :inline="true" :model="dataForm">
+              <el-form-item>
+                <el-input
+                  v-model="fileName"
+                  size="small"
+                  :placeholder="this.$i18n.t('videoManager.videoName')"
+                  @keypress.native.enter="searchImg(true)"
+                  clearable
+                ></el-input>
+              </el-form-item>
+              <el-form-item>
+                <div
+                  @click="searchImg(true)"
+                  class="primary-btn default-btn"
+                >{{$t("videoManager.query")}}</div>
+                <div
+                class="primary-btn default-btn"
+                :disabled="disabled"
+                @click="createGroup"
+              >{{$t("resource.newGroup")}}</div>
+              </el-form-item>
+              <!-- <el-form-item>
+                <el-button type="primary" @click="clean">清空</el-button>
+              </el-form-item>-->
+            </el-form>
+          </div>
+          <div class="operation-bar">
+            <div
+                class="default-btn primary-btn"
+                @click="uploadDialog"
+              >上传音频</div>
+          </div>
+          <div class="box">
+            <div class="group-box">
+              <div class="group">
+                <div class="group-item active-title">
+                  <span class="group-name">{{$t("resource.groupName")}}</span>
+                  <span class="sidebar-operate">{{$t("crud.menu")}}</span>
+                </div>
+                <div :class="['group-item',groupId === 0 ?'active': '']"  @click="clickGroup(0)">
+                  <span class="group-name">全部音频</span>
+                </div>
+                <div :class="['group-item',groupId === item.attachFileGroupId ?'active': '']" v-for="(item) in groupList" :key="item.attachFileGroupId">
+
+                  <el-input style="height: 31px !important;width: 210px" ref="updateGroupName" v-model="createGroupName" maxlength="6" v-if="isUploadGroup && updateGroupId === item.attachFileGroupId"  size="small">
+                    <template slot="append">
+                      <span @click="submitGroup">{{$t("resource.confirm")}}</span>
+                    </template>
+                  </el-input>
+                  <span v-else class="group-name" @click="clickGroup(item.attachFileGroupId)">{{ item.name }}</span>
+                  <span class="sidebar-operate">
+                    <div class="default-btn text-btn" @click="updateGroup(item.attachFileGroupId,item.name)" >{{$t("resource.update")}}</div>
+                    <div class="default-btn text-btn" @click="deleteGroup(item.attachFileGroupId)" >{{$t("resource.Delete")}}</div>
+                  </span>
+                </div>
+              </div>
+            </div>
+            <div class="img-list">
+              <div class="elx-main elx-img-list">
+                <div class="elx-head">
+                  <span class="text"><el-checkbox v-model="selectAll" :indeterminate="isIndeterminate" @change="selectAllEvent">{{$t("resource.selectAll")}}</el-checkbox></span>
+                  <span class="text" @click="delectImgs">{{$t("resource.Delete")}}</span>
+                  <span class="text" @click="batchMove">{{$t("resource.Move")}}</span>
+                </div>
+                <div class="img-item-con">
+                  <div v-for="(img, itemIndex) in imgRes.records" :key="itemIndex" class="img-item">
+                    <div class="thumb-wp" @click.stop="onClickListImage(img)">
+                      <!-- <img v-if="img.filePath" :src="(img.filePath).indexOf('http')===-1 ? resourcesUrl + img.filePath : img.filePath" alt="img.name" /> -->
+                      <video
+                        :src="resourcesUrl + img.filePath"
+                        controls="controls"
+                        class="showVideo"
+                        style="width:175px;height:87.5px;"
+                      />
+                      </div>
+                      <input
+                        type="text"
+                        @blur="isUpdateFileName = false"
+                        v-if="isUpdateFileName && updateFileId === img.fileId"
+                        v-model="updateFileName"
+                        autofocus
+                        ref="updateName"
+                        @keyup.enter="submitImgName"
+                        style="width: 175px;outline: none;">
+                      <div class="title" v-else @click="handleFileName(img)">{{img.fileName}}</div>
+                      <!-- <div class="label" v-if="img.label">{{img.label}}</div> -->
+                      <span class="selected-def" @click="onClickListImage(img)">
+                      </span>
+                      <span v-if="img.selected" class="selected" @click="onClickListImage(img)">
+                        <span class="icon el-icon-check" />
+                      </span>
+                    </div>
+                  </div>
+                </div>
+                <div class="data-tips" v-if="!imgRes.records||!imgRes.records.length">{{$t("order.noData")}}</div>
+                <el-pagination
+                    layout="total, prev, pager, next, jumper"
+                    :current-page="imgRes.current"
+                    :page-size="imgRes.size"
+                    :total="imgRes.total"
+                    class="pagination"
+                    @current-change="onPageNumChange"
+                ></el-pagination>
+            </div>
+          </div>
+        </div>
+    </div>
+    <!-- 批量移动分组 -->
+    <el-dialog
+      :title="$t('resource.mobileGroup')"
+      :close-on-click-modal="false"
+      :visible.sync="showBatchMove"
+      top="200px"
+      :append-to-body="visible"
+      width="500px"
+    >
+      <el-form ref="groupForm" label-width="80px">
+        <el-form-item :label="$t('resource.group')">
+          <el-select size="small" v-model="selectGroup" :placeholder="$t('resource.selectGroup')">
+            <el-option
+              v-for="item in groupList"
+              :key="item.attachFileGroupId"
+              :label="item.name"
+              :value="item.attachFileGroupId">
+            </el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <div class="default-btn" @click="showBatchMove = false">{{$t("resource.cancel")}}</div>
+        <div class="primary-btn default-btn" @click="submitBatchMove()">{{$t("resource.confirm")}}</div>
+      </span>
+    </el-dialog>
+    <upload-audio ref="uploadVideo" v-if="uploadDialogVisible" @getVideoListData="loadListImage(1)" @getGroupData="getGroupList" @uploadClose="uploadClose"  />
+    <group-add-or-update ref="groupAddOrUpdate" v-if="groupVisible" @getGroupData="getGroupList" />
+    <!-- /批量移动分组 -->
+  </div>
+</template>
+
+<script type="text/babel">
+import uploadAudio from './upload-audio.vue'
+import { Debounce } from '@/utils/debounce'
+import groupAddOrUpdate from '../components/group-add-or-update.vue'
+export default {
+  name: 'ElxImgbox',
+  components: {
+    uploadAudio,
+    groupAddOrUpdate
+  },
+  data () {
+    return {
+      theData: null, // 保存上次点击查询的请求条件
+
+      images: [], // 已选图片
+      fileIds: [], // 已选图片的fileId
+      dataForm: {},
+      uploadFileNum: 0,
+      createGroupName: '', // 新建分组名
+      groupVisible: false,
+      showBatchMove: false,
+      options: {
+        multiple: true, // 是否支持选取多个图片
+        limit: 20, // 最多可选择图片数量
+        maxSize: 2, // 最大尺寸(M)
+        activeTab: 'pick',
+        enableUpload: true, // 是否启用图片上传
+        callback: null
+      },
+      groupList: [], // 分组列表
+      selectGroup: '',
+      showGroupType: 0, // 0:新建分组 1:修改分组
+      errShow: false,
+      picNum: 0,
+      resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+      type: 2,
+      fileName: '',
+      listType: 'picture',
+      isLoading: true,
+      visible: false,
+      disabled: false,
+      notImg: false,
+      uploadSuccessCount: 0,
+      imgRes: {
+        current: 1
+      },
+      videoList: [],
+      isSubmit: false,
+      uploadFlag: 0,
+      selectAll: false,
+
+      uploadDialogVisible: false,
+      isUploadGroup: false,
+      groupId: 0, // 点击分组
+      updateGroupId: 0, // 修改分组的id
+      isUpdateFileName: false,
+      updateFileName: '',
+      updateFileId: '',
+      isIndeterminate: false
+    }
+  },
+
+  methods: {
+    handleFileName (img) {
+      this.selectGroup = img.attachFileGroupId
+      this.updateFileId = img.fileId
+      this.updateFileName = img.fileName
+      this.isUpdateFileName = true
+      this.$nextTick(() => { // 2. 弹框显示DOM更新完成后 获取refs.ref1 设置焦点
+        this.$refs.updateName[0].focus() // 设置焦点
+      })
+    },
+    show () {
+      this.visible = true
+    },
+
+    hide () {
+      this.visible = false
+    },
+    uploadClose () {
+      this.uploadDialogVisible = false
+    },
+    uploadDialog () {
+      this.uploadDialogVisible = true
+      this.$nextTick(() => {
+        this.$refs.uploadVideo.show()
+      })
+    },
+    onConfirm () {
+      if (this.type) {
+        this.$emit('refreshPic', this.images[0].filePath)
+      } else {
+        let imgPaths = this.images.map(file => {
+          return file.filePath
+        }).join(',')
+        this.$emit('refreshPic', imgPaths)
+      }
+      this.visible = false
+    },
+
+    /**
+     * 提交修改后的图片名称
+     */
+    submitImgName () {
+      this.$http({
+        url: this.$http.adornUrl('/admin/file/updateFile'),
+        method: 'put',
+        data: this.$http.adornData({
+          fileId: this.updateFileId,
+          fileName: this.updateFileName,
+          attachFileGroupId: this.selectGroup,
+          type: 2
+        })
+      }).then(({ data }) => {
+        this.$message({
+          message: this.$i18n.t('resource.updateSuccess'),
+          type: 'success',
+          duration: 1000,
+          onClose: res => {
+            this.selectGroup = ''
+            this.isUpdateFileName = false
+            this.loadListImage(this.imgRes.current)
+          }
+        })
+      }).catch(({ e }) => {
+      })
+    },
+    /**
+     * 批量删除
+     */
+    delectImgs () {
+      if (!this.fileIds.length) {
+        this.$message({
+          message: this.$i18n.t('videoManager.tips1'),
+          type: 'error',
+          duration: 1000
+        })
+        return
+      }
+      this.$confirm(this.$i18n.t('pictureManager.tips3'), this.$i18n.t('resource.tips'), {
+        confirmButtonText: this.$i18n.t('resource.confirm'),
+        cancelButtonText: this.$i18n.t('resource.cancel'),
+        type: 'warning'
+      }).then(() => {
+        this.$http({
+          url: this.$http.adornUrl('/admin/file/deleteByIds'),
+          method: 'delete',
+          data: this.fileIds
+        }).then(({ data }) => {
+          this.images = []
+          this.fileIds = []
+          this.selectAll = false
+          this.selectAllEvent()
+          this.loadListImage()
+        })
+      })
+    },
+    /**
+     * 批量移动分组
+     */
+    batchMove () {
+      if (!this.fileIds.length) {
+        this.$message({
+          message: this.$i18n.t('videoManager.tips1'),
+          type: 'error',
+          duration: 1000
+        })
+        return
+      }
+      this.showBatchMove = true
+    },
+    submitBatchMove () {
+      this.$http({
+        url: this.$http.adornUrl('/admin/file/batchMove'),
+        method: 'put',
+        data: this.fileIds,
+        params: {
+          groupId: this.selectGroup
+        }
+      }).then(({ data }) => {
+        this.images = []
+        this.fileIds = []
+        this.showBatchMove = false
+        this.selectAll = false
+        this.$message({
+          message: this.$i18n.t('publics.operation'),
+          type: 'success',
+          duration: 1000,
+          onClose: () => {
+            this.loadListImage()
+          }
+        })
+      })
+    },
+    /**
+     * 点击图片时选中或取消选中图片
+     * @param img object
+     */
+    onClickListImage (img) {
+      // if(!this.uploadNumberLimit()) {
+      //   return this.onUploadExceedTip()
+      // }
+        // 多选图片-如果已选中则取消选中
+      var imgIndex = this.selectedImageIndex(img)
+      if (img.selected) {
+          // 取消图片已选状态
+        img.selected = false
+        this.images.splice(imgIndex, 1)
+        this.fileIds.splice(imgIndex, 1)
+        if (this.images.length !== this.imgRes.records.length) {
+          this.selectAll = false
+        } else {
+          this.selectAll = true
+        }
+        if (this.images.length) {
+          this.isIndeterminate = true
+        } else {
+          this.isIndeterminate = false
+        }
+        this.$forceUpdate()
+        return
+      }
+      img.selected = true
+      this.images.push(JSON.parse(JSON.stringify(img)))
+      this.fileIds.push(img.fileId)
+      if (this.images.length !== this.imgRes.records.length) {
+        this.selectAll = false
+      } else {
+        this.selectAll = true
+      }
+      if (this.images.length) {
+        this.isIndeterminate = true
+      } else {
+        this.isIndeterminate = false
+      }
+      this.$forceUpdate()
+    },
+    /**
+     * 清除所有已点击图片样式
+     */
+    clearListSelected () {
+      if (this.type) {
+        let list = this.imgRes.records
+        list.forEach(element => {
+          element.selected = false
+        })
+      }
+    },
+    /**
+         * 按图片名称搜索图片
+         */
+    searchImg (newData = false) {
+      this.loadListImage(1, newData)
+    },
+    /**
+     * 加载图片列表数据
+     * @param page
+     */
+    loadListImage (current, newData = false) {
+      this.isLoading = true
+      if (newData || !this.theData) {
+        this.theData = {
+          current: current,
+          size: 18,
+          fileName: this.fileName ? this.fileName : null,
+          attachFileGroupId: this.groupId,
+          type: 4
+        }
+      } else {
+        this.theData = {fileName: this.theData.fileName,
+          ...{
+            current: current,
+            size: 18,
+            attachFileGroupId: this.groupId,
+            type: 4
+          } }
+      }
+      this.$http({
+        url: this.$http.adornUrl('/admin/file/attachFilePage'),
+        method: 'get',
+        params: this.$http.adornParams(this.theData)
+      }).then(({ data }) => {
+        this.imgRes = data
+        this.imgRes.records.forEach(img => {
+          if (!this.isExist(img)) {
+            img.selected = false
+          } else {
+            img.selected = true
+          }
+        })
+        // this.fileIds = []
+        this.isLoading = false
+        this.selectAll = false
+        this.isUploadGroup = false
+      })
+    },
+    isExist (img) {
+      for (let i = 0; i < this.images.length; i++) {
+        if (img.fileId === this.images[i].fileId) {
+          return true
+        }
+      }
+      return false
+    },
+    /**
+     * 图片已选则返回下标,未选则返回-1
+     */
+    selectedImageIndex (img) {
+      for (let i = 0; i < this.images.length; i++) {
+        var selectedImg = this.images[i]
+        if (selectedImg.fileId === img.fileId) {
+          return i
+        }
+      }
+      return -1
+    },
+
+    /**
+     * 分页页面变化时刷新数据
+     * @param page
+     */
+    onPageNumChange (page) {
+      this.loadListImage(page)
+    },
+    /**
+     * 新建分组
+     */
+    submitGroup: Debounce(function () {
+      if (!this.createGroupName.trim()) {
+        return this.$message.error(this.$i18n.t('resource.CannotBeEmpty'))
+      }
+      const method = 'put'
+      const param = {
+        name: this.createGroupName,
+        type: 3 // 1、图片 2、视频 3、文件 4、音频
+      }
+      param.attachFileGroupId = this.updateGroupId
+      this.$http({
+        url: this.$http.adornUrl('/admin/fileGroup'),
+        method,
+        data: param
+      }).then(res => {
+        this.$message({
+          message: this.$i18n.t('resource.successTips1'),
+          type: 'success',
+          duration: 100,
+          onClose: res => {
+            this.getGroupList()
+            this.isUploadGroup = false
+          }
+        })
+      })
+    }),
+    /**
+     * 获取分组列表
+     */
+    getGroupList () {
+      this.$http({
+        url: this.$http.adornUrl('/admin/fileGroup/list'),
+        method: 'get',
+        params: {
+          type: 2 // 1、图片 2、视频 3、文件 4、音频
+        }
+      }).then(res => {
+        this.groupList = res.data
+      })
+    },
+    /**
+     * 点击分组
+     */
+    clickGroup (id) {
+      this.groupId = id
+      this.loadListImage()
+    },
+    updateGroup (id, name) {
+      this.updateGroupId = id
+      this.createGroupName = name
+      this.isUploadGroup = true
+      this.$nextTick(() => { // 2. 弹框显示DOM更新完成后 获取refs 设置焦点
+        this.$refs.updateGroupName[0].focus() // 设置焦点
+      })
+    },
+    createGroup () {
+      this.groupVisible = true
+      this.$nextTick(() => {
+        this.$refs.groupAddOrUpdate.show(2)
+      })
+    },
+    deleteGroup (id) {
+      this.$confirm(this.$i18n.t('pictureManager.tips2'), this.$i18n.t('resource.tips'), {
+        confirmButtonText: this.$i18n.t('resource.confirm'),
+        cancelButtonText: this.$i18n.t('resource.cancel'),
+        type: 'warning'
+      }).then(() => {
+        this.$http({
+          url: this.$http.adornUrl('/admin/fileGroup'),
+          method: 'delete',
+          params: {
+            attachFileGroupId: id
+          }
+        }).then(res => {
+          this.getGroupList()
+        })
+      })
+    },
+    /**
+     * 提交上传图片
+     */
+    onUploadConfirm () {
+      this.notImg = true
+      this.isSubmit = true
+      this.fileIds = []
+      this.uploadFlag = 0
+      this.$refs.upload.submit()
+    },
+
+    onUploadProgress (event, file, fileList) {
+
+    },
+    /**
+     * 上传视频
+     */
+    httpRequest (event) {
+      this.videoList.forEach(item => {
+        if (item.uid === event.file.uid) {
+          this.uploadFile(event)
+          this.notImg = true
+        }
+      })
+    },
+    uploadFile (event) {
+      const file = event.file
+      // 获取本次上传文件的位置
+      const formdata = new FormData()
+      formdata.append('FileName', file.name)
+      formdata.append('file', file)
+      this.$http({
+        url: this.$http.adornUrl('/admin/file/upload/element'),
+        method: 'post',
+        headers: {
+          'Content-Type': file.type
+        },
+        data: formdata
+      }).then(res => {
+        event.onSuccess(res.data)
+      })
+    },
+    // 视频预上传
+    onUploadChange (file, fileList) {
+      if (['video/mp4', 'video/ogg', 'video/webm'].indexOf(file.raw.type) === -1) {
+        this.$message.error(this.$i18n.t('videoManager.tips2'))
+        return false
+      }
+      if (this.isSubmit) {
+        return
+      }
+      const showVideoList = document.getElementsByClassName('upShowVideo')
+      showVideoList.forEach((item) => {
+        if (!item.paused) { item.pause() }
+      })
+      const videoSrc = URL.createObjectURL(file.raw)
+      this.videoList.push({ url: videoSrc, uid: file.uid })
+    },
+    // 删除预览视频
+    preDeleteVideo (index) {
+      this.videoList.splice(index, 1)
+    },
+    errMsg () {
+      if (this.errShow && this.uploadFileNum === this.picNum) {
+        this.picNum = 0
+        this.message(this.$i18n.t('videoManager.onlyPictures'), true)
+        this.notImg = false
+      }
+    },
+    /**
+     * 上传视频前检查合法性
+     * @param file
+     * @returns {boolean}
+     */
+    beforeUploadVideo (file) {
+      const isLt20M = file.size / 1024 / 1024 < 20
+      if (!isLt20M) {
+        this.$message.error(this.$i18n.t('videoManager.tips3'))
+        return false
+      }
+      return true
+    },
+
+    uploadNumberLimit () {
+      if (!this.options.multiple) {
+        return 1
+      }
+      return this.options.limit - this.images.length - this.uploadFileNum
+    },
+
+    uploadTypeTip () {
+      return this.$i18n.t('videoManager.onlySupported') + ' mp4/mov/webm ' + this.$i18n.t('videoManager.video')
+    },
+
+    uploadSizeTip () {
+      return this.$i18n.t('videoManager.notExceed') + '20M'
+    },
+
+    uploadTips () {
+      let tips = [this.uploadTypeTip(), this.uploadSizeTip()]
+
+      if (!this.options.multiple) {
+        return tips.join(',')
+      }
+
+      if (this.images.length > 0) {
+        tips.push(this.$i18n.t('videoManager.alreadyExist') + this.images.length + this.$i18n.t('videoManager.unit'))
+      }
+
+      const uploadFileNum = this.videoList.length
+      if (uploadFileNum > 0) {
+        tips.push(this.$i18n.t('videoManager.soonUpload') + uploadFileNum + this.$i18n.t('videoManager.unit'))
+      }
+      this.uploadFileNum = uploadFileNum
+      tips.push(this.$i18n.t('videoManager.remainder') + (this.options.limit - this.images.length - uploadFileNum) + this.$i18n.t('videoManager.unit') + this.$i18n.t('videoManager.upload'))
+
+      return tips.join(',')
+    },
+
+    /**
+     * 上传错误处理
+     * @param err
+     * @param file
+     * @param fileList
+     */
+    onUploadError (err, file, fileList) {
+      this.message(this.$i18n.t('videoManager.requestError'), true)
+      throw err
+    },
+
+    /**
+     * 上传成功处理
+     * @param response
+     * @param file
+     * @param fileList
+     * @returns {boolean}
+     */
+    onUploadSuccess (fileId, file, fileList) {
+      this.uploadFlag ++
+      this.fileIds.push(fileId)
+      if (this.videoList.length === this.uploadFlag) {
+        this.disabled = true
+        this.$refs.upload.uploadFiles = []
+        if (this.selectGroup) {
+          this.submitBatchMove()
+        }
+        this.options.activeTab = 'pick'
+        setTimeout(() => {
+          this.isSubmit = false
+          this.videoList = []
+        })
+        this.loadListImage(1)
+      }
+    },
+
+    /**
+     * 选择上传文件超过限制文件个数提示
+     */
+    onUploadExceedTip () {
+      this.message(this.$i18n.t('videoManager.maxSelect') + this.uploadNumberLimit() + this.$i18n.t('videoManager.unit') + this.$i18n.t('videoManager.upload'))
+    },
+    message (msg, isInfo) {
+      var type = 'error'
+      if (isInfo) {
+        type = 'info'
+      }
+      this.$message({
+        message: msg,
+        type: type,
+        duration: 1500
+      })
+    },
+
+    /**
+     * tab切换事件
+     */
+    tabClick (tab) {
+      this.fileName = ''
+      if (tab.name === 'pick') {
+        this.loadListImage(1)
+      }
+    },
+    /**
+     * 全选图片事件
+     */
+    selectAllEvent () {
+      if (this.selectAll) {
+        this.imgRes.records.forEach(img => {
+          this.images.push(JSON.parse(JSON.stringify(img)))
+          this.fileIds.push(img.fileId)
+          img.selected = true
+        })
+        this.isIndeterminate = true
+      } else {
+        this.imgRes.records.forEach(img => {
+          img.selected = false
+          this.isIndeterminate = false
+          this.fileIds = []
+          this.images = []
+        })
+      }
+    },
+    /**
+     * 关闭回调
+     */
+    handleDialogClose () {
+      this.fileName = ''
+    }
+  },
+
+  mounted () {
+    this.getGroupList()
+    this.loadListImage()
+  },
+
+  computed: {
+
+  }
+}
+</script>
+
+<style lang="scss">
+.elx-images {
+  .el-upload-list__item,
+  .el-upload--picture-card {
+    width: 78px;
+    height: 78px;
+    line-height: 82px;
+    border-radius: 5px;
+  }
+}
+.elx-head {
+  background: #F7F7F7;
+  height: 40px;
+  width: 100%;
+  line-height: 40px;
+  .text {
+    color: #606266;
+    font-size: 14px;
+    margin-left: 7px;
+    cursor:pointer;
+  }
+}
+</style>
+<style lang="scss" scoped>
+div ::v-deep .el-input-group__append, .el-input-group__prepend {
+  background: #155BD4 !important;
+  color: #FFFFFF;
+  border: none;
+}
+.search-bar {
+  padding-bottom: 0px;
+}
+.box {
+  display: flex;
+  justify-content: flex-start;
+  .group {
+    min-width: 200px;
+    .group-item {
+      height: 44px;
+      line-height: 44px;
+      padding: 0 10px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      cursor:pointer;
+
+      .group-name {
+        width: 200px;
+      }
+      .sidebar-operate {
+        .default-btn + .default-btn {
+          margin-left: 12px;
+        }
+      }
+    }
+    .group-item:hover{
+      background: #F2F7FF;
+    }
+    .active {
+      background: #F2F7FF;
+    }
+    .active-title {
+      height: 40px;
+      line-height: 40px;
+      background: #f7f8fa !important;
+      cursor: auto;
+    }
+  }
+}
+.group-box {
+  height: 530px;
+  min-width: 380px;
+  margin-right: 25px;
+  border: 1px solid #E8E9EC;
+}
+.select-group-box {
+  padding: 20px 0 0 20px;
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  .select-group-box-item {
+    margin-right: 10px;
+  }
+}
+.pick-block {
+    $bg: #f6f6f6;
+    position: relative;
+    .elx-img-list-loading {
+      position: absolute;
+      top: 60px;
+      z-index: 9;
+      left: 0;
+      right: 0;
+      width: 100%;
+      height: 520px;
+      // 加载层高度
+      background: #fff;
+      text-align: center;
+
+      .el-icon-loading {
+        font-size: 50px;
+        color: #409eff;
+        line-height: 460px;
+      }
+    }
+
+    .elx-img-list {
+      min-height: 530px;
+      max-width: 1200px;
+      border: 1px solid #E8E9EC;
+      // 图片列表高度
+      .img-item-con {
+        padding-top: 15px;
+      }
+      .img-item {
+        $imgSize: 175px;
+        $size: 175px;
+        float: left;
+        width: $imgSize;
+        cursor: pointer;
+        position: relative;
+        font-size: 12px;
+        margin: 0 10px 20px;
+        img {
+          width: $imgSize;
+          height: $imgSize;
+          display: block;
+          object-fit: contain
+        }
+
+        .title {
+          line-height: 24px;
+          height: 24px;
+          display: block;
+          overflow: hidden;
+          background: $bg;
+          padding: 0 5px;
+          cursor: text;
+          word-break: break-word;
+          text-overflow: ellipsis;
+          display: -webkit-box;
+          -webkit-line-clamp: 1;
+         /* autoprefixer: ignore next */
+          -webkit-box-orient: vertical;
+          line-height: 20px;
+        }
+        .operate {
+          line-height: 24px;
+          height: 24px;
+          display: block;
+          overflow: hidden;
+          // background: $bg;
+          margin-top: 2px;
+          padding: 0 5px;
+          .edit {
+            float: left;
+            padding-left: 5px;
+          }
+          .del {
+            float: right;
+            padding-right: 5px;
+          }
+        }
+
+        .label {
+          position: absolute;
+          z-index: 9;
+          left: 0;
+          bottom: 24px;
+          width: 100%;
+          height: 21px;
+          line-height: 21px;
+          text-align: center;
+          color: #fff;
+
+          &:after {
+            content: " ";
+            position: absolute;
+            left: 0;
+            bottom: 0;
+            width: 100%;
+            height: 21px;
+            background: #000;
+            opacity: 0.3;
+            z-index: -1;
+          }
+        }
+
+        .selected {
+          position: absolute;
+          right: 0;
+          top: 0;
+          width: $size;
+          height: 115px;
+          border: 1px solid #155BD4;
+          text-align: right;
+          .icon {
+            background: #155BD4;
+            text-align: center;
+            height: 18px;
+            width: 18px;
+            line-height: 18px;
+            display: inline-block;
+            font-size: 16px;
+            color: #fff;
+            border-radius: 0 0 0 3px;
+            position: absolute;
+            right: 0;
+            top: 0;
+          }
+        }
+        .selected-def {
+          position: absolute;
+          right: 0;
+          top: 0;
+          width: 175px;
+          height: 50%;
+          text-align: left;
+        }
+      }
+
+      &::after {
+        content: " ";
+        display: table;
+        height: 0;
+        clear: both;
+        visibility: hidden;
+      }
+    }
+}
+div ::v-deep .el-tabs__header{
+  display: none !important;
+}
+.operation-bar {
+  margin: 20px 0;
+}
+.img-list {
+  width: 100%;
+  position: relative;
+    .data-tips {
+    position: absolute;
+    top: 30%;
+    left: 38%;
+  }
+}
+.pagination {
+  margin-top: 30px;
+  margin-right: 30px;
+}
+</style>

+ 443 - 0
src/views/modules/resource/audio-store/upload-audio.vue

@@ -0,0 +1,443 @@
+<template>
+  <el-dialog
+      title="上传音频"
+      :close-on-click-modal="false"
+      :visible.sync="visible"
+      @close="handleDialogClose"
+      top="200px"
+      v-if="visible"
+      width="770px"
+    >
+    <div class="elx-imgbox-dialog">
+      <div class="elx-main">
+        <el-form label-width="auto">
+          <el-form-item :label="$t('resource.selectGroup')+':'">
+            <el-select size="small" v-model="selectGroup" clearable :placeholder="$t('tip.select')" class="select-group-box-item">
+            <el-option
+              v-for="item in groupList"
+              :key="item.attachFileGroupId"
+              :label="item.name"
+              :value="item.attachFileGroupId">
+            </el-option>
+          </el-select>
+          <div class="default-btn text-btn select-group-box-item" @click="createGroup">{{$t("resource.newGroup")}}</div>
+          </el-form-item>
+          <el-form-item label="上传音频:">
+            <div class="upload-video-box">
+              <div v-for="(item, index) in videoList" :key="index" class="video-preview">
+                <video
+                  v-if="item.url"
+                  class="upShowVideo"
+                  :src="item.url"
+                  controls="controls"
+                  style="width:175px;height:87.5px;"
+                />
+                <span>{{item.name}}</span>
+                <!-- 显示查看和删除的按钮弹窗 -->
+                <div  class="avatar-uploader-popup" >
+                  <i class="el-icon-delete" @click="preDeleteVideo(index)" />
+                </div>
+              </div>
+            </div>
+              <el-upload
+                ref="upload"
+                :class="['upload-img-preview',uploadNumberLimit()?'uoloadSty':'disUoloadSty']"
+                list-type="picture-card"
+                action=""
+                :headers="{Authorization: $cookie.get('Authorization_vs'),locale:lang}"
+                :multiple="true"
+                accept="audio/*"
+                :auto-upload="false"
+                :show-file-list="false"
+                :limit="options.limit"
+                :before-upload="beforeUploadVideo"
+                :http-request="httpRequest"
+                :on-change="onUploadChange"
+                :on-progress="onUploadProgress"
+                :on-success="onUploadSuccess"
+                :on-error="onUploadError"
+                :on-exceed="onUploadExceedTip">
+                <i class="el-icon-plus"></i>
+              </el-upload>
+          </el-form-item>
+          <el-form-item>
+            <div class="upload-tip">{{ uploadTips() }}</div>
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
+    <span slot="footer">
+      <div class="default-btn" @click="handleDialogClose">{{$t("shopFeature.edit.back")}}</div>
+      <div
+        class="primary-btn default-btn"
+        @click="onUploadConfirm"
+      >{{$t("pictureManager.confirmUpload")}}</div>
+    </span>
+    <group-add-or-update ref="groupAddOrUpdate" v-if="groupVisible" @getGroupData="getGroupList" @pageUpdateGroup="pageUpdateGroup"  />
+  </el-dialog>
+</template>
+
+<script type="text/babel">
+import groupAddOrUpdate from '../components/group-add-or-update.vue'
+import { Debounce } from '@/utils/debounce'
+export default {
+  components: {
+    groupAddOrUpdate
+  },
+  data () {
+    return {
+      lang: localStorage.getItem('lang') || 'zh_CN',
+      images: [], // 已选图片
+      fileIds: [], // 已选图片的fileId
+      dataForm: {},
+      uploadFileNum: 0,
+      groupVisible: false,
+      showBatchMove: false,
+      options: {
+        multiple: true, // 是否支持选取多个图片
+        limit: 9, // 最多可选择图片数量
+        maxSize: 20, // 最大尺寸(M)
+        callback: null
+      },
+      groupList: [], // 分组列表
+      selectGroup: '',
+      showGroupType: 0, // 0:新建分组 1:修改分组
+      newImgName: '',
+      isTrue: true,
+      imageObject: null,
+      errShow: false,
+      picNum: 0,
+      resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
+      type: 2,
+      fileName: '',
+      listType: 'picture',
+      isLoading: true,
+      visible: false,
+      disabled: false,
+      notImg: false,
+      uploadSuccessCount: 0,
+      imgRes: {
+        current: 1
+      },
+      videoList: [],
+      isSubmit: false,
+      uploadFlag: 0,
+      updateGroupId: 0 // 修改分组的id
+    }
+  },
+
+  methods: {
+    show () {
+      this.visible = true
+    },
+
+    hide () {
+      this.visible = false
+    },
+    submitBatchMove () {
+      if (!this.selectGroup) {
+        this.visible = false
+        this.$emit('getVideoListData')
+        this.$emit('uploadClose')
+        return this.$message({
+          type: 'success',
+          message: this.$i18n.t('videoManager.video') + this.$i18n.t('resource.uploadSuccess')
+        })
+      }
+      this.$http({
+        url: this.$http.adornUrl('/admin/file/batchMove'),
+        method: 'put',
+        data: this.fileIds,
+        params: {
+          groupId: this.selectGroup
+        }
+      }).then(({ data }) => {
+        this.fileIds = []
+        this.$message({
+          type: 'success',
+          message: this.$i18n.t('videoManager.video') + this.$i18n.t('resource.uploadSuccess')
+        })
+        this.$emit('getVideoListData')
+        this.$emit('uploadClose')
+        this.visible = false
+      })
+    },
+    pageUpdateGroup () {
+      this.$emit('getGroupData')
+    },
+    /**
+     * 获取分组列表
+     */
+    getGroupList () {
+      this.$http({
+        url: this.$http.adornUrl('/admin/fileGroup/list'),
+        method: 'get',
+        params: {
+          type: 4 // 1、图片 2、视频 3、文件 4、音频
+        }
+      }).then(res => {
+        this.groupList = res.data
+      })
+    },
+    createGroup () {
+      this.groupVisible = true
+      this.$nextTick(() => {
+        this.$refs.groupAddOrUpdate.show(2)
+      })
+    },
+    /**
+     * 提交上传图片
+     */
+    onUploadConfirm: Debounce(function () {
+      if (!this.videoList.length) {
+        this.message(this.$i18n.t('videoManager.tips1'), false)
+        return
+      }
+      this.notImg = true
+      this.isSubmit = true
+      this.fileIds = []
+      this.uploadFlag = 0
+      this.$refs.upload.submit()
+    }, 1500),
+
+    onUploadProgress (event, file, fileList) {
+
+    },
+    /**
+     * 上传视频
+     */
+    httpRequest (event) {
+      this.videoList.forEach(item => {
+        if (item.uid === event.file.uid) {
+          this.uploadFile(event)
+          this.notImg = true
+        }
+      })
+    },
+    uploadFile (event) {
+      const file = event.file
+      // 获取本次上传文件的位置
+      const formdata = new FormData()
+      formdata.append('FileName', file.name)
+      formdata.append('file', file)
+      this.$http({
+        url: this.$http.adornUrl('/admin/file/upload/audio'),
+        method: 'post',
+        headers: {
+          'Content-Type': file.type
+        },
+        data: formdata
+      }).then(res => {
+        event.onSuccess(res.data)
+      })
+    },
+    // 音频预上传
+    onUploadChange (file, fileList) {
+      const isLt5M = file.size / 1024 / 1024 < 5
+      if (!isLt5M) {
+        this.$newMessage.error('上传音频大小不能超过5MB!')
+        return
+      }
+      let extend = file.raw.name.split(".")[1]
+      if (["wav", "mp3", "ogg", "acc", "webm", "amr"].indexOf(extend) === -1) {
+        this.$newMessage.error('请上传正确的音频格式')
+        return false
+      }
+      if (this.isSubmit) {
+        return
+      }
+      const showVideoList = document.getElementsByClassName('upShowVideo')
+      showVideoList.forEach((item) => {
+        if (!item.paused) { item.pause() }
+      })
+      const videoSrc = URL.createObjectURL(file.raw)
+      this.videoList.push({ url: videoSrc, uid: file.uid, name: file.name})
+    },
+    // 删除预览视频
+    preDeleteVideo (index) {
+      this.$refs.upload.uploadFiles.splice(index, 1)
+      this.videoList.splice(index, 1)
+    },
+    errMsg () {
+      if (this.errShow && this.uploadFileNum === this.picNum) {
+        this.picNum = 0
+        this.message(this.$i18n.t('videoManager.onlyPictures'), true)
+        this.notImg = false
+      }
+    },
+    /**
+     * 上传视频前检查合法性
+     * @param file
+     * @returns {boolean}
+     */
+    beforeUploadVideo (file) {
+      const isLt5M = file.size / 1024 / 1024 < 5
+      return isLt5M
+    },
+
+    uploadNumberLimit () {
+      if (!this.options.multiple) {
+        return 1
+      }
+      return this.options.limit - this.images.length - this.uploadFileNum
+    },
+
+    uploadTypeTip () {
+      return this.$i18n.t('videoManager.onlySupported') + 'wav, mp3, ogg, acc, webm, amr ' + '音频'
+    },
+
+    uploadSizeTip () {
+      return this.$i18n.t('videoManager.notExceed') + '5M'
+    },
+
+    uploadTips () {
+      let tips = [this.uploadTypeTip(), this.uploadSizeTip()]
+
+      if (!this.options.multiple) {
+        return tips.join(',')
+      }
+
+      if (this.images.length > 0) {
+        tips.push(this.$i18n.t('videoManager.alreadyExist') + this.images.length + this.$i18n.t('videoManager.unit'))
+      }
+
+      const uploadFileNum = this.videoList.length
+      if (uploadFileNum > 0) {
+        tips.push(this.$i18n.t('videoManager.soonUpload') + uploadFileNum + this.$i18n.t('videoManager.unit'))
+      }
+      this.uploadFileNum = uploadFileNum
+      tips.push(this.$i18n.t('videoManager.remainder') + (this.options.limit - this.images.length - uploadFileNum) + '个音频' + this.$i18n.t('videoManager.upload'))
+
+      return tips.join(',')
+    },
+
+    /**
+     * 上传错误处理
+     * @param err
+     * @param file
+     * @param fileList
+     */
+    onUploadError (err, file, fileList) {
+      this.isSubmit = false
+      this.message(this.$i18n.t('videoManager.requestError'), true)
+      // console.log(err)
+      this.videoList = []
+      throw err
+    },
+
+    /**
+     * 上传成功处理
+     * @param response
+     * @param file
+     * @param fileList
+     * @returns {boolean}
+     */
+    onUploadSuccess (fileId, file, fileList) {
+      this.uploadFlag ++
+      this.fileIds.push(fileId)
+      if (this.videoList.length === this.uploadFlag) {
+        this.disabled = true
+        this.$refs.upload.uploadFiles = []
+        this.submitBatchMove()
+        setTimeout(() => {
+          this.isSubmit = false
+          this.videoList = []
+        })
+      }
+    },
+
+    /**
+     * 选择上传文件超过限制文件个数提示
+     */
+    onUploadExceedTip () {
+      this.message(this.$i18n.t('videoManager.maxSelect') + this.uploadNumberLimit() + this.$i18n.t('videoManager.unit') + this.$i18n.t('videoManager.upload'))
+    },
+    message (msg, isInfo) {
+      var type = 'error'
+      if (isInfo) {
+        type = 'info'
+      }
+      this.$message({
+        message: msg,
+        type: type,
+        duration: 1500
+      })
+    },
+    /**
+     * 关闭回调
+     */
+    handleDialogClose () {
+      this.visible = false
+      this.fileName = ''
+      this.videoList = []
+      this.$emit('uploadClose')
+    }
+  },
+
+  mounted () {
+    this.getGroupList()
+  },
+
+  computed: {
+
+  }
+}
+</script>
+
+<style lang="scss">
+.elx-imgbox-dialog {
+  .el-upload-list__item,
+  .el-upload--picture-card {
+    width: 78px !important;
+    height: 78px !important;
+    line-height: 78px;
+    border-radius: 5px;
+  }
+}
+.disUoloadSty .el-upload--picture-card{
+  display:none;   /* 上传按钮隐藏 */
+}
+</style>
+<style lang="scss" scoped>
+.search-bar {
+  padding-bottom: 0px;
+}
+.select-group-box-item {
+  margin-right: 10px;
+}
+
+div ::v-deep .el-tabs__header{
+  display: none !important;
+}
+.operation-bar {
+  margin: 10px 0;
+}
+.upload-tip {
+  font-size: 12px;
+  color: #999999;
+}
+.upload-video-box {
+  width: 600px;
+  .video-preview {
+    width: 175px;
+    height: 100px;
+    display: inline-block;
+    text-align: center;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    margin-right: 8px;
+    margin-top: 20px;
+  }
+}
+.avatar-uploader-popup{
+  width: 100%;
+  background: #f6f6f6;
+  height: 18px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.el-icon-delete {
+  cursor: pointer;
+}
+</style>

+ 1 - 1
src/views/modules/resource/picture-store/picture-store.vue

@@ -41,7 +41,7 @@
               >{{$t("pictureManager.uploadPic")}}</div>
           </div>
           <div class="box">
-            <div class="group-box">
+            <div class="group-box" style="overflow: auto">
               <div class="group">
                 <div class="group-item active-title">
                   <span class="group-name">{{$t("resource.groupName")}}</span>