Sfoglia il codice sorgente

附件查看新地弹窗功能 2023-11-23

caojunjie 1 anno fa
parent
commit
9903b1e2fb
2 ha cambiato i file con 294 aggiunte e 23 eliminazioni
  1. 249 0
      src/components/PreviewImage/index.vue
  2. 45 23
      src/components/upload/index.vue

+ 249 - 0
src/components/PreviewImage/index.vue

@@ -0,0 +1,249 @@
+<template>
+    <!--<transition name="zoom">-->
+        <div v-if="show" class="previewImage_wrapper" @wheel="handleScroll">
+            <div class="previewImage_image">
+                <img ref="previewImage_img" :src="previewImgList[currentIndex] || ''">
+            </div>
+            <div class="previewImage_close previewImage_btn" @click="closePreviewImage">&times;</div>
+            <!--左右切换箭头-->
+            <!--<div class="previewImage_navigation">-->
+            <!--    <span class="previewImage_navigation_left previewImage_btn" @click="prevImage">&lt;</span>-->
+            <!--    <span class="previewImage_navigation_right previewImage_btn" @click="nextImage">&gt;</span>-->
+            <!--</div>-->
+            <div class="previewImage_toolbar">
+                <span class="previewImage_btn" @click="shrinkHandle">-</span>
+                <span class="previewImage_btn" @click="largeHandle">+</span>
+                <span class="previewImage_btn" @click="turnLeftHandle">↺</span>
+                <span class="previewImage_btn" @click="initImgHandle">▣</span>
+                <span class="previewImage_btn" @click="turnRightHandle">↻</span>
+            </div>
+        </div>
+    <!--</transition>-->
+</template>
+<script>
+// import transition from '@/components/PreviewImage/transition.vue'
+export default {
+    // components:{transition},
+    props: {
+        visible: { // 显示控制
+            type: Boolean,
+            default: false
+        },
+        previewImgList: { // url数组
+            type: Array,
+            default: () => []
+        },
+        currentIndex: { // 当前图片索引
+            type: Number,
+            default: 0
+        }
+    },
+    data() {
+        return {
+            imgHandle: { // 图片控制
+                scale: 1,
+                rotate: 0
+            }
+        }
+    },
+    computed: {
+        // 双向绑定
+        show: {
+            get() {
+                return this.visible
+            },
+            set(newVal) {
+                this.$emit('update:visible', newVal)
+            }
+        }
+    },
+    watch: {
+        visible: { // 给body动态增加style属性,禁止背景内容的鼠标滚轮滚动
+            handler(newVal) {
+                if(newVal) {
+                    document.body.style.overflow = "hidden";
+                    this.initImgHandle() // 每次打开图片初始化
+                } else {
+                    document.body.style.overflow = "";
+                }
+            }
+        },
+    },
+    methods: {
+        // 鼠标滚轮
+        handleScroll(event) {
+            if (event.deltaY > 0) {
+                // 向下滚动事件
+                // console.log('向下滚动');
+                this.shrinkHandle()
+            } else {
+                // 向上滚动事件
+                // console.log('向上滚动');
+                this.largeHandle()
+            }
+        },
+        // 向左翻转
+        async turnLeftHandle() {
+            this.imgHandle.rotate = this.imgHandle.rotate - 90
+            await this.$nextTick()
+            const element = this.$refs.previewImage_img
+            element.style.transform = `scale(${this.imgHandle.scale}) rotate(${this.imgHandle.rotate}deg)`
+        },
+        // 向右翻转
+        async turnRightHandle() {
+            this.imgHandle.rotate = this.imgHandle.rotate + 90
+            await this.$nextTick()
+            const element = this.$refs.previewImage_img
+            element.style.transform = `scale(${this.imgHandle.scale}) rotate(${this.imgHandle.rotate}deg)`
+        },
+        // 初始化还原图片缩放旋转控制
+        async initImgHandle() {
+            this.imgHandle = {
+                scale: 1,
+                rotate: 0
+            }
+            await this.$nextTick()
+            const element = this.$refs.previewImage_img
+            element.style.transform = `scale(${this.imgHandle.scale}) rotate(${this.imgHandle.rotate}deg)`
+        },
+        // 放大图片
+        async largeHandle() {
+            console.log(this.imgHandle.scale, 'scale')
+            this.imgHandle.scale = Number((this.imgHandle.scale + 0.2).toFixed(2)) // 使用toFixed防止小数点精度不准
+            const element = this.$refs.previewImage_img
+            element.style.transform = `scale(${this.imgHandle.scale}) rotate(${this.imgHandle.rotate}deg)`
+        },
+        // 缩小图片
+        async shrinkHandle() {
+            console.log(this.imgHandle.scale, 'scale')
+            if (this.imgHandle.scale === 0.2) { // 最低缩放到0.2倍
+                return
+            }
+            this.imgHandle.scale = Number((this.imgHandle.scale - 0.2).toFixed(2)) // 使用toFixed防止小数点精度不准
+            const element = this.$refs.previewImage_img
+            element.style.transform = `scale(${this.imgHandle.scale}) rotate(${this.imgHandle.rotate}deg)`
+        },
+        // 上一张图片
+        prevImage() {
+            if (this.currentIndex === 0) {
+                this.currentIndex = this.previewImgList.length - 1
+            } else {
+                this.currentIndex--
+            }
+            this.initImgHandle()
+        },
+        // 下一张图片
+        nextImage() {
+            if (this.currentIndex === this.previewImgList.length - 1) {
+                this.currentIndex = 0
+            } else {
+                this.currentIndex++
+            }
+            this.initImgHandle()
+        },
+        // 关闭预览图片组件
+        closePreviewImage() {
+            this.show = false
+        }
+    },
+    mounted() { // 插入body
+        document.body.appendChild(this.$el);
+    },
+    destroyed() { // 组件销毁后同步清除元素
+        this.$el.parentNode.removeChild(this.$el);
+    }
+}
+</script>
+<style lang="scss" scoped>
+.previewImage_wrapper{
+    position: fixed;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+    background: rgba(0, 0, 0, .5);
+    z-index: 9999;
+    .previewImage_image{
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        img {
+            width: 100vw;
+            height: 100vh;
+            object-fit: scale-down;
+            transition: transform 0.3s ease;
+        }
+    }
+    .previewImage_close{
+        position: absolute;
+        right: 20px;
+        top: 20px;
+        transition: transform 0.2s ease-out;
+        &:hover{
+            transform: scale(1.2);
+        }
+    }
+    .previewImage_navigation{
+        &_left{
+            position: absolute;
+            left: 15px;
+            top: 50%;
+            transform: translate(0, -50%);
+            transition: transform 0.2s ease-out;
+        }
+        &_right{
+            position: absolute;
+            right: 15px;
+            top: 50%;
+            transform: translate(0, -50%);
+            transition: transform 0.2s ease-out;
+        }
+        &_left:hover,&_right:hover{
+            transform: translate(0, -50%) scale(1.2);
+        }
+    }
+    .previewImage_toolbar{
+        position: absolute;
+        bottom: 10px;
+        left: 50%;
+        transform: translate(-50%, 0);
+        display: flex;
+        align-items: center;
+        span{
+            margin-right: 10px;
+            transition: transform 0.2s ease-out;
+            &:hover{
+                transform: scale(1.1) ;
+            }
+        }
+        span:last-child{
+            margin-right: 0;
+        }
+    }
+    .previewImage_btn{
+        width: 50px;
+        height: 50px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        font-size: 24px;
+        color: #fff;
+        background-color: #606266;
+        border-radius: 50%;
+        cursor: pointer;
+    }
+}
+.zoom-enter, .zoom-leave-to {
+    transform: scale(0);
+}
+.zoom-enter-active, .zoom-leave-active {
+    transition: transform 0.3s;
+}
+
+.slide-enter, .slide-leave-to {
+    transform: translateX(100%);
+}
+.slide-enter-active, .slide-leave-active {
+    transition: transform 0.3s ease-in-out;
+}
+</style>

+ 45 - 23
src/components/upload/index.vue

@@ -111,17 +111,25 @@
           </div>
         </el-upload>
       </el-dialog>
-      <el-dialog
-          width="80%"
-          title="附件"
-          :visible.sync="innerVisible"
-          :close-on-click-modal="false"
-          append-to-body
-      >
-        <div style="width: 50%;height: 50%;margin: 0 auto">
-          <img :src="imgUrl" alt="" style="width: 100%;height: 100%;" />
-        </div>
-      </el-dialog>
+        <!--之前的查看图片弹窗-->
+      <!--<el-dialog-->
+      <!--    width="80%"-->
+      <!--    title="附件"-->
+      <!--    :visible.sync="innerVisible"-->
+      <!--    :close-on-click-modal="false"-->
+      <!--    append-to-body-->
+      <!--&gt;-->
+      <!--  <div style="width: 50%;height: 50%;margin: 0 auto">-->
+      <!--    <img :src="imgUrl" alt="" style="width: 100%;height: 100%;" />-->
+      <!--  </div>-->
+      <!--</el-dialog>-->
+
+        <!--  新的查看图片弹窗-->
+        <PreviewImage
+            :visible.sync="innerVisible"
+            :currentIndex="0"
+            :previewImgList="[imgUrl]"
+        />
     </basic-container>
     <span v-else-if="true">
       <avue-crud
@@ -232,17 +240,25 @@
           </div>
         </el-upload>
       </el-dialog>
-      <el-dialog
-          width="80%"
-          title="附件"
-          :visible.sync="innerVisible"
-          :close-on-click-modal="false"
-          append-to-body
-      >
-        <div style="width: 50%;height: 50%;margin: 0 auto">
-          <img :src="imgUrl" alt="" style="width: 100%;height: 100%;" />
-        </div>
-      </el-dialog>
+        <!--之前的查看图片弹窗-->
+      <!--<el-dialog-->
+      <!--    width="80%"-->
+      <!--    title="附件"-->
+      <!--    :visible.sync="innerVisible"-->
+      <!--    :close-on-click-modal="false"-->
+      <!--    append-to-body-->
+      <!--&gt;-->
+      <!--  <div style="width: 50%;height: 50%;margin: 0 auto">-->
+      <!--    <img :src="imgUrl" alt="" style="width: 100%;height: 100%;" />-->
+      <!--  </div>-->
+      <!--</el-dialog>-->
+
+      <!--  新的查看图片弹窗-->
+        <PreviewImage
+            :visible.sync="innerVisible"
+            :currentIndex="0"
+            :previewImgList="[imgUrl]"
+        />
     </span>
   </div>
 </template>
@@ -254,8 +270,10 @@ import option from "@/views/exportTrade/customerInquiry/config/mainList.json";
 import { gainUser } from "@/api/basicData/customerInquiry";
 import { updateListRemove } from "@/api/uploadFile/upload-file";
 import {deleteImg} from "../../api/basicData/EquipmentArchives";
+import PreviewImage from '@/components/PreviewImage/index.vue'
 export default {
   name: "index",
+    components:{PreviewImage},
   props: {
     data: {
       type: Object
@@ -604,9 +622,13 @@ export default {
             scope.row.url.substring(scope.row.url.lastIndexOf(".")) ===
             ".png" ||
             scope.row.url.substring(scope.row.url.lastIndexOf(".")) ===
+            ".jpeg" ||
+            scope.row.url.substring(scope.row.url.lastIndexOf(".")) ===
             ".JPG" ||
             scope.row.url.substring(scope.row.url.lastIndexOf(".")) ===
-            ".PNG"
+            ".PNG" ||
+            scope.row.url.substring(scope.row.url.lastIndexOf(".")) ===
+            ".JPEG"
         ) {
           this.imgUrl = scope.row.url;
           this.innerVisible = true;