Эх сурвалжийг харах

fix: 附件预览可拖拽缩放

liuc 4 сар өмнө
parent
commit
9bbd79a410

+ 1 - 0
package.json

@@ -70,6 +70,7 @@
     "vcolorpicker": "^2.0.12",
     "vue": "3.4.27",
     "vue-codemirror-lite": "^1.0.4",
+    "vue-draggable-resizable": "^3.0.0",
     "vue-i18n": "9.13.1",
     "vue-plugin-hiprint": "^0.0.60",
     "vue-quill-editor": "^3.0.6",

+ 10 - 10
src/views/flow/stFormDesign/packages/StFormDesign/module/formItemProperties.vue

@@ -257,11 +257,11 @@
           <StChangeOption v-model:value='selectItem.columns' type='colspan'/>
         </a-form-item>
 
-        <a-form-item v-if="selectItem.type === 'switch'" label='默认值'>
+        <a-form-item v-if="selectItem.type === 'switch'&& isInBatchTable" label='默认值'>
           <a-switch v-model:value='options.defaultValue'/>
         </a-form-item>
         <a-form-item
-            v-if="['number', 'slider'].indexOf(selectItem.type) >= 0"
+            v-if="['number', 'slider'].indexOf(selectItem.type) >= 0&& isInBatchTable"
             label='默认值'
         >
           <a-input-number
@@ -271,7 +271,7 @@
               v-model:value='options.defaultValue'
           />
         </a-form-item>
-        <a-form-item v-if="selectItem.type === 'rate'" label='默认值'>
+        <a-form-item v-if="selectItem.type === 'rate'&& isInBatchTable" label='默认值'>
           <a-rate
               v-model:value='options.defaultValue'
               :allowHalf='options.allowHalf'
@@ -279,20 +279,20 @@
           />
         </a-form-item>
 
-        <a-form-item v-if="selectItem.type === 'radio'" label='默认值'>
+        <a-form-item v-if="selectItem.type === 'radio'&& isInBatchTable" label='默认值'>
           <a-radio-group
               :options='options.options'
               v-model:value='options.defaultValue'
           />
         </a-form-item>
-        <a-form-item v-if="selectItem.type === 'checkbox'" label='默认值'>
+        <a-form-item v-if="selectItem.type === 'checkbox'&& isInBatchTable" label='默认值'>
           <a-checkbox-group
               :options='options.options'
               v-model:value='options.defaultValue'
           />
         </a-form-item>
         <!-- 日期选择器默认值 start -->
-        <a-form-item v-if="selectItem.type === 'date'" label='默认值'>
+        <a-form-item v-if="selectItem.type === 'date'&& isInBatchTable" label='默认值'>
           <a-input
               v-if='!options.range'
               v-model:value='options.defaultValue'
@@ -329,7 +329,7 @@
               'slider',
               'html'
             ].includes(selectItem.type) &&
-              typeof options.defaultValue !== 'undefined'
+              typeof options.defaultValue !== 'undefined' && isInBatchTable
           "
             label='默认值'
         >
@@ -838,10 +838,10 @@ export default {
       this.selectItem.label = label[0]
       const target = this.findObjectByCode(this.fieldData, code)
       if (target) {
-        if (this.selectItem.options  && target.type === "MULTI") {
+        if (this.selectItem.options && target.type === "MULTI") {
           this.selectItem.options.multiple = true
         }
-        if (this.selectItem.options  && target.type !== "MULTI") {
+        if (this.selectItem.options && target.type !== "MULTI") {
           this.selectItem.options.multiple = false
         }
       }
@@ -939,7 +939,7 @@ export default {
         this.selectField = this.filterByType(clonedData, types);
       } else if (newVal == "cascader") {
         //级联选择
-        const types = [ 'MULTI'];
+        const types = ['MULTI'];
         this.selectField = this.filterByType(clonedData, types);
       } else if (newVal == "batch") {
         //子表

+ 224 - 19
src/views/flow/stFormDesign/packages/UploadFile/uploadFile.vue

@@ -19,7 +19,7 @@
           <a :style="file.status === 'error' ? 'color: red' : ''" @click="handlePreview(file)">{{ file.name }}</a>
           <a-space style="margin-right: 10px">
             <span style="color:#1677ff" v-show="file.originFileObj=='[object File]'">
-            上传进度:{{file.percent.toFixed(2)}}%
+            上传进度:{{ file.percent.toFixed(2) }}%
             </span>
             <a style="font-size:16px;margin-right: 10px" href="javascript:;" @click="handlePreview(file)">
               <EyeOutlined/>
@@ -37,21 +37,44 @@
       </template>
     </a-upload-dragger>
     <!-- 预览弹框 -->
-    <a-modal
-        v-model:open="previewVisible"
-        title="附件预览"
-        :footer="null"
-        :width="'100vw'"
-        wrap-class-name="fullscreen-modal"
-        :style="{ top: '0', left: '0' }"
-        :bodyStyle="{
-        height: 'calc(100vh - 95px)',
-        padding: '0',
-        overflow: 'auto',
-      }"
+    <vue-draggable-resizable
+        v-show="previewVisible"
+        :x="x1"
+        :y="y1"
+        :w="width"
+        :h="height"
+        class="popup-resize"
+        :resizable="true"
+        :draggable="draggableResize"
+        @resizing="handleResizing"
+        @dragging="onDragging"
+        :active="previewActive"
+        :min-width="300"
+        :min-height="100"
     >
-      <iframe :src="previewUrl" width="100%" height="100%" frameborder="0"></iframe>
-    </a-modal>
+      <div class="draggable-title">
+        <span class="preview-left">附件预览</span>
+        <span class="preview-title">{{ fileName }}</span>
+      </div>
+      <div class="draggable-content">
+        <iframe v-show="iframeShow" :src="previewUrl" width="100%" height="100%" frameborder="0"></iframe>
+        <div v-show="!iframeShow" class="overlay">
+          <a-divider class="horizontal" dashed>宽: {{ width }}</a-divider>
+          <a-divider class="vertical" type="vertical" dashed>高: {{ height }}</a-divider>
+        </div>
+      </div>
+      <div class="control-buttons">
+        <a-button v-show="!maxed" class="control-button" @click="maximize">
+          <ExpandOutlined/> <!-- 最大化图标 -->
+        </a-button>
+        <a-button v-show="maxed" class="control-button" @click="restore">
+          <ShrinkOutlined/> <!-- 返回图标 -->
+        </a-button>
+        <a-button class="control-button" @click="closeDrag">
+          <CloseOutlined/> <!-- 关闭图标 -->
+        </a-button>
+      </div>
+    </vue-draggable-resizable>
 
     <a-drawer
         title="附件预览"
@@ -81,11 +104,16 @@ import {useUserStore} from '/@/store/modules/system/user.js';
 import dayjs from 'dayjs';
 import {Base64} from 'js-base64';
 import {message, Modal} from 'ant-design-vue';
+import VueDraggableResizable from 'vue-draggable-resizable'
+import "vue-draggable-resizable/style.css";
 
 const fileUrl = import.meta.env.VITE_APP_API_FILE_VIEW_URL;
 export default {
   name: 'StUploadFile',
   props: ['record', 'value', 'config', 'parentDisabled', 'dynamicData'],
+  components: {
+    VueDraggableResizable
+  },
   data() {
     return {
       fileList: [],
@@ -94,8 +122,31 @@ export default {
       previewVisible: false, // 控制弹框显示
       previewVisibleMobile: false,
       previewUrl: '', // 预览的 URL
+      x1: 100,
+      y1: 10,
+      x2: 100,
+      y2: 10,
+      width: 0,
+      height: 0,
+      lastWidth: 0,
+      lastHeight: 0,
+      maxed: false,
+      scaleFactor: 1.1,
+      iframeShow: true,
+      previewActive: false,
+      fileName: '',
+      draggableResize: true,
     };
   },
+  mounted() {
+    this.width = window.innerWidth - 200
+    this.height = window.innerHeight - 90
+    document.addEventListener('mouseup', this.handleGlobalMouseUp);
+  },
+  beforeDestroy() {
+    // 在组件销毁时移除全局 mouseup 事件
+    document.removeEventListener('mouseup', this.handleGlobalMouseUp);
+  },
   watch: {
     value: {
       // value 需要深度监听及默认先执行handler函数
@@ -132,6 +183,23 @@ export default {
         this.fileList = this.value;
       }
     },
+    // 调整大小过程中持续触发
+    handleResizing(x, y, width, height) {
+      this.x1 = x
+      this.y1 = y
+      this.width = width
+      this.height = height
+      this.iframeShow = false
+      this.maxed = false
+    },
+    onDragging(x, y) {
+      this.x1 = x
+      this.y1 = y
+      this.maxed = false
+    },
+    handleGlobalMouseUp() {
+      this.iframeShow = true
+    },
     handleSelectChange() {
       setTimeout(() => {
         this.$emit('update:value', this.fileList); //主表,直接更新value
@@ -159,7 +227,9 @@ export default {
         this.previewVisibleMobile = true;
       } else {
         this.previewUrl = viewFile;
+        this.fileName = file.name
         this.previewVisible = true; // 显示弹框
+        this.previewActive = true;
       }
     },
     handleRemove(file) {
@@ -186,13 +256,33 @@ export default {
         this.$message.error(`文件上传失败`);
       }
     },
+    closeDrag() {
+      this.previewVisible = false
+    },
+    maximize() {
+      this.maxed = true
+      this.lastWidth = this.width
+      this.lastHeight = this.height
+      this.x2 = this.x1
+      this.y2 = this.y1
+      this.width = window.innerWidth
+      this.height = window.innerHeight
+      this.x1 = 0
+      this.y1 = 0
+      this.draggableResize=false
+    },
+    restore() {
+      this.width = this.lastWidth
+      this.height = this.lastHeight
+      this.x1 = this.x2
+      this.y1 = this.y2
+      this.maxed = false
+      this.draggableResize=true
+    }
   },
 };
 </script>
-<style scoped>
-/* .ant-upload.ant-upload-btn {
-} */
-
+<style scoped lang="scss">
 .fullscreen-modal {
   width: 100vw !important;
   height: 100vh !important;
@@ -215,4 +305,119 @@ export default {
   padding: 0px 0px 0px 0;
   background-color: #dde5f6;
 }
+
+:deep(.vdr) {
+  z-index: 10000 !important;
+  position: fixed;
+  left: 0;
+  top: 0;
+}
+
+.drag_btn {
+  background: #fff;
+  display: flex;
+  justify-content: center;
+
+  button {
+    font-size: 20px;
+    width: 70px;
+  }
+}
+
+.control-buttons {
+  background-color: #ffffff;
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+  position: absolute;
+  right: 8px;
+  top: 2px;
+  z-index: 100;
+}
+
+.control-button {
+  font-size: 16px;
+  margin-left: 8px; /* 按钮之间的间距 */
+  background: none;
+  border: none;
+  cursor: pointer;
+}
+
+.draggable-title {
+  display: flex;
+  justify-content: space-between; /* 子元素之间的间距均匀分布 */
+  align-items: center; /* 垂直居中 */
+  padding: 8px;
+  cursor: move;
+  background-color: #ffffff;
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  z-index: 10;
+}
+
+.preview-left {
+  margin-left: 20px;
+  color: rgba(0, 0, 0, 0.88);
+  font-weight: 600;
+  font-size: 16px;
+  line-height: 1.5;
+}
+
+.preview-title {
+  margin: 0 auto;
+  color: rgba(0, 0, 0, 0.88);
+  font-weight: 600;
+  font-size: 16px;
+  line-height: 1.5;
+}
+
+.draggable-content {
+  width: 100%;
+  height: 100%;
+  padding: 36px 22px 22px 22px;
+  cursor: move;
+}
+
+.popup-resize {
+  background-color: #ffffff;
+  border: 1px dashed #ffffff; /* 虚线边框,蓝色 */
+  border-radius: 8px; /* 圆角边框 */
+  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 添加阴影 */
+}
+
+.overlay {
+  position: absolute;
+  top: 60px;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  pointer-events: none; /* 防止鼠标事件干扰 iframe */
+}
+
+.horizontal {
+  height: 1px;
+  width: 100%;
+  border-color: #7cb305;
+  font-size: 18px;
+  font-weight: 600;
+  borderWidth: 2px;
+  color: #0D366F;
+}
+
+.vertical {
+  display: inline-flex !important;
+  align-items: center !important;
+  font-size: 18px;
+  font-weight: 600;
+  borderWidth: 2px;
+  color: #0D366F;
+  height: 100%;
+  border-color: #7cb305;
+  top: -92px;
+  z-index: 12;
+  margin-left: 70px;
+}
+
 </style>