فهرست منبع

feat: 优化打包流程,4普定制开发

bill 1 سال پیش
والد
کامیت
091e63e370
38فایلهای تغییر یافته به همراه2296 افزوده شده و 635 حذف شده
  1. 68 0
      generate-ts.ts
  2. 8 4
      package.json
  3. 493 69
      pnpm-lock.yaml
  4. 4 3
      src/App.vue
  5. 82 0
      src/app/4dmap/example/index.vue
  6. 969 0
      src/app/4dmap/example/storeData.json
  7. 10 3
      src/app/4dmap/index.ts
  8. 63 0
      src/app/4dmap/path.ts
  9. 225 0
      src/app/4dmap/point.ts
  10. 92 209
      src/app/4dmap/polygons.ts
  11. 1 3
      src/components/query-board/index.vue
  12. 0 0
      src/app/liantong/example/storeData.json
  13. 6 0
      src/app/liantong/index.ts
  14. 10 0
      src/board/helper/entity.ts
  15. 2 1
      src/board/index.ts
  16. 27 27
      src/board/packages/container.ts
  17. 35 20
      src/board/packages/entity.ts
  18. 0 1
      src/board/packages/poi/edit-poi.ts
  19. 16 7
      src/board/packages/whole-line/editable/edit-whole-line.ts
  20. 16 73
      src/board/packages/whole-line/editable/pen-whole-line.ts
  21. 11 0
      src/board/packages/whole-line/service/whole-line-base.ts
  22. 11 4
      src/board/packages/whole-line/service/whole-line-edit.ts
  23. 7 3
      src/board/packages/whole-line/service/whole-line-helper.ts
  24. 0 2
      src/board/packages/whole-line/service/whole-line-tear-merge.ts
  25. 4 3
      src/board/packages/whole-line/style.ts
  26. 3 2
      src/board/packages/whole-line/view/whole-line.ts
  27. 2 1
      src/board/plugins/bound-plugin.ts
  28. 1 0
      src/board/plugins/camera-plugin.ts
  29. 2 2
      src/board/register.ts
  30. 1 0
      src/board/shared/act.ts
  31. 4 5
      src/board/shared/entity-utils.ts
  32. 65 43
      src/board/shared/shape-mose.ts
  33. 14 2
      src/board/shared/util.ts
  34. 18 7
      src/board/type.d.ts
  35. 0 126
      src/components/query-board/streData-merge.json
  36. 5 7
      tsconfig.json
  37. 3 1
      tsconfig.node.json
  38. 18 7
      vite.config.ts

+ 68 - 0
generate-ts.ts

@@ -0,0 +1,68 @@
+import { resolve } from "path";
+import { writeFileSync, unlinkSync, rmSync } from "fs";
+import { execSync } from "child_process";
+import dts from "rollup-plugin-dts";
+import tsResolve from "@rollup/plugin-node-resolve";
+import * as Rollup from "rollup";
+
+const generateTs = (app: string) => {
+  const enter = app ? `src/app/${app}/` : `src/board/`;
+  const enterPath = resolve(__dirname, enter, `index.ts`);
+  const tsconfigPath = resolve(__dirname, "./tsconfig.prod.json");
+  const outPath = resolve(__dirname, "dist/tempts");
+  const tsconfig = {
+    compilerOptions: {
+      target: "es2015",
+      useDefineForClassFields: true,
+      module: "ESNext",
+      lib: ["es2015", "DOM", "DOM.Iterable"],
+      skipLibCheck: true,
+      /* Bundler mode */
+      moduleResolution: "Node",
+      resolveJsonModule: true,
+      isolatedModules: true,
+      jsx: "preserve",
+      /* Linting */
+      noUnusedLocals: true,
+      noUnusedParameters: true,
+      noFallthroughCasesInSwitch: true,
+      allowImportingTsExtensions: true,
+      emitDeclarationOnly: true, // 只输出声明文件(ts 产物)
+      declaration: true, // 自动生成声明文件
+      declarationDir: outPath, // 声明文件生成的目录
+      incremental: false, // 启用增量编译
+    },
+    include: [enterPath, "src/vite-env.d.ts"],
+    references: [
+      {
+        path: "./tsconfig.node.json",
+      },
+    ],
+  };
+  writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2));
+  try {
+    execSync(`cd ${__dirname} && npm run tsc`, { stdio: "inherit" });
+    unlinkSync(tsconfigPath);
+  } catch (error) {
+    console.error("Error executing command:", error);
+    throw error;
+  }
+
+  return outPath;
+};
+
+const mergeTs = async (app: string, input: string) => {
+  const name = app ? app : "board";
+  const enter = resolve(input, `${app ? `app/${app}/` : ``}index.d.ts`);
+  const out = resolve(__dirname, `./dist/${name}.d.ts`);
+  const bundle = await Rollup.rollup({
+    input: enter,
+    plugins: [dts(), tsResolve()],
+  });
+  await bundle.write({ file: out, format: "es" });
+  rmSync(input, { recursive: true, force: true });
+};
+
+export const generateDTS = async (app: string) => {
+  await mergeTs(app, generateTs(app));
+};

+ 8 - 4
package.json

@@ -6,14 +6,17 @@
   "main": "./src/board/index.ts",
   "scripts": {
     "dev": "vite",
-    "build-quisk": "vue-tsc && vite build",
-    "build": "npm run build-quisk ./ ",
-    "preview": "vite preview"
+    "tsc": "vue-tsc -p tsconfig.prod.json",
+    "build": "vite build ./"
   },
   "dependencies": {
+    "@rollup/plugin-node-resolve": "^15.2.3",
     "element-plus": "^2.7.3",
     "konva": "^9.3.6",
     "mitt": "^3.0.1",
+    "ol": "^9.2.4",
+    "rollup": "^4.18.0",
+    "rollup-plugin-dts": "^6.1.1",
     "sass": "^1.77.1",
     "stateshot": "^1.3.5",
     "three": "^0.164.1",
@@ -23,8 +26,9 @@
     "@types/node": "^20.14.5",
     "@types/three": "^0.164.0",
     "@vitejs/plugin-vue": "^5.0.4",
+    "dts-bundle": "^0.7.3",
     "typescript": "^5.2.2",
-    "vite": "^5.2.0",
+    "vite": "^5.2.11",
     "vue-tsc": "^2.0.6"
   }
 }

+ 493 - 69
pnpm-lock.yaml

@@ -1,24 +1,33 @@
 lockfileVersion: 5.4
 
 specifiers:
+  '@rollup/plugin-node-resolve': ^15.2.3
   '@types/node': ^20.14.5
   '@types/three': ^0.164.0
   '@vitejs/plugin-vue': ^5.0.4
+  dts-bundle: ^0.7.3
   element-plus: ^2.7.3
   konva: ^9.3.6
   mitt: ^3.0.1
+  ol: ^9.2.4
+  rollup: ^4.18.0
+  rollup-plugin-dts: ^6.1.1
   sass: ^1.77.1
   stateshot: ^1.3.5
   three: ^0.164.1
   typescript: ^5.2.2
-  vite: ^5.2.0
+  vite: ^5.2.11
   vue: ^3.4.21
   vue-tsc: ^2.0.6
 
 dependencies:
+  '@rollup/plugin-node-resolve': 15.2.3_rollup@4.18.0
   element-plus: 2.7.3_vue@3.4.27
   konva: 9.3.6
   mitt: 3.0.1
+  ol: 9.2.4
+  rollup: 4.18.0
+  rollup-plugin-dts: 6.1.1_kvrf5kykmw4i6hziq5unr5euja
   sass: 1.77.1
   stateshot: 1.3.5
   three: 0.164.1
@@ -28,12 +37,23 @@ devDependencies:
   '@types/node': 20.14.5
   '@types/three': 0.164.0
   '@vitejs/plugin-vue': 5.0.4_vite@5.2.11+vue@3.4.27
+  dts-bundle: 0.7.3
   typescript: 5.4.5
   vite: 5.2.11_rptimmxdh7ke3ahl2eyquqnrlq
   vue-tsc: 2.0.17_typescript@5.4.5
 
 packages:
 
+  /@babel/code-frame/7.24.7:
+    resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==}
+    engines: {node: '>=6.9.0'}
+    requiresBuild: true
+    dependencies:
+      '@babel/highlight': 7.24.7
+      picocolors: 1.0.1
+    dev: false
+    optional: true
+
   /@babel/helper-string-parser/7.24.1:
     resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==}
     engines: {node: '>=6.9.0'}
@@ -42,6 +62,23 @@ packages:
     resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==}
     engines: {node: '>=6.9.0'}
 
+  /@babel/helper-validator-identifier/7.24.7:
+    resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==}
+    engines: {node: '>=6.9.0'}
+    dev: false
+    optional: true
+
+  /@babel/highlight/7.24.7:
+    resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/helper-validator-identifier': 7.24.7
+      chalk: 2.4.2
+      js-tokens: 4.0.0
+      picocolors: 1.0.1
+    dev: false
+    optional: true
+
   /@babel/parser/7.24.5:
     resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==}
     engines: {node: '>=6.0.0'}
@@ -297,132 +334,153 @@ packages:
   /@jridgewell/sourcemap-codec/1.4.15:
     resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
 
-  /@rollup/rollup-android-arm-eabi/4.17.2:
-    resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==}
+  /@petamoriken/float16/3.8.7:
+    resolution: {integrity: sha512-/Ri4xDDpe12NT6Ex/DRgHzLlobiQXEW/hmG08w1wj/YU7hLemk97c+zHQFp0iZQ9r7YqgLEXZR2sls4HxBf9NA==}
+    dev: false
+
+  /@rollup/plugin-node-resolve/15.2.3_rollup@4.18.0:
+    resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==}
+    engines: {node: '>=14.0.0'}
+    peerDependencies:
+      rollup: ^2.78.0||^3.0.0||^4.0.0
+    peerDependenciesMeta:
+      rollup:
+        optional: true
+    dependencies:
+      '@rollup/pluginutils': 5.1.0_rollup@4.18.0
+      '@types/resolve': 1.20.2
+      deepmerge: 4.3.1
+      is-builtin-module: 3.2.1
+      is-module: 1.0.0
+      resolve: 1.22.8
+      rollup: 4.18.0
+    dev: false
+
+  /@rollup/pluginutils/5.1.0_rollup@4.18.0:
+    resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==}
+    engines: {node: '>=14.0.0'}
+    peerDependencies:
+      rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
+    peerDependenciesMeta:
+      rollup:
+        optional: true
+    dependencies:
+      '@types/estree': 1.0.5
+      estree-walker: 2.0.2
+      picomatch: 2.3.1
+      rollup: 4.18.0
+    dev: false
+
+  /@rollup/rollup-android-arm-eabi/4.18.0:
+    resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==}
     cpu: [arm]
     os: [android]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-android-arm64/4.17.2:
-    resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==}
+  /@rollup/rollup-android-arm64/4.18.0:
+    resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==}
     cpu: [arm64]
     os: [android]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-darwin-arm64/4.17.2:
-    resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==}
+  /@rollup/rollup-darwin-arm64/4.18.0:
+    resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==}
     cpu: [arm64]
     os: [darwin]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-darwin-x64/4.17.2:
-    resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==}
+  /@rollup/rollup-darwin-x64/4.18.0:
+    resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==}
     cpu: [x64]
     os: [darwin]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-linux-arm-gnueabihf/4.17.2:
-    resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==}
+  /@rollup/rollup-linux-arm-gnueabihf/4.18.0:
+    resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==}
     cpu: [arm]
     os: [linux]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-linux-arm-musleabihf/4.17.2:
-    resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==}
+  /@rollup/rollup-linux-arm-musleabihf/4.18.0:
+    resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==}
     cpu: [arm]
     os: [linux]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-linux-arm64-gnu/4.17.2:
-    resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==}
+  /@rollup/rollup-linux-arm64-gnu/4.18.0:
+    resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==}
     cpu: [arm64]
     os: [linux]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-linux-arm64-musl/4.17.2:
-    resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==}
+  /@rollup/rollup-linux-arm64-musl/4.18.0:
+    resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==}
     cpu: [arm64]
     os: [linux]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-linux-powerpc64le-gnu/4.17.2:
-    resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==}
+  /@rollup/rollup-linux-powerpc64le-gnu/4.18.0:
+    resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==}
     cpu: [ppc64]
     os: [linux]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-linux-riscv64-gnu/4.17.2:
-    resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==}
+  /@rollup/rollup-linux-riscv64-gnu/4.18.0:
+    resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==}
     cpu: [riscv64]
     os: [linux]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-linux-s390x-gnu/4.17.2:
-    resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==}
+  /@rollup/rollup-linux-s390x-gnu/4.18.0:
+    resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==}
     cpu: [s390x]
     os: [linux]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-linux-x64-gnu/4.17.2:
-    resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==}
+  /@rollup/rollup-linux-x64-gnu/4.18.0:
+    resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==}
     cpu: [x64]
     os: [linux]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-linux-x64-musl/4.17.2:
-    resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==}
+  /@rollup/rollup-linux-x64-musl/4.18.0:
+    resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==}
     cpu: [x64]
     os: [linux]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-win32-arm64-msvc/4.17.2:
-    resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==}
+  /@rollup/rollup-win32-arm64-msvc/4.18.0:
+    resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==}
     cpu: [arm64]
     os: [win32]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-win32-ia32-msvc/4.17.2:
-    resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==}
+  /@rollup/rollup-win32-ia32-msvc/4.18.0:
+    resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==}
     cpu: [ia32]
     os: [win32]
     requiresBuild: true
-    dev: true
     optional: true
 
-  /@rollup/rollup-win32-x64-msvc/4.17.2:
-    resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==}
+  /@rollup/rollup-win32-x64-msvc/4.18.0:
+    resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==}
     cpu: [x64]
     os: [win32]
     requiresBuild: true
-    dev: true
     optional: true
 
   /@sxzz/popperjs-es/2.11.7:
@@ -433,8 +491,18 @@ packages:
     resolution: {integrity: sha512-kMCNaZCJugWI86xiEHaY338CU5JpD0B97p1j1IKNn/Zto8PgACjQx0UxbHjmOcLl/dDOBnItwD07KmCs75pxtQ==}
     dev: true
 
+  /@types/detect-indent/0.1.30:
+    resolution: {integrity: sha512-AUmj9JHuHTD94slY1WR1VulFxRGC6D1pcNCN0MCulKFyiihvV/28lLS8oRHgfmc2Cxq954J8Vmosa8qzm7PLGQ==}
+    dev: true
+
   /@types/estree/1.0.5:
     resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
+
+  /@types/glob/5.0.30:
+    resolution: {integrity: sha512-ZM05wDByI+WA153sfirJyEHoYYoIuZ7lA2dB/Gl8ymmpMTR78fNRtDMqa7Z6SdH4fZdLWZNRE6mZpx3XqBOrHw==}
+    dependencies:
+      '@types/minimatch': 5.1.2
+      '@types/node': 20.14.5
     dev: true
 
   /@types/lodash-es/4.17.12:
@@ -447,12 +515,28 @@ packages:
     resolution: {integrity: sha512-X+2qazGS3jxLAIz5JDXDzglAF3KpijdhFxlf/V1+hEsOUc+HnWi81L/uv/EvGuV90WY+7mPGFCUDGfQC3Gj95Q==}
     dev: false
 
+  /@types/minimatch/5.1.2:
+    resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
+    dev: true
+
+  /@types/mkdirp/0.3.29:
+    resolution: {integrity: sha512-QRLQpFsIQGO2k8pupga9abfei85GKotAtQ+F6xuQmSGomUt6C52TyMiTFpP8kUwuPKr00gNtu3itLlC6gvI/NA==}
+    dev: true
+
   /@types/node/20.14.5:
     resolution: {integrity: sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==}
     dependencies:
       undici-types: 5.26.5
     dev: true
 
+  /@types/node/8.0.0:
+    resolution: {integrity: sha512-j2tekvJCO7j22cs+LO6i0kRPhmQ9MXaPZ55TzOc1lzkN5b6BWqq4AFjl04s1oRRQ1v5rSe+KEvnLUSTonuls/A==}
+    dev: true
+
+  /@types/resolve/1.20.2:
+    resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
+    dev: false
+
   /@types/stats.js/0.17.3:
     resolution: {integrity: sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==}
     dev: true
@@ -612,6 +696,14 @@ packages:
       - vue
     dev: false
 
+  /ansi-styles/3.2.1:
+    resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+    engines: {node: '>=4'}
+    dependencies:
+      color-convert: 1.9.3
+    dev: false
+    optional: true
+
   /anymatch/3.1.3:
     resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
     engines: {node: '>= 8'}
@@ -631,6 +723,13 @@ packages:
     resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
     engines: {node: '>=8'}
 
+  /brace-expansion/1.1.11:
+    resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+    dependencies:
+      balanced-match: 1.0.2
+      concat-map: 0.0.1
+    dev: true
+
   /brace-expansion/2.0.1:
     resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
     dependencies:
@@ -643,6 +742,21 @@ packages:
     dependencies:
       fill-range: 7.0.1
 
+  /builtin-modules/3.3.0:
+    resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
+    engines: {node: '>=6'}
+    dev: false
+
+  /chalk/2.4.2:
+    resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+    engines: {node: '>=4'}
+    dependencies:
+      ansi-styles: 3.2.1
+      escape-string-regexp: 1.0.5
+      supports-color: 5.5.0
+    dev: false
+    optional: true
+
   /chokidar/3.6.0:
     resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
     engines: {node: '>= 8.10.0'}
@@ -657,10 +771,52 @@ packages:
     optionalDependencies:
       fsevents: 2.3.3
 
+  /color-convert/1.9.3:
+    resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+    dependencies:
+      color-name: 1.1.3
+    dev: false
+    optional: true
+
+  /color-name/1.1.3:
+    resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+    dev: false
+    optional: true
+
+  /color-name/2.0.0:
+    resolution: {integrity: sha512-SbtvAMWvASO5TE2QP07jHBMXKafgdZz8Vrsrn96fiL+O92/FN/PLARzUW5sKt013fjAprK2d2iCn2hk2Xb5oow==}
+    engines: {node: '>=12.20'}
+    dev: false
+
+  /color-parse/2.0.2:
+    resolution: {integrity: sha512-eCtOz5w5ttWIUcaKLiktF+DxZO1R9KLNY/xhbV6CkhM7sR3GhVghmt6X6yOnzeaM24po+Z9/S1apbXMwA3Iepw==}
+    dependencies:
+      color-name: 2.0.0
+    dev: false
+
+  /color-rgba/3.0.0:
+    resolution: {integrity: sha512-PPwZYkEY3M2THEHHV6Y95sGUie77S7X8v+h1r6LSAPF3/LL2xJ8duUXSrkic31Nzc4odPwHgUbiX/XuTYzQHQg==}
+    dependencies:
+      color-parse: 2.0.2
+      color-space: 2.0.1
+    dev: false
+
+  /color-space/2.0.1:
+    resolution: {integrity: sha512-nKqUYlo0vZATVOFHY810BSYjmCARrG7e5R3UE3CQlyjJTvv5kSSmPG1kzm/oDyyqjehM+lW1RnEt9It9GNa5JA==}
+    dev: false
+
+  /commander/2.20.3:
+    resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+    dev: true
+
   /computeds/0.0.1:
     resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==}
     dev: true
 
+  /concat-map/0.0.1:
+    resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+    dev: true
+
   /csstype/3.1.3:
     resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
 
@@ -672,6 +828,39 @@ packages:
     resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
     dev: true
 
+  /deepmerge/4.3.1:
+    resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
+    engines: {node: '>=0.10.0'}
+    dev: false
+
+  /detect-indent/0.2.0:
+    resolution: {integrity: sha512-C6jyrDu/eGH4KT0ZxAzijiH+ts5YLy7DqGFoDuHGxZjMOdjzRltp3jByySnpFBVIy4Em0ZkLN8tIV6mcREdw5A==}
+    engines: {node: '>=0.10.0'}
+    hasBin: true
+    dependencies:
+      get-stdin: 0.1.0
+      minimist: 0.1.0
+    dev: true
+
+  /dts-bundle/0.7.3:
+    resolution: {integrity: sha512-EEAEuPRk8QyKhoN90NHTh+spSQujkkvOnKWUfuzpmC/fgryiWopL1SegSktx0UsoPfNidIGVDN7/AXpBDBv0WQ==}
+    engines: {node: '>= 0.10.0'}
+    hasBin: true
+    dependencies:
+      '@types/detect-indent': 0.1.30
+      '@types/glob': 5.0.30
+      '@types/mkdirp': 0.3.29
+      '@types/node': 8.0.0
+      commander: 2.20.3
+      detect-indent: 0.2.0
+      glob: 6.0.4
+      mkdirp: 0.5.6
+    dev: true
+
+  /earcut/2.2.4:
+    resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==}
+    dev: false
+
   /element-plus/2.7.3_vue@3.4.27:
     resolution: {integrity: sha512-OaqY1kQ2xzNyRFyge3fzM7jqMwux+464RBEqd+ybRV9xPiGxtgnj/sVK4iEbnKnzQIa9XK03DOIFzoToUhu1DA==}
     peerDependencies:
@@ -736,6 +925,12 @@ packages:
     resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
     dev: false
 
+  /escape-string-regexp/1.0.5:
+    resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+    engines: {node: '>=0.8.0'}
+    dev: false
+    optional: true
+
   /estree-walker/2.0.2:
     resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
 
@@ -756,26 +951,103 @@ packages:
     requiresBuild: true
     optional: true
 
+  /function-bind/1.1.2:
+    resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+    dev: false
+
+  /geotiff/2.1.3:
+    resolution: {integrity: sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==}
+    engines: {node: '>=10.19'}
+    dependencies:
+      '@petamoriken/float16': 3.8.7
+      lerc: 3.0.0
+      pako: 2.1.0
+      parse-headers: 2.0.5
+      quick-lru: 6.1.2
+      web-worker: 1.3.0
+      xml-utils: 1.10.1
+      zstddec: 0.1.0
+    dev: false
+
+  /get-stdin/0.1.0:
+    resolution: {integrity: sha512-/WBu3IaQZxE3bs3BhBmR10ipDY4pjN+U4EZgXULa1eqKA0B/Lka/MVoAqhTVYBkkRlCrEGDOU9itrzIgm9Ksng==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
   /glob-parent/5.1.2:
     resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
     engines: {node: '>= 6'}
     dependencies:
       is-glob: 4.0.3
 
+  /glob/6.0.4:
+    resolution: {integrity: sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==}
+    deprecated: Glob versions prior to v9 are no longer supported
+    dependencies:
+      inflight: 1.0.6
+      inherits: 2.0.4
+      minimatch: 3.1.2
+      once: 1.4.0
+      path-is-absolute: 1.0.1
+    dev: true
+
+  /has-flag/3.0.0:
+    resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+    engines: {node: '>=4'}
+    dev: false
+    optional: true
+
+  /hasown/2.0.2:
+    resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      function-bind: 1.1.2
+    dev: false
+
   /he/1.2.0:
     resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
     hasBin: true
     dev: true
 
+  /ieee754/1.2.1:
+    resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+    dev: false
+
   /immutable/4.3.6:
     resolution: {integrity: sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==}
 
+  /inflight/1.0.6:
+    resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+    deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
+    dependencies:
+      once: 1.4.0
+      wrappy: 1.0.2
+    dev: true
+
+  /inherits/2.0.4:
+    resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+    dev: true
+
   /is-binary-path/2.1.0:
     resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
     engines: {node: '>=8'}
     dependencies:
       binary-extensions: 2.3.0
 
+  /is-builtin-module/3.2.1:
+    resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==}
+    engines: {node: '>=6'}
+    dependencies:
+      builtin-modules: 3.3.0
+    dev: false
+
+  /is-core-module/2.14.0:
+    resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      hasown: 2.0.2
+    dev: false
+
   /is-extglob/2.1.1:
     resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
     engines: {node: '>=0.10.0'}
@@ -786,14 +1058,27 @@ packages:
     dependencies:
       is-extglob: 2.1.1
 
+  /is-module/1.0.0:
+    resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==}
+    dev: false
+
   /is-number/7.0.0:
     resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
     engines: {node: '>=0.12.0'}
 
+  /js-tokens/4.0.0:
+    resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+    dev: false
+    optional: true
+
   /konva/9.3.6:
     resolution: {integrity: sha512-dqR8EbcM0hjuilZCBP6xauQ5V3kH3m9kBcsDkqPypQuRgsXbcXUrxqYxhNbdvKZpYNW8Amq94jAD/C0NY3qfBQ==}
     dev: false
 
+  /lerc/3.0.0:
+    resolution: {integrity: sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==}
+    dev: false
+
   /lodash-es/4.17.21:
     resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
     dev: false
@@ -827,6 +1112,12 @@ packages:
     resolution: {integrity: sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==}
     dev: true
 
+  /minimatch/3.1.2:
+    resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+    dependencies:
+      brace-expansion: 1.1.11
+    dev: true
+
   /minimatch/9.0.4:
     resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==}
     engines: {node: '>=16 || 14 >=14.17'}
@@ -834,10 +1125,25 @@ packages:
       brace-expansion: 2.0.1
     dev: true
 
+  /minimist/0.1.0:
+    resolution: {integrity: sha512-wR5Ipl99t0mTGwLjQJnBjrP/O7zBbLZqvA3aw32DmLx+nXHfWctUjzDjnDx09pX1Po86WFQazF9xUzfMea3Cnw==}
+    dev: true
+
+  /minimist/1.2.8:
+    resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+    dev: true
+
   /mitt/3.0.1:
     resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
     dev: false
 
+  /mkdirp/0.5.6:
+    resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
+    hasBin: true
+    dependencies:
+      minimist: 1.2.8
+    dev: true
+
   /muggle-string/0.4.1:
     resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
     dev: true
@@ -855,10 +1161,52 @@ packages:
     resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==}
     dev: false
 
+  /ol/9.2.4:
+    resolution: {integrity: sha512-bsbu4ObaAlbELMIZWnYEvX4Z9jO+OyCBshtODhDKmqYTPEfnKOX3RieCr97tpJkqWTZvyV4tS9UQDvHoCdxS+A==}
+    dependencies:
+      color-rgba: 3.0.0
+      color-space: 2.0.1
+      earcut: 2.2.4
+      geotiff: 2.1.3
+      pbf: 3.2.1
+      rbush: 3.0.1
+    dev: false
+
+  /once/1.4.0:
+    resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+    dependencies:
+      wrappy: 1.0.2
+    dev: true
+
+  /pako/2.1.0:
+    resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
+    dev: false
+
+  /parse-headers/2.0.5:
+    resolution: {integrity: sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==}
+    dev: false
+
   /path-browserify/1.0.1:
     resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
     dev: true
 
+  /path-is-absolute/1.0.1:
+    resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /path-parse/1.0.7:
+    resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+    dev: false
+
+  /pbf/3.2.1:
+    resolution: {integrity: sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==}
+    hasBin: true
+    dependencies:
+      ieee754: 1.2.1
+      resolve-protobuf-schema: 2.1.0
+    dev: false
+
   /picocolors/1.0.1:
     resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
 
@@ -874,37 +1222,84 @@ packages:
       picocolors: 1.0.1
       source-map-js: 1.2.0
 
+  /protocol-buffers-schema/3.6.0:
+    resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==}
+    dev: false
+
+  /quick-lru/6.1.2:
+    resolution: {integrity: sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==}
+    engines: {node: '>=12'}
+    dev: false
+
+  /quickselect/2.0.0:
+    resolution: {integrity: sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==}
+    dev: false
+
+  /rbush/3.0.1:
+    resolution: {integrity: sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==}
+    dependencies:
+      quickselect: 2.0.0
+    dev: false
+
   /readdirp/3.6.0:
     resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
     engines: {node: '>=8.10.0'}
     dependencies:
       picomatch: 2.3.1
 
-  /rollup/4.17.2:
-    resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==}
+  /resolve-protobuf-schema/2.1.0:
+    resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==}
+    dependencies:
+      protocol-buffers-schema: 3.6.0
+    dev: false
+
+  /resolve/1.22.8:
+    resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+    hasBin: true
+    dependencies:
+      is-core-module: 2.14.0
+      path-parse: 1.0.7
+      supports-preserve-symlinks-flag: 1.0.0
+    dev: false
+
+  /rollup-plugin-dts/6.1.1_kvrf5kykmw4i6hziq5unr5euja:
+    resolution: {integrity: sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==}
+    engines: {node: '>=16'}
+    peerDependencies:
+      rollup: ^3.29.4 || ^4
+      typescript: ^4.5 || ^5.0
+    dependencies:
+      magic-string: 0.30.10
+      rollup: 4.18.0
+      typescript: 5.4.5
+    optionalDependencies:
+      '@babel/code-frame': 7.24.7
+    dev: false
+
+  /rollup/4.18.0:
+    resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==}
     engines: {node: '>=18.0.0', npm: '>=8.0.0'}
     hasBin: true
     dependencies:
       '@types/estree': 1.0.5
     optionalDependencies:
-      '@rollup/rollup-android-arm-eabi': 4.17.2
-      '@rollup/rollup-android-arm64': 4.17.2
-      '@rollup/rollup-darwin-arm64': 4.17.2
-      '@rollup/rollup-darwin-x64': 4.17.2
-      '@rollup/rollup-linux-arm-gnueabihf': 4.17.2
-      '@rollup/rollup-linux-arm-musleabihf': 4.17.2
-      '@rollup/rollup-linux-arm64-gnu': 4.17.2
-      '@rollup/rollup-linux-arm64-musl': 4.17.2
-      '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2
-      '@rollup/rollup-linux-riscv64-gnu': 4.17.2
-      '@rollup/rollup-linux-s390x-gnu': 4.17.2
-      '@rollup/rollup-linux-x64-gnu': 4.17.2
-      '@rollup/rollup-linux-x64-musl': 4.17.2
-      '@rollup/rollup-win32-arm64-msvc': 4.17.2
-      '@rollup/rollup-win32-ia32-msvc': 4.17.2
-      '@rollup/rollup-win32-x64-msvc': 4.17.2
+      '@rollup/rollup-android-arm-eabi': 4.18.0
+      '@rollup/rollup-android-arm64': 4.18.0
+      '@rollup/rollup-darwin-arm64': 4.18.0
+      '@rollup/rollup-darwin-x64': 4.18.0
+      '@rollup/rollup-linux-arm-gnueabihf': 4.18.0
+      '@rollup/rollup-linux-arm-musleabihf': 4.18.0
+      '@rollup/rollup-linux-arm64-gnu': 4.18.0
+      '@rollup/rollup-linux-arm64-musl': 4.18.0
+      '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0
+      '@rollup/rollup-linux-riscv64-gnu': 4.18.0
+      '@rollup/rollup-linux-s390x-gnu': 4.18.0
+      '@rollup/rollup-linux-x64-gnu': 4.18.0
+      '@rollup/rollup-linux-x64-musl': 4.18.0
+      '@rollup/rollup-win32-arm64-msvc': 4.18.0
+      '@rollup/rollup-win32-ia32-msvc': 4.18.0
+      '@rollup/rollup-win32-x64-msvc': 4.18.0
       fsevents: 2.3.3
-    dev: true
 
   /sass/1.77.1:
     resolution: {integrity: sha512-OMEyfirt9XEfyvocduUIOlUSkWOXS/LAt6oblR/ISXCTukyavjex+zQNm51pPCOiFKY1QpWvEH1EeCkgyV3I6w==}
@@ -929,6 +1324,19 @@ packages:
     resolution: {integrity: sha512-A/I230vCzTBDHAc2wzCXrH3ofcNnMd9Cs/HhRrxjWJ1YI90cOklljX9XATTdU45T4W/c/+g+jBtS/oQLs+Wkdw==}
     dev: false
 
+  /supports-color/5.5.0:
+    resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+    engines: {node: '>=4'}
+    dependencies:
+      has-flag: 3.0.0
+    dev: false
+    optional: true
+
+  /supports-preserve-symlinks-flag/1.0.0:
+    resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+    engines: {node: '>= 0.4'}
+    dev: false
+
   /three/0.164.1:
     resolution: {integrity: sha512-iC/hUBbl1vzFny7f5GtqzVXYjMJKaTPxiCxXfrvVdBi1Sf+jhd1CAkitiFwC7mIBFCo3MrDLJG97yisoaWig0w==}
     dev: false
@@ -983,7 +1391,7 @@ packages:
       '@types/node': 20.14.5
       esbuild: 0.20.2
       postcss: 8.4.38
-      rollup: 4.17.2
+      rollup: 4.18.0
       sass: 1.77.1
     optionalDependencies:
       fsevents: 2.3.3
@@ -1037,3 +1445,19 @@ packages:
       '@vue/server-renderer': 3.4.27_vue@3.4.27
       '@vue/shared': 3.4.27
       typescript: 5.4.5
+
+  /web-worker/1.3.0:
+    resolution: {integrity: sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==}
+    dev: false
+
+  /wrappy/1.0.2:
+    resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+    dev: true
+
+  /xml-utils/1.10.1:
+    resolution: {integrity: sha512-Dn6vJ1Z9v1tepSjvnCpwk5QqwIPcEFKdgnjqfYOABv1ngSofuAhtlugcUC3ehS1OHdgDWSG6C5mvj+Qm15udTQ==}
+    dev: false
+
+  /zstddec/0.1.0:
+    resolution: {integrity: sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==}
+    dev: false

+ 4 - 3
src/App.vue

@@ -3,8 +3,9 @@
 </template>
 
 <script setup lang="ts">
-import QueryBoard from "./components/query-board/index.vue";
+import QueryBoard from "./app/4dmap/example/index.vue";
+// import QueryBoard from "./app/liantong/example/index.vue";
 
-const width = window.innerWidth - 50;
-const height = window.innerHeight - 50;
+const width = window.innerWidth;
+const height = window.innerHeight;
 </script>

+ 82 - 0
src/app/4dmap/example/index.vue

@@ -0,0 +1,82 @@
+<template>
+  <div class="btns">
+    <!-- <ElButton @click="board.clear()"> 清除 </ElButton>
+    <ElButton :disabled="!board.history.state.hasUndo" @click="board.history.undo()">
+      撤销
+    </ElButton>
+    <ElButton :disabled="!board.history.state.hasRedo" @click="board.history.redo()">
+      重做
+    </ElButton> -->
+    <ElButton @click="getData">获取数据</ElButton>
+    <ElButton v-if="!drawing" @click="board.polygon.editPolygon()"> 绘画 </ElButton>
+  </div>
+  <div
+    class="board-layout"
+    :style="{ width: width + 'px', height: height + 'px' }"
+    ref="containerRef"
+  ></div>
+</template>
+
+<script setup lang="ts">
+import { shallowRef, watch } from "vue";
+import storeData from "./storeData.json";
+import { ElButton } from "element-plus";
+import { createBoard, changeEnv } from "../index";
+
+changeEnv(false);
+const width = 661;
+const height = 934;
+withDefaults(defineProps<{ width?: number; height?: number; pixelRation?: number }>(), {
+  width: 320,
+  height: 150,
+  pixelRation: 1,
+});
+const board = createBoard({ store: storeData });
+
+board.polygon.bus.on("clickPoint", (point) => {
+  board.polygon.status.activePointId = point.id;
+});
+
+const drawing = shallowRef<boolean>();
+board.polygon.bus.on("clickPolygon", (polygon) => {
+  board.polygon.editPolygon(polygon.id);
+  drawing.value = true;
+});
+
+board.polygon.bus.on("penEndHandler", () => {
+  drawing.value = false;
+});
+
+const containerRef = shallowRef<HTMLDivElement>();
+watch(containerRef, (container, _) => {
+  if (container) {
+    board.setProps({ dom: container });
+    board.raw.bound.setBound([
+      114.10671883665741,
+      24.922018922142065,
+      114.1102647169751,
+      24.927029288581885,
+    ]);
+  }
+});
+
+const getData = () => {
+  console.log(JSON.stringify(board.getData(), null, 4));
+};
+</script>
+
+<style lang="scss" scoped>
+.board-layout {
+  position: absolute;
+
+  canvas {
+    display: block;
+    width: 100%;
+    height: 100%;
+  }
+
+  // .btns {
+  //   position: absolute;
+  // }
+}
+</style>

+ 969 - 0
src/app/4dmap/example/storeData.json

@@ -0,0 +1,969 @@
+  {
+    "id": "7",
+    "lines": [
+      {
+        "id": "5",
+        "pointIds": [
+          "74",
+          "75"
+        ]
+      },
+      {
+        "id": "6",
+        "pointIds": [
+          "75",
+          "76"
+        ]
+      },
+      {
+        "id": "7",
+        "pointIds": [
+          "76",
+          "77"
+        ]
+      },
+      {
+        "id": "9",
+        "pointIds": [
+          "77",
+          "79"
+        ]
+      },
+      {
+        "id": "10",
+        "pointIds": [
+          "79",
+          "78"
+        ]
+      },
+      {
+        "id": "11",
+        "pointIds": [
+          "80",
+          "81"
+        ]
+      },
+      {
+        "id": "12",
+        "pointIds": [
+          "81",
+          "82"
+        ]
+      },
+      {
+        "id": "13",
+        "pointIds": [
+          "82",
+          "83"
+        ]
+      },
+      {
+        "id": "14",
+        "pointIds": [
+          "84",
+          "85"
+        ]
+      },
+      {
+        "id": "15",
+        "pointIds": [
+          "85",
+          "86"
+        ]
+      },
+      {
+        "id": "16",
+        "pointIds": [
+          "86",
+          "87"
+        ]
+      },
+      {
+        "id": "17",
+        "pointIds": [
+          "88",
+          "89"
+        ]
+      },
+      {
+        "id": "18",
+        "pointIds": [
+          "89",
+          "90"
+        ]
+      },
+      {
+        "id": "19",
+        "pointIds": [
+          "90",
+          "91"
+        ]
+      },
+      {
+        "id": "20",
+        "pointIds": [
+          "91",
+          "92"
+        ]
+      },
+      {
+        "id": "21",
+        "pointIds": [
+          "93",
+          "94"
+        ]
+      },
+      {
+        "id": "22",
+        "pointIds": [
+          "94",
+          "95"
+        ]
+      },
+      {
+        "id": "23",
+        "pointIds": [
+          "95",
+          "96"
+        ]
+      },
+      {
+        "id": "24",
+        "pointIds": [
+          "96",
+          "97"
+        ]
+      },
+      {
+        "id": "25",
+        "pointIds": [
+          "98",
+          "99"
+        ]
+      },
+      {
+        "id": "30",
+        "pointIds": [
+          "102",
+          "103"
+        ]
+      },
+      {
+        "id": "31",
+        "pointIds": [
+          "103",
+          "104"
+        ]
+      },
+      {
+        "id": "32",
+        "pointIds": [
+          "104",
+          "105"
+        ]
+      },
+      {
+        "id": "33",
+        "pointIds": [
+          "105",
+          "106"
+        ]
+      },
+      {
+        "id": "34",
+        "pointIds": [
+          "106",
+          "107"
+        ]
+      },
+      {
+        "id": "35",
+        "pointIds": [
+          "99",
+          "102"
+        ]
+      },
+      {
+        "id": "36",
+        "pointIds": [
+          "108",
+          "109"
+        ]
+      },
+      {
+        "id": "37",
+        "pointIds": [
+          "109",
+          "110"
+        ]
+      },
+      {
+        "id": "38",
+        "pointIds": [
+          "110",
+          "111"
+        ]
+      },
+      {
+        "id": "39",
+        "pointIds": [
+          "112",
+          "113"
+        ]
+      },
+      {
+        "id": "40",
+        "pointIds": [
+          "113",
+          "114"
+        ]
+      }
+    ],
+    "points": [
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "65",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "66",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "67",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "68",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.138507288396,
+        "y": 24.8999477336056,
+        "id": "14",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.138507288396,
+        "y": 24.8999477336056,
+        "id": "15",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.138439877894,
+        "y": 24.8987537036652,
+        "id": "16",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "17",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "18",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "19",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "20",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "21",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "22",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "23",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "24",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "25",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "26",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "27",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "28",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "29",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "30",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "31",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "32",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "33",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "34",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "35",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "36",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "37",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "38",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "39",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "40",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "41",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "42",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "43",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "44",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "45",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "46",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "47",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "48",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "49",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "50",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "51",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "52",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "53",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "54",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "55",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "56",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "57",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "58",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "59",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "60",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "61",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.108590244609,
+        "y": 24.9245532362898,
+        "id": "62",
+        "rtk": true,
+        "title": "1"
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "63",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.10840114482,
+        "y": 24.9244845900276,
+        "id": "64",
+        "rtk": true,
+        "title": "3"
+      },
+      {
+        "x": 114.1103559120816,
+        "y": 24.925548709205668,
+        "id": "69",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10917644710426,
+        "y": 24.924747939972377,
+        "id": "74",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10989464833442,
+        "y": 24.924923038619394,
+        "id": "75",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.1100608436604,
+        "y": 24.92402083542118,
+        "id": "76",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10923580257784,
+        "y": 24.924139546368313,
+        "id": "77",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10876689433664,
+        "y": 24.924908199751,
+        "id": "78",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.1089554051798,
+        "y": 24.924599185141044,
+        "id": "79",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.108495964645,
+        "y": 24.9246236813815,
+        "id": "80",
+        "rtk": true,
+        "title": "2"
+      },
+      {
+        "x": 114.1083776381601,
+        "y": 24.925023518759833,
+        "id": "81",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10800400634808,
+        "y": 24.92504248484166,
+        "id": "82",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10808176728357,
+        "y": 24.924636610690506,
+        "id": "83",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10752416447777,
+        "y": 24.925044381449847,
+        "id": "84",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10800400634808,
+        "y": 24.92504248484166,
+        "id": "85",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10808176728357,
+        "y": 24.924636610690506,
+        "id": "86",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10755451020869,
+        "y": 24.92461764460867,
+        "id": "87",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "88",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.10817849430089,
+        "y": 24.924291428001183,
+        "id": "89",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10832453313095,
+        "y": 24.92411314683198,
+        "id": "90",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10860712775025,
+        "y": 24.924236426363876,
+        "id": "91",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.108479753191,
+        "y": 24.924434913749,
+        "id": "92",
+        "rtk": true,
+        "title": "0"
+      },
+      {
+        "x": 114.10720174108664,
+        "y": 24.924464019345837,
+        "id": "93",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10761709827872,
+        "y": 24.92452281419951,
+        "id": "94",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10730795114488,
+        "y": 24.924031592680112,
+        "id": "95",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10709173781204,
+        "y": 24.92405435197831,
+        "id": "96",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10751468143684,
+        "y": 24.92382675899635,
+        "id": "97",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.1082999138974,
+        "y": 24.923651090658375,
+        "id": "98",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10865589083276,
+        "y": 24.923971877437815,
+        "id": "99",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10768537617332,
+        "y": 24.92414918238746,
+        "id": "102",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10761709827872,
+        "y": 24.92452281419951,
+        "id": "103",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10720174108664,
+        "y": 24.924464019345837,
+        "id": "104",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10751468143684,
+        "y": 24.92382675899635,
+        "id": "105",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10770434225512,
+        "y": 24.923686409990808,
+        "id": "106",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10795588449955,
+        "y": 24.923358418016093,
+        "id": "107",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10919646156958,
+        "y": 24.923331988543715,
+        "id": "108",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10960187787953,
+        "y": 24.923398632320698,
+        "id": "109",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.10959077058337,
+        "y": 24.924306653782015,
+        "id": "110",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "x": 114.1090742813118,
+        "y": 24.92361522459587,
+        "id": "111",
+        "rtk": false,
+        "title": ""
+      },
+      {
+        "rtk": false,
+        "title": "",
+        "x": 114.10863393389405,
+        "y": 24.922668016723673,
+        "id": "112"
+      },
+      {
+        "rtk": false,
+        "title": "",
+        "x": 114.10991066538514,
+        "y": 24.922555363945047,
+        "id": "113"
+      },
+      {
+        "rtk": false,
+        "title": "",
+        "x": 114.10889142595948,
+        "y": 24.92320982294468,
+        "id": "114"
+      }
+    ],
+    "polygons": [
+      {
+        "id": "3",
+        "name": "本体边界3",
+        "lineIds": [
+          "5",
+          "6",
+          "7",
+          "9",
+          "10"
+        ]
+      },
+      {
+        "id": "4",
+        "name": "本体边界4",
+        "lineIds": [
+          "11",
+          "12",
+          "13"
+        ]
+      },
+      {
+        "id": "5",
+        "name": "本体边界5",
+        "lineIds": [
+          "14",
+          "15",
+          "16"
+        ]
+      },
+      {
+        "id": "6",
+        "name": "本体边界6",
+        "lineIds": [
+          "17",
+          "18",
+          "19",
+          "20"
+        ]
+      },
+      {
+        "id": "7",
+        "name": "本体边界7",
+        "lineIds": [
+          "21",
+          "22",
+          "23",
+          "24"
+        ]
+      },
+      {
+        "id": "8",
+        "name": "本体边界8",
+        "lineIds": [
+          "25",
+          "35",
+          "30",
+          "31",
+          "32",
+          "33",
+          "34"
+        ]
+      },
+      {
+        "id": "9",
+        "name": "本体边界9",
+        "lineIds": [
+          "36",
+          "37",
+          "38"
+        ]
+      },
+      {
+        "id": "10",
+        "lineIds": [
+          "39",
+          "40"
+        ]
+      }
+    ]
+  }

+ 10 - 3
src/app/4dmap/index.ts

@@ -75,11 +75,18 @@ export const createBoard = (
     map?: Map;
   } = {}
 ) => {
-  const data = props.store || { id: "0", points: [], polygons: [], lines: [] };
+  const data = props.store || [
+    { id: "0", points: [], polygons: [], lines: [] },
+  ];
   const board = initBoard(props.dom, { polygons: data }, false);
   const mapJoin = boundJoinMap(board.bound, props.dom, props.map);
 
+  board.tree.bus.on("active", (entity) => {
+    console.log(entity);
+  });
+
   return {
+    raw: board,
     setProps(props: { dom?: HTMLDivElement; map?: Map }) {
       if (props.dom) {
         board.mount(props.dom);
@@ -92,8 +99,8 @@ export const createBoard = (
     getData() {
       return board.getData().polygons;
     },
-    setData(polygons: PolygonsAttrib & { id: string }) {
-      board.setData({ polygons });
+    setData(polygon: PolygonsAttrib & { id: string }) {
+      board.setData({ polygons: [polygon] });
     },
     destory() {
       mapJoin.destory();

+ 63 - 0
src/app/4dmap/path.ts

@@ -0,0 +1,63 @@
+import {
+  WholeLinePolygon,
+  WholeLinePolygonAttrib,
+  mergeFuns,
+} from "../../board";
+import { polygonShapeFactory } from "../../board/packages/whole-line/style";
+import { Line } from "konva/lib/shapes/Line";
+import { Polygons } from "./polygons";
+import { Group } from "konva/lib/Group";
+import { watchEffect } from "vue";
+
+const polygonActShapeFactory = (attrib, tree) => {
+  const polygons = tree.parent as Polygons;
+  const act = polygonShapeFactory({
+    autoClose: true,
+  });
+  const path = act.shape.findOne<Line>(".polygon-line");
+  const result = {
+    ...act,
+    common() {
+      path.fill("rgba(0, 0, 0, 0)");
+      act.closeLine.common();
+    },
+    hover() {
+      path.fill("rgba(0, 0, 0, 0.3)");
+      act.closeLine.hover();
+    },
+    active() {
+      path.fill("rgba(0, 0, 0, 0.3)");
+      act.closeLine.active();
+      if (!polygons.status.newModel) {
+        polygons.bus.emit("clickPolygon", attrib);
+      }
+    },
+  };
+  return result;
+};
+
+export class PoPath extends WholeLinePolygon<WholeLinePolygonAttrib, Group> {
+  actShapeFactory = polygonActShapeFactory;
+
+  init(): void {
+    super.init();
+    this.enableMouseAct(this.actShape);
+  }
+
+  protected initReactive() {
+    const polygons = this.parent as unknown as Polygons;
+    return mergeFuns(
+      super.initReactive(),
+      watchEffect(
+        () => {
+          if (polygons.status.editPolygonId === this.attrib.id) {
+            this.bus.emit("statusChange", { active: true });
+          } else {
+            this.bus.emit("statusChange", { active: false });
+          }
+        },
+        { flush: "post" }
+      )
+    );
+  }
+}

+ 225 - 0
src/app/4dmap/point.ts

@@ -0,0 +1,225 @@
+import { Path } from "konva/lib/shapes/Path";
+import {
+  CustomizeShape,
+  WholeLinePoint,
+  getRealAbsoluteSize,
+  getWholeLinePolygonPoints,
+  mergeFuns,
+  openEntityDrag,
+  wholeLineStyle,
+} from "../../board";
+import { PolygonsPointAttrib } from "./type";
+import { Group } from "konva/lib/Group";
+import { Text } from "konva/lib/shapes/Text";
+import { Circle } from "konva/lib/shapes/Circle";
+import { Polygons } from "./polygons";
+import { point } from "../../board/packages/whole-line/style";
+import { Label, Tag } from "konva/lib/shapes/Label";
+import { watch, watchEffect } from "vue";
+
+const pointActShapeFactory = (attrib: PolygonsPointAttrib, tree: Point) => {
+  const polygons = tree.parent as unknown as Polygons;
+  const size = { width: 43, height: 44 };
+  const out = new Path({
+    data: `M22 44C32.6667 33.891 38 25.891 38 20C38 11.1634 30.8366 4 22 4C13.1634 4 6 11.1634 6 20C6 25.891 11.3333 33.891 22 44Z`,
+    strokeScaleEnabled: true,
+    stroke: "#ffffff",
+    strokeWidth: 1,
+  });
+  const inner = new Path({
+    fill: "#fff",
+    data: `M22 30C27.5228 30 32 25.5228 32 20C32 14.4772 27.5228 10 22 10C16.4772 10 12 14.4772 12 20C12 25.5228 16.4772 30 22 30Z`,
+  });
+  const select = new Path({
+    fill: "#409EFF",
+    offset: {
+      x: -5,
+      y: -5,
+    },
+    data: `M20.5143 12.213C20.7983 12.497 20.7983 12.9575 20.5143 13.2415L15.2727 18.4831L11.8494 15.0597C11.5654 14.7757 11.5654 14.3152 11.8494 14.0312C12.1334 13.7472 12.5939 13.7472 12.8779 14.0312L15.2727 16.426L19.4857 12.213C19.7698 11.929 20.2302 11.929 20.5143 12.213Z`,
+  });
+
+  const rectGroup = new Group({
+    name: "anchor-move",
+  });
+  const rect = new Circle({
+    name: "anchor-move",
+    radius: Math.min(size.width, size.height) / 2,
+    fill: "rgba(0, 0, 0, 0)",
+    offset: { x: -size.width / 2, y: -size.height / 2 },
+  });
+  const wlp = wholeLineStyle.pointShapeFactory();
+  point.radius = 5;
+  point.hitStrokeWidth = point.strokeWidth = 4;
+  wlp.shape.name("anchor-point");
+
+  const index = new Text({
+    name: "text",
+    text: `1`,
+    fontFamily: "Calibri",
+    fontSize: 12,
+    padding: 5,
+    offsetY: -8,
+    fill: "#000",
+  });
+
+  const label = new Label({
+    visible: false,
+    opacity: 0.75,
+    name: "label",
+    offsetX: -size.width / 2,
+    offsetY: -6,
+  });
+
+  rectGroup.add(index, label, rect);
+
+  label.add(
+    new Tag({
+      name: "tag",
+      fill: "rgba(255, 255, 255, 0.8)",
+      pointerDirection: "down",
+      pointerWidth: 5,
+      pointerHeight: 5,
+      lineJoin: "round",
+      shadowColor: "black",
+      shadowBlur: 10,
+      shadowOffsetX: 10,
+      shadowOffsetY: 10,
+      shadowOpacity: 0.5,
+    }),
+    new Text({
+      name: "text",
+      text: attrib.title || `P${attrib.id}`,
+      fontFamily: "Calibri",
+      fontSize: 10,
+      padding: 5,
+      fill: "#000",
+    })
+  );
+
+  const offsetGroup = new Group();
+  offsetGroup.add(out, inner, select, rectGroup);
+  offsetGroup.x(-size.width / 2);
+  offsetGroup.y(-size.height);
+
+  const group = new Group();
+  group.add(offsetGroup, wlp.shape);
+
+  const result = {
+    shape: group,
+    common() {
+      out.fill(attrib.rtk ? "rgba(230, 162, 60, 1)" : "#409EFF");
+      select.fill(attrib.rtk ? "rgba(230, 162, 60, 1)" : "#409EFF");
+      wlp.common();
+      label.visible(false);
+    },
+    hover: () => {
+      label.visible(true);
+    },
+    setData(data: number[]) {
+      let [width, height] = getRealAbsoluteSize(group, [1, 1]);
+      group.scale({ x: width, y: height });
+      group.x(data[0]);
+      group.y(data[1]);
+
+      if (~tree.editPolygonNdx) {
+        index.text((tree.editPolygonNdx + 1).toString()).visible(true);
+        index.offsetX(-rect.width() / 2 + index.width() / 2);
+        wlp.shape.visible(true);
+        select.visible(false);
+      } else {
+        index.visible(false);
+        wlp.shape.visible(false);
+        select.visible(polygons.status.selectPoiIds.includes(attrib.id));
+      }
+    },
+    draging() {
+      if (~tree.editPolygonNdx) {
+        out.fill("#e0403c");
+        select.fill("#e0403c");
+      }
+    },
+    active() {
+      polygons.bus.emit("clickPoint", attrib);
+      label.visible(true);
+    },
+  };
+
+  return result;
+};
+
+export class Point extends WholeLinePoint<PolygonsPointAttrib, Group> {
+  actShape: CustomizeShape<number[], Group, { setNdx: (ndx: number) => void }> =
+    null;
+
+  get editPolygonNdx() {
+    const polygons = this.parent as unknown as Polygons;
+    if (polygons.status.editPolygonId) {
+      const points = getWholeLinePolygonPoints(
+        polygons.attrib,
+        polygons.status.editPolygonId
+      ).map(({ id }) => id);
+      return points.indexOf(this.attrib.id);
+    }
+    return -1;
+  }
+
+  init(): void {
+    this.actShapeFactory = pointActShapeFactory;
+    super.init();
+    this.enableMouseAct(this.actShape);
+  }
+
+  protected initReactive() {
+    const polygons = this.parent as unknown as Polygons;
+    return mergeFuns(
+      super.initReactive(),
+      watchEffect(() => {
+        if (polygons.status.editPolygonId === this.attrib.id) {
+          this.bus.emit("statusChange", { active: true });
+        } else {
+          this.bus.emit("statusChange", { active: false });
+        }
+      }),
+      watch(
+        () => this.editPolygonNdx,
+        (endx, _, onCleanup) => {
+          if (!~endx) {
+            onCleanup(() => {});
+          }
+          const anchor = this.shape.findOne<Group>(".anchor-move");
+
+          let clearCursor: (() => void) | null = null;
+          anchor.on("mouseenter.anchor", () => {
+            clearCursor && clearCursor();
+            clearCursor = this.container.setCursor("move");
+          });
+
+          anchor.on("mouseleave.anchor", () => {
+            clearCursor && clearCursor();
+            clearCursor = null;
+          });
+
+          openEntityDrag(this, {
+            readyHandler: (attrib) => {
+              return [attrib.x, attrib.y];
+            },
+            moveHandler: (pointAttrib, move) => {
+              if (~this.editPolygonNdx) {
+                pointAttrib.x = move[0];
+                pointAttrib.y = move[1];
+              }
+            },
+          });
+
+          onCleanup(() => {
+            anchor.off("mouseenter.anchor mouseleave.anchor");
+            clearCursor && clearCursor();
+            this.disableDrag();
+          });
+        },
+        { immediate: true }
+      )
+    );
+  }
+}

+ 92 - 209
src/app/4dmap/polygons.ts

@@ -1,24 +1,23 @@
-import { PolygonsAttrib, PolygonsPointAttrib } from "./type";
+import {
+  PolygonsAttrib,
+  PolygonsLineAttrib,
+  PolygonsPointAttrib,
+} from "./type";
 import {
   incEntitysFactoryGenerate,
   Attrib,
-  wholeLineStyle,
-  getRealAbsoluteSize,
-  PenEditWholeLine,
   WholeLinePoint,
-  getWholeLinePolygonPoints,
-  shapeParentsEq,
-  openEntityDrag,
-  WholeLineInc,
+  EntityEvent,
+  WholeLinePolygonAttrib,
+  WholeLine,
+  penWholeLinePoygonsEditWithHelperShapesMouse,
+  getWholeLinePolygonLinesRaw,
+  WholeLineLine,
 } from "../../board";
-import { Group } from "konva/lib/Group";
-import { Path } from "konva/lib/shapes/Path";
-import { Circle } from "konva/lib/shapes/Circle";
-import { Label, Tag } from "konva/lib/shapes/Label";
-import { Text } from "konva/lib/shapes/Text";
-import { ref } from "vue";
-import mitt from "mitt";
-import { point } from "../../board/packages/whole-line/style";
+import { reactive } from "vue";
+import { Point } from "./point";
+import { PoPath } from "./path";
+import { lineShapeFactory } from "../../board/packages/whole-line/style";
 
 // 加点
 const getPolygonPoint = (position: number[]) => {
@@ -31,166 +30,58 @@ const getPolygonPoint = (position: number[]) => {
   return pointAttrib;
 };
 
-const pointActShapeFactory = (attrib: PolygonsPointAttrib, tree: any) => {
+const lineActShapeFactory = (attrib: PolygonsLineAttrib, tree: any) => {
   const polygons = tree.parent as Polygons;
-  const size = { width: 43, height: 44 };
-  const out = new Path({
-    data: `M22 44C32.6667 33.891 38 25.891 38 20C38 11.1634 30.8366 4 22 4C13.1634 4 6 11.1634 6 20C6 25.891 11.3333 33.891 22 44Z`,
-    strokeScaleEnabled: true,
-    stroke: "#ffffff",
-    strokeWidth: 1,
-  });
-  const inner = new Path({
-    fill: "#fff",
-    data: `M22 30C27.5228 30 32 25.5228 32 20C32 14.4772 27.5228 10 22 10C16.4772 10 12 14.4772 12 20C12 25.5228 16.4772 30 22 30Z`,
-  });
-  const rect = new Circle({
-    name: "anchor-move",
-    radius: Math.min(size.width, size.height) / 2,
-    fill: "rgba(0, 0, 0, 0)",
-    offset: { x: -size.width / 2, y: -size.height / 2 },
-  });
-  const wlp = wholeLineStyle.pointShapeFactory();
-  point.radius = 5;
-
-  point.hitStrokeWidth = point.strokeWidth = 4;
-  wlp.shape.name("anchor-point");
-
-  const index = new Text({
-    name: "text",
-    text: `1`,
-    fontFamily: "Calibri",
-    fontSize: 12,
-    padding: 5,
-    offsetY: -8,
-    fill: "#000",
-  });
+  const wll = lineShapeFactory();
 
-  const label = new Label({
-    visible: false,
-    opacity: 0.75,
-    name: "label",
-    offsetX: -size.width / 2,
-    offsetY: -6,
-  });
-
-  label.add(
-    new Tag({
-      name: "tag",
-      fill: "rgba(255, 255, 255, 0.8)",
-      pointerDirection: "down",
-      pointerWidth: 5,
-      pointerHeight: 5,
-      lineJoin: "round",
-      shadowColor: "black",
-      shadowBlur: 10,
-      shadowOffsetX: 10,
-      shadowOffsetY: 10,
-      shadowOpacity: 0.5,
-    }),
-    new Text({
-      name: "text",
-      text: attrib.title || `P${attrib.id}`,
-      fontFamily: "Calibri",
-      fontSize: 10,
-      padding: 5,
-      fill: "#000",
-    })
-  );
-
-  const offsetGroup = new Group();
-  offsetGroup.add(out, inner, rect, label, index);
-  offsetGroup.x(-size.width / 2);
-  offsetGroup.y(-size.height);
-
-  const group = new Group();
-  group.add(offsetGroup, wlp.shape);
-
-  const activeNdx = () => {
-    if (polygons.editPolygonId.value) {
-      const points = getWholeLinePolygonPoints(
+  const isActive = () => {
+    if (polygons.status.editPolygonId) {
+      const lines = getWholeLinePolygonLinesRaw(
         polygons.attrib,
-        polygons.editPolygonId.value
-      ).map(({ id }) => id);
-      const ndx = points.indexOf(attrib.id);
-      return ndx;
+        polygons.status.editPolygonId
+      );
+      if (lines.some(({ id }) => id === attrib.id)) {
+        return true;
+      }
     }
-    return -1;
+    return false;
   };
 
-  const setStyle = () => {
-    let [width, height] = getRealAbsoluteSize(group, [1, 1]);
-    group.scale({ x: width, y: height });
-    const ndx = activeNdx();
-    if (~ndx) {
-      index.text((ndx + 1).toString()).visible(true);
-      index.offsetX(-rect.width() / 2 + index.width() / 2);
+  const common = () => {
+    if (isActive()) {
+      wll.active();
     } else {
-      index.visible(false);
+      wll.common();
     }
   };
-
-  const commonStyle = () => {
-    out.fill(attrib.rtk ? "rgba(230, 162, 60, 1)" : "#409EFF");
-    label.visible(false);
-    wlp.common();
-  };
-
-  const result = {
-    shape: group,
-    common: commonStyle,
-    hover: () => {
-      label.visible(true);
-    },
+  return {
+    shape: wll.shape,
     setData(data: number[]) {
-      setStyle();
-      group.x(data[0]);
-      group.y(data[1]);
-
-      label.visible(polygons.activePointId.value === attrib.id);
-    },
-    draging() {
-      if (polygons.editPolygonId.value && !attrib.rtk) {
-        out.fill("#e0403c");
-      }
-    },
-    active() {
-      polygons.activePointId.value = attrib.id;
-      polygons.bus.emit("clickPoint", attrib);
+      wll.setData(data);
+      common();
     },
+    common,
   };
-
-  return result;
 };
 
-export class Polygons extends PenEditWholeLine<PolygonsAttrib & Attrib> {
-  bus = mitt<{ clickPoint: PolygonsPointAttrib; penEndHandler: void }>();
-  activePointId = ref<string>();
-
-  dragAttach(inc: WholeLineInc<PolygonsAttrib & Attrib>) {
-    inc.pointEntityInc.adds.forEach((point) => {
-      openEntityDrag(point, {
-        readyHandler: (attrib) => {
-          return [attrib.x, attrib.y];
-        },
-        moveHandler: (pointAttrib, move) => {
-          if (this.editPolygonId.value && !pointAttrib.rtk) {
-            pointAttrib.x = move[0];
-            pointAttrib.y = move[1];
-          }
-        },
-      });
-      point.enableMouseAct(point.actShape);
-    });
-
-    inc.lineEntityInc.adds.forEach((line) => {
-      line.enableMouseAct(line.actShape);
-    });
-
-    inc.polygonEntityInc.adds.forEach((py) => {
-      py.enableMouseAct(py.actShape);
-    });
+export type PolygonsStatus = {
+  newModel: boolean;
+  activePointId?: string;
+  editPolygonId?: string;
+  selectPoiIds: string[];
+};
+export class Polygons extends WholeLine<
+  PolygonsAttrib & Attrib,
+  EntityEvent & {
+    clickPoint: PolygonsPointAttrib;
+    clickPolygon: WholeLinePolygonAttrib;
+    penEndHandler: void;
   }
+> {
+  status: PolygonsStatus = reactive({
+    selectPoiIds: ["108", "109", "110"],
+    newModel: false,
+  });
 
   removePolygon(polygonId: string) {
     const ndx = this.attrib.polygons.findIndex(({ id }) => id === polygonId);
@@ -228,64 +119,56 @@ export class Polygons extends PenEditWholeLine<PolygonsAttrib & Attrib> {
 
   initIncFactory() {
     super.initIncFactory();
-    this.incPointsFactory = incEntitysFactoryGenerate(
-      WholeLinePoint<any>,
+    this.incPointsFactory = incEntitysFactoryGenerate(Point, this);
+    this.incLinesFactory = incEntitysFactoryGenerate(
+      WholeLineLine,
       this,
-      (point) => {
-        point.actShapeFactory = pointActShapeFactory as any;
+      (line) => {
+        line.setConfig(this.attrib);
+        line.actShapeFactory = lineActShapeFactory;
       }
     );
+    this.incPolygonFactory = incEntitysFactoryGenerate(PoPath, this, (py) => {
+      py.setConfig(this.attrib);
+    });
   }
 
+  private endEditPolygon: () => void;
   editPolygon(polygonId?: string) {
-    this.activePointId.value = polygonId;
-    super.enterEditMode({
-      polygonId: polygonId,
-      pointAttribFactory: getPolygonPoint,
-      canOper: (tree, operShape) => {
-        return (
-          !tree.name.includes(WholeLinePoint.namespace) ||
-          operShape.name() === "anchor-point"
-        );
-      },
-      quitHandler: () => {
-        this.bus.emit("penEndHandler");
+    this.endEditPolygon && this.endEditPolygon();
+    this.status.newModel = !polygonId;
+    this.endEditPolygon = penWholeLinePoygonsEditWithHelperShapesMouse(
+      {
+        polygonId,
+        pointAttribFactory: getPolygonPoint,
+        canOper: (tree, operShape) => {
+          return (
+            !tree.name.includes(WholeLinePoint.namespace) ||
+            operShape.name() === "anchor-point"
+          );
+        },
+        quitHandler: () => {
+          this.status.newModel = false;
+          this.bus.emit("penEndHandler");
+        },
+        canDelPoint: (p: any) => !p.rtk,
+        quotePoint: false,
+        closeAutoQuit: true,
+        tree: this.container,
+        autoAdd: false,
+        autoClose: true,
+        config: this.attrib as any,
+        changePolygon: (pid: string) => {
+          this.status.editPolygonId = pid;
+        },
       },
-      canDelPoint: (p) => !p.rtk,
-      quotePoint: false,
-    });
-    return super.leaveEditMode;
+      this.shape
+    );
+    return this.endEditPolygon;
   }
 
-  mounted(): void {
-    super.mounted();
-    let clearCursor: (() => void) | null = null;
-    this.container.stage.on("mousemove.anchor-move", (evt) => {
-      const isPoint = evt.target.name() === "anchor-move";
-      if (!isPoint) {
-        clearCursor && clearCursor();
-        clearCursor = null;
-        return;
-      }
-
-      if (this.editPolygonId.value) {
-        clearCursor = this.container.setCursor("move");
-      } else {
-        clearCursor = this.container.setCursor("pointer");
-      }
-    });
-
-    this.container.stage.on("click.anchor-move", (evt) => {
-      const point = shapeParentsEq(evt.target, (shape) =>
-        shape.id().startsWith(WholeLinePoint.namespace)
-      );
-      if (!point) {
-        this.activePointId.value = undefined;
-      }
-    });
-  }
   destory(): void {
+    this.endEditPolygon && this.endEditPolygon();
     super.destory();
-    this.container.stage.off("mousemove.anchor-move click.anchor-move");
   }
 }

+ 1 - 3
src/components/query-board/index.vue

@@ -35,11 +35,9 @@
 
 <script setup lang="ts">
 import { shallowRef, watch } from "vue";
-import { EditWholeLine } from "../../board/packages";
+import { EditWholeLine, createBoard, EditPoi, changeEnv } from "../";
 import storeData from "./storeData.json";
 import { ElButton } from "element-plus";
-import { createBoard, EditPoi } from "../../app/liantong";
-import { changeEnv } from "../../board/env";
 
 changeEnv(true);
 withDefaults(defineProps<{ width?: number; height?: number; pixelRation?: number }>(), {

src/components/query-board/storeData.json → src/app/liantong/example/storeData.json


+ 6 - 0
src/app/liantong/index.ts

@@ -130,6 +130,11 @@ export const createBoard = (
       });
     },
     addPoi(type: string) {
+      if (!pois()) {
+        const data = board.getData();
+        board.setData({ ...data, pois: [] });
+      }
+      console.log(pois());
       board.tree.bus.emit("dataChangeBefore");
       const { promise, interrupt } = addEntityAttrib(board.tree, (pos) => {
         const attrib = {
@@ -138,6 +143,7 @@ export const createBoard = (
           y: pos[1],
           type,
         };
+        console.log(attrib);
         pois().push(attrib);
       });
       promise.finally(() => {

+ 10 - 0
src/board/helper/entity.ts

@@ -55,3 +55,13 @@ export const addEntityAttrib = <T>(
 
   return interrupt;
 };
+
+export const entityTreeExecute = (
+  entity: Entity,
+  execute: (entity: Entity) => void
+) => {
+  execute(entity);
+  for (const child of entity.children) {
+    entityTreeExecute(child, execute);
+  }
+};

+ 2 - 1
src/board/index.ts

@@ -2,4 +2,5 @@ export * from "./packages";
 export * from "./register";
 export * from "./shared";
 export * from "./plugins";
-export * from "./type.d";
+export * from "./type";
+export * from "./env";

+ 27 - 27
src/board/packages/container.ts

@@ -1,7 +1,7 @@
 import { watch } from "vue";
 import { Attrib, ShapeType } from "../type";
 import { Layer } from "konva/lib/Layer";
-import { Entity, EntityProps, EntityType } from "./entity";
+import { Entity, EntityEvent, EntityProps, EntityType } from "./entity";
 import { Stage } from "konva/lib/Stage";
 import {
   IncEntitysFactory,
@@ -10,9 +10,9 @@ import {
 import { Shape } from "konva/lib/Shape";
 import { Group } from "konva/lib/Group";
 import { getAbsoluteTransform } from "../shared";
-import mitt, { Emitter } from "mitt";
 import { Euler, MathUtils, Matrix4, Quaternion, Vector3 } from "three";
 import { constantFactory } from "./view-constant";
+import { entityTreeExecute } from "../helper/entity";
 
 export type ContainerProps<
   T extends string = string,
@@ -37,13 +37,16 @@ export class Container<
   ENTRYS extends { [key in T]: InstanceType<TYPES[key]>[] } = {
     [key in T]: InstanceType<TYPES[key]>[];
   }
-> extends Entity<Attrib & { data: DATA }, Layer> {
-  bus: Emitter<{
+> extends Entity<
+  Attrib & { data: DATA },
+  Layer,
+  EntityEvent & {
     active: Entity;
     dataChange: void;
     dataChangeBefore: void;
     dataChangeAfter: void;
-  }>;
+  }
+> {
   tempLayer: Layer;
   config: ContainerProps<T, R, S, C, TYPES, DATA>;
   entrys = {} as ENTRYS;
@@ -76,7 +79,6 @@ export class Container<
       width: dom.offsetWidth,
       height: dom.offsetHeight,
     });
-    this.bus = mitt();
     // this.tempLayer = new Layer();
     // this.stage.add(this.tempLayer);
   }
@@ -106,39 +108,37 @@ export class Container<
             this.entrys[key] = [];
           }
           this.entrys[key].push(entity);
-          const destory = entity.destory.bind(entity);
-          entity.destory = () => {
-            destory();
+          entity.bus.on("destroyed", () => {
             const ndx = this.entrys[key].indexOf(entity);
             if (~ndx) {
               this.entrys[key].splice(ndx, 1);
             }
-          };
+          });
         },
         (instance) => {
-          if (!instance.actShape?.active) return;
-          const entity = instance as Entity;
-          entity.enableActive((actived) => {
-            if (actived) {
-              if (active !== entity) {
-                this.bus.emit("active", entity);
-                active = entity;
+          entityTreeExecute(instance, (entity) => {
+            if (!(entity as any).actShape?.active || entity.activeDestory)
+              return;
+            entity.enableActive((actived) => {
+              if (actived) {
+                if (active !== entity) {
+                  this.bus.emit("active", entity);
+                  active = entity;
+                }
+              } else {
+                if (active === entity) {
+                  this.bus.emit("active", null);
+                  active = null;
+                }
               }
-            } else {
+            });
+            entity.bus.on("destroyed", () => {
               if (active === entity) {
                 this.bus.emit("active", null);
                 active = null;
               }
-            }
+            });
           });
-          const destory = entity.destory.bind(entity);
-          entity.destory = () => {
-            if (active === entity) {
-              this.bus.emit("active", null);
-              active = null;
-            }
-            return destory();
-          };
         }
       );
     }

+ 35 - 20
src/board/packages/entity.ts

@@ -1,5 +1,5 @@
 import konva from "konva";
-import { Attrib, ShapeStyles, ShapeType } from "../type";
+import { Attrib, ShapeStyles, ShapeStylesStatus, ShapeType } from "../type";
 import { DEV } from "../env";
 import { Group } from "konva/lib/Group";
 import { Layer } from "konva/lib/Layer";
@@ -12,6 +12,7 @@ import {
   openShapeMouseStyles,
 } from "../shared/shape-mose";
 import { Container } from "./container";
+import mitt from "mitt";
 
 export type EntityBaseProps = {
   reactive?: boolean;
@@ -35,20 +36,30 @@ export type EntityTypeEvent<T extends string, R> = {
   [key in T]: R;
 };
 
+export type EntityEvent = {
+  created: void;
+  mounted: void;
+  destroyed: void;
+  statusChange: Partial<ShapeStylesStatus> | null;
+  "*": void;
+};
+
 export type EntityType<
   T extends Attrib,
   S extends ShapeType,
   P extends EntityProps<T> = EntityProps<T>,
-  K extends Entity<T, S> = Entity<T, S>,
+  K extends Entity<T, S> = Entity<T, S, any>,
   EK extends string = string,
   ER = any
 > = (new (props: P) => K) & { EventHandler?: { [key in EK]: ER } };
 
 export abstract class Entity<
   T extends Attrib = Attrib,
-  S extends ShapeType = ShapeType
+  S extends ShapeType = ShapeType,
+  E extends EntityEvent = EntityEvent
 > {
   props: EntityProps<T>;
+  bus = mitt<E>();
   container: Container<
     string,
     Attrib,
@@ -62,7 +73,7 @@ export abstract class Entity<
   private zIndex: number;
   teleport: ParentShapeType<S>;
 
-  children: Entity<Attrib, ShapeType>[] = [];
+  children: Entity<Attrib, ShapeType, any>[] = [];
   parent: Entity<Attrib, ShapeType>;
 
   constructor(props: EntityProps<T>) {
@@ -71,10 +82,6 @@ export abstract class Entity<
     this.props = props;
     this.attrib = props.reactive ? (reactive(props.attrib) as T) : props.attrib;
     this.zIndex = props.zIndex || 0;
-
-    if (DEV) {
-      // console.log(this.name + " create");
-    }
   }
 
   abstract initShape(): S;
@@ -116,6 +123,7 @@ export abstract class Entity<
   init() {
     this.shape = this.initShape();
     this.shape.id(this.name);
+    this.bus.emit("created");
   }
 
   mount(tel?: ParentShapeType<S>) {
@@ -140,16 +148,19 @@ export abstract class Entity<
     if (this.props.reactive) {
       this.destoryReactive = this.initReactive();
     }
-    let raw = { ...this.attrib };
-    watch(
-      () => this.attrib.id,
-      (newId, oldId) => {
-        if (newId !== oldId) {
-          console.error("changeId", raw, this.attrib, newId, oldId);
-        }
-      },
-      { flush: "sync" }
-    );
+
+    if (DEV) {
+      let raw = { ...this.attrib };
+      watch(
+        () => this.attrib.id,
+        (newId, oldId) => {
+          if (newId !== oldId) {
+            console.error("changeId", raw, this.attrib, newId, oldId);
+          }
+        },
+        { flush: "sync" }
+      );
+    }
   }
 
   isMounted = false;
@@ -157,6 +168,7 @@ export abstract class Entity<
     this.diffRedraw();
     this.children.forEach((child) => child.mounted());
     this.isMounted = true;
+    this.bus.emit("mounted");
   }
 
   setParent(parent: Entity<any, any> | null) {
@@ -234,13 +246,14 @@ export abstract class Entity<
     this.dragDestory = null;
   }
 
-  private activeDestory: () => void;
+  activeDestory: () => void;
   enableActive(activeCallback: (isActive: boolean) => void) {
     this.disableActive();
     this.activeDestory = openShapeMouseStyles(
       this.shape,
       {
         active: () => activeCallback(true),
+        bus: this.bus as any,
         common: () => activeCallback(false),
       },
       "mouse-active"
@@ -256,7 +269,7 @@ export abstract class Entity<
     this.disableMouseAct();
     this.mouseActDestory = openShapeMouseStyles(
       this.shape,
-      styles,
+      { ...styles, bus: this.bus as any },
       "act-mouse"
     );
   }
@@ -280,6 +293,8 @@ export abstract class Entity<
     } else {
       this.shape.destroy();
     }
+    this.bus.emit("destroyed");
+    this.bus.off("*");
   }
 
   find(name: string): Entity {

+ 0 - 1
src/board/packages/poi/edit-poi.ts

@@ -4,7 +4,6 @@ import { Poi, PoiAttrib } from "./poi";
 export class EditPoi<T extends PoiAttrib = PoiAttrib> extends Poi<T> {
   mounted(): void {
     super.enableMouseAct(this.actShape);
-    console.log("??");
     super.enableDrag({
       readyHandler: () => {
         this.container.bus.emit("dataChangeBefore");

+ 16 - 7
src/board/packages/whole-line/editable/edit-whole-line.ts

@@ -30,13 +30,15 @@ import { ShapeType } from "../../../type";
 import { getAdsorbPosition } from "../../../shared/adsorb";
 import { currentConstant } from "../../view-constant";
 import mitt from "mitt";
+import { EntityEvent } from "../../entity";
 
 export class EditWholeLine<
   W extends WholeLineAttrib = WholeLineAttrib,
+  EV extends EntityEvent = EntityEvent,
   PS extends ShapeType = ShapeType,
   LS extends ShapeType = ShapeType,
   PYS extends ShapeType = ShapeType
-> extends WholeLine<W, PS, LS, PYS> {
+> extends WholeLine<W, EV, PS, LS, PYS> {
   points: WholeLinePoint[];
   lines: WholeLineLine[];
 
@@ -83,7 +85,7 @@ export class EditWholeLine<
    * 开始绘制多边形
    */
   private endCreatePolygon: () => void;
-  createPolygon() {
+  editPolygon(polygonId?: string) {
     disableMouse();
     this.container.constant.use();
     const prePolygonIds: Set<string> = new Set();
@@ -98,9 +100,11 @@ export class EditWholeLine<
     const promise = new Promise<string>((resolve) => {
       this.endCreatePolygon = penWholeLinePoygonsEditWithHelperShapesMouse(
         {
+          polygonId,
           quotePoint: true,
           autoClose: false,
           tree: this.container,
+          autoAdd: true,
           adsorbRadius: currentConstant.WHOLE_LINE_POINT_MERGE_DIST,
           config: this.attrib,
           changePolygon: (pid) => {
@@ -118,16 +122,16 @@ export class EditWholeLine<
           quitHandler: () => {
             this.container.bus.emit("dataChangeAfter");
             this.endCreatePolygon = null;
-            for (const pid of prePolygonIds) {
+            prePolygonIds.forEach((pid) => {
               const polygonAttrib = getWholeLinePolygonRaw(this.attrib, pid);
-              if (!polygonAttrib) continue;
+              if (!polygonAttrib) return;
 
               if (!interrupt) {
                 this.polygonAfterHandler(polygonAttrib);
               } else {
                 wholeLineDelPolygon(this.attrib, pid);
               }
-            }
+            });
             resolve(interrupt ? "cancel" : "submit");
             enableMouse();
             this.container.constant.unuse();
@@ -148,6 +152,10 @@ export class EditWholeLine<
     };
   }
 
+  createPolygon() {
+    return this.editPolygon();
+  }
+
   pointAfterHandler(pointAttrib: WholeLinePointAttrib) {
     this.container.constant.use();
     const merge = mergeWholeLinePointsByPoint(this.attrib, pointAttrib.id);
@@ -253,7 +261,8 @@ export class EditWholeLine<
     super.init();
   }
 
-  mounted(): void {
-    super.mounted();
+  destory(): void {
+    this.endCreatePolygon && this.endCreatePolygon();
+    super.destory();
   }
 }

+ 16 - 73
src/board/packages/whole-line/editable/pen-whole-line.ts

@@ -1,4 +1,4 @@
-import { Ref, computed, ref, watchEffect } from "vue";
+import { Ref, ref } from "vue";
 import {
   WLL,
   WLP,
@@ -15,24 +15,14 @@ import {
 } from "../view";
 import {
   WholeLineHelperInfoAL,
-  penWholeLinePoygonsEditWithHelperMouse,
-  wholeLineAnalysisHelperInfo,
+  penWholeLinePoygonsEditWithHelperShapesMouse,
 } from "../service/whole-line-helper";
-import {
-  lineShapeFactory,
-  pointShapeFactory,
-  polygonShapeFactory,
-} from "../style";
+import { lineShapeFactory, polygonShapeFactory } from "../style";
 import { getWholeLinePolygonLinesRaw } from "../service";
-import {
-  getRealAbsoluteSize,
-  incEntitysFactoryGenerate,
-  openEntityDrag,
-} from "../../../shared";
+import { incEntitysFactoryGenerate, openEntityDrag } from "../../../shared";
 import { CustomizeShape, ShapeType } from "../../../type";
 import { KonvaEventObject } from "konva/lib/Node";
-import addMouseIco from "../../../shared/cursor/pic_pen_a.ico";
-import delMouseIco from "../../../shared/cursor/pic_pen_r.ico";
+import { EntityEvent } from "../../entity";
 
 export const penLineActShapeFactory = <T extends WholeLineLineAttrib>(
   attrib: T,
@@ -124,8 +114,9 @@ export type PenEnterEditProps<P extends WholeLinePointAttrib> = {
 
 // 钢笔模式 只允许一个多边形一个多边形的编辑
 export class PenEditWholeLine<
-  W extends WholeLineAttrib = WholeLineAttrib
-> extends WholeLine<W> {
+  W extends WholeLineAttrib = WholeLineAttrib,
+  EV extends EntityEvent = EntityEvent
+> extends WholeLine<W, EV> {
   editPolygonId = ref<string>();
   helperInfo?: Ref<WholeLineHelperInfoAL>;
   autoClose = true;
@@ -162,6 +153,7 @@ export class PenEditWholeLine<
   }
 
   initIncFactory() {
+    super.initIncFactory();
     this.incLinesFactory = incEntitysFactoryGenerate(
       WholeLineLine<WLL<W>>,
       this,
@@ -190,73 +182,24 @@ export class PenEditWholeLine<
 
   private _leaveEditMode: (() => void) | void = void 0;
   enterEditMode(props: PenEnterEditProps<WLP<W>>) {
-    const { helperInfo: helperInfoRaw, destory: mouseDestory } =
-      penWholeLinePoygonsEditWithHelperMouse({
+    this._leaveEditMode && this._leaveEditMode();
+    this._leaveEditMode = penWholeLinePoygonsEditWithHelperShapesMouse(
+      {
         ...props,
         closeAutoQuit: true,
         tree: this.container,
+        autoAdd: false,
         autoClose: this.autoClose,
-        config: this.attrib,
+        config: this.attrib as any,
         changePolygon: (pid: string) => {
           this.editPolygonId.value = pid;
         },
         quitHandler: () => {
-          stopWatchHelper();
           props.quitHandler && props.quitHandler();
         },
-      });
-
-    this.helperInfo = computed(
-      () =>
-        helperInfoRaw.value &&
-        wholeLineAnalysisHelperInfo(helperInfoRaw.value, this.autoClose)
+      },
+      this.shape
     );
-
-    const tempPoint = pointShapeFactory();
-    tempPoint.shape.listening(false);
-
-    const tempLine = lineShapeFactory();
-    tempLine.active();
-    tempLine.shape.dash([5, 5]);
-    tempLine.shape.listening(false);
-
-    const stopWatchHelper = watchEffect((onCleanup) => {
-      if (!this.helperInfo.value) return;
-
-      const { addLines, cloneLines, addPoints } = this.helperInfo.value;
-
-      const lineShapes = [...addLines, ...Object.values(cloneLines)].map(
-        (line) => {
-          tempLine.setData(line);
-          return tempLine.shape.clone();
-        }
-      );
-
-      const [scale] = getRealAbsoluteSize(this.shape, [1, 1]);
-      const pointShapes = addPoints.map((point) => {
-        tempPoint.setData(point);
-        tempPoint.shape.scale({ x: scale, y: scale });
-        return tempPoint.shape.clone();
-      });
-
-      this.shape.add(...lineShapes, ...pointShapes);
-
-      let clearCursor;
-      if (this.helperInfo.value.delPoints.length) {
-        clearCursor = this.container.setCursor(delMouseIco);
-      } else if (addPoints.length) {
-        clearCursor = this.container.setCursor(addMouseIco);
-      }
-
-      onCleanup(() => {
-        [...lineShapes, ...pointShapes].forEach((shape) => {
-          shape.remove();
-        });
-        clearCursor && clearCursor();
-      });
-    });
-
-    this._leaveEditMode = mouseDestory;
   }
 
   leaveEditMode() {

+ 11 - 0
src/board/packages/whole-line/service/whole-line-base.ts

@@ -137,6 +137,17 @@ export const getWholeLinePolygonLinesByPoint = (
   return pLines;
 };
 
+export const getWholeLinePolygonByPoint = (
+  config: WholeLineAttrib,
+  pointId: string
+) => {
+  return config.polygons.filter((polygon) => {
+    return polygon.lineIds.some((lId) =>
+      getWholeLineLineRaw(config, lId).pointIds.includes(pointId)
+    );
+  });
+};
+
 export const getWholeLinePolygonPoints = (
   config: WholeLineAttrib,
   polygonId: string

+ 11 - 4
src/board/packages/whole-line/service/whole-line-edit.ts

@@ -39,6 +39,7 @@ export type PenWholeLinePoygonsEditProps<
   config: WholeLineAttrib<P & Attrib>;
   polygonId?: string;
   adsorbRadius?: number;
+  autoAdd?: boolean;
   closeAutoQuit?: boolean;
   pointAttribFactory?: (pos: number[]) => Omit<P, "id">;
   quotePoint?: boolean;
@@ -64,6 +65,7 @@ export const penWholeLinePoygonsEdit = <
   pointAttribFactory,
   quotePoint,
   canOper,
+  autoAdd,
   adsorbRadius,
   canDelPoint,
   closeAutoQuit,
@@ -94,6 +96,7 @@ export const penWholeLinePoygonsEdit = <
   let polyginAttrib: WholeLinePolygonAttrib;
   let newMode = false;
   let prevId: string | null = null;
+  let canAddPolygon = true;
 
   const start = (currentPolygonId: string | null) => {
     polyginAttrib = getPolygonAttrib(currentPolygonId);
@@ -104,6 +107,7 @@ export const penWholeLinePoygonsEdit = <
     polygonId = polyginAttrib.id;
     newMode = !currentPolygonId;
     prevId = null;
+    canAddPolygon = autoAdd || polyginAttrib.lineIds.length < 2;
   };
 
   start(polygonId);
@@ -178,7 +182,6 @@ export const penWholeLinePoygonsEdit = <
             const prev = getWholeLinePoint(config, prevId);
             points.push([prev.x, prev.y]);
           }
-          console.log(points, [...points].reverse());
           position = getAdsorbPosition({
             tree,
             pixel,
@@ -259,9 +262,13 @@ export const penWholeLinePoygonsEdit = <
         // 持续添加模式
         return afterHandler(mergeChange(change, mChange));
       } else {
-        // 直接当成新建操作
-        start(null);
-        return continuous(evt);
+        if (canAddPolygon) {
+          // 直接当成新建操作
+          start(null);
+          return continuous(evt);
+        } else {
+          return { change, isClose };
+        }
       }
     } else if (prevId) {
       const [offset] = getRealAbsoluteSize(tree.stage, [4, 4], true);

+ 7 - 3
src/board/packages/whole-line/service/whole-line-helper.ts

@@ -137,14 +137,16 @@ export const penWholeLinePoygonsEditWithHelperMouse = <
     helperInfo.value = undefined;
   };
 
-  const quitHandler = (ev: KeyboardEvent) => {
-    if (ev.key === "Escape") {
+  const quitHandler = (ev: Event) => {
+    if (ev instanceof KeyboardEvent) {
+      ev.key === "Escape" && leaveEditMode();
+    } else {
       leaveEditMode();
+      ev.preventDefault();
     }
   };
 
   let leaveEditMode = () => {
-    console.log("leaveEditMode");
     if (hasTouchEvents) {
       stage.off("touchstart.editPolygonsMode", touchstartHandler);
       stage.off("touchmove.editPolygonsMode", touchmoveHandler);
@@ -154,6 +156,7 @@ export const penWholeLinePoygonsEditWithHelperMouse = <
       stage.off("mousedown.editPolygonsMode", downHandler);
       stage.off("mousemove.editPolygonsMode", moveHandler);
       stage.off("mouseup.editPolygonsMode", upHandler);
+      document.removeEventListener("contextmenu", quitHandler);
       document.removeEventListener("keydown", quitHandler);
     }
 
@@ -171,6 +174,7 @@ export const penWholeLinePoygonsEditWithHelperMouse = <
     stage.on("mousedown.editPolygonsMode", downHandler);
     stage.on("mousemove.editPolygonsMode", moveHandler);
     stage.on("mouseup.editPolygonsMode", upHandler);
+    document.addEventListener("contextmenu", quitHandler);
     document.addEventListener("keydown", quitHandler);
   }
 

+ 0 - 2
src/board/packages/whole-line/service/whole-line-tear-merge.ts

@@ -779,6 +779,4 @@ export const fixWholeLineConfig = (config: WholeLineAttrib) => {
       lineIds: [lineId],
     });
   });
-
-  console.log("===>", delLines);
 };

+ 4 - 3
src/board/packages/whole-line/style.ts

@@ -110,6 +110,7 @@ export const polygonShapeFactory = (props: PolygonShapeProps = {}) => {
 
   const group = new Group();
   const path = new Line({
+    name: "polygon-line",
     closed: true,
     fill,
   });
@@ -125,20 +126,20 @@ export const polygonShapeFactory = (props: PolygonShapeProps = {}) => {
   }
 
   const common = (ev?: KonvaEventObject<any>) => {
-    // path.fill(polygon.fill);
+    path.fill(polygon.fill);
     closeLine && closeLine.common(ev);
   };
   const active = (ev: KonvaEventObject<any>) => {
-    // path.fill(polygon.activeFill);
+    path.fill(polygon.activeFill);
     closeLine && closeLine.active && closeLine.active(ev);
   };
 
   common();
   return {
+    closeLine,
     shape: group,
     setData(data: number[]) {
       path.points(data);
-
       if (closeLine) {
         if (data.length > 4) {
           const ndxs = [data.length - 2, data.length - 1, 0, 1];

+ 3 - 2
src/board/packages/whole-line/view/whole-line.ts

@@ -5,7 +5,7 @@ import { WholeLinePoint, WholeLinePointAttrib } from "./whole-line-point";
 import { WholeLineLine, WholeLineLineAttrib } from "./whole-line-line";
 import { WholeLinePolygon, WholeLinePolygonAttrib } from "./whole-line-polygon";
 import { Group } from "konva/lib/Group";
-import { Entity, EntityProps } from "../../entity";
+import { Entity, EntityEvent, EntityProps } from "../../entity";
 import {
   IncEntitys,
   IncEntitysFactory,
@@ -57,10 +57,11 @@ export type WholeLineInc<W extends WholeLineAttrib = WholeLineAttrib> = {
 
 export class WholeLine<
   W extends WholeLineAttrib = WholeLineAttrib,
+  EV extends EntityEvent = EntityEvent,
   PS extends ShapeType = ShapeType,
   LS extends ShapeType = ShapeType,
   PYS extends ShapeType = ShapeType
-> extends Entity<W, Group> {
+> extends Entity<W, Group, EV> {
   static namespace = "whole-line";
 
   incLinesFactory: IncEntitysFactory<WLL<W>, WholeLineLine<WLL<W>, LS>>;

+ 2 - 1
src/board/plugins/bound-plugin.ts

@@ -2,6 +2,7 @@ import { Matrix3, Vector2 } from "three";
 import { Container } from "../packages";
 import { openShapeDrag } from "../shared";
 import { getAbsoluteTransform } from "../shared/shape-helper";
+import { Layer } from "konva/lib/Layer";
 
 export type BoundQueryPluginProps = {
   move?: boolean;
@@ -165,9 +166,9 @@ export class BoundQueryPlugin {
     const offsetX = -this.bound[0] * scaleX;
     const offsetY = -this.bound[1] * scaleY;
     // 更新Konva Stage的位置和缩放
-
     stage.scale({ x: scaleX, y: scaleY });
     stage.position({ x: offsetX, y: offsetY });
     this.tree.redraw();
+    (this.tree.shape as Layer).batchDraw();
   }
 }

+ 1 - 0
src/board/plugins/camera-plugin.ts

@@ -226,6 +226,7 @@ export class CameraQueryPlugin {
   }
 
   update() {
+    console.log(this.clipMat.clone().multiply(this.cameraMat));
     this.tree.updateViewMat(this.clipMat.clone().multiply(this.cameraMat));
   }
 }

+ 2 - 2
src/board/register.ts

@@ -42,13 +42,13 @@ export const register = <
       if (virtual.parentElement) {
         virtual.parentElement.removeChild(virtual);
       }
-      console.log(virtual);
       dom.appendChild(virtual);
       virtual.style.width = "100%";
       virtual.style.height = "100%";
 
       container.stage.width(virtual.offsetWidth);
-      container.stage.width(virtual.offsetHeight);
+      container.stage.height(virtual.offsetHeight);
+
       mountedDom = dom;
     };
 

+ 1 - 0
src/board/shared/act.ts

@@ -67,6 +67,7 @@ export const pathsToActShape = (props: PathsToActShapeProps, test = false) => {
     },
     shape: group,
     setData(data) {
+      console.log("set", data);
       group.position(data);
       props.fixed && setStyle();
     },

+ 4 - 5
src/board/shared/entity-utils.ts

@@ -40,7 +40,7 @@ export const entityFactory = <
   }
   entity.init();
   entity.mount(entity.teleport);
-  if (parent.isMounted) {
+  if (parent?.isMounted) {
     entity.mounted();
   }
   created && created(entity);
@@ -61,10 +61,10 @@ export type IncEntitys<T extends Attrib, E extends Entity<T, any>> = {
 export const incEntitysFactoryGenerate = <
   T extends Attrib,
   S extends ShapeType,
-  C extends EntityType<T, S, { attrib: T }>
+  C extends EntityType<T, S, { attrib: T }, any>
 >(
   Type: C,
-  parent?: Entity<any, any>,
+  parent?: Entity<any, any, any>,
   extra?: (self: InstanceType<C>) => void,
   created?: (self: InstanceType<C>) => void
 ) => {
@@ -97,7 +97,6 @@ export const incEntitysFactoryGenerate = <
     const adds = addPort.map((d) => add(findAttrib(attribs, d.id)));
 
     const upds = changePort.map((id) => {
-      console.log("update", id);
       const newAttrib = findAttrib(attribs, id);
       if (inRevise(newAttrib, cache[id].attrib)) {
         cache[id].setAttrib(findAttrib(attribs, id));
@@ -109,7 +108,7 @@ export const incEntitysFactoryGenerate = <
     return {
       adds,
       dels,
-      upds: [],
+      upds,
     };
   };
 };

+ 65 - 43
src/board/shared/shape-mose.ts

@@ -1,4 +1,4 @@
-import { Attrib, ShapeStyles, ShapeType } from "../type";
+import { Attrib, ShapeStyles, ShapeStylesStatus, ShapeType } from "../type";
 import { Entity } from "../packages/entity";
 import { Shape } from "konva/lib/Shape";
 import { Group } from "konva/lib/Group";
@@ -13,11 +13,18 @@ export const disableMouse = () => {
   dragShapes.forEach((shape) => shape.draggable(false));
 };
 export const enableMouse = () => {
-  console.log("enable mose");
   mouseDisabled = false;
   dragShapes.forEach((shape) => shape.draggable(true));
 };
 
+export const getActiveKey = (
+  status: Partial<ShapeStylesStatus>,
+  excludes: string[] = []
+) => {
+  const apis = ["draging", "active", "hover"] as const;
+  return apis.find((api) => status[api] && !excludes.includes(api));
+};
+
 export const openShapeMouseStyles = <T extends Shape | Group>(
   shape: T,
   styles: ShapeStyles,
@@ -31,72 +38,86 @@ export const openShapeMouseStyles = <T extends Shape | Group>(
     useEvents.push(name);
   };
 
-  let enter = false;
-  let draging = false;
-  let active = false;
-
-  const mouseHandler = (ev: KonvaEventObject<any>) => {
-    const api = draging
-      ? "draging"
-      : active
-      ? "active"
-      : enter
-      ? "hover"
-      : "common";
-    if (!mouseDisabled) {
+  let outStatus: Partial<ShapeStylesStatus> | null;
+  if (styles.bus) {
+    styles.bus.on("statusChange", (status) => {
+      outStatus = status;
+      if (status) {
+        Object.assign(inStatus, status);
+      }
+      mouseHandler();
+    });
+  }
+
+  const inStatus: ShapeStylesStatus = {
+    hover: false,
+    draging: false,
+    active: false,
+  };
+  let prevApi = "common";
+
+  const mouseHandler = (ev?: KonvaEventObject<any>) => {
+    let api: string = outStatus && getActiveKey(outStatus);
+    if (!api) {
+      api = mouseDisabled ? "common" : getActiveKey(inStatus) || "common";
+    }
+    if (prevApi !== api) {
       styles[api] && styles[api](ev);
+      prevApi = api;
     }
   };
 
   if (styles.hover) {
     useOn(`mouseenter.${namespace}`, (ev) => {
-      enter = true;
+      inStatus.hover = true;
       mouseHandler(ev);
     });
     useOn(`mouseleave.${namespace}`, (ev) => {
-      if (!draging) {
-        enter = false;
-        mouseHandler(ev);
-      }
+      inStatus.hover = false;
+      mouseHandler(ev);
     });
   }
 
+  let unCheckActive: () => void;
   if (styles.active) {
+    let clickTime: number = 0;
     useOn(`click.${namespace} touchend.${namespace}`, (ev) => {
       if (!styles.active) return;
-      if (draging) return;
-      active = true;
+      inStatus.active = true;
       mouseHandler(ev);
+      clickTime = Date.now();
+    });
 
-      setTimeout(() => {
-        const stage = shape.getStage();
-        if (!stage) return;
-        stage.on(
-          `click.${namespace}${shape.id()} touchend.${namespace}${shape.id()}`,
-          (evt) => {
-            if (evt.target !== shape) {
-              active = false;
-              mouseHandler(evt);
-            }
-            setTimeout(() => {
-              if (!stage) return;
-              stage.off(
-                `click.${namespace}${shape.id()} touchend.${namespace}${shape.id()}`
-              );
-            });
-          }
-        );
+    const e = `click.${namespace}${shape.id()} touchend.${namespace}${shape.id()}`;
+    let count = 3;
+    let stage;
+    const interval = setInterval(() => {
+      if (!(stage = shape.getStage())) {
+        if (--count < 0) console.error("可能发生资源泄露");
+        return;
+      }
+      clearInterval(interval);
+      stage.on(e, (evt) => {
+        if (Date.now() - clickTime > 500 && evt.target !== shape) {
+          inStatus.active = false;
+          mouseHandler(evt);
+        }
       });
-    });
+    }, 100);
+
+    unCheckActive = () => {
+      stage && stage.off(e);
+      clearInterval(interval);
+    };
   }
 
   useOn(`dragstart.${namespace}`, (ev) => {
-    draging = true;
+    inStatus.draging = true;
     mouseHandler(ev);
   });
   useOn(`dragend.${namespace}`, (ev) => {
     setTimeout(() => {
-      draging = false;
+      inStatus.draging = false;
       mouseHandler(ev);
     }, 16);
   });
@@ -104,6 +125,7 @@ export const openShapeMouseStyles = <T extends Shape | Group>(
   return () => {
     shape.listening(false);
     shape.off(useEvents.join(" "));
+    unCheckActive && unCheckActive();
   };
 };
 

+ 14 - 2
src/board/shared/util.ts

@@ -1,5 +1,5 @@
 import { reactive, watch } from "vue";
-import { Attrib, GetSetPick } from "../type";
+import { Attrib, GetSetPick, ShapeType } from "../type";
 import { inRevise, toRawType } from "./public";
 import { Shape } from "konva/lib/Shape";
 import { Group } from "konva/lib/Group";
@@ -192,7 +192,7 @@ export const testPoint = (stage: Stage, points: number[][]) => {
   });
 };
 
-export const getFlatChildren = (root: Entity) => {
+export const getFlatChildren = (root: Entity<Attrib, ShapeType, any>) => {
   const flatChildren: Entity[] = [];
   for (const child of root.children) {
     flatChildren.push(child, ...getFlatChildren(child));
@@ -202,3 +202,15 @@ export const getFlatChildren = (root: Entity) => {
 
 export const generateId = (attribs: Attrib[]) =>
   (Math.max(1, ...attribs.map(({ id }) => Number(id))) + 1).toString();
+
+export const mergeFuns = (...fns: (() => void)[] | (() => void)[][]) => {
+  return () => {
+    fns.forEach((fn) => {
+      if (Array.isArray(fn)) {
+        fn.forEach((f) => f());
+      } else {
+        fn();
+      }
+    });
+  };
+};

+ 18 - 7
src/board/type.d.ts

@@ -1,11 +1,12 @@
-import konva from "konva";
 import { Shape } from "konva/lib/Shape";
 import { Group } from "konva/lib/Group";
 import { Layer } from "konva/lib/Layer";
 import { Stage } from "konva/lib/Stage";
-import { Container, Entity, EntityType } from "./packages";
+import { Container } from "./packages";
+import { Emitter } from "mitt";
+import { KonvaEventObject } from "konva/lib/Node";
 
-type ShapeType = Group | Layer | Stage | Shape;
+export type ShapeType = Group | Layer | Stage | Shape;
 
 interface GetSet<Type, This> {
   (a: Type): This;
@@ -14,11 +15,21 @@ export type GetSetPick<T extends Shape | Group> = {
   [key in keyof T]?: T[key] extends GetSet<infer V, T> ? V : never;
 };
 
+export type ShapeStylesStatus = {
+  draging: boolean;
+  hover: boolean;
+  active: boolean;
+};
 export type ShapeStyles = {
-  common: (ev: KonvaEventObject<any>) => void;
-  hover?: (ev: KonvaEventObject<any>) => void;
-  active?: (ev: KonvaEventObject<any>) => void;
-  draging?: (ev: KonvaEventObject<any>) => void;
+  common: (ev?: KonvaEventObject<any>) => void;
+  bus?: Emitter<{ statusChange: Partial<ShapeStylesStatus> | null }>;
+  getStatus?: (
+    status: ShapeStylesStatus,
+    ev: KonvaEventObject<any>
+  ) => "common" | "hover" | "active" | "draging" | null;
+  hover?: (ev?: KonvaEventObject<any>) => void;
+  active?: (ev?: KonvaEventObject<any>) => void;
+  draging?: (ev?: KonvaEventObject<any>) => void;
 };
 
 export type Attrib = {

+ 0 - 126
src/components/query-board/streData-merge.json

@@ -1,126 +0,0 @@
-{
-  "rooms": [
-    {
-      "id": "1",
-      "points": [
-        {
-          "x": 360,
-          "y": 232,
-          "id": "2"
-        },
-        {
-          "x": 773,
-          "y": 206,
-          "id": "3"
-        },
-        {
-          "x": 734,
-          "y": 455,
-          "id": "4"
-        },
-        {
-          "x": 339,
-          "y": 440,
-          "id": "5"
-        },
-        {
-          "x": 688,
-          "y": 606,
-          "id": "8"
-        },
-        {
-          "x": 443,
-          "y": 594,
-          "id": "9"
-        },
-        {
-          "x": 556.8756799999999,
-          "y": 448.27376,
-          "id": "10"
-        }
-      ],
-      "lines": [
-        {
-          "id": "2",
-          "pointIds": [
-            "2",
-            "3"
-          ]
-        },
-        {
-          "id": "3",
-          "pointIds": [
-            "3",
-            "4"
-          ]
-        },
-        {
-          "id": "5",
-          "pointIds": [
-            "5",
-            "2"
-          ]
-        },
-        {
-          "id": "8",
-          "pointIds": [
-            "8",
-            "9"
-          ]
-        },
-        {
-          "id": "10",
-          "pointIds": [
-            "9",
-            "10"
-          ]
-        },
-        {
-          "id": "12",
-          "pointIds": [
-            "4",
-            "10"
-          ]
-        },
-        {
-          "id": "13",
-          "pointIds": [
-            "10",
-            "5"
-          ]
-        },
-        {
-          "id": "14",
-          "pointIds": [
-            "10",
-            "8"
-          ]
-        }
-      ],
-      "polygons": [
-        {
-          "id": "2",
-          "lineIds": [
-            "2",
-            "3",
-            "12",
-            "13",
-            "5"
-          ]
-        },
-        {
-          "id": "3",
-          "lineIds": [
-            "10",
-            "14",
-            "8"
-          ]
-        },
-        {
-          "id": "4",
-          "lineIds": []
-        }
-      ]
-    }
-  ]
-}

+ 5 - 7
tsconfig.json

@@ -1,25 +1,23 @@
 {
   "compilerOptions": {
-    "target": "ES2020",
-    "useDefineForClassFields": true,
+    "target": "es2015",
     "module": "ESNext",
     "lib": [
-      "ES2020",
+      "es2015",
       "DOM",
       "DOM.Iterable"
     ],
     "skipLibCheck": true,
     /* Bundler mode */
-    "moduleResolution": "bundler",
-    "allowImportingTsExtensions": true,
+    "moduleResolution": "Node",
+    "allowImportingTsExtensions": false,
     "resolveJsonModule": true,
     "isolatedModules": true,
-    "noEmit": true,
     "jsx": "preserve",
     /* Linting */
     "noUnusedLocals": true,
     "noUnusedParameters": true,
-    "noFallthroughCasesInSwitch": true
+    "noFallthroughCasesInSwitch": true,
   },
   "include": [
     "src/**/*.ts",

+ 3 - 1
tsconfig.node.json

@@ -1,6 +1,7 @@
 {
   "compilerOptions": {
     "composite": true,
+    "resolveJsonModule": true,
     "esModuleInterop": true,
     "module": "ESNext",
     "skipLibCheck": true,
@@ -8,6 +9,7 @@
     "allowSyntheticDefaultImports": true
   },
   "include": [
-    "vite.config.ts"
+    "vite.config.ts",
+    "generate-ts.ts",
   ]
 }

+ 18 - 7
vite.config.ts

@@ -1,20 +1,23 @@
 import { defineConfig } from "vite";
-import vue from "@vitejs/plugin-vue";
 import { resolve } from "path";
+import vue from "@vitejs/plugin-vue";
+import { generateDTS } from "./generate-ts";
 
-let app = "liantong";
-if (process.argv.length > 3) {
+let app = "";
+if (process.argv.length > 4) {
   app = process.argv[process.argv.length - 1].trim();
 }
+const enter = app ? `src/app/${app}/` : `src/board/`;
+const name = app ? app : "board";
 
 // https://vitejs.dev/config/
 export default defineConfig({
   build: {
     lib: {
-      entry: resolve(__dirname, `src/app/${app}/index.ts`),
-      name: app,
+      entry: resolve(__dirname, enter, `index.ts`),
+      name: name,
       // the proper extensions will be added
-      fileName: app,
+      fileName: name,
     },
     rollupOptions: {
       // 确保外部化处理那些你不想打包进库的依赖
@@ -27,7 +30,15 @@ export default defineConfig({
       },
     },
   },
-  plugins: [vue()],
+  plugins: [
+    vue(),
+    {
+      name: "ts-generate",
+      closeBundle: async () => {
+        await generateDTS(app);
+      },
+    },
+  ],
   server: {
     port: 9005,
   },