Ver Fonte

Merge branch 'dev' of http://113.31.163.91:7777/quanshu/mp-ui-pc into dev

guanglong há 3 anos atrás
pai
commit
48c9cc10f2

+ 5 - 0
package-lock.json

@@ -4827,6 +4827,11 @@
       "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
       "dev": true
     },
+    "draggable": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmmirror.com/draggable/-/draggable-4.2.0.tgz",
+      "integrity": "sha512-mu0FSsNY1Sb2q3EuAi3IBI6oVMV8l74y6xxYmloHq2/PJjOJEfpZCLGShzNUQKAF7JMfxA6ejxoGPyw5x6v8Ow=="
+    },
     "duplexer": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",

+ 1 - 0
package.json

@@ -48,6 +48,7 @@
     "axios": "^0.21.1",
     "clipboard": "2.0.6",
     "core-js": "3.8.1",
+    "draggable": "^4.2.0",
     "echarts": "4.9.0",
     "element-ui": "2.15.5",
     "file-saver": "2.0.4",

+ 407 - 0
src/components/DragImageUpload/index.vue

@@ -0,0 +1,407 @@
+<template>
+  <div class="more-img-uploade">
+    <draggable
+      :list="previewList"
+      tag="ul"
+      class="img-list"
+      v-bind="dragOptions"
+      draggable=".item"
+      @update="updateDrag"
+    >
+      <li v-for="(item, index) in previewList" :key="index" class="item">
+        <div class="el-upload-list el-upload-list--picture-card flex">
+          <auth-img v-if="!isPublic" :auth-src="item.thumbUrl" image-width="80px" image-height="80px"></auth-img>
+          <el-image v-if="isPublic" :src="item.thumbUrl" fit="contain" style="width: 80px;height: 80px;"></el-image>
+          <label class="el-upload-list__item-status-label"><i class="el-icon-upload-success el-icon-check"></i></label>
+          <span class="el-upload-list__item-actions">
+            <span class="el-upload-list__item-preview"><i class="el-icon-zoom-in" @click="handlePreview(item)"></i></span>
+            <span class="el-upload-list__item-delete"><i class="el-icon-delete" @click="handleDelete(item)"></i></span>
+          </span>
+        </div>
+      </li>
+        <el-upload
+        :action="fileSaveUrl"
+        list-type="picture-card"
+        :data="reqData"
+        :on-success="fileUploadSuccess"
+        :before-upload="handleBeforeUpload"
+        :limit="limit"
+        :on-error="handleUploadError"
+        :on-exceed="handleExceed"
+        name="file"
+        multiple
+        :on-remove="handleRemove"
+        :show-file-list="false"
+        :headers="headers"
+        :http-request="reqUploadImage"
+        :file-list="previewList"
+        :on-preview="handlePictureCardPreview"
+        :auto-upload="true"
+        :class="{hide: this.fileList.length >= this.limit}">
+        <i class="el-icon-plus"></i>
+
+      </el-upload>
+    </draggable>
+
+    <el-dialog :visible.sync="dialogVisible" title="预览" width="800" append-to-body>
+      <div style="display: block; max-width: 100%; margin: 0 auto;text-align: center;max-height: 435px;overflow: auto;">
+        <auth-img v-if="!isPublic && dialogVisible" :auth-src="dialogImageUrl" image-width="435px" ></auth-img>
+        <img v-if="isPublic" :src="dialogImageUrl" style="display: block; max-width: 100%; margin: 0 auto" />
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import draggable from "vuedraggable";
+import { getToken, getSign } from "@/utils/auth";
+import { randomStr20 } from "@/utils/util";
+import {
+  privateFileSaveUrl,
+  publicFileSaveUrl,
+  publicFileSaveAPI,
+  privateFileSaveAPI,
+  publicFileGetUrl,
+  privateFileGetUrl,
+} from "@/api/common";
+
+import AuthImg from "@/components/AuthImg/index.vue";
+import UploadImg from "@/components/UploadImg/index.vue";
+export default {
+  components: {
+    draggable,
+    AuthImg,
+    UploadImg
+  },
+      props: {
+      // 已经上传的文件url列表
+      value: [String, Object, Array],
+      // 图片数量限制
+      limit: {
+        type: Number,
+        default: 5,
+      },
+      // 大小限制(MB)
+      fileSize: {
+        type: Number,
+        default: 5,
+      },
+      // 文件类型, 例如['png', 'jpg', 'jpeg']
+      fileType: {
+        type: Array,
+        default: () => ["png", "jpg", "jpeg"],
+      },
+      // 是否显示提示
+      isShowTip: {
+        type: Boolean,
+        default: true
+      },
+      // 是否显示提示
+      isPublic: {
+        type: Boolean,
+        default: true
+      },
+      // 半高显示
+      low: {
+        type: Boolean,
+        default: false
+      }
+    },
+    data() {
+      return {
+        dialogImageUrl: "",
+        dialogVisible: false,
+        hideUpload: false,
+        baseUrl: process.env.VUE_APP_BASE_API,
+        uploadImgUrl: this.isPublic ? publicFileSaveUrl : privateFileSaveUrl, // 上传的图片服务器地址
+        fileSaveUrl: '',
+        headers: {
+          Authorization: "Bearer " + getToken(),
+        },
+        fileList: [],
+        previewList: [],
+        reqData: {}
+      };
+    },
+
+  data() {
+    return {
+      dialogImageUrl: "",
+        dialogVisible: false,
+        hideUpload: false,
+        baseUrl: process.env.VUE_APP_BASE_API,
+        uploadImgUrl: this.isPublic ? publicFileSaveUrl : privateFileSaveUrl, // 上传的图片服务器地址
+        fileSaveUrl: '',
+        headers: {
+          Authorization: "Bearer " + getToken(),
+        },
+        fileList: [],
+        previewList: [],
+        reqData: {}
+    };
+  },
+  watch: {
+      value(val) {
+        if (val) {
+          this.initHandle()
+        }
+      }
+    },
+  computed: {
+    // 拖拽属性
+    dragOptions() {
+      return {
+        animation: 200, // 动画时间
+        disabled: false, // false可拖拽,true不可拖拽
+        group: "description",
+        ghostClass: "ghost",
+      };
+    },
+  },
+   methods: {
+    // 拖拽完成
+    updateDrag(e){
+      this.fileList = this.previewList.map(item => {
+        return {
+          fileName: item.name
+        }
+      })
+      this.$emit("input", this.fileList);
+      this.$emit('change')
+    },
+
+    initHandle() {
+      if (this.value) {
+        // 首先将值转为数组
+        const list = Array.isArray(this.value) ? this.value : this.value.split(',')
+        // 然后将数组转为对象数组
+        this.previewList = []
+        this.fileList = list.map(item => {
+          var pitem = {
+            name: item.fileName,
+            url:  (this.isPublic ? publicFileGetUrl : (this.baseUrl + privateFileGetUrl)) + item.fileName,
+            thumbUrl:  (this.isPublic ? publicFileGetUrl : (this.baseUrl + privateFileGetUrl)) + item.fileName + "_s"
+          };
+          this.previewList.push(pitem)
+          return item;
+        });
+      } else {
+        this.previewList = []
+        this.fileList = []
+      }
+    },
+
+    handlePreview(item){
+      this.dialogVisible = true;
+      this.dialogImageUrl = item.url
+
+    },
+
+    handleDelete(item){
+      const findex = this.fileList.map(f => f.fileName).indexOf(item.name);
+      this.fileList.splice(findex, 1);
+      this.previewList.splice(findex, 1);
+      this.$emit("input", this.fileList);
+      this.$emit('change')
+    },
+
+    // 删除图片
+    handleRemove(file, fileList) {
+      const findex = this.fileList.map(f => f.name).indexOf(file.name);
+      this.fileList.splice(findex, 1);
+      this.previewList.splice(findex, 1);
+      this.$emit("input", this.fileList);
+      this.$emit('change')
+    },
+
+    /**
+     * 上传图片
+     */
+    fileUploadSuccess(response, file, fileList) {
+      this.fileList.push({
+        fileName: response.fileName,
+        fileType: response.fileType
+      });
+      this.previewList.push({
+        name: response.fileName,
+        url:  (this.isPublic ? publicFileGetUrl : (this.baseUrl + privateFileGetUrl)) + response.fileName,
+        fileType: response.fileType
+      });
+      this.$emit("input", this.fileList);
+      this.$emit('change')
+      this.loading.close();
+
+    },
+
+    // 上传前loading加载
+    handleBeforeUpload(file) {
+      let isImg = false;
+      if (this.fileType.length) {
+        let fileExtension = "";
+        if (file.name.lastIndexOf(".") > -1) {
+          fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
+        }
+        isImg = this.fileType.some(type => {
+          if (file.type.indexOf(type) > -1) return true;
+          if (fileExtension && fileExtension.indexOf(type) > -1) return true;
+          return false;
+        });
+      } else {
+        isImg = file.type.indexOf("image") > -1;
+      }
+
+      if (!isImg) {
+        this.$message.error(
+          `文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`
+        );
+        return false;
+      }
+      if (this.fileSize) {
+        const isLt = file.size / 1024 / 1024 < this.fileSize;
+        if (!isLt) {
+          this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
+          return false;
+        }
+      }
+      this.getHttpHeader()
+      this.loading = this.$loading({
+        lock: true,
+        text: "上传中",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+    },
+
+    // 自定义文件上传的实现
+    reqUploadImage(param) {
+      var data = this.reqData || {}
+      var params = {
+        file: param.file,
+        ...data
+      }
+      const request = this.isPublic ? publicFileSaveAPI : privateFileSaveAPI
+      request(params, this.headers).then(response => {
+        var res = {
+          fileName: response.data.fileName,
+          fileType: response.data.fileType
+        }
+        this.fileList.push({
+          fileName: response.data.fileName,
+          fileType: response.data.fileType
+        });
+        this.previewList.push({
+          name: response.data.fileName,
+          url:  (this.isPublic ? publicFileGetUrl : (this.baseUrl + privateFileGetUrl)) + response.data.fileName,
+          fileType: response.fileType
+        });
+        this.$emit("input", this.fileList);
+        this.$emit('change')
+        this.loading.close();
+        // 但是我们上传成功了图片, fileList 里面的值却没有改变,还好有on-change指令可以使用
+      }).catch(response => {
+        param.onError()
+      })
+    },
+
+    // 请求头
+    getHttpHeader() {
+      let timestamp = parseInt(new Date().getTime()),
+        nonce = randomStr20();
+      var sign = getSign(this.reqData || {}, timestamp)
+      let url = this.uploadImgUrl + '?sign=' + sign + '&nonce=' + nonce;
+      this.fileSaveUrl = url
+      var headers = {
+        "Authorization": "Bearer " + getToken(),
+        "x-zz-timestamp": timestamp
+      }
+      this.headers = headers
+    },
+
+    // 文件个数超出
+    handleExceed() {
+      this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
+    },
+    // 上传失败
+    handleUploadError() {
+      // this.$message({
+      //   type: "error",
+      //   message: "上传失败",
+      // });
+      this.loading.close();
+    },
+    // 预览
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = true;
+    },
+    // 对象转成指定字符串分隔
+    listToString(list, separator) {
+      let strs = "";
+      separator = separator || ",";
+      for (let i in list) {
+        strs += list[i].url.replace(this.baseUrl, "") + separator;
+      }
+      return strs != '' ? strs.substr(0, strs.length - 1) : '';
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.flex{
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+// .el-upload--picture-card 控制加号部分
+::v-deep.hide .el-upload--picture-card {
+  display: none;
+}
+::v-deep .el-upload--picture-card{
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 80px;
+  height: 80px;
+  line-height: 80px;
+}
+</style>
+<style scoped>
+.img-list {
+  width: 100%;
+  display: flex;
+  flex-wrap: wrap;
+  padding: 0;
+}
+.img-list li,
+.img-li {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 80px;
+  height: 80px;
+  margin: 0 10px 10px;
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+}
+.img-li {
+  float: left;
+}
+.img-list li img {
+  width: 100%;
+  height: 100%;
+  object-fit: contain;
+  background: #000;
+}
+.upload-class {
+  font-size: 28px;
+  color: #8c939d;
+  text-align: center;
+  height: 120px;
+  width: 180px;
+  line-height: 120px;
+  box-sizing: border-box;
+}
+</style>

+ 1 - 1
src/components/ImageUpload/index.vue

@@ -177,7 +177,7 @@
       },
 
       handleDelete(item){
-        const findex = this.fileList.map(f => f.name).indexOf(item.name);
+        const findex = this.fileList.map(f => f.fileName).indexOf(item.name);
         this.fileList.splice(findex, 1);
         this.previewList.splice(findex, 1);
         this.$emit("input", this.fileList);

+ 1 - 1
src/views/business/goods/add.vue

@@ -97,7 +97,7 @@
   </div>
 </template>
 <script>
-import Upload from '@/components/ImageUpload'
+import Upload from '@/components/DragImageUpload'
 import Spec from './components/spec'
 import TinyEditor from '@/components/TinyEditor'
 import { getGoodsDetail, addGoods } from '@/api/business/goods'

+ 1 - 1
src/views/business/goods/components/spec.vue

@@ -138,7 +138,7 @@ export default {
           // console.log(specObj[key] instanceof Array)
           if (!specObj[key]) {
             specObj[key] = []
-            console.log(specObj[key])
+            // console.log(specObj[key])
           }
           specObj[key].push(p.split(':')[1])
         })

+ 1 - 1
src/views/business/goods/index.vue

@@ -116,7 +116,7 @@ import { publicFileGetUrl } from "@/api/common"
 import { getGoodsList, delGoods, setGoodsStatus } from '@/api/business/goods'
 import { accMul } from '@/utils/util'
 export default {
-  name: 'GoodsList',
+  name: 'List',
   data() {
     return {
       IMG_URL: publicFileGetUrl,