From 43a617e5da46b1b35b9071efada407a58d281cc5 Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 16 Jun 2026 15:12:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=91=98=E5=B7=A5=E7=AB=AFh5=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 10 + .env.production | 10 + .env.test | 10 + .gitignore | 27 + H5页面规划.md | 404 +++++++++++ README.md | 88 +++ env.d.ts | 18 + index.html | 13 + package.json | 35 + src/App.vue | 3 + src/api/auth.ts | 56 ++ src/api/events.ts | 19 + src/api/mock.ts | 295 ++++++++ src/api/orders.ts | 40 ++ src/api/request.ts | 36 + src/api/upload.ts | 20 + src/components/PageNav.vue | 28 + src/components/StatusTag.vue | 16 + src/main.ts | 16 + src/router/index.ts | 102 +++ src/stores/auth.ts | 109 +++ src/styles/main.css | 425 ++++++++++++ src/types/api.ts | 31 + src/types/event.ts | 32 + src/types/order.ts | 127 ++++ src/utils/constants.ts | 40 ++ src/utils/date.ts | 22 + src/utils/env.ts | 11 + src/utils/url.ts | 14 + src/views/events/EventCreateView.vue | 183 +++++ src/views/events/EventListView.vue | 171 +++++ src/views/home/HomeView.vue | 204 ++++++ src/views/layout/AppLayout.vue | 46 ++ src/views/login/LoginView.vue | 203 ++++++ src/views/mine/MineView.vue | 97 +++ src/views/orders/OrderDetailView.vue | 234 +++++++ src/views/orders/OrderListView.vue | 171 +++++ src/views/verify/VerifyConfirmView.vue | 198 ++++++ src/views/verify/VerifyResultView.vue | 101 +++ src/views/verify/VerifyView.vue | 99 +++ tsconfig.app.json | 13 + tsconfig.json | 11 + tsconfig.node.json | 12 + vite.config.ts | 46 ++ yarn.lock | 908 +++++++++++++++++++++++++ 45 files changed, 4754 insertions(+) create mode 100644 .env.example create mode 100644 .env.production create mode 100644 .env.test create mode 100644 .gitignore create mode 100644 H5页面规划.md create mode 100644 README.md create mode 100644 env.d.ts create mode 100644 index.html create mode 100644 package.json create mode 100644 src/App.vue create mode 100644 src/api/auth.ts create mode 100644 src/api/events.ts create mode 100644 src/api/mock.ts create mode 100644 src/api/orders.ts create mode 100644 src/api/request.ts create mode 100644 src/api/upload.ts create mode 100644 src/components/PageNav.vue create mode 100644 src/components/StatusTag.vue create mode 100644 src/main.ts create mode 100644 src/router/index.ts create mode 100644 src/stores/auth.ts create mode 100644 src/styles/main.css create mode 100644 src/types/api.ts create mode 100644 src/types/event.ts create mode 100644 src/types/order.ts create mode 100644 src/utils/constants.ts create mode 100644 src/utils/date.ts create mode 100644 src/utils/env.ts create mode 100644 src/utils/url.ts create mode 100644 src/views/events/EventCreateView.vue create mode 100644 src/views/events/EventListView.vue create mode 100644 src/views/home/HomeView.vue create mode 100644 src/views/layout/AppLayout.vue create mode 100644 src/views/login/LoginView.vue create mode 100644 src/views/mine/MineView.vue create mode 100644 src/views/orders/OrderDetailView.vue create mode 100644 src/views/orders/OrderListView.vue create mode 100644 src/views/verify/VerifyConfirmView.vue create mode 100644 src/views/verify/VerifyResultView.vue create mode 100644 src/views/verify/VerifyView.vue create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts create mode 100644 yarn.lock diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..cad86c9 --- /dev/null +++ b/.env.example @@ -0,0 +1,10 @@ +VITE_USE_MOCK=false +VITE_PROXY_TARGET=http://192.168.3.211:9999 +VITE_API_BASE_URL= +VITE_AUTH_BASE=/auth +VITE_ADMIN_BASE=/admin +VITE_STAFF_BASE=/hotelStaff +VITE_HOTEL_BIZ_BASE=/hotelBiz +VITE_CLIENT_ID=custom +VITE_CLIENT_SECRET= +VITE_CLIENT_CONFIG_ID= diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..94a593f --- /dev/null +++ b/.env.production @@ -0,0 +1,10 @@ +VITE_USE_MOCK=false +VITE_PROXY_TARGET= +VITE_API_BASE_URL=https://biz.nianxx.cn/ +VITE_AUTH_BASE=/auth +VITE_ADMIN_BASE=/admin +VITE_STAFF_BASE=/hotelStaff +VITE_HOTEL_BIZ_BASE=/hotelBiz +VITE_CLIENT_ID=custom +VITE_CLIENT_SECRET=custom +VITE_CLIENT_CONFIG_ID=6 diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..8dd73f3 --- /dev/null +++ b/.env.test @@ -0,0 +1,10 @@ +VITE_USE_MOCK=false +VITE_PROXY_TARGET= +VITE_API_BASE_URL=http://8.138.234.141/ingress +VITE_AUTH_BASE=/auth +VITE_ADMIN_BASE=/admin +VITE_STAFF_BASE=/hotelStaff +VITE_HOTEL_BIZ_BASE=/hotelBiz +VITE_CLIENT_ID=custom +VITE_CLIENT_SECRET=custom +VITE_CLIENT_CONFIG_ID=6 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bca4f22 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +*.local + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +unpackage +.hbuilderx +#.claude +#docs/* +#!docs/*.md diff --git a/H5页面规划.md b/H5页面规划.md new file mode 100644 index 0000000..f7e750f --- /dev/null +++ b/H5页面规划.md @@ -0,0 +1,404 @@ +# 酒店员工端 H5 页面规划 + +## 产品定位 + +面向酒店/商户员工的移动端工作台,核心解决三件事: + +- 员工通过手机号验证码登录。 +- 员工查看订单,并对可使用订单进行核销。 +- 员工发布和查看运营事件。 + +第一版优先保证业务闭环,不做复杂后台管理能力。 + +## 页面地图 + +```text +/login + 手机验证码登录 + +/ + /home + 工作台 + + /orders + 订单列表 + + /orders/:id + 订单详情 + └─ 进入核销确认 + + /verify + 核销入口 + + /verify/confirm + 核销确认 + + /verify/result + 核销结果 + + /events + 事件列表 + + /events/create + 发布事件 + + /mine + 我的 +``` + +## 底部导航 + +| Tab | 路由 | 说明 | +|---|---|---| +| 工作台 | `/home` | 展示关键数据和快捷入口 | +| 订单 | `/orders` | 查询订单、进入详情 | +| 核销 | `/verify` | 扫码或输入订单号核销 | +| 事件 | `/events` | 查看事件列表 | +| 我的 | `/mine` | 当前账号、接口模式、退出登录 | + +## 核心流程 + +### 登录流程 + +```text +输入手机号 +-> 获取验证码 +-> 输入验证码 +-> 调用 OAuth2 手机号登录 +-> 保存 access_token +-> 进入工作台 +``` + +接口: + +| 动作 | 接口 | +|---|---| +| 发送验证码 | `GET /admin/platformUser/sendMobileCode/{phone}` | +| 手机号登录 | `POST /auth/oauth2/token` | +| 登录后绑定并获取组织关系 | `POST /hotelStaff/organizationMember/bindUserInfoAndGetUserMemberInfoByPhone` | + +登录参数要点: + +- `grant_type=mobile` +- `mobile=手机号` +- `code=验证码` +- `scope=server` +- `clientConfigId` 需要和发送验证码时保持一致 + +### 订单核销流程 + +```text +订单列表 +-> 订单详情 +-> 点击立即核销 +-> 核销确认 +-> 调用核销接口 +-> 核销结果 +``` + +也支持: + +```text +核销入口 +-> 输入订单号 +-> 查询订单详情 +-> 核销确认 +-> 核销结果 +``` + +接口: + +| 页面/动作 | 接口 | +|---|---| +| 订单列表 | `POST /hotelStaff/order/commodityOrderList` | +| 订单详情 | `POST /hotelStaff/order/userOrderDetail` | +| 确认核销 | `POST /hotelStaff/order/writeOff` | + +当前后端核销能力以 `orderId` 为核心,暂未看到独立“核销码查询”接口。第一版扫码可先约定二维码内容为订单号;如果业务需要独立券码,后端建议补充“按核销码查询订单/商品”的接口。 + +### 事件流程 + +```text +事件列表 +-> 发布事件 +-> 填写事件信息 +-> 上传图片 +-> 发布 +-> 回到事件列表 +``` + +接口: + +| 页面/动作 | 接口 | +|---|---| +| 事件列表 | `POST /hotelStaff/event/eventList` | +| 创建事件 | `POST /hotelStaff/event/createEvent` | +| 图片上传 | `POST /hotelBiz/hotBizCommon/upload` | + +## 页面明细 + +### `/login` 手机验证码登录 + +目标:让员工用手机号进入系统。 + +展示内容: + +- 手机号输入框 +- 验证码输入框 +- 获取验证码按钮 +- 登录按钮 + +状态: + +- 手机号格式错误 +- 验证码倒计时 +- 登录中 +- 登录失败 + +### `/home` 工作台 + +目标:提供员工进入高频操作的首页。 + +展示内容: + +- 当前日期 +- 当前账号 +- 待使用订单数 +- 今日核销数 +- 生效事件数 +- 今日订单数 +- 快捷入口:扫码核销、订单列表、发布事件、事件列表 +- 近期订单 +- 近期事件 + +主要操作: + +- 去核销 +- 查看订单 +- 发布事件 +- 查看事件 + +### `/orders` 订单列表 + +目标:让员工快速查找订单。 + +展示内容: + +- 搜索框:订单号/手机号 +- 状态筛选:全部、待使用、待确认、退款中、已完成 +- 商品类型筛选:全部、酒店、门票、餐饮 +- 订单卡片:订单号、状态、商品名、联系人、手机号、金额、数量、时间 + +主要操作: + +- 搜索订单 +- 筛选状态 +- 进入订单详情 + +### `/orders/:id` 订单详情 + +目标:核对订单完整信息,并从详情发起核销。 + +展示内容: + +- 订单号 +- 订单状态 +- 商品图 +- 商品名称 +- 商品类型 +- 购买数量 +- 联系人信息 +- 支付信息 +- 使用/预约信息 +- 套餐内容 +- 核销记录 + +主要操作: + +- 待使用订单显示“立即核销” +- 点击后进入 `/verify/confirm` + +核销按钮显示条件: + +- `orderStatus === '2'`,即待使用 + +### `/verify` 核销入口 + +目标:提供独立核销入口。 + +展示内容: + +- 扫码核销入口 +- 手动输入订单号 + +主要操作: + +- 输入订单号查询订单 +- 进入核销确认 + +备注: + +- 当前扫码入口已预留。 +- 第一版先按订单号核销。 + +### `/verify/confirm` 核销确认 + +目标:防止员工误核销。 + +展示内容: + +- 订单号 +- 订单状态 +- 商品名称 +- 联系人 +- 核销套餐 +- 购买数量 +- 预约时间 +- 实付金额 + +主要操作: + +- 确认核销 +- 取消返回 + +状态: + +- 可核销 +- 当前订单不可核销 +- 核销提交中 +- 核销失败 + +### `/verify/result` 核销结果 + +目标:给员工明确反馈。 + +展示内容: + +- 成功/失败状态 +- 订单号 +- 核销内容 +- 操作时间 +- 失败原因 + +主要操作: + +- 继续核销 +- 查看订单 + +### `/events` 事件列表 + +目标:查看已发布事件。 + +展示内容: + +- 搜索框:实体名称 +- 状态筛选:全部、开启、关闭 +- 事件卡片:实体名称、事件描述、事件状态、显示状态、生效时间、发布人、是否弹窗提醒 + +主要操作: + +- 搜索事件 +- 筛选状态 +- 进入发布事件页 + +### `/events/create` 发布事件 + +目标:创建新的运营事件。 + +展示内容: + +- 实体名称 +- 事件描述 +- 图片上传 +- 发布时间 +- 生效开始时间 +- 生效结束时间 +- 弹窗提醒开关 + +主要操作: + +- 上传图片 +- 发布事件 + +校验: + +- 实体名称必填 +- 事件描述必填 +- 生效时间必填 + +### `/mine` 我的 + +目标:查看当前登录和接口配置状态。 + +展示内容: + +- 当前账号 +- 登录状态 +- 手机号绑定状态 +- 租户 +- 接口模式:Mock/真实接口 +- `clientId` +- `clientConfigId` +- 员工端接口前缀 + +主要操作: + +- 退出登录 + +## 订单状态 + +| 值 | 文案 | +|---|---| +| `0` | 待支付 | +| `1` | 待确认 | +| `2` | 待使用 | +| `3` | 已取消 | +| `4` | 退款中 | +| `5` | 已关闭 | +| `6` | 已完成 | + +## 商品类型 + +| 值 | 文案 | +|---|---| +| `0` | 酒店 | +| `1` | 门票 | +| `2` | 餐饮 | + +## 事件状态 + +| 值 | 文案 | +|---|---| +| `0` | 开启 | +| `1` | 关闭 | + +事件列表还会展示后端计算的 `showStatusDesc`: + +- 待生效 +- 生效中 +- 已过期 + +## 第一阶段 MVP + +必须包含: + +- 手机验证码登录 +- 工作台 +- 订单列表 +- 订单详情 +- 订单详情发起核销 +- 独立核销入口 +- 核销确认 +- 核销结果 +- 事件列表 +- 发布事件 +- 我的/退出登录 + +暂缓内容: + +- 独立核销码查询 +- 扫码真实调用微信/浏览器能力 +- 订单复杂高级筛选 +- 事件编辑/关闭/删除 +- 员工权限细分 +- 数据统计图表 diff --git a/README.md b/README.md new file mode 100644 index 0000000..b9fbbf8 --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +# 酒店员工端 H5 + +Vue 3 + Vite + TypeScript + Vant 的移动端员工工作台。当前包含 mock 数据,可直接预览完整流程。 + +## 启动 + +```bash +yarn -i +yarn dev +``` + +本地预览地址默认是 `http://127.0.0.1:5173/`。 + +本地开发环境后端网关: + +```bash +VITE_PROXY_TARGET=http://192.168.3.211:9999 +``` + +## 环境变量 + +复制 `.env.example` 后按实际网关配置调整: + +```bash +cp .env.example .env.local +``` + +关键配置: + +- `VITE_USE_MOCK=true`:使用前端 mock 数据。 +- `VITE_USE_MOCK=false`:调用真实后端接口。 +- `VITE_PROXY_TARGET=http://192.168.3.211:9999`:本地 Vite 代理到后端网关。 +- `VITE_API_BASE_URL`:打包后的接口网关地址。为空时使用当前站点同源地址。 +- `VITE_AUTH_BASE=/auth`:登录服务前缀。 +- `VITE_ADMIN_BASE=/admin`:用户与验证码服务前缀。 +- `VITE_STAFF_BASE=/hotelStaff`:员工端接口前缀。 +- `VITE_HOTEL_BIZ_BASE=/hotelBiz`:酒店业务通用接口前缀。 +- `VITE_CLIENT_ID`、`VITE_CLIENT_SECRET`、`VITE_CLIENT_CONFIG_ID`:短信登录所需客户端配置。 + +## 环境文件 + +| 文件 | 用途 | +|---|---| +| `.env.local` | 本地开发配置,不提交到仓库 | +| `.env.test` | 测试环境打包配置 | +| `.env.production` | 生产环境打包配置 | + +测试环境目前默认使用本地已确认网关: + +```bash +VITE_API_BASE_URL=http://192.168.3.211:9999 +``` + +生产环境如果 H5 和网关同域部署,`VITE_API_BASE_URL` 可以保持为空;如果不是同域部署,需要改成生产网关域名。 + +## 页面 + +- `/login`:手机号验证码登录。 +- `/home`:工作台。 +- `/orders`:订单列表。 +- `/orders/:id`:订单详情,可进入核销。 +- `/verify`:核销入口。 +- `/verify/confirm`:核销确认。 +- `/verify/result`:核销结果。 +- `/events`:事件列表。 +- `/events/create`:发布事件。 +- `/mine`:我的。 + +## 校验 + +```bash +yarn typecheck +yarn build:test +yarn build:prod +``` + +## 打包 + +```bash +# 测试环境 +yarn build:test + +# 生产环境 +yarn build:prod + +# 默认生产打包 +yarn build +``` diff --git a/env.d.ts b/env.d.ts new file mode 100644 index 0000000..64ad23a --- /dev/null +++ b/env.d.ts @@ -0,0 +1,18 @@ +/// + +interface ImportMetaEnv { + readonly VITE_USE_MOCK?: string + readonly VITE_PROXY_TARGET?: string + readonly VITE_API_BASE_URL?: string + readonly VITE_AUTH_BASE?: string + readonly VITE_ADMIN_BASE?: string + readonly VITE_STAFF_BASE?: string + readonly VITE_HOTEL_BIZ_BASE?: string + readonly VITE_CLIENT_ID?: string + readonly VITE_CLIENT_SECRET?: string + readonly VITE_CLIENT_CONFIG_ID?: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..bec013a --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + 酒店员工端 + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..1305d55 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "hotel-biz-h5", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite --host 0.0.0.0", + "dev:test": "vite --host 0.0.0.0 --mode test", + "build": "yarn build:prod", + "build:test": "vue-tsc -b && vite build --mode test", + "build:prod": "vue-tsc -b && vite build --mode production", + "preview": "vite preview --host 0.0.0.0", + "preview:test": "vite preview --host 0.0.0.0 --mode test", + "preview:prod": "vite preview --host 0.0.0.0 --mode production", + "typecheck": "vue-tsc -b" + }, + "dependencies": { + "@vitejs/plugin-vue": "^5.2.4", + "axios": "^1.10.0", + "dayjs": "^1.11.13", + "lucide-vue-next": "^0.468.0", + "pinia": "^2.3.1", + "vant": "^4.9.16", + "vue": "^3.5.13", + "vue-router": "^4.5.0" + }, + "devDependencies": { + "@types/node": "^22.13.1", + "@tsconfig/node22": "^22.0.0", + "@vue/tsconfig": "^0.7.0", + "typescript": "^5.7.3", + "vite": "^6.0.7", + "vue-tsc": "^2.2.0" + } +} diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..7c2aa3f --- /dev/null +++ b/src/App.vue @@ -0,0 +1,3 @@ + diff --git a/src/api/auth.ts b/src/api/auth.ts new file mode 100644 index 0000000..c4f247a --- /dev/null +++ b/src/api/auth.ts @@ -0,0 +1,56 @@ +import http from './request' +import { mockApi } from './mock' +import { env } from '@/utils/env' +import type { TokenResponse } from '@/types/api' +import { joinUrl } from '@/utils/url' + +export interface OrganizationMemberInfo { + memberId?: string + organizationId?: string + memberName?: string + userPhone?: string + memberRoleId?: string +} + +const basicAuth = () => { + const raw = `${env.clientId}:${env.clientSecret}` + return `Basic ${window.btoa(raw)}` +} + +export const sendMobileCode = async (phone: string) => { + if (env.useMock) return mockApi.sendMobileCode(phone) + return await http.get(joinUrl(env.adminBase, 'platformUser/sendMobileCode', phone), { + headers: { + clientId: env.clientId, + clientConfigId: env.clientConfigId + } + }) as unknown as boolean +} + +export const loginByMobile = async (phone: string, code: string): Promise => { + if (env.useMock) return mockApi.loginByMobile(phone) + + const form = new URLSearchParams() + form.set('grant_type', 'mobile') + form.set('mobile', phone) + form.set('code', code) + form.set('scope', 'server') + if (env.clientConfigId) { + form.set('clientConfigId', env.clientConfigId) + } + + return await http.post(joinUrl(env.authBase, 'oauth2/token'), form, { + headers: { + Authorization: basicAuth(), + 'Content-Type': 'application/x-www-form-urlencoded' + } + }) as unknown as TokenResponse +} + +export const bindUserInfoAndGetUserMemberInfoByPhone = async (phone: string) => { + if (env.useMock) return mockApi.bindOrganization(phone) + return await http.post( + joinUrl(env.staffBase, 'organizationMember/bindUserInfoAndGetUserMemberInfoByPhone'), + { userPhone: phone } + ) as unknown as OrganizationMemberInfo +} diff --git a/src/api/events.ts b/src/api/events.ts new file mode 100644 index 0000000..612b0e3 --- /dev/null +++ b/src/api/events.ts @@ -0,0 +1,19 @@ +import http from './request' +import { mockApi } from './mock' +import { env } from '@/utils/env' +import type { PageResponse } from '@/types/api' +import type { CreateEventPayload, EventData, EventSearch } from '@/types/event' +import { joinUrl } from '@/utils/url' + +export const fetchEventList = async (query: EventSearch): Promise> => { + if (env.useMock) return mockApi.eventList(query) + return await http.post>( + joinUrl(env.staffBase, 'event/eventList'), + query + ) as unknown as PageResponse +} + +export const createEvent = async (payload: CreateEventPayload) => { + if (env.useMock) return mockApi.createEvent(payload) + return http.post(joinUrl(env.staffBase, 'event/createEvent'), payload) +} diff --git a/src/api/mock.ts b/src/api/mock.ts new file mode 100644 index 0000000..eb2e772 --- /dev/null +++ b/src/api/mock.ts @@ -0,0 +1,295 @@ +import dayjs from 'dayjs' +import type { PageResponse, TokenResponse } from '@/types/api' +import type { + CommodityOrder, + CommodityOrderSearch, + UserOrderDetail, + WriteOffPayload, + WriteOffResult +} from '@/types/order' +import type { CreateEventPayload, EventData, EventSearch } from '@/types/event' +import { addDays, formatDateTime, today } from '@/utils/date' + +const wait = (ms = 260) => new Promise((resolve) => window.setTimeout(resolve, ms)) + +const coverImages = [ + 'https://images.unsplash.com/photo-1566073771259-6a8506099945?auto=format&fit=crop&w=900&q=80', + 'https://images.unsplash.com/photo-1542314831-068cd1dbfeeb?auto=format&fit=crop&w=900&q=80', + 'https://images.unsplash.com/photo-1551882547-ff40c63fe5fa?auto=format&fit=crop&w=900&q=80' +] + +let orders: CommodityOrder[] = [ + { + id: '202606160001', + orderAmt: '699.00', + visitorName: '林清', + contactPhone: '13800000001', + checkInData: today(), + checkOutData: addDays(1), + orderStatus: '2', + payStatus: '1', + payAmt: '659.00', + discountAmt: '40.00', + payTime: formatDateTime(dayjs().subtract(2, 'hour').toDate()), + orderType: '0', + createTime: formatDateTime(dayjs().subtract(3, 'hour').toDate()), + roomId: '1208', + commodityName: '湖景大床房含双早', + commodityCoverPhoto: coverImages[0], + commodityAmount: 1, + reservationDate: today() + }, + { + id: '202606150108', + orderAmt: '238.00', + visitorName: '王予安', + contactPhone: '13800000002', + orderStatus: '6', + payStatus: '1', + payAmt: '238.00', + orderType: '2', + createTime: formatDateTime(dayjs().subtract(1, 'day').toDate()), + commodityName: '云端餐厅双人套餐', + commodityCoverPhoto: coverImages[1], + commodityAmount: 1, + writeOffTime: formatDateTime(dayjs().subtract(4, 'hour').toDate()) + }, + { + id: '202606140072', + orderAmt: '158.00', + visitorName: '赵一鸣', + contactPhone: '13800000003', + orderStatus: '4', + payStatus: '1', + payAmt: '158.00', + orderType: '1', + createTime: formatDateTime(dayjs().subtract(2, 'day').toDate()), + commodityName: '温泉中心成人票', + commodityCoverPhoto: coverImages[2], + commodityAmount: 2 + }, + { + id: '202606130045', + orderAmt: '899.00', + visitorName: '许知夏', + contactPhone: '13800000004', + checkInData: addDays(2), + checkOutData: addDays(3), + orderStatus: '1', + payStatus: '1', + payAmt: '899.00', + orderType: '0', + createTime: formatDateTime(dayjs().subtract(3, 'day').toDate()), + commodityName: '亲子套房一晚', + commodityCoverPhoto: coverImages[0], + commodityAmount: 1, + reservationDate: addDays(2) + } +] + +let events: EventData[] = [ + { + id: 'EVT20260616001', + entityName: '前台', + eventDescription: '端午假期入住高峰,前台增开一组接待人员并优先处理已预付订单。', + eventStatus: 0, + effectiveStartTime: formatDateTime(dayjs().subtract(1, 'hour').toDate()), + effectiveEndTime: formatDateTime(dayjs().add(8, 'hour').toDate()), + createByName: '值班经理', + popUpReminder: 1, + publicTime: formatDateTime(dayjs().subtract(2, 'hour').toDate()), + imgUrl: coverImages[0], + showStatusDesc: '生效中' + }, + { + id: 'EVT20260615002', + entityName: '餐饮部', + eventDescription: '晚餐第二时段预约已满,建议推荐客人选择 19:45 后到店。', + eventStatus: 0, + effectiveStartTime: formatDateTime(dayjs().add(1, 'hour').toDate()), + effectiveEndTime: formatDateTime(dayjs().add(10, 'hour').toDate()), + createByName: '餐饮主管', + popUpReminder: 0, + publicTime: formatDateTime(dayjs().subtract(1, 'day').toDate()), + imgUrl: coverImages[1], + showStatusDesc: '待生效' + } +] + +const page = (records: T[], pageNum: number, pageSize: number): PageResponse => { + const start = (pageNum - 1) * pageSize + const current = records.slice(start, start + pageSize) + return { + records: current, + total: records.length, + size: pageSize, + current: pageNum, + pages: Math.ceil(records.length / pageSize) + } +} + +export const mockApi = { + async sendMobileCode(phone: string) { + await wait() + return { data: true, msg: phone ? '5678nianxx' : '请输入手机号' } + }, + + async loginByMobile(phone: string): Promise { + await wait() + return { + access_token: `mock-token-${Date.now()}`, + refresh_token: 'mock-refresh-token', + token_type: 'Bearer', + expires_in: 43200, + scope: 'server', + client_id: 'custom', + clientId: 'custom', + user_id: '10001', + username: phone, + tenant_id: 1 + } + }, + + async checkBindPhone() { + await wait(120) + return true + }, + + async bindOrganization(phone: string) { + await wait(180) + if (!phone) { + throw new Error('未绑定组织,请联系管理员') + } + return { + memberId: 'MEMBER10001', + organizationId: 'ORG10001', + memberName: '当前员工', + userPhone: phone, + memberRoleId: 'ROLE_STAFF' + } + }, + + async orderList(query: CommodityOrderSearch) { + await wait() + const keyword = query.orderId || query.contactPhone || '' + const filtered = orders.filter((item) => { + const matchStatus = query.orderStatus ? item.orderStatus === query.orderStatus : true + const matchType = query.commodityTypeCode ? item.orderType === query.commodityTypeCode : true + const matchKeyword = keyword + ? item.id.includes(keyword) || item.contactPhone.includes(keyword) || item.visitorName.includes(keyword) + : true + return matchStatus && matchType && matchKeyword + }) + return page(filtered, query.pageNum, query.pageSize) + }, + + async orderDetail(orderId: string): Promise { + await wait() + const order = orders.find((item) => item.id === orderId) || orders[0] + return { + orderId: order.id, + orderAmt: order.orderAmt, + consumerInfoList: [ + { + id: '1', + visitorName: order.visitorName, + contactPhone: order.contactPhone, + idCard: '430***********2218' + } + ], + checkInData: order.checkInData, + checkOutData: order.checkOutData, + reservationDate: order.reservationDate, + orderStatus: order.orderStatus, + userId: order.userId, + organizationId: order.organizationId, + payStatus: order.payStatus, + payAmt: order.payAmt, + discountAmt: order.discountAmt, + payTime: order.payTime, + createTime: order.createTime, + commodityCoverPhoto: order.commodityCoverPhoto, + commodityName: order.commodityName, + commodityAddress: '星河湾酒店一层前台', + commodityServiceList: [{ serviceName: '到店核销' }, { serviceName: '不可拆分使用' }], + commodityTip: '请在预约日期到店使用,核销后不支持退款。', + payWay: '0', + paySerialNumber: `WX${order.id}`, + paySource: '2', + orderType: order.orderType, + commodityAmount: String(order.commodityAmount), + storeName: '星河湾酒店', + complaintHotline: '18285123187', + refundable: order.orderStatus !== '6', + commodityId: `COM${order.id.slice(-4)}`, + commodityTypeCode: order.orderType, + commodityFacilityList: ['含早餐', '免费停车', '可预约'], + commodityDescription: '面向到店客人的酒店权益商品,需由员工确认后核销。', + commodityPackageConfig: [ + { + packageName: order.commodityName, + packageContent: `${order.commodityName} x ${order.commodityAmount}` + } + ], + reservationEnabled: order.reservationDate ? 1 : 0, + reservationRuleDesc: '预约订单请核对预约日期和联系人信息。', + writeOffRecordList: order.writeOffTime + ? [ + { + id: `WO${order.id}`, + orderId: order.id, + packageName: order.commodityName, + userName: '当前员工', + createTime: order.writeOffTime + } + ] + : [] + } + }, + + async writeOff(payload: WriteOffPayload): Promise { + await wait() + orders = orders.map((item) => + item.id === payload.orderId + ? { ...item, orderStatus: '6', writeOffTime: formatDateTime(new Date()) } + : item + ) + return { + success: true, + orderId: payload.orderId, + packageName: payload.packageName, + message: '核销成功', + operatedAt: formatDateTime(new Date()) + } + }, + + async eventList(query: EventSearch) { + await wait() + const filtered = events.filter((item) => { + const matchName = query.entityName ? item.entityName.includes(query.entityName) : true + const matchStatus = query.eventStatus === undefined ? true : item.eventStatus === query.eventStatus + return matchName && matchStatus + }) + return page(filtered, query.pageNum, query.pageSize) + }, + + async createEvent(payload: CreateEventPayload) { + await wait() + events = [ + { + id: `EVT${Date.now()}`, + ...payload, + eventStatus: 0, + createByName: '当前员工', + showStatusDesc: '待生效' + }, + ...events + ] + return true + }, + + async uploadFile(file: File) { + await wait() + return URL.createObjectURL(file) + } +} diff --git a/src/api/orders.ts b/src/api/orders.ts new file mode 100644 index 0000000..b2871a5 --- /dev/null +++ b/src/api/orders.ts @@ -0,0 +1,40 @@ +import http from './request' +import { mockApi } from './mock' +import { env } from '@/utils/env' +import type { PageResponse } from '@/types/api' +import { joinUrl } from '@/utils/url' +import type { + CommodityOrder, + CommodityOrderSearch, + UserOrderDetail, + WriteOffPayload, + WriteOffResult +} from '@/types/order' + +export const fetchOrderList = async (query: CommodityOrderSearch): Promise> => { + if (env.useMock) return mockApi.orderList(query) + return await http.post>( + joinUrl(env.staffBase, 'order/commodityOrderList'), + query + ) as unknown as PageResponse +} + +export const fetchOrderDetail = async (orderId: string): Promise => { + if (env.useMock) return mockApi.orderDetail(orderId) + return await http.post( + joinUrl(env.staffBase, 'order/userOrderDetail'), + { orderId } + ) as unknown as UserOrderDetail +} + +export const writeOffOrder = async (payload: WriteOffPayload): Promise => { + if (env.useMock) return mockApi.writeOff(payload) + await http.post(joinUrl(env.staffBase, 'order/writeOff'), payload) + return { + success: true, + orderId: payload.orderId, + packageName: payload.packageName, + message: '核销成功', + operatedAt: new Date().toISOString() + } +} diff --git a/src/api/request.ts b/src/api/request.ts new file mode 100644 index 0000000..2110c71 --- /dev/null +++ b/src/api/request.ts @@ -0,0 +1,36 @@ +import axios, { AxiosError } from 'axios' +import { showToast } from 'vant' +import { env } from '@/utils/env' + +const http = axios.create({ + baseURL: env.apiBase, + timeout: 15000 +}) + +http.interceptors.request.use((config) => { + const token = localStorage.getItem('hotel_h5_access_token') + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + return config +}) + +http.interceptors.response.use( + (response) => { + const payload = response.data + if (payload && typeof payload === 'object' && 'code' in payload) { + if (payload.code === 0 || payload.code === 200) { + return payload.data === undefined ? payload : payload.data + } + return Promise.reject(new Error(payload.msg || '请求失败')) + } + return payload + }, + (error: AxiosError<{ msg?: string }>) => { + const message = error.response?.data?.msg || error.message || '网络异常' + showToast(message) + return Promise.reject(error) + } +) + +export default http diff --git a/src/api/upload.ts b/src/api/upload.ts new file mode 100644 index 0000000..1d8cee3 --- /dev/null +++ b/src/api/upload.ts @@ -0,0 +1,20 @@ +import http from './request' +import { mockApi } from './mock' +import { env } from '@/utils/env' +import { joinUrl } from '@/utils/url' + +interface UploadResult { + url?: string +} + +export const uploadFile = async (file: File) => { + if (env.useMock) return mockApi.uploadFile(file) + const form = new FormData() + form.append('file', file) + const result = await http.post(joinUrl(env.hotelBizBase, 'hotBizCommon/upload'), form, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) as unknown as string | UploadResult + return typeof result === 'string' ? result : result.url || '' +} diff --git a/src/components/PageNav.vue b/src/components/PageNav.vue new file mode 100644 index 0000000..11345d8 --- /dev/null +++ b/src/components/PageNav.vue @@ -0,0 +1,28 @@ + + + diff --git a/src/components/StatusTag.vue b/src/components/StatusTag.vue new file mode 100644 index 0000000..1bb29a6 --- /dev/null +++ b/src/components/StatusTag.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..794d15a --- /dev/null +++ b/src/main.ts @@ -0,0 +1,16 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import Vant from 'vant' +import 'vant/lib/index.css' + +import App from './App.vue' +import router from './router' +import './styles/main.css' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) +app.use(Vant) + +app.mount('#app') diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..3327b18 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,102 @@ +import { createRouter, createWebHistory } from 'vue-router' +import { useAuthStore } from '@/stores/auth' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/login', + name: 'login', + component: () => import('@/views/login/LoginView.vue'), + meta: { public: true } + }, + { + path: '/', + component: () => import('@/views/layout/AppLayout.vue'), + children: [ + { + path: '', + redirect: '/home' + }, + { + path: 'home', + name: 'home', + component: () => import('@/views/home/HomeView.vue'), + meta: { title: '工作台' } + }, + { + path: 'orders', + name: 'orders', + component: () => import('@/views/orders/OrderListView.vue'), + meta: { title: '订单' } + }, + { + path: 'orders/:id', + name: 'order-detail', + component: () => import('@/views/orders/OrderDetailView.vue'), + meta: { title: '订单详情', hideTabbar: true } + }, + { + path: 'verify', + name: 'verify', + component: () => import('@/views/verify/VerifyView.vue'), + meta: { title: '核销' } + }, + { + path: 'verify/confirm', + name: 'verify-confirm', + component: () => import('@/views/verify/VerifyConfirmView.vue'), + meta: { title: '核销确认', hideTabbar: true } + }, + { + path: 'verify/result', + name: 'verify-result', + component: () => import('@/views/verify/VerifyResultView.vue'), + meta: { title: '核销结果', hideTabbar: true } + }, + { + path: 'events', + name: 'events', + component: () => import('@/views/events/EventListView.vue'), + meta: { title: '事件' } + }, + { + path: 'events/create', + name: 'event-create', + component: () => import('@/views/events/EventCreateView.vue'), + meta: { title: '发布事件', hideTabbar: true } + }, + { + path: 'mine', + name: 'mine', + component: () => import('@/views/mine/MineView.vue'), + meta: { title: '我的' } + } + ] + }, + { + path: '/:pathMatch(.*)*', + redirect: '/home' + } + ], + scrollBehavior() { + return { top: 0 } + } +}) + +router.beforeEach((to) => { + const auth = useAuthStore() + if (!to.meta.public && !auth.isLoggedIn) { + return { + name: 'login', + query: { + redirect: to.fullPath + } + } + } + if (to.name === 'login' && auth.isLoggedIn) { + return { name: 'home' } + } +}) + +export default router diff --git a/src/stores/auth.ts b/src/stores/auth.ts new file mode 100644 index 0000000..7b2f845 --- /dev/null +++ b/src/stores/auth.ts @@ -0,0 +1,109 @@ +import { computed, ref } from 'vue' +import { defineStore } from 'pinia' +import { + bindUserInfoAndGetUserMemberInfoByPhone, + loginByMobile, + type OrganizationMemberInfo +} from '@/api/auth' +import type { TokenResponse } from '@/types/api' +import { env } from '@/utils/env' + +export interface StaffUser { + id?: string + username?: string + phone?: string + tenantId?: string | number +} + +const TOKEN_KEY = 'hotel_h5_access_token' +const REFRESH_TOKEN_KEY = 'hotel_h5_refresh_token' +const USER_KEY = 'hotel_h5_user' +const MEMBER_KEY = 'hotel_h5_member' + +const readUser = (): StaffUser | null => { + const raw = localStorage.getItem(USER_KEY) + if (!raw) return null + try { + return JSON.parse(raw) as StaffUser + } catch { + return null + } +} + +const readMember = (): OrganizationMemberInfo | null => { + const raw = localStorage.getItem(MEMBER_KEY) + if (!raw) return null + try { + return JSON.parse(raw) as OrganizationMemberInfo + } catch { + return null + } +} + +export const useAuthStore = defineStore('auth', () => { + const token = ref(localStorage.getItem(TOKEN_KEY) || '') + const refreshToken = ref(localStorage.getItem(REFRESH_TOKEN_KEY) || '') + const user = ref(readUser()) + const memberInfo = ref(readMember()) + + const isLoggedIn = computed(() => Boolean(token.value)) + const hasOrganization = computed(() => Boolean(memberInfo.value?.organizationId)) + + const persistToken = (payload: TokenResponse, phone: string) => { + token.value = payload.access_token + refreshToken.value = payload.refresh_token || '' + user.value = { + id: payload.user_id, + username: payload.username || phone, + phone, + tenantId: payload.tenant_id + } + + localStorage.setItem(TOKEN_KEY, token.value) + if (refreshToken.value) { + localStorage.setItem(REFRESH_TOKEN_KEY, refreshToken.value) + } + localStorage.setItem(USER_KEY, JSON.stringify(user.value)) + } + + const login = async (phone: string, code: string) => { + const payload = await loginByMobile(phone, code) + persistToken(payload, phone) + try { + const member = await bindUserInfoAndGetUserMemberInfoByPhone(phone) + if (!member?.organizationId || !member?.memberId) { + throw new Error('未绑定组织,请联系管理员') + } + memberInfo.value = member + localStorage.setItem(MEMBER_KEY, JSON.stringify(member)) + } catch (error) { + logout() + throw new Error('未绑定组织,请联系管理员') + } + } + + const logout = () => { + token.value = '' + refreshToken.value = '' + user.value = null + memberInfo.value = null + localStorage.removeItem(TOKEN_KEY) + localStorage.removeItem(REFRESH_TOKEN_KEY) + localStorage.removeItem(USER_KEY) + localStorage.removeItem(MEMBER_KEY) + } + + return { + token, + refreshToken, + user, + memberInfo, + hasOrganization, + isLoggedIn, + isMockMode: env.useMock, + clientId: env.clientId, + clientConfigId: env.clientConfigId, + login, + logout + } +}) diff --git a/src/styles/main.css b/src/styles/main.css new file mode 100644 index 0000000..dbda731 --- /dev/null +++ b/src/styles/main.css @@ -0,0 +1,425 @@ +:root { + --app-bg: #f6f8f7; + --surface: #ffffff; + --surface-soft: #eef7f3; + --text-strong: #14211c; + --text-main: #26352f; + --text-muted: #7a8780; + --line: #e2e8e4; + --primary: #0f8b72; + --primary-deep: #08705e; + --primary-soft: #dff4ec; + --amber: #f3a51d; + --rose: #d94d5c; + --blue: #286fb7; + --shadow: 0 8px 20px rgba(18, 38, 31, 0.08); + --radius: 8px; + --safe-bottom: env(safe-area-inset-bottom); + color: var(--text-main); + background: var(--app-bg); + font-family: + -apple-system, + BlinkMacSystemFont, + "Segoe UI", + "PingFang SC", + "Hiragino Sans GB", + "Microsoft YaHei", + sans-serif; + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + letter-spacing: 0; +} + +* { + box-sizing: border-box; +} + +html, +body, +#app { + min-height: 100%; + margin: 0; + background: var(--app-bg); +} + +body { + min-width: 320px; +} + +button, +input, +textarea { + font: inherit; +} + +button { + color: inherit; +} + +.app-shell { + min-height: 100vh; + padding: 0 14px 78px; + background: + linear-gradient(180deg, #e9f6ef 0, rgba(246, 248, 247, 0) 210px), + var(--app-bg); +} + +.app-shell--no-tabbar { + padding-bottom: calc(18px + var(--safe-bottom)); +} + +.app-tabbar { + border-top: 1px solid var(--line); +} + +.page { + width: min(100%, 560px); + margin: 0 auto; + padding: 14px 0 18px; +} + +.page-header { + padding: 18px 2px 14px; +} + +.page-kicker { + margin: 0 0 6px; + color: var(--primary-deep); + font-size: 13px; + font-weight: 600; +} + +.page-title { + margin: 0; + color: var(--text-strong); + font-size: 24px; + font-weight: 750; + line-height: 1.2; +} + +.page-subtitle { + margin: 8px 0 0; + color: var(--text-muted); + font-size: 14px; + line-height: 1.5; +} + +.page-nav { + position: sticky; + z-index: 5; + top: 0; + display: grid; + grid-template-columns: 42px 1fr 72px; + align-items: center; + width: min(100%, 560px); + height: 52px; + margin: 0 auto; + padding-top: max(0px, env(safe-area-inset-top)); + background: rgba(246, 248, 247, 0.94); + backdrop-filter: blur(10px); +} + +.page-nav h1 { + overflow: hidden; + margin: 0; + color: var(--text-strong); + font-size: 18px; + font-weight: 750; + line-height: 1.2; + text-align: center; + text-overflow: ellipsis; + white-space: nowrap; +} + +.icon-button, +.nav-text-button { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 38px; + height: 38px; + border: 0; + border-radius: var(--radius); + background: transparent; +} + +.icon-button:active, +.nav-text-button:active { + background: rgba(15, 139, 114, 0.1); +} + +.nav-text-button { + color: var(--primary-deep); + font-size: 14px; + font-weight: 700; +} + +.nav-placeholder { + display: block; +} + +.panel { + overflow: hidden; + border: 1px solid rgba(226, 232, 228, 0.9); + border-radius: var(--radius); + background: var(--surface); + box-shadow: var(--shadow); +} + +.panel + .panel, +.section + .section { + margin-top: 12px; +} + +.section-title { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + margin: 0 0 10px; + color: var(--text-strong); + font-size: 16px; + font-weight: 750; +} + +.section-title small { + color: var(--text-muted); + font-size: 12px; + font-weight: 500; +} + +.toolbar { + display: flex; + gap: 8px; + align-items: center; + padding: 10px 0; +} + +.toolbar .van-search { + flex: 1; + padding: 0; + background: transparent; +} + +.quick-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 8px; +} + +.quick-action { + display: flex; + min-width: 0; + min-height: 76px; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; + border: 1px solid var(--line); + border-radius: var(--radius); + background: var(--surface); + color: var(--text-main); + text-decoration: none; +} + +.quick-action svg { + color: var(--primary); +} + +.quick-action span { + width: 100%; + overflow: hidden; + padding: 0 4px; + font-size: 12px; + font-weight: 650; + line-height: 1.2; + text-align: center; + text-overflow: ellipsis; + white-space: nowrap; +} + +.stat-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 8px; +} + +.stat-card { + min-height: 92px; + padding: 14px; + border-radius: var(--radius); + background: var(--surface); + box-shadow: var(--shadow); +} + +.stat-label { + color: var(--text-muted); + font-size: 12px; + line-height: 1.4; +} + +.stat-value { + margin-top: 8px; + color: var(--text-strong); + font-size: 25px; + font-weight: 800; + line-height: 1; +} + +.stat-hint { + margin-top: 8px; + color: var(--primary-deep); + font-size: 12px; +} + +.order-card, +.event-card { + display: block; + padding: 12px; + border: 1px solid var(--line); + border-radius: var(--radius); + background: var(--surface); + color: inherit; + text-decoration: none; +} + +.order-card + .order-card, +.event-card + .event-card { + margin-top: 10px; +} + +.order-card__main { + display: grid; + grid-template-columns: 76px 1fr; + gap: 10px; +} + +.thumb { + width: 76px; + height: 76px; + overflow: hidden; + border-radius: var(--radius); + background: var(--surface-soft); +} + +.thumb img { + display: block; + width: 100%; + height: 100%; + object-fit: cover; +} + +.card-title { + display: -webkit-box; + overflow: hidden; + margin: 0; + color: var(--text-strong); + font-size: 15px; + font-weight: 750; + line-height: 1.35; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; +} + +.meta-row, +.detail-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + color: var(--text-muted); + font-size: 12px; + line-height: 1.5; +} + +.meta-row strong, +.detail-row strong { + color: var(--text-main); + font-weight: 650; +} + +.stack { + display: flex; + flex-direction: column; + gap: 8px; +} + +.divider { + height: 1px; + margin: 12px 0; + background: var(--line); +} + +.empty-state { + padding: 34px 20px; + color: var(--text-muted); + text-align: center; +} + +.empty-state svg { + margin-bottom: 8px; + color: var(--primary); +} + +.fixed-action { + position: fixed; + z-index: 10; + right: 0; + bottom: 0; + left: 0; + padding: 10px 14px calc(10px + var(--safe-bottom)); + border-top: 1px solid var(--line); + background: rgba(255, 255, 255, 0.96); + backdrop-filter: blur(10px); +} + +.fixed-action__inner { + display: grid; + width: min(100%, 560px); + margin: 0 auto; + grid-template-columns: 1fr; + gap: 8px; +} + +.van-button { + border-radius: var(--radius); +} + +.van-button__content { + gap: 6px; +} + +.van-tabs__wrap { + border-radius: var(--radius); +} + +.form-panel { + padding: 12px; +} + +.plain-input { + width: 100%; + min-height: 44px; + padding: 0 12px; + border: 1px solid var(--line); + border-radius: var(--radius); + background: var(--surface); + color: var(--text-main); + outline: none; +} + +.plain-input:focus { + border-color: var(--primary); +} + +@media (max-width: 360px) { + .quick-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .stat-grid { + grid-template-columns: 1fr; + } +} diff --git a/src/types/api.ts b/src/types/api.ts new file mode 100644 index 0000000..1e26f5d --- /dev/null +++ b/src/types/api.ts @@ -0,0 +1,31 @@ +export interface ApiResponse { + code: number + msg?: string + data: T +} + +export interface PageResponse { + records: T[] + total: number + size: number + current: number + pages?: number +} + +export interface PageQuery { + pageNum: number + pageSize: number +} + +export interface TokenResponse { + access_token: string + refresh_token?: string + scope?: string + token_type?: string + expires_in?: number + client_id?: string + clientId?: string + user_id?: string + username?: string + tenant_id?: string | number +} diff --git a/src/types/event.ts b/src/types/event.ts new file mode 100644 index 0000000..e831d63 --- /dev/null +++ b/src/types/event.ts @@ -0,0 +1,32 @@ +import type { PageQuery } from './api' + +export type EventStatus = 0 | 1 + +export interface EventData { + id: string + entityName: string + eventDescription: string + eventStatus: EventStatus + effectiveStartTime: string + effectiveEndTime: string + createByName?: string + popUpReminder?: 0 | 1 + publicTime?: string + imgUrl?: string + showStatusDesc?: string +} + +export interface EventSearch extends PageQuery { + entityName?: string + eventStatus?: EventStatus +} + +export interface CreateEventPayload { + entityName: string + eventDescription: string + popUpReminder: 0 | 1 + publicTime: string + effectiveStartTime: string + effectiveEndTime: string + imgUrl?: string +} diff --git a/src/types/order.ts b/src/types/order.ts new file mode 100644 index 0000000..b303b0a --- /dev/null +++ b/src/types/order.ts @@ -0,0 +1,127 @@ +import type { PageQuery } from './api' + +export type OrderStatus = '0' | '1' | '2' | '3' | '4' | '5' | '6' +export type PayStatus = '0' | '1' +export type CommodityTypeCode = '0' | '1' | '2' + +export interface CommodityOrder { + id: string + orderAmt: string + visitorName: string + contactPhone: string + checkInData?: string + checkOutData?: string + orderStatus: OrderStatus + userId?: string + organizationId?: string + payStatus: PayStatus + payAmt: string + discountAmt?: string + payTime?: string + orderType: CommodityTypeCode + createTime: string + roomId?: string + commodityName: string + commodityCoverPhoto?: string + commodityAmount: number | string + reservationDate?: string + writeOffTime?: string +} + +export interface CommodityOrderSearch extends PageQuery { + commodityTypeCode?: string + orderStatus?: string + orderCreateTimeStartDate?: string + orderCreateTimeEndDate?: string + roomId?: string + orderId?: string + contactPhone?: string + reservationOrderFlag?: string +} + +export interface ConsumerInfo { + id?: string + visitorName?: string + contactPhone?: string + idCard?: string +} + +export interface CommodityService { + serviceName?: string + serviceDesc?: string +} + +export interface CommodityPackageConfig { + packageName?: string + packageContent?: string + packageDesc?: string + name?: string + content?: string +} + +export interface WriteOffRecord { + id?: string + orderId?: string + packageName?: string + userId?: string + userName?: string + createTime?: string +} + +export interface UserOrderDetail { + orderId: string + orderAmt: string + consumerInfoList?: ConsumerInfo[] + checkInData?: string + checkOutData?: string + reservationDate?: string + orderStatus: OrderStatus + userId?: string + organizationId?: string + payStatus: PayStatus + payAmt: string + discountAmt?: string + payTime?: string + createTime?: string + commodityCoverPhoto?: string + writeOffUrl?: string + commodityName: string + commodityAddress?: string + commodityLatitude?: string + commodityLongitude?: string + commodityServiceList?: CommodityService[] + commodityTip?: string + payWay?: string + paySerialNumber?: string + paySource?: string + orderType: CommodityTypeCode + commodityAmount: string + refundOrderNo?: string + storeName?: string + complaintHotline?: string + oneLevelAddress?: string + twoLevelAddress?: string + refundable?: boolean + commodityId?: string + commodityTypeCode?: string + commodityFacilityList?: string[] + commodityDescription?: string + commodityPackageConfig?: CommodityPackageConfig[] + reservationEnabled?: number + reservationRuleDesc?: string + writeOffRecordList?: WriteOffRecord[] + refundTime?: string +} + +export interface WriteOffPayload { + orderId: string + packageName?: string +} + +export interface WriteOffResult { + success: boolean + orderId: string + packageName?: string + message: string + operatedAt: string +} diff --git a/src/utils/constants.ts b/src/utils/constants.ts new file mode 100644 index 0000000..b7d8154 --- /dev/null +++ b/src/utils/constants.ts @@ -0,0 +1,40 @@ +import type { CommodityTypeCode, OrderStatus, PayStatus } from '@/types/order' +import type { EventStatus } from '@/types/event' + +export const orderStatusText: Record = { + '0': '待支付', + '1': '待确认', + '2': '待使用', + '3': '已取消', + '4': '退款中', + '5': '已关闭', + '6': '已完成' +} + +export const orderStatusTone: Record = { + '0': 'warning', + '1': 'primary', + '2': 'primary', + '3': 'default', + '4': 'warning', + '5': 'default', + '6': 'success' +} + +export const payStatusText: Record = { + '0': '未支付', + '1': '已支付' +} + +export const commodityTypeText: Record = { + '0': '酒店', + '1': '门票', + '2': '餐饮' +} + +export const eventStatusText: Record = { + 0: '开启', + 1: '关闭' +} + +export const canWriteOff = (status?: string) => status === '2' diff --git a/src/utils/date.ts b/src/utils/date.ts new file mode 100644 index 0000000..2d84291 --- /dev/null +++ b/src/utils/date.ts @@ -0,0 +1,22 @@ +import dayjs from 'dayjs' + +export const formatDateTime = (value?: string | Date) => { + if (!value) return '' + return dayjs(value).format('YYYY-MM-DD HH:mm:ss') +} + +export const formatDate = (value?: string | Date) => { + if (!value) return '' + return dayjs(value).format('YYYY-MM-DD') +} + +export const toBackendDateTime = (value?: string) => { + if (!value) return '' + return value.includes('T') ? `${value.replace('T', ' ')}:00`.slice(0, 19) : value +} + +export const toDateTimeInput = (value: Date | string = new Date()) => dayjs(value).format('YYYY-MM-DDTHH:mm') + +export const today = () => dayjs().format('YYYY-MM-DD') + +export const addDays = (days: number) => dayjs().add(days, 'day').format('YYYY-MM-DD') diff --git a/src/utils/env.ts b/src/utils/env.ts new file mode 100644 index 0000000..6b15f0e --- /dev/null +++ b/src/utils/env.ts @@ -0,0 +1,11 @@ +export const env = { + useMock: import.meta.env.VITE_USE_MOCK !== 'false', + apiBase: import.meta.env.VITE_API_BASE_URL || '', + authBase: import.meta.env.VITE_AUTH_BASE || '/auth', + adminBase: import.meta.env.VITE_ADMIN_BASE || '/admin', + staffBase: import.meta.env.VITE_STAFF_BASE || '/hotelStaff', + hotelBizBase: import.meta.env.VITE_HOTEL_BIZ_BASE || '/hotelBiz', + clientId: import.meta.env.VITE_CLIENT_ID || 'custom', + clientSecret: import.meta.env.VITE_CLIENT_SECRET || '', + clientConfigId: import.meta.env.VITE_CLIENT_CONFIG_ID || '' +} diff --git a/src/utils/url.ts b/src/utils/url.ts new file mode 100644 index 0000000..bc176d2 --- /dev/null +++ b/src/utils/url.ts @@ -0,0 +1,14 @@ +export const joinUrl = (...parts: Array) => + parts + .filter((part): part is string => Boolean(part)) + .map((part, index) => { + if (index === 0) { + const normalized = part.replace(/\/+$/g, '') + if (!normalized || /^https?:\/\//.test(normalized) || normalized.startsWith('/')) { + return normalized + } + return `/${normalized}` + } + return part.replace(/^\/+|\/+$/g, '') + }) + .join('/') diff --git a/src/views/events/EventCreateView.vue b/src/views/events/EventCreateView.vue new file mode 100644 index 0000000..148f365 --- /dev/null +++ b/src/views/events/EventCreateView.vue @@ -0,0 +1,183 @@ + + + + + diff --git a/src/views/events/EventListView.vue b/src/views/events/EventListView.vue new file mode 100644 index 0000000..abe1c39 --- /dev/null +++ b/src/views/events/EventListView.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/src/views/home/HomeView.vue b/src/views/home/HomeView.vue new file mode 100644 index 0000000..08daa30 --- /dev/null +++ b/src/views/home/HomeView.vue @@ -0,0 +1,204 @@ + + + + + diff --git a/src/views/layout/AppLayout.vue b/src/views/layout/AppLayout.vue new file mode 100644 index 0000000..4123b82 --- /dev/null +++ b/src/views/layout/AppLayout.vue @@ -0,0 +1,46 @@ + + + diff --git a/src/views/login/LoginView.vue b/src/views/login/LoginView.vue new file mode 100644 index 0000000..a0129e6 --- /dev/null +++ b/src/views/login/LoginView.vue @@ -0,0 +1,203 @@ + + + + + diff --git a/src/views/mine/MineView.vue b/src/views/mine/MineView.vue new file mode 100644 index 0000000..a816885 --- /dev/null +++ b/src/views/mine/MineView.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/src/views/orders/OrderDetailView.vue b/src/views/orders/OrderDetailView.vue new file mode 100644 index 0000000..f2e0724 --- /dev/null +++ b/src/views/orders/OrderDetailView.vue @@ -0,0 +1,234 @@ + + + + + diff --git a/src/views/orders/OrderListView.vue b/src/views/orders/OrderListView.vue new file mode 100644 index 0000000..9ec2c6b --- /dev/null +++ b/src/views/orders/OrderListView.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/src/views/verify/VerifyConfirmView.vue b/src/views/verify/VerifyConfirmView.vue new file mode 100644 index 0000000..bd812f0 --- /dev/null +++ b/src/views/verify/VerifyConfirmView.vue @@ -0,0 +1,198 @@ + + + + + diff --git a/src/views/verify/VerifyResultView.vue b/src/views/verify/VerifyResultView.vue new file mode 100644 index 0000000..a2ee62c --- /dev/null +++ b/src/views/verify/VerifyResultView.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/src/views/verify/VerifyView.vue b/src/views/verify/VerifyView.vue new file mode 100644 index 0000000..79bde92 --- /dev/null +++ b/src/views/verify/VerifyView.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..db4bf17 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,13 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..ea9d0cd --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..d6f29dd --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,12 @@ +{ + "extends": "@tsconfig/node22/tsconfig.json", + "include": ["vite.config.*"], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..6feb9f8 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,46 @@ +import { fileURLToPath, URL } from 'node:url' +import { defineConfig, loadEnv } from 'vite' +import vue from '@vitejs/plugin-vue' + +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd(), '') + const proxyTarget = env.VITE_PROXY_TARGET || 'http://localhost:9999' + + return { + plugins: [vue()], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + }, + server: { + port: 5173, + proxy: { + '/auth': { + target: proxyTarget, + changeOrigin: true + }, + '/admin': { + target: proxyTarget, + changeOrigin: true + }, + '/hotel-staff': { + target: proxyTarget, + changeOrigin: true + }, + '/hotel-biz': { + target: proxyTarget, + changeOrigin: true + }, + '/hotelStaff': { + target: proxyTarget, + changeOrigin: true + }, + '/hotelBiz': { + target: proxyTarget, + changeOrigin: true + } + } + } + } +}) diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..3eea8cb --- /dev/null +++ b/yarn.lock @@ -0,0 +1,908 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/helper-string-parser@^7.29.7": + version "7.29.7" + resolved "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz#7f0871d99824d23137d60f86fcf6130fd5a1b51f" + integrity sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw== + +"@babel/helper-validator-identifier@^7.29.7": + version "7.29.7" + resolved "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz#bd87084ced0c796ec46bda492de6e83d29e89fc2" + integrity sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg== + +"@babel/parser@^7.29.7": + version "7.29.7" + resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.7.tgz#837b87387cbf5ec5530cb634b3c622f68edb9334" + integrity sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg== + dependencies: + "@babel/types" "^7.29.7" + +"@babel/types@^7.29.7": + version "7.29.7" + resolved "https://registry.npmmirror.com/@babel/types/-/types-7.29.7.tgz#8005e31d82712ee7adaef6e23c63b71a62770a92" + integrity sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA== + dependencies: + "@babel/helper-string-parser" "^7.29.7" + "@babel/helper-validator-identifier" "^7.29.7" + +"@esbuild/aix-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz#80fcbe36130e58b7670511e888b8e88a259ed76c" + integrity sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA== + +"@esbuild/android-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz#8aa4965f8d0a7982dc21734bf6601323a66da752" + integrity sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg== + +"@esbuild/android-arm@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz#300712101f7f50f1d2627a162e6e09b109b6767a" + integrity sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg== + +"@esbuild/android-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz#87dfb27161202bdc958ef48bb61b09c758faee16" + integrity sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg== + +"@esbuild/darwin-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz#79197898ec1ff745d21c071e1c7cc3c802f0c1fd" + integrity sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg== + +"@esbuild/darwin-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz#146400a8562133f45c4d2eadcf37ddd09718079e" + integrity sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA== + +"@esbuild/freebsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz#1c5f9ba7206e158fd2b24c59fa2d2c8bb47ca0fe" + integrity sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg== + +"@esbuild/freebsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz#ea631f4a36beaac4b9279fa0fcc6ca29eaeeb2b3" + integrity sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ== + +"@esbuild/linux-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz#e1066bce58394f1b1141deec8557a5f0a22f5977" + integrity sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ== + +"@esbuild/linux-arm@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz#452cd66b20932d08bdc53a8b61c0e30baf4348b9" + integrity sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw== + +"@esbuild/linux-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz#b24f8acc45bcf54192c7f2f3be1b53e6551eafe0" + integrity sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA== + +"@esbuild/linux-loong64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz#f9cfffa7fc8322571fbc4c8b3268caf15bd81ad0" + integrity sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng== + +"@esbuild/linux-mips64el@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz#575a14bd74644ffab891adc7d7e60d275296f2cd" + integrity sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw== + +"@esbuild/linux-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz#75b99c70a95fbd5f7739d7692befe60601591869" + integrity sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA== + +"@esbuild/linux-riscv64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz#2e3259440321a44e79ddf7535c325057da875cd6" + integrity sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w== + +"@esbuild/linux-s390x@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz#17676cabbfe5928da5b2a0d6df5d58cd08db2663" + integrity sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg== + +"@esbuild/linux-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz#0583775685ca82066d04c3507f09524d3cd7a306" + integrity sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw== + +"@esbuild/netbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz#f04c4049cb2e252fe96b16fed90f70746b13f4a4" + integrity sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg== + +"@esbuild/netbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz#77da0d0a0d826d7c921eea3d40292548b258a076" + integrity sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ== + +"@esbuild/openbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz#6296f5867aedef28a81b22ab2009c786a952dccd" + integrity sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A== + +"@esbuild/openbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz#f8d23303360e27b16cf065b23bbff43c14142679" + integrity sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw== + +"@esbuild/openharmony-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz#49e0b768744a3924be0d7fd97dd6ce9b2923d88d" + integrity sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg== + +"@esbuild/sunos-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz#a6ed7d6778d67e528c81fb165b23f4911b9b13d6" + integrity sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w== + +"@esbuild/win32-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz#9ac14c378e1b653af17d08e7d3ce34caef587323" + integrity sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg== + +"@esbuild/win32-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz#918942dcbbb35cc14fca39afb91b5e6a3d127267" + integrity sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ== + +"@esbuild/win32-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz#9bdad8176be7811ad148d1f8772359041f46c6c5" + integrity sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA== + +"@jridgewell/sourcemap-codec@^1.5.5": + version "1.5.5" + resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@rollup/rollup-android-arm-eabi@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.0.tgz#634b0258cc501bef2353cee09a887b434826e81f" + integrity sha512-IPIQ55ythEHkfEd9jMEi32OQ7SxURsGA43JI22lj01OLZNt2NUbJX8YUHxkVWyQ6daHPNn0truF5nSj3DQp6YQ== + +"@rollup/rollup-android-arm64@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.0.tgz#d7804ff9c31c2b8e7c51d966fedac65a4c828578" + integrity sha512-M6s9cr10MibETyo8JsOkq+Lo1+lU6hcvb1MApnUql5qte/5hMEgzlN8/ReIKNfRV8rrqX50W1BX9zoUhC192RA== + +"@rollup/rollup-darwin-arm64@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.0.tgz#f26d03228e48c8bd55ff6be847242308dbfdb50d" + integrity sha512-BqCoMoIbn0keKys+dEAdBa70EtOwV1bEsQCUgU9FdiZmmMge/Zk7LlkYGqbrdHR+Frnt0E1FOanly+rlwvvQzw== + +"@rollup/rollup-darwin-x64@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.0.tgz#6e9037ccfc806a749aa044b063256a26ad32339d" + integrity sha512-SIMzST3VFNXDAbeIWDWiFCNM5qncUBDWaEV7NfE7oZbDt2mgfW4MvbKdbYiGOLoM32gbTv608UMd0XktEYSD7w== + +"@rollup/rollup-freebsd-arm64@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.0.tgz#ff448605b36cc4736a6fea89bd0eb74653f09cbc" + integrity sha512-ezjfSQMP7ArdUsbBwbQIfwAlhE84I2iVnzQNCFSveqV42q+BmKlzVpf7mxv5EchLcoWU4y6/heFzVg1F+hodUQ== + +"@rollup/rollup-freebsd-x64@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.0.tgz#a30fe00a8651b577966022d1db1fb1bd6776105e" + integrity sha512-9+qTWGW9AZRhnUgwtTwzNwcPlL87ngkeN0LA+q1bADvmY9aNvWaF2TFW8BZgnQPYxpDI7+rMVLivcd4V737TAQ== + +"@rollup/rollup-linux-arm-gnueabihf@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.0.tgz#0ba85b63893eb17e11052bd21fe2809afc475a82" + integrity sha512-T1dMEQhXA/jkJ/jyMIw9IovK8bSUq7A8kLIlvZTb/6YIVsp2zLavr4F3oyllHWo7eIVJRyE5n3tUjQJEbE1IuQ== + +"@rollup/rollup-linux-arm-musleabihf@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.0.tgz#982bf23fcfe4e8e13002912d4073f56a2eea2a39" + integrity sha512-2as0LgT7qQpyceQq6VUJYnumUMUrgGQCWIiDIN9DE0/tglsk6o66uCB4f3djRawAltvfCNLyZZrsqbPA6inCsA== + +"@rollup/rollup-linux-arm64-gnu@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.0.tgz#c94d1e8bd116ea2b569aab37dd04a6ccab74f1ab" + integrity sha512-bVURMg+6eNN9C/yc0aVjooZcwTTtYF4YW3xta5pP0//r3o1V8gXEHXWCndj47w/HhwsFroZrFhR+6uQP5T0n0g== + +"@rollup/rollup-linux-arm64-musl@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.0.tgz#a7d79014ba3c5dd2d140309730365d413976db24" + integrity sha512-Ful8pM/2yYI83PViWdFdpZhdI8HJ5qsXANe5atypbHDf+KIBBDsZsbyy8hbXnULVvW9NsTh5DHwbcBftyLTfiw== + +"@rollup/rollup-linux-loong64-gnu@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.0.tgz#5dd943c58bda55d8b269426bd60a47dd9c27776e" + integrity sha512-9Gp/DgrkzfUBmNPVTyPTvay+4xEP7M/clXpj3efXBcm6uTIVIgDg4rqUpqKXvLEuFRVuEpSAOkhgNeecvaZ4Cg== + +"@rollup/rollup-linux-loong64-musl@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.0.tgz#08b1b9d362c64847306fea979b935e93a2590c4e" + integrity sha512-m9tsJz54LUXkSYM8+8PG81B9IKK5r+2T0clMq4QrS16xFosufU7firBDAZEsDheDs7wTlP7h3++S7lMsU955HA== + +"@rollup/rollup-linux-ppc64-gnu@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.0.tgz#1c5de568966d11091281b22bc764ee7adf92667b" + integrity sha512-3UvJ5PNVU16aJf6M3tFI24pWzAl2/ynfbyRN3ICyQajK1lSkrnVYNnLz3v04J32qKa0FczJc22zeToc0lr2A3w== + +"@rollup/rollup-linux-ppc64-musl@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.0.tgz#4dde1c9b941748ea49e07cfc96c64b18236225cd" + integrity sha512-vRWUAbYLGHBZS6Q8Msb2sfnf1fvJf+47t8l/TwOerM2qArzy+IeNMTHrYLHXh95h8MoatPHI5hhSZNs+mGXKPg== + +"@rollup/rollup-linux-riscv64-gnu@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.0.tgz#21dd1014033b970dd23189d1d4d3cdab45de7f9a" + integrity sha512-c00T5SYENHAt86cfW47URaP3Us5vLC/4QO7GYud1G5VNRffCwwCuBspwqYrriuJB+5m0WFzClCn9wed0FBjKvg== + +"@rollup/rollup-linux-riscv64-musl@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.0.tgz#4664e0bae205a3a18eb6407c10054c4b8dd7f381" + integrity sha512-krrCDilhXOwFkSkO3Wm9I/f9H0L92XHHwy2fwxjukxIbh0dem8gZqOW5Y8BsHrpJv5qwlRBV+Wl4ZFyRWhUpwg== + +"@rollup/rollup-linux-s390x-gnu@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.0.tgz#b05a6b3af6a0d3c9b9f7be9c253eb4f101a67848" + integrity sha512-7pfYFSTc4/rUC/FtAI0Qp6QthDBCIi6/AuP1xYqFk5vanI6KnL5dWKP60OM/05LOsbwTmIcvr6eXC4CJuJ75IA== + +"@rollup/rollup-linux-x64-gnu@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.0.tgz#85dda72aa08cdc256f80f46d881b2a988bb0cce2" + integrity sha512-7SDIalKeIpG0Ifogbbdn58HmSotYMlf23K3dCJEmiVd9Fg36Vmni82iPQec27N3wY4Bvbxftkxz6vSx9OcouTg== + +"@rollup/rollup-linux-x64-musl@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.0.tgz#d79f5be62a484b58a8ec4d5ae23acf7b0eb1a8ff" + integrity sha512-eRZevouTH2i1HeAVLqJuLnt256krQkGY0TN6WsTmsIhuzbh457HuWDMakKwmi0Cjadux983CoSr8Lim2QhUIFw== + +"@rollup/rollup-openbsd-x64@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.0.tgz#8ebafe0d66cde1c8ab0a867cd9dcea89e22ee7b1" + integrity sha512-3oVS7FLGa4U1qcvao9ylGxrjXZyUQqR8UwxEcnUEyPX53O/C/mKDZegNXTdHCP+h3e6ta/f1EN38Yif1mmZHYg== + +"@rollup/rollup-openharmony-arm64@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.0.tgz#105537bcfcb2fd82796518184e995ae4396bb792" + integrity sha512-yTB9TgfWj5wHe5QgktAgXTLLot1gvEjl1NiPPAUiCs4oPrIWFl5V4nC3GrkNdj9LaAU4s94nVrGbGOCqUpyWsg== + +"@rollup/rollup-win32-arm64-msvc@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.0.tgz#08ebcfc01b5b3b106ae074bae3692e94a63b5125" + integrity sha512-5LOhoaesY3doG1c+ac/2JtgREpKoJr5bUHH8tKY0V8di7+uSV6BwLs2PlR0/yzefGOkR+wE7ZolZphHCsyG5Rw== + +"@rollup/rollup-win32-ia32-msvc@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.0.tgz#493005cb0fcab009e866ccdbad3c97c512c2bf4b" + integrity sha512-yYkWHhmbhRTWTnWos5HC4GcPQfjlzzCNbM9e/+GXrLuaBXYA3qSDR9f0Vgufd5S8yX81U8jPKp7ZnAjZFMtRnw== + +"@rollup/rollup-win32-x64-gnu@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.0.tgz#47b40294def035268329d5ffd5364347bf726e5f" + integrity sha512-SoTb6lPg25xZlA2ibwQ++ahCCnH+FP0qmEuafMJ4gznZKOlXioKEAeJLgCrqjM98ACziXM9V1amFjICVL4IFoA== + +"@rollup/rollup-win32-x64-msvc@4.62.0": + version "4.62.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.0.tgz#6850434fdb691e9b2408ded9b65ea357bf83636d" + integrity sha512-5L+T1fMX4RIEBoZzT0+sQ0PhTS36NULFmMXtl1TZo44TMAROIMHbZufSOjVWt/Y622BtxgxtaNOokbTDvfsrZA== + +"@tsconfig/node22@^22.0.0": + version "22.0.5" + resolved "https://registry.npmmirror.com/@tsconfig/node22/-/node22-22.0.5.tgz#56be9f34ccffd3aa85f9cc7365ad9765d5829adb" + integrity sha512-hLf2ld+sYN/BtOJjHUWOk568dvjFQkHnLNa6zce25GIH+vxKfvTgm3qpaH6ToF5tu/NN0IH66s+Bb5wElHrLcw== + +"@types/estree@1.0.9": + version "1.0.9" + resolved "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz#cf3f0e876d7bee15a93ab925b82bf570a3904a24" + integrity sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg== + +"@types/node@^22.13.1": + version "22.19.21" + resolved "https://registry.npmmirror.com/@types/node/-/node-22.19.21.tgz#5c9d843ea385b31ee937a9f743443830620a32de" + integrity sha512-VMeFBSCKQKmm2swI2kW51SFusDqekC6q9trBCvJ/JliDchFSuoYYKN7yVNjPthP1HKZcx3U1gI/wTcEBjEFKTA== + dependencies: + undici-types "~6.21.0" + +"@vant/popperjs@^1.3.0": + version "1.3.0" + resolved "https://registry.npmmirror.com/@vant/popperjs/-/popperjs-1.3.0.tgz#e0eff017124b5b2352ef3b36a6df06277f4400f2" + integrity sha512-hB+czUG+aHtjhaEmCJDuXOep0YTZjdlRR+4MSmIFnkCQIxJaXLQdSsR90XWvAI2yvKUI7TCGqR8pQg2RtvkMHw== + +"@vant/use@^1.6.0": + version "1.6.0" + resolved "https://registry.npmmirror.com/@vant/use/-/use-1.6.0.tgz#237df3091617255519552ca311ffdfea9de59001" + integrity sha512-PHHxeAASgiOpSmMjceweIrv2AxDZIkWXyaczksMoWvKV2YAYEhoizRuk/xFnKF+emUIi46TsQ+rvlm/t2BBCfA== + +"@vitejs/plugin-vue@^5.2.4": + version "5.2.4" + resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz#9e8a512eb174bfc2a333ba959bbf9de428d89ad8" + integrity sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA== + +"@volar/language-core@2.4.15": + version "2.4.15" + resolved "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.15.tgz#759d04cb4eab9920560b8bcfa4515d5b08a1b7ce" + integrity sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA== + dependencies: + "@volar/source-map" "2.4.15" + +"@volar/source-map@2.4.15": + version "2.4.15" + resolved "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.15.tgz#18aba09994c0268e59a418f9d738e4a85302781d" + integrity sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg== + +"@volar/typescript@2.4.15": + version "2.4.15" + resolved "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.15.tgz#1445d23f8e4f9ad821b6bfa58cf4a2b980dc5f97" + integrity sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg== + dependencies: + "@volar/language-core" "2.4.15" + path-browserify "^1.0.1" + vscode-uri "^3.0.8" + +"@vue/compiler-core@3.5.38": + version "3.5.38" + resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.38.tgz#fb6679d50a5de198398a1df2ce9d3a49ef8e8072" + integrity sha512-s99aGxWYig9ErHbct27KXEGhrBYlRI6c4MwAgXErOAbX9xiW37/uMa+XUDO69zLz83dng8UUZ70CTOJrLrYrEQ== + dependencies: + "@babel/parser" "^7.29.7" + "@vue/shared" "3.5.38" + entities "^7.0.1" + estree-walker "^2.0.2" + source-map-js "^1.2.1" + +"@vue/compiler-dom@3.5.38", "@vue/compiler-dom@^3.5.0": + version "3.5.38" + resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.38.tgz#10ad73a70399a4c09dedf45ff6a93d42eadc861f" + integrity sha512-JTqp25l8aFfJYF7/KmsXZjAxJz7T+SjmTJLoXVjHtc2BrSgSiW2n9Aem/cWq1OPe68A8JL06B3eVdhlP0H4TVw== + dependencies: + "@vue/compiler-core" "3.5.38" + "@vue/shared" "3.5.38" + +"@vue/compiler-sfc@3.5.38": + version "3.5.38" + resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.38.tgz#2b02036f89c7db0a688534a2eb0d42728c7f09c1" + integrity sha512-DuA2GiZawSEW442iw/9+Fkol8hTgb4Ke5KkhmSry65QA7YuyMbIdy8p0XZRMvNwJdgRz307W8g1CSzdvS4nuNg== + dependencies: + "@babel/parser" "^7.29.7" + "@vue/compiler-core" "3.5.38" + "@vue/compiler-dom" "3.5.38" + "@vue/compiler-ssr" "3.5.38" + "@vue/shared" "3.5.38" + 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.38": + version "3.5.38" + resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.38.tgz#23975aa9643752c78c0625277ffa86f58600300d" + integrity sha512-7s+W5Gc42FGxZMcuwl8H5B29T8BJPMdBT7KHFE+BbAuZ/iTEdTtv7z2XiMjiaUUw4w3ZcCEdHs36RuYJ2VA7bA== + dependencies: + "@vue/compiler-dom" "3.5.38" + "@vue/shared" "3.5.38" + +"@vue/compiler-vue2@^2.7.16": + version "2.7.16" + resolved "https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz#2ba837cbd3f1b33c2bc865fbe1a3b53fb611e249" + integrity sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A== + dependencies: + de-indent "^1.0.2" + he "^1.2.0" + +"@vue/devtools-api@^6.6.3", "@vue/devtools-api@^6.6.4": + version "6.6.4" + resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz#cbe97fe0162b365edc1dba80e173f90492535343" + integrity sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g== + +"@vue/language-core@2.2.12": + version "2.2.12" + resolved "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.12.tgz#d01f7e865f593f968cb65c12a13d8337e65641f0" + integrity sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA== + dependencies: + "@volar/language-core" "2.4.15" + "@vue/compiler-dom" "^3.5.0" + "@vue/compiler-vue2" "^2.7.16" + "@vue/shared" "^3.5.0" + alien-signals "^1.0.3" + minimatch "^9.0.3" + muggle-string "^0.4.1" + path-browserify "^1.0.1" + +"@vue/reactivity@3.5.38": + version "3.5.38" + resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.38.tgz#71cf88b764a6d5334dd27d5ac9f029c81cd4fc34" + integrity sha512-pG6LV/NDNRbKizcUjFFLAfjaL8mcv4DmR9avNcUw2gDHBzZneuS2TWCmp633ynzxz9YYKNeEPK2I8Wraqy2HUQ== + dependencies: + "@vue/shared" "3.5.38" + +"@vue/runtime-core@3.5.38": + version "3.5.38" + resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.38.tgz#26560a876b9c0251e57f7a05f9263e623f244f9c" + integrity sha512-iyW8WVfF1CpCXxncZY5Ei6rSd6oZr5DgEom//fUjRBRl56AXPD+s9ATvukRt77ZFTuYlnVA1bxY+dJB94tWVYw== + dependencies: + "@vue/reactivity" "3.5.38" + "@vue/shared" "3.5.38" + +"@vue/runtime-dom@3.5.38": + version "3.5.38" + resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.38.tgz#7aec70bd013e43166e9ccecd4a1f096fd8ca11fb" + integrity sha512-apX2wt9sdfDshS+a2xueFZLVpt0GkRJZSoPmrW/SA4yzXTznhfcMVW59gr7h4YQeY0vJhdJkk2rsIDwgfFgC5A== + dependencies: + "@vue/reactivity" "3.5.38" + "@vue/runtime-core" "3.5.38" + "@vue/shared" "3.5.38" + csstype "^3.2.3" + +"@vue/server-renderer@3.5.38": + version "3.5.38" + resolved "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.38.tgz#5d24a5305e776a53038fc772fbd9d1205c236588" + integrity sha512-vue8vbf2QlV4quHqzwmJy6dWfmRhP1J8l4wtZg60CL6VoKqcPY2oe7may3+1d9qfpedjK5PRLFqd5k3Isj9mUw== + dependencies: + "@vue/compiler-ssr" "3.5.38" + "@vue/shared" "3.5.38" + +"@vue/shared@3.5.38", "@vue/shared@^3.5.0", "@vue/shared@^3.5.31": + version "3.5.38" + resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.38.tgz#6c4be4defd86cdc35bfa2b7dd45d7b11a5d51101" + integrity sha512-FTW0AFZNaK5/mOqvGBwVfUlNLU38TiQn4+DQgIFUnrBBJQ1crMJ82yeGQLV5jyKFsO8yRukpbuP7x+nRbH6aug== + +"@vue/tsconfig@^0.7.0": + version "0.7.0" + resolved "https://registry.npmmirror.com/@vue/tsconfig/-/tsconfig-0.7.0.tgz#67044c847b7a137b8cbfd6b23104c36dbaf80d1d" + integrity sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg== + +agent-base@6: + version "6.0.2" + resolved "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +alien-signals@^1.0.3: + version "1.0.13" + resolved "https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz#8d6db73462f742ee6b89671fbd8c37d0b1727a7e" + integrity sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@^1.10.0: + version "1.18.0" + resolved "https://registry.npmmirror.com/axios/-/axios-1.18.0.tgz#8a7f8854af280fcaae063272df2ed9f3837d2398" + integrity sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw== + dependencies: + follow-redirects "^1.16.0" + form-data "^4.0.5" + https-proxy-agent "^5.0.1" + proxy-from-env "^2.1.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^2.0.2: + version "2.1.1" + resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.1.1.tgz#c68b1c4111c76aae3a6fba55d496cee10c39dad8" + integrity sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA== + dependencies: + balanced-match "^1.0.0" + +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +csstype@^3.2.3: + version "3.2.3" + resolved "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz#ec48c0f3e993e50648c86da559e2610995cf989a" + integrity sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ== + +dayjs@^1.11.13: + version "1.11.21" + resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.21.tgz#57f87562e62de76f3c704bd2b8d522fc33068eb2" + integrity sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA== + +de-indent@^1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" + integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== + +debug@4: + version "4.4.3" + resolved "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +entities@^7.0.1: + version "7.0.1" + resolved "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz#26e8a88889db63417dcb9a1e79a3f1bc92b5976b" + integrity sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA== + +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.2" + resolved "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz#a2d0b373205724dfa525d23b0c3e1b1ca582c99b" + integrity sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +esbuild@^0.25.0: + version "0.25.12" + resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz#97a1d041f4ab00c2fce2f838d2b9969a2d2a97a5" + integrity sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.12" + "@esbuild/android-arm" "0.25.12" + "@esbuild/android-arm64" "0.25.12" + "@esbuild/android-x64" "0.25.12" + "@esbuild/darwin-arm64" "0.25.12" + "@esbuild/darwin-x64" "0.25.12" + "@esbuild/freebsd-arm64" "0.25.12" + "@esbuild/freebsd-x64" "0.25.12" + "@esbuild/linux-arm" "0.25.12" + "@esbuild/linux-arm64" "0.25.12" + "@esbuild/linux-ia32" "0.25.12" + "@esbuild/linux-loong64" "0.25.12" + "@esbuild/linux-mips64el" "0.25.12" + "@esbuild/linux-ppc64" "0.25.12" + "@esbuild/linux-riscv64" "0.25.12" + "@esbuild/linux-s390x" "0.25.12" + "@esbuild/linux-x64" "0.25.12" + "@esbuild/netbsd-arm64" "0.25.12" + "@esbuild/netbsd-x64" "0.25.12" + "@esbuild/openbsd-arm64" "0.25.12" + "@esbuild/openbsd-x64" "0.25.12" + "@esbuild/openharmony-arm64" "0.25.12" + "@esbuild/sunos-x64" "0.25.12" + "@esbuild/win32-arm64" "0.25.12" + "@esbuild/win32-ia32" "0.25.12" + "@esbuild/win32-x64" "0.25.12" + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +fdir@^6.4.4, fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + +follow-redirects@^1.16.0: + version "1.16.0" + resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" + integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== + +form-data@^4.0.5: + version "4.0.6" + resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.6.tgz#28e864e1b786dbebb68db1f452f9635278665827" + integrity sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ== + 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" + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-intrinsic@^1.2.6: + version "1.3.0" + resolved "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.2, hasown@^2.0.4: + version "2.0.4" + resolved "https://registry.npmmirror.com/hasown/-/hasown-2.0.4.tgz#8c62d8cb90beb2aad5d0a5b67581ad9854c3f003" + integrity sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A== + dependencies: + function-bind "^1.1.2" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.npmmirror.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +https-proxy-agent@^5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +lucide-vue-next@^0.468.0: + version "0.468.0" + resolved "https://registry.npmmirror.com/lucide-vue-next/-/lucide-vue-next-0.468.0.tgz#5e3c84b534f43d5e82fb757b91933cfb4ab24bf9" + integrity sha512-quV/6T8YB1XK0VOEnebg3Byd8Rsan5/m95cvjnuHV4vcS3qEnLAybkrSh0hk3ppavx+V7R1PjNW+mGDvcBdz4A== + +magic-string@^0.30.21: + version "0.30.21" + resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.35: + version "2.1.35" + resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimatch@^9.0.3: + version "9.0.9" + resolved "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.9.tgz#9b0cb9fcb78087f6fd7eababe2511c4d3d60574e" + integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== + dependencies: + brace-expansion "^2.0.2" + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +muggle-string@^0.4.1: + version "0.4.1" + resolved "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz#3b366bd43b32f809dc20659534dd30e7c8a0d328" + integrity sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ== + +nanoid@^3.3.12: + version "3.3.12" + resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.12.tgz#ab3d912e217a6d0a514f00a72a16543a28982c05" + integrity sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ== + +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^4.0.2, picomatch@^4.0.4: + version "4.0.4" + resolved "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589" + integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== + +pinia@^2.3.1: + version "2.3.1" + resolved "https://registry.npmmirror.com/pinia/-/pinia-2.3.1.tgz#54c476675b72f5abcfafa24a7582531ea8c23d94" + integrity sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug== + dependencies: + "@vue/devtools-api" "^6.6.3" + vue-demi "^0.14.10" + +postcss@^8.5.15, postcss@^8.5.3: + version "8.5.15" + resolved "https://registry.npmmirror.com/postcss/-/postcss-8.5.15.tgz#d1eaf677a324e9ec02196da2d3fecf4a0b9a735c" + integrity sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A== + dependencies: + nanoid "^3.3.12" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +proxy-from-env@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz#a7487568adad577cfaaa7e88c49cab3ab3081aba" + integrity sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA== + +rollup@^4.34.9: + version "4.62.0" + resolved "https://registry.npmmirror.com/rollup/-/rollup-4.62.0.tgz#f68956c966f3c4a51dafbafc5d5388553244191b" + integrity sha512-nc72Wgq62I7rtDV4izT5/aaS0zxy3kttkinf9586ApknY3jZO9NYsmtc24fUckA0X7Q2v+ML4a15pdUlV5V/jA== + dependencies: + "@types/estree" "1.0.9" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.62.0" + "@rollup/rollup-android-arm64" "4.62.0" + "@rollup/rollup-darwin-arm64" "4.62.0" + "@rollup/rollup-darwin-x64" "4.62.0" + "@rollup/rollup-freebsd-arm64" "4.62.0" + "@rollup/rollup-freebsd-x64" "4.62.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.62.0" + "@rollup/rollup-linux-arm-musleabihf" "4.62.0" + "@rollup/rollup-linux-arm64-gnu" "4.62.0" + "@rollup/rollup-linux-arm64-musl" "4.62.0" + "@rollup/rollup-linux-loong64-gnu" "4.62.0" + "@rollup/rollup-linux-loong64-musl" "4.62.0" + "@rollup/rollup-linux-ppc64-gnu" "4.62.0" + "@rollup/rollup-linux-ppc64-musl" "4.62.0" + "@rollup/rollup-linux-riscv64-gnu" "4.62.0" + "@rollup/rollup-linux-riscv64-musl" "4.62.0" + "@rollup/rollup-linux-s390x-gnu" "4.62.0" + "@rollup/rollup-linux-x64-gnu" "4.62.0" + "@rollup/rollup-linux-x64-musl" "4.62.0" + "@rollup/rollup-openbsd-x64" "4.62.0" + "@rollup/rollup-openharmony-arm64" "4.62.0" + "@rollup/rollup-win32-arm64-msvc" "4.62.0" + "@rollup/rollup-win32-ia32-msvc" "4.62.0" + "@rollup/rollup-win32-x64-gnu" "4.62.0" + "@rollup/rollup-win32-x64-msvc" "4.62.0" + fsevents "~2.3.2" + +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +tinyglobby@^0.2.13: + version "0.2.17" + resolved "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.17.tgz#562a9a6c9eb2b3b123d39719f9af5bb44fcd7631" + integrity sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.4" + +typescript@^5.7.3: + version "5.9.3" + resolved "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" + integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +vant@^4.9.16: + version "4.9.24" + resolved "https://registry.npmmirror.com/vant/-/vant-4.9.24.tgz#fd8fe7a9d6b632f8f2800d4e2c0cdc45b733ed40" + integrity sha512-tP1A7Vjzv1/B1ljb95Jhv9Q9w6acaaZDJvy6wcKrwGgY0gQZlg+FXLZH/AIKZBE3xvYGDUsv/M7AuGcr/Pqd6A== + dependencies: + "@vant/popperjs" "^1.3.0" + "@vant/use" "^1.6.0" + "@vue/shared" "^3.5.31" + +vite@^6.0.7: + version "6.4.3" + resolved "https://registry.npmmirror.com/vite/-/vite-6.4.3.tgz#85a164db7ce706f2a776812efa2b340f1721858e" + integrity sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A== + dependencies: + esbuild "^0.25.0" + fdir "^6.4.4" + picomatch "^4.0.2" + postcss "^8.5.3" + rollup "^4.34.9" + tinyglobby "^0.2.13" + optionalDependencies: + fsevents "~2.3.3" + +vscode-uri@^3.0.8: + version "3.1.0" + resolved "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz#dd09ec5a66a38b5c3fffc774015713496d14e09c" + integrity sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ== + +vue-demi@^0.14.10: + version "0.14.10" + resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04" + integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg== + +vue-router@^4.5.0: + version "4.6.4" + resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz#a0a9cb9ef811a106d249e4bb9313d286718020d8" + integrity sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg== + dependencies: + "@vue/devtools-api" "^6.6.4" + +vue-tsc@^2.2.0: + version "2.2.12" + resolved "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.2.12.tgz#5f719b08ef7390a763c1a20169ca5c9d09d55688" + integrity sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw== + dependencies: + "@volar/typescript" "2.4.15" + "@vue/language-core" "2.2.12" + +vue@^3.5.13: + version "3.5.38" + resolved "https://registry.npmmirror.com/vue/-/vue-3.5.38.tgz#8a6d52f1768e197545e937920d6c197fe76fc2db" + integrity sha512-vAMKHfImQlYSy0C+PBue4s3ERZ2xGKfgZg5GXAsLInq1dyh2H78ILVP5sK0KPFPVW4kv+OGCIvBEondcjpZp7A== + dependencies: + "@vue/compiler-dom" "3.5.38" + "@vue/compiler-sfc" "3.5.38" + "@vue/runtime-dom" "3.5.38" + "@vue/server-renderer" "3.5.38" + "@vue/shared" "3.5.38"