|
|
@@ -0,0 +1,215 @@
|
|
|
+<template>
|
|
|
+ <el-dialog
|
|
|
+ title=""
|
|
|
+ :model-value="showDialog"
|
|
|
+ @update:model-value="showDialog = $event"
|
|
|
+ class="preview_dialog"
|
|
|
+ :modal-append-to-body="false"
|
|
|
+ append-to-body
|
|
|
+ fullscreen
|
|
|
+ height="100%"
|
|
|
+ >
|
|
|
+ <div class="preview_image">
|
|
|
+ <img
|
|
|
+ :src="currenImageUrl"
|
|
|
+ alt=""
|
|
|
+ :style="{ transform: `scale(${zoomLevel}) rotate(${rotateAngle}deg)` }"
|
|
|
+ />
|
|
|
+
|
|
|
+ <div class="preview_close" @click="CloseDialog()">
|
|
|
+ <el-icon><Close /></el-icon>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="preview_last"
|
|
|
+ :class="currentIndex==0?'button_diasble':''"
|
|
|
+ v-if="imageList.length>1"
|
|
|
+ @click="LastImage()"
|
|
|
+ >
|
|
|
+ <el-icon><ArrowLeft /></el-icon>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="preview_next"
|
|
|
+ :class="currentIndex==imageList.length-1?'button_diasble':''"
|
|
|
+ v-if="imageList.length>1"
|
|
|
+ @click="NextImage()"
|
|
|
+ >
|
|
|
+ <el-icon><ArrowRight /></el-icon>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import { ref, watch, computed } from 'vue';
|
|
|
+
|
|
|
+
|
|
|
+interface ImageItem {
|
|
|
+ url: string;
|
|
|
+ rotateAngle?: number;
|
|
|
+ pageNo?: number;
|
|
|
+}
|
|
|
+
|
|
|
+interface Props {
|
|
|
+ modelValue: boolean;
|
|
|
+ imageList: ImageItem[];
|
|
|
+ index?: number;
|
|
|
+ showTool?: boolean;
|
|
|
+}
|
|
|
+
|
|
|
+interface Emits {
|
|
|
+ (e: 'update:modelValue', value: boolean): void;
|
|
|
+ (e: 'GetRotateAngle', data: { currentIndex: number; rotateAngle: number }): void;
|
|
|
+}
|
|
|
+
|
|
|
+const props = withDefaults(defineProps<Props>(), {
|
|
|
+ imageList: () => [],
|
|
|
+ index: 0,
|
|
|
+ showTool: false,
|
|
|
+});
|
|
|
+
|
|
|
+const emit = defineEmits<Emits>();
|
|
|
+
|
|
|
+const currenImageUrl = ref('');
|
|
|
+const currentIndex = ref(0);
|
|
|
+const zoomLevel = ref(1);
|
|
|
+const maxZoom = ref(3);
|
|
|
+const minZoom = ref(0.5);
|
|
|
+const zoomStep = ref(0.1);
|
|
|
+const rotateAngle = ref(0);
|
|
|
+
|
|
|
+const toolList = [
|
|
|
+ {
|
|
|
+ title: '放大',
|
|
|
+ icon: 'icon_fangda',
|
|
|
+ value: '1',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '缩小',
|
|
|
+ icon: 'icon_suoxiao',
|
|
|
+ value: '2',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '逆时针90°',
|
|
|
+ icon: 'icon_nishizhen90',
|
|
|
+ value: '5',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '顺时针90°',
|
|
|
+ icon: 'icon_shunshizhen90',
|
|
|
+ value: '6',
|
|
|
+ },
|
|
|
+];
|
|
|
+
|
|
|
+const showDialog = computed({
|
|
|
+ get() {
|
|
|
+ return props.modelValue;
|
|
|
+ },
|
|
|
+ set(val) {
|
|
|
+ emit('update:modelValue', val);
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => props.modelValue,
|
|
|
+ (newVal) => {
|
|
|
+ if (newVal && props.imageList.length > 0) {
|
|
|
+ const targetIndex = props.index || 0;
|
|
|
+ currenImageUrl.value = props.imageList[targetIndex].url;
|
|
|
+ rotateAngle.value = props.imageList[targetIndex].rotateAngle || 0;
|
|
|
+ currentIndex.value = targetIndex;
|
|
|
+ }
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+const CloseDialog = () => {
|
|
|
+ showDialog.value = false;
|
|
|
+ let obj = {
|
|
|
+ currentIndex: currentIndex.value,
|
|
|
+ rotateAngle: rotateAngle.value,
|
|
|
+ };
|
|
|
+ emit('GetRotateAngle', obj);
|
|
|
+};
|
|
|
+
|
|
|
+const GetReturn = () => {
|
|
|
+ let obj = {
|
|
|
+ currentIndex: currentIndex.value,
|
|
|
+ rotateAngle: rotateAngle.value,
|
|
|
+ };
|
|
|
+ emit('GetRotateAngle', obj);
|
|
|
+};
|
|
|
+
|
|
|
+const LastImage = () => {
|
|
|
+ if (currentIndex.value > 0) {
|
|
|
+ currentIndex.value--;
|
|
|
+ }
|
|
|
+ currenImageUrl.value = props.imageList[currentIndex.value].url;
|
|
|
+ rotateAngle.value = props.imageList[currentIndex.value].rotateAngle || 0;
|
|
|
+};
|
|
|
+
|
|
|
+const NextImage = () => {
|
|
|
+ if (currentIndex.value < props.imageList.length - 1) {
|
|
|
+ currentIndex.value++;
|
|
|
+ }
|
|
|
+ currenImageUrl.value = props.imageList[currentIndex.value].url;
|
|
|
+ rotateAngle.value = props.imageList[currentIndex.value].rotateAngle || 0;
|
|
|
+};
|
|
|
+
|
|
|
+const ToolClick = (item: any) => {
|
|
|
+ if (item.value === '1') {
|
|
|
+ ZoomIn();
|
|
|
+ }
|
|
|
+ if (item.value === '2') {
|
|
|
+ ZoomOut();
|
|
|
+ }
|
|
|
+ if (item.value === '5') {
|
|
|
+ RotateCounterClockwise90();
|
|
|
+ }
|
|
|
+ if (item.value === '6') {
|
|
|
+ RotateClockwise90();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const ZoomIn = () => {
|
|
|
+ if (zoomLevel.value < maxZoom.value) {
|
|
|
+ zoomLevel.value += zoomStep.value;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const ZoomOut = () => {
|
|
|
+ if (zoomLevel.value > minZoom.value) {
|
|
|
+ zoomLevel.value -= zoomStep.value;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const RotateCounterClockwise90 = () => {
|
|
|
+ rotateAngle.value -= 90;
|
|
|
+ GetReturn();
|
|
|
+};
|
|
|
+
|
|
|
+const RotateClockwise90 = () => {
|
|
|
+ rotateAngle.value += 90;
|
|
|
+ GetReturn();
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.preview_canvas {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ .main_container {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ position: relative;
|
|
|
+ background: transparent;
|
|
|
+ user-select: none;
|
|
|
+ overflow: hidden;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .paper_template {
|
|
|
+ position: absolute;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|