From 11c48bf00ca37d8ea6149d2ca3b2982390a24202 Mon Sep 17 00:00:00 2001 From: Timi Date: Mon, 27 Jul 2026 13:10:08 +0800 Subject: [PATCH] init project --- .editorconfig | 9 + .env.development | 3 + .env.production | 2 + .eslintrc.cjs | 44 + .gitignore | 14 + .idea/.gitignore | 10 + .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/gao-customer-h5.iml | 8 + .idea/inspectionProfiles/Project_Default.xml | 20 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .serena/.gitignore | 2 + .serena/memories/project_overview.md | 4 + .serena/memories/style_conventions.md | 6 + .serena/memories/suggested_commands.md | 7 + .serena/memories/task_completion.md | 3 + .serena/project.yml | 153 + README.md | 4 +- eslint.config.js | 79 + index.html | 21 + package.json | 49 + pnpm-lock.yaml | 4181 +++++++++++++++++ public/icons/icon-192.png | Bin 0 -> 2908 bytes public/icons/icon-512.png | Bin 0 -> 10558 bytes public/icons/icon-maskable-512.png | Bin 0 -> 9705 bytes public/manifest.webmanifest | 27 + src/Root.vue | 51 + src/api/CustomerAPI.ts | 107 + src/api/GaoUserAPI.ts | 41 + src/api/RegistrationEventAPI.ts | 41 + src/api/RegistrationEventRecordAPI.ts | 88 + src/assets/sound/registration-success.mp3 | Bin 0 -> 21312 bytes src/assets/sound/scan-success.mp3 | Bin 0 -> 4320 bytes src/components/BodyAreaSelector.vue | 313 ++ src/components/CodeScanner.vue | 529 +++ src/components/CustomerProfileCard.vue | 130 + src/components/CustomerSelector.vue | 288 ++ src/components/GenderIcon.vue | 58 + src/components/PageTransition.vue | 153 + src/components/PhotoField.vue | 144 + src/components/PhotoScroller.vue | 206 + .../RegistrationEventRecordCalendar.vue | 425 ++ src/components/RegistrationEventSelector.vue | 89 + src/components/SegmentedSlider.vue | 186 + src/layout/MainLayout.vue | 251 + src/layout/RootLayout.vue | 20 + src/main.ts | 77 + src/pages/Login.vue | 209 + src/pages/customer/QuickEntryPage.vue | 576 +++ src/pages/customer/QuickSignInPage.vue | 445 ++ src/pages/management/CustomerDataCharts.vue | 670 +++ src/pages/management/CustomerDetail.vue | 564 +++ src/pages/management/CustomerEdit.vue | 541 +++ src/pages/management/CustomerList.vue | 374 ++ src/pages/management/ManagementDataCharts.vue | 521 ++ src/pages/management/ManagementPassword.vue | 98 + src/pages/management/ManagementProfile.vue | 279 ++ src/pages/management/ManagementQrCode.vue | 360 ++ src/pages/management/ManagementSettings.vue | 146 + src/pages/management/PermissionEdit.vue | 100 + src/pages/management/PermissionList.vue | 115 + src/pages/management/PermissionSettings.vue | 114 + .../management/RegistrationEventEdit.vue | 314 ++ .../management/RegistrationEventList.vue | 297 ++ .../RegistrationEventRecordDetail.vue | 138 + .../RegistrationEventRecordEdit.vue | 630 +++ .../RegistrationEventRecordList.vue | 629 +++ src/pages/management/RoleEdit.vue | 194 + src/pages/management/RoleList.vue | 89 + src/pages/management/RolePermissionAssign.vue | 290 ++ src/pages/management/UserDetail.vue | 240 + src/pages/management/UserEdit.vue | 147 + src/pages/management/UserList.vue | 195 + src/pages/management/UserRoleAssign.vue | 241 + src/pages/tabs/CustomerTab.vue | 129 + src/pages/tabs/ManagementTab.vue | 233 + src/router/index.ts | 108 + src/router/routes/chartRoutes.ts | 48 + src/router/routes/customerRoutes.ts | 110 + src/router/routes/managementRoutes.ts | 74 + src/router/routes/permissionRoutes.ts | 139 + src/router/routes/registrationRoutes.ts | 109 + src/router/routes/tabRoutes.ts | 36 + src/router/routes/userRoutes.ts | 80 + src/store/globalUI.ts | 41 + src/store/navBarStore.ts | 96 + src/store/permissionSettingsStore.ts | 339 ++ src/store/settingStore.ts | 232 + src/store/tabBarStore.ts | 9 + src/styles/global.less | 39 + src/styles/tdesign-custom.css | 284 ++ src/types/Customer.ts | 60 + src/types/GaoUser.ts | 10 + src/types/RegistrationEvent.ts | 18 + src/types/RegistrationEventRecord.ts | 81 + src/types/browser-image-compression.d.ts | 18 + src/utils/customer.ts | 32 + src/utils/gaoPermission.ts | 78 + src/utils/gaoRole.ts | 70 + src/utils/imageCompression.ts | 27 + src/utils/managementQrCode.ts | 278 ++ src/utils/registrationEventRecord.ts | 11 + tsconfig.app.json | 47 + tsconfig.json | 11 + tsconfig.node.json | 13 + tsconfig.publish.json | 25 + vite.config.ts | 88 + 107 files changed, 19350 insertions(+), 1 deletion(-) create mode 100644 .editorconfig create mode 100644 .env.development create mode 100644 .env.production create mode 100644 .eslintrc.cjs create mode 100644 .idea/.gitignore create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/gao-customer-h5.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .serena/.gitignore create mode 100644 .serena/memories/project_overview.md create mode 100644 .serena/memories/style_conventions.md create mode 100644 .serena/memories/suggested_commands.md create mode 100644 .serena/memories/task_completion.md create mode 100644 .serena/project.yml create mode 100644 eslint.config.js create mode 100644 index.html create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 public/icons/icon-192.png create mode 100644 public/icons/icon-512.png create mode 100644 public/icons/icon-maskable-512.png create mode 100644 public/manifest.webmanifest create mode 100644 src/Root.vue create mode 100644 src/api/CustomerAPI.ts create mode 100644 src/api/GaoUserAPI.ts create mode 100644 src/api/RegistrationEventAPI.ts create mode 100644 src/api/RegistrationEventRecordAPI.ts create mode 100644 src/assets/sound/registration-success.mp3 create mode 100644 src/assets/sound/scan-success.mp3 create mode 100644 src/components/BodyAreaSelector.vue create mode 100644 src/components/CodeScanner.vue create mode 100644 src/components/CustomerProfileCard.vue create mode 100644 src/components/CustomerSelector.vue create mode 100644 src/components/GenderIcon.vue create mode 100644 src/components/PageTransition.vue create mode 100644 src/components/PhotoField.vue create mode 100644 src/components/PhotoScroller.vue create mode 100644 src/components/RegistrationEventRecordCalendar.vue create mode 100644 src/components/RegistrationEventSelector.vue create mode 100644 src/components/SegmentedSlider.vue create mode 100644 src/layout/MainLayout.vue create mode 100644 src/layout/RootLayout.vue create mode 100644 src/main.ts create mode 100644 src/pages/Login.vue create mode 100644 src/pages/customer/QuickEntryPage.vue create mode 100644 src/pages/customer/QuickSignInPage.vue create mode 100644 src/pages/management/CustomerDataCharts.vue create mode 100644 src/pages/management/CustomerDetail.vue create mode 100644 src/pages/management/CustomerEdit.vue create mode 100644 src/pages/management/CustomerList.vue create mode 100644 src/pages/management/ManagementDataCharts.vue create mode 100644 src/pages/management/ManagementPassword.vue create mode 100644 src/pages/management/ManagementProfile.vue create mode 100644 src/pages/management/ManagementQrCode.vue create mode 100644 src/pages/management/ManagementSettings.vue create mode 100644 src/pages/management/PermissionEdit.vue create mode 100644 src/pages/management/PermissionList.vue create mode 100644 src/pages/management/PermissionSettings.vue create mode 100644 src/pages/management/RegistrationEventEdit.vue create mode 100644 src/pages/management/RegistrationEventList.vue create mode 100644 src/pages/management/RegistrationEventRecordDetail.vue create mode 100644 src/pages/management/RegistrationEventRecordEdit.vue create mode 100644 src/pages/management/RegistrationEventRecordList.vue create mode 100644 src/pages/management/RoleEdit.vue create mode 100644 src/pages/management/RoleList.vue create mode 100644 src/pages/management/RolePermissionAssign.vue create mode 100644 src/pages/management/UserDetail.vue create mode 100644 src/pages/management/UserEdit.vue create mode 100644 src/pages/management/UserList.vue create mode 100644 src/pages/management/UserRoleAssign.vue create mode 100644 src/pages/tabs/CustomerTab.vue create mode 100644 src/pages/tabs/ManagementTab.vue create mode 100644 src/router/index.ts create mode 100644 src/router/routes/chartRoutes.ts create mode 100644 src/router/routes/customerRoutes.ts create mode 100644 src/router/routes/managementRoutes.ts create mode 100644 src/router/routes/permissionRoutes.ts create mode 100644 src/router/routes/registrationRoutes.ts create mode 100644 src/router/routes/tabRoutes.ts create mode 100644 src/router/routes/userRoutes.ts create mode 100644 src/store/globalUI.ts create mode 100644 src/store/navBarStore.ts create mode 100644 src/store/permissionSettingsStore.ts create mode 100644 src/store/settingStore.ts create mode 100644 src/store/tabBarStore.ts create mode 100644 src/styles/global.less create mode 100644 src/styles/tdesign-custom.css create mode 100644 src/types/Customer.ts create mode 100644 src/types/GaoUser.ts create mode 100644 src/types/RegistrationEvent.ts create mode 100644 src/types/RegistrationEventRecord.ts create mode 100644 src/types/browser-image-compression.d.ts create mode 100644 src/utils/customer.ts create mode 100644 src/utils/gaoPermission.ts create mode 100644 src/utils/gaoRole.ts create mode 100644 src/utils/imageCompression.ts create mode 100644 src/utils/managementQrCode.ts create mode 100644 src/utils/registrationEventRecord.ts create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 tsconfig.publish.json create mode 100644 vite.config.ts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f7785bd --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = tab +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..873c9d8 --- /dev/null +++ b/.env.development @@ -0,0 +1,3 @@ +VITE_APP_TITLE=Gao Customer H5 +VITE_USE_LOCAL_TIMI_WEB=true +VITE_API_BASE_URL=http://localhost:8091 diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..dd8bb80 --- /dev/null +++ b/.env.production @@ -0,0 +1,2 @@ +VITE_APP_TITLE=Gao Customer H5 +VITE_API_BASE_URL=https://api.imyeyu.com diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..ae13a7c --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,44 @@ +module.exports = { + root: true, + env: { + browser: true, + es2022: true, + node: true + }, + extends: [ + "eslint:recommended", + "plugin:vue/vue3-essential", + "plugin:@typescript-eslint/recommended", + "./.eslintrc-auto-import.json" + ], + parser: "vue-eslint-parser", + parserOptions: { + parser: "@typescript-eslint/parser", + ecmaVersion: "latest", + sourceType: "module", + extraFileExtensions: [".vue"] + }, + plugins: ["vue", "@typescript-eslint"], + rules: { + "camelcase": "error", + "comma-dangle": ["error", "never"], + "eqeqeq": ["error", "always"], + "max-len": ["error", { code: 220 }], + "no-console": ["warn", { allow: ["warn", "error"] }], + "no-debugger": "warn", + "no-tabs": ["error", { allowIndentationTabs: true }], + "quotes": ["error", "double"], + "semi": ["error", "always"], + "space-before-function-paren": [ + "error", + { + "anonymous": "always", + "named": "never", + "asyncArrow": "always" + } + ], + "vue/multi-word-component-names": "off", + "vue/no-v-html": "off", + "@typescript-eslint/no-explicit-any": "off" + } +}; diff --git a/.gitignore b/.gitignore index 7f7e9bb..6fd4a3b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +/AGENTS.md +/.npmrc +/.env.production + # ---> Maven target/ pom.xml.tag @@ -122,3 +126,13 @@ fabric.properties hs_err_pid* replay_pid* +# ---> Node / Vite +node_modules +dist +dist-ssr +coverage +*.local +auto-imports.d.ts +components.d.ts +.eslintrc-auto-import.json + diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..30cf57e --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/gao-customer-h5.iml b/.idea/gao-customer-h5.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/gao-customer-h5.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..9f87cb1 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,20 @@ + + + + diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..9c28189 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.serena/.gitignore b/.serena/.gitignore new file mode 100644 index 0000000..2e510af --- /dev/null +++ b/.serena/.gitignore @@ -0,0 +1,2 @@ +/cache +/project.local.yml diff --git a/.serena/memories/project_overview.md b/.serena/memories/project_overview.md new file mode 100644 index 0000000..5ff99e2 --- /dev/null +++ b/.serena/memories/project_overview.md @@ -0,0 +1,4 @@ +- 项目用途:基于 Vue 3 + Vite + TypeScript + TDesign 的移动端 NAS 管理项目,包含文件管理、服务器状态、文件读取等功能。 +- 前端栈:Vue 3 Composition API(setup 语法糖)、Vite、TypeScript、Pinia、Vue Router、Axios、Less、TDesign。 +- 后端接口上下文:对接后端源码位于 E:\IDEAProject\TimiServerAPI\src\main\java\com\imyeyu\api\modules\system\controller。 +- 代码结构:主要业务页面位于 src/pages,下分 customer、management 等目录;入口与路由位于 src/main.ts、src/router/index.ts;存在 Pinia store。 \ No newline at end of file diff --git a/.serena/memories/style_conventions.md b/.serena/memories/style_conventions.md new file mode 100644 index 0000000..dae71a6 --- /dev/null +++ b/.serena/memories/style_conventions.md @@ -0,0 +1,6 @@ +- 所有沟通、文案、注释使用中文;文件编码使用 UTF-8。 +- 前端使用 Vue 3 Composition API + setup,代码按功能分块组织,公共变量/函数在前。 +- Vue 自定义组件标签使用全小写;模板中动态文本优先使用 v-text。 +- Less 必须使用层级写法,属性尽量缩写,单位优先 rem,小数写法如 .5。 +- 尽量定义 TypeScript 类型和必要的 JSDoc;Promise 写法优先 async/await。 +- 不轻易引入外部依赖,优先官方 API;需要兼容深色模式。 \ No newline at end of file diff --git a/.serena/memories/suggested_commands.md b/.serena/memories/suggested_commands.md new file mode 100644 index 0000000..d4b5c6e --- /dev/null +++ b/.serena/memories/suggested_commands.md @@ -0,0 +1,7 @@ +- 安装依赖:npm install +- 本地开发:npm run dev +- 生产构建:npm run build +- 预览构建:npm run preview +- ESLint 检查:npm run lint +- TypeScript 检查:npm run type-check +- Windows 常用命令:Get-ChildItem、Get-Content、rg、git status、git diff \ No newline at end of file diff --git a/.serena/memories/task_completion.md b/.serena/memories/task_completion.md new file mode 100644 index 0000000..80ed1c5 --- /dev/null +++ b/.serena/memories/task_completion.md @@ -0,0 +1,3 @@ +- 完成前端改动后,至少执行 npm run build 或 npm run type-check 验证没有明显编译错误。 +- 如涉及样式和交互,检查深色模式与移动端布局,避免固定底部按钮遮挡内容。 +- 不主动添加测试;若无法运行验证命令,需要在最终说明中明确指出。 \ No newline at end of file diff --git a/.serena/project.yml b/.serena/project.yml new file mode 100644 index 0000000..08e55a8 --- /dev/null +++ b/.serena/project.yml @@ -0,0 +1,153 @@ +# the name by which the project can be referenced within Serena +project_name: "gao-customer-h5" + + +# list of languages for which language servers are started; choose from: +# al bash clojure cpp csharp +# csharp_omnisharp dart elixir elm erlang +# fortran fsharp go groovy haskell +# haxe java julia kotlin lua +# markdown +# matlab nix pascal perl php +# php_phpactor powershell python python_jedi r +# rego ruby ruby_solargraph rust scala +# swift terraform toml typescript typescript_vts +# vue yaml zig +# (This list may be outdated. For the current list, see values of Language enum here: +# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py +# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.) +# Note: +# - For C, use cpp +# - For JavaScript, use typescript +# - For Free Pascal/Lazarus, use pascal +# Special requirements: +# Some languages require additional setup/installations. +# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers +# When using multiple languages, the first language server that supports a given file will be used for that file. +# The first language is the default language and the respective language server will be used as a fallback. +# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored. +languages: [] + +# the encoding used by text files in the project +# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings +encoding: "utf-8" + +# line ending convention to use when writing source files. +# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default) +# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings. +line_ending: + +# The language backend to use for this project. +# If not set, the global setting from serena_config.yml is used. +# Valid values: LSP, JetBrains +# Note: the backend is fixed at startup. If a project with a different backend +# is activated post-init, an error will be returned. +language_backend: + +# whether to use project's .gitignore files to ignore files +ignore_all_files_in_gitignore: true + +# advanced configuration option allowing to configure language server-specific options. +# Maps the language key to the options. +# Have a look at the docstring of the constructors of the LS implementations within solidlsp (e.g., for C# or PHP) to see which options are available. +# No documentation on options means no options are available. +ls_specific_settings: {} + +# list of additional paths to ignore in this project. +# Same syntax as gitignore, so you can use * and **. +# Note: global ignored_paths from serena_config.yml are also applied additively. +ignored_paths: [] + +# whether the project is in read-only mode +# If set to true, all editing tools will be disabled and attempts to use them will result in an error +# Added on 2025-04-18 +read_only: false + +# list of tool names to exclude. +# This extends the existing exclusions (e.g. from the global configuration) +# +# Below is the complete list of tools for convenience. +# To make sure you have the latest list of tools, and to view their descriptions, +# execute `uv run scripts/print_tool_overview.py`. +# +# * `activate_project`: Activates a project based on the project name or path. +# * `check_onboarding_performed`: Checks whether project onboarding was already performed. +# * `create_text_file`: Creates/overwrites a file in the project directory. +# * `delete_memory`: Delete a memory file. Should only happen if a user asks for it explicitly, +# for example by saying that the information retrieved from a memory file is no longer correct +# or no longer relevant for the project. +# * `edit_memory`: Replaces content matching a regular expression in a memory. +# * `execute_shell_command`: Executes a shell command. +# * `find_file`: Finds files in the given relative paths +# * `find_referencing_symbols`: Finds symbols that reference the given symbol using the language server backend +# * `find_symbol`: Performs a global (or local) search using the language server backend. +# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes. +# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file. +# * `initial_instructions`: Provides instructions Serena usage (i.e. the 'Serena Instructions Manual') +# for clients that do not read the initial instructions when the MCP server is connected. +# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol. +# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol. +# * `list_dir`: Lists files and directories in the given directory (optionally with recursion). +# * `list_memories`: List available memories. Any memory can be read using the `read_memory` tool. +# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building). +# * `read_file`: Reads a file within the project directory. +# * `read_memory`: Read the content of a memory file. This tool should only be used if the information +# is relevant to the current task. You can infer whether the information +# is relevant from the memory file name. +# You should not read the same memory file multiple times in the same conversation. +# * `rename_memory`: Renames or moves a memory. Moving between project and global scope is supported +# (e.g., renaming "global/foo" to "bar" moves it from global to project scope). +# * `rename_symbol`: Renames a symbol throughout the codebase using language server refactoring capabilities. +# For JB, we use a separate tool. +# * `replace_content`: Replaces content in a file (optionally using regular expressions). +# * `replace_symbol_body`: Replaces the full definition of a symbol using the language server backend. +# * `safe_delete_symbol`: +# * `search_for_pattern`: Performs a search for a pattern in the project. +# * `write_memory`: Write some information (utf-8-encoded) about this project that can be useful for future tasks to a memory in md format. +# The memory name should be meaningful. +excluded_tools: [] + +# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default). +# This extends the existing inclusions (e.g. from the global configuration). +included_optional_tools: [] + +# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools. +# This cannot be combined with non-empty excluded_tools or included_optional_tools. +fixed_tools: [] + +# list of mode names to that are always to be included in the set of active modes +# The full set of modes to be activated is base_modes + default_modes. +# If the setting is undefined, the base_modes from the global configuration (serena_config.yml) apply. +# Otherwise, this setting overrides the global configuration. +# Set this to [] to disable base modes for this project. +# Set this to a list of mode names to always include the respective modes for this project. +base_modes: + +# list of mode names that are to be activated by default. +# The full set of modes to be activated is base_modes + default_modes. +# If the setting is undefined, the default_modes from the global configuration (serena_config.yml) apply. +# Otherwise, this overrides the setting from the global configuration (serena_config.yml). +# This setting can, in turn, be overridden by CLI parameters (--mode). +default_modes: + +# initial prompt for the project. It will always be given to the LLM upon activating the project +# (contrary to the memories, which are loaded on demand). +initial_prompt: "" + +# time budget (seconds) per tool call for the retrieval of additional symbol information +# such as docstrings or parameter information. +# This overrides the corresponding setting in the global configuration; see the documentation there. +# If null or missing, use the setting from the global configuration. +symbol_info_budget: + +# list of regex patterns which, when matched, mark a memory entry as read‑only. +# Extends the list from the global configuration, merging the two lists. +read_only_memory_patterns: [] + +# list of regex patterns for memories to completely ignore. +# Matching memories will not appear in list_memories or activate_project output +# and cannot be accessed via read_memory or write_memory. +# To access ignored memory files, use the read_file tool on the raw file path. +# Extends the list from the global configuration, merging the two lists. +# Example: ["_archive/.*", "_episodes/.*"] +ignored_memory_patterns: [] diff --git a/README.md b/README.md index d9d6670..2291917 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ -# dtgao-customer-h5 +# gao-customer-h5 + +基于 Vue 3、Vite、TypeScript、Pinia、Vue Router、TDesign Mobile Vue 的移动端项目初始化骨架。 diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..7f0be18 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,79 @@ +import tsParser from "@typescript-eslint/parser"; +import tsPlugin from "@typescript-eslint/eslint-plugin"; +import vuePlugin from "eslint-plugin-vue"; +import vueParser from "vue-eslint-parser"; +import autoImportConfig from "./.eslintrc-auto-import.json" with { type: "json" }; + +const browserGlobals = { + document: "readonly", + File: "readonly", + HTMLCanvasElement: "readonly", + HTMLInputElement: "readonly", + HTMLElement: "readonly", + localStorage: "readonly", + MouseEvent: "readonly", + Touch: "readonly", + TouchEvent: "readonly", + URL: "readonly", + window: "readonly" +}; + +const nodeGlobals = { + console: "readonly", + process: "readonly" +}; + +export default [ + { + ignores: [ + "dist/**", + "node_modules/**", + "auto-imports.d.ts", + "components.d.ts" + ] + }, + ...vuePlugin.configs["flat/essential"], + { + files: ["**/*.ts", "**/*.vue"], + languageOptions: { + parser: vueParser, + parserOptions: { + parser: tsParser, + ecmaVersion: "latest", + sourceType: "module", + extraFileExtensions: [".vue"] + }, + globals: { + ...browserGlobals, + ...nodeGlobals, + ...autoImportConfig.globals + } + }, + plugins: { + "@typescript-eslint": tsPlugin + }, + rules: { + ...tsPlugin.configs.recommended.rules, + camelcase: "error", + "comma-dangle": ["error", "never"], + eqeqeq: ["error", "always"], + "max-len": ["error", { code: 220 }], + "no-console": ["warn", { allow: ["warn", "error"] }], + "no-debugger": "warn", + "no-tabs": ["error", { allowIndentationTabs: true }], + quotes: ["error", "double"], + semi: ["error", "always"], + "space-before-function-paren": [ + "error", + { + anonymous: "always", + named: "never", + asyncArrow: "always" + } + ], + "vue/multi-word-component-names": "off", + "vue/no-v-html": "off", + "@typescript-eslint/no-explicit-any": "off" + } + } +]; diff --git a/index.html b/index.html new file mode 100644 index 0000000..4bb048e --- /dev/null +++ b/index.html @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + Gao Customer H5 + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..7272345 --- /dev/null +++ b/package.json @@ -0,0 +1,49 @@ +{ + "name": "gao-customer-h5", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite --host", + "build": "pnpm run type-check:publish && vite build", + "preview": "vite preview", + "lint": "eslint . --ext .ts,.vue", + "type-check": "vue-tsc -p tsconfig.app.json --noEmit", + "type-check:publish": "vue-tsc -p tsconfig.publish.json --noEmit" + }, + "dependencies": { + "@zxing/browser": "^0.1.5", + "@zxing/library": "^0.21.3", + "echarts": "^6.0.0", + "vue-echarts": "^8.0.1", + "axios": "1.15.0", + "less": "^4.3.0", + "pinia": "^3.0.2", + "tdesign-mobile-vue": "^1.16.0", + "timi-tdesign-mobile": "0.0.10", + "browser-image-compression": "^2.0.2", + "timi-web": "0.0.24", + "ts-node": "^10.9.2", + "vue": "^3.5.16", + "vue-router": "4.5.1", + "vue-virtual-scroller": "2.0.0-beta.8" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.4", + "@types/node": "^24.2.0", + "@typescript-eslint/eslint-plugin": "^8.29.0", + "@typescript-eslint/parser": "^8.29.0", + "@vitejs/plugin-vue": "^5.2.4", + "@vue/compiler-sfc": "^3.5.16", + "@vue/eslint-config-typescript": "^14.5.0", + "@vue/tsconfig": "^0.7.0", + "eslint": "9.26.0", + "eslint-plugin-vue": "^9.33.0", + "typescript": "~5.8.3", + "unplugin-auto-import": "^19.1.1", + "unplugin-vue-components": "^28.4.1", + "vite": "^6.3.5", + "vue-eslint-parser": "^9.4.3", + "vue-tsc": "^2.2.12" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..05ff868 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,4181 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@zxing/browser': + specifier: ^0.1.5 + version: 0.1.5(@zxing/library@0.21.3) + '@zxing/library': + specifier: ^0.21.3 + version: 0.21.3 + axios: + specifier: 1.15.0 + version: 1.15.0 + browser-image-compression: + specifier: ^2.0.2 + version: 2.0.2 + echarts: + specifier: ^6.0.0 + version: 6.1.0 + less: + specifier: ^4.3.0 + version: 4.8.0 + pinia: + specifier: ^3.0.2 + version: 3.0.4(typescript@5.8.3)(vue@3.5.40(typescript@5.8.3)) + tdesign-mobile-vue: + specifier: ^1.16.0 + version: 1.16.0(vue@3.5.40(typescript@5.8.3)) + timi-tdesign-mobile: + specifier: 0.0.10 + version: 0.0.10(typescript@5.8.3) + timi-web: + specifier: 0.0.24 + version: 0.0.24(typescript@5.8.3)(vue@3.5.40(typescript@5.8.3)) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@24.13.3)(typescript@5.8.3) + vue: + specifier: ^3.5.16 + version: 3.5.40(typescript@5.8.3) + vue-echarts: + specifier: ^8.0.1 + version: 8.0.1(echarts@6.1.0)(vue@3.5.40(typescript@5.8.3)) + vue-router: + specifier: 4.5.1 + version: 4.5.1(vue@3.5.40(typescript@5.8.3)) + vue-virtual-scroller: + specifier: 2.0.0-beta.8 + version: 2.0.0-beta.8(vue@3.5.40(typescript@5.8.3)) + devDependencies: + '@tsconfig/node20': + specifier: ^20.1.4 + version: 20.1.9 + '@types/node': + specifier: ^24.2.0 + version: 24.13.3 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.0 + version: 8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.29.0 + version: 8.65.0(eslint@9.26.0)(typescript@5.8.3) + '@vitejs/plugin-vue': + specifier: ^5.2.4 + version: 5.2.4(vite@6.4.3(@types/node@24.13.3)(less@4.8.0)(terser@5.49.0))(vue@3.5.40(typescript@5.8.3)) + '@vue/compiler-sfc': + specifier: ^3.5.16 + version: 3.5.40 + '@vue/eslint-config-typescript': + specifier: ^14.5.0 + version: 14.9.0(eslint-plugin-vue@9.33.0(eslint@9.26.0))(eslint@9.26.0)(typescript@5.8.3) + '@vue/tsconfig': + specifier: ^0.7.0 + version: 0.7.0(typescript@5.8.3)(vue@3.5.40(typescript@5.8.3)) + eslint: + specifier: 9.26.0 + version: 9.26.0 + eslint-plugin-vue: + specifier: ^9.33.0 + version: 9.33.0(eslint@9.26.0) + typescript: + specifier: ~5.8.3 + version: 5.8.3 + unplugin-auto-import: + specifier: ^19.1.1 + version: 19.3.0(@vueuse/core@10.7.0(vue@3.5.40(typescript@5.8.3))) + unplugin-vue-components: + specifier: ^28.4.1 + version: 28.8.0(@babel/parser@7.29.7)(vue@3.5.40(typescript@5.8.3)) + vite: + specifier: ^6.3.5 + version: 6.4.3(@types/node@24.13.3)(less@4.8.0)(terser@5.49.0) + vue-eslint-parser: + specifier: ^9.4.3 + version: 9.4.3(eslint@9.26.0) + vue-tsc: + specifier: ^2.2.12 + version: 2.2.12(typescript@5.8.3) + +packages: + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + engines: {node: '>=6.9.0'} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.10.1': + resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.20.1': + resolution: {integrity: sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.2.3': + resolution: {integrity: sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.13.0': + resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.6': + resolution: {integrity: sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.26.0': + resolution: {integrity: sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.8': + resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@hono/node-server@1.19.15': + resolution: {integrity: sha512-Za2ai6TLdKjUvnur+eenO6nuYYipVAEhyCAdaV8IRvmU9kK8crOZUSYvIXn72E4f8fJqyAbpcJuTsYYmZp9Deg==} + engines: {node: '>=18.14.1'} + peerDependencies: + hono: ^4 + + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@modelcontextprotocol/sdk@1.29.0': + resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==} + engines: {node: '>=18'} + peerDependencies: + '@cfworker/json-schema': ^4.1.1 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + '@cfworker/json-schema': + optional: true + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@rollup/rollup-android-arm-eabi@4.62.3': + resolution: {integrity: sha512-c0wdcekXtQvvn5Tsrk/+op/gUArrbWaFduBnTLP2l1cKLSQs4diMWjJw3m6A0DdzT8dAAX95KpkJ3qynCePbmw==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.62.3': + resolution: {integrity: sha512-3YjElDdWN+qXAFbJ/CzPV+0wspLqh54k/I6GfdYtEJRqg7buSgc1yPM3B+93j1M4neobtkATHZTmxK2AMVGfnA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.62.3': + resolution: {integrity: sha512-Pch2pFNOxxz1hTjypIdPyRTR6riiwRl84+VcN9djS680fw+Co1nAJINrdpqp7KV0NvyuU8ilZXZCjd7ykJl1GQ==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.62.3': + resolution: {integrity: sha512-LEuncFUHFiF8t4yZVZvvZA1wk0pjAscRnsrn1EfTEmN4HXotBi2YtcnLRyaK6UbuczW7xZS5ES+81Rdz8Z0T6g==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.62.3': + resolution: {integrity: sha512-zvBUvsQUpOWALdDsk6qbS8bXf2VxmPisuudNDrY7x0p0jBdsoZl8HsHczIOgkQiZldmcacMKtBzpoGVNeIe2bQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.62.3': + resolution: {integrity: sha512-C2KmNrcSem/AMg984H/dev+si0lieQGdXdR/lYGJnuumXnFb9Y7QdiI62obFdLlxRYLBv4P0eUVIDbD4c1vVvw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.62.3': + resolution: {integrity: sha512-ggXnsTAEzNQx74XpunRsiZ9aBZDsI7XIa0hm2nzR9f4WzH5/f/d73ZSDaC5ejJ8YLY4NW+V3wr0tjOaeCq8hqA==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.62.3': + resolution: {integrity: sha512-2vng+FlzNUhKZxtej3IUqJgbZoQk2M/dwQM20+ULV0R/E/8tr9/P6uEf2iiGIk4HL0zMKh5Jry7mUHdUOvyGgA==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.62.3': + resolution: {integrity: sha512-LLLFZKt4/Nraf9rxDkhiU8QVgLF4WmCkfr0L4fj0fPfIZFBib0DeiFk1hhaYKd03LFAFJcxHslhDFlNJLylf5Q==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.62.3': + resolution: {integrity: sha512-WJkdQCvS9sWNOUBJZfQRKpZGFBztRzcowI+nndmflKgU4XY+3a420FgTOSKTsVqJbnzSxeT4vaJalpOaPo2YCQ==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.62.3': + resolution: {integrity: sha512-PwHXCCS2n64/1Ot6rP1YEYA02MGYBcQlr8CSZZyrUG2O7NH6NklYmvr9v3Jy+5e/eDeNchc/ukmKJi9LuflMIQ==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.62.3': + resolution: {integrity: sha512-vUjxINQu3RC8NZS3ykk1gN65gIz8pAopOq2HXuZhiIxHdx7TFvDG+jgrdSgInu1Eza4/Rfi2VzZgyIgEH4WOaw==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.62.3': + resolution: {integrity: sha512-wzko4aJ13+0G3kGnviCg5gnXFKd40izKsrf2uOw12US4XqprkDrmwOpeW14aSNa37V8bfPcz5Fkob6LZ3BAPmA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.62.3': + resolution: {integrity: sha512-8120ue0JUMSwy11stlwnfdX3pPd+WZYGCDBwEHWtIHi6pOpZmsEF5QKB7a/UN+XFdqvobxz98kv8RTqikyCEBw==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.62.3': + resolution: {integrity: sha512-XLFHnR3tXMjbOCh2vtVJHmxt+995uJsTERQyseFDRA0xxMxyTZPLa3OIUlyFaO4mF/Lu0FjmWHCuPXJT1n/IOg==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.62.3': + resolution: {integrity: sha512-se6yXvNGMIl0f+RQzyh7XAmia8/9kplQx424wnG2w0C1oi6XgO6Y8otKhdXFHbHs88Ihavzmvh1NWjuovE76BQ==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.62.3': + resolution: {integrity: sha512-gNoxRefktVIiGflpONuxWWXZAzIQG++z9qHO3xKwk4WdDMuQja3JHGfE1u0i3PfPDyvhypdk+WrgIJqLhGG7sg==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.62.3': + resolution: {integrity: sha512-V4KtWtQfAFMU7+9/A/VDps/VI8CHd3cYz0L8sgJzz8qK7eY7wI4ruFD82UYIYvW9Z4DtlTfhQcsl4XyPHW5uSg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.62.3': + resolution: {integrity: sha512-LBx9LYXvj2CBkMkjLdNAWLwH0MLMin7do2VcVo9kVPibGLkY0BQQut2fv7NVqkXqZ/CrAu9LqDHVV1xHCMpCPw==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.62.3': + resolution: {integrity: sha512-ABVf3Q0RCu7NcyCCOZQI0pJ3GuSdfSl8EXcy88QtdceIMIoCUdfhsJChZ64L9zVM2aJHjde1Bhn5uqSRcX9ySA==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.62.3': + resolution: {integrity: sha512-+2Cy/ldweGBLlPIKsQLF8U5N44a0KDdbrk1rAjHOM9M2K+kGdIVjHLmmrZIcx+9Ny3ke/1JomCsDI1ocb11+sg==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.62.3': + resolution: {integrity: sha512-dtZvzc8BedpSaFNy75x6uiWwAGTH+aZHDtdrqP6qk+WcLJrfti6sGje1ZJ9UxyzDLF23d/mV+PaMwuC0hL7UVA==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.62.3': + resolution: {integrity: sha512-Rj8Ra4noo+aYy7sKBggCx0407mws34kAb1ySyWuq5DAtFBQdkSwnsjCgPrhPe9cvgBKZIukpE+CVHvORCS93kQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.62.3': + resolution: {integrity: sha512-vp7N084ew/odXn2gi/mzm9mUkQu9l6AiN6dt4IeUM2Uvm9o+cVmP+YkqbMOteLbiGgqBBlJZjIMYVCfOOIVbVQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.62.3': + resolution: {integrity: sha512-MOG/3gTOn4Fwf574RVOaY61I5o6P90legkFADiTyn1hyjNydT+cerU2rLUwPdZkKKyJ+iT+K9p7WXK4LM1Ka6g==} + cpu: [x64] + os: [win32] + + '@tsconfig/node10@1.0.12': + resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@tsconfig/node20@20.1.9': + resolution: {integrity: sha512-IjlTv1RsvnPtUcjTqtVsZExKVq+KQx4g5pCP5tI7rAs6Xesl2qFwSz/tPDBC4JajkL/MlezBu3gPUwqRHl+RIg==} + + '@types/esrecurse@4.3.1': + resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@24.13.3': + resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==} + + '@types/web-bluetooth@0.0.20': + resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + + '@typescript-eslint/eslint-plugin@8.65.0': + resolution: {integrity: sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.65.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/parser@8.65.0': + resolution: {integrity: sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/project-service@8.65.0': + resolution: {integrity: sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/scope-manager@8.65.0': + resolution: {integrity: sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.65.0': + resolution: {integrity: sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/type-utils@8.65.0': + resolution: {integrity: sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/types@8.65.0': + resolution: {integrity: sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.65.0': + resolution: {integrity: sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/utils@8.65.0': + resolution: {integrity: sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/visitor-keys@8.65.0': + resolution: {integrity: sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@use-gesture/core@10.3.1': + resolution: {integrity: sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==} + + '@use-gesture/vanilla@10.3.1': + resolution: {integrity: sha512-lT4scGLu59ovA3zmtUonukAGcA0AdOOh+iwNDS05Bsu7Lq9aZToDHhI6D8Q2qvsVraovtsLLYwPrWdG/noMAKw==} + + '@vitejs/plugin-vue@5.2.4': + resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.2.25 + + '@volar/language-core@2.4.15': + resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==} + + '@volar/source-map@2.4.15': + resolution: {integrity: sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==} + + '@volar/typescript@2.4.15': + resolution: {integrity: sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==} + + '@vue/compiler-core@3.5.40': + resolution: {integrity: sha512-39E8IgOhTbVDnoJFMKc2DvYnypcZwUqgUhQkccva/0m6FUwtIKSGV7n1hpVmYcFaoRAwf9pBcwnKlCEsN63ZEQ==} + + '@vue/compiler-dom@3.5.40': + resolution: {integrity: sha512-pwkx4vqlqOspFstrcmzwkKLePVMD3PT65imRzLhanU2V1Fj4K13g6OXjanOyzw3aTAuRk84BOmY8f3rEHqPaVA==} + + '@vue/compiler-sfc@3.5.40': + resolution: {integrity: sha512-gIf497P4kpuALcvs5n3AEg1Vdn0pSY4XbjASIfHNYF1/MP3T2Mf2STERTubysBxCRxzJGJYtF/O7vwJrxFB3Vw==} + + '@vue/compiler-ssr@3.5.40': + resolution: {integrity: sha512-rrE5xiXG663+vHCHa3J9p2z5OcBRjXmoqenprJxAFQxg5pSshzeBiCE6pu46axapRJ2Adk0YDA2BRZVjiHXnhg==} + + '@vue/compiler-vue2@2.7.16': + resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} + + '@vue/devtools-api@6.6.4': + resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} + + '@vue/devtools-api@7.7.10': + resolution: {integrity: sha512-KxtEpUOOpFz/qOGRrAwA36QF7DqIA+FXgCYit9mk9wjbaZt0sXOFz81ElOZtKA4HbWHUdwNjZHBFsFFyp5BZiA==} + + '@vue/devtools-kit@7.7.10': + resolution: {integrity: sha512-3WNi2Kq4tbpVbmhml7RiphmAt0279oh3fKNeWMQIrltfX8Q91b4i5PL8DtyNKdwmcsGrV4fg+erwWOmD05CLIw==} + + '@vue/devtools-shared@7.7.10': + resolution: {integrity: sha512-wOPslzB8vTvpxwdaOcR2qAbwmuSP0L+rhpoC6Cf56V3Jip+HWb7PQQXOUPgBNQARpXsbQX/+mvi8kKucmBGRwQ==} + + '@vue/eslint-config-typescript@14.9.0': + resolution: {integrity: sha512-E3j9hDlfVf10F30MRcLTPY2IIhWIx1nsvkVukk14kTcuA+oBVot9zsP1hzsO+PAMDxV3Fd9FimBJtUBNBL5KFA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + eslint: ^9.10.0 || ^10.0.0 + eslint-plugin-vue: ^9.28.0 || ^10.0.0 + typescript: '>=4.8.4' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/language-core@2.2.12': + resolution: {integrity: sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/reactivity@3.5.40': + resolution: {integrity: sha512-B7ot9UlUZOi1zbq61/LvE88ZLTV8IlajTdiZTAEiDQgrnIMIZoPr9kGw0Zw46ObW62O9+H/Be3kMbfb7kYPQZA==} + + '@vue/runtime-core@3.5.40': + resolution: {integrity: sha512-KAZLweuZ6uUJPK1PMSQPgBU5gCjgrrfjUhSglmU9NhH+Zjepa8cnwSydPWDWHDwOgY4g3VcZ+PljbiHlURNCbw==} + + '@vue/runtime-dom@3.5.40': + resolution: {integrity: sha512-ZfrX8ssZQds900L9pr8AuK05ddnMsR4MPMZr8cPN9GoqoPWcXLhjvvbIA2SMv+7a97sJ1vv9pj/zxK0Cq/eEFQ==} + + '@vue/server-renderer@3.5.40': + resolution: {integrity: sha512-XNJym9WpevhTVt1HuwOrCRJ5Q+9z4BjTMrDtjTrvx74SmUll8spNTw6whWJa9mEkO4PKn5TihI/bm/8ds2QVJw==} + + '@vue/shared@3.5.40': + resolution: {integrity: sha512-WxnBtruIqOoV3rA4jeKDWzrYI5h7Cp4+pjwDi8kWGHz+IslhiN+wguLVVhtv2l8VoU02rzDCVfDjgCl1lNpZVg==} + + '@vue/tsconfig@0.7.0': + resolution: {integrity: sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg==} + peerDependencies: + typescript: 5.x + vue: ^3.4.0 + peerDependenciesMeta: + typescript: + optional: true + vue: + optional: true + + '@vueuse/core@10.7.0': + resolution: {integrity: sha512-4EUDESCHtwu44ZWK3Gc/hZUVhVo/ysvdtwocB5vcauSV4B7NiGY5972WnsojB3vRNdxvAt7kzJWE2h9h7C9d5w==} + + '@vueuse/metadata@10.7.0': + resolution: {integrity: sha512-GlaH7tKP2iBCZ3bHNZ6b0cl9g0CJK8lttkBNUX156gWvNYhTKEtbweWLm9rxCPIiwzYcr/5xML6T8ZUEt+DkvA==} + + '@vueuse/shared@10.7.0': + resolution: {integrity: sha512-kc00uV6CiaTdc3i1CDC4a3lBxzaBE9AgYNtFN87B5OOscqeWElj/uza8qVDmk7/U8JbqoONLbtqiLJ5LGRuqlw==} + + '@zxing/browser@0.1.5': + resolution: {integrity: sha512-4Lmrn/il4+UNb87Gk8h1iWnhj39TASEHpd91CwwSJtY5u+wa0iH9qS0wNLAWbNVYXR66WmT5uiMhZ7oVTrKfxw==} + peerDependencies: + '@zxing/library': ^0.21.0 + + '@zxing/library@0.21.3': + resolution: {integrity: sha512-hZHqFe2JyH/ZxviJZosZjV+2s6EDSY0O24R+FQmlWZBZXP9IqMo7S3nb3+2LBWxodJQkSurdQGnqE7KXqrYgow==} + engines: {node: '>= 10.4.0'} + + '@zxing/text-encoding@0.9.0': + resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==} + + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} + engines: {node: '>=0.4.0'} + + acorn@8.17.0: + resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + alien-signals@1.0.13: + resolution: {integrity: sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.15.0: + resolution: {integrity: sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==} + + axios@1.18.0: + resolution: {integrity: sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + birpc@2.9.0: + resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==} + + body-parser@2.3.0: + resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} + engines: {node: '>=18'} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.16: + resolution: {integrity: sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==} + + brace-expansion@2.1.2: + resolution: {integrity: sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==} + + brace-expansion@5.0.8: + resolution: {integrity: sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==} + engines: {node: 20 || >=22} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browser-image-compression@2.0.2: + resolution: {integrity: sha512-pBLlQyUf6yB8SmmngrcOw3EoS4RpQ1BcylI3T9Yqn7+4nrQTXJD4sJDe5ODnJdrvNMaio5OicFo75rDyJD2Ucw==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + confbox@0.2.4: + resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} + + content-disposition@1.1.0: + resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} + engines: {node: '>=18'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + content-type@2.0.0: + resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} + engines: {node: '>=18'} + + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + copy-anything@2.0.6: + resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + + copy-anything@3.0.5: + resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} + engines: {node: '>=12.13'} + + copy-anything@4.0.5: + resolution: {integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==} + engines: {node: '>=18'} + + cors@2.8.6: + resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} + engines: {node: '>= 0.10'} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + dayjs@1.11.21: + resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} + + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + diff@4.0.4: + resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} + engines: {node: '>=0.3.1'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + echarts@6.1.0: + resolution: {integrity: sha512-q0yaFPggC9FUdsWH4blavRWFmxdrIodbkoKNAjJudAI6CA9gNPxHtV2RcZNEepZVlk4yvBYkOkbk6HIVpIyHZA==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + errno@0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + hasBin: true + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + eslint-plugin-vue@9.33.0: + resolution: {integrity: sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-scope@9.1.2: + resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@9.26.0: + resolution: {integrity: sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + espree@11.2.0: + resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + eventsource-parser@3.1.0: + resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} + engines: {node: '>=18.0.0'} + + eventsource@3.0.7: + resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} + engines: {node: '>=18.0.0'} + + express-rate-limit@8.6.0: + resolution: {integrity: sha512-XKJXDsASUOo0LLtFwW5hCcQGH0N4WQc/Rn8/Pvoia+TJFOkkFPvrtW9lZOeeNcxQJspvOIERMwiRLsVFlhHEkA==} + engines: {node: '>= 16'} + peerDependencies: + express: '>= 4.11' + + express@5.2.1: + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} + engines: {node: '>= 18'} + + exsolve@1.1.0: + resolution: {integrity: sha512-D+42+T12DdIlJM3uepa55qGiL3sYdLBOxIl2ifQCzCHz4c7eiolaHsi3BIqEr7JxBzxv2pYZQX9kw16ziMcEmw==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-uri@3.1.4: + resolution: {integrity: sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@2.1.1: + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.4.3: + resolution: {integrity: sha512-/zipXxyO6rGvuNGDiULY9MvEGSkb2gaG4GGH4ygMi0ZZzyMHdUZBmntJmx5x1G2VuPytCwGN4xsJP6cw+sK+vQ==} + + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} + engines: {node: '>= 6'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + hono@4.12.32: + resolution: {integrity: sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg==} + engines: {node: '>=16.9.0'} + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.7.3: + resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} + engines: {node: '>=0.10.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.6: + resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} + engines: {node: '>= 4'} + + image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ip-address@10.3.1: + resolution: {integrity: sha512-1e9d3kb97NHJTIJDZW9rKqW2h6+dFa50Dy0fpPSMQp2ADje5gvKsXmdiK6dwY5t76TaTt5+P5N1Y/LoToIxP6g==} + engines: {node: '>= 12'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + + is-what@3.14.1: + resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} + + is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + + is-what@5.5.0: + resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==} + engines: {node: '>=18'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jose@6.2.4: + resolution: {integrity: sha512-N8acGzVsQy6M/fjFcxtysNc4Q379TcM5dM/qKkNtsHFji88yANnXTr7BLeP75iPnFwBfQzM/jg2BZ9+HZrHCZA==} + + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + + js-yaml@4.3.0: + resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-schema-typed@8.0.2: + resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + less@4.5.1: + resolution: {integrity: sha512-UKgI3/KON4u6ngSsnDADsUERqhZknsVZbnuzlRZXLQCmfC/MDld42fTydUE9B+Mla1AL6SJ/Pp6SlEFi/AVGfw==} + engines: {node: '>=14'} + hasBin: true + + less@4.8.0: + resolution: {integrity: sha512-7Y7DJBMbsW29UGjOG6NGvxQEx71AaDcrryBwYCMaFwn0kj8FkSueKN9r9WexVOetKEhXh38kL++WJncfkEpS+g==} + engines: {node: '>=18'} + hasBin: true + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + local-pkg@1.2.1: + resolution: {integrity: sha512-++gUqRDEvcnN6Zhqrr+y/CkVEHhlrR96vZn3nZZPYzMcBUyBtTKzB9NadClFIsIVSsu+3i9tfk/erqy9kAmt7Q==} + engines: {node: '>=14'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash-es@4.18.1: + resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + make-dir@2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + + make-dir@5.1.0: + resolution: {integrity: sha512-IfpFq6UM39dUNiphpA6uDezNx/AvWyhwfICWPR3t1VspkgkMZrL+Rk1RbN1bx+aeNYwOrqGJgEgV3yotk+ZUVw==} + engines: {node: '>=18'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + marked-gfm-heading-id@4.1.4: + resolution: {integrity: sha512-CspnvVfHSkb/znqdPS4jUR8HtCjq3M/DnrsJCrfLBLvdrgbemmoINKpeWKQYkBiXAoBGejw0cV7xzqrPdup3WA==} + peerDependencies: + marked: '>=13 <19' + + marked-highlight@2.2.4: + resolution: {integrity: sha512-PZxisNMJDduSjc0q6uvjsnqqHCXc9s0eyzxDO9sB1eNGJnd/H1/Fu+z6g/liC1dfJdFW4SftMwMlLvsBhUPrqQ==} + peerDependencies: + marked: '>=4 <19' + + marked-mangle@1.1.13: + resolution: {integrity: sha512-phz1W/nYMr1T08Q7wqH2aj+PPiK85E69WQGfId+prvryfgjY/Idibx4YUvKaYMDV9rK1qo+/yC+Quu/3gdaBeA==} + peerDependencies: + marked: '>=4 <19' + + marked@17.0.6: + resolution: {integrity: sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA==} + engines: {node: '>= 20'} + hasBin: true + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + media-typer@1.1.1: + resolution: {integrity: sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==} + engines: {node: '>= 0.8'} + + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + + mitt@2.1.0: + resolution: {integrity: sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + nanoid@3.3.16: + resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + needle@2.9.1: + resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==} + engines: {node: '>= 4.4.x'} + hasBin: true + + needle@3.5.0: + resolution: {integrity: sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==} + engines: {node: '>= 4.4.x'} + hasBin: true + + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-node-version@1.0.1: + resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} + engines: {node: '>= 0.10'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-to-regexp@8.4.2: + resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pinia@3.0.4: + resolution: {integrity: sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==} + peerDependencies: + typescript: '>=4.5.0' + vue: ^3.5.11 + peerDependenciesMeta: + typescript: + optional: true + + pkce-challenge@5.0.1: + resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} + engines: {node: '>=16.20.0'} + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + pkg-types@2.3.1: + resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==} + + postcss-selector-parser@6.1.4: + resolution: {integrity: sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==} + engines: {node: '>=4'} + + postcss@8.5.23: + resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + + probe-image-size@7.3.0: + resolution: {integrity: sha512-7CaDeBwiAbh6ohXsvLbAZhO7wzsZAmaevfxe39qvCwRh8LyaZfDlBGGLU1CCTgrTLtCOdwBBhjOrIHaIIimHfQ==} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} + + prr@1.0.1: + resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.15.3: + resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} + engines: {node: '>=0.6'} + + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + range-parser@1.3.0: + resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==} + engines: {node: '>= 0.6'} + + raw-body@3.0.2: + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} + engines: {node: '>= 0.10'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rollup@4.62.3: + resolution: {integrity: sha512-Gu0c0iH9FzgX1L1t7ByIbbS3Vmdz+6KHm/EsqmmC71gUQ82yvZRkTK6XzrFObSka91WUVdynqp6nsfilzr5k6Q==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sax@1.6.1: + resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==} + engines: {node: '>=11.0.0'} + + scule@1.3.0: + resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + send@1.2.1: + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} + engines: {node: '>= 18'} + + serve-static@2.2.1: + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} + engines: {node: '>= 18'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} + engines: {node: '>= 0.4'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + speakingurl@14.0.1: + resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} + engines: {node: '>=0.10.0'} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + stream-parser@0.3.1: + resolution: {integrity: sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + + superjson@2.2.6: + resolution: {integrity: sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==} + engines: {node: '>=16'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + tdesign-icons-vue-next@0.4.7: + resolution: {integrity: sha512-0TRVH0L9O7vAMQ7j2vU/VYBMzS5FI+OVf7bWjwAVMmWXArsAyJI8mzpNWThZok96B6hsRY+2hK/NSOFZy8hMqA==} + peerDependencies: + vue: ^3.0.0 + + tdesign-mobile-vue@1.16.0: + resolution: {integrity: sha512-Msn9PRrOkJD22hGFqSS3l0gvoaXTB2a5CTyvzazzPTITJmkY4CnC7ySbOsGxlA2qT/HyL44v+JJYauzUycQ1Fg==} + engines: {node: '>=12.0.0'} + peerDependencies: + vue: ^3.2.6 + + terser@5.49.0: + resolution: {integrity: sha512-SNiDnXyHSrxVcIOtVbULzcTmniUiwcV7Nwdyj1twVubeTmbjoa8p69KKDpfkdoOavuM4/GRm1+ykI8qqnavHoA==} + engines: {node: '>=10'} + hasBin: true + + timi-tdesign-mobile@0.0.10: + resolution: {integrity: sha512-fv83++YkMkeKTkReR/2+RoaSacj6fv5JHJfJ1P3C4p/KmLn9XTe+3jHYlFEWjQdxbehz9BifX1L8rVHmgScP5g==} + engines: {node: '>=16.0.0'} + + timi-web@0.0.24: + resolution: {integrity: sha512-qzcm72W9EE3BrYiUzc8a20J8xqxH17moEm/ovdijhRbIJtJUr81sslXFe2+OjNtx14meEIPJm3IfRooFzRswLg==} + engines: {node: '>=16.0.0'} + + tinycolor2@1.6.0: + resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + ts-custom-error@3.3.1: + resolution: {integrity: sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A==} + engines: {node: '>=14.0.0'} + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + tslib@2.3.0: + resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-is@2.1.0: + resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} + engines: {node: '>= 18'} + + typescript-eslint@8.65.0: + resolution: {integrity: sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + unimport@4.2.0: + resolution: {integrity: sha512-mYVtA0nmzrysnYnyb3ALMbByJ+Maosee2+WyE0puXl+Xm2bUwPorPaaeZt0ETfuroPOtG8jj1g/qeFZ6buFnag==} + engines: {node: '>=18.12.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + unplugin-auto-import@19.3.0: + resolution: {integrity: sha512-iIi0u4Gq2uGkAOGqlPJOAMI8vocvjh1clGTfSK4SOrJKrt+tirrixo/FjgBwXQNNdS7ofcr7OxzmOb/RjWxeEQ==} + engines: {node: '>=14'} + peerDependencies: + '@nuxt/kit': ^3.2.2 + '@vueuse/core': '*' + peerDependenciesMeta: + '@nuxt/kit': + optional: true + '@vueuse/core': + optional: true + + unplugin-utils@0.2.5: + resolution: {integrity: sha512-gwXJnPRewT4rT7sBi/IvxKTjsms7jX7QIDLOClApuZwR49SXbrB1z2NLUZ+vDHyqCj/n58OzRRqaW+B8OZi8vg==} + engines: {node: '>=18.12.0'} + + unplugin-vue-components@28.8.0: + resolution: {integrity: sha512-2Q6ZongpoQzuXDK0ZsVzMoshH0MWZQ1pzVL538G7oIDKRTVzHjppBDS8aB99SADGHN3lpGU7frraCG6yWNoL5Q==} + engines: {node: '>=14'} + peerDependencies: + '@babel/parser': ^7.15.8 + '@nuxt/kit': ^3.2.2 || ^4.0.0 + vue: 2 || 3 + peerDependenciesMeta: + '@babel/parser': + optional: true + '@nuxt/kit': + optional: true + + unplugin@2.3.11: + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.0'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + uzip@0.20201231.0: + resolution: {integrity: sha512-OZeJfZP+R0z9D6TmBgLq2LHzSSptGMGDGigGiEe0pr8UBe/7fdflgHlHBNDASTXB5jnFuxHpNaJywSg8YFeGng==} + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + validator@13.15.35: + resolution: {integrity: sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==} + engines: {node: '>= 0.10'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vite@6.4.3: + resolution: {integrity: sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-echarts@8.0.1: + resolution: {integrity: sha512-23rJTFLu1OUEGRWjJGmdGt8fP+8+ja1gVgzMYPIPaHWpXegcO1viIAaeu2H4QHESlVeHzUAHIxKXGrwjsyXAaA==} + peerDependencies: + echarts: ^6.0.0 + vue: ^3.3.0 + + vue-eslint-parser@10.4.1: + resolution: {integrity: sha512-Gk6gRDj0n/fkRa3C3l0bBheoBckUq/Rs0F/TvMWIS6nzzx67amAViMe9CkNgsP2tXyQONvGiHQESHwFtZ3aYDA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + + vue-eslint-parser@9.4.3: + resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + + vue-observe-visibility@2.0.0-alpha.1: + resolution: {integrity: sha512-flFbp/gs9pZniXR6fans8smv1kDScJ8RS7rEpMjhVabiKeq7Qz3D9+eGsypncjfIyyU84saU88XZ0zjbD6Gq/g==} + peerDependencies: + vue: ^3.0.0 + + vue-resize@2.0.0-alpha.1: + resolution: {integrity: sha512-7+iqOueLU7uc9NrMfrzbG8hwMqchfVfSzpVlCMeJQe4pyibqyoifDNbKTZvwxZKDvGkB+PdFeKvnGZMoEb8esg==} + peerDependencies: + vue: ^3.0.0 + + vue-router@4.5.0: + resolution: {integrity: sha512-HDuk+PuH5monfNuY+ct49mNmkCRK4xJAV9Ts4z9UFc4rzdDnxQLyCMGGc8pKhZhHTVzfanpNwB/lwqevcBwI4w==} + peerDependencies: + vue: ^3.2.0 + + vue-router@4.5.1: + resolution: {integrity: sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==} + peerDependencies: + vue: ^3.2.0 + + vue-tsc@2.2.12: + resolution: {integrity: sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==} + hasBin: true + peerDependencies: + typescript: '>=5.0.0' + + vue-virtual-scroller@2.0.0-beta.8: + resolution: {integrity: sha512-b8/f5NQ5nIEBRTNi6GcPItE4s7kxNHw2AIHLtDp+2QvqdTjVN0FgONwX9cr53jWRgnu+HRLPaWDOR2JPI5MTfQ==} + peerDependencies: + vue: ^3.2.0 + + vue@3.5.40: + resolution: {integrity: sha512-+8PJ4SJXdn/cHGImF4CKdxlWHIN5Dkt7DoufRREM6h6uVCx2m7QxgcEQmmzyOK8A9mcafg7sFbJFYsdFVubTig==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zod-to-json-schema@3.25.2: + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + peerDependencies: + zod: ^3.25.28 || ^4 + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zrender@6.1.0: + resolution: {integrity: sha512-oEGMDB6pOP2S6OwRR4PdVv610zrjnA3Bh+JnSG12fYJlBKjtNAoEb5fSUoCOOINlH96I2fU38/A2UpRKs67xYQ==} + +snapshots: + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/parser@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/runtime@7.29.7': {} + + '@babel/types@7.29.7': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-x64@0.25.12': + optional: true + + '@esbuild/openharmony-arm64@0.25.12': + optional: true + + '@esbuild/sunos-x64@0.25.12': + optional: true + + '@esbuild/win32-arm64@0.25.12': + optional: true + + '@esbuild/win32-ia32@0.25.12': + optional: true + + '@esbuild/win32-x64@0.25.12': + optional: true + + '@eslint-community/eslint-utils@4.10.1(eslint@9.26.0)': + dependencies: + eslint: 9.26.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.20.1': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.2.3': {} + + '@eslint/core@0.13.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.6': + dependencies: + ajv: 6.15.0 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.3.0 + minimatch: 3.1.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.26.0': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.2.8': + dependencies: + '@eslint/core': 0.13.0 + levn: 0.4.1 + + '@hono/node-server@1.19.15(hono@4.12.32)': + dependencies: + hono: 4.12.32 + + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 + + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 + + '@humanfs/types@0.15.0': {} + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/source-map@0.3.11': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@modelcontextprotocol/sdk@1.29.0(zod@3.25.76)': + dependencies: + '@hono/node-server': 1.19.15(hono@4.12.32) + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + content-type: 1.0.5 + cors: 2.8.6 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.1.0 + express: 5.2.1 + express-rate-limit: 8.6.0(express@5.2.1) + hono: 4.12.32 + jose: 6.2.4 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 3.25.76 + zod-to-json-schema: 3.25.2(zod@3.25.76) + transitivePeerDependencies: + - supports-color + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@rollup/rollup-android-arm-eabi@4.62.3': + optional: true + + '@rollup/rollup-android-arm64@4.62.3': + optional: true + + '@rollup/rollup-darwin-arm64@4.62.3': + optional: true + + '@rollup/rollup-darwin-x64@4.62.3': + optional: true + + '@rollup/rollup-freebsd-arm64@4.62.3': + optional: true + + '@rollup/rollup-freebsd-x64@4.62.3': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.62.3': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.62.3': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.62.3': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.62.3': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.62.3': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.62.3': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.62.3': + optional: true + + '@rollup/rollup-linux-x64-musl@4.62.3': + optional: true + + '@rollup/rollup-openbsd-x64@4.62.3': + optional: true + + '@rollup/rollup-openharmony-arm64@4.62.3': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.62.3': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.62.3': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.62.3': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.62.3': + optional: true + + '@tsconfig/node10@1.0.12': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@tsconfig/node20@20.1.9': {} + + '@types/esrecurse@4.3.1': {} + + '@types/estree@1.0.9': {} + + '@types/json-schema@7.0.15': {} + + '@types/node@24.13.3': + dependencies: + undici-types: 7.18.2 + + '@types/web-bluetooth@0.0.20': {} + + '@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.65.0(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.65.0 + '@typescript-eslint/type-utils': 8.65.0(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/utils': 8.65.0(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.65.0 + eslint: 9.26.0 + ignore: 7.0.6 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.65.0(eslint@9.26.0)(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.65.0 + '@typescript-eslint/types': 8.65.0 + '@typescript-eslint/typescript-estree': 8.65.0(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.65.0 + debug: 4.4.3 + eslint: 9.26.0 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.65.0(typescript@5.8.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.65.0(typescript@5.8.3) + '@typescript-eslint/types': 8.65.0 + debug: 4.4.3 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.65.0': + dependencies: + '@typescript-eslint/types': 8.65.0 + '@typescript-eslint/visitor-keys': 8.65.0 + + '@typescript-eslint/tsconfig-utils@8.65.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@typescript-eslint/type-utils@8.65.0(eslint@9.26.0)(typescript@5.8.3)': + dependencies: + '@typescript-eslint/types': 8.65.0 + '@typescript-eslint/typescript-estree': 8.65.0(typescript@5.8.3) + '@typescript-eslint/utils': 8.65.0(eslint@9.26.0)(typescript@5.8.3) + debug: 4.4.3 + eslint: 9.26.0 + ts-api-utils: 2.5.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.65.0': {} + + '@typescript-eslint/typescript-estree@8.65.0(typescript@5.8.3)': + dependencies: + '@typescript-eslint/project-service': 8.65.0(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.65.0(typescript@5.8.3) + '@typescript-eslint/types': 8.65.0 + '@typescript-eslint/visitor-keys': 8.65.0 + debug: 4.4.3 + minimatch: 10.2.5 + semver: 7.8.5 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.65.0(eslint@9.26.0)(typescript@5.8.3)': + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@9.26.0) + '@typescript-eslint/scope-manager': 8.65.0 + '@typescript-eslint/types': 8.65.0 + '@typescript-eslint/typescript-estree': 8.65.0(typescript@5.8.3) + eslint: 9.26.0 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.65.0': + dependencies: + '@typescript-eslint/types': 8.65.0 + eslint-visitor-keys: 5.0.1 + + '@use-gesture/core@10.3.1': {} + + '@use-gesture/vanilla@10.3.1': + dependencies: + '@use-gesture/core': 10.3.1 + + '@vitejs/plugin-vue@5.2.4(vite@6.4.3(@types/node@24.13.3)(less@4.8.0)(terser@5.49.0))(vue@3.5.40(typescript@5.8.3))': + dependencies: + vite: 6.4.3(@types/node@24.13.3)(less@4.8.0)(terser@5.49.0) + vue: 3.5.40(typescript@5.8.3) + + '@volar/language-core@2.4.15': + dependencies: + '@volar/source-map': 2.4.15 + + '@volar/source-map@2.4.15': {} + + '@volar/typescript@2.4.15': + dependencies: + '@volar/language-core': 2.4.15 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vue/compiler-core@3.5.40': + dependencies: + '@babel/parser': 7.29.7 + '@vue/shared': 3.5.40 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.40': + dependencies: + '@vue/compiler-core': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/compiler-sfc@3.5.40': + dependencies: + '@babel/parser': 7.29.7 + '@vue/compiler-core': 3.5.40 + '@vue/compiler-dom': 3.5.40 + '@vue/compiler-ssr': 3.5.40 + '@vue/shared': 3.5.40 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.23 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.40': + dependencies: + '@vue/compiler-dom': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/compiler-vue2@2.7.16': + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + + '@vue/devtools-api@6.6.4': {} + + '@vue/devtools-api@7.7.10': + dependencies: + '@vue/devtools-kit': 7.7.10 + + '@vue/devtools-kit@7.7.10': + dependencies: + '@vue/devtools-shared': 7.7.10 + birpc: 2.9.0 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.6 + + '@vue/devtools-shared@7.7.10': + dependencies: + rfdc: 1.4.1 + + '@vue/eslint-config-typescript@14.9.0(eslint-plugin-vue@9.33.0(eslint@9.26.0))(eslint@9.26.0)(typescript@5.8.3)': + dependencies: + '@typescript-eslint/utils': 8.65.0(eslint@9.26.0)(typescript@5.8.3) + eslint: 9.26.0 + eslint-plugin-vue: 9.33.0(eslint@9.26.0) + fast-glob: 3.3.3 + typescript-eslint: 8.65.0(eslint@9.26.0)(typescript@5.8.3) + vue-eslint-parser: 10.4.1(eslint@9.26.0) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@vue/language-core@2.2.12(typescript@5.8.3)': + dependencies: + '@volar/language-core': 2.4.15 + '@vue/compiler-dom': 3.5.40 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.40 + alien-signals: 1.0.13 + minimatch: 9.0.9 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 5.8.3 + + '@vue/reactivity@3.5.40': + dependencies: + '@vue/shared': 3.5.40 + + '@vue/runtime-core@3.5.40': + dependencies: + '@vue/reactivity': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/runtime-dom@3.5.40': + dependencies: + '@vue/reactivity': 3.5.40 + '@vue/runtime-core': 3.5.40 + '@vue/shared': 3.5.40 + csstype: 3.2.3 + + '@vue/server-renderer@3.5.40': + dependencies: + '@vue/compiler-ssr': 3.5.40 + '@vue/runtime-dom': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/shared@3.5.40': {} + + '@vue/tsconfig@0.7.0(typescript@5.8.3)(vue@3.5.40(typescript@5.8.3))': + optionalDependencies: + typescript: 5.8.3 + vue: 3.5.40(typescript@5.8.3) + + '@vueuse/core@10.7.0(vue@3.5.40(typescript@5.8.3))': + dependencies: + '@types/web-bluetooth': 0.0.20 + '@vueuse/metadata': 10.7.0 + '@vueuse/shared': 10.7.0(vue@3.5.40(typescript@5.8.3)) + vue-demi: 0.14.10(vue@3.5.40(typescript@5.8.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/metadata@10.7.0': {} + + '@vueuse/shared@10.7.0(vue@3.5.40(typescript@5.8.3))': + dependencies: + vue-demi: 0.14.10(vue@3.5.40(typescript@5.8.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@zxing/browser@0.1.5(@zxing/library@0.21.3)': + dependencies: + '@zxing/library': 0.21.3 + optionalDependencies: + '@zxing/text-encoding': 0.9.0 + + '@zxing/library@0.21.3': + dependencies: + ts-custom-error: 3.3.1 + optionalDependencies: + '@zxing/text-encoding': 0.9.0 + + '@zxing/text-encoding@0.9.0': + optional: true + + accepts@2.0.0: + dependencies: + mime-types: 3.0.2 + negotiator: 1.0.0 + + acorn-jsx@5.3.2(acorn@8.17.0): + dependencies: + acorn: 8.17.0 + + acorn-walk@8.3.5: + dependencies: + acorn: 8.17.0 + + acorn@8.17.0: {} + + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + ajv-formats@3.0.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.4 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + alien-signals@1.0.13: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.2 + + arg@4.1.3: {} + + argparse@2.0.1: {} + + asynckit@0.4.0: {} + + axios@1.15.0: + dependencies: + follow-redirects: 1.16.0 + form-data: 4.0.6 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + + axios@1.18.0: + dependencies: + follow-redirects: 1.16.0 + form-data: 4.0.6 + https-proxy-agent: 5.0.1 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + - supports-color + + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + + binary-extensions@2.3.0: {} + + birpc@2.9.0: {} + + body-parser@2.3.0: + dependencies: + bytes: 3.1.2 + content-type: 2.0.0 + debug: 4.4.3 + http-errors: 2.0.1 + iconv-lite: 0.7.3 + on-finished: 2.4.1 + qs: 6.15.3 + raw-body: 3.0.2 + type-is: 2.1.0 + transitivePeerDependencies: + - supports-color + + boolbase@1.0.0: {} + + brace-expansion@1.1.16: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.1.2: + dependencies: + balanced-match: 1.0.2 + + brace-expansion@5.0.8: + dependencies: + balanced-match: 4.0.4 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browser-image-compression@2.0.2: + dependencies: + uzip: 0.20201231.0 + + buffer-from@1.1.2: {} + + bytes@3.1.2: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@2.20.3: {} + + concat-map@0.0.1: {} + + confbox@0.1.8: {} + + confbox@0.2.4: {} + + content-disposition@1.1.0: {} + + content-type@1.0.5: {} + + content-type@2.0.0: {} + + cookie-signature@1.2.2: {} + + cookie@0.7.2: {} + + copy-anything@2.0.6: + dependencies: + is-what: 3.14.1 + + copy-anything@3.0.5: + dependencies: + is-what: 4.1.16 + + copy-anything@4.0.5: + dependencies: + is-what: 5.5.0 + + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + create-require@1.1.1: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cssesc@3.0.0: {} + + csstype@3.2.3: {} + + dayjs@1.11.21: {} + + de-indent@1.0.2: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + optional: true + + debug@3.2.7: + dependencies: + ms: 2.1.3 + optional: true + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + delayed-stream@1.0.0: {} + + depd@2.0.0: {} + + diff@4.0.4: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + echarts@6.1.0: + dependencies: + tslib: 2.3.0 + zrender: 6.1.0 + + ee-first@1.1.1: {} + + encodeurl@2.0.0: {} + + entities@7.0.1: {} + + errno@0.1.8: + dependencies: + prr: 1.0.1 + optional: true + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + + escape-html@1.0.3: {} + + escape-string-regexp@4.0.0: {} + + escape-string-regexp@5.0.0: {} + + eslint-plugin-vue@9.33.0(eslint@9.26.0): + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@9.26.0) + eslint: 9.26.0 + globals: 13.24.0 + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 6.1.4 + semver: 7.8.5 + vue-eslint-parser: 9.4.3(eslint@9.26.0) + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - supports-color + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-scope@9.1.2: + dependencies: + '@types/esrecurse': 4.3.1 + '@types/estree': 1.0.9 + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint-visitor-keys@5.0.1: {} + + eslint@9.26.0: + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@9.26.0) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.20.1 + '@eslint/config-helpers': 0.2.3 + '@eslint/core': 0.13.0 + '@eslint/eslintrc': 3.3.6 + '@eslint/js': 9.26.0 + '@eslint/plugin-kit': 0.2.8 + '@humanfs/node': 0.16.8 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@modelcontextprotocol/sdk': 1.29.0(zod@3.25.76) + '@types/estree': 1.0.9 + '@types/json-schema': 7.0.15 + ajv: 6.15.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.5 + natural-compare: 1.4.0 + optionator: 0.9.4 + zod: 3.25.76 + transitivePeerDependencies: + - '@cfworker/json-schema' + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.17.0 + acorn-jsx: 5.3.2(acorn@8.17.0) + eslint-visitor-keys: 4.2.1 + + espree@11.2.0: + dependencies: + acorn: 8.17.0 + acorn-jsx: 5.3.2(acorn@8.17.0) + eslint-visitor-keys: 5.0.1 + + espree@9.6.1: + dependencies: + acorn: 8.17.0 + acorn-jsx: 5.3.2(acorn@8.17.0) + eslint-visitor-keys: 3.4.3 + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + esutils@2.0.3: {} + + etag@1.8.1: {} + + eventsource-parser@3.1.0: {} + + eventsource@3.0.7: + dependencies: + eventsource-parser: 3.1.0 + + express-rate-limit@8.6.0(express@5.2.1): + dependencies: + debug: 4.4.3 + express: 5.2.1 + ip-address: 10.3.1 + transitivePeerDependencies: + - supports-color + + express@5.2.1: + dependencies: + accepts: 2.0.0 + body-parser: 2.3.0 + content-disposition: 1.1.0 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.3 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.1 + fresh: 2.0.0 + http-errors: 2.0.1 + merge-descriptors: 2.0.0 + mime-types: 3.0.2 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.15.3 + range-parser: 1.3.0 + router: 2.2.0 + send: 1.2.1 + serve-static: 2.2.1 + statuses: 2.0.2 + type-is: 2.1.0 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + exsolve@1.1.0: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-uri@3.1.4: {} + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@2.1.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.4.3 + keyv: 4.5.4 + + flatted@3.4.3: {} + + follow-redirects@1.16.0: {} + + form-data@4.0.6: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.4 + mime-types: 2.1.35 + + forwarded@0.2.0: {} + + fresh@2.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + github-slugger@2.0.0: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globals@14.0.0: {} + + gopd@1.2.0: {} + + graceful-fs@4.2.11: + optional: true + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + hono@4.12.32: {} + + hookable@5.5.3: {} + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + optional: true + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + optional: true + + iconv-lite@0.7.3: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + ignore@7.0.6: {} + + image-size@0.5.5: + optional: true + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + inherits@2.0.4: {} + + ip-address@10.3.1: {} + + ipaddr.js@1.9.1: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-promise@4.0.0: {} + + is-what@3.14.1: {} + + is-what@4.1.16: {} + + is-what@5.5.0: {} + + isexe@2.0.0: {} + + jose@6.2.4: {} + + js-tokens@9.0.1: {} + + js-yaml@4.3.0: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-schema-typed@8.0.2: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + less@4.5.1: + dependencies: + copy-anything: 2.0.6 + parse-node-version: 1.0.1 + tslib: 2.8.1 + optionalDependencies: + errno: 0.1.8 + graceful-fs: 4.2.11 + image-size: 0.5.5 + make-dir: 2.1.0 + mime: 1.6.0 + needle: 3.5.0 + source-map: 0.6.1 + + less@4.8.0: + dependencies: + copy-anything: 3.0.5 + parse-node-version: 1.0.1 + optionalDependencies: + errno: 0.1.8 + graceful-fs: 4.2.11 + make-dir: 5.1.0 + mime: 1.6.0 + needle: 3.5.0 + probe-image-size: 7.3.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + local-pkg@1.2.1: + dependencies: + mlly: 1.8.2 + pkg-types: 2.3.1 + quansync: 0.2.11 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash-es@4.18.1: {} + + lodash.merge@4.6.2: {} + + lodash@4.18.1: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + make-dir@2.1.0: + dependencies: + pify: 4.0.1 + semver: 5.7.2 + optional: true + + make-dir@5.1.0: + optional: true + + make-error@1.3.6: {} + + marked-gfm-heading-id@4.1.4(marked@17.0.6): + dependencies: + github-slugger: 2.0.0 + marked: 17.0.6 + + marked-highlight@2.2.4(marked@17.0.6): + dependencies: + marked: 17.0.6 + + marked-mangle@1.1.13(marked@17.0.6): + dependencies: + marked: 17.0.6 + + marked@17.0.6: {} + + math-intrinsics@1.1.0: {} + + media-typer@1.1.1: {} + + merge-descriptors@2.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + + mime@1.6.0: + optional: true + + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.8 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.16 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.1.2 + + mitt@2.1.0: {} + + mitt@3.0.1: {} + + mlly@1.8.2: + dependencies: + acorn: 8.17.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.4 + + ms@2.0.0: + optional: true + + ms@2.1.3: {} + + muggle-string@0.4.1: {} + + nanoid@3.3.16: {} + + natural-compare@1.4.0: {} + + needle@2.9.1: + dependencies: + debug: 3.2.7 + iconv-lite: 0.4.24 + sax: 1.6.1 + transitivePeerDependencies: + - supports-color + optional: true + + needle@3.5.0: + dependencies: + iconv-lite: 0.6.3 + sax: 1.6.1 + optional: true + + negotiator@1.0.0: {} + + normalize-path@3.0.0: {} + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-node-version@1.0.1: {} + + parseurl@1.3.3: {} + + path-browserify@1.0.1: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-to-regexp@8.4.2: {} + + pathe@2.0.3: {} + + perfect-debounce@1.0.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.5: {} + + pify@4.0.1: + optional: true + + pinia@3.0.4(typescript@5.8.3)(vue@3.5.40(typescript@5.8.3)): + dependencies: + '@vue/devtools-api': 7.7.10 + vue: 3.5.40(typescript@5.8.3) + optionalDependencies: + typescript: 5.8.3 + + pkce-challenge@5.0.1: {} + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.2 + pathe: 2.0.3 + + pkg-types@2.3.1: + dependencies: + confbox: 0.2.4 + exsolve: 1.1.0 + pathe: 2.0.3 + + postcss-selector-parser@6.1.4: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss@8.5.23: + dependencies: + nanoid: 3.3.16 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + prismjs@1.30.0: {} + + probe-image-size@7.3.0: + dependencies: + lodash.merge: 4.6.2 + needle: 2.9.1 + stream-parser: 0.3.1 + transitivePeerDependencies: + - supports-color + optional: true + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-from-env@2.1.0: {} + + prr@1.0.1: + optional: true + + punycode@2.3.1: {} + + qs@6.15.3: + dependencies: + es-define-property: 1.0.1 + side-channel: 1.1.1 + + quansync@0.2.11: {} + + queue-microtask@1.2.3: {} + + range-parser@1.3.0: {} + + raw-body@3.0.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.7.3 + unpipe: 1.0.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.2 + + require-from-string@2.0.2: {} + + resolve-from@4.0.0: {} + + reusify@1.1.0: {} + + rfdc@1.4.1: {} + + rollup@4.62.3: + dependencies: + '@types/estree': 1.0.9 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.62.3 + '@rollup/rollup-android-arm64': 4.62.3 + '@rollup/rollup-darwin-arm64': 4.62.3 + '@rollup/rollup-darwin-x64': 4.62.3 + '@rollup/rollup-freebsd-arm64': 4.62.3 + '@rollup/rollup-freebsd-x64': 4.62.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.3 + '@rollup/rollup-linux-arm-musleabihf': 4.62.3 + '@rollup/rollup-linux-arm64-gnu': 4.62.3 + '@rollup/rollup-linux-arm64-musl': 4.62.3 + '@rollup/rollup-linux-loong64-gnu': 4.62.3 + '@rollup/rollup-linux-loong64-musl': 4.62.3 + '@rollup/rollup-linux-ppc64-gnu': 4.62.3 + '@rollup/rollup-linux-ppc64-musl': 4.62.3 + '@rollup/rollup-linux-riscv64-gnu': 4.62.3 + '@rollup/rollup-linux-riscv64-musl': 4.62.3 + '@rollup/rollup-linux-s390x-gnu': 4.62.3 + '@rollup/rollup-linux-x64-gnu': 4.62.3 + '@rollup/rollup-linux-x64-musl': 4.62.3 + '@rollup/rollup-openbsd-x64': 4.62.3 + '@rollup/rollup-openharmony-arm64': 4.62.3 + '@rollup/rollup-win32-arm64-msvc': 4.62.3 + '@rollup/rollup-win32-ia32-msvc': 4.62.3 + '@rollup/rollup-win32-x64-gnu': 4.62.3 + '@rollup/rollup-win32-x64-msvc': 4.62.3 + fsevents: 2.3.3 + + router@2.2.0: + dependencies: + debug: 4.4.3 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.4.2 + transitivePeerDependencies: + - supports-color + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safer-buffer@2.1.2: {} + + sax@1.6.1: + optional: true + + scule@1.3.0: {} + + semver@5.7.2: + optional: true + + semver@7.8.5: {} + + send@1.2.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.1 + mime-types: 3.0.2 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.3.0 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serve-static@2.2.1: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.1 + transitivePeerDependencies: + - supports-color + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + source-map-js@1.2.1: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + speakingurl@14.0.1: {} + + statuses@2.0.2: {} + + stream-parser@0.3.1: + dependencies: + debug: 2.6.9 + transitivePeerDependencies: + - supports-color + optional: true + + strip-json-comments@3.1.1: {} + + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 + + superjson@2.2.6: + dependencies: + copy-anything: 4.0.5 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + tdesign-icons-vue-next@0.4.7(vue@3.5.40(typescript@5.8.3)): + dependencies: + '@babel/runtime': 7.29.7 + vue: 3.5.40(typescript@5.8.3) + + tdesign-mobile-vue@1.16.0(vue@3.5.40(typescript@5.8.3)): + dependencies: + '@babel/runtime': 7.29.7 + '@use-gesture/vanilla': 10.3.1 + '@vueuse/core': 10.7.0(vue@3.5.40(typescript@5.8.3)) + dayjs: 1.11.21 + lodash-es: 4.18.1 + tdesign-icons-vue-next: 0.4.7(vue@3.5.40(typescript@5.8.3)) + tinycolor2: 1.6.0 + validator: 13.15.35 + vue: 3.5.40(typescript@5.8.3) + transitivePeerDependencies: + - '@vue/composition-api' + + terser@5.49.0: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.17.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + timi-tdesign-mobile@0.0.10(typescript@5.8.3): + dependencies: + vue: 3.5.40(typescript@5.8.3) + vue-router: 4.5.0(vue@3.5.40(typescript@5.8.3)) + transitivePeerDependencies: + - typescript + + timi-web@0.0.24(typescript@5.8.3)(vue@3.5.40(typescript@5.8.3)): + dependencies: + axios: 1.18.0 + less: 4.5.1 + marked: 17.0.6 + marked-gfm-heading-id: 4.1.4(marked@17.0.6) + marked-highlight: 2.2.4(marked@17.0.6) + marked-mangle: 1.1.13(marked@17.0.6) + pinia: 3.0.4(typescript@5.8.3)(vue@3.5.40(typescript@5.8.3)) + prismjs: 1.30.0 + terser: 5.49.0 + transitivePeerDependencies: + - debug + - supports-color + - typescript + - vue + + tinycolor2@1.6.0: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + ts-api-utils@2.5.0(typescript@5.8.3): + dependencies: + typescript: 5.8.3 + + ts-custom-error@3.3.1: {} + + ts-node@10.9.2(@types/node@24.13.3)(typescript@5.8.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.12 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 24.13.3 + acorn: 8.17.0 + acorn-walk: 8.3.5 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.4 + make-error: 1.3.6 + typescript: 5.8.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + tslib@2.3.0: {} + + tslib@2.8.1: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.20.2: {} + + type-is@2.1.0: + dependencies: + content-type: 2.0.0 + media-typer: 1.1.1 + mime-types: 3.0.2 + + typescript-eslint@8.65.0(eslint@9.26.0)(typescript@5.8.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.65.0(@typescript-eslint/parser@8.65.0(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/parser': 8.65.0(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.65.0(typescript@5.8.3) + '@typescript-eslint/utils': 8.65.0(eslint@9.26.0)(typescript@5.8.3) + eslint: 9.26.0 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + typescript@5.8.3: {} + + ufo@1.6.4: {} + + undici-types@7.18.2: {} + + unimport@4.2.0: + dependencies: + acorn: 8.17.0 + escape-string-regexp: 5.0.0 + estree-walker: 3.0.3 + local-pkg: 1.2.1 + magic-string: 0.30.21 + mlly: 1.8.2 + pathe: 2.0.3 + picomatch: 4.0.5 + pkg-types: 2.3.1 + scule: 1.3.0 + strip-literal: 3.1.0 + tinyglobby: 0.2.17 + unplugin: 2.3.11 + unplugin-utils: 0.2.5 + + unpipe@1.0.0: {} + + unplugin-auto-import@19.3.0(@vueuse/core@10.7.0(vue@3.5.40(typescript@5.8.3))): + dependencies: + local-pkg: 1.2.1 + magic-string: 0.30.21 + picomatch: 4.0.5 + unimport: 4.2.0 + unplugin: 2.3.11 + unplugin-utils: 0.2.5 + optionalDependencies: + '@vueuse/core': 10.7.0(vue@3.5.40(typescript@5.8.3)) + + unplugin-utils@0.2.5: + dependencies: + pathe: 2.0.3 + picomatch: 4.0.5 + + unplugin-vue-components@28.8.0(@babel/parser@7.29.7)(vue@3.5.40(typescript@5.8.3)): + dependencies: + chokidar: 3.6.0 + debug: 4.4.3 + local-pkg: 1.2.1 + magic-string: 0.30.21 + mlly: 1.8.2 + tinyglobby: 0.2.17 + unplugin: 2.3.11 + unplugin-utils: 0.2.5 + vue: 3.5.40(typescript@5.8.3) + optionalDependencies: + '@babel/parser': 7.29.7 + transitivePeerDependencies: + - supports-color + + unplugin@2.3.11: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.17.0 + picomatch: 4.0.5 + webpack-virtual-modules: 0.6.2 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + uzip@0.20201231.0: {} + + v8-compile-cache-lib@3.0.1: {} + + validator@13.15.35: {} + + vary@1.1.2: {} + + vite@6.4.3(@types/node@24.13.3)(less@4.8.0)(terser@5.49.0): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + postcss: 8.5.23 + rollup: 4.62.3 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 24.13.3 + fsevents: 2.3.3 + less: 4.8.0 + terser: 5.49.0 + + vscode-uri@3.1.0: {} + + vue-demi@0.14.10(vue@3.5.40(typescript@5.8.3)): + dependencies: + vue: 3.5.40(typescript@5.8.3) + + vue-echarts@8.0.1(echarts@6.1.0)(vue@3.5.40(typescript@5.8.3)): + dependencies: + echarts: 6.1.0 + vue: 3.5.40(typescript@5.8.3) + + vue-eslint-parser@10.4.1(eslint@9.26.0): + dependencies: + debug: 4.4.3 + eslint: 9.26.0 + eslint-scope: 9.1.2 + eslint-visitor-keys: 5.0.1 + espree: 11.2.0 + esquery: 1.7.0 + semver: 7.8.5 + transitivePeerDependencies: + - supports-color + + vue-eslint-parser@9.4.3(eslint@9.26.0): + dependencies: + debug: 4.4.3 + eslint: 9.26.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.7.0 + lodash: 4.18.1 + semver: 7.8.5 + transitivePeerDependencies: + - supports-color + + vue-observe-visibility@2.0.0-alpha.1(vue@3.5.40(typescript@5.8.3)): + dependencies: + vue: 3.5.40(typescript@5.8.3) + + vue-resize@2.0.0-alpha.1(vue@3.5.40(typescript@5.8.3)): + dependencies: + vue: 3.5.40(typescript@5.8.3) + + vue-router@4.5.0(vue@3.5.40(typescript@5.8.3)): + dependencies: + '@vue/devtools-api': 6.6.4 + vue: 3.5.40(typescript@5.8.3) + + vue-router@4.5.1(vue@3.5.40(typescript@5.8.3)): + dependencies: + '@vue/devtools-api': 6.6.4 + vue: 3.5.40(typescript@5.8.3) + + vue-tsc@2.2.12(typescript@5.8.3): + dependencies: + '@volar/typescript': 2.4.15 + '@vue/language-core': 2.2.12(typescript@5.8.3) + typescript: 5.8.3 + + vue-virtual-scroller@2.0.0-beta.8(vue@3.5.40(typescript@5.8.3)): + dependencies: + mitt: 2.1.0 + vue: 3.5.40(typescript@5.8.3) + vue-observe-visibility: 2.0.0-alpha.1(vue@3.5.40(typescript@5.8.3)) + vue-resize: 2.0.0-alpha.1(vue@3.5.40(typescript@5.8.3)) + + vue@3.5.40(typescript@5.8.3): + dependencies: + '@vue/compiler-dom': 3.5.40 + '@vue/compiler-sfc': 3.5.40 + '@vue/runtime-dom': 3.5.40 + '@vue/server-renderer': 3.5.40 + '@vue/shared': 3.5.40 + optionalDependencies: + typescript: 5.8.3 + + webpack-virtual-modules@0.6.2: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + wrappy@1.0.2: {} + + xml-name-validator@4.0.0: {} + + yn@3.1.1: {} + + yocto-queue@0.1.0: {} + + zod-to-json-schema@3.25.2(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod@3.25.76: {} + + zrender@6.1.0: + dependencies: + tslib: 2.3.0 diff --git a/public/icons/icon-192.png b/public/icons/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..76ecc995076aa6d0eb308d04b2f661a74ccf3ec9 GIT binary patch literal 2908 zcmcImdpy)>7k_@g3}a*pBdILSxJ466inNW}j7u0(?qS+e2(!6FuD{TImf9HGWL!ej zxK$HbWVTJ#Wyx*q3`tqHGEtdH5%1VP-@o2J-u>e|=Q)?pIp_I4pU*kxGS!WujM;<% z04O^-+S6p5ze;F%*-0A?SCBC%nntk&Rb5-AWrEyE8&?|u?q?}29Yx7x#UCAgqXEGF zzDiIlqx?7km=8|&HizQ_#hm@U#78O@gplRtIk*v+@Hf*@8TPdVyq%niJx(Q74OYN9 z=IzzFeT5knc4c_`8!F@6+o^VCw#uXt4})X*k0oM~QO8rS$?voVRHjfzvqcI-VlD~~FV zVgXiW&?J+Fj{7d+$-?_rbsFd3!@fkMZY-Bx!V*c+zD?%@6c78#VW{J4A=A5@HicJ> zDnn9J0wJxwO*5|4+ZMW)=K&w}jkYi*2l32qalOi`GT_6Or?7}elKxaYtzpC4V0T7U z0{OJwYdOB-1?+hxE2DK@N{H3Qcs)zMvzC}lN|^T==~;_ktX(1~1{t8VuTC-_a{LI9 zq;*i&W1Tje6hFMbkj{w zIOLtwSpS(QcYrrpnL837$qXlg7yX?ZJ%+j~RY?z%BfcCuCOi<)YSLNpWh{O+@bh4} z335V?Wi^U{c!X`vs@>A}*veC#+d5o0Y5KH z&6*J^VumZkp#D%mmD@reZJ>KpB#DX`;dHeBQMXFr&XlHC!t2s6Ya5HeF+=`w(YKZW zU6=Pd8mM0mHZ-IsQ=kvNQv&S*y2TdakkWg zNJV^x-GErb->C@HQW53Q)XOhbF?1!=Urb?Foh|ZkZUW1hKNzWpOq^1t6oD^~e*z0v zvW1Q?FDPx%Xtl~n0$8@{3=e}|eCY7jt4&RlsK?tu&xdW1o2A`W4j^Vh>b|qd4`vwh zfAL2nR~zx`={)Aw_NYH(&`fNAJGUnbEWg?%Ev$Gujjo~`h}={N$|u302fCiGqSpwx zC^9DoWo?_a|aeh6IpPCsqgn)f`0w{=Kp%w7u+Z%C9H(skwoQusn5Z#XEA* z*Q~6I;1)KC52)iP%HF@ux4Wcq?aBI%ye9Xa-oS@16$!v%Zqi!GC0XfVgnYkGw_mVdpgyDOZC zl&R&4l5#+4rT4PMM$4=S)Ld0-ZsxBv5EWFbKAO%LSsEcqY|2au%7FdvwQ#(CbL>r9 zNN}#fOkTIM6`9}VAxyy1eHR(2t{>E4dTNhNO$1Lpb_DtM{0L_9aDsSC`i=SeOR`Mk z9aW;MQI9~=z6~Y()1$)QJhc>Bp&zjz|7!Mt`Hai#u7v}C7WQE+t_%IZ5u9s@lFV6T zsYE_J!&o$}M52mgMq$woPJId-z;6znWi8Z8KjlZq=6c?*L;kcj0-(b zSjVHBu3gE_N4$lK(;wWeZUj@;KgN<_|oLPMte%<-}61tTalR4S^7u4 z6>ILDsg-LLq>T7Ib)4+pl{-!3lDB36@%ihlkA79_`41C%-bVa2YcHx4_CFRGTsx^W>T9uOpo2AUl^3fzbc+&NU^IByN)t-}ZZ*L#zl1{- z#l)R&bp_HAi;C9aTM8Ad#FJ0a^znm`HCK~KduPFTfbN?cM=?|f0#bHkYw^HelUI8FG0ibW#RHq)HP{%Q!~eNPmd|4wa`j5o zb9`E`E)Qe+md765TjRQ=ul)BgR`Pw55W8K2LS+m!I7Xq|#y7nydA^HTYUhLEce{u| zOytbw6#0(4y&Cb3=f^(vPl`|9PUdm<2kn#L6~DvK3P*0P^%A(HC^;ZIcWS)AW|o2v zH3g#j7EDdRj8d&uXc||xzTDL6d12Ykd5tYTCLd`Gwr={jwzq$2Dg5uS&yp4v)JIeI VT69G}Ta<0Yz{$bQzRH%K_8*`^3e*4q literal 0 HcmV?d00001 diff --git a/public/icons/icon-512.png b/public/icons/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..0ee7cce71733231cd39141be75acd2ce015e87bb GIT binary patch literal 10558 zcmeHNc|4SF*S}{ZB|j-klu(i-yJX4MlNusRDhAn?AF>X@SVn%8i43Z-WGiKogpn;- zD$8g@p_we9vG425V3>LD(egb1zW=?S&-?u0WA5uZ*E#3azpX^r}N3N zH{AG+OYFbNcQc;X$lw56(@5w{aLPHMeGlR#&KU074Y?&D(;=^_T)tMPV_eleb(uc* zLi-9eYbCONF*akZwrYkpXGbl5fiT<3WieRwYdpa7a}WS^Qvg)J=)XVyPl7PN(PQ1P zJZtA)w?4bY+QfL~M*moEi}?Vn-`w!&99$m}&xx9U=x@$kNJc{e)4Oq7Mf$AXa^hPm zW9TB&PEYOvi>l9xiooeblrVn`)vK)gAK~Bx*3t_(SnfHjFEjTYt*_ZjWqdr;uud(X zaEK0E_8B(f1}?gx)n1KJB&czYOvNhU(oFX#7$rLH>#t}+gCUUr;-NYZ19#yoyNv}slz{bZO z<}yb=1aepn@ze5v&xTkTz&wF2v-5dHJe`ps?(i2pvpRdfE0+KyX?t2z;=7Plx9#Dz z&hQ1Lm}nZEwb6OM#QKaW!zZO7dhuQPfx)%FDSGOb>`$@M%~I3qo`vR8^Iqn4^OG(- zhA;1ZR-HKN6v>IS0RBE|B7kC5P-9uDj$zc=`~AvzyKbiKvAgH&uUYK)mI^iChd%)# zmwNS?j3RM|%ptYFaoZ_98uf|3ozz`}O+8#Cgmj6`M(zMgl6Nx=&FNoI>0{{QVJ>gH z=^zNPwPH`c5JXiQil*Jg=qx&po0LSw1f7O06WBcbrkaYg3+Hau2mqOcR5{M!$YFoo zUB12){F-Myv!cyctl42iZeFVL-JIf2LFb2LTTYhQB?!3 z>f2mWZrl!R5s#aTFfw(2v>_59^z69L(sC9AyS?A@ih#=3SGY*pBc+Q>(K_#n$xbZ# zsPcw_aGxbx*Ygdc5eq7Hz56-%VKsuKf?bAt38()1~4REEiGUYh5jSVxTp{ z$CQKkrps2~Vb1t-dccX{&DsU2c}Dp^Q03}sabY6f>^m`$*lOiiZisy?4_K|txxxnX>NtHzK;xWI6>=UnM8ZfvuRlObfGW2>jjY2YTSO2M>HWjsAw*|2*+VlX$Pq*rt2@e zruE)|eok3)#gw;eHoiXiSoCyCAvyDeiLGeZNM6s;K=tD-@Y$#sQZdRs!gfiC$<&>_ zQz3vFr8o)D*C_i}u6jx<6zuRYPJr?)+?Z(!OH7X~YyAMH=uXOt_;IdQQXJXlhahBt zwz{AXGlh67L&34r5A|(pMOBZxGv=p++ z%w8-zVh-ol*2QssHn_@6G!nG6xd`d)5Th|h$m$xBkRp|0D}YLBl5;}3wRyY3@op0$ zRk}1Itn|>~inWUZdDZWOo8GXNY9^0>2upM3sUdlsY?lM_Iiq^8t4&oWiR>%)~DHPD_T+2L?Y`9Bw6eUz-Ikf%&KNwuk^Ud`0Q(1#9AkHGKSM2 zA|9%&$C-CF@KjCf3zUj&)%RwaLs;`0}LL%$|~H`l?{R zhc{B-x6(;-WvGjyFAE$Pw%f~Hk2e>`KKLWKm1gsv_T>tsd^9Edsy!1^7;YyWt#4IQ z0vPSJ1X^%FusqWMw4)4en*kn_-^(iV9_g7m0d$=eKrMm5_m7y;QVyTN>fno!Ad7xA ztCGWijRz2f1fUccsIblm=)rpEo*dQDi%hFJJC zd>+2sW9EZ7aeQHOY481#sDj_R@ksD$+DYf=D^vSC;X(em3i22$?EP@hOs?#2piVf1In)zy*?7jPS{{ z!`d&rrrB;z40bh;|JWy1hrXPE)BipfP`uLfpCs=@sbRzNHG`GH84V%x z7cp5+{(y75VA?mkFc5$T)pXz0TDRMqn7F_yEQua-U1+xYBja6D?<6VXAXlLWkNYk|9~77W@F)4A}6_h&J#^qE3`c+j9%-PT|&j)lKQ2_=pp z7oV@a5jKKbjyH`w!By70K$^4Mc(@x;l)X1F_DLLsR2iU5rjwL$nx2bsOHy-qVF~P{ z4mvU;`-*+jh~R$rpI*{L_G)8v=(*+}MLAL40;n_1W9`L=@Vz=FF4FZO>lvAx?_5=3 zki3JOP8N1a9Pz{<6~g?om@~G?Oh=4(h~r3=?GBlbU&oN2Mt+kOw?fzjPE45B7U`@% zel$p0%yTNRu%3!C;JQ1e+Pd%%loMNAC&27E!@7hW=tH-5@?mE0)i8YaFSPa0CsZ=> z0gHQ3<K?5oU+}$L>MbvX#1^|6Go5w#uS@TdoMcIe_s=P zOA@|3EUu@B5CGUa7UHV5L!104*<6+W6dD1?uTG%tb}U5?)SfFHeWxF3KQ04Y&IfoD z&(G#|Z{)?un%Hh$-!7V~c42ka?qG;NfqB;~QJ-E}Nqq;F6!T3ZK{2K`676;1_2GPi-};KtU1S?!6oEIM;}qHV}AX>EWLOZx>rI=8g(@bC(!ZD*WkA@I2fmV`r`kF!x#l8}Zv|;Q2+! zWFqu4Y&+--d_k!ogP(!wZ3SrO1FQSCgUaF&^p{+A`tB1zb;tlwhT8$tQvd{?hfGRt z2Up&y|L3BBgvfO&*{n9%e*I1iqh*vvGk_%5IrTXVZ;&u0ZyMo zlteOKGYAJb4Mvx?ZPQNs;8=&~iy8&<^l}&*YrtcDbx&t*=wYpVAYMm|6T}z=ucwk8 z;jY0tR_y^ff@tnxFz~{@4Q&zibr~~U;#r|-TCUPLcH?WaU|ctTs9)`)o7aAPTgKn1 zfQSrzejYOH%sv)z*W3rcp(n6fdZ)pVTulC^MdSN-1c{}FPY=1zHX(?=1a#r*Hy(B? zs>b}s*d-5wQd1Z!S`2UxUZ_e!g3J%j@D=8lg%BMme}`&6Ocncb1rb4 zieKyu$pQ1AJ5!S|l(4@vyWJ9Cqr#tqTyO4HENd9(N5_CSTU{jB9MIb$GS=TI#i*?7 z+DQLQa%=xsM{nHUCIq?M=b3orxj5Y!b85ZL=2seAOBWU#>IRjp8AP{Au{0k!W~L2B zj<^nCLViXr3Nz)^J5*>t-=x1nEzxDn^u`?H?XgRAj#u3mCy5)>5c`Es>ub$?X;~f7& zC(bb}dUxUv_z|LVtE{XDJ(ob8&hJV8dmcYipE~n&89GPAw8AxE7NFt zvWTt`!;wEtWRX?Q8bfD5cn^Zvct{Gg$t^90V{UqglSkvPlPOQxljZC3??)N%ksrgC z6Ont?{z!b>o*~UTJ1zcOVcw6{9bbjsI|q^Z*c-zbhzR(+$A5EeRmpI}EE0>;8(B4m z$Pjv2q3l-A3Yu;QNwx&5XONsdh&~g$B=Da2AEPb3EE;=MFLwyRX>cA5RTkpR6ZT{= zM!{Cog#SVfR3aa&+7qA_Mmh^ay{u?7UT~rI&mdt}Cu2cDB?K%7eu+8S!E~Ln?bQfu z9{ZZhnq6g~R}XVK$#Wa*W1n$2edm2C?qJpX1Q1vpAS&fBBhMLPVcP->DC zv=KnPYyKGg&;=Vu2;HXTkr&DjpTNXuZcUL02OPFu?U%q?3ZTkl0FI*S$h1KbrZ?5^dBk1Gs|6?3Iu&xd_NEcIRfQ;jU4_&rt#M{GvCLo$in| zFlWT91?%ne;%DpHh>|mB)XD>o`{Z|}DCD!@6E>xC42D2<<-|&K9p9D|8%AOUL*nUU zgeAc5EJ5a{qNC3=hBUV_NS`i4cERo?#22QQbqk1qmm6?XXPP2dIkX$Kz&|mYbZc{# zH=_y83bzvgM8HlRd!F4m%w`(;OgKPxA$2k}{4|<){#o&n15_{k+-&@q|5(1x6~INO zk)0l=9IMQALbV)5memD+GwE=*SyJjQzJud7Sew;w)ZUs2Mbn4b?XP9(A4%Yi!I)9F zxoEwR#Vi?FF@o$;*!$74@yTV=Ix`Ev?ZGxY+Cp5lJZMNfeEDz4-_)l~!pMEr&IJx5 z;N{|{ttT&wHV!g~x#lt0Rw>>mWx8z2T|S;>P0+JeL-fqwUh=t6_&WAT*|O7hb8NdT z;N133t6;6UkyyB(0hXx0czqU%`-VL>AC+4rYcei`Quch2@pV-g~!@ktAXMtAe`R{xFtW zZ_-SUpSw9&v4)h`%bCZozc!|1cIVj$KmC14l@eHzhSd2Yn!KY^Y@DVdj2%%a;Eny; zifkxmlznjV_oqww>@m}weS5R?JX%~F$Eh#oqjm}}4t zY$z`Zb4rw5&u?}8k!we9E;ob#VTsUW8`BEn1EduS|NB|A9e=FlNaS>pW5z&7vJ^Ma z=qi9}q68u34euW@*IidM5dhYVHWdaAmUEl|8#o^}S-1}7S+M1MSug?7yrSijowU;a z7{&}OG+|F41i*@0&m=+)D0_`~sZ}}(Im?&(C`>*?-ZsSl;pebuLJv6(nr#1?F1a!( zVu)S63@Db&H}Q+P!o+U*&yUef@OmLxW%OurXMMac!SNxl8rotF!uU#!8$L9h0QveutW3 zkNO=7yI^M*_*F{JMCG|6ci6xyG*pOdtniL=@xBtlk}~SU`a;hzcEN_O##G%H7rl&s zdI!qq8SbMvF?b>JJY`sbOQGs7zXZCzo^)WrVXndI7yG&Bi$)Y$dnR&v=|)KX%Z7=Q zL!{M92Whj@kG)ThUR<>_U93Q{W!iXz4V{1jhG`K<VDy-0#>&CcGphjd`vaD1y8L5nlgrSxLy=CWlZ)|Uh~!h=DsvRg1qhKwWbrb zxm$Z^1N>D7lguJ%rn^T?A(KY4!8F1^IV)MJcaMQRR!jif z-j#Ml<-D6W<2ei@Z{IznZNkOvZcKxgTBB=?)dMJ=(=6dw{R&@l66mr9U7+6k(|%w+rm9Wpwk{8t@EB(I>3LfM+T~w^ z8^6gG!{hX}SEa>>*EQACUw0!Yr^w(U#AweOsqSf2ogZrWRd4YT3-$`p<%;e&{4pO$ zJV*1F47E@5&!MHGh_If@^I~;Rf~E-lLTTY{r*^r5<$rmzRA+VZ;$$YP%FUPrEo}ul zaH^j35u&0=Mp=i=eLHnwygTgibw8fNh0@SP(Fjjf_E~$jSV^iXUFd-ne2>9xA`5}# zO2P*iQlc{Za*&h>ZMm`s3q7ZF$DY&a+66mE;Pv78SchbXp{+bms+0)0WPJ#6pjT@e zsBm+-78#9cPeo3N`0YNYBUK9CF3u_}9I4FYeZZz1AnR!d=0%WA2nHsKSqJIPSsj|AG zt6z8(ymIwqo-wpL$&_!q3{Z4C0&Z8iJ*B6BF+Pr~oXW}XESNAYdmB8;bDJ2ZXK<0* zpcTs-dABvyEUG~rf6NM^86@%D9sBa?4L68QgtBgs#Bf(2aO6WKkOIru-v*w#NeUv@ z#5lUJ10|6cux@eyOf0zr?H+`yoRfu_UCTP{`eT+5iwdMVPYqqcszXRRd;Zar1rFN< zVJknOdy&YIjdSGB{Wej^QfuV$;lInCi+M?X-B*;k4*yfb6E{tx5|E1(gZJn zl8>v!CO+Q_6MKL)Grwo@4dyXboRIANj6lfDjb(zp=7iP=z07A^aWFUI+fcsdm(ALL z`ILJ&kyALGrb5Nn{~jh}1_B~tf`@yjg^p-}IS09lpCFktKc@0+%k{CuH=A6@xJ#fYP#duWau-p$95qHJuc_K#pYM zBmG=X7gS=v`xQr+_rWh>-AMfCB$yF{M7mrY=qYHI(-jxZ(M4h~k59U*^43X5O@?AN zo&Y?++K2>1ayLr6n%K9Xn=EaTBo74E zN}aX+w5Ev%Ue=^VuW~1vWBjR0yR)ANnBG@K-YD zlKOC^x|~iDu)z{yswBu*aDc*XK@=3nfLmsTdp{BjSuGbPB|7hd=_UNoRv@r**>h@LOzWS_t(9U?z;ghnEnpbPlcZeS_RRO z_}g^5^^^l*r8XdGr!&7k2`wGJk>Tv*kw9H7AJ`dh!|$Z?i)MIIa6+-XxicylVuR?_ z`tU7LeeX_fV(_8icv@WT9YIj7BESt!*T;X&w^K?>(>v;u!^Nj+{}}y5v%(kQ_U5nB3Bglf#sgol&X&b} zd_5oIHunNiC3+1Yb?ECy9CUr!eCZ90B?hWv!=IGDO=k(Heown6<%+8;yOqCJ$A_#= zShUEl*t?TEgOpi%9IWBl?~{x77|d?sUoymdgPcfTIGyGs-Uu6p1yjmZLBa0frwpD_ zBlv&m_y%y(d~WYSY}FG71?%w1xP`xPNEos#=m%7o?%s!{Fxz_$fe=noOPWuXBa<8^ zoaUad*r1ipk`#9dsD9u1w@PiS=(b>mJq86h<~fqtedGn5FY|<#Q4$t}fZBquAA&); z(vyqAzsYV}j!iVZ3!Hh_o1_S&6wYNzezn; zEW`%M()n;UmJ+_ts{fRAWk28}9@@0@bGzII1-D|3BJFP;ehj!};A_U;olgVhecKQc z=-+-3Unv9h3Nd?q_^#fDmeS}M?xgc?)2#Y6tZ!HR)zKTlC-;XeBWGQ_*XJN<7u#D7 z*%s%eO^FDkDBvFBb=m&-Gz1c_HfQR|N~sfaX|n)GgVXUv8Y26!cvOi=M z18UE{ehk78l;_HtpRLGqzWVC>h==1)rx*PCw_G-;U3kFFj;4YCdY@I$gbWY1&2sh- z(Iiioi&&#n-HY!0X66ndRL=Ulb!Pj5`4};TtMpCc@qrlH>WC;Cs@yBQC9;3PHvuO0 zGh&{C)UQG61xvCBw?V>{RlL2b|B_o{d49pO7QwQx3$71FbUmJwDr|4($~Nn#UoYcf z?lK^xyG8LY^QvgQJJV>Qc_QaD{d6mAi71_In6Gk5bmJRR>c*LlA1wgeEOpQHPXT5{ zV~<<~>x*}4w9xO-b%i#1BWk>op0SgDX!2Y;lCd~2Ht|5{rml= zVDeYHc|C9*eR zpDH>)jlXNe99v=}#v$$3(Q(McJ`7!AMuuL~eB6V#Y4}~W+>bMQJGPU~3^YJt=lN#% zWg@YR?4=%c{gotGy+oktufO73Ess4hYNqQr=3tH<(0A=5_O`$`>zWkM>BeRBAnG{BDhDp8Y+cYwou6-dt zWF!18+b4qDAk{+FTu*pj)?E4QBCvU>Y>Rierg;mASOLE%0Fw$>gD5tKHk(DvbNeB6 z*SNq+mpy6=j{4q|;V{3blBiZ&Si<%98TRIqm7RNx?}fHVOSk#4X6DndXM4529{Do7P60TMk&=|M!K2th$? zGzmgLq$t54#fWHVp@pUd2ndAGlDiYjz4zPu@Wyy!yzw6lMv}ee`mNd5Tx;$aYb*1O zaA`OI02@!9IDQ5Ipx{?1uwfneF&FY>3H*Qro-scP6n&KW4*pn+IbwMP07?=?RxZH6 z-+%d?Km`K8rh36YgzEdu9RL&~PaZ#VHpF?dw>IA!m99IzfC#DoAgZK&@YkQzog4O2 z>%1i&i#-xcvbnQvqtC+=>k}^dtyu$Gzy65yWry33E?ZyvSITV7de587KV*DkpmS}@W*Td_;4 z`f2IVIzLp5S|@$x><%Sfls!51MFBd>uDJ{S1`FGHNKqP1RDWDOcOrXHKWtP?{^H%&Hz!GU@YQwTRsZ-#oWkx0q*UF{|B9bIsX z##vnaVj|}1DImxTgG48{^@;OCRa>yNGwovw{O-w^?9h2b<+Nl0L(d%mCI#0j!|A3> z-pJ;5+h-Jqid@VXx+XF#7PDvixo=HdxO(G50Xr|Y;m_Zp4}qe&L{9Ts`_}CUPMAAU zP!)YEwXoygBnjYl^Qjc*79}2+OgQBo+ipO3I`Qf|l6L%UwDAsy;?45PfM{w8S_AOk z#=AwXLCk?j=)b!ONeMPF)!QT>2Y!z41N@nZ4Iyaz7jh}wuD+(Tb$OP!Fh#ob$}BC? zVVra72dHrnM-?bhWP2eZ4Oay?or?QUou(_F8a}($2!j_BFw;~hftMUlYz^^jv8`oC zOg=$WGjAM=7s}$32T-78^1evJ16q4#&PJ6CRbZrTVvdVNp9#nhcDQ2!ajhs|e3mc~ z<|?P3d+ zIVqg&07+YXyp1}4&*y5-59`NCG1*U@*6L>nv|d>T-QtOQMQ^eVb+w*oM_`!|K06I3 z9tqU!Qv&=eFE<@{jri`Y348MH!d^2a2kJ)bPpQ=btuH>Rt`9m7g^sRpHp@A1&2`~` zz2Oze89Rb1pyh7VbFrY}Gf}713P!=|^<2e`#r(L|j6^GBL+ecaeXnIYTE#skaE~@M ziNSUiy=V4Ka03WYl`XGkEE$oyUY?n7L8R0oUh9kJiWd&u&Q%89?78jj)@I}7qd$f4 zT}{^^1ssQ5QkRT7xV;kPVn$3m^oXFk4IJHvg4O0Gs%dyYgy zUyfq7DWxl)%O$^0cpih&t_O+9Rv8Nz1=zzh$)$L8%-9S~>(Y7S6 z@2jAePjOJcdghfJYKm(nh0|i=>ER2}3rmS$H~gbb3&fm;wY(W}DJaxp(=Ng5Hpb<* zI4?3v*@s+arBPkB0JB*?7FkSr_m<9@nn~BK4dRn&scp898D60i>wv1wTFmQXHw`54 zf753lmyI3DE0|CLs*z9pgSx|dt34wdTN|I_)8(>_+MTz4$pIJ@&JXG-=bGuen+1f% z+1upW4;FS99d$%;WGXu!h}lB4`J&9guLhoyM<5mc=KCDcP4s-afOrOj&0Am=6GuFJ z%|NCN;1~O{z2S8Uahe^@U17|oCOUM>g2%$?)0(fG7nJ?)riap&iM9~qj<*vrp*YWn zfW#*+9WGt`ie0&^FAY7;Ih|L~7O3zodM*u~R>=i*x(;pvDd}-3_O868u7(ydVWn>{ z_ZTL!OZ&D6}p*k;%8H^DM21GBl1NpXll@7V%}9`*yKEbRsl>YA0t3w z$X*l*4KT-ziaujKhNt$sR96!)!qw^iy}bOc!=I-c2ckJsg|D z%{a%)@(@yG29d)td<7rNEcMaV^c1M|iQ>?BgxsuORcPSWN5pJSojPx$SM6z_`nwm18pJuyeHj{6h10G`}fcwfo z!yIFy23_)%^X#JnM{r52lvjuNHor$<^RLOP-I^JKA?M|po&_9}`@hG#x9#6fZirk1 z`dDg;mxxLD195FPMP51E{!zu(z(+l9fV-HQ=*0 z9I%kU=P(s|)e?I*rKM0o^A7SmagXLRj{KQOXHjNXs)HXC2jBfgV3E5Aj-QK%)@_A7 zd`Tp)aSk(ZwbKB%Ey*sml6+T|4)TvGFBto-e=~QjuE0?h$mYK-UG5JGzgTVhze$S2 zG>v!eS4)MPoJP-`@>XYrwf?uA7>2d{-qj9DNlYzyK5Vy|1?VU>8#=-lRe$r(WS*+F zzh4wyN;(UKZQ@h2V4!NB0w-w7z&;xwHm(qhRkSK7>}Y8^1No-2f}1P__pM*1_BZZ; ztW0;*Ua9f4a{!U2`JZd~yMNolgd7CSbPm#49(m^k(74f7-|8P>>c6GO?6pzW=FAVcRL)VoKTK3qVQTFidZ3t*3y^P>3;evEU27?NZtCIjk+x7V}pfPZhou8<=nnbR#FrTAO(Q-TN?d)flr%>QQAl3Wp(`Ff8`wQ+|1Zdnrb3$%inTN zST;`4ADW>ksP8hU8@8zcE9V%m>1w~IN=_mZ3n~|Cx59wY$H4U6irC4dS?U@L7<=Bd z9yPD2)#Bq2yuJ$X<}uX(U!fU!UksndXV1*l&fctVmH-4bl?B0Jy`RB%>MCcmi@e%X z75o0#I8YodK2lc6d5qHl9c)0sZkjrDqr*x}@44fXpFm0Ke;bNj9Nb>p z(bVJy8(>gfaFaf<0~rTi&5v2%f&zhOfDlth7~-^OB3u7^b~Bhf{4}0yU{cyL_MBfH z$d3KVxf*j^cdODH?z@$Vg_`!22(*WX7er6rQY zP;}Om{^Wl?IS#p_emUa4AbCd*Kba?j!R>D0kgX_4^m{5VS1Vaa09|+Kn7_azed~me z1N#FQLFJGC1Mz=B7b_F}eDziwpUr3BOh*(6kAl2&1*U}Ky-%`A*MgdVz1)LaqAnLd zWrR;>^V^JSq*MTsVj*oSXr^yd**H$SU`!bZVEweAi9K$1Gmg)!N3729SSq@3JR|I< zF+Y7B!%a`{@>LN3^O?|B>}?~7XCPckN6imrdq3~JW!iV`X~E`14N?0wx%Fwy;``N( zDVfkyuz~xOom)y3%nk@0!bQ}gi;Lex^rgZ|h27g?IW1Ih1Mm(QwU z;_qma8BKQKkFR!2WP%mT;pJ-f8}48+E{OcBWS-?{E(}PSy)}-Qk6`-Xt*w{*dTCX* zC|4M>o3w`BBQ^(GLZWe0O+*NvhYXicB24~__}!kNqx?K0JAipXHI<|3_oLHH2sUwu zC7ARac*7YYvvD0Gluc2E2-*Q*kiYCn?TcjbSV2>-;C0lRm4>gu8p;sX&&1(GZ2F2D zz5t1?+Ro(n+@cKhe#C8mr6SBYPUX%=FbV`6 zvwh4yp8QtW9y2iq#E!!`LLm;tB?J)9@K`ilWEUy68Gr9+!Z9)1sm`J|Kbm7gC|1}n@y7xXg$>e%y} zV>aG$K$JH9RLYeio~9D~3~S6TML6Yr!&m;0KX%}k5UNGIVhe`UmL5@Z4=(E#Jr<}A`8E|a<%3q?m-Ie3X45^+~(3ZVqY7JDx z=JO{*L(1}i6W1kxo6x#*j;p@3dea+lyt_GMmoi{99!RUf^2>Ik18bD6A$KN}fweGv z9P#rk4?~+>=&N2%R|W3wgyA0oer>j4eSF&!;WNLVylni6%cfkzpYRl7=Tx{j9rw|M z14keaRfxWF`5mUioE%__1dwrY%>#7YQTZRKLU?aLVr z!6LkI5#I48Au5nGGa<34>N;Iy2=?P-9h>7>Lx#rD%wfu8Q2Et{7`&Jrg z>{@9bU2u>KUKF7=?-~(u?87Oqjk>%IzlFw>)E zCFdRXqzWeBnLZJN{h@+#bMv&&eGC&VPis+});|SH5(Ps6BgzHu-qp^6CFh{H%W~6T z56t{|bnU`QkOc6705!1&;LUns9#d5QdB_Iy!w{{}B?NelRr5pox2;S)Cb_Ah>{T7u zE}4>Z(|MZbVJ0Mj==ht=7YDt*A!Z5xfR#H#x+3WDp3&u8$1+|YSh4;hAz7JdDaaOQ z3yS+rlHP%-C(%DXEiHdk`DI>-RW0D^&10fAG;BD+T0ofna=?dpuP73BI_YbY;k7+KU|9kWB~%ngAZ49ZFkrE=Asfr-twOIEn!?kI*BI%5 zM_$7KOqIHR?^3Xa8WwKi_jN5}D{SC)1GKEAFj&6OGyv6w1^}NJs9$c_;ohlk%6q*+ zH?RN!ro~_bW(}D^*O`(I)cf0Dz<@l67Hf$+Af7*(YS)A@g#g@W!F7T2e1T*4PE9p9 zfJ8AY#mRTdBR7^?13u@yIY~(t_Wa#~5lf@0p@i(iwP>Vx=tQmh`D2iZ3#i1t2yfq& zf)+>cJgQN?^LqY;tNyp-_^XtuWQ*Ww%Gl$1%msDW!22w=tL~l-$4BlSqhRLc4sxa5 z^ZxSR)A^$SLL{8e7mxFB!+zt2J16H=dASNEB=iOIO7i)4Qqo20@_MC*PVJ90esb;N ziOwz4?c4LF!q0;0c1u$MY}ajm$6hPhnbS8b!VX^bi?5JQ z6lb;NYG@V6$s1|C2>kNiv2f=hAx{md-OqY~;>xAXsPr;`Lc8kA?B~>j`^OYJwoIBhJg9bD+61~(qK3ve^ z0E97$r1CVk-))G|unN<*{F@SOF4Nvd4O%iBTHG(kZ>w9llfSzeVv!p8?78agGwUh&h^ack6A^} zXvWuJZ#*lE3G!AgGY(o&vN&9^xQ}BsnefPC7#l)V4%OafNR)*=#7izsq=UJ8x0?2L zeEd_L_sd@m?kDTLB{XHIO;+T{rIcl-D9cNsY~Kv-hCPg?7Ew6vld0Brp8Ei)&EBzU z^YoI;cu6e-k5&xk8p=VNN}Qia;I6zPtS@>5USAx`FeY)v5$+!4&`(%*PZf*JmknY} z19G<>TP$?D6!SbP2~|31wW9mdqwuX5s>&H+C4t|=w8$|p7d_$$PTC*vZ1rB6Zlw3E z4KZQpT@PEBNIj( zi%FeLI@Ca)VcNc;Z)oaEh3yAD8w#_%LEZx9j^-7L+#wyXg)|zV9A}9MGFM!diInKK zjRn0DmuORwSkh<_OwR^@>j(IE(1qRxH))B$3}@WBnmg7F!VNdlrgdU2XVCrkNkxP| zrF?UqDE?%yS5OxR4Cj;@izEu*qur#kyzJu>oii&&DLP@p?voOxD`*1oO4T8>`S3Ff zi1KK(IIZt#l848A=>8@6@;xtmMq*#5XX}1!yg@?C{nqPdQ}%wcg4cahI!N5wkQ-#QIY9&PGEX+6l@=S8XNpv4;W zz65{Ei>AwE_N3fmQpYBzL=9^+hmojrKuVukiyQ|pr@8{6v4|bB^@X*;34$qReQr3S z&O(pCP*T>C)t`Kt@7dG$(4rggjv(WgSd(~j532t%(%{iO6dpNgfAL*_WKq5--Kw+VO>;GGQJul+@!KV9F&ZMS3 zBKq2MQxLa#+m|G=q=#Y^;O@QpHwt@m<4mb^iaNXb+bulWtd^Pd0o4`wKqE*QFfFWn zXSfu*N39FyI(%~8NQ>ESK(sKEWp%3u*9)lW5Xv))_cv+LV{802!X7@;ad~L&V(G3} z3b^+!%b{k^_awK`RL-OKYhP!e4HLGKIBTP2N?cQWo&XX-lUL@zWSF&HuzU`KFx)jW9yh0)9ZPG2xi*)0PLz{_j!b-Oi=71*7u+7@Eq(}bwPr2IDXK}q zb_H5=8oR83yxyldzK2#7im(nK)^A@!Iu22u8r(k~ed`!X$_ZeOr3Hf0j&F z-(2!R(y8n9rd@8!Oxu0y+`-c!qkj3hxslaDwOkRCQFT}B4nJoHxzFuRD>!S>#$ z^;^u?g?_SzYd(V!5?q5=?T#XOr=+yOc6rUXxU;1RAhRs&Y-iR!s82kMVBb=rWQ zs;v0wIA~pOs;{UxAuRrqo!NGL%kF-8UKY5F;|DTfNUP+!>$P%1k^5m$)yNuI@s?w7 zAXucvtWPsDB?-1`h;pr|dyGYPtg;N8yO%h&e(n9fOVv3yjn;W~U>*rl)mF<;Ex%jG42x_e^j zKn*x4>VHz=b%lmo@v3qC_w;t4dVxD| z*#-d5{PLiqlou!EUiWKJ2K;;6S?6VwZ7MhgFKC(TqDk&Zz)A=e4MHJSRj|5z{nV1E zBbkzDP&x7D>g>gR9>_J`>JAK9!F9vuDuA*BJIbuBe!$Ocmi*8ewvy|MGV-7?yIL;e zg?*mAU^xn|TPs(5B9=mpK~14=r=JPCcnin)OI&J05JqBd!v zW~t>efQ5pEE7&=sLGLVj$m)lk(9H#R)0aW}IvS-Tx|UoY-Z9?za?HPtu}&yJKHxsJ zEcdrya!0O_DZ{KqrV9E?-_HRDd{^TpQ1RsoLvMBbxAhy` z_i{JJUSKIx;bSPBp0o zDbSh>3Lt@ab22rpssPsRE2dfwYu}DpEkJ(PNuaC0sAOcqio^dBL1O{1~F_<=;(2OKTJ1k}=QI=raXLt1>aNJEPhBj$Fsc!deW+^Gyz8cLq9Sb(Kz_w#9+=TNL=gw}L^>TNo$tP&D zpCg!XgTvWUG0&5Y8{(b{JBKnh0IB%Pp4=k(0TSkjQ-LR~iKw)O7~kEx|H;0KuN7o- z-;ANw8AS-32yArSsh;$8XJ5s1G&R!Ap;0Z>03qbHGj08T@D5R~FGa$T?{6hg$OPE^ zn~=3frb|`&TbOYecMpYW;?En)J>dQ;Pj{!x$Sp3$CgoJ1Jy@fs7>9ofB#p0#jeRs8 zUj~?q>bR)M`yaTvv$>4G5ZT2m(jzJ>mK@q`^~67=Z&ua7%%prTL6;XUI$2ei2v&wd zaqB82w?%6*xXhg;Vy*P7ALWfF_MPwoA?OpZE%i+Qn~9YRdT*&mYxLe?oVBQ!%a%F+ znn~?ktQ-KdEr=is8+gRsLl_*8j5IbdZ_zGJN~&hJEjj~F2N(5@y#MR)_P^f$6*+p# z*WWvps3}&von?LTD=*scNX1owc07)QmyGoC%XGKJ9TFb>I~eDOd&EM>FHZF^*rIs(f5&<01I%0_B0ViQbN5RVC5WpVeJuyWldG z0waKBs@26vUAr69ue`;hFS`=|4#@yr5v%vq=oEw6Ye1B02*)w*Z&#}s>O|MBcisG- pw@?1_=FR`R*N-x5u`_(gKrUzP$L + + + + diff --git a/src/api/CustomerAPI.ts b/src/api/CustomerAPI.ts new file mode 100644 index 0000000..88b77d8 --- /dev/null +++ b/src/api/CustomerAPI.ts @@ -0,0 +1,107 @@ +import { axios, type Page, type PageResult } from "timi-web"; +import type { Customer, CustomerDailyStatView, CustomerGenderStatView, CustomerInviteUpdateReq, CustomerSearchReq, CustomerTrendStatReq, QuickRegisterReq } from "@/types/Customer"; +import type { RegistrationEventRecord } from "@/types/RegistrationEventRecord"; + +const BASE_URI = "/gao/customer"; + +async function list(req: Page): Promise> { + return await axios.post(`${BASE_URI}/list`, req); +} + +async function search(req: CustomerSearchReq): Promise { + return await axios.post(`${BASE_URI}/search`, req); +} + +async function searchPage(req: Page): Promise> { + return await axios.post(`${BASE_URI}/search/page`, req); +} + +async function exportExcel(req: CustomerSearchReq): Promise { + return await axios.post(`${BASE_URI}/export`, req, { + responseType: "blob" + }); +} + +async function detail(id: string): Promise { + return await axios.post(`${BASE_URI}/detail`, undefined, { + params: { id } + }); +} + +async function detailByCode(code: string): Promise { + return await axios.post(`${BASE_URI}/detail/code`, undefined, { + params: { code } + }); +} + +async function nullableDetailByCode(code: string): Promise { + return await axios.post(`${BASE_URI}/detail/code/nullable`, undefined, { + params: { code } + }); +} + +async function invitedList(introducerCustomerId: string): Promise { + return await axios.post(`${BASE_URI}/invited/list`, undefined, { + params: { introducerCustomerId } + }); +} + +async function create(req: Customer): Promise { + return await axios.post(`${BASE_URI}/create`, req); +} + +async function quickRegister(req: QuickRegisterReq): Promise { + return await axios.post(`${BASE_URI}/quick/register`, req); +} + +async function update(req: Customer): Promise { + return await axios.post(`${BASE_URI}/update`, req); +} + +async function remove(id: string): Promise { + return await axios.post(`${BASE_URI}/delete`, undefined, { + params: { id } + }); +} + +async function createInvite(req: CustomerInviteUpdateReq): Promise { + return await axios.post(`${BASE_URI}/invite/create`, req); +} + +async function updateInvite(req: CustomerInviteUpdateReq): Promise { + return await axios.post(`${BASE_URI}/invite/update`, req); +} + +async function deleteInvite(customerId: string): Promise { + return await axios.post(`${BASE_URI}/invite/delete`, undefined, { + params: { customerId } + }); +} + +async function dailyStat(req: CustomerTrendStatReq): Promise { + return await axios.post(`${BASE_URI}/stat/daily`, req); +} + +async function genderStat(): Promise { + return await axios.post(`${BASE_URI}/stat/gender`); +} + +export default { + list, + search, + searchPage, + exportExcel, + detail, + detailByCode, + nullableDetailByCode, + invitedList, + create, + quickRegister, + update, + remove, + createInvite, + updateInvite, + deleteInvite, + dailyStat, + genderStat +}; diff --git a/src/api/GaoUserAPI.ts b/src/api/GaoUserAPI.ts new file mode 100644 index 0000000..21733bc --- /dev/null +++ b/src/api/GaoUserAPI.ts @@ -0,0 +1,41 @@ +import { axios, type Page, type PageResult, type Role } from "timi-web"; +import type { GaoUser } from "@/types/GaoUser"; + +const BASE_URI = "/gao/user"; + +async function list(req: Page): Promise> { + return await axios.post(`${BASE_URI}/list`, req); +} + +async function detail(id: string): Promise { + return await axios.post(`${BASE_URI}/detail`, undefined, { + params: { id } + }); +} + +async function create(req: GaoUser): Promise { + return await axios.post(`${BASE_URI}/create`, req); +} + +async function update(req: GaoUser): Promise { + return await axios.post(`${BASE_URI}/update`, req); +} + +async function remove(id: string): Promise { + return await axios.post(`${BASE_URI}/delete`, undefined, { + params: { id } + }); +} + +async function roleList(): Promise { + return await axios.post(`${BASE_URI}/role/list`); +} + +export default { + list, + detail, + create, + update, + remove, + roleList +}; diff --git a/src/api/RegistrationEventAPI.ts b/src/api/RegistrationEventAPI.ts new file mode 100644 index 0000000..c75f2ad --- /dev/null +++ b/src/api/RegistrationEventAPI.ts @@ -0,0 +1,41 @@ +import { axios, type Page, type PageResult } from "timi-web"; +import type { RegistrationEvent } from "@/types/RegistrationEvent"; + +const BASE_URI = "/gao/registration-event"; + +async function list(req: Page): Promise> { + return await axios.post(`${BASE_URI}/list`, req); +} + +async function enabledList(): Promise { + return await axios.post(`${BASE_URI}/enabled/list`); +} + +async function detail(id: string): Promise { + return await axios.post(`${BASE_URI}/detail`, undefined, { + params: { id } + }); +} + +async function create(req: RegistrationEvent): Promise { + return await axios.post(`${BASE_URI}/create`, req); +} + +async function update(req: RegistrationEvent): Promise { + return await axios.post(`${BASE_URI}/update`, req); +} + +async function remove(id: string): Promise { + return await axios.post(`${BASE_URI}/delete`, undefined, { + params: { id } + }); +} + +export default { + list, + enabledList, + detail, + create, + update, + remove +}; diff --git a/src/api/RegistrationEventRecordAPI.ts b/src/api/RegistrationEventRecordAPI.ts new file mode 100644 index 0000000..190d4a9 --- /dev/null +++ b/src/api/RegistrationEventRecordAPI.ts @@ -0,0 +1,88 @@ +import { axios, type Page, type PageResult } from "timi-web"; +import type { + CustomerRegisterStatView, + RegistrationEventRecordCalendarView, + RegistrationEventRecord, + RegistrationEventRecordCreateReq, + RegistrationEventRecordDailyStatView, + RegistrationEventRecordListItemView, + RegistrationEventRecordRangeReq, + RegistrationEventRecordStatReq, + RegistrationEventRecordTrendStatReq +} from "@/types/RegistrationEventRecord"; + +const BASE_URI = "/gao/registration-event-record"; + +async function list(req: Page): Promise> { + return await axios.post(`${BASE_URI}/list`, req); +} + +async function detail(id: string): Promise { + return await axios.post(`${BASE_URI}/detail`, undefined, { + params: { id } + }); +} + +async function rangeList(req: RegistrationEventRecordRangeReq): Promise { + return await axios.post(`${BASE_URI}/range/list`, req); +} + +async function calendarRangeList(req: RegistrationEventRecordRangeReq): Promise { + return await axios.post(`${BASE_URI}/range/calendar/list`, req); +} + +async function rangePage(req: Page): Promise> { + return await axios.post(`${BASE_URI}/range/page`, req); +} + +async function rangeExport(req: RegistrationEventRecordRangeReq): Promise { + return await axios.post(`${BASE_URI}/range/export`, req, { + responseType: "blob" + }); +} + +async function create(req: RegistrationEventRecordCreateReq): Promise { + return await axios.post(`${BASE_URI}/create`, req); +} + +async function update(req: RegistrationEventRecord): Promise { + await axios.post(`${BASE_URI}/update`, req); +} + +async function remove(id: string): Promise { + await axios.post(`${BASE_URI}/delete`, undefined, { + params: { id } + }); +} + +async function customerRangeStat(req: RegistrationEventRecordStatReq): Promise { + return await axios.post(`${BASE_URI}/customer/range/stat`, req); +} + +async function allCustomerRangeStat(req: RegistrationEventRecordStatReq): Promise { + return await axios.post(`${BASE_URI}/all-customer/range/stat`, req); +} + +async function customerRegistrationEventDailyStat(req: RegistrationEventRecordTrendStatReq): Promise { + return await axios.post(`${BASE_URI}/customer/registration-event/daily/stat`, req); +} + +async function allCustomerRegistrationEventDailyStat(req: RegistrationEventRecordTrendStatReq): Promise { + return await axios.post(`${BASE_URI}/all-customer/registration-event/daily/stat`, req); +} + +export default { + list, + detail, + rangeList, + calendarRangeList, + rangePage, + rangeExport, + create, + update, + remove, + customerRangeStat, + allCustomerRangeStat, + customerRegistrationEventDailyStat, + allCustomerRegistrationEventDailyStat +}; diff --git a/src/assets/sound/registration-success.mp3 b/src/assets/sound/registration-success.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..1d8167c09cc40da84a1329470f430a423cbb9c6f GIT binary patch literal 21312 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 literal 0 HcmV?d00001 diff --git a/src/assets/sound/scan-success.mp3 b/src/assets/sound/scan-success.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..6aaf0019e18bb6c87d04219c702f45b31cdd196f GIT binary patch literal 4320 zcmd6o_g9mN5{ADNk^liy2qd%(p%{?zCDb5F2*nVhgr-3e5`-W{MbuqbQG%3&ru1r| zN>P+zLC~dF>8xu*MLPMpG2`bfYMS2fCWQfQM-ek3LUzzb8?FC(y0VZcgq{4zMX%OHHsf+YAavkz!c*N z7@Ka4FpC$1^Hkcd*4kjUmR>;VED&l>WM<-C;)%q-O&!=|Q9Mg$*dw{cMr!_$Xv3s> z1Iz`(zKK_smu4;usZ$dW4(fEBXC}GKTM6W<4|nzth7pLvn&%^b7tJKI^(##tiFGDf zRY+T{vWqAHE>{i=R8$j_b7GOklk##8%X3_z?~}xilh1R|7EstYkn*;s`iS|~6t+oy z>NTYqWv|xdt@SbI%QKm}?&m2*eW>o_>X27hV$4EpX>_H(uf4O{={b!t{;Q0(6I-UU zJ9p}*Y+ALzFNpt;T*%@wE^1-_m)Tk&|2Y5H|LchOPCHEl`L?mZHxxulM+=&P7#|7 zoLu9f7$p;ep+wyY)dlBREzI5jbec0!P}d-iZ;F2I|HYI^*3~v9pNy=+0x(pJcQgo{ zKVX2i)$Km^9=F(oZ7CQ}%nr!g05N{YT*%a+|OSm`X6G zPS`7!h*|NHu1he0I8mg)JsbFb; z-gR>1CVn!Irb_~a6WSV=q>aMv9genXXz#Md2pcT&!lBt9 zI6_su=LY;P_{jec>wO;+O@#3vyD&U~mP$VD`N5}Iu3<9<7$^SZYpZ$4W)T>T2FzQJ z4nRs40Y!rNuOeLfK47Jj4X*fkR&cK;NJ3EhB%7`4(1d(tLhT*MfC8^epc!D}7l7CB3opk+qq8o=6IckzN*F zlUAAO@1vpBh)|e#2k-M0a8wYi&base-+6s<4vK#=i zF-|^a7_k97UZ+F5X?gpa#Vgm1mua6dO1FJ~$D`2@RdmnHfu$wI@85&9VkS0r^t4IL zI+BUmBG<&rQRhUcc5aLum5~R5x2S811VweYvApQ)Ar%o~5o%|%K19icZ(Yj>3Tj@NJ)`P*sp5+pFBQo`K$$2%|Hd$7p8IzZAXQ8nC&!9oW@N9&F6V%P5)KiEN z6Cn~JG2)M5y)*uo<+qbiY^g&cehZMkaNRr{-EpAVAcgCKrtZD!uutVkeZet;>pD^Vs}G2`z%4ELWm( z>SN{I^BN%4>i1 z3=Ae}_KWb;YH=8cgpDm&i+%?_xU~G%`ycapedFCt12IW;^}P>VrvP9I9-o7NG|P#7 zo-DMuwdQ9%N3_cdkPqiLY2quw6b26~Zon5Jflx8Vtk4o#E0*Gaw8!x)kU}KXA(7}t zJd`?dHu@t;BN@dNhiC&`*16%Vp zGeVgi>=mpQ6-KP^Jt>qv?e-+P3wSE$JzF-bg^jj-NwKU_HU8jq)hPFQWdUbTnk5;+ zMInaC3S6qfumRkgaQ0d-B6moA4SWK~^MSnE=*9#bwM(M8Tl7}@gvLq^ICm4g zIjkbq>n(k_lZ*d05M+oJyUz6WocPJtLX#j--xfaRVs%nk&vU7N0Bw)PbUyOqYB@_g zhYh%wdi_A0vz=4yzRW_GO15ZkVT&VcY%S*a(fg!PN%P3@ zy=S8%^)KJpkiCes=Df?Tm$ffnOsfe3EUrgMU`Cjyic?s>1Oulx5e-!ytohTM&oz1T zQ>`SAMo;`x(u#TOf=YQxb-UV3TDR=*im7-lDl1?n0Fdn%`G&(0WU_Sjs<3Zr(U zDZro0V~;b^Jp74WF2$z|j&WV;r&;j8H0j;Fw_b$63MG`lY_AhV+x?C~<4Ts|o?M)Y zyE}ViO~!fM6SIpkHas2%Gy%9vhSJ`LA6tg53d(%Xbo7}~h$?ge`8`-`;x*mdZ@yE9 z+r$J5bGs)Thaa3Xzs0aw>FO*mMGwyCYDyI<0I#3-*@+ySrfPD`IF)u%RnM<)@;s^! zVvbV0f3RRnJxuYDjbdVP*;paOsMwrR(~$Dl4a9HO-mn%e--av+qmmuf@fMRmKveuS zOn=Tl0wUml=!tt;38NIWpPims()~@VH5Z4vmtsuVim2m<=^CYv_1ySy@8Uu(6>5Vc&~hTe>px!hpg2klMO%NoGvKCI$J~^_J@xYJ z9RQ zy1(yigByWO|2I=|yo=lWt``3+@Ya0~EvfAoq)}A_sG&d+P z74#haq6;<{~HHXF6vDb&CTwlP4f?8)OhYmJHvTl94v z*aQAW#{ zz!os9G8q1_Ux{-J^#48vIJ=qr<=En zA!qjX)MPoO;1pa3x_6J*+E0yr=$+vL|)>w0DA#YVsV$COI;y~9R^9;#PU zoj3|v6oTc!sI2XlR^dS<_IgEzB4}52ouU37N+#di2%eGy-)l_av~N7WE^m)WymqEK RjO(z|+1!){f_49g`VUYud; +
+ + + + + + + + + +

+

+ + + + + diff --git a/src/components/CodeScanner.vue b/src/components/CodeScanner.vue new file mode 100644 index 0000000..b7063e1 --- /dev/null +++ b/src/components/CodeScanner.vue @@ -0,0 +1,529 @@ + + + + + diff --git a/src/components/CustomerProfileCard.vue b/src/components/CustomerProfileCard.vue new file mode 100644 index 0000000..ec729fd --- /dev/null +++ b/src/components/CustomerProfileCard.vue @@ -0,0 +1,130 @@ + + + + + diff --git a/src/components/CustomerSelector.vue b/src/components/CustomerSelector.vue new file mode 100644 index 0000000..165f008 --- /dev/null +++ b/src/components/CustomerSelector.vue @@ -0,0 +1,288 @@ + + + + + diff --git a/src/components/GenderIcon.vue b/src/components/GenderIcon.vue new file mode 100644 index 0000000..5f3f213 --- /dev/null +++ b/src/components/GenderIcon.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/src/components/PageTransition.vue b/src/components/PageTransition.vue new file mode 100644 index 0000000..2a5d93b --- /dev/null +++ b/src/components/PageTransition.vue @@ -0,0 +1,153 @@ + + + + + diff --git a/src/components/PhotoField.vue b/src/components/PhotoField.vue new file mode 100644 index 0000000..af7a6fe --- /dev/null +++ b/src/components/PhotoField.vue @@ -0,0 +1,144 @@ + + + + + diff --git a/src/components/PhotoScroller.vue b/src/components/PhotoScroller.vue new file mode 100644 index 0000000..fabe38a --- /dev/null +++ b/src/components/PhotoScroller.vue @@ -0,0 +1,206 @@ + + + + + diff --git a/src/components/RegistrationEventRecordCalendar.vue b/src/components/RegistrationEventRecordCalendar.vue new file mode 100644 index 0000000..9af4e88 --- /dev/null +++ b/src/components/RegistrationEventRecordCalendar.vue @@ -0,0 +1,425 @@ + + + + + diff --git a/src/components/RegistrationEventSelector.vue b/src/components/RegistrationEventSelector.vue new file mode 100644 index 0000000..13d6aaf --- /dev/null +++ b/src/components/RegistrationEventSelector.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/src/components/SegmentedSlider.vue b/src/components/SegmentedSlider.vue new file mode 100644 index 0000000..e8701ca --- /dev/null +++ b/src/components/SegmentedSlider.vue @@ -0,0 +1,186 @@ + + + + + diff --git a/src/layout/MainLayout.vue b/src/layout/MainLayout.vue new file mode 100644 index 0000000..2a67630 --- /dev/null +++ b/src/layout/MainLayout.vue @@ -0,0 +1,251 @@ + + + + + diff --git a/src/layout/RootLayout.vue b/src/layout/RootLayout.vue new file mode 100644 index 0000000..dd020cb --- /dev/null +++ b/src/layout/RootLayout.vue @@ -0,0 +1,20 @@ + + + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..eb7ba86 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,77 @@ +import {createApp} from "vue"; +import {createPinia} from "pinia"; +import router from "@/router"; +import Root from "@/Root.vue"; + +import "tdesign-mobile-vue/es/style/index.css"; +import "timi-web/style.css"; +import "timi-tdesign-mobile/style.css"; +import "vue-virtual-scroller/dist/vue-virtual-scroller.css"; +import "@/styles/tdesign-custom.css"; +import "@/styles/global.less"; +import {configureUserStore, type ApiResponse, Network, useUserStore, VCan, VRole} from "timi-web"; +import {Toast} from "tdesign-mobile-vue"; + +export const pinia = createPinia(); +const apiBaseURL = import.meta.env.VITE_API_BASE_URL as string | undefined; + +if (apiBaseURL) { + Network.axios.defaults.baseURL = apiBaseURL; +} + +configureUserStore({ + storageKey: "gao-customer-h5:user" +}); + +Network.setGlobalRequestInterceptor((config: any) => { + const userStore = useUserStore(pinia); + if (apiBaseURL && !config.baseURL) { + config.baseURL = apiBaseURL; + } + + config.headers.set({ + "Accept-Language": "zh-CN" + }); + + if (userStore.token) { + config.headers.set({ + "Token": userStore.token + }); + } + return config; +}); +async function bootstrap(): Promise { + const app = createApp(Root); + app.use(pinia); + app.directive("can", VCan); + app.directive("role", VRole); + + const userStore = useUserStore(pinia); + await userStore.loginByStorage(); + + Network.setGlobalErrorCallback((resp: ApiResponse) => { + Toast({ + theme: "error", + direction: "row", + message: resp.message + }); + }); + + app.use(router); + app.mount("#root"); +} + +async function start(): Promise { + try { + await bootstrap(); + } catch (error) { + console.error(error); + Toast({ + theme: "error", + direction: "row", + message: "应用启动失败" + }); + } +} + +void start(); diff --git a/src/pages/Login.vue b/src/pages/Login.vue new file mode 100644 index 0000000..653d66a --- /dev/null +++ b/src/pages/Login.vue @@ -0,0 +1,209 @@ + + + + + diff --git a/src/pages/customer/QuickEntryPage.vue b/src/pages/customer/QuickEntryPage.vue new file mode 100644 index 0000000..8127b0a --- /dev/null +++ b/src/pages/customer/QuickEntryPage.vue @@ -0,0 +1,576 @@ + + + + + diff --git a/src/pages/customer/QuickSignInPage.vue b/src/pages/customer/QuickSignInPage.vue new file mode 100644 index 0000000..7c38886 --- /dev/null +++ b/src/pages/customer/QuickSignInPage.vue @@ -0,0 +1,445 @@ + + + + + diff --git a/src/pages/management/CustomerDataCharts.vue b/src/pages/management/CustomerDataCharts.vue new file mode 100644 index 0000000..94ac4bf --- /dev/null +++ b/src/pages/management/CustomerDataCharts.vue @@ -0,0 +1,670 @@ + + + + + diff --git a/src/pages/management/CustomerDetail.vue b/src/pages/management/CustomerDetail.vue new file mode 100644 index 0000000..d3f643d --- /dev/null +++ b/src/pages/management/CustomerDetail.vue @@ -0,0 +1,564 @@ + + + + + diff --git a/src/pages/management/CustomerEdit.vue b/src/pages/management/CustomerEdit.vue new file mode 100644 index 0000000..7789398 --- /dev/null +++ b/src/pages/management/CustomerEdit.vue @@ -0,0 +1,541 @@ + + + + + diff --git a/src/pages/management/CustomerList.vue b/src/pages/management/CustomerList.vue new file mode 100644 index 0000000..e6b12b1 --- /dev/null +++ b/src/pages/management/CustomerList.vue @@ -0,0 +1,374 @@ + + + + + diff --git a/src/pages/management/ManagementDataCharts.vue b/src/pages/management/ManagementDataCharts.vue new file mode 100644 index 0000000..1d6d006 --- /dev/null +++ b/src/pages/management/ManagementDataCharts.vue @@ -0,0 +1,521 @@ + + + + + diff --git a/src/pages/management/ManagementPassword.vue b/src/pages/management/ManagementPassword.vue new file mode 100644 index 0000000..a004f49 --- /dev/null +++ b/src/pages/management/ManagementPassword.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/src/pages/management/ManagementProfile.vue b/src/pages/management/ManagementProfile.vue new file mode 100644 index 0000000..25112a1 --- /dev/null +++ b/src/pages/management/ManagementProfile.vue @@ -0,0 +1,279 @@ + + + + + diff --git a/src/pages/management/ManagementQrCode.vue b/src/pages/management/ManagementQrCode.vue new file mode 100644 index 0000000..a492ca8 --- /dev/null +++ b/src/pages/management/ManagementQrCode.vue @@ -0,0 +1,360 @@ + + + + + diff --git a/src/pages/management/ManagementSettings.vue b/src/pages/management/ManagementSettings.vue new file mode 100644 index 0000000..668e651 --- /dev/null +++ b/src/pages/management/ManagementSettings.vue @@ -0,0 +1,146 @@ + + + + + diff --git a/src/pages/management/PermissionEdit.vue b/src/pages/management/PermissionEdit.vue new file mode 100644 index 0000000..3d1cece --- /dev/null +++ b/src/pages/management/PermissionEdit.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/src/pages/management/PermissionList.vue b/src/pages/management/PermissionList.vue new file mode 100644 index 0000000..7154015 --- /dev/null +++ b/src/pages/management/PermissionList.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/src/pages/management/PermissionSettings.vue b/src/pages/management/PermissionSettings.vue new file mode 100644 index 0000000..386a0d6 --- /dev/null +++ b/src/pages/management/PermissionSettings.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/src/pages/management/RegistrationEventEdit.vue b/src/pages/management/RegistrationEventEdit.vue new file mode 100644 index 0000000..c434964 --- /dev/null +++ b/src/pages/management/RegistrationEventEdit.vue @@ -0,0 +1,314 @@ + + + + + diff --git a/src/pages/management/RegistrationEventList.vue b/src/pages/management/RegistrationEventList.vue new file mode 100644 index 0000000..4cce3fd --- /dev/null +++ b/src/pages/management/RegistrationEventList.vue @@ -0,0 +1,297 @@ + + + + + diff --git a/src/pages/management/RegistrationEventRecordDetail.vue b/src/pages/management/RegistrationEventRecordDetail.vue new file mode 100644 index 0000000..98dac8a --- /dev/null +++ b/src/pages/management/RegistrationEventRecordDetail.vue @@ -0,0 +1,138 @@ + + + + + diff --git a/src/pages/management/RegistrationEventRecordEdit.vue b/src/pages/management/RegistrationEventRecordEdit.vue new file mode 100644 index 0000000..459a796 --- /dev/null +++ b/src/pages/management/RegistrationEventRecordEdit.vue @@ -0,0 +1,630 @@ + + + + + diff --git a/src/pages/management/RegistrationEventRecordList.vue b/src/pages/management/RegistrationEventRecordList.vue new file mode 100644 index 0000000..3d8eff9 --- /dev/null +++ b/src/pages/management/RegistrationEventRecordList.vue @@ -0,0 +1,629 @@ + + + + + diff --git a/src/pages/management/RoleEdit.vue b/src/pages/management/RoleEdit.vue new file mode 100644 index 0000000..ba12d44 --- /dev/null +++ b/src/pages/management/RoleEdit.vue @@ -0,0 +1,194 @@ + + + + + diff --git a/src/pages/management/RoleList.vue b/src/pages/management/RoleList.vue new file mode 100644 index 0000000..f554e64 --- /dev/null +++ b/src/pages/management/RoleList.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/src/pages/management/RolePermissionAssign.vue b/src/pages/management/RolePermissionAssign.vue new file mode 100644 index 0000000..ddffb83 --- /dev/null +++ b/src/pages/management/RolePermissionAssign.vue @@ -0,0 +1,290 @@ + + + + + diff --git a/src/pages/management/UserDetail.vue b/src/pages/management/UserDetail.vue new file mode 100644 index 0000000..0bb6395 --- /dev/null +++ b/src/pages/management/UserDetail.vue @@ -0,0 +1,240 @@ + + + + + diff --git a/src/pages/management/UserEdit.vue b/src/pages/management/UserEdit.vue new file mode 100644 index 0000000..13e3443 --- /dev/null +++ b/src/pages/management/UserEdit.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/src/pages/management/UserList.vue b/src/pages/management/UserList.vue new file mode 100644 index 0000000..b2fab42 --- /dev/null +++ b/src/pages/management/UserList.vue @@ -0,0 +1,195 @@ + + + + + diff --git a/src/pages/management/UserRoleAssign.vue b/src/pages/management/UserRoleAssign.vue new file mode 100644 index 0000000..c8b4dc4 --- /dev/null +++ b/src/pages/management/UserRoleAssign.vue @@ -0,0 +1,241 @@ + + + + + diff --git a/src/pages/tabs/CustomerTab.vue b/src/pages/tabs/CustomerTab.vue new file mode 100644 index 0000000..d172a39 --- /dev/null +++ b/src/pages/tabs/CustomerTab.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/src/pages/tabs/ManagementTab.vue b/src/pages/tabs/ManagementTab.vue new file mode 100644 index 0000000..f6e123d --- /dev/null +++ b/src/pages/tabs/ManagementTab.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..356b533 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,108 @@ +import { createRouter, createWebHistory } from "vue-router"; +import RootLayout from "@/layout/RootLayout.vue"; +import MainLayout from "@/layout/MainLayout.vue"; +import Login from "@/pages/Login.vue"; +import chartRoutes from "@/router/routes/chartRoutes"; +import customerRoutes from "@/router/routes/customerRoutes"; +import { managementAccountRoutes, managementSettingRoutes } from "@/router/routes/managementRoutes"; +import permissionRoutes from "@/router/routes/permissionRoutes"; +import registrationRoutes from "@/router/routes/registrationRoutes"; +import tabRoutes from "@/router/routes/tabRoutes"; +import userRoutes from "@/router/routes/userRoutes"; +import { useGlobalUIStore } from "@/store/globalUI"; +import { useUserStore } from "timi-web"; + +const detailRoutes = [ + ...customerRoutes, + ...userRoutes, + ...registrationRoutes, + ...managementSettingRoutes, + ...permissionRoutes, + ...chartRoutes, + ...managementAccountRoutes +]; + +const router = createRouter({ + history: createWebHistory("/"), + scrollBehavior(_to, _from, savedPosition) { + if (savedPosition) { + return savedPosition; + } + + return { + left: 0, + top: 0 + }; + }, + routes: [ + { + path: "/", + component: RootLayout, + children: [ + { + path: "", + redirect: "/customers" + }, + { + path: "login", + name: "Login", + component: Login, + meta: { + depth: 1, + navBarVisible: false, + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "", + component: MainLayout, + meta: { + depth: 1, + navBarVisible: false, + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + }, + children: [ + ...tabRoutes, + ...detailRoutes + ] + } + ] + }, + { + path: "/:pathMatch(.*)*", + redirect: "/customers" + } + ] +}); + +router.beforeEach((to) => { + const userStore = useUserStore(); + if (to.path === "/login") { + return userStore.isLogged() ? "/management" : true; + } + + if (!userStore.isLogged()) { + return { + path: "/login", + query: { + redirect: to.fullPath + } + }; + } + + return true; +}); + +router.afterEach((to) => { + const globalUIStore = useGlobalUIStore(); + const isDarkMode = globalUIStore.themeMode === "dark"; + const fallbackBackground = isDarkMode ? "#10161f" : "#F5F5F8"; + const targetBackground = isDarkMode ? to.meta.darkBodyBackground : to.meta.bodyBackground; + globalUIStore.setBodyBackground(typeof targetBackground === "string" ? targetBackground : fallbackBackground); +}); + +export default router; diff --git a/src/router/routes/chartRoutes.ts b/src/router/routes/chartRoutes.ts new file mode 100644 index 0000000..2c4ee56 --- /dev/null +++ b/src/router/routes/chartRoutes.ts @@ -0,0 +1,48 @@ +import type { RouteRecordRaw } from "vue-router"; + +const chartRoutes: RouteRecordRaw[] = [ + { + path: "/management/data-charts", + name: "ManagementDataCharts", + component: () => import("@/pages/management/ManagementDataCharts.vue"), + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "全局数据图表", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/customer-data-charts", + name: "CustomerDataCharts", + component: () => import("@/pages/management/CustomerDataCharts.vue"), + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "客户数据图表", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/customers/:id/data-charts", + name: "CustomerDataChartsFromCustomer", + component: () => import("@/pages/management/CustomerDataCharts.vue"), + meta: { + depth: 5, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "客户数据图表", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + } +]; + +export default chartRoutes; diff --git a/src/router/routes/customerRoutes.ts b/src/router/routes/customerRoutes.ts new file mode 100644 index 0000000..e5313fb --- /dev/null +++ b/src/router/routes/customerRoutes.ts @@ -0,0 +1,110 @@ +import type { RouteRecordRaw } from "vue-router"; +import QuickEntryPage from "@/pages/customer/QuickEntryPage.vue"; +import QuickSignInPage from "@/pages/customer/QuickSignInPage.vue"; +import RegistrationEventRecordEdit from "@/pages/management/RegistrationEventRecordEdit.vue"; +import CustomerList from "@/pages/management/CustomerList.vue"; +import CustomerDetail from "@/pages/management/CustomerDetail.vue"; +import CustomerEdit from "@/pages/management/CustomerEdit.vue"; + +const customerRoutes: RouteRecordRaw[] = [ + { + path: "/customer/quick-entry", + name: "QuickEntryPage", + component: QuickEntryPage, + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "快速补录登记", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/customer/quick-sign-in", + name: "QuickSignInPage", + component: QuickSignInPage, + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "快速扫码登记", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/customer/registration", + name: "CustomerRegistrationEventRecordCreate", + component: RegistrationEventRecordEdit, + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "登记", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/customers", + name: "CustomerList", + component: CustomerList, + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "客户管理", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/customers/create", + name: "CustomerCreate", + component: CustomerEdit, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "新增客户", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/customers/:id", + name: "CustomerDetail", + component: CustomerDetail, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "客户详情", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/customers/:id/edit", + name: "CustomerEdit", + component: CustomerEdit, + meta: { + depth: 5, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "编辑客户", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + } +]; + +export default customerRoutes; diff --git a/src/router/routes/managementRoutes.ts b/src/router/routes/managementRoutes.ts new file mode 100644 index 0000000..56cd7f9 --- /dev/null +++ b/src/router/routes/managementRoutes.ts @@ -0,0 +1,74 @@ +import type { RouteRecordRaw } from "vue-router"; +import ManagementSettings from "@/pages/management/ManagementSettings.vue"; +import ManagementProfile from "@/pages/management/ManagementProfile.vue"; +import ManagementPassword from "@/pages/management/ManagementPassword.vue"; +import ManagementQrCode from "@/pages/management/ManagementQrCode.vue"; + +export const managementSettingRoutes: RouteRecordRaw[] = [ + { + path: "/management/settings", + name: "ManagementSettings", + component: ManagementSettings, + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "应用设置", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + } +]; + +export const managementAccountRoutes: RouteRecordRaw[] = [ + { + path: "/management/profile", + name: "ManagementProfile", + component: ManagementProfile, + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "当前用户", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/profile/password", + name: "ManagementPassword", + component: ManagementPassword, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "修改密码", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/qr-code", + name: "ManagementQrCode", + component: ManagementQrCode, + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "生成二维码", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + } +]; + +const managementRoutes: RouteRecordRaw[] = [ + ...managementSettingRoutes, + ...managementAccountRoutes +]; + +export default managementRoutes; diff --git a/src/router/routes/permissionRoutes.ts b/src/router/routes/permissionRoutes.ts new file mode 100644 index 0000000..78c9aed --- /dev/null +++ b/src/router/routes/permissionRoutes.ts @@ -0,0 +1,139 @@ +import type { RouteRecordRaw } from "vue-router"; +import PermissionSettings from "@/pages/management/PermissionSettings.vue"; +import RoleList from "@/pages/management/RoleList.vue"; +import RoleEdit from "@/pages/management/RoleEdit.vue"; +import PermissionList from "@/pages/management/PermissionList.vue"; +import PermissionEdit from "@/pages/management/PermissionEdit.vue"; +import RolePermissionAssign from "@/pages/management/RolePermissionAssign.vue"; +import UserRoleAssign from "@/pages/management/UserRoleAssign.vue"; + +const permissionRoutes: RouteRecordRaw[] = [ + { + path: "/management/permissions", + name: "PermissionSettings", + component: PermissionSettings, + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "权限设置", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/permissions/roles", + name: "RoleList", + component: RoleList, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "角色管理", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/permissions/roles/create", + name: "RoleCreate", + component: RoleEdit, + meta: { + depth: 5, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "新增角色", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/permissions/roles/:id", + name: "RoleEdit", + component: RoleEdit, + meta: { + depth: 5, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "编辑角色", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/permissions/items", + name: "PermissionList", + component: PermissionList, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "权限管理", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/permissions/items/create", + name: "PermissionCreate", + component: PermissionEdit, + meta: { + depth: 5, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "新增权限", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/permissions/items/:id", + name: "PermissionEdit", + component: PermissionEdit, + meta: { + depth: 5, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "编辑权限", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/permissions/assign", + name: "RolePermissionAssign", + component: RolePermissionAssign, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "角色授权权限", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/permissions/user-roles", + name: "UserRoleAssign", + component: UserRoleAssign, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "用户授权角色", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + } +]; + +export default permissionRoutes; diff --git a/src/router/routes/registrationRoutes.ts b/src/router/routes/registrationRoutes.ts new file mode 100644 index 0000000..94bd9c1 --- /dev/null +++ b/src/router/routes/registrationRoutes.ts @@ -0,0 +1,109 @@ +import type { RouteRecordRaw } from "vue-router"; +import RegistrationEventEdit from "@/pages/management/RegistrationEventEdit.vue"; +import RegistrationEventList from "@/pages/management/RegistrationEventList.vue"; +import RegistrationEventRecordDetail from "@/pages/management/RegistrationEventRecordDetail.vue"; +import RegistrationEventRecordEdit from "@/pages/management/RegistrationEventRecordEdit.vue"; +import RegistrationEventRecordList from "@/pages/management/RegistrationEventRecordList.vue"; + +const registrationRoutes: RouteRecordRaw[] = [ + { + path: "/management/registration-events", + name: "RegistrationEventList", + component: RegistrationEventList, + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "登记事件管理", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/registration-events/create", + name: "RegistrationEventCreate", + component: RegistrationEventEdit, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "新增登记事件", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/registration-events/:id/edit", + name: "RegistrationEventEdit", + component: RegistrationEventEdit, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "编辑登记事件", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/registration-event-records", + name: "RegistrationEventRecordList", + component: RegistrationEventRecordList, + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "登记事件记录管理", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/registration-event-records/create", + name: "RegistrationEventRecordCreate", + component: RegistrationEventRecordEdit, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "新增登记事件记录", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/registration-event-records/:id", + name: "RegistrationEventRecordDetail", + component: RegistrationEventRecordDetail, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "登记事件记录详情", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/registration-event-records/:id/edit", + name: "RegistrationEventRecordEdit", + component: RegistrationEventRecordEdit, + meta: { + depth: 5, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "编辑登记事件记录", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + } +]; + +export default registrationRoutes; diff --git a/src/router/routes/tabRoutes.ts b/src/router/routes/tabRoutes.ts new file mode 100644 index 0000000..7981e89 --- /dev/null +++ b/src/router/routes/tabRoutes.ts @@ -0,0 +1,36 @@ +import type { RouteRecordRaw } from "vue-router"; +import CustomerTab from "@/pages/tabs/CustomerTab.vue"; +import ManagementTab from "@/pages/tabs/ManagementTab.vue"; + +const tabRoutes: RouteRecordRaw[] = [ + { + path: "/customers", + name: "CustomerTab", + component: CustomerTab, + meta: { + depth: 2, + navBarVisible: true, + navBarCanBack: false, + navBarTitle: "客户", + tabBarVisible: true, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management", + name: "ManagementTab", + component: ManagementTab, + meta: { + depth: 2, + navBarVisible: true, + navBarCanBack: false, + navBarTitle: "管理", + tabBarVisible: true, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + } +]; + +export default tabRoutes; diff --git a/src/router/routes/userRoutes.ts b/src/router/routes/userRoutes.ts new file mode 100644 index 0000000..ac2c916 --- /dev/null +++ b/src/router/routes/userRoutes.ts @@ -0,0 +1,80 @@ +import type { RouteRecordRaw } from "vue-router"; +import UserList from "@/pages/management/UserList.vue"; +import UserDetail from "@/pages/management/UserDetail.vue"; +import UserEdit from "@/pages/management/UserEdit.vue"; +import UserRoleAssign from "@/pages/management/UserRoleAssign.vue"; + +const userRoutes: RouteRecordRaw[] = [ + { + path: "/management/users", + name: "UserList", + component: UserList, + meta: { + depth: 3, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "用户管理", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/users/create", + name: "UserCreatePage", + component: UserEdit, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "新增用户", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/users/:id", + name: "UserDetail", + component: UserDetail, + meta: { + depth: 4, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "用户详情", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/users/:id/edit", + name: "UserEdit", + component: UserEdit, + meta: { + depth: 5, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "编辑用户", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + }, + { + path: "/management/users/:id/roles", + name: "UserRoleAssignFromUser", + component: UserRoleAssign, + meta: { + depth: 5, + navBarVisible: true, + navBarCanBack: true, + navBarTitle: "配置角色", + tabBarVisible: false, + bodyBackground: "#F5F5F8", + darkBodyBackground: "#10161f" + } + } +]; + +export default userRoutes; diff --git a/src/store/globalUI.ts b/src/store/globalUI.ts new file mode 100644 index 0000000..3867558 --- /dev/null +++ b/src/store/globalUI.ts @@ -0,0 +1,41 @@ +import type { Pinia } from "pinia"; +import { defineStore } from "pinia"; + +export const DEFAULT_BODY_BACKGROUND = "#FFF"; +const THEME_STORAGE_KEY = "gao-customer-h5:theme-mode"; + +export type ThemeMode = "light" | "dark" | "system"; + +function readStoredThemeMode(): ThemeMode { + const rawValue = localStorage.getItem(THEME_STORAGE_KEY); + if (rawValue === "light" || rawValue === "dark" || rawValue === "system") { + return rawValue; + } + + return "system"; +} + +const store = defineStore("globalUI", () => { + const bodyBackground = ref(DEFAULT_BODY_BACKGROUND); + const themeMode = ref(readStoredThemeMode()); + + function setBodyBackground(color?: string): void { + bodyBackground.value = color || DEFAULT_BODY_BACKGROUND; + } + + function setThemeMode(mode: ThemeMode): void { + themeMode.value = mode; + localStorage.setItem(THEME_STORAGE_KEY, mode); + } + + return { + bodyBackground, + themeMode, + setBodyBackground, + setThemeMode + }; +}); + +export function useGlobalUIStore(pinia?: Pinia) { + return store(pinia); +} diff --git a/src/store/navBarStore.ts b/src/store/navBarStore.ts new file mode 100644 index 0000000..2047c8d --- /dev/null +++ b/src/store/navBarStore.ts @@ -0,0 +1,96 @@ +export const useNavBarStore = defineStore("nav-bar", () => { + const route = useRoute(); + const router = useRouter(); + + const height = ref(0); + const title = ref(""); + const backTo = ref(); + const rightIcon = ref(""); + const rightText = ref(""); + const rightTextColor = ref(""); + const rightAction = shallowRef<(() => void | Promise) | undefined>(); + const customTitleVisible = ref(false); + const customRightVisible = ref(false); + + const isShowing = computed(() => !!router.currentRoute.value.meta.navBarVisible); + const canBack = computed(() => !!router.currentRoute.value.meta.navBarCanBack); + + watch( + () => route.meta.navBarTitle, + (value) => { + title.value = typeof value === "string" ? value : ""; + }, + { immediate: true } + ); + + function setHeight(value: number): void { + height.value = value; + } + + function setBackTo(value?: string): void { + backTo.value = value; + } + + function setRightIcon(value?: string, action?: () => void | Promise): void { + rightIcon.value = value || ""; + rightAction.value = action; + if (value) { + rightText.value = ""; + rightTextColor.value = ""; + customRightVisible.value = false; + } + } + + function setRightText(value?: string, color?: string, action?: () => void | Promise): void { + rightText.value = value || ""; + rightTextColor.value = color || ""; + rightAction.value = action; + if (value) { + rightIcon.value = ""; + customRightVisible.value = false; + } + } + + function setCustomTitleVisible(value: boolean): void { + customTitleVisible.value = value; + } + + function setCustomRightVisible(value: boolean): void { + customRightVisible.value = value; + if (value) { + rightIcon.value = ""; + rightText.value = ""; + rightTextColor.value = ""; + rightAction.value = undefined; + } + } + + function clearRight(): void { + rightIcon.value = ""; + rightText.value = ""; + rightTextColor.value = ""; + rightAction.value = undefined; + customRightVisible.value = false; + } + + return { + height, + title, + backTo, + rightIcon, + rightText, + rightTextColor, + rightAction, + customTitleVisible, + customRightVisible, + isShowing, + canBack, + setHeight, + setBackTo, + setRightIcon, + setRightText, + setCustomTitleVisible, + setCustomRightVisible, + clearRight + }; +}); diff --git a/src/store/permissionSettingsStore.ts b/src/store/permissionSettingsStore.ts new file mode 100644 index 0000000..5c625d4 --- /dev/null +++ b/src/store/permissionSettingsStore.ts @@ -0,0 +1,339 @@ +import { defineStore } from "pinia"; +import { + OrderType, + PermissionAPI, + RoleAPI, + type ModuleCode, + type Permission as UserPermission, + type PermissionPayload, + type Role as UserRole, + type RolePayload +} from "timi-web"; + +export const gaoModuleCode: ModuleCode = "GAO"; +const pageSize = 1000; + +export type Permission = UserPermission; +export type Role = UserRole & { + permissionIdList: string[]; + childRoleIdList: string[]; +}; + +export type RoleDraft = { + id?: string; + code: string; + name: string; + description: string; + nameLangId?: string; + moduleCode?: ModuleCode; + permissionIdList: string[]; + childRoleIdList: string[]; +}; +export type PermissionDraft = { + id?: string; + code: string; + name: string; + description: string; + nameLangId?: string; + moduleCode?: ModuleCode; +}; + +function normalizeRole(role: UserRole): Role { + return { + ...role, + moduleCode: role.moduleCode || gaoModuleCode, + description: role.description || "", + permissionIdList: role.permissionIdList || role.permissionList?.map(item => item.id) || [], + childRoleIdList: role.childRoleIdList || role.childRoleList?.map(item => item.id) || [] + }; +} + +function createEmptyRole(): Role { + return { + id: "", + moduleCode: gaoModuleCode, + code: "", + name: "", + description: "", + permissionIdList: [], + childRoleIdList: [] + }; +} + +function createEmptyPermission(): Permission { + return { + id: "", + moduleCode: gaoModuleCode, + code: "", + name: "", + description: "" + }; +} + +export const usePermissionSettingsStore = defineStore("permission-settings", () => { + const roleList = ref([]); + const permissionList = ref([]); + const loading = ref(false); + const loaded = ref(false); + let loadTask: Promise | null = null; + + const roleTree = computed>(() => { + const childIdSet = new Set(roleList.value.flatMap(item => item.childRoleIdList)); + const roots = roleList.value.filter(item => !childIdSet.has(item.id)); + return roots.flatMap(item => buildRoleTree(item.id, 0, new Set())); + }); + + // ---------- 基础数据 ---------- + + async function loadAll(force = false): Promise { + if (loaded.value && !force) { + return; + } + + if (loadTask && !force) { + await loadTask; + return; + } + + loading.value = true; + loadTask = (async () => { + const [roleResult, permissionResult] = await Promise.all([ + RoleAPI.list({ + index: 0, + size: pageSize, + equalsExample: { + moduleCode: gaoModuleCode + }, + orderMap: { + code: OrderType.ASC + } + }), + PermissionAPI.list({ + index: 0, + size: pageSize, + equalsExample: { + moduleCode: gaoModuleCode + }, + orderMap: { + code: OrderType.ASC + } + }) + ]); + roleList.value = roleResult.list.map(normalizeRole); + permissionList.value = permissionResult.list; + loaded.value = true; + })(); + + try { + await loadTask; + } finally { + loadTask = null; + loading.value = false; + } + } + + async function loadRoleDetail(id: string): Promise { + if (!id) { + return createEmptyRole(); + } + + const role = normalizeRole(await RoleAPI.detail(id)); + upsertLocalRole(role); + return role; + } + + async function loadPermissionDetail(id: string): Promise { + if (!id) { + return createEmptyPermission(); + } + + const permission = permissionList.value.find(item => item.id === id); + if (!permission) { + throw new Error("权限不存在"); + } + upsertLocalPermission(permission); + return permission; + } + + function upsertLocalRole(role: Role): void { + const index = roleList.value.findIndex(item => item.id === role.id); + if (-1 < index) { + roleList.value.splice(index, 1, role); + return; + } + roleList.value.unshift(role); + } + + function upsertLocalPermission(permission: Permission): void { + const index = permissionList.value.findIndex(item => item.id === permission.id); + if (-1 < index) { + permissionList.value.splice(index, 1, permission); + return; + } + permissionList.value.unshift(permission); + } + + // ---------- 查询 ---------- + + function buildRoleTree(roleId: string, level: number, visitedRoleIds: Set): Array { + const current = getRoleById(roleId); + if (!current || visitedRoleIds.has(roleId)) { + return []; + } + + const nextVisitedRoleIds = new Set(visitedRoleIds); + nextVisitedRoleIds.add(roleId); + + return [{ + ...current, + level + }, ...current.childRoleIdList.flatMap(childRoleId => buildRoleTree(childRoleId, level + 1, nextVisitedRoleIds))]; + } + + function getRoleById(id: string): Role | undefined { + return roleList.value.find(item => item.id === id); + } + + function getPermissionById(id: string): Permission | undefined { + return permissionList.value.find(item => item.id === id); + } + + function getChildRoles(role: Role): Role[] { + return role.childRoleIdList.map(getRoleById).filter(Boolean) as Role[]; + } + + function getRolePermissionList(role: Role): Permission[] { + return role.permissionIdList.map(getPermissionById).filter(Boolean) as Permission[]; + } + + function getInheritedPermissionList(role: Role): Permission[] { + const permissionMap = new Map(); + const allPermissionList = role.allPermissionList || []; + for (const permission of [...getRolePermissionList(role), ...allPermissionList]) { + permissionMap.set(permission.id, permission); + } + + for (const childRole of getChildRoles(role)) { + for (const permission of getRolePermissionList(childRole)) { + permissionMap.set(permission.id, permission); + } + } + + return Array.from(permissionMap.values()); + } + + // ---------- 写入 ---------- + + async function upsertRole(draft: RoleDraft, createMode: boolean): Promise { + const current = getRoleById(draft.id || ""); + const payload: RolePayload = { + ...draft, + moduleCode: gaoModuleCode, + code: draft.code.trim(), + nameLangId: current?.nameLangId, + name: draft.name.trim(), + description: draft.description.trim(), + permissionIdList: [...draft.permissionIdList], + childRoleIdList: [...draft.childRoleIdList] + }; + + if (createMode) { + await RoleAPI.create({ + moduleCode: payload.moduleCode, + code: payload.code, + name: payload.name, + description: payload.description, + permissionIdList: payload.permissionIdList, + childRoleIdList: payload.childRoleIdList + }); + await loadAll(true); + return undefined; + } + + await RoleAPI.update(payload); + const role = await loadRoleDetail(payload.id || ""); + await loadAll(true); + return role; + } + + async function removeRole(id: string): Promise { + await RoleAPI.remove(id); + roleList.value = roleList.value + .filter(item => item.id !== id) + .map(item => ({ + ...item, + childRoleIdList: item.childRoleIdList.filter(childId => childId !== id) + })); + } + + async function upsertPermission(draft: PermissionDraft, createMode: boolean): Promise { + const current = getPermissionById(draft.id || ""); + const payload: PermissionPayload = { + ...draft, + moduleCode: gaoModuleCode, + code: draft.code.trim(), + nameLangId: current?.nameLangId, + name: draft.name.trim(), + description: draft.description.trim() + }; + + if (createMode) { + await PermissionAPI.create({ + moduleCode: payload.moduleCode, + code: payload.code, + name: payload.name, + description: payload.description + }); + await loadAll(true); + return undefined; + } + + await PermissionAPI.update(payload); + const permission = await loadPermissionDetail(payload.id || ""); + await loadAll(true); + return permission; + } + + async function removePermission(id: string): Promise { + await PermissionAPI.remove(id); + permissionList.value = permissionList.value.filter(item => item.id !== id); + roleList.value = roleList.value.map(item => ({ + ...item, + permissionIdList: item.permissionIdList.filter(permissionId => permissionId !== id) + })); + } + + async function setRolePermissionList(roleId: string, permissionIds: string[]): Promise { + const role = await loadRoleDetail(roleId); + await upsertRole({ + id: role.id, + moduleCode: gaoModuleCode, + code: role.code, + name: role.name || "", + description: role.description || "", + permissionIdList: [...permissionIds], + childRoleIdList: [...role.childRoleIdList] + }, false); + } + + return { + roleList, + permissionList, + roleTree, + loading, + loaded, + loadAll, + loadRoleDetail, + loadPermissionDetail, + getRoleById, + getPermissionById, + getChildRoles, + getRolePermissionList, + getInheritedPermissionList, + upsertRole, + removeRole, + upsertPermission, + removePermission, + setRolePermissionList + }; +}); diff --git a/src/store/settingStore.ts b/src/store/settingStore.ts new file mode 100644 index 0000000..3a060cb --- /dev/null +++ b/src/store/settingStore.ts @@ -0,0 +1,232 @@ +import scanSuccessSoundUrl from "@/assets/sound/scan-success.mp3"; +import registrationSuccessSoundUrl from "@/assets/sound/registration-success.mp3"; + +export interface SoundSetting { + scanSuccess: boolean; + registerSuccess: boolean; + volume: number; +} + +type SoundType = "scanSuccess" | "registerSuccess"; + +const SOUND_STORAGE_KEY = "gao-customer-h5:sound"; +const soundUrlMap: Record = { + scanSuccess: scanSuccessSoundUrl, + registerSuccess: registrationSuccessSoundUrl +}; +// Windows 某些设备链路对极短提示音的起音处理不稳定,直接播放会偏小。 +// 这里先补一段极低音量的预热头,把输出链路“叫醒”后再接原音效。 +const SCAN_SUCCESS_WARMUP_HEAD_MS = 120; +const SCAN_SUCCESS_WARMUP_GAIN = .08; + +function createDefaultSoundSetting(): SoundSetting { + return { + scanSuccess: true, + registerSuccess: true, + volume: 70 + }; +} + +function readStoredSoundSetting(): SoundSetting { + const rawValue = localStorage.getItem(SOUND_STORAGE_KEY); + if (!rawValue) { + return createDefaultSoundSetting(); + } + + try { + const parsedValue = JSON.parse(rawValue) as Partial; + const volume = Number(parsedValue.volume); + return { + scanSuccess: parsedValue.scanSuccess !== false, + registerSuccess: parsedValue.registerSuccess !== false, + volume: Number.isFinite(volume) ? Math.min(100, Math.max(0, volume)) : 70 + }; + } catch { + return createDefaultSoundSetting(); + } +} + +export const useSettingStore = defineStore("setting", () => { + const sound = ref(readStoredSoundSetting()); + const soundPlayerMap = shallowRef | null>(null); + const audioContext = shallowRef(null); + const scanSuccessBuffer = shallowRef(null); + const activeScanSuccessSource = shallowRef(null); + const soundUnlocked = ref(false); + + function setSound(value: Partial): void { + sound.value = { + scanSuccess: value.scanSuccess ?? sound.value.scanSuccess, + registerSuccess: value.registerSuccess ?? sound.value.registerSuccess, + volume: Math.min(100, Math.max(0, value.volume ?? sound.value.volume)) + }; + localStorage.setItem(SOUND_STORAGE_KEY, JSON.stringify(sound.value)); + applySoundVolume(); + } + + function loadSoundPlayers(): void { + if (soundPlayerMap.value) { + return; + } + + soundPlayerMap.value = { + scanSuccess: createSoundPlayer(soundUrlMap.scanSuccess), + registerSuccess: createSoundPlayer(soundUrlMap.registerSuccess) + }; + applySoundVolume(); + } + + function getAudioContext(): AudioContext { + if (audioContext.value) { + return audioContext.value; + } + + audioContext.value = new window.AudioContext(); + return audioContext.value; + } + + function createSoundPlayer(url: string): HTMLAudioElement { + const player = new Audio(url); + player.preload = "auto"; + player.load(); + return player; + } + + function applySoundVolume(): void { + if (!soundPlayerMap.value) { + return; + } + + const volume = sound.value.volume / 100; + Object.values(soundPlayerMap.value).forEach((player) => { + player.volume = volume; + }); + } + + async function unlockSoundPlayers(): Promise { + loadSoundPlayers(); + if (soundUnlocked.value || !soundPlayerMap.value) { + return soundUnlocked.value; + } + + try { + await getAudioContext().resume(); + for (const player of Object.values(soundPlayerMap.value)) { + player.muted = true; + player.volume = 0; + player.currentTime = 0; + await player.play(); + player.pause(); + player.currentTime = 0; + player.muted = false; + } + applySoundVolume(); + soundUnlocked.value = true; + return true; + } catch { + Object.values(soundPlayerMap.value).forEach((player) => { + player.muted = false; + }); + applySoundVolume(); + return false; + } + } + + async function loadScanSuccessBuffer(): Promise { + if (scanSuccessBuffer.value) { + return scanSuccessBuffer.value; + } + + const response = await fetch(soundUrlMap.scanSuccess); + const arrayBuffer = await response.arrayBuffer(); + scanSuccessBuffer.value = await getAudioContext().decodeAudioData(arrayBuffer.slice(0)); + return scanSuccessBuffer.value; + } + + async function playScanSuccessBufferSound(): Promise { + const context = getAudioContext(); + if (context.state === "suspended") { + await context.resume(); + } + + activeScanSuccessSource.value?.stop(); + activeScanSuccessSource.value?.disconnect(); + + const source = context.createBufferSource(); + const gainNode = context.createGain(); + source.buffer = await buildScanSuccessPlaybackBuffer(); + gainNode.gain.value = sound.value.volume / 100; + source.connect(gainNode); + gainNode.connect(context.destination); + source.onended = () => { + if (activeScanSuccessSource.value === source) { + activeScanSuccessSource.value = null; + } + source.disconnect(); + gainNode.disconnect(); + }; + activeScanSuccessSource.value = source; + source.start(0); + } + + async function buildScanSuccessPlaybackBuffer(): Promise { + const sourceBuffer = await loadScanSuccessBuffer(); + const context = getAudioContext(); + const warmupFrameCount = Math.max(1, Math.round(context.sampleRate * SCAN_SUCCESS_WARMUP_HEAD_MS / 1000)); + const outputBuffer = context.createBuffer( + sourceBuffer.numberOfChannels, + sourceBuffer.length + warmupFrameCount, + sourceBuffer.sampleRate + ); + + for (let channelIndex = 0; channelIndex < sourceBuffer.numberOfChannels; channelIndex += 1) { + const outputData = outputBuffer.getChannelData(channelIndex); + const sourceData = sourceBuffer.getChannelData(channelIndex); + const warmupSourceLength = Math.min(sourceData.length, warmupFrameCount); + // 预热头不能是纯静音;纯静音对这类 Windows 问题无效。 + for (let frameIndex = 0; frameIndex < warmupFrameCount; frameIndex += 1) { + const sourceIndex = frameIndex % warmupSourceLength; + outputData[frameIndex] = sourceData[sourceIndex] * SCAN_SUCCESS_WARMUP_GAIN; + } + outputData.set(sourceData, warmupFrameCount); + } + + return outputBuffer; + } + + async function playSound(type: SoundType): Promise { + if (type === "scanSuccess") { + await playScanSuccessBufferSound(); + return; + } + + loadSoundPlayers(); + if (!sound.value[type] || !soundPlayerMap.value) { + return; + } + + const player = soundPlayerMap.value[type]; + player.pause(); + player.muted = false; + player.volume = sound.value.volume / 100; + player.currentTime = 0; + await player.play(); + } + + async function playScanSuccessSound(): Promise { + await playSound("scanSuccess"); + } + + async function playRegisterSuccessSound(): Promise { + await playSound("registerSuccess"); + } + + return { + sound, + setSound, + loadSoundPlayers, + unlockSoundPlayers, + playScanSuccessSound, + playRegisterSuccessSound + }; +}); diff --git a/src/store/tabBarStore.ts b/src/store/tabBarStore.ts new file mode 100644 index 0000000..206c7b9 --- /dev/null +++ b/src/store/tabBarStore.ts @@ -0,0 +1,9 @@ +export const useTabBarStore = defineStore("tab-bar", () => { + const router = useRouter(); + + const isShowing = computed(() => !!router.currentRoute.value.meta.tabBarVisible); + + return { + isShowing + }; +}); diff --git a/src/styles/global.less b/src/styles/global.less new file mode 100644 index 0000000..0cb3bb2 --- /dev/null +++ b/src/styles/global.less @@ -0,0 +1,39 @@ +html, +body, +#root { + --td-swiper-border-radius: 0; + + height: 100%; + min-height: 100vh; +} + +html { + color-scheme: light; + background: #F5F5F8; +} + +html.theme-dark { + color-scheme: dark; + background: #10161f; +} + +body { + margin: 0; + color: #111827; + background: #F5F5F8; + font-family: "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; + transition: background .2s ease, color .2s ease; +} + +html.theme-dark body { + color: #f3f4f6; + background: #10161f; +} + +* { + box-sizing: border-box; +} + +.t-form__label { + color: #555; +} diff --git a/src/styles/tdesign-custom.css b/src/styles/tdesign-custom.css new file mode 100644 index 0000000..fa57999 --- /dev/null +++ b/src/styles/tdesign-custom.css @@ -0,0 +1,284 @@ +:root, :root[theme-mode="light"] { + --td-brand-color-1: #ebf9f6; + --td-brand-color-2: #ceebe6; + --td-brand-color-3: #a4d5ce; + --td-brand-color-4: #76bbb3; + --td-brand-color-5: #559f97; + --td-brand-color-6: #29857d; + --td-brand-color-7: #0f766e; + --td-brand-color-8: #00524b; + --td-brand-color-9: #003b36; + --td-brand-color-10: #002723; + --td-warning-color-1: #fff1e9; + --td-warning-color-2: #ffd9c2; + --td-warning-color-3: #ffb98c; + --td-warning-color-4: #fa9550; + --td-warning-color-5: #e37318; + --td-warning-color-6: #be5a00; + --td-warning-color-7: #954500; + --td-warning-color-8: #713300; + --td-warning-color-9: #532300; + --td-warning-color-10: #3b1700; + --td-error-color-1: #fff0ed; + --td-error-color-2: #ffd8d2; + --td-error-color-3: #ffb9b0; + --td-error-color-4: #ff9285; + --td-error-color-5: #f6685d; + --td-error-color-6: #d54941; + --td-error-color-7: #ad352f; + --td-error-color-8: #881f1c; + --td-error-color-9: #68070a; + --td-error-color-10: #490002; + --td-success-color-1: #e3f9e9; + --td-success-color-2: #c6f3d7; + --td-success-color-3: #92dab2; + --td-success-color-4: #56c08d; + --td-success-color-5: #2ba471; + --td-success-color-6: #008858; + --td-success-color-7: #006c45; + --td-success-color-8: #005334; + --td-success-color-9: #003b23; + --td-success-color-10: #002515; + --td-gray-color-1: #f6f6f6; + --td-gray-color-2: #eeeceb; + --td-gray-color-3: #dddbdb; + --td-gray-color-4: #cac9c9; + --td-gray-color-5: #b6b6b6; + --td-gray-color-6: #a2a2a2; + --td-gray-color-7: #8f8f8f; + --td-gray-color-8: #7b7c7c; + --td-gray-color-9: #6a6b6b; + --td-gray-color-10: #585a5a; + --td-gray-color-11: #494a4a; + --td-gray-color-12: #3a3b3b; + --td-gray-color-13: #2c2e2e; + --td-gray-color-14: #202222; + --td-font-white-1: rgba(255, 255, 255, 1); + --td-font-white-2: rgba(255, 255, 255, .55); + --td-font-white-3: rgba(255, 255, 255, .35); + --td-font-white-4: rgba(255, 255, 255, .22); + --td-font-gray-1: rgba(0, 0, 0, .9); + --td-font-gray-2: rgba(0, 0, 0, .6); + --td-font-gray-3: rgba(0, 0, 0, .4); + --td-font-gray-4: rgba(0, 0, 0, .26); + --td-brand-color: var(--td-brand-color-7); + --td-warning-color: var(--td-warning-color-5); + --td-error-color: var(--td-error-color-6); + --td-success-color: var(--td-success-color-5); + --td-brand-color-focus: var(--td-brand-color-1); + --td-brand-color-active: var(--td-brand-color-8); + --td-brand-color-disabled: var(--td-brand-color-3); + --td-brand-color-light: var(--td-brand-color-1); + --td-brand-color-light-active: var(--td-brand-color-2); + --td-warning-color-active: var(--td-warning-color-6); + --td-warning-color-disabled: var(--td-warning-color-3); + --td-warning-color-focus: var(--td-warning-color-2); + --td-warning-color-light: var(--td-warning-color-1); + --td-warning-color-light-active: var(--td-warning-color-2); + --td-error-color-focus: var(--td-error-color-2); + --td-error-color-active: var(--td-error-color-7); + --td-error-color-disabled: var(--td-error-color-3); + --td-error-color-light: var(--td-error-color-1); + --td-error-color-light-active: var(--td-error-color-2); + --td-success-color-focus: var(--td-success-color-2); + --td-success-color-active: var(--td-success-color-6); + --td-success-color-disabled: var(--td-success-color-3); + --td-success-color-light: var(--td-success-color-1); + --td-success-color-light-active: var(--td-success-color-2); + --td-mask-active: rgba(0, 0, 0, .6); + --td-mask-disabled: rgba(255, 255, 255, .6); + --td-bg-color-page: var(--td-gray-color-1); + --td-bg-color-container: var(--td-font-white-1); + --td-bg-color-container-active: var(--td-gray-color-3); + --td-bg-color-secondarycontainer: var(--td-gray-color-1); + --td-bg-color-secondarycontainer-active: var(--td-gray-color-4); + --td-bg-color-component: var(--td-gray-color-3); + --td-bg-color-component-active: var(--td-gray-color-6); + --td-bg-color-component-disabled: var(--td-gray-color-2); + --td-bg-color-secondarycomponent: var(--td-gray-color-4); + --td-bg-color-secondarycomponent-active: var(--td-gray-color-6); + --td-bg-color-specialcomponent: #fff; + --td-text-color-primary: var(--td-font-gray-1); + --td-text-color-secondary: var(--td-font-gray-2); + --td-text-color-placeholder: var(--td-font-gray-3); + --td-text-color-disabled: var(--td-font-gray-4); + --td-text-color-anti: var(--td-font-white-1); + --td-text-color-brand: var(--td-brand-color); + --td-text-color-link: var(--td-brand-color); + --td-border-level-1-color: var(--td-gray-color-3); + --td-component-stroke: var(--td-gray-color-3); + --td-border-level-2-color: var(--td-gray-color-4); + --td-component-border: var(--td-gray-color-4); + --td-shadow-1: 0 1px 6px rgba(0, 0, 0, 0.05),0 3px 4px rgba(0, 0, 0, 0.04),0 1px 2px -1px rgba(0, 0, 0, 0.08); + --td-shadow-2: 0 3px 10px 2px rgba(0, 0, 0, 0.04),0 6px 8px rgba(0, 0, 0, 0.05),0 4px 4px -2px rgba(0, 0, 0, 0.08); + --td-shadow-3: 0 4px 18px 5px rgba(0, 0, 0, 0.05),0 10px 9px 2px rgba(0, 0, 0, 0.04),0 3px 5px -3px rgba(0, 0, 0, 0.08); + --td-shadow-4: 0 2px 8px 0 rgba(0, 0, 0, 6%); + --td-shadow-inset-top: inset 0 .5px 0 #dcdcdc; + --td-shadow-inset-right: inset .5px 0 0 #dcdcdc; + --td-shadow-inset-bottom: inset 0 -.5px 0 #dcdcdc; + --td-shadow-inset-left: inset -.5px 0 0 #dcdcdc; + --td-table-shadow-color: rgba(0, 0, 0, .08); + --td-scrollbar-color: rgba(0, 0, 0, .1); + --td-scrollbar-hover-color: rgba(0, 0, 0, .3); + --td-scroll-track-color: #fff; +} + +:root.dark, :root[theme-mode="dark"] { + --td-brand-color-1: #002723; + --td-brand-color-2: #003b36; + --td-brand-color-3: #00524b; + --td-brand-color-4: #0f766e; + --td-brand-color-5: #29857d; + --td-brand-color-6: #559f97; + --td-brand-color-7: #76bbb3; + --td-brand-color-8: #a4d5ce; + --td-brand-color-9: #ceebe6; + --td-brand-color-10: #ebf9f6; + --td-warning-color-1: #4f2a1d; + --td-warning-color-2: #582f21; + --td-warning-color-3: #733c23; + --td-warning-color-4: #a75d2b; + --td-warning-color-5: #cf6e2d; + --td-warning-color-6: #dc7633; + --td-warning-color-7: #e8935c; + --td-warning-color-8: #ecbf91; + --td-warning-color-9: #eed7bf; + --td-warning-color-10: #f3e9dc; + --td-error-color-1: #472324; + --td-error-color-2: #5e2a2d; + --td-error-color-3: #703439; + --td-error-color-4: #83383e; + --td-error-color-5: #a03f46; + --td-error-color-6: #c64751; + --td-error-color-7: #de6670; + --td-error-color-8: #ec888e; + --td-error-color-9: #edb1b6; + --td-error-color-10: #eeced0; + --td-success-color-1: #193a2a; + --td-success-color-2: #1a4230; + --td-success-color-3: #17533d; + --td-success-color-4: #0d7a55; + --td-success-color-5: #059465; + --td-success-color-6: #43af8a; + --td-success-color-7: #46bf96; + --td-success-color-8: #80d2b6; + --td-success-color-9: #b4e1d3; + --td-success-color-10: #deede8; + --td-gray-color-1: #f6f6f6; + --td-gray-color-2: #eeeceb; + --td-gray-color-3: #dddbdb; + --td-gray-color-4: #cac9c9; + --td-gray-color-5: #b6b6b6; + --td-gray-color-6: #a2a2a2; + --td-gray-color-7: #8f8f8f; + --td-gray-color-8: #7b7c7c; + --td-gray-color-9: #6a6b6b; + --td-gray-color-10: #585a5a; + --td-gray-color-11: #494a4a; + --td-gray-color-12: #3a3b3b; + --td-gray-color-13: #2c2e2e; + --td-gray-color-14: #202222; + --td-font-white-1: rgba(255, 255, 255, .9); + --td-font-white-2: rgba(255, 255, 255, .55); + --td-font-white-3: rgba(255, 255, 255, .35); + --td-font-white-4: rgba(255, 255, 255, .22); + --td-font-gray-1: rgba(0, 0, 0, .9); + --td-font-gray-2: rgba(0, 0, 0, .6); + --td-font-gray-3: rgba(0, 0, 0, .4); + --td-font-gray-4: rgba(0, 0, 0, .26); + --td-brand-color: var(--td-brand-color-6); + --td-warning-color: var(--td-warning-color-5); + --td-error-color: var(--td-error-color-6); + --td-success-color: var(--td-success-color-5); + --td-brand-color-focus: var(--td-brand-color-1); + --td-brand-color-active: var(--td-brand-color-7); + --td-brand-color-disabled: var(--td-brand-color-3); + --td-brand-color-light: var(--td-brand-color-1); + --td-brand-color-light-active: var(--td-brand-color-2); + --td-warning-color-focus: var(--td-warning-color-2); + --td-warning-color-active: var(--td-warning-color-4); + --td-warning-color-disabled: var(--td-warning-color-3); + --td-warning-color-light: var(--td-warning-color-1); + --td-warning-color-light-active: var(--td-warning-color-2); + --td-error-color-focus: var(--td-error-color-2); + --td-error-color-active: var(--td-error-color-5); + --td-error-color-disabled: var(--td-error-color-3); + --td-error-color-light: var(--td-error-color-1); + --td-error-color-light-active: var(--td-error-color-2); + --td-success-color-focus: var(--td-success-color-2); + --td-success-color-active: var(--td-success-color-4); + --td-success-color-disabled: var(--td-success-color-3); + --td-success-color-light: var(--td-success-color-1); + --td-success-color-light-active: var(--td-success-color-2); + --td-mask-active: rgba(0, 0, 0, .4); + --td-mask-disabled: rgba(0, 0, 0, .6); + --td-bg-color-page: var(--td-gray-color-14); + --td-bg-color-container: var(--td-gray-color-13); + --td-bg-color-secondarycontainer: var(--td-gray-color-12); + --td-bg-color-component: var(--td-gray-color-11); + --td-bg-color-container-active: var(--td-gray-color-12); + --td-bg-color-secondarycontainer-active: var(--td-gray-color-11); + --td-bg-color-component-active: var(--td-gray-color-10); + --td-bg-color-component-disabled: var(--td-gray-color-12); + --td-bg-color-specialcomponent: transparent; + --td-text-color-primary: var(--td-font-white-1); + --td-text-color-secondary: var(--td-font-white-2); + --td-text-color-placeholder: var(--td-font-white-3); + --td-text-color-disabled: var(--td-font-white-4); + --td-text-color-anti: var(--td-font-white-1); + --td-text-color-brand: var(--td-brand-color-8); + --td-text-color-link: var(--td-brand-color-8); + --td-border-level-1-color: var(--td-gray-color-11); + --td-component-stroke: var(--td-gray-color-11); + --td-border-level-2-color: var(--td-gray-color-9); + --td-component-border: var(--td-gray-color-9); + --td-shadow-1: 0 1px 6px rgba(0, 0, 0, 0.05),0 3px 4px rgba(0, 0, 0, 0.04),0 1px 2px -1px rgba(0, 0, 0, 0.08); + --td-shadow-2: 0 3px 10px 2px rgba(0, 0, 0, 0.04),0 6px 8px rgba(0, 0, 0, 0.05),0 4px 4px -2px rgba(0, 0, 0, 0.08); + --td-shadow-3: 0 4px 18px 5px rgba(0, 0, 0, 0.05),0 10px 9px 2px rgba(0, 0, 0, 0.04),0 3px 5px -3px rgba(0, 0, 0, 0.08); + --td-shadow-inset-top: inset 0 .5px 0 #5e5e5e; + --td-shadow-inset-right: inset .5px 0 0 #5e5e5e; + --td-shadow-inset-bottom: inset 0 -.5px 0 #5e5e5e; + --td-shadow-inset-left: inset -.5px 0 0 #5e5e5e; + --td-table-shadow-color: rgba(0, 0, 0, .55); + --td-scrollbar-color: rgba(255, 255, 255, .1); + --td-scroll-track-color: #333; +} + +:root { + --td-font-family: pingfang sc, microsoft yahei, arial regular; + --td-font-family-medium: pingfang sc, microsoft yahei, arial medium; + --td-font-size-link-small: 12px; + --td-font-size-link-medium: 14px; + --td-font-size-link-large: 16px; + --td-font-size-mark-extraSmall: 10px; + --td-font-size-mark-small: 12px; + --td-font-size-mark-medium: 14px; + --td-font-size-mark-large: 16px; + --td-font-size-body-extraSmall: 10px; + --td-font-size-body-small: 12px; + --td-font-size-body-medium: 14px; + --td-font-size-body-large: 16px; + --td-font-size-title-small: 14px; + --td-font-size-title-medium: 16px; + --td-font-size-title-large: 18px; + --td-font-size-title-extraLarge: 20px; + --td-font-size-headline-small: 24px; + --td-font-size-headline-medium: 28px; + --td-font-size-headline-large: 36px; + --td-font-size-display-medium: 48px; + --td-font-size-display-large: 64px; + --td-font-size: 10px; + --td-font-size-xs: var(--td-font-size-body-extraSmall); + --td-font-size-s: var(--td-font-size-body-small); + --td-font-size-base: var(--td-font-size-title-small); + --td-font-size-m: var(--td-font-size-title-medium); + --td-font-size-l: var(--td-font-size-title-large); + --td-font-size-xl: var(--td-font-size-title-extraLarge); + --td-font-size-xxl: var(--td-font-size-headline-large); + --td-radius-small: 4px; + --td-radius-default: 6px; + --td-radius-large: 18px; + --td-radius-extraLarge: 24px; + --td-radius-round: 999px; + --td-radius-circle: 50%; +} diff --git a/src/types/Customer.ts b/src/types/Customer.ts new file mode 100644 index 0000000..73f0c97 --- /dev/null +++ b/src/types/Customer.ts @@ -0,0 +1,60 @@ +import type { Attachment, Model, User } from "timi-web"; + +export type CustomerGender = "MALE" | "FEMALE"; + +export type BodyAreaValue = { + selectedCodeList: string[]; +}; + +export type Customer = { + code?: string; + name?: string; + gender?: CustomerGender; + age?: number; + telephone?: string; + address?: string; + remark?: string; + disease?: string; + conditioningPart?: BodyAreaValue; + introducerCustomerId?: string; + creatorUserId?: string; + lastSignInAt?: number; + introducerCustomer?: Customer; + creatorUser?: Partial; + invitedCount?: number; + attachmentList?: Attachment[]; + attachmentIdList?: string[]; +} & Model; + +export type CustomerSearchReq = { + keyword?: string; + introducerCustomerId?: string; +}; + +export type CustomerTrendStatReq = { + beginCreatedAt: number; + endCreatedAt: number; +}; + +export type CustomerDailyStatView = { + dateValue?: number; + newCustomerCount?: number; + totalCustomerCount?: number; +}; + +export type CustomerGenderStatView = { + genderCode?: CustomerGender | "UNKNOWN"; + count?: number; +}; + +export type CustomerInviteUpdateReq = { + customerId: string; + introducerCustomerId?: string; +}; + +export type QuickRegisterReq = { + customerCode: string; + registrationEventId: string; + remark?: string; + attachmentIdList?: string[]; +}; diff --git a/src/types/GaoUser.ts b/src/types/GaoUser.ts new file mode 100644 index 0000000..627f194 --- /dev/null +++ b/src/types/GaoUser.ts @@ -0,0 +1,10 @@ +import type { Model, Role, User } from "timi-web"; + +export type GaoUser = { + userId?: string; + enabled?: boolean; + remark?: string; + user?: Partial; + roleList?: Array; + roleIdList?: string[]; +} & Model; diff --git a/src/types/RegistrationEvent.ts b/src/types/RegistrationEvent.ts new file mode 100644 index 0000000..0471d4e --- /dev/null +++ b/src/types/RegistrationEvent.ts @@ -0,0 +1,18 @@ +import type { Model } from "timi-web"; + +export type RegistrationEventStatus = "ACTIVE" | "INACTIVE" | "DELETED"; + +export type RegistrationLimitType = "NONE" | "DAILY_HALF_DAY" | "NATURAL_DAY" | "INTERVAL_HOUR" | "NATURAL_MONTH" | "TOTAL_LIMIT"; + +export type RegistrationEvent = { + name: string; + description?: string; + color?: string; + status?: RegistrationEventStatus; + enabled?: boolean; + requirePhoto?: boolean; + limitType?: RegistrationLimitType; + limitValue?: number; + sort?: number; + roleCodeList?: string[]; +} & Model; diff --git a/src/types/RegistrationEventRecord.ts b/src/types/RegistrationEventRecord.ts new file mode 100644 index 0000000..7aa87f0 --- /dev/null +++ b/src/types/RegistrationEventRecord.ts @@ -0,0 +1,81 @@ +import type { Attachment, Model, User } from "timi-web"; +import type { Customer } from "@/types/Customer"; +import type { RegistrationEvent } from "@/types/RegistrationEvent"; + +export type RegistrationEventRecord = { + customerId?: string; + registrationEventId?: string; + operatorUserId?: string; + remark?: string; + registeredAt?: number; + customer?: Customer; + registrationEvent?: RegistrationEvent; + operator?: Partial; + attachmentList?: Array>; + attachmentIdList?: string[]; +} & Model; + +export type RegistrationEventRecordListItemView = { + id?: string; + customerId?: string; + customerName?: string; + customerPhotoAttachmentId?: string; + registrationEventId?: string; + registrationEventName?: string; + registeredAt?: number; +}; + +export type RegistrationEventRecordRangeReq = { + customerId?: string; + registrationEventId?: string; + registrationEventIdList?: string[]; + keyword?: string; + beginRegisteredAt: number; + endRegisteredAt: number; +}; + +export type RegistrationEventRecordStatReq = { + customerId?: string; + beginRegisteredAt: number; + endRegisteredAt: number; +}; + +export type RegistrationEventRecordTrendStatReq = { + customerId?: string; + registrationEventId: string; + beginRegisteredAt: number; + endRegisteredAt: number; +}; + +export type CustomerRegisterStatView = { + customerId?: string; + customerName?: string; + registrationEventId?: string; + registrationEventName?: string; + count?: number; + latestRegisteredAt?: number; +}; + +export type RegistrationEventRecordDailyStatView = { + dateValue?: number; + dailyCount?: number; + totalCount?: number; +}; + +export type RegistrationEventRecordCalendarView = { + id?: string; + customerId?: string; + customerCode?: string; + customerName?: string; + registrationEventId?: string; + registeredAt?: number; +}; + +export type RegistrationEventRecordCreateReq = { + customerId?: string; + customerCode?: string; + registrationEventId: string; + remark?: string; + registeredAt?: number; + attachmentIdList?: string[]; +}; diff --git a/src/types/browser-image-compression.d.ts b/src/types/browser-image-compression.d.ts new file mode 100644 index 0000000..049a8ea --- /dev/null +++ b/src/types/browser-image-compression.d.ts @@ -0,0 +1,18 @@ +declare module "browser-image-compression" { + export interface ImageCompressionOptions { + alwaysKeepResolution?: boolean; + exifOrientation?: number; + fileType?: string; + initialQuality?: number; + libURL?: string; + maxIteration?: number; + maxSizeMB?: number; + maxWidthOrHeight?: number; + onProgress?: (progress: number) => void; + preserveExif?: boolean; + signal?: AbortSignal; + useWebWorker?: boolean; + } + + export default function imageCompression(file: File, options: ImageCompressionOptions): Promise; +} diff --git a/src/utils/customer.ts b/src/utils/customer.ts new file mode 100644 index 0000000..51ffa09 --- /dev/null +++ b/src/utils/customer.ts @@ -0,0 +1,32 @@ +import { AttachmentAPI } from "timi-web"; +import type { BodyAreaValue, Customer } from "@/types/Customer"; + +export function getCustomerPhotoURL(customer?: Customer): string { + const attachment = customer?.attachmentList?.find(item => item.attachType === "PHOTO") || customer?.attachmentList?.[0]; + if (!attachment?.id) { + return ""; + } + + return AttachmentAPI.getReadURL(attachment.id); +} + +export function createBodyAreaValue(): BodyAreaValue { + return { + selectedCodeList: [] + }; +} + +export function normalizeBodyAreaValue(value: unknown): BodyAreaValue { + if (!value || typeof value !== "object") { + return createBodyAreaValue(); + } + + const raw = value as Partial; + if (!Array.isArray(raw.selectedCodeList)) { + return createBodyAreaValue(); + } + + return { + selectedCodeList: raw.selectedCodeList.map(item => String(item).trim()).filter(Boolean) + }; +} diff --git a/src/utils/gaoPermission.ts b/src/utils/gaoPermission.ts new file mode 100644 index 0000000..f11ebdc --- /dev/null +++ b/src/utils/gaoPermission.ts @@ -0,0 +1,78 @@ +export const gaoPermissionCodes = { + customer: { + create: "GAO:CUSTOMER:CREATE", + read: "GAO:CUSTOMER:READ", + update: "GAO:CUSTOMER:UPDATE", + delete: "GAO:CUSTOMER:DELETE" + }, + registrationEvent: { + create: "GAO:REGISTRATION_EVENT:CREATE", + read: "GAO:REGISTRATION_EVENT:READ", + update: "GAO:REGISTRATION_EVENT:UPDATE", + delete: "GAO:REGISTRATION_EVENT:DELETE" + }, + registrationEventRecord: { + create: "GAO:REGISTRATION_EVENT_RECORD:CREATE", + read: "GAO:REGISTRATION_EVENT_RECORD:READ", + update: "GAO:REGISTRATION_EVENT_RECORD:UPDATE", + delete: "GAO:REGISTRATION_EVENT_RECORD:DELETE" + }, + stat: { + read: "GAO:STAT:READ" + }, + user: { + create: "GAO:USER:CREATE", + read: "GAO:USER:READ", + update: "GAO:USER:UPDATE", + delete: "GAO:USER:DELETE" + }, + qrCode: { + create: "GAO:QR_CODE:CREATE" + } +} as const; + +export const corePermissionCodes = { + role: { + create: "CORE:ROLE:CREATE", + read: "CORE:ROLE:READ", + update: "CORE:ROLE:UPDATE", + delete: "CORE:ROLE:DELETE" + }, + permission: { + create: "CORE:PERMISSION:CREATE", + read: "CORE:PERMISSION:READ", + update: "CORE:PERMISSION:UPDATE", + delete: "CORE:PERMISSION:DELETE" + }, + rolePermission: { + create: "CORE:ROLE_PERMISSION:CREATE", + read: "CORE:ROLE_PERMISSION:READ", + delete: "CORE:ROLE_PERMISSION:DELETE" + }, + roleRelation: { + create: "CORE:ROLE_RELATION:CREATE", + read: "CORE:ROLE_RELATION:READ", + delete: "CORE:ROLE_RELATION:DELETE" + }, + userRole: { + create: "CORE:USER_ROLE:CREATE", + read: "CORE:USER_ROLE:READ", + delete: "CORE:USER_ROLE:DELETE" + } +} as const; + +export const coreRoleCodes = { + admin: "CORE:ADMIN", + userRoleAdmin: "CORE:USER_ROLE_ADMIN" +} as const; + +export const permissionManagementRoleAccess = { + value: [ + coreRoleCodes.admin, + coreRoleCodes.userRoleAdmin + ], + mode: "or" +} as const; + +export type GaoPermissionCodes = typeof gaoPermissionCodes; +export type CorePermissionCodes = typeof corePermissionCodes; diff --git a/src/utils/gaoRole.ts b/src/utils/gaoRole.ts new file mode 100644 index 0000000..5b91003 --- /dev/null +++ b/src/utils/gaoRole.ts @@ -0,0 +1,70 @@ +import type { Role } from "@/store/permissionSettingsStore"; +import type { GaoUser } from "@/types/GaoUser"; + +type GaoUserRole = NonNullable[number]; + +function buildRoleCode(role: Role): string { + return role.moduleCode && !role.code.includes(":") ? `${role.moduleCode}:${role.code}` : role.code; +} + +function getBareRoleCode(code: string): string { + const codePartList = code.split(":"); + return codePartList[codePartList.length - 1] || code; +} + +function findRole(role: GaoUserRole, roleList: Role[]): Role | undefined { + if (typeof role === "string") { + return roleList.find(roleItem => roleItem.code === role || buildRoleCode(roleItem) === role); + } + return roleList.find(roleItem => roleItem.id === role.id || roleItem.code === role.code || buildRoleCode(roleItem) === role.code); +} + +function appendCompatibleRoleCode(roleCodeSet: Set, code: string): void { + if (!code) { + return; + } + + roleCodeSet.add(code); + roleCodeSet.add(getBareRoleCode(code)); +} + +export function getGaoRoleName(role: GaoUserRole | undefined, roleList: Role[]): string { + if (!role) { + return "未配置角色"; + } + + const fullRole = findRole(role, roleList); + if (fullRole) { + return fullRole.name || fullRole.code || "未配置角色"; + } + + return typeof role === "string" ? getBareRoleCode(role) : role.name || role.code || "未配置角色"; +} + +export function buildEffectiveRoleCodeSet(user: GaoUser, roleList: Role[]): Set { + const roleCodeSet = new Set(); + for (const role of user.roleList || []) { + const fullRole = findRole(role, roleList); + if (fullRole) { + appendRoleCode(roleCodeSet, fullRole, roleList, new Set()); + continue; + } + appendCompatibleRoleCode(roleCodeSet, typeof role === "string" ? role : role.code); + } + return roleCodeSet; +} + +function appendRoleCode(roleCodeSet: Set, role: Role, roleList: Role[], visitedRoleIds: Set): void { + if (!role.id || visitedRoleIds.has(role.id)) { + return; + } + + visitedRoleIds.add(role.id); + appendCompatibleRoleCode(roleCodeSet, buildRoleCode(role)); + for (const childRoleId of role.childRoleIdList) { + const childRole = roleList.find(item => item.id === childRoleId); + if (childRole) { + appendRoleCode(roleCodeSet, childRole, roleList, visitedRoleIds); + } + } +} diff --git a/src/utils/imageCompression.ts b/src/utils/imageCompression.ts new file mode 100644 index 0000000..fb75190 --- /dev/null +++ b/src/utils/imageCompression.ts @@ -0,0 +1,27 @@ +import imageCompression from "browser-image-compression"; + +const PHOTO_MAX_SIZE_MB = 300 / 1024; +const PHOTO_MAX_WIDTH_OR_HEIGHT = 1920; + +/** + * 压缩上传图片,统一限制到 300 KB。 + */ +export async function compressUploadImage(file: File): Promise { + return await imageCompression(file, { + maxSizeMB: PHOTO_MAX_SIZE_MB, + maxWidthOrHeight: PHOTO_MAX_WIDTH_OR_HEIGHT, + useWebWorker: true, + initialQuality: .86 + }); +} + +/** + * 批量压缩上传图片。 + */ +export async function compressUploadImageList(fileList: File[]): Promise { + const result: File[] = []; + for (const file of fileList) { + result.push(await compressUploadImage(file)); + } + return result; +} diff --git a/src/utils/managementQrCode.ts b/src/utils/managementQrCode.ts new file mode 100644 index 0000000..1fdee5b --- /dev/null +++ b/src/utils/managementQrCode.ts @@ -0,0 +1,278 @@ +import { BarcodeFormat, EncodeHintType, QRCodeWriter } from "@zxing/library"; + +export interface ManagementQrCodePage { + pageIndex: number; + codes: string[]; +} + +export interface DownloadManagementQrCodeOptions { + codes: string[]; + filePrefix: string; + maxCodeLength?: number; +} + +export interface PrintManagementQrCodeOptions { + codes: string[]; + maxCodeLength?: number; + title?: string; +} + +export interface ManagementQrCodeGrid { + rows: number; + columns: number; + pageSize: number; +} + +const pageWidth = 2480; +const pageHeight = 3508; +const pagePadding = 80; +const qrSize = 300; +const minCellGap = 18; +const codeFontSize = 34; +const codeTopGap = 3; +const gridLineWidth = 2; +const codeTextHorizontalPadding = 28; +const codeTextWidthRatio = .62; +const qrWriter = new QRCodeWriter(); +const qrEncodeHints = new Map([ + [EncodeHintType.ERROR_CORRECTION, "H"], + [EncodeHintType.CHARACTER_SET, "UTF-8"], + [EncodeHintType.MARGIN, 4] +]); + +export function calculateManagementQrCodeGrid(maxCodeLength = 0): ManagementQrCodeGrid { + const codeTextMinWidth = Math.ceil(maxCodeLength * codeFontSize * codeTextWidthRatio + codeTextHorizontalPadding); + const cellMinWidth = Math.max(qrSize + minCellGap, codeTextMinWidth + minCellGap); + const cellMinHeight = qrSize + codeTopGap + codeFontSize + minCellGap; + const columns = Math.max(1, Math.floor((pageWidth - pagePadding * 2) / cellMinWidth)); + const rows = Math.max(1, Math.floor((pageHeight - pagePadding * 2) / cellMinHeight)); + + return { + rows, + columns, + pageSize: rows * columns + }; +} + +export function splitManagementQrCodePages(codes: string[], maxCodeLength = 0): ManagementQrCodePage[] { + const pages: ManagementQrCodePage[] = []; + const pageSize = calculateManagementQrCodeGrid(maxCodeLength).pageSize; + + for (let index = 0; index < codes.length; index += pageSize) { + pages.push({ + pageIndex: pages.length, + codes: codes.slice(index, index + pageSize) + }); + } + + return pages; +} + +export async function downloadManagementQrCodeImages(options: DownloadManagementQrCodeOptions): Promise { + const pages = splitManagementQrCodePages(options.codes, options.maxCodeLength); + + for (const page of pages) { + const canvas = renderManagementQrCodePage(page.codes, options.maxCodeLength); + await downloadCanvas(canvas, `${options.filePrefix}-${String(page.pageIndex + 1).padStart(2, "0")}.png`); + } +} + +export async function printManagementQrCodeImages(options: PrintManagementQrCodeOptions): Promise { + const printWindow = window.open("", "_blank"); + if (!printWindow) { + throw new Error("浏览器阻止了打印窗口,请允许弹出窗口后重试"); + } + + const pages = splitManagementQrCodePages(options.codes, options.maxCodeLength); + const imageList = pages.map(page => renderManagementQrCodePage(page.codes, options.maxCodeLength).toDataURL("image/png")); + const title = options.title || "客户二维码打印"; + const imageHTML = imageList.map(src => `
客户二维码
`).join(""); + + printWindow.document.open(); + printWindow.document.write(` + + + + ${escapeHTML(title)} + + +${imageHTML} +`); + printWindow.document.close(); + await waitPrintImagesLoaded(printWindow.document); + printWindow.focus(); + printWindow.print(); +} + +function renderManagementQrCodePage(codes: string[], maxCodeLength = 0): HTMLCanvasElement { + const canvas = document.createElement("canvas"); + canvas.width = pageWidth; + canvas.height = pageHeight; + const grid = calculateManagementQrCodeGrid(maxCodeLength); + + const context = canvas.getContext("2d"); + if (!context) { + throw new Error("当前浏览器不支持 Canvas"); + } + + context.fillStyle = "#ffffff"; + context.fillRect(0, 0, pageWidth, pageHeight); + context.fillStyle = "#000000"; + context.font = `500 ${codeFontSize}px Arial, sans-serif`; + context.textAlign = "center"; + context.textBaseline = "top"; + + const cellWidth = (pageWidth - pagePadding * 2) / grid.columns; + const cellHeight = (pageHeight - pagePadding * 2) / grid.rows; + + drawGridLines(context, grid, cellWidth, cellHeight); + + codes.forEach((code, index) => { + const rowIndex = Math.floor(index / grid.columns); + const columnIndex = index % grid.columns; + const cellLeft = pagePadding + columnIndex * cellWidth; + const cellTop = pagePadding + rowIndex * cellHeight; + const qrLeft = Math.round(cellLeft + (cellWidth - qrSize) / 2); + const qrTop = Math.round(cellTop + (cellHeight - qrSize - codeTopGap - codeFontSize) / 2); + + drawQrCode(context, code, qrLeft, qrTop, qrSize); + context.fillStyle = "#000000"; + context.fillText(code, cellLeft + cellWidth / 2, qrTop + qrSize + codeTopGap); + }); + + return canvas; +} + +async function waitPrintImagesLoaded(document: Document): Promise { + const imageList = Array.from(document.images); + await Promise.all(imageList.map(image => { + if (image.complete) { + return Promise.resolve(); + } + + return new Promise((resolve, reject) => { + image.onload = () => resolve(); + image.onerror = () => reject(new Error("打印图片加载失败")); + }); + })); +} + +function escapeHTML(value: string): string { + return value + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll("\"", """); +} + +function drawGridLines(context: CanvasRenderingContext2D, grid: ManagementQrCodeGrid, cellWidth: number, cellHeight: number): void { + context.strokeStyle = "#d1d5db"; + context.lineWidth = gridLineWidth; + + for (let rowIndex = 0; rowIndex <= grid.rows; rowIndex++) { + const top = Math.round(pagePadding + rowIndex * cellHeight); + context.beginPath(); + context.moveTo(pagePadding, top); + context.lineTo(pageWidth - pagePadding, top); + context.stroke(); + } + + for (let columnIndex = 0; columnIndex <= grid.columns; columnIndex++) { + const left = Math.round(pagePadding + columnIndex * cellWidth); + context.beginPath(); + context.moveTo(left, pagePadding); + context.lineTo(left, pageHeight - pagePadding); + context.stroke(); + } +} + +function drawQrCode(context: CanvasRenderingContext2D, code: string, left: number, top: number, qrSize: number): void { + const matrix = qrWriter.encode(code, BarcodeFormat.QR_CODE, qrSize, qrSize, qrEncodeHints); + const width = matrix.getWidth(); + const height = matrix.getHeight(); + const sourceCanvas = document.createElement("canvas"); + sourceCanvas.width = width; + sourceCanvas.height = height; + const sourceContext = sourceCanvas.getContext("2d"); + + if (!sourceContext) { + throw new Error("当前浏览器不支持 Canvas"); + } + + sourceContext.fillStyle = "#ffffff"; + sourceContext.fillRect(0, 0, width, height); + sourceContext.fillStyle = "#000000"; + + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + if (matrix.get(x, y)) { + sourceContext.fillRect(x, y, 1, 1); + } + } + } + + context.fillStyle = "#ffffff"; + context.fillRect(left, top, qrSize, qrSize); + context.imageSmoothingEnabled = false; + context.drawImage(sourceCanvas, left, top, qrSize, qrSize); + context.imageSmoothingEnabled = true; +} + +async function downloadCanvas(canvas: HTMLCanvasElement, fileName: string): Promise { + const blob = await new Promise((resolve, reject) => { + canvas.toBlob(result => { + if (result) { + resolve(result); + return; + } + + reject(new Error("图片生成失败")); + }, "image/png"); + }); + const link = document.createElement("a"); + const url = URL.createObjectURL(blob); + + link.href = url; + link.download = fileName; + link.click(); + + await new Promise(resolve => { + window.setTimeout(resolve, 80); + }); + + URL.revokeObjectURL(url); +} diff --git a/src/utils/registrationEventRecord.ts b/src/utils/registrationEventRecord.ts new file mode 100644 index 0000000..4590cd0 --- /dev/null +++ b/src/utils/registrationEventRecord.ts @@ -0,0 +1,11 @@ +import { AttachmentAPI } from "timi-web"; +import type { RegistrationEventRecord } from "@/types/RegistrationEventRecord"; + +export function getRegistrationEventRecordPhotoURL(record?: RegistrationEventRecord): string { + const attachment = record?.attachmentList?.find(item => item.attachType === "PHOTO") || record?.attachmentList?.[0]; + if (!attachment?.id) { + return ""; + } + + return AttachmentAPI.getReadURL(attachment.id); +} diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..ae394ad --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,47 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": [ + "src/*" + ], + "timi-web": [ + "../timi-web/dist/src/index.d.ts" + ], + "timi-web/*": [ + "../timi-web/dist/src/*" + ], + "vue": [ + "node_modules/vue" + ], + "pinia": [ + "node_modules/pinia" + ], + "vue-router": [ + "node_modules/vue-router" + ] + }, + "lib": [ + "ES2021", + "DOM", + "DOM.Iterable" + ], + "types": [ + "vite/client", + "tdesign-mobile-vue/global" + ], + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": [ + "src/**/*.ts", + "src/**/*.d.ts", + "src/**/*.vue", + "auto-imports.d.ts", + "components.d.ts" + ] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a5b06bf --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..3945ae4 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "allowSyntheticDefaultImports": true + }, + "include": [ + "vite.config.ts", + ".eslintrc.cjs" + ] +} diff --git a/tsconfig.publish.json b/tsconfig.publish.json new file mode 100644 index 0000000..7e57b30 --- /dev/null +++ b/tsconfig.publish.json @@ -0,0 +1,25 @@ +{ + "extends": "./tsconfig.app.json", + "compilerOptions": { + "paths": { + "@/*": [ + "src/*" + ], + "timi-web": [ + "../timi-web/dist/src/index.d.ts" + ], + "timi-web/*": [ + "../timi-web/dist/src/*" + ], + "vue": [ + "node_modules/vue" + ], + "pinia": [ + "node_modules/pinia" + ], + "vue-router": [ + "node_modules/vue-router" + ] + } + } +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..313379d --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,88 @@ +import { fileURLToPath, URL } from "node:url"; +import { defineConfig, loadEnv } from "vite"; +import vue from "@vitejs/plugin-vue"; +import AutoImport from "unplugin-auto-import/vite"; +import Components from "unplugin-vue-components/vite"; +import { TDesignResolver } from "unplugin-vue-components/resolvers"; + +const localTimiWebRoot = fileURLToPath(new URL("../timi-web", import.meta.url)); +const projectRoot = fileURLToPath(new URL(".", import.meta.url)); + +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd(), ""); + const useLocalTimiWeb = env.VITE_USE_LOCAL_TIMI_WEB !== "false"; + const useLocalTimiWebSource = useLocalTimiWeb && mode === "development"; + const useLocalTimiWebPublish = useLocalTimiWeb && mode !== "development"; + return { + resolve: { + dedupe: ["vue", "pinia", "vue-router"], + alias: [ + { + find: "@", + replacement: fileURLToPath(new URL("./src", import.meta.url)) + }, + ...(useLocalTimiWeb + ? [ + { + find: /^timi-web$/, + replacement: useLocalTimiWebSource + ? fileURLToPath(new URL("../timi-web/src/index.ts", import.meta.url)) + : fileURLToPath(new URL("../timi-web/dist/timi-web.mjs", import.meta.url)) + }, + { + find: /^timi-web\/style\.css$/, + replacement: useLocalTimiWebPublish + ? fileURLToPath(new URL("../timi-web/dist/timi-web.css", import.meta.url)) + : fileURLToPath(new URL("../timi-web/src/assets/style/timi-web.less", import.meta.url)) + } + ] + : []) + ] + }, + plugins: [ + vue(), + AutoImport({ + imports: ["vue", "vue-router", "pinia"], + dts: "auto-imports.d.ts", + eslintrc: { + enabled: true, + filepath: "./.eslintrc-auto-import.json", + globalsPropValue: true + }, + resolvers: [ + TDesignResolver({ + library: "mobile-vue" + }) + ] + }), + Components({ + dirs: ["src/components", "src/layout"], + dts: "components.d.ts", + resolvers: [ + TDesignResolver({ + library: "mobile-vue" + }) + ] + }) + ], + css: { + preprocessorOptions: { + less: { + javascriptEnabled: true + } + } + }, + server: { + port: 84, + allowedHosts: [ + "gao.imyeyu.dev" + ], + fs: { + allow: [ + projectRoot, + localTimiWebRoot + ] + } + } + }; +});