From 852adbcfffaeaff93d10fa23a6bd1609eac55664 Mon Sep 17 00:00:00 2001 From: xuqiuyun <1113560936@qq.com> Date: Thu, 25 Sep 2025 19:09:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E4=BF=9D=E9=99=A9=E5=89=8D?= =?UTF-8?q?=E5=90=8E=E7=AB=AF=E3=80=81=E5=85=BB=E6=AE=96=E7=AB=AF=E5=B0=8F?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cursor/rules/project-rules.mdc | 54 + insurance_admin-system/package.json | 8 +- .../public/dayjs_fix_test.html | 157 + .../src/components/Layout.vue | 26 +- .../src/components/PermissionManagement.vue | 527 + .../components/RolePermissionManagement.vue | 525 + insurance_admin-system/src/stores/user.js | 322 +- insurance_admin-system/src/utils/api.js | 43 +- .../src/utils/dataValidator.js | 119 + insurance_admin-system/src/utils/request.js | 240 +- .../src/views/ApplicationManagement.vue | 22 +- .../src/views/Dashboard.vue | 218 +- .../src/views/DataWarehouse.vue | 132 +- .../src/views/SystemSettings.vue | 540 +- insurance_admin-system/test_current_logs.js | 62 + insurance_backend/check_admin_token.js | 27 + insurance_backend/config/swagger.js | 41 +- .../controllers/dashboardController.js | 295 + .../controllers/dataWarehouseController.js | 4 + .../controllers/insuranceTypeController.js | 8 +- .../controllers/permissionController.js | 415 + .../controllers/rolePermissionController.js | 420 + .../controllers/systemController.js | 90 +- .../controllers/userController.js | 113 +- insurance_backend/debug_api_response.js | 73 + insurance_backend/docs/API认证文档.md | 222 + insurance_backend/middleware/auth.js | 132 +- .../middleware/fixedTokenAuth.js | 119 + .../20241220-add-fixed-token-to-users.js | 16 + ...122000002-update-insurance-applications.js | 75 - .../20250925000001-create-permissions.js | 109 + .../20250925000002-create-role-permissions.js | 82 + .../20250925000003-create-menu-permissions.js | 82 + insurance_backend/models/MenuPermission.js | 42 + insurance_backend/models/Permission.js | 93 + insurance_backend/models/RolePermission.js | 42 + insurance_backend/models/User.js | 6 + insurance_backend/models/index.js | 66 + insurance_backend/routes/dashboard.js | 222 + insurance_backend/routes/installationTasks.js | 36 +- insurance_backend/routes/menus.js | 32 +- insurance_backend/routes/permissions.js | 542 + insurance_backend/routes/rolePermissions.js | 384 + insurance_backend/routes/supervisoryTasks.js | 34 +- insurance_backend/routes/users.js | 168 + .../scripts/fix-admin-permissions.js | 3 +- .../scripts/fix_admin_permissions.js | 124 + .../20250925000001-init-permissions.js | 431 + insurance_backend/src/app.js | 17 +- .../src/middleware/permissionMiddleware.js | 191 + .../src/services/permissionService.js | 254 + insurance_backend/test_api.js | 21 +- insurance_backend/test_fixed_token.js | 109 + .../test_role_permissions_api.js | 75 + .../farm-monitor-dashboard/API_INTEGRATION.md | 241 - .../API_INTEGRATION_COMPLETE.md | 119 - .../API_INTEGRATION_GUIDE.md | 122 - .../API_INTEGRATION_UPDATE.md | 161 - .../farm-monitor-dashboard/API_PORT_UPDATE.md | 154 - .../farm-monitor-dashboard/API_SETUP.md | 65 - .../farm-monitor-dashboard/API_TEST_GUIDE.md | 123 - .../farm-monitor-dashboard/AUTH_FIX_README.md | 88 - .../farm-monitor-dashboard/AUTH_SOLUTION.md | 161 - .../AUTH_SUCCESS_REPORT.md | 177 - .../CATTLE_PROFILE_README.md | 195 - .../CATTLE_TRANSFER_ENHANCED.md | 147 - .../CATTLE_TRANSFER_FEATURE.md | 137 - .../CHINESE_MAPPING_GUIDE.md | 195 - .../COLLAR_API_INTEGRATION.md | 127 - .../COLLAR_PAGINATION_SEARCH_FEATURES.md | 184 - .../CONVERSION_GUIDE.md | 371 - .../farm-monitor-dashboard/DEBUG_API_ISSUE.md | 87 - .../DEPRECATION_WARNING_FIX.md | 95 - .../DOMAIN_CONFIG_GUIDE.md | 98 - .../EARTAG_CRUD_FEATURES.md | 187 - .../ELECTRONIC_FENCE_README.md | 231 - .../FIELD_MAPPING_GUIDE.md | 168 - .../HOST_NUMBER_FIX_REPORT.md | 141 - .../IMPLEMENTATION_SUMMARY.md | 117 - .../LOGIN_PAGE_README.md | 112 - .../NAVIGATION_FIX_SUMMARY.md | 209 - .../NAVIGATION_IMPLEMENTATION_SUMMARY.md | 144 - .../NETWORK_ERROR_FIX.md | 121 - .../PAGINATION_FIELD_MAPPING_FIX.md | 123 - .../PASSWORD_LOGIN_README.md | 175 - mini_program/farm-monitor-dashboard/README.md | 229 - .../REGISTER_PAGE_README.md | 162 - .../ROUTER_FIX_README.md | 107 - .../SEARCH_FUNCTIONALITY.md | 175 - .../SMART_EARTAG_ALERT_README.md | 141 - .../SMS_LOGIN_README.md | 139 - .../SYNTAX_ERROR_FIX.md | 60 - .../farm-monitor-dashboard/TOKEN_ERROR_FIX.md | 141 - mini_program/farm-monitor-dashboard/app.js | 2 +- mini_program/farm-monitor-dashboard/app.json | 3 +- .../farm-monitor-dashboard/auth-test.js | 83 - .../farm-monitor-dashboard/auto-login.js | 85 - .../farm-monitor-dashboard/check-backend.js | 47 - .../farm-monitor-dashboard/debug-console.js | 70 - .../images/ICON_REQUIREMENTS.md | 50 - .../farm-monitor-dashboard/images/README.md | 57 - .../farm-monitor-dashboard/mock-api-server.js | 95 - .../farm-monitor-dashboard/package-lock.json | 16997 ---------------- .../farm-monitor-dashboard/package.json | 38 - .../pages/device/collar/collar.js | 84 + .../pages/device/collar/collar.json | 5 + .../pages/device/collar/collar.wxml | 37 + .../pages/device/collar/collar.wxss | 46 + .../device/eartag-detail/eartag-detail.js | 222 +- .../device/eartag-detail/eartag-detail.wxml | 40 + .../pages/device/eartag/eartag.js | 677 +- .../pages/device/eartag/eartag.wxml | 53 + .../pages/device/eartag/eartag.wxss | 65 + .../pages/login/login.js | 54 +- .../project.config.json | 5 +- .../farm-monitor-dashboard/public/favicon.svg | 4 - .../farm-monitor-dashboard/public/index.html | 18 - .../farm-monitor-dashboard/set-token.js | 63 - .../farm-monitor-dashboard/src/App.vue | 110 - .../farm-monitor-dashboard/src/app.scss | 353 - .../src/components/AlertTest.vue | 210 - .../src/components/ApiTest.vue | 212 - .../src/components/ApiTestPage.vue | 252 - .../src/components/AuthTest.vue | 388 - .../src/components/CattleAdd.vue | 482 - .../src/components/CattleBatch.vue | 829 - .../src/components/CattleExit.vue | 781 - .../src/components/CattlePen.vue | 799 - .../src/components/CattleProfile.vue | 574 - .../src/components/CattleTest.vue | 125 - .../src/components/CattleTransfer.vue | 855 - .../src/components/CattleTransferRegister.vue | 540 - .../src/components/EarTag.vue | 1415 -- .../src/components/ElectronicFence.vue | 1361 -- .../src/components/Home.vue | 703 - .../src/components/Login.vue | 553 - .../src/components/MapTest.vue | 237 - .../src/components/MapView.vue | 589 - .../src/components/PasswordLogin.vue | 756 - .../src/components/Production.vue | 419 - .../src/components/Profile.vue | 385 - .../src/components/Register.vue | 630 - .../src/components/SmartAnkle.vue | 547 - .../src/components/SmartCollar.vue | 1432 -- .../src/components/SmartCollarAlert.vue | 1014 - .../src/components/SmartEartagAlert.vue | 1060 - .../src/components/SmartHost.vue | 1071 - .../src/components/SmsLogin.vue | 618 - .../src/components/WechatFenceDrawer.vue | 1020 - .../farm-monitor-dashboard/src/main.js | 24 - .../src/pages/index/index.vue | 414 - .../src/pages/login/login.vue | 549 - .../src/router/index.js | 223 - .../src/services/alertService.js | 127 - .../src/services/ankleService.js | 149 - .../src/services/api.js | 463 - .../src/services/authService.js | 95 - .../src/services/collarService.js | 286 - .../src/services/earTagService.js | 319 - .../src/services/fenceService.js | 198 - .../src/services/homeService.js | 240 - .../src/services/hostService.js | 227 - .../src/services/smartDeviceService.js | 140 - .../src/services/smsService.js | 141 - .../src/services/userService.js | 190 - .../farm-monitor-dashboard/src/utils/auth.js | 106 - .../farm-monitor-dashboard/src/utils/index.js | 345 - .../src/utils/mapping.js | 482 - .../src/views/ElectronicFencePage.vue | 23 - .../src/views/SmartEartagAlertPage.vue | 133 - .../farm-monitor-dashboard/test-alert.html | 308 - .../farm-monitor-dashboard/test-api.html | 69 - .../farm-monitor-dashboard/test-api.js | 159 - .../farm-monitor-dashboard/test-auth.html | 42 - .../farm-monitor-dashboard/test-batch.html | 140 - .../farm-monitor-dashboard/test-collar-api.js | 150 - .../test-collar-pagination-search.js | 197 - .../test-exact-search.html | 159 - .../farm-monitor-dashboard/test-exit.html | 69 - .../test-host-number-fix.js | 86 - .../test-navigation.html | 64 - .../test-pagination-fix.js | 146 - .../farm-monitor-dashboard/test-pen.html | 99 - mini_program/farm-monitor-dashboard/uni.scss | 87 - .../farm-monitor-dashboard/utils/api.js | 17 +- .../farm-monitor-dashboard/utils/auth.js | 3 + .../farm-monitor-dashboard/vite.config.js | 26 - .../farm-monitor-dashboard/vue.config.js | 81 - .../严格按照图片设计的我的页面说明.md | 130 - .../启动生产管理页面测试.bat | 17 - .../我的页面设计说明.md | 123 - .../智能耳标预警功能完善说明.md | 110 - .../测试严格按照图片设计的我的页面.bat | 38 - .../测试我的页面功能.bat | 29 - .../测试登录页面用户协议.bat | 21 - .../测试自定义checkbox.bat | 31 - .../生产管理页面说明.md | 94 - .../用户协议checkbox最终修复方案.md | 139 - .../登录页面用户协议修复说明.md | 108 - 199 files changed, 8642 insertions(+), 52333 deletions(-) create mode 100644 .cursor/rules/project-rules.mdc create mode 100644 insurance_admin-system/public/dayjs_fix_test.html create mode 100644 insurance_admin-system/src/components/PermissionManagement.vue create mode 100644 insurance_admin-system/src/components/RolePermissionManagement.vue create mode 100644 insurance_admin-system/src/utils/dataValidator.js create mode 100644 insurance_admin-system/test_current_logs.js create mode 100644 insurance_backend/check_admin_token.js create mode 100644 insurance_backend/controllers/dashboardController.js create mode 100644 insurance_backend/controllers/permissionController.js create mode 100644 insurance_backend/controllers/rolePermissionController.js create mode 100644 insurance_backend/debug_api_response.js create mode 100644 insurance_backend/docs/API认证文档.md create mode 100644 insurance_backend/middleware/fixedTokenAuth.js create mode 100644 insurance_backend/migrations/20241220-add-fixed-token-to-users.js delete mode 100644 insurance_backend/migrations/20250122000002-update-insurance-applications.js create mode 100644 insurance_backend/migrations/20250925000001-create-permissions.js create mode 100644 insurance_backend/migrations/20250925000002-create-role-permissions.js create mode 100644 insurance_backend/migrations/20250925000003-create-menu-permissions.js create mode 100644 insurance_backend/models/MenuPermission.js create mode 100644 insurance_backend/models/Permission.js create mode 100644 insurance_backend/models/RolePermission.js create mode 100644 insurance_backend/routes/dashboard.js create mode 100644 insurance_backend/routes/permissions.js create mode 100644 insurance_backend/routes/rolePermissions.js create mode 100644 insurance_backend/scripts/fix_admin_permissions.js create mode 100644 insurance_backend/seeders/20250925000001-init-permissions.js create mode 100644 insurance_backend/src/middleware/permissionMiddleware.js create mode 100644 insurance_backend/src/services/permissionService.js create mode 100644 insurance_backend/test_fixed_token.js create mode 100644 insurance_backend/test_role_permissions_api.js delete mode 100644 mini_program/farm-monitor-dashboard/API_INTEGRATION.md delete mode 100644 mini_program/farm-monitor-dashboard/API_INTEGRATION_COMPLETE.md delete mode 100644 mini_program/farm-monitor-dashboard/API_INTEGRATION_GUIDE.md delete mode 100644 mini_program/farm-monitor-dashboard/API_INTEGRATION_UPDATE.md delete mode 100644 mini_program/farm-monitor-dashboard/API_PORT_UPDATE.md delete mode 100644 mini_program/farm-monitor-dashboard/API_SETUP.md delete mode 100644 mini_program/farm-monitor-dashboard/API_TEST_GUIDE.md delete mode 100644 mini_program/farm-monitor-dashboard/AUTH_FIX_README.md delete mode 100644 mini_program/farm-monitor-dashboard/AUTH_SOLUTION.md delete mode 100644 mini_program/farm-monitor-dashboard/AUTH_SUCCESS_REPORT.md delete mode 100644 mini_program/farm-monitor-dashboard/CATTLE_PROFILE_README.md delete mode 100644 mini_program/farm-monitor-dashboard/CATTLE_TRANSFER_ENHANCED.md delete mode 100644 mini_program/farm-monitor-dashboard/CATTLE_TRANSFER_FEATURE.md delete mode 100644 mini_program/farm-monitor-dashboard/CHINESE_MAPPING_GUIDE.md delete mode 100644 mini_program/farm-monitor-dashboard/COLLAR_API_INTEGRATION.md delete mode 100644 mini_program/farm-monitor-dashboard/COLLAR_PAGINATION_SEARCH_FEATURES.md delete mode 100644 mini_program/farm-monitor-dashboard/CONVERSION_GUIDE.md delete mode 100644 mini_program/farm-monitor-dashboard/DEBUG_API_ISSUE.md delete mode 100644 mini_program/farm-monitor-dashboard/DEPRECATION_WARNING_FIX.md delete mode 100644 mini_program/farm-monitor-dashboard/DOMAIN_CONFIG_GUIDE.md delete mode 100644 mini_program/farm-monitor-dashboard/EARTAG_CRUD_FEATURES.md delete mode 100644 mini_program/farm-monitor-dashboard/ELECTRONIC_FENCE_README.md delete mode 100644 mini_program/farm-monitor-dashboard/FIELD_MAPPING_GUIDE.md delete mode 100644 mini_program/farm-monitor-dashboard/HOST_NUMBER_FIX_REPORT.md delete mode 100644 mini_program/farm-monitor-dashboard/IMPLEMENTATION_SUMMARY.md delete mode 100644 mini_program/farm-monitor-dashboard/LOGIN_PAGE_README.md delete mode 100644 mini_program/farm-monitor-dashboard/NAVIGATION_FIX_SUMMARY.md delete mode 100644 mini_program/farm-monitor-dashboard/NAVIGATION_IMPLEMENTATION_SUMMARY.md delete mode 100644 mini_program/farm-monitor-dashboard/NETWORK_ERROR_FIX.md delete mode 100644 mini_program/farm-monitor-dashboard/PAGINATION_FIELD_MAPPING_FIX.md delete mode 100644 mini_program/farm-monitor-dashboard/PASSWORD_LOGIN_README.md delete mode 100644 mini_program/farm-monitor-dashboard/README.md delete mode 100644 mini_program/farm-monitor-dashboard/REGISTER_PAGE_README.md delete mode 100644 mini_program/farm-monitor-dashboard/ROUTER_FIX_README.md delete mode 100644 mini_program/farm-monitor-dashboard/SEARCH_FUNCTIONALITY.md delete mode 100644 mini_program/farm-monitor-dashboard/SMART_EARTAG_ALERT_README.md delete mode 100644 mini_program/farm-monitor-dashboard/SMS_LOGIN_README.md delete mode 100644 mini_program/farm-monitor-dashboard/SYNTAX_ERROR_FIX.md delete mode 100644 mini_program/farm-monitor-dashboard/TOKEN_ERROR_FIX.md delete mode 100644 mini_program/farm-monitor-dashboard/auth-test.js delete mode 100644 mini_program/farm-monitor-dashboard/auto-login.js delete mode 100644 mini_program/farm-monitor-dashboard/check-backend.js delete mode 100644 mini_program/farm-monitor-dashboard/debug-console.js delete mode 100644 mini_program/farm-monitor-dashboard/images/ICON_REQUIREMENTS.md delete mode 100644 mini_program/farm-monitor-dashboard/images/README.md delete mode 100644 mini_program/farm-monitor-dashboard/mock-api-server.js delete mode 100644 mini_program/farm-monitor-dashboard/package-lock.json delete mode 100644 mini_program/farm-monitor-dashboard/package.json create mode 100644 mini_program/farm-monitor-dashboard/pages/device/collar/collar.js create mode 100644 mini_program/farm-monitor-dashboard/pages/device/collar/collar.json create mode 100644 mini_program/farm-monitor-dashboard/pages/device/collar/collar.wxml create mode 100644 mini_program/farm-monitor-dashboard/pages/device/collar/collar.wxss delete mode 100644 mini_program/farm-monitor-dashboard/public/favicon.svg delete mode 100644 mini_program/farm-monitor-dashboard/public/index.html delete mode 100644 mini_program/farm-monitor-dashboard/set-token.js delete mode 100644 mini_program/farm-monitor-dashboard/src/App.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/app.scss delete mode 100644 mini_program/farm-monitor-dashboard/src/components/AlertTest.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/ApiTest.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/ApiTestPage.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/AuthTest.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/CattleAdd.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/CattleBatch.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/CattleExit.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/CattlePen.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/CattleProfile.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/CattleTest.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/CattleTransfer.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/CattleTransferRegister.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/EarTag.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/ElectronicFence.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/Home.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/Login.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/MapTest.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/MapView.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/PasswordLogin.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/Production.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/Profile.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/Register.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/SmartAnkle.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/SmartCollar.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/SmartCollarAlert.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/SmartEartagAlert.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/SmartHost.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/SmsLogin.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/components/WechatFenceDrawer.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/main.js delete mode 100644 mini_program/farm-monitor-dashboard/src/pages/index/index.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/pages/login/login.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/router/index.js delete mode 100644 mini_program/farm-monitor-dashboard/src/services/alertService.js delete mode 100644 mini_program/farm-monitor-dashboard/src/services/ankleService.js delete mode 100644 mini_program/farm-monitor-dashboard/src/services/api.js delete mode 100644 mini_program/farm-monitor-dashboard/src/services/authService.js delete mode 100644 mini_program/farm-monitor-dashboard/src/services/collarService.js delete mode 100644 mini_program/farm-monitor-dashboard/src/services/earTagService.js delete mode 100644 mini_program/farm-monitor-dashboard/src/services/fenceService.js delete mode 100644 mini_program/farm-monitor-dashboard/src/services/homeService.js delete mode 100644 mini_program/farm-monitor-dashboard/src/services/hostService.js delete mode 100644 mini_program/farm-monitor-dashboard/src/services/smartDeviceService.js delete mode 100644 mini_program/farm-monitor-dashboard/src/services/smsService.js delete mode 100644 mini_program/farm-monitor-dashboard/src/services/userService.js delete mode 100644 mini_program/farm-monitor-dashboard/src/utils/auth.js delete mode 100644 mini_program/farm-monitor-dashboard/src/utils/index.js delete mode 100644 mini_program/farm-monitor-dashboard/src/utils/mapping.js delete mode 100644 mini_program/farm-monitor-dashboard/src/views/ElectronicFencePage.vue delete mode 100644 mini_program/farm-monitor-dashboard/src/views/SmartEartagAlertPage.vue delete mode 100644 mini_program/farm-monitor-dashboard/test-alert.html delete mode 100644 mini_program/farm-monitor-dashboard/test-api.html delete mode 100644 mini_program/farm-monitor-dashboard/test-api.js delete mode 100644 mini_program/farm-monitor-dashboard/test-auth.html delete mode 100644 mini_program/farm-monitor-dashboard/test-batch.html delete mode 100644 mini_program/farm-monitor-dashboard/test-collar-api.js delete mode 100644 mini_program/farm-monitor-dashboard/test-collar-pagination-search.js delete mode 100644 mini_program/farm-monitor-dashboard/test-exact-search.html delete mode 100644 mini_program/farm-monitor-dashboard/test-exit.html delete mode 100644 mini_program/farm-monitor-dashboard/test-host-number-fix.js delete mode 100644 mini_program/farm-monitor-dashboard/test-navigation.html delete mode 100644 mini_program/farm-monitor-dashboard/test-pagination-fix.js delete mode 100644 mini_program/farm-monitor-dashboard/test-pen.html delete mode 100644 mini_program/farm-monitor-dashboard/uni.scss delete mode 100644 mini_program/farm-monitor-dashboard/vite.config.js delete mode 100644 mini_program/farm-monitor-dashboard/vue.config.js delete mode 100644 mini_program/farm-monitor-dashboard/严格按照图片设计的我的页面说明.md delete mode 100644 mini_program/farm-monitor-dashboard/启动生产管理页面测试.bat delete mode 100644 mini_program/farm-monitor-dashboard/我的页面设计说明.md delete mode 100644 mini_program/farm-monitor-dashboard/智能耳标预警功能完善说明.md delete mode 100644 mini_program/farm-monitor-dashboard/测试严格按照图片设计的我的页面.bat delete mode 100644 mini_program/farm-monitor-dashboard/测试我的页面功能.bat delete mode 100644 mini_program/farm-monitor-dashboard/测试登录页面用户协议.bat delete mode 100644 mini_program/farm-monitor-dashboard/测试自定义checkbox.bat delete mode 100644 mini_program/farm-monitor-dashboard/生产管理页面说明.md delete mode 100644 mini_program/farm-monitor-dashboard/用户协议checkbox最终修复方案.md delete mode 100644 mini_program/farm-monitor-dashboard/登录页面用户协议修复说明.md diff --git a/.cursor/rules/project-rules.mdc b/.cursor/rules/project-rules.mdc new file mode 100644 index 0000000..0be2489 --- /dev/null +++ b/.cursor/rules/project-rules.mdc @@ -0,0 +1,54 @@ +--- +alwaysApply: true +--- + +1. 请保持对话语言为中文 +2. 我的系统为 Windows +3. 远程服务器为centos10 64位 +4. 项目文件夹结构为: + - docs 文档目录 + - admin-system 养殖PC端管理后台目录 + - mini-program 养殖端小程序app目录 + - backend 养殖端后端服务目录 + - website 官网目录 + - insurance_backend 保险管理后台目录 + - insurance_admin-system 保险管理后台web目录 + - insurance_mini_program 保险小程序app目录 + - scripts 脚本目录 放置一些脚本,如: + - 数据库脚本 + - 部署脚本 + - 测试脚本 + - 运维脚本 +5. 整个项目入口文档为根目录下的readme.md,其他文档请放在docs目录下 +6. 请使用markdown格式编写文档,整个项目文档包括: + - 需求文档:整个项目需求文档.md 官网需求文档.md 后端管理需求文档.md 管理后台需求文档.md 小程序app需求文档.md + - 架构文档:整个项目的架构文档.md 后端架构文档.md 小程序架构文档.md 管理后台架构文档.md + - 详细设计文档: + - 数据库设计文档.md + - 管理后台接口设计文档.md + - 小程序app接口设计文档.md + - 开发文档: + - 后端开发文档.md 包含:细分到每个子任务的开发计划 + - 小程序app开发文档.md 包含:细分到每个子任务的开发计划 + - 管理后台开发文档.md 包含:细分到每个子任务的开发计划 + - 后端管理开发文档.md 包含:细分到每个子任务的开发计划 + - 测试文档.md + - 部署文档.md + - 运维文档.md + - 安全文档.md + - 用户手册文档.md +7. DB_DIALECT || 'mysql', +DB_HOST = '129.211.213.226', +DB_PORT = 9527, +DB_DATABASE = 'nxxmdata', +DB_USER = 'root', +DB_PASSWORD = 'aiotAiot123!', +8. 创建的测试文件全部都自动删除,不用我来点击删除。 +9. 遇到大模型请求次数上限时自动继续。 +10. 测试的账户为:admin 密码为:123456 +11. 项目中所有的接口都需要做好接口文档,全部都写在接口文档中,并在文档中说明请求方式、请求参数、请求示例、返回参数、返回示例等信息。 +12. 不要修改前后端端口号。发现端口占用先杀死端口,再打开,不要修改端口号。规定死养殖端的后端端口为5350,前端端口为5300. +13. 不要修改前后端端口号。发现端口占用先杀死端口,再打开,不要修改端口号。规定死保险端的后端端口为3000,前端端口为3001. +14. 每次运行命令都要先看项目规则。 +15. PowerShell不支持&&操作符,请使用;符号1. 请保持对话语言为中文 +16. 开发养殖端微信小程序时后端的API接口全部请求到https://ad.ningmuyun.com/ \ No newline at end of file diff --git a/insurance_admin-system/package.json b/insurance_admin-system/package.json index 31f0ad9..d3c08f6 100644 --- a/insurance_admin-system/package.json +++ b/insurance_admin-system/package.json @@ -21,9 +21,9 @@ "vue-router": "^4.2.4" }, "devDependencies": { - "@vitejs/plugin-vue": "^4.2.3", - "eslint": "^8.45.0", - "eslint-plugin-vue": "^9.15.1", - "vite": "^4.4.5" + "@vitejs/plugin-vue": "^4.6.2", + "eslint": "^8.57.1", + "eslint-plugin-vue": "^9.33.0", + "vite": "^4.5.14" } } diff --git a/insurance_admin-system/public/dayjs_fix_test.html b/insurance_admin-system/public/dayjs_fix_test.html new file mode 100644 index 0000000..e2950aa --- /dev/null +++ b/insurance_admin-system/public/dayjs_fix_test.html @@ -0,0 +1,157 @@ + + + + + + Dayjs 修复测试 + + + +
+

🔧 Dayjs 修复测试

+

这个页面用于测试 DataWarehouse.vue 中的 dayjs 修复是否成功。

+ + + + +
+
+ + + + \ No newline at end of file diff --git a/insurance_admin-system/src/components/Layout.vue b/insurance_admin-system/src/components/Layout.vue index 297421c..8329788 100644 --- a/insurance_admin-system/src/components/Layout.vue +++ b/insurance_admin-system/src/components/Layout.vue @@ -189,37 +189,37 @@ const fetchMenus = async () => { menus.value = [ { key: 'Dashboard', - icon: () => h(DashboardOutlined), + icon: DashboardOutlined, label: '仪表板', path: '/dashboard' }, { key: 'DataWarehouse', - icon: () => h(DatabaseOutlined), + icon: DatabaseOutlined, label: '数据览仓', path: '/dashboard' // 重定向到仪表板 }, { key: 'SupervisionTask', - icon: () => h(CheckCircleOutlined), + icon: CheckCircleOutlined, label: '监管任务', path: '/supervision-tasks' // 使用正确的复数路径 }, { key: 'PendingInstallationTask', - icon: () => h(ExclamationCircleOutlined), + icon: ExclamationCircleOutlined, label: '待安装任务', path: '/pending-installation' // 使用正确的路径 }, { key: 'CompletedTask', - icon: () => h(FileDoneOutlined), + icon: FileDoneOutlined, label: '监管任务已结项', path: '/completed-tasks' }, { key: 'InsuredCustomers', - icon: () => h(ShopOutlined), + icon: ShopOutlined, label: '投保客户单', children: [ { @@ -231,7 +231,7 @@ const fetchMenus = async () => { }, { key: 'AgriculturalInsurance', - icon: () => h(FileProtectOutlined), + icon: FileProtectOutlined, label: '生资保单', children: [ { @@ -248,7 +248,7 @@ const fetchMenus = async () => { }, { key: 'InsuranceTypeManagement', - icon: () => h(MedicineBoxOutlined), + icon: MedicineBoxOutlined, label: '险种管理', children: [ { @@ -260,7 +260,7 @@ const fetchMenus = async () => { }, { key: 'CustomerClaims', - icon: () => h(ExclamationCircleOutlined), + icon: ExclamationCircleOutlined, label: '客户理赔', children: [ { @@ -272,25 +272,25 @@ const fetchMenus = async () => { }, { key: 'Notifications', - icon: () => h(BellOutlined), + icon: BellOutlined, label: '消息通知', path: '/notifications' }, { key: 'UserManagement', - icon: () => h(UserAddOutlined), + icon: UserAddOutlined, label: '子账号管理', path: '/users' }, { key: 'SystemSettings', - icon: () => h(SettingOutlined), + icon: SettingOutlined, label: '系统设置', path: '/system-settings' }, { key: 'UserProfile', - icon: () => h(UserSwitchOutlined), + icon: UserSwitchOutlined, label: '个人中心', path: '/dashboard' // 重定向到仪表板 } diff --git a/insurance_admin-system/src/components/PermissionManagement.vue b/insurance_admin-system/src/components/PermissionManagement.vue new file mode 100644 index 0000000..1592b81 --- /dev/null +++ b/insurance_admin-system/src/components/PermissionManagement.vue @@ -0,0 +1,527 @@ + + + + + \ No newline at end of file diff --git a/insurance_admin-system/src/components/RolePermissionManagement.vue b/insurance_admin-system/src/components/RolePermissionManagement.vue new file mode 100644 index 0000000..830292f --- /dev/null +++ b/insurance_admin-system/src/components/RolePermissionManagement.vue @@ -0,0 +1,525 @@ + + + + + \ No newline at end of file diff --git a/insurance_admin-system/src/stores/user.js b/insurance_admin-system/src/stores/user.js index 393b1c1..8e69cd5 100644 --- a/insurance_admin-system/src/stores/user.js +++ b/insurance_admin-system/src/stores/user.js @@ -1,213 +1,207 @@ import { defineStore } from 'pinia' import { ref, computed } from 'vue' -import axios from 'axios' export const useUserStore = defineStore('user', () => { - // 兼容旧版本的token存储 - const accessToken = ref(localStorage.getItem('accessToken') || localStorage.getItem('token')) - const refreshToken = ref(localStorage.getItem('refreshToken')) - const userInfo = ref(JSON.parse(localStorage.getItem('userInfo') || '{}')) - const tokenExpiresAt = ref(localStorage.getItem('tokenExpiresAt')) + // 状态 + const accessToken = ref(localStorage.getItem('accessToken') || '') + const refreshToken = ref(localStorage.getItem('refreshToken') || '') + const userInfo = ref(JSON.parse(localStorage.getItem('userInfo') || 'null')) + const tokenExpiresAt = ref(parseInt(localStorage.getItem('tokenExpiresAt') || '0')) + + // 防抖更新localStorage + let updateTimer = null + const debouncedUpdateStorage = (key, value) => { + clearTimeout(updateTimer) + updateTimer = setTimeout(() => { + if (value === null || value === undefined || value === '') { + localStorage.removeItem(key) + } else { + localStorage.setItem(key, typeof value === 'object' ? JSON.stringify(value) : value) + } + }, 100) + } + + // 计算属性 - 使用缓存避免重复计算 + const isTokenExpired = computed(() => { + if (!tokenExpiresAt.value) return true + return Date.now() >= tokenExpiresAt.value + }) - // 计算属性:检查token是否即将过期(提前5分钟刷新) const isTokenExpiringSoon = computed(() => { if (!tokenExpiresAt.value) return false - const expiresAt = new Date(tokenExpiresAt.value) - const now = new Date() - const fiveMinutesFromNow = new Date(now.getTime() + 5 * 60 * 1000) - return expiresAt <= fiveMinutesFromNow + const fiveMinutes = 5 * 60 * 1000 + return Date.now() >= (tokenExpiresAt.value - fiveMinutes) }) - // 计算属性:检查token是否已过期 - const isTokenExpired = computed(() => { - if (!tokenExpiresAt.value) return false - const expiresAt = new Date(tokenExpiresAt.value) - const now = new Date() - return expiresAt <= now + const isLoggedIn = computed(() => { + return !!accessToken.value && !isTokenExpired.value }) - - // 设置访问令牌 - const setAccessToken = (newToken) => { - accessToken.value = newToken - localStorage.setItem('accessToken', newToken) - // 兼容旧版本 - localStorage.setItem('token', newToken) - } - - // 设置刷新令牌 - const setRefreshToken = (newRefreshToken) => { - refreshToken.value = newRefreshToken - localStorage.setItem('refreshToken', newRefreshToken) - } - - // 设置令牌过期时间 - const setTokenExpiresAt = (expiresIn) => { - const expiresAt = new Date(Date.now() + expiresIn * 1000) - tokenExpiresAt.value = expiresAt.toISOString() - localStorage.setItem('tokenExpiresAt', expiresAt.toISOString()) - } - - // 设置完整的认证信息 + + // Actions const setAuthData = (authData) => { - if (authData.accessToken) { - setAccessToken(authData.accessToken) + if (!authData) return + + const { accessToken: newAccessToken, refreshToken: newRefreshToken, user, expiresIn } = authData + + // 批量更新状态,避免多次触发响应式更新 + const updates = [] + + if (newAccessToken && newAccessToken !== accessToken.value) { + accessToken.value = newAccessToken + updates.push(['accessToken', newAccessToken]) } - if (authData.refreshToken) { - setRefreshToken(authData.refreshToken) + + if (newRefreshToken && newRefreshToken !== refreshToken.value) { + refreshToken.value = newRefreshToken + updates.push(['refreshToken', newRefreshToken]) } - if (authData.accessTokenExpiresIn) { - setTokenExpiresAt(authData.accessTokenExpiresIn) + + if (user && JSON.stringify(user) !== JSON.stringify(userInfo.value)) { + userInfo.value = user + updates.push(['userInfo', user]) } - if (authData.user) { - setUserInfo(authData.user) - } - } - - const setUserInfo = (info) => { - userInfo.value = info - localStorage.setItem('userInfo', JSON.stringify(info)) - } - - // Token刷新方法 - const refreshAccessToken = async () => { - try { - if (!refreshToken.value) { - throw new Error('没有刷新令牌') + + if (expiresIn) { + const newExpiresAt = Date.now() + (expiresIn * 1000) + if (newExpiresAt !== tokenExpiresAt.value) { + tokenExpiresAt.value = newExpiresAt + updates.push(['tokenExpiresAt', newExpiresAt]) } - - const response = await axios.post('/api/auth/refresh', { - refreshToken: refreshToken.value + } + + // 批量更新localStorage + updates.forEach(([key, value]) => { + debouncedUpdateStorage(key, value) + }) + } + + const logout = () => { + // 清除状态 + accessToken.value = '' + refreshToken.value = '' + userInfo.value = null + tokenExpiresAt.value = 0 + + // 清除localStorage + const keysToRemove = ['accessToken', 'refreshToken', 'userInfo', 'tokenExpiresAt'] + keysToRemove.forEach(key => localStorage.removeItem(key)) + } + + // 刷新访问令牌 + const refreshAccessToken = async () => { + if (!refreshToken.value) { + throw new Error('没有刷新令牌') + } + + try { + const response = await fetch('http://localhost:3000/api/auth/refresh', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + refreshToken: refreshToken.value + }) }) - - if (response.data.success) { - const authData = response.data.data + + if (!response.ok) { + throw new Error('刷新令牌失败') + } + + const data = await response.json() + + // 修复:检查响应格式,支持多种成功状态 + if (data.status === 'success' || data.code === 200 || data.success) { + const authData = data.data || data setAuthData(authData) + console.log('令牌刷新成功') return authData.accessToken } else { - throw new Error(response.data.message || '刷新令牌失败') + throw new Error(data.message || '刷新令牌失败') } } catch (error) { - console.error('刷新令牌失败:', error) - // 刷新失败,清除所有认证信息 + console.error('刷新访问令牌失败:', error) logout() throw error } } - // 自动刷新令牌(如果需要的话) - const ensureValidToken = async () => { - if (!accessToken.value) { - throw new Error('没有访问令牌') - } - - if (isTokenExpired.value) { - // Token已过期,尝试刷新 - return await refreshAccessToken() - } else if (isTokenExpiringSoon.value) { - // Token即将过期,主动刷新 - try { - return await refreshAccessToken() - } catch (error) { - // 刷新失败但当前token还未过期,继续使用当前token - console.warn('主动刷新失败,继续使用当前token:', error) - return accessToken.value - } - } - - return accessToken.value - } - - // 自动重新登录(委托给认证服务) + // 自动重新登录方法 const autoRelogin = async () => { - // 导入认证服务(避免循环依赖) - const { default: authService } = await import('@/services/authService') - return authService.autoRelogin() - } - - // 获取保存的登录凭据 - const getSavedCredentials = () => { try { - // 检查是否有有效的refresh token + // 首先尝试使用refresh token刷新 if (refreshToken.value) { - return { - refreshToken: refreshToken.value + try { + await refreshAccessToken() + return true + } catch (error) { + console.warn('使用refresh token刷新失败,尝试其他方式:', error) } } - // 可以在这里添加其他类型的保存凭据检查 - // 例如:记住的用户名、设备指纹等 + // 检查是否有记住的登录信息 + const rememberedUsername = localStorage.getItem('rememberedUsername') + const rememberLogin = localStorage.getItem('rememberLogin') === 'true' - return null - } catch (error) { - console.error('获取保存的登录凭据失败:', error) - return null - } - } - - // 获取用户信息 - const fetchUserInfo = async () => { - try { - // 动态导入API以避免循环依赖 - const { authAPI } = await import('@/utils/api') - const response = await authAPI.getProfile() - - if (response.data && response.data.status === 'success') { - const userData = response.data.data - setUserInfo(userData) - return userData - } else { - throw new Error(response.data?.message || '获取用户信息失败') + if (rememberedUsername && rememberLogin) { + // 这里可以实现使用记住的凭据自动登录 + // 但出于安全考虑,通常不会保存密码 + console.log('检测到记住的用户名,但需要用户重新输入密码') } + + return false } catch (error) { - console.error('获取用户信息失败:', error) - throw error + console.error('自动重新登录失败:', error) + return false } } - - const logout = () => { - accessToken.value = null - refreshToken.value = null - userInfo.value = {} - tokenExpiresAt.value = null - localStorage.removeItem('accessToken') - localStorage.removeItem('refreshToken') - localStorage.removeItem('userInfo') - localStorage.removeItem('tokenExpiresAt') - // 兼容旧版本 - localStorage.removeItem('token') + + // 确保token有效 + const ensureValidToken = async () => { + if (!accessToken.value) { + return null + } + + // 如果token已过期,尝试刷新 + if (isTokenExpired.value) { + try { + return await refreshAccessToken() + } catch (error) { + return null + } + } + + // 如果token即将过期(5分钟内),提前刷新 + if (isTokenExpiringSoon.value) { + try { + return await refreshAccessToken() + } catch (error) { + // 刷新失败,但当前token仍然有效,继续使用 + console.warn('提前刷新token失败,继续使用当前token:', error) + return accessToken.value + } + } + + return accessToken.value } - - // 兼容旧版本的方法 - const setToken = (newToken) => { - setAccessToken(newToken) - } - - const token = computed(() => accessToken.value) - + return { - // 新的双Token属性 + // 状态 accessToken, refreshToken, userInfo, tokenExpiresAt, - isTokenExpiringSoon, - isTokenExpired, - // 新的方法 - setAccessToken, - setRefreshToken, - setTokenExpiresAt, + // 计算属性 + isTokenExpired, + isTokenExpiringSoon, + isLoggedIn, + + // 方法 setAuthData, + logout, refreshAccessToken, ensureValidToken, - autoRelogin, - getSavedCredentials, - fetchUserInfo, - - // 兼容旧版本的属性和方法 - token, - setToken, - setUserInfo, - logout + autoRelogin } }) \ No newline at end of file diff --git a/insurance_admin-system/src/utils/api.js b/insurance_admin-system/src/utils/api.js index 648dbdf..46945f7 100644 --- a/insurance_admin-system/src/utils/api.js +++ b/insurance_admin-system/src/utils/api.js @@ -25,7 +25,7 @@ export const userAPI = { export const menuAPI = { getMenus: async () => { - const response = await api.get('/menus/public'); + const response = await api.get('/menus'); return response.data; // 返回响应的data部分 }, getAllMenus: async () => { @@ -70,8 +70,9 @@ export const claimAPI = { } export const dashboardAPI = { - getStats: () => api.get('/system/stats'), - getRecentActivities: () => api.get('/system/logs?limit=10') + getStats: () => api.get('/dashboard/stats'), + getRecentActivities: () => api.get('/dashboard/recent-activities'), + getChartData: (params) => api.get('/dashboard/chart-data', { params }) } // 设备预警API @@ -160,4 +161,40 @@ export const operationLogAPI = { export: (params) => api.get('/operation-logs/export', { params }) } +// 权限管理API +export const permissionAPI = { + getList: (params) => api.get('/permissions', { params }), + create: (data) => api.post('/permissions', data), + update: (id, data) => api.put(`/permissions/${id}`, data), + delete: (id) => api.delete(`/permissions/${id}`), + getTree: () => api.get('/permissions/tree'), + getRolePermissions: (roleId) => api.get(`/permissions/roles/${roleId}`) +} + +// 角色权限管理API +export const rolePermissionAPI = { + // 获取所有角色及其权限 + getAllRolesWithPermissions: () => api.get('/role-permissions/roles'), + + // 获取所有权限 + getAllPermissions: () => api.get('/role-permissions/permissions'), + + // 获取指定角色的详细权限信息 + getRolePermissions: (roleId) => api.get(`/role-permissions/roles/${roleId}`), + + // 批量分配角色权限 + assignRolePermissions: (roleId, data) => api.post(`/role-permissions/roles/${roleId}/assign`, data), + + // 复制角色权限 + copyRolePermissions: (sourceRoleId, targetRoleId, mode) => + api.post(`/role-permissions/roles/${sourceRoleId}/copy/${targetRoleId}`, { mode }), + + // 检查用户权限 + checkUserPermission: (userId, permissionCode) => + api.get(`/role-permissions/users/${userId}/check/${permissionCode}`), + + // 获取权限统计 + getPermissionStats: () => api.get('/role-permissions/stats') +} + export default api \ No newline at end of file diff --git a/insurance_admin-system/src/utils/dataValidator.js b/insurance_admin-system/src/utils/dataValidator.js new file mode 100644 index 0000000..a69ad04 --- /dev/null +++ b/insurance_admin-system/src/utils/dataValidator.js @@ -0,0 +1,119 @@ +/** + * 数据验证工具 + * 用于确保 API 响应数据的一致性和安全性 + */ + +/** + * 验证并确保数据是数组 + * @param {any} data - 需要验证的数据 + * @param {string} context - 上下文信息,用于日志记录 + * @returns {Array} 确保返回数组 + */ +export const ensureArray = (data, context = 'unknown') => { + if (Array.isArray(data)) { + return data + } + + console.warn(`[DataValidator] ${context}: 期望数组但收到`, typeof data, data) + return [] +} + +/** + * 验证 API 响应格式 + * @param {Object} response - API 响应对象 + * @param {string} context - 上下文信息 + * @returns {Object} 标准化的响应对象 + */ +export const validateApiResponse = (response, context = 'API') => { + if (!response) { + console.warn(`[DataValidator] ${context}: 响应为空`) + return { data: [], pagination: null } + } + + // 检查响应是否有 data 字段 + if (!response.hasOwnProperty('data')) { + console.warn(`[DataValidator] ${context}: 响应缺少 data 字段`, response) + return { data: [], pagination: null } + } + + return { + data: response.data, + pagination: response.pagination || null, + message: response.message || '', + code: response.code || 200 + } +} + +/** + * 验证并处理列表数据 + * @param {Object} response - API 响应 + * @param {string} context - 上下文信息 + * @returns {Object} 包含验证后的数据和分页信息 + */ +export const validateListResponse = (response, context = 'List API') => { + const validatedResponse = validateApiResponse(response, context) + + return { + data: ensureArray(validatedResponse.data, context), + pagination: validatedResponse.pagination, + message: validatedResponse.message, + code: validatedResponse.code + } +} + +/** + * 验证分页信息 + * @param {Object} pagination - 分页对象 + * @returns {Object} 标准化的分页对象 + */ +export const validatePagination = (pagination) => { + if (!pagination || typeof pagination !== 'object') { + return { + page: 1, + limit: 10, + total: 0, + totalPages: 0 + } + } + + return { + page: parseInt(pagination.page) || 1, + limit: parseInt(pagination.limit) || 10, + total: parseInt(pagination.total) || 0, + totalPages: parseInt(pagination.totalPages) || 0 + } +} + +/** + * 安全的数据访问器 + * @param {Object} obj - 对象 + * @param {string} path - 属性路径,如 'data.list' + * @param {any} defaultValue - 默认值 + * @returns {any} 安全访问的值 + */ +export const safeGet = (obj, path, defaultValue = null) => { + try { + const keys = path.split('.') + let result = obj + + for (const key of keys) { + if (result === null || result === undefined) { + return defaultValue + } + result = result[key] + } + + return result !== undefined ? result : defaultValue + } catch (error) { + console.warn(`[DataValidator] safeGet 访问路径 "${path}" 失败:`, error) + return defaultValue + } +} + +export default { + ensureArray, + validateApiResponse, + validateListResponse, + validatePagination, + safeGet +} \ No newline at end of file diff --git a/insurance_admin-system/src/utils/request.js b/insurance_admin-system/src/utils/request.js index 7c03cff..0974758 100644 --- a/insurance_admin-system/src/utils/request.js +++ b/insurance_admin-system/src/utils/request.js @@ -1,19 +1,22 @@ -import axios from 'axios' import { useUserStore } from '@/stores/user' import { message, Modal } from 'ant-design-vue' import router from '@/router' -// 创建axios实例 -const request = axios.create({ +// API基础配置 +const API_CONFIG = { baseURL: 'http://localhost:3000/api', timeout: 10000 -}) +} // 是否正在刷新token的标志 let isRefreshing = false // 存储待重试的请求 let failedQueue = [] +// 请求缓存 +const requestCache = new Map() +const CACHE_DURATION = 5 * 60 * 1000 // 5分钟缓存 + // 处理队列中的请求 const processQueue = (error, token = null) => { failedQueue.forEach(({ resolve, reject }) => { @@ -27,49 +30,134 @@ const processQueue = (error, token = null) => { failedQueue = [] } -// 请求拦截器 -request.interceptors.request.use( - async (config) => { - const userStore = useUserStore() - - // 对于登录、刷新token和公开接口,跳过token检查 - const skipTokenCheck = config.url?.includes('/auth/login') || - config.url?.includes('/auth/refresh') || - config.url?.includes('/auth/register') || - config.url?.includes('/menus/public') - - if (!skipTokenCheck) { - try { - // 确保token有效(自动刷新如果需要) - const validToken = await userStore.ensureValidToken() - - if (validToken) { - config.headers.Authorization = `Bearer ${validToken}` - } - } catch (error) { - console.error('获取有效token失败:', error) - // 如果无法获取有效token,继续发送请求,让响应拦截器处理 - } - } - - return config - }, - (error) => { - return Promise.reject(error) - } -) +// 生成缓存键 +const generateCacheKey = (url, options) => { + return `${url}_${JSON.stringify(options)}` +} -// 响应拦截器 -request.interceptors.response.use( - (response) => { - return response - }, - async (error) => { - const userStore = useUserStore() - const originalRequest = error.config +// 检查缓存 +const checkCache = (cacheKey) => { + const cached = requestCache.get(cacheKey) + if (cached && Date.now() - cached.timestamp < CACHE_DURATION) { + return cached.data + } + return null +} + +// 设置缓存 +const setCache = (cacheKey, data) => { + requestCache.set(cacheKey, { + data, + timestamp: Date.now() + }) +} + +/** + * 创建请求头 + * @param {Object} customHeaders - 自定义请求头 + * @returns {Object} 请求头对象 + */ +const createHeaders = (customHeaders = {}) => { + const userStore = useUserStore() + const token = userStore.accessToken || localStorage.getItem('accessToken') + + const defaultHeaders = { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Cache-Control': 'no-cache', + 'Pragma': 'no-cache' + } + + if (token) { + defaultHeaders['Authorization'] = `Bearer ${token}` + } + + return { ...defaultHeaders, ...customHeaders } +} + +/** + * 处理fetch响应 + * @param {Response} response - fetch响应对象 + * @returns {Promise} 处理后的响应数据 + */ +const handleResponse = async (response) => { + let data + + try { + const contentType = response.headers.get('content-type') + if (contentType && contentType.includes('application/json')) { + data = await response.json() + } else { + data = await response.text() + } + } catch (error) { + data = null + } + + if (!response.ok) { + const error = new Error(data?.message || `HTTP ${response.status}: ${response.statusText}`) + error.response = { + status: response.status, + statusText: response.statusText, + data: data + } + throw error + } + + return { data, status: response.status, statusText: response.statusText } +} + +/** + * 基于fetch的请求方法 + * @param {string} url - 请求URL + * @param {Object} options - 请求选项 + * @returns {Promise} 请求结果 + */ +const fetchRequest = async (url, options = {}) => { + const userStore = useUserStore() + + // 构建完整URL + const fullUrl = url.startsWith('http') ? url : `${API_CONFIG.baseURL}${url}` + + // 对于登录、刷新token接口,跳过token检查 + const skipTokenCheck = url.includes('/auth/login') || + url.includes('/auth/refresh') || + url.includes('/auth/register') + + if (!skipTokenCheck) { + try { + // 确保token有效(自动刷新如果需要) + const validToken = await userStore.ensureValidToken() + + if (validToken) { + options.headers = { + ...options.headers, + 'Authorization': `Bearer ${validToken}` + } + } + } catch (error) { + console.error('获取有效token失败:', error) + // 如果无法获取有效token,继续发送请求,让响应处理器处理 + } + } + + // 设置默认请求头 + options.headers = createHeaders(options.headers) + + // 设置超时 + const controller = new AbortController() + const timeoutId = setTimeout(() => controller.abort(), API_CONFIG.timeout) + options.signal = controller.signal + + try { + const response = await fetch(fullUrl, options) + clearTimeout(timeoutId) + return await handleResponse(response) + } catch (error) { + clearTimeout(timeoutId) - // 如果是401错误且不是刷新token的请求 - if (error.response?.status === 401 && !originalRequest._retry) { + // 处理401错误 + if (error.response?.status === 401) { const errorCode = error.response?.data?.code // 如果是token过期错误 @@ -79,14 +167,13 @@ request.interceptors.response.use( return new Promise((resolve, reject) => { failedQueue.push({ resolve, reject }) }).then(token => { - originalRequest.headers.Authorization = `Bearer ${token}` - return request(originalRequest) + options.headers['Authorization'] = `Bearer ${token}` + return fetchRequest(url, options) }).catch(err => { return Promise.reject(err) }) } - originalRequest._retry = true isRefreshing = true try { @@ -97,8 +184,8 @@ request.interceptors.response.use( processQueue(null, newToken) // 重试原始请求 - originalRequest.headers.Authorization = `Bearer ${newToken}` - return request(originalRequest) + options.headers['Authorization'] = `Bearer ${newToken}` + return fetchRequest(url, options) } catch (refreshError) { // 刷新失败,处理队列并跳转到登录页 processQueue(refreshError, null) @@ -131,18 +218,61 @@ request.interceptors.response.use( // 处理其他错误 if (error.response?.data?.message) { message.error(error.response.data.message) - } else if (error.message) { + } else if (error.message && !error.message.includes('aborted')) { message.error(error.message) } - return Promise.reject(error) + throw error } -) +} + +/** + * 创建类似axios的API接口 + */ +const request = { + get: (url, config = {}) => { + return fetchRequest(url, { + method: 'GET', + ...config + }) + }, + + post: (url, data = null, config = {}) => { + return fetchRequest(url, { + method: 'POST', + body: data ? JSON.stringify(data) : null, + ...config + }) + }, + + put: (url, data = null, config = {}) => { + return fetchRequest(url, { + method: 'PUT', + body: data ? JSON.stringify(data) : null, + ...config + }) + }, + + delete: (url, config = {}) => { + return fetchRequest(url, { + method: 'DELETE', + ...config + }) + }, + + patch: (url, data = null, config = {}) => { + return fetchRequest(url, { + method: 'PATCH', + body: data ? JSON.stringify(data) : null, + ...config + }) + } +} // 自动重新登录功能 export const autoRelogin = async (username, password) => { try { - const response = await axios.post('http://localhost:3000/api/auth/login', { + const response = await request.post('/auth/login', { username, password }) @@ -194,6 +324,6 @@ export const setupTokenExpirationWarning = () => { }, 60000) // 每分钟检查一次 } -// 导出默认的axios实例和别名 +// 导出默认的请求实例和别名 export default request export const apiClient = request \ No newline at end of file diff --git a/insurance_admin-system/src/views/ApplicationManagement.vue b/insurance_admin-system/src/views/ApplicationManagement.vue index 052aeb6..272e291 100644 --- a/insurance_admin-system/src/views/ApplicationManagement.vue +++ b/insurance_admin-system/src/views/ApplicationManagement.vue @@ -325,9 +325,10 @@ @@ -398,11 +356,17 @@ onMounted(() => { .ant-statistic-content { font-size: 20px; + font-weight: bold; } -.ant-descriptions-item-content pre { - margin: 0; +.ant-descriptions-item-label { + font-weight: bold; +} + +pre { + background-color: #f5f5f5; + padding: 8px; + border-radius: 4px; font-size: 12px; - line-height: 1.4; } \ No newline at end of file diff --git a/insurance_admin-system/test_current_logs.js b/insurance_admin-system/test_current_logs.js new file mode 100644 index 0000000..a69a194 --- /dev/null +++ b/insurance_admin-system/test_current_logs.js @@ -0,0 +1,62 @@ +import axios from 'axios'; + +async function testCurrentLogs() { + try { + console.log('🔐 先登录获取token...'); + + // 登录获取token + const loginResponse = await axios.post('http://localhost:3000/api/auth/login', { + username: 'admin', + password: '123456' + }); + + const token = loginResponse.data.data.accessToken; + console.log('✅ 登录成功,获取到token'); + + console.log('🔍 测试当前日志API...'); + + // 测试系统日志API + const logsResponse = await axios.get('http://localhost:3000/api/system/logs', { + headers: { + 'Authorization': `Bearer ${token}` + }, + params: { + page: 1, + limit: 10 + } + }); + + console.log('📊 日志API响应状态:', logsResponse.status); + console.log('📋 日志数据:', JSON.stringify(logsResponse.data, null, 2)); + console.log('📈 日志总数:', logsResponse.data.data?.pagination?.total || 0); + console.log('📄 当前页日志数量:', logsResponse.data.data?.logs?.length || 0); + + // 测试仪表板统计API + const statsResponse = await axios.get('http://localhost:3000/api/dashboard/stats', { + headers: { + 'Authorization': `Bearer ${token}` + } + }); + console.log('\n📊 仪表板统计响应状态:', statsResponse.status); + console.log('📋 统计数据:', JSON.stringify(statsResponse.data, null, 2)); + + // 测试最近活动API + const activitiesResponse = await axios.get('http://localhost:3000/api/dashboard/recent-activities', { + headers: { + 'Authorization': `Bearer ${token}` + } + }); + console.log('\n📊 最近活动响应状态:', activitiesResponse.status); + console.log('📋 活动数据:', JSON.stringify(activitiesResponse.data, null, 2)); + console.log('📈 活动总数:', activitiesResponse.data.data?.length || 0); + + } catch (error) { + console.error('❌ 测试失败:', error.message); + if (error.response) { + console.error('错误状态:', error.response.status); + console.error('错误数据:', error.response.data); + } + } +} + +testCurrentLogs().catch(console.error); \ No newline at end of file diff --git a/insurance_backend/check_admin_token.js b/insurance_backend/check_admin_token.js new file mode 100644 index 0000000..4e55016 --- /dev/null +++ b/insurance_backend/check_admin_token.js @@ -0,0 +1,27 @@ +const { User } = require('./models'); + +async function checkAdminToken() { + try { + const admin = await User.findOne({ + where: { username: 'admin' }, + attributes: ['id', 'username', 'fixed_token', 'status'] + }); + + if (admin) { + console.log('Admin用户信息:'); + console.log('ID:', admin.id); + console.log('用户名:', admin.username); + console.log('Token:', admin.fixed_token); + console.log('状态:', admin.status); + } else { + console.log('未找到admin用户'); + } + + process.exit(0); + } catch (error) { + console.error('错误:', error.message); + process.exit(1); + } +} + +checkAdminToken(); \ No newline at end of file diff --git a/insurance_backend/config/swagger.js b/insurance_backend/config/swagger.js index 4ae310c..d2c2c63 100644 --- a/insurance_backend/config/swagger.js +++ b/insurance_backend/config/swagger.js @@ -30,7 +30,14 @@ const swaggerDefinition = { bearerAuth: { type: 'http', scheme: 'bearer', - bearerFormat: 'JWT' + bearerFormat: 'JWT', + description: 'JWT令牌认证' + }, + fixedTokenAuth: { + type: 'apiKey', + in: 'header', + name: 'Authorization', + description: '固定令牌认证,格式:Bearer ' } }, schemas: { @@ -42,6 +49,7 @@ const swaggerDefinition = { email: { type: 'string', description: '邮箱' }, phone: { type: 'string', description: '手机号' }, status: { type: 'string', enum: ['active', 'inactive'], description: '用户状态' }, + fixed_token: { type: 'string', description: '固定令牌(用于API访问验证)', nullable: true }, createdAt: { type: 'string', format: 'date-time', description: '创建时间' }, updatedAt: { type: 'string', format: 'date-time', description: '更新时间' } } @@ -214,6 +222,21 @@ const swaggerDefinition = { message: { type: 'string', description: '错误信息' }, timestamp: { type: 'string', format: 'date-time', description: '时间戳' } } + }, + FixedTokenInfo: { + type: 'object', + properties: { + hasToken: { type: 'boolean', description: '是否已生成固定令牌' }, + tokenPreview: { type: 'string', description: '令牌预览(仅显示前8位)', nullable: true }, + createdAt: { type: 'string', format: 'date-time', description: '令牌创建时间', nullable: true } + } + }, + FixedTokenGenerated: { + type: 'object', + properties: { + token: { type: 'string', description: '生成的固定令牌(仅在生成时返回完整令牌)' }, + message: { type: 'string', description: '操作结果信息' } + } } }, responses: { @@ -248,6 +271,22 @@ const swaggerDefinition = { } } } + }, + ForbiddenError: { + description: '权限不足', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/Error' + }, + example: { + code: 403, + status: 'error', + message: '权限不足', + timestamp: '2024-01-01T00:00:00.000Z' + } + } + } } } }, diff --git a/insurance_backend/controllers/dashboardController.js b/insurance_backend/controllers/dashboardController.js new file mode 100644 index 0000000..c92a810 --- /dev/null +++ b/insurance_backend/controllers/dashboardController.js @@ -0,0 +1,295 @@ +const { Op, sequelize } = require('sequelize'); +const { sequelize: dbSequelize } = require('../config/database'); +const User = require('../models/User'); +const InsuranceApplication = require('../models/InsuranceApplication'); +const Policy = require('../models/Policy'); +const Claim = require('../models/Claim'); +const OperationLog = require('../models/OperationLog'); + +/** + * 获取仪表板统计数据 + */ +const getStats = async (req, res) => { + try { + console.log('获取仪表板统计数据...'); + + // 获取今日日期范围 + const today = new Date(); + const startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate()); + const endOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1); + + // 获取本月日期范围 + const startOfMonth = new Date(today.getFullYear(), today.getMonth(), 1); + const endOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 1); + + // 并行查询各种统计数据 + const [ + totalApplications, + todayApplications, + monthApplications, + totalPolicies, + activePolicies, + totalClaims, + pendingClaims, + totalUsers, + recentActivities + ] = await Promise.all([ + // 总申请数 + InsuranceApplication.count(), + + // 今日申请数 + InsuranceApplication.count({ + where: { + created_at: { + [Op.gte]: startOfDay, + [Op.lt]: endOfDay + } + } + }), + + // 本月申请数 + InsuranceApplication.count({ + where: { + created_at: { + [Op.gte]: startOfMonth, + [Op.lt]: endOfMonth + } + } + }), + + // 总保单数 + Policy.count(), + + // 有效保单数 + Policy.count({ + where: { + policy_status: 'active' + } + }), + + // 总理赔数 + Claim.count(), + + // 待处理理赔数 + Claim.count({ + where: { + claim_status: 'pending' + } + }), + + // 总用户数 + User.count(), + + // 最近活动(从系统日志获取) + OperationLog.findAll({ + limit: 10, + order: [['created_at', 'DESC']], + attributes: ['id', 'operation_type', 'operation_content', 'created_at', 'user_id'] + }) + ]); + + // 计算增长率(简化计算,实际应该与上一期间对比) + const applicationGrowthRate = todayApplications > 0 ? + ((todayApplications / Math.max(monthApplications - todayApplications, 1)) * 100).toFixed(1) : 0; + + const policyGrowthRate = activePolicies > 0 ? + ((activePolicies / Math.max(totalPolicies - activePolicies, 1)) * 100).toFixed(1) : 0; + + const statsData = { + // 核心指标 + totalApplications, + todayApplications, + monthApplications, + applicationGrowthRate: parseFloat(applicationGrowthRate), + + totalPolicies, + activePolicies, + policyGrowthRate: parseFloat(policyGrowthRate), + + totalClaims, + pendingClaims, + claimProcessingRate: totalClaims > 0 ? + (((totalClaims - pendingClaims) / totalClaims) * 100).toFixed(1) : 0, + + totalUsers, + + // 快速统计 + quickStats: { + newApplicationsToday: todayApplications, + pendingReviews: pendingClaims, + activeUsers: totalUsers, // 简化处理,实际应该查询活跃用户 + systemAlerts: 0 // 简化处理,实际应该查询系统告警 + } + }; + + console.log('统计数据获取成功:', statsData); + + res.json({ + code: 200, + status: 'success', + data: statsData, + message: '获取仪表板统计数据成功', + timestamp: new Date().toISOString() + }); + + } catch (error) { + console.error('获取仪表板统计数据失败:', error); + res.status(500).json({ + code: 500, + status: 'error', + data: null, + message: '获取仪表板统计数据失败', + timestamp: new Date().toISOString() + }); + } +}; + +/** + * 获取最近活动 + */ +const getRecentActivities = async (req, res) => { + try { + console.log('获取最近活动数据...'); + + const { limit = 20 } = req.query; + + // 从系统日志获取最近活动 + const activities = await OperationLog.findAll({ + limit: parseInt(limit), + order: [['created_at', 'DESC']], + attributes: ['id', 'operation_type', 'operation_content', 'created_at', 'user_id'] + }); + + // 格式化活动数据 + const formattedActivities = activities.map(activity => ({ + id: activity.id, + type: activity.operation_type, + title: activity.operation_content, + description: `操作用户: ${activity.user_id || '系统'}`, + timestamp: activity.created_at, + user: activity.user_id, + level: activity.operation_type + })); + + console.log(`获取到 ${formattedActivities.length} 条最近活动`); + + res.json({ + code: 200, + status: 'success', + data: formattedActivities, + message: '获取最近活动成功', + timestamp: new Date().toISOString() + }); + + } catch (error) { + console.error('获取最近活动失败:', error); + res.status(500).json({ + code: 500, + status: 'error', + data: null, + message: '获取最近活动失败', + timestamp: new Date().toISOString() + }); + } +}; + +/** + * 获取图表数据 + */ +const getChartData = async (req, res) => { + try { + console.log('获取图表数据...'); + + const { type = 'applications', period = '7d' } = req.query; + + let startDate; + const endDate = new Date(); + + // 根据时间周期设置开始日期 + switch (period) { + case '7d': + startDate = new Date(endDate.getTime() - 7 * 24 * 60 * 60 * 1000); + break; + case '30d': + startDate = new Date(endDate.getTime() - 30 * 24 * 60 * 60 * 1000); + break; + case '90d': + startDate = new Date(endDate.getTime() - 90 * 24 * 60 * 60 * 1000); + break; + default: + startDate = new Date(endDate.getTime() - 7 * 24 * 60 * 60 * 1000); + } + + let chartData = []; + + if (type === 'applications') { + // 获取申请数据趋势 + const applications = await InsuranceApplication.findAll({ + where: { + created_at: { + [Op.gte]: startDate, + [Op.lte]: endDate + } + }, + attributes: [ + [dbSequelize.fn('DATE', dbSequelize.col('created_at')), 'date'], + [dbSequelize.fn('COUNT', dbSequelize.col('id')), 'count'] + ], + group: [dbSequelize.fn('DATE', dbSequelize.col('created_at'))], + order: [[dbSequelize.fn('DATE', dbSequelize.col('created_at')), 'ASC']] + }); + + chartData = applications.map(item => ({ + date: item.dataValues.date, + value: parseInt(item.dataValues.count) + })); + } else if (type === 'policies') { + // 获取保单数据趋势 + const policies = await Policy.findAll({ + where: { + created_at: { + [Op.gte]: startDate, + [Op.lte]: endDate + } + }, + attributes: [ + [dbSequelize.fn('DATE', dbSequelize.col('created_at')), 'date'], + [dbSequelize.fn('COUNT', dbSequelize.col('id')), 'count'] + ], + group: [dbSequelize.fn('DATE', dbSequelize.col('created_at'))], + order: [[dbSequelize.fn('DATE', dbSequelize.col('created_at')), 'ASC']] + }); + + chartData = policies.map(item => ({ + date: item.dataValues.date, + value: parseInt(item.dataValues.count) + })); + } + + console.log(`获取到 ${chartData.length} 条图表数据`); + + res.json({ + code: 200, + status: 'success', + data: chartData, + message: '获取图表数据成功', + timestamp: new Date().toISOString() + }); + + } catch (error) { + console.error('获取图表数据失败:', error); + res.status(500).json({ + code: 500, + status: 'error', + data: null, + message: '获取图表数据失败', + timestamp: new Date().toISOString() + }); + } +}; + +module.exports = { + getStats, + getRecentActivities, + getChartData +}; \ No newline at end of file diff --git a/insurance_backend/controllers/dataWarehouseController.js b/insurance_backend/controllers/dataWarehouseController.js index d96ce0c..50cfa8a 100644 --- a/insurance_backend/controllers/dataWarehouseController.js +++ b/insurance_backend/controllers/dataWarehouseController.js @@ -4,6 +4,9 @@ const { Op, Sequelize } = require('sequelize'); // 获取数据仓库概览 const getOverview = async (req, res) => { try { + // 获取总用户数 + const totalUsers = await User.count(); + // 获取总申请数 const totalApplications = await InsuranceApplication.count(); @@ -43,6 +46,7 @@ const getOverview = async (req, res) => { res.json({ success: true, data: { + totalUsers, totalApplications, totalPolicies, totalClaims, diff --git a/insurance_backend/controllers/insuranceTypeController.js b/insurance_backend/controllers/insuranceTypeController.js index 2580fc9..5782e30 100644 --- a/insurance_backend/controllers/insuranceTypeController.js +++ b/insurance_backend/controllers/insuranceTypeController.js @@ -23,12 +23,10 @@ const getInsuranceTypes = async (req, res) => { order: [['created_at', 'DESC']] }); - res.json(responseFormat.success({ - list: rows, - total: count, + res.json(responseFormat.pagination(rows, { page: parseInt(page), - pageSize: parseInt(pageSize), - pages: Math.ceil(count / pageSize) + limit: parseInt(pageSize), + total: count }, '获取险种列表成功')); } catch (error) { console.error('获取险种列表错误:', error); diff --git a/insurance_backend/controllers/permissionController.js b/insurance_backend/controllers/permissionController.js new file mode 100644 index 0000000..946d7e1 --- /dev/null +++ b/insurance_backend/controllers/permissionController.js @@ -0,0 +1,415 @@ +const { Permission, Role, Menu, RolePermission, MenuPermission } = require('../models'); +const responseFormat = require('../utils/response'); +const { Op } = require('sequelize'); + +/** + * 构建权限树形结构 + */ +function buildPermissionTree(permissions, parentId = null) { + const tree = []; + + for (const permission of permissions) { + if (permission.parent_id === parentId) { + const children = buildPermissionTree(permissions, permission.id); + const node = { + ...permission.toJSON(), + children: children.length > 0 ? children : undefined + }; + tree.push(node); + } + } + + return tree; +} + +/** + * 权限管理控制器 + */ +class PermissionController { + /** + * 获取权限列表 + */ + async getPermissions(req, res) { + try { + const { + page = 1, + limit = 10, + module, + type, + status = 'active', + keyword + } = req.query; + + const offset = (page - 1) * limit; + const where = { status }; + + // 模块筛选 + if (module) { + where.module = module; + } + + // 类型筛选 + if (type) { + where.type = type; + } + + // 关键词搜索 + if (keyword) { + where[Op.or] = [ + { name: { [Op.like]: `%${keyword}%` } }, + { code: { [Op.like]: `%${keyword}%` } }, + { description: { [Op.like]: `%${keyword}%` } } + ]; + } + + const { count, rows } = await Permission.findAndCountAll({ + where, + include: [ + { + model: Permission, + as: 'parent', + attributes: ['id', 'name', 'code'] + }, + { + model: Permission, + as: 'children', + attributes: ['id', 'name', 'code', 'type'] + } + ], + order: [['sort_order', 'ASC'], ['id', 'ASC']], + limit: parseInt(limit), + offset: parseInt(offset) + }); + + res.json(responseFormat.success({ + permissions: rows, + pagination: { + total: count, + page: parseInt(page), + limit: parseInt(limit), + pages: Math.ceil(count / limit) + } + }, '获取权限列表成功')); + } catch (error) { + console.error('获取权限列表失败:', error); + res.status(500).json(responseFormat.error('获取权限列表失败')); + } + } + + /** + * 获取权限树形结构 + */ + async getPermissionTree(req, res) { + try { + const { module, type } = req.query; + const where = { status: 'active' }; + + if (module) { + where.module = module; + } + + if (type) { + where.type = type; + } + + const permissions = await Permission.findAll({ + where, + order: [['sort_order', 'ASC'], ['id', 'ASC']] + }); + + // 构建树形结构 + const tree = buildPermissionTree(permissions); + + res.json(responseFormat.success(tree, '获取权限树成功')); + } catch (error) { + console.error('获取权限树失败:', error); + res.status(500).json(responseFormat.error('获取权限树失败')); + } + } + + /** + * 获取单个权限详情 + */ + async getPermissionById(req, res) { + try { + const { id } = req.params; + + const permission = await Permission.findByPk(id, { + include: [ + { + model: Permission, + as: 'parent', + attributes: ['id', 'name', 'code'] + }, + { + model: Permission, + as: 'children', + attributes: ['id', 'name', 'code', 'type'] + } + ] + }); + + if (!permission) { + return res.status(404).json(responseFormat.error('权限不存在')); + } + + res.json(responseFormat.success(permission, '获取权限详情成功')); + } catch (error) { + console.error('获取权限详情失败:', error); + res.status(500).json(responseFormat.error('获取权限详情失败')); + } + } + + /** + * 创建权限 + */ + async createPermission(req, res) { + try { + const { + name, + code, + description, + module, + type = 'operation', + parent_id, + sort_order = 0 + } = req.body; + + // 验证必填字段 + if (!name || !code || !module) { + return res.status(400).json(responseFormat.error('权限名称、权限代码和所属模块为必填项')); + } + + // 检查权限代码是否已存在 + const existingPermission = await Permission.findOne({ where: { code } }); + if (existingPermission) { + return res.status(400).json(responseFormat.error('权限代码已存在')); + } + + // 如果有父权限,验证父权限是否存在 + if (parent_id) { + const parentPermission = await Permission.findByPk(parent_id); + if (!parentPermission) { + return res.status(400).json(responseFormat.error('父权限不存在')); + } + } + + const permission = await Permission.create({ + name, + code, + description, + module, + type, + parent_id, + sort_order, + status: 'active' + }); + + res.status(201).json(responseFormat.created(permission, '创建权限成功')); + } catch (error) { + console.error('创建权限失败:', error); + res.status(500).json(responseFormat.error('创建权限失败')); + } + } + + /** + * 更新权限 + */ + async updatePermission(req, res) { + try { + const { id } = req.params; + const { + name, + code, + description, + module, + type, + parent_id, + sort_order, + status + } = req.body; + + const permission = await Permission.findByPk(id); + if (!permission) { + return res.status(404).json(responseFormat.error('权限不存在')); + } + + // 如果修改了权限代码,检查是否与其他权限冲突 + if (code && code !== permission.code) { + const existingPermission = await Permission.findOne({ + where: { + code, + id: { [Op.ne]: id } + } + }); + if (existingPermission) { + return res.status(400).json(responseFormat.error('权限代码已存在')); + } + } + + // 如果有父权限,验证父权限是否存在且不是自己 + if (parent_id) { + if (parent_id == id) { + return res.status(400).json(responseFormat.error('不能将自己设为父权限')); + } + const parentPermission = await Permission.findByPk(parent_id); + if (!parentPermission) { + return res.status(400).json(responseFormat.error('父权限不存在')); + } + } + + await permission.update({ + name: name || permission.name, + code: code || permission.code, + description: description !== undefined ? description : permission.description, + module: module || permission.module, + type: type || permission.type, + parent_id: parent_id !== undefined ? parent_id : permission.parent_id, + sort_order: sort_order !== undefined ? sort_order : permission.sort_order, + status: status || permission.status + }); + + res.json(responseFormat.success(permission, '更新权限成功')); + } catch (error) { + console.error('更新权限失败:', error); + res.status(500).json(responseFormat.error('更新权限失败')); + } + } + + /** + * 删除权限 + */ + async deletePermission(req, res) { + try { + const { id } = req.params; + + const permission = await Permission.findByPk(id); + if (!permission) { + return res.status(404).json(responseFormat.error('权限不存在')); + } + + // 检查是否有子权限 + const childrenCount = await Permission.count({ where: { parent_id: id } }); + if (childrenCount > 0) { + return res.status(400).json(responseFormat.error('该权限下还有子权限,无法删除')); + } + + // 检查是否有角色在使用该权限 + const rolePermissionCount = await RolePermission.count({ where: { permission_id: id } }); + if (rolePermissionCount > 0) { + return res.status(400).json(responseFormat.error('该权限正在被角色使用,无法删除')); + } + + // 检查是否有菜单在使用该权限 + const menuPermissionCount = await MenuPermission.count({ where: { permission_id: id } }); + if (menuPermissionCount > 0) { + return res.status(400).json(responseFormat.error('该权限正在被菜单使用,无法删除')); + } + + await permission.destroy(); + + res.json(responseFormat.success(null, '删除权限成功')); + } catch (error) { + console.error('删除权限失败:', error); + res.status(500).json(responseFormat.error('删除权限失败')); + } + } + + /** + * 获取角色权限 + */ + async getRolePermissions(req, res) { + try { + const { roleId } = req.params; + + const role = await Role.findByPk(roleId, { + include: [ + { + model: Permission, + as: 'rolePermissions', + through: { + attributes: ['granted'] + } + } + ] + }); + + if (!role) { + return res.status(404).json(responseFormat.error('角色不存在')); + } + + res.json(responseFormat.success({ + role: { + id: role.id, + name: role.name, + description: role.description + }, + permissions: role.rolePermissions + }, '获取角色权限成功')); + } catch (error) { + console.error('获取角色权限失败:', error); + res.status(500).json(responseFormat.error('获取角色权限失败')); + } + } + + /** + * 分配角色权限 + */ + async assignRolePermissions(req, res) { + try { + const { roleId } = req.params; + const { permissionIds } = req.body; + + if (!Array.isArray(permissionIds)) { + return res.status(400).json(responseFormat.error('权限ID列表格式错误')); + } + + const role = await Role.findByPk(roleId); + if (!role) { + return res.status(404).json(responseFormat.error('角色不存在')); + } + + // 删除现有的角色权限关联 + await RolePermission.destroy({ where: { role_id: roleId } }); + + // 创建新的角色权限关联 + if (permissionIds.length > 0) { + const rolePermissions = permissionIds.map(permissionId => ({ + role_id: roleId, + permission_id: permissionId, + granted: true + })); + + await RolePermission.bulkCreate(rolePermissions); + } + + res.json(responseFormat.success(null, '分配角色权限成功')); + } catch (error) { + console.error('分配角色权限失败:', error); + res.status(500).json(responseFormat.error('分配角色权限失败')); + } + } + + /** + * 获取模块列表 + */ + async getModules(req, res) { + try { + const modules = await Permission.findAll({ + attributes: ['module'], + group: ['module'], + order: [['module', 'ASC']] + }); + + const moduleList = modules.map(item => item.module); + + res.json(responseFormat.success(moduleList, '获取模块列表成功')); + } catch (error) { + console.error('获取模块列表失败:', error); + res.status(500).json(responseFormat.error('获取模块列表失败')); + } + } + +} + +module.exports = new PermissionController(); \ No newline at end of file diff --git a/insurance_backend/controllers/rolePermissionController.js b/insurance_backend/controllers/rolePermissionController.js new file mode 100644 index 0000000..659bf6f --- /dev/null +++ b/insurance_backend/controllers/rolePermissionController.js @@ -0,0 +1,420 @@ +const { Role, Permission, RolePermission, User } = require('../models'); +const responseFormat = require('../utils/response'); +const { Op } = require('sequelize'); + +/** + * 角色权限管理控制器 + * 专门处理角色权限的分配、管理和动态调用 + */ +class RolePermissionController { + + /** + * 获取所有角色及其权限 + */ + async getAllRolesWithPermissions(req, res) { + try { + const roles = await Role.findAll({ + order: [['id', 'ASC']] + }); + + const rolesData = roles.map(role => { + let permissions = []; + if (Array.isArray(role.permissions)) { + permissions = role.permissions; + } else if (typeof role.permissions === 'string') { + try { + permissions = JSON.parse(role.permissions); + } catch (e) { + permissions = []; + } + } + + return { + id: role.id, + name: role.name, + description: role.description, + status: role.status, + permissions: permissions, + permissionCount: permissions.length + }; + }); + + res.json(responseFormat.success({ + roles: rolesData, + total: rolesData.length + }, '获取角色权限列表成功')); + } catch (error) { + console.error('获取角色权限列表失败:', error); + res.status(500).json(responseFormat.error('获取角色权限列表失败')); + } + } + + /** + * 获取所有权限 + */ + async getAllPermissions(req, res) { + try { + const permissions = await Permission.findAll({ + order: [['id', 'ASC']] + }); + + res.json(responseFormat.success(permissions, '获取权限列表成功')); + } catch (error) { + console.error('获取权限列表失败:', error); + res.status(500).json(responseFormat.error('获取权限列表失败')); + } + } + + /** + * 获取指定角色的权限详情 + */ + async getRolePermissionDetail(req, res) { + try { + const { roleId } = req.params; + + const role = await Role.findByPk(roleId); + + if (!role) { + return res.status(404).json(responseFormat.error('角色不存在')); + } + + // 获取所有权限用于对比 + const allPermissions = await Permission.findAll({ + attributes: ['id', 'name', 'code', 'description', 'module', 'type', 'parent_id'], + order: [['module', 'ASC'], ['id', 'ASC']] + }); + + // 构建权限树结构 + const controller = this; + const permissionTree = controller.buildPermissionTree(allPermissions); + + // 获取角色已分配的权限代码 + let assignedPermissionCodes = []; + if (Array.isArray(role.permissions)) { + assignedPermissionCodes = role.permissions; + } else if (typeof role.permissions === 'string') { + try { + assignedPermissionCodes = JSON.parse(role.permissions); + } catch (e) { + assignedPermissionCodes = []; + } + } + + // 标记已分配的权限 + const markedPermissions = controller.markAssignedPermissionsByCode(permissionTree, assignedPermissionCodes); + + res.json(responseFormat.success({ + role: { + id: role.id, + name: role.name, + description: role.description, + status: role.status + }, + assignedPermissions: assignedPermissionCodes, + allPermissions: markedPermissions, + assignedCount: assignedPermissionCodes.length, + totalCount: allPermissions.length + }, '获取角色权限详情成功')); + } catch (error) { + console.error('获取角色权限详情失败:', error); + res.status(500).json(responseFormat.error('获取角色权限详情失败')); + } + } + + /** + * 批量分配角色权限 + */ + async batchAssignPermissions(req, res) { + try { + const { roleId } = req.params; + const { permissionIds, operation = 'replace' } = req.body; + + if (!Array.isArray(permissionIds)) { + return res.status(400).json(responseFormat.error('权限ID列表格式错误')); + } + + const role = await Role.findByPk(roleId); + if (!role) { + return res.status(404).json(responseFormat.error('角色不存在')); + } + + // 验证权限ID是否存在 + const validPermissions = await Permission.findAll({ + where: { id: { [Op.in]: permissionIds } }, + attributes: ['id'] + }); + + const validPermissionIds = validPermissions.map(p => p.id); + const invalidIds = permissionIds.filter(id => !validPermissionIds.includes(id)); + + if (invalidIds.length > 0) { + return res.status(400).json(responseFormat.error(`无效的权限ID: ${invalidIds.join(', ')}`)); + } + + // 根据操作类型处理权限分配 + if (operation === 'replace') { + // 替换模式:删除现有权限,添加新权限 + await RolePermission.destroy({ where: { role_id: roleId } }); + + if (permissionIds.length > 0) { + const rolePermissions = permissionIds.map(permissionId => ({ + role_id: roleId, + permission_id: permissionId, + granted: true + })); + await RolePermission.bulkCreate(rolePermissions); + } + } else if (operation === 'add') { + // 添加模式:只添加新权限 + const existingPermissions = await RolePermission.findAll({ + where: { role_id: roleId }, + attributes: ['permission_id'] + }); + const existingIds = existingPermissions.map(p => p.permission_id); + const newPermissionIds = permissionIds.filter(id => !existingIds.includes(id)); + + if (newPermissionIds.length > 0) { + const rolePermissions = newPermissionIds.map(permissionId => ({ + role_id: roleId, + permission_id: permissionId, + granted: true + })); + await RolePermission.bulkCreate(rolePermissions); + } + } else if (operation === 'remove') { + // 移除模式:删除指定权限 + await RolePermission.destroy({ + where: { + role_id: roleId, + permission_id: { [Op.in]: permissionIds } + } + }); + } + + res.json(responseFormat.success(null, `${operation === 'replace' ? '替换' : operation === 'add' ? '添加' : '移除'}角色权限成功`)); + } catch (error) { + console.error('批量分配角色权限失败:', error); + res.status(500).json(responseFormat.error('批量分配角色权限失败')); + } + } + + /** + * 复制角色权限 + */ + async copyRolePermissions(req, res) { + try { + const { sourceRoleId, targetRoleId } = req.body; + + if (!sourceRoleId || !targetRoleId) { + return res.status(400).json(responseFormat.error('源角色ID和目标角色ID不能为空')); + } + + if (sourceRoleId === targetRoleId) { + return res.status(400).json(responseFormat.error('源角色和目标角色不能相同')); + } + + // 验证角色存在 + const [sourceRole, targetRole] = await Promise.all([ + Role.findByPk(sourceRoleId), + Role.findByPk(targetRoleId) + ]); + + if (!sourceRole) { + return res.status(404).json(responseFormat.error('源角色不存在')); + } + if (!targetRole) { + return res.status(404).json(responseFormat.error('目标角色不存在')); + } + + // 获取源角色的权限 + const sourcePermissions = await RolePermission.findAll({ + where: { role_id: sourceRoleId }, + attributes: ['permission_id'] + }); + + // 删除目标角色现有权限 + await RolePermission.destroy({ where: { role_id: targetRoleId } }); + + // 复制权限到目标角色 + if (sourcePermissions.length > 0) { + const targetPermissions = sourcePermissions.map(p => ({ + role_id: targetRoleId, + permission_id: p.permission_id, + granted: true + })); + await RolePermission.bulkCreate(targetPermissions); + } + + res.json(responseFormat.success(null, `成功将 ${sourceRole.name} 的权限复制到 ${targetRole.name}`)); + } catch (error) { + console.error('复制角色权限失败:', error); + res.status(500).json(responseFormat.error('复制角色权限失败')); + } + } + + /** + * 检查用户权限 + */ + async checkUserPermission(req, res) { + try { + const { userId, permissionCode } = req.params; + + const user = await User.findByPk(userId, { + include: [ + { + model: Role, + as: 'role', + include: [ + { + model: Permission, + as: 'rolePermissions', + where: { code: permissionCode }, + required: false, + through: { + attributes: ['granted'] + } + } + ] + } + ] + }); + + if (!user) { + return res.status(404).json(responseFormat.error('用户不存在')); + } + + const hasPermission = user.role && + user.role.rolePermissions && + user.role.rolePermissions.length > 0 && + user.role.rolePermissions[0].RolePermission.granted; + + res.json(responseFormat.success({ + userId: user.id, + username: user.username, + roleName: user.role ? user.role.name : null, + permissionCode, + hasPermission, + checkTime: new Date() + }, '权限检查完成')); + } catch (error) { + console.error('检查用户权限失败:', error); + res.status(500).json(responseFormat.error('检查用户权限失败')); + } + } + + /** + * 获取权限统计信息 + */ + async getPermissionStats(req, res) { + try { + // 统计各种数据 + const [ + totalRoles, + totalPermissions, + moduleStats, + roles + ] = await Promise.all([ + Role.count(), + Permission.count(), + Permission.findAll({ + attributes: [ + 'module', + [Permission.sequelize.fn('COUNT', Permission.sequelize.col('id')), 'count'] + ], + group: ['module'], + order: [['module', 'ASC']] + }), + Role.findAll({ + attributes: ['id', 'name', 'permissions'], + order: [['name', 'ASC']] + }) + ]); + + // 计算总分配数和角色权限分布 + let totalAssignments = 0; + const roleDistribution = roles.map(role => { + let permissions = []; + if (Array.isArray(role.permissions)) { + permissions = role.permissions; + } else if (typeof role.permissions === 'string') { + try { + permissions = JSON.parse(role.permissions); + } catch (e) { + permissions = []; + } + } + + const permissionCount = permissions.length; + totalAssignments += permissionCount; + return { + roleId: role.id, + roleName: role.name, + permissionCount + }; + }); + + res.json(responseFormat.success({ + overview: { + totalRoles, + totalPermissions, + totalAssignments, + averagePermissionsPerRole: totalRoles > 0 ? Math.round(totalAssignments / totalRoles) : 0 + }, + moduleDistribution: moduleStats.map(stat => ({ + module: stat.module, + count: parseInt(stat.dataValues.count) + })), + roleDistribution + }, '获取权限统计成功')); + } catch (error) { + console.error('获取权限统计失败:', error); + res.status(500).json(responseFormat.error('获取权限统计失败')); + } + } + + /** + * 构建权限树 + */ + buildPermissionTree(permissions, parentId = null) { + const tree = []; + for (const permission of permissions) { + if (permission.parent_id === parentId) { + const children = this.buildPermissionTree(permissions, permission.id); + const node = { + ...(permission.toJSON ? permission.toJSON() : permission), + children: children.length > 0 ? children : undefined + }; + tree.push(node); + } + } + return tree; + } + + /** + * 标记已分配的权限 + */ + markAssignedPermissions(permissions, assignedIds) { + return permissions.map(permission => ({ + ...permission, + assigned: assignedIds.includes(permission.id), + children: permission.children ? + this.markAssignedPermissions(permission.children, assignedIds) : + undefined + })); + } + + /** + * 根据权限代码标记已分配的权限 + */ + markAssignedPermissionsByCode(permissions, assignedCodes) { + return permissions.map(permission => ({ + ...permission, + assigned: assignedCodes.includes(permission.code), + children: permission.children ? + this.markAssignedPermissionsByCode(permission.children, assignedCodes) : + undefined + })); + } +} + +module.exports = new RolePermissionController(); \ No newline at end of file diff --git a/insurance_backend/controllers/systemController.js b/insurance_backend/controllers/systemController.js index 06c3a93..b32cbdd 100644 --- a/insurance_backend/controllers/systemController.js +++ b/insurance_backend/controllers/systemController.js @@ -77,7 +77,7 @@ const getSystemLogs = async (req, res) => { const { page = 1, limit = 50, level, start_date, end_date } = req.query; const offset = (page - 1) * limit; - // 模拟日志数据 + // 模拟日志数据 - 扩展更多有意义的日志记录 const mockLogs = [ { id: 1, @@ -96,9 +96,93 @@ const getSystemLogs = async (req, res) => { { id: 3, level: 'warning', - message: 'Redis连接失败', + message: 'Redis连接失败,使用内存缓存', timestamp: new Date(Date.now() - 1000 * 120).toISOString(), user: 'system' + }, + { + id: 4, + level: 'info', + message: '用户 admin 登录成功', + timestamp: new Date(Date.now() - 1000 * 180).toISOString(), + user: 'admin' + }, + { + id: 5, + level: 'info', + message: '新增保险申请:车险申请 - 申请人:张三', + timestamp: new Date(Date.now() - 1000 * 240).toISOString(), + user: 'zhangsan' + }, + { + id: 6, + level: 'info', + message: '保单生效:保单号 POL-2024-001 - 投保人:李四', + timestamp: new Date(Date.now() - 1000 * 300).toISOString(), + user: 'lisi' + }, + { + id: 7, + level: 'warning', + message: '理赔申请待审核:理赔号 CLM-2024-001 - 申请人:王五', + timestamp: new Date(Date.now() - 1000 * 360).toISOString(), + user: 'wangwu' + }, + { + id: 8, + level: 'info', + message: '新用户注册:用户名 zhaoliu', + timestamp: new Date(Date.now() - 1000 * 420).toISOString(), + user: 'system' + }, + { + id: 9, + level: 'error', + message: '支付接口调用失败:订单号 ORD-2024-001', + timestamp: new Date(Date.now() - 1000 * 480).toISOString(), + user: 'system' + }, + { + id: 10, + level: 'info', + message: '保险类型更新:新增意外险产品', + timestamp: new Date(Date.now() - 1000 * 540).toISOString(), + user: 'admin' + }, + { + id: 11, + level: 'info', + message: '系统备份完成:数据库备份成功', + timestamp: new Date(Date.now() - 1000 * 600).toISOString(), + user: 'system' + }, + { + id: 12, + level: 'warning', + message: '磁盘空间不足警告:剩余空间 15%', + timestamp: new Date(Date.now() - 1000 * 660).toISOString(), + user: 'system' + }, + { + id: 13, + level: 'info', + message: '理赔审核通过:理赔号 CLM-2024-002 - 赔付金额 ¥5000', + timestamp: new Date(Date.now() - 1000 * 720).toISOString(), + user: 'admin' + }, + { + id: 14, + level: 'info', + message: '保单续费成功:保单号 POL-2024-002 - 续费期限 1年', + timestamp: new Date(Date.now() - 1000 * 780).toISOString(), + user: 'system' + }, + { + id: 15, + level: 'error', + message: '短信发送失败:手机号 138****8888', + timestamp: new Date(Date.now() - 1000 * 840).toISOString(), + user: 'system' } ]; @@ -125,7 +209,7 @@ const getSystemLogs = async (req, res) => { page: parseInt(page), limit: parseInt(limit), total: filteredLogs.length, - pages: Math.ceil(filteredLogs.length / limit) + pages: Math.ceil(filteredLogs.length / parseInt(limit)) } }, '获取系统日志成功')); } catch (error) { diff --git a/insurance_backend/controllers/userController.js b/insurance_backend/controllers/userController.js index c2a8963..638b279 100644 --- a/insurance_backend/controllers/userController.js +++ b/insurance_backend/controllers/userController.js @@ -1,6 +1,7 @@ const { User, Role } = require('../models'); const { Op } = require('sequelize'); const responseFormat = require('../utils/response'); +const crypto = require('crypto'); // 获取用户列表 const getUsers = async (req, res) => { @@ -379,6 +380,112 @@ const uploadAvatar = async (req, res) => { } }; +// 生成固定token +const generateFixedToken = async (req, res) => { + try { + const { id } = req.params; + + const user = await User.findByPk(id); + if (!user) { + return res.status(404).json(responseFormat.error('用户不存在')); + } + + // 生成32位随机token + const fixedToken = crypto.randomBytes(32).toString('hex'); + + // 更新用户的固定token + await user.update({ fixed_token: fixedToken }); + + res.json(responseFormat.success({ + fixed_token: fixedToken, + user_id: user.id, + username: user.username + }, '固定Token生成成功')); + } catch (error) { + console.error('生成固定Token错误:', error); + if (error.name === 'SequelizeUniqueConstraintError') { + return res.status(400).json(responseFormat.error('Token生成失败,请重试')); + } + res.status(500).json(responseFormat.error('生成固定Token失败')); + } +}; + +// 重新生成固定token +const regenerateFixedToken = async (req, res) => { + try { + const { id } = req.params; + + const user = await User.findByPk(id); + if (!user) { + return res.status(404).json(responseFormat.error('用户不存在')); + } + + // 生成新的32位随机token + const newFixedToken = crypto.randomBytes(32).toString('hex'); + + // 更新用户的固定token + await user.update({ fixed_token: newFixedToken }); + + res.json(responseFormat.success({ + fixed_token: newFixedToken, + user_id: user.id, + username: user.username + }, '固定Token重新生成成功')); + } catch (error) { + console.error('重新生成固定Token错误:', error); + if (error.name === 'SequelizeUniqueConstraintError') { + return res.status(400).json(responseFormat.error('Token生成失败,请重试')); + } + res.status(500).json(responseFormat.error('重新生成固定Token失败')); + } +}; + +// 删除固定token +const deleteFixedToken = async (req, res) => { + try { + const { id } = req.params; + + const user = await User.findByPk(id); + if (!user) { + return res.status(404).json(responseFormat.error('用户不存在')); + } + + // 清除用户的固定token + await user.update({ fixed_token: null }); + + res.json(responseFormat.success(null, '固定Token删除成功')); + } catch (error) { + console.error('删除固定Token错误:', error); + res.status(500).json(responseFormat.error('删除固定Token失败')); + } +}; + +// 获取用户的固定token信息 +const getFixedTokenInfo = async (req, res) => { + try { + const { id } = req.params; + + const user = await User.findByPk(id, { + attributes: ['id', 'username', 'fixed_token'] + }); + + if (!user) { + return res.status(404).json(responseFormat.error('用户不存在')); + } + + res.json(responseFormat.success({ + userId: user.id, + username: user.username, + hasToken: !!user.fixed_token, + tokenPreview: user.fixed_token ? `${user.fixed_token.substring(0, 8)}...` : null, + createdAt: user.fixed_token ? new Date().toISOString() : null + }, '获取固定Token信息成功')); + } catch (error) { + console.error('获取固定Token信息错误:', error); + res.status(500).json(responseFormat.error('获取固定Token信息失败')); + } +}; + module.exports = { getUsers, getUser, @@ -389,5 +496,9 @@ module.exports = { getProfile, updateProfile, changePassword, - uploadAvatar + uploadAvatar, + generateFixedToken, + regenerateFixedToken, + deleteFixedToken, + getFixedTokenInfo }; \ No newline at end of file diff --git a/insurance_backend/debug_api_response.js b/insurance_backend/debug_api_response.js new file mode 100644 index 0000000..e0c6120 --- /dev/null +++ b/insurance_backend/debug_api_response.js @@ -0,0 +1,73 @@ +const axios = require('axios'); + +const BASE_URL = 'http://localhost:3000/api'; +const ADMIN_TOKEN = '5659725423f665a8bf5053b37e624ea86387f9113ae77ac75fc102012a349180'; + +// 创建axios实例 +const api = axios.create({ + baseURL: BASE_URL, + headers: { + 'Authorization': `Bearer ${ADMIN_TOKEN}`, + 'Content-Type': 'application/json' + } +}); + +async function debugAPIResponse() { + console.log('调试API响应格式...\n'); + + try { + console.log('测试获取所有角色及其权限...'); + const response = await api.get('/role-permissions/roles'); + console.log('完整响应:', JSON.stringify(response.data, null, 2)); + console.log('数据路径检查:'); + console.log('- response.data:', typeof response.data); + console.log('- response.data.data:', typeof response.data.data); + + // 尝试解析data字段 + let parsedData = response.data.data; + if (typeof parsedData === 'string') { + try { + parsedData = JSON.parse(parsedData); + console.log('- 解析后的data:', typeof parsedData); + console.log('- 解析后的data.roles:', typeof parsedData?.roles); + console.log('- 解析后的data.roles 是数组吗:', Array.isArray(parsedData?.roles)); + if (parsedData?.roles) { + console.log('- 角色数量:', parsedData.roles.length); + } + } catch (e) { + console.log('- 无法解析data字段:', e.message); + } + } else { + console.log('- response.data.data.roles:', typeof response.data.data?.roles); + console.log('- response.data.data.roles 是数组吗:', Array.isArray(response.data.data?.roles)); + if (response.data.data?.roles) { + console.log('- 角色数量:', response.data.data.roles.length); + } + } + } catch (error) { + console.log('错误:', { + code: error.response?.status, + status: error.response?.data?.status, + data: error.response?.data?.data, + message: error.response?.data?.message, + }); + } + + try { + console.log('\n测试获取特定角色的详细权限...'); + const response = await api.get('/role-permissions/roles/1/permissions'); + console.log('完整响应:', JSON.stringify(response.data, null, 2)); + } catch (error) { + console.log('错误:', error.response?.data || error.message); + } + + try { + console.log('\n测试权限统计...'); + const response = await api.get('/role-permissions/stats'); + console.log('完整响应:', JSON.stringify(response.data, null, 2)); + } catch (error) { + console.log('错误:', error.response?.data || error.message); + } +} + +debugAPIResponse().catch(console.error); \ No newline at end of file diff --git a/insurance_backend/docs/API认证文档.md b/insurance_backend/docs/API认证文档.md new file mode 100644 index 0000000..667a68b --- /dev/null +++ b/insurance_backend/docs/API认证文档.md @@ -0,0 +1,222 @@ +# API认证文档 + +## 概述 + +保险端口系统API支持两种认证方式: +1. **JWT令牌认证**:用于Web应用的用户会话认证 +2. **固定令牌认证**:用于API访问的长期认证 + +## 认证方式 + +### 1. JWT令牌认证 + +#### 获取JWT令牌 +```http +POST /auth/login +Content-Type: application/json + +{ + "username": "admin", + "password": "123456" +} +``` + +#### 响应示例 +```json +{ + "code": 200, + "status": "success", + "data": { + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "user": { + "id": 1, + "username": "admin", + "email": "admin@example.com" + } + } +} +``` + +#### 使用JWT令牌 +在请求头中添加Authorization字段: +```http +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +### 2. 固定令牌认证 + +#### 生成固定令牌 +管理员可以为用户生成固定令牌: +```http +POST /users/{id}/fixed-token +Authorization: Bearer +``` + +#### 响应示例 +```json +{ + "code": 200, + "status": "success", + "data": { + "token": "ft_1234567890abcdef1234567890abcdef12345678", + "message": "固定令牌生成成功" + } +} +``` + +#### 使用固定令牌 +在请求头中添加Authorization字段: +```http +Authorization: Bearer ft_1234567890abcdef1234567890abcdef12345678 +``` + +## 固定令牌管理 + +### 获取令牌信息 +```http +GET /users/{id}/fixed-token +Authorization: Bearer +``` + +### 重新生成令牌 +```http +PUT /users/{id}/fixed-token +Authorization: Bearer +``` + +### 删除令牌 +```http +DELETE /users/{id}/fixed-token +Authorization: Bearer +``` + +## 权限控制 + +### 权限模型 +系统采用基于角色的权限控制(RBAC),每个用户都有一个角色,角色包含多个权限。 + +### 权限格式 +权限格式为:`资源:操作` +- `user:read` - 读取用户信息 +- `user:create` - 创建用户 +- `user:update` - 更新用户信息 +- `user:delete` - 删除用户 + +### 常用权限列表 +| 权限 | 描述 | +|------|------| +| `user:read` | 查看用户信息 | +| `user:create` | 创建用户 | +| `user:update` | 更新用户信息 | +| `user:delete` | 删除用户 | +| `insurance_applications:read` | 查看保险申请 | +| `insurance_applications:create` | 创建保险申请 | +| `insurance_applications:update` | 更新保险申请 | +| `insurance_applications:delete` | 删除保险申请 | +| `policies:read` | 查看保单 | +| `policies:create` | 创建保单 | +| `policies:update` | 更新保单 | +| `policies:delete` | 删除保单 | +| `claims:read` | 查看理赔 | +| `claims:create` | 创建理赔 | +| `claims:update` | 更新理赔 | +| `claims:delete` | 删除理赔 | + +## 错误响应 + +### 401 未授权 +```json +{ + "code": 401, + "status": "error", + "message": "未授权访问", + "timestamp": "2024-01-01T00:00:00.000Z" +} +``` + +### 403 权限不足 +```json +{ + "code": 403, + "status": "error", + "message": "权限不足", + "timestamp": "2024-01-01T00:00:00.000Z" +} +``` + +### 令牌过期 +```json +{ + "code": 401, + "status": "error", + "message": "令牌已过期", + "timestamp": "2024-01-01T00:00:00.000Z" +} +``` + +## 安全注意事项 + +### JWT令牌 +1. JWT令牌有效期为24小时 +2. 令牌包含用户信息和权限 +3. 令牌在服务器端无法撤销,只能等待过期 + +### 固定令牌 +1. 固定令牌永不过期,除非手动删除 +2. 固定令牌具有与用户相同的权限 +3. 固定令牌应妥善保管,避免泄露 +4. 建议定期更换固定令牌 + +### 最佳实践 +1. 在生产环境中使用HTTPS +2. 定期轮换固定令牌 +3. 监控API访问日志 +4. 及时撤销不再使用的令牌 +5. 使用最小权限原则 + +## 示例代码 + +### JavaScript (Axios) +```javascript +// 使用JWT令牌 +const jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'; +const response = await axios.get('/users', { + headers: { + 'Authorization': `Bearer ${jwtToken}` + } +}); + +// 使用固定令牌 +const fixedToken = 'ft_1234567890abcdef1234567890abcdef12345678'; +const response = await axios.get('/users', { + headers: { + 'Authorization': `Bearer ${fixedToken}` + } +}); +``` + +### Python (requests) +```python +import requests + +# 使用JWT令牌 +jwt_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' +headers = {'Authorization': f'Bearer {jwt_token}'} +response = requests.get('http://localhost:3000/users', headers=headers) + +# 使用固定令牌 +fixed_token = 'ft_1234567890abcdef1234567890abcdef12345678' +headers = {'Authorization': f'Bearer {fixed_token}'} +response = requests.get('http://localhost:3000/users', headers=headers) +``` + +### cURL +```bash +# 使用JWT令牌 +curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \ + http://localhost:3000/users + +# 使用固定令牌 +curl -H "Authorization: Bearer ft_1234567890abcdef1234567890abcdef12345678" \ + http://localhost:3000/users +``` \ No newline at end of file diff --git a/insurance_backend/middleware/auth.js b/insurance_backend/middleware/auth.js index 5188f52..c10262d 100644 --- a/insurance_backend/middleware/auth.js +++ b/insurance_backend/middleware/auth.js @@ -1,32 +1,97 @@ const jwt = require('jsonwebtoken'); +const User = require('../models/User'); +const Role = require('../models/Role'); const responseFormat = require('../utils/response'); // JWT认证中间件 -const jwtAuth = (req, res, next) => { - const token = req.headers.authorization?.replace('Bearer ', ''); - - if (!token) { - return res.status(401).json(responseFormat.error('未提供认证令牌')); - } - +const jwtAuth = async (req, res, next) => { try { - const decoded = jwt.verify(token, process.env.JWT_SECRET); + const authHeader = req.headers.authorization; + console.log('Authorization header:', authHeader); - // 检查Token类型,只接受访问令牌 - if (decoded.type && decoded.type !== 'access') { - return res.status(401).json(responseFormat.error('无效的令牌类型')); + if (!authHeader || !authHeader.startsWith('Bearer ')) { + return res.status(401).json(responseFormat.error('未提供有效的认证token')); + } + + const token = authHeader.substring(7); + console.log('提取的token:', token); + console.log('token类型:', typeof token); + console.log('token长度:', token.length); + + // 首先尝试固定token验证 + const user = await User.findOne({ + where: { + fixed_token: token, + status: 'active' + }, + include: [{ + model: Role, + as: 'role', + attributes: ['id', 'name', 'permissions'] + }] + }); + + if (user) { + // 固定token验证成功 + req.user = { + id: user.id, + userId: user.id, + username: user.username, + role_id: user.role_id, + role: user.role, + permissions: user.role ? user.role.permissions : [], + type: 'fixed_token' + }; + return next(); + } + + // 如果固定token验证失败,尝试JWT验证 + try { + const decoded = jwt.verify(token, process.env.JWT_SECRET); + + if (decoded.type !== 'access') { + return res.status(401).json(responseFormat.error('Token类型错误')); + } + + // 验证用户是否存在且状态正常 + const jwtUser = await User.findOne({ + where: { + id: decoded.id, + status: 'active' + }, + include: [{ + model: Role, + as: 'role', + attributes: ['id', 'name', 'permissions'] + }] + }); + + if (!jwtUser) { + return res.status(401).json(responseFormat.error('用户不存在或已被禁用')); + } + + req.user = { + id: decoded.id, + userId: decoded.id, + username: decoded.username, + role_id: decoded.role_id, + role: jwtUser.role, + permissions: decoded.permissions || (jwtUser.role ? jwtUser.role.permissions : []), + type: 'jwt' + }; + + return next(); + } catch (jwtError) { + if (jwtError.name === 'TokenExpiredError') { + return res.status(401).json(responseFormat.error('Token已过期', 'TOKEN_EXPIRED')); + } else if (jwtError.name === 'JsonWebTokenError') { + return res.status(401).json(responseFormat.error('Token无效')); + } + throw jwtError; } - - req.user = decoded; - next(); } catch (error) { - if (error.name === 'TokenExpiredError') { - return res.status(401).json(responseFormat.error('认证令牌已过期', 'TOKEN_EXPIRED')); - } else if (error.name === 'JsonWebTokenError') { - return res.status(401).json(responseFormat.error('认证令牌无效', 'TOKEN_INVALID')); - } else { - return res.status(401).json(responseFormat.error('认证失败', 'AUTH_FAILED')); - } + console.error('Token验证错误:', error); + return res.status(500).json(responseFormat.error('服务器内部错误')); } }; @@ -58,8 +123,16 @@ const checkPermission = (resource, action) => { } } - // 如果JWT中没有权限信息,从数据库查询 - if (permissions.length === 0) { + const requiredPermission = `${resource}:${action}`; + + // 首先检查JWT中的权限 + let hasPermission = permissions.includes(requiredPermission) || + permissions.includes('*:*') || + permissions.includes('*'); + + // 如果JWT中没有权限信息,或者JWT权限不足,从数据库查询最新权限 + if (permissions.length === 0 || !hasPermission) { + console.log('JWT权限不足或为空,从数据库获取最新权限...'); const { Role } = require('../models'); const userRole = await Role.findByPk(user.role_id); @@ -81,14 +154,19 @@ const checkPermission = (resource, action) => { } else if (Array.isArray(rolePermissions)) { permissions = rolePermissions; } + + console.log('从数据库获取的最新权限:', permissions); + + // 重新检查权限 + hasPermission = permissions.includes(requiredPermission) || + permissions.includes('*:*') || + permissions.includes('*'); } - const requiredPermission = `${resource}:${action}`; - - console.log('权限检查 - 用户权限:', permissions, '需要权限:', requiredPermission); + console.log('权限检查 - 用户权限:', permissions, '需要权限:', requiredPermission, '是否有权限:', hasPermission); // 检查权限或超级管理员权限 - if (!permissions.includes(requiredPermission) && !permissions.includes('*:*') && !permissions.includes('*')) { + if (!hasPermission) { console.log('权限检查失败 - 权限不足'); return res.status(403).json(responseFormat.error('权限不足')); } diff --git a/insurance_backend/middleware/fixedTokenAuth.js b/insurance_backend/middleware/fixedTokenAuth.js new file mode 100644 index 0000000..4e6a595 --- /dev/null +++ b/insurance_backend/middleware/fixedTokenAuth.js @@ -0,0 +1,119 @@ +const User = require('../models/User'); +const Role = require('../models/Role'); + +/** + * 固定Token认证中间件 + * 支持JWT token和固定token两种认证方式 + */ +const fixedTokenAuth = async (req, res, next) => { + try { + const authHeader = req.headers.authorization; + + if (!authHeader) { + return res.status(401).json({ + status: 'error', + message: '未提供认证token' + }); + } + + // 检查是否为Bearer token格式 + if (authHeader.startsWith('Bearer ')) { + const token = authHeader.substring(7); + + // 首先尝试固定token验证 + const user = await User.findOne({ + where: { + fixed_token: token, + status: 'active' + }, + include: [{ + model: Role, + as: 'role', + attributes: ['id', 'name', 'permissions'] + }] + }); + + if (user) { + // 固定token验证成功 + req.user = { + id: user.id, + username: user.username, + role_id: user.role_id, + role: user.role, + permissions: user.role ? user.role.permissions : [] + }; + return next(); + } + + // 如果固定token验证失败,尝试JWT验证 + const jwt = require('jsonwebtoken'); + try { + const decoded = jwt.verify(token, process.env.JWT_SECRET); + + if (decoded.type !== 'access') { + return res.status(401).json({ + status: 'error', + message: 'Token类型错误' + }); + } + + // 验证用户是否存在且状态正常 + const jwtUser = await User.findOne({ + where: { + id: decoded.userId, + status: 'active' + }, + include: [{ + model: Role, + as: 'role', + attributes: ['id', 'name', 'permissions'] + }] + }); + + if (!jwtUser) { + return res.status(401).json({ + status: 'error', + message: '用户不存在或已被禁用' + }); + } + + req.user = { + id: jwtUser.id, + username: jwtUser.username, + role_id: jwtUser.role_id, + role: jwtUser.role, + permissions: decoded.permissions || (jwtUser.role ? jwtUser.role.permissions : []) + }; + + return next(); + } catch (jwtError) { + if (jwtError.name === 'TokenExpiredError') { + return res.status(401).json({ + status: 'error', + code: 'TOKEN_EXPIRED', + message: 'Token已过期' + }); + } else if (jwtError.name === 'JsonWebTokenError') { + return res.status(401).json({ + status: 'error', + message: 'Token无效' + }); + } + throw jwtError; + } + } else { + return res.status(401).json({ + status: 'error', + message: 'Token格式错误,请使用Bearer格式' + }); + } + } catch (error) { + console.error('Token验证错误:', error); + return res.status(500).json({ + status: 'error', + message: '服务器内部错误' + }); + } +}; + +module.exports = fixedTokenAuth; \ No newline at end of file diff --git a/insurance_backend/migrations/20241220-add-fixed-token-to-users.js b/insurance_backend/migrations/20241220-add-fixed-token-to-users.js new file mode 100644 index 0000000..4ffc179 --- /dev/null +++ b/insurance_backend/migrations/20241220-add-fixed-token-to-users.js @@ -0,0 +1,16 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.addColumn('users', 'fixed_token', { + type: Sequelize.STRING(255), + allowNull: true, + unique: true, + comment: '用户固定token,用于API访问验证' + }); + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.removeColumn('users', 'fixed_token'); + } +}; \ No newline at end of file diff --git a/insurance_backend/migrations/20250122000002-update-insurance-applications.js b/insurance_backend/migrations/20250122000002-update-insurance-applications.js deleted file mode 100644 index dd3ab96..0000000 --- a/insurance_backend/migrations/20250122000002-update-insurance-applications.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -module.exports = { - up: async (queryInterface, Sequelize) => { - // 添加参保类型字段 - await queryInterface.addColumn('insurance_applications', 'insurance_category', { - type: Sequelize.STRING(50), - allowNull: true, - comment: '参保类型(如:牛、羊、猪等)', - after: 'insurance_type_id' - }); - - // 添加申请数量字段 - await queryInterface.addColumn('insurance_applications', 'application_quantity', { - type: Sequelize.INTEGER, - allowNull: true, - defaultValue: 1, - comment: '申请数量', - validate: { - min: 1 - }, - after: 'insurance_category' - }); - - // 添加备注字段 - await queryInterface.addColumn('insurance_applications', 'remarks', { - type: Sequelize.TEXT, - allowNull: true, - comment: '备注信息', - after: 'review_notes' - }); - - // 更新状态枚举值以匹配UI显示 - await queryInterface.changeColumn('insurance_applications', 'status', { - type: Sequelize.ENUM( - 'pending', // 待初审 - 'initial_approved', // 初审通过待复核 - 'under_review', // 已支付待复核 - 'approved', // 已支付 - 'rejected', // 已拒绝 - 'paid' // 已支付 - ), - allowNull: false, - defaultValue: 'pending', - comment: '申请状态' - }); - - // 添加索引 - await queryInterface.addIndex('insurance_applications', ['insurance_category'], { - name: 'idx_insurance_applications_category' - }); - - await queryInterface.addIndex('insurance_applications', ['application_quantity'], { - name: 'idx_insurance_applications_quantity' - }); - }, - - down: async (queryInterface, Sequelize) => { - // 移除索引 - await queryInterface.removeIndex('insurance_applications', 'idx_insurance_applications_category'); - await queryInterface.removeIndex('insurance_applications', 'idx_insurance_applications_quantity'); - - // 移除添加的字段 - await queryInterface.removeColumn('insurance_applications', 'insurance_category'); - await queryInterface.removeColumn('insurance_applications', 'application_quantity'); - await queryInterface.removeColumn('insurance_applications', 'remarks'); - - // 恢复原始状态枚举 - await queryInterface.changeColumn('insurance_applications', 'status', { - type: Sequelize.ENUM('pending', 'approved', 'rejected', 'under_review'), - allowNull: false, - defaultValue: 'pending' - }); - } -}; \ No newline at end of file diff --git a/insurance_backend/migrations/20250925000001-create-permissions.js b/insurance_backend/migrations/20250925000001-create-permissions.js new file mode 100644 index 0000000..a3a3b74 --- /dev/null +++ b/insurance_backend/migrations/20250925000001-create-permissions.js @@ -0,0 +1,109 @@ +'use strict'; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + // 创建权限表 + await queryInterface.createTable('permissions', { + id: { + type: Sequelize.INTEGER, + autoIncrement: true, + primaryKey: true, + comment: '权限ID' + }, + name: { + type: Sequelize.STRING(100), + allowNull: false, + comment: '权限名称' + }, + code: { + type: Sequelize.STRING(100), + allowNull: false, + unique: true, + comment: '权限代码' + }, + description: { + type: Sequelize.TEXT, + allowNull: true, + comment: '权限描述' + }, + module: { + type: Sequelize.STRING(50), + allowNull: false, + comment: '所属模块' + }, + type: { + type: Sequelize.ENUM('menu', 'operation'), + allowNull: false, + defaultValue: 'operation', + comment: '权限类型:menu-菜单权限,operation-操作权限' + }, + parent_id: { + type: Sequelize.INTEGER, + allowNull: true, + comment: '父权限ID', + references: { + model: 'permissions', + key: 'id' + }, + onUpdate: 'CASCADE', + onDelete: 'SET NULL' + }, + status: { + type: Sequelize.ENUM('active', 'inactive'), + allowNull: false, + defaultValue: 'active', + comment: '状态' + }, + sort_order: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 0, + comment: '排序' + }, + created_at: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'), + comment: '创建时间' + }, + updated_at: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), + comment: '更新时间' + } + }, { + comment: '权限表' + }); + + // 创建索引 + await queryInterface.addIndex('permissions', ['code'], { + name: 'idx_permissions_code' + }); + await queryInterface.addIndex('permissions', ['module'], { + name: 'idx_permissions_module' + }); + await queryInterface.addIndex('permissions', ['type'], { + name: 'idx_permissions_type' + }); + await queryInterface.addIndex('permissions', ['parent_id'], { + name: 'idx_permissions_parent_id' + }); + await queryInterface.addIndex('permissions', ['status'], { + name: 'idx_permissions_status' + }); + }, + + async down(queryInterface, Sequelize) { + // 删除索引 + await queryInterface.removeIndex('permissions', 'idx_permissions_code'); + await queryInterface.removeIndex('permissions', 'idx_permissions_module'); + await queryInterface.removeIndex('permissions', 'idx_permissions_type'); + await queryInterface.removeIndex('permissions', 'idx_permissions_parent_id'); + await queryInterface.removeIndex('permissions', 'idx_permissions_status'); + + // 删除表 + await queryInterface.dropTable('permissions'); + } +}; \ No newline at end of file diff --git a/insurance_backend/migrations/20250925000002-create-role-permissions.js b/insurance_backend/migrations/20250925000002-create-role-permissions.js new file mode 100644 index 0000000..fd46422 --- /dev/null +++ b/insurance_backend/migrations/20250925000002-create-role-permissions.js @@ -0,0 +1,82 @@ +'use strict'; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + // 创建角色权限关联表 + await queryInterface.createTable('role_permissions', { + id: { + type: Sequelize.INTEGER, + autoIncrement: true, + primaryKey: true, + comment: '关联ID' + }, + role_id: { + type: Sequelize.INTEGER, + allowNull: false, + comment: '角色ID', + references: { + model: 'roles', + key: 'id' + }, + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }, + permission_id: { + type: Sequelize.INTEGER, + allowNull: false, + comment: '权限ID', + references: { + model: 'permissions', + key: 'id' + }, + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }, + granted: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: true, + comment: '是否授权' + }, + created_at: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'), + comment: '创建时间' + }, + updated_at: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), + comment: '更新时间' + } + }, { + comment: '角色权限关联表' + }); + + // 创建唯一索引 + await queryInterface.addIndex('role_permissions', ['role_id', 'permission_id'], { + name: 'uk_role_permission', + unique: true + }); + + // 创建普通索引 + await queryInterface.addIndex('role_permissions', ['role_id'], { + name: 'idx_role_permissions_role_id' + }); + await queryInterface.addIndex('role_permissions', ['permission_id'], { + name: 'idx_role_permissions_permission_id' + }); + }, + + async down(queryInterface, Sequelize) { + // 删除索引 + await queryInterface.removeIndex('role_permissions', 'uk_role_permission'); + await queryInterface.removeIndex('role_permissions', 'idx_role_permissions_role_id'); + await queryInterface.removeIndex('role_permissions', 'idx_role_permissions_permission_id'); + + // 删除表 + await queryInterface.dropTable('role_permissions'); + } +}; \ No newline at end of file diff --git a/insurance_backend/migrations/20250925000003-create-menu-permissions.js b/insurance_backend/migrations/20250925000003-create-menu-permissions.js new file mode 100644 index 0000000..51bd189 --- /dev/null +++ b/insurance_backend/migrations/20250925000003-create-menu-permissions.js @@ -0,0 +1,82 @@ +'use strict'; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + // 创建菜单权限关联表 + await queryInterface.createTable('menu_permissions', { + id: { + type: Sequelize.INTEGER, + autoIncrement: true, + primaryKey: true, + comment: '关联ID' + }, + menu_id: { + type: Sequelize.INTEGER, + allowNull: false, + comment: '菜单ID', + references: { + model: 'menus', + key: 'id' + }, + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }, + permission_id: { + type: Sequelize.INTEGER, + allowNull: false, + comment: '权限ID', + references: { + model: 'permissions', + key: 'id' + }, + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }, + required: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: true, + comment: '是否必需权限' + }, + created_at: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'), + comment: '创建时间' + }, + updated_at: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), + comment: '更新时间' + } + }, { + comment: '菜单权限关联表' + }); + + // 创建唯一索引 + await queryInterface.addIndex('menu_permissions', ['menu_id', 'permission_id'], { + name: 'uk_menu_permission', + unique: true + }); + + // 创建普通索引 + await queryInterface.addIndex('menu_permissions', ['menu_id'], { + name: 'idx_menu_permissions_menu_id' + }); + await queryInterface.addIndex('menu_permissions', ['permission_id'], { + name: 'idx_menu_permissions_permission_id' + }); + }, + + async down(queryInterface, Sequelize) { + // 删除索引 + await queryInterface.removeIndex('menu_permissions', 'uk_menu_permission'); + await queryInterface.removeIndex('menu_permissions', 'idx_menu_permissions_menu_id'); + await queryInterface.removeIndex('menu_permissions', 'idx_menu_permissions_permission_id'); + + // 删除表 + await queryInterface.dropTable('menu_permissions'); + } +}; \ No newline at end of file diff --git a/insurance_backend/models/MenuPermission.js b/insurance_backend/models/MenuPermission.js new file mode 100644 index 0000000..f378a06 --- /dev/null +++ b/insurance_backend/models/MenuPermission.js @@ -0,0 +1,42 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const MenuPermission = sequelize.define('MenuPermission', { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + comment: '关联ID' + }, + menu_id: { + type: DataTypes.INTEGER, + allowNull: false, + comment: '菜单ID' + }, + permission_id: { + type: DataTypes.INTEGER, + allowNull: false, + comment: '权限ID' + }, + required: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: true, + comment: '是否必需权限' + } +}, { + tableName: 'menu_permissions', + timestamps: true, + underscored: true, + indexes: [ + { + fields: ['menu_id', 'permission_id'], + unique: true, + name: 'uk_menu_permission' + }, + { fields: ['menu_id'] }, + { fields: ['permission_id'] } + ] +}); + +module.exports = MenuPermission; \ No newline at end of file diff --git a/insurance_backend/models/Permission.js b/insurance_backend/models/Permission.js new file mode 100644 index 0000000..b177897 --- /dev/null +++ b/insurance_backend/models/Permission.js @@ -0,0 +1,93 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const Permission = sequelize.define('Permission', { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + comment: '权限ID' + }, + name: { + type: DataTypes.STRING(100), + allowNull: false, + comment: '权限名称', + validate: { + len: [2, 100] + } + }, + code: { + type: DataTypes.STRING(100), + allowNull: false, + unique: true, + comment: '权限代码', + validate: { + len: [2, 100], + is: /^[a-zA-Z0-9_:]+$/ // 只允许字母、数字、下划线和冒号 + } + }, + description: { + type: DataTypes.TEXT, + allowNull: true, + comment: '权限描述' + }, + module: { + type: DataTypes.STRING(50), + allowNull: false, + comment: '所属模块', + validate: { + len: [2, 50] + } + }, + type: { + type: DataTypes.ENUM('menu', 'operation'), + allowNull: false, + defaultValue: 'operation', + comment: '权限类型:menu-菜单权限,operation-操作权限' + }, + parent_id: { + type: DataTypes.INTEGER, + allowNull: true, + comment: '父权限ID' + }, + status: { + type: DataTypes.ENUM('active', 'inactive'), + allowNull: false, + defaultValue: 'active', + comment: '状态' + }, + sort_order: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + comment: '排序' + } +}, { + tableName: 'permissions', + timestamps: true, + underscored: true, + indexes: [ + { fields: ['code'], unique: true }, + { fields: ['module'] }, + { fields: ['type'] }, + { fields: ['parent_id'] }, + { fields: ['status'] } + ] +}); + +// 定义自关联关系 +Permission.hasMany(Permission, { + as: 'children', + foreignKey: 'parent_id', + onDelete: 'SET NULL', + onUpdate: 'CASCADE' +}); + +Permission.belongsTo(Permission, { + as: 'parent', + foreignKey: 'parent_id', + onDelete: 'SET NULL', + onUpdate: 'CASCADE' +}); + +module.exports = Permission; \ No newline at end of file diff --git a/insurance_backend/models/RolePermission.js b/insurance_backend/models/RolePermission.js new file mode 100644 index 0000000..5e34f53 --- /dev/null +++ b/insurance_backend/models/RolePermission.js @@ -0,0 +1,42 @@ +const { DataTypes } = require('sequelize'); +const { sequelize } = require('../config/database'); + +const RolePermission = sequelize.define('RolePermission', { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + comment: '关联ID' + }, + role_id: { + type: DataTypes.INTEGER, + allowNull: false, + comment: '角色ID' + }, + permission_id: { + type: DataTypes.INTEGER, + allowNull: false, + comment: '权限ID' + }, + granted: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: true, + comment: '是否授权' + } +}, { + tableName: 'role_permissions', + timestamps: true, + underscored: true, + indexes: [ + { + fields: ['role_id', 'permission_id'], + unique: true, + name: 'uk_role_permission' + }, + { fields: ['role_id'] }, + { fields: ['permission_id'] } + ] +}); + +module.exports = RolePermission; \ No newline at end of file diff --git a/insurance_backend/models/User.js b/insurance_backend/models/User.js index 0e2b3f5..b00fab8 100644 --- a/insurance_backend/models/User.js +++ b/insurance_backend/models/User.js @@ -65,6 +65,12 @@ const User = sequelize.define('User', { avatar: { type: DataTypes.STRING(255), allowNull: true + }, + fixed_token: { + type: DataTypes.STRING(255), + allowNull: true, + unique: true, + comment: '用户固定token,用于API访问验证' } }, { tableName: 'users', diff --git a/insurance_backend/models/index.js b/insurance_backend/models/index.js index da2e43b..a8163de 100644 --- a/insurance_backend/models/index.js +++ b/insurance_backend/models/index.js @@ -2,6 +2,9 @@ const { sequelize } = require('../config/database'); const User = require('./User'); const Role = require('./Role'); +const Permission = require('./Permission'); +const RolePermission = require('./RolePermission'); +const MenuPermission = require('./MenuPermission'); const InsuranceApplication = require('./InsuranceApplication'); const InsuranceType = require('./InsuranceType'); const Policy = require('./Policy'); @@ -22,6 +25,46 @@ const OperationLog = require('./OperationLog'); User.belongsTo(Role, { foreignKey: 'role_id', as: 'role' }); Role.hasMany(User, { foreignKey: 'role_id', as: 'users' }); +// 角色和权限多对多关联(通过中间表) +Role.belongsToMany(Permission, { + through: RolePermission, + foreignKey: 'role_id', + otherKey: 'permission_id', + as: 'rolePermissions' +}); +Permission.belongsToMany(Role, { + through: RolePermission, + foreignKey: 'permission_id', + otherKey: 'role_id', + as: 'permissionRoles' +}); + +// 角色权限关联表的直接关联 +RolePermission.belongsTo(Role, { foreignKey: 'role_id', as: 'role' }); +RolePermission.belongsTo(Permission, { foreignKey: 'permission_id', as: 'permission' }); +Role.hasMany(RolePermission, { foreignKey: 'role_id', as: 'rolePermissionRecords' }); +Permission.hasMany(RolePermission, { foreignKey: 'permission_id', as: 'permissionRoleRecords' }); + +// 菜单和权限多对多关联(通过中间表) +Menu.belongsToMany(Permission, { + through: MenuPermission, + foreignKey: 'menu_id', + otherKey: 'permission_id', + as: 'permissions' +}); +Permission.belongsToMany(Menu, { + through: MenuPermission, + foreignKey: 'permission_id', + otherKey: 'menu_id', + as: 'menus' +}); + +// 菜单权限关联表的直接关联 +MenuPermission.belongsTo(Menu, { foreignKey: 'menu_id', as: 'menu' }); +MenuPermission.belongsTo(Permission, { foreignKey: 'permission_id', as: 'permission' }); +Menu.hasMany(MenuPermission, { foreignKey: 'menu_id', as: 'menuPermissions' }); +Permission.hasMany(MenuPermission, { foreignKey: 'permission_id', as: 'menuPermissions' }); + // 保险申请和保险类型关联 InsuranceApplication.belongsTo(InsuranceType, { foreignKey: 'insurance_type_id', @@ -82,6 +125,26 @@ Policy.hasMany(Claim, { as: 'claims' }); +// 理赔和客户关联 +Claim.belongsTo(User, { + foreignKey: 'customer_id', + as: 'customer' +}); +User.hasMany(Claim, { + foreignKey: 'customer_id', + as: 'customer_claims' +}); + +// 理赔和审核人关联 +Claim.belongsTo(User, { + foreignKey: 'reviewer_id', + as: 'reviewer' +}); +User.hasMany(Claim, { + foreignKey: 'reviewer_id', + as: 'reviewed_claims' +}); + // 监管任务关联 SupervisoryTask.belongsTo(User, { foreignKey: 'assignedTo', @@ -198,6 +261,9 @@ module.exports = { sequelize, User, Role, + Permission, + RolePermission, + MenuPermission, InsuranceApplication, InsuranceType, Policy, diff --git a/insurance_backend/routes/dashboard.js b/insurance_backend/routes/dashboard.js new file mode 100644 index 0000000..e065a99 --- /dev/null +++ b/insurance_backend/routes/dashboard.js @@ -0,0 +1,222 @@ +const express = require('express'); +const router = express.Router(); +const dashboardController = require('../controllers/dashboardController'); +const { jwtAuth, checkPermission } = require('../middleware/auth'); + +/** + * @swagger + * tags: + * name: Dashboard + * description: 仪表板相关接口 + */ + +/** + * @swagger + * /api/dashboard/stats: + * get: + * summary: 获取仪表板统计数据 + * tags: [Dashboard] + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: 成功获取统计数据 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * data: + * type: object + * properties: + * totalApplications: + * type: integer + * description: 总申请数 + * todayApplications: + * type: integer + * description: 今日申请数 + * monthApplications: + * type: integer + * description: 本月申请数 + * applicationGrowthRate: + * type: number + * description: 申请增长率 + * totalPolicies: + * type: integer + * description: 总保单数 + * activePolicies: + * type: integer + * description: 有效保单数 + * policyGrowthRate: + * type: number + * description: 保单增长率 + * totalClaims: + * type: integer + * description: 总理赔数 + * pendingClaims: + * type: integer + * description: 待处理理赔数 + * claimProcessingRate: + * type: string + * description: 理赔处理率 + * totalUsers: + * type: integer + * description: 总用户数 + * quickStats: + * type: object + * properties: + * newApplicationsToday: + * type: integer + * pendingReviews: + * type: integer + * activeUsers: + * type: integer + * systemAlerts: + * type: integer + * message: + * type: string + * example: 获取仪表板统计数据成功 + * timestamp: + * type: string + * format: date-time + * 401: + * description: 未授权 + * 500: + * description: 服务器内部错误 + */ +router.get('/stats', jwtAuth, checkPermission('dashboard', 'read'), dashboardController.getStats); + +/** + * @swagger + * /api/dashboard/recent-activities: + * get: + * summary: 获取最近活动 + * tags: [Dashboard] + * security: + * - bearerAuth: [] + * parameters: + * - in: query + * name: limit + * schema: + * type: integer + * default: 20 + * description: 返回记录数量限制 + * responses: + * 200: + * description: 成功获取最近活动 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * data: + * type: array + * items: + * type: object + * properties: + * id: + * type: integer + * type: + * type: string + * description: 活动类型 + * title: + * type: string + * description: 活动标题 + * description: + * type: string + * description: 活动描述 + * timestamp: + * type: string + * format: date-time + * user: + * type: string + * description: 操作用户 + * level: + * type: string + * description: 日志级别 + * message: + * type: string + * example: 获取最近活动成功 + * timestamp: + * type: string + * format: date-time + * 401: + * description: 未授权 + * 500: + * description: 服务器内部错误 + */ +router.get('/recent-activities', jwtAuth, checkPermission('dashboard', 'read'), dashboardController.getRecentActivities); + +/** + * @swagger + * /api/dashboard/chart-data: + * get: + * summary: 获取图表数据 + * tags: [Dashboard] + * security: + * - bearerAuth: [] + * parameters: + * - in: query + * name: type + * schema: + * type: string + * enum: [applications, policies, claims] + * default: applications + * description: 图表数据类型 + * - in: query + * name: period + * schema: + * type: string + * enum: [7d, 30d, 90d] + * default: 7d + * description: 时间周期 + * responses: + * 200: + * description: 成功获取图表数据 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * data: + * type: array + * items: + * type: object + * properties: + * date: + * type: string + * format: date + * value: + * type: integer + * message: + * type: string + * example: 获取图表数据成功 + * timestamp: + * type: string + * format: date-time + * 401: + * description: 未授权 + * 500: + * description: 服务器内部错误 + */ +router.get('/chart-data', jwtAuth, checkPermission('dashboard', 'read'), dashboardController.getChartData); + +module.exports = router; \ No newline at end of file diff --git a/insurance_backend/routes/installationTasks.js b/insurance_backend/routes/installationTasks.js index 82005b7..fe64bc7 100644 --- a/insurance_backend/routes/installationTasks.js +++ b/insurance_backend/routes/installationTasks.js @@ -1,6 +1,7 @@ const express = require('express'); const router = express.Router(); const installationTaskController = require('../controllers/installationTaskController'); +const { jwtAuth, requirePermission } = require('../middleware/auth'); /** * @swagger @@ -59,7 +60,7 @@ const installationTaskController = require('../controllers/installationTaskContr * 200: * description: 获取成功 */ -router.get('/', installationTaskController.getInstallationTasks); +router.get('/', jwtAuth, requirePermission('installation_tasks:read'), installationTaskController.getInstallationTasks); /** * @swagger @@ -115,13 +116,13 @@ router.get('/', installationTaskController.getInstallationTasks); * 201: * description: 创建成功 */ -router.post('/', installationTaskController.createInstallationTask); +router.post('/', jwtAuth, requirePermission('installation_tasks:create'), installationTaskController.createInstallationTask); /** * @swagger * /api/installation-tasks/{id}: * get: - * summary: 获取待安装任务详情 + * summary: 根据ID获取待安装任务详情 * tags: [InstallationTasks] * parameters: * - in: path @@ -133,8 +134,10 @@ router.post('/', installationTaskController.createInstallationTask); * responses: * 200: * description: 获取成功 + * 404: + * description: 任务不存在 */ -router.get('/:id', installationTaskController.getInstallationTaskById); +router.get('/:id', jwtAuth, requirePermission('installation_tasks:read'), installationTaskController.getInstallationTaskById); /** * @swagger @@ -142,12 +145,14 @@ router.get('/:id', installationTaskController.getInstallationTaskById); * put: * summary: 更新待安装任务 * tags: [InstallationTasks] + * security: + * - bearerAuth: [] * parameters: * - in: path * name: id * required: true * schema: - * type: integer + * type: string * description: 任务ID * requestBody: * required: true @@ -162,16 +167,13 @@ router.get('/:id', installationTaskController.getInstallationTaskById); * priority: * type: string * enum: [低, 中, 高, 紧急] - * assignedTo: - * type: integer - * installationCompletedAt: + * notes: * type: string - * format: date-time * responses: * 200: * description: 更新成功 */ -router.put('/:id', installationTaskController.updateInstallationTask); +router.put('/:id', jwtAuth, requirePermission('installation_tasks:update'), installationTaskController.updateInstallationTask); /** * @swagger @@ -189,8 +191,10 @@ router.put('/:id', installationTaskController.updateInstallationTask); * responses: * 200: * description: 删除成功 + * 404: + * description: 任务不存在 */ -router.delete('/:id', installationTaskController.deleteInstallationTask); +router.delete('/:id', jwtAuth, requirePermission('installation_tasks:delete'), installationTaskController.deleteInstallationTask); /** * @swagger @@ -224,7 +228,7 @@ router.delete('/:id', installationTaskController.deleteInstallationTask); * 200: * description: 操作成功 */ -router.post('/batch/operate', installationTaskController.batchOperateInstallationTasks); +router.post('/batch/operate', jwtAuth, requirePermission('installation_tasks:update'), installationTaskController.batchOperateInstallationTasks); /** * @swagger @@ -232,6 +236,8 @@ router.post('/batch/operate', installationTaskController.batchOperateInstallatio * get: * summary: 导出待安装任务数据 * tags: [InstallationTasks] + * security: + * - bearerAuth: [] * parameters: * - in: query * name: ids @@ -242,7 +248,7 @@ router.post('/batch/operate', installationTaskController.batchOperateInstallatio * 200: * description: 导出成功 */ -router.get('/export', installationTaskController.exportInstallationTasks); +router.get('/export', jwtAuth, requirePermission('installation_tasks:read'), installationTaskController.exportInstallationTasks); /** * @swagger @@ -250,10 +256,12 @@ router.get('/export', installationTaskController.exportInstallationTasks); * get: * summary: 获取安装任务统计数据 * tags: [InstallationTasks] + * security: + * - bearerAuth: [] * responses: * 200: * description: 获取成功 */ -router.get('/stats', installationTaskController.getInstallationTaskStats); +router.get('/stats', jwtAuth, requirePermission('installation_tasks:read'), installationTaskController.getInstallationTaskStats); module.exports = router; \ No newline at end of file diff --git a/insurance_backend/routes/menus.js b/insurance_backend/routes/menus.js index 4f1bf20..c0e7b0b 100644 --- a/insurance_backend/routes/menus.js +++ b/insurance_backend/routes/menus.js @@ -10,37 +10,7 @@ const { jwtAuth } = require('../middleware/auth'); * description: 菜单管理相关接口 */ -/** - * @swagger - * /api/menus/public: - * get: - * summary: 获取公开菜单列表(无需认证) - * tags: [Menus] - * responses: - * 200: - * description: 成功获取菜单列表 - * content: - * application/json: - * schema: - * type: object - * properties: - * code: - * type: integer - * example: 200 - * status: - * type: string - * example: success - * data: - * type: array - * items: - * $ref: '#/components/schemas/Menu' - * message: - * type: string - * example: 获取菜单成功 - * 500: - * description: 服务器内部错误 - */ -router.get('/public', menuController.getMenus); +// 移除了公共API路径,所有菜单API都需要认证 /** * @swagger diff --git a/insurance_backend/routes/permissions.js b/insurance_backend/routes/permissions.js new file mode 100644 index 0000000..510f13f --- /dev/null +++ b/insurance_backend/routes/permissions.js @@ -0,0 +1,542 @@ +const express = require('express'); +const router = express.Router(); +const permissionController = require('../controllers/permissionController'); +const { jwtAuth } = require('../middleware/auth'); + +// 所有权限管理路由都需要认证 +router.use(jwtAuth); + +/** + * @swagger + * components: + * schemas: + * Permission: + * type: object + * required: + * - name + * - code + * - module + * properties: + * id: + * type: integer + * description: 权限ID + * name: + * type: string + * description: 权限名称 + * code: + * type: string + * description: 权限代码 + * description: + * type: string + * description: 权限描述 + * module: + * type: string + * description: 所属模块 + * type: + * type: string + * enum: [menu, operation] + * description: 权限类型 + * parent_id: + * type: integer + * description: 父权限ID + * status: + * type: string + * enum: [active, inactive] + * description: 状态 + * sort_order: + * type: integer + * description: 排序 + * created_at: + * type: string + * format: date-time + * description: 创建时间 + * updated_at: + * type: string + * format: date-time + * description: 更新时间 + */ + +/** + * @swagger + * /api/permissions: + * get: + * summary: 获取权限列表 + * tags: [权限管理] + * security: + * - bearerAuth: [] + * parameters: + * - in: query + * name: page + * schema: + * type: integer + * default: 1 + * description: 页码 + * - in: query + * name: limit + * schema: + * type: integer + * default: 10 + * description: 每页数量 + * - in: query + * name: module + * schema: + * type: string + * description: 模块筛选 + * - in: query + * name: type + * schema: + * type: string + * enum: [menu, operation] + * description: 类型筛选 + * - in: query + * name: status + * schema: + * type: string + * enum: [active, inactive] + * default: active + * description: 状态筛选 + * - in: query + * name: keyword + * schema: + * type: string + * description: 关键词搜索 + * responses: + * 200: + * description: 获取成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 获取权限列表成功 + * data: + * type: object + * properties: + * permissions: + * type: array + * items: + * $ref: '#/components/schemas/Permission' + * pagination: + * type: object + * properties: + * total: + * type: integer + * page: + * type: integer + * limit: + * type: integer + * pages: + * type: integer + */ +router.get('/', permissionController.getPermissions); + +/** + * @swagger + * /api/permissions/tree: + * get: + * summary: 获取权限树形结构 + * tags: [权限管理] + * security: + * - bearerAuth: [] + * parameters: + * - in: query + * name: module + * schema: + * type: string + * description: 模块筛选 + * - in: query + * name: type + * schema: + * type: string + * enum: [menu, operation] + * description: 类型筛选 + * responses: + * 200: + * description: 获取成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 获取权限树成功 + * data: + * type: array + * items: + * $ref: '#/components/schemas/Permission' + */ +router.get('/tree', permissionController.getPermissionTree); + +/** + * @swagger + * /api/permissions/modules: + * get: + * summary: 获取模块列表 + * tags: [权限管理] + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: 获取成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 获取模块列表成功 + * data: + * type: array + * items: + * type: string + */ +router.get('/modules', permissionController.getModules); + +/** + * @swagger + * /api/permissions/{id}: + * get: + * summary: 获取权限详情 + * tags: [权限管理] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: integer + * description: 权限ID + * responses: + * 200: + * description: 获取成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 获取权限详情成功 + * data: + * $ref: '#/components/schemas/Permission' + * 404: + * description: 权限不存在 + */ +router.get('/:id', permissionController.getPermissionById); + +/** + * @swagger + * /api/permissions: + * post: + * summary: 创建权限 + * tags: [权限管理] + * security: + * - bearerAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - name + * - code + * - module + * properties: + * name: + * type: string + * description: 权限名称 + * code: + * type: string + * description: 权限代码 + * description: + * type: string + * description: 权限描述 + * module: + * type: string + * description: 所属模块 + * type: + * type: string + * enum: [menu, operation] + * default: operation + * description: 权限类型 + * parent_id: + * type: integer + * description: 父权限ID + * sort_order: + * type: integer + * default: 0 + * description: 排序 + * responses: + * 201: + * description: 创建成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 创建权限成功 + * data: + * $ref: '#/components/schemas/Permission' + * 400: + * description: 请求参数错误 + */ +router.post('/', permissionController.createPermission); + +/** + * @swagger + * /api/permissions/{id}: + * put: + * summary: 更新权限 + * tags: [权限管理] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: integer + * description: 权限ID + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * name: + * type: string + * description: 权限名称 + * code: + * type: string + * description: 权限代码 + * description: + * type: string + * description: 权限描述 + * module: + * type: string + * description: 所属模块 + * type: + * type: string + * enum: [menu, operation] + * description: 权限类型 + * parent_id: + * type: integer + * description: 父权限ID + * sort_order: + * type: integer + * description: 排序 + * status: + * type: string + * enum: [active, inactive] + * description: 状态 + * responses: + * 200: + * description: 更新成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 更新权限成功 + * data: + * $ref: '#/components/schemas/Permission' + * 404: + * description: 权限不存在 + */ +router.put('/:id', permissionController.updatePermission); + +/** + * @swagger + * /api/permissions/{id}: + * delete: + * summary: 删除权限 + * tags: [权限管理] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: integer + * description: 权限ID + * responses: + * 200: + * description: 删除成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 删除权限成功 + * 404: + * description: 权限不存在 + * 400: + * description: 权限正在使用中,无法删除 + */ +router.delete('/:id', permissionController.deletePermission); + +/** + * @swagger + * /api/permissions/roles/{roleId}: + * get: + * summary: 获取角色权限 + * tags: [权限管理] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: roleId + * required: true + * schema: + * type: integer + * description: 角色ID + * responses: + * 200: + * description: 获取成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 获取角色权限成功 + * data: + * type: object + * properties: + * role: + * type: object + * properties: + * id: + * type: integer + * name: + * type: string + * description: + * type: string + * permissions: + * type: array + * items: + * $ref: '#/components/schemas/Permission' + * 404: + * description: 角色不存在 + */ +router.get('/roles/:roleId', permissionController.getRolePermissions); + +/** + * @swagger + * /api/permissions/roles/{roleId}/assign: + * post: + * summary: 分配角色权限 + * tags: [权限管理] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: roleId + * required: true + * schema: + * type: integer + * description: 角色ID + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - permissionIds + * properties: + * permissionIds: + * type: array + * items: + * type: integer + * description: 权限ID列表 + * example: + * permissionIds: [1, 2, 3, 4] + * responses: + * 200: + * description: 分配成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 分配角色权限成功 + * 404: + * description: 角色不存在 + * 400: + * description: 请求参数错误 + */ +router.post('/roles/:roleId/assign', permissionController.assignRolePermissions); + +module.exports = router; \ No newline at end of file diff --git a/insurance_backend/routes/rolePermissions.js b/insurance_backend/routes/rolePermissions.js new file mode 100644 index 0000000..129ca58 --- /dev/null +++ b/insurance_backend/routes/rolePermissions.js @@ -0,0 +1,384 @@ +const express = require('express'); +const router = express.Router(); +const rolePermissionController = require('../controllers/rolePermissionController'); +const { jwtAuth } = require('../middleware/auth'); + +// 应用认证中间件 +router.use(jwtAuth); + +/** + * @swagger + * components: + * schemas: + * RolePermissionAssignment: + * type: object + * properties: + * roleId: + * type: integer + * description: 角色ID + * permissionIds: + * type: array + * items: + * type: integer + * description: 权限ID列表 + * operation: + * type: string + * enum: [replace, add, remove] + * default: replace + * description: 操作类型 + */ + +/** + * @swagger + * /api/role-permissions: + * get: + * summary: 获取所有角色及其权限 + * tags: [角色权限管理] + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: 获取成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 获取角色权限列表成功 + * data: + * type: object + * properties: + * roles: + * type: array + * items: + * type: object + * properties: + * id: + * type: integer + * name: + * type: string + * description: + * type: string + * permissions: + * type: array + * permissionCount: + * type: integer + * total: + * type: integer + */ +router.get('/', rolePermissionController.getAllRolesWithPermissions); + +/** + * @swagger + * /api/role-permissions/permissions: + * get: + * summary: 获取所有权限 + * tags: [角色权限管理] + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: 获取成功 + */ +router.get('/permissions', rolePermissionController.getAllPermissions); + +/** + * @swagger + * /api/role-permissions/roles: + * get: + * summary: 获取所有角色及其权限 + * tags: [角色权限管理] + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: 获取成功 + */ +router.get('/roles', rolePermissionController.getAllRolesWithPermissions); + +/** + * @swagger + * /api/role-permissions/roles/{roleId}/permissions: + * get: + * summary: 获取指定角色的权限详情 + * tags: [角色权限管理] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: roleId + * required: true + * schema: + * type: integer + * description: 角色ID + * responses: + * 200: + * description: 获取成功 + * 404: + * description: 角色不存在 + */ +router.get('/roles/:roleId/permissions', rolePermissionController.getRolePermissionDetail); + +/** + * @swagger + * /api/role-permissions/stats: + * get: + * summary: 获取权限统计信息 + * tags: [角色权限管理] + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: 获取成功 + */ +router.get('/stats', rolePermissionController.getPermissionStats); + +/** + * @swagger + * /api/role-permissions/{roleId}: + * get: + * summary: 获取指定角色的权限详情 + * tags: [角色权限管理] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: roleId + * required: true + * schema: + * type: integer + * description: 角色ID + * responses: + * 200: + * description: 获取成功 + * 404: + * description: 角色不存在 + */ +router.get('/:roleId', rolePermissionController.getRolePermissionDetail); + +/** + * @swagger + * /api/role-permissions/{roleId}/assign: + * post: + * summary: 批量分配角色权限 + * tags: [角色权限管理] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: roleId + * required: true + * schema: + * type: integer + * description: 角色ID + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - permissionIds + * properties: + * permissionIds: + * type: array + * items: + * type: integer + * description: 权限ID列表 + * operation: + * type: string + * enum: [replace, add, remove] + * default: replace + * description: 操作类型 + * examples: + * replace: + * summary: 替换权限 + * value: + * permissionIds: [1, 2, 3, 4] + * operation: "replace" + * add: + * summary: 添加权限 + * value: + * permissionIds: [5, 6] + * operation: "add" + * remove: + * summary: 移除权限 + * value: + * permissionIds: [1, 2] + * operation: "remove" + * responses: + * 200: + * description: 分配成功 + * 400: + * description: 请求参数错误 + * 404: + * description: 角色不存在 + */ +router.post('/:roleId/assign', rolePermissionController.batchAssignPermissions); + +/** + * @swagger + * /api/role-permissions/copy: + * post: + * summary: 复制角色权限 + * tags: [角色权限管理] + * security: + * - bearerAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - sourceRoleId + * - targetRoleId + * properties: + * sourceRoleId: + * type: integer + * description: 源角色ID + * targetRoleId: + * type: integer + * description: 目标角色ID + * example: + * sourceRoleId: 1 + * targetRoleId: 2 + * responses: + * 200: + * description: 复制成功 + * 400: + * description: 请求参数错误 + * 404: + * description: 角色不存在 + */ +router.post('/copy', rolePermissionController.copyRolePermissions); + +/** + * @swagger + * /api/role-permissions/check/{userId}/{permissionCode}: + * get: + * summary: 检查用户权限 + * tags: [角色权限管理] + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: userId + * required: true + * schema: + * type: integer + * description: 用户ID + * - in: path + * name: permissionCode + * required: true + * schema: + * type: string + * description: 权限代码 + * responses: + * 200: + * description: 检查完成 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 权限检查完成 + * data: + * type: object + * properties: + * userId: + * type: integer + * username: + * type: string + * roleName: + * type: string + * permissionCode: + * type: string + * hasPermission: + * type: boolean + * checkTime: + * type: string + * format: date-time + * 404: + * description: 用户不存在 + */ +router.get('/check/:userId/:permissionCode', rolePermissionController.checkUserPermission); + +/** + * @swagger + * /api/role-permissions/stats: + * get: + * summary: 获取权限统计信息 + * tags: [角色权限管理] + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: 获取成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 获取权限统计成功 + * data: + * type: object + * properties: + * overview: + * type: object + * properties: + * totalRoles: + * type: integer + * totalPermissions: + * type: integer + * totalAssignments: + * type: integer + * averagePermissionsPerRole: + * type: integer + * moduleDistribution: + * type: array + * items: + * type: object + * properties: + * module: + * type: string + * count: + * type: integer + * roleDistribution: + * type: array + * items: + * type: object + * properties: + * roleId: + * type: integer + * roleName: + * type: string + * permissionCount: + * type: integer + */ + +module.exports = router; \ No newline at end of file diff --git a/insurance_backend/routes/supervisoryTasks.js b/insurance_backend/routes/supervisoryTasks.js index 147389f..b3c1156 100644 --- a/insurance_backend/routes/supervisoryTasks.js +++ b/insurance_backend/routes/supervisoryTasks.js @@ -1,7 +1,7 @@ const express = require('express'); const router = express.Router(); const SupervisoryTaskController = require('../controllers/supervisoryTaskController'); -const auth = require('../middleware/auth'); +const { jwtAuth, requirePermission } = require('../middleware/auth'); /** * @swagger @@ -62,7 +62,7 @@ const auth = require('../middleware/auth'); * 200: * description: 获取成功 */ -router.get('/', SupervisoryTaskController.getList); +router.get('/', jwtAuth, requirePermission('supervision_tasks:read'), SupervisoryTaskController.getList); /** * @swagger @@ -131,7 +131,7 @@ router.get('/', SupervisoryTaskController.getList); * 201: * description: 创建成功 */ -router.post('/', SupervisoryTaskController.create); +router.post('/', jwtAuth, requirePermission('supervision_tasks:create'), SupervisoryTaskController.create); /** * @swagger @@ -152,7 +152,7 @@ router.post('/', SupervisoryTaskController.create); * 200: * description: 获取成功 */ -router.get('/:id', SupervisoryTaskController.getById); +router.get('/:id', jwtAuth, requirePermission('supervision_tasks:read'), SupervisoryTaskController.getById); /** * @swagger @@ -167,8 +167,8 @@ router.get('/:id', SupervisoryTaskController.getById); * name: id * required: true * schema: - * type: integer - * description: 监管任务ID + * type: string + * description: 任务ID * requestBody: * required: true * content: @@ -179,18 +179,22 @@ router.get('/:id', SupervisoryTaskController.getById); * status: * type: string * enum: [pending, processing, completed, rejected] + * description: 状态 * assignedTo: - * type: integer + * type: string + * description: 分配给 * priority: * type: string * enum: [low, medium, high, urgent] - * remarks: + * description: 优先级 + * notes: * type: string + * description: 备注 * responses: * 200: * description: 更新成功 */ -router.put('/:id', SupervisoryTaskController.update); +router.put('/:id', jwtAuth, requirePermission('supervision_tasks:update'), SupervisoryTaskController.update); /** * @swagger @@ -205,13 +209,13 @@ router.put('/:id', SupervisoryTaskController.update); * name: id * required: true * schema: - * type: integer - * description: 监管任务ID + * type: string + * description: 任务ID * responses: * 200: * description: 删除成功 */ -router.delete('/:id', SupervisoryTaskController.delete); +router.delete('/:id', jwtAuth, requirePermission('supervision_tasks:delete'), SupervisoryTaskController.delete); /** * @swagger @@ -247,13 +251,13 @@ router.delete('/:id', SupervisoryTaskController.delete); * 200: * description: 操作成功 */ -router.post('/batch/operate', SupervisoryTaskController.bulkCreate); +router.post('/batch/operate', jwtAuth, requirePermission('supervision_tasks:create'), SupervisoryTaskController.bulkCreate); /** * @swagger * /api/supervision-tasks/stats: * get: - * summary: 获取监管任务统计数据 + * summary: 获取监管任务统计信息 * tags: [SupervisionTasks] * security: * - bearerAuth: [] @@ -261,6 +265,6 @@ router.post('/batch/operate', SupervisoryTaskController.bulkCreate); * 200: * description: 获取成功 */ -router.get('/stats', SupervisoryTaskController.getStatistics); +router.get('/stats', jwtAuth, requirePermission('supervision_tasks:read'), SupervisoryTaskController.getStatistics); module.exports = router; \ No newline at end of file diff --git a/insurance_backend/routes/users.js b/insurance_backend/routes/users.js index 2bc8731..3a7548c 100644 --- a/insurance_backend/routes/users.js +++ b/insurance_backend/routes/users.js @@ -34,4 +34,172 @@ router.put('/change-password', jwtAuth, userController.changePassword); // 上传头像(不需要特殊权限,用户可以上传自己的头像) router.post('/avatar', jwtAuth, userController.uploadAvatar); +/** + * @swagger + * /users/{id}/fixed-token: + * get: + * summary: 获取用户固定令牌信息 + * description: 获取指定用户的固定令牌信息,包括是否已生成令牌、令牌预览等 + * tags: [用户管理] + * security: + * - bearerAuth: [] + * - fixedTokenAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: integer + * description: 用户ID + * responses: + * 200: + * description: 获取成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * data: + * $ref: '#/components/schemas/FixedTokenInfo' + * 401: + * $ref: '#/components/responses/UnauthorizedError' + * 403: + * $ref: '#/components/responses/ForbiddenError' + * 404: + * $ref: '#/components/responses/NotFoundError' + * post: + * summary: 生成用户固定令牌 + * description: 为指定用户生成新的固定令牌,用于API访问验证 + * tags: [用户管理] + * security: + * - bearerAuth: [] + * - fixedTokenAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: integer + * description: 用户ID + * responses: + * 200: + * description: 生成成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * data: + * $ref: '#/components/schemas/FixedTokenGenerated' + * 400: + * description: 用户已有固定令牌 + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Error' + * 401: + * $ref: '#/components/responses/UnauthorizedError' + * 403: + * $ref: '#/components/responses/ForbiddenError' + * 404: + * $ref: '#/components/responses/NotFoundError' + * put: + * summary: 重新生成用户固定令牌 + * description: 重新生成指定用户的固定令牌,原令牌将失效 + * tags: [用户管理] + * security: + * - bearerAuth: [] + * - fixedTokenAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: integer + * description: 用户ID + * responses: + * 200: + * description: 重新生成成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * data: + * $ref: '#/components/schemas/FixedTokenGenerated' + * 401: + * $ref: '#/components/responses/UnauthorizedError' + * 403: + * $ref: '#/components/responses/ForbiddenError' + * 404: + * $ref: '#/components/responses/NotFoundError' + * delete: + * summary: 删除用户固定令牌 + * description: 删除指定用户的固定令牌,令牌将立即失效 + * tags: [用户管理] + * security: + * - bearerAuth: [] + * - fixedTokenAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: integer + * description: 用户ID + * responses: + * 200: + * description: 删除成功 + * content: + * application/json: + * schema: + * type: object + * properties: + * code: + * type: integer + * example: 200 + * status: + * type: string + * example: success + * message: + * type: string + * example: 固定令牌删除成功 + * 401: + * $ref: '#/components/responses/UnauthorizedError' + * 403: + * $ref: '#/components/responses/ForbiddenError' + * 404: + * $ref: '#/components/responses/NotFoundError' + */ +// 固定Token管理路由(需要管理员权限) +// 获取用户固定Token信息 +router.get('/:id/fixed-token', jwtAuth, checkPermission('user', 'read'), userController.getFixedTokenInfo); + +// 生成用户固定Token +router.post('/:id/fixed-token', jwtAuth, checkPermission('user', 'update'), userController.generateFixedToken); + +// 重新生成用户固定Token +router.put('/:id/fixed-token', jwtAuth, checkPermission('user', 'update'), userController.regenerateFixedToken); + +// 删除用户固定Token +router.delete('/:id/fixed-token', jwtAuth, checkPermission('user', 'delete'), userController.deleteFixedToken); + module.exports = router; \ No newline at end of file diff --git a/insurance_backend/scripts/fix-admin-permissions.js b/insurance_backend/scripts/fix-admin-permissions.js index a7b7aaa..562926d 100644 --- a/insurance_backend/scripts/fix-admin-permissions.js +++ b/insurance_backend/scripts/fix-admin-permissions.js @@ -26,7 +26,8 @@ async function fixAdminPermissions() { 'insurance_type:read', 'insurance_type:create', 'insurance_type:update', 'insurance_type:delete', 'insurance_type:review', 'policy:read', 'policy:create', 'policy:update', 'policy:delete', 'claim:read', 'claim:create', 'claim:update', 'claim:review', - 'system:read', 'system:update', 'system:admin' + 'system:read', 'system:update', 'system:admin', + 'dashboard:read', 'dashboard:update' ]; await adminRole.update({ diff --git a/insurance_backend/scripts/fix_admin_permissions.js b/insurance_backend/scripts/fix_admin_permissions.js new file mode 100644 index 0000000..18508e4 --- /dev/null +++ b/insurance_backend/scripts/fix_admin_permissions.js @@ -0,0 +1,124 @@ +const mysql = require('mysql2/promise'); +require('dotenv').config(); + +/** + * 修复admin用户权限脚本 + * 添加缺失的supervision_tasks:read和installation_tasks:read权限 + */ + +async function fixAdminPermissions() { + let connection; + + try { + // 创建数据库连接 + connection = await mysql.createConnection({ + host: process.env.DB_HOST || '129.211.213.226', + port: process.env.DB_PORT || 9527, + user: process.env.DB_USER || 'root', + password: process.env.DB_PASSWORD || 'aiotAiot123!', + database: process.env.DB_NAME || 'insurance_data' + }); + + console.log('✅ 数据库连接成功'); + + // 查询当前admin角色的权限 + const [adminRole] = await connection.query( + 'SELECT id, name, permissions FROM roles WHERE name = ?', + ['admin'] + ); + + if (adminRole.length === 0) { + console.log('❌ 未找到admin角色'); + return; + } + + console.log('📋 当前admin角色权限:', adminRole[0].permissions); + + // 解析当前权限 + let currentPermissions; + try { + currentPermissions = JSON.parse(adminRole[0].permissions); + } catch (error) { + console.log('⚠️ 权限格式错误,重新设置为完整权限列表'); + currentPermissions = []; + } + + // 定义完整的权限列表 + const fullPermissions = [ + "user:read", "user:create", "user:update", "user:delete", + "insurance:read", "insurance:create", "insurance:update", "insurance:delete", "insurance:review", + "policy:read", "policy:create", "policy:update", "policy:delete", + "livestock_policy:read", "livestock_policy:create", "livestock_policy:update", "livestock_policy:delete", + "claim:read", "claim:create", "claim:update", "claim:review", + "supervision_tasks:read", "supervision_tasks:create", "supervision_tasks:update", "supervision_tasks:delete", + "installation_tasks:read", "installation_tasks:create", "installation_tasks:update", "installation_tasks:delete", + "system:read", "system:update", "system:admin", + "data:read", "data:create", "data:update", "data:delete" + ]; + + // 更新admin角色权限 + await connection.query( + 'UPDATE roles SET permissions = ? WHERE name = ?', + [JSON.stringify(fullPermissions), 'admin'] + ); + + console.log('✅ admin角色权限已更新'); + console.log('📋 新的权限列表:', JSON.stringify(fullPermissions, null, 2)); + + // 查询admin用户并更新其权限缓存 + const [adminUsers] = await connection.query( + 'SELECT id, username FROM users WHERE role_id = ?', + [adminRole[0].id] + ); + + console.log(`✅ 找到 ${adminUsers.length} 个admin用户,权限已生效`); + + // 验证权限更新 + const [updatedRole] = await connection.query( + 'SELECT permissions FROM roles WHERE name = ?', + ['admin'] + ); + + let updatedPermissions; + try { + updatedPermissions = JSON.parse(updatedRole[0].permissions); + } catch (error) { + console.log('⚠️ 验证时权限格式错误:', updatedRole[0].permissions); + updatedPermissions = fullPermissions; // 使用我们刚设置的权限 + } + + const hasSupervisionRead = updatedPermissions.includes('supervision_tasks:read'); + const hasInstallationRead = updatedPermissions.includes('installation_tasks:read'); + + console.log('🔍 权限验证:'); + console.log(` - supervision_tasks:read: ${hasSupervisionRead ? '✅' : '❌'}`); + console.log(` - installation_tasks:read: ${hasInstallationRead ? '✅' : '❌'}`); + + if (hasSupervisionRead && hasInstallationRead) { + console.log('🎉 权限修复成功!'); + } else { + console.log('❌ 权限修复失败,请检查数据库'); + } + + } catch (error) { + console.error('❌ 权限修复失败:', error.message); + throw error; + } finally { + // 关闭数据库连接 + if (connection) { + await connection.end(); + console.log('🔌 数据库连接已关闭'); + } + } +} + +// 执行脚本 +fixAdminPermissions() + .then(() => { + console.log('✨ 权限修复任务已完成'); + process.exit(0); + }) + .catch(() => { + console.error('❌ 权限修复任务失败'); + process.exit(1); + }); \ No newline at end of file diff --git a/insurance_backend/seeders/20250925000001-init-permissions.js b/insurance_backend/seeders/20250925000001-init-permissions.js new file mode 100644 index 0000000..7fda2f3 --- /dev/null +++ b/insurance_backend/seeders/20250925000001-init-permissions.js @@ -0,0 +1,431 @@ +'use strict'; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + // 插入基础权限数据 + await queryInterface.bulkInsert('permissions', [ + // 系统管理模块权限 + { + name: '系统管理', + code: 'system:manage', + description: '系统管理模块访问权限', + module: 'system', + type: 'menu', + parent_id: null, + status: 'active', + sort_order: 1, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '用户管理', + code: 'system:user:manage', + description: '用户管理页面访问权限', + module: 'system', + type: 'menu', + parent_id: 1, + status: 'active', + sort_order: 1, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '用户查看', + code: 'system:user:view', + description: '查看用户列表权限', + module: 'system', + type: 'operation', + parent_id: 2, + status: 'active', + sort_order: 1, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '用户新增', + code: 'system:user:create', + description: '新增用户权限', + module: 'system', + type: 'operation', + parent_id: 2, + status: 'active', + sort_order: 2, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '用户编辑', + code: 'system:user:edit', + description: '编辑用户权限', + module: 'system', + type: 'operation', + parent_id: 2, + status: 'active', + sort_order: 3, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '用户删除', + code: 'system:user:delete', + description: '删除用户权限', + module: 'system', + type: 'operation', + parent_id: 2, + status: 'active', + sort_order: 4, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '角色管理', + code: 'system:role:manage', + description: '角色管理页面访问权限', + module: 'system', + type: 'menu', + parent_id: 1, + status: 'active', + sort_order: 2, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '角色查看', + code: 'system:role:view', + description: '查看角色列表权限', + module: 'system', + type: 'operation', + parent_id: 7, + status: 'active', + sort_order: 1, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '角色新增', + code: 'system:role:create', + description: '新增角色权限', + module: 'system', + type: 'operation', + parent_id: 7, + status: 'active', + sort_order: 2, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '角色编辑', + code: 'system:role:edit', + description: '编辑角色权限', + module: 'system', + type: 'operation', + parent_id: 7, + status: 'active', + sort_order: 3, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '角色删除', + code: 'system:role:delete', + description: '删除角色权限', + module: 'system', + type: 'operation', + parent_id: 7, + status: 'active', + sort_order: 4, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '权限管理', + code: 'system:permission:manage', + description: '权限管理页面访问权限', + module: 'system', + type: 'menu', + parent_id: 1, + status: 'active', + sort_order: 3, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '权限查看', + code: 'system:permission:view', + description: '查看权限列表权限', + module: 'system', + type: 'operation', + parent_id: 12, + status: 'active', + sort_order: 1, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '权限分配', + code: 'system:permission:assign', + description: '分配权限给角色权限', + module: 'system', + type: 'operation', + parent_id: 12, + status: 'active', + sort_order: 2, + created_at: new Date(), + updated_at: new Date() + }, + + // 保险管理模块权限 + { + name: '保险管理', + code: 'insurance:manage', + description: '保险管理模块访问权限', + module: 'insurance', + type: 'menu', + parent_id: null, + status: 'active', + sort_order: 2, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '保险申请管理', + code: 'insurance:application:manage', + description: '保险申请管理页面访问权限', + module: 'insurance', + type: 'menu', + parent_id: 15, + status: 'active', + sort_order: 1, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '保险申请查看', + code: 'insurance:application:view', + description: '查看保险申请权限', + module: 'insurance', + type: 'operation', + parent_id: 16, + status: 'active', + sort_order: 1, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '保险申请审核', + code: 'insurance:application:review', + description: '审核保险申请权限', + module: 'insurance', + type: 'operation', + parent_id: 16, + status: 'active', + sort_order: 2, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '保单管理', + code: 'insurance:policy:manage', + description: '保单管理页面访问权限', + module: 'insurance', + type: 'menu', + parent_id: 15, + status: 'active', + sort_order: 2, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '保单查看', + code: 'insurance:policy:view', + description: '查看保单权限', + module: 'insurance', + type: 'operation', + parent_id: 19, + status: 'active', + sort_order: 1, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '理赔管理', + code: 'insurance:claim:manage', + description: '理赔管理页面访问权限', + module: 'insurance', + type: 'menu', + parent_id: 15, + status: 'active', + sort_order: 3, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '理赔查看', + code: 'insurance:claim:view', + description: '查看理赔权限', + module: 'insurance', + type: 'operation', + parent_id: 21, + status: 'active', + sort_order: 1, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '理赔审核', + code: 'insurance:claim:review', + description: '审核理赔权限', + module: 'insurance', + type: 'operation', + parent_id: 21, + status: 'active', + sort_order: 2, + created_at: new Date(), + updated_at: new Date() + }, + + // 监管任务模块权限 + { + name: '监管任务', + code: 'supervision:manage', + description: '监管任务模块访问权限', + module: 'supervision', + type: 'menu', + parent_id: null, + status: 'active', + sort_order: 3, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '监管任务查看', + code: 'supervision:task:view', + description: '查看监管任务权限', + module: 'supervision', + type: 'operation', + parent_id: 24, + status: 'active', + sort_order: 1, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '监管任务创建', + code: 'supervision:task:create', + description: '创建监管任务权限', + module: 'supervision', + type: 'operation', + parent_id: 24, + status: 'active', + sort_order: 2, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '监管任务分配', + code: 'supervision:task:assign', + description: '分配监管任务权限', + module: 'supervision', + type: 'operation', + parent_id: 24, + status: 'active', + sort_order: 3, + created_at: new Date(), + updated_at: new Date() + }, + + // 设备管理模块权限 + { + name: '设备管理', + code: 'device:manage', + description: '设备管理模块访问权限', + module: 'device', + type: 'menu', + parent_id: null, + status: 'active', + sort_order: 4, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '设备查看', + code: 'device:view', + description: '查看设备权限', + module: 'device', + type: 'operation', + parent_id: 28, + status: 'active', + sort_order: 1, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '设备新增', + code: 'device:create', + description: '新增设备权限', + module: 'device', + type: 'operation', + parent_id: 28, + status: 'active', + sort_order: 2, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '设备编辑', + code: 'device:edit', + description: '编辑设备权限', + module: 'device', + type: 'operation', + parent_id: 28, + status: 'active', + sort_order: 3, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '设备删除', + code: 'device:delete', + description: '删除设备权限', + module: 'device', + type: 'operation', + parent_id: 28, + status: 'active', + sort_order: 4, + created_at: new Date(), + updated_at: new Date() + }, + + // 日志管理模块权限 + { + name: '日志管理', + code: 'log:manage', + description: '日志管理模块访问权限', + module: 'log', + type: 'menu', + parent_id: null, + status: 'active', + sort_order: 5, + created_at: new Date(), + updated_at: new Date() + }, + { + name: '操作日志查看', + code: 'log:operation:view', + description: '查看操作日志权限', + module: 'log', + type: 'operation', + parent_id: 33, + status: 'active', + sort_order: 1, + created_at: new Date(), + updated_at: new Date() + } + ], {}); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.bulkDelete('permissions', null, {}); + } +}; \ No newline at end of file diff --git a/insurance_backend/src/app.js b/insurance_backend/src/app.js index aefd73e..9edc892 100644 --- a/insurance_backend/src/app.js +++ b/insurance_backend/src/app.js @@ -17,11 +17,15 @@ app.use(cors({ credentials: true })); -// 速率限制 +// 速率限制 - 开发环境下放宽限制 const limiter = rateLimit({ - windowMs: 15 * 60 * 1000, // 15分钟 - max: 100, // 限制每个IP每15分钟最多100个请求 - message: '请求过于频繁,请稍后再试' + windowMs: 1 * 60 * 1000, // 1分钟 + max: 1000, // 限制每个IP每1分钟最多1000个请求 + message: '请求过于频繁,请稍后再试', + skip: (req) => { + // 在开发环境下跳过限流 + return process.env.NODE_ENV === 'development'; + } }); app.use(limiter); @@ -56,6 +60,7 @@ app.use('/api/insurance-types', require('../routes/insuranceTypes')); app.use('/api/policies', require('../routes/policies')); app.use('/api/claims', require('../routes/claims')); app.use('/api/system', require('../routes/system')); +app.use('/api/dashboard', require('../routes/dashboard')); app.use('/api/operation-logs', require('../routes/operationLogs')); app.use('/api/menus', require('../routes/menus')); app.use('/api/data-warehouse', require('../routes/dataWarehouse')); @@ -73,6 +78,10 @@ app.use('/api/livestock-claims', require('../routes/livestockClaims')); app.use('/api/devices', require('../routes/devices')); app.use('/api/device-alerts', require('../routes/deviceAlerts')); +// 权限管理相关路由 +app.use('/api/permissions', require('../routes/permissions')); +app.use('/api/role-permissions', require('../routes/rolePermissions')); + // API文档路由 app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec, { explorer: true, diff --git a/insurance_backend/src/middleware/permissionMiddleware.js b/insurance_backend/src/middleware/permissionMiddleware.js new file mode 100644 index 0000000..908dddf --- /dev/null +++ b/insurance_backend/src/middleware/permissionMiddleware.js @@ -0,0 +1,191 @@ +const PermissionService = require('../services/permissionService'); +const jwt = require('jsonwebtoken'); + +/** + * 权限检查中间件 + * @param {string|string[]} requiredPermissions - 必需的权限代码(单个或数组) + * @param {string} checkType - 检查类型:'any'(任意一个)或 'all'(全部) + * @returns {Function} Express中间件函数 + */ +const requirePermission = (requiredPermissions, checkType = 'any') => { + return async (req, res, next) => { + try { + // 从请求头获取token + const token = req.headers.authorization?.replace('Bearer ', ''); + + if (!token) { + return res.status(401).json({ + success: false, + message: '未提供认证令牌' + }); + } + + // 验证token并获取用户信息 + const decoded = jwt.verify(token, process.env.JWT_SECRET); + const userId = decoded.userId; + + if (!userId) { + return res.status(401).json({ + success: false, + message: '无效的认证令牌' + }); + } + + // 确保权限是数组格式 + const permissions = Array.isArray(requiredPermissions) + ? requiredPermissions + : [requiredPermissions]; + + let hasPermission = false; + + // 根据检查类型进行权限验证 + if (checkType === 'all') { + hasPermission = await PermissionService.checkUserAllPermissions(userId, permissions); + } else { + hasPermission = await PermissionService.checkUserAnyPermission(userId, permissions); + } + + if (!hasPermission) { + return res.status(403).json({ + success: false, + message: '权限不足,无法访问此资源', + requiredPermissions: permissions + }); + } + + // 将用户ID添加到请求对象中,供后续使用 + req.userId = userId; + next(); + } catch (error) { + console.error('权限检查中间件错误:', error); + + if (error.name === 'JsonWebTokenError') { + return res.status(401).json({ + success: false, + message: '无效的认证令牌' + }); + } + + if (error.name === 'TokenExpiredError') { + return res.status(401).json({ + success: false, + message: '认证令牌已过期' + }); + } + + return res.status(500).json({ + success: false, + message: '权限检查失败' + }); + } + }; +}; + +/** + * 检查单个权限的中间件 + * @param {string} permission - 权限代码 + * @returns {Function} Express中间件函数 + */ +const requireSinglePermission = (permission) => { + return requirePermission(permission, 'any'); +}; + +/** + * 检查多个权限中任意一个的中间件 + * @param {string[]} permissions - 权限代码数组 + * @returns {Function} Express中间件函数 + */ +const requireAnyPermission = (permissions) => { + return requirePermission(permissions, 'any'); +}; + +/** + * 检查多个权限全部具备的中间件 + * @param {string[]} permissions - 权限代码数组 + * @returns {Function} Express中间件函数 + */ +const requireAllPermissions = (permissions) => { + return requirePermission(permissions, 'all'); +}; + +/** + * 管理员权限检查中间件 + * @returns {Function} Express中间件函数 + */ +const requireAdmin = () => { + return requireSinglePermission('system:admin'); +}; + +/** + * 超级管理员权限检查中间件 + * @returns {Function} Express中间件函数 + */ +const requireSuperAdmin = () => { + return requireSinglePermission('system:super_admin'); +}; + +/** + * 权限检查装饰器(用于控制器方法) + * @param {string|string[]} permissions - 权限代码 + * @param {string} checkType - 检查类型 + * @returns {Function} 装饰器函数 + */ +const withPermission = (permissions, checkType = 'any') => { + return (target, propertyKey, descriptor) => { + const originalMethod = descriptor.value; + + descriptor.value = async function(req, res, next) { + try { + const middleware = requirePermission(permissions, checkType); + await new Promise((resolve, reject) => { + middleware(req, res, (err) => { + if (err) reject(err); + else resolve(); + }); + }); + + return originalMethod.call(this, req, res, next); + } catch (error) { + return res.status(403).json({ + success: false, + message: '权限不足' + }); + } + }; + + return descriptor; + }; +}; + +/** + * 动态权限检查中间件 + * 根据请求参数动态确定所需权限 + * @param {Function} permissionResolver - 权限解析函数 + * @returns {Function} Express中间件函数 + */ +const requireDynamicPermission = (permissionResolver) => { + return async (req, res, next) => { + try { + const requiredPermissions = await permissionResolver(req); + const middleware = requirePermission(requiredPermissions); + return middleware(req, res, next); + } catch (error) { + console.error('动态权限检查失败:', error); + return res.status(500).json({ + success: false, + message: '权限检查失败' + }); + } + }; +}; + +module.exports = { + requirePermission, + requireSinglePermission, + requireAnyPermission, + requireAllPermissions, + requireAdmin, + requireSuperAdmin, + withPermission, + requireDynamicPermission +}; \ No newline at end of file diff --git a/insurance_backend/src/services/permissionService.js b/insurance_backend/src/services/permissionService.js new file mode 100644 index 0000000..b4b2577 --- /dev/null +++ b/insurance_backend/src/services/permissionService.js @@ -0,0 +1,254 @@ +const { User, Role, Permission, RolePermission } = require('../models'); + +/** + * 权限服务类 - 提供动态权限检查和管理功能 + */ +class PermissionService { + /** + * 检查用户是否具有指定权限 + * @param {number} userId - 用户ID + * @param {string} permissionCode - 权限代码 + * @returns {Promise} 是否具有权限 + */ + static async checkUserPermission(userId, permissionCode) { + try { + const user = await User.findByPk(userId, { + include: [{ + model: Role, + as: 'role', + include: [{ + model: Permission, + as: 'permissions', + where: { code: permissionCode }, + required: false + }] + }] + }); + + if (!user || !user.role) { + return false; + } + + return user.role.permissions && user.role.permissions.length > 0; + } catch (error) { + console.error('检查用户权限失败:', error); + return false; + } + } + + /** + * 检查用户是否具有多个权限中的任意一个 + * @param {number} userId - 用户ID + * @param {string[]} permissionCodes - 权限代码数组 + * @returns {Promise} 是否具有任意一个权限 + */ + static async checkUserAnyPermission(userId, permissionCodes) { + try { + const user = await User.findByPk(userId, { + include: [{ + model: Role, + as: 'role', + include: [{ + model: Permission, + as: 'permissions', + where: { code: permissionCodes }, + required: false + }] + }] + }); + + if (!user || !user.role) { + return false; + } + + return user.role.permissions && user.role.permissions.length > 0; + } catch (error) { + console.error('检查用户权限失败:', error); + return false; + } + } + + /** + * 检查用户是否具有所有指定权限 + * @param {number} userId - 用户ID + * @param {string[]} permissionCodes - 权限代码数组 + * @returns {Promise} 是否具有所有权限 + */ + static async checkUserAllPermissions(userId, permissionCodes) { + try { + const user = await User.findByPk(userId, { + include: [{ + model: Role, + as: 'role', + include: [{ + model: Permission, + as: 'permissions', + where: { code: permissionCodes }, + required: false + }] + }] + }); + + if (!user || !user.role) { + return false; + } + + const userPermissions = user.role.permissions || []; + return permissionCodes.every(code => + userPermissions.some(permission => permission.code === code) + ); + } catch (error) { + console.error('检查用户权限失败:', error); + return false; + } + } + + /** + * 获取用户的所有权限 + * @param {number} userId - 用户ID + * @returns {Promise} 用户权限代码数组 + */ + static async getUserPermissions(userId) { + try { + const user = await User.findByPk(userId, { + include: [{ + model: Role, + as: 'role', + include: [{ + model: Permission, + as: 'permissions' + }] + }] + }); + + if (!user || !user.role || !user.role.permissions) { + return []; + } + + return user.role.permissions.map(permission => permission.code); + } catch (error) { + console.error('获取用户权限失败:', error); + return []; + } + } + + /** + * 获取角色的所有权限 + * @param {number} roleId - 角色ID + * @returns {Promise} 权限对象数组 + */ + static async getRolePermissions(roleId) { + try { + const role = await Role.findByPk(roleId, { + include: [{ + model: Permission, + as: 'permissions' + }] + }); + + return role ? role.permissions || [] : []; + } catch (error) { + console.error('获取角色权限失败:', error); + return []; + } + } + + /** + * 检查权限是否存在 + * @param {string} permissionCode - 权限代码 + * @returns {Promise} 权限是否存在 + */ + static async permissionExists(permissionCode) { + try { + const permission = await Permission.findOne({ + where: { code: permissionCode } + }); + return !!permission; + } catch (error) { + console.error('检查权限存在性失败:', error); + return false; + } + } + + /** + * 获取权限树结构 + * @returns {Promise} 权限树 + */ + static async getPermissionTree() { + try { + const permissions = await Permission.findAll({ + order: [['module', 'ASC'], ['type', 'ASC'], ['code', 'ASC']] + }); + + // 按模块分组 + const modules = {}; + permissions.forEach(permission => { + if (!modules[permission.module]) { + modules[permission.module] = { + module: permission.module, + permissions: [] + }; + } + modules[permission.module].permissions.push(permission); + }); + + return Object.values(modules); + } catch (error) { + console.error('获取权限树失败:', error); + return []; + } + } + + /** + * 批量检查用户权限 + * @param {number} userId - 用户ID + * @param {string[]} permissionCodes - 权限代码数组 + * @returns {Promise} 权限检查结果对象 + */ + static async batchCheckUserPermissions(userId, permissionCodes) { + try { + const userPermissions = await this.getUserPermissions(userId); + const result = {}; + + permissionCodes.forEach(code => { + result[code] = userPermissions.includes(code); + }); + + return result; + } catch (error) { + console.error('批量检查用户权限失败:', error); + return {}; + } + } + + /** + * 获取用户可访问的菜单 + * @param {number} userId - 用户ID + * @returns {Promise} 可访问的菜单数组 + */ + static async getUserAccessibleMenus(userId) { + try { + const userPermissions = await this.getUserPermissions(userId); + + // 这里可以根据权限过滤菜单 + // 示例:假设菜单与权限有对应关系 + const allMenus = [ + { id: 1, name: '用户管理', permission: 'user:view', path: '/users' }, + { id: 2, name: '角色管理', permission: 'role:view', path: '/roles' }, + { id: 3, name: '权限管理', permission: 'permission:view', path: '/permissions' }, + { id: 4, name: '保单管理', permission: 'policy:view', path: '/policies' }, + { id: 5, name: '理赔管理', permission: 'claim:view', path: '/claims' }, + { id: 6, name: '系统设置', permission: 'system:view', path: '/system' } + ]; + + return allMenus.filter(menu => + userPermissions.includes(menu.permission) + ); + } catch (error) { + console.error('获取用户可访问菜单失败:', error); + return []; + } + } +} + +module.exports = PermissionService; \ No newline at end of file diff --git a/insurance_backend/test_api.js b/insurance_backend/test_api.js index 9fad042..2f917e6 100644 --- a/insurance_backend/test_api.js +++ b/insurance_backend/test_api.js @@ -1,25 +1,32 @@ // 简单的API测试脚本 const axios = require('axios'); -async function testPublicApi() { +async function testAuthenticatedApi() { try { - console.log('测试公开菜单API...'); - const response = await axios.get('http://localhost:3000/api/menus/public'); - console.log('✅ 公开菜单API测试成功'); + console.log('测试认证菜单API...'); + // 注意:这个测试需要有效的JWT token + const response = await axios.get('http://localhost:3000/api/menus', { + headers: { + 'Authorization': 'Bearer YOUR_JWT_TOKEN_HERE' + } + }); + console.log('✅ 认证菜单API测试成功'); console.log('返回数据:', response.data); return true; } catch (error) { - console.error('❌ 公开菜单API测试失败:', error.message); + console.error('❌ 认证菜单API测试失败:', error.message); + console.log('提示:请确保服务器运行并提供有效的JWT token'); return false; } } async function testAllApis() { console.log('开始API测试...'); - const publicApiResult = await testPublicApi(); + console.log('注意:所有API现在都需要认证,请确保提供有效的JWT token'); + const authApiResult = await testAuthenticatedApi(); console.log('\n测试总结:'); - console.log(`公开菜单API: ${publicApiResult ? '通过' : '失败'}`); + console.log(`认证菜单API: ${authApiResult ? '通过' : '失败'}`); } testAllApis().then(() => { diff --git a/insurance_backend/test_fixed_token.js b/insurance_backend/test_fixed_token.js new file mode 100644 index 0000000..461dbdb --- /dev/null +++ b/insurance_backend/test_fixed_token.js @@ -0,0 +1,109 @@ +const axios = require('axios'); + +const BASE_URL = 'http://localhost:3000'; + +// 测试固定令牌功能 +async function testFixedToken() { + try { + console.log('🧪 开始测试固定令牌功能...\n'); + + // 1. 登录获取JWT令牌 + console.log('1. 登录获取JWT令牌...'); + const loginResponse = await axios.post(`${BASE_URL}/api/auth/login`, { + username: 'admin', + password: '123456' + }); + + if (loginResponse.data.code !== 200) { + console.error('❌ 登录失败:', loginResponse.data.message); + return; + } + + const jwtToken = loginResponse.data.data.accessToken; + const userId = loginResponse.data.data.user.id; + console.log('✅ 登录成功,用户ID:', userId); + + // 2. 检查用户是否已有固定令牌 + console.log('\n2. 检查用户固定令牌状态...'); + const tokenInfoResponse = await axios.get(`${BASE_URL}/api/users/${userId}/fixed-token`, { + headers: { Authorization: `Bearer ${jwtToken}` } + }); + + console.log('✅ 令牌状态:', tokenInfoResponse.data.data); + + // 3. 如果没有固定令牌,则生成一个 + let fixedToken; + if (!tokenInfoResponse.data.data.hasToken) { + console.log('\n3. 生成固定令牌...'); + const generateResponse = await axios.post(`${BASE_URL}/api/users/${userId}/fixed-token`, {}, { + headers: { Authorization: `Bearer ${jwtToken}` } + }); + + if (generateResponse.data.code === 200) { + fixedToken = generateResponse.data.data.fixed_token; + console.log('✅ 固定令牌生成成功'); + console.log('🔑 固定令牌:', fixedToken); + } else { + console.error('❌ 固定令牌生成失败:', generateResponse.data.message); + return; + } + } else { + console.log('\n3. 用户已有固定令牌,重新生成...'); + const regenerateResponse = await axios.put(`${BASE_URL}/api/users/${userId}/fixed-token`, {}, { + headers: { Authorization: `Bearer ${jwtToken}` } + }); + + if (regenerateResponse.data.code === 200) { + fixedToken = regenerateResponse.data.data.fixed_token; + console.log('✅ 固定令牌重新生成成功'); + console.log('🔑 新固定令牌:', fixedToken); + } else { + console.error('❌ 固定令牌重新生成失败:', regenerateResponse.data.message); + return; + } + } + + // 4. 使用固定令牌访问API + console.log('\n4. 使用固定令牌访问用户列表API...'); + const usersResponse = await axios.get(`${BASE_URL}/api/users`, { + headers: { Authorization: `Bearer ${fixedToken}` } + }); + + if (usersResponse.data.code === 200) { + console.log('✅ 使用固定令牌访问API成功'); + console.log('📊 用户数量:', usersResponse.data.data.users.length); + } else { + console.error('❌ 使用固定令牌访问API失败:', usersResponse.data.message); + } + + // 5. 测试无效令牌 + console.log('\n5. 测试无效固定令牌...'); + try { + await axios.get(`${BASE_URL}/api/users`, { + headers: { Authorization: 'Bearer ft_invalid_token' } + }); + console.error('❌ 无效令牌测试失败:应该返回401错误'); + } catch (error) { + if (error.response && error.response.status === 401) { + console.log('✅ 无效令牌正确返回401错误'); + } else { + console.error('❌ 无效令牌测试异常:', error.message); + } + } + + // 6. 再次检查令牌信息 + console.log('\n6. 再次检查令牌信息...'); + const finalTokenInfoResponse = await axios.get(`${BASE_URL}/api/users/${userId}/fixed-token`, { + headers: { Authorization: `Bearer ${jwtToken}` } + }); + console.log('✅ 最终令牌状态:', finalTokenInfoResponse.data.data); + + console.log('\n🎉 固定令牌功能测试完成!'); + + } catch (error) { + console.error('❌ 测试过程中发生错误:', error.response?.data || error.message); + } +} + +// 运行测试 +testFixedToken(); \ No newline at end of file diff --git a/insurance_backend/test_role_permissions_api.js b/insurance_backend/test_role_permissions_api.js new file mode 100644 index 0000000..820fe40 --- /dev/null +++ b/insurance_backend/test_role_permissions_api.js @@ -0,0 +1,75 @@ +const axios = require('axios'); + +const BASE_URL = 'http://localhost:3000/api'; +const ADMIN_TOKEN = '5659725423f665a8bf5053b37e624ea86387f9113ae77ac75fc102012a349180'; + +// 创建axios实例 +const api = axios.create({ + baseURL: BASE_URL, + headers: { + 'Authorization': `Bearer ${ADMIN_TOKEN}`, + 'Content-Type': 'application/json' + } +}); + +async function testRolePermissionsAPI() { + console.log('开始测试角色权限管理API...\n'); + + // 测试1: 获取所有权限 + try { + console.log('1. 测试获取所有权限...'); + const response = await api.get('/role-permissions/permissions'); + console.log('✅ 获取所有权限成功'); + console.log('权限数量:', response.data.data?.length || 0); + } catch (error) { + console.log('❌ 获取所有权限失败:', error.response?.data?.message || error.message); + } + + // 测试2: 获取所有角色及其权限 + try { + console.log('\n2. 测试获取所有角色及其权限...'); + const response = await api.get('/role-permissions/roles'); + console.log('✅ 获取所有角色及其权限成功'); + const roles = response.data.data?.roles || []; + console.log('角色数量:', roles.length); + if (roles && roles.length > 0) { + roles.forEach(role => { + console.log(` - ${role.name}: ${role.permissionCount || 0} 个权限`); + }); + } + } catch (error) { + console.log('❌ 获取所有角色及其权限失败:', error.response?.data?.message || error.message); + } + + // 测试3: 获取特定角色的详细权限 + try { + console.log('\n3. 测试获取特定角色的详细权限...'); + const response = await api.get('/role-permissions/roles/1/permissions'); + console.log('✅ 获取特定角色的详细权限成功'); + console.log('权限树结构:', response.data.data ? '已构建' : '未构建'); + } catch (error) { + console.log('❌ 获取特定角色的详细权限失败:', error.response?.data?.message || error.message); + } + + // 测试4: 权限统计 + try { + console.log('\n4. 测试权限统计...'); + const response = await api.get('/role-permissions/stats'); + console.log('✅ 权限统计成功'); + if (response.data.data) { + const stats = response.data.data; + console.log('统计信息:'); + console.log(` - 总角色数: ${stats.overview?.totalRoles || 0}`); + console.log(` - 总权限数: ${stats.overview?.totalPermissions || 0}`); + console.log(` - 总分配数: ${stats.overview?.totalAssignments || 0}`); + console.log(` - 平均每角色权限数: ${stats.overview?.averagePermissionsPerRole || 0}`); + } + } catch (error) { + console.log('❌ 权限统计失败:', error.response?.data?.message || error.message); + } + + console.log('\n测试完成!'); +} + +// 运行测试 +testRolePermissionsAPI().catch(console.error); \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/API_INTEGRATION.md b/mini_program/farm-monitor-dashboard/API_INTEGRATION.md deleted file mode 100644 index a19fa00..0000000 --- a/mini_program/farm-monitor-dashboard/API_INTEGRATION.md +++ /dev/null @@ -1,241 +0,0 @@ -# 智能设备API接口集成文档 - -## 概述 -本文档描述了智慧养殖小程序中智能设备管理系统的API接口集成情况。 - -## 基础配置 -- **API基础地址**: `http://localhost:5350` -- **认证方式**: Bearer Token (存储在localStorage中) -- **请求超时**: 10秒 -- **内容类型**: application/json - -## 智能设备接口 - -### 1. 智能项圈管理 (`/api/smart-devices/collars`) - -#### 获取项圈设备列表 -- **接口**: `GET /api/smart-devices/collars` -- **参数**: - - `page` (可选): 页码 - - `limit` (可选): 每页数量 - - `status` (可选): 设备状态筛选 -- **返回**: 项圈设备列表数据 - -#### 绑定项圈设备 -- **接口**: `POST /api/smart-devices/collars/bind` -- **参数**: - ```json - { - "collarId": "string", - "animalId": "string" - } - ``` - -#### 解绑项圈设备 -- **接口**: `POST /api/smart-devices/collars/unbind` -- **参数**: - ```json - { - "collarId": "string" - } - ``` - -### 2. 智能耳标管理 (`/api/smart-devices/eartags`) - -#### 获取耳标设备列表 -- **接口**: `GET /api/smart-devices/eartags` -- **参数**: - - `page` (可选): 页码 - - `limit` (可选): 每页数量 - - `status` (可选): 设备状态筛选 -- **返回**: 耳标设备列表数据 - -#### 绑定耳标设备 -- **接口**: `POST /api/smart-devices/eartags/bind` -- **参数**: - ```json - { - "earTagId": "string", - "animalId": "string" - } - ``` - -#### 解绑耳标设备 -- **接口**: `POST /api/smart-devices/eartags/unbind` -- **参数**: - ```json - { - "earTagId": "string" - } - ``` - -#### 获取耳标设备详情 -- **接口**: `GET /api/smart-devices/eartags/{earTagId}` -- **返回**: 耳标设备详细信息 - -#### 更新耳标设备信息 -- **接口**: `PUT /api/smart-devices/eartags/{earTagId}` -- **参数**: 设备更新数据 - -#### 删除耳标设备 -- **接口**: `DELETE /api/smart-devices/eartags/{earTagId}` - -### 3. 智能脚环管理 (`/api/smart-devices/anklets`) - -#### 获取脚环设备列表 -- **接口**: `GET /api/smart-devices/anklets` -- **参数**: - - `page` (可选): 页码 - - `limit` (可选): 每页数量 - - `status` (可选): 设备状态筛选 -- **返回**: 脚环设备列表数据 - -#### 绑定脚环设备 -- **接口**: `POST /api/smart-devices/anklets/bind` -- **参数**: - ```json - { - "ankleId": "string", - "animalId": "string" - } - ``` - -#### 解绑脚环设备 -- **接口**: `POST /api/smart-devices/anklets/unbind` -- **参数**: - ```json - { - "ankleId": "string" - } - ``` - -### 4. 智能主机管理 (`/api/smart-devices/hosts`) - -#### 获取主机设备列表 -- **接口**: `GET /api/smart-devices/hosts` -- **参数**: - - `page` (可选): 页码 - - `limit` (可选): 每页数量 - - `status` (可选): 设备状态筛选 -- **返回**: 主机设备列表数据 - -#### 重启主机设备 -- **接口**: `POST /api/smart-devices/hosts/restart` -- **参数**: - ```json - { - "hostId": "string" - } - ``` - -#### 启动主机设备 -- **接口**: `POST /api/smart-devices/hosts/start` -- **参数**: - ```json - { - "hostId": "string" - } - ``` - -#### 停止主机设备 -- **接口**: `POST /api/smart-devices/hosts/stop` -- **参数**: - ```json - { - "hostId": "string" - } - ``` - -### 5. 设备搜索和状态监控 (`/api/smart-devices`) - -#### 设备搜索 -- **接口**: `GET /api/smart-devices/search` -- **参数**: - - `keyword` (可选): 搜索关键词 - - `deviceType` (可选): 设备类型 - - `status` (可选): 设备状态 -- **返回**: 搜索结果 - -#### 获取设备状态监控 -- **接口**: `GET /api/smart-devices/status` -- **参数**: - - `deviceIds` (可选): 设备ID数组 - - `deviceType` (可选): 设备类型 -- **返回**: 设备状态数据 - -#### 获取设备统计信息 -- **接口**: `GET /api/smart-devices/statistics` -- **返回**: 设备统计汇总数据 - -#### 批量更新设备状态 -- **接口**: `POST /api/smart-devices/batch-update` -- **参数**: - ```json - { - "deviceIds": ["string"], - "statusData": {} - } - ``` - -#### 获取设备实时数据 -- **接口**: `GET /api/smart-devices/{deviceType}/{deviceId}/realtime` -- **返回**: 设备实时监控数据 - -#### 获取设备历史数据 -- **接口**: `GET /api/smart-devices/{deviceType}/{deviceId}/history` -- **参数**: - - `startTime` (可选): 开始时间 - - `endTime` (可选): 结束时间 -- **返回**: 设备历史数据 - -## 错误处理 - -所有API调用都包含错误处理机制: -- 网络错误时显示控制台错误信息 -- API错误时抛出异常供组件处理 -- 提供模拟数据作为降级方案 - -## 使用示例 - -### 在Vue组件中使用API服务 - -```javascript -import { getCollarDevices, bindCollar } from '@/services/collarService' - -export default { - async mounted() { - try { - const response = await getCollarDevices() - this.devices = response.data - } catch (error) { - console.error('加载设备失败:', error) - // 使用模拟数据 - this.devices = this.getMockData() - } - }, - - async handleBind(device) { - try { - await bindCollar(device.id, 'animal_123') - device.isBound = true - } catch (error) { - console.error('绑定失败:', error) - } - } -} -``` - -## 注意事项 - -1. 所有API调用都需要有效的认证token -2. 请求失败时会自动使用模拟数据 -3. 设备绑定操作需要提供动物ID -4. 主机操作(启动/重启/停止)需要确认设备状态 -5. 搜索和筛选功能支持多参数组合查询 - -## 更新日志 - -- **2025-09-18**: 初始版本,集成所有智能设备API接口 -- 统一API路径为 `/api/smart-devices/*` -- 添加完整的错误处理和模拟数据支持 -- 实现设备绑定/解绑、状态监控等功能 diff --git a/mini_program/farm-monitor-dashboard/API_INTEGRATION_COMPLETE.md b/mini_program/farm-monitor-dashboard/API_INTEGRATION_COMPLETE.md deleted file mode 100644 index de5fd6d..0000000 --- a/mini_program/farm-monitor-dashboard/API_INTEGRATION_COMPLETE.md +++ /dev/null @@ -1,119 +0,0 @@ -# 智能耳标API集成完成报告 - -## ✅ 集成状态:已完成 - -### API接口信息 -- **接口地址**: `http://localhost:5350/api/smart-devices/public/eartags` -- **请求方法**: GET -- **参数**: `page=1&limit=10&refresh=true` -- **认证**: 无需认证(使用公开API) - -### 配置更新 - -#### 1. API配置文件 (`utils/api.js`) -```javascript -const config = { - baseUrl: 'http://localhost:5350/api', // 智能耳标API地址 - timeout: 10000, - header: { - 'Content-Type': 'application/json' - } -} -``` - -#### 2. 智能耳标页面 (`pages/device/eartag/eartag.js`) -```javascript -// 使用真实的智能耳标API接口(公开API,无需认证) -const response = await get('/smart-devices/public/eartags?page=1&limit=10&refresh=true') -``` - -### API响应数据格式 -```json -{ - "success": true, - "message": "数据获取成功", - "data": { - "list": [ - { - "id": 99833, - "sn": "DEV099833", - "rsrp": "-", - "bandge_status": 1, - "deviceInfo": "0", - "temperature": "39.00", - "status": "在线", - "steps": 0, - "location": "无定位", - "updateInte": "..." - } - ], - "pagination": { - "page": 1, - "limit": 10, - "total": 100 - } - } -} -``` - -### 字段映射 -智能耳标页面会自动将API数据映射为前端显示格式: -- `sn` → `eartagNumber` (耳标编号) -- `temperature` → `temperature` (体温) -- `status` → `isBound` (绑定状态) -- `steps` → `totalMovement` (运动量) -- `location` → `location` (位置) - -### 测试结果 -- ✅ API连接成功 (状态码: 200) -- ✅ 数据返回正常 -- ✅ 字段映射正确 -- ✅ 无需认证即可访问 - -## 🚀 使用说明 - -### 1. 启动后端服务 -```bash -cd backend -npm start -``` -后端将在 `http://localhost:5350` 运行 - -### 2. 微信开发者工具配置 -- 打开微信开发者工具 -- 点击右上角"详情"按钮 -- 在"本地设置"中勾选 **"不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书"** - -### 3. 测试智能耳标功能 -1. 点击首页"智能设备" → "智能耳标" -2. 页面将自动调用真实API获取数据 -3. 数据会实时显示在列表中 - -## 📋 功能特性 - -- **动态数据获取**: 实时从后端API获取智能耳标数据 -- **字段自动映射**: 自动将API字段映射为中文显示 -- **分页支持**: 支持分页加载更多数据 -- **搜索功能**: 支持按耳标编号搜索 -- **状态筛选**: 支持按绑定状态筛选 -- **下拉刷新**: 支持下拉刷新获取最新数据 - -## 🔧 技术实现 - -- **API工具**: 使用 `utils/api.js` 统一处理API请求 -- **错误处理**: 完善的错误处理和用户提示 -- **数据缓存**: 支持数据缓存和实时更新 -- **响应式设计**: 适配不同屏幕尺寸 - -## 📝 注意事项 - -1. **域名白名单**: 生产环境需要在微信公众平台配置域名白名单 -2. **HTTPS要求**: 生产环境必须使用HTTPS协议 -3. **数据安全**: 当前使用公开API,生产环境建议使用认证API -4. **性能优化**: 大数据量时建议实现虚拟滚动 - ---- - -**集成完成时间**: 2025年9月23日 -**API状态**: 正常运行 -**测试状态**: 通过 diff --git a/mini_program/farm-monitor-dashboard/API_INTEGRATION_GUIDE.md b/mini_program/farm-monitor-dashboard/API_INTEGRATION_GUIDE.md deleted file mode 100644 index 01a9d9b..0000000 --- a/mini_program/farm-monitor-dashboard/API_INTEGRATION_GUIDE.md +++ /dev/null @@ -1,122 +0,0 @@ -# 智能耳标API集成指南 - -## 📡 API接口信息 - -**接口地址**: `/api/iot-jbq-client` -**请求方法**: GET -**数据格式**: JSON - -## 🔄 字段映射和数据处理 - -### 输入字段映射 -智能耳标页面会自动处理以下API字段的映射: - -| 页面显示字段 | API可能字段名 | 处理函数 | 说明 | -|-------------|-------------|----------|------| -| 耳标编号 | `eartagNumber`, `eartag_number`, `id` | 直接映射 | 唯一标识符 | -| 绑定状态 | `isBound`, `is_bound`, `bound`, `status` | `checkIfBound()` | 判断是否已绑定 | -| 设备电量 | `batteryLevel`, `battery_level`, `battery`, `power` | `formatBatteryLevel()` | 格式化电量百分比 | -| 设备温度 | `temperature`, `temp`, `device_temp` | `formatTemperature()` | 格式化温度值 | -| 被采集主机 | `hostNumber`, `host_number`, `hostId`, `host_id`, `collector` | `formatHostNumber()` | 主机标识 | -| 总运动量 | `totalMovement`, `total_movement`, `movement_total` | `formatMovement()` | 运动量数值 | -| 今日运动量 | `todayMovement`, `today_movement`, `movement_today` | `formatMovement()` | 今日运动量 | -| 更新时间 | `updateTime`, `update_time`, `last_update` | `formatUpdateTime()` | 格式化时间显示 | - -### 数据处理函数 - -#### 1. `checkIfBound(item)` - 绑定状态判断 -```javascript -// 优先级判断逻辑: -// 1. 明确的绑定状态字段 -// 2. 状态字符串匹配 -// 3. 根据是否有牛只ID判断 -``` - -#### 2. `formatBatteryLevel(item)` - 电量格式化 -```javascript -// 提取电量值并四舍五入为整数 -// 默认值:0 -``` - -#### 3. `formatTemperature(item)` - 温度格式化 -```javascript -// 保留一位小数 -// 默认值:0.0 -``` - -#### 4. `formatUpdateTime(timeStr)` - 时间格式化 -```javascript -// 转换为中文格式:YYYY-MM-DD HH:mm:ss -// 处理各种时间格式 -``` - -## 🎯 功能特性 - -### 1. 动态数据加载 -- ✅ 自动调用API接口获取数据 -- ✅ 实时更新筛选标签计数 -- ✅ 支持下拉刷新 - -### 2. 筛选功能 -- ✅ **耳标总数**: 显示所有耳标数量 -- ✅ **已绑定数量**: 显示已绑定耳标数量 -- ✅ **未绑定数量**: 显示未绑定耳标数量 - -### 3. 搜索功能 -- ✅ 支持按耳标编号搜索 -- ✅ 支持按主机号搜索 -- ✅ 实时搜索过滤 - -### 4. 交互功能 -- ✅ 点击耳标项查看详情 -- ✅ 添加新耳标功能 -- ✅ 绑定状态显示 - -## 🎨 UI设计特点 - -### 严格按照图片设计实现: -1. **顶部绿色区域**: 搜索框 + 添加按钮 -2. **筛选标签**: 三个标签页,蓝色下划线选中效果 -3. **耳标列表**: 卡片式布局,包含所有字段信息 -4. **绑定状态**: 蓝色"未绑定"按钮,绿色"已绑定"按钮 -5. **响应式设计**: 适配不同屏幕尺寸 - -## 🔧 技术实现 - -### 文件结构 -``` -pages/device/eartag/ -├── eartag.wxml # 页面结构 -├── eartag.wxss # 页面样式 -└── eartag.js # 页面逻辑 -``` - -### 核心功能 -- **API集成**: 使用`get('/api/iot-jbq-client')`获取数据 -- **数据处理**: 自动字段映射和格式化 -- **状态管理**: 筛选、搜索、加载状态 -- **错误处理**: API调用失败时的用户提示 - -## 📱 使用说明 - -1. **页面访问**: 通过首页"智能设备"模块进入 -2. **数据刷新**: 下拉页面刷新数据 -3. **筛选查看**: 点击顶部标签切换不同视图 -4. **搜索功能**: 在搜索框输入关键词 -5. **添加耳标**: 点击右上角"+"按钮 - -## ⚠️ 注意事项 - -1. **API兼容性**: 支持多种字段名格式,自动适配 -2. **数据验证**: 对无效数据进行默认值处理 -3. **性能优化**: 使用数据缓存,避免重复请求 -4. **错误处理**: 网络异常时显示友好提示 - -## 🚀 扩展功能 - -未来可以扩展的功能: -- 耳标详情页面 -- 批量操作功能 -- 数据导出功能 -- 实时数据更新 -- 历史数据查看 diff --git a/mini_program/farm-monitor-dashboard/API_INTEGRATION_UPDATE.md b/mini_program/farm-monitor-dashboard/API_INTEGRATION_UPDATE.md deleted file mode 100644 index f7fb837..0000000 --- a/mini_program/farm-monitor-dashboard/API_INTEGRATION_UPDATE.md +++ /dev/null @@ -1,161 +0,0 @@ -# API接口集成更新说明 - -## 更新概述 - -根据您提供的栏舍API接口 `http://localhost:5300/api/cattle-pens?page=1&pageSize=10`,我已经更新了牛只转栏记录功能,确保使用正确的API接口获取栏舍数据。 - -## 主要更新 - -### 1. API服务更新 - -**更新了栏舍API接口:** -```javascript -// 更新前 -getBarnsForTransfer: (farmId) => { - return get('/barns', { farmId }) -} - -// 更新后 -getBarnsForTransfer: (params = {}) => { - return get('/cattle-pens', params) -} -``` - -**支持分页参数:** -- `page`: 页码(默认1) -- `pageSize`: 每页数量(默认10,转栏功能中设置为100以获取更多数据) - -### 2. 数据格式适配 - -**根据API文档,栏舍API返回格式为:** -```json -{ - "success": true, - "data": { - "list": [ - { - "id": 1, - "name": "栏舍名称", - "code": "栏舍编号", - "type": "育成栏", - "capacity": 50, - "currentCount": 10, - "area": 100.50, - "location": "位置描述", - "status": "启用", - "remark": "备注", - "farmId": 1 - } - ], - "total": 100, - "page": 1, - "pageSize": 10 - }, - "message": "获取栏舍列表成功" -} -``` - -**更新了数据处理逻辑:** -```javascript -// 支持多种数据格式 -if (response && Array.isArray(response)) { - this.barns = response -} else if (response && response.data && response.data.list && Array.isArray(response.data.list)) { - this.barns = response.data.list // 主要格式 -} else if (response && response.data && Array.isArray(response.data)) { - this.barns = response.data -} else if (response && response.records && Array.isArray(response.records)) { - this.barns = response.records -} -``` - -### 3. 新增API测试功能 - -**创建了API测试页面:** -- 路径:`/api-test-page` -- 功能:测试栏舍API、转栏记录API、可用牛只API -- 显示:API响应数据的JSON格式 -- 调试:方便开发时查看API返回的数据结构 - -**在首页添加了测试入口:** -- 开发环境下显示"API测试"按钮 -- 点击可跳转到API测试页面 - -## 栏舍数据字段映射 - -根据API文档,栏舍数据包含以下字段: - -| 字段名 | 类型 | 说明 | 前端使用 | -|--------|------|------|----------| -| id | Integer | 栏舍ID | 作为选择值 | -| name | String | 栏舍名称 | 显示名称 | -| code | String | 栏舍编号 | 辅助显示 | -| type | Enum | 栏舍类型 | 分类显示 | -| capacity | Integer | 栏舍容量 | 容量信息 | -| currentCount | Integer | 当前牛只数量 | 状态信息 | -| area | Decimal | 面积(平方米) | 详细信息 | -| location | Text | 位置描述 | 详细信息 | -| status | Enum | 状态(启用/停用) | 过滤条件 | -| remark | Text | 备注 | 详细信息 | -| farmId | Integer | 所属农场ID | 关联信息 | - -## 转栏功能中的栏舍选择 - -**在转栏登记页面:** -- 转出栏舍和转入栏舍都从 `/api/cattle-pens` 接口获取 -- 显示格式:`栏舍名称 - 栏舍编号` -- 支持分页加载(pageSize=100) -- 自动处理API返回的数据格式 - -**在转栏记录显示:** -- 显示栏舍的 `name` 字段 -- 通过关联的 `fromPen` 和 `toPen` 对象获取栏舍信息 - -## 测试方法 - -### 1. 通过API测试页面 -1. 在开发环境下访问首页 -2. 点击"API测试"按钮 -3. 在测试页面点击"测试栏舍API"按钮 -4. 查看返回的JSON数据格式 - -### 2. 通过转栏功能 -1. 访问转栏记录页面 -2. 点击"转栏登记"按钮 -3. 查看栏舍下拉选择框是否正常加载数据 - -### 3. 通过浏览器开发者工具 -1. 打开浏览器开发者工具 -2. 查看Network标签页 -3. 访问转栏功能时观察API请求 -4. 检查请求URL和响应数据 - -## 错误处理 - -**API调用失败时的处理:** -- 显示错误提示信息 -- 在控制台输出详细错误信息 -- 栏舍列表为空时不影响其他功能 - -**数据格式异常时的处理:** -- 在控制台输出警告信息 -- 尝试多种数据格式解析 -- 最终解析失败时使用空数组 - -## 注意事项 - -1. **API地址** - 确保后端API `http://localhost:5300/api/cattle-pens` 正常运行 -2. **认证要求** - 需要有效的认证token -3. **数据格式** - 确保API返回的数据格式符合文档规范 -4. **分页参数** - 转栏功能中设置pageSize=100以获取更多栏舍数据 -5. **错误处理** - 网络错误和业务错误都有相应的处理机制 - -## 后续优化建议 - -1. **缓存机制** - 栏舍数据相对稳定,可以考虑缓存 -2. **搜索功能** - 栏舍数量多时可以添加搜索功能 -3. **分类筛选** - 根据栏舍类型进行筛选 -4. **状态筛选** - 只显示启用状态的栏舍 -5. **懒加载** - 栏舍数量很大时可以考虑懒加载 - -现在牛只转栏记录功能已经完全集成了正确的栏舍API接口,可以动态获取真实的栏舍数据! diff --git a/mini_program/farm-monitor-dashboard/API_PORT_UPDATE.md b/mini_program/farm-monitor-dashboard/API_PORT_UPDATE.md deleted file mode 100644 index 5db5454..0000000 --- a/mini_program/farm-monitor-dashboard/API_PORT_UPDATE.md +++ /dev/null @@ -1,154 +0,0 @@ -# API端口更新说明 - -## 更新概述 - -根据您提供的牛只转栏记录API接口 `http://localhost:5300/api/cattle-transfer-records?page=1&pageSize=10&search=`,我已经更新了API配置,将端口从5350更改为5300。 - -## 主要更新 - -### 1. API基础URL更新 - -**更新前:** -```javascript -baseURL: process.env.VUE_APP_BASE_URL || 'http://localhost:5350/api' -``` - -**更新后:** -```javascript -baseURL: process.env.VUE_APP_BASE_URL || 'http://localhost:5300/api' -``` - -### 2. 影响的API接口 - -所有API接口现在都使用新的端口5300: - -- **转栏记录相关:** - - `GET /api/cattle-transfer-records` - 获取转栏记录列表 - - `POST /api/cattle-transfer-records` - 创建转栏记录 - - `GET /api/cattle-transfer-records/{id}` - 获取转栏记录详情 - - `PUT /api/cattle-transfer-records/{id}` - 更新转栏记录 - - `DELETE /api/cattle-transfer-records/{id}` - 删除转栏记录 - - `POST /api/cattle-transfer-records/batch-delete` - 批量删除 - - `GET /api/cattle-transfer-records/available-animals` - 获取可用牛只 - -- **栏舍相关:** - - `GET /api/cattle-pens` - 获取栏舍列表 - -- **其他API:** - - 所有其他API接口也会使用新的端口 - -### 3. API测试功能增强 - -**新增搜索功能测试:** -- 在API测试页面添加了搜索输入框 -- 可以测试带搜索参数的转栏记录API -- 支持测试 `search` 参数功能 - -**测试页面功能:** -- 基础API测试(无搜索参数) -- 搜索功能测试(带搜索参数) -- 实时显示API响应数据 -- 错误处理和显示 - -## 转栏记录API参数 - -根据您提供的接口,转栏记录API支持以下参数: - -### 查询参数 -- `page`: 页码(默认1) -- `pageSize`: 每页数量(默认10) -- `search`: 搜索关键词(可选) - -### 示例请求 -``` -GET http://localhost:5300/api/cattle-transfer-records?page=1&pageSize=10&search= -``` - -### 搜索功能 -- 支持按耳号搜索转栏记录 -- 支持按其他字段搜索(具体取决于后端实现) -- 搜索参数为空时返回所有记录 - -## 测试方法 - -### 1. 通过API测试页面 -1. 访问首页,点击"API测试"按钮 -2. 在转栏记录API测试区域: - - 点击"测试转栏记录API"测试基础功能 - - 输入搜索关键词,点击"测试搜索功能"测试搜索 -3. 查看返回的JSON数据格式 - -### 2. 通过转栏功能 -1. 访问转栏记录页面 -2. 在搜索框中输入耳号进行搜索 -3. 观察API请求和响应 - -### 3. 通过浏览器开发者工具 -1. 打开开发者工具的Network标签页 -2. 访问转栏功能 -3. 查看API请求的URL和参数 -4. 检查响应数据格式 - -## 数据格式预期 - -根据API接口,转栏记录数据应该包含以下字段: - -```json -{ - "success": true, - "data": { - "list": [ - { - "id": 1, - "recordId": "TR20250101001", - "animalId": 123, - "earNumber": "123456", - "fromPenId": 1, - "toPenId": 2, - "transferDate": "2025-01-01T10:00:00Z", - "reason": "正常调栏", - "operator": "张三", - "status": "已完成", - "remark": "备注信息", - "farmId": 1, - "created_at": "2025-01-01T10:00:00Z", - "updated_at": "2025-01-01T10:00:00Z", - "fromPen": { - "id": 1, - "name": "转出栏舍", - "code": "PEN001" - }, - "toPen": { - "id": 2, - "name": "转入栏舍", - "code": "PEN002" - } - } - ], - "total": 100, - "page": 1, - "pageSize": 10 - }, - "message": "获取转栏记录列表成功" -} -``` - -## 注意事项 - -1. **端口一致性** - 确保后端API服务运行在5300端口 -2. **认证要求** - 所有API都需要有效的认证token -3. **搜索功能** - 搜索参数为空时应该返回所有记录 -4. **分页功能** - 支持分页查询,默认每页10条记录 -5. **错误处理** - API调用失败时有相应的错误处理 - -## 环境变量配置 - -如果需要通过环境变量配置API地址,可以在项目根目录创建 `.env` 文件: - -```env -VUE_APP_BASE_URL=http://localhost:5300/api -``` - -这样可以在不同环境中使用不同的API地址,而不需要修改代码。 - -现在所有API接口都使用正确的端口5300,转栏记录功能可以正常调用后端API获取数据! diff --git a/mini_program/farm-monitor-dashboard/API_SETUP.md b/mini_program/farm-monitor-dashboard/API_SETUP.md deleted file mode 100644 index 99133d1..0000000 --- a/mini_program/farm-monitor-dashboard/API_SETUP.md +++ /dev/null @@ -1,65 +0,0 @@ -# API 设置说明 - -## 问题描述 -后端API返回401未授权错误,需要正确的认证信息才能获取371台主机的数据。 - -## 当前状态 -- ✅ API服务正在运行 (http://localhost:5350) -- ✅ API端点存在 (/api/smart-devices/hosts) -- ❌ 需要认证才能访问 -- ❌ 前端显示10台主机而不是371台 - -## 解决方案 - -### 方案1: 获取正确的认证token -1. 联系后端开发者获取测试用的认证token -2. 在浏览器控制台执行以下代码设置token: -```javascript -localStorage.setItem('token', 'YOUR_ACTUAL_TOKEN_HERE') -``` - -### 方案2: 检查API是否需要特殊参数 -可能API需要特定的请求参数,如: -- 用户ID -- 项目ID -- 其他业务参数 - -### 方案3: 临时测试token -如果后端有测试模式,可以尝试: -```javascript -localStorage.setItem('token', 'test-token') -``` - -## 测试步骤 - -1. 运行认证测试: -```bash -node auth-test.js -``` - -2. 运行API测试: -```bash -node test-api.js -``` - -3. 在浏览器中测试前端: - - 打开开发者工具 - - 查看控制台日志 - - 检查网络请求 - -## 预期结果 -- API应该返回371台主机的数据 -- 前端应该正确显示总数371 -- 分页功能应该正常工作 - -## 当前代码状态 -- ✅ 已移除所有模拟数据 -- ✅ 只使用真实API接口 -- ✅ 正确处理API响应结构 -- ✅ 支持分页和搜索 -- ❌ 需要解决认证问题 - -## 下一步 -1. 获取正确的认证信息 -2. 测试API连接 -3. 验证前端显示371台主机 diff --git a/mini_program/farm-monitor-dashboard/API_TEST_GUIDE.md b/mini_program/farm-monitor-dashboard/API_TEST_GUIDE.md deleted file mode 100644 index 7f42a7a..0000000 --- a/mini_program/farm-monitor-dashboard/API_TEST_GUIDE.md +++ /dev/null @@ -1,123 +0,0 @@ -# API测试指南 - -## 问题解决状态 - -✅ **401认证错误已修复** -- 修复了代理配置,从 `http://localhost:3000` 改为 `http://localhost:5350` -- 实现了真实的JWT token认证 -- 移除了模拟数据回退,使用真实API数据 - -## 测试步骤 - -### 1. 访问认证测试页面 -``` -http://localhost:8080/auth-test -``` - -### 2. 测试API连接 -1. 点击"设置测试Token"按钮 -2. 系统会自动使用 `admin/123456` 登录获取真实JWT token -3. 点击"测试所有API"按钮 -4. 查看测试结果 - -### 3. 预期结果 -- ✅ 耳标API测试成功,获取到真实数据 -- ✅ 项圈API测试成功,获取到真实数据 -- ✅ 脚环API测试成功,获取到真实数据 -- ✅ 主机API测试成功,获取到真实数据 - -## 技术实现 - -### 认证流程 -1. 前端调用 `/api/auth/login` 获取JWT token -2. 将token存储在 `localStorage` 中 -3. 所有API请求自动添加 `Authorization: Bearer ` 头 -4. 后端验证JWT token并返回数据 - -### API端点 -- **登录**: `POST /api/auth/login` -- **耳标设备**: `GET /api/smart-devices/eartags` -- **项圈设备**: `GET /api/smart-devices/collars` -- **脚环设备**: `GET /api/smart-devices/anklets` -- **主机设备**: `GET /api/smart-devices/hosts` - -### 默认账号 -- **用户名**: `admin` -- **密码**: `123456` - -## 故障排除 - -### 如果仍然出现401错误 -1. 检查后端服务是否运行在 `http://localhost:5350` -2. 检查前端代理配置是否正确 -3. 清除浏览器缓存和localStorage -4. 重新设置测试token - -### 如果API返回空数据 -1. 检查数据库是否有测试数据 -2. 检查用户权限是否正确设置 -3. 查看后端日志了解详细错误信息 - -## 开发说明 - -### 环境变量 -```javascript -VUE_APP_API_BASE_URL=http://localhost:5350 -``` - -### 代理配置 -```javascript -// vue.config.js -devServer: { - proxy: { - '/api': { - target: 'http://localhost:5350', - changeOrigin: true - } - } -} -``` - -### 认证头格式 -```javascript -headers: { - 'Authorization': `Bearer ${token}` -} -``` - -## 下一步 - -1. 实现用户登录页面集成真实API -2. 添加错误处理和用户提示 -3. 实现token自动刷新机制 -4. 添加权限控制 -5. 优化API响应处理 - -## 测试命令 - -### 手动测试API -```powershell -# 登录获取token -$response = Invoke-WebRequest -Uri "http://localhost:5350/api/auth/login" -Method POST -Body '{"username":"admin","password":"123456"}' -ContentType "application/json" -$token = ($response.Content | ConvertFrom-Json).token - -# 测试耳标API -Invoke-WebRequest -Uri "http://localhost:5350/api/smart-devices/eartags" -Headers @{"Authorization"="Bearer $token"} -Method GET -``` - -### 检查服务状态 -```powershell -# 检查后端服务 -netstat -an | findstr :5350 - -# 检查前端服务 -netstat -an | findstr :8080 -``` - -## 成功指标 - -- [x] 401错误已解决 -- [x] 真实API数据正常返回 -- [x] JWT认证正常工作 -- [x] 前端代理配置正确 -- [x] 所有设备API可正常调用 diff --git a/mini_program/farm-monitor-dashboard/AUTH_FIX_README.md b/mini_program/farm-monitor-dashboard/AUTH_FIX_README.md deleted file mode 100644 index b7133b2..0000000 --- a/mini_program/farm-monitor-dashboard/AUTH_FIX_README.md +++ /dev/null @@ -1,88 +0,0 @@ -# 401认证错误修复说明 - -## 问题描述 -在访问智能设备页面时出现 `401 (Unauthorized)` 错误,这是因为API请求需要有效的认证token。 - -## 解决方案 - -### 1. 自动修复(推荐) -应用已经自动处理了这个问题: -- 开发环境会自动设置测试token -- API请求失败时会自动使用模拟数据 -- 所有设备页面都能正常显示和操作 - -### 2. 手动设置Token -如果需要使用真实API,可以: - -#### 方法一:通过认证测试页面 -1. 访问首页,在开发工具部分点击"🔧 认证测试" -2. 在认证测试页面点击"设置测试Token" -3. 测试各个API接口 - -#### 方法二:通过浏览器控制台 -```javascript -// 设置测试token -localStorage.setItem('token', 'your-actual-token-here') - -// 设置用户信息 -localStorage.setItem('userInfo', JSON.stringify({ - id: 'user-001', - name: 'AIOTAGRO', - phone: '15586823774', - role: 'admin' -})) - -// 刷新页面 -location.reload() -``` - -### 3. 当前状态 -✅ **已修复的问题:** -- 401认证错误不再阻止页面加载 -- 所有API服务都有模拟数据降级 -- 开发环境自动设置测试token -- 添加了认证测试工具页面 - -✅ **功能正常:** -- 智能耳标页面 (`/ear-tag`) -- 智能项圈页面 (`/smart-collar`) -- 智能脚环页面 (`/smart-ankle`) -- 智能主机页面 (`/smart-host`) -- 所有设备操作(绑定、解绑、状态管理) - -### 4. 测试方法 -1. 访问 http://localhost:8080/ -2. 点击任意智能设备进入对应页面 -3. 页面应该正常加载并显示模拟数据 -4. 可以正常进行搜索、筛选、绑定等操作 - -### 5. 生产环境配置 -在生产环境中,需要: -1. 确保后端API正常运行 -2. 实现真实的用户认证流程 -3. 获取有效的JWT token -4. 将token存储到localStorage中 - -## 技术实现 - -### API服务改进 -- 添加了401错误拦截器 -- 自动降级到模拟数据 -- 统一的错误处理机制 - -### 认证工具 -- `src/utils/auth.js` - 认证管理工具 -- `src/components/AuthTest.vue` - 认证测试页面 - -### 模拟数据 -每个API服务都包含完整的模拟数据: -- 智能耳标:4个设备示例 -- 智能项圈:4个设备示例 -- 智能脚环:4个设备示例 -- 智能主机:4个设备示例 - -## 注意事项 -- 模拟数据仅用于开发和测试 -- 生产环境需要连接真实API -- 所有设备操作在模拟模式下都是本地状态更新 -- 刷新页面后状态会重置为初始值 diff --git a/mini_program/farm-monitor-dashboard/AUTH_SOLUTION.md b/mini_program/farm-monitor-dashboard/AUTH_SOLUTION.md deleted file mode 100644 index a339c50..0000000 --- a/mini_program/farm-monitor-dashboard/AUTH_SOLUTION.md +++ /dev/null @@ -1,161 +0,0 @@ -# 智能耳标认证问题解决方案 - -## 🎯 问题总结 - -**问题**: 智能耳标API返回401未授权错误,无法获取数据 -**原因**: 需要JWT认证token才能访问API -**解决**: 自动获取并设置认证token - -## ✅ 解决方案 - -### 方案1: 自动获取Token (推荐) - -```bash -# 运行自动登录脚本 -node auto-login.js -``` - -### 方案2: 手动设置Token - -```bash -# 运行token设置工具 -node set-token.js -``` - -### 方案3: 浏览器控制台设置 - -1. 打开浏览器开发者工具 (F12) -2. 在控制台中执行: -```javascript -localStorage.setItem('token', 'YOUR_TOKEN_HERE') -``` -3. 刷新页面 - -## 🔍 测试结果 - -### 智能主机API -- ✅ **主机总数**: 371台 -- ✅ **API状态**: 正常 -- ✅ **认证**: 成功 - -### 智能耳标API -- ✅ **耳标总数**: 1486台 -- ✅ **API状态**: 正常 -- ✅ **认证**: 成功 - -## 📊 API测试命令 - -```bash -# 测试所有API -node test-api.js - -# 测试认证方法 -node auth-test.js - -# 自动登录获取token -node auto-login.js -``` - -## 🔧 技术细节 - -### 认证流程 -1. 调用 `/api/auth/login` 接口 -2. 使用用户名: `admin`, 密码: `123456` -3. 获取JWT token -4. 在请求头中添加 `Authorization: Bearer TOKEN` - -### API端点 -- **登录**: `POST /api/auth/login` -- **智能主机**: `GET /api/smart-devices/hosts` -- **智能耳标**: `GET /api/iot-jbq-client` - -### Token格式 -```javascript -// JWT Token示例 -eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5jb20iLCJpYXQiOjE3NTgyNDkwMTMsImV4cCI6MTc1ODMzNTQxM30.Ic8WGgwN3PtshHtsM6VYoqGeb5TNWdEIl15wfMSutKA -``` - -## 🚀 前端集成 - -### 1. 自动登录功能 -```javascript -// 在应用启动时自动登录 -async function autoLogin() { - try { - const response = await axios.post('/api/auth/login', { - username: 'admin', - password: '123456' - }) - - if (response.data.success) { - localStorage.setItem('token', response.data.token) - return response.data.token - } - } catch (error) { - console.error('自动登录失败:', error) - } -} -``` - -### 2. 请求拦截器 -```javascript -// 自动添加认证头 -api.interceptors.request.use(config => { - const token = localStorage.getItem('token') - if (token) { - config.headers.Authorization = `Bearer ${token}` - } - return config -}) -``` - -### 3. 响应拦截器 -```javascript -// 处理认证错误 -api.interceptors.response.use( - response => response, - error => { - if (error.response?.status === 401) { - // 清除过期token - localStorage.removeItem('token') - // 重新登录 - autoLogin() - } - return Promise.reject(error) - } -) -``` - -## 📝 验证步骤 - -1. **运行自动登录**: - ```bash - node auto-login.js - ``` - -2. **检查输出**: - - ✅ 登录成功 - - ✅ 智能主机API: 371台 - - ✅ 智能耳标API: 1486台 - -3. **设置前端token**: - ```javascript - localStorage.setItem('token', 'YOUR_TOKEN') - ``` - -4. **刷新页面测试** - -## 🎉 结果 - -- ✅ **认证问题已解决** -- ✅ **智能主机API正常**: 371台主机 -- ✅ **智能耳标API正常**: 1486台耳标 -- ✅ **前端可以正常获取数据** -- ✅ **分页功能正常工作** - -## 🔄 维护说明 - -- Token有效期为24小时 -- 过期后需要重新获取 -- 建议实现自动token刷新机制 -- 生产环境应使用更安全的认证方式 diff --git a/mini_program/farm-monitor-dashboard/AUTH_SUCCESS_REPORT.md b/mini_program/farm-monitor-dashboard/AUTH_SUCCESS_REPORT.md deleted file mode 100644 index e4e3245..0000000 --- a/mini_program/farm-monitor-dashboard/AUTH_SUCCESS_REPORT.md +++ /dev/null @@ -1,177 +0,0 @@ -# 智能耳标认证问题解决成功报告 - -## 🎉 问题解决状态 - -**✅ 认证问题已完全解决!** - -## 📊 测试结果 - -### 智能主机API -- ✅ **状态**: 正常 -- ✅ **主机总数**: 371台 -- ✅ **分页功能**: 正常 -- ✅ **搜索功能**: 正常 -- ✅ **认证**: 成功 - -### 智能耳标API -- ✅ **状态**: 正常 -- ✅ **耳标总数**: 1486台 -- ✅ **分页功能**: 正常 -- ✅ **认证**: 成功 - -## 🔧 解决方案 - -### 1. 自动认证系统 -- 实现了自动登录获取JWT token -- 自动在API请求中添加认证头 -- 支持token过期自动刷新 - -### 2. 创建的工具 -- `auto-login.js` - 自动登录脚本 -- `set-token.js` - Token设置工具 -- `test-api.js` - API测试脚本 -- `auth-test.js` - 认证方法测试 - -### 3. 认证流程 -``` -1. 调用 /api/auth/login -2. 用户名: admin, 密码: 123456 -3. 获取JWT token -4. 在请求头添加 Authorization: Bearer TOKEN -5. 成功访问所有API -``` - -## 📈 性能数据 - -### API响应时间 -- 登录API: ~200ms -- 智能主机API: ~150ms -- 智能耳标API: ~180ms - -### 数据量 -- 智能主机: 371台设备 -- 智能耳标: 1486台设备 -- 分页支持: 每页10条记录 - -## 🚀 前端集成 - -### 1. 自动登录功能 -```javascript -// 应用启动时自动获取token -const token = await autoLogin() -localStorage.setItem('token', token) -``` - -### 2. 请求拦截器 -```javascript -// 自动添加认证头 -api.interceptors.request.use(config => { - const token = localStorage.getItem('token') - if (token) { - config.headers.Authorization = `Bearer ${token}` - } - return config -}) -``` - -### 3. 错误处理 -```javascript -// 处理401认证错误 -api.interceptors.response.use( - response => response, - error => { - if (error.response?.status === 401) { - // 重新登录 - autoLogin() - } - return Promise.reject(error) - } -) -``` - -## 📋 使用指南 - -### 快速开始 -```bash -# 1. 自动获取token -node auto-login.js - -# 2. 测试API连接 -node test-api.js - -# 3. 在浏览器中设置token -localStorage.setItem('token', 'YOUR_TOKEN') -``` - -### 前端设置 -1. 打开浏览器开发者工具 (F12) -2. 在控制台执行: - ```javascript - localStorage.setItem('token', 'YOUR_TOKEN') - ``` -3. 刷新页面 - -## 🔍 验证步骤 - -### 1. 运行测试 -```bash -node test-api.js -``` - -### 2. 检查输出 -- ✅ 认证token获取成功 -- ✅ API连接成功 -- ✅ 主机总数: 371 -- ✅ 分页功能正常 -- ✅ 搜索功能正常 - -### 3. 前端验证 -- 打开智能主机页面 -- 检查是否显示371台主机 -- 测试分页功能 -- 测试搜索功能 - -## 📝 技术细节 - -### JWT Token -- **算法**: HS256 -- **有效期**: 24小时 -- **包含信息**: 用户ID、用户名、邮箱 - -### API端点 -- **登录**: `POST /api/auth/login` -- **智能主机**: `GET /api/smart-devices/hosts` -- **智能耳标**: `GET /api/iot-jbq-client` - -### 认证头格式 -``` -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... -``` - -## 🎯 最终结果 - -- ✅ **认证问题完全解决** -- ✅ **所有API正常工作** -- ✅ **前端可以获取真实数据** -- ✅ **分页功能正常** -- ✅ **搜索功能正常** -- ✅ **智能主机显示371台** -- ✅ **智能耳标显示1486台** - -## 🔄 维护建议 - -1. **Token管理**: 实现自动刷新机制 -2. **错误处理**: 完善401错误处理 -3. **安全性**: 生产环境使用更安全的认证 -4. **监控**: 添加API调用监控 - -## 📞 支持 - -如有问题,请参考: -- `AUTH_SOLUTION.md` - 详细解决方案 -- `API_SETUP.md` - API设置说明 -- `IMPLEMENTATION_SUMMARY.md` - 实现总结 - ---- - -**🎉 认证问题解决完成!现在前端可以正常访问所有API并显示真实数据。** diff --git a/mini_program/farm-monitor-dashboard/CATTLE_PROFILE_README.md b/mini_program/farm-monitor-dashboard/CATTLE_PROFILE_README.md deleted file mode 100644 index 7818670..0000000 --- a/mini_program/farm-monitor-dashboard/CATTLE_PROFILE_README.md +++ /dev/null @@ -1,195 +0,0 @@ -# 牛只档案功能说明 - -## 功能概述 - -根据提供的UI设计图片,实现了完整的牛只档案管理系统,包括: - -1. **牛只档案列表页面** (`/cattle-profile`) -2. **新增牛只档案页面** (`/cattle-add`) -3. **API接口集成** (调用 `http://localhost:5350/api/cattle-type` 等接口) - -## 页面功能 - -### 牛只档案列表页面 (`CattleProfile.vue`) - -**UI特性:** -- 移动端友好的设计,完全按照图片UI实现 -- 顶部状态栏:返回按钮、标题、操作图标 -- 搜索栏:支持按耳号精确查询 -- 牛只卡片列表:显示牛只详细信息 -- 分页功能:支持分页浏览 -- 新增档案按钮:固定在底部的绿色按钮 - -**数据字段映射:** -- 耳号:`earNumber` (绿色高亮显示) -- 佩戴设备:`deviceNumber` -- 出生日期:`birthday` (格式化显示) -- 品类:`cate` (中文映射:犊牛、育成母牛等) -- 品种:`varieties` (从API获取品种名称) -- 生理阶段:`level` (中文映射) -- 性别:`sex` (公/母) -- 栏舍:`penName` (从API获取栏舍名称) - -**功能特性:** -- 实时搜索:输入耳号后自动搜索 -- 分页展示:支持翻页浏览 -- 点击查看详情:点击卡片可查看详细信息 -- 响应式设计:适配移动端屏幕 - -### 新增牛只档案页面 (`CattleAdd.vue`) - -**表单字段:** -- 基本信息:耳号、性别、品类、品种、品系 -- 出生信息:出生体重、出生日期 -- 管理信息:栏舍、批次、入栏时间、当前体重 - -**功能特性:** -- 表单验证:必填字段验证 -- 下拉选择:品种、栏舍、批次从API动态加载 -- 数据格式化:日期转换为时间戳 -- 保存功能:调用API创建牛只档案 - -## API接口集成 - -### 已实现的API接口 - -```javascript -// 获取牛只档案列表 -cattleApi.getCattleList(params) - -// 根据耳号搜索牛只 -cattleApi.searchCattleByEarNumber(earNumber) - -// 获取牛只详情 -cattleApi.getCattleDetail(id) - -// 获取牛只类型列表 -cattleApi.getCattleTypes() - -// 获取栏舍列表 -cattleApi.getPens(farmId) - -// 获取批次列表 -cattleApi.getBatches(farmId) - -// 创建牛只档案 -cattleApi.createCattle(data) - -// 更新牛只档案 -cattleApi.updateCattle(id, data) - -// 删除牛只档案 -cattleApi.deleteCattle(id) -``` - -### 后端API接口 - -- **获取牛只列表**: `GET /api/iot-cattle/public` -- **获取牛只类型**: `GET /api/cattle-type` -- **创建牛只档案**: `POST /api/iot-cattle` -- **获取栏舍列表**: `GET /api/iot-cattle/pens` -- **获取批次列表**: `GET /api/iot-cattle/batches` - -## 数据映射 - -### 字段中文映射 - -```javascript -// 性别映射 -const sexMap = { - 1: '公', - 2: '母' -} - -// 品类映射 -const categoryMap = { - 1: '犊牛', - 2: '育成母牛', - 3: '架子牛', - 4: '青年牛', - 5: '基础母牛', - 6: '育肥牛' -} - -// 生理阶段映射 -const stageMap = { - 1: '犊牛', - 2: '育成期', - 3: '青年期', - 4: '成年期', - 5: '老年期' -} -``` - -## 使用方法 - -### 1. 访问牛只档案页面 - -```javascript -// 从首页点击"档案拍照"按钮 -this.$router.push('/cattle-profile') - -// 或直接访问URL -http://localhost:8080/cattle-profile -``` - -### 2. 搜索牛只 - -在搜索框中输入耳号,系统会自动搜索并显示匹配的牛只信息。 - -### 3. 新增牛只档案 - -点击底部的"新增档案"按钮,填写表单信息后保存。 - -### 4. 测试功能 - -访问测试页面验证功能: -```javascript -this.$router.push('/cattle-test') -``` - -## 技术实现 - -### 前端技术栈 -- Vue.js 2.x -- Vue Router -- Axios (HTTP请求) -- CSS3 (移动端样式) - -### 关键特性 -- 响应式设计 -- 移动端优化 -- 实时搜索 -- 分页加载 -- 表单验证 -- 错误处理 - -### 文件结构 -``` -src/ -├── components/ -│ ├── CattleProfile.vue # 牛只档案列表页面 -│ ├── CattleAdd.vue # 新增牛只档案页面 -│ └── CattleTest.vue # 功能测试页面 -├── services/ -│ └── api.js # API接口封装 -└── router/ - └── index.js # 路由配置 -``` - -## 注意事项 - -1. **API地址**: 确保后端服务运行在 `http://localhost:5350` -2. **认证**: 部分接口可能需要认证token -3. **数据格式**: 日期需要转换为时间戳格式 -4. **错误处理**: 所有API调用都包含错误处理 -5. **移动端**: 页面针对移动端进行了优化 - -## 后续扩展 - -1. 牛只详情页面 -2. 编辑牛只档案功能 -3. 批量操作功能 -4. 数据导入导出 -5. 图片上传功能 -6. 更多筛选条件 diff --git a/mini_program/farm-monitor-dashboard/CATTLE_TRANSFER_ENHANCED.md b/mini_program/farm-monitor-dashboard/CATTLE_TRANSFER_ENHANCED.md deleted file mode 100644 index 92804f3..0000000 --- a/mini_program/farm-monitor-dashboard/CATTLE_TRANSFER_ENHANCED.md +++ /dev/null @@ -1,147 +0,0 @@ -# 牛只转栏记录功能完善说明 - -## 功能概述 - -根据提供的API接口文档,完善了牛只转栏记录功能,实现了所有API接口的动态调用,完全移除了模拟数据。 - -## 实现的API接口 - -### 1. 基础CRUD操作 -- **GET /api/cattle-transfer-records** - 获取转栏记录列表 -- **POST /api/cattle-transfer-records** - 创建转栏记录 -- **GET /api/cattle-transfer-records/{id}** - 获取转栏记录详情 -- **PUT /api/cattle-transfer-records/{id}** - 更新转栏记录 -- **DELETE /api/cattle-transfer-records/{id}** - 删除转栏记录 - -### 2. 批量操作 -- **POST /api/cattle-transfer-records/batch-delete** - 批量删除转栏记录 - -### 3. 辅助功能 -- **GET /api/cattle-transfer-records/available-animals** - 获取可用的牛只列表 - -## 新增功能特性 - -### 1. 批量操作功能 -- **全选/取消全选** - 支持一键选择所有记录 -- **批量删除** - 可以同时删除多条记录 -- **选择状态显示** - 实时显示已选择的记录数量 -- **视觉反馈** - 选中的记录有特殊的视觉标识 - -### 2. 编辑功能 -- **编辑模式** - 支持编辑现有转栏记录 -- **数据回填** - 编辑时自动填充现有数据 -- **动态标题** - 根据模式显示"转栏登记"或"编辑转栏记录" -- **动态按钮** - 根据模式显示"提交"或"更新" - -### 3. 删除功能 -- **单条删除** - 支持删除单条记录 -- **确认对话框** - 删除前显示确认提示 -- **批量删除** - 支持批量删除多条记录 -- **操作反馈** - 删除成功后显示提示信息 - -### 4. 数据选择优化 -- **耳号选择** - 从可用牛只列表中选择,而不是手动输入 -- **栏舍选择** - 从后端获取栏舍列表进行选择 -- **数据验证** - 确保选择的牛只和栏舍有效 - -## 界面改进 - -### 1. 列表视图 -- **卡片式布局** - 每条记录以卡片形式展示 -- **选择框** - 每条记录都有选择框 -- **操作按钮** - 每条记录都有编辑和删除按钮 -- **状态指示** - 选中的记录有特殊样式 - -### 2. 批量操作栏 -- **全选控制** - 顶部有全选复选框 -- **选择计数** - 显示已选择的记录数量 -- **批量删除按钮** - 支持批量删除操作 - -### 3. 表单优化 -- **耳号下拉选择** - 从可用牛只列表中选择 -- **动态标题** - 根据编辑/新建模式显示不同标题 -- **动态按钮** - 根据模式显示不同的按钮文本 - -## 技术实现 - -### 1. API服务层 -```javascript -export const cattleTransferApi = { - getTransferRecords: (params) => get('/cattle-transfer-records', params), - createTransferRecord: (data) => post('/cattle-transfer-records', data), - getTransferRecordDetail: (id) => get(`/cattle-transfer-records/${id}`), - updateTransferRecord: (id, data) => put(`/cattle-transfer-records/${id}`, data), - deleteTransferRecord: (id) => del(`/cattle-transfer-records/${id}`), - batchDeleteTransferRecords: (ids) => post('/cattle-transfer-records/batch-delete', { ids }), - getAvailableAnimals: (params) => get('/cattle-transfer-records/available-animals', params), - getBarnsForTransfer: (farmId) => get('/barns', { farmId }) -} -``` - -### 2. 状态管理 -- **selectedRecords** - 存储选中的记录ID数组 -- **selectAll** - 全选状态 -- **isEdit** - 编辑模式标识 -- **editId** - 编辑的记录ID - -### 3. 方法实现 -- **toggleSelectAll()** - 全选/取消全选逻辑 -- **batchDelete()** - 批量删除逻辑 -- **editRecord()** - 编辑记录逻辑 -- **deleteRecord()** - 删除记录逻辑 -- **loadRecordForEdit()** - 加载编辑数据逻辑 - -## 用户体验优化 - -### 1. 操作反馈 -- **成功提示** - 操作成功后显示成功消息 -- **错误处理** - 操作失败时显示错误信息 -- **加载状态** - 操作过程中显示加载状态 - -### 2. 确认机制 -- **删除确认** - 删除前显示确认对话框 -- **批量删除确认** - 批量删除前显示确认对话框 - -### 3. 数据验证 -- **表单验证** - 提交前验证必填字段 -- **业务验证** - 验证转出和转入栏舍不能相同 - -## 使用方式 - -### 1. 查看转栏记录 -- 从首页"业务办理"模块点击"牛只转栏" -- 从生产管理页面"牛只管理"模块点击"转栏记录" - -### 2. 新增转栏记录 -- 在转栏记录页面点击"转栏登记"按钮 -- 填写完整的转栏信息 -- 选择牛只耳号和栏舍信息 - -### 3. 编辑转栏记录 -- 在记录列表中点击"编辑"按钮 -- 系统自动跳转到编辑页面并填充数据 -- 修改后点击"更新"按钮 - -### 4. 删除转栏记录 -- **单条删除** - 点击记录上的"删除"按钮 -- **批量删除** - 选择多条记录后点击"批量删除"按钮 - -### 5. 批量操作 -- 使用顶部的"全选"复选框选择所有记录 -- 或单独选择需要的记录 -- 点击"批量删除"按钮进行批量删除 - -## 注意事项 - -1. **API依赖** - 确保后端API正常运行 -2. **认证要求** - 所有API都需要有效的认证token -3. **数据格式** - 确保API返回的数据格式正确 -4. **错误处理** - 网络错误和业务错误都有相应的处理 - -## 后续优化建议 - -1. **搜索功能** - 添加更多搜索和筛选条件 -2. **导出功能** - 支持数据导出 -3. **统计功能** - 添加转栏记录统计 -4. **权限控制** - 根据用户权限控制操作按钮 -5. **数据缓存** - 优化数据加载性能 diff --git a/mini_program/farm-monitor-dashboard/CATTLE_TRANSFER_FEATURE.md b/mini_program/farm-monitor-dashboard/CATTLE_TRANSFER_FEATURE.md deleted file mode 100644 index 2774be9..0000000 --- a/mini_program/farm-monitor-dashboard/CATTLE_TRANSFER_FEATURE.md +++ /dev/null @@ -1,137 +0,0 @@ -# 牛只转栏记录功能实现说明 - -## 功能概述 - -根据提供的UI设计图片,实现了完整的牛只转栏记录功能,包括记录查看、搜索、分页和新增登记功能。 - -## 实现的功能 - -### 1. 牛只转栏记录查看页面 (`CattleTransfer.vue`) - -**UI特性:** -- 完全按照图片设计实现,包括顶部状态栏、搜索栏、记录卡片、分页控制和底部操作按钮 -- 响应式设计,适配移动端显示 -- 现代化的卡片式布局,符合移动应用设计规范 - -**功能特性:** -- 动态调用 `http://localhost:5350/api/cattle-transfer-records` 接口获取数据 -- 支持按耳号搜索转栏记录 -- 分页显示记录列表 -- 显示详细的转栏信息,包括: - - 耳号(绿色高亮显示) - - 转舍日期 - - 转入栋舍 - - 转出栋舍 - - 登记人 - - 登记日期 - - 转栏原因 - - 状态 - - 备注 - -**字段映射:** -- `earNumber` → 耳号 -- `transferDate` → 转舍日期 -- `toPen.name` → 转入栋舍 -- `fromPen.name` → 转出栋舍 -- `operator` → 登记人 -- `created_at` → 登记日期 -- `reason` → 转栏原因 -- `status` → 状态 -- `remark` → 备注 - -### 2. 转栏登记页面 (`CattleTransferRegister.vue`) - -**功能特性:** -- 完整的表单验证 -- 支持选择转出/转入栏舍 -- 转栏原因下拉选择(正常调栏、疾病治疗、配种需要、产房准备、隔离观察、其他) -- 状态选择(已完成、进行中) -- 操作人员输入 -- 备注信息输入 -- 自动设置当前日期时间为默认转栏时间 - -### 3. API服务集成 (`api.js`) - -**新增API接口:** -```javascript -export const cattleTransferApi = { - getTransferRecords: (params) => get('/cattle-transfer-records', params), - searchTransferRecordsByEarNumber: (earNumber, params) => get('/cattle-transfer-records', { earNumber, ...params }), - getTransferRecordDetail: (id) => get(`/cattle-transfer-records/${id}`), - createTransferRecord: (data) => post('/cattle-transfer-records', data), - updateTransferRecord: (id, data) => put(`/cattle-transfer-records/${id}`, data), - deleteTransferRecord: (id) => del(`/cattle-transfer-records/${id}`), - getBarnsForTransfer: (farmId) => get('/barns', { farmId }) -} -``` - -### 4. 路由配置 - -**新增路由:** -- `/cattle-transfer` - 转栏记录查看页面 -- `/cattle-transfer-register` - 转栏登记页面 - -### 5. 首页集成 - -在首页的"业务办理"模块中添加了"牛只转栏"入口,点击可跳转到转栏记录页面。 - -## 技术实现细节 - -### 数据流处理 -1. 组件挂载时自动加载转栏记录 -2. 支持搜索防抖处理(500ms延迟) -3. 分页数据动态加载 -4. 错误处理和用户提示 - -### 响应式设计 -- 移动端优先设计 -- 适配不同屏幕尺寸 -- 触摸友好的交互元素 - -### 用户体验优化 -- 加载状态提示 -- 空状态展示 -- 表单验证反馈 -- 操作成功/失败提示 - -## 文件结构 - -``` -src/ -├── components/ -│ ├── CattleTransfer.vue # 转栏记录查看页面 -│ └── CattleTransferRegister.vue # 转栏登记页面 -├── services/ -│ └── api.js # API服务(已更新) -├── router/ -│ └── index.js # 路由配置(已更新) -└── components/ - └── Home.vue # 首页(已更新) -``` - -## 使用说明 - -1. **查看转栏记录:** - - 在首页点击"牛只转栏"进入记录列表 - - 可通过耳号搜索特定记录 - - 支持分页浏览 - -2. **新增转栏记录:** - - 在转栏记录页面点击"转栏登记"按钮 - - 填写完整的转栏信息 - - 提交后自动跳转回记录列表 - -## 注意事项 - -1. 确保后端API `http://localhost:5350/api/cattle-transfer-records` 正常运行 -2. 需要有效的认证token才能访问API -3. 栏舍数据需要从 `/barns` 接口获取 -4. 建议在生产环境中添加更多的错误处理和用户反馈 - -## 后续优化建议 - -1. 添加编辑功能的具体实现 -2. 增加批量操作功能 -3. 添加数据导出功能 -4. 优化搜索和筛选功能 -5. 添加数据统计和图表展示 diff --git a/mini_program/farm-monitor-dashboard/CHINESE_MAPPING_GUIDE.md b/mini_program/farm-monitor-dashboard/CHINESE_MAPPING_GUIDE.md deleted file mode 100644 index 545e19f..0000000 --- a/mini_program/farm-monitor-dashboard/CHINESE_MAPPING_GUIDE.md +++ /dev/null @@ -1,195 +0,0 @@ -# 中文映射指南 - -## 概述 - -本系统使用统一的中文映射工具来将数据库中的数字代码转换为用户友好的中文显示。所有映射规则都集中在 `src/utils/mapping.js` 文件中。 - -## 映射字段 - -### 1. 性别映射 (sexMap) -```javascript -{ - 1: '公', - 2: '母' -} -``` - -### 2. 品类映射 (categoryMap) -```javascript -{ - 1: '犊牛', - 2: '育成母牛', - 3: '架子牛', - 4: '青年牛', - 5: '基础母牛', - 6: '育肥牛' -} -``` - -### 3. 品种映射 (breedMap) -```javascript -{ - 1: '西藏高山牦牛', - 2: '宁夏牛', - 3: '华西牛', - 4: '秦川牛', - 5: '西门塔尔牛', - 6: '荷斯坦牛' -} -``` - -### 4. 品系映射 (strainMap) -```javascript -{ - 1: '乳肉兼用', - 2: '肉用型', - 3: '乳用型', - 4: '兼用型' -} -``` - -### 5. 生理阶段映射 (physiologicalStageMap) -```javascript -{ - 1: '犊牛', - 2: '育成期', - 3: '青年期', - 4: '成年期', - 5: '老年期' -} -``` - -### 6. 来源映射 (sourceMap) -```javascript -{ - 1: '合作社', - 2: '农户', - 3: '养殖场', - 4: '进口', - 5: '自繁' -} -``` - -### 7. 事件映射 (eventMap) -```javascript -{ - 1: '正常', - 2: '生病', - 3: '怀孕', - 4: '分娩', - 5: '断奶', - 6: '转栏', - 7: '离栏' -} -``` - -### 8. 销售状态映射 (sellStatusMap) -```javascript -{ - 100: '在栏', - 200: '已售', - 300: '死亡', - 400: '淘汰' -} -``` - -## 使用方法 - -### 在Vue组件中使用 - -```javascript -import { - getSexName, - getCategoryName, - getBreedName, - formatDate -} from '@/utils/mapping' - -// 在方法中使用 -const sexName = getSexName(cattle.sex) // 返回 '公' 或 '母' -const categoryName = getCategoryName(cattle.cate) // 返回 '犊牛' 等 -const breedName = getBreedName(cattle.varieties) // 返回 '华西牛' 等 -const formattedDate = formatDate(cattle.birthday) // 返回 '2024-08-07' -``` - -### 在模板中使用 - -```vue - -``` - -## 数据格式化 - -### 日期格式化 -```javascript -// 时间戳转日期字符串 -const dateString = formatDate(1723017600) // 返回 '2024-08-07' - -// 日期字符串转时间戳 -const timestamp = formatDateToTimestamp('2024-08-07') // 返回 1723017600 -``` - -## 扩展映射 - -如果需要添加新的映射字段,请按以下步骤操作: - -1. 在 `src/utils/mapping.js` 中添加新的映射对象 -2. 添加对应的获取函数 -3. 在默认导出中包含新的映射 -4. 在需要使用的组件中导入并使用 - -### 示例:添加新的映射字段 - -```javascript -// 在 mapping.js 中添加 -export const newFieldMap = { - 1: '选项1', - 2: '选项2', - 3: '选项3' -} - -export function getNewFieldName(code) { - return newFieldMap[code] || '--' -} - -// 在默认导出中添加 -export default { - // ... 其他映射 - newFieldMap, - getNewFieldName -} -``` - -## 注意事项 - -1. **一致性**: 所有映射都应该使用相同的格式和命名规范 -2. **默认值**: 当映射不到对应值时,统一返回 '--' -3. **类型安全**: 确保传入的参数类型正确 -4. **维护性**: 映射规则应该集中管理,便于维护和更新 - -## 当前使用位置 - -- `CattleProfile.vue`: 牛只档案列表页面 -- `CattleAdd.vue`: 新增牛只档案页面 -- 其他需要显示中文的组件 - -## 测试 - -可以通过以下方式测试映射功能: - -1. 在浏览器控制台中测试映射函数 -2. 使用测试页面验证显示效果 -3. 检查API返回的数据是否正确映射 - -```javascript -// 在浏览器控制台中测试 -import { getSexName, getCategoryName } from '@/utils/mapping' -console.log(getSexName(1)) // 应该输出 '公' -console.log(getCategoryName(1)) // 应该输出 '犊牛' -``` diff --git a/mini_program/farm-monitor-dashboard/COLLAR_API_INTEGRATION.md b/mini_program/farm-monitor-dashboard/COLLAR_API_INTEGRATION.md deleted file mode 100644 index 0353ae0..0000000 --- a/mini_program/farm-monitor-dashboard/COLLAR_API_INTEGRATION.md +++ /dev/null @@ -1,127 +0,0 @@ -# 智能项圈模块 API 集成完成报告 - -## 概述 -智能项圈模块已成功从模拟数据迁移到真实API调用,模仿智能耳标模块的实现方式,提供了完整的数据管理功能。 - -## 主要更新 - -### 1. collarService.js 服务层更新 -- **移除模拟数据逻辑**:完全移除了 `getMockCollarDevices()` 函数 -- **添加真实API调用**:实现 `getAllCollarDevices()` 函数调用 `/api/smart-devices/collars` 接口 -- **数据字段映射**:确保API返回的数据正确映射到前端显示字段 -- **分页支持**:支持 `page` 和 `limit` 参数 -- **搜索支持**:支持 `search` 参数进行设备搜索 -- **状态筛选**:支持 `status` 参数进行设备状态筛选 -- **统计功能**:添加 `getCollarStatistics()` 函数获取设备统计信息 -- **CRUD操作**:添加设备更新、删除等操作函数 - -#### 字段映射关系 -```javascript -// API返回字段 -> 前端显示字段 -sn/deviceId -> collarId (项圈编号) -voltage -> battery (设备电量) -temperature -> temperature (设备温度) -sid -> collectedHost (被采集主机) -walk -> totalMovement (总运动量) -walk - y_steps -> todayMovement (今日运动量) -gps -> gpsLocation (GPS位置) -time/uptime -> updateTime (数据更新时间) -bandge_status/state -> isBound (绑定状态,优先使用bandge_status) -``` - -#### 绑定状态判断逻辑 -```javascript -// 绑定状态判断优先级 -isBound = device.bandge_status === 1 || device.bandge_status === '1' || - device.state === 1 || device.state === '1' - -// 状态字段说明 -// bandge_status: 绑带状态字段 (优先使用) -// - 1: 已绑定 -// - 0: 未绑定 -// state: 设备状态字段 (备用) -// - 1: 已绑定 -// - 0: 未绑定 -``` - -### 2. SmartCollar.vue 组件更新 -- **分页功能**:添加完整的分页控件,支持页码跳转和每页数量选择 -- **搜索功能**:实现实时搜索,支持精确匹配和模糊搜索 -- **统计显示**:显示设备总数、已绑定数量、未绑定数量 -- **设备操作**:添加编辑、删除、绑定/解绑等操作 -- **错误处理**:完善的错误处理和用户提示 -- **加载状态**:添加加载动画和状态管理 -- **刷新功能**:添加数据刷新按钮 - -#### 新增功能特性 -1. **实时搜索**:输入框支持实时搜索,500ms防抖 -2. **分页导航**:支持页码跳转、上一页/下一页、每页数量选择 -3. **设备管理**:支持编辑设备信息、删除设备 -4. **状态管理**:实时显示设备绑定状态 -5. **数据刷新**:支持手动刷新数据 -6. **响应式设计**:适配移动端显示 - -### 3. API接口调用 -- **GET /api/smart-devices/collars**:获取项圈设备列表(支持分页、搜索、筛选) -- **POST /api/smart-devices/collars/bind**:绑定项圈设备 -- **POST /api/smart-devices/collars/unbind**:解绑项圈设备 -- **PUT /api/smart-devices/collars/:id**:更新项圈设备 -- **DELETE /api/smart-devices/collars/:id**:删除项圈设备 - -## 技术实现细节 - -### 数据流程 -1. 组件挂载时同时加载设备列表和统计信息 -2. 用户操作(搜索、分页、筛选)触发API调用 -3. API返回数据经过字段映射后显示在界面上 -4. 错误情况显示友好的错误提示 - -### 状态管理 -- `devices`:当前页面的设备列表 -- `pagination`:分页信息(当前页、每页数量、总页数等) -- `isSearching`:搜索状态标识 -- `searchResults`:搜索结果列表 -- `totalCount/boundCount/unboundCount`:统计信息 - -### 错误处理 -- 网络错误:显示"加载设备失败,请检查网络连接或重新登录" -- 认证错误:自动清除本地token并跳转到登录页 -- API错误:在控制台记录详细错误信息 - -## 测试验证 - -### 测试脚本 -创建了 `test-collar-api.js` 测试脚本,可以验证: -- API接口连通性 -- 数据字段映射正确性 -- 搜索功能有效性 - -### 运行测试 -```bash -cd mini_program/farm-monitor-dashboard -node test-collar-api.js -``` - -## 使用说明 - -### 基本操作 -1. **查看设备**:页面加载时自动显示设备列表 -2. **搜索设备**:在搜索框输入设备编号进行搜索 -3. **分页浏览**:使用分页控件浏览更多设备 -4. **设备操作**:点击编辑/删除按钮管理设备 -5. **绑定管理**:点击绑定按钮切换设备绑定状态 -6. **刷新数据**:点击刷新按钮更新最新数据 - -### 界面特性 -- **橙色主题**:与智能项圈模块的橙色主题保持一致 -- **响应式布局**:适配不同屏幕尺寸 -- **直观操作**:清晰的操作按钮和状态指示 -- **实时反馈**:操作结果实时显示 - -## 兼容性说明 -- 保持与原有API接口的完全兼容 -- 支持向后兼容的字段映射 -- 错误情况下优雅降级 - -## 总结 -智能项圈模块已成功完成从模拟数据到真实API的迁移,提供了与智能耳标模块一致的功能体验,包括分页、搜索、统计、CRUD操作等完整功能。模块现在可以动态查询和调用后端API,不再依赖模拟数据。 diff --git a/mini_program/farm-monitor-dashboard/COLLAR_PAGINATION_SEARCH_FEATURES.md b/mini_program/farm-monitor-dashboard/COLLAR_PAGINATION_SEARCH_FEATURES.md deleted file mode 100644 index e1ce9ab..0000000 --- a/mini_program/farm-monitor-dashboard/COLLAR_PAGINATION_SEARCH_FEATURES.md +++ /dev/null @@ -1,184 +0,0 @@ -# 智能项圈分页和搜索功能完善报告 - -## 功能概述 -智能项圈模块已完成分页展示和搜索功能的全面优化,支持所有数据的正确分页显示和根据项圈编号的精确查询。 - -## 主要功能特性 - -### 1. 分页展示功能 ✅ - -#### 1.1 完整分页支持 -- **数据分页加载**:所有数据通过API分页加载,支持大数据量展示 -- **分页控件**:提供上一页、下一页、页码跳转等完整分页控件 -- **每页数量选择**:支持5、10、20、50条每页显示数量选择 -- **分页信息显示**:实时显示当前页范围和总数据量 - -#### 1.2 分页状态管理 -```javascript -// 分页数据结构 -pagination: { - current: 1, // 当前页码 - pageSize: 10, // 每页数量 - total: 0, // 总数据量 - totalPages: 0 // 总页数 -} -``` - -#### 1.3 分页操作 -- **页码跳转**:点击页码直接跳转到指定页面 -- **上一页/下一页**:支持键盘和鼠标操作 -- **每页数量调整**:动态调整每页显示数量并重置到第一页 -- **分页信息实时更新**:显示"第 X-Y 条,共 Z 条"格式信息 - -### 2. 搜索功能 ✅ - -#### 2.1 精确搜索实现 -- **API全局搜索**:调用后端API进行全局数据搜索,不限于当前页面 -- **项圈编号精确查询**:支持根据项圈编号进行精确匹配搜索 -- **实时搜索**:输入框支持实时搜索,500ms防抖优化 -- **搜索状态管理**:独立的搜索状态和分页管理 - -#### 2.2 搜索功能特性 -```javascript -// 搜索参数 -{ - page: 1, // 搜索分页 - pageSize: 10, // 搜索每页数量 - search: "22012000108" // 搜索关键词 -} -``` - -#### 2.3 搜索用户体验 -- **搜索状态显示**:显示"搜索 '关键词' 的结果" -- **搜索结果分页**:搜索结果支持独立分页 -- **空状态提示**:未找到结果时显示友好提示 -- **清除搜索**:一键清除搜索条件并返回正常列表 - -### 3. 界面优化 ✅ - -#### 3.1 搜索界面优化 -- **搜索状态栏**:动态显示搜索进度和结果 -- **搜索提示**:提供搜索建议和操作提示 -- **空状态处理**:区分正常空状态和搜索无结果状态 - -#### 3.2 分页界面优化 -- **分页控件**:美观的分页按钮和页码显示 -- **分页信息**:清晰的分页状态信息 -- **响应式设计**:适配不同屏幕尺寸 - -#### 3.3 用户体验提升 -- **加载状态**:搜索和分页加载时显示加载动画 -- **错误处理**:网络错误时显示友好错误提示 -- **操作反馈**:操作结果实时反馈 - -## 技术实现细节 - -### 1. 分页实现 -```javascript -// 分页数据加载 -async loadDevices() { - const params = { - page: this.pagination.current, - pageSize: this.pagination.pageSize, - search: this.searchQuery || undefined - } - - const response = await getAllCollarDevices(params) - // 更新分页信息和设备列表 -} -``` - -### 2. 搜索实现 -```javascript -// 全局搜索 -async performSearch() { - const params = { - page: 1, - pageSize: 10, - search: this.searchQuery.trim() - } - - const response = await getAllCollarDevices(params) - // 更新搜索结果和搜索分页信息 -} -``` - -### 3. 状态管理 -```javascript -// 搜索状态管理 -isSearching: false, // 是否在搜索模式 -searchResults: [], // 搜索结果 -searchPagination: { // 搜索分页信息 - current: 1, - pageSize: 10, - total: 0, - totalPages: 0 -} -``` - -## 测试验证 - -### 1. 测试脚本 -创建了 `test-collar-pagination-search.js` 测试脚本,包含: -- **分页功能测试**:测试多页数据加载和分页控件 -- **搜索功能测试**:测试精确搜索和模糊搜索 -- **搜索分页测试**:测试搜索结果的分页功能 - -### 2. 运行测试 -```bash -cd mini_program/farm-monitor-dashboard -node test-collar-pagination-search.js -``` - -### 3. 测试覆盖 -- ✅ 分页数据加载 -- ✅ 分页控件操作 -- ✅ 每页数量调整 -- ✅ 精确搜索功能 -- ✅ 模糊搜索功能 -- ✅ 搜索分页功能 -- ✅ 空状态处理 -- ✅ 错误状态处理 - -## 使用说明 - -### 1. 分页操作 -1. **浏览数据**:使用分页控件浏览不同页面的数据 -2. **调整每页数量**:使用下拉菜单选择每页显示数量 -3. **跳转页面**:点击页码数字直接跳转到指定页面 -4. **上一页/下一页**:使用箭头按钮翻页 - -### 2. 搜索操作 -1. **输入搜索关键词**:在搜索框中输入项圈编号 -2. **实时搜索**:输入时自动触发搜索(500ms延迟) -3. **查看搜索结果**:搜索结果支持分页浏览 -4. **清除搜索**:点击"清除搜索"按钮返回正常列表 - -### 3. 界面说明 -- **搜索状态栏**:显示当前搜索状态和结果数量 -- **分页信息**:显示当前页范围和总数据量 -- **分页控件**:提供完整的分页操作功能 -- **空状态提示**:未找到数据时显示相应提示 - -## 性能优化 - -### 1. 搜索优化 -- **防抖处理**:输入搜索时500ms防抖,避免频繁API调用 -- **API全局搜索**:直接调用后端API搜索,不依赖前端数据 -- **分页搜索**:搜索结果支持分页,避免一次性加载大量数据 - -### 2. 分页优化 -- **按需加载**:只加载当前页面的数据 -- **状态保持**:搜索和分页状态独立管理 -- **缓存优化**:合理的数据缓存和状态管理 - -## 总结 - -智能项圈模块的分页和搜索功能已全面完善: - -1. **分页功能**:支持所有数据的正确分页展示,提供完整的分页控件和操作 -2. **搜索功能**:实现根据项圈编号的精确查询,支持全局搜索和搜索分页 -3. **用户体验**:优化界面交互,提供友好的操作反馈和状态提示 -4. **性能优化**:合理的API调用和状态管理,确保良好的性能表现 - -所有功能已通过测试验证,可以正常使用。 diff --git a/mini_program/farm-monitor-dashboard/CONVERSION_GUIDE.md b/mini_program/farm-monitor-dashboard/CONVERSION_GUIDE.md deleted file mode 100644 index 3650da6..0000000 --- a/mini_program/farm-monitor-dashboard/CONVERSION_GUIDE.md +++ /dev/null @@ -1,371 +0,0 @@ -# 项目转换指南 - -## 转换概述 - -本项目已从uni-app技术栈转换为微信小程序原生技术栈。以下是详细的转换说明和注意事项。 - -## 技术栈对比 - -| 项目 | uni-app | 微信小程序原生 | -|------|---------|----------------| -| 框架 | Vue.js + uni-app | 微信小程序原生 | -| 模板 | Vue单文件组件 | WXML | -| 样式 | SCSS/CSS | WXSS | -| 逻辑 | Vue.js | JavaScript ES6+ | -| 路由 | Vue Router | 微信小程序路由 | -| 状态管理 | Pinia | 微信小程序全局数据 | -| 网络请求 | axios | wx.request | -| 组件库 | uView UI | 微信小程序原生组件 | - -## 主要转换内容 - -### 1. 项目结构转换 - -#### 原uni-app结构 -``` -src/ -├── App.vue -├── main.js -├── pages/ -├── components/ -├── services/ -└── utils/ -``` - -#### 转换后微信小程序结构 -``` -├── app.js -├── app.json -├── app.wxss -├── pages/ -├── services/ -└── utils/ -``` - -### 2. 页面转换 - -#### Vue单文件组件 → 微信小程序页面 -- `.vue` → `.js` + `.wxml` + `.wxss` -- `template` → `.wxml` -- `script` → `.js` -- `style` → `.wxss` - -#### 示例对比 - -**Vue组件 (原)** -```vue - - - - - -``` - -**微信小程序页面 (转换后)** -```javascript -// .js -Page({ - data: { - message: 'Hello World' - } -}) -``` - -```xml - - - {{message}} - -``` - -```css -/* .wxss */ -.container { - padding: 20rpx; -} -``` - -### 3. 路由转换 - -#### uni-app路由 -```javascript -// 页面跳转 -uni.navigateTo({ url: '/pages/detail/detail' }) - -// 路由配置 -export default new VueRouter({ - routes: [ - { path: '/detail', component: Detail } - ] -}) -``` - -#### 微信小程序路由 -```javascript -// 页面跳转 -wx.navigateTo({ url: '/pages/detail/detail' }) - -// 路由配置 (app.json) -{ - "pages": [ - "pages/detail/detail" - ] -} -``` - -### 4. 状态管理转换 - -#### uni-app (Pinia) -```javascript -// store/user.js -export const useUserStore = defineStore('user', { - state: () => ({ - userInfo: null - }), - actions: { - setUserInfo(info) { - this.userInfo = info - } - } -}) - -// 组件中使用 -const userStore = useUserStore() -userStore.setUserInfo(userInfo) -``` - -#### 微信小程序全局数据 -```javascript -// app.js -App({ - globalData: { - userInfo: null - }, - setUserInfo(info) { - this.globalData.userInfo = info - } -}) - -// 页面中使用 -const app = getApp() -app.setUserInfo(userInfo) -``` - -### 5. 网络请求转换 - -#### uni-app (axios) -```javascript -import axios from 'axios' - -const api = axios.create({ - baseURL: '/api', - timeout: 10000 -}) - -api.get('/users').then(res => { - console.log(res.data) -}) -``` - -#### 微信小程序 (wx.request) -```javascript -wx.request({ - url: 'https://api.example.com/users', - method: 'GET', - success: (res) => { - console.log(res.data) - } -}) -``` - -### 6. 组件转换 - -#### Vue组件 -```vue - - - -``` - -#### 微信小程序组件 -```javascript -// components/custom-component.js -Component({ - properties: { - title: String - }, - methods: { - handleClick() { - this.triggerEvent('click') - } - } -}) -``` - -```xml - - - - -``` - -## 依赖处理 - -### 移除的依赖 -- `@dcloudio/uni-app` -- `@dcloudio/uni-cli-shared` -- `@dcloudio/uni-h5` -- `@dcloudio/uni-mp-weixin` -- `@vue/composition-api` -- `vue` -- `vue-router` -- `vue-template-compiler` -- `pinia` -- `axios` -- `@vant/weapp` - -### 保留的依赖 -- `dayjs` - 日期处理库 - -### 新增的依赖 -- 无(使用微信小程序原生API) - -## 配置文件转换 - -### 1. package.json -- 移除uni-app相关依赖 -- 更新项目描述和脚本 -- 保留必要的开发依赖 - -### 2. manifest.json → app.json -- 页面配置迁移到app.json -- 移除uni-app特有配置 -- 保留微信小程序配置 - -### 3. pages.json → app.json -- 页面路由配置 -- tabBar配置 -- 全局样式配置 - -## 样式转换 - -### 1. SCSS变量 → WXSS变量 -```scss -// 原SCSS -$primary-color: #3cc51f; -$font-size: 14px; - -.container { - color: $primary-color; - font-size: $font-size; -} -``` - -```css -/* 转换后WXSS */ -.container { - color: #3cc51f; - font-size: 28rpx; /* 注意单位转换 */ -} -``` - -### 2. 响应式设计 -- 使用rpx单位替代px -- 适配不同屏幕尺寸 -- 保持设计一致性 - -## 功能适配 - -### 1. 生命周期 -- Vue生命周期 → 微信小程序生命周期 -- `created` → `onLoad` -- `mounted` → `onReady` -- `destroyed` → `onUnload` - -### 2. 事件处理 -- Vue事件 → 微信小程序事件 -- `@click` → `bindtap` -- `@input` → `bindinput` - -### 3. 数据绑定 -- Vue数据绑定 → 微信小程序数据绑定 -- `v-model` → `value` + `bindinput` -- `v-for` → `wx:for` - -## 注意事项 - -### 1. 兼容性 -- 微信小程序API限制 -- 网络请求域名配置 -- 图片资源大小限制 - -### 2. 性能优化 -- 避免频繁setData -- 合理使用分包 -- 图片懒加载 - -### 3. 开发调试 -- 使用微信开发者工具 -- 真机调试测试 -- 控制台日志查看 - -## 迁移检查清单 - -- [ ] 页面结构转换完成 -- [ ] 样式适配完成 -- [ ] 逻辑代码转换完成 -- [ ] 路由配置正确 -- [ ] 网络请求正常 -- [ ] 组件功能正常 -- [ ] 状态管理正确 -- [ ] 生命周期适配 -- [ ] 事件处理正确 -- [ ] 数据绑定正常 -- [ ] 依赖清理完成 -- [ ] 配置文件更新 -- [ ] 功能测试通过 -- [ ] 性能优化完成 - -## 后续维护 - -1. 定期更新微信小程序基础库版本 -2. 关注微信小程序API更新 -3. 优化性能和用户体验 -4. 及时修复bug和问题 -5. 保持代码质量和规范 - -## 技术支持 - -如有转换相关问题,请参考: -- 微信小程序官方文档 -- 项目README文档 -- 代码注释和说明 diff --git a/mini_program/farm-monitor-dashboard/DEBUG_API_ISSUE.md b/mini_program/farm-monitor-dashboard/DEBUG_API_ISSUE.md deleted file mode 100644 index 9b33587..0000000 --- a/mini_program/farm-monitor-dashboard/DEBUG_API_ISSUE.md +++ /dev/null @@ -1,87 +0,0 @@ -# API连接问题调试指南 - -## 问题描述 -在访问牛只档案页面时出现错误:`Cannot read properties of undefined (reading 'error')` - -## 可能的原因 - -1. **后端服务未启动** - - 后端服务需要在 `http://localhost:5350` 运行 - - 检查后端服务是否正常启动 - -2. **API路径错误** - - 已修复API路径配置 - - 牛只列表:`/api/iot-cattle/public` - - 栏舍列表:`/api/iot-cattle/public/pens/list` - - 批次列表:`/api/iot-cattle/public/batches/list` - -3. **CORS跨域问题** - - 后端需要配置CORS允许前端访问 - -4. **网络连接问题** - - 检查前端是否能访问后端服务 - -## 调试步骤 - -### 1. 检查后端服务 -```bash -# 在后端目录运行 -cd backend -npm start -# 或 -node server.js -``` - -### 2. 测试API连接 -访问测试页面:`http://localhost:8080/api-test` - -### 3. 检查浏览器控制台 -打开浏览器开发者工具,查看Network标签页和Console标签页的错误信息 - -### 4. 手动测试API -在浏览器中直接访问: -- `http://localhost:5350/api/cattle-type` -- `http://localhost:5350/api/iot-cattle/public` - -## 已修复的问题 - -1. **错误处理优化** - - 修复了 `error` 属性未定义的问题 - - 添加了更详细的错误信息输出 - -2. **API路径修正** - - 修正了栏舍和批次API的路径 - - 确保路径与后端路由配置一致 - -3. **调试信息添加** - - 在CattleProfile组件中添加了详细的调试日志 - - 可以查看请求参数和响应数据 - -## 临时解决方案 - -如果API连接有问题,可以: - -1. **使用模拟数据** - - 在CattleProfile组件中临时使用模拟数据 - - 注释掉API调用,使用静态数据 - -2. **检查环境变量** - - 确保 `VUE_APP_BASE_URL` 正确设置 - - 默认值:`http://localhost:5350/api` - -## 下一步 - -1. 启动后端服务 -2. 访问测试页面验证API连接 -3. 如果仍有问题,检查后端日志 -4. 确认数据库连接正常 - -## 测试页面功能 - -访问 `/api-test` 页面可以测试: -- 基础连接测试 -- 牛只档案API测试 -- 牛只类型API测试 -- 栏舍API测试 -- 批次API测试 -- 直接HTTP请求测试 diff --git a/mini_program/farm-monitor-dashboard/DEPRECATION_WARNING_FIX.md b/mini_program/farm-monitor-dashboard/DEPRECATION_WARNING_FIX.md deleted file mode 100644 index f68c709..0000000 --- a/mini_program/farm-monitor-dashboard/DEPRECATION_WARNING_FIX.md +++ /dev/null @@ -1,95 +0,0 @@ -# SharedArrayBuffer 弃用警告解决方案 - -## ⚠️ 警告信息 -``` -[Deprecation] SharedArrayBuffer will require cross-origin isolation as of M92, around July 2021. -See https://developer.chrome.com/blog/enabling-shared-array-buffer/ for more details. -``` - -## 🔍 问题分析 - -这个警告是由微信开发者工具内部使用 SharedArrayBuffer 导致的,不会影响您的智能耳标页面功能。警告出现的原因: - -1. **开发者工具版本**: 较旧版本的微信开发者工具 -2. **编译模式**: 使用了旧的编译模式 -3. **浏览器兼容性**: Chrome M92+ 版本的安全策略变更 - -## ✅ 解决方案 - -### 方案1: 更新开发者工具(推荐) -1. 下载最新版本的微信开发者工具 -2. 在工具设置中启用"使用新的编译模式" -3. 重启开发者工具 - -### 方案2: 项目配置优化 -已更新 `project.config.json` 配置: -- ✅ 启用 `newFeature: true` - 使用新特性 -- ✅ 启用 `disableSWC: false` - 使用新的编译器 -- ✅ 启用 `useCompilerModule: true` - 使用编译器模块 -- ✅ 启用 `useStaticServer: true` - 使用静态服务器 -- ✅ 保持其他优化设置 - -### 方案3: 忽略警告(临时方案) -如果警告不影响功能,可以暂时忽略: -- 警告不会影响智能耳标页面的API调用 -- 不会影响数据展示和交互功能 -- 只是开发者工具的兼容性提示 - -## 🎯 验证方法 - -### 检查智能耳标页面功能: -1. **API调用**: 确认 `/api/iot-jbq-client` 接口正常调用 -2. **数据显示**: 确认耳标数据正常显示 -3. **筛选功能**: 确认总数、已绑定、未绑定筛选正常 -4. **搜索功能**: 确认搜索功能正常 -5. **交互功能**: 确认点击、添加等功能正常 - -### 测试步骤: -```javascript -// 在开发者工具控制台测试 -console.log('智能耳标页面功能测试:') -console.log('✅ API接口调用正常') -console.log('✅ 数据显示正常') -console.log('✅ 筛选功能正常') -console.log('✅ 搜索功能正常') -console.log('✅ 交互功能正常') -``` - -## 📱 功能确认 - -智能耳标页面的所有功能都正常工作: - -### ✅ 已实现功能 -- **API集成**: `/api/iot-jbq-client` 接口调用 -- **数据映射**: 字段自动映射和格式化 -- **UI设计**: 严格按照图片设计实现 -- **筛选功能**: 总数、已绑定、未绑定 -- **搜索功能**: 按编号和主机号搜索 -- **添加功能**: 新增耳标功能 -- **响应式设计**: 适配不同屏幕 - -### ✅ 数据处理 -- **绑定状态**: 智能判断绑定状态 -- **电量显示**: 格式化电量百分比 -- **温度显示**: 格式化温度值 -- **时间显示**: 中文时间格式 -- **运动量**: 数值格式化显示 - -## 🚀 后续优化 - -1. **定期更新**: 保持微信开发者工具为最新版本 -2. **监控警告**: 关注新的弃用警告 -3. **功能测试**: 定期测试页面功能 -4. **性能优化**: 持续优化页面性能 - -## 📞 技术支持 - -如果警告持续出现或影响功能: -1. 检查微信开发者工具版本 -2. 尝试重新编译项目 -3. 清除缓存后重新加载 -4. 联系微信开发者工具技术支持 - ---- - -**注意**: 这个警告不会影响您的智能耳标页面功能,所有API调用、数据显示、交互功能都正常工作。 diff --git a/mini_program/farm-monitor-dashboard/DOMAIN_CONFIG_GUIDE.md b/mini_program/farm-monitor-dashboard/DOMAIN_CONFIG_GUIDE.md deleted file mode 100644 index bf4789d..0000000 --- a/mini_program/farm-monitor-dashboard/DOMAIN_CONFIG_GUIDE.md +++ /dev/null @@ -1,98 +0,0 @@ -# 微信小程序域名配置指南 - -## 问题描述 -错误信息:`"request:fail url not in domain list"` - -这是因为微信小程序要求所有网络请求的域名必须在微信公众平台配置的域名白名单中。 - -## 解决方案 - -### 方案1:开发环境 - 开启调试模式(推荐) - -1. **在微信开发者工具中开启调试模式**: - - 打开微信开发者工具 - - 点击右上角的"详情"按钮 - - 在"本地设置"中勾选"不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书" - - 这样可以在开发阶段使用本地API - -2. **确保后端服务运行**: - ```bash - cd backend - npm start - # 后端将在 http://localhost:5350 运行 - ``` - -### 方案2:生产环境 - 配置域名白名单 - -1. **登录微信公众平台**: - - 访问 https://mp.weixin.qq.com - - 使用小程序账号登录 - -2. **配置服务器域名**: - - 进入"开发" -> "开发管理" -> "开发设置" - - 在"服务器域名"中添加: - - request合法域名:`https://your-backend-domain.com` - - socket合法域名:`wss://your-backend-domain.com` - - uploadFile合法域名:`https://your-backend-domain.com` - - downloadFile合法域名:`https://your-backend-domain.com` - -3. **更新API配置**: - ```javascript - // utils/api.js - const config = { - baseUrl: 'https://your-backend-domain.com/api', - // ... 其他配置 - } - ``` - -### 方案3:使用ngrok内网穿透(临时方案) - -1. **启动ngrok**: - ```bash - cd backend - ./ngrok.exe http 5350 - ``` - -2. **获取公网地址**: - - ngrok会提供一个公网地址,如:`https://abc123.ngrok.io` - -3. **更新API配置**: - ```javascript - // utils/api.js - const config = { - baseUrl: 'https://abc123.ngrok.io/api', - // ... 其他配置 - } - ``` - -4. **在微信公众平台添加域名**: - - 将ngrok提供的域名添加到服务器域名白名单 - -## 当前配置 - -当前API配置使用本地地址: -```javascript -baseUrl: 'http://localhost:5350/api' -``` - -## 测试步骤 - -1. **确保后端服务运行**: - ```bash - cd backend - npm start - ``` - -2. **开启微信开发者工具调试模式**: - - 勾选"不校验合法域名" - -3. **测试智能耳标页面**: - - 点击首页"智能设备" -> "智能耳标" - - 应该能正常加载数据 - -## 注意事项 - -- 开发环境建议使用方案1(开启调试模式) -- 生产环境必须使用方案2(配置域名白名单) -- ngrok方案仅适用于临时测试 -- 确保后端API接口 `/api/iot-jbq-client` 正常工作 diff --git a/mini_program/farm-monitor-dashboard/EARTAG_CRUD_FEATURES.md b/mini_program/farm-monitor-dashboard/EARTAG_CRUD_FEATURES.md deleted file mode 100644 index 05fc76c..0000000 --- a/mini_program/farm-monitor-dashboard/EARTAG_CRUD_FEATURES.md +++ /dev/null @@ -1,187 +0,0 @@ -# 智能耳标功能模块完善 - -## 功能概述 - -根据提供的API接口文档,完善了智能耳标设备管理功能,实现了完整的CRUD操作。 - -## API接口支持 - -### 1. 获取所有智能耳标设备 -- **接口**: `GET /api/iot-jbq-client` -- **功能**: 获取所有智能耳标设备列表 -- **方法**: `getAllEarTagDevices(params)` - -### 2. 根据CID获取设备 -- **接口**: `GET /api/iot-jbq-client/cid/{cid}` -- **功能**: 根据客户端ID获取相关设备 -- **方法**: `getEarTagDevicesByCid(cid)` - -### 3. 根据ID获取设备 -- **接口**: `GET /api/iot-jbq-client/{id}` -- **功能**: 根据设备ID获取单个设备详情 -- **方法**: `getEarTagDeviceById(id)` - -### 4. 更新设备 -- **接口**: `PUT /api/iot-jbq-client/{id}` -- **功能**: 更新智能耳标设备信息 -- **方法**: `updateEarTagDevice(id, data)` - -### 5. 删除设备 -- **接口**: `DELETE /api/iot-jbq-client/{id}` -- **功能**: 删除智能耳标设备 -- **方法**: `deleteEarTagDevice(id)` - -## 新增功能 - -### 1. 设备管理功能 -- ✅ **查看所有设备**: 显示完整的设备列表 -- ✅ **按CID过滤**: 根据客户端ID筛选设备 -- ✅ **设备详情**: 查看单个设备的详细信息 -- ✅ **编辑设备**: 修改设备属性信息 -- ✅ **删除设备**: 移除不需要的设备 - -### 2. 用户界面增强 -- ✅ **操作按钮**: 每个设备卡片添加编辑和删除按钮 -- ✅ **编辑对话框**: 模态对话框用于编辑设备信息 -- ✅ **删除确认**: 删除前的确认对话框 -- ✅ **CID过滤**: 可选的CID过滤功能 -- ✅ **响应式设计**: 适配不同屏幕尺寸 - -### 3. 数据字段支持 -- ✅ **耳标编号**: `eartagNumber` -- ✅ **设备电量**: `battery` -- ✅ **设备温度**: `temperature` -- ✅ **被采集主机**: `collectedHost` -- ✅ **总运动量**: `totalMovement` -- ✅ **今日运动量**: `dailyMovement` -- ✅ **位置信息**: `location` -- ✅ **更新时间**: `lastUpdate` - -## 使用方法 - -### 1. 访问设备管理 -``` -http://localhost:8080/ear-tag -``` - -### 2. 基本操作 -- **查看设备**: 页面加载时自动显示所有设备 -- **搜索设备**: 使用搜索框按设备ID或主机ID搜索 -- **编辑设备**: 点击设备卡片上的✏️按钮 -- **删除设备**: 点击设备卡片上的🗑️按钮 - -### 3. 高级功能 -- **CID过滤**: 点击"CID过滤"按钮,输入CID进行筛选 -- **设备详情**: 点击设备卡片查看详细信息 -- **批量操作**: 支持多设备同时操作 - -## 技术实现 - -### 1. 服务层 (earTagService.js) -```javascript -// 新增的API方法 -export const getAllEarTagDevices = async (params = {}) -export const getEarTagDevicesByCid = async (cid) -export const getEarTagDeviceById = async (id) -export const updateEarTagDevice = async (id, data) -export const deleteEarTagDevice = async (id) -``` - -### 2. 组件层 (EarTag.vue) -```javascript -// 新增的数据属性 -showEditDialog: false, -showDeleteDialog: false, -selectedDevice: null, -editDevice: {}, -cidFilter: '', -showCidFilter: false - -// 新增的方法 -loadDevicesByCid() -loadDeviceById() -showEditDevice() -updateDevice() -showDeleteDevice() -confirmDeleteDevice() -``` - -### 3. 用户界面 -```vue - -
- -
- - -
- -
-``` - -## 样式特性 - -### 1. 对话框样式 -- **模态覆盖**: 半透明黑色背景 -- **居中显示**: 响应式居中布局 -- **表单样式**: 统一的输入框和按钮样式 -- **动画效果**: 平滑的显示/隐藏动画 - -### 2. 操作按钮 -- **编辑按钮**: 蓝色主题,铅笔图标 -- **删除按钮**: 红色主题,垃圾桶图标 -- **悬停效果**: 鼠标悬停时的颜色变化 - -### 3. 响应式设计 -- **移动端适配**: 小屏幕设备优化 -- **触摸友好**: 适合触摸操作的按钮大小 -- **滚动支持**: 长列表的滚动处理 - -## 错误处理 - -### 1. API错误处理 -- **网络错误**: 显示友好的错误信息 -- **认证错误**: 自动重定向到登录页面 -- **数据错误**: 显示具体的错误原因 - -### 2. 用户操作错误 -- **表单验证**: 输入数据的格式验证 -- **操作确认**: 危险操作的二次确认 -- **状态反馈**: 操作成功/失败的即时反馈 - -## 测试方法 - -### 1. 功能测试 -1. 访问 `http://localhost:8080/ear-tag` -2. 测试设备列表加载 -3. 测试编辑功能 -4. 测试删除功能 -5. 测试CID过滤 - -### 2. API测试 -1. 访问 `http://localhost:8080/auth-test` -2. 点击"设置真实Token" -3. 点击"测试所有API" -4. 查看测试结果 - -## 注意事项 - -1. **API兼容性**: 确保后端API接口正常工作 -2. **认证状态**: 需要有效的JWT token -3. **数据格式**: 确保API返回的数据格式正确 -4. **错误处理**: 网络错误时的优雅降级 - -## 下一步计划 - -1. **添加设备功能**: 实现设备创建功能 -2. **批量操作**: 支持多设备批量编辑/删除 -3. **数据导出**: 支持设备数据导出 -4. **实时更新**: 设备状态的实时刷新 -5. **权限控制**: 基于角色的操作权限 - -## 相关文件 - -- `src/services/earTagService.js` - API服务层 -- `src/components/EarTag.vue` - 设备管理组件 -- `src/components/AuthTest.vue` - API测试组件 -- `backend/routes/smart-devices.js` - 后端API路由 diff --git a/mini_program/farm-monitor-dashboard/ELECTRONIC_FENCE_README.md b/mini_program/farm-monitor-dashboard/ELECTRONIC_FENCE_README.md deleted file mode 100644 index 0653e8d..0000000 --- a/mini_program/farm-monitor-dashboard/ELECTRONIC_FENCE_README.md +++ /dev/null @@ -1,231 +0,0 @@ -# 电子围栏功能实现说明 - -## 功能概述 - -基于管理系统的ElectronicFence.vue实现,为小程序完善了电子围栏功能,包括围栏绘制、管理、查看等核心功能。 - -## 文件结构 - -``` -src/ -├── services/ -│ └── fenceService.js # 电子围栏API服务 -├── components/ -│ ├── ElectronicFence.vue # 电子围栏主组件 -│ └── MapView.vue # 地图视图组件 -├── views/ -│ └── ElectronicFencePage.vue # 电子围栏页面 -└── router/ - └── index.js # 路由配置(已更新) -``` - -## 核心功能 - -### 1. 围栏绘制 -- **开始绘制**:点击"开始绘制"按钮进入绘制模式 -- **坐标点添加**:在地图上点击添加围栏坐标点 -- **实时反馈**:显示当前绘制状态和坐标点信息 -- **完成绘制**:至少3个点才能完成围栏绘制 -- **取消绘制**:随时可以取消当前绘制操作 - -### 2. 围栏管理 -- **围栏列表**:查看所有围栏,支持搜索和筛选 -- **围栏信息**:显示围栏名称、类型、坐标点数量、面积等 -- **围栏编辑**:修改围栏名称、类型、描述等信息 -- **围栏删除**:删除不需要的围栏 -- **围栏选择**:点击围栏在地图上定位显示 - -### 3. 围栏类型 -- **放牧区** 🌿:绿色标识,用于放牧区域 -- **安全区** 🛡️:蓝色标识,用于安全保护区域 -- **限制区** ⚠️:红色标识,用于限制进入区域 -- **收集区** 📦:橙色标识,用于收集作业区域 - -## API接口集成 - -### 围栏管理接口 -```javascript -// 获取围栏列表 -GET /api/electronic-fences - -// 获取单个围栏 -GET /api/electronic-fences/{id} - -// 创建围栏 -POST /api/electronic-fences - -// 更新围栏 -PUT /api/electronic-fences/{id} - -// 删除围栏 -DELETE /api/electronic-fences/{id} - -// 搜索围栏 -GET /api/electronic-fences/search -``` - -### 坐标点管理接口 -```javascript -// 获取围栏坐标点 -GET /api/electronic-fence-points/fence/{fenceId} - -// 创建坐标点 -POST /api/electronic-fence-points - -// 批量创建坐标点 -POST /api/electronic-fence-points/batch - -// 更新坐标点 -PUT /api/electronic-fence-points/{id} - -// 删除坐标点 -DELETE /api/electronic-fence-points/{id} - -// 获取围栏边界框 -GET /api/electronic-fence-points/fence/{fenceId}/bounds - -// 搜索坐标点 -GET /api/electronic-fence-points/search -``` - -## 组件说明 - -### ElectronicFence.vue -主组件,包含以下功能模块: -- 顶部导航栏 -- 地图容器 -- 绘制控制面板 -- 围栏列表面板 -- 围栏信息面板 -- 围栏编辑模态框 - -### MapView.vue -地图视图组件,提供: -- 地图显示和交互 -- 绘制模式切换 -- 围栏显示 -- 坐标点标记 -- 地图控制功能 - -### fenceService.js -API服务类,包含: -- 围栏CRUD操作 -- 坐标点管理 -- 围栏类型配置 -- 工具函数(面积计算、中心点计算等) - -## 使用方式 - -### 1. 访问电子围栏 -从首页点击"电子围栏"工具卡片,或直接访问 `/electronic-fence` 路由。 - -### 2. 地图功能测试 -访问 `/map-test` 路由可以测试百度地图集成功能: -- 地图加载和显示 -- 围栏绘制和显示 -- 坐标点标记 -- 地图交互控制 - -### 3. 绘制新围栏 -1. 点击"开始绘制"按钮 -2. 在地图上点击添加坐标点(至少3个) -3. 点击"完成绘制"按钮 -4. 填写围栏信息(名称、类型、描述) -5. 点击"确定"保存围栏 - -### 4. 管理围栏 -1. 点击右上角菜单按钮查看围栏列表 -2. 使用搜索框筛选围栏 -3. 点击围栏项查看详细信息 -4. 使用编辑/删除按钮管理围栏 - -## 技术特点 - -### 1. 响应式设计 -- 适配移动端屏幕 -- 触摸友好的交互设计 -- 优化的UI布局 - -### 2. 状态管理 -- 绘制状态实时更新 -- 围栏数据响应式绑定 -- 错误处理和用户反馈 - -### 3. 百度地图集成 -- 使用百度地图API v3.0 -- 支持地图缩放、拖拽、点击交互 -- 实时坐标点显示和绘制 -- 围栏边界可视化 -- 支持多种围栏类型颜色区分 - -### 4. 数据验证 -- 围栏数据完整性检查 -- 坐标点数量验证 -- 面积计算和验证 - -## 配置说明 - -### 地图配置 -```javascript -// 百度地图API密钥 -const BAIDU_MAP_AK = 'SOawZTeQbxdgrKYYx0o2hn34G0DyU2uo' - -// 地图中心点配置 -mapCenter: { lng: 106.27, lat: 38.47 }, // 宁夏中心坐标 -mapZoom: 8 // 适合宁夏全区域的缩放级别 - -// 百度地图API加载 -const script = document.createElement('script') -script.src = `https://api.map.baidu.com/api?v=3.0&ak=${BAIDU_MAP_AK}&callback=initBaiduMap` -``` - -### 围栏类型配置 -```javascript -fenceTypes: { - grazing: { name: '放牧区', color: '#52c41a', icon: '🌿' }, - safety: { name: '安全区', color: '#1890ff', icon: '🛡️' }, - restricted: { name: '限制区', color: '#ff4d4f', icon: '⚠️' }, - collector: { name: '收集区', color: '#fa8c16', icon: '📦' } -} -``` - -## 扩展功能 - -### 1. 地图SDK集成 -✅ **已完成百度地图API集成** -- 使用百度地图API v3.0 -- 支持围栏绘制和显示 -- 支持坐标点标记 -- 支持地图交互控制 - -其他可选地图服务: -- 高德地图API -- 腾讯地图API -- 其他地图服务 - -### 2. 高级功能 -- 围栏面积计算 -- 围栏重叠检测 -- 围栏历史记录 -- 围栏权限管理 - -### 3. 数据导出 -- 围栏数据导出 -- 坐标点数据导出 -- 围栏报告生成 - -## 注意事项 - -1. **地图SDK**:需要集成实际的地图SDK才能实现完整功能 -2. **坐标系统**:确保使用正确的坐标系统(WGS84) -3. **网络请求**:需要配置正确的API基础URL -4. **权限管理**:根据用户权限控制围栏操作 -5. **数据同步**:确保与后端数据同步 - -## 开发建议 - -1. 优先集成地图SDK实现基础绘制功能 -2. 完善错误处理和用户提示 -3. 添加数据缓存机制提升性能 -4. 实现离线模式支持 -5. 添加围栏导入/导出功能 diff --git a/mini_program/farm-monitor-dashboard/FIELD_MAPPING_GUIDE.md b/mini_program/farm-monitor-dashboard/FIELD_MAPPING_GUIDE.md deleted file mode 100644 index e302a04..0000000 --- a/mini_program/farm-monitor-dashboard/FIELD_MAPPING_GUIDE.md +++ /dev/null @@ -1,168 +0,0 @@ -# 智能耳标字段映射指南 - -## API响应字段映射 - -根据 `/api/iot-jbq-client` 接口的响应数据,以下是字段映射关系: - -### 主要字段映射 - -| 中文标签 | API字段 | 数据类型 | 说明 | 示例值 | -|---------|---------|----------|------|--------| -| 耳标编号 | `cid` | number | 设备唯一标识 | 2105517333 | -| 设备电量/% | `voltage` | string | 设备电压百分比 | "98" | -| 设备温度/°C | `temperature` | string | 设备温度 | "39" | -| 被采集主机 | `sid` | string | 采集主机ID | "" | -| 总运动量 | `walk` | number | 总步数 | 1000 | -| 今日运动量 | 计算字段 | number | walk - y_steps | 500 | -| 数据更新时间 | `time` | number | Unix时间戳 | 1646969844 | -| 绑定状态 | `state` | number | 1=已绑定, 0=未绑定 | 1 | - -### 计算字段 - -#### 今日运动量 -```javascript -今日运动量 = walk - y_steps -// 示例: 1000 - 500 = 500 -``` - -#### 数据更新时间格式化 -```javascript -// Unix时间戳转换为本地时间 -const date = new Date(timestamp * 1000) -const formattedTime = date.toLocaleString('zh-CN') -``` - -#### 绑定状态判断 -```javascript -// state字段为1表示已绑定,0或其他值表示未绑定 -const isBound = device.state === 1 || device.state === '1' -``` - -### 备用字段映射 - -为了保持向后兼容性,系统支持以下备用字段: - -| 主字段 | 备用字段 | 说明 | -|--------|----------|------| -| `cid` | `aaid`, `id` | 设备标识 | -| `voltage` | `battery` | 电量信息 | -| `walk` | `totalMovement` | 总运动量 | -| `sid` | `collectedHost` | 采集主机 | -| `time` | `uptime`, `updateTime` | 更新时间 | - -### 数据处理逻辑 - -#### 1. 数据标准化 -```javascript -const processedDevice = { - ...device, - // 确保关键字段存在 - cid: device.cid || device.aaid || device.id, - voltage: device.voltage || '0', - temperature: device.temperature || '0', - walk: device.walk || 0, - y_steps: device.y_steps || 0, - time: device.time || device.uptime || 0, - // 保持向后兼容 - earTagId: device.cid || device.earTagId, - battery: device.voltage || device.battery, - totalMovement: device.walk || device.totalMovement, - todayMovement: (device.walk || 0) - (device.y_steps || 0), - collectedHost: device.sid || device.collectedHost, - updateTime: device.time || device.updateTime -} -``` - -#### 2. 今日运动量计算 -```javascript -calculateTodayMovement(device) { - const walk = parseInt(device.walk) || 0 - const ySteps = parseInt(device.y_steps) || 0 - return Math.max(0, walk - ySteps) -} -``` - -#### 3. 时间格式化 -```javascript -formatUpdateTime(device) { - const timestamp = device.time || device.updateTime || device.uptime - if (!timestamp) return '未知' - - try { - const date = new Date(timestamp * 1000) - if (isNaN(date.getTime())) { - return new Date(timestamp).toLocaleString('zh-CN') - } - return date.toLocaleString('zh-CN') - } catch (error) { - return '时间格式错误' - } -} -``` - -### 搜索功能支持 - -搜索功能支持以下字段: -- `cid` (耳标编号) -- `earTagId` (备用耳标编号) -- `collectedHost` (被采集主机) -- `sid` (备用采集主机) - -### 分页参数 - -API支持以下分页参数: -- `page`: 页码,默认1 -- `pageSize`: 每页数量,默认10 -- `cid`: 设备CID过滤(可选) - -### 示例API调用 - -```javascript -// 获取第一页数据,每页10条 -GET /api/iot-jbq-client?page=1&pageSize=10 - -// 根据CID过滤 -GET /api/iot-jbq-client?cid=2105517333&page=1&pageSize=10 -``` - -### 响应格式 - -```json -{ - "success": true, - "data": [ - { - "id": 165019, - "org_id": 326, - "cid": 2105517333, - "aaid": 2105517333, - "uid": 326, - "time": 1646969844, - "uptime": 1646969844, - "sid": "", - "walk": 1000, - "y_steps": 500, - "r_walk": 0, - "lat": "38.902401", - "lon": "106.534732", - "gps_state": "V", - "voltage": "98", - "temperature": "39", - "temperature_two": "0", - "state": 1, - "type": 1, - "sort": 1, - "ver": "0", - "weight": 0, - "start_time": 0, - "run_days": 240 - } - ], - "pagination": { - "current": 1, - "pageSize": 10, - "total": 100 - }, - "message": "获取智能耳标设备列表成功" -} -``` diff --git a/mini_program/farm-monitor-dashboard/HOST_NUMBER_FIX_REPORT.md b/mini_program/farm-monitor-dashboard/HOST_NUMBER_FIX_REPORT.md deleted file mode 100644 index 436a518..0000000 --- a/mini_program/farm-monitor-dashboard/HOST_NUMBER_FIX_REPORT.md +++ /dev/null @@ -1,141 +0,0 @@ -# 主机编号显示问题修复报告 - -## 🎯 问题描述 - -**问题**: 智能主机页面中主机编号显示为空 -**现象**: 前端界面显示"主机编号:" 但后面没有数值 -**影响**: 用户无法识别具体的主机设备 - -## 🔍 问题分析 - -### API返回数据结构 -```json -{ - "success": true, - "data": [ - { - "id": 4925, - "deviceNumber": "2024010103", // ← 主机编号字段 - "battery": 100, - "signalValue": "强", - "temperature": 5, - "updateTime": "2024-01-10 09:39:20", - // ... 其他字段 - } - ] -} -``` - -### 前端代码问题 -```javascript -// 修复前 - 错误的字段映射 -
主机编号: {{ device.sid || device.hostId }}
- -// 修复后 - 正确的字段映射 -
主机编号: {{ device.deviceNumber || device.sid || device.hostId }}
-``` - -## ✅ 修复方案 - -### 1. 显示字段修复 -**文件**: `src/components/SmartHost.vue` (第66行) -```javascript -// 修复前 -device.sid || device.hostId - -// 修复后 -device.deviceNumber || device.sid || device.hostId -``` - -### 2. 搜索功能修复 -**文件**: `src/components/SmartHost.vue` (第264行) -```javascript -// 修复前 -const hostId = device.sid || device.hostId || '' - -// 修复后 -const hostId = device.deviceNumber || device.sid || device.hostId || '' -``` - -### 3. 编辑功能修复 -**文件**: `src/components/SmartHost.vue` (第381行) -```javascript -// 修复前 -hostId: device.sid || device.hostId - -// 修复后 -hostId: device.deviceNumber || device.sid || device.hostId -``` - -## 📊 修复验证 - -### 测试结果 -- ✅ **主机编号显示**: 正常显示 `deviceNumber` 值 -- ✅ **搜索功能**: 可以按主机编号搜索 -- ✅ **编辑功能**: 编辑对话框正确显示主机编号 -- ✅ **数据完整性**: 所有371台主机都有正确的主机编号 - -### 测试数据示例 -``` -设备 1: 2024010103 -设备 2: 2072516173 -设备 3: 22C0281357 -设备 4: 22C0281272 -设备 5: 2072515306 -``` - -## 🔧 技术细节 - -### 字段优先级 -```javascript -// 按优先级顺序尝试获取主机编号 -device.deviceNumber || device.sid || device.hostId -``` - -### API字段映射 -| 前端显示 | API字段 | 说明 | -|---------|---------|------| -| 主机编号 | deviceNumber | 主要字段 | -| 设备电量 | voltage | 电量百分比 | -| 设备信号 | signal | 信号强度 | -| 设备温度 | temperature | 温度值 | -| 绑带状态 | bandge_status | 连接状态 | -| 更新时间 | updateTime | 最后更新时间 | - -## 🎉 修复结果 - -### 修复前 -- ❌ 主机编号显示为空 -- ❌ 搜索功能无法按主机编号搜索 -- ❌ 编辑功能无法正确显示主机编号 - -### 修复后 -- ✅ 主机编号正确显示 (如: 2024010103) -- ✅ 搜索功能正常工作 -- ✅ 编辑功能正确显示主机编号 -- ✅ 所有371台主机都有正确的主机编号 - -## 📋 相关文件 - -- `src/components/SmartHost.vue` - 主要修复文件 -- `test-host-number-fix.js` - 修复验证脚本 -- `HOST_NUMBER_FIX_REPORT.md` - 本修复报告 - -## 🚀 使用说明 - -1. **刷新页面**: 重新加载智能主机页面 -2. **检查显示**: 确认主机编号正确显示 -3. **测试搜索**: 尝试按主机编号搜索 -4. **测试编辑**: 点击编辑按钮查看主机编号 - -## 🔄 维护建议 - -1. **字段映射**: 保持API字段与前端显示的一致性 -2. **向后兼容**: 使用 `||` 操作符确保向后兼容 -3. **测试验证**: 定期测试字段映射的正确性 -4. **文档更新**: 及时更新API文档和前端文档 - ---- - -**🎉 主机编号显示问题已完全解决!现在所有主机都能正确显示其编号。** - diff --git a/mini_program/farm-monitor-dashboard/IMPLEMENTATION_SUMMARY.md b/mini_program/farm-monitor-dashboard/IMPLEMENTATION_SUMMARY.md deleted file mode 100644 index f5b04b8..0000000 --- a/mini_program/farm-monitor-dashboard/IMPLEMENTATION_SUMMARY.md +++ /dev/null @@ -1,117 +0,0 @@ -# 智能主机API集成实现总结 - -## ✅ 已完成的功能 - -### 1. **完全移除模拟数据** -- ✅ 移除了所有硬编码的模拟数据 -- ✅ 移除了`getMockData()`方法 -- ✅ 移除了API错误时的模拟数据降级 -- ✅ 确保只使用真实API接口数据 - -### 2. **真实API集成** -- ✅ 直接调用`/api/smart-devices/hosts`接口 -- ✅ 正确处理API响应结构(包含`success`, `data`, `total`字段) -- ✅ 支持分页参数(`page`, `pageSize`) -- ✅ 支持搜索参数(`search`) - -### 3. **动态数据获取** -- ✅ 主机总数使用API返回的`total`字段(应该是371) -- ✅ 在线/离线数量基于API返回的真实数据计算 -- ✅ 分页信息完全来自API响应 -- ✅ 实时更新统计数据 - -### 4. **分页功能** -- ✅ 完整的分页控件(上一页/下一页/页码) -- ✅ 当前页高亮显示 -- ✅ 分页信息显示(共X条记录,第X/X页) -- ✅ 智能页码显示逻辑 - -### 5. **搜索功能** -- ✅ 按主机编号精确搜索 -- ✅ 搜索时重置到第一页 -- ✅ 实时过滤结果 - -### 6. **错误处理** -- ✅ 详细的API调用日志 -- ✅ 认证错误检测 -- ✅ 网络错误处理 -- ✅ 用户友好的错误提示 - -## 🔧 技术实现 - -### API服务层 (`hostService.js`) -```javascript -// 直接调用真实API,无模拟数据 -export const getHostDevices = async (params = {}) => { - const response = await api.get('/api/smart-devices/hosts', { params }) - // 处理API响应结构 - return { - data: apiData.data, - pagination: { - total: apiData.total, // 使用API返回的371 - // ... - } - } -} -``` - -### 组件层 (`SmartHost.vue`) -```javascript -// 使用API返回的真实数据 -this.totalCount = this.pagination.total || this.devices.length -this.onlineCount = this.devices.filter(device => device.isOnline).length -this.offlineCount = this.devices.filter(device => !device.isOnline).length -``` - -## 🚨 当前问题 - -### 认证问题 -- ❌ API返回401未授权错误 -- ❌ 需要正确的认证token才能访问 -- ❌ 前端无法获取371台主机的数据 - -### 解决方案 -1. **获取认证token**: - ```bash - node set-token.js - ``` - -2. **在浏览器中设置token**: - ```javascript - localStorage.setItem('token', 'YOUR_ACTUAL_TOKEN') - ``` - -3. **测试API连接**: - ```bash - node test-api.js - ``` - -## 📊 预期结果 - -一旦解决认证问题,前端应该: -- ✅ 显示主机总数:371 -- ✅ 正确显示在线/离线数量 -- ✅ 分页显示所有371台主机 -- ✅ 搜索功能正常工作 -- ✅ 编辑功能正常工作 - -## 🛠️ 测试工具 - -1. **API测试**:`node test-api.js` -2. **认证测试**:`node auth-test.js` -3. **Token设置**:`node set-token.js` - -## 📝 下一步 - -1. 联系后端开发者获取正确的认证信息 -2. 设置认证token -3. 测试API连接 -4. 验证前端显示371台主机 - -## 🎯 代码特点 - -- **无硬编码**:所有数据都来自API -- **无模拟数据**:完全使用真实接口 -- **统一接口**:使用标准的REST API -- **动态更新**:实时获取最新数据 -- **错误处理**:完善的错误处理机制 diff --git a/mini_program/farm-monitor-dashboard/LOGIN_PAGE_README.md b/mini_program/farm-monitor-dashboard/LOGIN_PAGE_README.md deleted file mode 100644 index 6727b01..0000000 --- a/mini_program/farm-monitor-dashboard/LOGIN_PAGE_README.md +++ /dev/null @@ -1,112 +0,0 @@ -# 登录页面使用说明 - -## 页面地址 -- **登录页面**: http://localhost:8080/login -- **首页**: http://localhost:8080/ - -## 功能特点 - -### 🎨 界面设计 -- **简洁美观**: 采用白色背景,绿色主题色 -- **响应式设计**: 适配手机、平板、桌面等不同设备 -- **状态栏**: 显示时间、信号、WiFi、电池状态 -- **语言选择**: 支持简体中文和英文切换 - -### 🔐 登录功能 -- **一键登录**: 主要登录方式,绿色按钮突出显示 -- **协议同意**: 必须同意用户服务协议和隐私政策才能登录 -- **其他登录方式**: 短信登录、注册账号、其它方式(预留接口) - -### 🛡️ 安全机制 -- **路由守卫**: 未登录用户自动跳转到登录页 -- **登录状态检查**: 已登录用户访问登录页会跳转到首页 -- **认证管理**: 使用localStorage存储token和用户信息 - -## 使用方法 - -### 1. 访问登录页面 -``` -http://localhost:8080/login -``` - -### 2. 登录流程 -1. 勾选"我已阅读并同意《用户服务协议》及《隐私政策》" -2. 点击"一键登录"按钮 -3. 系统模拟登录过程(1.5秒) -4. 登录成功后自动跳转到首页 - -### 3. 其他功能 -- **短信登录**: 点击"短信登录"(功能开发中) -- **注册账号**: 点击"注册账号"(功能开发中) -- **其它登录**: 点击"其它"(功能开发中) -- **生资监管方案**: 点击底部服务链接 -- **绑定天翼账号**: 点击底部服务链接 - -## 技术实现 - -### 组件结构 -``` -Login.vue -├── 状态栏 (status-bar) -├── 头部导航 (header-bar) -├── 语言选择 (language-selector) -├── 主要内容 (main-content) -│ ├── 应用标题 (app-title) -│ ├── 登录区域 (login-section) -│ ├── 其他登录方式 (alternative-login) -│ ├── 底部服务 (footer-services) -│ └── 免责声明 (disclaimer) -``` - -### 核心功能 -- **认证管理**: 集成 `@/utils/auth` 工具 -- **路由守卫**: 自动处理登录状态检查 -- **状态管理**: 使用Vue data管理组件状态 -- **事件处理**: 完整的用户交互逻辑 - -### 样式特点 -- **移动优先**: 响应式设计,适配各种屏幕尺寸 -- **交互反馈**: 按钮悬停、点击效果 -- **视觉层次**: 清晰的信息层级和视觉引导 -- **品牌色彩**: 绿色主题色,符合农业应用特色 - -## 开发说明 - -### 模拟登录 -当前使用模拟登录,实际项目中需要: -1. 连接真实登录API -2. 处理登录验证逻辑 -3. 实现短信验证码功能 -4. 添加注册功能 - -### 自定义配置 -可以在 `Login.vue` 中修改: -- 应用名称和标题 -- 主题色彩 -- 登录方式 -- 服务链接 -- 免责声明内容 - -### 扩展功能 -可以添加: -- 忘记密码功能 -- 第三方登录(微信、QQ等) -- 生物识别登录 -- 多语言支持 -- 主题切换 - -## 注意事项 - -1. **协议同意**: 用户必须同意协议才能登录 -2. **登录状态**: 登录后访问 `/login` 会自动跳转到首页 -3. **退出登录**: 在"我的"页面可以退出登录 -4. **路由保护**: 未登录用户无法访问其他页面 -5. **数据持久化**: 登录状态保存在localStorage中 - -## 测试方法 - -1. 直接访问 http://localhost:8080/login -2. 不勾选协议,点击登录(应该提示需要同意协议) -3. 勾选协议,点击登录(应该成功登录并跳转) -4. 登录后访问 http://localhost:8080/login(应该跳转到首页) -5. 在"我的"页面点击"退出登录"(应该跳转到登录页) diff --git a/mini_program/farm-monitor-dashboard/NAVIGATION_FIX_SUMMARY.md b/mini_program/farm-monitor-dashboard/NAVIGATION_FIX_SUMMARY.md deleted file mode 100644 index 9892ffa..0000000 --- a/mini_program/farm-monitor-dashboard/NAVIGATION_FIX_SUMMARY.md +++ /dev/null @@ -1,209 +0,0 @@ -# 智能耳标页面跳转功能修复总结 - -## 🔍 问题分析 - -**问题描述**: 点击智能耳标没有跳转 - -**根本原因**: -1. 目标页面 `eartag-detail` 不存在 -2. 缺少错误处理机制 -3. 数据传递可能存在问题 - -## ✅ 解决方案 - -### 1. 创建耳标详情页面 -**文件**: `pages/device/eartag-detail/` - -#### 功能特性: -- ✅ 显示耳标详细信息 -- ✅ 绑定/解绑牛只功能 -- ✅ 编辑信息功能 -- ✅ 返回上一页功能 -- ✅ 加载状态处理 - -#### 页面结构: -```javascript -// 主要功能 -- onLoad(options) // 接收耳标ID参数 -- fetchEartagDetail() // 获取详情数据 -- onBind() // 绑定牛只 -- onUnbind() // 解绑牛只 -- onEdit() // 编辑信息 -- goBack() // 返回上一页 -``` - -### 2. 创建添加耳标页面 -**文件**: `pages/device/eartag-add/` - -#### 功能特性: -- ✅ 表单输入验证 -- ✅ API接口调用 -- ✅ 成功/失败提示 -- ✅ 自动返回上一页 - -#### 表单字段: -- 耳标编号 (必填) -- 主机号 (必填) -- 初始电量 (可选) -- 备注 (可选) - -### 3. 优化点击事件处理 -**文件**: `pages/device/eartag/eartag.js` - -#### 改进内容: -```javascript -// 优化前 -onEartagClick(e) { - const item = e.currentTarget.dataset.item - wx.navigateTo({ - url: `/pages/device/eartag-detail/eartag-detail?id=${item.eartagNumber}` - }) -} - -// 优化后 -onEartagClick(e) { - const item = e.currentTarget.dataset.item - - // 数据验证 - if (!item || !item.eartagNumber) { - wx.showToast({ - title: '数据错误', - icon: 'none' - }) - return - } - - // 跳转 with 错误处理 - wx.navigateTo({ - url: `/pages/device/eartag-detail/eartag-detail?id=${item.eartagNumber}`, - success: () => { - console.log('跳转成功') - }, - fail: (error) => { - console.error('跳转失败:', error) - wx.showToast({ - title: '跳转失败', - icon: 'none' - }) - } - }) -} -``` - -### 4. 更新页面配置 -**文件**: `app.json` - -#### 新增页面: -```json -{ - "pages": [ - "pages/device/eartag/eartag", - "pages/device/eartag-detail/eartag-detail", - "pages/device/eartag-add/eartag-add" - ] -} -``` - -## 🎯 修复结果 - -### ✅ 解决的问题: -1. **页面不存在**: 创建了详情页和添加页 -2. **跳转失败**: 添加了错误处理机制 -3. **数据验证**: 增加了数据有效性检查 -4. **用户体验**: 添加了成功/失败提示 - -### ✅ 新增功能: -1. **耳标详情页**: 完整的详情展示和操作 -2. **添加耳标页**: 表单输入和API调用 -3. **错误处理**: 完善的异常处理机制 -4. **用户反馈**: 清晰的状态提示 - -## 📱 使用流程 - -### 智能耳标页面操作流程: -1. **查看列表**: 显示所有耳标数据 -2. **点击耳标**: 跳转到详情页面 -3. **查看详情**: 显示耳标详细信息 -4. **绑定操作**: 绑定/解绑牛只 -5. **编辑信息**: 修改耳标信息 -6. **添加耳标**: 点击"+"按钮添加新耳标 - -### 跳转路径: -``` -智能耳标列表页 - ↓ (点击耳标) -耳标详情页 - ↓ (点击编辑) -耳标编辑页 - ↓ (点击添加) -添加耳标页 -``` - -## 🔧 技术实现 - -### 数据传递: -```javascript -// 列表页 → 详情页 -wx.navigateTo({ - url: `/pages/device/eartag-detail/eartag-detail?id=${item.eartagNumber}` -}) - -// 详情页接收参数 -onLoad(options) { - if (options.id) { - this.setData({ eartagId: options.id }) - this.fetchEartagDetail(options.id) - } -} -``` - -### 错误处理: -```javascript -// 数据验证 -if (!item || !item.eartagNumber) { - wx.showToast({ - title: '数据错误', - icon: 'none' - }) - return -} - -// 跳转错误处理 -wx.navigateTo({ - url: '...', - success: () => console.log('跳转成功'), - fail: (error) => { - console.error('跳转失败:', error) - wx.showToast({ - title: '跳转失败', - icon: 'none' - }) - } -}) -``` - -## 🚀 测试建议 - -### 功能测试: -1. **点击耳标**: 确认能正常跳转到详情页 -2. **查看详情**: 确认数据正确显示 -3. **返回功能**: 确认能正常返回列表页 -4. **添加耳标**: 确认能正常跳转到添加页 -5. **表单提交**: 确认能正常添加耳标 - -### 错误测试: -1. **数据异常**: 测试数据为空时的处理 -2. **网络异常**: 测试API调用失败时的处理 -3. **参数错误**: 测试参数缺失时的处理 - -## 📞 后续优化 - -1. **API集成**: 对接真实的详情和添加API -2. **数据缓存**: 优化数据加载性能 -3. **离线支持**: 添加离线数据支持 -4. **批量操作**: 支持批量绑定/解绑 -5. **数据同步**: 实时同步数据更新 - ---- - -**修复完成**: 智能耳标页面点击跳转功能已完全修复,所有相关页面和功能都已实现! diff --git a/mini_program/farm-monitor-dashboard/NAVIGATION_IMPLEMENTATION_SUMMARY.md b/mini_program/farm-monitor-dashboard/NAVIGATION_IMPLEMENTATION_SUMMARY.md deleted file mode 100644 index 60854b5..0000000 --- a/mini_program/farm-monitor-dashboard/NAVIGATION_IMPLEMENTATION_SUMMARY.md +++ /dev/null @@ -1,144 +0,0 @@ -# 养殖端微信小程序底部导航栏实现总结 - -## 📱 项目概述 - -已成功实现养殖端微信小程序的底部导航栏,包含三个主要页面:**首页**、**生产管理**、**我的**。 - -## ✅ 完成的功能 - -### 1. 底部导航栏配置 -- ✅ 更新 `app.json` 中的 `tabBar` 配置 -- ✅ 设置三个导航页面:首页、生产管理、我的 -- ✅ 配置导航栏颜色和样式 - -### 2. 首页页面 (pages/home/home) -- ✅ 根据图片UI样式重新设计首页 -- ✅ 顶部状态栏(时间、位置、天气) -- ✅ 搜索框和扫描功能 -- ✅ 数据统计卡片(总牛只数、怀孕牛只、泌乳牛只、健康牛只) -- ✅ 功能模块网格(8个功能模块) -- ✅ 最近活动列表 -- ✅ 响应式设计 - -### 3. 生产管理页面 (pages/production/production) -- ✅ 创建完整的生产管理页面 -- ✅ 生产数据统计卡片 -- ✅ 生产管理功能模块(8个模块) -- ✅ 最近生产活动记录 -- ✅ 与首页一致的设计风格 - -### 4. 我的页面 (pages/profile/profile) -- ✅ 使用现有的个人中心页面 -- ✅ 保持原有功能不变 - -## 🎨 UI设计特点 - -### 首页设计亮点 -1. **渐变背景**:使用现代化的渐变背景设计 -2. **状态栏**:顶部显示时间、位置和天气信息 -3. **搜索功能**:集成搜索框和二维码扫描功能 -4. **数据可视化**:统计卡片显示趋势变化 -5. **功能模块**:4x2网格布局,图标+文字设计 -6. **活动列表**:最近活动记录,支持点击跳转 - -### 配色方案 -- 主色调:绿色 (#3cc51f) -- 辅助色:蓝色 (#1890ff)、橙色 (#faad14)、红色 (#f5222d) -- 背景:渐变白色到浅灰色 -- 文字:深灰色 (#333)、中灰色 (#666)、浅灰色 (#999) - -## 📁 文件结构 - -``` -mini_program/farm-monitor-dashboard/ -├── app.json # 应用配置(已更新tabBar) -├── pages/ -│ ├── home/ # 首页 -│ │ ├── home.wxml # 页面结构 -│ │ ├── home.wxss # 页面样式 -│ │ └── home.js # 页面逻辑 -│ ├── production/ # 生产管理页面 -│ │ ├── production.wxml # 页面结构 -│ │ ├── production.wxss # 页面样式 -│ │ └── production.js # 页面逻辑 -│ └── profile/ # 我的页面 -│ ├── profile.wxml # 页面结构 -│ ├── profile.wxss # 页面样式 -│ └── profile.js # 页面逻辑 -├── images/ -│ └── ICON_REQUIREMENTS.md # 图标需求说明 -└── test-navigation.js # 导航测试脚本 -``` - -## 🔧 技术实现 - -### 1. 页面配置 -- 在 `app.json` 中配置了三个tabBar页面 -- 设置了统一的导航栏样式和颜色 - -### 2. 首页功能 -- 实时时间显示(每分钟更新) -- 搜索功能(支持关键词搜索) -- 二维码扫描功能 -- 数据统计(支持趋势显示) -- 下拉刷新功能 - -### 3. 生产管理页面 -- 生产数据统计 -- 8个生产管理功能模块 -- 最近生产活动记录 -- 与首页一致的设计风格 - -### 4. 响应式设计 -- 支持不同屏幕尺寸 -- 小屏幕设备优化(375px以下) -- 网格布局自适应 - -## ⚠️ 注意事项 - -### 图标文件 -需要创建以下图标文件(当前为占位符): -- `images/home.png` - 首页未选中图标 -- `images/home-active.png` - 首页选中图标 -- `images/production.png` - 生产管理未选中图标 -- `images/production-active.png` - 生产管理选中图标 -- `images/profile.png` - 我的未选中图标 -- `images/profile-active.png` - 我的选中图标 - -### 图标规格 -- 尺寸:40x40 像素 -- 格式:PNG格式,支持透明背景 -- 颜色:未选中 #7A7E83,选中 #3cc51f - -## 🚀 使用方法 - -1. 在微信开发者工具中打开项目 -2. 确保所有页面文件存在 -3. 添加所需的图标文件 -4. 编译并预览小程序 -5. 测试底部导航栏功能 - -## 📋 测试清单 - -- [x] 底部导航栏显示正常 -- [x] 三个页面可以正常切换 -- [x] 首页功能完整 -- [x] 生产管理页面功能完整 -- [x] 我的页面功能完整 -- [x] 响应式设计正常 -- [ ] 图标文件需要添加 -- [ ] 实际数据接口对接 - -## 🎯 下一步计划 - -1. 添加底部导航栏图标文件 -2. 对接真实的后端API接口 -3. 完善搜索和扫描功能 -4. 添加更多交互效果 -5. 优化性能和用户体验 - ---- - -**开发完成时间**: 2024年 -**开发状态**: ✅ 基础功能完成 -**待办事项**: 图标文件、API对接 diff --git a/mini_program/farm-monitor-dashboard/NETWORK_ERROR_FIX.md b/mini_program/farm-monitor-dashboard/NETWORK_ERROR_FIX.md deleted file mode 100644 index aa43df3..0000000 --- a/mini_program/farm-monitor-dashboard/NETWORK_ERROR_FIX.md +++ /dev/null @@ -1,121 +0,0 @@ -# 网络连接错误修复说明 - -## 问题描述 -出现错误:`API请求错误: 0 /api/smart-devices/eartags` 和 `net::ERR_CONNECTION_REFUSED` - -## 问题原因 -后端API服务器没有运行,导致前端无法连接到 `http://localhost:5350` - -## 解决方案 - -### 1. 启动后端服务 -```bash -cd C:\nxxmdata\backend -npm start -``` - -### 2. 验证服务状态 -```powershell -# 检查后端服务 -netstat -an | findstr :5350 - -# 检查前端服务 -netstat -an | findstr :8080 -``` - -### 3. 测试API连接 -```powershell -# 测试登录API -Invoke-WebRequest -Uri "http://localhost:5350/api/auth/login" -Method POST -Body '{"username":"admin","password":"123456"}' -ContentType "application/json" - -# 测试耳标API -$response = Invoke-WebRequest -Uri "http://localhost:5350/api/auth/login" -Method POST -Body '{"username":"admin","password":"123456"}' -ContentType "application/json" -$token = ($response.Content | ConvertFrom-Json).token -Invoke-WebRequest -Uri "http://localhost:5350/api/smart-devices/eartags" -Headers @{"Authorization"="Bearer $token"} -Method GET -``` - -## 当前状态 - -### ✅ 后端服务 -- **状态**: 正在运行 -- **端口**: 5350 -- **API**: 正常工作 -- **认证**: JWT token正常 - -### ✅ 前端服务 -- **状态**: 正在运行 -- **端口**: 8080 -- **代理**: 配置正确 - -### ✅ API测试 -- **登录API**: 正常返回token -- **耳标API**: 正常返回数据 -- **认证**: JWT token验证正常 - -## 使用方法 - -### 1. 访问应用 -``` -http://localhost:8080 -``` - -### 2. 测试API -``` -http://localhost:8080/auth-test -``` - -### 3. 设备管理 -- 耳标设备: `http://localhost:8080/ear-tag` -- 项圈设备: `http://localhost:8080/smart-collar` -- 脚环设备: `http://localhost:8080/smart-ankle` -- 主机设备: `http://localhost:8080/smart-host` - -## 故障排除 - -### 如果仍然出现连接错误 -1. 检查后端服务是否运行:`netstat -an | findstr :5350` -2. 检查前端服务是否运行:`netstat -an | findstr :8080` -3. 重启后端服务:`cd C:\nxxmdata\backend && npm start` -4. 重启前端服务:`cd C:\nxxmdata\mini_program\farm-monitor-dashboard && npm run serve` - -### 如果API返回401错误 -1. 访问认证测试页面 -2. 点击"设置真实Token"按钮 -3. 点击"测试所有API"按钮 - -### 如果代理不工作 -1. 检查vue.config.js配置 -2. 重启前端开发服务器 -3. 清除浏览器缓存 - -## 服务启动顺序 - -1. **启动后端服务** - ```bash - cd C:\nxxmdata\backend - npm start - ``` - -2. **启动前端服务** - ```bash - cd C:\nxxmdata\mini_program\farm-monitor-dashboard - npm run serve - ``` - -3. **验证服务** - - 后端: http://localhost:5350/api-docs - - 前端: http://localhost:8080 - -## 预期结果 - -- ✅ 前端可以正常访问后端API -- ✅ 所有设备API返回真实数据 -- ✅ 认证系统正常工作 -- ✅ 不再出现网络连接错误 - -## 注意事项 - -1. 确保两个服务都在运行 -2. 后端服务必须先启动 -3. 如果修改了配置,需要重启服务 -4. 检查防火墙设置是否阻止了端口访问 diff --git a/mini_program/farm-monitor-dashboard/PAGINATION_FIELD_MAPPING_FIX.md b/mini_program/farm-monitor-dashboard/PAGINATION_FIELD_MAPPING_FIX.md deleted file mode 100644 index b0508a6..0000000 --- a/mini_program/farm-monitor-dashboard/PAGINATION_FIELD_MAPPING_FIX.md +++ /dev/null @@ -1,123 +0,0 @@ -# 分页字段映射修复报告 - -## 问题描述 -API响应分页信息为 `{page: 3, limit: 10, total: 2000, pages: 200}`,但前端分页高亮显示的是第1页,存在字段映射不匹配的问题。 - -## 问题分析 - -### 1. API响应字段格式 -```javascript -// API实际返回的分页字段 -{ - page: 3, // 当前页码 - limit: 10, // 每页数量 - total: 2000, // 总数据量 - pages: 200 // 总页数 -} -``` - -### 2. 前端期望字段格式 -```javascript -// 前端期望的分页字段 -{ - current: 3, // 当前页码 - pageSize: 10, // 每页数量 - total: 2000, // 总数据量 - totalPages: 200 // 总页数 -} -``` - -### 3. 字段映射不匹配 -- `page` → `current` -- `limit` → `pageSize` -- `pages` → `totalPages` -- `total` → `total` (相同) - -## 修复方案 - -### 1. 更新collarService.js中的字段映射 -```javascript -// 确保分页信息存在并正确映射字段 -if (response.data.pagination) { - // 映射API返回的分页字段到前端期望的字段 - response.data.pagination = { - current: parseInt(response.data.pagination.page || response.data.pagination.current || queryParams.page) || 1, - pageSize: parseInt(response.data.pagination.limit || response.data.pagination.pageSize || queryParams.limit) || 10, - total: parseInt(response.data.pagination.total || 0) || 0, - totalPages: parseInt(response.data.pagination.pages || response.data.pagination.totalPages || 1) || 1 - } -} -``` - -### 2. 字段映射优先级 -1. **current**: `page` → `current` → `queryParams.page` -2. **pageSize**: `limit` → `pageSize` → `queryParams.limit` -3. **total**: `total` → `0` -4. **totalPages**: `pages` → `totalPages` → `1` - -### 3. 向后兼容性 -- 支持API返回 `page` 或 `current` 字段 -- 支持API返回 `limit` 或 `pageSize` 字段 -- 支持API返回 `pages` 或 `totalPages` 字段 -- 如果API没有返回分页信息,使用默认值 - -## 修复效果 - -### 修复前 -- API返回: `{page: 3, limit: 10, total: 2000, pages: 200}` -- 前端显示: 分页高亮第1页 ❌ -- 分页信息: "第 NaN-NaN条,共2000条" ❌ - -### 修复后 -- API返回: `{page: 3, limit: 10, total: 2000, pages: 200}` -- 映射后: `{current: 3, pageSize: 10, total: 2000, totalPages: 200}` -- 前端显示: 分页高亮第3页 ✅ -- 分页信息: "第 21-30条,共2000条" ✅ - -## 测试验证 - -### 1. 测试脚本 -创建了 `test-pagination-fix.js` 测试脚本,包含: -- 原始API响应分页信息显示 -- 字段映射验证 -- 分页高亮正确性验证 - -### 2. 运行测试 -```bash -cd mini_program/farm-monitor-dashboard -node test-pagination-fix.js -``` - -### 3. 测试覆盖 -- ✅ API字段映射正确性 -- ✅ 分页高亮显示正确性 -- ✅ 分页信息计算正确性 -- ✅ 向后兼容性 - -## 技术细节 - -### 1. 字段映射逻辑 -```javascript -// 智能字段映射,支持多种API响应格式 -current: parseInt(response.data.pagination.page || response.data.pagination.current || queryParams.page) || 1 -``` - -### 2. 数据类型转换 -- 使用 `parseInt()` 确保数值类型 -- 提供默认值防止 `NaN` 错误 -- 支持字符串和数字类型转换 - -### 3. 错误处理 -- 如果API没有返回分页信息,使用默认值 -- 如果字段值为空或无效,使用查询参数 -- 如果所有值都无效,使用硬编码默认值 - -## 总结 - -通过修复分页字段映射问题,现在: -1. **分页高亮正确**:API返回第3页时,前端正确高亮第3页 -2. **分页信息正确**:显示正确的"第 X-Y 条,共 Z 条"格式 -3. **向后兼容**:支持多种API响应格式 -4. **错误处理**:提供完善的错误处理和默认值 - -分页功能现在可以正常工作,用户界面与API数据完全同步。 diff --git a/mini_program/farm-monitor-dashboard/PASSWORD_LOGIN_README.md b/mini_program/farm-monitor-dashboard/PASSWORD_LOGIN_README.md deleted file mode 100644 index 1cb3829..0000000 --- a/mini_program/farm-monitor-dashboard/PASSWORD_LOGIN_README.md +++ /dev/null @@ -1,175 +0,0 @@ -# 密码登录页面使用说明 - -## 页面地址 -- **密码登录页面**: http://localhost:8080/password-login -- **一键登录页面**: http://localhost:8080/login -- **短信登录页面**: http://localhost:8080/sms-login -- **注册页面**: http://localhost:8080/register -- **首页**: http://localhost:8080/ - -## 功能特点 - -### 🎨 界面设计 -- **简洁美观**: 采用白色背景,绿色主题色 -- **响应式设计**: 适配手机、平板、桌面等不同设备 -- **状态栏**: 显示时间、信号、WiFi、电池状态 -- **语言选择**: 支持简体中文和英文切换 - -### 🔐 密码登录功能 -- **账号输入**: 支持用户名、手机号、邮箱等格式 -- **密码输入**: 支持显示/隐藏切换,最少6位 -- **协议同意**: 必须同意用户服务协议和隐私政策 -- **实时验证**: 输入格式实时验证和错误提示 - -### 🔄 多种登录方式 -- **一键登录**: 跳转到一键登录页面 -- **短信登录**: 跳转到短信登录页面 -- **注册账号**: 跳转到注册页面 -- **其它方式**: 预留更多登录方式接口 - -## 使用方法 - -### 1. 访问密码登录页面 -``` -http://localhost:8080/password-login -``` - -### 2. 登录流程 -1. 输入账号(用户名、手机号或邮箱) -2. 输入密码(最少6位) -3. 勾选"我已阅读并同意《用户服务协议》及《隐私政策》" -4. 点击"登录"按钮 -5. 登录成功后自动跳转到首页 - -### 3. 其他功能 -- **密码显示**: 点击密码框右侧眼睛图标切换显示/隐藏 -- **其他登录方式**: 点击下方登录方式选项 -- **服务链接**: 点击底部服务链接 - -## 技术实现 - -### 组件结构 -``` -PasswordLogin.vue -├── 状态栏 (status-bar) -├── 头部导航 (header-bar) -├── 语言选择 (language-selector) -├── 主要内容 (main-content) -│ ├── 应用标题 (app-title) -│ ├── 登录表单 (login-form) -│ │ ├── 账号输入框 (input-group) -│ │ ├── 密码输入框 (input-group) -│ │ └── 协议同意 (agreement-section) -│ ├── 其他登录方式 (alternative-login) -│ ├── 底部服务 (footer-services) -│ └── 免责声明 (disclaimer) -``` - -### 核心功能 -- **表单验证**: 实时验证账号和密码格式 -- **密码安全**: 支持密码显示/隐藏切换 -- **协议管理**: 必须同意协议才能登录 -- **状态管理**: 完整的加载和错误状态 - -### 登录验证 -- **模拟验证**: 开发环境使用模拟验证 -- **测试账号**: admin/123456(开发环境) -- **密码强度**: 最少6位密码要求 -- **错误处理**: 详细的错误信息提示 - -## 开发说明 - -### 模拟功能 -当前使用模拟登录验证,实际项目中需要: -1. 连接真实用户认证API -2. 实现密码加密传输 -3. 添加记住密码功能 -4. 集成单点登录(SSO) - -### 验证规则 -- **账号格式**: 支持用户名、手机号、邮箱 -- **密码强度**: 最少6位,建议包含字母和数字 -- **协议同意**: 必须勾选协议才能登录 -- **登录状态**: 已登录用户访问会跳转到首页 - -### 自定义配置 -可以在 `PasswordLogin.vue` 中修改: -- 密码最小长度 -- 账号格式验证 -- 错误提示信息 -- 样式和主题 - -## 测试方法 - -### 1. 基本功能测试 -1. 访问 http://localhost:8080/password-login -2. 输入账号(如:admin) -3. 输入密码(如:123456) -4. 勾选协议同意 -5. 点击"登录" - -### 2. 验证测试 -1. 输入空账号 -2. 应该显示"请输入账号"错误 -3. 输入空密码 -4. 应该显示"请输入密码"错误 -5. 输入短密码(如:123) -6. 应该显示"密码长度不能少于6位"错误 - -### 3. 协议测试 -1. 不勾选协议同意 -2. 登录按钮应该被禁用 -3. 勾选协议同意 -4. 登录按钮应该可用 - -## 注意事项 - -1. **协议同意**: 必须同意用户服务协议和隐私政策 -2. **密码安全**: 支持密码显示/隐藏切换 -3. **登录状态**: 已登录用户访问会跳转到首页 -4. **错误处理**: 所有错误都有相应的用户提示 -5. **多种登录**: 支持多种登录方式切换 - -## 扩展功能 - -可以添加的功能: -- 记住密码 -- 自动登录 -- 忘记密码 -- 第三方登录(微信、QQ、支付宝等) -- 生物识别登录 -- 多因素认证 -- 单点登录(SSO) - -## 样式特点 - -- **移动优先**: 响应式设计,适配各种屏幕 -- **交互反馈**: 按钮状态、输入框焦点效果 -- **视觉层次**: 清晰的信息层级 -- **品牌一致**: 与整体应用风格保持一致 -- **无障碍**: 支持键盘导航和屏幕阅读器 - -## 页面跳转 - -- **从登录页**: 点击"其它"跳转到密码登录页 -- **一键登录**: 点击"一键登录"跳转到一键登录页 -- **短信登录**: 点击"短信登录"跳转到短信登录页 -- **注册账号**: 点击"注册账号"跳转到注册页 -- **返回上一页**: 点击左上角房子图标 - -## 登录方式对比 - -| 登录方式 | 页面地址 | 特点 | 适用场景 | -|---------|---------|------|---------| -| 一键登录 | /login | 简单快速 | 首次使用 | -| 短信登录 | /sms-login | 安全可靠 | 忘记密码 | -| 密码登录 | /password-login | 传统方式 | 日常使用 | -| 注册账号 | /register | 新用户 | 首次注册 | - -## 安全建议 - -1. **密码强度**: 建议使用强密码 -2. **定期更换**: 定期更换密码 -3. **安全环境**: 在安全环境下登录 -4. **退出登录**: 使用完毕后及时退出 -5. **协议阅读**: 仔细阅读用户协议和隐私政策 diff --git a/mini_program/farm-monitor-dashboard/README.md b/mini_program/farm-monitor-dashboard/README.md deleted file mode 100644 index b83db14..0000000 --- a/mini_program/farm-monitor-dashboard/README.md +++ /dev/null @@ -1,229 +0,0 @@ -# 养殖管理系统微信小程序 - -## 项目简介 - -这是一个基于微信小程序原生技术开发的养殖管理系统,用于管理牛只档案、设备监控、预警管理等养殖业务。 - -## 技术栈 - -- **框架**: 微信小程序原生开发 -- **语言**: JavaScript ES6+ -- **样式**: WXSS -- **模板**: WXML -- **状态管理**: 微信小程序全局数据 -- **网络请求**: wx.request -- **UI组件**: 微信小程序原生组件 - -## 项目结构 - -``` -farm-monitor-dashboard/ -├── app.js # 小程序入口文件 -├── app.json # 小程序全局配置 -├── app.wxss # 小程序全局样式 -├── sitemap.json # 站点地图配置 -├── project.config.json # 项目配置文件 -├── package.json # 项目依赖配置 -├── pages/ # 页面目录 -│ ├── home/ # 首页 -│ │ ├── home.js -│ │ ├── home.wxml -│ │ └── home.wxss -│ ├── login/ # 登录页 -│ │ ├── login.js -│ │ ├── login.wxml -│ │ └── login.wxss -│ ├── cattle/ # 牛只管理 -│ │ ├── cattle.js -│ │ ├── cattle.wxml -│ │ └── cattle.wxss -│ ├── device/ # 设备管理 -│ │ ├── device.js -│ │ ├── device.wxml -│ │ └── device.wxss -│ ├── alert/ # 预警中心 -│ │ ├── alert.js -│ │ ├── alert.wxml -│ │ └── alert.wxss -│ └── profile/ # 个人中心 -│ ├── profile.js -│ ├── profile.wxml -│ └── profile.wxss -├── services/ # 服务层 -│ ├── api.js # API接口定义 -│ ├── cattleService.js # 牛只管理服务 -│ ├── deviceService.js # 设备管理服务 -│ └── alertService.js # 预警管理服务 -├── utils/ # 工具函数 -│ ├── index.js # 通用工具函数 -│ ├── api.js # API请求工具 -│ └── auth.js # 认证工具 -├── images/ # 图片资源 -│ └── README.md -└── README.md # 项目说明文档 -``` - -## 功能特性 - -### 1. 用户认证 -- 密码登录 -- 短信验证码登录 -- 微信授权登录 -- 自动登录状态保持 - -### 2. 牛只管理 -- 牛只档案管理 -- 牛只信息查询和搜索 -- 牛只状态管理 -- 牛只健康记录 -- 牛只繁殖记录 -- 牛只饲喂记录 - -### 3. 设备管理 -- 智能设备监控 -- 设备状态管理 -- 设备配置管理 -- 设备历史数据查看 -- 设备实时数据监控 - -### 4. 预警中心 -- 智能预警管理 -- 预警类型分类 -- 预警处理流程 -- 预警统计分析 -- 预警规则配置 - -### 5. 个人中心 -- 用户信息管理 -- 系统设置 -- 消息通知 -- 帮助中心 - -## 开发环境配置 - -### 1. 安装微信开发者工具 -下载并安装 [微信开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html) - -### 2. 导入项目 -1. 打开微信开发者工具 -2. 选择"导入项目" -3. 选择项目目录 -4. 填写AppID(测试可使用测试号) -5. 点击"导入" - -### 3. 配置后端API -在 `utils/api.js` 中修改 `baseUrl` 为实际的后端API地址: - -```javascript -const config = { - baseUrl: 'https://your-backend-url.com/api', // 修改为实际的后端API地址 - // ... -} -``` - -## 开发指南 - -### 1. 页面开发 -每个页面包含三个文件: -- `.js` - 页面逻辑 -- `.wxml` - 页面结构 -- `.wxss` - 页面样式 - -### 2. 组件开发 -微信小程序支持自定义组件,可以在 `components` 目录下创建组件。 - -### 3. API调用 -使用 `utils/api.js` 中封装的请求方法: - -```javascript -const { get, post, put, del } = require('../../utils/api') - -// GET请求 -const data = await get('/api/endpoint', params) - -// POST请求 -const result = await post('/api/endpoint', data) -``` - -### 4. 状态管理 -使用微信小程序的全局数据管理: - -```javascript -// 设置全局数据 -getApp().globalData.userInfo = userInfo - -// 获取全局数据 -const userInfo = getApp().globalData.userInfo -``` - -## 部署说明 - -### 1. 代码审核 -1. 在微信开发者工具中点击"上传" -2. 填写版本号和项目备注 -3. 上传代码到微信后台 - -### 2. 提交审核 -1. 登录微信公众平台 -2. 进入小程序管理后台 -3. 在"版本管理"中提交审核 - -### 3. 发布上线 -审核通过后,在版本管理页面点击"发布"即可上线。 - -## 注意事项 - -### 1. 网络请求 -- 所有网络请求必须使用HTTPS -- 需要在微信公众平台配置服务器域名 -- 请求超时时间建议设置为10秒 - -### 2. 图片资源 -- 图片大小建议不超过2MB -- 支持格式:JPG、PNG、GIF -- 建议使用CDN加速 - -### 3. 性能优化 -- 合理使用分包加载 -- 避免频繁的setData操作 -- 使用图片懒加载 -- 优化网络请求 - -### 4. 兼容性 -- 支持微信版本7.0.0及以上 -- 支持iOS 10.0和Android 5.0及以上 -- 建议在真机上测试功能 - -## 常见问题 - -### 1. 网络请求失败 -- 检查服务器域名是否已配置 -- 确认API地址是否正确 -- 检查网络连接状态 - -### 2. 页面显示异常 -- 检查WXML语法是否正确 -- 确认数据绑定是否正确 -- 查看控制台错误信息 - -### 3. 样式问题 -- 检查WXSS语法是否正确 -- 确认选择器是否正确 -- 注意样式优先级 - -## 更新日志 - -### v1.0.0 (2024-01-01) -- 初始版本发布 -- 完成基础功能开发 -- 支持牛只管理、设备监控、预警管理 - -## 技术支持 - -如有问题,请联系开发团队或查看相关文档: -- 微信小程序官方文档:https://developers.weixin.qq.com/miniprogram/dev/ -- 项目文档:查看项目根目录下的文档文件 - -## 许可证 - -MIT License \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/REGISTER_PAGE_README.md b/mini_program/farm-monitor-dashboard/REGISTER_PAGE_README.md deleted file mode 100644 index 79a33cc..0000000 --- a/mini_program/farm-monitor-dashboard/REGISTER_PAGE_README.md +++ /dev/null @@ -1,162 +0,0 @@ -# 注册账号页面使用说明 - -## 页面地址 -- **注册页面**: http://localhost:8080/register -- **登录页面**: http://localhost:8080/login -- **短信登录**: http://localhost:8080/sms-login -- **首页**: http://localhost:8080/ - -## 功能特点 - -### 🎨 界面设计 -- **简洁美观**: 采用白色背景,绿色主题色 -- **响应式设计**: 适配手机、平板、桌面等不同设备 -- **状态栏**: 显示时间、信号、WiFi、电池状态 -- **返回按钮**: 左上角返回按钮,支持返回上一页 - -### 📝 注册功能 -- **真实姓名**: 必填项,用于身份验证 -- **手机号**: 必填项,支持中国大陆手机号格式 -- **验证码**: 6位数字验证码,60秒倒计时 -- **密码**: 最少6位,支持显示/隐藏切换 -- **实时验证**: 输入格式实时验证和错误提示 - -### 🔐 安全机制 -- **手机号检查**: 验证手机号是否已注册 -- **验证码验证**: 短信验证码验证 -- **密码强度**: 最少6位密码要求 -- **重复注册检查**: 防止重复注册 -- **自动登录**: 注册成功后自动登录 - -## 使用方法 - -### 1. 访问注册页面 -``` -http://localhost:8080/register -``` - -### 2. 注册流程 -1. 输入真实姓名(必填) -2. 输入手机号(支持1[3-9]xxxxxxxxx格式) -3. 点击"发送验证码"按钮 -4. 等待60秒倒计时结束 -5. 输入收到的6位验证码 -6. 输入密码(最少6位) -7. 点击"确认"按钮 -8. 注册成功后自动登录并跳转到首页 - -### 3. 其他功能 -- **已有账号登录**: 点击"已有账号?立即登录"跳转到登录页 -- **密码显示**: 点击密码框右侧眼睛图标切换显示/隐藏 - -## 技术实现 - -### 组件结构 -``` -Register.vue -├── 状态栏 (status-bar) -├── 头部导航 (header-bar) -├── 主要内容 (main-content) -│ ├── 注册表单 (register-form) -│ │ ├── 真实姓名输入框 (input-group) -│ │ ├── 手机号输入框 (input-group) -│ │ ├── 验证码输入框 (input-group) -│ │ └── 密码输入框 (input-group) -│ └── 其他选项 (alternative-options) -``` - -### 核心功能 -- **表单验证**: 实时验证所有输入字段 -- **倒计时管理**: 60秒发送间隔保护 -- **API集成**: 集成用户注册和短信服务API -- **状态管理**: 完整的加载和错误状态 - -### 用户服务API -- **用户注册**: `POST /api/user/register` -- **检查手机号**: `GET /api/user/check-phone/{phone}` -- **检查用户名**: `GET /api/user/check-username/{username}` -- **获取用户信息**: `GET /api/user/{userId}` -- **更新用户信息**: `PUT /api/user/{userId}` -- **修改密码**: `POST /api/user/{userId}/change-password` -- **重置密码**: `POST /api/user/reset-password` - -## 开发说明 - -### 模拟功能 -当前使用模拟注册服务,实际项目中需要: -1. 连接真实用户注册API -2. 实现用户数据存储 -3. 添加邮箱验证功能 -4. 集成实名认证服务 - -### 验证规则 -- **真实姓名**: 不能为空,支持中文和英文 -- **手机号**: 中国大陆手机号格式(1[3-9]xxxxxxxxx) -- **验证码**: 6位数字,5分钟有效期 -- **密码**: 最少6位,支持字母数字组合 - -### 自定义配置 -可以在 `Register.vue` 中修改: -- 密码最小长度 -- 验证码长度和格式 -- 错误提示信息 -- 样式和主题 - -## 测试方法 - -### 1. 基本功能测试 -1. 访问 http://localhost:8080/register -2. 输入真实姓名(如:张三) -3. 输入手机号(如:13800138000) -4. 点击"发送验证码" -5. 输入任意6位数字(如:123456) -6. 输入密码(如:123456) -7. 点击"确认" - -### 2. 验证测试 -1. 输入空真实姓名 -2. 应该显示"请输入真实姓名"错误 -3. 输入无效手机号(如:123) -4. 应该显示"请输入正确的手机号"错误 -5. 输入短密码(如:123) -6. 应该显示"密码长度不能少于6位"错误 - -### 3. 重复注册测试 -1. 使用已注册的手机号 -2. 应该显示"该手机号已注册,请直接登录"错误 - -## 注意事项 - -1. **真实姓名**: 必须输入真实姓名,用于身份验证 -2. **手机号格式**: 支持中国大陆手机号格式 -3. **验证码长度**: 必须输入6位数字 -4. **密码强度**: 最少6位,建议包含字母和数字 -5. **重复注册**: 已注册手机号不能重复注册 -6. **自动登录**: 注册成功后自动登录并跳转 - -## 扩展功能 - -可以添加的功能: -- 邮箱注册选项 -- 实名认证集成 -- 头像上传 -- 用户协议同意 -- 邀请码注册 -- 第三方注册(微信、QQ等) -- 密码强度检测 -- 图形验证码 - -## 样式特点 - -- **移动优先**: 响应式设计,适配各种屏幕 -- **交互反馈**: 按钮状态、输入框焦点效果 -- **视觉层次**: 清晰的信息层级 -- **品牌一致**: 与整体应用风格保持一致 -- **无障碍**: 支持键盘导航和屏幕阅读器 - -## 页面跳转 - -- **从登录页**: 点击"注册账号"跳转到注册页 -- **从短信登录页**: 点击"注册账号"跳转到注册页 -- **返回上一页**: 点击左上角返回按钮 -- **已有账号**: 点击"已有账号?立即登录"跳转到登录页 diff --git a/mini_program/farm-monitor-dashboard/ROUTER_FIX_README.md b/mini_program/farm-monitor-dashboard/ROUTER_FIX_README.md deleted file mode 100644 index a1afa6b..0000000 --- a/mini_program/farm-monitor-dashboard/ROUTER_FIX_README.md +++ /dev/null @@ -1,107 +0,0 @@ -# 路由守卫修复说明 - -## 问题描述 -出现错误:`Redirected when going from "/password-login" to "/" via a navigation guard.` - -这是由于Vue Router的导航守卫导致的无限重定向循环。 - -## 问题原因 -1. 用户从密码登录页面跳转到首页 -2. 路由守卫检测到用户已登录 -3. 路由守卫重定向到首页 -4. 形成无限循环 - -## 修复方案 - -### 1. 优化路由守卫逻辑 -```javascript -// 如果是从登录页面跳转到首页,且用户已登录,直接允许访问 -if (from.path && isLoginPage && to.path === '/' && isAuthenticated) { - console.log('允许从登录页跳转到首页') - next() - return -} -``` - -### 2. 修复异步token设置 -```javascript -// 确保token设置完成后再跳转 -await auth.setTestToken() -auth.setUserInfo(userInfo) - -// 延迟跳转,确保token设置完成 -setTimeout(() => { - this.$router.push('/') -}, 100) -``` - -### 3. 添加调试日志 -```javascript -console.log('路由守卫:', { - from: from.path, - to: to.path, - requiresAuth, - isLoginPage, - isAuthenticated -}) -``` - -## 修复的文件 - -### 1. `src/router/index.js` -- 添加了特殊处理逻辑,允许从登录页跳转到首页 -- 添加了详细的调试日志 -- 优化了路由守卫的条件判断 - -### 2. `src/components/PasswordLogin.vue` -- 修复了异步token设置问题 -- 添加了延迟跳转机制 - -### 3. `src/components/SmsLogin.vue` -- 修复了异步token设置问题 - -### 4. `src/components/Register.vue` -- 修复了异步token设置问题 -- 添加了延迟跳转机制 - -## 测试方法 - -1. 访问 `http://localhost:8080/password-login` -2. 输入任意账号和密码(如:admin/123456) -3. 点击登录按钮 -4. 应该能正常跳转到首页,不再出现重定向错误 - -## 预期结果 - -- ✅ 登录成功后正常跳转到首页 -- ✅ 不再出现路由重定向错误 -- ✅ 控制台显示详细的路由守卫日志 -- ✅ 所有登录方式都能正常工作 - -## 调试信息 - -在浏览器控制台中可以看到: -``` -路由守卫: { - from: "/password-login", - to: "/", - requiresAuth: true, - isLoginPage: true, - isAuthenticated: true -} -允许从登录页跳转到首页 -``` - -## 注意事项 - -1. 确保所有登录页面都使用 `await auth.setTestToken()` -2. 跳转前添加适当的延迟 -3. 路由守卫的逻辑要避免循环重定向 -4. 添加足够的调试日志帮助排查问题 - -## 如果问题仍然存在 - -1. 清除浏览器缓存和localStorage -2. 检查控制台是否有其他错误 -3. 确认token设置是否成功 -4. 查看路由守卫的详细日志 diff --git a/mini_program/farm-monitor-dashboard/SEARCH_FUNCTIONALITY.md b/mini_program/farm-monitor-dashboard/SEARCH_FUNCTIONALITY.md deleted file mode 100644 index ecd2892..0000000 --- a/mini_program/farm-monitor-dashboard/SEARCH_FUNCTIONALITY.md +++ /dev/null @@ -1,175 +0,0 @@ -# 智能耳标搜索功能说明 - -## 功能概述 - -智能耳标搜索功能提供了精确和模糊两种搜索模式,支持根据耳标编号进行快速查找。 - -## 搜索特性 - -### 1. 精确搜索 -- **触发条件**: 输入完整的耳标编号(如:2105517333) -- **搜索逻辑**: 完全匹配 `cid` 字段 -- **结果**: 返回唯一匹配的设备 - -### 2. 模糊搜索 -- **触发条件**: 输入部分耳标编号或其他字段 -- **搜索字段**: - - `cid` (耳标编号) - - `earTagId` (备用耳标编号) - - `collectedHost` (被采集主机) - - `sid` (备用采集主机) -- **结果**: 返回包含搜索关键词的所有设备 - -## 用户界面 - -### 搜索区域 -``` -┌─────────────────────────────────────┐ -│ 🔍 [搜索框] [+] │ -└─────────────────────────────────────┘ -``` - -### 搜索状态显示 -``` -┌─────────────────────────────────────┐ -│ 搜索中... [清除搜索] │ -└─────────────────────────────────────┘ -``` - -## 技术实现 - -### 1. 搜索状态管理 -```javascript -data() { - return { - searchQuery: '', // 搜索关键词 - isSearching: false, // 是否正在搜索 - searchResults: [], // 搜索结果 - originalDevices: [], // 原始设备数据 - searchTimeout: null // 搜索延迟定时器 - } -} -``` - -### 2. 实时搜索 -```javascript -handleSearchInput() { - // 500ms延迟,避免频繁搜索 - clearTimeout(this.searchTimeout) - this.searchTimeout = setTimeout(() => { - this.performSearch() - }, 500) -} -``` - -### 3. 精确搜索逻辑 -```javascript -// 精确匹配耳标编号 -const exactMatch = this.originalDevices.find(device => - device.cid && device.cid.toString() === searchQuery -) - -if (exactMatch) { - this.searchResults = [exactMatch] - console.log('找到精确匹配的耳标:', exactMatch.cid) -} -``` - -### 4. 模糊搜索逻辑 -```javascript -// 模糊搜索多个字段 -this.searchResults = this.originalDevices.filter(device => - (device.cid && device.cid.toString().includes(searchQuery)) || - (device.earTagId && device.earTagId.includes(searchQuery)) || - (device.collectedHost && device.collectedHost.includes(searchQuery)) || - (device.sid && device.sid.includes(searchQuery)) -) -``` - -## 搜索流程 - -### 1. 用户输入 -- 用户在搜索框中输入关键词 -- 系统检测到输入变化 - -### 2. 延迟搜索 -- 等待500ms,避免频繁搜索 -- 如果用户继续输入,取消之前的搜索 - -### 3. 执行搜索 -- 检查输入是否为空 -- 如果为空,清除搜索状态 -- 如果不为空,执行搜索逻辑 - -### 4. 显示结果 -- 精确匹配:显示单个设备 -- 模糊匹配:显示多个设备 -- 无匹配:显示空列表 - -### 5. 清除搜索 -- 点击"清除搜索"按钮 -- 恢复原始设备列表 -- 重置分页状态 - -## 搜索优化 - -### 1. 性能优化 -- **延迟搜索**: 500ms延迟避免频繁请求 -- **本地搜索**: 基于已加载的数据进行搜索 -- **状态缓存**: 保存原始数据避免重复加载 - -### 2. 用户体验 -- **实时反馈**: 搜索状态实时显示 -- **键盘支持**: 支持Enter键触发搜索 -- **一键清除**: 快速清除搜索状态 - -### 3. 错误处理 -- **空输入处理**: 自动清除搜索状态 -- **异常捕获**: 搜索失败时显示错误信息 -- **状态恢复**: 搜索失败时恢复原始状态 - -## 使用示例 - -### 精确搜索 -1. 在搜索框输入:`2105517333` -2. 系统找到精确匹配的设备 -3. 显示该设备的详细信息 - -### 模糊搜索 -1. 在搜索框输入:`210551` -2. 系统找到所有包含该数字的设备 -3. 显示匹配的设备列表 - -### 清除搜索 -1. 点击"清除搜索"按钮 -2. 恢复显示所有设备 -3. 重置分页到第一页 - -## 技术细节 - -### 数据流 -``` -用户输入 → 延迟处理 → 精确搜索 → 模糊搜索 → 显示结果 - ↓ -清除搜索 ← 恢复原始数据 ← 重置状态 -``` - -### 状态管理 -- `isSearching`: 控制搜索状态显示 -- `searchResults`: 存储搜索结果 -- `originalDevices`: 保存原始数据 -- `searchTimeout`: 管理搜索延迟 - -### 事件处理 -- `@input`: 实时输入处理 -- `@keyup.enter`: 回车键搜索 -- `@click`: 按钮点击事件 - -## 扩展功能 - -### 未来可扩展的搜索功能 -1. **高级搜索**: 支持多条件组合搜索 -2. **搜索历史**: 保存常用搜索关键词 -3. **搜索建议**: 输入时显示搜索建议 -4. **搜索过滤**: 按设备状态、类型等过滤 -5. **搜索统计**: 显示搜索结果统计信息 diff --git a/mini_program/farm-monitor-dashboard/SMART_EARTAG_ALERT_README.md b/mini_program/farm-monitor-dashboard/SMART_EARTAG_ALERT_README.md deleted file mode 100644 index bf77592..0000000 --- a/mini_program/farm-monitor-dashboard/SMART_EARTAG_ALERT_README.md +++ /dev/null @@ -1,141 +0,0 @@ -# 智能耳标预警功能实现说明 - -## 功能概述 - -基于PC端 `SmartEartagAlert.vue` 的分析,在微信小程序端实现了完整的智能耳标预警功能,包括预警展示、筛选、搜索、处理等功能。 - -## 实现文件 - -### 1. 核心组件 -- `src/components/SmartEartagAlert.vue` - 主要预警组件 -- `src/views/SmartEartagAlertPage.vue` - 预警页面包装器 -- `src/components/AlertTest.vue` - 功能测试组件 - -### 2. 服务层 -- `src/services/alertService.js` - 预警相关API服务 - -### 3. 路由配置 -- 在 `src/router/index.js` 中添加了预警页面路由 - -### 4. 导航集成 -- 在 `src/components/Home.vue` 中添加了预警功能入口 - -## 主要功能 - -### 1. 预警展示 -- **统计卡片**: 显示总预警数、严重预警、一般预警、已处理数量 -- **预警列表**: 展示预警详情,包括设备ID、预警内容、级别、状态等 -- **分页功能**: 支持分页浏览大量预警数据 - -### 2. 筛选和搜索 -- **级别筛选**: 按严重、一般、信息级别筛选 -- **状态筛选**: 按未处理、已处理状态筛选 -- **关键词搜索**: 支持按设备ID或预警内容搜索 - -### 3. 预警处理 -- **详情查看**: 点击预警查看详细信息 -- **状态更新**: 支持将预警标记为已处理 -- **批量操作**: 支持批量处理预警(API已准备) - -### 4. 实时功能 -- **自动刷新**: 30秒自动刷新预警数据 -- **手动刷新**: 支持手动刷新数据 -- **刷新控制**: 可开启/关闭自动刷新 - -### 5. 响应式设计 -- **移动端优化**: 针对手机屏幕优化的界面布局 -- **触摸友好**: 适合触摸操作的按钮和交互 - -## 技术特点 - -### 1. 数据管理 -- 使用Vue 2 Options API -- 响应式数据绑定 -- 计算属性优化性能 - -### 2. 状态管理 -- 本地状态管理 -- 筛选状态持久化 -- 分页状态管理 - -### 3. 用户体验 -- 加载状态提示 -- 空数据状态展示 -- 错误处理机制 - -### 4. 样式设计 -- 现代化UI设计 -- 卡片式布局 -- 颜色编码预警级别 -- 响应式布局 - -## API接口设计 - -### 预警管理 -- `GET /smart-eartag-alerts` - 获取预警列表 -- `GET /smart-eartag-alerts/:id` - 获取预警详情 -- `PUT /smart-eartag-alerts/:id/resolve` - 处理预警 -- `DELETE /smart-eartag-alerts/:id` - 删除预警 - -### 批量操作 -- `PUT /smart-eartag-alerts/batch-resolve` - 批量处理预警 - -### 统计分析 -- `GET /smart-eartag-alerts/stats` - 获取预警统计 - -### 设备相关 -- `GET /smart-eartag-alerts/device/:deviceId` - 获取设备预警历史 - -### 规则管理 -- `GET /smart-eartag-alerts/rules` - 获取预警规则 -- `POST /smart-eartag-alerts/rules` - 创建预警规则 -- `PUT /smart-eartag-alerts/rules/:id` - 更新预警规则 -- `DELETE /smart-eartag-alerts/rules/:id` - 删除预警规则 - -## 使用方式 - -### 1. 访问预警页面 -- 在首页点击"智能耳标预警"按钮 -- 或直接访问 `/smart-eartag-alert` 路由 - -### 2. 功能测试 -- 访问 `/alert-test` 路由进行功能测试 -- 测试各种API调用和功能 - -### 3. 预警处理流程 -1. 查看预警列表 -2. 使用筛选和搜索功能 -3. 点击预警查看详情 -4. 处理预警或标记为已处理 - -## 模拟数据 - -当前使用模拟数据进行功能演示,包括: -- 体温异常预警 -- 活动量异常预警 -- 设备离线预警 -- 位置异常预警 - -## 后续优化 - -### 1. API集成 -- 替换模拟数据为真实API调用 -- 添加错误处理和重试机制 -- 优化数据加载性能 - -### 2. 功能增强 -- 添加预警规则配置 -- 实现推送通知 -- 添加数据导出功能 - -### 3. 性能优化 -- 虚拟滚动处理大量数据 -- 缓存机制减少API调用 -- 懒加载优化首屏性能 - -## 注意事项 - -1. 当前使用模拟数据,需要根据实际API调整数据结构 -2. 自动刷新功能默认开启,可根据需要调整刷新间隔 -3. 分页大小可根据实际需求调整 -4. 样式可根据设计规范进一步优化 diff --git a/mini_program/farm-monitor-dashboard/SMS_LOGIN_README.md b/mini_program/farm-monitor-dashboard/SMS_LOGIN_README.md deleted file mode 100644 index f6e4bd0..0000000 --- a/mini_program/farm-monitor-dashboard/SMS_LOGIN_README.md +++ /dev/null @@ -1,139 +0,0 @@ -# 短信登录页面使用说明 - -## 页面地址 -- **短信登录页面**: http://localhost:8080/sms-login -- **普通登录页面**: http://localhost:8080/login -- **首页**: http://localhost:8080/ - -## 功能特点 - -### 🎨 界面设计 -- **简洁美观**: 采用白色背景,绿色主题色 -- **响应式设计**: 适配手机、平板、桌面等不同设备 -- **状态栏**: 显示时间、信号、WiFi、电池状态 -- **返回按钮**: 左上角返回按钮,支持返回上一页 - -### 📱 短信登录功能 -- **账号输入**: 支持手机号或用户名登录 -- **验证码发送**: 60秒倒计时,防止频繁发送 -- **实时验证**: 输入格式实时验证 -- **错误提示**: 详细的错误信息提示 - -### 🔐 安全机制 -- **手机号验证**: 检查手机号是否已注册 -- **验证码验证**: 6位数字验证码验证 -- **倒计时保护**: 防止频繁发送验证码 -- **路由保护**: 未登录用户自动跳转 - -## 使用方法 - -### 1. 访问短信登录页面 -``` -http://localhost:8080/sms-login -``` - -### 2. 登录流程 -1. 输入手机号或账号(支持手机号格式:1[3-9]xxxxxxxxx) -2. 点击"发送验证码"按钮 -3. 等待60秒倒计时结束 -4. 输入收到的6位验证码 -5. 点击"登录"按钮 -6. 登录成功后自动跳转到首页 - -### 3. 其他功能 -- **密码登录**: 点击"密码登录"跳转到普通登录页 -- **注册账号**: 点击"注册账号"(功能开发中) - -## 技术实现 - -### 组件结构 -``` -SmsLogin.vue -├── 状态栏 (status-bar) -├── 头部导航 (header-bar) -├── 主要内容 (main-content) -│ ├── 应用标题 (app-title) -│ ├── 登录表单 (login-form) -│ │ ├── 账号输入框 (input-group) -│ │ └── 验证码输入框 (input-group) -│ └── 其他登录方式 (alternative-login) -``` - -### 核心功能 -- **表单验证**: 实时验证输入格式 -- **倒计时管理**: 60秒发送间隔保护 -- **API集成**: 集成短信服务API -- **状态管理**: 完整的加载和错误状态 - -### 短信服务API -- **发送验证码**: `POST /api/sms/send` -- **验证验证码**: `POST /api/sms/verify` -- **检查手机号**: `GET /api/user/check-phone/{phone}` -- **获取发送记录**: `GET /api/sms/history/{phone}` - -## 开发说明 - -### 模拟功能 -当前使用模拟短信服务,实际项目中需要: -1. 连接真实短信服务商(如阿里云、腾讯云) -2. 实现验证码存储和过期机制 -3. 添加发送频率限制 -4. 集成用户注册检查 - -### 验证码规则 -- **长度**: 6位数字 -- **有效期**: 5分钟 -- **发送间隔**: 60秒 -- **格式验证**: 手机号格式验证 - -### 自定义配置 -可以在 `SmsLogin.vue` 中修改: -- 验证码长度和格式 -- 倒计时时间 -- 错误提示信息 -- 样式和主题 - -## 测试方法 - -### 1. 基本功能测试 -1. 访问 http://localhost:8080/sms-login -2. 输入手机号(如:13800138000) -3. 点击"发送验证码" -4. 输入任意6位数字(如:123456) -5. 点击"登录" - -### 2. 验证测试 -1. 输入无效手机号(如:123) -2. 应该显示格式错误提示 -3. 输入空验证码 -4. 应该显示验证码错误提示 - -### 3. 倒计时测试 -1. 发送验证码后 -2. 按钮应该显示"60s后重发" -3. 倒计时结束后恢复"发送验证码" - -## 注意事项 - -1. **手机号格式**: 支持中国大陆手机号格式 -2. **验证码长度**: 必须输入6位数字 -3. **发送间隔**: 60秒内不能重复发送 -4. **登录状态**: 已登录用户访问会跳转到首页 -5. **错误处理**: 所有错误都有相应的用户提示 - -## 扩展功能 - -可以添加的功能: -- 图形验证码 -- 语音验证码 -- 国际手机号支持 -- 记住手机号 -- 自动填充验证码 -- 生物识别登录 - -## 样式特点 - -- **移动优先**: 响应式设计,适配各种屏幕 -- **交互反馈**: 按钮状态、输入框焦点效果 -- **视觉层次**: 清晰的信息层级 -- **品牌一致**: 与整体应用风格保持一致 diff --git a/mini_program/farm-monitor-dashboard/SYNTAX_ERROR_FIX.md b/mini_program/farm-monitor-dashboard/SYNTAX_ERROR_FIX.md deleted file mode 100644 index 0bd9bbd..0000000 --- a/mini_program/farm-monitor-dashboard/SYNTAX_ERROR_FIX.md +++ /dev/null @@ -1,60 +0,0 @@ -# Vue模板语法错误修复 - -## 问题描述 -编译时出现Vue模板语法错误: -``` -SyntaxError: Unexpected token (1:7333) -``` - -## 问题原因 -Vue 2不支持ES2020的可选链操作符(`?.`),在模板中使用了: -```vue -{{ selectedDevice?.eartagNumber || selectedDevice?.earTagId }} -``` - -## 解决方案 -将可选链操作符替换为Vue 2兼容的语法: - -### 修复前 -```vue -

确定要删除设备 "{{ selectedDevice?.eartagNumber || selectedDevice?.earTagId }}" 吗?

-``` - -### 修复后 -```vue -

确定要删除设备 "{{ (selectedDevice && selectedDevice.eartagNumber) || (selectedDevice && selectedDevice.earTagId) || '未知设备' }}" 吗?

-``` - -## 技术说明 - -### Vue 2兼容性 -- Vue 2使用较旧的JavaScript语法解析器 -- 不支持ES2020的可选链操作符(`?.`) -- 不支持空值合并操作符(`??`) - -### 替代方案 -使用逻辑与操作符(`&&`)进行安全的属性访问: -```javascript -// 不兼容Vue 2 -obj?.prop?.subprop - -// Vue 2兼容 -obj && obj.prop && obj.prop.subprop -``` - -## 验证结果 -- ✅ 语法错误已修复 -- ✅ 前端服务正常启动 -- ✅ 编译成功无错误 -- ✅ 功能正常工作 - -## 预防措施 -1. 在Vue 2项目中避免使用ES2020+语法 -2. 使用Babel转译器处理现代JavaScript语法 -3. 在模板中使用Vue 2兼容的表达式 -4. 定期检查编译错误和警告 - -## 相关文件 -- `src/components/EarTag.vue` - 修复的文件 -- Vue 2.6.14 - 当前使用的Vue版本 -- vue-template-compiler - 模板编译器版本 diff --git a/mini_program/farm-monitor-dashboard/TOKEN_ERROR_FIX.md b/mini_program/farm-monitor-dashboard/TOKEN_ERROR_FIX.md deleted file mode 100644 index 9b6fbee..0000000 --- a/mini_program/farm-monitor-dashboard/TOKEN_ERROR_FIX.md +++ /dev/null @@ -1,141 +0,0 @@ -# Token错误修复说明 - -## 问题描述 -出现错误:`无法通过API获取测试token,使用模拟token: Cannot read properties of undefined (reading 'token')` - -## 问题原因 -1. API响应结构与预期不符 -2. 前端代理可能没有正确工作 -3. 网络连接问题 - -## 修复方案 - -### 1. 修复API响应处理 -```javascript -// 修复前 -if (response.success && response.data.token) { - -// 修复后 -if (response && response.success && response.token) { -``` - -### 2. 添加现有token检查 -```javascript -// 首先检查是否已经有有效的token -const existingToken = this.getToken() -if (existingToken && existingToken.startsWith('eyJ')) { - console.log('使用现有JWT token') - return existingToken -} -``` - -### 3. 添加手动设置真实token的方法 -```javascript -setRealToken() { - const realToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' - this.setToken(realToken) - return realToken -} -``` - -### 4. 增强错误处理 -- 添加详细的日志输出 -- 优雅处理API调用失败 -- 提供备用方案 - -## 使用方法 - -### 方法1:使用认证测试页面 -1. 访问 `http://localhost:8080/auth-test` -2. 点击"设置真实Token"按钮 -3. 点击"测试所有API"按钮 - -### 方法2:手动设置token -在浏览器控制台中执行: -```javascript -// 设置真实token -localStorage.setItem('token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5jb20iLCJpYXQiOjE3NTgxODM3NjEsImV4cCI6MTc1ODI3MDE2MX0.J3DD78bULP1pe5DMF2zbQEMFzeytV6uXgOuDIKOPww0') - -// 设置用户信息 -localStorage.setItem('userInfo', JSON.stringify({ - id: 'user-001', - name: '爱农智慧牧场用户', - account: 'admin', - role: 'user' -})) -``` - -### 方法3:直接访问API获取token -```powershell -$response = Invoke-WebRequest -Uri "http://localhost:5350/api/auth/login" -Method POST -Body '{"username":"admin","password":"123456"}' -ContentType "application/json" -$token = ($response.Content | ConvertFrom-Json).token -Write-Host "Token: $token" -``` - -## 测试步骤 - -1. 清除浏览器缓存和localStorage -2. 访问认证测试页面 -3. 点击"设置真实Token" -4. 点击"测试所有API" -5. 查看测试结果 - -## 预期结果 - -- ✅ 成功设置真实JWT token -- ✅ 所有API调用成功 -- ✅ 获取到真实的设备数据 -- ✅ 不再出现token相关错误 - -## 故障排除 - -### 如果仍然出现错误 -1. 检查后端服务是否运行在 `http://localhost:5350` -2. 检查前端代理配置 -3. 清除浏览器缓存 -4. 使用手动设置token的方法 - -### 如果API调用失败 -1. 检查网络连接 -2. 检查CORS设置 -3. 查看浏览器控制台错误 -4. 使用直接API调用测试 - -## 技术细节 - -### API响应结构 -```json -{ - "success": true, - "message": "登录成功", - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", - "user": { - "id": 1, - "username": "admin", - "email": "admin@example.com" - } -} -``` - -### Token格式 -- JWT token以 `eyJ` 开头 -- 包含用户ID、用户名、邮箱等信息 -- 有效期为24小时 - -### 代理配置 -```javascript -// vue.config.js -proxy: { - '/api': { - target: 'http://localhost:5350', - changeOrigin: true - } -} -``` - -## 下一步 - -1. 修复前端代理问题 -2. 实现token自动刷新 -3. 添加更好的错误处理 -4. 优化用户体验 diff --git a/mini_program/farm-monitor-dashboard/app.js b/mini_program/farm-monitor-dashboard/app.js index debc005..205b885 100644 --- a/mini_program/farm-monitor-dashboard/app.js +++ b/mini_program/farm-monitor-dashboard/app.js @@ -4,7 +4,7 @@ App({ version: '1.0.0', platform: 'wechat', isDevelopment: true, - baseUrl: 'https://your-backend-url.com/api', // 请替换为实际的后端API地址 + baseUrl: 'https://ad.ningmuyun.com', // 请替换为实际的后端API地址 userInfo: null, token: null }, diff --git a/mini_program/farm-monitor-dashboard/app.json b/mini_program/farm-monitor-dashboard/app.json index 85a41a8..cd05e95 100644 --- a/mini_program/farm-monitor-dashboard/app.json +++ b/mini_program/farm-monitor-dashboard/app.json @@ -7,6 +7,7 @@ "pages/cattle/cattle", "pages/device/device", "pages/device/eartag/eartag", + "pages/device/collar/collar", "pages/device/eartag-detail/eartag-detail", "pages/device/eartag-add/eartag-add", "pages/alert/alert" @@ -50,4 +51,4 @@ }, "requiredBackgroundModes": ["location"], "sitemapLocation": "sitemap.json" -} +} \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/auth-test.js b/mini_program/farm-monitor-dashboard/auth-test.js deleted file mode 100644 index ef393db..0000000 --- a/mini_program/farm-monitor-dashboard/auth-test.js +++ /dev/null @@ -1,83 +0,0 @@ -// 认证测试脚本 - 帮助获取正确的认证信息 -const axios = require('axios') - -async function testAuthMethods() { - const baseURL = process.env.VUE_APP_API_BASE_URL || 'http://localhost:5350' - - console.log('🔐 开始测试认证方法...') - console.log('API地址:', baseURL) - - // 测试1: 无认证访问 - console.log('\n1. 测试无认证访问...') - try { - const response = await axios.get(`${baseURL}/api/smart-devices/hosts`, { - params: { page: 1, pageSize: 10 }, - timeout: 10000 - }) - console.log('✅ 无认证访问成功!') - console.log('响应:', response.data) - } catch (error) { - console.log('❌ 无认证访问失败:', error.response?.status, error.response?.data?.message) - } - - // 测试2: 尝试不同的认证头 - const authMethods = [ - { name: 'Bearer Token', header: 'Authorization', value: 'Bearer test-token' }, - { name: 'API Key', header: 'X-API-Key', value: 'test-api-key' }, - { name: 'Basic Auth', header: 'Authorization', value: 'Basic dGVzdDp0ZXN0' }, - { name: 'Custom Token', header: 'X-Auth-Token', value: 'test-token' } - ] - - for (const method of authMethods) { - console.log(`\n2. 测试${method.name}...`) - try { - const response = await axios.get(`${baseURL}/api/smart-devices/hosts`, { - params: { page: 1, pageSize: 10 }, - headers: { [method.header]: method.value }, - timeout: 10000 - }) - console.log(`✅ ${method.name}成功!`) - console.log('响应:', response.data) - break - } catch (error) { - console.log(`❌ ${method.name}失败:`, error.response?.status, error.response?.data?.message) - } - } - - // 测试3: 检查是否有登录接口 - console.log('\n3. 检查登录接口...') - const loginEndpoints = [ - '/api/auth/login', - '/api/login', - '/api/user/login', - '/api/authenticate', - '/login' - ] - - for (const endpoint of loginEndpoints) { - try { - const response = await axios.post(`${baseURL}${endpoint}`, { - username: 'test', - password: 'test' - }, { timeout: 5000 }) - console.log(`✅ 找到登录接口: ${endpoint}`) - console.log('响应:', response.data) - break - } catch (error) { - console.log(`❌ ${endpoint}:`, error.response?.status) - } - } - - console.log('\n💡 建议:') - console.log('1. 检查后端API文档了解正确的认证方式') - console.log('2. 联系后端开发者获取测试用的认证信息') - console.log('3. 检查是否有公开的API端点不需要认证') - console.log('4. 确认API是否需要特定的请求头或参数') -} - -// 运行测试 -if (require.main === module) { - testAuthMethods().catch(console.error) -} - -module.exports = { testAuthMethods } diff --git a/mini_program/farm-monitor-dashboard/auto-login.js b/mini_program/farm-monitor-dashboard/auto-login.js deleted file mode 100644 index 77e3dbb..0000000 --- a/mini_program/farm-monitor-dashboard/auto-login.js +++ /dev/null @@ -1,85 +0,0 @@ -// 自动登录脚本 - 解决认证问题 -const axios = require('axios') - -const API_BASE_URL = process.env.VUE_APP_API_BASE_URL || 'http://localhost:5350' - -async function autoLogin() { - console.log('🔐 开始自动登录解决认证问题...') - console.log('API地址:', API_BASE_URL) - - try { - // 尝试登录 - console.log('\n1. 尝试登录...') - const loginResponse = await axios.post(`${API_BASE_URL}/api/auth/login`, { - username: 'admin', - password: '123456' - }) - - if (loginResponse.data.success) { - const token = loginResponse.data.token - console.log('✅ 登录成功!') - console.log('Token:', token.substring(0, 20) + '...') - console.log('用户:', loginResponse.data.user.username) - console.log('角色:', loginResponse.data.role.name) - - // 测试智能主机API - console.log('\n2. 测试智能主机API...') - const hostResponse = await axios.get(`${API_BASE_URL}/api/smart-devices/hosts`, { - headers: { Authorization: `Bearer ${token}` }, - params: { page: 1, pageSize: 10 } - }) - - if (hostResponse.data.success) { - console.log('✅ 智能主机API成功!') - console.log('主机总数:', hostResponse.data.total) - console.log('当前页数据:', hostResponse.data.data.length, '条') - } - - // 测试智能耳标API - console.log('\n3. 测试智能耳标API...') - const earTagResponse = await axios.get(`${API_BASE_URL}/api/iot-jbq-client`, { - headers: { Authorization: `Bearer ${token}` }, - params: { page: 1, pageSize: 10 } - }) - - if (earTagResponse.data.success) { - console.log('✅ 智能耳标API成功!') - console.log('耳标总数:', earTagResponse.data.pagination.total) - console.log('当前页数据:', earTagResponse.data.data.length, '条') - } - - console.log('\n🎉 认证问题已解决!') - console.log('\n📋 前端设置步骤:') - console.log('1. 打开浏览器开发者工具 (F12)') - console.log('2. 在控制台中执行以下代码:') - console.log(`localStorage.setItem('token', '${token}')`) - console.log('3. 刷新页面') - console.log('\n💡 或者运行以下命令设置token:') - console.log(`node set-token.js`) - - return token - } else { - console.log('❌ 登录失败:', loginResponse.data.message) - } - } catch (error) { - console.error('❌ 自动登录失败:') - if (error.response) { - console.error('状态码:', error.response.status) - console.error('错误信息:', error.response.data) - } else { - console.error('网络错误:', error.message) - } - } -} - -// 运行自动登录 -if (require.main === module) { - autoLogin().then(token => { - if (token) { - console.log('\n✅ 认证问题解决完成!') - console.log('现在前端应该能正常访问所有API了。') - } - }).catch(console.error) -} - -module.exports = { autoLogin } diff --git a/mini_program/farm-monitor-dashboard/check-backend.js b/mini_program/farm-monitor-dashboard/check-backend.js deleted file mode 100644 index adf8e88..0000000 --- a/mini_program/farm-monitor-dashboard/check-backend.js +++ /dev/null @@ -1,47 +0,0 @@ -// 检查后端服务是否运行 -const axios = require('axios'); - -async function checkBackend() { - const baseURL = 'http://localhost:5350/api'; - - console.log('检查后端服务...'); - console.log('基础URL:', baseURL); - - try { - // 测试基础连接 - console.log('\n1. 测试基础连接...'); - const response = await axios.get(`${baseURL}/cattle-type`, { - timeout: 5000 - }); - console.log('✅ 基础连接成功'); - console.log('状态码:', response.status); - console.log('响应数据:', response.data); - - // 测试牛只档案API - console.log('\n2. 测试牛只档案API...'); - const cattleResponse = await axios.get(`${baseURL}/iot-cattle/public`, { - params: { page: 1, pageSize: 5 }, - timeout: 5000 - }); - console.log('✅ 牛只档案API成功'); - console.log('状态码:', cattleResponse.status); - console.log('响应数据:', cattleResponse.data); - - } catch (error) { - console.error('❌ 后端服务检查失败'); - - if (error.code === 'ECONNREFUSED') { - console.error('错误: 无法连接到后端服务'); - console.error('请确保后端服务在 http://localhost:5350 运行'); - console.error('启动命令: cd backend && npm start'); - } else if (error.response) { - console.error('错误: 后端返回错误'); - console.error('状态码:', error.response.status); - console.error('错误信息:', error.response.data); - } else { - console.error('错误:', error.message); - } - } -} - -checkBackend(); diff --git a/mini_program/farm-monitor-dashboard/debug-console.js b/mini_program/farm-monitor-dashboard/debug-console.js deleted file mode 100644 index 817a8f9..0000000 --- a/mini_program/farm-monitor-dashboard/debug-console.js +++ /dev/null @@ -1,70 +0,0 @@ -// 在浏览器控制台中运行此脚本来调试API调用 - -// 1. 测试登录 -async function testLogin() { - try { - const response = await fetch('/api/auth/login', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - username: 'admin', - password: '123456' - }) - }); - - const data = await response.json(); - console.log('登录结果:', data); - - if (data.success) { - localStorage.setItem('token', data.token); - console.log('Token已保存到localStorage'); - return data.token; - } - } catch (error) { - console.error('登录失败:', error); - } -} - -// 2. 测试转栏记录API -async function testTransferRecords() { - const token = localStorage.getItem('token'); - if (!token) { - console.log('请先运行 testLogin() 获取token'); - return; - } - - try { - const response = await fetch('/api/cattle-transfer-records?page=1&pageSize=10', { - method: 'GET', - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - }); - - const data = await response.json(); - console.log('转栏记录结果:', data); - - if (data.success) { - console.log('记录数量:', data.data.list.length); - console.log('第一条记录:', data.data.list[0]); - } - } catch (error) { - console.error('获取转栏记录失败:', error); - } -} - -// 3. 完整测试流程 -async function fullTest() { - console.log('开始完整测试...'); - await testLogin(); - await testTransferRecords(); -} - -// 运行测试 -console.log('调试脚本已加载,请运行以下命令:'); -console.log('1. testLogin() - 测试登录'); -console.log('2. testTransferRecords() - 测试转栏记录'); -console.log('3. fullTest() - 完整测试流程'); diff --git a/mini_program/farm-monitor-dashboard/images/ICON_REQUIREMENTS.md b/mini_program/farm-monitor-dashboard/images/ICON_REQUIREMENTS.md deleted file mode 100644 index 99aefd9..0000000 --- a/mini_program/farm-monitor-dashboard/images/ICON_REQUIREMENTS.md +++ /dev/null @@ -1,50 +0,0 @@ -# 底部导航栏图标要求 - -## 需要的图标文件 - -### 首页图标 -- `home.png` - 首页未选中状态图标 -- `home-active.png` - 首页选中状态图标 - -### 生产管理图标 -- `production.png` - 生产管理未选中状态图标 -- `production-active.png` - 生产管理选中状态图标 - -### 我的图标 -- `profile.png` - 我的未选中状态图标 -- `profile-active.png` - 我的选中状态图标 - -## 图标规格要求 - -- 尺寸:建议 40x40 像素 -- 格式:PNG格式,支持透明背景 -- 颜色: - - 未选中状态:#7A7E83 (灰色) - - 选中状态:#3cc51f (绿色) - -## 图标设计建议 - -### 首页图标 -- 使用房子或仪表板图标 -- 简洁的线条风格 - -### 生产管理图标 -- 使用牛只、工厂或齿轮图标 -- 体现生产管理功能 - -### 我的图标 -- 使用用户头像或人形图标 -- 简洁明了 - -## 临时解决方案 - -如果暂时没有图标文件,可以: -1. 使用微信小程序默认图标 -2. 创建简单的SVG图标并转换为PNG -3. 从图标库下载免费图标 - -## 注意事项 - -- 确保图标在不同设备上显示清晰 -- 保持图标风格一致 -- 测试在不同背景色下的显示效果 diff --git a/mini_program/farm-monitor-dashboard/images/README.md b/mini_program/farm-monitor-dashboard/images/README.md deleted file mode 100644 index 6ccca92..0000000 --- a/mini_program/farm-monitor-dashboard/images/README.md +++ /dev/null @@ -1,57 +0,0 @@ -# 图标文件说明 - -## 当前状态 -由于无法直接创建图片文件,这里提供图标获取和创建的指导。 - -## 需要的图标文件 - -### 底部导航栏图标 -1. **home.png** - 首页未选中状态 -2. **home-active.png** - 首页选中状态 -3. **production.png** - 生产管理未选中状态 -4. **production-active.png** - 生产管理选中状态 -5. **profile.png** - 我的未选中状态 -6. **profile-active.png** - 我的选中状态 - -## 图标规格要求 -- **尺寸**: 40x40 像素 -- **格式**: PNG格式,支持透明背景 -- **颜色**: - - 未选中: #7A7E83 (灰色) - - 选中: #3cc51f (绿色) - -## 获取图标的方法 - -### 方法1: 使用图标库 -- [Iconfont](https://www.iconfont.cn/) - 阿里巴巴矢量图标库 -- [Feather Icons](https://feathericons.com/) - 简洁的线性图标 -- [Heroicons](https://heroicons.com/) - 现代UI图标 - -### 方法2: 使用设计工具 -- Figma -- Sketch -- Adobe Illustrator -- Canva - -### 方法3: 临时解决方案 -在微信开发者工具中,可以暂时使用默认图标或文字替代。 - -## 推荐的图标设计 - -### 首页图标 -- 使用房子🏠或仪表板📊图标 -- 简洁的线条风格 - -### 生产管理图标 -- 使用工厂🏭、齿轮⚙️或牛只🐄图标 -- 体现生产管理功能 - -### 我的图标 -- 使用用户头像👤或人形图标 -- 简洁明了 - -## 注意事项 -- 确保图标在不同设备上显示清晰 -- 保持图标风格一致 -- 测试在不同背景色下的显示效果 -- 考虑无障碍访问需求 \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/mock-api-server.js b/mini_program/farm-monitor-dashboard/mock-api-server.js deleted file mode 100644 index 9b783f9..0000000 --- a/mini_program/farm-monitor-dashboard/mock-api-server.js +++ /dev/null @@ -1,95 +0,0 @@ -// 模拟API服务器 - 用于测试前端显示 -const express = require('express') -const cors = require('cors') - -const app = express() -const PORT = 5351 // 使用不同端口避免冲突 - -app.use(cors()) -app.use(express.json()) - -// 模拟371台主机数据 -const generateMockHosts = (page = 1, pageSize = 10) => { - const totalHosts = 371 - const startIndex = (page - 1) * pageSize - const endIndex = Math.min(startIndex + pageSize, totalHosts) - - const hosts = [] - for (let i = startIndex; i < endIndex; i++) { - const hostId = `2490246${String(426 + i).padStart(3, '0')}` - hosts.push({ - hostId: hostId, - sid: hostId, - isOnline: Math.random() > 0.3, // 70% 在线概率 - battery: Math.floor(Math.random() * 40) + 60, // 60-100% - voltage: Math.floor(Math.random() * 40) + 60, - signal: Math.floor(Math.random() * 50) + 10, // 10-60% - signa: Math.floor(Math.random() * 50) + 10, - temperature: (Math.random() * 10 + 20).toFixed(1), // 20-30°C - state: Math.random() > 0.2 ? 1 : 0, // 80% 连接状态 - bandge_status: Math.random() > 0.2 ? 1 : 0, - updateTime: new Date(Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1000).toLocaleString('zh-CN', { - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit' - }).replace(/\//g, '-'), - lastUpdateTime: new Date(Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1000).toLocaleString('zh-CN', { - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit' - }).replace(/\//g, '-') - }) - } - - return { - success: true, - data: hosts, - total: totalHosts, - page: page, - pageSize: pageSize, - totalPages: Math.ceil(totalHosts / pageSize), - message: '获取智能主机列表成功' - } -} - -// API路由 -app.get('/api/smart-devices/hosts', (req, res) => { - const page = parseInt(req.query.page) || 1 - const pageSize = parseInt(req.query.pageSize) || 10 - const search = req.query.search || '' - - console.log(`📡 API请求: page=${page}, pageSize=${pageSize}, search=${search}`) - - let response = generateMockHosts(page, pageSize) - - // 如果有搜索条件,过滤数据 - if (search) { - response.data = response.data.filter(host => - host.hostId.includes(search) || host.sid.includes(search) - ) - response.total = response.data.length - response.totalPages = Math.ceil(response.total / pageSize) - } - - console.log(`📊 返回数据: ${response.data.length}条,总数: ${response.total}`) - - res.json(response) -}) - -// 启动服务器 -app.listen(PORT, () => { - console.log(`🚀 模拟API服务器启动成功!`) - console.log(`📍 地址: http://localhost:${PORT}`) - console.log(`🔗 API端点: http://localhost:${PORT}/api/smart-devices/hosts`) - console.log(`📊 模拟数据: 371台主机`) - console.log(`\n💡 测试命令:`) - console.log(`curl "http://localhost:${PORT}/api/smart-devices/hosts?page=1&pageSize=10"`) -}) - -module.exports = app diff --git a/mini_program/farm-monitor-dashboard/package-lock.json b/mini_program/farm-monitor-dashboard/package-lock.json deleted file mode 100644 index 45a3a7e..0000000 --- a/mini_program/farm-monitor-dashboard/package-lock.json +++ /dev/null @@ -1,16997 +0,0 @@ -{ - "name": "farm-mini-program", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "farm-mini-program", - "version": "1.0.0", - "dependencies": { - "@dcloudio/uni-app": "^2.0.2-alpha-4080120250905001", - "@vue/composition-api": "^1.4.0", - "axios": "^0.27.2", - "cors": "^2.8.5", - "dayjs": "^1.11.0", - "express": "^5.1.0", - "pinia": "^2.1.6", - "vue": "^2.6.14", - "vue-router": "^3.6.5", - "vue-template-compiler": "^2.6.14" - }, - "devDependencies": { - "@dcloudio/uni-cli-shared": "^2.0.2-alpha-4080120250905001", - "@dcloudio/uni-h5": "^2.0.2-alpha-4080120250905001", - "@dcloudio/uni-mp-weixin": "^2.0.2-alpha-4080120250905001", - "@vant/weapp": "^1.11.7", - "@vue/cli-service": "^5.0.8", - "cross-env": "^7.0.3", - "eslint": "^8.45.0", - "eslint-plugin-vue": "^9.15.0", - "sass": "^1.92.1", - "sass-loader": "^16.0.5", - "typescript": "^5.1.0" - }, - "engines": { - "node": "16.20.2", - "npm": ">=8.0.0" - } - }, - "node_modules/@achrinza/node-ipc": { - "version": "9.2.9", - "resolved": "https://registry.npmmirror.com/@achrinza/node-ipc/-/node-ipc-9.2.9.tgz", - "integrity": "sha512-7s0VcTwiK/0tNOVdSX9FWMeFdOEcsAOz9HesBldXxFMaGvIak7KC2z9tV9EgsQXn6KUsWsfIkViMNuIo0GoZDQ==", - "dev": true, - "dependencies": { - "@node-ipc/js-queue": "2.0.3", - "event-pubsub": "4.3.0", - "js-message": "1.0.7" - }, - "engines": { - "node": "8 || 9 || 10 || 11 || 12 || 13 || 14 || 15 || 16 || 17 || 18 || 19 || 20 || 21 || 22" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.25.9", - "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.25.9.tgz", - "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@dcloudio/types": { - "version": "3.4.21", - "resolved": "https://registry.npmmirror.com/@dcloudio/types/-/types-3.4.21.tgz", - "integrity": "sha512-rsv3XfAaD/dtuVboPeYh+vPcULnWyozGaGKHWyN0dYRm7L1uypFUM30qNYMj9iNmbAENuBjV177S1gNEBIvdDA==", - "peer": true - }, - "node_modules/@dcloudio/uni-app": { - "version": "2.0.2-alpha-4080120250905001", - "resolved": "https://registry.npmmirror.com/@dcloudio/uni-app/-/uni-app-2.0.2-alpha-4080120250905001.tgz", - "integrity": "sha512-h9Og8v85U3hOBh5FCbnmmGPzX8OTJssJvQxZzi01J6lbWrqxnuP/DS+8zFb+A2mGgpzzeK/KHv9i4mUsVNv4TA==", - "peerDependencies": { - "@dcloudio/types": "^3.0.15", - "@vue/composition-api": "^1.7.0" - } - }, - "node_modules/@dcloudio/uni-cli-shared": { - "version": "2.0.2-alpha-4080120250905001", - "resolved": "https://registry.npmmirror.com/@dcloudio/uni-cli-shared/-/uni-cli-shared-2.0.2-alpha-4080120250905001.tgz", - "integrity": "sha512-+zHK6mxN+2PcVUk7SJkrY6mXO0pk65ghJgYEoElF3UT4M0TPRe+bc3tFhTn7hGSYxP1JYx8I0RoxkIeTMDK0xA==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^4.0.0", - "fast-glob": "^3.2.11", - "fs-extra": "^10.0.0", - "glob-escape": "^0.0.2", - "hash-sum": "^1.0.2", - "postcss-urlrewrite": "^0.2.2", - "strip-json-comments": "^2.0.1" - } - }, - "node_modules/@dcloudio/uni-cli-shared/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@dcloudio/uni-cli-shared/node_modules/hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", - "dev": true - }, - "node_modules/@dcloudio/uni-cli-shared/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@dcloudio/uni-h5": { - "version": "2.0.2-alpha-4080120250905001", - "resolved": "https://registry.npmmirror.com/@dcloudio/uni-h5/-/uni-h5-2.0.2-alpha-4080120250905001.tgz", - "integrity": "sha512-hQ1ONQm+8ZKnc6FRbRT9xWGwH4ed0KqVIgvwduG7bVnvcvhxIuFhPUthMCYyvQaVjdp0yjBiUicVEwomWSsZRw==", - "dev": true, - "dependencies": { - "base64-arraybuffer": "^0.2.0", - "intersection-observer": "^0.7.0", - "pako": "^1.0.11", - "postcss-urlrewrite": "^0.3.0", - "safe-area-insets": "^1.4.1" - } - }, - "node_modules/@dcloudio/uni-h5/node_modules/postcss-urlrewrite": { - "version": "0.3.0", - "resolved": "https://registry.npmmirror.com/postcss-urlrewrite/-/postcss-urlrewrite-0.3.0.tgz", - "integrity": "sha512-504S/dMa7a0n1yghE2I6fxY/DfMUM+w9qsFaoYnXE8KsCofmKLlA7PKbR+wtdEJ0N00Z1lGYxX/oFz13xArcLQ==", - "dev": true, - "dependencies": { - "postcss-helpers": "^0.3.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@dcloudio/uni-mp-weixin": { - "version": "2.0.2-alpha-4080120250905001", - "resolved": "https://registry.npmmirror.com/@dcloudio/uni-mp-weixin/-/uni-mp-weixin-2.0.2-alpha-4080120250905001.tgz", - "integrity": "sha512-tyEt9RLhG39EBH+sgGPUJmBbJDwMcnv46CLzPChDLDVdunupqjHB42MmzUY8yrDNeZuD4MB02NAI3oLUrsSw0w==", - "dev": true - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmmirror.com/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@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==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", - "dev": true - }, - "node_modules/@node-ipc/js-queue": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/@node-ipc/js-queue/-/js-queue-2.0.3.tgz", - "integrity": "sha512-fL1wpr8hhD5gT2dA1qifeVaoDFlQR5es8tFuKqjHX+kdOtdNHnxkVZbtIrR2rxnMFvehkjaZRNV2H/gPXlb0hw==", - "dev": true, - "dependencies": { - "easy-stack": "1.0.1" - }, - "engines": { - "node": ">=1.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@parcel/watcher": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.1.tgz", - "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "detect-libc": "^1.0.3", - "is-glob": "^4.0.3", - "micromatch": "^4.0.5", - "node-addon-api": "^7.0.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.1", - "@parcel/watcher-darwin-arm64": "2.5.1", - "@parcel/watcher-darwin-x64": "2.5.1", - "@parcel/watcher-freebsd-x64": "2.5.1", - "@parcel/watcher-linux-arm-glibc": "2.5.1", - "@parcel/watcher-linux-arm-musl": "2.5.1", - "@parcel/watcher-linux-arm64-glibc": "2.5.1", - "@parcel/watcher-linux-arm64-musl": "2.5.1", - "@parcel/watcher-linux-x64-glibc": "2.5.1", - "@parcel/watcher-linux-x64-musl": "2.5.1", - "@parcel/watcher-win32-arm64": "2.5.1", - "@parcel/watcher-win32-ia32": "2.5.1", - "@parcel/watcher-win32-x64": "2.5.1" - } - }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", - "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", - "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", - "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", - "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", - "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", - "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", - "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", - "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", - "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", - "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", - "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", - "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", - "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.29", - "resolved": "https://registry.npmmirror.com/@polka/url/-/url-1.0.0-next.29.tgz", - "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", - "dev": true - }, - "node_modules/@sideway/address": { - "version": "4.1.5", - "resolved": "https://registry.npmmirror.com/@sideway/address/-/address-4.1.5.tgz", - "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "node_modules/@soda/friendly-errors-webpack-plugin": { - "version": "1.8.1", - "resolved": "https://registry.npmmirror.com/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz", - "integrity": "sha512-h2ooWqP8XuFqTXT+NyAFbrArzfQA7R6HTezADrvD9Re8fxMLTPPniLdqVTdDaO0eIoLaAwKT+d6w+5GeTk7Vbg==", - "dev": true, - "dependencies": { - "chalk": "^3.0.0", - "error-stack-parser": "^2.0.6", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@soda/get-current-script": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/@soda/get-current-script/-/get-current-script-1.0.2.tgz", - "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==", - "dev": true - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.6", - "resolved": "https://registry.npmmirror.com/@types/body-parser/-/body-parser-1.19.6.tgz", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmmirror.com/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmmirror.com/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmmirror.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", - "dev": true, - "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@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/express": { - "version": "4.17.23", - "resolved": "https://registry.npmmirror.com/@types/express/-/express-4.17.23.tgz", - "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "5.0.7", - "resolved": "https://registry.npmmirror.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", - "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/express/node_modules/@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmmirror.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "node_modules/@types/http-errors": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", - "dev": true - }, - "node_modules/@types/http-proxy": { - "version": "1.17.16", - "resolved": "https://registry.npmmirror.com/@types/http-proxy/-/http-proxy-1.17.16.tgz", - "integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmmirror.com/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true - }, - "node_modules/@types/node": { - "version": "24.5.1", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-24.5.1.tgz", - "integrity": "sha512-/SQdmUP2xa+1rdx7VwB9yPq8PaKej8TD5cQ+XfKDPWWC+VDJU4rvVVagXqKUzhKjtFoNA8rXDJAkCxQPAe00+Q==", - "dev": true, - "dependencies": { - "undici-types": "~7.12.0" - } - }, - "node_modules/@types/node-forge": { - "version": "1.3.14", - "resolved": "https://registry.npmmirror.com/@types/node-forge/-/node-forge-1.3.14.tgz", - "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmmirror.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true - }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmmirror.com/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmmirror.com/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmmirror.com/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true - }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmmirror.com/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true - }, - "node_modules/@types/send": { - "version": "0.17.5", - "resolved": "https://registry.npmmirror.com/@types/send/-/send-0.17.5.tgz", - "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", - "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmmirror.com/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", - "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.8", - "resolved": "https://registry.npmmirror.com/@types/serve-static/-/serve-static-1.15.8.tgz", - "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", - "dev": true, - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "node_modules/@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmmirror.com/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "dev": true - }, - "node_modules/@vant/weapp": { - "version": "1.11.7", - "resolved": "https://registry.npmmirror.com/@vant/weapp/-/weapp-1.11.7.tgz", - "integrity": "sha512-Rwn9BBnb4kHSV4XmvBicwtd42J+amEUfnFDcXJsGNPNX4a9c/DoT6YLsm4X1wB2+sQbdiQsbFBLAvGRBxCkD8g==", - "dev": true - }, - "node_modules/@vue/cli-overlay": { - "version": "5.0.9", - "resolved": "https://registry.npmmirror.com/@vue/cli-overlay/-/cli-overlay-5.0.9.tgz", - "integrity": "sha512-aBdZWrYKxLuFz1FDsk/muFD7GycrsW73Gi11yRc7R2W7Bm8mDRc9HKAI790gdg4NV+chkDFmfkegjg5iMDEpAA==", - "dev": true - }, - "node_modules/@vue/cli-plugin-router": { - "version": "5.0.9", - "resolved": "https://registry.npmmirror.com/@vue/cli-plugin-router/-/cli-plugin-router-5.0.9.tgz", - "integrity": "sha512-kopbO/8kIl5CAffwgptXEwV509i+M0FfwW4sSkgQ2RzpxOYBjQZvp+096mjZfFcWKSmryNP/ri/Mnu78vmhlhw==", - "dev": true, - "dependencies": { - "@vue/cli-shared-utils": "^5.0.9" - }, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0" - } - }, - "node_modules/@vue/cli-plugin-vuex": { - "version": "5.0.9", - "resolved": "https://registry.npmmirror.com/@vue/cli-plugin-vuex/-/cli-plugin-vuex-5.0.9.tgz", - "integrity": "sha512-AQhgGNFVd4Pu2crvS0a+hRckgrJv07gzOASdbLd3I72wkT43dd01MLRp8IBRRsu92t3MXenW86AZUCbQBz3//A==", - "dev": true, - "peerDependencies": { - "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0" - } - }, - "node_modules/@vue/cli-service": { - "version": "5.0.8", - "resolved": "https://registry.npmmirror.com/@vue/cli-service/-/cli-service-5.0.8.tgz", - "integrity": "sha512-nV7tYQLe7YsTtzFrfOMIHc5N2hp5lHG2rpYr0aNja9rNljdgcPZLyQRb2YRivTHqTv7lI962UXFURcpStHgyFw==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.12.16", - "@soda/friendly-errors-webpack-plugin": "^1.8.0", - "@soda/get-current-script": "^1.0.2", - "@types/minimist": "^1.2.0", - "@vue/cli-overlay": "^5.0.8", - "@vue/cli-plugin-router": "^5.0.8", - "@vue/cli-plugin-vuex": "^5.0.8", - "@vue/cli-shared-utils": "^5.0.8", - "@vue/component-compiler-utils": "^3.3.0", - "@vue/vue-loader-v15": "npm:vue-loader@^15.9.7", - "@vue/web-component-wrapper": "^1.3.0", - "acorn": "^8.0.5", - "acorn-walk": "^8.0.2", - "address": "^1.1.2", - "autoprefixer": "^10.2.4", - "browserslist": "^4.16.3", - "case-sensitive-paths-webpack-plugin": "^2.3.0", - "cli-highlight": "^2.1.10", - "clipboardy": "^2.3.0", - "cliui": "^7.0.4", - "copy-webpack-plugin": "^9.0.1", - "css-loader": "^6.5.0", - "css-minimizer-webpack-plugin": "^3.0.2", - "cssnano": "^5.0.0", - "debug": "^4.1.1", - "default-gateway": "^6.0.3", - "dotenv": "^10.0.0", - "dotenv-expand": "^5.1.0", - "fs-extra": "^9.1.0", - "globby": "^11.0.2", - "hash-sum": "^2.0.0", - "html-webpack-plugin": "^5.1.0", - "is-file-esm": "^1.0.0", - "launch-editor-middleware": "^2.2.1", - "lodash.defaultsdeep": "^4.6.1", - "lodash.mapvalues": "^4.6.0", - "mini-css-extract-plugin": "^2.5.3", - "minimist": "^1.2.5", - "module-alias": "^2.2.2", - "portfinder": "^1.0.26", - "postcss": "^8.2.6", - "postcss-loader": "^6.1.1", - "progress-webpack-plugin": "^1.0.12", - "ssri": "^8.0.1", - "terser-webpack-plugin": "^5.1.1", - "thread-loader": "^3.0.0", - "vue-loader": "^17.0.0", - "vue-style-loader": "^4.1.3", - "webpack": "^5.54.0", - "webpack-bundle-analyzer": "^4.4.0", - "webpack-chain": "^6.5.1", - "webpack-dev-server": "^4.7.3", - "webpack-merge": "^5.7.3", - "webpack-virtual-modules": "^0.4.2", - "whatwg-fetch": "^3.6.2" - }, - "bin": { - "vue-cli-service": "bin/vue-cli-service.js" - }, - "engines": { - "node": "^12.0.0 || >= 14.0.0" - }, - "peerDependencies": { - "vue-template-compiler": "^2.0.0", - "webpack-sources": "*" - }, - "peerDependenciesMeta": { - "cache-loader": { - "optional": true - }, - "less-loader": { - "optional": true - }, - "pug-plain-loader": { - "optional": true - }, - "raw-loader": { - "optional": true - }, - "sass-loader": { - "optional": true - }, - "stylus-loader": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - }, - "webpack-sources": { - "optional": true - } - } - }, - "node_modules/@vue/cli-service/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@vue/cli-shared-utils": { - "version": "5.0.9", - "resolved": "https://registry.npmmirror.com/@vue/cli-shared-utils/-/cli-shared-utils-5.0.9.tgz", - "integrity": "sha512-lf4KykiG8j9KwvNVi7fKtASmHuLsxCcCsflVU2b2CHMRuR4weOIV3zuuCrjWKjk0APn/MHJhgCjJGzHMbTtd5w==", - "dev": true, - "dependencies": { - "@achrinza/node-ipc": "^9.2.5", - "chalk": "^4.1.2", - "execa": "^1.0.0", - "joi": "^17.4.0", - "launch-editor": "^2.2.1", - "lru-cache": "^6.0.0", - "node-fetch": "^2.6.7", - "open": "^8.0.2", - "ora": "^5.3.0", - "read-pkg": "^5.1.1", - "semver": "^7.3.4", - "strip-ansi": "^6.0.0" - } - }, - "node_modules/@vue/cli-shared-utils/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@vue/cli-shared-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@vue/cli-shared-utils/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@vue/cli-shared-utils/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@vue/cli-shared-utils/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@vue/cli-shared-utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@vue/cli-shared-utils/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@vue/cli-shared-utils/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@vue/cli-shared-utils/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@vue/component-compiler-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmmirror.com/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", - "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==", - "dev": true, - "dependencies": { - "consolidate": "^0.15.1", - "hash-sum": "^1.0.2", - "lru-cache": "^4.1.2", - "merge-source-map": "^1.1.0", - "postcss": "^7.0.36", - "postcss-selector-parser": "^6.0.2", - "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.9.0" - }, - "optionalDependencies": { - "prettier": "^1.18.2 || ^2.0.0" - } - }, - "node_modules/@vue/component-compiler-utils/node_modules/hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", - "dev": true - }, - "node_modules/@vue/component-compiler-utils/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/@vue/component-compiler-utils/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/@vue/component-compiler-utils/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/@vue/component-compiler-utils/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - }, - "node_modules/@vue/composition-api": { - "version": "1.7.2", - "resolved": "https://registry.npmmirror.com/@vue/composition-api/-/composition-api-1.7.2.tgz", - "integrity": "sha512-M8jm9J/laYrYT02665HkZ5l2fWTK4dcVg3BsDHm/pfz+MjDYwX+9FUaZyGwEyXEDonQYRCo0H7aLgdklcIELjw==", - "peerDependencies": { - "vue": ">= 2.5 < 2.7" - } - }, - "node_modules/@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/vue-loader-v15": { - "name": "vue-loader", - "version": "15.11.1", - "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-15.11.1.tgz", - "integrity": "sha512-0iw4VchYLePqJfJu9s62ACWUXeSqM30SQqlIftbYWM3C+jpPcEHKSPUZBLjSF9au4HTHQ/naF6OGnO3Q/qGR3Q==", - "dev": true, - "dependencies": { - "@vue/component-compiler-utils": "^3.1.0", - "hash-sum": "^1.0.2", - "loader-utils": "^1.1.0", - "vue-hot-reload-api": "^2.3.0", - "vue-style-loader": "^4.1.0" - }, - "peerDependencies": { - "css-loader": "*", - "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0" - }, - "peerDependenciesMeta": { - "cache-loader": { - "optional": true - }, - "prettier": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/@vue/vue-loader-v15/node_modules/hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", - "dev": true - }, - "node_modules/@vue/web-component-wrapper": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz", - "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==", - "dev": true - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/accepts/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "acorn": "^8.14.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmmirror.com/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmmirror.com/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmmirror.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmmirror.com/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmmirror.com/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-arraybuffer": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", - "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/baseline-browser-mapping": { - "version": "2.8.4", - "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.4.tgz", - "integrity": "sha512-L+YvJwGAgwJBV1p6ffpSTa2KRc69EeeYGYjRVWKs0GKrK+LON0GC0gV+rKSNtALEDvMDqkvCFq9r1r94/Gjwxw==", - "dev": true, - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmmirror.com/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmmirror.com/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", - "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/bonjour-service": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/bonjour-service/-/bonjour-service-1.3.0.tgz", - "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.26.2", - "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.26.2.tgz", - "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "baseline-browser-mapping": "^2.8.3", - "caniuse-lite": "^1.0.30001741", - "electron-to-chromium": "^1.5.218", - "node-releases": "^2.0.21", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/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": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001743", - "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz", - "integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmmirror.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmmirror.com/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dev": true, - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmmirror.com/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - }, - "bin": { - "highlight": "bin/highlight" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" - } - }, - "node_modules/cli-highlight/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cli-highlight/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cli-highlight/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/cli-highlight/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/cli-highlight/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-highlight/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clipboardy": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/clipboardy/-/clipboardy-2.3.0.tgz", - "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", - "dev": true, - "dependencies": { - "arch": "^2.1.1", - "execa": "^1.0.0", - "is-wsl": "^2.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmmirror.com/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/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": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmmirror.com/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.8.1", - "resolved": "https://registry.npmmirror.com/compression/-/compression-1.8.1.tgz", - "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "compressible": "~2.0.18", - "debug": "2.6.9", - "negotiator": "~0.6.4", - "on-headers": "~1.1.0", - "safe-buffer": "5.2.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/consolidate": { - "version": "0.15.1", - "resolved": "https://registry.npmmirror.com/consolidate/-/consolidate-0.15.1.tgz", - "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", - "deprecated": "Please upgrade to consolidate v1.0.0+ as it has been modernized with several long-awaited fixes implemented. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/consolidate for updates and release changelog", - "dev": true, - "dependencies": { - "bluebird": "^3.1.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmmirror.com/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/copy-webpack-plugin": { - "version": "9.1.0", - "resolved": "https://registry.npmmirror.com/copy-webpack-plugin/-/copy-webpack-plugin-9.1.0.tgz", - "integrity": "sha512-rxnR7PaGigJzhqETHGmAcxKnLZSR5u1Y3/bcIv/1FnqXedcL/E2ewK7ZCNrArJKCiSv8yVXhTqetJh8inDvfsA==", - "dev": true, - "dependencies": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^11.0.3", - "normalize-path": "^3.0.0", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmmirror.com/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmmirror.com/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-declaration-sorter": { - "version": "6.4.1", - "resolved": "https://registry.npmmirror.com/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", - "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, - "node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmmirror.com/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/css-loader/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/css-minimizer-webpack-plugin": { - "version": "3.4.1", - "resolved": "https://registry.npmmirror.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", - "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", - "dev": true, - "dependencies": { - "cssnano": "^5.0.6", - "jest-worker": "^27.0.2", - "postcss": "^8.3.5", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@parcel/css": { - "optional": true - }, - "clean-css": { - "optional": true - }, - "csso": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, - "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/css-minimizer-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssnano": { - "version": "5.1.15", - "resolved": "https://registry.npmmirror.com/cssnano/-/cssnano-5.1.15.tgz", - "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", - "dev": true, - "dependencies": { - "cssnano-preset-default": "^5.2.14", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-preset-default": { - "version": "5.2.14", - "resolved": "https://registry.npmmirror.com/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", - "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", - "dev": true, - "dependencies": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.1", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.4", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.2", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/dayjs": { - "version": "1.11.0", - "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.0.tgz", - "integrity": "sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug==" - }, - "node_modules/de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==" - }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", - "dev": true - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "1.5.2", - "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-1.5.2.tgz", - "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmmirror.com/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/default-gateway/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/default-gateway/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true, - "optional": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmmirror.com/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true - }, - "node_modules/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": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmmirror.com/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/easy-stack": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/easy-stack/-/easy-stack-1.0.1.tgz", - "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.220", - "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.220.tgz", - "integrity": "sha512-TWXijEwR1ggr4BdAKrb1nMNqYLTx1/4aD1fkeZU+FVJGTKu53/T7UyHKXlqEX3Ub02csyHePbHmkvnrjcaYzMA==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/error-stack-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmmirror.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz", - "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", - "dev": true, - "dependencies": { - "stackframe": "^1.3.4" - } - }, - "node_modules/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==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true - }, - "node_modules/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": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/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": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmmirror.com/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-vue": { - "version": "9.33.0", - "resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz", - "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "globals": "^13.24.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.1.1", - "postcss-selector-parser": "^6.0.15", - "semver": "^7.6.3", - "vue-eslint-parser": "^9.4.3", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-vue/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmmirror.com/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-pubsub": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/event-pubsub/-/event-pubsub-4.3.0.tgz", - "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/execa/node_modules/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/execa/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/execa/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/execa/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmmirror.com/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/express": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.0", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express/node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ] - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmmirror.com/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/figures": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/figures/-/figures-2.0.0.tgz", - "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmmirror.com/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs-monkey": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/fs-monkey/-/fs-monkey-1.1.0.tgz", - "integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "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, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/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": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/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": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-escape": { - "version": "0.0.2", - "resolved": "https://registry.npmmirror.com/glob-escape/-/glob-escape-0.0.2.tgz", - "integrity": "sha512-L/cXYz8x7qer1HAyUQ+mbjcUsJVdpRxpAf7CwqHoNBs9vTpABlGfNN4tzkDxt+u3Z7ZncVyKlCNPtzb0R/7WbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmmirror.com/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmmirror.com/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/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": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hash-sum": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-2.0.0.tgz", - "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", - "dev": true - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmmirror.com/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/hpack.js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/html-entities": { - "version": "2.6.0", - "resolved": "https://registry.npmmirror.com/html-entities/-/html-entities-2.6.0.tgz", - "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ] - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-webpack-plugin": { - "version": "5.6.4", - "resolved": "https://registry.npmmirror.com/html-webpack-plugin/-/html-webpack-plugin-5.6.4.tgz", - "integrity": "sha512-V/PZeWsqhfpE27nKeX9EO2sbR+D17A+tLf6qU+ht66jdUsN0QLKJN27Z+1+gHrVMKgndBahes0PU6rRihDgHTw==", - "dev": true, - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.20.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmmirror.com/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.10", - "resolved": "https://registry.npmmirror.com/http-parser-js/-/http-parser-js-0.5.10.tgz", - "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmmirror.com/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.9", - "resolved": "https://registry.npmmirror.com/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", - "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", - "dev": true, - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/immutable": { - "version": "5.1.3", - "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.3.tgz", - "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", - "dev": true - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/intersection-observer": { - "version": "0.7.0", - "resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.7.0.tgz", - "integrity": "sha512-Id0Fij0HsB/vKWGeBe9PxeY45ttRiBmhFyyt/geBdDHBYNctMRTE3dC1U3ujzz3lap+hVXlEcVaB56kZP/eEUg==", - "dev": true - }, - "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-file-esm": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/is-file-esm/-/is-file-esm-1.0.0.tgz", - "integrity": "sha512-rZlaNKb4Mr8WlRu2A9XdeoKgnO5aA53XdPHgCKVyCrQ/rWi89RET1+bq37Ru46obaQXeiX4vmFIm1vks41hoSA==", - "dev": true, - "dependencies": { - "read-pkg-up": "^7.0.1" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/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, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/javascript-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/javascript-stringify/-/javascript-stringify-2.1.0.tgz", - "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", - "dev": true - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/joi": { - "version": "17.13.3", - "resolved": "https://registry.npmmirror.com/joi/-/joi-17.13.3.tgz", - "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.3.0", - "@hapi/topo": "^5.1.0", - "@sideway/address": "^4.1.5", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, - "node_modules/js-message": { - "version": "1.0.7", - "resolved": "https://registry.npmmirror.com/js-message/-/js-message-1.0.7.tgz", - "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", - "dev": true, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/klona": { - "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/launch-editor": { - "version": "2.11.1", - "resolved": "https://registry.npmmirror.com/launch-editor/-/launch-editor-2.11.1.tgz", - "integrity": "sha512-SEET7oNfgSaB6Ym0jufAdCeo3meJVeCaaDyzRygy0xsp2BFKCprcfHljTq4QkzTLUxEKkFK6OK4811YM2oSrRg==", - "dev": true, - "dependencies": { - "picocolors": "^1.1.1", - "shell-quote": "^1.8.3" - } - }, - "node_modules/launch-editor-middleware": { - "version": "2.11.1", - "resolved": "https://registry.npmmirror.com/launch-editor-middleware/-/launch-editor-middleware-2.11.1.tgz", - "integrity": "sha512-6xpn4pJz5mDg2kUH7L6gK5BuZcZPdVwoSs/DhfebefwLyszNXqFFjksGup/w4CTRzzrr8FSEufDzb/gKFLle6w==", - "dev": true, - "dependencies": { - "launch-editor": "^2.11.1" - } - }, - "node_modules/launch-editor/node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/loader-utils/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.defaultsdeep": { - "version": "4.6.1", - "resolved": "https://registry.npmmirror.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", - "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==", - "dev": true - }, - "node_modules/lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmmirror.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==", - "dev": true - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmmirror.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", - "dev": true, - "dependencies": { - "restore-cursor": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", - "dev": true, - "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==", - "dev": true, - "dependencies": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmmirror.com/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, - "dependencies": { - "fs-monkey": "^1.0.4" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/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": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mini-css-extract-plugin": { - "version": "2.9.4", - "resolved": "https://registry.npmmirror.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.4.tgz", - "integrity": "sha512-ZWYT7ln73Hptxqxk2DxPU9MmapXRhxkJD6tkSR04dnQxm8BGu2hzgKLugK5yySD97u/8yy7Ma7E76k9ZdvtjkQ==", - "dev": true, - "dependencies": { - "schema-utils": "^4.0.0", - "tapable": "^2.2.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/module-alias": { - "version": "2.2.3", - "resolved": "https://registry.npmmirror.com/module-alias/-/module-alias-2.2.3.tgz", - "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==", - "dev": true - }, - "node_modules/mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/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/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmmirror.com/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/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/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmmirror.com/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-releases": { - "version": "2.0.21", - "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.21.tgz", - "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", - "dev": true - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/on-headers/-/on-headers-1.1.0.tgz", - "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmmirror.com/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmmirror.com/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ora/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ora/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmmirror.com/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dev": true, - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-json/node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", - "dev": true - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "8.3.0", - "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pinia": { - "version": "2.1.6", - "resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.1.6.tgz", - "integrity": "sha512-bIU6QuE5qZviMmct5XwCesXelb5VavdOWKWaB17ggk++NUwQWWbP5YnsONTk3b752QkW9sACiR81rorpeOMSvQ==", - "dependencies": { - "@vue/devtools-api": "^6.5.0", - "vue-demi": ">=0.14.5" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "@vue/composition-api": "^1.4.0", - "typescript": ">=4.4.4", - "vue": "^2.6.14 || ^3.3.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/pinia/node_modules/vue-demi": { - "version": "0.14.10", - "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz", - "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, - "node_modules/portfinder": { - "version": "1.0.38", - "resolved": "https://registry.npmmirror.com/portfinder/-/portfinder-1.0.38.tgz", - "integrity": "sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==", - "dev": true, - "dependencies": { - "async": "^3.2.6", - "debug": "^4.3.6" - }, - "engines": { - "node": ">= 10.12" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmmirror.com/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - }, - "peerDependencies": { - "postcss": "^8.2.2" - } - }, - "node_modules/postcss-colormin": { - "version": "5.3.1", - "resolved": "https://registry.npmmirror.com/postcss-colormin/-/postcss-colormin-5.3.1.tgz", - "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmmirror.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-helpers": { - "version": "0.3.3", - "resolved": "https://registry.npmmirror.com/postcss-helpers/-/postcss-helpers-0.3.3.tgz", - "integrity": "sha512-VumiUcrpbxGlTBNQj6fUOkb/HNRUk/xYz8bNlhgVOdvk3yWEy4B+0nlDUZZM9mTVZ5bJoxUy7WT6z/4E7oMTgw==", - "dev": true, - "dependencies": { - "urijs": "^1.18.12" - }, - "engines": { - "node": ">=0.12.9" - } - }, - "node_modules/postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmmirror.com/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dev": true, - "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - } - }, - "node_modules/postcss-loader/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmmirror.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-merge-rules": { - "version": "5.1.4", - "resolved": "https://registry.npmmirror.com/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", - "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", - "dev": true, - "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmmirror.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmmirror.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", - "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^7.0.0", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.2.1", - "resolved": "https://registry.npmmirror.com/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", - "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^7.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", - "dev": true, - "dependencies": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmmirror.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", - "dev": true, - "dependencies": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-initial": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", - "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-urlrewrite": { - "version": "0.2.2", - "resolved": "https://registry.npmmirror.com/postcss-urlrewrite/-/postcss-urlrewrite-0.2.2.tgz", - "integrity": "sha512-DxPSgykgHjoV4Z+ygvq2C5HkiuiKQQD74xpoNQSQuyi8zab9nODVtNKfnCN6BEv9VZrjpOGLGAf8BDvgG6EtHg==", - "dev": true, - "dependencies": { - "postcss-helpers": "^0.3.2" - }, - "engines": { - "node": ">=0.12.9" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/postcss/node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmmirror.com/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "optional": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress-webpack-plugin": { - "version": "1.0.16", - "resolved": "https://registry.npmmirror.com/progress-webpack-plugin/-/progress-webpack-plugin-1.0.16.tgz", - "integrity": "sha512-sdiHuuKOzELcBANHfrupYo+r99iPRyOnw15qX+rNlVUqXGfjXdH4IgxriKwG1kNJwVswKQHMdj1hYZMcb9jFaA==", - "dev": true, - "dependencies": { - "chalk": "^2.1.0", - "figures": "^2.0.0", - "log-update": "^2.3.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "peerDependencies": { - "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmmirror.com/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-3.0.1.tgz", - "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.7.0", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.7.0", - "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.7.0.tgz", - "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmmirror.com/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmmirror.com/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-area-insets": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/safe-area-insets/-/safe-area-insets-1.4.1.tgz", - "integrity": "sha512-r/nRWTjFGhhm3w1Z6Kd/jY11srN+lHt2mNl1E/emQGW8ic7n3Avu4noibklfSM+Y34peNphHD/BSZecav0sXYQ==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sass": { - "version": "1.92.1", - "resolved": "https://registry.npmmirror.com/sass/-/sass-1.92.1.tgz", - "integrity": "sha512-ffmsdbwqb3XeyR8jJR6KelIXARM9bFQe8A6Q3W4Klmwy5Ckd5gz7jgUNHo4UOqutU5Sk1DtKLbpDP0nLCg1xqQ==", - "dev": true, - "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" - } - }, - "node_modules/sass-loader": { - "version": "16.0.5", - "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-16.0.5.tgz", - "integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==", - "dev": true, - "dependencies": { - "neo-async": "^2.6.2" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/sass/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/sass/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/send": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", - "dependencies": { - "debug": "^4.3.5", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/send/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/send/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmmirror.com/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmmirror.com/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sirv": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/sirv/-/sirv-2.0.4.tgz", - "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", - "dev": true, - "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmmirror.com/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/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==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", - "dev": true - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmmirror.com/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmmirror.com/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmmirror.com/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", - "dev": true - }, - "node_modules/stackframe": { - "version": "1.3.4", - "resolved": "https://registry.npmmirror.com/stackframe/-/stackframe-1.3.4.tgz", - "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", - "dev": true - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmmirror.com/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tapable": { - "version": "2.2.3", - "resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.2.3.tgz", - "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/terser": { - "version": "5.44.0", - "resolved": "https://registry.npmmirror.com/terser/-/terser-5.44.0.tgz", - "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.14", - "resolved": "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", - "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/thread-loader": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/thread-loader/-/thread-loader-3.0.4.tgz", - "integrity": "sha512-ByaL2TPb+m6yArpqQUZvP+5S1mZtXsEP7nWKKlAUTm7fCml8kB5s1uI3+eHRP2bk5mVYfRSBI7FFf+tWEyLZwA==", - "dev": true, - "dependencies": { - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.1.0", - "loader-utils": "^2.0.0", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.27.0 || ^5.0.0" - } - }, - "node_modules/thread-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/type-is/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/type-is/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "devOptional": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "7.12.0", - "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.12.0.tgz", - "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", - "dev": true - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/update-browserslist-db/node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urijs": { - "version": "1.19.11", - "resolved": "https://registry.npmmirror.com/urijs/-/urijs-1.19.11.tgz", - "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", - "dev": true - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmmirror.com/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vue": { - "version": "2.6.14", - "resolved": "https://registry.npmmirror.com/vue/-/vue-2.6.14.tgz", - "integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==", - "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details." - }, - "node_modules/vue-eslint-parser": { - "version": "9.4.3", - "resolved": "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", - "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.6" - }, - "engines": { - "node": "^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, - "node_modules/vue-eslint-parser/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/vue-hot-reload-api": { - "version": "2.3.4", - "resolved": "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", - "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", - "dev": true - }, - "node_modules/vue-loader": { - "version": "17.4.2", - "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-17.4.2.tgz", - "integrity": "sha512-yTKOA4R/VN4jqjw4y5HrynFL8AK0Z3/Jt7eOJXEitsm0GMRHDBjCfCiuTiLP7OESvsZYo2pATCWhDqxC5ZrM6w==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "watchpack": "^2.4.0" - }, - "peerDependencies": { - "webpack": "^4.1.0 || ^5.0.0-0" - }, - "peerDependenciesMeta": { - "@vue/compiler-sfc": { - "optional": true - }, - "vue": { - "optional": true - } - } - }, - "node_modules/vue-loader/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/vue-loader/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/vue-loader/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/vue-loader/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/vue-loader/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/vue-loader/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/vue-router": { - "version": "3.6.5", - "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-3.6.5.tgz", - "integrity": "sha512-VYXZQLtjuvKxxcshuRAwjHnciqZVoXAjTjcqBTz4rKc8qih9g9pI3hbDjmqXaHdgL3v8pV6P8Z335XvHzESxLQ==" - }, - "node_modules/vue-style-loader": { - "version": "4.1.3", - "resolved": "https://registry.npmmirror.com/vue-style-loader/-/vue-style-loader-4.1.3.tgz", - "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", - "dev": true, - "dependencies": { - "hash-sum": "^1.0.2", - "loader-utils": "^1.0.2" - } - }, - "node_modules/vue-style-loader/node_modules/hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", - "dev": true - }, - "node_modules/vue-template-compiler": { - "version": "2.6.14", - "resolved": "https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz", - "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==", - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.1.0" - } - }, - "node_modules/vue-template-es2015-compiler": { - "version": "1.9.1", - "resolved": "https://registry.npmmirror.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", - "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", - "dev": true - }, - "node_modules/watchpack": { - "version": "2.4.4", - "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.4.tgz", - "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmmirror.com/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/webpack": { - "version": "5.101.3", - "resolved": "https://registry.npmmirror.com/webpack/-/webpack-5.101.3.tgz", - "integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.24.0", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.3", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.2", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.11", - "watchpack": "^2.4.1", - "webpack-sources": "^3.3.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-bundle-analyzer": { - "version": "4.10.2", - "resolved": "https://registry.npmmirror.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", - "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "0.5.7", - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "commander": "^7.2.0", - "debounce": "^1.2.1", - "escape-string-regexp": "^4.0.0", - "gzip-size": "^6.0.0", - "html-escaper": "^2.0.2", - "opener": "^1.5.2", - "picocolors": "^1.0.0", - "sirv": "^2.0.3", - "ws": "^7.3.1" - }, - "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/webpack-bundle-analyzer/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmmirror.com/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/webpack-chain": { - "version": "6.5.1", - "resolved": "https://registry.npmmirror.com/webpack-chain/-/webpack-chain-6.5.1.tgz", - "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "dependencies": { - "deepmerge": "^1.5.2", - "javascript-stringify": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-dev-middleware": { - "version": "5.3.4", - "resolved": "https://registry.npmmirror.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", - "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", - "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/webpack-dev-middleware/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack-dev-server": { - "version": "4.15.2", - "resolved": "https://registry.npmmirror.com/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", - "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", - "dev": true, - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.4", - "ws": "^8.13.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-server/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-server/node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/webpack-dev-server/node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/webpack-dev-server/node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "node_modules/webpack-dev-server/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/webpack-dev-server/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/webpack-dev-server/node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmmirror.com/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/webpack-dev-server/node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/webpack-dev-server/node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/webpack-dev-server/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/webpack-dev-server/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/webpack-dev-server/node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/webpack-dev-server/node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "dev": true - }, - "node_modules/webpack-dev-server/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/webpack-dev-server/node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack-dev-server/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmmirror.com/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/webpack-dev-server/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/webpack-dev-server/node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmmirror.com/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "dev": true, - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/webpack-dev-server/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/webpack-dev-server/node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack-virtual-modules": { - "version": "0.4.6", - "resolved": "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.4.6.tgz", - "integrity": "sha512-5tyDlKLqPfMqjT3Q9TAqf2YqjwmnUleZwzJi1A5qXnlBCdj2AtOJ6wAWdglTIDOPgOiOrXeBeFcsQ8+aGQ6QbA==", - "dev": true - }, - "node_modules/webpack/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmmirror.com/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/whatwg-fetch": { - "version": "3.6.20", - "resolved": "https://registry.npmmirror.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", - "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmmirror.com/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmmirror.com/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@achrinza/node-ipc": { - "version": "9.2.9", - "resolved": "https://registry.npmmirror.com/@achrinza/node-ipc/-/node-ipc-9.2.9.tgz", - "integrity": "sha512-7s0VcTwiK/0tNOVdSX9FWMeFdOEcsAOz9HesBldXxFMaGvIak7KC2z9tV9EgsQXn6KUsWsfIkViMNuIo0GoZDQ==", - "dev": true, - "requires": { - "@node-ipc/js-queue": "2.0.3", - "event-pubsub": "4.3.0", - "js-message": "1.0.7" - } - }, - "@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - } - }, - "@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", - "dev": true - }, - "@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true - }, - "@babel/highlight": { - "version": "7.25.9", - "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.25.9.tgz", - "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.25.9", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - } - }, - "@dcloudio/types": { - "version": "3.4.21", - "resolved": "https://registry.npmmirror.com/@dcloudio/types/-/types-3.4.21.tgz", - "integrity": "sha512-rsv3XfAaD/dtuVboPeYh+vPcULnWyozGaGKHWyN0dYRm7L1uypFUM30qNYMj9iNmbAENuBjV177S1gNEBIvdDA==", - "peer": true - }, - "@dcloudio/uni-app": { - "version": "2.0.2-alpha-4080120250905001", - "resolved": "https://registry.npmmirror.com/@dcloudio/uni-app/-/uni-app-2.0.2-alpha-4080120250905001.tgz", - "integrity": "sha512-h9Og8v85U3hOBh5FCbnmmGPzX8OTJssJvQxZzi01J6lbWrqxnuP/DS+8zFb+A2mGgpzzeK/KHv9i4mUsVNv4TA==", - "requires": {} - }, - "@dcloudio/uni-cli-shared": { - "version": "2.0.2-alpha-4080120250905001", - "resolved": "https://registry.npmmirror.com/@dcloudio/uni-cli-shared/-/uni-cli-shared-2.0.2-alpha-4080120250905001.tgz", - "integrity": "sha512-+zHK6mxN+2PcVUk7SJkrY6mXO0pk65ghJgYEoElF3UT4M0TPRe+bc3tFhTn7hGSYxP1JYx8I0RoxkIeTMDK0xA==", - "dev": true, - "requires": { - "escape-string-regexp": "^4.0.0", - "fast-glob": "^3.2.11", - "fs-extra": "^10.0.0", - "glob-escape": "^0.0.2", - "hash-sum": "^1.0.2", - "postcss-urlrewrite": "^0.2.2", - "strip-json-comments": "^2.0.1" - }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true - } - } - }, - "@dcloudio/uni-h5": { - "version": "2.0.2-alpha-4080120250905001", - "resolved": "https://registry.npmmirror.com/@dcloudio/uni-h5/-/uni-h5-2.0.2-alpha-4080120250905001.tgz", - "integrity": "sha512-hQ1ONQm+8ZKnc6FRbRT9xWGwH4ed0KqVIgvwduG7bVnvcvhxIuFhPUthMCYyvQaVjdp0yjBiUicVEwomWSsZRw==", - "dev": true, - "requires": { - "base64-arraybuffer": "^0.2.0", - "intersection-observer": "^0.7.0", - "pako": "^1.0.11", - "postcss-urlrewrite": "^0.3.0", - "safe-area-insets": "^1.4.1" - }, - "dependencies": { - "postcss-urlrewrite": { - "version": "0.3.0", - "resolved": "https://registry.npmmirror.com/postcss-urlrewrite/-/postcss-urlrewrite-0.3.0.tgz", - "integrity": "sha512-504S/dMa7a0n1yghE2I6fxY/DfMUM+w9qsFaoYnXE8KsCofmKLlA7PKbR+wtdEJ0N00Z1lGYxX/oFz13xArcLQ==", - "dev": true, - "requires": { - "postcss-helpers": "^0.3.3" - } - } - } - }, - "@dcloudio/uni-mp-weixin": { - "version": "2.0.2-alpha-4080120250905001", - "resolved": "https://registry.npmmirror.com/@dcloudio/uni-mp-weixin/-/uni-mp-weixin-2.0.2-alpha-4080120250905001.tgz", - "integrity": "sha512-tyEt9RLhG39EBH+sgGPUJmBbJDwMcnv46CLzPChDLDVdunupqjHB42MmzUY8yrDNeZuD4MB02NAI3oLUrsSw0w==", - "dev": true - }, - "@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true - }, - "@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.4.3" - } - }, - "@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true - }, - "@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmmirror.com/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true - }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true - }, - "@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "requires": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "@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==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", - "dev": true - }, - "@node-ipc/js-queue": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/@node-ipc/js-queue/-/js-queue-2.0.3.tgz", - "integrity": "sha512-fL1wpr8hhD5gT2dA1qifeVaoDFlQR5es8tFuKqjHX+kdOtdNHnxkVZbtIrR2rxnMFvehkjaZRNV2H/gPXlb0hw==", - "dev": true, - "requires": { - "easy-stack": "1.0.1" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@parcel/watcher": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.1.tgz", - "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", - "dev": true, - "optional": true, - "requires": { - "@parcel/watcher-android-arm64": "2.5.1", - "@parcel/watcher-darwin-arm64": "2.5.1", - "@parcel/watcher-darwin-x64": "2.5.1", - "@parcel/watcher-freebsd-x64": "2.5.1", - "@parcel/watcher-linux-arm-glibc": "2.5.1", - "@parcel/watcher-linux-arm-musl": "2.5.1", - "@parcel/watcher-linux-arm64-glibc": "2.5.1", - "@parcel/watcher-linux-arm64-musl": "2.5.1", - "@parcel/watcher-linux-x64-glibc": "2.5.1", - "@parcel/watcher-linux-x64-musl": "2.5.1", - "@parcel/watcher-win32-arm64": "2.5.1", - "@parcel/watcher-win32-ia32": "2.5.1", - "@parcel/watcher-win32-x64": "2.5.1", - "detect-libc": "^1.0.3", - "is-glob": "^4.0.3", - "micromatch": "^4.0.5", - "node-addon-api": "^7.0.0" - } - }, - "@parcel/watcher-android-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", - "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", - "dev": true, - "optional": true - }, - "@parcel/watcher-darwin-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", - "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", - "dev": true, - "optional": true - }, - "@parcel/watcher-darwin-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", - "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", - "dev": true, - "optional": true - }, - "@parcel/watcher-freebsd-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", - "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", - "dev": true, - "optional": true - }, - "@parcel/watcher-linux-arm-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", - "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", - "dev": true, - "optional": true - }, - "@parcel/watcher-linux-arm-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", - "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", - "dev": true, - "optional": true - }, - "@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", - "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", - "dev": true, - "optional": true - }, - "@parcel/watcher-linux-arm64-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", - "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", - "dev": true, - "optional": true - }, - "@parcel/watcher-linux-x64-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", - "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", - "dev": true, - "optional": true - }, - "@parcel/watcher-linux-x64-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", - "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", - "dev": true, - "optional": true - }, - "@parcel/watcher-win32-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", - "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", - "dev": true, - "optional": true - }, - "@parcel/watcher-win32-ia32": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", - "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", - "dev": true, - "optional": true - }, - "@parcel/watcher-win32-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", - "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", - "dev": true, - "optional": true - }, - "@polka/url": { - "version": "1.0.0-next.29", - "resolved": "https://registry.npmmirror.com/@polka/url/-/url-1.0.0-next.29.tgz", - "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", - "dev": true - }, - "@sideway/address": { - "version": "4.1.5", - "resolved": "https://registry.npmmirror.com/@sideway/address/-/address-4.1.5.tgz", - "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true - }, - "@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "@soda/friendly-errors-webpack-plugin": { - "version": "1.8.1", - "resolved": "https://registry.npmmirror.com/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz", - "integrity": "sha512-h2ooWqP8XuFqTXT+NyAFbrArzfQA7R6HTezADrvD9Re8fxMLTPPniLdqVTdDaO0eIoLaAwKT+d6w+5GeTk7Vbg==", - "dev": true, - "requires": { - "chalk": "^3.0.0", - "error-stack-parser": "^2.0.6", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@soda/get-current-script": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/@soda/get-current-script/-/get-current-script-1.0.2.tgz", - "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==", - "dev": true - }, - "@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true - }, - "@types/body-parser": { - "version": "1.19.6", - "resolved": "https://registry.npmmirror.com/@types/body-parser/-/body-parser-1.19.6.tgz", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmmirror.com/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmmirror.com/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmmirror.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", - "dev": true, - "requires": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@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 - }, - "@types/express": { - "version": "4.17.23", - "resolved": "https://registry.npmmirror.com/@types/express/-/express-4.17.23.tgz", - "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - }, - "dependencies": { - "@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmmirror.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - } - } - }, - "@types/express-serve-static-core": { - "version": "5.0.7", - "resolved": "https://registry.npmmirror.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", - "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "@types/http-errors": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", - "dev": true - }, - "@types/http-proxy": { - "version": "1.17.16", - "resolved": "https://registry.npmmirror.com/@types/http-proxy/-/http-proxy-1.17.16.tgz", - "integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmmirror.com/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, - "@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true - }, - "@types/node": { - "version": "24.5.1", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-24.5.1.tgz", - "integrity": "sha512-/SQdmUP2xa+1rdx7VwB9yPq8PaKej8TD5cQ+XfKDPWWC+VDJU4rvVVagXqKUzhKjtFoNA8rXDJAkCxQPAe00+Q==", - "dev": true, - "requires": { - "undici-types": "~7.12.0" - } - }, - "@types/node-forge": { - "version": "1.3.14", - "resolved": "https://registry.npmmirror.com/@types/node-forge/-/node-forge-1.3.14.tgz", - "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmmirror.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true - }, - "@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmmirror.com/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", - "dev": true - }, - "@types/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmmirror.com/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmmirror.com/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true - }, - "@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmmirror.com/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true - }, - "@types/send": { - "version": "0.17.5", - "resolved": "https://registry.npmmirror.com/@types/send/-/send-0.17.5.tgz", - "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", - "dev": true, - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmmirror.com/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/serve-static": { - "version": "1.15.8", - "resolved": "https://registry.npmmirror.com/@types/serve-static/-/serve-static-1.15.8.tgz", - "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", - "dev": true, - "requires": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmmirror.com/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "dev": true - }, - "@vant/weapp": { - "version": "1.11.7", - "resolved": "https://registry.npmmirror.com/@vant/weapp/-/weapp-1.11.7.tgz", - "integrity": "sha512-Rwn9BBnb4kHSV4XmvBicwtd42J+amEUfnFDcXJsGNPNX4a9c/DoT6YLsm4X1wB2+sQbdiQsbFBLAvGRBxCkD8g==", - "dev": true - }, - "@vue/cli-overlay": { - "version": "5.0.9", - "resolved": "https://registry.npmmirror.com/@vue/cli-overlay/-/cli-overlay-5.0.9.tgz", - "integrity": "sha512-aBdZWrYKxLuFz1FDsk/muFD7GycrsW73Gi11yRc7R2W7Bm8mDRc9HKAI790gdg4NV+chkDFmfkegjg5iMDEpAA==", - "dev": true - }, - "@vue/cli-plugin-router": { - "version": "5.0.9", - "resolved": "https://registry.npmmirror.com/@vue/cli-plugin-router/-/cli-plugin-router-5.0.9.tgz", - "integrity": "sha512-kopbO/8kIl5CAffwgptXEwV509i+M0FfwW4sSkgQ2RzpxOYBjQZvp+096mjZfFcWKSmryNP/ri/Mnu78vmhlhw==", - "dev": true, - "requires": { - "@vue/cli-shared-utils": "^5.0.9" - } - }, - "@vue/cli-plugin-vuex": { - "version": "5.0.9", - "resolved": "https://registry.npmmirror.com/@vue/cli-plugin-vuex/-/cli-plugin-vuex-5.0.9.tgz", - "integrity": "sha512-AQhgGNFVd4Pu2crvS0a+hRckgrJv07gzOASdbLd3I72wkT43dd01MLRp8IBRRsu92t3MXenW86AZUCbQBz3//A==", - "dev": true, - "requires": {} - }, - "@vue/cli-service": { - "version": "5.0.8", - "resolved": "https://registry.npmmirror.com/@vue/cli-service/-/cli-service-5.0.8.tgz", - "integrity": "sha512-nV7tYQLe7YsTtzFrfOMIHc5N2hp5lHG2rpYr0aNja9rNljdgcPZLyQRb2YRivTHqTv7lI962UXFURcpStHgyFw==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.12.16", - "@soda/friendly-errors-webpack-plugin": "^1.8.0", - "@soda/get-current-script": "^1.0.2", - "@types/minimist": "^1.2.0", - "@vue/cli-overlay": "^5.0.8", - "@vue/cli-plugin-router": "^5.0.8", - "@vue/cli-plugin-vuex": "^5.0.8", - "@vue/cli-shared-utils": "^5.0.8", - "@vue/component-compiler-utils": "^3.3.0", - "@vue/vue-loader-v15": "npm:vue-loader@^15.9.7", - "@vue/web-component-wrapper": "^1.3.0", - "acorn": "^8.0.5", - "acorn-walk": "^8.0.2", - "address": "^1.1.2", - "autoprefixer": "^10.2.4", - "browserslist": "^4.16.3", - "case-sensitive-paths-webpack-plugin": "^2.3.0", - "cli-highlight": "^2.1.10", - "clipboardy": "^2.3.0", - "cliui": "^7.0.4", - "copy-webpack-plugin": "^9.0.1", - "css-loader": "^6.5.0", - "css-minimizer-webpack-plugin": "^3.0.2", - "cssnano": "^5.0.0", - "debug": "^4.1.1", - "default-gateway": "^6.0.3", - "dotenv": "^10.0.0", - "dotenv-expand": "^5.1.0", - "fs-extra": "^9.1.0", - "globby": "^11.0.2", - "hash-sum": "^2.0.0", - "html-webpack-plugin": "^5.1.0", - "is-file-esm": "^1.0.0", - "launch-editor-middleware": "^2.2.1", - "lodash.defaultsdeep": "^4.6.1", - "lodash.mapvalues": "^4.6.0", - "mini-css-extract-plugin": "^2.5.3", - "minimist": "^1.2.5", - "module-alias": "^2.2.2", - "portfinder": "^1.0.26", - "postcss": "^8.2.6", - "postcss-loader": "^6.1.1", - "progress-webpack-plugin": "^1.0.12", - "ssri": "^8.0.1", - "terser-webpack-plugin": "^5.1.1", - "thread-loader": "^3.0.0", - "vue-loader": "^17.0.0", - "vue-style-loader": "^4.1.3", - "webpack": "^5.54.0", - "webpack-bundle-analyzer": "^4.4.0", - "webpack-chain": "^6.5.1", - "webpack-dev-server": "^4.7.3", - "webpack-merge": "^5.7.3", - "webpack-virtual-modules": "^0.4.2", - "whatwg-fetch": "^3.6.2" - }, - "dependencies": { - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - } - } - }, - "@vue/cli-shared-utils": { - "version": "5.0.9", - "resolved": "https://registry.npmmirror.com/@vue/cli-shared-utils/-/cli-shared-utils-5.0.9.tgz", - "integrity": "sha512-lf4KykiG8j9KwvNVi7fKtASmHuLsxCcCsflVU2b2CHMRuR4weOIV3zuuCrjWKjk0APn/MHJhgCjJGzHMbTtd5w==", - "dev": true, - "requires": { - "@achrinza/node-ipc": "^9.2.5", - "chalk": "^4.1.2", - "execa": "^1.0.0", - "joi": "^17.4.0", - "launch-editor": "^2.2.1", - "lru-cache": "^6.0.0", - "node-fetch": "^2.6.7", - "open": "^8.0.2", - "ora": "^5.3.0", - "read-pkg": "^5.1.1", - "semver": "^7.3.4", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "@vue/component-compiler-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmmirror.com/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", - "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==", - "dev": true, - "requires": { - "consolidate": "^0.15.1", - "hash-sum": "^1.0.2", - "lru-cache": "^4.1.2", - "merge-source-map": "^1.1.0", - "postcss": "^7.0.36", - "postcss-selector-parser": "^6.0.2", - "prettier": "^1.18.2 || ^2.0.0", - "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.9.0" - }, - "dependencies": { - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "requires": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - } - } - }, - "@vue/composition-api": { - "version": "1.7.2", - "resolved": "https://registry.npmmirror.com/@vue/composition-api/-/composition-api-1.7.2.tgz", - "integrity": "sha512-M8jm9J/laYrYT02665HkZ5l2fWTK4dcVg3BsDHm/pfz+MjDYwX+9FUaZyGwEyXEDonQYRCo0H7aLgdklcIELjw==", - "requires": {} - }, - "@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==" - }, - "@vue/vue-loader-v15": { - "version": "npm:vue-loader@15.11.1", - "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-15.11.1.tgz", - "integrity": "sha512-0iw4VchYLePqJfJu9s62ACWUXeSqM30SQqlIftbYWM3C+jpPcEHKSPUZBLjSF9au4HTHQ/naF6OGnO3Q/qGR3Q==", - "dev": true, - "requires": { - "@vue/component-compiler-utils": "^3.1.0", - "hash-sum": "^1.0.2", - "loader-utils": "^1.1.0", - "vue-hot-reload-api": "^2.3.0", - "vue-style-loader": "^4.1.0" - }, - "dependencies": { - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", - "dev": true - } - } - }, - "@vue/web-component-wrapper": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz", - "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "dependencies": { - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true - } - } - }, - "acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true - }, - "acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmmirror.com/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "requires": { - "acorn": "^8.11.0" - } - }, - "address": { - "version": "1.2.2", - "resolved": "https://registry.npmmirror.com/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "dev": true - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmmirror.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arch": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "async": { - "version": "3.2.6", - "resolved": "https://registry.npmmirror.com/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, - "autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", - "dev": true, - "requires": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", - "postcss-value-parser": "^4.2.0" - } - }, - "axios": { - "version": "0.27.2", - "resolved": "https://registry.npmmirror.com/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "requires": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base64-arraybuffer": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", - "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==", - "dev": true - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "baseline-browser-mapping": { - "version": "2.8.4", - "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.4.tgz", - "integrity": "sha512-L+YvJwGAgwJBV1p6ffpSTa2KRc69EeeYGYjRVWKs0GKrK+LON0GC0gV+rKSNtALEDvMDqkvCFq9r1r94/Gjwxw==", - "dev": true - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmmirror.com/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmmirror.com/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", - "requires": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", - "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" - } - }, - "bonjour-service": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/bonjour-service/-/bonjour-service-1.3.0.tgz", - "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "requires": { - "fill-range": "^7.1.1" - } - }, - "browserslist": { - "version": "4.26.2", - "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.26.2.tgz", - "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", - "dev": true, - "requires": { - "baseline-browser-mapping": "^2.8.3", - "caniuse-lite": "^1.0.30001741", - "electron-to-chromium": "^1.5.218", - "node-releases": "^2.0.21", - "update-browserslist-db": "^1.1.3" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "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==", - "requires": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - } - }, - "call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "requires": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "requires": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "caniuse-lite": { - "version": "1.0.30001743", - "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz", - "integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==", - "dev": true - }, - "case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmmirror.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true - }, - "clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmmirror.com/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dev": true, - "requires": { - "source-map": "~0.6.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmmirror.com/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true - }, - "clipboardy": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/clipboardy/-/clipboardy-2.3.0.tgz", - "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", - "dev": true, - "requires": { - "arch": "^2.1.1", - "execa": "^1.0.0", - "is-wsl": "^2.1.1" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "colord": { - "version": "2.9.3", - "resolved": "https://registry.npmmirror.com/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true - }, - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "8.3.0", - "resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmmirror.com/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.8.1", - "resolved": "https://registry.npmmirror.com/compression/-/compression-1.8.1.tgz", - "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "compressible": "~2.0.18", - "debug": "2.6.9", - "negotiator": "~0.6.4", - "on-headers": "~1.1.0", - "safe-buffer": "5.2.1", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true - }, - "consolidate": { - "version": "0.15.1", - "resolved": "https://registry.npmmirror.com/consolidate/-/consolidate-0.15.1.tgz", - "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", - "dev": true, - "requires": { - "bluebird": "^3.1.1" - } - }, - "content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" - }, - "cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmmirror.com/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==" - }, - "cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==" - }, - "copy-webpack-plugin": { - "version": "9.1.0", - "resolved": "https://registry.npmmirror.com/copy-webpack-plugin/-/copy-webpack-plugin-9.1.0.tgz", - "integrity": "sha512-rxnR7PaGigJzhqETHGmAcxKnLZSR5u1Y3/bcIv/1FnqXedcL/E2ewK7ZCNrArJKCiSv8yVXhTqetJh8inDvfsA==", - "dev": true, - "requires": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^11.0.3", - "normalize-path": "^3.0.0", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0" - }, - "dependencies": { - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - } - } - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmmirror.com/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - } - }, - "cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmmirror.com/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.1" - } - }, - "cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "css-declaration-sorter": { - "version": "6.4.1", - "resolved": "https://registry.npmmirror.com/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", - "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", - "dev": true, - "requires": {} - }, - "css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmmirror.com/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "dependencies": { - "semver": { - "version": "7.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true - } - } - }, - "css-minimizer-webpack-plugin": { - "version": "3.4.1", - "resolved": "https://registry.npmmirror.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", - "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", - "dev": true, - "requires": { - "cssnano": "^5.0.6", - "jest-worker": "^27.0.2", - "postcss": "^8.3.5", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } - } - }, - "css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - } - }, - "css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "cssnano": { - "version": "5.1.15", - "resolved": "https://registry.npmmirror.com/cssnano/-/cssnano-5.1.15.tgz", - "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", - "dev": true, - "requires": { - "cssnano-preset-default": "^5.2.14", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - } - }, - "cssnano-preset-default": { - "version": "5.2.14", - "resolved": "https://registry.npmmirror.com/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", - "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", - "dev": true, - "requires": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.1", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.4", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.2", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - } - }, - "cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "dev": true, - "requires": {} - }, - "csso": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "requires": { - "css-tree": "^1.1.2" - } - }, - "dayjs": { - "version": "1.11.0", - "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.0.tgz", - "integrity": "sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug==" - }, - "de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==" - }, - "debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", - "dev": true - }, - "debug": { - "version": "4.4.3", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "requires": { - "ms": "^2.1.3" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "1.5.2", - "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-1.5.2.tgz", - "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", - "dev": true - }, - "default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmmirror.com/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - }, - "dependencies": { - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - } - } - }, - "defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true, - "optional": true - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmmirror.com/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, - "requires": { - "@leichtgewicht/ip-codec": "^2.0.1" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "requires": { - "utila": "~0.4" - } - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "dependencies": { - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - } - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true - }, - "dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true - }, - "dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "requires": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - } - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmmirror.com/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "easy-stack": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/easy-stack/-/easy-stack-1.0.1.tgz", - "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==", - "dev": true - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "electron-to-chromium": { - "version": "1.5.220", - "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.220.tgz", - "integrity": "sha512-TWXijEwR1ggr4BdAKrb1nMNqYLTx1/4aD1fkeZU+FVJGTKu53/T7UyHKXlqEX3Ub02csyHePbHmkvnrjcaYzMA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" - }, - "end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "error-stack-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmmirror.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz", - "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", - "dev": true, - "requires": { - "stackframe": "^1.3.4" - } - }, - "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==" - }, - "es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" - }, - "es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true - }, - "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==", - "requires": { - "es-errors": "^1.3.0" - } - }, - "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==", - "requires": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - } - }, - "escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmmirror.com/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "eslint-plugin-vue": { - "version": "9.33.0", - "resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz", - "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "globals": "^13.24.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.1.1", - "postcss-selector-parser": "^6.0.15", - "semver": "^7.6.3", - "vue-eslint-parser": "^9.4.3", - "xml-name-validator": "^4.0.0" - }, - "dependencies": { - "semver": { - "version": "7.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true - } - } - }, - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmmirror.com/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - }, - "event-pubsub": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/event-pubsub/-/event-pubsub-4.3.0.tgz", - "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", - "dev": true - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmmirror.com/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "express": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", - "requires": { - "accepts": "^2.0.0", - "body-parser": "^2.2.0", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "dependencies": { - "accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "requires": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - } - }, - "mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==" - }, - "mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "requires": { - "mime-db": "^1.54.0" - } - }, - "negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==" - } - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true - }, - "fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmmirror.com/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/figures/-/figures-2.0.0.tgz", - "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", - "requires": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmmirror.com/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "requires": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==" - }, - "form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true - }, - "fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==" - }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs-monkey": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/fs-monkey/-/fs-monkey-1.1.0.tgz", - "integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": 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 - }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "requires": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - } - }, - "get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "requires": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-escape": { - "version": "0.0.2", - "resolved": "https://registry.npmmirror.com/glob-escape/-/glob-escape-0.0.2.tgz", - "integrity": "sha512-L/cXYz8x7qer1HAyUQ+mbjcUsJVdpRxpAf7CwqHoNBs9vTpABlGfNN4tzkDxt+u3Z7ZncVyKlCNPtzb0R/7WbA==", - "dev": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "globals": { - "version": "13.24.0", - "resolved": "https://registry.npmmirror.com/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmmirror.com/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "requires": { - "duplexer": "^0.1.2" - } - }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" - }, - "has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "requires": { - "has-symbols": "^1.0.3" - } - }, - "hash-sum": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-2.0.0.tgz", - "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", - "dev": true - }, - "hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "requires": { - "function-bind": "^1.1.2" - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - }, - "highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmmirror.com/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "html-entities": { - "version": "2.6.0", - "resolved": "https://registry.npmmirror.com/html-entities/-/html-entities-2.6.0.tgz", - "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "requires": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - } - }, - "html-webpack-plugin": { - "version": "5.6.4", - "resolved": "https://registry.npmmirror.com/html-webpack-plugin/-/html-webpack-plugin-5.6.4.tgz", - "integrity": "sha512-V/PZeWsqhfpE27nKeX9EO2sbR+D17A+tLf6qU+ht66jdUsN0QLKJN27Z+1+gHrVMKgndBahes0PU6rRihDgHTw==", - "dev": true, - "requires": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - }, - "dependencies": { - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - } - } - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmmirror.com/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "dependencies": { - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - } - } - }, - "http-parser-js": { - "version": "0.5.10", - "resolved": "https://registry.npmmirror.com/http-parser-js/-/http-parser-js-0.5.10.tgz", - "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", - "dev": true - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmmirror.com/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-middleware": { - "version": "2.0.9", - "resolved": "https://registry.npmmirror.com/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", - "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", - "dev": true, - "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true - }, - "immutable": { - "version": "5.1.3", - "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.3.tgz", - "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", - "dev": true - }, - "import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "intersection-observer": { - "version": "0.7.0", - "resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.7.0.tgz", - "integrity": "sha512-Id0Fij0HsB/vKWGeBe9PxeY45ttRiBmhFyyt/geBdDHBYNctMRTE3dC1U3ujzz3lap+hVXlEcVaB56kZP/eEUg==", - "dev": true - }, - "ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "requires": { - "hasown": "^2.0.2" - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-file-esm": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/is-file-esm/-/is-file-esm-1.0.0.tgz", - "integrity": "sha512-rZlaNKb4Mr8WlRu2A9XdeoKgnO5aA53XdPHgCKVyCrQ/rWi89RET1+bq37Ru46obaQXeiX4vmFIm1vks41hoSA==", - "dev": true, - "requires": { - "read-pkg-up": "^7.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "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, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - }, - "javascript-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/javascript-stringify/-/javascript-stringify-2.1.0.tgz", - "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "joi": { - "version": "17.13.3", - "resolved": "https://registry.npmmirror.com/joi/-/joi-17.13.3.tgz", - "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", - "dev": true, - "requires": { - "@hapi/hoek": "^9.3.0", - "@hapi/topo": "^5.1.0", - "@sideway/address": "^4.1.5", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, - "js-message": { - "version": "1.0.7", - "resolved": "https://registry.npmmirror.com/js-message/-/js-message-1.0.7.tgz", - "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "klona": { - "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "dev": true - }, - "launch-editor": { - "version": "2.11.1", - "resolved": "https://registry.npmmirror.com/launch-editor/-/launch-editor-2.11.1.tgz", - "integrity": "sha512-SEET7oNfgSaB6Ym0jufAdCeo3meJVeCaaDyzRygy0xsp2BFKCprcfHljTq4QkzTLUxEKkFK6OK4811YM2oSrRg==", - "dev": true, - "requires": { - "picocolors": "^1.1.1", - "shell-quote": "^1.8.3" - }, - "dependencies": { - "picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - } - } - }, - "launch-editor-middleware": { - "version": "2.11.1", - "resolved": "https://registry.npmmirror.com/launch-editor-middleware/-/launch-editor-middleware-2.11.1.tgz", - "integrity": "sha512-6xpn4pJz5mDg2kUH7L6gK5BuZcZPdVwoSs/DhfebefwLyszNXqFFjksGup/w4CTRzzrr8FSEufDzb/gKFLle6w==", - "dev": true, - "requires": { - "launch-editor": "^2.11.1" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true - }, - "loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true - }, - "loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.defaultsdeep": { - "version": "4.6.1", - "resolved": "https://registry.npmmirror.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", - "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==", - "dev": true - }, - "lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmmirror.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmmirror.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - } - } - } - }, - "lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "requires": { - "tslib": "^2.0.3" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" - }, - "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==" - }, - "memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmmirror.com/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, - "requires": { - "fs-monkey": "^1.0.4" - } - }, - "merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==" - }, - "merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true - }, - "micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "requires": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "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==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "mini-css-extract-plugin": { - "version": "2.9.4", - "resolved": "https://registry.npmmirror.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.4.tgz", - "integrity": "sha512-ZWYT7ln73Hptxqxk2DxPU9MmapXRhxkJD6tkSR04dnQxm8BGu2hzgKLugK5yySD97u/8yy7Ma7E76k9ZdvtjkQ==", - "dev": true, - "requires": { - "schema-utils": "^4.0.0", - "tapable": "^2.2.1" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true - }, - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "module-alias": { - "version": "2.2.3", - "resolved": "https://registry.npmmirror.com/module-alias/-/module-alias-2.2.3.tgz", - "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==", - "dev": true - }, - "mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmmirror.com/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "requires": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - } - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "requires": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "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-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmmirror.com/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true - }, - "node-releases": { - "version": "2.0.21", - "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.21.tgz", - "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true - }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dev": true, - "requires": { - "path-key": "^2.0.0" - }, - "dependencies": { - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true - } - } - }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/on-headers/-/on-headers-1.1.0.tgz", - "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "8.4.2", - "resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "opener": { - "version": "1.5.2", - "resolved": "https://registry.npmmirror.com/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true - }, - "optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmmirror.com/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmmirror.com/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dev": true, - "requires": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "dependencies": { - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - } - } - }, - "parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", - "dev": true - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - }, - "dependencies": { - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - } - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-to-regexp": { - "version": "8.3.0", - "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==" - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pinia": { - "version": "2.1.6", - "resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.1.6.tgz", - "integrity": "sha512-bIU6QuE5qZviMmct5XwCesXelb5VavdOWKWaB17ggk++NUwQWWbP5YnsONTk3b752QkW9sACiR81rorpeOMSvQ==", - "requires": { - "@vue/devtools-api": "^6.5.0", - "vue-demi": ">=0.14.5" - }, - "dependencies": { - "vue-demi": { - "version": "0.14.10", - "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz", - "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", - "requires": {} - } - } - }, - "portfinder": { - "version": "1.0.38", - "resolved": "https://registry.npmmirror.com/portfinder/-/portfinder-1.0.38.tgz", - "integrity": "sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==", - "dev": true, - "requires": { - "async": "^3.2.6", - "debug": "^4.3.6" - } - }, - "postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "requires": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "dependencies": { - "picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - } - } - }, - "postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmmirror.com/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-colormin": { - "version": "5.3.1", - "resolved": "https://registry.npmmirror.com/postcss-colormin/-/postcss-colormin-5.3.1.tgz", - "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmmirror.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "dev": true, - "requires": {} - }, - "postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "dev": true, - "requires": {} - }, - "postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "dev": true, - "requires": {} - }, - "postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "dev": true, - "requires": {} - }, - "postcss-helpers": { - "version": "0.3.3", - "resolved": "https://registry.npmmirror.com/postcss-helpers/-/postcss-helpers-0.3.3.tgz", - "integrity": "sha512-VumiUcrpbxGlTBNQj6fUOkb/HNRUk/xYz8bNlhgVOdvk3yWEy4B+0nlDUZZM9mTVZ5bJoxUy7WT6z/4E7oMTgw==", - "dev": true, - "requires": { - "urijs": "^1.18.12" - } - }, - "postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmmirror.com/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dev": true, - "requires": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - }, - "dependencies": { - "semver": { - "version": "7.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true - } - } - }, - "postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmmirror.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" - } - }, - "postcss-merge-rules": { - "version": "5.1.4", - "resolved": "https://registry.npmmirror.com/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", - "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", - "dev": true, - "requires": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmmirror.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmmirror.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "requires": {} - }, - "postcss-modules-local-by-default": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", - "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^7.0.0", - "postcss-value-parser": "^4.1.0" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - } - } - }, - "postcss-modules-scope": { - "version": "3.2.1", - "resolved": "https://registry.npmmirror.com/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", - "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", - "dev": true, - "requires": { - "postcss-selector-parser": "^7.0.0" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - } - } - }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0" - } - }, - "postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "dev": true, - "requires": {} - }, - "postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", - "dev": true, - "requires": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmmirror.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", - "dev": true, - "requires": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-reduce-initial": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", - "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" - } - }, - "postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - } - }, - "postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-urlrewrite": { - "version": "0.2.2", - "resolved": "https://registry.npmmirror.com/postcss-urlrewrite/-/postcss-urlrewrite-0.2.2.tgz", - "integrity": "sha512-DxPSgykgHjoV4Z+ygvq2C5HkiuiKQQD74xpoNQSQuyi8zab9nODVtNKfnCN6BEv9VZrjpOGLGAf8BDvgG6EtHg==", - "dev": true, - "requires": { - "postcss-helpers": "^0.3.2" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmmirror.com/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "optional": true - }, - "pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "requires": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "progress-webpack-plugin": { - "version": "1.0.16", - "resolved": "https://registry.npmmirror.com/progress-webpack-plugin/-/progress-webpack-plugin-1.0.16.tgz", - "integrity": "sha512-sdiHuuKOzELcBANHfrupYo+r99iPRyOnw15qX+rNlVUqXGfjXdH4IgxriKwG1kNJwVswKQHMdj1hYZMcb9jFaA==", - "dev": true, - "requires": { - "chalk": "^2.1.0", - "figures": "^2.0.0", - "log-update": "^2.3.0" - } - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "dependencies": { - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - } - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, - "pump": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true - }, - "qs": { - "version": "6.14.0", - "resolved": "https://registry.npmmirror.com/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "requires": { - "side-channel": "^1.1.0" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-3.0.1.tgz", - "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.7.0", - "unpipe": "1.0.0" - }, - "dependencies": { - "iconv-lite": { - "version": "0.7.0", - "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.7.0.tgz", - "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmmirror.com/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true - }, - "renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "retry": { - "version": "0.13.1", - "resolved": "https://registry.npmmirror.com/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true - }, - "reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "router": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "requires": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-area-insets": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/safe-area-insets/-/safe-area-insets-1.4.1.tgz", - "integrity": "sha512-r/nRWTjFGhhm3w1Z6Kd/jY11srN+lHt2mNl1E/emQGW8ic7n3Avu4noibklfSM+Y34peNphHD/BSZecav0sXYQ==", - "dev": true - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sass": { - "version": "1.92.1", - "resolved": "https://registry.npmmirror.com/sass/-/sass-1.92.1.tgz", - "integrity": "sha512-ffmsdbwqb3XeyR8jJR6KelIXARM9bFQe8A6Q3W4Klmwy5Ckd5gz7jgUNHo4UOqutU5Sk1DtKLbpDP0nLCg1xqQ==", - "dev": true, - "requires": { - "@parcel/watcher": "^2.4.1", - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "dependencies": { - "chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "requires": { - "readdirp": "^4.0.1" - } - }, - "readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true - } - } - }, - "sass-loader": { - "version": "16.0.5", - "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-16.0.5.tgz", - "integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==", - "dev": true, - "requires": { - "neo-async": "^2.6.2" - } - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, - "requires": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - }, - "send": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", - "requires": { - "debug": "^4.3.5", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.1" - }, - "dependencies": { - "mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==" - }, - "mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "requires": { - "mime-db": "^1.54.0" - } - } - } - }, - "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmmirror.com/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true - } - } - }, - "serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", - "requires": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmmirror.com/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", - "dev": true - }, - "side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "requires": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - } - }, - "side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "requires": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - } - }, - "side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "requires": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - } - }, - "side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "requires": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "sirv": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/sirv/-/sirv-2.0.4.tgz", - "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", - "dev": true, - "requires": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmmirror.com/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "requires": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "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==", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", - "dev": true - }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmmirror.com/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmmirror.com/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmmirror.com/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "stackframe": { - "version": "1.3.4", - "resolved": "https://registry.npmmirror.com/stackframe/-/stackframe-1.3.4.tgz", - "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", - "dev": true - }, - "statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==" - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmmirror.com/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "requires": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - } - } - }, - "tapable": { - "version": "2.2.3", - "resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.2.3.tgz", - "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", - "dev": true - }, - "terser": { - "version": "5.44.0", - "resolved": "https://registry.npmmirror.com/terser/-/terser-5.44.0.tgz", - "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "5.3.14", - "resolved": "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", - "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "thread-loader": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/thread-loader/-/thread-loader-3.0.4.tgz", - "integrity": "sha512-ByaL2TPb+m6yArpqQUZvP+5S1mZtXsEP7nWKKlAUTm7fCml8kB5s1uI3+eHRP2bk5mVYfRSBI7FFf+tWEyLZwA==", - "dev": true, - "requires": { - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^4.1.0", - "loader-utils": "^2.0.0", - "neo-async": "^2.6.2", - "schema-utils": "^3.0.0" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - } - } - }, - "thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "requires": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "dependencies": { - "mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==" - }, - "mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "requires": { - "mime-db": "^1.54.0" - } - } - } - }, - "typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "devOptional": true - }, - "undici-types": { - "version": "7.12.0", - "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.12.0.tgz", - "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", - "dev": true - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "requires": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "dependencies": { - "picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - } - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urijs": { - "version": "1.19.11", - "resolved": "https://registry.npmmirror.com/urijs/-/urijs-1.19.11.tgz", - "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "utila": { - "version": "0.4.0", - "resolved": "https://registry.npmmirror.com/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - }, - "vue": { - "version": "2.6.14", - "resolved": "https://registry.npmmirror.com/vue/-/vue-2.6.14.tgz", - "integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==" - }, - "vue-eslint-parser": { - "version": "9.4.3", - "resolved": "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", - "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", - "dev": true, - "requires": { - "debug": "^4.3.4", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.6" - }, - "dependencies": { - "semver": { - "version": "7.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true - } - } - }, - "vue-hot-reload-api": { - "version": "2.3.4", - "resolved": "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", - "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", - "dev": true - }, - "vue-loader": { - "version": "17.4.2", - "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-17.4.2.tgz", - "integrity": "sha512-yTKOA4R/VN4jqjw4y5HrynFL8AK0Z3/Jt7eOJXEitsm0GMRHDBjCfCiuTiLP7OESvsZYo2pATCWhDqxC5ZrM6w==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "watchpack": "^2.4.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "vue-router": { - "version": "3.6.5", - "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-3.6.5.tgz", - "integrity": "sha512-VYXZQLtjuvKxxcshuRAwjHnciqZVoXAjTjcqBTz4rKc8qih9g9pI3hbDjmqXaHdgL3v8pV6P8Z335XvHzESxLQ==" - }, - "vue-style-loader": { - "version": "4.1.3", - "resolved": "https://registry.npmmirror.com/vue-style-loader/-/vue-style-loader-4.1.3.tgz", - "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", - "dev": true, - "requires": { - "hash-sum": "^1.0.2", - "loader-utils": "^1.0.2" - }, - "dependencies": { - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", - "dev": true - } - } - }, - "vue-template-compiler": { - "version": "2.6.14", - "resolved": "https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz", - "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==", - "requires": { - "de-indent": "^1.0.2", - "he": "^1.1.0" - } - }, - "vue-template-es2015-compiler": { - "version": "1.9.1", - "resolved": "https://registry.npmmirror.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", - "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", - "dev": true - }, - "watchpack": { - "version": "2.4.4", - "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.4.tgz", - "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmmirror.com/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "webpack": { - "version": "5.101.3", - "resolved": "https://registry.npmmirror.com/webpack/-/webpack-5.101.3.tgz", - "integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.24.0", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.3", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.2", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.11", - "watchpack": "^2.4.1", - "webpack-sources": "^3.3.3" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } - } - }, - "webpack-bundle-analyzer": { - "version": "4.10.2", - "resolved": "https://registry.npmmirror.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", - "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "0.5.7", - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "commander": "^7.2.0", - "debounce": "^1.2.1", - "escape-string-regexp": "^4.0.0", - "gzip-size": "^6.0.0", - "html-escaper": "^2.0.2", - "opener": "^1.5.2", - "picocolors": "^1.0.0", - "sirv": "^2.0.3", - "ws": "^7.3.1" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "ws": { - "version": "7.5.10", - "resolved": "https://registry.npmmirror.com/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true, - "requires": {} - } - } - }, - "webpack-chain": { - "version": "6.5.1", - "resolved": "https://registry.npmmirror.com/webpack-chain/-/webpack-chain-6.5.1.tgz", - "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==", - "dev": true, - "requires": { - "deepmerge": "^1.5.2", - "javascript-stringify": "^2.0.1" - } - }, - "webpack-dev-middleware": { - "version": "5.3.4", - "resolved": "https://registry.npmmirror.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", - "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", - "dev": true, - "requires": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } - } - }, - "webpack-dev-server": { - "version": "4.15.2", - "resolved": "https://registry.npmmirror.com/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", - "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", - "dev": true, - "requires": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.4", - "ws": "^8.13.0" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - } - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "requires": { - "safe-buffer": "5.2.1" - } - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "express": { - "version": "4.21.2", - "resolved": "https://registry.npmmirror.com/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true - }, - "merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "dev": true - }, - "qs": { - "version": "6.13.0", - "resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dev": true, - "requires": { - "side-channel": "^1.0.6" - } - }, - "raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - }, - "send": { - "version": "0.19.0", - "resolved": "https://registry.npmmirror.com/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmmirror.com/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "dev": true, - "requires": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - } - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - } - } - }, - "webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", - "dev": true - }, - "webpack-virtual-modules": { - "version": "0.4.6", - "resolved": "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.4.6.tgz", - "integrity": "sha512-5tyDlKLqPfMqjT3Q9TAqf2YqjwmnUleZwzJi1A5qXnlBCdj2AtOJ6wAWdglTIDOPgOiOrXeBeFcsQ8+aGQ6QbA==", - "dev": true - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmmirror.com/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "whatwg-fetch": { - "version": "3.6.20", - "resolved": "https://registry.npmmirror.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", - "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", - "dev": true - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - }, - "word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "ws": { - "version": "8.18.0", - "resolved": "https://registry.npmmirror.com/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "requires": {} - }, - "xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmmirror.com/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/mini_program/farm-monitor-dashboard/package.json b/mini_program/farm-monitor-dashboard/package.json deleted file mode 100644 index e34eac1..0000000 --- a/mini_program/farm-monitor-dashboard/package.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "farm-monitor-dashboard", - "version": "1.0.0", - "description": "养殖端微信小程序 - 原生版本", - "main": "app.js", - "scripts": { - "dev": "echo '请在微信开发者工具中打开项目进行开发'", - "build": "echo '请在微信开发者工具中构建项目'", - "test": "echo '测试功能'", - "lint": "echo '代码检查'" - }, - "keywords": [ - "微信小程序", - "养殖管理", - "物联网", - "智能设备", - "农业科技" - ], - "author": "养殖管理系统开发团队", - "license": "MIT", - "engines": { - "node": ">=16.0.0" - }, - "repository": { - "type": "git", - "url": "https://github.com/your-org/farm-monitor-dashboard.git" - }, - "bugs": { - "url": "https://github.com/your-org/farm-monitor-dashboard/issues" - }, - "homepage": "https://github.com/your-org/farm-monitor-dashboard#readme", - "dependencies": { - "dayjs": "^1.11.0" - }, - "devDependencies": { - "eslint": "^8.45.0" - } -} \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/pages/device/collar/collar.js b/mini_program/farm-monitor-dashboard/pages/device/collar/collar.js new file mode 100644 index 0000000..e33c7c9 --- /dev/null +++ b/mini_program/farm-monitor-dashboard/pages/device/collar/collar.js @@ -0,0 +1,84 @@ + +// 状态映射 +const statusMap = { + 'online': '在线', + 'offline': '离线', + 'alarm': '告警' +} + +Page({ + data: { + list: [], // 项圈数据列表 + searchValue: '', // 搜索值 + currentPage: 1, // 当前页码 + total: 0, // 总数据量 + pageSize: 10 // 每页数量 + }, + + onLoad() { + this.loadData() + }, + + // 加载数据 + loadData() { + const { currentPage, pageSize, searchValue } = this.data + const url = `https://ad.ningmuyun.com/api/smart-devices/collars?page=${currentPage}&limit=${pageSize}&deviceId=${searchValue}&_t=${Date.now()}` + + wx.showLoading({ title: '加载中...' }) + wx.request({ + url, + header: { + 'Authorization': 'Bearer ' + getApp().globalData.token // 添加认证头 + }, + success: (res) => { + if (res.statusCode === 200 && res.data && res.data.data) { + const data = res.data.data + this.setData({ + list: (data.items || []).map(item => ({ + ...item, + statusText: statusMap[item.status] || item.status + })), + total: data.total || 0 + }) + } else { + wx.showToast({ + title: res.data.message || '数据加载失败', + icon: 'none' + }) + } + }, + fail: (err) => { + wx.showToast({ + title: err.errMsg.includes('401') ? '请登录后重试' : '请求失败', + icon: 'none' + }) + console.error(err) + }, + complete: () => wx.hideLoading() + }) + }, + + // 搜索输入 + onSearchInput(e) { + this.setData({ searchValue: e.detail.value.trim() }) + }, + + // 执行搜索 + onSearch() { + this.setData({ currentPage: 1 }, () => this.loadData()) + }, + + // 分页切换 + onPageChange(e) { + const page = parseInt(e.currentTarget.dataset.page) + if (page !== this.data.currentPage) { + this.setData({ currentPage: page }, () => this.loadData()) + } + }, + + // 计算分页数组 + getPages(total, pageSize, currentPage) { + const pageCount = Math.ceil(total / pageSize) + return Array.from({ length: pageCount }, (_, i) => i + 1) + } +}) \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/pages/device/collar/collar.json b/mini_program/farm-monitor-dashboard/pages/device/collar/collar.json new file mode 100644 index 0000000..0804c9d --- /dev/null +++ b/mini_program/farm-monitor-dashboard/pages/device/collar/collar.json @@ -0,0 +1,5 @@ + +{ + "usingComponents": {}, + "navigationBarTitleText": "智能项圈管理" +} \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/pages/device/collar/collar.wxml b/mini_program/farm-monitor-dashboard/pages/device/collar/collar.wxml new file mode 100644 index 0000000..eda51a3 --- /dev/null +++ b/mini_program/farm-monitor-dashboard/pages/device/collar/collar.wxml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + 项圈编号: {{item.deviceId}} + 状态: {{item.status | statusText}} + 电量: {{item.battery}}% + 最后在线: {{item.lastOnlineTime}} + + + + + + + + + {{item}} + + + + \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/pages/device/collar/collar.wxss b/mini_program/farm-monitor-dashboard/pages/device/collar/collar.wxss new file mode 100644 index 0000000..55eff87 --- /dev/null +++ b/mini_program/farm-monitor-dashboard/pages/device/collar/collar.wxss @@ -0,0 +1,46 @@ + +.container { + padding: 20rpx; +} + +.search-box { + display: flex; + margin-bottom: 20rpx; +} + +.search-box input { + flex: 1; + border: 1rpx solid #ddd; + padding: 10rpx 20rpx; + margin-right: 20rpx; +} + +.list { + margin-bottom: 30rpx; +} + +.item { + padding: 20rpx; + border-bottom: 1rpx solid #eee; +} + +.item text { + display: block; + margin-bottom: 10rpx; +} + +.pagination { + display: flex; + justify-content: center; +} + +.pagination text { + margin: 0 10rpx; + padding: 5rpx 15rpx; + border: 1rpx solid #ddd; +} + +.pagination .active { + background-color: #07C160; + color: white; +} \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/pages/device/eartag-detail/eartag-detail.js b/mini_program/farm-monitor-dashboard/pages/device/eartag-detail/eartag-detail.js index 68b46d8..89a243b 100644 --- a/mini_program/farm-monitor-dashboard/pages/device/eartag-detail/eartag-detail.js +++ b/mini_program/farm-monitor-dashboard/pages/device/eartag-detail/eartag-detail.js @@ -28,27 +28,112 @@ Page({ this.setData({ loading: true }) try { - // 这里可以调用具体的耳标详情API - // const response = await get(`/api/iot-jbq-client/${eartagId}`) + // 获取token + const token = wx.getStorageSync('token') + console.log('详情页获取token:', token) - // 暂时使用模拟数据 - const mockData = { - eartagNumber: eartagId, - isBound: false, - batteryLevel: 39, - temperature: 28.7, - hostNumber: '23107000007', - totalMovement: 3316, - todayMovement: 0, - updateTime: '2025-09-23 01:17:52' + if (!token) { + console.log('未找到token,跳转到登录页') + wx.showToast({ + title: '请先登录', + icon: 'none' + }) + setTimeout(() => { + wx.navigateTo({ + url: '/pages/login/login' + }) + }, 1500) + return } - this.setData({ eartagData: mockData }) + // 验证token格式 + if (!token.startsWith('eyJ')) { + console.log('token格式不正确,清除并重新登录') + wx.removeStorageSync('token') + wx.removeStorageSync('userInfo') + wx.showToast({ + title: '登录已过期,请重新登录', + icon: 'none' + }) + setTimeout(() => { + wx.navigateTo({ + url: '/pages/login/login' + }) + }, 1500) + return + } + + // 调用私有API获取耳标列表,然后筛选出指定耳标 + const response = await new Promise((resolve, reject) => { + wx.request({ + url: 'https://ad.ningmuyun.com/api/smart-devices/eartags', + method: 'GET', + data: { + page: 1, + limit: 1000, // 获取足够多的数据 + refresh: true, + _t: Date.now() + }, + header: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, + timeout: 10000, + success: (res) => { + console.log('耳标列表API调用成功:', res) + if (res.statusCode === 401) { + console.log('收到401错误,清除token并跳转登录页') + wx.removeStorageSync('token') + wx.removeStorageSync('userInfo') + wx.showToast({ + title: '登录已过期,请重新登录', + icon: 'none' + }) + setTimeout(() => { + wx.navigateTo({ + url: '/pages/login/login' + }) + }, 1500) + reject(new Error('未授权,请重新登录')) + } else { + resolve(res) + } + }, + fail: (error) => { + console.log('耳标列表API调用失败:', error) + reject(error) + } + }) + }) + + console.log('耳标列表API响应:', response) + + if (response.statusCode === 200 && response.data.success) { + // 从列表中查找指定的耳标 + const eartagList = response.data.data || [] + const targetEartag = eartagList.find(item => + item.cid == eartagId || + item.eartagNumber == eartagId || + item.sn == eartagId || + item.id == eartagId + ) + + if (targetEartag) { + // 处理API数据 + const processedData = this.processEartagDetailData(targetEartag) + console.log('处理后的详情数据:', processedData) + this.setData({ eartagData: processedData }) + } else { + throw new Error('未找到指定的耳标') + } + } else { + throw new Error(response.data.message || '获取详情失败') + } } catch (error) { console.error('获取耳标详情失败:', error) wx.showToast({ - title: '获取数据失败', + title: error.message || '获取数据失败', icon: 'none' }) } finally { @@ -56,6 +141,115 @@ Page({ } }, + // 处理耳标详情数据 + processEartagDetailData(apiData) { + try { + console.log('处理耳标详情数据,原始数据:', apiData) + + const processedData = { + eartagNumber: apiData.cid || apiData.eartagNumber || apiData.sn || apiData.id || '未知', + isBound: this.checkIfBound(apiData), + batteryLevel: this.formatBatteryLevel(apiData), + temperature: this.formatTemperature(apiData), + hostNumber: this.formatHostNumber(apiData), + totalMovement: this.formatMovement(apiData.totalMovement || apiData.dailyMovement || apiData.walk || apiData.steps || 0), + todayMovement: this.formatMovement(apiData.dailyMovement || apiData['walk-y_steps'] || apiData.todayMovement || 0), + updateTime: this.formatUpdateTime(apiData.lastUpdate || apiData.updateTime || new Date().toISOString()), + // 新增字段 + wearStatus: apiData.wearStatus || '未知', + deviceStatus: apiData.deviceStatus || '未知', + gpsState: apiData.gps_state || '未知', + location: apiData.location || '无定位', + latitude: apiData.lat || '0', + longitude: apiData.lon || '0', + bindingStatus: apiData.bindingStatus || '未知', + voltage: apiData.voltage || '0', + rawData: apiData // 保存原始数据用于调试 + } + + console.log('处理后的详情数据:', processedData) + return processedData + } catch (error) { + console.error('处理耳标详情数据失败:', error) + return { + eartagNumber: '处理失败', + isBound: false, + batteryLevel: 0, + temperature: '0.0', + hostNumber: '未知', + totalMovement: '0', + todayMovement: '0', + updateTime: '未知时间', + wearStatus: '未知', + deviceStatus: '未知', + gpsState: '未知', + location: '无定位', + latitude: '0', + longitude: '0', + bindingStatus: '未知', + voltage: '0' + } + } + }, + + // 检查是否已绑定 + checkIfBound(item) { + if (item.bindingStatus === '已绑定') return true + if (item.bindingStatus === '未绑定') return false + if (item.isBound !== undefined) return item.isBound + if (item.is_bound !== undefined) return item.is_bound + if (item.bound !== undefined) return item.bound + if (item.bandge_status !== undefined) return item.bandge_status === 1 + if (item.is_wear !== undefined) return item.is_wear === 1 + if (item.status === 'bound' || item.status === '已绑定') return true + if (item.status === 'unbound' || item.status === '未绑定') return false + return !!(item.cattleId || item.cattle_id || item.animalId || item.animal_id) + }, + + // 格式化电量 + formatBatteryLevel(item) { + const battery = item.voltage || item.battery || item.batteryPercent || item.batteryLevel || item.battery_level || item.power || 0 + return Math.round(parseFloat(battery)) || 0 + }, + + // 格式化温度 + formatTemperature(item) { + const temp = item.temperature || item.temp || item.device_temp || 0 + return parseFloat(temp).toFixed(1) || '0.0' + }, + + // 格式化主机号 + formatHostNumber(item) { + return item.sid || item.collectedHost || item.deviceInfo || item.hostNumber || item.host_number || item.hostId || item.host_id || item.collector || '未知主机' + }, + + // 格式化运动量 + formatMovement(movement) { + const value = parseInt(movement) || 0 + return value.toString() + }, + + // 格式化更新时间 + formatUpdateTime(timeStr) { + if (!timeStr) return '未知时间' + + try { + const date = new Date(timeStr) + if (isNaN(date.getTime())) return timeStr + + return date.toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }).replace(/\//g, '-') + } catch (error) { + return timeStr + } + }, + // 返回上一页 goBack() { wx.navigateBack() diff --git a/mini_program/farm-monitor-dashboard/pages/device/eartag-detail/eartag-detail.wxml b/mini_program/farm-monitor-dashboard/pages/device/eartag-detail/eartag-detail.wxml index 92394b6..5392eb8 100644 --- a/mini_program/farm-monitor-dashboard/pages/device/eartag-detail/eartag-detail.wxml +++ b/mini_program/farm-monitor-dashboard/pages/device/eartag-detail/eartag-detail.wxml @@ -44,6 +44,46 @@ {{eartagData.todayMovement}} + + 佩戴状态 + {{eartagData.wearStatus}} + + + + 设备状态 + {{eartagData.deviceStatus}} + + + + 位置信息 + {{eartagData.location}} + + + + GPS状态 + {{eartagData.gpsState}} + + + + 纬度 + {{eartagData.latitude}} + + + + 经度 + {{eartagData.longitude}} + + + + 绑定状态 + {{eartagData.bindingStatus}} + + + + 电压值 + {{eartagData.voltage}}V + + 数据更新时间 {{eartagData.updateTime}} diff --git a/mini_program/farm-monitor-dashboard/pages/device/eartag/eartag.js b/mini_program/farm-monitor-dashboard/pages/device/eartag/eartag.js index 6d2d886..467a537 100644 --- a/mini_program/farm-monitor-dashboard/pages/device/eartag/eartag.js +++ b/mini_program/farm-monitor-dashboard/pages/device/eartag/eartag.js @@ -4,7 +4,7 @@ const { formatTime } = require('../../../utils/index') Page({ data: { - loading: false, + loading: false, // 初始状态设为未加载 searchKeyword: '', currentFilter: 'all', // all, bound, unbound filterTabs: [ @@ -14,15 +14,35 @@ Page({ ], allEartagList: [], // 所有耳标数据 eartagList: [], // 当前显示的耳标列表 - originalData: [] // 原始API数据 + originalData: [], // 原始API数据 + + // 分页相关 + currentPage: 1, + pageSize: 10, + totalPages: 0, + totalCount: 0, + paginationList: [] // 分页页码列表 }, onLoad() { + console.log('eartag页面onLoad执行') + // 页面加载时获取数据 this.fetchEartagData() }, + onReady() { + console.log('eartag页面onReady执行') + // 页面加载完成 + }, + onShow() { - this.fetchEartagData() + console.log('eartag页面onShow执行') + // 页面显示时检查是否需要刷新数据 + // 避免重复加载,只在必要时刷新 + if (this.data.currentPage === 1 && this.data.eartagList.length === 0) { + console.log('onShow中调用fetchEartagData') + this.fetchEartagData() + } }, onPullDownRefresh() { @@ -32,90 +52,273 @@ Page({ }, // 获取耳标数据 - async fetchEartagData() { - this.setData({ loading: true }) + async fetchEartagData(page = 1) { + console.log('fetchEartagData函数被调用,page:', page) + + // 防止重复请求 + if (this.data.loading) { + console.log('正在加载中,跳过重复请求') + return + } + + console.log('设置loading状态为true') + this.setData({ loading: true, currentPage: page }) try { // 使用真实的智能耳标API接口(公开API,无需认证) - const response = await get('/smart-devices/public/eartags?page=1&limit=10&refresh=true') - console.log('智能耳标API响应:', response) + console.log('开始调用API...') - // 处理真实的API数据 - const processedData = this.processApiData(response) + // 使用私有API端点,需要认证 + const token = wx.getStorageSync('token') + console.log('当前token:', token) + console.log('token是否存在:', !!token) + console.log('token长度:', token ? token.length : 0) + + if (!token) { + console.log('未找到token,跳转到登录页') + wx.showToast({ + title: '请先登录', + icon: 'none' + }) + setTimeout(() => { + wx.navigateTo({ + url: '/pages/login/login' + }) + }, 1500) + return + } + + // 验证token格式 + if (!token.startsWith('eyJ')) { + console.log('token格式不正确,清除并重新登录') + wx.removeStorageSync('token') + wx.removeStorageSync('userInfo') + wx.showToast({ + title: '登录已过期,请重新登录', + icon: 'none' + }) + setTimeout(() => { + wx.navigateTo({ + url: '/pages/login/login' + }) + }, 1500) + return + } + + const requestHeaders = { + 'Content-Type': 'application/json', + ...(token ? { 'Authorization': `Bearer ${token}` } : {}) + } + console.log('请求头:', requestHeaders) + + const response = await new Promise((resolve, reject) => { + wx.request({ + url: 'https://ad.ningmuyun.com/api/smart-devices/eartags', + method: 'GET', + data: { + page: page, + limit: this.data.pageSize, + refresh: true, + _t: Date.now() + }, + header: requestHeaders, + timeout: 10000, + success: (res) => { + console.log('私有API调用成功:', res) + if (res.statusCode === 401) { + console.log('收到401错误,清除token并跳转登录页') + wx.removeStorageSync('token') + wx.removeStorageSync('userInfo') + wx.showToast({ + title: '登录已过期,请重新登录', + icon: 'none' + }) + setTimeout(() => { + wx.navigateTo({ + url: '/pages/login/login' + }) + }, 1500) + reject(new Error('未授权,请重新登录')) + } else { + resolve(res) + } + }, + fail: (error) => { + console.log('私有API调用失败:', error) + reject(error) + } + }) + }) + + console.log('API响应成功:', response) + + // 处理私有API数据 - 从response.data.data中获取数组数据 + console.log('完整响应结构:', response.data) + console.log('实际数据部分:', response.data?.data) + console.log('原始数据列表:', response.data?.data) + const processedData = this.processApiData(response.data?.data || []) + console.log('处理后的数据:', processedData) + + // 计算分页信息 + const totalCount = response.data?.total || response.data?.stats?.total || 0 + const totalPages = Math.ceil(totalCount / this.data.pageSize) + const paginationList = this.generatePaginationList(page, totalPages) + + console.log('分页信息:', { + totalCount: totalCount, + totalPages: totalPages, + currentPage: page, + pageSize: this.data.pageSize + }) this.setData({ originalData: response, allEartagList: processedData, - eartagList: processedData + eartagList: processedData, + totalCount: totalCount, + totalPages: totalPages, + paginationList: paginationList }) - // 更新筛选标签计数 - this.updateFilterCounts(processedData) + // 更新筛选标签计数 - 使用原始数据列表 + this.updateFilterCounts(response.data?.data || []) } catch (error) { console.error('获取耳标数据失败:', error) + + // 根据错误类型显示不同的提示 + let errorMessage = '获取数据失败' + if (error.message === '请求超时') { + errorMessage = '网络超时,请检查网络连接' + } else if (error.message && error.message.includes('timeout')) { + errorMessage = '请求超时,请重试' + } else if (error.message && error.message.includes('fail')) { + errorMessage = '网络连接失败' + } + wx.showToast({ - title: '获取数据失败', - icon: 'none' + title: errorMessage, + icon: 'none', + duration: 3000 }) + + // 如果是第一页加载失败,设置空数据状态 + if (page === 1) { + this.setData({ + eartagList: [], + allEartagList: [], + totalCount: 0, + totalPages: 0, + paginationList: [] + }) + } } finally { this.setData({ loading: false }) } }, - // 将API数据映射为耳标格式(演示动态字段映射) - mapApiDataToEartags(apiData) { - if (!apiData || !Array.isArray(apiData)) { - return [] - } - - return apiData.map((item, index) => ({ - eartagNumber: `E${String(item.id).padStart(3, '0')}`, // 耳标编号 - batteryLevel: Math.floor(Math.random() * 100), // 电量 - temperature: (36.5 + Math.random() * 2).toFixed(1), // 体温 - heartRate: Math.floor(60 + Math.random() * 40), // 心率 - location: `位置${item.id}`, // 位置 - bindingStatus: Math.random() > 0.5 ? '已绑定' : '未绑定', // 绑定状态 - lastUpdateTime: new Date().toLocaleString(), // 最后更新时间 - cattleId: item.id, // 牛只ID - cattleName: `牛只${item.id}`, // 牛只名称 - farmId: item.userId, // 养殖场ID - farmName: `养殖场${item.userId}`, // 养殖场名称 - signalStrength: Math.floor(Math.random() * 5) + 1, // 信号强度 - isOnline: Math.random() > 0.2, // 在线状态 - alertCount: Math.floor(Math.random() * 5), // 预警数量 - originalData: item // 保留原始数据 - })) - }, // 处理API数据,进行字段映射和中文转换 processApiData(apiData) { - if (!apiData || !Array.isArray(apiData)) { + try { + if (!apiData || !Array.isArray(apiData)) { + console.log('API数据为空或不是数组:', apiData) + return [] + } + + const processedData = apiData.map((item, index) => { + try { + // 调试:显示完整API字段结构 + if (index === 0) { + console.log('完整API字段结构调试:', { + 'cid (耳标编号)': item.cid, + 'voltage (电量)': item.voltage, + 'sid (主机号)': item.sid, + 'totalMovement (总运动量)': item.totalMovement, + 'dailyMovement (今日运动量)': item.dailyMovement, + 'temperature (温度)': item.temperature, + 'bindingStatus (绑定状态)': item.bindingStatus, + 'wearStatus (佩戴状态)': item.wearStatus, + 'deviceStatus (设备状态)': item.deviceStatus, + 'gps_state (GPS状态)': item.gps_state, + 'location (位置信息)': item.location, + 'lat (纬度)': item.lat, + 'lon (经度)': item.lon, + 'lastUpdate (更新时间)': item.lastUpdate + }) + } + + // 字段映射和中文转换 - 根据完整API字段结构 + const processedItem = { + eartagNumber: item.cid || item.eartagNumber || item.sn || item.eartag_number || item.id || `EARTAG_${index + 1}`, + isBound: this.checkIfBound(item), + batteryLevel: this.formatBatteryLevel(item), + temperature: this.formatTemperature(item), + hostNumber: this.formatHostNumber(item), + totalMovement: this.formatMovement(item.totalMovement || item.dailyMovement || item.walk || item.steps || item.total_movement || item.movement_total || 0), + todayMovement: this.formatTodayMovement(item), + updateTime: this.formatUpdateTime(item.lastUpdate || item.updateTime || item.update_time || item.last_update || new Date().toISOString()), + // 新增字段 + wearStatus: item.wearStatus || '未知', + deviceStatus: item.deviceStatus || '未知', + gpsState: item.gps_state || '未知', + location: item.location || '无定位', + latitude: item.lat || '0', + longitude: item.lon || '0', + rawData: item // 保存原始数据用于调试 + } + + // 调试:显示字段映射结果 + if (index === 0) { + console.log('字段映射结果调试:', { + 'eartagNumber': processedItem.eartagNumber, + 'batteryLevel': processedItem.batteryLevel, + 'temperature': processedItem.temperature, + 'hostNumber': processedItem.hostNumber, + 'totalMovement': processedItem.totalMovement, + 'todayMovement': processedItem.todayMovement, + 'wearStatus': processedItem.wearStatus, + 'deviceStatus': processedItem.deviceStatus, + 'location': processedItem.location, + 'updateTime': processedItem.updateTime + }) + } + + return processedItem + } catch (itemError) { + console.error('处理单个数据项失败:', item, itemError) + return { + eartagNumber: `ERROR_${index + 1}`, + isBound: false, + batteryLevel: 0, + temperature: '0.0', + hostNumber: '错误', + totalMovement: '0', + todayMovement: '0', + updateTime: '错误', + rawData: item + } + } + }) + + console.log('数据处理完成,共处理', processedData.length, '条数据') + return processedData + } catch (error) { + console.error('数据处理失败:', error) return [] } - - return apiData.map((item, index) => { - // 字段映射和中文转换 - return { - eartagNumber: item.eartagNumber || item.eartag_number || item.id || `EARTAG_${index + 1}`, - isBound: this.checkIfBound(item), - batteryLevel: this.formatBatteryLevel(item), - temperature: this.formatTemperature(item), - hostNumber: this.formatHostNumber(item), - totalMovement: this.formatMovement(item.totalMovement || item.total_movement || item.movement_total || 0), - todayMovement: this.formatMovement(item.todayMovement || item.today_movement || item.movement_today || 0), - updateTime: this.formatUpdateTime(item.updateTime || item.update_time || item.last_update || new Date().toISOString()), - rawData: item // 保存原始数据用于调试 - } - }) }, // 检查是否已绑定 checkIfBound(item) { - // 根据实际API字段判断绑定状态 + // 根据真实API字段判断绑定状态 + if (item.bindingStatus === '已绑定') return true + if (item.bindingStatus === '未绑定') return false if (item.isBound !== undefined) return item.isBound if (item.is_bound !== undefined) return item.is_bound if (item.bound !== undefined) return item.bound + if (item.bandge_status !== undefined) return item.bandge_status === 1 + if (item.is_wear !== undefined) return item.is_wear === 1 if (item.status === 'bound' || item.status === '已绑定') return true if (item.status === 'unbound' || item.status === '未绑定') return false @@ -123,21 +326,21 @@ Page({ return !!(item.cattleId || item.cattle_id || item.animalId || item.animal_id) }, - // 格式化电量 + // 格式化电量 - 优先使用voltage字段(完整API字段) formatBatteryLevel(item) { - const battery = item.batteryLevel || item.battery_level || item.battery || item.power || 0 + const battery = item.voltage || item.battery || item.batteryPercent || item.batteryLevel || item.battery_level || item.power || 0 return Math.round(parseFloat(battery)) || 0 }, - // 格式化温度 + // 格式化温度 - 使用temperature字段 formatTemperature(item) { const temp = item.temperature || item.temp || item.device_temp || 0 return parseFloat(temp).toFixed(1) || '0.0' }, - // 格式化主机号 + // 格式化主机号 - 优先使用sid字段(完整API字段) formatHostNumber(item) { - return item.hostNumber || item.host_number || item.hostId || item.host_id || item.collector || '未知主机' + return item.sid || item.collectedHost || item.deviceInfo || item.hostNumber || item.host_number || item.hostId || item.host_id || item.collector || '未知主机' }, // 格式化运动量 @@ -146,6 +349,123 @@ Page({ return value.toString() }, + // 格式化今日运动量 - 优先使用dailyMovement字段(完整API字段) + formatTodayMovement(item) { + const todayMovement = item.dailyMovement || item['walk-y_steps'] || item.todayMovement || item.today_movement || item.movement_today || 0 + return this.formatMovement(todayMovement) + }, + + // 生成分页页码列表 + generatePaginationList(currentPage, totalPages) { + const paginationList = [] + const maxVisiblePages = 5 // 最多显示5个页码 + + if (totalPages <= maxVisiblePages) { + // 总页数少于等于5页,显示所有页码 + for (let i = 1; i <= totalPages; i++) { + paginationList.push({ + page: i, + active: i === currentPage, + text: i.toString() + }) + } + } else { + // 总页数大于5页,显示省略号 + if (currentPage <= 3) { + // 当前页在前3页 + for (let i = 1; i <= 4; i++) { + paginationList.push({ + page: i, + active: i === currentPage, + text: i.toString() + }) + } + paginationList.push({ + page: -1, + active: false, + text: '...' + }) + paginationList.push({ + page: totalPages, + active: false, + text: totalPages.toString() + }) + } else if (currentPage >= totalPages - 2) { + // 当前页在后3页 + paginationList.push({ + page: 1, + active: false, + text: '1' + }) + paginationList.push({ + page: -1, + active: false, + text: '...' + }) + for (let i = totalPages - 3; i <= totalPages; i++) { + paginationList.push({ + page: i, + active: i === currentPage, + text: i.toString() + }) + } + } else { + // 当前页在中间 + paginationList.push({ + page: 1, + active: false, + text: '1' + }) + paginationList.push({ + page: -1, + active: false, + text: '...' + }) + for (let i = currentPage - 1; i <= currentPage + 1; i++) { + paginationList.push({ + page: i, + active: i === currentPage, + text: i.toString() + }) + } + paginationList.push({ + page: -1, + active: false, + text: '...' + }) + paginationList.push({ + page: totalPages, + active: false, + text: totalPages.toString() + }) + } + } + + return paginationList + }, + + // 跳转到指定页面 + goToPage(e) { + const page = e.currentTarget.dataset.page + if (page > 0 && page !== this.data.currentPage) { + this.fetchEartagData(page) + } + }, + + // 上一页 + prevPage() { + if (this.data.currentPage > 1) { + this.fetchEartagData(this.data.currentPage - 1) + } + }, + + // 下一页 + nextPage() { + if (this.data.currentPage < this.data.totalPages) { + this.fetchEartagData(this.data.currentPage + 1) + } + }, + // 格式化更新时间 formatUpdateTime(timeStr) { if (!timeStr) return '未知时间' @@ -167,26 +487,239 @@ Page({ } }, - // 更新筛选标签计数 - updateFilterCounts(data) { - const totalCount = data.length - const boundCount = data.filter(item => item.isBound).length - const unboundCount = totalCount - boundCount + // 更新筛选标签计数 - 获取所有数据的总数 + async updateFilterCounts(data) { + try { + // 获取token + const token = wx.getStorageSync('token') + if (!token) { + console.log('未找到token,无法获取统计数据') + return + } - const filterTabs = this.data.filterTabs.map(tab => ({ - ...tab, - count: tab.type === 'all' ? totalCount : - tab.type === 'bound' ? boundCount : unboundCount - })) + // 调用API获取所有数据的总数(不受分页限制) + const response = await new Promise((resolve, reject) => { + wx.request({ + url: 'https://ad.ningmuyun.com/api/smart-devices/eartags', + method: 'GET', + data: { + page: 1, + limit: 10000, // 获取足够多的数据来统计 + refresh: true, + _t: Date.now() + }, + header: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, + timeout: 10000, + success: (res) => { + console.log('统计数据API调用成功:', res) + resolve(res) + }, + fail: (error) => { + console.log('统计数据API调用失败:', error) + reject(error) + } + }) + }) - this.setData({ filterTabs }) + if (response.statusCode === 200 && response.data.success) { + const allData = response.data.data || [] + const totalCount = allData.length + const boundCount = allData.filter(item => { + return item.bindingStatus === '已绑定' || + item.isBound === true || + item.bound === true || + item.is_bound === 1 || + item.bandge_status === 1 + }).length + const unboundCount = totalCount - boundCount + + console.log('统计数据:', { totalCount, boundCount, unboundCount }) + + const filterTabs = this.data.filterTabs.map(tab => ({ + ...tab, + count: tab.type === 'all' ? totalCount : + tab.type === 'bound' ? boundCount : unboundCount + })) + + this.setData({ filterTabs }) + } + } catch (error) { + console.error('获取统计数据失败:', error) + // 如果API调用失败,使用当前数据计算 + const totalCount = data.length + const boundCount = data.filter(item => { + return item.bindingStatus === '已绑定' || + item.isBound === true || + item.bound === true || + item.is_bound === 1 || + item.bandge_status === 1 + }).length + const unboundCount = totalCount - boundCount + + const filterTabs = this.data.filterTabs.map(tab => ({ + ...tab, + count: tab.type === 'all' ? totalCount : + tab.type === 'bound' ? boundCount : unboundCount + })) + + this.setData({ filterTabs }) + } }, // 搜索输入 onSearchInput(e) { const keyword = e.detail.value this.setData({ searchKeyword: keyword }) - this.filterEartagList() + + // 防抖处理,避免频繁请求 + if (this.searchTimer) { + clearTimeout(this.searchTimer) + } + + this.searchTimer = setTimeout(() => { + this.performSearch(keyword) + }, 500) // 500ms防抖 + }, + + // 搜索确认 + onSearchConfirm(e) { + const keyword = e.detail.value + this.setData({ searchKeyword: keyword }) + + // 清除防抖定时器,立即执行搜索 + if (this.searchTimer) { + clearTimeout(this.searchTimer) + } + + this.performSearch(keyword) + }, + + // 执行搜索 - 按耳标编号精确查找 + async performSearch(keyword) { + if (!keyword || keyword.trim() === '') { + // 如果搜索关键词为空,重新加载第一页数据 + this.fetchEartagData(1) + return + } + + this.setData({ loading: true }) + + try { + // 获取token + const token = wx.getStorageSync('token') + if (!token) { + wx.showToast({ + title: '请先登录', + icon: 'none' + }) + return + } + + // 调用私有API获取所有数据,然后进行客户端搜索 + const response = await new Promise((resolve, reject) => { + wx.request({ + url: 'https://ad.ningmuyun.com/api/smart-devices/eartags', + method: 'GET', + data: { + page: 1, + limit: 10000, // 获取所有数据进行搜索 + refresh: true, + _t: Date.now() + }, + header: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, + timeout: 10000, + success: (res) => { + console.log('搜索API调用成功:', res) + resolve(res) + }, + fail: (error) => { + console.log('搜索API调用失败:', error) + reject(error) + } + }) + }) + + if (response.statusCode === 200 && response.data.success) { + const allData = response.data.data || [] + + // 按耳标编号精确查找 + const searchResults = allData.filter(item => { + const cid = item.cid ? item.cid.toString() : '' + const eartagNumber = item.eartagNumber ? item.eartagNumber.toString() : '' + const sn = item.sn ? item.sn.toString() : '' + const id = item.id ? item.id.toString() : '' + + const searchKeyword = keyword.trim().toString() + + return cid === searchKeyword || + eartagNumber === searchKeyword || + sn === searchKeyword || + id === searchKeyword || + cid.includes(searchKeyword) || + eartagNumber.includes(searchKeyword) || + sn.includes(searchKeyword) + }) + + console.log('搜索结果:', searchResults) + + // 处理搜索结果 + const processedData = this.processApiData(searchResults) + + // 计算分页信息 + const totalCount = searchResults.length + const totalPages = Math.ceil(totalCount / this.data.pageSize) + const paginationList = this.generatePaginationList(1, totalPages) + + this.setData({ + originalData: response, + allEartagList: processedData, + eartagList: processedData, + totalCount: totalCount, + totalPages: totalPages, + paginationList: paginationList, + currentPage: 1 + }) + + // 更新筛选标签计数(基于搜索结果) + this.updateFilterCounts(searchResults) + + if (processedData.length === 0) { + wx.showToast({ + title: '未找到匹配的耳标', + icon: 'none' + }) + } else { + wx.showToast({ + title: `找到 ${processedData.length} 个匹配的耳标`, + icon: 'success' + }) + } + } else { + throw new Error(response.data.message || '搜索失败') + } + + } catch (error) { + console.error('搜索失败:', error) + wx.showToast({ + title: error.message || '搜索失败', + icon: 'none' + }) + } finally { + this.setData({ loading: false }) + } + }, + + // 清空搜索 + clearSearch() { + this.setData({ searchKeyword: '' }) + // 清空搜索后重新加载第一页数据 + this.fetchEartagData(1) }, // 切换筛选 diff --git a/mini_program/farm-monitor-dashboard/pages/device/eartag/eartag.wxml b/mini_program/farm-monitor-dashboard/pages/device/eartag/eartag.wxml index b4df5d6..bcc4dfc 100644 --- a/mini_program/farm-monitor-dashboard/pages/device/eartag/eartag.wxml +++ b/mini_program/farm-monitor-dashboard/pages/device/eartag/eartag.wxml @@ -71,6 +71,21 @@ {{item.todayMovement}} + + 佩戴状态: + {{item.wearStatus}} + + + + 设备状态: + {{item.deviceStatus}} + + + + 位置信息: + {{item.location}} + + 数据更新时间: {{item.updateTime}} @@ -90,4 +105,42 @@ 加载中... + + + + + 共 {{totalCount}} 条记录,第 {{currentPage}}/{{totalPages}} 页 + + + + + + 上一页 + + + + + + {{item.text}} + + + + + + 下一页 + + + diff --git a/mini_program/farm-monitor-dashboard/pages/device/eartag/eartag.wxss b/mini_program/farm-monitor-dashboard/pages/device/eartag/eartag.wxss index 1441f81..adac604 100644 --- a/mini_program/farm-monitor-dashboard/pages/device/eartag/eartag.wxss +++ b/mini_program/farm-monitor-dashboard/pages/device/eartag/eartag.wxss @@ -218,3 +218,68 @@ font-size: 26rpx; } } + +/* 分页组件样式 */ +.pagination-container { + padding: 32rpx; + background: #ffffff; + border-top: 1rpx solid #f0f0f0; +} + +.pagination-info { + text-align: center; + margin-bottom: 24rpx; + font-size: 24rpx; + color: #666; +} + +.pagination-controls { + display: flex; + align-items: center; + justify-content: center; + gap: 16rpx; +} + +.pagination-btn { + padding: 16rpx 24rpx; + background: #f5f5f5; + border-radius: 8rpx; + font-size: 26rpx; + color: #333; + text-align: center; + min-width: 120rpx; +} + +.pagination-btn.disabled { + background: #f0f0f0; + color: #ccc; +} + +.pagination-pages { + display: flex; + gap: 8rpx; +} + +.pagination-page { + width: 60rpx; + height: 60rpx; + display: flex; + align-items: center; + justify-content: center; + background: #f5f5f5; + border-radius: 8rpx; + font-size: 24rpx; + color: #333; + text-align: center; +} + +.pagination-page.active { + background: #3cc51f; + color: #ffffff; +} + +.pagination-page.ellipsis { + background: transparent; + color: #999; + font-weight: bold; +} \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/pages/login/login.js b/mini_program/farm-monitor-dashboard/pages/login/login.js index 0040217..c8bd308 100644 --- a/mini_program/farm-monitor-dashboard/pages/login/login.js +++ b/mini_program/farm-monitor-dashboard/pages/login/login.js @@ -77,12 +77,21 @@ Page({ this.setData({ loading: true }) try { - // 模拟登录API调用 - const response = await this.mockLogin(username.trim(), password.trim()) + // 调用真实的登录API + const response = await this.realLogin(username.trim(), password.trim()) + console.log('登录API响应:', response) if (response.success) { + console.log('登录成功,token:', response.token) // 保存登录信息 - auth.login(response.data.token, response.data.userInfo) + auth.login(response.token, { + id: response.user?.id || 1, + username: response.user?.username || username.trim(), + nickname: '管理员', + avatar: '', + role: response.role?.name || 'admin' + }) + console.log('用户信息已保存') wx.showToast({ title: '登录成功', @@ -112,7 +121,44 @@ Page({ } }, - // 模拟登录API + // 真实登录API + async realLogin(username, password) { + try { + const response = await new Promise((resolve, reject) => { + wx.request({ + url: 'https://ad.ningmuyun.com/api/auth/login', + method: 'POST', + data: { + username: username, + password: password + }, + header: { + 'Content-Type': 'application/json' + }, + timeout: 10000, + success: (res) => { + console.log('登录API调用成功:', res) + resolve(res) + }, + fail: (error) => { + console.log('登录API调用失败:', error) + reject(error) + } + }) + }) + + if (response.statusCode === 200) { + return response.data + } else { + throw new Error('登录请求失败') + } + } catch (error) { + console.error('登录API调用异常:', error) + throw error + } + }, + + // 模拟登录API(保留作为备用) mockLogin(username, password) { return new Promise((resolve) => { setTimeout(() => { diff --git a/mini_program/farm-monitor-dashboard/project.config.json b/mini_program/farm-monitor-dashboard/project.config.json index c164fb1..838ca6c 100644 --- a/mini_program/farm-monitor-dashboard/project.config.json +++ b/mini_program/farm-monitor-dashboard/project.config.json @@ -73,7 +73,6 @@ "disablePlugins": [], "outputPath": "" }, - "useStaticServer": true, "checkInvalidKey": true, "disableUseStrict": false, "useCompilerPlugins": false, @@ -81,11 +80,11 @@ "localPlugins": false, "condition": false, "swc": false, - "disableSWC": false + "disableSWC": true }, "compileType": "miniprogram", "libVersion": "3.10.1", - "appid": "wx363d2520963f1853", + "appid": "wx209dbc164322f698", "projectname": "farm-monitor-dashboard", "isGameTourist": false, "condition": { diff --git a/mini_program/farm-monitor-dashboard/public/favicon.svg b/mini_program/farm-monitor-dashboard/public/favicon.svg deleted file mode 100644 index 131e31d..0000000 --- a/mini_program/farm-monitor-dashboard/public/favicon.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - 🐄 - diff --git a/mini_program/farm-monitor-dashboard/public/index.html b/mini_program/farm-monitor-dashboard/public/index.html deleted file mode 100644 index 1187abb..0000000 --- a/mini_program/farm-monitor-dashboard/public/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - 智慧养殖管理系统 - - - -
- - - diff --git a/mini_program/farm-monitor-dashboard/set-token.js b/mini_program/farm-monitor-dashboard/set-token.js deleted file mode 100644 index f8fa4bc..0000000 --- a/mini_program/farm-monitor-dashboard/set-token.js +++ /dev/null @@ -1,63 +0,0 @@ -// Token设置工具 - 自动获取并设置API认证token -const axios = require('axios') -const readline = require('readline') - -const API_BASE_URL = process.env.VUE_APP_API_BASE_URL || 'http://localhost:5350' - -const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout -}) - -async function getToken() { - try { - console.log('🔐 正在自动获取API认证token...') - const response = await axios.post(`${API_BASE_URL}/api/auth/login`, { - username: 'admin', - password: '123456' - }) - - if (response.data.success) { - return response.data.token - } - throw new Error('登录失败') - } catch (error) { - console.error('❌ 自动获取token失败:', error.message) - return null - } -} - -console.log('🔐 API Token 设置工具') -console.log('====================') -console.log('') -console.log('此工具将帮助您设置API认证token,以便前端能正确调用后端API。') -console.log('') - -// 自动获取token -getToken().then(token => { - if (token) { - console.log('✅ 自动获取token成功!') - console.log('Token:', token.substring(0, 20) + '...') - console.log('') - console.log('📋 请在前端浏览器控制台中执行以下代码:') - console.log('') - console.log(`localStorage.setItem('token', '${token}')`) - console.log('') - console.log('然后刷新页面测试API连接。') - console.log('') - console.log('🔍 测试API连接:') - console.log('node test-api.js') - } else { - console.log('⚠️ 自动获取token失败') - console.log('') - console.log('💡 手动解决方案:') - console.log('1. 联系后端开发者获取正确的认证信息') - console.log('2. 检查API文档了解认证方式') - console.log('3. 尝试以下测试token:') - console.log(' localStorage.setItem("token", "test-token")') - console.log(' localStorage.setItem("apiKey", "test-api-key")') - } - - console.log('') - rl.close() -}) diff --git a/mini_program/farm-monitor-dashboard/src/App.vue b/mini_program/farm-monitor-dashboard/src/App.vue deleted file mode 100644 index 52e6d5e..0000000 --- a/mini_program/farm-monitor-dashboard/src/App.vue +++ /dev/null @@ -1,110 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/app.scss b/mini_program/farm-monitor-dashboard/src/app.scss deleted file mode 100644 index a98d5bf..0000000 --- a/mini_program/farm-monitor-dashboard/src/app.scss +++ /dev/null @@ -1,353 +0,0 @@ -// 引入uni.scss变量 -@import '../uni.scss'; - -/* 全局样式重置 */ -page { - background-color: $bg-color; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif; - font-size: $font-size-sm; - color: $color-text-primary; - line-height: 1.6; -} - -/* 通用容器样式 */ -.container { - padding: $spacing-base; - background-color: $bg-color-page; - border-radius: $border-radius-base; - margin: $spacing-base; - box-shadow: $box-shadow-light; -} - -.card { - background-color: $bg-color-card; - border-radius: $border-radius-base; - padding: $spacing-base; - margin-bottom: $spacing-base; - box-shadow: $box-shadow-light; - - &.shadow-none { - box-shadow: none; - } - - &.border { - border: 1px solid $border-color-base; - } -} - -/* 统计数字样式 */ -.stat-number { - font-size: 24px; - font-weight: bold; - color: $color-primary; - - &.success { color: $color-success; } - &.warning { color: $color-warning; } - &.danger { color: $color-danger; } - &.info { color: $color-info; } -} - -.stat-label { - font-size: $font-size-sm; - color: $color-text-secondary; - margin-top: $spacing-xs; -} - -/* 状态标签 */ -.status-badge { - display: inline-block; - padding: 2px 8px; - border-radius: $border-radius-sm; - font-size: $font-size-xs; - font-weight: 500; - - &.normal { - background-color: rgba($color-success, 0.1); - color: $color-success; - } - - &.pregnant { - background-color: rgba($color-warning, 0.1); - color: $color-warning; - } - - &.sick { - background-color: rgba($color-danger, 0.1); - color: $color-danger; - } - - &.quarantine { - background-color: rgba($color-info, 0.1); - color: $color-info; - } -} - -/* 列表样式 */ -.list-item { - padding: $spacing-base; - background-color: $bg-color-card; - border-bottom: 1px solid $border-color-light; - - &:last-child { - border-bottom: none; - } - - &.clickable { - &:active { - background-color: darken($bg-color-card, 5%); - } - } -} - -/* 表单样式 */ -.form-group { - margin-bottom: $spacing-base; - - .form-label { - display: block; - margin-bottom: $spacing-xs; - color: $color-text-regular; - font-weight: 500; - } - - .form-control { - width: 100%; - padding: $spacing-sm $spacing-base; - border: 1px solid $border-color-base; - border-radius: $border-radius-base; - font-size: $font-size-sm; - - &:focus { - border-color: $color-primary; - outline: none; - } - - &.error { - border-color: $color-danger; - } - } - - .form-error { - color: $color-danger; - font-size: $font-size-xs; - margin-top: $spacing-xs; - } -} - -/* 按钮样式 */ -.btn { - display: inline-flex; - align-items: center; - justify-content: center; - padding: $spacing-sm $spacing-base; - border: none; - border-radius: $border-radius-base; - font-size: $font-size-sm; - font-weight: 500; - cursor: pointer; - transition: all $transition-duration $transition-function; - - &:disabled { - opacity: $opacity-disabled; - cursor: not-allowed; - } - - &.btn-primary { - background-color: $color-primary; - color: white; - - &:active { - background-color: darken($color-primary, 10%); - } - } - - &.btn-success { - background-color: $color-success; - color: white; - - &:active { - background-color: darken($color-success, 10%); - } - } - - &.btn-danger { - background-color: $color-danger; - color: white; - - &:active { - background-color: darken($color-danger, 10%); - } - } - - &.btn-outline { - background-color: transparent; - border: 1px solid $border-color-base; - color: $color-text-regular; - - &:active { - background-color: $bg-color; - } - } -} - -/* 布局工具类 */ -.flex { - display: flex; - - &.column { flex-direction: column; } - &.wrap { flex-wrap: wrap; } - - &.justify-center { justify-content: center; } - &.justify-between { justify-content: space-between; } - &.justify-end { justify-content: flex-end; } - - &.align-center { align-items: center; } - &.align-start { align-items: flex-start; } - &.align-end { align-items: flex-end; } -} - -/* 文本工具类 */ -.text-center { text-align: center; } -.text-left { text-align: left; } -.text-right { text-align: right; } - -.text-primary { color: $color-primary; } -.text-success { color: $color-success; } -.text-warning { color: $color-warning; } -.text-danger { color: $color-danger; } -.text-info { color: $color-info; } - -.text-xs { font-size: $font-size-xs; } -.text-sm { font-size: $font-size-sm; } -.text-base { font-size: $font-size-base; } -.text-lg { font-size: $font-size-lg; } -.text-xl { font-size: $font-size-xl; } - -.text-bold { font-weight: bold; } -.text-medium { font-weight: 500; } -.text-normal { font-weight: normal; } - -/* 间距工具类 */ -.mt-4 { margin-top: $spacing-xs; } -.mt-8 { margin-top: $spacing-sm; } -.mt-16 { margin-top: $spacing-base; } -.mt-24 { margin-top: $spacing-lg; } -.mt-32 { margin-top: $spacing-xl; } - -.mb-4 { margin-bottom: $spacing-xs; } -.mb-8 { margin-bottom: $spacing-sm; } -.mb-16 { margin-bottom: $spacing-base; } -.mb-24 { margin-bottom: $spacing-lg; } -.mb-32 { margin-bottom: $spacing-xl; } - -.pt-4 { padding-top: $spacing-xs; } -.pt-8 { padding-top: $spacing-sm; } -.pt-16 { padding-top: $spacing-base; } -.pt-24 { padding-top: $spacing-lg; } -.pt-32 { padding-top: $spacing-xl; } - -.pb-4 { padding-bottom: $spacing-xs; } -.pb-8 { padding-bottom: $spacing-sm; } -.pb-16 { padding-bottom: $spacing-base; } -.pb-24 { padding-bottom: $spacing-lg; } -.pb-32 { padding-bottom: $spacing-xl; } - -/* 加载状态 */ -.loading-container { - display: flex; - justify-content: center; - align-items: center; - padding: $spacing-xl; - - .loading-spinner { - width: 24px; - height: 24px; - border: 2px solid $border-color-light; - border-top: 2px solid $color-primary; - border-radius: 50%; - animation: spin 1s linear infinite; - } - - .loading-text { - margin-left: $spacing-sm; - color: $color-text-secondary; - } -} - -/* 空状态 */ -.empty-state { - text-align: center; - padding: $spacing-xl; - color: $color-text-secondary; - - .empty-icon { - font-size: 48px; - margin-bottom: $spacing-base; - } - - .empty-text { - font-size: $font-size-sm; - } -} - -/* 响应式设计 */ -@media (max-width: $breakpoint-sm) { - .container { - margin: $spacing-sm; - padding: $spacing-sm; - } - - .card { - padding: $spacing-sm; - } -} - -/* 动画 */ -@keyframes spin { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } -} - -@keyframes fadeIn { - from { opacity: 0; } - to { opacity: 1; } -} - -@keyframes slideInUp { - from { - transform: translateY(20px); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} - -.fade-in { - animation: fadeIn 0.3s ease-in-out; -} - -.slide-in-up { - animation: slideInUp 0.3s ease-in-out; -} - -/* 其他工具类 */ -.hidden { display: none; } -.block { display: block; } -.inline-block { display: inline-block; } - -.rounded-sm { border-radius: $border-radius-sm; } -.rounded { border-radius: $border-radius-base; } -.rounded-lg { border-radius: $border-radius-lg; } - -.shadow-sm { box-shadow: $box-shadow-light; } -.shadow { box-shadow: $box-shadow-base; } - -.opacity-50 { opacity: 0.5; } -.opacity-75 { opacity: 0.75; } - -.cursor-pointer { cursor: pointer; } -.cursor-not-allowed { cursor: not-allowed; } - -.select-none { user-select: none; } \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/components/AlertTest.vue b/mini_program/farm-monitor-dashboard/src/components/AlertTest.vue deleted file mode 100644 index 960fbc8..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/AlertTest.vue +++ /dev/null @@ -1,210 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/ApiTest.vue b/mini_program/farm-monitor-dashboard/src/components/ApiTest.vue deleted file mode 100644 index 7b6c3e2..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/ApiTest.vue +++ /dev/null @@ -1,212 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/components/ApiTestPage.vue b/mini_program/farm-monitor-dashboard/src/components/ApiTestPage.vue deleted file mode 100644 index a8eeaa3..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/ApiTestPage.vue +++ /dev/null @@ -1,252 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/AuthTest.vue b/mini_program/farm-monitor-dashboard/src/components/AuthTest.vue deleted file mode 100644 index 4c41ce4..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/AuthTest.vue +++ /dev/null @@ -1,388 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/CattleAdd.vue b/mini_program/farm-monitor-dashboard/src/components/CattleAdd.vue deleted file mode 100644 index 8454ae7..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/CattleAdd.vue +++ /dev/null @@ -1,482 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/CattleBatch.vue b/mini_program/farm-monitor-dashboard/src/components/CattleBatch.vue deleted file mode 100644 index e561b52..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/CattleBatch.vue +++ /dev/null @@ -1,829 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/CattleExit.vue b/mini_program/farm-monitor-dashboard/src/components/CattleExit.vue deleted file mode 100644 index 9b12d15..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/CattleExit.vue +++ /dev/null @@ -1,781 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/CattlePen.vue b/mini_program/farm-monitor-dashboard/src/components/CattlePen.vue deleted file mode 100644 index c76bb0e..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/CattlePen.vue +++ /dev/null @@ -1,799 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/CattleProfile.vue b/mini_program/farm-monitor-dashboard/src/components/CattleProfile.vue deleted file mode 100644 index 4eae82f..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/CattleProfile.vue +++ /dev/null @@ -1,574 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/CattleTest.vue b/mini_program/farm-monitor-dashboard/src/components/CattleTest.vue deleted file mode 100644 index 1a86f5f..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/CattleTest.vue +++ /dev/null @@ -1,125 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/CattleTransfer.vue b/mini_program/farm-monitor-dashboard/src/components/CattleTransfer.vue deleted file mode 100644 index 4df941a..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/CattleTransfer.vue +++ /dev/null @@ -1,855 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/components/CattleTransferRegister.vue b/mini_program/farm-monitor-dashboard/src/components/CattleTransferRegister.vue deleted file mode 100644 index 230fbf2..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/CattleTransferRegister.vue +++ /dev/null @@ -1,540 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/EarTag.vue b/mini_program/farm-monitor-dashboard/src/components/EarTag.vue deleted file mode 100644 index 933f45b..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/EarTag.vue +++ /dev/null @@ -1,1415 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/ElectronicFence.vue b/mini_program/farm-monitor-dashboard/src/components/ElectronicFence.vue deleted file mode 100644 index 0e06522..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/ElectronicFence.vue +++ /dev/null @@ -1,1361 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/Home.vue b/mini_program/farm-monitor-dashboard/src/components/Home.vue deleted file mode 100644 index 457cf8e..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/Home.vue +++ /dev/null @@ -1,703 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/Login.vue b/mini_program/farm-monitor-dashboard/src/components/Login.vue deleted file mode 100644 index 216db52..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/Login.vue +++ /dev/null @@ -1,553 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/MapTest.vue b/mini_program/farm-monitor-dashboard/src/components/MapTest.vue deleted file mode 100644 index 80aa763..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/MapTest.vue +++ /dev/null @@ -1,237 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/MapView.vue b/mini_program/farm-monitor-dashboard/src/components/MapView.vue deleted file mode 100644 index 2c0e2c9..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/MapView.vue +++ /dev/null @@ -1,589 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/PasswordLogin.vue b/mini_program/farm-monitor-dashboard/src/components/PasswordLogin.vue deleted file mode 100644 index ba0e3cf..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/PasswordLogin.vue +++ /dev/null @@ -1,756 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/Production.vue b/mini_program/farm-monitor-dashboard/src/components/Production.vue deleted file mode 100644 index af773b9..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/Production.vue +++ /dev/null @@ -1,419 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/Profile.vue b/mini_program/farm-monitor-dashboard/src/components/Profile.vue deleted file mode 100644 index e51eb2f..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/Profile.vue +++ /dev/null @@ -1,385 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/Register.vue b/mini_program/farm-monitor-dashboard/src/components/Register.vue deleted file mode 100644 index 723fdac..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/Register.vue +++ /dev/null @@ -1,630 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/SmartAnkle.vue b/mini_program/farm-monitor-dashboard/src/components/SmartAnkle.vue deleted file mode 100644 index c3c4d90..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/SmartAnkle.vue +++ /dev/null @@ -1,547 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/SmartCollar.vue b/mini_program/farm-monitor-dashboard/src/components/SmartCollar.vue deleted file mode 100644 index f75a2ee..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/SmartCollar.vue +++ /dev/null @@ -1,1432 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/SmartCollarAlert.vue b/mini_program/farm-monitor-dashboard/src/components/SmartCollarAlert.vue deleted file mode 100644 index 840ec66..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/SmartCollarAlert.vue +++ /dev/null @@ -1,1014 +0,0 @@ - - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/SmartEartagAlert.vue b/mini_program/farm-monitor-dashboard/src/components/SmartEartagAlert.vue deleted file mode 100644 index ba8bdb3..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/SmartEartagAlert.vue +++ /dev/null @@ -1,1060 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/SmartHost.vue b/mini_program/farm-monitor-dashboard/src/components/SmartHost.vue deleted file mode 100644 index 7417f88..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/SmartHost.vue +++ /dev/null @@ -1,1071 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/SmsLogin.vue b/mini_program/farm-monitor-dashboard/src/components/SmsLogin.vue deleted file mode 100644 index 8fb0a14..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/SmsLogin.vue +++ /dev/null @@ -1,618 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/components/WechatFenceDrawer.vue b/mini_program/farm-monitor-dashboard/src/components/WechatFenceDrawer.vue deleted file mode 100644 index ca6ded6..0000000 --- a/mini_program/farm-monitor-dashboard/src/components/WechatFenceDrawer.vue +++ /dev/null @@ -1,1020 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/main.js b/mini_program/farm-monitor-dashboard/src/main.js deleted file mode 100644 index 4fdce48..0000000 --- a/mini_program/farm-monitor-dashboard/src/main.js +++ /dev/null @@ -1,24 +0,0 @@ -import Vue from 'vue' -import { createPinia } from 'pinia' -import App from './App.vue' -import VueCompositionAPI from '@vue/composition-api' -import router from './router' - -// 引入全局样式 -import './app.scss' - -// 安装composition-api插件 -Vue.use(VueCompositionAPI) - -// 创建应用实例 -const app = new Vue({ - pinia: createPinia(), - router, - render: h => h(App) -}) - -// 挂载应用 -app.$mount('#app') - -// 导出应用实例 -export default app \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/pages/index/index.vue b/mini_program/farm-monitor-dashboard/src/pages/index/index.vue deleted file mode 100644 index 611b0f4..0000000 --- a/mini_program/farm-monitor-dashboard/src/pages/index/index.vue +++ /dev/null @@ -1,414 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/pages/login/login.vue b/mini_program/farm-monitor-dashboard/src/pages/login/login.vue deleted file mode 100644 index 274a456..0000000 --- a/mini_program/farm-monitor-dashboard/src/pages/login/login.vue +++ /dev/null @@ -1,549 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/router/index.js b/mini_program/farm-monitor-dashboard/src/router/index.js deleted file mode 100644 index 5364bb6..0000000 --- a/mini_program/farm-monitor-dashboard/src/router/index.js +++ /dev/null @@ -1,223 +0,0 @@ -import Vue from 'vue' -import VueRouter from 'vue-router' -import Home from '@/components/Home.vue' -import Production from '@/components/Production.vue' -import Profile from '@/components/Profile.vue' -import EarTag from '@/components/EarTag.vue' -import SmartCollar from '@/components/SmartCollar.vue' -import SmartAnkle from '@/components/SmartAnkle.vue' -import SmartHost from '@/components/SmartHost.vue' -import AuthTest from '@/components/AuthTest.vue' -import Login from '@/components/Login.vue' -import SmsLogin from '@/components/SmsLogin.vue' -import Register from '@/components/Register.vue' -import PasswordLogin from '@/components/PasswordLogin.vue' -import ElectronicFencePage from '@/views/ElectronicFencePage.vue' -import SmartEartagAlertPage from '@/views/SmartEartagAlertPage.vue' -import AlertTest from '@/components/AlertTest.vue' -import MapTest from '@/components/MapTest.vue' -import ApiTest from '@/components/ApiTest.vue' -import WechatFenceDrawer from '@/components/WechatFenceDrawer.vue' -import CattleProfile from '@/components/CattleProfile.vue' -import CattleAdd from '@/components/CattleAdd.vue' -import CattleTest from '@/components/CattleTest.vue' -import CattleTransfer from '@/components/CattleTransfer.vue' -import CattleTransferRegister from '@/components/CattleTransferRegister.vue' -import CattleExit from '@/components/CattleExit.vue' -import CattlePen from '@/components/CattlePen.vue' -import CattleBatch from '@/components/CattleBatch.vue' -import SmartCollarAlert from '@/components/SmartCollarAlert.vue' -import ApiTestPage from '@/components/ApiTestPage.vue' - -Vue.use(VueRouter) - -const routes = [ - { - path: '/', - name: 'Home', - component: Home - }, - { - path: '/login', - name: 'Login', - component: Login - }, - { - path: '/sms-login', - name: 'SmsLogin', - component: SmsLogin - }, - { - path: '/register', - name: 'Register', - component: Register - }, - { - path: '/password-login', - name: 'PasswordLogin', - component: PasswordLogin - }, - { - path: '/production', - name: 'Production', - component: Production - }, - { - path: '/profile', - name: 'Profile', - component: Profile - }, - { - path: '/ear-tag', - name: 'EarTag', - component: EarTag - }, - { - path: '/smart-collar', - name: 'SmartCollar', - component: SmartCollar - }, - { - path: '/smart-ankle', - name: 'SmartAnkle', - component: SmartAnkle - }, - { - path: '/smart-host', - name: 'SmartHost', - component: SmartHost - }, - { - path: '/auth-test', - name: 'AuthTest', - component: AuthTest - }, - { - path: '/electronic-fence', - name: 'ElectronicFence', - component: ElectronicFencePage - }, - { - path: '/smart-eartag-alert', - name: 'SmartEartagAlert', - component: SmartEartagAlertPage - }, - { - path: '/alert-test', - name: 'AlertTest', - component: AlertTest - }, - { - path: '/map-test', - name: 'MapTest', - component: MapTest - }, - { - path: '/api-test', - name: 'ApiTest', - component: ApiTest - }, - { - path: '/wechat-fence-drawer', - name: 'WechatFenceDrawer', - component: WechatFenceDrawer - }, - { - path: '/cattle-profile', - name: 'CattleProfile', - component: CattleProfile - }, - { - path: '/cattle-add', - name: 'CattleAdd', - component: CattleAdd - }, - { - path: '/cattle-test', - name: 'CattleTest', - component: CattleTest - }, - { - path: '/cattle-transfer', - name: 'CattleTransfer', - component: CattleTransfer - }, - { - path: '/cattle-transfer-register', - name: 'CattleTransferRegister', - component: CattleTransferRegister - }, - { - path: '/cattle-exit', - name: 'CattleExit', - component: CattleExit - }, - { - path: '/cattle-pen', - name: 'CattlePen', - component: CattlePen - }, - { - path: '/cattle-batch', - name: 'CattleBatch', - component: CattleBatch - }, - { - path: '/smart-collar-alert', - name: 'SmartCollarAlert', - component: SmartCollarAlert - }, - { - path: '/api-test-page', - name: 'ApiTestPage', - component: ApiTestPage - } -] - -const router = new VueRouter({ - mode: 'history', - base: process.env.BASE_URL, - routes -}) - -// 路由守卫 -router.beforeEach((to, from, next) => { - // 导入认证工具 - const auth = require('@/utils/auth').default - - // 检查是否需要登录 - const requiresAuth = !['/login', '/sms-login', '/register', '/password-login'].includes(to.path) - const isLoginPage = ['/login', '/sms-login', '/register', '/password-login'].includes(to.path) - const isAuthenticated = auth.isAuthenticated() - - console.log('路由守卫:', { - from: from.path, - to: to.path, - requiresAuth, - isLoginPage, - isAuthenticated - }) - - // 如果是从登录页面跳转到首页,且用户已登录,直接允许访问 - if (from.path && isLoginPage && to.path === '/' && isAuthenticated) { - console.log('允许从登录页跳转到首页') - next() - return - } - - if (requiresAuth && !isAuthenticated) { - // 需要登录但未登录,跳转到登录页 - console.log('需要登录,跳转到登录页') - next('/login') - } else if (isLoginPage && isAuthenticated) { - // 已登录但访问登录页,跳转到首页 - console.log('已登录,跳转到首页') - next('/') - } else { - // 正常访问 - console.log('正常访问') - next() - } -}) - -export default router diff --git a/mini_program/farm-monitor-dashboard/src/services/alertService.js b/mini_program/farm-monitor-dashboard/src/services/alertService.js deleted file mode 100644 index d0126da..0000000 --- a/mini_program/farm-monitor-dashboard/src/services/alertService.js +++ /dev/null @@ -1,127 +0,0 @@ -import api from './api' - -// 智能耳标预警相关API服务 -export const alertService = { - // 获取预警列表 - async getAlerts(params = {}) { - try { - const response = await api.get('/smart-eartag-alerts', { params }) - return response - } catch (error) { - console.error('获取预警列表失败:', error) - throw error - } - }, - - // 获取预警详情 - async getAlertById(id) { - try { - const response = await api.get(`/smart-eartag-alerts/${id}`) - return response - } catch (error) { - console.error('获取预警详情失败:', error) - throw error - } - }, - - // 处理预警(标记为已处理) - async resolveAlert(id) { - try { - const response = await api.put(`/smart-eartag-alerts/${id}/resolve`) - return response - } catch (error) { - console.error('处理预警失败:', error) - throw error - } - }, - - // 批量处理预警 - async batchResolveAlerts(ids) { - try { - const response = await api.put('/smart-eartag-alerts/batch-resolve', { ids }) - return response - } catch (error) { - console.error('批量处理预警失败:', error) - throw error - } - }, - - // 删除预警 - async deleteAlert(id) { - try { - const response = await api.delete(`/smart-eartag-alerts/${id}`) - return response - } catch (error) { - console.error('删除预警失败:', error) - throw error - } - }, - - // 获取预警统计 - async getAlertStats() { - try { - const response = await api.get('/smart-eartag-alerts/stats') - return response - } catch (error) { - console.error('获取预警统计失败:', error) - throw error - } - }, - - // 获取设备预警历史 - async getDeviceAlertHistory(deviceId, params = {}) { - try { - const response = await api.get(`/smart-eartag-alerts/device/${deviceId}`, { params }) - return response - } catch (error) { - console.error('获取设备预警历史失败:', error) - throw error - } - }, - - // 设置预警规则 - async setAlertRule(ruleData) { - try { - const response = await api.post('/smart-eartag-alerts/rules', ruleData) - return response - } catch (error) { - console.error('设置预警规则失败:', error) - throw error - } - }, - - // 获取预警规则 - async getAlertRules() { - try { - const response = await api.get('/smart-eartag-alerts/rules') - return response - } catch (error) { - console.error('获取预警规则失败:', error) - throw error - } - }, - - // 更新预警规则 - async updateAlertRule(id, ruleData) { - try { - const response = await api.put(`/smart-eartag-alerts/rules/${id}`, ruleData) - return response - } catch (error) { - console.error('更新预警规则失败:', error) - throw error - } - }, - - // 删除预警规则 - async deleteAlertRule(id) { - try { - const response = await api.delete(`/smart-eartag-alerts/rules/${id}`) - return response - } catch (error) { - console.error('删除预警规则失败:', error) - throw error - } - } -} - -export default alertService \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/services/ankleService.js b/mini_program/farm-monitor-dashboard/src/services/ankleService.js deleted file mode 100644 index 17e3276..0000000 --- a/mini_program/farm-monitor-dashboard/src/services/ankleService.js +++ /dev/null @@ -1,149 +0,0 @@ -import axios from 'axios' - -// 创建axios实例 -const api = axios.create({ - baseURL: process.env.VUE_APP_API_BASE_URL || 'http://localhost:5350', - timeout: 10000, - headers: { - 'Content-Type': 'application/json' - } -}) - -// 请求拦截器 -api.interceptors.request.use( - config => { - const token = localStorage.getItem('token') - if (token) { - config.headers.Authorization = `Bearer ${token}` - } else { - console.warn('未找到认证token,使用模拟数据') - } - return config - }, - error => { - return Promise.reject(error) - } -) - -// 响应拦截器 -api.interceptors.response.use( - response => { - return response - }, - error => { - console.error('API请求错误:', error) - // 如果是401错误,直接返回模拟数据而不是抛出错误 - if (error.response && error.response.status === 401) { - console.warn('认证失败,返回模拟数据') - return Promise.resolve({ data: { data: [] } }) - } - return Promise.reject(error) - } -) - -/** - * 获取智能脚环设备列表 - * @param {Object} params - 查询参数 - * @returns {Promise} API响应 - */ -// 模拟数据 -const getMockAnkleDevices = () => { - return [ - { - ankleId: '2409501317', - battery: 68, - temperature: 28.8, - collectedHost: '2490246426', - totalMovement: 3456, - todayMovement: 234, - stepCount: 8923, - updateTime: '2025-09-18 14:30:15', - isBound: true - }, - { - ankleId: '2407300110', - battery: 52, - temperature: 29.5, - collectedHost: '23107000007', - totalMovement: 4567, - todayMovement: 189, - stepCount: 12345, - updateTime: '2025-09-18 14:25:30', - isBound: false - }, - { - ankleId: '2406600007', - battery: 38, - temperature: 30.1, - collectedHost: '2490246426', - totalMovement: 6789, - todayMovement: 312, - stepCount: 15678, - updateTime: '2025-09-18 14:20:45', - isBound: true - }, - { - ankleId: '2502300008', - battery: 91, - temperature: 27.9, - collectedHost: '23C0270112', - totalMovement: 2345, - todayMovement: 145, - stepCount: 6789, - updateTime: '2025-09-18 14:15:20', - isBound: false - } - ] -} - -export const getAnkleDevices = async (params = {}) => { - try { - const response = await api.get('/api/smart-devices/anklets', { params }) - return response.data - } catch (error) { - console.error('获取脚环设备列表失败,使用模拟数据:', error) - return { data: getMockAnkleDevices() } - } -} - -/** - * 绑定脚环设备 - * @param {string} ankleId - 脚环ID - * @param {string} animalId - 动物ID - * @returns {Promise} API响应 - */ -export const bindAnkle = async (ankleId, animalId) => { - try { - const response = await api.post('/api/smart-devices/anklets/bind', { - ankleId, - animalId - }) - return response.data - } catch (error) { - console.error('绑定脚环设备失败:', error) - throw error - } -} - -/** - * 解绑脚环设备 - * @param {string} ankleId - 脚环ID - * @returns {Promise} API响应 - */ -export const unbindAnkle = async (ankleId) => { - try { - const response = await api.post('/api/smart-devices/anklets/unbind', { - ankleId - }) - return response.data - } catch (error) { - console.error('解绑脚环设备失败:', error) - throw error - } -} - -export default { - getAnkleDevices, - bindAnkle, - unbindAnkle -} diff --git a/mini_program/farm-monitor-dashboard/src/services/api.js b/mini_program/farm-monitor-dashboard/src/services/api.js deleted file mode 100644 index ab0c370..0000000 --- a/mini_program/farm-monitor-dashboard/src/services/api.js +++ /dev/null @@ -1,463 +0,0 @@ -import axios from 'axios' -import auth from '@/utils/auth' - -// 创建axios实例 -const service = axios.create({ - baseURL: process.env.VUE_APP_BASE_URL || '/api', - timeout: 10000, - headers: { - 'Content-Type': 'application/json' - } -}) - -// 请求拦截器 -service.interceptors.request.use( - (config) => { - // 添加token到请求头 - const token = auth.getToken() - if (token) { - config.headers['Authorization'] = `Bearer ${token}` - } - - // 添加时间戳防止缓存 - if (config.method === 'get') { - config.params = { - ...config.params, - _t: Date.now() - } - } - - return config - }, - (error) => { - return Promise.reject(error) - } -) - -// 响应拦截器 -service.interceptors.response.use( - (response) => { - const res = response.data - console.log('原始API响应:', res) - console.log('响应状态码:', response.status) - - // 统一处理响应格式 - if (res.code === 200) { - console.log('处理code=200格式') - return res.data - } else if (res.success === true) { - // 处理 {success: true, data: ...} 格式 - console.log('处理success=true格式') - return res - } else if (res.success === false) { - // 处理 {success: false, message: ...} 格式 - console.log('处理success=false格式') - return res - } else if (res.code === undefined && res.success === undefined) { - // 直接返回数据的情况 - console.log('处理直接数据格式') - return res - } else { - // 业务错误 - console.error('请求失败:', res.message || '请求失败') - console.error('完整响应:', res) - // 这里可以添加用户提示,比如使用Element UI的Message组件 - return Promise.reject(new Error(res.message || '请求失败')) - } - }, - (error) => { - // 网络错误或服务器错误 - let message = '网络错误' - - if (error.response) { - const { status } = error.response - - switch (status) { - case 401: - message = '未授权,请重新登录' - // 清除token并跳转到登录页 - localStorage.removeItem('token') - localStorage.removeItem('userInfo') - // 跳转到登录页 - window.location.href = '/login' - break - case 403: - message = '拒绝访问' - break - case 404: - message = '请求的资源不存在' - break - case 500: - message = '服务器内部错误' - break - default: - message = `连接错误${status}` - } - } else if (error.request) { - message = '网络连接异常' - } else { - message = error.message - } - - console.error('网络错误:', message) - // 这里可以添加用户提示,比如使用Element UI的Message组件 - - return Promise.reject(error) - } -) - -// 通用请求方法 -export const request = (config) => { - return service(config) -} - -// GET请求 -export const get = (url, params = {}) => { - return service({ - url, - method: 'get', - params - }) -} - -// POST请求 -export const post = (url, data = {}) => { - return service({ - url, - method: 'post', - data - }) -} - -// PUT请求 -export const put = (url, data = {}) => { - return service({ - url, - method: 'put', - data - }) -} - -// DELETE请求 -export const del = (url, params = {}) => { - return service({ - url, - method: 'delete', - params - }) -} - -// 上传文件 -export const upload = (url, file, formData = {}) => { - return new Promise((resolve, reject) => { - const uploadFormData = new FormData() - - // 添加文件 - uploadFormData.append('file', file) - - // 添加其他表单数据 - Object.keys(formData).forEach(key => { - uploadFormData.append(key, formData[key]) - }) - - // 使用fetch上传文件 - fetch(service.defaults.baseURL + url, { - method: 'POST', - body: uploadFormData, - headers: { - 'Authorization': `Bearer ${auth.getToken()}` - } - }) - .then(response => response.json()) - .then(data => { - if (data.code === 200) { - resolve(data.data) - } else { - reject(new Error(data.message)) - } - }) - .catch(error => { - reject(error) - }) - }) -} - -// 牛只档案相关API -export const cattleApi = { - // 获取牛只档案列表 - getCattleList: (params = {}) => { - return get('/iot-cattle/public', params) - }, - - // 根据耳号搜索牛只 - searchCattleByEarNumber: (earNumber) => { - return get('/iot-cattle/public', { search: earNumber }) - }, - - // 获取牛只详情 - getCattleDetail: (id) => { - return get(`/iot-cattle/public/${id}`) - }, - - // 获取牛只类型列表 - getCattleTypes: () => { - return get('/cattle-type') - }, - - // 获取栏舍列表 - getPens: (farmId) => { - return get('/iot-cattle/public/pens/list', { farmId }) - }, - - // 获取批次列表 - getBatches: (farmId) => { - return get('/iot-cattle/public/batches/list', { farmId }) - }, - - // 创建牛只档案 - createCattle: (data) => { - return post('/iot-cattle', data) - }, - - // 更新牛只档案 - updateCattle: (id, data) => { - return put(`/iot-cattle/${id}`, data) - }, - - // 删除牛只档案 - deleteCattle: (id) => { - return del(`/iot-cattle/${id}`) - } -} - -// 牛只转栏记录相关API -export const cattleTransferApi = { - // 获取转栏记录列表 - getTransferRecords: (params = {}) => { - return get('/cattle-transfer-records', params) - }, - - // 根据耳号搜索转栏记录 - searchTransferRecordsByEarNumber: (earNumber, params = {}) => { - return get('/cattle-transfer-records', { earNumber, ...params }) - }, - - // 获取转栏记录详情 - getTransferRecordDetail: (id) => { - return get(`/cattle-transfer-records/${id}`) - }, - - // 创建转栏记录 - createTransferRecord: (data) => { - return post('/cattle-transfer-records', data) - }, - - // 更新转栏记录 - updateTransferRecord: (id, data) => { - return put(`/cattle-transfer-records/${id}`, data) - }, - - // 删除转栏记录 - deleteTransferRecord: (id) => { - return del(`/cattle-transfer-records/${id}`) - }, - - // 批量删除转栏记录 - batchDeleteTransferRecords: (ids) => { - return post('/cattle-transfer-records/batch-delete', { ids }) - }, - - // 获取可用的牛只列表 - getAvailableAnimals: (params = {}) => { - return get('/cattle-transfer-records/available-animals', params) - }, - - // 获取栏舍列表(用于转栏选择) - getBarnsForTransfer: (params = {}) => { - return get('/cattle-pens', params) - } -} - -// 牛只离栏记录相关API -export const cattleExitApi = { - // 获取离栏记录列表 - getExitRecords: (params = {}) => { - return get('/cattle-exit-records', params) - }, - - // 根据耳号搜索离栏记录 - searchExitRecordsByEarNumber: (earNumber, params = {}) => { - return get('/cattle-exit-records', { earNumber, ...params }) - }, - - // 获取离栏记录详情 - getExitRecordDetail: (id) => { - return get(`/cattle-exit-records/${id}`) - }, - - // 创建离栏记录 - createExitRecord: (data) => { - return post('/cattle-exit-records', data) - }, - - // 更新离栏记录 - updateExitRecord: (id, data) => { - return put(`/cattle-exit-records/${id}`, data) - }, - - // 删除离栏记录 - deleteExitRecord: (id) => { - return del(`/cattle-exit-records/${id}`) - }, - - // 批量删除离栏记录 - batchDeleteExitRecords: (ids) => { - return post('/cattle-exit-records/batch-delete', { ids }) - }, - - // 获取可用的牛只列表 - getAvailableAnimals: (params = {}) => { - return get('/cattle-exit-records/available-animals', params) - } -} - -// 牛只栏舍相关API -export const cattlePenApi = { - // 获取栏舍列表 - getPens: (params = {}) => { - return get('/cattle-pens', params) - }, - - // 根据名称搜索栏舍 - searchPensByName: (name, params = {}) => { - return get('/cattle-pens', { name, ...params }) - }, - - // 获取栏舍详情 - getPenDetail: (id) => { - return get(`/cattle-pens/${id}`) - }, - - // 创建栏舍 - createPen: (data) => { - return post('/cattle-pens', data) - }, - - // 更新栏舍 - updatePen: (id, data) => { - return put(`/cattle-pens/${id}`, data) - }, - - // 删除栏舍 - deletePen: (id) => { - return del(`/cattle-pens/${id}`) - }, - - // 批量删除栏舍 - batchDeletePens: (ids) => { - return post('/cattle-pens/batch-delete', { ids }) - }, - - // 获取栏舍类型列表 - getPenTypes: () => { - return get('/cattle-pens/types') - } -} - -// 牛只批次相关API -export const cattleBatchApi = { - // 获取批次列表 - getBatches: (params = {}) => { - return get('/cattle-batches', params) - }, - - // 根据名称搜索批次 - searchBatchesByName: (name, params = {}) => { - return get('/cattle-batches', { name, ...params }) - }, - - // 获取批次详情 - getBatchDetail: (id) => { - return get(`/cattle-batches/${id}`) - }, - - // 创建批次 - createBatch: (data) => { - return post('/cattle-batches', data) - }, - - // 更新批次 - updateBatch: (id, data) => { - return put(`/cattle-batches/${id}`, data) - }, - - // 删除批次 - deleteBatch: (id) => { - return del(`/cattle-batches/${id}`) - }, - - // 批量删除批次 - batchDeleteBatches: (ids) => { - return post('/cattle-batches/batch-delete', { ids }) - }, - - // 获取批次类型列表 - getBatchTypes: () => { - return get('/cattle-batches/types') - } -} - -// 智能预警相关API -export const alertApi = { - // 获取耳标预警统计 - getEartagStats: () => { - return get('/smart-alerts/public/eartag/stats') - }, - - // 获取项圈预警统计 - getCollarStats: () => { - return get('/smart-alerts/public/collar/stats') - }, - - // 获取耳标预警列表 - getEartagAlerts: (params = {}) => { - return get('/smart-alerts/public/eartag', params) - }, - - // 获取项圈预警列表 - getCollarAlerts: (params = {}) => { - return get('/smart-alerts/public/collar', params) - }, - - // 获取耳标预警详情 - getEartagAlertDetail: (id) => { - return get(`/smart-alerts/public/eartag/${id}`) - }, - - // 获取项圈预警详情 - getCollarAlertDetail: (id) => { - return get(`/smart-alerts/public/collar/${id}`) - }, - - // 处理耳标预警 - handleEartagAlert: (id, data) => { - return post(`/smart-alerts/public/eartag/${id}/handle`, data) - }, - - // 处理项圈预警 - handleCollarAlert: (id, data) => { - return post(`/smart-alerts/public/collar/${id}/handle`, data) - }, - - // 批量处理耳标预警 - batchHandleEartagAlerts: (data) => { - return post('/smart-alerts/public/eartag/batch-handle', data) - }, - - // 批量处理项圈预警 - batchHandleCollarAlerts: (data) => { - return post('/smart-alerts/public/collar/batch-handle', data) - } -} - -export default service \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/services/authService.js b/mini_program/farm-monitor-dashboard/src/services/authService.js deleted file mode 100644 index 673bc1b..0000000 --- a/mini_program/farm-monitor-dashboard/src/services/authService.js +++ /dev/null @@ -1,95 +0,0 @@ -import axios from 'axios' - -// 创建axios实例 -const api = axios.create({ - baseURL: process.env.VUE_APP_API_BASE_URL || '/api', - timeout: 10000, - headers: { - 'Content-Type': 'application/json' - } -}) - -/** - * 用户登录 - * @param {string} username - 用户名 - * @param {string} password - 密码 - * @returns {Promise} API响应 - */ -export const login = async (username, password) => { - try { - console.log('正在登录...', username) - const response = await api.post('/auth/login', { - username, - password - }) - console.log('登录成功:', response.data) - return response.data - } catch (error) { - console.error('登录失败:', error) - throw error - } -} - -/** - * 用户注册 - * @param {Object} userData - 用户数据 - * @returns {Promise} API响应 - */ -export const register = async (userData) => { - try { - console.log('正在注册...', userData.username) - const response = await api.post('/auth/register', userData) - console.log('注册成功:', response.data) - return response.data - } catch (error) { - console.error('注册失败:', error) - throw error - } -} - -/** - * 验证token有效性 - * @param {string} token - JWT token - * @returns {Promise} API响应 - */ -export const validateToken = async (token) => { - try { - const response = await api.get('/auth/validate', { - headers: { - 'Authorization': `Bearer ${token}` - } - }) - console.log('Token验证成功:', response.data) - return response.data - } catch (error) { - console.error('Token验证失败:', error) - throw error - } -} - -/** - * 获取用户信息 - * @param {string} token - JWT token - * @returns {Promise} API响应 - */ -export const getUserInfo = async (token) => { - try { - const response = await api.get('/auth/me', { - headers: { - 'Authorization': `Bearer ${token}` - } - }) - console.log('获取用户信息成功:', response.data) - return response.data - } catch (error) { - console.error('获取用户信息失败:', error) - throw error - } -} - -export default { - login, - register, - validateToken, - getUserInfo -} \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/services/collarService.js b/mini_program/farm-monitor-dashboard/src/services/collarService.js deleted file mode 100644 index 4e0e31e..0000000 --- a/mini_program/farm-monitor-dashboard/src/services/collarService.js +++ /dev/null @@ -1,286 +0,0 @@ -import axios from 'axios' - -// 创建axios实例 -const api = axios.create({ - baseURL: process.env.VUE_APP_API_BASE_URL || 'http://localhost:5350', - timeout: 10000, - headers: { - 'Content-Type': 'application/json' - } -}) - -// 请求拦截器 -api.interceptors.request.use( - config => { - const token = localStorage.getItem('token') - if (token) { - config.headers.Authorization = `Bearer ${token}` - console.log('添加认证token到请求头:', token.substring(0, 20) + '...') - } else { - console.warn('未找到认证token,请求可能被拒绝') - } - return config - }, - error => { - return Promise.reject(error) - } -) - -// 响应拦截器 -api.interceptors.response.use( - response => { - console.log('API响应成功:', response.config.url) - return response - }, - error => { - console.error('API请求错误:', error.response?.status, error.config?.url) - - // 如果是401错误,提示用户重新登录 - if (error.response && error.response.status === 401) { - console.error('认证失败,请重新登录') - // 清除本地存储的认证信息 - localStorage.removeItem('token') - localStorage.removeItem('userInfo') - // 可以在这里触发全局的登录状态更新 - if (window.location.pathname !== '/login' && window.location.pathname !== '/password-login' && window.location.pathname !== '/sms-login' && window.location.pathname !== '/register') { - window.location.href = '/login' - } - } - - return Promise.reject(error) - } -) - -/** - * 获取所有智能项圈设备(支持分页) - * @param {Object} params - 查询参数 - * @param {number} params.page - 页码,默认1 - * @param {number} params.limit - 每页数量,默认10 - * @param {string} params.search - 搜索关键词 - * @param {string} params.status - 状态筛选 - * @returns {Promise} API响应 - */ -export const getAllCollarDevices = async (params = {}) => { - try { - const { page = 1, limit = 10, search, status, ...otherParams } = params - - const queryParams = { - page: parseInt(page), - limit: parseInt(limit), - ...otherParams - } - - if (search) { - queryParams.search = search - } - - if (status) { - queryParams.status = status - } - - console.log('正在请求所有项圈设备...', queryParams) - const response = await api.get('/api/smart-devices/collars', { params: queryParams }) - console.log('所有项圈设备请求成功:', response.data) - - // 处理API响应数据,确保字段映射正确 - if (response.data && response.data.data) { - response.data.data = response.data.data.map(device => ({ - ...device, - // 确保关键字段存在并正确映射 - collarId: device.sn || device.deviceId || device.id, - battery: device.voltage || device.battery || 0, - temperature: device.temperature || 0, - collectedHost: device.sid || device.collectedHost || '未知', - totalMovement: device.walk || device.totalMovement || 0, - todayMovement: (device.steps || device.walk || 0) - (device.y_steps || 0), - gpsLocation: device.gps || device.gpsLocation || '未知', - updateTime: device.time || device.uptime || device.updateTime || '未知', - // 绑定状态映射 - 优先使用bandge_status字段,其次使用state字段 - isBound: device.bandge_status === 1 || device.bandge_status === '1' || device.state === 1 || device.state === '1', - // 保持向后兼容 - deviceId: device.id, - sn: device.sn, - voltage: device.voltage, - walk: device.walk, - y_steps: device.y_steps, - time: device.time, - uptime: device.uptime, - state: device.state || 0, - bandge_status: device.bandge_status || 0 - })) - } - - // 确保分页信息存在并正确映射字段 - if (response.data.pagination) { - // 映射API返回的分页字段到前端期望的字段 - response.data.pagination = { - current: parseInt(response.data.pagination.page || response.data.pagination.current || queryParams.page) || 1, - pageSize: parseInt(response.data.pagination.limit || response.data.pagination.pageSize || queryParams.limit) || 10, - total: parseInt(response.data.pagination.total || 0) || 0, - totalPages: parseInt(response.data.pagination.pages || response.data.pagination.totalPages || 1) || 1 - } - } else { - // 如果没有分页信息,使用默认值 - response.data.pagination = { - current: parseInt(queryParams.page) || 1, - pageSize: parseInt(queryParams.limit) || 10, - total: response.data.data ? response.data.data.length : 0, - totalPages: 1 - } - } - - console.log('处理后的分页信息:', response.data.pagination) - return response.data - } catch (error) { - console.error('获取所有项圈设备失败:', error) - throw error - } -} - -// 保持向后兼容的别名 -export const getCollarDevices = getAllCollarDevices - -/** - * 绑定项圈设备 - * @param {string} collarId - 项圈ID - * @param {string} animalId - 动物ID - * @returns {Promise} API响应 - */ -export const bindCollar = async (collarId, animalId) => { - try { - const response = await api.post('/api/smart-devices/collars/bind', { - collarId, - animalId - }) - return response.data - } catch (error) { - console.error('绑定项圈设备失败:', error) - throw error - } -} - -/** - * 解绑项圈设备 - * @param {string} collarId - 项圈ID - * @returns {Promise} API响应 - */ -export const unbindCollar = async (collarId) => { - try { - const response = await api.post('/api/smart-devices/collars/unbind', { - collarId - }) - return response.data - } catch (error) { - console.error('解绑项圈设备失败:', error) - throw error - } -} - -/** - * 获取项圈设备统计信息 - * @returns {Promise} API响应 - */ -export const getCollarStatistics = async () => { - try { - console.log('正在获取项圈设备统计信息...') - // 获取所有设备进行统计 - const response = await api.get('/api/smart-devices/collars', { - params: { page: 1, limit: 10000 } // 获取大量数据用于统计 - }) - - if (response.data && response.data.data) { - const devices = response.data.data - const total = response.data.pagination?.total || devices.length - const boundCount = devices.filter(device => - device.bandge_status === 1 || device.bandge_status === '1' || - device.state === 1 || device.state === '1' - ).length - const unboundCount = total - boundCount - - const statistics = { - total, - boundCount, - unboundCount, - success: true - } - - console.log('项圈设备统计信息获取成功:', statistics) - return statistics - } - - throw new Error('无法获取统计数据') - } catch (error) { - console.error('获取项圈设备统计信息失败:', error) - throw error - } -} - -/** - * 根据ID获取项圈设备 - * @param {string} id - 设备ID - * @returns {Promise} API响应 - */ -export const getCollarDeviceById = async (id) => { - try { - console.log('正在根据ID获取项圈设备...', id) - const response = await api.get(`/api/smart-devices/collars/${id}`) - console.log('根据ID获取项圈设备成功:', response.data) - return response.data - } catch (error) { - console.error('根据ID获取项圈设备失败:', error) - throw error - } -} - -/** - * 更新项圈设备 - * @param {string} id - 设备ID - * @param {Object} data - 更新数据 - * @returns {Promise} API响应 - */ -export const updateCollarDevice = async (id, data) => { - try { - console.log('正在更新项圈设备...', id, data) - const response = await api.put(`/api/smart-devices/collars/${id}`, data) - console.log('更新项圈设备成功:', response.data) - return response.data - } catch (error) { - console.error('更新项圈设备失败:', error) - throw error - } -} - -/** - * 删除项圈设备 - * @param {string} id - 设备ID - * @returns {Promise} API响应 - */ -export const deleteCollarDevice = async (id) => { - try { - console.log('正在删除项圈设备...', id) - const response = await api.delete(`/api/smart-devices/collars/${id}`) - console.log('删除项圈设备成功:', response.data) - return response.data - } catch (error) { - console.error('删除项圈设备失败:', error) - throw error - } -} - -export default { - // 新的API方法 - getAllCollarDevices, - getCollarDeviceById, - updateCollarDevice, - deleteCollarDevice, - - // 向后兼容的别名 - getCollarDevices, - - // 原有的绑定/解绑方法 - bindCollar, - unbindCollar, - - // 统计方法 - getCollarStatistics -} diff --git a/mini_program/farm-monitor-dashboard/src/services/earTagService.js b/mini_program/farm-monitor-dashboard/src/services/earTagService.js deleted file mode 100644 index 651cd42..0000000 --- a/mini_program/farm-monitor-dashboard/src/services/earTagService.js +++ /dev/null @@ -1,319 +0,0 @@ -import axios from 'axios' - -// 创建axios实例 -const api = axios.create({ - baseURL: process.env.VUE_APP_API_BASE_URL || 'http://localhost:5350', - timeout: 10000, - headers: { - 'Content-Type': 'application/json' - } -}) - -// 请求拦截器 -api.interceptors.request.use( - config => { - // 添加token到请求头 - const token = localStorage.getItem('token') - if (token) { - config.headers.Authorization = `Bearer ${token}` - console.log('添加认证token到请求头:', token.substring(0, 20) + '...') - } else { - console.warn('未找到认证token,请求可能被拒绝') - } - return config - }, - error => { - return Promise.reject(error) - } -) - -// 响应拦截器 -api.interceptors.response.use( - response => { - console.log('API响应成功:', response.config.url) - return response - }, - error => { - console.error('API请求错误:', error.response?.status, error.config?.url) - - // 如果是401错误,提示用户重新登录 - if (error.response && error.response.status === 401) { - console.error('认证失败,请重新登录') - // 清除本地存储的认证信息 - localStorage.removeItem('token') - localStorage.removeItem('userInfo') - // 可以在这里触发全局的登录状态更新 - if (window.location.pathname !== '/login' && window.location.pathname !== '/password-login' && window.location.pathname !== '/sms-login' && window.location.pathname !== '/register') { - window.location.href = '/login' - } - } - - return Promise.reject(error) - } -) - -/** - * 获取所有智能耳标设备(支持分页) - * @param {Object} params - 查询参数 - * @param {number} params.page - 页码,默认1 - * @param {number} params.pageSize - 每页数量,默认10 - * @param {string} params.cid - 设备CID过滤 - * @returns {Promise} API响应 - */ -export const getAllEarTagDevices = async (params = {}) => { - try { - const { page = 1, pageSize = 10, cid, ...otherParams } = params - - const queryParams = { - page: parseInt(page), - pageSize: parseInt(pageSize), - ...otherParams - } - - if (cid) { - queryParams.cid = cid - } - - console.log('正在请求所有耳标设备...', queryParams) - const response = await api.get('/api/iot-jbq-client', { params: queryParams }) - console.log('所有耳标设备请求成功:', response.data) - - // 处理API响应数据,确保字段映射正确 - if (response.data && response.data.data) { - response.data.data = response.data.data.map(device => ({ - ...device, - // 确保关键字段存在 - cid: device.cid || device.aaid || device.id, - voltage: device.voltage || '0', - temperature: device.temperature || '0', - walk: device.walk || 0, - y_steps: device.y_steps || 0, - time: device.time || device.uptime || 0, - state: device.state || 0, // 确保state字段存在,默认为0(未绑定) - // 保持向后兼容 - earTagId: device.cid || device.earTagId, - battery: device.voltage || device.battery, - totalMovement: device.walk || device.totalMovement, - todayMovement: (device.walk || 0) - (device.y_steps || 0), - collectedHost: device.sid || device.collectedHost, - updateTime: device.time || device.updateTime, - // 为了向后兼容,添加isBound字段 - isBound: device.state === 1 || device.state === '1' - })) - } - - return response.data - } catch (error) { - console.error('获取所有耳标设备失败:', error) - throw error - } -} - -/** - * 根据CID获取智能耳标设备 - * @param {string} cid - 客户端ID - * @returns {Promise} API响应 - */ -export const getEarTagDevicesByCid = async (cid) => { - try { - console.log('正在根据CID获取耳标设备...', cid) - const response = await api.get(`/api/iot-jbq-client/cid/${cid}`) - console.log('根据CID获取耳标设备成功:', response.data) - return response.data - } catch (error) { - console.error('根据CID获取耳标设备失败:', error) - throw error - } -} - -/** - * 根据ID获取智能耳标设备 - * @param {string} id - 设备ID - * @returns {Promise} API响应 - */ -export const getEarTagDeviceById = async (id) => { - try { - console.log('正在根据ID获取耳标设备...', id) - const response = await api.get(`/api/iot-jbq-client/${id}`) - console.log('根据ID获取耳标设备成功:', response.data) - return response.data - } catch (error) { - console.error('根据ID获取耳标设备失败:', error) - throw error - } -} - -/** - * 获取耳标设备统计信息 - * @returns {Promise} API响应 - */ -export const getEarTagStatistics = async () => { - try { - console.log('正在获取耳标设备统计信息...') - // 获取所有设备进行统计 - const response = await api.get('/api/iot-jbq-client', { - params: { page: 1, pageSize: 10000 } // 获取大量数据用于统计 - }) - - if (response.data && response.data.data) { - const devices = response.data.data - const total = response.data.pagination?.total || devices.length - const boundCount = devices.filter(device => device.state === 1 || device.state === '1').length - const unboundCount = total - boundCount - - const statistics = { - total, - boundCount, - unboundCount, - success: true - } - - console.log('耳标设备统计信息获取成功:', statistics) - return statistics - } - - throw new Error('无法获取统计数据') - } catch (error) { - console.error('获取耳标设备统计信息失败:', error) - throw error - } -} - -/** - * 更新智能耳标设备 - * @param {string} id - 设备ID - * @param {Object} data - 更新数据 - * @returns {Promise} API响应 - */ -export const updateEarTagDevice = async (id, data) => { - try { - console.log('正在更新耳标设备...', id, data) - const response = await api.put(`/api/iot-jbq-client/${id}`, data) - console.log('更新耳标设备成功:', response.data) - return response.data - } catch (error) { - console.error('更新耳标设备失败:', error) - throw error - } -} - -/** - * 删除智能耳标设备 - * @param {string} id - 设备ID - * @returns {Promise} API响应 - */ -export const deleteEarTagDevice = async (id) => { - try { - console.log('正在删除耳标设备...', id) - const response = await api.delete(`/api/iot-jbq-client/${id}`) - console.log('删除耳标设备成功:', response.data) - return response.data - } catch (error) { - console.error('删除耳标设备失败:', error) - throw error - } -} - -// 保持向后兼容的别名 -export const getEarTagDevices = getAllEarTagDevices - -/** - * 绑定耳标设备 - * @param {string} earTagId - 耳标ID - * @param {string} animalId - 动物ID - * @returns {Promise} API响应 - */ -export const bindEarTag = async (earTagId, animalId) => { - try { - const response = await api.post('/api/smart-devices/eartags/bind', { - earTagId, - animalId - }) - return response.data - } catch (error) { - console.error('绑定耳标设备失败:', error) - throw error - } -} - -/** - * 解绑耳标设备 - * @param {string} earTagId - 耳标ID - * @returns {Promise} API响应 - */ -export const unbindEarTag = async (earTagId) => { - try { - const response = await api.post('/api/smart-devices/eartags/unbind', { - earTagId - }) - return response.data - } catch (error) { - console.error('解绑耳标设备失败:', error) - throw error - } -} - -/** - * 获取耳标设备详情 - * @param {string} earTagId - 耳标ID - * @returns {Promise} API响应 - */ -export const getEarTagDetail = async (earTagId) => { - try { - const response = await api.get(`/api/smart-devices/eartags/${earTagId}`) - return response.data - } catch (error) { - console.error('获取耳标设备详情失败:', error) - throw error - } -} - -/** - * 更新耳标设备信息 - * @param {string} earTagId - 耳标ID - * @param {Object} data - 更新数据 - * @returns {Promise} API响应 - */ -export const updateEarTag = async (earTagId, data) => { - try { - const response = await api.put(`/api/smart-devices/eartags/${earTagId}`, data) - return response.data - } catch (error) { - console.error('更新耳标设备失败:', error) - throw error - } -} - -/** - * 删除耳标设备 - * @param {string} earTagId - 耳标ID - * @returns {Promise} API响应 - */ -export const deleteEarTag = async (earTagId) => { - try { - const response = await api.delete(`/api/smart-devices/eartags/${earTagId}`) - return response.data - } catch (error) { - console.error('删除耳标设备失败:', error) - throw error - } -} - -export default { - // 新的API方法 - getAllEarTagDevices, - getEarTagDevicesByCid, - getEarTagDeviceById, - updateEarTagDevice, - deleteEarTagDevice, - - // 向后兼容的别名 - getEarTagDevices, - - // 原有的绑定/解绑方法 - bindEarTag, - unbindEarTag, - getEarTagDetail, - updateEarTag, - deleteEarTag -} diff --git a/mini_program/farm-monitor-dashboard/src/services/fenceService.js b/mini_program/farm-monitor-dashboard/src/services/fenceService.js deleted file mode 100644 index 3c36978..0000000 --- a/mini_program/farm-monitor-dashboard/src/services/fenceService.js +++ /dev/null @@ -1,198 +0,0 @@ -import { get, post, put, del } from './api' - -// 电子围栏API服务 -export const fenceService = { - // 获取围栏列表 - getFences(params = {}) { - return get('/electronic-fence', params) - }, - - // 获取单个围栏详情 - getFenceById(id) { - return get(`/electronic-fence/${id}`) - }, - - // 创建围栏 - createFence(data) { - return post('/electronic-fence', data) - }, - - // 更新围栏 - updateFence(id, data) { - return put(`/electronic-fence/${id}`, data) - }, - - // 删除围栏 - deleteFence(id) { - return del(`/electronic-fence/${id}`) - }, - - // 搜索围栏 - searchFences(params) { - return get('/electronic-fence/search', params) - } -} - -// 电子围栏坐标点API服务 -export const fencePointService = { - // 获取围栏的所有坐标点 - getByFenceId(fenceId) { - return get(`/electronic-fence-points/fence/${fenceId}`) - }, - - // 获取单个坐标点详情 - getPointById(id) { - return get(`/electronic-fence-points/${id}`) - }, - - // 创建坐标点 - createPoint(data) { - return post('/electronic-fence-points', data) - }, - - // 批量创建坐标点 - createPoints(data) { - return post('/electronic-fence-points/batch', data) - }, - - // 更新坐标点 - updatePoint(id, data) { - return put(`/electronic-fence-points/${id}`, data) - }, - - // 更新围栏的所有坐标点 - updateFencePoints(fenceId, data) { - return put(`/electronic-fence-points/fence/${fenceId}`, data) - }, - - // 删除坐标点 - deletePoint(id) { - return del(`/electronic-fence-points/${id}`) - }, - - // 删除围栏的所有坐标点 - deleteFencePoints(fenceId) { - return del(`/electronic-fence-points/fence/${fenceId}`) - }, - - // 获取围栏边界框 - getFenceBounds(fenceId) { - return get(`/electronic-fence-points/fence/${fenceId}/bounds`) - }, - - // 搜索坐标点 - searchPoints(params) { - return get('/electronic-fence-points/search', params) - } -} - -// 围栏类型配置 -export const fenceTypes = { - grazing: { - name: '放牧区', - color: '#52c41a', - icon: '🌿' - }, - safety: { - name: '安全区', - color: '#1890ff', - icon: '🛡️' - }, - restricted: { - name: '限制区', - color: '#ff4d4f', - icon: '⚠️' - }, - collector: { - name: '收集区', - color: '#fa8c16', - icon: '📦' - } -} - -// 围栏工具函数 -export const fenceUtils = { - // 计算多边形中心点 - calculateCenter(points) { - if (points.length === 0) return { lng: 0, lat: 0 } - - let lngSum = 0 - let latSum = 0 - - points.forEach(point => { - lngSum += point.lng - latSum += point.lat - }) - - return { - lng: lngSum / points.length, - lat: latSum / points.length - } - }, - - // 计算多边形面积(简化计算) - calculateArea(points) { - if (points.length < 3) return 0 - - let area = 0 - const n = points.length - - for (let i = 0; i < n; i++) { - const j = (i + 1) % n - area += points[i].lng * points[j].lat - area -= points[j].lng * points[i].lat - } - - area = Math.abs(area) / 2 - - // 转换为平方米(粗略计算) - return area * 111000 * 111000 - }, - - // 验证围栏数据 - validateFence(fence) { - const errors = [] - - if (!fence.name || fence.name.trim() === '') { - errors.push('围栏名称不能为空') - } - - if (!fence.type) { - errors.push('请选择围栏类型') - } - - if (!fence.coordinates || fence.coordinates.length < 3) { - errors.push('围栏至少需要3个坐标点') - } - - return { - valid: errors.length === 0, - errors - } - }, - - // 格式化围栏数据 - formatFenceData(rawData) { - return { - id: rawData.id, - name: rawData.name, - type: rawData.type, - description: rawData.description || '', - coordinates: rawData.coordinates || [], - center_lng: rawData.center_lng, - center_lat: rawData.center_lat, - area: rawData.area, - farm_id: rawData.farm_id, - is_active: rawData.is_active !== false, - created_at: rawData.created_at, - updated_at: rawData.updated_at - } - } -} - -export default { - fenceService, - fencePointService, - fenceTypes, - fenceUtils -} diff --git a/mini_program/farm-monitor-dashboard/src/services/homeService.js b/mini_program/farm-monitor-dashboard/src/services/homeService.js deleted file mode 100644 index 1fb5a3c..0000000 --- a/mini_program/farm-monitor-dashboard/src/services/homeService.js +++ /dev/null @@ -1,240 +0,0 @@ -import { get } from './api' - -// 获取首页统计信息 -export const getHomeStats = async () => { - try { - const data = await get('/home/stats') - return data - } catch (error) { - console.error('获取首页统计失败:', error) - // 返回默认数据 - return { - totalCattle: 0, - pregnantCattle: 0, - sickCattle: 0, - totalFarms: 0 - } - } -} - -// 获取最近活动记录 -export const getRecentActivities = async () => { - try { - const data = await get('/activities/recent') - return data - } catch (error) { - console.error('获取最近活动失败:', error) - // 返回空数组 - return [] - } -} - -// 获取牛只状态分布 -export const getCattleStatusDistribution = async () => { - try { - const data = await get('/cattle/status-distribution') - return data - } catch (error) { - console.error('获取牛只状态分布失败:', error) - return {} - } -} - -// 获取养殖场统计 -export const getFarmStatistics = async () => { - try { - const data = await get('/farms/statistics') - return data - } catch (error) { - console.error('获取养殖场统计失败:', error) - return {} - } -} - -// 获取预警信息 -export const getAlerts = async () => { - try { - const data = await get('/alerts') - return data - } catch (error) { - console.error('获取预警信息失败:', error) - return [] - } -} - -// 获取待办事项 -export const getTodos = async () => { - try { - const data = await get('/todos') - return data - } catch (error) { - console.error('获取待办事项失败:', error) - return [] - } -} - -// 获取天气信息 -export const getWeather = async (location) => { - try { - const params = location ? { location } : {} - const data = await get('/weather', params) - return data - } catch (error) { - console.error('获取天气信息失败:', error) - return {} - } -} - -// 获取市场行情 -export const getMarketPrices = async () => { - try { - const data = await get('/market/prices') - return data - } catch (error) { - console.error('获取市场行情失败:', error) - return {} - } -} - -// 获取通知消息 -export const getNotifications = async () => { - try { - const data = await get('/notifications') - return data - } catch (error) { - console.error('获取通知消息失败:', error) - return [] - } -} - -// 标记通知为已读 -export const markNotificationAsRead = async (notificationId) => { - try { - await post(`/notifications/${notificationId}/read`) - return true - } catch (error) { - console.error('标记通知为已读失败:', error) - return false - } -} - -// 获取系统公告 -export const getAnnouncements = async () => { - try { - const data = await get('/announcements') - return data - } catch (error) { - console.error('获取系统公告失败:', error) - return [] - } -} - -// 获取用户仪表盘配置 -export const getDashboardConfig = async () => { - try { - const data = await get('/user/dashboard-config') - return data - } catch (error) { - console.error('获取仪表盘配置失败:', error) - return {} - } -} - -// 更新用户仪表盘配置 -export const updateDashboardConfig = async (config) => { - try { - const data = await post('/user/dashboard-config', config) - return data - } catch (error) { - console.error('更新仪表盘配置失败:', error) - return false - } -} - -// 获取首页图表数据 -export const getChartData = async (chartType, params = {}) => { - try { - const data = await get(`/charts/${chartType}`, params) - return data - } catch (error) { - console.error('获取图表数据失败:', error) - return {} - } -} - -// 获取首页快速统计数据 -export const getQuickStats = async () => { - try { - const data = await get('/home/quick-stats') - return data - } catch (error) { - console.error('获取快速统计数据失败:', error) - return {} - } -} - -// 获取首页推荐操作 -export const getRecommendedActions = async () => { - try { - const data = await get('/home/recommended-actions') - return data - } catch (error) { - console.error('获取推荐操作失败:', error) - return [] - } -} - -// 获取首页时间线数据 -export const getTimelineData = async () => { - try { - const data = await get('/home/timeline') - return data - } catch (error) { - console.error('获取时间线数据失败:', error) - return [] - } -} - -// 获取首页资源使用情况 -export const getResourceUsage = async () => { - try { - const data = await get('/home/resource-usage') - return data - } catch (error) { - console.error('获取资源使用情况失败:', error) - return {} - } -} - -// 获取首页性能指标 -export const getPerformanceMetrics = async () => { - try { - const data = await get('/home/performance-metrics') - return data - } catch (error) { - console.error('获取性能指标失败:', error) - return {} - } -} - -export default { - getHomeStats, - getRecentActivities, - getCattleStatusDistribution, - getFarmStatistics, - getAlerts, - getTodos, - getWeather, - getMarketPrices, - getNotifications, - markNotificationAsRead, - getAnnouncements, - getDashboardConfig, - updateDashboardConfig, - getChartData, - getQuickStats, - getRecommendedActions, - getTimelineData, - getResourceUsage, - getPerformanceMetrics -} \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/services/hostService.js b/mini_program/farm-monitor-dashboard/src/services/hostService.js deleted file mode 100644 index cb91d5f..0000000 --- a/mini_program/farm-monitor-dashboard/src/services/hostService.js +++ /dev/null @@ -1,227 +0,0 @@ -import axios from 'axios' - -// 创建axios实例 -const api = axios.create({ - baseURL: process.env.VUE_APP_API_BASE_URL || 'http://localhost:5350', - timeout: 10000, - headers: { - 'Content-Type': 'application/json' - } -}) - -// 请求拦截器 -api.interceptors.request.use( - config => { - // 尝试多种token存储方式 - const token = localStorage.getItem('token') || - localStorage.getItem('authToken') || - localStorage.getItem('accessToken') || - sessionStorage.getItem('token') || - sessionStorage.getItem('authToken') - - if (token) { - config.headers.Authorization = `Bearer ${token}` - console.log('使用认证token:', token.substring(0, 10) + '...') - } else { - console.warn('未找到认证token,尝试无认证访问') - // 尝试其他认证方式 - const apiKey = localStorage.getItem('apiKey') - if (apiKey) { - config.headers['X-API-Key'] = apiKey - console.log('使用API Key认证') - } - } - return config - }, - error => { - return Promise.reject(error) - } -) - -// 响应拦截器 -api.interceptors.response.use( - response => { - return response - }, - error => { - console.error('API请求错误:', error) - return Promise.reject(error) - } -) - -/** - * 获取智能主机设备列表 - * @param {Object} params - 查询参数 (page, pageSize, search等) - * @returns {Promise} API响应 - */ -// 模拟数据生成器 -const generateMockHostDevices = (page = 1, pageSize = 10) => { - const totalDevices = 25 // 模拟总共25台设备 - const startIndex = (page - 1) * pageSize - const endIndex = Math.min(startIndex + pageSize, totalDevices) - - const devices = [] - for (let i = startIndex; i < endIndex; i++) { - const deviceId = `2490246${String(426 + i).padStart(3, '0')}` - devices.push({ - hostId: deviceId, - sid: deviceId, - isOnline: Math.random() > 0.3, // 70% 在线概率 - battery: Math.floor(Math.random() * 40) + 60, // 60-100% - voltage: Math.floor(Math.random() * 40) + 60, - signal: Math.floor(Math.random() * 50) + 10, // 10-60% - signa: Math.floor(Math.random() * 50) + 10, - temperature: (Math.random() * 10 + 20).toFixed(1), // 20-30°C - state: Math.random() > 0.2 ? 1 : 0, // 80% 连接状态 - bandge_status: Math.random() > 0.2 ? 1 : 0, - updateTime: new Date(Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1000).toLocaleString('zh-CN', { - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit' - }).replace(/\//g, '-'), - lastUpdateTime: new Date(Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1000).toLocaleString('zh-CN', { - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit' - }).replace(/\//g, '-') - }) - } - - return { - data: devices, - pagination: { - currentPage: page, - pageSize: pageSize, - total: totalDevices, - totalPages: Math.ceil(totalDevices / pageSize) - } - } -} - -export const getHostDevices = async (params = {}) => { - console.log('正在调用真实API获取主机设备列表...', params) - - const response = await api.get('/api/smart-devices/hosts', { - params: { - page: params.page || 1, - pageSize: params.pageSize || 10, - search: params.search || '', - ...params - } - }) - - console.log('API响应成功:', response.data) - - // 根据API响应结构处理数据 - const apiData = response.data - - // 如果API返回的数据结构包含data字段和total字段 - if (apiData.success && apiData.data) { - return { - data: apiData.data, - pagination: { - currentPage: params.page || 1, - pageSize: params.pageSize || 10, - total: apiData.total || apiData.data.length, - totalPages: Math.ceil((apiData.total || apiData.data.length) / (params.pageSize || 10)) - } - } - } - - // 如果API直接返回数组 - if (Array.isArray(apiData)) { - return { - data: apiData, - pagination: { - currentPage: params.page || 1, - pageSize: params.pageSize || 10, - total: apiData.length, - totalPages: Math.ceil(apiData.length / (params.pageSize || 10)) - } - } - } - - // 默认返回API数据 - return apiData -} - -/** - * 重启主机设备 - * @param {string} hostId - 主机ID - * @returns {Promise} API响应 - */ -export const restartHost = async (hostId) => { - try { - const response = await api.post('/api/smart-devices/hosts/restart', { - hostId - }) - return response.data - } catch (error) { - console.error('重启主机设备失败:', error) - throw error - } -} - -/** - * 启动主机设备 - * @param {string} hostId - 主机ID - * @returns {Promise} API响应 - */ -export const startHost = async (hostId) => { - try { - const response = await api.post('/api/smart-devices/hosts/start', { - hostId - }) - return response.data - } catch (error) { - console.error('启动主机设备失败:', error) - throw error - } -} - -/** - * 停止主机设备 - * @param {string} hostId - 主机ID - * @returns {Promise} API响应 - */ -export const stopHost = async (hostId) => { - try { - const response = await api.post('/api/smart-devices/hosts/stop', { - hostId - }) - return response.data - } catch (error) { - console.error('停止主机设备失败:', error) - throw error - } -} - -/** - * 更新主机设备信息 - * @param {string} hostId - 主机ID - * @param {Object} updateData - 更新数据 - * @returns {Promise} API响应 - */ -export const updateHostDevice = async (hostId, updateData) => { - try { - const response = await api.put(`/api/smart-devices/hosts/${hostId}`, updateData) - return response.data - } catch (error) { - console.error('更新主机设备信息失败:', error) - throw error - } -} - -export default { - getHostDevices, - restartHost, - startHost, - stopHost, - updateHostDevice -} diff --git a/mini_program/farm-monitor-dashboard/src/services/smartDeviceService.js b/mini_program/farm-monitor-dashboard/src/services/smartDeviceService.js deleted file mode 100644 index deeea9d..0000000 --- a/mini_program/farm-monitor-dashboard/src/services/smartDeviceService.js +++ /dev/null @@ -1,140 +0,0 @@ -import axios from 'axios' - -// 创建axios实例 -const api = axios.create({ - baseURL: process.env.VUE_APP_API_BASE_URL || 'http://localhost:5350', - timeout: 10000, - headers: { - 'Content-Type': 'application/json' - } -}) - -// 请求拦截器 -api.interceptors.request.use( - config => { - const token = localStorage.getItem('token') - if (token) { - config.headers.Authorization = `Bearer ${token}` - } - return config - }, - error => { - return Promise.reject(error) - } -) - -// 响应拦截器 -api.interceptors.response.use( - response => { - return response - }, - error => { - console.error('API请求错误:', error) - return Promise.reject(error) - } -) - -/** - * 设备搜索和状态监控 - * @param {Object} params - 搜索参数 - * @returns {Promise} API响应 - */ -export const searchDevices = async (params = {}) => { - try { - const response = await api.get('/api/smart-devices/search', { params }) - return response.data - } catch (error) { - console.error('搜索设备失败:', error) - throw error - } -} - -/** - * 获取设备状态监控数据 - * @param {Object} params - 查询参数 - * @returns {Promise} API响应 - */ -export const getDeviceStatus = async (params = {}) => { - try { - const response = await api.get('/api/smart-devices/status', { params }) - return response.data - } catch (error) { - console.error('获取设备状态失败:', error) - throw error - } -} - -/** - * 获取所有智能设备统计信息 - * @returns {Promise} API响应 - */ -export const getDeviceStatistics = async () => { - try { - const response = await api.get('/api/smart-devices/statistics') - return response.data - } catch (error) { - console.error('获取设备统计信息失败:', error) - throw error - } -} - -/** - * 批量更新设备状态 - * @param {Array} deviceIds - 设备ID数组 - * @param {Object} statusData - 状态数据 - * @returns {Promise} API响应 - */ -export const batchUpdateDeviceStatus = async (deviceIds, statusData) => { - try { - const response = await api.post('/api/smart-devices/batch-update', { - deviceIds, - statusData - }) - return response.data - } catch (error) { - console.error('批量更新设备状态失败:', error) - throw error - } -} - -/** - * 获取设备实时数据 - * @param {string} deviceId - 设备ID - * @param {string} deviceType - 设备类型 (collar, eartag, anklet, host) - * @returns {Promise} API响应 - */ -export const getDeviceRealtimeData = async (deviceId, deviceType) => { - try { - const response = await api.get(`/api/smart-devices/${deviceType}/${deviceId}/realtime`) - return response.data - } catch (error) { - console.error('获取设备实时数据失败:', error) - throw error - } -} - -/** - * 获取设备历史数据 - * @param {string} deviceId - 设备ID - * @param {string} deviceType - 设备类型 - * @param {Object} params - 查询参数 (时间范围等) - * @returns {Promise} API响应 - */ -export const getDeviceHistoryData = async (deviceId, deviceType, params = {}) => { - try { - const response = await api.get(`/api/smart-devices/${deviceType}/${deviceId}/history`, { params }) - return response.data - } catch (error) { - console.error('获取设备历史数据失败:', error) - throw error - } -} - -export default { - searchDevices, - getDeviceStatus, - getDeviceStatistics, - batchUpdateDeviceStatus, - getDeviceRealtimeData, - getDeviceHistoryData -} diff --git a/mini_program/farm-monitor-dashboard/src/services/smsService.js b/mini_program/farm-monitor-dashboard/src/services/smsService.js deleted file mode 100644 index adf93f6..0000000 --- a/mini_program/farm-monitor-dashboard/src/services/smsService.js +++ /dev/null @@ -1,141 +0,0 @@ -import axios from 'axios' - -// 创建axios实例 -const api = axios.create({ - baseURL: process.env.VUE_APP_API_BASE_URL || 'http://localhost:5350', - timeout: 10000, - headers: { - 'Content-Type': 'application/json' - } -}) - -// 请求拦截器 -api.interceptors.request.use( - config => { - const token = localStorage.getItem('token') - if (token) { - config.headers.Authorization = `Bearer ${token}` - } - return config - }, - error => { - return Promise.reject(error) - } -) - -// 响应拦截器 -api.interceptors.response.use( - response => { - return response - }, - error => { - console.error('SMS API请求错误:', error) - return Promise.reject(error) - } -) - -/** - * 发送短信验证码 - * @param {string} phone - 手机号 - * @param {string} type - 验证码类型 (login, register, reset) - * @returns {Promise} API响应 - */ -export const sendSmsCode = async (phone, type = 'login') => { - try { - const response = await api.post('/api/sms/send', { - phone, - type - }) - return response.data - } catch (error) { - console.error('发送短信验证码失败:', error) - // 模拟发送成功 - return { - success: true, - message: '验证码已发送', - data: { - codeId: 'sms_' + Date.now(), - expireTime: Date.now() + 5 * 60 * 1000 // 5分钟后过期 - } - } - } -} - -/** - * 验证短信验证码 - * @param {string} phone - 手机号 - * @param {string} code - 验证码 - * @param {string} type - 验证码类型 - * @returns {Promise} API响应 - */ -export const verifySmsCode = async (phone, code, type = 'login') => { - try { - const response = await api.post('/api/sms/verify', { - phone, - code, - type - }) - return response.data - } catch (error) { - console.error('验证短信验证码失败:', error) - // 模拟验证成功(开发环境) - if (process.env.NODE_ENV === 'development') { - return { - success: true, - message: '验证码验证成功', - data: { - isValid: true, - token: 'sms_token_' + Date.now() - } - } - } - throw error - } -} - -/** - * 检查手机号是否已注册 - * @param {string} phone - 手机号 - * @returns {Promise} API响应 - */ -export const checkPhoneExists = async (phone) => { - try { - const response = await api.get(`/api/user/check-phone/${phone}`) - return response.data - } catch (error) { - console.error('检查手机号失败:', error) - // 模拟检查结果 - return { - success: true, - data: { - exists: true, - canLogin: true - } - } - } -} - -/** - * 获取验证码发送记录 - * @param {string} phone - 手机号 - * @returns {Promise} API响应 - */ -export const getSmsHistory = async (phone) => { - try { - const response = await api.get(`/api/sms/history/${phone}`) - return response.data - } catch (error) { - console.error('获取短信记录失败:', error) - return { - success: true, - data: [] - } - } -} - -export default { - sendSmsCode, - verifySmsCode, - checkPhoneExists, - getSmsHistory -} diff --git a/mini_program/farm-monitor-dashboard/src/services/userService.js b/mini_program/farm-monitor-dashboard/src/services/userService.js deleted file mode 100644 index 5fe8437..0000000 --- a/mini_program/farm-monitor-dashboard/src/services/userService.js +++ /dev/null @@ -1,190 +0,0 @@ -import axios from 'axios' - -// 创建axios实例 -const api = axios.create({ - baseURL: process.env.VUE_APP_API_BASE_URL || 'http://localhost:5350', - timeout: 10000, - headers: { - 'Content-Type': 'application/json' - } -}) - -// 请求拦截器 -api.interceptors.request.use( - config => { - const token = localStorage.getItem('token') - if (token) { - config.headers.Authorization = `Bearer ${token}` - } - return config - }, - error => { - return Promise.reject(error) - } -) - -// 响应拦截器 -api.interceptors.response.use( - response => { - return response - }, - error => { - console.error('User API请求错误:', error) - return Promise.reject(error) - } -) - -/** - * 用户注册 - * @param {Object} userData - 用户注册数据 - * @returns {Promise} API响应 - */ -export const registerUser = async (userData) => { - try { - const response = await api.post('/api/user/register', userData) - return response.data - } catch (error) { - console.error('用户注册失败:', error) - // 模拟注册成功 - return { - success: true, - message: '注册成功', - data: { - userId: 'user_' + Date.now(), - token: 'register_token_' + Date.now(), - userInfo: { - id: 'user_' + Date.now(), - name: userData.realName, - phone: userData.phone, - role: 'user', - registerTime: new Date().toISOString() - } - } - } - } -} - -/** - * 检查手机号是否已注册 - * @param {string} phone - 手机号 - * @returns {Promise} API响应 - */ -export const checkPhoneExists = async (phone) => { - try { - const response = await api.get(`/api/user/check-phone/${phone}`) - return response.data - } catch (error) { - console.error('检查手机号失败:', error) - // 模拟检查结果 - return { - success: true, - data: { - exists: false, - canRegister: true - } - } - } -} - -/** - * 检查用户名是否已存在 - * @param {string} username - 用户名 - * @returns {Promise} API响应 - */ -export const checkUsernameExists = async (username) => { - try { - const response = await api.get(`/api/user/check-username/${username}`) - return response.data - } catch (error) { - console.error('检查用户名失败:', error) - return { - success: true, - data: { - exists: false, - canUse: true - } - } - } -} - -/** - * 获取用户信息 - * @param {string} userId - 用户ID - * @returns {Promise} API响应 - */ -export const getUserInfo = async (userId) => { - try { - const response = await api.get(`/api/user/${userId}`) - return response.data - } catch (error) { - console.error('获取用户信息失败:', error) - throw error - } -} - -/** - * 更新用户信息 - * @param {string} userId - 用户ID - * @param {Object} userData - 用户数据 - * @returns {Promise} API响应 - */ -export const updateUserInfo = async (userId, userData) => { - try { - const response = await api.put(`/api/user/${userId}`, userData) - return response.data - } catch (error) { - console.error('更新用户信息失败:', error) - throw error - } -} - -/** - * 修改密码 - * @param {string} userId - 用户ID - * @param {string} oldPassword - 旧密码 - * @param {string} newPassword - 新密码 - * @returns {Promise} API响应 - */ -export const changePassword = async (userId, oldPassword, newPassword) => { - try { - const response = await api.post(`/api/user/${userId}/change-password`, { - oldPassword, - newPassword - }) - return response.data - } catch (error) { - console.error('修改密码失败:', error) - throw error - } -} - -/** - * 重置密码 - * @param {string} phone - 手机号 - * @param {string} verificationCode - 验证码 - * @param {string} newPassword - 新密码 - * @returns {Promise} API响应 - */ -export const resetPassword = async (phone, verificationCode, newPassword) => { - try { - const response = await api.post('/api/user/reset-password', { - phone, - verificationCode, - newPassword - }) - return response.data - } catch (error) { - console.error('重置密码失败:', error) - throw error - } -} - -export default { - registerUser, - checkPhoneExists, - checkUsernameExists, - getUserInfo, - updateUserInfo, - changePassword, - resetPassword -} diff --git a/mini_program/farm-monitor-dashboard/src/utils/auth.js b/mini_program/farm-monitor-dashboard/src/utils/auth.js deleted file mode 100644 index a007a18..0000000 --- a/mini_program/farm-monitor-dashboard/src/utils/auth.js +++ /dev/null @@ -1,106 +0,0 @@ -import { login as apiLogin, validateToken } from '@/services/authService' - -// 认证工具类 -export const auth = { - // 设置认证token - setToken(token) { - localStorage.setItem('token', token) - console.log('Token已设置:', token.substring(0, 20) + '...') - }, - - // 获取认证token - getToken() { - return localStorage.getItem('token') - }, - - // 清除认证token - clearToken() { - localStorage.removeItem('token') - console.log('Token已清除') - }, - - // 检查是否已认证 - isAuthenticated() { - return !!this.getToken() - }, - - // 设置测试token(用于开发测试) - async setTestToken() { - // 首先检查是否已经有有效的token - const existingToken = this.getToken() - if (existingToken && existingToken.startsWith('eyJ')) { - console.log('使用现有JWT token') - return existingToken - } - - try { - // 尝试使用测试账号登录获取真实token - console.log('开始API登录...') - const response = await apiLogin('admin', '123456') - console.log('API登录响应:', response) - - if (response && response.success && response.token) { - this.setToken(response.token) - console.log('成功获取真实token:', response.token.substring(0, 20) + '...') - return response.token - } else { - console.error('API响应格式不正确:', response) - throw new Error('API响应格式不正确') - } - } catch (error) { - console.error('无法通过API获取测试token:', error.message) - throw error - } - }, - - // 验证当前token是否有效 - async validateCurrentToken() { - const token = this.getToken() - if (!token) { - return false - } - - try { - await validateToken(token) - return true - } catch (error) { - console.warn('Token验证失败:', error.message) - this.clearToken() - return false - } - }, - - // 设置用户信息 - setUserInfo(userInfo) { - localStorage.setItem('userInfo', JSON.stringify(userInfo)) - }, - - // 获取用户信息 - getUserInfo() { - const userInfo = localStorage.getItem('userInfo') - return userInfo ? JSON.parse(userInfo) : null - }, - - // 清除用户信息 - clearUserInfo() { - localStorage.removeItem('userInfo') - }, - - // 登出 - logout() { - this.clearToken() - this.clearUserInfo() - console.log('用户已登出') - }, - - // 手动设置真实token(用于开发测试) - setRealToken() { - // 这是一个真实的JWT token,用于测试 - const realToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5jb20iLCJpYXQiOjE3NTgxODM3NjEsImV4cCI6MTc1ODI3MDE2MX0.J3DD78bULP1pe5DMF2zbQEMFzeytV6uXgOuDIKOPww0' - this.setToken(realToken) - console.log('手动设置真实token') - return realToken - } -} - -export default auth \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/utils/index.js b/mini_program/farm-monitor-dashboard/src/utils/index.js deleted file mode 100644 index 28951c2..0000000 --- a/mini_program/farm-monitor-dashboard/src/utils/index.js +++ /dev/null @@ -1,345 +0,0 @@ -// 工具函数集合 - -// 防抖函数 -export const debounce = (func, wait, immediate) => { - let timeout - return function executedFunction(...args) { - const later = () => { - timeout = null - if (!immediate) func.apply(this, args) - } - const callNow = immediate && !timeout - clearTimeout(timeout) - timeout = setTimeout(later, wait) - if (callNow) func.apply(this, args) - } -} - -// 节流函数 -export const throttle = (func, limit) => { - let inThrottle - return function(...args) { - if (!inThrottle) { - func.apply(this, args) - inThrottle = true - setTimeout(() => (inThrottle = false), limit) - } - } -} - -// 深拷贝 -export const deepClone = (obj) => { - if (obj === null || typeof obj !== 'object') return obj - if (obj instanceof Date) return new Date(obj.getTime()) - if (obj instanceof Array) return obj.map(item => deepClone(item)) - if (typeof obj === 'object') { - const clonedObj = {} - for (const key in obj) { - if (obj.hasOwnProperty(key)) { - clonedObj[key] = deepClone(obj[key]) - } - } - return clonedObj - } -} - -// 格式化日期 -export const formatDate = (date, format = 'YYYY-MM-DD') => { - if (!date) return '' - - const d = new Date(date) - const year = d.getFullYear() - const month = String(d.getMonth() + 1).padStart(2, '0') - const day = String(d.getDate()).padStart(2, '0') - const hours = String(d.getHours()).padStart(2, '0') - const minutes = String(d.getMinutes()).padStart(2, '0') - const seconds = String(d.getSeconds()).padStart(2, '0') - - return format - .replace('YYYY', year) - .replace('MM', month) - .replace('DD', day) - .replace('HH', hours) - .replace('mm', minutes) - .replace('ss', seconds) -} - -// 格式化数字(千分位) -export const formatNumber = (num, decimals = 0) => { - if (num === null || num === undefined) return '0' - - const number = Number(num) - if (isNaN(number)) return '0' - - return number.toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ',') -} - -// 手机号脱敏 -export const maskPhone = (phone) => { - if (!phone) return '' - return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') -} - -// 邮箱脱敏 -export const maskEmail = (email) => { - if (!email) return '' - const [name, domain] = email.split('@') - if (name.length <= 2) { - return `${name}****@${domain}` - } - return `${name.substring(0, 2)}****${name.substring(name.length - 1)}@${domain}` -} - -// 获取文件扩展名 -export const getFileExtension = (filename) => { - return filename.slice((filename.lastIndexOf('.') - 1 >>> 0) + 2) -} - -// 文件大小格式化 -export const formatFileSize = (bytes) => { - if (bytes === 0) return '0 Bytes' - - const k = 1024 - const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'] - const i = Math.floor(Math.log(bytes) / Math.log(k)) - - return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i] -} - -// 生成随机ID -export const generateId = (length = 8) => { - const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' - let result = '' - for (let i = 0; i < length; i++) { - result += chars.charAt(Math.floor(Math.random() * chars.length)) - } - return result -} - -// 数组去重 -export const uniqueArray = (arr, key) => { - if (key) { - const seen = new Set() - return arr.filter(item => { - const value = item[key] - if (seen.has(value)) { - return false - } - seen.add(value) - return true - }) - } - return [...new Set(arr)] -} - -// 对象数组排序 -export const sortBy = (arr, key, order = 'asc') => { - return arr.sort((a, b) => { - const valueA = a[key] - const valueB = b[key] - - if (typeof valueA === 'string' && typeof valueB === 'string') { - return order === 'asc' - ? valueA.localeCompare(valueB) - : valueB.localeCompare(valueA) - } - - return order === 'asc' ? valueA - valueB : valueB - valueA - }) -} - -// 获取URL参数 -export const getUrlParams = (url = '') => { - const params = {} - const urlObj = new URL(url, window.location.origin) - urlObj.searchParams.forEach((value, key) => { - params[key] = value - }) - return params -} - -// 构建URL参数 -export const buildUrlParams = (params) => { - const searchParams = new URLSearchParams() - Object.keys(params).forEach(key => { - if (params[key] !== null && params[key] !== undefined) { - searchParams.append(key, params[key]) - } - }) - return searchParams.toString() -} - -// 本地存储封装 -export const storage = { - set: (key, value) => { - try { - localStorage.setItem(key, JSON.stringify(value)) - } catch (error) { - console.error('存储数据失败:', error) - } - }, - - get: (key, defaultValue = null) => { - try { - const value = localStorage.getItem(key) - return value !== null && value !== undefined ? JSON.parse(value) : defaultValue - } catch (error) { - console.error('获取存储数据失败:', error) - return defaultValue - } - }, - - remove: (key) => { - try { - localStorage.removeItem(key) - } catch (error) { - console.error('删除存储数据失败:', error) - } - }, - - clear: () => { - try { - localStorage.clear() - } catch (error) { - console.error('清空存储失败:', error) - } - } -} - -// 验证函数 -export const validators = { - // 验证手机号 - isPhone: (phone) => { - const reg = /^1[3-9]\d{9}$/ - return reg.test(phone) - }, - - // 验证邮箱 - isEmail: (email) => { - const reg = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ - return reg.test(email) - }, - - // 验证身份证号 - isIdCard: (idCard) => { - const reg = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/ - return reg.test(idCard) - }, - - // 验证密码强度 - isStrongPassword: (password) => { - // 至少8个字符,包含字母、数字和特殊字符 - const reg = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]).{8,}$/ - return reg.test(password) - }, - - // 验证URL - isUrl: (url) => { - try { - new URL(url) - return true - } catch { - return false - } - }, - - // 验证数字 - isNumber: (value) => { - return !isNaN(parseFloat(value)) && isFinite(value) - }, - - // 验证是否为空 - isEmpty: (value) => { - if (value === null || value === undefined) return true - if (typeof value === 'string') return value.trim() === '' - if (Array.isArray(value)) return value.length === 0 - if (typeof value === 'object') return Object.keys(value).length === 0 - return false - } -} - -// 颜色操作 -export const colorUtils = { - // 16进制转RGB - hexToRgb: (hex) => { - const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) - return result ? { - r: parseInt(result[1], 16), - g: parseInt(result[2], 16), - b: parseInt(result[3], 16) - } : null - }, - - // RGB转16进制 - rgbToHex: (r, g, b) => { - return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}` - }, - - // 颜色变亮 - lighten: (hex, percent) => { - const rgb = colorUtils.hexToRgb(hex) - if (!rgb) return hex - - const r = Math.min(255, rgb.r + (255 - rgb.r) * percent) - const g = Math.min(255, rgb.g + (255 - rgb.g) * percent) - const b = Math.min(255, rgb.b + (255 - rgb.b) * percent) - - return colorUtils.rgbToHex(Math.round(r), Math.round(g), Math.round(b)) - }, - - // 颜色变暗 - darken: (hex, percent) => { - const rgb = colorUtils.hexToRgb(hex) - if (!rgb) return hex - - const r = Math.max(0, rgb.r * (1 - percent)) - const g = Math.max(0, rgb.g * (1 - percent)) - const b = Math.max(0, rgb.b * (1 - percent)) - - return colorUtils.rgbToHex(Math.round(r), Math.round(g), Math.round(b)) - } -} - -// 性能监控 -export const perf = { - start: (name) => { - if (typeof performance !== 'undefined') { - performance.mark(`${name}-start`) - } - }, - - end: (name) => { - if (typeof performance !== 'undefined') { - performance.mark(`${name}-end`) - performance.measure(name, `${name}-start`, `${name}-end`) - const measures = performance.getEntriesByName(name) - const duration = measures[0]?.duration || 0 - performance.clearMarks(`${name}-start`) - performance.clearMarks(`${name}-end`) - performance.clearMeasures(name) - return duration - } - return 0 - } -} - -export default { - debounce, - throttle, - deepClone, - formatDate, - formatNumber, - maskPhone, - maskEmail, - getFileExtension, - formatFileSize, - generateId, - uniqueArray, - sortBy, - getUrlParams, - buildUrlParams, - storage, - validators, - colorUtils, - perf -} \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/src/utils/mapping.js b/mini_program/farm-monitor-dashboard/src/utils/mapping.js deleted file mode 100644 index 940bce4..0000000 --- a/mini_program/farm-monitor-dashboard/src/utils/mapping.js +++ /dev/null @@ -1,482 +0,0 @@ -/** - * 中文映射工具 - * 统一管理所有字段的中文映射 - */ - -// 性别映射 -export const sexMap = { - 1: '公', - 2: '母' -} - -// 品类映射(与后端保持一致) -export const categoryMap = { - 1: '犊牛', - 2: '育成母牛', - 3: '架子牛', - 4: '青年牛', - 5: '基础母牛', - 6: '育肥牛' -} - -// 品种映射 -export const breedMap = { - 1: '西藏高山牦牛', - 2: '宁夏牛', - 3: '华西牛', - 4: '秦川牛', - 5: '西门塔尔牛', - 6: '荷斯坦牛' -} - -// 品系映射 -export const strainMap = { - 1: '乳肉兼用', - 2: '肉用型', - 3: '乳用型', - 4: '兼用型' -} - -// 生理阶段映射(与后端parity字段对应) -export const physiologicalStageMap = { - 1: '犊牛', - 2: '育成期', - 3: '青年期', - 4: '成年期', - 5: '老年期', - 6: '怀孕期', - 7: '哺乳期' -} - -// 来源映射 -export const sourceMap = { - 1: '合作社', - 2: '农户', - 3: '养殖场', - 4: '进口', - 5: '自繁' -} - -// 事件映射 -export const eventMap = { - 1: '正常', - 2: '生病', - 3: '怀孕', - 4: '分娩', - 5: '断奶', - 6: '转栏', - 7: '离栏' -} - -// 是否佩戴设备映射 -export const wearMap = { - 0: '否', - 1: '是' -} - -// 是否删除映射 -export const deleteMap = { - 0: '否', - 1: '是' -} - -// 是否出栏映射 -export const outMap = { - 0: '否', - 1: '是' -} - -// 是否电子认证映射 -export const eleAuthMap = { - 0: '否', - 1: '是' -} - -// 是否检疫认证映射 -export const quaAuthMap = { - 0: '否', - 1: '是' -} - -// 是否免疫映射 -export const vaccinMap = { - 0: '否', - 1: '是' -} - -// 是否配种映射 -export const inseminationMap = { - 0: '否', - 1: '是' -} - -// 是否保险映射 -export const insureMap = { - 0: '否', - 1: '是' -} - -// 是否抵押映射 -export const mortgageMap = { - 0: '否', - 1: '是' -} - -// 销售状态映射 -export const sellStatusMap = { - 100: '在栏', - 200: '已售', - 300: '死亡', - 400: '淘汰' -} - -// 离栏原因映射 -export const exitReasonMap = { - '出售': '出售', - '死亡': '死亡', - '淘汰': '淘汰', - '转场': '转场', - '其他': '其他' -} - -// 处理方式映射 -export const disposalMethodMap = { - '屠宰': '屠宰', - '转售': '转售', - '掩埋': '掩埋', - '焚烧': '焚烧', - '其他': '其他' -} - -// 离栏状态映射 -export const exitStatusMap = { - '已确认': '已确认', - '待确认': '待确认', - '已取消': '已取消' -} - -// 栏舍类型映射 -export const penTypeMap = { - '产房': '产房', - '配种栏': '配种栏', - '隔离栏': '隔离栏', - '育成栏': '育成栏', - '育肥栏': '育肥栏', - '犊牛栏': '犊牛栏', - '母牛栏': '母牛栏', - '公牛栏': '公牛栏', - '病牛栏': '病牛栏', - '观察栏': '观察栏' -} - -// 栏舍状态映射 -export const penStatusMap = { - '启用': '启用', - '停用': '停用', - '维修': '维修', - '废弃': '废弃' -} - -// 批次类型映射 -export const batchTypeMap = { - '繁殖批次': '繁殖批次', - '育肥批次': '育肥批次', - '隔离批次': '隔离批次', - '育成批次': '育成批次', - '配种批次': '配种批次', - '分娩批次': '分娩批次', - '断奶批次': '断奶批次', - '观察批次': '观察批次' -} - -// 批次状态映射 -export const batchStatusMap = { - '进行中': '进行中', - '已完成': '已完成', - '已暂停': '已暂停', - '已取消': '已取消', - '待开始': '待开始' -} - -// 预警类型映射 - 与PC端保持一致 -export const alertTypeMap = { - 'battery': '低电量预警', - 'offline': '离线预警', - 'temperature': '温度预警', - 'movement': '异常运动预警', - 'wear': '佩戴异常预警', - 'location': '位置异常预警', - // 兼容旧字段 - 'lowBattery': '电量偏低', - 'highTemperature': '温度过高', - 'lowTemperature': '温度过低', - 'abnormalMovement': '运动异常', - 'wearOff': '项圈脱落', - 'notCollected': '今日未被采集', - 'highActivity': '运动量偏高', - 'lowActivity': '运动量偏低' -} - -// 预警级别映射 - 与PC端保持一致 -export const alertSeverityMap = { - 'high': '高级', - 'medium': '中级', - 'low': '低级', - 'critical': '紧急', - // 兼容旧字段 - 'warning': '一般', - 'info': '信息' -} - -// 预警状态映射 -export const alertStatusMap = { - 'unresolved': '未处理', - 'resolved': '已处理', - 'processing': '处理中' -} - -/** - * 获取性别中文名称 - * @param {number} sex 性别代码 - * @returns {string} 中文名称 - */ -export function getSexName(sex) { - return sexMap[sex] || '--' -} - -/** - * 获取品类中文名称 - * @param {number} cate 品类代码 - * @returns {string} 中文名称 - */ -export function getCategoryName(cate) { - return categoryMap[cate] || '--' -} - -/** - * 获取品种中文名称 - * @param {number} varieties 品种代码 - * @returns {string} 中文名称 - */ -export function getBreedName(varieties) { - return breedMap[varieties] || varieties || '--' -} - -/** - * 获取品系中文名称 - * @param {number} strain 品系代码 - * @returns {string} 中文名称 - */ -export function getStrainName(strain) { - return strainMap[strain] || strain || '--' -} - -/** - * 获取生理阶段中文名称 - * @param {number} level 生理阶段代码 - * @returns {string} 中文名称 - */ -export function getPhysiologicalStage(level) { - return physiologicalStageMap[level] || '--' -} - -/** - * 获取来源中文名称 - * @param {number} source 来源代码 - * @returns {string} 中文名称 - */ -export function getSourceName(source) { - return sourceMap[source] || '--' -} - -/** - * 获取事件中文名称 - * @param {number} event 事件代码 - * @returns {string} 中文名称 - */ -export function getEventName(event) { - return eventMap[event] || '--' -} - -/** - * 获取是否佩戴设备中文名称 - * @param {number} isWear 是否佩戴代码 - * @returns {string} 中文名称 - */ -export function getWearName(isWear) { - return wearMap[isWear] || '--' -} - -/** - * 获取销售状态中文名称 - * @param {number} sellStatus 销售状态代码 - * @returns {string} 中文名称 - */ -export function getSellStatusName(sellStatus) { - return sellStatusMap[sellStatus] || '--' -} - -/** - * 获取离栏原因中文名称 - * @param {string} exitReason 离栏原因 - * @returns {string} 中文名称 - */ -export function getExitReasonName(exitReason) { - return exitReasonMap[exitReason] || exitReason || '--' -} - -/** - * 获取处理方式中文名称 - * @param {string} disposalMethod 处理方式 - * @returns {string} 中文名称 - */ -export function getDisposalMethodName(disposalMethod) { - return disposalMethodMap[disposalMethod] || disposalMethod || '--' -} - -/** - * 获取离栏状态中文名称 - * @param {string} exitStatus 离栏状态 - * @returns {string} 中文名称 - */ -export function getExitStatusName(exitStatus) { - return exitStatusMap[exitStatus] || exitStatus || '--' -} - -/** - * 获取栏舍类型中文名称 - * @param {string} penType 栏舍类型 - * @returns {string} 中文名称 - */ -export function getPenTypeName(penType) { - return penTypeMap[penType] || penType || '--' -} - -/** - * 获取栏舍状态中文名称 - * @param {string} penStatus 栏舍状态 - * @returns {string} 中文名称 - */ -export function getPenStatusName(penStatus) { - return penStatusMap[penStatus] || penStatus || '--' -} - -/** - * 获取批次类型中文名称 - * @param {string} batchType 批次类型 - * @returns {string} 中文名称 - */ -export function getBatchTypeName(batchType) { - return batchTypeMap[batchType] || batchType || '--' -} - -/** - * 获取批次状态中文名称 - * @param {string} batchStatus 批次状态 - * @returns {string} 中文名称 - */ -export function getBatchStatusName(batchStatus) { - return batchStatusMap[batchStatus] || batchStatus || '--' -} - -/** - * 获取预警类型中文名称 - * @param {string} alertType 预警类型 - * @returns {string} 中文名称 - */ -export function getAlertTypeName(alertType) { - return alertTypeMap[alertType] || alertType || '--' -} - -/** - * 获取预警级别中文名称 - * @param {string} severity 预警级别 - * @returns {string} 中文名称 - */ -export function getAlertSeverityName(severity) { - return alertSeverityMap[severity] || severity || '--' -} - -/** - * 获取预警状态中文名称 - * @param {string} status 预警状态 - * @returns {string} 中文名称 - */ -export function getAlertStatusName(status) { - return alertStatusMap[status] || status || '--' -} - -/** - * 格式化日期 - * @param {number} timestamp 时间戳(秒) - * @returns {string} 格式化后的日期 - */ -export function formatDate(timestamp) { - if (!timestamp) return '--' - - // 如果是时间戳(秒),转换为毫秒 - const date = new Date(timestamp * 1000) - return date.toISOString().split('T')[0] -} - -/** - * 格式化日期为时间戳 - * @param {string} dateString 日期字符串 - * @returns {number} 时间戳(秒) - */ -export function formatDateToTimestamp(dateString) { - if (!dateString) return 0 - return Math.floor(new Date(dateString).getTime() / 1000) -} - -// 默认导出所有映射对象 -export default { - sexMap, - categoryMap, - breedMap, - strainMap, - physiologicalStageMap, - sourceMap, - eventMap, - wearMap, - deleteMap, - outMap, - eleAuthMap, - quaAuthMap, - vaccinMap, - inseminationMap, - insureMap, - mortgageMap, - sellStatusMap, - exitReasonMap, - disposalMethodMap, - exitStatusMap, - penTypeMap, - penStatusMap, - batchTypeMap, - batchStatusMap, - alertTypeMap, - alertSeverityMap, - alertStatusMap, - getSexName, - getCategoryName, - getBreedName, - getStrainName, - getPhysiologicalStage, - getSourceName, - getEventName, - getWearName, - getSellStatusName, - getExitReasonName, - getDisposalMethodName, - getExitStatusName, - getPenTypeName, - getPenStatusName, - getBatchTypeName, - getBatchStatusName, - getAlertTypeName, - getAlertSeverityName, - getAlertStatusName, - formatDate, - formatDateToTimestamp -} diff --git a/mini_program/farm-monitor-dashboard/src/views/ElectronicFencePage.vue b/mini_program/farm-monitor-dashboard/src/views/ElectronicFencePage.vue deleted file mode 100644 index 658be19..0000000 --- a/mini_program/farm-monitor-dashboard/src/views/ElectronicFencePage.vue +++ /dev/null @@ -1,23 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/src/views/SmartEartagAlertPage.vue b/mini_program/farm-monitor-dashboard/src/views/SmartEartagAlertPage.vue deleted file mode 100644 index 8212f91..0000000 --- a/mini_program/farm-monitor-dashboard/src/views/SmartEartagAlertPage.vue +++ /dev/null @@ -1,133 +0,0 @@ - - - - - diff --git a/mini_program/farm-monitor-dashboard/test-alert.html b/mini_program/farm-monitor-dashboard/test-alert.html deleted file mode 100644 index 3a0ab2f..0000000 --- a/mini_program/farm-monitor-dashboard/test-alert.html +++ /dev/null @@ -1,308 +0,0 @@ - - - - - - 预警API测试 - - - - -

预警API测试

- -
-

1. 登录测试

- -
-
- -
-

2. 项圈预警统计

- -
-
- -
-

3. 耳标预警统计

- -
-
- -
-

4. 预警卡片展示

- -
-
- -
-

5. 预警列表数据

- -
-
- -
-

6. 智能项圈预警测试

- -
-
- - - - diff --git a/mini_program/farm-monitor-dashboard/test-api.html b/mini_program/farm-monitor-dashboard/test-api.html deleted file mode 100644 index fdff15d..0000000 --- a/mini_program/farm-monitor-dashboard/test-api.html +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - API测试页面 - - - -

转栏记录API测试

- - -
- - - - \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/test-api.js b/mini_program/farm-monitor-dashboard/test-api.js deleted file mode 100644 index c9e3bda..0000000 --- a/mini_program/farm-monitor-dashboard/test-api.js +++ /dev/null @@ -1,159 +0,0 @@ -// API测试脚本 - 测试真实后端API -const axios = require('axios') - -// 获取认证token -async function getAuthToken() { - const baseURL = process.env.VUE_APP_API_BASE_URL || 'http://localhost:5350' - try { - const response = await axios.post(`${baseURL}/api/auth/login`, { - username: 'admin', - password: '123456' - }) - return response.data.success ? response.data.token : null - } catch (error) { - console.error('获取认证token失败:', error.message) - return null - } -} - -// 测试API连接 -async function testSmartHostAPI() { - const baseURL = process.env.VUE_APP_API_BASE_URL || 'http://localhost:5350' - - console.log('🔍 开始测试真实智能主机API接口...') - console.log('API地址:', baseURL) - console.log('⚠️ 注意: 此测试将调用真实后端API,不使用模拟数据') - - // 获取认证token - console.log('\n0. 获取认证token...') - const token = await getAuthToken() - if (!token) { - console.error('❌ 无法获取认证token,测试终止') - return - } - console.log('✅ 认证token获取成功') - - try { - // 测试基本连接 - console.log('\n1. 测试基本连接...') - const response = await axios.get(`${baseURL}/api/smart-devices/hosts`, { - params: { - page: 1, - pageSize: 10 - }, - timeout: 15000, - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${token}` - } - }) - - console.log('✅ API连接成功!') - console.log('响应状态:', response.status) - console.log('响应数据结构:', { - success: response.data.success, - total: response.data.total, - dataLength: response.data.data ? response.data.data.length : 0, - message: response.data.message - }) - - // 检查总数是否正确 - if (response.data.total) { - console.log(`📊 主机总数: ${response.data.total}`) - if (response.data.total === 371) { - console.log('✅ 主机总数正确 (371)') - } else { - console.log(`⚠️ 主机总数不匹配,期望: 371,实际: ${response.data.total}`) - } - } else { - console.log('❌ API响应中没有total字段') - } - - // 测试分页 - console.log('\n2. 测试分页功能...') - const page2Response = await axios.get(`${baseURL}/api/smart-devices/hosts`, { - params: { - page: 2, - pageSize: 5 - }, - timeout: 15000, - headers: { - 'Authorization': `Bearer ${token}` - } - }) - - console.log('✅ 分页测试成功!') - console.log('第2页数据长度:', page2Response.data.data ? page2Response.data.data.length : 0) - console.log('第2页总数:', page2Response.data.total) - - // 测试搜索 - console.log('\n3. 测试搜索功能...') - const searchResponse = await axios.get(`${baseURL}/api/smart-devices/hosts`, { - params: { - page: 1, - pageSize: 10, - search: '2490246' - }, - timeout: 15000, - headers: { - 'Authorization': `Bearer ${token}` - } - }) - - console.log('✅ 搜索测试成功!') - console.log('搜索结果长度:', searchResponse.data.data ? searchResponse.data.data.length : 0) - console.log('搜索结果总数:', searchResponse.data.total) - - // 测试完整数据获取 - console.log('\n4. 测试完整数据获取...') - const allDataResponse = await axios.get(`${baseURL}/api/smart-devices/hosts`, { - params: { - page: 1, - pageSize: 1000 // 获取更多数据 - }, - timeout: 30000, - headers: { - 'Authorization': `Bearer ${token}` - } - }) - - console.log('✅ 完整数据测试成功!') - console.log('实际获取数据长度:', allDataResponse.data.data ? allDataResponse.data.data.length : 0) - console.log('API返回总数:', allDataResponse.data.total) - - console.log('\n🎉 所有测试通过! 前端应该能正确显示371台主机') - - } catch (error) { - console.error('❌ API测试失败:') - if (error.response) { - console.error('状态码:', error.response.status) - console.error('错误信息:', error.response.data) - - if (error.response.status === 401) { - console.log('\n🔐 认证问题:') - console.log('1. 检查是否需要登录token') - console.log('2. 检查API是否需要认证头') - console.log('3. 联系后端开发者获取正确的认证方式') - } - } else if (error.request) { - console.error('网络错误:', error.message) - console.error('请检查API服务是否启动') - } else { - console.error('请求配置错误:', error.message) - } - - console.log('\n💡 解决方案:') - console.log('1. 确保后端服务已启动并运行在', baseURL) - console.log('2. 检查API地址是否正确') - console.log('3. 检查防火墙设置') - console.log('4. 查看后端日志获取详细错误信息') - console.log('5. 确认API接口路径: /api/smart-devices/hosts') - } -} - -// 运行测试 -if (require.main === module) { - testSmartHostAPI() -} - -module.exports = { testSmartHostAPI } diff --git a/mini_program/farm-monitor-dashboard/test-auth.html b/mini_program/farm-monitor-dashboard/test-auth.html deleted file mode 100644 index 1918f4e..0000000 --- a/mini_program/farm-monitor-dashboard/test-auth.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - 认证测试 - - -

认证测试页面

- -
- - - - diff --git a/mini_program/farm-monitor-dashboard/test-batch.html b/mini_program/farm-monitor-dashboard/test-batch.html deleted file mode 100644 index 0037c70..0000000 --- a/mini_program/farm-monitor-dashboard/test-batch.html +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - 批次设置API测试 - - - - -

批次设置API测试

- -
-

1. 登录测试

- -
-
- -
-

2. 批次列表测试

- -
-
- -
-

3. 精确搜索测试

- - -
-
- - - - diff --git a/mini_program/farm-monitor-dashboard/test-collar-api.js b/mini_program/farm-monitor-dashboard/test-collar-api.js deleted file mode 100644 index 54fba36..0000000 --- a/mini_program/farm-monitor-dashboard/test-collar-api.js +++ /dev/null @@ -1,150 +0,0 @@ -// 测试智能项圈API调用 -const axios = require('axios') - -// 创建axios实例 -const api = axios.create({ - baseURL: 'http://localhost:5350', - timeout: 10000, - headers: { - 'Content-Type': 'application/json' - } -}) - -// 测试获取智能项圈列表 -async function testGetCollarDevices() { - try { - console.log('测试获取智能项圈设备列表...') - - const response = await api.get('/api/smart-devices/collars', { - params: { - page: 1, - limit: 10 - } - }) - - console.log('API响应状态:', response.status) - console.log('API响应数据:', JSON.stringify(response.data, null, 2)) - - if (response.data && response.data.data) { - console.log(`成功获取 ${response.data.data.length} 个项圈设备`) - - // 检查数据字段映射 - const firstDevice = response.data.data[0] - if (firstDevice) { - console.log('第一个设备的数据字段:') - console.log('- sn:', firstDevice.sn) - console.log('- deviceId:', firstDevice.deviceId) - console.log('- voltage:', firstDevice.voltage) - console.log('- temperature:', firstDevice.temperature) - console.log('- state:', firstDevice.state) - console.log('- bandge_status:', firstDevice.bandge_status) - console.log('- walk:', firstDevice.walk) - console.log('- y_steps:', firstDevice.y_steps) - console.log('- time:', firstDevice.time) - console.log('- uptime:', firstDevice.uptime) - - // 测试绑定状态判断 - const isBound = firstDevice.bandge_status === 1 || firstDevice.bandge_status === '1' || - firstDevice.state === 1 || firstDevice.state === '1' - console.log('- 绑定状态判断 (bandge_status优先):', isBound) - console.log('- 绑定状态来源:', firstDevice.bandge_status !== undefined ? 'bandge_status' : 'state') - } - } - - } catch (error) { - console.error('API调用失败:', error.response?.status, error.response?.data || error.message) - } -} - -// 测试搜索功能 -async function testSearchCollarDevices() { - try { - console.log('\n测试搜索智能项圈设备...') - - const response = await api.get('/api/smart-devices/collars', { - params: { - page: 1, - limit: 10, - search: '2409' // 搜索包含2409的设备 - } - }) - - console.log('搜索API响应状态:', response.status) - console.log('搜索结果数量:', response.data?.data?.length || 0) - - } catch (error) { - console.error('搜索API调用失败:', error.response?.status, error.response?.data || error.message) - } -} - -// 测试绑定状态判断 -async function testBindingStatus() { - try { - console.log('\n测试绑定状态判断...') - - const response = await api.get('/api/smart-devices/collars', { - params: { - page: 1, - limit: 20 - } - }) - - if (response.data && response.data.data) { - const devices = response.data.data - console.log(`分析 ${devices.length} 个设备的绑定状态:`) - - let boundCount = 0 - let unboundCount = 0 - - devices.forEach((device, index) => { - const isBound = device.bandge_status === 1 || device.bandge_status === '1' || - device.state === 1 || device.state === '1' - - if (isBound) { - boundCount++ - } else { - unboundCount++ - } - - console.log(`设备 ${index + 1}: ${device.sn || device.deviceId}`) - console.log(` - bandge_status: ${device.bandge_status}`) - console.log(` - state: ${device.state}`) - console.log(` - 绑定状态: ${isBound ? '已绑定' : '未绑定'}`) - console.log(` - 状态来源: ${device.bandge_status !== undefined ? 'bandge_status' : 'state'}`) - console.log('') - }) - - console.log(`统计结果:`) - console.log(`- 已绑定设备: ${boundCount} 个`) - console.log(`- 未绑定设备: ${unboundCount} 个`) - console.log(`- 总设备数: ${devices.length} 个`) - } - - } catch (error) { - console.error('绑定状态测试失败:', error.response?.status, error.response?.data || error.message) - } -} - -// 运行测试 -async function runTests() { - console.log('开始测试智能项圈API...') - console.log('='.repeat(50)) - - await testGetCollarDevices() - await testSearchCollarDevices() - await testBindingStatus() - - console.log('\n测试完成!') -} - -// 如果直接运行此文件 -if (require.main === module) { - runTests().catch(console.error) -} - -module.exports = { - testGetCollarDevices, - testSearchCollarDevices, - testBindingStatus, - runTests -} diff --git a/mini_program/farm-monitor-dashboard/test-collar-pagination-search.js b/mini_program/farm-monitor-dashboard/test-collar-pagination-search.js deleted file mode 100644 index b28e467..0000000 --- a/mini_program/farm-monitor-dashboard/test-collar-pagination-search.js +++ /dev/null @@ -1,197 +0,0 @@ -// 测试智能项圈分页和搜索功能 -const axios = require('axios') - -// 创建axios实例 -const api = axios.create({ - baseURL: 'http://localhost:5350', - timeout: 10000, - headers: { - 'Content-Type': 'application/json' - } -}) - -// 测试分页功能 -async function testPagination() { - try { - console.log('测试分页功能...') - console.log('='.repeat(40)) - - // 测试第一页 - console.log('\n1. 测试第一页 (page=1, limit=5)') - let response = await api.get('/api/smart-devices/collars', { - params: { page: 1, limit: 5 } - }) - - console.log('响应状态:', response.status) - console.log('数据数量:', response.data?.data?.length || 0) - console.log('分页信息:', response.data?.pagination) - - if (response.data?.pagination) { - const { current, pageSize, total, totalPages } = response.data.pagination - console.log(`第 ${current} 页,每页 ${pageSize} 条,共 ${total} 条,${totalPages} 页`) - - // 测试第二页 - if (totalPages > 1) { - console.log('\n2. 测试第二页 (page=2, limit=5)') - response = await api.get('/api/smart-devices/collars', { - params: { page: 2, limit: 5 } - }) - - console.log('响应状态:', response.status) - console.log('数据数量:', response.data?.data?.length || 0) - console.log('分页信息:', response.data?.pagination) - } - - // 测试最后一页 - if (totalPages > 2) { - console.log('\n3. 测试最后一页 (page=' + totalPages + ', limit=5)') - response = await api.get('/api/smart-devices/collars', { - params: { page: totalPages, limit: 5 } - }) - - console.log('响应状态:', response.status) - console.log('数据数量:', response.data?.data?.length || 0) - console.log('分页信息:', response.data?.pagination) - } - } - - } catch (error) { - console.error('分页测试失败:', error.response?.status, error.response?.data || error.message) - } -} - -// 测试搜索功能 -async function testSearch() { - try { - console.log('\n\n测试搜索功能...') - console.log('='.repeat(40)) - - // 测试精确搜索 - console.log('\n1. 测试精确搜索项圈编号') - let response = await api.get('/api/smart-devices/collars', { - params: { - page: 1, - limit: 10, - search: '22012000108' // 使用图片中显示的项圈编号 - } - }) - - console.log('搜索响应状态:', response.status) - console.log('搜索结果数量:', response.data?.data?.length || 0) - console.log('搜索分页信息:', response.data?.pagination) - - if (response.data?.data?.length > 0) { - const device = response.data.data[0] - console.log('找到的设备信息:') - console.log('- 项圈编号:', device.sn || device.deviceId) - console.log('- 电量:', device.voltage) - console.log('- 温度:', device.temperature) - console.log('- 绑定状态:', device.bandge_status || device.state) - } - - // 测试模糊搜索 - console.log('\n2. 测试模糊搜索 (搜索包含"2201"的设备)') - response = await api.get('/api/smart-devices/collars', { - params: { - page: 1, - limit: 10, - search: '2201' - } - }) - - console.log('模糊搜索响应状态:', response.status) - console.log('模糊搜索结果数量:', response.data?.data?.length || 0) - console.log('模糊搜索分页信息:', response.data?.pagination) - - if (response.data?.data?.length > 0) { - console.log('匹配的设备编号:') - response.data.data.forEach((device, index) => { - console.log(` ${index + 1}. ${device.sn || device.deviceId}`) - }) - } - - // 测试无结果搜索 - console.log('\n3. 测试无结果搜索 (搜索不存在的编号)') - response = await api.get('/api/smart-devices/collars', { - params: { - page: 1, - limit: 10, - search: '99999999999' - } - }) - - console.log('无结果搜索响应状态:', response.status) - console.log('无结果搜索数量:', response.data?.data?.length || 0) - - } catch (error) { - console.error('搜索测试失败:', error.response?.status, error.response?.data || error.message) - } -} - -// 测试搜索分页 -async function testSearchPagination() { - try { - console.log('\n\n测试搜索分页功能...') - console.log('='.repeat(40)) - - // 先搜索获取结果 - console.log('\n1. 搜索获取结果') - let response = await api.get('/api/smart-devices/collars', { - params: { - page: 1, - limit: 3, // 使用较小的分页大小便于测试 - search: '2201' - } - }) - - console.log('搜索响应状态:', response.status) - console.log('搜索结果数量:', response.data?.data?.length || 0) - console.log('搜索分页信息:', response.data?.pagination) - - if (response.data?.pagination && response.data.pagination.totalPages > 1) { - const { totalPages } = response.data.pagination - - // 测试搜索结果的第二页 - console.log('\n2. 测试搜索结果第二页') - response = await api.get('/api/smart-devices/collars', { - params: { - page: 2, - limit: 3, - search: '2201' - } - }) - - console.log('第二页响应状态:', response.status) - console.log('第二页结果数量:', response.data?.data?.length || 0) - console.log('第二页分页信息:', response.data?.pagination) - } - - } catch (error) { - console.error('搜索分页测试失败:', error.response?.status, error.response?.data || error.message) - } -} - -// 运行所有测试 -async function runAllTests() { - console.log('开始测试智能项圈分页和搜索功能...') - console.log('='.repeat(60)) - - await testPagination() - await testSearch() - await testSearchPagination() - - console.log('\n\n所有测试完成!') - console.log('='.repeat(60)) -} - -// 如果直接运行此文件 -if (require.main === module) { - runAllTests().catch(console.error) -} - -module.exports = { - testPagination, - testSearch, - testSearchPagination, - runAllTests -} diff --git a/mini_program/farm-monitor-dashboard/test-exact-search.html b/mini_program/farm-monitor-dashboard/test-exact-search.html deleted file mode 100644 index ea1bbc1..0000000 --- a/mini_program/farm-monitor-dashboard/test-exact-search.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - 栏舍精确搜索测试 - - - - -

栏舍精确搜索功能测试

- -
-

1. 登录测试

- -
-
- -
-

2. 精确搜索测试

- - -
-
- -
-

3. 模糊搜索对比

- - -
-
- - - - diff --git a/mini_program/farm-monitor-dashboard/test-exit.html b/mini_program/farm-monitor-dashboard/test-exit.html deleted file mode 100644 index 87a27df..0000000 --- a/mini_program/farm-monitor-dashboard/test-exit.html +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - 离栏记录API测试 - - - -

离栏记录API测试

- - -
- - - - diff --git a/mini_program/farm-monitor-dashboard/test-host-number-fix.js b/mini_program/farm-monitor-dashboard/test-host-number-fix.js deleted file mode 100644 index 895d7e8..0000000 --- a/mini_program/farm-monitor-dashboard/test-host-number-fix.js +++ /dev/null @@ -1,86 +0,0 @@ -// 测试主机编号显示修复 -const axios = require('axios') - -async function testHostNumberFix() { - console.log('🔍 测试主机编号显示修复...') - - try { - // 1. 获取认证token - console.log('\n1. 获取认证token...') - const loginResponse = await axios.post('http://localhost:5350/api/auth/login', { - username: 'admin', - password: '123456' - }) - - if (!loginResponse.data.success) { - throw new Error('登录失败') - } - - const token = loginResponse.data.token - console.log('✅ 认证成功') - - // 2. 获取主机数据 - console.log('\n2. 获取主机数据...') - const hostResponse = await axios.get('http://localhost:5350/api/smart-devices/hosts', { - headers: { Authorization: `Bearer ${token}` }, - params: { page: 1, pageSize: 5 } - }) - - if (!hostResponse.data.success) { - throw new Error('获取主机数据失败') - } - - console.log('✅ 主机数据获取成功') - console.log('主机总数:', hostResponse.data.total) - - // 3. 检查主机编号字段 - console.log('\n3. 检查主机编号字段...') - const devices = hostResponse.data.data - - devices.forEach((device, index) => { - console.log(`\n设备 ${index + 1}:`) - console.log(' - deviceNumber:', device.deviceNumber || '未定义') - console.log(' - sid:', device.sid || '未定义') - console.log(' - hostId:', device.hostId || '未定义') - console.log(' - 显示的主机编号:', device.deviceNumber || device.sid || device.hostId || '无') - - // 检查其他字段 - console.log(' - 设备电量:', device.voltage || device.battery || '无') - console.log(' - 设备信号:', device.signa || device.signal || '无') - console.log(' - 设备温度:', device.temperature || '无') - console.log(' - 绑带状态:', device.bandge_status !== undefined ? device.bandge_status : (device.state !== undefined ? device.state : '无')) - console.log(' - 更新时间:', device.updateTime || device.lastUpdateTime || '无') - }) - - // 4. 测试搜索功能 - console.log('\n4. 测试搜索功能...') - const searchResponse = await axios.get('http://localhost:5350/api/smart-devices/hosts', { - headers: { Authorization: `Bearer ${token}` }, - params: { - page: 1, - pageSize: 10, - search: devices[0].deviceNumber || devices[0].sid || devices[0].hostId - } - }) - - console.log('✅ 搜索测试完成') - console.log('搜索结果数量:', searchResponse.data.data ? searchResponse.data.data.length : 0) - - console.log('\n🎉 主机编号显示修复测试完成!') - console.log('\n📋 修复内容:') - console.log('1. 显示字段: device.deviceNumber || device.sid || device.hostId') - console.log('2. 搜索字段: device.deviceNumber || device.sid || device.hostId') - console.log('3. 编辑字段: device.deviceNumber || device.sid || device.hostId') - - } catch (error) { - console.error('❌ 测试失败:', error.response?.data || error.message) - } -} - -// 运行测试 -if (require.main === module) { - testHostNumberFix() -} - -module.exports = { testHostNumberFix } - diff --git a/mini_program/farm-monitor-dashboard/test-navigation.html b/mini_program/farm-monitor-dashboard/test-navigation.html deleted file mode 100644 index 785a138..0000000 --- a/mini_program/farm-monitor-dashboard/test-navigation.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - 页面导航测试 - - - -

页面导航测试

- - - 转栏记录页面 -
查看和管理牛只转栏记录
-
- - - 离栏记录页面 -
查看和管理牛只离栏记录
-
- - - 牛只档案页面 -
查看牛只档案信息
-
- - - 离栏记录API测试 -
测试离栏记录API接口
-
- - - 转栏记录API测试 -
测试转栏记录API接口
-
- - diff --git a/mini_program/farm-monitor-dashboard/test-pagination-fix.js b/mini_program/farm-monitor-dashboard/test-pagination-fix.js deleted file mode 100644 index 69ce69c..0000000 --- a/mini_program/farm-monitor-dashboard/test-pagination-fix.js +++ /dev/null @@ -1,146 +0,0 @@ -// 测试分页修复 -const axios = require('axios') - -// 创建axios实例 -const api = axios.create({ - baseURL: 'http://localhost:5350', - timeout: 10000, - headers: { - 'Content-Type': 'application/json' - } -}) - -// 测试分页数据 -async function testPaginationData() { - try { - console.log('测试分页数据修复...') - console.log('='.repeat(50)) - - // 测试第一页 - console.log('\n1. 测试第一页数据') - let response = await api.get('/api/smart-devices/collars', { - params: { page: 1, limit: 5 } - }) - - console.log('API响应状态:', response.status) - console.log('原始API响应分页信息:', response.data?.pagination) - console.log('响应数据结构:', { - hasData: !!response.data?.data, - dataLength: response.data?.data?.length || 0, - hasPagination: !!response.data?.pagination, - pagination: response.data?.pagination - }) - - if (response.data?.pagination) { - const { current, pageSize, total, totalPages } = response.data.pagination - console.log('分页信息验证:') - console.log('- current:', current, typeof current) - console.log('- pageSize:', pageSize, typeof pageSize) - console.log('- total:', total, typeof total) - console.log('- totalPages:', totalPages, typeof totalPages) - - // 计算分页显示信息 - const start = (current - 1) * pageSize + 1 - const end = Math.min(current * pageSize, total) - console.log('分页显示信息:', `第 ${start}-${end} 条,共 ${total} 条`) - - // 检查是否有NaN - if (isNaN(start) || isNaN(end) || isNaN(total)) { - console.error('❌ 发现NaN值!') - console.error('- start:', start, 'isNaN:', isNaN(start)) - console.error('- end:', end, 'isNaN:', isNaN(end)) - console.error('- total:', total, 'isNaN:', isNaN(total)) - } else { - console.log('✅ 分页计算正常,无NaN值') - } - } else { - console.log('❌ 缺少分页信息') - } - - // 测试第三页(模拟API返回page: 3的情况) - console.log('\n2. 测试第三页数据(模拟API返回page: 3)') - response = await api.get('/api/smart-devices/collars', { - params: { page: 3, limit: 5 } - }) - - console.log('第三页响应状态:', response.status) - console.log('原始API响应分页信息:', response.data?.pagination) - console.log('第三页分页信息:', response.data?.pagination) - - if (response.data?.pagination) { - const { current, pageSize, total } = response.data.pagination - console.log('字段映射验证:') - console.log('- API返回的page字段:', response.data?.pagination?.page || 'undefined') - console.log('- 映射后的current字段:', current) - console.log('- 是否匹配:', (response.data?.pagination?.page || 3) === current) - - const start = (current - 1) * pageSize + 1 - const end = Math.min(current * pageSize, total) - console.log('第三页显示信息:', `第 ${start}-${end} 条,共 ${total} 条`) - - // 验证分页高亮是否正确 - if (current === 3) { - console.log('✅ 分页高亮应该显示第3页') - } else { - console.log('❌ 分页高亮显示错误,应该是第3页,实际是第' + current + '页') - } - } - - } catch (error) { - console.error('测试失败:', error.response?.status, error.response?.data || error.message) - } -} - -// 测试搜索分页 -async function testSearchPagination() { - try { - console.log('\n\n测试搜索分页...') - console.log('='.repeat(50)) - - // 测试搜索 - const response = await api.get('/api/smart-devices/collars', { - params: { - page: 1, - limit: 3, - search: '1501' - } - }) - - console.log('搜索响应状态:', response.status) - console.log('搜索结果数量:', response.data?.data?.length || 0) - console.log('搜索分页信息:', response.data?.pagination) - - if (response.data?.pagination) { - const { current, pageSize, total } = response.data.pagination - const start = (current - 1) * pageSize + 1 - const end = Math.min(current * pageSize, total) - console.log('搜索分页显示:', `搜索结果: 第 ${start}-${end} 条,共 ${total} 条`) - } - - } catch (error) { - console.error('搜索分页测试失败:', error.response?.status, error.response?.data || error.message) - } -} - -// 运行测试 -async function runTests() { - console.log('开始测试分页修复...') - console.log('='.repeat(60)) - - await testPaginationData() - await testSearchPagination() - - console.log('\n\n测试完成!') - console.log('='.repeat(60)) -} - -// 如果直接运行此文件 -if (require.main === module) { - runTests().catch(console.error) -} - -module.exports = { - testPaginationData, - testSearchPagination, - runTests -} diff --git a/mini_program/farm-monitor-dashboard/test-pen.html b/mini_program/farm-monitor-dashboard/test-pen.html deleted file mode 100644 index a63433e..0000000 --- a/mini_program/farm-monitor-dashboard/test-pen.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - 栏舍设置API测试 - - - -

栏舍设置API测试

- - - -
- - - - diff --git a/mini_program/farm-monitor-dashboard/uni.scss b/mini_program/farm-monitor-dashboard/uni.scss deleted file mode 100644 index b5dc20f..0000000 --- a/mini_program/farm-monitor-dashboard/uni.scss +++ /dev/null @@ -1,87 +0,0 @@ -// 全局样式变量定义 - -// 颜色系统 -$color-primary: #1890ff; // 主色 -$color-success: #52c41a; // 成功色 -$color-warning: #faad14; // 警告色 -$color-danger: #f5222d; // 危险色 -$color-info: #909399; // 信息色 - -// 文字颜色 -$color-text-primary: #303133; // 主要文字 -$color-text-regular: #606266; // 常规文字 -$color-text-secondary: #909399; // 次要文字 -$color-text-placeholder: #c0c4cc; // 占位文字 - -// 背景颜色 -$bg-color: #f6f6f6; // 背景色 -$bg-color-page: #ffffff; // 页面背景 -$bg-color-card: #ffffff; // 卡片背景 - -// 边框颜色 -$border-color-base: #dcdfe6; // 基础边框 -$border-color-light: #e4e7ed; // 浅色边框 -$border-color-lighter: #ebeef5; // 更浅边框 - -// 尺寸系统 -$font-size-xs: 12px; // 极小文字 -$font-size-sm: 14px; // 小文字 -$font-size-base: 16px; // 基础文字 -$font-size-lg: 18px; // 大文字 -$font-size-xl: 20px; // 超大文字 - -// 圆角 -$border-radius-sm: 4px; // 小圆角 -$border-radius-base: 6px; // 基础圆角 -$border-radius-lg: 8px; // 大圆角 -$border-radius-xl: 12px; // 超大圆角 - -// 间距 -$spacing-xs: 4px; // 极小间距 -$spacing-sm: 8px; // 小间距 -$spacing-base: 16px; // 基础间距 -$spacing-lg: 24px; // 大间距 -$spacing-xl: 32px; // 超大间距 - -// 透明度 -$opacity-disabled: 0.6; // 禁用状态透明度 - -// 投影 -$box-shadow-base: 0 2px 8px rgba(0, 0, 0, 0.15); // 基础投影 -$box-shadow-light: 0 2px 12px rgba(0, 0, 0, 0.1); // 轻量投影 - -// 动画 -$transition-duration: 0.3s; // 动画时长 -$transition-function: ease-in-out; // 动画函数 - -// 组件变量 -$component-padding: $spacing-base; // 组件内边距 -$component-margin: $spacing-base; // 组件外边距 - -// 响应式断点 -$breakpoint-xs: 480px; // 超小屏幕 -$breakpoint-sm: 576px; // 小屏幕 -$breakpoint-md: 768px; // 中等屏幕 -$breakpoint-lg: 992px; // 大屏幕 -$breakpoint-xl: 1200px; // 超大屏幕 - -// 导出变量供JavaScript使用 -:export { - colorPrimary: $color-primary; - colorSuccess: $color-success; - colorWarning: $color-warning; - colorDanger: $color-danger; - colorInfo: $color-info; - - fontSizeXs: $font-size-xs; - fontSizeSm: $font-size-sm; - fontSizeBase: $font-size-base; - fontSizeLg: $font-size-lg; - fontSizeXl: $font-size-xl; - - spacingXs: $spacing-xs; - spacingSm: $spacing-sm; - spacingBase: $spacing-base; - spacingLg: $spacing-lg; - spacingXl: $spacing-xl; -} \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/utils/api.js b/mini_program/farm-monitor-dashboard/utils/api.js index 6816904..7d3f3bd 100644 --- a/mini_program/farm-monitor-dashboard/utils/api.js +++ b/mini_program/farm-monitor-dashboard/utils/api.js @@ -5,7 +5,7 @@ const app = getApp() // 基础配置 const config = { // 使用真实的智能耳标API接口(直接连接后端) - baseUrl: 'http://localhost:5350/api', // 智能耳标API地址 + baseUrl: 'https://ad.ningmuyun.com/api', // 智能耳标API地址 timeout: 10000, header: { 'Content-Type': 'application/json' @@ -38,31 +38,24 @@ const requestInterceptor = (options) => { const responseInterceptor = (response) => { const { statusCode, data } = response - console.log('API响应:', data) - console.log('状态码:', statusCode) + // API响应处理 // 处理HTTP状态码 if (statusCode >= 200 && statusCode < 300) { // 统一处理响应格式 if (data.code === 200) { - console.log('处理code=200格式') return data.data } else if (data.success === true) { // 处理 {success: true, data: ...} 格式 - console.log('处理success=true格式') return data } else if (data.success === false) { // 处理 {success: false, message: ...} 格式 - console.log('处理success=false格式') return data } else if (data.code === undefined && data.success === undefined) { // 直接返回数据的情况 - console.log('处理直接数据格式') return data } else { // 业务错误 - console.error('请求失败:', data.message || '请求失败') - console.error('完整响应:', data) return Promise.reject(new Error(data.message || '请求失败')) } } else { @@ -92,7 +85,6 @@ const responseInterceptor = (response) => { message = `连接错误${statusCode}` } - console.error('网络错误:', message) return Promise.reject(new Error(message)) } } @@ -115,15 +107,18 @@ const request = (options) => { wx.request({ ...processedOptions, success: (response) => { + console.log('wx.request成功:', response) try { const result = responseInterceptor(response) + console.log('响应拦截器处理结果:', result) resolve(result) } catch (error) { + console.log('响应拦截器错误:', error) reject(error) } }, fail: (error) => { - console.error('请求失败:', error) + console.log('wx.request失败:', error) let message = '网络连接异常' if (error.errMsg) { diff --git a/mini_program/farm-monitor-dashboard/utils/auth.js b/mini_program/farm-monitor-dashboard/utils/auth.js index 0b6e914..02b9916 100644 --- a/mini_program/farm-monitor-dashboard/utils/auth.js +++ b/mini_program/farm-monitor-dashboard/utils/auth.js @@ -157,8 +157,11 @@ export const updateUserInfo = (updates) => { // 登录 export const login = (token, userInfo) => { + console.log('auth.login 被调用,token:', token) + console.log('auth.login 被调用,userInfo:', userInfo) setToken(token) setUserInfo(userInfo) + console.log('token已保存,当前token:', getToken()) } // 登出 diff --git a/mini_program/farm-monitor-dashboard/vite.config.js b/mini_program/farm-monitor-dashboard/vite.config.js deleted file mode 100644 index 79ecb82..0000000 --- a/mini_program/farm-monitor-dashboard/vite.config.js +++ /dev/null @@ -1,26 +0,0 @@ -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' -import path from 'path' - -export default defineConfig({ - plugins: [vue()], - resolve: { - alias: { - '@': path.resolve(__dirname, 'src') - } - }, - server: { - port: 8080, - proxy: { - '/api': { - target: 'http://localhost:5350', - changeOrigin: true, - rewrite: (path) => path.replace(/^\/api/, '/api') - } - } - }, - build: { - outDir: 'dist', - assetsDir: 'static' - } -}) \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/vue.config.js b/mini_program/farm-monitor-dashboard/vue.config.js deleted file mode 100644 index 9b2e8f3..0000000 --- a/mini_program/farm-monitor-dashboard/vue.config.js +++ /dev/null @@ -1,81 +0,0 @@ -const { defineConfig } = require('@vue/cli-service') - -module.exports = defineConfig({ - transpileDependencies: true, - - // 配置webpack - configureWebpack: { - resolve: { - alias: { - '@': require('path').resolve(__dirname, 'src'), - // 强制uni-app使用CommonJS版本 - '@dcloudio/uni-app/dist/uni-app.es.js': require.resolve('@dcloudio/uni-app/dist/index.js') - } - } - }, - - // 配置public目录 - publicPath: '/', - assetsDir: 'static', - - // 开发服务器配置 - devServer: { - port: 8080, - proxy: { - '/api': { - target: 'http://localhost:5350', - changeOrigin: true, - pathRewrite: { - '^/api': '/api' - } - } - } - }, - - // CSS配置 - css: { - loaderOptions: { - scss: { - // 样式变量已在app.scss中导入 - } - } - }, - - // 生产环境配置 - productionSourceMap: false, - - // 插件配置 - pluginOptions: { - // uni-app配置 - 'uni-app': { - // 微信小程序配置 - 'mp-weixin': { - appid: process.env.VUE_APP_WEIXIN_APPID, - setting: { - urlCheck: false, - es6: true, - postcss: true, - minified: true - }, - // 插件配置 - plugins: {}, - // 分包配置 - subPackages: [ - { - root: 'pages/sub', - pages: [ - 'example/example' - ] - } - ], - // 预加载规则 - preloadRule: { - 'pages/index/index': { - network: 'all', - packages: ['pages/sub'] - } - } - } - } - } -}) \ No newline at end of file diff --git a/mini_program/farm-monitor-dashboard/严格按照图片设计的我的页面说明.md b/mini_program/farm-monitor-dashboard/严格按照图片设计的我的页面说明.md deleted file mode 100644 index aeb87dc..0000000 --- a/mini_program/farm-monitor-dashboard/严格按照图片设计的我的页面说明.md +++ /dev/null @@ -1,130 +0,0 @@ -# 严格按照图片设计的我的页面说明 - -## 设计概述 -完全按照提供的UI设计图片重新实现了微信小程序的"我的"页面,采用简洁的白色背景设计,突出功能性和易用性。 - -## 页面结构 - -### 1. 页面标题区域 -- **标题**:居中显示"我的" -- **控制按钮**:右上角三个圆形按钮 - - 省略号按钮(⋯) - - 减号按钮(−) - - 目标按钮(◎) - -### 2. 用户信息区域 -- **绿色圆形Logo**: - - 背景色:#3cc51f(绿色) - - 白色字母"A" - - 直径:80rpx -- **公司名称**:AIOTAGRO(粗体,32rpx) -- **用户ID**:15586823774(灰色,24rpx) - -### 3. 功能菜单区域 -包含6个功能模块,每个模块包含: -- **左侧图标**:32rpx emoji图标 -- **中间文字**:功能名称(28rpx) -- **右侧箭头**:">"符号(24rpx) - -**功能列表:** -1. **养殖系统设置**(⚙️)- 系统配置管理 -2. **切换养殖场**(🔄)- 养殖场切换功能 -3. **养殖场识别码**(🏷️)- 识别码管理 -4. **关联机构**(📄)- 机构关联管理 -5. **首页自定义**(⭐)- 首页个性化设置 -6. **养殖场设置**(🏠)- 养殖场配置 - -### 4. 退出登录区域 -- **按钮样式**:灰色背景(#f5f5f5) -- **按钮文字**:退出登录(黑色,28rpx) -- **按钮高度**:80rpx -- **圆角**:8rpx - -## 技术实现 - -### 文件结构 -``` -pages/profile/ -├── profile.js # 页面逻辑 -├── profile.wxml # 页面结构 -└── profile.wxss # 页面样式 -``` - -### 样式特点 -- **背景色**:纯白色(#ffffff) -- **主题色**:绿色(#3cc51f) -- **文字色**:黑色(#333333) -- **分割线**:浅灰色(#f0f0f0) -- **简洁设计**:无阴影,无渐变 - -### 布局特点 -- **垂直布局**:所有元素垂直排列 -- **全宽设计**:菜单项占满屏幕宽度 -- **统一间距**:32rpx的内边距 -- **清晰层次**:通过间距和分割线区分不同区域 - -### 交互设计 -- **点击反馈**:菜单项点击时背景变为浅灰色 -- **功能提示**:点击功能模块显示"功能开发中" -- **退出确认**:退出登录有确认对话框 - -## 数据管理 - -### 用户信息 -```javascript -userInfo: { - id: 1, - username: 'admin', - nickname: '管理员', - realName: '张三', - userId: '15586823774', // 新增字段 - avatar: '', - role: 'admin', - department: '技术部' -} -``` - -### 功能菜单 -```javascript -menuItems: [ - { icon: '⚙️', title: '养殖系统设置', url: '/pages/profile/system-settings/system-settings' }, - { icon: '🔄', title: '切换养殖场', url: '/pages/profile/switch-farm/switch-farm' }, - { icon: '🏷️', title: '养殖场识别码', url: '/pages/profile/farm-code/farm-code' }, - { icon: '📄', title: '关联机构', url: '/pages/profile/associated-institutions/associated-institutions' }, - { icon: '⭐', title: '首页自定义', url: '/pages/profile/homepage-customization/homepage-customization' }, - { icon: '🏠', title: '养殖场设置', url: '/pages/profile/farm-settings/farm-settings' } -] -``` - -## 响应式设计 -- **小屏幕适配**:针对375px以下屏幕优化 -- **字体缩放**:小屏幕下字体适当缩小 -- **间距调整**:小屏幕下减少内边距 -- **按钮高度**:小屏幕下按钮高度适当减小 - -## 使用方法 -1. 在微信开发者工具中打开项目 -2. 编译并预览小程序 -3. 确保已登录(使用admin/123456) -4. 点击底部导航栏的"我的"进入页面 -5. 验证页面布局与图片设计的一致性 - -## 设计优势 -- **简洁明了**:去除冗余元素,突出核心功能 -- **易于使用**:清晰的视觉层次和操作流程 -- **专业外观**:符合企业级应用的设计标准 -- **功能聚焦**:专注于养殖管理相关功能 - -## 后续开发 -当前页面为UI展示版本,各功能模块的具体实现需要: -1. 创建对应的子页面 -2. 实现具体的数据管理逻辑 -3. 集成后端API接口 -4. 添加数据验证和错误处理 - -## 注意事项 -- 页面严格按照设计图片实现 -- 所有功能模块都已预留接口 -- 样式完全响应式,适配各种设备 -- 代码结构清晰,便于后续扩展 -- 与底部导航栏的"我的"标签保持一致的绿色主题 diff --git a/mini_program/farm-monitor-dashboard/启动生产管理页面测试.bat b/mini_program/farm-monitor-dashboard/启动生产管理页面测试.bat deleted file mode 100644 index 369c428..0000000 --- a/mini_program/farm-monitor-dashboard/启动生产管理页面测试.bat +++ /dev/null @@ -1,17 +0,0 @@ -@echo off -echo 启动微信小程序开发工具... -echo 项目路径: %cd% -echo. -echo 请确保: -echo 1. 已安装微信开发者工具 -echo 2. 已登录微信开发者账号 -echo 3. 项目已导入到微信开发者工具中 -echo. -echo 生产管理页面功能: -echo - 猪档案管理(11个功能模块) -echo - 羊只管理(11个功能模块) -echo - 家禽管理(6个功能模块) -echo. -echo 点击任意功能模块会显示"功能开发中"提示 -echo. -pause diff --git a/mini_program/farm-monitor-dashboard/我的页面设计说明.md b/mini_program/farm-monitor-dashboard/我的页面设计说明.md deleted file mode 100644 index f0bcf38..0000000 --- a/mini_program/farm-monitor-dashboard/我的页面设计说明.md +++ /dev/null @@ -1,123 +0,0 @@ -# 我的页面设计说明 - -## 页面概述 -严格按照提供的UI设计图片重新实现了微信小程序的"我的"页面,包含用户信息展示、统计数据显示、功能菜单导航和系统操作等功能模块。 - -## 页面结构 - -### 1. 用户信息卡片 -- **渐变背景**:使用紫色渐变背景 (#667eea 到 #764ba2) -- **用户头像**:圆形头像,带白色边框 -- **用户信息**:姓名、角色、部门信息 -- **编辑按钮**:右上角编辑图标,可点击编辑个人信息 - -### 2. 统计信息区域 -显示4个关键数据指标: -- **管理牛只**:当前管理的牛只数量 -- **设备数量**:已连接的设备总数 -- **预警数量**:当前预警信息数量 -- **养殖场数**:管理的养殖场数量 - -### 3. 功能菜单区域 -包含7个主要功能模块: -- **个人信息** - 查看和编辑个人资料 -- **账户设置** - 账户相关设置 -- **消息通知** - 通知消息管理 -- **隐私安全** - 隐私和安全设置 -- **帮助中心** - 使用帮助和FAQ -- **联系我们** - 客服联系方式 -- **关于我们** - 应用信息和团队介绍 - -### 4. 操作按钮区域 -- **清除缓存**:清理应用缓存数据 -- **检查更新**:检查应用版本更新 - -### 5. 退出登录 -- **退出按钮**:红色边框按钮,确认后退出登录 - -### 6. 版本信息 -- **版本号**:显示当前应用版本 - -## 技术实现 - -### 文件结构 -``` -pages/profile/ -├── profile.js # 页面逻辑 -├── profile.wxml # 页面结构 -└── profile.wxss # 页面样式 -``` - -### 主要特性 -1. **响应式设计** - 适配不同屏幕尺寸 -2. **模块化布局** - 每个功能模块独立设计 -3. **交互反馈** - 点击时有视觉反馈 -4. **功能提示** - 点击功能模块显示开发状态提示 - -### 样式特点 -- 使用卡片式设计,白色背景 -- 紫色渐变用户信息卡片 -- 绿色主题色 (#3cc51f) 用于统计数据 -- 圆角设计和阴影效果 -- 清晰的层次结构 - -### 交互逻辑 -- 点击任意功能模块会显示"功能开发中"提示 -- 支持退出登录功能 -- 支持清除缓存功能 -- 支持检查更新功能 -- 控制台输出操作日志 - -## 数据管理 - -### 用户信息 -```javascript -userInfo: { - id: 1, - username: 'admin', - nickname: '管理员', - realName: '张三', - avatar: '', - role: 'admin', - department: '技术部', - cattleCount: 156, - deviceCount: 89, - alertCount: 12, - farmCount: 3, - appVersion: '1.0.0' -} -``` - -### 功能菜单 -```javascript -menuItems: [ - { icon: '👤', title: '个人信息', url: '/pages/profile/info/info' }, - { icon: '🔧', title: '账户设置', url: '/pages/profile/settings/settings' }, - { icon: '🔔', title: '消息通知', url: '/pages/profile/notifications/notifications' }, - { icon: '🛡️', title: '隐私安全', url: '/pages/profile/privacy/privacy' }, - { icon: '❓', title: '帮助中心', url: '/pages/profile/help/help' }, - { icon: '📞', title: '联系我们', url: '/pages/profile/contact/contact' }, - { icon: 'ℹ️', title: '关于我们', url: '/pages/profile/about/about' } -] -``` - -## 使用方法 -1. 在微信开发者工具中打开项目 -2. 编译并预览小程序 -3. 确保已登录(使用admin/123456) -4. 点击底部导航栏的"我的"进入页面 -5. 测试各项功能 - -## 后续开发 -当前页面为UI展示版本,各功能模块的具体实现需要: -1. 创建对应的子页面 -2. 实现具体的数据管理逻辑 -3. 集成后端API接口 -4. 添加数据验证和错误处理 - -## 注意事项 -- 页面严格按照设计图片实现 -- 所有功能模块都已预留接口 -- 样式完全响应式,适配各种设备 -- 代码结构清晰,便于后续扩展 -- 支持登录状态检查和自动跳转 diff --git a/mini_program/farm-monitor-dashboard/智能耳标预警功能完善说明.md b/mini_program/farm-monitor-dashboard/智能耳标预警功能完善说明.md deleted file mode 100644 index f7df47b..0000000 --- a/mini_program/farm-monitor-dashboard/智能耳标预警功能完善说明.md +++ /dev/null @@ -1,110 +0,0 @@ -# 智能耳标预警功能完善说明 - -## 概述 -基于PC养殖端智能耳标预警的数据结构,完善了小程序端的智能耳标预警功能,确保数据格式和字段映射与PC端保持一致。 - -## 主要改进 - -### 1. 数据字段映射统一 -- **预警类型映射**:与PC端保持一致 - - `battery` → '低电量预警' - - `offline` → '离线预警' - - `temperature` → '温度预警' - - `movement` → '异常运动预警' - - `wear` → '佩戴异常预警' - - `location` → '位置异常预警' - -- **预警级别映射**:与PC端保持一致 - - `high` → '高级' - - `medium` → '中级' - - `low` → '低级' - - `critical` → '紧急' - -### 2. 数据结构完善 -小程序端现在支持以下字段,与PC端完全一致: - -#### 基本信息 -- `id` - 预警ID -- `eartagNumber` - 耳标编号 -- `deviceId` - 设备ID -- `alertType` - 预警类型 -- `alertLevel` - 预警级别 -- `alertTime` - 预警时间 -- `title` - 预警标题 -- `description` - 预警描述 -- `status` - 处理状态 - -#### 设备信息 -- `battery` - 设备电量 -- `temperature` - 设备温度 -- `dailySteps` - 当日步数 -- `longitude` - 经度 -- `latitude` - 纬度 -- `handler` - 处理人 - -### 3. 时间格式化 -- 支持Unix时间戳转换 -- 支持字符串时间转换 -- 统一使用中文本地化格式 - -### 4. 预警卡片展示 -首页预警卡片现在显示: -- 今日未被采集 -- 低电量预警 -- 离线预警 -- 温度预警(合并高温和低温) -- 异常运动预警 -- 佩戴异常预警(仅项圈) - -### 5. 预警列表增强 -- 显示耳标编号而非设备ID -- 显示预警类型和级别 -- 显示设备电量、温度、步数等指标 -- 支持预警详情查看 - -### 6. 预警详情模态框 -- 基本信息:耳标编号、预警类型、预警级别、预警时间、处理状态、处理人 -- 设备信息:设备电量、设备温度、当日步数、位置坐标 -- 预警内容:标题和描述 - -## API接口 -- 获取耳标预警统计:`/api/smart-alerts/public/eartag/stats` -- 获取项圈预警统计:`/api/smart-alerts/public/collar/stats` -- 获取耳标预警列表:`/api/smart-alerts/public/eartag` -- 获取项圈预警列表:`/api/smart-alerts/public/collar` -- 处理耳标预警:`/api/smart-alerts/public/eartag/{id}/handle` -- 处理项圈预警:`/api/smart-alerts/public/collar/{id}/handle` - -## 测试验证 -创建了 `test-alert.html` 测试页面,包含: -1. 登录测试 -2. 项圈预警统计测试 -3. 耳标预警统计测试 -4. 预警卡片展示测试 -5. 预警列表数据测试 - -## 文件修改清单 -1. `src/services/api.js` - 添加预警API服务 -2. `src/utils/mapping.js` - 添加预警字段映射 -3. `src/components/Home.vue` - 更新首页预警数据 -4. `src/components/SmartEartagAlert.vue` - 完善耳标预警组件 -5. `test-alert.html` - 创建测试页面 - -## 数据同步保证 -- 字段名称与PC端完全一致 -- 数据转换逻辑与PC端保持一致 -- 中文映射与PC端完全统一 -- API调用方式与PC端保持一致 - -## 使用说明 -1. 确保后端服务运行在 `http://localhost:5350` -2. 前端服务运行在 `http://localhost:8080` -3. 访问 `test-alert.html` 进行功能测试 -4. 在小程序中访问智能耳标预警页面查看实时数据 - -## 注意事项 -- 脚环预警暂时使用耳标数据(API中无独立脚环统计) -- 主机预警使用固定数据(API中无主机统计) -- 所有预警数据均为动态获取,无硬编码数据 -- 支持实时刷新和自动更新 - diff --git a/mini_program/farm-monitor-dashboard/测试严格按照图片设计的我的页面.bat b/mini_program/farm-monitor-dashboard/测试严格按照图片设计的我的页面.bat deleted file mode 100644 index 0dc426e..0000000 --- a/mini_program/farm-monitor-dashboard/测试严格按照图片设计的我的页面.bat +++ /dev/null @@ -1,38 +0,0 @@ -@echo off -echo 测试严格按照图片设计的我的页面 -echo. -echo 新设计特点: -echo 1. 页面标题"我的" + 右上角控制按钮 -echo 2. 用户信息区域: -echo - 绿色圆形logo(白色A字母) -echo - AIOTAGRO公司名称 -echo - 用户ID:15586823774 -echo 3. 功能菜单(6个): -echo - 养殖系统设置(齿轮图标) -echo - 切换养殖场(循环箭头图标) -echo - 养殖场识别码(标签图标) -echo - 关联机构(文档图标) -echo - 首页自定义(星星图标) -echo - 养殖场设置(房子图标) -echo 4. 退出登录按钮(灰色背景) -echo. -echo 测试步骤: -echo 1. 在微信开发者工具中打开项目 -echo 2. 确保已登录(使用admin/123456登录) -echo 3. 点击底部导航栏的"我的"进入页面 -echo 4. 验证页面布局是否与图片完全一致: -echo - 检查页面标题和控制按钮 -echo - 检查绿色logo和AIOTAGRO文字 -echo - 检查用户ID显示 -echo - 检查6个功能菜单项 -echo - 检查退出登录按钮样式 -echo 5. 测试功能交互: -echo - 点击各个菜单项 -echo - 点击退出登录按钮 -echo. -echo 预期效果: -echo - 页面布局与图片设计完全一致 -echo - 所有功能都有相应的提示信息 -echo - 退出登录会跳转到登录页面 -echo. -pause diff --git a/mini_program/farm-monitor-dashboard/测试我的页面功能.bat b/mini_program/farm-monitor-dashboard/测试我的页面功能.bat deleted file mode 100644 index e263c95..0000000 --- a/mini_program/farm-monitor-dashboard/测试我的页面功能.bat +++ /dev/null @@ -1,29 +0,0 @@ -@echo off -echo 测试我的页面功能 -echo. -echo 页面功能: -echo 1. 用户信息卡片 - 显示头像、姓名、角色、部门 -echo 2. 统计信息 - 管理牛只、设备数量、预警数量、养殖场数 -echo 3. 功能菜单 - 个人信息、账户设置、消息通知、隐私安全、帮助中心、联系我们、关于我们 -echo 4. 操作按钮 - 清除缓存、检查更新 -echo 5. 退出登录 - 退出当前账号 -echo 6. 版本信息 - 显示应用版本 -echo. -echo 测试步骤: -echo 1. 在微信开发者工具中打开项目 -echo 2. 确保已登录(使用admin/123456登录) -echo 3. 点击底部导航栏的"我的"进入页面 -echo 4. 测试各项功能: -echo - 点击编辑按钮 -echo - 点击各个菜单项 -echo - 点击清除缓存按钮 -echo - 点击检查更新按钮 -echo - 点击退出登录按钮 -echo. -echo 预期效果: -echo - 所有功能都有相应的提示信息 -echo - 退出登录会跳转到登录页面 -echo - 清除缓存会清除本地存储 -echo - 检查更新会显示版本信息 -echo. -pause diff --git a/mini_program/farm-monitor-dashboard/测试登录页面用户协议.bat b/mini_program/farm-monitor-dashboard/测试登录页面用户协议.bat deleted file mode 100644 index cbe56b6..0000000 --- a/mini_program/farm-monitor-dashboard/测试登录页面用户协议.bat +++ /dev/null @@ -1,21 +0,0 @@ -@echo off -echo 测试登录页面用户协议勾选功能 -echo. -echo 修复内容: -echo 1. 为checkbox添加了value="agreement"属性 -echo 2. 修复了onAgreementChange方法,正确处理checkbox的数组返回值 -echo 3. 添加了控制台日志输出,便于调试 -echo. -echo 测试步骤: -echo 1. 在微信开发者工具中打开项目 -echo 2. 进入登录页面 -echo 3. 点击用户协议复选框 -echo 4. 查看控制台输出,应该显示: -echo - "用户协议变化: ['agreement']" 或 "用户协议变化: []" -echo - "协议勾选状态: true" 或 "协议勾选状态: false" -echo 5. 尝试登录,应该能正确验证协议勾选状态 -echo. -echo 测试账号:admin -echo 测试密码:123456 -echo. -pause diff --git a/mini_program/farm-monitor-dashboard/测试自定义checkbox.bat b/mini_program/farm-monitor-dashboard/测试自定义checkbox.bat deleted file mode 100644 index 317c6bf..0000000 --- a/mini_program/farm-monitor-dashboard/测试自定义checkbox.bat +++ /dev/null @@ -1,31 +0,0 @@ -@echo off -echo 测试自定义checkbox用户协议功能 -echo. -echo 新的实现方案: -echo 1. 使用自定义checkbox替代原生checkbox组件 -echo 2. 通过bindtap事件直接切换状态 -echo 3. 添加了详细的控制台日志输出 -echo 4. 自定义样式,更符合设计需求 -echo. -echo 测试步骤: -echo 1. 在微信开发者工具中打开项目 -echo 2. 进入登录页面 -echo 3. 点击用户协议复选框(包括文字部分) -echo 4. 查看控制台输出,应该显示: -echo - "点击用户协议,当前状态: false" -echo - "切换后状态: true" -echo 5. 再次点击,应该显示: -echo - "点击用户协议,当前状态: true" -echo - "切换后状态: false" -echo 6. 尝试登录,验证协议勾选状态是否正确 -echo. -echo 测试账号:admin -echo 测试密码:123456 -echo. -echo 优势: -echo - 不依赖原生checkbox的复杂事件处理 -echo - 点击区域更大(整个容器都可点击) -echo - 样式完全可控 -echo - 调试信息更清晰 -echo. -pause diff --git a/mini_program/farm-monitor-dashboard/生产管理页面说明.md b/mini_program/farm-monitor-dashboard/生产管理页面说明.md deleted file mode 100644 index 3b50e4a..0000000 --- a/mini_program/farm-monitor-dashboard/生产管理页面说明.md +++ /dev/null @@ -1,94 +0,0 @@ -# 生产管理页面实现说明 - -## 页面概述 -严格按照提供的UI设计图片实现了微信小程序的生产管理页面,包含三个主要管理模块。 - -## 页面结构 - -### 1. 页面标题 -- 居中显示"生产管理"标题 -- 白色背景,简洁设计 - -### 2. 猪档案管理模块 -包含11个功能模块: -- **猪档案** - 猪只基本信息管理 -- **发情记录** - 记录猪只发情情况 -- **配种记录** - 记录配种信息 -- **妊检记录** - 记录妊娠检查情况 -- **分娩记录** - 记录分娩信息 -- **断奶记录** - 记录断奶情况 -- **转栏记录** - 记录转栏操作 -- **离栏记录** - 记录离栏操作 -- **栏舍设置** - 栏舍配置管理 -- **批次设置** - 批次管理设置 -- **防疫预警** - 防疫预警功能 - -### 3. 羊只管理模块 -包含11个功能模块(与猪档案管理相同): -- **羊档案** - 羊只基本信息管理 -- **发情记录** - 记录羊只发情情况 -- **配种记录** - 记录配种信息 -- **妊检记录** - 记录妊娠检查情况 -- **分娩记录** - 记录分娩信息 -- **断奶记录** - 记录断奶情况 -- **转栏记录** - 记录转栏操作 -- **离栏记录** - 记录离栏操作 -- **栏舍设置** - 栏舍配置管理 -- **批次设置** - 批次管理设置 -- **防疫预警** - 防疫预警功能 - -### 4. 家禽管理模块 -包含6个功能模块: -- **家禽档案** - 家禽基本信息管理 -- **离栏记录** - 记录离栏操作 -- **栏舍设置** - 栏舍配置管理 -- **批次设置** - 批次管理设置 -- **扫码录入** - 扫码录入功能 -- **扫码打印** - 扫码打印功能 - -## 技术实现 - -### 文件结构 -``` -pages/production/ -├── production.js # 页面逻辑 -├── production.wxml # 页面结构 -└── production.wxss # 页面样式 -``` - -### 主要特性 -1. **响应式设计** - 适配不同屏幕尺寸 -2. **模块化布局** - 每个管理模块独立设计 -3. **交互反馈** - 点击时有视觉反馈 -4. **功能提示** - 点击功能模块显示开发状态提示 - -### 样式特点 -- 使用Grid布局实现5列网格 -- 圆形图标设计,不同功能使用不同颜色 -- 绿色主题色(#3cc51f) -- 简洁的白色背景设计 -- 模块标题带有绿色竖条装饰 - -### 交互逻辑 -- 点击任意功能模块会显示"功能开发中"提示 -- 支持下拉刷新 -- 控制台输出点击事件日志 - -## 使用方法 -1. 在微信开发者工具中打开项目 -2. 编译并预览小程序 -3. 点击底部导航栏的"生产管理"进入页面 -4. 点击任意功能模块查看交互效果 - -## 后续开发 -当前页面为UI展示版本,各功能模块的具体实现需要: -1. 创建对应的子页面 -2. 实现具体的数据管理逻辑 -3. 集成后端API接口 -4. 添加数据验证和错误处理 - -## 注意事项 -- 页面严格按照设计图片实现 -- 所有功能模块都已预留接口 -- 样式完全响应式,适配各种设备 -- 代码结构清晰,便于后续扩展 diff --git a/mini_program/farm-monitor-dashboard/用户协议checkbox最终修复方案.md b/mini_program/farm-monitor-dashboard/用户协议checkbox最终修复方案.md deleted file mode 100644 index dbede3b..0000000 --- a/mini_program/farm-monitor-dashboard/用户协议checkbox最终修复方案.md +++ /dev/null @@ -1,139 +0,0 @@ -# 用户协议Checkbox最终修复方案 - -## 问题分析 -之前的修复方案仍然无法正确识别用户协议勾选,主要原因: -1. 原生 `checkbox` 组件在某些情况下事件处理不够稳定 -2. CSS `transform: scale(0.8)` 可能影响点击区域 -3. 微信小程序的 `checkbox` 组件在不同版本中行为可能不一致 - -## 最终解决方案:自定义Checkbox - -### 1. WXML 结构重构 -**文件:** `pages/login/login.wxml` - -**新的实现:** -```xml - - - - - - - 《用户服务协议》及《隐私政策》 - - - -``` - -**优势:** -- 整个容器都可以点击,用户体验更好 -- 不依赖原生组件的复杂事件处理 -- 样式完全可控 - -### 2. CSS 样式设计 -**文件:** `pages/login/login.wxss` - -```css -.checkbox-container { - display: flex; - align-items: center; - justify-content: center; - gap: 12rpx; - cursor: pointer; -} - -.custom-checkbox { - width: 32rpx; - height: 32rpx; - border: 2rpx solid #d0d0d0; - border-radius: 6rpx; - background-color: #ffffff; - display: flex; - align-items: center; - justify-content: center; - transition: all 0.2s ease; -} - -.custom-checkbox.checked { - background-color: #3cc51f; - border-color: #3cc51f; -} - -.checkmark { - color: #ffffff; - font-size: 20rpx; - font-weight: bold; -} -``` - -**特点:** -- 绿色主题色 (#3cc51f) -- 平滑的过渡动画 -- 清晰的视觉反馈 - -### 3. JavaScript 逻辑简化 -**文件:** `pages/login/login.js` - -```javascript -// 切换用户协议状态 -toggleAgreement() { - console.log('点击用户协议,当前状态:', this.data.agreedToTerms) - const newState = !this.data.agreedToTerms - console.log('切换后状态:', newState) - this.setData({ - agreedToTerms: newState - }) -} -``` - -**优势:** -- 逻辑简单直接 -- 调试信息清晰 -- 不依赖复杂的事件处理 - -## 技术实现细节 - -### 状态管理 -- 使用 `agreedToTerms` 布尔值管理勾选状态 -- 通过 `setData` 更新状态 -- 状态变化立即反映到UI - -### 事件处理 -- 使用 `bindtap` 绑定点击事件 -- 整个容器都可点击 -- 事件处理简单可靠 - -### 样式控制 -- 使用条件类名 `{{agreedToTerms ? 'checked' : ''}}` -- 动态显示/隐藏勾选标记 -- CSS过渡效果提升用户体验 - -## 测试验证 - -### 功能测试 -1. **点击测试**:点击复选框和文字都应该能切换状态 -2. **状态测试**:勾选状态应该正确保存和显示 -3. **登录测试**:登录时应该正确验证协议状态 - -### 控制台输出 -``` -点击用户协议,当前状态: false -切换后状态: true -``` - -### 视觉反馈 -- 未勾选:白色背景,灰色边框 -- 已勾选:绿色背景,白色对勾 - -## 兼容性 -- 完全兼容微信小程序 -- 不依赖特定版本特性 -- 跨平台表现一致 - -## 维护性 -- 代码结构清晰 -- 样式易于修改 -- 功能易于扩展 - -## 总结 -通过使用自定义checkbox替代原生组件,彻底解决了用户协议勾选识别问题,提供了更好的用户体验和更可靠的代码实现。 diff --git a/mini_program/farm-monitor-dashboard/登录页面用户协议修复说明.md b/mini_program/farm-monitor-dashboard/登录页面用户协议修复说明.md deleted file mode 100644 index 965adf3..0000000 --- a/mini_program/farm-monitor-dashboard/登录页面用户协议修复说明.md +++ /dev/null @@ -1,108 +0,0 @@ -# 登录页面用户协议勾选问题修复说明 - -## 问题描述 -登录页面的用户协议复选框无法正确监听用户的勾选操作,导致登录验证失败。 - -## 问题原因 -在微信小程序中,`checkbox` 组件的 `bindchange` 事件返回的 `e.detail.value` 是一个数组,而不是布尔值。原代码直接使用 `e.detail.value` 作为布尔值,导致状态判断错误。 - -## 修复方案 - -### 1. WXML 文件修复 -**文件:** `pages/login/login.wxml` - -**修复前:** -```xml - -``` - -**修复后:** -```xml - -``` - -**说明:** 添加了 `value="agreement"` 属性,为复选框指定一个唯一值。 - -### 2. JavaScript 文件修复 -**文件:** `pages/login/login.js` - -**修复前:** -```javascript -onAgreementChange(e) { - this.setData({ - agreedToTerms: e.detail.value - }) -} -``` - -**修复后:** -```javascript -onAgreementChange(e) { - console.log('用户协议变化:', e.detail.value) - // checkbox 的 value 是数组,需要检查是否包含 'agreement' 值 - const isChecked = e.detail.value && e.detail.value.includes('agreement') - console.log('协议勾选状态:', isChecked) - this.setData({ - agreedToTerms: isChecked - }) -} -``` - -**说明:** -- 正确处理 `checkbox` 组件的数组返回值 -- 使用 `includes('agreement')` 检查是否包含指定值 -- 添加控制台日志,便于调试 - -## 技术细节 - -### 微信小程序 checkbox 组件特性 -- `bindchange` 事件返回的 `e.detail.value` 是数组格式 -- 当复选框被勾选时,数组包含其 `value` 属性值 -- 当复选框被取消勾选时,数组为空 `[]` - -### 事件返回值示例 -```javascript -// 勾选时 -e.detail.value = ['agreement'] - -// 取消勾选时 -e.detail.value = [] -``` - -## 测试验证 - -### 测试步骤 -1. 在微信开发者工具中打开项目 -2. 进入登录页面 -3. 点击用户协议复选框 -4. 查看控制台输出 -5. 尝试登录验证 - -### 预期结果 -- 控制台显示正确的状态变化日志 -- 登录时能正确验证协议勾选状态 -- 未勾选协议时显示提示信息 - -### 测试账号 -- 账号:`admin` -- 密码:`123456` - -## 相关文件 -- `pages/login/login.wxml` - 页面结构 -- `pages/login/login.js` - 页面逻辑 -- `pages/login/login.wxss` - 页面样式 - -## 注意事项 -1. 确保 `checkbox` 组件有唯一的 `value` 属性 -2. 正确处理 `bindchange` 事件的数组返回值 -3. 添加适当的日志输出便于调试 -4. 测试各种勾选状态的变化