소스 검색

feat: 复核检查快捷盘和图片展示

zhangjie 9 달 전
부모
커밋
106cda17d6
4개의 변경된 파일149개의 추가작업 그리고 14개의 파일을 삭제
  1. 23 1
      src/render/styles/pages.less
  2. 21 9
      src/render/views/Review/ReviewImage.vue
  3. 102 2
      src/render/views/Review/ReviewMarkPan.vue
  4. 3 2
      src/render/views/Review/index.vue

+ 23 - 1
src/render/styles/pages.less

@@ -324,11 +324,12 @@
 
   // mark-pan
   &-mark-pan {
-    position: fixed;
+    position: absolute;
     top: 200px;
     left: 200px;
     width: 212px;
     width: 212px;
+    z-index: 19;
     background: #f2f3f5;
     box-shadow: 0px 10px 10px 0px rgba(54, 61, 89, 0.2);
     overflow: hidden;
@@ -372,6 +373,27 @@
     }
   }
 
+  // image
+  &-image {
+    height: 100%;
+    padding: 8px;
+
+    &-box {
+      padding: 8px;
+    }
+
+    &-item {
+      height: 100%;
+      overflow: auto;
+
+      img {
+        display: block;
+        max-height: none;
+        height: auto;
+      }
+    }
+  }
+
   // ant
   .ant-collapse {
     border-radius: 0;

+ 21 - 9
src/render/views/Review/ReviewImage.vue

@@ -6,8 +6,17 @@
       :key="index"
       :style="boxStyle"
     >
-      <div class="review-image-item" :data-index="index" @scroll="onImgScroll">
-        <img :src="item.uri" alt="第一页" />
+      <div
+        class="review-image-item"
+        :data-index="index + 1"
+        @scroll="onImgScroll"
+      >
+        <!-- TODO:测试数据 -->
+        <img
+          src="../RecognizeCheck/data/202302040117-1.jpg"
+          :alt="`第${index + 1}页`"
+        />
+        <!-- <img :src="item.uri" :alt="`第${index + 1}页`" /> -->
       </div>
     </div>
   </div>
@@ -37,15 +46,18 @@ function onImgScroll(e: Event) {
 
   const targetDom = e.target as HTMLElement;
   const targetIndex = targetDom.getAttribute("data-index");
+
   if (curTargetIndex && targetIndex !== curTargetIndex) return;
 
-  const curTargetIndex = targetIndex;
-  const siblingsDoms = (targetDom.parentElement as HTMLElement)
-    .querySelectorAll("review-image-item")
-    .forEach((elem) => {
-      if (elem.getAttribute("data-index") === curTargetIndex) return;
-      elem.scrollTop = targetDom.scrollTop;
-    });
+  curTargetIndex = targetIndex;
+  const siblingsDoms = (
+    targetDom.parentElement.parentElement as HTMLElement
+  ).querySelectorAll(".review-image-item");
+
+  siblingsDoms.forEach((elem) => {
+    if (elem.getAttribute("data-index") === curTargetIndex) return;
+    elem.scrollTop = targetDom.scrollTop;
+  });
 
   setTimeout(() => {
     curTargetIndex = "";

+ 102 - 2
src/render/views/Review/ReviewMarkPan.vue

@@ -1,6 +1,13 @@
 <template>
-  <div class="review-mark-pan">
-    <div class="pan-head"></div>
+  <div ref="reviewMarkPanRef" class="review-mark-pan" :style="areaStyle">
+    <div
+      class="pan-head"
+      v-ele-move-directive.prevent.stop="{
+        moveStart: moveAreaStart,
+        moveElement: moveArea,
+        moveStop: moveAreaStop,
+      }"
+    ></div>
     <div class="pan-body">
       <p>{{ reviewStore.curTask?.examNumber }}</p>
       <p>{{ reviewStore.curTask?.name }}</p>
@@ -11,7 +18,10 @@
 </template>
 
 <script setup lang="ts">
+import { ref, computed, reactive, onMounted, onBeforeMount } from "vue";
 import { useReviewStore } from "@/store";
+import { vEleMoveDirective } from "@/directives/eleMove";
+import { local } from "@/utils/tool";
 
 defineOptions({
   name: "ReviewMarkPan",
@@ -24,4 +34,94 @@ const reviewStore = useReviewStore();
 function onMark() {
   emit("mark", true);
 }
+
+// move
+const areaSize = reactive({
+  left: 200,
+  top: 300,
+});
+
+const areaStyle = computed(() => {
+  return { left: `${areaSize.left}px`, top: `${areaSize.top}px` };
+});
+let areaOriginSize = {
+  left: 40,
+  top: 0,
+};
+
+interface MovePos {
+  left: number;
+  top: number;
+}
+interface MarkPanCacheData {
+  left: number;
+  top: number;
+  limitWidth: number;
+  limitHeight: number;
+}
+
+const reviewMarkPanRef = ref();
+let limitWidth = 0;
+let limitHeight = 0;
+let panWidth = 0;
+let panHeight = 0;
+
+function moveAreaStart() {
+  areaOriginSize = { ...areaSize };
+  updateStaticSize();
+}
+function moveArea(pos: MovePos) {
+  const areaTop = pos.top + areaOriginSize.top;
+  areaSize.top = Math.min(areaTop, limitHeight - panHeight);
+  areaSize.top = Math.max(0, areaSize.top);
+  const areaLeft = pos.left + areaOriginSize.left;
+  areaSize.left = Math.min(areaLeft, limitWidth - panWidth);
+  areaSize.left = Math.max(0, areaSize.left);
+}
+
+function moveAreaStop(pos: MovePos) {
+  moveArea(pos);
+
+  local.set("mark-pan", {
+    ...areaSize,
+    limitHeight,
+    limitWidth,
+  });
+}
+
+function updateStaticSize() {
+  const panDom = reviewMarkPanRef.value as HTMLDivElement;
+  panWidth = panDom.clientWidth;
+  panHeight = panDom.clientHeight;
+  const parentDom = panDom.parentElement as HTMLDivElement;
+  limitWidth = parentDom.clientWidth;
+  limitHeight = parentDom.clientHeight;
+}
+
+function initAreaSize() {
+  const cacheSize: MarkPanCacheData | null = local.get("mark-pan");
+  updateStaticSize();
+
+  if (!cacheSize) {
+    areaSize.left = (limitWidth - panWidth) / 2;
+    areaSize.top = (limitHeight - panHeight) / 2;
+    return;
+  }
+
+  const rate = limitWidth / cacheSize.limitWidth;
+  const areaLeft = (limitWidth * cacheSize.left) / cacheSize.limitWidth;
+  areaSize.left = Math.min(areaLeft, limitWidth - panWidth);
+  const areaTop = (limitHeight * cacheSize.top) / cacheSize.limitHeight;
+  areaSize.top = Math.min(areaTop, limitHeight - panHeight);
+}
+
+onMounted(() => {
+  initAreaSize();
+
+  window.addEventListener("resize", initAreaSize);
+});
+
+onBeforeMount(() => {
+  window.removeEventListener("resize", initAreaSize);
+});
 </script>

+ 3 - 2
src/render/views/Review/index.vue

@@ -25,6 +25,9 @@
     <!-- body -->
     <div class="review-body">
       <ReviewImage />
+
+      <!-- ReviewMarkPan -->
+      <ReviewMarkPan v-if="reviewStore.curTask" @mark="onMark" />
     </div>
 
     <!-- action -->
@@ -36,8 +39,6 @@
       :subject="resetSubject"
       @confirm="onResetConfirm"
     />
-    <!-- ReviewMarkPan -->
-    <ReviewMarkPan v-if="reviewStore.curTask" @mark="onMark" />
   </div>
 </template>