|  | @@ -27,20 +27,36 @@
 | 
	
		
			
				|  |  |          />
 | 
	
		
			
				|  |  |        </div>
 | 
	
		
			
				|  |  |        <div
 | 
	
		
			
				|  |  | -        id="selectableArea"
 | 
	
		
			
				|  |  | +        class="background-img"
 | 
	
		
			
				|  |  |          :style="{
 | 
	
		
			
				|  |  |            width: data.image_width + 'px',
 | 
	
		
			
				|  |  |            height: data.image_height + 'px',
 | 
	
		
			
				|  |  | -          background: data.image_list[0]
 | 
	
		
			
				|  |  | -            ? 'url(' + data.image_list[0].file_url + ') center / contain no-repeat'
 | 
	
		
			
				|  |  | -            : '#DCDFE6',
 | 
	
		
			
				|  |  | -          position: 'relative',
 | 
	
		
			
				|  |  |            border: '1px dotted #DCDFE6',
 | 
	
		
			
				|  |  | -          textAlign: 'center',
 | 
	
		
			
				|  |  | -          lineHeight: data.image_height + 'px',
 | 
	
		
			
				|  |  | +          background: data.image_list[0] && file_url ? '' : '#DCDFE6',
 | 
	
		
			
				|  |  |          }"
 | 
	
		
			
				|  |  |        >
 | 
	
		
			
				|  |  | -        {{ data.image_list[0] ? '' : '背景图' }}
 | 
	
		
			
				|  |  | +        <div
 | 
	
		
			
				|  |  | +          v-if="data.image_list[0] && file_url"
 | 
	
		
			
				|  |  | +          class="img-set"
 | 
	
		
			
				|  |  | +          :style="{ top: `${data.imgData.top - 9}px`, left: `${data.imgData.left}px` }"
 | 
	
		
			
				|  |  | +        >
 | 
	
		
			
				|  |  | +          <div class="dot top-left" @mousedown="dragStart($event, 'nwse-resize', 'top-left')"></div>
 | 
	
		
			
				|  |  | +          <div class="horizontal-line" @mousedown="dragStart($event, 'ns-resize', 'top')"></div>
 | 
	
		
			
				|  |  | +          <div class="dot top-right" @mousedown="dragStart($event, 'nesw-resize', 'top-right')"></div>
 | 
	
		
			
				|  |  | +          <div class="vertical-line" @mousedown="dragStart($event, 'ew-resize', 'left')"></div>
 | 
	
		
			
				|  |  | +          <img
 | 
	
		
			
				|  |  | +            :src="file_url"
 | 
	
		
			
				|  |  | +            draggable="false"
 | 
	
		
			
				|  |  | +            alt="背景图"
 | 
	
		
			
				|  |  | +            :style="{ width: `${data.imgData.width}px`, height: `${data.imgData.height}px` }"
 | 
	
		
			
				|  |  | +            @mousedown="dragStart($event, 'move', 'move')"
 | 
	
		
			
				|  |  | +          />
 | 
	
		
			
				|  |  | +          <div class="vertical-line" @mousedown="dragStart($event, 'ew-resize', 'right')"></div>
 | 
	
		
			
				|  |  | +          <div class="dot bottom-left" @mousedown="dragStart($event, 'nesw-resize', 'bottom-left')"></div>
 | 
	
		
			
				|  |  | +          <div class="horizontal-line" @mousedown="dragStart($event, 'ns-resize', 'bottom')"></div>
 | 
	
		
			
				|  |  | +          <div class="dot bottom-right" @mousedown="dragStart($event, 'nwse-resize', 'bottom-right')"></div>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +        <p v-else :style="{ lineHeight: data.image_height + 'px', textAlign: 'center' }">背景图</p>
 | 
	
		
			
				|  |  |        </div>
 | 
	
		
			
				|  |  |      </template>
 | 
	
		
			
				|  |  |    </ModuleBase>
 | 
	
	
		
			
				|  | @@ -63,6 +79,7 @@ export default {
 | 
	
		
			
				|  |  |        labelText: '背景图',
 | 
	
		
			
				|  |  |        acceptFileType: '.jpg,.png,.jpeg',
 | 
	
		
			
				|  |  |        iconClass: 'picture',
 | 
	
		
			
				|  |  | +      file_url: '',
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    watch: {
 | 
	
	
		
			
				|  | @@ -75,18 +92,55 @@ export default {
 | 
	
		
			
				|  |  |        immediate: true,
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  | +  mounted() {
 | 
	
		
			
				|  |  | +    document.querySelector('.background-img').addEventListener('mousemove', this.mouseMove);
 | 
	
		
			
				|  |  | +    document.body.addEventListener('mouseup', this.mouseUp);
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  beforeDestroy() {
 | 
	
		
			
				|  |  | +    document.querySelector('.background-img')?.removeEventListener('mousemove', this.mouseMove);
 | 
	
		
			
				|  |  | +    document.body.removeEventListener('mouseup', this.mouseUp);
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  |    methods: {
 | 
	
		
			
				|  |  |      updateFileList({ file_list, file_id_list, file_info_list }) {
 | 
	
		
			
				|  |  |        this.data.image_list = file_list;
 | 
	
		
			
				|  |  |        this.data.image_id_list = file_id_list;
 | 
	
		
			
				|  |  |        this.data.image_info_list = file_info_list;
 | 
	
		
			
				|  |  |        this.data.file_id_list = file_id_list;
 | 
	
		
			
				|  |  | +      if (file_list.length > 0) {
 | 
	
		
			
				|  |  | +        const img = new Image();
 | 
	
		
			
				|  |  | +        img.src = file_list[0].file_url;
 | 
	
		
			
				|  |  | +        this.file_url = file_list[0].file_url;
 | 
	
		
			
				|  |  | +        img.onload = () => {
 | 
	
		
			
				|  |  | +          const { width, height } = img;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          if (width > this.data.image_width || height > this.data.image_height) {
 | 
	
		
			
				|  |  | +            const wScale = width / this.data.image_width;
 | 
	
		
			
				|  |  | +            const hScale = height / this.data.image_height;
 | 
	
		
			
				|  |  | +            const scale = wScale > hScale ? this.data.image_width / 2 / width : this.data.image_height / 2 / height;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            this.data.imgData = {
 | 
	
		
			
				|  |  | +              width: width * scale,
 | 
	
		
			
				|  |  | +              height: height * scale,
 | 
	
		
			
				|  |  | +              top: 0,
 | 
	
		
			
				|  |  | +              left: 0,
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +          } else {
 | 
	
		
			
				|  |  | +            this.data.imgData = {
 | 
	
		
			
				|  |  | +              width,
 | 
	
		
			
				|  |  | +              height,
 | 
	
		
			
				|  |  | +              top: 0,
 | 
	
		
			
				|  |  | +              left: 0,
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      handleData() {
 | 
	
		
			
				|  |  |        this.data.image_list.forEach((item) => {
 | 
	
		
			
				|  |  |          GetFileURLMap({ file_id_list: [item.file_id] }).then(({ url_map }) => {
 | 
	
		
			
				|  |  | -          this.$set(item, 'file_url', url_map[item.file_id]);
 | 
	
		
			
				|  |  | +          this.file_url = url_map[item.file_id];
 | 
	
		
			
				|  |  | +          // this.$set(item, 'file_url', url_map[item.file_id]);
 | 
	
		
			
				|  |  |          });
 | 
	
		
			
				|  |  |        });
 | 
	
		
			
				|  |  |        this.handleMindMap();
 | 
	
	
		
			
				|  | @@ -102,6 +156,127 @@ export default {
 | 
	
		
			
				|  |  |        });
 | 
	
		
			
				|  |  |        this.data.mind_map.node_list = node_list;
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 拖拽开始
 | 
	
		
			
				|  |  | +     * @param {MouseEvent} event
 | 
	
		
			
				|  |  | +     * @param {string} cursor
 | 
	
		
			
				|  |  | +     * @param {string} type
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    dragStart(event, cursor, type) {
 | 
	
		
			
				|  |  | +      const { clientX, clientY } = event;
 | 
	
		
			
				|  |  | +      this.data.drag = {
 | 
	
		
			
				|  |  | +        dragging: true,
 | 
	
		
			
				|  |  | +        startX: clientX,
 | 
	
		
			
				|  |  | +        startY: clientY,
 | 
	
		
			
				|  |  | +        type,
 | 
	
		
			
				|  |  | +      };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      document.querySelector('.background-img').style.cursor = cursor;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 鼠标移动
 | 
	
		
			
				|  |  | +     * @param {MouseEvent} event
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    mouseMove(event) {
 | 
	
		
			
				|  |  | +      if (!this.data.drag.dragging) return;
 | 
	
		
			
				|  |  | +      const { clientX, clientY } = event;
 | 
	
		
			
				|  |  | +      const { startX, startY, type } = this.data.drag;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      const widthDiff = clientX - startX;
 | 
	
		
			
				|  |  | +      const heightDiff = clientY - startY;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (type === 'top-left') {
 | 
	
		
			
				|  |  | +        this.data.imgData.width = Math.min(this.data.image_width, Math.max(0, this.data.imgData.width - widthDiff));
 | 
	
		
			
				|  |  | +        this.data.imgData.height = Math.min(this.data.image_height, Math.max(0, this.data.imgData.height - heightDiff));
 | 
	
		
			
				|  |  | +        this.data.imgData.top = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_height - this.data.imgData.height,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.top + heightDiff),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        this.data.imgData.left = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_width - this.data.imgData.width,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.left + widthDiff),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +      } else if (type === 'top-right') {
 | 
	
		
			
				|  |  | +        this.data.imgData.width = Math.min(this.data.image_width, Math.max(this.data.imgData.width + widthDiff));
 | 
	
		
			
				|  |  | +        this.data.imgData.height = Math.min(this.data.image_height, Math.max(0, this.data.imgData.height - heightDiff));
 | 
	
		
			
				|  |  | +        this.data.imgData.top = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_height - this.data.imgData.height,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.top + heightDiff),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        this.data.imgData.left = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_width - this.data.imgData.width,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.left),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +      } else if (type === 'bottom-left') {
 | 
	
		
			
				|  |  | +        this.data.imgData.width = Math.min(this.data.image_width, Math.max(0, this.data.imgData.width - widthDiff));
 | 
	
		
			
				|  |  | +        this.data.imgData.height = Math.min(this.data.image_height, Math.max(this.data.imgData.height + heightDiff));
 | 
	
		
			
				|  |  | +        this.data.imgData.top = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_height - this.data.imgData.height,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.top),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        this.data.imgData.left = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_width - this.data.imgData.width,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.left + widthDiff),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +      } else if (type === 'bottom-right') {
 | 
	
		
			
				|  |  | +        this.data.imgData.width = Math.min(this.data.image_width, Math.max(this.data.imgData.width + widthDiff));
 | 
	
		
			
				|  |  | +        this.data.imgData.height = Math.min(this.data.image_height, Math.max(this.data.imgData.height + heightDiff));
 | 
	
		
			
				|  |  | +        this.data.imgData.top = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_height - this.data.imgData.height,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.top),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        this.data.imgData.left = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_width - this.data.imgData.width,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.left),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (type === 'top') {
 | 
	
		
			
				|  |  | +        this.data.imgData.height = Math.min(this.data.image_height, Math.max(0, this.data.imgData.height - heightDiff));
 | 
	
		
			
				|  |  | +        this.data.imgData.top = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_height - this.data.imgData.height,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.top + heightDiff),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +      } else if (type === 'bottom') {
 | 
	
		
			
				|  |  | +        this.data.imgData.height = Math.min(this.data.image_height, Math.max(this.data.imgData.height + heightDiff));
 | 
	
		
			
				|  |  | +        this.data.imgData.top = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_height - this.data.imgData.height,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.top),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +      } else if (type === 'left') {
 | 
	
		
			
				|  |  | +        this.data.imgData.width = Math.min(this.data.image_width, Math.max(this.data.imgData.width - widthDiff));
 | 
	
		
			
				|  |  | +        this.data.imgData.left = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_width - this.data.imgData.width,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.left + widthDiff),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +      } else if (type === 'right') {
 | 
	
		
			
				|  |  | +        this.data.imgData.width = Math.min(this.data.image_width, Math.max(this.data.imgData.width + widthDiff));
 | 
	
		
			
				|  |  | +        this.data.imgData.left = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_width - this.data.imgData.width,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.left),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (type === 'move') {
 | 
	
		
			
				|  |  | +        this.data.imgData.top = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_height - this.data.imgData.height,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.top + heightDiff),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        this.data.imgData.left = Math.min(
 | 
	
		
			
				|  |  | +          this.data.image_width - this.data.imgData.width,
 | 
	
		
			
				|  |  | +          Math.max(0, this.data.imgData.left + widthDiff),
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      this.data.drag.startX = clientX;
 | 
	
		
			
				|  |  | +      this.data.drag.startY = clientY;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 鼠标抬起
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    mouseUp() {
 | 
	
		
			
				|  |  | +      this.data.drag.dragging = false;
 | 
	
		
			
				|  |  | +      document.querySelector('.background-img').style.cursor = 'auto';
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  </script>
 | 
	
	
		
			
				|  | @@ -141,4 +316,79 @@ export default {
 | 
	
		
			
				|  |  |    align-items: center;
 | 
	
		
			
				|  |  |    padding: 20px 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +.background-img {
 | 
	
		
			
				|  |  | +  height: 310px;
 | 
	
		
			
				|  |  | +  border: 1px dashed rgba(0, 0, 0, 8%);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  .img-set {
 | 
	
		
			
				|  |  | +    position: relative;
 | 
	
		
			
				|  |  | +    display: inline-grid;
 | 
	
		
			
				|  |  | +    grid-template:
 | 
	
		
			
				|  |  | +      ' . . . ' 2px
 | 
	
		
			
				|  |  | +      ' . img . ' auto
 | 
	
		
			
				|  |  | +      ' . . . ' 2px
 | 
	
		
			
				|  |  | +      / 2px auto 2px;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    img {
 | 
	
		
			
				|  |  | +      object-fit: cover;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .horizontal-line,
 | 
	
		
			
				|  |  | +    .vertical-line {
 | 
	
		
			
				|  |  | +      background-color: $main-color;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .horizontal-line {
 | 
	
		
			
				|  |  | +      width: 100%;
 | 
	
		
			
				|  |  | +      height: 2px;
 | 
	
		
			
				|  |  | +      cursor: ns-resize;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .vertical-line {
 | 
	
		
			
				|  |  | +      width: 2px;
 | 
	
		
			
				|  |  | +      height: 100%;
 | 
	
		
			
				|  |  | +      cursor: ew-resize;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    .dot {
 | 
	
		
			
				|  |  | +      z-index: 1;
 | 
	
		
			
				|  |  | +      width: 6px;
 | 
	
		
			
				|  |  | +      height: 6px;
 | 
	
		
			
				|  |  | +      background-color: $main-color;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &.top-left {
 | 
	
		
			
				|  |  | +        top: -2px;
 | 
	
		
			
				|  |  | +        left: -2px;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &.top-right {
 | 
	
		
			
				|  |  | +        top: -2px;
 | 
	
		
			
				|  |  | +        right: 2px;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &.bottom-left {
 | 
	
		
			
				|  |  | +        bottom: 2px;
 | 
	
		
			
				|  |  | +        left: -2px;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &.bottom-right {
 | 
	
		
			
				|  |  | +        right: 2px;
 | 
	
		
			
				|  |  | +        bottom: 2px;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &.top-left,
 | 
	
		
			
				|  |  | +      &.bottom-right {
 | 
	
		
			
				|  |  | +        position: relative;
 | 
	
		
			
				|  |  | +        cursor: nwse-resize;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      &.top-right,
 | 
	
		
			
				|  |  | +      &.bottom-left {
 | 
	
		
			
				|  |  | +        position: relative;
 | 
	
		
			
				|  |  | +        cursor: nesw-resize;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  </style>
 |