commit 43a617e5da46b1b35b9071efada407a58d281cc5 Author: andy Date: Tue Jun 16 15:12:54 2026 +0800 员工端h5版本代码提交 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"