From 3af52f6a984c5fe6671640dbfb1c40540416ea7d Mon Sep 17 00:00:00 2001
From: yangfeng <wanwan926_4@163.com>
Date: 星期三, 08 十一月 2023 16:40:51 +0800
Subject: [PATCH] 新建产品增加上传图片功能,增加vue-cropper插件

---
 src/main.js                                          |    3 
 package.json                                         |    1 
 src/views/productManage/product/IconCropper.vue      |  288 +++++++++++++++++++++++++++++++++++++++++
 src/views/productManage/product/AddProductDialog.vue |   70 +++------
 4 files changed, 314 insertions(+), 48 deletions(-)

diff --git a/package.json b/package.json
index 69f1fc5..5b40fc3 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
     "element-ui": "^2.15.13",
     "js-cookie": "^3.0.5",
     "vue": "^2.6.14",
+    "vue-cropper": "^0.6.4",
     "vue-router": "^3.5.1",
     "vuex": "^3.6.2"
   },
diff --git a/src/main.js b/src/main.js
index 8acc4e8..fdfe8f5 100644
--- a/src/main.js
+++ b/src/main.js
@@ -15,6 +15,9 @@
 ElementUI.Dialog.props.closeOnClickModal.default = false
 
 Vue.config.productionTip = false
+// 鍥剧墖瑁佸壀
+import VueCropper from "vue-cropper"
+Vue.use(VueCropper)
 
 new Vue({
   router,
diff --git a/src/views/productManage/product/AddProductDialog.vue b/src/views/productManage/product/AddProductDialog.vue
index 5c63af6..28db941 100644
--- a/src/views/productManage/product/AddProductDialog.vue
+++ b/src/views/productManage/product/AddProductDialog.vue
@@ -122,6 +122,14 @@
                       :disabled="!showFooter"
                     ></el-input>
                   </el-form-item>
+                  <el-form-item label="鍥剧墖涓婁紶锛�" prop="imageUrl">
+                    <IconCropper
+                      :isView="isView"
+                      :image-url="editConfig.infomation.imageSrc"
+                      @getImageData="getImageData"
+                      style="width: 85%"
+                    />
+                  </el-form-item>
                 </div>
                 <div class="right">
                   <el-form-item label="閿�鍞环鏍�" prop="salePrice">
@@ -462,11 +470,10 @@
 </template>
 
 <script>
-// import CommonFormTableView from "@/components/makepager/CommonFormTableView"
+import IconCropper from "./IconCropper"
 import { getProductCategoryList } from "@/api/product/productCategory"
 import { getProductList, addProduct, updateProduct } from "@/api/product/product"
 
-let inputElement = null
 export default {
   name: "AddProductDialog",
   props: {
@@ -482,7 +489,7 @@
       }
     }
   },
-  components: {},
+  components: { IconCropper },
   computed: {
     modalTitle() {
       if (this.editConfig.title === "缂栬緫" && this.editConfig.autoEdit) {
@@ -542,10 +549,19 @@
       ],
       statisticsMap: {
         inLibrary: 0 // 鍦ㄥ簱
-      }
+      },
+      isView: false
     }
   },
   created() {
+    if (this.editConfig.title === "缂栬緫" && !this.editConfig.autoEdit) {
+      this.isView = true
+    }
+    // if (this.editConfig.title === "鏂板缓") {
+    //   this.editConfig.infomation.imageSrc = ""
+    // } else {
+    //   this.editConfig.infomation.imageSrc = "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
+    // }
     this.getProductCategoryList()
     this.getProductList()
     this.setTableForm()
@@ -712,50 +728,8 @@
       this.tableData.splice(scope.$index, 1)
     },
     // 涓婁紶鍥剧墖
-    toGetImg() {
-      if (this.showFooter) {
-        if (inputElement === null) {
-          // 鐢熸垚鏂囦欢涓婁紶鐨勬帶浠�
-          inputElement = document.createElement("input")
-          inputElement.setAttribute("type", "file")
-          inputElement.style.display = "none"
-          if (window.addEventListener) {
-            inputElement.addEventListener("change", this.uploadFile, false)
-          } else {
-            inputElement.attachEvent("onchange", this.uploadFile)
-          }
-          document.body.appendChild(inputElement)
-        }
-        inputElement.click()
-      }
-    },
-    uploadFile(el) {
-      if (el && el.target && el.target.files && el.target.files.length > 0) {
-        console.log(el)
-        const files = el.target.files[0]
-        const isLt2M = files.size / 1024 / 1024 < 2
-        const size = files.size / 1024 / 1024
-        console.log(size)
-        // 鍒ゆ柇涓婁紶鏂囦欢鐨勫ぇ灏�
-        if (!isLt2M) {
-          this.$message.error("涓婁紶澶村儚鍥剧墖澶у皬涓嶈兘瓒呰繃 2MB!")
-        } else if (files.type.indexOf("image") === -1) {
-          //濡傛灉涓嶆槸鍥剧墖鏍煎紡
-          this.$message.error("璇烽�夋嫨鍥剧墖鏂囦欢")
-        } else {
-          const that = this
-          const reader = new FileReader() // 鍒涘缓璇诲彇鏂囦欢瀵硅薄
-          reader.readAsDataURL(el.target.files[0]) // 鍙戣捣寮傛璇锋眰锛岃鍙栨枃浠�
-          reader.onload = function () {
-            // 璇诲彇瀹屾垚鍚庯紝灏嗙粨鏋滆祴鍊肩粰img鐨剆rc
-            that.imageSrc = this.result
-            console.log(this.result)
-            // 鏁版嵁浼犲埌鍚庡彴
-            //const formData = new FormData()
-            //formData.append('file', files); // 鍙互浼犲埌鍚庡彴鐨勬暟鎹�
-          }
-        }
-      }
+    getImageData(data) {
+      console.log(data, "鍥剧墖鏁版嵁")
     },
     // 杩涘嚭鐐瑰嚮
     inOutBoundClick() {
diff --git a/src/views/productManage/product/IconCropper.vue b/src/views/productManage/product/IconCropper.vue
new file mode 100644
index 0000000..4a2cf7c
--- /dev/null
+++ b/src/views/productManage/product/IconCropper.vue
@@ -0,0 +1,288 @@
+<template>
+  <div class="cropper-wrapper">
+    <div v-if="isView">
+      <el-image :src="imageUrl" class="view-image">
+        <div slot="error" class="image-slot">
+          <i class="el-icon-picture-outline"></i>
+        </div>
+      </el-image>
+    </div>
+    <div v-else>
+      <template v-if="!isPreview">
+        <!-- element 涓婁紶鍥剧墖鎸夐挳 -->
+        <el-upload
+          class="avatar-uploader"
+          action=""
+          drag
+          :auto-upload="false"
+          :show-file-list="false"
+          :on-change="handleChangeUpload"
+        >
+          <i class="el-icon-plus avatar-uploader-icon"></i>
+        </el-upload>
+      </template>
+      <div class="pre-box" v-else>
+        <el-image :src="previewImg" alt="" class="view-image" />
+        <el-upload
+          class="upload-demo"
+          action=""
+          :auto-upload="false"
+          :show-file-list="false"
+          :on-change="handleChangeUpload"
+        >
+          <el-button v-if="!isView" type="primary" plain>鏇存崲鍥剧墖</el-button>
+        </el-upload>
+      </div>
+    </div>
+    <!-- vueCropper 鍓鍥剧墖瀹炵幇-->
+    <el-dialog title="鍥剧墖鍓" :visible.sync="dialogVisible" class="crop-dialog" append-to-body>
+      <div class="cropper-content">
+        <div class="cropper" style="text-align: center">
+          <vueCropper
+            ref="cropper"
+            :img="option.img"
+            :outputSize="option.size"
+            :outputType="option.outputType"
+            :info="true"
+            :full="option.full"
+            :canMove="option.canMove"
+            :canMoveBox="option.canMoveBox"
+            :original="option.original"
+            :autoCrop="option.autoCrop"
+            :fixed="option.fixed"
+            :fixedNumber="option.fixedNumber"
+            :centerBox="option.centerBox"
+            :infoTrue="option.infoTrue"
+            :fixedBox="option.fixedBox"
+            :autoCropWidth="option.autoCropWidth"
+            :autoCropHeight="option.autoCropHeight"
+            @cropMoving="cropMoving"
+          />
+        </div>
+      </div>
+      <div class="action-box">
+        <el-upload
+          class="upload-demo"
+          action=""
+          :auto-upload="false"
+          :show-file-list="false"
+          :on-change="handleChangeUpload"
+        >
+          <el-button type="primary" plain>鏇存崲鍥剧墖</el-button>
+        </el-upload>
+        <el-button type="primary" plain @click="clearImgHandle">娓呴櫎鍥剧墖</el-button>
+        <el-button type="primary" plain @click="rotateLeftHandle">宸︽棆杞�</el-button>
+        <el-button type="primary" plain @click="rotateRightHandle">鍙虫棆杞�</el-button>
+        <el-button type="primary" plain @click="changeScaleHandle(1)">鏀惧ぇ</el-button>
+        <el-button type="primary" plain @click="changeScaleHandle(-1)">缂╁皬</el-button>
+        <el-button type="primary" plain @click="downloadHandle('blob')">涓嬭浇</el-button>
+      </div>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+        <el-button type="primary" @click="finish" :loading="loading">纭</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "CropperV",
+  props: {
+    isView: {
+      type: Boolean,
+      default: false
+    },
+    imageUrl: {
+      type: String,
+      default: ""
+    }
+  },
+  data() {
+    return {
+      isPreview: false,
+      dialogVisible: false,
+      previewImg: "", // 棰勮鍥剧墖鍦板潃
+      // 瑁佸壀缁勪欢鐨勫熀纭�閰嶇疆option
+      option: {
+        img: "https://pic1.zhimg.com/80/v2-366c0aeae2b4050fa2fcbfc09c74aad4_720w.jpg", // 瑁佸壀鍥剧墖鐨勫湴鍧�
+        info: true, // 瑁佸壀妗嗙殑澶у皬淇℃伅
+        outputSize: 1, // 瑁佸壀鐢熸垚鍥剧墖鐨勮川閲�
+        outputType: "png", // 瑁佸壀鐢熸垚鍥剧墖鐨勬牸寮�
+        canScale: true, // 鍥剧墖鏄惁鍏佽婊氳疆缂╂斁
+        autoCrop: true, // 鏄惁榛樿鐢熸垚鎴浘妗�
+        canMoveBox: true, // 鎴浘妗嗚兘鍚︽嫋鍔�
+        autoCropWidth: 200, // 榛樿鐢熸垚鎴浘妗嗗搴�
+        autoCropHeight: 200, // 榛樿鐢熸垚鎴浘妗嗛珮搴�
+        fixedBox: false, // 鍥哄畾鎴浘妗嗗ぇ灏� 涓嶅厑璁告敼鍙�
+        fixed: true, // 鏄惁寮�鍚埅鍥炬瀹介珮鍥哄畾姣斾緥
+        fixedNumber: [1, 1], // 鎴浘妗嗙殑瀹介珮姣斾緥
+        full: false, // 鏄惁杈撳嚭鍘熷浘姣斾緥鐨勬埅鍥�
+        original: false, // 涓婁紶鍥剧墖鎸夌収鍘熷姣斾緥娓叉煋
+        centerBox: false, // 鎴浘妗嗘槸鍚﹁闄愬埗鍦ㄥ浘鐗囬噷闈�
+        infoTrue: true // true 涓哄睍绀虹湡瀹炶緭鍑哄浘鐗囧楂� false 灞曠ず鐪嬪埌鐨勬埅鍥炬瀹介珮
+      },
+      // 闃叉閲嶅鎻愪氦
+      loading: false
+    }
+  },
+  mounted() {
+    console.log(this.imageUrl)
+    if (!this.isView && this.imageUrl?.length > 0) {
+      this.isPreview = true
+      this.previewImg = this.imageUrl
+    } else {
+      this.isPreview = false
+    }
+  },
+  methods: {
+    // 涓婁紶鎸夐挳 闄愬埗鍥剧墖澶у皬鍜岀被鍨�
+    handleChangeUpload(file, fileList) {
+      const isJPG = file.raw.type === "image/jpeg" || file.raw.type === "image/png"
+      const isLt2M = file.size / 1024 / 1024 < 2
+      if (!isJPG) {
+        this.$message.error("涓婁紶澶村儚鍥剧墖鍙兘鏄� JPG/PNG 鏍煎紡!")
+        return false
+      }
+      if (!isLt2M) {
+        this.$message.error("涓婁紶澶村儚鍥剧墖澶у皬涓嶈兘瓒呰繃 2MB!")
+        return false
+      }
+      console.log(file, fileList)
+      // 涓婁紶鎴愬姛鍚庡皢鍥剧墖鍦板潃璧嬪�肩粰瑁佸壀妗嗘樉绀哄浘鐗�
+      this.$nextTick(async () => {
+        // base64鏂瑰紡
+        // this.option.img = await fileByBase64(file.raw)
+        this.option.img = URL.createObjectURL(file.raw)
+        this.loading = false
+        this.dialogVisible = true
+      })
+    },
+    // 鏀惧ぇ/缂╁皬
+    changeScaleHandle(num) {
+      num = num || 1
+      this.$refs.cropper.changeScale(num)
+    },
+    // 宸︽棆杞�
+    rotateLeftHandle() {
+      this.$refs.cropper.rotateLeft()
+    },
+    // 鍙虫棆杞�
+    rotateRightHandle() {
+      this.$refs.cropper.rotateRight()
+    },
+    // 涓嬭浇
+    downloadHandle(type) {
+      let aLink = document.createElement("a")
+      aLink.download = "author-img"
+      if (type === "blob") {
+        this.$refs.cropper.getCropBlob((data) => {
+          aLink.href = URL.createObjectURL(data)
+          aLink.click()
+        })
+      } else {
+        this.$refs.cropper.getCropData((data) => {
+          aLink.href = data
+          aLink.click()
+        })
+      }
+    },
+    // 娓呯悊鍥剧墖
+    clearImgHandle() {
+      this.option.img = ""
+    },
+    // 鎴浘妗嗙Щ鍔ㄥ洖璋冨嚱鏁�
+    cropMoving(data) {
+      console.log(data)
+      // 鎴浘妗嗙殑宸︿笂瑙� x锛寉鍜屽彸涓嬭鍧愭爣x锛寉
+      // let cropAxis = [data.axis.x1, data.axis.y1, data.axis.x2, data.axis.y2]
+      // console.log(cropAxis)
+    },
+    finish() {
+      // 鑾峰彇鎴浘鐨� blob 鏁版嵁
+      this.$refs.cropper.getCropBlob((blob) => {
+        this.loading = true
+        this.dialogVisible = false
+        this.previewImg = URL.createObjectURL(blob)
+        this.isPreview = true
+        console.log(blob)
+        this.$emit("getImageData", blob)
+      })
+      // 鑾峰彇鎴浘鐨� base64 鏁版嵁
+      // this.$refs.cropper.getCropData(data => {
+      //     console.log(data)
+      // })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.cropper-wrapper {
+  .avatar-uploader .el-upload:hover {
+    border-color: #409eff;
+  }
+  .avatar-uploader-icon {
+    font-size: 28px;
+    color: #8c939d;
+    width: 178px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+  }
+  .avatar {
+    width: 178px;
+    height: 178px;
+    display: block;
+  }
+  .view-image {
+    width: 180px;
+    height: 180px;
+    background: #f5f7fa;
+    font-size: 30px;
+    text-align: center;
+    line-height: 180px;
+  }
+  .image-slot {
+    color: #909399;
+    text-align: center;
+  }
+}
+::v-deep {
+  .el-upload-dragger {
+    width: 180px;
+    height: 180px;
+  }
+}
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+  width: 178px;
+  height: 178px;
+}
+
+.crop-dialog {
+  .cropper-content {
+    padding: 0 40px;
+
+    .cropper {
+      width: auto;
+      height: 350px;
+    }
+  }
+
+  .action-box {
+    padding: 25px 40px 10px;
+    display: flex;
+    justify-content: center;
+
+    button {
+      width: 80px;
+      margin-right: 15px;
+    }
+  }
+}
+</style>

--
Gitblit v1.8.0