commit 1cc427cbb049f314a376e248ab9393b30bd72e31 Author: molong Date: Sat Jan 10 10:04:08 2026 +0800 first commit diff --git a/.env b/.env new file mode 100644 index 0000000..e6b6f97 --- /dev/null +++ b/.env @@ -0,0 +1,22 @@ +# 【通用】环境变量 + +# 版本号 +VITE_VERSION = 3.0.1 + +# 端口号 +VITE_PORT = 3006 + +# 应用部署基础路径(如部署在子目录 /admin,则设置为 /admin/) +VITE_BASE_URL = / + +# 权限模式【 frontend 前端模式 / backend 后端模式 】 +VITE_ACCESS_MODE = frontend + +# 跨域请求时是否携带 Cookie(开启前需确保后端支持) +VITE_WITH_CREDENTIALS = false + +# 是否打开路由信息 +VITE_OPEN_ROUTE_INFO = false + +# 锁屏加密密钥 +VITE_LOCK_ENCRYPT_KEY = s3cur3k3y4adpro diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..10cc209 --- /dev/null +++ b/.env.development @@ -0,0 +1,13 @@ +# 【开发】环境变量 + +# 应用部署基础路径(如部署在子目录 /admin,则设置为 /admin/) +VITE_BASE_URL = / + +# API 请求基础路径(开发环境设置为 / 使用代理,生产环境设置为完整后端地址) +VITE_API_URL = / + +# 代理目标地址(开发环境通过 Vite 代理转发请求到此地址,解决跨域问题) +VITE_API_PROXY_URL = https://m1.apifoxmock.com/m1/6400575-6097373-default + +# Delete console +VITE_DROP_CONSOLE = false \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..89e0aaa --- /dev/null +++ b/.env.production @@ -0,0 +1,10 @@ +# 【生产】环境变量 + +# 应用部署基础路径(如部署在子目录 /admin,则设置为 /admin/) +VITE_BASE_URL = / + +# API 地址前缀 +VITE_API_URL = https://m1.apifoxmock.com/m1/6400575-6097373-default + +# Delete console +VITE_DROP_CONSOLE = true \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..866e8ee --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.html linguist-detectable=false +*.vue linguist-detectable=true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e48d2e9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local +.cursorrules + +# Auto-generated files +src/types/import/auto-imports.d.ts +src/types/import/components.d.ts +.auto-import.json diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..9e96efc --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +/node_modules/* +/dist/* +/src/main.ts \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..f3d6ad5 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,20 @@ +{ + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "semi": false, + "vueIndentScriptAndStyle": true, + "singleQuote": true, + "quoteProps": "as-needed", + "bracketSpacing": true, + "trailingComma": "none", + "bracketSameLine": false, + "jsxSingleQuote": false, + "arrowParens": "always", + "insertPragma": false, + "requirePragma": false, + "proseWrap": "never", + "htmlWhitespaceSensitivity": "strict", + "endOfLine": "auto", + "rangeStart": 0 +} diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 0000000..476ea45 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,9 @@ +dist +node_modules +public +.husky +.vscode + +src/components/Layout/MenuLeft/index.vue +src/assets +stats.html \ No newline at end of file diff --git a/.stylelintrc.cjs b/.stylelintrc.cjs new file mode 100644 index 0000000..9dbea0b --- /dev/null +++ b/.stylelintrc.cjs @@ -0,0 +1,82 @@ +module.exports = { + // 继承推荐规范配置 + extends: [ + 'stylelint-config-standard', + 'stylelint-config-recommended-scss', + 'stylelint-config-recommended-vue/scss', + 'stylelint-config-html/vue', + 'stylelint-config-recess-order' + ], + // 指定不同文件对应的解析器 + overrides: [ + { + files: ['**/*.{vue,html}'], + customSyntax: 'postcss-html' + }, + { + files: ['**/*.{css,scss}'], + customSyntax: 'postcss-scss' + } + ], + // 自定义规则 + rules: { + 'import-notation': 'string', // 指定导入CSS文件的方式("string"|"url") + 'selector-class-pattern': null, // 选择器类名命名规则 + 'custom-property-pattern': null, // 自定义属性命名规则 + 'keyframes-name-pattern': null, // 动画帧节点样式命名规则 + 'no-descending-specificity': null, // 允许无降序特异性 + 'no-empty-source': null, // 允许空样式 + 'property-no-vendor-prefix': null, // 允许属性前缀 + // 允许 global 、export 、deep伪类 + 'selector-pseudo-class-no-unknown': [ + true, + { + ignorePseudoClasses: ['global', 'export', 'deep'] + } + ], + // 允许未知属性 + 'property-no-unknown': [ + true, + { + ignoreProperties: [] + } + ], + // 允许未知规则 + 'at-rule-no-unknown': [ + true, + { + ignoreAtRules: [ + 'apply', + 'use', + 'mixin', + 'include', + 'extend', + 'each', + 'if', + 'else', + 'for', + 'while', + 'reference' + ] + } + ], + 'scss/at-rule-no-unknown': [ + true, + { + ignoreAtRules: [ + 'apply', + 'use', + 'mixin', + 'include', + 'extend', + 'each', + 'if', + 'else', + 'for', + 'while', + 'reference' + ] + } + ] + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..68322de --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 SuperManTT + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..bb317f6 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,83 @@ +// 从 URL 和路径模块中导入必要的功能 +import fs from 'fs' +import path, { dirname } from 'path' +import { fileURLToPath } from 'url' + +// 从 ESLint 插件中导入推荐配置 +import pluginJs from '@eslint/js' +import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended' +import pluginVue from 'eslint-plugin-vue' +import globals from 'globals' +import tseslint from 'typescript-eslint' + +// 使用 import.meta.url 获取当前模块的路径 +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) + +// 读取 .auto-import.json 文件的内容,并将其解析为 JSON 对象 +const autoImportConfig = JSON.parse( + fs.readFileSync(path.resolve(__dirname, '.auto-import.json'), 'utf-8') +) + +export default [ + // 指定文件匹配规则 + { + files: ['**/*.{js,mjs,cjs,ts,vue}'] + }, + // 指定全局变量和环境 + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.node + } + } + }, + // 扩展配置 + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + ...pluginVue.configs['flat/essential'], + // 自定义规则 + { + // 针对所有 JavaScript、TypeScript 和 Vue 文件应用以下配置 + files: ['**/*.{js,mjs,cjs,ts,vue}'], + + languageOptions: { + globals: { + // 合并从 autoImportConfig 中读取的全局变量配置 + ...autoImportConfig.globals, + // TypeScript 全局命名空间 + Api: 'readonly' + } + }, + rules: { + quotes: ['error', 'single'], // 使用单引号 + semi: ['error', 'never'], // 语句末尾不加分号 + 'no-var': 'error', // 要求使用 let 或 const 而不是 var + '@typescript-eslint/no-explicit-any': 'off', // 禁用 any 检查 + 'vue/multi-word-component-names': 'off', // 禁用对 Vue 组件名称的多词要求检查 + 'no-multiple-empty-lines': ['warn', { max: 1 }], // 不允许多个空行 + 'no-unexpected-multiline': 'error' // 禁止空余的多行 + } + }, + // vue 规则 + { + files: ['**/*.vue'], + languageOptions: { + parserOptions: { parser: tseslint.parser } + } + }, + // 忽略文件 + { + ignores: [ + 'node_modules', + 'dist', + 'public', + '.vscode/**', + 'src/assets/**', + 'src/utils/console.ts' + ] + }, + // prettier 配置 + eslintPluginPrettierRecommended +] diff --git a/index.html b/index.html new file mode 100644 index 0000000..ba51ce5 --- /dev/null +++ b/index.html @@ -0,0 +1,47 @@ + + + + Art Design Pro + + + + + + + + + + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..f1c5621 --- /dev/null +++ b/package.json @@ -0,0 +1,118 @@ +{ + "name": "art-design-pro", + "version": "0.0.0", + "type": "module", + "engines": { + "node": ">=20.19.0", + "pnpm": ">=8.8.0" + }, + "scripts": { + "dev": "vite --open", + "build": "vue-tsc --noEmit && vite build", + "serve": "vite preview", + "lint": "eslint", + "fix": "eslint --fix", + "lint:prettier": "prettier --write \"**/*.{js,cjs,ts,json,tsx,css,less,scss,vue,html,md}\"", + "lint:stylelint": "stylelint \"**/*.{css,scss,vue}\" --fix", + "lint:lint-staged": "lint-staged", + "prepare": "husky", + "commit": "git-cz", + "clean:dev": "tsx scripts/clean-dev.ts" + }, + "config": { + "commitizen": { + "path": "node_modules/cz-git" + } + }, + "lint-staged": { + "*.{js,ts,mjs,mts,tsx}": [ + "eslint --fix", + "prettier --write" + ], + "*.{cjs,json,jsonc}": [ + "prettier --write" + ], + "*.vue": [ + "eslint --fix", + "stylelint --fix --allow-empty-input", + "prettier --write" + ], + "*.{html,htm}": [ + "prettier --write" + ], + "*.{scss,css,less}": [ + "stylelint --fix --allow-empty-input", + "prettier --write" + ], + "*.{md,mdx}": [ + "prettier --write" + ], + "*.{yaml,yml}": [ + "prettier --write" + ] + }, + "dependencies": { + "@element-plus/icons-vue": "^2.3.2", + "@iconify/vue": "^5.0.0", + "@tailwindcss/vite": "^4.1.14", + "@vue/reactivity": "^3.5.21", + "@vueuse/core": "^13.9.0", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-vue": "next", + "axios": "^1.12.2", + "crypto-js": "^4.2.0", + "echarts": "^6.0.0", + "element-plus": "^2.11.2", + "file-saver": "^2.0.5", + "highlight.js": "^11.10.0", + "mitt": "^3.0.1", + "nprogress": "^0.2.0", + "ohash": "^2.0.11", + "pinia": "^3.0.3", + "pinia-plugin-persistedstate": "^4.3.0", + "qrcode.vue": "^3.6.0", + "tailwindcss": "^4.1.14", + "vue": "^3.5.21", + "vue-draggable-plus": "^0.6.0", + "vue-i18n": "^9.14.0", + "vue-router": "^4.5.1", + "xgplayer": "^3.0.20", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "@eslint/js": "^9.9.1", + "@types/node": "^24.0.5", + "@typescript-eslint/eslint-plugin": "^8.3.0", + "@typescript-eslint/parser": "^8.3.0", + "@vitejs/plugin-vue": "^6.0.1", + "@vue/compiler-sfc": "^3.0.5", + "eslint": "^9.9.1", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-vue": "^9.27.0", + "globals": "^15.9.0", + "lint-staged": "^15.5.2", + "prettier": "^3.5.3", + "rollup-plugin-visualizer": "^5.12.0", + "sass": "^1.81.0", + "stylelint": "^16.20.0", + "stylelint-config-html": "^1.1.0", + "stylelint-config-recess-order": "^4.6.0", + "stylelint-config-recommended-scss": "^14.1.0", + "stylelint-config-recommended-vue": "^1.5.0", + "stylelint-config-standard": "^36.0.1", + "terser": "^5.36.0", + "tsx": "^4.20.3", + "typescript": "~5.6.3", + "typescript-eslint": "^8.9.0", + "unplugin-auto-import": "^20.2.0", + "unplugin-element-plus": "^0.10.0", + "unplugin-vue-components": "^29.1.0", + "vite": "^7.1.5", + "vite-plugin-compression": "^0.5.1", + "vite-plugin-vue-devtools": "^7.7.6", + "vue-demi": "^0.14.9", + "vue-img-cutter": "^3.0.5", + "vue-tsc": "~2.1.6" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..401c518 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,10109 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + .: + dependencies: + '@element-plus/icons-vue': + specifier: ^2.3.2 + version: 2.3.2(vue@3.5.22(typescript@5.6.3)) + '@iconify/vue': + specifier: ^5.0.0 + version: 5.0.0(vue@3.5.22(typescript@5.6.3)) + '@tailwindcss/vite': + specifier: ^4.1.14 + version: 4.1.14(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + '@vue/reactivity': + specifier: ^3.5.21 + version: 3.5.22 + '@vueuse/core': + specifier: ^13.9.0 + version: 13.9.0(vue@3.5.22(typescript@5.6.3)) + '@wangeditor/editor': + specifier: ^5.1.23 + version: 5.1.23 + '@wangeditor/editor-for-vue': + specifier: next + version: 5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.22(typescript@5.6.3)) + axios: + specifier: ^1.12.2 + version: 1.12.2 + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 + echarts: + specifier: ^6.0.0 + version: 6.0.0 + element-plus: + specifier: ^2.11.2 + version: 2.11.4(vue@3.5.22(typescript@5.6.3)) + file-saver: + specifier: ^2.0.5 + version: 2.0.5 + highlight.js: + specifier: ^11.10.0 + version: 11.11.1 + mitt: + specifier: ^3.0.1 + version: 3.0.1 + nprogress: + specifier: ^0.2.0 + version: 0.2.0 + ohash: + specifier: ^2.0.11 + version: 2.0.11 + pinia: + specifier: ^3.0.3 + version: 3.0.3(typescript@5.6.3)(vue@3.5.22(typescript@5.6.3)) + pinia-plugin-persistedstate: + specifier: ^4.3.0 + version: 4.5.0(pinia@3.0.3(typescript@5.6.3)(vue@3.5.22(typescript@5.6.3))) + qrcode.vue: + specifier: ^3.6.0 + version: 3.6.0(vue@3.5.22(typescript@5.6.3)) + tailwindcss: + specifier: ^4.1.14 + version: 4.1.14 + vue: + specifier: ^3.5.21 + version: 3.5.22(typescript@5.6.3) + vue-draggable-plus: + specifier: ^0.6.0 + version: 0.6.0(@types/sortablejs@1.15.8) + vue-i18n: + specifier: ^9.14.0 + version: 9.14.5(vue@3.5.22(typescript@5.6.3)) + vue-router: + specifier: ^4.5.1 + version: 4.5.1(vue@3.5.22(typescript@5.6.3)) + xgplayer: + specifier: ^3.0.20 + version: 3.0.23(core-js@3.45.1) + xlsx: + specifier: ^0.18.5 + version: 0.18.5 + devDependencies: + '@commitlint/cli': + specifier: ^19.4.1 + version: 19.8.1(@types/node@24.8.1)(typescript@5.6.3) + '@commitlint/config-conventional': + specifier: ^19.4.1 + version: 19.8.1 + '@eslint/js': + specifier: ^9.9.1 + version: 9.36.0 + '@types/node': + specifier: ^24.0.5 + version: 24.8.1 + '@typescript-eslint/eslint-plugin': + specifier: ^8.3.0 + version: 8.44.1(@typescript-eslint/parser@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3))(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3) + '@typescript-eslint/parser': + specifier: ^8.3.0 + version: 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3) + '@vitejs/plugin-vue': + specifier: ^6.0.1 + version: 6.0.1(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.22(typescript@5.6.3)) + '@vue/compiler-sfc': + specifier: ^3.0.5 + version: 3.5.22 + commitizen: + specifier: ^4.3.0 + version: 4.3.1(@types/node@24.8.1)(typescript@5.6.3) + cz-git: + specifier: ^1.11.1 + version: 1.12.0 + eslint: + specifier: ^9.9.1 + version: 9.36.0(jiti@2.6.0) + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.2(eslint@9.36.0(jiti@2.6.0)) + eslint-plugin-prettier: + specifier: ^5.2.1 + version: 5.5.4(eslint-config-prettier@9.1.2(eslint@9.36.0(jiti@2.6.0)))(eslint@9.36.0(jiti@2.6.0))(prettier@3.6.2) + eslint-plugin-vue: + specifier: ^9.27.0 + version: 9.33.0(eslint@9.36.0(jiti@2.6.0)) + globals: + specifier: ^15.9.0 + version: 15.15.0 + husky: + specifier: ^9.1.5 + version: 9.1.7 + lint-staged: + specifier: ^15.5.2 + version: 15.5.2 + prettier: + specifier: ^3.5.3 + version: 3.6.2 + rollup-plugin-visualizer: + specifier: ^5.12.0 + version: 5.14.0(rollup@4.52.3) + sass: + specifier: ^1.81.0 + version: 1.93.2 + stylelint: + specifier: ^16.20.0 + version: 16.24.0(typescript@5.6.3) + stylelint-config-html: + specifier: ^1.1.0 + version: 1.1.0(postcss-html@1.8.0)(stylelint@16.24.0(typescript@5.6.3)) + stylelint-config-recess-order: + specifier: ^4.6.0 + version: 4.6.0(stylelint@16.24.0(typescript@5.6.3)) + stylelint-config-recommended-scss: + specifier: ^14.1.0 + version: 14.1.0(postcss@8.5.6)(stylelint@16.24.0(typescript@5.6.3)) + stylelint-config-recommended-vue: + specifier: ^1.5.0 + version: 1.6.1(postcss-html@1.8.0)(stylelint@16.24.0(typescript@5.6.3)) + stylelint-config-standard: + specifier: ^36.0.1 + version: 36.0.1(stylelint@16.24.0(typescript@5.6.3)) + terser: + specifier: ^5.36.0 + version: 5.44.0 + tsx: + specifier: ^4.20.3 + version: 4.20.6 + typescript: + specifier: ~5.6.3 + version: 5.6.3 + typescript-eslint: + specifier: ^8.9.0 + version: 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3) + unplugin-auto-import: + specifier: ^20.2.0 + version: 20.2.0(@vueuse/core@13.9.0(vue@3.5.22(typescript@5.6.3))) + unplugin-element-plus: + specifier: ^0.10.0 + version: 0.10.0 + unplugin-vue-components: + specifier: ^29.1.0 + version: 29.1.0(@babel/parser@7.28.4)(vue@3.5.22(typescript@5.6.3)) + vite: + specifier: ^7.1.5 + version: 7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + vite-plugin-compression: + specifier: ^0.5.1 + version: 0.5.1(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + vite-plugin-vue-devtools: + specifier: ^7.7.6 + version: 7.7.7(rollup@4.52.3)(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.22(typescript@5.6.3)) + vue-demi: + specifier: ^0.14.9 + version: 0.14.10(vue@3.5.22(typescript@5.6.3)) + vue-img-cutter: + specifier: ^3.0.5 + version: 3.0.7(typescript@5.6.3) + vue-tsc: + specifier: ~2.1.6 + version: 2.1.10(typescript@5.6.3) + +packages: + '@antfu/utils@0.7.10': + resolution: + { + integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww== + } + + '@babel/code-frame@7.27.1': + resolution: + { + integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + } + engines: { node: '>=6.9.0' } + + '@babel/compat-data@7.28.4': + resolution: + { + integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw== + } + engines: { node: '>=6.9.0' } + + '@babel/core@7.28.4': + resolution: + { + integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA== + } + engines: { node: '>=6.9.0' } + + '@babel/generator@7.28.3': + resolution: + { + integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw== + } + engines: { node: '>=6.9.0' } + + '@babel/helper-annotate-as-pure@7.27.3': + resolution: + { + integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg== + } + engines: { node: '>=6.9.0' } + + '@babel/helper-compilation-targets@7.27.2': + resolution: + { + integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== + } + engines: { node: '>=6.9.0' } + + '@babel/helper-create-class-features-plugin@7.28.3': + resolution: + { + integrity: sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg== + } + engines: { node: '>=6.9.0' } + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-globals@7.28.0': + resolution: + { + integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + } + engines: { node: '>=6.9.0' } + + '@babel/helper-member-expression-to-functions@7.27.1': + resolution: + { + integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA== + } + engines: { node: '>=6.9.0' } + + '@babel/helper-module-imports@7.27.1': + resolution: + { + integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== + } + engines: { node: '>=6.9.0' } + + '@babel/helper-module-transforms@7.28.3': + resolution: + { + integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw== + } + engines: { node: '>=6.9.0' } + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.27.1': + resolution: + { + integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw== + } + engines: { node: '>=6.9.0' } + + '@babel/helper-plugin-utils@7.27.1': + resolution: + { + integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== + } + engines: { node: '>=6.9.0' } + + '@babel/helper-replace-supers@7.27.1': + resolution: + { + integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA== + } + engines: { node: '>=6.9.0' } + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: + { + integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg== + } + engines: { node: '>=6.9.0' } + + '@babel/helper-string-parser@7.27.1': + resolution: + { + integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + } + engines: { node: '>=6.9.0' } + + '@babel/helper-validator-identifier@7.27.1': + resolution: + { + integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + } + engines: { node: '>=6.9.0' } + + '@babel/helper-validator-option@7.27.1': + resolution: + { + integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + } + engines: { node: '>=6.9.0' } + + '@babel/helpers@7.28.4': + resolution: + { + integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w== + } + engines: { node: '>=6.9.0' } + + '@babel/parser@7.28.4': + resolution: + { + integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg== + } + engines: { node: '>=6.0.0' } + hasBin: true + + '@babel/plugin-proposal-decorators@7.28.0': + resolution: + { + integrity: sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg== + } + engines: { node: '>=6.9.0' } + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-decorators@7.27.1': + resolution: + { + integrity: sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A== + } + engines: { node: '>=6.9.0' } + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.27.1': + resolution: + { + integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== + } + engines: { node: '>=6.9.0' } + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: + { + integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + } + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.27.1': + resolution: + { + integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w== + } + engines: { node: '>=6.9.0' } + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.27.1': + resolution: + { + integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ== + } + engines: { node: '>=6.9.0' } + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.28.0': + resolution: + { + integrity: sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg== + } + engines: { node: '>=6.9.0' } + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.28.4': + resolution: + { + integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ== + } + engines: { node: '>=6.9.0' } + + '@babel/template@7.27.2': + resolution: + { + integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== + } + engines: { node: '>=6.9.0' } + + '@babel/traverse@7.28.4': + resolution: + { + integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ== + } + engines: { node: '>=6.9.0' } + + '@babel/types@7.28.4': + resolution: + { + integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q== + } + engines: { node: '>=6.9.0' } + + '@cacheable/memoize@2.0.2': + resolution: + { + integrity: sha512-wPrr7FUiq3Qt4yQyda2/NcOLTJCFcQSU3Am2adP+WLy+sz93/fKTokVTHmtz+rjp4PD7ee0AEOeRVNN6IvIfsg== + } + + '@cacheable/memory@2.0.2': + resolution: + { + integrity: sha512-sJTITLfeCI1rg7P3ssaGmQryq235EGT8dXGcx6oZwX5NRnKq9IE6lddlllcOl+oXW+yaeTRddCjo0xrfU6ZySA== + } + + '@cacheable/utils@2.0.2': + resolution: + { + integrity: sha512-JTFM3raFhVv8LH95T7YnZbf2YoE9wEtkPPStuRF9a6ExZ103hFvs+QyCuYJ6r0hA9wRtbzgZtwUCoDWxssZd4Q== + } + + '@commitlint/cli@19.8.1': + resolution: + { + integrity: sha512-LXUdNIkspyxrlV6VDHWBmCZRtkEVRpBKxi2Gtw3J54cGWhLCTouVD/Q6ZSaSvd2YaDObWK8mDjrz3TIKtaQMAA== + } + engines: { node: '>=v18' } + hasBin: true + + '@commitlint/config-conventional@19.8.1': + resolution: + { + integrity: sha512-/AZHJL6F6B/G959CsMAzrPKKZjeEiAVifRyEwXxcT6qtqbPwGw+iQxmNS+Bu+i09OCtdNRW6pNpBvgPrtMr9EQ== + } + engines: { node: '>=v18' } + + '@commitlint/config-validator@19.8.1': + resolution: + { + integrity: sha512-0jvJ4u+eqGPBIzzSdqKNX1rvdbSU1lPNYlfQQRIFnBgLy26BtC0cFnr7c/AyuzExMxWsMOte6MkTi9I3SQ3iGQ== + } + engines: { node: '>=v18' } + + '@commitlint/config-validator@20.0.0': + resolution: + { + integrity: sha512-BeyLMaRIJDdroJuYM2EGhDMGwVBMZna9UiIqV9hxj+J551Ctc6yoGuGSmghOy/qPhBSuhA6oMtbEiTmxECafsg== + } + engines: { node: '>=v18' } + + '@commitlint/ensure@19.8.1': + resolution: + { + integrity: sha512-mXDnlJdvDzSObafjYrOSvZBwkD01cqB4gbnnFuVyNpGUM5ijwU/r/6uqUmBXAAOKRfyEjpkGVZxaDsCVnHAgyw== + } + engines: { node: '>=v18' } + + '@commitlint/execute-rule@19.8.1': + resolution: + { + integrity: sha512-YfJyIqIKWI64Mgvn/sE7FXvVMQER/Cd+s3hZke6cI1xgNT/f6ZAz5heND0QtffH+KbcqAwXDEE1/5niYayYaQA== + } + engines: { node: '>=v18' } + + '@commitlint/execute-rule@20.0.0': + resolution: + { + integrity: sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw== + } + engines: { node: '>=v18' } + + '@commitlint/format@19.8.1': + resolution: + { + integrity: sha512-kSJj34Rp10ItP+Eh9oCItiuN/HwGQMXBnIRk69jdOwEW9llW9FlyqcWYbHPSGofmjsqeoxa38UaEA5tsbm2JWw== + } + engines: { node: '>=v18' } + + '@commitlint/is-ignored@19.8.1': + resolution: + { + integrity: sha512-AceOhEhekBUQ5dzrVhDDsbMaY5LqtN8s1mqSnT2Kz1ERvVZkNihrs3Sfk1Je/rxRNbXYFzKZSHaPsEJJDJV8dg== + } + engines: { node: '>=v18' } + + '@commitlint/lint@19.8.1': + resolution: + { + integrity: sha512-52PFbsl+1EvMuokZXLRlOsdcLHf10isTPlWwoY1FQIidTsTvjKXVXYb7AvtpWkDzRO2ZsqIgPK7bI98x8LRUEw== + } + engines: { node: '>=v18' } + + '@commitlint/load@19.8.1': + resolution: + { + integrity: sha512-9V99EKG3u7z+FEoe4ikgq7YGRCSukAcvmKQuTtUyiYPnOd9a2/H9Ak1J9nJA1HChRQp9OA/sIKPugGS+FK/k1A== + } + engines: { node: '>=v18' } + + '@commitlint/load@20.0.0': + resolution: + { + integrity: sha512-WiNKO9fDPlLY90Rruw2HqHKcghrmj5+kMDJ4GcTlX1weL8K07Q6b27C179DxnsrjGCRAKVwFKyzxV4x+xDY28Q== + } + engines: { node: '>=v18' } + + '@commitlint/message@19.8.1': + resolution: + { + integrity: sha512-+PMLQvjRXiU+Ae0Wc+p99EoGEutzSXFVwQfa3jRNUZLNW5odZAyseb92OSBTKCu+9gGZiJASt76Cj3dLTtcTdg== + } + engines: { node: '>=v18' } + + '@commitlint/parse@19.8.1': + resolution: + { + integrity: sha512-mmAHYcMBmAgJDKWdkjIGq50X4yB0pSGpxyOODwYmoexxxiUCy5JJT99t1+PEMK7KtsCtzuWYIAXYAiKR+k+/Jw== + } + engines: { node: '>=v18' } + + '@commitlint/read@19.8.1': + resolution: + { + integrity: sha512-03Jbjb1MqluaVXKHKRuGhcKWtSgh3Jizqy2lJCRbRrnWpcM06MYm8th59Xcns8EqBYvo0Xqb+2DoZFlga97uXQ== + } + engines: { node: '>=v18' } + + '@commitlint/resolve-extends@19.8.1': + resolution: + { + integrity: sha512-GM0mAhFk49I+T/5UCYns5ayGStkTt4XFFrjjf0L4S26xoMTSkdCf9ZRO8en1kuopC4isDFuEm7ZOm/WRVeElVg== + } + engines: { node: '>=v18' } + + '@commitlint/resolve-extends@20.0.0': + resolution: + { + integrity: sha512-BA4vva1hY8y0/Hl80YDhe9TJZpRFMsUYzVxvwTLPTEBotbGx/gS49JlVvtF1tOCKODQp7pS7CbxCpiceBgp3Dg== + } + engines: { node: '>=v18' } + + '@commitlint/rules@19.8.1': + resolution: + { + integrity: sha512-Hnlhd9DyvGiGwjfjfToMi1dsnw1EXKGJNLTcsuGORHz6SS9swRgkBsou33MQ2n51/boIDrbsg4tIBbRpEWK2kw== + } + engines: { node: '>=v18' } + + '@commitlint/to-lines@19.8.1': + resolution: + { + integrity: sha512-98Mm5inzbWTKuZQr2aW4SReY6WUukdWXuZhrqf1QdKPZBCCsXuG87c+iP0bwtD6DBnmVVQjgp4whoHRVixyPBg== + } + engines: { node: '>=v18' } + + '@commitlint/top-level@19.8.1': + resolution: + { + integrity: sha512-Ph8IN1IOHPSDhURCSXBz44+CIu+60duFwRsg6HqaISFHQHbmBtxVw4ZrFNIYUzEP7WwrNPxa2/5qJ//NK1FGcw== + } + engines: { node: '>=v18' } + + '@commitlint/types@19.8.1': + resolution: + { + integrity: sha512-/yCrWGCoA1SVKOks25EGadP9Pnj0oAIHGpl2wH2M2Y46dPM2ueb8wyCVOD7O3WCTkaJ0IkKvzhl1JY7+uCT2Dw== + } + engines: { node: '>=v18' } + + '@commitlint/types@20.0.0': + resolution: + { + integrity: sha512-bVUNBqG6aznYcYjTjnc3+Cat/iBgbgpflxbIBTnsHTX0YVpnmINPEkSRWymT2Q8aSH3Y7aKnEbunilkYe8TybA== + } + engines: { node: '>=v18' } + + '@csstools/css-parser-algorithms@3.0.5': + resolution: + { + integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ== + } + engines: { node: '>=18' } + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-tokenizer@3.0.4': + resolution: + { + integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw== + } + engines: { node: '>=18' } + + '@csstools/media-query-list-parser@4.0.3': + resolution: + { + integrity: sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ== + } + engines: { node: '>=18' } + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/selector-specificity@5.0.0': + resolution: + { + integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw== + } + engines: { node: '>=18' } + peerDependencies: + postcss-selector-parser: ^7.0.0 + + '@ctrl/tinycolor@3.6.1': + resolution: + { + integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA== + } + engines: { node: '>=10' } + + '@dual-bundle/import-meta-resolve@4.2.1': + resolution: + { + integrity: sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg== + } + + '@element-plus/icons-vue@2.3.2': + resolution: + { + integrity: sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A== + } + peerDependencies: + vue: ^3.2.0 + + '@esbuild/aix-ppc64@0.25.10': + resolution: + { + integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw== + } + engines: { node: '>=18' } + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.10': + resolution: + { + integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg== + } + engines: { node: '>=18' } + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.10': + resolution: + { + integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w== + } + engines: { node: '>=18' } + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.10': + resolution: + { + integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg== + } + engines: { node: '>=18' } + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.10': + resolution: + { + integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA== + } + engines: { node: '>=18' } + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.10': + resolution: + { + integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg== + } + engines: { node: '>=18' } + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.10': + resolution: + { + integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg== + } + engines: { node: '>=18' } + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.10': + resolution: + { + integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA== + } + engines: { node: '>=18' } + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.10': + resolution: + { + integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ== + } + engines: { node: '>=18' } + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.10': + resolution: + { + integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg== + } + engines: { node: '>=18' } + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.10': + resolution: + { + integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ== + } + engines: { node: '>=18' } + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.10': + resolution: + { + integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg== + } + engines: { node: '>=18' } + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.10': + resolution: + { + integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA== + } + engines: { node: '>=18' } + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.10': + resolution: + { + integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA== + } + engines: { node: '>=18' } + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.10': + resolution: + { + integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA== + } + engines: { node: '>=18' } + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.10': + resolution: + { + integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew== + } + engines: { node: '>=18' } + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.10': + resolution: + { + integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA== + } + engines: { node: '>=18' } + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.10': + resolution: + { + integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A== + } + engines: { node: '>=18' } + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.10': + resolution: + { + integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig== + } + engines: { node: '>=18' } + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.10': + resolution: + { + integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw== + } + engines: { node: '>=18' } + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.10': + resolution: + { + integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw== + } + engines: { node: '>=18' } + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.10': + resolution: + { + integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag== + } + engines: { node: '>=18' } + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.10': + resolution: + { + integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ== + } + engines: { node: '>=18' } + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.10': + resolution: + { + integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw== + } + engines: { node: '>=18' } + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.10': + resolution: + { + integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw== + } + engines: { node: '>=18' } + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.10': + resolution: + { + integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw== + } + engines: { node: '>=18' } + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.9.0': + resolution: + { + integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g== + } + 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.1': + resolution: + { + integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + } + engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 } + + '@eslint/config-array@0.21.0': + resolution: + { + integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@eslint/config-helpers@0.3.1': + resolution: + { + integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@eslint/core@0.15.2': + resolution: + { + integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@eslint/eslintrc@3.3.1': + resolution: + { + integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@eslint/js@9.36.0': + resolution: + { + integrity: sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@eslint/object-schema@2.1.6': + resolution: + { + integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@eslint/plugin-kit@0.3.5': + resolution: + { + integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@floating-ui/core@1.7.3': + resolution: + { + integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w== + } + + '@floating-ui/dom@1.7.4': + resolution: + { + integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA== + } + + '@floating-ui/utils@0.2.10': + resolution: + { + integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ== + } + + '@humanfs/core@0.19.1': + resolution: + { + integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + } + engines: { node: '>=18.18.0' } + + '@humanfs/node@0.16.7': + resolution: + { + integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ== + } + 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' } + + '@iconify/types@2.0.0': + resolution: + { + integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg== + } + + '@iconify/vue@5.0.0': + resolution: + { + integrity: sha512-C+KuEWIF5nSBrobFJhT//JS87OZ++QDORB6f2q2Wm6fl2mueSTpFBeBsveK0KW9hWiZ4mNiPjsh6Zs4jjdROSg== + } + peerDependencies: + vue: '>=3' + + '@intlify/core-base@9.14.5': + resolution: + { + integrity: sha512-5ah5FqZG4pOoHjkvs8mjtv+gPKYU0zCISaYNjBNNqYiaITxW8ZtVih3GS/oTOqN8d9/mDLyrjD46GBApNxmlsA== + } + engines: { node: '>= 16' } + + '@intlify/message-compiler@9.14.5': + resolution: + { + integrity: sha512-IHzgEu61/YIpQV5Pc3aRWScDcnFKWvQA9kigcINcCBXN8mbW+vk9SK+lDxA6STzKQsVJxUPg9ACC52pKKo3SVQ== + } + engines: { node: '>= 16' } + + '@intlify/shared@9.14.5': + resolution: + { + integrity: sha512-9gB+E53BYuAEMhbCAxVgG38EZrk59sxBtv3jSizNL2hEWlgjBjAw1AwpLHtNaeda12pe6W20OGEa0TwuMSRbyQ== + } + engines: { node: '>= 16' } + + '@isaacs/fs-minipass@4.0.1': + resolution: + { + integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== + } + engines: { node: '>=18.0.0' } + + '@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== + } + + '@keyv/bigmap@1.0.2': + resolution: + { + integrity: sha512-KR03xkEZlAZNF4IxXgVXb+uNIVNvwdh8UwI0cnc7WI6a+aQcDp8GL80qVfeB4E5NpsKJzou5jU0r6yLSSbMOtA== + } + engines: { node: '>= 18' } + + '@keyv/serialize@1.1.1': + resolution: + { + integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA== + } + + '@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' } + + '@parcel/watcher-android-arm64@2.5.1': + resolution: + { + integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA== + } + engines: { node: '>= 10.0.0' } + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.5.1': + resolution: + { + integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw== + } + engines: { node: '>= 10.0.0' } + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.5.1': + resolution: + { + integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg== + } + engines: { node: '>= 10.0.0' } + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.5.1': + resolution: + { + integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ== + } + engines: { node: '>= 10.0.0' } + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.5.1': + resolution: + { + integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA== + } + engines: { node: '>= 10.0.0' } + cpu: [arm] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm-musl@2.5.1': + resolution: + { + integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q== + } + engines: { node: '>= 10.0.0' } + cpu: [arm] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + resolution: + { + integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w== + } + engines: { node: '>= 10.0.0' } + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm64-musl@2.5.1': + resolution: + { + integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg== + } + engines: { node: '>= 10.0.0' } + cpu: [arm64] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-x64-glibc@2.5.1': + resolution: + { + integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A== + } + engines: { node: '>= 10.0.0' } + cpu: [x64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-x64-musl@2.5.1': + resolution: + { + integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg== + } + engines: { node: '>= 10.0.0' } + cpu: [x64] + os: [linux] + libc: [musl] + + '@parcel/watcher-win32-arm64@2.5.1': + resolution: + { + integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw== + } + engines: { node: '>= 10.0.0' } + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.5.1': + resolution: + { + integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ== + } + engines: { node: '>= 10.0.0' } + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.5.1': + resolution: + { + integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA== + } + engines: { node: '>= 10.0.0' } + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.5.1': + resolution: + { + integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg== + } + engines: { node: '>= 10.0.0' } + + '@pkgr/core@0.2.9': + resolution: + { + integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== + } + engines: { node: ^12.20.0 || ^14.18.0 || >=16.0.0 } + + '@polka/url@1.0.0-next.29': + resolution: + { + integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww== + } + + '@rolldown/pluginutils@1.0.0-beta.29': + resolution: + { + integrity: sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q== + } + + '@rollup/pluginutils@5.3.0': + resolution: + { + integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q== + } + engines: { node: '>=14.0.0' } + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.52.3': + resolution: + { + integrity: sha512-h6cqHGZ6VdnwliFG1NXvMPTy/9PS3h8oLh7ImwR+kl+oYnQizgjxsONmmPSb2C66RksfkfIxEVtDSEcJiO0tqw== + } + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.52.3': + resolution: + { + integrity: sha512-wd+u7SLT/u6knklV/ifG7gr5Qy4GUbH2hMWcDauPFJzmCZUAJ8L2bTkVXC2niOIxp8lk3iH/QX8kSrUxVZrOVw== + } + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.52.3': + resolution: + { + integrity: sha512-lj9ViATR1SsqycwFkJCtYfQTheBdvlWJqzqxwc9f2qrcVrQaF/gCuBRTiTolkRWS6KvNxSk4KHZWG7tDktLgjg== + } + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.52.3': + resolution: + { + integrity: sha512-+Dyo7O1KUmIsbzx1l+4V4tvEVnVQqMOIYtrxK7ncLSknl1xnMHLgn7gddJVrYPNZfEB8CIi3hK8gq8bDhb3h5A== + } + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.52.3': + resolution: + { + integrity: sha512-u9Xg2FavYbD30g3DSfNhxgNrxhi6xVG4Y6i9Ur1C7xUuGDW3banRbXj+qgnIrwRN4KeJ396jchwy9bCIzbyBEQ== + } + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.52.3': + resolution: + { + integrity: sha512-5M8kyi/OX96wtD5qJR89a/3x5x8x5inXBZO04JWhkQb2JWavOWfjgkdvUqibGJeNNaz1/Z1PPza5/tAPXICI6A== + } + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.52.3': + resolution: + { + integrity: sha512-IoerZJ4l1wRMopEHRKOO16e04iXRDyZFZnNZKrWeNquh5d6bucjezgd+OxG03mOMTnS1x7hilzb3uURPkJ0OfA== + } + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.52.3': + resolution: + { + integrity: sha512-ZYdtqgHTDfvrJHSh3W22TvjWxwOgc3ThK/XjgcNGP2DIwFIPeAPNsQxrJO5XqleSlgDux2VAoWQ5iJrtaC1TbA== + } + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.52.3': + resolution: + { + integrity: sha512-NcViG7A0YtuFDA6xWSgmFb6iPFzHlf5vcqb2p0lGEbT+gjrEEz8nC/EeDHvx6mnGXnGCC1SeVV+8u+smj0CeGQ== + } + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.52.3': + resolution: + { + integrity: sha512-d3pY7LWno6SYNXRm6Ebsq0DJGoiLXTb83AIPCXl9fmtIQs/rXoS8SJxxUNtFbJ5MiOvs+7y34np77+9l4nfFMw== + } + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.52.3': + resolution: + { + integrity: sha512-3y5GA0JkBuirLqmjwAKwB0keDlI6JfGYduMlJD/Rl7fvb4Ni8iKdQs1eiunMZJhwDWdCvrcqXRY++VEBbvk6Eg== + } + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-gnu@4.52.3': + resolution: + { + integrity: sha512-AUUH65a0p3Q0Yfm5oD2KVgzTKgwPyp9DSXc3UA7DtxhEb/WSPfbG4wqXeSN62OG5gSo18em4xv6dbfcUGXcagw== + } + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-gnu@4.52.3': + resolution: + { + integrity: sha512-1makPhFFVBqZE+XFg3Dkq+IkQ7JvmUrwwqaYBL2CE+ZpxPaqkGaiWFEWVGyvTwZace6WLJHwjVh/+CXbKDGPmg== + } + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.52.3': + resolution: + { + integrity: sha512-OOFJa28dxfl8kLOPMUOQBCO6z3X2SAfzIE276fwT52uXDWUS178KWq0pL7d6p1kz7pkzA0yQwtqL0dEPoVcRWg== + } + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.52.3': + resolution: + { + integrity: sha512-jMdsML2VI5l+V7cKfZx3ak+SLlJ8fKvLJ0Eoa4b9/vCUrzXKgoKxvHqvJ/mkWhFiyp88nCkM5S2v6nIwRtPcgg== + } + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.52.3': + resolution: + { + integrity: sha512-tPgGd6bY2M2LJTA1uGq8fkSPK8ZLYjDjY+ZLK9WHncCnfIz29LIXIqUgzCR0hIefzy6Hpbe8Th5WOSwTM8E7LA== + } + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.52.3': + resolution: + { + integrity: sha512-BCFkJjgk+WFzP+tcSMXq77ymAPIxsX9lFJWs+2JzuZTLtksJ2o5hvgTdIcZ5+oKzUDMwI0PfWzRBYAydAHF2Mw== + } + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openharmony-arm64@4.52.3': + resolution: + { + integrity: sha512-KTD/EqjZF3yvRaWUJdD1cW+IQBk4fbQaHYJUmP8N4XoKFZilVL8cobFSTDnjTtxWJQ3JYaMgF4nObY/+nYkumA== + } + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.52.3': + resolution: + { + integrity: sha512-+zteHZdoUYLkyYKObGHieibUFLbttX2r+58l27XZauq0tcWYYuKUwY2wjeCN9oK1Um2YgH2ibd6cnX/wFD7DuA== + } + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.52.3': + resolution: + { + integrity: sha512-of1iHkTQSo3kr6dTIRX6t81uj/c/b15HXVsPcEElN5sS859qHrOepM5p9G41Hah+CTqSh2r8Bm56dL2z9UQQ7g== + } + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.52.3': + resolution: + { + integrity: sha512-s0hybmlHb56mWVZQj8ra9048/WZTPLILKxcvcq+8awSZmyiSUZjjem1AhU3Tf4ZKpYhK4mg36HtHDOe8QJS5PQ== + } + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.52.3': + resolution: + { + integrity: sha512-zGIbEVVXVtauFgl3MRwGWEN36P5ZGenHRMgNw88X5wEhEBpq0XrMEZwOn07+ICrwM17XO5xfMZqh0OldCH5VTA== + } + cpu: [x64] + os: [win32] + + '@sec-ant/readable-stream@0.4.1': + resolution: + { + integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg== + } + + '@sindresorhus/merge-streams@4.0.0': + resolution: + { + integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ== + } + engines: { node: '>=18' } + + '@sxzz/popperjs-es@2.11.7': + resolution: + { + integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ== + } + + '@tailwindcss/node@4.1.14': + resolution: + { + integrity: sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw== + } + + '@tailwindcss/oxide-android-arm64@4.1.14': + resolution: + { + integrity: sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ== + } + engines: { node: '>= 10' } + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.1.14': + resolution: + { + integrity: sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA== + } + engines: { node: '>= 10' } + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.1.14': + resolution: + { + integrity: sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw== + } + engines: { node: '>= 10' } + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.1.14': + resolution: + { + integrity: sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw== + } + engines: { node: '>= 10' } + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14': + resolution: + { + integrity: sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw== + } + engines: { node: '>= 10' } + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.14': + resolution: + { + integrity: sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w== + } + engines: { node: '>= 10' } + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-arm64-musl@4.1.14': + resolution: + { + integrity: sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ== + } + engines: { node: '>= 10' } + cpu: [arm64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-linux-x64-gnu@4.1.14': + resolution: + { + integrity: sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg== + } + engines: { node: '>= 10' } + cpu: [x64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-x64-musl@4.1.14': + resolution: + { + integrity: sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q== + } + engines: { node: '>= 10' } + cpu: [x64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-wasm32-wasi@4.1.14': + resolution: + { + integrity: sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ== + } + engines: { node: '>=14.0.0' } + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.14': + resolution: + { + integrity: sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA== + } + engines: { node: '>= 10' } + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.1.14': + resolution: + { + integrity: sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA== + } + engines: { node: '>= 10' } + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.1.14': + resolution: + { + integrity: sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw== + } + engines: { node: '>= 10' } + + '@tailwindcss/vite@4.1.14': + resolution: + { + integrity: sha512-BoFUoU0XqgCUS1UXWhmDJroKKhNXeDzD7/XwabjkDIAbMnc4ULn5e2FuEuBbhZ6ENZoSYzKlzvZ44Yr6EUDUSA== + } + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 + + '@transloadit/prettier-bytes@0.0.7': + resolution: + { + integrity: sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA== + } + + '@types/conventional-commits-parser@5.0.1': + resolution: + { + integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ== + } + + '@types/estree@1.0.8': + resolution: + { + integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + } + + '@types/event-emitter@0.3.5': + resolution: + { + integrity: sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ== + } + + '@types/json-schema@7.0.15': + resolution: + { + integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + } + + '@types/lodash-es@4.17.12': + resolution: + { + integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ== + } + + '@types/lodash@4.17.20': + resolution: + { + integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA== + } + + '@types/node@24.8.1': + resolution: + { + integrity: sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q== + } + + '@types/sortablejs@1.15.8': + resolution: + { + integrity: sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg== + } + + '@types/web-bluetooth@0.0.16': + resolution: + { + integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ== + } + + '@types/web-bluetooth@0.0.21': + resolution: + { + integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA== + } + + '@typescript-eslint/eslint-plugin@8.44.1': + resolution: + { + integrity: sha512-molgphGqOBT7t4YKCSkbasmu1tb1MgrZ2szGzHbclF7PNmOkSTQVHy+2jXOSnxvR3+Xe1yySHFZoqMpz3TfQsw== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + '@typescript-eslint/parser': ^8.44.1 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.44.1': + resolution: + { + integrity: sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.44.1': + resolution: + { + integrity: sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.44.1': + resolution: + { + integrity: sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@typescript-eslint/tsconfig-utils@8.44.1': + resolution: + { + integrity: sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.44.1': + resolution: + { + integrity: sha512-KdEerZqHWXsRNKjF9NYswNISnFzXfXNDfPxoTh7tqohU/PRIbwTmsjGK6V9/RTYWau7NZvfo52lgVk+sJh0K3g== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.44.1': + resolution: + { + integrity: sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@typescript-eslint/typescript-estree@8.44.1': + resolution: + { + integrity: sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.44.1': + resolution: + { + integrity: sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.44.1': + resolution: + { + integrity: sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@uppy/companion-client@2.2.2': + resolution: + { + integrity: sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og== + } + + '@uppy/core@2.3.4': + resolution: + { + integrity: sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ== + } + + '@uppy/store-default@2.1.1': + resolution: + { + integrity: sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ== + } + + '@uppy/utils@4.1.3': + resolution: + { + integrity: sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw== + } + + '@uppy/xhr-upload@2.1.3': + resolution: + { + integrity: sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ== + } + peerDependencies: + '@uppy/core': ^2.3.3 + + '@vitejs/plugin-vue@6.0.1': + resolution: + { + integrity: sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw== + } + engines: { node: ^20.19.0 || >=22.12.0 } + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 + vue: ^3.2.25 + + '@volar/language-core@2.4.23': + resolution: + { + integrity: sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ== + } + + '@volar/source-map@2.4.23': + resolution: + { + integrity: sha512-Z1Uc8IB57Lm6k7q6KIDu/p+JWtf3xsXJqAX/5r18hYOTpJyBn0KXUR8oTJ4WFYOcDzWC9n3IflGgHowx6U6z9Q== + } + + '@volar/typescript@2.4.23': + resolution: + { + integrity: sha512-lAB5zJghWxVPqfcStmAP1ZqQacMpe90UrP5RJ3arDyrhy4aCUQqmxPPLB2PWDKugvylmO41ljK7vZ+t6INMTag== + } + + '@vue/babel-helper-vue-transform-on@1.5.0': + resolution: + { + integrity: sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA== + } + + '@vue/babel-plugin-jsx@1.5.0': + resolution: + { + integrity: sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw== + } + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + + '@vue/babel-plugin-resolve-type@1.5.0': + resolution: + { + integrity: sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w== + } + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@vue/compiler-core@3.5.22': + resolution: + { + integrity: sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ== + } + + '@vue/compiler-dom@3.5.22': + resolution: + { + integrity: sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA== + } + + '@vue/compiler-sfc@3.5.22': + resolution: + { + integrity: sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ== + } + + '@vue/compiler-ssr@3.5.22': + resolution: + { + integrity: sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww== + } + + '@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.7': + resolution: + { + integrity: sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg== + } + + '@vue/devtools-core@7.7.7': + resolution: + { + integrity: sha512-9z9TLbfC+AjAi1PQyWX+OErjIaJmdFlbDHcD+cAMYKY6Bh5VlsAtCeGyRMrXwIlMEQPukvnWt3gZBLwTAIMKzQ== + } + peerDependencies: + vue: ^3.0.0 + + '@vue/devtools-kit@7.7.7': + resolution: + { + integrity: sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA== + } + + '@vue/devtools-shared@7.7.7': + resolution: + { + integrity: sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw== + } + + '@vue/language-core@2.1.10': + resolution: + { + integrity: sha512-DAI289d0K3AB5TUG3xDp9OuQ71CnrujQwJrQnfuZDwo6eGNf0UoRlPuaVNO+Zrn65PC3j0oB2i7mNmVPggeGeQ== + } + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/reactivity@3.5.22': + resolution: + { + integrity: sha512-f2Wux4v/Z2pqc9+4SmgZC1p73Z53fyD90NFWXiX9AKVnVBEvLFOWCEgJD3GdGnlxPZt01PSlfmLqbLYzY/Fw4A== + } + + '@vue/runtime-core@3.5.22': + resolution: + { + integrity: sha512-EHo4W/eiYeAzRTN5PCextDUZ0dMs9I8mQ2Fy+OkzvRPUYQEyK9yAjbasrMCXbLNhF7P0OUyivLjIy0yc6VrLJQ== + } + + '@vue/runtime-dom@3.5.22': + resolution: + { + integrity: sha512-Av60jsryAkI023PlN7LsqrfPvwfxOd2yAwtReCjeuugTJTkgrksYJJstg1e12qle0NarkfhfFu1ox2D+cQotww== + } + + '@vue/server-renderer@3.5.22': + resolution: + { + integrity: sha512-gXjo+ao0oHYTSswF+a3KRHZ1WszxIqO7u6XwNHqcqb9JfyIL/pbWrrh/xLv7jeDqla9u+LK7yfZKHih1e1RKAQ== + } + peerDependencies: + vue: 3.5.22 + + '@vue/shared@3.5.22': + resolution: + { + integrity: sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w== + } + + '@vueuse/core@13.9.0': + resolution: + { + integrity: sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA== + } + peerDependencies: + vue: ^3.5.0 + + '@vueuse/core@9.13.0': + resolution: + { + integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw== + } + + '@vueuse/metadata@13.9.0': + resolution: + { + integrity: sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg== + } + + '@vueuse/metadata@9.13.0': + resolution: + { + integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ== + } + + '@vueuse/shared@13.9.0': + resolution: + { + integrity: sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g== + } + peerDependencies: + vue: ^3.5.0 + + '@vueuse/shared@9.13.0': + resolution: + { + integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw== + } + + '@wangeditor/basic-modules@1.1.7': + resolution: + { + integrity: sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg== + } + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + lodash.throttle: ^4.1.1 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/code-highlight@1.0.3': + resolution: + { + integrity: sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw== + } + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/core@1.1.19': + resolution: + { + integrity: sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q== + } + peerDependencies: + '@uppy/core': ^2.1.1 + '@uppy/xhr-upload': ^2.0.3 + dom7: ^3.0.0 + is-hotkey: ^0.2.0 + lodash.camelcase: ^4.3.0 + lodash.clonedeep: ^4.5.0 + lodash.debounce: ^4.0.8 + lodash.foreach: ^4.5.0 + lodash.isequal: ^4.5.0 + lodash.throttle: ^4.1.1 + lodash.toarray: ^4.4.0 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/editor-for-vue@5.1.12': + resolution: + { + integrity: sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ== + } + peerDependencies: + '@wangeditor/editor': '>=5.1.0' + vue: ^3.0.5 + + '@wangeditor/editor@5.1.23': + resolution: + { + integrity: sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ== + } + + '@wangeditor/list-module@1.0.5': + resolution: + { + integrity: sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ== + } + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/table-module@1.1.4': + resolution: + { + integrity: sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w== + } + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + lodash.isequal: ^4.5.0 + lodash.throttle: ^4.1.1 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/upload-image-module@1.0.2': + resolution: + { + integrity: sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA== + } + peerDependencies: + '@uppy/core': ^2.0.3 + '@uppy/xhr-upload': ^2.0.3 + '@wangeditor/basic-modules': 1.x + '@wangeditor/core': 1.x + dom7: ^3.0.0 + lodash.foreach: ^4.5.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/video-module@1.1.4': + resolution: + { + integrity: sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg== + } + peerDependencies: + '@uppy/core': ^2.1.4 + '@uppy/xhr-upload': ^2.0.7 + '@wangeditor/core': 1.x + dom7: ^3.0.0 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + JSONStream@1.3.5: + resolution: + { + integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== + } + hasBin: true + + acorn-jsx@5.3.2: + resolution: + { + integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + } + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.15.0: + resolution: + { + integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + } + engines: { node: '>=0.4.0' } + hasBin: true + + adler-32@1.3.1: + resolution: + { + integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A== + } + engines: { node: '>=0.8' } + + ajv@6.12.6: + resolution: + { + integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + } + + ajv@8.17.1: + resolution: + { + integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + } + + alien-signals@0.2.2: + resolution: + { + integrity: sha512-cZIRkbERILsBOXTQmMrxc9hgpxglstn69zm+F1ARf4aPAzdAFYd6sBq87ErO0Fj3DV94tglcyHG5kQz9nDC/8A== + } + + ansi-escapes@4.3.2: + resolution: + { + integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + } + engines: { node: '>=8' } + + ansi-escapes@7.1.1: + resolution: + { + integrity: sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q== + } + engines: { node: '>=18' } + + ansi-regex@5.0.1: + resolution: + { + integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + } + engines: { node: '>=8' } + + ansi-regex@6.2.2: + resolution: + { + integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + } + engines: { node: '>=12' } + + ansi-styles@3.2.1: + resolution: + { + integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + } + engines: { node: '>=4' } + + ansi-styles@4.3.0: + resolution: + { + integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + } + engines: { node: '>=8' } + + ansi-styles@6.2.3: + resolution: + { + integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + } + engines: { node: '>=12' } + + anymatch@3.1.3: + resolution: + { + integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + } + engines: { node: '>= 8' } + + argparse@2.0.1: + resolution: + { + integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + } + + array-ify@1.0.0: + resolution: + { + integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== + } + + array-union@2.1.0: + resolution: + { + integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + } + engines: { node: '>=8' } + + astral-regex@2.0.0: + resolution: + { + integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + } + engines: { node: '>=8' } + + async-validator@4.2.5: + resolution: + { + integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg== + } + + asynckit@0.4.0: + resolution: + { + integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + } + + at-least-node@1.0.0: + resolution: + { + integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + } + engines: { node: '>= 4.0.0' } + + axios@1.12.2: + resolution: + { + integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw== + } + + balanced-match@1.0.2: + resolution: + { + integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + } + + balanced-match@2.0.0: + resolution: + { + integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA== + } + + base64-js@1.5.1: + resolution: + { + integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + } + + baseline-browser-mapping@2.8.8: + resolution: + { + integrity: sha512-be0PUaPsQX/gPWWgFsdD+GFzaoig5PXaUC1xLkQiYdDnANU8sMnHoQd8JhbJQuvTWrWLyeFN9Imb5Qtfvr4RrQ== + } + hasBin: true + + binary-extensions@2.3.0: + resolution: + { + integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + } + engines: { node: '>=8' } + + birpc@2.6.1: + resolution: + { + integrity: sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ== + } + + bl@4.1.0: + resolution: + { + integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + } + + boolbase@1.0.0: + resolution: + { + integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + } + + brace-expansion@1.1.12: + resolution: + { + integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + } + + brace-expansion@2.0.2: + resolution: + { + integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + } + + braces@3.0.3: + resolution: + { + integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + } + engines: { node: '>=8' } + + browserslist@4.26.2: + resolution: + { + integrity: sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A== + } + engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } + hasBin: true + + buffer-from@1.1.2: + resolution: + { + integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + } + + buffer@5.7.1: + resolution: + { + integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + } + + bundle-name@4.1.0: + resolution: + { + integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q== + } + engines: { node: '>=18' } + + cacheable@2.0.2: + resolution: + { + integrity: sha512-dWjhLx8RWnPsAWVKwW/wI6OJpQ/hSVb1qS0NUif8TR9vRiSwci7Gey8x04kRU9iAF+Rnbtex5Kjjfg/aB5w8Pg== + } + + cachedir@2.3.0: + resolution: + { + integrity: sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== + } + engines: { node: '>=6' } + + call-bind-apply-helpers@1.0.2: + resolution: + { + integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + } + engines: { node: '>= 0.4' } + + callsites@3.1.0: + resolution: + { + integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + } + engines: { node: '>=6' } + + caniuse-lite@1.0.30001745: + resolution: + { + integrity: sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ== + } + + cfb@1.2.2: + resolution: + { + integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA== + } + engines: { node: '>=0.8' } + + chalk@2.4.2: + resolution: + { + integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + } + engines: { node: '>=4' } + + chalk@4.1.2: + resolution: + { + integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + } + engines: { node: '>=10' } + + chalk@5.6.2: + resolution: + { + integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== + } + engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } + + chardet@0.7.0: + resolution: + { + integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + } + + chokidar@3.6.0: + resolution: + { + integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + } + engines: { node: '>= 8.10.0' } + + chokidar@4.0.3: + resolution: + { + integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + } + engines: { node: '>= 14.16.0' } + + chownr@3.0.0: + resolution: + { + integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== + } + engines: { node: '>=18' } + + cli-cursor@3.1.0: + resolution: + { + integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + } + engines: { node: '>=8' } + + cli-cursor@5.0.0: + resolution: + { + integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw== + } + engines: { node: '>=18' } + + cli-spinners@2.9.2: + resolution: + { + integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + } + engines: { node: '>=6' } + + cli-truncate@4.0.0: + resolution: + { + integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA== + } + engines: { node: '>=18' } + + cli-width@3.0.0: + resolution: + { + integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + } + engines: { node: '>= 10' } + + cliui@8.0.1: + resolution: + { + integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + } + engines: { node: '>=12' } + + clone@1.0.4: + resolution: + { + integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + } + engines: { node: '>=0.8' } + + codepage@1.15.0: + resolution: + { + integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA== + } + engines: { node: '>=0.8' } + + color-convert@1.9.3: + resolution: + { + integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + } + + color-convert@2.0.1: + resolution: + { + integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + } + engines: { node: '>=7.0.0' } + + color-name@1.1.3: + resolution: + { + integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + } + + color-name@1.1.4: + resolution: + { + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + } + + colord@2.9.3: + resolution: + { + integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== + } + + colorette@2.0.20: + resolution: + { + integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + } + + combined-stream@1.0.8: + resolution: + { + integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + } + engines: { node: '>= 0.8' } + + commander@13.1.0: + resolution: + { + integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw== + } + engines: { node: '>=18' } + + commander@2.20.3: + resolution: + { + integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + } + + commitizen@4.3.1: + resolution: + { + integrity: sha512-gwAPAVTy/j5YcOOebcCRIijn+mSjWJC+IYKivTu6aG8Ei/scoXgfsMRnuAk6b0GRste2J4NGxVdMN3ZpfNaVaw== + } + engines: { node: '>= 12' } + hasBin: true + + compare-func@2.0.0: + resolution: + { + integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA== + } + + compute-scroll-into-view@1.0.20: + resolution: + { + integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg== + } + + concat-map@0.0.1: + resolution: + { + integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + } + + confbox@0.1.8: + resolution: + { + integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + } + + confbox@0.2.2: + resolution: + { + integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ== + } + + conventional-changelog-angular@7.0.0: + resolution: + { + integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ== + } + engines: { node: '>=16' } + + conventional-changelog-conventionalcommits@7.0.2: + resolution: + { + integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w== + } + engines: { node: '>=16' } + + conventional-commit-types@3.0.0: + resolution: + { + integrity: sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg== + } + + conventional-commits-parser@5.0.0: + resolution: + { + integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA== + } + engines: { node: '>=16' } + hasBin: true + + convert-source-map@2.0.0: + resolution: + { + integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + } + + copy-anything@3.0.5: + resolution: + { + integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w== + } + engines: { node: '>=12.13' } + + core-js@3.45.1: + resolution: + { + integrity: sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg== + } + + cosmiconfig-typescript-loader@6.1.0: + resolution: + { + integrity: sha512-tJ1w35ZRUiM5FeTzT7DtYWAFFv37ZLqSRkGi2oeCK1gPhvaWjkAtfXvLmvE1pRfxxp9aQo6ba/Pvg1dKj05D4g== + } + engines: { node: '>=v18' } + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=9' + typescript: '>=5' + + cosmiconfig@9.0.0: + resolution: + { + integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== + } + engines: { node: '>=14' } + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + crc-32@1.2.2: + resolution: + { + integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + } + engines: { node: '>=0.8' } + hasBin: true + + cross-spawn@7.0.6: + resolution: + { + integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + } + engines: { node: '>= 8' } + + crypto-js@4.2.0: + resolution: + { + integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== + } + + css-functions-list@3.2.3: + resolution: + { + integrity: sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA== + } + engines: { node: '>=12 || >=16' } + + css-tree@3.1.0: + resolution: + { + integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w== + } + engines: { node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0 } + + cssesc@3.0.0: + resolution: + { + integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + } + engines: { node: '>=4' } + hasBin: true + + csstype@3.1.3: + resolution: + { + integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + } + + cz-conventional-changelog@3.3.0: + resolution: + { + integrity: sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw== + } + engines: { node: '>= 10' } + + cz-git@1.12.0: + resolution: + { + integrity: sha512-LaZ+8whPPUOo6Y0Zy4nIbf6JOleV3ejp41sT6N4RPKiKKA+ICWf4ueeIlxIO8b6JtdlDxRzHH/EcRji07nDxcg== + } + engines: { node: '>=v12.20.0' } + + d@1.0.2: + resolution: + { + integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== + } + engines: { node: '>=0.12' } + + danmu.js@1.1.13: + resolution: + { + integrity: sha512-knFd0/cB2HA4FFWiA7eB2suc5vCvoHdqio33FyyCSfP7C+1A+zQcTvnvwfxaZhrxsGj4qaQI2I8XiTqedRaVmg== + } + + dargs@8.1.0: + resolution: + { + integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw== + } + engines: { node: '>=12' } + + dayjs@1.11.18: + resolution: + { + integrity: sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA== + } + + de-indent@1.0.2: + resolution: + { + integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== + } + + debug@4.4.3: + resolution: + { + integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + } + engines: { node: '>=6.0' } + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + dedent@0.7.0: + resolution: + { + integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== + } + + deep-is@0.1.4: + resolution: + { + integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + } + + deep-pick-omit@1.2.1: + resolution: + { + integrity: sha512-2J6Kc/m3irCeqVG42T+SaUMesaK7oGWaedGnQQK/+O0gYc+2SP5bKh/KKTE7d7SJ+GCA9UUE1GRzh6oDe0EnGw== + } + + default-browser-id@5.0.0: + resolution: + { + integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA== + } + engines: { node: '>=18' } + + default-browser@5.2.1: + resolution: + { + integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg== + } + engines: { node: '>=18' } + + defaults@1.0.4: + resolution: + { + integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + } + + define-lazy-prop@2.0.0: + resolution: + { + integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + } + engines: { node: '>=8' } + + define-lazy-prop@3.0.0: + resolution: + { + integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + } + engines: { node: '>=12' } + + defu@6.1.4: + resolution: + { + integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg== + } + + delayed-stream@1.0.0: + resolution: + { + integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + } + engines: { node: '>=0.4.0' } + + delegate@3.2.0: + resolution: + { + integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== + } + + destr@2.0.5: + resolution: + { + integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA== + } + + detect-file@1.0.0: + resolution: + { + integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q== + } + engines: { node: '>=0.10.0' } + + detect-indent@6.1.0: + resolution: + { + integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== + } + engines: { node: '>=8' } + + detect-libc@1.0.3: + resolution: + { + integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + } + engines: { node: '>=0.10' } + hasBin: true + + detect-libc@2.1.2: + resolution: + { + integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + } + engines: { node: '>=8' } + + dir-glob@3.0.1: + resolution: + { + integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + } + engines: { node: '>=8' } + + dom-serializer@2.0.0: + resolution: + { + integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + } + + dom7@3.0.0: + resolution: + { + integrity: sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g== + } + + domelementtype@2.3.0: + resolution: + { + integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + } + + domhandler@5.0.3: + resolution: + { + integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + } + engines: { node: '>= 4' } + + domutils@3.2.2: + resolution: + { + integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== + } + + dot-prop@5.3.0: + resolution: + { + integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== + } + engines: { node: '>=8' } + + downloadjs@1.4.7: + resolution: + { + integrity: sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q== + } + + dunder-proto@1.0.1: + resolution: + { + integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + } + engines: { node: '>= 0.4' } + + echarts@6.0.0: + resolution: + { + integrity: sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ== + } + + electron-to-chromium@1.5.227: + resolution: + { + integrity: sha512-ITxuoPfJu3lsNWUi2lBM2PaBPYgH3uqmxut5vmBxgYvyI4AlJ6P3Cai1O76mOrkJCBzq0IxWg/NtqOrpu/0gKA== + } + + element-plus@2.11.4: + resolution: + { + integrity: sha512-sLq+Ypd0cIVilv8wGGMEGvzRVBBsRpJjnAS5PsI/1JU1COZXqzH3N1UYMUc/HCdvdjf6dfrBy80Sj7KcACsT7w== + } + peerDependencies: + vue: ^3.2.0 + + emoji-regex@10.5.0: + resolution: + { + integrity: sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg== + } + + emoji-regex@8.0.0: + resolution: + { + integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + } + + enhanced-resolve@5.18.3: + resolution: + { + integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww== + } + engines: { node: '>=10.13.0' } + + entities@4.5.0: + resolution: + { + integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + } + engines: { node: '>=0.12' } + + env-paths@2.2.1: + resolution: + { + integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + } + engines: { node: '>=6' } + + environment@1.1.0: + resolution: + { + integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== + } + engines: { node: '>=18' } + + error-ex@1.3.4: + resolution: + { + integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== + } + + error-stack-parser-es@0.1.5: + resolution: + { + integrity: sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg== + } + + 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-module-lexer@1.7.0: + resolution: + { + integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== + } + + es-object-atoms@1.1.1: + resolution: + { + integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + } + engines: { node: '>= 0.4' } + + es-set-tostringtag@2.1.0: + resolution: + { + integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + } + engines: { node: '>= 0.4' } + + es5-ext@0.10.64: + resolution: + { + integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg== + } + engines: { node: '>=0.10' } + + es6-iterator@2.0.3: + resolution: + { + integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + } + + es6-symbol@3.1.4: + resolution: + { + integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg== + } + engines: { node: '>=0.12' } + + esbuild@0.25.10: + resolution: + { + integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ== + } + engines: { node: '>=18' } + hasBin: true + + escalade@3.2.0: + resolution: + { + integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + } + engines: { node: '>=6' } + + escape-html@1.0.3: + resolution: + { + integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + } + + escape-string-regexp@1.0.5: + resolution: + { + integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + } + engines: { node: '>=0.8.0' } + + 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-config-prettier@9.1.2: + resolution: + { + integrity: sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ== + } + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-plugin-prettier@5.5.4: + resolution: + { + integrity: sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg== + } + engines: { node: ^14.18.0 || >=16.0.0 } + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + + 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-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@9.36.0: + resolution: + { + integrity: sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + esniff@2.0.1: + resolution: + { + integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== + } + engines: { node: '>=0.10' } + + espree@10.4.0: + resolution: + { + integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + 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.6.0: + resolution: + { + integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + } + 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' } + + event-emitter@0.3.5: + resolution: + { + integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + } + + eventemitter3@4.0.7: + resolution: + { + integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + } + + eventemitter3@5.0.1: + resolution: + { + integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + } + + execa@8.0.1: + resolution: + { + integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== + } + engines: { node: '>=16.17' } + + execa@9.6.0: + resolution: + { + integrity: sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw== + } + engines: { node: ^18.19.0 || >=20.5.0 } + + expand-tilde@2.0.2: + resolution: + { + integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw== + } + engines: { node: '>=0.10.0' } + + exsolve@1.0.7: + resolution: + { + integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw== + } + + ext@1.7.0: + resolution: + { + integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + } + + external-editor@3.1.0: + resolution: + { + integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + } + engines: { node: '>=4' } + + fast-deep-equal@3.1.3: + resolution: + { + integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + } + + fast-diff@1.3.0: + resolution: + { + integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + } + + 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.0: + resolution: + { + integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== + } + + fastest-levenshtein@1.0.16: + resolution: + { + integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + } + engines: { node: '>= 4.9.1' } + + fastq@1.19.1: + resolution: + { + integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + } + + fdir@6.5.0: + resolution: + { + integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + } + engines: { node: '>=12.0.0' } + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + figures@3.2.0: + resolution: + { + integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + } + engines: { node: '>=8' } + + figures@6.1.0: + resolution: + { + integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg== + } + engines: { node: '>=18' } + + file-entry-cache@10.1.4: + resolution: + { + integrity: sha512-5XRUFc0WTtUbjfGzEwXc42tiGxQHBmtbUG1h9L2apu4SulCGN3Hqm//9D6FAolf8MYNL7f/YlJl9vy08pj5JuA== + } + + file-entry-cache@8.0.0: + resolution: + { + integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + } + engines: { node: '>=16.0.0' } + + file-saver@2.0.5: + resolution: + { + integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== + } + + fill-range@7.1.1: + resolution: + { + integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + } + engines: { node: '>=8' } + + find-node-modules@2.1.3: + resolution: + { + integrity: sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg== + } + + find-root@1.1.0: + resolution: + { + integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + } + + find-up@5.0.0: + resolution: + { + integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + } + engines: { node: '>=10' } + + find-up@7.0.0: + resolution: + { + integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g== + } + engines: { node: '>=18' } + + findup-sync@4.0.0: + resolution: + { + integrity: sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ== + } + engines: { node: '>= 8' } + + flat-cache@4.0.1: + resolution: + { + integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + } + engines: { node: '>=16' } + + flat-cache@6.1.14: + resolution: + { + integrity: sha512-ExZSCSV9e7v/Zt7RzCbX57lY2dnPdxzU/h3UE6WJ6NtEMfwBd8jmi1n4otDEUfz+T/R+zxrFDpICFdjhD3H/zw== + } + + flatted@3.3.3: + resolution: + { + integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== + } + + follow-redirects@1.15.11: + resolution: + { + integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== + } + engines: { node: '>=4.0' } + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.4: + resolution: + { + integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow== + } + engines: { node: '>= 6' } + + frac@1.1.2: + resolution: + { + integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA== + } + engines: { node: '>=0.8' } + + fs-extra@10.1.0: + resolution: + { + integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + } + engines: { node: '>=12' } + + fs-extra@11.3.2: + resolution: + { + integrity: sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A== + } + engines: { node: '>=14.14' } + + fs-extra@9.1.0: + resolution: + { + integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + } + engines: { node: '>=10' } + + fs.realpath@1.0.0: + resolution: + { + integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + } + + 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== + } + + gensync@1.0.0-beta.2: + resolution: + { + integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + } + engines: { node: '>=6.9.0' } + + get-caller-file@2.0.5: + resolution: + { + integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + } + engines: { node: 6.* || 8.* || >= 10.* } + + get-east-asian-width@1.4.0: + resolution: + { + integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q== + } + engines: { node: '>=18' } + + 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' } + + get-stream@8.0.1: + resolution: + { + integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== + } + engines: { node: '>=16' } + + get-stream@9.0.1: + resolution: + { + integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA== + } + engines: { node: '>=18' } + + get-tsconfig@4.10.1: + resolution: + { + integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ== + } + + git-raw-commits@4.0.0: + resolution: + { + integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ== + } + engines: { node: '>=16' } + hasBin: true + + 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' } + + glob@7.2.3: + resolution: + { + integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + } + deprecated: Glob versions prior to v9 are no longer supported + + global-directory@4.0.1: + resolution: + { + integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q== + } + engines: { node: '>=18' } + + global-modules@1.0.0: + resolution: + { + integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + } + engines: { node: '>=0.10.0' } + + global-modules@2.0.0: + resolution: + { + integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + } + engines: { node: '>=6' } + + global-prefix@1.0.2: + resolution: + { + integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg== + } + engines: { node: '>=0.10.0' } + + global-prefix@3.0.0: + resolution: + { + integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + } + engines: { node: '>=6' } + + 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' } + + globals@15.15.0: + resolution: + { + integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg== + } + engines: { node: '>=18' } + + globby@11.1.0: + resolution: + { + integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + } + engines: { node: '>=10' } + + globjoin@0.1.4: + resolution: + { + integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg== + } + + 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== + } + + graphemer@1.4.0: + resolution: + { + integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + } + + has-flag@3.0.0: + resolution: + { + integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + } + engines: { node: '>=4' } + + 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.2: + resolution: + { + integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + } + engines: { node: '>= 0.4' } + + he@1.2.0: + resolution: + { + integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + } + hasBin: true + + highlight.js@11.11.1: + resolution: + { + integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w== + } + engines: { node: '>=12.0.0' } + + homedir-polyfill@1.0.3: + resolution: + { + integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + } + engines: { node: '>=0.10.0' } + + hookable@5.5.3: + resolution: + { + integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ== + } + + hookified@1.12.1: + resolution: + { + integrity: sha512-xnKGl+iMIlhrZmGHB729MqlmPoWBznctSQTYCpFKqNsCgimJQmithcW0xSQMMFzYnV2iKUh25alswn6epgxS0Q== + } + + html-tags@3.3.1: + resolution: + { + integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ== + } + engines: { node: '>=8' } + + html-void-elements@2.0.1: + resolution: + { + integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A== + } + + htmlparser2@8.0.2: + resolution: + { + integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== + } + + human-signals@5.0.0: + resolution: + { + integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== + } + engines: { node: '>=16.17.0' } + + human-signals@8.0.1: + resolution: + { + integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ== + } + engines: { node: '>=18.18.0' } + + husky@9.1.7: + resolution: + { + integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== + } + engines: { node: '>=18' } + hasBin: true + + i18next@20.6.1: + resolution: + { + integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A== + } + + iconv-lite@0.4.24: + resolution: + { + integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + } + engines: { node: '>=0.10.0' } + + ieee754@1.2.1: + resolution: + { + integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + } + + ignore@5.3.2: + resolution: + { + integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + } + engines: { node: '>= 4' } + + ignore@7.0.5: + resolution: + { + integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== + } + engines: { node: '>= 4' } + + immer@9.0.21: + resolution: + { + integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== + } + + immutable@5.1.3: + resolution: + { + integrity: sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg== + } + + import-fresh@3.3.1: + resolution: + { + integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== + } + engines: { node: '>=6' } + + import-meta-resolve@4.2.0: + resolution: + { + integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg== + } + + imurmurhash@0.1.4: + resolution: + { + integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + } + engines: { node: '>=0.8.19' } + + inflight@1.0.6: + resolution: + { + integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + } + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: + { + integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + } + + ini@1.3.8: + resolution: + { + integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + } + + ini@4.1.1: + resolution: + { + integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g== + } + engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + + inquirer@8.2.5: + resolution: + { + integrity: sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ== + } + engines: { node: '>=12.0.0' } + + is-arrayish@0.2.1: + resolution: + { + integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + } + + is-binary-path@2.1.0: + resolution: + { + integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + } + engines: { node: '>=8' } + + is-docker@2.2.1: + resolution: + { + integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + } + engines: { node: '>=8' } + hasBin: true + + is-docker@3.0.0: + resolution: + { + integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + hasBin: true + + is-extglob@2.1.1: + resolution: + { + integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + } + engines: { node: '>=0.10.0' } + + is-fullwidth-code-point@3.0.0: + resolution: + { + integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + } + engines: { node: '>=8' } + + is-fullwidth-code-point@4.0.0: + resolution: + { + integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + } + engines: { node: '>=12' } + + is-fullwidth-code-point@5.1.0: + resolution: + { + integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ== + } + engines: { node: '>=18' } + + is-glob@4.0.3: + resolution: + { + integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + } + engines: { node: '>=0.10.0' } + + is-hotkey@0.2.0: + resolution: + { + integrity: sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw== + } + + is-inside-container@1.0.0: + resolution: + { + integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + } + engines: { node: '>=14.16' } + hasBin: true + + is-interactive@1.0.0: + resolution: + { + integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + } + engines: { node: '>=8' } + + is-number@7.0.0: + resolution: + { + integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + } + engines: { node: '>=0.12.0' } + + is-obj@2.0.0: + resolution: + { + integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + } + engines: { node: '>=8' } + + is-plain-obj@4.1.0: + resolution: + { + integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== + } + engines: { node: '>=12' } + + is-plain-object@5.0.0: + resolution: + { + integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + } + engines: { node: '>=0.10.0' } + + is-stream@3.0.0: + resolution: + { + integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + is-stream@4.0.1: + resolution: + { + integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A== + } + engines: { node: '>=18' } + + is-text-path@2.0.0: + resolution: + { + integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw== + } + engines: { node: '>=8' } + + is-unicode-supported@0.1.0: + resolution: + { + integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + } + engines: { node: '>=10' } + + is-unicode-supported@2.1.0: + resolution: + { + integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ== + } + engines: { node: '>=18' } + + is-url@1.2.4: + resolution: + { + integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + } + + is-utf8@0.2.1: + resolution: + { + integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== + } + + is-what@4.1.16: + resolution: + { + integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A== + } + engines: { node: '>=12.13' } + + is-windows@1.0.2: + resolution: + { + integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + } + engines: { node: '>=0.10.0' } + + is-wsl@2.2.0: + resolution: + { + integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + } + engines: { node: '>=8' } + + is-wsl@3.1.0: + resolution: + { + integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== + } + engines: { node: '>=16' } + + isexe@2.0.0: + resolution: + { + integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + } + + jiti@2.6.0: + resolution: + { + integrity: sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ== + } + hasBin: true + + js-tokens@4.0.0: + resolution: + { + integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + } + + js-tokens@9.0.1: + resolution: + { + integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ== + } + + js-yaml@4.1.0: + resolution: + { + integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + } + hasBin: true + + jsesc@3.1.0: + resolution: + { + integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + } + engines: { node: '>=6' } + hasBin: true + + json-buffer@3.0.1: + resolution: + { + integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + } + + json-parse-even-better-errors@2.3.1: + resolution: + { + integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + } + + 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-stable-stringify-without-jsonify@1.0.1: + resolution: + { + integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + } + + json5@2.2.3: + resolution: + { + integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + } + engines: { node: '>=6' } + hasBin: true + + jsonfile@6.2.0: + resolution: + { + integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg== + } + + jsonparse@1.3.1: + resolution: + { + integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + } + engines: { '0': node >= 0.2.0 } + + keyv@4.5.4: + resolution: + { + integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + } + + keyv@5.5.3: + resolution: + { + integrity: sha512-h0Un1ieD+HUrzBH6dJXhod3ifSghk5Hw/2Y4/KHBziPlZecrFyE9YOTPU6eOs0V9pYl8gOs86fkr/KN8lUX39A== + } + + kind-of@6.0.3: + resolution: + { + integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + } + engines: { node: '>=0.10.0' } + + known-css-properties@0.36.0: + resolution: + { + integrity: sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA== + } + + known-css-properties@0.37.0: + resolution: + { + integrity: sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ== + } + + kolorist@1.8.0: + resolution: + { + integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== + } + + levn@0.4.1: + resolution: + { + integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + } + engines: { node: '>= 0.8.0' } + + lightningcss-darwin-arm64@1.30.1: + resolution: + { + integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ== + } + engines: { node: '>= 12.0.0' } + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.30.1: + resolution: + { + integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA== + } + engines: { node: '>= 12.0.0' } + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.30.1: + resolution: + { + integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig== + } + engines: { node: '>= 12.0.0' } + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.30.1: + resolution: + { + integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q== + } + engines: { node: '>= 12.0.0' } + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.30.1: + resolution: + { + integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw== + } + engines: { node: '>= 12.0.0' } + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.30.1: + resolution: + { + integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ== + } + engines: { node: '>= 12.0.0' } + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.30.1: + resolution: + { + integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw== + } + engines: { node: '>= 12.0.0' } + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.30.1: + resolution: + { + integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ== + } + engines: { node: '>= 12.0.0' } + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.30.1: + resolution: + { + integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA== + } + engines: { node: '>= 12.0.0' } + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.30.1: + resolution: + { + integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg== + } + engines: { node: '>= 12.0.0' } + cpu: [x64] + os: [win32] + + lightningcss@1.30.1: + resolution: + { + integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg== + } + engines: { node: '>= 12.0.0' } + + lilconfig@3.1.3: + resolution: + { + integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== + } + engines: { node: '>=14' } + + lines-and-columns@1.2.4: + resolution: + { + integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + } + + lint-staged@15.5.2: + resolution: + { + integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w== + } + engines: { node: '>=18.12.0' } + hasBin: true + + listr2@8.3.3: + resolution: + { + integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ== + } + engines: { node: '>=18.0.0' } + + local-pkg@1.1.2: + resolution: + { + integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A== + } + engines: { node: '>=14' } + + locate-path@6.0.0: + resolution: + { + integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + } + engines: { node: '>=10' } + + locate-path@7.2.0: + resolution: + { + integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + lodash-es@4.17.21: + resolution: + { + integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + } + + lodash-unified@1.0.3: + resolution: + { + integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ== + } + peerDependencies: + '@types/lodash-es': '*' + lodash: '*' + lodash-es: '*' + + lodash.camelcase@4.3.0: + resolution: + { + integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + } + + lodash.clonedeep@4.5.0: + resolution: + { + integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== + } + + lodash.debounce@4.0.8: + resolution: + { + integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + } + + lodash.foreach@4.5.0: + resolution: + { + integrity: sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ== + } + + lodash.isequal@4.5.0: + resolution: + { + integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + } + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + + lodash.isplainobject@4.0.6: + resolution: + { + integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + } + + lodash.kebabcase@4.1.1: + resolution: + { + integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g== + } + + lodash.map@4.6.0: + resolution: + { + integrity: sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q== + } + + lodash.merge@4.6.2: + resolution: + { + integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + } + + lodash.mergewith@4.6.2: + resolution: + { + integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== + } + + lodash.snakecase@4.1.1: + resolution: + { + integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw== + } + + lodash.startcase@4.4.0: + resolution: + { + integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg== + } + + lodash.throttle@4.1.1: + resolution: + { + integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + } + + lodash.toarray@4.4.0: + resolution: + { + integrity: sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw== + } + + lodash.truncate@4.4.2: + resolution: + { + integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + } + + lodash.uniq@4.5.0: + resolution: + { + integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== + } + + lodash.upperfirst@4.3.1: + resolution: + { + integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== + } + + lodash@4.17.21: + resolution: + { + integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + } + + log-symbols@4.1.0: + resolution: + { + integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + } + engines: { node: '>=10' } + + log-update@6.1.0: + resolution: + { + integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w== + } + engines: { node: '>=18' } + + longest@2.0.1: + resolution: + { + integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q== + } + engines: { node: '>=0.10.0' } + + lru-cache@5.1.1: + resolution: + { + integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + } + + magic-string@0.30.19: + resolution: + { + integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw== + } + + math-intrinsics@1.1.0: + resolution: + { + integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + } + engines: { node: '>= 0.4' } + + mathml-tag-names@2.1.3: + resolution: + { + integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== + } + + mdn-data@2.12.2: + resolution: + { + integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA== + } + + mdn-data@2.24.0: + resolution: + { + integrity: sha512-i97fklrJl03tL1tdRVw0ZfLLvuDsdb6wxL+TrJ+PKkCbLrp2PCu2+OYdCKychIUm19nSM/35S6qz7pJpnXttoA== + } + + memoize-one@6.0.0: + resolution: + { + integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== + } + + meow@12.1.1: + resolution: + { + integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw== + } + engines: { node: '>=16.10' } + + meow@13.2.0: + resolution: + { + integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA== + } + engines: { node: '>=18' } + + merge-stream@2.0.0: + resolution: + { + integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + } + + merge2@1.4.1: + resolution: + { + integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + } + engines: { node: '>= 8' } + + merge@2.1.1: + resolution: + { + integrity: sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w== + } + + 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-match@1.0.2: + resolution: + { + integrity: sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg== + } + + mime-types@2.1.35: + resolution: + { + integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + } + engines: { node: '>= 0.6' } + + mimic-fn@2.1.0: + resolution: + { + integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + } + engines: { node: '>=6' } + + mimic-fn@4.0.0: + resolution: + { + integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + } + engines: { node: '>=12' } + + mimic-function@5.0.1: + resolution: + { + integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== + } + engines: { node: '>=18' } + + minimatch@3.1.2: + resolution: + { + integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + } + + minimatch@9.0.5: + resolution: + { + integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + } + engines: { node: '>=16 || 14 >=14.17' } + + minimist@1.2.7: + resolution: + { + integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + } + + minimist@1.2.8: + resolution: + { + integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + } + + minipass@7.1.2: + resolution: + { + integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + } + engines: { node: '>=16 || 14 >=14.17' } + + minizlib@3.1.0: + resolution: + { + integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw== + } + engines: { node: '>= 18' } + + mitt@3.0.1: + resolution: + { + integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== + } + + mlly@1.8.0: + resolution: + { + integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g== + } + + mrmime@2.0.1: + resolution: + { + integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ== + } + engines: { node: '>=10' } + + ms@2.1.3: + resolution: + { + integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + } + + muggle-string@0.4.1: + resolution: + { + integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ== + } + + mute-stream@0.0.8: + resolution: + { + integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + } + + namespace-emitter@2.0.1: + resolution: + { + integrity: sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g== + } + + nanoid@3.3.11: + resolution: + { + integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + } + engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } + hasBin: true + + nanoid@5.1.6: + resolution: + { + integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg== + } + engines: { node: ^18 || >=20 } + hasBin: true + + natural-compare@1.4.0: + resolution: + { + integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + } + + next-tick@1.1.0: + resolution: + { + integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + } + + node-addon-api@7.1.1: + resolution: + { + integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== + } + + node-releases@2.0.21: + resolution: + { + integrity: sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw== + } + + normalize-path@3.0.0: + resolution: + { + integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + } + engines: { node: '>=0.10.0' } + + normalize-wheel-es@1.2.0: + resolution: + { + integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw== + } + + npm-run-path@5.3.0: + resolution: + { + integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + npm-run-path@6.0.0: + resolution: + { + integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA== + } + engines: { node: '>=18' } + + nprogress@0.2.0: + resolution: + { + integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA== + } + + nth-check@2.1.1: + resolution: + { + integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + } + + ohash@2.0.11: + resolution: + { + integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ== + } + + once@1.4.0: + resolution: + { + integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + } + + onetime@5.1.2: + resolution: + { + integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + } + engines: { node: '>=6' } + + onetime@6.0.0: + resolution: + { + integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + } + engines: { node: '>=12' } + + onetime@7.0.0: + resolution: + { + integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ== + } + engines: { node: '>=18' } + + open@10.2.0: + resolution: + { + integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA== + } + engines: { node: '>=18' } + + open@8.4.2: + resolution: + { + integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + } + engines: { node: '>=12' } + + optionator@0.9.4: + resolution: + { + integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + } + engines: { node: '>= 0.8.0' } + + ora@5.4.1: + resolution: + { + integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + } + engines: { node: '>=10' } + + os-tmpdir@1.0.2: + resolution: + { + integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + } + engines: { node: '>=0.10.0' } + + p-limit@3.1.0: + resolution: + { + integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + } + engines: { node: '>=10' } + + p-limit@4.0.0: + resolution: + { + integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + p-locate@5.0.0: + resolution: + { + integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + } + engines: { node: '>=10' } + + p-locate@6.0.0: + resolution: + { + integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + parent-module@1.0.1: + resolution: + { + integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + } + engines: { node: '>=6' } + + parse-json@5.2.0: + resolution: + { + integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + } + engines: { node: '>=8' } + + parse-ms@4.0.0: + resolution: + { + integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw== + } + engines: { node: '>=18' } + + parse-passwd@1.0.0: + resolution: + { + integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== + } + engines: { node: '>=0.10.0' } + + 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-exists@5.0.0: + resolution: + { + integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + path-is-absolute@1.0.1: + resolution: + { + integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + } + engines: { node: '>=0.10.0' } + + path-key@3.1.1: + resolution: + { + integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + } + engines: { node: '>=8' } + + path-key@4.0.0: + resolution: + { + integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + } + engines: { node: '>=12' } + + path-type@4.0.0: + resolution: + { + integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + } + engines: { node: '>=8' } + + 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.1: + resolution: + { + integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + } + engines: { node: '>=8.6' } + + picomatch@4.0.3: + resolution: + { + integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + } + engines: { node: '>=12' } + + pidtree@0.6.0: + resolution: + { + integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== + } + engines: { node: '>=0.10' } + hasBin: true + + pinia-plugin-persistedstate@4.5.0: + resolution: + { + integrity: sha512-QTkP1xJVyCdr2I2p3AKUZM84/e+IS+HktRxKGAIuDzkyaKKV48mQcYkJFVVDuvTxlI5j6X3oZObpqoVB8JnWpw== + } + peerDependencies: + '@nuxt/kit': '>=3.0.0' + '@pinia/nuxt': '>=0.10.0' + pinia: '>=3.0.0' + peerDependenciesMeta: + '@nuxt/kit': + optional: true + '@pinia/nuxt': + optional: true + pinia: + optional: true + + pinia@3.0.3: + resolution: + { + integrity: sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA== + } + peerDependencies: + typescript: '>=4.4.4' + vue: ^2.7.0 || ^3.5.11 + peerDependenciesMeta: + typescript: + optional: true + + pkg-types@1.3.1: + resolution: + { + integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== + } + + pkg-types@2.3.0: + resolution: + { + integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig== + } + + postcss-html@1.8.0: + resolution: + { + integrity: sha512-5mMeb1TgLWoRKxZ0Xh9RZDfwUUIqRrcxO2uXO+Ezl1N5lqpCiSU5Gk6+1kZediBfBHFtPCdopr2UZ2SgUsKcgQ== + } + engines: { node: ^12 || >=14 } + + postcss-media-query-parser@0.2.3: + resolution: + { + integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig== + } + + postcss-resolve-nested-selector@0.1.6: + resolution: + { + integrity: sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw== + } + + postcss-safe-parser@6.0.0: + resolution: + { + integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ== + } + engines: { node: '>=12.0' } + peerDependencies: + postcss: ^8.3.3 + + postcss-safe-parser@7.0.1: + resolution: + { + integrity: sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A== + } + engines: { node: '>=18.0' } + peerDependencies: + postcss: ^8.4.31 + + postcss-scss@4.0.9: + resolution: + { + integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A== + } + engines: { node: '>=12.0' } + peerDependencies: + postcss: ^8.4.29 + + postcss-selector-parser@6.1.2: + resolution: + { + integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== + } + engines: { node: '>=4' } + + postcss-selector-parser@7.1.0: + resolution: + { + integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA== + } + engines: { node: '>=4' } + + postcss-sorting@8.0.2: + resolution: + { + integrity: sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q== + } + peerDependencies: + postcss: ^8.4.20 + + postcss-value-parser@4.2.0: + resolution: + { + integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + } + + postcss@8.5.6: + resolution: + { + integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== + } + engines: { node: ^10 || ^12 || >=14 } + + preact@10.27.2: + resolution: + { + integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg== + } + + prelude-ls@1.2.1: + resolution: + { + integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + } + engines: { node: '>= 0.8.0' } + + prettier-linter-helpers@1.0.0: + resolution: + { + integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + } + engines: { node: '>=6.0.0' } + + prettier@3.6.2: + resolution: + { + integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ== + } + engines: { node: '>=14' } + hasBin: true + + pretty-ms@9.3.0: + resolution: + { + integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ== + } + engines: { node: '>=18' } + + prismjs@1.30.0: + resolution: + { + integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw== + } + engines: { node: '>=6' } + + proxy-from-env@1.1.0: + resolution: + { + integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + } + + punycode@2.3.1: + resolution: + { + integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + } + engines: { node: '>=6' } + + qrcode.vue@3.6.0: + resolution: + { + integrity: sha512-vQcl2fyHYHMjDO1GguCldJxepq2izQjBkDEEu9NENgfVKP6mv/e2SU62WbqYHGwTgWXLhxZ1NCD1dAZKHQq1fg== + } + peerDependencies: + vue: ^3.0.0 + + quansync@0.2.11: + resolution: + { + integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA== + } + + queue-microtask@1.2.3: + resolution: + { + integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + } + + readable-stream@3.6.2: + resolution: + { + integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + } + engines: { node: '>= 6' } + + readdirp@3.6.0: + resolution: + { + integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + } + engines: { node: '>=8.10.0' } + + readdirp@4.1.2: + resolution: + { + integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + } + engines: { node: '>= 14.18.0' } + + require-directory@2.1.1: + resolution: + { + integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + } + engines: { node: '>=0.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-dir@1.0.1: + resolution: + { + integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg== + } + engines: { node: '>=0.10.0' } + + resolve-from@4.0.0: + resolution: + { + integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + } + engines: { node: '>=4' } + + resolve-from@5.0.0: + resolution: + { + integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + } + engines: { node: '>=8' } + + resolve-pkg-maps@1.0.0: + resolution: + { + integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + } + + restore-cursor@3.1.0: + resolution: + { + integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + } + engines: { node: '>=8' } + + restore-cursor@5.1.0: + resolution: + { + integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA== + } + engines: { node: '>=18' } + + 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-plugin-visualizer@5.14.0: + resolution: + { + integrity: sha512-VlDXneTDaKsHIw8yzJAFWtrzguoJ/LnQ+lMpoVfYJ3jJF4Ihe5oYLAqLklIK/35lgUY+1yEzCkHyZ1j4A5w5fA== + } + engines: { node: '>=18' } + hasBin: true + peerDependencies: + rolldown: 1.x + rollup: 2.x || 3.x || 4.x + peerDependenciesMeta: + rolldown: + optional: true + rollup: + optional: true + + rollup@4.52.3: + resolution: + { + integrity: sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A== + } + engines: { node: '>=18.0.0', npm: '>=8.0.0' } + hasBin: true + + run-applescript@7.1.0: + resolution: + { + integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q== + } + engines: { node: '>=18' } + + run-async@2.4.1: + resolution: + { + integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + } + engines: { node: '>=0.12.0' } + + run-parallel@1.2.0: + resolution: + { + integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + } + + rxjs@7.8.2: + resolution: + { + integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== + } + + safe-buffer@5.2.1: + resolution: + { + integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + } + + safer-buffer@2.1.2: + resolution: + { + integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + } + + sass@1.93.2: + resolution: + { + integrity: sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg== + } + engines: { node: '>=14.0.0' } + hasBin: true + + scroll-into-view-if-needed@2.2.31: + resolution: + { + integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA== + } + + scule@1.3.0: + resolution: + { + integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g== + } + + semver@6.3.1: + resolution: + { + integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + } + hasBin: true + + semver@7.7.2: + resolution: + { + integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== + } + engines: { node: '>=10' } + hasBin: true + + 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' } + + signal-exit@3.0.7: + resolution: + { + integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + } + + signal-exit@4.1.0: + resolution: + { + integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + } + engines: { node: '>=14' } + + sirv@3.0.2: + resolution: + { + integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g== + } + engines: { node: '>=18' } + + slash@3.0.0: + resolution: + { + integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + } + engines: { node: '>=8' } + + slate-history@0.66.0: + resolution: + { + integrity: sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng== + } + peerDependencies: + slate: '>=0.65.3' + + slate@0.72.8: + resolution: + { + integrity: sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw== + } + + slice-ansi@4.0.0: + resolution: + { + integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + } + engines: { node: '>=10' } + + slice-ansi@5.0.0: + resolution: + { + integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== + } + engines: { node: '>=12' } + + slice-ansi@7.1.2: + resolution: + { + integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w== + } + engines: { node: '>=18' } + + snabbdom@3.6.2: + resolution: + { + integrity: sha512-ig5qOnCDbugFntKi6c7Xlib8bA6xiJVk8O+WdFrV3wxbMqeHO0hXFQC4nAhPVWfZfi8255lcZkNhtIBINCc4+Q== + } + engines: { node: '>=12.17.0' } + + 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' } + + source-map@0.7.6: + resolution: + { + integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ== + } + engines: { node: '>= 12' } + + speakingurl@14.0.1: + resolution: + { + integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ== + } + engines: { node: '>=0.10.0' } + + split2@4.2.0: + resolution: + { + integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + } + engines: { node: '>= 10.x' } + + ssf@0.11.2: + resolution: + { + integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g== + } + engines: { node: '>=0.8' } + + ssr-window@3.0.0: + resolution: + { + integrity: sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA== + } + + string-argv@0.3.2: + resolution: + { + integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== + } + engines: { node: '>=0.6.19' } + + string-width@4.2.3: + resolution: + { + integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + } + engines: { node: '>=8' } + + string-width@7.2.0: + resolution: + { + integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== + } + engines: { node: '>=18' } + + string_decoder@1.3.0: + resolution: + { + integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + } + + strip-ansi@6.0.1: + resolution: + { + integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + } + engines: { node: '>=8' } + + strip-ansi@7.1.2: + resolution: + { + integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== + } + engines: { node: '>=12' } + + strip-bom@4.0.0: + resolution: + { + integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + } + engines: { node: '>=8' } + + strip-final-newline@3.0.0: + resolution: + { + integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + } + engines: { node: '>=12' } + + strip-final-newline@4.0.0: + resolution: + { + integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw== + } + engines: { node: '>=18' } + + 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== + } + + stylelint-config-html@1.1.0: + resolution: + { + integrity: sha512-IZv4IVESjKLumUGi+HWeb7skgO6/g4VMuAYrJdlqQFndgbj6WJAXPhaysvBiXefX79upBdQVumgYcdd17gCpjQ== + } + engines: { node: ^12 || >=14 } + peerDependencies: + postcss-html: ^1.0.0 + stylelint: '>=14.0.0' + + stylelint-config-recess-order@4.6.0: + resolution: + { + integrity: sha512-V76fhv3YtcNXh/hyAuAdSzi5FmcrG54Mp2AThJ3D/PTMTSYzUPd7GIhP6z9mTqnRhmkk6YTfcu/JWB8h+Yrcaw== + } + peerDependencies: + stylelint: '>=15' + + stylelint-config-recommended-scss@14.1.0: + resolution: + { + integrity: sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg== + } + engines: { node: '>=18.12.0' } + peerDependencies: + postcss: ^8.3.3 + stylelint: ^16.6.1 + peerDependenciesMeta: + postcss: + optional: true + + stylelint-config-recommended-vue@1.6.1: + resolution: + { + integrity: sha512-lLW7hTIMBiTfjenGuDq2kyHA6fBWd/+Df7MO4/AWOxiFeXP9clbpKgg27kHfwA3H7UNMGC7aeP3mNlZB5LMmEQ== + } + engines: { node: ^12 || >=14 } + peerDependencies: + postcss-html: ^1.0.0 + stylelint: '>=14.0.0' + + stylelint-config-recommended@14.0.1: + resolution: + { + integrity: sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg== + } + engines: { node: '>=18.12.0' } + peerDependencies: + stylelint: ^16.1.0 + + stylelint-config-recommended@17.0.0: + resolution: + { + integrity: sha512-WaMSdEiPfZTSFVoYmJbxorJfA610O0tlYuU2aEwY33UQhSPgFbClrVJYWvy3jGJx+XW37O+LyNLiZOEXhKhJmA== + } + engines: { node: '>=18.12.0' } + peerDependencies: + stylelint: ^16.23.0 + + stylelint-config-standard@36.0.1: + resolution: + { + integrity: sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw== + } + engines: { node: '>=18.12.0' } + peerDependencies: + stylelint: ^16.1.0 + + stylelint-order@6.0.4: + resolution: + { + integrity: sha512-0UuKo4+s1hgQ/uAxlYU4h0o0HS4NiQDud0NAUNI0aa8FJdmYHA5ZZTFHiV5FpmE3071e9pZx5j0QpVJW5zOCUA== + } + peerDependencies: + stylelint: ^14.0.0 || ^15.0.0 || ^16.0.1 + + stylelint-scss@6.12.1: + resolution: + { + integrity: sha512-UJUfBFIvXfly8WKIgmqfmkGKPilKB4L5j38JfsDd+OCg2GBdU0vGUV08Uw82tsRZzd4TbsUURVVNGeOhJVF7pA== + } + engines: { node: '>=18.12.0' } + peerDependencies: + stylelint: ^16.0.2 + + stylelint@16.24.0: + resolution: + { + integrity: sha512-7ksgz3zJaSbTUGr/ujMXvLVKdDhLbGl3R/3arNudH7z88+XZZGNLMTepsY28WlnvEFcuOmUe7fg40Q3lfhOfSQ== + } + engines: { node: '>=18.12.0' } + hasBin: true + + superjson@2.2.2: + resolution: + { + integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q== + } + engines: { node: '>=16' } + + supports-color@5.5.0: + resolution: + { + integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + } + engines: { node: '>=4' } + + supports-color@7.2.0: + resolution: + { + integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + } + engines: { node: '>=8' } + + supports-hyperlinks@3.2.0: + resolution: + { + integrity: sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig== + } + engines: { node: '>=14.18' } + + svg-tags@1.0.0: + resolution: + { + integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA== + } + + synckit@0.11.11: + resolution: + { + integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw== + } + engines: { node: ^14.18.0 || >=16.0.0 } + + table@6.9.0: + resolution: + { + integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A== + } + engines: { node: '>=10.0.0' } + + tailwindcss@4.1.14: + resolution: + { + integrity: sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA== + } + + tapable@2.3.0: + resolution: + { + integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg== + } + engines: { node: '>=6' } + + tar@7.5.1: + resolution: + { + integrity: sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g== + } + engines: { node: '>=18' } + + terser@5.44.0: + resolution: + { + integrity: sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w== + } + engines: { node: '>=10' } + hasBin: true + + text-extensions@2.4.0: + resolution: + { + integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g== + } + engines: { node: '>=8' } + + through@2.3.8: + resolution: + { + integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + } + + tiny-warning@1.0.3: + resolution: + { + integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + } + + tinyexec@1.0.1: + resolution: + { + integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw== + } + + tinyglobby@0.2.15: + resolution: + { + integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ== + } + engines: { node: '>=12.0.0' } + + tmp@0.0.33: + resolution: + { + integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + } + engines: { node: '>=0.6.0' } + + to-regex-range@5.0.1: + resolution: + { + integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + } + engines: { node: '>=8.0' } + + totalist@3.0.1: + resolution: + { + integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== + } + engines: { node: '>=6' } + + ts-api-utils@2.1.0: + resolution: + { + integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== + } + engines: { node: '>=18.12' } + peerDependencies: + typescript: '>=4.8.4' + + tslib@2.3.0: + resolution: + { + integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== + } + + tslib@2.8.1: + resolution: + { + integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + } + + tsx@4.20.6: + resolution: + { + integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg== + } + engines: { node: '>=18.0.0' } + hasBin: true + + 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-fest@0.21.3: + resolution: + { + integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + } + engines: { node: '>=10' } + + type@2.7.3: + resolution: + { + integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ== + } + + typescript-eslint@8.44.1: + resolution: + { + integrity: sha512-0ws8uWGrUVTjEeN2OM4K1pLKHK/4NiNP/vz6ns+LjT/6sqpaYzIVFajZb1fj/IDwpsrrHb3Jy0Qm5u9CPcKaeg== + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + typescript@5.6.3: + resolution: + { + integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== + } + engines: { node: '>=14.17' } + hasBin: true + + ufo@1.6.1: + resolution: + { + integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA== + } + + undici-types@7.14.0: + resolution: + { + integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA== + } + + unicorn-magic@0.1.0: + resolution: + { + integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ== + } + engines: { node: '>=18' } + + unicorn-magic@0.3.0: + resolution: + { + integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA== + } + engines: { node: '>=18' } + + unimport@5.4.0: + resolution: + { + integrity: sha512-g/OLFZR2mEfqbC6NC9b2225eCJGvufxq34mj6kM3OmI5gdSL0qyqtnv+9qmsGpAmnzSl6x0IWZj4W+8j2hLkMA== + } + engines: { node: '>=18.12.0' } + + universalify@2.0.1: + resolution: + { + integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + } + engines: { node: '>= 10.0.0' } + + unplugin-auto-import@20.2.0: + resolution: + { + integrity: sha512-vfBI/SvD9hJqYNinipVOAj5n8dS8DJXFlCKFR5iLDp2SaQwsfdnfLXgZ+34Kd3YY3YEY9omk8XQg0bwos3Q8ug== + } + engines: { node: '>=14' } + peerDependencies: + '@nuxt/kit': ^4.0.0 + '@vueuse/core': '*' + peerDependenciesMeta: + '@nuxt/kit': + optional: true + '@vueuse/core': + optional: true + + unplugin-element-plus@0.10.0: + resolution: + { + integrity: sha512-oRSW0x6U58xBOWKy8TcoVZNA8ElIpfp3TUJRLQI6ey/E9PpjHl9/deeTAZNt8D57Li4OA4pCJtM6p2cb4Ff4ZA== + } + engines: { node: '>=18.12.0' } + + unplugin-utils@0.2.5: + resolution: + { + integrity: sha512-gwXJnPRewT4rT7sBi/IvxKTjsms7jX7QIDLOClApuZwR49SXbrB1z2NLUZ+vDHyqCj/n58OzRRqaW+B8OZi8vg== + } + engines: { node: '>=18.12.0' } + + unplugin-utils@0.3.0: + resolution: + { + integrity: sha512-JLoggz+PvLVMJo+jZt97hdIIIZ2yTzGgft9e9q8iMrC4ewufl62ekeW7mixBghonn2gVb/ICjyvlmOCUBnJLQg== + } + engines: { node: '>=20.19.0' } + + unplugin-vue-components@29.1.0: + resolution: + { + integrity: sha512-z/9ACPXth199s9aCTCdKZAhe5QGOpvzJYP+Hkd0GN1/PpAmsu+W3UlRY3BJAewPqQxh5xi56+Og6mfiCV1Jzpg== + } + 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.10: + resolution: + { + integrity: sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw== + } + engines: { node: '>=18.12.0' } + + update-browserslist-db@1.1.3: + resolution: + { + integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== + } + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: + { + integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + } + + util-deprecate@1.0.2: + resolution: + { + integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + } + + vite-hot-client@2.1.0: + resolution: + { + integrity: sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ== + } + peerDependencies: + vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + + vite-plugin-compression@0.5.1: + resolution: + { + integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg== + } + peerDependencies: + vite: '>=2.0.0' + + vite-plugin-inspect@0.8.9: + resolution: + { + integrity: sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A== + } + engines: { node: '>=14' } + peerDependencies: + '@nuxt/kit': '*' + vite: ^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + + vite-plugin-vue-devtools@7.7.7: + resolution: + { + integrity: sha512-d0fIh3wRcgSlr4Vz7bAk4va1MkdqhQgj9ANE/rBhsAjOnRfTLs2ocjFMvSUOsv6SRRXU9G+VM7yMgqDb6yI4iQ== + } + engines: { node: '>=v14.21.3' } + peerDependencies: + vite: ^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + + vite-plugin-vue-inspector@5.3.2: + resolution: + { + integrity: sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q== + } + peerDependencies: + vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + + vite@7.1.7: + resolution: + { + integrity: sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA== + } + engines: { node: ^20.19.0 || >=22.12.0 } + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + 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-draggable-plus@0.6.0: + resolution: + { + integrity: sha512-G5TSfHrt9tX9EjdG49InoFJbt2NYk0h3kgjgKxkFWr3ulIUays0oFObr5KZ8qzD4+QnhtALiRwIqY6qul4egqw== + } + peerDependencies: + '@types/sortablejs': ^1.15.0 + '@vue/composition-api': '*' + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + 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-i18n@9.14.5: + resolution: + { + integrity: sha512-0jQ9Em3ymWngyiIkj0+c/k7WgaPO+TNzjKSNq9BvBQaKJECqn9cd9fL4tkDhB5G1QBskGl9YxxbDAhgbFtpe2g== + } + engines: { node: '>= 16' } + peerDependencies: + vue: ^3.0.0 + + vue-img-cutter@3.0.7: + resolution: + { + integrity: sha512-fNw3kimawg9XVXDZCw2bI74NI+Jq+H42wjymatZVVSY46wuBty6LbQsu4GeVfo/yzpS9AHY0tzckpYzX3D2fmA== + } + + vue-router@4.5.1: + resolution: + { + integrity: sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw== + } + peerDependencies: + vue: ^3.2.0 + + vue-tsc@2.1.10: + resolution: + { + integrity: sha512-RBNSfaaRHcN5uqVqJSZh++Gy/YUzryuv9u1aFWhsammDJXNtUiJMNoJ747lZcQ68wUQFx6E73y4FY3D8E7FGMA== + } + hasBin: true + peerDependencies: + typescript: '>=5.0.0' + + vue@3.5.22: + resolution: + { + integrity: sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ== + } + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + wcwidth@1.0.1: + resolution: + { + integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + } + + webpack-virtual-modules@0.6.2: + resolution: + { + integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ== + } + + which@1.3.1: + resolution: + { + integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + } + hasBin: true + + which@2.0.2: + resolution: + { + integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + } + engines: { node: '>= 8' } + hasBin: true + + wildcard@1.1.2: + resolution: + { + integrity: sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng== + } + + wmf@1.0.2: + resolution: + { + integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw== + } + engines: { node: '>=0.8' } + + word-wrap@1.2.5: + resolution: + { + integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + } + engines: { node: '>=0.10.0' } + + word@0.3.0: + resolution: + { + integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA== + } + engines: { node: '>=0.8' } + + wrap-ansi@7.0.0: + resolution: + { + integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + } + engines: { node: '>=10' } + + wrap-ansi@9.0.2: + resolution: + { + integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww== + } + engines: { node: '>=18' } + + wrappy@1.0.2: + resolution: + { + integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + } + + write-file-atomic@5.0.1: + resolution: + { + integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== + } + engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + + wsl-utils@0.1.0: + resolution: + { + integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw== + } + engines: { node: '>=18' } + + xgplayer-subtitles@3.0.23: + resolution: + { + integrity: sha512-deGdV75giVzfTTdG9XATmji39NHwKTpEelWt2rRx/RyXGgU2bQFp0Ft7yWaK2Uu8A/WVrP5fpxEAj4MstREMkQ== + } + peerDependencies: + core-js: '>=3.12.1' + + xgplayer@3.0.23: + resolution: + { + integrity: sha512-Bn3zQfMMAZimlVG9EeIDybMcklc+6FH8Sv47KpTq4K6ofCzyhPG/KenxailDedlHmxjb5B2o+240TpJtMQ3oJA== + } + peerDependencies: + core-js: '>=3.12.1' + + xlsx@0.18.5: + resolution: + { + integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ== + } + engines: { node: '>=0.8' } + hasBin: true + + xml-name-validator@4.0.0: + resolution: + { + integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== + } + engines: { node: '>=12' } + + y18n@5.0.8: + resolution: + { + integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + } + engines: { node: '>=10' } + + yallist@3.1.1: + resolution: + { + integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + } + + yallist@5.0.0: + resolution: + { + integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== + } + engines: { node: '>=18' } + + yaml@2.8.1: + resolution: + { + integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw== + } + engines: { node: '>= 14.6' } + hasBin: true + + yargs-parser@21.1.1: + resolution: + { + integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + } + engines: { node: '>=12' } + + yargs@17.7.2: + resolution: + { + integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + } + engines: { node: '>=12' } + + yocto-queue@0.1.0: + resolution: + { + integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + } + engines: { node: '>=10' } + + yocto-queue@1.2.1: + resolution: + { + integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg== + } + engines: { node: '>=12.20' } + + yoctocolors@2.1.2: + resolution: + { + integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug== + } + engines: { node: '>=18' } + + zrender@6.0.0: + resolution: + { + integrity: sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg== + } + +snapshots: + '@antfu/utils@0.7.10': {} + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.4': {} + + '@babel/core@7.28.4': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.3 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.4 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.28.3': + dependencies: + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.28.4 + + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.4 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.26.2 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.28.3(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.4) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.28.4 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.27.1': + dependencies: + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.28.4 + + '@babel/helper-plugin-utils@7.27.1': {} + + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.28.4': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.4 + + '@babel/parser@7.28.4': + dependencies: + '@babel/types': 7.28.4 + + '@babel/plugin-proposal-decorators@7.28.0(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.4) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-decorators': 7.27.1(@babel/core@7.28.4) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-syntax-decorators@7.27.1(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.4) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.4) + transitivePeerDependencies: + - supports-color + + '@babel/runtime@7.28.4': {} + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 + + '@babel/traverse@7.28.4': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.3 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.4 + '@babel/template': 7.27.2 + '@babel/types': 7.28.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.28.4': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + + '@cacheable/memoize@2.0.2': + dependencies: + '@cacheable/utils': 2.0.2 + + '@cacheable/memory@2.0.2': + dependencies: + '@cacheable/memoize': 2.0.2 + '@cacheable/utils': 2.0.2 + '@keyv/bigmap': 1.0.2 + hookified: 1.12.1 + keyv: 5.5.3 + + '@cacheable/utils@2.0.2': {} + + '@commitlint/cli@19.8.1(@types/node@24.8.1)(typescript@5.6.3)': + dependencies: + '@commitlint/format': 19.8.1 + '@commitlint/lint': 19.8.1 + '@commitlint/load': 19.8.1(@types/node@24.8.1)(typescript@5.6.3) + '@commitlint/read': 19.8.1 + '@commitlint/types': 19.8.1 + tinyexec: 1.0.1 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/config-conventional@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + conventional-changelog-conventionalcommits: 7.0.2 + + '@commitlint/config-validator@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + ajv: 8.17.1 + + '@commitlint/config-validator@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + ajv: 8.17.1 + optional: true + + '@commitlint/ensure@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 + + '@commitlint/execute-rule@19.8.1': {} + + '@commitlint/execute-rule@20.0.0': + optional: true + + '@commitlint/format@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + chalk: 5.6.2 + + '@commitlint/is-ignored@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + semver: 7.7.2 + + '@commitlint/lint@19.8.1': + dependencies: + '@commitlint/is-ignored': 19.8.1 + '@commitlint/parse': 19.8.1 + '@commitlint/rules': 19.8.1 + '@commitlint/types': 19.8.1 + + '@commitlint/load@19.8.1(@types/node@24.8.1)(typescript@5.6.3)': + dependencies: + '@commitlint/config-validator': 19.8.1 + '@commitlint/execute-rule': 19.8.1 + '@commitlint/resolve-extends': 19.8.1 + '@commitlint/types': 19.8.1 + chalk: 5.6.2 + cosmiconfig: 9.0.0(typescript@5.6.3) + cosmiconfig-typescript-loader: 6.1.0(@types/node@24.8.1)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/load@20.0.0(@types/node@24.8.1)(typescript@5.6.3)': + dependencies: + '@commitlint/config-validator': 20.0.0 + '@commitlint/execute-rule': 20.0.0 + '@commitlint/resolve-extends': 20.0.0 + '@commitlint/types': 20.0.0 + chalk: 5.6.2 + cosmiconfig: 9.0.0(typescript@5.6.3) + cosmiconfig-typescript-loader: 6.1.0(@types/node@24.8.1)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript + optional: true + + '@commitlint/message@19.8.1': {} + + '@commitlint/parse@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + conventional-changelog-angular: 7.0.0 + conventional-commits-parser: 5.0.0 + + '@commitlint/read@19.8.1': + dependencies: + '@commitlint/top-level': 19.8.1 + '@commitlint/types': 19.8.1 + git-raw-commits: 4.0.0 + minimist: 1.2.8 + tinyexec: 1.0.1 + + '@commitlint/resolve-extends@19.8.1': + dependencies: + '@commitlint/config-validator': 19.8.1 + '@commitlint/types': 19.8.1 + global-directory: 4.0.1 + import-meta-resolve: 4.2.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + + '@commitlint/resolve-extends@20.0.0': + dependencies: + '@commitlint/config-validator': 20.0.0 + '@commitlint/types': 20.0.0 + global-directory: 4.0.1 + import-meta-resolve: 4.2.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + optional: true + + '@commitlint/rules@19.8.1': + dependencies: + '@commitlint/ensure': 19.8.1 + '@commitlint/message': 19.8.1 + '@commitlint/to-lines': 19.8.1 + '@commitlint/types': 19.8.1 + + '@commitlint/to-lines@19.8.1': {} + + '@commitlint/top-level@19.8.1': + dependencies: + find-up: 7.0.0 + + '@commitlint/types@19.8.1': + dependencies: + '@types/conventional-commits-parser': 5.0.1 + chalk: 5.6.2 + + '@commitlint/types@20.0.0': + dependencies: + '@types/conventional-commits-parser': 5.0.1 + chalk: 5.6.2 + optional: true + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-tokenizer@3.0.4': {} + + '@csstools/media-query-list-parser@4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.0)': + dependencies: + postcss-selector-parser: 7.1.0 + + '@ctrl/tinycolor@3.6.1': {} + + '@dual-bundle/import-meta-resolve@4.2.1': {} + + '@element-plus/icons-vue@2.3.2(vue@3.5.22(typescript@5.6.3))': + dependencies: + vue: 3.5.22(typescript@5.6.3) + + '@esbuild/aix-ppc64@0.25.10': + optional: true + + '@esbuild/android-arm64@0.25.10': + optional: true + + '@esbuild/android-arm@0.25.10': + optional: true + + '@esbuild/android-x64@0.25.10': + optional: true + + '@esbuild/darwin-arm64@0.25.10': + optional: true + + '@esbuild/darwin-x64@0.25.10': + optional: true + + '@esbuild/freebsd-arm64@0.25.10': + optional: true + + '@esbuild/freebsd-x64@0.25.10': + optional: true + + '@esbuild/linux-arm64@0.25.10': + optional: true + + '@esbuild/linux-arm@0.25.10': + optional: true + + '@esbuild/linux-ia32@0.25.10': + optional: true + + '@esbuild/linux-loong64@0.25.10': + optional: true + + '@esbuild/linux-mips64el@0.25.10': + optional: true + + '@esbuild/linux-ppc64@0.25.10': + optional: true + + '@esbuild/linux-riscv64@0.25.10': + optional: true + + '@esbuild/linux-s390x@0.25.10': + optional: true + + '@esbuild/linux-x64@0.25.10': + optional: true + + '@esbuild/netbsd-arm64@0.25.10': + optional: true + + '@esbuild/netbsd-x64@0.25.10': + optional: true + + '@esbuild/openbsd-arm64@0.25.10': + optional: true + + '@esbuild/openbsd-x64@0.25.10': + optional: true + + '@esbuild/openharmony-arm64@0.25.10': + optional: true + + '@esbuild/sunos-x64@0.25.10': + optional: true + + '@esbuild/win32-arm64@0.25.10': + optional: true + + '@esbuild/win32-ia32@0.25.10': + optional: true + + '@esbuild/win32-x64@0.25.10': + optional: true + + '@eslint-community/eslint-utils@4.9.0(eslint@9.36.0(jiti@2.6.0))': + dependencies: + eslint: 9.36.0(jiti@2.6.0) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.21.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.3 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.3.1': {} + + '@eslint/core@0.15.2': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.36.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.3.5': + dependencies: + '@eslint/core': 0.15.2 + levn: 0.4.1 + + '@floating-ui/core@1.7.3': + dependencies: + '@floating-ui/utils': 0.2.10 + + '@floating-ui/dom@1.7.4': + dependencies: + '@floating-ui/core': 1.7.3 + '@floating-ui/utils': 0.2.10 + + '@floating-ui/utils@0.2.10': {} + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@iconify/types@2.0.0': {} + + '@iconify/vue@5.0.0(vue@3.5.22(typescript@5.6.3))': + dependencies: + '@iconify/types': 2.0.0 + vue: 3.5.22(typescript@5.6.3) + + '@intlify/core-base@9.14.5': + dependencies: + '@intlify/message-compiler': 9.14.5 + '@intlify/shared': 9.14.5 + + '@intlify/message-compiler@9.14.5': + dependencies: + '@intlify/shared': 9.14.5 + source-map-js: 1.2.1 + + '@intlify/shared@9.14.5': {} + + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.2 + + '@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 + + '@keyv/bigmap@1.0.2': + dependencies: + hookified: 1.12.1 + + '@keyv/serialize@1.1.1': {} + + '@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.19.1 + + '@parcel/watcher-android-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-x64@2.5.1': + optional: true + + '@parcel/watcher-freebsd-x64@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-musl@2.5.1': + optional: true + + '@parcel/watcher-win32-arm64@2.5.1': + optional: true + + '@parcel/watcher-win32-ia32@2.5.1': + optional: true + + '@parcel/watcher-win32-x64@2.5.1': + optional: true + + '@parcel/watcher@2.5.1': + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.8 + node-addon-api: 7.1.1 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.5.1 + '@parcel/watcher-darwin-arm64': 2.5.1 + '@parcel/watcher-darwin-x64': 2.5.1 + '@parcel/watcher-freebsd-x64': 2.5.1 + '@parcel/watcher-linux-arm-glibc': 2.5.1 + '@parcel/watcher-linux-arm-musl': 2.5.1 + '@parcel/watcher-linux-arm64-glibc': 2.5.1 + '@parcel/watcher-linux-arm64-musl': 2.5.1 + '@parcel/watcher-linux-x64-glibc': 2.5.1 + '@parcel/watcher-linux-x64-musl': 2.5.1 + '@parcel/watcher-win32-arm64': 2.5.1 + '@parcel/watcher-win32-ia32': 2.5.1 + '@parcel/watcher-win32-x64': 2.5.1 + optional: true + + '@pkgr/core@0.2.9': {} + + '@polka/url@1.0.0-next.29': {} + + '@rolldown/pluginutils@1.0.0-beta.29': {} + + '@rollup/pluginutils@5.3.0(rollup@4.52.3)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.52.3 + + '@rollup/rollup-android-arm-eabi@4.52.3': + optional: true + + '@rollup/rollup-android-arm64@4.52.3': + optional: true + + '@rollup/rollup-darwin-arm64@4.52.3': + optional: true + + '@rollup/rollup-darwin-x64@4.52.3': + optional: true + + '@rollup/rollup-freebsd-arm64@4.52.3': + optional: true + + '@rollup/rollup-freebsd-x64@4.52.3': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.52.3': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.52.3': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.52.3': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.52.3': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.52.3': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.52.3': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.52.3': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.52.3': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.52.3': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.52.3': + optional: true + + '@rollup/rollup-linux-x64-musl@4.52.3': + optional: true + + '@rollup/rollup-openharmony-arm64@4.52.3': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.52.3': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.52.3': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.52.3': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.52.3': + optional: true + + '@sec-ant/readable-stream@0.4.1': {} + + '@sindresorhus/merge-streams@4.0.0': {} + + '@sxzz/popperjs-es@2.11.7': {} + + '@tailwindcss/node@4.1.14': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.18.3 + jiti: 2.6.0 + lightningcss: 1.30.1 + magic-string: 0.30.19 + source-map-js: 1.2.1 + tailwindcss: 4.1.14 + + '@tailwindcss/oxide-android-arm64@4.1.14': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.1.14': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.1.14': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.1.14': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.14': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.1.14': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.1.14': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.1.14': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.1.14': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.14': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.1.14': + optional: true + + '@tailwindcss/oxide@4.1.14': + dependencies: + detect-libc: 2.1.2 + tar: 7.5.1 + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.1.14 + '@tailwindcss/oxide-darwin-arm64': 4.1.14 + '@tailwindcss/oxide-darwin-x64': 4.1.14 + '@tailwindcss/oxide-freebsd-x64': 4.1.14 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.14 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.14 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.14 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.14 + '@tailwindcss/oxide-linux-x64-musl': 4.1.14 + '@tailwindcss/oxide-wasm32-wasi': 4.1.14 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.14 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.14 + + '@tailwindcss/vite@4.1.14(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': + dependencies: + '@tailwindcss/node': 4.1.14 + '@tailwindcss/oxide': 4.1.14 + tailwindcss: 4.1.14 + vite: 7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + + '@transloadit/prettier-bytes@0.0.7': {} + + '@types/conventional-commits-parser@5.0.1': + dependencies: + '@types/node': 24.8.1 + + '@types/estree@1.0.8': {} + + '@types/event-emitter@0.3.5': {} + + '@types/json-schema@7.0.15': {} + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.20 + + '@types/lodash@4.17.20': {} + + '@types/node@24.8.1': + dependencies: + undici-types: 7.14.0 + + '@types/sortablejs@1.15.8': {} + + '@types/web-bluetooth@0.0.16': {} + + '@types/web-bluetooth@0.0.21': {} + + '@typescript-eslint/eslint-plugin@8.44.1(@typescript-eslint/parser@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3))(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.44.1 + '@typescript-eslint/type-utils': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3) + '@typescript-eslint/utils': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.44.1 + eslint: 9.36.0(jiti@2.6.0) + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.6.3) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.44.1 + '@typescript-eslint/types': 8.44.1 + '@typescript-eslint/typescript-estree': 8.44.1(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.44.1 + debug: 4.4.3 + eslint: 9.36.0(jiti@2.6.0) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.44.1(typescript@5.6.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.44.1(typescript@5.6.3) + '@typescript-eslint/types': 8.44.1 + debug: 4.4.3 + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.44.1': + dependencies: + '@typescript-eslint/types': 8.44.1 + '@typescript-eslint/visitor-keys': 8.44.1 + + '@typescript-eslint/tsconfig-utils@8.44.1(typescript@5.6.3)': + dependencies: + typescript: 5.6.3 + + '@typescript-eslint/type-utils@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3)': + dependencies: + '@typescript-eslint/types': 8.44.1 + '@typescript-eslint/typescript-estree': 8.44.1(typescript@5.6.3) + '@typescript-eslint/utils': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3) + debug: 4.4.3 + eslint: 9.36.0(jiti@2.6.0) + ts-api-utils: 2.1.0(typescript@5.6.3) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.44.1': {} + + '@typescript-eslint/typescript-estree@8.44.1(typescript@5.6.3)': + dependencies: + '@typescript-eslint/project-service': 8.44.1(typescript@5.6.3) + '@typescript-eslint/tsconfig-utils': 8.44.1(typescript@5.6.3) + '@typescript-eslint/types': 8.44.1 + '@typescript-eslint/visitor-keys': 8.44.1 + debug: 4.4.3 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.6.3) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.0)) + '@typescript-eslint/scope-manager': 8.44.1 + '@typescript-eslint/types': 8.44.1 + '@typescript-eslint/typescript-estree': 8.44.1(typescript@5.6.3) + eslint: 9.36.0(jiti@2.6.0) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.44.1': + dependencies: + '@typescript-eslint/types': 8.44.1 + eslint-visitor-keys: 4.2.1 + + '@uppy/companion-client@2.2.2': + dependencies: + '@uppy/utils': 4.1.3 + namespace-emitter: 2.0.1 + + '@uppy/core@2.3.4': + dependencies: + '@transloadit/prettier-bytes': 0.0.7 + '@uppy/store-default': 2.1.1 + '@uppy/utils': 4.1.3 + lodash.throttle: 4.1.1 + mime-match: 1.0.2 + namespace-emitter: 2.0.1 + nanoid: 3.3.11 + preact: 10.27.2 + + '@uppy/store-default@2.1.1': {} + + '@uppy/utils@4.1.3': + dependencies: + lodash.throttle: 4.1.1 + + '@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4)': + dependencies: + '@uppy/companion-client': 2.2.2 + '@uppy/core': 2.3.4 + '@uppy/utils': 4.1.3 + nanoid: 3.3.11 + + '@vitejs/plugin-vue@6.0.1(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.22(typescript@5.6.3))': + dependencies: + '@rolldown/pluginutils': 1.0.0-beta.29 + vite: 7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + vue: 3.5.22(typescript@5.6.3) + + '@volar/language-core@2.4.23': + dependencies: + '@volar/source-map': 2.4.23 + + '@volar/source-map@2.4.23': {} + + '@volar/typescript@2.4.23': + dependencies: + '@volar/language-core': 2.4.23 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vue/babel-helper-vue-transform-on@1.5.0': {} + + '@vue/babel-plugin-jsx@1.5.0(@babel/core@7.28.4)': + dependencies: + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.4) + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + '@vue/babel-helper-vue-transform-on': 1.5.0 + '@vue/babel-plugin-resolve-type': 1.5.0(@babel/core@7.28.4) + '@vue/shared': 3.5.22 + optionalDependencies: + '@babel/core': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@vue/babel-plugin-resolve-type@1.5.0(@babel/core@7.28.4)': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/core': 7.28.4 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/parser': 7.28.4 + '@vue/compiler-sfc': 3.5.22 + transitivePeerDependencies: + - supports-color + + '@vue/compiler-core@3.5.22': + dependencies: + '@babel/parser': 7.28.4 + '@vue/shared': 3.5.22 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.22': + dependencies: + '@vue/compiler-core': 3.5.22 + '@vue/shared': 3.5.22 + + '@vue/compiler-sfc@3.5.22': + dependencies: + '@babel/parser': 7.28.4 + '@vue/compiler-core': 3.5.22 + '@vue/compiler-dom': 3.5.22 + '@vue/compiler-ssr': 3.5.22 + '@vue/shared': 3.5.22 + estree-walker: 2.0.2 + magic-string: 0.30.19 + postcss: 8.5.6 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.22': + dependencies: + '@vue/compiler-dom': 3.5.22 + '@vue/shared': 3.5.22 + + '@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.7': + dependencies: + '@vue/devtools-kit': 7.7.7 + + '@vue/devtools-core@7.7.7(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.22(typescript@5.6.3))': + dependencies: + '@vue/devtools-kit': 7.7.7 + '@vue/devtools-shared': 7.7.7 + mitt: 3.0.1 + nanoid: 5.1.6 + pathe: 2.0.3 + vite-hot-client: 2.1.0(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + vue: 3.5.22(typescript@5.6.3) + transitivePeerDependencies: + - vite + + '@vue/devtools-kit@7.7.7': + dependencies: + '@vue/devtools-shared': 7.7.7 + birpc: 2.6.1 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.2 + + '@vue/devtools-shared@7.7.7': + dependencies: + rfdc: 1.4.1 + + '@vue/language-core@2.1.10(typescript@5.6.3)': + dependencies: + '@volar/language-core': 2.4.23 + '@vue/compiler-dom': 3.5.22 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.22 + alien-signals: 0.2.2 + minimatch: 9.0.5 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 5.6.3 + + '@vue/reactivity@3.5.22': + dependencies: + '@vue/shared': 3.5.22 + + '@vue/runtime-core@3.5.22': + dependencies: + '@vue/reactivity': 3.5.22 + '@vue/shared': 3.5.22 + + '@vue/runtime-dom@3.5.22': + dependencies: + '@vue/reactivity': 3.5.22 + '@vue/runtime-core': 3.5.22 + '@vue/shared': 3.5.22 + csstype: 3.1.3 + + '@vue/server-renderer@3.5.22(vue@3.5.22(typescript@5.6.3))': + dependencies: + '@vue/compiler-ssr': 3.5.22 + '@vue/shared': 3.5.22 + vue: 3.5.22(typescript@5.6.3) + + '@vue/shared@3.5.22': {} + + '@vueuse/core@13.9.0(vue@3.5.22(typescript@5.6.3))': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 13.9.0 + '@vueuse/shared': 13.9.0(vue@3.5.22(typescript@5.6.3)) + vue: 3.5.22(typescript@5.6.3) + + '@vueuse/core@9.13.0(vue@3.5.22(typescript@5.6.3))': + dependencies: + '@types/web-bluetooth': 0.0.16 + '@vueuse/metadata': 9.13.0 + '@vueuse/shared': 9.13.0(vue@3.5.22(typescript@5.6.3)) + vue-demi: 0.14.10(vue@3.5.22(typescript@5.6.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/metadata@13.9.0': {} + + '@vueuse/metadata@9.13.0': {} + + '@vueuse/shared@13.9.0(vue@3.5.22(typescript@5.6.3))': + dependencies: + vue: 3.5.22(typescript@5.6.3) + + '@vueuse/shared@9.13.0(vue@3.5.22(typescript@5.6.3))': + dependencies: + vue-demi: 0.14.10(vue@3.5.22(typescript@5.6.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + is-url: 1.2.4 + lodash.throttle: 4.1.1 + nanoid: 3.3.11 + slate: 0.72.8 + snabbdom: 3.6.2 + + '@wangeditor/code-highlight@1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + prismjs: 1.30.0 + slate: 0.72.8 + snabbdom: 3.6.2 + + '@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@types/event-emitter': 0.3.5 + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + dom7: 3.0.0 + event-emitter: 0.3.5 + html-void-elements: 2.0.1 + i18next: 20.6.1 + is-hotkey: 0.2.0 + lodash.camelcase: 4.3.0 + lodash.clonedeep: 4.5.0 + lodash.debounce: 4.0.8 + lodash.foreach: 4.5.0 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + lodash.toarray: 4.4.0 + nanoid: 3.3.11 + scroll-into-view-if-needed: 2.2.31 + slate: 0.72.8 + slate-history: 0.66.0(slate@0.72.8) + snabbdom: 3.6.2 + + '@wangeditor/editor-for-vue@5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.22(typescript@5.6.3))': + dependencies: + '@wangeditor/editor': 5.1.23 + vue: 3.5.22(typescript@5.6.3) + + '@wangeditor/editor@5.1.23': + dependencies: + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + '@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/code-highlight': 1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/list-module': 1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/table-module': 1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/upload-image-module': 1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/video-module': 1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + is-hotkey: 0.2.0 + lodash.camelcase: 4.3.0 + lodash.clonedeep: 4.5.0 + lodash.debounce: 4.0.8 + lodash.foreach: 4.5.0 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + lodash.toarray: 4.4.0 + nanoid: 3.3.11 + slate: 0.72.8 + snabbdom: 3.6.2 + + '@wangeditor/list-module@1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + slate: 0.72.8 + snabbdom: 3.6.2 + + '@wangeditor/table-module@1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + nanoid: 3.3.11 + slate: 0.72.8 + snabbdom: 3.6.2 + + '@wangeditor/upload-image-module@1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + '@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + lodash.foreach: 4.5.0 + slate: 0.72.8 + snabbdom: 3.6.2 + + '@wangeditor/video-module@1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + nanoid: 3.3.11 + slate: 0.72.8 + snabbdom: 3.6.2 + + JSONStream@1.3.5: + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + adler-32@1.3.1: {} + + ajv@6.12.6: + 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.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + alien-signals@0.2.2: {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-escapes@7.1.1: + dependencies: + environment: 1.1.0 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.3: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + argparse@2.0.1: {} + + array-ify@1.0.0: {} + + array-union@2.1.0: {} + + astral-regex@2.0.0: {} + + async-validator@4.2.5: {} + + asynckit@0.4.0: {} + + at-least-node@1.0.0: {} + + axios@1.12.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + balanced-match@1.0.2: {} + + balanced-match@2.0.0: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.8.8: {} + + binary-extensions@2.3.0: {} + + birpc@2.6.1: {} + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + boolbase@1.0.0: {} + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.26.2: + dependencies: + baseline-browser-mapping: 2.8.8 + caniuse-lite: 1.0.30001745 + electron-to-chromium: 1.5.227 + node-releases: 2.0.21 + update-browserslist-db: 1.1.3(browserslist@4.26.2) + + buffer-from@1.1.2: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + + cacheable@2.0.2: + dependencies: + '@cacheable/memoize': 2.0.2 + '@cacheable/memory': 2.0.2 + '@cacheable/utils': 2.0.2 + hookified: 1.12.1 + keyv: 5.5.3 + + cachedir@2.3.0: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001745: {} + + cfb@1.2.2: + dependencies: + adler-32: 1.3.1 + crc-32: 1.2.2 + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.6.2: {} + + chardet@0.7.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 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + chownr@3.0.0: {} + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-spinners@2.9.2: {} + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + + cli-width@3.0.0: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone@1.0.4: {} + + codepage@1.15.0: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + colord@2.9.3: {} + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@13.1.0: {} + + commander@2.20.3: {} + + commitizen@4.3.1(@types/node@24.8.1)(typescript@5.6.3): + dependencies: + cachedir: 2.3.0 + cz-conventional-changelog: 3.3.0(@types/node@24.8.1)(typescript@5.6.3) + dedent: 0.7.0 + detect-indent: 6.1.0 + find-node-modules: 2.1.3 + find-root: 1.1.0 + fs-extra: 9.1.0 + glob: 7.2.3 + inquirer: 8.2.5 + is-utf8: 0.2.1 + lodash: 4.17.21 + minimist: 1.2.7 + strip-bom: 4.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - '@types/node' + - typescript + + compare-func@2.0.0: + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + + compute-scroll-into-view@1.0.20: {} + + concat-map@0.0.1: {} + + confbox@0.1.8: {} + + confbox@0.2.2: {} + + conventional-changelog-angular@7.0.0: + dependencies: + compare-func: 2.0.0 + + conventional-changelog-conventionalcommits@7.0.2: + dependencies: + compare-func: 2.0.0 + + conventional-commit-types@3.0.0: {} + + conventional-commits-parser@5.0.0: + dependencies: + JSONStream: 1.3.5 + is-text-path: 2.0.0 + meow: 12.1.1 + split2: 4.2.0 + + convert-source-map@2.0.0: {} + + copy-anything@3.0.5: + dependencies: + is-what: 4.1.16 + + core-js@3.45.1: {} + + cosmiconfig-typescript-loader@6.1.0(@types/node@24.8.1)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3): + dependencies: + '@types/node': 24.8.1 + cosmiconfig: 9.0.0(typescript@5.6.3) + jiti: 2.6.0 + typescript: 5.6.3 + + cosmiconfig@9.0.0(typescript@5.6.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.6.3 + + crc-32@1.2.2: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypto-js@4.2.0: {} + + css-functions-list@3.2.3: {} + + css-tree@3.1.0: + dependencies: + mdn-data: 2.12.2 + source-map-js: 1.2.1 + + cssesc@3.0.0: {} + + csstype@3.1.3: {} + + cz-conventional-changelog@3.3.0(@types/node@24.8.1)(typescript@5.6.3): + dependencies: + chalk: 2.4.2 + commitizen: 4.3.1(@types/node@24.8.1)(typescript@5.6.3) + conventional-commit-types: 3.0.0 + lodash.map: 4.6.0 + longest: 2.0.1 + word-wrap: 1.2.5 + optionalDependencies: + '@commitlint/load': 20.0.0(@types/node@24.8.1)(typescript@5.6.3) + transitivePeerDependencies: + - '@types/node' + - typescript + + cz-git@1.12.0: {} + + d@1.0.2: + dependencies: + es5-ext: 0.10.64 + type: 2.7.3 + + danmu.js@1.1.13: + dependencies: + event-emitter: 0.3.5 + + dargs@8.1.0: {} + + dayjs@1.11.18: {} + + de-indent@1.0.2: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + dedent@0.7.0: {} + + deep-is@0.1.4: {} + + deep-pick-omit@1.2.1: {} + + default-browser-id@5.0.0: {} + + default-browser@5.2.1: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + define-lazy-prop@2.0.0: {} + + define-lazy-prop@3.0.0: {} + + defu@6.1.4: {} + + delayed-stream@1.0.0: {} + + delegate@3.2.0: {} + + destr@2.0.5: {} + + detect-file@1.0.0: {} + + detect-indent@6.1.0: {} + + detect-libc@1.0.3: + optional: true + + detect-libc@2.1.2: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + dom7@3.0.0: + dependencies: + ssr-window: 3.0.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dot-prop@5.3.0: + dependencies: + is-obj: 2.0.0 + + downloadjs@1.4.7: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + echarts@6.0.0: + dependencies: + tslib: 2.3.0 + zrender: 6.0.0 + + electron-to-chromium@1.5.227: {} + + element-plus@2.11.4(vue@3.5.22(typescript@5.6.3)): + dependencies: + '@ctrl/tinycolor': 3.6.1 + '@element-plus/icons-vue': 2.3.2(vue@3.5.22(typescript@5.6.3)) + '@floating-ui/dom': 1.7.4 + '@popperjs/core': '@sxzz/popperjs-es@2.11.7' + '@types/lodash': 4.17.20 + '@types/lodash-es': 4.17.12 + '@vueuse/core': 9.13.0(vue@3.5.22(typescript@5.6.3)) + async-validator: 4.2.5 + dayjs: 1.11.18 + escape-html: 1.0.3 + lodash: 4.17.21 + lodash-es: 4.17.21 + lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21) + memoize-one: 6.0.0 + normalize-wheel-es: 1.2.0 + vue: 3.5.22(typescript@5.6.3) + transitivePeerDependencies: + - '@vue/composition-api' + + emoji-regex@10.5.0: {} + + emoji-regex@8.0.0: {} + + enhanced-resolve@5.18.3: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.0 + + entities@4.5.0: {} + + env-paths@2.2.1: {} + + environment@1.1.0: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + error-stack-parser-es@0.1.5: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.1: + 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.2 + + es5-ext@0.10.64: + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + esniff: 2.0.1 + next-tick: 1.1.0 + + es6-iterator@2.0.3: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-symbol: 3.1.4 + + es6-symbol@3.1.4: + dependencies: + d: 1.0.2 + ext: 1.7.0 + + esbuild@0.25.10: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.10 + '@esbuild/android-arm': 0.25.10 + '@esbuild/android-arm64': 0.25.10 + '@esbuild/android-x64': 0.25.10 + '@esbuild/darwin-arm64': 0.25.10 + '@esbuild/darwin-x64': 0.25.10 + '@esbuild/freebsd-arm64': 0.25.10 + '@esbuild/freebsd-x64': 0.25.10 + '@esbuild/linux-arm': 0.25.10 + '@esbuild/linux-arm64': 0.25.10 + '@esbuild/linux-ia32': 0.25.10 + '@esbuild/linux-loong64': 0.25.10 + '@esbuild/linux-mips64el': 0.25.10 + '@esbuild/linux-ppc64': 0.25.10 + '@esbuild/linux-riscv64': 0.25.10 + '@esbuild/linux-s390x': 0.25.10 + '@esbuild/linux-x64': 0.25.10 + '@esbuild/netbsd-arm64': 0.25.10 + '@esbuild/netbsd-x64': 0.25.10 + '@esbuild/openbsd-arm64': 0.25.10 + '@esbuild/openbsd-x64': 0.25.10 + '@esbuild/openharmony-arm64': 0.25.10 + '@esbuild/sunos-x64': 0.25.10 + '@esbuild/win32-arm64': 0.25.10 + '@esbuild/win32-ia32': 0.25.10 + '@esbuild/win32-x64': 0.25.10 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + escape-string-regexp@5.0.0: {} + + eslint-config-prettier@9.1.2(eslint@9.36.0(jiti@2.6.0)): + dependencies: + eslint: 9.36.0(jiti@2.6.0) + + eslint-plugin-prettier@5.5.4(eslint-config-prettier@9.1.2(eslint@9.36.0(jiti@2.6.0)))(eslint@9.36.0(jiti@2.6.0))(prettier@3.6.2): + dependencies: + eslint: 9.36.0(jiti@2.6.0) + prettier: 3.6.2 + prettier-linter-helpers: 1.0.0 + synckit: 0.11.11 + optionalDependencies: + eslint-config-prettier: 9.1.2(eslint@9.36.0(jiti@2.6.0)) + + eslint-plugin-vue@9.33.0(eslint@9.36.0(jiti@2.6.0)): + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.0)) + eslint: 9.36.0(jiti@2.6.0) + globals: 13.24.0 + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 6.1.2 + semver: 7.7.2 + vue-eslint-parser: 9.4.3(eslint@9.36.0(jiti@2.6.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-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.36.0(jiti@2.6.0): + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.0)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.1 + '@eslint/core': 0.15.2 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.36.0 + '@eslint/plugin-kit': 0.3.5 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + 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.6.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.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.0 + transitivePeerDependencies: + - supports-color + + esniff@2.0.1: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + event-emitter: 0.3.5 + type: 2.7.3 + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + espree@9.6.1: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 3.4.3 + + esquery@1.6.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.8 + + esutils@2.0.3: {} + + event-emitter@0.3.5: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + + eventemitter3@4.0.7: {} + + eventemitter3@5.0.1: {} + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + execa@9.6.0: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.1 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.3.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.2 + + expand-tilde@2.0.2: + dependencies: + homedir-polyfill: 1.0.3 + + exsolve@1.0.7: {} + + ext@1.7.0: + dependencies: + type: 2.7.3 + + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + + fast-deep-equal@3.1.3: {} + + fast-diff@1.3.0: {} + + 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.0: {} + + fastest-levenshtein@1.0.16: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + figures@3.2.0: + dependencies: + escape-string-regexp: 1.0.5 + + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + + file-entry-cache@10.1.4: + dependencies: + flat-cache: 6.1.14 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + file-saver@2.0.5: {} + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-node-modules@2.1.3: + dependencies: + findup-sync: 4.0.0 + merge: 2.1.1 + + find-root@1.1.0: {} + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + find-up@7.0.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + + findup-sync@4.0.0: + dependencies: + detect-file: 1.0.0 + is-glob: 4.0.3 + micromatch: 4.0.8 + resolve-dir: 1.0.1 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flat-cache@6.1.14: + dependencies: + cacheable: 2.0.2 + flatted: 3.3.3 + hookified: 1.12.1 + + flatted@3.3.3: {} + + follow-redirects@1.15.11: {} + + form-data@4.0.4: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + frac@1.1.2: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs-extra@11.3.2: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.4.0: {} + + 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.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@8.0.1: {} + + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + + get-tsconfig@4.10.1: + dependencies: + resolve-pkg-maps: 1.0.0 + + git-raw-commits@4.0.0: + dependencies: + dargs: 8.1.0 + meow: 12.1.1 + split2: 4.2.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + global-modules@1.0.0: + dependencies: + global-prefix: 1.0.2 + is-windows: 1.0.2 + resolve-dir: 1.0.1 + + global-modules@2.0.0: + dependencies: + global-prefix: 3.0.0 + + global-prefix@1.0.2: + dependencies: + expand-tilde: 2.0.2 + homedir-polyfill: 1.0.3 + ini: 1.3.8 + is-windows: 1.0.2 + which: 1.3.1 + + global-prefix@3.0.0: + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globals@14.0.0: {} + + globals@15.15.0: {} + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + globjoin@0.1.4: {} + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + highlight.js@11.11.1: {} + + homedir-polyfill@1.0.3: + dependencies: + parse-passwd: 1.0.0 + + hookable@5.5.3: {} + + hookified@1.12.1: {} + + html-tags@3.3.1: {} + + html-void-elements@2.0.1: {} + + htmlparser2@8.0.2: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 4.5.0 + + human-signals@5.0.0: {} + + human-signals@8.0.1: {} + + husky@9.1.7: {} + + i18next@20.6.1: + dependencies: + '@babel/runtime': 7.28.4 + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + immer@9.0.21: {} + + immutable@5.1.3: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-meta-resolve@4.2.0: {} + + imurmurhash@0.1.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ini@1.3.8: {} + + ini@4.1.1: {} + + inquirer@8.2.5: + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.8.2 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + wrap-ansi: 7.0.0 + + is-arrayish@0.2.1: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-docker@2.2.1: {} + + is-docker@3.0.0: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.1.0: + dependencies: + get-east-asian-width: 1.4.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-hotkey@0.2.0: {} + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-interactive@1.0.0: {} + + is-number@7.0.0: {} + + is-obj@2.0.0: {} + + is-plain-obj@4.1.0: {} + + is-plain-object@5.0.0: {} + + is-stream@3.0.0: {} + + is-stream@4.0.1: {} + + is-text-path@2.0.0: + dependencies: + text-extensions: 2.4.0 + + is-unicode-supported@0.1.0: {} + + is-unicode-supported@2.1.0: {} + + is-url@1.2.4: {} + + is-utf8@0.2.1: {} + + is-what@4.1.16: {} + + is-windows@1.0.2: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + + isexe@2.0.0: {} + + jiti@2.6.0: {} + + js-tokens@4.0.0: {} + + js-tokens@9.0.1: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + jsonfile@6.2.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonparse@1.3.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + keyv@5.5.3: + dependencies: + '@keyv/serialize': 1.1.1 + + kind-of@6.0.3: {} + + known-css-properties@0.36.0: {} + + known-css-properties@0.37.0: {} + + kolorist@1.8.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-darwin-arm64@1.30.1: + optional: true + + lightningcss-darwin-x64@1.30.1: + optional: true + + lightningcss-freebsd-x64@1.30.1: + optional: true + + lightningcss-linux-arm-gnueabihf@1.30.1: + optional: true + + lightningcss-linux-arm64-gnu@1.30.1: + optional: true + + lightningcss-linux-arm64-musl@1.30.1: + optional: true + + lightningcss-linux-x64-gnu@1.30.1: + optional: true + + lightningcss-linux-x64-musl@1.30.1: + optional: true + + lightningcss-win32-arm64-msvc@1.30.1: + optional: true + + lightningcss-win32-x64-msvc@1.30.1: + optional: true + + lightningcss@1.30.1: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-darwin-arm64: 1.30.1 + lightningcss-darwin-x64: 1.30.1 + lightningcss-freebsd-x64: 1.30.1 + lightningcss-linux-arm-gnueabihf: 1.30.1 + lightningcss-linux-arm64-gnu: 1.30.1 + lightningcss-linux-arm64-musl: 1.30.1 + lightningcss-linux-x64-gnu: 1.30.1 + lightningcss-linux-x64-musl: 1.30.1 + lightningcss-win32-arm64-msvc: 1.30.1 + lightningcss-win32-x64-msvc: 1.30.1 + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + lint-staged@15.5.2: + dependencies: + chalk: 5.6.2 + commander: 13.1.0 + debug: 4.4.3 + execa: 8.0.1 + lilconfig: 3.1.3 + listr2: 8.3.3 + micromatch: 4.0.8 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.8.1 + transitivePeerDependencies: + - supports-color + + listr2@8.3.3: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.2 + + local-pkg@1.1.2: + dependencies: + mlly: 1.8.0 + pkg-types: 2.3.0 + quansync: 0.2.11 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + locate-path@7.2.0: + dependencies: + p-locate: 6.0.0 + + lodash-es@4.17.21: {} + + lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21): + dependencies: + '@types/lodash-es': 4.17.12 + lodash: 4.17.21 + lodash-es: 4.17.21 + + lodash.camelcase@4.3.0: {} + + lodash.clonedeep@4.5.0: {} + + lodash.debounce@4.0.8: {} + + lodash.foreach@4.5.0: {} + + lodash.isequal@4.5.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.kebabcase@4.1.1: {} + + lodash.map@4.6.0: {} + + lodash.merge@4.6.2: {} + + lodash.mergewith@4.6.2: {} + + lodash.snakecase@4.1.1: {} + + lodash.startcase@4.4.0: {} + + lodash.throttle@4.1.1: {} + + lodash.toarray@4.4.0: {} + + lodash.truncate@4.4.2: {} + + lodash.uniq@4.5.0: {} + + lodash.upperfirst@4.3.1: {} + + lodash@4.17.21: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + log-update@6.1.0: + dependencies: + ansi-escapes: 7.1.1 + cli-cursor: 5.0.0 + slice-ansi: 7.1.2 + strip-ansi: 7.1.2 + wrap-ansi: 9.0.2 + + longest@2.0.1: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.19: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + math-intrinsics@1.1.0: {} + + mathml-tag-names@2.1.3: {} + + mdn-data@2.12.2: {} + + mdn-data@2.24.0: {} + + memoize-one@6.0.0: {} + + meow@12.1.1: {} + + meow@13.2.0: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + merge@2.1.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-match@1.0.2: + dependencies: + wildcard: 1.1.2 + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mimic-fn@2.1.0: {} + + mimic-fn@4.0.0: {} + + mimic-function@5.0.1: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.2 + + minimist@1.2.7: {} + + minimist@1.2.8: {} + + minipass@7.1.2: {} + + minizlib@3.1.0: + dependencies: + minipass: 7.1.2 + + mitt@3.0.1: {} + + mlly@1.8.0: + dependencies: + acorn: 8.15.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.1 + + mrmime@2.0.1: {} + + ms@2.1.3: {} + + muggle-string@0.4.1: {} + + mute-stream@0.0.8: {} + + namespace-emitter@2.0.1: {} + + nanoid@3.3.11: {} + + nanoid@5.1.6: {} + + natural-compare@1.4.0: {} + + next-tick@1.1.0: {} + + node-addon-api@7.1.1: + optional: true + + node-releases@2.0.21: {} + + normalize-path@3.0.0: {} + + normalize-wheel-es@1.2.0: {} + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + + nprogress@0.2.0: {} + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + ohash@2.0.11: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + open@10.2.0: + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + wsl-utils: 0.1.0 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + 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 + + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + + os-tmpdir@1.0.2: {} + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-limit@4.0.0: + dependencies: + yocto-queue: 1.2.1 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-locate@6.0.0: + dependencies: + p-limit: 4.0.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.27.1 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-ms@4.0.0: {} + + parse-passwd@1.0.0: {} + + path-browserify@1.0.1: {} + + path-exists@4.0.0: {} + + path-exists@5.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-type@4.0.0: {} + + pathe@2.0.3: {} + + perfect-debounce@1.0.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + pidtree@0.6.0: {} + + pinia-plugin-persistedstate@4.5.0(pinia@3.0.3(typescript@5.6.3)(vue@3.5.22(typescript@5.6.3))): + dependencies: + deep-pick-omit: 1.2.1 + defu: 6.1.4 + destr: 2.0.5 + optionalDependencies: + pinia: 3.0.3(typescript@5.6.3)(vue@3.5.22(typescript@5.6.3)) + + pinia@3.0.3(typescript@5.6.3)(vue@3.5.22(typescript@5.6.3)): + dependencies: + '@vue/devtools-api': 7.7.7 + vue: 3.5.22(typescript@5.6.3) + optionalDependencies: + typescript: 5.6.3 + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.0 + pathe: 2.0.3 + + pkg-types@2.3.0: + dependencies: + confbox: 0.2.2 + exsolve: 1.0.7 + pathe: 2.0.3 + + postcss-html@1.8.0: + dependencies: + htmlparser2: 8.0.2 + js-tokens: 9.0.1 + postcss: 8.5.6 + postcss-safe-parser: 6.0.0(postcss@8.5.6) + + postcss-media-query-parser@0.2.3: {} + + postcss-resolve-nested-selector@0.1.6: {} + + postcss-safe-parser@6.0.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-safe-parser@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-scss@4.0.9(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-selector-parser@7.1.0: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-sorting@8.0.2(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-value-parser@4.2.0: {} + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + preact@10.27.2: {} + + prelude-ls@1.2.1: {} + + prettier-linter-helpers@1.0.0: + dependencies: + fast-diff: 1.3.0 + + prettier@3.6.2: {} + + pretty-ms@9.3.0: + dependencies: + parse-ms: 4.0.0 + + prismjs@1.30.0: {} + + proxy-from-env@1.1.0: {} + + punycode@2.3.1: {} + + qrcode.vue@3.6.0(vue@3.5.22(typescript@5.6.3)): + dependencies: + vue: 3.5.22(typescript@5.6.3) + + quansync@0.2.11: {} + + queue-microtask@1.2.3: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + readdirp@4.1.2: {} + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + resolve-dir@1.0.1: + dependencies: + expand-tilde: 2.0.2 + global-modules: 1.0.0 + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + reusify@1.1.0: {} + + rfdc@1.4.1: {} + + rollup-plugin-visualizer@5.14.0(rollup@4.52.3): + dependencies: + open: 8.4.2 + picomatch: 4.0.3 + source-map: 0.7.6 + yargs: 17.7.2 + optionalDependencies: + rollup: 4.52.3 + + rollup@4.52.3: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.52.3 + '@rollup/rollup-android-arm64': 4.52.3 + '@rollup/rollup-darwin-arm64': 4.52.3 + '@rollup/rollup-darwin-x64': 4.52.3 + '@rollup/rollup-freebsd-arm64': 4.52.3 + '@rollup/rollup-freebsd-x64': 4.52.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.52.3 + '@rollup/rollup-linux-arm-musleabihf': 4.52.3 + '@rollup/rollup-linux-arm64-gnu': 4.52.3 + '@rollup/rollup-linux-arm64-musl': 4.52.3 + '@rollup/rollup-linux-loong64-gnu': 4.52.3 + '@rollup/rollup-linux-ppc64-gnu': 4.52.3 + '@rollup/rollup-linux-riscv64-gnu': 4.52.3 + '@rollup/rollup-linux-riscv64-musl': 4.52.3 + '@rollup/rollup-linux-s390x-gnu': 4.52.3 + '@rollup/rollup-linux-x64-gnu': 4.52.3 + '@rollup/rollup-linux-x64-musl': 4.52.3 + '@rollup/rollup-openharmony-arm64': 4.52.3 + '@rollup/rollup-win32-arm64-msvc': 4.52.3 + '@rollup/rollup-win32-ia32-msvc': 4.52.3 + '@rollup/rollup-win32-x64-gnu': 4.52.3 + '@rollup/rollup-win32-x64-msvc': 4.52.3 + fsevents: 2.3.3 + + run-applescript@7.1.0: {} + + run-async@2.4.1: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + sass@1.93.2: + dependencies: + chokidar: 4.0.3 + immutable: 5.1.3 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.1 + + scroll-into-view-if-needed@2.2.31: + dependencies: + compute-scroll-into-view: 1.0.20 + + scule@1.3.0: {} + + semver@6.3.1: {} + + semver@7.7.2: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + sirv@3.0.2: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + + slash@3.0.0: {} + + slate-history@0.66.0(slate@0.72.8): + dependencies: + is-plain-object: 5.0.0 + slate: 0.72.8 + + slate@0.72.8: + dependencies: + immer: 9.0.21 + is-plain-object: 5.0.0 + tiny-warning: 1.0.3 + + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.2: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + + snabbdom@3.6.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: {} + + source-map@0.7.6: {} + + speakingurl@14.0.1: {} + + split2@4.2.0: {} + + ssf@0.11.2: + dependencies: + frac: 1.1.2 + + ssr-window@3.0.0: {} + + string-argv@0.3.2: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.5.0 + get-east-asian-width: 1.4.0 + strip-ansi: 7.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.2: + dependencies: + ansi-regex: 6.2.2 + + strip-bom@4.0.0: {} + + strip-final-newline@3.0.0: {} + + strip-final-newline@4.0.0: {} + + strip-json-comments@3.1.1: {} + + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 + + stylelint-config-html@1.1.0(postcss-html@1.8.0)(stylelint@16.24.0(typescript@5.6.3)): + dependencies: + postcss-html: 1.8.0 + stylelint: 16.24.0(typescript@5.6.3) + + stylelint-config-recess-order@4.6.0(stylelint@16.24.0(typescript@5.6.3)): + dependencies: + stylelint: 16.24.0(typescript@5.6.3) + stylelint-order: 6.0.4(stylelint@16.24.0(typescript@5.6.3)) + + stylelint-config-recommended-scss@14.1.0(postcss@8.5.6)(stylelint@16.24.0(typescript@5.6.3)): + dependencies: + postcss-scss: 4.0.9(postcss@8.5.6) + stylelint: 16.24.0(typescript@5.6.3) + stylelint-config-recommended: 14.0.1(stylelint@16.24.0(typescript@5.6.3)) + stylelint-scss: 6.12.1(stylelint@16.24.0(typescript@5.6.3)) + optionalDependencies: + postcss: 8.5.6 + + stylelint-config-recommended-vue@1.6.1(postcss-html@1.8.0)(stylelint@16.24.0(typescript@5.6.3)): + dependencies: + postcss-html: 1.8.0 + semver: 7.7.2 + stylelint: 16.24.0(typescript@5.6.3) + stylelint-config-html: 1.1.0(postcss-html@1.8.0)(stylelint@16.24.0(typescript@5.6.3)) + stylelint-config-recommended: 17.0.0(stylelint@16.24.0(typescript@5.6.3)) + + stylelint-config-recommended@14.0.1(stylelint@16.24.0(typescript@5.6.3)): + dependencies: + stylelint: 16.24.0(typescript@5.6.3) + + stylelint-config-recommended@17.0.0(stylelint@16.24.0(typescript@5.6.3)): + dependencies: + stylelint: 16.24.0(typescript@5.6.3) + + stylelint-config-standard@36.0.1(stylelint@16.24.0(typescript@5.6.3)): + dependencies: + stylelint: 16.24.0(typescript@5.6.3) + stylelint-config-recommended: 14.0.1(stylelint@16.24.0(typescript@5.6.3)) + + stylelint-order@6.0.4(stylelint@16.24.0(typescript@5.6.3)): + dependencies: + postcss: 8.5.6 + postcss-sorting: 8.0.2(postcss@8.5.6) + stylelint: 16.24.0(typescript@5.6.3) + + stylelint-scss@6.12.1(stylelint@16.24.0(typescript@5.6.3)): + dependencies: + css-tree: 3.1.0 + is-plain-object: 5.0.0 + known-css-properties: 0.36.0 + mdn-data: 2.24.0 + postcss-media-query-parser: 0.2.3 + postcss-resolve-nested-selector: 0.1.6 + postcss-selector-parser: 7.1.0 + postcss-value-parser: 4.2.0 + stylelint: 16.24.0(typescript@5.6.3) + + stylelint@16.24.0(typescript@5.6.3): + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0) + '@dual-bundle/import-meta-resolve': 4.2.1 + balanced-match: 2.0.0 + colord: 2.9.3 + cosmiconfig: 9.0.0(typescript@5.6.3) + css-functions-list: 3.2.3 + css-tree: 3.1.0 + debug: 4.4.3 + fast-glob: 3.3.3 + fastest-levenshtein: 1.0.16 + file-entry-cache: 10.1.4 + global-modules: 2.0.0 + globby: 11.1.0 + globjoin: 0.1.4 + html-tags: 3.3.1 + ignore: 7.0.5 + imurmurhash: 0.1.4 + is-plain-object: 5.0.0 + known-css-properties: 0.37.0 + mathml-tag-names: 2.1.3 + meow: 13.2.0 + micromatch: 4.0.8 + normalize-path: 3.0.0 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-resolve-nested-selector: 0.1.6 + postcss-safe-parser: 7.0.1(postcss@8.5.6) + postcss-selector-parser: 7.1.0 + postcss-value-parser: 4.2.0 + resolve-from: 5.0.0 + string-width: 4.2.3 + supports-hyperlinks: 3.2.0 + svg-tags: 1.0.0 + table: 6.9.0 + write-file-atomic: 5.0.1 + transitivePeerDependencies: + - supports-color + - typescript + + superjson@2.2.2: + dependencies: + copy-anything: 3.0.5 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-hyperlinks@3.2.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + svg-tags@1.0.0: {} + + synckit@0.11.11: + dependencies: + '@pkgr/core': 0.2.9 + + table@6.9.0: + dependencies: + ajv: 8.17.1 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + tailwindcss@4.1.14: {} + + tapable@2.3.0: {} + + tar@7.5.1: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.1.0 + yallist: 5.0.0 + + terser@5.44.0: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.15.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + text-extensions@2.4.0: {} + + through@2.3.8: {} + + tiny-warning@1.0.3: {} + + tinyexec@1.0.1: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + totalist@3.0.1: {} + + ts-api-utils@2.1.0(typescript@5.6.3): + dependencies: + typescript: 5.6.3 + + tslib@2.3.0: {} + + tslib@2.8.1: {} + + tsx@4.20.6: + dependencies: + esbuild: 0.25.10 + get-tsconfig: 4.10.1 + optionalDependencies: + fsevents: 2.3.3 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.20.2: {} + + type-fest@0.21.3: {} + + type@2.7.3: {} + + typescript-eslint@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.44.1(@typescript-eslint/parser@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3))(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3) + '@typescript-eslint/parser': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3) + '@typescript-eslint/typescript-estree': 8.44.1(typescript@5.6.3) + '@typescript-eslint/utils': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.6.3) + eslint: 9.36.0(jiti@2.6.0) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + typescript@5.6.3: {} + + ufo@1.6.1: {} + + undici-types@7.14.0: {} + + unicorn-magic@0.1.0: {} + + unicorn-magic@0.3.0: {} + + unimport@5.4.0: + dependencies: + acorn: 8.15.0 + escape-string-regexp: 5.0.0 + estree-walker: 3.0.3 + local-pkg: 1.1.2 + magic-string: 0.30.19 + mlly: 1.8.0 + pathe: 2.0.3 + picomatch: 4.0.3 + pkg-types: 2.3.0 + scule: 1.3.0 + strip-literal: 3.1.0 + tinyglobby: 0.2.15 + unplugin: 2.3.10 + unplugin-utils: 0.3.0 + + universalify@2.0.1: {} + + unplugin-auto-import@20.2.0(@vueuse/core@13.9.0(vue@3.5.22(typescript@5.6.3))): + dependencies: + local-pkg: 1.1.2 + magic-string: 0.30.19 + picomatch: 4.0.3 + unimport: 5.4.0 + unplugin: 2.3.10 + unplugin-utils: 0.3.0 + optionalDependencies: + '@vueuse/core': 13.9.0(vue@3.5.22(typescript@5.6.3)) + + unplugin-element-plus@0.10.0: + dependencies: + es-module-lexer: 1.7.0 + magic-string: 0.30.19 + unplugin: 2.3.10 + unplugin-utils: 0.2.5 + + unplugin-utils@0.2.5: + dependencies: + pathe: 2.0.3 + picomatch: 4.0.3 + + unplugin-utils@0.3.0: + dependencies: + pathe: 2.0.3 + picomatch: 4.0.3 + + unplugin-vue-components@29.1.0(@babel/parser@7.28.4)(vue@3.5.22(typescript@5.6.3)): + dependencies: + chokidar: 3.6.0 + debug: 4.4.3 + local-pkg: 1.1.2 + magic-string: 0.30.19 + mlly: 1.8.0 + tinyglobby: 0.2.15 + unplugin: 2.3.10 + unplugin-utils: 0.3.0 + vue: 3.5.22(typescript@5.6.3) + optionalDependencies: + '@babel/parser': 7.28.4 + transitivePeerDependencies: + - supports-color + + unplugin@2.3.10: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.15.0 + picomatch: 4.0.3 + webpack-virtual-modules: 0.6.2 + + update-browserslist-db@1.1.3(browserslist@4.26.2): + dependencies: + browserslist: 4.26.2 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + vite-hot-client@2.1.0(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)): + dependencies: + vite: 7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + + vite-plugin-compression@0.5.1(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)): + dependencies: + chalk: 4.1.2 + debug: 4.4.3 + fs-extra: 10.1.0 + vite: 7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + transitivePeerDependencies: + - supports-color + + vite-plugin-inspect@0.8.9(rollup@4.52.3)(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)): + dependencies: + '@antfu/utils': 0.7.10 + '@rollup/pluginutils': 5.3.0(rollup@4.52.3) + debug: 4.4.3 + error-stack-parser-es: 0.1.5 + fs-extra: 11.3.2 + open: 10.2.0 + perfect-debounce: 1.0.0 + picocolors: 1.1.1 + sirv: 3.0.2 + vite: 7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + transitivePeerDependencies: + - rollup + - supports-color + + vite-plugin-vue-devtools@7.7.7(rollup@4.52.3)(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.22(typescript@5.6.3)): + dependencies: + '@vue/devtools-core': 7.7.7(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.22(typescript@5.6.3)) + '@vue/devtools-kit': 7.7.7 + '@vue/devtools-shared': 7.7.7 + execa: 9.6.0 + sirv: 3.0.2 + vite: 7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + vite-plugin-inspect: 0.8.9(rollup@4.52.3)(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + vite-plugin-vue-inspector: 5.3.2(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + transitivePeerDependencies: + - '@nuxt/kit' + - rollup + - supports-color + - vue + + vite-plugin-vue-inspector@5.3.2(vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)): + dependencies: + '@babel/core': 7.28.4 + '@babel/plugin-proposal-decorators': 7.28.0(@babel/core@7.28.4) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.4) + '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.4) + '@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.28.4) + '@vue/compiler-dom': 3.5.22 + kolorist: 1.8.0 + magic-string: 0.30.19 + vite: 7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + transitivePeerDependencies: + - supports-color + + vite@7.1.7(@types/node@24.8.1)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1): + dependencies: + esbuild: 0.25.10 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.52.3 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.8.1 + fsevents: 2.3.3 + jiti: 2.6.0 + lightningcss: 1.30.1 + sass: 1.93.2 + terser: 5.44.0 + tsx: 4.20.6 + yaml: 2.8.1 + + vscode-uri@3.1.0: {} + + vue-demi@0.14.10(vue@3.5.22(typescript@5.6.3)): + dependencies: + vue: 3.5.22(typescript@5.6.3) + + vue-draggable-plus@0.6.0(@types/sortablejs@1.15.8): + dependencies: + '@types/sortablejs': 1.15.8 + + vue-eslint-parser@9.4.3(eslint@9.36.0(jiti@2.6.0)): + dependencies: + debug: 4.4.3 + eslint: 9.36.0(jiti@2.6.0) + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.6.0 + lodash: 4.17.21 + semver: 7.7.2 + transitivePeerDependencies: + - supports-color + + vue-i18n@9.14.5(vue@3.5.22(typescript@5.6.3)): + dependencies: + '@intlify/core-base': 9.14.5 + '@intlify/shared': 9.14.5 + '@vue/devtools-api': 6.6.4 + vue: 3.5.22(typescript@5.6.3) + + vue-img-cutter@3.0.7(typescript@5.6.3): + dependencies: + core-js: 3.45.1 + vue: 3.5.22(typescript@5.6.3) + vue-i18n: 9.14.5(vue@3.5.22(typescript@5.6.3)) + transitivePeerDependencies: + - typescript + + vue-router@4.5.1(vue@3.5.22(typescript@5.6.3)): + dependencies: + '@vue/devtools-api': 6.6.4 + vue: 3.5.22(typescript@5.6.3) + + vue-tsc@2.1.10(typescript@5.6.3): + dependencies: + '@volar/typescript': 2.4.23 + '@vue/language-core': 2.1.10(typescript@5.6.3) + semver: 7.7.2 + typescript: 5.6.3 + + vue@3.5.22(typescript@5.6.3): + dependencies: + '@vue/compiler-dom': 3.5.22 + '@vue/compiler-sfc': 3.5.22 + '@vue/runtime-dom': 3.5.22 + '@vue/server-renderer': 3.5.22(vue@3.5.22(typescript@5.6.3)) + '@vue/shared': 3.5.22 + optionalDependencies: + typescript: 5.6.3 + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + webpack-virtual-modules@0.6.2: {} + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wildcard@1.1.2: {} + + wmf@1.0.2: {} + + word-wrap@1.2.5: {} + + word@0.3.0: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.1.2 + + wrappy@1.0.2: {} + + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + + wsl-utils@0.1.0: + dependencies: + is-wsl: 3.1.0 + + xgplayer-subtitles@3.0.23(core-js@3.45.1): + dependencies: + core-js: 3.45.1 + eventemitter3: 4.0.7 + + xgplayer@3.0.23(core-js@3.45.1): + dependencies: + core-js: 3.45.1 + danmu.js: 1.1.13 + delegate: 3.2.0 + downloadjs: 1.4.7 + eventemitter3: 4.0.7 + xgplayer-subtitles: 3.0.23(core-js@3.45.1) + + xlsx@0.18.5: + dependencies: + adler-32: 1.3.1 + cfb: 1.2.2 + codepage: 1.15.0 + crc-32: 1.2.2 + ssf: 0.11.2 + wmf: 1.0.2 + word: 0.3.0 + + xml-name-validator@4.0.0: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yallist@5.0.0: {} + + yaml@2.8.1: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} + + yocto-queue@1.2.1: {} + + yoctocolors@2.1.2: {} + + zrender@6.0.0: + dependencies: + tslib: 2.3.0 diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/public/favicon.ico differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..3433913 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/api/auth.ts b/src/api/auth.ts new file mode 100644 index 0000000..9dc7b6a --- /dev/null +++ b/src/api/auth.ts @@ -0,0 +1,29 @@ +import request from '@/utils/http' + +/** + * 登录 + * @param params 登录参数 + * @returns 登录响应 + */ +export function fetchLogin(params: Api.Auth.LoginParams) { + return request.post({ + url: '/api/auth/login', + params + // showSuccessMessage: true // 显示成功消息 + // showErrorMessage: false // 不显示错误消息 + }) +} + +/** + * 获取用户信息 + * @returns 用户信息 + */ +export function fetchGetUserInfo() { + return request.get({ + url: '/api/user/info' + // 自定义请求头 + // headers: { + // 'X-Custom-Header': 'your-custom-value' + // } + }) +} diff --git a/src/api/system-manage.ts b/src/api/system-manage.ts new file mode 100644 index 0000000..8f4a8e6 --- /dev/null +++ b/src/api/system-manage.ts @@ -0,0 +1,25 @@ +import request from '@/utils/http' +import { AppRouteRecord } from '@/types/router' + +// 获取用户列表 +export function fetchGetUserList(params: Api.SystemManage.UserSearchParams) { + return request.get({ + url: '/api/user/list', + params + }) +} + +// 获取角色列表 +export function fetchGetRoleList(params: Api.SystemManage.RoleSearchParams) { + return request.get({ + url: '/api/role/list', + params + }) +} + +// 获取菜单列表 +export function fetchGetMenuList() { + return request.get({ + url: '/api/v3/system/menus/simple' + }) +} diff --git a/src/assets/images/avatar/avatar.webp b/src/assets/images/avatar/avatar.webp new file mode 100644 index 0000000..bea307b Binary files /dev/null and b/src/assets/images/avatar/avatar.webp differ diff --git a/src/assets/images/avatar/avatar1.webp b/src/assets/images/avatar/avatar1.webp new file mode 100644 index 0000000..68e256c Binary files /dev/null and b/src/assets/images/avatar/avatar1.webp differ diff --git a/src/assets/images/avatar/avatar10.webp b/src/assets/images/avatar/avatar10.webp new file mode 100644 index 0000000..a813d4c Binary files /dev/null and b/src/assets/images/avatar/avatar10.webp differ diff --git a/src/assets/images/avatar/avatar2.webp b/src/assets/images/avatar/avatar2.webp new file mode 100644 index 0000000..6716e3f Binary files /dev/null and b/src/assets/images/avatar/avatar2.webp differ diff --git a/src/assets/images/avatar/avatar3.webp b/src/assets/images/avatar/avatar3.webp new file mode 100644 index 0000000..7355ad4 Binary files /dev/null and b/src/assets/images/avatar/avatar3.webp differ diff --git a/src/assets/images/avatar/avatar4.webp b/src/assets/images/avatar/avatar4.webp new file mode 100644 index 0000000..56a9549 Binary files /dev/null and b/src/assets/images/avatar/avatar4.webp differ diff --git a/src/assets/images/avatar/avatar5.webp b/src/assets/images/avatar/avatar5.webp new file mode 100644 index 0000000..f78400c Binary files /dev/null and b/src/assets/images/avatar/avatar5.webp differ diff --git a/src/assets/images/avatar/avatar6.webp b/src/assets/images/avatar/avatar6.webp new file mode 100644 index 0000000..9771b78 Binary files /dev/null and b/src/assets/images/avatar/avatar6.webp differ diff --git a/src/assets/images/avatar/avatar7.webp b/src/assets/images/avatar/avatar7.webp new file mode 100644 index 0000000..e5ef6fe Binary files /dev/null and b/src/assets/images/avatar/avatar7.webp differ diff --git a/src/assets/images/avatar/avatar8.webp b/src/assets/images/avatar/avatar8.webp new file mode 100644 index 0000000..b66e48f Binary files /dev/null and b/src/assets/images/avatar/avatar8.webp differ diff --git a/src/assets/images/avatar/avatar9.webp b/src/assets/images/avatar/avatar9.webp new file mode 100644 index 0000000..7974139 Binary files /dev/null and b/src/assets/images/avatar/avatar9.webp differ diff --git a/src/assets/images/ceremony/hb.png b/src/assets/images/ceremony/hb.png new file mode 100644 index 0000000..4103324 Binary files /dev/null and b/src/assets/images/ceremony/hb.png differ diff --git a/src/assets/images/ceremony/sd.png b/src/assets/images/ceremony/sd.png new file mode 100644 index 0000000..75ec838 Binary files /dev/null and b/src/assets/images/ceremony/sd.png differ diff --git a/src/assets/images/ceremony/xc.png b/src/assets/images/ceremony/xc.png new file mode 100644 index 0000000..9c7ab67 Binary files /dev/null and b/src/assets/images/ceremony/xc.png differ diff --git a/src/assets/images/ceremony/yd.png b/src/assets/images/ceremony/yd.png new file mode 100644 index 0000000..426912d Binary files /dev/null and b/src/assets/images/ceremony/yd.png differ diff --git a/src/assets/images/common/logo.webp b/src/assets/images/common/logo.webp new file mode 100644 index 0000000..71542b5 Binary files /dev/null and b/src/assets/images/common/logo.webp differ diff --git a/src/assets/images/draw/draw1.png b/src/assets/images/draw/draw1.png new file mode 100644 index 0000000..da5d87a Binary files /dev/null and b/src/assets/images/draw/draw1.png differ diff --git a/src/assets/images/favicon.ico b/src/assets/images/favicon.ico new file mode 100644 index 0000000..21e7063 Binary files /dev/null and b/src/assets/images/favicon.ico differ diff --git a/src/assets/images/lock/bg_dark.webp b/src/assets/images/lock/bg_dark.webp new file mode 100644 index 0000000..1c33435 Binary files /dev/null and b/src/assets/images/lock/bg_dark.webp differ diff --git a/src/assets/images/lock/bg_light.webp b/src/assets/images/lock/bg_light.webp new file mode 100644 index 0000000..00efbd9 Binary files /dev/null and b/src/assets/images/lock/bg_light.webp differ diff --git a/src/assets/images/login/lf_icon2.webp b/src/assets/images/login/lf_icon2.webp new file mode 100644 index 0000000..5e4f3fd Binary files /dev/null and b/src/assets/images/login/lf_icon2.webp differ diff --git a/src/assets/images/settings/menu_layouts/dual_column.png b/src/assets/images/settings/menu_layouts/dual_column.png new file mode 100644 index 0000000..9b868ca Binary files /dev/null and b/src/assets/images/settings/menu_layouts/dual_column.png differ diff --git a/src/assets/images/settings/menu_layouts/horizontal.png b/src/assets/images/settings/menu_layouts/horizontal.png new file mode 100644 index 0000000..ca779bc Binary files /dev/null and b/src/assets/images/settings/menu_layouts/horizontal.png differ diff --git a/src/assets/images/settings/menu_layouts/mixed.png b/src/assets/images/settings/menu_layouts/mixed.png new file mode 100644 index 0000000..c82b580 Binary files /dev/null and b/src/assets/images/settings/menu_layouts/mixed.png differ diff --git a/src/assets/images/settings/menu_layouts/vertical.png b/src/assets/images/settings/menu_layouts/vertical.png new file mode 100644 index 0000000..16e942b Binary files /dev/null and b/src/assets/images/settings/menu_layouts/vertical.png differ diff --git a/src/assets/images/settings/menu_styles/dark.png b/src/assets/images/settings/menu_styles/dark.png new file mode 100644 index 0000000..e1653b7 Binary files /dev/null and b/src/assets/images/settings/menu_styles/dark.png differ diff --git a/src/assets/images/settings/menu_styles/design.png b/src/assets/images/settings/menu_styles/design.png new file mode 100644 index 0000000..7681aa8 Binary files /dev/null and b/src/assets/images/settings/menu_styles/design.png differ diff --git a/src/assets/images/settings/menu_styles/light.png b/src/assets/images/settings/menu_styles/light.png new file mode 100644 index 0000000..3007b99 Binary files /dev/null and b/src/assets/images/settings/menu_styles/light.png differ diff --git a/src/assets/images/settings/theme_styles/dark.png b/src/assets/images/settings/theme_styles/dark.png new file mode 100644 index 0000000..e8c6e44 Binary files /dev/null and b/src/assets/images/settings/theme_styles/dark.png differ diff --git a/src/assets/images/settings/theme_styles/light.png b/src/assets/images/settings/theme_styles/light.png new file mode 100644 index 0000000..6754238 Binary files /dev/null and b/src/assets/images/settings/theme_styles/light.png differ diff --git a/src/assets/images/settings/theme_styles/system.png b/src/assets/images/settings/theme_styles/system.png new file mode 100644 index 0000000..6a6baa9 Binary files /dev/null and b/src/assets/images/settings/theme_styles/system.png differ diff --git a/src/assets/images/svg/403.svg b/src/assets/images/svg/403.svg new file mode 100644 index 0000000..68790ad --- /dev/null +++ b/src/assets/images/svg/403.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/svg/404.svg b/src/assets/images/svg/404.svg new file mode 100644 index 0000000..48e1ca3 --- /dev/null +++ b/src/assets/images/svg/404.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/svg/500.svg b/src/assets/images/svg/500.svg new file mode 100644 index 0000000..512429f --- /dev/null +++ b/src/assets/images/svg/500.svg @@ -0,0 +1,5 @@ + diff --git a/src/assets/images/svg/login_icon.svg b/src/assets/images/svg/login_icon.svg new file mode 100644 index 0000000..4beb3ab --- /dev/null +++ b/src/assets/images/svg/login_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/user/avatar.webp b/src/assets/images/user/avatar.webp new file mode 100644 index 0000000..6d7234b Binary files /dev/null and b/src/assets/images/user/avatar.webp differ diff --git a/src/assets/images/user/bg.webp b/src/assets/images/user/bg.webp new file mode 100644 index 0000000..762b22d Binary files /dev/null and b/src/assets/images/user/bg.webp differ diff --git a/src/assets/styles/core/app.scss b/src/assets/styles/core/app.scss new file mode 100644 index 0000000..c0efeed --- /dev/null +++ b/src/assets/styles/core/app.scss @@ -0,0 +1,292 @@ +// 全局样式 +// 顶部进度条颜色 +#nprogress .bar { + z-index: 2400; + background-color: color-mix(in srgb, var(--theme-color) 70%, white); +} + +#nprogress .peg { + box-shadow: + 0 0 10px var(--theme-color), + 0 0 5px var(--theme-color) !important; +} + +#nprogress .spinner-icon { + border-top-color: var(--theme-color) !important; + border-left-color: var(--theme-color) !important; +} + +// 处理移动端组件兼容性 +@media screen and (max-width: 640px) { + * { + cursor: default !important; + } +} + +// 背景滤镜 +*, +::before, +::after { + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +// 色弱模式 +.color-weak { + filter: invert(80%); + -webkit-filter: invert(80%); +} + +#noop { + display: none; +} + +// 语言切换选中样式 +.langDropDownStyle { + // 选中项背景颜色 + .is-selected { + background-color: var(--art-el-active-color) !important; + } + + // 语言切换按钮菜单样式优化 + .lang-btn-item { + .el-dropdown-menu__item { + padding-left: 13px !important; + padding-right: 6px !important; + margin-bottom: 3px !important; + } + + &:last-child { + .el-dropdown-menu__item { + margin-bottom: 0 !important; + } + } + + .menu-txt { + min-width: 60px; + display: block; + } + + i { + font-size: 10px; + margin-left: 10px; + } + } +} + +// 盒子默认边框 +.page-content { + border: 1px solid var(--art-card-border) !important; +} + +@mixin art-card-base($border-color, $shadow: none, $radius-diff: 4px) { + background: var(--default-box-color); + border: 1px solid #{$border-color} !important; + border-radius: calc(var(--custom-radius) + #{$radius-diff}) !important; + box-shadow: #{$shadow} !important; + + --el-card-border-color: var(--default-border) !important; +} + +.art-card, +.art-card-sm, +.art-card-xs { + border: 1px solid var(--art-card-border); +} + +// 盒子边框 +[data-box-mode='border-mode'] { + .page-content, + .art-table-card { + border: 1px solid var(--art-card-border) !important; + } + + .art-card { + @include art-card-base(var(--art-card-border), none, 4px); + } + + .art-card-sm { + @include art-card-base(var(--art-card-border), none, 0px); + } + + .art-card-xs { + @include art-card-base(var(--art-card-border), none, -4px); + } +} + +// 盒子阴影 +[data-box-mode='shadow-mode'] { + .page-content, + .art-table-card { + box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.04) !important; + border: 1px solid var(--art-gray-200) !important; + } + + .layout-sidebar { + border-right: 1px solid var(--art-card-border) !important; + } + + .art-card { + @include art-card-base( + var(--art-gray-200), + (0 1px 3px 0 rgba(0, 0, 0, 0.03), 0 1px 2px -1px rgba(0, 0, 0, 0.08)), + 4px + ); + } + + .art-card-sm { + @include art-card-base( + var(--art-gray-200), + (0 1px 3px 0 rgba(0, 0, 0, 0.03), 0 1px 2px -1px rgba(0, 0, 0, 0.08)), + 2px + ); + } + + .art-card-xs { + @include art-card-base( + var(--art-gray-200), + (0 1px 2px 0 rgba(0, 0, 0, 0.03), 0 1px 1px -1px rgba(0, 0, 0, 0.08)), + -4px + ); + } +} + +// 元素全屏 +.el-full-screen { + position: fixed; + top: 0; + left: 0; + right: 0; + width: 100vw !important; + height: 100% !important; + z-index: 2300; + margin-top: 0; + padding: 15px; + box-sizing: border-box; + background-color: var(--default-box-color); + display: flex; + flex-direction: column; +} + +// 表格卡片 +.art-table-card { + flex: 1; + display: flex; + flex-direction: column; + margin-top: 12px; + border-radius: calc(var(--custom-radius) / 2 + 2px) !important; + + .el-card__body { + height: 100%; + overflow: hidden; + } +} + +// 容器全高 +.art-full-height { + height: var(--art-full-height); + display: flex; + flex-direction: column; + + @media (max-width: 640px) { + height: auto; + } +} + +// 徽章样式 +.art-badge { + position: absolute; + top: 0; + right: 20px; + bottom: 0; + width: 6px; + height: 6px; + margin: auto; + background: #ff3860; + border-radius: 50%; + animation: breathe 1.5s ease-in-out infinite; + + &.art-badge-horizontal { + right: 0; + } + + &.art-badge-mixed { + right: 0; + } + + &.art-badge-dual { + right: 5px; + top: 5px; + bottom: auto; + } +} + +// 文字徽章样式 +.art-text-badge { + position: absolute; + top: 0; + right: 12px; + bottom: 0; + min-width: 20px; + height: 18px; + line-height: 17px; + padding: 0 5px; + margin: auto; + font-size: 10px; + color: #fff; + text-align: center; + background: #fd4e4e; + border-radius: 4px; +} + +@keyframes breathe { + 0% { + opacity: 0.7; + transform: scale(1); + } + + 50% { + opacity: 1; + transform: scale(1.1); + } + + 100% { + opacity: 0.7; + transform: scale(1); + } +} + +// 修复老机型 loading 定位问题 +.art-loading-fix { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + bottom: 0 !important; + width: 100vw !important; + height: 100vh !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; +} + +.art-loading-fix .el-loading-spinner { + position: static !important; + top: auto !important; + left: auto !important; + transform: none !important; +} + +// 去除移动端点击背景色 +@media screen and (max-width: 1180px) { + * { + -webkit-tap-highlight-color: transparent; + } +} diff --git a/src/assets/styles/core/dark.scss b/src/assets/styles/core/dark.scss new file mode 100644 index 0000000..c52abc3 --- /dev/null +++ b/src/assets/styles/core/dark.scss @@ -0,0 +1,93 @@ +/* +* 深色主题 +* 单页面移除深色主题 document.getElementsByTagName("html")[0].removeAttribute('class') +*/ + +$font-color: rgba(#ffffff, 0.85); + +/* 覆盖element-plus默认深色背景色 */ +html.dark { + // element-plus + --el-bg-color: var(--default-box-color); + --el-text-color-regular: #{$font-color}; + + // 富文本编辑器 + // 工具栏背景颜色 + --w-e-toolbar-bg-color: #18191c; + // 输入区域背景颜色 + --w-e-textarea-bg-color: #090909; + // 工具栏文字颜色 + --w-e-toolbar-color: var(--art-gray-600); + // 选中菜单颜色 + --w-e-toolbar-active-bg-color: #25262b; + // 弹窗边框颜色 + --w-e-toolbar-border-color: var(--default-border-dashed); + // 分割线颜色 + --w-e-textarea-border-color: var(--default-border-dashed); + // 链接输入框边框颜色 + --w-e-modal-button-border-color: var(--default-border-dashed); + // 表格头颜色 + --w-e-textarea-slight-bg-color: #090909; + // 按钮背景颜色 + --w-e-modal-button-bg-color: #090909; + // hover toolbar 背景颜色 + --w-e-toolbar-active-color: var(--art-gray-800); +} + +.dark { + .page-content .article-list .item .left .outer > div { + border-right-color: var(--dark-border-color) !important; + } + + // 富文本编辑器 + .editor-wrapper { + *:not(pre code *) { + color: inherit !important; + } + } + // 分隔线 + .w-e-bar-divider { + background-color: var(--art-gray-300) !important; + } + + .w-e-select-list, + .w-e-drop-panel, + .w-e-bar-item-group .w-e-bar-item-menus-container, + .w-e-text-container [data-slate-editor] pre > code { + border: 1px solid var(--default-border) !important; + } + + // 下拉选择框 + .w-e-select-list { + background-color: var(--default-box-color) !important; + } + + /* 下拉选择框 hover 样式调整 */ + .w-e-select-list ul li:hover, + /* 工具栏 hover 按钮背景颜色 */ + .w-e-bar-item button:hover { + background-color: #090909 !important; + } + + /* 代码块 */ + .w-e-text-container [data-slate-editor] pre > code { + background-color: #25262b !important; + text-shadow: none !important; + } + + /* 引用 */ + .w-e-text-container [data-slate-editor] blockquote { + border-left: 4px solid var(--default-border-dashed) !important; + background-color: var(--art-color); + } + + .editor-wrapper { + .w-e-text-container [data-slate-editor] .table-container th:last-of-type { + border-right: 1px solid var(--default-border-dashed) !important; + } + + .w-e-modal { + background-color: var(--art-color); + } + } +} diff --git a/src/assets/styles/core/el-dark.scss b/src/assets/styles/core/el-dark.scss new file mode 100644 index 0000000..8f81cdf --- /dev/null +++ b/src/assets/styles/core/el-dark.scss @@ -0,0 +1,2 @@ +// 导入暗黑主题 +@use 'element-plus/theme-chalk/src/dark/css-vars.scss' as *; diff --git a/src/assets/styles/core/el-light.scss b/src/assets/styles/core/el-light.scss new file mode 100644 index 0000000..ddf2bc5 --- /dev/null +++ b/src/assets/styles/core/el-light.scss @@ -0,0 +1,34 @@ +// https://github.com/element-plus/element-plus/blob/dev/packages/theme-chalk/src/common/var.scss +// 自定义Element 亮色主题 + +@forward 'element-plus/theme-chalk/src/common/var.scss' with ( + $colors: ( + 'white': #ffffff, + 'black': #000000, + 'success': ( + 'base': #13deb9 + ), + 'warning': ( + 'base': #ffae1f + ), + 'danger': ( + 'base': #ff4d4f + ), + 'error': ( + 'base': #fa896b + ) + ), + $button: ( + 'hover-bg-color': var(--el-color-primary-light-9), + 'hover-border-color': var(--el-color-primary), + 'border-color': var(--el-color-primary), + 'text-color': var(--el-color-primary) + ), + $messagebox: ( + 'border-radius': '12px' + ), + $popover: ( + 'padding': '14px', + 'border-radius': '10px' + ) +); diff --git a/src/assets/styles/core/el-ui.scss b/src/assets/styles/core/el-ui.scss new file mode 100644 index 0000000..44429a1 --- /dev/null +++ b/src/assets/styles/core/el-ui.scss @@ -0,0 +1,519 @@ +// 优化 Element Plus 组件库默认样式 + +:root { + // 系统主色 + --main-color: var(--el-color-primary); + --el-color-white: white !important; + --el-color-black: white !important; + // 输入框边框颜色 + // --el-border-color: #E4E4E7 !important; // DCDFE6 + // 按钮粗度 + --el-font-weight-primary: 400 !important; + + --el-component-custom-height: 36px !important; + + --el-component-size: var(--el-component-custom-height) !important; + + // 边框、按钮圆角... + --el-border-radius-base: calc(var(--custom-radius) / 3 + 2px) !important; + + --el-border-radius-small: calc(var(--custom-radius) / 3 + 4px) !important; + --el-messagebox-border-radius: calc(var(--custom-radius) / 3 + 4px) !important; + --el-popover-border-radius: calc(var(--custom-radius) / 3 + 4px) !important; + + .region .el-radio-button__original-radio:checked + .el-radio-button__inner { + color: var(--theme-color); + } +} + +// 优化 el-form-item 标签高度 +.el-form-item__label { + height: var(--el-component-custom-height) !important; + line-height: var(--el-component-custom-height) !important; +} + +// 日期选择器 +.el-date-range-picker { + --el-datepicker-inrange-bg-color: var(--art-gray-200) !important; +} + +// el-card 背景色跟系统背景色保持一致 +html.dark .el-card { + --el-card-bg-color: var(--default-box-color) !important; +} + +// 修改 el-pagination 大小 +.el-pagination--default { + & { + --el-pagination-button-width: 32px !important; + --el-pagination-button-height: var(--el-pagination-button-width) !important; + } + + @media (max-width: 1180px) { + & { + --el-pagination-button-width: 28px !important; + } + } + + .el-select--default .el-select__wrapper { + min-height: var(--el-pagination-button-width) !important; + } + + .el-pagination__jump .el-input { + height: var(--el-pagination-button-width) !important; + } +} + +.el-pager li { + padding: 0 10px !important; + // border: 1px solid red !important; +} + +// 优化菜单折叠展开动画(提升动画流畅度) +.el-menu.el-menu--inline { + transition: max-height 0.26s cubic-bezier(0.4, 0, 0.2, 1) !important; +} + +// 优化菜单 item hover 动画(提升鼠标跟手感) +.el-sub-menu__title, +.el-menu-item { + transition: background-color 0s !important; +} + +// -------------------------------- 修改 el-size=default 组件默认高度 start -------------------------------- +// 修改 el-button 高度 +.el-button--default { + height: var(--el-component-custom-height) !important; +} + +// circle 按钮宽度优化 +.el-button--default.is-circle { + width: var(--el-component-custom-height) !important; +} + +// 修改 el-select 高度 +.el-select--default { + .el-select__wrapper { + min-height: var(--el-component-custom-height) !important; + } +} + +// 修改 el-checkbox-button 高度 +.el-checkbox-button--default .el-checkbox-button__inner, +// 修改 el-radio-button 高度 +.el-radio-button--default .el-radio-button__inner { + padding: 10px 15px !important; +} +// -------------------------------- 修改 el-size=default 组件默认高度 end -------------------------------- + +.el-pagination.is-background .btn-next, +.el-pagination.is-background .btn-prev, +.el-pagination.is-background .el-pager li { + border-radius: 6px; +} + +.el-popover { + min-width: 80px; + border-radius: var(--el-border-radius-small) !important; +} + +.el-dialog { + border-radius: 100px !important; + border-radius: calc(var(--custom-radius) / 1.2 + 2px) !important; + overflow: hidden; +} + +.el-dialog__header { + .el-dialog__title { + font-size: 16px; + } +} + +.el-dialog__body { + padding: 25px 0 !important; + position: relative; // 为了兼容 el-pagination 样式,需要设置 relative,不然会影响 el-pagination 的样式,比如 el-pagination__jump--small 会被影响,导致 el-pagination__jump--small 按钮无法点击,详见 URL_ADDRESS.com/element-plus/element-plus/issues/5684#issuecomment-1176299275; +} + +.el-dialog.el-dialog-border { + .el-dialog__body { + // 上边框 + &::before, + // 下边框 + &::after { + content: ''; + position: absolute; + left: -16px; + width: calc(100% + 32px); + height: 1px; + background-color: var(--art-gray-300); + } + + &::before { + top: 0; + } + + &::after { + bottom: 0; + } + } +} + +// el-message 样式优化 +.el-message { + background-color: var(--default-box-color) !important; + border: 0 !important; + box-shadow: + 0 6px 16px 0 rgba(0, 0, 0, 0.08), + 0 3px 6px -4px rgba(0, 0, 0, 0.12), + 0 9px 28px 8px rgba(0, 0, 0, 0.05) !important; + + p { + font-size: 13px; + } +} + +// 修改 el-dropdown 样式 +.el-dropdown-menu { + padding: 6px !important; + border-radius: 10px !important; + border: none !important; + + .el-dropdown-menu__item { + padding: 6px 16px !important; + border-radius: 6px !important; + + &:hover:not(.is-disabled) { + color: var(--art-gray-900) !important; + background-color: var(--art-el-active-color) !important; + } + + &:focus:not(.is-disabled) { + color: var(--art-gray-900) !important; + background-color: var(--art-gray-200) !important; + } + } +} + +// 隐藏 select、dropdown 的三角 +.el-select__popper, +.el-dropdown__popper { + margin-top: -6px !important; + + .el-popper__arrow { + display: none; + } +} + +.el-dropdown-selfdefine:focus { + outline: none !important; +} + +// 处理移动端组件兼容性 +@media screen and (max-width: 640px) { + .el-message-box, + .el-dialog { + width: calc(100% - 24px) !important; + } + + .el-date-picker.has-sidebar.has-time { + width: calc(100% - 24px); + left: 12px !important; + } + + .el-picker-panel *[slot='sidebar'], + .el-picker-panel__sidebar { + display: none; + } + + .el-picker-panel *[slot='sidebar'] + .el-picker-panel__body, + .el-picker-panel__sidebar + .el-picker-panel__body { + margin-left: 0; + } +} + +// 修改el-button样式 +.el-button { + &.el-button--text { + background-color: transparent !important; + padding: 0 !important; + + span { + margin-left: 0 !important; + } + } +} + +// 修改el-tag样式 +.el-tag { + font-weight: 500; + transition: all 0s !important; + + &.el-tag--default { + height: 26px !important; + } +} + +.el-checkbox-group { + &.el-table-filter__checkbox-group label.el-checkbox { + height: 17px !important; + + .el-checkbox__label { + font-weight: 400 !important; + } + } +} + +.el-radio--default { + // 优化单选按钮大小 + .el-radio__input { + .el-radio__inner { + width: 16px; + height: 16px; + + &::after { + width: 6px; + height: 6px; + } + } + } +} + +.el-checkbox { + .el-checkbox__inner { + border-radius: 2px !important; + } +} + +// 优化复选框样式 +.el-checkbox--default { + .el-checkbox__inner { + width: 16px !important; + height: 16px !important; + border-radius: 4px !important; + + &::before { + content: ''; + height: 4px !important; + top: 5px !important; + background-color: #fff !important; + transform: scale(0.6) !important; + } + } + + .is-checked { + .el-checkbox__inner { + &::after { + width: 3px; + height: 8px; + margin: auto; + border: 2px solid var(--el-checkbox-checked-icon-color); + border-left: 0; + border-top: 0; + transform: translate(-45%, -60%) rotate(45deg) scale(0.86) !important; + transform-origin: center; + } + } + } +} + +.el-notification .el-notification__icon { + font-size: 22px !important; +} + +// 修改 el-message-box 样式 +.el-message-box__headerbtn .el-message-box__close, +.el-dialog__headerbtn .el-dialog__close { + top: 7px; + right: 7px; + width: 30px; + height: 30px; + border-radius: 5px; + transition: all 0.3s; + + &:hover { + background-color: var(--art-hover-color) !important; + color: var(--art-gray-900) !important; + } +} + +.el-message-box { + padding: 25px 20px !important; +} + +.el-message-box__title { + font-weight: 500 !important; +} + +.el-table__column-filter-trigger i { + color: var(--theme-color) !important; + margin: -3px 0 0 2px; +} + +// 去除 el-dropdown 鼠标放上去出现的边框 +.el-tooltip__trigger:focus-visible { + outline: unset; +} + +// ipad 表单右侧按钮优化 +@media screen and (max-width: 1180px) { + .el-table-fixed-column--right { + padding-right: 0 !important; + } +} + +.login-out-dialog { + padding: 30px 20px !important; + border-radius: 10px !important; +} + +// 修改 dialog 动画 +.dialog-fade-enter-active { + .el-dialog:not(.is-draggable) { + animation: dialog-open 0.3s cubic-bezier(0.32, 0.14, 0.15, 0.86); + + // 修复 el-dialog 动画后宽度不自适应问题 + .el-select__selected-item { + display: inline-block; + } + } +} + +.dialog-fade-leave-active { + animation: fade-out 0.2s linear; + + .el-dialog:not(.is-draggable) { + animation: dialog-close 0.5s; + } +} + +@keyframes dialog-open { + 0% { + opacity: 0; + transform: scale(0.2); + } + + 100% { + opacity: 1; + transform: scale(1); + } +} + +@keyframes dialog-close { + 0% { + opacity: 1; + transform: scale(1); + } + + 100% { + opacity: 0; + transform: scale(0.2); + } +} + +// 遮罩层动画 +@keyframes fade-out { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +// 修改 el-select 样式 +.el-select__popper:not(.el-tree-select__popper) { + .el-select-dropdown__list { + padding: 5px !important; + + .el-select-dropdown__item { + height: 34px !important; + line-height: 34px !important; + border-radius: 6px !important; + + &.is-selected { + color: var(--art-gray-900) !important; + font-weight: 400 !important; + background-color: var(--art-el-active-color) !important; + margin-bottom: 4px !important; + } + + &:hover { + background-color: var(--art-hover-color) !important; + } + } + + .el-select-dropdown__item:hover ~ .is-selected, + .el-select-dropdown__item.is-selected:has(~ .el-select-dropdown__item:hover) { + background-color: transparent !important; + } + } +} + +// 修改 el-tree-select 样式 +.el-tree-select__popper { + .el-select-dropdown__list { + padding: 5px !important; + + .el-tree-node { + .el-tree-node__content { + height: 36px !important; + border-radius: 6px !important; + + &:hover { + background-color: var(--art-gray-200) !important; + } + } + } + } +} + +// 实现水波纹在文字下面效果 +.el-button > span { + position: relative; + z-index: 10; +} + +// 优化颜色选择器圆角 +.el-color-picker__color { + border-radius: 2px !important; +} + +// 优化日期时间选择器底部圆角 +.el-picker-panel { + .el-picker-panel__footer { + border-radius: 0 0 var(--el-border-radius-base) var(--el-border-radius-base); + } +} + +// 优化树型菜单样式 +.el-tree-node__content { + border-radius: 4px; + margin-bottom: 4px; + padding: 1px 0; + + &:hover { + background-color: var(--art-hover-color) !important; + } +} + +.dark { + .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content { + background-color: var(--art-gray-300) !important; + } +} + +// 隐藏折叠菜单弹窗 hover 出现的边框 +.menu-left-popper:focus-within, +.horizontal-menu-popper:focus-within { + box-shadow: none !important; + outline: none !important; +} + +// 数字输入组件右侧按钮高度跟随自定义组件高度 +.el-input-number--default.is-controls-right { + .el-input-number__decrease, + .el-input-number__increase { + height: calc((var(--el-component-size) / 2)) !important; + } +} diff --git a/src/assets/styles/core/md.scss b/src/assets/styles/core/md.scss new file mode 100644 index 0000000..b22fdc2 --- /dev/null +++ b/src/assets/styles/core/md.scss @@ -0,0 +1,1036 @@ +/* 文章标题设置(h1-h6)*/ +/* ------------------------------------------------ */ +$font-color: #24292e; + +.markdown-body h1, +.markdown-body h2, +.markdown-body h3, +.markdown-body h4, +.markdown-body h5, +.markdown-body h6 { + color: var(--art-gray-800) !important; + margin: 30px 0 10px 0; + font-weight: 600; +} + +.markdown-body h1 { + font-size: 30px; +} + +@media only screen and (max-width: 550px) { + .markdown-body h1 { + font-size: 26px; + } + + .markdown-body h2 { + font-size: 22px; + } + + .markdown-body h3 { + font-size: 18px; + } +} + +/* 块引用 */ +/* ------------------------------------------------ */ +.markdown-body blockquote { + color: rgba(60, 60, 67, 0.7); + font-size: 15px !important; + border-left: 0.18em solid #e7e7e8; + background: #f8f8f8; + padding: 15px 1em; + font-weight: 400 !important; +} + +/* 详情页文章字体颜色 */ +/* ------------------------------------------------ */ +.markdown-body p { + line-height: 28px; + margin-bottom: 10px; +} + +.markdown-body li, +.markdown-body p { + color: var(--art-gray-800) !important; + font-size: 16px !important; +} + +.dark .markdown-body li span { + color: var(--art-gray-800) !important; + background-color: transparent !important; +} + +.dark .markdown-body p span { + color: var(--art-gray-800) !important; + background-color: transparent !important; +} + +.line-numbers-mode { + background-color: var(--art-code-bg); + border-radius: 8px; + position: relative; + padding-left: 32px; + box-sizing: border-box; +} + +.line-numbers-mode pre { + flex: 1; + border-radius: 0 8px 8px 0; + background-color: var(--art-code-bg); +} + +.line-numbers-mode .line-numbers-wrapper { + width: 32px; + height: 100%; + text-align: center; + padding: 16px 0; + box-sizing: border-box; + border-right: 1px solid #000000; + position: absolute; + left: 0; + top: 0; +} + +.line-numbers-mode .line-numbers-wrapper span { + height: 23.6px; + line-height: 23.6px; + display: block; + color: #72747b; + font-size: 13px; + box-sizing: border-box; +} + +.line-numbers-mode .copy-btn { + display: inline-block; + display: flex; + position: absolute; + right: 10px; + top: 10px; + cursor: pointer; + opacity: 0; + background-color: #000; + border-radius: 5px; + text-align: center; + color: rgba(255, 255, 255, 0.6); + transition: opacity 0.3s; +} + +.line-numbers-mode .copy-btn div { + width: 34px; + height: 34px; + line-height: 34px; + cursor: pointer; + text-align: center; + font-size: 20px; +} + +.line-numbers-mode:hover .copy-btn { + opacity: 1; +} + +.line-numbers-mode .copy-btn span { + height: 34px; + line-height: 34px; + font-size: 13px; + padding-left: 10px; + display: none; +} + +.line-numbers-mode .copy-btn .show-copy { + opacity: 1; + display: block; +} + +.line-numbers-mode ::-webkit-scrollbar-track { + background-color: #292b30 !important; +} + +.markdown-body .anchor { + float: left; + line-height: 1; + margin-left: -20px; + padding-right: 4px; +} + +.markdown-body .anchor:focus { + outline: none; +} + +.markdown-body h1 .octicon-link, +.markdown-body h2 .octicon-link, +.markdown-body h3 .octicon-link, +.markdown-body h4 .octicon-link, +.markdown-body h5 .octicon-link, +.markdown-body h6 .octicon-link { + color: #1b1f23; + vertical-align: middle; + visibility: hidden; +} + +.markdown-body h1:hover .anchor, +.markdown-body h2:hover .anchor, +.markdown-body h3:hover .anchor, +.markdown-body h4:hover .anchor, +.markdown-body h5:hover .anchor, +.markdown-body h6:hover .anchor { + text-decoration: none; +} + +.markdown-body h1:hover .anchor .octicon-link, +.markdown-body h2:hover .anchor .octicon-link, +.markdown-body h3:hover .anchor .octicon-link, +.markdown-body h4:hover .anchor .octicon-link, +.markdown-body h5:hover .anchor .octicon-link, +.markdown-body h6:hover .anchor .octicon-link { + visibility: visible; +} + +.markdown-body h1:hover .anchor .octicon-link:before, +.markdown-body h2:hover .anchor .octicon-link:before, +.markdown-body h3:hover .anchor .octicon-link:before, +.markdown-body h4:hover .anchor .octicon-link:before, +.markdown-body h5:hover .anchor .octicon-link:before, +.markdown-body h6:hover .anchor .octicon-link:before { + width: 16px; + height: 16px; + content: ' '; + display: inline-block; +} + +.markdown-body { + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + line-height: 1.5; + color: $font-color; + font-size: 16px; + line-height: 1.5; + word-wrap: break-word; +} + +.markdown-body details { + display: block; +} + +.markdown-body summary { + display: list-item; +} + +.markdown-body a { + background-color: initial; +} + +.markdown-body a:active, +.markdown-body a:hover { + outline-width: 0; +} + +.markdown-body strong { + font-weight: inherit; + font-weight: bolder; +} + +.markdown-body p br { + display: inline; + line-height: 11px; +} + +.markdown-body img { + border-style: none; +} + +.markdown-body hr { + box-sizing: initial; + height: 0; + overflow: visible; +} + +.markdown-body input { + font: inherit; + margin: 0; +} + +.markdown-body input { + overflow: visible; +} + +.markdown-body [type='checkbox'] { + box-sizing: border-box; + padding: 0; +} + +.markdown-body * { + box-sizing: border-box; +} + +.markdown-body input { + font-size: inherit; + line-height: inherit; +} + +.markdown-body a { + color: #0366d6; + text-decoration: none; +} + +.markdown-body a:hover { + text-decoration: underline; +} + +.markdown-body strong { + font-weight: 600; +} + +.markdown-body hr { + height: 0; + margin: 15px 0; + overflow: hidden; + background: transparent; + border: 0; + border-bottom: 1px solid #dfe2e5; +} + +.markdown-body hr:after, +.markdown-body hr:before { + display: table; + content: ''; +} + +.markdown-body hr:after { + clear: both; +} + +.markdown-body table { + border-spacing: 0; + border-collapse: collapse; +} + +.markdown-body td, +.markdown-body th { + padding: 0; +} + +.markdown-body details summary { + cursor: pointer; +} + +.markdown-body kbd { + display: inline-block; + padding: 3px 5px; + font: + 11px SFMono-Regular, + Consolas, + Liberation Mono, + Menlo, + monospace; + line-height: 10px; + color: #444d56; + vertical-align: middle; + background-color: #fafbfc; + border: 1px solid #d1d5da; + border-radius: 3px; + box-shadow: inset 0 -1px 0 #d1d5da; +} + +.markdown-body blockquote { + margin: 0; +} + +.markdown-body ol, +.markdown-body ul { + padding-left: 0; + margin-top: 0; + margin-bottom: 0; +} + +.markdown-body ol ol, +.markdown-body ul ol { + list-style-type: lower-roman; +} + +.markdown-body ol ol ol, +.markdown-body ol ul ol, +.markdown-body ul ol ol, +.markdown-body ul ul ol { + list-style-type: lower-alpha; +} + +.markdown-body dd { + margin-left: 0; +} + +.markdown-body code, +.markdown-body pre, +.markdown-body .line-number { + font-size: 14px !important; + border-radius: 8px; + background-color: #282c34; +} + +.dark { + .markdown-body code, + .markdown-body pre, + .markdown-body .line-number { + background-color: #252525; + } +} + +.markdown-body pre { + margin-top: 0; + margin-bottom: 0; +} + +.markdown-body input::-webkit-inner-spin-button, +.markdown-body input::-webkit-outer-spin-button { + margin: 0; + -webkit-appearance: none; + appearance: none; +} + +.markdown-body :checked + .radio-label { + position: relative; + z-index: 1; + border-color: #0366d6; +} + +.markdown-body .border { + border: 1px solid #e1e4e8 !important; +} + +.markdown-body .border-0 { + border: 0 !important; +} + +.markdown-body .border-bottom { + border-bottom: 1px solid #e1e4e8 !important; +} + +.markdown-body .rounded-1 { + border-radius: 3px !important; +} + +.markdown-body .bg-white { + background-color: #fff !important; +} + +.markdown-body .bg-gray-light { + background-color: #fafbfc !important; +} + +.markdown-body .text-gray-light { + color: #6a737d !important; +} + +.markdown-body .mb-0 { + margin-bottom: 0 !important; +} + +.markdown-body .my-2 { + margin-top: 8px !important; + margin-bottom: 8px !important; +} + +.markdown-body .pl-0 { + padding-left: 0 !important; +} + +.markdown-body .py-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.markdown-body .pl-1 { + padding-left: 4px !important; +} + +.markdown-body .pl-2 { + padding-left: 8px !important; +} + +.markdown-body .py-2 { + padding-top: 8px !important; + padding-bottom: 8px !important; +} + +.markdown-body .pl-3, +.markdown-body .px-3 { + padding-left: 16px !important; +} + +.markdown-body .px-3 { + padding-right: 16px !important; +} + +.markdown-body .pl-4 { + padding-left: 24px !important; +} + +.markdown-body .pl-5 { + padding-left: 32px !important; +} + +.markdown-body .pl-6 { + padding-left: 40px !important; +} + +.markdown-body .f6 { + font-size: 12px !important; +} + +.markdown-body .lh-condensed { + line-height: 1.25 !important; +} + +.markdown-body .text-bold { + font-weight: 600 !important; +} + +.markdown-body .pl-c { + color: #6a737d; +} + +.markdown-body .pl-c1, +.markdown-body .pl-s .pl-v { + color: #005cc5; +} + +.markdown-body .pl-e, +.markdown-body .pl-en { + color: #6f42c1; +} + +.markdown-body .pl-s .pl-s1, +.markdown-body .pl-smi { + color: $font-color; +} + +.markdown-body .pl-ent { + color: #22863a; +} + +.markdown-body .pl-k { + color: #d73a49; +} + +.markdown-body .pl-pds, +.markdown-body .pl-s, +.markdown-body .pl-s .pl-pse .pl-s1, +.markdown-body .pl-sr, +.markdown-body .pl-sr .pl-cce, +.markdown-body .pl-sr .pl-sra, +.markdown-body .pl-sr .pl-sre { + color: #032f62; +} + +.markdown-body .pl-smw, +.markdown-body .pl-v { + color: #e36209; +} + +.markdown-body .pl-bu { + color: #b31d28; +} + +.markdown-body .pl-ii { + color: #fafbfc; + background-color: #b31d28; +} + +.markdown-body .pl-c2 { + color: #fafbfc; + background-color: #d73a49; +} + +.markdown-body .pl-c2:before { + content: '^M'; +} + +.markdown-body .pl-sr .pl-cce { + font-weight: 700; + color: #22863a; +} + +.markdown-body .pl-ml { + color: #735c0f; +} + +.markdown-body .pl-mh, +.markdown-body .pl-mh .pl-en, +.markdown-body .pl-ms { + font-weight: 700; + color: #005cc5; +} + +.markdown-body .pl-mi { + font-style: italic; + color: $font-color; +} + +.markdown-body .pl-mb { + font-weight: 700; + color: $font-color; +} + +.markdown-body .pl-md { + color: #b31d28; + background-color: #ffeef0; +} + +.markdown-body .pl-mi1 { + color: #22863a; + background-color: #f0fff4; +} + +.markdown-body .pl-mc { + color: #e36209; + background-color: #ffebda; +} + +.markdown-body .pl-mi2 { + color: #f6f8fa; + background-color: #005cc5; +} + +.markdown-body .pl-mdr { + font-weight: 700; + color: #6f42c1; +} + +.markdown-body .pl-ba { + color: #586069; +} + +.markdown-body .pl-sg { + color: #959da5; +} + +.markdown-body .pl-corl { + text-decoration: underline; + color: #032f62; +} + +.markdown-body .mb-0 { + margin-bottom: 0 !important; +} + +.markdown-body .my-2 { + margin-bottom: 8px !important; +} + +.markdown-body .my-2 { + margin-top: 8px !important; +} + +.markdown-body .pl-0 { + padding-left: 0 !important; +} + +.markdown-body .py-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.markdown-body .pl-1 { + padding-left: 4px !important; +} + +.markdown-body .pl-2 { + padding-left: 8px !important; +} + +.markdown-body .py-2 { + padding-top: 8px !important; + padding-bottom: 8px !important; +} + +.markdown-body .pl-3 { + padding-left: 16px !important; +} + +.markdown-body .pl-4 { + padding-left: 24px !important; +} + +.markdown-body .pl-5 { + padding-left: 32px !important; +} + +.markdown-body .pl-6 { + padding-left: 40px !important; +} + +.markdown-body .pl-7 { + padding-left: 48px !important; +} + +.markdown-body .pl-8 { + padding-left: 64px !important; +} + +.markdown-body .pl-9 { + padding-left: 80px !important; +} + +.markdown-body .pl-10 { + padding-left: 96px !important; +} + +.markdown-body .pl-11 { + padding-left: 112px !important; +} + +.markdown-body .pl-12 { + padding-left: 128px !important; +} + +.markdown-body hr { + border-bottom-color: #eee; +} + +.markdown-body kbd { + display: inline-block; + padding: 3px 5px; + font: + 11px SFMono-Regular, + Consolas, + Liberation Mono, + Menlo, + monospace; + line-height: 10px; + color: #444d56; + vertical-align: middle; + background-color: #fafbfc; + border: 1px solid #d1d5da; + border-radius: 3px; + box-shadow: inset 0 -1px 0 #d1d5da; +} + +.markdown-body:after, +.markdown-body:before { + display: table; + content: ''; +} + +.markdown-body:after { + clear: both; +} + +.markdown-body > :first-child { + margin-top: 0 !important; +} + +.markdown-body > :last-child { + margin-bottom: 0 !important; +} + +.markdown-body a:not([href]) { + color: inherit; + text-decoration: none; +} + +.markdown-body blockquote, +.markdown-body details, +.markdown-body dl, +.markdown-body ol, +.markdown-body pre, +.markdown-body table, +.markdown-body ul { + margin-top: 0; + margin-bottom: 16px; +} + +.markdown-body hr { + height: 0.25em; + padding: 0; + margin: 24px 0; + background-color: #e1e4e8; + border: 0; +} + +.markdown-body blockquote > :first-child { + margin-top: 0; +} + +.markdown-body blockquote > :last-child { + margin-bottom: 0; +} + +.markdown-body ol, +.markdown-body ul { + padding-left: 1em; +} + +.markdown-body ol ol, +.markdown-body ol ul, +.markdown-body ul ol, +.markdown-body ul ul { + margin-top: 0; + margin-bottom: 0; +} + +.markdown-body li { + line-height: 28px; + font-size: 14px; + word-wrap: break-all; + list-style: disc; + margin-left: 10px; +} + +.markdown-body li > p { + margin-top: 16px; +} + +.markdown-body li + li { + margin-top: 0.25em; +} + +.markdown-body dl { + padding: 0; +} + +.markdown-body dl dt { + padding: 0; + margin-top: 16px; + font-size: 1em; + font-style: italic; + font-weight: 600; +} + +.markdown-body dl dd { + padding: 0 16px; + margin-bottom: 16px; +} + +.markdown-body table { + display: block; + width: 100%; + overflow: auto; +} + +.markdown-body table th { + font-weight: 600; +} + +.markdown-body table td, +.markdown-body table th { + padding: 6px 13px; + border: 1px solid #dfe2e5; +} + +.markdown-body table tr { + background-color: #fff; + border-top: 1px solid #c6cbd1; +} + +.markdown-body table tr:nth-child(2n) { + background-color: #f6f8fa; +} + +.markdown-body img { + max-width: 100%; + box-sizing: initial; + background-color: #fff; + border: 1px solid #eee; + border: 1px solid var(--art-c-border-2); + cursor: zoom-in; +} + +.markdown-body img[align='right'] { + padding-left: 20px; +} + +.markdown-body img[align='left'] { + padding-right: 20px; +} + +.markdown-body code { + padding: 0.2em 0.4em; + margin: 0; + font-size: 85%; + background-color: rgba(27, 31, 35, 0.05); + border-radius: 3px; +} + +.markdown-body pre { + word-wrap: normal; +} + +.markdown-body pre > code { + padding: 0; + margin: 0; + font-size: 100%; + word-break: normal; + white-space: pre; + background: transparent; + border: 0; +} + +.markdown-body .highlight { + margin-bottom: 16px; +} + +.markdown-body .highlight pre { + margin-bottom: 0; + word-break: normal; +} + +.markdown-body .highlight pre, +.markdown-body pre { + padding: 15px 20px 15px 0; + overflow: auto; + font-size: 92%; + line-height: 1.6; +} + +.markdown-body pre code { + display: inline; + max-width: auto; + padding: 0; + margin: 0; + overflow: visible; + line-height: inherit; + word-wrap: normal; + background-color: initial; + border: 0; +} + +.markdown-body .commit-tease-sha { + display: inline-block; + font-size: 90%; + color: #444d56; +} + +.markdown-body .full-commit .btn-outline:not(:disabled):hover { + color: #005cc5; + border-color: #005cc5; +} + +.markdown-body .blob-wrapper { + overflow-x: auto; + overflow-y: hidden; +} + +.markdown-body .blob-wrapper-embedded { + max-height: 240px; + overflow-y: auto; +} + +.markdown-body .blob-num { + width: 1%; + min-width: 50px; + padding-right: 10px; + padding-left: 10px; + font-size: 12px; + line-height: 20px; + color: rgba(27, 31, 35, 0.3); + text-align: right; + white-space: nowrap; + vertical-align: top; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.markdown-body .blob-num:hover { + color: rgba(27, 31, 35, 0.6); +} + +.markdown-body .blob-num:before { + content: attr(data-line-number); +} + +.markdown-body .blob-code { + position: relative; + padding-right: 10px; + padding-left: 10px; + line-height: 20px; + vertical-align: top; +} + +.markdown-body .blob-code-inner { + overflow: visible; + font-size: 12px; + color: $font-color; + word-wrap: normal; + white-space: pre; +} + +.markdown-body .pl-token.active, +.markdown-body .pl-token:hover { + cursor: pointer; + background: #ffea7f; +} + +.markdown-body .tab-size[data-tab-size='1'] { + -moz-tab-size: 1; + tab-size: 1; +} + +.markdown-body .tab-size[data-tab-size='2'] { + -moz-tab-size: 2; + tab-size: 2; +} + +.markdown-body .tab-size[data-tab-size='3'] { + -moz-tab-size: 3; + tab-size: 3; +} + +.markdown-body .tab-size[data-tab-size='4'] { + -moz-tab-size: 4; + tab-size: 4; +} + +.markdown-body .tab-size[data-tab-size='5'] { + -moz-tab-size: 5; + tab-size: 5; +} + +.markdown-body .tab-size[data-tab-size='6'] { + -moz-tab-size: 6; + tab-size: 6; +} + +.markdown-body .tab-size[data-tab-size='7'] { + -moz-tab-size: 7; + tab-size: 7; +} + +.markdown-body .tab-size[data-tab-size='8'] { + -moz-tab-size: 8; + tab-size: 8; +} + +.markdown-body .tab-size[data-tab-size='9'] { + -moz-tab-size: 9; + tab-size: 9; +} + +.markdown-body .tab-size[data-tab-size='10'] { + -moz-tab-size: 10; + tab-size: 10; +} + +.markdown-body .tab-size[data-tab-size='11'] { + -moz-tab-size: 11; + tab-size: 11; +} + +.markdown-body .tab-size[data-tab-size='12'] { + -moz-tab-size: 12; + tab-size: 12; +} + +.markdown-body .task-list-item { + list-style-type: none; +} + +.markdown-body .task-list-item + .task-list-item { + margin-top: 3px; +} + +.markdown-body .task-list-item input { + margin: 0 0.2em 0.25em -1.6em; + vertical-align: middle; +} diff --git a/src/assets/styles/core/mixin.scss b/src/assets/styles/core/mixin.scss new file mode 100644 index 0000000..db36888 --- /dev/null +++ b/src/assets/styles/core/mixin.scss @@ -0,0 +1,157 @@ +// sass 混合宏(函数) + +/** +* 溢出省略号 +* @param {Number} 行数 +*/ +@mixin ellipsis($rowCount: 1) { + @if $rowCount <=1 { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } @else { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: $rowCount; + -webkit-box-orient: vertical; + } +} + +/** +* 控制用户能否选中文本 +* @param {String} 类型 +*/ +@mixin userSelect($value: none) { + user-select: $value; + -moz-user-select: $value; + -ms-user-select: $value; + -webkit-user-select: $value; +} + +// 绝对定位居中 +@mixin absoluteCenter() { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + margin: auto; +} + +/** +* css3动画 +* +*/ +@mixin animation( + $from: ( + width: 0px + ), + $to: ( + width: 100px + ), + $name: mymove, + $animate: mymove 2s 1 linear infinite +) { + -webkit-animation: $animate; + -o-animation: $animate; + animation: $animate; + + @keyframes #{$name} { + from { + @each $key, $value in $from { + #{$key}: #{$value}; + } + } + + to { + @each $key, $value in $to { + #{$key}: #{$value}; + } + } + } + + @-webkit-keyframes #{$name} { + from { + @each $key, $value in $from { + $key: $value; + } + } + + to { + @each $key, $value in $to { + $key: $value; + } + } + } +} + +// 圆形盒子 +@mixin circle($size: 11px, $bg: #fff) { + border-radius: 50%; + width: $size; + height: $size; + line-height: $size; + text-align: center; + background: $bg; +} + +// placeholder +@mixin placeholder($color: #bbb) { + // Firefox + &::-moz-placeholder { + color: $color; + opacity: 1; + } + + // Internet Explorer 10+ + &:-ms-input-placeholder { + color: $color; + } + + // Safari and Chrome + &::-webkit-input-placeholder { + color: $color; + } + + &:placeholder-shown { + text-overflow: ellipsis; + } +} + +//背景透明,文字不透明。兼容IE8 +@mixin betterTransparentize($color, $alpha) { + $c: rgba($color, $alpha); + $ie_c: ie_hex_str($c); + background: rgba($color, 1); + background: $c; + background: transparent \9; + zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#{$ie_c}, endColorstr=#{$ie_c}); + -ms-filter: 'progid:DXImageTransform.Microsoft.gradient(startColorstr=#{$ie_c}, endColorstr=#{$ie_c})'; +} + +//添加浏览器前缀 +@mixin browserPrefix($propertyName, $value) { + @each $prefix in -webkit-, -moz-, -ms-, -o-, '' { + #{$prefix}#{$propertyName}: $value; + } +} + +// 边框 +@mixin border($color: red) { + border: 1px solid $color; +} + +// 背景滤镜 +@mixin backdropBlur() { + --tw-backdrop-blur: blur(30px); + -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) + var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) + var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) + var(--tw-backdrop-sepia); + backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) + var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) + var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); +} diff --git a/src/assets/styles/core/reset.scss b/src/assets/styles/core/reset.scss new file mode 100644 index 0000000..17a3bcf --- /dev/null +++ b/src/assets/styles/core/reset.scss @@ -0,0 +1,41 @@ +@charset "UTF-8"; + +/*滚动条*/ +/*滚动条整体部分,必须要设置*/ +::-webkit-scrollbar { + width: 8px !important; + height: 0 !important; +} + +/*滚动条的轨道*/ +::-webkit-scrollbar-track { + background-color: var(--art-gray-200); +} + +/*滚动条的滑块按钮*/ +::-webkit-scrollbar-thumb { + border-radius: 5px; + background-color: #cccccc !important; + transition: all 0.2s; + -webkit-transition: all 0.2s; +} + +::-webkit-scrollbar-thumb:hover { + background-color: #b0abab !important; +} + +/*滚动条的上下两端的按钮*/ +::-webkit-scrollbar-button { + height: 0px; + width: 0; +} + +.dark { + ::-webkit-scrollbar-track { + background-color: var(--default-bg-color); + } + + ::-webkit-scrollbar-thumb { + background-color: var(--art-gray-300) !important; + } +} diff --git a/src/assets/styles/core/router-transition.scss b/src/assets/styles/core/router-transition.scss new file mode 100644 index 0000000..f47c741 --- /dev/null +++ b/src/assets/styles/core/router-transition.scss @@ -0,0 +1,104 @@ +@use 'sass:map'; + +// === 变量区域 === +$transition: ( + // 动画持续时间 + duration: 0.25s, + // 滑动动画的移动距离 + distance: 15px, + // 默认缓动函数 + easing: cubic-bezier(0.25, 0.1, 0.25, 1), + // 淡入淡出专用的缓动函数 + fade-easing: cubic-bezier(0.4, 0, 0.6, 1) +); + +// 抽取配置值函数,提高可复用性 +@function transition-config($key) { + @return map.get($transition, $key); +} + +// 变量简写 +$duration: transition-config('duration'); +$distance: transition-config('distance'); +$easing: transition-config('easing'); +$fade-easing: transition-config('fade-easing'); + +// === 动画类 === + +// 淡入淡出动画 +.fade { + &-enter-active, + &-leave-active { + transition: opacity $duration $fade-easing; + will-change: opacity; + } + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-to, + &-leave-from { + opacity: 1; + } +} + +// 滑动动画通用样式 +@mixin slide-transition($direction) { + $distance-x: 0; + $distance-y: 0; + + @if $direction == 'left' { + $distance-x: -$distance; + } @else if $direction == 'right' { + $distance-x: $distance; + } @else if $direction == 'top' { + $distance-y: -$distance; + } @else if $direction == 'bottom' { + $distance-y: $distance; + } + + &-enter-active { + transition: + opacity $duration $easing, + transform $duration $easing; + will-change: opacity, transform; + } + + &-leave-active { + transition: + opacity calc($duration * 0.7) $easing, + transform calc($duration * 0.7) $easing; + will-change: opacity, transform; + } + + &-enter-from { + opacity: 0; + transform: translate3d($distance-x, $distance-y, 0); + } + + &-enter-to { + opacity: 1; + transform: translate3d(0, 0, 0); + } + + &-leave-to { + opacity: 0; + transform: translate3d(-$distance-x, -$distance-y, 0); + } +} + +// 滑动动画方向类 +.slide-left { + @include slide-transition('left'); +} +.slide-right { + @include slide-transition('right'); +} +.slide-top { + @include slide-transition('top'); +} +.slide-bottom { + @include slide-transition('bottom'); +} diff --git a/src/assets/styles/core/tailwind.css b/src/assets/styles/core/tailwind.css new file mode 100644 index 0000000..1a9e22c --- /dev/null +++ b/src/assets/styles/core/tailwind.css @@ -0,0 +1,208 @@ +@import 'tailwindcss'; +@custom-variant dark (&:where(.dark, .dark *)); + +/* ==================== Light Mode Variables ==================== */ +:root { + /* Base Colors */ + --art-color: #ffffff; + --theme-color: var(--main-color); + + /* Theme Colors - OKLCH Format */ + --art-primary: oklch(0.7 0.23 260); + --art-secondary: oklch(0.72 0.19 231.6); + --art-error: oklch(0.73 0.15 25.3); + --art-info: oklch(0.58 0.03 254.1); + --art-success: oklch(0.78 0.17 166.1); + --art-warning: oklch(0.78 0.14 75.5); + --art-danger: oklch(0.68 0.22 25.3); + + /* Gray Scale - Light Mode */ + --art-gray-100: #f9fafb; + --art-gray-200: #f2f4f5; + --art-gray-300: #e6eaeb; + --art-gray-400: #dbdfe1; + --art-gray-500: #949eb7; + --art-gray-600: #7987a1; + --art-gray-700: #4d5875; + --art-gray-800: #383853; + --art-gray-900: #323251; + + /* Border Colors */ + --art-card-border: rgba(0, 0, 0, 0.08); + + --default-border: #e2e8ee; + --default-border-dashed: #dbdfe9; + + /* Background Colors */ + --default-bg-color: #fafbfc; + --default-box-color: #ffffff; + + /* Hover Color */ + --art-hover-color: #edeff0; + + /* Active Color */ + --art-active-color: #f2f4f5; + + /* Element Component Active Color */ + --art-el-active-color: #f2f4f5; +} + +/* ==================== Dark Mode Variables ==================== */ +.dark { + /* Base Colors */ + --art-color: #000000; + + /* Gray Scale - Dark Mode */ + --art-gray-100: #110f0f; + --art-gray-200: #17171c; + --art-gray-300: #393946; + --art-gray-400: #505062; + --art-gray-500: #73738c; + --art-gray-600: #8f8fa3; + --art-gray-700: #ababba; + --art-gray-800: #c7c7d1; + --art-gray-900: #e3e3e8; + + /* Border Colors */ + --art-card-border: rgba(255, 255, 255, 0.08); + + --default-border: rgba(255, 255, 255, 0.1); + --default-border-dashed: #363843; + + /* Background Colors */ + --default-bg-color: #070707; + --default-box-color: #161618; + + /* Hover Color */ + --art-hover-color: #252530; + + /* Active Color */ + --art-active-color: #202226; + + /* Element Component Active Color */ + --art-el-active-color: #2e2e38; +} + +/* ==================== Tailwind Theme Configuration ==================== */ +@theme { + /* Box Color (Light: white / Dark: black) */ + --color-box: var(--default-box-color); + + /* System Theme Color */ + --color-theme: var(--theme-color); + + /* Hover Color */ + --color-hover-color: var(--art-hover-color); + + /* Active Color */ + --color-active-color: var(--art-active-color); + + /* Active Color */ + --color-el-active-color: var(--art-active-color); + + /* ElementPlus Theme Colors */ + --color-primary: var(--art-primary); + --color-secondary: var(--art-secondary); + --color-error: var(--art-error); + --color-info: var(--art-info); + --color-success: var(--art-success); + --color-warning: var(--art-warning); + --color-danger: var(--art-danger); + + /* Gray Scale Colors (Auto-adapts to dark mode) */ + --color-g-100: var(--art-gray-100); + --color-g-200: var(--art-gray-200); + --color-g-300: var(--art-gray-300); + --color-g-400: var(--art-gray-400); + --color-g-500: var(--art-gray-500); + --color-g-600: var(--art-gray-600); + --color-g-700: var(--art-gray-700); + --color-g-800: var(--art-gray-800); + --color-g-900: var(--art-gray-900); +} + +/* ==================== Custom Border Radius Utilities ==================== */ +@utility rounded-custom-xs { + border-radius: calc(var(--custom-radius) / 2); +} + +@utility rounded-custom-sm { + border-radius: calc(var(--custom-radius) / 2 + 2px); +} + +/* ==================== Custom Utility Classes ==================== */ +@layer utilities { + /* Flexbox Layout Utilities */ + .flex-c { + @apply flex items-center; + } + + .flex-b { + @apply flex justify-between; + } + + .flex-cc { + @apply flex items-center justify-center; + } + + .flex-cb { + @apply flex items-center justify-between; + } + + /* Transition Utilities */ + .tad-200 { + @apply transition-all duration-200; + } + + .tad-300 { + @apply transition-all duration-300; + } + + /* Border Utilities */ + .border-full-d { + @apply border border-[var(--default-border)]; + } + + .border-b-d { + @apply border-b border-[var(--default-border)]; + } + + .border-t-d { + @apply border-t border-[var(--default-border)]; + } + + .border-l-d { + @apply border-l border-[var(--default-border)]; + } + + .border-r-d { + @apply border-r border-[var(--default-border)]; + } + + /* Cursor Utilities */ + .c-p { + @apply cursor-pointer; + } +} + +/* ==================== Custom Component Classes ==================== */ +@layer components { + /* Art Card Header Component */ + .art-card-header { + @apply flex justify-between pr-6 pb-1; + + .title { + h4 { + @apply text-lg font-medium text-g-900; + } + + p { + @apply mt-1 text-sm text-g-600; + + span { + @apply ml-2 font-medium; + } + } + } + } +} diff --git a/src/assets/styles/core/theme-animation.scss b/src/assets/styles/core/theme-animation.scss new file mode 100644 index 0000000..377b945 --- /dev/null +++ b/src/assets/styles/core/theme-animation.scss @@ -0,0 +1,63 @@ +// 定义基础变量 +$bg-animation-color-light: #000; +$bg-animation-color-dark: #fff; +$bg-animation-duration: 0.5s; + +html { + --bg-animation-color: $bg-animation-color-light; + + &.dark { + --bg-animation-color: $bg-animation-color-dark; + } + + // View transition styles + &::view-transition-old(*) { + animation: none; + } + + &::view-transition-new(*) { + animation: clip $bg-animation-duration ease-in both; + } + + &::view-transition-old(root) { + z-index: 1; + } + + &::view-transition-new(root) { + z-index: 9999; + } + + &.dark { + &::view-transition-old(*) { + animation: clip $bg-animation-duration ease-in reverse both; + } + + &::view-transition-new(*) { + animation: none; + } + + &::view-transition-old(root) { + z-index: 9999; + } + + &::view-transition-new(root) { + z-index: 1; + } + } +} + +// 定义动画 +@keyframes clip { + from { + clip-path: circle(0% at var(--x) var(--y)); + } + + to { + clip-path: circle(var(--r) at var(--x) var(--y)); + } +} + +// body 相关样式 +body { + background-color: var(--bg-animation-color); +} diff --git a/src/assets/styles/core/theme-change.scss b/src/assets/styles/core/theme-change.scss new file mode 100644 index 0000000..5b640d2 --- /dev/null +++ b/src/assets/styles/core/theme-change.scss @@ -0,0 +1,11 @@ +// 主题切换过渡优化,优化除视觉上的不适感 +.theme-change { + * { + transition: 0s !important; + } + + .el-switch__core, + .el-switch__action { + transition: all 0.3s !important; + } +} diff --git a/src/assets/styles/custom/one-dark-pro.scss b/src/assets/styles/custom/one-dark-pro.scss new file mode 100644 index 0000000..36bdf63 --- /dev/null +++ b/src/assets/styles/custom/one-dark-pro.scss @@ -0,0 +1,98 @@ +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + + color: #a6accd; +} + +.hljs-string, +.hljs-section, +.hljs-selector-class, +.hljs-template-variable, +.hljs-deletion { + color: #aed07e !important; +} + +.hljs-comment, +.hljs-quote { + color: #6f747d; +} + +.hljs-doctag, +.hljs-keyword, +.hljs-formula { + color: #c792ea; +} + +.hljs-section, +.hljs-name, +.hljs-selector-tag, +.hljs-deletion, +.hljs-subst { + color: #c86068; +} + +.hljs-literal { + color: #56b6c2; +} + +.hljs-string, +.hljs-regexp, +.hljs-addition, +.hljs-attribute, +.hljs-meta-string { + color: #abb2bf; +} + +.hljs-attribute { + color: #c792ea; +} + +.hljs-function { + color: #c792ea; +} + +.hljs-type { + color: #f07178; +} + +.hljs-title { + color: #82aaff !important; +} + +.hljs-built_in, +.hljs-class { + color: #82aaff; +} + +// 括号 +.hljs-params { + color: #a6accd; +} + +.hljs-attr, +.hljs-variable, +.hljs-template-variable, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-number { + color: #de7e61; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-link, +.hljs-meta, +.hljs-selector-id { + color: #61aeee; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-link { + text-decoration: underline; +} diff --git a/src/assets/styles/index.scss b/src/assets/styles/index.scss new file mode 100644 index 0000000..cdc2ddc --- /dev/null +++ b/src/assets/styles/index.scss @@ -0,0 +1,23 @@ +// 重置默认样式 +@use './core/reset.scss'; + +// 应用全局样式 +@use './core/app.scss'; + +// Element Plus 样式优化 +@use './core/el-ui.scss'; + +// Element Plus 暗黑主题 +@use './core/el-dark.scss'; + +// 暗黑主题样式优化 +@use './core/dark.scss'; + +// 路由切换动画 +@use './core/router-transition'; + +// 主题切换过渡优化 +@use './core/theme-change.scss'; + +// 主题切换圆形扩散动画 +@use './core/theme-animation.scss'; diff --git a/src/assets/svg/loading.ts b/src/assets/svg/loading.ts new file mode 100644 index 0000000..fdfb078 --- /dev/null +++ b/src/assets/svg/loading.ts @@ -0,0 +1,32 @@ +// 自定义四点旋转SVG +export const fourDotsSpinnerSvg = ` + + + + + + + + + +` diff --git a/src/components/core/banners/art-basic-banner/index.vue b/src/components/core/banners/art-basic-banner/index.vue new file mode 100644 index 0000000..65b47e4 --- /dev/null +++ b/src/components/core/banners/art-basic-banner/index.vue @@ -0,0 +1,343 @@ + + + + + + diff --git a/src/components/core/banners/art-card-banner/index.vue b/src/components/core/banners/art-card-banner/index.vue new file mode 100644 index 0000000..8a5f9d4 --- /dev/null +++ b/src/components/core/banners/art-card-banner/index.vue @@ -0,0 +1,114 @@ + + + + diff --git a/src/components/core/base/art-back-to-top/index.vue b/src/components/core/base/art-back-to-top/index.vue new file mode 100644 index 0000000..6f8da61 --- /dev/null +++ b/src/components/core/base/art-back-to-top/index.vue @@ -0,0 +1,40 @@ + + + + diff --git a/src/components/core/base/art-logo/index.vue b/src/components/core/base/art-logo/index.vue new file mode 100644 index 0000000..8bc8309 --- /dev/null +++ b/src/components/core/base/art-logo/index.vue @@ -0,0 +1,21 @@ + + + + diff --git a/src/components/core/base/art-svg-icon/index.vue b/src/components/core/base/art-svg-icon/index.vue new file mode 100644 index 0000000..0bfcd0c --- /dev/null +++ b/src/components/core/base/art-svg-icon/index.vue @@ -0,0 +1,24 @@ + + + + diff --git a/src/components/core/cards/art-bar-chart-card/index.vue b/src/components/core/cards/art-bar-chart-card/index.vue new file mode 100644 index 0000000..6815c2b --- /dev/null +++ b/src/components/core/cards/art-bar-chart-card/index.vue @@ -0,0 +1,103 @@ + + + + diff --git a/src/components/core/cards/art-data-list-card/index.vue b/src/components/core/cards/art-data-list-card/index.vue new file mode 100644 index 0000000..fc43323 --- /dev/null +++ b/src/components/core/cards/art-data-list-card/index.vue @@ -0,0 +1,74 @@ + + + + diff --git a/src/components/core/cards/art-donut-chart-card/index.vue b/src/components/core/cards/art-donut-chart-card/index.vue new file mode 100644 index 0000000..df2dcbb --- /dev/null +++ b/src/components/core/cards/art-donut-chart-card/index.vue @@ -0,0 +1,124 @@ + + + + diff --git a/src/components/core/cards/art-image-card/index.vue b/src/components/core/cards/art-image-card/index.vue new file mode 100644 index 0000000..d27fe00 --- /dev/null +++ b/src/components/core/cards/art-image-card/index.vue @@ -0,0 +1,89 @@ + + + + diff --git a/src/components/core/cards/art-line-chart-card/index.vue b/src/components/core/cards/art-line-chart-card/index.vue new file mode 100644 index 0000000..e58c9b2 --- /dev/null +++ b/src/components/core/cards/art-line-chart-card/index.vue @@ -0,0 +1,126 @@ + + + + diff --git a/src/components/core/cards/art-progress-card/index.vue b/src/components/core/cards/art-progress-card/index.vue new file mode 100644 index 0000000..048a836 --- /dev/null +++ b/src/components/core/cards/art-progress-card/index.vue @@ -0,0 +1,86 @@ + + + + diff --git a/src/components/core/cards/art-stats-card/index.vue b/src/components/core/cards/art-stats-card/index.vue new file mode 100644 index 0000000..8e0341b --- /dev/null +++ b/src/components/core/cards/art-stats-card/index.vue @@ -0,0 +1,67 @@ + + + + diff --git a/src/components/core/cards/art-timeline-list-card/index.vue b/src/components/core/cards/art-timeline-list-card/index.vue new file mode 100644 index 0000000..fbb2c78 --- /dev/null +++ b/src/components/core/cards/art-timeline-list-card/index.vue @@ -0,0 +1,69 @@ + + + + diff --git a/src/components/core/charts/art-bar-chart/index.vue b/src/components/core/charts/art-bar-chart/index.vue new file mode 100644 index 0000000..d677196 --- /dev/null +++ b/src/components/core/charts/art-bar-chart/index.vue @@ -0,0 +1,203 @@ + + + + diff --git a/src/components/core/charts/art-dual-bar-compare-chart/index.vue b/src/components/core/charts/art-dual-bar-compare-chart/index.vue new file mode 100644 index 0000000..32aa60f --- /dev/null +++ b/src/components/core/charts/art-dual-bar-compare-chart/index.vue @@ -0,0 +1,195 @@ + + + + diff --git a/src/components/core/charts/art-h-bar-chart/index.vue b/src/components/core/charts/art-h-bar-chart/index.vue new file mode 100644 index 0000000..2e34759 --- /dev/null +++ b/src/components/core/charts/art-h-bar-chart/index.vue @@ -0,0 +1,208 @@ + + + + diff --git a/src/components/core/charts/art-k-line-chart/index.vue b/src/components/core/charts/art-k-line-chart/index.vue new file mode 100644 index 0000000..0061b51 --- /dev/null +++ b/src/components/core/charts/art-k-line-chart/index.vue @@ -0,0 +1,152 @@ + + + + diff --git a/src/components/core/charts/art-line-chart/index.vue b/src/components/core/charts/art-line-chart/index.vue new file mode 100644 index 0000000..b70c2c3 --- /dev/null +++ b/src/components/core/charts/art-line-chart/index.vue @@ -0,0 +1,371 @@ + + + + diff --git a/src/components/core/charts/art-radar-chart/index.vue b/src/components/core/charts/art-radar-chart/index.vue new file mode 100644 index 0000000..e99fff6 --- /dev/null +++ b/src/components/core/charts/art-radar-chart/index.vue @@ -0,0 +1,105 @@ + + + + diff --git a/src/components/core/charts/art-ring-chart/index.vue b/src/components/core/charts/art-ring-chart/index.vue new file mode 100644 index 0000000..79115f7 --- /dev/null +++ b/src/components/core/charts/art-ring-chart/index.vue @@ -0,0 +1,133 @@ + + + + diff --git a/src/components/core/charts/art-scatter-chart/index.vue b/src/components/core/charts/art-scatter-chart/index.vue new file mode 100644 index 0000000..995b56a --- /dev/null +++ b/src/components/core/charts/art-scatter-chart/index.vue @@ -0,0 +1,115 @@ + + + + diff --git a/src/components/core/forms/art-button-more/index.vue b/src/components/core/forms/art-button-more/index.vue new file mode 100644 index 0000000..858d305 --- /dev/null +++ b/src/components/core/forms/art-button-more/index.vue @@ -0,0 +1,71 @@ + + + + diff --git a/src/components/core/forms/art-button-table/index.vue b/src/components/core/forms/art-button-table/index.vue new file mode 100644 index 0000000..c849901 --- /dev/null +++ b/src/components/core/forms/art-button-table/index.vue @@ -0,0 +1,59 @@ + + + + diff --git a/src/components/core/forms/art-drag-verify/index.vue b/src/components/core/forms/art-drag-verify/index.vue new file mode 100644 index 0000000..5306e04 --- /dev/null +++ b/src/components/core/forms/art-drag-verify/index.vue @@ -0,0 +1,430 @@ + + + + + + + + diff --git a/src/components/core/forms/art-excel-export/index.vue b/src/components/core/forms/art-excel-export/index.vue new file mode 100644 index 0000000..08207c2 --- /dev/null +++ b/src/components/core/forms/art-excel-export/index.vue @@ -0,0 +1,389 @@ + + + + + + diff --git a/src/components/core/forms/art-excel-import/index.vue b/src/components/core/forms/art-excel-import/index.vue new file mode 100644 index 0000000..8aa82fe --- /dev/null +++ b/src/components/core/forms/art-excel-import/index.vue @@ -0,0 +1,62 @@ + + + + diff --git a/src/components/core/forms/art-form/index.vue b/src/components/core/forms/art-form/index.vue new file mode 100644 index 0000000..1e76f14 --- /dev/null +++ b/src/components/core/forms/art-form/index.vue @@ -0,0 +1,311 @@ + + + + + + diff --git a/src/components/core/forms/art-search-bar/index.vue b/src/components/core/forms/art-search-bar/index.vue new file mode 100644 index 0000000..b25b5bb --- /dev/null +++ b/src/components/core/forms/art-search-bar/index.vue @@ -0,0 +1,437 @@ + + + + + + + + diff --git a/src/components/core/forms/art-wang-editor/index.vue b/src/components/core/forms/art-wang-editor/index.vue new file mode 100644 index 0000000..cfc457e --- /dev/null +++ b/src/components/core/forms/art-wang-editor/index.vue @@ -0,0 +1,219 @@ + + + + + + diff --git a/src/components/core/forms/art-wang-editor/style.scss b/src/components/core/forms/art-wang-editor/style.scss new file mode 100644 index 0000000..fd5dbca --- /dev/null +++ b/src/components/core/forms/art-wang-editor/style.scss @@ -0,0 +1,210 @@ +$box-radius: calc(var(--custom-radius) / 3 + 2px); + +// 全屏容器 z-index 调整 +.w-e-full-screen-container { + z-index: 100 !important; +} + +/* 编辑器容器 */ +.editor-wrapper { + width: 100%; + height: 100%; + border: 1px solid var(--art-gray-300); + border-radius: $box-radius !important; + + .w-e-bar { + border-radius: $box-radius $box-radius 0 0 !important; + } + + .menu-item { + display: flex; + flex-direction: row; + align-items: center; + + i { + margin-right: 5px; + } + } + + /* 工具栏 */ + .editor-toolbar { + border-bottom: 1px solid var(--default-border); + } + + /* 下拉选择框配置 */ + .w-e-select-list { + min-width: 140px; + padding: 5px 10px 10px; + border: none; + border-radius: $box-radius; + } + + /* 下拉选择框元素配置 */ + .w-e-select-list ul li { + margin-top: 5px; + font-size: 15px !important; + border-radius: $box-radius; + } + + /* 下拉选择框 正文文字大小调整 */ + .w-e-select-list ul li:last-of-type { + font-size: 16px !important; + } + + /* 下拉选择框 hover 样式调整 */ + .w-e-select-list ul li:hover { + background-color: var(--art-gray-200); + } + + :root { + /* 激活颜色 */ + --w-e-toolbar-active-bg-color: var(--art-gray-200); + + /* toolbar 图标和文字颜色 */ + --w-e-toolbar-color: #000; + + /* 表格选中时候的边框颜色 */ + --w-e-textarea-selected-border-color: #ddd; + + /* 表格头背景颜色 */ + --w-e-textarea-slight-bg-color: var(--art-gray-200); + } + + /* 工具栏按钮样式 */ + .w-e-bar-item svg { + fill: var(--art-gray-800); + } + + .w-e-bar-item button { + color: var(--art-gray-800); + border-radius: $box-radius; + } + + /* 工具栏 hover 按钮背景颜色 */ + .w-e-bar-item button:hover { + background-color: var(--art-gray-200); + } + + /* 工具栏分割线 */ + .w-e-bar-divider { + height: 20px; + margin-top: 10px; + background-color: #ccc; + } + + /* 工具栏菜单 */ + .w-e-bar-item-group .w-e-bar-item-menus-container { + min-width: 120px; + padding: 10px 0; + border: none; + border-radius: $box-radius; + + .w-e-bar-item { + button { + width: 100%; + margin: 0 5px; + } + } + } + + /* 代码块 */ + .w-e-text-container [data-slate-editor] pre > code { + padding: 0.6rem 1rem; + background-color: var(--art-gray-50); + border-radius: $box-radius; + } + + /* 弹出框 */ + .w-e-drop-panel { + border: 0; + border-radius: $box-radius; + } + + a { + color: #318ef4; + } + + .w-e-text-container { + strong, + b { + font-weight: 500; + } + + i, + em { + font-style: italic; + } + } + + /* 表格样式优化 */ + .w-e-text-container [data-slate-editor] .table-container th { + border-right: none; + } + + .w-e-text-container [data-slate-editor] .table-container th:last-of-type { + border-right: 1px solid #ccc !important; + } + + /* 引用 */ + .w-e-text-container [data-slate-editor] blockquote { + background-color: var(--art-gray-200); + border-left: 4px solid var(--art-gray-300); + } + + /* 输入区域弹出 bar */ + .w-e-hover-bar { + border-radius: $box-radius; + } + + /* 超链接弹窗 */ + .w-e-modal { + border: none; + border-radius: $box-radius; + } + + /* 图片样式调整 */ + .w-e-text-container [data-slate-editor] .w-e-selected-image-container { + overflow: inherit; + + &:hover { + border: 0; + } + + img { + border: 1px solid transparent; + transition: border 0.3s; + + &:hover { + border: 1px solid #318ef4 !important; + } + } + + .w-e-image-dragger { + width: 12px; + height: 12px; + background-color: #318ef4; + border: 2px solid #fff; + border-radius: $box-radius; + } + + .left-top { + top: -6px; + left: -6px; + } + + .right-top { + top: -6px; + right: -6px; + } + + .left-bottom { + bottom: -6px; + left: -6px; + } + + .right-bottom { + right: -6px; + bottom: -6px; + } + } +} diff --git a/src/components/core/layouts/art-breadcrumb/index.vue b/src/components/core/layouts/art-breadcrumb/index.vue new file mode 100644 index 0000000..4b54859 --- /dev/null +++ b/src/components/core/layouts/art-breadcrumb/index.vue @@ -0,0 +1,142 @@ + + + + diff --git a/src/components/core/layouts/art-chat-window/index.vue b/src/components/core/layouts/art-chat-window/index.vue new file mode 100644 index 0000000..f3d9471 --- /dev/null +++ b/src/components/core/layouts/art-chat-window/index.vue @@ -0,0 +1,262 @@ + + + + diff --git a/src/components/core/layouts/art-fast-enter/index.vue b/src/components/core/layouts/art-fast-enter/index.vue new file mode 100644 index 0000000..fdde222 --- /dev/null +++ b/src/components/core/layouts/art-fast-enter/index.vue @@ -0,0 +1,113 @@ + + + + diff --git a/src/components/core/layouts/art-fireworks-effect/index.vue b/src/components/core/layouts/art-fireworks-effect/index.vue new file mode 100644 index 0000000..be85274 --- /dev/null +++ b/src/components/core/layouts/art-fireworks-effect/index.vue @@ -0,0 +1,633 @@ + + + + diff --git a/src/components/core/layouts/art-global-component/index.vue b/src/components/core/layouts/art-global-component/index.vue new file mode 100644 index 0000000..6908f94 --- /dev/null +++ b/src/components/core/layouts/art-global-component/index.vue @@ -0,0 +1,14 @@ + + + + diff --git a/src/components/core/layouts/art-global-search/index.vue b/src/components/core/layouts/art-global-search/index.vue new file mode 100644 index 0000000..a7d88df --- /dev/null +++ b/src/components/core/layouts/art-global-search/index.vue @@ -0,0 +1,426 @@ + + + + + + + diff --git a/src/components/core/layouts/art-header-bar/index.vue b/src/components/core/layouts/art-header-bar/index.vue new file mode 100644 index 0000000..4e3c8f9 --- /dev/null +++ b/src/components/core/layouts/art-header-bar/index.vue @@ -0,0 +1,485 @@ + + + + + + diff --git a/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue b/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue new file mode 100644 index 0000000..c8c5832 --- /dev/null +++ b/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue @@ -0,0 +1,167 @@ + + + + + + diff --git a/src/components/core/layouts/art-menus/art-horizontal-menu/index.vue b/src/components/core/layouts/art-menus/art-horizontal-menu/index.vue new file mode 100644 index 0000000..edd1473 --- /dev/null +++ b/src/components/core/layouts/art-menus/art-horizontal-menu/index.vue @@ -0,0 +1,110 @@ + + + + + + diff --git a/src/components/core/layouts/art-menus/art-horizontal-menu/widget/HorizontalSubmenu.vue b/src/components/core/layouts/art-menus/art-horizontal-menu/widget/HorizontalSubmenu.vue new file mode 100644 index 0000000..ff32c1e --- /dev/null +++ b/src/components/core/layouts/art-menus/art-horizontal-menu/widget/HorizontalSubmenu.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/src/components/core/layouts/art-menus/art-mixed-menu/index.vue b/src/components/core/layouts/art-menus/art-mixed-menu/index.vue new file mode 100644 index 0000000..4e98246 --- /dev/null +++ b/src/components/core/layouts/art-menus/art-mixed-menu/index.vue @@ -0,0 +1,279 @@ + + + + + + + + diff --git a/src/components/core/layouts/art-menus/art-sidebar-menu/index.vue b/src/components/core/layouts/art-menus/art-sidebar-menu/index.vue new file mode 100644 index 0000000..39387dc --- /dev/null +++ b/src/components/core/layouts/art-menus/art-sidebar-menu/index.vue @@ -0,0 +1,355 @@ + + + + + + + + diff --git a/src/components/core/layouts/art-menus/art-sidebar-menu/style.scss b/src/components/core/layouts/art-menus/art-sidebar-menu/style.scss new file mode 100644 index 0000000..b98011c --- /dev/null +++ b/src/components/core/layouts/art-menus/art-sidebar-menu/style.scss @@ -0,0 +1,253 @@ +.layout-sidebar { + display: flex; + height: 100vh; + user-select: none; + scrollbar-width: none; + border-right: 1px solid var(--art-card-border); + + &.no-border { + border-right: none !important; + } + + // 自定义滚动条宽度 + :deep(.el-scrollbar__bar.is-vertical) { + width: 4px; + } + + :deep(.el-scrollbar__thumb) { + right: -2px; + background-color: #ccc; + border-radius: 2px; + } + + .dual-menu-left { + position: relative; + width: 80px; + height: 100%; + border-right: 1px solid var(--art-card-border) !important; + transition: width 0.25s; + + .logo { + margin: auto; + margin-top: 12px; + margin-bottom: 3px; + cursor: pointer; + } + + ul { + li { + > div { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin: 8px; + overflow: hidden; + text-align: center; + cursor: pointer; + border-radius: 5px; + + .art-svg-icon { + display: block; + margin: 0 auto; + font-size: 20px; + } + + span { + display: -webkit-box; + width: 100%; + overflow: hidden; + font-size: 12px; + text-overflow: ellipsis; + -webkit-line-clamp: 1; + line-clamp: 1; + -webkit-box-orient: vertical; + } + + &.is-active { + background: var(--el-color-primary-light-9); + + .art-svg-icon, + span { + color: var(--theme-color) !important; + } + } + } + } + } + + .switch-btn { + position: absolute; + right: 0; + bottom: 15px; + left: 0; + margin: auto; + } + } + + .menu-left { + position: relative; + box-sizing: border-box; + height: 100vh; + + @media only screen and (width <= 640px) { + height: 100dvh; + } + + .el-menu { + height: 100%; + } + + &:hover { + .dual-menu-collapse-btn { + opacity: 1 !important; + } + } + + .dual-menu-collapse-btn { + position: absolute; + top: 50%; + right: -11px; + z-index: 10; + width: 11px; + height: 50px; + cursor: pointer; + background-color: var(--default-box-color); + border: 1px solid var(--art-card-border); + border-radius: 0 15px 15px 0; + opacity: 0; + transition: opacity 0.2s; + transform: translateY(-50%); + + &:hover { + .art-svg-icon { + color: var(--art-gray-800) !important; + } + } + + .art-svg-icon { + position: absolute; + top: 0; + bottom: 0; + left: -4px; + margin: auto; + transition: all 0.3s; + } + } + } + + .header { + position: relative; + box-sizing: border-box; + display: flex; + align-items: center; + width: 100%; + height: 60px; + overflow: hidden; + line-height: 60px; + cursor: pointer; + + .logo { + margin-left: 22px; + } + + p { + position: absolute; + top: 0; + bottom: 0; + left: 58px; + box-sizing: border-box; + margin-left: 10px; + font-size: 18px; + + &.is-dual-menu-name { + left: 25px; + margin: auto; + } + } + } + + .el-menu { + box-sizing: border-box; + height: calc(100vh - 60px); + overflow-y: auto; + // 防止菜单内的滚动影响整个页面滚动 + overscroll-behavior: contain; + border-right: 0; + scrollbar-width: none; + -ms-scroll-chaining: contain; + + &::-webkit-scrollbar { + width: 0 !important; + } + } + + .menu-model { + display: none; + } +} + +@media only screen and (width <= 800px) { + .layout-sidebar { + width: 0; + + .header { + height: 50px; + line-height: 50px; + } + + .el-menu { + height: calc(100vh - 60px); + } + + .el-menu--collapse { + width: 0; + } + + // 折叠状态下的header样式 + .menu-left-close .header { + .logo { + display: none; + } + + p { + left: 16px; + font-size: 0; + opacity: 0 !important; + } + } + + .menu-model { + position: fixed; + top: 0; + left: 0; + z-index: -1; + display: block; + width: 100%; + height: 100vh; + background: rgba($color: #000, $alpha: 50%); + transition: opacity 0.2s ease-in-out; + } + } +} + +@media only screen and (width <= 640px) { + .layout-sidebar { + border-right: 0 !important; + } +} + +.dark { + .layout-sidebar { + border-right: 1px solid rgb(255 255 255 / 13%); + + :deep(.el-scrollbar__thumb) { + background-color: #777; + } + + .dual-menu-left { + border-right: 1px solid rgb(255 255 255 / 9%) !important; + } + } +} diff --git a/src/components/core/layouts/art-menus/art-sidebar-menu/theme.scss b/src/components/core/layouts/art-menus/art-sidebar-menu/theme.scss new file mode 100644 index 0000000..7626c42 --- /dev/null +++ b/src/components/core/layouts/art-menus/art-sidebar-menu/theme.scss @@ -0,0 +1,258 @@ +@use '@styles/core/mixin.scss' as *; + +// 菜单样式变量 +$menu-height: 42px; +$menu-icon-size: 20px; +$menu-font-size: 14px; +$hover-bg-color: var(--art-gray-200); +$popup-menu-height: 40px; +$popup-menu-padding: 8px; +$popup-menu-margin: 5px; +$popup-menu-radius: 6px; + +// 通用菜单项样式 +@mixin menu-item-base { + width: calc(100% - 16px); + margin-left: 8px; + border-radius: 6px; + + .menu-icon { + margin-left: -7px; + } +} + +// 通用 hover 样式 +@mixin menu-hover($bg-color) { + .el-sub-menu__title:hover, + .el-menu-item:not(.is-active):hover { + background: $bg-color !important; + } +} + +// 通用选中样式 +@mixin menu-active($color, $bg-color, $icon-color: var(--theme-color)) { + .el-menu-item.is-active { + color: $color !important; + background-color: $bg-color; + + .menu-icon { + .art-svg-icon { + color: $icon-color !important; + } + } + } +} + +// 弹窗菜单项样式 +@mixin popup-menu-item { + height: $popup-menu-height; + margin-bottom: $popup-menu-margin; + border-radius: $popup-menu-radius; + + .menu-icon { + margin-right: 5px; + } + + &:last-of-type { + margin-bottom: 0; + } +} + +// 主题菜单通用样式(合并 design 和 dark 主题的共同逻辑) +@mixin theme-menu-base { + .el-sub-menu__title, + .el-menu-item { + @include menu-item-base; + } +} + +// 弹窗菜单通用样式 +@mixin popup-menu-base($hover-bg, $active-color, $active-bg) { + .el-menu--popup { + padding: $popup-menu-padding; + + .el-sub-menu__title:hover, + .el-menu-item:hover { + background-color: $hover-bg !important; + border-radius: $popup-menu-radius; + } + + .el-menu-item { + @include popup-menu-item; + + &.is-active { + color: $active-color !important; + background-color: $active-bg !important; + } + } + + .el-sub-menu { + @include popup-menu-item; + + height: $popup-menu-height !important; + + .el-sub-menu__title { + height: $popup-menu-height !important; + border-radius: $popup-menu-radius; + } + } + } +} + +.layout-sidebar { + // ---------------------- Modify default style ---------------------- + + // 菜单折叠样式 + .menu-left-close { + .header { + .logo { + margin: 0 auto; + } + } + } + + // 菜单图标 + .menu-icon { + margin-right: 8px; + font-size: $menu-icon-size; + } + + // 菜单高度 + .el-sub-menu__title, + .el-menu-item { + height: $menu-height !important; + margin-bottom: 4px; + line-height: $menu-height !important; + + span { + font-size: $menu-font-size !important; + + @include ellipsis(); + } + } + + // 右侧箭头 + .el-sub-menu__icon-arrow { + width: 13px !important; + font-size: 13px !important; + } + + // 菜单折叠 + .el-menu--collapse { + .el-sub-menu.is-active { + .el-sub-menu__title { + .menu-icon { + .art-svg-icon { + // 选中菜单图标颜色 + color: var(--theme-color) !important; + } + } + } + } + } + + // ---------------------- Design theme menu ---------------------- + .el-menu-design { + @include theme-menu-base; + @include menu-active(var(--theme-color), var(--el-color-primary-light-9)); + @include menu-hover($hover-bg-color); + + .el-sub-menu__icon-arrow { + color: var(--art-gray-600); + } + } + + // ---------------------- Dark theme menu ---------------------- + .el-menu-dark { + @include theme-menu-base; + @include menu-active(#fff, #27282d, #fff); + @include menu-hover(#0f1015); + + .el-sub-menu__icon-arrow { + color: var(--art-gray-400); + } + } + + // ---------------------- Light theme menu ---------------------- + .el-menu-light { + .el-sub-menu__title, + .el-menu-item { + .menu-icon { + margin-left: 1px; + } + } + + .el-menu-item.is-active { + background-color: var(--el-color-primary-light-9); + + .art-svg-icon { + color: var(--theme-color) !important; + } + + &::before { + position: absolute; + top: 0; + left: 0; + width: 4px; + height: 100%; + content: ''; + background: var(--theme-color); + } + } + + @include menu-hover($hover-bg-color); + + .el-sub-menu__icon-arrow { + color: var(--art-gray-600); + } + } +} + +@media only screen and (width <= 640px) { + .layout-sidebar { + .el-menu-design { + > .el-sub-menu { + margin-left: 0; + } + + .el-sub-menu { + width: 100% !important; + } + } + } +} + +// 菜单折叠 hover 弹窗样式(浅色主题) +.el-menu--vertical, +.el-menu--popup-container { + @include popup-menu-base(var(--art-gray-200), var(--art-gray-900), var(--art-gray-200)); +} + +// 暗黑模式菜单样式 +.dark { + .el-menu--vertical, + .el-menu--popup-container { + @include popup-menu-base(var(--art-gray-200), var(--art-gray-900), #292a2e); + } + + .layout-sidebar { + // 图标颜色、文字颜色 + .menu-icon .art-svg-icon, + .menu-name { + color: var(--art-gray-800) !important; + } + + // 选中的文字颜色跟图标颜色 + .el-menu-item.is-active { + span, + .menu-icon .art-svg-icon { + color: var(--theme-color) !important; + } + } + + // 右侧箭头颜色 + .el-sub-menu__icon-arrow { + color: #fff; + } + } +} diff --git a/src/components/core/layouts/art-menus/art-sidebar-menu/widget/SidebarSubmenu.vue b/src/components/core/layouts/art-menus/art-sidebar-menu/widget/SidebarSubmenu.vue new file mode 100644 index 0000000..a7ac6a9 --- /dev/null +++ b/src/components/core/layouts/art-menus/art-sidebar-menu/widget/SidebarSubmenu.vue @@ -0,0 +1,188 @@ + + + diff --git a/src/components/core/layouts/art-notification/index.vue b/src/components/core/layouts/art-notification/index.vue new file mode 100644 index 0000000..a58853c --- /dev/null +++ b/src/components/core/layouts/art-notification/index.vue @@ -0,0 +1,456 @@ + + + + + + diff --git a/src/components/core/layouts/art-page-content/index.vue b/src/components/core/layouts/art-page-content/index.vue new file mode 100644 index 0000000..a862df1 --- /dev/null +++ b/src/components/core/layouts/art-page-content/index.vue @@ -0,0 +1,136 @@ + + + diff --git a/src/components/core/layouts/art-screen-lock/index.vue b/src/components/core/layouts/art-screen-lock/index.vue new file mode 100644 index 0000000..5bf5248 --- /dev/null +++ b/src/components/core/layouts/art-screen-lock/index.vue @@ -0,0 +1,519 @@ + + + + + + diff --git a/src/components/core/layouts/art-settings-panel/composables/useSettingsConfig.ts b/src/components/core/layouts/art-settings-panel/composables/useSettingsConfig.ts new file mode 100644 index 0000000..35e8066 --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/composables/useSettingsConfig.ts @@ -0,0 +1,248 @@ +import { computed } from 'vue' +import { useI18n } from 'vue-i18n' +import { ContainerWidthEnum } from '@/enums/appEnum' +import AppConfig from '@/config' +import { headerBarConfig } from '@/config/modules/headerBar' + +/** + * 设置项配置选项管理 + */ +export function useSettingsConfig() { + const { t } = useI18n() + + // 标签页风格选项 + const tabStyleOptions = computed(() => [ + { + value: 'tab-default', + label: t('setting.tabStyle.default') + }, + { + value: 'tab-card', + label: t('setting.tabStyle.card') + }, + { + value: 'tab-google', + label: t('setting.tabStyle.google') + } + ]) + + // 页面切换动画选项 + const pageTransitionOptions = computed(() => [ + { + value: '', + label: t('setting.transition.list.none') + }, + { + value: 'fade', + label: t('setting.transition.list.fade') + }, + { + value: 'slide-left', + label: t('setting.transition.list.slideLeft') + }, + { + value: 'slide-bottom', + label: t('setting.transition.list.slideBottom') + }, + { + value: 'slide-top', + label: t('setting.transition.list.slideTop') + } + ]) + + // 圆角大小选项 + const customRadiusOptions = [ + { value: '0', label: '0' }, + { value: '0.25', label: '0.25' }, + { value: '0.5', label: '0.5' }, + { value: '0.75', label: '0.75' }, + { value: '1', label: '1' } + ] + + // 容器宽度选项 + const containerWidthOptions = computed(() => [ + { + value: ContainerWidthEnum.FULL, + label: t('setting.container.list[0]'), + icon: 'icon-park-outline:auto-width' + }, + { + value: ContainerWidthEnum.BOXED, + label: t('setting.container.list[1]'), + icon: 'ix:width' + } + ]) + + // 盒子样式选项 + const boxStyleOptions = computed(() => [ + { + value: 'border-mode', + label: t('setting.box.list[0]'), + type: 'border-mode' as const + }, + { + value: 'shadow-mode', + label: t('setting.box.list[1]'), + type: 'shadow-mode' as const + } + ]) + + // 从配置文件获取的选项 + const configOptions = { + // 主题色彩选项 + mainColors: AppConfig.systemMainColor, + + // 主题风格选项 + themeList: AppConfig.settingThemeList, + + // 菜单布局选项 + menuLayoutList: AppConfig.menuLayoutList + } + + // 基础设置项配置 + const basicSettingsConfig = computed(() => { + // 定义所有基础设置项 + const allSettings = [ + { + key: 'showWorkTab', + label: t('setting.basics.list.multiTab'), + type: 'switch' as const, + handler: 'workTab', + headerBarKey: null // 不依赖headerBar配置 + }, + { + key: 'uniqueOpened', + label: t('setting.basics.list.accordion'), + type: 'switch' as const, + handler: 'uniqueOpened', + headerBarKey: null // 不依赖headerBar配置 + }, + { + key: 'showMenuButton', + label: t('setting.basics.list.collapseSidebar'), + type: 'switch' as const, + handler: 'menuButton', + headerBarKey: 'menuButton' as const + }, + { + key: 'showFastEnter', + label: t('setting.basics.list.fastEnter'), + type: 'switch' as const, + handler: 'fastEnter', + headerBarKey: 'fastEnter' as const + }, + { + key: 'showRefreshButton', + label: t('setting.basics.list.reloadPage'), + type: 'switch' as const, + handler: 'refreshButton', + headerBarKey: 'refreshButton' as const + }, + { + key: 'showCrumbs', + label: t('setting.basics.list.breadcrumb'), + type: 'switch' as const, + handler: 'crumbs', + mobileHide: true, + headerBarKey: 'breadcrumb' as const + }, + { + key: 'showLanguage', + label: t('setting.basics.list.language'), + type: 'switch' as const, + handler: 'language', + headerBarKey: 'language' as const + }, + { + key: 'showNprogress', + label: t('setting.basics.list.progressBar'), + type: 'switch' as const, + handler: 'nprogress', + headerBarKey: null // 不依赖headerBar配置 + }, + { + key: 'colorWeak', + label: t('setting.basics.list.weakMode'), + type: 'switch' as const, + handler: 'colorWeak', + headerBarKey: null // 不依赖headerBar配置 + }, + { + key: 'watermarkVisible', + label: t('setting.basics.list.watermark'), + type: 'switch' as const, + handler: 'watermark', + headerBarKey: null // 不依赖headerBar配置 + }, + { + key: 'menuOpenWidth', + label: t('setting.basics.list.menuWidth'), + type: 'input-number' as const, + handler: 'menuOpenWidth', + min: 180, + max: 320, + step: 10, + style: { width: '120px' }, + controlsPosition: 'right' as const, + headerBarKey: null // 不依赖headerBar配置 + }, + { + key: 'tabStyle', + label: t('setting.basics.list.tabStyle'), + type: 'select' as const, + handler: 'tabStyle', + options: tabStyleOptions.value, + style: { width: '120px' }, + headerBarKey: null // 不依赖headerBar配置 + }, + { + key: 'pageTransition', + label: t('setting.basics.list.pageTransition'), + type: 'select' as const, + handler: 'pageTransition', + options: pageTransitionOptions.value, + style: { width: '120px' }, + headerBarKey: null // 不依赖headerBar配置 + }, + { + key: 'customRadius', + label: t('setting.basics.list.borderRadius'), + type: 'select' as const, + handler: 'customRadius', + options: customRadiusOptions, + style: { width: '120px' }, + headerBarKey: null // 不依赖headerBar配置 + } + ] + + // 根据 headerBarConfig 过滤设置项 + return ( + allSettings + .filter((setting) => { + // 如果设置项不依赖headerBar配置,则始终显示 + if (setting.headerBarKey === null) { + return true + } + + // 如果依赖headerBar配置,检查对应的功能是否启用 + const headerBarFeature = headerBarConfig[setting.headerBarKey] + return headerBarFeature?.enabled !== false + }) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + .map(({ headerBarKey: _headerBarKey, ...setting }) => setting) + ) + }) + + return { + // 选项配置 + tabStyleOptions, + pageTransitionOptions, + customRadiusOptions, + containerWidthOptions, + boxStyleOptions, + configOptions, + + // 设置项配置 + basicSettingsConfig + } +} diff --git a/src/components/core/layouts/art-settings-panel/composables/useSettingsHandlers.ts b/src/components/core/layouts/art-settings-panel/composables/useSettingsHandlers.ts new file mode 100644 index 0000000..392c690 --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/composables/useSettingsHandlers.ts @@ -0,0 +1,167 @@ +import { useSettingStore } from '@/store/modules/setting' +import { storeToRefs } from 'pinia' +import type { ContainerWidthEnum } from '@/enums/appEnum' + +/** + * 设置项通用处理逻辑 + */ +export function useSettingsHandlers() { + const settingStore = useSettingStore() + + // DOM 操作相关 + const domOperations = { + // 设置HTML类名 + setHtmlClass: (className: string, add: boolean) => { + const el = document.getElementsByTagName('html')[0] + if (add) { + el.classList.add(className) + } else { + el.classList.remove(className) + } + }, + + // 设置根元素属性 + setRootAttribute: (attribute: string, value: string) => { + const el = document.documentElement + el.setAttribute(attribute, value) + }, + + // 设置body类名 + setBodyClass: (className: string, add: boolean) => { + const el = document.getElementsByTagName('body')[0] + if (add) { + el.classList.add(className) + } else { + el.classList.remove(className) + } + } + } + + // 通用切换处理器 + const createToggleHandler = (storeMethod: () => void, callback?: () => void) => { + return () => { + storeMethod() + callback?.() + } + } + + // 通用值变更处理器 + const createValueHandler = ( + storeMethod: (value: T) => void, + callback?: (value: T) => void + ) => { + return (value: T) => { + if (value !== undefined && value !== null) { + storeMethod(value) + callback?.(value) + } + } + } + + // 基础设置处理器 + const basicHandlers = { + // 工作台标签页 + workTab: createToggleHandler(() => settingStore.setWorkTab(!settingStore.showWorkTab)), + + // 菜单手风琴 + uniqueOpened: createToggleHandler(() => settingStore.setUniqueOpened()), + + // 显示菜单按钮 + menuButton: createToggleHandler(() => settingStore.setButton()), + + // 显示快速入口 + fastEnter: createToggleHandler(() => settingStore.setFastEnter()), + + // 显示刷新按钮 + refreshButton: createToggleHandler(() => settingStore.setShowRefreshButton()), + + // 显示面包屑 + crumbs: createToggleHandler(() => settingStore.setCrumbs()), + + // 显示语言切换 + language: createToggleHandler(() => settingStore.setLanguage()), + + // 显示进度条 + nprogress: createToggleHandler(() => settingStore.setNprogress()), + + // 色弱模式 + colorWeak: createToggleHandler( + () => settingStore.setColorWeak(), + () => { + domOperations.setHtmlClass('color-weak', settingStore.colorWeak) + } + ), + + // 水印显示 + watermark: createToggleHandler(() => + settingStore.setWatermarkVisible(!settingStore.watermarkVisible) + ), + + // 菜单展开宽度 + menuOpenWidth: createValueHandler((width: number) => + settingStore.setMenuOpenWidth(width) + ), + + // 标签页风格 + tabStyle: createValueHandler((style: string) => settingStore.setTabStyle(style)), + + // 页面切换动画 + pageTransition: createValueHandler((transition: string) => + settingStore.setPageTransition(transition) + ), + + // 圆角大小 + customRadius: createValueHandler((radius: string) => + settingStore.setCustomRadius(radius) + ) + } + + // 盒子样式处理器 + const boxStyleHandlers = { + // 设置盒子模式 + setBoxMode: (type: 'border-mode' | 'shadow-mode') => { + const { boxBorderMode } = storeToRefs(settingStore) + + // 防止重复设置 + if ( + (type === 'shadow-mode' && boxBorderMode.value === false) || + (type === 'border-mode' && boxBorderMode.value === true) + ) { + return + } + + setTimeout(() => { + domOperations.setRootAttribute('data-box-mode', type) + settingStore.setBorderMode() + }, 50) + } + } + + // 颜色设置处理器 + const colorHandlers = { + // 选择主题色 + selectColor: (theme: string) => { + settingStore.setElementTheme(theme) + settingStore.reload() + } + } + + // 容器设置处理器 + const containerHandlers = { + // 设置容器宽度 + setWidth: (type: ContainerWidthEnum) => { + settingStore.setContainerWidth(type) + settingStore.reload() + } + } + + return { + domOperations, + basicHandlers, + boxStyleHandlers, + colorHandlers, + containerHandlers, + createToggleHandler, + createValueHandler + } +} diff --git a/src/components/core/layouts/art-settings-panel/composables/useSettingsPanel.ts b/src/components/core/layouts/art-settings-panel/composables/useSettingsPanel.ts new file mode 100644 index 0000000..358ef57 --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/composables/useSettingsPanel.ts @@ -0,0 +1,207 @@ +import { ref, computed, watch } from 'vue' +import { useSettingStore } from '@/store/modules/setting' +import { storeToRefs } from 'pinia' +import { useBreakpoints } from '@vueuse/core' +import AppConfig from '@/config' +import { SystemThemeEnum, MenuTypeEnum } from '@/enums/appEnum' +import { mittBus } from '@/utils/sys' +import { useTheme } from '@/hooks/core/useTheme' +import { useCeremony } from '@/hooks/core/useCeremony' +import { useSettingsState } from './useSettingsState' +import { useSettingsHandlers } from './useSettingsHandlers' + +/** + * 设置面板核心逻辑管理 + */ +export function useSettingsPanel() { + const settingStore = useSettingStore() + const { systemThemeType, systemThemeMode, menuType } = storeToRefs(settingStore) + + // Composables + const { openFestival, cleanup } = useCeremony() + const { setSystemTheme, setSystemAutoTheme } = useTheme() + const { initColorWeak } = useSettingsState() + const { domOperations } = useSettingsHandlers() + + // 响应式状态 + const showDrawer = ref(false) + + // 使用 VueUse breakpoints 优化性能 + const breakpoints = useBreakpoints({ tablet: 1000 }) + const isMobile = breakpoints.smaller('tablet') + + // 记录窗口宽度变化前的菜单类型 + const beforeMenuType = ref() + const hasChangedMenu = ref(false) + + // 计算属性 + const systemThemeColor = computed(() => settingStore.systemThemeColor as string) + + // 主题相关处理 + const useThemeHandlers = () => { + // 初始化系统颜色 + const initSystemColor = () => { + if (!AppConfig.systemMainColor.includes(systemThemeColor.value)) { + settingStore.setElementTheme(AppConfig.systemMainColor[0]) + settingStore.reload() + } + } + + // 初始化系统主题 + const initSystemTheme = () => { + if (systemThemeMode.value === SystemThemeEnum.AUTO) { + setSystemAutoTheme() + } else { + setSystemTheme(systemThemeType.value) + } + } + + // 监听系统主题变化 + const listenerSystemTheme = () => { + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)') + mediaQuery.addEventListener('change', initSystemTheme) + return () => { + mediaQuery.removeEventListener('change', initSystemTheme) + } + } + + return { + initSystemColor, + initSystemTheme, + listenerSystemTheme + } + } + + // 响应式布局处理 + const useResponsiveLayout = () => { + // 使用 watch 监听断点变化,性能更优 + const stopWatch = watch( + isMobile, + (mobile: boolean) => { + if (mobile) { + // 切换到移动端布局 + if (!hasChangedMenu.value) { + beforeMenuType.value = menuType.value + useSettingsState().switchMenuLayouts(MenuTypeEnum.LEFT) + settingStore.setMenuOpen(false) + hasChangedMenu.value = true + } + } else { + // 恢复桌面端布局 + if (hasChangedMenu.value && beforeMenuType.value) { + useSettingsState().switchMenuLayouts(beforeMenuType.value) + settingStore.setMenuOpen(true) + hasChangedMenu.value = false + } + } + }, + { immediate: true } + ) + + return { stopWatch } + } + + // 抽屉控制 + const useDrawerControl = () => { + // 用于存储 setTimeout 的 ID,以便在需要时清除 + let themeChangeTimer: ReturnType | null = null + + // 打开抽屉 + const handleOpen = () => { + // 清除可能存在的旧定时器 + if (themeChangeTimer) { + clearTimeout(themeChangeTimer) + } + // 延迟添加 theme-change class,避免抽屉打开动画受影响 + themeChangeTimer = setTimeout(() => { + domOperations.setBodyClass('theme-change', true) + themeChangeTimer = null + }, 500) + } + + // 关闭抽屉 + const handleClose = () => { + // 清除未执行的定时器,防止关闭后才添加 class + if (themeChangeTimer) { + clearTimeout(themeChangeTimer) + themeChangeTimer = null + } + // 立即移除 theme-change class + domOperations.setBodyClass('theme-change', false) + } + + // 打开设置 + const openSetting = () => { + showDrawer.value = true + } + + // 关闭设置 + const closeDrawer = () => { + showDrawer.value = false + } + + return { + handleOpen, + handleClose, + openSetting, + closeDrawer + } + } + + // Props 变化监听 + const usePropsWatcher = (props: { open?: boolean }) => { + watch( + () => props.open, + (val: boolean | undefined) => { + if (val !== undefined) { + showDrawer.value = val + } + } + ) + } + + // 初始化设置 + const useSettingsInitializer = () => { + const themeHandlers = useThemeHandlers() + const { openSetting } = useDrawerControl() + const { stopWatch } = useResponsiveLayout() + let themeCleanup: (() => void) | null = null + + const initializeSettings = () => { + mittBus.on('openSetting', openSetting) + themeHandlers.initSystemColor() + themeCleanup = themeHandlers.listenerSystemTheme() + initColorWeak() + + // 设置盒子模式 + const boxMode = settingStore.boxBorderMode ? 'border-mode' : 'shadow-mode' + domOperations.setRootAttribute('data-box-mode', boxMode) + + themeHandlers.initSystemTheme() + openFestival() + } + + const cleanupSettings = () => { + stopWatch() + themeCleanup?.() + cleanup() + } + + return { + initializeSettings, + cleanupSettings + } + } + + return { + // 状态 + showDrawer, + + // 方法组合 + useThemeHandlers, + useResponsiveLayout, + useDrawerControl, + usePropsWatcher, + useSettingsInitializer + } +} diff --git a/src/components/core/layouts/art-settings-panel/composables/useSettingsState.ts b/src/components/core/layouts/art-settings-panel/composables/useSettingsState.ts new file mode 100644 index 0000000..65352d2 --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/composables/useSettingsState.ts @@ -0,0 +1,37 @@ +import { useSettingStore } from '@/store/modules/setting' +import { MenuThemeEnum, MenuTypeEnum } from '@/enums/appEnum' + +/** + * 设置状态管理 + */ +export function useSettingsState() { + const settingStore = useSettingStore() + + // 色弱模式初始化 + const initColorWeak = () => { + if (settingStore.colorWeak) { + const el = document.getElementsByTagName('html')[0] + setTimeout(() => { + el.classList.add('color-weak') + }, 100) + } + } + + // 菜单布局切换 + const switchMenuLayouts = (type: MenuTypeEnum) => { + if (type === MenuTypeEnum.LEFT || type === MenuTypeEnum.TOP_LEFT) { + settingStore.setMenuOpen(true) + } + settingStore.switchMenuLayouts(type) + if (type === MenuTypeEnum.DUAL_MENU) { + settingStore.switchMenuStyles(MenuThemeEnum.DESIGN) + settingStore.setMenuOpen(true) + } + } + + return { + // 方法 + initColorWeak, + switchMenuLayouts + } +} diff --git a/src/components/core/layouts/art-settings-panel/index.vue b/src/components/core/layouts/art-settings-panel/index.vue new file mode 100644 index 0000000..0cbf344 --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/index.vue @@ -0,0 +1,72 @@ + + + + + + diff --git a/src/components/core/layouts/art-settings-panel/style.scss b/src/components/core/layouts/art-settings-panel/style.scss new file mode 100644 index 0000000..e863074 --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/style.scss @@ -0,0 +1,92 @@ +@use '@styles/core/mixin.scss' as *; + +// 设置抽屉模态框样式 +.setting-modal { + background: transparent !important; + + .el-drawer { + // 背景滤镜效果 + background: rgba($color: #fff, $alpha: 50%) !important; + box-shadow: 0 0 30px rgb(0 0 0 / 10%) !important; + + @include backdropBlur(); + + .setting-box-wrap { + display: flex; + flex-wrap: wrap; + align-items: center; + width: calc(100% + 15px); + margin-bottom: 10px; + + .setting-item { + box-sizing: border-box; + width: calc(33.333% - 15px); + margin-right: 15px; + text-align: center; + + .box { + position: relative; + box-sizing: border-box; + display: flex; + height: 52px; + overflow: hidden; + cursor: pointer; + border: 2px solid var(--default-border); + border-radius: 8px; + box-shadow: 0 0 8px 0 rgb(0 0 0 / 10%); + transition: box-shadow 0.1s; + + &.mt-16 { + margin-top: 16px; + } + + &.is-active { + border: 2px solid var(--theme-color); + } + + img { + width: 100%; + height: 100%; + } + } + + .name { + margin-top: 6px; + font-size: 14px; + text-align: center; + } + } + } + } + + // 去除滚动条 + .el-drawer__body::-webkit-scrollbar { + width: 0 !important; + } +} + +.dark { + .setting-modal { + .el-drawer { + background: rgba($color: #000, $alpha: 50%) !important; + + .setting-item { + .box { + border: 2px solid transparent; + } + } + } + } +} + +// 去除火狐浏览器滚动条 +:deep(.el-drawer__body) { + scrollbar-width: none; +} + +// 移动端隐藏 +@media screen and (width <= 800px) { + .mobile-hide { + display: none !important; + } +} diff --git a/src/components/core/layouts/art-settings-panel/widget/BasicSettings.vue b/src/components/core/layouts/art-settings-panel/widget/BasicSettings.vue new file mode 100644 index 0000000..b6dc9d3 --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/widget/BasicSettings.vue @@ -0,0 +1,77 @@ + + + diff --git a/src/components/core/layouts/art-settings-panel/widget/BoxStyleSettings.vue b/src/components/core/layouts/art-settings-panel/widget/BoxStyleSettings.vue new file mode 100644 index 0000000..86c7a9e --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/widget/BoxStyleSettings.vue @@ -0,0 +1,38 @@ + + + diff --git a/src/components/core/layouts/art-settings-panel/widget/ColorSettings.vue b/src/components/core/layouts/art-settings-panel/widget/ColorSettings.vue new file mode 100644 index 0000000..05a4b41 --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/widget/ColorSettings.vue @@ -0,0 +1,35 @@ + + + diff --git a/src/components/core/layouts/art-settings-panel/widget/ContainerSettings.vue b/src/components/core/layouts/art-settings-panel/widget/ContainerSettings.vue new file mode 100644 index 0000000..1f5be72 --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/widget/ContainerSettings.vue @@ -0,0 +1,33 @@ + + + diff --git a/src/components/core/layouts/art-settings-panel/widget/MenuLayoutSettings.vue b/src/components/core/layouts/art-settings-panel/widget/MenuLayoutSettings.vue new file mode 100644 index 0000000..dbcae46 --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/widget/MenuLayoutSettings.vue @@ -0,0 +1,31 @@ + + + diff --git a/src/components/core/layouts/art-settings-panel/widget/MenuStyleSettings.vue b/src/components/core/layouts/art-settings-panel/widget/MenuStyleSettings.vue new file mode 100644 index 0000000..61237eb --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/widget/MenuStyleSettings.vue @@ -0,0 +1,44 @@ + + + diff --git a/src/components/core/layouts/art-settings-panel/widget/SectionTitle.vue b/src/components/core/layouts/art-settings-panel/widget/SectionTitle.vue new file mode 100644 index 0000000..31ef00c --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/widget/SectionTitle.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/components/core/layouts/art-settings-panel/widget/SettingActions.vue b/src/components/core/layouts/art-settings-panel/widget/SettingActions.vue new file mode 100644 index 0000000..7b47d1a --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/widget/SettingActions.vue @@ -0,0 +1,235 @@ + + + + diff --git a/src/components/core/layouts/art-settings-panel/widget/SettingDrawer.vue b/src/components/core/layouts/art-settings-panel/widget/SettingDrawer.vue new file mode 100644 index 0000000..85372be --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/widget/SettingDrawer.vue @@ -0,0 +1,51 @@ + + + diff --git a/src/components/core/layouts/art-settings-panel/widget/SettingHeader.vue b/src/components/core/layouts/art-settings-panel/widget/SettingHeader.vue new file mode 100644 index 0000000..e3ead9e --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/widget/SettingHeader.vue @@ -0,0 +1,18 @@ + + + diff --git a/src/components/core/layouts/art-settings-panel/widget/SettingItem.vue b/src/components/core/layouts/art-settings-panel/widget/SettingItem.vue new file mode 100644 index 0000000..5721027 --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/widget/SettingItem.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/src/components/core/layouts/art-settings-panel/widget/ThemeSettings.vue b/src/components/core/layouts/art-settings-panel/widget/ThemeSettings.vue new file mode 100644 index 0000000..4b46fcd --- /dev/null +++ b/src/components/core/layouts/art-settings-panel/widget/ThemeSettings.vue @@ -0,0 +1,28 @@ + + + diff --git a/src/components/core/layouts/art-work-tab/index.vue b/src/components/core/layouts/art-work-tab/index.vue new file mode 100644 index 0000000..152ff63 --- /dev/null +++ b/src/components/core/layouts/art-work-tab/index.vue @@ -0,0 +1,584 @@ + + + + + + diff --git a/src/components/core/media/art-cutter-img/index.vue b/src/components/core/media/art-cutter-img/index.vue new file mode 100644 index 0000000..191ceed --- /dev/null +++ b/src/components/core/media/art-cutter-img/index.vue @@ -0,0 +1,350 @@ + + + + + + diff --git a/src/components/core/media/art-video-player/index.vue b/src/components/core/media/art-video-player/index.vue new file mode 100644 index 0000000..4f681ea --- /dev/null +++ b/src/components/core/media/art-video-player/index.vue @@ -0,0 +1,111 @@ + + + + diff --git a/src/components/core/others/art-menu-right/index.vue b/src/components/core/others/art-menu-right/index.vue new file mode 100644 index 0000000..1cc92ab --- /dev/null +++ b/src/components/core/others/art-menu-right/index.vue @@ -0,0 +1,415 @@ + + + + + + diff --git a/src/components/core/others/art-watermark/index.vue b/src/components/core/others/art-watermark/index.vue new file mode 100644 index 0000000..1d7f06b --- /dev/null +++ b/src/components/core/others/art-watermark/index.vue @@ -0,0 +1,64 @@ + + + + diff --git a/src/components/core/tables/art-table-header/index.vue b/src/components/core/tables/art-table-header/index.vue new file mode 100644 index 0000000..788c2b7 --- /dev/null +++ b/src/components/core/tables/art-table-header/index.vue @@ -0,0 +1,339 @@ + + + + + + diff --git a/src/components/core/tables/art-table/index.vue b/src/components/core/tables/art-table/index.vue new file mode 100644 index 0000000..2392d96 --- /dev/null +++ b/src/components/core/tables/art-table/index.vue @@ -0,0 +1,342 @@ + + + + + + + + + diff --git a/src/components/core/tables/art-table/style.scss b/src/components/core/tables/art-table/style.scss new file mode 100644 index 0000000..67459e8 --- /dev/null +++ b/src/components/core/tables/art-table/style.scss @@ -0,0 +1,99 @@ +.art-table { + position: relative; + height: 100%; + + .el-table { + height: 100%; + margin-top: 10px; + } + + :deep(.el-loading-mask) { + z-index: 100; + background-color: var(--default-box-color) !important; + } + + // Loading 过渡动画 - 消失时淡出 + .loading-fade-leave-active { + transition: opacity 0.3s ease-out; + } + + .loading-fade-leave-to { + opacity: 0; + } + + // 空状态垂直居中 + &.is-empty { + :deep(.el-scrollbar__wrap) { + display: flex; + } + } + + .pagination { + display: flex; + margin-top: 13px; + + :deep(.el-select) { + width: 102px !important; + } + + // 分页对齐方式 + &.left { + justify-content: flex-start; + } + + &.center { + justify-content: center; + } + + &.right { + justify-content: flex-end; + } + + // 自定义分页组件样式 + &.custom-pagination { + :deep(.el-pagination) { + .btn-prev, + .btn-next { + background-color: transparent; + border: 1px solid var(--art-gray-300); + transition: border-color 0.15s; + + &:hover:not(.is-disabled) { + color: var(--theme-color); + border-color: var(--theme-color); + } + } + + li { + box-sizing: border-box; + font-weight: 400 !important; + background-color: transparent; + border: 1px solid var(--art-gray-300); + transition: border-color 0.15s; + + &.is-active { + font-weight: 400; + color: #fff; + background-color: var(--theme-color); + border: 1px solid var(--theme-color); + } + + &:hover:not(.is-disabled) { + border-color: var(--theme-color); + } + } + } + } + } +} + +// 移动端分页 +@media (width <= 640px) { + :deep(.el-pagination) { + display: flex; + flex-wrap: wrap; + gap: 15px 0; + align-items: center; + justify-content: center; + } +} diff --git a/src/components/core/text-effect/art-count-to/index.vue b/src/components/core/text-effect/art-count-to/index.vue new file mode 100644 index 0000000..7fb104b --- /dev/null +++ b/src/components/core/text-effect/art-count-to/index.vue @@ -0,0 +1,310 @@ + + + + diff --git a/src/components/core/text-effect/art-festival-text-scroll/index.vue b/src/components/core/text-effect/art-festival-text-scroll/index.vue new file mode 100644 index 0000000..770b457 --- /dev/null +++ b/src/components/core/text-effect/art-festival-text-scroll/index.vue @@ -0,0 +1,32 @@ + + + + diff --git a/src/components/core/text-effect/art-text-scroll/index.vue b/src/components/core/text-effect/art-text-scroll/index.vue new file mode 100644 index 0000000..90be30f --- /dev/null +++ b/src/components/core/text-effect/art-text-scroll/index.vue @@ -0,0 +1,285 @@ + + + + diff --git a/src/components/core/theme/theme-svg/index.vue b/src/components/core/theme/theme-svg/index.vue new file mode 100644 index 0000000..0b565a9 --- /dev/null +++ b/src/components/core/theme/theme-svg/index.vue @@ -0,0 +1,100 @@ + + + + + + + diff --git a/src/components/core/views/exception/ArtException.vue b/src/components/core/views/exception/ArtException.vue new file mode 100644 index 0000000..699228f --- /dev/null +++ b/src/components/core/views/exception/ArtException.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/components/core/views/login/AuthTopBar.vue b/src/components/core/views/login/AuthTopBar.vue new file mode 100644 index 0000000..9455253 --- /dev/null +++ b/src/components/core/views/login/AuthTopBar.vue @@ -0,0 +1,149 @@ + + + + + + diff --git a/src/components/core/views/login/LoginLeftView.vue b/src/components/core/views/login/LoginLeftView.vue new file mode 100644 index 0000000..af6a904 --- /dev/null +++ b/src/components/core/views/login/LoginLeftView.vue @@ -0,0 +1,602 @@ + + + + + + diff --git a/src/components/core/views/result/ArtResultPage.vue b/src/components/core/views/result/ArtResultPage.vue new file mode 100644 index 0000000..b2eca48 --- /dev/null +++ b/src/components/core/views/result/ArtResultPage.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/components/core/widget/art-icon-button/index.vue b/src/components/core/widget/art-icon-button/index.vue new file mode 100644 index 0000000..760888b --- /dev/null +++ b/src/components/core/widget/art-icon-button/index.vue @@ -0,0 +1,23 @@ + + + + diff --git a/src/config/assets/images.ts b/src/config/assets/images.ts new file mode 100644 index 0000000..f3e89dd --- /dev/null +++ b/src/config/assets/images.ts @@ -0,0 +1,61 @@ +/** + * 配置图片资源 + * + * 统一管理设置中心使用的预览图片资源。 + * 包含主题样式、菜单布局、菜单风格的预览图。 + * + * ## 图片分类 + * + * - themeStyles: 系统主题预览图(亮色/暗色/自动) + * - menuLayouts: 菜单布局预览图(左侧/顶部/混合/双栏) + * - menuStyles: 菜单风格预览图(设计/暗色/亮色) + * + * @module config/assets/images + * @author Art Design Pro Team + */ + +import lightTheme from '@imgs/settings/theme_styles/light.png' +import darkTheme from '@imgs/settings/theme_styles/dark.png' +import systemTheme from '@imgs/settings/theme_styles/system.png' +import verticalLayout from '@imgs/settings/menu_layouts/vertical.png' +import horizontalLayout from '@imgs/settings/menu_layouts/horizontal.png' +import mixedLayout from '@imgs/settings/menu_layouts/mixed.png' +import dualColumnLayout from '@imgs/settings/menu_layouts/dual_column.png' +import designStyle from '@imgs/settings/menu_styles/design.png' +import darkStyle from '@imgs/settings/menu_styles/dark.png' +import lightStyle from '@imgs/settings/menu_styles/light.png' + +/** + * 配置中心图片资源对象 + */ +export const configImages = { + /** 系统主题预览图 */ + themeStyles: { + /** 亮色主题 */ + light: lightTheme, + /** 暗色主题 */ + dark: darkTheme, + /** 自动主题(跟随系统) */ + system: systemTheme + }, + /** 菜单布局预览图 */ + menuLayouts: { + /** 左侧菜单 */ + vertical: verticalLayout, + /** 顶部菜单 */ + horizontal: horizontalLayout, + /** 混合菜单 */ + mixed: mixedLayout, + /** 双栏菜单 */ + dualColumn: dualColumnLayout + }, + /** 菜单风格预览图 */ + menuStyles: { + /** 设计风格 */ + design: designStyle, + /** 暗色风格 */ + dark: darkStyle, + /** 亮色风格 */ + light: lightStyle + } +} diff --git a/src/config/fastEnter.ts b/src/config/fastEnter.ts new file mode 100644 index 0000000..ccade16 --- /dev/null +++ b/src/config/fastEnter.ts @@ -0,0 +1,79 @@ +/** + * 快速入口配置 + * 包含:应用列表、快速链接等配置 + */ +import { WEB_LINKS } from '@/utils/constants' +import type { FastEnterConfig } from '@/types/config' + +const fastEnterConfig: FastEnterConfig = { + // 显示条件(屏幕宽度) + minWidth: 1200, + // 应用列表 + applications: [ + { + name: '工作台', + description: '系统概览与数据统计', + icon: 'ri:pie-chart-line', + iconColor: '#377dff', + enabled: true, + order: 1, + routeName: 'Console' + }, + { + name: '官方文档', + description: '使用指南与开发文档', + icon: 'ri:bill-line', + iconColor: '#ffb100', + enabled: true, + order: 2, + link: WEB_LINKS.DOCS + }, + { + name: '技术支持', + description: '技术支持与问题反馈', + icon: 'ri:user-location-line', + iconColor: '#ff6b6b', + enabled: true, + order: 3, + link: WEB_LINKS.COMMUNITY + }, + { + name: '哔哩哔哩', + description: '技术分享与交流', + icon: 'ri:bilibili-line', + iconColor: '#FB7299', + enabled: true, + order: 4, + link: WEB_LINKS.BILIBILI + } + ], + // 快速链接 + quickLinks: [ + { + name: '登录', + enabled: true, + order: 1, + routeName: 'Login' + }, + { + name: '注册', + enabled: true, + order: 2, + routeName: 'Register' + }, + { + name: '忘记密码', + enabled: true, + order: 3, + routeName: 'ForgetPassword' + }, + { + name: '个人中心', + enabled: true, + order: 4, + routeName: 'UserCenter' + } + ] +} + +export default Object.freeze(fastEnterConfig) diff --git a/src/config/index.ts b/src/config/index.ts new file mode 100644 index 0000000..daa623a --- /dev/null +++ b/src/config/index.ts @@ -0,0 +1,135 @@ +/** + * 系统全局配置 + * + * 这是系统的核心配置文件,集中管理所有全局配置项。 + * 包含系统信息、主题样式、菜单布局、颜色方案等所有可配置项。 + * + * ## 主要功能 + * + * - 系统信息 - 系统名称等基础信息 + * - 主题配置 - 亮色/暗色/自动主题的样式配置 + * - 菜单配置 - 菜单布局、主题、宽度等配置 + * - 颜色方案 - 系统主色和预设颜色列表 + * - 快速入口 - 快速入口应用和链接配置 + * - 顶部栏配置 - 顶部栏功能模块配置 + * + * ## 配置项说明 + * + * - systemInfo: 系统基础信息(名称等) + * - systemThemeStyles: 系统主题样式映射 + * - settingThemeList: 可选的系统主题列表 + * - menuLayoutList: 可选的菜单布局列表 + * - themeList: 菜单主题样式列表 + * - darkMenuStyles: 暗黑模式下的菜单样式 + * - systemMainColor: 预设的系统主色列表 + * - fastEnter: 快速入口配置 + * - headerBar: 顶部栏功能配置 + * + * @module config + * @author Art Design Pro Team + */ + +import { MenuThemeEnum, MenuTypeEnum, SystemThemeEnum } from '@/enums/appEnum' +import { SystemConfig } from '@/types/config' +import { configImages } from './assets/images' +import fastEnterConfig from './modules/fastEnter' +import { headerBarConfig } from './modules/headerBar' + +const appConfig: SystemConfig = { + // 系统信息 + systemInfo: { + name: 'Art Design Pro' // 系统名称 + }, + // 系统主题 + systemThemeStyles: { + [SystemThemeEnum.LIGHT]: { className: '' }, + [SystemThemeEnum.DARK]: { className: SystemThemeEnum.DARK } + }, + // 系统主题列表 + settingThemeList: [ + { + name: 'Light', + theme: SystemThemeEnum.LIGHT, + color: ['#fff', '#fff'], + leftLineColor: '#EDEEF0', + rightLineColor: '#EDEEF0', + img: configImages.themeStyles.light + }, + { + name: 'Dark', + theme: SystemThemeEnum.DARK, + color: ['#22252A'], + leftLineColor: '#3F4257', + rightLineColor: '#3F4257', + img: configImages.themeStyles.dark + }, + { + name: 'System', + theme: SystemThemeEnum.AUTO, + color: ['#fff', '#22252A'], + leftLineColor: '#EDEEF0', + rightLineColor: '#3F4257', + img: configImages.themeStyles.system + } + ], + // 菜单布局列表 + menuLayoutList: [ + { name: 'Left', value: MenuTypeEnum.LEFT, img: configImages.menuLayouts.vertical }, + { name: 'Top', value: MenuTypeEnum.TOP, img: configImages.menuLayouts.horizontal }, + { name: 'Mixed', value: MenuTypeEnum.TOP_LEFT, img: configImages.menuLayouts.mixed }, + { name: 'Dual Column', value: MenuTypeEnum.DUAL_MENU, img: configImages.menuLayouts.dualColumn } + ], + // 菜单主题列表 + themeList: [ + { + theme: MenuThemeEnum.DESIGN, + background: '#FFFFFF', + systemNameColor: 'var(--art-gray-800)', + iconColor: '#6B6B6B', + textColor: '#29343D', + img: configImages.menuStyles.design + }, + { + theme: MenuThemeEnum.DARK, + background: '#191A23', + systemNameColor: '#D9DADB', + iconColor: '#BABBBD', + textColor: '#BABBBD', + img: configImages.menuStyles.dark + }, + { + theme: MenuThemeEnum.LIGHT, + background: '#ffffff', + systemNameColor: 'var(--art-gray-800)', + iconColor: '#6B6B6B', + textColor: '#29343D', + img: configImages.menuStyles.light + } + ], + // 暗黑模式菜单样式 + darkMenuStyles: [ + { + theme: MenuThemeEnum.DARK, + background: 'var(--default-box-color)', + systemNameColor: '#DDDDDD', + iconColor: '#BABBBD', + textColor: 'rgba(#FFFFFF, 0.7)' + } + ], + // 系统主色 + systemMainColor: [ + '#5D87FF', + '#B48DF3', + '#1D84FF', + '#60C041', + '#38C0FC', + '#F9901F', + '#FF80C8' + ] as const, + // 快速入口配置 + fastEnter: fastEnterConfig, + // 顶部栏功能配置 + headerBar: headerBarConfig +} + +export default Object.freeze(appConfig) diff --git a/src/config/modules/component.ts b/src/config/modules/component.ts new file mode 100644 index 0000000..bc709e0 --- /dev/null +++ b/src/config/modules/component.ts @@ -0,0 +1,105 @@ +/** + * 全局组件配置 + * + * 统一管理系统级全局组件的注册。 + * 这些组件会在应用启动时全局注册,可在任何地方使用。 + * + * ## 主要功能 + * + * - 组件配置 - 集中管理全局组件的配置信息 + * - 异步加载 - 使用 defineAsyncComponent 实现按需加载 + * - 开关控制 - 支持通过 enabled 字段启用/禁用组件 + * - 配置查询 - 提供工具函数快速查询组件配置 + * + * @module config/component + * @author Art Design Pro Team + */ + +import { defineAsyncComponent } from 'vue' + +/** + * 全局组件配置列表 + */ +export const globalComponentsConfig: GlobalComponentConfig[] = [ + { + name: '设置面板', + key: 'settings-panel', + component: defineAsyncComponent( + () => import('@/components/core/layouts/art-settings-panel/index.vue') + ), + enabled: true + }, + { + name: '全局搜索', + key: 'global-search', + component: defineAsyncComponent( + () => import('@/components/core/layouts/art-global-search/index.vue') + ), + enabled: true + }, + { + name: '锁屏', + key: 'screen-lock', + component: defineAsyncComponent( + () => import('@/components/core/layouts/art-screen-lock/index.vue') + ), + enabled: true + }, + { + name: '聊天窗口', + key: 'chat-window', + component: defineAsyncComponent( + () => import('@/components/core/layouts/art-chat-window/index.vue') + ), + enabled: true + }, + { + name: '礼花效果', + key: 'fireworks-effect', + component: defineAsyncComponent( + () => import('@/components/core/layouts/art-fireworks-effect/index.vue') + ), + enabled: true + }, + { + name: '水印效果', + key: 'watermark', + component: defineAsyncComponent( + () => import('@/components/core/others/art-watermark/index.vue') + ), + enabled: true + } +] + +/** + * 全局组件配置接口 + */ +export interface GlobalComponentConfig { + /** 组件名称 */ + name: string + /** 组件标识 */ + key: string + /** 组件 */ + component: any + /** 是否启用 */ + enabled?: boolean + /** 组件描述 */ + description?: string +} + +/** + * 获取启用的全局组件 + * @returns 已启用的组件配置列表 + */ +export const getEnabledGlobalComponents = () => { + return globalComponentsConfig.filter((config) => config.enabled !== false) +} + +/** + * 根据 key 获取组件配置 + * @param key 组件标识 + * @returns 组件配置对象 + */ +export const getGlobalComponentByKey = (key: string) => { + return globalComponentsConfig.find((config) => config.key === key) +} diff --git a/src/config/modules/fastEnter.ts b/src/config/modules/fastEnter.ts new file mode 100644 index 0000000..6b9740c --- /dev/null +++ b/src/config/modules/fastEnter.ts @@ -0,0 +1,127 @@ +/** + * 快速入口配置 + * 包含:应用列表、快速链接等配置 + */ +import { WEB_LINKS } from '@/utils/constants' +import type { FastEnterConfig } from '@/types/config' + +const fastEnterConfig: FastEnterConfig = { + // 显示条件(屏幕宽度) + minWidth: 1200, + // 应用列表 + applications: [ + { + name: '工作台', + description: '系统概览与数据统计', + icon: 'ri:pie-chart-line', + iconColor: '#377dff', + enabled: true, + order: 1, + routeName: 'Console' + }, + { + name: '分析页', + description: '数据分析与可视化', + icon: 'ri:game-line', + iconColor: '#ff3b30', + enabled: true, + order: 2, + routeName: 'Analysis' + }, + { + name: '礼花效果', + description: '动画特效展示', + icon: 'ri:loader-line', + iconColor: '#7A7FFF', + enabled: true, + order: 3, + routeName: 'Fireworks' + }, + { + name: '聊天', + description: '即时通讯功能', + icon: 'ri:user-line', + iconColor: '#13DEB9', + enabled: true, + order: 4, + routeName: 'Chat' + }, + { + name: '官方文档', + description: '使用指南与开发文档', + icon: 'ri:bill-line', + iconColor: '#ffb100', + enabled: true, + order: 5, + link: WEB_LINKS.DOCS + }, + { + name: '技术支持', + description: '技术支持与问题反馈', + icon: 'ri:user-location-line', + iconColor: '#ff6b6b', + enabled: true, + order: 6, + link: WEB_LINKS.COMMUNITY + }, + { + name: '更新日志', + description: '版本更新与变更记录', + icon: 'ri:gamepad-line', + iconColor: '#38C0FC', + enabled: true, + order: 7, + routeName: 'ChangeLog' + }, + { + name: '哔哩哔哩', + description: '技术分享与交流', + icon: 'ri:bilibili-line', + iconColor: '#FB7299', + enabled: true, + order: 8, + link: WEB_LINKS.BILIBILI + } + ], + // 快速链接 + quickLinks: [ + { + name: '登录', + enabled: true, + order: 1, + routeName: 'Login' + }, + { + name: '注册', + enabled: true, + order: 2, + routeName: 'Register' + }, + { + name: '忘记密码', + enabled: true, + order: 3, + routeName: 'ForgetPassword' + }, + { + name: '定价', + enabled: true, + order: 4, + routeName: 'Pricing' + }, + { + name: '个人中心', + enabled: true, + order: 5, + routeName: 'UserCenter' + }, + { + name: '留言管理', + enabled: true, + order: 6, + routeName: 'ArticleComment' + } + ] +} + +export default Object.freeze(fastEnterConfig) diff --git a/src/config/modules/festival.ts b/src/config/modules/festival.ts new file mode 100644 index 0000000..39cd790 --- /dev/null +++ b/src/config/modules/festival.ts @@ -0,0 +1,51 @@ +/** + * 节日庆祝配置 + * + * 配置系统的节日烟花效果和祝福文本。 + * 支持单日节日和跨日期节日,可自定义烟花播放次数。 + * + * ## 配置说明 + * + * - name: 节日名称 + * - date: 节日开始日期(格式:YYYY-MM-DD) + * - endDate: 节日结束日期(可选,用于跨日期节日) + * - image: 烟花图片(需要预先导入) + * - scrollText: 滚动显示的祝福文本 + * - count: 烟花播放次数(可选,默认为 3 次) + * + * ## 注意事项 + * + * - 图片需要预先导入并在配置中引用 + * - 跨日期节日会在整个日期范围内生效 + * - 每个用户每天只会播放一次烟花效果 + * + * @module config/modules/festival + * @author Art Design Pro Team + */ + +import { FestivalConfig } from '@/types/config' + +// 导入烟花图片(根据需要取消注释) +// import sd from '@imgs/ceremony/sd.png' +// import yd from '@imgs/ceremony/yd.png' + +export const festivalConfigList: FestivalConfig[] = [ + // 跨日期示例 + // { + // name: 'v3.0 Sass 升级至 TailwindCSS', + // date: '2025-11-03', + // endDate: '2025-11-09', + // image: '', + // count: 3, + // scrollText: + // '🚀 系统 v3.0 测试阶段正式开启!测试周期为 11 月 3 日 - 11 月 16 日,通过 TailwindCSS 重构样式体系、统一 Iconify 图标方案,带来更高效现代的开发体验,正式发布敬请期待~' + // } + // 单日示例:圣诞节 + // { + // name: '圣诞节', + // date: '2024-12-25', + // image: sd, + // count: 3 // 可选,不设置则使用默认值 3 次 + // scrollText: 'Merry Christmas!Art Design Pro 祝您圣诞快乐,愿节日的欢乐与祝福如雪花般纷至沓来!', + // } +] diff --git a/src/config/modules/headerBar.ts b/src/config/modules/headerBar.ts new file mode 100644 index 0000000..a420e82 --- /dev/null +++ b/src/config/modules/headerBar.ts @@ -0,0 +1,63 @@ +/** + * 顶部栏功能配置 + * + * 统一管理顶部栏各个功能模块的启用状态。 + * 通过修改此配置文件可以快速启用或禁用顶部栏的功能按钮。 + * + * @module config/headerBar + * @author Art Design Pro Team + */ + +import { HeaderBarFeatureConfig } from '@/types' + +/** + * 顶部栏功能配置对象 + */ +export const headerBarConfig: HeaderBarFeatureConfig = { + menuButton: { + enabled: true, + description: '控制左侧菜单的展开/收起按钮' + }, + refreshButton: { + enabled: true, + description: '页面刷新按钮' + }, + fastEnter: { + enabled: true, + description: '快速入口功能,提供常用应用和链接的快速访问' + }, + breadcrumb: { + enabled: true, + description: '面包屑导航,显示当前页面路径' + }, + globalSearch: { + enabled: true, + description: '全局搜索功能,支持快捷键 Ctrl+K 或 Cmd+K' + }, + fullscreen: { + enabled: true, + description: '全屏切换功能' + }, + notification: { + enabled: true, + description: '通知中心,显示系统通知和消息' + }, + chat: { + enabled: true, + description: '聊天功能,提供实时沟通' + }, + language: { + enabled: true, + description: '多语言切换功能' + }, + settings: { + enabled: true, + description: '系统设置面板' + }, + themeToggle: { + enabled: true, + description: '主题切换功能(明暗主题)' + } +} + +export default headerBarConfig diff --git a/src/config/setting.ts b/src/config/setting.ts new file mode 100644 index 0000000..94f2d2c --- /dev/null +++ b/src/config/setting.ts @@ -0,0 +1,109 @@ +/** + * 系统设置默认值配置 + * + * 统一管理系统设置的所有默认值 + * + * ## 主要功能 + * + * - 菜单相关默认配置 + * - 主题相关默认配置 + * - 界面显示默认配置 + * - 功能开关默认配置 + * - 样式相关默认配置 + * + * ## 注意事项 + * + * 1. 修改此文件的配置项时,需要同步更新以下文件: + * - src/components/core/layouts/art-settings-panel/widget/SettingActions.vue(复制配置和重置配置逻辑) + * - src/store/modules/setting.ts(Store 状态定义) + * 2. 可以通过设置面板的"复制配置"按钮快速生成配置代码 + * 3. 枚举类型的值需要与 src/enums/appEnum.ts 中的定义保持一致 + */ + +import AppConfig from '@/config' +import { SystemThemeEnum, MenuThemeEnum, MenuTypeEnum, ContainerWidthEnum } from '@/enums/appEnum' + +/** + * 系统设置默认值配置 + */ +export const SETTING_DEFAULT_CONFIG = { + /** 菜单类型 */ + menuType: MenuTypeEnum.LEFT, + /** 菜单展开宽度 */ + menuOpenWidth: 230, + /** 菜单是否展开 */ + menuOpen: true, + /** 双菜单是否显示文本 */ + dualMenuShowText: false, + /** 系统主题类型 */ + systemThemeType: SystemThemeEnum.AUTO, + /** 系统主题模式 */ + systemThemeMode: SystemThemeEnum.AUTO, + /** 菜单风格 */ + menuThemeType: MenuThemeEnum.DESIGN, + /** 系统主题颜色 */ + systemThemeColor: AppConfig.systemMainColor[0], + /** 是否显示菜单按钮 */ + showMenuButton: true, + /** 是否显示快速入口 */ + showFastEnter: true, + /** 是否显示刷新按钮 */ + showRefreshButton: true, + /** 是否显示面包屑 */ + showCrumbs: true, + /** 是否显示工作台标签 */ + showWorkTab: true, + /** 是否显示语言切换 */ + showLanguage: true, + /** 是否显示进度条 */ + showNprogress: false, + /** 是否显示设置引导 */ + showSettingGuide: true, + /** 是否显示节日文本 */ + showFestivalText: false, + /** 是否显示水印 */ + watermarkVisible: false, + /** 是否自动关闭 */ + autoClose: false, + /** 是否唯一展开 */ + uniqueOpened: true, + /** 是否色弱模式 */ + colorWeak: false, + /** 是否刷新 */ + refresh: false, + /** 是否加载节日烟花 */ + holidayFireworksLoaded: false, + /** 边框模式 */ + boxBorderMode: true, + /** 页面过渡效果 */ + pageTransition: 'slide-left', + /** 标签页样式 */ + tabStyle: 'tab-default', + /** 自定义圆角 */ + customRadius: '0.75', + /** 容器宽度 */ + containerWidth: ContainerWidthEnum.FULL, + /** 节日日期 */ + festivalDate: '' +} + +/** + * 获取设置默认值 + * @returns 设置默认值对象 + */ +export function getSettingDefaults() { + return { ...SETTING_DEFAULT_CONFIG } +} + +/** + * 重置为默认设置 + * @param currentSettings 当前设置对象 + */ +export function resetToDefaults(currentSettings: Record) { + const defaults = getSettingDefaults() + Object.keys(defaults).forEach((key) => { + if (key in currentSettings) { + currentSettings[key] = defaults[key as keyof typeof defaults] + } + }) +} diff --git a/src/directives/business/highlight.ts b/src/directives/business/highlight.ts new file mode 100644 index 0000000..13af225 --- /dev/null +++ b/src/directives/business/highlight.ts @@ -0,0 +1,248 @@ +/** + * v-highlight 代码高亮指令 + * + * 为代码块提供语法高亮、行号显示和一键复制功能。 + * 基于 highlight.js 实现,支持多种编程语言的语法高亮。 + * + * ## 主要功能 + * + * - 语法高亮 - 使用 highlight.js 自动识别并高亮代码 + * - 行号显示 - 自动为每行代码添加行号 + * - 一键复制 - 提供复制按钮,点击即可复制代码(自动过滤行号) + * - 性能优化 - 批量处理代码块,避免阻塞渲染 + * - 动态监听 - 使用 MutationObserver 监听新增代码块 + * - 防重复处理 - 自动标记已处理的代码块,避免重复处理 + * + * ## 使用示例 + * + * ```vue + * + * ``` + * + * ## 性能优化 + * + * - 批量处理:每次处理 10 个代码块,避免长时间阻塞 + * - 延迟处理:使用 requestAnimationFrame 分批处理 + * - 重试机制:自动重试处理失败的代码块 + * - 智能监听:只在有新代码块时才触发处理 + * + * @module directives/highlight + * @author Art Design Pro Team + */ + +import { App, Directive } from 'vue' +import hljs from 'highlight.js' + +// 高亮代码 +function highlightCode(block: HTMLElement) { + hljs.highlightElement(block) +} + +// 插入行号 +function insertLineNumbers(block: HTMLElement) { + const lines = block.innerHTML.split('\n') + const numberedLines = lines + .map((line, index) => { + return `${index + 1} ${line}` + }) + .join('\n') + block.innerHTML = numberedLines +} + +// 添加复制按钮:调整 DOM 结构,将代码部分包裹在 .code-wrapper 内 +function addCopyButton(block: HTMLElement) { + const copyButton = document.createElement('i') + copyButton.className = 'copy-button' + copyButton.innerHTML = + '' + copyButton.onclick = () => { + // 过滤掉行号,只复制代码内容 + const codeContent = block.innerText.replace(/^\d+\s+/gm, '') + navigator.clipboard.writeText(codeContent).then(() => { + ElMessage.success('复制成功') + }) + } + + const preElement = block.parentElement + if (preElement) { + let codeWrapper: HTMLElement + // 如果代码块还没有被包裹,则创建包裹容器 + if (!block.parentElement.classList.contains('code-wrapper')) { + codeWrapper = document.createElement('div') + codeWrapper.className = 'code-wrapper' + preElement.replaceChild(codeWrapper, block) + codeWrapper.appendChild(block) + } else { + codeWrapper = block.parentElement + } + // 将复制按钮添加到 pre 元素(而非 codeWrapper 内),这样它不会随滚动条滚动 + preElement.appendChild(copyButton) + } +} + +// 检查代码块是否已经被处理过 +function isBlockProcessed(block: HTMLElement): boolean { + return ( + block.hasAttribute('data-highlighted') || + !!block.querySelector('.line-number') || + !!block.parentElement?.querySelector('.copy-button') + ) +} + +// 标记代码块为已处理 +function markBlockAsProcessed(block: HTMLElement) { + block.setAttribute('data-highlighted', 'true') +} + +// 处理单个代码块 +function processBlock(block: HTMLElement) { + if (isBlockProcessed(block)) { + return + } + + try { + highlightCode(block) + insertLineNumbers(block) + addCopyButton(block) + markBlockAsProcessed(block) + } catch (error) { + console.warn('处理代码块时出错:', error) + } +} + +// 查找并处理所有代码块 +function processAllCodeBlocks(el: HTMLElement) { + const blocks = Array.from(el.querySelectorAll('pre code')) + const unprocessedBlocks = blocks.filter((block) => !isBlockProcessed(block)) + + if (unprocessedBlocks.length === 0) { + return + } + + if (unprocessedBlocks.length <= 10) { + // 如果代码块数量少于等于10,直接处理所有代码块 + unprocessedBlocks.forEach((block) => processBlock(block)) + } else { + // 定义每次处理的代码块数 + const batchSize = 10 + let currentIndex = 0 + + const processBatch = () => { + const batch = unprocessedBlocks.slice(currentIndex, currentIndex + batchSize) + + batch.forEach((block) => { + processBlock(block) + }) + + // 更新索引并继续处理下一批 + currentIndex += batchSize + if (currentIndex < unprocessedBlocks.length) { + // 使用 requestAnimationFrame 确保下一帧再处理 + requestAnimationFrame(processBatch) + } + } + + // 开始处理第一批代码块 + processBatch() + } +} + +// 重试处理函数 +function retryProcessing(el: HTMLElement, maxRetries: number = 3, delay: number = 200) { + let retryCount = 0 + + const tryProcess = () => { + processAllCodeBlocks(el) + + // 检查是否还有未处理的代码块 + const remainingBlocks = Array.from(el.querySelectorAll('pre code')).filter( + (block) => !isBlockProcessed(block) + ) + + if (remainingBlocks.length > 0 && retryCount < maxRetries) { + retryCount++ + setTimeout(tryProcess, delay * retryCount) // 递增延迟 + } + } + + tryProcess() +} + +// 代码高亮、插入行号、复制按钮 +const highlightDirective: Directive = { + mounted(el: HTMLElement) { + // 立即尝试处理一次 + processAllCodeBlocks(el) + + // 延迟处理,确保 v-html 内容已经渲染 + setTimeout(() => { + retryProcessing(el) + }, 100) + + // 使用 MutationObserver 监听 DOM 变化 + const observer = new MutationObserver((mutations) => { + let hasNewCodeBlocks = false + + mutations.forEach((mutation) => { + if (mutation.type === 'childList') { + mutation.addedNodes.forEach((node) => { + if (node.nodeType === Node.ELEMENT_NODE) { + const element = node as HTMLElement + // 检查新添加的节点是否包含代码块 + if (element.tagName === 'PRE' || element.querySelector('pre code')) { + hasNewCodeBlocks = true + } + } + }) + } + }) + + if (hasNewCodeBlocks) { + // 延迟处理新添加的代码块 + setTimeout(() => { + processAllCodeBlocks(el) + }, 50) + } + }) + + // 开始观察 + observer.observe(el, { + childList: true, + subtree: true + }) + + // 将 observer 存储到元素上,以便在 unmounted 时清理 + ;(el as any)._highlightObserver = observer + }, + + updated(el: HTMLElement) { + // 当组件更新时,重新处理代码块 + setTimeout(() => { + processAllCodeBlocks(el) + }, 50) + }, + + unmounted(el: HTMLElement) { + // 清理 MutationObserver + const observer = (el as any)._highlightObserver + if (observer) { + observer.disconnect() + delete (el as any)._highlightObserver + } + } +} + +export function setupHighlightDirective(app: App) { + app.directive('highlight', highlightDirective) +} diff --git a/src/directives/business/ripple.ts b/src/directives/business/ripple.ts new file mode 100644 index 0000000..8d7d8f9 --- /dev/null +++ b/src/directives/business/ripple.ts @@ -0,0 +1,114 @@ +/** + * v-ripple 水波纹效果指令 + * + * 为元素添加 Material Design 风格的水波纹点击效果。 + * 点击时从点击位置扩散出圆形水波纹动画,提升交互体验。 + * + * ## 主要功能 + * + * - 水波纹动画 - 点击时从点击位置扩散圆形波纹 + * - 自适应大小 - 根据元素尺寸自动调整波纹大小和动画时长 + * - 智能配色 - 自动识别按钮类型,使用合适的波纹颜色 + * - 自定义颜色 - 支持通过参数自定义波纹颜色 + * - 性能优化 - 使用 requestAnimationFrame 和自动清理机制 + * + * ## 使用示例 + * + * ```vue + * + * ``` + * + * ## 颜色规则 + * + * - 有色按钮(primary、success、warning 等):使用白色半透明波纹 + * - 默认按钮:使用主题色半透明波纹 + * - 自定义:通过 color 参数指定任意颜色 + * + * @module directives/ripple + * @author Art Design Pro Team + */ + +import type { App, Directive, DirectiveBinding } from 'vue' + +export interface RippleOptions { + /** 水波纹颜色 */ + color?: string +} + +export const vRipple: Directive = { + mounted(el: HTMLElement, binding: DirectiveBinding) { + // 获取指令的配置参数 + const options: RippleOptions = binding.value || {} + + // 设置元素为相对定位,并隐藏溢出部分 + el.style.position = 'relative' + el.style.overflow = 'hidden' + + // 点击事件处理 + el.addEventListener('mousedown', (e: MouseEvent) => { + const rect = el.getBoundingClientRect() + const left = e.clientX - rect.left + const top = e.clientY - rect.top + + // 创建水波纹元素 + const ripple = document.createElement('div') + const diameter = Math.max(el.clientWidth, el.clientHeight) + const radius = diameter / 2 + + // 根据直径计算动画时间(直径越大,动画时间越长) + const baseTime = 600 // 基础动画时间(毫秒) + const scaleFactor = 0.5 // 缩放因子 + const animationDuration = baseTime + diameter * scaleFactor + + // 设置水波纹的尺寸和位置 + ripple.style.width = ripple.style.height = `${diameter}px` + ripple.style.left = `${left - radius}px` + ripple.style.top = `${top - radius}px` + ripple.style.position = 'absolute' + ripple.style.borderRadius = '50%' + ripple.style.pointerEvents = 'none' + + // 判断是否为有色按钮(Element Plus 按钮类型) + const buttonTypes = ['primary', 'info', 'warning', 'danger', 'success'].map( + (type) => `el-button--${type}` + ) + const isColoredButton = buttonTypes.some((type) => el.classList.contains(type)) + const defaultColor = isColoredButton + ? 'rgba(255, 255, 255, 0.25)' // 有色按钮使用白色水波纹 + : 'var(--el-color-primary-light-7)' // 默认按钮使用主题色水波纹 + + // 设置水波纹颜色、初始状态和过渡效果 + ripple.style.backgroundColor = options.color || defaultColor + ripple.style.transform = 'scale(0)' + ripple.style.transition = `transform ${animationDuration}ms cubic-bezier(0.3, 0, 0.2, 1), opacity ${animationDuration}ms cubic-bezier(0.3, 0, 0.5, 1)` + ripple.style.zIndex = '1' + + // 添加水波纹元素到DOM中 + el.appendChild(ripple) + + // 触发动画 + requestAnimationFrame(() => { + ripple.style.transform = 'scale(2)' + ripple.style.opacity = '0' + }) + + // 动画结束后移除水波纹元素 + setTimeout(() => { + ripple.remove() + }, animationDuration + 500) // 增加500ms缓冲时间 + }) + } +} + +export function setupRippleDirective(app: App) { + app.directive('ripple', vRipple) +} diff --git a/src/directives/core/auth.ts b/src/directives/core/auth.ts new file mode 100644 index 0000000..b9e85d8 --- /dev/null +++ b/src/directives/core/auth.ts @@ -0,0 +1,68 @@ +/** + * v-auth 权限指令 + * + * 适用于后端权限控制模式,基于权限标识控制 DOM 元素的显示和隐藏。 + * 如果用户没有对应权限,元素将从 DOM 中移除。 + * + * ## 主要功能 + * + * - 权限验证 - 根据路由 meta 中的权限列表验证用户权限 + * - DOM 控制 - 无权限时自动移除元素,而非隐藏 + * - 响应式更新 - 权限变化时自动更新元素状态 + * + * ## 使用示例 + * + * ```vue + * + * 新增 + * + * + * 编辑 + * + * + * 删除 + * ``` + * + * ## 注意事项 + * + * - 该指令会直接移除 DOM 元素,而不是使用 v-if 隐藏 + * - 权限列表从当前路由的 meta.authList 中获取 + * + * @module directives/auth + * @author Art Design Pro Team + */ + +import { router } from '@/router' +import { App, Directive, DirectiveBinding } from 'vue' + +interface AuthBinding extends DirectiveBinding { + value: string +} + +function checkAuthPermission(el: HTMLElement, binding: AuthBinding): void { + // 获取当前路由的权限列表 + const authList = (router.currentRoute.value.meta.authList as Array<{ authMark: string }>) || [] + + // 检查是否有对应的权限标识 + const hasPermission = authList.some((item) => item.authMark === binding.value) + + // 如果没有权限,移除元素 + if (!hasPermission) { + removeElement(el) + } +} + +function removeElement(el: HTMLElement): void { + if (el.parentNode) { + el.parentNode.removeChild(el) + } +} + +const authDirective: Directive = { + mounted: checkAuthPermission, + updated: checkAuthPermission +} + +export function setupAuthDirective(app: App): void { + app.directive('auth', authDirective) +} diff --git a/src/directives/core/roles.ts b/src/directives/core/roles.ts new file mode 100644 index 0000000..2ab1029 --- /dev/null +++ b/src/directives/core/roles.ts @@ -0,0 +1,89 @@ +/** + * v-roles 角色权限指令 + * + * 基于用户角色控制 DOM 元素的显示和隐藏。 + * 只要用户拥有指定角色中的任意一个,元素就会显示,否则从 DOM 中移除。 + * + * ## 主要功能 + * + * - 角色验证 - 检查用户是否拥有指定角色 + * - 多角色支持 - 支持单个角色或多个角色(满足其一即可) + * - DOM 控制 - 无权限时自动移除元素,而非隐藏 + * - 响应式更新 - 角色变化时自动更新元素状态 + * + * ## 使用示例 + * + * ```vue + * + * ``` + * + * ## 权限逻辑 + * + * - 用户角色从 userStore.getUserInfo.roles 获取 + * - 只要用户拥有指定角色中的任意一个,元素就会显示 + * - 如果用户没有任何角色或不满足条件,元素将被移除 + * + * ## 注意事项 + * + * - 该指令会直接移除 DOM 元素,而不是使用 v-if 隐藏 + * - 适用于基于角色的粗粒度权限控制 + * - 如需基于具体操作的细粒度权限控制,请使用 v-auth 指令 + * + * @module directives/roles + * @author Art Design Pro Team + */ + +import { useUserStore } from '@/store/modules/user' +import { App, Directive, DirectiveBinding } from 'vue' + +interface RolesBinding extends DirectiveBinding { + value: string | string[] +} + +function checkRolePermission(el: HTMLElement, binding: RolesBinding): void { + const userStore = useUserStore() + const userRoles = userStore.getUserInfo.roles + + // 如果用户角色为空或未定义,移除元素 + if (!userRoles?.length) { + removeElement(el) + return + } + + // 确保指令值为数组格式 + const requiredRoles = Array.isArray(binding.value) ? binding.value : [binding.value] + + // 检查用户是否具有所需角色之一 + const hasPermission = requiredRoles.some((role: string) => userRoles.includes(role)) + + // 如果没有权限,安全地移除元素 + if (!hasPermission) { + removeElement(el) + } +} + +function removeElement(el: HTMLElement): void { + if (el.parentNode) { + el.parentNode.removeChild(el) + } +} + +const rolesDirective: Directive = { + mounted: checkRolePermission, + updated: checkRolePermission +} + +export function setupRolesDirective(app: App): void { + app.directive('roles', rolesDirective) +} diff --git a/src/directives/index.ts b/src/directives/index.ts new file mode 100644 index 0000000..780464b --- /dev/null +++ b/src/directives/index.ts @@ -0,0 +1,12 @@ +import type { App } from 'vue' +import { setupAuthDirective } from './core/auth' +import { setupHighlightDirective } from './business/highlight' +import { setupRippleDirective } from './business/ripple' +import { setupRolesDirective } from './core/roles' + +export function setupGlobDirectives(app: App) { + setupAuthDirective(app) // 权限指令 + setupRolesDirective(app) // 角色权限指令 + setupHighlightDirective(app) // 高亮指令 + setupRippleDirective(app) // 水波纹指令 +} diff --git a/src/enums/appEnum.ts b/src/enums/appEnum.ts new file mode 100644 index 0000000..a39c278 --- /dev/null +++ b/src/enums/appEnum.ts @@ -0,0 +1,81 @@ +/** + * 系统级别枚举定义模块 + * + * ## 主要功能 + * + * - 菜单类型枚举(左侧、顶部、混合、双栏) + * - 主题类型枚举(亮色、暗色、自动) + * - 菜单主题枚举(设计、亮色、暗色) + * - 语言类型枚举(中文、英文) + * - 容器宽度枚举(全屏、固定) + * - 菜单宽度枚举(收起宽度) + * + * @module enums/appEnum + * @author Art Design Pro Team + */ + +/** + * 菜单类型 + */ +export enum MenuTypeEnum { + /** 左侧菜单 */ + LEFT = 'left', + /** 顶部菜单 */ + TOP = 'top', + /** 顶部+左侧菜单 */ + TOP_LEFT = 'top-left', + /** 双栏菜单 */ + DUAL_MENU = 'dual-menu' +} + +/** + * 系统主题 + */ +export enum SystemThemeEnum { + /** 暗色主题 */ + DARK = 'dark', + /** 亮色主题 */ + LIGHT = 'light', + /** 自动主题(跟随系统) */ + AUTO = 'auto' +} + +/** + * 菜单主题 + */ +export enum MenuThemeEnum { + /** 暗色主题 */ + DARK = 'dark', + /** 亮色主题 */ + LIGHT = 'light', + /** 设计主题 */ + DESIGN = 'design' +} + +/** + * 菜单宽度 + */ +export enum MenuWidth { + /** 收起宽度 */ + CLOSE = '64px' +} + +/** + * 语言类型 + */ +export enum LanguageEnum { + /** 中文 */ + ZH = 'zh', + /** 英文 */ + EN = 'en' +} + +/** + * 容器宽度 + */ +export enum ContainerWidthEnum { + /** 全屏宽度 */ + FULL = '100%', + /** 固定宽度 */ + BOXED = '1200px' +} diff --git a/src/enums/formEnum.ts b/src/enums/formEnum.ts new file mode 100644 index 0000000..8e9b3b4 --- /dev/null +++ b/src/enums/formEnum.ts @@ -0,0 +1,24 @@ +/** + * 表单相关枚举定义模块 + * + * ## 主要功能 + * + * - 页面模式枚举(新增、编辑) + * - 表格尺寸枚举(默认、紧凑、宽松) + * + * @module enums/formEnum + * @author Art Design Pro Team + */ + +// 页面类型 +export enum PageModeEnum { + Add, // 新增 + Edit // 编辑 +} + +// 表格大小 +export enum TableSizeEnum { + DEFAULT = 'default', + SMALL = 'small', + LARGE = 'large' +} diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 0000000..4401f21 --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1,34 @@ +/// + +declare module 'nprogress' + +declare module 'crypto-js' + +declare module 'vue-img-cutter' + +declare module 'file-saver' + +declare module 'qrcode.vue' { + export type Level = 'L' | 'M' | 'Q' | 'H' + export type RenderAs = 'canvas' | 'svg' + export type GradientType = 'linear' | 'radial' + export interface ImageSettings { + src: string + height: number + width: number + excavate: boolean + } + export interface QRCodeProps { + value: string + size?: number + level?: Level + background?: string + foreground?: string + renderAs?: RenderAs + } + const QrcodeVue: any + export default QrcodeVue +} + +// 全局变量声明 +declare const __APP_VERSION__: string // 版本号 diff --git a/src/hooks/core/useAppMode.ts b/src/hooks/core/useAppMode.ts new file mode 100644 index 0000000..c39cd9e --- /dev/null +++ b/src/hooks/core/useAppMode.ts @@ -0,0 +1,45 @@ +/** + * useAppMode - 应用模式管理 + * + * 提供应用访问模式的判断和管理功能,支持前端和后端两种权限控制模式。 + * 根据环境变量 VITE_ACCESS_MODE 自动识别当前运行模式。 + * + * ## 主要功能 + * + * 1. 模式识别 - 自动识别前端模式或后端模式 + * 2. 前端模式 - 权限由前端路由配置控制,适合小型项目或演示环境 + * 3. 后端模式 - 权限由后端接口返回的菜单数据控制,适合企业级应用 + * 4. 响应式状态 - 提供响应式的模式判断,方便在组件中使用 + * + * @module useAppMode + * @author Art Design Pro Team + */ + +import { computed } from 'vue' + +export function useAppMode() { + // 获取访问模式配置 + const accessMode = import.meta.env.VITE_ACCESS_MODE + + /** + * 是否为前端控制模式 + * 前端模式:权限由前端路由配置控制 + */ + const isFrontendMode = computed(() => accessMode === 'frontend') + /** + * 是否为后端控制模式 + * 后端模式:权限由后端接口返回的菜单数据控制 + */ + const isBackendMode = computed(() => accessMode === 'backend') + + /** + * 当前应用模式 + */ + const currentMode = computed(() => accessMode) + + return { + isFrontendMode, + isBackendMode, + currentMode + } +} diff --git a/src/hooks/core/useAuth.ts b/src/hooks/core/useAuth.ts new file mode 100644 index 0000000..283b859 --- /dev/null +++ b/src/hooks/core/useAuth.ts @@ -0,0 +1,74 @@ +/** + * useAuth - 权限验证管理 + * + * 提供统一的权限验证功能,支持前端和后端两种权限模式。 + * 用于控制页面按钮、操作等功能的显示和访问权限。 + * + * ## 主要功能 + * + * 1. 权限检查 - 检查用户是否拥有指定的权限标识 + * 2. 双模式支持 - 自动适配前端模式和后端模式的权限验证 + * 3. 前端模式 - 从用户信息中获取按钮权限列表(如 ['add', 'edit', 'delete']) + * 4. 后端模式 - 从路由 meta 配置中获取权限列表(如 [{ authMark: 'add' }]) + * + * ## 使用示例 + * + * ```typescript + * const { hasAuth } = useAuth() + * + * // 检查是否有新增权限 + * if (hasAuth('add')) { + * // 显示新增按钮 + * } + * + * // 在模板中使用 + * 编辑 + * 删除 + * ``` + * + * @module useAuth + * @author Art Design Pro Team + */ + +import { useRoute } from 'vue-router' +import { storeToRefs } from 'pinia' +import { useUserStore } from '@/store/modules/user' +import { useAppMode } from '@/hooks/core/useAppMode' +import type { AppRouteRecord } from '@/types/router' + +type AuthItem = NonNullable[number] + +const userStore = useUserStore() + +export const useAuth = () => { + const route = useRoute() + const { isFrontendMode } = useAppMode() + const { info } = storeToRefs(userStore) + + // 前端按钮权限(例如:['add', 'edit']) + const frontendAuthList = info.value?.buttons ?? [] + + // 后端路由 meta 配置的权限列表(例如:[{ authMark: 'add' }]) + const backendAuthList: AuthItem[] = Array.isArray(route.meta.authList) + ? (route.meta.authList as AuthItem[]) + : [] + + /** + * 检查是否拥有某权限标识(前后端模式通用) + * @param auth 权限标识 + * @returns 是否有权限 + */ + const hasAuth = (auth: string): boolean => { + // 前端模式 + if (isFrontendMode.value) { + return frontendAuthList.includes(auth) + } + + // 后端模式 + return backendAuthList.some((item) => item?.authMark === auth) + } + + return { + hasAuth + } +} diff --git a/src/hooks/core/useCeremony.ts b/src/hooks/core/useCeremony.ts new file mode 100644 index 0000000..ead2630 --- /dev/null +++ b/src/hooks/core/useCeremony.ts @@ -0,0 +1,184 @@ +/** + * useCeremony - 节日庆祝管理 + * + * 提供节日烟花效果和祝福文本展示功能,为系统增添节日氛围。 + * 自动检测当前日期是否为节日,并在首次进入时播放烟花动画和显示祝福语。 + * + * ## 主要功能 + * + * 1. 节日检测 - 自动匹配当前日期与节日配置列表,支持单日和跨日期节日 + * 2. 烟花动画 - 播放节日烟花特效,支持自定义图片和触发次数 + * 3. 祝福文本 - 烟花结束后显示节日祝福文本 + * 4. 状态管理 - 记录烟花播放状态,避免重复播放 + * 5. 清理机制 - 提供清理方法,支持手动停止和重置 + * + * ## 使用示例 + * + * ```typescript + * // 在配置文件中定义节日 + * // 单日节日 + * { + * date: '2024-12-25', + * name: '圣诞节', + * image: christmasImage, + * count: 3 // 可选,不设置则使用默认值 3 次 + * scrollText: 'Merry Christmas!', + * } + * + * // 跨日期节日 + * { + * date: '2025-11-07', + * endDate: '2025-11-10', + * name: 'v3.0 测试阶段', + * image: '', + * count: 5 // 自定义烟花播放次数 + * scrollText: '系统 v3.0 测试阶段正式开启!', + * } + * ``` + * + * @module useCeremony + * @author Art Design Pro Team + */ + +import { useTimeoutFn, useIntervalFn, useDateFormat } from '@vueuse/core' +import { storeToRefs } from 'pinia' +import { computed } from 'vue' +import { useSettingStore } from '@/store/modules/setting' +import { mittBus } from '@/utils/sys' +import { festivalConfigList } from '@/config/modules/festival' + +/** + * 节日庆祝配置常量 + */ +const FESTIVAL_CONFIG = { + /** 初始延迟(毫秒) */ + INITIAL_DELAY: 300, + /** 烟花播放间隔(毫秒) */ + FIREWORK_INTERVAL: 1000, + /** 文本显示延迟(毫秒) */ + TEXT_DELAY: 2000, + /** 默认烟花播放次数 */ + DEFAULT_FIREWORKS_COUNT: 3 +} as const + +/** + * 节日庆祝功能 + * 提供节日烟花效果和祝福文本展示 + */ +export function useCeremony() { + const settingStore = useSettingStore() + const { holidayFireworksLoaded, isShowFireworks } = storeToRefs(settingStore) + + let fireworksInterval: { pause: () => void } | null = null + + /** + * 检查日期是否在节日范围内 + * @param currentDate 当前日期 + * @param festivalDate 节日开始日期 + * @param festivalEndDate 节日结束日期(可选) + */ + const isDateInRange = ( + currentDate: string, + festivalDate: string, + festivalEndDate?: string + ): boolean => { + if (!festivalEndDate) { + // 单日节日 + return currentDate === festivalDate + } + + // 跨日期节日 + const current = new Date(currentDate) + const start = new Date(festivalDate) + const end = new Date(festivalEndDate) + + return current >= start && current <= end + } + + /** + * 获取当前日期对应的节日数据 + */ + const currentFestivalData = computed(() => { + const currentDate = useDateFormat(new Date(), 'YYYY-MM-DD').value + return festivalConfigList.find((item) => isDateInRange(currentDate, item.date, item.endDate)) + }) + + /** + * 更新节日日期到 store + */ + const updateFestivalDate = () => { + settingStore.setFestivalDate(currentFestivalData.value?.date || '') + } + + /** + * 触发烟花效果 + */ + const triggerFirework = () => { + mittBus.emit('triggerFireworks', currentFestivalData.value?.image) + } + + /** + * 完成烟花效果后显示文本 + */ + const showFestivalText = () => { + settingStore.setholidayFireworksLoaded(true) + + useTimeoutFn(() => { + settingStore.setShowFestivalText(true) + updateFestivalDate() + }, FESTIVAL_CONFIG.TEXT_DELAY) + } + + /** + * 启动烟花循环 + */ + const startFireworksLoop = () => { + let playedCount = 0 + // 使用节日配置的播放次数,如果没有则使用默认值 + const count = currentFestivalData.value?.count ?? FESTIVAL_CONFIG.DEFAULT_FIREWORKS_COUNT + + const { pause } = useIntervalFn(() => { + triggerFirework() + playedCount++ + + if (playedCount >= count) { + pause() + showFestivalText() + } + }, FESTIVAL_CONFIG.FIREWORK_INTERVAL) + + fireworksInterval = { pause } + } + + /** + * 开启节日庆祝 + */ + const openFestival = () => { + if (!currentFestivalData.value || !isShowFireworks.value) { + return + } + + const { start } = useTimeoutFn(startFireworksLoop, FESTIVAL_CONFIG.INITIAL_DELAY) + start() + } + + /** + * 清理烟花效果 + */ + const cleanup = () => { + if (fireworksInterval) { + fireworksInterval.pause() + fireworksInterval = null + } + settingStore.setShowFestivalText(false) + updateFestivalDate() + } + + return { + openFestival, + cleanup, + holidayFireworksLoaded, + currentFestivalData, + isShowFireworks + } +} diff --git a/src/hooks/core/useChart.ts b/src/hooks/core/useChart.ts new file mode 100644 index 0000000..29ba1d1 --- /dev/null +++ b/src/hooks/core/useChart.ts @@ -0,0 +1,745 @@ +/** + * useChart - ECharts 图表管理 + * + * 提供完整的 ECharts 图表生命周期管理和配置能力,简化图表开发流程。 + * 自动处理图表初始化、更新、销毁、主题切换、响应式调整等复杂逻辑。 + * + * ## 核心功能 + * + * 1. 图表生命周期管理 - 自动处理初始化、更新、销毁,支持延迟加载和可见性检测 + * 2. 主题自动适配 - 响应系统主题变化,自动更新图表样式和配色 + * 3. 响应式调整 - 监听窗口大小、菜单展开等变化,自动调整图表尺寸 + * 4. 空状态处理 - 优雅的空数据展示,自动显示"暂无数据"提示 + * 5. 样式配置统一 - 提供坐标轴、图例、提示框等统一的样式配置方法 + * 6. 性能优化 - 防抖处理、样式缓存、requestAnimationFrame 优化 + * 7. 高级组件抽象 - useChartComponent 提供更高层次的图表组件封装 + * + * ## 使用示例 + * + * ```typescript + * // 基础用法 + * const { + * chartRef, + * initChart, + * updateChart, + * getAxisLineStyle, + * getTooltipStyle + * } = useChart() + * + * onMounted(() => { + * initChart({ + * xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed'] }, + * yAxis: { type: 'value' }, + * series: [{ data: [120, 200, 150], type: 'bar' }] + * }) + * }) + * + * // 高级用法 - 组件抽象 + * const chart = useChartComponent({ + * props, + * generateOptions: () => ({ + * // ECharts 配置 + * }), + * checkEmpty: () => data.value.length === 0, + * watchSources: [() => props.data] + * }) + * ``` + * + * @module useChart + * @author Art Design Pro Team + */ + +import { echarts, type EChartsOption } from '@/plugins/echarts' +import { storeToRefs } from 'pinia' +import { useSettingStore } from '@/store/modules/setting' +import { getCssVar } from '@/utils/ui' +import type { BaseChartProps, ChartThemeConfig, UseChartOptions } from '@/types/component/chart' + +// 图表主题配置 +export const useChartOps = (): ChartThemeConfig => ({ + /** */ + chartHeight: '16rem', + /** 字体大小 */ + fontSize: 13, + /** 字体颜色 */ + fontColor: '#999', + /** 主题颜色 */ + themeColor: getCssVar('--el-color-primary-light-1'), + /** 颜色组 */ + colors: [ + getCssVar('--el-color-primary-light-1'), + '#4ABEFF', + '#EDF2FF', + '#14DEBA', + '#FFAF20', + '#FA8A6C', + '#FFAF20' + ] +}) + +// 常量定义 +const RESIZE_DELAYS = [50, 100, 200, 350] as const +const MENU_RESIZE_DELAYS = [50, 100, 200] as const +const RESIZE_DEBOUNCE_DELAY = 100 + +export function useChart(options: UseChartOptions = {}) { + const { initOptions, initDelay = 0, threshold = 0.1, autoTheme = true } = options + + const settingStore = useSettingStore() + const { isDark, menuOpen, menuType } = storeToRefs(settingStore) + + const chartRef = ref() + let chart: echarts.ECharts | null = null + let intersectionObserver: IntersectionObserver | null = null + let pendingOptions: EChartsOption | null = null + let resizeTimeoutId: number | null = null + let resizeFrameId: number | null = null + let isDestroyed = false + let emptyStateDiv: HTMLElement | null = null + + // 清理定时器的统一方法 + const clearTimers = () => { + if (resizeTimeoutId) { + clearTimeout(resizeTimeoutId) + resizeTimeoutId = null + } + if (resizeFrameId) { + cancelAnimationFrame(resizeFrameId) + resizeFrameId = null + } + } + + // 使用 requestAnimationFrame 优化 resize 处理 + const requestAnimationResize = () => { + if (resizeFrameId) { + cancelAnimationFrame(resizeFrameId) + } + resizeFrameId = requestAnimationFrame(() => { + handleResize() + resizeFrameId = null + }) + } + + // 防抖的resize处理(用于窗口resize事件) + const debouncedResize = () => { + if (resizeTimeoutId) { + clearTimeout(resizeTimeoutId) + } + resizeTimeoutId = window.setTimeout(() => { + requestAnimationResize() + resizeTimeoutId = null + }, RESIZE_DEBOUNCE_DELAY) + } + + // 多延迟resize处理 - 统一方法 + const multiDelayResize = (delays: readonly number[]) => { + // 立即调用一次,快速响应 + nextTick(requestAnimationResize) + + // 使用延迟时间,确保图表正确适应变化 + delays.forEach((delay) => { + setTimeout(requestAnimationResize, delay) + }) + } + + // 收缩菜单时,重新计算图表大小(仅在图表存在时监听) + let menuOpenStopHandle: (() => void) | null = null + let menuTypeStopHandle: (() => void) | null = null + + const setupMenuWatchers = () => { + menuOpenStopHandle = watch(menuOpen, () => multiDelayResize(RESIZE_DELAYS)) + menuTypeStopHandle = watch(menuType, () => { + nextTick(requestAnimationResize) + setTimeout(() => multiDelayResize(MENU_RESIZE_DELAYS), 0) + }) + } + + const cleanupMenuWatchers = () => { + menuOpenStopHandle?.() + menuTypeStopHandle?.() + menuOpenStopHandle = null + menuTypeStopHandle = null + } + + // 主题变化时重新设置图表选项 + let themeStopHandle: (() => void) | null = null + + const setupThemeWatcher = () => { + if (autoTheme) { + themeStopHandle = watch(isDark, () => { + // 更新空状态样式 + emptyStateManager.updateStyle() + + if (chart && !isDestroyed) { + // 使用 requestAnimationFrame 优化主题更新 + requestAnimationFrame(() => { + if (chart && !isDestroyed) { + const currentOptions = chart.getOption() + if (currentOptions) { + updateChart(currentOptions as EChartsOption) + } + } + }) + } + }) + } + } + + const cleanupThemeWatcher = () => { + themeStopHandle?.() + themeStopHandle = null + } + + // 样式生成器 - 统一的样式配置 + const createLineStyle = (color: string, width = 1, type?: 'solid' | 'dashed') => ({ + color, + width, + ...(type && { type }) + }) + + // 缓存样式配置以减少重复计算 + const styleCache = { + axisLine: null as any, + splitLine: null as any, + axisLabel: null as any, + lastDarkValue: isDark.value + } + + const clearStyleCache = () => { + styleCache.axisLine = null + styleCache.splitLine = null + styleCache.axisLabel = null + styleCache.lastDarkValue = isDark.value + } + + // 坐标轴线样式 + const getAxisLineStyle = (show: boolean = true) => { + if (styleCache.lastDarkValue !== isDark.value) { + clearStyleCache() + } + if (!styleCache.axisLine) { + styleCache.axisLine = { + show, + lineStyle: createLineStyle(isDark.value ? '#444' : '#EDEDED') + } + } + return styleCache.axisLine + } + + // 分割线样式 + const getSplitLineStyle = (show: boolean = true) => { + if (styleCache.lastDarkValue !== isDark.value) { + clearStyleCache() + } + if (!styleCache.splitLine) { + styleCache.splitLine = { + show, + lineStyle: createLineStyle(isDark.value ? '#444' : '#EDEDED', 1, 'dashed') + } + } + return styleCache.splitLine + } + + // 坐标轴标签样式 + const getAxisLabelStyle = (show: boolean = true) => { + if (styleCache.lastDarkValue !== isDark.value) { + clearStyleCache() + } + if (!styleCache.axisLabel) { + const { fontColor, fontSize } = useChartOps() + styleCache.axisLabel = { + show, + color: fontColor, + fontSize + } + } + return styleCache.axisLabel + } + + // 坐标轴刻度样式(静态配置,无需缓存) + const getAxisTickStyle = () => ({ + show: false + }) + + // 获取动画配置 + const getAnimationConfig = (animationDelay: number = 50, animationDuration: number = 1500) => ({ + animationDelay: (idx: number) => idx * animationDelay + 200, + animationDuration: (idx: number) => animationDuration - idx * 50, + animationEasing: 'quarticOut' as const + }) + + // 获取统一的 tooltip 配置 + const getTooltipStyle = (trigger: 'item' | 'axis' = 'axis', customOptions: any = {}) => ({ + trigger, + backgroundColor: isDark.value ? 'rgba(0, 0, 0, 0.8)' : 'rgba(255, 255, 255, 0.9)', + borderColor: isDark.value ? '#333' : '#ddd', + borderWidth: 1, + textStyle: { + color: isDark.value ? '#fff' : '#333' + }, + ...customOptions + }) + + // 获取统一的图例配置 + const getLegendStyle = ( + position: 'bottom' | 'top' | 'left' | 'right' = 'bottom', + customOptions: any = {} + ) => { + const baseConfig = { + textStyle: { + color: isDark.value ? '#fff' : '#333' + }, + itemWidth: 12, + itemHeight: 12, + itemGap: 20, + ...customOptions + } + + // 根据位置设置不同的配置 + switch (position) { + case 'bottom': + return { + ...baseConfig, + bottom: 0, + left: 'center', + orient: 'horizontal', + icon: 'roundRect' + } + case 'top': + return { + ...baseConfig, + top: 0, + left: 'center', + orient: 'horizontal', + icon: 'roundRect' + } + case 'left': + return { + ...baseConfig, + left: 0, + top: 'center', + orient: 'vertical', + icon: 'roundRect' + } + case 'right': + return { + ...baseConfig, + right: 0, + top: 'center', + orient: 'vertical', + icon: 'roundRect' + } + default: + return baseConfig + } + } + + // 根据图例位置计算 grid 配置 + const getGridWithLegend = ( + showLegend: boolean, + legendPosition: 'bottom' | 'top' | 'left' | 'right' = 'bottom', + baseGrid: any = {} + ) => { + const defaultGrid = { + top: 15, + right: 15, + bottom: 8, + left: 0, + containLabel: true, + ...baseGrid + } + + if (!showLegend) { + return defaultGrid + } + + // 根据图例位置调整 grid + switch (legendPosition) { + case 'bottom': + return { + ...defaultGrid, + bottom: 40 + } + case 'top': + return { + ...defaultGrid, + top: 40 + } + case 'left': + return { + ...defaultGrid, + left: 120 + } + case 'right': + return { + ...defaultGrid, + right: 120 + } + default: + return defaultGrid + } + } + + // 创建IntersectionObserver + const createIntersectionObserver = () => { + if (intersectionObserver || !chartRef.value) return + + intersectionObserver = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting && pendingOptions && !isDestroyed) { + // 使用 requestAnimationFrame 确保在下一帧初始化图表 + requestAnimationFrame(() => { + if (!isDestroyed && pendingOptions) { + try { + // 元素变为可见,初始化图表 + if (!chart) { + chart = echarts.init(entry.target as HTMLElement) + } + + // 触发自定义事件,让组件处理动画逻辑 + const event = new CustomEvent('chartVisible', { + detail: { options: pendingOptions } + }) + entry.target.dispatchEvent(event) + + pendingOptions = null + cleanupIntersectionObserver() + } catch (error) { + console.error('图表初始化失败:', error) + } + } + }) + } + }) + }, + { threshold } + ) + + intersectionObserver.observe(chartRef.value) + } + + // 清理IntersectionObserver + const cleanupIntersectionObserver = () => { + if (intersectionObserver) { + intersectionObserver.disconnect() + intersectionObserver = null + } + } + + // 检查容器是否可见 + const isContainerVisible = (element: HTMLElement): boolean => { + const rect = element.getBoundingClientRect() + return rect.width > 0 && rect.height > 0 && rect.top < window.innerHeight && rect.bottom > 0 + } + + // 图表初始化核心逻辑 + const performChartInit = (options: EChartsOption) => { + if (!chart && chartRef.value && !isDestroyed) { + chart = echarts.init(chartRef.value) + // 图表创建后立即设置监听器 + setupMenuWatchers() + setupThemeWatcher() + } + if (chart && !isDestroyed) { + chart.setOption(options) + pendingOptions = null + } + } + + // 空状态管理器 + const emptyStateManager = { + create: () => { + if (!chartRef.value || emptyStateDiv) return + + emptyStateDiv = document.createElement('div') + emptyStateDiv.style.cssText = ` + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: 12px; + color: ${isDark.value ? '#555555' : '#B3B2B2'}; + background: transparent; + z-index: 10; + ` + emptyStateDiv.innerHTML = `暂无数据` + + // 确保父容器有相对定位 + if ( + chartRef.value.style.position !== 'relative' && + chartRef.value.style.position !== 'absolute' + ) { + chartRef.value.style.position = 'relative' + } + + chartRef.value.appendChild(emptyStateDiv) + }, + + remove: () => { + if (emptyStateDiv && chartRef.value) { + chartRef.value.removeChild(emptyStateDiv) + emptyStateDiv = null + } + }, + + updateStyle: () => { + if (emptyStateDiv) { + emptyStateDiv.style.color = isDark.value ? '#666' : '#999' + } + } + } + + // 初始化图表 + const initChart = (options: EChartsOption = {}, isEmpty: boolean = false) => { + if (!chartRef.value || isDestroyed) return + + const mergedOptions = { ...initOptions, ...options } + + try { + if (isEmpty) { + // 处理空数据情况 - 显示自定义空状态div + if (chart) { + chart.clear() + } + emptyStateManager.create() + return + } else { + // 有数据时移除空状态div + emptyStateManager.remove() + } + + if (isContainerVisible(chartRef.value)) { + // 容器可见,正常初始化 + if (initDelay > 0) { + setTimeout(() => performChartInit(mergedOptions), initDelay) + } else { + performChartInit(mergedOptions) + } + } else { + // 容器不可见,保存选项并设置监听器 + pendingOptions = mergedOptions + createIntersectionObserver() + } + } catch (error) { + console.error('图表初始化失败:', error) + } + } + + // 更新图表 + const updateChart = (options: EChartsOption) => { + if (isDestroyed) return + + try { + if (!chart) { + // 如果图表不存在,先初始化 + initChart(options) + return + } + chart.setOption(options) + } catch (error) { + console.error('图表更新失败:', error) + } + } + + // 处理窗口大小变化 + const handleResize = () => { + if (chart && !isDestroyed) { + try { + chart.resize() + } catch (error) { + console.error('图表resize失败:', error) + } + } + } + + // 销毁图表 + const destroyChart = () => { + isDestroyed = true + + if (chart) { + try { + chart.dispose() + } catch (error) { + console.error('图表销毁失败:', error) + } finally { + chart = null + } + } + + // 清理所有监听器和资源 + cleanupMenuWatchers() + cleanupThemeWatcher() + emptyStateManager.remove() + cleanupIntersectionObserver() + clearTimers() + clearStyleCache() + pendingOptions = null + } + + // 获取图表实例 + const getChartInstance = () => chart + + // 获取图表是否已初始化 + const isChartInitialized = () => chart !== null + + onMounted(() => { + window.addEventListener('resize', debouncedResize) + }) + + onBeforeUnmount(() => { + window.removeEventListener('resize', debouncedResize) + }) + + onUnmounted(() => { + destroyChart() + }) + + return { + isDark, + chartRef, + initChart, + updateChart, + handleResize, + destroyChart, + getChartInstance, + isChartInitialized, + emptyStateManager, + getAxisLineStyle, + getSplitLineStyle, + getAxisLabelStyle, + getAxisTickStyle, + getAnimationConfig, + getTooltipStyle, + getLegendStyle, + useChartOps, + getGridWithLegend + } +} + +// 高级图表组件抽象 +interface UseChartComponentOptions { + /** Props响应式对象 */ + props: T + /** 图表配置生成函数 */ + generateOptions: () => EChartsOption + /** 空数据检查函数 */ + checkEmpty?: () => boolean + /** 自定义监听的响应式数据 */ + watchSources?: (() => any)[] + /** 自定义可视事件处理 */ + onVisible?: () => void + /** useChart选项 */ + chartOptions?: UseChartOptions +} + +export function useChartComponent(options: UseChartComponentOptions) { + const { + props, + generateOptions, + checkEmpty, + watchSources = [], + onVisible, + chartOptions = {} + } = options + + const chart = useChart(chartOptions) + const { chartRef, initChart, isDark, emptyStateManager } = chart + + // 检查是否为空数据 + const isEmpty = computed(() => { + if (props.isEmpty) return true + if (checkEmpty) return checkEmpty() + return false + }) + + // 更新图表 + const updateChart = () => { + nextTick(() => { + if (isEmpty.value) { + // 处理空数据情况 - 显示自定义空状态div + if (chart.getChartInstance()) { + chart.getChartInstance()?.clear() + } + emptyStateManager.create() + } else { + // 有数据时移除空状态div并初始化图表 + emptyStateManager.remove() + initChart(generateOptions()) + } + }) + } + + // 处理图表进入可视区域时的逻辑 + const handleChartVisible = () => { + if (onVisible) { + onVisible() + } else { + updateChart() + } + } + + // 存储监听器停止函数 + const stopHandles: (() => void)[] = [] + + // 设置数据监听 + const setupWatchers = () => { + // 监听自定义数据源 + if (watchSources.length > 0) { + const stopHandle = watch(watchSources, updateChart, { deep: true }) + stopHandles.push(stopHandle) + } + + // 监听主题变化 + const themeStopHandle = watch(isDark, () => { + emptyStateManager.updateStyle() + updateChart() + }) + stopHandles.push(themeStopHandle) + } + + // 清理所有监听器 + const cleanupWatchers = () => { + stopHandles.forEach((stop) => stop()) + stopHandles.length = 0 + } + + // 设置生命周期 + const setupLifecycle = () => { + onMounted(() => { + updateChart() + + // 监听图表可见事件 + if (chartRef.value) { + chartRef.value.addEventListener('chartVisible', handleChartVisible) + } + }) + + onBeforeUnmount(() => { + // 清理事件监听器 + if (chartRef.value) { + chartRef.value.removeEventListener('chartVisible', handleChartVisible) + } + // 清理所有监听器 + cleanupWatchers() + // 清理空状态div + emptyStateManager.remove() + }) + } + + // 初始化 + setupWatchers() + setupLifecycle() + + return { + ...chart, + isEmpty, + updateChart, + handleChartVisible + } +} diff --git a/src/hooks/core/useCommon.ts b/src/hooks/core/useCommon.ts new file mode 100644 index 0000000..c936854 --- /dev/null +++ b/src/hooks/core/useCommon.ts @@ -0,0 +1,87 @@ +/** + * useCommon - 通用功能集合 + * + * 提供常用的页面操作功能,包括页面刷新、滚动控制、路径获取等。 + * 这些功能在多个页面和组件中都会用到,统一封装便于复用。 + * + * ## 主要功能 + * + * 1. 首页路径 - 获取系统配置的首页路径 + * 2. 页面刷新 - 刷新当前页面内容 + * 3. 滚动控制 - 提供多种滚动到顶部和指定位置的方法 + * 4. 平滑滚动 - 支持平滑滚动动画效果 + * + * @module useCommon + * @author Art Design Pro Team + */ + +import { computed } from 'vue' +import { useMenuStore } from '@/store/modules/menu' +import { useSettingStore } from '@/store/modules/setting' + +export function useCommon() { + const menuStore = useMenuStore() + const settingStore = useSettingStore() + + /** + * 首页路径 + * 从菜单 store 中获取配置的首页路径 + */ + const homePath = computed(() => menuStore.getHomePath()) + + /** + * 刷新当前页面 + * 通过切换 setting store 中的 refresh 状态触发页面重新渲染 + */ + const refresh = () => { + settingStore.reload() + } + + /** + * 滚动到页面顶部 + * 查找主内容区域并将其滚动位置重置为顶部 + */ + const scrollToTop = () => { + const scrollContainer = document.getElementById('app-main') + if (scrollContainer) { + scrollContainer.scrollTop = 0 + } + } + + /** + * 平滑滚动到页面顶部 + * 使用 smooth 行为实现平滑滚动效果 + */ + const smoothScrollToTop = () => { + const scrollContainer = document.getElementById('app-main') + if (scrollContainer) { + scrollContainer.scrollTo({ + top: 0, + behavior: 'smooth' + }) + } + } + + /** + * 滚动到指定位置 + * @param top 目标滚动位置(像素) + * @param smooth 是否使用平滑滚动 + */ + const scrollTo = (top: number, smooth: boolean = false) => { + const scrollContainer = document.getElementById('app-main') + if (scrollContainer) { + scrollContainer.scrollTo({ + top, + behavior: smooth ? 'smooth' : 'auto' + }) + } + } + + return { + homePath, + refresh, + scrollTo, + scrollToTop, + smoothScrollToTop + } +} diff --git a/src/hooks/core/useFastEnter.ts b/src/hooks/core/useFastEnter.ts new file mode 100644 index 0000000..555eb65 --- /dev/null +++ b/src/hooks/core/useFastEnter.ts @@ -0,0 +1,55 @@ +/** + * useFastEnter - 快速入口管理 + * + * 管理顶部栏的快速入口功能,提供应用列表和快速链接的配置和过滤。 + * 支持动态启用/禁用、自定义排序、响应式宽度控制等功能。 + * + * ## 主要功能 + * + * 1. 应用列表管理 - 获取启用的应用列表,自动按排序权重排序 + * 2. 快速链接管理 - 获取启用的快速链接,支持自定义排序 + * 3. 响应式配置 - 所有配置自动响应变化,无需手动更新 + * 4. 宽度控制 - 提供最小显示宽度配置,支持响应式布局 + * + * @module useFastEnter + * @author Art Design Pro Team + */ + +import { computed } from 'vue' +import appConfig from '@/config' +import type { FastEnterApplication, FastEnterQuickLink } from '@/types/config' + +export function useFastEnter() { + // 获取快速入口配置 + const fastEnterConfig = computed(() => appConfig.fastEnter) + + // 获取启用的应用列表(按排序权重排序) + const enabledApplications = computed(() => { + if (!fastEnterConfig.value?.applications) return [] + + return fastEnterConfig.value.applications + .filter((app) => app.enabled !== false) + .sort((a, b) => (a.order || 0) - (b.order || 0)) + }) + + // 获取启用的快速链接(按排序权重排序) + const enabledQuickLinks = computed(() => { + if (!fastEnterConfig.value?.quickLinks) return [] + + return fastEnterConfig.value.quickLinks + .filter((link) => link.enabled !== false) + .sort((a, b) => (a.order || 0) - (b.order || 0)) + }) + + // 获取最小显示宽度 + const minWidth = computed(() => { + return fastEnterConfig.value?.minWidth || 1200 + }) + + return { + fastEnterConfig, + enabledApplications, + enabledQuickLinks, + minWidth + } +} diff --git a/src/hooks/core/useHeaderBar.ts b/src/hooks/core/useHeaderBar.ts new file mode 100644 index 0000000..be10712 --- /dev/null +++ b/src/hooks/core/useHeaderBar.ts @@ -0,0 +1,201 @@ +/** + * useHeaderBar - 顶部栏功能管理 + * + * 统一管理顶部栏各个功能模块的显示状态和配置信息。 + * 提供灵活的功能开关控制,支持动态显示/隐藏顶部栏的各个功能按钮。 + * + * ## 主要功能 + * + * 1. 功能开关控制 - 统一管理菜单按钮、刷新按钮、快速入口等功能的显示状态 + * 2. 配置信息获取 - 获取各个功能模块的详细配置信息 + * 3. 功能列表查询 - 快速获取所有启用或禁用的功能列表 + * 4. 响应式状态 - 所有状态自动响应配置和 store 变化 + * + * @module useHeaderBar + * @author Art Design Pro Team + */ + +import { computed } from 'vue' +import { storeToRefs } from 'pinia' +import { useSettingStore } from '@/store/modules/setting' +import { headerBarConfig } from '@/config/modules/headerBar' +import { HeaderBarFeatureConfig } from '@/types' + +/** + * 顶部栏功能管理 + * @returns 顶部栏功能相关的状态和方法 + */ +export function useHeaderBar() { + const settingStore = useSettingStore() + + // 获取顶部栏配置 + const headerBarConfigRef = computed(() => headerBarConfig) + + // 从store中获取相关状态 + const { showMenuButton, showFastEnter, showRefreshButton, showCrumbs, showLanguage } = + storeToRefs(settingStore) + + /** + * 检查特定功能是否启用 + * @param feature 功能名称 + * @returns 是否启用 + */ + const isFeatureEnabled = (feature: keyof HeaderBarFeatureConfig): boolean => { + return headerBarConfigRef.value[feature]?.enabled ?? false + } + + /** + * 获取功能配置信息 + * @param feature 功能名称 + * @returns 功能配置信息 + */ + const getFeatureConfig = (feature: keyof HeaderBarFeatureConfig) => { + return headerBarConfigRef.value[feature] + } + + // 检查菜单按钮是否显示 + const shouldShowMenuButton = computed(() => { + return isFeatureEnabled('menuButton') && showMenuButton.value + }) + + // 检查刷新按钮是否显示 + const shouldShowRefreshButton = computed(() => { + return isFeatureEnabled('refreshButton') && showRefreshButton.value + }) + + // 检查快速入口是否显示 + const shouldShowFastEnter = computed(() => { + return isFeatureEnabled('fastEnter') && showFastEnter.value + }) + + // 检查面包屑是否显示 + const shouldShowBreadcrumb = computed(() => { + return isFeatureEnabled('breadcrumb') && showCrumbs.value + }) + + // 检查全局搜索是否显示 + const shouldShowGlobalSearch = computed(() => { + return isFeatureEnabled('globalSearch') + }) + + // 检查全屏按钮是否显示 + const shouldShowFullscreen = computed(() => { + return isFeatureEnabled('fullscreen') + }) + + // 检查通知中心是否显示 + const shouldShowNotification = computed(() => { + return isFeatureEnabled('notification') + }) + + // 检查聊天功能是否显示 + const shouldShowChat = computed(() => { + return isFeatureEnabled('chat') + }) + + // 检查语言切换是否显示 + const shouldShowLanguage = computed(() => { + return isFeatureEnabled('language') && showLanguage.value + }) + + // 检查设置面板是否显示 + const shouldShowSettings = computed(() => { + return isFeatureEnabled('settings') + }) + + // 检查主题切换是否显示 + const shouldShowThemeToggle = computed(() => { + return isFeatureEnabled('themeToggle') + }) + + // 获取快速入口的最小宽度 + const fastEnterMinWidth = computed(() => { + const config = getFeatureConfig('fastEnter') + return (config as any)?.minWidth || 1200 + }) + + /** + * 检查功能是否启用(别名) + * @param feature 功能名称 + * @returns 是否启用 + */ + const isFeatureActive = (feature: keyof HeaderBarFeatureConfig): boolean => { + return isFeatureEnabled(feature) + } + + /** + * 获取功能配置(别名) + * @param feature 功能名称 + * @returns 功能配置 + */ + const getFeatureInfo = (feature: keyof HeaderBarFeatureConfig) => { + return getFeatureConfig(feature) + } + + /** + * 获取所有启用的功能列表 + * @returns 启用的功能名称数组 + */ + const getEnabledFeatures = (): (keyof HeaderBarFeatureConfig)[] => { + return Object.keys(headerBarConfigRef.value).filter( + (key) => headerBarConfigRef.value[key as keyof HeaderBarFeatureConfig]?.enabled + ) as (keyof HeaderBarFeatureConfig)[] + } + + /** + * 获取所有禁用的功能列表 + * @returns 禁用的功能名称数组 + */ + const getDisabledFeatures = (): (keyof HeaderBarFeatureConfig)[] => { + return Object.keys(headerBarConfigRef.value).filter( + (key) => !headerBarConfigRef.value[key as keyof HeaderBarFeatureConfig]?.enabled + ) as (keyof HeaderBarFeatureConfig)[] + } + + /** + * 获取所有启用的功能(别名) + * @returns 启用的功能列表 + */ + const getActiveFeatures = () => { + return getEnabledFeatures() + } + + /** + * 获取所有禁用的功能(别名) + * @returns 禁用的功能列表 + */ + const getInactiveFeatures = () => { + return getDisabledFeatures() + } + + return { + // 配置 + headerBarConfig: headerBarConfigRef, + + // 显示状态计算属性 + shouldShowMenuButton, // 是否显示菜单按钮 + shouldShowRefreshButton, // 是否显示刷新按钮 + shouldShowFastEnter, // 是否显示快速入口 + shouldShowBreadcrumb, // 是否显示面包屑 + shouldShowGlobalSearch, // 是否显示全局搜索 + shouldShowFullscreen, // 是否显示全屏按钮 + shouldShowNotification, // 是否显示通知中心 + shouldShowChat, // 是否显示聊天功能 + shouldShowLanguage, // 是否显示语言切换 + shouldShowSettings, // 是否显示设置面板 + shouldShowThemeToggle, // 是否显示主题切换 + + // 配置相关 + fastEnterMinWidth, // 快速入口最小宽度 + + // 方法 + isFeatureEnabled, // 检查功能是否启用 + isFeatureActive, // 检查功能是否启用(别名) + getFeatureConfig, // 获取功能配置 + getFeatureInfo, // 获取功能配置(别名) + getEnabledFeatures, // 获取所有启用的功能 + getDisabledFeatures, // 获取所有禁用的功能 + getActiveFeatures, // 获取所有启用的功能(别名) + getInactiveFeatures // 获取所有禁用的功能(别名) + } +} diff --git a/src/hooks/core/useLayoutHeight.ts b/src/hooks/core/useLayoutHeight.ts new file mode 100644 index 0000000..4b1171a --- /dev/null +++ b/src/hooks/core/useLayoutHeight.ts @@ -0,0 +1,148 @@ +/** + * useLayoutHeight - 页面布局高度管理 + * + * 自动计算和管理页面内容区域的高度,确保内容区域能够正确填充剩余空间。 + * 监听头部元素高度变化,动态调整内容区域高度,避免出现滚动条或布局错乱。 + * + * ## 主要功能 + * + * 1. 动态高度计算 - 根据头部元素高度自动计算内容区域高度 + * 2. 响应式监听 - 自动监听元素尺寸变化并更新高度 + * 3. CSS 变量同步 - 自动更新 CSS 变量,方便全局使用 + * 4. 灵活配置 - 支持自定义间距、CSS 变量名等 + * 5. 自动查找模式 - 提供通过 ID 自动查找元素的便捷方式 + * + * @module useLayoutHeight + * @author Art Design Pro Team + */ + +import { ref, computed, watch, onMounted } from 'vue' +import { useElementSize } from '@vueuse/core' + +/** + * 页面容器高度配置 + */ +interface LayoutHeightOptions { + /** 额外的间距(默认 15px) */ + extraSpacing?: number + /** 是否自动更新 CSS 变量(默认 true) */ + updateCssVar?: boolean + /** CSS 变量名称(默认 '--art-full-height') */ + cssVarName?: string +} + +export function useLayoutHeight(options: LayoutHeightOptions = {}) { + const { extraSpacing = 15, updateCssVar = true, cssVarName = '--art-full-height' } = options + + // 元素引用 + const headerRef = ref() + const contentHeaderRef = ref() + + // 使用 VueUse 自动监听元素尺寸变化 + const { height: headerHeight } = useElementSize(headerRef) + const { height: contentHeaderHeight } = useElementSize(contentHeaderRef) + + // 计算容器最小高度(响应式) + const containerMinHeight = computed(() => { + const totalHeight = headerHeight.value + contentHeaderHeight.value + extraSpacing + return `calc(100vh - ${totalHeight}px)` + }) + + if (updateCssVar) { + watch( + containerMinHeight, + (newHeight) => { + requestAnimationFrame(() => { + document.documentElement.style.setProperty(cssVarName, newHeight) + }) + }, + { immediate: true } + ) + } + + return { + /** 容器最小高度(响应式) */ + containerMinHeight, + /** 头部元素引用 */ + headerRef, + /** 内容头部元素引用 */ + contentHeaderRef, + /** 头部高度(响应式) */ + headerHeight, + /** 内容头部高度(响应式) */ + contentHeaderHeight + } +} + +/** + * 通过 ID 自动查找元素的布局高度管理 + * 适用于无法直接获取元素引用的场景 + * + * @param headerIds 头部元素的 ID 数组 + * @param options 配置选项 + * + * ``` + */ +export function useAutoLayoutHeight( + headerIds: string[] = ['app-header', 'app-content-header'], + options: LayoutHeightOptions = {} +) { + const { extraSpacing = 15, updateCssVar = true, cssVarName = '--art-full-height' } = options + + // 创建元素引用 + const headerRef = ref() + const contentHeaderRef = ref() + + // 使用 VueUse 自动监听元素尺寸变化 + const { height: headerHeight } = useElementSize(headerRef) + const { height: contentHeaderHeight } = useElementSize(contentHeaderRef) + + // 计算容器最小高度(响应式) + const containerMinHeight = computed(() => { + const totalHeight = headerHeight.value + contentHeaderHeight.value + extraSpacing + return `calc(100vh - ${totalHeight}px)` + }) + + if (updateCssVar) { + watch( + containerMinHeight, + (newHeight) => { + requestAnimationFrame(() => { + document.documentElement.style.setProperty(cssVarName, newHeight) + }) + }, + { immediate: true } + ) + } + + // 在 DOM 挂载后查找元素 + onMounted(() => { + if (typeof document !== 'undefined') { + // 使用 nextTick 确保 DOM 完全渲染 + requestAnimationFrame(() => { + const header = document.getElementById(headerIds[0]) + const contentHeader = document.getElementById(headerIds[1]) + + if (header) { + headerRef.value = header + } + if (contentHeader) { + contentHeaderRef.value = contentHeader + } + }) + } + }) + + return { + /** 容器最小高度(响应式) */ + containerMinHeight, + /** 头部元素引用 */ + headerRef, + /** 内容头部元素引用 */ + contentHeaderRef, + /** 头部高度(响应式) */ + headerHeight, + /** 内容头部高度(响应式) */ + contentHeaderHeight + } +} diff --git a/src/hooks/core/useTable.ts b/src/hooks/core/useTable.ts new file mode 100644 index 0000000..afe9ebe --- /dev/null +++ b/src/hooks/core/useTable.ts @@ -0,0 +1,736 @@ +/** + * useTable - 企业级表格数据管理方案 + * + * 功能完整的表格数据管理解决方案,专为后台管理系统设计。 + * 封装了表格开发中的所有常见需求,让你专注于业务逻辑。 + * + * ## 主要功能 + * + * 1. 数据管理 - 自动处理 API 请求、响应转换、加载状态和错误处理 + * 2. 分页控制 - 自动同步分页状态、移动端适配、智能页码边界处理 + * 3. 搜索功能 - 防抖搜索优化、参数管理、一键重置、参数过滤 + * 4. 缓存系统 - 智能请求缓存、多种清理策略、自动过期管理、统计信息 + * 5. 刷新策略 - 提供 5 种刷新方法适配不同业务场景(新增/更新/删除/手动/定时) + * 6. 列配置管理 - 动态显示/隐藏列、列排序、配置持久化、批量操作(可选) + * + * @module useTable + * @author Art Design Pro Team + */ + +import { ref, reactive, computed, onMounted, onUnmounted, nextTick, readonly } from 'vue' +import { useWindowSize } from '@vueuse/core' +import { useTableColumns } from './useTableColumns' +import type { ColumnOption } from '@/types/component' +import { + TableCache, + CacheInvalidationStrategy, + type ApiResponse +} from '../../utils/table/tableCache' +import { + type TableError, + defaultResponseAdapter, + extractTableData, + updatePaginationFromResponse, + createSmartDebounce, + createErrorHandler +} from '../../utils/table/tableUtils' +import { tableConfig } from '../../utils/table/tableConfig' + +// 类型推导工具类型 +type InferApiParams = T extends (params: infer P) => any ? P : never +type InferApiResponse = T extends (params: any) => Promise ? R : never +type InferRecordType = T extends Api.Common.PaginatedResponse ? U : never + +// 优化的配置接口 - 支持自动类型推导 +export interface UseTableConfig< + TApiFn extends (params: any) => Promise = (params: any) => Promise, + TRecord = InferRecordType>, + TParams = InferApiParams, + TResponse = InferApiResponse +> { + // 核心配置 + core: { + /** API 请求函数 */ + apiFn: TApiFn + /** 默认请求参数 */ + apiParams?: Partial + /** 排除 apiParams 中的属性 */ + excludeParams?: string[] + /** 是否立即加载数据 */ + immediate?: boolean + /** 列配置工厂函数 */ + columnsFactory?: () => ColumnOption[] + /** 自定义分页字段映射 */ + paginationKey?: { + /** 当前页码字段名,默认为 'current' */ + current?: string + /** 每页条数字段名,默认为 'size' */ + size?: string + } + } + + // 数据处理 + transform?: { + /** 数据转换函数 */ + dataTransformer?: (data: TRecord[]) => TRecord[] + /** 响应数据适配器 */ + responseAdapter?: (response: TResponse) => ApiResponse + } + + // 性能优化 + performance?: { + /** 是否启用缓存 */ + enableCache?: boolean + /** 缓存时间(毫秒) */ + cacheTime?: number + /** 防抖延迟时间(毫秒) */ + debounceTime?: number + /** 最大缓存条数限制 */ + maxCacheSize?: number + } + + // 生命周期钩子 + hooks?: { + /** 数据加载成功回调(仅网络请求成功时触发) */ + onSuccess?: (data: TRecord[], response: ApiResponse) => void + /** 错误处理回调 */ + onError?: (error: TableError) => void + /** 缓存命中回调(从缓存获取数据时触发) */ + onCacheHit?: (data: TRecord[], response: ApiResponse) => void + /** 加载状态变化回调 */ + onLoading?: (loading: boolean) => void + /** 重置表单回调函数 */ + resetFormCallback?: () => void + } + + // 调试配置 + debug?: { + /** 是否启用日志输出 */ + enableLog?: boolean + /** 日志级别 */ + logLevel?: 'info' | 'warn' | 'error' + } +} + +export function useTable Promise>( + config: UseTableConfig +) { + return useTableImpl(config) +} + +/** + * useTable 的核心实现 - 强大的表格数据管理 Hook + * + * 提供完整的表格解决方案,包括: + * - 数据获取与缓存 + * - 分页控制 + * - 搜索功能 + * - 智能刷新策略 + * - 错误处理 + * - 列配置管理 + */ +function useTableImpl Promise>( + config: UseTableConfig +) { + type TRecord = InferRecordType> + type TParams = InferApiParams + const { + core: { + apiFn, + apiParams = {} as Partial, + excludeParams = [], + immediate = true, + columnsFactory, + paginationKey + }, + transform: { dataTransformer, responseAdapter = defaultResponseAdapter } = {}, + performance: { + enableCache = false, + cacheTime = 5 * 60 * 1000, + debounceTime = 300, + maxCacheSize = 50 + } = {}, + hooks: { onSuccess, onError, onCacheHit, resetFormCallback } = {}, + debug: { enableLog = false } = {} + } = config + + // 分页字段名配置:优先使用传入的配置,否则使用全局配置 + const pageKey = paginationKey?.current || tableConfig.paginationKey.current + const sizeKey = paginationKey?.size || tableConfig.paginationKey.size + + // 响应式触发器,用于手动更新缓存统计信息 + const cacheUpdateTrigger = ref(0) + + // 日志工具函数 + const logger = { + log: (message: string, ...args: unknown[]) => { + if (enableLog) { + console.log(`[useTable] ${message}`, ...args) + } + }, + warn: (message: string, ...args: unknown[]) => { + if (enableLog) { + console.warn(`[useTable] ${message}`, ...args) + } + }, + error: (message: string, ...args: unknown[]) => { + if (enableLog) { + console.error(`[useTable] ${message}`, ...args) + } + } + } + + // 缓存实例 + const cache = enableCache ? new TableCache(cacheTime, maxCacheSize, enableLog) : null + + // 加载状态机 + type LoadingState = 'idle' | 'loading' | 'success' | 'error' + const loadingState = ref('idle') + const loading = computed(() => loadingState.value === 'loading') + + // 错误状态 + const error = ref(null) + + // 表格数据 + const data = ref([]) + + // 请求取消控制器 + let abortController: AbortController | null = null + + // 缓存清理定时器 + let cacheCleanupTimer: NodeJS.Timeout | null = null + + // 搜索参数 + const searchParams = reactive( + Object.assign( + { + [pageKey]: 1, + [sizeKey]: 10 + }, + apiParams || {} + ) as TParams + ) + + // 分页配置 + const pagination = reactive({ + current: ((searchParams as Record)[pageKey] as number) || 1, + size: ((searchParams as Record)[sizeKey] as number) || 10, + total: 0 + }) + + // 移动端分页 (响应式) + const { width } = useWindowSize() + const mobilePagination = computed(() => ({ + ...pagination, + small: width.value < 768 + })) + + // 列配置 + const columnConfig = columnsFactory ? useTableColumns(columnsFactory) : null + const columns = columnConfig?.columns + const columnChecks = columnConfig?.columnChecks + + // 是否有数据 + const hasData = computed(() => data.value.length > 0) + + // 缓存统计信息 + const cacheInfo = computed(() => { + // 依赖触发器,确保缓存变化时重新计算 + void cacheUpdateTrigger.value + if (!cache) return { total: 0, size: '0KB', hitRate: '0 avg hits' } + return cache.getStats() + }) + + // 错误处理函数 + const handleError = createErrorHandler(onError, enableLog) + + // 清理缓存,根据不同的业务场景选择性地清理缓存 + const clearCache = (strategy: CacheInvalidationStrategy, context?: string): void => { + if (!cache) return + + let clearedCount = 0 + + switch (strategy) { + case CacheInvalidationStrategy.CLEAR_ALL: + cache.clear() + logger.log(`清空所有缓存 - ${context || ''}`) + break + + case CacheInvalidationStrategy.CLEAR_CURRENT: + clearedCount = cache.clearCurrentSearch(searchParams) + logger.log(`清空当前搜索缓存 ${clearedCount} 条 - ${context || ''}`) + break + + case CacheInvalidationStrategy.CLEAR_PAGINATION: + clearedCount = cache.clearPagination() + logger.log(`清空分页缓存 ${clearedCount} 条 - ${context || ''}`) + break + + case CacheInvalidationStrategy.KEEP_ALL: + default: + logger.log(`保持缓存不变 - ${context || ''}`) + break + } + // 手动触发缓存状态更新 + cacheUpdateTrigger.value++ + } + + // 获取数据的核心方法 + const fetchData = async ( + params?: Partial, + useCache = enableCache + ): Promise> => { + // 取消上一个请求 + if (abortController) { + abortController.abort() + } + + // 创建新的取消控制器 + const currentController = new AbortController() + abortController = currentController + + // 状态机:进入 loading 状态 + loadingState.value = 'loading' + error.value = null + + try { + let requestParams = Object.assign( + {}, + searchParams, + { + [pageKey]: pagination.current, + [sizeKey]: pagination.size + }, + params || {} + ) as TParams + + // 剔除不需要的参数 + if (excludeParams.length > 0) { + const filteredParams = { ...requestParams } + excludeParams.forEach((key) => { + delete (filteredParams as Record)[key] + }) + requestParams = filteredParams as TParams + } + + // 检查缓存 + if (useCache && cache) { + const cachedItem = cache.get(requestParams) + if (cachedItem) { + data.value = cachedItem.data + updatePaginationFromResponse(pagination, cachedItem.response) + + // 修复:避免重复设置相同的值,防止响应式循环更新 + const paramsRecord = searchParams as Record + if (paramsRecord[pageKey] !== pagination.current) { + paramsRecord[pageKey] = pagination.current + } + if (paramsRecord[sizeKey] !== pagination.size) { + paramsRecord[sizeKey] = pagination.size + } + + // 状态机:缓存命中,进入 success 状态 + loadingState.value = 'success' + + // 缓存命中时触发专门的回调,而不是 onSuccess + if (onCacheHit) { + onCacheHit(cachedItem.data, cachedItem.response) + } + + logger.log(`缓存命中`) + return cachedItem.response + } + } + + const response = await apiFn(requestParams) + + // 检查请求是否被取消 + if (currentController.signal.aborted) { + throw new Error('请求已取消') + } + + // 使用响应适配器转换为标准格式 + const standardResponse = responseAdapter(response) + + // 处理响应数据 + let tableData = extractTableData(standardResponse) + + // 应用数据转换函数 + if (dataTransformer) { + tableData = dataTransformer(tableData) + } + + // 更新状态 + data.value = tableData + updatePaginationFromResponse(pagination, standardResponse) + + // 修复:避免重复设置相同的值,防止响应式循环更新 + const paramsRecord = searchParams as Record + if (paramsRecord[pageKey] !== pagination.current) { + paramsRecord[pageKey] = pagination.current + } + if (paramsRecord[sizeKey] !== pagination.size) { + paramsRecord[sizeKey] = pagination.size + } + + // 缓存数据 + if (useCache && cache) { + cache.set(requestParams, tableData, standardResponse) + // 手动触发缓存状态更新 + cacheUpdateTrigger.value++ + logger.log(`数据已缓存`) + } + + // 状态机:请求成功,进入 success 状态 + loadingState.value = 'success' + + // 成功回调 + if (onSuccess) { + onSuccess(tableData, standardResponse) + } + + return standardResponse + } catch (err) { + if (err instanceof Error && err.message === '请求已取消') { + // 请求被取消,回到 idle 状态 + loadingState.value = 'idle' + return { records: [], total: 0, current: 1, size: 10 } + } + + // 状态机:请求失败,进入 error 状态 + loadingState.value = 'error' + data.value = [] + const tableError = handleError(err, '获取表格数据失败') + throw tableError + } finally { + // 只有当前控制器是活跃的才清空 + if (abortController === currentController) { + abortController = null + } + } + } + + // 获取数据 (保持当前页) + const getData = async (params?: Partial): Promise | void> => { + try { + return await fetchData(params) + } catch { + // 错误已在 fetchData 中处理 + return Promise.resolve() + } + } + + // 分页获取数据 (重置到第一页) - 专门用于搜索场景 + const getDataByPage = async (params?: Partial): Promise | void> => { + pagination.current = 1 + ;(searchParams as Record)[pageKey] = 1 + + // 搜索时清空当前搜索条件的缓存,确保获取最新数据 + clearCache(CacheInvalidationStrategy.CLEAR_CURRENT, '搜索数据') + + try { + return await fetchData(params, false) // 搜索时不使用缓存 + } catch { + // 错误已在 fetchData 中处理 + return Promise.resolve() + } + } + + // 智能防抖搜索函数 + const debouncedGetDataByPage = createSmartDebounce(getDataByPage, debounceTime) + + // 重置搜索参数 + const resetSearchParams = async (): Promise => { + // 取消防抖的搜索 + debouncedGetDataByPage.cancel() + + // 保存分页相关的默认值 + const paramsRecord = searchParams as Record + const defaultPagination = { + [pageKey]: 1, + [sizeKey]: (paramsRecord[sizeKey] as number) || 10 + } + + // 清空所有搜索参数 + Object.keys(searchParams).forEach((key) => { + delete paramsRecord[key] + }) + + // 重新设置默认参数 + Object.assign(searchParams, apiParams || {}, defaultPagination) + + // 重置分页 + pagination.current = 1 + pagination.size = defaultPagination[sizeKey] as number + + // 清空错误状态 + error.value = null + + // 清空缓存 + clearCache(CacheInvalidationStrategy.CLEAR_ALL, '重置搜索') + + // 重新获取数据 + await getData() + + // 执行重置回调 + if (resetFormCallback) { + await nextTick() + resetFormCallback() + } + } + + // 防重复调用的标志 + let isCurrentChanging = false + + // 处理分页大小变化 + const handleSizeChange = async (newSize: number): Promise => { + if (newSize <= 0) return + + debouncedGetDataByPage.cancel() + + const paramsRecord = searchParams as Record + pagination.size = newSize + pagination.current = 1 + paramsRecord[sizeKey] = newSize + paramsRecord[pageKey] = 1 + + clearCache(CacheInvalidationStrategy.CLEAR_CURRENT, '分页大小变化') + + await getData() + } + + // 处理当前页变化 + const handleCurrentChange = async (newCurrent: number): Promise => { + if (newCurrent <= 0) return + + // 修复:防止重复调用 + if (isCurrentChanging) { + return + } + + // 修复:如果当前页没有变化,不需要重新请求 + if (pagination.current === newCurrent) { + logger.log('分页页码未变化,跳过请求') + return + } + + try { + isCurrentChanging = true + + // 修复:只更新必要的状态 + const paramsRecord = searchParams as Record + pagination.current = newCurrent + // 只有当 searchParams 的分页字段与新值不同时才更新 + if (paramsRecord[pageKey] !== newCurrent) { + paramsRecord[pageKey] = newCurrent + } + + await getData() + } finally { + isCurrentChanging = false + } + } + + // 针对不同业务场景的刷新方法 + + // 新增后刷新:回到第一页并清空分页缓存(适用于新增数据后) + const refreshCreate = async (): Promise => { + debouncedGetDataByPage.cancel() + pagination.current = 1 + ;(searchParams as Record)[pageKey] = 1 + clearCache(CacheInvalidationStrategy.CLEAR_PAGINATION, '新增数据') + await getData() + } + + // 更新后刷新:保持当前页,仅清空当前搜索缓存(适用于更新数据后) + const refreshUpdate = async (): Promise => { + clearCache(CacheInvalidationStrategy.CLEAR_CURRENT, '编辑数据') + await getData() + } + + // 删除后刷新:智能处理页码,避免空页面(适用于删除数据后) + const refreshRemove = async (): Promise => { + const { current } = pagination + + // 清除缓存并获取最新数据 + clearCache(CacheInvalidationStrategy.CLEAR_CURRENT, '删除数据') + await getData() + + // 如果当前页为空且不是第一页,回到上一页 + if (data.value.length === 0 && current > 1) { + pagination.current = current - 1 + ;(searchParams as Record)[pageKey] = current - 1 + await getData() + } + } + + // 全量刷新:清空所有缓存,重新获取数据(适用于手动刷新按钮) + const refreshData = async (): Promise => { + debouncedGetDataByPage.cancel() + clearCache(CacheInvalidationStrategy.CLEAR_ALL, '手动刷新') + await getData() + } + + // 轻量刷新:仅清空当前搜索条件的缓存,保持分页状态(适用于定时刷新) + const refreshSoft = async (): Promise => { + clearCache(CacheInvalidationStrategy.CLEAR_CURRENT, '软刷新') + await getData() + } + + // 取消当前请求 + const cancelRequest = (): void => { + if (abortController) { + abortController.abort() + } + debouncedGetDataByPage.cancel() + } + + // 清空数据 + const clearData = (): void => { + data.value = [] + error.value = null + clearCache(CacheInvalidationStrategy.CLEAR_ALL, '清空数据') + } + + // 清理已过期的缓存条目,释放内存空间 + const clearExpiredCache = (): number => { + if (!cache) return 0 + const cleanedCount = cache.cleanupExpired() + if (cleanedCount > 0) { + // 手动触发缓存状态更新 + cacheUpdateTrigger.value++ + } + return cleanedCount + } + + // 设置定期清理过期缓存 + if (enableCache && cache) { + cacheCleanupTimer = setInterval(() => { + const cleanedCount = cache.cleanupExpired() + if (cleanedCount > 0) { + logger.log(`自动清理 ${cleanedCount} 条过期缓存`) + // 手动触发缓存状态更新 + cacheUpdateTrigger.value++ + } + }, cacheTime / 2) // 每半个缓存周期清理一次 + } + + // 挂载时自动加载数据 + if (immediate) { + onMounted(async () => { + await getData() + }) + } + + // 组件卸载时彻底清理 + onUnmounted(() => { + cancelRequest() + if (cache) { + cache.clear() + } + if (cacheCleanupTimer) { + clearInterval(cacheCleanupTimer) + } + }) + + // 优化的返回值结构 + return { + // 数据相关 + /** 表格数据 */ + data, + /** 数据加载状态 */ + loading: readonly(loading), + /** 错误状态 */ + error: readonly(error), + /** 数据是否为空 */ + isEmpty: computed(() => data.value.length === 0), + /** 是否有数据 */ + hasData, + + // 分页相关 + /** 分页状态信息 */ + pagination: readonly(pagination), + /** 移动端分页配置 */ + paginationMobile: mobilePagination, + /** 页面大小变化处理 */ + handleSizeChange, + /** 当前页变化处理 */ + handleCurrentChange, + + // 搜索相关 - 统一前缀 + /** 搜索参数 */ + searchParams, + /** 重置搜索参数 */ + resetSearchParams, + + // 数据操作 - 更明确的操作意图 + /** 加载数据 */ + fetchData: getData, + /** 获取数据 */ + getData: getDataByPage, + /** 获取数据(防抖) */ + getDataDebounced: debouncedGetDataByPage, + /** 清空数据 */ + clearData, + + // 刷新策略 + /** 全量刷新:清空所有缓存,重新获取数据(适用于手动刷新按钮) */ + refreshData, + /** 轻量刷新:仅清空当前搜索条件的缓存,保持分页状态(适用于定时刷新) */ + refreshSoft, + /** 新增后刷新:回到第一页并清空分页缓存(适用于新增数据后) */ + refreshCreate, + /** 更新后刷新:保持当前页,仅清空当前搜索缓存(适用于更新数据后) */ + refreshUpdate, + /** 删除后刷新:智能处理页码,避免空页面(适用于删除数据后) */ + refreshRemove, + + // 缓存控制 + /** 缓存统计信息 */ + cacheInfo, + /** 清除缓存,根据不同的业务场景选择性地清理缓存: */ + clearCache, + // 支持4种清理策略 + // clearCache(CacheInvalidationStrategy.CLEAR_ALL, '手动刷新') // 清空所有缓存 + // clearCache(CacheInvalidationStrategy.CLEAR_CURRENT, '搜索数据') // 只清空当前搜索条件的缓存 + // clearCache(CacheInvalidationStrategy.CLEAR_PAGINATION, '新增数据') // 清空分页相关缓存 + // clearCache(CacheInvalidationStrategy.KEEP_ALL, '保持缓存') // 不清理任何缓存 + /** 清理已过期的缓存条目,释放内存空间 */ + clearExpiredCache, + + // 请求控制 + /** 取消当前请求 */ + cancelRequest, + + // 列配置 (如果提供了 columnsFactory) + ...(columnConfig && { + /** 表格列配置 */ + columns, + /** 列显示控制 */ + columnChecks, + /** 新增列 */ + addColumn: columnConfig.addColumn, + /** 删除列 */ + removeColumn: columnConfig.removeColumn, + /** 切换列显示状态 */ + toggleColumn: columnConfig.toggleColumn, + /** 更新列配置 */ + updateColumn: columnConfig.updateColumn, + /** 批量更新列配置 */ + batchUpdateColumns: columnConfig.batchUpdateColumns, + /** 重新排序列 */ + reorderColumns: columnConfig.reorderColumns, + /** 获取指定列配置 */ + getColumnConfig: columnConfig.getColumnConfig, + /** 获取所有列配置 */ + getAllColumns: columnConfig.getAllColumns, + /** 重置所有列配置到默认状态 */ + resetColumns: columnConfig.resetColumns + }) + } +} + +// 重新导出类型和枚举,方便使用 +export { CacheInvalidationStrategy } from '../../utils/table/tableCache' +export type { ApiResponse, CacheItem } from '../../utils/table/tableCache' +export type { BaseRequestParams, TableError } from '../../utils/table/tableUtils' diff --git a/src/hooks/core/useTableColumns.ts b/src/hooks/core/useTableColumns.ts new file mode 100644 index 0000000..84b6e13 --- /dev/null +++ b/src/hooks/core/useTableColumns.ts @@ -0,0 +1,312 @@ +/** + * useTableColumns - 表格列配置管理 + * + * 提供动态的表格列配置管理能力,支持运行时灵活控制列的显示、隐藏、排序等操作。 + * 通常与 useTable 配合使用,为表格提供完整的列管理功能。 + * + * ## 主要功能 + * + * 1. 列显示控制 - 动态显示/隐藏列,支持批量操作 + * 2. 列排序 - 拖拽或编程方式重新排列列顺序 + * 3. 列配置管理 - 新增、删除、更新列配置 + * 4. 特殊列支持 - 自动处理 selection、expand、index 等特殊列 + * 5. 状态持久化 - 保持列的显示状态,支持重置到初始状态 + * + * ## 使用示例 + * + * ```typescript + * const { columns, columnChecks, toggleColumn, reorderColumns } = useTableColumns(() => [ + * { prop: 'name', label: '姓名', visible: true }, + * { prop: 'email', label: '邮箱', visible: true }, + * { prop: 'status', label: '状态', visible: false } + * ]) + * + * // 切换列显示 + * toggleColumn('email', false) + * + * // 重新排序 + * reorderColumns(0, 2) + * ``` + * + * @module useTableColumns + * @author Art Design Pro Team + */ + +import { ref, computed, watch } from 'vue' +import { $t } from '@/locales' +import type { ColumnOption } from '@/types/component' + +/** + * 特殊列类型 + */ +const SPECIAL_COLUMNS: Record = { + selection: { prop: '__selection__', label: $t('table.column.selection') }, + expand: { prop: '__expand__', label: $t('table.column.expand') }, + index: { prop: '__index__', label: $t('table.column.index') } +} + +/** + * 获取列的唯一标识 + */ +export const getColumnKey = (col: ColumnOption) => + SPECIAL_COLUMNS[col.type as keyof typeof SPECIAL_COLUMNS]?.prop ?? (col.prop as string) + +/** + * 获取列的显示状态 + * 优先使用 visible 字段,如果不存在则使用 checked 字段 + */ +export const getColumnVisibility = (col: ColumnOption): boolean => { + // visible 优先级高于 checked + if (col.visible !== undefined) { + return col.visible + } + // 如果 visible 未定义,使用 checked,默认为 true + return col.checked ?? true +} + +/** + * 获取列的检查状态 + */ +export const getColumnChecks = (columns: ColumnOption[]) => + columns.map((col) => { + const special = col.type && SPECIAL_COLUMNS[col.type] + const visibility = getColumnVisibility(col) + + if (special) { + return { ...col, prop: special.prop, label: special.label, checked: true, visible: true } + } + return { ...col, checked: visibility, visible: visibility } + }) + +/** + * 动态列配置接口 + */ +export interface DynamicColumnConfig { + /** + * 新增列(支持单个或批量) + * @param column 列配置或列配置数组 + * @param index 可选的插入位置,默认末尾(批量时为第一个列的位置) + */ + addColumn: (column: ColumnOption | ColumnOption[], index?: number) => void + /** + * 删除列(支持单个或批量) + * @param prop 列的唯一标识或标识数组 + */ + removeColumn: (prop: string | string[]) => void + /** + * 切换列显示状态(支持单个或批量) + * @param prop 列的唯一标识或标识数组 + * @param visible 可选的显示状态,默认取反 + */ + toggleColumn: (prop: string | string[], visible?: boolean) => void + + /** + * 更新列(支持单个或批量) + * @param prop 列的唯一标识或更新配置数组 + * @param updates 列配置更新(当 prop 为字符串时使用) + */ + updateColumn: ( + prop: string | Array<{ prop: string; updates: Partial> }>, + updates?: Partial> + ) => void + /** + * 批量更新列(兼容旧版本,推荐使用 updateColumn 的数组模式) + * @param updates 列更新配置 + * @deprecated 推荐使用 updateColumn 的数组模式 + */ + batchUpdateColumns: (updates: Array<{ prop: string; updates: Partial> }>) => void + /** + * 重新排序列 + * @param fromIndex 源索引 + * @param toIndex 目标索引 + */ + reorderColumns: (fromIndex: number, toIndex: number) => void + /** + * 获取列配置 + * @param prop 列的唯一标识 + * @returns 列配置 + */ + getColumnConfig: (prop: string) => ColumnOption | undefined + /** + * 获取所有列配置 + * @returns 所有列配置 + */ + getAllColumns: () => ColumnOption[] + /** + * 重置所有列 + */ + resetColumns: () => void +} + +export function useTableColumns( + columnsFactory: () => ColumnOption[] +): { + columns: any + columnChecks: any +} & DynamicColumnConfig { + const dynamicColumns = ref[]>(columnsFactory()) + const columnChecks = ref[]>(getColumnChecks(dynamicColumns.value)) + + // 当 dynamicColumns 变动时,重新生成 columnChecks 且保留已存在的显示状态 + watch( + dynamicColumns, + (newCols) => { + const visibilityMap = new Map( + columnChecks.value.map((c) => [getColumnKey(c), getColumnVisibility(c)]) + ) + const newChecks = getColumnChecks(newCols).map((c) => { + const key = getColumnKey(c) + const visibility = visibilityMap.has(key) ? visibilityMap.get(key) : getColumnVisibility(c) + return { + ...c, + checked: visibility, + visible: visibility + } + }) + columnChecks.value = newChecks + }, + { deep: true } + ) + + // 当前显示列(基于 columnChecks 的 checked 或 visible) + const columns = computed(() => { + const colMap = new Map(dynamicColumns.value.map((c) => [getColumnKey(c), c])) + return columnChecks.value + .filter((c) => getColumnVisibility(c)) + .map((c) => colMap.get(getColumnKey(c))) + .filter(Boolean) as ColumnOption[] + }) + + // 支持 updater 返回新数组或直接在传入数组上 mutate + const setDynamicColumns = (updater: (cols: ColumnOption[]) => void | ColumnOption[]) => { + const copy = [...dynamicColumns.value] + const result = updater(copy) + dynamicColumns.value = Array.isArray(result) ? result : copy + } + + return { + columns, + columnChecks, + + /** + * 新增列(支持单个或批量) + */ + addColumn: (column: ColumnOption | ColumnOption[], index?: number) => + setDynamicColumns((cols) => { + const next = [...cols] + const columnsToAdd = Array.isArray(column) ? column : [column] + const insertIndex = + typeof index === 'number' && index >= 0 && index <= next.length ? index : next.length + + // 批量插入 + next.splice(insertIndex, 0, ...columnsToAdd) + return next + }), + + /** + * 删除列(支持单个或批量) + */ + removeColumn: (prop: string | string[]) => + setDynamicColumns((cols) => { + const propsToRemove = Array.isArray(prop) ? prop : [prop] + return cols.filter((c) => !propsToRemove.includes(getColumnKey(c))) + }), + + /** + * 更新列(支持单个或批量) + */ + updateColumn: ( + prop: string | Array<{ prop: string; updates: Partial> }>, + updates?: Partial> + ) => { + // 批量模式:prop 是数组 + if (Array.isArray(prop)) { + setDynamicColumns((cols) => { + const map = new Map(prop.map((u) => [u.prop, u.updates])) + return cols.map((c) => { + const key = getColumnKey(c) + const upd = map.get(key) + return upd ? { ...c, ...upd } : c + }) + }) + } + // 单个模式:prop 是字符串 + else if (updates) { + setDynamicColumns((cols) => + cols.map((c) => (getColumnKey(c) === prop ? { ...c, ...updates } : c)) + ) + } + }, + + /** + * 切换列显示状态(支持单个或批量) + */ + toggleColumn: (prop: string | string[], visible?: boolean) => { + const propsToToggle = Array.isArray(prop) ? prop : [prop] + const next = [...columnChecks.value] + + propsToToggle.forEach((p) => { + const i = next.findIndex((c) => getColumnKey(c) === p) + if (i > -1) { + const currentVisibility = getColumnVisibility(next[i]) + const newVisibility = visible ?? !currentVisibility + // 同时更新 checked 和 visible 以保持兼容性 + next[i] = { ...next[i], checked: newVisibility, visible: newVisibility } + } + }) + + columnChecks.value = next + }, + + /** + * 重置所有列 + */ + resetColumns: () => { + dynamicColumns.value = columnsFactory() + }, + + /** + * 批量更新列(兼容旧版本) + * @deprecated 推荐使用 updateColumn 的数组模式 + */ + batchUpdateColumns: (updates) => + setDynamicColumns((cols) => { + const map = new Map(updates.map((u) => [u.prop, u.updates])) + return cols.map((c) => { + const key = getColumnKey(c) + const upd = map.get(key) + return upd ? { ...c, ...upd } : c + }) + }), + + /** + * 重新排序列 + */ + reorderColumns: (fromIndex: number, toIndex: number) => + setDynamicColumns((cols) => { + if ( + fromIndex < 0 || + fromIndex >= cols.length || + toIndex < 0 || + toIndex >= cols.length || + fromIndex === toIndex + ) { + return cols + } + const next = [...cols] + const [moved] = next.splice(fromIndex, 1) + next.splice(toIndex, 0, moved) + return next + }), + + /** + * 获取列配置 + */ + getColumnConfig: (prop: string) => dynamicColumns.value.find((c) => getColumnKey(c) === prop), + + /** + * 获取所有列配置 + */ + getAllColumns: () => [...dynamicColumns.value] + } +} diff --git a/src/hooks/core/useTableHeight.ts b/src/hooks/core/useTableHeight.ts new file mode 100644 index 0000000..8fdf6da --- /dev/null +++ b/src/hooks/core/useTableHeight.ts @@ -0,0 +1,105 @@ +/** + * useTableHeight - 表格高度自动计算 + * + * 自动计算表格容器的最佳高度,确保表格在不同布局场景下都能正确显示。 + * 根据表格头部、分页器等元素的高度动态调整容器高度,避免出现滚动条或布局错乱。 + * + * ## 主要功能 + * + * 1. 动态高度计算 - 根据表格头部、分页器高度自动计算容器高度 + * 2. 响应式更新 - 配置变化时自动重新计算高度 + * 3. 灵活配置 - 支持自定义各部分高度和间距 + * 4. 智能适配 - 无额外元素时自动使用 100% 高度 + * + * @module useTableHeight + * @author Art Design Pro Team + */ + +import { computed, type Ref } from 'vue' + +/** + * 表格高度计算器配置接口 + */ +interface TableHeightOptions { + /** 是否显示表格头部 */ + showTableHeader: Ref + /** 分页器高度 */ + paginationHeight: Ref + /** 表格头部高度 */ + tableHeaderHeight: Ref + /** 分页器间距 */ + paginationSpacing: Ref +} + +/** + * 表格高度计算器类 + */ +class TableHeightCalculator { + // 常量配置 + private static readonly DEFAULT_TABLE_HEADER_HEIGHT = 44 + private static readonly TABLE_HEADER_SPACING = 12 + + constructor(private options: TableHeightOptions) {} + + /** + * 计算容器高度 + */ + calculate(): { height: string } { + const offset = this.calculateOffset() + return { + height: offset === 0 ? '100%' : `calc(100% - ${offset}px)` + } + } + + /** + * 计算偏移量 + */ + private calculateOffset(): number { + if (!this.options.showTableHeader.value) { + return this.calculatePaginationOffset() + } + + const headerHeight = this.getHeaderHeight() + const paginationOffset = this.calculatePaginationOffset() + + return headerHeight + paginationOffset + TableHeightCalculator.TABLE_HEADER_SPACING + } + + /** + * 获取表格头部高度 + */ + private getHeaderHeight(): number { + return this.options.tableHeaderHeight.value || TableHeightCalculator.DEFAULT_TABLE_HEADER_HEIGHT + } + + /** + * 计算分页器偏移量 + */ + private calculatePaginationOffset(): number { + const { paginationHeight, paginationSpacing } = this.options + return paginationHeight.value === 0 ? 0 : paginationHeight.value + paginationSpacing.value + } +} + +/** + * 表格高度计算 Hook + * + * 提供表格容器高度的自动计算功能,支持: + * - 表格头部高度 + * - 分页器高度 + * - 动态间距计算 + * + * @param options 配置选项 + * @returns 容器高度计算结果 + */ +export function useTableHeight(options: TableHeightOptions) { + const containerHeight = computed(() => { + const calculator = new TableHeightCalculator(options) + return calculator.calculate() + }) + + return { + /** 容器高度样式对象 */ + containerHeight + } +} diff --git a/src/hooks/core/useTheme.ts b/src/hooks/core/useTheme.ts new file mode 100644 index 0000000..187c3e0 --- /dev/null +++ b/src/hooks/core/useTheme.ts @@ -0,0 +1,174 @@ +/** + * useTheme - 系统主题管理 + * + * 提供完整的主题切换和管理功能,支持亮色、暗色和自动模式。 + * 自动处理主题切换时的过渡效果,确保切换流畅无闪烁。 + * + * ## 主要功能 + * + * 1. 主题切换 - 支持亮色、暗色、自动三种主题模式 + * 2. 自动模式 - 根据系统偏好自动切换主题 + * 3. 颜色适配 - 自动调整主题色的明暗变体(9 个层级) + * 4. 过渡优化 - 切换时临时禁用过渡效果,避免闪烁 + * 5. 状态持久化 - 主题设置自动保存到 store + * + * ## 使用示例 + * + * ```typescript + * const { switchThemeStyles } = useTheme() + * + * // 切换到暗色主题 + * switchThemeStyles(SystemThemeEnum.DARK) + * + * // 切换到亮色主题 + * switchThemeStyles(SystemThemeEnum.LIGHT) + * + * // 切换到自动模式(跟随系统) + * switchThemeStyles(SystemThemeEnum.AUTO) + * ``` + * + * @module useTheme + * @author Art Design Pro Team + */ + +import { useSettingStore } from '@/store/modules/setting' +import { SystemThemeEnum } from '@/enums/appEnum' +import AppConfig from '@/config' +import { SystemThemeTypes } from '@/types/store' +import { getDarkColor, getLightColor, setElementThemeColor } from '@/utils/ui' +import { usePreferredDark } from '@vueuse/core' +import { watch } from 'vue' + +export function useTheme() { + const settingStore = useSettingStore() + + // 禁用过渡效果 + const disableTransitions = () => { + const style = document.createElement('style') + style.setAttribute('id', 'disable-transitions') + style.textContent = '* { transition: none !important; }' + document.head.appendChild(style) + } + + // 启用过渡效果 + const enableTransitions = () => { + const style = document.getElementById('disable-transitions') + if (style) { + style.remove() + } + } + + // 设置系统主题 + const setSystemTheme = (theme: SystemThemeEnum, themeMode?: SystemThemeEnum) => { + // 临时禁用过渡效果 + disableTransitions() + + const el = document.getElementsByTagName('html')[0] + const isDark = theme === SystemThemeEnum.DARK + + if (!themeMode) { + themeMode = theme + } + + const currentTheme = AppConfig.systemThemeStyles[theme as keyof SystemThemeTypes] + + if (currentTheme) { + el.setAttribute('class', currentTheme.className) + } + + // 设置按钮颜色加深或变浅 + const primary = settingStore.systemThemeColor + + for (let i = 1; i <= 9; i++) { + document.documentElement.style.setProperty( + `--el-color-primary-light-${i}`, + isDark ? `${getDarkColor(primary, i / 10)}` : `${getLightColor(primary, i / 10)}` + ) + } + + // 更新store中的主题设置 + settingStore.setGlopTheme(theme, themeMode) + + // 使用 requestAnimationFrame 确保在下一帧恢复过渡效果 + requestAnimationFrame(() => { + requestAnimationFrame(() => { + enableTransitions() + }) + }) + } + + // 使用 VueUse 的 usePreferredDark 检测系统主题偏好 + const prefersDark = usePreferredDark() + + // 自动设置系统主题 + const setSystemAutoTheme = () => { + const theme = prefersDark.value ? SystemThemeEnum.DARK : SystemThemeEnum.LIGHT + setSystemTheme(theme, SystemThemeEnum.AUTO) + } + + // 切换主题 + const switchThemeStyles = (theme: SystemThemeEnum) => { + if (theme === SystemThemeEnum.AUTO) { + setSystemAutoTheme() + } else { + setSystemTheme(theme) + } + } + + return { + setSystemTheme, + setSystemAutoTheme, + switchThemeStyles, + prefersDark + } +} + +/** + * 初始化主题系统 + */ +export function initializeTheme() { + const settingStore = useSettingStore() + const prefersDark = usePreferredDark() + + // 根据系统偏好应用主题 + const applyThemeByMode = () => { + const el = document.getElementsByTagName('html')[0] + let actualTheme = settingStore.systemThemeType + + // 如果是 AUTO 模式,检测系统偏好 + if (settingStore.systemThemeMode === SystemThemeEnum.AUTO) { + actualTheme = prefersDark.value ? SystemThemeEnum.DARK : SystemThemeEnum.LIGHT + // 更新实际应用的主题类型 + settingStore.systemThemeType = actualTheme + } + + // 设置主题 class + const currentTheme = AppConfig.systemThemeStyles[actualTheme as keyof SystemThemeTypes] + if (currentTheme) { + el.setAttribute('class', currentTheme.className) + } + + // 设置主题颜色 + setElementThemeColor(settingStore.systemThemeColor) + + // 设置圆角 + document.documentElement.style.setProperty('--custom-radius', `${settingStore.customRadius}rem`) + } + + // 应用主题 + applyThemeByMode() + + // 如果是 AUTO 模式,监听系统主题变化(使用 VueUse 的响应式特性) + if (settingStore.systemThemeMode === SystemThemeEnum.AUTO) { + watch( + prefersDark, + () => { + // 只有在 AUTO 模式下才响应系统主题变化 + if (settingStore.systemThemeMode === SystemThemeEnum.AUTO) { + applyThemeByMode() + } + }, + { immediate: false } + ) + } +} diff --git a/src/hooks/index.ts b/src/hooks/index.ts new file mode 100644 index 0000000..472b09c --- /dev/null +++ b/src/hooks/index.ts @@ -0,0 +1,32 @@ +// 通用功能集合 +export { useCommon } from './core/useCommon' + +// 应用模式 +export { useAppMode } from './core/useAppMode' + +// 权限控制 +export { useAuth } from './core/useAuth' + +// 表格数据管理方案 +export { useTable } from './core/useTable' + +// 表格列配置管理 +export { useTableColumns } from './core/useTableColumns' + +// 主题相关 +export { useTheme } from './core/useTheme' + +// 礼花+文字滚动 +export { useCeremony } from './core/useCeremony' + +// 顶栏快速入口 +export { useFastEnter } from './core/useFastEnter' + +// 顶栏功能管理 +export { useHeaderBar } from './core/useHeaderBar' + +// 图表相关 +export { useChart, useChartComponent, useChartOps } from './core/useChart' + +// 布局高度 +export { useLayoutHeight, useAutoLayoutHeight } from './core/useLayoutHeight' diff --git a/src/locales/index.ts b/src/locales/index.ts new file mode 100644 index 0000000..36c2648 --- /dev/null +++ b/src/locales/index.ts @@ -0,0 +1,123 @@ +/** + * 国际化配置 + * + * 基于 vue-i18n 实现的多语言国际化解决方案。 + * 支持中文和英文切换,自动从本地存储恢复用户的语言偏好。 + * + * ## 主要功能 + * + * - 多语言支持 - 支持中文(简体)和英文两种语言 + * - 语言切换 - 运行时动态切换语言,无需刷新页面 + * - 持久化存储 - 自动保存和恢复用户的语言偏好 + * - 全局注入 - 在任何组件中都可以使用 $t 函数进行翻译 + * - 类型安全 - 提供 TypeScript 类型支持 + * + * ## 支持的语言 + * + * - zh: 简体中文 + * - en: English + * + * @module locales + * @author Art Design Pro Team + */ + +import { createI18n } from 'vue-i18n' +import type { I18n, I18nOptions } from 'vue-i18n' +import { LanguageEnum } from '@/enums/appEnum' +import { getSystemStorage } from '@/utils/storage' +import { StorageKeyManager } from '@/utils/storage/storage-key-manager' + +// 同步导入语言文件 +import enMessages from './langs/en.json' +import zhMessages from './langs/zh.json' + +/** + * 存储键管理器实例 + */ +const storageKeyManager = new StorageKeyManager() + +/** + * 语言消息对象 + */ +const messages = { + [LanguageEnum.EN]: enMessages, + [LanguageEnum.ZH]: zhMessages +} + +/** + * 语言选项列表 + * 用于语言切换下拉框 + */ +export const languageOptions = [ + { value: LanguageEnum.ZH, label: '简体中文' }, + { value: LanguageEnum.EN, label: 'English' } +] + +/** + * 从存储中获取语言设置 + * @returns 语言设置,如果获取失败则返回默认语言 + */ +const getDefaultLanguage = (): LanguageEnum => { + // 尝试从版本化的存储中获取语言设置 + try { + const storageKey = storageKeyManager.getStorageKey('user') + const userStore = localStorage.getItem(storageKey) + + if (userStore) { + const { language } = JSON.parse(userStore) + if (language && Object.values(LanguageEnum).includes(language)) { + return language + } + } + } catch (error) { + console.warn('[i18n] 从版本化存储获取语言设置失败:', error) + } + + // 尝试从系统存储中获取语言设置 + try { + const sys = getSystemStorage() + if (sys) { + const { user } = JSON.parse(sys) + if (user?.language && Object.values(LanguageEnum).includes(user.language)) { + return user.language + } + } + } catch (error) { + console.warn('[i18n] 从系统存储获取语言设置失败:', error) + } + + // 返回默认语言 + console.debug('[i18n] 使用默认语言:', LanguageEnum.ZH) + return LanguageEnum.ZH +} + +/** + * i18n 配置选项 + */ +const i18nOptions: I18nOptions = { + locale: getDefaultLanguage(), + legacy: false, + globalInjection: true, + fallbackLocale: LanguageEnum.ZH, + messages +} + +/** + * i18n 实例 + */ +const i18n: I18n = createI18n(i18nOptions) + +/** + * 翻译函数类型 + */ +interface Translation { + (key: string): string +} + +/** + * 全局翻译函数 + * 可在任何地方使用,无需导入 useI18n + */ +export const $t = i18n.global.t as Translation + +export default i18n diff --git a/src/locales/langs/en.json b/src/locales/langs/en.json new file mode 100644 index 0000000..51e196b --- /dev/null +++ b/src/locales/langs/en.json @@ -0,0 +1,296 @@ +{ + "httpMsg": { + "unauthorized": "Unauthorized access, please login again", + "forbidden": "Access to this resource is forbidden", + "notFound": "The requested resource does not exist", + "methodNotAllowed": "Request method not allowed", + "requestTimeout": "Request timeout, please try again later", + "internalServerError": "Internal server error, please try again later", + "badGateway": "Bad gateway error, please try again later", + "serviceUnavailable": "Service temporarily unavailable, please try again later", + "gatewayTimeout": "Gateway timeout, please try again later", + "requestCancelled": "Request cancelled", + "networkError": "Network connection error, please check your connection", + "requestFailed": "Request failed", + "requestConfigError": "Request configuration error" + }, + "topBar": { + "search": { + "title": "Search" + }, + "user": { + "userCenter": "User center", + "docs": "Document", + "github": "Github", + "lockScreen": "Lock screen", + "logout": "Log out" + }, + "guide": { + "title": "Click here to view", + "theme": "Theme style", + "menu": "Open top menu", + "description": "More configurations" + } + }, + "common": { + "tips": "Prompt", + "cancel": "Cancel", + "confirm": "Confirm", + "logOutTips": "Do you want to log out?" + }, + "search": { + "placeholder": "Search page", + "historyTitle": "Search history", + "switchKeydown": "Navigate", + "selectKeydown": "Select", + "exitKeydown": "Close" + }, + "setting": { + "menuType": { + "title": "Menu Layout", + "list": [ + "Vertical", + "Horizontal", + "Mixed", + "Dual" + ] + }, + "theme": { + "title": "Theme Style", + "list": [ + "Light", + "Dark", + "System" + ] + }, + "menu": { + "title": "Menu Style" + }, + "color": { + "title": "Theme Color" + }, + "box": { + "title": "Box Style", + "list": [ + "Border", + "Shadow" + ] + }, + "container": { + "title": "Container Width", + "list": [ + "Full", + "Boxed" + ] + }, + "basics": { + "title": "Basic Config", + "list": { + "multiTab": "Show work tab", + "accordion": "Sidebar opens accordion", + "collapseSidebar": "Show sidebar button", + "reloadPage": "Show reload page button", + "fastEnter": "Show fast enter", + "breadcrumb": "Show crumb navigation", + "language": "Show multilingual selection", + "progressBar": "Show top progress bar", + "weakMode": "Color Weakness Mode", + "watermark": "Global watermark", + "menuWidth": "Menu width", + "tabStyle": "Tab style", + "pageTransition": "Page animation", + "borderRadius": "Custom radius" + } + }, + "tabStyle": { + "default": "Default", + "card": "Card", + "google": "Chrome" + }, + "transition": { + "list": { + "none": "None", + "fade": "Fade", + "slideLeft": "Slide Left", + "slideBottom": "Slide Bottom", + "slideTop": "Slide Top" + } + }, + "actions": { + "resetConfig": "Reset Config", + "copyConfig": "Copy Config", + "copySuccess": "Configuration copied to clipboard, paste it into src/config/setting.ts file", + "copyFailed": "Copy failed, please try again", + "resetFailed": "Reset failed, please refresh the page and try again" + } + }, + "notice": { + "title": "Notice", + "btnRead": "Mark as read", + "bar": [ + "Notice", + "Message", + "Todo" + ], + "text": [ + "No" + ], + "viewAll": "View all" + }, + "worktab": { + "btn": { + "refresh": "Refresh", + "fixed": "Fixed", + "unfixed": "Unfixed", + "closeLeft": "Close left", + "closeRight": "Close right", + "closeOther": "Close other", + "closeAll": "Close all" + } + }, + "login": { + "leftView": { + "title": "A backend system of beauty and efficiency", + "subTitle": "A sleek and practical interface for a great user experience" + }, + "title": "Welcome back", + "subTitle": "Please enter your account and password to login", + "roles": { + "super": "Super Admin", + "admin": "Admin", + "user": "User" + }, + "placeholder": { + "username": "Please enter your account", + "password": "Please enter your password", + "slider": "Please slide to verify" + }, + "sliderText": "Please slide to verify", + "sliderSuccessText": "Verification successful", + "rememberPwd": "Remember password", + "forgetPwd": "Forgot password", + "btnText": "Login", + "noAccount": "No account yet?", + "register": "Register", + "success": { + "title": "Login successful", + "message": "Welcome back" + } + }, + "forgetPassword": { + "title": "Forgot password?", + "subTitle": "Enter your email to reset your password", + "placeholder": "Please enter your email", + "submitBtnText": "Submit", + "backBtnText": "Back" + }, + "register": { + "title": "Create account", + "subTitle": "Welcome to join us, please fill in the following information to complete the registration", + "placeholder": { + "username": "Please enter your account", + "password": "Please enter your password", + "confirmPassword": "Please enter your password again" + }, + "rule": { + "confirmPasswordRequired": "Please enter your password again", + "passwordMismatch": "The two passwords are inconsistent!", + "usernameLength": "The length is 3 to 20 characters", + "passwordLength": "The password length cannot be less than 6 digits", + "agreementRequired": "Please agree to the privacy policy" + }, + "agreeText": "I agree", + "privacyPolicy": "Privacy policy", + "submitBtnText": "Register", + "hasAccount": "Already have an account?", + "toLogin": "To login" + }, + "lockScreen": { + "pwdError": "Password error", + "lock": { + "inputPlaceholder": "Please input lock screen password", + "btnText": "Lock" + }, + "unlock": { + "inputPlaceholder": "Please input unlock password", + "btnText": "Unlock", + "backBtnText": "Back to login" + } + }, + "greeting": { + "dawn": "Good morning!", + "morning": "Good morning!", + "afternoon": "Good afternoon!", + "evening": "Good evening!" + }, + "exceptionPage": { + "403": "Sorry, you do not have permission to access this page", + "404": "Sorry, the page you are trying to access does not exist", + "500": "Sorry, there was an error on the server", + "gohome": "Go Home" + }, + "menus": { + "login": { + "title": "Login" + }, + "register": { + "title": "Register" + }, + "forgetPassword": { + "title": "Forget Password" + }, + "outside": { + "title": "Outside" + }, + "dashboard": { + "title": "Dashboard", + "console": "Console" + }, + "result": { + "title": "Result Page", + "success": "Success", + "fail": "Fail" + }, + "exception": { + "title": "Exception", + "forbidden": "403", + "notFound": "404", + "serverError": "500" + }, + "system": { + "title": "System Settings", + "user": "User Manage", + "role": "Role Manage", + "userCenter": "User Center", + "menu": "Menu Manage" + } + }, + "table": { + "form": { + "reset": "Reset", + "submit": "Submit" + }, + "searchBar": { + "reset": "Reset", + "search": "Search", + "expand": "Expand", + "collapse": "Collapse", + "searchInputPlaceholder": "Please enter", + "searchSelectPlaceholder": "Please select" + }, + "selection": "Select", + "sizeOptions": { + "small": "Compact", + "default": "Default", + "large": "Loose" + }, + "column": { + "selection": "Select", + "expand": "Expand", + "index": "Index" + }, + "zebra": "Zebra", + "border": "Border", + "headerBackground": "Header BG" + } +} \ No newline at end of file diff --git a/src/locales/langs/zh.json b/src/locales/langs/zh.json new file mode 100644 index 0000000..77a23a5 --- /dev/null +++ b/src/locales/langs/zh.json @@ -0,0 +1,296 @@ +{ + "httpMsg": { + "unauthorized": "未授权访问,请重新登录", + "forbidden": "禁止访问该资源", + "notFound": "请求的资源不存在", + "methodNotAllowed": "请求方法不允许", + "requestTimeout": "请求超时,请稍后重试", + "internalServerError": "服务器内部错误,请稍后重试", + "badGateway": "网关错误,请稍后重试", + "serviceUnavailable": "服务暂时不可用,请稍后重试", + "gatewayTimeout": "网关超时,请稍后重试", + "requestCancelled": "请求已取消", + "networkError": "网络连接异常,请检查网络连接", + "requestFailed": "请求失败", + "requestConfigError": "请求配置错误" + }, + "topBar": { + "search": { + "title": "搜索" + }, + "user": { + "userCenter": "个人中心", + "docs": "使用文档", + "github": "Github", + "lockScreen": "锁定屏幕", + "logout": "退出登录" + }, + "guide": { + "title": "点击这里查看", + "theme": "主题风格", + "menu": "开启顶栏菜单", + "description": "等更多配置" + } + }, + "common": { + "tips": "提示", + "cancel": "取消", + "confirm": "确定", + "logOutTips": "您是否要退出登录?" + }, + "search": { + "placeholder": "搜索页面", + "historyTitle": "搜索历史", + "switchKeydown": "切换", + "selectKeydown": "选择", + "exitKeydown": "关闭" + }, + "setting": { + "menuType": { + "title": "菜单布局", + "list": [ + "垂直", + "水平", + "混合", + "双列" + ] + }, + "theme": { + "title": "主题风格", + "list": [ + "浅色", + "深色", + "系统" + ] + }, + "menu": { + "title": "菜单风格" + }, + "color": { + "title": "系统主题色" + }, + "box": { + "title": "盒子样式", + "list": [ + "边框", + "阴影" + ] + }, + "container": { + "title": "容器宽度", + "list": [ + "铺满", + "定宽" + ] + }, + "basics": { + "title": "基础配置", + "list": { + "multiTab": "开启多标签栏", + "accordion": "侧边栏开启手风琴模式", + "collapseSidebar": "显示折叠侧边栏按钮", + "fastEnter": "显示快速入口", + "reloadPage": "显示重载页面按钮", + "breadcrumb": "显示全局面包屑导航", + "language": "显示多语言选择", + "progressBar": "显示顶部进度条", + "weakMode": "色弱模式", + "watermark": "全局水印", + "menuWidth": "菜单宽度", + "tabStyle": "标签页风格", + "pageTransition": "页面切换动画", + "borderRadius": "自定义圆角" + } + }, + "tabStyle": { + "default": "默认", + "card": "卡片", + "google": "谷歌" + }, + "transition": { + "list": { + "none": "无动画", + "fade": "淡入淡出", + "slideLeft": "左侧滑入", + "slideBottom": "下方滑入", + "slideTop": "上方滑入" + } + }, + "actions": { + "resetConfig": "重置配置", + "copyConfig": "复制配置", + "copySuccess": "配置已复制到剪贴板,可粘贴到 src/config/setting.ts 文件中", + "copyFailed": "复制失败,请重试", + "resetFailed": "重置失败,请刷新页面后重试" + } + }, + "notice": { + "title": "通知", + "btnRead": "标为已读", + "bar": [ + "通知", + "消息", + "代办" + ], + "text": [ + "暂无" + ], + "viewAll": "查看全部" + }, + "worktab": { + "btn": { + "refresh": "刷新", + "fixed": "固定", + "unfixed": "取消固定", + "closeLeft": "关闭左侧", + "closeRight": "关闭右侧", + "closeOther": "关闭其他", + "closeAll": "关闭全部" + } + }, + "login": { + "leftView": { + "title": "一款兼具设计美学与高效开发的后台系统", + "subTitle": "美观实用的界面,经过视觉优化,确保卓越的用户体验" + }, + "title": "欢迎回来", + "subTitle": "输入您的账号和密码登录", + "roles": { + "super": "超级管理员", + "admin": "管理员", + "user": "普通用户" + }, + "placeholder": { + "username": "请输入账号", + "password": "请输入密码", + "slider": "请拖动滑块完成验证" + }, + "sliderText": "按住滑块拖动", + "sliderSuccessText": "验证成功", + "rememberPwd": "记住密码", + "forgetPwd": "忘记密码", + "btnText": "登录", + "noAccount": "还没有账号?", + "register": "注册", + "success": { + "title": "登录成功", + "message": "欢迎回来" + } + }, + "forgetPassword": { + "title": "忘记密码?", + "subTitle": "输入您的电子邮件来重置您的密码", + "placeholder": "请输入您的电子邮件", + "submitBtnText": "提交", + "backBtnText": "返回" + }, + "register": { + "title": "创建账号", + "subTitle": "欢迎加入我们,请填写以下信息完成注册", + "placeholder": { + "username": "请输入账号", + "password": "请输入密码", + "confirmPassword": "请再次输入密码" + }, + "rule": { + "confirmPasswordRequired": "请再次输入密码", + "passwordMismatch": "两次输入密码不一致!", + "usernameLength": "长度在 3 到 20 个字符", + "passwordLength": "密码长度不能小于6位", + "agreementRequired": "请同意隐私协议" + }, + "agreeText": "我同意", + "privacyPolicy": "《隐私政策》", + "submitBtnText": "注册", + "hasAccount": "已有账号?", + "toLogin": "去登录" + }, + "lockScreen": { + "pwdError": "密码错误", + "lock": { + "inputPlaceholder": "请输入锁屏密码", + "btnText": "锁定" + }, + "unlock": { + "inputPlaceholder": "请输入解锁密码", + "btnText": "解锁", + "backBtnText": "返回登录" + } + }, + "greeting": { + "dawn": "凌晨了!", + "morning": "上午好!", + "afternoon": "下午好!", + "evening": "晚上好!" + }, + "exceptionPage": { + "403": "抱歉,您无权访问该页面", + "404": "抱歉,您访问的页面不存在", + "500": "抱歉,服务器出错了", + "gohome": "返回首页" + }, + "menus": { + "login": { + "title": "登录" + }, + "register": { + "title": "注册" + }, + "forgetPassword": { + "title": "忘记密码" + }, + "outside": { + "title": "内嵌页面" + }, + "dashboard": { + "title": "仪表盘", + "console": "工作台" + }, + "result": { + "title": "结果页面", + "success": "成功页", + "fail": "失败页" + }, + "exception": { + "title": "异常页面", + "forbidden": "403", + "notFound": "404", + "serverError": "500" + }, + "system": { + "title": "系统管理", + "user": "用户管理", + "role": "角色管理", + "userCenter": "个人中心", + "menu": "菜单管理" + } + }, + "table": { + "form": { + "reset": "重置", + "submit": "提交" + }, + "searchBar": { + "reset": "重置", + "search": "查询", + "expand": "展开", + "collapse": "收起", + "searchInputPlaceholder": "请输入", + "searchSelectPlaceholder": "请选择" + }, + "selection": "选择", + "sizeOptions": { + "small": "紧凑", + "default": "默认", + "large": "宽松" + }, + "column": { + "selection": "勾选", + "expand": "展开", + "index": "序号" + }, + "zebra": "斑马纹", + "border": "边框", + "headerBackground": "表头背景" + } +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..7df948a --- /dev/null +++ b/src/main.ts @@ -0,0 +1,25 @@ +import App from './App.vue' +import { createApp } from 'vue' +import { initStore } from './store' // Store +import { initRouter } from './router' // Router +import language from './locales' // 国际化 +import '@styles/core/tailwind.css' // tailwind +import '@styles/index.scss' // 样式 +import '@utils/sys/console.ts' // 控制台输出内容 +import { setupGlobDirectives } from './directives' +import { setupErrorHandle } from './utils/sys/error-handle' + +document.addEventListener( + 'touchstart', + function () {}, + { passive: false } +) + +const app = createApp(App) +initStore(app) +initRouter(app) +setupGlobDirectives(app) +setupErrorHandle(app) + +app.use(language) +app.mount('#app') \ No newline at end of file diff --git a/src/mock/temp/formData.ts b/src/mock/temp/formData.ts new file mode 100644 index 0000000..8aa7ae5 --- /dev/null +++ b/src/mock/temp/formData.ts @@ -0,0 +1,273 @@ +import avatar1 from '@/assets/images/avatar/avatar1.webp' +import avatar2 from '@/assets/images/avatar/avatar2.webp' +import avatar3 from '@/assets/images/avatar/avatar3.webp' +import avatar4 from '@/assets/images/avatar/avatar4.webp' +import avatar5 from '@/assets/images/avatar/avatar5.webp' +import avatar6 from '@/assets/images/avatar/avatar6.webp' +import avatar7 from '@/assets/images/avatar/avatar7.webp' +import avatar8 from '@/assets/images/avatar/avatar8.webp' +import avatar9 from '@/assets/images/avatar/avatar9.webp' +import avatar10 from '@/assets/images/avatar/avatar10.webp' + +export interface User { + id: number + username: string + gender: 1 | 0 + mobile: string + email: string + dep: string + status: string + create_time: string + avatar: string +} + +// 用户列表 +export const ACCOUNT_TABLE_DATA: User[] = [ + { + id: 1, + username: 'alexmorgan', + gender: 1, + mobile: '18670001591', + email: 'alexmorgan@company.com', + dep: '研发部', + status: '1', + create_time: '2020-09-09 10:01:10', + avatar: avatar1 + }, + { + id: 2, + username: 'sophiabaker', + gender: 1, + mobile: '17766664444', + email: 'sophiabaker@company.com', + dep: '电商部', + status: '1', + create_time: '2020-10-10 13:01:12', + avatar: avatar2 + }, + { + id: 3, + username: 'liampark', + gender: 1, + mobile: '18670001597', + email: 'liampark@company.com', + dep: '人事部', + status: '1', + create_time: '2020-11-14 12:01:45', + avatar: avatar3 + }, + { + id: 4, + username: 'oliviagrant', + gender: 0, + mobile: '18670001596', + email: 'oliviagrant@company.com', + dep: '产品部', + status: '1', + create_time: '2020-11-14 09:01:20', + avatar: avatar4 + }, + { + id: 5, + username: 'emmawilson', + gender: 0, + mobile: '18670001595', + email: 'emmawilson@company.com', + dep: '财务部', + status: '1', + create_time: '2020-11-13 11:01:05', + avatar: avatar5 + }, + { + id: 6, + username: 'noahevan', + gender: 1, + mobile: '18670001594', + email: 'noahevan@company.com', + dep: '运营部', + status: '1', + create_time: '2020-10-11 13:10:26', + avatar: avatar6 + }, + { + id: 7, + username: 'avamartin', + gender: 1, + mobile: '18123820191', + email: 'avamartin@company.com', + dep: '客服部', + status: '2', + create_time: '2020-05-14 12:05:10', + avatar: avatar7 + }, + { + id: 8, + username: 'jacoblee', + gender: 1, + mobile: '18670001592', + email: 'jacoblee@company.com', + dep: '总经办', + status: '3', + create_time: '2020-11-12 07:22:25', + avatar: avatar8 + }, + { + id: 9, + username: 'miaclark', + gender: 0, + mobile: '18670001581', + email: 'miaclark@company.com', + dep: '研发部', + status: '4', + create_time: '2020-06-12 05:04:20', + avatar: avatar9 + }, + { + id: 10, + username: 'ethanharris', + gender: 1, + mobile: '13755554444', + email: 'ethanharris@company.com', + dep: '研发部', + status: '1', + create_time: '2020-11-12 16:01:10', + avatar: avatar10 + }, + { + id: 11, + username: 'isabellamoore', + gender: 1, + mobile: '13766660000', + email: 'isabellamoore@company.com', + dep: '研发部', + status: '1', + create_time: '2020-11-14 12:01:20', + avatar: avatar6 + }, + { + id: 12, + username: 'masonwhite', + gender: 1, + mobile: '18670001502', + email: 'masonwhite@company.com', + dep: '研发部', + status: '1', + create_time: '2020-11-14 12:01:20', + avatar: avatar7 + }, + { + id: 13, + username: 'charlottehall', + gender: 1, + mobile: '13006644977', + email: 'charlottehall@company.com', + dep: '研发部', + status: '1', + create_time: '2020-11-14 12:01:20', + avatar: avatar8 + }, + { + id: 14, + username: 'benjaminscott', + gender: 0, + mobile: '13599998888', + email: 'benjaminscott@company.com', + dep: '研发部', + status: '1', + create_time: '2020-11-14 12:01:20', + avatar: avatar9 + }, + { + id: 15, + username: 'ameliaking', + gender: 1, + mobile: '13799998888', + email: 'ameliaking@company.com', + dep: '研发部', + status: '1', + create_time: '2020-11-14 12:01:20', + avatar: avatar10 + } +] + +export interface Role { + roleName: string + roleCode: string + des: string + date: string + enable: boolean +} + +// 角色列表 +export const ROLE_LIST_DATA: Role[] = [ + { + roleName: '超级管理员', + roleCode: 'R_SUPER', + des: '拥有系统全部权限', + date: '2025-05-15 12:30:45', + enable: true + }, + { + roleName: '管理员', + roleCode: 'R_ADMIN', + des: '拥有系统管理权限', + date: '2025-05-15 12:30:45', + enable: true + }, + { + roleName: '普通用户', + roleCode: 'R_USER', + des: '拥有系统普通权限', + date: '2025-05-15 12:30:45', + enable: true + }, + { + roleName: '财务管理员', + roleCode: 'R_FINANCE', + des: '管理财务相关权限', + date: '2025-05-16 09:15:30', + enable: true + }, + { + roleName: '数据分析师', + roleCode: 'R_ANALYST', + des: '拥有数据分析权限', + date: '2025-05-16 11:45:00', + enable: false + }, + { + roleName: '客服专员', + roleCode: 'R_SUPPORT', + des: '处理客户支持请求', + date: '2025-05-17 14:30:22', + enable: true + }, + { + roleName: '营销经理', + roleCode: 'R_MARKETING', + des: '管理营销活动权限', + date: '2025-05-17 15:10:50', + enable: true + }, + { + roleName: '访客用户', + roleCode: 'R_GUEST', + des: '仅限浏览权限', + date: '2025-05-18 08:25:40', + enable: false + }, + { + roleName: '系统维护员', + roleCode: 'R_MAINTAINER', + des: '负责系统维护和更新', + date: '2025-05-18 09:50:12', + enable: true + }, + { + roleName: '项目经理', + roleCode: 'R_PM', + des: '管理项目相关权限', + date: '2025-05-19 13:40:35', + enable: true + } +] diff --git a/src/mock/upgrade/changeLog.ts b/src/mock/upgrade/changeLog.ts new file mode 100644 index 0000000..dd6b772 --- /dev/null +++ b/src/mock/upgrade/changeLog.ts @@ -0,0 +1,12 @@ +import { ref } from 'vue' + +interface UpgradeLog { + version: string // 版本号 + title: string // 更新标题 + date: string // 更新日期 + detail?: string[] // 更新内容 + requireReLogin?: boolean // 是否需要重新登录 + remark?: string // 备注 +} + +export const upgradeLogList = ref([]) diff --git a/src/plugins/echarts.ts b/src/plugins/echarts.ts new file mode 100644 index 0000000..4f56d89 --- /dev/null +++ b/src/plugins/echarts.ts @@ -0,0 +1,76 @@ +/** + * ECharts 插件配置 + * + * 按需导入 ECharts 图表和组件,减小打包体积。 + * 只注册项目中实际使用的图表类型和组件。 + * + * @module plugins/echarts + * @author Art Design Pro Team + */ + +// ECharts 按需导入配置 +import * as echarts from 'echarts/core' + +// 导入图表类型 +import { + BarChart, + LineChart, + PieChart, + ScatterChart, + RadarChart, + MapChart, + CandlestickChart +} from 'echarts/charts' + +// 导入组件 +import { + TitleComponent, + TooltipComponent, + GridComponent, + LegendComponent, + DataZoomComponent, + MarkPointComponent, + MarkLineComponent, + ToolboxComponent, + BrushComponent, + GeoComponent, + VisualMapComponent +} from 'echarts/components' + +// 导入渲染器 +import { CanvasRenderer } from 'echarts/renderers' + +// 注册必要的组件 +echarts.use([ + // 图表类型 + BarChart, + LineChart, + PieChart, + ScatterChart, + RadarChart, + MapChart, + CandlestickChart, + + // 组件 + TitleComponent, + TooltipComponent, + GridComponent, + LegendComponent, + DataZoomComponent, + MarkPointComponent, + MarkLineComponent, + ToolboxComponent, + BrushComponent, + GeoComponent, + VisualMapComponent, + + // 渲染器 + CanvasRenderer +]) + +// 导出 echarts 实例和类型 +export { echarts } +export type { EChartsOption, BarSeriesOption } from 'echarts' + +// 导出常用的图形工具 +export const graphic = echarts.graphic diff --git a/src/plugins/index.ts b/src/plugins/index.ts new file mode 100644 index 0000000..4536a86 --- /dev/null +++ b/src/plugins/index.ts @@ -0,0 +1,6 @@ +/** + * 插件统一导出 + * 集中管理第三方库的封装和配置 + */ + +export * from './echarts' diff --git a/src/router/core/ComponentLoader.ts b/src/router/core/ComponentLoader.ts new file mode 100644 index 0000000..8af3ce3 --- /dev/null +++ b/src/router/core/ComponentLoader.ts @@ -0,0 +1,82 @@ +/** + * 组件加载器 + * + * 负责动态加载 Vue 组件 + * + * @module router/core/ComponentLoader + * @author Art Design Pro Team + */ + +import { h } from 'vue' + +export class ComponentLoader { + private modules: Record Promise> + + constructor() { + // 动态导入 views 目录下所有 .vue 组件 + this.modules = import.meta.glob('../../views/**/*.vue') + } + + /** + * 加载组件 + */ + load(componentPath: string): () => Promise { + if (!componentPath) { + return this.createEmptyComponent() + } + + // 构建可能的路径 + const fullPath = `../../views${componentPath}.vue` + const fullPathWithIndex = `../../views${componentPath}/index.vue` + + // 先尝试直接路径,再尝试添加/index的路径 + const module = this.modules[fullPath] || this.modules[fullPathWithIndex] + + if (!module) { + console.error( + `[ComponentLoader] 未找到组件: ${componentPath},尝试过的路径: ${fullPath} 和 ${fullPathWithIndex}` + ) + return this.createErrorComponent(componentPath) + } + + return module + } + + /** + * 加载布局组件 + */ + loadLayout(): () => Promise { + return () => import('@/views/index/index.vue') + } + + /** + * 加载 iframe 组件 + */ + loadIframe(): () => Promise { + return () => import('@/views/outside/Iframe.vue') + } + + /** + * 创建空组件 + */ + private createEmptyComponent(): () => Promise { + return () => + Promise.resolve({ + render() { + return h('div', {}) + } + }) + } + + /** + * 创建错误提示组件 + */ + private createErrorComponent(componentPath: string): () => Promise { + return () => + Promise.resolve({ + render() { + return h('div', { class: 'route-error' }, `组件未找到: ${componentPath}`) + } + }) + } +} diff --git a/src/router/core/IframeRouteManager.ts b/src/router/core/IframeRouteManager.ts new file mode 100644 index 0000000..c054ca1 --- /dev/null +++ b/src/router/core/IframeRouteManager.ts @@ -0,0 +1,78 @@ +/** + * Iframe 路由管理器 + * + * 负责管理 iframe 类型的路由 + * + * @module router/core/IframeRouteManager + * @author Art Design Pro Team + */ + +import type { AppRouteRecord } from '@/types/router' + +export class IframeRouteManager { + private static instance: IframeRouteManager + private iframeRoutes: AppRouteRecord[] = [] + + private constructor() {} + + static getInstance(): IframeRouteManager { + if (!IframeRouteManager.instance) { + IframeRouteManager.instance = new IframeRouteManager() + } + return IframeRouteManager.instance + } + + /** + * 添加 iframe 路由 + */ + add(route: AppRouteRecord): void { + if (!this.iframeRoutes.find((r) => r.path === route.path)) { + this.iframeRoutes.push(route) + } + } + + /** + * 获取所有 iframe 路由 + */ + getAll(): AppRouteRecord[] { + return this.iframeRoutes + } + + /** + * 根据路径查找 iframe 路由 + */ + findByPath(path: string): AppRouteRecord | undefined { + return this.iframeRoutes.find((route) => route.path === path) + } + + /** + * 清空所有 iframe 路由 + */ + clear(): void { + this.iframeRoutes = [] + } + + /** + * 保存到 sessionStorage + */ + save(): void { + if (this.iframeRoutes.length > 0) { + sessionStorage.setItem('iframeRoutes', JSON.stringify(this.iframeRoutes)) + } + } + + /** + * 从 sessionStorage 加载 + */ + load(): void { + try { + const data = sessionStorage.getItem('iframeRoutes') + if (data) { + this.iframeRoutes = JSON.parse(data) + } + } catch (error) { + console.error('[IframeRouteManager] 加载 iframe 路由失败:', error) + this.iframeRoutes = [] + } + } +} diff --git a/src/router/core/MenuProcessor.ts b/src/router/core/MenuProcessor.ts new file mode 100644 index 0000000..57bf183 --- /dev/null +++ b/src/router/core/MenuProcessor.ts @@ -0,0 +1,241 @@ +/** + * 菜单处理器 + * + * 负责菜单数据的获取、过滤和处理 + * + * @module router/core/MenuProcessor + * @author Art Design Pro Team + */ + +import type { AppRouteRecord } from '@/types/router' +import { useUserStore } from '@/store/modules/user' +import { useAppMode } from '@/hooks/core/useAppMode' +import { fetchGetMenuList } from '@/api/system-manage' +import { asyncRoutes } from '../routes/asyncRoutes' +import { RoutesAlias } from '../routesAlias' +import { formatMenuTitle } from '@/utils' + +export class MenuProcessor { + /** + * 获取菜单数据 + */ + async getMenuList(): Promise { + const { isFrontendMode } = useAppMode() + + let menuList: AppRouteRecord[] + if (isFrontendMode.value) { + menuList = await this.processFrontendMenu() + } else { + menuList = await this.processBackendMenu() + } + + // 在规范化路径之前,验证原始路径配置 + this.validateMenuPaths(menuList) + + // 规范化路径(将相对路径转换为完整路径) + return this.normalizeMenuPaths(menuList) + } + + /** + * 处理前端控制模式的菜单 + */ + private async processFrontendMenu(): Promise { + const userStore = useUserStore() + const roles = userStore.info?.roles + + let menuList = [...asyncRoutes] + + // 根据角色过滤菜单 + if (roles && roles.length > 0) { + menuList = this.filterMenuByRoles(menuList, roles) + } + + return this.filterEmptyMenus(menuList) + } + + /** + * 处理后端控制模式的菜单 + */ + private async processBackendMenu(): Promise { + const list = await fetchGetMenuList() + return this.filterEmptyMenus(list) + } + + /** + * 根据角色过滤菜单 + */ + private filterMenuByRoles(menu: AppRouteRecord[], roles: string[]): AppRouteRecord[] { + return menu.reduce((acc: AppRouteRecord[], item) => { + const itemRoles = item.meta?.roles + const hasPermission = !itemRoles || itemRoles.some((role) => roles?.includes(role)) + + if (hasPermission) { + const filteredItem = { ...item } + if (filteredItem.children?.length) { + filteredItem.children = this.filterMenuByRoles(filteredItem.children, roles) + } + acc.push(filteredItem) + } + + return acc + }, []) + } + + /** + * 递归过滤空菜单项 + */ + private filterEmptyMenus(menuList: AppRouteRecord[]): AppRouteRecord[] { + return menuList + .map((item) => { + // 如果有子菜单,先递归过滤子菜单 + if (item.children && item.children.length > 0) { + const filteredChildren = this.filterEmptyMenus(item.children) + return { + ...item, + children: filteredChildren + } + } + return item + }) + .filter((item) => { + // 如果定义了 children 属性(即使是空数组),说明这是一个目录菜单,应该保留 + if ('children' in item) { + return true + } + + // 如果有外链或 iframe,保留 + if (item.meta?.isIframe === true || item.meta?.link) { + return true + } + + // 如果有有效的 component,保留 + if (item.component && item.component !== '' && item.component !== RoutesAlias.Layout) { + return true + } + + // 其他情况过滤掉 + return false + }) + } + + /** + * 验证菜单列表是否有效 + */ + validateMenuList(menuList: AppRouteRecord[]): boolean { + return Array.isArray(menuList) && menuList.length > 0 + } + + /** + * 规范化菜单路径 + * 将相对路径转换为完整路径,确保菜单跳转正确 + */ + private normalizeMenuPaths(menuList: AppRouteRecord[], parentPath = ''): AppRouteRecord[] { + return menuList.map((item) => { + // 构建完整路径 + const fullPath = this.buildFullPath(item.path || '', parentPath) + + // 递归处理子菜单 + const children = item.children?.length + ? this.normalizeMenuPaths(item.children, fullPath) + : item.children + + return { + ...item, + path: fullPath, + children + } + }) + } + + /** + * 验证菜单路径配置 + * 检测非一级菜单是否错误使用了 / 开头的路径 + */ + /** + * 验证菜单路径配置 + * 检测非一级菜单是否错误使用了 / 开头的路径 + */ + private validateMenuPaths(menuList: AppRouteRecord[], level = 1): void { + menuList.forEach((route) => { + if (!route.children?.length) return + + const parentName = String(route.name || route.path || '未知路由') + + route.children.forEach((child) => { + const childPath = child.path || '' + + // 跳过合法的绝对路径:外部链接和 iframe 路由 + if (this.isValidAbsolutePath(childPath)) return + + // 检测非法的绝对路径 + if (childPath.startsWith('/')) { + this.logPathError(child, childPath, parentName, level) + } + }) + + // 递归检查更深层级的子路由 + this.validateMenuPaths(route.children, level + 1) + }) + } + + /** + * 判断是否为合法的绝对路径 + */ + private isValidAbsolutePath(path: string): boolean { + return ( + path.startsWith('http://') || + path.startsWith('https://') || + path.startsWith('/outside/iframe/') + ) + } + + /** + * 输出路径配置错误日志 + */ + private logPathError( + route: AppRouteRecord, + path: string, + parentName: string, + level: number + ): void { + const routeName = String(route.name || path || '未知路由') + const menuTitle = route.meta?.title || routeName + const suggestedPath = path.split('/').pop() || path.slice(1) + + console.error( + `[路由配置错误] 菜单 "${formatMenuTitle(menuTitle)}" (name: ${routeName}, path: ${path}) 配置错误\n` + + ` 位置: ${parentName} > ${routeName}\n` + + ` 问题: ${level + 1}级菜单的 path 不能以 / 开头\n` + + ` 当前配置: path: '${path}'\n` + + ` 应该改为: path: '${suggestedPath}'` + ) + } + + /** + * 构建完整路径 + */ + private buildFullPath(path: string, parentPath: string): string { + if (!path) return '' + + // 外部链接直接返回 + if (path.startsWith('http://') || path.startsWith('https://')) { + return path + } + + // 如果已经是绝对路径,直接返回 + if (path.startsWith('/')) { + return path + } + + // 拼接父路径和当前路径 + if (parentPath) { + // 移除父路径末尾的斜杠,移除子路径开头的斜杠,然后拼接 + const cleanParent = parentPath.replace(/\/$/, '') + const cleanChild = path.replace(/^\//, '') + return `${cleanParent}/${cleanChild}` + } + + // 没有父路径,添加前导斜杠 + return `/${path}` + } +} diff --git a/src/router/core/RoutePermissionValidator.ts b/src/router/core/RoutePermissionValidator.ts new file mode 100644 index 0000000..c33e663 --- /dev/null +++ b/src/router/core/RoutePermissionValidator.ts @@ -0,0 +1,119 @@ +/** + * 路由权限验证模块 + * + * 提供路由权限验证和路径检查功能 + * + * ## 主要功能 + * + * - 验证路径是否在用户菜单权限中 + * - 构建菜单路径集合(扁平化处理) + * - 支持动态路由参数匹配 + * - 路径前缀匹配 + * + * ## 使用场景 + * + * - 路由守卫中验证用户权限 + * - 动态路由注册后的权限检查 + * - 防止用户访问无权限的页面 + * + * @module router/core/RoutePermissionValidator + * @author Art Design Pro Team + */ + +import type { AppRouteRecord } from '@/types/router' + +/** + * 路由权限验证器 + */ +export class RoutePermissionValidator { + /** + * 验证路径是否在用户菜单权限中 + * @param targetPath 目标路径 + * @param menuList 菜单列表 + * @returns 是否有权限访问 + */ + static hasPermission(targetPath: string, menuList: AppRouteRecord[]): boolean { + // 根路径始终允许访问 + if (targetPath === '/') { + return true + } + + // 构建路径集合 + const pathSet = this.buildMenuPathSet(menuList) + + // 检查路径是否在集合中(精确匹配或前缀匹配) + return pathSet.has(targetPath) || this.checkPathPrefix(targetPath, pathSet) + } + + /** + * 构建菜单路径集合(扁平化处理) + * @param menuList 菜单列表 + * @param pathSet 路径集合 + * @returns 路径集合 + */ + static buildMenuPathSet( + menuList: AppRouteRecord[], + pathSet: Set = new Set() + ): Set { + if (!Array.isArray(menuList) || menuList.length === 0) { + return pathSet + } + + for (const menuItem of menuList) { + // 跳过隐藏的菜单项 + if (menuItem.meta?.isHide || !menuItem.path) { + continue + } + + // 标准化路径并添加到集合 + const menuPath = menuItem.path.startsWith('/') ? menuItem.path : `/${menuItem.path}` + pathSet.add(menuPath) + + // 递归处理子菜单 + if (menuItem.children?.length) { + this.buildMenuPathSet(menuItem.children, pathSet) + } + } + + return pathSet + } + + /** + * 检查目标路径是否匹配集合中的某个路径前缀 + * 用于支持动态路由参数匹配,如 /user/123 匹配 /user + * @param targetPath 目标路径 + * @param pathSet 路径集合 + * @returns 是否匹配 + */ + static checkPathPrefix(targetPath: string, pathSet: Set): boolean { + // 遍历路径集合,检查是否有前缀匹配 + for (const menuPath of pathSet) { + if (targetPath.startsWith(`${menuPath}/`)) { + return true + } + } + return false + } + + /** + * 验证并返回有效的路径 + * 如果目标路径无权限,返回首页路径 + * @param targetPath 目标路径 + * @param menuList 菜单列表 + * @param homePath 首页路径 + * @returns 验证后的路径 + */ + static validatePath( + targetPath: string, + menuList: AppRouteRecord[], + homePath: string = '/' + ): { path: string; hasPermission: boolean } { + const hasPermission = this.hasPermission(targetPath, menuList) + + if (hasPermission) { + return { path: targetPath, hasPermission: true } + } + + return { path: homePath, hasPermission: false } + } +} diff --git a/src/router/core/RouteRegistry.ts b/src/router/core/RouteRegistry.ts new file mode 100644 index 0000000..e1acb9e --- /dev/null +++ b/src/router/core/RouteRegistry.ts @@ -0,0 +1,90 @@ +/** + * 路由注册核心类 + * + * 负责动态路由的注册、验证和管理 + * + * @module router/core/RouteRegistry + * @author Art Design Pro Team + */ + +import type { Router, RouteRecordRaw } from 'vue-router' +import type { AppRouteRecord } from '@/types/router' +import { ComponentLoader } from './ComponentLoader' +import { RouteValidator } from './RouteValidator' +import { RouteTransformer } from './RouteTransformer' + +export class RouteRegistry { + private router: Router + private componentLoader: ComponentLoader + private validator: RouteValidator + private transformer: RouteTransformer + private removeRouteFns: (() => void)[] = [] + private registered = false + + constructor(router: Router) { + this.router = router + this.componentLoader = new ComponentLoader() + this.validator = new RouteValidator() + this.transformer = new RouteTransformer(this.componentLoader) + } + + /** + * 注册动态路由 + */ + register(menuList: AppRouteRecord[]): void { + if (this.registered) { + console.warn('[RouteRegistry] 路由已注册,跳过重复注册') + return + } + + // 验证路由配置 + const validationResult = this.validator.validate(menuList) + if (!validationResult.valid) { + throw new Error(`路由配置验证失败: ${validationResult.errors.join(', ')}`) + } + + // 转换并注册路由 + const removeRouteFns: (() => void)[] = [] + + menuList.forEach((route) => { + if (route.name && !this.router.hasRoute(route.name)) { + const routeConfig = this.transformer.transform(route) + const removeRouteFn = this.router.addRoute(routeConfig as RouteRecordRaw) + removeRouteFns.push(removeRouteFn) + } + }) + + this.removeRouteFns = removeRouteFns + this.registered = true + } + + /** + * 移除所有动态路由 + */ + unregister(): void { + this.removeRouteFns.forEach((fn) => fn()) + this.removeRouteFns = [] + this.registered = false + } + + /** + * 检查是否已注册 + */ + isRegistered(): boolean { + return this.registered + } + + /** + * 获取移除函数列表(用于 store 管理) + */ + getRemoveRouteFns(): (() => void)[] { + return this.removeRouteFns + } + + /** + * 标记为已注册(用于错误处理场景,避免重复请求) + */ + markAsRegistered(): void { + this.registered = true + } +} diff --git a/src/router/core/RouteTransformer.ts b/src/router/core/RouteTransformer.ts new file mode 100644 index 0000000..0f6900c --- /dev/null +++ b/src/router/core/RouteTransformer.ts @@ -0,0 +1,132 @@ +/** + * 路由转换器 + * + * 负责将菜单数据转换为 Vue Router 路由配置 + * + * @module router/core/RouteTransformer + * @author Art Design Pro Team + */ + +import type { RouteRecordRaw } from 'vue-router' +import type { AppRouteRecord } from '@/types/router' +import { ComponentLoader } from './ComponentLoader' +import { IframeRouteManager } from './IframeRouteManager' + +interface ConvertedRoute extends Omit { + id?: number + children?: ConvertedRoute[] + component?: RouteRecordRaw['component'] | (() => Promise) +} + +export class RouteTransformer { + private componentLoader: ComponentLoader + private iframeManager: IframeRouteManager + + constructor(componentLoader: ComponentLoader) { + this.componentLoader = componentLoader + this.iframeManager = IframeRouteManager.getInstance() + } + + /** + * 转换路由配置 + */ + transform(route: AppRouteRecord, depth = 0): ConvertedRoute { + const { component, children, ...routeConfig } = route + + // 基础路由配置 + const converted: ConvertedRoute = { + ...routeConfig, + component: undefined + } + + // 处理不同类型的路由 + if (route.meta.isIframe) { + this.handleIframeRoute(converted, route, depth) + } else if (this.isFirstLevelRoute(route, depth)) { + this.handleFirstLevelRoute(converted, route, component as string) + } else { + this.handleNormalRoute(converted, component as string) + } + + // 递归处理子路由 + if (children?.length) { + converted.children = children.map((child) => this.transform(child, depth + 1)) + } + + return converted + } + + /** + * 判断是否为一级路由(需要 Layout 包裹) + */ + private isFirstLevelRoute(route: AppRouteRecord, depth: number): boolean { + return depth === 0 && (!route.children || route.children.length === 0) + } + + /** + * 处理 iframe 类型路由 + */ + private handleIframeRoute( + targetRoute: ConvertedRoute, + sourceRoute: AppRouteRecord, + depth: number + ): void { + if (depth === 0) { + // 顶级 iframe:用 Layout 包裹 + targetRoute.component = this.componentLoader.loadLayout() + targetRoute.path = this.extractFirstSegment(sourceRoute.path || '') + targetRoute.name = '' + + targetRoute.children = [ + { + ...sourceRoute, + component: this.componentLoader.loadIframe() + } as ConvertedRoute + ] + } else { + // 非顶级(嵌套)iframe:直接使用 Iframe.vue + targetRoute.component = this.componentLoader.loadIframe() + } + + // 记录 iframe 路由 + this.iframeManager.add(sourceRoute) + } + + /** + * 处理一级菜单路由 + */ + private handleFirstLevelRoute( + converted: ConvertedRoute, + route: AppRouteRecord, + component: string | undefined + ): void { + converted.component = this.componentLoader.loadLayout() + converted.path = this.extractFirstSegment(route.path || '') + converted.name = '' + route.meta.isFirstLevel = true + + converted.children = [ + { + ...route, + component: component ? this.componentLoader.load(component) : undefined + } as ConvertedRoute + ] + } + + /** + * 处理普通路由 + */ + private handleNormalRoute(converted: ConvertedRoute, component: string | undefined): void { + if (component) { + converted.component = this.componentLoader.load(component) + } + } + + /** + * 提取路径的第一段 + */ + private extractFirstSegment(path: string): string { + const segments = path.split('/').filter(Boolean) + return segments.length > 0 ? `/${segments[0]}` : '/' + } +} diff --git a/src/router/core/RouteValidator.ts b/src/router/core/RouteValidator.ts new file mode 100644 index 0000000..f8e58fc --- /dev/null +++ b/src/router/core/RouteValidator.ts @@ -0,0 +1,187 @@ +/** + * 路由验证器 + * + * 负责验证路由配置的合法性 + * + * @module router/core/RouteValidator + * @author Art Design Pro Team + */ + +import type { AppRouteRecord } from '@/types/router' +import { RoutesAlias } from '../routesAlias' + +export interface ValidationResult { + valid: boolean + errors: string[] + warnings: string[] +} + +export class RouteValidator { + // 用于记录已经提示过的路由,避免重复提示 + private warnedRoutes = new Set() + + /** + * 验证路由配置 + */ + validate(routes: AppRouteRecord[]): ValidationResult { + const errors: string[] = [] + const warnings: string[] = [] + + // 检测重复路由 + this.checkDuplicates(routes, errors, warnings) + + // 检测组件配置 + this.checkComponents(routes, errors, warnings) + + // 检测嵌套菜单的 /index/index 配置 + this.checkNestedIndexComponent(routes) + + return { + valid: errors.length === 0, + errors, + warnings + } + } + + /** + * 检测重复路由 + */ + private checkDuplicates( + routes: AppRouteRecord[], + errors: string[], + warnings: string[], + parentPath = '' + ): void { + const routeNameMap = new Map() + const componentPathMap = new Map() + + const checkRoutes = (routes: AppRouteRecord[], parentPath = '') => { + routes.forEach((route) => { + const currentPath = route.path || '' + const fullPath = this.resolvePath(parentPath, currentPath) + + // 名称重复检测 + if (route.name) { + const routeName = String(route.name) + if (routeNameMap.has(routeName)) { + warnings.push(`路由名称重复: "${routeName}" (${fullPath})`) + } else { + routeNameMap.set(routeName, fullPath) + } + } + + // 组件路径重复检测 + if (route.component && typeof route.component === 'string') { + const componentPath = route.component + if (componentPath !== RoutesAlias.Layout) { + const componentKey = `${parentPath}:${componentPath}` + if (componentPathMap.has(componentKey)) { + warnings.push(`组件路径重复: "${componentPath}" (${fullPath})`) + } else { + componentPathMap.set(componentKey, fullPath) + } + } + } + + // 递归处理子路由 + if (route.children?.length) { + checkRoutes(route.children, fullPath) + } + }) + } + + checkRoutes(routes, parentPath) + } + + /** + * 检测组件配置 + */ + private checkComponents( + routes: AppRouteRecord[], + errors: string[], + warnings: string[], + parentPath = '' + ): void { + routes.forEach((route) => { + const hasExternalLink = !!route.meta?.link?.trim() + const hasChildren = Array.isArray(route.children) && route.children.length > 0 + const routePath = route.path || '[未定义路径]' + const isIframe = route.meta?.isIframe + + // 如果配置了 component,则无需校验 + if (route.component) { + // 递归检查子路由 + if (route.children?.length) { + const fullPath = this.resolvePath(parentPath, route.path || '') + this.checkComponents(route.children, errors, warnings, fullPath) + } + return + } + + // 一级菜单:必须指定 Layout,除非是外链或 iframe + if (parentPath === '' && !hasExternalLink && !isIframe) { + errors.push(`一级菜单(${routePath}) 缺少 component,必须指向 ${RoutesAlias.Layout}`) + return + } + + // 非一级菜单:如果既不是外链、iframe,也没有子路由,则必须配置 component + if (!hasExternalLink && !isIframe && !hasChildren) { + errors.push(`路由(${routePath}) 缺少 component 配置`) + } + + // 递归检查子路由 + if (route.children?.length) { + const fullPath = this.resolvePath(parentPath, route.path || '') + this.checkComponents(route.children, errors, warnings, fullPath) + } + }) + } + + /** + * 检测嵌套菜单的 Layout 组件配置 + * 只有一级菜单才能使用 Layout,二级及以下菜单不能使用 + */ + private checkNestedIndexComponent(routes: AppRouteRecord[], level = 1): void { + routes.forEach((route) => { + // 检查二级及以下菜单是否错误使用了 Layout + if (level > 1 && route.component === RoutesAlias.Layout) { + this.logLayoutError(route, level) + } + + // 递归检查子路由 + if (route.children?.length) { + this.checkNestedIndexComponent(route.children, level + 1) + } + }) + } + + /** + * 输出 Layout 组件配置错误日志 + */ + private logLayoutError(route: AppRouteRecord, level: number): void { + const routeName = String(route.name || route.path || '未知路由') + const routeKey = `${routeName}_${route.path}` + + // 避免重复提示 + if (this.warnedRoutes.has(routeKey)) return + this.warnedRoutes.add(routeKey) + + const menuTitle = route.meta?.title || routeName + const routePath = route.path || '/' + + console.error( + `[路由配置错误] 菜单 "${menuTitle}" (name: ${routeName}, path: ${routePath}) 配置错误\n` + + ` 问题: ${level}级菜单不能使用 ${RoutesAlias.Layout} 作为 component\n` + + ` 说明: 只有一级菜单才能使用 ${RoutesAlias.Layout},二级及以下菜单应该指向具体的组件路径\n` + + ` 当前配置: component: '${RoutesAlias.Layout}'\n` + + ` 应该改为: component: '/your/component/path' 或留空 ''(如果是目录菜单)` + ) + } + + /** + * 路径解析 + */ + private resolvePath(parent: string, child: string): string { + return [parent.replace(/\/$/, ''), child.replace(/^\//, '')].filter(Boolean).join('/') + } +} diff --git a/src/router/core/index.ts b/src/router/core/index.ts new file mode 100644 index 0000000..fcfecfc --- /dev/null +++ b/src/router/core/index.ts @@ -0,0 +1,14 @@ +/** + * 路由核心模块导出 + * + * @module router/core + * @author Art Design Pro Team + */ + +export { RouteRegistry } from './RouteRegistry' +export { ComponentLoader } from './ComponentLoader' +export { RouteValidator } from './RouteValidator' +export { RouteTransformer } from './RouteTransformer' +export { IframeRouteManager } from './IframeRouteManager' +export { MenuProcessor } from './MenuProcessor' +export { RoutePermissionValidator } from './RoutePermissionValidator' diff --git a/src/router/guards/afterEach.ts b/src/router/guards/afterEach.ts new file mode 100644 index 0000000..d60572d --- /dev/null +++ b/src/router/guards/afterEach.ts @@ -0,0 +1,34 @@ +import { nextTick } from 'vue' +import { useSettingStore } from '@/store/modules/setting' +import { Router } from 'vue-router' +import NProgress from 'nprogress' +import { useCommon } from '@/hooks/core/useCommon' +import { loadingService } from '@/utils/ui' +import { getPendingLoading, resetPendingLoading } from './beforeEach' + +/** 路由全局后置守卫 */ +export function setupAfterEachGuard(router: Router) { + const { scrollToTop } = useCommon() + + router.afterEach(() => { + scrollToTop() + + // 关闭进度条 + const settingStore = useSettingStore() + if (settingStore.showNprogress) { + NProgress.done() + // 确保进度条完全移除,避免残影 + setTimeout(() => { + NProgress.remove() + }, 600) + } + + // 关闭 loading 效果 + if (getPendingLoading()) { + nextTick(() => { + loadingService.hideLoading() + resetPendingLoading() + }) + } + }) +} diff --git a/src/router/guards/beforeEach.ts b/src/router/guards/beforeEach.ts new file mode 100644 index 0000000..e94f633 --- /dev/null +++ b/src/router/guards/beforeEach.ts @@ -0,0 +1,400 @@ +/** + * 路由全局前置守卫模块 + * + * 提供完整的路由导航守卫功能 + * + * ## 主要功能 + * + * - 登录状态验证和重定向 + * - 动态路由注册和权限控制 + * - 菜单数据获取和处理(前端/后端模式) + * - 用户信息获取和缓存 + * - 页面标题设置 + * - 工作标签页管理 + * - 进度条和加载动画控制 + * - 静态路由识别和处理 + * - 错误处理和异常跳转 + * + * ## 使用场景 + * + * - 路由跳转前的权限验证 + * - 动态菜单加载和路由注册 + * - 用户登录状态管理 + * - 页面访问控制 + * - 路由级别的加载状态管理 + * + * ## 工作流程 + * + * 1. 检查登录状态,未登录跳转到登录页 + * 2. 首次访问时获取用户信息和菜单数据 + * 3. 根据权限动态注册路由 + * 4. 设置页面标题和工作标签页 + * 5. 处理根路径重定向到首页 + * 6. 未匹配路由跳转到 404 页面 + * + * @module router/guards/beforeEach + * @author Art Design Pro Team + */ +import type { Router, RouteLocationNormalized, NavigationGuardNext } from 'vue-router' +import { nextTick } from 'vue' +import NProgress from 'nprogress' +import { useSettingStore } from '@/store/modules/setting' +import { useUserStore } from '@/store/modules/user' +import { useMenuStore } from '@/store/modules/menu' +import { setWorktab } from '@/utils/navigation' +import { setPageTitle } from '@/utils/router' +import { RoutesAlias } from '../routesAlias' +import { staticRoutes } from '../routes/staticRoutes' +import { loadingService } from '@/utils/ui' +import { useCommon } from '@/hooks/core/useCommon' +import { useWorktabStore } from '@/store/modules/worktab' +import { fetchGetUserInfo } from '@/api/auth' +import { ApiStatus } from '@/utils/http/status' +import { isHttpError } from '@/utils/http/error' +import { RouteRegistry, MenuProcessor, IframeRouteManager, RoutePermissionValidator } from '../core' + +// 路由注册器实例 +let routeRegistry: RouteRegistry | null = null + +// 菜单处理器实例 +const menuProcessor = new MenuProcessor() + +// 跟踪是否需要关闭 loading +let pendingLoading = false + +// 路由初始化失败标记,防止死循环 +// 一旦设置为 true,只有刷新页面或重新登录才能重置 +let routeInitFailed = false + +// 路由初始化进行中标记,防止并发请求 +let routeInitInProgress = false + +/** + * 获取 pendingLoading 状态 + */ +export function getPendingLoading(): boolean { + return pendingLoading +} + +/** + * 重置 pendingLoading 状态 + */ +export function resetPendingLoading(): void { + pendingLoading = false +} + +/** + * 获取路由初始化失败状态 + */ +export function getRouteInitFailed(): boolean { + return routeInitFailed +} + +/** + * 重置路由初始化状态(用于重新登录场景) + */ +export function resetRouteInitState(): void { + routeInitFailed = false + routeInitInProgress = false +} + +/** + * 设置路由全局前置守卫 + */ +export function setupBeforeEachGuard(router: Router): void { + // 初始化路由注册器 + routeRegistry = new RouteRegistry(router) + + router.beforeEach( + async ( + to: RouteLocationNormalized, + from: RouteLocationNormalized, + next: NavigationGuardNext + ) => { + try { + await handleRouteGuard(to, from, next, router) + } catch (error) { + console.error('[RouteGuard] 路由守卫处理失败:', error) + closeLoading() + next({ name: 'Exception500' }) + } + } + ) +} + +/** + * 关闭 loading 效果 + */ +function closeLoading(): void { + if (pendingLoading) { + nextTick(() => { + loadingService.hideLoading() + pendingLoading = false + }) + } +} + +/** + * 处理路由守卫逻辑 + */ +async function handleRouteGuard( + to: RouteLocationNormalized, + from: RouteLocationNormalized, + next: NavigationGuardNext, + router: Router +): Promise { + const settingStore = useSettingStore() + const userStore = useUserStore() + + // 启动进度条 + if (settingStore.showNprogress) { + NProgress.start() + } + + // 1. 检查登录状态 + if (!handleLoginStatus(to, userStore, next)) { + return + } + + // 2. 检查路由初始化是否已失败(防止死循环) + if (routeInitFailed) { + // 已经失败过,直接放行到错误页面,不再重试 + if (to.matched.length > 0) { + next() + } else { + // 未匹配到路由,跳转到 500 页面 + next({ name: 'Exception500', replace: true }) + } + return + } + + // 3. 处理动态路由注册 + if (!routeRegistry?.isRegistered() && userStore.isLogin) { + // 防止并发请求(快速连续导航场景) + if (routeInitInProgress) { + // 正在初始化中,等待完成后重新导航 + next(false) + return + } + await handleDynamicRoutes(to, next, router) + return + } + + // 4. 处理根路径重定向 + if (handleRootPathRedirect(to, next)) { + return + } + + // 5. 处理已匹配的路由 + if (to.matched.length > 0) { + setWorktab(to) + setPageTitle(to) + next() + return + } + + // 6. 未匹配到路由,跳转到 404 + next({ name: 'Exception404' }) +} + +/** + * 处理登录状态 + * @returns true 表示可以继续,false 表示已处理跳转 + */ +function handleLoginStatus( + to: RouteLocationNormalized, + userStore: ReturnType, + next: NavigationGuardNext +): boolean { + // 已登录或访问登录页或静态路由,直接放行 + if (userStore.isLogin || to.path === RoutesAlias.Login || isStaticRoute(to.path)) { + return true + } + + // 未登录且访问需要权限的页面,跳转到登录页并携带 redirect 参数 + userStore.logOut() + next({ + name: 'Login', + query: { redirect: to.fullPath } + }) + return false +} + +/** + * 检查路由是否为静态路由 + */ +function isStaticRoute(path: string): boolean { + const checkRoute = (routes: any[], targetPath: string): boolean => { + return routes.some((route) => { + // 处理动态路由参数匹配 + const routePath = route.path + const pattern = routePath.replace(/:[^/]+/g, '[^/]+').replace(/\*/g, '.*') + const regex = new RegExp(`^${pattern}$`) + + if (regex.test(targetPath)) { + return true + } + if (route.children && route.children.length > 0) { + return checkRoute(route.children, targetPath) + } + return false + }) + } + + return checkRoute(staticRoutes, path) +} + +/** + * 处理动态路由注册 + */ +async function handleDynamicRoutes( + to: RouteLocationNormalized, + next: NavigationGuardNext, + router: Router +): Promise { + // 标记初始化进行中 + routeInitInProgress = true + + // 显示 loading + pendingLoading = true + loadingService.showLoading() + + try { + // 1. 获取用户信息 + await fetchUserInfo() + + // 2. 获取菜单数据 + const menuList = await menuProcessor.getMenuList() + + // 3. 验证菜单数据 + if (!menuProcessor.validateMenuList(menuList)) { + throw new Error('获取菜单列表失败,请重新登录') + } + + // 4. 注册动态路由 + routeRegistry?.register(menuList) + + // 5. 保存菜单数据到 store + const menuStore = useMenuStore() + menuStore.setMenuList(menuList) + menuStore.addRemoveRouteFns(routeRegistry?.getRemoveRouteFns() || []) + + // 6. 保存 iframe 路由 + IframeRouteManager.getInstance().save() + + // 7. 验证工作标签页 + useWorktabStore().validateWorktabs(router) + + // 8. 验证目标路径权限 + const { homePath } = useCommon() + const { path: validatedPath, hasPermission } = RoutePermissionValidator.validatePath( + to.path, + menuList, + homePath.value || '/' + ) + + // 初始化成功,重置进行中标记 + routeInitInProgress = false + + // 9. 重新导航到目标路由 + if (!hasPermission) { + // 无权限访问,跳转到首页 + closeLoading() + + // 输出警告信息 + console.warn(`[RouteGuard] 用户无权限访问路径: ${to.path},已跳转到首页`) + + // 直接跳转到首页 + next({ + path: validatedPath, + replace: true + }) + } else { + // 有权限,正常导航 + next({ + path: to.path, + query: to.query, + hash: to.hash, + replace: true + }) + } + } catch (error) { + console.error('[RouteGuard] 动态路由注册失败:', error) + + // 关闭 loading + closeLoading() + + // 401 错误:axios 拦截器已处理退出登录,取消当前导航 + if (isUnauthorizedError(error)) { + // 重置状态,允许重新登录后再次初始化 + routeInitInProgress = false + next(false) + return + } + + // 标记初始化失败,防止死循环 + routeInitFailed = true + routeInitInProgress = false + + // 输出详细错误信息,便于排查 + if (isHttpError(error)) { + console.error(`[RouteGuard] 错误码: ${error.code}, 消息: ${error.message}`) + } + + // 跳转到 500 页面,使用 replace 避免产生历史记录 + next({ name: 'Exception500', replace: true }) + } +} + +/** + * 获取用户信息 + */ +async function fetchUserInfo(): Promise { + const userStore = useUserStore() + const data = await fetchGetUserInfo() + userStore.setUserInfo(data) + // 检查并清理工作台标签页(如果是不同用户登录) + userStore.checkAndClearWorktabs() +} + +/** + * 重置路由相关状态 + */ +export function resetRouterState(delay: number): void { + setTimeout(() => { + routeRegistry?.unregister() + IframeRouteManager.getInstance().clear() + + const menuStore = useMenuStore() + menuStore.removeAllDynamicRoutes() + menuStore.setMenuList([]) + + // 重置路由初始化状态,允许重新登录后再次初始化 + resetRouteInitState() + }, delay) +} + +/** + * 处理根路径重定向到首页 + * @returns true 表示已处理跳转,false 表示无需跳转 + */ +function handleRootPathRedirect(to: RouteLocationNormalized, next: NavigationGuardNext): boolean { + if (to.path !== '/') { + return false + } + + const { homePath } = useCommon() + if (homePath.value && homePath.value !== '/') { + next({ path: homePath.value, replace: true }) + return true + } + + return false +} + +/** + * 判断是否为未授权错误(401) + */ +function isUnauthorizedError(error: unknown): boolean { + return isHttpError(error) && error.code === ApiStatus.unauthorized +} diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..286ae58 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,23 @@ +import type { App } from 'vue' +import { createRouter, createWebHashHistory } from 'vue-router' +import { staticRoutes } from './routes/staticRoutes' +import { configureNProgress } from '@/utils/router' +import { setupBeforeEachGuard } from './guards/beforeEach' +import { setupAfterEachGuard } from './guards/afterEach' + +// 创建路由实例 +export const router = createRouter({ + history: createWebHashHistory(), + routes: staticRoutes // 静态路由 +}) + +// 初始化路由 +export function initRouter(app: App): void { + configureNProgress() // 顶部进度条 + setupBeforeEachGuard(router) // 路由前置守卫 + setupAfterEachGuard(router) // 路由后置守卫 + app.use(router) +} + +// 主页路径,默认使用菜单第一个有效路径,配置后使用此路径 +export const HOME_PAGE_PATH = '' diff --git a/src/router/modules/dashboard.ts b/src/router/modules/dashboard.ts new file mode 100644 index 0000000..5f9c3e9 --- /dev/null +++ b/src/router/modules/dashboard.ts @@ -0,0 +1,24 @@ +import { AppRouteRecord } from '@/types/router' + +export const dashboardRoutes: AppRouteRecord = { + name: 'Dashboard', + path: '/dashboard', + component: '/index/index', + meta: { + title: 'menus.dashboard.title', + icon: 'ri:pie-chart-line', + roles: ['R_SUPER', 'R_ADMIN'] + }, + children: [ + { + path: 'console', + name: 'Console', + component: '/dashboard/console', + meta: { + title: 'menus.dashboard.console', + keepAlive: false, + fixedTab: true + } + } + ] +} diff --git a/src/router/modules/exception.ts b/src/router/modules/exception.ts new file mode 100644 index 0000000..07c5604 --- /dev/null +++ b/src/router/modules/exception.ts @@ -0,0 +1,46 @@ +import { AppRouteRecord } from '@/types/router' + +export const exceptionRoutes: AppRouteRecord = { + path: '/exception', + name: 'Exception', + component: '/index/index', + meta: { + title: 'menus.exception.title', + icon: 'ri:error-warning-line' + }, + children: [ + { + path: '403', + name: 'Exception403', + component: '/exception/403', + meta: { + title: 'menus.exception.forbidden', + keepAlive: true, + isHideTab: true, + isFullPage: true + } + }, + { + path: '404', + name: 'Exception404', + component: '/exception/404', + meta: { + title: 'menus.exception.notFound', + keepAlive: true, + isHideTab: true, + isFullPage: true + } + }, + { + path: '500', + name: 'Exception500', + component: '/exception/500', + meta: { + title: 'menus.exception.serverError', + keepAlive: true, + isHideTab: true, + isFullPage: true + } + } + ] +} diff --git a/src/router/modules/index.ts b/src/router/modules/index.ts new file mode 100644 index 0000000..deff162 --- /dev/null +++ b/src/router/modules/index.ts @@ -0,0 +1,15 @@ +import { AppRouteRecord } from '@/types/router' +import { dashboardRoutes } from './dashboard' +import { systemRoutes } from './system' +import { resultRoutes } from './result' +import { exceptionRoutes } from './exception' + +/** + * 导出所有模块化路由 + */ +export const routeModules: AppRouteRecord[] = [ + dashboardRoutes, + systemRoutes, + resultRoutes, + exceptionRoutes +] diff --git a/src/router/modules/result.ts b/src/router/modules/result.ts new file mode 100644 index 0000000..575a2f7 --- /dev/null +++ b/src/router/modules/result.ts @@ -0,0 +1,33 @@ +import { AppRouteRecord } from '@/types/router' + +export const resultRoutes: AppRouteRecord = { + path: '/result', + name: 'Result', + component: '/index/index', + meta: { + title: 'menus.result.title', + icon: 'ri:checkbox-circle-line' + }, + children: [ + { + path: 'success', + name: 'ResultSuccess', + component: '/result/success', + meta: { + title: 'menus.result.success', + icon: 'ri:checkbox-circle-line', + keepAlive: true + } + }, + { + path: 'fail', + name: 'ResultFail', + component: '/result/fail', + meta: { + title: 'menus.result.fail', + icon: 'ri:close-circle-line', + keepAlive: true + } + } + ] +} diff --git a/src/router/modules/system.ts b/src/router/modules/system.ts new file mode 100644 index 0000000..16df585 --- /dev/null +++ b/src/router/modules/system.ts @@ -0,0 +1,60 @@ +import { AppRouteRecord } from '@/types/router' + +export const systemRoutes: AppRouteRecord = { + path: '/system', + name: 'System', + component: '/index/index', + meta: { + title: 'menus.system.title', + icon: 'ri:user-3-line', + roles: ['R_SUPER', 'R_ADMIN'] + }, + children: [ + { + path: 'user', + name: 'User', + component: '/system/user', + meta: { + title: 'menus.system.user', + keepAlive: true, + roles: ['R_SUPER', 'R_ADMIN'] + } + }, + { + path: 'role', + name: 'Role', + component: '/system/role', + meta: { + title: 'menus.system.role', + keepAlive: true, + roles: ['R_SUPER'] + } + }, + { + path: 'user-center', + name: 'UserCenter', + component: '/system/user-center', + meta: { + title: 'menus.system.userCenter', + isHide: true, + keepAlive: true, + isHideTab: true + } + }, + { + path: 'menu', + name: 'Menus', + component: '/system/menu', + meta: { + title: 'menus.system.menu', + keepAlive: true, + roles: ['R_SUPER'], + authList: [ + { title: '新增', authMark: 'add' }, + { title: '编辑', authMark: 'edit' }, + { title: '删除', authMark: 'delete' } + ] + } + } + ] +} diff --git a/src/router/routes/asyncRoutes.ts b/src/router/routes/asyncRoutes.ts new file mode 100644 index 0000000..ccf1201 --- /dev/null +++ b/src/router/routes/asyncRoutes.ts @@ -0,0 +1,9 @@ +// 权限文档:https://www.artd.pro/docs/zh/guide/in-depth/permission.html +import { AppRouteRecord } from '@/types/router' +import { routeModules } from '../modules' + +/** + * 动态路由(需要权限才能访问的路由) + * 用于渲染菜单以及根据菜单权限动态加载路由,如果没有权限无法访问 + */ +export const asyncRoutes: AppRouteRecord[] = routeModules diff --git a/src/router/routes/staticRoutes.ts b/src/router/routes/staticRoutes.ts new file mode 100644 index 0000000..334d0c2 --- /dev/null +++ b/src/router/routes/staticRoutes.ts @@ -0,0 +1,72 @@ +import { AppRouteRecordRaw } from '@/utils/router' + +/** + * 静态路由配置(不需要权限就能访问的路由) + * + * 属性说明: + * isHideTab: true 表示不在标签页中显示 + * + * 注意事项: + * 1、path、name 不要和动态路由冲突,否则会导致路由冲突无法访问 + * 2、静态路由不管是否登录都可以访问 + */ +export const staticRoutes: AppRouteRecordRaw[] = [ + // 不需要登录就能访问的路由示例 + // { + // path: '/welcome', + // name: 'WelcomeStatic', + // component: () => import('@views/dashboard/console/index.vue'), + // meta: { title: 'menus.dashboard.title' } + // }, + { + path: '/auth/login', + name: 'Login', + component: () => import('@views/auth/login/index.vue'), + meta: { title: 'menus.login.title', isHideTab: true } + }, + { + path: '/auth/register', + name: 'Register', + component: () => import('@views/auth/register/index.vue'), + meta: { title: 'menus.register.title', isHideTab: true } + }, + { + path: '/auth/forget-password', + name: 'ForgetPassword', + component: () => import('@views/auth/forget-password/index.vue'), + meta: { title: 'menus.forgetPassword.title', isHideTab: true } + }, + { + path: '/403', + name: 'Exception403', + component: () => import('@views/exception/403/index.vue'), + meta: { title: '403', isHideTab: true } + }, + { + path: '/:pathMatch(.*)*', + name: 'Exception404', + component: () => import('@views/exception/404/index.vue'), + meta: { title: '404', isHideTab: true } + }, + { + path: '/500', + name: 'Exception500', + component: () => import('@views/exception/500/index.vue'), + meta: { title: '500', isHideTab: true } + }, + { + path: '/outside', + component: () => import('@views/index/index.vue'), + name: 'Outside', + meta: { title: 'menus.outside.title' }, + children: [ + // iframe 内嵌页面 + { + path: '/outside/iframe/:path', + name: 'Iframe', + component: () => import('@/views/outside/Iframe.vue'), + meta: { title: 'iframe' } + } + ] + } +] diff --git a/src/router/routesAlias.ts b/src/router/routesAlias.ts new file mode 100644 index 0000000..2af1c68 --- /dev/null +++ b/src/router/routesAlias.ts @@ -0,0 +1,8 @@ +/** + * 公共路由别名 + # 存放系统级公共路由路径,如布局容器、登录页等 + */ +export enum RoutesAlias { + Layout = '/index/index', // 布局容器 + Login = '/auth/login' // 登录页 +} diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..b485999 --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,52 @@ +/** + * Pinia Store 配置模块 + * + * 提供全局状态管理的初始化和配置 + * + * ## 主要功能 + * + * - Pinia Store 实例创建 + * - 持久化插件配置(pinia-plugin-persistedstate) + * - 版本化存储键管理 + * - 自动数据迁移(跨版本) + * - LocalStorage 序列化配置 + * - Store 初始化函数 + * + * ## 持久化策略 + * + * - 使用 StorageKeyManager 生成版本化的存储键 + * - 格式:sys-v{version}-{storeId} + * - 自动迁移旧版本数据到当前版本 + * - 使用 localStorage 作为存储介质 + * + * @module store/index + * @author Art Design Pro Team + */ +import type { App } from 'vue' +import { createPinia } from 'pinia' +import { createPersistedState } from 'pinia-plugin-persistedstate' +import { StorageKeyManager } from '@/utils/storage/storage-key-manager' + +export const store = createPinia() + +// 创建存储键管理器实例 +const storageKeyManager = new StorageKeyManager() + +// 配置持久化插件 +store.use( + createPersistedState({ + key: (storeId: string) => storageKeyManager.getStorageKey(storeId), + storage: localStorage, + serializer: { + serialize: JSON.stringify, + deserialize: JSON.parse + } + }) +) + +/** + * 初始化 Store + */ +export function initStore(app: App): void { + app.use(store) +} diff --git a/src/store/modules/menu.ts b/src/store/modules/menu.ts new file mode 100644 index 0000000..85d13da --- /dev/null +++ b/src/store/modules/menu.ts @@ -0,0 +1,109 @@ +/** + * 菜单状态管理模块 + * + * 提供菜单数据和动态路由的状态管理 + * + * ## 主要功能 + * + * - 菜单列表存储和管理 + * - 首页路径配置 + * - 动态路由注册和移除 + * - 路由移除函数管理 + * - 菜单宽度配置 + * + * ## 使用场景 + * + * - 动态菜单加载和渲染 + * - 路由权限控制 + * - 首页路径动态设置 + * - 登出时清理动态路由 + * + * ## 工作流程 + * + * 1. 获取菜单数据(前端/后端模式) + * 2. 设置菜单列表和首页路径 + * 3. 注册动态路由并保存移除函数 + * 4. 登出时调用移除函数清理路由 + * + * @module store/modules/menu + * @author Art Design Pro Team + */ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { AppRouteRecord } from '@/types/router' +import { getFirstMenuPath } from '@/utils' +import { HOME_PAGE_PATH } from '@/router' + +/** + * 菜单状态管理 + * 管理应用的菜单列表、首页路径、菜单宽度和动态路由移除函数 + */ +export const useMenuStore = defineStore('menuStore', () => { + /** 首页路径 */ + const homePath = ref(HOME_PAGE_PATH) + /** 菜单列表 */ + const menuList = ref([]) + /** 菜单宽度 */ + const menuWidth = ref('') + /** 存储路由移除函数的数组 */ + const removeRouteFns = ref<(() => void)[]>([]) + + /** + * 设置菜单列表 + * @param list 菜单路由记录数组 + */ + const setMenuList = (list: AppRouteRecord[]) => { + menuList.value = list + setHomePath(HOME_PAGE_PATH || getFirstMenuPath(list)) + } + + /** + * 获取首页路径 + * @returns 首页路径字符串 + */ + const getHomePath = () => homePath.value + + /** + * 设置主页路径 + * @param path 主页路径 + */ + const setHomePath = (path: string) => { + homePath.value = path + } + + /** + * 添加路由移除函数 + * @param fns 要添加的路由移除函数数组 + */ + const addRemoveRouteFns = (fns: (() => void)[]) => { + removeRouteFns.value.push(...fns) + } + + /** + * 移除所有动态路由 + * 执行所有存储的路由移除函数并清空数组 + */ + const removeAllDynamicRoutes = () => { + removeRouteFns.value.forEach((fn) => fn()) + removeRouteFns.value = [] + } + + /** + * 清空路由移除函数数组 + */ + const clearRemoveRouteFns = () => { + removeRouteFns.value = [] + } + + return { + menuList, + menuWidth, + removeRouteFns, + setMenuList, + getHomePath, + setHomePath, + addRemoveRouteFns, + removeAllDynamicRoutes, + clearRemoveRouteFns + } +}) diff --git a/src/store/modules/setting.ts b/src/store/modules/setting.ts new file mode 100644 index 0000000..2878259 --- /dev/null +++ b/src/store/modules/setting.ts @@ -0,0 +1,450 @@ +/** + * 系统设置状态管理模块 + * + * 提供完整的系统设置状态管理 + * + * ## 主要功能 + * + * - 菜单布局配置(左侧、顶部、混合、双栏) + * - 主题管理(亮色、暗色、自动) + * - 菜单主题样式配置 + * - 界面显示开关(面包屑、标签页、语言切换等) + * - 功能开关(手风琴模式、色弱模式、水印等) + * - 样式配置(边框、圆角、容器宽度、页面过渡) + * - 节日功能配置 + * - Element Plus 主题色动态设置 + * + * ## 使用场景 + * + * - 设置面板配置管理 + * - 主题切换和样式定制 + * - 界面功能开关控制 + * - 用户偏好设置持久化 + * + * ## 持久化 + * + * - 使用 localStorage 存储 + * - 存储键:sys-v{version}-setting + * - 支持跨版本数据迁移 + * + * @module store/modules/setting + * @author Art Design Pro Team + */ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import { MenuThemeType } from '@/types/store' +import AppConfig from '@/config' +import { SystemThemeEnum, MenuThemeEnum, MenuTypeEnum, ContainerWidthEnum } from '@/enums/appEnum' +import { setElementThemeColor } from '@/utils/ui' +import { useCeremony } from '@/hooks/core/useCeremony' +import { StorageConfig } from '@/utils' +import { SETTING_DEFAULT_CONFIG } from '@/config/setting' + +/** + * 系统设置状态管理 + * 管理应用的菜单、主题、界面显示等各项设置 + */ +export const useSettingStore = defineStore( + 'settingStore', + () => { + // 菜单相关设置 + /** 菜单类型 */ + const menuType = ref(SETTING_DEFAULT_CONFIG.menuType) + /** 菜单展开宽度 */ + const menuOpenWidth = ref(SETTING_DEFAULT_CONFIG.menuOpenWidth) + /** 菜单是否展开 */ + const menuOpen = ref(SETTING_DEFAULT_CONFIG.menuOpen) + /** 双菜单是否显示文本 */ + const dualMenuShowText = ref(SETTING_DEFAULT_CONFIG.dualMenuShowText) + + // 主题相关设置 + /** 系统主题类型 */ + const systemThemeType = ref(SETTING_DEFAULT_CONFIG.systemThemeType) + /** 系统主题模式 */ + const systemThemeMode = ref(SETTING_DEFAULT_CONFIG.systemThemeMode) + /** 菜单主题类型 */ + const menuThemeType = ref(SETTING_DEFAULT_CONFIG.menuThemeType) + /** 系统主题颜色 */ + const systemThemeColor = ref(SETTING_DEFAULT_CONFIG.systemThemeColor) + + // 界面显示设置 + /** 是否显示菜单按钮 */ + const showMenuButton = ref(SETTING_DEFAULT_CONFIG.showMenuButton) + /** 是否显示快速入口 */ + const showFastEnter = ref(SETTING_DEFAULT_CONFIG.showFastEnter) + /** 是否显示刷新按钮 */ + const showRefreshButton = ref(SETTING_DEFAULT_CONFIG.showRefreshButton) + /** 是否显示面包屑 */ + const showCrumbs = ref(SETTING_DEFAULT_CONFIG.showCrumbs) + /** 是否显示工作台标签 */ + const showWorkTab = ref(SETTING_DEFAULT_CONFIG.showWorkTab) + /** 是否显示语言切换 */ + const showLanguage = ref(SETTING_DEFAULT_CONFIG.showLanguage) + /** 是否显示进度条 */ + const showNprogress = ref(SETTING_DEFAULT_CONFIG.showNprogress) + /** 是否显示设置引导 */ + const showSettingGuide = ref(SETTING_DEFAULT_CONFIG.showSettingGuide) + /** 是否显示节日文本 */ + const showFestivalText = ref(SETTING_DEFAULT_CONFIG.showFestivalText) + /** 是否显示水印 */ + const watermarkVisible = ref(SETTING_DEFAULT_CONFIG.watermarkVisible) + + // 功能设置 + /** 是否自动关闭 */ + const autoClose = ref(SETTING_DEFAULT_CONFIG.autoClose) + /** 是否唯一展开 */ + const uniqueOpened = ref(SETTING_DEFAULT_CONFIG.uniqueOpened) + /** 是否色弱模式 */ + const colorWeak = ref(SETTING_DEFAULT_CONFIG.colorWeak) + /** 是否刷新 */ + const refresh = ref(SETTING_DEFAULT_CONFIG.refresh) + /** 是否加载节日烟花 */ + const holidayFireworksLoaded = ref(SETTING_DEFAULT_CONFIG.holidayFireworksLoaded) + + // 样式设置 + /** 边框模式 */ + const boxBorderMode = ref(SETTING_DEFAULT_CONFIG.boxBorderMode) + /** 页面过渡效果 */ + const pageTransition = ref(SETTING_DEFAULT_CONFIG.pageTransition) + /** 标签页样式 */ + const tabStyle = ref(SETTING_DEFAULT_CONFIG.tabStyle) + /** 自定义圆角 */ + const customRadius = ref(SETTING_DEFAULT_CONFIG.customRadius) + /** 容器宽度 */ + const containerWidth = ref(SETTING_DEFAULT_CONFIG.containerWidth) + + // 节日相关 + /** 节日日期 */ + const festivalDate = ref('') + + /** + * 获取菜单主题 + * 根据当前主题类型和暗色模式返回对应的主题配置 + */ + const getMenuTheme = computed((): MenuThemeType => { + const list = AppConfig.themeList.filter((item) => item.theme === menuThemeType.value) + if (isDark.value) { + return AppConfig.darkMenuStyles[0] + } else { + return list[0] + } + }) + + /** + * 判断是否为暗色模式 + */ + const isDark = computed((): boolean => { + return systemThemeType.value === SystemThemeEnum.DARK + }) + + /** + * 获取菜单展开宽度 + */ + const getMenuOpenWidth = computed((): string => { + return menuOpenWidth.value + 'px' || SETTING_DEFAULT_CONFIG.menuOpenWidth + 'px' + }) + + /** + * 获取自定义圆角 + */ + const getCustomRadius = computed((): string => { + return customRadius.value + 'rem' || SETTING_DEFAULT_CONFIG.customRadius + 'rem' + }) + + /** + * 是否显示烟花 + * 根据当前日期和节日日期判断是否显示烟花效果 + */ + const isShowFireworks = computed((): boolean => { + return festivalDate.value === useCeremony().currentFestivalData.value?.date ? false : true + }) + + /** + * 切换菜单布局 + * @param type 菜单类型 + */ + const switchMenuLayouts = (type: MenuTypeEnum) => { + menuType.value = type + } + + /** + * 设置菜单展开宽度 + * @param width 宽度值 + */ + const setMenuOpenWidth = (width: number) => { + menuOpenWidth.value = width + } + + /** + * 设置全局主题 + * @param theme 主题类型 + * @param themeMode 主题模式 + */ + const setGlopTheme = (theme: SystemThemeEnum, themeMode: SystemThemeEnum) => { + systemThemeType.value = theme + systemThemeMode.value = themeMode + localStorage.setItem(StorageConfig.THEME_KEY, theme) + } + + /** + * 切换菜单样式 + * @param theme 菜单主题 + */ + const switchMenuStyles = (theme: MenuThemeEnum) => { + menuThemeType.value = theme + } + + /** + * 设置Element Plus主题颜色 + * @param theme 主题颜色 + */ + const setElementTheme = (theme: string) => { + systemThemeColor.value = theme + setElementThemeColor(theme) + } + + /** + * 切换边框模式 + */ + const setBorderMode = () => { + boxBorderMode.value = !boxBorderMode.value + } + + /** + * 设置容器宽度 + * @param width 容器宽度枚举值 + */ + const setContainerWidth = (width: ContainerWidthEnum) => { + containerWidth.value = width + } + + /** + * 切换唯一展开模式 + */ + const setUniqueOpened = () => { + uniqueOpened.value = !uniqueOpened.value + } + + /** + * 切换菜单按钮显示 + */ + const setButton = () => { + showMenuButton.value = !showMenuButton.value + } + + /** + * 切换快速入口显示 + */ + const setFastEnter = () => { + showFastEnter.value = !showFastEnter.value + } + + /** + * 切换自动关闭 + */ + const setAutoClose = () => { + autoClose.value = !autoClose.value + } + + /** + * 切换刷新按钮显示 + */ + const setShowRefreshButton = () => { + showRefreshButton.value = !showRefreshButton.value + } + + /** + * 切换面包屑显示 + */ + const setCrumbs = () => { + showCrumbs.value = !showCrumbs.value + } + + /** + * 设置工作台标签显示 + * @param show 是否显示 + */ + const setWorkTab = (show: boolean) => { + showWorkTab.value = show + } + + /** + * 切换语言切换显示 + */ + const setLanguage = () => { + showLanguage.value = !showLanguage.value + } + + /** + * 切换进度条显示 + */ + const setNprogress = () => { + showNprogress.value = !showNprogress.value + } + + /** + * 切换色弱模式 + */ + const setColorWeak = () => { + colorWeak.value = !colorWeak.value + } + + /** + * 隐藏设置引导 + */ + const hideSettingGuide = () => { + showSettingGuide.value = false + } + + /** + * 显示设置引导 + */ + const openSettingGuide = () => { + showSettingGuide.value = true + } + + /** + * 设置页面过渡效果 + * @param transition 过渡效果名称 + */ + const setPageTransition = (transition: string) => { + pageTransition.value = transition + } + + /** + * 设置标签页样式 + * @param style 样式名称 + */ + const setTabStyle = (style: string) => { + tabStyle.value = style + } + + /** + * 设置菜单展开状态 + * @param open 是否展开 + */ + const setMenuOpen = (open: boolean) => { + menuOpen.value = open + } + + /** + * 刷新页面 + */ + const reload = () => { + refresh.value = !refresh.value + } + + /** + * 设置水印显示 + * @param visible 是否显示 + */ + const setWatermarkVisible = (visible: boolean) => { + watermarkVisible.value = visible + } + + /** + * 设置自定义圆角 + * @param radius 圆角值 + */ + const setCustomRadius = (radius: string) => { + customRadius.value = radius + document.documentElement.style.setProperty('--custom-radius', `${radius}rem`) + } + + /** + * 设置节日烟花加载状态 + * @param isLoad 是否已加载 + */ + const setholidayFireworksLoaded = (isLoad: boolean) => { + holidayFireworksLoaded.value = isLoad + } + + /** + * 设置节日文本显示 + * @param show 是否显示 + */ + const setShowFestivalText = (show: boolean) => { + showFestivalText.value = show + } + + const setFestivalDate = (date: string) => { + festivalDate.value = date + } + + const setDualMenuShowText = (show: boolean) => { + dualMenuShowText.value = show + } + + return { + menuType, + menuOpenWidth, + systemThemeType, + systemThemeMode, + menuThemeType, + systemThemeColor, + boxBorderMode, + uniqueOpened, + showMenuButton, + showFastEnter, + showRefreshButton, + showCrumbs, + autoClose, + showWorkTab, + showLanguage, + showNprogress, + colorWeak, + showSettingGuide, + pageTransition, + tabStyle, + menuOpen, + refresh, + watermarkVisible, + customRadius, + holidayFireworksLoaded, + showFestivalText, + festivalDate, + dualMenuShowText, + containerWidth, + getMenuTheme, + isDark, + getMenuOpenWidth, + getCustomRadius, + isShowFireworks, + switchMenuLayouts, + setMenuOpenWidth, + setGlopTheme, + switchMenuStyles, + setElementTheme, + setBorderMode, + setContainerWidth, + setUniqueOpened, + setButton, + setFastEnter, + setAutoClose, + setShowRefreshButton, + setCrumbs, + setWorkTab, + setLanguage, + setNprogress, + setColorWeak, + hideSettingGuide, + openSettingGuide, + setPageTransition, + setTabStyle, + setMenuOpen, + reload, + setWatermarkVisible, + setCustomRadius, + setholidayFireworksLoaded, + setShowFestivalText, + setFestivalDate, + setDualMenuShowText + } + }, + { + persist: { + key: 'setting', + storage: localStorage + } + } +) diff --git a/src/store/modules/table.ts b/src/store/modules/table.ts new file mode 100644 index 0000000..094c310 --- /dev/null +++ b/src/store/modules/table.ts @@ -0,0 +1,97 @@ +/** + * 表格状态管理模块 + * + * 提供表格显示配置的状态管理 + * + * ## 主要功能 + * + * - 表格尺寸配置(紧凑、默认、宽松) + * - 斑马纹显示开关 + * - 边框显示开关 + * - 表头背景显示开关 + * - 全屏模式开关 + * + * ## 使用场景 + * - 表格组件样式配置 + * - 用户表格偏好设置 + * - 表格工具栏功能控制 + * + * ## 持久化 + * + * - 使用 localStorage 存储 + * - 存储键:sys-v{version}-table + * - 用户配置跨页面保持 + * + * @module store/modules/table + * @author Art Design Pro Team + */ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { TableSizeEnum } from '@/enums/formEnum' + +// 表格 +export const useTableStore = defineStore( + 'tableStore', + () => { + // 表格大小 + const tableSize = ref(TableSizeEnum.DEFAULT) + // 斑马纹 + const isZebra = ref(false) + // 边框 + const isBorder = ref(false) + // 表头背景 + const isHeaderBackground = ref(false) + + // 是否全屏 + const isFullScreen = ref(false) + + /** + * 设置表格大小 + * @param size 表格大小枚举值 + */ + const setTableSize = (size: TableSizeEnum) => (tableSize.value = size) + + /** + * 设置斑马纹显示状态 + * @param value 是否显示斑马纹 + */ + const setIsZebra = (value: boolean) => (isZebra.value = value) + + /** + * 设置表格边框显示状态 + * @param value 是否显示边框 + */ + const setIsBorder = (value: boolean) => (isBorder.value = value) + + /** + * 设置表头背景显示状态 + * @param value 是否显示表头背景 + */ + const setIsHeaderBackground = (value: boolean) => (isHeaderBackground.value = value) + + /** + * 设置是否全屏 + * @param value 是否全屏 + */ + const setIsFullScreen = (value: boolean) => (isFullScreen.value = value) + + return { + tableSize, + isZebra, + isBorder, + isHeaderBackground, + setTableSize, + setIsZebra, + setIsBorder, + setIsHeaderBackground, + isFullScreen, + setIsFullScreen + } + }, + { + persist: { + key: 'table', + storage: localStorage + } + } +) diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts new file mode 100644 index 0000000..08f7684 --- /dev/null +++ b/src/store/modules/user.ts @@ -0,0 +1,235 @@ +/** + * 用户状态管理模块 + * + * 提供用户相关的状态管理 + * + * ## 主要功能 + * + * - 用户登录状态管理 + * - 用户信息存储 + * - 访问令牌和刷新令牌管理 + * - 语言设置 + * - 搜索历史记录 + * - 锁屏状态和密码管理 + * - 登出清理逻辑 + * + * ## 使用场景 + * + * - 用户登录和认证 + * - 权限验证 + * - 个人信息展示 + * - 多语言切换 + * - 锁屏功能 + * - 搜索历史管理 + * + * ## 持久化 + * + * - 使用 localStorage 存储 + * - 存储键:sys-v{version}-user + * - 登出时自动清理 + * + * @module store/modules/user + * @author Art Design Pro Team + */ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import { LanguageEnum } from '@/enums/appEnum' +import { router } from '@/router' +import { useSettingStore } from './setting' +import { useWorktabStore } from './worktab' +import { AppRouteRecord } from '@/types/router' +import { setPageTitle } from '@/utils/router' +import { resetRouterState } from '@/router/guards/beforeEach' +import { useMenuStore } from './menu' +import { StorageConfig } from '@/utils/storage/storage-config' + +/** + * 用户状态管理 + * 管理用户登录状态、个人信息、语言设置、搜索历史、锁屏状态等 + */ +export const useUserStore = defineStore( + 'userStore', + () => { + // 语言设置 + const language = ref(LanguageEnum.ZH) + // 登录状态 + const isLogin = ref(false) + // 锁屏状态 + const isLock = ref(false) + // 锁屏密码 + const lockPassword = ref('') + // 用户信息 + const info = ref>({}) + // 搜索历史记录 + const searchHistory = ref([]) + // 访问令牌 + const accessToken = ref('') + // 刷新令牌 + const refreshToken = ref('') + + // 计算属性:获取用户信息 + const getUserInfo = computed(() => info.value) + // 计算属性:获取设置状态 + const getSettingState = computed(() => useSettingStore().$state) + // 计算属性:获取工作台状态 + const getWorktabState = computed(() => useWorktabStore().$state) + + /** + * 设置用户信息 + * @param newInfo 新的用户信息 + */ + const setUserInfo = (newInfo: Api.Auth.UserInfo) => { + info.value = newInfo + } + + /** + * 设置登录状态 + * @param status 登录状态 + */ + const setLoginStatus = (status: boolean) => { + isLogin.value = status + } + + /** + * 设置语言 + * @param lang 语言枚举值 + */ + const setLanguage = (lang: LanguageEnum) => { + setPageTitle(router.currentRoute.value) + language.value = lang + } + + /** + * 设置搜索历史 + * @param list 搜索历史列表 + */ + const setSearchHistory = (list: AppRouteRecord[]) => { + searchHistory.value = list + } + + /** + * 设置锁屏状态 + * @param status 锁屏状态 + */ + const setLockStatus = (status: boolean) => { + isLock.value = status + } + + /** + * 设置锁屏密码 + * @param password 锁屏密码 + */ + const setLockPassword = (password: string) => { + lockPassword.value = password + } + + /** + * 设置令牌 + * @param newAccessToken 访问令牌 + * @param newRefreshToken 刷新令牌(可选) + */ + const setToken = (newAccessToken: string, newRefreshToken?: string) => { + accessToken.value = newAccessToken + if (newRefreshToken) { + refreshToken.value = newRefreshToken + } + } + + /** + * 退出登录 + * 清空所有用户相关状态并跳转到登录页 + * 如果是同一账号重新登录,保留工作台标签页 + */ + const logOut = () => { + // 保存当前用户 ID,用于下次登录时判断是否为同一用户 + const currentUserId = info.value.userId + if (currentUserId) { + localStorage.setItem(StorageConfig.LAST_USER_ID_KEY, String(currentUserId)) + } + + // 清空用户信息 + info.value = {} + // 重置登录状态 + isLogin.value = false + // 重置锁屏状态 + isLock.value = false + // 清空锁屏密码 + lockPassword.value = '' + // 清空访问令牌 + accessToken.value = '' + // 清空刷新令牌 + refreshToken.value = '' + // 注意:不清空工作台标签页,等下次登录时根据用户判断 + // 移除iframe路由缓存 + sessionStorage.removeItem('iframeRoutes') + // 清空主页路径 + useMenuStore().setHomePath('') + // 重置路由状态 + resetRouterState(500) + // 跳转到登录页,携带当前路由作为 redirect 参数 + const currentRoute = router.currentRoute.value + const redirect = currentRoute.path !== '/login' ? currentRoute.fullPath : undefined + router.push({ + name: 'Login', + query: redirect ? { redirect } : undefined + }) + } + + /** + * 检查并清理工作台标签页 + * 如果不是同一用户登录,清空工作台标签页 + * 应在登录成功后调用 + */ + const checkAndClearWorktabs = () => { + const lastUserId = localStorage.getItem(StorageConfig.LAST_USER_ID_KEY) + const currentUserId = info.value.userId + + // 无法获取当前用户 ID,跳过检查 + if (!currentUserId) return + + // 首次登录或缓存已清除,保留现有标签页 + if (!lastUserId) { + return + } + + // 不同用户登录,清空工作台标签页 + if (String(currentUserId) !== lastUserId) { + const worktabStore = useWorktabStore() + worktabStore.opened = [] + worktabStore.keepAliveExclude = [] + } + + // 清除临时存储 + localStorage.removeItem(StorageConfig.LAST_USER_ID_KEY) + } + + return { + language, + isLogin, + isLock, + lockPassword, + info, + searchHistory, + accessToken, + refreshToken, + getUserInfo, + getSettingState, + getWorktabState, + setUserInfo, + setLoginStatus, + setLanguage, + setSearchHistory, + setLockStatus, + setLockPassword, + setToken, + logOut, + checkAndClearWorktabs + } + }, + { + persist: { + key: 'user', + storage: localStorage + } + } +) diff --git a/src/store/modules/worktab.ts b/src/store/modules/worktab.ts new file mode 100644 index 0000000..caa0d90 --- /dev/null +++ b/src/store/modules/worktab.ts @@ -0,0 +1,568 @@ +/** + * 工作标签页状态管理模块 + * + * 提供多标签页功能的完整状态管理 + * + * ## 主要功能 + * + * - 标签页打开和关闭 + * - 标签页固定和取消固定 + * - 批量关闭(左侧、右侧、其他、全部) + * - 标签页缓存管理(KeepAlive) + * - 标签页标题自定义 + * - 标签页路由验证 + * - 动态路由参数处理 + * + * ## 使用场景 + * + * - 多标签页导航 + * - 页面缓存控制 + * - 标签页右键菜单 + * - 固定常用页面 + * - 批量关闭标签 + * + * ## 核心特性 + * + * - 智能标签页复用(同路由名称复用) + * - 固定标签页保护(不可关闭) + * - KeepAlive 缓存排除管理 + * - 路由有效性验证 + * - 首页自动保留 + * + * ## 持久化 + * - 使用 localStorage 存储 + * - 存储键:sys-v{version}-worktab + * - 刷新页面保持标签状态 + * + * @module store/modules/worktab + * @author Art Design Pro Team + */ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import { router } from '@/router' +import { LocationQueryRaw, Router } from 'vue-router' +import { WorkTab } from '@/types' +import { useCommon } from '@/hooks/core/useCommon' + +interface WorktabState { + current: Partial + opened: WorkTab[] + keepAliveExclude: string[] +} + +/** + * 工作台标签页管理 Store + */ +export const useWorktabStore = defineStore( + 'worktabStore', + () => { + // 状态定义 + const current = ref>({}) + const opened = ref([]) + const keepAliveExclude = ref([]) + + // 计算属性 + const hasOpenedTabs = computed(() => opened.value.length > 0) + const hasMultipleTabs = computed(() => opened.value.length > 1) + const currentTabIndex = computed(() => + current.value.path ? opened.value.findIndex((tab) => tab.path === current.value.path) : -1 + ) + + /** + * 查找标签页索引 + */ + const findTabIndex = (path: string): number => { + return opened.value.findIndex((tab) => tab.path === path) + } + + /** + * 获取标签页 + */ + const getTab = (path: string): WorkTab | undefined => { + return opened.value.find((tab) => tab.path === path) + } + + /** + * 检查标签页是否可关闭 + */ + const isTabClosable = (tab: WorkTab): boolean => { + return !tab.fixedTab + } + + /** + * 安全的路由跳转 + */ + const safeRouterPush = (tab: Partial): void => { + if (!tab.path) { + console.warn('尝试跳转到无效路径的标签页') + return + } + + try { + router.push({ + path: tab.path, + query: tab.query as LocationQueryRaw + }) + } catch (error) { + console.error('路由跳转失败:', error) + } + } + + /** + * 打开或激活一个选项卡 + */ + const openTab = (tab: WorkTab): void => { + if (!tab.path) { + console.warn('尝试打开无效的标签页') + return + } + + // 从 keepAlive 排除列表中移除 + if (tab.name) { + removeKeepAliveExclude(tab.name) + } + + // 先根据路由名称查找(应对动态路由参数导致的多开问题),找不到再根据路径查找 + let existingIndex = -1 + if (tab.name) { + existingIndex = opened.value.findIndex((t) => t.name === tab.name) + } + if (existingIndex === -1) { + existingIndex = findTabIndex(tab.path) + } + + if (existingIndex === -1) { + // 新增标签页 + const insertIndex = tab.fixedTab ? findFixedTabInsertIndex() : opened.value.length + const newTab = { ...tab } + + if (tab.fixedTab) { + opened.value.splice(insertIndex, 0, newTab) + } else { + opened.value.push(newTab) + } + + current.value = newTab + } else { + // 更新现有标签页(当动态路由参数或查询变更时,复用同一标签) + const existingTab = opened.value[existingIndex] + + opened.value[existingIndex] = { + ...existingTab, + path: tab.path, + params: tab.params, + query: tab.query, + title: tab.title || existingTab.title, + fixedTab: tab.fixedTab ?? existingTab.fixedTab, + keepAlive: tab.keepAlive ?? existingTab.keepAlive, + name: tab.name || existingTab.name, + icon: tab.icon || existingTab.icon + } + + current.value = opened.value[existingIndex] + } + } + + /** + * 查找固定标签页的插入位置 + */ + const findFixedTabInsertIndex = (): number => { + let insertIndex = 0 + for (let i = 0; i < opened.value.length; i++) { + if (opened.value[i].fixedTab) { + insertIndex = i + 1 + } else { + break + } + } + return insertIndex + } + + /** + * 关闭指定的选项卡 + */ + const removeTab = (path: string): void => { + const targetTab = getTab(path) + const targetIndex = findTabIndex(path) + + if (targetIndex === -1) { + console.warn(`尝试关闭不存在的标签页: ${path}`) + return + } + + if (targetTab && !isTabClosable(targetTab)) { + console.warn(`尝试关闭固定标签页: ${path}`) + return + } + + // 从标签页列表中移除 + opened.value.splice(targetIndex, 1) + + // 处理缓存排除 + if (targetTab?.name) { + addKeepAliveExclude(targetTab) + } + + const { homePath } = useCommon() + + // 如果关闭后无标签页,跳转首页 + if (!hasOpenedTabs.value) { + if (path !== homePath.value) { + current.value = {} + safeRouterPush({ path: homePath.value }) + } + return + } + + // 如果关闭的是当前激活标签,需要激活其他标签 + if (current.value.path === path) { + const newIndex = targetIndex >= opened.value.length ? opened.value.length - 1 : targetIndex + current.value = opened.value[newIndex] + safeRouterPush(current.value) + } + } + + /** + * 关闭左侧选项卡 + */ + const removeLeft = (path: string): void => { + const targetIndex = findTabIndex(path) + + if (targetIndex === -1) { + console.warn(`尝试关闭左侧标签页,但目标标签页不存在: ${path}`) + return + } + + // 获取左侧可关闭的标签页 + const leftTabs = opened.value.slice(0, targetIndex) + const closableLeftTabs = leftTabs.filter(isTabClosable) + + if (closableLeftTabs.length === 0) { + console.warn('左侧没有可关闭的标签页') + return + } + + // 标记为缓存排除 + markTabsToRemove(closableLeftTabs) + + // 移除左侧可关闭的标签页 + opened.value = opened.value.filter( + (tab, index) => index >= targetIndex || !isTabClosable(tab) + ) + + // 确保当前标签是激活状态 + const targetTab = getTab(path) + if (targetTab) { + current.value = targetTab + } + } + + /** + * 关闭右侧选项卡 + */ + const removeRight = (path: string): void => { + const targetIndex = findTabIndex(path) + + if (targetIndex === -1) { + console.warn(`尝试关闭右侧标签页,但目标标签页不存在: ${path}`) + return + } + + // 获取右侧可关闭的标签页 + const rightTabs = opened.value.slice(targetIndex + 1) + const closableRightTabs = rightTabs.filter(isTabClosable) + + if (closableRightTabs.length === 0) { + console.warn('右侧没有可关闭的标签页') + return + } + + // 标记为缓存排除 + markTabsToRemove(closableRightTabs) + + // 移除右侧可关闭的标签页 + opened.value = opened.value.filter( + (tab, index) => index <= targetIndex || !isTabClosable(tab) + ) + + // 确保当前标签是激活状态 + const targetTab = getTab(path) + if (targetTab) { + current.value = targetTab + } + } + + /** + * 关闭其他选项卡 + */ + const removeOthers = (path: string): void => { + const targetTab = getTab(path) + + if (!targetTab) { + console.warn(`尝试关闭其他标签页,但目标标签页不存在: ${path}`) + return + } + + // 获取其他可关闭的标签页 + const otherTabs = opened.value.filter((tab) => tab.path !== path) + const closableTabs = otherTabs.filter(isTabClosable) + + if (closableTabs.length === 0) { + console.warn('没有其他可关闭的标签页') + return + } + + // 标记为缓存排除 + markTabsToRemove(closableTabs) + + // 只保留当前标签和固定标签 + opened.value = opened.value.filter((tab) => tab.path === path || !isTabClosable(tab)) + + // 确保当前标签是激活状态 + current.value = targetTab + } + + /** + * 关闭所有可关闭的标签页 + */ + const removeAll = (): void => { + const { homePath } = useCommon() + const hasFixedTabs = opened.value.some((tab) => tab.fixedTab) + + // 获取可关闭的标签页 + const closableTabs = opened.value.filter((tab) => { + if (!isTabClosable(tab)) return false + // 如果有固定标签,则所有可关闭的都可以关闭;否则保留首页 + return hasFixedTabs || tab.path !== homePath.value + }) + + if (closableTabs.length === 0) { + console.warn('没有可关闭的标签页') + return + } + + // 标记为缓存排除 + markTabsToRemove(closableTabs) + + // 保留不可关闭的标签页和首页(当没有固定标签时) + opened.value = opened.value.filter((tab) => { + return !isTabClosable(tab) || (!hasFixedTabs && tab.path === homePath.value) + }) + + // 处理激活状态 + if (!hasOpenedTabs.value) { + current.value = {} + safeRouterPush({ path: homePath.value }) + return + } + + // 选择激活的标签页:优先首页,其次第一个可用标签 + const homeTab = opened.value.find((tab) => tab.path === homePath.value) + const targetTab = homeTab || opened.value[0] + + current.value = targetTab + safeRouterPush(targetTab) + } + + /** + * 将指定选项卡添加到 keepAlive 排除列表中 + */ + const addKeepAliveExclude = (tab: WorkTab): void => { + if (!tab.keepAlive || !tab.name) return + + if (!keepAliveExclude.value.includes(tab.name)) { + keepAliveExclude.value.push(tab.name) + } + } + + /** + * 从 keepAlive 排除列表中移除指定组件名称 + */ + const removeKeepAliveExclude = (name: string): void => { + if (!name) return + + keepAliveExclude.value = keepAliveExclude.value.filter((item) => item !== name) + } + + /** + * 将传入的一组选项卡的组件名称标记为排除缓存 + */ + const markTabsToRemove = (tabs: WorkTab[]): void => { + tabs.forEach((tab) => { + if (tab.name) { + addKeepAliveExclude(tab) + } + }) + } + + /** + * 切换指定标签页的固定状态 + */ + const toggleFixedTab = (path: string): void => { + const targetIndex = findTabIndex(path) + + if (targetIndex === -1) { + console.warn(`尝试切换不存在标签页的固定状态: ${path}`) + return + } + + const tab = { ...opened.value[targetIndex] } + tab.fixedTab = !tab.fixedTab + + // 移除原位置 + opened.value.splice(targetIndex, 1) + + if (tab.fixedTab) { + // 固定标签插入到所有固定标签的末尾 + const firstNonFixedIndex = opened.value.findIndex((t) => !t.fixedTab) + const insertIndex = firstNonFixedIndex === -1 ? opened.value.length : firstNonFixedIndex + opened.value.splice(insertIndex, 0, tab) + } else { + // 非固定标签插入到所有固定标签后 + const fixedCount = opened.value.filter((t) => t.fixedTab).length + opened.value.splice(fixedCount, 0, tab) + } + + // 更新当前标签引用 + if (current.value.path === path) { + current.value = tab + } + } + + /** + * 验证工作台标签页的路由有效性 + */ + const validateWorktabs = (routerInstance: Router): void => { + try { + // 动态路由校验:优先使用路由 name 判断有效性;否则用 resolve 匹配参数化路径 + const isTabRouteValid = (tab: Partial): boolean => { + try { + if (tab.name) { + const routes = routerInstance.getRoutes() + if (routes.some((r) => r.name === tab.name)) return true + } + if (tab.path) { + const resolved = routerInstance.resolve({ + path: tab.path, + query: (tab.query as LocationQueryRaw) || undefined + }) + return resolved.matched.length > 0 + } + return false + } catch { + return false + } + } + + // 过滤出有效的标签页 + const validTabs = opened.value.filter((tab) => isTabRouteValid(tab)) + + if (validTabs.length !== opened.value.length) { + console.warn('发现无效的标签页路由,已自动清理') + opened.value = validTabs + } + + // 验证当前激活标签的有效性 + const isCurrentValid = current.value && isTabRouteValid(current.value) + + if (!isCurrentValid && validTabs.length > 0) { + console.warn('当前激活标签无效,已自动切换') + current.value = validTabs[0] + } else if (!isCurrentValid) { + current.value = {} + } + } catch (error) { + console.error('验证工作台标签页失败:', error) + } + } + + /** + * 清空所有状态(用于登出等场景) + */ + const clearAll = (): void => { + current.value = {} + opened.value = [] + keepAliveExclude.value = [] + } + + /** + * 获取状态快照(用于持久化存储) + */ + const getStateSnapshot = (): WorktabState => { + return { + current: { ...current.value }, + opened: [...opened.value], + keepAliveExclude: [...keepAliveExclude.value] + } + } + + /** + * 获取标签页标题 + */ + const getTabTitle = (path: string): WorkTab | undefined => { + const tab = getTab(path) + return tab + } + + /** + * 更新标签页标题 + */ + const updateTabTitle = (path: string, title: string): void => { + const tab = getTab(path) + if (tab) { + tab.customTitle = title + } + } + + /** + * 重置标签页标题 + */ + const resetTabTitle = (path: string): void => { + const tab = getTab(path) + if (tab) { + tab.customTitle = '' + } + } + + return { + // 状态 + current, + opened, + keepAliveExclude, + + // 计算属性 + hasOpenedTabs, + hasMultipleTabs, + currentTabIndex, + + // 方法 + openTab, + removeTab, + removeLeft, + removeRight, + removeOthers, + removeAll, + toggleFixedTab, + validateWorktabs, + clearAll, + getStateSnapshot, + + // 工具方法 + findTabIndex, + getTab, + isTabClosable, + addKeepAliveExclude, + removeKeepAliveExclude, + markTabsToRemove, + getTabTitle, + updateTabTitle, + resetTabTitle + } + }, + { + persist: { + key: 'worktab', + storage: localStorage + } + } +) diff --git a/src/types/api/api.d.ts b/src/types/api/api.d.ts new file mode 100644 index 0000000..fd3abbb --- /dev/null +++ b/src/types/api/api.d.ts @@ -0,0 +1,135 @@ +/** + * API 接口类型定义模块 + * + * 提供所有后端接口的类型定义 + * + * ## 主要功能 + * + * - 通用类型(分页参数、响应结构等) + * - 认证类型(登录、用户信息等) + * - 系统管理类型(用户、角色等) + * - 全局命名空间声明 + * + * ## 使用场景 + * + * - API 请求参数类型约束 + * - API 响应数据类型定义 + * - 接口文档类型同步 + * + * ## 注意事项 + * + * - 在 .vue 文件使用需要在 eslint.config.mjs 中配置 globals: { Api: 'readonly' } + * - 使用全局命名空间,无需导入即可使用 + * + * ## 使用方式 + * + * ```typescript + * const params: Api.Auth.LoginParams = { userName: 'admin', password: '123456' } + * const response: Api.Auth.UserInfo = await fetchUserInfo() + * ``` + * + * @module types/api/api + * @author Art Design Pro Team + */ + +declare namespace Api { + /** 通用类型 */ + namespace Common { + /** 分页参数 */ + interface PaginationParams { + /** 当前页码 */ + current: number + /** 每页条数 */ + size: number + /** 总条数 */ + total: number + } + + /** 通用搜索参数 */ + type CommonSearchParams = Pick + + /** 分页响应基础结构 */ + interface PaginatedResponse { + records: T[] + current: number + size: number + total: number + } + + /** 启用状态 */ + type EnableStatus = '1' | '2' + } + + /** 认证类型 */ + namespace Auth { + /** 登录参数 */ + interface LoginParams { + userName: string + password: string + } + + /** 登录响应 */ + interface LoginResponse { + token: string + refreshToken: string + } + + /** 用户信息 */ + interface UserInfo { + buttons: string[] + roles: string[] + userId: number + userName: string + email: string + avatar?: string + } + } + + /** 系统管理类型 */ + namespace SystemManage { + /** 用户列表 */ + type UserList = Api.Common.PaginatedResponse + + /** 用户列表项 */ + interface UserListItem { + id: number + avatar: string + status: string + userName: string + userGender: string + nickName: string + userPhone: string + userEmail: string + userRoles: string[] + createBy: string + createTime: string + updateBy: string + updateTime: string + } + + /** 用户搜索参数 */ + type UserSearchParams = Partial< + Pick & + Api.Common.CommonSearchParams + > + + /** 角色列表 */ + type RoleList = Api.Common.PaginatedResponse + + /** 角色列表项 */ + interface RoleListItem { + roleId: number + roleName: string + roleCode: string + description: string + enabled: boolean + createTime: string + } + + /** 角色搜索参数 */ + type RoleSearchParams = Partial< + Pick & + Api.Common.CommonSearchParams + > + } +} diff --git a/src/types/common/index.ts b/src/types/common/index.ts new file mode 100644 index 0000000..7e751d1 --- /dev/null +++ b/src/types/common/index.ts @@ -0,0 +1,95 @@ +/** + * 通用类型定义模块 + * + * 提供项目中常用的通用类型定义 + * + * ## 主要功能 + * + * - 状态类型(启用/禁用) + * - 性别类型 + * - 排序方向类型 + * - 操作类型(增删改查) + * - 记录类型(键值对) + * - 时间范围类型 + * - 文件信息类型 + * - 坐标和尺寸类型 + * - 响应式断点类型 + * - 主题和语言类型 + * - 环境和弹窗类型 + * + * ## 使用场景 + * + * - 通用数据结构定义 + * - 类型约束和提示 + * - 减少重复类型定义 + * + * @module types/common/index + * @author Art Design Pro Team + */ + +// 导出响应类型 +export * from './response' + +// 状态类型 +export type Status = 0 | 1 // 0: 禁用, 1: 启用 + +// 性别类型 +export type Gender = 'male' | 'female' | 'unknown' + +// 排序方向 +export type SortOrder = 'ascending' | 'descending' + +// 操作类型 +export type ActionType = 'create' | 'update' | 'delete' | 'view' + +// 可选的记录类型 +export type Recordable = Record + +// 键值对类型 +export type KeyValue = { + key: string + value: T + label?: string +} + +// 时间范围类型 +export interface TimeRange { + startTime: string + endTime: string +} + +// 文件类型 +export interface FileInfo { + name: string + url: string + size: number + type: string + lastModified?: number +} + +// 坐标类型 +export interface Position { + x: number + y: number +} + +// 尺寸类型 +export interface Size { + width: number + height: number +} + +// 响应式断点类型 +export type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl' + +// 主题类型 +export type ThemeMode = 'light' | 'dark' | 'auto' + +// 语言类型 +export type Language = 'zh-CN' | 'en-US' + +// 环境类型 +export type Environment = 'development' | 'production' | 'test' + +// 弹窗类型 +export type DialogType = 'add' | 'edit' diff --git a/src/types/common/response.ts b/src/types/common/response.ts new file mode 100644 index 0000000..4a5fdab --- /dev/null +++ b/src/types/common/response.ts @@ -0,0 +1,30 @@ +/** + * API 响应类型定义模块 + * + * 提供统一的 API 响应结构类型定义 + * + * ## 主要功能 + * + * - 基础响应结构定义 + * - 泛型支持(适配不同数据类型) + * - 统一的响应格式约束 + * + * ## 使用场景 + * + * - API 请求响应类型约束 + * - 接口数据类型定义 + * - 响应数据解析 + * + * @module types/common/response + * @author Art Design Pro Team + */ + +/** 基础 API 响应结构 */ +export interface BaseResponse { + /** 状态码 */ + code: number + /** 消息 */ + msg: string + /** 数据 */ + data: T +} diff --git a/src/types/component/chart.ts b/src/types/component/chart.ts new file mode 100644 index 0000000..c3225c9 --- /dev/null +++ b/src/types/component/chart.ts @@ -0,0 +1,324 @@ +/** + * 图表组件类型定义模块 + * + * 提供 ECharts 图表组件的完整类型定义 + * + * ## 主要功能 + * + * - 基础图表配置类型 + * - 柱状图类型定义 + * - 折线图类型定义 + * - 饼图/环形图类型定义 + * - 雷达图类型定义 + * - K线图类型定义 + * - 散点图类型定义 + * - 地图图表类型定义 + * - 双向堆叠柱状图类型定义 + * - 图表主题配置类型 + * - 图表事件回调类型 + * + * ## 使用场景 + * + * - 图表组件 Props 类型约束 + * - 图表配置类型定义 + * - 图表数据结构定义 + * - 图表事件处理 + * + * @module types/component/chart + * @author Art Design Pro Team + */ +import type { EChartsOption } from '@/plugins/echarts' + +// 图例位置类型 +export type LegendPosition = 'bottom' | 'top' | 'left' | 'right' + +export type SymbolType = + | 'circle' + | 'rect' + | 'roundRect' + | 'triangle' + | 'diamond' + | 'pin' + | 'arrow' + | 'none' + +// 图表主题配置 +export interface ChartThemeConfig { + /** 图表高度 */ + chartHeight: string + /** 字体大小 */ + fontSize: number + /** 字体颜色 */ + fontColor: string + /** 主题颜色 */ + themeColor: string + /** 颜色组 */ + colors: string[] +} + +// 图表初始化选项 +export interface UseChartOptions { + /** 初始化选项 */ + initOptions?: EChartsOption + /** 延迟初始化时间(ms) */ + initDelay?: number + /** IntersectionObserver阈值 */ + threshold?: number + /** 是否自动响应主题变化 */ + autoTheme?: boolean +} + +// 基础图表 Props 接口 - 统一所有图表的基础属性 +export interface BaseChartProps { + /** 图表高度 */ + height?: string + /** 是否加载中 */ + loading?: boolean + isEmpty?: boolean + /** 颜色配置 */ + colors?: string[] +} + +// 轴线显示控制接口 - 统一轴线相关配置 +export interface AxisDisplayProps { + /** 是否显示坐标轴标签 */ + showAxisLabel?: boolean + /** 是否显示坐标轴线 */ + showAxisLine?: boolean + /** 是否显示分割线 */ + showSplitLine?: boolean +} + +// 交互显示控制接口 - 统一交互相关配置 +export interface InteractionProps { + /** 是否显示提示框 */ + showTooltip?: boolean + /** 是否显示图例 */ + showLegend?: boolean + /** 图例位置 */ + legendPosition?: LegendPosition +} + +// 柱状图数据项接口 +export interface BarDataItem { + /** 系列名称 */ + name: string + /** 数据值 */ + data: number[] + /** 柱状图宽度 */ + barWidth?: string | number + /** 堆叠分组名称 */ + stack?: string +} + +// 柱状图 Props 接口 - 统一柱状图配置 +export interface BarChartProps extends BaseChartProps, AxisDisplayProps, InteractionProps { + /** 图表数据 - 支持单组数据或多组数据 */ + data: number[] | BarDataItem[] + /** X轴标签数据 */ + xAxisData?: string[] + /** 柱状图宽度 */ + barWidth?: string | number + /** 是否堆叠显示 */ + stack?: boolean + /** 圆角 */ + borderRadius?: number | number[] +} + +// 折线图数据项接口 +export interface LineDataItem { + /** 系列名称 */ + name: string + /** 数据值 */ + data: number[] + /** 线条宽度 */ + lineWidth?: number + /** 是否显示区域填充 */ + showAreaColor?: boolean + /** 区域样式配置 */ + areaStyle?: { + /** 渐变开始透明度 */ + startOpacity?: number + /** 渐变结束透明度 */ + endOpacity?: number + /** 自定义 ECharts areaStyle 配置 */ + custom?: any + } + /** 是否平滑曲线 */ + smooth?: boolean + /** 数据点符号 */ + symbol?: SymbolType + /** 数据点大小 */ + symbolSize?: number +} + +// 折线图 Props 接口 - 统一折线图配置 +export interface LineChartProps extends BaseChartProps, AxisDisplayProps, InteractionProps { + /** 图表数据 - 支持单组数据或多组数据 */ + data: number[] | LineDataItem[] + /** X轴标签数据 */ + xAxisData?: string[] + /** 线条宽度 */ + lineWidth?: number + /** 是否显示区域填充 */ + showAreaColor?: boolean + /** 是否平滑曲线 */ + smooth?: boolean + /** 数据点符号 */ + symbol?: SymbolType + /** 数据点大小 */ + symbolSize?: number + /** 多数据动画延迟间隔(毫秒) */ + animationDelay?: number +} + +// 雷达图数据项接口 +export interface RadarDataItem { + /** 系列名称 */ + name: string + /** 数据值 */ + value: number[] +} + +// 雷达图 Props 接口 - 统一雷达图配置 +export interface RadarChartProps extends BaseChartProps, InteractionProps { + /** 雷达图指标配置 */ + indicator?: Array<{ name: string; max: number }> + /** 图表数据 */ + data?: RadarDataItem[] +} + +// 饼图/环形图数据项接口 +export interface PieDataItem { + /** 数据值 */ + value: number + /** 数据名称 */ + name: string +} + +// 环形图 Props 接口 - 统一环形图配置 +export interface RingChartProps extends BaseChartProps, InteractionProps { + /** 图表数据 */ + data: PieDataItem[] + /** 内外半径 */ + radius?: string[] + /** 边框圆角 */ + borderRadius?: number + /** 中心文本 */ + centerText?: string + /** 是否显示标签 */ + showLabel?: boolean +} + +// K线图数据项接口 +export interface KLineDataItem { + /** 时间标签 */ + time: string + /** 开盘价 */ + open: number + /** 收盘价 */ + close: number + /** 最高价 */ + high: number + /** 最低价 */ + low: number +} + +// K线图 Props 接口 - 统一K线图配置 +export interface KLineChartProps extends BaseChartProps { + /** 图表数据 */ + data?: KLineDataItem[] + /** 是否显示数据缩放控件 */ + showDataZoom?: boolean + /** 数据缩放初始开始位置 */ + dataZoomStart?: number + /** 数据缩放初始结束位置 */ + dataZoomEnd?: number +} + +// 散点图数据项接口 +export interface ScatterDataItem { + /** 坐标值 [x, y] */ + value: number[] +} + +// 散点图 Props 接口 - 统一散点图配置 +export interface ScatterChartProps extends BaseChartProps, AxisDisplayProps, InteractionProps { + /** 图表数据 */ + data?: ScatterDataItem[] + /** 散点大小 */ + symbolSize?: number +} + +// 双柱对比图 Props 接口 - 统一双柱对比图配置 +export interface DualBarCompareChartProps extends BaseChartProps { + /** 上方数据 */ + topData: number[] + /** 下方数据 */ + bottomData: number[] + /** X轴标签数据 */ + xAxisData: string[] + /** 上方柱子颜色 */ + topColor?: string + /** 下方柱子颜色 */ + bottomColor?: string + /** 柱状图宽度 */ + barWidth?: number +} + +// 地图图表 Props 接口 - 统一地图图表配置 +export interface MapChartProps extends BaseChartProps { + /** 地图数据 */ + mapData?: any[] + /** 选中区域 */ + selectedRegion?: string + /** 是否显示标签 */ + showLabels?: boolean + /** 是否显示散点 */ + showScatter?: boolean +} + +// 双向堆叠柱状图 Props 接口(人口金字塔样式) +export interface BidirectionalBarChartProps + extends BaseChartProps, + AxisDisplayProps, + InteractionProps { + /** 正向数据(向上显示) */ + positiveData: number[] + /** 负向数据(向下显示) */ + negativeData: number[] + /** X轴标签数据 */ + xAxisData?: string[] + /** 正向数据名称 */ + positiveName?: string + /** 负向数据名称 */ + negativeName?: string + /** 柱状图宽度 */ + barWidth?: string | number + /** Y轴最小值 */ + yAxisMin?: number + /** Y轴最大值 */ + yAxisMax?: number + /** 是否显示数据标签 */ + showDataLabel?: boolean + /** 正向数据圆角配置 */ + positiveBorderRadius?: number | number[] + /** 负向数据圆角配置 */ + negativeBorderRadius?: number | number[] +} + +// 图表配置生成器函数类型 +export type ChartOptionGenerator = () => EChartsOption + +// 图表事件回调类型 +export type ChartEventCallback = (params: any) => void + +// 图表错误信息接口 +export interface ChartError { + /** 错误码 */ + code: string + /** 错误信息 */ + message: string + /** 错误详情 */ + details?: any +} diff --git a/src/types/component/index.ts b/src/types/component/index.ts new file mode 100644 index 0000000..cd89bce --- /dev/null +++ b/src/types/component/index.ts @@ -0,0 +1,145 @@ +/** + * 组件类型定义模块 + * + * 提供项目组件的类型定义 + * + * ## 主要功能 + * + * - 搜索组件类型定义 + * - 表格列配置类型 + * - 分页配置类型 + * - 表单规则类型 + * - 对话框配置类型 + * + * ## 使用场景 + * + * - 组件 Props 类型约束 + * - 组件配置类型定义 + * - 组件事件参数类型 + * + * @module types/component/index + * @author Art Design Pro Team + */ + +// 搜索组件类型 +export type SearchComponentType = + | 'input' + | 'select' + | 'radio' + | 'checkbox' + | 'date' + | 'datetime' + | 'daterange' + | 'datetimerange' + | 'month' + | 'monthrange' + | 'year' + | 'yearrange' + | 'week' + | 'time' + | 'timerange' + +// 搜索框值变化参数 +export interface SearchChangeParams { + prop: string + val: unknown +} + +// 表格列配置接口 +export interface ColumnOption { + // 列类型 + type?: 'selection' | 'expand' | 'index' | 'globalIndex' + // 列属性名 + prop?: string + // 列标题 + label?: string + // 列宽度 + width?: string | number + // 最小列宽度 + minWidth?: string | number + // 固定列 + fixed?: boolean | 'left' | 'right' + // 是否可排序 + sortable?: boolean + // 过滤器选项 + filters?: any[] + // 过滤方法 + filterMethod?: (value: any, row: any) => boolean + // 过滤器位置 + filterPlacement?: string + // 是否禁用 + disabled?: boolean + // 是否显示列 + visible?: boolean + // 是否选中显示 + checked?: boolean + // 自定义渲染函数 + formatter?: (row: T) => any + // 插槽相关配置 + // 是否使用插槽渲染内容 + useSlot?: boolean + // 插槽名称(默认为 prop 值) + slotName?: string + // 是否使用表头插槽 + useHeaderSlot?: boolean + // 表头插槽名称(默认为 `${prop}-header`) + headerSlotName?: string + // 其他属性 + [key: string]: any +} + +// 分页配置 +export interface PaginationConfig { + // 当前页 + currentPage: number + // 每页条数 + pageSize: number + // 总条数 + total: number + // 每页显示个数选择器的选项 + pageSizes?: number[] + // 组件布局 + layout?: string + // 是否为小型分页 + small?: boolean +} + +// 表单规则 +export interface FormRule { + // 是否必填 + required?: boolean + // 错误提示信息 + message?: string + // 触发方式 + trigger?: string | string[] + // 最小长度 + min?: number + // 最大长度 + max?: number + // 正则表达式 + pattern?: RegExp + // 自定义验证函数 + validator?: (rule: any, value: any, callback: any) => void +} + +// 对话框配置 +export interface DialogConfig { + // 标题 + title: string + // 是否显示 + visible: boolean + // 宽度 + width?: string | number + // 是否可以通过点击 modal 关闭 + closeOnClickModal?: boolean + // 是否可以通过按下 ESC 关闭 + closeOnPressEscape?: boolean + // 是否显示关闭按钮 + showClose?: boolean + // 是否在 Dialog 出现时将 body 滚动锁定 + lockScroll?: boolean + // 是否显示遮罩层 + modal?: boolean + // 自定义类名 + customClass?: string +} diff --git a/src/types/config/index.ts b/src/types/config/index.ts new file mode 100644 index 0000000..dd144de --- /dev/null +++ b/src/types/config/index.ts @@ -0,0 +1,211 @@ +/** + * 配置类型定义模块 + * + * 提供系统配置相关的类型定义 + * + * ## 主要功能 + * + * - 主题设置类型 + * - 菜单布局类型 + * - 节日配置类型 + * - 系统基础配置类型 + * - 快速入口配置类型 + * - 顶部栏功能配置类型 + * - 环境配置类型 + * - 应用配置类型 + * + * ## 使用场景 + * + * - 系统配置文件类型约束 + * - 配置项类型定义 + * - 配置数据验证 + * + * @module types/config/index + * @author Art Design Pro Team + */ + +import { MenuTypeEnum, SystemThemeEnum } from '@/enums/appEnum' +import { MenuThemeType, SystemThemeTypes } from '@/types/store' + +// 主题设置 +export interface ThemeSetting { + /** 主题名称 */ + name: string + /** 系统主题类型 */ + theme: SystemThemeEnum + /** 主题颜色数组 */ + color: string[] + /** 左侧线条颜色 */ + leftLineColor: string + /** 右侧线条颜色 */ + rightLineColor: string + /** 主题图片 */ + img: string +} + +// 菜单布局 +export interface MenuLayout { + /** 布局名称 */ + name: string + /** 菜单类型值 */ + value: MenuTypeEnum + /** 布局预览图 */ + img: string + /** 布局描述 */ + description?: string +} + +// 节日配置 +export interface FestivalConfig { + /** 节日日期(单日)或开始日期(日期范围) */ + date: string + /** 节日结束日期(可选,用于跨日期节日) */ + endDate?: string + /** 节日名称 */ + name: string + /** 烟花图片 */ + image: string + /** 滚动文本 */ + scrollText: string + /** 是否激活 */ + isActive?: boolean + /** 烟花播放次数(可选,默认为 3 次) */ + count?: number +} + +// 系统基础配置 +export interface SystemBasicConfig { + // 系统名称 + name: string + // 系统描述 + description?: string + // 系统logo + logo?: string + // 系统favicon + favicon?: string + // 版权信息 + copyright?: string +} + +// 快速入口基础项 +export interface FastEnterBaseItem { + /** 名称 */ + name: string + /** 是否启用 */ + enabled?: boolean + /** 排序权重 */ + order?: number + /** 路由名称 */ + routeName?: string + /** 外部链接 */ + link?: string +} + +// 快速入口应用项 +export interface FastEnterApplication extends FastEnterBaseItem { + /** 应用描述 */ + description: string + /** 图标代码 */ + icon: string + /** 图标颜色 */ + iconColor: string +} + +// 快速链接项 +export type FastEnterQuickLink = FastEnterBaseItem + +// 快速入口配置 +export interface FastEnterConfig { + /** 应用列表 */ + applications: FastEnterApplication[] + /** 快速链接 */ + quickLinks: FastEnterQuickLink[] + /** 显示条件(屏幕宽度) */ + minWidth?: number +} + +// 系统配置 +export interface SystemConfig { + // 系统基础信息 + systemInfo: SystemBasicConfig + // 系统主题样式 + systemThemeStyles: SystemThemeTypes + // 设置主题列表 + settingThemeList: ThemeSetting[] + // 菜单布局列表 + menuLayoutList: MenuLayout[] + // 主题列表 + themeList: MenuThemeType[] + // 暗色菜单样式 + darkMenuStyles: MenuThemeType[] + // 系统主色调 + systemMainColor: readonly string[] + // 快速入口配置 + fastEnter?: FastEnterConfig + // 顶部栏功能配置 + headerBar?: HeaderBarFeatureConfig +} + +// 环境配置 +export interface EnvConfig { + // 环境名称 + NODE_ENV: string + // 应用版本 + VITE_VERSION: string + // 应用端口 + VITE_PORT: string + // 应用基础路径 + VITE_BASE_URL: string + // API 地址 + VITE_API_URL: string + // 是否开启 Mock + VITE_USE_MOCK?: string + // 是否开启压缩 + VITE_USE_GZIP?: string + // 是否开启 CDN + VITE_USE_CDN?: string +} + +// 应用配置 +export interface AppConfig extends SystemConfig { + // 环境配置 + env: EnvConfig + // 开发模式 + isDev: boolean + // 生产模式 + isProd: boolean + // 测试模式 + isTest: boolean +} + +// 功能配置项基础接口 +export interface FeatureConfigItem { + enabled: boolean + description: string +} + +// 顶部栏功能配置接口 +export interface HeaderBarFeatureConfig { + /** 菜单按钮 */ + menuButton: FeatureConfigItem + /** 刷新按钮 */ + refreshButton: FeatureConfigItem + /** 快速入口 */ + fastEnter: FeatureConfigItem + /** 面包屑导航 */ + breadcrumb: FeatureConfigItem + /** 全局搜索 */ + globalSearch: FeatureConfigItem + /** 全屏功能 */ + fullscreen: FeatureConfigItem + /** 通知功能 */ + notification: FeatureConfigItem + /** 聊天功能 */ + chat: FeatureConfigItem + /** 多语言切换 */ + language: FeatureConfigItem + /** 设置面板 */ + settings: FeatureConfigItem + /** 主题切换 */ + themeToggle: FeatureConfigItem +} diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..9032fd2 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,22 @@ +/** + * 类型定义统一导出模块 + * 提供全局类型定义的统一导出入口 + * + * @module types/index + * @author Art Design Pro Team + */ + +/** 通用类型定义(基础类型、工具类型等) */ +export * from './common' + +/** 组件相关类型定义 */ +export * from './component' + +/** 状态管理相关类型定义 */ +export * from './store' + +/** 路由相关类型定义 */ +export * from './router' + +/** 配置相关类型定义 */ +export * from './config' diff --git a/src/types/router/index.ts b/src/types/router/index.ts new file mode 100644 index 0000000..d9ef012 --- /dev/null +++ b/src/types/router/index.ts @@ -0,0 +1,80 @@ +/** + * 路由类型定义模块 + * + * 提供路由相关的类型定义 + * + * ## 主要功能 + * + * - 路由元数据类型(标题、图标、权限等) + * - 应用路由记录类型 + * - 路由配置扩展 + * + * ## 使用场景 + * + * - 路由配置类型约束 + * - 路由元数据定义 + * - 菜单生成 + * - 权限控制 + * + * @module types/router/index + * @author Art Design Pro Team + */ + +import { RouteRecordRaw } from 'vue-router' + +/** + * 路由元数据接口 + * 定义路由的各种配置属性 + */ +export interface RouteMeta extends Record { + /** 路由标题 */ + title: string + /** 路由图标 */ + icon?: string + /** 是否显示徽章 */ + showBadge?: boolean + /** 文本徽章 */ + showTextBadge?: string + /** 是否在菜单中隐藏 */ + isHide?: boolean + /** 是否在标签页中隐藏 */ + isHideTab?: boolean + /** 外部链接 */ + link?: string + /** 是否为iframe */ + isIframe?: boolean + /** 是否缓存 */ + keepAlive?: boolean + /** 操作权限 */ + authList?: Array<{ + title: string + authMark: string + }> + /** 是否为一级菜单 */ + isFirstLevel?: boolean + /** 角色权限 */ + roles?: string[] + /** 是否固定标签页 */ + fixedTab?: boolean + /** 激活菜单路径 */ + activePath?: string + /** 是否为全屏页面 */ + isFullPage?: boolean + /** 是否为权限按钮行 */ + isAuthButton?: boolean + /** 权限标识 */ + authMark?: string + /** 父级路径 */ + parentPath?: string +} + +/** + * 应用路由记录接口 + * 扩展 Vue Router 的路由记录类型 + */ +export interface AppRouteRecord extends Omit { + id?: number + meta: RouteMeta + children?: AppRouteRecord[] + component?: string | (() => Promise) +} diff --git a/src/types/store/index.ts b/src/types/store/index.ts new file mode 100644 index 0000000..019801e --- /dev/null +++ b/src/types/store/index.ts @@ -0,0 +1,157 @@ +/** + * Store 状态类型定义模块 + * + * 提供 Pinia Store 的状态类型定义 + * + * ## 主要功能 + * + * - 系统主题类型 + * - 菜单主题类型 + * - 设置状态类型 + * - 工作标签页类型 + * - 用户状态类型 + * - 菜单状态类型 + * - 根状态类型 + * + * ## 使用场景 + * + * - Store 状态类型约束 + * - 状态数据结构定义 + * - 类型提示和自动补全 + * + * @module types/store/index + * @author Art Design Pro Team + */ + +import { MenuThemeEnum, SystemThemeEnum } from '@/enums/appEnum' +import { LocationQueryRaw } from 'vue-router' + +// 系统主题样式(light | dark) +export interface SystemThemeType { + /** 主题类名 */ + className: string +} + +// 定义包含多个主题的类型 +export type SystemThemeTypes = { + [key in Exclude]: SystemThemeType +} + +// 菜单主题样式 +export interface MenuThemeType { + /** 主题类型 */ + theme: MenuThemeEnum + /** 背景颜色 */ + background: string + /** 系统名称颜色 */ + systemNameColor: string + /** 文本颜色 */ + textColor: string + /** 图标颜色 */ + iconColor: string + /** 背景图片 */ + img?: string +} + +// 设置中心 +export interface SettingState { + /** 主题 */ + theme: string + /** 是否只保持一个子菜单的展开 */ + uniqueOpened: boolean + /** 是否显示菜单按钮 */ + menuButton: boolean + /** 是否显示刷新按钮 */ + showRefreshButton: boolean + /** 是否显示面包屑 */ + showCrumbs: boolean + /** 是否自动关闭 */ + autoClose: boolean + /** 是否显示工作标签页 */ + showWorkTab: boolean + /** 是否显示语言切换 */ + showLanguage: boolean + /** 是否显示进度条 */ + showNprogress: boolean + /** 主题模式 */ + themeModel: string +} + +// 多标签 +export interface WorkTab { + /** 标签标题 */ + title: string + /** 自定义标题 */ + customTitle?: string + /** 路由路径 */ + path: string + /** 路由名称 */ + name: string + /** 是否缓存 */ + keepAlive: boolean + /** 是否固定标签 */ + fixedTab?: boolean + /** 路由参数 */ + params?: object + /** 路由查询参数 */ + query?: LocationQueryRaw + /** 图标 */ + icon?: string + /** 是否激活 */ + isActive?: boolean +} + +// 用户Store状态 +export interface UserState { + /** 用户信息 */ + userInfo: Api.Auth.UserInfo | null + /** 认证令牌 */ + token: string | null + /** 用户角色列表 */ + roles: string[] + /** 用户权限列表 */ + permissions: string[] +} + +// 设置Store状态 +export interface SettingStoreState extends SettingState { + // 额外的设置状态 + /** 菜单是否折叠 */ + collapsed: boolean + /** 设备类型 */ + device: 'desktop' | 'mobile' + /** 当前语言 */ + language: string +} + +// 工作标签页Store状态 +export interface WorkTabState { + /** 标签页列表 */ + tabs: WorkTab[] + /** 当前激活的标签页 */ + activeTab: string + /** 缓存的标签页列表 */ + cachedTabs: string[] +} + +// 菜单Store状态 +export interface MenuState { + /** 菜单列表 */ + menuList: any[] + /** 菜单是否已加载 */ + isLoaded: boolean + /** 菜单是否折叠 */ + collapsed: boolean +} + +// 根Store状态类型 +export interface RootState { + /** 用户状态 */ + user: UserState + /** 设置状态 */ + setting: SettingStoreState + /** 工作标签页状态 */ + workTab: WorkTabState + /** 菜单状态 */ + menu: MenuState +} diff --git a/src/utils/constants/index.ts b/src/utils/constants/index.ts new file mode 100644 index 0000000..831be29 --- /dev/null +++ b/src/utils/constants/index.ts @@ -0,0 +1,8 @@ +/** + * 常量定义相关工具函数统一导出 + * + * @module utils/constants/index + * @author Art Design Pro Team + */ + +export * from './links' diff --git a/src/utils/constants/links.ts b/src/utils/constants/links.ts new file mode 100644 index 0000000..06d297e --- /dev/null +++ b/src/utils/constants/links.ts @@ -0,0 +1,35 @@ +/** + * 网站链接常量配置 + * 集中管理便于维护和更新链接地址 + * + * @module utils/constants/links + * @author Art Design Pro Team + */ +export const WEB_LINKS = { + // Github 主页 + GITHUB_HOME: 'https://github.com/Daymychen/art-design-pro', + + // 项目 Github 主页 + GITHUB: 'https://github.com/Daymychen/art-design-pro', + + // 个人博客 + BLOG: 'https://www.artd.pro', + + // 项目文档 + DOCS: 'https://www.artd.pro/docs/zh/', + + // 精简版本 + LiteVersion: 'https://www.artd.pro/docs/zh/guide/lite-version.html', + + // v2.6.1版本 + OldVersion: 'https://www.artd.pro/v2/', + + // 项目社区 + COMMUNITY: 'https://www.artd.pro/docs/zh/community/communicate.html', + + // 个人 Bilibili 主页 + BILIBILI: 'https://space.bilibili.com/425500936?spm_id_from=333.1007.0.0', + + // 项目介绍 + INTRODUCE: 'https://www.artd.pro/docs/zh/guide/introduce.html' +} diff --git a/src/utils/form/index.ts b/src/utils/form/index.ts new file mode 100644 index 0000000..ed23a46 --- /dev/null +++ b/src/utils/form/index.ts @@ -0,0 +1,12 @@ +/** + * 表单工具函数统一导出 + * + * @module utils/form + * @author Art Design Pro Team + */ + +// 表单验证器 +export * from './validator' + +// 响应式布局 +export * from './responsive' diff --git a/src/utils/form/responsive.ts b/src/utils/form/responsive.ts new file mode 100644 index 0000000..c11df92 --- /dev/null +++ b/src/utils/form/responsive.ts @@ -0,0 +1,122 @@ +/** + * 表单响应式布局工具模块 + * + * 提供表单项在不同屏幕尺寸下的智能布局计算 + * + * ## 主要功能 + * + * - 响应式断点管理(xs/sm/md/lg/xl) + * - 表单列宽自动降级(避免小屏幕压缩) + * - 基于阈值的智能 span 计算 + * - 响应式计算器工厂函数 + * - 可配置的断点规则 + * + * ## 使用场景 + * + * - 表单组件响应式布局 + * - 搜索表单自适应 + * - 移动端表单优化 + * - 多列表单布局 + * + * ## 断点说明(基于 Element Plus Grid 24 栅格系统): + * - xs (手机): < 768px,小于 12 时降级为 24(满宽) + * - sm (平板): ≥ 768px,小于 12 时降级为 12(半宽) + * - md (中等屏幕): ≥ 992px,小于 8 时降级为 8(三分之一宽) + * - lg (大屏幕): ≥ 1200px,直接使用设置的 span + * - xl (超大屏幕): ≥ 1920px,直接使用设置的 span + * + * ## 核心功能 + * + * - calculateResponsiveSpan: 计算响应式列宽 + * - createResponsiveSpanCalculator: 创建 span 计算器(柯里化) + * + * @module utils/form/responsive + * @author Art Design Pro Team + */ + +/** + * 响应式断点类型 + */ +export type ResponsiveBreakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl' + +/** + * 断点配置映射 + */ +interface BreakpointConfig { + /** 最小 span 阈值 */ + threshold: number + /** 降级后的 span 值 */ + fallback: number +} + +/** + * 响应式断点配置 + */ +const BREAKPOINT_CONFIG: Record = { + xs: { threshold: 12, fallback: 24 }, // 手机:小于 12 时使用满宽 + sm: { threshold: 12, fallback: 12 }, // 平板:小于 12 时使用半宽 + md: { threshold: 8, fallback: 8 }, // 中等屏幕:小于 8 时使用三分之一宽 + lg: null, // 大屏幕:直接使用设置的 span + xl: null // 超大屏幕:直接使用设置的 span +} + +/** + * 计算响应式列宽 + * + * 根据屏幕尺寸智能降级,避免小屏幕上表单项被压缩过小 + * + * @param itemSpan 表单项自定义的 span 值 + * @param defaultSpan 默认的 span 值 + * @param breakpoint 当前断点 + * @returns 计算后的 span 值 + * + * @example + * ```ts + * // 在 xs 断点下,span 为 6 会降级为 24(满宽) + * calculateResponsiveSpan(6, 6, 'xs') // 24 + * + * // 在 md 断点下,span 为 6 会降级为 8(三分之一宽) + * calculateResponsiveSpan(6, 6, 'md') // 8 + * + * // 在 lg 断点下,直接使用原始 span + * calculateResponsiveSpan(6, 6, 'lg') // 6 + * ``` + */ +export function calculateResponsiveSpan( + itemSpan: number | undefined, + defaultSpan: number, + breakpoint: ResponsiveBreakpoint +): number { + const finalSpan = itemSpan ?? defaultSpan + const config = BREAKPOINT_CONFIG[breakpoint] + + // 如果没有配置(lg/xl),直接返回原始 span + if (!config) { + return finalSpan + } + + // 如果 span 小于阈值,使用降级值 + return finalSpan >= config.threshold ? finalSpan : config.fallback +} + +/** + * 创建响应式 span 计算器 + * + * 返回一个函数,用于计算指定断点下的 span 值 + * + * @param defaultSpan 默认的 span 值 + * @returns span 计算函数 + * + * @example + * ```ts + * const getColSpan = createResponsiveSpanCalculator(6) + * getColSpan(undefined, 'xs') // 24 + * getColSpan(8, 'md') // 8 + * getColSpan(12, 'lg') // 12 + * ``` + */ +export function createResponsiveSpanCalculator(defaultSpan: number) { + return (itemSpan: number | undefined, breakpoint: ResponsiveBreakpoint): number => { + return calculateResponsiveSpan(itemSpan, defaultSpan, breakpoint) + } +} diff --git a/src/utils/form/validator.ts b/src/utils/form/validator.ts new file mode 100644 index 0000000..3670763 --- /dev/null +++ b/src/utils/form/validator.ts @@ -0,0 +1,316 @@ +/** + * 表单验证工具模块 + * + * 提供全面的表单字段验证功能 + * + * ## 主要功能 + * + * - 手机号码验证(中国大陆格式) + * - 固定电话验证(支持区号格式) + * - 用户账号验证(字母开头,支持数字和下划线) + * - 密码强度验证(普通密码、强密码) + * - 密码强度评估(弱、中、强) + * - IPv4 地址验证 + * - 邮箱地址验证(RFC 5322 标准) + * - URL 地址验证 + * - 身份证号码验证(18位,含校验码验证) + * - 银行卡号验证(Luhn 算法) + * - 字符串空格处理 + * + * ## 验证规则 + * + * - 手机号:1开头,第二位3-9,共11位 + * - 账号:字母开头,5-20位,支持字母数字下划线 + * - 普通密码:6-20位,必须包含字母和数字 + * - 强密码:8-20位,必须包含大小写字母、数字和特殊字符 + * - 身份证:18位,含出生日期和校验码验证 + * - 银行卡:13-19位,通过 Luhn 算法验证 + * + * @module utils/validation/formValidator + * @author Art Design Pro Team + */ + +/** + * 密码强度级别枚举 + */ +export enum PasswordStrength { + WEAK = '弱', + MEDIUM = '中', + STRONG = '强' +} + +/** + * 去除字符串首尾空格 + * @param value 待处理的字符串 + * @returns 返回去除首尾空格后的字符串 + */ +export function trimSpaces(value: string): string { + if (typeof value !== 'string') { + return '' + } + return value.trim() +} + +/** + * 验证手机号码(中国大陆) + * @param value 手机号码字符串 + * @returns 返回验证结果,true表示格式正确 + */ +export function validatePhone(value: string): boolean { + if (!value || typeof value !== 'string') { + return false + } + + // 中国大陆手机号码:1开头,第二位为3-9,共11位数字 + const phoneRegex = /^1[3-9]\d{9}$/ + return phoneRegex.test(value.trim()) +} + +/** + * 验证固定电话号码(中国大陆) + * @param value 电话号码字符串 + * @returns 返回验证结果,true表示格式正确 + */ +export function validateTelPhone(value: string): boolean { + if (!value || typeof value !== 'string') { + return false + } + + // 支持格式:区号-号码,如:010-12345678、0755-1234567 + const telRegex = /^0\d{2,3}-?\d{7,8}$/ + return telRegex.test(value.trim().replace(/\s+/g, '')) +} + +/** + * 验证用户账号 + * @param value 账号字符串 + * @returns 返回验证结果,true表示格式正确 + * @description 规则:字母开头,5-20位,支持字母、数字、下划线 + */ +export function validateAccount(value: string): boolean { + if (!value || typeof value !== 'string') { + return false + } + + // 字母开头,5-20位,支持字母、数字、下划线 + const accountRegex = /^[a-zA-Z][a-zA-Z0-9_]{4,19}$/ + return accountRegex.test(value.trim()) +} + +/** + * 验证密码 + * @param value 密码字符串 + * @returns 返回验证结果,true表示格式正确 + * @description 规则:6-20位,必须包含字母和数字 + */ +export function validatePassword(value: string): boolean { + if (!value || typeof value !== 'string') { + return false + } + + const trimmedValue = value.trim() + + // 长度检查 + if (trimmedValue.length < 6 || trimmedValue.length > 20) { + return false + } + + // 必须包含字母和数字 + const hasLetter = /[a-zA-Z]/.test(trimmedValue) + const hasNumber = /\d/.test(trimmedValue) + + return hasLetter && hasNumber +} + +/** + * 验证强密码 + * @param value 密码字符串 + * @returns 返回验证结果,true表示格式正确 + * @description 规则:8-20位,必须包含大写字母、小写字母、数字和特殊字符 + */ +export function validateStrongPassword(value: string): boolean { + if (!value || typeof value !== 'string') { + return false + } + + const trimmedValue = value.trim() + + // 长度检查 + if (trimmedValue.length < 8 || trimmedValue.length > 20) { + return false + } + + // 必须包含:大写字母、小写字母、数字、特殊字符 + const hasUpperCase = /[A-Z]/.test(trimmedValue) + const hasLowerCase = /[a-z]/.test(trimmedValue) + const hasNumber = /\d/.test(trimmedValue) + const hasSpecialChar = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(trimmedValue) + + return hasUpperCase && hasLowerCase && hasNumber && hasSpecialChar +} + +/** + * 获取密码强度 + * @param value 密码字符串 + * @returns 返回密码强度:弱、中、强 + * @description 弱:纯数字/纯字母/纯特殊字符;中:两种组合;强:三种或以上组合 + */ +export function getPasswordStrength(value: string): PasswordStrength { + if (!value || typeof value !== 'string') { + return PasswordStrength.WEAK + } + + const trimmedValue = value.trim() + + if (trimmedValue.length < 6) { + return PasswordStrength.WEAK + } + + const hasUpperCase = /[A-Z]/.test(trimmedValue) + const hasLowerCase = /[a-z]/.test(trimmedValue) + const hasNumber = /\d/.test(trimmedValue) + const hasSpecialChar = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(trimmedValue) + + const typeCount = [hasUpperCase, hasLowerCase, hasNumber, hasSpecialChar].filter(Boolean).length + + if (typeCount >= 3) { + return PasswordStrength.STRONG + } else if (typeCount >= 2) { + return PasswordStrength.MEDIUM + } else { + return PasswordStrength.WEAK + } +} + +/** + * 验证IPv4地址 + * @param value IP地址字符串 + * @returns 返回验证结果,true表示格式正确 + */ +export function validateIPv4Address(value: string): boolean { + if (!value || typeof value !== 'string') { + return false + } + + const trimmedValue = value.trim() + const ipRegex = /^((25[0-5]|2[0-4]\d|[01]?\d{1,2})\.){3}(25[0-5]|2[0-4]\d|[01]?\d{1,2})$/ + + if (!ipRegex.test(trimmedValue)) { + return false + } + + // 额外检查每个段是否在有效范围内 + const segments = trimmedValue.split('.') + return segments.every((segment) => { + const num = parseInt(segment, 10) + return num >= 0 && num <= 255 + }) +} + +/** + * 验证邮箱地址 + * @param value 邮箱地址字符串 + * @returns 返回验证结果,true表示格式正确 + */ +export function validateEmail(value: string): boolean { + if (!value || typeof value !== 'string') { + return false + } + + const trimmedValue = value.trim() + + // RFC 5322 标准的简化版邮箱正则 + const emailRegex = + /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ + + return emailRegex.test(trimmedValue) && trimmedValue.length <= 254 +} + +/** + * 验证URL地址 + * @param value URL字符串 + * @returns 返回验证结果,true表示格式正确 + */ +export function validateURL(value: string): boolean { + if (!value || typeof value !== 'string') { + return false + } + + try { + new URL(value.trim()) + return true + } catch { + return false + } +} + +/** + * 验证身份证号码(中国大陆) + * @param value 身份证号码字符串 + * @returns 返回验证结果,true表示格式正确 + */ +export function validateChineseIDCard(value: string): boolean { + if (!value || typeof value !== 'string') { + return false + } + + const trimmedValue = value.trim() + + // 18位身份证号码正则 + const idCardRegex = + /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/ + + if (!idCardRegex.test(trimmedValue)) { + return false + } + + // 验证校验码 + const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] + const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'] + + let sum = 0 + for (let i = 0; i < 17; i++) { + sum += parseInt(trimmedValue[i]) * weights[i] + } + + const checkCode = checkCodes[sum % 11] + return trimmedValue[17].toUpperCase() === checkCode +} + +/** + * 验证银行卡号 + * @param value 银行卡号字符串 + * @returns 返回验证结果,true表示格式正确 + */ +export function validateBankCard(value: string): boolean { + if (!value || typeof value !== 'string') { + return false + } + + const trimmedValue = value.trim().replace(/\s+/g, '') + + // 银行卡号通常为13-19位数字 + if (!/^\d{13,19}$/.test(trimmedValue)) { + return false + } + + // Luhn算法验证 + let sum = 0 + let shouldDouble = false + + for (let i = trimmedValue.length - 1; i >= 0; i--) { + let digit = parseInt(trimmedValue[i]) + + if (shouldDouble) { + digit *= 2 + if (digit > 9) { + digit = (digit % 10) + 1 + } + } + + sum += digit + shouldDouble = !shouldDouble + } + + return sum % 10 === 0 +} diff --git a/src/utils/http/error.ts b/src/utils/http/error.ts new file mode 100644 index 0000000..0f2c1ae --- /dev/null +++ b/src/utils/http/error.ts @@ -0,0 +1,182 @@ +/** + * HTTP 错误处理模块 + * + * 提供统一的 HTTP 请求错误处理机制 + * + * ## 主要功能 + * + * - 自定义 HttpError 错误类,封装错误信息、状态码、时间戳等 + * - 错误拦截和转换,将 Axios 错误转换为标准的 HttpError + * - 错误消息国际化处理,根据状态码返回对应的多语言错误提示 + * - 错误日志记录,便于问题追踪和调试 + * - 错误和成功消息的统一展示 + * - 类型守卫函数,用于判断错误类型 + * + * ## 使用场景 + * + * - HTTP 请求拦截器中统一处理错误 + * - 业务代码中捕获和处理特定错误 + * - 错误日志收集和上报 + * + * @module utils/http/error + * @author Art Design Pro Team + */ +import { AxiosError } from 'axios' +import { ApiStatus } from './status' +import { $t } from '@/locales' + +// 错误响应接口 +export interface ErrorResponse { + /** 错误状态码 */ + code: number + /** 错误消息 */ + msg: string + /** 错误附加数据 */ + data?: unknown +} + +// 错误日志数据接口 +export interface ErrorLogData { + /** 错误状态码 */ + code: number + /** 错误消息 */ + message: string + /** 错误附加数据 */ + data?: unknown + /** 错误发生时间戳 */ + timestamp: string + /** 请求 URL */ + url?: string + /** 请求方法 */ + method?: string + /** 错误堆栈信息 */ + stack?: string +} + +// 自定义 HttpError 类 +export class HttpError extends Error { + public readonly code: number + public readonly data?: unknown + public readonly timestamp: string + public readonly url?: string + public readonly method?: string + + constructor( + message: string, + code: number, + options?: { + data?: unknown + url?: string + method?: string + } + ) { + super(message) + this.name = 'HttpError' + this.code = code + this.data = options?.data + this.timestamp = new Date().toISOString() + this.url = options?.url + this.method = options?.method + } + + public toLogData(): ErrorLogData { + return { + code: this.code, + message: this.message, + data: this.data, + timestamp: this.timestamp, + url: this.url, + method: this.method, + stack: this.stack + } + } +} + +/** + * 获取错误消息 + * @param status 错误状态码 + * @returns 错误消息 + */ +const getErrorMessage = (status: number): string => { + const errorMap: Record = { + [ApiStatus.unauthorized]: 'httpMsg.unauthorized', + [ApiStatus.forbidden]: 'httpMsg.forbidden', + [ApiStatus.notFound]: 'httpMsg.notFound', + [ApiStatus.methodNotAllowed]: 'httpMsg.methodNotAllowed', + [ApiStatus.requestTimeout]: 'httpMsg.requestTimeout', + [ApiStatus.internalServerError]: 'httpMsg.internalServerError', + [ApiStatus.badGateway]: 'httpMsg.badGateway', + [ApiStatus.serviceUnavailable]: 'httpMsg.serviceUnavailable', + [ApiStatus.gatewayTimeout]: 'httpMsg.gatewayTimeout' + } + + return $t(errorMap[status] || 'httpMsg.internalServerError') +} + +/** + * 处理错误 + * @param error 错误对象 + * @returns 错误对象 + */ +export function handleError(error: AxiosError): never { + // 处理取消的请求 + if (error.code === 'ERR_CANCELED') { + console.warn('Request cancelled:', error.message) + throw new HttpError($t('httpMsg.requestCancelled'), ApiStatus.error) + } + + const statusCode = error.response?.status + const errorMessage = error.response?.data?.msg || error.message + const requestConfig = error.config + + // 处理网络错误 + if (!error.response) { + throw new HttpError($t('httpMsg.networkError'), ApiStatus.error, { + url: requestConfig?.url, + method: requestConfig?.method?.toUpperCase() + }) + } + + // 处理 HTTP 状态码错误 + const message = statusCode + ? getErrorMessage(statusCode) + : errorMessage || $t('httpMsg.requestFailed') + throw new HttpError(message, statusCode || ApiStatus.error, { + data: error.response.data, + url: requestConfig?.url, + method: requestConfig?.method?.toUpperCase() + }) +} + +/** + * 显示错误消息 + * @param error 错误对象 + * @param showMessage 是否显示错误消息 + */ +export function showError(error: HttpError, showMessage: boolean = true): void { + if (showMessage) { + ElMessage.error(error.message) + } + // 记录错误日志 + console.error('[HTTP Error]', error.toLogData()) +} + +/** + * 显示成功消息 + * @param message 成功消息 + * @param showMessage 是否显示消息 + */ +export function showSuccess(message: string, showMessage: boolean = true): void { + if (showMessage) { + ElMessage.success(message) + } +} + +/** + * 判断是否为 HttpError 类型 + * @param error 错误对象 + * @returns 是否为 HttpError 类型 + */ +export const isHttpError = (error: unknown): error is HttpError => { + return error instanceof HttpError +} diff --git a/src/utils/http/index.ts b/src/utils/http/index.ts new file mode 100644 index 0000000..0e0002a --- /dev/null +++ b/src/utils/http/index.ts @@ -0,0 +1,214 @@ +/** + * HTTP 请求封装模块 + * 基于 Axios 封装的 HTTP 请求工具,提供统一的请求/响应处理 + * + * ## 主要功能 + * + * - 请求/响应拦截器(自动添加 Token、统一错误处理) + * - 401 未授权自动登出(带防抖机制) + * - 请求失败自动重试(可配置) + * - 统一的成功/错误消息提示 + * - 支持 GET/POST/PUT/DELETE 等常用方法 + * + * @module utils/http + * @author Art Design Pro Team + */ + +import axios, { AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios' +import { useUserStore } from '@/store/modules/user' +import { ApiStatus } from './status' +import { HttpError, handleError, showError, showSuccess } from './error' +import { $t } from '@/locales' +import { BaseResponse } from '@/types' + +/** 请求配置常量 */ +const REQUEST_TIMEOUT = 15000 +const LOGOUT_DELAY = 500 +const MAX_RETRIES = 0 +const RETRY_DELAY = 1000 +const UNAUTHORIZED_DEBOUNCE_TIME = 3000 + +/** 401防抖状态 */ +let isUnauthorizedErrorShown = false +let unauthorizedTimer: NodeJS.Timeout | null = null + +/** 扩展 AxiosRequestConfig */ +interface ExtendedAxiosRequestConfig extends AxiosRequestConfig { + showErrorMessage?: boolean + showSuccessMessage?: boolean +} + +const { VITE_API_URL, VITE_WITH_CREDENTIALS } = import.meta.env + +/** Axios实例 */ +const axiosInstance = axios.create({ + timeout: REQUEST_TIMEOUT, + baseURL: VITE_API_URL, + withCredentials: VITE_WITH_CREDENTIALS === 'true', + validateStatus: (status) => status >= 200 && status < 300, + transformResponse: [ + (data, headers) => { + const contentType = headers['content-type'] + if (contentType?.includes('application/json')) { + try { + return JSON.parse(data) + } catch { + return data + } + } + return data + } + ] +}) + +/** 请求拦截器 */ +axiosInstance.interceptors.request.use( + (request: InternalAxiosRequestConfig) => { + const { accessToken } = useUserStore() + if (accessToken) request.headers.set('Authorization', accessToken) + + if (request.data && !(request.data instanceof FormData) && !request.headers['Content-Type']) { + request.headers.set('Content-Type', 'application/json') + request.data = JSON.stringify(request.data) + } + + return request + }, + (error) => { + showError(createHttpError($t('httpMsg.requestConfigError'), ApiStatus.error)) + return Promise.reject(error) + } +) + +/** 响应拦截器 */ +axiosInstance.interceptors.response.use( + (response: AxiosResponse) => { + const { code, msg } = response.data + if (code === ApiStatus.success) return response + if (code === ApiStatus.unauthorized) handleUnauthorizedError(msg) + throw createHttpError(msg || $t('httpMsg.requestFailed'), code) + }, + (error) => { + if (error.response?.status === ApiStatus.unauthorized) handleUnauthorizedError() + return Promise.reject(handleError(error)) + } +) + +/** 统一创建HttpError */ +function createHttpError(message: string, code: number) { + return new HttpError(message, code) +} + +/** 处理401错误(带防抖) */ +function handleUnauthorizedError(message?: string): never { + const error = createHttpError(message || $t('httpMsg.unauthorized'), ApiStatus.unauthorized) + + if (!isUnauthorizedErrorShown) { + isUnauthorizedErrorShown = true + logOut() + + unauthorizedTimer = setTimeout(resetUnauthorizedError, UNAUTHORIZED_DEBOUNCE_TIME) + + showError(error, true) + throw error + } + + throw error +} + +/** 重置401防抖状态 */ +function resetUnauthorizedError() { + isUnauthorizedErrorShown = false + if (unauthorizedTimer) clearTimeout(unauthorizedTimer) + unauthorizedTimer = null +} + +/** 退出登录函数 */ +function logOut() { + setTimeout(() => { + useUserStore().logOut() + }, LOGOUT_DELAY) +} + +/** 是否需要重试 */ +function shouldRetry(statusCode: number) { + return [ + ApiStatus.requestTimeout, + ApiStatus.internalServerError, + ApiStatus.badGateway, + ApiStatus.serviceUnavailable, + ApiStatus.gatewayTimeout + ].includes(statusCode) +} + +/** 请求重试逻辑 */ +async function retryRequest( + config: ExtendedAxiosRequestConfig, + retries: number = MAX_RETRIES +): Promise { + try { + return await request(config) + } catch (error) { + if (retries > 0 && error instanceof HttpError && shouldRetry(error.code)) { + await delay(RETRY_DELAY) + return retryRequest(config, retries - 1) + } + throw error + } +} + +/** 延迟函数 */ +function delay(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + +/** 请求函数 */ +async function request(config: ExtendedAxiosRequestConfig): Promise { + // POST | PUT 参数自动填充 + if ( + ['POST', 'PUT'].includes(config.method?.toUpperCase() || '') && + config.params && + !config.data + ) { + config.data = config.params + config.params = undefined + } + + try { + const res = await axiosInstance.request>(config) + + // 显示成功消息 + if (config.showSuccessMessage && res.data.msg) { + showSuccess(res.data.msg) + } + + return res.data.data as T + } catch (error) { + if (error instanceof HttpError && error.code !== ApiStatus.unauthorized) { + const showMsg = config.showErrorMessage !== false + showError(error, showMsg) + } + return Promise.reject(error) + } +} + +/** API方法集合 */ +const api = { + get(config: ExtendedAxiosRequestConfig) { + return retryRequest({ ...config, method: 'GET' }) + }, + post(config: ExtendedAxiosRequestConfig) { + return retryRequest({ ...config, method: 'POST' }) + }, + put(config: ExtendedAxiosRequestConfig) { + return retryRequest({ ...config, method: 'PUT' }) + }, + del(config: ExtendedAxiosRequestConfig) { + return retryRequest({ ...config, method: 'DELETE' }) + }, + request(config: ExtendedAxiosRequestConfig) { + return retryRequest(config) + } +} + +export default api diff --git a/src/utils/http/status.ts b/src/utils/http/status.ts new file mode 100644 index 0000000..989bb37 --- /dev/null +++ b/src/utils/http/status.ts @@ -0,0 +1,18 @@ +/** + * 接口状态码 + */ +export enum ApiStatus { + success = 200, // 成功 + error = 400, // 错误 + unauthorized = 401, // 未授权 + forbidden = 403, // 禁止访问 + notFound = 404, // 未找到 + methodNotAllowed = 405, // 方法不允许 + requestTimeout = 408, // 请求超时 + internalServerError = 500, // 服务器错误 + notImplemented = 501, // 未实现 + badGateway = 502, // 网关错误 + serviceUnavailable = 503, // 服务不可用 + gatewayTimeout = 504, // 网关超时 + httpVersionNotSupported = 505 // HTTP版本不支持 +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..f1e1b77 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,34 @@ +/** + * Utils 工具函数统一导出 + * 提供向后兼容性和便捷导入 + * + * @module utils/index + * @author Art Design Pro Team + */ + +// UI 相关 +export * from './ui' + +// 路由相关 +export * from './router' + +// 路由导航相关 +export * from './navigation' + +// 系统管理相关 +export * from './sys' + +// 常量定义相关 +export * from './constants' + +// 存储相关 +export * from './storage' + +// HTTP 相关 +export * from './http' + +// 表单相关 +export * from './form' + +// socket 相关 +export * from './socket' diff --git a/src/utils/navigation/index.ts b/src/utils/navigation/index.ts new file mode 100644 index 0000000..0b84e78 --- /dev/null +++ b/src/utils/navigation/index.ts @@ -0,0 +1,10 @@ +/** + * 路由和导航相关工具函数统一导出 + * + * @module utils/navigation/index + * @author Art Design Pro Team + */ + +export * from './jump' +export * from './worktab' +export * from './route' diff --git a/src/utils/navigation/jump.ts b/src/utils/navigation/jump.ts new file mode 100644 index 0000000..4fde1e8 --- /dev/null +++ b/src/utils/navigation/jump.ts @@ -0,0 +1,62 @@ +/** + * 导航跳转工具模块 + * + * 提供统一的页面跳转和导航功能 + * + * ## 主要功能 + * + * - 外部链接打开(新窗口) + * - 菜单项跳转处理(支持内部路由和外部链接) + * - iframe 页面跳转支持 + * - 递归查找并跳转到第一个可见的子菜单 + * - 智能判断跳转目标类型(外部链接/内部路由) + * + * @module utils/navigation/jump + * @author Art Design Pro Team + */ +import { AppRouteRecord } from '@/types/router' +import { router } from '@/router' + +// 打开外部链接 +export const openExternalLink = (link: string) => { + window.open(link, '_blank') +} + +/** + * 菜单跳转 + * @param item 菜单项 + * @param jumpToFirst 是否跳转到第一个子菜单 + * @returns + */ +export const handleMenuJump = (item: AppRouteRecord, jumpToFirst: boolean = false) => { + // 处理外部链接 + const { link, isIframe } = item.meta + if (link && !isIframe) { + return openExternalLink(link) + } + + // 如果不需要跳转到第一个子菜单,或者没有子菜单,直接跳转当前路径 + if (!jumpToFirst || !item.children?.length) { + return router.push(item.path) + } + + // 递归查找第一个可见的叶子节点菜单 + const findFirstLeafMenu = (items: AppRouteRecord[]): AppRouteRecord => { + for (const child of items) { + if (!child.meta.isHide) { + return child.children?.length ? findFirstLeafMenu(child.children) : child + } + } + return items[0] + } + + const firstChild = findFirstLeafMenu(item.children) + + // 如果第一个子菜单是外部链接则打开新窗口 + if (firstChild.meta?.link) { + return openExternalLink(firstChild.meta.link) + } + + // 跳转到子菜单路径 + router.push(firstChild.path) +} diff --git a/src/utils/navigation/route.ts b/src/utils/navigation/route.ts new file mode 100644 index 0000000..9ca4f29 --- /dev/null +++ b/src/utils/navigation/route.ts @@ -0,0 +1,78 @@ +/** + * 路由工具模块 + * + * 提供路由处理和菜单路径相关的工具函数 + * + * ## 主要功能 + * + * - iframe 路由检测,判断是否为外部嵌入页面 + * - 菜单项有效性验证,过滤隐藏和无效菜单 + * - 路径标准化处理,统一路径格式 + * - 递归查找菜单树中第一个有效路径 + * - 支持多级嵌套菜单的路径解析 + * + * ## 使用场景 + * + * - 系统初始化时获取默认跳转路径 + * - 菜单权限过滤后获取首个可访问页面 + * - 路由重定向逻辑处理 + * - iframe 页面特殊处理 + * + * @module utils/navigation/route + * @author Art Design Pro Team + */ + +import { AppRouteRecord } from '@/types' + +// 检查是否为 iframe 路由 +export function isIframe(url: string): boolean { + return url.startsWith('/outside/iframe/') +} + +/** + * 验证菜单项是否有效 + * @param menuItem 菜单项 + * @returns 是否为有效菜单项 + */ +const isValidMenuItem = (menuItem: AppRouteRecord): boolean => { + return !!(menuItem.path && menuItem.path.trim() && !menuItem.meta?.isHide) +} + +/** + * 标准化路径格式 + * @param path 路径 + * @returns 标准化后的路径 + */ +const normalizePath = (path: string): string => { + return path.startsWith('/') ? path : `/${path}` +} + +/** + * 递归获取菜单的第一个有效路径 + * @param menuList 菜单列表 + * @returns 第一个有效路径,如果没有找到则返回空字符串 + */ +export const getFirstMenuPath = (menuList: AppRouteRecord[]): string => { + if (!Array.isArray(menuList) || menuList.length === 0) { + return '' + } + + for (const menuItem of menuList) { + if (!isValidMenuItem(menuItem)) { + continue + } + + // 如果有子菜单,优先查找子菜单 + if (menuItem.children?.length) { + const childPath = getFirstMenuPath(menuItem.children) + if (childPath) { + return childPath + } + } + + // 返回当前菜单项的标准化路径 + return normalizePath(menuItem.path!) + } + + return '' +} diff --git a/src/utils/navigation/worktab.ts b/src/utils/navigation/worktab.ts new file mode 100644 index 0000000..6db6a77 --- /dev/null +++ b/src/utils/navigation/worktab.ts @@ -0,0 +1,67 @@ +/** + * 工作标签页管理模块 + * + * 提供工作标签页(Worktab)的自动管理功能 + * + * ## 主要功能 + * + * - 根据路由导航自动创建和更新工作标签页 + * - iframe 页面标签页特殊处理 + * - 标签页信息提取(标题、路径、缓存状态等) + * - 固定标签页支持 + * - 根据系统设置控制标签页显示 + * - 首页标签页特殊处理 + * + * ## 使用场景 + * + * - 路由守卫中自动创建标签页 + * - 页面切换时更新标签页状态 + * - 多标签页导航系统 + * + * @module utils/navigation/worktab + * @author Art Design Pro Team + */ +import { useWorktabStore } from '@/store/modules/worktab' +import { RouteLocationNormalized } from 'vue-router' +import { isIframe } from './route' +import { useSettingStore } from '@/store/modules/setting' +import { IframeRouteManager } from '@/router/core' +import { useCommon } from '@/hooks/core/useCommon' + +/** + * 根据当前路由信息设置工作标签页(worktab) + * @param to 当前路由对象 + */ +export const setWorktab = (to: RouteLocationNormalized): void => { + const worktabStore = useWorktabStore() + const { meta, path, name, params, query } = to + if (!meta.isHideTab) { + // 如果是 iframe 页面,则特殊处理工作标签页 + if (isIframe(path)) { + const iframeRoute = IframeRouteManager.getInstance().findByPath(to.path) + + if (iframeRoute?.meta) { + worktabStore.openTab({ + title: iframeRoute.meta.title, + icon: meta.icon as string, + path, + name: name as string, + keepAlive: meta.keepAlive as boolean, + params, + query + }) + } + } else if (useSettingStore().showWorkTab || path === useCommon().homePath.value) { + worktabStore.openTab({ + title: meta.title as string, + icon: meta.icon as string, + path, + name: name as string, + keepAlive: meta.keepAlive as boolean, + params, + query, + fixedTab: meta.fixedTab as boolean + }) + } + } +} diff --git a/src/utils/router.ts b/src/utils/router.ts new file mode 100644 index 0000000..8c838ff --- /dev/null +++ b/src/utils/router.ts @@ -0,0 +1,61 @@ +/** + * 路由工具函数 + * + * 提供路由相关的工具函数 + * + * @module utils/router + */ +import { RouteLocationNormalized, RouteRecordRaw } from 'vue-router' +import AppConfig from '@/config' +import NProgress from 'nprogress' +import 'nprogress/nprogress.css' +import i18n, { $t } from '@/locales' + +/** 扩展的路由配置类型 */ +export type AppRouteRecordRaw = RouteRecordRaw & { + hidden?: boolean +} + +/** 顶部进度条配置 */ +export const configureNProgress = () => { + NProgress.configure({ + easing: 'ease', + speed: 600, + showSpinner: false, + parent: 'body' + }) +} + +/** + * 设置页面标题,根据路由元信息和系统信息拼接标题 + * @param to 当前路由对象 + */ +export const setPageTitle = (to: RouteLocationNormalized): void => { + const { title } = to.meta + if (title) { + setTimeout(() => { + document.title = `${formatMenuTitle(String(title))} - ${AppConfig.systemInfo.name}` + }, 150) + } +} + +/** + * 格式化菜单标题 + * @param title 菜单标题,可以是 i18n 的 key,也可以是字符串 + * @returns 格式化后的菜单标题 + */ +export const formatMenuTitle = (title: string): string => { + if (title) { + if (title.startsWith('menus.')) { + // 使用 te() 方法检查翻译键值是否存在,避免控制台警告 + if (i18n.global.te(title)) { + return $t(title) + } else { + // 如果翻译不存在,返回键值的最后部分作为fallback + return title.split('.').pop() || title + } + } + return title + } + return '' +} diff --git a/src/utils/socket/index.ts b/src/utils/socket/index.ts new file mode 100644 index 0000000..77d46ad --- /dev/null +++ b/src/utils/socket/index.ts @@ -0,0 +1,388 @@ +interface WebSocketOptions { + url?: string + messageHandler: (event: MessageEvent) => void + reconnectInterval?: number // 重连间隔(ms) + heartbeatInterval?: number // 心跳检测间隔(ms) + pingInterval?: number // 发送ping间隔(ms) + reconnectTimeout?: number // 重连超时时间(ms) + maxReconnectAttempts?: number // 最大重连次数 + connectionTimeout?: number // 连接建立超时时间(ms) +} + +export default class WebSocketClient { + private static instance: WebSocketClient | null = null + private ws: WebSocket | null = null + private url: string + private messageHandler: (event: MessageEvent) => void + private reconnectInterval: number + private heartbeatInterval: number + private pingInterval: number + private reconnectTimeout: number + private maxReconnectAttempts: number + private connectionTimeout: number + private reconnectAttempts: number = 0 // 当前重连次数 + + // 消息队列 - 缓存连接建立前的消息 + private messageQueue: Array = [] + + // 定时器 + private detectionTimer: NodeJS.Timeout | null = null + private timeoutTimer: NodeJS.Timeout | null = null + private reconnectTimer: NodeJS.Timeout | null = null + private pingTimer: NodeJS.Timeout | null = null + private connectionTimer: NodeJS.Timeout | null = null // 连接超时定时器 + + // 状态标识 + private isConnected: boolean = false + private isConnecting: boolean = false // 是否正在连接中 + private stopReconnect: boolean = false + + private constructor(options: WebSocketOptions) { + this.url = options.url || (process.env.VUE_APP_LOGIN_WEBSOCKET as string) + this.messageHandler = options.messageHandler + this.reconnectInterval = options.reconnectInterval || 20 * 1000 // 默认20秒 + this.heartbeatInterval = options.heartbeatInterval || 5 * 1000 // 默认5秒 + this.pingInterval = options.pingInterval || 10 * 1000 // 默认10秒 + this.reconnectTimeout = options.reconnectTimeout || 30 * 1000 // 默认30秒 + this.maxReconnectAttempts = options.maxReconnectAttempts || 10 // 默认最多重连10次 + this.connectionTimeout = options.connectionTimeout || 10 * 1000 // 连接超时10秒 + } + + // 单例模式获取实例 + static getInstance(options: WebSocketOptions): WebSocketClient { + if (!WebSocketClient.instance) { + WebSocketClient.instance = new WebSocketClient(options) + } else { + // 更新消息处理器 + WebSocketClient.instance.messageHandler = options.messageHandler + // 如果提供了新的URL,则更新并重新连接 + if (options.url && WebSocketClient.instance.url !== options.url) { + WebSocketClient.instance.url = options.url + WebSocketClient.instance.reconnectAttempts = 0 + WebSocketClient.instance.init() + } + } + return WebSocketClient.instance + } + + // 初始化连接 + init(): void { + // 如果正在连接中,不重复连接 + if (this.isConnecting) { + console.log('正在建立WebSocket连接中...') + return + } + + // 如果已连接,不重复连接 + if (this.ws?.readyState === WebSocket.OPEN) { + console.warn('WebSocket连接已存在') + this.flushMessageQueue() // 确保队列中的消息被发送 + return + } + + try { + this.isConnecting = true + this.reconnectAttempts = 0 // 重置重连次数 + this.ws = new WebSocket(this.url) + + // 设置连接超时检测 + this.clearTimer('connectionTimer') + this.connectionTimer = setTimeout(() => { + console.error(`WebSocket连接超时 (${this.connectionTimeout}ms):${this.url}`) + this.handleConnectionTimeout() + }, this.connectionTimeout) + + this.ws.onopen = (event) => this.handleOpen(event) + this.ws.onmessage = (event) => this.handleMessage(event) + this.ws.onclose = (event) => this.handleClose(event) + this.ws.onerror = (event) => this.handleError(event) + } catch (error) { + console.error('WebSocket初始化失败:', error) + this.isConnecting = false + this.reconnect() + } + } + + // 处理连接超时 + private handleConnectionTimeout(): void { + if (this.ws?.readyState !== WebSocket.OPEN) { + console.error('WebSocket连接超时,强制关闭连接') + this.ws?.close(1000, 'Connection timeout') + this.isConnecting = false + this.reconnect() + } + } + + // 关闭连接 + close(force?: boolean): void { + this.clearAllTimers() + this.stopReconnect = true + this.isConnecting = false + + if (this.ws) { + // 1000 表示正常关闭 + this.ws.close(force ? 1001 : 1000, force ? 'Force closed' : 'Normal close') + this.ws = null + } + + this.isConnected = false + } + + // 发送消息 - 增加消息队列 + send(data: string | ArrayBufferLike | Blob | ArrayBufferView, immediate: boolean = false): void { + // 如果要求立即发送且未连接,则直接报错 + if (immediate && (!this.ws || this.ws.readyState !== WebSocket.OPEN)) { + console.error('WebSocket未连接,无法立即发送消息') + return + } + + // 如果未连接且不要求立即发送,则加入消息队列 + if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { + console.log('WebSocket未连接,消息已加入队列等待发送') + this.messageQueue.push(data) + // 如果未在重连中,则尝试重连 + if (!this.isConnecting && !this.stopReconnect) { + this.init() + } + return + } + + try { + this.ws.send(data) + } catch (error) { + console.error('WebSocket发送消息失败:', error) + // 发送失败时将消息加入队列,等待重连后重试 + this.messageQueue.push(data) + this.reconnect() + } + } + + // 发送队列中的消息 + private flushMessageQueue(): void { + if (this.messageQueue.length > 0 && this.ws?.readyState === WebSocket.OPEN) { + console.log(`发送队列中的${this.messageQueue.length}条消息`) + while (this.messageQueue.length > 0) { + const data = this.messageQueue.shift() + if (data) { + try { + this.ws?.send(data) + } catch (error) { + console.error('发送队列消息失败:', error) + // 如果发送失败,将消息放回队列头部 + if (data) this.messageQueue.unshift(data) + break + } + } + } + } + } + + // 处理连接打开 + private handleOpen(event: Event): void { + console.log('WebSocket连接成功', event) + this.clearTimer('connectionTimer') // 清除连接超时定时器 + this.isConnected = true + this.isConnecting = false + this.stopReconnect = false + this.reconnectAttempts = 0 // 重置重连次数 + this.startHeartbeat() + this.startPing() + this.flushMessageQueue() // 发送队列中的消息 + } + + // 处理收到的消息 + private handleMessage(event: MessageEvent): void { + console.log('收到WebSocket消息:', event) + this.resetHeartbeat() + this.messageHandler(event) + } + + // 处理连接关闭 + private handleClose(event: CloseEvent): void { + console.log( + `WebSocket断开: 代码=${event.code}, 原因=${event.reason}, 干净关闭=${event.wasClean}` + ) + + // 1000 是正常关闭代码 + const isNormalClose = event.code === 1000 + + this.isConnected = false + this.isConnecting = false + this.clearAllTimers() + + if (!this.stopReconnect && !isNormalClose) { + this.reconnect() + } + } + + // 处理错误 - 增加详细错误信息 + private handleError(event: Event): void { + console.error('WebSocket连接错误:') + console.error('错误事件:', event) + console.error( + '当前连接状态:', + this.ws?.readyState ? this.getReadyStateText(this.ws.readyState) : '未初始化' + ) + + this.isConnected = false + this.isConnecting = false + + // 只有在未停止重连的情况下才尝试重连 + if (!this.stopReconnect) { + this.reconnect() + } + } + + // 转换连接状态为文本描述 + private getReadyStateText(state: number): string { + switch (state) { + case WebSocket.CONNECTING: + return 'CONNECTING (0) - 正在连接' + case WebSocket.OPEN: + return 'OPEN (1) - 已连接' + case WebSocket.CLOSING: + return 'CLOSING (2) - 正在关闭' + case WebSocket.CLOSED: + return 'CLOSED (3) - 已关闭' + default: + return `未知状态 (${state})` + } + } + + // 开始心跳检测 + private startHeartbeat(): void { + this.clearTimer('detectionTimer') + this.clearTimer('timeoutTimer') + + this.detectionTimer = setTimeout(() => { + this.isConnected = this.ws?.readyState === WebSocket.OPEN + + if (!this.isConnected) { + console.warn('WebSocket心跳检测失败,尝试重连') + this.reconnect() + + this.timeoutTimer = setTimeout(() => { + console.warn('WebSocket重连超时') + this.close() + }, this.reconnectTimeout) + } + }, this.heartbeatInterval) + } + + // 重置心跳检测 + private resetHeartbeat(): void { + this.clearTimer('detectionTimer') + this.clearTimer('timeoutTimer') + this.startHeartbeat() + } + + // 开始发送ping消息 + private startPing(): void { + this.clearTimer('pingTimer') + + this.pingTimer = setInterval(() => { + if (this.ws?.readyState !== WebSocket.OPEN) { + console.warn('WebSocket未连接,停止发送ping') + this.clearTimer('pingTimer') + this.reconnect() + return + } + + try { + this.ws.send('ping') + console.log('发送ping消息') + } catch (error) { + console.error('发送ping消息失败:', error) + this.clearTimer('pingTimer') + this.reconnect() + } + }, this.pingInterval) + } + + // 重连 - 增加重连次数限制 + private reconnect(): void { + if (this.stopReconnect || this.isConnecting) { + return + } + + // 检查是否超过最大重连次数 + if (this.reconnectAttempts >= this.maxReconnectAttempts) { + console.error(`已达到最大重连次数(${this.maxReconnectAttempts}),停止重连`) + this.close(true) + return + } + + this.reconnectAttempts++ + this.stopReconnect = true + this.close(true) + + const delay = this.calculateReconnectDelay() + console.log( + `将在${delay / 1000}秒后尝试重新连接(第${this.reconnectAttempts}/${this.maxReconnectAttempts}次)` + ) + + this.clearTimer('reconnectTimer') + this.reconnectTimer = setTimeout(() => { + console.log(`尝试重新连接WebSocket(第${this.reconnectAttempts}次)`) + this.init() + this.stopReconnect = false + }, delay) + } + + // 计算重连延迟 - 指数退避策略 + private calculateReconnectDelay(): number { + // 基础延迟 + 随机值,避免多个客户端同时重连 + const jitter = Math.random() * 1000 // 0-1秒的随机延迟 + const baseDelay = Math.min( + this.reconnectInterval * Math.pow(1.5, this.reconnectAttempts - 1), + this.reconnectInterval * 5 + ) + return baseDelay + jitter + } + + // 清除指定定时器 + private clearTimer( + timerName: + | 'detectionTimer' + | 'timeoutTimer' + | 'reconnectTimer' + | 'pingTimer' + | 'connectionTimer' + ): void { + if (this[timerName]) { + clearTimeout(this[timerName] as NodeJS.Timeout) + this[timerName] = null + } + } + + // 清除所有定时器 + private clearAllTimers(): void { + this.clearTimer('detectionTimer') + this.clearTimer('timeoutTimer') + this.clearTimer('reconnectTimer') + this.clearTimer('pingTimer') + this.clearTimer('connectionTimer') + } + + // 获取当前连接状态 + get isWebSocketConnected(): boolean { + return this.isConnected + } + + // 获取当前连接状态文本 + get connectionStatusText(): string { + if (this.isConnecting) return '正在连接' + if (this.isConnected) return '已连接' + if (this.reconnectAttempts > 0 && !this.stopReconnect) + return `重连中(${this.reconnectAttempts}/${this.maxReconnectAttempts})` + return '已断开' + } + + // 销毁实例 + static destroyInstance(): void { + if (WebSocketClient.instance) { + WebSocketClient.instance.close() + WebSocketClient.instance = null + } + } +} diff --git a/src/utils/storage/index.ts b/src/utils/storage/index.ts new file mode 100644 index 0000000..a4366f0 --- /dev/null +++ b/src/utils/storage/index.ts @@ -0,0 +1,7 @@ +/** + * 存储相关工具函数统一导出 + */ + +export * from './storage' +export * from './storage-config' +export * from './storage-key-manager' diff --git a/src/utils/storage/storage-config.ts b/src/utils/storage/storage-config.ts new file mode 100644 index 0000000..c41b60b --- /dev/null +++ b/src/utils/storage/storage-config.ts @@ -0,0 +1,122 @@ +/** + * 存储配置管理模块 + * + * 提供统一的本地存储配置和工具方法 + * + * ## 主要功能 + * + * - 版本化存储键管理,支持多版本数据隔离 + * - 存储键名生成和解析(带版本前缀) + * - 版本号提取和验证 + * - 存储键匹配的正则表达式生成 + * - 旧版本存储键兼容处理 + * - 升级和登出延迟配置 + * - 主题存储键配置 + * + * ## 使用场景 + * + * - Pinia Store 持久化存储 + * - 应用版本升级时的数据迁移 + * - 多版本数据清理 + * - 存储键的统一管理和规范 + * + * 存储键格式:sys-v{version}-{storeId} + * 例如:sys-v1.0.0-user, sys-v1.0.0-setting + * + * @module utils/storage/storage-config + * @author Art Design Pro Team + */ +export class StorageConfig { + /** 当前应用版本 */ + static readonly CURRENT_VERSION = __APP_VERSION__ + + /** 存储键前缀 */ + static readonly STORAGE_PREFIX = 'sys-v' + + /** 版本键名 */ + static readonly VERSION_KEY = 'sys-version' + + /** 主题键名(index.html中使用了,如果修改,需要同步修改) */ + static readonly THEME_KEY = 'sys-theme' + + /** 上次登录用户ID键名(用于判断是否为同一用户登录) */ + static readonly LAST_USER_ID_KEY = 'sys-last-user-id' + + /** 跳过升级检查的版本 */ + static readonly SKIP_UPGRADE_VERSION = '1.0.0' + + /** 升级处理延迟时间(毫秒) */ + static readonly UPGRADE_DELAY = 1000 + + /** 登出延迟时间(毫秒) */ + static readonly LOGOUT_DELAY = 1000 + + /** + * 生成版本化的存储键名 + * @param storeId 存储ID + * @param version 版本号,默认使用当前版本 + */ + static generateStorageKey(storeId: string, version: string = this.CURRENT_VERSION): string { + return `${this.STORAGE_PREFIX}${version}-${storeId}` + } + + /** + * 生成旧版本的存储键名(不带分隔符) + * @param version 版本号,默认使用当前版本 + */ + static generateLegacyKey(version: string = this.CURRENT_VERSION): string { + return `${this.STORAGE_PREFIX}${version}` + } + + /** + * 创建存储键匹配的正则表达式 + * @param storeId 存储ID + */ + static createKeyPattern(storeId: string): RegExp { + return new RegExp(`^${this.STORAGE_PREFIX}[^-]+-${storeId}$`) + } + + /** + * 创建当前版本存储键匹配的正则表达式 + */ + static createCurrentVersionPattern(): RegExp { + return new RegExp(`^${this.STORAGE_PREFIX}${this.CURRENT_VERSION}-`) + } + + /** + * 创建任意版本存储键匹配的正则表达式 + */ + static createVersionPattern(): RegExp { + return new RegExp(`^${this.STORAGE_PREFIX}`) + } + + /** + * 检查是否为当前版本的键 + */ + static isCurrentVersionKey(key: string): boolean { + return key.startsWith(`${this.STORAGE_PREFIX}${this.CURRENT_VERSION}`) + } + + /** + * 检查是否为版本化的键 + */ + static isVersionedKey(key: string): boolean { + return key.startsWith(this.STORAGE_PREFIX) + } + + /** + * 从存储键中提取版本号 + */ + static extractVersionFromKey(key: string): string | null { + const match = key.match(new RegExp(`^${this.STORAGE_PREFIX}([^-]+)`)) + return match ? match[1] : null + } + + /** + * 从存储键中提取存储ID + */ + static extractStoreIdFromKey(key: string): string | null { + const match = key.match(new RegExp(`^${this.STORAGE_PREFIX}[^-]+-(.+)$`)) + return match ? match[1] : null + } +} diff --git a/src/utils/storage/storage-key-manager.ts b/src/utils/storage/storage-key-manager.ts new file mode 100644 index 0000000..ba14f65 --- /dev/null +++ b/src/utils/storage/storage-key-manager.ts @@ -0,0 +1,97 @@ +/** + * 存储键名管理器模块 + * + * 提供智能的版本化存储键管理和数据迁移功能 + * + * ## 主要功能 + * + * - 自动生成当前版本的存储键名 + * - 检测当前版本数据是否存在 + * - 查找其他版本的同名存储数据 + * - 自动将旧版本数据迁移到当前版本 + * - 数据迁移日志记录 + * - 迁移失败的错误处理 + * + * ## 使用场景 + * + * - Pinia Store 持久化插件中获取存储键 + * - 应用版本升级时自动迁移用户数据 + * - 避免版本升级导致的数据丢失 + * - 实现平滑的版本过渡 + * + * ## 工作流程 + * + * 1. 优先使用当前版本的存储键 + * 2. 如果当前版本无数据,查找其他版本的同名数据 + * 3. 找到旧版本数据后自动迁移到当前版本 + * 4. 返回当前版本的存储键供使用 + * + * @module utils/storage/storage-key-manager + * @author Art Design Pro Team + */ +import { StorageConfig } from '@/utils/storage' + +/** + * 存储键名管理器 + * 负责处理版本化的存储键名生成和数据迁移 + */ +export class StorageKeyManager { + /** + * 获取当前版本的存储键名 + */ + private getCurrentVersionKey(storeId: string): string { + return StorageConfig.generateStorageKey(storeId) + } + + /** + * 检查当前版本的数据是否存在 + */ + private hasCurrentVersionData(key: string): boolean { + return localStorage.getItem(key) !== null + } + + /** + * 查找其他版本的同名存储键 + */ + private findExistingKey(storeId: string): string | null { + const storageKeys = Object.keys(localStorage) + const pattern = StorageConfig.createKeyPattern(storeId) + + return storageKeys.find((key) => pattern.test(key) && localStorage.getItem(key)) || null + } + + /** + * 将数据从旧版本迁移到当前版本 + */ + private migrateData(fromKey: string, toKey: string): void { + try { + const existingData = localStorage.getItem(fromKey) + if (existingData) { + localStorage.setItem(toKey, existingData) + console.info(`[Storage] 已迁移数据: ${fromKey} → ${toKey}`) + } + } catch (error) { + console.warn(`[Storage] 数据迁移失败: ${fromKey}`, error) + } + } + + /** + * 获取持久化存储的键名(支持自动数据迁移) + */ + getStorageKey(storeId: string): string { + const currentKey = this.getCurrentVersionKey(storeId) + + // 优先使用当前版本的数据 + if (this.hasCurrentVersionData(currentKey)) { + return currentKey + } + + // 查找并迁移其他版本的数据 + const existingKey = this.findExistingKey(storeId) + if (existingKey) { + this.migrateData(existingKey, currentKey) + } + + return currentKey + } +} diff --git a/src/utils/storage/storage.ts b/src/utils/storage/storage.ts new file mode 100644 index 0000000..67b9e9e --- /dev/null +++ b/src/utils/storage/storage.ts @@ -0,0 +1,250 @@ +/** + * 存储兼容性管理模块 + * + * 提供完整的本地存储兼容性检查和数据验证功能 + * + * 主要功能 + * + * - 多版本存储数据检测和验证 + * - 新旧存储格式兼容处理 + * - 存储数据完整性校验 + * - 存储异常自动恢复(清理+登出) + * - 登录状态验证 + * - 存储为空检测 + * - 版本号管理 + * + * ## 使用场景 + * + * - 应用启动时检查存储数据有效性 + * - 路由守卫中验证登录状态 + * - 版本升级时的数据兼容性检查 + * - 存储异常时的自动恢复 + * - 防止因存储数据损坏导致的系统异常 + * + * ## 工作流程 + * + * 1. 优先检查当前版本的存储数据 + * 2. 检查其他版本的存储数据 + * 3. 兼容旧格式的存储数据 + * 4. 验证数据完整性 + * 5. 异常时提示用户并执行登出 + * + * @module utils/storage/storage + * @author Art Design Pro Team + */ +import { router } from '@/router' +import { useUserStore } from '@/store/modules/user' +import { StorageConfig } from '@/utils/storage/storage-config' + +/** + * 存储兼容性管理器 + * 负责处理不同版本间的存储兼容性检查和数据验证 + */ +class StorageCompatibilityManager { + /** + * 获取系统版本号 + */ + getSystemVersion(): string | null { + return localStorage.getItem(StorageConfig.VERSION_KEY) + } + + /** + * 获取系统存储数据(兼容旧格式) + */ + getSystemStorage(): any { + const version = this.getSystemVersion() || StorageConfig.CURRENT_VERSION + const legacyKey = StorageConfig.generateLegacyKey(version) + const data = localStorage.getItem(legacyKey) + return data ? JSON.parse(data) : null + } + + /** + * 检查当前版本是否有存储数据 + */ + private hasCurrentVersionStorage(): boolean { + const storageKeys = Object.keys(localStorage) + const currentVersionPattern = StorageConfig.createCurrentVersionPattern() + + return storageKeys.some( + (key) => currentVersionPattern.test(key) && localStorage.getItem(key) !== null + ) + } + + /** + * 检查是否存在任何版本的存储数据 + */ + private hasAnyVersionStorage(): boolean { + const storageKeys = Object.keys(localStorage) + const versionPattern = StorageConfig.createVersionPattern() + + return storageKeys.some((key) => versionPattern.test(key) && localStorage.getItem(key) !== null) + } + + /** + * 获取旧格式的本地存储数据 + */ + private getLegacyStorageData(): Record { + try { + const systemStorage = this.getSystemStorage() + return systemStorage || {} + } catch (error) { + console.warn('[Storage] 解析旧格式存储数据失败:', error) + return {} + } + } + + /** + * 显示存储错误消息 + */ + private showStorageError(): void { + ElMessage({ + type: 'error', + offset: 40, + duration: 5000, + message: '系统检测到本地数据异常,请重新登录系统恢复使用!' + }) + } + + /** + * 执行系统登出 + */ + private performSystemLogout(): void { + setTimeout(() => { + try { + localStorage.clear() + useUserStore().logOut() + router.push({ name: 'Login' }) + console.info('[Storage] 已执行系统登出') + } catch (error) { + console.error('[Storage] 系统登出失败:', error) + } + }, StorageConfig.LOGOUT_DELAY) + } + + /** + * 处理存储异常 + */ + private handleStorageError(): void { + this.showStorageError() + this.performSystemLogout() + } + + /** + * 验证存储数据完整性 + * @param requireAuth 是否需要验证登录状态(默认 false) + */ + validateStorageData(requireAuth: boolean = false): boolean { + try { + // 优先检查新版本存储结构 + if (this.hasCurrentVersionStorage()) { + // console.debug('[Storage] 发现当前版本存储数据') + return true + } + + // 检查是否有任何版本的存储数据 + if (this.hasAnyVersionStorage()) { + // console.debug('[Storage] 发现其他版本存储数据,可能需要迁移') + return true + } + + // 检查旧版本存储结构 + const legacyData = this.getLegacyStorageData() + if (Object.keys(legacyData).length === 0) { + // 只有在需要验证登录状态时才执行登出操作 + if (requireAuth) { + console.warn('[Storage] 未发现任何存储数据,需要重新登录') + this.performSystemLogout() + return false + } + // 首次访问或访问静态路由,不需要登出 + // console.debug('[Storage] 未发现存储数据,首次访问或访问静态路由') + return true + } + + console.debug('[Storage] 发现旧版本存储数据') + return true + } catch (error) { + console.error('[Storage] 存储数据验证失败:', error) + // 只有在需要验证登录状态时才处理错误 + if (requireAuth) { + this.handleStorageError() + return false + } + return true + } + } + + /** + * 检查存储是否为空 + */ + isStorageEmpty(): boolean { + // 检查新版本存储结构 + if (this.hasCurrentVersionStorage()) { + return false + } + + // 检查是否有任何版本的存储数据 + if (this.hasAnyVersionStorage()) { + return false + } + + // 检查旧版本存储结构 + const legacyData = this.getLegacyStorageData() + return Object.keys(legacyData).length === 0 + } + + /** + * 检查存储兼容性 + * @param requireAuth 是否需要验证登录状态(默认 false) + */ + checkCompatibility(requireAuth: boolean = false): boolean { + try { + const isValid = this.validateStorageData(requireAuth) + const isEmpty = this.isStorageEmpty() + + if (isValid || isEmpty) { + // console.debug('[Storage] 存储兼容性检查通过') + return true + } + + console.warn('[Storage] 存储兼容性检查失败') + return false + } catch (error) { + console.error('[Storage] 兼容性检查异常:', error) + return false + } + } +} + +// 创建存储兼容性管理器实例 +const storageManager = new StorageCompatibilityManager() + +/** + * 获取系统存储数据 + */ +export function getSystemStorage(): any { + return storageManager.getSystemStorage() +} + +/** + * 获取系统版本号 + */ +export function getSysVersion(): string | null { + return storageManager.getSystemVersion() +} + +/** + * 验证本地存储数据 + * @param requireAuth 是否需要验证登录状态(默认 false) + */ +export function validateStorageData(requireAuth: boolean = false): boolean { + return storageManager.validateStorageData(requireAuth) +} + +/** + * 检查存储兼容性 + * @param requireAuth 是否需要验证登录状态(默认 false) + */ +export function checkStorageCompatibility(requireAuth: boolean = false): boolean { + return storageManager.checkCompatibility(requireAuth) +} diff --git a/src/utils/sys/console.ts b/src/utils/sys/console.ts new file mode 100644 index 0000000..d631087 --- /dev/null +++ b/src/utils/sys/console.ts @@ -0,0 +1,13 @@ +// ANSI 转义码生成网站 https://patorjk.com/software/taag/#p=display&f=Big&t=ABB%0A +const asciiArt = ` +\x1b[32m欢迎使用 Art Design Pro! +\x1b[0m +\x1b[36m哇!你居然在用我的项目~ 好用的话别忘了去 GitHub 点个 ★Star 呀,你的支持就是我更新的超强动力!祝使用体验满分💯 +\x1b[0m +\x1b[33mGitHub: https://github.com/Daymychen/art-design-pro +\x1b[0m +\x1b[31m技术支持(QQ群): 1038930070,和开发者一起交流~ 群里有小伙伴实时答疑,遇到问题不用慌! +\x1b[0m +` + +console.log(asciiArt) diff --git a/src/utils/sys/error-handle.ts b/src/utils/sys/error-handle.ts new file mode 100644 index 0000000..22109c2 --- /dev/null +++ b/src/utils/sys/error-handle.ts @@ -0,0 +1,102 @@ +/** + * 全局错误处理模块 + * + * 提供统一的错误捕获和处理机制 + * + * ## 主要功能 + * + * - Vue 运行时错误捕获(组件错误、生命周期错误等) + * - 全局脚本错误捕获(语法错误、运行时错误等) + * - Promise 未捕获错误处理(unhandledrejection) + * - 静态资源加载错误监控(图片、脚本、样式等) + * - 错误日志记录和上报 + * - 统一的错误处理入口 + * + * ## 使用场景 + * - 应用启动时安装全局错误处理器 + * - 捕获和记录所有类型的错误 + * - 错误上报到监控平台 + * - 提升应用稳定性和可维护性 + * - 问题排查和调试 + * + * ## 错误类型 + * + * - VueError: Vue 组件相关错误 + * - ScriptError: JavaScript 脚本错误 + * - PromiseError: Promise 未捕获的 rejection + * - ResourceError: 静态资源加载失败 + * + * @module utils/sys/error-handle + * @author Art Design Pro Team + */ +import type { App } from 'vue' + +/** + * Vue 运行时错误处理 + */ +export function vueErrorHandler(err: unknown, instance: any, info: string) { + console.error('[VueError]', err, info, instance) + // 这里可以上报到服务端,比如: + // reportError({ type: 'vue', err, info }) +} + +/** + * 全局脚本错误处理 + */ +export function scriptErrorHandler( + message: Event | string, + source?: string, + lineno?: number, + colno?: number, + error?: Error +): boolean { + console.error('[ScriptError]', { message, source, lineno, colno, error }) + // reportError({ type: 'script', message, source, lineno, colno, error }) + return true // 阻止默认控制台报错,可根据需求改 +} + +/** + * Promise 未捕获错误处理 + */ +export function registerPromiseErrorHandler() { + window.addEventListener('unhandledrejection', (event) => { + console.error('[PromiseError]', event.reason) + // reportError({ type: 'promise', reason: event.reason }) + }) +} + +/** + * 资源加载错误处理 (img, script, css...) + */ +export function registerResourceErrorHandler() { + window.addEventListener( + 'error', + (event: Event) => { + const target = event.target as HTMLElement + if ( + target && + (target.tagName === 'IMG' || target.tagName === 'SCRIPT' || target.tagName === 'LINK') + ) { + console.error('[ResourceError]', { + tagName: target.tagName, + src: + (target as HTMLImageElement).src || + (target as HTMLScriptElement).src || + (target as HTMLLinkElement).href + }) + // reportError({ type: 'resource', target }) + } + }, + true // 捕获阶段才能监听到资源错误 + ) +} + +/** + * 安装统一错误处理 + */ +export function setupErrorHandle(app: App) { + app.config.errorHandler = vueErrorHandler + window.onerror = scriptErrorHandler + registerPromiseErrorHandler() + registerResourceErrorHandler() +} diff --git a/src/utils/sys/index.ts b/src/utils/sys/index.ts new file mode 100644 index 0000000..a2e0729 --- /dev/null +++ b/src/utils/sys/index.ts @@ -0,0 +1,6 @@ +/** + * 系统管理相关工具函数统一导出 + */ + +export * from './upgrade' +export { default as mittBus } from './mittBus' diff --git a/src/utils/sys/mittBus.ts b/src/utils/sys/mittBus.ts new file mode 100644 index 0000000..22f0108 --- /dev/null +++ b/src/utils/sys/mittBus.ts @@ -0,0 +1,63 @@ +/** + * 全局事件总线模块 + * + * 基于 mitt 库实现的类型安全的事件总线 + * + * ## 主要功能 + * + * - 跨组件通信(发布/订阅模式) + * - 类型安全的事件定义和调用 + * - 全局事件管理(烟花效果、设置面板、搜索对话框等) + * - 解耦组件间的直接依赖 + * + * ## 使用场景 + * + * - 跨层级组件通信 + * - 全局功能触发(设置、搜索、聊天、锁屏等) + * - 特效触发(烟花效果) + * - 避免 props 层层传递 + * + * ## 用法示例 + * + * ```typescript + * // 订阅事件 + * mittBus.on('openSetting', () => { ... }) + * + * // 发布事件 + * mittBus.emit('openSetting') + * + * // 带参数的事件 + * mittBus.emit('triggerFireworks', 'image-url') + * ``` + * + * ## 已定义的事件 + * + * - triggerFireworks: 触发烟花效果(可选图片URL) + * - openSetting: 打开设置面板 + * - openSearchDialog: 打开搜索对话框 + * - openChat: 打开聊天窗口 + * - openLockScreen: 打开锁屏 + * + * @module utils/sys/mittBus + * @author Art Design Pro Team + */ +import mitt, { type Emitter } from 'mitt' + +// 定义事件类型映射 +type Events = { + // 烟花效果事件 - 可选的图片URL参数 + triggerFireworks: string | undefined + // 打开设置面板事件 - 无参数 + openSetting: void + // 打开搜索对话框事件 - 无参数 + openSearchDialog: void + // 打开聊天窗口事件 - 无参数 + openChat: void + // 打开锁屏事件 - 无参数 + openLockScreen: void +} + +// 创建类型安全的事件总线实例 +const mittBus: Emitter = mitt() + +export default mittBus diff --git a/src/utils/sys/upgrade.ts b/src/utils/sys/upgrade.ts new file mode 100644 index 0000000..53d3465 --- /dev/null +++ b/src/utils/sys/upgrade.ts @@ -0,0 +1,277 @@ +/** + * 系统版本升级管理模块 + * + * 提供完整的应用版本升级检测和处理功能 + * + * ## 主要功能 + * + * - 版本号比较和升级检测 + * - 首次访问识别和处理 + * - 旧版本数据自动清理 + * - 升级日志展示和通知 + * - 强制重新登录控制(根据升级日志配置) + * - 版本号规范化处理 + * - 旧存储结构迁移和清理 + * - 升级流程延迟执行(确保应用完全加载) + * + * ## 使用场景 + * + * - 应用启动时自动检测版本升级 + * - 版本更新后清理旧数据 + * - 向用户展示版本更新内容 + * - 重大更新时要求用户重新登录 + * - 防止旧版本数据污染新版本 + * + * ## 工作流程 + * + * 1. 检查本地存储的版本号 + * 2. 与当前应用版本对比 + * 3. 查找并清理旧版本数据 + * 4. 展示升级通知(包含更新日志) + * 5. 根据配置决定是否强制重新登录 + * 6. 更新本地版本号 + * + * @module utils/sys/upgrade + * @author Art Design Pro Team + */ +import { upgradeLogList } from '@/mock/upgrade/changeLog' +import { ElNotification } from 'element-plus' +import { useUserStore } from '@/store/modules/user' +import { StorageConfig } from '@/utils/storage/storage-config' + +/** + * 版本管理器 + * 负责处理版本比较、升级检测和数据清理 + */ +class VersionManager { + /** + * 规范化版本号字符串,移除前缀 'v' + */ + private normalizeVersion(version: string): string { + return version.replace(/^v/, '') + } + + /** + * 获取存储的版本号 + */ + private getStoredVersion(): string | null { + return localStorage.getItem(StorageConfig.VERSION_KEY) + } + + /** + * 设置版本号到存储 + */ + private setStoredVersion(version: string): void { + localStorage.setItem(StorageConfig.VERSION_KEY, version) + } + + /** + * 检查是否应该跳过升级处理 + */ + private shouldSkipUpgrade(): boolean { + return StorageConfig.CURRENT_VERSION === StorageConfig.SKIP_UPGRADE_VERSION + } + + /** + * 检查是否为首次访问 + */ + private isFirstVisit(storedVersion: string | null): boolean { + return !storedVersion + } + + /** + * 检查版本是否相同 + */ + private isSameVersion(storedVersion: string): boolean { + return storedVersion === StorageConfig.CURRENT_VERSION + } + + /** + * 查找旧的存储结构 + */ + private findLegacyStorage(): { oldSysKey: string | null; oldVersionKeys: string[] } { + const storageKeys = Object.keys(localStorage) + const currentVersionPrefix = StorageConfig.generateStorageKey('').slice(0, -1) // 移除末尾的 '-' + + // 查找旧的单一存储结构 + const oldSysKey = + storageKeys.find( + (key) => + StorageConfig.isVersionedKey(key) && key !== currentVersionPrefix && !key.includes('-') + ) || null + + // 查找旧版本的分离存储键 + const oldVersionKeys = storageKeys.filter( + (key) => + StorageConfig.isVersionedKey(key) && + !StorageConfig.isCurrentVersionKey(key) && + key.includes('-') + ) + + return { oldSysKey, oldVersionKeys } + } + + /** + * 检查是否需要重新登录 + */ + private shouldRequireReLogin(storedVersion: string): boolean { + const normalizedCurrent = this.normalizeVersion(StorageConfig.CURRENT_VERSION) + const normalizedStored = this.normalizeVersion(storedVersion) + + return upgradeLogList.value.some((item) => { + const itemVersion = this.normalizeVersion(item.version) + return ( + item.requireReLogin && itemVersion > normalizedStored && itemVersion <= normalizedCurrent + ) + }) + } + + /** + * 构建升级通知消息 + */ + private buildUpgradeMessage(requireReLogin: boolean): string { + const { title: content } = upgradeLogList.value[0] + + const messageParts = [ + `

`, + `系统已升级到 ${StorageConfig.CURRENT_VERSION} 版本,此次更新带来了以下改进:`, + `

`, + content + ] + + if (requireReLogin) { + messageParts.push( + `

升级完成,请重新登录后继续使用。

` + ) + } + + return messageParts.join('') + } + + /** + * 显示升级通知 + */ + private showUpgradeNotification(message: string): void { + ElNotification({ + title: '系统升级公告', + message, + duration: 0, + type: 'success', + dangerouslyUseHTMLString: true + }) + } + + /** + * 清理旧版本数据 + */ + private cleanupLegacyData(oldSysKey: string | null, oldVersionKeys: string[]): void { + // 清理旧的单一存储结构 + if (oldSysKey) { + localStorage.removeItem(oldSysKey) + console.info(`[Upgrade] 已清理旧存储: ${oldSysKey}`) + } + + // 清理旧版本的分离存储 + oldVersionKeys.forEach((key) => { + localStorage.removeItem(key) + console.info(`[Upgrade] 已清理旧存储: ${key}`) + }) + } + + /** + * 执行升级后的登出操作 + */ + private performLogout(): void { + try { + useUserStore().logOut() + console.info('[Upgrade] 已执行升级后登出') + } catch (error) { + console.error('[Upgrade] 升级后登出失败:', error) + } + } + + /** + * 执行升级流程 + */ + private async executeUpgrade( + storedVersion: string, + legacyStorage: ReturnType + ): Promise { + try { + if (!upgradeLogList.value.length) { + console.warn('[Upgrade] 升级日志列表为空') + return + } + + const requireReLogin = this.shouldRequireReLogin(storedVersion) + const message = this.buildUpgradeMessage(requireReLogin) + + // 显示升级通知 + this.showUpgradeNotification(message) + + // 更新版本号 + this.setStoredVersion(StorageConfig.CURRENT_VERSION) + + // 清理旧数据 + this.cleanupLegacyData(legacyStorage.oldSysKey, legacyStorage.oldVersionKeys) + + // 执行登出(如果需要) + if (requireReLogin) { + this.performLogout() + } + + console.info(`[Upgrade] 升级完成: ${storedVersion} → ${StorageConfig.CURRENT_VERSION}`) + } catch (error) { + console.error('[Upgrade] 系统升级处理失败:', error) + } + } + + /** + * 系统升级处理主流程 + */ + async processUpgrade(): Promise { + // 跳过特定版本 + if (this.shouldSkipUpgrade()) { + console.debug('[Upgrade] 跳过版本升级检查') + return + } + + const storedVersion = this.getStoredVersion() + + // 首次访问处理 + if (this.isFirstVisit(storedVersion)) { + this.setStoredVersion(StorageConfig.CURRENT_VERSION) + // console.info('[Upgrade] 首次访问,已设置当前版本') + return + } + + // 版本相同,无需升级 + if (this.isSameVersion(storedVersion!)) { + // console.debug('[Upgrade] 版本相同,无需升级') + return + } + + // 检查是否有需要升级的旧数据 + const legacyStorage = this.findLegacyStorage() + if (!legacyStorage.oldSysKey && legacyStorage.oldVersionKeys.length === 0) { + this.setStoredVersion(StorageConfig.CURRENT_VERSION) + console.info('[Upgrade] 无旧数据,已更新版本号') + return + } + + // 延迟执行升级流程,确保应用已完全加载 + setTimeout(() => { + this.executeUpgrade(storedVersion!, legacyStorage) + }, StorageConfig.UPGRADE_DELAY) + } +} + +// 创建版本管理器实例 +const versionManager = new VersionManager() + +/** + * 系统升级处理入口函数 + */ +export async function systemUpgrade(): Promise { + await versionManager.processUpgrade() +} diff --git a/src/utils/table/tableCache.ts b/src/utils/table/tableCache.ts new file mode 100644 index 0000000..045a7ce --- /dev/null +++ b/src/utils/table/tableCache.ts @@ -0,0 +1,266 @@ +/** + * 表格缓存管理模块 + * + * 提供高性能的表格数据缓存机制 + * + * ## 主要功能 + * + * - 基于参数的智能缓存键生成(使用 ohash) + * - LRU(最近最少使用)缓存淘汰策略 + * - 缓存过期时间管理 + * - 缓存大小限制和自动清理 + * - 基于标签的缓存分组管理 + * - 多种缓存失效策略(清空所有、清空当前、清空分页等) + * - 缓存访问统计和命中率分析 + * - 缓存大小估算 + * + * ## 使用场景 + * + * - 表格数据的分页缓存 + * - 减少重复的 API 请求 + * - 提升表格切换和返回的响应速度 + * - 搜索条件变化时的智能缓存管理 + * - 数据更新后的缓存失效处理 + * + * ## 缓存策略 + * + * - CLEAR_ALL: 清空所有缓存(适用于全局数据更新) + * - CLEAR_CURRENT: 仅清空当前查询条件的缓存(适用于单条数据更新) + * - CLEAR_PAGINATION: 清空所有分页缓存但保留不同搜索条件(适用于批量操作) + * - KEEP_ALL: 不清除缓存(适用于只读操作) + * + * @module utils/table/tableCache + * @author Art Design Pro Team + */ +import { hash } from 'ohash' + +// 缓存失效策略枚举 +export enum CacheInvalidationStrategy { + /** 清空所有缓存 */ + CLEAR_ALL = 'clear_all', + /** 仅清空当前查询条件的缓存 */ + CLEAR_CURRENT = 'clear_current', + /** 清空所有分页缓存(保留不同搜索条件的缓存) */ + CLEAR_PAGINATION = 'clear_pagination', + /** 不清除缓存 */ + KEEP_ALL = 'keep_all' +} + +// 通用 API 响应接口(兼容不同的后端响应格式) +export interface ApiResponse { + records?: T[] + data?: T[] + total?: number + current?: number + size?: number + [key: string]: unknown +} + +// 缓存存储接口 +export interface CacheItem { + data: T[] + response: ApiResponse + timestamp: number + params: string + // 缓存标签,用于分组管理 + tags: Set + // 访问次数(用于 LRU 算法) + accessCount: number + // 最后访问时间 + lastAccessTime: number +} + +// 增强的缓存管理类 +export class TableCache { + private cache = new Map>() + private cacheTime: number + private maxSize: number + private enableLog: boolean + + constructor(cacheTime = 5 * 60 * 1000, maxSize = 50, enableLog = false) { + // 默认5分钟,最多50条缓存 + this.cacheTime = cacheTime + this.maxSize = maxSize + this.enableLog = enableLog + } + + // 内部日志工具 + private log(message: string, ...args: any[]) { + if (this.enableLog) { + console.log(`[TableCache] ${message}`, ...args) + } + } + + // 生成稳定的缓存键 + private generateKey(params: unknown): string { + return hash(params) + } + + // 🔧 优化:增强类型安全性 + private generateTags(params: Record): Set { + const tags = new Set() + + // 添加搜索条件标签 + const searchKeys = Object.keys(params).filter( + (key) => + !['current', 'size', 'total'].includes(key) && + params[key] !== undefined && + params[key] !== '' && + params[key] !== null + ) + + if (searchKeys.length > 0) { + const searchTag = searchKeys.map((key) => `${key}:${String(params[key])}`).join('|') + tags.add(`search:${searchTag}`) + } else { + tags.add('search:default') + } + + // 添加分页标签 + tags.add(`pagination:${params.size || 10}`) + // 添加通用分页标签,用于清理所有分页缓存 + tags.add('pagination') + + return tags + } + + // 🔧 优化:LRU 缓存清理 + private evictLRU(): void { + if (this.cache.size <= this.maxSize) return + + // 找到最少使用的缓存项 + let lruKey = '' + let minAccessCount = Infinity + let oldestTime = Infinity + + for (const [key, item] of this.cache.entries()) { + if ( + item.accessCount < minAccessCount || + (item.accessCount === minAccessCount && item.lastAccessTime < oldestTime) + ) { + lruKey = key + minAccessCount = item.accessCount + oldestTime = item.lastAccessTime + } + } + + if (lruKey) { + this.cache.delete(lruKey) + this.log(`LRU 清理缓存: ${lruKey}`) + } + } + + // 设置缓存 + set(params: unknown, data: T[], response: ApiResponse): void { + const key = this.generateKey(params) + const tags = this.generateTags(params as Record) + const now = Date.now() + + // 检查是否需要清理 + this.evictLRU() + + this.cache.set(key, { + data, + response, + timestamp: now, + params: key, + tags, + accessCount: 1, + lastAccessTime: now + }) + } + + // 获取缓存 + get(params: unknown): CacheItem | null { + const key = this.generateKey(params) + const item = this.cache.get(key) + + if (!item) return null + + // 检查是否过期 + if (Date.now() - item.timestamp > this.cacheTime) { + this.cache.delete(key) + return null + } + + // 更新访问统计 + item.accessCount++ + item.lastAccessTime = Date.now() + + return item + } + + // 根据标签清除缓存 + clearByTags(tags: string[]): number { + let clearedCount = 0 + + for (const [key, item] of this.cache.entries()) { + // 检查是否包含任意一个标签 + const hasMatchingTag = tags.some((tag) => + Array.from(item.tags).some((itemTag) => itemTag.includes(tag)) + ) + + if (hasMatchingTag) { + this.cache.delete(key) + clearedCount++ + } + } + + return clearedCount + } + + // 清除当前搜索条件的缓存 + clearCurrentSearch(params: unknown): number { + const key = this.generateKey(params) + const deleted = this.cache.delete(key) + return deleted ? 1 : 0 + } + + // 清除分页缓存 + clearPagination(): number { + return this.clearByTags(['pagination']) + } + + // 清空所有缓存 + clear(): void { + this.cache.clear() + } + + // 获取缓存统计信息 + getStats(): { total: number; size: string; hitRate: string } { + const total = this.cache.size + let totalSize = 0 + let totalAccess = 0 + + for (const item of this.cache.values()) { + // 粗略估算大小(JSON字符串长度) + totalSize += JSON.stringify(item.data).length + totalAccess += item.accessCount + } + + // 转换为人类可读的大小 + const sizeInKB = (totalSize / 1024).toFixed(2) + const avgHits = total > 0 ? (totalAccess / total).toFixed(1) : '0' + + return { + total, + size: `${sizeInKB}KB`, + hitRate: `${avgHits} avg hits` + } + } + + // 清理过期缓存 + cleanupExpired(): number { + let cleanedCount = 0 + const now = Date.now() + + for (const [key, item] of this.cache.entries()) { + if (now - item.timestamp > this.cacheTime) { + this.cache.delete(key) + cleanedCount++ + } + } + + return cleanedCount + } +} diff --git a/src/utils/table/tableConfig.ts b/src/utils/table/tableConfig.ts new file mode 100644 index 0000000..e464c89 --- /dev/null +++ b/src/utils/table/tableConfig.ts @@ -0,0 +1,55 @@ +/** + * 表格全局配置模块 + * + * 提供表格与后端接口的字段映射配置 + * + * ## 主要功能 + * + * - 响应数据字段自动识别和映射 + * - 支持多种常见的后端响应格式 + * - 请求参数字段映射配置 + * - 可扩展的字段配置机制 + * + * ## 使用场景 + * + * - 适配不同后端的分页接口格式 + * - 统一前端表格组件的数据处理 + * - 减少重复的数据转换代码 + * - 支持多个后端服务的接口对接 + * + * ## 配置说明 + * + * - recordFields: 列表数据字段名(按优先级顺序查找) + * - totalFields: 总条数字段名 + * - currentFields: 当前页码字段名 + * - sizeFields: 每页大小字段名 + * - paginationKey: 前端发送请求时使用的分页参数名 + * + * ## 扩展方式 + * + * 如果后端使用其他字段名,可以在对应数组中添加新的字段名 + * 例如:recordFields: ['list', 'data', 'records', 'items', 'yourCustomField'] + * + * @module utils/table/tableConfig + * @author Art Design Pro Team + */ +export const tableConfig = { + // 响应数据字段映射配置,系统会从接口返回数据中按顺序查找这些字段 + // 列表数据 + recordFields: ['list', 'data', 'records', 'items', 'result', 'rows'], + // 总条数 + totalFields: ['total', 'count'], + // 当前页码 + currentFields: ['current', 'page', 'pageNum'], + // 每页大小 + sizeFields: ['size', 'pageSize', 'limit'], + + // 请求参数映射配置,前端发送请求时使用的分页参数名 + // useTable 组合式函数传递分页参数的时候 用 current 跟 size + paginationKey: { + // 当前页码 + current: 'current', + // 每页大小 + size: 'size' + } +} diff --git a/src/utils/table/tableUtils.ts b/src/utils/table/tableUtils.ts new file mode 100644 index 0000000..3ca9db1 --- /dev/null +++ b/src/utils/table/tableUtils.ts @@ -0,0 +1,297 @@ +/** + * 表格工具函数模块 + * + * 提供表格数据处理和请求管理的核心工具函数 + * + * ## 主要功能 + * + * - 多格式 API 响应自动适配和标准化 + * - 表格数据提取和转换 + * - 分页信息自动更新和校验 + * - 智能防抖函数(支持取消和立即执行) + * - 统一的错误处理机制 + * - 嵌套数据结构解析 + * + * ## 使用场景 + * + * - useTable 组合式函数的底层工具 + * - 适配各种后端接口响应格式 + * - 表格数据的标准化处理 + * - 请求防抖和性能优化 + * - 错误统一处理和日志记录 + * + * ## 支持的响应格式 + * + * 1. 直接数组: [item1, item2, ...] + * 2. 标准对象: { records: [], total: 100 } + * 3. 嵌套data: { data: { list: [], total: 100 } } + * 4. 多种字段名: list/data/records/items/result/rows + * + * ## 核心功能 + * + * - defaultResponseAdapter: 智能识别和转换响应格式 + * - extractTableData: 提取表格数据数组 + * - updatePaginationFromResponse: 更新分页信息 + * - createSmartDebounce: 创建可控的防抖函数 + * - createErrorHandler: 生成错误处理器 + * + * @module utils/table/tableUtils + * @author Art Design Pro Team + */ + +import type { ApiResponse } from './tableCache' +import { tableConfig } from './tableConfig' + +// 请求参数基础接口,扩展分页参数 +export interface BaseRequestParams extends Api.Common.PaginationParams { + [key: string]: unknown +} + +// 错误处理接口 +export interface TableError { + code: string + message: string + details?: unknown +} + +// 辅助函数:从对象中提取记录数组 +function extractRecords(obj: Record, fields: string[]): T[] { + for (const field of fields) { + if (field in obj && Array.isArray(obj[field])) { + return obj[field] as T[] + } + } + return [] +} + +// 辅助函数:从对象中提取总数 +function extractTotal(obj: Record, records: unknown[], fields: string[]): number { + for (const field of fields) { + if (field in obj && typeof obj[field] === 'number') { + return obj[field] as number + } + } + return records.length +} + +// 辅助函数:提取分页参数 +function extractPagination( + obj: Record, + data?: Record +): Pick, 'current' | 'size'> | undefined { + const result: Partial, 'current' | 'size'>> = {} + const sources = [obj, data ?? {}] + + const currentFields = tableConfig.currentFields + for (const src of sources) { + for (const field of currentFields) { + if (field in src && typeof src[field] === 'number') { + result.current = src[field] as number + break + } + } + if (result.current !== undefined) break + } + + const sizeFields = tableConfig.sizeFields + for (const src of sources) { + for (const field of sizeFields) { + if (field in src && typeof src[field] === 'number') { + result.size = src[field] as number + break + } + } + if (result.size !== undefined) break + } + + if (result.current === undefined && result.size === undefined) return undefined + return result +} + +/** + * 默认响应适配器 - 支持多种常见的API响应格式 + */ +export const defaultResponseAdapter = (response: unknown): ApiResponse => { + // 定义支持的字段 + const recordFields = tableConfig.recordFields + + if (!response) { + return { records: [], total: 0 } + } + + if (Array.isArray(response)) { + return { records: response, total: response.length } + } + + if (typeof response !== 'object') { + console.warn( + '[tableUtils] 无法识别的响应格式,支持的格式包括: 数组、包含' + + recordFields.join('/') + + '字段的对象、嵌套data对象。当前格式:', + response + ) + return { records: [], total: 0 } + } + + const res = response as Record + let records: T[] = [] + let total = 0 + let pagination: Pick, 'current' | 'size'> | undefined + + // 处理标准格式或直接列表 + records = extractRecords(res, recordFields) + total = extractTotal(res, records, tableConfig.totalFields) + pagination = extractPagination(res) + + // 如果没有找到,检查嵌套data + if (records.length === 0 && 'data' in res && typeof res.data === 'object') { + const data = res.data as Record + records = extractRecords(data, ['list', 'records', 'items']) + total = extractTotal(data, records, tableConfig.totalFields) + pagination = extractPagination(res, data) + + if (Array.isArray(res.data)) { + records = res.data as T[] + total = records.length + } + } + + if (!recordFields.some((field) => field in res) && records.length === 0) { + console.warn('[tableUtils] 无法识别的响应格式') + console.warn('支持的字段包括: ' + recordFields.join('、'), response) + console.warn('扩展字段请到 utils/table/tableConfig 文件配置') + } + + const result: ApiResponse = { records, total } + if (pagination) { + Object.assign(result, pagination) + } + return result +} + +/** + * 从标准化的API响应中提取表格数据 + */ +export const extractTableData = (response: ApiResponse): T[] => { + const data = response.records || response.data || [] + return Array.isArray(data) ? data : [] +} + +/** + * 根据API响应更新分页信息 + */ +export const updatePaginationFromResponse = ( + pagination: Api.Common.PaginationParams, + response: ApiResponse +): void => { + pagination.total = response.total ?? pagination.total ?? 0 + + if (response.current !== undefined) { + pagination.current = response.current + } + + const maxPage = Math.max(1, Math.ceil(pagination.total / (pagination.size || 1))) + if (pagination.current > maxPage) { + pagination.current = maxPage + } +} + +/** + * 创建智能防抖函数 - 支持取消和立即执行 + */ +export const createSmartDebounce = Promise>( + fn: T, + delay: number +): T & { cancel: () => void; flush: () => Promise } => { + let timeoutId: NodeJS.Timeout | null = null + let lastArgs: Parameters | null = null + let lastResolve: ((value: any) => void) | null = null + let lastReject: ((reason: any) => void) | null = null + + const debouncedFn = (...args: Parameters): Promise => { + return new Promise((resolve, reject) => { + if (timeoutId) clearTimeout(timeoutId) + lastArgs = args + lastResolve = resolve + lastReject = reject + timeoutId = setTimeout(async () => { + try { + const result = await fn(...args) + resolve(result) + } catch (error) { + reject(error) + } finally { + timeoutId = null + lastArgs = null + lastResolve = null + lastReject = null + } + }, delay) + }) + } + + debouncedFn.cancel = () => { + if (timeoutId) clearTimeout(timeoutId) + timeoutId = null + lastArgs = null + lastResolve = null + lastReject = null + } + + debouncedFn.flush = async () => { + if (timeoutId && lastArgs && lastResolve && lastReject) { + clearTimeout(timeoutId) + timeoutId = null + const args = lastArgs + const resolve = lastResolve + const reject = lastReject + lastArgs = null + lastResolve = null + lastReject = null + try { + const result = await fn(...args) + resolve(result) + return result + } catch (error) { + reject(error) + throw error + } + } + return Promise.resolve() + } + + return debouncedFn as any +} + +/** + * 生成错误处理函数 + */ +export const createErrorHandler = ( + onError?: (error: TableError) => void, + enableLog: boolean = false +) => { + const logger = { + error: (message: string, ...args: any[]) => { + if (enableLog) console.error(`[useTable] ${message}`, ...args) + } + } + + return (err: unknown, context: string): TableError => { + const tableError: TableError = { + code: 'UNKNOWN_ERROR', + message: '未知错误', + details: err + } + + if (err instanceof Error) { + tableError.message = err.message + tableError.code = err.name + } else if (typeof err === 'string') { + tableError.message = err + } + + logger.error(`${context}:`, err) + onError?.(tableError) + return tableError + } +} diff --git a/src/utils/ui/animation.ts b/src/utils/ui/animation.ts new file mode 100644 index 0000000..5efd02a --- /dev/null +++ b/src/utils/ui/animation.ts @@ -0,0 +1,80 @@ +/** + * 主题动画工具模块 + * + * 提供主题切换的视觉动画效果 + * + * ## 主要功能 + * + * - 基于鼠标点击位置的圆形扩散动画 + * - View Transition API 支持(现代浏览器) + * - 降级处理(不支持动画的浏览器) + * - 暗黑主题切换过渡效果 + * - 页面刷新时的主题过渡优化 + * + * ## 使用场景 + * + * - 明暗主题切换 + * - 提升用户体验的视觉反馈 + * - 页面刷新时的平滑过渡 + * + * ## 技术实现 + * + * - 使用 CSS 变量存储点击位置和半径 + * - 利用 View Transition API 实现流畅动画 + * - 通过 CSS class 控制过渡效果 + * - 自动计算最大扩散半径 + * + * @module utils/theme/animation + * @author Art Design Pro Team + */ +import { useCommon } from '@/hooks/core/useCommon' +import { useTheme } from '@/hooks/core/useTheme' +import { SystemThemeEnum } from '@/enums/appEnum' +import { useSettingStore } from '@/store/modules/setting' +const { LIGHT, DARK } = SystemThemeEnum + +/** + * 主题切换动画 + * @param e 鼠标点击事件 + */ +export const themeAnimation = (e: any) => { + const x = e.clientX + const y = e.clientY + // 计算鼠标点击位置距离视窗的最大圆半径 + const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y)) + + // 设置CSS变量 + document.documentElement.style.setProperty('--x', x + 'px') + document.documentElement.style.setProperty('--y', y + 'px') + document.documentElement.style.setProperty('--r', endRadius + 'px') + + if (document.startViewTransition) { + document.startViewTransition(() => toggleTheme()) + } else { + toggleTheme() + } +} + +/** + * 切换主题 + */ +const toggleTheme = () => { + useTheme().switchThemeStyles(useSettingStore().systemThemeType === LIGHT ? DARK : LIGHT) + useCommon().refresh() +} + +/** + * 切换主题过渡效果 + * @param enable 是否启用过渡效果 + */ +export const toggleTransition = (enable: boolean) => { + const body = document.body + + if (enable) { + body.classList.add('theme-change') + } else { + setTimeout(() => { + body.classList.remove('theme-change') + }, 300) + } +} diff --git a/src/utils/ui/colors.ts b/src/utils/ui/colors.ts new file mode 100644 index 0000000..b4f6b77 --- /dev/null +++ b/src/utils/ui/colors.ts @@ -0,0 +1,273 @@ +/** + * 颜色处理工具模块 + * + * 提供完整的颜色格式转换和处理功能 + * + * ## 主要功能 + * + * - Hex 与 RGB/RGBA 格式互转 + * - 颜色混合计算 + * - 颜色变浅/变深处理 + * - Element Plus 主题色自动生成 + * - 颜色格式验证 + * - CSS 变量读取 + * - 暗黑模式颜色适配 + * + * ## 使用场景 + * + * - 主题色动态切换 + * - Element Plus 组件主题定制 + * - 颜色渐变生成 + * - 明暗主题颜色计算 + * - 颜色格式标准化 + * + * ## 核心功能 + * + * - hexToRgba: Hex 转 RGBA(支持透明度) + * - hexToRgb: Hex 转 RGB 数组 + * - rgbToHex: RGB 转 Hex + * - colourBlend: 两种颜色混合 + * - getLightColor: 生成变浅的颜色 + * - getDarkColor: 生成变深的颜色 + * - handleElementThemeColor: 处理 Element Plus 主题色 + * - setElementThemeColor: 设置完整的主题色系统 + * + * ## 支持格式 + * + * - Hex: #FFF, #FFFFFF + * - RGB: rgb(255, 255, 255) + * - RGBA: rgba(255, 255, 255, 0.5) + * + * @module utils/ui/colors + * @author Art Design Pro Team + */ +import { useSettingStore } from '@/store/modules/setting' + +/** + * 颜色转换结果接口 + */ +interface RgbaResult { + red: number + green: number + blue: number + rgba: string +} + +/** + * 获取CSS变量值(别名函数) + * @param name CSS变量名 + * @returns CSS变量值 + */ +export function getCssVar(name: string): string { + return getComputedStyle(document.documentElement).getPropertyValue(name) +} + +/** + * 验证hex颜色格式 + * @param hex hex颜色值 + * @returns 是否为有效的hex颜色 + */ +function isValidHexColor(hex: string): boolean { + const cleanHex = hex.trim().replace(/^#/, '') + return /^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(cleanHex) +} + +/** + * 验证RGB颜色值 + * @param r 红色值 + * @param g 绿色值 + * @param b 蓝色值 + * @returns 是否为有效的RGB值 + */ +function isValidRgbValue(r: number, g: number, b: number): boolean { + const isValid = (value: number) => Number.isInteger(value) && value >= 0 && value <= 255 + return isValid(r) && isValid(g) && isValid(b) +} + +/** + * 将hex颜色转换为RGBA + * @param hex hex颜色值 (支持 #FFF 或 #FFFFFF 格式) + * @param opacity 透明度 (0-1) + * @returns 包含RGB值和RGBA字符串的对象 + */ +export function hexToRgba(hex: string, opacity: number): RgbaResult { + if (!isValidHexColor(hex)) { + throw new Error('Invalid hex color format') + } + + // 移除可能存在的 # 前缀并转换为大写 + let cleanHex = hex.trim().replace(/^#/, '').toUpperCase() + + // 如果是缩写形式(如 FFF),转换为完整形式 + if (cleanHex.length === 3) { + cleanHex = cleanHex + .split('') + .map((char) => char.repeat(2)) + .join('') + } + + // 解析 RGB 值 + const [red, green, blue] = cleanHex.match(/\w\w/g)!.map((x) => parseInt(x, 16)) + + // 确保 opacity 在有效范围内 + const validOpacity = Math.max(0, Math.min(1, opacity)) + + // 构建 RGBA 字符串 + const rgba = `rgba(${red}, ${green}, ${blue}, ${validOpacity.toFixed(2)})` + + return { red, green, blue, rgba } +} + +/** + * 将hex颜色转换为RGB数组 + * @param hexColor hex颜色值 + * @returns RGB数组 [r, g, b] + */ +export function hexToRgb(hexColor: string): number[] { + if (!isValidHexColor(hexColor)) { + ElMessage.warning('输入错误的hex颜色值') + throw new Error('Invalid hex color format') + } + + const cleanHex = hexColor.replace(/^#/, '') + let hex = cleanHex + + // 处理缩写形式 + if (hex.length === 3) { + hex = hex + .split('') + .map((char) => char.repeat(2)) + .join('') + } + + const hexPairs = hex.match(/../g) + if (!hexPairs) { + throw new Error('Invalid hex color format') + } + + return hexPairs.map((hexPair) => parseInt(hexPair, 16)) +} + +/** + * 将RGB颜色转换为hex + * @param r 红色值 (0-255) + * @param g 绿色值 (0-255) + * @param b 蓝色值 (0-255) + * @returns hex颜色值 + */ +export function rgbToHex(r: number, g: number, b: number): string { + if (!isValidRgbValue(r, g, b)) { + ElMessage.warning('输入错误的RGB颜色值') + throw new Error('Invalid RGB color values') + } + + const toHex = (value: number) => { + const hex = value.toString(16) + return hex.length === 1 ? `0${hex}` : hex + } + + return `#${toHex(r)}${toHex(g)}${toHex(b)}` +} + +/** + * 颜色混合 + * @param color1 第一个颜色 + * @param color2 第二个颜色 + * @param ratio 混合比例 (0-1) + * @returns 混合后的颜色 + */ +export function colourBlend(color1: string, color2: string, ratio: number): string { + const validRatio = Math.max(0, Math.min(1, Number(ratio))) + + const rgb1 = hexToRgb(color1) + const rgb2 = hexToRgb(color2) + + const blendedRgb = rgb1.map((value1, index) => { + const value2 = rgb2[index] + return Math.round(value1 * (1 - validRatio) + value2 * validRatio) + }) + + return rgbToHex(blendedRgb[0], blendedRgb[1], blendedRgb[2]) +} + +/** + * 获取变浅的颜色 + * @param color 原始颜色 + * @param level 变浅程度 (0-1) + * @param isDark 是否为暗色主题 + * @returns 变浅后的颜色 + */ +export function getLightColor(color: string, level: number, isDark: boolean = false): string { + if (!isValidHexColor(color)) { + ElMessage.warning('输入错误的hex颜色值') + throw new Error('Invalid hex color format') + } + + if (isDark) { + return getDarkColor(color, level) + } + + const rgb = hexToRgb(color) + const lightRgb = rgb.map((value) => Math.floor((255 - value) * level + value)) + + return rgbToHex(lightRgb[0], lightRgb[1], lightRgb[2]) +} + +/** + * 获取变深的颜色 + * @param color 原始颜色 + * @param level 变深程度 (0-1) + * @returns 变深后的颜色 + */ +export function getDarkColor(color: string, level: number): string { + if (!isValidHexColor(color)) { + ElMessage.warning('输入错误的hex颜色值') + throw new Error('Invalid hex color format') + } + + const rgb = hexToRgb(color) + const darkRgb = rgb.map((value) => Math.floor(value * (1 - level))) + + return rgbToHex(darkRgb[0], darkRgb[1], darkRgb[2]) +} + +/** + * 处理 Element Plus 主题颜色 + * @param theme 主题颜色 + * @param isDark 是否为暗色主题 + */ +export function handleElementThemeColor(theme: string, isDark: boolean = false): void { + document.documentElement.style.setProperty('--el-color-primary', theme) + + for (let i = 1; i <= 9; i++) { + document.documentElement.style.setProperty( + `--el-color-primary-light-${i}`, + getLightColor(theme, i / 10, isDark) + ) + } + + for (let i = 1; i <= 9; i++) { + document.documentElement.style.setProperty( + `--el-color-primary-dark-${i}`, + getDarkColor(theme, i / 10) + ) + } +} + +/** + * 设置 Element Plus 主题颜色 + * @param color 主题颜色 + */ +export function setElementThemeColor(color: string): void { + const mixColor = '#ffffff' + const elStyle = document.documentElement.style + + elStyle.setProperty('--el-color-primary', color) + handleElementThemeColor(color, useSettingStore().isDark) + + // 生成更淡一点的颜色 + for (let i = 1; i < 16; i++) { + const itemColor = colourBlend(color, mixColor, i / 16) + elStyle.setProperty(`--el-color-primary-custom-${i}`, itemColor) + } +} diff --git a/src/utils/ui/emojo.ts b/src/utils/ui/emojo.ts new file mode 100644 index 0000000..cabad7d --- /dev/null +++ b/src/utils/ui/emojo.ts @@ -0,0 +1,24 @@ +/** + * 表情 + * 用于在消息提示的时候显示对应的表情 + * + * 用法 + * ElMessage.success(`${EmojiText[200]} 图片上传成功`) + * ElMessage.error(`${EmojiText[400]} 图片上传失败`) + * ElMessage.error(`${EmojiText[500]} 图片上传失败`) + * + * @module utils/ui/emojo + * @author Art Design Pro Team + */ + +// macos 用户 按 shift + 6 可以唤出更多表情…… +const EmojiText: { [key: string]: string } = { + '0': 'O_O', // 空 + '200': '^_^', // 成功 + '400': 'T_T', // 错误请求 + '500': 'X_X' // 服务器内部错误,无法完成请求 +} + +// const EmojiIcon = ['🟢', '🔴', '🟡 ', '🚀', '✨', '💡', '🛠️', '🔥', '🎉', '🌟', '🌈'] + +export default EmojiText diff --git a/src/utils/ui/iconify-loader.ts b/src/utils/ui/iconify-loader.ts new file mode 100644 index 0000000..035de16 --- /dev/null +++ b/src/utils/ui/iconify-loader.ts @@ -0,0 +1,31 @@ +/** + * 离线图标加载器 + * + * 用于在内网环境下支持 Iconify 图标的离线加载。 + * 通过预加载图标集数据,避免运行时从 CDN 获取图标。 + * + * 使用方式: + * 1. 安装所需图标集:pnpm add -D @iconify-json/[icon-set-name] + * 2. 在此文件中导入并注册图标集 + * 3. 在组件中使用: + * + * @module utils/ui/iconify-loader + * @author Art Design Pro Team + */ + +// import { addCollection } from '@iconify/vue' + +// // 导入离线图标数据 + +// // 系统必要图标库 +// import riIcons from '@iconify-json/ri/icons.json' + +// // 演示图标库(可选,生产环境可移除) +// import svgSpinners from '@iconify-json/svg-spinners/icons.json' +// import lineMd from '@iconify-json/line-md/icons.json' + +// // 注册离线图标集 + +// addCollection(riIcons) +// addCollection(svgSpinners) +// addCollection(lineMd) diff --git a/src/utils/ui/index.ts b/src/utils/ui/index.ts new file mode 100644 index 0000000..9ca1049 --- /dev/null +++ b/src/utils/ui/index.ts @@ -0,0 +1,11 @@ +/** + * UI 相关工具函数统一导出 + * + * @module utils/ui/index + * @author Art Design Pro Team + */ + +export * from './colors' +export * from './loading' +export * from './tabs' +export * from './emojo' diff --git a/src/utils/ui/loading.ts b/src/utils/ui/loading.ts new file mode 100644 index 0000000..6580e02 --- /dev/null +++ b/src/utils/ui/loading.ts @@ -0,0 +1,84 @@ +/** + * 全局 Loading 加载管理模块 + * + * 提供统一的全屏加载动画管理 + * + * ## 主要功能 + * + * - 全屏 Loading 显示和隐藏 + * - 自动适配明暗主题背景色 + * - 自定义 SVG 加载动画 + * - 单例模式防止重复创建 + * - 锁定页面交互 + * + * ## 使用场景 + * + * - 页面初始化加载 + * - 大量数据请求 + * - 路由切换过渡 + * - 异步操作等待 + * + * ## 特性 + * + * - 自动检测当前主题并应用对应背景色 + * - 使用自定义 SVG 动画(四点旋转) + * - 单例模式确保同时只有一个 Loading + * - 提供便捷的显示/隐藏方法 + * + * @module utils/ui/loading + * @author Art Design Pro Team + */ +import { fourDotsSpinnerSvg } from '@/assets/svg/loading' + +/** + * 获取当前主题对应的loading背景色 + * @returns 背景色字符串 + */ +const getLoadingBackground = (): string => { + const isDark = document.documentElement.classList.contains('dark') + return isDark ? 'rgba(7, 7, 7, 0.85)' : '#fff' +} + +const DEFAULT_LOADING_CONFIG = { + lock: true, + get background() { + return getLoadingBackground() + }, + svg: fourDotsSpinnerSvg, + svgViewBox: '0 0 40 40', + customClass: 'art-loading-fix' +} as const + +interface LoadingInstance { + close: () => void +} + +let loadingInstance: LoadingInstance | null = null + +export const loadingService = { + /** + * 显示 loading + * @returns 关闭 loading 的函数 + */ + showLoading(): () => void { + if (!loadingInstance) { + // 每次显示时获取最新的配置,确保背景色与当前主题同步 + const config = { + ...DEFAULT_LOADING_CONFIG, + background: getLoadingBackground() + } + loadingInstance = ElLoading.service(config) + } + return () => this.hideLoading() + }, + + /** + * 隐藏 loading + */ + hideLoading(): void { + if (loadingInstance) { + loadingInstance.close() + loadingInstance = null + } + } +} diff --git a/src/utils/ui/tabs.ts b/src/utils/ui/tabs.ts new file mode 100644 index 0000000..5f53ea5 --- /dev/null +++ b/src/utils/ui/tabs.ts @@ -0,0 +1,60 @@ +/** + * 标签页布局配置模块 + * + * 提供不同标签页样式的高度和间距配置 + * + * ## 主要功能 + * + * - 多种标签页样式配置(默认、卡片、谷歌风格) + * - 标签页打开/关闭状态的高度管理 + * - 顶部间距自动计算 + * - 配置获取和默认值处理 + * + * ## 使用场景 + * + * - 工作标签页(Worktab)布局计算 + * - 页面内容区域高度调整 + * - 标签页显示/隐藏时的动画 + * - 响应式布局适配 + * + * ## 配置项说明 + * + * - openTop: 标签页显示时,内容区域距离顶部的距离 + * - closeTop: 标签页隐藏时,内容区域距离顶部的距离 + * - openHeight: 标签页显示时的总高度(包含标签栏) + * - closeHeight: 标签页隐藏时的总高度(仅头部) + * + * ## 支持的样式 + * + * - tab-default: 默认标签页样式 + * - tab-card: 卡片式标签页 + * - tab-google: 谷歌浏览器风格标签页 + * + * @module utils/ui/tabs + * @author Art Design Pro Team + */ +export const TAB_CONFIG = { + 'tab-default': { + openTop: 106, + closeTop: 60, + openHeight: 121, + closeHeight: 75 + }, + 'tab-card': { + openTop: 122, + closeTop: 78, + openHeight: 139, + closeHeight: 95 + }, + 'tab-google': { + openTop: 122, + closeTop: 78, + openHeight: 139, + closeHeight: 95 + } +} + +// 获取当前 tab 样式配置,设置默认值 +export const getTabConfig = (style: string) => { + return TAB_CONFIG[style as keyof typeof TAB_CONFIG] || TAB_CONFIG['tab-card'] // 默认使用 tab-card 配置 +} diff --git a/src/views/auth/forget-password/index.vue b/src/views/auth/forget-password/index.vue new file mode 100644 index 0000000..147259e --- /dev/null +++ b/src/views/auth/forget-password/index.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/src/views/auth/login/index.vue b/src/views/auth/login/index.vue new file mode 100644 index 0000000..2a857d7 --- /dev/null +++ b/src/views/auth/login/index.vue @@ -0,0 +1,284 @@ + + + + + + + + diff --git a/src/views/auth/login/style.css b/src/views/auth/login/style.css new file mode 100644 index 0000000..bd8c3a9 --- /dev/null +++ b/src/views/auth/login/style.css @@ -0,0 +1,38 @@ +@reference '@styles/core/tailwind.css'; + +/* 授权页右侧区域 */ +.auth-right-wrap { + @apply absolute inset-0 w-[440px] h-[650px] py-[5px] m-auto overflow-hidden + max-sm:px-7 max-sm:w-full + animate-[slideInRight_0.6s_cubic-bezier(0.25,0.46,0.45,0.94)_forwards] + max-md:animate-none; + + .form { + @apply h-full py-[40px]; + } + + .title { + @apply text-g-900 text-4xl font-semibold max-md:text-3xl max-sm:pt-10; + } + + .sub-title { + @apply mt-[10px] text-g-600 text-sm; + } + + .custom-height { + @apply !h-[40px]; + } +} + +/* 滑入动画 */ +@keyframes slideInRight { + from { + opacity: 0; + transform: translateX(30px); + } + + to { + opacity: 1; + transform: translateX(0); + } +} diff --git a/src/views/auth/register/index.vue b/src/views/auth/register/index.vue new file mode 100644 index 0000000..9a8570d --- /dev/null +++ b/src/views/auth/register/index.vue @@ -0,0 +1,240 @@ + + + + + + diff --git a/src/views/dashboard/console/index.vue b/src/views/dashboard/console/index.vue new file mode 100644 index 0000000..154c330 --- /dev/null +++ b/src/views/dashboard/console/index.vue @@ -0,0 +1,41 @@ + + + + diff --git a/src/views/dashboard/console/modules/about-project.vue b/src/views/dashboard/console/modules/about-project.vue new file mode 100644 index 0000000..ed946ce --- /dev/null +++ b/src/views/dashboard/console/modules/about-project.vue @@ -0,0 +1,44 @@ + + + diff --git a/src/views/dashboard/console/modules/active-user.vue b/src/views/dashboard/console/modules/active-user.vue new file mode 100644 index 0000000..da740f2 --- /dev/null +++ b/src/views/dashboard/console/modules/active-user.vue @@ -0,0 +1,47 @@ + + + diff --git a/src/views/dashboard/console/modules/card-list.vue b/src/views/dashboard/console/modules/card-list.vue new file mode 100644 index 0000000..5fc76a7 --- /dev/null +++ b/src/views/dashboard/console/modules/card-list.vue @@ -0,0 +1,74 @@ + + + diff --git a/src/views/dashboard/console/modules/dynamic-stats.vue b/src/views/dashboard/console/modules/dynamic-stats.vue new file mode 100644 index 0000000..1876950 --- /dev/null +++ b/src/views/dashboard/console/modules/dynamic-stats.vue @@ -0,0 +1,79 @@ + + + diff --git a/src/views/dashboard/console/modules/new-user.vue b/src/views/dashboard/console/modules/new-user.vue new file mode 100644 index 0000000..9d39522 --- /dev/null +++ b/src/views/dashboard/console/modules/new-user.vue @@ -0,0 +1,169 @@ + + + + + diff --git a/src/views/dashboard/console/modules/sales-overview.vue b/src/views/dashboard/console/modules/sales-overview.vue new file mode 100644 index 0000000..32904b8 --- /dev/null +++ b/src/views/dashboard/console/modules/sales-overview.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/views/dashboard/console/modules/todo-list.vue b/src/views/dashboard/console/modules/todo-list.vue new file mode 100644 index 0000000..ab9a86c --- /dev/null +++ b/src/views/dashboard/console/modules/todo-list.vue @@ -0,0 +1,71 @@ + + + diff --git a/src/views/exception/403/index.vue b/src/views/exception/403/index.vue new file mode 100644 index 0000000..2756c42 --- /dev/null +++ b/src/views/exception/403/index.vue @@ -0,0 +1,16 @@ + + + + diff --git a/src/views/exception/404/index.vue b/src/views/exception/404/index.vue new file mode 100644 index 0000000..6b64f45 --- /dev/null +++ b/src/views/exception/404/index.vue @@ -0,0 +1,16 @@ + + + + diff --git a/src/views/exception/500/index.vue b/src/views/exception/500/index.vue new file mode 100644 index 0000000..1b26377 --- /dev/null +++ b/src/views/exception/500/index.vue @@ -0,0 +1,16 @@ + + + + diff --git a/src/views/index/index.vue b/src/views/index/index.vue new file mode 100644 index 0000000..415a436 --- /dev/null +++ b/src/views/index/index.vue @@ -0,0 +1,29 @@ + + + + + + diff --git a/src/views/index/style.scss b/src/views/index/style.scss new file mode 100644 index 0000000..c89f354 --- /dev/null +++ b/src/views/index/style.scss @@ -0,0 +1,93 @@ +.app-layout { + display: flex; + width: 100%; + min-height: 100vh; + background: var(--default-bg-color); + + #app-sidebar { + flex-shrink: 0; + } + + #app-main { + display: flex; + flex: 1; + flex-direction: column; + min-width: 0; + height: 100vh; + overflow: auto; + + #app-header { + position: sticky; + top: 0; + z-index: 50; + flex-shrink: 0; + width: 100%; + } + + #app-content { + flex: 1; + + :deep(.layout-content) { + box-sizing: border-box; + width: calc(100% - 40px); + margin: auto; + + // 子页面默认 style + .page-content { + position: relative; + box-sizing: border-box; + padding: 20px; + overflow: hidden; + background: var(--default-box-color); + border-radius: calc(var(--custom-radius) / 2 + 2px) !important; + } + } + } + } +} + +@media only screen and (width <= 1180px) { + .app-layout { + #app-main { + height: 100dvh; + } + } +} + +@media only screen and (width <= 800px) { + .app-layout { + position: relative; + + #app-sidebar { + position: fixed; + top: 0; + left: 0; + z-index: 300; + height: 100vh; + } + + #app-main { + width: 100%; + height: auto; + overflow: visible; + + #app-content { + :deep(.layout-content) { + width: calc(100% - 40px); + } + } + } + } +} + +@media only screen and (width <= 640px) { + .app-layout { + #app-main { + #app-content { + :deep(.layout-content) { + width: calc(100% - 30px); + } + } + } + } +} diff --git a/src/views/outside/Iframe.vue b/src/views/outside/Iframe.vue new file mode 100644 index 0000000..33ea0dc --- /dev/null +++ b/src/views/outside/Iframe.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/views/result/fail/index.vue b/src/views/result/fail/index.vue new file mode 100644 index 0000000..8fe2583 --- /dev/null +++ b/src/views/result/fail/index.vue @@ -0,0 +1,28 @@ + + + diff --git a/src/views/result/success/index.vue b/src/views/result/success/index.vue new file mode 100644 index 0000000..ae57aba --- /dev/null +++ b/src/views/result/success/index.vue @@ -0,0 +1,21 @@ + + + diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue new file mode 100644 index 0000000..973b1e7 --- /dev/null +++ b/src/views/system/menu/index.vue @@ -0,0 +1,479 @@ + + + + diff --git a/src/views/system/menu/modules/menu-dialog.vue b/src/views/system/menu/modules/menu-dialog.vue new file mode 100644 index 0000000..f512301 --- /dev/null +++ b/src/views/system/menu/modules/menu-dialog.vue @@ -0,0 +1,384 @@ + + + diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue new file mode 100644 index 0000000..aca447e --- /dev/null +++ b/src/views/system/role/index.vue @@ -0,0 +1,242 @@ + + + + diff --git a/src/views/system/role/modules/role-edit-dialog.vue b/src/views/system/role/modules/role-edit-dialog.vue new file mode 100644 index 0000000..46ff9b1 --- /dev/null +++ b/src/views/system/role/modules/role-edit-dialog.vue @@ -0,0 +1,162 @@ + + + diff --git a/src/views/system/role/modules/role-permission-dialog.vue b/src/views/system/role/modules/role-permission-dialog.vue new file mode 100644 index 0000000..3691ac8 --- /dev/null +++ b/src/views/system/role/modules/role-permission-dialog.vue @@ -0,0 +1,254 @@ + + + diff --git a/src/views/system/role/modules/role-search.vue b/src/views/system/role/modules/role-search.vue new file mode 100644 index 0000000..1d59cee --- /dev/null +++ b/src/views/system/role/modules/role-search.vue @@ -0,0 +1,121 @@ + + + diff --git a/src/views/system/user-center/index.vue b/src/views/system/user-center/index.vue new file mode 100644 index 0000000..ab52f00 --- /dev/null +++ b/src/views/system/user-center/index.vue @@ -0,0 +1,247 @@ + + + + diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue new file mode 100644 index 0000000..fb794d7 --- /dev/null +++ b/src/views/system/user/index.vue @@ -0,0 +1,261 @@ + + + + + + + + diff --git a/src/views/system/user/modules/user-dialog.vue b/src/views/system/user/modules/user-dialog.vue new file mode 100644 index 0000000..03cab4f --- /dev/null +++ b/src/views/system/user/modules/user-dialog.vue @@ -0,0 +1,143 @@ + + + diff --git a/src/views/system/user/modules/user-search.vue b/src/views/system/user/modules/user-search.vue new file mode 100644 index 0000000..e097720 --- /dev/null +++ b/src/views/system/user/modules/user-search.vue @@ -0,0 +1,112 @@ + + + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4331962 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "moduleResolution": "node", + "strict": true, + "jsx": "preserve", + "sourceMap": true, + "resolveJsonModule": true, + "esModuleInterop": true, + "lib": ["esnext", "dom"], + "types": ["vite/client", "node", "element-plus/global"], + "skipLibCheck": true, + "baseUrl": ".", + "paths": { + "@/*": ["src/*"], + "@views/*": ["src/views/*"], + "@imgs/*": ["src/assets/images/*"], + "@icons/*": ["src/assets/icons/*"], + "@utils/*": ["src/utils/*"], + "@stores/*": ["src/store/*"], + "@plugins/*": ["src/plugins/*"], + "@styles/*": ["src/assets/styles/*"] + } + }, + "include": ["src/**/*", "src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], + "exclude": ["node_modules", "dist", "**/*.js"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..c2ef072 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,156 @@ +import { defineConfig, loadEnv } from 'vite' +import vue from '@vitejs/plugin-vue' +import path from 'path' +import { fileURLToPath } from 'url' +import vueDevTools from 'vite-plugin-vue-devtools' +import viteCompression from 'vite-plugin-compression' +import Components from 'unplugin-vue-components/vite' +import AutoImport from 'unplugin-auto-import/vite' +import ElementPlus from 'unplugin-element-plus/vite' +import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' +import tailwindcss from '@tailwindcss/vite' +// import { visualizer } from 'rollup-plugin-visualizer' + +export default ({ mode }: { mode: string }) => { + const root = process.cwd() + const env = loadEnv(mode, root) + const { VITE_VERSION, VITE_PORT, VITE_BASE_URL, VITE_API_URL, VITE_API_PROXY_URL } = env + + console.log(`🚀 API_URL = ${VITE_API_URL}`) + console.log(`🚀 VERSION = ${VITE_VERSION}`) + + return defineConfig({ + define: { + __APP_VERSION__: JSON.stringify(VITE_VERSION) + }, + base: VITE_BASE_URL, + server: { + port: Number(VITE_PORT), + proxy: { + '/api': { + target: VITE_API_PROXY_URL, + changeOrigin: true + } + }, + host: true + }, + // 路径别名 + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + '@views': resolvePath('src/views'), + '@imgs': resolvePath('src/assets/images'), + '@icons': resolvePath('src/assets/icons'), + '@utils': resolvePath('src/utils'), + '@stores': resolvePath('src/store'), + '@styles': resolvePath('src/assets/styles') + } + }, + build: { + target: 'es2015', + outDir: 'dist', + chunkSizeWarningLimit: 2000, + minify: 'terser', + terserOptions: { + compress: { + // 生产环境去除 console + drop_console: true, + // 生产环境去除 debugger + drop_debugger: true + } + }, + dynamicImportVarsOptions: { + warnOnError: true, + exclude: [], + include: ['src/views/**/*.vue'] + } + }, + plugins: [ + vue(), + tailwindcss(), + // 自动按需导入 API + AutoImport({ + imports: ['vue', 'vue-router', 'pinia', '@vueuse/core'], + dts: 'src/types/import/auto-imports.d.ts', + resolvers: [ElementPlusResolver()], + eslintrc: { + enabled: true, + filepath: './.auto-import.json', + globalsPropValue: true + } + }), + // 自动按需导入组件 + Components({ + dts: 'src/types/import/components.d.ts', + resolvers: [ElementPlusResolver()] + }), + // 按需定制主题配置 + ElementPlus({ + useSource: true + }), + // 压缩 + viteCompression({ + verbose: false, // 是否在控制台输出压缩结果 + disable: false, // 是否禁用 + algorithm: 'gzip', // 压缩算法 + ext: '.gz', // 压缩后的文件名后缀 + threshold: 10240, // 只有大小大于该值的资源会被处理 10240B = 10KB + deleteOriginFile: false // 压缩后是否删除原文件 + }), + vueDevTools() + // 打包分析 + // visualizer({ + // open: true, + // gzipSize: true, + // brotliSize: true, + // filename: 'dist/stats.html' // 分析图生成的文件名及路径 + // }), + ], + // 依赖预构建:避免运行时重复请求与转换,提升首次加载速度 + optimizeDeps: { + include: [ + 'echarts/core', + 'echarts/charts', + 'echarts/components', + 'echarts/renderers', + 'xlsx', + 'xgplayer', + 'crypto-js', + 'file-saver', + 'vue-img-cutter', + 'element-plus/es', + 'element-plus/es/components/*/style/css', + 'element-plus/es/components/*/style/index' + ] + }, + css: { + preprocessorOptions: { + // sass variable and mixin + scss: { + additionalData: ` + @use "@styles/core/el-light.scss" as *; + @use "@styles/core/mixin.scss" as *; + ` + } + }, + postcss: { + plugins: [ + { + postcssPlugin: 'internal:charset-removal', + AtRule: { + charset: (atRule) => { + if (atRule.name === 'charset') { + atRule.remove() + } + } + } + } + ] + } + } + }) +} + +function resolvePath(paths: string) { + return path.resolve(__dirname, paths) +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..bc5060a --- /dev/null +++ b/yarn.lock @@ -0,0 +1,4865 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@antfu/utils@^0.7.10": + version "0.7.10" + resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-0.7.10.tgz#ae829f170158e297a9b6a28f161a8e487d00814d" + integrity sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww== + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/compat-data@^7.27.2": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.5.tgz#a8a4962e1567121ac0b3b487f52107443b455c7f" + integrity sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA== + +"@babel/core@^7.23.0": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.5.tgz#4c81b35e51e1b734f510c99b07dfbc7bbbb48f7e" + integrity sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.5" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-module-transforms" "^7.28.3" + "@babel/helpers" "^7.28.4" + "@babel/parser" "^7.28.5" + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.5" + "@babel/types" "^7.28.5" + "@jridgewell/remapping" "^2.3.5" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.5.tgz#712722d5e50f44d07bc7ac9fe84438742dd61298" + integrity sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ== + dependencies: + "@babel/parser" "^7.28.5" + "@babel/types" "^7.28.5" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + +"@babel/helper-annotate-as-pure@^7.27.3": + version "7.27.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz#f31fd86b915fc4daf1f3ac6976c59be7084ed9c5" + integrity sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg== + dependencies: + "@babel/types" "^7.27.3" + +"@babel/helper-compilation-targets@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" + integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== + dependencies: + "@babel/compat-data" "^7.27.2" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.27.1", "@babel/helper-create-class-features-plugin@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz#472d0c28028850968979ad89f173594a6995da46" + integrity sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.3" + "@babel/helper-member-expression-to-functions" "^7.28.5" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/traverse" "^7.28.5" + semver "^6.3.1" + +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + +"@babel/helper-member-expression-to-functions@^7.27.1", "@babel/helper-member-expression-to-functions@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz#f3e07a10be37ed7a63461c63e6929575945a6150" + integrity sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg== + dependencies: + "@babel/traverse" "^7.28.5" + "@babel/types" "^7.28.5" + +"@babel/helper-module-imports@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" + integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/helper-module-transforms@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz#a2b37d3da3b2344fe085dab234426f2b9a2fa5f6" + integrity sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw== + dependencies: + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.28.3" + +"@babel/helper-optimise-call-expression@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz#c65221b61a643f3e62705e5dd2b5f115e35f9200" + integrity sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw== + dependencies: + "@babel/types" "^7.27.1" + +"@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" + integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== + +"@babel/helper-replace-supers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz#b1ed2d634ce3bdb730e4b52de30f8cccfd692bc0" + integrity sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/traverse" "^7.27.1" + +"@babel/helper-skip-transparent-expression-wrappers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz#62bb91b3abba8c7f1fec0252d9dbea11b3ee7a56" + integrity sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.27.1", "@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/helpers@^7.28.4": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.4.tgz#fe07274742e95bdf7cf1443593eeb8926ab63827" + integrity sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w== + dependencies: + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.4" + +"@babel/parser@^7.27.2", "@babel/parser@^7.28.0", "@babel/parser@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.5.tgz#0b0225ee90362f030efd644e8034c99468893b08" + integrity sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ== + dependencies: + "@babel/types" "^7.28.5" + +"@babel/plugin-proposal-decorators@^7.23.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.28.0.tgz#419c8acc31088e05a774344c021800f7ddc39bf0" + integrity sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-syntax-decorators" "^7.27.1" + +"@babel/plugin-syntax-decorators@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz#ee7dd9590aeebc05f9d4c8c0560007b05979a63d" + integrity sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-import-attributes@^7.22.5": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz#34c017d54496f9b11b61474e7ea3dfd5563ffe07" + integrity sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-jsx@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz#2f9beb5eff30fa507c5532d107daac7b888fa34c" + integrity sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-typescript@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz#5147d29066a793450f220c63fa3a9431b7e6dd18" + integrity sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-typescript@^7.22.15": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz#441c5f9a4a1315039516c6c612fc66d5f4594e72" + integrity sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.3" + "@babel/helper-create-class-features-plugin" "^7.28.5" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/plugin-syntax-typescript" "^7.27.1" + +"@babel/runtime@^7.12.0": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.4.tgz#a70226016fabe25c5783b2f22d3e1c9bc5ca3326" + integrity sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ== + +"@babel/template@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" + integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" + +"@babel/traverse@^7.27.1", "@babel/traverse@^7.28.0", "@babel/traverse@^7.28.3", "@babel/traverse@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.5.tgz#450cab9135d21a7a2ca9d2d35aa05c20e68c360b" + integrity sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.5" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.5" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.5" + debug "^4.3.1" + +"@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.28.2", "@babel/types@^7.28.4", "@babel/types@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.5.tgz#10fc405f60897c35f07e85493c932c7b5ca0592b" + integrity sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" + +"@cacheable/memory@^2.0.6": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@cacheable/memory/-/memory-2.0.7.tgz#1e066dc543b7c6797d0d230ce23d90898aca14c7" + integrity sha512-RbxnxAMf89Tp1dLhXMS7ceft/PGsDl1Ip7T20z5nZ+pwIAsQ1p2izPjVG69oCLv/jfQ7HDPHTWK0c9rcAWXN3A== + dependencies: + "@cacheable/utils" "^2.3.3" + "@keyv/bigmap" "^1.3.0" + hookified "^1.14.0" + keyv "^5.5.5" + +"@cacheable/utils@^2.3.2", "@cacheable/utils@^2.3.3": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@cacheable/utils/-/utils-2.3.3.tgz#56f0c0a3b2cad85f32ee2de3c73ff05d455e2c6c" + integrity sha512-JsXDL70gQ+1Vc2W/KUFfkAJzgb4puKwwKehNLuB+HrNKWf91O736kGfxn4KujXCCSuh6mRRL4XEB0PkAFjWS0A== + dependencies: + hashery "^1.3.0" + keyv "^5.5.5" + +"@csstools/css-parser-algorithms@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz#5755370a9a29abaec5515b43c8b3f2cf9c2e3076" + integrity sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ== + +"@csstools/css-syntax-patches-for-csstree@^1.0.19": + version "1.0.22" + resolved "https://registry.yarnpkg.com/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.22.tgz#7a14209eee004598dae61310e180f9826821d6c9" + integrity sha512-qBcx6zYlhleiFfdtzkRgwNC7VVoAwfK76Vmsw5t+PbvtdknO9StgRk7ROvq9so1iqbdW4uLIDAsXRsTfUrIoOw== + +"@csstools/css-tokenizer@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz#333fedabc3fd1a8e5d0100013731cf19e6a8c5d3" + integrity sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw== + +"@csstools/media-query-list-parser@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz#7aec77bcb89c2da80ef207e73f474ef9e1b3cdf1" + integrity sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ== + +"@csstools/selector-specificity@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz#037817b574262134cabd68fc4ec1a454f168407b" + integrity sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw== + +"@ctrl/tinycolor@^3.4.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz#b6c75a56a1947cc916ea058772d666a2c8932f31" + integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA== + +"@dual-bundle/import-meta-resolve@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.2.1.tgz#cd0b25b3808cd9e684cd6cd549bbf8e1dcf05ee7" + integrity sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg== + +"@element-plus/icons-vue@^2.3.2": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz#7e9cb231fb738b2056f33e22c3a29e214b538dcf" + integrity sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A== + +"@emnapi/core@^1.7.1": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.8.1.tgz#fd9efe721a616288345ffee17a1f26ac5dd01349" + integrity sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg== + dependencies: + "@emnapi/wasi-threads" "1.1.0" + tslib "^2.4.0" + +"@emnapi/runtime@^1.7.1": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.8.1.tgz#550fa7e3c0d49c5fb175a116e8cd70614f9a22a5" + integrity sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg== + dependencies: + tslib "^2.4.0" + +"@emnapi/wasi-threads@1.1.0", "@emnapi/wasi-threads@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf" + integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ== + dependencies: + tslib "^2.4.0" + +"@esbuild/aix-ppc64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz#521cbd968dcf362094034947f76fa1b18d2d403c" + integrity sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw== + +"@esbuild/android-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz#61ea550962d8aa12a9b33194394e007657a6df57" + integrity sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA== + +"@esbuild/android-arm@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.27.2.tgz#554887821e009dd6d853f972fde6c5143f1de142" + integrity sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA== + +"@esbuild/android-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.27.2.tgz#a7ce9d0721825fc578f9292a76d9e53334480ba2" + integrity sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A== + +"@esbuild/darwin-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz#2cb7659bd5d109803c593cfc414450d5430c8256" + integrity sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg== + +"@esbuild/darwin-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz#e741fa6b1abb0cd0364126ba34ca17fd5e7bf509" + integrity sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA== + +"@esbuild/freebsd-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz#2b64e7116865ca172d4ce034114c21f3c93e397c" + integrity sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g== + +"@esbuild/freebsd-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz#e5252551e66f499e4934efb611812f3820e990bb" + integrity sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA== + +"@esbuild/linux-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz#dc4acf235531cd6984f5d6c3b13dbfb7ddb303cb" + integrity sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw== + +"@esbuild/linux-arm@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz#56a900e39240d7d5d1d273bc053daa295c92e322" + integrity sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw== + +"@esbuild/linux-ia32@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz#d4a36d473360f6870efcd19d52bbfff59a2ed1cc" + integrity sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w== + +"@esbuild/linux-loong64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz#fcf0ab8c3eaaf45891d0195d4961cb18b579716a" + integrity sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg== + +"@esbuild/linux-mips64el@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz#598b67d34048bb7ee1901cb12e2a0a434c381c10" + integrity sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw== + +"@esbuild/linux-ppc64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz#3846c5df6b2016dab9bc95dde26c40f11e43b4c0" + integrity sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ== + +"@esbuild/linux-riscv64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz#173d4475b37c8d2c3e1707e068c174bb3f53d07d" + integrity sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA== + +"@esbuild/linux-s390x@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz#f7a4790105edcab8a5a31df26fbfac1aa3dacfab" + integrity sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w== + +"@esbuild/linux-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz#2ecc1284b1904aeb41e54c9ddc7fcd349b18f650" + integrity sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA== + +"@esbuild/netbsd-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz#e2863c2cd1501845995cb11adf26f7fe4be527b0" + integrity sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw== + +"@esbuild/netbsd-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz#93f7609e2885d1c0b5a1417885fba8d1fcc41272" + integrity sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA== + +"@esbuild/openbsd-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz#a1985604a203cdc325fd47542e106fafd698f02e" + integrity sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA== + +"@esbuild/openbsd-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz#8209e46c42f1ffbe6e4ef77a32e1f47d404ad42a" + integrity sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg== + +"@esbuild/openharmony-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz#8fade4441893d9cc44cbd7dcf3776f508ab6fb2f" + integrity sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag== + +"@esbuild/sunos-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz#980d4b9703a16f0f07016632424fc6d9a789dfc2" + integrity sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg== + +"@esbuild/win32-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz#1c09a3633c949ead3d808ba37276883e71f6111a" + integrity sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg== + +"@esbuild/win32-ia32@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz#1b1e3a63ad4bef82200fef4e369e0fff7009eee5" + integrity sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ== + +"@esbuild/win32-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz#9e585ab6086bef994c6e8a5b3a0481219ada862b" + integrity sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ== + +"@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.8.0", "@eslint-community/eslint-utils@^4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" + integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.12.1", "@eslint-community/regexpp@^4.12.2": + version "4.12.2" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" + integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== + +"@eslint/config-array@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.1.tgz#7d1b0060fea407f8301e932492ba8c18aff29713" + integrity sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA== + dependencies: + "@eslint/object-schema" "^2.1.7" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/config-helpers@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz#1bd006ceeb7e2e55b2b773ab318d300e1a66aeda" + integrity sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw== + dependencies: + "@eslint/core" "^0.17.0" + +"@eslint/core@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.17.0.tgz#77225820413d9617509da9342190a2019e78761c" + integrity sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.3.1": + version "3.3.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.3.tgz#26393a0806501b5e2b6a43aa588a4d8df67880ac" + integrity sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.1" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.39.2", "@eslint/js@^9.9.1": + version "9.39.2" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.39.2.tgz#2d4b8ec4c3ea13c1b3748e0c97ecd766bdd80599" + integrity sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA== + +"@eslint/object-schema@^2.1.7": + version "2.1.7" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.7.tgz#6e2126a1347e86a4dedf8706ec67ff8e107ebbad" + integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA== + +"@eslint/plugin-kit@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz#9779e3fd9b7ee33571a57435cf4335a1794a6cb2" + integrity sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA== + dependencies: + "@eslint/core" "^0.17.0" + levn "^0.4.1" + +"@floating-ui/core@^1.7.3": + version "1.7.3" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.7.3.tgz#462d722f001e23e46d86fd2bd0d21b7693ccb8b7" + integrity sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w== + dependencies: + "@floating-ui/utils" "^0.2.10" + +"@floating-ui/dom@^1.0.1": + version "1.7.4" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.7.4.tgz#ee667549998745c9c3e3e84683b909c31d6c9a77" + integrity sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA== + dependencies: + "@floating-ui/core" "^1.7.3" + "@floating-ui/utils" "^0.2.10" + +"@floating-ui/utils@^0.2.10": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.10.tgz#a2a1e3812d14525f725d011a73eceb41fef5bc1c" + integrity sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ== + +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.7" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.7.tgz#822cb7b3a12c5a240a24f621b5a2413e27a45f26" + integrity sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.4.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/retry@^0.4.0", "@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== + +"@iconify/types@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57" + integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg== + +"@iconify/vue@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@iconify/vue/-/vue-5.0.0.tgz#c47e4b3a225a64bbf28dce924934f23e54b061a4" + integrity sha512-C+KuEWIF5nSBrobFJhT//JS87OZ++QDORB6f2q2Wm6fl2mueSTpFBeBsveK0KW9hWiZ4mNiPjsh6Zs4jjdROSg== + dependencies: + "@iconify/types" "^2.0.0" + +"@intlify/core-base@9.14.5": + version "9.14.5" + resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.14.5.tgz#cfed631e98b34f4f6fe1312e6c02dd8ace180197" + integrity sha512-5ah5FqZG4pOoHjkvs8mjtv+gPKYU0zCISaYNjBNNqYiaITxW8ZtVih3GS/oTOqN8d9/mDLyrjD46GBApNxmlsA== + dependencies: + "@intlify/message-compiler" "9.14.5" + "@intlify/shared" "9.14.5" + +"@intlify/message-compiler@9.14.5": + version "9.14.5" + resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.14.5.tgz#03b0a358c93cb2eed95936531c8a5871fd3841b0" + integrity sha512-IHzgEu61/YIpQV5Pc3aRWScDcnFKWvQA9kigcINcCBXN8mbW+vk9SK+lDxA6STzKQsVJxUPg9ACC52pKKo3SVQ== + dependencies: + "@intlify/shared" "9.14.5" + source-map-js "^1.0.2" + +"@intlify/shared@9.14.5": + version "9.14.5" + resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.14.5.tgz#2e42193b8356db20ee28c15d1ee6c8f0fda6c0b9" + integrity sha512-9gB+E53BYuAEMhbCAxVgG38EZrk59sxBtv3jSizNL2hEWlgjBjAw1AwpLHtNaeda12pe6W20OGEa0TwuMSRbyQ== + +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/remapping@^2.3.4", "@jridgewell/remapping@^2.3.5": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/source-map@^0.3.3": + version "0.3.11" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.11.tgz#b21835cbd36db656b857c2ad02ebd413cc13a9ba" + integrity sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + +"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@keyv/bigmap@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@keyv/bigmap/-/bigmap-1.3.0.tgz#f06d9bb38488a59f012cd2758e6f429dfd312fb5" + integrity sha512-KT01GjzV6AQD5+IYrcpoYLkCu1Jod3nau1Z7EsEuViO3TZGRacSbO9MfHmbJ1WaOXFtWLxPVj169cn2WNKPkIg== + dependencies: + hashery "^1.2.0" + hookified "^1.13.0" + +"@keyv/serialize@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@keyv/serialize/-/serialize-1.1.1.tgz#0c01dd3a3483882af7cf3878d4e71d505c81fc4a" + integrity sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA== + +"@napi-rs/wasm-runtime@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz#c3705ab549d176b8dc5172723d6156c3dc426af2" + integrity sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A== + dependencies: + "@emnapi/core" "^1.7.1" + "@emnapi/runtime" "^1.7.1" + "@tybys/wasm-util" "^0.10.1" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@parcel/watcher-android-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz#507f836d7e2042f798c7d07ad19c3546f9848ac1" + integrity sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA== + +"@parcel/watcher-darwin-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz#3d26dce38de6590ef79c47ec2c55793c06ad4f67" + integrity sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw== + +"@parcel/watcher-darwin-x64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz#99f3af3869069ccf774e4ddfccf7e64fd2311ef8" + integrity sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg== + +"@parcel/watcher-freebsd-x64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz#14d6857741a9f51dfe51d5b08b7c8afdbc73ad9b" + integrity sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ== + +"@parcel/watcher-linux-arm-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz#43c3246d6892381db473bb4f663229ad20b609a1" + integrity sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA== + +"@parcel/watcher-linux-arm-musl@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz#663750f7090bb6278d2210de643eb8a3f780d08e" + integrity sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q== + +"@parcel/watcher-linux-arm64-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz#ba60e1f56977f7e47cd7e31ad65d15fdcbd07e30" + integrity sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w== + +"@parcel/watcher-linux-arm64-musl@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz#f7fbcdff2f04c526f96eac01f97419a6a99855d2" + integrity sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg== + +"@parcel/watcher-linux-x64-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz#4d2ea0f633eb1917d83d483392ce6181b6a92e4e" + integrity sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A== + +"@parcel/watcher-linux-x64-musl@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz#277b346b05db54f55657301dd77bdf99d63606ee" + integrity sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg== + +"@parcel/watcher-win32-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz#7e9e02a26784d47503de1d10e8eab6cceb524243" + integrity sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw== + +"@parcel/watcher-win32-ia32@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz#2d0f94fa59a873cdc584bf7f6b1dc628ddf976e6" + integrity sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ== + +"@parcel/watcher-win32-x64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz#ae52693259664ba6f2228fa61d7ee44b64ea0947" + integrity sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA== + +"@parcel/watcher@^2.4.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.5.1.tgz#342507a9cfaaf172479a882309def1e991fb1200" + integrity sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg== + dependencies: + detect-libc "^1.0.3" + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^7.0.0" + optionalDependencies: + "@parcel/watcher-android-arm64" "2.5.1" + "@parcel/watcher-darwin-arm64" "2.5.1" + "@parcel/watcher-darwin-x64" "2.5.1" + "@parcel/watcher-freebsd-x64" "2.5.1" + "@parcel/watcher-linux-arm-glibc" "2.5.1" + "@parcel/watcher-linux-arm-musl" "2.5.1" + "@parcel/watcher-linux-arm64-glibc" "2.5.1" + "@parcel/watcher-linux-arm64-musl" "2.5.1" + "@parcel/watcher-linux-x64-glibc" "2.5.1" + "@parcel/watcher-linux-x64-musl" "2.5.1" + "@parcel/watcher-win32-arm64" "2.5.1" + "@parcel/watcher-win32-ia32" "2.5.1" + "@parcel/watcher-win32-x64" "2.5.1" + +"@pkgr/core@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" + integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== + +"@polka/url@^1.0.0-next.24": + version "1.0.0-next.29" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.29.tgz#5a40109a1ab5f84d6fd8fc928b19f367cbe7e7b1" + integrity sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww== + +"@popperjs/core@npm:@sxzz/popperjs-es@^2.11.7": + version "2.11.7" + resolved "https://registry.yarnpkg.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz#a7f69e3665d3da9b115f9e71671dae1b97e13671" + integrity sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ== + +"@rolldown/pluginutils@1.0.0-beta.53": + version "1.0.0-beta.53" + resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz#c57a5234ae122671aff6fe72e673a7ed90f03f87" + integrity sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ== + +"@rollup/pluginutils@^5.1.3": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.3.0.tgz#57ba1b0cbda8e7a3c597a4853c807b156e21a7b4" + integrity sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^4.0.2" + +"@rollup/rollup-android-arm-eabi@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz#76e0fef6533b3ce313f969879e61e8f21f0eeb28" + integrity sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg== + +"@rollup/rollup-android-arm64@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz#d3cfc675a40bbdec97bda6d7fe3b3b05f0e1cd93" + integrity sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg== + +"@rollup/rollup-darwin-arm64@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz#eb912b8f59dd47c77b3c50a78489013b1d6772b4" + integrity sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg== + +"@rollup/rollup-darwin-x64@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz#e7d0839fdfd1276a1d34bc5ebbbd0dfd7d0b81a0" + integrity sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ== + +"@rollup/rollup-freebsd-arm64@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz#7ff8118760f7351e48fd0cd3717ff80543d6aac8" + integrity sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg== + +"@rollup/rollup-freebsd-x64@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz#49d330dadbda1d4e9b86b4a3951b59928a9489a9" + integrity sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw== + +"@rollup/rollup-linux-arm-gnueabihf@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz#98c5f1f8b9776b4a36e466e2a1c9ed1ba52ef1b6" + integrity sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ== + +"@rollup/rollup-linux-arm-musleabihf@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz#b9acecd3672e742f70b0c8a94075c816a91ff040" + integrity sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg== + +"@rollup/rollup-linux-arm64-gnu@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz#7a6ab06651bc29e18b09a50ed1a02bc972977c9b" + integrity sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ== + +"@rollup/rollup-linux-arm64-musl@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz#3c8c9072ba4a4d4ef1156b85ab9a2cbb57c1fad0" + integrity sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA== + +"@rollup/rollup-linux-loong64-gnu@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz#17a7af13530f4e4a7b12cd26276c54307a84a8b0" + integrity sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g== + +"@rollup/rollup-linux-loong64-musl@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz#5cd7a900fd7b077ecd753e34a9b7ff1157fe70c1" + integrity sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw== + +"@rollup/rollup-linux-ppc64-gnu@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz#03a097e70243ddf1c07b59d3c20f38e6f6800539" + integrity sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw== + +"@rollup/rollup-linux-ppc64-musl@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz#a5389873039d4650f35b4fa060d286392eb21a94" + integrity sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw== + +"@rollup/rollup-linux-riscv64-gnu@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz#789e60e7d6e2b76132d001ffb24ba80007fb17d0" + integrity sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw== + +"@rollup/rollup-linux-riscv64-musl@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz#3556fa88d139282e9a73c337c9a170f3c5fe7aa4" + integrity sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg== + +"@rollup/rollup-linux-s390x-gnu@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz#c085995b10143c16747a67f1a5487512b2ff04b2" + integrity sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg== + +"@rollup/rollup-linux-x64-gnu@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz#9563a5419dd2604841bad31a39ccfdd2891690fb" + integrity sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg== + +"@rollup/rollup-linux-x64-musl@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz#691bb06e6269a8959c13476b0cd2aa7458facb31" + integrity sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w== + +"@rollup/rollup-openbsd-x64@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz#223e71224746a59ce6d955bbc403577bb5a8be9d" + integrity sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg== + +"@rollup/rollup-openharmony-arm64@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz#0817e5d8ecbfeb8b7939bf58f8ce3c9dd67fce77" + integrity sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw== + +"@rollup/rollup-win32-arm64-msvc@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz#de56d8f2013c84570ef5fb917aae034abda93e4a" + integrity sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g== + +"@rollup/rollup-win32-ia32-msvc@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz#659aff5244312475aeea2c9479a6c7d397b517bf" + integrity sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA== + +"@rollup/rollup-win32-x64-gnu@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz#2cb09549cbb66c1b979f9238db6dd454cac14a88" + integrity sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg== + +"@rollup/rollup-win32-x64-msvc@4.55.1": + version "4.55.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz#f79437939020b83057faf07e98365b1fa51c458b" + integrity sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw== + +"@sec-ant/readable-stream@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz#60de891bb126abfdc5410fdc6166aca065f10a0c" + integrity sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg== + +"@sindresorhus/merge-streams@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz#abb11d99aeb6d27f1b563c38147a72d50058e339" + integrity sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ== + +"@tailwindcss/node@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/node/-/node-4.1.18.tgz#9863be0d26178638794a38d6c7c14666fb992e8a" + integrity sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ== + dependencies: + "@jridgewell/remapping" "^2.3.4" + enhanced-resolve "^5.18.3" + jiti "^2.6.1" + lightningcss "1.30.2" + magic-string "^0.30.21" + source-map-js "^1.2.1" + tailwindcss "4.1.18" + +"@tailwindcss/oxide-android-arm64@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz#79717f87e90135e5d3d23a3d3aecde4ca5595dd5" + integrity sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q== + +"@tailwindcss/oxide-darwin-arm64@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz#7fa47608d62d60e9eb020682249d20159667fbb0" + integrity sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A== + +"@tailwindcss/oxide-darwin-x64@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz#c05991c85aa2af47bf9d1f8172fe9e4636591e79" + integrity sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw== + +"@tailwindcss/oxide-freebsd-x64@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz#3d48e8d79fd08ece0e02af8e72d5059646be34d0" + integrity sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA== + +"@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz#982ecd1a65180807ccfde67dc17c6897f2e50aa8" + integrity sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA== + +"@tailwindcss/oxide-linux-arm64-gnu@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz#df49357bc9737b2e9810ea950c1c0647ba6573c3" + integrity sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw== + +"@tailwindcss/oxide-linux-arm64-musl@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz#b266c12822bf87883cf152615f8fffb8519d689c" + integrity sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg== + +"@tailwindcss/oxide-linux-x64-gnu@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz#5c737f13dd9529b25b314e6000ff54e05b3811da" + integrity sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g== + +"@tailwindcss/oxide-linux-x64-musl@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz#3380e17f7be391f1ef924be9f0afe1f304fe3478" + integrity sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ== + +"@tailwindcss/oxide-wasm32-wasi@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz#9464df0e28a499aab1c55e97682be37b3a656c88" + integrity sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA== + dependencies: + "@emnapi/core" "^1.7.1" + "@emnapi/runtime" "^1.7.1" + "@emnapi/wasi-threads" "^1.1.0" + "@napi-rs/wasm-runtime" "^1.1.0" + "@tybys/wasm-util" "^0.10.1" + tslib "^2.4.0" + +"@tailwindcss/oxide-win32-arm64-msvc@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz#bbcdd59c628811f6a0a4d5b09616967d8fb0c4d4" + integrity sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA== + +"@tailwindcss/oxide-win32-x64-msvc@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz#9c628d04623aa4c3536c508289f58d58ba4b3fb1" + integrity sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q== + +"@tailwindcss/oxide@4.1.18": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide/-/oxide-4.1.18.tgz#c8335cd0a83e9880caecd60abf7904f43ebab582" + integrity sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A== + optionalDependencies: + "@tailwindcss/oxide-android-arm64" "4.1.18" + "@tailwindcss/oxide-darwin-arm64" "4.1.18" + "@tailwindcss/oxide-darwin-x64" "4.1.18" + "@tailwindcss/oxide-freebsd-x64" "4.1.18" + "@tailwindcss/oxide-linux-arm-gnueabihf" "4.1.18" + "@tailwindcss/oxide-linux-arm64-gnu" "4.1.18" + "@tailwindcss/oxide-linux-arm64-musl" "4.1.18" + "@tailwindcss/oxide-linux-x64-gnu" "4.1.18" + "@tailwindcss/oxide-linux-x64-musl" "4.1.18" + "@tailwindcss/oxide-wasm32-wasi" "4.1.18" + "@tailwindcss/oxide-win32-arm64-msvc" "4.1.18" + "@tailwindcss/oxide-win32-x64-msvc" "4.1.18" + +"@tailwindcss/vite@^4.1.14": + version "4.1.18" + resolved "https://registry.yarnpkg.com/@tailwindcss/vite/-/vite-4.1.18.tgz#614b9d5483559518c72d31bca05d686f8df28e9a" + integrity sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA== + dependencies: + "@tailwindcss/node" "4.1.18" + "@tailwindcss/oxide" "4.1.18" + tailwindcss "4.1.18" + +"@transloadit/prettier-bytes@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz#cdb5399f445fdd606ed833872fa0cabdbc51686b" + integrity sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA== + +"@tybys/wasm-util@^0.10.1": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" + integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg== + dependencies: + tslib "^2.4.0" + +"@types/estree@1.0.8", "@types/estree@^1.0.0", "@types/estree@^1.0.6": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +"@types/event-emitter@^0.3.3": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@types/event-emitter/-/event-emitter-0.3.5.tgz#ce9b513f72c50dcf0443a12165a93a79ba7a7092" + integrity sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ== + +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/lodash-es@^4.17.12": + version "4.17.12" + resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.12.tgz#65f6d1e5f80539aa7cfbfc962de5def0cf4f341b" + integrity sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ== + dependencies: + "@types/lodash" "*" + +"@types/lodash@*", "@types/lodash@^4.17.20": + version "4.17.21" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.21.tgz#b806831543d696b14f8112db600ea9d3a1df6ea4" + integrity sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ== + +"@types/node@^24.0.5": + version "24.10.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.10.4.tgz#9d27c032a1b2c42a4eab8fb65c5856a8b8e098c4" + integrity sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg== + dependencies: + undici-types "~7.16.0" + +"@types/sortablejs@^1.15.8": + version "1.15.9" + resolved "https://registry.yarnpkg.com/@types/sortablejs/-/sortablejs-1.15.9.tgz#82d2337f54d4db827914d80dee5cf65539ae3c8b" + integrity sha512-7HP+rZGE2p886PKV9c9OJzLBI6BBJu1O7lJGYnPyG3fS4/duUCcngkNCjsLwIMV+WMqANe3tt4irrXHSIe68OQ== + +"@types/web-bluetooth@^0.0.20": + version "0.0.20" + resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz#f066abfcd1cbe66267cdbbf0de010d8a41b41597" + integrity sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow== + +"@types/web-bluetooth@^0.0.21": + version "0.0.21" + resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz#525433c784aed9b457aaa0ee3d92aeb71f346b63" + integrity sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA== + +"@typescript-eslint/eslint-plugin@8.52.0", "@typescript-eslint/eslint-plugin@^8.3.0": + version "8.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.52.0.tgz#9a9f1d2ee974ed77a8b1bda94e77123f697ee8b4" + integrity sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q== + dependencies: + "@eslint-community/regexpp" "^4.12.2" + "@typescript-eslint/scope-manager" "8.52.0" + "@typescript-eslint/type-utils" "8.52.0" + "@typescript-eslint/utils" "8.52.0" + "@typescript-eslint/visitor-keys" "8.52.0" + ignore "^7.0.5" + natural-compare "^1.4.0" + ts-api-utils "^2.4.0" + +"@typescript-eslint/parser@8.52.0", "@typescript-eslint/parser@^8.3.0": + version "8.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.52.0.tgz#9fae9f5f13ebb1c8f31a50c34381bfd6bf96a05f" + integrity sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg== + dependencies: + "@typescript-eslint/scope-manager" "8.52.0" + "@typescript-eslint/types" "8.52.0" + "@typescript-eslint/typescript-estree" "8.52.0" + "@typescript-eslint/visitor-keys" "8.52.0" + debug "^4.4.3" + +"@typescript-eslint/project-service@8.52.0": + version "8.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.52.0.tgz#5fb4c16af4eda6d74c70cbc62f5d3f77b96e4cbe" + integrity sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.52.0" + "@typescript-eslint/types" "^8.52.0" + debug "^4.4.3" + +"@typescript-eslint/scope-manager@8.52.0": + version "8.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.52.0.tgz#9884ff690fad30380ccabfb08af1ac200af6b4e5" + integrity sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA== + dependencies: + "@typescript-eslint/types" "8.52.0" + "@typescript-eslint/visitor-keys" "8.52.0" + +"@typescript-eslint/tsconfig-utils@8.52.0", "@typescript-eslint/tsconfig-utils@^8.52.0": + version "8.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.52.0.tgz#0296751c22ed05c83787a6eaec65ae221bd8b8ed" + integrity sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg== + +"@typescript-eslint/type-utils@8.52.0": + version "8.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.52.0.tgz#6e554113f8a074cf9b2faa818d2ebfccb867d6c5" + integrity sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ== + dependencies: + "@typescript-eslint/types" "8.52.0" + "@typescript-eslint/typescript-estree" "8.52.0" + "@typescript-eslint/utils" "8.52.0" + debug "^4.4.3" + ts-api-utils "^2.4.0" + +"@typescript-eslint/types@8.52.0", "@typescript-eslint/types@^8.52.0": + version "8.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.52.0.tgz#1eb0a16b324824bc23b89d109a267c38c9213c4a" + integrity sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg== + +"@typescript-eslint/typescript-estree@8.52.0": + version "8.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.52.0.tgz#2ad7721c671be2127951286cb7f44c4ce55b0591" + integrity sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ== + dependencies: + "@typescript-eslint/project-service" "8.52.0" + "@typescript-eslint/tsconfig-utils" "8.52.0" + "@typescript-eslint/types" "8.52.0" + "@typescript-eslint/visitor-keys" "8.52.0" + debug "^4.4.3" + minimatch "^9.0.5" + semver "^7.7.3" + tinyglobby "^0.2.15" + ts-api-utils "^2.4.0" + +"@typescript-eslint/utils@8.52.0": + version "8.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.52.0.tgz#b249be8264899b80d996fa353b4b84da4662f962" + integrity sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ== + dependencies: + "@eslint-community/eslint-utils" "^4.9.1" + "@typescript-eslint/scope-manager" "8.52.0" + "@typescript-eslint/types" "8.52.0" + "@typescript-eslint/typescript-estree" "8.52.0" + +"@typescript-eslint/visitor-keys@8.52.0": + version "8.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.52.0.tgz#50361c48a6302676230fe498f80f6decce4bf673" + integrity sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ== + dependencies: + "@typescript-eslint/types" "8.52.0" + eslint-visitor-keys "^4.2.1" + +"@uppy/companion-client@^2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@uppy/companion-client/-/companion-client-2.2.2.tgz#c70b42fdcca728ef88b3eebf7ee3e2fa04b4923b" + integrity sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og== + dependencies: + "@uppy/utils" "^4.1.2" + namespace-emitter "^2.0.1" + +"@uppy/core@^2.1.1": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@uppy/core/-/core-2.3.4.tgz#260b85b6bf3aa03cdc67da231f8c69cfbfdcc84a" + integrity sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ== + dependencies: + "@transloadit/prettier-bytes" "0.0.7" + "@uppy/store-default" "^2.1.1" + "@uppy/utils" "^4.1.3" + lodash.throttle "^4.1.1" + mime-match "^1.0.2" + namespace-emitter "^2.0.1" + nanoid "^3.1.25" + preact "^10.5.13" + +"@uppy/store-default@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@uppy/store-default/-/store-default-2.1.1.tgz#62a656a099bdaa012306e054d093754cb2d36e3e" + integrity sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ== + +"@uppy/utils@^4.1.2", "@uppy/utils@^4.1.3": + version "4.1.3" + resolved "https://registry.yarnpkg.com/@uppy/utils/-/utils-4.1.3.tgz#9d0be6ece4df25f228d30ef40be0f14208258ce3" + integrity sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw== + dependencies: + lodash.throttle "^4.1.1" + +"@uppy/xhr-upload@^2.0.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz#0d4e355332fe0c6eb372d7731315e04d02aeeb18" + integrity sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ== + dependencies: + "@uppy/companion-client" "^2.2.2" + "@uppy/utils" "^4.1.2" + nanoid "^3.1.25" + +"@vitejs/plugin-vue@^6.0.1": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-6.0.3.tgz#b857c5dcbc5cfb30bf5d7f9d6e274afcca2d46d1" + integrity sha512-TlGPkLFLVOY3T7fZrwdvKpjprR3s4fxRln0ORDo1VQ7HHyxJwTlrjKU3kpVWTlaAjIEuCTokmjkZnr8Tpc925w== + dependencies: + "@rolldown/pluginutils" "1.0.0-beta.53" + +"@volar/language-core@2.4.27", "@volar/language-core@~2.4.8": + version "2.4.27" + resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-2.4.27.tgz#c66d44cd22a914384d238bbcd0f621ecc57e3618" + integrity sha512-DjmjBWZ4tJKxfNC1F6HyYERNHPYS7L7OPFyCrestykNdUZMFYzI9WTyvwPcaNaHlrEUwESHYsfEw3isInncZxQ== + dependencies: + "@volar/source-map" "2.4.27" + +"@volar/source-map@2.4.27": + version "2.4.27" + resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-2.4.27.tgz#8ce6f16e207987078fd866e2faf65c35c4d15987" + integrity sha512-ynlcBReMgOZj2i6po+qVswtDUeeBRCTgDurjMGShbm8WYZgJ0PA4RmtebBJ0BCYol1qPv3GQF6jK7C9qoVc7lg== + +"@volar/typescript@~2.4.8": + version "2.4.27" + resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-2.4.27.tgz#8950318a33d5dfcdc4b0e5bbe5a38c1b8383eae6" + integrity sha512-eWaYCcl/uAPInSK2Lze6IqVWaBu/itVqR5InXcHXFyles4zO++Mglt3oxdgj75BDcv1Knr9Y93nowS8U3wqhxg== + dependencies: + "@volar/language-core" "2.4.27" + path-browserify "^1.0.1" + vscode-uri "^3.0.8" + +"@vue/babel-helper-vue-transform-on@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz#b7e99d37eeb144d7b9757d7a1f40cd977fde748a" + integrity sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA== + +"@vue/babel-plugin-jsx@^1.1.5": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz#1b988b497cb1f79725da94463e75cebe60b72e70" + integrity sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw== + dependencies: + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-syntax-jsx" "^7.27.1" + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.0" + "@babel/types" "^7.28.2" + "@vue/babel-helper-vue-transform-on" "1.5.0" + "@vue/babel-plugin-resolve-type" "1.5.0" + "@vue/shared" "^3.5.18" + +"@vue/babel-plugin-resolve-type@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz#6881d7b1478e9fc0ea4bb08aaad1f4d206655568" + integrity sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/parser" "^7.28.0" + "@vue/compiler-sfc" "^3.5.18" + +"@vue/compiler-core@3.5.26": + version "3.5.26" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.26.tgz#1a91ea90980528bedff7b1c292690bfb30612485" + integrity sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w== + dependencies: + "@babel/parser" "^7.28.5" + "@vue/shared" "3.5.26" + entities "^7.0.0" + estree-walker "^2.0.2" + source-map-js "^1.2.1" + +"@vue/compiler-dom@3.5.26", "@vue/compiler-dom@^3.3.4", "@vue/compiler-dom@^3.5.0": + version "3.5.26" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.26.tgz#66c36b6ed8bdf43236d7188ea332bc9d078eb286" + integrity sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A== + dependencies: + "@vue/compiler-core" "3.5.26" + "@vue/shared" "3.5.26" + +"@vue/compiler-sfc@3.5.26", "@vue/compiler-sfc@^3.0.5", "@vue/compiler-sfc@^3.5.18": + version "3.5.26" + resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.26.tgz#fb1c6c4bf9a9e22bb169e039e19437cb6995917a" + integrity sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA== + dependencies: + "@babel/parser" "^7.28.5" + "@vue/compiler-core" "3.5.26" + "@vue/compiler-dom" "3.5.26" + "@vue/compiler-ssr" "3.5.26" + "@vue/shared" "3.5.26" + estree-walker "^2.0.2" + magic-string "^0.30.21" + postcss "^8.5.6" + source-map-js "^1.2.1" + +"@vue/compiler-ssr@3.5.26": + version "3.5.26" + resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.5.26.tgz#f6e94bccbb5339180779036ddfb614f998a197ea" + integrity sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw== + dependencies: + "@vue/compiler-dom" "3.5.26" + "@vue/shared" "3.5.26" + +"@vue/compiler-vue2@^2.7.16": + version "2.7.16" + resolved "https://registry.yarnpkg.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz#2ba837cbd3f1b33c2bc865fbe1a3b53fb611e249" + integrity sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A== + dependencies: + de-indent "^1.0.2" + he "^1.2.0" + +"@vue/devtools-api@^6.5.0", "@vue/devtools-api@^6.6.4": + version "6.6.4" + resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz#cbe97fe0162b365edc1dba80e173f90492535343" + integrity sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g== + +"@vue/devtools-api@^7.7.7": + version "7.7.9" + resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-7.7.9.tgz#999dbea50da6b00cf59a1336f11fdc2b43d9e063" + integrity sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g== + dependencies: + "@vue/devtools-kit" "^7.7.9" + +"@vue/devtools-core@^7.7.9": + version "7.7.9" + resolved "https://registry.yarnpkg.com/@vue/devtools-core/-/devtools-core-7.7.9.tgz#3c64bff202124e58827aaebf7e98b25f0b68744d" + integrity sha512-48jrBSwG4GVQRvVeeXn9p9+dlx+ISgasM7SxZZKczseohB0cBz+ITKr4YbLWjmJdy45UHL7UMPlR4Y0CWTRcSQ== + dependencies: + "@vue/devtools-kit" "^7.7.9" + "@vue/devtools-shared" "^7.7.9" + mitt "^3.0.1" + nanoid "^5.1.0" + pathe "^2.0.3" + vite-hot-client "^2.0.4" + +"@vue/devtools-kit@^7.7.9": + version "7.7.9" + resolved "https://registry.yarnpkg.com/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz#bc218a815616e8987df7ab3e10fc1fb3b8706c58" + integrity sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA== + dependencies: + "@vue/devtools-shared" "^7.7.9" + birpc "^2.3.0" + hookable "^5.5.3" + mitt "^3.0.1" + perfect-debounce "^1.0.0" + speakingurl "^14.0.1" + superjson "^2.2.2" + +"@vue/devtools-shared@^7.7.9": + version "7.7.9" + resolved "https://registry.yarnpkg.com/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz#fa4c096b744927081a7dda5fcf05f34b1ae6ca14" + integrity sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA== + dependencies: + rfdc "^1.4.1" + +"@vue/language-core@2.1.10": + version "2.1.10" + resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-2.1.10.tgz#5988e9ea155f3e09ccbbb3b2a0ddd530dad912e6" + integrity sha512-DAI289d0K3AB5TUG3xDp9OuQ71CnrujQwJrQnfuZDwo6eGNf0UoRlPuaVNO+Zrn65PC3j0oB2i7mNmVPggeGeQ== + dependencies: + "@volar/language-core" "~2.4.8" + "@vue/compiler-dom" "^3.5.0" + "@vue/compiler-vue2" "^2.7.16" + "@vue/shared" "^3.5.0" + alien-signals "^0.2.0" + minimatch "^9.0.3" + muggle-string "^0.4.1" + path-browserify "^1.0.1" + +"@vue/reactivity@3.5.26", "@vue/reactivity@^3.5.21": + version "3.5.26" + resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.5.26.tgz#59a1edf566dc80133c1c26c93711c877e8602c48" + integrity sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ== + dependencies: + "@vue/shared" "3.5.26" + +"@vue/runtime-core@3.5.26": + version "3.5.26" + resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.5.26.tgz#3f2c040bcf8018c03a1ab5adb0d788c13c986f0e" + integrity sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q== + dependencies: + "@vue/reactivity" "3.5.26" + "@vue/shared" "3.5.26" + +"@vue/runtime-dom@3.5.26": + version "3.5.26" + resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.5.26.tgz#5954848614883948ecc1f631a67b32cc32f81936" + integrity sha512-XLLd/+4sPC2ZkN/6+V4O4gjJu6kSDbHAChvsyWgm1oGbdSO3efvGYnm25yCjtFm/K7rrSDvSfPDgN1pHgS4VNQ== + dependencies: + "@vue/reactivity" "3.5.26" + "@vue/runtime-core" "3.5.26" + "@vue/shared" "3.5.26" + csstype "^3.2.3" + +"@vue/server-renderer@3.5.26": + version "3.5.26" + resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.5.26.tgz#269055497fcc75b3984063f866f17c748b565ef4" + integrity sha512-TYKLXmrwWKSodyVuO1WAubucd+1XlLg4set0YoV+Hu8Lo79mp/YMwWV5mC5FgtsDxX3qo1ONrxFaTP1OQgy1uA== + dependencies: + "@vue/compiler-ssr" "3.5.26" + "@vue/shared" "3.5.26" + +"@vue/shared@3.5.26", "@vue/shared@^3.5.0", "@vue/shared@^3.5.18": + version "3.5.26" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.26.tgz#1e02ef2d64aced818cd31d81ce5175711dc90a9f" + integrity sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A== + +"@vueuse/core@^10.11.0": + version "10.11.1" + resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.11.1.tgz#15d2c0b6448d2212235b23a7ba29c27173e0c2c6" + integrity sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww== + dependencies: + "@types/web-bluetooth" "^0.0.20" + "@vueuse/metadata" "10.11.1" + "@vueuse/shared" "10.11.1" + vue-demi ">=0.14.8" + +"@vueuse/core@^13.9.0": + version "13.9.0" + resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-13.9.0.tgz#051aeff47a259e9e4d7d0cc3e54879817b0cbcad" + integrity sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA== + dependencies: + "@types/web-bluetooth" "^0.0.21" + "@vueuse/metadata" "13.9.0" + "@vueuse/shared" "13.9.0" + +"@vueuse/metadata@10.11.1": + version "10.11.1" + resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-10.11.1.tgz#209db7bb5915aa172a87510b6de2ca01cadbd2a7" + integrity sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw== + +"@vueuse/metadata@13.9.0": + version "13.9.0" + resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-13.9.0.tgz#57c738d99661c33347080c0bc4cd11160e0d0881" + integrity sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg== + +"@vueuse/shared@10.11.1": + version "10.11.1" + resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-10.11.1.tgz#62b84e3118ae6e1f3ff38f4fbe71b0c5d0f10938" + integrity sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA== + dependencies: + vue-demi ">=0.14.8" + +"@vueuse/shared@13.9.0": + version "13.9.0" + resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-13.9.0.tgz#7168b4ed647e625b05eb4e7e80fe8aabd00e3923" + integrity sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g== + +"@wangeditor/basic-modules@^1.1.7": + version "1.1.7" + resolved "https://registry.yarnpkg.com/@wangeditor/basic-modules/-/basic-modules-1.1.7.tgz#a9c3ccf4ef53332f29550d59d3676e15f395946f" + integrity sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg== + dependencies: + is-url "^1.2.4" + +"@wangeditor/code-highlight@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@wangeditor/code-highlight/-/code-highlight-1.0.3.tgz#90256857714d5c0cf83ac475aea64db7bf29a7cd" + integrity sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw== + dependencies: + prismjs "^1.23.0" + +"@wangeditor/core@^1.1.19": + version "1.1.19" + resolved "https://registry.yarnpkg.com/@wangeditor/core/-/core-1.1.19.tgz#f9155f7fd92d03cb1982405b3b82e54c31f1c2b0" + integrity sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q== + dependencies: + "@types/event-emitter" "^0.3.3" + event-emitter "^0.3.5" + html-void-elements "^2.0.0" + i18next "^20.4.0" + scroll-into-view-if-needed "^2.2.28" + slate-history "^0.66.0" + +"@wangeditor/editor-for-vue@next": + version "5.1.12" + resolved "https://registry.yarnpkg.com/@wangeditor/editor-for-vue/-/editor-for-vue-5.1.12.tgz#f7d5f239b39cdfc01d31151488de8443fe6edc64" + integrity sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ== + +"@wangeditor/editor@^5.1.23": + version "5.1.23" + resolved "https://registry.yarnpkg.com/@wangeditor/editor/-/editor-5.1.23.tgz#c9d2007b7cb0ceef6b72692b4ee87b01ee2367b3" + integrity sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ== + dependencies: + "@uppy/core" "^2.1.1" + "@uppy/xhr-upload" "^2.0.3" + "@wangeditor/basic-modules" "^1.1.7" + "@wangeditor/code-highlight" "^1.0.3" + "@wangeditor/core" "^1.1.19" + "@wangeditor/list-module" "^1.0.5" + "@wangeditor/table-module" "^1.1.4" + "@wangeditor/upload-image-module" "^1.0.2" + "@wangeditor/video-module" "^1.1.4" + dom7 "^3.0.0" + is-hotkey "^0.2.0" + lodash.camelcase "^4.3.0" + lodash.clonedeep "^4.5.0" + lodash.debounce "^4.0.8" + lodash.foreach "^4.5.0" + lodash.isequal "^4.5.0" + lodash.throttle "^4.1.1" + lodash.toarray "^4.4.0" + nanoid "^3.2.0" + slate "^0.72.0" + snabbdom "^3.1.0" + +"@wangeditor/list-module@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@wangeditor/list-module/-/list-module-1.0.5.tgz#3fc0b167acddf885536b45fa0c127f9c6adaea33" + integrity sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ== + +"@wangeditor/table-module@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@wangeditor/table-module/-/table-module-1.1.4.tgz#757d4a5868b2b658041cd323854a4d707c8347e9" + integrity sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w== + +"@wangeditor/upload-image-module@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@wangeditor/upload-image-module/-/upload-image-module-1.0.2.tgz#89e9b9467e10cbc6b11dc5748e08dd23aaebee30" + integrity sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA== + +"@wangeditor/video-module@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@wangeditor/video-module/-/video-module-1.1.4.tgz#b9df1b3ab2cd53f678b19b4d927e200774a6f532" + integrity sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.15.0, acorn@^8.9.0: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + +adler-32@~1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/adler-32/-/adler-32-1.3.1.tgz#1dbf0b36dda0012189a32b3679061932df1821e2" + integrity sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A== + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +alien-signals@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/alien-signals/-/alien-signals-0.2.2.tgz#439d09b363dc4d609c0f6ce69362dce068d23197" + integrity sha512-cZIRkbERILsBOXTQmMrxc9hgpxglstn69zm+F1ARf4aPAzdAFYd6sBq87ErO0Fj3DV94tglcyHG5kQz9nDC/8A== + +ansi-escapes@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.2.0.tgz#31b25afa3edd3efc09d98c2fee831d460ff06b49" + integrity sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw== + dependencies: + environment "^1.0.0" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.0.0, ansi-styles@^6.2.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async-validator@^4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339" + integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@^1.12.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.13.2.tgz#9ada120b7b5ab24509553ec3e40123521117f687" + integrity sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.4" + proxy-from-env "^1.1.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +balanced-match@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9" + integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA== + +baseline-browser-mapping@^2.9.0: + version "2.9.11" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz#53724708c8db5f97206517ecfe362dbe5181deea" + integrity sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +birpc@^2.3.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/birpc/-/birpc-2.9.0.tgz#b59550897e4cd96a223e2a6c1475b572236ed145" + integrity sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw== + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +brace-expansion@^1.1.7: + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browserslist@^4.24.0: + version "4.28.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95" + integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA== + dependencies: + baseline-browser-mapping "^2.9.0" + caniuse-lite "^1.0.30001759" + electron-to-chromium "^1.5.263" + node-releases "^2.0.27" + update-browserslist-db "^1.2.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +bundle-name@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-4.1.0.tgz#f3b96b34160d6431a19d7688135af7cfb8797889" + integrity sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q== + dependencies: + run-applescript "^7.0.0" + +cacheable@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/cacheable/-/cacheable-2.3.1.tgz#db374342fbb48b032d57a2a7d296555be4ad574e" + integrity sha512-yr+FSHWn1ZUou5LkULX/S+jhfgfnLbuKQjE40tyEd4fxGZVMbBL5ifno0J0OauykS8UiCSgHi+DV/YD+rjFxFg== + dependencies: + "@cacheable/memory" "^2.0.6" + "@cacheable/utils" "^2.3.2" + hookified "^1.14.0" + keyv "^5.5.5" + qified "^0.5.3" + +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +caniuse-lite@^1.0.30001759: + version "1.0.30001762" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001762.tgz#e4dbfeda63d33258cdde93e53af2023a13ba27d4" + integrity sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw== + +cfb@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cfb/-/cfb-1.2.2.tgz#94e687628c700e5155436dac05f74e08df23bc44" + integrity sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA== + dependencies: + adler-32 "~1.3.0" + crc-32 "~1.2.0" + +chalk@^4.0.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^5.4.1: + version "5.6.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea" + integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== + +chokidar@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +cli-cursor@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-5.0.0.tgz#24a4831ecf5a6b01ddeb32fb71a4b2088b0dce38" + integrity sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw== + dependencies: + restore-cursor "^5.0.0" + +cli-truncate@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-4.0.0.tgz#6cc28a2924fee9e25ce91e973db56c7066e6172a" + integrity sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA== + dependencies: + slice-ansi "^5.0.0" + string-width "^7.0.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +codepage@~1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/codepage/-/codepage-1.15.0.tgz#2e00519024b39424ec66eeb3ec07227e692618ab" + integrity sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colord@^2.9.3: + version "2.9.3" + resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" + integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== + +colorette@^2.0.20: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^13.1.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" + integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +compute-scroll-into-view@^1.0.20: + version "1.0.20" + resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz#1768b5522d1172754f5d0c9b02de3af6be506a43" + integrity sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + +confbox@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.2.2.tgz#8652f53961c74d9e081784beed78555974a9c110" + integrity sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +copy-anything@^4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-4.0.5.tgz#16cabafd1ea4bb327a540b750f2b4df522825aea" + integrity sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA== + dependencies: + is-what "^5.2.0" + +core-js@^3.20.3: + version "3.47.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.47.0.tgz#436ef07650e191afeb84c24481b298bd60eb4a17" + integrity sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg== + +cosmiconfig@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d" + integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== + dependencies: + env-paths "^2.2.1" + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + +crc-32@~1.2.0, crc-32@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + +cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto-js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== + +css-functions-list@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/css-functions-list/-/css-functions-list-3.2.3.tgz#95652b0c24f0f59b291a9fc386041a19d4f40dbe" + integrity sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA== + +css-tree@^3.0.1, css-tree@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-3.1.0.tgz#7aabc035f4e66b5c86f54570d55e05b1346eb0fd" + integrity sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w== + dependencies: + mdn-data "2.12.2" + source-map-js "^1.0.1" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +csstype@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.2.3.tgz#ec48c0f3e993e50648c86da559e2610995cf989a" + integrity sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ== + +d@1, d@^1.0.1, d@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.2.tgz#2aefd554b81981e7dccf72d6842ae725cb17e5de" + integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== + dependencies: + es5-ext "^0.10.64" + type "^2.7.2" + +danmu.js@>=1.1.6: + version "1.2.1" + resolved "https://registry.yarnpkg.com/danmu.js/-/danmu.js-1.2.1.tgz#952bedb14a344bca5b45fb3ea13cba80ae0c7c1d" + integrity sha512-evDEImUBo94c846fC92K//Dzll8jXnZ3zKmYlQHwMzmvw6IW2IyjWL3Ew2SqEAzuqauFnDkwJEgZauu3uW/p1Q== + dependencies: + event-emitter "^0.3.5" + +dayjs@^1.11.19: + version "1.11.19" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.19.tgz#15dc98e854bb43917f12021806af897c58ae2938" + integrity sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw== + +de-indent@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" + integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== + +debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.7, debug@^4.4.0, debug@^4.4.3: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +default-browser-id@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-5.0.1.tgz#f7a7ccb8f5104bf8e0f71ba3b1ccfa5eafdb21e8" + integrity sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q== + +default-browser@^5.2.1: + version "5.4.0" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-5.4.0.tgz#b55cf335bb0b465dd7c961a02cd24246aa434287" + integrity sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg== + dependencies: + bundle-name "^4.1.0" + default-browser-id "^5.0.0" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + +defu@^6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" + integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +delegate@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" + integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== + +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + +detect-libc@^2.0.3: + version "2.1.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" + integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +dom7@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/dom7/-/dom7-3.0.0.tgz#b861ce5d67a6becd7aaa3ad02942ff14b1240331" + integrity sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g== + dependencies: + ssr-window "^3.0.0-alpha.1" + +downloadjs@1.4.7: + version "1.4.7" + resolved "https://registry.yarnpkg.com/downloadjs/-/downloadjs-1.4.7.tgz#f69f96f940e0d0553dac291139865a3cd0101e3c" + integrity sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q== + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +echarts@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/echarts/-/echarts-6.0.0.tgz#2935aa7751c282d1abbbf7d719d397199a15b9e7" + integrity sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ== + dependencies: + tslib "2.3.0" + zrender "6.0.0" + +electron-to-chromium@^1.5.263: + version "1.5.267" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz#5d84f2df8cdb6bfe7e873706bb21bd4bfb574dc7" + integrity sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw== + +element-plus@^2.11.2: + version "2.13.0" + resolved "https://registry.yarnpkg.com/element-plus/-/element-plus-2.13.0.tgz#e2ae817c1ed4fa9e94456af69a0f88cd824ee0c7" + integrity sha512-qjxS+SBChvqCl6lU6ShiliLMN6WqFHiXQENYbAY3GKNflG+FS3jqn8JmQq0CBZq4koFqsi95NT1M6SL4whZfrA== + dependencies: + "@ctrl/tinycolor" "^3.4.1" + "@element-plus/icons-vue" "^2.3.2" + "@floating-ui/dom" "^1.0.1" + "@popperjs/core" "npm:@sxzz/popperjs-es@^2.11.7" + "@types/lodash" "^4.17.20" + "@types/lodash-es" "^4.17.12" + "@vueuse/core" "^10.11.0" + async-validator "^4.2.5" + dayjs "^1.11.19" + lodash "^4.17.21" + lodash-es "^4.17.21" + lodash-unified "^1.0.3" + memoize-one "^6.0.0" + normalize-wheel-es "^1.2.0" + +emoji-regex@^10.3.0: + version "10.6.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.6.0.tgz#bf3d6e8f7f8fd22a65d9703475bc0147357a6b0d" + integrity sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +enhanced-resolve@^5.18.3: + version "5.18.4" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz#c22d33055f3952035ce6a144ce092447c525f828" + integrity sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +entities@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-7.0.0.tgz#2ae4e443f3f17d152d3f5b0f79b932c1e59deb7a" + integrity sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ== + +env-paths@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +environment@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" + integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== + +error-ex@^1.3.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" + integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== + dependencies: + is-arrayish "^0.2.1" + +error-stack-parser-es@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/error-stack-parser-es/-/error-stack-parser-es-0.1.5.tgz#15b50b67bea4b6ed6596976ee07c7867ae25bb1c" + integrity sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg== + +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-module-lexer@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" + integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.62, es5-ext@^0.10.64, es5-ext@~0.10.14: + version "0.10.64" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714" + integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + esniff "^2.0.1" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.4" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.4.tgz#f4e7d28013770b4208ecbf3e0bf14d3bcb557b8c" + integrity sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg== + dependencies: + d "^1.0.2" + ext "^1.7.0" + +esbuild@^0.27.0, esbuild@~0.27.0: + version "0.27.2" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.27.2.tgz#d83ed2154d5813a5367376bb2292a9296fc83717" + integrity sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.27.2" + "@esbuild/android-arm" "0.27.2" + "@esbuild/android-arm64" "0.27.2" + "@esbuild/android-x64" "0.27.2" + "@esbuild/darwin-arm64" "0.27.2" + "@esbuild/darwin-x64" "0.27.2" + "@esbuild/freebsd-arm64" "0.27.2" + "@esbuild/freebsd-x64" "0.27.2" + "@esbuild/linux-arm" "0.27.2" + "@esbuild/linux-arm64" "0.27.2" + "@esbuild/linux-ia32" "0.27.2" + "@esbuild/linux-loong64" "0.27.2" + "@esbuild/linux-mips64el" "0.27.2" + "@esbuild/linux-ppc64" "0.27.2" + "@esbuild/linux-riscv64" "0.27.2" + "@esbuild/linux-s390x" "0.27.2" + "@esbuild/linux-x64" "0.27.2" + "@esbuild/netbsd-arm64" "0.27.2" + "@esbuild/netbsd-x64" "0.27.2" + "@esbuild/openbsd-arm64" "0.27.2" + "@esbuild/openbsd-x64" "0.27.2" + "@esbuild/openharmony-arm64" "0.27.2" + "@esbuild/sunos-x64" "0.27.2" + "@esbuild/win32-arm64" "0.27.2" + "@esbuild/win32-ia32" "0.27.2" + "@esbuild/win32-x64" "0.27.2" + +escalade@^3.1.1, escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" + integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== + +eslint-config-prettier@^9.1.0: + version "9.1.2" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.2.tgz#90deb4fa0259592df774b600dbd1d2249a78ce91" + integrity sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ== + +eslint-plugin-prettier@^5.2.1: + version "5.5.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz#9d61c4ea11de5af704d4edf108c82ccfa7f2e61c" + integrity sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.11.7" + +eslint-plugin-vue@^9.27.0: + version "9.33.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz#de33eba8f78e1d172c59c8ec7fbfd60c6ca35c39" + integrity sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + globals "^13.24.0" + natural-compare "^1.4.0" + nth-check "^2.1.1" + postcss-selector-parser "^6.0.15" + semver "^7.6.3" + vue-eslint-parser "^9.4.3" + xml-name-validator "^4.0.0" + +eslint-scope@^7.1.1: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-scope@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== + +eslint@^9.9.1: + version "9.39.2" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.39.2.tgz#cb60e6d16ab234c0f8369a3fe7cc87967faf4b6c" + integrity sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw== + dependencies: + "@eslint-community/eslint-utils" "^4.8.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.21.1" + "@eslint/config-helpers" "^0.4.2" + "@eslint/core" "^0.17.0" + "@eslint/eslintrc" "^3.3.1" + "@eslint/js" "9.39.2" + "@eslint/plugin-kit" "^0.4.1" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.2" + "@types/estree" "^1.0.6" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.6" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.4.0" + eslint-visitor-keys "^4.2.1" + espree "^10.4.0" + esquery "^1.5.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + json-stable-stringify-without-jsonify "^1.0.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + +esniff@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" + integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== + dependencies: + d "^1.0.1" + es5-ext "^0.10.62" + event-emitter "^0.3.5" + type "^2.7.2" + +espree@^10.0.1, espree@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== + dependencies: + acorn "^8.15.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.1" + +espree@^9.3.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.0, esquery@^1.5.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.7.0.tgz#08d048f261f0ddedb5bae95f46809463d9c9496d" + integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +estree-walker@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + +eventemitter3@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + +execa@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" + integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^8.0.1" + human-signals "^5.0.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^4.1.0" + strip-final-newline "^3.0.0" + +execa@^9.5.2: + version "9.6.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-9.6.1.tgz#5b90acedc6bdc0fa9b9a6ddf8f9cbb0c75a7c471" + integrity sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA== + dependencies: + "@sindresorhus/merge-streams" "^4.0.0" + cross-spawn "^7.0.6" + figures "^6.1.0" + get-stream "^9.0.0" + human-signals "^8.0.1" + is-plain-obj "^4.1.0" + is-stream "^4.0.1" + npm-run-path "^6.0.0" + pretty-ms "^9.2.0" + signal-exit "^4.1.0" + strip-final-newline "^4.0.0" + yoctocolors "^2.1.1" + +exsolve@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/exsolve/-/exsolve-1.0.8.tgz#7f5e34da61cd1116deda5136e62292c096f50613" + integrity sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA== + +ext@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-glob@^3.2.9, fast-glob@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-uri@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" + integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== + +fastest-levenshtein@^1.0.16: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +fastq@^1.6.0: + version "1.20.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.20.1.tgz#ca750a10dc925bc8b18839fd203e3ef4b3ced675" + integrity sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw== + dependencies: + reusify "^1.0.4" + +fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + +figures@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-6.1.0.tgz#935479f51865fa7479f6fa94fc6fc7ac14e62c4a" + integrity sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg== + dependencies: + is-unicode-supported "^2.0.0" + +file-entry-cache@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-11.1.1.tgz#728918c624dbeb09372276837ea0c413ec78806b" + integrity sha512-TPVFSDE7q91Dlk1xpFLvFllf8r0HyOMOlnWy7Z2HBku5H3KhIeOGInexrIeg2D64DosVB/JXkrrk6N/7Wriq4A== + dependencies: + flat-cache "^6.1.19" + +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + +file-saver@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" + integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flat-cache@^6.1.19: + version "6.1.19" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-6.1.19.tgz#20e5b201c9b181a7b773b3b150108932077d2bbf" + integrity sha512-l/K33newPTZMTGAnnzaiqSl6NnH7Namh8jBNjrgjprWxGmZUuxx/sJNIRaijOh3n7q7ESbhNZC+pvVZMFdeU4A== + dependencies: + cacheable "^2.2.0" + flatted "^3.3.3" + hookified "^1.13.0" + +flatted@^3.2.9, flatted@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" + integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== + +follow-redirects@^1.15.6: + version "1.15.11" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340" + integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== + +form-data@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053" + integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" + mime-types "^2.1.12" + +frac@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b" + integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA== + +fs-extra@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^11.2.0: + version "11.3.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.3.tgz#a27da23b72524e81ac6c3815cc0179b8c74c59ee" + integrity sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-east-asian-width@^1.0.0, get-east-asian-width@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz#9bc4caa131702b4b61729cb7e42735bc550c9ee6" + integrity sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q== + +get-intrinsic@^1.2.6: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-stream@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" + integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== + +get-stream@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-9.0.1.tgz#95157d21df8eb90d1647102b63039b1df60ebd27" + integrity sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA== + dependencies: + "@sec-ant/readable-stream" "^0.4.1" + is-stream "^4.0.1" + +get-tsconfig@^4.7.5: + version "4.13.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.13.0.tgz#fcdd991e6d22ab9a600f00e91c318707a5d9a0d7" + integrity sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ== + dependencies: + resolve-pkg-maps "^1.0.0" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +globals@^13.24.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + +globals@^15.9.0: + version "15.15.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-15.15.0.tgz#7c4761299d41c32b075715a4ce1ede7897ff72a8" + integrity sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg== + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +globjoin@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" + integrity sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg== + +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hashery@^1.2.0, hashery@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/hashery/-/hashery-1.4.0.tgz#3af04d9af0c63ff2f15a353ee9c2d11fdef7919f" + integrity sha512-Wn2i1In6XFxl8Az55kkgnFRiAlIAushzh26PTjL2AKtQcEfXrcLa7Hn5QOWGZEf3LU057P9TwwZjFyxfS1VuvQ== + dependencies: + hookified "^1.14.0" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +highlight.js@^11.10.0: + version "11.11.1" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.11.1.tgz#fca06fa0e5aeecf6c4d437239135fabc15213585" + integrity sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w== + +hookable@^5.5.3: + version "5.5.3" + resolved "https://registry.yarnpkg.com/hookable/-/hookable-5.5.3.tgz#6cfc358984a1ef991e2518cb9ed4a778bbd3215d" + integrity sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ== + +hookified@^1.13.0, hookified@^1.14.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/hookified/-/hookified-1.15.0.tgz#d51db9fe134b8bd19c1aa88f9fcd7878995e4b66" + integrity sha512-51w+ZZGt7Zw5q7rM3nC4t3aLn/xvKDETsXqMczndvwyVQhAHfUmUuFBRFcos8Iyebtk7OAE9dL26wFNzZVVOkw== + +html-tags@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce" + integrity sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ== + +html-void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-2.0.1.tgz#29459b8b05c200b6c5ee98743c41b979d577549f" + integrity sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A== + +human-signals@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" + integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== + +human-signals@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-8.0.1.tgz#f08bb593b6d1db353933d06156cedec90abe51fb" + integrity sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ== + +i18next@^20.4.0: + version "20.6.1" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-20.6.1.tgz#535e5f6e5baeb685c7d25df70db63bf3cc0aa345" + integrity sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A== + dependencies: + "@babel/runtime" "^7.12.0" + +ignore@^5.2.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +ignore@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" + integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== + +immer@^9.0.6: + version "9.0.21" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" + integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== + +immutable@^5.0.2: + version "5.1.4" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.1.4.tgz#e3f8c1fe7b567d56cf26698f31918c241dae8c1f" + integrity sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA== + +import-fresh@^3.2.1, import-fresh@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +ini@^1.3.5: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-fullwidth-code-point@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" + integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + +is-fullwidth-code-point@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz#046b2a6d4f6b156b2233d3207d4b5a9783999b98" + integrity sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ== + dependencies: + get-east-asian-width "^1.3.1" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hotkey@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/is-hotkey/-/is-hotkey-0.2.0.tgz#1835a68171a91e5c9460869d96336947c8340cef" + integrity sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw== + +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" + integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== + +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + +is-stream@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-4.0.1.tgz#375cf891e16d2e4baec250b85926cffc14720d9b" + integrity sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A== + +is-unicode-supported@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz#09f0ab0de6d3744d48d265ebb98f65d11f2a9b3a" + integrity sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ== + +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +is-what@^5.2.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/is-what/-/is-what-5.5.0.tgz#a3031815757cfe1f03fed990bf6355a2d3f628c4" + integrity sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw== + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +is-wsl@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" + integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== + dependencies: + is-inside-container "^1.0.0" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +jiti@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.6.1.tgz#178ef2fc9a1a594248c20627cd820187a4d78d92" + integrity sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.1.tgz#2ec43964658435296f6761b34e10671c2d9527f4" + integrity sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ== + +js-yaml@^4.1.0, js-yaml@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== + dependencies: + argparse "^2.0.1" + +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonfile@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.2.0.tgz#7c265bd1b65de6977478300087c99f1c84383f62" + integrity sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +keyv@^5.5.5: + version "5.5.5" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-5.5.5.tgz#a975b32fc03e300a0e443c705b103d8b05220834" + integrity sha512-FA5LmZVF1VziNc0bIdCSA1IoSVnDCqE8HJIZZv2/W8YmoAM50+tnUgJR/gQZwEeIMleuIOnRnHA/UaZRNeV4iQ== + dependencies: + "@keyv/serialize" "^1.1.1" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +known-css-properties@^0.37.0: + version "0.37.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.37.0.tgz#10ebe49b9dbb6638860ff8a002fb65a053f4aec5" + integrity sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ== + +kolorist@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c" + integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lightningcss-android-arm64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz#6966b7024d39c94994008b548b71ab360eb3a307" + integrity sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A== + +lightningcss-darwin-arm64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz#a5fa946d27c029e48c7ff929e6e724a7de46eb2c" + integrity sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA== + +lightningcss-darwin-x64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz#5ce87e9cd7c4f2dcc1b713f5e8ee185c88d9b7cd" + integrity sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ== + +lightningcss-freebsd-x64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz#6ae1d5e773c97961df5cff57b851807ef33692a5" + integrity sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA== + +lightningcss-linux-arm-gnueabihf@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz#62c489610c0424151a6121fa99d77731536cdaeb" + integrity sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA== + +lightningcss-linux-arm64-gnu@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz#2a3661b56fe95a0cafae90be026fe0590d089298" + integrity sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A== + +lightningcss-linux-arm64-musl@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz#d7ddd6b26959245e026bc1ad9eb6aa983aa90e6b" + integrity sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA== + +lightningcss-linux-x64-gnu@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz#5a89814c8e63213a5965c3d166dff83c36152b1a" + integrity sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w== + +lightningcss-linux-x64-musl@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz#808c2e91ce0bf5d0af0e867c6152e5378c049728" + integrity sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA== + +lightningcss-win32-arm64-msvc@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz#ab4a8a8a2e6a82a4531e8bbb6bf0ff161ee6625a" + integrity sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ== + +lightningcss-win32-x64-msvc@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz#f01f382c8e0a27e1c018b0bee316d210eac43b6e" + integrity sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw== + +lightningcss@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.30.2.tgz#4ade295f25d140f487d37256f4cd40dc607696d0" + integrity sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ== + dependencies: + detect-libc "^2.0.3" + optionalDependencies: + lightningcss-android-arm64 "1.30.2" + lightningcss-darwin-arm64 "1.30.2" + lightningcss-darwin-x64 "1.30.2" + lightningcss-freebsd-x64 "1.30.2" + lightningcss-linux-arm-gnueabihf "1.30.2" + lightningcss-linux-arm64-gnu "1.30.2" + lightningcss-linux-arm64-musl "1.30.2" + lightningcss-linux-x64-gnu "1.30.2" + lightningcss-linux-x64-musl "1.30.2" + lightningcss-win32-arm64-msvc "1.30.2" + lightningcss-win32-x64-msvc "1.30.2" + +lilconfig@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" + integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +lint-staged@^15.5.2: + version "15.5.2" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.5.2.tgz#beff028fd0681f7db26ffbb67050a21ed4d059a3" + integrity sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w== + dependencies: + chalk "^5.4.1" + commander "^13.1.0" + debug "^4.4.0" + execa "^8.0.1" + lilconfig "^3.1.3" + listr2 "^8.2.5" + micromatch "^4.0.8" + pidtree "^0.6.0" + string-argv "^0.3.2" + yaml "^2.7.0" + +listr2@^8.2.5: + version "8.3.3" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.3.3.tgz#815fc8f738260ff220981bf9e866b3e11e8121bf" + integrity sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ== + dependencies: + cli-truncate "^4.0.0" + colorette "^2.0.20" + eventemitter3 "^5.0.1" + log-update "^6.1.0" + rfdc "^1.4.1" + wrap-ansi "^9.0.0" + +local-pkg@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-1.1.2.tgz#c03d208787126445303f8161619dc701afa4abb5" + integrity sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A== + dependencies: + mlly "^1.7.4" + pkg-types "^2.3.0" + quansync "^0.2.11" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash-es@^4.17.21: + version "4.17.22" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.22.tgz#eb7d123ec2470d69b911abe34f85cb694849b346" + integrity sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q== + +lodash-unified@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/lodash-unified/-/lodash-unified-1.0.3.tgz#80b1eac10ed2eb02ed189f08614a29c27d07c894" + integrity sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ== + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lodash.foreach@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + integrity sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ== + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +lodash.toarray@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" + integrity sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-update@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.1.0.tgz#1a04ff38166f94647ae1af562f4bd6a15b1b7cd4" + integrity sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w== + dependencies: + ansi-escapes "^7.0.0" + cli-cursor "^5.0.0" + slice-ansi "^7.1.0" + strip-ansi "^7.1.0" + wrap-ansi "^9.0.0" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +magic-string@^0.30.17, magic-string@^0.30.19, magic-string@^0.30.21, magic-string@^0.30.4: + version "0.30.21" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +mathml-tag-names@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" + integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== + +mdn-data@2.12.2: + version "2.12.2" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.12.2.tgz#9ae6c41a9e65adf61318b32bff7b64fbfb13f8cf" + integrity sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA== + +mdn-data@^2.25.0: + version "2.25.0" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.25.0.tgz#d45610fae17b222d600bbef3136bd6155ac9cc16" + integrity sha512-T2LPsjgUE/tgMmRXREVmwsux89DwWfNjiynOeXuLd2mX6jphGQ2YE3Ukz7LQ2VOFKiVZU/Ee1GqzHiipZCjymw== + +memoize-one@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" + integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== + +meow@^13.2.0: + version "13.2.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-13.2.0.tgz#6b7d63f913f984063b3cc261b6e8800c4cd3474f" + integrity sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.5, micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-match@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/mime-match/-/mime-match-1.0.2.tgz#3f87c31e9af1a5fd485fb9db134428b23bbb7ba8" + integrity sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg== + dependencies: + wildcard "^1.1.0" + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + +mimic-function@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mimic-function/-/mimic-function-5.0.1.tgz#acbe2b3349f99b9deaca7fb70e48b83e94e67076" + integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== + +minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^9.0.3, minimatch@^9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +mitt@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" + integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== + +mlly@^1.7.4, mlly@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.8.0.tgz#e074612b938af8eba1eaf43299cbc89cb72d824e" + integrity sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g== + dependencies: + acorn "^8.15.0" + pathe "^2.0.3" + pkg-types "^1.3.1" + ufo "^1.6.1" + +mrmime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.1.tgz#bc3e87f7987853a54c9850eeb1f1078cd44adddc" + integrity sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +muggle-string@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/muggle-string/-/muggle-string-0.4.1.tgz#3b366bd43b32f809dc20659534dd30e7c8a0d328" + integrity sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ== + +namespace-emitter@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/namespace-emitter/-/namespace-emitter-2.0.1.tgz#978d51361c61313b4e6b8cf6f3853d08dfa2b17c" + integrity sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g== + +nanoid@^3.1.25, nanoid@^3.2.0, nanoid@^3.3.11: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +nanoid@^5.1.0: + version "5.1.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-5.1.6.tgz#30363f664797e7d40429f6c16946d6bd7a3f26c9" + integrity sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +node-addon-api@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" + integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== + +node-releases@^2.0.27: + version "2.0.27" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" + integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-wheel-es@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz#0fa2593d619f7245a541652619105ab076acf09e" + integrity sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw== + +npm-run-path@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" + integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== + dependencies: + path-key "^4.0.0" + +npm-run-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-6.0.0.tgz#25cfdc4eae04976f3349c0b1afc089052c362537" + integrity sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA== + dependencies: + path-key "^4.0.0" + unicorn-magic "^0.3.0" + +nprogress@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" + integrity sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA== + +nth-check@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +ohash@^2.0.11: + version "2.0.11" + resolved "https://registry.yarnpkg.com/ohash/-/ohash-2.0.11.tgz#60b11e8cff62ca9dee88d13747a5baa145f5900b" + integrity sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ== + +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +onetime@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-7.0.0.tgz#9f16c92d8c9ef5120e3acd9dd9957cceecc1ab60" + integrity sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ== + dependencies: + mimic-function "^5.0.0" + +open@^10.1.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/open/-/open-10.2.0.tgz#b9d855be007620e80b6fb05fac98141fe62db73c" + integrity sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA== + dependencies: + default-browser "^5.2.1" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + wsl-utils "^0.1.0" + +open@^8.4.0: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse-ms@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-4.0.0.tgz#c0c058edd47c2a590151a718990533fd62803df4" + integrity sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw== + +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pathe@^2.0.1, pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + +perfect-debounce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz#9c2e8bc30b169cc984a58b7d5b28049839591d2a" + integrity sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^4.0.2, picomatch@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + +pidtree@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" + integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== + +pinia-plugin-persistedstate@^4.3.0: + version "4.7.1" + resolved "https://registry.yarnpkg.com/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-4.7.1.tgz#d13880e0b7efdafd1b73fca3d73cd64ae34bde84" + integrity sha512-WHOqh2esDlR3eAaknPbqXrkkj0D24h8shrDPqysgCFR6ghqP/fpFfJmMPJp0gETHsvrh9YNNg6dQfo2OEtDnIQ== + dependencies: + defu "^6.1.4" + +pinia@^3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/pinia/-/pinia-3.0.4.tgz#75dde12784a61e34c1fa6abcd13c1a1061c360c0" + integrity sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw== + dependencies: + "@vue/devtools-api" "^7.7.7" + +pkg-types@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.3.1.tgz#bd7cc70881192777eef5326c19deb46e890917df" + integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== + dependencies: + confbox "^0.1.8" + mlly "^1.7.4" + pathe "^2.0.1" + +pkg-types@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-2.3.0.tgz#037f2c19bd5402966ff6810e32706558cb5b5726" + integrity sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig== + dependencies: + confbox "^0.2.2" + exsolve "^1.0.7" + pathe "^2.0.3" + +postcss-media-query-parser@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" + integrity sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig== + +postcss-resolve-nested-selector@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz#3d84dec809f34de020372c41b039956966896686" + integrity sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw== + +postcss-safe-parser@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz#36e4f7e608111a0ca940fd9712ce034718c40ec0" + integrity sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A== + +postcss-scss@^4.0.9: + version "4.0.9" + resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-4.0.9.tgz#a03c773cd4c9623cb04ce142a52afcec74806685" + integrity sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A== + +postcss-selector-parser@^6.0.15: + version "6.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de" + integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-selector-parser@^7.1.0, postcss-selector-parser@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz#e75d2e0d843f620e5df69076166f4e16f891cb9f" + integrity sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-sorting@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/postcss-sorting/-/postcss-sorting-8.0.2.tgz#6393385ece272baf74bee9820fb1b58098e4eeca" + integrity sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q== + +postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.4.32, postcss@^8.5.6: + version "8.5.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +preact@^10.5.13: + version "10.28.2" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.28.2.tgz#4b668383afa4b4a2546bbe4bd1747e02e2360138" + integrity sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz#6a31f88a4bad6c7adda253de12ba4edaea80ebcd" + integrity sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg== + dependencies: + fast-diff "^1.1.2" + +prettier@^3.5.3: + version "3.7.4" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.7.4.tgz#d2f8335d4b1cec47e1c8098645411b0c9dff9c0f" + integrity sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA== + +pretty-ms@^9.2.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-9.3.0.tgz#dd2524fcb3c326b4931b2272dfd1e1a8ed9a9f5a" + integrity sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ== + dependencies: + parse-ms "^4.0.0" + +prismjs@^1.23.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.30.0.tgz#d9709969d9d4e16403f6f348c63553b19f0975a9" + integrity sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw== + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +qified@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/qified/-/qified-0.5.3.tgz#2d01866eb99c8de3a18965a4a809d9349e26210a" + integrity sha512-kXuQdQTB6oN3KhI6V4acnBSZx8D2I4xzZvn9+wFLLFCoBNQY/sFnCW6c43OL7pOQ2HvGV4lnWIXNmgfp7cTWhQ== + dependencies: + hookified "^1.13.0" + +qrcode.vue@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/qrcode.vue/-/qrcode.vue-3.6.0.tgz#d940fe96712922232aa19892bdd68793e62c73e7" + integrity sha512-vQcl2fyHYHMjDO1GguCldJxepq2izQjBkDEEu9NENgfVKP6mv/e2SU62WbqYHGwTgWXLhxZ1NCD1dAZKHQq1fg== + +quansync@^0.2.11: + version "0.2.11" + resolved "https://registry.yarnpkg.com/quansync/-/quansync-0.2.11.tgz#f9c3adda2e1272e4f8cf3f1457b04cbdb4ee692a" + integrity sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +restore-cursor@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-5.1.0.tgz#0766d95699efacb14150993f55baf0953ea1ebe7" + integrity sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA== + dependencies: + onetime "^7.0.0" + signal-exit "^4.1.0" + +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +rfdc@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== + +rollup-plugin-visualizer@^5.12.0: + version "5.14.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.14.0.tgz#be82d43fb3c644e396e2d50ac8a53d354022d57c" + integrity sha512-VlDXneTDaKsHIw8yzJAFWtrzguoJ/LnQ+lMpoVfYJ3jJF4Ihe5oYLAqLklIK/35lgUY+1yEzCkHyZ1j4A5w5fA== + dependencies: + open "^8.4.0" + picomatch "^4.0.2" + source-map "^0.7.4" + yargs "^17.5.1" + +rollup@^4.43.0: + version "4.55.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.55.1.tgz#4ec182828be440648e7ee6520dc35e9f20e05144" + integrity sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A== + dependencies: + "@types/estree" "1.0.8" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.55.1" + "@rollup/rollup-android-arm64" "4.55.1" + "@rollup/rollup-darwin-arm64" "4.55.1" + "@rollup/rollup-darwin-x64" "4.55.1" + "@rollup/rollup-freebsd-arm64" "4.55.1" + "@rollup/rollup-freebsd-x64" "4.55.1" + "@rollup/rollup-linux-arm-gnueabihf" "4.55.1" + "@rollup/rollup-linux-arm-musleabihf" "4.55.1" + "@rollup/rollup-linux-arm64-gnu" "4.55.1" + "@rollup/rollup-linux-arm64-musl" "4.55.1" + "@rollup/rollup-linux-loong64-gnu" "4.55.1" + "@rollup/rollup-linux-loong64-musl" "4.55.1" + "@rollup/rollup-linux-ppc64-gnu" "4.55.1" + "@rollup/rollup-linux-ppc64-musl" "4.55.1" + "@rollup/rollup-linux-riscv64-gnu" "4.55.1" + "@rollup/rollup-linux-riscv64-musl" "4.55.1" + "@rollup/rollup-linux-s390x-gnu" "4.55.1" + "@rollup/rollup-linux-x64-gnu" "4.55.1" + "@rollup/rollup-linux-x64-musl" "4.55.1" + "@rollup/rollup-openbsd-x64" "4.55.1" + "@rollup/rollup-openharmony-arm64" "4.55.1" + "@rollup/rollup-win32-arm64-msvc" "4.55.1" + "@rollup/rollup-win32-ia32-msvc" "4.55.1" + "@rollup/rollup-win32-x64-gnu" "4.55.1" + "@rollup/rollup-win32-x64-msvc" "4.55.1" + fsevents "~2.3.2" + +run-applescript@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-7.1.0.tgz#2e9e54c4664ec3106c5b5630e249d3d6595c4911" + integrity sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +sass@^1.81.0: + version "1.97.2" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.97.2.tgz#e515a319092fd2c3b015228e3094b40198bff0da" + integrity sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw== + dependencies: + chokidar "^4.0.0" + immutable "^5.0.2" + source-map-js ">=0.6.2 <2.0.0" + optionalDependencies: + "@parcel/watcher" "^2.4.1" + +scroll-into-view-if-needed@^2.2.28: + version "2.2.31" + resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz#d3c482959dc483e37962d1521254e3295d0d1587" + integrity sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA== + dependencies: + compute-scroll-into-view "^1.0.20" + +scule@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/scule/-/scule-1.3.0.tgz#6efbd22fd0bb801bdcc585c89266a7d2daa8fbd3" + integrity sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.5, semver@^7.3.6, semver@^7.5.4, semver@^7.6.3, semver@^7.7.3: + version "7.7.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" + integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^4.0.1, signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +sirv@^3.0.0, sirv@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-3.0.2.tgz#f775fccf10e22a40832684848d636346f41cd970" + integrity sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g== + dependencies: + "@polka/url" "^1.0.0-next.24" + mrmime "^2.0.0" + totalist "^3.0.0" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slate-history@^0.66.0: + version "0.66.0" + resolved "https://registry.yarnpkg.com/slate-history/-/slate-history-0.66.0.tgz#ac63fddb903098ceb4c944433e3f75fe63acf940" + integrity sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng== + dependencies: + is-plain-object "^5.0.0" + +slate@^0.72.0: + version "0.72.8" + resolved "https://registry.yarnpkg.com/slate/-/slate-0.72.8.tgz#5a018edf24e45448655293a68bfbcf563aa5ba81" + integrity sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw== + dependencies: + immer "^9.0.6" + is-plain-object "^5.0.0" + tiny-warning "^1.0.3" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" + integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== + dependencies: + ansi-styles "^6.0.0" + is-fullwidth-code-point "^4.0.0" + +slice-ansi@^7.1.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.2.tgz#adf7be70aa6d72162d907cd0e6d5c11f507b5403" + integrity sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w== + dependencies: + ansi-styles "^6.2.1" + is-fullwidth-code-point "^5.0.0" + +snabbdom@^3.1.0: + version "3.6.3" + resolved "https://registry.yarnpkg.com/snabbdom/-/snabbdom-3.6.3.tgz#1cdcd0a7188d3590da77e1fad87dbcc026b87b26" + integrity sha512-W2lHLLw2qR2Vv0DcMmcxXqcfdBaIcoN+y/86SmHv8fn4DazEQSH6KN3TjZcWvwujW56OHiiirsbHWZb4vx/0fg== + +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2, source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.4: + version "0.7.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.6.tgz#a3658ab87e5b6429c8a1f3ba0083d4c61ca3ef02" + integrity sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ== + +speakingurl@^14.0.1: + version "14.0.1" + resolved "https://registry.yarnpkg.com/speakingurl/-/speakingurl-14.0.1.tgz#f37ec8ddc4ab98e9600c1c9ec324a8c48d772a53" + integrity sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ== + +ssf@~0.11.2: + version "0.11.2" + resolved "https://registry.yarnpkg.com/ssf/-/ssf-0.11.2.tgz#0b99698b237548d088fc43cdf2b70c1a7512c06c" + integrity sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g== + dependencies: + frac "~1.1.2" + +ssr-window@^3.0.0-alpha.1: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ssr-window/-/ssr-window-3.0.0.tgz#fd5b82801638943e0cc704c4691801435af7ac37" + integrity sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA== + +string-argv@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" + integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" + integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== + dependencies: + emoji-regex "^10.3.0" + get-east-asian-width "^1.0.0" + strip-ansi "^7.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.1.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba" + integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== + dependencies: + ansi-regex "^6.0.1" + +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + +strip-final-newline@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-4.0.0.tgz#35a369ec2ac43df356e3edd5dcebb6429aa1fa5c" + integrity sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-literal@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-3.1.0.tgz#222b243dd2d49c0bcd0de8906adbd84177196032" + integrity sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg== + dependencies: + js-tokens "^9.0.1" + +stylelint-config-html@>=1.0.0, stylelint-config-html@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/stylelint-config-html/-/stylelint-config-html-1.1.0.tgz#999db19aea713b7ff6dde92ada76e4c1bd812b66" + integrity sha512-IZv4IVESjKLumUGi+HWeb7skgO6/g4VMuAYrJdlqQFndgbj6WJAXPhaysvBiXefX79upBdQVumgYcdd17gCpjQ== + +stylelint-config-recess-order@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/stylelint-config-recess-order/-/stylelint-config-recess-order-4.6.0.tgz#b4c851c490b4e626b14712686b1eab1e4b17e253" + integrity sha512-V76fhv3YtcNXh/hyAuAdSzi5FmcrG54Mp2AThJ3D/PTMTSYzUPd7GIhP6z9mTqnRhmkk6YTfcu/JWB8h+Yrcaw== + dependencies: + stylelint-order "6.x" + +stylelint-config-recommended-scss@^14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz#1a5855655cddcb5f77c10f38c76567adf2bb9aa3" + integrity sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg== + dependencies: + postcss-scss "^4.0.9" + stylelint-config-recommended "^14.0.1" + stylelint-scss "^6.4.0" + +stylelint-config-recommended-vue@^1.5.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/stylelint-config-recommended-vue/-/stylelint-config-recommended-vue-1.6.1.tgz#6a93082ce4a5c1f64793b789175a833c57ce8309" + integrity sha512-lLW7hTIMBiTfjenGuDq2kyHA6fBWd/+Df7MO4/AWOxiFeXP9clbpKgg27kHfwA3H7UNMGC7aeP3mNlZB5LMmEQ== + dependencies: + semver "^7.3.5" + stylelint-config-html ">=1.0.0" + stylelint-config-recommended ">=6.0.0" + +stylelint-config-recommended@>=6.0.0: + version "17.0.0" + resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-17.0.0.tgz#4f77c70609b2d7093cc60bb48adfabdde434aa5d" + integrity sha512-WaMSdEiPfZTSFVoYmJbxorJfA610O0tlYuU2aEwY33UQhSPgFbClrVJYWvy3jGJx+XW37O+LyNLiZOEXhKhJmA== + +stylelint-config-recommended@^14.0.1: + version "14.0.1" + resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz#d25e86409aaf79ee6c6085c2c14b33c7e23c90c6" + integrity sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg== + +stylelint-config-standard@^36.0.1: + version "36.0.1" + resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-36.0.1.tgz#727cbb2a1ef3e210f5ce8329cde531129f156609" + integrity sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw== + dependencies: + stylelint-config-recommended "^14.0.1" + +stylelint-order@6.x: + version "6.0.4" + resolved "https://registry.yarnpkg.com/stylelint-order/-/stylelint-order-6.0.4.tgz#3e80d876c61a98d2640de181433686f24284748b" + integrity sha512-0UuKo4+s1hgQ/uAxlYU4h0o0HS4NiQDud0NAUNI0aa8FJdmYHA5ZZTFHiV5FpmE3071e9pZx5j0QpVJW5zOCUA== + dependencies: + postcss "^8.4.32" + postcss-sorting "^8.0.2" + +stylelint-scss@^6.4.0: + version "6.14.0" + resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-6.14.0.tgz#b3f69e6e6236807aef021caf995fdf00255d80f0" + integrity sha512-ZKmHMZolxeuYsnB+PCYrTpFce0/QWX9i9gh0hPXzp73WjuIMqUpzdQaBCrKoLWh6XtCFSaNDErkMPqdjy1/8aA== + dependencies: + css-tree "^3.0.1" + is-plain-object "^5.0.0" + known-css-properties "^0.37.0" + mdn-data "^2.25.0" + postcss-media-query-parser "^0.2.3" + postcss-resolve-nested-selector "^0.1.6" + postcss-selector-parser "^7.1.1" + postcss-value-parser "^4.2.0" + +stylelint@^16.20.0: + version "16.26.1" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.26.1.tgz#7048accf9c3990dc074dff13c6f3cdc35c780c95" + integrity sha512-v20V59/crfc8sVTAtge0mdafI3AdnzQ2KsWe6v523L4OA1bJO02S7MO2oyXDCS6iWb9ckIPnqAFVItqSBQr7jw== + dependencies: + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-syntax-patches-for-csstree" "^1.0.19" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/media-query-list-parser" "^4.0.3" + "@csstools/selector-specificity" "^5.0.0" + "@dual-bundle/import-meta-resolve" "^4.2.1" + balanced-match "^2.0.0" + colord "^2.9.3" + cosmiconfig "^9.0.0" + css-functions-list "^3.2.3" + css-tree "^3.1.0" + debug "^4.4.3" + fast-glob "^3.3.3" + fastest-levenshtein "^1.0.16" + file-entry-cache "^11.1.1" + global-modules "^2.0.0" + globby "^11.1.0" + globjoin "^0.1.4" + html-tags "^3.3.1" + ignore "^7.0.5" + imurmurhash "^0.1.4" + is-plain-object "^5.0.0" + known-css-properties "^0.37.0" + mathml-tag-names "^2.1.3" + meow "^13.2.0" + micromatch "^4.0.8" + normalize-path "^3.0.0" + picocolors "^1.1.1" + postcss "^8.5.6" + postcss-resolve-nested-selector "^0.1.6" + postcss-safe-parser "^7.0.1" + postcss-selector-parser "^7.1.0" + postcss-value-parser "^4.2.0" + resolve-from "^5.0.0" + string-width "^4.2.3" + supports-hyperlinks "^3.2.0" + svg-tags "^1.0.0" + table "^6.9.0" + write-file-atomic "^5.0.1" + +superjson@^2.2.2: + version "2.2.6" + resolved "https://registry.yarnpkg.com/superjson/-/superjson-2.2.6.tgz#a223a3a988172a5f9656e2063fe5f733af40d099" + integrity sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA== + dependencies: + copy-anything "^4" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-hyperlinks@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz#b8e485b179681dea496a1e7abdf8985bd3145461" + integrity sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +svg-tags@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" + integrity sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA== + +synckit@^0.11.7: + version "0.11.11" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.11.tgz#c0b619cf258a97faa209155d9cd1699b5c998cb0" + integrity sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw== + dependencies: + "@pkgr/core" "^0.2.9" + +table@^6.9.0: + version "6.9.0" + resolved "https://registry.yarnpkg.com/table/-/table-6.9.0.tgz#50040afa6264141c7566b3b81d4d82c47a8668f5" + integrity sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +tailwindcss@4.1.18, tailwindcss@^4.1.14: + version "4.1.18" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-4.1.18.tgz#f488ba47853abdb5354daf9679d3e7791fc4f4e3" + integrity sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw== + +tapable@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.0.tgz#7e3ea6d5ca31ba8e078b560f0d83ce9a14aa8be6" + integrity sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg== + +terser@^5.36.0: + version "5.44.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.44.1.tgz#e391e92175c299b8c284ad6ded609e37303b0a9c" + integrity sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.15.0" + commander "^2.20.0" + source-map-support "~0.5.20" + +tiny-warning@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + +tinyglobby@^0.2.15: + version "0.2.15" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2" + integrity sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.3" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +totalist@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" + integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== + +ts-api-utils@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.4.0.tgz#2690579f96d2790253bdcf1ca35d569ad78f9ad8" + integrity sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA== + +tslib@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" + integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== + +tslib@^2.4.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tsx@^4.20.3: + version "4.21.0" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.21.0.tgz#32aa6cf17481e336f756195e6fe04dae3e6308b1" + integrity sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw== + dependencies: + esbuild "~0.27.0" + get-tsconfig "^4.7.5" + optionalDependencies: + fsevents "~2.3.3" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type@^2.7.2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.3.tgz#436981652129285cc3ba94f392886c2637ea0486" + integrity sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ== + +typescript-eslint@^8.9.0: + version "8.52.0" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.52.0.tgz#b8c156b6f2b4dee202a85712ff6a37f614476413" + integrity sha512-atlQQJ2YkO4pfTVQmQ+wvYQwexPDOIgo+RaVcD7gHgzy/IQA+XTyuxNM9M9TVXvttkF7koBHmcwisKdOAf2EcA== + dependencies: + "@typescript-eslint/eslint-plugin" "8.52.0" + "@typescript-eslint/parser" "8.52.0" + "@typescript-eslint/typescript-estree" "8.52.0" + "@typescript-eslint/utils" "8.52.0" + +typescript@~5.6.3: + version "5.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" + integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== + +ufo@^1.6.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.6.2.tgz#aaf4d46b98425b2fb5031abe8d65ca069e93e755" + integrity sha512-heMioaxBcG9+Znsda5Q8sQbWnLJSl98AFDXTO80wELWEzX3hordXsTdxrIfMQoO9IY1MEnoGoPjpoKpMj+Yx0Q== + +undici-types@~7.16.0: + version "7.16.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" + integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== + +unicorn-magic@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.3.0.tgz#4efd45c85a69e0dd576d25532fbfa22aa5c8a104" + integrity sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA== + +unimport@^5.5.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/unimport/-/unimport-5.6.0.tgz#22cd39a0eb74b76c5e64ed6bec27ca4fd4b086e3" + integrity sha512-8rqAmtJV8o60x46kBAJKtHpJDJWkA2xcBqWKPI14MgUb05o1pnpnCnXSxedUXyeq7p8fR5g3pTo2BaswZ9lD9A== + dependencies: + acorn "^8.15.0" + escape-string-regexp "^5.0.0" + estree-walker "^3.0.3" + local-pkg "^1.1.2" + magic-string "^0.30.21" + mlly "^1.8.0" + pathe "^2.0.3" + picomatch "^4.0.3" + pkg-types "^2.3.0" + scule "^1.3.0" + strip-literal "^3.1.0" + tinyglobby "^0.2.15" + unplugin "^2.3.11" + unplugin-utils "^0.3.1" + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +unplugin-auto-import@^20.2.0: + version "20.3.0" + resolved "https://registry.yarnpkg.com/unplugin-auto-import/-/unplugin-auto-import-20.3.0.tgz#a4947cea55b2b06413b28a8477cb120e03b9db32" + integrity sha512-RcSEQiVv7g0mLMMXibYVKk8mpteKxvyffGuDKqZZiFr7Oq3PB1HwgHdK5O7H4AzbhzHoVKG0NnMnsk/1HIVYzQ== + dependencies: + local-pkg "^1.1.2" + magic-string "^0.30.21" + picomatch "^4.0.3" + unimport "^5.5.0" + unplugin "^2.3.11" + unplugin-utils "^0.3.1" + +unplugin-element-plus@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/unplugin-element-plus/-/unplugin-element-plus-0.10.0.tgz#ad6e85a29ac1b5536483c9adae9498b323bd69c9" + integrity sha512-oRSW0x6U58xBOWKy8TcoVZNA8ElIpfp3TUJRLQI6ey/E9PpjHl9/deeTAZNt8D57Li4OA4pCJtM6p2cb4Ff4ZA== + dependencies: + es-module-lexer "^1.6.0" + magic-string "^0.30.17" + unplugin "^2.3.2" + unplugin-utils "^0.2.4" + +unplugin-utils@^0.2.4: + version "0.2.5" + resolved "https://registry.yarnpkg.com/unplugin-utils/-/unplugin-utils-0.2.5.tgz#d2fe44566ffffd7f216579bbb01184f6702e379b" + integrity sha512-gwXJnPRewT4rT7sBi/IvxKTjsms7jX7QIDLOClApuZwR49SXbrB1z2NLUZ+vDHyqCj/n58OzRRqaW+B8OZi8vg== + dependencies: + pathe "^2.0.3" + picomatch "^4.0.3" + +unplugin-utils@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/unplugin-utils/-/unplugin-utils-0.3.1.tgz#ef2873670a6a2a21bd2c9d31307257cc863a709c" + integrity sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog== + dependencies: + pathe "^2.0.3" + picomatch "^4.0.3" + +unplugin-vue-components@^29.1.0: + version "29.2.0" + resolved "https://registry.yarnpkg.com/unplugin-vue-components/-/unplugin-vue-components-29.2.0.tgz#5cf1aace82f6e7481fb068e6d23f33ef1ef849d6" + integrity sha512-QxBeBdmEflgtJRgMQMc/z/JVV5lcwXN5nOy5ehX6CKDGylIu6Qn4Goy8X95S0qOxF7EdI+uNhdBd4v5i0bvzCw== + dependencies: + chokidar "^3.6.0" + debug "^4.4.3" + local-pkg "^1.1.2" + magic-string "^0.30.19" + mlly "^1.8.0" + tinyglobby "^0.2.15" + unplugin "^2.3.10" + unplugin-utils "^0.3.1" + +unplugin@^2.3.10, unplugin@^2.3.11, unplugin@^2.3.2: + version "2.3.11" + resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-2.3.11.tgz#411e020dd2ba90e2fbe1e7bd63a5a399e6ee3b54" + integrity sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww== + dependencies: + "@jridgewell/remapping" "^2.3.5" + acorn "^8.15.0" + picomatch "^4.0.3" + webpack-virtual-modules "^0.6.2" + +update-browserslist-db@^1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" + integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +vite-hot-client@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/vite-hot-client/-/vite-hot-client-2.1.0.tgz#88f8469875e0121eae2f460cbf35cb528c049961" + integrity sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ== + +vite-plugin-compression@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz#a75b0d8f48357ebb377b65016da9f20885ef39b6" + integrity sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg== + dependencies: + chalk "^4.1.2" + debug "^4.3.3" + fs-extra "^10.0.0" + +vite-plugin-inspect@0.8.9: + version "0.8.9" + resolved "https://registry.yarnpkg.com/vite-plugin-inspect/-/vite-plugin-inspect-0.8.9.tgz#01a7e484ccbc12a8c86ee8bc90efe13aeb0fed1b" + integrity sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A== + dependencies: + "@antfu/utils" "^0.7.10" + "@rollup/pluginutils" "^5.1.3" + debug "^4.3.7" + error-stack-parser-es "^0.1.5" + fs-extra "^11.2.0" + open "^10.1.0" + perfect-debounce "^1.0.0" + picocolors "^1.1.1" + sirv "^3.0.0" + +vite-plugin-vue-devtools@^7.7.6: + version "7.7.9" + resolved "https://registry.yarnpkg.com/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.7.9.tgz#1c0623c5cc8cff549681c36c1fc835ec456459e8" + integrity sha512-08DvePf663SxqLFJeMVNW537zzVyakp9KIrI2K7lwgaTqA5R/ydN/N2K8dgZO34tg/Qmw0ch84fOKoBtCEdcGg== + dependencies: + "@vue/devtools-core" "^7.7.9" + "@vue/devtools-kit" "^7.7.9" + "@vue/devtools-shared" "^7.7.9" + execa "^9.5.2" + sirv "^3.0.1" + vite-plugin-inspect "0.8.9" + vite-plugin-vue-inspector "^5.3.1" + +vite-plugin-vue-inspector@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.3.2.tgz#70c8a4e913e5e8126fb8751881692b2a53ddcf54" + integrity sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q== + dependencies: + "@babel/core" "^7.23.0" + "@babel/plugin-proposal-decorators" "^7.23.0" + "@babel/plugin-syntax-import-attributes" "^7.22.5" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-transform-typescript" "^7.22.15" + "@vue/babel-plugin-jsx" "^1.1.5" + "@vue/compiler-dom" "^3.3.4" + kolorist "^1.8.0" + magic-string "^0.30.4" + +vite@^7.1.5: + version "7.3.1" + resolved "https://registry.yarnpkg.com/vite/-/vite-7.3.1.tgz#7f6cfe8fb9074138605e822a75d9d30b814d6507" + integrity sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA== + dependencies: + esbuild "^0.27.0" + fdir "^6.5.0" + picomatch "^4.0.3" + postcss "^8.5.6" + rollup "^4.43.0" + tinyglobby "^0.2.15" + optionalDependencies: + fsevents "~2.3.3" + +vscode-uri@^3.0.8: + version "3.1.0" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.1.0.tgz#dd09ec5a66a38b5c3fffc774015713496d14e09c" + integrity sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ== + +vue-demi@>=0.14.8, vue-demi@^0.14.9: + version "0.14.10" + resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04" + integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg== + +vue-draggable-plus@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/vue-draggable-plus/-/vue-draggable-plus-0.6.0.tgz#e4da6917e94ca73402f34113073f44771691fa5e" + integrity sha512-G5TSfHrt9tX9EjdG49InoFJbt2NYk0h3kgjgKxkFWr3ulIUays0oFObr5KZ8qzD4+QnhtALiRwIqY6qul4egqw== + dependencies: + "@types/sortablejs" "^1.15.8" + +vue-eslint-parser@^9.4.3: + version "9.4.3" + resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz#9b04b22c71401f1e8bca9be7c3e3416a4bde76a8" + integrity sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg== + dependencies: + debug "^4.3.4" + eslint-scope "^7.1.1" + eslint-visitor-keys "^3.3.0" + espree "^9.3.1" + esquery "^1.4.0" + lodash "^4.17.21" + semver "^7.3.6" + +vue-i18n@^9.1.10, vue-i18n@^9.14.0: + version "9.14.5" + resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-9.14.5.tgz#72fbf4384b83a1c59ec9e01ff5d30224bd9150cf" + integrity sha512-0jQ9Em3ymWngyiIkj0+c/k7WgaPO+TNzjKSNq9BvBQaKJECqn9cd9fL4tkDhB5G1QBskGl9YxxbDAhgbFtpe2g== + dependencies: + "@intlify/core-base" "9.14.5" + "@intlify/shared" "9.14.5" + "@vue/devtools-api" "^6.5.0" + +vue-img-cutter@^3.0.5: + version "3.0.7" + resolved "https://registry.yarnpkg.com/vue-img-cutter/-/vue-img-cutter-3.0.7.tgz#ef29c32b866b1693faa7e45e186e6aa0c46f8ef4" + integrity sha512-fNw3kimawg9XVXDZCw2bI74NI+Jq+H42wjymatZVVSY46wuBty6LbQsu4GeVfo/yzpS9AHY0tzckpYzX3D2fmA== + dependencies: + core-js "^3.20.3" + vue "^3.2.29" + vue-i18n "^9.1.10" + +vue-router@^4.5.1: + version "4.6.4" + resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.6.4.tgz#a0a9cb9ef811a106d249e4bb9313d286718020d8" + integrity sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg== + dependencies: + "@vue/devtools-api" "^6.6.4" + +vue-tsc@~2.1.6: + version "2.1.10" + resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-2.1.10.tgz#4d61a64e5fad763b8b40c1884259fd48986f0b4e" + integrity sha512-RBNSfaaRHcN5uqVqJSZh++Gy/YUzryuv9u1aFWhsammDJXNtUiJMNoJ747lZcQ68wUQFx6E73y4FY3D8E7FGMA== + dependencies: + "@volar/typescript" "~2.4.8" + "@vue/language-core" "2.1.10" + semver "^7.5.4" + +vue@^3.2.29, vue@^3.5.21: + version "3.5.26" + resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.26.tgz#03a0b17311e0e593d34b9358fa249b85e3a6d9fb" + integrity sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA== + dependencies: + "@vue/compiler-dom" "3.5.26" + "@vue/compiler-sfc" "3.5.26" + "@vue/runtime-dom" "3.5.26" + "@vue/server-renderer" "3.5.26" + "@vue/shared" "3.5.26" + +webpack-virtual-modules@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz#057faa9065c8acf48f24cb57ac0e77739ab9a7e8" + integrity sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ== + +which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-1.1.2.tgz#a7020453084d8cd2efe70ba9d3696263de1710a5" + integrity sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng== + +wmf@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wmf/-/wmf-1.0.2.tgz#7d19d621071a08c2bdc6b7e688a9c435298cc2da" + integrity sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw== + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +word@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/word/-/word-0.3.0.tgz#8542157e4f8e849f4a363a288992d47612db9961" + integrity sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.2.tgz#956832dea9494306e6d209eb871643bb873d7c98" + integrity sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww== + dependencies: + ansi-styles "^6.2.1" + string-width "^7.0.0" + strip-ansi "^7.1.0" + +write-file-atomic@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" + integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^4.0.1" + +wsl-utils@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/wsl-utils/-/wsl-utils-0.1.0.tgz#8783d4df671d4d50365be2ee4c71917a0557baab" + integrity sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw== + dependencies: + is-wsl "^3.1.0" + +xgplayer-subtitles@3.0.23: + version "3.0.23" + resolved "https://registry.yarnpkg.com/xgplayer-subtitles/-/xgplayer-subtitles-3.0.23.tgz#ce5fb26370735312f4c79ef4e43d24e5b84ded13" + integrity sha512-deGdV75giVzfTTdG9XATmji39NHwKTpEelWt2rRx/RyXGgU2bQFp0Ft7yWaK2Uu8A/WVrP5fpxEAj4MstREMkQ== + dependencies: + eventemitter3 "^4.0.7" + +xgplayer@^3.0.20: + version "3.0.23" + resolved "https://registry.yarnpkg.com/xgplayer/-/xgplayer-3.0.23.tgz#45cdc76ed94b53b649de846700d69c59790a1b39" + integrity sha512-Bn3zQfMMAZimlVG9EeIDybMcklc+6FH8Sv47KpTq4K6ofCzyhPG/KenxailDedlHmxjb5B2o+240TpJtMQ3oJA== + dependencies: + danmu.js ">=1.1.6" + delegate "^3.2.0" + downloadjs "1.4.7" + eventemitter3 "^4.0.7" + xgplayer-subtitles "3.0.23" + +xlsx@^0.18.5: + version "0.18.5" + resolved "https://registry.yarnpkg.com/xlsx/-/xlsx-0.18.5.tgz#16711b9113c848076b8a177022799ad356eba7d0" + integrity sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ== + dependencies: + adler-32 "~1.3.0" + cfb "~1.2.1" + codepage "~1.15.0" + crc-32 "~1.2.1" + ssf "~0.11.2" + wmf "~1.0.1" + word "~0.3.0" + +xml-name-validator@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" + integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yaml@^2.7.0: + version "2.8.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.2.tgz#5694f25eca0ce9c3e7a9d9e00ce0ddabbd9e35c5" + integrity sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.5.1: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +yoctocolors@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yoctocolors/-/yoctocolors-2.1.2.tgz#d795f54d173494e7d8db93150cec0ed7f678c83a" + integrity sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug== + +zrender@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/zrender/-/zrender-6.0.0.tgz#947077bc69cdea744134984927f132f3727f8079" + integrity sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg== + dependencies: + tslib "2.3.0"