Преглед изворни кода

预览面板比例适配、拖拽异常删除、激活失活布局开关、面板首页处理滚动

unknown пре 3 недеља
родитељ
комит
cbf1fa600e

+ 1 - 0
.env.development

@@ -0,0 +1 @@
+NODE_ENV='development'

+ 1 - 0
.env.production

@@ -0,0 +1 @@
+NODE_ENV='production'

+ 1 - 0
package.json

@@ -10,6 +10,7 @@
   },
   "dependencies": {
     "@element-plus/icons-vue": "^2.3.1",
+    "axios": "^1.7.7",
     "color": "^4.2.3",
     "element-plus": "^2.7.5",
     "pinia": "^2.2.0",

+ 1498 - 0
pnpm-lock.yaml

@@ -0,0 +1,1498 @@
+lockfileVersion: '9.0'
+
+settings:
+  autoInstallPeers: true
+  excludeLinksFromLockfile: false
+
+importers:
+
+  .:
+    dependencies:
+      '@element-plus/icons-vue':
+        specifier: ^2.3.1
+        version: 2.3.1(vue@3.5.12(typescript@5.6.3))
+      axios:
+        specifier: ^1.7.7
+        version: 1.7.7
+      color:
+        specifier: ^4.2.3
+        version: 4.2.3
+      element-plus:
+        specifier: ^2.7.5
+        version: 2.8.5(vue@3.5.12(typescript@5.6.3))
+      pinia:
+        specifier: ^2.2.0
+        version: 2.2.4(typescript@5.6.3)(vue@3.5.12(typescript@5.6.3))
+      pinia-plugin-persistedstate:
+        specifier: ^3.2.1
+        version: 3.2.3(pinia@2.2.4(typescript@5.6.3)(vue@3.5.12(typescript@5.6.3)))
+      vue:
+        specifier: ^3.4.21
+        version: 3.5.12(typescript@5.6.3)
+      vue-drag-resize:
+        specifier: ^1.5.4
+        version: 1.5.4
+      vue-router:
+        specifier: ^4.3.3
+        version: 4.4.5(vue@3.5.12(typescript@5.6.3))
+      vue3-draggable-resizable:
+        specifier: ^1.6.5
+        version: 1.6.5
+      vuedraggable:
+        specifier: ^4.1.0
+        version: 4.1.0(vue@3.5.12(typescript@5.6.3))
+    devDependencies:
+      '@types/node':
+        specifier: ^20.14.2
+        version: 20.16.11
+      '@vitejs/plugin-vue':
+        specifier: ^5.0.4
+        version: 5.1.4(vite@5.4.8(@types/node@20.16.11)(sass@1.79.5))(vue@3.5.12(typescript@5.6.3))
+      sass:
+        specifier: ^1.77.5
+        version: 1.79.5
+      sass-loader:
+        specifier: ^14.2.1
+        version: 14.2.1(sass@1.79.5)
+      typescript:
+        specifier: ^5.2.2
+        version: 5.6.3
+      vite:
+        specifier: ^5.2.0
+        version: 5.4.8(@types/node@20.16.11)(sass@1.79.5)
+      vue-tsc:
+        specifier: ^2.0.6
+        version: 2.1.6(typescript@5.6.3)
+
+packages:
+
+  '@babel/helper-string-parser@7.25.7':
+    resolution: {integrity: sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-validator-identifier@7.25.7':
+    resolution: {integrity: sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/parser@7.25.8':
+    resolution: {integrity: sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==}
+    engines: {node: '>=6.0.0'}
+    hasBin: true
+
+  '@babel/types@7.25.8':
+    resolution: {integrity: sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==}
+    engines: {node: '>=6.9.0'}
+
+  '@ctrl/tinycolor@3.6.1':
+    resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
+    engines: {node: '>=10'}
+
+  '@element-plus/icons-vue@2.3.1':
+    resolution: {integrity: sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==}
+    peerDependencies:
+      vue: ^3.2.0
+
+  '@esbuild/aix-ppc64@0.21.5':
+    resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
+    engines: {node: '>=12'}
+    cpu: [ppc64]
+    os: [aix]
+
+  '@esbuild/android-arm64@0.21.5':
+    resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [android]
+
+  '@esbuild/android-arm@0.21.5':
+    resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
+    engines: {node: '>=12'}
+    cpu: [arm]
+    os: [android]
+
+  '@esbuild/android-x64@0.21.5':
+    resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [android]
+
+  '@esbuild/darwin-arm64@0.21.5':
+    resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@esbuild/darwin-x64@0.21.5':
+    resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [darwin]
+
+  '@esbuild/freebsd-arm64@0.21.5':
+    resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [freebsd]
+
+  '@esbuild/freebsd-x64@0.21.5':
+    resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [freebsd]
+
+  '@esbuild/linux-arm64@0.21.5':
+    resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [linux]
+
+  '@esbuild/linux-arm@0.21.5':
+    resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
+    engines: {node: '>=12'}
+    cpu: [arm]
+    os: [linux]
+
+  '@esbuild/linux-ia32@0.21.5':
+    resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
+    engines: {node: '>=12'}
+    cpu: [ia32]
+    os: [linux]
+
+  '@esbuild/linux-loong64@0.21.5':
+    resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
+    engines: {node: '>=12'}
+    cpu: [loong64]
+    os: [linux]
+
+  '@esbuild/linux-mips64el@0.21.5':
+    resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
+    engines: {node: '>=12'}
+    cpu: [mips64el]
+    os: [linux]
+
+  '@esbuild/linux-ppc64@0.21.5':
+    resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
+    engines: {node: '>=12'}
+    cpu: [ppc64]
+    os: [linux]
+
+  '@esbuild/linux-riscv64@0.21.5':
+    resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
+    engines: {node: '>=12'}
+    cpu: [riscv64]
+    os: [linux]
+
+  '@esbuild/linux-s390x@0.21.5':
+    resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
+    engines: {node: '>=12'}
+    cpu: [s390x]
+    os: [linux]
+
+  '@esbuild/linux-x64@0.21.5':
+    resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [linux]
+
+  '@esbuild/netbsd-x64@0.21.5':
+    resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [netbsd]
+
+  '@esbuild/openbsd-x64@0.21.5':
+    resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [openbsd]
+
+  '@esbuild/sunos-x64@0.21.5':
+    resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [sunos]
+
+  '@esbuild/win32-arm64@0.21.5':
+    resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [win32]
+
+  '@esbuild/win32-ia32@0.21.5':
+    resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
+    engines: {node: '>=12'}
+    cpu: [ia32]
+    os: [win32]
+
+  '@esbuild/win32-x64@0.21.5':
+    resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [win32]
+
+  '@floating-ui/core@1.6.8':
+    resolution: {integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==}
+
+  '@floating-ui/dom@1.6.11':
+    resolution: {integrity: sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==}
+
+  '@floating-ui/utils@0.2.8':
+    resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==}
+
+  '@jridgewell/sourcemap-codec@1.5.0':
+    resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
+
+  '@parcel/watcher-android-arm64@2.4.1':
+    resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==}
+    engines: {node: '>= 10.0.0'}
+    cpu: [arm64]
+    os: [android]
+
+  '@parcel/watcher-darwin-arm64@2.4.1':
+    resolution: {integrity: sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==}
+    engines: {node: '>= 10.0.0'}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@parcel/watcher-darwin-x64@2.4.1':
+    resolution: {integrity: sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==}
+    engines: {node: '>= 10.0.0'}
+    cpu: [x64]
+    os: [darwin]
+
+  '@parcel/watcher-freebsd-x64@2.4.1':
+    resolution: {integrity: sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==}
+    engines: {node: '>= 10.0.0'}
+    cpu: [x64]
+    os: [freebsd]
+
+  '@parcel/watcher-linux-arm-glibc@2.4.1':
+    resolution: {integrity: sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==}
+    engines: {node: '>= 10.0.0'}
+    cpu: [arm]
+    os: [linux]
+    libc: [glibc]
+
+  '@parcel/watcher-linux-arm64-glibc@2.4.1':
+    resolution: {integrity: sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==}
+    engines: {node: '>= 10.0.0'}
+    cpu: [arm64]
+    os: [linux]
+    libc: [glibc]
+
+  '@parcel/watcher-linux-arm64-musl@2.4.1':
+    resolution: {integrity: sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==}
+    engines: {node: '>= 10.0.0'}
+    cpu: [arm64]
+    os: [linux]
+    libc: [musl]
+
+  '@parcel/watcher-linux-x64-glibc@2.4.1':
+    resolution: {integrity: sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==}
+    engines: {node: '>= 10.0.0'}
+    cpu: [x64]
+    os: [linux]
+    libc: [glibc]
+
+  '@parcel/watcher-linux-x64-musl@2.4.1':
+    resolution: {integrity: sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==}
+    engines: {node: '>= 10.0.0'}
+    cpu: [x64]
+    os: [linux]
+    libc: [musl]
+
+  '@parcel/watcher-win32-arm64@2.4.1':
+    resolution: {integrity: sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==}
+    engines: {node: '>= 10.0.0'}
+    cpu: [arm64]
+    os: [win32]
+
+  '@parcel/watcher-win32-ia32@2.4.1':
+    resolution: {integrity: sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==}
+    engines: {node: '>= 10.0.0'}
+    cpu: [ia32]
+    os: [win32]
+
+  '@parcel/watcher-win32-x64@2.4.1':
+    resolution: {integrity: sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==}
+    engines: {node: '>= 10.0.0'}
+    cpu: [x64]
+    os: [win32]
+
+  '@parcel/watcher@2.4.1':
+    resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==}
+    engines: {node: '>= 10.0.0'}
+
+  '@rollup/rollup-android-arm-eabi@4.24.0':
+    resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==}
+    cpu: [arm]
+    os: [android]
+
+  '@rollup/rollup-android-arm64@4.24.0':
+    resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==}
+    cpu: [arm64]
+    os: [android]
+
+  '@rollup/rollup-darwin-arm64@4.24.0':
+    resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@rollup/rollup-darwin-x64@4.24.0':
+    resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==}
+    cpu: [x64]
+    os: [darwin]
+
+  '@rollup/rollup-linux-arm-gnueabihf@4.24.0':
+    resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==}
+    cpu: [arm]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-arm-musleabihf@4.24.0':
+    resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==}
+    cpu: [arm]
+    os: [linux]
+    libc: [musl]
+
+  '@rollup/rollup-linux-arm64-gnu@4.24.0':
+    resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==}
+    cpu: [arm64]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-arm64-musl@4.24.0':
+    resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==}
+    cpu: [arm64]
+    os: [linux]
+    libc: [musl]
+
+  '@rollup/rollup-linux-powerpc64le-gnu@4.24.0':
+    resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==}
+    cpu: [ppc64]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-riscv64-gnu@4.24.0':
+    resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==}
+    cpu: [riscv64]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-s390x-gnu@4.24.0':
+    resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==}
+    cpu: [s390x]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-x64-gnu@4.24.0':
+    resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==}
+    cpu: [x64]
+    os: [linux]
+    libc: [glibc]
+
+  '@rollup/rollup-linux-x64-musl@4.24.0':
+    resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==}
+    cpu: [x64]
+    os: [linux]
+    libc: [musl]
+
+  '@rollup/rollup-win32-arm64-msvc@4.24.0':
+    resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==}
+    cpu: [arm64]
+    os: [win32]
+
+  '@rollup/rollup-win32-ia32-msvc@4.24.0':
+    resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==}
+    cpu: [ia32]
+    os: [win32]
+
+  '@rollup/rollup-win32-x64-msvc@4.24.0':
+    resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==}
+    cpu: [x64]
+    os: [win32]
+
+  '@sxzz/popperjs-es@2.11.7':
+    resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==}
+
+  '@types/estree@1.0.6':
+    resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
+
+  '@types/lodash-es@4.17.12':
+    resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
+
+  '@types/lodash@4.17.10':
+    resolution: {integrity: sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==}
+
+  '@types/node@20.16.11':
+    resolution: {integrity: sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==}
+
+  '@types/web-bluetooth@0.0.16':
+    resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==}
+
+  '@vitejs/plugin-vue@5.1.4':
+    resolution: {integrity: sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==}
+    engines: {node: ^18.0.0 || >=20.0.0}
+    peerDependencies:
+      vite: ^5.0.0
+      vue: ^3.2.25
+
+  '@volar/language-core@2.4.6':
+    resolution: {integrity: sha512-FxUfxaB8sCqvY46YjyAAV6c3mMIq/NWQMVvJ+uS4yxr1KzOvyg61gAuOnNvgCvO4TZ7HcLExBEsWcDu4+K4E8A==}
+
+  '@volar/source-map@2.4.6':
+    resolution: {integrity: sha512-Nsh7UW2ruK+uURIPzjJgF0YRGP5CX9nQHypA2OMqdM2FKy7rh+uv3XgPnWPw30JADbKvZ5HuBzG4gSbVDYVtiw==}
+
+  '@volar/typescript@2.4.6':
+    resolution: {integrity: sha512-NMIrA7y5OOqddL9VtngPWYmdQU03htNKFtAYidbYfWA0TOhyGVd9tfcP4TsLWQ+RBWDZCbBqsr8xzU0ZOxYTCQ==}
+
+  '@vue/compiler-core@3.5.12':
+    resolution: {integrity: sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==}
+
+  '@vue/compiler-dom@3.5.12':
+    resolution: {integrity: sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==}
+
+  '@vue/compiler-sfc@3.5.12':
+    resolution: {integrity: sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==}
+
+  '@vue/compiler-ssr@3.5.12':
+    resolution: {integrity: sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==}
+
+  '@vue/compiler-vue2@2.7.16':
+    resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==}
+
+  '@vue/devtools-api@6.6.4':
+    resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==}
+
+  '@vue/language-core@2.1.6':
+    resolution: {integrity: sha512-MW569cSky9R/ooKMh6xa2g1D0AtRKbL56k83dzus/bx//RDJk24RHWkMzbAlXjMdDNyxAaagKPRquBIxkxlCkg==}
+    peerDependencies:
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
+  '@vue/reactivity@3.5.12':
+    resolution: {integrity: sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==}
+
+  '@vue/runtime-core@3.5.12':
+    resolution: {integrity: sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==}
+
+  '@vue/runtime-dom@3.5.12':
+    resolution: {integrity: sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==}
+
+  '@vue/server-renderer@3.5.12':
+    resolution: {integrity: sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==}
+    peerDependencies:
+      vue: 3.5.12
+
+  '@vue/shared@3.5.12':
+    resolution: {integrity: sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==}
+
+  '@vueuse/core@9.13.0':
+    resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==}
+
+  '@vueuse/metadata@9.13.0':
+    resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==}
+
+  '@vueuse/shared@9.13.0':
+    resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==}
+
+  async-validator@4.2.5:
+    resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
+
+  asynckit@0.4.0:
+    resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+  axios@1.7.7:
+    resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==}
+
+  balanced-match@1.0.2:
+    resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+  brace-expansion@2.0.1:
+    resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+
+  braces@3.0.3:
+    resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+    engines: {node: '>=8'}
+
+  chokidar@4.0.1:
+    resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==}
+    engines: {node: '>= 14.16.0'}
+
+  color-convert@2.0.1:
+    resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+    engines: {node: '>=7.0.0'}
+
+  color-name@1.1.4:
+    resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+  color-string@1.9.1:
+    resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
+
+  color@4.2.3:
+    resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
+    engines: {node: '>=12.5.0'}
+
+  combined-stream@1.0.8:
+    resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+    engines: {node: '>= 0.8'}
+
+  computeds@0.0.1:
+    resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==}
+
+  csstype@3.1.3:
+    resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+  dayjs@1.11.13:
+    resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
+
+  de-indent@1.0.2:
+    resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
+
+  delayed-stream@1.0.0:
+    resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+    engines: {node: '>=0.4.0'}
+
+  detect-libc@1.0.3:
+    resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
+    engines: {node: '>=0.10'}
+    hasBin: true
+
+  element-plus@2.8.5:
+    resolution: {integrity: sha512-Px+kPbRTVvn5oa5+9saa7QEOnUweKXm0JVI7yJHzKF/doQGixwcFMsQEF2+3Fy62EA/7dRRKVuhsNGGZYNk3cw==}
+    peerDependencies:
+      vue: ^3.2.0
+
+  entities@4.5.0:
+    resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+    engines: {node: '>=0.12'}
+
+  esbuild@0.21.5:
+    resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
+    engines: {node: '>=12'}
+    hasBin: true
+
+  escape-html@1.0.3:
+    resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+
+  estree-walker@2.0.2:
+    resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+
+  fill-range@7.1.1:
+    resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+    engines: {node: '>=8'}
+
+  follow-redirects@1.15.9:
+    resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==}
+    engines: {node: '>=4.0'}
+    peerDependencies:
+      debug: '*'
+    peerDependenciesMeta:
+      debug:
+        optional: true
+
+  form-data@4.0.1:
+    resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==}
+    engines: {node: '>= 6'}
+
+  fsevents@2.3.3:
+    resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+    engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+    os: [darwin]
+
+  he@1.2.0:
+    resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
+    hasBin: true
+
+  immutable@4.3.7:
+    resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==}
+
+  is-arrayish@0.3.2:
+    resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
+
+  is-extglob@2.1.1:
+    resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+    engines: {node: '>=0.10.0'}
+
+  is-glob@4.0.3:
+    resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+    engines: {node: '>=0.10.0'}
+
+  is-number@7.0.0:
+    resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+    engines: {node: '>=0.12.0'}
+
+  lodash-es@4.17.21:
+    resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
+
+  lodash-unified@1.0.3:
+    resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==}
+    peerDependencies:
+      '@types/lodash-es': '*'
+      lodash: '*'
+      lodash-es: '*'
+
+  lodash@4.17.21:
+    resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
+  magic-string@0.30.12:
+    resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==}
+
+  memoize-one@6.0.0:
+    resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==}
+
+  micromatch@4.0.8:
+    resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+    engines: {node: '>=8.6'}
+
+  mime-db@1.52.0:
+    resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+    engines: {node: '>= 0.6'}
+
+  mime-types@2.1.35:
+    resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+    engines: {node: '>= 0.6'}
+
+  minimatch@9.0.5:
+    resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
+    engines: {node: '>=16 || 14 >=14.17'}
+
+  muggle-string@0.4.1:
+    resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
+
+  nanoid@3.3.7:
+    resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+    engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+    hasBin: true
+
+  neo-async@2.6.2:
+    resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
+
+  node-addon-api@7.1.1:
+    resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
+
+  normalize-wheel-es@1.2.0:
+    resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==}
+
+  path-browserify@1.0.1:
+    resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
+
+  picocolors@1.1.0:
+    resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==}
+
+  picomatch@2.3.1:
+    resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+    engines: {node: '>=8.6'}
+
+  pinia-plugin-persistedstate@3.2.3:
+    resolution: {integrity: sha512-Cm819WBj/s5K5DGw55EwbXDtx+EZzM0YR5AZbq9XE3u0xvXwvX2JnWoFpWIcdzISBHqy9H1UiSIUmXyXqWsQRQ==}
+    peerDependencies:
+      pinia: ^2.0.0
+
+  pinia@2.2.4:
+    resolution: {integrity: sha512-K7ZhpMY9iJ9ShTC0cR2+PnxdQRuwVIsXDO/WIEV/RnMC/vmSoKDTKW/exNQYPI+4ij10UjXqdNiEHwn47McANQ==}
+    peerDependencies:
+      '@vue/composition-api': ^1.4.0
+      typescript: '>=4.4.4'
+      vue: ^2.6.14 || ^3.3.0
+    peerDependenciesMeta:
+      '@vue/composition-api':
+        optional: true
+      typescript:
+        optional: true
+
+  postcss@8.4.47:
+    resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==}
+    engines: {node: ^10 || ^12 || >=14}
+
+  proxy-from-env@1.1.0:
+    resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+
+  readdirp@4.0.2:
+    resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==}
+    engines: {node: '>= 14.16.0'}
+
+  rollup@4.24.0:
+    resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==}
+    engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+    hasBin: true
+
+  sass-loader@14.2.1:
+    resolution: {integrity: sha512-G0VcnMYU18a4N7VoNDegg2OuMjYtxnqzQWARVWCIVSZwJeiL9kg8QMsuIZOplsJgTzZLF6jGxI3AClj8I9nRdQ==}
+    engines: {node: '>= 18.12.0'}
+    peerDependencies:
+      '@rspack/core': 0.x || 1.x
+      node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
+      sass: ^1.3.0
+      sass-embedded: '*'
+      webpack: ^5.0.0
+    peerDependenciesMeta:
+      '@rspack/core':
+        optional: true
+      node-sass:
+        optional: true
+      sass:
+        optional: true
+      sass-embedded:
+        optional: true
+      webpack:
+        optional: true
+
+  sass@1.79.5:
+    resolution: {integrity: sha512-W1h5kp6bdhqFh2tk3DsI771MoEJjvrSY/2ihJRJS4pjIyfJCw0nTsxqhnrUzaLMOJjFchj8rOvraI/YUVjtx5g==}
+    engines: {node: '>=14.0.0'}
+    hasBin: true
+
+  semver@7.6.3:
+    resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
+    engines: {node: '>=10'}
+    hasBin: true
+
+  simple-swizzle@0.2.2:
+    resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
+
+  sortablejs@1.14.0:
+    resolution: {integrity: sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==}
+
+  source-map-js@1.2.1:
+    resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+    engines: {node: '>=0.10.0'}
+
+  to-fast-properties@2.0.0:
+    resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+    engines: {node: '>=4'}
+
+  to-regex-range@5.0.1:
+    resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+    engines: {node: '>=8.0'}
+
+  typescript@5.6.3:
+    resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
+    engines: {node: '>=14.17'}
+    hasBin: true
+
+  undici-types@6.19.8:
+    resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
+
+  vite@5.4.8:
+    resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==}
+    engines: {node: ^18.0.0 || >=20.0.0}
+    hasBin: true
+    peerDependencies:
+      '@types/node': ^18.0.0 || >=20.0.0
+      less: '*'
+      lightningcss: ^1.21.0
+      sass: '*'
+      sass-embedded: '*'
+      stylus: '*'
+      sugarss: '*'
+      terser: ^5.4.0
+    peerDependenciesMeta:
+      '@types/node':
+        optional: true
+      less:
+        optional: true
+      lightningcss:
+        optional: true
+      sass:
+        optional: true
+      sass-embedded:
+        optional: true
+      stylus:
+        optional: true
+      sugarss:
+        optional: true
+      terser:
+        optional: true
+
+  vscode-uri@3.0.8:
+    resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
+
+  vue-demi@0.14.10:
+    resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
+    engines: {node: '>=12'}
+    hasBin: true
+    peerDependencies:
+      '@vue/composition-api': ^1.0.0-rc.1
+      vue: ^3.0.0-0 || ^2.6.0
+    peerDependenciesMeta:
+      '@vue/composition-api':
+        optional: true
+
+  vue-drag-resize@1.5.4:
+    resolution: {integrity: sha512-SR3U7n6TAZEBgP7zw7bR9mjtAlYBjqIoaWTDPz5HXN/nYhOxKSA31aD7p71fmq1jtyt9reAnCx62valNL9ZAcg==}
+    engines: {node: '>= 4.0.0', npm: '>= 3.0.0'}
+
+  vue-router@4.4.5:
+    resolution: {integrity: sha512-4fKZygS8cH1yCyuabAXGUAsyi1b2/o/OKgu/RUb+znIYOxPRxdkytJEx+0wGcpBE1pX6vUgh5jwWOKRGvuA/7Q==}
+    peerDependencies:
+      vue: ^3.2.0
+
+  vue-tsc@2.1.6:
+    resolution: {integrity: sha512-f98dyZp5FOukcYmbFpuSCJ4Z0vHSOSmxGttZJCsFeX0M4w/Rsq0s4uKXjcSRsZqsRgQa6z7SfuO+y0HVICE57Q==}
+    hasBin: true
+    peerDependencies:
+      typescript: '>=5.0.0'
+
+  vue3-draggable-resizable@1.6.5:
+    resolution: {integrity: sha512-31142E31fGNnq3HKqvmFLSsqIbhck7TyGuQWhUKrDw6DOcGAuRx4ddRjaxvT6fe7dgeKH53qAh+i0ZlWtPLl2g==}
+
+  vue@3.5.12:
+    resolution: {integrity: sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==}
+    peerDependencies:
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
+  vuedraggable@4.1.0:
+    resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==}
+    peerDependencies:
+      vue: ^3.0.1
+
+snapshots:
+
+  '@babel/helper-string-parser@7.25.7': {}
+
+  '@babel/helper-validator-identifier@7.25.7': {}
+
+  '@babel/parser@7.25.8':
+    dependencies:
+      '@babel/types': 7.25.8
+
+  '@babel/types@7.25.8':
+    dependencies:
+      '@babel/helper-string-parser': 7.25.7
+      '@babel/helper-validator-identifier': 7.25.7
+      to-fast-properties: 2.0.0
+
+  '@ctrl/tinycolor@3.6.1': {}
+
+  '@element-plus/icons-vue@2.3.1(vue@3.5.12(typescript@5.6.3))':
+    dependencies:
+      vue: 3.5.12(typescript@5.6.3)
+
+  '@esbuild/aix-ppc64@0.21.5':
+    optional: true
+
+  '@esbuild/android-arm64@0.21.5':
+    optional: true
+
+  '@esbuild/android-arm@0.21.5':
+    optional: true
+
+  '@esbuild/android-x64@0.21.5':
+    optional: true
+
+  '@esbuild/darwin-arm64@0.21.5':
+    optional: true
+
+  '@esbuild/darwin-x64@0.21.5':
+    optional: true
+
+  '@esbuild/freebsd-arm64@0.21.5':
+    optional: true
+
+  '@esbuild/freebsd-x64@0.21.5':
+    optional: true
+
+  '@esbuild/linux-arm64@0.21.5':
+    optional: true
+
+  '@esbuild/linux-arm@0.21.5':
+    optional: true
+
+  '@esbuild/linux-ia32@0.21.5':
+    optional: true
+
+  '@esbuild/linux-loong64@0.21.5':
+    optional: true
+
+  '@esbuild/linux-mips64el@0.21.5':
+    optional: true
+
+  '@esbuild/linux-ppc64@0.21.5':
+    optional: true
+
+  '@esbuild/linux-riscv64@0.21.5':
+    optional: true
+
+  '@esbuild/linux-s390x@0.21.5':
+    optional: true
+
+  '@esbuild/linux-x64@0.21.5':
+    optional: true
+
+  '@esbuild/netbsd-x64@0.21.5':
+    optional: true
+
+  '@esbuild/openbsd-x64@0.21.5':
+    optional: true
+
+  '@esbuild/sunos-x64@0.21.5':
+    optional: true
+
+  '@esbuild/win32-arm64@0.21.5':
+    optional: true
+
+  '@esbuild/win32-ia32@0.21.5':
+    optional: true
+
+  '@esbuild/win32-x64@0.21.5':
+    optional: true
+
+  '@floating-ui/core@1.6.8':
+    dependencies:
+      '@floating-ui/utils': 0.2.8
+
+  '@floating-ui/dom@1.6.11':
+    dependencies:
+      '@floating-ui/core': 1.6.8
+      '@floating-ui/utils': 0.2.8
+
+  '@floating-ui/utils@0.2.8': {}
+
+  '@jridgewell/sourcemap-codec@1.5.0': {}
+
+  '@parcel/watcher-android-arm64@2.4.1':
+    optional: true
+
+  '@parcel/watcher-darwin-arm64@2.4.1':
+    optional: true
+
+  '@parcel/watcher-darwin-x64@2.4.1':
+    optional: true
+
+  '@parcel/watcher-freebsd-x64@2.4.1':
+    optional: true
+
+  '@parcel/watcher-linux-arm-glibc@2.4.1':
+    optional: true
+
+  '@parcel/watcher-linux-arm64-glibc@2.4.1':
+    optional: true
+
+  '@parcel/watcher-linux-arm64-musl@2.4.1':
+    optional: true
+
+  '@parcel/watcher-linux-x64-glibc@2.4.1':
+    optional: true
+
+  '@parcel/watcher-linux-x64-musl@2.4.1':
+    optional: true
+
+  '@parcel/watcher-win32-arm64@2.4.1':
+    optional: true
+
+  '@parcel/watcher-win32-ia32@2.4.1':
+    optional: true
+
+  '@parcel/watcher-win32-x64@2.4.1':
+    optional: true
+
+  '@parcel/watcher@2.4.1':
+    dependencies:
+      detect-libc: 1.0.3
+      is-glob: 4.0.3
+      micromatch: 4.0.8
+      node-addon-api: 7.1.1
+    optionalDependencies:
+      '@parcel/watcher-android-arm64': 2.4.1
+      '@parcel/watcher-darwin-arm64': 2.4.1
+      '@parcel/watcher-darwin-x64': 2.4.1
+      '@parcel/watcher-freebsd-x64': 2.4.1
+      '@parcel/watcher-linux-arm-glibc': 2.4.1
+      '@parcel/watcher-linux-arm64-glibc': 2.4.1
+      '@parcel/watcher-linux-arm64-musl': 2.4.1
+      '@parcel/watcher-linux-x64-glibc': 2.4.1
+      '@parcel/watcher-linux-x64-musl': 2.4.1
+      '@parcel/watcher-win32-arm64': 2.4.1
+      '@parcel/watcher-win32-ia32': 2.4.1
+      '@parcel/watcher-win32-x64': 2.4.1
+
+  '@rollup/rollup-android-arm-eabi@4.24.0':
+    optional: true
+
+  '@rollup/rollup-android-arm64@4.24.0':
+    optional: true
+
+  '@rollup/rollup-darwin-arm64@4.24.0':
+    optional: true
+
+  '@rollup/rollup-darwin-x64@4.24.0':
+    optional: true
+
+  '@rollup/rollup-linux-arm-gnueabihf@4.24.0':
+    optional: true
+
+  '@rollup/rollup-linux-arm-musleabihf@4.24.0':
+    optional: true
+
+  '@rollup/rollup-linux-arm64-gnu@4.24.0':
+    optional: true
+
+  '@rollup/rollup-linux-arm64-musl@4.24.0':
+    optional: true
+
+  '@rollup/rollup-linux-powerpc64le-gnu@4.24.0':
+    optional: true
+
+  '@rollup/rollup-linux-riscv64-gnu@4.24.0':
+    optional: true
+
+  '@rollup/rollup-linux-s390x-gnu@4.24.0':
+    optional: true
+
+  '@rollup/rollup-linux-x64-gnu@4.24.0':
+    optional: true
+
+  '@rollup/rollup-linux-x64-musl@4.24.0':
+    optional: true
+
+  '@rollup/rollup-win32-arm64-msvc@4.24.0':
+    optional: true
+
+  '@rollup/rollup-win32-ia32-msvc@4.24.0':
+    optional: true
+
+  '@rollup/rollup-win32-x64-msvc@4.24.0':
+    optional: true
+
+  '@sxzz/popperjs-es@2.11.7': {}
+
+  '@types/estree@1.0.6': {}
+
+  '@types/lodash-es@4.17.12':
+    dependencies:
+      '@types/lodash': 4.17.10
+
+  '@types/lodash@4.17.10': {}
+
+  '@types/node@20.16.11':
+    dependencies:
+      undici-types: 6.19.8
+
+  '@types/web-bluetooth@0.0.16': {}
+
+  '@vitejs/plugin-vue@5.1.4(vite@5.4.8(@types/node@20.16.11)(sass@1.79.5))(vue@3.5.12(typescript@5.6.3))':
+    dependencies:
+      vite: 5.4.8(@types/node@20.16.11)(sass@1.79.5)
+      vue: 3.5.12(typescript@5.6.3)
+
+  '@volar/language-core@2.4.6':
+    dependencies:
+      '@volar/source-map': 2.4.6
+
+  '@volar/source-map@2.4.6': {}
+
+  '@volar/typescript@2.4.6':
+    dependencies:
+      '@volar/language-core': 2.4.6
+      path-browserify: 1.0.1
+      vscode-uri: 3.0.8
+
+  '@vue/compiler-core@3.5.12':
+    dependencies:
+      '@babel/parser': 7.25.8
+      '@vue/shared': 3.5.12
+      entities: 4.5.0
+      estree-walker: 2.0.2
+      source-map-js: 1.2.1
+
+  '@vue/compiler-dom@3.5.12':
+    dependencies:
+      '@vue/compiler-core': 3.5.12
+      '@vue/shared': 3.5.12
+
+  '@vue/compiler-sfc@3.5.12':
+    dependencies:
+      '@babel/parser': 7.25.8
+      '@vue/compiler-core': 3.5.12
+      '@vue/compiler-dom': 3.5.12
+      '@vue/compiler-ssr': 3.5.12
+      '@vue/shared': 3.5.12
+      estree-walker: 2.0.2
+      magic-string: 0.30.12
+      postcss: 8.4.47
+      source-map-js: 1.2.1
+
+  '@vue/compiler-ssr@3.5.12':
+    dependencies:
+      '@vue/compiler-dom': 3.5.12
+      '@vue/shared': 3.5.12
+
+  '@vue/compiler-vue2@2.7.16':
+    dependencies:
+      de-indent: 1.0.2
+      he: 1.2.0
+
+  '@vue/devtools-api@6.6.4': {}
+
+  '@vue/language-core@2.1.6(typescript@5.6.3)':
+    dependencies:
+      '@volar/language-core': 2.4.6
+      '@vue/compiler-dom': 3.5.12
+      '@vue/compiler-vue2': 2.7.16
+      '@vue/shared': 3.5.12
+      computeds: 0.0.1
+      minimatch: 9.0.5
+      muggle-string: 0.4.1
+      path-browserify: 1.0.1
+    optionalDependencies:
+      typescript: 5.6.3
+
+  '@vue/reactivity@3.5.12':
+    dependencies:
+      '@vue/shared': 3.5.12
+
+  '@vue/runtime-core@3.5.12':
+    dependencies:
+      '@vue/reactivity': 3.5.12
+      '@vue/shared': 3.5.12
+
+  '@vue/runtime-dom@3.5.12':
+    dependencies:
+      '@vue/reactivity': 3.5.12
+      '@vue/runtime-core': 3.5.12
+      '@vue/shared': 3.5.12
+      csstype: 3.1.3
+
+  '@vue/server-renderer@3.5.12(vue@3.5.12(typescript@5.6.3))':
+    dependencies:
+      '@vue/compiler-ssr': 3.5.12
+      '@vue/shared': 3.5.12
+      vue: 3.5.12(typescript@5.6.3)
+
+  '@vue/shared@3.5.12': {}
+
+  '@vueuse/core@9.13.0(vue@3.5.12(typescript@5.6.3))':
+    dependencies:
+      '@types/web-bluetooth': 0.0.16
+      '@vueuse/metadata': 9.13.0
+      '@vueuse/shared': 9.13.0(vue@3.5.12(typescript@5.6.3))
+      vue-demi: 0.14.10(vue@3.5.12(typescript@5.6.3))
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+      - vue
+
+  '@vueuse/metadata@9.13.0': {}
+
+  '@vueuse/shared@9.13.0(vue@3.5.12(typescript@5.6.3))':
+    dependencies:
+      vue-demi: 0.14.10(vue@3.5.12(typescript@5.6.3))
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+      - vue
+
+  async-validator@4.2.5: {}
+
+  asynckit@0.4.0: {}
+
+  axios@1.7.7:
+    dependencies:
+      follow-redirects: 1.15.9
+      form-data: 4.0.1
+      proxy-from-env: 1.1.0
+    transitivePeerDependencies:
+      - debug
+
+  balanced-match@1.0.2: {}
+
+  brace-expansion@2.0.1:
+    dependencies:
+      balanced-match: 1.0.2
+
+  braces@3.0.3:
+    dependencies:
+      fill-range: 7.1.1
+
+  chokidar@4.0.1:
+    dependencies:
+      readdirp: 4.0.2
+
+  color-convert@2.0.1:
+    dependencies:
+      color-name: 1.1.4
+
+  color-name@1.1.4: {}
+
+  color-string@1.9.1:
+    dependencies:
+      color-name: 1.1.4
+      simple-swizzle: 0.2.2
+
+  color@4.2.3:
+    dependencies:
+      color-convert: 2.0.1
+      color-string: 1.9.1
+
+  combined-stream@1.0.8:
+    dependencies:
+      delayed-stream: 1.0.0
+
+  computeds@0.0.1: {}
+
+  csstype@3.1.3: {}
+
+  dayjs@1.11.13: {}
+
+  de-indent@1.0.2: {}
+
+  delayed-stream@1.0.0: {}
+
+  detect-libc@1.0.3: {}
+
+  element-plus@2.8.5(vue@3.5.12(typescript@5.6.3)):
+    dependencies:
+      '@ctrl/tinycolor': 3.6.1
+      '@element-plus/icons-vue': 2.3.1(vue@3.5.12(typescript@5.6.3))
+      '@floating-ui/dom': 1.6.11
+      '@popperjs/core': '@sxzz/popperjs-es@2.11.7'
+      '@types/lodash': 4.17.10
+      '@types/lodash-es': 4.17.12
+      '@vueuse/core': 9.13.0(vue@3.5.12(typescript@5.6.3))
+      async-validator: 4.2.5
+      dayjs: 1.11.13
+      escape-html: 1.0.3
+      lodash: 4.17.21
+      lodash-es: 4.17.21
+      lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21)
+      memoize-one: 6.0.0
+      normalize-wheel-es: 1.2.0
+      vue: 3.5.12(typescript@5.6.3)
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+
+  entities@4.5.0: {}
+
+  esbuild@0.21.5:
+    optionalDependencies:
+      '@esbuild/aix-ppc64': 0.21.5
+      '@esbuild/android-arm': 0.21.5
+      '@esbuild/android-arm64': 0.21.5
+      '@esbuild/android-x64': 0.21.5
+      '@esbuild/darwin-arm64': 0.21.5
+      '@esbuild/darwin-x64': 0.21.5
+      '@esbuild/freebsd-arm64': 0.21.5
+      '@esbuild/freebsd-x64': 0.21.5
+      '@esbuild/linux-arm': 0.21.5
+      '@esbuild/linux-arm64': 0.21.5
+      '@esbuild/linux-ia32': 0.21.5
+      '@esbuild/linux-loong64': 0.21.5
+      '@esbuild/linux-mips64el': 0.21.5
+      '@esbuild/linux-ppc64': 0.21.5
+      '@esbuild/linux-riscv64': 0.21.5
+      '@esbuild/linux-s390x': 0.21.5
+      '@esbuild/linux-x64': 0.21.5
+      '@esbuild/netbsd-x64': 0.21.5
+      '@esbuild/openbsd-x64': 0.21.5
+      '@esbuild/sunos-x64': 0.21.5
+      '@esbuild/win32-arm64': 0.21.5
+      '@esbuild/win32-ia32': 0.21.5
+      '@esbuild/win32-x64': 0.21.5
+
+  escape-html@1.0.3: {}
+
+  estree-walker@2.0.2: {}
+
+  fill-range@7.1.1:
+    dependencies:
+      to-regex-range: 5.0.1
+
+  follow-redirects@1.15.9: {}
+
+  form-data@4.0.1:
+    dependencies:
+      asynckit: 0.4.0
+      combined-stream: 1.0.8
+      mime-types: 2.1.35
+
+  fsevents@2.3.3:
+    optional: true
+
+  he@1.2.0: {}
+
+  immutable@4.3.7: {}
+
+  is-arrayish@0.3.2: {}
+
+  is-extglob@2.1.1: {}
+
+  is-glob@4.0.3:
+    dependencies:
+      is-extglob: 2.1.1
+
+  is-number@7.0.0: {}
+
+  lodash-es@4.17.21: {}
+
+  lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21):
+    dependencies:
+      '@types/lodash-es': 4.17.12
+      lodash: 4.17.21
+      lodash-es: 4.17.21
+
+  lodash@4.17.21: {}
+
+  magic-string@0.30.12:
+    dependencies:
+      '@jridgewell/sourcemap-codec': 1.5.0
+
+  memoize-one@6.0.0: {}
+
+  micromatch@4.0.8:
+    dependencies:
+      braces: 3.0.3
+      picomatch: 2.3.1
+
+  mime-db@1.52.0: {}
+
+  mime-types@2.1.35:
+    dependencies:
+      mime-db: 1.52.0
+
+  minimatch@9.0.5:
+    dependencies:
+      brace-expansion: 2.0.1
+
+  muggle-string@0.4.1: {}
+
+  nanoid@3.3.7: {}
+
+  neo-async@2.6.2: {}
+
+  node-addon-api@7.1.1: {}
+
+  normalize-wheel-es@1.2.0: {}
+
+  path-browserify@1.0.1: {}
+
+  picocolors@1.1.0: {}
+
+  picomatch@2.3.1: {}
+
+  pinia-plugin-persistedstate@3.2.3(pinia@2.2.4(typescript@5.6.3)(vue@3.5.12(typescript@5.6.3))):
+    dependencies:
+      pinia: 2.2.4(typescript@5.6.3)(vue@3.5.12(typescript@5.6.3))
+
+  pinia@2.2.4(typescript@5.6.3)(vue@3.5.12(typescript@5.6.3)):
+    dependencies:
+      '@vue/devtools-api': 6.6.4
+      vue: 3.5.12(typescript@5.6.3)
+      vue-demi: 0.14.10(vue@3.5.12(typescript@5.6.3))
+    optionalDependencies:
+      typescript: 5.6.3
+
+  postcss@8.4.47:
+    dependencies:
+      nanoid: 3.3.7
+      picocolors: 1.1.0
+      source-map-js: 1.2.1
+
+  proxy-from-env@1.1.0: {}
+
+  readdirp@4.0.2: {}
+
+  rollup@4.24.0:
+    dependencies:
+      '@types/estree': 1.0.6
+    optionalDependencies:
+      '@rollup/rollup-android-arm-eabi': 4.24.0
+      '@rollup/rollup-android-arm64': 4.24.0
+      '@rollup/rollup-darwin-arm64': 4.24.0
+      '@rollup/rollup-darwin-x64': 4.24.0
+      '@rollup/rollup-linux-arm-gnueabihf': 4.24.0
+      '@rollup/rollup-linux-arm-musleabihf': 4.24.0
+      '@rollup/rollup-linux-arm64-gnu': 4.24.0
+      '@rollup/rollup-linux-arm64-musl': 4.24.0
+      '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0
+      '@rollup/rollup-linux-riscv64-gnu': 4.24.0
+      '@rollup/rollup-linux-s390x-gnu': 4.24.0
+      '@rollup/rollup-linux-x64-gnu': 4.24.0
+      '@rollup/rollup-linux-x64-musl': 4.24.0
+      '@rollup/rollup-win32-arm64-msvc': 4.24.0
+      '@rollup/rollup-win32-ia32-msvc': 4.24.0
+      '@rollup/rollup-win32-x64-msvc': 4.24.0
+      fsevents: 2.3.3
+
+  sass-loader@14.2.1(sass@1.79.5):
+    dependencies:
+      neo-async: 2.6.2
+    optionalDependencies:
+      sass: 1.79.5
+
+  sass@1.79.5:
+    dependencies:
+      '@parcel/watcher': 2.4.1
+      chokidar: 4.0.1
+      immutable: 4.3.7
+      source-map-js: 1.2.1
+
+  semver@7.6.3: {}
+
+  simple-swizzle@0.2.2:
+    dependencies:
+      is-arrayish: 0.3.2
+
+  sortablejs@1.14.0: {}
+
+  source-map-js@1.2.1: {}
+
+  to-fast-properties@2.0.0: {}
+
+  to-regex-range@5.0.1:
+    dependencies:
+      is-number: 7.0.0
+
+  typescript@5.6.3: {}
+
+  undici-types@6.19.8: {}
+
+  vite@5.4.8(@types/node@20.16.11)(sass@1.79.5):
+    dependencies:
+      esbuild: 0.21.5
+      postcss: 8.4.47
+      rollup: 4.24.0
+    optionalDependencies:
+      '@types/node': 20.16.11
+      fsevents: 2.3.3
+      sass: 1.79.5
+
+  vscode-uri@3.0.8: {}
+
+  vue-demi@0.14.10(vue@3.5.12(typescript@5.6.3)):
+    dependencies:
+      vue: 3.5.12(typescript@5.6.3)
+
+  vue-drag-resize@1.5.4: {}
+
+  vue-router@4.4.5(vue@3.5.12(typescript@5.6.3)):
+    dependencies:
+      '@vue/devtools-api': 6.6.4
+      vue: 3.5.12(typescript@5.6.3)
+
+  vue-tsc@2.1.6(typescript@5.6.3):
+    dependencies:
+      '@volar/typescript': 2.4.6
+      '@vue/language-core': 2.1.6(typescript@5.6.3)
+      semver: 7.6.3
+      typescript: 5.6.3
+
+  vue3-draggable-resizable@1.6.5: {}
+
+  vue@3.5.12(typescript@5.6.3):
+    dependencies:
+      '@vue/compiler-dom': 3.5.12
+      '@vue/compiler-sfc': 3.5.12
+      '@vue/runtime-dom': 3.5.12
+      '@vue/server-renderer': 3.5.12(vue@3.5.12(typescript@5.6.3))
+      '@vue/shared': 3.5.12
+    optionalDependencies:
+      typescript: 5.6.3
+
+  vuedraggable@4.1.0(vue@3.5.12(typescript@5.6.3)):
+    dependencies:
+      sortablejs: 1.14.0
+      vue: 3.5.12(typescript@5.6.3)

+ 17 - 0
src/api/classify/index.ts

@@ -0,0 +1,17 @@
+import { get } from '../http/request'
+// 获取分类列表
+export const getOutPatientsApi = async (data: object) => {
+    let ret = get({
+        url: `/componentclass`,
+        data
+    })
+    return ret
+}
+// 获取组件列表
+export const getComponentListApi = async (data: object) => {
+    let ret = get({
+        url: `/componentList`,
+        data
+    })
+    return ret
+}

+ 114 - 0
src/api/http/request.ts

@@ -0,0 +1,114 @@
+import axios from "axios"
+import { ElMessage } from 'element-plus'
+import router from "../../router/index.ts"
+
+const baseUrl = '/api';
+const Service = axios.create({
+    timeout: 8000,
+    baseURL: baseUrl,
+    headers: {
+        "Content-type": "application/json;charset=utf-8",
+        "Authorization": ""
+    }
+})
+// 添加请求拦截器
+Service.interceptors.request.use(function (config) {
+    // 在发送请求之前做些什么
+    if (config.headers.Authorization == null || config.headers.Authorization == "") {
+        // config.headers.Authorization = 'manage:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjozLCJ1c2VyX25hbWUiOiJ5YW5nIiwicm9sZSI6ImFkbWluIiwiaXNzIjoibGNfb2F1dGgiLCJleHAiOjE3MjkyMTQ1MjV9.eyNs2QV4-e6TBKCh2KfxarWEM0Cmaw9cYEz1EMQ8838'
+    }
+    return config;
+}, function (error) {
+    // 对请求错误做些什么
+    return Promise.reject(error);
+});
+
+// 添加响应拦截器
+Service.interceptors.response.use(function (response) {
+    const data = response.data;
+    if (data.code != undefined) {
+        if (data.code != 200 && data.code != 201) {
+            if (data.code == 401) {
+                router.push('/')
+                return data;
+            }
+            ElMessage.error(data.message || "服务器出错")
+            return data
+        }
+    }
+    return data
+}, function (error) {
+    if (error && error.response) {
+        switch (error.response.status) {
+            case 400:
+                error.message = '错误请求';
+                break;
+            case 401:
+                error.message = '未授权,请重新登录';
+                break;
+            case 403:
+                error.message = '禁止访问';
+                break;
+            case 404:
+                error.message = '请求的资源不存在';
+                break;
+            case 408:
+                error.message = '请求超时';
+                break;
+            case 500:
+                error.message = '服务器内部错误';
+                break;
+            case 501:
+                error.message = '服务未实现';
+                break;
+            case 502:
+                error.message = '网关错误';
+                break;
+            case 503:
+                error.message = '服务不可用';
+                break;
+            case 504:
+                error.message = '网关超时';
+                break;
+            case 505:
+                error.message = 'HTTP版本不受支持';
+                break;
+            default:
+                error.message = `连接错误${error.response.status}`;
+        }
+    } else {
+        error.message = '连接到服务器失败';
+    }
+    ElMessage.error(error.message || "服务器出错")
+    // console.error('HTTP Error:', error);
+    // 超出 2xx 范围的状态码都会触发该函数。
+    // 对响应错误做点什么
+    return Promise.reject(error);
+});
+
+
+
+// get请求
+export const get = async (config: any) => {
+    let ret = await Service({ ...config, method: "get", params: config.data })
+    return ret
+}
+
+// post请求
+export const post = async (config: any) => {
+    let ret = await Service({ ...config, method: "post", data: config.data })
+    return ret
+}
+
+
+// put请求
+export const put = async (config: any) => {
+    let ret = await Service({ ...config, method: "put", data: config.data })
+    return ret
+}
+
+// delete请求
+export const del = async (config: any) => {
+    let ret = await Service({ ...config, method: "delete" })
+    return ret
+}

BIN
src/assets/componentIcon/Switch1.png


BIN
src/assets/componentIcon/Switch2.png


BIN
src/assets/componentIcon/Switch3.png


BIN
src/assets/componentIcon/Vertical1.png


BIN
src/assets/componentIcon/Vertical2.png


BIN
src/assets/componentIcon/Vertical3.png


BIN
src/assets/componentIcon/slide1.png


BIN
src/assets/componentIcon/slide2.png


BIN
src/assets/componentIcon/slide3.png


+ 1 - 1
src/components/drag/index.vue

@@ -7,7 +7,7 @@
 </template>
 
 <script lang="ts" setup>
-import getName from '../../views/widgets/getWidget';
+import getName from '../widgets/getWidget';
 import VueDragResize from 'vue-drag-resize/src'
 import { ref } from "vue";
 const w = ref(0)

+ 5 - 5
src/components/drag/resizable.vue

@@ -1,11 +1,11 @@
 <template>
     <Vue3DraggableResizable :style="{ zIndex: zIndex, }"
         :classNameDraggable="dargData.config.lineNum ? 'forceAutoHeight' : ''" :snap="true" classNameActive="active"
-        :key="dargData.soleId" :initW="initW" :initH="initH" v-model:x="left" v-model:y="top" v-model:w="w" v-model:h="h"
-        v-model:active="active" :handles="sticks" :draggable="draggable" :resizable="resizable"
+        :key="dargData.soleId" :initW="initW" :initH="initH" v-model:x="left" v-model:y="top" v-model:w="w"
+        v-model:h="h" v-model:active="active" :handles="sticks" :draggable="draggable" :resizable="resizable"
         @drag-start="print('drag-start')" @resize-start="print('resize-start')" @resizing="print('resizing')"
-        @dragging="print('dragging')" @drag-end="print('drag-end')" @resize-end="print('resize-end')" @activated="activated"
-        @deactivated="deactivated" @click.native="clickHandler">
+        @dragging="print('dragging')" @drag-end="print('drag-end')" @resize-end="print('resize-end')"
+        @activated="activated" @deactivated="deactivated" @click.native="clickHandler">
         <component :is="getWidget(currentItem.type)" :config="currentItem"></component>
         <!-- 锁定 -->
         <div class="card_lock center_in" v-if="active && lock">
@@ -120,7 +120,7 @@ function deactivated() {
 }
 // 点击激活
 function clickHandler() {
-    active.value = true
+    currentItem.value.active = true
     const arr = {
         index: props.index,
         soleId: props.dargData.soleId,

+ 1 - 1
src/components/maskedbox/iconSize.vue

@@ -6,7 +6,7 @@ const props = defineProps({
         required: true
     },
     iconName: {
-        type: Number,
+        type: String,
         required: true
     },
 })

+ 1 - 1
src/components/maskedbox/literalName.vue

@@ -2,7 +2,7 @@
 import { ref, watch } from "vue";
 const props = defineProps({
     name: {
-        type: Number,
+        type: String,
         required: true
     },
 })

+ 28 - 48
src/components/moduleLibrary.vue

@@ -1,11 +1,11 @@
 <template>
     <div class="card_tree">
-        <el-tree :data="data" node-key="type" :current-node-key="current" :indent="0" default-expand-all highlight-current
-            :props="defaultProps" @node-click="handleNodeClick">
-            <template #default="{ node }">
+        <el-tree :data="libraryData" node-key="id" :current-node-key="current" :indent="0" default-expand-all
+            highlight-current :props="defaultProps" @node-click="handleNodeClick">
+            <template #default="{ node, data }">
                 <span class="custom-tree-node">
                     <span class="title_tree">{{ node.label }}</span>
-                    <el-icon color="#d5d5d9">
+                    <el-icon color="#d5d5d9" v-if="!data.child">
                         <ArrowRight />
                     </el-icon>
                 </span>
@@ -13,59 +13,35 @@
         </el-tree>
     </div>
 </template>
-  
-<script lang="ts" setup>
-defineProps(["current"])
 
+<script lang="ts" setup>
+import { ref, watch } from 'vue'
+const props = defineProps(['componentData', 'current'])
 interface Tree {
-    label: string
-    type: string
-    children?: Tree[]
+    name: string
+    id: string
+    child?: Tree[]
 }
-const data: Tree[] = [
-    {
-        type: '1',
-        label: '基础元素',
-    },
-    {
-        type: '2',
-        label: '布局',
-    },
-    {
-        type: '0',
-        label: '控制',
-        children: [
-            {
-                type: '3',
-                label: '布尔',
-            },
-            {
-                type: '4',
-                label: '数值',
-            },
-            {
-                type: '5',
-                label: '枚举',
-            },
-            {
-                type: '6',
-                label: '通用',
-            },
-        ],
-    },
-]
+const libraryData: any = ref([])
 const defaultProps = {
-    children: 'children',
-    label: 'label',
+    children: 'child',
+    label: 'name'
 }
-
 const emit = defineEmits(["send-data"]);
 const handleNodeClick = (data: Tree) => {
-    const { type } = data;
-    emit("send-data", type);
+    if (!data.child) {
+        const { id } = data;
+        emit("send-data", id);
+    }
 }
+watch(() => props.componentData, (newValue) => {
+    if (newValue) {
+        libraryData.value = newValue
+        console.log(libraryData.value, 678)
+    }
+}, { immediate: true, deep: true })
 </script>
- 
+
 <style lang="scss" scoped>
 .custom-tree-node {
     display: flex;
@@ -90,6 +66,10 @@ const handleNodeClick = (data: Tree) => {
     background-color: #e7f1fc !important;
 }
 
+.card_tree :deep(.is-current .title_tree) {
+    color: #0F73E6 !important;
+}
+
 .title_tree {
     font-size: 12px;
     flex: 1 1 0%;

+ 6 - 3
src/components/widgets/Icon.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="center_in"
+  <div class="center_in icon_overflow"
     :style="{ width: btndata.css.width + 'px', height: btndata.css.height + 'px', backgroundColor: btndata.css.backgroundColor, borderRadius: btndata.css.borderRadius + 'px', }">
     <div class="icon_card_btn" :style="{ width: btndata.css.iconSize + 'px', height: btndata.css.iconSize + 'px', }">
       <el-image class="images_icon"
@@ -14,7 +14,7 @@ import { watch, ref } from "vue";
 const props = defineProps(["config"])
 
 const btndata: any = ref({})
-function getAssetsImages(name) {
+function getAssetsImages(name: any) {
   var arr = '../../assets/iconData/' + name + '.png'
   return new URL(`${arr}`, import.meta.url).href;
 }
@@ -27,11 +27,14 @@ watch(() => props.config, (newValue) => {
 </script>
 
 <style lang="scss" scoped>
+.icon_overflow {
+  overflow: hidden;
+}
+
 .card_btn {
   flex-direction: column;
   background-color: #fff;
   border-radius: 8px;
-  overflow: hidden;
 }
 
 .bg_item_btn {

+ 0 - 1
src/components/widgets/Switch.vue

@@ -17,7 +17,6 @@ watch(() => props.config, (newValue) => {
   if (newValue) {
     width.value = newValue.css.width
     height.value = newValue.css.height
-    console.log(newValue, 2556)
     activeColor.value = newValue.css.colorOpen
     inactiveColor.value = newValue.css.colorClose
   }

+ 2 - 1
src/components/widgets/Text.vue

@@ -1,7 +1,8 @@
 <template>
   <div :class="configData.config.lineNum != null ? 'text_word' : ''"
     :style="{ width: configData.css.width + 'px', height: configData.css.height + 'px', fontSize: configData.css.fontSize + 'px', fontWeight: configData.css.fontWeight, textAlign: configData.css.textAlign, }">
-    {{ configData.name }}</div>
+    {{ configData.name }}
+  </div>
 </template>
 
 <script setup lang="ts">

+ 22 - 0
src/module/classification.ts

@@ -0,0 +1,22 @@
+const classify = [{
+    id: 1, name: "基础元素", parentId: 0,
+}, {
+    id: 2, name: "布局", parentId: 0,
+}, {
+    id: 3, name: "控制", parentId: 0,
+    child: [{
+        id: 4, name: "布尔", parentId: 3,
+    }, {
+        id: 5, name: "数值", parentId: 3,
+    }, {
+        id: 6, name: "枚举", parentId: 3,
+    }, {
+        id: 7, name: "通用", parentId: 3,
+    }]
+}, {
+    id: 4, name: "系统", parentId: 0,
+    child: [{
+        id: 8, name: "日志", parentId: 4,
+    }]
+}]
+export { classify };

+ 50 - 5
src/module/index.ts

@@ -8,27 +8,72 @@ import { sceneConfig, sceneCss } from "./config/sceneButton";
 import { configList1, cssList1 } from "./config/input";
 
 const baseComponent = [{
-    id: 5, type: 'Text', name: "文字", active: false,
+    id: 1, type: 'Text', name: "文字", active: false,
     displayPicture: true,
     config: TextConfig,
     css: TextCss,
 }, {
-    id: 6, type: 'Switch', name: "开关", active: false,
+    id: 2, type: 'Switch', name: "开关", active: false,
     displayPicture: true,
     config: switchConfig,
     css: switchCss,
 }, {
-    id: 7, type: 'Button', name: "按钮", active: false,
+    id: 3, type: 'Switch1', name: "开关-1", active: false,
+    displayPicture: true,
+    config: switchConfig,
+    css: switchCss,
+}, {
+    id: 4, type: 'Switch2', name: "开关-2", active: false,
+    displayPicture: true,
+    config: switchConfig,
+    css: switchCss,
+}, {
+    id: 5, type: 'Switch3', name: "开关-3", active: false,
+    displayPicture: true,
+    config: switchConfig,
+    css: switchCss,
+}, {
+    id: 6, type: 'Button', name: "按钮", active: false,
     displayPicture: true,
     config: btnConfig,
     css: btnCss,
 }, {
-    id: 8, type: 'Icon', name: "图标", active: false,
+    id: 7, type: 'Icon', name: "图标", active: false,
     displayPicture: true,
     config: iconConfig,
     css: iconCss,
 }, {
-    id: 9, type: 'Picture', name: "图片", active: false,
+    id: 8, type: 'Picture', name: "图片", active: false,
+    displayPicture: true,
+    config: pictureConfig,
+    css: pictureCss,
+}, {
+    id: 9, type: 'slide1', name: "滑动条-1", active: false,
+    displayPicture: true,
+    config: pictureConfig,
+    css: pictureCss,
+}, {
+    id: 10, type: 'slide2', name: "滑动条-2", active: false,
+    displayPicture: true,
+    config: pictureConfig,
+    css: pictureCss,
+}, {
+    id: 11, type: 'slide3', name: "滑动条-3", active: false,
+    displayPicture: true,
+    config: pictureConfig,
+    css: pictureCss,
+}, {
+    id: 12, type: 'Vertical1', name: "竖滑条-1", active: false,
+    displayPicture: true,
+    config: pictureConfig,
+    css: pictureCss,
+}, {
+    id: 13, type: 'Vertical2', name: "竖滑条-2", active: false,
+    displayPicture: true,
+    config: pictureConfig,
+    css: pictureCss,
+}, {
+    id: 14, type: 'Vertical3', name: "竖滑条-3", active: false,
     displayPicture: true,
     config: pictureConfig,
     css: pictureCss,

+ 90 - 0
src/utils/storage.ts

@@ -0,0 +1,90 @@
+/**
+ * window.localStorage 浏览器永久缓存
+ * @method set 设置永久缓存
+ * @method get 获取永久缓存
+ * @method remove 移除永久缓存
+ * @method clear 移除全部永久缓存
+ */
+export const Local = {
+	// 设置永久缓存
+	set(key: string, val: any) {
+		window.localStorage.setItem(key, JSON.stringify(val));
+	},
+	// 获取永久缓存
+	get(key: string) {
+		const json = <string>window.localStorage.getItem(key);
+		// !null为true
+		if (!json) return null;
+		// 这里是防止 在本地直接修改了localStorage的值,不经过上面转换,导致JSON.parse报错
+		return JSON.parse(JSON.stringify(json));
+	},
+	// 移除永久缓存
+	remove(key: string) {
+		window.localStorage.removeItem(key);
+	},
+	// 移除全部永久缓存
+	clear() {
+		window.localStorage.clear();
+	},
+};
+
+/**
+ * window.sessionStorage 浏览器临时缓存
+ * @method set 设置临时缓存
+ * @method get 获取临时缓存
+ * @method remove 移除临时缓存
+ * @method clear 移除全部临时缓存
+ */
+export const Session = {
+	// 设置临时缓存
+	set(key: string, val: any) {
+		window.sessionStorage.setItem(key, JSON.stringify(val));
+	},
+	// 获取临时缓存
+	get(key: string) {
+		const json = <string>window.sessionStorage.getItem(key);
+		if (!json) return null;
+		return JSON.parse(JSON.stringify(json));
+	},
+	// 移除临时缓存
+	remove(key: string) {
+		window.sessionStorage.removeItem(key);
+	},
+	// 移除全部临时缓存
+	clear() {
+		window.sessionStorage.clear();
+	},
+};
+/**
+ * 获取本地的key集合
+ * @method getLocalKey
+ * @param { string }  key - 要获取的key值
+ * @param { object }  type - 从那里获取 localStorage、sessionStorage
+ * @description 传入key值,返回匹配的key,不传返回全部key数组
+ * @returns { string } 返回匹配的key或者全部key数组
+ * @example
+ * > getLocalKey('token') // 返回local token
+ * > getLocalKey('token', localStorage) // 返回local token
+ * > getLocalKey('token', sessionStorage) // 返回session token
+ * > getLocalKey() // 返回localStorage全部key数组
+ * > getLocalKey(undefined, sessionStorage) // 返回sessionStorage全部key数组
+ * @author zk
+ * @createDate 2023/08/17 13:58:19
+ * @lastFixDate 2023/08/17 13:58:19
+ */
+export const getLocalKey = (
+	key?: string,
+	type: object = localStorage
+): string[] | string | undefined => {
+	const keys = Object.keys(type);
+	if (!key) return keys;
+	if (keys.length > 0) {
+		for (let i = 0; i < keys.length; i++) {
+			const item = keys[i];
+			if (item.indexOf(key) > -1) {
+				return item;
+			}
+		}
+	}
+	return void 0;
+};

+ 95 - 9
src/views/HomeView.vue

@@ -50,7 +50,7 @@
     </div>
     <div class="part">
       <!-- 左侧 -->
-      <div class="panel_left">
+      <div class="panel_left" v-loading="leftLoading">
         <!-- <div class="left_tabs_switch">
           <div class="card_tabs_view center_in" :class="tabsType == 'module' ? 'tabs_active' : ''"
             @click="getTabs('module')">
@@ -70,7 +70,8 @@
                 <div>214</div>
               </el-tab-pane>
               <el-tab-pane label="组件库" name="bank">
-                <module-library :current="current" @send-data="handleReceivedData"></module-library>
+                <module-library :componentData="componentGallery" :current="current"
+                  @send-data="handleReceivedData"></module-library>
               </el-tab-pane>
             </el-tabs>
           </div>
@@ -99,7 +100,7 @@
       <!-- 中间 -->
       <div class="panel_center">
         <div class="head_page_view">
-          <additionPage @switchPage="switchPage"></additionPage>
+          <additionPage @switchPage="switchPage" @addSwitchPage="switchPage"></additionPage>
         </div>
         <div class="card_selectSize" :style="{ width: (viewName == '卡片' ? cardWidth + 'px' : '375px') }">
           <div style="display: flex;" v-if="viewName == '卡片'">
@@ -200,6 +201,7 @@
 </template>
 
 <script lang="ts" setup>
+// import { getOutPatientsApi } from "../api/classify"
 import { DraggableContainer } from 'vue3-draggable-resizable'
 import Draggable from "vuedraggable";
 import moduleLibrary from "../components/moduleLibrary.vue";
@@ -209,19 +211,22 @@ import iconLibrary from '../components/iconLibrary.vue'
 import maskedbox from './maskedbox.vue'
 import additionPage from './additionPage.vue'
 import { baseComponent, attributeValue, layout } from '../module/index';
-import { ref, computed } from "vue";
+import { classify } from '../module/classification';
+import { ref, watch, computed } from "vue";
 import { useRouter } from 'vue-router'
 import { ElMessageBox, ClickOutside as vClickOutside } from 'element-plus'
 // 存储
 import { useUserStore, moduleStore } from '../stores/index'
 import { storeToRefs } from 'pinia';
+// 组件库分类数据
+const componentGallery = ref(classify)
+const leftLoading = ref(false)
 const storeUser = useUserStore()
 const { viewList } = storeToRefs(storeUser)
 // 组件存储数据
 const storeModule = moduleStore()
 const { moduleList } = storeToRefs(storeModule)
 const listmodule: any = ref(moduleList)
-
 //module、page、切换组件页面
 const tabsType = ref('module')
 // 图标弹窗
@@ -229,12 +234,15 @@ const drawer = ref(false)
 // const tabPosition = ref<string>('style');
 const activeName = ref<string>('bank');
 // 默认选择组件库
-const current = ref<string>('1');
+const current = ref<Number>(0);
+current.value = componentGallery.value[0].id
 const imageUrl = new URL('@/assets/images/head.png', import.meta.url).href;
 // 组件库
 const extraImgs: any = ref(baseComponent);
 const componentLibrary: any = ref([])
 componentLibrary.value = JSON.parse(JSON.stringify(extraImgs.value))
+// console.log(componentLibrary.value, 5654);
+
 // 视图库
 const extraImgs1: any = ref([]);
 const viewName: any = ref('')
@@ -427,7 +435,6 @@ const onEnd = (value) => {
     redoStack.value = [];
   } else {
     cloneItem.value = {}
-    extraImgs1.value.splice(value.newIndex, 1)
   }
 };
 
@@ -445,12 +452,15 @@ const getWidget = (name: string) => {
 }
 // 组件库选择
 const handleReceivedData = (num: any) => {
+  console.log(num, 'zujianxuanzhe')
   extraImgs.value = []
   if (num == 1) {
     extraImgs.value = baseComponent
   } else if (num == 2) {
     extraImgs.value = attributeValue
-  } else if (num == 3) {
+  } else if (num == 4) {
+    extraImgs.value = layout
+  } else if (num == 5) {
     extraImgs.value = layout
   }
   componentLibrary.value = JSON.parse(JSON.stringify(extraImgs.value))
@@ -558,6 +568,9 @@ function clickHandler(params: any) {
 // 失去活跃状态
 function inactivation(params: any) {
   if (currentMove.value.soleId == params.soleId) {
+    extraImgs1.value.forEach((item) => {
+      item.active = false
+    })
     currentMove.value = {}
   }
 }
@@ -638,6 +651,22 @@ function getIconSelection(params: any) {
   drawer.value = false
   currentMove.value.config.img = params.icon
 }
+// onMounted(() => {
+//   getPatientsList();
+// });
+// // 获取分类列表
+// const getPatientsList = () => {
+//   leftLoading.value = true
+//   getOutPatientsApi({}).then((res: any) => {
+//     if (res.code == 200) {
+//       componentGallery.value = res.data
+//       current.value = res.data[0].ID
+//     }
+//     leftLoading.value = false
+//   }).catch(() => {
+//     leftLoading.value = false
+//   })
+// }
 </script>
 
 <style lang="scss">
@@ -1000,9 +1029,66 @@ function getIconSelection(params: any) {
   user-select: none;
 }
 
+@mixin scrollbar() {
+  &::-webkit-scrollbar {
+    width: 2px;
+    background-color: rgba(0, 0, 0, 0);
+    box-shadow: none;
+  }
+
+  /* Track:轨道 */
+  &::-webkit-scrollbar-track {
+    background: rgba(0, 0, 0, 0);
+    box-shadow: none;
+  }
+
+  /* Handle */
+  &::-webkit-scrollbar-thumb {
+    border-radius: 2px;
+    background: rgba(0, 0, 0, 0);
+    box-shadow: none;
+  }
+
+  /* Handle on hover */
+  &::-webkit-scrollbar-thumb:hover {
+    background: rgba(0, 0, 0, 0);
+    box-shadow: none;
+  }
+}
+
+@mixin scrollbar_hover() {
+
+  /* width */
+  &::-webkit-scrollbar {
+    width: 2px;
+  }
+
+  /* Track:轨道 */
+  &::-webkit-scrollbar-track {
+    background: rgba(0, 0, 0, 0);
+    box-shadow: none;
+  }
+
+  /* Handle */
+  &::-webkit-scrollbar-thumb {
+    border-radius: 2px;
+    background: #D3D2D6;
+  }
+
+  /* Handle on hover */
+  &::-webkit-scrollbar-thumb:hover {
+    background: gray;
+  }
+}
+
 .Bzu {
   position: relative;
-  overflow: hidden;
+  overflow: hidden auto;
+  @include scrollbar();
+}
+
+.Bzu:hover {
+  @include scrollbar_hover();
 }
 
 .Bzu .ghost {

+ 4 - 4
src/views/TestDrag.vue

@@ -1,18 +1,18 @@
 <template>
     <div style="display: flex;">
         <div class="left">
-            <!-- <DraggableContainer>
+            <DraggableContainer>
                 <div v-for="(element, index) in extraImgs" :key="index">
                     <VueDrag class="draggable" :dargData="element"></VueDrag>
                 </div>
-            </DraggableContainer> -->
+            </DraggableContainer>
             <DraggableContainer>
                 <Vue3DraggableResizable draggable :lock-aspect-ratio="true" @activated="activated"
                     @deactivated="deactivated">
                     <div style="width: 200px;height: 200px;background-color: #fff;">2151</div>
                 </Vue3DraggableResizable>
-                <div style="width: 600px;height: 600px;" id="parent">
-                    <Vue3DraggableResizable parent="#parent" draggable @activated="activated" @deactivated="deactivated">
+                <div style="width: 600px;height: 600px;" id="parent"> //parent="#parent"
+                    <Vue3DraggableResizable  draggable @activated="activated" @deactivated="deactivated">
                         <div style="width: 200px;height: 200px;background-color: #fff;">Another test</div>
                     </Vue3DraggableResizable>
                 </div>

+ 12 - 3
src/views/additionPage.vue

@@ -32,8 +32,9 @@
                                     :class="item.icon" v-if="item.icon"></span>
                                 <span>{{ item.name }}</span>
                             </div>
-                            <input v-if="editIndex === index && item.inputFlag" :ref="setInputRef" class="title_input_edit"
-                                v-model="item.name" type="text" @input="handleInput" @blur="handleBlur">
+                            <input v-if="editIndex === index && item.inputFlag" :ref="setInputRef"
+                                class="title_input_edit" v-model="item.name" type="text" @input="handleInput"
+                                @blur="handleBlur">
                         </div>
                     </template>
                 </el-popover>
@@ -55,7 +56,7 @@ import { storeToRefs } from 'pinia';
 const storeUser = useUserStore()
 const { viewList } = storeToRefs(storeUser)
 
-const emit = defineEmits(['switchPage']);
+const emit = defineEmits(['switchPage', 'addSwitchPage']);
 const listTabs = ref(viewList)
 function getTabs(params: any) {
     listTabs.value.forEach(item => {
@@ -121,6 +122,7 @@ function editTitle(params: any) {
 // 右键删除页面
 function deletePage(params: any) {
     const index = listTabs.value.findIndex(item => item.id === params.id);
+    console.log(params, index, 25);
     if (index !== -1) {
         listTabs.value[index].visible = false;
         listTabs.value[index].inputFlag = false;
@@ -135,6 +137,10 @@ function deletePage(params: any) {
         }
     ).then(() => {
         listTabs.value = listTabs.value.filter(item => item.id !== params.id);
+        if (params.flag) {
+            listTabs.value[index - 1].flag = true
+            emit('switchPage');
+        }
     }).catch((err) => {
         console.log(err);
     })
@@ -164,6 +170,7 @@ function addPage() {
         viewData: [],
     }
     listTabs.value.push(arrList)
+    emit('addSwitchPage');
 }
 
 
@@ -228,6 +235,7 @@ const handleClickOutside = (event: MouseEvent) => {
     flex-shrink: 0;
     background-color: #fff;
     border-radius: 5px;
+    // border: 1px solid #ffffff;
 }
 
 .card_add_page_title {
@@ -311,6 +319,7 @@ const handleClickOutside = (event: MouseEvent) => {
 .active_card_page {
     color: #409EFF;
     background: rgba(15, 115, 230, 0.08);
+    border: 1px solid #409EFF;
 }
 
 .edit_card_page {

+ 116 - 11
src/views/dimensionsView.vue

@@ -1,6 +1,7 @@
 <template>
     <div class="card_dimensions">
-        <div class="card_module" :style="{ width: previewWidth + 'px', height: previewHeight + 'px', }">
+        <div class="card_module"
+            :style="{ width: previewWidth + 'px', height: previewHeight + 'px', marginTop: clientFlag ? '' : '5vh', }">
             <component class="absolute" :style="getStyle(item)" v-for="(item, index) in listmodule" :key="index"
                 :is="getWidget(item.type)" :config="item">
             </component>
@@ -10,19 +11,66 @@
 
 <script lang="ts" setup>
 import getName from '../components/widgets/getWidget';
-
-import { ref, onMounted } from "vue";
+import { ref, onMounted, computed } from "vue";
 import { moduleStore } from '../stores/index'
 import { storeToRefs } from 'pinia';
 const storeModule = moduleStore()
 const { moduleList } = storeToRefs(storeModule)
 const listmodule: any = ref(moduleList)
-console.log(listmodule.value, 265);
+const clientFlag = ref(false)
+// console.log(listmodule.value, 265);
+const previewWidth = computed(() => {
+    let inwidth = 0
+    if (window.innerWidth < 450) {
+        clientFlag.value = true
+        inwidth = window.innerWidth
+    } else {
+        clientFlag.value = false
+        inwidth = 375
+    }
+    return inwidth
+});
+const previewHeight = computed(() => {
+    let inHeight = 0
+    if (window.innerWidth < 450) {
+        clientFlag.value = true
+        inHeight = window.innerHeight
+    } else {
+        clientFlag.value = false
+        inHeight = 603
+    }
+    return inHeight
+});
 
-const previewWidth: any = ref(420)
-const previewHeight: any = ref(844)
+// * 默认缩放值
+const scale: any = ref({
+    width: '1',
+    height: '1'
+})
+// * 设计稿尺寸(px)
+const baseWidth = 375
+const baseHeight = 603
+const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
+// 重新设置缩放比例值
+const calcRate = () => {
+    // 当前视口的宽高比例
+    const currentRate = parseFloat((window.innerWidth / window.innerHeight).toFixed(5))
+    // 获取到的当前实例
+    if (currentRate > baseProportion) {
+        // 表示更宽
+        scale.value.width = ((window.innerHeight * baseProportion) / baseWidth).toFixed(5)
+        scale.value.height = (window.innerHeight / baseHeight).toFixed(5)
+    } else {
+        // 表示更高
+        scale.value.height = ((window.innerWidth / baseProportion) / baseHeight).toFixed(5)
+        scale.value.width = (window.innerWidth / baseWidth).toFixed(5)
+    }
+}
 onMounted(() => {
     document.title = '页面预览'
+    if (window.innerWidth < 450) {
+        calcRate()
+    }
 })
 
 const getWidget = (name: string) => {
@@ -32,10 +80,10 @@ const getWidget = (name: string) => {
 const getStyle = (event: any) => {
     //组件名映射
     return {
-        left: (event.css.left / 375) * previewWidth.value + 'px',
-        top: (event.css.top / 603) * previewHeight.value + 'px',
-        width: (event.css.width / 375) * previewWidth.value + 'px',
-        height: (event.css.height / 603) * previewHeight.value + 'px',
+        left: event.css.left * Number(scale.value.width) + 'px',
+        top: event.css.top * Number(scale.value.width) + 'px',
+        width: event.css.width * Number(scale.value.width) + 'px',
+        height: event.css.height * Number(scale.value.width) + 'px',
     }
 }
 </script>
@@ -49,10 +97,67 @@ const getStyle = (event: any) => {
     background-color: #f4f4f4;
 }
 
+@mixin scrollbar() {
+    &::-webkit-scrollbar {
+        width: 2px;
+        background-color: rgba(0, 0, 0, 0);
+        box-shadow: none;
+    }
+
+    /* Track:轨道 */
+    &::-webkit-scrollbar-track {
+        background: rgba(0, 0, 0, 0);
+        box-shadow: none;
+    }
+
+    /* Handle */
+    &::-webkit-scrollbar-thumb {
+        border-radius: 2px;
+        background: rgba(0, 0, 0, 0);
+        box-shadow: none;
+    }
+
+    /* Handle on hover */
+    &::-webkit-scrollbar-thumb:hover {
+        background: rgba(0, 0, 0, 0);
+        box-shadow: none;
+    }
+}
+
+@mixin scrollbar_hover() {
+
+    /* width */
+    &::-webkit-scrollbar {
+        width: 2px;
+    }
+
+    /* Track:轨道 */
+    &::-webkit-scrollbar-track {
+        background: rgba(0, 0, 0, 0);
+        box-shadow: none;
+    }
+
+    /* Handle */
+    &::-webkit-scrollbar-thumb {
+        border-radius: 2px;
+        background: #D3D2D6;
+    }
+
+    /* Handle on hover */
+    &::-webkit-scrollbar-thumb:hover {
+        background: gray;
+    }
+}
+
 .card_module {
     position: relative;
-    margin-top: 20px;
     background-color: #fff;
+    overflow: hidden auto;
+    @include scrollbar();
+}
+
+.card_module:hover {
+    @include scrollbar_hover();
 }
 
 .absolute {

+ 29 - 9
vite.config.ts

@@ -6,18 +6,38 @@ export default defineConfig({
   plugins: [vue()],
   //解决“vite use `--host` to expose”
   base: './',
-  server: {             
-    host: '0.0.0.0',	
-    // port: 8080,      
-    open: true
+  server: {
+    proxy: {
+      '/api': {
+        target: 'http://192.168.11.77:8888',
+        changeOrigin: true,
+        rewrite: (path) => {
+          return path.replace(/\/api/, '/api')
+        }
+      },
+      '/app': {
+        target: 'http://192.168.11.77:8080',
+        changeOrigin: true,
+        rewrite: (path) => {
+          return path.replace(/\/app/, '/api')
+        }
+      }
+    }
   },
-  resolve:{   
+  resolve: {
     //别名配置,引用src路径下的东西可以通过@如:import Layout from '@/layout/index.vue'
-    alias:[   
+    alias: [
       {
-        find:'@',
-        replacement:resolve(__dirname,'src') 
+        find: '@',
+        replacement: resolve(__dirname, 'src')
       }
     ]
-  }
+  },
+  css: {
+    preprocessorOptions: {
+      scss: {
+        api: 'modern-compiler'
+      }
+    },
+  },
 })