2 Commits 9f50f3d921 ... d27859062a

Tác giả SHA1 Thông báo Ngày
  yanxin d27859062a [web_demo] server属性统一管理以及table_rec,ocr,detection模块适配封装组件,首页新增跳转DocumentAI在线文档链接 1 năm trước cách đây
  yanxin 36c9f0697e [web_demo] 代码组件化,方便组件复用,点击图片显示区域或者将文件拖拽至该区域实现文件上传,magic_color已适配 1 năm trước cách đây

+ 0 - 1
src/App.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import HelloWorld from './components/HelloWorld.vue'
 import MainView from "@/MainView.vue";
 </script>
 

+ 7 - 3
src/MainView.vue

@@ -5,9 +5,9 @@
     </el-aside>
     <el-container>
       <!-- <el-header>Header</el-header> -->
-      <el-main>
+      <!-- <el-main> -->
         <RouterView></RouterView>
-      </el-main>
+      <!-- </el-main> -->
       <!-- <el-footer>Footer</el-footer> -->
     </el-container>
   </el-container>
@@ -19,13 +19,17 @@ import { onMounted } from "vue";
 import { GetVersion } from './api/api'
 import { storeToRefs } from 'pinia'
 import { useVersionStore } from './store/Version';
+import { useServerStore } from './store/Server';
 
 const vr = useVersionStore();
 const { version } = storeToRefs(vr);
 
+const si = useServerStore();
+const { api_version } = storeToRefs(si);
+
 
 onMounted(async () => {
-  GetVersion("/v1/version").then(res => {
+  GetVersion(api_version.value).then(res => {
     version.value = res;
   })
 });

+ 2 - 1
src/MenuView.vue

@@ -45,7 +45,8 @@
       </el-menu>
     </el-col>
   </el-row>
-  <el-tag size="large" style="position: absolute; bottom: 0%;">V 1.1.1</el-tag>
+  <el-link style="position: absolute; bottom: 5%; left: 0%;" type="primary" href="https://documentaidocs.readthedocs.io/en/latest/" target="_blank">DocumentAI 在线文档</el-link>
+  <el-tag size="large" style="position: absolute; bottom: 0%; left: 0%;">V 1.1.1</el-tag>
 </template>
 
 <style scoped lang="less">

+ 105 - 0
src/components/FileUpload.vue

@@ -0,0 +1,105 @@
+<template>
+    <div class="upload-container">
+        <div class="mask" @dragover.prevent @drop="handleDrop">
+            <el-upload class="upload" drag :before-upload="BeforeUpload">
+                <el-button type="primary">点击或拖拽上传文件</el-button>
+            </el-upload>
+        </div>
+    </div>
+</template>
+
+<script setup lang="ts">
+import { useCanvasImgStore } from '../store/CanvasImg';
+import { usePdfProperty } from '../store/PdfProperty';
+import { storeToRefs } from 'pinia'
+import { fabric } from 'fabric';
+
+
+const c_img = useCanvasImgStore();
+const { show_image, show_canvas, fabric_canvas, input_file } = storeToRefs(c_img);
+const pdf_property = usePdfProperty();
+const { is_pdf, pdf_source } = storeToRefs(pdf_property);
+
+function handleDrop(e: any) {
+    e.preventDefault()
+    const files = e.dataTransfer.files
+    if (files.length > 0) {
+        const file = files[0]
+        if (fabric_canvas.value != null) {
+            fabric_canvas.value.dispose();
+            fabric_canvas.value = null;
+        }
+
+        const post_ = file.name.substring(file.name.lastIndexOf("."), file.name.length).toLowerCase();
+        if (post_ == ".pdf") {
+            is_pdf.value = true;
+            pdf_source.value = URL.createObjectURL(file);
+        } else if (post_ == ".jpg" || post_ == ".png" || post_ == ".bmp" || post_ == ".jpeg") {
+            is_pdf.value = false
+            show_image.value.src = URL.createObjectURL(file);
+            show_image.value.onload = () => {
+                show_canvas.value.width = show_image.value.width;
+                show_canvas.value.height = show_image.value.height;
+                fabric_canvas.value = new fabric.Canvas(show_canvas.value);
+                fabric_canvas.value.clear()
+            }
+            input_file.value = file;
+        } else {
+            alert('不支持的文件格式!')
+        }
+    }
+}
+
+const BeforeUpload = (file: File): boolean | Promise<boolean> => {
+    if (fabric_canvas.value != null) {
+        fabric_canvas.value.dispose();
+        fabric_canvas.value = null;
+    }
+    const post_ = file.name.substring(file.name.lastIndexOf("."), file.name.length).toLowerCase();
+    if (post_ == ".pdf") {
+        is_pdf.value = true;
+        pdf_source.value = URL.createObjectURL(file);
+    } else if (post_ == ".jpg" || post_ == ".png" || post_ == ".bmp" || post_ == ".jpeg") {
+        is_pdf.value = false
+        show_image.value.src = URL.createObjectURL(file);
+        show_image.value.onload = () => {
+            show_canvas.value.width = show_image.value.width;
+            show_canvas.value.height = show_image.value.height;
+            fabric_canvas.value = new fabric.Canvas(show_canvas.value);
+            fabric_canvas.value.clear()
+        }
+        input_file.value = file;
+    } else {
+        alert('不支持的文件格式!')
+    }
+    return true;
+}
+</script>
+
+<style scoped lang="less">
+.upload-container {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 200px;
+    background-color: gray;
+}
+
+.mask {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+}
+
+.upload {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+}
+</style>

+ 0 - 38
src/components/HelloWorld.vue

@@ -1,38 +0,0 @@
-<script setup lang="ts">
-import { ref } from 'vue'
-
-defineProps<{ msg: string }>()
-
-const count = ref(0)
-</script>
-
-<template>
-  <h1>{{ msg }}</h1>
-
-  <div class="card">
-    <button type="button" @click="count++">count is {{ count }}</button>
-    <p>
-      Edit
-      <code>components/HelloWorld.vue</code> to test HMR
-    </p>
-  </div>
-
-  <p>
-    Check out
-    <a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
-      >create-vue</a
-    >, the official Vue + Vite starter
-  </p>
-  <p>
-    Install
-    <a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>
-    in your IDE for a better DX
-  </p>
-  <p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
-</template>
-
-<style scoped>
-.read-the-docs {
-  color: #888;
-}
-</style>

+ 144 - 161
src/components/PdfPreview.vue

@@ -1,189 +1,172 @@
-<!-- <template>
-  <div class="pdf-preview">
-        <div class="pdf-wrap">
-          <vue-pdf-embed :source="state.source" :style="scale" class="vue-pdf-embed" :page="state.pageNum" />
-        </div>
-        <div class="page-tool">
-          <div class="page-tool-item" @click="prePage">上一页</div>
-          <div class="page-tool-item" @click="nextPage">下一页</div>
-          <div class="page-tool-item">{{ state.pageNum }}/{{ state.numPages }}</div>
-          <div class="page-tool-item" @click="pageZoomOut">放大</div>
-          <div class="page-tool-item" @click="pageZoomIn">缩小</div>
-          <el-input type="number" v-model="pdf_page"></el-input>
-          <el-button type="primary" @click="SetPdfPage" plain>页面跳转</el-button>
-        </div>
-      </div>
+<template>
+    <div v-show="is_pdf">
+        <el-row>
+            <el-button-group>
+                <el-button type="primary" :icon="ArrowLeft" @click="prePage">上一页</el-button>
+                <el-button type="primary" @click="nextPage">
+                    下一页<el-icon class="el-icon--right">
+                        <ArrowRight />
+                    </el-icon>
+                </el-button>
+            </el-button-group>
+            <div class="page-tool-item">{{ state.pageNum }}/{{ state.numPages }}</div>
+            <el-container>
+                <el-input type="number" v-model="pdf_page"></el-input>
+                <el-button type="primary" @click="SetPdfPage" plain>页面跳转</el-button>
+            </el-container>
+        </el-row>
+    </div>
 </template>
 
-<script lang="ts" setup>
-import { reactive, ref, toRefs, computed } from 'vue'
-import { onMounted } from "vue";
-import VuePdfEmbed from "vue-pdf-embed";
-import { createLoadingTask } from "vue3-pdfjs/esm"; // 获得总页数
+<script setup lang="ts">
+import { reactive, ref, onMounted, watchEffect } from 'vue'
+import { createLoadingTask } from "vue3-pdfjs/esm";
+import { useCanvasImgStore } from '../store/CanvasImg';
+import { usePdfProperty } from '../store/PdfProperty';
+import { storeToRefs } from 'pinia'
+import { fabric } from 'fabric';
 
-let loadingTask: any;
 
-const pdf_page = ref(1);
+import {
+    ArrowLeft,
+    ArrowRight
+} from '@element-plus/icons-vue'
+
+const c_img = useCanvasImgStore();
+const { show_image, show_canvas, hide_canvas, fabric_canvas, input_file } = storeToRefs(c_img);
+const pdf_property = usePdfProperty();
+const { is_pdf, pdf_source, old_pdf_source } = storeToRefs(pdf_property);
 
 const state = reactive({
-  source: "", //预览pdf文件地址
-  pageNum: 1, //当前页面
-  scale: 1, // 缩放比例
-  numPages: 0, // 总页数
+    source: "", //预览pdf文件地址
+    pageNum: 1, //当前页面
+    numPages: 0, // 总页数
 });
 
-const scale = computed(() => `transform:scale(${state.scale})`)
-
-function getPdfImage(index: number) {
-  // console.log(index, state.pageNum)
-  loadingTask.promise.then((pdf: any) => {
-    state.numPages = pdf.numPages;
-    pdf.getPage(index).then((page: any) => {
-      const viewport = page.getViewport({ scale: 1 })
-      canvas.value.height = viewport.height;
-      canvas.value.width = viewport.width;
-      // 画布的dom大小, 设置移动端,宽度设置铺满整个屏幕
-      // const clientWidth = document.body.clientWidth;
-      const destWidth = 398;
-      canvas.value.style.width = destWidth + 'px';
-      // 根据pdf每页的宽高比例设置canvas的高度
-      canvas.value.style.height = destWidth * (viewport.height / viewport.width) + 'px';
-      const ctx = canvas.value.getContext('2d');
-      page.render({
-        canvasContext: ctx,
-        viewport,
-      });
-      canvas.value.toBlob(function (blob) {
-        pdf_img.value = dataURLtoBlob(canvas.value.toDataURL())
-        // console.log(pdf_img.value);
-        console.log(canvas.value.toDataURL(), state.pageNum)
-      });
-    })
-  });
-}
+const pdf_page = ref(1);
+const pdf_img: any = ref("")
+let loadingTask: any;
 
-function SetPdfPage() {
-  if (pdf_page.value >= 1 && pdf_page.value <= state.numPages) {
-    console.log(pdf_page.value)
-    state.pageNum = Number(pdf_page.value);
-    getPdfImage(state.pageNum);
-  } else {
-    console.log(pdf_page.value)
-    alert('输入的pdf页面无效!')
-  }
-}
+onMounted(async () => {
+    show_image.value = document.getElementById("show_img") as HTMLImageElement;
+    show_canvas.value = document.getElementById("show_canvas") as HTMLCanvasElement;
+    hide_canvas.value = document.getElementById("hide_canvas") as HTMLCanvasElement;
+});
 
 function prePage() {
-  if (state.pageNum > 1) {
-    state.pageNum -= 1;
-    getPdfImage(state.pageNum);
-  }
+    if (state.pageNum > 1) {
+        state.pageNum -= 1;
+        getPdfImage(state.pageNum);
+    }
 }
 
 function nextPage() {
-  if (state.pageNum < state.numPages) {
-    state.pageNum += 1;
-    getPdfImage(state.pageNum);
-  }
-}
-function pageZoomOut() {
-  if (state.scale < 2) {
-    state.scale += 0.1;
-  }
+    if (state.pageNum < state.numPages) {
+        state.pageNum += 1;
+        getPdfImage(state.pageNum);
+    }
 }
-function pageZoomIn() {
-  if (state.scale > 1) {
-    state.scale -= 0.1;
-  }
-}
-
-function dataURLtoBlob(dataURL: any) {
-  var arr = dataURL.split(','),
-      mime = arr[0].match(/:(.*?);/)[1],
-      bstr = atob(arr[1]),
-      n = bstr.length,
-      u8arr = new Uint8Array(n);
-  while (n--) {
-    u8arr[n] = bstr.charCodeAt(n);
-  }
-  return new Blob([u8arr], {type:mime});
-}
-
-async function convertCanvasToFile(canvas: HTMLCanvasElement, fileName: any) {
-  // 将 Canvas 转为 Blob 对象
-  const blob = await new Promise(resolve => canvas.toBlob(blob => {
-            resolve(blob);
-        }, pdf_img.value.type, 1.0));
-  // 手动构造 File 对象
-  let file = null;
-  try {
-    file = new File([pdf_img.value], fileName, { type: pdf_img.value.type });
-  } catch (e) {
-    // Safari 浏览器不支持直接通过 new File() 创建文件对象,需要手动构造
-    const rawFile = blobToFile(blob, fileName);
-    file = Object.assign(rawFile, { lastModifiedDate: new Date(), name: fileName });
-  }
-  return file;
-}
-
-</script>
 
-<style scoped>
-.pdf-preview {
-  position: relative;
-  height: 100vh;
-  padding: 20px 0;
-  box-sizing: border-box;
-  background: rgb(66, 66, 66);
+function SetPdfPage() {
+    if (pdf_page.value >= 1 && pdf_page.value <= state.numPages) {
+        state.pageNum = Number(pdf_page.value);
+        getPdfImage(state.pageNum);
+    } else {
+        alert('输入的pdf页面无效!')
+    }
 }
 
-.vue-pdf-embed {
-  text-align: center;
-  width: 515px;
-  border: 1px solid #e5e5e5;
-  margin: 0 auto;
-  box-sizing: border-box;
+function blobToFile(blob: any, fileName: any) {
+    blob.lastModifiedDate = new Date();
+    blob.name = fileName;
+    return blob;
 }
 
-.pdf-preview {
-  position: relative;
-  height: 100vh;
-  padding: 20px 0;
-  box-sizing: border-box;
-  background-color: e9e9e9;
+async function convertCanvasToFile(canvas: HTMLCanvasElement, fileName: any) {
+    // 将 Canvas 转为 Blob 对象
+    const blob = await new Promise(resolve => canvas.toBlob(blob => {
+        resolve(blob);
+    }, pdf_img.value.type, 1.0));
+    // 手动构造 File 对象
+    let file = null;
+    try {
+        file = new File([pdf_img.value], fileName, { type: pdf_img.value.type });
+    } catch (e) {
+        // Safari 浏览器不支持直接通过 new File() 创建文件对象,需要手动构造
+        const rawFile = blobToFile(blob, fileName);
+        file = Object.assign(rawFile, { lastModifiedDate: new Date(), name: fileName });
+    }
+    return file;
 }
 
-.pdf-wrap {
-  overflow-y: auto;
+function getPdfImage(index: number) {
+    loadingTask.promise.then((pdf: any) => {
+        state.numPages = pdf.numPages;
+        pdf.getPage(index).then((page: any) => {
+            const viewport = page.getViewport({ scale: 2.0 })
+            hide_canvas.value.height = viewport.height;
+            hide_canvas.value.width = viewport.width;
+            show_canvas.value.height = viewport.height;
+            show_canvas.value.width = viewport.width;
+            const destWidth = 398;
+            hide_canvas.value.style.width = destWidth + 'px';
+
+            hide_canvas.value.style.height = destWidth * (viewport.height / viewport.width) + 'px';
+            show_canvas.value.style.width = destWidth + 'px';
+
+            show_canvas.value.style.height = destWidth * (viewport.height / viewport.width) + 'px';
+            const ctx = hide_canvas.value.getContext('2d');
+            page.render({
+                canvasContext: ctx,
+                viewport,
+            });
+            hide_canvas.value.toBlob(function (blob: any) {
+                pdf_img.value = dataURLtoBlob(hide_canvas.value.toDataURL('images/png', 1.0))
+                show_image.value.src = hide_canvas.value.toDataURL('images/png', 1.0);
+                show_image.value.onload = () => {
+                    show_canvas.value.width = show_image.value.width;
+                    show_canvas.value.height = show_image.value.height;
+                    convertCanvasToFile(hide_canvas.value, "pdf.png").then(result => {
+                        if (is_pdf.value == true) {
+                            input_file.value = result;
+                        }
+                    });
+                    if (fabric_canvas.value != null) {
+                        fabric_canvas.value.dispose();
+                        fabric_canvas.value = null;
+                    }
+                    fabric_canvas.value = new fabric.Canvas(show_canvas.value);
+                    fabric_canvas.value.clear()
+                }
+            });
+        })
+    });
 }
 
-.vue-pdf-embed {
-  text-align: center;
-  width: 515px;
-  border: 1px solid #e5e5e5;
-  margin: 0 auto;
-  box-sizing: border-box;
+function dataURLtoBlob(dataURL: any) {
+    var arr = dataURL.split(','),
+        mime = arr[0].match(/:(.*?);/)[1],
+        bstr = atob(arr[1]),
+        n = bstr.length,
+        u8arr = new Uint8Array(n);
+    while (n--) {
+        u8arr[n] = bstr.charCodeAt(n);
+    }
+    return new Blob([u8arr], { type: mime });
 }
 
-.page-tool {
-  position: absolute;
-  /* bottom: 35px; */
-  /* padding-left: 15px; */
-  /* padding-right: 15px; */
-  display: flex;
-  align-items: center;
-  background: rgb(66, 66, 66);
-  color: white;
-  border-radius: 19px;
-  z-index: 100;
-  cursor: pointer;
-  margin-left: 50%;
-  transform: translateX(-50%);
+function initPdf(source: any) {
+    state.pageNum = 1;
+    state.source = source;
+    loadingTask = createLoadingTask(state.source);
+    getPdfImage(state.pageNum);
 }
 
-.page-tool-item {
-  padding: 8px 15px;
-  padding-left: 10px;
-  cursor: pointer;
-}
-</style> -->
+watchEffect(() => {
+    if (old_pdf_source.value != pdf_source.value && is_pdf.value == true) {
+        old_pdf_source.value = pdf_source.value;
+        state.source = pdf_source.value; // 更新 source 变量
+        initPdf(pdf_source.value); // 调用 initPdf 方法重新加载 PDF 文件
+    }
+});
+</script>

+ 69 - 0
src/components/ShowImage.vue

@@ -0,0 +1,69 @@
+<template>
+    <div class="image-container">
+        <img id="show_img" v-if="showSrcImage">
+        <img id="res_img" class="image" v-else>
+        <canvas id="show_canvas"></canvas>
+        <canvas id="hide_canvas" style="display: none;"></canvas>
+    </div>
+</template>
+
+<script lang="ts" setup>
+
+import { ref, onMounted } from 'vue'
+import { useCanvasImgStore } from '../store/CanvasImg';
+import { storeToRefs } from 'pinia'
+
+const c_img = useCanvasImgStore();
+const { show_image, res_image, show_canvas, hide_canvas } = storeToRefs(c_img);
+
+onMounted(async () => {
+    show_image.value = document.getElementById("show_img") as HTMLImageElement;
+    res_image.value = document.getElementById("res_img") as HTMLImageElement;
+    show_canvas.value = document.getElementById("show_canvas") as HTMLCanvasElement;
+    hide_canvas.value = document.getElementById("hide_canvas") as HTMLCanvasElement;
+});
+
+defineProps<{
+    showSrcImage?: boolean,
+}>()
+</script>
+
+<style scoped lang="less">
+.image-container {
+    display: relative;
+    width: 100%;
+    height: 600px;
+    background-color: gainsboro;
+}
+
+#show_canvas {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 0;
+    background-color: transparent;
+}
+
+#show_img {
+    z-index: 0;
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    // margin: auto;
+    max-width: 100%;
+    max-height: 100%;
+}
+
+.image {
+    max-width: 100%;
+    max-height: 100%;
+    position: flex;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    margin: auto;
+}
+</style>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
src/dist/assets/index-9585a3a9.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 117 - 117
src/dist/assets/index-42269111.js


+ 2 - 2
src/dist/index.html

@@ -4,8 +4,8 @@
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>DocumentAI Web Demo</title>
-    <script type="module" crossorigin src="./assets/index-42269111.js"></script>
-    <link rel="stylesheet" href="./assets/index-9585a3a9.css">
+    <script type="module" crossorigin src="./assets/index-2ef0df5a.js"></script>
+    <link rel="stylesheet" href="./assets/index-15b83f1d.css">
   </head>
   <body>
     <div id="app"></div>

+ 3 - 6
src/main.ts

@@ -5,8 +5,7 @@ import App from "./App.vue";
 import router from "./pages/main/router";
 import { createPinia } from "pinia";
 import { storeToRefs } from "pinia";
-import { useServerIpStore } from "./store/ServerIp";
-import { useServerPortStore } from "./store/ServerPort";
+import { useServerStore } from "./store/Server";
 
 const app = createApp(App);
 const pinia = createPinia();
@@ -16,10 +15,8 @@ app.use(ElementPlus);
 app.use(router);
 app.mount("#app");
 
-const si = useServerIpStore();
-const { server_ip } = storeToRefs(si);
-const sp = useServerPortStore();
-const { server_port } = storeToRefs(sp);
+const si = useServerStore();
+const { server_ip, server_port } = storeToRefs(si);
 
 const xhr = new XMLHttpRequest();
 xhr.open("GET", window.location.href);

+ 91 - 408
src/pages/main/views/Detection/LayoutAnalysis.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-row :gutter="20">
+  <el-row :gutter="20" class="page">
     <el-col :span="12" class="place">
       <el-row class="small-title">
         <h2>版面分析</h2>
@@ -7,46 +7,19 @@
       <el-row style="color: gray; font-size: small;">
         <p>目前支持检测图片与表格</p>
       </el-row>
+      <el-row>
+        <ShowImage :show-src-image=true   />
+      </el-row>
+      <el-row>
+        <FileUpload />
+      </el-row>
       <el-row style="color: gray; font-size: small;">
-        <h4>支持jpg, png, bmp, pdf等文件格式</h4>
+        <h4>支持jpg, png, bmp, pdf等文件格式,点击灰色区域或者直接拖拽文件至灰色区域上传文件</h4>
       </el-row>
-      <div class="common-layout">
-        <el-upload class="upload-demo" drag :before-upload="beforeUpload" multiple>
-          <el-icon class="el-icon--upload"><upload-filled /></el-icon>
-          <div class="el-upload__text">
-            Drop file here or <em>click to upload</em>
-          </div>
-          <template #tip>
-            <div class="el-upload__tip">
-              {{ fileName }}
-            </div>
-          </template>
-        </el-upload>
+      <el-row style="position: absolute;">
+        <PdfPreview />
         <el-button type="primary" @click="predict" :loading="loading">Predict</el-button>
-      </div>
-      <div v-show="is_pdf">
-        <el-row>
-          <el-button-group>
-            <el-button type="primary" :icon="ArrowLeft" @click="prePage">上一页</el-button>
-            <el-button type="primary" @click="nextPage">
-              下一页<el-icon class="el-icon--right">
-                <ArrowRight />
-              </el-icon>
-            </el-button>
-          </el-button-group>
-          <div class="page-tool-item">{{ state.pageNum }}/{{ state.numPages }}</div>
-          <el-container>
-            <el-input type="number" v-model="pdf_page"></el-input>
-            <el-button type="primary" @click="SetPdfPage" plain>页面跳转</el-button>
-          </el-container>
-        </el-row>
-      </div>
-      <el-row>
-        <!-- 用于展示图片 -->
-        <img id="show-img" class="show-area" />
       </el-row>
-      <canvas id="canvas"></canvas>
-      <canvas id="img_canvas" style="display: none;"></canvas>
     </el-col>
     <el-col :span="12" class="place">
       <el-row class="small-title">
@@ -83,159 +56,32 @@
 <script lang="ts" setup>
 import { Detection, SubmitBug } from '../../../../api/api'
 import { fabric } from 'fabric';
-import { reactive, ref } from 'vue'
-import { onMounted } from "vue";
-import { createLoadingTask } from "vue3-pdfjs/esm"; // 获得总页数
-import {
-  ArrowLeft,
-  ArrowRight,
-  UploadFilled
-} from '@element-plus/icons-vue'
+import { reactive, ref, onMounted } from 'vue'
 
 import { storeToRefs } from 'pinia'
-import { useServerIpStore } from '../../../../store/ServerIp';
-import { useServerPortStore } from '../../../../store/ServerPort';
-
-const si = useServerIpStore();
-const { server_ip } = storeToRefs(si);
-const sp = useServerPortStore();
-const { server_port } = storeToRefs(sp);
-
-const api = "/v1/detection/layout_parser";
-
-let loadingTask: any;
-const is_pdf = ref(false);
-const pdf_page = ref(1);
-const pdf_img: any = ref("")
-
-const input_file = ref(null as unknown as File)
-
-const state = reactive({
-  source: "", //预览pdf文件地址
-  pageNum: 1, //当前页面
-  numPages: 0, // 总页数
-});
-
-function dataURLtoBlob(dataURL: any) {
-  var arr = dataURL.split(','),
-    mime = arr[0].match(/:(.*?);/)[1],
-    bstr = atob(arr[1]),
-    n = bstr.length,
-    u8arr = new Uint8Array(n);
-  while (n--) {
-    u8arr[n] = bstr.charCodeAt(n);
-  }
-  return new Blob([u8arr], { type: mime });
-}
-
-function getPdfImage(index: number) {
-  console.log(index, state.pageNum)
-  const showImg = document.getElementById("show-img") as HTMLImageElement;
-  loadingTask.promise.then((pdf: any) => {
-    state.numPages = pdf.numPages;
-    pdf.getPage(index).then((page: any) => {
-      const viewport = page.getViewport({ scale: 2.0 })
-      img_canvas.value.height = viewport.height;
-      img_canvas.value.width = viewport.width;
-      canvas.value.height = viewport.height;
-      canvas.value.width = viewport.width;
-      const destWidth = 398;
-      img_canvas.value.style.width = destWidth + 'px';
-
-      img_canvas.value.style.height = destWidth * (viewport.height / viewport.width) + 'px';
-      canvas.value.style.width = destWidth + 'px';
-
-      canvas.value.style.height = destWidth * (viewport.height / viewport.width) + 'px';
-      const ctx = img_canvas.value.getContext('2d');
-      page.render({
-        canvasContext: ctx,
-        viewport,
-      });
-      img_canvas.value.toBlob(function (blob) {
-        let data = img_canvas.value.toDataURL('images/png', 1.0)
-        pdf_img.value = dataURLtoBlob(data)
-        showImg.src = data;
-        showImg.onload = () => {
-          canvas.value.width = showImg.width;
-          canvas.value.height = showImg.height;
-          if (fa_canvas != null) {
-            fa_canvas.dispose();
-            fa_canvas = null;
-          }
-          fa_canvas = new fabric.Canvas(canvas.value);
-          fa_canvas.clear()
-          figure_rects.splice(0)
-          table_rects.splice(0)
-          figureSelectedItem.value = -1;
-          tableSelectedItem.value = -1;
-        }
-      });
-    })
-  });
-}
-
-function SetPdfPage() {
-  if (pdf_page.value >= 1 && pdf_page.value <= state.numPages) {
-    console.log(pdf_page.value)
-    state.pageNum = Number(pdf_page.value);
-    getPdfImage(state.pageNum);
-  } else {
-    console.log(pdf_page.value)
-    alert('输入的pdf页面无效!')
-  }
-}
-
-function prePage() {
-  if (state.pageNum > 1) {
-    state.pageNum -= 1;
-    getPdfImage(state.pageNum);
-  }
-}
+import { useServerStore } from '../../../../store/Server';
+import { useCanvasImgStore } from '../../../../store/CanvasImg';
 
-function nextPage() {
-  if (state.pageNum < state.numPages) {
-    state.pageNum += 1;
-    getPdfImage(state.pageNum);
-  }
-}
+import FileUpload from '../../../../components/FileUpload.vue'
+import ShowImage from '../../../../components/ShowImage.vue'
+import PdfPreview from '../../../../components/PdfPreview.vue'
 
-// 构建 File 对象
-function blobToFile(blob: any, fileName: any) {
-  blob.lastModifiedDate = new Date();
-  blob.name = fileName;
-  return blob;
-}
+const si = useServerStore();
+const { server_ip, server_port, api_layout_analysis } = storeToRefs(si);
+const my_canvas = useCanvasImgStore();
+const { input_file, fabric_canvas, show_canvas, show_image } = storeToRefs(my_canvas);
 
-async function convertCanvasToFile(canvas: HTMLCanvasElement, fileName: any) {
-  // 将 Canvas 转为 Blob 对象
-  const blob = await new Promise(resolve => canvas.toBlob(blob => {
-    resolve(blob);
-  }, pdf_img.value.type, 1.0));
-  // 手动构造 File 对象
-  let file = null;
-  try {
-    file = new File([pdf_img.value], fileName, { type: pdf_img.value.type });
-  } catch (e) {
-    // Safari 浏览器不支持直接通过 new File() 创建文件对象,需要手动构造
-    const rawFile = blobToFile(blob, fileName);
-    file = Object.assign(rawFile, { lastModifiedDate: new Date(), name: fileName });
-  }
-  return file;
-}
 
 let loading = ref(false)
 let show_predict = ref(false)
 let predictTime = ref(0)
 const fileName = ref(null as unknown as string);
-const canvas = ref(null as unknown as HTMLCanvasElement);
-const img_canvas = ref(null as unknown as HTMLCanvasElement);
 let figureSelectedItem = ref(-1)
 let tableSelectedItem = ref(-1)
 
 let figureArr: any = ref([])
 let tableArr: any = ref([])
 
-let fa_canvas: any = null;
 let bugId = ref("");
 const json_result = ref("");
 
@@ -249,56 +95,6 @@ interface iRect {
 let figure_rects: any = []
 let table_rects: any = []
 
-onMounted(async () => {
-  canvas.value = document.getElementById("canvas") as HTMLCanvasElement;
-  img_canvas.value = document.getElementById("img_canvas") as HTMLCanvasElement;
-});
-
-const beforeUpload = (file: File): boolean | Promise<boolean> => {
-  if (fa_canvas != null) {
-    fa_canvas.dispose();
-    fa_canvas = null;
-  }
-
-  const showImg = document.getElementById("show-img") as HTMLImageElement;
-
-  const post_ = file.name.substring(file.name.lastIndexOf("."), file.name.length).toLowerCase();
-  if (post_ == ".pdf") {
-    state.pageNum = 1;
-    state.source = URL.createObjectURL(file);
-    is_pdf.value = true
-    loadingTask = createLoadingTask(state.source);
-    getPdfImage(state.pageNum);
-  } else
-    if (post_ == ".jpg" || post_ == ".png" || post_ == ".bmp" || post_ == ".jpeg") {
-      showImg.src = URL.createObjectURL(file);
-      input_file.value = file
-      showImg.onload = () => {
-        canvas.value.width = showImg.width;
-        canvas.value.height = showImg.height;
-        if (fa_canvas != null) {
-          fa_canvas.dispose();
-          fa_canvas = null;
-        }
-        fa_canvas = new fabric.Canvas(canvas.value);
-        fa_canvas.clear()
-        figure_rects.splice(0)
-        table_rects.splice(0)
-        figureSelectedItem.value = -1;
-        tableSelectedItem.value = -1;
-      }
-      is_pdf.value = false
-    } else {
-      alert('不支持的文件格式!')
-      fileName.value = ''
-    }
-  fileName.value = file.name
-
-  if (show_predict.value === true)
-    show_predict.value = !show_predict.value;
-  return true
-}
-
 type RectWithId = fabric.Rect & { id: number };
 
 function CreateRect(canvas: any, i: number, left: number, top: number, width: number, height: number, highlight: boolean, label: number) {
@@ -319,135 +115,77 @@ function CreateRect(canvas: any, i: number, left: number, top: number, width: nu
 }
 
 const predict = async () => {
+  fileName.value = ''
+  fileName.value = input_file.value?.name
   if (fileName.value == undefined || fileName.value == '') {
     alert('请上传图片!')
     return;
   }
 
-  if (fa_canvas != null) {
-    fa_canvas.dispose();
-    fa_canvas = null;
-    fa_canvas = new fabric.Canvas(canvas.value);
-    fa_canvas.clear()
+  if (fabric_canvas.value != null) {
+    fabric_canvas.value.dispose();
+    fabric_canvas.value = null;
+    fabric_canvas.value = new fabric.Canvas(show_canvas.value);
+    fabric_canvas.value.clear()
   }
   figure_rects.splice(0)
   table_rects.splice(0)
 
-  const img = document.getElementById("show-img") as HTMLImageElement;
-
   loading.value = !loading.value
   var data = new FormData();
-
-  if (is_pdf.value) {
-    const file: any = convertCanvasToFile(img_canvas.value, "pdf.png").then(result => {
-      console.log(result)
-      data.append('image', result);
-      Detection(api, data).then(res => {
-        console.log(res.code)
-        json_result.value = JSON.stringify(res.data, null, 4);
-        console.log(res.data);
-        figureArr.value.splice(0);
-        tableArr.value.splice(0);
-        let tmp_labels = res.data.labels;
-        if (tmp_labels.length == 0) {
-          alert("no result!");
-        } else {
-          let tmp_boxes = res.data.boxes;
-          const h_radio = img.height / img.naturalHeight;
-          const w_radio = img.width / img.naturalWidth;
-
-          for (let i = 0; i < tmp_labels.length; i++) {
-            let left = w_radio * tmp_boxes[i][0];
-            let top = h_radio * tmp_boxes[i][1];
-            let width = w_radio * (tmp_boxes[i][2] - tmp_boxes[i][0]);
-            let height = h_radio * (tmp_boxes[i][3] - tmp_boxes[i][1]);
-            const rect: iRect = { left, top, width, height };
-            if (tmp_labels[i] == "Figure") {
-              figureArr.value.push("图片");
-              figure_rects.push(rect);
-              CreateRect(fa_canvas, i, left, top, width, height, false, 1);
-            } else if (tmp_labels[i] == "Table_0" || tmp_labels[i] == "Table_std") {
-              tableArr.value.push("表格(" + tmp_labels[i] + ")");
-              table_rects.push(rect);
-              CreateRect(fa_canvas, i, left, top, width, height, false, 2);
-            }
-          }
-          figureArr.value.reverse();
-          tableArr.value.reverse();
-          table_rects.reverse();
-          for (let i = 0; i < figureArr.value.length; i++) {
-            figureArr.value[i] = figureArr.value[i] + " -- " + String(i + 1);
-          }
-          for (let i = 0; i < tableArr.value.length; i++) {
-            tableArr.value[i] = tableArr.value[i] + " -- " + String(i + 1);
-          }
-        }
-        predictTime.value = res.data.cost;
-        loading.value = !loading.value;
-        bugId.value = res.response_id;
-        if (show_predict.value === false)
-          show_predict.value = !show_predict.value;
-      }).catch(function (err) {
-        loading.value = !loading.value;
-        bugId.value = ""
-        predictTime.value = 0
-      });
-    })
-  } else {
-    data.append('image', input_file.value);
-
-    Detection(api, data).then(res => {
-      console.log(res.code)
-      json_result.value = JSON.stringify(res.data, null, 4);
-      console.log(res.data);
-      // rec_result.value = res.data.text.reduce((total: any, cur: any) => total + `<p>${cur}</p>`);
-      figureArr.value.splice(0);
-      tableArr.value.splice(0);
-      let tmp_labels = res.data.labels;
-      if (tmp_labels.length == 0) {
-        alert("no result!");
-      } else {
-        let tmp_boxes = res.data.boxes;
-        const h_radio = img.height / img.naturalHeight;
-        const w_radio = img.width / img.naturalWidth;
-
-        for (let i = 0; i < tmp_labels.length; i++) {
-          let left = w_radio * tmp_boxes[i][0];
-          let top = h_radio * tmp_boxes[i][1];
-          let width = w_radio * (tmp_boxes[i][2] - tmp_boxes[i][0]);
-          let height = h_radio * (tmp_boxes[i][3] - tmp_boxes[i][1]);
-          const rect: iRect = { left, top, width, height };
-          if (tmp_labels[i] == "Figure") {
-            figureArr.value.push("图片");
-            figure_rects.push(rect);
-            CreateRect(fa_canvas, i, left, top, width, height, false, 1);
-          } else if (tmp_labels[i] == "Table_0" || tmp_labels[i] == "Table_std") {
-            tableArr.value.push("表格(" + tmp_labels[i] + ")");
-            table_rects.push(rect);
-            CreateRect(fa_canvas, i, left, top, width, height, false, 2);
-          }
-        }
-        figureArr.value.reverse();
-        tableArr.value.reverse();
-        table_rects.reverse();
-        for (let i = 0; i < figureArr.value.length; i++) {
-          figureArr.value[i] = figureArr.value[i] + " -- " + String(i + 1);
-        }
-        for (let i = 0; i < tableArr.value.length; i++) {
-          tableArr.value[i] = tableArr.value[i] + " -- " + String(i + 1);
+  data.append('image', input_file.value);
+
+  Detection(api_layout_analysis.value, data).then(res => {
+    // console.log(res.code)
+    json_result.value = JSON.stringify(res.data, null, 4);
+    // console.log(res.data);
+    // rec_result.value = res.data.text.reduce((total: any, cur: any) => total + `<p>${cur}</p>`);
+    figureArr.value.splice(0);
+    tableArr.value.splice(0);
+    let tmp_labels = res.data.labels;
+    if (tmp_labels.length == 0) {
+      alert("no result!");
+    } else {
+      let tmp_boxes = res.data.boxes;
+      const h_radio = show_image.value.height / show_image.value.naturalHeight;
+      const w_radio = show_image.value.width / show_image.value.naturalWidth;
+
+      for (let i = 0; i < tmp_labels.length; i++) {
+        let left = w_radio * tmp_boxes[i][0];
+        let top = h_radio * tmp_boxes[i][1];
+        let width = w_radio * (tmp_boxes[i][2] - tmp_boxes[i][0]);
+        let height = h_radio * (tmp_boxes[i][3] - tmp_boxes[i][1]);
+        const rect: iRect = { left, top, width, height };
+        if (tmp_labels[i] == "Figure") {
+          figureArr.value.push("图片");
+          figure_rects.push(rect);
+          CreateRect(fabric_canvas.value, i, left, top, width, height, false, 1);
+        } else if (tmp_labels[i] == "Table_0" || tmp_labels[i] == "Table_std") {
+          tableArr.value.push("表格(" + tmp_labels[i] + ")");
+          table_rects.push(rect);
+          CreateRect(fabric_canvas.value, i, left, top, width, height, false, 2);
         }
       }
-      predictTime.value = res.data.cost;
-      loading.value = !loading.value;
-      bugId.value = res.response_id;
-      if (show_predict.value === false)
-        show_predict.value = !show_predict.value;
-    }).catch(function (err) {
-      loading.value = !loading.value;
-      bugId.value = ""
-      predictTime.value = 0
-    });
-  }
+      figureArr.value.reverse();
+      tableArr.value.reverse();
+      table_rects.reverse();
+      for (let i = 0; i < figureArr.value.length; i++) {
+        figureArr.value[i] = figureArr.value[i] + " -- " + String(i + 1);
+      }
+      for (let i = 0; i < tableArr.value.length; i++) {
+        tableArr.value[i] = tableArr.value[i] + " -- " + String(i + 1);
+      }
+    }
+    predictTime.value = res.data.cost;
+    loading.value = !loading.value;
+    bugId.value = res.response_id;
+    if (show_predict.value === false)
+      show_predict.value = !show_predict.value;
+  }).catch(function (err) {
+    loading.value = !loading.value;
+    bugId.value = ""
+    predictTime.value = 0
+  });
 };
 
 const submitBug = async () => {
@@ -456,7 +194,7 @@ const submitBug = async () => {
     return;
   }
 
-  SubmitBug(api, bugId.value).then(res => {
+  SubmitBug(api_layout_analysis.value, bugId.value).then(res => {
     console.log(res.code, res.data)
   }).catch(function (err) {
     console.log(err)
@@ -464,89 +202,44 @@ const submitBug = async () => {
   });
 };
 
+onMounted(async () => {
+  console.log('layout analysis mounted')
+  input_file.value = undefined
+})
+
 async function figureHandleClick(index: any, item: any, rects: any) {
   figureSelectedItem.value = index;
   tableSelectedItem.value = -1;
-  let objects = fa_canvas.getObjects();
+  let objects = fabric_canvas.value.getObjects();
   for (let i = 0; i < objects.length; i++) {
     if (objects[i].name === 'high') {
       // 找到名为 rectName 的矩形元素,执行删除操作等
-      fa_canvas.remove(objects[i]);
+      fabric_canvas.value.remove(objects[i]);
       break;
     }
   }
-  CreateRect(fa_canvas, index, rects[index].left, rects[index].top, rects[index].width, rects[index].height, true, 1);
+  CreateRect(fabric_canvas.value, index, rects[index].left, rects[index].top, rects[index].width, rects[index].height, true, 1);
 }
 
 async function tableHandleClick(index: any, item: any, rects: any) {
   tableSelectedItem.value = index;
   figureSelectedItem.value = -1;
-  let objects = fa_canvas.getObjects();
+  let objects = fabric_canvas.value.getObjects();
   for (let i = 0; i < objects.length; i++) {
     if (objects[i].name === 'high') {
       // 找到名为 rectName 的矩形元素,执行删除操作等
-      fa_canvas.remove(objects[i]);
+      fabric_canvas.value.remove(objects[i]);
       break;
     }
   }
-  CreateRect(fa_canvas, index, rects[index].left, rects[index].top, rects[index].width, rects[index].height, true, 2);
+  CreateRect(fabric_canvas.value, index, rects[index].left, rects[index].top, rects[index].width, rects[index].height, true, 2);
 }
 </script>
 
 <style scoped>
-#canvas {
-  position: absolute;
-  top: 0;
-  left: 0;
-  z-index: 0;
-  /* 设置Canvas的层级,使其显示在图像之上 */
-  background-color: transparent;
-}
-
-#show-img {
-  position: absolute;
-  top: 0;
-  left: 0;
-  z-index: 0;
-}
-
-.demo-image__placeholder .block {
-  padding: 30px 0;
-  text-align: center;
-  border-right: solid 1px var(--el-border-color);
-  display: inline-block;
-  width: 50%;
-  box-sizing: border-box;
-  vertical-align: top;
-}
-
-.demo-image__placeholder .demonstration {
-  display: block;
-  color: var(--el-text-color-secondary);
-  font-size: 14px;
-  margin-bottom: 20px;
-}
-
-.demo-image__placeholder .el-image {
-  padding: 0 5px;
-  max-width: 300px;
-  max-height: 200px;
-}
-
-.demo-image__placeholder.image-slot {
-  display: flex;
-  justify-content: center;
-  align-items: center;
+.page {
   width: 100%;
   height: 100%;
-  background: var(--el-fill-color-light);
-  color: var(--el-text-color-secondary);
-  font-size: 14px;
-}
-
-.demo-image__placeholder .dot {
-  animation: dot 2s infinite steps(3, start);
-  overflow: hidden;
 }
 
 .place {
@@ -555,18 +248,8 @@ async function tableHandleClick(index: any, item: any, rects: any) {
   border-right: solid 1px #ccc;
 }
 
-.show-area {
-  width: 100%;
-}
-
 .small-title {
   justify-content: space-between;
   align-items: center;
 }
-
-.page-tool-item {
-  padding: 8px 15px;
-  padding-left: 10px;
-  cursor: pointer;
-}
 </style>

+ 57 - 248
src/pages/main/views/ImageProcess/magicColor.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-row :gutter="20">
+  <el-row :gutter="20" class="page">
     <el-col :span="12" class="place">
       <el-row class="small-title">
         <h2>图像锐化增强</h2>
@@ -7,282 +7,96 @@
       <el-row style="color: gray; font-size: small;">
         <p>V1 主要针对文档图片,去阴影效果较好</p>
       </el-row>
+      <el-row>
+        <ShowImage :show-src-image=true />
+      </el-row>
+      <el-row>
+        <FileUpload />
+      </el-row>
       <el-row style="color: gray; font-size: small;">
-        <h4>支持jpg, png, bmp, pdf等文件格式</h4>
+        <h4>支持jpg, png, bmp, pdf等文件格式,点击灰色区域或者直接拖拽文件至灰色区域上传文件</h4>
       </el-row>
-      <div class="common-layout">
-        <el-upload class="upload-demo" drag :before-upload="beforeUpload" multiple>
-          <el-icon class="el-icon--upload"><upload-filled /></el-icon>
-          <div class="el-upload__text">
-            Drop file here or <em>click to upload</em>
-          </div>
-          <template #tip>
-            <div class="el-upload__tip">
-              {{ fileName }}
-            </div>
-          </template>
-        </el-upload>
+      <el-row style="position: absolute;">
+        <PdfPreview />
         <el-button type="primary" @click="predict" :loading="loading">Predict</el-button>
-      </div>
-      <div v-show="is_pdf">
-        <el-row>
-          <el-button-group>
-            <el-button type="primary" :icon="ArrowLeft" @click="prePage">上一页</el-button>
-            <el-button type="primary" @click="nextPage">
-              下一页<el-icon class="el-icon--right">
-                <ArrowRight />
-              </el-icon>
-            </el-button>
-          </el-button-group>
-          <div class="page-tool-item">{{ state.pageNum }}/{{ state.numPages }}</div>
-          <el-container>
-            <el-input type="number" v-model="pdf_page"></el-input>
-            <el-button type="primary" @click="SetPdfPage" plain>页面跳转</el-button>
-          </el-container>
-        </el-row>
-      </div>
-      <el-row>
-        <img id="show-img" class="show-area" />
       </el-row>
-      <canvas id="canvas" style="display: none;"></canvas>
     </el-col>
     <el-col :span="12" class="place">
       <el-row class="small-title">
         <h2 style="margin-right: 100;">推理结果展示</h2>
-        <el-button type="danger" @click="submitBug" disabled>提交bug</el-button>
+        <!-- <el-button type="danger" @click="submitBug" disabled>提交bug</el-button> -->
       </el-row>
-      <el-row style="color: gray; font-size: small;">
-        <p></p>
-      </el-row>
-      <el-row style="color: gray; font-size: small;">
-        <h4></h4>
-      </el-row>
-      <div>
-        <h4></h4>
-        <h4></h4>
+      <div style="margin-top: 43px;">
+        <ShowImage :show-src-image=false />
       </div>
-      <el-row class="small-title">
-        <h4></h4>
-        <h4></h4>
-      </el-row>
-      <el-row>
-        <img id="res-img" class="show-area" />
-        <section> 耗时:{{ predictTime }} ms</section>
-      </el-row>
+      <section> 耗时:{{ predictTime }} ms</section>
     </el-col>
   </el-row>
 </template>
 
 <script lang="ts" setup>
 import { IMMagicColor, SubmitBug } from '../../../../api/api'
-import { reactive, ref } from 'vue'
-import { onMounted } from "vue";
-import {
-  ArrowLeft,
-  ArrowRight,
-  UploadFilled
-} from '@element-plus/icons-vue'
-import { createLoadingTask } from "vue3-pdfjs/esm"; // 获得总页数
+import { ref, onMounted } from 'vue'
 
-import { storeToRefs } from 'pinia'
-import { useServerIpStore } from '../../../../store/ServerIp';
-import { useServerPortStore } from '../../../../store/ServerPort';
-
-const si = useServerIpStore();
-const { server_ip } = storeToRefs(si);
-const sp = useServerPortStore();
-const { server_port } = storeToRefs(sp);
-
-const api = "/v1/image_process/magic_color";
-
-let loadingTask: any;
-const pdf_page = ref(1);
-const pdf_img: any = ref("")
-
-const state = reactive({
-  source: "", //预览pdf文件地址
-  pageNum: 1, //当前页面
-  numPages: 0, // 总页数
-});
-
-function dataURLtoBlob(dataURL: any) {
-  var arr = dataURL.split(','),
-    mime = arr[0].match(/:(.*?);/)[1],
-    bstr = atob(arr[1]),
-    n = bstr.length,
-    u8arr = new Uint8Array(n);
-  while (n--) {
-    u8arr[n] = bstr.charCodeAt(n);
-  }
-  return new Blob([u8arr], { type: mime });
-}
-
-function getPdfImage(index: number) {
-  loadingTask.promise.then((pdf: any) => {
-    state.numPages = pdf.numPages;
-    pdf.getPage(index).then((page: any) => {
-      const viewport = page.getViewport({ scale: 2.0 })
-      canvas.value.height = viewport.height;
-      canvas.value.width = viewport.width;
-      const destWidth = 398;
-      canvas.value.style.width = destWidth + 'px';
-      canvas.value.style.height = destWidth * (viewport.height / viewport.width) + 'px';
-      const ctx = canvas.value.getContext('2d');
-      page.render({
-        canvasContext: ctx,
-        viewport,
-      });
-      canvas.value.toBlob(function (blob) {
-        pdf_img.value = dataURLtoBlob(canvas.value.toDataURL('images/png', 1.0))
-        const showImg = document.getElementById("show-img") as HTMLImageElement;
-        showImg.src = canvas.value.toDataURL('images/png', 1.0);
-        showImg.onload = () => {
-          console.log(canvas.value.toDataURL('images/png', 1.0))
-        }
-      });
-    })
-  });
-}
-
-function SetPdfPage() {
-  if (pdf_page.value >= 1 && pdf_page.value <= state.numPages) {
-    console.log(pdf_page.value)
-    state.pageNum = Number(pdf_page.value);
-    getPdfImage(state.pageNum);
-  } else {
-    console.log(pdf_page.value)
-    alert('输入的pdf页面无效!')
-  }
-}
+import FileUpload from '../../../../components/FileUpload.vue'
+import ShowImage from '../../../../components/ShowImage.vue'
+import PdfPreview from '../../../../components/PdfPreview.vue'
 
-function prePage() {
-  if (state.pageNum > 1) {
-    state.pageNum -= 1;
-    getPdfImage(state.pageNum);
-  }
-}
-
-function nextPage() {
-  if (state.pageNum < state.numPages) {
-    state.pageNum += 1;
-    getPdfImage(state.pageNum);
-  }
-}
-
-// 构建 File 对象
-function blobToFile(blob: any, fileName: any) {
-  blob.lastModifiedDate = new Date();
-  blob.name = fileName;
-  return blob;
-}
+import { storeToRefs } from 'pinia'
+import { useServerStore } from '../../../../store/Server';
+import { useCanvasImgStore } from '../../../../store/CanvasImg';
 
-async function convertCanvasToFile(canvas: HTMLCanvasElement, fileName: any) {
-  // 将 Canvas 转为 Blob 对象
-  const blob = await new Promise(resolve => canvas.toBlob(blob => {
-    resolve(blob);
-  }, pdf_img.value.type, 1.0));
-  // 手动构造 File 对象
-  let file = null;
-  try {
-    file = new File([pdf_img.value], fileName, { type: pdf_img.value.type });
-  } catch (e) {
-    // Safari 浏览器不支持直接通过 new File() 创建文件对象,需要手动构造
-    const rawFile = blobToFile(blob, fileName);
-    file = Object.assign(rawFile, { lastModifiedDate: new Date(), name: fileName });
-  }
-  return file;
-}
+const si = useServerStore();
+const { server_ip, server_port, api_magic_color } = storeToRefs(si);
+const my_canvas = useCanvasImgStore();
+const { input_file, res_image } = storeToRefs(my_canvas);
 
 let loading = ref(false)
 const fileName = ref(null as unknown as string);
 let bugId = ref("");
 let predictTime = ref(0)
-const is_pdf = ref(false);
-const canvas = ref(null as unknown as HTMLCanvasElement);
-const res_image: any = ref();
-
-const input_file = ref(null as unknown as File)
-
-onMounted(async () => {
-  canvas.value = document.getElementById("canvas") as HTMLCanvasElement;
-  res_image.value = document.getElementById("res-img") as HTMLImageElement;
-});
-
-const beforeUpload = (file: File): boolean | Promise<boolean> => {
-  const showImg = document.getElementById("show-img") as HTMLImageElement;
-
-  const post_ = file.name.substring(file.name.lastIndexOf("."), file.name.length).toLowerCase();
-  if (post_ == ".pdf") {
-    state.pageNum = 1;
-    state.source = URL.createObjectURL(file);
-    is_pdf.value = true
-    loadingTask = createLoadingTask(state.source);
-    getPdfImage(state.pageNum);
-  } else
-    if (post_ == ".jpg" || post_ == ".png" || post_ == ".bmp" || post_ == ".jpeg") {
-      showImg.src = URL.createObjectURL(file);
-      input_file.value = file;
-      is_pdf.value = false
-    } else {
-      alert('不支持的文件格式!')
-      fileName.value = ''
-    }
-  fileName.value = file.name
-  return true
-}
 
 const predict = () => {
+  fileName.value = ''
+  fileName.value = input_file.value?.name
   if (fileName.value == undefined || fileName.value == '') {
     alert('请上传图片!')
     return;
   }
-
   loading.value = !loading.value
   var data = new FormData();
 
-  if (is_pdf.value) {
-    const file: any = convertCanvasToFile(canvas.value, "pdf.png").then(result => {
-      console.log(result)
-      data.append('image', result);
-      IMMagicColor(api, data).then(res => {
-        res_image.value.src = res.data.image
-        predictTime.value = res.data.cost
-        bugId.value = res.response_id;
-        loading.value = !loading.value
-      }).catch(function (err) {
-        loading.value = !loading.value;
-        bugId.value = ""
-        predictTime.value = 0
-      });
-    })
-  } else {
-    data.append('image', input_file.value);
-
-    IMMagicColor(api, data).then(res => {
-      res_image.value.src = res.data.image
-      predictTime.value = res.data.cost
-      bugId.value = res.response_id;
-      loading.value = !loading.value
-    }).catch(function (err) {
-      loading.value = !loading.value;
-      bugId.value = ""
-      predictTime.value = 0
-    });
-  }
-}
-
-const submitBug = async () => {
-  if (bugId.value == undefined || bugId.value == "") {
-    alert('请先预测结果!')
-    return;
-  }
+  data.append('image', input_file.value);
 
-  SubmitBug(api, bugId.value).then(res => {
-    console.log(res.code, res.data)
+  IMMagicColor(api_magic_color.value, data).then(res => {
+    res_image.value.src = res.data.image
+    predictTime.value = res.data.cost
+    bugId.value = res.response_id;
+    loading.value = !loading.value
   }).catch(function (err) {
-    console.log(err)
+    loading.value = !loading.value;
+    bugId.value = ""
+    predictTime.value = 0
   });
-};
+}
+
+onMounted(async () => {
+  console.log('magic color mounted')
+  input_file.value = undefined
+})
+
+// const submitBug = async () => {
+//   if (bugId.value == undefined || bugId.value == "") {
+//     alert('请先预测结果!')
+//     return;
+//   }
+
+//   SubmitBug(api, bugId.value).then(res => {
+//     console.log(res.code, res.data)
+//   }).catch(function (err) {
+//     console.log(err)
+//   });
+// };
 </script>
 
 <style scoped>
@@ -292,7 +106,8 @@ const submitBug = async () => {
   border-right: solid 1px #ccc;
 }
 
-.show-area {
+.page {
+  height: 100%;
   width: 100%;
 }
 
@@ -300,10 +115,4 @@ const submitBug = async () => {
   justify-content: space-between;
   align-items: center;
 }
-
-.page-tool-item {
-  padding: 8px 15px;
-  padding-left: 10px;
-  cursor: pointer;
-}
 </style>

+ 92 - 384
src/pages/main/views/Recognize/ocr.vue

@@ -1,7 +1,7 @@
 <!--  -->
 <template>
-  <el-row :gutter="20">
-    <el-col :span="8" class="place">
+  <el-row :gutter="20" class="page">
+    <el-col :span="12" class="place">
       <el-row class="small-title">
         <h2>通用文字识别</h2>
       </el-row>
@@ -9,57 +9,24 @@
         <p>支持识别图片/通过领先的深度学习技术,对各种表格,图片,文档、证件、面单等多种通用场景进行快速、精准的检测和识别,支持简体中文/繁体中文/英文/西欧主流语言等多种种语言,同时支持印刷体、手写体、倾斜、折叠、旋转等。</p>
       </el-row>
       <el-row style="color: gray; font-size: small;">
-        <h4>支持jpg, png, bmp, pdf等文件格式</h4>
+        <h4>支持jpg, png, bmp, pdf等文件格式,点击灰色区域或者直接拖拽文件至灰色区域上传文件</h4>
       </el-row>
-      <div class="common-layout">
-        <el-upload class="upload-demo" drag :before-upload="beforeUpload" multiple>
-          <el-icon class="el-icon--upload"><upload-filled /></el-icon>
-          <div class="el-upload__text">
-            Drop file here or <em>click to upload</em>
-          </div>
-          <template #tip>
-            <div class="el-upload__tip">
-              {{ fileName }}
-            </div>
-          </template>
-        </el-upload>
-        <OcrLangList />
-        <el-button type="primary" @click="predict" :loading="loading">Predict</el-button>
-      </div>
-      <div v-show="is_pdf">
-        <el-row>
-          <el-button-group>
-            <el-button type="primary" :icon="ArrowLeft" @click="prePage">上一页</el-button>
-            <el-button type="primary" @click="nextPage">
-              下一页<el-icon class="el-icon--right">
-                <ArrowRight />
-              </el-icon>
-            </el-button>
-          </el-button-group>
-          <div class="page-tool-item">{{ state.pageNum }}/{{ state.numPages }}</div>
-          <el-container>
-            <el-input type="number" v-model="pdf_page"></el-input>
-            <el-button type="primary" @click="SetPdfPage" plain>页面跳转</el-button>
-          </el-container>
-        </el-row>
-      </div>
-    </el-col>
-    <el-col :span="8" class="place">
-      <el-row class="small-title">
-        <h2>文字区域检测</h2>
+      <el-row>
+        <ShowImage :show-src-image=true />
       </el-row>
       <el-row>
-        <div>
-          <img id="show-img" class="show-area" />
-          <canvas id="canvas"></canvas>
-          <canvas id="img_canvas" style="display: none;"></canvas>
-        </div>
+        <FileUpload />
+      </el-row>
+      <OcrLangList />
+      <el-row style="position: absolute;">
+        <PdfPreview />
+        <el-button type="primary" @click="predict" :loading="loading">Predict</el-button>
       </el-row>
     </el-col>
-    <el-col :span="8" class="place">
+    <el-col :span="12" class="place">
       <el-row class="small-title">
         <h2 style="margin-right: 0;">识别结果展示</h2>
-        <el-button type="danger" @click="submitBug" disabled>提交bug</el-button>
+        <!-- <el-button type="danger" @click="submitBug" disabled>提交bug</el-button> -->
       </el-row>
       <div class="demo-collapse">
         <el-collapse v-model="activeName" accordion>
@@ -90,156 +57,22 @@
 <script lang='ts' setup>
 import { OcrRec, SubmitBug } from '../../../../api/api'
 import { storeToRefs } from 'pinia'
-import OcrLangList from '../../../../components/OcrLangList.vue'
-import { useOcrLangStore } from '../../../../store/OcrLang';
 import { fabric } from 'fabric';
-import { reactive, ref } from 'vue'
-import { onMounted } from "vue";
-import useClipboard from 'vue-clipboard3'
-import { createLoadingTask } from "vue3-pdfjs/esm"; // 获得总页数
-import {
-  ArrowLeft,
-  ArrowRight,
-  UploadFilled
-} from '@element-plus/icons-vue'
-import { useServerIpStore } from '../../../../store/ServerIp';
-import { useServerPortStore } from '../../../../store/ServerPort';
-
-const si = useServerIpStore();
-const { server_ip } = storeToRefs(si);
-const sp = useServerPortStore();
-const { server_port } = storeToRefs(sp);
-
-const api = "/v1/ocr";
-
-let loadingTask: any;
-
-const is_pdf = ref(false);
-const pdf_page = ref(1);
-const pdf_img: any = ref("")
-
-const state = reactive({
-  source: "", //预览pdf文件地址
-  pageNum: 1, //当前页面
-  numPages: 0, // 总页数
-});
-
-function dataURLtoBlob(dataURL: any) {
-  var arr = dataURL.split(','),
-    mime = arr[0].match(/:(.*?);/)[1],
-    bstr = atob(arr[1]),
-    n = bstr.length,
-    u8arr = new Uint8Array(n);
-  while (n--) {
-    u8arr[n] = bstr.charCodeAt(n);
-  }
-  return new Blob([u8arr], { type: mime });
-}
-
-function getPdfImage(index: number) {
-  // console.log(index, state.pageNum)
-  loadingTask.promise.then((pdf: any) => {
-    state.numPages = pdf.numPages;
-    pdf.getPage(index).then((page: any) => {
-      const viewport = page.getViewport({ scale: 2.0 })
-      img_canvas.value.height = viewport.height;
-      img_canvas.value.width = viewport.width;
-      canvas.value.height = viewport.height;
-      canvas.value.width = viewport.width;
-      const destWidth = 398;
-      img_canvas.value.style.width = destWidth + 'px';
-
-      img_canvas.value.style.height = destWidth * (viewport.height / viewport.width) + 'px';
-      canvas.value.style.width = destWidth + 'px';
-
-      canvas.value.style.height = destWidth * (viewport.height / viewport.width) + 'px';
-      const ctx = img_canvas.value.getContext('2d');
-      page.render({
-        canvasContext: ctx,
-        viewport,
-      });
-      img_canvas.value.toBlob(function (blob) {
-        pdf_img.value = dataURLtoBlob(img_canvas.value.toDataURL('images/png', 1.0))
-        const showImg = document.getElementById("show-img") as HTMLImageElement;
-        showImg.src = img_canvas.value.toDataURL('images/png', 1.0);
-        showImg.onload = () => {
-          canvas.value.width = showImg.width;
-          canvas.value.height = showImg.height;
-          if (fa_canvas != null) {
-            fa_canvas.dispose();
-            fa_canvas = null;
-          }
-          fa_canvas = new fabric.Canvas(canvas.value);
-          fa_canvas.clear()
-          rects.splice(0)
-          selectedItem.value = -1;
-        }
-      });
-    })
-  });
-}
-
-function SetPdfPage() {
-  if (pdf_page.value >= 1 && pdf_page.value <= state.numPages) {
-    console.log(pdf_page.value)
-    state.pageNum = Number(pdf_page.value);
-    if (fa_canvas && typeof fa_canvas.dispose === 'function') {
-      fa_canvas.dispose();
-      fa_canvas = null;
-    }
-    getPdfImage(state.pageNum);
-  } else {
-    console.log(pdf_page.value)
-    alert('输入的pdf页面无效!')
-  }
-}
-
-function prePage() {
-  if (state.pageNum > 1) {
-    state.pageNum -= 1;
-    if (fa_canvas && typeof fa_canvas.dispose === 'function') {
-      fa_canvas.dispose();
-      fa_canvas = null;
-    }
-    getPdfImage(state.pageNum);
-  }
-}
-
-function nextPage() {
-  if (state.pageNum < state.numPages) {
-    state.pageNum += 1;
-    if (fa_canvas && typeof fa_canvas.dispose === 'function') {
-      fa_canvas.dispose();
-      fa_canvas = null;
-    }
-    getPdfImage(state.pageNum);
-  }
-}
-
-// 构建 File 对象
-function blobToFile(blob: any, fileName: any) {
-  blob.lastModifiedDate = new Date();
-  blob.name = fileName;
-  return blob;
-}
+import { reactive, ref, onMounted } from 'vue'
+import { useOcrLangStore } from '../../../../store/OcrLang';
+import { useServerStore } from '../../../../store/Server';
+import { useCanvasImgStore } from '../../../../store/CanvasImg';
 
-async function convertCanvasToFile(canvas: HTMLCanvasElement, fileName: any) {
-  // 将 Canvas 转为 Blob 对象
-  const blob = await new Promise(resolve => canvas.toBlob(blob => {
-    resolve(blob);
-  }, pdf_img.value.type, 1.0));
-  // 手动构造 File 对象
-  let file = null;
-  try {
-    file = new File([pdf_img.value], fileName, { type: pdf_img.value.type });
-  } catch (e) {
-    // Safari 浏览器不支持直接通过 new File() 创建文件对象,需要手动构造
-    const rawFile = blobToFile(blob, fileName);
-    file = Object.assign(rawFile, { lastModifiedDate: new Date(), name: fileName });
-  }
-  return file;
-}
 
+import OcrLangList from '../../../../components/OcrLangList.vue'
+import FileUpload from '../../../../components/FileUpload.vue'
+import ShowImage from '../../../../components/ShowImage.vue'
+import PdfPreview from '../../../../components/PdfPreview.vue'
+
+const si = useServerStore();
+const { server_ip, server_port, api_ocr } = storeToRefs(si);
+const my_canvas = useCanvasImgStore();
+const { input_file, show_image, show_canvas, fabric_canvas } = storeToRefs(my_canvas);
 const ol = useOcrLangStore();
 const { ocr_lang } = storeToRefs(ol);
 
@@ -247,24 +80,15 @@ let loading = ref(false)
 let show_predict = ref(false)
 let predictTime = ref(0)
 const fileName = ref(null as unknown as string);
-const canvas = ref(null as unknown as HTMLCanvasElement);
-const img_canvas = ref(null as unknown as HTMLCanvasElement);
 
 let selectedItem = ref(-1)
 
 let recArr: any = ref([])
-
-let fa_canvas: any = null;
 const rec_result = ref("");
 let bugId = ref("");
-
 const activeName = ref('2')
 const json_result = ref("");
 
-const { toClipboard } = useClipboard()
-
-const input_file = ref(null as unknown as File)
-
 interface iRect {
   left: number,
   top: number,
@@ -274,53 +98,6 @@ interface iRect {
 
 let rects: any = []
 
-onMounted(async () => {
-  canvas.value = document.getElementById("canvas") as HTMLCanvasElement;
-  img_canvas.value = document.getElementById("img_canvas") as HTMLCanvasElement;
-});
-
-const beforeUpload = (file: File): boolean | Promise<boolean> => {
-  if (fa_canvas != null) {
-    fa_canvas.dispose();
-    fa_canvas = null;
-  }
-
-  const showImg = document.getElementById("show-img") as HTMLImageElement;
-
-  const post_ = file.name.substring(file.name.lastIndexOf("."), file.name.length).toLowerCase();
-  if (post_ == ".pdf") {
-    state.pageNum = 1;
-    state.source = URL.createObjectURL(file);
-    is_pdf.value = true
-    loadingTask = createLoadingTask(state.source);
-    getPdfImage(state.pageNum);
-  } else
-    if (post_ == ".jpg" || post_ == ".png" || post_ == ".bmp" || post_ == ".jpeg") {
-      showImg.src = URL.createObjectURL(file);
-      input_file.value = file;
-      showImg.onload = () => {
-        canvas.value.width = showImg.width;
-        canvas.value.height = showImg.height;
-        if (fa_canvas != null) {
-          fa_canvas.dispose();
-          fa_canvas = null;
-        }
-        fa_canvas = new fabric.Canvas(canvas.value);
-        fa_canvas.clear()
-        rects.splice(0)
-        selectedItem.value = -1;
-      }
-      is_pdf.value = false
-    } else {
-      alert('不支持的文件格式!')
-      fileName.value = ''
-    }
-  fileName.value = file.name
-  if (show_predict.value === true)
-    show_predict.value = !show_predict.value;
-  return true
-}
-
 type RectWithId = fabric.Rect & { id: number };
 
 function CreateRect(canvas: any, i: number, left: number, top: number, width: number, height: number, highlight: boolean) {
@@ -339,21 +116,23 @@ function CreateRect(canvas: any, i: number, left: number, top: number, width: nu
   rect.set('id', i);
   rect.on('mouseup', function () {
     selectedItem.value = i;
-    let objects = fa_canvas.getObjects();
+    let objects = fabric_canvas.value.getObjects();
     for (let i = 0; i < objects.length; i++) {
       if (objects[i].name === 'high') {
         // 找到名为 rectName 的矩形元素,执行删除操作等
-        fa_canvas.remove(objects[i]);
+        fabric_canvas.value.remove(objects[i]);
         break;
       }
     }
-    CreateRect(fa_canvas, i, rects[i].left, rects[i].top, rects[i].width, rects[i].height, true);
+    CreateRect(fabric_canvas.value, i, rects[i].left, rects[i].top, rects[i].width, rects[i].height, true);
   });
   canvas.add(rect);
-  // canvas.renderAll();
 }
 
 const predict = async () => {
+  // my_canvas.reset_images()
+  fileName.value = ''
+  fileName.value = input_file.value?.name
   if (fileName.value == undefined || fileName.value == '') {
     alert('请上传图片!')
     return;
@@ -363,161 +142,96 @@ const predict = async () => {
     return;
   }
 
-  if (fa_canvas != null) {
-    fa_canvas.dispose();
-    fa_canvas = null;
-    fa_canvas = new fabric.Canvas(canvas.value);
+  if (fabric_canvas.value != null) {
+    fabric_canvas.value.dispose();
+    fabric_canvas.value = null;
+    fabric_canvas.value = new fabric.Canvas(show_canvas.value);
   }
   rects.splice(0)
 
-  const img = document.getElementById("show-img") as HTMLImageElement;
-
   loading.value = !loading.value
   var data = new FormData();
   data.append('lang', ocr_lang.value);
-
-  if (is_pdf.value) {
-    const file: any = convertCanvasToFile(img_canvas.value, "pdf.png").then(result => {
-      console.log(result)
-      data.append('image', result);
-      OcrRec(api, data).then(res => {
-        console.log(res.code)
-        json_result.value = JSON.stringify(res.data, null, 4);
-        rec_result.value = res.data.text.reduce((total: any, cur: any) => total + `<p>${cur}</p>`);
-        recArr.value.splice(0);
-        let tmp_text = res.data.text;
-        if (tmp_text.length == 0) {
-          alert('未检测到结果!');
-        } else {
-          for (let i = 0; i < tmp_text.length; i++) {
-            recArr.value.push(tmp_text[i]);
-          }
-        }
-        let tmp_boxes = res.data.boxes;
-        const h_radio = img.height / img.naturalHeight;
-        const w_radio = img.width / img.naturalWidth;
-        for (let i = 0; i < tmp_boxes.length; i++) {
-          let left = w_radio * tmp_boxes[i][0];
-          let top = h_radio * tmp_boxes[i][1];
-          let width = w_radio * (tmp_boxes[i][2] - tmp_boxes[i][0]);
-          let height = h_radio * (tmp_boxes[i][5] - tmp_boxes[i][1]);
-          const rect: iRect = { left, top, width, height };
-          rects.push(rect);
-          CreateRect(fa_canvas, i, left, top, width, height, false);
-        }
-        predictTime.value = res.data.cost;
-        loading.value = !loading.value;
-        bugId.value = res.response_id;
-        if (show_predict.value === false)
-          show_predict.value = !show_predict.value;
-      }).catch(function (err) {
-        loading.value = !loading.value;
-        bugId.value = ""
-        predictTime.value = 0
-      });
-    })
-  } else {
-    data.append('image', input_file.value);
-
-    OcrRec(api, data).then(res => {
-      console.log(res.code)
-      json_result.value = JSON.stringify(res.data, null, 4);
-      rec_result.value = res.data.text.reduce((total: any, cur: any) => total + `<p>${cur}</p>`);
-      recArr.value.splice(0);
-      let tmp_text = res.data.text;
-      if (tmp_text.length == 0) {
-        alert('未检测到结果!');
-      } else {
-        for (let i = 0; i < tmp_text.length; i++) {
-          recArr.value.push(tmp_text[i]);
-        }
-      }
-      let tmp_boxes = res.data.boxes;
-      const h_radio = img.height / img.naturalHeight;
-      const w_radio = img.width / img.naturalWidth;
-      for (let i = 0; i < tmp_boxes.length; i++) {
-        let left = w_radio * tmp_boxes[i][0];
-        let top = h_radio * tmp_boxes[i][1];
-        let width = w_radio * (tmp_boxes[i][2] - tmp_boxes[i][0]);
-        let height = h_radio * (tmp_boxes[i][5] - tmp_boxes[i][1]);
-        const rect: iRect = { left, top, width, height };
-        rects.push(rect);
-        CreateRect(fa_canvas, i, left, top, width, height, false);
+  data.append('image', input_file.value);
+
+  OcrRec(api_ocr.value, data).then(res => {
+    // console.log(res.code)
+    json_result.value = JSON.stringify(res.data, null, 4);
+    rec_result.value = res.data.text.reduce((total: any, cur: any) => total + `<p>${cur}</p>`);
+    recArr.value.splice(0);
+    let tmp_text = res.data.text;
+    if (tmp_text.length == 0) {
+      alert('未检测到结果!');
+    } else {
+      for (let i = 0; i < tmp_text.length; i++) {
+        recArr.value.push(tmp_text[i]);
       }
-      predictTime.value = res.data.cost;
-      loading.value = !loading.value;
-      bugId.value = res.response_id;
-      if (show_predict.value === false)
-        show_predict.value = !show_predict.value;
-    }).catch(function (err) {
-      loading.value = !loading.value;
-      bugId.value = ""
-      predictTime.value = 0
-    });
-  }
+    }
+    let tmp_boxes = res.data.boxes;
+    const h_radio = show_image.value.height / show_image.value.naturalHeight;
+    const w_radio = show_image.value.width / show_image.value.naturalWidth;
+    for (let i = 0; i < tmp_boxes.length; i++) {
+      let left = w_radio * tmp_boxes[i][0];
+      let top = h_radio * tmp_boxes[i][1];
+      let width = w_radio * (tmp_boxes[i][2] - tmp_boxes[i][0]);
+      let height = h_radio * (tmp_boxes[i][5] - tmp_boxes[i][1]);
+      const rect: iRect = { left, top, width, height };
+      rects.push(rect);
+      CreateRect(fabric_canvas.value, i, left, top, width, height, false);
+    }
+    predictTime.value = res.data.cost;
+    loading.value = !loading.value;
+    bugId.value = res.response_id;
+    if (show_predict.value === false)
+      show_predict.value = !show_predict.value;
+  }).catch(function (err) {
+    loading.value = !loading.value;
+    bugId.value = ""
+    predictTime.value = 0
+  });
 };
 
-const submitBug = async () => {
-  if (bugId.value == undefined || bugId.value == "") {
-    alert('请先预测结果!')
-    return;
-  }
+// const submitBug = async () => {
+//   if (bugId.value == undefined || bugId.value == "") {
+//     alert('请先预测结果!')
+//     return;
+//   }
 
 
-  SubmitBug(api, bugId.value).then(res => {
-    console.log(res.code, res.data)
-  }).catch(function (err) {
-    console.log(err)
-  });
-};
+//   SubmitBug(api, bugId.value).then(res => {
+//     console.log(res.code, res.data)
+//   }).catch(function (err) {
+//     console.log(err)
+//   });
+// };
 
 async function handleClick(index: any, item: any) {
   selectedItem.value = index;
-  let objects = fa_canvas.getObjects();
+  let objects = fabric_canvas.value.getObjects();
   for (let i = 0; i < objects.length; i++) {
     if (objects[i].name === 'high') {
       // 找到名为 rectName 的矩形元素,执行删除操作等
-      fa_canvas.remove(objects[i]);
+      fabric_canvas.value.remove(objects[i]);
       break;
     }
   }
-  CreateRect(fa_canvas, index, rects[index].left, rects[index].top, rects[index].width, rects[index].height, true);
-}
-
-function copy(index: any) {
-  try {
-    toClipboard(recArr.value[index])
-    console.log('Copied to clipboard')
-  } catch (e) {
-    console.error(e)
-  }
+  CreateRect(fabric_canvas.value, index, rects[index].left, rects[index].top, rects[index].width, rects[index].height, true);
 }
 
+onMounted(async () => {
+  console.log('ocr mounted')
+  input_file.value = undefined
+})
 </script>
 
 <style scoped lang="less">
-#canvas {
-  position: absolute;
-  top: 0;
-  left: 0;
-  z-index: 0;
-  /* 设置Canvas的层级,使其显示在图像之上 */
-  background-color: transparent;
-}
-
-#show-img {
-  position: absolute;
-  top: 0;
-  left: 0;
-  z-index: 0;
-}
-
 .small-title {
   justify-content: space-between;
   align-items: center;
 }
 
-.show-area {
+.page {
+  height: 100%;
   width: 100%;
 }
 
@@ -526,10 +240,4 @@ function copy(index: any) {
   margin-left: auto;
   border-right: solid 1px #ccc;
 }
-
-.page-tool-item {
-  padding: 8px 15px;
-  padding-left: 10px;
-  cursor: pointer;
-}
 </style>

+ 76 - 282
src/pages/main/views/Recognize/tableRec.vue

@@ -1,7 +1,7 @@
 <!--  -->
 <template>
-  <el-row :gutter="20">
-    <el-col :span="8" class="place">
+  <el-row :gutter="20" class="page">
+    <el-col :span="10" class="place">
       <el-row class="small-title">
         <h2>通用表格识别</h2>
       </el-row>
@@ -9,50 +9,24 @@
         <p>支持识别图片/PDF格式文档中的表格内容,包括有线表格、无线表格、合并单元格表格,同时支持单张图片内的多个表格内容识别,返回各表格的表头表尾内容、单元格文字内容及其行列位置信息。</p>
       </el-row>
       <el-row style="color: gray; font-size: small;">
-        <h4>支持jpg, png, bmp, pdf等文件格式</h4>
+        <h4>支持jpg, png, bmp, pdf等文件格式,点击灰色区域或者直接拖拽文件至灰色区域上传文件</h4>
+      </el-row>
+      <el-row>
+        <ShowImage :show-src-image=true />
       </el-row>
-      <div class="common-layout">
-        <el-upload class="upload-demo" drag :before-upload="beforeUpload" multiple>
-          <el-icon class="el-icon--upload"><upload-filled /></el-icon>
-          <div class="el-upload__text">
-            Drop file here or <em>click to upload</em>
-          </div>
-          <template #tip>
-            <div class="el-upload__tip">
-              {{ fileName }}
-            </div>
-          </template>
-        </el-upload>
-        <OcrLangList />
-        <el-button type="primary" @click="predict" :loading="loading">Predict</el-button>
-      </div>
-      <div v-show="is_pdf">
-        <el-row>
-          <el-button-group>
-            <el-button type="primary" :icon="ArrowLeft" @click="prePage">上一页</el-button>
-            <el-button type="primary" @click="nextPage">
-              下一页<el-icon class="el-icon--right">
-                <ArrowRight />
-              </el-icon>
-            </el-button>
-          </el-button-group>
-          <div class="page-tool-item">{{ state.pageNum }}/{{ state.numPages }}</div>
-          <el-container>
-            <el-input type="number" v-model="pdf_page"></el-input>
-            <el-button type="primary" @click="SetPdfPage" plain>页面跳转</el-button>
-          </el-container>
-        </el-row>
-      </div>
       <el-row>
-        <!-- 用于展示图片 -->
-        <img id="show-img" class="show-area" />
+        <FileUpload />
+      </el-row>
+      <OcrLangList />
+      <el-row style="position: absolute;">
+        <PdfPreview />
+        <el-button type="primary" @click="predict" :loading="loading">Predict</el-button>
       </el-row>
-      <canvas id="canvas" style="display: none;"></canvas>
     </el-col>
-    <el-col :span="16" class="place">
+    <el-col :span="14" class="place">
       <el-row class="small-title">
         <h2 style="margin-right: 100;">识别结果展示</h2>
-        <el-button type="danger" @click="submitBug" disabled>提交bug</el-button>
+        <!-- <el-button type="danger" @click="submitBug" disabled>提交bug</el-button> -->
       </el-row>
       <div class="demo-collapse">
         <el-collapse v-model="activeName" accordion>
@@ -64,13 +38,15 @@
             </li>
           </el-collapse-item>
           <el-collapse-item title="识别结果" name="2">
-            <li v-for="(item, index) in htmlArr" :key="index">
-              <el-scrollbar height="auto">
-                <div style="display: flex;">
-                  <span v-html="item"></span>
-                </div>
-              </el-scrollbar>
-            </li>
+            <el-scrollbar height="700px">
+              <li v-for="(item, index) in htmlArr" :key="index">
+                <el-scrollbar height="auto" style="overflow-y: auto;overflow-x: auto;">
+                  <div style="display: flex;">
+                    <span v-html="item"></span>
+                  </div>
+                </el-scrollbar>
+              </li>
+            </el-scrollbar>
           </el-collapse-item>
         </el-collapse>
       </div>
@@ -82,92 +58,42 @@
 </template>
 
 <script lang='ts' setup>
-import { reactive, ref } from 'vue'
-import { onMounted } from "vue";
+import { reactive, ref, onMounted } from 'vue'
 import { TableRec, SubmitBug } from '../../../../api/api'
-import { createLoadingTask } from "vue3-pdfjs/esm"; // 获得总页数
 import { storeToRefs } from 'pinia'
-import OcrLangList from '../../../../components/OcrLangList.vue'
 import { useOcrLangStore } from '../../../../store/OcrLang';
 import { useBugIdStore } from '../../../../store/BugID';
-import {
-  ArrowLeft,
-  ArrowRight,
-  UploadFilled
-} from '@element-plus/icons-vue'
-import { useServerIpStore } from '../../../../store/ServerIp';
-import { useServerPortStore } from '../../../../store/ServerPort';
+import { useServerStore } from '../../../../store/Server';
+import { useCanvasImgStore } from '../../../../store/CanvasImg';
 
-const si = useServerIpStore();
-const { server_ip } = storeToRefs(si);
-const sp = useServerPortStore();
-const { server_port } = storeToRefs(sp);
+import OcrLangList from '../../../../components/OcrLangList.vue'
+import FileUpload from '../../../../components/FileUpload.vue'
+import ShowImage from '../../../../components/ShowImage.vue'
+import PdfPreview from '../../../../components/PdfPreview.vue'
 
-const api = "/v1/table_rec";
+const si = useServerStore();
+const { server_ip, server_port, api_table_rec } = storeToRefs(si);
 
 const ol = useOcrLangStore();
 const { ocr_lang } = storeToRefs(ol);
 
+const my_canvas = useCanvasImgStore();
+const { input_file } = storeToRefs(my_canvas);
+
 const bi = useBugIdStore();
 const { bug_id } = storeToRefs(bi);
 
-// const si = useServerIpStore()
-// const { server_ip } = storeToRefs(si);
-
-const state = reactive({
-  source: "", //预览pdf文件地址
-  pageNum: 1, //当前页面
-  numPages: 0, // 总页数
-});
-
 let loading = ref(false)
 let predictTime = ref(0)
 const fileName = ref(null as unknown as string);
-const pdf_page = ref(1);
-
-const is_pdf = ref(false);
-
 const activeName = ref('2')
 
-const pdf_img: any = ref("")
-
-const canvas = ref(null as unknown as HTMLCanvasElement);
-
 let jsonArr: any = ref([])
 let htmlArr: any = ref([])
 
-let loadingTask: any;
-
-const input_file = ref(null as unknown as File)
-
-onMounted(async () => {
-  canvas.value = document.getElementById("canvas") as HTMLCanvasElement;
-});
-
-const beforeUpload = (file: File): boolean | Promise<boolean> => {
-  const showImg = document.getElementById("show-img") as HTMLImageElement;
-
-  const post_ = file.name.substring(file.name.lastIndexOf("."), file.name.length).toLowerCase();
-  if (post_ == ".pdf") {
-    state.pageNum = 1;
-    state.source = URL.createObjectURL(file);
-    is_pdf.value = true
-    loadingTask = createLoadingTask(state.source);
-    getPdfImage(state.pageNum);
-  } else
-    if (post_ == ".jpg" || post_ == ".png" || post_ == ".bmp" || post_ == ".jpeg") {
-      showImg.src = URL.createObjectURL(file);
-      input_file.value = file;
-      is_pdf.value = false
-    } else {
-      alert('不支持的文件格式!')
-      fileName.value = ''
-    }
-  fileName.value = file.name
-  return true
-}
-
 const predict = async () => {
+  fileName.value = ''
+  fileName.value = input_file.value?.name
   if (fileName.value == undefined || fileName.value == '') {
     alert('请上传图片!')
     return;
@@ -181,165 +107,50 @@ const predict = async () => {
 
   var data = new FormData();
   data.append('lang', ocr_lang.value);
+  data.append('image', input_file.value);
   // console.log('is_pdf' + is_pdf.value)
-  if (is_pdf.value) {
-    const file: any = convertCanvasToFile(canvas.value, "pdf.png").then(result => {
-      console.log(result)
-      data.append('image', result);
-      TableRec(api, data).then(res => {
-        console.log(api)
-        bug_id.value = res.response_id;
-        predictTime.value = res.data.cost;
-        jsonArr.value.splice(0);
-        let tmp_json = res.data.json_items;
-        for (let i = 0; i < tmp_json.length; i++) {
-          jsonArr.value.push(JSON.stringify(tmp_json[i], null, 4));
-        }
-
-        htmlArr.value.splice(0);
-        let tmp_html = res.data.html_items;
-        for (let i = 0; i < tmp_html.length; i++) {
-          htmlArr.value.push(tmp_html[i]);
-        }
-        loading.value = false
-      }).catch(function (err) {
-        loading.value = false
-        bug_id.value = ""
-        predictTime.value = 0
-      });
-    })
-  } else {
-    // console.log(file)
-    data.append('image', input_file.value);
-    TableRec(api, data).then(res => {
-      console.log(api)
-      bug_id.value = res.response_id;
-      predictTime.value = res.data.cost;
-      jsonArr.value.splice(0);
-      let tmp_json = res.data.json_items;
-      for (let i = 0; i < tmp_json.length; i++) {
-        jsonArr.value.push(JSON.stringify(tmp_json[i], null, 4));
-      }
-
-      htmlArr.value.splice(0);
-      let tmp_html = res.data.html_items;
-      for (let i = 0; i < tmp_html.length; i++) {
-        htmlArr.value.push(tmp_html[i]);
-      }
-      loading.value = false
-    }).catch(function (err) {
-      loading.value = false
-      bug_id.value = ""
-      predictTime.value = 0
-    });
-  }
-};
-
-function SetPdfPage() {
-  if (pdf_page.value >= 1 && pdf_page.value <= state.numPages) {
-    console.log(pdf_page.value)
-    state.pageNum = Number(pdf_page.value);
-    getPdfImage(state.pageNum);
-  } else {
-    console.log(pdf_page.value)
-    alert('输入的pdf页面无效!')
-  }
-}
-
-
-const submitBug = async () => {
-  if (bug_id.value == undefined || bug_id.value == "") {
-    alert('请先预测结果!')
-    return;
-  }
+  // console.log(file)
+  TableRec(api_table_rec.value, data).then(res => {
+    bug_id.value = res.response_id;
+    predictTime.value = res.data.cost;
+    jsonArr.value.splice(0);
+    let tmp_json = res.data.json_items;
+    for (let i = 0; i < tmp_json.length; i++) {
+      jsonArr.value.push(JSON.stringify(tmp_json[i], null, 4));
+    }
 
-  SubmitBug(api, bug_id.value).then(res => {
-    console.log(res.code, res.data)
+    htmlArr.value.splice(0);
+    let tmp_html = res.data.html_items;
+    for (let i = 0; i < tmp_html.length; i++) {
+      htmlArr.value.push(tmp_html[i]);
+    }
+    loading.value = false
   }).catch(function (err) {
-    console.log(err)
-    // loading.value = !loading.value;
+    loading.value = false
+    bug_id.value = ""
+    predictTime.value = 0
   });
 };
 
-async function convertCanvasToFile(canvas: HTMLCanvasElement, fileName: any) {
-  // 将 Canvas 转为 Blob 对象
-  const blob = await new Promise(resolve => canvas.toBlob(blob => {
-    resolve(blob);
-  }, pdf_img.value.type, 1.0));
-  // 手动构造 File 对象
-  let file = null;
-  try {
-    file = new File([pdf_img.value], fileName, { type: pdf_img.value.type });
-  } catch (e) {
-    // Safari 浏览器不支持直接通过 new File() 创建文件对象,需要手动构造
-    const rawFile = blobToFile(blob, fileName);
-    file = Object.assign(rawFile, { lastModifiedDate: new Date(), name: fileName });
-  }
-  return file;
-}
 
-// 构建 File 对象
-function blobToFile(blob: any, fileName: any) {
-  blob.lastModifiedDate = new Date();
-  blob.name = fileName;
-  return blob;
-}
-
-function dataURLtoBlob(dataURL: any) {
-  var arr = dataURL.split(','),
-    mime = arr[0].match(/:(.*?);/)[1],
-    bstr = atob(arr[1]),
-    n = bstr.length,
-    u8arr = new Uint8Array(n);
-  while (n--) {
-    u8arr[n] = bstr.charCodeAt(n);
-  }
-  return new Blob([u8arr], { type: mime });
-}
+// const submitBug = async () => {
+//   if (bug_id.value == undefined || bug_id.value == "") {
+//     alert('请先预测结果!')
+//     return;
+//   }
 
-function getPdfImage(index: number) {
-  // console.log(index, state.pageNum)
-  loadingTask.promise.then((pdf: any) => {
-    state.numPages = pdf.numPages;
-    pdf.getPage(index).then((page: any) => {
-      const viewport = page.getViewport({ scale: 2.0 })
-      canvas.value.height = viewport.height;
-      canvas.value.width = viewport.width;
-      const destWidth = 398;
-      canvas.value.style.width = destWidth + 'px';
-
-      canvas.value.style.height = destWidth * (viewport.height / viewport.width) + 'px';
-      const ctx = canvas.value.getContext('2d');
-      page.render({
-        canvasContext: ctx,
-        viewport,
-      });
-      canvas.value.toBlob(function (blob) {
-        pdf_img.value = dataURLtoBlob(canvas.value.toDataURL('images/png', 1.0))
-        const showImg = document.getElementById("show-img") as HTMLImageElement;
-        showImg.src = canvas.value.toDataURL('images/png', 1.0);
-        showImg.onload = () => {
-          console.log(canvas.value.toDataURL('images/png', 1.0))
-        }
-      });
-    })
-  });
-}
-
-function prePage() {
-  if (state.pageNum > 1) {
-    state.pageNum -= 1;
-    getPdfImage(state.pageNum);
-  }
-}
-
-function nextPage() {
-  if (state.pageNum < state.numPages) {
-    state.pageNum += 1;
-    getPdfImage(state.pageNum);
-  }
-}
+//   SubmitBug(api, bug_id.value).then(res => {
+//     console.log(res.code, res.data)
+//   }).catch(function (err) {
+//     console.log(err)
+//     // loading.value = !loading.value;
+//   });
+// };
 
+onMounted(async () => {
+  console.log('table rec mounted')
+  input_file.value = undefined
+})
 </script>
 
 <style scoped lang="less">
@@ -348,31 +159,14 @@ function nextPage() {
   align-items: center;
 }
 
-.show-area {
+.page {
   width: 100%;
+  height: 100%;
 }
 
 .place {
-  margin-right: auto;
-  margin-left: auto;
+  // margin-right: auto;
+  // margin-left: auto;
   border-right: solid 1px #ccc;
 }
-
-.page-tool-item {
-  padding: 8px 15px;
-  padding-left: 10px;
-  cursor: pointer;
-}
-
-.input_text {
-  background-color: #F5F5F5;
-  border: 1px solid #CCCCCC;
-  padding: 10px;
-  margin: 10px;
-  border-radius: 5px;
-  font-size: 14px;
-  color: #333333;
-  text-align: left;
-  box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.25);
-}
 </style>

+ 36 - 20
src/pages/main/views/homePage.vue

@@ -1,22 +1,35 @@
 <template>
-  <h1>DocumentAI</h1>
-
-  <h3>build version</h3>
-  <p class="italic">{{ version }}</p>
-
-  <h3>build tag</h3>
-  <p class="italic">{{ build_tag }}</p>
-
-
-  <h3>模型信息</h3>
-  <p>模型个数:{{ model_num }}</p>
-  <el-table :data="model_data" style="width: 100%">
-    <el-table-column prop="key" label="Key" width="auto" />
-    <el-table-column prop="type" label="Type" width="auto" />
-    <el-table-column prop="subtype" label="Subtype" width="auto" />
-    <el-table-column prop="format" label="Format" width="auto" />
-    <el-table-column prop="version" label="Version" width="auto" />
-  </el-table>
+  <el-row :gutter="20"> 
+    <el-col>
+      <h1>DocumentAI</h1>
+    </el-col> 
+    <el-col>
+      <h3>build version</h3>
+    </el-col>
+    <el-col>
+      <p class="italic">{{ version }}</p>
+    </el-col>
+    <el-col>
+      <h3>build tag</h3>
+    </el-col>
+    <el-col>
+      <p class="italic">{{ build_tag }}</p>
+    </el-col>
+  
+    <el-col>
+      <h3>模型信息</h3>
+    </el-col>
+    <el-col>
+      <p>模型个数:{{ model_num }}</p>
+    </el-col>
+    <el-table :data="model_data" style="width: 100%">
+      <el-table-column prop="key" label="Key" width="auto" />
+      <el-table-column prop="type" label="Type" width="auto" />
+      <el-table-column prop="subtype" label="Subtype" width="auto" />
+      <el-table-column prop="format" label="Format" width="auto" />
+      <el-table-column prop="version" label="Version" width="auto" />
+    </el-table>
+  </el-row>
 </template>
 
 <script setup lang="ts">
@@ -24,21 +37,24 @@ import { onMounted, ref } from "vue";
 import { GetBuildTag, GetModelInfo } from '../../../api/api'
 import { storeToRefs } from 'pinia'
 import { useVersionStore } from '../../../store/Version';
+import { useServerStore } from '../../../store/Server';
 
 const vr = useVersionStore();
 const { build_tag, model_info, version } = storeToRefs(vr);
+const si = useServerStore();
+const { api_build_tag, api_model_info } = storeToRefs(si);
 
 let model_num = ref(0)
 let model_data: any = ref([])
 
 onMounted(async () => {
   if (build_tag.value == "") {
-    GetBuildTag("/v1/buildTag").then(res => {
+    GetBuildTag(api_build_tag.value).then(res => {
       build_tag.value = res;
     })
   }
   if (model_info.value == "") {
-    GetModelInfo("/v1/modelInfo").then(res => {
+    GetModelInfo(api_model_info.value).then(res => {
       model_info.value = res;
       const model = JSON.parse(model_info.value)
       model_num.value = model['model_num']

+ 28 - 6
src/store/CanvasImg.ts

@@ -1,8 +1,30 @@
-import { defineStore } from 'pinia';
-import { ref } from 'vue'
+import { defineStore } from "pinia";
+import { ref } from "vue";
 
-export const useCanvasImgStore = defineStore('canvas_img', () => {
-  const canvas_img = ref(HTMLCanvasElement)
+export const useCanvasImgStore = defineStore("canvas_img", () => {
+  const show_image: any = ref(null as unknown as HTMLImageElement);
+  const res_image: any = ref(null as unknown as HTMLImageElement);
+  const show_canvas: any = ref(null as unknown as HTMLCanvasElement);
+  const hide_canvas: any = ref(null as unknown as HTMLCanvasElement);
+  const input_file: any = ref(null as unknown as File);
+  const fabric_canvas: any = ref(null);
 
-  return { canvas_img }
-})
+  const reset_images =  () => {
+    show_image.value = ''; // 清空 show_image 对象
+    res_image.value = ''; // 清空 res_image 对象
+    show_canvas.value.getContext('2d').clearRect(0, 0, show_canvas.value.width, show_canvas.value.height);
+    hide_canvas.value = ''; // 清空 hide_canvas 对象
+    input_file.value = undefined; // 清空 input_file 对象
+    // fabric_canvas.value?.dispose(); // 释放 fabric_canvas 对象占用的资源
+  }
+
+  return {
+    show_image,
+    res_image,
+    show_canvas,
+    hide_canvas,
+    fabric_canvas,
+    input_file,
+    reset_images
+  };
+});

+ 10 - 0
src/store/PdfProperty.ts

@@ -0,0 +1,10 @@
+import { defineStore } from 'pinia';
+import { ref } from 'vue'
+
+export const usePdfProperty = defineStore('PdfProperty', () => {
+  const is_pdf = ref(false)
+  const pdf_source = ref("")
+  const old_pdf_source = ref("")
+
+  return { is_pdf, pdf_source, old_pdf_source }
+})

+ 20 - 0
src/store/Server.ts

@@ -0,0 +1,20 @@
+import { defineStore } from 'pinia';
+import { ref } from 'vue'
+
+export const useServerStore = defineStore('server', () => {
+  const tmp_ip = "http://192.168.10.84:80"
+  const server_ip = ref("localhost")
+  const server_port = ref(":7896")
+  const api_dewarp = ref("")
+  const api_version = ref(tmp_ip + "/v1/version")
+  const api_build_tag = ref(tmp_ip + "/v1/buildTag")
+  const api_model_info = ref(tmp_ip + "/v1/modelInfo")
+  const api_magic_color = ref(tmp_ip + "/v1/image_process/magic_color")
+  const api_ocr = ref(tmp_ip + "/v1/ocr")
+  const api_table_rec = ref(tmp_ip + "/v1/table_rec")
+  const api_layout_analysis = ref(tmp_ip + "/v1/detection/layout_parser")
+  const api_seal_detection = ref("")
+
+  return { server_ip, server_port, api_dewarp, api_layout_analysis, api_magic_color, 
+           api_ocr, api_seal_detection, api_table_rec, api_build_tag, api_model_info, api_version }
+})

+ 0 - 8
src/store/ServerIp.ts

@@ -1,8 +0,0 @@
-import { defineStore } from 'pinia';
-import { ref } from 'vue'
-
-export const useServerIpStore = defineStore('server_ip', () => {
-  const server_ip = ref("localhost")
-
-  return { server_ip }
-})

+ 0 - 8
src/store/ServerPort.ts

@@ -1,8 +0,0 @@
-import { defineStore } from 'pinia';
-import { ref } from 'vue'
-
-export const useServerPortStore = defineStore('server_port', () => {
-  const server_port = ref(":7896")
-
-  return { server_port }
-})