From 2c8b74ea8ac525434cf338c2dac92ed1faf009ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E9=B9=8F?= Date: Sat, 23 May 2026 11:31:38 +0800 Subject: [PATCH] Expand EasyCode front workbench features --- RuoYi-Vue/easycode-web/.env.development | 1 + RuoYi-Vue/easycode-web/.env.production | 1 + RuoYi-Vue/easycode-web/package-lock.json | 1177 ++++++++--------- RuoYi-Vue/easycode-web/src/api/project.js | 36 +- RuoYi-Vue/easycode-web/src/api/request.js | 3 +- RuoYi-Vue/easycode-web/src/api/source.js | 45 + .../easycode-web/src/api/sourceAdapter.js | 82 ++ .../src/api/sourceAdapter.test.mjs | 46 + RuoYi-Vue/easycode-web/src/api/timeouts.js | 9 + .../easycode-web/src/components/AppHeader.vue | 2 + .../src/components/DatabaseDesigner.vue | 7 +- .../src/components/ErDiagramView.vue | 514 +++++++ .../easycode-web/src/data/sourceProjects.js | 217 +++ .../src/data/sourceProjects.test.mjs | 46 + RuoYi-Vue/easycode-web/src/router/index.js | 6 + RuoYi-Vue/easycode-web/src/utils/download.js | 17 + RuoYi-Vue/easycode-web/src/utils/erExport.js | 92 ++ .../easycode-web/src/utils/erExport.test.mjs | 41 + RuoYi-Vue/easycode-web/src/utils/erGraph.js | 154 +++ .../easycode-web/src/utils/erGraph.test.mjs | 95 ++ RuoYi-Vue/easycode-web/src/utils/markdown.js | 148 +++ .../easycode-web/src/utils/markdown.test.mjs | 22 + .../easycode-web/src/views/GenerateView.vue | 134 +- RuoYi-Vue/easycode-web/src/views/HomeView.vue | 3 +- .../easycode-web/src/views/PreviewView.vue | 24 +- .../src/views/ProjectListView.vue | 225 ++++ .../src/views/SourceDetailView.vue | 403 ++++++ .../src/views/SourceStoreView.vue | 345 +++++ .../src/views/sourceStoreLayout.test.mjs | 56 + .../front/FrontProjectController.java | 7 +- .../front/FrontSourceController.java | 92 ++ .../src/main/resources/application.yml | 7 +- .../front/FrontSourceControllerTest.java | 55 + .../framework/config/SecurityConfig.java | 1 + .../generator/config/DeepSeekProperties.java | 6 +- .../controller/SourceProjectController.java | 88 ++ .../controller/SourcePurchaseController.java | 63 + .../ruoyi/generator/domain/SourceProject.java | 100 ++ .../generator/domain/SourcePurchase.java | 50 + .../generator/domain/front/FrontProject.java | 3 + .../front/dto/DatabaseDesignResponse.java | 3 + .../domain/source/SourceProjectResponse.java | 57 + .../domain/source/SourcePurchaseResponse.java | 35 + .../generator/mapper/SourceProjectMapper.java | 25 + .../mapper/SourcePurchaseMapper.java | 20 + .../service/ISourceProjectService.java | 33 + .../service/ISourcePurchaseService.java | 13 + .../service/SourceProjectServiceImpl.java | 333 +++++ .../service/SourcePurchaseServiceImpl.java | 34 + .../service/front/AiGenerateServiceImpl.java | 396 +++++- .../front/FrontProjectPreviewServiceImpl.java | 79 ++ .../front/FrontProjectServiceImpl.java | 48 +- .../service/front/HttpDeepSeekClient.java | 97 +- .../front/IFrontProjectPreviewService.java | 2 + .../mapper/front/FrontProjectMapper.xml | 6 +- .../mapper/generator/SourceProjectMapper.xml | 189 +++ .../mapper/generator/SourcePurchaseMapper.xml | 107 ++ .../service/SourceProjectServiceImplTest.java | 150 +++ .../front/AiGenerateServiceImplTest.java | 218 +++ .../FrontProjectPreviewServiceImplTest.java | 55 + .../front/FrontProjectServiceImplTest.java | 23 + .../service/front/HttpDeepSeekClientTest.java | 69 + .../src/api/generator/sourceProject.js | 47 + .../src/api/generator/sourcePurchase.js | 24 + .../views/generator/sourceProject/index.vue | 360 +++++ .../views/generator/sourcePurchase/index.vue | 194 +++ RuoYi-Vue/sql/db.sql | 101 ++ RuoYi-Vue/sql/front_er_diagram.sql | 3 + RuoYi-Vue/sql/front_workbench.sql | 1 + RuoYi-Vue/sql/source_store.sql | 89 ++ 70 files changed, 6596 insertions(+), 638 deletions(-) create mode 100644 RuoYi-Vue/easycode-web/src/api/source.js create mode 100644 RuoYi-Vue/easycode-web/src/api/sourceAdapter.js create mode 100644 RuoYi-Vue/easycode-web/src/api/sourceAdapter.test.mjs create mode 100644 RuoYi-Vue/easycode-web/src/api/timeouts.js create mode 100644 RuoYi-Vue/easycode-web/src/components/ErDiagramView.vue create mode 100644 RuoYi-Vue/easycode-web/src/data/sourceProjects.js create mode 100644 RuoYi-Vue/easycode-web/src/data/sourceProjects.test.mjs create mode 100644 RuoYi-Vue/easycode-web/src/utils/download.js create mode 100644 RuoYi-Vue/easycode-web/src/utils/erExport.js create mode 100644 RuoYi-Vue/easycode-web/src/utils/erExport.test.mjs create mode 100644 RuoYi-Vue/easycode-web/src/utils/erGraph.js create mode 100644 RuoYi-Vue/easycode-web/src/utils/erGraph.test.mjs create mode 100644 RuoYi-Vue/easycode-web/src/utils/markdown.js create mode 100644 RuoYi-Vue/easycode-web/src/utils/markdown.test.mjs create mode 100644 RuoYi-Vue/easycode-web/src/views/ProjectListView.vue create mode 100644 RuoYi-Vue/easycode-web/src/views/SourceDetailView.vue create mode 100644 RuoYi-Vue/easycode-web/src/views/SourceStoreView.vue create mode 100644 RuoYi-Vue/easycode-web/src/views/sourceStoreLayout.test.mjs create mode 100644 RuoYi-Vue/ruoyi-admin/src/main/java/com/ruoyi/web/controller/front/FrontSourceController.java create mode 100644 RuoYi-Vue/ruoyi-admin/src/test/java/com/ruoyi/web/controller/front/FrontSourceControllerTest.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/SourceProjectController.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/SourcePurchaseController.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/SourceProject.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/SourcePurchase.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/source/SourceProjectResponse.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/source/SourcePurchaseResponse.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/SourceProjectMapper.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/SourcePurchaseMapper.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/service/ISourceProjectService.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/service/ISourcePurchaseService.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/service/SourceProjectServiceImpl.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/java/com/ruoyi/generator/service/SourcePurchaseServiceImpl.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/resources/mapper/generator/SourceProjectMapper.xml create mode 100644 RuoYi-Vue/ruoyi-generator/src/main/resources/mapper/generator/SourcePurchaseMapper.xml create mode 100644 RuoYi-Vue/ruoyi-generator/src/test/java/com/ruoyi/generator/service/SourceProjectServiceImplTest.java create mode 100644 RuoYi-Vue/ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/HttpDeepSeekClientTest.java create mode 100644 RuoYi-Vue/ruoyi-ui/src/api/generator/sourceProject.js create mode 100644 RuoYi-Vue/ruoyi-ui/src/api/generator/sourcePurchase.js create mode 100644 RuoYi-Vue/ruoyi-ui/src/views/generator/sourceProject/index.vue create mode 100644 RuoYi-Vue/ruoyi-ui/src/views/generator/sourcePurchase/index.vue create mode 100644 RuoYi-Vue/sql/front_er_diagram.sql create mode 100644 RuoYi-Vue/sql/source_store.sql diff --git a/RuoYi-Vue/easycode-web/.env.development b/RuoYi-Vue/easycode-web/.env.development index a8cf54a..8a557dc 100644 --- a/RuoYi-Vue/easycode-web/.env.development +++ b/RuoYi-Vue/easycode-web/.env.development @@ -1 +1,2 @@ VITE_API_BASE_URL=http://localhost:8080 +VITE_GENERATE_TIMEOUT=180000 diff --git a/RuoYi-Vue/easycode-web/.env.production b/RuoYi-Vue/easycode-web/.env.production index a95f7a2..297977c 100644 --- a/RuoYi-Vue/easycode-web/.env.production +++ b/RuoYi-Vue/easycode-web/.env.production @@ -1 +1,2 @@ VITE_API_BASE_URL=/front +VITE_GENERATE_TIMEOUT=180000 diff --git a/RuoYi-Vue/easycode-web/package-lock.json b/RuoYi-Vue/easycode-web/package-lock.json index 1c7e1be..3c093e2 100644 --- a/RuoYi-Vue/easycode-web/package-lock.json +++ b/RuoYi-Vue/easycode-web/package-lock.json @@ -1,281 +1,87 @@ { "name": "easycode-web", "version": "1.0.0", - "lockfileVersion": 3, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "easycode-web", - "version": "1.0.0", - "dependencies": { - "@element-plus/icons-vue": "^2.3.1", - "axios": "^1.7.9", - "element-plus": "^2.9.1", - "vue": "^3.5.13", - "vue-router": "^4.5.0" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^5.2.1", - "sass": "^1.83.0", - "vite": "^6.0.7" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@babel/helper-string-parser": { + "dependencies": { + "@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==" }, - "node_modules/@babel/helper-validator-identifier": { + "@babel/helper-validator-identifier": { "version": "7.28.5", "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==" }, - "node_modules/@babel/parser": { + "@babel/parser": { "version": "7.29.3", "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.3.tgz", "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", - "dependencies": { + "requires": { "@babel/types": "^7.29.0" } }, - "node_modules/@babel/types": { + "@babel/types": { "version": "7.29.0", "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz", "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dependencies": { + "requires": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, - "node_modules/@ctrl/tinycolor": { + "@ctrl/tinycolor": { "version": "4.2.0", "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz", "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==" }, - "node_modules/@element-plus/icons-vue": { + "@element-plus/icons-vue": { "version": "2.3.2", "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz", "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==" }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "dev": true, - "optional": true - }, - "node_modules/@esbuild/win32-x64": { + "@esbuild/win32-x64": { "version": "0.25.12", "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", "dev": true, "optional": true }, - "node_modules/@floating-ui/core": { + "@floating-ui/core": { "version": "1.7.5", "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.5.tgz", "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", - "dependencies": { + "requires": { "@floating-ui/utils": "^0.2.11" } }, - "node_modules/@floating-ui/dom": { + "@floating-ui/dom": { "version": "1.7.6", "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.6.tgz", "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", - "dependencies": { + "requires": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, - "node_modules/@floating-ui/utils": { + "@floating-ui/utils": { "version": "0.2.11", "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.11.tgz", "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==" }, - "node_modules/@jridgewell/sourcemap-codec": { + "@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" }, - "node_modules/@parcel/watcher": { + "@parcel/watcher": { "version": "2.5.6", "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.6.tgz", "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", "dev": true, "optional": true, - "dependencies": { + "requires": { "@parcel/watcher-android-arm64": "2.5.6", "@parcel/watcher-darwin-arm64": "2.5.6", "@parcel/watcher-darwin-x64": "2.5.6", @@ -293,315 +99,155 @@ "is-glob": "^4.0.3", "node-addon-api": "^7.0.0", "picomatch": "^4.0.3" + }, + "dependencies": { + "@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "dev": true, + "optional": true + }, + "@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "dev": true, + "optional": true + }, + "@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "dev": true, + "optional": true + }, + "@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "dev": true, + "optional": true + }, + "@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "dev": true, + "optional": true + }, + "@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "dev": true, + "optional": true + }, + "@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "dev": true, + "optional": true + }, + "@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "dev": true, + "optional": true + }, + "@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "dev": true, + "optional": true + }, + "@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "dev": true, + "optional": true + }, + "@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "dev": true, + "optional": true + }, + "@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "dev": true, + "optional": true + } } }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", - "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", - "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", - "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", - "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", - "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", - "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", - "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", - "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", - "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", - "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", - "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", - "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher-win32-x64": { + "@parcel/watcher-win32-x64": { "version": "2.5.6", "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", "dev": true, "optional": true }, - "node_modules/@popperjs/core": { - "name": "@sxzz/popperjs-es", - "version": "2.11.8", + "@popperjs/core": { + "version": "npm:@sxzz/popperjs-es@2.11.8", "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz", "integrity": "sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==" }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", - "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz", - "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz", - "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz", - "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz", - "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz", - "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz", - "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz", - "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz", - "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz", - "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz", - "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz", - "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz", - "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz", - "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz", - "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz", - "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz", - "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", - "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz", - "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz", - "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz", - "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz", - "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz", - "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { + "@rollup/rollup-win32-x64-gnu": { "version": "4.60.4", "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz", "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==", "dev": true, "optional": true }, - "node_modules/@rollup/rollup-win32-x64-msvc": { + "@rollup/rollup-win32-x64-msvc": { "version": "4.60.4", "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz", "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==", "dev": true, "optional": true }, - "node_modules/@types/estree": { + "@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true }, - "node_modules/@types/lodash": { + "@types/lodash": { "version": "4.17.24", "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.24.tgz", "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==" }, - "node_modules/@types/lodash-es": { + "@types/lodash-es": { "version": "4.17.12", "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz", "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", - "dependencies": { + "requires": { "@types/lodash": "*" } }, - "node_modules/@types/web-bluetooth": { + "@types/web-bluetooth": { "version": "0.0.21", "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==" }, - "node_modules/@vitejs/plugin-vue": { + "@vitejs/plugin-vue": { "version": "5.2.4", "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", "dev": true }, - "node_modules/@vue/compiler-core": { + "@vue/compiler-core": { "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.34.tgz", "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==", - "dependencies": { + "requires": { "@babel/parser": "^7.29.3", "@vue/shared": "3.5.34", "entities": "^7.0.1", @@ -609,20 +255,20 @@ "source-map-js": "^1.2.1" } }, - "node_modules/@vue/compiler-dom": { + "@vue/compiler-dom": { "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz", "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==", - "dependencies": { + "requires": { "@vue/compiler-core": "3.5.34", "@vue/shared": "3.5.34" } }, - "node_modules/@vue/compiler-sfc": { + "@vue/compiler-sfc": { "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz", "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==", - "dependencies": { + "requires": { "@babel/parser": "^7.29.3", "@vue/compiler-core": "3.5.34", "@vue/compiler-dom": "3.5.34", @@ -634,182 +280,182 @@ "source-map-js": "^1.2.1" } }, - "node_modules/@vue/compiler-ssr": { + "@vue/compiler-ssr": { "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz", "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==", - "dependencies": { + "requires": { "@vue/compiler-dom": "3.5.34", "@vue/shared": "3.5.34" } }, - "node_modules/@vue/devtools-api": { + "@vue/devtools-api": { "version": "6.6.4", "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==" }, - "node_modules/@vue/reactivity": { + "@vue/reactivity": { "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.34.tgz", "integrity": "sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==", - "dependencies": { + "requires": { "@vue/shared": "3.5.34" } }, - "node_modules/@vue/runtime-core": { + "@vue/runtime-core": { "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.34.tgz", "integrity": "sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==", - "dependencies": { + "requires": { "@vue/reactivity": "3.5.34", "@vue/shared": "3.5.34" } }, - "node_modules/@vue/runtime-dom": { + "@vue/runtime-dom": { "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.34.tgz", "integrity": "sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==", - "dependencies": { + "requires": { "@vue/reactivity": "3.5.34", "@vue/runtime-core": "3.5.34", "@vue/shared": "3.5.34", "csstype": "^3.2.3" } }, - "node_modules/@vue/server-renderer": { + "@vue/server-renderer": { "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.34.tgz", "integrity": "sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==", - "dependencies": { + "requires": { "@vue/compiler-ssr": "3.5.34", "@vue/shared": "3.5.34" } }, - "node_modules/@vue/shared": { + "@vue/shared": { "version": "3.5.34", "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.34.tgz", "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==" }, - "node_modules/@vueuse/core": { + "@vueuse/core": { "version": "14.3.0", "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-14.3.0.tgz", "integrity": "sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==", - "dependencies": { + "requires": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "14.3.0", "@vueuse/shared": "14.3.0" } }, - "node_modules/@vueuse/metadata": { + "@vueuse/metadata": { "version": "14.3.0", "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-14.3.0.tgz", "integrity": "sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==" }, - "node_modules/@vueuse/shared": { + "@vueuse/shared": { "version": "14.3.0", "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-14.3.0.tgz", "integrity": "sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==" }, - "node_modules/agent-base": { + "agent-base": { "version": "6.0.2", "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { + "requires": { "debug": "4" } }, - "node_modules/async-validator": { + "async-validator": { "version": "4.2.5", "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz", "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" }, - "node_modules/asynckit": { + "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "node_modules/axios": { + "axios": { "version": "1.16.1", "resolved": "https://registry.npmmirror.com/axios/-/axios-1.16.1.tgz", "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==", - "dependencies": { + "requires": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } }, - "node_modules/call-bind-apply-helpers": { + "call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dependencies": { + "requires": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, - "node_modules/chokidar": { + "chokidar": { "version": "5.0.0", "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-5.0.0.tgz", "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "dev": true, - "dependencies": { + "requires": { "readdirp": "^5.0.0" } }, - "node_modules/combined-stream": { + "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { + "requires": { "delayed-stream": "~1.0.0" } }, - "node_modules/csstype": { + "csstype": { "version": "3.2.3", "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==" }, - "node_modules/dayjs": { + "dayjs": { "version": "1.11.20", "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.20.tgz", "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==" }, - "node_modules/debug": { + "debug": { "version": "4.4.3", "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dependencies": { + "requires": { "ms": "^2.1.3" } }, - "node_modules/delayed-stream": { + "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, - "node_modules/detect-libc": { + "detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "optional": true }, - "node_modules/dunder-proto": { + "dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dependencies": { + "requires": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, - "node_modules/element-plus": { + "element-plus": { "version": "2.14.0", "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.14.0.tgz", "integrity": "sha512-POgH+TtoreaEKWqYYAVQyE6i8rQMEFqAEublyF29dBA5yASWPLKY6EzfeqBTr2Uv26mPss4vSrMrNPyaK7LX5w==", - "dependencies": { + "requires": { "@ctrl/tinycolor": "^4.2.0", "@element-plus/icons-vue": "^2.3.2", "@floating-ui/dom": "^1.0.1", @@ -827,46 +473,46 @@ "vue-component-type-helpers": "^3.2.8" } }, - "node_modules/entities": { + "entities": { "version": "7.0.1", "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==" }, - "node_modules/es-define-property": { + "es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" }, - "node_modules/es-errors": { + "es-errors": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" }, - "node_modules/es-object-atoms": { + "es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dependencies": { + "requires": { "es-errors": "^1.3.0" } }, - "node_modules/es-set-tostringtag": { + "es-set-tostringtag": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dependencies": { + "requires": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, - "node_modules/esbuild": { + "esbuild": { "version": "0.25.12", "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz", "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, - "optionalDependencies": { + "requires": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", @@ -893,29 +539,206 @@ "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" + }, + "dependencies": { + "@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "dev": true, + "optional": true + }, + "@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "dev": true, + "optional": true + } } }, - "node_modules/estree-walker": { + "estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, - "node_modules/fdir": { + "fdir": { "version": "6.5.0", "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true }, - "node_modules/follow-redirects": { + "follow-redirects": { "version": "1.16.0", "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.16.0.tgz", "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==" }, - "node_modules/form-data": { + "form-data": { "version": "4.0.5", "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", - "dependencies": { + "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", @@ -923,23 +746,16 @@ "mime-types": "^2.1.12" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "optional": true - }, - "node_modules/function-bind": { + "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, - "node_modules/get-intrinsic": { + "get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dependencies": { + "requires": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", @@ -952,182 +768,179 @@ "math-intrinsics": "^1.1.0" } }, - "node_modules/get-proto": { + "get-proto": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dependencies": { + "requires": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, - "node_modules/gopd": { + "gopd": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" }, - "node_modules/has-symbols": { + "has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" }, - "node_modules/has-tostringtag": { + "has-tostringtag": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dependencies": { + "requires": { "has-symbols": "^1.0.3" } }, - "node_modules/hasown": { + "hasown": { "version": "2.0.3", "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.3.tgz", "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", - "dependencies": { + "requires": { "function-bind": "^1.1.2" } }, - "node_modules/https-proxy-agent": { + "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dependencies": { + "requires": { "agent-base": "6", "debug": "4" } }, - "node_modules/immutable": { + "immutable": { "version": "5.1.5", "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.5.tgz", "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", "dev": true }, - "node_modules/is-extglob": { + "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "optional": true }, - "node_modules/is-glob": { + "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "optional": true, - "dependencies": { + "requires": { "is-extglob": "^2.1.1" } }, - "node_modules/lodash": { + "lodash": { "version": "4.18.1", "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz", "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==" }, - "node_modules/lodash-es": { + "lodash-es": { "version": "4.18.1", "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.18.1.tgz", "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==" }, - "node_modules/lodash-unified": { + "lodash-unified": { "version": "1.0.3", "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz", "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==" }, - "node_modules/magic-string": { + "magic-string": { "version": "0.30.21", "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dependencies": { + "requires": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/math-intrinsics": { + "math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" }, - "node_modules/memoize-one": { + "memoize-one": { "version": "6.0.0", "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" }, - "node_modules/mime-db": { + "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, - "node_modules/mime-types": { + "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { + "requires": { "mime-db": "1.52.0" } }, - "node_modules/ms": { + "ms": { "version": "2.1.3", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "node_modules/nanoid": { + "nanoid": { "version": "3.3.12", "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.12.tgz", "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==" }, - "node_modules/node-addon-api": { + "node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "dev": true, "optional": true }, - "node_modules/normalize-wheel-es": { + "normalize-wheel-es": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==" }, - "node_modules/picocolors": { + "picocolors": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, - "node_modules/picomatch": { + "picomatch": { "version": "4.0.4", "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true }, - "node_modules/postcss": { + "postcss": { "version": "8.5.15", "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.15.tgz", "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", - "dependencies": { + "requires": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, - "node_modules/proxy-from-env": { + "proxy-from-env": { "version": "2.1.0", "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz", "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==" }, - "node_modules/readdirp": { + "readdirp": { "version": "5.0.0", "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-5.0.0.tgz", "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", "dev": true }, - "node_modules/rollup": { + "rollup": { "version": "4.60.4", "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.60.4.tgz", "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", "dev": true, - "dependencies": { - "@types/estree": "1.0.8" - }, - "optionalDependencies": { + "requires": { "@rollup/rollup-android-arm-eabi": "4.60.4", "@rollup/rollup-android-arm64": "4.60.4", "@rollup/rollup-darwin-arm64": "4.60.4", @@ -1153,60 +966,236 @@ "@rollup/rollup-win32-ia32-msvc": "4.60.4", "@rollup/rollup-win32-x64-gnu": "4.60.4", "@rollup/rollup-win32-x64-msvc": "4.60.4", + "@types/estree": "1.0.8", "fsevents": "~2.3.2" + }, + "dependencies": { + "@rollup/rollup-android-arm-eabi": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", + "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-android-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz", + "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-darwin-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz", + "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-darwin-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz", + "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-freebsd-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz", + "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==", + "dev": true, + "optional": true + }, + "@rollup/rollup-freebsd-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz", + "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz", + "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz", + "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz", + "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz", + "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz", + "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-loong64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz", + "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz", + "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz", + "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz", + "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz", + "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz", + "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", + "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz", + "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-openbsd-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz", + "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-openharmony-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz", + "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz", + "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz", + "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==", + "dev": true, + "optional": true + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + } } }, - "node_modules/sass": { + "sass": { "version": "1.100.0", "resolved": "https://registry.npmmirror.com/sass/-/sass-1.100.0.tgz", "integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==", "dev": true, - "dependencies": { + "requires": { + "@parcel/watcher": "^2.4.1", "chokidar": "^5.0.0", "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" } }, - "node_modules/source-map-js": { + "source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" }, - "node_modules/tinyglobby": { + "tinyglobby": { "version": "0.2.16", "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.16.tgz", "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", "dev": true, - "dependencies": { + "requires": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, - "node_modules/vite": { + "vite": { "version": "6.4.2", "resolved": "https://registry.npmmirror.com/vite/-/vite-6.4.2.tgz", "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", "dev": true, - "dependencies": { + "requires": { "esbuild": "^0.25.0", "fdir": "^6.4.4", + "fsevents": "~2.3.3", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, - "optionalDependencies": { - "fsevents": "~2.3.3" + "dependencies": { + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + } } }, - "node_modules/vue": { + "vue": { "version": "3.5.34", "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.34.tgz", "integrity": "sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==", - "dependencies": { + "requires": { "@vue/compiler-dom": "3.5.34", "@vue/compiler-sfc": "3.5.34", "@vue/runtime-dom": "3.5.34", @@ -1214,16 +1203,16 @@ "@vue/shared": "3.5.34" } }, - "node_modules/vue-component-type-helpers": { + "vue-component-type-helpers": { "version": "3.3.1", "resolved": "https://registry.npmmirror.com/vue-component-type-helpers/-/vue-component-type-helpers-3.3.1.tgz", "integrity": "sha512-pu58kqxmVyEH6VfNYW1UyEfR3XAnJ27ZXT3yzXxxpjLxVzAbyC35Zk/nm/RMs7ijWnJNSd9fWkeex2OhUsx3MA==" }, - "node_modules/vue-router": { + "vue-router": { "version": "4.6.4", "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz", "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", - "dependencies": { + "requires": { "@vue/devtools-api": "^6.6.4" } } diff --git a/RuoYi-Vue/easycode-web/src/api/project.js b/RuoYi-Vue/easycode-web/src/api/project.js index 943fd20..030571e 100644 --- a/RuoYi-Vue/easycode-web/src/api/project.js +++ b/RuoYi-Vue/easycode-web/src/api/project.js @@ -1,4 +1,5 @@ import request from './request' +import { GENERATE_REQUEST_TIMEOUT } from './timeouts' function unwrap(res) { return res && Object.prototype.hasOwnProperty.call(res, 'data') ? res.data : res @@ -12,10 +13,32 @@ export function createProject(data) { }).then(unwrap) } +export function listProjects() { + return request({ + url: '/front/project/list', + method: 'get' + }).then(unwrap) +} + +export function getProject(projectId) { + return request({ + url: `/front/project/${projectId}`, + method: 'get' + }).then(unwrap) +} + +export function deleteProject(projectId) { + return request({ + url: `/front/project/${projectId}`, + method: 'delete' + }).then(unwrap) +} + export function generateDatabase(projectId, data) { return request({ url: `/front/project/${projectId}/generate-database`, method: 'post', + timeout: GENERATE_REQUEST_TIMEOUT, data }).then(unwrap) } @@ -38,7 +61,8 @@ export function saveDatabase(projectId, data) { export function generateProject(projectId) { return request({ url: `/front/project/${projectId}/preview`, - method: 'post' + method: 'post', + timeout: GENERATE_REQUEST_TIMEOUT }).then(unwrap) } @@ -57,3 +81,13 @@ export function getFileContent(projectId, params) { params }).then(unwrap) } + +export function downloadProject(projectId, templateType) { + return request({ + url: `/front/project/${projectId}/download`, + method: 'get', + params: templateType ? { templateType } : undefined, + responseType: 'blob', + timeout: GENERATE_REQUEST_TIMEOUT + }).then(unwrap) +} diff --git a/RuoYi-Vue/easycode-web/src/api/request.js b/RuoYi-Vue/easycode-web/src/api/request.js index 7a3d5c8..2a9b32a 100644 --- a/RuoYi-Vue/easycode-web/src/api/request.js +++ b/RuoYi-Vue/easycode-web/src/api/request.js @@ -1,10 +1,11 @@ import axios from 'axios' import { ElMessage } from 'element-plus' import { getToken, removeToken } from '@/utils/auth' +import { DEFAULT_REQUEST_TIMEOUT } from './timeouts' const service = axios.create({ baseURL: '', - timeout: 30000 + timeout: DEFAULT_REQUEST_TIMEOUT }) service.interceptors.request.use((config) => { diff --git a/RuoYi-Vue/easycode-web/src/api/source.js b/RuoYi-Vue/easycode-web/src/api/source.js new file mode 100644 index 0000000..9a46ced --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/api/source.js @@ -0,0 +1,45 @@ +import request from './request' +import { normalizeSourceCategories, normalizeSourceProject, normalizeSourceProjects } from './sourceAdapter' + +export function listSourceCategories() { + return request({ + url: '/front/source/categories', + method: 'get' + }).then((result) => normalizeSourceCategories(result.data)) +} + +export function listSourceProjects(params = {}) { + return request({ + url: '/front/source/projects', + method: 'get', + params + }).then((result) => normalizeSourceProjects(result.data)) +} + +export function getSourceProject(slug) { + return request({ + url: `/front/source/projects/${slug}`, + method: 'get' + }).then((result) => normalizeSourceProject(result.data)) +} + +export function purchaseSourceProject(projectId) { + return request({ + url: `/front/source/projects/${projectId}/purchase`, + method: 'post' + }) +} + +export function listSourcePurchases() { + return request({ + url: '/front/source/purchases', + method: 'get' + }).then((result) => result.data || []) +} + +export function getSourceDownloadInfo(projectId) { + return request({ + url: `/front/source/projects/${projectId}/download`, + method: 'get' + }).then((result) => result.data) +} diff --git a/RuoYi-Vue/easycode-web/src/api/sourceAdapter.js b/RuoYi-Vue/easycode-web/src/api/sourceAdapter.js new file mode 100644 index 0000000..b0ca61a --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/api/sourceAdapter.js @@ -0,0 +1,82 @@ +export function normalizeSourceProject(project = {}) { + return { + projectId: project.projectId, + id: project.slug || String(project.projectId || ''), + name: project.projectName || project.name || '', + category: project.category || '', + coverText: project.coverText || '', + summary: project.summary || '', + descriptionMd: project.descriptionMd || '', + price: project.priceLabel || formatPrice(project.price), + priceValue: Number(project.price || 0), + views: Number(project.viewCount || project.views || 0), + updateTime: normalizeDate(project.updateTime), + tags: normalizeList(project.tags), + modules: normalizeList(project.modules), + scenes: normalizeList(project.scenes), + purchased: Boolean(project.purchased), + resourceReady: Boolean(project.resourceReady) + } +} + +export function normalizeSourceProjects(projects = []) { + return Array.isArray(projects) ? projects.map(normalizeSourceProject) : [] +} + +export function normalizeSourceCategories(categories = []) { + if (!Array.isArray(categories)) return [] + return categories + .map((category) => ({ + value: category.value || category.dictValue || '', + label: category.label || category.dictLabel || category.value || category.dictValue || '' + })) + .filter((category) => category.value) +} + +export function buildSourceCategories(projects = [], sourceCategories = []) { + const seen = new Set() + const categories = [{ value: 'all', label: '全部源码' }] + normalizeSourceCategories(sourceCategories).forEach((category) => { + if (seen.has(category.value)) return + seen.add(category.value) + categories.push(category) + }) + projects.forEach((project) => { + const value = project.category + if (!value || seen.has(value)) return + seen.add(value) + categories.push({ + value, + label: value + }) + }) + return categories +} + +function normalizeList(value) { + if (Array.isArray(value)) return value + if (!value) return [] + if (typeof value !== 'string') return [] + try { + const parsed = JSON.parse(value) + return Array.isArray(parsed) ? parsed : [] + } catch (error) { + return value + .split(/[,,\n]/) + .map((item) => item.trim()) + .filter(Boolean) + } +} + +function normalizeDate(value) { + if (!value) return '' + if (typeof value === 'string') return value.slice(0, 10) + const date = new Date(value) + if (Number.isNaN(date.getTime())) return '' + return date.toISOString().slice(0, 10) +} + +function formatPrice(cents) { + const value = Number(cents || 0) / 100 + return `¥${Number.isInteger(value) ? value : value.toFixed(2)}` +} diff --git a/RuoYi-Vue/easycode-web/src/api/sourceAdapter.test.mjs b/RuoYi-Vue/easycode-web/src/api/sourceAdapter.test.mjs new file mode 100644 index 0000000..349c8e2 --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/api/sourceAdapter.test.mjs @@ -0,0 +1,46 @@ +import assert from 'node:assert/strict' +import { buildSourceCategories, normalizeSourceProject } from './sourceAdapter.js' + +const backendProject = { + projectId: 10, + slug: 'dms-platform', + projectName: 'Commercial DMS', + category: 'enterprise', + coverText: 'DMS', + summary: 'DMS source', + descriptionMd: '# DMS', + price: 39900, + priceLabel: '¥399', + viewCount: 2860, + updateTime: '2026-05-18 12:00:00', + tags: ['Spring Boot', 'Vue2'], + modules: ['Dealer', 'Repair'], + scenes: ['Aftermarket'], + purchased: true +} + +const project = normalizeSourceProject(backendProject) + +assert.equal(project.id, 'dms-platform') +assert.equal(project.projectId, 10) +assert.equal(project.name, 'Commercial DMS') +assert.equal(project.price, '¥399') +assert.equal(project.views, 2860) +assert.equal(project.updateTime, '2026-05-18') +assert.equal(project.tags[1], 'Vue2') +assert.equal(project.modules[0], 'Dealer') +assert.equal(project.purchased, true) + +const categories = buildSourceCategories( + [ + backendProject, + { ...backendProject, projectId: 11, slug: 'mall', category: 'mall' } + ], + [ + { dictValue: 'enterprise', dictLabel: 'Enterprise Systems' }, + { dictValue: 'mall', dictLabel: 'Mall Systems' } + ] +) + +assert.deepEqual(categories.map((category) => category.value), ['all', 'enterprise', 'mall']) +assert.deepEqual(categories.map((category) => category.label), ['全部源码', 'Enterprise Systems', 'Mall Systems']) diff --git a/RuoYi-Vue/easycode-web/src/api/timeouts.js b/RuoYi-Vue/easycode-web/src/api/timeouts.js new file mode 100644 index 0000000..3f029ab --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/api/timeouts.js @@ -0,0 +1,9 @@ +function toPositiveNumber(value, fallback) { + const number = Number(value) + return Number.isFinite(number) && number > 0 ? number : fallback +} + +const env = import.meta.env || {} + +export const DEFAULT_REQUEST_TIMEOUT = toPositiveNumber(env.VITE_API_TIMEOUT, 30000) +export const GENERATE_REQUEST_TIMEOUT = toPositiveNumber(env.VITE_GENERATE_TIMEOUT, 180000) diff --git a/RuoYi-Vue/easycode-web/src/components/AppHeader.vue b/RuoYi-Vue/easycode-web/src/components/AppHeader.vue index 55b3b04..503e794 100644 --- a/RuoYi-Vue/easycode-web/src/components/AppHeader.vue +++ b/RuoYi-Vue/easycode-web/src/components/AppHeader.vue @@ -8,6 +8,8 @@
diff --git a/RuoYi-Vue/easycode-web/src/components/DatabaseDesigner.vue b/RuoYi-Vue/easycode-web/src/components/DatabaseDesigner.vue index bd83c6a..3b1dca4 100644 --- a/RuoYi-Vue/easycode-web/src/components/DatabaseDesigner.vue +++ b/RuoYi-Vue/easycode-web/src/components/DatabaseDesigner.vue @@ -323,7 +323,8 @@ function removeField(index) { .delete-col { display: flex; - align-items: end; + align-items: flex-start; + padding-top: 30px; } .field-head { @@ -347,5 +348,9 @@ function removeField(index) { border-right: 0; border-bottom: 1px solid #e3e8f0; } + + .delete-col { + padding-top: 0; + } } diff --git a/RuoYi-Vue/easycode-web/src/components/ErDiagramView.vue b/RuoYi-Vue/easycode-web/src/components/ErDiagramView.vue new file mode 100644 index 0000000..2b3bdcb --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/components/ErDiagramView.vue @@ -0,0 +1,514 @@ + + + + + diff --git a/RuoYi-Vue/easycode-web/src/data/sourceProjects.js b/RuoYi-Vue/easycode-web/src/data/sourceProjects.js new file mode 100644 index 0000000..37ce84d --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/data/sourceProjects.js @@ -0,0 +1,217 @@ +export const sourceCategories = [ + { value: 'enterprise', label: '企业管理系统' }, + { value: 'mall', label: '商城系统' }, + { value: 'office', label: 'OA 办公' }, + { value: 'lowcode', label: '低代码平台' }, + { value: 'microservice', label: '微服务脚手架' } +] + +export const sourceProjects = [ + { + id: 'dms-platform', + name: '商用车 DMS 管理系统', + category: 'enterprise', + coverText: 'DMS', + summary: '覆盖经销商、维修工单、索赔、配件库存、服务活动和结算的商用车售后管理源码。', + price: '¥399', + views: 2860, + updateTime: '2026-05-18', + tags: ['Spring Boot', 'Vue2', 'MySQL'], + modules: ['经销商管理', '维修工单', '配件库存', '索赔结算', '服务活动'], + scenes: ['汽车后市场', '商用车售后', '经销商协同'], + descriptionMd: `# 商用车 DMS 管理系统 + +这套源码面向商用车售后服务场景,提供经销商、车辆档案、维修工单、索赔流程、配件库存和结算对账等核心能力。 + +## 核心功能 + +- 经销商档案、服务站和维修技师管理 +- 车辆档案、保养提醒和维修历史追踪 +- 维修工单、派工、完工质检和费用结算 +- 配件入库、出库、调拨和库存预警 +- 索赔申请、审核、结算和统计报表 + +## 技术栈 + +| 层级 | 技术 | +| --- | --- | +| 后端 | Spring Boot、MyBatis、Spring Security | +| 前端 | Vue2、Element UI | +| 数据库 | MySQL | + +## 目录结构 + +\`\`\`text +dms-platform +├─ backend +├─ admin-web +├─ sql +└─ docs +\`\`\` + +## 适合人群 + +适合需要快速交付售后服务、维修工单、配件库存类系统的开发团队。` + }, + { + id: 'mall-order-system', + name: '商城订单管理系统', + category: 'mall', + coverText: 'MALL', + summary: '包含商品、订单、支付、库存、优惠券、会员和后台统计模块的商城管理源码。', + price: '¥299', + views: 1980, + updateTime: '2026-05-15', + tags: ['Spring Cloud', 'Redis', 'Vue3'], + modules: ['商品中心', '订单中心', '支付记录', '会员体系', '营销活动'], + scenes: ['电商后台', '订单运营', '会员营销'], + descriptionMd: `# 商城订单管理系统 + +项目提供从商品上架到订单履约的完整后台管理能力,适合作为中小型商城或订单中台的启动源码。 + +## 功能模块 + +- 商品分类、SKU、库存和上下架 +- 购物车、订单、支付记录和售后单 +- 优惠券、满减活动和会员等级 +- 后台统计看板和经营数据导出 + +## 部署说明 + +\`\`\`bash +npm install +npm run build +\`\`\` + +后端服务默认读取 MySQL 与 Redis 配置,可按环境拆分配置文件。` + }, + { + id: 'oa-approval-suite', + name: 'OA 办公审批系统', + category: 'office', + coverText: 'OA', + summary: '集成用户、角色、菜单、审批流、请假、报销、公告和文件管理的办公源码。', + price: '¥268', + views: 1750, + updateTime: '2026-05-12', + tags: ['Sa-Token', 'Element UI', '工作流'], + modules: ['审批流程', '请假报销', '公告通知', '文件管理', '权限菜单'], + scenes: ['企业内网', '行政审批', '协同办公'], + descriptionMd: `# OA 办公审批系统 + +这是一套偏企业内网办公的基础源码,重点覆盖审批、公告、文件与权限管理。 + +## 亮点 + +- 可配置审批节点和审批人 +- 请假、报销、外出等常见办公流程 +- 公告通知、附件上传和文件归档 +- 角色、菜单、按钮级权限控制 + +> 适合二次开发为企业内部管理平台。` + }, + { + id: 'erp-warehouse', + name: 'ERP 仓储管理系统', + category: 'enterprise', + coverText: 'ERP', + summary: '提供采购、销售、入库、出库、盘点、供应商和库存报表模块的仓储源码。', + price: '¥199', + views: 1320, + updateTime: '2026-05-09', + tags: ['ERP', 'MyBatis-Plus', 'Excel'], + modules: ['采购入库', '销售出库', '库存盘点', '供应商管理', '报表导出'], + scenes: ['仓储管理', '进销存', '供应链后台'], + descriptionMd: `# ERP 仓储管理系统 + +源码聚焦进销存和仓储管理,适合小型供应链、仓库和贸易公司快速搭建业务后台。 + +## 模块清单 + +- 采购订单、采购入库和供应商档案 +- 销售订单、销售出库和客户档案 +- 库存流水、库存盘点和预警规则 +- Excel 导入导出与库存报表` + }, + { + id: 'lowcode-form-platform', + name: '低代码表单平台', + category: 'lowcode', + coverText: 'FORM', + summary: '支持动态表单、拖拽布局、字段配置、数据字典和在线设计的低代码源码。', + price: '¥499', + views: 980, + updateTime: '2026-05-06', + tags: ['Vue3', 'Element Plus', '拖拽设计'], + modules: ['表单设计器', '字段配置', '动态校验', '数据字典', '表单预览'], + scenes: ['低代码平台', '动态表单', '配置化后台'], + descriptionMd: `# 低代码表单平台 + +项目用于构建配置化表单和数据采集页面,包含设计器、字段配置、预览和提交数据管理。 + +## 能力范围 + +- 拖拽式表单组件编排 +- 字段属性、校验规则和选项配置 +- 字典数据联动 +- 表单预览与数据提交记录` + }, + { + id: 'microservice-auth-starter', + name: '微服务权限脚手架', + category: 'microservice', + coverText: 'MS', + summary: '集成网关、认证中心、系统服务、日志服务、文件服务和监控基础能力的脚手架源码。', + price: '¥599', + views: 2560, + updateTime: '2026-05-03', + tags: ['Spring Cloud', 'Nacos', 'Gateway'], + modules: ['网关服务', '认证中心', '系统服务', '日志中心', '文件服务'], + scenes: ['微服务基础架构', '权限平台', '多服务治理'], + descriptionMd: `# 微服务权限脚手架 + +这套源码适合从单体后台升级到微服务架构的团队,预置认证、网关、系统权限和基础监控能力。 + +## 服务组成 + +- Gateway 网关统一鉴权和路由 +- Auth 认证中心 +- System 系统权限服务 +- Log 操作日志服务 +- File 文件服务 + +## 推荐用途 + +可作为企业级微服务后台的基础工程,按业务域继续拆分服务。` + } +] + +export function listSourceCategories() { + const usedCategories = new Set(sourceProjects.map((project) => project.category)) + return [ + { value: 'all', label: '全部源码' }, + ...sourceCategories.filter((category) => usedCategories.has(category.value)) + ] +} + +export function findSourceProject(id) { + return sourceProjects.find((project) => project.id === id) || null +} + +export function filterSourceProjects({ category = 'all', keyword = '' } = {}) { + const normalizedKeyword = keyword.trim().toLowerCase() + return sourceProjects.filter((project) => { + const categoryMatched = category === 'all' || project.category === category + if (!categoryMatched) return false + if (!normalizedKeyword) return true + + const searchText = [ + project.name, + project.summary, + ...project.tags, + ...project.modules, + ...project.scenes + ].join(' ').toLowerCase() + return searchText.includes(normalizedKeyword) + }) +} diff --git a/RuoYi-Vue/easycode-web/src/data/sourceProjects.test.mjs b/RuoYi-Vue/easycode-web/src/data/sourceProjects.test.mjs new file mode 100644 index 0000000..5e18edd --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/data/sourceProjects.test.mjs @@ -0,0 +1,46 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import { filterSourceProjects, findSourceProject, listSourceCategories, sourceProjects } from './sourceProjects.js' + +test('sourceProjects exposes visible projects with required display fields', () => { + assert.ok(sourceProjects.length >= 6) + sourceProjects.forEach((project) => { + assert.ok(project.id) + assert.ok(project.name) + assert.ok(project.summary) + assert.ok(project.coverText) + assert.equal(Object.prototype.hasOwnProperty.call(project, 'sourceSize'), false) + assert.ok(Array.isArray(project.tags)) + assert.ok(project.tags.length >= 3) + assert.ok(project.descriptionMd.includes('# ')) + }) +}) + +test('listSourceCategories includes all plus project categories without duplicates', () => { + const categories = listSourceCategories() + + assert.equal(categories[0].value, 'all') + assert.equal(categories[0].label, '全部源码') + assert.deepEqual(new Set(categories.map((category) => category.value)).size, categories.length) + assert.ok(categories.some((category) => category.value === 'enterprise')) + assert.ok(categories.some((category) => category.value === 'mall')) +}) + +test('findSourceProject returns project by id and falls back to null', () => { + assert.equal(findSourceProject('dms-platform')?.name, '商用车 DMS 管理系统') + assert.equal(findSourceProject('missing-project'), null) +}) + +test('filterSourceProjects filters by category and keyword', () => { + const mallProjects = filterSourceProjects({ category: 'mall' }) + assert.deepEqual( + mallProjects.map((project) => project.id), + ['mall-order-system'] + ) + + const searchProjects = filterSourceProjects({ category: 'all', keyword: '审批' }) + assert.deepEqual( + searchProjects.map((project) => project.id), + ['oa-approval-suite'] + ) +}) diff --git a/RuoYi-Vue/easycode-web/src/router/index.js b/RuoYi-Vue/easycode-web/src/router/index.js index 5eef946..9b7b6f9 100644 --- a/RuoYi-Vue/easycode-web/src/router/index.js +++ b/RuoYi-Vue/easycode-web/src/router/index.js @@ -5,12 +5,18 @@ import HomeView from '@/views/HomeView.vue' import LoginView from '@/views/LoginView.vue' import RegisterView from '@/views/RegisterView.vue' import GenerateView from '@/views/GenerateView.vue' +import ProjectListView from '@/views/ProjectListView.vue' import PreviewView from '@/views/PreviewView.vue' +import SourceDetailView from '@/views/SourceDetailView.vue' +import SourceStoreView from '@/views/SourceStoreView.vue' const routes = [ { path: '/', name: 'home', component: HomeView }, { path: '/login', name: 'login', component: LoginView }, { path: '/register', name: 'register', component: RegisterView }, + { path: '/source-store', name: 'source-store', component: SourceStoreView }, + { path: '/source-store/:sourceId', name: 'source-detail', component: SourceDetailView }, + { path: '/projects', name: 'projects', component: ProjectListView, meta: { requiresAuth: true } }, { path: '/generate', name: 'generate', component: GenerateView, meta: { requiresAuth: true } }, { path: '/project/:projectId/preview', diff --git a/RuoYi-Vue/easycode-web/src/utils/download.js b/RuoYi-Vue/easycode-web/src/utils/download.js new file mode 100644 index 0000000..23ab996 --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/utils/download.js @@ -0,0 +1,17 @@ +export function saveBlob(blob, filename) { + const url = window.URL.createObjectURL(blob) + const link = document.createElement('a') + link.href = url + link.download = filename + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + window.URL.revokeObjectURL(url) +} + +export function sourceZipName(project) { + const fallback = project?.projectId ? `project-${project.projectId}` : 'easycode-project' + const rawName = project?.projectFileName || project?.projectName || fallback + const safeName = String(rawName).trim().replace(/[\\/:*?"<>|]/g, '_') || fallback + return `${safeName}-source.zip` +} diff --git a/RuoYi-Vue/easycode-web/src/utils/erExport.js b/RuoYi-Vue/easycode-web/src/utils/erExport.js new file mode 100644 index 0000000..8cfdd24 --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/utils/erExport.js @@ -0,0 +1,92 @@ +const HEADER_HEIGHT = 60 +const FIELD_HEIGHT = 28 + +function escapeXml(value) { + return String(value ?? '') + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') +} + +function truncate(value, maxLength) { + const text = String(value ?? '') + return text.length > maxLength ? `${text.slice(0, maxLength - 3)}...` : text +} + +function badgeOf(field) { + if (field.primary) { + return { text: 'PK', fill: '#dbeafe', color: '#1d4ed8' } + } + if (field.required) { + return { text: '*', fill: '#fef3c7', color: '#b45309' } + } + return { text: '-', fill: '#ffffff', color: '#cbd5e1' } +} + +function renderEdge(edge) { + return ` + + ${escapeXml(edge.fieldName)}` +} + +function renderField(field, index) { + const y = HEADER_HEIGHT + index * FIELD_HEIGHT + 20 + const badge = badgeOf(field) + return ` + + ${escapeXml(badge.text)} + ${escapeXml(truncate(field.name, 18))} + ${escapeXml(truncate(field.comment, 12))}` +} + +function renderNode(node) { + const fields = node.fields.length + ? node.fields.map(renderField).join('') + : 'No fields' + + return ` + + + + + + ${escapeXml(truncate(node.title, 24))} + ${escapeXml(truncate(node.comment, 26))} + ${fields} + ` +} + +export function buildErExportSvg({ width, height, nodes, edges }) { + const canvasWidth = Math.max(1, Number(width) || 1) + const canvasHeight = Math.max(1, Number(height) || 1) + const exportNodes = Array.isArray(nodes) ? nodes : [] + const exportEdges = Array.isArray(edges) ? edges : [] + + return ` + + + + + + + + + ${exportEdges.map(renderEdge).join('')} + ${exportNodes.map(renderNode).join('')} +` +} diff --git a/RuoYi-Vue/easycode-web/src/utils/erExport.test.mjs b/RuoYi-Vue/easycode-web/src/utils/erExport.test.mjs new file mode 100644 index 0000000..1bb4fbf --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/utils/erExport.test.mjs @@ -0,0 +1,41 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import { buildErExportSvg } from './erExport.js' + +test('buildErExportSvg renders a pure SVG that can be drawn to canvas safely', () => { + const svg = buildErExportSvg({ + width: 900, + height: 480, + nodes: [ + { + id: 'student_info', + title: 'student_info', + comment: 'Student table', + x: 20, + y: 30, + width: 260, + height: 132, + fields: [ + { name: 'id', comment: 'ID', primary: true, required: true }, + { name: 'department_id', comment: 'Department', primary: false, required: false } + ] + } + ], + edges: [ + { + id: 'student_info.department_id->department.id', + path: 'M 280 120 C 340 120, 420 120, 480 120', + labelX: 380, + labelY: 112, + fieldName: 'department_id', + inferred: true + } + ] + }) + + assert.match(svg, /^<\?xml version="1.0" encoding="UTF-8"\?>/) + assert.equal(svg.includes(' node.id !== sourceId && candidates.includes(normalizeKey(node.title))) + if (exact) return exact + + return nodes.find((node) => { + if (node.id === sourceId) return false + const nodeKey = normalizeKey(node.title) + return nodeKey.startsWith(normalizeKey(`${base}_`)) || nodeKey.startsWith(normalizeKey(base)) + }) +} + +function primaryFieldOf(node) { + return node.fields.find((field) => field.primary) || node.fields.find((field) => field.name === 'id') || node.fields[0] +} + +function buildInferredEdges(nodes, deletedEdgeIds) { + const edges = [] + const deleted = new Set(Array.isArray(deletedEdgeIds) ? deletedEdgeIds : []) + + nodes.forEach((sourceNode) => { + sourceNode.fields.forEach((field) => { + const fieldName = String(field.name || '').toLowerCase() + if (field.primary || !fieldName.endsWith('_id')) return + + const base = fieldName.slice(0, -3) + if (!base) return + + const targetNode = findTargetNode(nodes, base, sourceNode.id) + if (!targetNode) return + + const targetField = primaryFieldOf(targetNode) + const id = `${sourceNode.id}.${field.name}->${targetNode.id}.${targetField?.name || 'id'}` + if (deleted.has(id)) return + + edges.push({ + id, + source: sourceNode.id, + target: targetNode.id, + fieldName: field.name, + targetFieldName: targetField?.name || 'id', + inferred: true + }) + }) + }) + + return edges +} + +function buildManualEdges(nodes, relations) { + const nodeIds = new Set(nodes.map((node) => node.id)) + return (Array.isArray(relations) ? relations : []) + .filter((relation) => nodeIds.has(relation?.source) && nodeIds.has(relation?.target)) + .map((relation, index) => ({ + id: cleanName(relation.id, `manual_${index + 1}`), + source: relation.source, + target: relation.target, + fieldName: cleanName(relation.fieldName, 'id'), + targetFieldName: cleanName(relation.targetFieldName, 'id'), + inferred: false + })) +} + +function applyPositions(nodes, draft) { + return nodes.map((node) => { + const position = savedPositionFor(draft, node.id) + return position ? { ...node, ...position } : node + }) +} + +export function buildErGraph(tables, draft = {}) { + const sourceTables = Array.isArray(tables) ? tables : [] + const nodes = applyPositions( + sourceTables.map((table, index) => buildNode(table, index, Array.isArray(table?.columns) ? table.columns : [])), + draft + ) + + return { + nodes, + edges: [ + ...buildInferredEdges(nodes, draft?.deletedEdgeIds), + ...buildManualEdges(nodes, draft?.relations) + ] + } +} diff --git a/RuoYi-Vue/easycode-web/src/utils/erGraph.test.mjs b/RuoYi-Vue/easycode-web/src/utils/erGraph.test.mjs new file mode 100644 index 0000000..c5dab06 --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/utils/erGraph.test.mjs @@ -0,0 +1,95 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import { buildErGraph } from './erGraph.js' + +test('buildErGraph creates table nodes with primary and required fields', () => { + const graph = buildErGraph([ + { + tableName: 'department', + tableComment: '院系表', + columns: [ + { columnName: 'id', columnComment: '主键ID', isPk: '1', isRequired: '1' }, + { columnName: 'dept_name', columnComment: '院系名称', isRequired: '1' } + ] + } + ]) + + assert.equal(graph.nodes.length, 1) + assert.equal(graph.nodes[0].title, 'department') + assert.equal(graph.nodes[0].comment, '院系表') + assert.deepEqual( + graph.nodes[0].fields.map((field) => ({ name: field.name, primary: field.primary, required: field.required })), + [ + { name: 'id', primary: true, required: true }, + { name: 'dept_name', primary: false, required: true } + ] + ) +}) + +test('buildErGraph infers foreign-key style edges from xxx_id fields', () => { + const graph = buildErGraph([ + { + tableName: 'department', + columns: [{ columnName: 'id', isPk: '1' }] + }, + { + tableName: 'student_info', + columns: [ + { columnName: 'id', isPk: '1' }, + { columnName: 'department_id', columnComment: '所属院系' } + ] + } + ]) + + assert.equal(graph.edges.length, 1) + assert.deepEqual( + { + source: graph.edges[0].source, + target: graph.edges[0].target, + fieldName: graph.edges[0].fieldName, + targetFieldName: graph.edges[0].targetFieldName + }, + { + source: 'student_info', + target: 'department', + fieldName: 'department_id', + targetFieldName: 'id' + } + ) +}) + +test('buildErGraph applies saved node positions', () => { + const graph = buildErGraph( + [{ tableName: 'department', columns: [{ columnName: 'id', isPk: '1' }] }], + { positions: { department: { x: 120, y: 240 } } } + ) + + assert.equal(graph.nodes[0].x, 120) + assert.equal(graph.nodes[0].y, 240) +}) + +test('buildErGraph merges manual relations and hides deleted inferred relations', () => { + const graph = buildErGraph( + [ + { tableName: 'department', columns: [{ columnName: 'id', isPk: '1' }] }, + { tableName: 'student_info', columns: [{ columnName: 'id', isPk: '1' }, { columnName: 'department_id' }] }, + { tableName: 'class_info', columns: [{ columnName: 'id', isPk: '1' }] } + ], + { + deletedEdgeIds: ['student_info.department_id->department.id'], + relations: [ + { + id: 'manual_student_class', + source: 'student_info', + target: 'class_info', + fieldName: 'id', + targetFieldName: 'id' + } + ] + } + ) + + assert.equal(graph.edges.length, 1) + assert.equal(graph.edges[0].id, 'manual_student_class') + assert.equal(graph.edges[0].inferred, false) +}) diff --git a/RuoYi-Vue/easycode-web/src/utils/markdown.js b/RuoYi-Vue/easycode-web/src/utils/markdown.js new file mode 100644 index 0000000..b6fe05b --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/utils/markdown.js @@ -0,0 +1,148 @@ +const escapeMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' +} + +function escapeHtml(value) { + return String(value ?? '').replace(/[&<>"']/g, (char) => escapeMap[char]) +} + +function renderInline(value) { + let html = escapeHtml(value) + html = html.replace(/`([^`]+)`/g, '$1') + html = html.replace(/\*\*([^*]+)\*\*/g, '$1') + html = html.replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g, '$1') + return html +} + +function renderTable(rows) { + if (rows.length < 2) return '' + const headers = splitTableRow(rows[0]) + const bodyRows = rows.slice(2).map(splitTableRow) + const headerHtml = headers.map((header) => `${renderInline(header)}`).join('') + const bodyHtml = bodyRows + .map((row) => `${row.map((cell) => `${renderInline(cell)}`).join('')}`) + .join('') + + return `${headerHtml}${bodyHtml}
` +} + +function splitTableRow(row) { + return row + .trim() + .replace(/^\|/, '') + .replace(/\|$/, '') + .split('|') + .map((cell) => cell.trim()) +} + +function isTableDivider(line) { + return /^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(line) +} + +function flushParagraph(parts, output) { + if (!parts.length) return + output.push(`

${renderInline(parts.join(' '))}

`) + parts.length = 0 +} + +function flushList(items, output) { + if (!items.length) return + output.push(`
    ${items.map((item) => `
  • ${renderInline(item)}
  • `).join('')}
`) + items.length = 0 +} + +function flushTable(rows, output) { + if (!rows.length) return + const html = renderTable(rows) + if (html) { + output.push(html) + } + rows.length = 0 +} + +export function renderMarkdown(markdown) { + const lines = String(markdown || '').replace(/\r\n/g, '\n').split('\n') + const output = [] + const paragraph = [] + const listItems = [] + const tableRows = [] + let codeLanguage = '' + let codeLines = [] + + function flushBlocks() { + flushParagraph(paragraph, output) + flushList(listItems, output) + flushTable(tableRows, output) + } + + lines.forEach((line) => { + const fenceMatch = line.match(/^```(\w+)?\s*$/) + if (fenceMatch) { + if (codeLanguage || codeLines.length) { + const languageClass = codeLanguage ? ` class="language-${escapeHtml(codeLanguage)}"` : '' + output.push(`
${escapeHtml(`${codeLines.join('\n')}\n`)}
`) + codeLanguage = '' + codeLines = [] + } else { + flushBlocks() + codeLanguage = fenceMatch[1] || 'text' + } + return + } + + if (codeLanguage || codeLines.length) { + codeLines.push(line) + return + } + + if (!line.trim()) { + flushBlocks() + return + } + + if (tableRows.length || (line.includes('|') && lines[lines.indexOf(line) + 1] && isTableDivider(lines[lines.indexOf(line) + 1]))) { + flushParagraph(paragraph, output) + flushList(listItems, output) + tableRows.push(line) + return + } + + const headingMatch = line.match(/^(#{1,4})\s+(.+)$/) + if (headingMatch) { + flushBlocks() + const level = headingMatch[1].length + output.push(`${renderInline(headingMatch[2])}`) + return + } + + const listMatch = line.match(/^\s*[-*]\s+(.+)$/) + if (listMatch) { + flushParagraph(paragraph, output) + listItems.push(listMatch[1]) + return + } + + const quoteMatch = line.match(/^>\s+(.+)$/) + if (quoteMatch) { + flushBlocks() + output.push(`
${renderInline(quoteMatch[1])}
`) + return + } + + flushList(listItems, output) + flushTable(tableRows, output) + paragraph.push(line.trim()) + }) + + if (codeLanguage || codeLines.length) { + const languageClass = codeLanguage ? ` class="language-${escapeHtml(codeLanguage)}"` : '' + output.push(`
${escapeHtml(`${codeLines.join('\n')}\n`)}
`) + } + flushBlocks() + + return output.join('\n') +} diff --git a/RuoYi-Vue/easycode-web/src/utils/markdown.test.mjs b/RuoYi-Vue/easycode-web/src/utils/markdown.test.mjs new file mode 100644 index 0000000..0cff8b1 --- /dev/null +++ b/RuoYi-Vue/easycode-web/src/utils/markdown.test.mjs @@ -0,0 +1,22 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import { renderMarkdown } from './markdown.js' + +test('renderMarkdown renders common markdown and keeps raw html escaped', () => { + const html = renderMarkdown(`# 项目介绍 + +- Spring Boot +- Vue3 + +\`\`\`bash +npm run dev +\`\`\` + +`) + + assert.match(html, /

项目介绍<\/h1>/) + assert.match(html, /
  • Spring Boot<\/li>/) + assert.match(html, /
    npm run dev\n<\/code><\/pre>/)
    +  assert.equal(html.includes('
     
     
    diff --git a/RuoYi-Vue/easycode-web/src/views/HomeView.vue b/RuoYi-Vue/easycode-web/src/views/HomeView.vue
    index 40b0cbb..1807b0d 100644
    --- a/RuoYi-Vue/easycode-web/src/views/HomeView.vue
    +++ b/RuoYi-Vue/easycode-web/src/views/HomeView.vue
    @@ -22,7 +22,6 @@
             
               立即生成
             
    -        登录
           
     
           
    @@ -95,7 +94,7 @@ function handleGenerate() { .quick-form { display: grid; - grid-template-columns: minmax(240px, 1fr) auto auto; + grid-template-columns: minmax(240px, 1fr) auto; gap: 12px; } diff --git a/RuoYi-Vue/easycode-web/src/views/PreviewView.vue b/RuoYi-Vue/easycode-web/src/views/PreviewView.vue index b366577..a23467e 100644 --- a/RuoYi-Vue/easycode-web/src/views/PreviewView.vue +++ b/RuoYi-Vue/easycode-web/src/views/PreviewView.vue @@ -4,7 +4,10 @@