commit 690568861b049478dec553e68811cec177eb7153 Author: zhaogd Date: Sun Jul 26 12:54:46 2026 +0800 init: 橘视厅酒店版会员系统前端 diff --git a/.babelrc b/.babelrc new file mode 100755 index 0000000..d3cc83a --- /dev/null +++ b/.babelrc @@ -0,0 +1,19 @@ +{ + "presets": [ + ["env", { + "modules": false + }], + "stage-2" + ], + "plugins": ["transform-runtime", ["component", [ + { + "libraryName": "element-ui" + } + ]]], + "env": { + "test": { + "presets": ["env", "stage-2"], + "plugins": ["transform-es2015-modules-commonjs", "dynamic-import-node"] + } + } +} diff --git a/.cursor/rules/camelcase-identifiers.mdc b/.cursor/rules/camelcase-identifiers.mdc new file mode 100755 index 0000000..dcb6b35 --- /dev/null +++ b/.cursor/rules/camelcase-identifiers.mdc @@ -0,0 +1,27 @@ +--- +description: 使用 AI 编写/修改代码时,标识符命名统一为小驼峰(camelCase)。 +alwaysApply: true +--- + +在本仓库中由 AI 生成或修改的代码须遵守以下命名约定: + +## 小驼峰(camelCase)— 必须使用 + +- **变量**(`let` / `const` / `ref` / `reactive` 字段等) +- **函数**、**方法** +- **普通对象属性**(TypeScript 接口/类型中的字段名、请求体与前端模型字段,优先 camelCase) +- **函数参数**与**回调形参** + +禁止使用蛇形命名(`snake_case`)作为上述标识符,除非下文「例外」另有说明。 + +## 命名例外(不按小驼峰) + +- **类型 / 接口 / 枚举名**:使用 PascalCase(如 `OrgInfo`、`UserStatus`)。 +- **Vue 单文件组件文件名**:PascalCase(如 `OrgAddOrUpdate.vue`)。 +- **常量**:若项目已有约定,可使用全大写下划线(如 `MAX_RETRY`);新建常量优先与现有文件保持一致。 +- **与外部协议强绑定且无法改名的字段**:仅在访问边界做映射,内部仍用 camelCase 变量承接(例如 `const userId = raw.user_id` 再避免把 `user_id` 传满业务层)。 + +## AI 行为要求 + +- 新增代码默认全部小驼峰;不要为「对齐后端蛇形」而在业务层引入蛇形变量名。 +- 与现有文件风格冲突时,以**当前文件**已有风格为准,但新增标识符仍优先 camelCase。 diff --git a/.cursor/rules/git.mdc b/.cursor/rules/git.mdc new file mode 100755 index 0000000..e617bf6 --- /dev/null +++ b/.cursor/rules/git.mdc @@ -0,0 +1,17 @@ +--- +alwaysApply: true +--- + +--- +description: 自动生成或编写 Git commit 消息时使用的规范。 +alwaysApply: true +--- + +当生成 Git commit 消息时(包括点击 Git 面板的“小火花”图标自动生成),请严格遵守以下规则: +1. **语言**:必须使用简体中文编写。 +2. **格式**:使用 Conventional Commits 规范 (例如: `feat:`, `fix:`, `docs:`, `style:`, `refactor:`, `chore:`)。 +3. **内容**:描述应简洁明了,准确反映代码变更。 +4. **示例**: + - `feat: 添加用户登录功能` + - `fix: 修复诗词列表加载失败的问题` + - `docs: 更新项目说明文档` diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 0000000..9d08a1a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.env b/.env new file mode 100755 index 0000000..0dc36f0 --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ +# 所有环境通用(可被 .env.development / .env.production 覆盖) +# 开发服务器端口(可选) +# VITE_DEV_PORT=3000 diff --git a/.env.development b/.env.development new file mode 100755 index 0000000..77d9b51 --- /dev/null +++ b/.env.development @@ -0,0 +1,5 @@ +# 开发环境:baseApi 固定为 /api,所有接口走 Vite 代理(避免跨域) +VITE_APP_PROXY_TARGET=http://127.0.0.1:8083 +# manage 后端(/manage/ 前缀接口)—— 云端测试 +VITE_MANAGE_PROXY_TARGET=http://58.220.83.58:8084 +# VITE_DEV_PORT=3000 diff --git a/.env.production b/.env.production new file mode 100755 index 0000000..48500d1 --- /dev/null +++ b/.env.production @@ -0,0 +1,5 @@ +# 生产环境(打包时使用) +# baseApi 固定为 /api,请求会发往同源再由 nginx 转发 +VITE_APP_PROXY_TARGET=http://jst.ainetv.cn +# manage 后端(生产环境由 nginx 同源转发,此处仅占位) +VITE_MANAGE_PROXY_TARGET=http://jst.ainetv.cn \ No newline at end of file diff --git a/.env.test b/.env.test new file mode 100755 index 0000000..eecb999 --- /dev/null +++ b/.env.test @@ -0,0 +1,11 @@ +# =========================================== +# 环境变量示例(复制为 .env 或 .env.local 后按需修改) +# 仅以 VITE_ 开头的变量会注入到前端代码(import.meta.env / @/config/env) +# =========================================== + +# 开发时代理目标(VITE_APP_PROXY_TARGET),baseApi 固定为 /api +# VITE_APP_PROXY_TARGET=http://localhost:8080 + +# 开发服务器端口(可选,默认 3000) +# VITE_DEV_PORT=3000 +VITE_APP_PROXY_TARGET=http://172.16.100.134:8083 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..3607af8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +.DS_Store +node_modules/ +dist/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +/test/unit/coverage/ +/test/e2e/reports/ +selenium-debug.log + +# 生产环境本地配置(可覆盖 .env.production,不提交) +.env.production.local + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln + +# Skills +**/skills/ +**/*SKILL* +skills-lock.json + +.codegraph + +# 本地敏感文档(含数据库密码等,勿提交) +项目进展总结.md + +# 构建产物压缩包 +dist.zip +*.zip diff --git a/README.md b/README.md new file mode 100755 index 0000000..c63caa1 --- /dev/null +++ b/README.md @@ -0,0 +1,70 @@ +# 爱视(aishi)管理后台前端 + +基于 **Vue 3**、**Vite**、**Element Plus** 的后台管理界面,与后端通过 **HTTP API** 对接。开发环境下请求统一走 Vite 代理,避免浏览器跨域问题。 + +## 技术栈 + +| 类别 | 技术 | +|------|------| +| 框架 | Vue 3(Composition API、`script setup`) | +| 构建 | Vite 8、TypeScript、`vue-tsc` | +| UI | Element Plus、SCSS、UnoCSS | +| 路由与状态 | Vue Router 5、Pinia | +| HTTP | Axios、`qs` | +| 其他 | Lodash、xlsx(导入导出)、部分图标与区域数据组件 | + +## 环境要求 + +建议使用 **Node.js** 当前 LTS 版本;包管理统一使用 **[pnpm](https://pnpm.io/)**(安装:`npm install -g pnpm` 或见官网)。 + +## 快速开始 + +```bash +# 安装依赖 +pnpm install + +# 本地开发(默认读取 .env.development) +pnpm dev +``` + +## pnpm 脚本 + +| 命令 | 说明 | +|------|------| +| `pnpm dev` | 启动开发服务器(Vite) | +| `pnpm build` | 类型检查(`vue-tsc`)后生产构建 | +| `pnpm build:dev` | 以 `development` 模式构建 | +| `pnpm build:test` | 以 `test` 模式构建 | +| `pnpm preview` | 本地预览构建产物 | +| `pnpm typecheck` | 仅执行 TypeScript / 模板类型检查 | + +## 环境变量 + +前缀均为 `VITE_`,在 `vite.config.js` 中通过 `loadEnv` 加载。常见配置: + +| 变量 | 说明 | +|------|------| +| `VITE_APP_PROXY_TARGET` | 开发代理目标地址(后端服务 origin),如 `http://127.0.0.1:8083` | +| `VITE_DEV_PORT` | 开发服务器端口,未设置时默认 **3000** | + +各环境的示例或覆盖见项目根目录 `.env`、`.env.development`、`.env.production`、`.env.test`。**不要将含密钥的 `.env` 文件提交到版本库。** + +### 代理说明 + +开发模式下,`/api` 会代理到 `VITE_APP_PROXY_TARGET`,并将路径前缀 `/api` 重写为后端的实际前缀(见 `vite.config.js`)。接口客户端里的 `baseApi` 需与此约定一致。 + +## 目录结构(简要) + +``` +src/ +├── api/ # 接口封装 +├── assets/ # 静态资源 +├── components/ # 全局组件 +├── layout/ # 布局与框架页 +├── router/ # 路由 +├── stores/ # Pinia +├── utils/ # 工具函数 +└── views/ # 业务页面(按模块划分,如 modules/sys、modules/device) +``` + +路径别名:`@` → `src`,`@assets` → `src/assets`(见 `vite.config.js`)。 \ No newline at end of file diff --git a/auto-imports.d.ts b/auto-imports.d.ts new file mode 100755 index 0000000..9d24007 --- /dev/null +++ b/auto-imports.d.ts @@ -0,0 +1,10 @@ +/* eslint-disable */ +/* prettier-ignore */ +// @ts-nocheck +// noinspection JSUnusedGlobalSymbols +// Generated by unplugin-auto-import +// biome-ignore lint: disable +export {} +declare global { + +} diff --git a/components.d.ts b/components.d.ts new file mode 100755 index 0000000..63173f2 --- /dev/null +++ b/components.d.ts @@ -0,0 +1,79 @@ +/* eslint-disable */ +// @ts-nocheck +// biome-ignore lint: disable +// oxlint-disable +// ------ +// Generated by unplugin-vue-components +// Read more: https://github.com/vuejs/core/pull/3399 + +export {} + +/* prettier-ignore */ +declare module 'vue' { + export interface GlobalComponents { + AgentStoreSelect: typeof import('./src/components/agent-store-select/index.vue')['default'] + CardFlowFromToOrgSelect: typeof import('./src/components/card-flow-from-to-org-select/index.vue')['default'] + ChannelAgentTreeSelect: typeof import('./src/components/channel-agent-tree-select/index.vue')['default'] + ChannelSelect: typeof import('./src/components/channel-select/index.vue')['default'] + ElAlert: typeof import('element-plus/es')['ElAlert'] + ElBadge: typeof import('element-plus/es')['ElBadge'] + ElButton: typeof import('element-plus/es')['ElButton'] + ElCard: typeof import('element-plus/es')['ElCard'] + ElCascader: typeof import('element-plus/es')['ElCascader'] + ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] + ElCol: typeof import('element-plus/es')['ElCol'] + ElCollapse: typeof import('element-plus/es')['ElCollapse'] + ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'] + ElCollapseTransition: typeof import('element-plus/es')['ElCollapseTransition'] + ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] + ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] + ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] + ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] + ElDialog: typeof import('element-plus/es')['ElDialog'] + ElDivider: typeof import('element-plus/es')['ElDivider'] + ElDropdown: typeof import('element-plus/es')['ElDropdown'] + ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] + ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] + ElEmpty: typeof import('element-plus/es')['ElEmpty'] + ElForm: typeof import('element-plus/es')['ElForm'] + ElFormItem: typeof import('element-plus/es')['ElFormItem'] + ElIcon: typeof import('element-plus/es')['ElIcon'] + ElImage: typeof import('element-plus/es')['ElImage'] + ElInput: typeof import('element-plus/es')['ElInput'] + ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] + ElLink: typeof import('element-plus/es')['ElLink'] + ElMenu: typeof import('element-plus/es')['ElMenu'] + ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] + ElOption: typeof import('element-plus/es')['ElOption'] + ElOptionGroup: typeof import('element-plus/es')['ElOptionGroup'] + ElPagination: typeof import('element-plus/es')['ElPagination'] + ElPopover: typeof import('element-plus/es')['ElPopover'] + ElRadio: typeof import('element-plus/es')['ElRadio'] + ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] + ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] + ElResult: typeof import('element-plus/es')['ElResult'] + ElRow: typeof import('element-plus/es')['ElRow'] + ElSelect: typeof import('element-plus/es')['ElSelect'] + ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] + ElSwitch: typeof import('element-plus/es')['ElSwitch'] + ElTable: typeof import('element-plus/es')['ElTable'] + ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] + ElTabPane: typeof import('element-plus/es')['ElTabPane'] + ElTabs: typeof import('element-plus/es')['ElTabs'] + ElTag: typeof import('element-plus/es')['ElTag'] + ElTooltip: typeof import('element-plus/es')['ElTooltip'] + ElTree: typeof import('element-plus/es')['ElTree'] + ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] + ElUpload: typeof import('element-plus/es')['ElUpload'] + IconSvg: typeof import('./src/components/icon-svg/index.vue')['default'] + NearExpiryUnusedCardsDialog: typeof import('./src/components/NearExpiryUnusedCardsDialog.vue')['default'] + OrgTreeSelect: typeof import('./src/components/org-tree-select/index.vue')['default'] + RouterLink: typeof import('vue-router')['RouterLink'] + RouterView: typeof import('vue-router')['RouterView'] + StoreSelect: typeof import('./src/components/store-select/index.vue')['default'] + TableTreeColumn: typeof import('./src/components/table-tree-column/index.vue')['default'] + } + export interface GlobalDirectives { + vLoading: typeof import('element-plus/es')['ElLoadingDirective'] + } +} diff --git a/db/add-jetsen-media-menu.sql b/db/add-jetsen-media-menu.sql new file mode 100644 index 0000000..6e37350 --- /dev/null +++ b/db/add-jetsen-media-menu.sql @@ -0,0 +1,20 @@ +-- ============================================================ +-- 橘视厅媒资管理菜单 +-- 目标库:as-daycard-openapi(dev-0418.sys_menu) +-- 路由映射:menu.url='jetsen-media/list' -> src/views/modules/jetsen-media/list.vue +-- 依赖后端接口:GET /sys/jetsen-media/{nav,tags,list,search,export}(as-daycard-openapi) +-- ============================================================ + +-- 新建顶级目录"媒资管理" + 子菜单"橘视厅媒资" +-- 超级管理员(org_id IS NULL) 自动拥有全部 type IN(0,1) 且 show='10' 的菜单,无需配 sys_role_menu。 +INSERT INTO `sys_menu` + (`id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `show`, `order_num`, `created_at`, `updated_at`) +VALUES + (116, 0, '媒资管理', NULL, '', 0, 'Film', '10', 2, NOW(), NOW()), + (117, 116, '橘视厅媒资', 'jetsen-media/list', '', 1, 'Film', '10', 1, NOW(), NOW()); + +-- 非超管角色授权(按需执行): +-- INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (, 116), (, 117); + +-- 回滚: +-- DELETE FROM `sys_menu` WHERE `id` IN (116, 117); diff --git a/db/add-manage-menus.sql b/db/add-manage-menus.sql new file mode 100644 index 0000000..0e21eb1 --- /dev/null +++ b/db/add-manage-menus.sql @@ -0,0 +1,30 @@ +-- ============================================================ +-- 修复:新增 manage 菜单 天卡激活码 / 分润规则 / 分账记录 +-- 目标库:as-daycard-openapi(dev-0418.sys_menu) +-- 路由映射:menu.url -> src/views/modules/${url}.vue +-- ============================================================ + +-- 1) 还原 107/108 名称(避免与新菜单「分润规则/分账记录」重名) +-- 107 原 url=settle-rule -> 名字还原为「结算规则」 +-- 108 原 url=settle-record -> 名字还原为「结算记录」 +UPDATE `sys_menu` SET `name` = '结算规则', `updated_at` = NOW() WHERE `id` = 107; +UPDATE `sys_menu` SET `name` = '结算记录', `updated_at` = NOW() WHERE `id` = 108; + +-- 2) 插入 3 个新菜单(续接现有最大 ID 112,使用 113~115) +INSERT INTO `sys_menu` + (`id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `show`, `order_num`, `created_at`, `updated_at`) +VALUES + (113, 100, '天卡激活码', 'manage/activation-code', '', 1, 'Ticket', '10', 13, NOW(), NOW()), + (114, 100, '分润规则', 'manage/profit-rule', '', 1, 'Coin', '10', 14, NOW(), NOW()), + (115, 100, '分账记录', 'manage/profit-sharing', '', 1, 'Wallet', '10', 15, NOW(), NOW()); + +-- ------------------------------------------------------------ +-- 超级管理员(org_id IS NULL) 自动拥有全部 type IN(0,1) 且 show='10' 的菜单, +-- 无需配 sys_role_menu。非超管角色需显式关联: +-- INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES +-- (, 113), (, 114), (, 115); + +-- 回滚 +-- DELETE FROM `sys_menu` WHERE `id` IN (113, 114, 115); +-- UPDATE `sys_menu` SET `name`='分润规则' WHERE `id`=107; +-- UPDATE `sys_menu` SET `name`='分账记录' WHERE `id`=108; diff --git a/db/add-partner-menus.sql b/db/add-partner-menus.sql new file mode 100644 index 0000000..165032a --- /dev/null +++ b/db/add-partner-menus.sql @@ -0,0 +1,32 @@ +-- ============================================================ +-- 业务管理目录改名 + 第三方接口管理目录新增(合作伙伴/内容包/采购天卡) +-- 目标库:as-daycard-openapi(sys_menu) +-- 路由映射:menu.url -> src/views/modules/${url}.vue +-- ============================================================ + +-- 1) id=100「合作伙伴管理」目录改名为「业务管理」 +UPDATE `sys_menu` SET `name` = '业务管理', `updated_at` = NOW() WHERE `id` = 100; + +-- 2) 新建一级目录「第三方接口管理」(id=121, parent_id=0,与业务管理并行) +INSERT INTO `sys_menu` + (`id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `show`, `order_num`, `created_at`, `updated_at`) +VALUES + (121, 0, '第三方接口管理', NULL, '', 0, 'Setting', '10', 19, NOW(), NOW()); + +-- 3) 3 个子菜单挂到「第三方接口管理」目录下 +INSERT INTO `sys_menu` + (`id`, `parent_id`, `name`, `url`, `perms`, `type`, `icon`, `show`, `order_num`, `created_at`, `updated_at`) +VALUES + (118, 121, '合作伙伴管理', 'manage/partner', '', 1, 'Connection', '10', 1, NOW(), NOW()), + (119, 121, '内容包配置', 'manage/content-package', '', 1, 'Files', '10', 2, NOW(), NOW()), + (120, 121, '采购天卡', 'manage/partner-card', '', 1, 'ShoppingCart', '10', 3, NOW(), NOW()); + +-- ------------------------------------------------------------ +-- 超级管理员(org_id IS NULL) 自动拥有全部 type IN(0,1) 且 show='10' 的菜单, +-- 无需配 sys_role_menu。非超管角色需显式关联: +-- INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES +-- (, 118), (, 119), (, 120), (, 121); + +-- 回滚 +-- DELETE FROM `sys_menu` WHERE `id` IN (118, 119, 120, 121); +-- UPDATE `sys_menu` SET `name`='合作伙伴管理' WHERE `id`=100; diff --git a/db/cleanup-settle-menus.sql b/db/cleanup-settle-menus.sql new file mode 100644 index 0000000..6ede08b --- /dev/null +++ b/db/cleanup-settle-menus.sql @@ -0,0 +1,4 @@ +-- 删除冗余菜单:结算规则(107) 和 结算记录(108) +-- 这两个视图与 分润规则(114)/分账记录(115) 调同一套 API,已删除前端文件 +DELETE FROM `sys_role_menu` WHERE `menu_id` IN (107, 108); +DELETE FROM `sys_menu` WHERE `id` IN (107, 108); diff --git a/index.html b/index.html new file mode 100755 index 0000000..2b35487 --- /dev/null +++ b/index.html @@ -0,0 +1,15 @@ + + + + + + + 橘视厅酒店版会员系统 + + + + +
+ + + diff --git a/package.json b/package.json new file mode 100755 index 0000000..8f09a97 --- /dev/null +++ b/package.json @@ -0,0 +1,56 @@ +{ + "name": "aishi", + "version": "1.2.2", + "type": "module", + "author": "lrq", + "private": true, + "scripts": { + "dev": "vite dev", + "build": "vite build", + "build:dev": "vite build --mode development", + "build:test": "vite build --mode test", + "preview": "vite preview", + "typecheck": "vue-tsc --noEmit" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.3.2", + "axios": "^1.17.0", + "cos-js-sdk-v5": "^1.10.1", + "element-china-area-data": "^6.1.0", + "element-plus": "^2.14.1", + "lodash": "^4.18.1", + "pinia": "^3.0.4", + "qs": "^6.15.2", + "sass": "^1.100.0", + "svg-sprite-loader": "3.7.3", + "tesseract.js": "^7.0.0", + "unocss": "^66.7.0", + "vue": "^3.5.35", + "vue-cookie": "^1.1.4", + "vue-router": "^5.1.0", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "@types/lodash": "^4.17.24", + "@types/node": "^25.9.2", + "@types/qs": "^6.15.1", + "@unocss/vite": "^66.7.0", + "@vitejs/plugin-vue": "^6.0.7", + "@vue/language-plugin-pug": "^3.3.4", + "@vue/language-server": "^3.3.4", + "autoprefixer": "7.1.2", + "typescript": "^6.0.3", + "unplugin-auto-import": "^21.0.0", + "unplugin-vue-components": "^31.1.0", + "vite": "^8.0.16", + "vue-loader": "^13.7.3", + "vue-style-loader": "^3.1.2", + "vue-template-compiler": "^2.7.16", + "vue-tsc": "^3.3.4" + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 8" + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100755 index 0000000..2fc0a30 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,7580 @@ +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.35(typescript@6.0.3)) + axios: + specifier: ^1.17.0 + version: 1.17.0 + cos-js-sdk-v5: + specifier: ^1.10.1 + version: 1.10.1 + element-china-area-data: + specifier: ^6.1.0 + version: 6.1.0 + element-plus: + specifier: ^2.14.1 + version: 2.14.1(vue@3.5.35(typescript@6.0.3)) + lodash: + specifier: ^4.18.1 + version: 4.18.1 + pinia: + specifier: ^3.0.4 + version: 3.0.4(typescript@6.0.3)(vue@3.5.35(typescript@6.0.3)) + qs: + specifier: ^6.15.2 + version: 6.15.2 + sass: + specifier: ^1.100.0 + version: 1.100.0 + svg-sprite-loader: + specifier: 3.7.3 + version: 3.7.3 + tesseract.js: + specifier: ^7.0.0 + version: 7.0.0 + unocss: + specifier: ^66.7.0 + version: 66.7.0(vite@8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0)) + vue: + specifier: ^3.5.35 + version: 3.5.35(typescript@6.0.3) + vue-cookie: + specifier: ^1.1.4 + version: 1.1.4 + vue-router: + specifier: ^5.1.0 + version: 5.1.0(@vue/compiler-sfc@3.5.35)(pinia@3.0.4(typescript@6.0.3)(vue@3.5.35(typescript@6.0.3)))(vite@8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0))(vue@3.5.35(typescript@6.0.3)) + xlsx: + specifier: ^0.18.5 + version: 0.18.5 + devDependencies: + '@types/lodash': + specifier: ^4.17.24 + version: 4.17.24 + '@types/node': + specifier: ^25.9.2 + version: 25.9.2 + '@types/qs': + specifier: ^6.15.1 + version: 6.15.1 + '@unocss/vite': + specifier: ^66.7.0 + version: 66.7.0(vite@8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0)) + '@vitejs/plugin-vue': + specifier: ^6.0.7 + version: 6.0.7(vite@8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0))(vue@3.5.35(typescript@6.0.3)) + '@vue/language-plugin-pug': + specifier: ^3.3.4 + version: 3.3.4 + '@vue/language-server': + specifier: ^3.3.4 + version: 3.3.4(typescript@6.0.3) + autoprefixer: + specifier: 7.1.2 + version: 7.1.2 + typescript: + specifier: ^6.0.3 + version: 6.0.3 + unplugin-auto-import: + specifier: ^21.0.0 + version: 21.0.0(@vueuse/core@14.3.0(vue@3.5.35(typescript@6.0.3))) + unplugin-vue-components: + specifier: ^31.1.0 + version: 31.1.0(vue@3.5.35(typescript@6.0.3)) + vite: + specifier: ^8.0.16 + version: 8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0) + vue-loader: + specifier: ^13.7.3 + version: 13.7.3(@vue/compiler-sfc@3.5.35)(babel-core@6.26.3)(css-loader@0.28.0)(handlebars@4.7.8)(lodash@4.18.1)(vue-template-compiler@2.7.16)(webpack@5.105.4(esbuild@0.27.3)(postcss@5.2.18)) + vue-style-loader: + specifier: ^3.1.2 + version: 3.1.2 + vue-template-compiler: + specifier: ^2.7.16 + version: 2.7.16 + vue-tsc: + specifier: ^3.3.4 + version: 3.3.4(typescript@6.0.3) + +packages: + + '@antfu/install-pkg@1.1.0': + resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} + + '@babel/generator@8.0.0-rc.6': + resolution: {integrity: sha512-6mIzgVK8DgEzvIapoQwhXTMnnkuE4STQmVv9H03i/tZ2ml8oev3TRvZJgTenK2Bsq0YWNtzOrFdTyNzCMFtjJQ==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@8.0.0-rc.6': + resolution: {integrity: sha512-BCkFy+zN6kXQed3YOT7aJl93NfDSzQc3pBfsvTVPs9gU9X3V0aefEF5kwBT0E+mDWH9QgKaZstYUQN9VdQZT4g==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@8.0.0-rc.6': + resolution: {integrity: sha512-nVJ+1JcCgntv8d78rRo++o2wuODT0Irknx2BF8Np4Ft2CRgjLqIs4qzSZ8b66yGbBdMWGmZBO9WEZv1hhNiSpg==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/parser@8.0.0-rc.6': + resolution: {integrity: sha512-rOS8IpdO7mQELkTPlCsTgPejO0bFuZdEDCGQJouYbYf9e1FLTym7Fei2pEjq8q7MWbX0ravcd7QQYKs1TxOuog==} + engines: {node: ^22.18.0 || >=24.11.0} + hasBin: true + + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + engines: {node: '>=6.9.0'} + + '@babel/types@8.0.0-rc.6': + resolution: {integrity: sha512-p7/ABylAYlexb31wtRdIfH9L9A0Z2T/9H6zAqzqndkY2PLkvNNc580wGhp/gGKN4Sp9sQvSkhc6Oga8/O+wTyw==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@ctrl/tinycolor@4.2.0': + resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==} + engines: {node: '>=14'} + + '@element-plus/icons-vue@2.3.2': + resolution: {integrity: sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==} + peerDependencies: + vue: ^3.2.0 + + '@emmetio/abbreviation@2.3.3': + resolution: {integrity: sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==} + + '@emmetio/css-abbreviation@2.1.8': + resolution: {integrity: sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==} + + '@emmetio/css-parser@0.4.1': + resolution: {integrity: sha512-2bC6m0MV/voF4CTZiAbG5MWKbq5EBmDPKu9Sb7s7nVcEzNQlrZP6mFFFlIaISM8X6514H9shWMme1fCm8cWAfQ==} + + '@emmetio/html-matcher@1.3.0': + resolution: {integrity: sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ==} + + '@emmetio/scanner@1.0.4': + resolution: {integrity: sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==} + + '@emmetio/stream-reader-utils@0.1.0': + resolution: {integrity: sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A==} + + '@emmetio/stream-reader@2.2.0': + resolution: {integrity: sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==} + + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + + '@esbuild/aix-ppc64@0.27.3': + resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.3': + resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.3': + resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.3': + resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.3': + resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.3': + resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.3': + resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.3': + resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.3': + resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.3': + resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.3': + resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.3': + resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.3': + resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.3': + resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.3': + resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.3': + resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.3': + resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.3': + resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.3': + resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.3': + resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.3': + resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.3': + resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.3': + resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.3': + resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.3': + resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.3': + resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@floating-ui/core@1.7.5': + resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} + + '@floating-ui/dom@1.7.6': + resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==} + + '@floating-ui/utils@0.2.11': + resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} + + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/utils@3.1.3': + resolution: {integrity: sha512-LPKOXPn/zV+zis1oOfGWogaXVpqUybF3ZS6SCZIsz8vg0ivVp9+fVqyYB7xq0aiST/VhUQYGO1qo6uoYSiEJqw==} + + '@johnsoncodehk/pug-beautify@0.2.2': + resolution: {integrity: sha512-qqNS/YD0Nck5wtQLCPHAfGVgWbbGafxSPjNh0ekYPFSNNqnDH2kamnduzYly8IiADmeVx/MfAE1njMEjVeHTMA==} + + '@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==} + + '@napi-rs/wasm-runtime@1.1.5': + resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@oxc-parser/binding-android-arm-eabi@0.131.0': + resolution: {integrity: sha512-t2xicr9pfzkSRYx5aPqZqlLaayIwJTqgQ81Jor31Xep2nGyL2Aq3d0K5wOfeR7VevaSdxaS9dzSQP9xDwn8fDg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxc-parser/binding-android-arm64@0.131.0': + resolution: {integrity: sha512-nlGIod6gw75x1aEDgLS+srj+JRGY0HHm9MI9YgzE/B64l6d6+H3MSP9NOgp0+HTg8tp4vV9rVfgQGgd+TfVZcA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxc-parser/binding-darwin-arm64@0.131.0': + resolution: {integrity: sha512-jukuV6xe5RbQKFo7QD34NDCLDZp4PSOm8rmckhNdH/60ymG5zXbDzGBEyc+nTkuLQNama2aSGCt+CPfpjNTqyw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxc-parser/binding-darwin-x64@0.131.0': + resolution: {integrity: sha512-g3JOo4khe9rslHm5WYaVDWb0HS/M1MLR3I9S8560MkKIcC96VQY00QjOlsuRyfSj/JDXj8i9T7ryPO2RidiXVg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxc-parser/binding-freebsd-x64@0.131.0': + resolution: {integrity: sha512-1hziITDTxjMePnX+dR9ocVT+EuZkQ8wm4FPAbmbEiKG+Phbo73J1ZnPAA6Y/aGsWF3McOFnQuZIktAFwalkfJQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxc-parser/binding-linux-arm-gnueabihf@0.131.0': + resolution: {integrity: sha512-9uRxfXwyKG9+MwmGQBo2ncPNwZH5HTmCETFM2WiuDBNDCW4NC5ttSQkwCAMrTAWgwMzVBH1CP8pM0v7nebCWXQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm-musleabihf@0.131.0': + resolution: {integrity: sha512-mgbLvzRShXOLBdWGInf08Af4q+pfj1xD8hSgLClDZ9of/BXkB6+LIhTH7fihiDUipqB3yoSkKBWaZ3Ejlf5Yag==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm64-gnu@0.131.0': + resolution: {integrity: sha512-OPT8++4aN6j2GJ8+3IZHS/byXoZP4aSBn+FoG6rgBJ2fKwPKXWF3MqrFMNW7NKHM28FLY579xYLxJSfgobEqPA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-arm64-musl@0.131.0': + resolution: {integrity: sha512-vtPiwmfVTAXzaxDKsOXG+LwgRAA7WEnaeHzhS5z0GE89gAK18KSXnly7Z6saXXq6L3dVMyK44uoTI03zKxrpmw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-ppc64-gnu@0.131.0': + resolution: {integrity: sha512-8AW8L7w5cGHSdZPcyZX2yR0+GUODsT15rbRjfdD54rv6DMbtuEB19ysLOpKJlRGfH6UNYNpCHaU1uJWgTWf1/w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-gnu@0.131.0': + resolution: {integrity: sha512-vvpjkjEOUsPcsYf8evE4MO3aGx9+3wodXEBOicGNnOwTuAik8eBONNkgSdhkGsAblQmfVHJyanRnpxglddTXIA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-musl@0.131.0': + resolution: {integrity: sha512-AqmcNC3fClXX+fxQ6VGEN1667xVFiRBkY0CZmDMSiaeFUsv1+UkBPYYi48IUKcA9/ivvoKNRzQl2I4//kT9F/w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-s390x-gnu@0.131.0': + resolution: {integrity: sha512-7d3jOMKy7RSQCcDLIci+ySll2FgsOMl/GiRux4q2JNv0zg4EdhFISa9idvrdN/HEUIQQJNg6dmveUeJl2YErGA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-gnu@0.131.0': + resolution: {integrity: sha512-JHK/h95qVqVQ+ITER837kcTdwBDFpFaNnOTYGCP0zdUSX/mLKC7tXOoyrTb6vG7iRPwGlcgBil3v2IjYw1FqJA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-musl@0.131.0': + resolution: {integrity: sha512-b2BO82O8azXAyf7EUgOPKu145nWypbNyk07HbU09fkzhm9lEA5oPvaN/M8Nlo7tOErVTa2WOgS4QbOnxAPXdDQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-openharmony-arm64@0.131.0': + resolution: {integrity: sha512-GHO9glZaX7LkX/OGfluEPf1yjg+ehiFbUdowbX6uNWOQhmwKWU4m4+nZ9FJkrHNKuxyI1KKertMdGjVKCApKWA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxc-parser/binding-wasm32-wasi@0.131.0': + resolution: {integrity: sha512-3SkikPaEFoih1N83qLVEDLRLeY4nYsf6JT9SnWiMCQ5lGQdKup6bEuKCqkRiG9dD1IIaFeYz9RjlciPmYoFIWA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@oxc-parser/binding-win32-arm64-msvc@0.131.0': + resolution: {integrity: sha512-Os5bEhryeA2jkH+ZrnZyAC1EP5gs+X4YB1Fjqml7UPD5kU7ecsK1MPEVMfCrdt/GDNpDbavYXiOXOdyJ5b3OPw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxc-parser/binding-win32-ia32-msvc@0.131.0': + resolution: {integrity: sha512-m+jNz9EuF0NXoiptc6B9h5yompZQVW/a5MJeOu5zojfH5yWk82tvF2ccrHkfhgtrS9h9DD5l1Qv8dWlfY7Nz8g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxc-parser/binding-win32-x64-msvc@0.131.0': + resolution: {integrity: sha512-o14Hk8dAyiEUMFEWEgmAwFZvBt1RzAYLM3xeQ+5315JXgVYhoemivgYcbYVRbsFkS71ShMGlAFE0kPnr460rww==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@oxc-project/types@0.131.0': + resolution: {integrity: sha512-PgnWDfV0h+b16XNKbXU7Daib/BFSt/J2mEzfYIBu6JB/wNdlU+kVYXCkGA1A9fWkTbOgbjh4e6NhPeQOYvFhEA==} + + '@oxc-project/types@0.133.0': + resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + + '@parcel/watcher-android-arm64@2.5.6': + resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.5.6': + resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.5.6': + resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.5.6': + resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.5.6': + resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm-musl@2.5.6': + resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-arm64-glibc@2.5.6': + resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm64-musl@2.5.6': + resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-x64-glibc@2.5.6': + resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-x64-musl@2.5.6': + resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@parcel/watcher-win32-arm64@2.5.6': + resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.5.6': + resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.5.6': + resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.5.6': + resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==} + engines: {node: '>= 10.0.0'} + + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + + '@quansync/fs@1.0.0': + resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} + + '@rolldown/binding-android-arm64@1.0.3': + resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.3': + resolution: {integrity: sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.3': + resolution: {integrity: sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.3': + resolution: {integrity: sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + resolution: {integrity: sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.3': + resolution: {integrity: sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.0.3': + resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.0.3': + resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.0.3': + resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.0.3': + resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.0.3': + resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.3': + resolution: {integrity: sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.3': + resolution: {integrity: sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.3': + resolution: {integrity: sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@sxzz/popperjs-es@2.11.8': + resolution: {integrity: sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==} + + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} + + '@types/eslint-scope@3.7.7': + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/jsesc@2.5.1': + resolution: {integrity: sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==} + + '@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.24': + resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} + + '@types/node@25.9.2': + resolution: {integrity: sha512-G05zqtJhcDLb8uslf5EjCxXg9G1KQxiV8OS0R26IC//Eoyitzqe8z37I7cqvnZlrlSfgocQRfSn/AHBZJJFyGw==} + + '@types/qs@6.15.1': + resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==} + + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + + '@unocss/cli@66.7.0': + resolution: {integrity: sha512-Pkd/R+WDs8gc1i9fI5XDW8N5r7aoCWjNzt8wGGj5FWTbmsEzewueaL5LQTH4ymv/BhSHFcYpL7geQ5vYont+BA==} + hasBin: true + + '@unocss/config@66.7.0': + resolution: {integrity: sha512-C6waL+xzqAPzz5n47qnrs4GbyAtlusNYYmcV6DKYh1MgUP4EFhMnEMyuR2mw3M3tsBpyGuehLdRK5+ECF5yLkA==} + + '@unocss/core@66.7.0': + resolution: {integrity: sha512-j6MFMx5C3iIwW4T4hVbh+30fKWgSGkmS3bCcdjlfqM88lRT+dHFBN9nkfNOBJT6e6IHN9415nexuzcQvTjJXxw==} + + '@unocss/extractor-arbitrary-variants@66.7.0': + resolution: {integrity: sha512-iHMlXmb8aGtYgPQ8o3D4rMz9DKOqSp8g/LWvEoiM7arSjJF9jMpcpYlqZXzkg1mSQX23TRW76Qxj1gyI4lRd9w==} + + '@unocss/inspector@66.7.0': + resolution: {integrity: sha512-W1MOO2d/1ZHwFR8+mrUUW6KW3MgJ6FdrSWfWeQ1+fgb0TVj8CweNzeSh46sTEXEcpvlui5mnGYFxanpLMoyOtA==} + + '@unocss/preset-attributify@66.7.0': + resolution: {integrity: sha512-n8ikthHHkAOeHWUwqRNIMGijV6LuIhiZb3D6kreV3oK98wJYupGNGYMByx7R9gQD9uBNLGs0f1jsaAScV3S2Sw==} + + '@unocss/preset-icons@66.7.0': + resolution: {integrity: sha512-y6I2qZ2cwNAS2XRBig1lHzdFG9qTnZM/mx3fL3XnURnEYZird4uidLyWOyUGcdy1kMot1QcYVb0D/s9NgrEOgQ==} + + '@unocss/preset-mini@66.7.0': + resolution: {integrity: sha512-+YtRlr1Fjd24GYWhPB93r6fjefTBCnFUsZCASncSEU29u2Mi8MYINjefLfKlSJFMKg6AKzWbelKMCQfoKlUkbg==} + + '@unocss/preset-tagify@66.7.0': + resolution: {integrity: sha512-MaM07ChHsX8XZM3tlMPuRsZxbNvRVTbmIncOj9cCCrFpeOu8hy2ggRAgGOalWIwnIHc+5KQIkqucbgmXN7KBdA==} + + '@unocss/preset-typography@66.7.0': + resolution: {integrity: sha512-Ekdz7jw/TYTiH+QFqMWcWNMnvBnUZ/XPUF938C8DfqD79hZyLdRPo0kQaZh62cit13xNRAb49QP3HIUJIUxoGA==} + + '@unocss/preset-uno@66.7.0': + resolution: {integrity: sha512-fcLTj5Wax3QydCSdJq9yQHhqKph6Mx9exwNnkaBCXtmBvrSBd2O6O9ZAylcISnACeXJkjSverU8qVu1X2tITdA==} + + '@unocss/preset-web-fonts@66.7.0': + resolution: {integrity: sha512-jpNLjo/2X/J2J+G/M9W+y6VuiIhjZ9AyOnyNJHsdhmSJYCsnMuaYtP9eFn4d9+oe3Sz2lVNPV0A9RiqQ+xVAyQ==} + + '@unocss/preset-wind3@66.7.0': + resolution: {integrity: sha512-1xxHBV4TtUHXPpYnWH8J2UHhxaMF84fTvadVzRRaXkyVrXD86Hveh/lfbXHXnCyf0JxwqsleOq8CnCTT8AgoAg==} + + '@unocss/preset-wind4@66.7.0': + resolution: {integrity: sha512-5o3y2BcImLbkxa0fNtwaH8iB47FrOKzT7Xogni5PIDOX/DsoHfDLNiNBRrHHHHBeZ3jqvjv2T9T5kEkD5/WtYQ==} + + '@unocss/preset-wind@66.7.0': + resolution: {integrity: sha512-K2cCgQawl4GzFyI9almN4jZ33OJNI6U7WxZ9s7D5bivZYfHPaStLTPffNxWlmawwUZF0qpH0S+S7H745ZzgajQ==} + + '@unocss/rule-utils@66.7.0': + resolution: {integrity: sha512-DMJIiey/m+xr0hpSbxFhSbKlC3e7QsuwdAEdgMmIM7pEcu/AEMl7oH198QYX9880P2X0hy5iFE6UCWx9CwGAXQ==} + + '@unocss/transformer-attributify-jsx@66.7.0': + resolution: {integrity: sha512-mmsAUluRprSyejbzeQnC3ST056EUj2IxD2hMpPJPtnA4QkkyIgBNCmi2OSeVcEWMat1s3r4LcYSTqN88EcX5Kg==} + + '@unocss/transformer-compile-class@66.7.0': + resolution: {integrity: sha512-Z3K/s3TmUqUBGgB2SThWbUAP5E9VIFacbs2+bNJNn+53y1kqdLA1MIje3xlU5hig3OzGk8newwiMflh3s3Jzhg==} + + '@unocss/transformer-directives@66.7.0': + resolution: {integrity: sha512-6T9JxrPfLQlJFNLv7paG4yGiIgGrJY30268HWLkBFwgsldNPtQ+GeQJOzfemCH19UXXqqXMP0WnvbsFucdclmg==} + + '@unocss/transformer-variant-group@66.7.0': + resolution: {integrity: sha512-2TXYLowPMXszGNYRXAWzQ1G9nGP6EYv9XeJvwNvnf0w9J6qOQVVtW/ZViIz61Kk083c06cZ6nai8pCBnc8aPAw==} + + '@unocss/vite@66.7.0': + resolution: {integrity: sha512-7J8Mk9M1j55S3bXL87/yHOspnuAaftQWbc3HjCH0/sXNLZJZnlpmUue3EtT5Ez+PE01T3DK1D9Xxn/MvtdvXtA==} + peerDependencies: + vite: ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 || ^8.0.0-0 + + '@vitejs/plugin-vue@6.0.7': + resolution: {integrity: sha512-km+p+XdSz9Sxm5rqUbqcSfZYaAniKxWBj1KURl+Jr7UaPvvX7BmaWMdP69I5rrFDeQGyxAG7NXdc57vz+snhWg==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + vue: ^3.2.25 + + '@volar/language-core@2.4.28': + resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} + + '@volar/language-server@2.4.28': + resolution: {integrity: sha512-NqcLnE5gERKuS4PUFwlhMxf6vqYo7hXtbMFbViXcbVkbZ905AIVWhnSo0ZNBC2V127H1/2zP7RvVOVnyITFfBw==} + + '@volar/language-service@2.4.28': + resolution: {integrity: sha512-Rh/wYCZJrI5vCwMk9xyw/Z+MsWxlJY1rmMZPsxUoJKfzIRjS/NF1NmnuEcrMbEVGja00aVpCsInJfixQTMdvLw==} + + '@volar/source-map@2.4.28': + resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==} + + '@volar/typescript@2.4.28': + resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==} + + '@vscode/emmet-helper@2.11.0': + resolution: {integrity: sha512-QLxjQR3imPZPQltfbWRnHU6JecWTF1QSWhx3GAKQpslx7y3Dp6sIIXhKjiUJ/BR9FX8PVthjr9PD6pNwOJfAzw==} + + '@vscode/l10n@0.0.18': + resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==} + + '@vue-macros/common@3.1.2': + resolution: {integrity: sha512-h9t4ArDdniO9ekYHAD95t9AZcAbb19lEGK+26iAjUODOIJKmObDNBSe4+6ELQAA3vtYiFPPBtHh7+cQCKi3Dng==} + engines: {node: '>=20.19.0'} + peerDependencies: + vue: ^2.7.0 || ^3.2.25 + peerDependenciesMeta: + vue: + optional: true + + '@vue/compiler-core@3.5.35': + resolution: {integrity: sha512-BUmHaR1J+O+CKZ9uJucdVTEr1LHsdyvv7vG3eNRhK3CczEHeMd/LtsHAuD7PbrxvI2envCY2v7HI1vC1aBRzKw==} + + '@vue/compiler-dom@3.5.35': + resolution: {integrity: sha512-k+bprkXxuqhVajgTx5mUHuir7TwQzUKOWR40ng1ncAqQRPnrLngGGgqVEEhOnTMlc8btHYVKmrP8s5Qyg0hvYA==} + + '@vue/compiler-sfc@3.5.35': + resolution: {integrity: sha512-G5VPMcXTSywXBgtFOZOnHKBxKSrwXUcvY1iaF5/hRcy7t0J6CH/d8ha9F4nzi00Fax1eLV0QHM7v4mQu68jydw==} + + '@vue/compiler-ssr@3.5.35': + resolution: {integrity: sha512-rGhAeXgdM7/ffTJGXT69rCCdTmjDewnFuUZfBQQHTdcEBeWdT5HCGY60y2ytLJr9/Dsu7IntUi5z/w0h6Rjnzw==} + + '@vue/devtools-api@7.7.9': + resolution: {integrity: sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==} + + '@vue/devtools-api@8.1.2': + resolution: {integrity: sha512-vA0O112YqyDuNA1s7Yb2gCgToQ/OxOWiFDO5ThLCcDy0ldHnSd1dUTaSYhOldbqoNgumE4dxtGAoAaSUKUD1Zg==} + + '@vue/devtools-kit@7.7.9': + resolution: {integrity: sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==} + + '@vue/devtools-kit@8.1.2': + resolution: {integrity: sha512-f75/upc+GCyjXErpgPGz4582ujS0L/adAltGy+tqXMGUJpgAcfGr6CxnnhpZY8BHuMYt6KpbF8uaFrrQG66rGQ==} + + '@vue/devtools-shared@7.7.9': + resolution: {integrity: sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==} + + '@vue/devtools-shared@8.1.2': + resolution: {integrity: sha512-X9RyVFYAdkBe4IUf5v48TxBF/6QPmF8CmWrDAjXzfUHrgQ/HGfTC1A6TqgXqZ03ye66l3AD51BAGD69IvKM9sw==} + + '@vue/language-core@3.3.4': + resolution: {integrity: sha512-IuHqQ5zGGOE7CXP72VX6A42IVeIzYv4WAhO6arej11TRNqtdZfGyH8Yr2FOCaDX0dSQG+JwULLoFHGY1igYVjQ==} + + '@vue/language-plugin-pug@3.2.9': + resolution: {integrity: sha512-EaRtg3/1TQo9D20nBex1G3NtWElJbSgiiisZe6TwiNKpSCRwFmmvuAkz+AfMmsQc53si3zbkApU8RF0o6ULQag==} + + '@vue/language-plugin-pug@3.3.4': + resolution: {integrity: sha512-hbp1NakJCUYz/XItrnCwLkcvuJf38CvUJ4pv2CKLlVYaZKUhra/uv0PlVdNkdVTQS3loAHGg9GvmbCXzmJhg6g==} + + '@vue/language-server@3.3.4': + resolution: {integrity: sha512-yNlIAbYFLipUgMsHcH2q0EfUc3qKEBEeD5bErFc1ecgJiFHvbnBROlqY+yK7AhGWCq4R/4s3dhfEf6lFTMjIJw==} + hasBin: true + peerDependencies: + typescript: '*' + + '@vue/language-service@3.3.4': + resolution: {integrity: sha512-BOeap3uVCkPCirHz/MTe6gbEHUQQkyChYV8C3lkW6sXb6/gm8rAA3gnKwc1j2B4QOEWWsdnh36nEaigPWKskfQ==} + + '@vue/reactivity@3.5.35': + resolution: {integrity: sha512-tVc+SsHConvh/Lz64qq1pP3rYArBmK42xonovEcxY74SQtvctZodG/zhq54P5dr38cVuw25d27cPNRdlMidpGQ==} + + '@vue/runtime-core@3.5.35': + resolution: {integrity: sha512-A/xFNX9loIcWDygeQuNCfKuh0CoYBzxhqEMNah5TSFg9Z53DrFYEN2qi5CU9necjM1OWYegYREUTHmXTmhfXtg==} + + '@vue/runtime-dom@3.5.35': + resolution: {integrity: sha512-odrJ1C391dbGnyDRh8U+rnP7J2amIEzfmRk5vXy7xi3aZhEXofTvpi0T4HJb6jlNqQZTNPR5MPHSB3RHNkIORA==} + + '@vue/server-renderer@3.5.35': + resolution: {integrity: sha512-NkebSOYdB97wi8OQcO3HqzZSlymJi/aWsN/7h74OSVhRTm6qGs3Jp3e0rCXynmWwSlKeRrnlIug+ilYoHBmQDA==} + peerDependencies: + vue: 3.5.35 + + '@vue/shared@3.5.35': + resolution: {integrity: sha512-zSbjL7gRXwks2ZQLRGCajBtBXEOXW9Ddhn/HvSdrGkE2dqGnumzW8XtusRrxrE9LvqtiqDXQ+A60Hp6mvdYxfA==} + + '@vue/typescript-plugin@3.3.4': + resolution: {integrity: sha512-/JD46EO1/nUZuTsoC2x1SD6ELrp3PW4sknjrvBJWX1uggEQAjJ7NR3IK3V7kfS6oky6Np9w1kYi4oFpdLA0zbQ==} + + '@vueuse/core@14.3.0': + resolution: {integrity: sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==} + peerDependencies: + vue: ^3.5.0 + + '@vueuse/metadata@14.3.0': + resolution: {integrity: sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==} + + '@vueuse/shared@14.3.0': + resolution: {integrity: sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==} + peerDependencies: + vue: ^3.5.0 + + '@webassemblyjs/ast@1.14.1': + resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} + + '@webassemblyjs/floating-point-hex-parser@1.13.2': + resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} + + '@webassemblyjs/helper-api-error@1.13.2': + resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} + + '@webassemblyjs/helper-buffer@1.14.1': + resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} + + '@webassemblyjs/helper-numbers@1.13.2': + resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': + resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} + + '@webassemblyjs/helper-wasm-section@1.14.1': + resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} + + '@webassemblyjs/ieee754@1.13.2': + resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} + + '@webassemblyjs/leb128@1.13.2': + resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} + + '@webassemblyjs/utf8@1.13.2': + resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} + + '@webassemblyjs/wasm-edit@1.14.1': + resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} + + '@webassemblyjs/wasm-gen@1.14.1': + resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} + + '@webassemblyjs/wasm-opt@1.14.1': + resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} + + '@webassemblyjs/wasm-parser@1.14.1': + resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} + + '@webassemblyjs/wast-printer@1.14.1': + resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} + + '@xtuc/ieee754@1.2.0': + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + + '@xtuc/long@4.2.2': + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + + acorn-import-phases@1.0.4: + resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} + engines: {node: '>=10.13.0'} + peerDependencies: + acorn: ^8.14.0 + + acorn@7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + adler-32@1.3.1: + resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==} + engines: {node: '>=0.8'} + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-keywords@5.1.0: + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + alien-signals@3.2.1: + resolution: {integrity: sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==} + + alphanum-sort@1.0.2: + resolution: {integrity: sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ==} + + ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + + ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + arr-diff@4.0.0: + resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} + engines: {node: '>=0.10.0'} + + arr-flatten@1.1.0: + resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} + engines: {node: '>=0.10.0'} + + arr-union@3.1.0: + resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} + engines: {node: '>=0.10.0'} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-unique@0.3.2: + resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} + engines: {node: '>=0.10.0'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + assign-symbols@1.0.0: + resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} + engines: {node: '>=0.10.0'} + + ast-kit@2.2.0: + resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==} + engines: {node: '>=20.19.0'} + + ast-walker-scope@0.9.0: + resolution: {integrity: sha512-IJdzo2vLiElBxKzwS36VsCue/62d6IdWjnPB2v3nuPKeWGynp6FF/CYoLa5i/3jXH/z97ZDdsXz6abpgM6w07A==} + engines: {node: '>=20.19.0'} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + + autoprefixer@6.7.7: + resolution: {integrity: sha512-WKExI/eSGgGAkWAO+wMVdFObZV7hQen54UpD1kCCTN3tvlL3W1jL4+lPP/M7MwoP7Q4RHzKtO3JQ4HxYEcd+xQ==} + + autoprefixer@7.1.2: + resolution: {integrity: sha512-PoN1+x0sy4ocZLq29AKZFrnpxNqJNlpYWHP12twS+MxM+BHl5kgE6MgU5qWdJIEKAE1cW8+iSfOSwThiN5P1WA==} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axios@1.17.0: + resolution: {integrity: sha512-J8SwNxprqqpbfenehxWYXE7CW+wM1BB4w3+N+g+/Wx40xM4rsLrfPmHHxSWIxJLYDgSY/HqlFPIYb2/S3rxafw==} + + babel-code-frame@6.26.0: + resolution: {integrity: sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==} + + babel-core@6.26.3: + resolution: {integrity: sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==} + + babel-generator@6.26.1: + resolution: {integrity: sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==} + + babel-helpers@6.24.1: + resolution: {integrity: sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ==} + + babel-messages@6.23.0: + resolution: {integrity: sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==} + + babel-register@6.26.0: + resolution: {integrity: sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A==} + + babel-runtime@6.26.0: + resolution: {integrity: sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==} + + babel-template@6.26.0: + resolution: {integrity: sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==} + + babel-traverse@6.26.0: + resolution: {integrity: sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==} + + babel-types@6.26.0: + resolution: {integrity: sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==} + + babylon@6.18.0: + resolution: {integrity: sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==} + hasBin: true + + balanced-match@0.4.2: + resolution: {integrity: sha512-STw03mQKnGUYtoNjmowo4F2cRmIIxYEGiMsjjwla/u5P1lxadj/05WkNaFjNiKTgJkj8KiXbgAiRTmcQRwQNtg==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base@0.11.2: + resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} + engines: {node: '>=0.10.0'} + + baseline-browser-mapping@2.10.35: + resolution: {integrity: sha512-honAfLBde0HAFLdNyBEfuuENkF6zR+ozxqxa/2zJKHBe1qzLqyTSeRKpdPEHAP03rlDGyQOPnCSxnVpVqQo9Mg==} + engines: {node: '>=6.0.0'} + hasBin: true + + big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + + birpc@2.9.0: + resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==} + + bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + + bmp-js@0.1.0: + resolution: {integrity: sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==} + + brace-expansion@1.1.15: + resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==} + + braces@2.3.2: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + + browserslist@1.7.7: + resolution: {integrity: sha512-qHJblDE2bXVRYzuDetv/wAeHOJyO97+9wxC1cdCtyzgNuSozOyRCiiLaCR1f71AN66lQdVVBipWm63V+a7bPOw==} + deprecated: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools. + hasBin: true + + browserslist@2.11.3: + resolution: {integrity: sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==} + deprecated: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools. + hasBin: true + + browserslist@4.28.2: + resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} + 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==} + + cac@7.0.0: + resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==} + engines: {node: '>=20.19.0'} + + cache-base@1.0.1: + resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} + engines: {node: '>=0.10.0'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + caniuse-api@1.6.1: + resolution: {integrity: sha512-SBTl70K0PkDUIebbkXrxWqZlHNs0wRgRD6QZ8guctShjbh63gEPfF+Wj0Yw+75f5Y8tSzqAI/NcisYv/cCah2Q==} + + caniuse-db@1.0.30001797: + resolution: {integrity: sha512-wV1BrKS/ZUWGpO22bqFgYx0d51CVR5lgWNdvtF1Aib78DNXVyeIZUG2mMTr9Vuul2Qab/YNs94S3rRmeE9cQ8g==} + + caniuse-lite@1.0.30001797: + resolution: {integrity: sha512-l8xKG+gwAIExZGl9FrF7KUwuOmk6wbEPC9Xoy/RtnWv1XG0Q4LFlagaLpUv3Kiza3W/wm27zy0yWJEieYKAP6w==} + + cfb@1.2.2: + resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==} + engines: {node: '>=0.8'} + + chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + character-parser@2.2.0: + resolution: {integrity: sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==} + + china-division@2.7.0: + resolution: {integrity: sha512-4uUPAT+1WfqDh5jytq7omdCmHNk3j+k76zEG/2IqaGcYB90c2SwcixttcypdsZ3T/9tN1TTpBDoeZn+Yw/qBEA==} + + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} + engines: {node: '>=6.0'} + + clap@1.2.3: + resolution: {integrity: sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==} + engines: {node: '>=0.10.0'} + + class-utils@0.3.6: + resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} + engines: {node: '>=0.10.0'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + clone@2.1.2: + resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} + engines: {node: '>=0.8'} + + coa@1.0.4: + resolution: {integrity: sha512-KAGck/eNAmCL0dcT3BiuYwLbExK6lduR8DxM3C1TyDzaXhZHyZ8ooX5I5+na2e3dPFuibfxrGdorr0/Lr7RYCQ==} + engines: {node: '>= 0.8.0'} + + codepage@1.15.0: + resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==} + engines: {node: '>=0.8'} + + collection-visit@1.0.0: + resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} + engines: {node: '>=0.10.0'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@0.3.0: + resolution: {integrity: sha512-sz29j1bmSDfoAxKIEU6zwoIZXN6BrFbAMIhfYCNyiZXBDuU/aiHlN84lp/xDzL2ubyFhLDobHIlU1X70XRrMDA==} + + color@0.11.4: + resolution: {integrity: sha512-Ajpjd8asqZ6EdxQeqGzU5WBhhTfJ/0cA4Wlbre7e5vXfmDSmda7Ov6jeKoru+b0vHcb1CqvuroTHp5zIWzhVMA==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + colormin@1.1.2: + resolution: {integrity: sha512-XSEQUUQUR/lXqGyddiNH3XYFUPYlYr1vXy9rTFMsSOw+J7Q6EQkdlQIrTlYn4TccpsOaUE1PYQNjBn20gwCdgQ==} + + colors@1.1.2: + resolution: {integrity: sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==} + engines: {node: '>=0.1.90'} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + confbox@0.2.4: + resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + + consolidate@0.14.5: + resolution: {integrity: sha512-PZFskfj64QnpKVK9cPdY36pyWEhZNM+srRVqtwMiVTlnViSoZcvX35PpBhhUcyLTHXYvz7pZRmxvsqwzJqg9kA==} + deprecated: Please upgrade to consolidate v1.0.0+ as it has been modernized with several long-awaited fixes implemented. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/consolidate for updates and release changelog + peerDependencies: + arc-templates: ^0.5.3 + atpl: '>=0.7.6' + babel-core: ^6.26.3 + bracket-template: ^1.1.5 + coffee-script: ^1.12.7 + dot: ^1.1.3 + dust: ^0.3.0 + dustjs-helpers: ^1.7.4 + dustjs-linkedin: ^2.7.5 + eco: ^1.1.0-rc-3 + ect: ^0.5.9 + ejs: ^3.1.5 + haml-coffee: ^1.14.1 + hamlet: ^0.3.3 + hamljs: ^0.6.2 + handlebars: ^4.7.6 + hogan.js: ^3.0.2 + htmling: ^0.0.8 + jade: ^1.11.0 + jazz: ^0.0.18 + jqtpl: ~1.1.0 + just: ^0.1.8 + liquid-node: ^3.0.1 + liquor: ^0.0.5 + lodash: ^4.17.20 + marko: ^3.14.4 + mote: ^0.2.0 + mustache: ^3.0.0 + nunjucks: ^3.2.2 + plates: ~0.4.11 + pug: ^3.0.0 + qejs: ^3.0.5 + ractive: ^1.3.12 + razor-tmpl: ^1.3.1 + react: ^16.13.1 + react-dom: ^16.13.1 + slm: ^2.0.0 + squirrelly: ^5.1.0 + swig: ^1.4.2 + swig-templates: ^2.0.3 + teacup: ^2.0.0 + templayed: '>=0.2.3' + then-jade: '*' + then-pug: '*' + tinyliquid: ^0.2.34 + toffee: ^0.3.6 + twig: ^1.15.2 + twing: ^5.0.2 + underscore: ^1.11.0 + vash: ^0.13.0 + velocityjs: ^2.0.1 + walrus: ^0.10.1 + whiskers: ^0.4.0 + peerDependenciesMeta: + arc-templates: + optional: true + atpl: + optional: true + babel-core: + optional: true + bracket-template: + optional: true + coffee-script: + optional: true + dot: + optional: true + dust: + optional: true + dustjs-helpers: + optional: true + dustjs-linkedin: + optional: true + eco: + optional: true + ect: + optional: true + ejs: + optional: true + haml-coffee: + optional: true + hamlet: + optional: true + hamljs: + optional: true + handlebars: + optional: true + hogan.js: + optional: true + htmling: + optional: true + jade: + optional: true + jazz: + optional: true + jqtpl: + optional: true + just: + optional: true + liquid-node: + optional: true + liquor: + optional: true + lodash: + optional: true + marko: + optional: true + mote: + optional: true + mustache: + optional: true + nunjucks: + optional: true + plates: + optional: true + pug: + optional: true + qejs: + optional: true + ractive: + optional: true + razor-tmpl: + optional: true + react: + optional: true + react-dom: + optional: true + slm: + optional: true + squirrelly: + optional: true + swig: + optional: true + swig-templates: + optional: true + teacup: + optional: true + templayed: + optional: true + then-jade: + optional: true + then-pug: + optional: true + tinyliquid: + optional: true + toffee: + optional: true + twig: + optional: true + twing: + optional: true + underscore: + optional: true + vash: + optional: true + velocityjs: + optional: true + walrus: + optional: true + whiskers: + optional: true + + convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + + copy-anything@4.0.5: + resolution: {integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==} + engines: {node: '>=18'} + + copy-descriptor@0.1.1: + resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} + engines: {node: '>=0.10.0'} + + core-js@2.6.12: + resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==} + deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. + + cos-js-sdk-v5@1.10.1: + resolution: {integrity: sha512-a4SRfCY5g6Z35C7OWe9te/S1zk77rVQzfpvZ33gmTdJQzKxbNbEG7Aw/v453XwVMsQB352FIf7KRMm5Ya/wlZQ==} + + cosmiconfig@2.2.2: + resolution: {integrity: sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==} + engines: {node: '>=0.12'} + + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + css-color-names@0.0.4: + resolution: {integrity: sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q==} + + css-loader@0.28.0: + resolution: {integrity: sha512-mMr5h1el+Oqw+OtZgWNzADQU8OzoJXSDeH0Rkjno4gpfVLVfkQHe1vqi9+fgbM9Uv/NaviFR+Qx61mWtw7tYkg==} + engines: {node: '>=0.12.0 || >=4.3.0 <5.0.0 || >=5.10'} + + css-selector-tokenizer@0.7.3: + resolution: {integrity: sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==} + + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + 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 + + cssnano@3.10.0: + resolution: {integrity: sha512-0o0IMQE0Ezo4b41Yrm8U6Rp9/Ag81vNXY1gZMnT1XhO4DpjEf2utKERqWJbOoz3g1Wdc1d3QSta/cIuJ1wSTEg==} + + csso@2.3.2: + resolution: {integrity: sha512-FmCI/hmqDeHHLaIQckMhMZneS84yzUZdrWDAvJVVxOwcKE1P1LF9FGmzr1ktIQSxOw6fl3PaQsmfg+GN+VvR3w==} + engines: {node: '>=0.10.0'} + hasBin: true + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + dayjs@1.11.21: + resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} + + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + + deepmerge@1.3.2: + resolution: {integrity: sha512-qjMjTrk+RKv/sp4RPDpV5CnKhxjFI9p+GkLBOls5A8EEElldYWCWA9zceAkmfd0xIo2aU1nxiaLFoiya2sb6Cg==} + engines: {node: '>=0.10.0'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + define-property@0.2.5: + resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} + engines: {node: '>=0.10.0'} + + define-property@1.0.0: + resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} + engines: {node: '>=0.10.0'} + + define-property@2.0.2: + resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} + engines: {node: '>=0.10.0'} + + defined@1.0.1: + resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==} + + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + destr@2.0.5: + resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + + detect-indent@4.0.0: + resolution: {integrity: sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A==} + engines: {node: '>=0.10.0'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + dom-serializer@0.2.2: + resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==} + + domelementtype@1.3.1: + resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@2.4.2: + resolution: {integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==} + + domready@1.0.8: + resolution: {integrity: sha512-uIzsOJUNk+AdGE9a6VDeessoMCzF8RrZvJCX/W8QtyfgdR6Uofn/MvRonih3OtCO79b2VDzDOymuiABrQ4z3XA==} + + domutils@1.7.0: + resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + + electron-to-chromium@1.5.371: + resolution: {integrity: sha512-e9htk9mAYL6AzmkEhSvVVw7IWGSBJ/Bqdn2eRyRLrj1g6sncN4WbFt5qnILYoCktktr45pyjIrOiRvBThQ808w==} + + element-china-area-data@6.1.0: + resolution: {integrity: sha512-IkpcjwQv2A/2AxFiSoaISZ+oMw1rZCPUSOg5sOCwT5jKc96TaawmKZeY81xfxXsO0QbKxU5LLc6AirhG52hUmg==} + + element-plus@2.14.1: + resolution: {integrity: sha512-UFnm1+BckNi+azkKJ7L32q1uXs9ekr99Z9pWTQPeDR05jqEWUwQq51ro4kZMVrANbjknX3Z7ukCZwTi2T6Tr9A==} + peerDependencies: + vue: ^3.3.7 + + emmet@2.4.11: + resolution: {integrity: sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==} + + emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + + enhanced-resolve@5.23.0: + resolution: {integrity: sha512-yJN/BOOLxcOW2aQgeif9mSnaUB8KtvmMMp56oA1kx1CRfBKbhZm2pJ+NBY+3eOboHxix8lfjWpHE0Ei5U8RbSA==} + engines: {node: '>=10.13.0'} + + entities@1.1.2: + resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + es-abstract@1.24.2: + resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==} + engines: {node: '>= 0.4'} + + 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@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} + + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + esbuild@0.27.3: + resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + + esprima@2.7.3: + resolution: {integrity: sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==} + engines: {node: '>=0.10.0'} + hasBin: true + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + 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'} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + expand-brackets@2.1.4: + resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} + engines: {node: '>=0.10.0'} + + exsolve@1.0.8: + resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} + + extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + + extend-shallow@3.0.2: + resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} + engines: {node: '>=0.10.0'} + + extglob@2.0.4: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} + + fast-xml-parser@4.5.0: + resolution: {integrity: sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==} + hasBin: true + + fastparse@1.1.2: + resolution: {integrity: sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fill-range@4.0.0: + resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} + engines: {node: '>=0.10.0'} + + flatten@1.0.3: + resolution: {integrity: sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==} + deprecated: flatten is deprecated in favor of utility frameworks such as lodash. + + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + for-in@1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + frac@1.1.2: + resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==} + engines: {node: '>=0.8'} + + fragment-cache@0.2.1: + resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} + engines: {node: '>=0.10.0'} + + 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==} + + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + + 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-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + get-value@2.0.6: + resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} + engines: {node: '>=0.10.0'} + + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + + globals@9.18.0: + resolution: {integrity: sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==} + engines: {node: '>=0.10.0'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + 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==} + + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + + handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@1.0.0: + resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} + engines: {node: '>=0.10.0'} + + 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-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + 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'} + + has-value@0.3.1: + resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} + engines: {node: '>=0.10.0'} + + has-value@1.0.0: + resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} + engines: {node: '>=0.10.0'} + + has-values@0.1.4: + resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} + engines: {node: '>=0.10.0'} + + has-values@1.0.0: + resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} + engines: {node: '>=0.10.0'} + + has@1.0.4: + resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} + engines: {node: '>= 0.4.0'} + + hash-sum@1.0.2: + resolution: {integrity: sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + home-or-tmp@2.0.0: + resolution: {integrity: sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg==} + engines: {node: '>=0.10.0'} + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + html-comment-regex@1.1.2: + resolution: {integrity: sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==} + + htmlparser2@3.10.1: + resolution: {integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + icss-replace-symbols@1.1.0: + resolution: {integrity: sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==} + + idb-keyval@6.2.5: + resolution: {integrity: sha512-eKQkTnS0relYsSOYomx8ozIbmdsQCKUdhyuIaQ2DZgKuaxtyQQMkyD/wlnQN32pO3yutN1b1L8uqwcDKaJd7/Q==} + + image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + + immutable@5.1.6: + resolution: {integrity: sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==} + + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + + indexes-of@1.0.1: + resolution: {integrity: sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + invariant@2.2.4: + resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + + is-absolute-url@2.1.0: + resolution: {integrity: sha512-vOx7VprsKyllwjSkLV79NIhpyLfr3jAp7VaTCMXOJHu4m0Ew1CZ2fcjASwmV1jI3BWuWHB013M48eyeldk9gYg==} + engines: {node: '>=0.10.0'} + + is-accessor-descriptor@1.0.2: + resolution: {integrity: sha512-AIbwAcazqP3R65dGvqk1V+a+vE5Fg1yu/ZKMOiBWSUIXXiwQkYmXQcVa2O0nh0tSDKDFKxG2mY7dB1Sr4hEP1g==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.2: + resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} + engines: {node: '>= 0.4'} + + is-data-descriptor@1.0.1: + resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-descriptor@0.1.8: + resolution: {integrity: sha512-SceYGWXvdqlWa/OnQ5FQuV+NxvNmMRhMw/w9AHkH71hTzveND4BTYgvp16g+oITK47qbOl/3D0bl0iygehWAWQ==} + engines: {node: '>= 0.4'} + + is-descriptor@1.0.4: + resolution: {integrity: sha512-bv5z95W0dDtLfKwDfkTNxaRxmISBD3eQBKJeVxv2AQ7MjuUnDNG7cIQqvFtMOUYhsILWHhMayWdoGqNqYYYjww==} + engines: {node: '>= 0.4'} + + is-directory@0.3.1: + resolution: {integrity: sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==} + engines: {node: '>=0.10.0'} + + is-expression@4.0.0: + resolution: {integrity: sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==} + + is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + + is-extendable@1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-finite@1.1.0: + resolution: {integrity: sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==} + engines: {node: '>=0.10.0'} + + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} + engines: {node: '>=0.10.0'} + + is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + + is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-svg@2.1.0: + resolution: {integrity: sha512-Ya1giYJUkcL/94quj0+XGcmts6cETPBW1MiFz1ReJrnDJ680F52qpAEGAEGU0nq96FRGIGPx6Yo1CyPXcOoyGw==} + engines: {node: '>=0.10.0'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-url@1.2.4: + resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + is-what@5.5.0: + resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==} + engines: {node: '>=18'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isobject@2.1.0: + resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} + engines: {node: '>=0.10.0'} + + isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + + jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + + js-base64@2.6.4: + resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} + + js-tokens@3.0.2: + resolution: {integrity: sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + hasBin: true + + js-yaml@3.7.0: + resolution: {integrity: sha512-eIlkGty7HGmntbV6P/ZlAsoncFLGsNoM27lkTzS+oneY/EiNhj+geqD9ezg/ip+SW6Var0BJU2JtV0vEUZpWVQ==} + hasBin: true + + jsesc@1.3.0: + resolution: {integrity: sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json5@0.5.1: + resolution: {integrity: sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==} + hasBin: true + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonc-parser@2.3.1: + resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==} + + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + + kind-of@3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + + kind-of@4.0.0: + resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} + engines: {node: '>=0.10.0'} + + kind-of@5.1.0: + resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} + engines: {node: '>=0.10.0'} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + loader-runner@4.3.2: + resolution: {integrity: sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==} + engines: {node: '>=6.11.5'} + + loader-utils@1.4.2: + resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==} + engines: {node: '>=4.0.0'} + + local-pkg@1.2.1: + resolution: {integrity: sha512-++gUqRDEvcnN6Zhqrr+y/CkVEHhlrR96vZn3nZZPYzMcBUyBtTKzB9NadClFIsIVSsu+3i9tfk/erqy9kAmt7Q==} + engines: {node: '>=14'} + + lodash-es@4.18.1: + resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} + + 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.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + + magic-regexp@0.10.0: + resolution: {integrity: sha512-Uly1Bu4lO1hwHUW0CQeSWuRtzCMNO00CmXtS8N6fyvB3B979GOEEeAkiTUDsmbYLAbvpUS/Kt5c4ibosAzVyVg==} + + magic-string-ast@1.0.3: + resolution: {integrity: sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==} + engines: {node: '>=20.19.0'} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + + map-visit@1.0.0: + resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} + engines: {node: '>=0.10.0'} + + math-expression-evaluator@1.4.0: + resolution: {integrity: sha512-4vRUvPyxdO8cWULGTh9dZWL2tZK6LDBvj+OGHBER7poH9Qdt7kXEoj20wiz4lQUbUXQZFjPbe5mVDo9nutizCw==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + + memoize-one@6.0.0: + resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + + merge-options@1.0.1: + resolution: {integrity: sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==} + engines: {node: '>=4'} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + micromatch@3.1.0: + resolution: {integrity: sha512-3StSelAE+hnRvMs8IdVW7Uhk8CVed5tp+kLLGlBP6WiRAXS21GPGu/Nat4WNPXj2Eoc24B02SaeoyozPMfj0/g==} + engines: {node: '>=0.10.0'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + mitt@1.1.2: + resolution: {integrity: sha512-3btxP0O9iGADGWAkteQ8mzDtEspZqu4I32y4GZYCV5BrwtzdcRpF4dQgNdJadCrbBx7Lu6Sq9AVrerMHR0Hkmw==} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + + mixin-deep@1.3.2: + resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} + engines: {node: '>=0.10.0'} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanomatch@1.2.13: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-releases@2.0.47: + resolution: {integrity: sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==} + engines: {node: '>=18'} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + normalize-url@1.9.1: + resolution: {integrity: sha512-A48My/mtCklowHBlI8Fq2jFWK4tX4lJ5E6ytFsSOq1fzpvT0SQSgKhSg7lN5c2uYFOrUAOQp6zhhJnpp1eMloQ==} + engines: {node: '>=4'} + + normalize-wheel-es@1.2.0: + resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==} + + num2fraction@1.2.2: + resolution: {integrity: sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-copy@0.1.0: + resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object-visit@1.0.1: + resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} + engines: {node: '>=0.10.0'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + + obug@2.1.2: + resolution: {integrity: sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg==} + engines: {node: '>=12.20.0'} + + ofetch@1.5.1: + resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} + + opencollective-postinstall@2.0.3: + resolution: {integrity: sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==} + hasBin: true + + os-homedir@1.0.2: + resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} + engines: {node: '>=0.10.0'} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + oxc-parser@0.131.0: + resolution: {integrity: sha512-SJ3/7ZPbgie8dr5Z9BI/M51zZbpXba+hRSG0MDzVwMW5CRQg2fjYE0jHGlLX4eeiibGgC/mzoDFKSDHwVZEHRQ==} + engines: {node: ^20.19.0 || >=22.12.0} + + oxc-walker@0.7.0: + resolution: {integrity: sha512-54B4KUhrzbzc4sKvKwVYm7E2PgeROpGba0/2nlNZMqfDyca+yOor5IMb4WLGBatGDT0nkzYdYuzylg7n3YfB7A==} + peerDependencies: + oxc-parser: '>=0.98.0' + + package-manager-detector@1.6.0: + resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} + + parse-json@2.2.0: + resolution: {integrity: sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==} + engines: {node: '>=0.10.0'} + + pascalcase@0.1.1: + resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} + engines: {node: '>=0.10.0'} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + + perfect-debounce@2.1.0: + resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + + pinia@3.0.4: + resolution: {integrity: sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==} + peerDependencies: + typescript: '>=4.5.0' + vue: ^3.5.11 + peerDependenciesMeta: + typescript: + optional: true + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + pkg-types@2.3.1: + resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==} + + posix-character-classes@0.1.1: + resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} + engines: {node: '>=0.10.0'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss-calc@5.3.1: + resolution: {integrity: sha512-iBcptYFq+QUh9gzP7ta2btw50o40s4uLI4UDVgd5yRAZtUDWc5APdl5yQDd2h/TyiZNbJrv0HiYhT102CMgN7Q==} + + postcss-colormin@2.2.2: + resolution: {integrity: sha512-XXitQe+jNNPf+vxvQXIQ1+pvdQKWKgkx8zlJNltcMEmLma1ypDRDQwlLt+6cP26fBreihNhZxohh1rcgCH2W5w==} + + postcss-convert-values@2.6.1: + resolution: {integrity: sha512-SE7mf25D3ORUEXpu3WUqQqy0nCbMuM5BEny+ULE/FXdS/0UMA58OdzwvzuHJRpIFlk1uojt16JhaEogtP6W2oA==} + + postcss-discard-comments@2.0.4: + resolution: {integrity: sha512-yGbyBDo5FxsImE90LD8C87vgnNlweQkODMkUZlDVM/CBgLr9C5RasLGJxxh9GjVOBeG8NcCMatoqI1pXg8JNXg==} + + postcss-discard-duplicates@2.1.0: + resolution: {integrity: sha512-+lk5W1uqO8qIUTET+UETgj9GWykLC3LOldr7EehmymV0Wu36kyoHimC4cILrAAYpHQ+fr4ypKcWcVNaGzm0reA==} + + postcss-discard-empty@2.1.0: + resolution: {integrity: sha512-IBFoyrwk52dhF+5z/ZAbzq5Jy7Wq0aLUsOn69JNS+7YeuyHaNzJwBIYE0QlUH/p5d3L+OON72Fsexyb7OK/3og==} + + postcss-discard-overridden@0.1.1: + resolution: {integrity: sha512-IyKoDL8QNObOiUc6eBw8kMxBHCfxUaERYTUe2QF8k7j/xiirayDzzkmlR6lMQjrAM1p1DDRTvWrS7Aa8lp6/uA==} + + postcss-discard-unused@2.2.3: + resolution: {integrity: sha512-nCbFNfqYAbKCw9J6PSJubpN9asnrwVLkRDFc4KCwyUEdOtM5XDE/eTW3OpqHrYY1L4fZxgan7LLRAAYYBzwzrg==} + + postcss-filter-plugins@2.0.3: + resolution: {integrity: sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==} + + postcss-load-config@1.2.0: + resolution: {integrity: sha512-3fpCfnXo9Qd/O/q/XL4cJUhRsqjVD2V1Vhy3wOEcLE5kz0TGtdDXJSoiTdH4e847KphbEac4+EZSH4qLRYIgLw==} + engines: {node: '>=0.12'} + + postcss-load-options@1.2.0: + resolution: {integrity: sha512-WKS5LJMZLWGwtfhs5ahb2ycpoYF3m0kK4QEaM+elr5EpiMt0H296P/9ETa13WXzjPwB0DDTBiUBBWSHoApQIJg==} + engines: {node: '>=0.12'} + + postcss-load-plugins@2.3.0: + resolution: {integrity: sha512-/WGUMYhKiryWjYO6c7kAcqMuD7DVkaQ8HcbQenDme/d3OBOmrYMFObOKgUWyUy1uih5U2Dakq8H6VcJi5C9wHQ==} + engines: {node: '>=0.12'} + + postcss-merge-idents@2.1.7: + resolution: {integrity: sha512-9DHmfCZ7/hNHhIKnNkz4CU0ejtGen5BbTRJc13Z2uHfCedeCUsK2WEQoAJRBL+phs68iWK6Qf8Jze71anuysWA==} + + postcss-merge-longhand@2.0.2: + resolution: {integrity: sha512-ma7YvxjdLQdifnc1HFsW/AW6fVfubGyR+X4bE3FOSdBVMY9bZjKVdklHT+odknKBB7FSCfKIHC3yHK7RUAqRPg==} + + postcss-merge-rules@2.1.2: + resolution: {integrity: sha512-Wgg2FS6W3AYBl+5L9poL6ZUISi5YzL+sDCJfM7zNw/Q1qsyVQXXZ2cbVui6mu2cYJpt1hOKCGj1xA4mq/obz/Q==} + + postcss-message-helpers@2.0.0: + resolution: {integrity: sha512-tPLZzVAiIJp46TBbpXtrUAKqedXSyW5xDEo1sikrfEfnTs+49SBZR/xDdqCiJvSSbtr615xDsaMF3RrxS2jZlA==} + + postcss-minify-font-values@1.0.5: + resolution: {integrity: sha512-vFSPzrJhNe6/8McOLU13XIsERohBJiIFFuC1PolgajOZdRWqRgKITP/A4Z/n4GQhEmtbxmO9NDw3QLaFfE1dFQ==} + + postcss-minify-gradients@1.0.5: + resolution: {integrity: sha512-DZhT0OE+RbVqVyGsTIKx84rU/5cury1jmwPa19bViqYPQu499ZU831yMzzsyC8EhiZVd73+h5Z9xb/DdaBpw7Q==} + + postcss-minify-params@1.2.2: + resolution: {integrity: sha512-hhJdMVgP8vasrHbkKAk+ab28vEmPYgyuDzRl31V3BEB3QOR3L5TTIVEWLDNnZZ3+fiTi9d6Ker8GM8S1h8p2Ow==} + + postcss-minify-selectors@2.1.1: + resolution: {integrity: sha512-e13vxPBSo3ZaPne43KVgM+UETkx3Bs4/Qvm6yXI9HQpQp4nyb7HZ0gKpkF+Wn2x+/dbQ+swNpCdZSbMOT7+TIA==} + + postcss-modules-extract-imports@1.2.1: + resolution: {integrity: sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==} + + postcss-modules-local-by-default@1.2.0: + resolution: {integrity: sha512-X4cquUPIaAd86raVrBwO8fwRfkIdbwFu7CTfEOjiZQHVQwlHRSkTgH5NLDmMm5+1hQO8u6dZ+TOOJDbay1hYpA==} + + postcss-modules-scope@1.1.0: + resolution: {integrity: sha512-LTYwnA4C1He1BKZXIx1CYiHixdSe9LWYVKadq9lK5aCCMkoOkFyZ7aigt+srfjlRplJY3gIol6KUNefdMQJdlw==} + + postcss-modules-values@1.3.0: + resolution: {integrity: sha512-i7IFaR9hlQ6/0UgFuqM6YWaCfA1Ej8WMg8A5DggnH1UGKJvTV/ugqq/KaULixzzOi3T/tF6ClBXcHGCzdd5unA==} + + postcss-normalize-charset@1.1.1: + resolution: {integrity: sha512-RKgjEks83l8w4yEhztOwNZ+nLSrJ+NvPNhpS+mVDzoaiRHZQVoG7NF2TP5qjwnaN9YswUhj6m1E0S0Z+WDCgEQ==} + + postcss-normalize-url@3.0.8: + resolution: {integrity: sha512-WqtWG6GV2nELsQEFES0RzfL2ebVwmGl/M8VmMbshKto/UClBo+mznX8Zi4/hkThdqx7ijwv+O8HWPdpK7nH/Ig==} + + postcss-ordered-values@2.2.3: + resolution: {integrity: sha512-5RB1IUZhkxDCfa5fx/ogp/A82mtq+r7USqS+7zt0e428HJ7+BHCxyeY39ClmkkUtxdOd3mk8gD6d9bjH2BECMg==} + + postcss-prefix-selector@1.16.1: + resolution: {integrity: sha512-Umxu+FvKMwlY6TyDzGFoSUnzW+NOfMBLyC1tAkIjgX+Z/qGspJeRjVC903D7mx7TuBpJlwti2ibXtWuA7fKMeQ==} + peerDependencies: + postcss: '>4 <9' + + postcss-reduce-idents@2.4.0: + resolution: {integrity: sha512-0+Ow9e8JLtffjumJJFPqvN4qAvokVbdQPnijUDSOX8tfTwrILLP4ETvrZcXZxAtpFLh/U0c+q8oRMJLr1Kiu4w==} + + postcss-reduce-initial@1.0.1: + resolution: {integrity: sha512-jJFrV1vWOPCQsIVitawGesRgMgunbclERQ/IRGW7r93uHrVzNQQmHQ7znsOIjJPZ4yWMzs5A8NFhp3AkPHPbDA==} + + postcss-reduce-transforms@1.0.4: + resolution: {integrity: sha512-lGgRqnSuAR5i5uUg1TA33r9UngfTadWxOyL2qx1KuPoCQzfmtaHjp9PuwX7yVyRxG3BWBzeFUaS5uV9eVgnEgQ==} + + postcss-selector-parser@2.2.3: + resolution: {integrity: sha512-3pqyakeGhrO0BQ5+/tGTfvi5IAUAhHRayGK8WFSu06aEv2BmHoXw/Mhb+w7VY5HERIuC+QoUI7wgrCcq2hqCVA==} + + postcss-svgo@2.1.6: + resolution: {integrity: sha512-y5AdQdgBoF4rbpdbeWAJuxE953g/ylRfVNp6mvAi61VCN/Y25Tu9p5mh3CyI42WbTRIiwR9a1GdFtmDnNPeskQ==} + + postcss-unique-selectors@2.0.2: + resolution: {integrity: sha512-WZX8r1M0+IyljoJOJleg3kYm10hxNYF9scqAT7v/xeSX1IdehutOM85SNO0gP9K+bgs86XERr7Ud5u3ch4+D8g==} + + postcss-value-parser@3.3.1: + resolution: {integrity: sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==} + + postcss-zindex@2.2.0: + resolution: {integrity: sha512-uhRZ2hRgj0lorxm9cr62B01YzpUe63h0RXMXQ4gWW3oa2rpJh+FJAiEAytaFCPU/VgaBS+uW2SJ1XKyDNz1h4w==} + + postcss@5.2.18: + resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==} + engines: {node: '>=0.12'} + + postcss@6.0.23: + resolution: {integrity: sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==} + engines: {node: '>=4.0.0'} + + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + engines: {node: ^10 || ^12 || >=14} + + posthtml-parser@0.2.1: + resolution: {integrity: sha512-nPC53YMqJnc/+1x4fRYFfm81KV2V+G9NZY+hTohpYg64Ay7NemWWcV4UWuy/SgMupqQ3kJ88M/iRfZmSnxT+pw==} + + posthtml-rename-id@1.0.12: + resolution: {integrity: sha512-UKXf9OF/no8WZo9edRzvuMenb6AD5hDLzIepJW+a4oJT+T/Lx7vfMYWT4aWlGNQh0WMhnUx1ipN9OkZ9q+ddEw==} + + posthtml-render@1.4.0: + resolution: {integrity: sha512-W1779iVHGfq0Fvh2PROhCe2QhB8mEErgqzo1wpIt36tCgChafP+hbXIhLDOM8ePJrZcFs0vkNEtdibEWVqChqw==} + engines: {node: '>=10'} + + posthtml-svg-mode@1.0.3: + resolution: {integrity: sha512-hEqw9NHZ9YgJ2/0G7CECOeuLQKZi8HjWLkBaSVtOWjygQ9ZD8P7tqeowYs7WrFdKsWEKG7o+IlsPY8jrr0CJpQ==} + + posthtml@0.9.2: + resolution: {integrity: sha512-spBB5sgC4cv2YcW03f/IAUN1pgDJWNWD8FzkyY4mArLUMJW+KlQhlmUdKAHQuPfb00Jl5xIfImeOsf6YL8QK7Q==} + engines: {node: '>=0.10.0'} + + prepend-http@1.0.4: + resolution: {integrity: sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==} + engines: {node: '>=0.10.0'} + + prettier@1.19.1: + resolution: {integrity: sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==} + engines: {node: '>=4'} + hasBin: true + + private@0.1.8: + resolution: {integrity: sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==} + engines: {node: '>= 0.6'} + + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} + + pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + + pug-error@2.1.0: + resolution: {integrity: sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==} + + pug-lexer@5.0.1: + resolution: {integrity: sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==} + + pug-parser@6.0.0: + resolution: {integrity: sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==} + + q@1.5.1: + resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} + engines: {node: '>=0.6.0', teleport: '>=0.2.0'} + deprecated: |- + You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. + + (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) + + qs@6.15.2: + resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} + engines: {node: '>=0.6'} + + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + + quansync@1.0.0: + resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} + + query-string@4.3.4: + resolution: {integrity: sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==} + engines: {node: '>=0.10.0'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + + reduce-css-calc@1.3.0: + resolution: {integrity: sha512-0dVfwYVOlf/LBA2ec4OwQ6p3X9mYxn/wOl2xTcLwjnPYrkgEfPx3VI4eGCH3rQLlPISG5v9I9bkZosKsNRTRKA==} + + reduce-function-call@1.0.3: + resolution: {integrity: sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ==} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regenerator-runtime@0.11.1: + resolution: {integrity: sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==} + + regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + + regex-not@1.0.2: + resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} + engines: {node: '>=0.10.0'} + + regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + repeat-element@1.1.4: + resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} + engines: {node: '>=0.10.0'} + + repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + + repeating@2.0.1: + resolution: {integrity: sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==} + engines: {node: '>=0.10.0'} + + request-light@0.7.0: + resolution: {integrity: sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==} + + require-from-string@1.2.1: + resolution: {integrity: sha512-H7AkJWMobeskkttHyhTVtS0fxpFLjxhbfMa6Bk3wimP7sdPRGL3EyCg3sAQenFfAe+xQ+oAc85Nmtvq0ROM83Q==} + 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-url@0.2.1: + resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} + deprecated: https://github.com/lydell/resolve-url#deprecated + + resolve@1.22.12: + resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} + engines: {node: '>= 0.4'} + hasBin: true + + ret@0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rolldown@1.0.3: + resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + safe-array-concat@1.1.4: + resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} + engines: {node: '>=0.4'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safe-regex@1.1.0: + resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + + sass@1.100.0: + resolution: {integrity: sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==} + engines: {node: '>=20.19.0'} + hasBin: true + + sax@1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + + schema-utils@4.3.3: + resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} + engines: {node: '>= 10.13.0'} + + scule@1.3.0: + resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} + + semver@7.8.4: + resolution: {integrity: sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==} + engines: {node: '>=10'} + hasBin: true + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + set-value@2.0.1: + resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} + engines: {node: '>=0.10.0'} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} + engines: {node: '>= 0.4'} + + sirv@3.0.2: + resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} + engines: {node: '>=18'} + + slash@1.0.0: + resolution: {integrity: sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==} + engines: {node: '>=0.10.0'} + + snapdragon-node@2.1.1: + resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} + engines: {node: '>=0.10.0'} + + snapdragon-util@3.0.1: + resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} + engines: {node: '>=0.10.0'} + + snapdragon@0.8.2: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + + sort-keys@1.1.2: + resolution: {integrity: sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==} + engines: {node: '>=0.10.0'} + + source-list-map@0.1.8: + resolution: {integrity: sha512-cabwdhnSNf/tTDMh/DXZXlkeQLvdYT5xfGYBohqHG7wb3bBQrQlHQNWM9NWSOboXXK1zgwz6JzS5e4hZq9vxMw==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-resolve@0.5.3: + resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated + + source-map-support@0.4.18: + resolution: {integrity: sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map-url@0.4.1: + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + deprecated: See https://github.com/lydell/source-map-url#deprecated + + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + speakingurl@14.0.1: + resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} + engines: {node: '>=0.10.0'} + + split-string@3.1.0: + resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + ssf@0.11.2: + resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==} + engines: {node: '>=0.8'} + + static-extend@0.1.2: + resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} + engines: {node: '>=0.10.0'} + + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + + strict-uri-encode@1.1.0: + resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} + engines: {node: '>=0.10.0'} + + string.prototype.trim@1.2.11: + resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.10: + resolution: {integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + + strnum@1.1.2: + resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} + + superjson@2.2.6: + resolution: {integrity: sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==} + engines: {node: '>=16'} + + supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + + supports-color@3.2.3: + resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} + engines: {node: '>=0.8.0'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svg-baker-runtime@1.4.7: + resolution: {integrity: sha512-Zorfwwj5+lWjk/oxwSMsRdS2sPQQdTmmsvaSpzU+i9ZWi3zugHLt6VckWfnswphQP0LmOel3nggpF5nETbt6xw==} + + svg-baker@1.7.0: + resolution: {integrity: sha512-nibslMbkXOIkqKVrfcncwha45f97fGuAOn1G99YwnwTj8kF9YiM6XexPcUso97NxOm6GsP0SIvYVIosBis1xLg==} + + svg-sprite-loader@3.7.3: + resolution: {integrity: sha512-P53xc3RvqYCvT5shjk6QU+JsL559OT0Q3NuS0oKdIBYx9If4d2ezTvcZoK8tDCQtaFi24+pvA7rV7WBgmorFUg==} + engines: {node: '>=6'} + + svgo@0.7.2: + resolution: {integrity: sha512-jT/g9FFMoe9lu2IT6HtAxTA7RR2XOrmcrmCtGnyB/+GQnV6ZjNn+KOHZbZ35yL81+1F/aB6OeEsJztzBQ2EEwA==} + engines: {node: '>=0.10.0'} + deprecated: This SVGO version is no longer supported. Upgrade to v2.x.x. + hasBin: true + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + + terser-webpack-plugin@5.6.1: + resolution: {integrity: sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@minify-html/node': '*' + '@swc/core': '*' + '@swc/css': '*' + '@swc/html': '*' + clean-css: '*' + cssnano: '*' + csso: '*' + esbuild: '*' + html-minifier-terser: '*' + lightningcss: '*' + postcss: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@minify-html/node': + optional: true + '@swc/core': + optional: true + '@swc/css': + optional: true + '@swc/html': + optional: true + clean-css: + optional: true + cssnano: + optional: true + csso: + optional: true + esbuild: + optional: true + html-minifier-terser: + optional: true + lightningcss: + optional: true + postcss: + optional: true + uglify-js: + optional: true + + terser@5.48.0: + resolution: {integrity: sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==} + engines: {node: '>=10'} + hasBin: true + + tesseract.js-core@7.0.0: + resolution: {integrity: sha512-WnNH518NzmbSq9zgTPeoF8c+xmilS8rFIl1YKbk/ptuuc7p6cLNELNuPAzcmsYw450ca6bLa8j3t0VAtq435Vw==} + + tesseract.js@7.0.0: + resolution: {integrity: sha512-exPBkd+z+wM1BuMkx/Bjv43OeLBxhL5kKWsz/9JY+DXcXdiBjiAch0V49QR3oAJqCaL5qURE0vx9Eo+G5YE7mA==} + + tiny-cookie@1.0.1: + resolution: {integrity: sha512-4KJ21HYTNumxnHvCbLrtrrhSwtWXzpmaRJIUg4biBii5AiSe2izod5bauXiiQxVuf2Fta57U2DTW1Fa4/6Cmgw==} + + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + to-fast-properties@1.0.3: + resolution: {integrity: sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==} + engines: {node: '>=0.10.0'} + + to-object-path@0.3.0: + resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} + engines: {node: '>=0.10.0'} + + to-regex-range@2.1.1: + resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} + engines: {node: '>=0.10.0'} + + to-regex@3.0.2: + resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} + engines: {node: '>=0.10.0'} + + token-stream@1.0.0: + resolution: {integrity: sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + traverse@0.6.11: + resolution: {integrity: sha512-vxXDZg8/+p3gblxB6BhhG5yWVn1kGRlaL8O78UDXc3wRnPizB5g83dcvWV1jpDMIPnjZjOFuxlMmE82XJ4407w==} + engines: {node: '>= 0.4'} + + trim-right@1.0.1: + resolution: {integrity: sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==} + engines: {node: '>=0.10.0'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-level-regexp@0.1.17: + resolution: {integrity: sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg==} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.8: + resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==} + engines: {node: '>= 0.4'} + + typedarray.prototype.slice@1.0.5: + resolution: {integrity: sha512-q7QNVDGTdl702bVFiI5eY4l/HkgCM6at9KhcFbgUAzezHFbOVy4+0O/lCjsABEQwbZPravVfBIiBVGo89yzHFg==} + engines: {node: '>= 0.4'} + + typescript-auto-import-cache@0.3.6: + resolution: {integrity: sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ==} + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + unconfig-core@7.5.0: + resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} + + unconfig@7.5.0: + resolution: {integrity: sha512-oi8Qy2JV4D3UQ0PsopR28CzdQ3S/5A1zwsUwp/rosSbfhJ5z7b90bIyTwi/F7hCLD4SGcZVjDzd4XoUQcEanvA==} + + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + + unidecode@0.1.8: + resolution: {integrity: sha512-SdoZNxCWpN2tXTCrGkPF/0rL2HEq+i2gwRG1ReBvx8/0yTzC3enHfugOf8A9JBShVwwrRIkLX0YcDUGbzjbVCA==} + engines: {node: '>= 0.4.12'} + + unimport@5.7.0: + resolution: {integrity: sha512-njnL6sp8lEA8QQbZrt+52p/g4X0rw3bnGGmUcJnt1jeG8+iiqO779aGz0PirCtydAIVcuTBRlJ52F0u46z309Q==} + engines: {node: '>=18.12.0'} + + union-value@1.0.1: + resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} + engines: {node: '>=0.10.0'} + + uniq@1.0.1: + resolution: {integrity: sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==} + + uniqs@2.0.0: + resolution: {integrity: sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ==} + + unocss@66.7.0: + resolution: {integrity: sha512-dVfkL7SQv3fOiZdqeRX1PdpQqXlB+wHcEQjVR0D/2nXsuqmUqTVnX3EUUWFjqVR83Z51zQ0EyVgym8ooDfcVvw==} + peerDependencies: + '@unocss/astro': 66.7.0 + '@unocss/postcss': 66.7.0 + '@unocss/webpack': 66.7.0 + peerDependenciesMeta: + '@unocss/astro': + optional: true + '@unocss/postcss': + optional: true + '@unocss/webpack': + optional: true + + unplugin-auto-import@21.0.0: + resolution: {integrity: sha512-vWuC8SwqJmxZFYwPojhOhOXDb5xFhNNcEVb9K/RFkyk/3VnfaOjzitWN7v+8DEKpMjSsY2AEGXNgt6I0yQrhRQ==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@nuxt/kit': ^4.0.0 + '@vueuse/core': '*' + peerDependenciesMeta: + '@nuxt/kit': + optional: true + '@vueuse/core': + optional: true + + unplugin-utils@0.3.1: + resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==} + engines: {node: '>=20.19.0'} + + unplugin-vue-components@31.1.0: + resolution: {integrity: sha512-9EbV5ark21A4BOBt6RJGJXCVD2I1eoxTZL1TAvNgYTokcrFIiuxpufb8owyWn7n+z2x8daz/ltZq6IRRKL3ydQ==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@nuxt/kit': ^3.2.2 || ^4.0.0 + vue: ^3.0.0 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + + unplugin@2.3.11: + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.0'} + + unplugin@3.0.0: + resolution: {integrity: sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==} + engines: {node: ^20.19.0 || >=22.12.0} + + unset-value@1.0.0: + resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} + engines: {node: '>=0.10.0'} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + urix@0.1.0: + resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} + deprecated: Please see https://github.com/lydell/urix#deprecated + + url-slug@2.0.0: + resolution: {integrity: sha512-aiNmSsVgrjCiJ2+KWPferjT46YFKoE8i0YX04BlMVDue022Xwhg/zYlnZ6V9/mP3p8Wj7LEp0myiTkC/p6sxew==} + + use@3.1.1: + resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} + engines: {node: '>=0.10.0'} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vendors@1.0.4: + resolution: {integrity: sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==} + + vite@8.0.16: + resolution: {integrity: sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.18 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.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 + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + volar-service-css@0.0.71: + resolution: {integrity: sha512-wRRFt9BpjMKCazcgOh67MSjUjiWUCAh99DyYSDIOTuxaRjEtDC7PpB0k1Y1wbJIW/pVtMUSVbpPo3UGSm0Byxw==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-emmet@0.0.71: + resolution: {integrity: sha512-zqjzt6bN95e3CUstBm0PBFAJnrfz0ZAARka87fart46/gNCLLuP3Vujy8V/J8HEziTFLnfkgIASLFYPUhonJcA==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-html@0.0.71: + resolution: {integrity: sha512-e8tHPhgQ7ooLfudAEIku+kgd9pWkq3SSz8RbnQDI1+Eb8wbenkLGHqoirLqz5ORLV6wIMr2Iv08RWBG5eOcgpw==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-json@0.0.71: + resolution: {integrity: sha512-behyNhAG5UEXfvbIOWdE62XsPkp/e5W0V3sz3AW6zy7vgWLzgvElR77YSlcu708GwKu7OOFl5m9sUGVfqLIriQ==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-pug-beautify@0.0.71: + resolution: {integrity: sha512-4oxv7xGwT6TxxuFZdXj9EdqUUUWSd1oz9H47z4s/shT9YVLKwrty+9ACbdQsjyWZTp6ES/EtcuSqKuPhz3Uhaw==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-pug@0.0.71: + resolution: {integrity: sha512-vG4nkQxRfRTCwJsA1CbQ2hSsZjzsrsLDBGeJTDjIaymtOBfML5UMOROTB3ClVuEZVrtg1rquVzVlGTjhvc2ysg==} + + volar-service-typescript@0.0.71: + resolution: {integrity: sha512-yTtM/BVT6hoyEYnDtaCyAtNhdNeS/mhTTABlBOdw3NNiRBUin3IznFJpgfjer4c6RYopiPjjQjc9VFhxVl1mLw==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + vscode-css-languageservice@6.3.10: + resolution: {integrity: sha512-eq5N9Er3fC4vA9zd9EFhyBG90wtCCuXgRSpAndaOgXMh1Wgep5lBgRIeDgjZBW9pa+332yC9+49cZMW8jcL3MA==} + + vscode-html-languageservice@5.6.2: + resolution: {integrity: sha512-ulCrSnFnfQ16YzvwnYUgEbUEl/ZG7u2eV27YhvLObSHKkb8fw1Z9cgsnUwjTEeDIdJDoTDTDpxuhQwoenoLNMg==} + + vscode-json-languageservice@5.7.2: + resolution: {integrity: sha512-WtKRDtJfFEmLrgtu+ODexOHm/6/krRF0k6t+uvkKIKW1Jh9ZIyxZQwJJwB3qhrEgvAxa37zbUg+vn+UyUK/U2w==} + + vscode-jsonrpc@8.2.0: + resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} + engines: {node: '>=14.0.0'} + + vscode-jsonrpc@9.0.0: + resolution: {integrity: sha512-+VvMmQPJhtvJ+8O+zu2JKIRiLxXF8NW7krWgyMGeOHrp4Cn23T5hc0v2LknNeopDOB70wghHAds7mKtcZ0I4Sg==} + engines: {node: '>=14.0.0'} + + vscode-languageserver-protocol@3.17.5: + resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} + + vscode-languageserver-protocol@3.18.0: + resolution: {integrity: sha512-Zdz+kJ12Iz6tc11xfZyEo501bBATHXrCjmMfnaR3pMnf1CoqZBKIynba3P+/bi9VEdrMbNtAVKYpKhbODvqy+Q==} + + vscode-languageserver-textdocument@1.0.12: + resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} + + vscode-languageserver-types@3.17.5: + resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} + + vscode-languageserver-types@3.18.0: + resolution: {integrity: sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g==} + + vscode-languageserver@9.0.1: + resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} + hasBin: true + + vscode-nls@5.2.0: + resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==} + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + vue-component-meta@3.3.4: + resolution: {integrity: sha512-FSF6+AaO9u3UiZ94QTx64arR1Gw7hNYP98N8DORLN2FKmkESAuaQdVkNSTtOHehfEnGpKKutPzfoDKTbtJ4vyQ==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + vue-component-type-helpers@3.3.4: + resolution: {integrity: sha512-joip1uZTaQR0nD23N400gIdJ7xY+WiiiMA/BCKz842gvGBknqDQAzklUvDEhqFvvrhQY8S2ZANBMu4X70VMFGw==} + + vue-cookie@1.1.4: + resolution: {integrity: sha512-lxWIzmUTCVra0H7YPbNpYx0wbTQThV+n7ueUOcqtK8dlckmfB8fcyf4OEiRuQUd7iiVub2T3IDlWiisEM5Ku0Q==} + + vue-hot-reload-api@2.3.4: + resolution: {integrity: sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==} + + vue-loader@13.7.3: + resolution: {integrity: sha512-ACCwbfeC6HjY2pnDii+Zer+MZ6sdOtwvLmDXRK/BoD3WNR551V22R6KEagwHoTRJ0ZlIhpCBkptpCU6+Ri/05w==} + peerDependencies: + '@vue/compiler-sfc': ^3.0.8 + css-loader: '*' + vue-template-compiler: ^2.0.0 + webpack: ^4.1.0 || ^5.0.0-0 + peerDependenciesMeta: + '@vue/compiler-sfc': + optional: true + + vue-router@5.1.0: + resolution: {integrity: sha512-HAbiLzLEHQwxPgvsbOJDAwtavszEgLwri6XfyrsPECIFez8+59xc9LofWVdc/HEaSRT822lJ8H9Ns38VVond5g==} + peerDependencies: + '@pinia/colada': '>=0.21.2' + '@vue/compiler-sfc': ^3.5.34 + pinia: ^3.0.4 + vite: ^7.0.0 || ^8.0.0 + vue: ^3.5.34 + peerDependenciesMeta: + '@pinia/colada': + optional: true + '@vue/compiler-sfc': + optional: true + pinia: + optional: true + vite: + optional: true + + vue-style-loader@3.1.2: + resolution: {integrity: sha512-ICtVdK/p+qXWpdSs2alWtsXt9YnDoYjQe0w5616j9+/EhjoxZkbun34uWgsMFnC1MhrMMwaWiImz3K2jK1Yp2Q==} + + vue-template-compiler@2.7.16: + resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==} + + vue-template-es2015-compiler@1.9.1: + resolution: {integrity: sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==} + + vue-tsc@3.3.4: + resolution: {integrity: sha512-XA/JqmQwS2GZmfgpjOEGdrKwaTSEuPwxpHa7/t6f4yiGrJb3gVHTPb9wBfByMNZwQ+xDXs41b8gaS2DKsOozUw==} + hasBin: true + peerDependencies: + typescript: '>=5.0.0' + + vue@3.5.35: + resolution: {integrity: sha512-cx89fnr+0kVGHiNFG6y6s0bdjypJRFNZn6x3WPstNdQR1bi1mbB7h4v5IBGTsPJU3nK1+0Iqj3Zf+hZWMieR4Q==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + wasm-feature-detect@1.8.0: + resolution: {integrity: sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==} + + watchpack@2.5.1: + resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} + engines: {node: '>=10.13.0'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webpack-sources@3.5.0: + resolution: {integrity: sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==} + engines: {node: '>=10.13.0'} + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + webpack@5.105.4: + resolution: {integrity: sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + whet.extend@0.9.9: + resolution: {integrity: sha512-mmIPAft2vTgEILgPeZFqE/wWh24SEsR/k+N9fJ3Jxrz44iDFy9aemCxdksfURSHYFCLmvs/d/7Iso5XjPpNfrA==} + engines: {node: '>=0.6.0'} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.22: + resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} + engines: {node: '>= 0.4'} + + wmf@1.0.2: + resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==} + engines: {node: '>=0.8'} + + word@0.3.0: + resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==} + engines: {node: '>=0.8'} + + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + + xlsx@0.18.5: + resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==} + engines: {node: '>=0.8'} + hasBin: true + + yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true + + zlibjs@0.3.1: + resolution: {integrity: sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==} + +snapshots: + + '@antfu/install-pkg@1.1.0': + dependencies: + package-manager-detector: 1.6.0 + tinyexec: 1.2.4 + + '@babel/generator@8.0.0-rc.6': + dependencies: + '@babel/parser': 8.0.0-rc.6 + '@babel/types': 8.0.0-rc.6 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@types/jsesc': 2.5.1 + jsesc: 3.1.0 + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-string-parser@8.0.0-rc.6': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-identifier@8.0.0-rc.6': {} + + '@babel/parser@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/parser@8.0.0-rc.6': + dependencies: + '@babel/types': 8.0.0-rc.6 + + '@babel/types@7.29.7': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@babel/types@8.0.0-rc.6': + dependencies: + '@babel/helper-string-parser': 8.0.0-rc.6 + '@babel/helper-validator-identifier': 8.0.0-rc.6 + + '@ctrl/tinycolor@4.2.0': {} + + '@element-plus/icons-vue@2.3.2(vue@3.5.35(typescript@6.0.3))': + dependencies: + vue: 3.5.35(typescript@6.0.3) + + '@emmetio/abbreviation@2.3.3': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/css-abbreviation@2.1.8': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/css-parser@0.4.1': + dependencies: + '@emmetio/stream-reader': 2.2.0 + '@emmetio/stream-reader-utils': 0.1.0 + + '@emmetio/html-matcher@1.3.0': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/scanner@1.0.4': {} + + '@emmetio/stream-reader-utils@0.1.0': {} + + '@emmetio/stream-reader@2.2.0': {} + + '@emnapi/core@1.10.0': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.27.3': + optional: true + + '@esbuild/android-arm64@0.27.3': + optional: true + + '@esbuild/android-arm@0.27.3': + optional: true + + '@esbuild/android-x64@0.27.3': + optional: true + + '@esbuild/darwin-arm64@0.27.3': + optional: true + + '@esbuild/darwin-x64@0.27.3': + optional: true + + '@esbuild/freebsd-arm64@0.27.3': + optional: true + + '@esbuild/freebsd-x64@0.27.3': + optional: true + + '@esbuild/linux-arm64@0.27.3': + optional: true + + '@esbuild/linux-arm@0.27.3': + optional: true + + '@esbuild/linux-ia32@0.27.3': + optional: true + + '@esbuild/linux-loong64@0.27.3': + optional: true + + '@esbuild/linux-mips64el@0.27.3': + optional: true + + '@esbuild/linux-ppc64@0.27.3': + optional: true + + '@esbuild/linux-riscv64@0.27.3': + optional: true + + '@esbuild/linux-s390x@0.27.3': + optional: true + + '@esbuild/linux-x64@0.27.3': + optional: true + + '@esbuild/netbsd-arm64@0.27.3': + optional: true + + '@esbuild/netbsd-x64@0.27.3': + optional: true + + '@esbuild/openbsd-arm64@0.27.3': + optional: true + + '@esbuild/openbsd-x64@0.27.3': + optional: true + + '@esbuild/openharmony-arm64@0.27.3': + optional: true + + '@esbuild/sunos-x64@0.27.3': + optional: true + + '@esbuild/win32-arm64@0.27.3': + optional: true + + '@esbuild/win32-ia32@0.27.3': + optional: true + + '@esbuild/win32-x64@0.27.3': + optional: true + + '@floating-ui/core@1.7.5': + dependencies: + '@floating-ui/utils': 0.2.11 + + '@floating-ui/dom@1.7.6': + dependencies: + '@floating-ui/core': 1.7.5 + '@floating-ui/utils': 0.2.11 + + '@floating-ui/utils@0.2.11': {} + + '@iconify/types@2.0.0': {} + + '@iconify/utils@3.1.3': + dependencies: + '@antfu/install-pkg': 1.1.0 + '@iconify/types': 2.0.0 + import-meta-resolve: 4.2.0 + + '@johnsoncodehk/pug-beautify@0.2.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 + + '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.2 + optional: true + + '@oxc-parser/binding-android-arm-eabi@0.131.0': + optional: true + + '@oxc-parser/binding-android-arm64@0.131.0': + optional: true + + '@oxc-parser/binding-darwin-arm64@0.131.0': + optional: true + + '@oxc-parser/binding-darwin-x64@0.131.0': + optional: true + + '@oxc-parser/binding-freebsd-x64@0.131.0': + optional: true + + '@oxc-parser/binding-linux-arm-gnueabihf@0.131.0': + optional: true + + '@oxc-parser/binding-linux-arm-musleabihf@0.131.0': + optional: true + + '@oxc-parser/binding-linux-arm64-gnu@0.131.0': + optional: true + + '@oxc-parser/binding-linux-arm64-musl@0.131.0': + optional: true + + '@oxc-parser/binding-linux-ppc64-gnu@0.131.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-gnu@0.131.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-musl@0.131.0': + optional: true + + '@oxc-parser/binding-linux-s390x-gnu@0.131.0': + optional: true + + '@oxc-parser/binding-linux-x64-gnu@0.131.0': + optional: true + + '@oxc-parser/binding-linux-x64-musl@0.131.0': + optional: true + + '@oxc-parser/binding-openharmony-arm64@0.131.0': + optional: true + + '@oxc-parser/binding-wasm32-wasi@0.131.0': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@oxc-parser/binding-win32-arm64-msvc@0.131.0': + optional: true + + '@oxc-parser/binding-win32-ia32-msvc@0.131.0': + optional: true + + '@oxc-parser/binding-win32-x64-msvc@0.131.0': + optional: true + + '@oxc-project/types@0.131.0': {} + + '@oxc-project/types@0.133.0': {} + + '@parcel/watcher-android-arm64@2.5.6': + optional: true + + '@parcel/watcher-darwin-arm64@2.5.6': + optional: true + + '@parcel/watcher-darwin-x64@2.5.6': + optional: true + + '@parcel/watcher-freebsd-x64@2.5.6': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.5.6': + optional: true + + '@parcel/watcher-linux-arm-musl@2.5.6': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.5.6': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.5.6': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.5.6': + optional: true + + '@parcel/watcher-linux-x64-musl@2.5.6': + optional: true + + '@parcel/watcher-win32-arm64@2.5.6': + optional: true + + '@parcel/watcher-win32-ia32@2.5.6': + optional: true + + '@parcel/watcher-win32-x64@2.5.6': + optional: true + + '@parcel/watcher@2.5.6': + dependencies: + detect-libc: 2.1.2 + is-glob: 4.0.3 + node-addon-api: 7.1.1 + picomatch: 4.0.4 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.5.6 + '@parcel/watcher-darwin-arm64': 2.5.6 + '@parcel/watcher-darwin-x64': 2.5.6 + '@parcel/watcher-freebsd-x64': 2.5.6 + '@parcel/watcher-linux-arm-glibc': 2.5.6 + '@parcel/watcher-linux-arm-musl': 2.5.6 + '@parcel/watcher-linux-arm64-glibc': 2.5.6 + '@parcel/watcher-linux-arm64-musl': 2.5.6 + '@parcel/watcher-linux-x64-glibc': 2.5.6 + '@parcel/watcher-linux-x64-musl': 2.5.6 + '@parcel/watcher-win32-arm64': 2.5.6 + '@parcel/watcher-win32-ia32': 2.5.6 + '@parcel/watcher-win32-x64': 2.5.6 + optional: true + + '@polka/url@1.0.0-next.29': {} + + '@quansync/fs@1.0.0': + dependencies: + quansync: 1.0.0 + + '@rolldown/binding-android-arm64@1.0.3': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.3': + optional: true + + '@rolldown/binding-darwin-x64@1.0.3': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.3': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.3': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.3': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.3': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.3': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.3': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.3': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@sxzz/popperjs-es@2.11.8': {} + + '@tybys/wasm-util@0.10.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/eslint-scope@3.7.7': + dependencies: + '@types/eslint': 9.6.1 + '@types/estree': 1.0.9 + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.9 + '@types/json-schema': 7.0.15 + + '@types/estree@1.0.9': {} + + '@types/jsesc@2.5.1': {} + + '@types/json-schema@7.0.15': {} + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.24 + + '@types/lodash@4.17.24': {} + + '@types/node@25.9.2': + dependencies: + undici-types: 7.24.6 + + '@types/qs@6.15.1': {} + + '@types/web-bluetooth@0.0.21': {} + + '@unocss/cli@66.7.0': + dependencies: + '@jridgewell/remapping': 2.3.5 + '@unocss/config': 66.7.0 + '@unocss/core': 66.7.0 + '@unocss/preset-wind3': 66.7.0 + '@unocss/preset-wind4': 66.7.0 + '@unocss/transformer-directives': 66.7.0 + cac: 7.0.0 + chokidar: 5.0.0 + colorette: 2.0.20 + consola: 3.4.2 + magic-string: 0.30.21 + pathe: 2.0.3 + perfect-debounce: 2.1.0 + tinyglobby: 0.2.17 + unplugin-utils: 0.3.1 + + '@unocss/config@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + colorette: 2.0.20 + consola: 3.4.2 + unconfig: 7.5.0 + + '@unocss/core@66.7.0': {} + + '@unocss/extractor-arbitrary-variants@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + + '@unocss/inspector@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + '@unocss/rule-utils': 66.7.0 + colorette: 2.0.20 + gzip-size: 6.0.0 + sirv: 3.0.2 + + '@unocss/preset-attributify@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + + '@unocss/preset-icons@66.7.0': + dependencies: + '@iconify/utils': 3.1.3 + '@unocss/core': 66.7.0 + ofetch: 1.5.1 + + '@unocss/preset-mini@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + '@unocss/extractor-arbitrary-variants': 66.7.0 + '@unocss/rule-utils': 66.7.0 + + '@unocss/preset-tagify@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + + '@unocss/preset-typography@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + '@unocss/rule-utils': 66.7.0 + + '@unocss/preset-uno@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + '@unocss/preset-wind3': 66.7.0 + + '@unocss/preset-web-fonts@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + ofetch: 1.5.1 + + '@unocss/preset-wind3@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + '@unocss/preset-mini': 66.7.0 + '@unocss/rule-utils': 66.7.0 + + '@unocss/preset-wind4@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + '@unocss/extractor-arbitrary-variants': 66.7.0 + '@unocss/rule-utils': 66.7.0 + + '@unocss/preset-wind@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + '@unocss/preset-wind3': 66.7.0 + + '@unocss/rule-utils@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + magic-string: 0.30.21 + + '@unocss/transformer-attributify-jsx@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + oxc-parser: 0.131.0 + oxc-walker: 0.7.0(oxc-parser@0.131.0) + + '@unocss/transformer-compile-class@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + + '@unocss/transformer-directives@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + '@unocss/rule-utils': 66.7.0 + css-tree: 3.2.1 + + '@unocss/transformer-variant-group@66.7.0': + dependencies: + '@unocss/core': 66.7.0 + + '@unocss/vite@66.7.0(vite@8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0))': + dependencies: + '@jridgewell/remapping': 2.3.5 + '@unocss/config': 66.7.0 + '@unocss/core': 66.7.0 + '@unocss/inspector': 66.7.0 + chokidar: 5.0.0 + magic-string: 0.30.21 + pathe: 2.0.3 + tinyglobby: 0.2.17 + unplugin-utils: 0.3.1 + vite: 8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0) + + '@vitejs/plugin-vue@6.0.7(vite@8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0))(vue@3.5.35(typescript@6.0.3))': + dependencies: + '@rolldown/pluginutils': 1.0.1 + vite: 8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0) + vue: 3.5.35(typescript@6.0.3) + + '@volar/language-core@2.4.28': + dependencies: + '@volar/source-map': 2.4.28 + + '@volar/language-server@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + '@volar/language-service': 2.4.28 + '@volar/typescript': 2.4.28 + path-browserify: 1.0.1 + request-light: 0.7.0 + vscode-languageserver: 9.0.1 + vscode-languageserver-protocol: 3.18.0 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + + '@volar/language-service@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + vscode-languageserver-protocol: 3.18.0 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + + '@volar/source-map@2.4.28': {} + + '@volar/typescript@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vscode/emmet-helper@2.11.0': + dependencies: + emmet: 2.4.11 + jsonc-parser: 2.3.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.18.0 + vscode-uri: 3.1.0 + + '@vscode/l10n@0.0.18': {} + + '@vue-macros/common@3.1.2(vue@3.5.35(typescript@6.0.3))': + dependencies: + '@vue/compiler-sfc': 3.5.35 + ast-kit: 2.2.0 + local-pkg: 1.2.1 + magic-string-ast: 1.0.3 + unplugin-utils: 0.3.1 + optionalDependencies: + vue: 3.5.35(typescript@6.0.3) + + '@vue/compiler-core@3.5.35': + dependencies: + '@babel/parser': 7.29.7 + '@vue/shared': 3.5.35 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.35': + dependencies: + '@vue/compiler-core': 3.5.35 + '@vue/shared': 3.5.35 + + '@vue/compiler-sfc@3.5.35': + dependencies: + '@babel/parser': 7.29.7 + '@vue/compiler-core': 3.5.35 + '@vue/compiler-dom': 3.5.35 + '@vue/compiler-ssr': 3.5.35 + '@vue/shared': 3.5.35 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.15 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.35': + dependencies: + '@vue/compiler-dom': 3.5.35 + '@vue/shared': 3.5.35 + + '@vue/devtools-api@7.7.9': + dependencies: + '@vue/devtools-kit': 7.7.9 + + '@vue/devtools-api@8.1.2': + dependencies: + '@vue/devtools-kit': 8.1.2 + + '@vue/devtools-kit@7.7.9': + dependencies: + '@vue/devtools-shared': 7.7.9 + birpc: 2.9.0 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.6 + + '@vue/devtools-kit@8.1.2': + dependencies: + '@vue/devtools-shared': 8.1.2 + birpc: 2.9.0 + hookable: 5.5.3 + perfect-debounce: 2.1.0 + + '@vue/devtools-shared@7.7.9': + dependencies: + rfdc: 1.4.1 + + '@vue/devtools-shared@8.1.2': {} + + '@vue/language-core@3.3.4': + dependencies: + '@volar/language-core': 2.4.28 + '@vue/compiler-dom': 3.5.35 + '@vue/shared': 3.5.35 + alien-signals: 3.2.1 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + picomatch: 4.0.4 + + '@vue/language-plugin-pug@3.2.9': + dependencies: + '@volar/source-map': 2.4.28 + muggle-string: 0.4.1 + pug-lexer: 5.0.1 + pug-parser: 6.0.0 + vscode-languageserver-textdocument: 1.0.12 + + '@vue/language-plugin-pug@3.3.4': + dependencies: + '@volar/source-map': 2.4.28 + muggle-string: 0.4.1 + pug-lexer: 5.0.1 + pug-parser: 6.0.0 + vscode-languageserver-textdocument: 1.0.12 + + '@vue/language-server@3.3.4(typescript@6.0.3)': + dependencies: + '@volar/language-server': 2.4.28 + '@vue/language-core': 3.3.4 + '@vue/language-service': 3.3.4 + '@vue/typescript-plugin': 3.3.4(typescript@6.0.3) + typescript: 6.0.3 + vscode-uri: 3.1.0 + + '@vue/language-service@3.3.4': + dependencies: + '@volar/language-service': 2.4.28 + '@vue/language-core': 3.3.4 + '@vue/shared': 3.5.35 + path-browserify: 1.0.1 + volar-service-css: 0.0.71(@volar/language-service@2.4.28) + volar-service-emmet: 0.0.71(@volar/language-service@2.4.28) + volar-service-html: 0.0.71(@volar/language-service@2.4.28) + volar-service-json: 0.0.71(@volar/language-service@2.4.28) + volar-service-pug: 0.0.71 + volar-service-pug-beautify: 0.0.71(@volar/language-service@2.4.28) + volar-service-typescript: 0.0.71(@volar/language-service@2.4.28) + vscode-html-languageservice: 5.6.2 + vscode-uri: 3.1.0 + + '@vue/reactivity@3.5.35': + dependencies: + '@vue/shared': 3.5.35 + + '@vue/runtime-core@3.5.35': + dependencies: + '@vue/reactivity': 3.5.35 + '@vue/shared': 3.5.35 + + '@vue/runtime-dom@3.5.35': + dependencies: + '@vue/reactivity': 3.5.35 + '@vue/runtime-core': 3.5.35 + '@vue/shared': 3.5.35 + csstype: 3.2.3 + + '@vue/server-renderer@3.5.35(vue@3.5.35(typescript@6.0.3))': + dependencies: + '@vue/compiler-ssr': 3.5.35 + '@vue/shared': 3.5.35 + vue: 3.5.35(typescript@6.0.3) + + '@vue/shared@3.5.35': {} + + '@vue/typescript-plugin@3.3.4(typescript@6.0.3)': + dependencies: + '@volar/typescript': 2.4.28 + '@vue/language-core': 3.3.4 + '@vue/shared': 3.5.35 + path-browserify: 1.0.1 + vue-component-meta: 3.3.4(typescript@6.0.3) + transitivePeerDependencies: + - typescript + + '@vueuse/core@14.3.0(vue@3.5.35(typescript@6.0.3))': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 14.3.0 + '@vueuse/shared': 14.3.0(vue@3.5.35(typescript@6.0.3)) + vue: 3.5.35(typescript@6.0.3) + + '@vueuse/metadata@14.3.0': {} + + '@vueuse/shared@14.3.0(vue@3.5.35(typescript@6.0.3))': + dependencies: + vue: 3.5.35(typescript@6.0.3) + + '@webassemblyjs/ast@1.14.1': + dependencies: + '@webassemblyjs/helper-numbers': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + + '@webassemblyjs/floating-point-hex-parser@1.13.2': {} + + '@webassemblyjs/helper-api-error@1.13.2': {} + + '@webassemblyjs/helper-buffer@1.14.1': {} + + '@webassemblyjs/helper-numbers@1.13.2': + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.13.2 + '@webassemblyjs/helper-api-error': 1.13.2 + '@xtuc/long': 4.2.2 + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} + + '@webassemblyjs/helper-wasm-section@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/wasm-gen': 1.14.1 + + '@webassemblyjs/ieee754@1.13.2': + dependencies: + '@xtuc/ieee754': 1.2.0 + + '@webassemblyjs/leb128@1.13.2': + dependencies: + '@xtuc/long': 4.2.2 + + '@webassemblyjs/utf8@1.13.2': {} + + '@webassemblyjs/wasm-edit@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/helper-wasm-section': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-opt': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + '@webassemblyjs/wast-printer': 1.14.1 + + '@webassemblyjs/wasm-gen@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wasm-opt@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + + '@webassemblyjs/wasm-parser@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-api-error': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wast-printer@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@xtuc/long': 4.2.2 + + '@xtuc/ieee754@1.2.0': {} + + '@xtuc/long@4.2.2': {} + + acorn-import-phases@1.0.4(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn@7.4.1: {} + + acorn@8.16.0: {} + + adler-32@1.3.1: {} + + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + ajv-formats@2.1.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv-keywords@5.1.0(ajv@8.20.0): + dependencies: + ajv: 8.20.0 + fast-deep-equal: 3.1.3 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.2 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + alien-signals@3.2.1: {} + + alphanum-sort@1.0.2: {} + + ansi-regex@2.1.1: {} + + ansi-styles@2.2.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + arr-diff@4.0.0: {} + + arr-flatten@1.1.0: {} + + arr-union@3.1.0: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-unique@0.3.2: {} + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + assign-symbols@1.0.0: {} + + ast-kit@2.2.0: + dependencies: + '@babel/parser': 7.29.7 + pathe: 2.0.3 + + ast-walker-scope@0.9.0: + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + ast-kit: 2.2.0 + + async-function@1.0.0: {} + + async-validator@4.2.5: {} + + asynckit@0.4.0: {} + + atob@2.1.2: {} + + autoprefixer@6.7.7: + dependencies: + browserslist: 1.7.7 + caniuse-db: 1.0.30001797 + normalize-range: 0.1.2 + num2fraction: 1.2.2 + postcss: 5.2.18 + postcss-value-parser: 3.3.1 + + autoprefixer@7.1.2: + dependencies: + browserslist: 2.11.3 + caniuse-lite: 1.0.30001797 + normalize-range: 0.1.2 + num2fraction: 1.2.2 + postcss: 6.0.23 + postcss-value-parser: 3.3.1 + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axios@1.17.0: + dependencies: + follow-redirects: 1.16.0 + form-data: 4.0.5 + https-proxy-agent: 5.0.1 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + - supports-color + + babel-code-frame@6.26.0: + dependencies: + chalk: 1.1.3 + esutils: 2.0.3 + js-tokens: 3.0.2 + + babel-core@6.26.3: + dependencies: + babel-code-frame: 6.26.0 + babel-generator: 6.26.1 + babel-helpers: 6.24.1 + babel-messages: 6.23.0 + babel-register: 6.26.0 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + babylon: 6.18.0 + convert-source-map: 1.9.0 + debug: 2.6.9 + json5: 0.5.1 + lodash: 4.18.1 + minimatch: 3.1.5 + path-is-absolute: 1.0.1 + private: 0.1.8 + slash: 1.0.0 + source-map: 0.5.7 + transitivePeerDependencies: + - supports-color + optional: true + + babel-generator@6.26.1: + dependencies: + babel-messages: 6.23.0 + babel-runtime: 6.26.0 + babel-types: 6.26.0 + detect-indent: 4.0.0 + jsesc: 1.3.0 + lodash: 4.18.1 + source-map: 0.5.7 + trim-right: 1.0.1 + optional: true + + babel-helpers@6.24.1: + dependencies: + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + optional: true + + babel-messages@6.23.0: + dependencies: + babel-runtime: 6.26.0 + optional: true + + babel-register@6.26.0: + dependencies: + babel-core: 6.26.3 + babel-runtime: 6.26.0 + core-js: 2.6.12 + home-or-tmp: 2.0.0 + lodash: 4.18.1 + mkdirp: 0.5.6 + source-map-support: 0.4.18 + transitivePeerDependencies: + - supports-color + optional: true + + babel-runtime@6.26.0: + dependencies: + core-js: 2.6.12 + regenerator-runtime: 0.11.1 + optional: true + + babel-template@6.26.0: + dependencies: + babel-runtime: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + babylon: 6.18.0 + lodash: 4.18.1 + transitivePeerDependencies: + - supports-color + optional: true + + babel-traverse@6.26.0: + dependencies: + babel-code-frame: 6.26.0 + babel-messages: 6.23.0 + babel-runtime: 6.26.0 + babel-types: 6.26.0 + babylon: 6.18.0 + debug: 2.6.9 + globals: 9.18.0 + invariant: 2.2.4 + lodash: 4.18.1 + transitivePeerDependencies: + - supports-color + optional: true + + babel-types@6.26.0: + dependencies: + babel-runtime: 6.26.0 + esutils: 2.0.3 + lodash: 4.18.1 + to-fast-properties: 1.0.3 + optional: true + + babylon@6.18.0: + optional: true + + balanced-match@0.4.2: {} + + balanced-match@1.0.2: {} + + base@0.11.2: + dependencies: + cache-base: 1.0.1 + class-utils: 0.3.6 + component-emitter: 1.3.1 + define-property: 1.0.0 + isobject: 3.0.1 + mixin-deep: 1.3.2 + pascalcase: 0.1.1 + + baseline-browser-mapping@2.10.35: {} + + big.js@5.2.2: {} + + birpc@2.9.0: {} + + bluebird@3.7.2: {} + + bmp-js@0.1.0: {} + + brace-expansion@1.1.15: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + optional: true + + braces@2.3.2: + dependencies: + arr-flatten: 1.1.0 + array-unique: 0.3.2 + extend-shallow: 2.0.1 + fill-range: 4.0.0 + isobject: 3.0.1 + repeat-element: 1.1.4 + snapdragon: 0.8.2 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + browserslist@1.7.7: + dependencies: + caniuse-db: 1.0.30001797 + electron-to-chromium: 1.5.371 + + browserslist@2.11.3: + dependencies: + caniuse-lite: 1.0.30001797 + electron-to-chromium: 1.5.371 + + browserslist@4.28.2: + dependencies: + baseline-browser-mapping: 2.10.35 + caniuse-lite: 1.0.30001797 + electron-to-chromium: 1.5.371 + node-releases: 2.0.47 + update-browserslist-db: 1.2.3(browserslist@4.28.2) + + buffer-from@1.1.2: {} + + cac@7.0.0: {} + + cache-base@1.0.1: + dependencies: + collection-visit: 1.0.0 + component-emitter: 1.3.1 + get-value: 2.0.6 + has-value: 1.0.0 + isobject: 3.0.1 + set-value: 2.0.1 + to-object-path: 0.3.0 + union-value: 1.0.1 + unset-value: 1.0.0 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.9: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + caniuse-api@1.6.1: + dependencies: + browserslist: 1.7.7 + caniuse-db: 1.0.30001797 + lodash.memoize: 4.1.2 + lodash.uniq: 4.5.0 + + caniuse-db@1.0.30001797: {} + + caniuse-lite@1.0.30001797: {} + + cfb@1.2.2: + dependencies: + adler-32: 1.3.1 + crc-32: 1.2.2 + + chalk@1.1.3: + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + character-parser@2.2.0: + dependencies: + is-regex: 1.2.1 + + china-division@2.7.0: {} + + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + + chrome-trace-event@1.0.4: {} + + clap@1.2.3: + dependencies: + chalk: 1.1.3 + + class-utils@0.3.6: + dependencies: + arr-union: 3.1.0 + define-property: 0.2.5 + isobject: 3.0.1 + static-extend: 0.1.2 + + clone@1.0.4: {} + + clone@2.1.2: {} + + coa@1.0.4: + dependencies: + q: 1.5.1 + + codepage@1.15.0: {} + + collection-visit@1.0.0: + dependencies: + map-visit: 1.0.0 + object-visit: 1.0.1 + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color-string@0.3.0: + dependencies: + color-name: 1.1.4 + + color@0.11.4: + dependencies: + clone: 1.0.4 + color-convert: 1.9.3 + color-string: 0.3.0 + + colorette@2.0.20: {} + + colormin@1.1.2: + dependencies: + color: 0.11.4 + css-color-names: 0.0.4 + has: 1.0.4 + + colors@1.1.2: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@2.20.3: {} + + component-emitter@1.3.1: {} + + concat-map@0.0.1: + optional: true + + confbox@0.1.8: {} + + confbox@0.2.4: {} + + consola@3.4.2: {} + + consolidate@0.14.5(babel-core@6.26.3)(handlebars@4.7.8)(lodash@4.18.1): + dependencies: + bluebird: 3.7.2 + optionalDependencies: + babel-core: 6.26.3 + handlebars: 4.7.8 + lodash: 4.18.1 + + convert-source-map@1.9.0: + optional: true + + copy-anything@4.0.5: + dependencies: + is-what: 5.5.0 + + copy-descriptor@0.1.1: {} + + core-js@2.6.12: + optional: true + + cos-js-sdk-v5@1.10.1: + dependencies: + fast-xml-parser: 4.5.0 + + cosmiconfig@2.2.2: + dependencies: + is-directory: 0.3.1 + js-yaml: 3.14.2 + minimist: 1.2.8 + object-assign: 4.1.1 + os-homedir: 1.0.2 + parse-json: 2.2.0 + require-from-string: 1.2.1 + + crc-32@1.2.2: {} + + css-color-names@0.0.4: {} + + css-loader@0.28.0: + dependencies: + babel-code-frame: 6.26.0 + css-selector-tokenizer: 0.7.3 + cssnano: 3.10.0 + loader-utils: 1.4.2 + lodash.camelcase: 4.3.0 + object-assign: 4.1.1 + postcss: 5.2.18 + postcss-modules-extract-imports: 1.2.1 + postcss-modules-local-by-default: 1.2.0 + postcss-modules-scope: 1.1.0 + postcss-modules-values: 1.3.0 + source-list-map: 0.1.8 + + css-selector-tokenizer@0.7.3: + dependencies: + cssesc: 3.0.0 + fastparse: 1.1.2 + + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + + cssesc@3.0.0: {} + + cssnano@3.10.0: + dependencies: + autoprefixer: 6.7.7 + decamelize: 1.2.0 + defined: 1.0.1 + has: 1.0.4 + object-assign: 4.1.1 + postcss: 5.2.18 + postcss-calc: 5.3.1 + postcss-colormin: 2.2.2 + postcss-convert-values: 2.6.1 + postcss-discard-comments: 2.0.4 + postcss-discard-duplicates: 2.1.0 + postcss-discard-empty: 2.1.0 + postcss-discard-overridden: 0.1.1 + postcss-discard-unused: 2.2.3 + postcss-filter-plugins: 2.0.3 + postcss-merge-idents: 2.1.7 + postcss-merge-longhand: 2.0.2 + postcss-merge-rules: 2.1.2 + postcss-minify-font-values: 1.0.5 + postcss-minify-gradients: 1.0.5 + postcss-minify-params: 1.2.2 + postcss-minify-selectors: 2.1.1 + postcss-normalize-charset: 1.1.1 + postcss-normalize-url: 3.0.8 + postcss-ordered-values: 2.2.3 + postcss-reduce-idents: 2.4.0 + postcss-reduce-initial: 1.0.1 + postcss-reduce-transforms: 1.0.4 + postcss-svgo: 2.1.6 + postcss-unique-selectors: 2.0.2 + postcss-value-parser: 3.3.1 + postcss-zindex: 2.2.0 + + csso@2.3.2: + dependencies: + clap: 1.2.3 + source-map: 0.5.7 + + csstype@3.2.3: {} + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + dayjs@1.11.21: {} + + de-indent@1.0.2: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decamelize@1.2.0: {} + + decode-uri-component@0.2.2: {} + + deepmerge@1.3.2: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + define-property@0.2.5: + dependencies: + is-descriptor: 0.1.8 + + define-property@1.0.0: + dependencies: + is-descriptor: 1.0.4 + + define-property@2.0.2: + dependencies: + is-descriptor: 1.0.4 + isobject: 3.0.1 + + defined@1.0.1: {} + + defu@6.1.7: {} + + delayed-stream@1.0.0: {} + + destr@2.0.5: {} + + detect-indent@4.0.0: + dependencies: + repeating: 2.0.1 + optional: true + + detect-libc@2.1.2: {} + + dom-serializer@0.2.2: + dependencies: + domelementtype: 2.3.0 + entities: 2.2.0 + + domelementtype@1.3.1: {} + + domelementtype@2.3.0: {} + + domhandler@2.4.2: + dependencies: + domelementtype: 1.3.1 + + domready@1.0.8: {} + + domutils@1.7.0: + dependencies: + dom-serializer: 0.2.2 + domelementtype: 1.3.1 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexer@0.1.2: {} + + electron-to-chromium@1.5.371: {} + + element-china-area-data@6.1.0: + dependencies: + china-division: 2.7.0 + + element-plus@2.14.1(vue@3.5.35(typescript@6.0.3)): + dependencies: + '@ctrl/tinycolor': 4.2.0 + '@element-plus/icons-vue': 2.3.2(vue@3.5.35(typescript@6.0.3)) + '@floating-ui/dom': 1.7.6 + '@popperjs/core': '@sxzz/popperjs-es@2.11.8' + '@types/lodash': 4.17.24 + '@types/lodash-es': 4.17.12 + '@vueuse/core': 14.3.0(vue@3.5.35(typescript@6.0.3)) + async-validator: 4.2.5 + dayjs: 1.11.21 + lodash: 4.18.1 + lodash-es: 4.18.1 + lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.18.1)(lodash@4.18.1) + memoize-one: 6.0.0 + normalize-wheel-es: 1.2.0 + vue: 3.5.35(typescript@6.0.3) + vue-component-type-helpers: 3.3.4 + + emmet@2.4.11: + dependencies: + '@emmetio/abbreviation': 2.3.3 + '@emmetio/css-abbreviation': 2.1.8 + + emojis-list@3.0.0: {} + + enhanced-resolve@5.23.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + + entities@1.1.2: {} + + entities@2.2.0: {} + + entities@7.0.1: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + es-abstract@1.24.2: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.4 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.11 + string.prototype.trimend: 1.0.10 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.8 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.22 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@2.1.0: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + esbuild@0.27.3: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.3 + '@esbuild/android-arm': 0.27.3 + '@esbuild/android-arm64': 0.27.3 + '@esbuild/android-x64': 0.27.3 + '@esbuild/darwin-arm64': 0.27.3 + '@esbuild/darwin-x64': 0.27.3 + '@esbuild/freebsd-arm64': 0.27.3 + '@esbuild/freebsd-x64': 0.27.3 + '@esbuild/linux-arm': 0.27.3 + '@esbuild/linux-arm64': 0.27.3 + '@esbuild/linux-ia32': 0.27.3 + '@esbuild/linux-loong64': 0.27.3 + '@esbuild/linux-mips64el': 0.27.3 + '@esbuild/linux-ppc64': 0.27.3 + '@esbuild/linux-riscv64': 0.27.3 + '@esbuild/linux-s390x': 0.27.3 + '@esbuild/linux-x64': 0.27.3 + '@esbuild/netbsd-arm64': 0.27.3 + '@esbuild/netbsd-x64': 0.27.3 + '@esbuild/openbsd-arm64': 0.27.3 + '@esbuild/openbsd-x64': 0.27.3 + '@esbuild/openharmony-arm64': 0.27.3 + '@esbuild/sunos-x64': 0.27.3 + '@esbuild/win32-arm64': 0.27.3 + '@esbuild/win32-ia32': 0.27.3 + '@esbuild/win32-x64': 0.27.3 + optional: true + + escalade@3.2.0: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@5.0.0: {} + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + esprima@2.7.3: {} + + esprima@4.0.1: {} + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@4.3.0: {} + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + esutils@2.0.3: {} + + events@3.3.0: {} + + expand-brackets@2.1.4: + dependencies: + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + exsolve@1.0.8: {} + + extend-shallow@2.0.1: + dependencies: + is-extendable: 0.1.1 + + extend-shallow@3.0.2: + dependencies: + assign-symbols: 1.0.0 + is-extendable: 1.0.1 + + extglob@2.0.4: + dependencies: + array-unique: 0.3.2 + define-property: 1.0.0 + expand-brackets: 2.1.4 + extend-shallow: 2.0.1 + fragment-cache: 0.2.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + fast-deep-equal@3.1.3: {} + + fast-uri@3.1.2: {} + + fast-xml-parser@4.5.0: + dependencies: + strnum: 1.1.2 + + fastparse@1.1.2: {} + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + fill-range@4.0.0: + dependencies: + extend-shallow: 2.0.1 + is-number: 3.0.0 + repeat-string: 1.6.1 + to-regex-range: 2.1.1 + + flatten@1.0.3: {} + + follow-redirects@1.16.0: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + for-in@1.0.2: {} + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.4 + mime-types: 2.1.35 + + frac@1.1.2: {} + + fragment-cache@0.2.1: + dependencies: + map-cache: 0.2.2 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.4 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + generator-function@2.0.1: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + get-value@2.0.6: {} + + glob-to-regexp@0.4.1: {} + + globals@9.18.0: + optional: true + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + + handlebars@4.7.8: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.19.3 + optional: true + + has-ansi@2.0.0: + dependencies: + ansi-regex: 2.1.1 + + has-bigints@1.1.0: {} + + has-flag@1.0.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + has-value@0.3.1: + dependencies: + get-value: 2.0.6 + has-values: 0.1.4 + isobject: 2.1.0 + + has-value@1.0.0: + dependencies: + get-value: 2.0.6 + has-values: 1.0.0 + isobject: 3.0.1 + + has-values@0.1.4: {} + + has-values@1.0.0: + dependencies: + is-number: 3.0.0 + kind-of: 4.0.0 + + has@1.0.4: {} + + hash-sum@1.0.2: {} + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + home-or-tmp@2.0.0: + dependencies: + os-homedir: 1.0.2 + os-tmpdir: 1.0.2 + optional: true + + hookable@5.5.3: {} + + html-comment-regex@1.1.2: {} + + htmlparser2@3.10.1: + dependencies: + domelementtype: 1.3.1 + domhandler: 2.4.2 + domutils: 1.7.0 + entities: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.2 + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + icss-replace-symbols@1.1.0: {} + + idb-keyval@6.2.5: {} + + image-size@0.5.5: {} + + immutable@5.1.6: {} + + import-meta-resolve@4.2.0: {} + + indexes-of@1.0.1: {} + + inherits@2.0.4: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.4 + side-channel: 1.1.1 + + invariant@2.2.4: + dependencies: + loose-envify: 1.4.0 + optional: true + + is-absolute-url@2.1.0: {} + + is-accessor-descriptor@1.0.2: + dependencies: + hasown: 2.0.4 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-arrayish@0.2.1: {} + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-buffer@1.1.6: {} + + is-callable@1.2.7: {} + + is-core-module@2.16.2: + dependencies: + hasown: 2.0.4 + + is-data-descriptor@1.0.1: + dependencies: + hasown: 2.0.4 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-descriptor@0.1.8: + dependencies: + is-accessor-descriptor: 1.0.2 + is-data-descriptor: 1.0.1 + + is-descriptor@1.0.4: + dependencies: + is-accessor-descriptor: 1.0.2 + is-data-descriptor: 1.0.1 + + is-directory@0.3.1: {} + + is-expression@4.0.0: + dependencies: + acorn: 7.4.1 + object-assign: 4.1.1 + + is-extendable@0.1.1: {} + + is-extendable@1.0.1: + dependencies: + is-plain-object: 2.0.4 + + is-extglob@2.1.1: + optional: true + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-finite@1.1.0: + optional: true + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + optional: true + + is-map@2.0.3: {} + + is-negative-zero@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@3.0.0: + dependencies: + kind-of: 3.2.2 + + is-plain-obj@1.1.0: {} + + is-plain-object@2.0.4: + dependencies: + isobject: 3.0.1 + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-svg@2.1.0: + dependencies: + html-comment-regex: 1.1.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.22 + + is-url@1.2.4: {} + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-what@5.5.0: {} + + is-windows@1.0.2: {} + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isobject@2.1.0: + dependencies: + isarray: 1.0.0 + + isobject@3.0.1: {} + + jest-worker@27.5.1: + dependencies: + '@types/node': 25.9.2 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jiti@2.7.0: {} + + js-base64@2.6.4: {} + + js-tokens@3.0.2: {} + + js-tokens@4.0.0: + optional: true + + js-tokens@9.0.1: {} + + js-yaml@3.14.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@3.7.0: + dependencies: + argparse: 1.0.10 + esprima: 2.7.3 + + jsesc@1.3.0: + optional: true + + jsesc@3.1.0: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@1.0.0: {} + + json5@0.5.1: + optional: true + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsonc-parser@2.3.1: {} + + jsonc-parser@3.3.1: {} + + kind-of@3.2.2: + dependencies: + is-buffer: 1.1.6 + + kind-of@4.0.0: + dependencies: + is-buffer: 1.1.6 + + kind-of@5.1.0: {} + + kind-of@6.0.3: {} + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + loader-runner@4.3.2: {} + + loader-utils@1.4.2: + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 1.0.2 + + local-pkg@1.2.1: + dependencies: + mlly: 1.8.2 + pkg-types: 2.3.1 + quansync: 0.2.11 + + lodash-es@4.18.1: {} + + lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.18.1)(lodash@4.18.1): + dependencies: + '@types/lodash-es': 4.17.12 + lodash: 4.18.1 + lodash-es: 4.18.1 + + lodash.camelcase@4.3.0: {} + + lodash.memoize@4.1.2: {} + + lodash.uniq@4.5.0: {} + + lodash@4.18.1: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + optional: true + + lru-cache@4.1.5: + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 + + magic-regexp@0.10.0: + dependencies: + estree-walker: 3.0.3 + magic-string: 0.30.21 + mlly: 1.8.2 + regexp-tree: 0.1.27 + type-level-regexp: 0.1.17 + ufo: 1.6.4 + unplugin: 2.3.11 + + magic-string-ast@1.0.3: + dependencies: + magic-string: 0.30.21 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + map-cache@0.2.2: {} + + map-visit@1.0.0: + dependencies: + object-visit: 1.0.1 + + math-expression-evaluator@1.4.0: {} + + math-intrinsics@1.1.0: {} + + mdn-data@2.27.1: {} + + memoize-one@6.0.0: {} + + merge-options@1.0.1: + dependencies: + is-plain-obj: 1.1.0 + + merge-stream@2.0.0: {} + + micromatch@3.1.0: + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2 + define-property: 1.0.0 + extend-shallow: 2.0.1 + extglob: 2.0.4 + fragment-cache: 0.2.1 + kind-of: 5.1.0 + nanomatch: 1.2.13 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.15 + optional: true + + minimist@1.2.8: {} + + mitt@1.1.2: {} + + mitt@3.0.1: {} + + mixin-deep@1.3.2: + dependencies: + for-in: 1.0.2 + is-extendable: 1.0.1 + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + mlly@1.8.2: + dependencies: + acorn: 8.16.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.4 + + mrmime@2.0.1: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + muggle-string@0.4.1: {} + + nanoid@3.3.12: {} + + nanomatch@1.2.13: + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + fragment-cache: 0.2.1 + is-windows: 1.0.2 + kind-of: 6.0.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + neo-async@2.6.2: {} + + node-addon-api@7.1.1: + optional: true + + node-fetch-native@1.6.7: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-releases@2.0.47: {} + + normalize-range@0.1.2: {} + + normalize-url@1.9.1: + dependencies: + object-assign: 4.1.1 + prepend-http: 1.0.4 + query-string: 4.3.4 + sort-keys: 1.1.2 + + normalize-wheel-es@1.2.0: {} + + num2fraction@1.2.2: {} + + object-assign@4.1.1: {} + + object-copy@0.1.0: + dependencies: + copy-descriptor: 0.1.1 + define-property: 0.2.5 + kind-of: 3.2.2 + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object-visit@1.0.1: + dependencies: + isobject: 3.0.1 + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.pick@1.3.0: + dependencies: + isobject: 3.0.1 + + obug@2.1.2: {} + + ofetch@1.5.1: + dependencies: + destr: 2.0.5 + node-fetch-native: 1.6.7 + ufo: 1.6.4 + + opencollective-postinstall@2.0.3: {} + + os-homedir@1.0.2: {} + + os-tmpdir@1.0.2: + optional: true + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + oxc-parser@0.131.0: + dependencies: + '@oxc-project/types': 0.131.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.131.0 + '@oxc-parser/binding-android-arm64': 0.131.0 + '@oxc-parser/binding-darwin-arm64': 0.131.0 + '@oxc-parser/binding-darwin-x64': 0.131.0 + '@oxc-parser/binding-freebsd-x64': 0.131.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.131.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.131.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.131.0 + '@oxc-parser/binding-linux-arm64-musl': 0.131.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.131.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.131.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.131.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.131.0 + '@oxc-parser/binding-linux-x64-gnu': 0.131.0 + '@oxc-parser/binding-linux-x64-musl': 0.131.0 + '@oxc-parser/binding-openharmony-arm64': 0.131.0 + '@oxc-parser/binding-wasm32-wasi': 0.131.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.131.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.131.0 + '@oxc-parser/binding-win32-x64-msvc': 0.131.0 + + oxc-walker@0.7.0(oxc-parser@0.131.0): + dependencies: + magic-regexp: 0.10.0 + oxc-parser: 0.131.0 + + package-manager-detector@1.6.0: {} + + parse-json@2.2.0: + dependencies: + error-ex: 1.3.4 + + pascalcase@0.1.1: {} + + path-browserify@1.0.1: {} + + path-is-absolute@1.0.1: + optional: true + + path-parse@1.0.7: {} + + pathe@2.0.3: {} + + perfect-debounce@1.0.0: {} + + perfect-debounce@2.1.0: {} + + picocolors@1.1.1: {} + + picomatch@4.0.4: {} + + pinia@3.0.4(typescript@6.0.3)(vue@3.5.35(typescript@6.0.3)): + dependencies: + '@vue/devtools-api': 7.7.9 + vue: 3.5.35(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.2 + pathe: 2.0.3 + + pkg-types@2.3.1: + dependencies: + confbox: 0.2.4 + exsolve: 1.0.8 + pathe: 2.0.3 + + posix-character-classes@0.1.1: {} + + possible-typed-array-names@1.1.0: {} + + postcss-calc@5.3.1: + dependencies: + postcss: 5.2.18 + postcss-message-helpers: 2.0.0 + reduce-css-calc: 1.3.0 + + postcss-colormin@2.2.2: + dependencies: + colormin: 1.1.2 + postcss: 5.2.18 + postcss-value-parser: 3.3.1 + + postcss-convert-values@2.6.1: + dependencies: + postcss: 5.2.18 + postcss-value-parser: 3.3.1 + + postcss-discard-comments@2.0.4: + dependencies: + postcss: 5.2.18 + + postcss-discard-duplicates@2.1.0: + dependencies: + postcss: 5.2.18 + + postcss-discard-empty@2.1.0: + dependencies: + postcss: 5.2.18 + + postcss-discard-overridden@0.1.1: + dependencies: + postcss: 5.2.18 + + postcss-discard-unused@2.2.3: + dependencies: + postcss: 5.2.18 + uniqs: 2.0.0 + + postcss-filter-plugins@2.0.3: + dependencies: + postcss: 5.2.18 + + postcss-load-config@1.2.0: + dependencies: + cosmiconfig: 2.2.2 + object-assign: 4.1.1 + postcss-load-options: 1.2.0 + postcss-load-plugins: 2.3.0 + + postcss-load-options@1.2.0: + dependencies: + cosmiconfig: 2.2.2 + object-assign: 4.1.1 + + postcss-load-plugins@2.3.0: + dependencies: + cosmiconfig: 2.2.2 + object-assign: 4.1.1 + + postcss-merge-idents@2.1.7: + dependencies: + has: 1.0.4 + postcss: 5.2.18 + postcss-value-parser: 3.3.1 + + postcss-merge-longhand@2.0.2: + dependencies: + postcss: 5.2.18 + + postcss-merge-rules@2.1.2: + dependencies: + browserslist: 1.7.7 + caniuse-api: 1.6.1 + postcss: 5.2.18 + postcss-selector-parser: 2.2.3 + vendors: 1.0.4 + + postcss-message-helpers@2.0.0: {} + + postcss-minify-font-values@1.0.5: + dependencies: + object-assign: 4.1.1 + postcss: 5.2.18 + postcss-value-parser: 3.3.1 + + postcss-minify-gradients@1.0.5: + dependencies: + postcss: 5.2.18 + postcss-value-parser: 3.3.1 + + postcss-minify-params@1.2.2: + dependencies: + alphanum-sort: 1.0.2 + postcss: 5.2.18 + postcss-value-parser: 3.3.1 + uniqs: 2.0.0 + + postcss-minify-selectors@2.1.1: + dependencies: + alphanum-sort: 1.0.2 + has: 1.0.4 + postcss: 5.2.18 + postcss-selector-parser: 2.2.3 + + postcss-modules-extract-imports@1.2.1: + dependencies: + postcss: 6.0.23 + + postcss-modules-local-by-default@1.2.0: + dependencies: + css-selector-tokenizer: 0.7.3 + postcss: 6.0.23 + + postcss-modules-scope@1.1.0: + dependencies: + css-selector-tokenizer: 0.7.3 + postcss: 6.0.23 + + postcss-modules-values@1.3.0: + dependencies: + icss-replace-symbols: 1.1.0 + postcss: 6.0.23 + + postcss-normalize-charset@1.1.1: + dependencies: + postcss: 5.2.18 + + postcss-normalize-url@3.0.8: + dependencies: + is-absolute-url: 2.1.0 + normalize-url: 1.9.1 + postcss: 5.2.18 + postcss-value-parser: 3.3.1 + + postcss-ordered-values@2.2.3: + dependencies: + postcss: 5.2.18 + postcss-value-parser: 3.3.1 + + postcss-prefix-selector@1.16.1(postcss@5.2.18): + dependencies: + postcss: 5.2.18 + + postcss-reduce-idents@2.4.0: + dependencies: + postcss: 5.2.18 + postcss-value-parser: 3.3.1 + + postcss-reduce-initial@1.0.1: + dependencies: + postcss: 5.2.18 + + postcss-reduce-transforms@1.0.4: + dependencies: + has: 1.0.4 + postcss: 5.2.18 + postcss-value-parser: 3.3.1 + + postcss-selector-parser@2.2.3: + dependencies: + flatten: 1.0.3 + indexes-of: 1.0.1 + uniq: 1.0.1 + + postcss-svgo@2.1.6: + dependencies: + is-svg: 2.1.0 + postcss: 5.2.18 + postcss-value-parser: 3.3.1 + svgo: 0.7.2 + + postcss-unique-selectors@2.0.2: + dependencies: + alphanum-sort: 1.0.2 + postcss: 5.2.18 + uniqs: 2.0.0 + + postcss-value-parser@3.3.1: {} + + postcss-zindex@2.2.0: + dependencies: + has: 1.0.4 + postcss: 5.2.18 + uniqs: 2.0.0 + + postcss@5.2.18: + dependencies: + chalk: 1.1.3 + js-base64: 2.6.4 + source-map: 0.5.7 + supports-color: 3.2.3 + + postcss@6.0.23: + dependencies: + chalk: 2.4.2 + source-map: 0.6.1 + supports-color: 5.5.0 + + postcss@8.5.15: + dependencies: + nanoid: 3.3.12 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + posthtml-parser@0.2.1: + dependencies: + htmlparser2: 3.10.1 + isobject: 2.1.0 + + posthtml-rename-id@1.0.12: + dependencies: + escape-string-regexp: 1.0.5 + + posthtml-render@1.4.0: {} + + posthtml-svg-mode@1.0.3: + dependencies: + merge-options: 1.0.1 + posthtml: 0.9.2 + posthtml-parser: 0.2.1 + posthtml-render: 1.4.0 + + posthtml@0.9.2: + dependencies: + posthtml-parser: 0.2.1 + posthtml-render: 1.4.0 + + prepend-http@1.0.4: {} + + prettier@1.19.1: {} + + private@0.1.8: + optional: true + + proxy-from-env@2.1.0: {} + + pseudomap@1.0.2: {} + + pug-error@2.1.0: {} + + pug-lexer@5.0.1: + dependencies: + character-parser: 2.2.0 + is-expression: 4.0.0 + pug-error: 2.1.0 + + pug-parser@6.0.0: + dependencies: + pug-error: 2.1.0 + token-stream: 1.0.0 + + q@1.5.1: {} + + qs@6.15.2: + dependencies: + side-channel: 1.1.1 + + quansync@0.2.11: {} + + quansync@1.0.0: {} + + query-string@4.3.4: + dependencies: + object-assign: 4.1.1 + strict-uri-encode: 1.1.0 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@5.0.0: {} + + reduce-css-calc@1.3.0: + dependencies: + balanced-match: 0.4.2 + math-expression-evaluator: 1.4.0 + reduce-function-call: 1.0.3 + + reduce-function-call@1.0.3: + dependencies: + balanced-match: 1.0.2 + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regenerator-runtime@0.11.1: + optional: true + + regenerator-runtime@0.13.11: {} + + regex-not@1.0.2: + dependencies: + extend-shallow: 3.0.2 + safe-regex: 1.1.0 + + regexp-tree@0.1.27: {} + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + repeat-element@1.1.4: {} + + repeat-string@1.6.1: {} + + repeating@2.0.1: + dependencies: + is-finite: 1.1.0 + optional: true + + request-light@0.7.0: {} + + require-from-string@1.2.1: {} + + require-from-string@2.0.2: {} + + resolve-url@0.2.1: {} + + resolve@1.22.12: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.2 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + ret@0.1.15: {} + + rfdc@1.4.1: {} + + rolldown@1.0.3: + dependencies: + '@oxc-project/types': 0.133.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.3 + '@rolldown/binding-darwin-arm64': 1.0.3 + '@rolldown/binding-darwin-x64': 1.0.3 + '@rolldown/binding-freebsd-x64': 1.0.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.3 + '@rolldown/binding-linux-arm64-gnu': 1.0.3 + '@rolldown/binding-linux-arm64-musl': 1.0.3 + '@rolldown/binding-linux-ppc64-gnu': 1.0.3 + '@rolldown/binding-linux-s390x-gnu': 1.0.3 + '@rolldown/binding-linux-x64-gnu': 1.0.3 + '@rolldown/binding-linux-x64-musl': 1.0.3 + '@rolldown/binding-openharmony-arm64': 1.0.3 + '@rolldown/binding-wasm32-wasi': 1.0.3 + '@rolldown/binding-win32-arm64-msvc': 1.0.3 + '@rolldown/binding-win32-x64-msvc': 1.0.3 + + safe-array-concat@1.1.4: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.2.1: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safe-regex@1.1.0: + dependencies: + ret: 0.1.15 + + sass@1.100.0: + dependencies: + chokidar: 5.0.0 + immutable: 5.1.6 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.6 + + sax@1.2.4: {} + + schema-utils@4.3.3: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.20.0 + ajv-formats: 2.1.1(ajv@8.20.0) + ajv-keywords: 5.1.0(ajv@8.20.0) + + scule@1.3.0: {} + + semver@7.8.4: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + + set-value@2.0.1: + dependencies: + extend-shallow: 2.0.1 + is-extendable: 0.1.1 + is-plain-object: 2.0.4 + split-string: 3.1.0 + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + sirv@3.0.2: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + + slash@1.0.0: + optional: true + + snapdragon-node@2.1.1: + dependencies: + define-property: 1.0.0 + isobject: 3.0.1 + snapdragon-util: 3.0.1 + + snapdragon-util@3.0.1: + dependencies: + kind-of: 3.2.2 + + snapdragon@0.8.2: + dependencies: + base: 0.11.2 + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + transitivePeerDependencies: + - supports-color + + sort-keys@1.1.2: + dependencies: + is-plain-obj: 1.1.0 + + source-list-map@0.1.8: {} + + source-map-js@1.2.1: {} + + source-map-resolve@0.5.3: + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.2 + resolve-url: 0.2.1 + source-map-url: 0.4.1 + urix: 0.1.0 + + source-map-support@0.4.18: + dependencies: + source-map: 0.5.7 + optional: true + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map-url@0.4.1: {} + + source-map@0.5.7: {} + + source-map@0.6.1: {} + + speakingurl@14.0.1: {} + + split-string@3.1.0: + dependencies: + extend-shallow: 3.0.2 + + sprintf-js@1.0.3: {} + + ssf@0.11.2: + dependencies: + frac: 1.1.2 + + static-extend@0.1.2: + dependencies: + define-property: 0.2.5 + object-copy: 0.1.0 + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + strict-uri-encode@1.1.0: {} + + string.prototype.trim@1.2.11: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + has-property-descriptors: 1.0.2 + safe-regex-test: 1.1.0 + + string.prototype.trimend@1.0.10: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@3.0.1: + dependencies: + ansi-regex: 2.1.1 + + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 + + strnum@1.1.2: {} + + superjson@2.2.6: + dependencies: + copy-anything: 4.0.5 + + supports-color@2.0.0: {} + + supports-color@3.2.3: + dependencies: + has-flag: 1.0.0 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svg-baker-runtime@1.4.7: + dependencies: + deepmerge: 1.3.2 + mitt: 1.1.2 + svg-baker: 1.7.0 + transitivePeerDependencies: + - supports-color + + svg-baker@1.7.0: + dependencies: + bluebird: 3.7.2 + clone: 2.1.2 + he: 1.2.0 + image-size: 0.5.5 + loader-utils: 1.4.2 + merge-options: 1.0.1 + micromatch: 3.1.0 + postcss: 5.2.18 + postcss-prefix-selector: 1.16.1(postcss@5.2.18) + posthtml-rename-id: 1.0.12 + posthtml-svg-mode: 1.0.3 + query-string: 4.3.4 + traverse: 0.6.11 + transitivePeerDependencies: + - supports-color + + svg-sprite-loader@3.7.3: + dependencies: + bluebird: 3.7.2 + deepmerge: 1.3.2 + domready: 1.0.8 + escape-string-regexp: 1.0.5 + loader-utils: 1.4.2 + svg-baker: 1.7.0 + svg-baker-runtime: 1.4.7 + url-slug: 2.0.0 + transitivePeerDependencies: + - supports-color + + svgo@0.7.2: + dependencies: + coa: 1.0.4 + colors: 1.1.2 + csso: 2.3.2 + js-yaml: 3.7.0 + mkdirp: 0.5.6 + sax: 1.2.4 + whet.extend: 0.9.9 + + tapable@2.3.3: {} + + terser-webpack-plugin@5.6.1(esbuild@0.27.3)(postcss@5.2.18)(webpack@5.105.4(esbuild@0.27.3)(postcss@5.2.18)): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + jest-worker: 27.5.1 + schema-utils: 4.3.3 + terser: 5.48.0 + webpack: 5.105.4(esbuild@0.27.3)(postcss@5.2.18) + optionalDependencies: + esbuild: 0.27.3 + postcss: 5.2.18 + + terser@5.48.0: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.16.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + tesseract.js-core@7.0.0: {} + + tesseract.js@7.0.0: + dependencies: + bmp-js: 0.1.0 + idb-keyval: 6.2.5 + is-url: 1.2.4 + node-fetch: 2.7.0 + opencollective-postinstall: 2.0.3 + regenerator-runtime: 0.13.11 + tesseract.js-core: 7.0.0 + wasm-feature-detect: 1.8.0 + zlibjs: 0.3.1 + transitivePeerDependencies: + - encoding + + tiny-cookie@1.0.1: {} + + tinyexec@1.2.4: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + to-fast-properties@1.0.3: + optional: true + + to-object-path@0.3.0: + dependencies: + kind-of: 3.2.2 + + to-regex-range@2.1.1: + dependencies: + is-number: 3.0.0 + repeat-string: 1.6.1 + + to-regex@3.0.2: + dependencies: + define-property: 2.0.2 + extend-shallow: 3.0.2 + regex-not: 1.0.2 + safe-regex: 1.1.0 + + token-stream@1.0.0: {} + + totalist@3.0.1: {} + + tr46@0.0.3: {} + + traverse@0.6.11: + dependencies: + gopd: 1.2.0 + typedarray.prototype.slice: 1.0.5 + which-typed-array: 1.1.22 + + trim-right@1.0.1: + optional: true + + tslib@2.8.1: + optional: true + + type-level-regexp@0.1.17: {} + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.8: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typedarray.prototype.slice@1.0.5: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + get-proto: 1.0.1 + math-intrinsics: 1.1.0 + typed-array-buffer: 1.0.3 + typed-array-byte-offset: 1.0.4 + + typescript-auto-import-cache@0.3.6: + dependencies: + semver: 7.8.4 + + typescript@6.0.3: {} + + ufo@1.6.4: {} + + uglify-js@3.19.3: + optional: true + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + unconfig-core@7.5.0: + dependencies: + '@quansync/fs': 1.0.0 + quansync: 1.0.0 + + unconfig@7.5.0: + dependencies: + '@quansync/fs': 1.0.0 + defu: 6.1.7 + jiti: 2.7.0 + quansync: 1.0.0 + unconfig-core: 7.5.0 + + undici-types@7.24.6: {} + + unidecode@0.1.8: {} + + unimport@5.7.0: + dependencies: + acorn: 8.16.0 + escape-string-regexp: 5.0.0 + estree-walker: 3.0.3 + local-pkg: 1.2.1 + magic-string: 0.30.21 + mlly: 1.8.2 + pathe: 2.0.3 + picomatch: 4.0.4 + pkg-types: 2.3.1 + scule: 1.3.0 + strip-literal: 3.1.0 + tinyglobby: 0.2.17 + unplugin: 2.3.11 + unplugin-utils: 0.3.1 + + union-value@1.0.1: + dependencies: + arr-union: 3.1.0 + get-value: 2.0.6 + is-extendable: 0.1.1 + set-value: 2.0.1 + + uniq@1.0.1: {} + + uniqs@2.0.0: {} + + unocss@66.7.0(vite@8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0)): + dependencies: + '@unocss/cli': 66.7.0 + '@unocss/core': 66.7.0 + '@unocss/preset-attributify': 66.7.0 + '@unocss/preset-icons': 66.7.0 + '@unocss/preset-mini': 66.7.0 + '@unocss/preset-tagify': 66.7.0 + '@unocss/preset-typography': 66.7.0 + '@unocss/preset-uno': 66.7.0 + '@unocss/preset-web-fonts': 66.7.0 + '@unocss/preset-wind': 66.7.0 + '@unocss/preset-wind3': 66.7.0 + '@unocss/preset-wind4': 66.7.0 + '@unocss/transformer-attributify-jsx': 66.7.0 + '@unocss/transformer-compile-class': 66.7.0 + '@unocss/transformer-directives': 66.7.0 + '@unocss/transformer-variant-group': 66.7.0 + '@unocss/vite': 66.7.0(vite@8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0)) + transitivePeerDependencies: + - vite + + unplugin-auto-import@21.0.0(@vueuse/core@14.3.0(vue@3.5.35(typescript@6.0.3))): + dependencies: + local-pkg: 1.2.1 + magic-string: 0.30.21 + picomatch: 4.0.4 + unimport: 5.7.0 + unplugin: 2.3.11 + unplugin-utils: 0.3.1 + optionalDependencies: + '@vueuse/core': 14.3.0(vue@3.5.35(typescript@6.0.3)) + + unplugin-utils@0.3.1: + dependencies: + pathe: 2.0.3 + picomatch: 4.0.4 + + unplugin-vue-components@31.1.0(vue@3.5.35(typescript@6.0.3)): + dependencies: + chokidar: 5.0.0 + local-pkg: 1.2.1 + magic-string: 0.30.21 + mlly: 1.8.2 + obug: 2.1.2 + picomatch: 4.0.4 + tinyglobby: 0.2.17 + unplugin: 2.3.11 + unplugin-utils: 0.3.1 + vue: 3.5.35(typescript@6.0.3) + + unplugin@2.3.11: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.16.0 + picomatch: 4.0.4 + webpack-virtual-modules: 0.6.2 + + unplugin@3.0.0: + dependencies: + '@jridgewell/remapping': 2.3.5 + picomatch: 4.0.4 + webpack-virtual-modules: 0.6.2 + + unset-value@1.0.0: + dependencies: + has-value: 0.3.1 + isobject: 3.0.1 + + update-browserslist-db@1.2.3(browserslist@4.28.2): + dependencies: + browserslist: 4.28.2 + escalade: 3.2.0 + picocolors: 1.1.1 + + urix@0.1.0: {} + + url-slug@2.0.0: + dependencies: + unidecode: 0.1.8 + + use@3.1.1: {} + + util-deprecate@1.0.2: {} + + vendors@1.0.4: {} + + vite@8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.15 + rolldown: 1.0.3 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 25.9.2 + esbuild: 0.27.3 + fsevents: 2.3.3 + jiti: 2.7.0 + sass: 1.100.0 + terser: 5.48.0 + yaml: 2.9.0 + + volar-service-css@0.0.71(@volar/language-service@2.4.28): + dependencies: + vscode-css-languageservice: 6.3.10 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-emmet@0.0.71(@volar/language-service@2.4.28): + dependencies: + '@emmetio/css-parser': 0.4.1 + '@emmetio/html-matcher': 1.3.0 + '@vscode/emmet-helper': 2.11.0 + vscode-uri: 3.1.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-html@0.0.71(@volar/language-service@2.4.28): + dependencies: + vscode-html-languageservice: 5.6.2 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-json@0.0.71(@volar/language-service@2.4.28): + dependencies: + vscode-json-languageservice: 5.7.2 + vscode-uri: 3.1.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-pug-beautify@0.0.71(@volar/language-service@2.4.28): + dependencies: + '@johnsoncodehk/pug-beautify': 0.2.2 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-pug@0.0.71: + dependencies: + '@volar/language-service': 2.4.28 + '@vue/language-plugin-pug': 3.2.9 + volar-service-html: 0.0.71(@volar/language-service@2.4.28) + vscode-html-languageservice: 5.6.2 + vscode-languageserver-textdocument: 1.0.12 + + volar-service-typescript@0.0.71(@volar/language-service@2.4.28): + dependencies: + path-browserify: 1.0.1 + semver: 7.8.4 + typescript-auto-import-cache: 0.3.6 + vscode-languageserver-textdocument: 1.0.12 + vscode-nls: 5.2.0 + vscode-uri: 3.1.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + vscode-css-languageservice@6.3.10: + dependencies: + '@vscode/l10n': 0.0.18 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.1.0 + + vscode-html-languageservice@5.6.2: + dependencies: + '@vscode/l10n': 0.0.18 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.18.0 + vscode-uri: 3.1.0 + + vscode-json-languageservice@5.7.2: + dependencies: + '@vscode/l10n': 0.0.18 + jsonc-parser: 3.3.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.18.0 + vscode-uri: 3.1.0 + + vscode-jsonrpc@8.2.0: {} + + vscode-jsonrpc@9.0.0: {} + + vscode-languageserver-protocol@3.17.5: + dependencies: + vscode-jsonrpc: 8.2.0 + vscode-languageserver-types: 3.17.5 + + vscode-languageserver-protocol@3.18.0: + dependencies: + vscode-jsonrpc: 9.0.0 + vscode-languageserver-types: 3.18.0 + + vscode-languageserver-textdocument@1.0.12: {} + + vscode-languageserver-types@3.17.5: {} + + vscode-languageserver-types@3.18.0: {} + + vscode-languageserver@9.0.1: + dependencies: + vscode-languageserver-protocol: 3.17.5 + + vscode-nls@5.2.0: {} + + vscode-uri@3.1.0: {} + + vue-component-meta@3.3.4(typescript@6.0.3): + dependencies: + '@volar/typescript': 2.4.28 + '@vue/language-core': 3.3.4 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 6.0.3 + + vue-component-type-helpers@3.3.4: {} + + vue-cookie@1.1.4: + dependencies: + tiny-cookie: 1.0.1 + + vue-hot-reload-api@2.3.4: {} + + vue-loader@13.7.3(@vue/compiler-sfc@3.5.35)(babel-core@6.26.3)(css-loader@0.28.0)(handlebars@4.7.8)(lodash@4.18.1)(vue-template-compiler@2.7.16)(webpack@5.105.4(esbuild@0.27.3)(postcss@5.2.18)): + dependencies: + consolidate: 0.14.5(babel-core@6.26.3)(handlebars@4.7.8)(lodash@4.18.1) + css-loader: 0.28.0 + hash-sum: 1.0.2 + loader-utils: 1.4.2 + lru-cache: 4.1.5 + postcss: 6.0.23 + postcss-load-config: 1.2.0 + postcss-selector-parser: 2.2.3 + prettier: 1.19.1 + resolve: 1.22.12 + source-map: 0.6.1 + vue-hot-reload-api: 2.3.4 + vue-style-loader: 3.1.2 + vue-template-compiler: 2.7.16 + vue-template-es2015-compiler: 1.9.1 + webpack: 5.105.4(esbuild@0.27.3)(postcss@5.2.18) + optionalDependencies: + '@vue/compiler-sfc': 3.5.35 + transitivePeerDependencies: + - arc-templates + - atpl + - babel-core + - bracket-template + - coffee-script + - dot + - dust + - dustjs-helpers + - dustjs-linkedin + - eco + - ect + - ejs + - haml-coffee + - hamlet + - hamljs + - handlebars + - hogan.js + - htmling + - jade + - jazz + - jqtpl + - just + - liquid-node + - liquor + - lodash + - marko + - mote + - mustache + - nunjucks + - plates + - pug + - qejs + - ractive + - razor-tmpl + - react + - react-dom + - slm + - squirrelly + - swig + - swig-templates + - teacup + - templayed + - then-jade + - then-pug + - tinyliquid + - toffee + - twig + - twing + - underscore + - vash + - velocityjs + - walrus + - whiskers + + vue-router@5.1.0(@vue/compiler-sfc@3.5.35)(pinia@3.0.4(typescript@6.0.3)(vue@3.5.35(typescript@6.0.3)))(vite@8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0))(vue@3.5.35(typescript@6.0.3)): + dependencies: + '@babel/generator': 8.0.0-rc.6 + '@vue-macros/common': 3.1.2(vue@3.5.35(typescript@6.0.3)) + '@vue/devtools-api': 8.1.2 + ast-walker-scope: 0.9.0 + chokidar: 5.0.0 + json5: 2.2.3 + local-pkg: 1.2.1 + magic-string: 0.30.21 + mlly: 1.8.2 + muggle-string: 0.4.1 + pathe: 2.0.3 + picomatch: 4.0.4 + scule: 1.3.0 + tinyglobby: 0.2.17 + unplugin: 3.0.0 + unplugin-utils: 0.3.1 + vue: 3.5.35(typescript@6.0.3) + yaml: 2.9.0 + optionalDependencies: + '@vue/compiler-sfc': 3.5.35 + pinia: 3.0.4(typescript@6.0.3)(vue@3.5.35(typescript@6.0.3)) + vite: 8.0.16(@types/node@25.9.2)(esbuild@0.27.3)(jiti@2.7.0)(sass@1.100.0)(terser@5.48.0)(yaml@2.9.0) + + vue-style-loader@3.1.2: + dependencies: + hash-sum: 1.0.2 + loader-utils: 1.4.2 + + vue-template-compiler@2.7.16: + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + + vue-template-es2015-compiler@1.9.1: {} + + vue-tsc@3.3.4(typescript@6.0.3): + dependencies: + '@volar/typescript': 2.4.28 + '@vue/language-core': 3.3.4 + typescript: 6.0.3 + + vue@3.5.35(typescript@6.0.3): + dependencies: + '@vue/compiler-dom': 3.5.35 + '@vue/compiler-sfc': 3.5.35 + '@vue/runtime-dom': 3.5.35 + '@vue/server-renderer': 3.5.35(vue@3.5.35(typescript@6.0.3)) + '@vue/shared': 3.5.35 + optionalDependencies: + typescript: 6.0.3 + + wasm-feature-detect@1.8.0: {} + + watchpack@2.5.1: + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + + webidl-conversions@3.0.1: {} + + webpack-sources@3.5.0: {} + + webpack-virtual-modules@0.6.2: {} + + webpack@5.105.4(esbuild@0.27.3)(postcss@5.2.18): + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.9 + '@types/json-schema': 7.0.15 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.16.0 + acorn-import-phases: 1.0.4(acorn@8.16.0) + browserslist: 4.28.2 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.23.0 + es-module-lexer: 2.1.0 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.2 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 4.3.3 + tapable: 2.3.3 + terser-webpack-plugin: 5.6.1(esbuild@0.27.3)(postcss@5.2.18)(webpack@5.105.4(esbuild@0.27.3)(postcss@5.2.18)) + watchpack: 2.5.1 + webpack-sources: 3.5.0 + transitivePeerDependencies: + - '@minify-html/node' + - '@swc/core' + - '@swc/css' + - '@swc/html' + - clean-css + - cssnano + - csso + - esbuild + - html-minifier-terser + - lightningcss + - postcss + - uglify-js + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + whet.extend@0.9.9: {} + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.22 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.22: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + wmf@1.0.2: {} + + word@0.3.0: {} + + wordwrap@1.0.0: + optional: true + + 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 + + yallist@2.1.2: {} + + yaml@2.9.0: {} + + zlibjs@0.3.1: {} diff --git a/src/App.vue b/src/App.vue new file mode 100755 index 0000000..2795759 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,18 @@ + + + diff --git a/src/api/card.ts b/src/api/card.ts new file mode 100755 index 0000000..7da95a8 --- /dev/null +++ b/src/api/card.ts @@ -0,0 +1,109 @@ +import http from '@/utils/httpRequest' +import type { ApiResponse, PageParams, PageResult } from '@/types/api' + +/** + * 卡信息 + */ +export interface CardInfo { + id: number + cardNo: string + cardType: string + status: string + activeAt?: string + expireAt?: string + [key: string]: any +} + +/** + * 卡列表参数 + */ +export interface CardListParams extends PageParams { + cardNo?: string + cardCode?: string + status?: string + cardType?: string + inventoryStatus?: string + usageStatus?: string + beginActiveAt?: string + endActiveAt?: string +} + +/** + * 卡导入数据 + */ +export interface CardImportData { + cardType: string + items: Array<{ + cardNo: string + expireAt?: string + }> +} + +/** + * 卡导入预览结果 + */ +export interface CardImportPreview { + total: number + valid: number + invalid: number + items: Array<{ + cardNo: string + valid: boolean + reason?: string + }> +} + +/** 卡详情 */ +export function getCardInfo(cardId: number | string): Promise> { + return http.get(http.adornUrl(`/sys/card/info/${cardId}`), { params: http.adornParams() }) +} + +/** 卡列表(分页) */ +export function getCardList(params?: CardListParams): Promise>> { + return http + .get(http.adornUrl('/sys/card/list'), { params: http.adornParams(params || {}) }) + .then((res) => res.data) +} + +/** 卡批量导入 */ +export function importCard(data: CardImportData): Promise> { + return http.post(http.adornUrl('/sys/card/import'), http.adornData(data, false)) +} + +/** 卡预导入 */ +export function importCardPreview(data: CardImportData): Promise> { + return http.post(http.adornUrl('/sys/card/import/preview'), http.adornData(data, false)) +} + +/** 卡导入批次(分页) */ +export function getImportBatchList(params?: PageParams): Promise>> { + return http.get(http.adornUrl('/sys/card/import-batches'), { params: http.adornParams(params || {}) }) +} + +/** 某导入批次下的卡(分页) */ +export function getImportBatchCards( + importBatchId: number | string, + params?: PageParams +): Promise>> { + return http.get( + http.adornUrl(`/sys/card/import-batches/${importBatchId}/cards`), + { params: http.adornParams(params || {}) } + ) +} + +/** 临期未使用卡(剩余激活时间 ≤ 31 天) */ +export interface NearExpiryUnusedCard { + id: number + cardNo: string + cardType: string + orgId: number + orgName: string + activationExpireAt: string + remainingActivationDays: number +} + +export function getNearExpiryUnusedCards(): Promise> { + return http + .get(http.adornUrl('/sys/card/near-expiry-unused'), { params: http.adornParams() }) + .then((res) => res.data) +} diff --git a/src/api/cardAllocation.ts b/src/api/cardAllocation.ts new file mode 100755 index 0000000..63f703e --- /dev/null +++ b/src/api/cardAllocation.ts @@ -0,0 +1,60 @@ +import type { AxiosResponse } from 'axios' +import http from '@/utils/httpRequest' +import type { ApiResponse } from '@/types/api' + +/** + * 卡分配明细参数 + */ +export interface CardAllocationDetailParams { + startDate: string + endDate: string + orgId?: string | number +} + +/** + * 卡分配明细项 + */ +export interface CardAllocationDetailItem { + bizDate: string + counterpartyOrgId: number + counterpartyOrgName: string + inCount: number + outCount: number + [key: string]: any +} + +/** 详情接口 data 中可选字段(蛇形 / 驼峰会一并兼容解析) */ +export interface CardAllocationDetailPayload { + cardFlowBreakdown?: CardAllocationDetailItem[] + card_flow_breakdown?: CardAllocationDetailItem[] + byType?: Array<{ + cardType: string + cardTypeName?: string + allocatableCount?: number + }> +} + +/** + * 卡分配详情:data.cardFlowBreakdown(bizDate、counterpartyOrg*、inCount、outCount);可选 byType 等。 + * @param params yyyy-MM-dd;可选 orgId + */ +export function getCardAllocationDetail( + params: CardAllocationDetailParams +): Promise>> { + return http.get(http.adornUrl('/sys/card-allocation/detail'), { + params: http.adornParams(params || {}) + }) +} + +/** + * 卡分配详情导出(Excel);查询参数与 getCardAllocationDetail 一致。 + * @param params yyyy-MM-dd;可选 orgId + */ +export function exportCardAllocationDetail( + params: CardAllocationDetailParams +): Promise> { + return http.get(http.adornUrl('/sys/card-allocation/detail/export'), { + params: http.adornParams(params || {}), + responseType: 'blob' + }) +} diff --git a/src/api/cardFlow.ts b/src/api/cardFlow.ts new file mode 100755 index 0000000..776ef3b --- /dev/null +++ b/src/api/cardFlow.ts @@ -0,0 +1,145 @@ +import type { AxiosResponse } from 'axios' +import http from '@/utils/httpRequest' +import type { ApiResponse } from '@/types/api' + +/** + * POST /sys/card-flow/allocate — 与后端 CardFlowAllocateRequest 对齐 + */ +export interface CardFlowAllocateRequest { + /** 分配数量(≥1) */ + count: number + /** YEAR / QUARTER / MONTH / WEEK / OTHER */ + cardType: string + /** 目标渠道/代理商/门店组织 ID */ + toChannelOrgId: number + /** 分配到门店时的权益激活码(可选,不传则服务端生成) */ + activationCode?: string +} + +/** + * 卡转移 / 回退等通用请求体(allocate 请用 CardFlowAllocateRequest) + */ +export interface CardFlowData { + cardNos?: string[] + count?: number + fromOrgId?: number + toOrgId?: number + cardType?: string + importBatchId?: number + [key: string]: any +} + +/** 卡分配/销售 */ +export function allocateCard(data: CardFlowAllocateRequest): Promise> { + return http.post(http.adornUrl('/sys/card-flow/allocate'), http.adornData(data)) +} + +/** 卡转移 */ +export function transferCard(data: CardFlowData): Promise> { + return http.post(http.adornUrl('/sys/card-flow/transfer'), http.adornData(data)) +} + +/** 卡回退(渠道/代理商按数量回退到上级,请求体:{ count, fromOrgId, cardType }) */ +export function rollbackCard(data: CardFlowData): Promise> { + return http.post(http.adornUrl('/sys/card-flow/rollback-to-parent-by-count'), http.adornData(data)) +} + +/** 无效卡按导入批次回退至渠道,请求体:{ importBatchId } */ +export function rollbackInvalidImportBatchToChannel( + data: Pick +): Promise> { + return http.post(http.adornUrl('/sys/card-flow/rollback-invalid-import-batch-to-channel'), http.adornData(data)) +} + +/** GET /sys/card-flow/allocation-orders/search 查询参数(fromOrgId / toOrgId 至少填一个) */ +export interface AllocationOrderSearchParams { + fromOrgId?: number + toOrgId?: number + page?: number + limit?: number +} + +/** 分配单搜索列表项 */ +export interface AllocationOrderSearchItem { + id: number + orderNo: string + fromOrgId: number + fromOrgName: string + fromOrgType: string + toOrgId: number + toOrgName: string + toOrgType: string + totalCount: number + status: string + createdAt: string +} + +/** 分配单搜索响应(字段可能在 data 内或响应根级) */ +export interface AllocationOrderSearchPayload { + fromOrgId?: number + toOrgId?: number + items?: AllocationOrderSearchItem[] + totalCount?: number + page?: { + list?: AllocationOrderSearchItem[] + totalCount?: number + } +} + +/** GET /sys/card-flow/allocation-order-final-destination-stat 查询参数 */ +export interface AllocationOrderFinalDestinationStatsParams { + /** 分配单 ID */ + allocationOrderId: number + page?: number + limit?: number +} + +/** 各组织最终去向统计行 */ +export interface AllocationOrderFinalDestinationStatItem { + orgId: number + orgName: string + orgType: string + count: number +} + +/** 分配单卡最终去向统计响应(字段可能在 data 内或响应根级) */ +export interface AllocationOrderFinalDestinationStatsPayload { + allocationOrderId: number + orderNo: string + fromOrgId: number + toOrgId: number + /** 卡总数(与 cardTotalCount 同义) */ + totalCount?: number + cardTotalCount?: number + totalCountOnOrder?: number + items?: AllocationOrderFinalDestinationStatItem[] + page?: { + list?: AllocationOrderFinalDestinationStatItem[] + totalCount?: number + pageSize?: number + totalPage?: number + currPage?: number + } +} + +/** + * 按流出/流入组织搜索分配单 + */ +export function searchAllocationOrders( + params: AllocationOrderSearchParams +): Promise>> { + return http.get(http.adornUrl('/sys/card-flow/allocation-orders/search'), { + params: http.adornParams(params) + }) +} + +/** + * 按分配单 ID 统计卡最终流向(card_allocation_log → card.org_id 分组) + */ +export function getAllocationOrderFinalDestinationStats( + params: AllocationOrderFinalDestinationStatsParams +): Promise>> { + return http.get(http.adornUrl('/sys/card-flow/allocation-order-final-destination-stats'), { + params: http.adornParams(params) + }) +} diff --git a/src/api/contract.ts b/src/api/contract.ts new file mode 100755 index 0000000..0c1d694 --- /dev/null +++ b/src/api/contract.ts @@ -0,0 +1,75 @@ +import http from '@/utils/httpRequest' +import type { ApiResponse, PageParams, PageResult } from '@/types/api' + +/** + * 激活码信息 + */ +export interface ActivationCode { + id: number + code: string + status: string + maxDeviceCount?: number + [key: string]: any +} + +/** + * 合同查询参数 + */ +export interface ContractQueryParams extends PageParams { + storeOrgId?: number + [key: string]: any +} + +/** + * 保存激活码数据(常与合同页对齐:code、cardType、maxDeviceCount) + */ +export interface SaveActivationCodeData { + code?: string + maxDeviceCount?: number + [key: string]: any +} + +/** 按门店查询合同/激活码列表 */ +export function getContractByStore(data: ContractQueryParams): Promise>> { + return http.post(http.adornUrl('/manage/contract/by-store'), http.adornData(data)) +} + +/** 获取合同下激活码 */ +export function getContractActivationCode( + storeOrgId: number +): Promise> { + return http.get(http.adornUrl(`/manage/contract/${storeOrgId}/activation-code`), { params: http.adornParams() }) +} + +/** 获取合同下激活码(传 contractId) */ +export function getActivationCodeByContractId( + contractId: number +): Promise> { + return http.get(http.adornUrl(`/manage/contract/${contractId}/activation-code`), { params: http.adornParams() }) +} + +/** 重新生成激活码 */ +export function regenerateActivationCode(cacId: number): Promise> { + return http.post(http.adornUrl(`/manage/contract/activation-code/${cacId}/regenerate-code`), http.adornData({})) +} + +/** 获取激活码最大设备数 */ +export function getActivationCodeMaxDeviceCount(storeOrgId: number): Promise> { + return http.get(http.adornUrl(`/manage/contract/activation-code/${storeOrgId}/max-device-count`), { params: http.adornParams() }) +} + +/** 更新激活码最大设备数(PUT);路径参数为门店组织 ID,非 CAC 主键 */ +export function updateActivationCodeMaxDeviceCount( + storeOrgId: number, + data: { maxDeviceCount: number } & Record +): Promise> { + return http.put(http.adornUrl(`/manage/contract/activation-code/${storeOrgId}/max-device-count`), http.adornData(data)) +} + +/** 创建/保存门店下权益激活码(POST) */ +export function saveStoreActivationCode( + storeOrgId: number, + data: SaveActivationCodeData +): Promise> { + return http.post(http.adornUrl(`/manage/contract/${storeOrgId}/activation-code`), http.adornData(data)) +} diff --git a/src/api/device.ts b/src/api/device.ts new file mode 100755 index 0000000..7cbc47e --- /dev/null +++ b/src/api/device.ts @@ -0,0 +1,231 @@ +import http from '@/utils/httpRequest' +import type { ApiResponse, PageParams, PageResult } from '@/types/api' + +/** + * 设备信息 + */ +export interface DeviceInfo { + id: number + deviceSn?: string + sn?: string + deviceUid?: string + uid?: string + mac?: string + status?: string + bindCardNo?: string | null + bindCardActiveAt?: string | null + bindCardPresetAt?: string | null + bindCardExpireAt?: string | null + bindCardStatus?: string | null + [key: string]: any +} + +/** + * 设备列表查询参数 + */ +export interface DeviceListParams extends PageParams { + storeOrgId?: number + mac?: string + cardStatus?: 'UNBOUND' | 'PRESET' | 'ACTIVATING' | 'ACTIVATION_FAILED' | 'ACTIVE' | 'EXPIRED' + [key: string]: any +} + +/** + * 设备导入数据 + */ +export interface DeviceImportData { + storeOrgId: number + cardType: string + items: Array<{ + mac?: string + deviceSn?: string + deviceUid?: string + roomNo?: string + }> +} + +/** + * 设备批量预置数据 + */ +export interface DeviceBatchPresetData { + storeOrgId: number + cardType: string + items: Array<{ + deviceId?: number + mac?: string + deviceSn?: string + deviceUid?: string + }> +} + +/** 设备列表:page、limit、storeOrgId(可选)、mac(模糊)、cardStatus */ +export function getDeviceList(params?: DeviceListParams): Promise>> { + return http.get(http.adornUrl('/sys/device/list'), { params: http.adornParams(params || {}) }) +} + +/** 导出设备列表 Excel */ +export function exportDeviceListExcel(params?: DeviceListParams): Promise { + return http.get(http.adornUrl('/sys/device/export-excel'), { + params: http.adornParams(params || {}), + responseType: 'blob' + }) +} + +/** 重复 MAC/设备 SN 列表 */ +export function getDuplicateMacDeviceSnList( + params?: DeviceListParams +): Promise>> { + return http.get(http.adornUrl('/sys/device/duplicate-mac'), { params: http.adornParams(params || {}) }) +} + +/** 临期设备(年卡等即将到期)列表 */ +export function getExpiringYearDeviceList( + params?: DeviceListParams +): Promise>> { + return http.get(http.adornUrl('/sys/device/expiring-year'), { params: http.adornParams(params || {}) }) +} + +/** 设备列表(不按组织过滤) */ +export function getDeviceListWithoutOrg( + params?: DeviceListParams +): Promise>> { + return http.get(http.adornUrl('/sys/device/list-without-org'), { params: http.adornParams(params || {}) }) +} + +/** 按组织 ID 获取该组织下设备列表 */ +export function getDeviceListByOrg(orgId: number): Promise> { + return http.get(http.adornUrl(`/sys/device/list-by-org/${orgId}`), { params: http.adornParams() }) +} + +/** 设备批量导入 */ +export function importDevice(data: DeviceImportData): Promise> { + return http.post(http.adornUrl('/sys/device/import'), http.adornData(data)) +} + +/** 设备单条导入(手动添加) */ +export function importDeviceOne(data: Partial): Promise> { + return http.post(http.adornUrl('/sys/device/import-one'), http.adornData(data)) +} + +/** 设备批量预置(设备授权/预置) */ +export function batchPresetDevice(data: DeviceBatchPresetData): Promise> { + return http.post(http.adornUrl('/sys/device/batch-preset'), http.adornData(data)) +} + +/** 批量预置/导入前服务端校验 */ +export function validateDeviceImport(data: DeviceImportData): Promise> { + return http.post(http.adornUrl('/sys/device/import-validate'), http.adornData(data)) +} + +/** 设备预激活 */ +export function bindDevicePreImport(data: { deviceId: number }): Promise> { + return http.post(http.adornUrl('/sys/device/preImport'), http.adornData(data)) +} + +/** 设备解绑 */ +export function unbindDevice(data: { deviceId: number }): Promise> { + return http.post(http.adornUrl('/sys/device/unbind'), http.adornData(data)) +} + +/** 预置设备删除预置 */ +export function cancelPresetDevice(data: { deviceId: number }): Promise> { + return http.post(http.adornUrl('/sys/device/cancel-preset'), http.adornData(data)) +} + +/** 设备间权益卡转移 */ +export function transferDeviceCard(data: { + fromDeviceId: number + toDeviceId: number +}): Promise> { + return http.post(http.adornUrl('/sys/device/transfer-card'), http.adornData(data)) +} + +/** 可换绑的卡信息 */ +export interface ReplaceableCard { + id: number + cardNo: string + thirdCardNo?: string + cardType: string + thirdStartAt?: string + thirdExpireAt?: string +} + +/** 查询设备可换绑的卡列表 */ +export function getReplaceableCards(deviceId: number | string): Promise> { + return http.get(http.adornUrl(`/sys/device/${deviceId}/replaceable-cards`), { params: http.adornParams() }) +} + +/** 设备换卡 */ +export function replaceCard(data: { deviceId: number; cardId: number }): Promise> { + return http.post(http.adornUrl('/sys/device/replace-card'), http.adornData(data)) +} + +/** 修改设备房间号 */ +export function updateDeviceRoomNo(data: { deviceId: number; roomNo: string }): Promise> { + return http.post(http.adornUrl('/sys/device/update-room-no'), http.adornData(data)) +} + +/** 修改设备 MAC */ +export function updateDeviceMac(data: { deviceId: number; mac: string }): Promise> { + return http.post(http.adornUrl('/sys/device/update-mac'), http.adornData(data)) +} + +/** 设备续费 */ +export function renewDevice(data: { deviceId: number; cardType: string }): Promise> { + return http.post(http.adornUrl('/sys/device/renew'), http.adornData(data)) +} + +/** 根据设备ID查询设备详细信息 */ +export function getDeviceDetail(deviceId: number): Promise> { + return http.get(http.adornUrl(`/sys/device/detail/${deviceId}`), { params: http.adornParams() }) +} + +/** 开发人员设备迁移 */ +export function developerManualImportDevice(data: { + storeId: number + mac: string + expireAt: string +}): Promise> { + return http.post(http.adornUrl('/sys/device/developer-manual-import'), http.adornData(data)) +} + +/** 设备转移门店 */ +export function assignDeviceStore(data: { + deviceId: number + toStoreOrgId?: number + storeOrgId?: number +}): Promise> { + const payload = { + deviceId: data?.deviceId, + toStoreOrgId: data?.toStoreOrgId ?? data?.storeOrgId + } + return http.post(http.adornUrl('/sys/device/transform'), http.adornData(payload)) +} + +/** 清空设备 SN/UID */ +export function clearDeviceSnUid(data: { deviceId: number }): Promise> { + return http.post(http.adornUrl('/sys/device/clear-sn-uid'), http.adornData(data)) +} + +/** 软删除设备 */ +export function softDeleteDevice(data: { deviceId: number }): Promise> { + return http.post(http.adornUrl('/sys/device/soft-delete'), http.adornData(data)) +} + +/** 禁用设备(status → DISABLED) */ +export function disableDevice(data: { deviceId: number }): Promise> { + return http.post(http.adornUrl('/sys/device/disable'), http.adornData(data)) +} + +/** 同 MAC 已绑卡设备列表(不含自身,字段与 duplicate-mac 列表一致) */ +export function getSameMacBoundDeviceList(deviceId: number): Promise> { + return http.get(http.adornUrl(`/sys/device/same-mac-bound-list/${deviceId}`), { params: http.adornParams() }) +} + +/** 替换重复设备:保留 device1 绑卡,交换 SN/UID,软删除 device2 */ +export function replaceDuplicateDevice(data: { + device1: number + device2: number +}): Promise> { + return http.post(http.adornUrl('/sys/device/replace-duplicate'), http.adornData(data)) +} diff --git a/src/api/index.ts b/src/api/index.ts new file mode 100755 index 0000000..8d3249f --- /dev/null +++ b/src/api/index.ts @@ -0,0 +1,22 @@ +/** + * 统一导出 http 实例及所有 API 模块 + * 业务请从各模块按需引入,例如:import { getOrgTree } from '@/api/org' + * + * 新 manage 后端接口(/manage/ 前缀)请从独立入口引入: + * import { getChannelList, getOverviewStats } from '@/api/manage' + * 或按模块引入: + * import { getChannelList } from '@/api/manage/channel' + */ +import http from '@/utils/httpRequest' + +export { http } +export * from './org' +export * from './card' +export * from './cardFlow' +export * from './cardAllocation' +export * from './contract' +export * from './store' +export * from './device' +export * from './mediaAsset' +export * from './mediaAssetRank' +export * from './sys' diff --git a/src/api/jetsenMedia.ts b/src/api/jetsenMedia.ts new file mode 100644 index 0000000..7df9cd8 --- /dev/null +++ b/src/api/jetsenMedia.ts @@ -0,0 +1,83 @@ +import http from '@/utils/httpRequest' + +/** + * 橘视厅媒资内容项(对应后端透传的橘视厅 result 字段) + */ +export interface JetsenContentItem { + contentcode: string + name: string + categoryname?: string + score?: string + actordisplay?: string + description?: string + releaseyear?: string + originalcountry?: string + isFree?: number + episodecount?: number + duration?: string + posterimg?: string + midimg?: string + image?: string + [key: string]: any +} + +/** 栏目标签 */ +export interface JetsenTag { + id: number + name: string + code: string + type?: number + parent_id?: number + big_project?: string + [key: string]: any +} + +/** 栏目树节点(一级含 children 二级子栏目) */ +export interface JetsenCatalogNode { + id: number + name: string + code?: string + children?: JetsenCatalogNode[] +} + +/** 分页数据(后端 R.dataSuccess 统一格式) */ +export interface JetsenPageData { + list: T[] + totalCount: number + currPage: number + pageSize: number + totalPage: number +} + +/** 首页导航(一级栏目入口) */ +export function getJetsenMediaNav() { + return http.get(http.adornUrl('/manage/jetsen-media/nav'), { params: http.adornParams() }) +} + +/** 栏目标签(一级栏目传 parentid=0) */ +export function getJetsenMediaTags(parentid: string | number = 0) { + return http.get(http.adornUrl('/manage/jetsen-media/tags'), { params: http.adornParams({ parentid }) }) +} + +/** 栏目树(一级栏目 + 其下二级子栏目,查内容列表用二级 id) */ +export function getJetsenMediaCatalogTree() { + return http.get(http.adornUrl('/manage/jetsen-media/catalog-tree'), { params: http.adornParams() }) +} + +/** 内容列表(按栏目 catalogid 分页) */ +export function getJetsenMediaList(params: { catalogid: string | number; pageindex: number; pagesize: number }) { + return http.get(http.adornUrl('/manage/jetsen-media/list'), { params: http.adornParams(params) }) +} + +/** 搜索 */ +export function searchJetsenMedia(params: { keyword: string; pageindex: number; pagesize: number }) { + return http.get(http.adornUrl('/manage/jetsen-media/search'), { params: http.adornParams(params) }) +} + +/** 导出 Excel(返回 blob) */ +export function exportJetsenMedia(params: { catalogid?: string | number; keyword?: string; catalogName?: string }) { + return http.get(http.adornUrl('/manage/jetsen-media/export'), { + params: http.adornParams(params), + responseType: 'blob' + }) +} diff --git a/src/api/manage/activationCode.ts b/src/api/manage/activationCode.ts new file mode 100644 index 0000000..0ba231b --- /dev/null +++ b/src/api/manage/activationCode.ts @@ -0,0 +1,55 @@ +import http from '@/utils/httpRequest' +import type { ManageResponse } from './types' + +// ===================== 天卡设备激活码 ===================== + +/** 激活码实体 */ +export interface ActivationCodeItem { + id: number + /** 激活码(5位字符,如 7A3FK) */ + code: string + /** 渠道组织ID */ + channelOrgId: number + /** 门店组织ID */ + storeOrgId: number + /** 状态:ACTIVE-启用 / DISABLED-禁用 */ + status: 'ACTIVE' | 'DISABLED' + /** 最大可激活设备数(0=不限) */ + maxDeviceCount: number + /** 已激活设备数 */ + activatedCount: number + /** 备注 */ + remark: string | null + createdAt: string +} + +/** 生成激活码请求体 */ +export interface ActivationCodeGenerateBody { + storeOrgId: number + remark?: string +} + +/** 按门店查询激活码列表(GET /manage/daycard/activation-code/list/{storeOrgId}) */ +export function getActivationCodeList (storeOrgId: number): Promise> { + return http.get(http.adornUrl(`/manage/daycard/activation-code/list/${storeOrgId}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 为门店生成激活码(每门店一个,已存在则返回已有的) */ +export function generateActivationCode (data: ActivationCodeGenerateBody): Promise> { + return http.post(http.adornUrl('/manage/daycard/activation-code/generate'), http.adornData(data)).then(res => res.data) +} + +/** 重新生成激活码(旧码失效) */ +export function regenerateActivationCode (id: number): Promise> { + return http.post(http.adornUrl(`/manage/daycard/activation-code/${id}/regenerate`), http.adornData({})).then(res => res.data) +} + +/** 启用/禁用激活码(PUT /manage/daycard/activation-code/{id}/status) */ +export function updateActivationCodeStatus (id: number, status: 'ACTIVE' | 'DISABLED'): Promise { + return http.put(http.adornUrl(`/manage/daycard/activation-code/${id}/status`), http.adornData({ status })).then(res => res.data) +} + +/** 删除激活码(软删除) */ +export function deleteActivationCode (id: number): Promise { + return http.delete(http.adornUrl(`/manage/daycard/activation-code/${id}`)).then(res => res.data) +} diff --git a/src/api/manage/channel.ts b/src/api/manage/channel.ts new file mode 100644 index 0000000..d9872af --- /dev/null +++ b/src/api/manage/channel.ts @@ -0,0 +1,75 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +/** + * 渠道信息 + */ +export interface ChannelInfo { + id: number + parentId: number + mpath: string + name: string + orderNo?: number + type: string + /** 后端 @JsonProperty("orgCode") 重命名,JSON 中为 orgCode */ + orgCode?: string + canHoldInventory: boolean + activationPrefix: string + brandLogoUrl: string | null + developmentStaff?: string + contactPhone?: string + servicePartner?: string + wechatQrImageUrl?: string | null + status: string + createdAt: string + updatedAt: string + /** 非表字段,后端 join 返回 */ + parentOrgName?: string + channelName?: string + children?: ChannelInfo[] +} + +/** + * 渠道列表查询参数 + */ +export interface ChannelListParams extends ManagePageParams { + name?: string + status?: string +} + +/** + * 渠道保存/更新数据 + */ +export interface ChannelSaveData { + id?: number + parentId: number + name: string + orgCode?: string + canHoldInventory?: boolean + activationPrefix?: string + brandLogoUrl?: string + developmentStaff?: string + contactPhone?: string + servicePartner?: string +} + +/** 渠道分页列表 */ +export function getChannelList(params?: ChannelListParams): Promise> { + return http.get(http.adornUrl('/manage/org/channel/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 渠道详情 */ +export function getChannelInfo(id: number): Promise> { + return http.get(http.adornUrl(`/manage/org/channel/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 新增/修改渠道 */ +export function saveOrUpdateChannel(data: ChannelSaveData): Promise { + const url = data.id ? '/manage/org/channel/update' : '/manage/org/channel/save' + return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data) +} + +/** 删除渠道(批量软删除) */ +export function deleteChannel(ids: number[]): Promise { + return http.post(http.adornUrl('/manage/org/channel/delete'), http.adornData(ids, false)).then(res => res.data) +} diff --git a/src/api/manage/content-package.ts b/src/api/manage/content-package.ts new file mode 100644 index 0000000..c1bb31e --- /dev/null +++ b/src/api/manage/content-package.ts @@ -0,0 +1,112 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +/** + * 内容包信息(绑定 partnerId) + */ +export interface ContentPackage { + id: number + /** 合作伙伴UUID(字符串) */ + partnerId: string + name: string + description?: string + /** 状态:ACTIVE-启用 / DISABLED-禁用 */ + status: 'ACTIVE' | 'DISABLED' + createdAt: string + updatedAt: string + /** 非表字段,后端 join 返回 */ + partnerName?: string +} + +/** + * 内容包保存/更新数据 + */ +export interface ContentPackageSaveData { + id?: number + /** 合作伙伴UUID(字符串) */ + partnerId: string + name: string + description?: string + status?: 'ACTIVE' | 'DISABLED' +} + +/** + * 内容包列表查询参数 + */ +export interface ContentPackageListParams extends ManagePageParams { + /** 合作伙伴UUID(字符串) */ + partnerId?: string + name?: string + status?: string +} + +/** 内容包分页列表 */ +export function getContentPackageList(params?: ContentPackageListParams): Promise> { + return http.get(http.adornUrl('/manage/content-package/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +// ===================== 栏目内容选择辅助接口 ===================== + +/** 栏目内容预览项(精简字段,供管理员勾选) */ +export interface CatalogContentItem { + contentcode: string + name: string + posterimg?: string + categoryname?: string + score?: string + isFree?: number | string + episodecount?: number + duration?: number + releaseyear?: string + originalcountry?: string +} + +/** 内容包详情(含解析后的内容列表,前端直接展示,无需 JSON.parse) */ +export interface ContentPackageDetail { + /** 原始实体(contentCodes 是 JSON 字符串) */ + contentPackage: ContentPackage + /** 解析后的内容数组 */ + contentList: CatalogContentItem[] +} + +/** 内容包详情(按 id,含 contentList) */ +export function getContentPackageInfo(id: number): Promise> { + return http.get(http.adornUrl(`/manage/content-package/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 内容包详情(按 partnerId,含 contentList) */ +export function getContentPackageInfoByPartner(partnerId: string): Promise> { + return http.get(http.adornUrl(`/manage/content-package/info-by-partner/${partnerId}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 新增/修改内容包元信息(绑定 partnerId) */ +export function saveOrUpdateContentPackage(data: ContentPackageSaveData): Promise { + const url = data.id ? '/manage/content-package/update' : '/manage/content-package/save' + return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data) +} + +/** 删除内容包(软删除,批量) */ +export function deleteContentPackage(ids: number[]): Promise { + return http.post(http.adornUrl('/manage/content-package/delete'), http.adornData(ids, false)).then(res => res.data) +} + +/** 拉取栏目内容预览(GET /manage/content-package/fetch-contents?catalogid=&pagesize=) */ +export function fetchPackageContents(params: { catalogid: string | number; pagesize?: number; pageindex?: number }): Promise> { + return http.get(http.adornUrl('/manage/content-package/fetch-contents'), { params: http.adornParams(params) }).then(res => res.data) +} + +/** 一键保存勾选内容请求体(POST /manage/content-package/save-from-selection;传 id 覆盖,不传新建) */ +export interface SaveFromSelectionBody { + /** 传 id 按 id 更新覆盖;不传按 partnerId 查找 */ + id?: number + /** 合作伙伴UUID(字符串) */ + partnerId: string + name: string + catalogIds: string + selectedContents: CatalogContentItem[] +} + +/** 一键保存勾选内容(管理员勾选的内容对象数组直接传后端,序列化存入 content_codes;不带 t 时间戳) */ +export function saveContentPackageFromSelection(data: SaveFromSelectionBody): Promise { + return http.post(http.adornUrl('/manage/content-package/save-from-selection'), http.adornData(data, false)).then(res => res.data) +} diff --git a/src/api/manage/daycard.ts b/src/api/manage/daycard.ts new file mode 100644 index 0000000..fca6880 --- /dev/null +++ b/src/api/manage/daycard.ts @@ -0,0 +1,151 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +// ===================== 天卡池 ===================== + +/** 天卡池实体 */ +export interface DayCardPoolItem { + id: number + /** 卡密(橘视厅激活码) */ + cardCode: string + /** 第三方引用标识(橘视厅免密登录 uid) */ + thirdPartyRef: string + /** 第三方卡号(D + 24位随机,App 用于访问内容) */ + thirdCardNo: string + cardType: string + partnerId: number + /** 状态: UNUSED / RESERVED / USED */ + status: string + /** 激活状态: PENDING / SUCCESS / FAILED */ + activateStatus: string + activateError: string | null + activatedAt: string | null + orderNo: string | null + deviceId: number | null + importBatchId: number | null + expireAt: string | null + usedAt: string | null + createdAt: string + updatedAt: string +} + +/** 卡池列表参数 */ +export interface DayCardPoolListParams extends ManagePageParams { + partnerId?: number + status?: string + cardCode?: string + orderNo?: string +} + +/** 卡池统计 */ +export interface DayCardPoolStats { + total: number + available: number + reserved: number + used: number +} + +/** 导入卡密请求 */ +export interface DayCardPoolImportData { + partnerId: number + cardCodes: string[] +} + +/** 导入卡密响应 */ +export interface DayCardPoolImportResult { + successCount: number + totalCount: number +} + +/** 导入批次 */ +export interface DayCardImportBatch { + id: number + batchNo: string + partnerId: number + status: string + totalCount: number + successCount: number + failCount: number + remark: string | null + createdAt: string +} + +/** 获取天卡池列表 */ +export function getDayCardPoolList (params?: DayCardPoolListParams): Promise> { + return http.get(http.adornUrl('/manage/daycard/pool/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 获取卡池统计 */ +export function getDayCardPoolStats (partnerId?: number): Promise> { + return http.get(http.adornUrl('/manage/daycard/pool/stats'), { params: http.adornParams({ partnerId }) }).then(res => res.data) +} + +/** 导入卡密 */ +export function importDayCardPool (data: DayCardPoolImportData): Promise> { + return http.post(http.adornUrl('/manage/daycard/pool/import'), http.adornData(data)).then(res => res.data) +} + +// ===================== 天卡订单 ===================== + +/** 天卡订单实体 */ +export interface DayCardOrderItem { + id: number + orderNo: string + partnerId: number + deviceId: number + storeOrgId: number + channelOrgId: number + /** 卡号(值为 DayCardPoolEntity.cardCode) */ + cardNo: string | null + /** 订单状态: CREATED / PAYING / PAID / PAY_FAILED / CANCELLED */ + status: string + amount: number + /** 支付渠道: WECHAT 等 */ + payChannel: string | null + /** 微信支付二维码链接 */ + codeUrl: string | null + payNo: string | null + payAmount: number | null + payTime: string | null + expireTime: string | null + cancelTime: string | null + createdAt: string + updatedAt: string + /** 非表字段 */ + partnerName?: string + deviceMac?: string +} + +/** 订单列表参数 */ +export interface DayCardOrderListParams extends ManagePageParams { + partnerId?: number + orderNo?: string + status?: string + startDate?: string + endDate?: string +} + +/** 获取订单列表 */ +export function getDayCardOrderList (params?: DayCardOrderListParams): Promise> { + return http.get(http.adornUrl('/manage/daycard/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 获取订单详情 */ +export function getDayCardOrderInfo (orderNo: string): Promise> { + return http.get(http.adornUrl(`/manage/daycard/info/${orderNo}`), { params: http.adornParams() }).then(res => res.data) +} + +// ===================== 设备权益 ===================== + +/** 设备天卡权益 */ +export interface DeviceBenefits { + hasBenefits: boolean + thirdCardNo?: string + cardCode?: string + expireAt?: string +} + +/** 查询设备天卡权益 */ +export function getDeviceBenefits (deviceId: number): Promise> { + return http.get(http.adornUrl(`/manage/daycard/benefits/${deviceId}`), { params: http.adornParams() }).then(res => res.data) +} diff --git a/src/api/manage/device.ts b/src/api/manage/device.ts new file mode 100644 index 0000000..b706fe6 --- /dev/null +++ b/src/api/manage/device.ts @@ -0,0 +1,117 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +/** + * 终端/设备信息 + */ +export interface DeviceInfo { + id: number + storeOrgId: number + mac: string + deviceSn: string + wifiMac?: string + deviceUid?: string + androidId?: string + manufacturer?: string + model?: string + brand?: string + identifierStrategy?: string + deviceName: string + deviceModel: string + verCode?: string + verName?: string + androidVersion?: string + roomNo: string + lastHeartbeat?: string + remark: string + status: string + createdAt: string + updatedAt: string + /** 非表字段,后端 join 返回 */ + storeName?: string + channelOrgId?: number + channelName?: string + agentOrgName?: string + /** 设备来源:PLATFORM-平台 / PARTNER-第三方接口注册 */ + source?: string + /** 合作伙伴UUID(source=PARTNER 时) */ + partnerId?: string +} + +/** + * 终端列表查询参数 + */ +export interface DeviceListParams extends ManagePageParams { + storeOrgId?: number + status?: string + deviceName?: string + mac?: string + /** 设备来源:PLATFORM / PARTNER */ + source?: string + /** 合作伙伴UUID(source=PARTNER 时筛选) */ + partnerId?: string +} + +/** + * 终端保存/更新数据 + */ +export interface DeviceSaveData { + id?: number + storeOrgId: number + mac?: string + wifiMac?: string + deviceUid?: string + deviceSn?: string + deviceName?: string + deviceModel?: string + roomNo?: string + remark?: string +} + +/** 终端分页列表 */ +export function getDeviceList(params?: DeviceListParams): Promise> { + return http.get(http.adornUrl('/manage/device/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 终端详情 */ +export function getDeviceInfo(id: number): Promise> { + return http.get(http.adornUrl(`/manage/device/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 新增/修改终端 */ +export function saveOrUpdateDevice(data: DeviceSaveData): Promise { + const url = data.id ? '/manage/device/update' : '/manage/device/save' + return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data) +} + +/** 删除终端(批量软删除) */ +export function deleteDevice(ids: number[]): Promise { + return http.post(http.adornUrl('/manage/device/delete'), http.adornData(ids, false)).then(res => res.data) +} + +/** 绑定门店(query 参数传 deviceId 和 storeOrgId) */ +export function bindDeviceStore(deviceId: number, storeOrgId: number): Promise { + return http.post( + http.adornUrl('/manage/device/bindStore'), + http.adornData({}), + { params: http.adornParams({ deviceId, storeOrgId }) } + ).then(res => res.data) +} + +/** 解绑设备(换场所):清门店关联 + 作废 sign + 释放天卡权益 */ +export function unbindDeviceOrg(deviceId: number): Promise { + return http.post( + http.adornUrl('/manage/daycard/device/unbind-org'), + http.adornData({}), + { params: http.adornParams({ deviceId }) } + ).then(res => res.data) +} + +/** 退天卡:仅退卡,不解绑门店 */ +export function unbindDayCard(deviceId: number): Promise { + return http.post( + http.adornUrl('/manage/daycard/device/unbind'), + http.adornData({}), + { params: http.adornParams({ deviceId }) } + ).then(res => res.data) +} diff --git a/src/api/manage/index.ts b/src/api/manage/index.ts new file mode 100644 index 0000000..473cc32 --- /dev/null +++ b/src/api/manage/index.ts @@ -0,0 +1,28 @@ +/** + * /manage/ 接口模块统一导出 + * + * 业务请从各模块按需引入,例如: + * import { getChannelList } from '@/api/manage/channel' + * import { getOverviewStats } from '@/api/manage/stats' + * + * 或从统一入口引入: + * import { getChannelList, getOverviewStats } from '@/api/manage' + */ +export * from './types' +export * from './channel' +export * from './store' +export * from './orgTree' +export * from './device' +export * from './payConfig' +export * from './price' +export * from './stats' +export * from './daycard' +export * from './activationCode' +export * from './profitRule' +export * from './profitReceiver' +export * from './profitSharing' +export * from './refund' +export * from './partner' +export * from './content-package' +export * from './partner-card' +export * from './openapiCallLog' diff --git a/src/api/manage/openapiCallLog.ts b/src/api/manage/openapiCallLog.ts new file mode 100644 index 0000000..364ca29 --- /dev/null +++ b/src/api/manage/openapiCallLog.ts @@ -0,0 +1,42 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManagePageParams } from './types' + +/** + * OpenAPI 调用日志(第三方接口审计日志) + */ +export interface OpenApiCallLogItem { + id: number + /** 合作伙伴UUID */ + partnerId: string + /** 应用Key */ + appKey: string + /** 接口路径 */ + api: string + /** 请求方法:GET / POST */ + httpMethod: string + /** 请求参数(consume 记录设备标识,media 记录 query string) */ + params: string + /** 结果码:0=成功,400/500=失败 */ + resultCode: number + /** 调用方IP */ + ip: string + /** 耗时(毫秒) */ + costMs: number + /** 调用时间 */ + createdAt: string +} + +/** + * 查询参数 + */ +export interface OpenApiCallLogListParams extends ManagePageParams { + /** 合作伙伴UUID */ + partnerId?: string + /** 接口路径(模糊查询) */ + api?: string +} + +/** OpenAPI 调用日志列表(第三方接口审计日志) */ +export function getOpenApiCallLogList(params?: OpenApiCallLogListParams): Promise> { + return http.get(http.adornUrl('/manage/openapi/call-log/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} diff --git a/src/api/manage/orgTree.ts b/src/api/manage/orgTree.ts new file mode 100644 index 0000000..becb313 --- /dev/null +++ b/src/api/manage/orgTree.ts @@ -0,0 +1,22 @@ +import http from '@/utils/httpRequest' +import type { ManageResponse } from './types' + +/** + * 组织树节点 + */ +export interface OrgTreeNode { + id: number + name: string + type: string + mpath: string + code?: string + children: OrgTreeNode[] +} + +/** + * 获取完整组织树 + * 层级:PLATFORM → CHANNEL → SERVICE_PROVIDER → STORE + */ +export function getOrgTree(): Promise> { + return http.get(http.adornUrl('/manage/org/tree'), { params: http.adornParams() }).then(res => res.data) +} diff --git a/src/api/manage/partner-card.ts b/src/api/manage/partner-card.ts new file mode 100644 index 0000000..70afbf1 --- /dev/null +++ b/src/api/manage/partner-card.ts @@ -0,0 +1,98 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +/** + * 合作伙伴天卡(卡密级别) + */ +export interface PartnerCardItem { + id: number + /** 合作伙伴UUID(字符串) */ + partnerId: string + /** 平台天卡池ID(day_card_pool.id) */ + poolId: number + /** 天卡卡密 */ + cardCode: string + /** 橘视厅第三方卡号 */ + thirdCardNo: string + /** 状态:AVAILABLE-可用 / CONSUMED-已消耗 / DISABLED-已禁用 */ + status: 'AVAILABLE' | 'CONSUMED' | 'DISABLED' + /** 消耗后绑定的设备ID(未消耗=null) */ + deviceId: number | null + /** 渠道机构ID(消耗时传入,未消耗=null) */ + channelOrgId: number | null + /** 采购批次号(同批次采购的天卡批次号相同) */ + purchaseBatch: string + /** 消耗时间(未消耗=null) */ + consumedAt: string | null + deleteFlag: string + /** 创建时间(采购时间) */ + createdAt: string + updatedAt: string +} + +/** + * 库存统计 + */ +export interface PartnerCardStats { + total: number + available: number + used: number +} + +/** + * 库存列表查询参数 + */ +export interface PartnerCardListParams extends ManagePageParams { + /** 合作伙伴UUID(字符串) */ + partnerId?: string + /** 状态:AVAILABLE / CONSUMED / DISABLED */ + status?: string + /** 采购批次号 */ + purchaseBatch?: string +} + +/** + * 采购天卡请求体(后端 @RequestParam,参数走 URL query) + */ +export interface PartnerCardPurchaseBody { + /** 合作伙伴UUID(字符串) */ + partnerId: string + /** 采购卡数 */ + quantity: number + /** 金额(分) */ + amount?: number + remark?: string +} + +/** 天卡库存列表(卡密级别) */ +export function getPartnerCardList(params?: PartnerCardListParams): Promise> { + return http.get(http.adornUrl('/manage/partner-card/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 采购天卡(划拨天卡到 partner 池子;后端 @RequestParam,参数走 URL query,不放 JSON body) */ +export function purchasePartnerCard(data: PartnerCardPurchaseBody): Promise { + return http.post( + http.adornUrl('/manage/partner-card/purchase'), + http.adornData({}), + { params: http.adornParams({ partnerId: data.partnerId, quantity: data.quantity, amount: data.amount, remark: data.remark }, false) } + ).then(res => res.data) +} + +/** + * 回退天卡请求体(后端 @RequestParam,参数走 URL query) + */ +export interface PartnerCardRevertBody { + /** 合作伙伴UUID(字符串) */ + partnerId: string + /** 回退数量 */ + quantity: number +} + +/** 回退天卡(从 partner 池取 N 张 AVAILABLE 天卡回退;平台池 RESERVED->UNUSED,partner 池卡 DISABLED;@RequestParam,URL query) */ +export function revertPartnerCard(data: PartnerCardRevertBody): Promise> { + return http.post( + http.adornUrl('/manage/partner-card/revert'), + http.adornData({}), + { params: http.adornParams({ partnerId: data.partnerId, quantity: data.quantity }, false) } + ).then(res => res.data) +} diff --git a/src/api/manage/partner.ts b/src/api/manage/partner.ts new file mode 100644 index 0000000..439f8cc --- /dev/null +++ b/src/api/manage/partner.ts @@ -0,0 +1,67 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +/** + * 合作伙伴信息 + */ +export interface PartnerInfo { + id: number + /** 合作伙伴业务UUID(16位字符串,传给内容包/采购等接口用此字段,非自增 id) */ + partnerId: string + name: string + /** 应用标识(新增后由后端自动生成) */ + appKey: string + /** 应用密钥(新增后由后端自动生成,仅明文返回一次) */ + appSecret: string + /** 状态:ACTIVE-启用 / DISABLED-禁用(禁用后 appKey 签名校验失败) */ + status: 'ACTIVE' | 'DISABLED' + /** 限流(次/分钟,0=不限) */ + rateLimit?: number + remark?: string + createdAt: string + updatedAt: string +} + +/** + * 合作伙伴保存/更新数据 + */ +export interface PartnerSaveData { + id?: number + name: string + status?: 'ACTIVE' | 'DISABLED' + rateLimit?: number + remark?: string +} + +/** + * 合作伙伴列表查询参数 + */ +export interface PartnerListParams extends ManagePageParams { + name?: string + status?: string +} + +/** 合作伙伴分页列表 */ +export function getPartnerList(params?: PartnerListParams): Promise> { + return http.get(http.adornUrl('/manage/partner/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 合作伙伴详情(含 appKey/appSecret 明文) */ +export function getPartnerInfo(id: number): Promise> { + return http.get(http.adornUrl(`/manage/partner/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 新增合作伙伴(自动生成 appKey/appSecret,返回在 data 中) */ +export function savePartner(data: PartnerSaveData): Promise> { + return http.post(http.adornUrl('/manage/partner/save'), http.adornData(data)).then(res => res.data) +} + +/** 修改合作伙伴(改名称/状态/限流等;status=DISABLED 禁用) */ +export function updatePartner(data: PartnerSaveData): Promise { + return http.post(http.adornUrl('/manage/partner/update'), http.adornData(data)).then(res => res.data) +} + +/** 删除合作伙伴(软删除,批量) */ +export function deletePartner(ids: number[]): Promise { + return http.post(http.adornUrl('/manage/partner/delete'), http.adornData(ids, false)).then(res => res.data) +} diff --git a/src/api/manage/payConfig.ts b/src/api/manage/payConfig.ts new file mode 100644 index 0000000..0666718 --- /dev/null +++ b/src/api/manage/payConfig.ts @@ -0,0 +1,63 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +/** + * 微信支付配置信息 + */ +export interface PayConfigInfo { + id: number + partnerId: number | null + appId: string + mchId: string + apiV3Key: string + certSerialNo: string + privateKeyPath: string + notifyUrl: string + status: string + remark: string +} + +/** + * 支付配置列表查询参数 + */ +export interface PayConfigListParams extends ManagePageParams { + partnerId?: number + status?: string +} + +/** + * 支付配置保存/更新数据 + */ +export interface PayConfigSaveData { + id?: number + partnerId?: number + appId: string + mchId: string + apiV3Key: string + certSerialNo?: string + privateKeyPath?: string + notifyUrl: string + status?: string + remark?: string +} + +/** 支付配置分页列表 */ +export function getPayConfigList(params?: PayConfigListParams): Promise> { + return http.get(http.adornUrl('/manage/payconfig/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 支付配置详情 */ +export function getPayConfigInfo(id: number): Promise> { + return http.get(http.adornUrl(`/manage/payconfig/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 新增/修改支付配置 */ +export function saveOrUpdatePayConfig(data: PayConfigSaveData): Promise { + const url = data.id ? '/manage/payconfig/update' : '/manage/payconfig/save' + return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data) +} + +/** 删除支付配置(批量软删除) */ +export function deletePayConfig(ids: number[]): Promise { + return http.post(http.adornUrl('/manage/payconfig/delete'), http.adornData(ids, false)).then(res => res.data) +} diff --git a/src/api/manage/price.ts b/src/api/manage/price.ts new file mode 100644 index 0000000..78668db --- /dev/null +++ b/src/api/manage/price.ts @@ -0,0 +1,71 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +/** + * 定价策略信息 + */ +export interface PriceConfigInfo { + id: number + partnerId: number + channelOrgId: number | null + storeOrgId: number | null + price: number + durationHours: number + name: string + status: string + /** 生效起始日期 yyyy-MM-dd */ + effectiveFrom: string | null + /** 生效截止日期 yyyy-MM-dd(null=长期) */ + effectiveTo: string | null + createdAt: string +} + +/** + * 定价策略列表查询参数 + */ +export interface PriceListParams extends ManagePageParams { + partnerId?: number + channelOrgId?: number + storeOrgId?: number + status?: string +} + +/** + * 定价策略保存/更新数据 + */ +export interface PriceSaveData { + id?: number + partnerId?: number + channelOrgId?: number + storeOrgId?: number + price: number + durationHours?: number + name?: string + status?: string +} + +/** 定价策略分页列表 */ +export function getPriceList(params?: PriceListParams): Promise> { + return http.get(http.adornUrl('/manage/price/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 定价策略详情 */ +export function getPriceInfo(id: number): Promise> { + return http.get(http.adornUrl(`/manage/price/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 新增/修改定价策略 */ +export function saveOrUpdatePrice(data: PriceSaveData): Promise { + const url = data.id ? '/manage/price/update' : '/manage/price/save' + return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data) +} + +/** 删除定价策略(批量软删除) */ +export function deletePrice(ids: number[]): Promise { + return http.post(http.adornUrl('/manage/price/delete'), http.adornData(ids, false)).then(res => res.data) +} + +/** 查询生效中的定价(GET /manage/price/effective?channelOrgId=&storeOrgId=) */ +export function getEffectivePrice(params: { channelOrgId?: number; storeOrgId?: number }): Promise> { + return http.get(http.adornUrl('/manage/price/effective'), { params: http.adornParams(params) }).then(res => res.data) +} diff --git a/src/api/manage/profitReceiver.ts b/src/api/manage/profitReceiver.ts new file mode 100644 index 0000000..c66f1fb --- /dev/null +++ b/src/api/manage/profitReceiver.ts @@ -0,0 +1,58 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +// ===================== 分账接收方 ===================== + +export interface ProfitReceiver { + id: number + /** 关联组织ID(渠道/代理商/门店) */ + orgId: number + orgName: string + /** 接收方类型: MERCHANT_ID-商户号 / PERSONAL_OPENID-个人openid */ + receiverType: 'MERCHANT_ID' | 'PERSONAL_OPENID' + /** 接收方账号(商户号或openid) */ + receiverAccount: string + /** 收款方名称 */ + receiverName: string + /** 绑定状态: PENDING-待确认 / ACTIVE-已绑定 / FAILED-绑定失败 */ + bindStatus: 'PENDING' | 'ACTIVE' | 'FAILED' +} + +export interface ProfitReceiverSaveBody { + id?: number + orgId: number + receiverType: 'MERCHANT_ID' | 'PERSONAL_OPENID' + receiverAccount: string + receiverName: string +} + +export interface ProfitReceiverListParams extends ManagePageParams { + orgId?: number + bindStatus?: string +} + +/** 接收方列表 */ +export function getProfitReceiverList (params?: ProfitReceiverListParams): Promise> { + return http.get(http.adornUrl('/manage/profit-receiver/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 接收方详情 */ +export function getProfitReceiverInfo (id: number): Promise> { + return http.get(http.adornUrl(`/manage/profit-receiver/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 保存接收方 */ +export function saveProfitReceiver (data: ProfitReceiverSaveBody): Promise { + return http.post(http.adornUrl('/manage/profit-receiver/save'), http.adornData(data)).then(res => res.data) +} + +/** 删除接收方(body: Long[] ids) */ +export function deleteProfitReceiver (ids: number | number[]): Promise { + const arr = Array.isArray(ids) ? ids : [ids] + return http.post(http.adornUrl('/manage/profit-receiver/delete'), http.adornData(arr, false)).then(res => res.data) +} + +/** 同步接收方到微信(POST /manage/profit-receiver/sync/{id}) */ +export function syncProfitReceiver (id: number): Promise { + return http.post(http.adornUrl(`/manage/profit-receiver/sync/${id}`), http.adornData({})).then(res => res.data) +} diff --git a/src/api/manage/profitRule.ts b/src/api/manage/profitRule.ts new file mode 100644 index 0000000..2f85cca --- /dev/null +++ b/src/api/manage/profitRule.ts @@ -0,0 +1,100 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +// ===================== 分润规则 ===================== + +export interface ProfitRule { + id: number + ruleName: string + scopeType: 'GLOBAL' | 'CHANNEL' | 'AGENT' | 'STORE' + scopeOrgId: number | null + scopeOrgName: string | null + priority: number + status: 'ACTIVE' | 'INACTIVE' + effectiveFrom: string | null + effectiveTo: string | null +} + +export interface ProfitRuleItem { + id: number + orgRole: 'PLATFORM' | 'CHANNEL' | 'AGENT' | 'STORE' + shareType: 'RATIO' | 'FIXED' + /** RATIO: 百分比(如 20 表示 20%);FIXED: 分 */ + shareValue: number + sortOrder: number +} + +export interface ProfitRuleDetail extends ProfitRule { + items: ProfitRuleItem[] +} + +export interface ProfitRuleSaveBody { + id?: number + ruleName: string + scopeType: 'GLOBAL' | 'CHANNEL' | 'AGENT' | 'STORE' + scopeOrgId: number | null + priority: number + status: 'ACTIVE' | 'INACTIVE' + effectiveFrom: string | null + effectiveTo: string | null + items: Omit[] +} + +export interface ProfitRuleListParams extends ManagePageParams { + scopeType?: string +} + +// ===================== 试算 ===================== + +export interface ProfitRulePreviewBody { + storeOrgId: number + /** 单位:分 */ + amount: number +} + +export interface ProfitRulePreviewDetail { + orgRole: 'PLATFORM' | 'CHANNEL' | 'AGENT' | 'STORE' + orgId: number + orgName: string + shareType: 'RATIO' | 'FIXED' + shareValue: number + /** 计算后金额(分) */ + amount: number +} + +export interface ProfitRulePreviewResp { + ruleId: number + ruleName: string + details: ProfitRulePreviewDetail[] + nonPlatformTotalRatio: number + warning: string | null +} + +// ===================== API 方法 ===================== + +/** 分润规则列表 */ +export function getProfitRuleList (params?: ProfitRuleListParams): Promise> { + return http.get(http.adornUrl('/manage/profit-rule/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 分润规则详情(含 items 子表) */ +export function getProfitRuleInfo (id: number): Promise> { + return http.get(http.adornUrl(`/manage/profit-rule/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 保存/更新分润规则 */ +export function saveOrUpdateProfitRule (data: ProfitRuleSaveBody): Promise { + const url = data.id ? '/manage/profit-rule/update' : '/manage/profit-rule/save' + return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data) +} + +/** 删除分润规则(body: Long[] ids) */ +export function deleteProfitRule (ids: number | number[]): Promise { + const arr = Array.isArray(ids) ? ids : [ids] + return http.post(http.adornUrl('/manage/profit-rule/delete'), http.adornData(arr, false)).then(res => res.data) +} + +/** 试算分润(POST /manage/profit-rule/preview) */ +export function previewProfitRule (data: ProfitRulePreviewBody): Promise> { + return http.post(http.adornUrl('/manage/profit-rule/preview'), http.adornData(data)).then(res => res.data) +} diff --git a/src/api/manage/profitSharing.ts b/src/api/manage/profitSharing.ts new file mode 100644 index 0000000..6ebbc99 --- /dev/null +++ b/src/api/manage/profitSharing.ts @@ -0,0 +1,86 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +// ===================== 分账记录 ===================== + +export interface ProfitSharingItem { + id: number + /** 支付订单号 */ + payOrderNo: string + /** 分账单号 */ + outOrderNo: string + status: 'PENDING' | 'SUCCESS' | 'FAILED' | 'PARTIAL' + /** 订单总金额(分) */ + totalAmount: number + ruleName: string | null + createdAt: string + storeName: string | null + channelName: string | null +} + +export interface ProfitSharingDetailItem { + id: number + orgRole: 'PLATFORM' | 'CHANNEL' | 'AGENT' | 'STORE' + orgName: string | null + receiverAccount: string + /** 分账金额(分) */ + amount: number + status: 'PENDING' | 'SUCCESS' | 'FAILED' + successTime: string | null + failReason: string | null +} + +export interface ProfitSharingDetail extends ProfitSharingItem { + /** 规则快照 JSON */ + ruleSnapshot: string | null + /** 组织链路快照 */ + orgPathSnapshot: string | null + details: ProfitSharingDetailItem[] +} + +export interface ProfitSharingListParams extends ManagePageParams { + orderNo?: string + status?: string + startDate?: string + endDate?: string +} + +/** 分账记录列表(含 details 子表) */ +export function getProfitSharingList (params?: ProfitSharingListParams): Promise> { + return http.get(http.adornUrl('/manage/profit-sharing/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 分账记录详情(含明细) */ +export function getProfitSharingInfo (id: number): Promise> { + return http.get(http.adornUrl(`/manage/profit-sharing/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 分账统计 */ +export interface ProfitSharingStatsSummary { + totalCount: number + totalAmount: number + successCount: number + successAmount: number +} + +export interface ProfitSharingStatsGroup { + orgId: number + orgName: string + orgType: string + count: number + amount: number +} + +export interface ProfitSharingStats { + summary: ProfitSharingStatsSummary + groups: ProfitSharingStatsGroup[] +} + +export function getProfitSharingStats (params?: { startDate?: string; endDate?: string; groupBy?: string }): Promise> { + return http.get(http.adornUrl('/manage/profit-sharing/stats'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 重试分账 */ +export function retryProfitSharing (id: number): Promise { + return http.post(http.adornUrl('/manage/profit-sharing/retry'), http.adornData({ id })).then(res => res.data) +} diff --git a/src/api/manage/refund.ts b/src/api/manage/refund.ts new file mode 100644 index 0000000..77d59d6 --- /dev/null +++ b/src/api/manage/refund.ts @@ -0,0 +1,60 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +// ===================== 退款记录 ===================== + +export interface RefundItem { + id: number + /** 退款单号 */ + refundNo: string + /** 原支付订单号 */ + payOrderNo: string + /** 退款金额(分) */ + refundAmount: number + /** 原订单金额(分) */ + totalAmount: number + /** 退款状态 */ + status: 'PENDING' | 'PROCESSING' | 'SUCCESS' | 'FAILED' | 'CLOSED' + /** 退款原因 */ + reason: string | null + /** 微信退款单号 */ + wxRefundId: string | null + /** 退款发起人 */ + operator: string | null + errorMessage: string | null + refundedAt: string | null + createdAt: string + updatedAt: string +} + +export interface RefundListParams extends ManagePageParams { + refundNo?: string + payOrderNo?: string + status?: string +} + +/** 发起退款请求体(文档:body {orderNo, reason}) */ +export interface RefundApplyBody { + orderNo: string + reason: string +} + +/** 退款记录列表 */ +export function getRefundList (params?: RefundListParams): Promise> { + return http.get(http.adornUrl('/manage/refund/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 退款详情(按退款单号 refundNo 查询) */ +export function getRefundInfo (refundNo: string): Promise> { + return http.get(http.adornUrl(`/manage/refund/info/${refundNo}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 发起退款(POST /manage/refund/apply) */ +export function applyRefund (data: RefundApplyBody): Promise { + return http.post(http.adornUrl('/manage/refund/apply'), http.adornData(data)).then(res => res.data) +} + +/** 重试退款 */ +export function retryRefund (id: number): Promise { + return http.post(http.adornUrl('/manage/refund/retry'), http.adornData({ id })).then(res => res.data) +} diff --git a/src/api/manage/stats.ts b/src/api/manage/stats.ts new file mode 100644 index 0000000..0e0f667 --- /dev/null +++ b/src/api/manage/stats.ts @@ -0,0 +1,73 @@ +import http from '@/utils/httpRequest' +import type { ManageResponse } from './types' + +/** + * 总览看板统计 + */ +export interface OverviewStats { + totalOrders: number + todayOrders: number + totalRevenue: number + todayRevenue: number + totalPool: number + availablePool: number + usedPool: number + activateFailed: number +} + +/** + * 订单趋势统计项 + */ +export interface OrderTrendItem { + date: string + orderCount: number + revenue: number +} + +/** + * 库存统计 + * 实际返回:statusStats / activateStats 均为 Map<状态, 数量> + */ +export interface PoolStats { + /** 按库存状态:{ UNUSED: 1, USED: 2 } */ + statusStats: Record + /** 按激活状态:{ PENDING: 2, FAILED: 1 } */ + activateStats: Record +} + +/** + * 渠道统计项 + */ +export interface ChannelStatItem { + channelOrgId: number + orderCount: number + revenue: number +} + +/** + * 订单趋势统计查询参数 + */ +export interface OrderStatsParams { + startDate: string + endDate: string +} + +/** 总览看板 */ +export function getOverviewStats(): Promise> { + return http.get(http.adornUrl('/manage/stats/overview'), { params: http.adornParams() }).then(res => res.data) +} + +/** 订单趋势统计 */ +export function getOrderStats(params: OrderStatsParams): Promise> { + return http.get(http.adornUrl('/manage/stats/orders'), { params: http.adornParams(params) }).then(res => res.data) +} + +/** 库存统计 */ +export function getPoolStats(): Promise> { + return http.get(http.adornUrl('/manage/stats/pool'), { params: http.adornParams() }).then(res => res.data) +} + +/** 渠道统计 */ +export function getChannelStats(): Promise> { + return http.get(http.adornUrl('/manage/stats/channels'), { params: http.adornParams() }).then(res => res.data) +} diff --git a/src/api/manage/store.ts b/src/api/manage/store.ts new file mode 100644 index 0000000..bbab712 --- /dev/null +++ b/src/api/manage/store.ts @@ -0,0 +1,63 @@ +import http from '@/utils/httpRequest' +import type { ManageListResponse, ManageResponse, ManagePageParams } from './types' + +/** + * 门店信息 + */ +export interface StoreInfo { + id: number + parentId: number + mpath: string + name: string + orderNo?: number + type: string + /** 后端 @JsonProperty("orgCode") 重命名,JSON 中为 orgCode */ + orgCode?: string + status: string + createdAt: string + updatedAt: string + /** 非表字段,后端 join 返回 */ + parentOrgName?: string + channelName?: string + children?: StoreInfo[] +} + +/** + * 门店列表查询参数 + */ +export interface StoreListParams extends ManagePageParams { + name?: string + status?: string + channelOrgId?: number +} + +/** + * 门店保存/更新数据 + */ +export interface StoreSaveData { + id?: number + parentId: number + name: string + orgCode?: string +} + +/** 门店分页列表 */ +export function getStoreList(params?: StoreListParams): Promise> { + return http.get(http.adornUrl('/manage/org/store/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 门店详情 */ +export function getStoreInfo(id: number): Promise> { + return http.get(http.adornUrl(`/manage/org/store/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +/** 新增/修改门店 */ +export function saveOrUpdateStore(data: StoreSaveData): Promise { + const url = data.id ? '/manage/org/store/update' : '/manage/org/store/save' + return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data) +} + +/** 删除门店(批量软删除) */ +export function deleteStore(ids: number[]): Promise { + return http.post(http.adornUrl('/manage/org/store/delete'), http.adornData(ids, false)).then(res => res.data) +} diff --git a/src/api/manage/types.ts b/src/api/manage/types.ts new file mode 100644 index 0000000..329bae3 --- /dev/null +++ b/src/api/manage/types.ts @@ -0,0 +1,33 @@ +/** + * /manage/ 接口共享类型定义 + * + * 统一响应格式:{ code, msg, data: {...} } + * - 业务数据统一在 data 字段内 + * - 分页结构在 data.page 内:{ data: { page: { totalCount, list, ... } } } + */ + +/** /manage/ 接口统一响应基础格式 */ +export interface ManageResponse { + code: number + msg: string + data: T +} + +/** /manage/ 分页 page 对象 */ +export interface ManagePage { + totalCount: number + pageSize?: number + totalPage?: number + currPage?: number + list: T[] +} + +/** /manage/ 分页列表响应 */ +export interface ManageListResponse extends ManageResponse<{ page: ManagePage }> {} + +/** 分页查询参数 */ +export interface ManagePageParams { + page?: number + limit?: number + [key: string]: any +} diff --git a/src/api/mediaAsset.ts b/src/api/mediaAsset.ts new file mode 100755 index 0000000..bf2c240 --- /dev/null +++ b/src/api/mediaAsset.ts @@ -0,0 +1,53 @@ +import http from '@/utils/httpRequest' +import type { ApiResponse, PageParams, PageResult } from '@/types/api' + +/** + * 媒资信息 + */ +export interface MediaAsset { + id: number + name: string + code: string + isOnline?: number + deleteFlag?: number + region?: string + releaseYear?: number + [key: string]: any +} + +/** + * 媒资列表参数 + */ +export interface MediaAssetListParams extends PageParams { + name?: string + code?: string + isOnline?: number + deleteFlag?: number + region?: string + releaseYear?: number +} + +/** + * 媒资分页列表 + */ +export function getMediaAssetList( + params?: MediaAssetListParams +): Promise>> { + return http.get(http.adornUrl('/sys/mediaAsset/list'), { params: http.adornParams(params || {}) }) +} + +/** 媒资详情 */ +export function getMediaAssetInfo(id: number): Promise> { + return http.get(http.adornUrl(`/sys/mediaAsset/info/${id}`), { params: http.adornParams() }) +} + +/** 修改/添加媒资 */ +export function saveMediaAsset(data: Partial): Promise> { + const url = data.id ? '/sys/mediaAsset/update' : '/sys/mediaAsset/save' + return http.post(http.adornUrl(url), http.adornData(data)) +} + +/** 删除媒资 */ +export function deleteMediaAsset(ids: number[]): Promise> { + return http.post(http.adornUrl('/sys/mediaAsset/delete'), http.adornData(ids, false)) +} diff --git a/src/api/mediaAssetRank.ts b/src/api/mediaAssetRank.ts new file mode 100755 index 0000000..e9bde57 --- /dev/null +++ b/src/api/mediaAssetRank.ts @@ -0,0 +1,95 @@ +import http from '@/utils/httpRequest' +import type { ApiResponse } from '@/types/api' + +/** + * 媒资排行项 + */ +export interface MediaAssetRankItem { + code: string + name: string + sortOrder: number + [key: string]: any +} + +/** + * 设置排行榜数据 + */ +export interface SetRankData { + codeList: string[] +} + +/** + * 排序更新数据 + */ +export interface UpdateSortData { + code?: string + targetSortOrder?: number + orderList?: Array<{ code: string; sortOrder: number }> +} + +/** 获取当前 Top10 榜(含媒资信息) */ +export function getMediaAssetRankTop10(): Promise> { + return http.get(http.adornUrl('/sys/mediaAssetRank/top10'), { params: http.adornParams() }) +} + +/** 当前排序/序号信息 */ +export function getMediaAssetRankGetSortOrder(): Promise> { + return http.get(http.adornUrl('/sys/mediaAssetRank/getSortOrder'), { params: http.adornParams() }) +} + +/** + * 批量设置排行榜 + * 若依侧通过 adornData 会附带 t 等默认字段,一般与 Jackson 兼容。 + * @param data 仅编码数组,或 { codeList } + */ +export function setMediaAssetRank(data: string[] | SetRankData): Promise> { + const codeList = Array.isArray(data) + ? data + : data?.codeList || [] + return http.post( + http.adornUrl('/sys/mediaAssetRank/set'), + http.adornData({ codeList }, true) + ) +} + +/** 单条移除 */ +export function removeMediaAssetRank(code: string): Promise> { + return http.post( + http.adornUrl('/sys/mediaAssetRank/remove'), + http.adornData({ code }, true) + ) +} + +/** + * 调整排序 + * 请求体与后端一致,如 { code, targetSortOrder } 或 { orderList: [...] } 等 + */ +export function updateMediaAssetRankSort(data: UpdateSortData): Promise> { + return http.post( + http.adornUrl('/sys/mediaAssetRank/updateSort'), + http.adornData(data && typeof data === 'object' ? data : {}, true) + ) +} + +/** 上移一位 */ +export function moveUpMediaAssetRank(code: string): Promise> { + return http.post( + http.adornUrl('/sys/mediaAssetRank/moveUp'), + http.adornData({}), + { params: http.adornParams({ code }) } + ) +} + +/** 下移一位 */ +export function moveDownMediaAssetRank(code: string): Promise> { + return http.post( + http.adornUrl('/sys/mediaAssetRank/moveDown'), + http.adornData({}), + { params: http.adornParams({ code }) } + ) +} + +/** 清空排行榜 */ +export function clearMediaAssetRank(): Promise> { + return http.post(http.adornUrl('/sys/mediaAssetRank/clear'), http.adornData({})) +} diff --git a/src/api/org.ts b/src/api/org.ts new file mode 100755 index 0000000..3dd62dc --- /dev/null +++ b/src/api/org.ts @@ -0,0 +1,148 @@ +import http from '@/utils/httpRequest' +import type { ApiResponse, PageParams, PageResult } from '@/types/api' + +/** + * 组织信息 + */ +export interface OrgInfo { + id: number + name: string + parentId?: number + type?: string + status?: string + [key: string]: any +} + +/** + * 组织列表参数 + */ +export interface OrgListParams extends PageParams { + name?: string + type?: string +} + +/** + * 组织卡统计 + */ +export interface OrgCardStats { + allocatable: number + activated: number + pendingActivation: number +} + +/** + * 组织卡总览 + */ +export interface OrgCardOverview { + totalCount: number + usedCount: number + availableCount: number +} + +/** + * 组织版本信息 + */ +export interface OrgVersionInfo { + orgId: number + verCode?: string + verName?: string + url?: string + touchUrl?: string + keyUrl?: string + compulsory?: boolean +} + +/** 组织树 */ +export function getOrgTree(params?: OrgListParams): Promise> { + return http.get(http.adornUrl('/manage/org/tree'), { params: http.adornParams(params || {}) }) +} + + +/** 组织树(含门店):全类型组织树,含 STORE 节点,用于门店选择器等 */ +export function getOrgAllTree(params?: OrgListParams): Promise> { + return http.get(http.adornUrl('/manage/org/all-tree'), { params: http.adornParams(params || {}) }) +} + +/** + * 解析 /manage/org/list-data 等接口响应体中的扁平组织列表。 + * 兼容:顶层 `list`、或 `data` 为数组、或 `data: { list }`。 + */ +export function parseOrgListDataBody(body: Record | null | undefined): OrgInfo[] { + if (!body) return [] + if (Array.isArray(body.list)) return body.list as OrgInfo[] + const inner = body.data + if (Array.isArray(inner)) return inner as OrgInfo[] + if (inner && typeof inner === 'object' && Array.isArray(inner.list)) return inner.list as OrgInfo[] + return [] +} + +/** 组织列表(扁平,用于下拉/树选) */ +export function getOrgListData(params?: OrgListParams): Promise> { + return http.get(http.adornUrl('/manage/org/list-data'), { params: http.adornParams(params || {}) }) +} + +/** 组织列表(/list) */ +export function getOrgList(params?: OrgListParams): Promise>> { + return http.get(http.adornUrl('/manage/org/list'), { params: http.adornParams(params || {}) }) +} + +/** 当前账号数据范围内全部渠道(type=CHANNEL、ACTIVE)扁平列表 */ +export function getOrgChannels(): Promise> { + return http.get(http.adornUrl('/manage/org/channels'), { params: http.adornParams() }) +} + +/** 指定渠道下仅 SERVICE_PROVIDER 的多级树(不含门店) */ +export function getChannelAgentTree(channelId: number): Promise> { + return http.get(http.adornUrl(`/manage/org/channel/${channelId}/agent-tree`), { params: http.adornParams() }) +} + +/** 组织详情 */ +export function getOrgInfo(id: number): Promise> { + return http.get(http.adornUrl(`/manage/org/info/${id}`), { params: http.adornParams() }) +} + +/** 删除组织(单个或批量) */ +export function deleteOrg(ids: number[]): Promise> { + return http.post(http.adornUrl('/manage/org/delete'), http.adornData(ids, false)) +} + +/** 组织下卡统计(可分配/已激活/待激活) */ +export function getOrgCardStats(orgId: number): Promise> { + return http.get(http.adornUrl(`/manage/org/${orgId}/card-stats`), { params: http.adornParams() }) +} + +/** 组织卡总览统计(用于设备导入页顶部数据概览) */ +export function getOrgCardOverview(params?: { orgId?: number }): Promise> { + return http.get(http.adornUrl('/manage/org/card-overview'), { params: http.adornParams(params || {}) }) +} + +/** 按卡类型维度的明细统计(首页/全库口径) */ +export function getOrgCardTypeDetailStats(params?: { orgId?: number }): Promise> { + return http.get(http.adornUrl('/manage/org/card-type-detail-stats'), { params: http.adornParams(params || {}) }) +} + +/** 同渠道组织树(用于设备卡转移选择目标组织) */ +export function getSameChannelOrgs(orgId: number): Promise> { + return http.get(http.adornUrl(`/manage/org/${orgId}/same-channel-orgs`), { params: http.adornParams() }) +} + +/** 组织保存/更新(根据是否有 id 决定) */ +export function saveOrUpdateOrg(data: Partial): Promise> { + const url = data.id ? '/manage/org/update' : '/manage/org/save' + return http.post(http.adornUrl(url), http.adornData(data)) +} + +/** 组织版本详情 */ +export function getOrgVersionInfo(orgId: number): Promise> { + return http.get(http.adornUrl('/sys/org-version/info'), { params: http.adornParams({ orgId }) }) +} + +/** 组织版本保存 { orgId, verCode, ver_name, url, compulsory } */ +export function saveOrgVersion(data: OrgVersionInfo): Promise> { + return http.post(http.adornUrl('/sys/org-version/save'), http.adornData(data)) +} + +/** 删除组织版本 */ +export function deleteOrgVersion(orgId: number): Promise> { + return http.post(http.adornUrl('/sys/org-version/delete'), http.adornData({ orgId })) +} diff --git a/src/api/oss.ts b/src/api/oss.ts new file mode 100755 index 0000000..f4def9d --- /dev/null +++ b/src/api/oss.ts @@ -0,0 +1,60 @@ +import http from '@/utils/httpRequest' +/** + * 后端 STS 临时凭证(字段名兼容常见驼峰写法;与 COS getAuthorization 入参对齐) + */ +export interface OssStsCredentialPayload { + TmpSecretId?: string + tmpSecretId?: string + TmpSecretKey?: string + tmpSecretKey?: string + SecurityToken?: string + securityToken?: string + sessionToken?: string + /** 过期时间戳(秒,或毫秒则由上传工具归一化) */ + ExpiredTime?: number + expiredTime?: number + bucket?: string + Bucket?: string + region?: string + Region?: string + /** 对象 Key(须与 STS 策略一致,不可自行改写) */ + key?: string + Key?: string + /** 上传成功后的访问地址 */ + url?: string + /** 以下字段不参与 COS 前端上传,仅占位兼容接口 */ + appId?: number + startTime?: number + durationSeconds?: number +} + +/** GET /sys/oss/sts-credential 实际响应:凭证在顶层 `credential`(非标准 `data`) */ +export interface OssStsCredentialApiResponse { + code: number + msg: string + credential?: OssStsCredentialPayload + /** 兼容若后端改为包在 data 内 */ + data?: OssStsCredentialPayload +} + +export interface OssStsCredentialOptions { + /** 为 true 时请求保留原始文件名(不去重哈希),需后端 sts-credential 支持 */ + keepOriginalFileName?: boolean +} + +/** GET /sys/oss/sts-credential?filename=xxx */ +export function getOssStsCredential ( + filename: string, + options?: OssStsCredentialOptions +): Promise { + const params: Record = { filename } + if (options?.keepOriginalFileName) { + params.keepOriginalFileName = 1 + params.dedupe = 0 + } + return http + .get(http.adornUrl('/sys/oss/sts-credential'), { + params: http.adornParams(params), + }) + .then(res => res.data) +} diff --git a/src/api/store.ts b/src/api/store.ts new file mode 100755 index 0000000..2a705b0 --- /dev/null +++ b/src/api/store.ts @@ -0,0 +1,54 @@ +import http from '@/utils/httpRequest' +import type { ApiResponse, PageParams, PageResult } from '@/types/api' + +/** + * 门店信息 + */ +export interface StoreInfo { + id: number + name: string + orgId: number + status?: string + [key: string]: any +} + +/** + * 门店列表参数 + */ +export interface StoreListParams extends PageParams { + name?: string + orgId?: number +} + +/** + * 门店卡信息 + */ +export interface StoreCard { + id: number + cardNo: string + status: string + [key: string]: any +} + +/** 门店列表(下拉等场景) */ +export function getStoreList(params?: StoreListParams): Promise> { + return http.get(http.adornUrl('/manage/store/list'), { params: http.adornParams(params || {}) }) +} + +/** 按代理商组织查询门店(与 list + orgId=代理商 等价;会校验目标为 SERVICE_PROVIDER) */ +export function getStoreListByAgent(agentOrgId: number): Promise> { + return http.get(http.adornUrl(`/manage/store/list-by-agent/${agentOrgId}`), { params: http.adornParams() }) +} + +/** 门店搜索(分页) */ +export function searchStore(params?: StoreListParams): Promise>> { + return http.get(http.adornUrl('/manage/store/search'), { params: http.adornParams(params || {}) }) +} + +/** 门店下的卡列表 */ +export function getStoreCards( + storeId: number, + params?: PageParams +): Promise>> { + return http.get(http.adornUrl(`/manage/store/${storeId}/cards`), { params: http.adornParams(params || {}) }) +} diff --git a/src/api/sys.ts b/src/api/sys.ts new file mode 100755 index 0000000..4b0828d --- /dev/null +++ b/src/api/sys.ts @@ -0,0 +1,351 @@ +import http from '@/utils/httpRequest' +import type { ApiResponse, PageParams, PageResult } from '@/types/api' +import { uploadFileViaStsCos } from '@/utils/ossCosUpload' + +// ==================== 类型定义 ==================== + +/** + * 登录表单数据 + */ +export interface LoginData { + username: string + password: string + captcha: string + uuid: string +} + +/** + * 登录响应 + */ +export interface LoginResult { + token: string + expire: number + refreshToken?: string + refreshExpire?: number +} + +/** + * 用户信息 + */ +export interface UserInfo { + id: number + username: string + realName?: string + avatar?: string + roleIdList?: number[] + orgId?: number + orgName?: string + [key: string]: any +} + +/** + * 菜单信息 + */ +export interface MenuInfo { + id: number + parentId?: number + name: string + url?: string + icon?: string + sort?: number + show?: number + perms?: string + list?: MenuInfo[] + [key: string]: any +} + +/** + * 菜单导航响应 + */ +export interface MenuNavResponse { + code: number + menuList: MenuInfo[] + permissions: string[] +} + +/** + * 角色信息 + */ +export interface RoleInfo { + id: number + roleName: string + remark?: string + [key: string]: any +} + +/** + * 参数配置 + */ +export interface ConfigInfo { + id: number + paramKey: string + paramValue: string + remark?: string + [key: string]: any +} + +/** + * 定时任务 + */ +export interface ScheduleInfo { + jobId?: number + beanName: string + methodName: string + params?: string + cronExpression: string + status?: number + remark?: string + [key: string]: any +} + +/** + * 日志信息 + */ +export interface LogInfo { + id: number + operation: string + method: string + params?: string + time?: number + ip?: string + createDate?: string + [key: string]: any +} + +/** + * 审计日志 + */ +export interface AuditLogInfo extends LogInfo { + module?: string + action?: string + [key: string]: any +} + +/** 吉客云 / JST API 调用日志(设备与组织可为空) */ +export interface ApiJstCallLogInfo { + id?: number + apiPath?: string | null + requestBody?: string | null + dataId?: string | number | null + createTime?: string | null + mac?: string | null + deviceSn?: string | null + deviceUid?: string | null + storeOrgId?: number | null + storeOrgName?: string | null + storeOrgCode?: string | null + storeOrgType?: string | null + [key: string]: any +} + +/** + * 定时任务日志 + */ +export interface ScheduleLogInfo { + logId: number + jobId: number + beanName: string + methodName: string + params?: string + status?: number + error?: string + times?: number + createTime?: string + [key: string]: any +} + +// ==================== 登录 / 认证 ==================== + +export function login(data: LoginData): Promise> { + return http.post(http.adornUrl('/sys/login'), http.adornData(data)).then(res => res.data) +} + +export function logout(): Promise> { + return http.post(http.adornUrl('/sys/logout'), http.adornData({})).then(res => res.data) +} + +/** 获取当前登录用户信息;若传入 userId,则获取指定用户信息 */ +export function getUserInfo(userId?: number | string | null): Promise> { + const url = userId !== null && userId !== undefined && userId !== '' + ? `/manage/user/info/${userId}` + : '/manage/user/info' + return http.get(http.adornUrl(url), { params: http.adornParams() }).then(res => res.data) +} + +export function updatePassword(data: { password: string; newPassword: string }): Promise> { + return http.post(http.adornUrl('/manage/user/password'), http.adornData(data)).then(res => res.data) +} + +// ==================== 菜单 ==================== + +export function getMenuNav(): Promise> { + return http.get(http.adornUrl('/manage/menu/nav'), { params: http.adornParams() }).then(res => res.data) +} + +/** 验证码图片地址(img src 需完整路径 /api/xxx,走代理) */ +export function getCaptchaUrl(uuid: string): string { + return http.adornUrl(`/captcha.jpg?uuid=${uuid}`) +} + +export function getMenuList(params?: PageParams): Promise>> { + return http.get(http.adornUrl('/manage/menu/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +export function getMenuSelect(): Promise> { + return http.get(http.adornUrl('/manage/menu/select'), { params: http.adornParams() }).then(res => res.data) +} + +export function getMenuInfo(id: number): Promise> { + return http.get(http.adornUrl(`/manage/menu/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +export function saveMenu(data: Partial): Promise> { + const url = data.id ? '/manage/menu/update' : '/manage/menu/save' + return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data) +} + +export function deleteMenu(id: number): Promise> { + return http.post(http.adornUrl(`/manage/menu/delete/${id}`), http.adornData({})).then(res => res.data) +} + +// ==================== 用户 ==================== + +export function getUserList(params?: PageParams): Promise>> { + return http.get(http.adornUrl('/manage/user/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +export function getUserInfoById(id: number): Promise> { + return getUserInfo(id) +} + +export function saveUser(data: Partial): Promise> { + const url = data.id ? '/manage/user/update' : '/manage/user/save' + return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data) +} + +export function deleteUser(ids: number[]): Promise> { + return http.post(http.adornUrl('/manage/user/delete'), http.adornData(ids, false)).then(res => res.data) +} + +export function getRoleSelect(): Promise> { + return http.get(http.adornUrl('/manage/role/select'), { params: http.adornParams() }).then(res => res.data) +} + +// ==================== 角色 ==================== + +export function getRoleList(params?: PageParams): Promise>> { + return http.get(http.adornUrl('/manage/role/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +export function getRoleInfo(id: number): Promise> { + return http.get(http.adornUrl(`/manage/role/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +export function saveRole(data: Partial): Promise> { + const url = data.id ? '/manage/role/update' : '/manage/role/save' + return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data) +} + +export function deleteRole(ids: number[]): Promise> { + return http.post(http.adornUrl('/manage/role/delete'), http.adornData(ids, false)).then(res => res.data) +} + +// ==================== 参数配置 ==================== + +export function getConfigList(params?: PageParams): Promise>> { + return http.get(http.adornUrl('/sys/config/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +export function getConfigInfo(id: number): Promise> { + return http.get(http.adornUrl(`/sys/config/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +export function saveConfig(data: Partial): Promise> { + const url = data.id ? '/sys/config/update' : '/sys/config/save' + return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data) +} + +export function deleteConfig(ids: number[]): Promise> { + return http.post(http.adornUrl('/sys/config/delete'), http.adornData(ids, false)).then(res => res.data) +} + +// ==================== 日志 ==================== + +export function getLogList(params?: PageParams): Promise>> { + return http.get(http.adornUrl('/sys/log/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** 审计日志;分页结构含 totalCount、list 等,与系统日志分页一致 */ +export function getAuditLogList(params?: PageParams): Promise>> { + return http.get(http.adornUrl('/sys/auditLog/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +/** API 调用日志(JST 等);分页结构与审计日志一致 */ +export function getApiJstCallLogList(params?: PageParams): Promise>> { + return http.get(http.adornUrl('/sys/apiJstCallLog/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +// ==================== 定时任务 ==================== + +export function getScheduleList(params?: PageParams): Promise>> { + return http.get(http.adornUrl('/sys/schedule/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +export function getScheduleInfo(id: number): Promise> { + return http.get(http.adornUrl(`/sys/schedule/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +export function saveSchedule(data: Partial): Promise> { + const url = data.jobId ? '/sys/schedule/update' : '/sys/schedule/save' + return http.post(http.adornUrl(url), http.adornData(data)).then(res => res.data) +} + +export function deleteSchedule(ids: number[]): Promise> { + return http.post(http.adornUrl('/sys/schedule/delete'), http.adornData(ids, false)).then(res => res.data) +} + +export function pauseSchedule(jobId: number): Promise> { + return http.post(http.adornUrl('/sys/schedule/pause'), http.adornData({ jobId })).then(res => res.data) +} + +export function resumeSchedule(jobId: number): Promise> { + return http.post(http.adornUrl('/sys/schedule/resume'), http.adornData({ jobId })).then(res => res.data) +} + +export function runSchedule(jobId: number): Promise> { + return http.post(http.adornUrl('/sys/schedule/run'), http.adornData({ jobId })).then(res => res.data) +} + +// ==================== 定时任务日志 ==================== + +export function getScheduleLogList(params?: PageParams): Promise>> { + return http.get(http.adornUrl('/sys/scheduleLog/list'), { params: http.adornParams(params || {}) }).then(res => res.data) +} + +export function getScheduleLogInfo(id: number): Promise> { + return http.get(http.adornUrl(`/sys/scheduleLog/info/${id}`), { params: http.adornParams() }).then(res => res.data) +} + +// ==================== OSS 上传 ==================== + +/** 直传 COS:GET STS 凭证后前端 putObject,成功返回 data.url(与后端下发 key 一致) */ +export async function uploadOssDedupe (file: File): Promise> { + try { + const url = await uploadFileViaStsCos(file) + return { code: 0, msg: 'success', data: { url } } + } catch (e: unknown) { + const message = e instanceof Error ? e.message : '上传失败' + return { code: 500, msg: message, data: { url: '' } } + } +} + +/** 直传 COS 且保留原始文件名(版本 APK 等场景,需后端 sts-credential 支持 keepOriginalFileName) */ +export async function uploadOssKeepFileName (file: File): Promise> { + try { + const url = await uploadFileViaStsCos(file, { keepOriginalFileName: true }) + return { code: 0, msg: 'success', data: { url } } + } catch (e: unknown) { + const message = e instanceof Error ? e.message : '上传失败' + return { code: 500, msg: message, data: { url: '' } } + } +} diff --git a/src/assets/img/avatar.png b/src/assets/img/avatar.png new file mode 100755 index 0000000..88526ec Binary files /dev/null and b/src/assets/img/avatar.png differ diff --git a/src/assets/img/login_bg.jpg b/src/assets/img/login_bg.jpg new file mode 100755 index 0000000..e8f43fc Binary files /dev/null and b/src/assets/img/login_bg.jpg differ diff --git a/src/assets/scss/_base.scss b/src/assets/scss/_base.scss new file mode 100755 index 0000000..5a86d12 --- /dev/null +++ b/src/assets/scss/_base.scss @@ -0,0 +1,441 @@ +@use "sass:color"; +@use "./variables" as v; + +*, +*:before, +*:after { + box-sizing: border-box; +} +body { + font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif; + font-size: 14px; + line-height: 1.15; + color: #303133; + background-color: #fff; +} +a { + color: color.mix(#fff, v.$color-primary, 20%); + text-decoration: none; + &:focus, + &:hover { + color: v.$color-primary; + text-decoration: underline; + } +} +img { + vertical-align: middle; +} + + +/* Utils +------------------------------ */ +.clearfix:before, +.clearfix:after { + content: " "; + display: table; +} +.clearfix:after { + clear: both; +} + + +/* Animation +------------------------------ */ +.fade-enter-active, +.fade-leave-active { + transition: opacity .5s; +} +.fade-enter, +.fade-leave-to { + opacity: 0; +} + + +/* Reset element-ui +------------------------------ */ +.site-wrapper { + .el-pagination { + margin-top: 15px; + text-align: right; + display: flex; + justify-content: flex-end; + } +} + +/* 表格+分页:分页在表格下方靠右(表格右下角) */ +.table-page-wrap { + .el-pagination { + margin-top: 15px; + text-align: right; + display: flex; + justify-content: flex-end; + } +} + +/* 全局:所有分页均在表格/内容右下 */ +.el-pagination { + display: flex; + justify-content: flex-end; +} + + +/* Layout +------------------------------ */ +.site-wrapper { + position: relative; + min-width: 1180px; +} + + +/* Sidebar fold +------------------------------ */ +.site-sidebar--fold { + .site-navbar__header, + .site-sidebar, + .site-sidebar__inner, + .el-menu.site-sidebar__menu { + width: 64px; + } + .site-navbar__body, + .site-content__wrapper { + margin-left: 64px; + } + // 折叠时仅保留文字(显示 brand-mini),隐藏图标按钮 + .site-navbar__brand { + &-lg { + display: none; + } + &-mini { + display: inline-block; + } + } + .site-navbar__switch { + display: none; + } + .site-sidebar, + .site-sidebar__inner { + overflow: initial; + } + .site-sidebar__menu-icon { + margin-right: 0; + font-size: 20px; + } + // 折叠后只显示图标:隐藏菜单标题中的文字部分 + .site-sidebar__menu { + .el-menu-item span, + .el-sub-menu__title span { + display: none; + } + .el-menu-item__title { + display: none; + } + } + .site-content--tabs > .el-tabs > .el-tabs__header { + left: 64px; + } +} +// animation +.site-navbar__header, +.site-navbar__brand, +.site-navbar__body, +.site-sidebar, +.site-sidebar__inner, +.site-sidebar__menu.el-menu, +.site-sidebar__menu-icon, +.site-content__wrapper, +.site-content--tabs > .el-tabs .el-tabs__header { + transition: inline-block .3s, left .3s, width .3s, margin-left .3s, font-size .3s; +} + + +/* Navbar +------------------------------ */ +.site-navbar { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; + height: 50px; + box-shadow: 0 2px 4px rgba(0, 0, 0, .08); + background-color: v.$navbar-background-color; + + &--inverse { + .site-navbar__body { + background-color: transparent; + } + .site-navbar__body > .el-dropdown .el-dropdown-link { + color: #fff; + } + .el-menu { + > .el-menu-item, + > .el-sub-menu > .el-sub-menu__title { + color: #fff; + &:focus, + &:hover { + color: #fff; + background-color: color.mix(#000, v.$navbar-background-color, 15%); + } + } + > .el-menu-item.is-active, + > .el-sub-menu.is-active > .el-sub-menu__title { + border-bottom-color: color.mix(#fff, v.$navbar-background-color, 85%); + } + .el-menu-item i, + .el-sub-menu__title i, + .el-dropdown { + color: #fff; + } + } + .el-menu--popup-bottom-start { + background-color: v.$navbar-background-color; + } + } + + &__header { + position: relative; + float: left; + width: 230px; + height: 50px; + overflow: hidden; + } + &__brand { + display: table-cell; + vertical-align: middle; + width: 230px; + height: 50px; + margin: 0; + line-height: 50px; + font-size: 20px; + text-align: center; + text-transform: uppercase; + white-space: nowrap; + color: #fff; + + &-lg, + &-mini { + margin: 0 5px; + color: #fff; + &:focus, + &:hover { + color: #fff; + text-decoration: none; + } + } + &-mini { + display: none; + } + } + &__switch { + display: none; + font-size: 18px; + border-bottom: none !important; + position: absolute; + left: 10px; + top: 50%; + transform: translateY(-50%); + line-height: 1; + } + &__avatar { + font-size: 18px; + border-bottom: none !important; + * { + vertical-align: inherit; + } + .el-dropdown__icon, + .el-icon { + display: none !important; + } + .el-dropdown-link { + display: inline-flex; + align-items: center; + > img { + width: 36px; + height: 36px; + margin-right: 0; + object-fit: cover; + border-radius: 100%; + vertical-align: middle; + } + } + &.site-navbar__avatar-wrap .el-dropdown-link > img { + margin: 0; + } + } + &__body { + position: relative; + margin-left: 230px; + padding-right: 15px; + background-color: #fff; + > .el-dropdown.site-navbar__avatar-wrap { + float: right; + height: 50px; + line-height: 50px; + display: flex; + align-items: center; + .el-dropdown__icon, + .el-icon { + display: none !important; + } + .el-dropdown-link { + display: inline-flex; + align-items: center; + cursor: pointer; + > img { + width: 36px; + height: 36px; + object-fit: cover; + border-radius: 100%; + vertical-align: middle; + } + } + } + } + &__menu { + float: left; + background-color: transparent; + border-bottom: 0; + + &--right { + float: right; + } + a:focus, + a:hover { + text-decoration: none; + } + .el-menu-item, + .el-sub-menu > .el-sub-menu__title { + height: 50px; + line-height: 50px; + } + .el-sub-menu > .el-menu { + top: 55px; + } + .el-badge { + display: inline; + z-index: 2; + &__content { + line-height: 16px; + } + } + } +} + + +/* Sidebar +------------------------------ */ +.site-sidebar { + position: fixed; + top: 50px; + left: 0; + bottom: 0; + z-index: 1020; + width: 230px; + overflow: hidden; + + &--dark, + &--dark-popper { + background-color: v.$sidebar-background-color-dark; + .site-sidebar__menu.el-menu, + > .el-menu--popup { + background-color: v.$sidebar-background-color-dark; + .el-menu-item, + .el-sub-menu > .el-sub-menu__title { + color: v.$sidebar-color-text-dark; + &:focus, + &:hover { + color: color.mix(#fff, v.$sidebar-color-text-dark, 50%); + background-color: color.mix(#fff, v.$sidebar-background-color-dark, 2.5%); + } + } + .el-menu, + .el-sub-menu.is-opened { + background-color: color.mix(#000, v.$sidebar-background-color-dark, 15%); + } + .el-menu-item.is-active, + .el-sub-menu.is-active > .el-sub-menu__title { + color: color.mix(#fff, v.$sidebar-color-text-dark, 80%); + } + } + } + &__inner { + position: relative; + z-index: 1; + width: 250px; + height: 100%; + padding-bottom: 15px; + overflow-y: scroll; + } + &__menu.el-menu { + width: 230px; + border-right: 0; + } + &__menu-icon { + width: 24px; + margin-right: 5px; + text-align: center; + font-size: 16px; + color: inherit !important; + } +} + + +/* Content +------------------------------ */ +.site-content { + position: relative; + padding: 15px; + + &__wrapper { + position: relative; + padding-top: 50px; + margin-left: 230px; + min-height: 100%; + background: v.$content-background-color; + } + &--tabs { + padding: 55px 0 0; + } + > .el-tabs { + > .el-tabs__header { + position: fixed; + top: 50px; + left: 230px; + right: 0; + z-index: 930; + padding: 0 55px 0 15px; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .12), 0 0 6px 0 rgba(0, 0, 0, .04); + background-color: #fff; + > .el-tabs__nav-wrap { + margin-bottom: 0; + &:after { + display: none; + } + } + } + > .el-tabs__content { + padding: 0 15px 15px; + > .site-tabs__tools { + position: fixed; + top: 50px; + right: 0; + z-index: 931; + height: 40px; + padding: 0 12px; + font-size: 16px; + line-height: 40px; + background-color: v.$content-background-color; + cursor: pointer; + .el-icon--right { + margin-left: 0; + } + } + } + } +} +.el-table__expand-icon { + display: inline-block; + width: 14px; + vertical-align: middle; + margin-right: 5px; +} diff --git a/src/assets/scss/_normalize.scss b/src/assets/scss/_normalize.scss new file mode 100755 index 0000000..9bb2529 --- /dev/null +++ b/src/assets/scss/_normalize.scss @@ -0,0 +1,447 @@ +/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in + * IE on Windows Phone and in iOS. + */ + + html { + line-height: 1.15; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers (opinionated). + */ + +body { + margin: 0; +} + +/** + * Add the correct display in IE 9-. + */ + +article, +aside, +footer, +header, +nav, +section { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + * 1. Add the correct display in IE. + */ + +figcaption, +figure, +main { /* 1 */ + display: block; +} + +/** + * Add the correct margin in IE 8. + */ + +figure { + margin: 1em 40px; +} + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * 1. Remove the gray background on active links in IE 10. + * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. + */ + +a { + background-color: transparent; /* 1 */ + -webkit-text-decoration-skip: objects; /* 2 */ +} + +/** + * 1. Remove the bottom border in Chrome 57- and Firefox 39-. + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Prevent the duplicate application of `bolder` by the next rule in Safari 6. + */ + +b, +strong { + font-weight: inherit; +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font style in Android 4.3-. + */ + +dfn { + font-style: italic; +} + +/** + * Add the correct background and color in IE 9-. + */ + +mark { + background-color: #ff0; + color: #000; +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + */ + +audio, +video { + display: inline-block; +} + +/** + * Add the correct display in iOS 4-7. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Remove the border on images inside links in IE 10-. + */ + +img { + border-style: none; +} + +/** + * Hide the overflow in IE. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers (opinionated). + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: sans-serif; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` + * controls in Android 4. + * 2. Correct the inability to style clickable types in iOS and Safari. + */ + +button, +html [type="button"], /* 1 */ +[type="reset"], +[type="submit"] { + -webkit-appearance: button; /* 2 */ +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * 1. Add the correct display in IE 9-. + * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Remove the default vertical scrollbar in IE. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10-. + * 2. Remove the padding in IE 10-. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in IE 9-. + * 1. Add the correct display in Edge, IE, and Firefox. + */ + +details, /* 1 */ +menu { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Scripting + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + */ + +canvas { + display: inline-block; +} + +/** + * Add the correct display in IE. + */ + +template { + display: none; +} + +/* Hidden + ========================================================================== */ + +/** + * Add the correct display in IE 10-. + */ + +[hidden] { + display: none; +} \ No newline at end of file diff --git a/src/assets/scss/_variables.scss b/src/assets/scss/_variables.scss new file mode 100755 index 0000000..de8df84 --- /dev/null +++ b/src/assets/scss/_variables.scss @@ -0,0 +1,13 @@ +// 站点主色(与 Element UI 默认主题一致:#409EFF) +// tips: 要达到整站主题修改效果, 请确保[$color-primary]站点主色与[/src/element-ui-theme/index.js]文件中[import './element-[#17B3A3]/index.css']当前主题色一致 +$color-primary: #409EFF; + +// Navbar +$navbar-background-color: $color-primary; + +// Sidebar +$sidebar-background-color-dark: #263238; +$sidebar-color-text-dark: #8a979e; + +// Content +$content-background-color: #f1f4f5; diff --git a/src/assets/scss/index.scss b/src/assets/scss/index.scss new file mode 100755 index 0000000..7010342 --- /dev/null +++ b/src/assets/scss/index.scss @@ -0,0 +1,4 @@ +// Dart Sass 推荐使用 @use 替代已弃用的 @import +@use "./normalize"; +@use "./variables"; +@use "./base"; diff --git a/src/components/NearExpiryUnusedCardsDialog.vue b/src/components/NearExpiryUnusedCardsDialog.vue new file mode 100755 index 0000000..f12ced9 --- /dev/null +++ b/src/components/NearExpiryUnusedCardsDialog.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/src/components/agent-store-select/index.data.ts b/src/components/agent-store-select/index.data.ts new file mode 100755 index 0000000..83ec21a --- /dev/null +++ b/src/components/agent-store-select/index.data.ts @@ -0,0 +1,49 @@ +import type { StoreInfo } from '@/api/store' + +/** AgentStoreSelect 组件 Props */ +export interface AgentStoreSelectProps { + /** 渠道组织 ID(CHANNEL) */ + channelId?: string | number | null + /** 代理商组织 ID(SERVICE_PROVIDER) */ + agentOrgId?: string | number | null + /** 当前选中的值 */ + modelValue?: string | number | null + /** 占位符文本 */ + placeholder?: string + /** 需要先选择代理商时的占位符 */ + placeholderNeedAgent?: string + /** 需要先选择渠道或代理商时的占位符 */ + placeholderNeedScope?: string + /** 是否可搜索 */ + filterable?: boolean + /** 是否可清空 */ + clearable?: boolean + /** 是否禁用 */ + disabled?: boolean + /** 选择器宽度 */ + width?: string + /** 是否自动加载 */ + autoLoad?: boolean + /** 无数据时的占位文本 */ + emptyText?: string +} + +/** 门店选项 */ +export interface StoreOption { + /** 门店 ID */ + id: string | number + /** 门店名称 */ + name: string + /** 原始数据 */ + raw: StoreInfo +} + +/** AgentStoreSelect 组件事件 */ +export interface AgentStoreSelectEmits { + /** 更新 modelValue */ + (e: 'update:modelValue', value: string | number | null): void + /** 值改变时触发 */ + (e: 'change', value: string | number | null, raw: StoreInfo | null): void + /** 选项加载完成时触发 */ + (e: 'loaded', options: StoreOption[]): void +} diff --git a/src/components/agent-store-select/index.vue b/src/components/agent-store-select/index.vue new file mode 100755 index 0000000..aab63a3 --- /dev/null +++ b/src/components/agent-store-select/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/src/components/card-flow-from-to-org-select/index.data.ts b/src/components/card-flow-from-to-org-select/index.data.ts new file mode 100755 index 0000000..2871deb --- /dev/null +++ b/src/components/card-flow-from-to-org-select/index.data.ts @@ -0,0 +1,48 @@ +/** 卡流流出/流入组织选择器 Props */ +export interface CardFlowFromToOrgSelectProps { + /** 流出组织 ID */ + fromOrgId?: string | number | null + /** 流入组织 ID */ + toOrgId?: string | number | null + /** 流出组织表单项标签 */ + fromLabel?: string + /** 流入组织表单项标签 */ + toLabel?: string + /** 选择器宽度 */ + width?: string + /** 是否 inline 表单布局(渲染 el-form-item) */ + inline?: boolean + /** 流出组织占位符 */ + fromPlaceholder?: string + /** 流入组织占位符 */ + toPlaceholder?: string + /** 加载完成后是否自动选中默认流出组织 */ + autoDefaultFrom?: boolean +} + +/** 组织行(扁平列表项) */ +export interface CardFlowOrgRow { + id: string | number + orgId?: string | number + name?: string + type?: string + orgType?: string + parentId?: string | number + label?: string + disabled?: boolean + children?: CardFlowOrgRow[] +} + +export interface CardFlowFromToOrgChangePayload { + fromOrgId: string | number | null + toOrgId: string | number | null + fromOrgName: string | null + toOrgName: string | null +} + +export const CARD_FLOW_ORG_TYPE_LABEL: Record = { + PLATFORM: '平台', + CHANNEL: '渠道', + SERVICE_PROVIDER: '代理商', + STORE: '门店' +} diff --git a/src/components/card-flow-from-to-org-select/index.vue b/src/components/card-flow-from-to-org-select/index.vue new file mode 100755 index 0000000..76f44ad --- /dev/null +++ b/src/components/card-flow-from-to-org-select/index.vue @@ -0,0 +1,365 @@ + + + + + diff --git a/src/components/channel-agent-tree-select/index.data.ts b/src/components/channel-agent-tree-select/index.data.ts new file mode 100755 index 0000000..d99708d --- /dev/null +++ b/src/components/channel-agent-tree-select/index.data.ts @@ -0,0 +1,53 @@ +import type { OrgInfo } from '@/api/org' + +/** ChannelAgentTreeSelect 组件 Props */ +export interface ChannelAgentTreeSelectProps { + /** 渠道 ID */ + channelId?: string | number | null + /** 当前选中的值 */ + modelValue?: string | number | null + /** 外部传入的树形数据 */ + treeData?: OrgInfo[] | null + /** 是否自动加载 */ + autoLoad?: boolean + /** 下拉框高度 */ + height?: string + /** 选择器宽度 */ + width?: string + /** 是否默认展开所有节点 */ + defaultExpandAll?: boolean + /** 是否禁用 */ + disabled?: boolean + /** 占位符文本 */ + placeholder?: string + /** 需要先选择渠道时的占位符 */ + placeholderNeedChannel?: string + /** 是否可清空 */ + clearable?: boolean + /** 是否可搜索 */ + filterable?: boolean + /** 无数据时的占位文本 */ + emptyText?: string +} + +/** ChannelAgentTreeSelect 组件事件 */ +export interface ChannelAgentTreeSelectEmits { + /** 更新 modelValue */ + (e: 'update:modelValue', value: string | number | null): void + /** 值改变时触发 */ + (e: 'change', payload: { + node: OrgInfo | null + path: OrgInfo[] + agentOrgId: string | number | null + }): void + /** 数据加载完成时触发 */ + (e: 'loaded', data: OrgInfo[]): void +} + +/** 树选择节点 */ +export interface TreeSelectNode extends OrgInfo { + /** 显示标签 */ + label: string + /** 子节点 */ + children?: TreeSelectNode[] +} diff --git a/src/components/channel-agent-tree-select/index.vue b/src/components/channel-agent-tree-select/index.vue new file mode 100755 index 0000000..fe20137 --- /dev/null +++ b/src/components/channel-agent-tree-select/index.vue @@ -0,0 +1,218 @@ + + + + + diff --git a/src/components/channel-select/index.data.ts b/src/components/channel-select/index.data.ts new file mode 100755 index 0000000..6f40f23 --- /dev/null +++ b/src/components/channel-select/index.data.ts @@ -0,0 +1,43 @@ +import type { OrgInfo } from '@/api/org' + +/** ChannelSelect 组件 Props */ +export interface ChannelSelectProps { + /** 当前选中的值 */ + modelValue?: string | number | null + /** 占位符文本 */ + placeholder?: string + /** 是否可搜索 */ + filterable?: boolean + /** 是否可清空 */ + clearable?: boolean + /** 是否禁用 */ + disabled?: boolean + /** 选择器宽度 */ + width?: string + /** 是否自动加载 */ + autoLoad?: boolean + /** 无初始值时,渠道列表加载完成后自动选中第一项 */ + defaultFirst?: boolean + /** 无数据时的占位文本 */ + emptyText?: string +} + +/** 渠道选项 */ +export interface ChannelOption { + /** 渠道 ID */ + id: string | number + /** 渠道显示标签 */ + label: string + /** 原始数据 */ + raw: OrgInfo +} + +/** ChannelSelect 组件事件 */ +export interface ChannelSelectEmits { + /** 更新 modelValue */ + (e: 'update:modelValue', value: string | number | null): void + /** 值改变时触发 */ + (e: 'change', value: string | number | null, raw: OrgInfo | null): void + /** 选项加载完成时触发 */ + (e: 'loaded', options: ChannelOption[]): void +} diff --git a/src/components/channel-select/index.vue b/src/components/channel-select/index.vue new file mode 100755 index 0000000..5c89224 --- /dev/null +++ b/src/components/channel-select/index.vue @@ -0,0 +1,126 @@ + + + diff --git a/src/components/icon-svg/index.data.ts b/src/components/icon-svg/index.data.ts new file mode 100755 index 0000000..636bf20 --- /dev/null +++ b/src/components/icon-svg/index.data.ts @@ -0,0 +1,11 @@ +/** IconSvg 组件 Props */ +export interface IconSvgProps { + /** 图标名称 */ + name: string + /** 自定义类名 */ + className?: string + /** 图标宽度 */ + width?: string + /** 图标高度 */ + height?: string +} diff --git a/src/components/icon-svg/index.vue b/src/components/icon-svg/index.vue new file mode 100755 index 0000000..5de4a58 --- /dev/null +++ b/src/components/icon-svg/index.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/src/components/org-tree-select/index.data.ts b/src/components/org-tree-select/index.data.ts new file mode 100755 index 0000000..55a2900 --- /dev/null +++ b/src/components/org-tree-select/index.data.ts @@ -0,0 +1,61 @@ +import type { OrgInfo } from '@/api/org' + +/** OrgTreeSelect 组件 Props */ +export interface OrgTreeSelectProps { + /** 当前选中的值 */ + modelValue?: string | number | null + /** 外部传入的树形数据 */ + treeData?: OrgInfo[] | null + /** 是否自动加载 */ + autoLoad?: boolean + /** 下拉框高度 */ + height?: string + /** 选择器宽度 */ + width?: string + /** 是否默认展开所有节点 */ + defaultExpandAll?: boolean + /** 是否禁用 */ + disabled?: boolean + /** 占位符文本 */ + placeholder?: string + /** 是否可清空 */ + clearable?: boolean + /** 是否可搜索 */ + filterable?: boolean + /** 无数据时的占位文本 */ + emptyText?: string + /** 隐藏指定类型节点 */ + hideNodeTypes?: string[] +} + +/** OrgTreeSelect 组件事件 */ +export interface OrgTreeSelectEmits { + /** 更新 modelValue */ + (e: 'update:modelValue', value: string | number | null): void + /** 值改变时触发 */ + (e: 'change', payload: { + node: OrgInfo | null + path: OrgInfo[] + orgId: string | number | null + channelOrgId: string | number | null + agentOrgId: string | number | null + }): void + /** 数据加载完成时触发 */ + (e: 'loaded', data: OrgInfo[]): void +} + +/** 组织类型标签映射 */ +export const typeLabelMap: Record = { + PLATFORM: '平台', + CHANNEL: '渠道', + SERVICE_PROVIDER: '代理商', + STORE: '门店' +} + +/** 树选择节点 */ +export interface TreeSelectNode extends OrgInfo { + /** 显示标签 */ + label: string + /** 子节点 */ + children?: TreeSelectNode[] +} diff --git a/src/components/org-tree-select/index.vue b/src/components/org-tree-select/index.vue new file mode 100755 index 0000000..47e522f --- /dev/null +++ b/src/components/org-tree-select/index.vue @@ -0,0 +1,254 @@ + + + + + diff --git a/src/components/store-select/index.data.ts b/src/components/store-select/index.data.ts new file mode 100755 index 0000000..b78b526 --- /dev/null +++ b/src/components/store-select/index.data.ts @@ -0,0 +1,39 @@ +import type { StoreInfo } from '@/api/store' + +/** StoreSelect 组件 Props */ +export interface StoreSelectProps { + /** 当前选中的值 */ + modelValue?: string | number + /** 占位符文本 */ + placeholder?: string + /** 是否可搜索 */ + filterable?: boolean + /** 是否可清空 */ + clearable?: boolean + /** 是否禁用 */ + disabled?: boolean + /** 选择器宽度 */ + width?: string + /** 是否自动加载 */ + autoLoad?: boolean +} + +/** 门店选项 */ +export interface StoreOption { + /** 门店 ID */ + id: string | number + /** 门店名称 */ + name: string + /** 原始数据 */ + raw?: StoreInfo +} + +/** StoreSelect 组件事件 */ +export interface StoreSelectEmits { + /** 更新 modelValue */ + (e: 'update:modelValue', value: string | number): void + /** 值改变时触发 */ + (e: 'change', value: string | number, selected: StoreOption | null): void + /** 选项加载完成时触发 */ + (e: 'loaded', options: StoreOption[]): void +} diff --git a/src/components/store-select/index.vue b/src/components/store-select/index.vue new file mode 100755 index 0000000..84d31f4 --- /dev/null +++ b/src/components/store-select/index.vue @@ -0,0 +1,103 @@ + + + diff --git a/src/components/table-tree-column/index.data.ts b/src/components/table-tree-column/index.data.ts new file mode 100755 index 0000000..bc5d2d5 --- /dev/null +++ b/src/components/table-tree-column/index.data.ts @@ -0,0 +1,20 @@ +/** TableTreeColumn 组件 Props */ +export interface TableTreeColumnProps { + /** 列属性名 */ + prop?: string + /** 树节点的 key */ + treeKey?: string + /** 父节点 key */ + parentKey?: string + /** 层级 key */ + levelKey?: string + /** 子节点 key */ + childKey?: string +} + +/** 表格行数据 */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export interface TableRow extends Record { + /** 是否展开 */ + _expanded?: boolean +} diff --git a/src/components/table-tree-column/index.vue b/src/components/table-tree-column/index.vue new file mode 100755 index 0000000..f8de7fd --- /dev/null +++ b/src/components/table-tree-column/index.vue @@ -0,0 +1,87 @@ + + + diff --git a/src/composables/useChannelScopeFromRole.ts b/src/composables/useChannelScopeFromRole.ts new file mode 100755 index 0000000..88dbf1a --- /dev/null +++ b/src/composables/useChannelScopeFromRole.ts @@ -0,0 +1,162 @@ +import { computed, nextTick, watch, type ComputedRef, type Ref } from 'vue' +import { useUserStore } from '@/stores/user' +import { getOrgInfo, type OrgInfo } from '@/api/org' + +/** + * useChannelScopeFromRole 选项 + */ +export interface ChannelScopeOptions { + channelId: Ref + agentOrgId: Ref + storeId: Ref + channelAgentTreeSelectRef: Ref<{ loadTree?: () => Promise } | null> + agentStoreSelectRef: Ref<{ loadStoreOptions?: () => Promise } | null> +} + +/** + * useChannelScopeFromRole 返回值 + */ +export interface ChannelScopeReturn { + showChannelPicker: ComputedRef + showAgentPicker: ComputedRef + ensureChannelFilterFromUserRole: () => Promise +} + +/** + * 解析组织信息响应 + * @param data - API 响应数据 + * @returns 组织信息或 null + */ +export function parseOrgInfoPayload( + data: + | { + code?: number + org?: OrgInfo + data?: OrgInfo | null + } + | OrgInfo + | null +): OrgInfo | null { + if (!data) return null + if (typeof data === 'object' && 'code' in data && data.code !== undefined) { + const p = data as { code?: number; org?: OrgInfo; data?: OrgInfo | null } + if (p.code === 0 && p.org) return p.org + if (p.code === 0 && p.data != null) return p.data + return null + } + return data as OrgInfo +} + +/** 自某组织向上查找渠道组织 ID */ +export async function findChannelIdFromAncestor(orgId: number): Promise { + let cid: number | null = orgId + let guard = 0 + while (cid != null && guard++ < 24) { + const res = await getOrgInfo(cid) + const info = parseOrgInfoPayload(res) + if (!info) return null + const t = String(info.type || '').toUpperCase() + if (t === 'CHANNEL') return info.id + cid = info.parentId ?? null + } + return null +} + +/** + * 解析渠道 ID,失败时短暂重试(避免首屏接口竞态) + * @param orgId - 组织 ID + * @param attempts - 重试次数 + * @param delayMs - 延迟毫秒数 + * @returns 渠道 ID 或 null + */ +async function findChannelIdFromAncestorWithRetry( + orgId: number, + attempts: number = 3, + delayMs: number = 120 +): Promise { + for (let i = 0; i < attempts; i++) { + if (i > 0) await new Promise(r => setTimeout(r, delayMs)) + const ch = await findChannelIdFromAncestor(orgId) + if (ch != null) return ch + } + return null +} + +/** + * 渠道账号:不展示「渠道」选择框(showChannelPicker=false);纯代理商账号不展示「代理商」树(showAgentPicker=false)。 + * 内部仍会解析并写入 channelId;纯代理商登录时写入 agentOrgId=当前所属组织,供门店下拉与接口 org 范围使用。 + */ +export function useChannelScopeFromRole({ + channelId, + agentOrgId, + storeId: _storeId, + channelAgentTreeSelectRef, + agentStoreSelectRef +}: ChannelScopeOptions): ChannelScopeReturn { + const userStore = useUserStore() + /** 仅平台等非渠道/非代理商角色展示「渠道」下拉 */ + const showChannelPicker = computed(() => !userStore.isAgent && !userStore.isChannel) + /** + * 纯代理商:不展示「代理商」树(范围锁定当前组织)。 + * 含渠道角色时仍展示(即使角色名同时命中「代理」类关键字,避免树被误藏)。 + */ + const showAgentPicker = computed(() => !userStore.isAgent || userStore.isChannel) + + async function ensureChannelFilterFromUserRole(): Promise { + if (userStore.isChannel) { + const oid = userStore.orgId + if (oid == null) return + if (channelId.value == null || channelId.value === '') { + const res = await getOrgInfo(Number(oid)) + const info = parseOrgInfoPayload(res) + const t = String(info?.type || '').toUpperCase() + if (t === 'CHANNEL') { + channelId.value = info?.id ?? oid + } else { + const ch = await findChannelIdFromAncestorWithRetry(Number(oid)) + if (ch != null) channelId.value = ch + } + } + await nextTick() + await channelAgentTreeSelectRef.value?.loadTree?.() + await agentStoreSelectRef.value?.loadStoreOptions?.() + return + } + + if (!userStore.isAgent) return + const oid = userStore.orgId + if (oid == null) return + + if (channelId.value == null || channelId.value === '') { + const ch = await findChannelIdFromAncestorWithRetry(Number(oid)) + if (ch != null) { + channelId.value = ch + await nextTick() + await channelAgentTreeSelectRef.value?.loadTree?.() + } + } + + /** 代理商账号不可切换代理商:范围固定为当前登录组织 */ + agentOrgId.value = oid + await nextTick() + await agentStoreSelectRef.value?.loadStoreOptions?.() + } + + /** + * orgId / 角色晚于首屏就绪时补解析 channelId 并刷新代理商树、门店列表 + * (避免渠道账号首页等仅 onMounted 跑一次时 channelId 仍为空导致代理商下拉无数据) + */ + watch( + () => [userStore.orgId, userStore.isAgent, userStore.isChannel] as const, + async () => { + if (!userStore.isAgent && !userStore.isChannel) return + if (userStore.orgId == null) return + if (channelId.value != null && channelId.value !== '') return + await ensureChannelFilterFromUserRole() + await agentStoreSelectRef.value?.loadStoreOptions?.() + }, + { flush: 'post' } + ) + + return { showChannelPicker, showAgentPicker, ensureChannelFilterFromUserRole } +} diff --git a/src/composables/useFlashScrollbar.ts b/src/composables/useFlashScrollbar.ts new file mode 100755 index 0000000..b6a98e0 --- /dev/null +++ b/src/composables/useFlashScrollbar.ts @@ -0,0 +1,31 @@ +import { ref, onUnmounted } from 'vue' + +const DEFAULT_HIDE_AFTER_MS = 900 + +/** 滚动条默认隐藏,发生滚动后短暂显示,停止滚动一段时间后自动隐藏 */ +export function useFlashScrollbar(hideAfterMs = DEFAULT_HIDE_AFTER_MS) { + const scrollbarVisible = ref(false) + let hideTimer: ReturnType | null = null + + function clearHideTimer() { + if (hideTimer != null) { + clearTimeout(hideTimer) + hideTimer = null + } + } + + function onScrollableScroll() { + scrollbarVisible.value = true + clearHideTimer() + hideTimer = setTimeout(() => { + scrollbarVisible.value = false + hideTimer = null + }, hideAfterMs) + } + + onUnmounted(() => { + clearHideTimer() + }) + + return { scrollbarVisible, onScrollableScroll } +} diff --git a/src/composables/useNearExpiryUnusedCards.ts b/src/composables/useNearExpiryUnusedCards.ts new file mode 100755 index 0000000..c762c7e --- /dev/null +++ b/src/composables/useNearExpiryUnusedCards.ts @@ -0,0 +1,69 @@ +import { ref } from 'vue' +import { getNearExpiryUnusedCards } from '@/api/card' +import type { ApiResponse } from '@/types/api' +import type { NearExpiryUnusedCard } from '@/api/card' + +export const NEAR_EXPIRY_UNUSED_PROMPT_SHOWN_KEY = 'nearExpiryUnusedCardsPromptShown' + +type NearExpiryUnusedPayload = ApiResponse<{ list: NearExpiryUnusedCard[] }> & { + list?: NearExpiryUnusedCard[] +} + +const nearExpiryUnusedList = ref([]) +const nearExpiryUnusedCount = ref(0) +const nearExpiryLoading = ref(false) +const nearExpiryDialogVisible = ref(false) + +function parseNearExpiryList (body: NearExpiryUnusedPayload | null | undefined): NearExpiryUnusedCard[] { + if (!body || body.code !== 0) return [] + return Array.isArray(body.list) ? body.list : [] +} + +async function fetchNearExpiryUnusedCards (): Promise { + nearExpiryLoading.value = true + try { + const body = await getNearExpiryUnusedCards() + const list = parseNearExpiryList(body as NearExpiryUnusedPayload) + nearExpiryUnusedList.value = list + nearExpiryUnusedCount.value = list.length + return list + } catch { + nearExpiryUnusedList.value = [] + nearExpiryUnusedCount.value = 0 + return [] + } finally { + nearExpiryLoading.value = false + } +} + +/** 登录后检查临期卡,存在则自动弹窗(同一会话仅自动弹一次) */ +export async function checkNearExpiryUnusedCardsAfterLogin (): Promise { + if (sessionStorage.getItem(NEAR_EXPIRY_UNUSED_PROMPT_SHOWN_KEY) === '1') return + const list = await fetchNearExpiryUnusedCards() + if (list.length > 0) { + sessionStorage.setItem(NEAR_EXPIRY_UNUSED_PROMPT_SHOWN_KEY, '1') + nearExpiryDialogVisible.value = true + } +} + +export function openNearExpiryUnusedCardsDialog (): void { + nearExpiryDialogVisible.value = true + void fetchNearExpiryUnusedCards() +} + +export function resetNearExpiryUnusedCardsPrompt (): void { + sessionStorage.removeItem(NEAR_EXPIRY_UNUSED_PROMPT_SHOWN_KEY) +} + +export function useNearExpiryUnusedCards () { + return { + nearExpiryUnusedList, + nearExpiryUnusedCount, + nearExpiryLoading, + nearExpiryDialogVisible, + fetchNearExpiryUnusedCards, + checkNearExpiryUnusedCardsAfterLogin, + openNearExpiryUnusedCardsDialog, + resetNearExpiryUnusedCardsPrompt + } +} diff --git a/src/config/env.d.ts b/src/config/env.d.ts new file mode 100755 index 0000000..d1abaf2 --- /dev/null +++ b/src/config/env.d.ts @@ -0,0 +1 @@ +export const baseApi: string diff --git a/src/config/env.js b/src/config/env.js new file mode 100755 index 0000000..dd62a9a --- /dev/null +++ b/src/config/env.js @@ -0,0 +1,35 @@ +/** + * 项目环境变量统一入口 + * 所有通过 Vite 注入的 VITE_ 变量在此集中定义默认值与类型说明,便于维护和 IDE 提示 + * + * 使用方式: + * import { baseApi, devPort, isDev } from '@/config/env' + * + * 配置方式: + * 在项目根目录 .env / .env.development / .env.production 中配置,变量名需以 VITE_ 开头 + */ + +const env = import.meta.env + +/** 后端 API 基础地址(开发走 Vite 代理,生产走 nginx 代理,均为同源 /api) */ +export const baseApi = '/api' + +/** 开发服务器端口 */ +export const devPort = Number(env.VITE_DEV_PORT) || 3000 + +/** 是否为开发环境 */ +export const isDev = env.DEV + +/** 是否为生产环境 */ +export const isProd = env.PROD + +/** 当前 mode:development | production */ +export const mode = env.MODE + +export default { + baseApi, + devPort, + isDev, + isProd, + mode +} diff --git a/src/icons/iconfont.js b/src/icons/iconfont.js new file mode 100755 index 0000000..e69de29 diff --git a/src/icons/index.d.ts b/src/icons/index.d.ts new file mode 100755 index 0000000..3750e8f --- /dev/null +++ b/src/icons/index.d.ts @@ -0,0 +1,10 @@ +import { App } from 'vue' +import IconSvg from '@/components/icon-svg/index.vue' + +export function getNameList(): string[] + +export default { + install(app: App): void +} + +export { IconSvg } diff --git a/src/icons/index.js b/src/icons/index.js new file mode 100755 index 0000000..aebacf3 --- /dev/null +++ b/src/icons/index.js @@ -0,0 +1,17 @@ +import IconSvg from '@/components/icon-svg/index.vue' +import './iconfont.js' + +const svgFiles = import.meta.glob('./svg/*.svg', { eager: true }) +const iconList = Object.values(svgFiles) + +export function getNameList () { + return iconList.map(item => item.default.id.replace('icon-', '')) +} + +export default { + install (app) { + app.component('IconSvg', IconSvg) + } +} + +export { IconSvg } diff --git a/src/icons/svg/icon-admin.svg b/src/icons/svg/icon-admin.svg new file mode 100755 index 0000000..a8889a1 --- /dev/null +++ b/src/icons/svg/icon-admin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-bianji.svg b/src/icons/svg/icon-bianji.svg new file mode 100755 index 0000000..1305cd6 --- /dev/null +++ b/src/icons/svg/icon-bianji.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-config.svg b/src/icons/svg/icon-config.svg new file mode 100755 index 0000000..c75b438 --- /dev/null +++ b/src/icons/svg/icon-config.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-dangdifill.svg b/src/icons/svg/icon-dangdifill.svg new file mode 100755 index 0000000..9eb0113 --- /dev/null +++ b/src/icons/svg/icon-dangdifill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-daohang.svg b/src/icons/svg/icon-daohang.svg new file mode 100755 index 0000000..e3ee42d --- /dev/null +++ b/src/icons/svg/icon-daohang.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-duanxin.svg b/src/icons/svg/icon-duanxin.svg new file mode 100755 index 0000000..855c516 --- /dev/null +++ b/src/icons/svg/icon-duanxin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-editor.svg b/src/icons/svg/icon-editor.svg new file mode 100755 index 0000000..6fdd731 --- /dev/null +++ b/src/icons/svg/icon-editor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-geren.svg b/src/icons/svg/icon-geren.svg new file mode 100755 index 0000000..89b1484 --- /dev/null +++ b/src/icons/svg/icon-geren.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-jiesuo.svg b/src/icons/svg/icon-jiesuo.svg new file mode 100755 index 0000000..2e8cc02 --- /dev/null +++ b/src/icons/svg/icon-jiesuo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-job.svg b/src/icons/svg/icon-job.svg new file mode 100755 index 0000000..c2fc231 --- /dev/null +++ b/src/icons/svg/icon-job.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-log.svg b/src/icons/svg/icon-log.svg new file mode 100755 index 0000000..b38fd72 --- /dev/null +++ b/src/icons/svg/icon-log.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-menu.svg b/src/icons/svg/icon-menu.svg new file mode 100755 index 0000000..c115201 --- /dev/null +++ b/src/icons/svg/icon-menu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-mudedi.svg b/src/icons/svg/icon-mudedi.svg new file mode 100755 index 0000000..665f4ef --- /dev/null +++ b/src/icons/svg/icon-mudedi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-oss.svg b/src/icons/svg/icon-oss.svg new file mode 100755 index 0000000..964ff54 --- /dev/null +++ b/src/icons/svg/icon-oss.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-pinglun.svg b/src/icons/svg/icon-pinglun.svg new file mode 100755 index 0000000..89dbe1d --- /dev/null +++ b/src/icons/svg/icon-pinglun.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-role.svg b/src/icons/svg/icon-role.svg new file mode 100755 index 0000000..6d02fc1 --- /dev/null +++ b/src/icons/svg/icon-role.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-shanchu.svg b/src/icons/svg/icon-shanchu.svg new file mode 100755 index 0000000..02e4673 --- /dev/null +++ b/src/icons/svg/icon-shanchu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-shezhi.svg b/src/icons/svg/icon-shezhi.svg new file mode 100755 index 0000000..270e54c --- /dev/null +++ b/src/icons/svg/icon-shezhi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-shoucang.svg b/src/icons/svg/icon-shoucang.svg new file mode 100755 index 0000000..ab6fc17 --- /dev/null +++ b/src/icons/svg/icon-shoucang.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-shoucangfill.svg b/src/icons/svg/icon-shoucangfill.svg new file mode 100755 index 0000000..8e278e1 --- /dev/null +++ b/src/icons/svg/icon-shoucangfill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-shouye.svg b/src/icons/svg/icon-shouye.svg new file mode 100755 index 0000000..9f672aa --- /dev/null +++ b/src/icons/svg/icon-shouye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-sousuo.svg b/src/icons/svg/icon-sousuo.svg new file mode 100755 index 0000000..08c5ffb --- /dev/null +++ b/src/icons/svg/icon-sousuo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-sql.svg b/src/icons/svg/icon-sql.svg new file mode 100755 index 0000000..d820372 --- /dev/null +++ b/src/icons/svg/icon-sql.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-suoding.svg b/src/icons/svg/icon-suoding.svg new file mode 100755 index 0000000..9ab7d7a --- /dev/null +++ b/src/icons/svg/icon-suoding.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-system.svg b/src/icons/svg/icon-system.svg new file mode 100755 index 0000000..0a36a86 --- /dev/null +++ b/src/icons/svg/icon-system.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-tixing.svg b/src/icons/svg/icon-tixing.svg new file mode 100755 index 0000000..03084e9 --- /dev/null +++ b/src/icons/svg/icon-tixing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-tubiao.svg b/src/icons/svg/icon-tubiao.svg new file mode 100755 index 0000000..549d651 --- /dev/null +++ b/src/icons/svg/icon-tubiao.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-xiangqu.svg b/src/icons/svg/icon-xiangqu.svg new file mode 100755 index 0000000..4a46c9b --- /dev/null +++ b/src/icons/svg/icon-xiangqu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-xiangqufill.svg b/src/icons/svg/icon-xiangqufill.svg new file mode 100755 index 0000000..f56ac48 --- /dev/null +++ b/src/icons/svg/icon-xiangqufill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-zhedie.svg b/src/icons/svg/icon-zhedie.svg new file mode 100755 index 0000000..422a8fb --- /dev/null +++ b/src/icons/svg/icon-zhedie.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/icon-zonghe.svg b/src/icons/svg/icon-zonghe.svg new file mode 100755 index 0000000..9c2fa5f --- /dev/null +++ b/src/icons/svg/icon-zonghe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/layout/main-content.vue b/src/layout/main-content.vue new file mode 100755 index 0000000..7018c3f --- /dev/null +++ b/src/layout/main-content.vue @@ -0,0 +1,117 @@ + + + diff --git a/src/layout/main-navbar-update-password.vue b/src/layout/main-navbar-update-password.vue new file mode 100755 index 0000000..f10bbad --- /dev/null +++ b/src/layout/main-navbar-update-password.vue @@ -0,0 +1,154 @@ + + + diff --git a/src/layout/main-navbar.vue b/src/layout/main-navbar.vue new file mode 100755 index 0000000..f566423 --- /dev/null +++ b/src/layout/main-navbar.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/layout/main-sidebar-sub-menu.vue b/src/layout/main-sidebar-sub-menu.vue new file mode 100755 index 0000000..89a346e --- /dev/null +++ b/src/layout/main-sidebar-sub-menu.vue @@ -0,0 +1,92 @@ + + + diff --git a/src/layout/main-sidebar.vue b/src/layout/main-sidebar.vue new file mode 100755 index 0000000..2899546 --- /dev/null +++ b/src/layout/main-sidebar.vue @@ -0,0 +1,151 @@ + + + diff --git a/src/layout/main.vue b/src/layout/main.vue new file mode 100755 index 0000000..69c8545 --- /dev/null +++ b/src/layout/main.vue @@ -0,0 +1,72 @@ + + + diff --git a/src/main.ts b/src/main.ts new file mode 100755 index 0000000..426dc7a --- /dev/null +++ b/src/main.ts @@ -0,0 +1,31 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from '@/App.vue' +import router from '@/router' +import icons from '@/icons' +import { useCommonStore } from '@/stores/common' +import { useUserStore } from '@/stores/user' +import 'element-plus/dist/index.css' +import '@assets/scss/index.scss' +import httpRequest from '@/utils/httpRequest' +import { isAuth } from '@/utils' +import cloneDeep from 'lodash/cloneDeep' +import 'virtual:uno.css' + +const app = createApp(App) +const pinia = createPinia() +app.use(pinia) +app.use(router) +app.use(icons) + +app.config.globalProperties.$http = httpRequest +app.config.globalProperties.isAuth = isAuth + +if (window.SITE_CONFIG) { + window.SITE_CONFIG.storeState = { + common: cloneDeep(useCommonStore().$state), + user: cloneDeep(useUserStore().$state) + } +} + +app.mount('#app') diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100755 index 0000000..c61d020 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,243 @@ +import { createRouter, createWebHashHistory, RouteRecordRaw, RouteLocationNormalized } from 'vue-router' +import { getMenuNav } from '@/api/sys' +import { isURL } from '@/utils/validate' +import { clearLoginInfo, getToken, getRefreshToken, isAuth, isRefreshTokenValid } from '@/utils' + +/** + * 扩展的路由实例类型 + */ +interface ExtendedRouter { + isAddDynamicMenuRoutes: boolean +} + +/** + * 菜单项接口 + */ +interface MenuItem { + id: string | number + name: string + url?: string + show?: number + preBind?: boolean + preBindCardType?: string + perms?: string + list?: MenuItem[] + [key: string]: any +} + +/** + * 菜单导航响应 + */ +interface MenuNavResponse { + code: number + menuList?: MenuItem[] + permissions?: string[] +} + +// 预加载 views/modules 下的所有页面组件 +const modules = import.meta.glob<{ default: any }>('/src/views/modules/**/*.vue', { eager: true }) + +// 全局路由(无需嵌套上左右整体布局) +const globalRoutes: RouteRecordRaw[] = [ + { path: '/404', component: () => import('@/views/common/404.vue'), name: '404', meta: { title: '404未找到' } }, + { path: '/login', component: () => import('@/views/common/login.vue'), name: 'login', meta: { title: '登录' } } +] + +// 主入口路由(需嵌套上左右整体布局) +const mainRoutes: RouteRecordRaw & { children?: RouteRecordRaw[] } = { + path: '/', + component: () => import('@/layout/main.vue'), + name: 'main', + redirect: { name: 'home' }, + meta: { title: '主入口整体布局' }, + children: [ + // 通过meta对象设置路由展示方式 + // 1. isTab: 是否通过tab展示内容, true: 是, false: 否 + // 2. iframeUrl: 是否通过iframe嵌套展示内容, '以http[s]://开头': 是, '': 否 + // 提示: 如需要通过iframe嵌套展示内容, 但不通过tab打开, 请自行创建组件使用iframe处理! + { path: '/home', component: () => import('@/views/common/home.vue'), name: 'home', meta: { title: '首页' } }, + ], + beforeEnter(_to: RouteLocationNormalized, _from: RouteLocationNormalized) { + const token = getToken() + const hasRefresh = getRefreshToken() && isRefreshTokenValid() + if ((!token || !/\S/.test(token)) && !hasRefresh) { + clearLoginInfo() + return { name: 'login' } + } + } +} + +const router = createRouter({ + history: createWebHashHistory(), + scrollBehavior: () => ({ top: 0 }), + routes: globalRoutes.concat([mainRoutes as RouteRecordRaw]) +}) as ReturnType & ExtendedRouter + +router.isAddDynamicMenuRoutes = false + +router.beforeEach((to: RouteLocationNormalized, _from: RouteLocationNormalized) => { + // 权限控制(优先):动态菜单路由会把后端 perms 注入到 route.meta.perms + if (to?.meta?.perms) { + const permsStr = String(to.meta.perms || '') + const permsList = permsStr.split(',').map(s => s.trim()).filter(Boolean) + const hasAny = permsList.some(p => isAuth(p)) + if (!hasAny) return { name: '404' } + } + + if (router.isAddDynamicMenuRoutes || fnCurrentRouteType(to, globalRoutes) === 'global') { + return + } + return getMenuNav().then((data: MenuNavResponse) => { + if (data && data.code === 0) { + // /manage/menu/nav 统一返回 {code,msg,data:{menuList,permissions}};兼容旧顶层格式 + const navData = (data as any).data || data + const menuList = fnFilterMenuByShow(navData.menuList || []) + fnAddDynamicMenuRoutes(menuList) + router.isAddDynamicMenuRoutes = true + sessionStorage.setItem('menuList', JSON.stringify(menuList)) + sessionStorage.setItem('permissions', JSON.stringify(navData.permissions || '[]')) + return { ...to, replace: true } + } else { + sessionStorage.setItem('menuList', '[]') + sessionStorage.setItem('permissions', '[]') + return + } + }).catch(() => { + return { name: 'login' } + }) +}) + +/** + * 按 show 过滤菜单:仅保留 show 为 10(展示)的项,20(隐藏)及未设置(视为展示)的按需处理 + */ +function fnFilterMenuByShow(menuList: MenuItem[]): MenuItem[] { + return menuList.filter((item: MenuItem) => { + if (item.show === 20) return false + if (item.list && item.list.length > 0) { + item.list = fnFilterMenuByShow(item.list) + } + return true + }) +} + +/** + * 判断当前路由类型, global: 全局路由, main: 主入口路由 + * @param route 当前路由 + * @param globalRoutes 全局路由列表 + */ +function fnCurrentRouteType(route: RouteLocationNormalized, globalRoutes: RouteRecordRaw[] = []): string { + let temp: RouteRecordRaw[] = [] + for (let i = 0; i < globalRoutes.length; i++) { + const gr = globalRoutes[i] + if (!gr) continue + if (route.path === gr.path) { + return 'global' + } + const children = gr.children + if (children && children.length >= 1) { + temp = temp.concat(children) + } + } + return temp.length >= 1 ? fnCurrentRouteType(route, temp) : 'main' +} + +/** + * 添加动态(菜单)路由 + * @param menuList 菜单列表 + * @param routes 递归创建的动态(菜单)路由 + */ +function fnAddDynamicMenuRoutes(menuList: MenuItem[] = [], routes: RouteRecordRaw[] = []): void { + let temp: MenuItem[] = [] + for (let i = 0; i < menuList.length; i++) { + const mi = menuList[i] + if (!mi) continue + if (mi.list && mi.list.length >= 1) { + temp = temp.concat(mi.list) + } else if (mi.url && /\S/.test(mi.url)) { + mi.url = mi.url.replace(/^\//, '') + const menuId = mi.id + const rawUrl = String(mi.url || '') + const isPresetDeviceImport = rawUrl === 'device/device-import-preset' + const route = { + path: rawUrl.replace('/', '-'), + name: rawUrl.replace('/', '-'), + meta: { + id: menuId, + title: mi.name, + isDynamic: true, + isTab: true, + iframeUrl: '', + preBind: isPresetDeviceImport || mi.preBind === true, + preBindCardType: mi.preBindCardType || 'YEAR', + perms: mi.perms || '' + } + } as unknown as RouteRecordRaw + if (isURL(rawUrl)) { + route.path = `i-${menuId}` + route.name = `i-${menuId}` + route.meta!.iframeUrl = mi.url + } else { + const componentPath = `/src/views/modules/${rawUrl}.vue` + const matched = modules[componentPath] + if (matched) { + route.component = matched.default || matched + } + } + routes.push(route) + } + } + if (temp.length >= 1) { + fnAddDynamicMenuRoutes(temp, routes) + } else { + // 补充设备批量导入页面路由(可从设备列表按钮跳转,即使菜单未配置也可访问) + const deviceImportMod = modules['/src/views/modules/device/device-import.vue'] + const deviceImportComp = deviceImportMod ? (deviceImportMod.default || deviceImportMod) : null + if (deviceImportComp && !routes.some(r => r.name === 'device-device-import')) { + routes.push({ + path: 'device-device-import', + name: 'device-device-import', + component: deviceImportComp, + meta: { title: '批量导入设备', isDynamic: true, isTab: true, iframeUrl: '', preBind: false } + }) + } + // 与菜单 url「device/device-import-preset」一致:预置/授权明细 + 数据概览(不依赖后端是否配置该菜单) + if (deviceImportComp && !routes.some(r => r.name === 'device-device-import-preset')) { + routes.push({ + path: 'device-device-import-preset', + name: 'device-device-import-preset', + component: deviceImportComp, + meta: { + title: '设备授权明细', + isDynamic: true, + isTab: true, + iframeUrl: '', + preBind: true, + preBindCardType: 'YEAR' + } + }) + } + const dupMacSnMod = modules['/src/views/modules/device/device-duplicate-mac-sn.vue'] + const dupMacSnComp = dupMacSnMod ? (dupMacSnMod.default || dupMacSnMod) : null + if (dupMacSnComp && !routes.some(r => r.name === 'device-device-duplicate-mac-sn')) { + routes.push({ + path: 'device-device-duplicate-mac-sn', + name: 'device-device-duplicate-mac-sn', + component: dupMacSnComp, + meta: { title: '重复 MAC / 设备 SN', isDynamic: true, isTab: true, iframeUrl: '' } + }) + } + mainRoutes.name = 'main-dynamic' + mainRoutes.children = routes + router.addRoute(mainRoutes) + router.addRoute({ path: '/:pathMatch(.*)*', redirect: { name: '404' } }) + // 存一份仅含 name/path/meta 的可序列化数据,保证 meta.menuId 等不丢失 + const serializableRoutes = (mainRoutes.children || []).map(r => ({ + name: r.name, + path: r.path, + meta: { ...(r.meta || {}) } + })) + sessionStorage.setItem('dynamicMenuRoutes', JSON.stringify(serializableRoutes)) + } +} + +export default router diff --git a/src/stores/common.ts b/src/stores/common.ts new file mode 100755 index 0000000..7e3ed56 --- /dev/null +++ b/src/stores/common.ts @@ -0,0 +1,88 @@ +import { defineStore } from 'pinia' + +/** + * 标签页项 + */ +export interface TabItem { + menuId?: number | string + name: string + title?: string + path?: string + type?: 'iframe' | 'module' + iframeUrl?: string + params?: Record + query?: Record + [key: string]: any +} + +/** + * 菜单项 + */ +export interface MenuItem { + id?: string | number + parentId?: string | number + name?: string + title?: string + path?: string + icon?: string + children?: MenuItem[] + [key: string]: any +} + +/** + * 通用状态接口 + */ +interface CommonState { + documentClientHeight: number + navbarLayoutType: string + sidebarLayoutSkin: string + sidebarFold: boolean + menuList: MenuItem[] + menuActiveName: string + contentIsNeedRefresh: boolean + mainTabs: TabItem[] + mainTabsActiveName: string +} + +export const useCommonStore = defineStore('common', { + state: (): CommonState => ({ + documentClientHeight: 0, + navbarLayoutType: 'default', + sidebarLayoutSkin: 'dark', + sidebarFold: false, + menuList: [], + menuActiveName: '', + contentIsNeedRefresh: false, + mainTabs: [], + mainTabsActiveName: '' + }), + actions: { + updateDocumentClientHeight(height: number): void { + this.documentClientHeight = height + }, + updateNavbarLayoutType(type: string): void { + this.navbarLayoutType = type + }, + updateSidebarLayoutSkin(skin: string): void { + this.sidebarLayoutSkin = skin + }, + updateSidebarFold(fold: boolean): void { + this.sidebarFold = fold + }, + updateMenuList(list: MenuItem[]): void { + this.menuList = list + }, + updateMenuActiveName(name: string): void { + this.menuActiveName = name + }, + updateContentIsNeedRefresh(status: boolean): void { + this.contentIsNeedRefresh = status + }, + updateMainTabs(tabs: TabItem[]): void { + this.mainTabs = tabs + }, + updateMainTabsActiveName(name: string): void { + this.mainTabsActiveName = name + } + } +}) diff --git a/src/stores/reset.ts b/src/stores/reset.ts new file mode 100755 index 0000000..f462a5b --- /dev/null +++ b/src/stores/reset.ts @@ -0,0 +1,29 @@ +import cloneDeep from 'lodash/cloneDeep' +import { useCommonStore } from './common' +import { useUserStore } from './user' + +/** + * 站点配置状态快照 + */ +interface StoreStateSnapshot { + common: Record + user: Record +} + +declare global { + interface Window { + SITE_CONFIG?: { + storeState?: StoreStateSnapshot + } + } +} + +/** + * 将 common / user 恢复为 main.js 中保存的初始快照(与原先 Vuex resetStore 行为一致) + */ +export function resetStoresFromSiteConfig(): void { + if (!window.SITE_CONFIG?.storeState) return + const snap = window.SITE_CONFIG.storeState + useCommonStore().$patch(cloneDeep(snap.common)) + useUserStore().$patch(cloneDeep(snap.user)) +} diff --git a/src/stores/user.ts b/src/stores/user.ts new file mode 100755 index 0000000..768e70c --- /dev/null +++ b/src/stores/user.ts @@ -0,0 +1,131 @@ +import { defineStore } from 'pinia' + +/** + * 角色别名映射 + */ +interface RoleAlias { + platform: string[] + channel: string[] + agent: string[] + store: string[] +} + +/** + * 用户状态接口 + */ +interface UserState { + id: number + name: string + roleNames: string[] + /** 当前用户所属组织 id(渠道/代理/门店等,接口返回时写入) */ + orgId: number | null +} + +/** 与登录返回的 roleNames 做匹配:支持中文、英文代码及常见后缀(如「平台管理员」) */ +const ROLE_ALIAS: RoleAlias = { + platform: ['平台', 'PLATFORM', '超级管理员', '超管', 'SUPER_ADMIN', 'SUPERADMIN'], + channel: ['渠道', 'CHANNEL'], + agent: ['代理商', '代理', '代理服务商', 'SERVICE_PROVIDER', 'AGENT'], + store: ['门店', 'STORE', 'SHOP'] +} + +/** + * 检查角色名是否匹配别名列表 + * @param roleNames - 角色名列表 + * @param aliases - 别名列表 + * @returns 是否匹配 + */ +function roleNamesMatch(roleNames: string[], aliases: string[]): boolean { + if (!Array.isArray(roleNames) || roleNames.length === 0) return false + for (const raw of roleNames) { + const s = String(raw).trim() + if (!s) continue + const upper = s.toUpperCase() + for (const alias of aliases) { + const a = String(alias) + if (s === a || upper === a.toUpperCase()) return true + if (a.length >= 2 && s.includes(a)) return true + } + } + return false +} + +export const useUserStore = defineStore('user', { + state: (): UserState => ({ + id: 0, + name: '', + roleNames: [], + /** 当前用户所属组织 id(渠道/代理/门店等,接口返回时写入) */ + orgId: null + }), + getters: { + isPlatform(state): boolean { + return roleNamesMatch(state.roleNames, ROLE_ALIAS.platform) + }, + isChannel(state): boolean { + return roleNamesMatch(state.roleNames, ROLE_ALIAS.channel) + }, + isAgent(state): boolean { + return roleNamesMatch(state.roleNames, ROLE_ALIAS.agent) + }, + isStore(state): boolean { + return roleNamesMatch(state.roleNames, ROLE_ALIAS.store) + } + }, + actions: { + /** + * 从登录或 /manage/user/info 返回体中解析并写入当前用户信息(兼容 data 嵌套、user 子对象、字段别名) + */ + applyProfileFromAuth(inner: Record | null | undefined, envelope?: Record): void { + const core = inner && typeof inner === 'object' && !Array.isArray(inner) ? inner : {} + const env = envelope && typeof envelope === 'object' && !Array.isArray(envelope) ? envelope : {} + const user = + core.user && typeof core.user === 'object' && !Array.isArray(core.user) ? core.user : core + const uid = user.id ?? user.userId ?? core.userId ?? env.userId + if (uid != null && uid !== '') { + const n = typeof uid === 'number' ? uid : parseInt(String(uid), 10) + if (!Number.isNaN(n)) this.updateId(n) + } + const display = + (typeof user.username === 'string' && user.username) || + (typeof user.realName === 'string' && user.realName) || + (typeof user.real_name === 'string' && user.real_name) || + (typeof core.username === 'string' && core.username) || + (typeof core.realName === 'string' && core.realName) || + (typeof env.username === 'string' && env.username) || + '' + if (display) this.updateName(display) + const roles = + core.roleNames ?? core.roleName ?? user.roleNames ?? user.roleName ?? env.roleNames ?? env.roleName + if (roles != null && roles !== '') this.updateRoleNames(roles) + const oid = user.orgId ?? user.org_id ?? core.orgId ?? core.org_id ?? env.orgId + this.updateOrgId(oid) + }, + updateId(id: number): void { + this.id = id + }, + updateName(name: string): void { + this.name = name + }, + updateRoleNames(roleNames: string | string[] | null | undefined): void { + if (roleNames == null) { + this.roleNames = [] + } else if (Array.isArray(roleNames)) { + this.roleNames = roleNames.slice() + } else if (typeof roleNames === 'string') { + this.roleNames = roleNames + ? roleNames.split(',').map((s) => s.trim()).filter(Boolean) + : [] + } else { + this.roleNames = [] + } + }, + updateOrgId(orgId: number | string | null | undefined): void { + if (orgId == null || orgId === '') { + this.orgId = null + } else { + this.orgId = typeof orgId === 'string' ? parseInt(orgId, 10) : orgId + } + } + } +}) diff --git a/src/types/api.d.ts b/src/types/api.d.ts new file mode 100755 index 0000000..5c60c93 --- /dev/null +++ b/src/types/api.d.ts @@ -0,0 +1,54 @@ +// API 响应类型 +export interface ApiResponse { + code: number + msg: string + data: T +} + +// 分页参数 +export interface PageParams { + page?: number + limit?: number + [key: string]: any +} + +// 分页响应 +export interface PageResult { + list: T[] + totalCount: number + pageSize?: number + currPage?: number + totalPage?: number + /** 部分接口将 list/totalCount 放在 page 子对象中 */ + page?: { + list: T[] + totalCount: number + pageSize?: number + currPage?: number + totalPage?: number + } +} + +// 用户相关类型 +export interface UserInfo { + id: number + username: string + realName: string + avatar: string + roleIdList: number[] + orgId: number + orgName: string +} + +// 登录相关类型 +export interface LoginForm { + username: string + password: string + captcha: string + uuid: string +} + +export interface LoginResult { + token: string + expire: number +} diff --git a/src/types/components.d.ts b/src/types/components.d.ts new file mode 100755 index 0000000..916bd78 --- /dev/null +++ b/src/types/components.d.ts @@ -0,0 +1,44 @@ +/** + * 组件通用类型定义 + */ + +/** + * 门店选项 + */ +export interface StoreOption { + id: string | number + name: string + raw?: Record +} + +/** + * 组织树节点 + */ +export interface OrgTreeNode { + id: string | number + name: string + type?: string + parentId?: string | number + children?: OrgTreeNode[] + [key: string]: any +} + +/** + * 渠道选项 + */ +export interface ChannelOption { + id: string | number + label: string + raw?: Record +} + +/** + * 代理商树节点 + */ +export interface AgentTreeNode { + id: string | number + name: string + label?: string + children?: AgentTreeNode[] + [key: string]: any +} diff --git a/src/types/env.d.ts b/src/types/env.d.ts new file mode 100755 index 0000000..323c78a --- /dev/null +++ b/src/types/env.d.ts @@ -0,0 +1,7 @@ +/// + +declare module '*.vue' { + import type { DefineComponent } from 'vue' + const component: DefineComponent<{}, {}, any> + export default component +} diff --git a/src/types/global.d.ts b/src/types/global.d.ts new file mode 100755 index 0000000..7c6e53c --- /dev/null +++ b/src/types/global.d.ts @@ -0,0 +1,13 @@ +declare module 'vue-cookie' + +declare module 'element-china-area-data' + +interface ImportMetaEnv { + readonly VITE_APP_BASE_API: string + readonly VITE_APP_TITLE: string + readonly VITE_APP_ENV: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} diff --git a/src/types/main.d.ts b/src/types/main.d.ts new file mode 100755 index 0000000..ee09c5c --- /dev/null +++ b/src/types/main.d.ts @@ -0,0 +1,29 @@ +import httpRequest from '@/utils/httpRequest' + +/** + * 全局 SITE_CONFIG 配置 + */ +interface SiteConfig { + storeState?: { + common: Record + user: Record + } +} + +declare global { + interface Window { + SITE_CONFIG?: SiteConfig + } +} + +/** + * Vue 全局属性类型声明 + */ +declare module '@vue/runtime-core' { + interface ComponentCustomProperties { + $http: typeof httpRequest + isAuth: (key: string) => boolean + } +} + +export {} diff --git a/src/utils/cookie.ts b/src/utils/cookie.ts new file mode 100755 index 0000000..35127e8 --- /dev/null +++ b/src/utils/cookie.ts @@ -0,0 +1,17 @@ +/** + * 简单 cookie 读写,替代 vue-cookie,供 Vue 3 项目使用 + */ +export function getCookie(name: string): string | null { + const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)') + return v ? decodeURIComponent(v[2]) : null +} + +export function setCookie(name: string, value: string, days: number = 7): void { + const d = new Date() + d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000) + document.cookie = name + '=' + encodeURIComponent(value) + ';path=/;expires=' + d.toUTCString() +} + +export function deleteCookie(name: string): void { + document.cookie = name + '=;path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT' +} diff --git a/src/utils/device-list.ts b/src/utils/device-list.ts new file mode 100755 index 0000000..bb0e4c7 --- /dev/null +++ b/src/utils/device-list.ts @@ -0,0 +1,112 @@ +/** + * 设备绑定的卡片信息 + */ +export interface BoundCard { + cardNo?: string + activeAt?: string | null + bindAt?: string | null + expireAt?: string | null + cardStatus?: string + usageStatus?: string + bindStatus?: string + [key: string]: any +} + +/** + * 设备列表项基础接口 + */ +export interface DeviceListItem { + deviceSn?: string + sn?: string + deviceUid?: string + uid?: string + status?: string + authorizedAt?: string | null + expireAt?: string | null + bindCardNo?: string | null + bindCardActiveAt?: string | null + bindCardPresetAt?: string | null + bindCardExpireAt?: string | null + bindCardStatus?: string | null + /** 设备固件/应用版本展示名 */ + verName?: string | null + /** 设备版本编码 */ + verCode?: string | null + cardLists?: BoundCard[] + boundList?: BoundCard[] + boundCards?: BoundCard[] + cards?: BoundCard[] + cardList?: BoundCard[] + [key: string]: any +} + +/** + * 设备列表/详情:绑定卡数组字段名兼容(详情 cardLists / boundList、列表 boundCards 等)。 + * @param item - 设备对象 + * @returns 绑定的卡片列表 + */ +export function getDeviceBoundList(item: Record): BoundCard[] { + if (!item || typeof item !== 'object') return [] + const list = item.cardLists ?? item.boundList ?? item.boundCards ?? item.cards ?? item.cardList + return Array.isArray(list) ? list : [] +} + +/** + * 从绑定的卡片列表中选择一个主要卡片 + * @param boundCards - 绑定的卡片列表 + * @returns 主要卡片或 null + */ +function pickPrimaryBoundCard(boundCards: BoundCard[]): BoundCard | null { + if (!Array.isArray(boundCards) || !boundCards.length) return null + const bound = boundCards.find(c => String(c?.bindStatus || '').toUpperCase() === 'BOUND') + return bound || boundCards[0] +} + +/** + * 将设备记录规范为表格使用的扁平字段(兼容 boundList / boundCards、authorizedAt 等)。 + * @param item - 设备对象 + * @returns 规范化后的设备对象 + */ +export function normalizeDeviceListItem(item: Record): DeviceListItem { + if (!item || typeof item !== 'object') return item + const primary = pickPrimaryBoundCard(getDeviceBoundList(item)) + + const bindCardNo = item.bindCardNo ?? primary?.cardNo ?? null + const bindCardActiveAt = + item.bindCardActiveAt ?? primary?.activeAt ?? primary?.bindAt ?? item.authorizedAt ?? null + const bindCardPresetAt = item.bindCardPresetAt ?? null + const bindCardExpireAt = + item.bindCardExpireAt ?? primary?.expireAt ?? item.expireAt ?? null + + let bindCardStatus = item.bindCardStatus + if (bindCardStatus == null || bindCardStatus === '') { + if (primary) { + bindCardStatus = primary.cardStatus ?? primary.usageStatus ?? item.status + } else { + bindCardStatus = item.status ?? 'UNBOUND' + } + } + + return { + ...item, + deviceSn: item.deviceSn ?? item.sn, + deviceUid: item.deviceUid ?? item.uid, + verName: item.verName ?? item.ver_name ?? null, + verCode: item.verCode ?? item.ver_code ?? null, + bindCardNo, + bindCardActiveAt, + bindCardPresetAt, + bindCardExpireAt, + bindCardStatus + } +} + +/** + * 规范化设备列表 + * @param list - 设备列表 + * @returns 规范化后的设备列表 + */ +export function normalizeDeviceList(list: any[]): DeviceListItem[] { + if (!Array.isArray(list)) return [] + return list.map(normalizeDeviceListItem) +} diff --git a/src/utils/httpRequest.ts b/src/utils/httpRequest.ts new file mode 100755 index 0000000..a3a768b --- /dev/null +++ b/src/utils/httpRequest.ts @@ -0,0 +1,201 @@ +import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig, AxiosResponse } from 'axios' +import router from '@/router' +import qs from 'qs' +import merge from 'lodash/merge' +import { clearLoginInfo, getToken, getRefreshToken, isRefreshTokenValid, setTokenData } from '@/utils' +import { baseApi } from '@/config/env' + +/** + * API 响应数据标准格式 + */ +export interface ApiResponse { + code: number + msg: string + data: T +} + +/** + * 刷新 Token 响应 + */ +export interface RefreshTokenResponse { + code?: number + token?: string + expire?: number + refreshToken?: string + refreshExpire?: number +} + +/** + * 扩展的 Axios 实例,包含自定义方法 + */ +interface HttpInstance extends AxiosInstance { + adornUrl: (actionName?: string) => string + adornParams: (params?: Record, openDefaultParams?: boolean) => Record + adornData: (data?: Record, openDefaultData?: boolean, contentType?: 'json' | 'form') => string +} + +/** + * 仅用于刷新 token 的 axios 实例(无拦截器,避免 401 死循环) + * baseURL 为空,所有路径由 adornUrl 统一返回 /api/xxx,全部走代理 + */ +const refreshHttp: AxiosInstance = axios.create({ + baseURL: '', + timeout: 10000, + withCredentials: false, + headers: { 'Content-Type': 'application/json; charset=utf-8' } +}) + +let refreshPromise: Promise | null = null + +/** + * 使用 refreshToken 换取新的 token + * @returns 新的 access token 或 null + */ +function doRefresh(): Promise { + if (refreshPromise) return refreshPromise + const refreshToken = getRefreshToken() + if (!refreshToken || !isRefreshTokenValid()) { + clearLoginInfo() + router.push({ name: 'login' }) + return Promise.resolve(null) + } + refreshPromise = refreshHttp.post>(`${baseApi}/sys/refresh`, { refreshToken }, { + headers: { 'Content-Type': 'application/json' } + }).then((res) => { + const data = res.data?.data || res.data + if (data && (res.data.code === 0 || res.data.code === undefined) && data.token) { + setTokenData({ + token: data.token, + expire: data.expire, + refreshToken: data.refreshToken, + refreshExpire: data.refreshExpire + }) + return data.token + } + clearLoginInfo() + router.push({ name: 'login' }) + return null + }).catch(() => { + clearLoginInfo() + router.push({ name: 'login' }) + return null + }).finally(() => { + refreshPromise = null + }) + return refreshPromise +} + +/** + * axios 实例 + * baseURL 为空,所有路径由 adornUrl 统一返回 /api/xxx,全部走代理 + */ +const http: HttpInstance = axios.create({ + baseURL: '', + timeout: 1000 * 30, + withCredentials: false, + headers: { + 'Content-Type': 'application/json; charset=utf-8' + } +}) as HttpInstance + +/** + * 请求拦截:附带 access token;若已过期则先刷新再带新 token + */ +http.interceptors.request.use( + async (config: InternalAxiosRequestConfig): Promise => { + if (config.url && config.url.includes(`${baseApi}/sys/refresh`)) { + return config + } + let token = getToken() + if (!token && getRefreshToken() && isRefreshTokenValid()) { + token = await doRefresh() + } + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + return config + }, + (error: AxiosError): Promise => Promise.reject(error) +) + +/** + * 响应拦截:业务 401 或 HTTP 401 时尝试用 refreshToken 换新 token 并重试一次,失败则跳转登录 + */ +http.interceptors.response.use( + (response: AxiosResponse): AxiosResponse | Promise> => { + if (response.data && response.data.code === 401) { + return handle401(response.config) + } + return response + }, + async (error: AxiosError): Promise> => { + if (error.response && error.response.status === 401) { + return handle401(error.config as InternalAxiosRequestConfig) + } + return Promise.reject(error) + } +) + +async function handle401(config: InternalAxiosRequestConfig): Promise> { + const refreshToken = getRefreshToken() + if (refreshToken && isRefreshTokenValid()) { + const newToken = await doRefresh() + if (newToken && config) { + config.headers = config.headers || {} + config.headers.Authorization = `Bearer ${newToken}` + return http.request(config) + } + } + clearLoginInfo() + router.push({ name: 'login' }) + return Promise.reject(new Error('登录已失效')) +} + +/** + * 请求地址处理:统一返回 /api/xxx,任何接口都走代理 + * @param actionName action 方法名称,如:'/sys/login'、'/captcha.jpg?uuid=xxx' + */ +http.adornUrl = (actionName: string = ''): string => { + // 已是完整 URL 则直接返回(跨域场景,不常见) + if (/^https?:\/\//.test(actionName)) { + return actionName + } + const path = (actionName || '').replace(/^\/+/, '').replace(/^api\/?/, '') + if (!path) { + return baseApi + } + return `${baseApi}/${path}` +} + +/** + * GET 请求参数处理 + * - 默认带上时间戳 t,防止缓存,与原逻辑一致 + * @param params 参数对象 + * @param openDefaultParams 是否开启默认参数 + */ +http.adornParams = (params: Record = {}, openDefaultParams: boolean = true): Record => { + const defaults = { + t: Date.now() + } + return openDefaultParams ? merge(defaults, params) : params +} + +/** + * POST 请求数据处理 + * - 默认带上时间戳 t,防止缓存 + * - 支持 json / form 两种 Content-Type,与原逻辑一致 + * @param data 数据对象 + * @param openDefaultData 是否开启默认数据 + * @param contentType 数据格式 + */ +http.adornData = (data: Record = {}, openDefaultData: boolean = true, contentType: 'json' | 'form' = 'json'): string => { + const defaults = { + t: Date.now() + } + const merged = openDefaultData ? merge(defaults, data) : data + return contentType === 'json' + ? JSON.stringify(merged) + : qs.stringify(merged) +} + +export default http diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100755 index 0000000..7c56977 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,154 @@ +import router from '@/router' +import { resetStoresFromSiteConfig } from '@/stores/reset' + +const TOKEN_KEY = 'token' +const TOKEN_EXPIRE_KEY = 'tokenExpire' +const REFRESH_TOKEN_KEY = 'refreshToken' +const REFRESH_EXPIRE_KEY = 'refreshExpire' + +/** + * Token 数据结构 + */ +export interface TokenData { + token?: string + expire?: number + refreshToken?: string + refreshExpire?: number +} + +/** + * 树形数据节点 + */ +export interface TreeNode { + id?: string | number + parentId?: string | number + children?: TreeNode[] + _level?: number + [key: string]: any +} + +/** + * 获取uuid + * @returns UUID 字符串 + */ +export function getUUID(): string { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { + const r = (Math.random() * 16) | 0 + const v = c === 'x' ? r : (r & 0x3) | 0x8 + return v.toString(16) + }) +} + +/** + * 是否有权限 + * @param key - 权限标识 + * @returns 是否有权限 + */ +export function isAuth(key: string): boolean { + return JSON.parse(sessionStorage.getItem('permissions') || '[]').indexOf(key) !== -1 || false +} + +/** + * 树形数据转换 + * @param data - 原始数据数组 + * @param id - ID 字段名 + * @param pid - 父ID 字段名 + * @returns 转换后的树形结构 + */ +export function treeDataTranslate( + data: TreeNode[], + id: string = 'id', + pid: string = 'parentId' +): TreeNode[] { + const res: TreeNode[] = [] + const temp: Record = {} + for (let i = 0; i < data.length; i++) { + temp[data[i][id] as string] = data[i] + } + for (let k = 0; k < data.length; k++) { + if (temp[data[k][pid] as string] && data[k][id] !== data[k][pid]) { + if (!temp[data[k][pid] as string]['children']) { + temp[data[k][pid] as string]['children'] = [] + } + if (!temp[data[k][pid] as string]['_level']) { + temp[data[k][pid] as string]['_level'] = 1 + } + data[k]['_level'] = temp[data[k][pid] as string]._level! + 1 + temp[data[k][pid] as string]['children']!.push(data[k]) + } else { + res.push(data[k]) + } + } + return res +} + +/** + * 获取 token(供 httpRequest 等使用) + * 使用 localStorage 存储,不写入 Cookie,关键信息不在 Cookie 中暴露 + * @returns token 或 null + */ +export function getToken(): string | null { + const token = localStorage.getItem(TOKEN_KEY) + const tokenExpire = localStorage.getItem(TOKEN_EXPIRE_KEY) + if (!token) return null + const expireAt = tokenExpire ? parseInt(tokenExpire, 10) : 0 + if (expireAt > 0 && Date.now() >= expireAt) return null + return token +} + +/** + * 获取 refreshToken + * @returns refreshToken 或 null + */ +export function getRefreshToken(): string | null { + return localStorage.getItem(REFRESH_TOKEN_KEY) +} + +/** + * refreshToken 是否仍在有效期内(未过期) + * @returns 是否有效 + */ +export function isRefreshTokenValid(): boolean { + const refreshExpire = localStorage.getItem(REFRESH_EXPIRE_KEY) + if (!refreshExpire) return false + const expireAt = parseInt(refreshExpire, 10) + return expireAt > Date.now() +} + +/** + * 保存双 token 数据(登录或刷新后调用) + * @param data - { token, expire, refreshToken, refreshExpire } 其中 expire/refreshExpire 单位为秒 + */ +export function setTokenData(data: TokenData): void { + if (!data) return + if (data.token) localStorage.setItem(TOKEN_KEY, data.token) + if (data.expire != null) { + const expireAt = Date.now() + Number(data.expire) * 1000 + localStorage.setItem(TOKEN_EXPIRE_KEY, String(expireAt)) + } + if (data.refreshToken) localStorage.setItem(REFRESH_TOKEN_KEY, data.refreshToken) + if (data.refreshExpire != null) { + const refreshExpireAt = Date.now() + Number(data.refreshExpire) * 1000 + localStorage.setItem(REFRESH_EXPIRE_KEY, String(refreshExpireAt)) + } +} + +/** + * 清除登录信息(含双 token) + */ +export function clearLoginInfo(): void { + localStorage.removeItem(TOKEN_KEY) + localStorage.removeItem(TOKEN_EXPIRE_KEY) + localStorage.removeItem(REFRESH_TOKEN_KEY) + localStorage.removeItem(REFRESH_EXPIRE_KEY) + sessionStorage.removeItem('nearExpiryUnusedCardsPromptShown') + // 清除旧菜单数据,确保重新登录后获取最新菜单路由 + sessionStorage.removeItem('menuList') + sessionStorage.removeItem('dynamicMenuRoutes') + // 清理可能残留的 token Cookie,避免关键信息暴露 + ;['token', 'tokenExpire', 'refreshToken', 'refreshExpire'].forEach((name) => { + document.cookie = name + '=;path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT' + }) + resetStoresFromSiteConfig() + ;(router as any).isAddDynamicMenuRoutes = false +} diff --git a/src/utils/ossCosUpload.ts b/src/utils/ossCosUpload.ts new file mode 100755 index 0000000..d328fc2 --- /dev/null +++ b/src/utils/ossCosUpload.ts @@ -0,0 +1,169 @@ +import COS from 'cos-js-sdk-v5' +import { getOssStsCredential, type OssStsCredentialOptions, type OssStsCredentialPayload } from '@/api/oss' + +export interface OssStsUploadOptions extends OssStsCredentialOptions {} + +/** 上传用安全文件名(去掉路径分隔符) */ +export function sanitizeUploadFileName (name: string): string { + const trimmed = (name || '').trim().replace(/[/\\]+/g, '_') + return trimmed || 'file.bin' +} + +/** 将访问 URL 最后一段替换为指定文件名 */ +export function replaceUrlBasename (url: string, basename: string): string { + try { + const u = new URL(url) + const segments = u.pathname.split('/') + segments[segments.length - 1] = basename + u.pathname = segments.join('/') + return u.href + } catch { + return url + } +} + +/** + * 解析应写入表单的访问地址:当 COS Key 已是原始文件名时,将 URL 末尾同步为同名(避免后端 url 仍返回哈希名) + */ +export function resolveUploadedFileUrl ( + cred: NormalizedOssStsCredential, + fileName: string +): string { + if (!cred.url) return '' + const safeName = sanitizeUploadFileName(fileName) + const keyBase = cred.key.split('/').filter(Boolean).pop() || '' + if ( + safeName && + (keyBase === safeName || keyBase.toLowerCase() === safeName.toLowerCase()) + ) { + return replaceUrlBasename(cred.url, safeName) + } + return cred.url +} + +/** 访问 URL 末尾是否与原始文件名一致 */ +export function uploadedUrlKeepsFileName (url: string, fileName: string): boolean { + const safeName = sanitizeUploadFileName(fileName).toLowerCase() + if (!safeName || !url) return false + try { + const base = decodeURIComponent(new URL(url).pathname.split('/').pop() || '').toLowerCase() + return base === safeName + } catch { + return url.toLowerCase().endsWith(safeName) + } +} + +export interface NormalizedOssStsCredential { + tmpSecretId: string + tmpSecretKey: string + securityToken: string + /** Unix 秒 */ + expiredTime: number + bucket: string + region: string + /** 必须使用后端下发的 Key */ + key: string + url: string +} + +function pickStr (...vals: Array): string { + for (const v of vals) { + if (v != null && String(v).trim() !== '') return String(v).trim() + } + return '' +} + +function normalizeExpiredTime (t: unknown): number { + const n = typeof t === 'number' ? t : Number(t) + if (!Number.isFinite(n) || n <= 0) return 0 + // 毫秒时间戳常见 > 1e12 + if (n > 1e12) return Math.floor(n / 1000) + return Math.floor(n) +} + +/** 解析接口返回的凭证对象(credential 或 data)为可用的 COS 信息 */ +export function normalizeStsCredentialPayload (raw: OssStsCredentialPayload | null | undefined): NormalizedOssStsCredential | null { + if (!raw || typeof raw !== 'object') return null + const tmpSecretId = pickStr(raw.TmpSecretId, raw.tmpSecretId) + const tmpSecretKey = pickStr(raw.TmpSecretKey, raw.tmpSecretKey) + const securityToken = pickStr(raw.SecurityToken, raw.securityToken, raw.sessionToken) + const expiredTime = normalizeExpiredTime( + raw.ExpiredTime != null ? raw.ExpiredTime : raw.expiredTime + ) + const bucket = pickStr(raw.bucket, raw.Bucket) + const region = pickStr(raw.region, raw.Region) + const key = pickStr(raw.key, raw.Key) + const url = pickStr(raw.url) + if (!tmpSecretId || !tmpSecretKey || !bucket || !region || !key) return null + return { + tmpSecretId, + tmpSecretKey, + securityToken, + expiredTime, + bucket, + region, + key, + url, + } +} + +async function fetchNormalizedCredential ( + filename: string, + options?: OssStsUploadOptions +): Promise { + const res = await getOssStsCredential(filename, options) + if (!res || res.code !== 0) { + const msg = res && typeof res.msg === 'string' ? res.msg : '获取上传凭证失败' + throw new Error(msg) + } + const normalized = normalizeStsCredentialPayload( + res.credential ?? (typeof res.data === 'object' && res.data !== null ? res.data : undefined) + ) + if (!normalized) { + throw new Error('上传凭证数据不完整') + } + return normalized +} + +/** 使用 STS 凭证将文件 PUT 至 COS(Key 必须为后端下发的 key) */ +export function cosPutObjectWithStsCredential (file: File, cred: NormalizedOssStsCredential): Promise { + return new Promise((resolve, reject) => { + const cos = new COS({ + getAuthorization (_options, callback) { + const authParams: Record = { + TmpSecretId: cred.tmpSecretId, + TmpSecretKey: cred.tmpSecretKey, + } + if (cred.securityToken) authParams.SecurityToken = cred.securityToken + if (cred.expiredTime > 0) authParams.ExpiredTime = cred.expiredTime + callback(authParams as never) + }, + }) + cos.putObject( + { + Bucket: cred.bucket, + Region: cred.region, + Key: cred.key, + Body: file, + }, + err => { + if (err) reject(err) + else resolve() + } + ) + }) +} + +/** 请求 STS → COS putObject → 返回与原始文件名一致的访问 URL */ +export async function uploadFileViaStsCos ( + file: File, + options?: OssStsUploadOptions +): Promise { + const safeName = sanitizeUploadFileName(file?.name || 'file.bin') + const cred = await fetchNormalizedCredential(safeName, options) + await cosPutObjectWithStsCredential(file, cred) + if (!cred.url) { + throw new Error('未返回访问地址 url') + } + return resolveUploadedFileUrl(cred, safeName) +} diff --git a/src/utils/validate.ts b/src/utils/validate.ts new file mode 100755 index 0000000..df4fc70 --- /dev/null +++ b/src/utils/validate.ts @@ -0,0 +1,31 @@ +/** + * 邮箱 + * @param s - 待验证字符串 + */ +export function isEmail(s: string): boolean { + return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s) +} + +/** + * 手机号码 + * @param s - 待验证字符串 + */ +export function isMobile(s: string): boolean { + return /^1[0-9]{10}$/.test(s) +} + +/** + * 电话号码 + * @param s - 待验证字符串 + */ +export function isPhone(s: string): boolean { + return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s) +} + +/** + * URL地址 + * @param s - 待验证字符串 + */ +export function isURL(s: string): boolean { + return /^http[s]?:\/\/.*/.test(s) +} diff --git a/src/views/common/404.vue b/src/views/common/404.vue new file mode 100755 index 0000000..f9b1872 --- /dev/null +++ b/src/views/common/404.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/src/views/common/home.vue b/src/views/common/home.vue new file mode 100755 index 0000000..ffab9a2 --- /dev/null +++ b/src/views/common/home.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/src/views/common/login.vue b/src/views/common/login.vue new file mode 100755 index 0000000..62c7e9b --- /dev/null +++ b/src/views/common/login.vue @@ -0,0 +1,786 @@ + + + + + diff --git a/src/views/modules/card-allocation/detail.data.ts b/src/views/modules/card-allocation/detail.data.ts new file mode 100755 index 0000000..df10fb0 --- /dev/null +++ b/src/views/modules/card-allocation/detail.data.ts @@ -0,0 +1,52 @@ +/** 各卡类型可分配统计行 */ +export interface ByTypeStatItem { + cardType: string + cardTypeName?: string + allocatableCount?: number +} + +/** 周期卡 / 其他 分组区块 */ +export interface ByTypeSection { + key: string + title: string + items: ByTypeStatItem[] +} + +/** 卡流向明细表格行 */ +export interface CardFlowRow { + bizDate: string + counterpartyOrgName: string + counterpartyOrgType: string + counterpartyOrgId?: number | string + outCount: number + inCount: number +} + +/** 接口原始行(解析后写入 CardFlowRow) */ +export interface RawFlowRow { + bizDate?: string + counterpartyOrgName?: string + counterpartyOrgType?: string + counterpartyOrgId?: number | string + outCount?: number + inCount?: number +} + +/** 服务端组织类型枚举 -> 文案 */ +export const ORG_TYPE_LABEL: Record = { + SERVICE_PROVIDER: '服务商', + STORE: '门店', + CHANNEL: '渠道' +} + +/** 周期卡:年 / 季 / 月 / 周;其余归入「其他」 */ +export const PERIOD_CARD_TYPES = ['YEAR', 'QUARTER', 'MONTH', 'WEEK'] as const + +export type PeriodCardType = (typeof PERIOD_CARD_TYPES)[number] + +export const PERIOD_TYPE_ORDER: Record = { + YEAR: 0, + QUARTER: 1, + MONTH: 2, + WEEK: 3 +} diff --git a/src/views/modules/card-allocation/detail.vue b/src/views/modules/card-allocation/detail.vue new file mode 100755 index 0000000..c0c4e28 --- /dev/null +++ b/src/views/modules/card-allocation/detail.vue @@ -0,0 +1,581 @@ + + + + + diff --git a/src/views/modules/card-flow/allocation-order-final-destination-stats.vue b/src/views/modules/card-flow/allocation-order-final-destination-stats.vue new file mode 100755 index 0000000..4a10d92 --- /dev/null +++ b/src/views/modules/card-flow/allocation-order-final-destination-stats.vue @@ -0,0 +1,581 @@ + + + + + diff --git a/src/views/modules/card-flow/card-flow.vue b/src/views/modules/card-flow/card-flow.vue new file mode 100755 index 0000000..5f22da4 --- /dev/null +++ b/src/views/modules/card-flow/card-flow.vue @@ -0,0 +1,452 @@ + + + + + diff --git a/src/views/modules/card/card-import-batches.vue b/src/views/modules/card/card-import-batches.vue new file mode 100755 index 0000000..1564470 --- /dev/null +++ b/src/views/modules/card/card-import-batches.vue @@ -0,0 +1,460 @@ + + + + + diff --git a/src/views/modules/card/card-import.vue b/src/views/modules/card/card-import.vue new file mode 100755 index 0000000..acfb0a8 --- /dev/null +++ b/src/views/modules/card/card-import.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/views/modules/card/card.vue b/src/views/modules/card/card.vue new file mode 100755 index 0000000..809a9a8 --- /dev/null +++ b/src/views/modules/card/card.vue @@ -0,0 +1,302 @@ + + + + + diff --git a/src/views/modules/card/components/card-detail.vue b/src/views/modules/card/components/card-detail.vue new file mode 100755 index 0000000..968f936 --- /dev/null +++ b/src/views/modules/card/components/card-detail.vue @@ -0,0 +1,124 @@ + + + + + diff --git a/src/views/modules/card/components/card-import-dialog.vue b/src/views/modules/card/components/card-import-dialog.vue new file mode 100755 index 0000000..ac9cd4c --- /dev/null +++ b/src/views/modules/card/components/card-import-dialog.vue @@ -0,0 +1,48 @@ + + + diff --git a/src/views/modules/card/components/card-import-form.vue b/src/views/modules/card/components/card-import-form.vue new file mode 100755 index 0000000..8e1ffb4 --- /dev/null +++ b/src/views/modules/card/components/card-import-form.vue @@ -0,0 +1,829 @@ + + + diff --git a/src/views/modules/card/data.ts b/src/views/modules/card/data.ts new file mode 100755 index 0000000..e24d5e7 --- /dev/null +++ b/src/views/modules/card/data.ts @@ -0,0 +1,74 @@ +import type { CardInfo } from '@/api/card' +import type { PageParams, PageResult } from '@/types/api' + +export type ElTagType = 'success' | 'warning' | 'info' | 'danger' | undefined + +export interface CardTypeUiItem { + label: string + tagType?: ElTagType +} + +/** 导入批次列表行(兼容 snake_case 字段) */ +export interface ImportBatchRow extends Record { + id?: number | string + batchNo?: string + cardType?: string + cardTypeName?: string + totalCount?: number + importCount?: number + cardCount?: number + remark?: string + remarkNote?: string + note?: string + memo?: string + createdAt?: string +} + +export interface DataForm { + batchNo: string + remark: string + status: string +} + +export interface CardFilterForm { + usageStatus: string +} + +export interface CurrentBatch { + id: number | string | null + batchNo: string +} + +export interface ImportBatchListParams extends PageParams { + batchNo?: string + remark?: string + status?: string +} + +/** 列表接口响应体(兼容 page / list 两种分页形态;与 axios 的 data 字段一致) */ +export type ImportBatchListPayload = { + code?: number + msg?: string + page?: PageResult + list?: ImportBatchRow[] + totalCount?: number +} + +export type ImportBatchCardsPayload = { + code?: number + msg?: string + page?: PageResult + list?: CardInfo[] + totalCount?: number +} + +/** 无效卡回退渠道接口响应体 */ +export type RollbackInvalidBatchPayload = { + code?: number + msg?: string +} + +export interface BatchStatusOption { + value: string + label: string +} diff --git a/src/views/modules/device/components/device-import-dialog.data.ts b/src/views/modules/device/components/device-import-dialog.data.ts new file mode 100755 index 0000000..b405946 --- /dev/null +++ b/src/views/modules/device/components/device-import-dialog.data.ts @@ -0,0 +1,13 @@ +export interface DeviceImportDialogEmits { + (e: 'update:modelValue', v: boolean): void + (e: 'success'): void +} + +export interface DeviceImportFormInstance { + submitImport: () => Promise | void + importLoading?: { value: boolean } + canSubmit?: { value: boolean } + importResult?: { value: unknown } + activeStep?: unknown + primaryFooterLabel?: unknown +} diff --git a/src/views/modules/device/components/device-import-dialog.vue b/src/views/modules/device/components/device-import-dialog.vue new file mode 100755 index 0000000..9500970 --- /dev/null +++ b/src/views/modules/device/components/device-import-dialog.vue @@ -0,0 +1,64 @@ + + + diff --git a/src/views/modules/device/components/device-import-form.data.ts b/src/views/modules/device/components/device-import-form.data.ts new file mode 100755 index 0000000..c3dab3f --- /dev/null +++ b/src/views/modules/device/components/device-import-form.data.ts @@ -0,0 +1,64 @@ +import type { DeviceListItem } from '@/utils/device-list' + +/** 导入表格行(可编辑 MAC / 房间号及校验状态) */ +export type DeviceImportValidateStatus = + | 'validate_fail' + | 'validate_ok' + | 'import_fail' + | 'import_skip' + | null + +export interface DeviceImportRowItem { + mac: string + roomNo: string + _validateStatus?: DeviceImportValidateStatus + _validateMessage?: string + _removing?: boolean + _fromSelect?: boolean + _sourceRowUid?: string +} + +export type PreBindCardType = 'YEAR' | 'QUARTER' | 'MONTH' | 'WEEK' | 'OTHER' | string + +export const CARD_TYPE_LABELS: Record = { + YEAR: '年卡', + QUARTER: '季卡', + MONTH: '月卡', + WEEK: '周卡', + OTHER: '天卡' +} + +/** 批量预置导入结果 */ +export interface DeviceBatchImportResult { + successCount: number + failCount: number + skipCount: number + totalCount: number + hasError: boolean + items?: unknown +} + +export interface ValidatePassedBanner { + title: string + description: string +} + +/** 可选设备表格行(附加 rowUid 用于勾选同步) */ +export type SelectDeviceRow = DeviceListItem & { rowUid?: string } + +export interface DeviceImportFormModel { + storeOrgId: string | number | null + preBindCardType: PreBindCardType + items: DeviceImportRowItem[] +} + +export interface DeviceImportFormProps { + showActionBar: boolean + presetPreBindCardType: PreBindCardType + hidePreBindCardTypeSelector: boolean +} + +export interface OverviewChangePayload { + storeOrgId?: string | number | null + cardType?: PreBindCardType +} diff --git a/src/views/modules/device/components/device-import-form.vue b/src/views/modules/device/components/device-import-form.vue new file mode 100755 index 0000000..f0b1ffe --- /dev/null +++ b/src/views/modules/device/components/device-import-form.vue @@ -0,0 +1,1503 @@ + + + + + diff --git a/src/views/modules/device/components/device-preset-dialog.data.ts b/src/views/modules/device/components/device-preset-dialog.data.ts new file mode 100755 index 0000000..339a547 --- /dev/null +++ b/src/views/modules/device/components/device-preset-dialog.data.ts @@ -0,0 +1,13 @@ +export interface DevicePresetDialogEmits { + (e: 'update:modelValue', v: boolean): void + (e: 'success'): void +} + +export interface DeviceImportFormInstance { + submitImport: () => Promise | void + importLoading?: { value: boolean } + canSubmit?: { value: boolean } + importResult?: { value: unknown } + activeStep?: unknown + primaryFooterLabel?: unknown +} diff --git a/src/views/modules/device/components/device-preset-dialog.vue b/src/views/modules/device/components/device-preset-dialog.vue new file mode 100755 index 0000000..e9c3e45 --- /dev/null +++ b/src/views/modules/device/components/device-preset-dialog.vue @@ -0,0 +1,69 @@ + + + + diff --git a/src/views/modules/device/components/device-replace-duplicate-dialog.vue b/src/views/modules/device/components/device-replace-duplicate-dialog.vue new file mode 100755 index 0000000..fef746d --- /dev/null +++ b/src/views/modules/device/components/device-replace-duplicate-dialog.vue @@ -0,0 +1,243 @@ + + + + + + + diff --git a/src/views/modules/device/components/device-select-fullscreen-dialog.data.ts b/src/views/modules/device/components/device-select-fullscreen-dialog.data.ts new file mode 100755 index 0000000..acfbbc1 --- /dev/null +++ b/src/views/modules/device/components/device-select-fullscreen-dialog.data.ts @@ -0,0 +1,18 @@ +import type { DeviceImportRowItem } from './device-import-form.data' + +/** 设备列表行(选择弹窗右侧表格,与导入行结构兼容) */ +export interface SelectableDeviceRow { + mac?: string | null + deviceMac?: string | null + device_mac?: string | null + roomNo?: string | null + storeName?: string | null + storeOrgName?: string | null + orgName?: string | null + hotelName?: string | null + rowUid?: string + _removing?: boolean + [key: string]: unknown +} + +export type DeviceSelectImportItem = DeviceImportRowItem diff --git a/src/views/modules/device/components/device-select-fullscreen-dialog.vue b/src/views/modules/device/components/device-select-fullscreen-dialog.vue new file mode 100755 index 0000000..36a4600 --- /dev/null +++ b/src/views/modules/device/components/device-select-fullscreen-dialog.vue @@ -0,0 +1,328 @@ + + + + + diff --git a/src/views/modules/device/components/device-transfer-card-dialog.data.ts b/src/views/modules/device/components/device-transfer-card-dialog.data.ts new file mode 100755 index 0000000..820a729 --- /dev/null +++ b/src/views/modules/device/components/device-transfer-card-dialog.data.ts @@ -0,0 +1,30 @@ +import type { DeviceListItem } from '@/utils/device-list' + +export interface SameChannelOrgNode { + id?: string | number + name?: string + type?: string + label?: string + disabled?: boolean + children?: SameChannelOrgNode[] + [key: string]: unknown +} + +/** 选择目标设备时下拉中的「新增设备」哨兵值 */ +export const ADD_DEVICE_VALUE = '__ADD_DEVICE__' as const + +export interface TransferCardForm { + targetOrgId: string | number | null + toDeviceId: string | number | typeof ADD_DEVICE_VALUE | null + reason: string + reasonOther: string +} + +export interface TransferAddDeviceForm { + mac: string + deviceSn: string + roomNo: string + remark: string +} + +export type TransferSourceRow = DeviceListItem diff --git a/src/views/modules/device/components/device-transfer-card-dialog.vue b/src/views/modules/device/components/device-transfer-card-dialog.vue new file mode 100755 index 0000000..9aee1af --- /dev/null +++ b/src/views/modules/device/components/device-transfer-card-dialog.vue @@ -0,0 +1,493 @@ + + + + + + + diff --git a/src/views/modules/device/components/device-update-mac-dialog.data.ts b/src/views/modules/device/components/device-update-mac-dialog.data.ts new file mode 100755 index 0000000..323ca11 --- /dev/null +++ b/src/views/modules/device/components/device-update-mac-dialog.data.ts @@ -0,0 +1,7 @@ +import type { DeviceListItem } from '@/utils/device-list' + +export interface DeviceUpdateMacForm { + mac: string +} + +export type DeviceUpdateMacDevice = DeviceListItem | null diff --git a/src/views/modules/device/components/device-update-mac-dialog.vue b/src/views/modules/device/components/device-update-mac-dialog.vue new file mode 100755 index 0000000..1586a64 --- /dev/null +++ b/src/views/modules/device/components/device-update-mac-dialog.vue @@ -0,0 +1,155 @@ + + + diff --git a/src/views/modules/device/device-activation-failed.data.ts b/src/views/modules/device/device-activation-failed.data.ts new file mode 100755 index 0000000..93f8c7f --- /dev/null +++ b/src/views/modules/device/device-activation-failed.data.ts @@ -0,0 +1,13 @@ +import type { DeviceListItem } from '@/utils/device-list' + +export interface StoreOption { + id: string | number + name: string +} + +export interface ActivationFailedQueryForm { + orgId: string | number | null + mac: string +} + +export type ActivationFailedDeviceRow = DeviceListItem diff --git a/src/views/modules/device/device-activation-failed.vue b/src/views/modules/device/device-activation-failed.vue new file mode 100755 index 0000000..6bf92ac --- /dev/null +++ b/src/views/modules/device/device-activation-failed.vue @@ -0,0 +1,237 @@ + + + + + diff --git a/src/views/modules/device/device-duplicate-mac-sn.data.ts b/src/views/modules/device/device-duplicate-mac-sn.data.ts new file mode 100755 index 0000000..c8d5fee --- /dev/null +++ b/src/views/modules/device/device-duplicate-mac-sn.data.ts @@ -0,0 +1,33 @@ +import type { DeviceListItem } from '@/utils/device-list' + +export const STATUS_CONFIG = { + UNBOUND: { label: '未绑定', class: 'unbound' }, + PRESET: { label: '预置', class: 'preset' }, + ACTIVATING: { label: '激活中', class: 'activating' }, + ACTIVATION_FAILED: { label: '激活失败', class: 'activation-failed' }, + ACTIVE: { label: '已激活', class: 'active' }, + EXPIRED: { label: '过期', class: 'expired' }, + ACTIVATION_BIND: { label: '激活码', class: 'activation-bind' } +} as const + +export type DeviceStatusKey = keyof typeof STATUS_CONFIG + +export const STATUS_KEYS = Object.keys(STATUS_CONFIG) as DeviceStatusKey[] + +export const STATUS_ALIASES: Record = { + ACTIVATED: 'ACTIVE', + ACTIVATE_FAILED: 'ACTIVATION_FAILED' +} + +export const STATUS_NUM_MAP: Record = { + 1: 'UNBOUND', + 2: 'PRESET', + 3: 'ACTIVATING', + 4: 'ACTIVATION_FAILED', + 5: 'ACTIVE', + 6: 'EXPIRED' +} + +export type DuplicateMacSnDeviceRow = DeviceListItem + +export type ActionKind = 'clear' | 'delete' | 'disable' diff --git a/src/views/modules/device/device-duplicate-mac-sn.vue b/src/views/modules/device/device-duplicate-mac-sn.vue new file mode 100755 index 0000000..f2dd732 --- /dev/null +++ b/src/views/modules/device/device-duplicate-mac-sn.vue @@ -0,0 +1,353 @@ + + + + + diff --git a/src/views/modules/device/device-expiring-year.data.ts b/src/views/modules/device/device-expiring-year.data.ts new file mode 100755 index 0000000..dea6459 --- /dev/null +++ b/src/views/modules/device/device-expiring-year.data.ts @@ -0,0 +1,40 @@ +import type { DeviceListItem } from '@/utils/device-list' + +export const STATUS_CONFIG = { + UNBOUND: { label: '未绑定', class: 'unbound' }, + PRESET: { label: '预置', class: 'preset' }, + ACTIVATING: { label: '激活中', class: 'activating' }, + ACTIVATION_FAILED: { label: '激活失败', class: 'activation-failed' }, + ACTIVE: { label: '已激活', class: 'active' }, + EXPIRED: { label: '过期', class: 'expired' }, + ACTIVATION_BIND: { label: '激活码', class: 'activation-bind' } +} as const + +export type DeviceStatusKey = keyof typeof STATUS_CONFIG + +export const STATUS_KEYS = Object.keys(STATUS_CONFIG) as DeviceStatusKey[] + +export const STATUS_ALIASES: Record = { + ACTIVATED: 'ACTIVE', + ACTIVATE_FAILED: 'ACTIVATION_FAILED' +} + +export const STATUS_NUM_MAP: Record = { + 1: 'UNBOUND', + 2: 'PRESET', + 3: 'ACTIVATING', + 4: 'ACTIVATION_FAILED', + 5: 'ACTIVE', + 6: 'EXPIRED' +} + +export interface StoreOption { + id: string | number + name: string +} + +export interface ExpiringYearQueryForm { + orgId: string | number | null +} + +export type ExpiringYearDeviceRow = DeviceListItem diff --git a/src/views/modules/device/device-expiring-year.vue b/src/views/modules/device/device-expiring-year.vue new file mode 100755 index 0000000..52b224c --- /dev/null +++ b/src/views/modules/device/device-expiring-year.vue @@ -0,0 +1,263 @@ + + + + + diff --git a/src/views/modules/device/device-import.data.ts b/src/views/modules/device/device-import.data.ts new file mode 100755 index 0000000..710dae3 --- /dev/null +++ b/src/views/modules/device/device-import.data.ts @@ -0,0 +1,23 @@ +/** 设备导入页数据概览(展示用) */ +export interface DashboardStats { + cumulativePurchase: number + cumulativeActivation: number + preRecharge: number + currentRemaining: number + estimatedRemaining: number + activationFailedCount: number + unboundActivation: number + activeCodeCount: number +} + +/** 概览 byType 单项 */ +export interface OrgCardOverviewByTypeRow { + cardType?: string + allocatableCount?: number + [key: string]: unknown +} + +export interface OverviewChangePayload { + storeOrgId?: string | number | null + cardType?: string +} diff --git a/src/views/modules/device/device-import.vue b/src/views/modules/device/device-import.vue new file mode 100755 index 0000000..9ba5069 --- /dev/null +++ b/src/views/modules/device/device-import.vue @@ -0,0 +1,136 @@ + + + + + diff --git a/src/views/modules/device/device-info.data.ts b/src/views/modules/device/device-info.data.ts new file mode 100755 index 0000000..e348951 --- /dev/null +++ b/src/views/modules/device/device-info.data.ts @@ -0,0 +1,14 @@ +import type { DeviceListItem } from '@/utils/device-list' + +export interface AssignStoreForm { + storeOrgId: string +} + +/** 无组织设备列表行 */ +export type DeviceInfoRow = DeviceListItem & { + id?: string | number + deviceId?: string | number + mac?: string | null + createdAt?: string | number | null + [key: string]: unknown +} diff --git a/src/views/modules/device/device-info.vue b/src/views/modules/device/device-info.vue new file mode 100755 index 0000000..f1aead1 --- /dev/null +++ b/src/views/modules/device/device-info.vue @@ -0,0 +1,224 @@ + + + + + \ No newline at end of file diff --git a/src/views/modules/device/device.data.ts b/src/views/modules/device/device.data.ts new file mode 100755 index 0000000..b5784cf --- /dev/null +++ b/src/views/modules/device/device.data.ts @@ -0,0 +1,118 @@ +import type { DeviceListItem } from '@/utils/device-list' + +/** 列表权益状态(与后端枚举对齐;部分状态仅接口返回、无展示配置时回落为 unknown 样式) */ +export const STATUS_CONFIG = { + UNBOUND: { label: '未绑定', class: 'unbound' }, + PRESET: { label: '预置', class: 'preset' }, + ACTIVATING: { label: '激活中', class: 'activating' }, + ACTIVATION_FAILED: { label: '激活失败', class: 'activation-failed' }, + ACTIVE: { label: '已激活', class: 'active' }, + EXPIRED: { label: '过期', class: 'expired' } +} as const + +export type DeviceBindStatusKey = keyof typeof STATUS_CONFIG | 'ACTIVATION_BIND' + +export const STATUS_KEYS = Object.keys(STATUS_CONFIG) as (keyof typeof STATUS_CONFIG)[] + +export const STATUS_ALIASES: Record = { + ACTIVATED: 'ACTIVE', + ACTIVATE_FAILED: 'ACTIVATION_FAILED' +} + +export const STATUS_NUM_MAP: Record = { + 1: 'UNBOUND', + 2: 'PRESET', + 3: 'ACTIVATING', + 4: 'ACTIVATION_FAILED', + 5: 'ACTIVE', + 6: 'EXPIRED' +} + +/** 操作列 fixed 宽度 */ +export const DEVICE_TABLE_ACTION_COL_WIDTH = 580 + +export interface StoreOption { + id: string | number + name: string +} + +export interface StoreNameOption { + id: string | number + label: string +} + +export type StorePickMode = 'name' | string + +export interface DeviceQueryForm { + status: string | null + mac: string + cardNo: string +} + +export type DeviceDialogKey = + | 'transfer' + | 'transferStore' + | 'replace' + | 'editRoom' + | 'renew' + | 'detail' + | 'updateMac' + | 'developerMigrate' + +export type DeviceLoadingFlagKey = + | 'add' + | 'transferStore' + | 'replace' + | 'editRoom' + | 'renew' + | 'detail' + | 'developerMigrate' + +export interface DeviceDialogsState { + transfer: boolean + transferStore: boolean + replace: boolean + editRoom: boolean + renew: boolean + detail: boolean + updateMac: boolean + developerMigrate: boolean +} + +export interface DeviceLoadingFlagsState { + add: boolean + transferStore: boolean + replace: boolean + editRoom: boolean + renew: boolean + detail: boolean + developerMigrate: boolean +} + +export interface DeviceFormsState { + editRoom: { mac: string; currentRoomNo: string; roomNo: string } + renew: { mac: string; cardType: string } + replace: { cardId: number | null } + transferStore: { mac: string; currentStoreName: string; storeOrgId: string | number | null } + developerMigrate: { storeId: string | number | null; mac: string; expireAt: string } +} + +export interface DeviceAddForm { + storeOrgId: string | number | null + mac: string + deviceSn: string + roomNo: string + remark: string + preBind: boolean + preBindCardType: string +} + +export interface DeviceDetailItem { + label: string + prop?: string + format: (d: DeviceListItem | null | undefined) => string +} + +export type DeviceResetFormKey = keyof Pick + +export type DeviceTableRow = DeviceListItem diff --git a/src/views/modules/device/device.vue b/src/views/modules/device/device.vue new file mode 100755 index 0000000..cf88f51 --- /dev/null +++ b/src/views/modules/device/device.vue @@ -0,0 +1,1355 @@ + + + + + diff --git a/src/views/modules/jetsen-media/list.vue b/src/views/modules/jetsen-media/list.vue new file mode 100644 index 0000000..caf37d9 --- /dev/null +++ b/src/views/modules/jetsen-media/list.vue @@ -0,0 +1,300 @@ + + + + + diff --git a/src/views/modules/job/components/schedule-add-or-update.vue b/src/views/modules/job/components/schedule-add-or-update.vue new file mode 100755 index 0000000..e45620c --- /dev/null +++ b/src/views/modules/job/components/schedule-add-or-update.vue @@ -0,0 +1,140 @@ + + + diff --git a/src/views/modules/job/components/schedule-log.vue b/src/views/modules/job/components/schedule-log.vue new file mode 100755 index 0000000..7bc26b0 --- /dev/null +++ b/src/views/modules/job/components/schedule-log.vue @@ -0,0 +1,196 @@ + + + diff --git a/src/views/modules/job/schedule.vue b/src/views/modules/job/schedule.vue new file mode 100755 index 0000000..04d3f3a --- /dev/null +++ b/src/views/modules/job/schedule.vue @@ -0,0 +1,336 @@ + + + diff --git a/src/views/modules/manage/activation-code.vue b/src/views/modules/manage/activation-code.vue new file mode 100644 index 0000000..9ae5c60 --- /dev/null +++ b/src/views/modules/manage/activation-code.vue @@ -0,0 +1,215 @@ + + + + + diff --git a/src/views/modules/manage/card-order.vue b/src/views/modules/manage/card-order.vue new file mode 100644 index 0000000..ca2f42c --- /dev/null +++ b/src/views/modules/manage/card-order.vue @@ -0,0 +1,242 @@ + + + + + diff --git a/src/views/modules/manage/card-pool.vue b/src/views/modules/manage/card-pool.vue new file mode 100644 index 0000000..3d7cf0f --- /dev/null +++ b/src/views/modules/manage/card-pool.vue @@ -0,0 +1,312 @@ + + + + + diff --git a/src/views/modules/manage/channel.vue b/src/views/modules/manage/channel.vue new file mode 100644 index 0000000..0c2d492 --- /dev/null +++ b/src/views/modules/manage/channel.vue @@ -0,0 +1,314 @@ + + + + + diff --git a/src/views/modules/manage/content-package.vue b/src/views/modules/manage/content-package.vue new file mode 100644 index 0000000..d25a957 --- /dev/null +++ b/src/views/modules/manage/content-package.vue @@ -0,0 +1,542 @@ + + + + + diff --git a/src/views/modules/manage/device.vue b/src/views/modules/manage/device.vue new file mode 100644 index 0000000..81a0d23 --- /dev/null +++ b/src/views/modules/manage/device.vue @@ -0,0 +1,503 @@ + + + + + diff --git a/src/views/modules/manage/openapi-call-log.vue b/src/views/modules/manage/openapi-call-log.vue new file mode 100644 index 0000000..4396229 --- /dev/null +++ b/src/views/modules/manage/openapi-call-log.vue @@ -0,0 +1,159 @@ + + + + + diff --git a/src/views/modules/manage/partner-card.vue b/src/views/modules/manage/partner-card.vue new file mode 100644 index 0000000..ef88618 --- /dev/null +++ b/src/views/modules/manage/partner-card.vue @@ -0,0 +1,385 @@ + + + + + diff --git a/src/views/modules/manage/partner-device.vue b/src/views/modules/manage/partner-device.vue new file mode 100644 index 0000000..d990c6f --- /dev/null +++ b/src/views/modules/manage/partner-device.vue @@ -0,0 +1,133 @@ + + + + + diff --git a/src/views/modules/manage/partner.vue b/src/views/modules/manage/partner.vue new file mode 100644 index 0000000..9ac6c6b --- /dev/null +++ b/src/views/modules/manage/partner.vue @@ -0,0 +1,283 @@ + + + + + diff --git a/src/views/modules/manage/pay-config.vue b/src/views/modules/manage/pay-config.vue new file mode 100644 index 0000000..3406e5b --- /dev/null +++ b/src/views/modules/manage/pay-config.vue @@ -0,0 +1,288 @@ + + + + + diff --git a/src/views/modules/manage/price.vue b/src/views/modules/manage/price.vue new file mode 100644 index 0000000..af1c2ac --- /dev/null +++ b/src/views/modules/manage/price.vue @@ -0,0 +1,391 @@ + + + + + diff --git a/src/views/modules/manage/profit-receiver.vue b/src/views/modules/manage/profit-receiver.vue new file mode 100644 index 0000000..00e0ea8 --- /dev/null +++ b/src/views/modules/manage/profit-receiver.vue @@ -0,0 +1,246 @@ + + + + + diff --git a/src/views/modules/manage/profit-rule.vue b/src/views/modules/manage/profit-rule.vue new file mode 100644 index 0000000..6aa0d86 --- /dev/null +++ b/src/views/modules/manage/profit-rule.vue @@ -0,0 +1,407 @@ + + + + + diff --git a/src/views/modules/manage/profit-sharing.vue b/src/views/modules/manage/profit-sharing.vue new file mode 100644 index 0000000..bf2f433 --- /dev/null +++ b/src/views/modules/manage/profit-sharing.vue @@ -0,0 +1,305 @@ + + + + + diff --git a/src/views/modules/manage/refund.vue b/src/views/modules/manage/refund.vue new file mode 100644 index 0000000..dab5098 --- /dev/null +++ b/src/views/modules/manage/refund.vue @@ -0,0 +1,306 @@ + + + + + diff --git a/src/views/modules/manage/stats-overview.vue b/src/views/modules/manage/stats-overview.vue new file mode 100644 index 0000000..21adc8a --- /dev/null +++ b/src/views/modules/manage/stats-overview.vue @@ -0,0 +1,479 @@ + + + + + diff --git a/src/views/modules/manage/store.vue b/src/views/modules/manage/store.vue new file mode 100644 index 0000000..b71aa57 --- /dev/null +++ b/src/views/modules/manage/store.vue @@ -0,0 +1,260 @@ + + + + + diff --git a/src/views/modules/media/components/media-asset-add-or-update.vue b/src/views/modules/media/components/media-asset-add-or-update.vue new file mode 100755 index 0000000..2a39b88 --- /dev/null +++ b/src/views/modules/media/components/media-asset-add-or-update.vue @@ -0,0 +1,283 @@ + + + + + diff --git a/src/views/modules/media/components/media-asset-detail-dialog.vue b/src/views/modules/media/components/media-asset-detail-dialog.vue new file mode 100755 index 0000000..9aa9d35 --- /dev/null +++ b/src/views/modules/media/components/media-asset-detail-dialog.vue @@ -0,0 +1,337 @@ + + + + + + + diff --git a/src/views/modules/media/components/media-rank-dialog.vue b/src/views/modules/media/components/media-rank-dialog.vue new file mode 100755 index 0000000..297c84a --- /dev/null +++ b/src/views/modules/media/components/media-rank-dialog.vue @@ -0,0 +1,62 @@ + + + + + + + diff --git a/src/views/modules/media/components/rank-board-panel.vue b/src/views/modules/media/components/rank-board-panel.vue new file mode 100755 index 0000000..a2745c4 --- /dev/null +++ b/src/views/modules/media/components/rank-board-panel.vue @@ -0,0 +1,441 @@ + + + + + diff --git a/src/views/modules/media/media-asset.vue b/src/views/modules/media/media-asset.vue new file mode 100755 index 0000000..23aca1b --- /dev/null +++ b/src/views/modules/media/media-asset.vue @@ -0,0 +1,201 @@ + + + + + diff --git a/src/views/modules/media/rank-board.vue b/src/views/modules/media/rank-board.vue new file mode 100755 index 0000000..8c825fc --- /dev/null +++ b/src/views/modules/media/rank-board.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/src/views/modules/org/components/org-add-or-update.data.ts b/src/views/modules/org/components/org-add-or-update.data.ts new file mode 100755 index 0000000..60c5063 --- /dev/null +++ b/src/views/modules/org/components/org-add-or-update.data.ts @@ -0,0 +1,120 @@ +/** 组织类型 */ +export type OrgType = 'PLATFORM' | 'CHANNEL' | 'SERVICE_PROVIDER' | 'STORE' + +/** 组织状态 */ +export type OrgStatus = 'ACTIVE' | 'DISABLED' + +/** 代理服务商扩展信息(由渠道等服务商侧维护) */ +export interface ServiceProviderProfile { + /** 联系电话(仅限手机或带区号的固话) */ + contactPhone: string + /** 服务商(名称或对接说明) */ + servicePartner: string + /** 微信二维码图片 URL */ + wechatQrImageUrl: string +} + +/** 门店档案 */ +export interface StoreProfile { + storeName: string + legalPerson: string + licenseNo: string + licenseImageUrl: string + region: string + address: string + phone: string + remark: string +} + +/** 组织表单数据 */ +export interface OrgDataForm { + id: number + parentId: string | number | null + parentName: string + name: string + type: OrgType | string + orderNo: number + canHoldInventory: boolean + activationPrefix: string + /** 代理服务商:开拓人员(选填) */ + developmentStaff: string + /** 代理服务商:联系方式与微信二维码 */ + serviceProviderProfile: ServiceProviderProfile + status: OrgStatus | string + loginMobile: string + loginPassword: string + confirmPassword: string + storeProfile: StoreProfile +} + +/** 组织树节点 */ +export interface OrgTreeNode { + id: string | number + name: string + type: string + parentId?: string | number + children?: OrgTreeNode[] + [key: string]: unknown +} + +/** 组织信息响应 */ +export interface OrgInfoResponse { + code?: number + org?: OrgInfo + data?: OrgInfo +} + +/** 组织信息 */ +export interface OrgInfo { + id?: string | number + parentId?: string | number + name?: string + type?: string + orderNo?: number + activationPrefix?: string + developmentStaff?: string + canHoldInventory?: boolean | number | string + status?: string + loginMobile?: string + mobile?: string + storeProfile?: StoreProfileData + /** 代理服务商字段:接口层平铺字段 */ + contactPhone?: string + servicePartner?: string + wechatQrImageUrl?: string + /** 兼容旧接口:曾与 storeProfile 同级的嵌套包 */ + serviceProviderProfile?: ServiceProviderProfileData +} + +/** 门店档案数据 */ +export interface StoreProfileData { + storeName?: string + legalPerson?: string + licenseNo?: string + licenseImageUrl?: string + region?: string + address?: string + phone?: string + remark?: string +} + +/** 代理服务商扩展(接口载荷) */ +export interface ServiceProviderProfileData { + contactPhone?: string + /** 旧字段兼容:历史数据仍为 contactInfo */ + contactInfo?: string + servicePartner?: string + wechatQrImageUrl?: string +} + +/** 省市区数据 */ +export interface RegionData { + value: string + label: string + children?: RegionData[] +} + +/** 初始化选项 */ +export interface InitOptions { + typeOnly?: string +} diff --git a/src/views/modules/org/components/org-add-or-update.vue b/src/views/modules/org/components/org-add-or-update.vue new file mode 100755 index 0000000..4d802ee --- /dev/null +++ b/src/views/modules/org/components/org-add-or-update.vue @@ -0,0 +1,1019 @@ + + + + + + + + diff --git a/src/views/modules/org/components/org-allocate-card-dialog.data.ts b/src/views/modules/org/components/org-allocate-card-dialog.data.ts new file mode 100755 index 0000000..d00c9e2 --- /dev/null +++ b/src/views/modules/org/components/org-allocate-card-dialog.data.ts @@ -0,0 +1,31 @@ +/** 表单数据 */ +export interface FormData { + allocateParentOrgId: string | number | null + toChannelOrgId: string | number | null + cardType: string + count: number +} + +/** 当前卡统计 */ +export interface CurrentCardStats { + cardType: string + cardTypeName?: string + totalCount: number + usedCount: number + availableCount: number +} + +/** 卡统计响应 */ +export interface CardStatsResponse { + code?: number + data?: { + current?: { + cardType: string + totalCount?: number + usedCount?: number + availableCount?: number + } + children?: CurrentCardStats[] + } + msg?: string +} diff --git a/src/views/modules/org/components/org-allocate-card-dialog.vue b/src/views/modules/org/components/org-allocate-card-dialog.vue new file mode 100755 index 0000000..0155059 --- /dev/null +++ b/src/views/modules/org/components/org-allocate-card-dialog.vue @@ -0,0 +1,455 @@ + + + diff --git a/src/views/modules/org/components/org-version-dialog.data.ts b/src/views/modules/org/components/org-version-dialog.data.ts new file mode 100755 index 0000000..ef24069 --- /dev/null +++ b/src/views/modules/org/components/org-version-dialog.data.ts @@ -0,0 +1,118 @@ +/** 在组织树中查找从根到目标节点的 id 路径 */ +export function findPathIdsInTree ( + nodes: T[] | undefined, + targetId: string | number, + path: Array = [] +): Array | null { + if (!nodes?.length) return null + const sid = String(targetId) + for (const n of nodes) { + const next = [...path, n.id] + if (String(n.id) === sid) return next + const sub = findPathIdsInTree(n.children, targetId, next) + if (sub) return sub + } + return null +} + +/** 将 id 路径拼成 mpath(如 1/6/23) */ +export function buildMpathFromPathIds (pathIds: Array | null | undefined): string { + if (!pathIds?.length) return '' + return pathIds.map(String).join('/') +} + +/** 解析 mpath 第二级(如 "1/6/23" → "6") */ +export function parseMpathSecondLevel (mPath: string | null | undefined): string | null { + if (!mPath || typeof mPath !== 'string') return null + const parts = mPath.split('/').filter(Boolean) + if (parts.length < 2) return null + return parts[1] +} + +/** mpath 第二级为 2 或 6 时的 APK 文件名格式提示 */ +export interface ApkFileNameFormatHint { + keyPrefix: string + touchPrefix: string +} + +export function getApkFileNameFormatHint (secondLevel: string | null): ApkFileNameFormatHint | null { + if (secondLevel === '6') { + return { + keyPrefix: 'ruigeerRemoteRelease', + touchPrefix: 'ruigeerTouchRelease' + } + } + if (secondLevel === '2') { + return { + keyPrefix: 'aishiRemoteRelease', + touchPrefix: 'aishiTouchRelease' + } + } + return null +} + +/** 包名是否包含应匹配的前缀(不区分大小写) */ +export function apkFileNameHasExpectedPrefix (fileName: string, prefix: string): boolean { + if (!prefix) return true + if (!fileName) return false + return fileName.toLowerCase().includes(prefix.toLowerCase()) +} + +/** 在包名中高亮应匹配的字符片段 */ +export interface ApkFileNameSegment { + text: string + matched: boolean +} + +export function splitApkFileNameByPrefix (fileName: string, prefix: string): ApkFileNameSegment[] { + if (!fileName) return [{ text: '-', matched: false }] + if (!prefix) return [{ text: fileName, matched: false }] + const idx = fileName.toLowerCase().indexOf(prefix.toLowerCase()) + if (idx === -1) return [{ text: fileName, matched: false }] + const segments: ApkFileNameSegment[] = [] + if (idx > 0) segments.push({ text: fileName.slice(0, idx), matched: false }) + segments.push({ text: fileName.slice(idx, idx + prefix.length), matched: true }) + if (idx + prefix.length < fileName.length) { + segments.push({ text: fileName.slice(idx + prefix.length), matched: false }) + } + return segments +} + +/** 版本表单 */ +export interface VersionForm { + orgId: string | number | null + orgName: string + verCode: string + verName: string + touchUrl: string + keyUrl: string + compulsory: boolean +} + +/** 版本信息响应 */ +export interface VersionInfoResponse { + code?: number + data?: { + verCode?: string + verName?: string + touchUrl?: string + keyUrl?: string + compulsory?: boolean | string + } +} + +/** 上传接口统一响应(外层 code/msg/data) */ +export interface UploadResponse { + code?: number + msg?: string + data?: string | { + url?: string + path?: string + storagePath?: string + storage_path?: string + } + url?: string + path?: string + storagePath?: string + storage_path?: string +} diff --git a/src/views/modules/org/components/org-version-dialog.vue b/src/views/modules/org/components/org-version-dialog.vue new file mode 100755 index 0000000..e7caab9 --- /dev/null +++ b/src/views/modules/org/components/org-version-dialog.vue @@ -0,0 +1,726 @@ + + + + + + diff --git a/src/views/modules/org/components/shop-allocate-dialog.vue b/src/views/modules/org/components/shop-allocate-dialog.vue new file mode 100755 index 0000000..023088e --- /dev/null +++ b/src/views/modules/org/components/shop-allocate-dialog.vue @@ -0,0 +1,177 @@ + + + diff --git a/src/views/modules/org/components/shop-card-stats.data.ts b/src/views/modules/org/components/shop-card-stats.data.ts new file mode 100755 index 0000000..a0ca4d7 --- /dev/null +++ b/src/views/modules/org/components/shop-card-stats.data.ts @@ -0,0 +1,15 @@ +/** 总统计数据 */ +export interface TotalStats { + allocatableCount: number + activatedCount: number + pendingActivationCount: number +} + +/** 按类型统计 */ +export interface ByTypeStats { + cardType: string + cardTypeName: string + allocatableCount: number + activatedCount: number + pendingActivationCount: number +} diff --git a/src/views/modules/org/components/shop-card-stats.vue b/src/views/modules/org/components/shop-card-stats.vue new file mode 100755 index 0000000..ac0703e --- /dev/null +++ b/src/views/modules/org/components/shop-card-stats.vue @@ -0,0 +1,426 @@ + + + + + diff --git a/src/views/modules/org/components/shop-cards-dialog.data.ts b/src/views/modules/org/components/shop-cards-dialog.data.ts new file mode 100755 index 0000000..620434a --- /dev/null +++ b/src/views/modules/org/components/shop-cards-dialog.data.ts @@ -0,0 +1,25 @@ +/** 卡查询表单 */ +export interface CardsForm { + cardNo: string + cardType: string + inventoryStatus: string + usageStatus: string +} + +/** 卡数据 */ +export interface CardItem { + id: string | number + cardNo?: string + cardType?: string + usageStatus?: string + expireAt?: string +} + +/** 卡列表响应 */ +export interface CardsResponse { + code?: number + page?: { + list?: CardItem[] + totalCount?: number + } +} diff --git a/src/views/modules/org/components/shop-cards-dialog.vue b/src/views/modules/org/components/shop-cards-dialog.vue new file mode 100755 index 0000000..d1cd199 --- /dev/null +++ b/src/views/modules/org/components/shop-cards-dialog.vue @@ -0,0 +1,200 @@ + + + + + diff --git a/src/views/modules/org/components/shop-channel-tree.data.ts b/src/views/modules/org/components/shop-channel-tree.data.ts new file mode 100755 index 0000000..cb588b7 --- /dev/null +++ b/src/views/modules/org/components/shop-channel-tree.data.ts @@ -0,0 +1,8 @@ +/** 渠道代理商树节点 */ +export interface ChannelAgentNode { + id: string | number + name: string + type: string + disabled?: boolean + children?: ChannelAgentNode[] +} diff --git a/src/views/modules/org/components/shop-channel-tree.vue b/src/views/modules/org/components/shop-channel-tree.vue new file mode 100755 index 0000000..8b6c1c6 --- /dev/null +++ b/src/views/modules/org/components/shop-channel-tree.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/src/views/modules/org/components/shop-max-device-dialog.data.ts b/src/views/modules/org/components/shop-max-device-dialog.data.ts new file mode 100755 index 0000000..7a09721 --- /dev/null +++ b/src/views/modules/org/components/shop-max-device-dialog.data.ts @@ -0,0 +1,19 @@ +/** 激活码项 */ +export interface ActivationCodeItem { + id: string | number + code?: string + cardType?: string + maxDeviceCount?: number +} + +/** 表单数据 */ +export interface FormData { + cardType: string + maxDeviceCount: number +} + +/** 激活码结果 */ +export interface ActivationCodeResult { + list: ActivationCodeItem[] + contractId?: string | number | null +} diff --git a/src/views/modules/org/components/shop-max-device-dialog.vue b/src/views/modules/org/components/shop-max-device-dialog.vue new file mode 100755 index 0000000..9dc7f7a --- /dev/null +++ b/src/views/modules/org/components/shop-max-device-dialog.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/src/views/modules/org/components/shop-regenerate-code-dialog.data.ts b/src/views/modules/org/components/shop-regenerate-code-dialog.data.ts new file mode 100755 index 0000000..81e8439 --- /dev/null +++ b/src/views/modules/org/components/shop-regenerate-code-dialog.data.ts @@ -0,0 +1,16 @@ +/** 激活码项 */ +export interface ActivationCodeItem { + id: string | number + code?: string + cardType?: string +} + +/** 激活码响应 */ +export interface ActivationCodeResponse { + code?: number + activationCode?: string + data?: { + activationCode?: string + } + msg?: string +} diff --git a/src/views/modules/org/components/shop-regenerate-code-dialog.vue b/src/views/modules/org/components/shop-regenerate-code-dialog.vue new file mode 100755 index 0000000..b4f3834 --- /dev/null +++ b/src/views/modules/org/components/shop-regenerate-code-dialog.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/src/views/modules/org/components/shop-store-list.data.ts b/src/views/modules/org/components/shop-store-list.data.ts new file mode 100755 index 0000000..be2d225 --- /dev/null +++ b/src/views/modules/org/components/shop-store-list.data.ts @@ -0,0 +1,49 @@ +/** 门店查询表单 */ +export interface DataForm { + name: string + activationCode: string + status: string +} + +/** 卡类型统计 */ +export interface CardStatsByType { + cardType: string + totalCount?: number + usedCount?: number +} + +/** 门店档案 */ +export interface StoreProfile { + storeName?: string + region?: string + address?: string + phone?: string +} + +/** 门店行数据 */ +export interface ShopRow { + id: string | number + name?: string + orgId?: string | number + status?: string + cardStatsByType?: CardStatsByType[] + storeProfile?: StoreProfile + deviceCount?: number + boundDeviceCount?: number + terminalCount?: number + storeCards?: number | unknown[] + activationCodeGroup?: string + yearActivationCode?: string + quarterActivationCode?: string + monthActivationCode?: string + weekActivationCode?: string + otherActivationCode?: string + rootChannelActivationPrefix?: string + channelName?: string + primaryAgentName?: string + secondaryAgentName?: string + region?: string + address?: string + phone?: string + [key: string]: unknown +} diff --git a/src/views/modules/org/components/shop-store-list.vue b/src/views/modules/org/components/shop-store-list.vue new file mode 100755 index 0000000..3319d75 --- /dev/null +++ b/src/views/modules/org/components/shop-store-list.vue @@ -0,0 +1,408 @@ + + + + + diff --git a/src/views/modules/org/org.data.ts b/src/views/modules/org/org.data.ts new file mode 100755 index 0000000..bdba64b --- /dev/null +++ b/src/views/modules/org/org.data.ts @@ -0,0 +1,45 @@ +/** 组织类型 */ +export type OrgType = 'PLATFORM' | 'CHANNEL' | 'SERVICE_PROVIDER' | 'STORE' + +/** 组织状态 */ +export type OrgStatus = 'ACTIVE' | 'DISABLED' + +/** 查询表单数据 */ +export interface DataForm { + name: string + type: string + status: string +} + +/** 回退卡表单 */ +export interface RollbackForm { + cardType: string + count: number +} + +/** 组织树节点 */ +export interface OrgNode { + id: string | number + name: string + type: OrgType | string + orgCode?: string + code?: string + orderNo?: number + status: OrgStatus | string + createdAt?: string + parentId?: string | number + children?: OrgNode[] + [key: string]: unknown +} + +/** 过滤选项 */ +export interface FilterOptions { + name: string + type: string + status: string +} + +/** AddOrUpdate 组件实例方法 */ +export interface AddOrUpdateInstance { + init: (id?: string | number | null, parentId?: string | number | null) => void +} diff --git a/src/views/modules/org/org.vue b/src/views/modules/org/org.vue new file mode 100755 index 0000000..0386f3a --- /dev/null +++ b/src/views/modules/org/org.vue @@ -0,0 +1,457 @@ + + + + + diff --git a/src/views/modules/org/shop.data.ts b/src/views/modules/org/shop.data.ts new file mode 100755 index 0000000..00efea2 --- /dev/null +++ b/src/views/modules/org/shop.data.ts @@ -0,0 +1,106 @@ +/** 门店查询表单 */ +export interface ShopDataForm { + name: string + activationCode: string + status: string +} + +/** 门店数据 */ +export interface ShopRow { + id: string | number + name?: string + orgId?: string | number + code?: string + orgCode?: string + region?: string + address?: string + phone?: string + status?: string + storeCards?: number | unknown[] + cardStatsByType?: CardStatsByType[] + storeProfile?: StoreProfile + deviceCount?: number + boundDeviceCount?: number + terminalCount?: number + activationCodeGroup?: string + yearActivationCode?: string + quarterActivationCode?: string + monthActivationCode?: string + weekActivationCode?: string + otherActivationCode?: string + rootChannelActivationPrefix?: string + channelName?: string + primaryAgentName?: string + secondaryAgentName?: string + [key: string]: unknown +} + +/** 门店档案 */ +export interface StoreProfile { + storeName?: string + legalPerson?: string + licenseNo?: string + licenseImageUrl?: string + region?: string + address?: string + phone?: string + remark?: string +} + +/** 卡类型统计 */ +export interface CardStatsByType { + cardType: string + cardTypeName?: string + totalCount?: number + usedCount?: number +} + +/** 代理商回退表单 */ +export interface AgentRollbackForm { + cardType: string + count: number +} + +/** 组织树节点 */ +export interface OrgTreeNode { + id: string | number + name: string + type: string + children?: OrgTreeNode[] + [key: string]: unknown +} + +/** 卡统计数据 */ +export interface CardStats { + allocatableCount: number + activatedCount: number + pendingActivationCount: number +} + +/** 按类型卡统计 */ +export interface CardStatsByTypeItem { + cardType: string + cardTypeName: string + allocatableCount: number + activatedCount: number + pendingActivationCount: number +} + +/** 激活码结果 */ +export interface ActivationCodeResult { + list: ActivationCodeItem[] + contractId?: string | number | null +} + +/** 激活码项 */ +export interface ActivationCodeItem { + id: string | number + code?: string + cardType?: string + maxDeviceCount?: number +} + +/** AddOrUpdate 组件实例 */ +export interface AddOrUpdateInstance { + init: (id?: string | number | null, parentId?: string | number | null, options?: { typeOnly?: string }) => void +} diff --git a/src/views/modules/org/shop.vue b/src/views/modules/org/shop.vue new file mode 100755 index 0000000..de91545 --- /dev/null +++ b/src/views/modules/org/shop.vue @@ -0,0 +1,666 @@ + + + + + diff --git a/src/views/modules/org/utils/extract-channel-agent-tree.ts b/src/views/modules/org/utils/extract-channel-agent-tree.ts new file mode 100755 index 0000000..8cbd836 --- /dev/null +++ b/src/views/modules/org/utils/extract-channel-agent-tree.ts @@ -0,0 +1,69 @@ +/** 组织树节点 */ +export interface OrgTreeNode { + id: string | number + name: string + type: string + children?: OrgTreeNode[] + [key: string]: unknown +} + +/** 渠道代理商树节点 */ +export interface ChannelAgentNode { + id: string | number + name: string + type: string + disabled?: boolean + children?: ChannelAgentNode[] +} + +/** + * 与 shop-channel-tree 中 el-tree 的 :data 一致:从 org 树提取「渠道 → 代理商」结构 + * @param nodes - 组织树节点数组 + * @returns 渠道-代理商树 + */ +export function extractChannelAgentTree(nodes: OrgTreeNode[] | null | undefined): ChannelAgentNode[] { + if (!nodes || !Array.isArray(nodes)) return [] + + function mapAgentNode(node: OrgTreeNode): ChannelAgentNode { + const children = (node.children || []) + .filter(c => c.type === 'SERVICE_PROVIDER') + .map(mapAgentNode) + return { + id: node.id, + name: node.name, + type: node.type, + children: children.length > 0 ? children : undefined + } + } + + const result: ChannelAgentNode[] = [] + for (const node of nodes) { + if (node.type === 'PLATFORM') { + const children = extractChannelAgentTree(node.children || []) + if (children.length === 0) continue + result.push({ + id: node.id, + name: node.name, + type: node.type, + disabled: false, + children: children.length > 0 ? children : undefined + }) + } else if (node.type === 'CHANNEL') { + const children = (node.children || []) + .filter(c => c.type === 'SERVICE_PROVIDER') + .map(mapAgentNode) + result.push({ + id: node.id, + name: node.name, + type: node.type, + children: children.length > 0 ? children : undefined + }) + } else if (node.type === 'SERVICE_PROVIDER') { + // 仅有代理商、无渠道时,根或平台子节点必须是 SERVICE_PROVIDER,否则原逻辑只递归 children 会得到空树 + result.push(mapAgentNode(node)) + } else { + result.push(...extractChannelAgentTree(node.children || [])) + } + } + return result +} diff --git a/src/views/modules/sys/api-jst-call-log.vue b/src/views/modules/sys/api-jst-call-log.vue new file mode 100755 index 0000000..775e506 --- /dev/null +++ b/src/views/modules/sys/api-jst-call-log.vue @@ -0,0 +1,219 @@ + + + diff --git a/src/views/modules/sys/audit-log.vue b/src/views/modules/sys/audit-log.vue new file mode 100755 index 0000000..c5451ca --- /dev/null +++ b/src/views/modules/sys/audit-log.vue @@ -0,0 +1,211 @@ + + + diff --git a/src/views/modules/sys/components/config-add-or-update.vue b/src/views/modules/sys/components/config-add-or-update.vue new file mode 100755 index 0000000..463c1fa --- /dev/null +++ b/src/views/modules/sys/components/config-add-or-update.vue @@ -0,0 +1,108 @@ + + + diff --git a/src/views/modules/sys/components/menu-add-or-update.vue b/src/views/modules/sys/components/menu-add-or-update.vue new file mode 100755 index 0000000..3a31176 --- /dev/null +++ b/src/views/modules/sys/components/menu-add-or-update.vue @@ -0,0 +1,315 @@ + + + + + diff --git a/src/views/modules/sys/components/role-add-or-update.vue b/src/views/modules/sys/components/role-add-or-update.vue new file mode 100755 index 0000000..0ea61f0 --- /dev/null +++ b/src/views/modules/sys/components/role-add-or-update.vue @@ -0,0 +1,158 @@ + + + diff --git a/src/views/modules/sys/components/user-add-or-update.vue b/src/views/modules/sys/components/user-add-or-update.vue new file mode 100755 index 0000000..b3537b5 --- /dev/null +++ b/src/views/modules/sys/components/user-add-or-update.vue @@ -0,0 +1,332 @@ + + + diff --git a/src/views/modules/sys/config.vue b/src/views/modules/sys/config.vue new file mode 100755 index 0000000..d722651 --- /dev/null +++ b/src/views/modules/sys/config.vue @@ -0,0 +1,168 @@ + + + diff --git a/src/views/modules/sys/log.vue b/src/views/modules/sys/log.vue new file mode 100755 index 0000000..5890c95 --- /dev/null +++ b/src/views/modules/sys/log.vue @@ -0,0 +1,138 @@ + + + diff --git a/src/views/modules/sys/menu.vue b/src/views/modules/sys/menu.vue new file mode 100755 index 0000000..ab2b91a --- /dev/null +++ b/src/views/modules/sys/menu.vue @@ -0,0 +1,165 @@ + + + diff --git a/src/views/modules/sys/role.vue b/src/views/modules/sys/role.vue new file mode 100755 index 0000000..c374e49 --- /dev/null +++ b/src/views/modules/sys/role.vue @@ -0,0 +1,194 @@ + + + diff --git a/src/views/modules/sys/user.vue b/src/views/modules/sys/user.vue new file mode 100755 index 0000000..46682d1 --- /dev/null +++ b/src/views/modules/sys/user.vue @@ -0,0 +1,185 @@ + + + diff --git a/static/img/favicon.jpg b/static/img/favicon.jpg new file mode 100755 index 0000000..d734920 Binary files /dev/null and b/static/img/favicon.jpg differ diff --git a/tsconfig.json b/tsconfig.json new file mode 100755 index 0000000..9910d6c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "baseUrl": ".", + "ignoreDeprecations": "6.0", + "paths": { + "@/*": ["./src/*"] + }, + "types": ["node"] + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100755 index 0000000..5c523f4 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true + }, + "include": ["vite.config.*", "env.d.ts"] +} diff --git a/uno.config.ts b/uno.config.ts new file mode 100755 index 0000000..3d32a74 --- /dev/null +++ b/uno.config.ts @@ -0,0 +1,8 @@ +import { defineConfig, presetWind3 } from 'unocss' + +export default defineConfig({ + presets: [presetWind3()], + content: { + filesystem: ['index.html', 'src/**/*.{vue,js,ts,jsx,tsx}'], + }, +}) diff --git a/vite.config.ts b/vite.config.ts new file mode 100755 index 0000000..d58995e --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,145 @@ +import { defineConfig, loadEnv } from 'vite' +import AutoImport from 'unplugin-auto-import/vite' +import Components from 'unplugin-vue-components/vite' +import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' +import vue from '@vitejs/plugin-vue' +import path from 'path' +import UnoCSS from '@unocss/vite' + +export default defineConfig(({ mode }) => { + const envDir = process.cwd() + const env = loadEnv(mode, envDir, '') + const devPort = Number(env.VITE_DEV_PORT) || 3000 + const proxyTarget = (env.VITE_APP_PROXY_TARGET || 'http://172.16.100.134:8083').trim() + const manageProxyTarget = (env.VITE_MANAGE_PROXY_TARGET || 'http://127.0.0.1:8084').trim() + return { + base: './', + plugins: [ + vue({ + vapor: true + }), + AutoImport({ + resolvers: [ElementPlusResolver({ importStyle: 'css' })], + }), + Components({ + resolvers: [ElementPlusResolver({ importStyle: 'css' })], + }), + UnoCSS() + ], + envPrefix: ['VITE_'], + server: { + host: '0.0.0.0', + port: devPort, + proxy: { + // /api/manage/* → manage 后端(端口 8084),须在 /api 之前匹配 + '/api/manage': { + target: manageProxyTarget, + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, ''), + configure: (proxy) => { + proxy.on('proxyReq', (proxyReq) => { + proxyReq.removeHeader('Cookie') + }) + proxy.on('proxyRes', (proxyRes) => { + delete proxyRes.headers['set-cookie'] + }) + } + }, + // /api/sys/* → manage 后端(端口 8084),账号体系已迁移 + '/api/sys': { + target: manageProxyTarget, + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, ''), + configure: (proxy) => { + proxy.on('proxyReq', (proxyReq) => { + proxyReq.removeHeader('Cookie') + }) + proxy.on('proxyRes', (proxyRes) => { + delete proxyRes.headers['set-cookie'] + }) + } + }, + // /api/captcha.jpg → manage 后端(端口 8084),验证码 + '/api/captcha.jpg': { + target: manageProxyTarget, + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, ''), + configure: (proxy) => { + proxy.on('proxyReq', (proxyReq) => { + proxyReq.removeHeader('Cookie') + }) + proxy.on('proxyRes', (proxyRes) => { + delete proxyRes.headers['set-cookie'] + }) + } + }, + // /api/openapi/* → manage 后端(端口 8084),天卡池/订单/权益 + '/api/openapi': { + target: manageProxyTarget, + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, ''), + configure: (proxy) => { + proxy.on('proxyReq', (proxyReq) => { + proxyReq.removeHeader('Cookie') + }) + proxy.on('proxyRes', (proxyRes) => { + delete proxyRes.headers['set-cookie'] + }) + } + }, + // /api/* → 原 sys 后端(端口 8083) + // 所有 /api 接口都走代理,baseApi=/api 时全部请求同源转发 + // 仅使用 Authorization 头认证,Cookie 不携带/不接收敏感信息 + '/api': { + target: proxyTarget, + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, ''), + configure: (proxy) => { + proxy.on('proxyReq', (proxyReq) => { + proxyReq.removeHeader('Cookie') + }) + proxy.on('proxyRes', (proxyRes) => { + delete proxyRes.headers['set-cookie'] + }) + } + } + } + }, + resolve: { + alias: { + '@': path.resolve(__dirname, 'src'), + '@assets': path.resolve(__dirname, 'src/assets'), + 'components': path.resolve(__dirname, 'src/components') + } + }, + css: { + preprocessorOptions: { + scss: { api: 'modern-compiler' }, + } + }, + build: { + target: 'baseline-widely-available', + minify: 'oxc', + cssCodeSplit: true, + rolldownOptions: { + treeshake: true, + output: { + manualChunks: (id) => { + if (id.includes('node_modules')) { + if (id.includes('element-plus') && !id.includes('icons-vue')) return 'element-plus' + if (id.includes('@element-plus/icons-vue')) return 'element-plus-icons' + if (id.includes('vue') || id.includes('vue-router') || id.includes('pinia')) return 'vue-vendor' + if (id.includes('xlsx')) return 'xlsx' + if (id.includes('element-china-area-data')) return 'region-data' + return 'vendor' + } + }, + chunkFileNames: 'js/[name]-[hash].js', + entryFileNames: 'js/[name]-[hash].js', + assetFileNames: '[ext]/[name]-[hash].[ext]' + } + }, + chunkSizeWarningLimit: 600 + } + } +})