louhangfei před 2 roky
rodič
revize
4824d317d5

+ 3 - 2
package.json

@@ -48,6 +48,7 @@
     "element-plus": "2.3.6",
     "element-resize-detector": "1.2.4",
     "fabric": "5.3.0",
+    "konva": "9.3.0",
     "lodash-es": "4.17.21",
     "mockjs": "1.1.0",
     "nprogress": "0.2.0",
@@ -108,7 +109,7 @@
     "tailwindcss": "3.3.2",
     "ts-node": "10.9.1",
     "typescript": "4.7.4",
-    "vite": "3.2.7",
+    "vite": "5.0.10",
     "vite-plugin-compression": "0.5.1",
     "vite-plugin-html": "3.2.0",
     "vite-plugin-mock": "2.9.6",
@@ -146,4 +147,4 @@
       ]
     }
   }
-}
+}

+ 401 - 242
pnpm-lock.yaml

@@ -56,6 +56,9 @@ dependencies:
   fabric:
     specifier: 5.3.0
     version: 5.3.0
+  konva:
+    specifier: 9.3.0
+    version: 9.3.0
   lodash-es:
     specifier: 4.17.21
     version: 4.17.21
@@ -87,7 +90,7 @@ dependencies:
     specifier: 3.3.4
     version: 3.3.4
   vue-hooks-plus:
-    specifier: ^1.8.6
+    specifier: 1.8.6
     version: 1.8.6(vue@3.3.4)
   vue-router:
     specifier: 4.1.2
@@ -132,7 +135,7 @@ devDependencies:
     version: 5.30.7(eslint@8.20.0)(typescript@4.7.4)
   '@vitejs/plugin-vue':
     specifier: 2.3.3
-    version: 2.3.3(vite@3.2.7)(vue@3.3.4)
+    version: 2.3.3(vite@5.0.10)(vue@3.3.4)
   '@vitejs/plugin-vue-jsx':
     specifier: 1.3.10
     version: 1.3.10
@@ -233,23 +236,23 @@ devDependencies:
     specifier: 4.7.4
     version: 4.7.4
   vite:
-    specifier: 3.2.7
-    version: 3.2.7(@types/node@17.0.45)(sass@1.53.0)
+    specifier: 5.0.10
+    version: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
   vite-plugin-compression:
     specifier: 0.5.1
-    version: 0.5.1(vite@3.2.7)
+    version: 0.5.1(vite@5.0.10)
   vite-plugin-html:
     specifier: 3.2.0
-    version: 3.2.0(vite@3.2.7)
+    version: 3.2.0(vite@5.0.10)
   vite-plugin-mock:
     specifier: 2.9.6
-    version: 2.9.6(mockjs@1.1.0)(vite@3.2.7)
+    version: 2.9.6(mockjs@1.1.0)(vite@5.0.10)
   vite-plugin-style-import:
     specifier: 2.0.0
-    version: 2.0.0(vite@3.2.7)
+    version: 2.0.0(vite@5.0.10)
   vite-plugin-vue-setup-extend:
     specifier: 0.4.0
-    version: 0.4.0(vite@3.2.7)
+    version: 0.4.0(vite@5.0.10)
   vue-eslint-parser:
     specifier: 9.0.3
     version: 9.0.3(eslint@8.20.0)
@@ -788,8 +791,26 @@ packages:
       get-tsconfig: 4.2.0
     dev: true
 
-  /@esbuild/android-arm@0.15.14:
-    resolution: {integrity: sha512-+Rb20XXxRGisNu2WmNKk+scpanb7nL5yhuI1KR9wQFiC43ddPj/V1fmNyzlFC9bKiG4mYzxW7egtoHVcynr+OA==}
+  /@esbuild/aix-ppc64@0.19.10:
+    resolution: {integrity: sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q==}
+    engines: {node: '>=12'}
+    cpu: [ppc64]
+    os: [aix]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/android-arm64@0.19.10:
+    resolution: {integrity: sha512-1X4CClKhDgC3by7k8aOWZeBXQX8dHT5QAMCAQDArCLaYfkppoARvh0fit3X2Qs+MXDngKcHv6XXyQCpY0hkK1Q==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [android]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/android-arm@0.19.10:
+    resolution: {integrity: sha512-7W0bK7qfkw1fc2viBfrtAEkDKHatYfHzr/jKAHNr9BvkYDXPcC6bodtm8AyLJNNuqClLNaeTLuwURt4PRT9d7w==}
     engines: {node: '>=12'}
     cpu: [arm]
     os: [android]
@@ -797,6 +818,78 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/android-x64@0.19.10:
+    resolution: {integrity: sha512-O/nO/g+/7NlitUxETkUv/IvADKuZXyH4BHf/g/7laqKC4i/7whLpB0gvpPc2zpF0q9Q6FXS3TS75QHac9MvVWw==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [android]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/darwin-arm64@0.19.10:
+    resolution: {integrity: sha512-YSRRs2zOpwypck+6GL3wGXx2gNP7DXzetmo5pHXLrY/VIMsS59yKfjPizQ4lLt5vEI80M41gjm2BxrGZ5U+VMA==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [darwin]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/darwin-x64@0.19.10:
+    resolution: {integrity: sha512-alfGtT+IEICKtNE54hbvPg13xGBe4GkVxyGWtzr+yHO7HIiRJppPDhOKq3zstTcVf8msXb/t4eavW3jCDpMSmA==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [darwin]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/freebsd-arm64@0.19.10:
+    resolution: {integrity: sha512-dMtk1wc7FSH8CCkE854GyGuNKCewlh+7heYP/sclpOG6Cectzk14qdUIY5CrKDbkA/OczXq9WesqnPl09mj5dg==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [freebsd]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/freebsd-x64@0.19.10:
+    resolution: {integrity: sha512-G5UPPspryHu1T3uX8WiOEUa6q6OlQh6gNl4CO4Iw5PS+Kg5bVggVFehzXBJY6X6RSOMS8iXDv2330VzaObm4Ag==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [freebsd]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-arm64@0.19.10:
+    resolution: {integrity: sha512-QxaouHWZ+2KWEj7cGJmvTIHVALfhpGxo3WLmlYfJ+dA5fJB6lDEIg+oe/0//FuyVHuS3l79/wyBxbHr0NgtxJQ==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-arm@0.19.10:
+    resolution: {integrity: sha512-j6gUW5aAaPgD416Hk9FHxn27On28H4eVI9rJ4az7oCGTFW48+LcgNDBN+9f8rKZz7EEowo889CPKyeaD0iw9Kg==}
+    engines: {node: '>=12'}
+    cpu: [arm]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-ia32@0.19.10:
+    resolution: {integrity: sha512-4ub1YwXxYjj9h1UIZs2hYbnTZBtenPw5NfXCRgEkGb0b6OJ2gpkMvDqRDYIDRjRdWSe/TBiZltm3Y3Q8SN1xNg==}
+    engines: {node: '>=12'}
+    cpu: [ia32]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@esbuild/linux-loong64@0.14.54:
     resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==}
     engines: {node: '>=12'}
@@ -806,8 +899,8 @@ packages:
     dev: true
     optional: true
 
-  /@esbuild/linux-loong64@0.15.14:
-    resolution: {integrity: sha512-eQi9rosGNVQFJyJWV0HCA5WZae/qWIQME7s8/j8DMvnylfBv62Pbu+zJ2eUDqNf2O4u3WB+OEXyfkpBoe194sg==}
+  /@esbuild/linux-loong64@0.19.10:
+    resolution: {integrity: sha512-lo3I9k+mbEKoxtoIbM0yC/MZ1i2wM0cIeOejlVdZ3D86LAcFXFRdeuZmh91QJvUTW51bOK5W2BznGNIl4+mDaA==}
     engines: {node: '>=12'}
     cpu: [loong64]
     os: [linux]
@@ -815,6 +908,105 @@ packages:
     dev: true
     optional: true
 
+  /@esbuild/linux-mips64el@0.19.10:
+    resolution: {integrity: sha512-J4gH3zhHNbdZN0Bcr1QUGVNkHTdpijgx5VMxeetSk6ntdt+vR1DqGmHxQYHRmNb77tP6GVvD+K0NyO4xjd7y4A==}
+    engines: {node: '>=12'}
+    cpu: [mips64el]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-ppc64@0.19.10:
+    resolution: {integrity: sha512-tgT/7u+QhV6ge8wFMzaklOY7KqiyitgT1AUHMApau32ZlvTB/+efeCtMk4eXS+uEymYK249JsoiklZN64xt6oQ==}
+    engines: {node: '>=12'}
+    cpu: [ppc64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-riscv64@0.19.10:
+    resolution: {integrity: sha512-0f/spw0PfBMZBNqtKe5FLzBDGo0SKZKvMl5PHYQr3+eiSscfJ96XEknCe+JoOayybWUFQbcJTrk946i3j9uYZA==}
+    engines: {node: '>=12'}
+    cpu: [riscv64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-s390x@0.19.10:
+    resolution: {integrity: sha512-pZFe0OeskMHzHa9U38g+z8Yx5FNCLFtUnJtQMpwhS+r4S566aK2ci3t4NCP4tjt6d5j5uo4h7tExZMjeKoehAA==}
+    engines: {node: '>=12'}
+    cpu: [s390x]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/linux-x64@0.19.10:
+    resolution: {integrity: sha512-SpYNEqg/6pZYoc+1zLCjVOYvxfZVZj6w0KROZ3Fje/QrM3nfvT2llI+wmKSrWuX6wmZeTapbarvuNNK/qepSgA==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/netbsd-x64@0.19.10:
+    resolution: {integrity: sha512-ACbZ0vXy9zksNArWlk2c38NdKg25+L9pr/mVaj9SUq6lHZu/35nx2xnQVRGLrC1KKQqJKRIB0q8GspiHI3J80Q==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [netbsd]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/openbsd-x64@0.19.10:
+    resolution: {integrity: sha512-PxcgvjdSjtgPMiPQrM3pwSaG4kGphP+bLSb+cihuP0LYdZv1epbAIecHVl5sD3npkfYBZ0ZnOjR878I7MdJDFg==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [openbsd]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/sunos-x64@0.19.10:
+    resolution: {integrity: sha512-ZkIOtrRL8SEJjr+VHjmW0znkPs+oJXhlJbNwfI37rvgeMtk3sxOQevXPXjmAPZPigVTncvFqLMd+uV0IBSEzqA==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [sunos]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/win32-arm64@0.19.10:
+    resolution: {integrity: sha512-+Sa4oTDbpBfGpl3Hn3XiUe4f8TU2JF7aX8cOfqFYMMjXp6ma6NJDztl5FDG8Ezx0OjwGikIHw+iA54YLDNNVfw==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/win32-ia32@0.19.10:
+    resolution: {integrity: sha512-EOGVLK1oWMBXgfttJdPHDTiivYSjX6jDNaATeNOaCOFEVcfMjtbx7WVQwPSE1eIfCp/CaSF2nSrDtzc4I9f8TQ==}
+    engines: {node: '>=12'}
+    cpu: [ia32]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@esbuild/win32-x64@0.19.10:
+    resolution: {integrity: sha512-whqLG6Sc70AbU73fFYvuYzaE4MNMBIlR1Y/IrUeOXFrWHxBEjjbZaQ3IXIQS8wJdAzue2GwYZCjOrgrU1oUHoA==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@eslint/eslintrc@1.3.0:
     resolution: {integrity: sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -997,6 +1189,110 @@ packages:
       picomatch: 2.3.1
     dev: true
 
+  /@rollup/rollup-android-arm-eabi@4.9.1:
+    resolution: {integrity: sha512-6vMdBZqtq1dVQ4CWdhFwhKZL6E4L1dV6jUjuBvsavvNJSppzi6dLBbuV+3+IyUREaj9ZFvQefnQm28v4OCXlig==}
+    cpu: [arm]
+    os: [android]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-android-arm64@4.9.1:
+    resolution: {integrity: sha512-Jto9Fl3YQ9OLsTDWtLFPtaIMSL2kwGyGoVCmPC8Gxvym9TCZm4Sie+cVeblPO66YZsYH8MhBKDMGZ2NDxuk/XQ==}
+    cpu: [arm64]
+    os: [android]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-darwin-arm64@4.9.1:
+    resolution: {integrity: sha512-LtYcLNM+bhsaKAIGwVkh5IOWhaZhjTfNOkGzGqdHvhiCUVuJDalvDxEdSnhFzAn+g23wgsycmZk1vbnaibZwwA==}
+    cpu: [arm64]
+    os: [darwin]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-darwin-x64@4.9.1:
+    resolution: {integrity: sha512-KyP/byeXu9V+etKO6Lw3E4tW4QdcnzDG/ake031mg42lob5tN+5qfr+lkcT/SGZaH2PdW4Z1NX9GHEkZ8xV7og==}
+    cpu: [x64]
+    os: [darwin]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-arm-gnueabihf@4.9.1:
+    resolution: {integrity: sha512-Yqz/Doumf3QTKplwGNrCHe/B2p9xqDghBZSlAY0/hU6ikuDVQuOUIpDP/YcmoT+447tsZTmirmjgG3znvSCR0Q==}
+    cpu: [arm]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-arm64-gnu@4.9.1:
+    resolution: {integrity: sha512-u3XkZVvxcvlAOlQJ3UsD1rFvLWqu4Ef/Ggl40WAVCuogf4S1nJPHh5RTgqYFpCOvuGJ7H5yGHabjFKEZGExk5Q==}
+    cpu: [arm64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-arm64-musl@4.9.1:
+    resolution: {integrity: sha512-0XSYN/rfWShW+i+qjZ0phc6vZ7UWI8XWNz4E/l+6edFt+FxoEghrJHjX1EY/kcUGCnZzYYRCl31SNdfOi450Aw==}
+    cpu: [arm64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-riscv64-gnu@4.9.1:
+    resolution: {integrity: sha512-LmYIO65oZVfFt9t6cpYkbC4d5lKHLYv5B4CSHRpnANq0VZUQXGcCPXHzbCXCz4RQnx7jvlYB1ISVNCE/omz5cw==}
+    cpu: [riscv64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-x64-gnu@4.9.1:
+    resolution: {integrity: sha512-kr8rEPQ6ns/Lmr/hiw8sEVj9aa07gh1/tQF2Y5HrNCCEPiCBGnBUt9tVusrcBBiJfIt1yNaXN6r1CCmpbFEDpg==}
+    cpu: [x64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-linux-x64-musl@4.9.1:
+    resolution: {integrity: sha512-t4QSR7gN+OEZLG0MiCgPqMWZGwmeHhsM4AkegJ0Kiy6TnJ9vZ8dEIwHw1LcZKhbHxTY32hp9eVCMdR3/I8MGRw==}
+    cpu: [x64]
+    os: [linux]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-win32-arm64-msvc@4.9.1:
+    resolution: {integrity: sha512-7XI4ZCBN34cb+BH557FJPmh0kmNz2c25SCQeT9OiFWEgf8+dL6ZwJ8f9RnUIit+j01u07Yvrsuu1rZGxJCc51g==}
+    cpu: [arm64]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-win32-ia32-msvc@4.9.1:
+    resolution: {integrity: sha512-yE5c2j1lSWOH5jp+Q0qNL3Mdhr8WuqCNVjc6BxbVfS5cAS6zRmdiw7ktb8GNpDCEUJphILY6KACoFoRtKoqNQg==}
+    cpu: [ia32]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
+  /@rollup/rollup-win32-x64-msvc@4.9.1:
+    resolution: {integrity: sha512-PyJsSsafjmIhVgaI1Zdj7m8BB8mMckFah/xbpplObyHfiXzKcI5UOUXRyOdHW7nz4DpMCuzLnF7v5IWHenCwYA==}
+    cpu: [x64]
+    os: [win32]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /@sxzz/popperjs-es@2.11.7:
     resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==}
     dev: false
@@ -1297,14 +1593,14 @@ packages:
       - supports-color
     dev: true
 
-  /@vitejs/plugin-vue@2.3.3(vite@3.2.7)(vue@3.3.4):
+  /@vitejs/plugin-vue@2.3.3(vite@5.0.10)(vue@3.3.4):
     resolution: {integrity: sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==}
     engines: {node: '>=12.0.0'}
     peerDependencies:
       vite: ^2.5.10
       vue: ^3.2.25
     dependencies:
-      vite: 3.2.7(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
       vue: 3.3.4
     dev: true
 
@@ -3016,15 +3312,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-android-64@0.15.14:
-    resolution: {integrity: sha512-HuilVIb4rk9abT4U6bcFdU35UHOzcWVGLSjEmC58OVr96q5UiRqzDtWjPlCMugjhgUGKEs8Zf4ueIvYbOStbIg==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [android]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-android-arm64@0.14.54:
     resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==}
     engines: {node: '>=12'}
@@ -3034,15 +3321,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-android-arm64@0.15.14:
-    resolution: {integrity: sha512-/QnxRVxsR2Vtf3XottAHj7hENAMW2wCs6S+OZcAbc/8nlhbAL/bCQRCVD78VtI5mdwqWkVi3wMqM94kScQCgqg==}
-    engines: {node: '>=12'}
-    cpu: [arm64]
-    os: [android]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-darwin-64@0.14.54:
     resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==}
     engines: {node: '>=12'}
@@ -3052,15 +3330,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-darwin-64@0.15.14:
-    resolution: {integrity: sha512-ToNuf1uifu8hhwWvoZJGCdLIX/1zpo8cOGnT0XAhDQXiKOKYaotVNx7pOVB1f+wHoWwTLInrOmh3EmA7Fd+8Vg==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [darwin]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-darwin-arm64@0.14.54:
     resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==}
     engines: {node: '>=12'}
@@ -3070,15 +3339,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-darwin-arm64@0.15.14:
-    resolution: {integrity: sha512-KgGP+y77GszfYJgceO0Wi/PiRtYo5y2Xo9rhBUpxTPaBgWDJ14gqYN0+NMbu+qC2fykxXaipHxN4Scaj9tUS1A==}
-    engines: {node: '>=12'}
-    cpu: [arm64]
-    os: [darwin]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-freebsd-64@0.14.54:
     resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==}
     engines: {node: '>=12'}
@@ -3088,15 +3348,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-freebsd-64@0.15.14:
-    resolution: {integrity: sha512-xr0E2n5lyWw3uFSwwUXHc0EcaBDtsal/iIfLioflHdhAe10KSctV978Te7YsfnsMKzcoGeS366+tqbCXdqDHQA==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [freebsd]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-freebsd-arm64@0.14.54:
     resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==}
     engines: {node: '>=12'}
@@ -3106,15 +3357,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-freebsd-arm64@0.15.14:
-    resolution: {integrity: sha512-8XH96sOQ4b1LhMlO10eEWOjEngmZ2oyw3pW4o8kvBcpF6pULr56eeYVP5radtgw54g3T8nKHDHYEI5AItvskZg==}
-    engines: {node: '>=12'}
-    cpu: [arm64]
-    os: [freebsd]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-linux-32@0.14.54:
     resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==}
     engines: {node: '>=12'}
@@ -3124,15 +3366,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-linux-32@0.15.14:
-    resolution: {integrity: sha512-6ssnvwaTAi8AzKN8By2V0nS+WF5jTP7SfuK6sStGnDP7MCJo/4zHgM9oE1eQTS2jPmo3D673rckuCzRlig+HMA==}
-    engines: {node: '>=12'}
-    cpu: [ia32]
-    os: [linux]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-linux-64@0.14.54:
     resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==}
     engines: {node: '>=12'}
@@ -3142,15 +3375,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-linux-64@0.15.14:
-    resolution: {integrity: sha512-ONySx3U0wAJOJuxGUlXBWxVKFVpWv88JEv0NZ6NlHknmDd1yCbf4AEdClSgLrqKQDXYywmw4gYDvdLsS6z0hcw==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [linux]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-linux-arm64@0.14.54:
     resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==}
     engines: {node: '>=12'}
@@ -3160,15 +3384,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-linux-arm64@0.15.14:
-    resolution: {integrity: sha512-kle2Ov6a1e5AjlHlMQl1e+c4myGTeggrRzArQFmWp6O6JoqqB9hT+B28EW4tjFWgV/NxUq46pWYpgaWXsXRPAg==}
-    engines: {node: '>=12'}
-    cpu: [arm64]
-    os: [linux]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-linux-arm@0.14.54:
     resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==}
     engines: {node: '>=12'}
@@ -3178,15 +3393,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-linux-arm@0.15.14:
-    resolution: {integrity: sha512-D2LImAIV3QzL7lHURyCHBkycVFbKwkDb1XEUWan+2fb4qfW7qAeUtul7ZIcIwFKZgPcl+6gKZmvLgPSj26RQ2Q==}
-    engines: {node: '>=12'}
-    cpu: [arm]
-    os: [linux]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-linux-mips64le@0.14.54:
     resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==}
     engines: {node: '>=12'}
@@ -3196,15 +3402,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-linux-mips64le@0.15.14:
-    resolution: {integrity: sha512-FVdMYIzOLXUq+OE7XYKesuEAqZhmAIV6qOoYahvUp93oXy0MOVTP370ECbPfGXXUdlvc0TNgkJa3YhEwyZ6MRA==}
-    engines: {node: '>=12'}
-    cpu: [mips64el]
-    os: [linux]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-linux-ppc64le@0.14.54:
     resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==}
     engines: {node: '>=12'}
@@ -3214,15 +3411,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-linux-ppc64le@0.15.14:
-    resolution: {integrity: sha512-2NzH+iuzMDA+jjtPjuIz/OhRDf8tzbQ1tRZJI//aT25o1HKc0reMMXxKIYq/8nSHXiJSnYV4ODzTiv45s+h73w==}
-    engines: {node: '>=12'}
-    cpu: [ppc64]
-    os: [linux]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-linux-riscv64@0.14.54:
     resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==}
     engines: {node: '>=12'}
@@ -3232,15 +3420,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-linux-riscv64@0.15.14:
-    resolution: {integrity: sha512-VqxvutZNlQxmUNS7Ac+aczttLEoHBJ9e3OYGqnULrfipRvG97qLrAv9EUY9iSrRKBqeEbSvS9bSfstZqwz0T4Q==}
-    engines: {node: '>=12'}
-    cpu: [riscv64]
-    os: [linux]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-linux-s390x@0.14.54:
     resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==}
     engines: {node: '>=12'}
@@ -3250,15 +3429,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-linux-s390x@0.15.14:
-    resolution: {integrity: sha512-+KVHEUshX5n6VP6Vp/AKv9fZIl5kr2ph8EUFmQUJnDpHwcfTSn2AQgYYm0HTBR2Mr4d0Wlr0FxF/Cs5pbFgiOw==}
-    engines: {node: '>=12'}
-    cpu: [s390x]
-    os: [linux]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-netbsd-64@0.14.54:
     resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==}
     engines: {node: '>=12'}
@@ -3268,15 +3438,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-netbsd-64@0.15.14:
-    resolution: {integrity: sha512-6D/dr17piEgevIm1xJfZP2SjB9Z+g8ERhNnBdlZPBWZl+KSPUKLGF13AbvC+nzGh8IxOH2TyTIdRMvKMP0nEzQ==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [netbsd]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-openbsd-64@0.14.54:
     resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==}
     engines: {node: '>=12'}
@@ -3286,15 +3447,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-openbsd-64@0.15.14:
-    resolution: {integrity: sha512-rREQBIlMibBetgr2E9Lywt2Qxv2ZdpmYahR4IUlAQ1Efv/A5gYdO0/VIN3iowDbCNTLxp0bb57Vf0LFcffD6kA==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [openbsd]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-sunos-64@0.14.54:
     resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==}
     engines: {node: '>=12'}
@@ -3304,15 +3456,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-sunos-64@0.15.14:
-    resolution: {integrity: sha512-DNVjSp/BY4IfwtdUAvWGIDaIjJXY5KI4uD82+15v6k/w7px9dnaDaJJ2R6Mu+KCgr5oklmFc0KjBjh311Gxl9Q==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [sunos]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-windows-32@0.14.54:
     resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==}
     engines: {node: '>=12'}
@@ -3322,15 +3465,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-windows-32@0.15.14:
-    resolution: {integrity: sha512-pHBWrcA+/oLgvViuG9FO3kNPO635gkoVrRQwe6ZY1S0jdET07xe2toUvQoJQ8KT3/OkxqUasIty5hpuKFLD+eg==}
-    engines: {node: '>=12'}
-    cpu: [ia32]
-    os: [win32]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-windows-64@0.14.54:
     resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==}
     engines: {node: '>=12'}
@@ -3340,15 +3474,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-windows-64@0.15.14:
-    resolution: {integrity: sha512-CszIGQVk/P8FOS5UgAH4hKc9zOaFo69fe+k1rqgBHx3CSK3Opyk5lwYriIamaWOVjBt7IwEP6NALz+tkVWdFog==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [win32]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild-windows-arm64@0.14.54:
     resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==}
     engines: {node: '>=12'}
@@ -3358,15 +3483,6 @@ packages:
     dev: true
     optional: true
 
-  /esbuild-windows-arm64@0.15.14:
-    resolution: {integrity: sha512-KW9W4psdZceaS9A7Jsgl4WialOznSURvqX/oHZk3gOP7KbjtHLSsnmSvNdzagGJfxbAe30UVGXRe8q8nDsOSQw==}
-    engines: {node: '>=12'}
-    cpu: [arm64]
-    os: [win32]
-    requiresBuild: true
-    dev: true
-    optional: true
-
   /esbuild@0.11.3:
     resolution: {integrity: sha512-BzVRHcCtFepjS9WcqRjqoIxLqgpK21a8J4Zi4msSGxDxiXVO1IbcqT1KjhdDDnJxKfe7bvzZrvMEX+bVO0Elcw==}
     hasBin: true
@@ -3402,34 +3518,35 @@ packages:
       esbuild-windows-arm64: 0.14.54
     dev: true
 
-  /esbuild@0.15.14:
-    resolution: {integrity: sha512-pJN8j42fvWLFWwSMG4luuupl2Me7mxciUOsMegKvwCmhEbJ2covUdFnihxm0FMIBV+cbwbtMoHgMCCI+pj1btQ==}
+  /esbuild@0.19.10:
+    resolution: {integrity: sha512-S1Y27QGt/snkNYrRcswgRFqZjaTG5a5xM3EQo97uNBnH505pdzSNe/HLBq1v0RO7iK/ngdbhJB6mDAp0OK+iUA==}
     engines: {node: '>=12'}
     hasBin: true
     requiresBuild: true
     optionalDependencies:
-      '@esbuild/android-arm': 0.15.14
-      '@esbuild/linux-loong64': 0.15.14
-      esbuild-android-64: 0.15.14
-      esbuild-android-arm64: 0.15.14
-      esbuild-darwin-64: 0.15.14
-      esbuild-darwin-arm64: 0.15.14
-      esbuild-freebsd-64: 0.15.14
-      esbuild-freebsd-arm64: 0.15.14
-      esbuild-linux-32: 0.15.14
-      esbuild-linux-64: 0.15.14
-      esbuild-linux-arm: 0.15.14
-      esbuild-linux-arm64: 0.15.14
-      esbuild-linux-mips64le: 0.15.14
-      esbuild-linux-ppc64le: 0.15.14
-      esbuild-linux-riscv64: 0.15.14
-      esbuild-linux-s390x: 0.15.14
-      esbuild-netbsd-64: 0.15.14
-      esbuild-openbsd-64: 0.15.14
-      esbuild-sunos-64: 0.15.14
-      esbuild-windows-32: 0.15.14
-      esbuild-windows-64: 0.15.14
-      esbuild-windows-arm64: 0.15.14
+      '@esbuild/aix-ppc64': 0.19.10
+      '@esbuild/android-arm': 0.19.10
+      '@esbuild/android-arm64': 0.19.10
+      '@esbuild/android-x64': 0.19.10
+      '@esbuild/darwin-arm64': 0.19.10
+      '@esbuild/darwin-x64': 0.19.10
+      '@esbuild/freebsd-arm64': 0.19.10
+      '@esbuild/freebsd-x64': 0.19.10
+      '@esbuild/linux-arm': 0.19.10
+      '@esbuild/linux-arm64': 0.19.10
+      '@esbuild/linux-ia32': 0.19.10
+      '@esbuild/linux-loong64': 0.19.10
+      '@esbuild/linux-mips64el': 0.19.10
+      '@esbuild/linux-ppc64': 0.19.10
+      '@esbuild/linux-riscv64': 0.19.10
+      '@esbuild/linux-s390x': 0.19.10
+      '@esbuild/linux-x64': 0.19.10
+      '@esbuild/netbsd-x64': 0.19.10
+      '@esbuild/openbsd-x64': 0.19.10
+      '@esbuild/sunos-x64': 0.19.10
+      '@esbuild/win32-arm64': 0.19.10
+      '@esbuild/win32-ia32': 0.19.10
+      '@esbuild/win32-x64': 0.19.10
     dev: true
 
   /escalade@3.1.1:
@@ -3987,6 +4104,14 @@ packages:
     dev: true
     optional: true
 
+  /fsevents@2.3.3:
+    resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+    engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+    os: [darwin]
+    requiresBuild: true
+    dev: true
+    optional: true
+
   /function-bind@1.1.1:
     resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
 
@@ -4749,6 +4874,10 @@ packages:
     resolution: {integrity: sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==}
     dev: true
 
+  /konva@9.3.0:
+    resolution: {integrity: sha512-qLTW06GRwb+WMMUXJcGIb0qP4uO0mZLAwgRI82zuCkRmCH1lFsVPmrPzqqHnjKCMu4Jzw6d/R8JxkPw7gkVnuw==}
+    dev: false
+
   /levn@0.4.1:
     resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
     engines: {node: '>= 0.8.0'}
@@ -5186,6 +5315,12 @@ packages:
     engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
     hasBin: true
 
+  /nanoid@3.3.7:
+    resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+    engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+    hasBin: true
+    dev: true
+
   /natural-compare@1.4.0:
     resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
     dev: true
@@ -5706,6 +5841,15 @@ packages:
       source-map-js: 1.0.2
     dev: true
 
+  /postcss@8.4.32:
+    resolution: {integrity: sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==}
+    engines: {node: ^10 || ^12 || >=14}
+    dependencies:
+      nanoid: 3.3.7
+      picocolors: 1.0.0
+      source-map-js: 1.0.2
+    dev: true
+
   /preact@10.11.3:
     resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==}
     dev: false
@@ -6008,12 +6152,25 @@ packages:
       yargs: 17.5.1
     dev: true
 
-  /rollup@2.79.1:
-    resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==}
-    engines: {node: '>=10.0.0'}
+  /rollup@4.9.1:
+    resolution: {integrity: sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==}
+    engines: {node: '>=18.0.0', npm: '>=8.0.0'}
     hasBin: true
     optionalDependencies:
-      fsevents: 2.3.2
+      '@rollup/rollup-android-arm-eabi': 4.9.1
+      '@rollup/rollup-android-arm64': 4.9.1
+      '@rollup/rollup-darwin-arm64': 4.9.1
+      '@rollup/rollup-darwin-x64': 4.9.1
+      '@rollup/rollup-linux-arm-gnueabihf': 4.9.1
+      '@rollup/rollup-linux-arm64-gnu': 4.9.1
+      '@rollup/rollup-linux-arm64-musl': 4.9.1
+      '@rollup/rollup-linux-riscv64-gnu': 4.9.1
+      '@rollup/rollup-linux-x64-gnu': 4.9.1
+      '@rollup/rollup-linux-x64-musl': 4.9.1
+      '@rollup/rollup-win32-arm64-msvc': 4.9.1
+      '@rollup/rollup-win32-ia32-msvc': 4.9.1
+      '@rollup/rollup-win32-x64-msvc': 4.9.1
+      fsevents: 2.3.3
     dev: true
 
   /run-async@2.4.1:
@@ -6873,7 +7030,7 @@ packages:
       spdx-expression-parse: 3.0.1
     dev: true
 
-  /vite-plugin-compression@0.5.1(vite@3.2.7):
+  /vite-plugin-compression@0.5.1(vite@5.0.10):
     resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==}
     peerDependencies:
       vite: '>=2.0.0'
@@ -6881,12 +7038,12 @@ packages:
       chalk: 4.1.2
       debug: 4.3.4
       fs-extra: 10.1.0
-      vite: 3.2.7(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /vite-plugin-html@3.2.0(vite@3.2.7):
+  /vite-plugin-html@3.2.0(vite@5.0.10):
     resolution: {integrity: sha512-2VLCeDiHmV/BqqNn5h2V+4280KRgQzCFN47cst3WiNK848klESPQnzuC3okH5XHtgwHH/6s1Ho/YV6yIO0pgoQ==}
     peerDependencies:
       vite: '>=2.0.0'
@@ -6903,10 +7060,10 @@ packages:
       html-minifier-terser: 6.1.0
       node-html-parser: 5.3.3
       pathe: 0.2.0
-      vite: 3.2.7(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
     dev: true
 
-  /vite-plugin-mock@2.9.6(mockjs@1.1.0)(vite@3.2.7):
+  /vite-plugin-mock@2.9.6(mockjs@1.1.0)(vite@5.0.10):
     resolution: {integrity: sha512-/Rm59oPppe/ncbkSrUuAxIQihlI2YcBmnbR4ST1RA2VzM1C0tEQc1KlbQvnUGhXECAGTaQN2JyasiwXP6EtKgg==}
     engines: {node: '>=12.0.0'}
     peerDependencies:
@@ -6923,13 +7080,13 @@ packages:
       fast-glob: 3.2.12
       mockjs: 1.1.0
       path-to-regexp: 6.2.1
-      vite: 3.2.7(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
     transitivePeerDependencies:
       - rollup
       - supports-color
     dev: true
 
-  /vite-plugin-style-import@2.0.0(vite@3.2.7):
+  /vite-plugin-style-import@2.0.0(vite@5.0.10):
     resolution: {integrity: sha512-qtoHQae5dSUQPo/rYz/8p190VU5y19rtBaeV7ryLa/AYAU/e9CG89NrN/3+k7MR8mJy/GPIu91iJ3zk9foUOSA==}
     peerDependencies:
       vite: '>=2.0.0'
@@ -6941,26 +7098,27 @@ packages:
       fs-extra: 10.1.0
       magic-string: 0.25.9
       pathe: 0.2.0
-      vite: 3.2.7(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
     dev: true
 
-  /vite-plugin-vue-setup-extend@0.4.0(vite@3.2.7):
+  /vite-plugin-vue-setup-extend@0.4.0(vite@5.0.10):
     resolution: {integrity: sha512-WMbjPCui75fboFoUTHhdbXzu4Y/bJMv5N9QT9a7do3wNMNHHqrk+Tn2jrSJU0LS5fGl/EG+FEDBYVUeWIkDqXQ==}
     peerDependencies:
       vite: '>=2.0.0'
     dependencies:
       '@vue/compiler-sfc': 3.3.4
       magic-string: 0.25.9
-      vite: 3.2.7(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
     dev: true
 
-  /vite@3.2.7(@types/node@17.0.45)(sass@1.53.0):
-    resolution: {integrity: sha512-29pdXjk49xAP0QBr0xXqu2s5jiQIXNvE/xwd0vUizYT2Hzqe4BksNNoWllFVXJf4eLZ+UlVQmXfB4lWrc+t18g==}
-    engines: {node: ^14.18.0 || >=16.0.0}
+  /vite@5.0.10(@types/node@17.0.45)(sass@1.53.0):
+    resolution: {integrity: sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==}
+    engines: {node: ^18.0.0 || >=20.0.0}
     hasBin: true
     peerDependencies:
-      '@types/node': '>= 14'
+      '@types/node': ^18.0.0 || >=20.0.0
       less: '*'
+      lightningcss: ^1.21.0
       sass: '*'
       stylus: '*'
       sugarss: '*'
@@ -6970,6 +7128,8 @@ packages:
         optional: true
       less:
         optional: true
+      lightningcss:
+        optional: true
       sass:
         optional: true
       stylus:
@@ -6980,13 +7140,12 @@ packages:
         optional: true
     dependencies:
       '@types/node': 17.0.45
-      esbuild: 0.15.14
-      postcss: 8.4.23
-      resolve: 1.22.2
-      rollup: 2.79.1
+      esbuild: 0.19.10
+      postcss: 8.4.32
+      rollup: 4.9.1
       sass: 1.53.0
     optionalDependencies:
-      fsevents: 2.3.2
+      fsevents: 2.3.3
     dev: true
 
   /vue-demi@0.13.11(vue@3.3.4):

+ 3 - 0
src/views/result/components/AlgorithmsSetting/AlgorithmsSetting.vue

@@ -0,0 +1,3 @@
+<template> 算法配置 </template>
+<script lang="ts" setup></script>
+<style scoped></style>

+ 11 - 0
src/views/result/components/CameraViewSetting/CameraViewSetting.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>
+    <FenceToolbar />
+    <!-- <FenceEditor /> -->
+  </div>
+</template>
+<script lang="ts" setup>
+  import FenceToolbar from '../FenceToolbar/FenceToolbar.vue';
+  import FenceEditor from '../FenceEditor/FenceEditor.vue';
+</script>
+<style scoped></style>

+ 649 - 0
src/views/result/components/FenceEditor/FenceEditor.vue

@@ -0,0 +1,649 @@
+<template>
+  <div id="editorMap" ref="mapRef"></div>
+</template>
+
+<script lang="ts" setup>
+  import Konva from 'konva';
+  import { ref, onMounted, onUnmounted } from 'vue';
+  import {
+    GROUP_NAME,
+    POLYGON_NAME,
+    Points,
+    ServerLine,
+    ToolObjectItem,
+    toolObject,
+  } from './constants';
+  import { ElMessage } from 'element-plus';
+  import { getDefaultScale } from './utils';
+  import { Group } from 'konva/lib/Group';
+
+  const mapRef = ref<HTMLCanvasElement | null>(null);
+  let currentTool: ToolObjectItem = toolObject[1];
+
+  let stage: Konva.Stage | null = null;
+  let layer: Konva.Layer | null = null;
+  let currentDrawingShape: Konva.Group | null = null; //现在绘画的图形
+  let polygonPoints: number[] = []; //存储绘画多边形各个顶点的数组
+  let stageWidth = 0; //舞台宽
+  let stageHeight = 0; //舞台高
+  let scale = 1; //窗口变化的缩放比例
+  let drawing = false; //一开始不能绘画
+  let currentDel: Konva.Node | null = null; //删除对象
+
+  onMounted(() => {
+    initKonvaStage();
+    //禁止浏览器右击菜单
+    document.oncontextmenu = function () {
+      return false;
+    };
+  });
+
+  onUnmounted(() => {
+    stage?.destroy();
+  });
+
+  /**
+   *初始化konva舞台
+   */
+  function initKonvaStage() {
+    //1实例化stage层
+    stageWidth = mapRef.value?.clientWidth || 0;
+    stageHeight = mapRef.value?.clientHeight || 0;
+    console.log('stageWidth', stageWidth);
+    stage = new Konva.Stage({
+      container: 'editorMap',
+      width: stageWidth,
+      height: stageHeight,
+      ignoreStroke: true,
+      background: '#00ff00',
+    });
+    window.stage = stage;
+    setStageCursor('pointer');
+
+    //2实例化layer层
+    layer = new Konva.Layer();
+    //3添加layer层
+    stage?.add(layer);
+
+    //给***舞台***绑定事件
+    stageBindEvent();
+  }
+  /**
+   * 舞台绑定的事件
+   * @param vc_this
+   */
+  function stageBindEvent() {
+    //鼠标按下
+    stage?.on('mousedown', (e) => {
+      //鼠标左键开始
+      console.log('stage mousedown', e);
+      if (e.evt.button == 0) {
+        if (e.target === stage) {
+          stageMousedown(currentTool!);
+          return;
+        }
+        //图形起始点只能在图片层上
+        // if (e.target === shape) {
+        //   //开始初始绘画
+        //   stageMousedown(currentTool!);
+        //   return;
+        // }
+        //允许后续点绘画在其他图形上
+        if (drawing) {
+          stageMousedown(currentTool!);
+          return;
+        }
+      } else if (e.evt.button == 2) {
+        // 如果polygonPoints为空,那么右击是没有反应的。
+        console.log('mousedown 2');
+      }
+    });
+    //鼠标移动
+    stage?.on('mousemove', () => {
+      if (currentTool && drawing) {
+        //绘画中
+        stageMousemove();
+      }
+    });
+    //鼠标放开
+    stage?.on('mouseup', (e: Konva.KonvaEventObject<any>) => {
+      if (e.evt.button == 0) {
+        if (drawing) {
+          stageMouseup(e);
+        }
+      } else if (e.evt.button == 2) {
+        if (polygonPoints.length != 0) {
+          stageMouseup(e);
+        }
+      }
+    });
+    //   //鼠标滚轮事件取消
+
+    //舞台快捷键
+    var container = stage?.container();
+    if (!container) return;
+    container.tabIndex = 1;
+    container?.focus();
+    container?.addEventListener('keydown', (e) => {
+      //删除的快捷键
+      if (e.keyCode === 46) {
+        removeCurrent();
+      }
+      if (container) {
+        container.style.cursor = 'crosshair';
+      }
+      e.preventDefault();
+      layer?.draw();
+    });
+  }
+
+  const getPolygonInGroup = (g: Konva.Group | null) => {
+    if (!g) return;
+    return g.findOne(POLYGON_NAME) as Konva.Line;
+  };
+
+  /** 设置当前选中的group */
+  function setCurrentGroup(group: Konva.Group) {
+    currentDrawingShape = group;
+    setGroupActive(group);
+    currentDel = group;
+  }
+
+  /**
+   * 在舞台上鼠标点下发生的事件
+   * @param currentTool 当前选择的工具
+   * @param e 传入的event对象
+   */
+  function stageMousedown(currentTool: ToolObjectItem) {
+    console.log('stagemousedown');
+
+    //如果数组长度小于2,初始化多边形和顶点,使它们成为一组,否则什么都不做
+    // 小于2说明一个点也没有,一个点的长度是2,所以要先创建group
+    if (polygonPoints.length < 2) {
+      //最好使用konva提供的鼠标xy点坐标
+      var mousePos = stage?.getPointerPosition();
+      if (!mousePos) return;
+      //考虑鼠标缩放
+      var x = (mousePos.x / scale - layer?.getAttr('x')) / getDefaultScale(layer?.scaleX()),
+        y = (mousePos.y / scale - layer?.getAttr('y')) / getDefaultScale(layer?.scaleY());
+      //拖拽组
+      var group = new Konva.Group({
+        name: currentTool.name + 'group',
+        draggable: false,
+      });
+      polygonPoints = [x, y];
+      //添加多边形的点
+      drawCircle(x, y, group, polygonPoints);
+
+      //绘画多边形
+      drawPolygon(currentTool, polygonPoints, group);
+      //添加多边形的边
+      // drawLine(currentTool, polygonPoints, group);
+      layer?.add(group);
+      setCurrentGroup(group);
+      currentDel = group;
+
+      //使所有顶点在顶层显示
+      stage?.find('Circle').forEach((element) => {
+        element.moveToTop();
+      });
+      layer?.draw();
+    } //多边形增加顶点
+    else {
+      //最好使用konva提供的鼠标xy点坐标
+      var mousePos = stage?.getPointerPosition();
+      if (!mousePos) return;
+      //考虑鼠标缩放
+      var x = (mousePos.x / scale - layer?.getAttr('x')) / getDefaultScale(layer?.scaleX()),
+        y = (mousePos.y / scale - layer?.getAttr('y')) / getDefaultScale(layer?.scaleY());
+      //group继续添加多边形的点
+      drawCircle(x, y, currentDrawingShape!, polygonPoints);
+      polygonPoints.push(x);
+      polygonPoints.push(y);
+
+      const polygon = getPolygonInGroup(currentDrawingShape);
+      currentDel = currentDrawingShape;
+      //绘画多边形
+      polygon?.setAttr('points', polygonPoints);
+      //group继续添加多边形的边
+      //使所有顶点在顶层显示
+      stage?.find('Circle').forEach((element) => {
+        element.moveToTop();
+      });
+      layer?.draw();
+    }
+
+    drawing = true;
+  }
+  /**
+   * 鼠标在舞台上移动事件
+   * @param currentTool 当前选择的工具
+   * @param e 传入的event对象
+   */
+  function stageMousemove() {
+    const container = stage?.container();
+    if (!container) return;
+
+    container.style.cursor = 'crosshair';
+    //多边形初始化后,如果数组长度大于2,鼠标移动时,实时更新下一个点
+    if (polygonPoints.length >= 2) {
+      var mousePos = stage?.getPointerPosition();
+      if (!mousePos) return;
+      var x = (mousePos.x / scale - layer?.getAttr('x')) / getDefaultScale(layer?.scaleX()),
+        y = (mousePos.y / scale - layer?.getAttr('y')) / getDefaultScale(layer?.scaleY());
+      var tempPoints = polygonPoints.concat([]);
+      tempPoints.push(x);
+      tempPoints.push(y);
+
+      const polygon = getPolygonInGroup(currentDrawingShape);
+      //更新多边形
+      polygon?.setAttr('points', tempPoints);
+      //使所有顶点在顶层显示
+      stage?.find('Circle').forEach((element) => {
+        element.moveToTop();
+      });
+    }
+
+    layer?.draw();
+  }
+  /**
+   * 鼠标在舞台弹起
+   * @param currentTool 当前选择的工具
+   * @param e 传入的event对象
+   */
+  function stageMouseup(e: Konva.KonvaEventObject<any>) {
+    if (e.evt.button == 2) {
+      if (polygonPoints.length != 0) {
+        //最好使用konva提供的鼠标xy点坐标
+        var mousePos = stage?.getPointerPosition();
+        if (!mousePos) return;
+        //考虑鼠标缩放
+        var x = (mousePos.x / scale - layer?.getAttr('x')) / getDefaultScale(layer?.scaleX()),
+          y = (mousePos.y / scale - layer?.getAttr('y')) / getDefaultScale(layer?.scaleY());
+        //group继续添加多边形的点
+        // 右击和左击都要添加一个点
+        drawCircle(x, y, currentDrawingShape!, polygonPoints);
+        polygonPoints.push(x);
+        polygonPoints.push(y);
+        const polygon = getPolygonInGroup(currentDrawingShape);
+        //绘画多边形
+        polygon?.setAttr('points', polygonPoints);
+
+        //判断是否是只有两个点的多边形,如果起点和终点相同,不允许绘画
+        if (polygon?.points().length == 2 || polygon?.points().length == 4) {
+          drawing = false;
+          currentDrawingShape?.destroy();
+          polygonPoints = [];
+          ElMessage({
+            message: '顶点数必须大于2个!',
+            type: 'warning',
+            center: true,
+            duration: 1000,
+          });
+          return;
+        }
+        //右键弹起
+        polygonPoints = [];
+        // 停止事件冒泡
+        e.cancelBubble = true;
+        // 停止画多边形
+        drawing = false;
+      }
+    }
+
+    //使所有顶点在顶层显示
+    stage?.find('Circle').forEach((element) => {
+      element.moveToTop();
+    });
+
+    layer?.draw();
+  }
+  /**
+   * 多边形圆形
+   * @param //x x坐标
+   * @param //y y坐标
+   */
+  function drawCircle(x: number, y: number, group: Konva.Group, shapePoints: number[]) {
+    const circle = new Konva.Circle({
+      name: currentTool.name + 'circle',
+      x: x,
+      y: y,
+      radius: 5 / scale / getDefaultScale(layer?.scaleX()),
+      visible: true, //是否显示
+      fill: currentTool.anchorColor,
+      stroke: currentTool.anchorColor,
+      draggable: false,
+      strokeWidth: 0.5,
+      strokeScaleEnabled: false,
+      //增加点击区域
+      hitStrokeWidth: 8 / scale / getDefaultScale(layer?.scaleX()),
+      //设置拖动区域,不能超过舞台大小
+      dragBoundFunc: function (pos) {
+        //左上角
+        if (pos.x < 0 && pos.y < 0) {
+          return {
+            x: 0,
+            y: 0,
+          };
+        } //左侧
+        else if (pos.x <= 0 && 0 <= pos.y && pos.y <= (stage?.height() ?? 0)) {
+          return {
+            x: 0,
+            y: pos.y,
+          };
+        }
+        //左下角
+        else if (pos.x < 0 && pos.y > (stage?.height() ?? 0)) {
+          return {
+            x: 0,
+            y: stage?.height(),
+          };
+        } //下侧
+        else if (0 <= pos.x && pos.x <= (stage?.width() ?? 0) && pos.y > (stage?.height() ?? 0)) {
+          return {
+            x: pos.x,
+            y: stage?.height(),
+          };
+        } //右下角
+        else if (pos.x > (stage?.width() ?? 0) && pos.y > (stage?.height() ?? 0)) {
+          return {
+            x: stage?.width(),
+            y: stage?.height(),
+          };
+        }
+        //右侧
+        else if (pos.x > (stage?.width() ?? 0) && 0 <= pos.y && pos.y <= (stage?.height() ?? 0)) {
+          return {
+            x: stage?.width(),
+            y: pos.y,
+          };
+        }
+        //右上角
+        else if (pos.x > (stage?.width() ?? 0) && pos.y < 0) {
+          return {
+            x: stage?.width(),
+            y: 0,
+          };
+        } //上侧
+        else if (0 <= pos.x && pos.x <= (stage?.width() ?? 0) && pos.y < 0) {
+          return {
+            x: pos.x,
+            y: 0,
+          };
+        }
+      },
+    });
+    group.add(circle);
+    let xChange: number, yChange: number;
+    circle.on('mouseover', () => {
+      const c = stage?.container();
+      if (!c) return;
+      c.style.cursor = 'pointer';
+    });
+    circle.on('mousedown', (e) => {
+      console.log('circle,');
+      if (!drawing) {
+        circle.draggable(true);
+        //将现在绘画的对象改为group
+        setCurrentGroup(circle.getParent() as Konva.Group);
+      } else {
+        circle.draggable(false);
+      }
+      e.cancelBubble = true;
+    });
+    circle.on('mouseleave', () => {
+      const c = stage?.container();
+      if (!c) return;
+      c.style.cursor = 'crosshair';
+    });
+    circle.on('dragstart', () => {
+      switch (currentTool?.type) {
+        case 'poly':
+          //查找拖拽了多边形的哪个点
+          for (var i = 0; i < shapePoints.length; i += 2) {
+            if (
+              circle.getAttr('x') == shapePoints[i] &&
+              circle.getAttr('y') == shapePoints[i + 1]
+            ) {
+              xChange = i;
+              yChange = i + 1;
+              break;
+            }
+          }
+          break;
+        default:
+          break;
+      }
+    });
+    circle.on('dragmove', () => {
+      switch (currentTool?.type) {
+        case 'poly':
+          var x = circle.x();
+          var y = circle.y();
+          //更改拖拽点的位置
+          shapePoints[xChange] = x;
+          shapePoints[yChange] = y;
+          break;
+        default:
+          break;
+      }
+    });
+    circle.on('dragend', (e) => {
+      switch (currentTool?.type) {
+        case 'poly':
+          //使所有顶点在顶层显示
+          stage?.find('Circle').forEach((element) => {
+            element.moveToTop();
+          });
+          circle.draggable(false);
+          break;
+        default:
+          break;
+      }
+      ElMessage({
+        message: '修改成功!',
+        type: 'success',
+        center: true,
+        duration: 1000,
+      });
+      e.cancelBubble = true;
+    });
+    return circle;
+  }
+
+  function setStageCursor(cursor: string) {
+    const c = stage?.container();
+    if (c) {
+      c.style.cursor = cursor;
+    }
+  }
+
+  /** 设置当前的group为active */
+  function setGroupActive(activeGroup: Group) {
+    const groups = stage?.find(GROUP_NAME) as Konva.Group[];
+    if (!groups) return;
+    /** 将其他组的线条设为非高亮 */
+    groups.forEach((g: Konva.Group) => {
+      if (g === activeGroup) return;
+      g.find(POLYGON_NAME).forEach((line) => {
+        (line as Konva.Line).stroke(currentTool?.color!);
+      });
+
+      g.find('Circle').forEach((circle) => {
+        (circle as Konva.Circle).hide();
+      });
+    });
+
+    const thisLine = activeGroup.findOne(POLYGON_NAME) as Konva.Line;
+    if (thisLine) {
+      thisLine.stroke(currentTool.activeColor);
+    }
+    const thisCircles = activeGroup.find('Circle') as Konva.Circle[];
+    if (thisCircles) {
+      thisCircles.forEach((circle) => {
+        (circle as Konva.Circle).show();
+      });
+    }
+    layer?.draw();
+  }
+  /**
+ *多边形
+  @param currentTool
+  * @param points 多边形绘画的各个顶点,类型数组
+  */
+  function drawPolygon(currentTool: ToolObjectItem, points: number[], group: Konva.Group) {
+    let poly = new Konva.Line({
+      name: currentTool.name + 'poly',
+      points: points,
+      /*  fill: currentTool.color, */
+      stroke: currentTool.color,
+      strokeWidth: 1,
+      draggable: false,
+      opacity: 0.5,
+      lineCap: 'round',
+      lineJoin: 'round',
+      closed: true,
+      strokeScaleEnabled: false,
+    });
+    group.add(poly);
+    setCurrentGroup(group);
+    const pParent = group;
+    pParent?.on('mouseleave', () => {
+      const c = stage?.container();
+      if (c) {
+        c.style.cursor = 'crosshair';
+      }
+    });
+    pParent?.on('mousedown', (e) => {
+      console.log('group mouse down');
+      if (e.evt.button == 0) {
+        //绘画结束
+        if (!drawing) {
+          setStageCursor('move');
+          //设置现在绘画节点的对象为该多边形和顶点的组
+          // 如果要让顶点和多边形一起拖拽,必须设置,多边形不能被拖拽
+          poly.setAttr('draggable', false);
+          currentDrawingShape?.setAttr('draggable', true);
+          //使所有顶点在顶层显示
+          stage?.find('Circle').forEach((element) => {
+            element.moveToTop();
+          });
+          //添加删除撤销对象
+          currentDel = currentDrawingShape;
+          setCurrentGroup(poly.getParent() as Konva.Group);
+
+          layer?.draw();
+        } else {
+          setStageCursor('crosshair');
+          poly.getParent()?.setAttr('draggable', false);
+        }
+      }
+    });
+
+    pParent?.on('dragend', () => {
+      console.log('dragend');
+      /** 这里可以把工具的类型用枚举值定义 */
+
+      //使所有顶点在顶层显示
+      stage?.find('Circle').forEach((element) => {
+        element.moveToTop();
+      });
+      //添加删除撤销对象
+      currentDel = currentDrawingShape;
+      layer?.draw();
+      /*   vc_setMaskData(); */
+
+      ElMessage({
+        message: '修改成功!',
+        type: 'success',
+        center: true,
+        duration: 1000,
+      });
+      setStageCursor('crosshair');
+      //设置组不能拖动
+      currentDrawingShape?.setAttr('draggable', false);
+    });
+    return poly;
+  }
+
+  /** 根据json数据创建group */
+  function createGroupByPoints(points: Points) {
+    var group = new Konva.Group({
+      name: currentTool.name + 'group',
+      draggable: false,
+    });
+    //添加多边形的点
+
+    //绘画多边形
+    drawPolygon(currentTool, points, group);
+    for (let i = 0; i < points.length; i += 2) {
+      const x = points[i];
+      const y = points[i + 1];
+      drawCircle(x, y, group, points);
+    }
+    // group.setAttrs({ x: groupData.attrs.x, y: groupData.attrs.y })
+
+    layer?.add(group);
+    layer?.draw();
+  }
+
+  const removeCurrent = () => {
+    if (currentDel) {
+      currentDel.destroy();
+      currentDel = null;
+      currentDrawingShape = null;
+      ElMessage({
+        message: '删除成功!',
+        type: 'success',
+        center: true,
+        duration: 1000,
+      });
+    }
+    layer?.draw();
+  };
+
+  const toObject = () => {
+    const polyGroups = stage?.find('.polygroup');
+    const gropuPoints = polyGroups?.map((item) => {
+      const groupX = item.x();
+      const groupY = item.y();
+
+      const line = (item as Konva.Group).findOne((x: any) => x.className === 'Line') as Konva.Line;
+      const points = line?.points();
+      const newPoints = [];
+      /** 存到后端的时候,只给点的坐标信息,不会给group的位置信息,所以要将点的坐标加上group的位移,才是之后点的最终坐标 */
+      for (let i = 0; i < points.length; i += 2) {
+        newPoints.push([points[i] + groupX, points[i + 1] + groupY]);
+      }
+      return newPoints;
+    });
+    return gropuPoints;
+  };
+
+  const initStageByJSON = (param: { width: number; height: number }) => {
+    stage?.setAttrs({ width: param.width, height: param.height });
+  };
+
+  const toRawObject = () => {
+    return stage?.toObject();
+  };
+
+  defineExpose({
+    remove: removeCurrent,
+    toObject,
+    toRawObject,
+    createGroupByPoints,
+    initStageByJSON,
+  });
+</script>
+
+<style scoped>
+  #editorMap {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    border: 2px solid #0f0;
+  }
+</style>

+ 45 - 0
src/views/result/components/FenceEditor/constants.ts

@@ -0,0 +1,45 @@
+export const toolObject: ToolObjectItem[] = [
+  {
+    name: 'rect',
+    type: 'rect',
+    /* 矩形颜色 */ color: '#75fb4c',
+    /* 边框颜色 */ lineColor: '#75fb4c',
+    /* 顶点颜色 */ anchorColor: 'green',
+    activeColor: '#0f0',
+  },
+  {
+    name: 'poly',
+    type: 'poly',
+    /* 多边形颜色 */ color: '#E63F00',
+    /* 边框颜色 */ lineColor: '#E63F00 ',
+    /* 顶点颜色 */ anchorColor: 'red',
+    /** 选中模式状态下的边框颜色 */
+    activeColor: '#0f0',
+  },
+];
+
+export interface ToolObjectItem {
+  name: string;
+  type: string;
+  /* 矩形颜色 */
+  color: string;
+  /* 边框颜色 */
+  lineColor: string;
+  /* 顶点颜色 */
+  anchorColor: string;
+
+  activeColor: string;
+}
+
+export const GROUP_NAME = '.polygroup';
+export const POLYGON_NAME = '.polypoly';
+
+export type Points = number[];
+
+/** 导出给后端的单个点坐标格式 */
+export type ServerLinePoint = [number, number];
+/** 一个多边形的所有点坐标 */
+export type ServerLine = ServerLinePoint[];
+
+/** 图上所有的多边形 */
+export type ServerLines = ServerLine[];

+ 3 - 0
src/views/result/components/FenceEditor/utils.ts

@@ -0,0 +1,3 @@
+export function getDefaultScale(scale: number | undefined | null) {
+  return scale ?? 1;
+}

+ 101 - 0
src/views/result/components/FenceToolbar/FenceToolbar.vue

@@ -0,0 +1,101 @@
+<template>
+  <div class="camera-wrapper">
+    <div style="text-align: center"> camera 画面 </div>
+    <div class="editor-wrapper" v-if="isFenceOn">
+      <div class="toolbar">
+        <div>
+          <ElButton>编辑</ElButton>
+          <ElButton @click="remove">删除</ElButton>
+          <ElButton @click="toObject">保存到localStorage</ElButton>
+          <ElButton @click="loadGroup">从local加载group</ElButton>
+          <ElButton @click="toRawObject">保存Raw</ElButton>
+        </div>
+      </div>
+      <PolygonEditor class="polygonEditor" ref="polygonEditorRef" />
+    </div>
+  </div>
+  <div>
+    <div
+      >打开电子围栏
+      <ElSwitch v-model="isFenceOn" />
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+  import { ref } from 'vue';
+  import { ElButton, ElSwitch } from 'element-plus';
+  import PolygonEditor from '../FenceEditor/FenceEditor.vue';
+  import { ServerLines } from '../FenceEditor/constants';
+
+  const isFenceOn = ref(true);
+
+  const polygonEditorRef = ref<typeof PolygonEditor | null>(null);
+
+  const remove = () => {
+    polygonEditorRef.value?.remove();
+  };
+
+  const toObject = () => {
+    const json = polygonEditorRef.value?.toObject();
+    console.log('toObject json', json);
+    localStorage.setItem('mapDataV2', JSON.stringify(json));
+  };
+
+  const toRawObject = () => {
+    const objects = polygonEditorRef.value?.toRawObject();
+    console.log('objects', objects);
+    localStorage.setItem('mapData', JSON.stringify(objects));
+  };
+
+  const loadGroup = () => {
+    const data = localStorage.getItem('mapDataV2');
+    console.log('loadGroup data', data);
+    if (!data) return;
+    const dataJSON = JSON.parse(data) as ServerLines;
+    const groups = dataJSON;
+    const rawLinePoints = groups[0];
+    const points: number[] = [];
+    rawLinePoints.forEach((line) => {
+      points.push(line[0], line[1]);
+    });
+    console.log('points', points);
+
+    polygonEditorRef.value?.createGroupByPoints(points);
+  };
+
+  const preview = () => {
+    polygonEditorRef.value?.preview();
+  };
+</script>
+
+<style scoped>
+  .camera-wrapper {
+    position: relative;
+    border: 1px solid #f00;
+    background: #fff;
+    height: 600px;
+  }
+
+  .toolbar {
+    width: 100px;
+    height: 400px;
+    position: absolute;
+    left: 0;
+    top: 50px;
+    border: 1px solid #f00;
+    z-index: 10;
+    color: #000;
+  }
+
+  .editor-wrapper {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+  }
+
+  .polygonEditor {
+    flex-grow: 1;
+  }
+</style>

+ 11 - 0
src/views/result/store/useCameraDetail.ts

@@ -0,0 +1,11 @@
+/** 相机详情的store */
+
+import { defineStore } from 'pinia';
+import { ref } from 'vue';
+
+const useCameraDetailStore = defineStore('cameraDetail', () => {
+  const detail = ref(null);
+  return { detail };
+});
+
+export default useCameraDetailStore;

+ 8 - 3
src/views/result/success.vue

@@ -4,16 +4,21 @@
     <div class="cameraMain">
       <div class="cameraTree">场景树</div>
       <div class="cameraSettingWrapper">
-        <div class="cameraView">这是相机预览画面</div>
+        <div class="cameraView">
+          <CameraViewSetting />
+        </div>
         <div class="cameraParamsSettingWrapper">
           <div class="cameraParamsSetting"> 相机的参数设置 </div>
-          <div class="algorithmsSetting"> 算法配置 </div>
+          <div class="algorithmsSetting"> <AlgorithmsSetting /> </div>
         </div>
       </div>
     </div>
   </div>
 </template>
-<script lang="ts" setup></script>
+
+<script lang="ts" setup>
+  import CameraViewSetting from './components/CameraViewSetting/CameraViewSetting.vue';
+</script>
 <style lang="scss" scoped>
   .cameraView {
     width: 800px;