Procházet zdrojové kódy

draw answer paper image

Michael Wang před 4 roky
rodič
revize
d77b29c0c7

+ 5 - 0
src/api/markPage.ts

@@ -1,6 +1,11 @@
 import { httpApp } from "@/plugins/axiosApp";
 import { Setting, UISetting } from "@/types";
 
+/** 清除评卷任务(之前锁住的任务之类的) */
+export async function clearMarkTask() {
+  return httpApp.post("/mark/clear");
+}
+
 /** 获取评卷设置 */
 export async function getSetting() {
   return httpApp.post("/mark/getSetting");

+ 13 - 2
src/components/mark/Mark.vue

@@ -7,7 +7,13 @@
 
 <script lang="ts">
 import { defineComponent, onMounted, toRefs } from "vue";
-import { getGroup, getSetting, getStatus, getTask } from "@/api/markPage";
+import {
+  clearMarkTask,
+  getGroup,
+  getSetting,
+  getStatus,
+  getTask,
+} from "@/api/markPage";
 import { store } from "./store";
 import MarkHeader from "./MarkHeader.vue";
 import MarkBody from "./MarkBody.vue";
@@ -22,6 +28,10 @@ export default defineComponent({
   setup: () => {
     const { addInterval } = useTimers();
 
+    async function updateMarkTask() {
+      const settingRes = await clearMarkTask();
+    }
+
     async function updateSetting() {
       const settingRes = await getSetting();
       store.setting = settingRes.data;
@@ -50,7 +60,8 @@ export default defineComponent({
       }
     }, 5 * 1000);
 
-    onMounted(() => {
+    onMounted(async () => {
+      await updateMarkTask();
       updateSetting();
       updateStatus();
       updateGroups();

+ 74 - 6
src/components/mark/MarkBody.vue

@@ -1,19 +1,87 @@
 <template>
-  <div>
-    <div>
-      <a href="/mark/subject-select">{{ store.setting.subject?.name }}</a>
-    </div>
+  <div class="mark-body-container" ref="container">
+    <template v-for="(item, index) in imageWithStyles" :key="index">
+      <img :src="item.url" />
+      <!-- style="border: 1px solid black; background: black" -->
+    </template>
   </div>
 </template>
 
 <script lang="ts">
-import { defineComponent } from "vue";
+import { defineComponent, onMounted, reactive, ref, watchEffect } from "vue";
 import { store } from "./store";
+import filters from "@/filters";
 
+interface ImageStyle {
+  width: number; // or string?
+}
 export default defineComponent({
   name: "MarkBody",
   setup() {
-    return { store };
+    const container = ref(null);
+    const imageWithStyles: Array<any> = reactive([]);
+    watchEffect(async () => {
+      if (store.currentTask?.sliceConfig) {
+        async function loadImage(url: string): Promise<HTMLImageElement> {
+          return new Promise((resolve, reject) => {
+            const image = new Image();
+            image.setAttribute("crossorigin", "anonymous");
+            image.src = url;
+            image.onload = () => resolve(image);
+            image.onerror = reject;
+          });
+        }
+        for (const url of store.currentTask.sliceUrls) {
+          await loadImage(filters.toCompleteUrl(url));
+        }
+        let zIndex = 500;
+        for (const sliceConfig of store.currentTask.sliceConfig) {
+          const url = filters.toCompleteUrl(
+            store.currentTask.sliceUrls[sliceConfig.i - 1]
+          );
+          const image = await loadImage(url);
+
+          const div: HTMLDivElement = container.value;
+          // const containerWidth = +getComputedStyle(div).width.replace("px", "");
+          // console.log(div, containerWidth, sliceConfig);
+          // console.log(container);
+          // const originalWidth = image.naturalWidth;
+          // const originalHeight = image.naturalHeight;
+          // console.log({ originalWidth, originalHeight });
+          // const ratio = containerWidth / originalWidth;
+          // getNaturalWidth
+          const canvas = document.createElement("canvas");
+          canvas.width = sliceConfig.w;
+          canvas.height = sliceConfig.h;
+          const ctx = canvas.getContext("2d");
+          ctx?.drawImage(
+            image,
+            sliceConfig.x,
+            sliceConfig.y,
+            sliceConfig.w,
+            sliceConfig.h,
+            0,
+            0,
+            sliceConfig.w,
+            sliceConfig.h
+          );
+          console.log(image, canvas.height, sliceConfig, ctx);
+          // console.log(canvas.toDataURL());
+          imageWithStyles.push({
+            url: canvas.toDataURL(),
+          });
+        }
+      }
+      console.log("watch effect", imageWithStyles);
+    });
+    return { container, store, imageWithStyles };
   },
 });
 </script>
+
+<style scoped>
+.mark-body-container {
+  height: calc(100vh - 21px);
+  /* overflow: scroll; */
+}
+</style>

+ 5 - 2
src/components/mark/MarkHeader.vue

@@ -1,5 +1,8 @@
 <template>
-  <div class="flex gap-4">
+  <div
+    class="flex gap-4"
+    style="z-index: 10000; position: relative; background-color: white"
+  >
     <div>
       <a href="/mark/subject-select">{{ store.setting.subject?.name }}</a>
     </div>
@@ -26,7 +29,7 @@
       <ul class="flex gap-1">
         <li>放大</li>
         <li>缩小</li>
-        <li>回看</li>
+        <li>适应</li>
       </ul>
     </div>
     <div>回看</div>

+ 6 - 0
src/filters/index.ts

@@ -1,8 +1,14 @@
 import { YYYYMMDDHHmmss } from "@/constants/constants";
 import moment from "moment";
+import { store } from "@/components/mark/store";
 
 export default {
+  /** 返回YYYY-MM-DD HH:mm:ss */
   datetimeFilter(epochTime: number) {
     return moment(epochTime).format(YYYYMMDDHHmmss);
   },
+  /** 根据fileServer得到完整的资源路径 */
+  toCompleteUrl(path: string) {
+    return store.setting.fileServer + path;
+  },
 };