diff --git a/.gitignore b/.gitignore index 594b81b5..3504937c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,10 +12,10 @@ dist/ .codex-tmp/ .logs/ outputs/ +reports/ components.d.ts auto-imports.d.ts *.log .DS_Store Thumbs.db - diff --git a/AGENTS.md b/AGENTS.md index ec459c45..ef295bde 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -35,31 +35,54 @@ | 业务 | Admin 入口 | 联查 | |---|---|---| +| 登录、会话与双区域 Token | `modules/auth/`、`core/auth/` | 国内 `auth/`、`iam/`;海外请求客户端再读 `shared/api/AGENTS.md` | +| 启动与懒加载资源恢复 | `main.ts`、`core/routing/navigationRecovery.ts` | 仅识别动态模块/Chunk 资源过期;30 秒内同目标最多自动恢复一次,存在未保存编辑时必须先确认 | | 工作台与指标 | `modules/dashboard/` | 指标所属模块与服务端,不复制领域契约 | | 客户、企业审核、客户统计 | `modules/customers/` | `iam/`、`file/`、`firstleg/customerstatistics/` | | 供应商、国内整柜 | `modules/suppliers/`、`modules/domestic-containers/` | Backend `warehouse/` 及对应 OpenAPI | -| 平台仓库与仓储资源 | `modules/warehouses/`、`modules/warehouse-resources/` | `warehouse/` | +| 平台仓库与仓储资源 | 仓库主档 `modules/warehouses/`,国内资源 `modules/warehouse-resources/` | 全部仓库 ID、类型、状态、地址和能力归国内 `warehouse/`;海外 `warehouse-overseas-service/` 只维护引用同一 warehouseId 的库位、托盘和锁 | | 平台用户、RBAC、导航 | `modules/iam/`、`core/access/`、`core/navigation/` | `auth/`、`iam/`、平台权限契约 | +| 海外 PDA 拣货员与实际收货仓绑定 | `modules/iam/pages/InternalUsersView.vue`、`modules/iam/api/platformIam.ts` | `WAREHOUSE_PICKER` 必须且只能绑定一个 `overseasWarehouseId`;候选来自国内 Warehouse 平台仓库 API 的公共 `OVERSEAS + ACTIVE + RECEIVING` 收货仓,服务端约束在 `iam/`,Claim 与实时校验联查 `common-security/`、`lastleg-service/security/` | | 消息中心 | `modules/notifications/` | Backend `iam/.../notification/`;仅顶部消息中心,不进入左侧菜单 | -| 订单列表、详情与入库费用 | `modules/unified-orders/`、`modules/first-leg-orders/` | `order/`、`firstleg/`、Finance | -| 入库、测量与计价主数据 | `modules/inbounds/`、`fba-pricing/`、`dimension-config/`、`fee-items/` | `firstleg/`、`order/`、`file/`、`integration-service/` | +| 订单列表、详情、商品图片与入库费用 | `modules/unified-orders/`、`modules/first-leg-orders/`;平台商品图片由 `modules/unified-orders/api/unifiedOrders.ts` 按客户与 fileId 下载 | `order/`、`firstleg/`、Finance;图片读取归 `file/` 的 `PlatformProductImageController` | +| 入库、测量与计价主数据 | `modules/inbounds/`、`modules/fba-pricing/`、`modules/dimension-config/`、`modules/fee-items/` | `firstleg/`、`order/`、`file/`、`integration-service/` | | 财务 | `modules/finance/`,继续读该目录 `AGENTS.md` | `finance/`、`firstleg/`、`file/`、`docs/财务管理/` | -| 货柜、排柜与装柜清单 | `modules/container-loading/`、`modules/loading-lists/` | `firstleg/loading/`、`firstleg/split/`、`warehouse/`、`file/` | -| 三期订舱、出仓前船期 | `modules/ocean-bookings/`、`modules/port-schedules/` | `firstleg/oceanbooking/`、`firstleg/portschedule/`;出仓后节点归四期 | +| 货柜、排柜与装柜清单 | `modules/container-loading/`、`modules/loading-lists/`;详情 `pages/ContainerDetailView.vue`,资料/PDA 证据 `components/ContainerOverviewPanel.vue` | 详情承载四类当前资料、PDA 证据、异常历史与整柜国内出仓门禁;Backend `firstleg/loading/`、`firstleg/split/`、`outbound/dispatch/`、`warehouse/`、`file/` | +| 智能装柜按入仓码候选与箱数分配 | `modules/container-loading/pages/SmartLoadingWorkbenchView.vue`、`api/platformContainerLoading.ts` | Backend `firstleg/` 的 `PlatformSmartLoadingController`、`SmartLoadingService`;`GlobalSmartLoadingView.vue` 当前未注册路由,不作为正式入口 | +| 三期订舱、关联候选与出仓前船期 | `modules/ocean-bookings/`、`modules/container-loading/`、`modules/port-schedules/` | `platformOceanBookings.ts` 的 `/link-candidates` 只消费服务端分页;列表 `containerCount` 是柜型需求 `quantity` 总和,不是已关联柜数;Backend `firstleg/oceanbooking/`、`firstleg/portschedule/`,出仓后节点归四期 | | 拖车、报关、国内出仓 | `modules/trucking/`、`modules/customs/`、`modules/outbound-dispatch/` | `firstleg/outbound/dispatch/`、`firstleg/customs/`、`file/` | | 主数据、下载、审计 | `modules/master-data/`、`modules/downloads/`、`modules/audit/` | `warehouse/`、`file/`、`audit-service/` | | 四期海外接柜、入库与库存 | `modules/overseas-warehouse/` | `gateway-overseas/`、`lastleg-service/`、`warehouse-overseas-service/`;不含出库和派送 | | 四期海外采购、卡车、散板 | `modules/overseas-business/` | `gateway-overseas/`、`lastleg-service/` | | 四期合作仓与通用资料 | 合作仓 `modules/warehouses/`;报价/汇率/车辆 `modules/overseas-master-data/` | 国内 `warehouse/`、海外实际资源与服务 | -| 四期国内出仓后船节点 | `modules/port-schedules/`、`modules/ocean-bookings/`、货柜详情 | `firstleg/portschedule/`、`integration-service/`,至目的港到达 | +| 四期国内出仓后船节点 | `modules/port-schedules/`、`modules/ocean-bookings/`、货柜详情 | `firstleg/portschedule/`、`integration-service/`;预计节点只展示不推进实际进度,手工实际节点必须严格向后追加并防重复,十节点标准见 `../../docs/四期/船节点标准化契约.md` | 全量验收按业务从 `../../docs/一期/`、`二期/`、`三期/`、`财务管理/` 选择最小契约;四期开发先读 `../../docs/四期/README.md`。进度、排期或验收状态问题再读取进度表和报告。 +## 四期海外模块内部快速索引 + +| 关键词 | 页面/路由入口 | API 与联查 | +|---|---|---| +| 尾程订单 | `modules/overseas-warehouse/pages/LastMileOrdersView.vue`、`LastMileOrderDetailView.vue` | `modules/overseas-warehouse/api/lastMileOrders.ts`;Backend `lastleg-service/` | +| 入仓单、入仓计划、FBA 预约 | `modules/overseas-warehouse/pages/InboundOrdersView.vue`、`InboundOrderDetailView.vue` | 列表/预约 `modules/overseas-warehouse/api/inboundOrders.ts`,计划列表/详情 `inboundPlans.ts`;Backend `lastleg-service/inboundplan/` | +| 排车查询与智能预排 | `modules/overseas-warehouse/pages/DispatchesView.vue`、`DispatchDetailView.vue`、`components/SmartDispatchDialog.vue` | `modules/overseas-warehouse/api/dispatches.ts`;Backend `lastleg-service/dispatch/`;覆盖详情、候选、草稿柜、托盘即时锁/解锁/整草稿释放和 `pre-arrange`,不据此开放出库编辑、取消、发车、PDA 出库或派送 | +| 海外出库、派送、异常与回访(范围外现存代码) | `pages/OutboundsView.vue`、`DeliveryOrdersView.vue`、`DeliveryOrderDetailView.vue`、`ExceptionOrdersView.vue`、`CustomerVisitsView.vue` 及对应 `api/outbounds.ts`、`deliveryOrders.ts`、`exceptionOrders.ts`、`customerVisits.ts`;当前路由和导航已有注册 | 当前四期契约仍排除海外仓出库、派送及其派生运营页面;不得因代码、菜单、权限或 API 存在而纳入正式范围、验收或继续扩展,只有用户当前明确确认新范围后才能启用其业务语义 | +| 库存余额、库位与流水 | `modules/overseas-warehouse/pages/InventoryView.vue`、`InventoryDetailView.vue`、`InventoryTransactionsView.vue` | `modules/overseas-warehouse/api/inventory.ts`;业务库存归 `lastleg-service/inventory/`,实物资源归 `warehouse-overseas-service/` | +| 托盘、箱唛、产品与换标 | `modules/overseas-warehouse/pages/PalletsView.vue`、`CartonsView.vue`、`ProductsView.vue`、`RelabelOrdersView.vue` 及详情页 | `modules/overseas-warehouse/api/pallets.ts`、`relabelOrders.ts`;路由是否公开以 `modules/overseas-warehouse/routes.ts` 为准 | +| 海外采购 | `modules/overseas-business/pages/PurchaseOrdersView.vue`、详情/编辑页 | `modules/overseas-business/api/platformOverseasBusiness.ts` 的 purchase 方法;Backend `lastleg-service/procurement/` | +| 美国卡车、本土散板 | `modules/overseas-business/pages/TransportOrdersView.vue`、`TransportOrderFormView.vue` | 同一 API 的 us-truck/looseboard 方法;Backend `lastleg-service/trucking/`、`looseboard/` | +| 海外报价、月度汇率、车辆 | `modules/overseas-master-data/pages/OverseasQuotesView.vue`、`ExchangeRatesView.vue`、`VehiclesView.vue` | `modules/overseas-master-data/api/overseasMasterData.ts`;Backend `lastleg-service/masterdata/` | + +- 三个海外模块统一使用 `shared/api/overseasHttp.ts`;页面是否已接真实接口先查对应 `api/` 和挂载测试,不以 `PROTOTYPE_MATRIX.md` 或 `CONTRACT_GAPS.md` 代替当前代码与服务端契约。 + ## 业务、安全与共享装配 - 当前只有平台、客户两级;Admin 不显示“租户”。平台仓库是公共主数据,不与客户绑定;客户筛选不得缩小仓库候选。完整语义见平台客户层级与权限契约。 - 菜单、列表路由和详情只读统一使用 `*:list`,写操作使用独立权限;前端守卫不能替代服务端鉴权。供应商固定使用 `platform:supplier:list`。 +- 平台用户选择 `WAREHOUSE_PICKER` 时必须选择唯一实际海外收货仓,其他角色不得提交 `overseasWarehouseId`;编辑时保留已绑定仓库并按字符串透传长整型 ID,前端校验不能替代 IAM 服务端约束。 +- 国内出仓以真实货柜为原子边界:货柜详情只在装柜完成、全部入仓绑定门禁通过且有写权限时显示确认离仓;成功后由服务端同事务推进全部技术行并幂等创建船节点查询。前端不得逐入仓确认、把拖车状态当阻断门禁或重复追加实际船节点。 - `core/navigation/adminNavigation.ts`、`app/router/index.ts` 和模块 `routes.ts` 是共享装配文件;并行任务不得覆盖总控已确认语义,重叠时保留现有改动并回传总控。 +- `core/routing/navigationRecovery.ts` 只处理已识别的动态 import/Chunk 资源过期;普通路由错误直接提示。自动恢复前保护未保存表单,同一目标 30 秒内不得重复刷新或形成重载循环。 - 认证统一经过 `core/auth/auth.ts`、`shared/api/http.ts` 和 `shared/api/overseasHttp.ts`。登录/刷新原子替换国内、海外 Token,海外 401 统一刷新并最多重放一次;页面不读写 Token 或手工拼 `Authorization`。 - 接入真实接口时删除对应模拟路径,不允许生产逻辑静默回退假数据。客户专属写操作显式选择客户,长整型 ID 按字符串透传,不从本地存储推断。 - 订舱代理、拖车承运商和报关代理提交服务端供应商 ID,从公共供应商列表选择 `ACTIVE` 且类别/范围匹配的记录;参数变化同步检查 API、类型、表单、展示、Mock/Fixture、测试和 OpenAPI。 diff --git a/Dockerfile b/Dockerfile index b3ecd31c..8c6e73e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,8 @@ -# 构建 Vue 静态文件 -FROM node:22-alpine AS build +# 构建 Vue 静态文件。CI 通过构建参数切换到内网基础镜像, +# 本地开发仍可使用 Docker Hub 默认值。 +ARG NODE_IMAGE=node:22-alpine +ARG NGINX_IMAGE=nginx:1.27-alpine +FROM ${NODE_IMAGE} AS build WORKDIR /app @@ -24,7 +27,7 @@ ENV VITE_CLIENT_WEB_URL=${VITE_CLIENT_WEB_URL} RUN pnpm build # 运行阶段:仅保留构建产物和 Nginx,不包含源码或 node_modules。 -FROM nginx:1.27-alpine +FROM ${NGINX_IMAGE} COPY nginx/default.conf.template /etc/nginx/templates/default.conf.template COPY docker/runtime-config.sh /docker-entrypoint.d/40-runtime-config.sh diff --git a/Jenkinsfile b/Jenkinsfile index 6d6848f0..c80b947f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,11 +1,15 @@ pipeline { - agent any + agent { + label "${env.JOB_BASE_NAME?.endsWith('-dev') ? 'java-dev' : 'java-test'}" + } environment { - DEVELOPMENT_SSH_TARGET = 'deploy@172.31.198.8' - DEVELOPMENT_SSH_KEY = '/var/jenkins_home/.ssh/dev_deploy' - DEVELOPMENT_SSH_KNOWN_HOSTS = '/var/jenkins_home/.ssh/known_hosts' - DEVELOPMENT_DEPLOY_DIR = '/opt/firstleg/frontend/admin-web' + DEVELOPMENT_COMPOSE_FILE = 'docker-compose.development.yml' + DEVELOPMENT_COMPOSE_PROJECT = 'admin-web' + REGISTRY_HOST = '172.31.198.7:10082' + REGISTRY_CREDENTIALS = 'gitea-registry-token' + NODE_BASE_IMAGE = '172.31.198.7:10082/java-project/node:22-alpine' + NGINX_BASE_IMAGE = '172.31.198.7:10082/java-project/nginx:1.27-alpine' } options { @@ -27,42 +31,53 @@ pipeline { stage('构建并部署测试前端') { when { expression { env.IS_DEVELOPMENT != 'true' } } steps { - sh ''' - set -eu - docker compose -f docker-compose.test.yml build --pull=false - docker compose -f docker-compose.test.yml up -d --remove-orphans - ''' + withCredentials([usernamePassword(credentialsId: env.REGISTRY_CREDENTIALS, usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASSWORD')]) { + sh ''' + set -eu + export DOCKER_CONFIG="${WORKSPACE}@tmp/docker-auth" + rm -rf "$DOCKER_CONFIG" + mkdir -p "$DOCKER_CONFIG" + cleanup_registry() { + docker logout "$REGISTRY_HOST" >/dev/null 2>&1 || true + rm -rf "$DOCKER_CONFIG" + } + trap cleanup_registry EXIT HUP INT TERM + printf %s "$REGISTRY_PASSWORD" | docker login -u "$REGISTRY_USER" --password-stdin "$REGISTRY_HOST" + docker compose -f docker-compose.test.yml build --pull=false + docker compose -f docker-compose.test.yml up -d --remove-orphans + ''' + } } } stage('构建并部署开发前端') { when { expression { env.IS_DEVELOPMENT == 'true' } } steps { - sh ''' - set -eu - image="admin-web-development:${SOURCE_TAG}" - ssh_args="-i ${DEVELOPMENT_SSH_KEY} -o BatchMode=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=${DEVELOPMENT_SSH_KNOWN_HOSTS} -o ConnectTimeout=10" + withCredentials([usernamePassword(credentialsId: env.REGISTRY_CREDENTIALS, usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASSWORD')]) { + sh ''' + set -eu + export DOCKER_CONFIG="${WORKSPACE}@tmp/docker-auth" + rm -rf "$DOCKER_CONFIG" + mkdir -p "$DOCKER_CONFIG" + cleanup_registry() { + docker logout "$REGISTRY_HOST" >/dev/null 2>&1 || true + rm -rf "$DOCKER_CONFIG" + } + trap cleanup_registry EXIT HUP INT TERM + printf %s "$REGISTRY_PASSWORD" | docker login -u "$REGISTRY_USER" --password-stdin "$REGISTRY_HOST" + image="admin-web-development:${SOURCE_TAG}" - docker build \ - --build-arg VITE_CLIENT_WEB_URL=http://8.163.49.32:9002 \ - -t "$image" . - docker save "$image" | gzip -1 | ssh $ssh_args "$DEVELOPMENT_SSH_TARGET" 'gzip -dc | docker load' - - ssh $ssh_args "$DEVELOPMENT_SSH_TARGET" "install -d -m 750 '$DEVELOPMENT_DEPLOY_DIR'" - scp $ssh_args docker-compose.development.yml \ - "$DEVELOPMENT_SSH_TARGET:$DEVELOPMENT_DEPLOY_DIR/docker-compose.yml.tmp" - ssh $ssh_args "$DEVELOPMENT_SSH_TARGET" \ - "mv -f '$DEVELOPMENT_DEPLOY_DIR/docker-compose.yml.tmp' '$DEVELOPMENT_DEPLOY_DIR/docker-compose.yml'" - - ssh $ssh_args "$DEVELOPMENT_SSH_TARGET" sh -s -- "$DEVELOPMENT_DEPLOY_DIR" "$SOURCE_TAG" <<'REMOTE' - set -eu - cd "$1" - export IMAGE_TAG="$2" - docker compose -f docker-compose.yml up -d --remove-orphans --pull never - docker compose -f docker-compose.yml ps - docker compose -f docker-compose.yml exec -T admin-web wget -qO- http://127.0.0.1/healthz -REMOTE - ''' + docker build \ + --build-arg NODE_IMAGE="$NODE_BASE_IMAGE" \ + --build-arg NGINX_IMAGE="$NGINX_BASE_IMAGE" \ + --build-arg VITE_CLIENT_WEB_URL=http://8.163.49.32:9002 \ + -t "$image" . + export IMAGE_TAG="$SOURCE_TAG" + docker compose -p "$DEVELOPMENT_COMPOSE_PROJECT" -f "$DEVELOPMENT_COMPOSE_FILE" up -d --remove-orphans --pull never + docker compose -p "$DEVELOPMENT_COMPOSE_PROJECT" -f "$DEVELOPMENT_COMPOSE_FILE" ps + docker compose -p "$DEVELOPMENT_COMPOSE_PROJECT" -f "$DEVELOPMENT_COMPOSE_FILE" exec -T admin-web wget -qO- http://127.0.0.1/healthz + ''' + } } } @@ -82,9 +97,7 @@ REMOTE failure { sh ''' if [ "${IS_DEVELOPMENT:-false}" = "true" ]; then - ssh -i "$DEVELOPMENT_SSH_KEY" -o BatchMode=yes -o StrictHostKeyChecking=yes \ - -o UserKnownHostsFile="$DEVELOPMENT_SSH_KNOWN_HOSTS" \ - "$DEVELOPMENT_SSH_TARGET" 'docker logs --tail=100 admin-web-development || true' || true + docker logs --tail=100 admin-web-development || true else docker compose -f docker-compose.test.yml logs --tail=100 || true fi diff --git a/docker-compose.development.yml b/docker-compose.development.yml index 2e126b7c..f39efb2b 100644 --- a/docker-compose.development.yml +++ b/docker-compose.development.yml @@ -4,9 +4,19 @@ services: container_name: admin-web-development restart: unless-stopped ports: - - "9001:80" - extra_hosts: - - "host.docker.internal:host-gateway" + - "127.0.0.1:9001:80" environment: CLIENT_WEB_URL: "http://8.163.49.32:9002" - API_UPSTREAM: "http://host.docker.internal:9000" + API_UPSTREAM: "http://firstleg-development-gateway:9000" + OVERSEAS_API_UPSTREAM: "http://firstleg-development-gateway-overseas:9300" + networks: + - development-backend + - development-overseas-backend + +networks: + development-backend: + external: true + name: firstleg-development-network + development-overseas-backend: + external: true + name: firstleg-development-overseas-network diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 23ad5bdc..c76791f1 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -3,6 +3,9 @@ services: build: context: . dockerfile: Dockerfile + args: + NODE_IMAGE: "${NODE_BASE_IMAGE:-node:22-alpine}" + NGINX_IMAGE: "${NGINX_BASE_IMAGE:-nginx:1.27-alpine}" image: admin-web-test:local container_name: admin-web-test restart: unless-stopped @@ -16,3 +19,4 @@ services: # 测试环境固定走 Docker 宿主机网关,避免 Jenkins 全局环境变量或 # 工作区残留配置把上游覆盖成公网 IP,造成容器回连公网端口失败。 API_UPSTREAM: "http://host.docker.internal:9000" + OVERSEAS_API_UPSTREAM: "http://host.docker.internal:9300" diff --git a/index.html b/index.html index 7a610ec4..be740a3a 100644 --- a/index.html +++ b/index.html @@ -13,3 +13,5 @@ + + diff --git a/nginx/default.conf.template b/nginx/default.conf.template index 4bbf5ed5..3ec922ae 100644 --- a/nginx/default.conf.template +++ b/nginx/default.conf.template @@ -30,6 +30,18 @@ server { proxy_set_header X-Forwarded-Proto $scheme; } + # 海外业务使用独立 Gateway;将浏览器前缀改写为 Gateway 的 /api 前缀。 + location /overseas-api/ { + client_max_body_size 12m; + rewrite ^/overseas-api/(.*)$ /api/$1 break; + proxy_pass ${OVERSEAS_API_UPSTREAM}; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + # HTML must be revalidated on every visit so a new deployment cannot keep # referencing hashed chunks that were removed with the previous image. location = /index.html { diff --git a/node_modules.corrupt/.bin/tsc b/node_modules.corrupt/.bin/tsc new file mode 100644 index 00000000..2184a0ac --- /dev/null +++ b/node_modules.corrupt/.bin/tsc @@ -0,0 +1,43 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") +basedir_win="$basedir" +exe="" +msys="" + +case `uname -a` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir_win=`cygpath -w "$basedir"` + fi + exe=".exe" + msys="true" + ;; + *WSL2*) + if command -v wslpath > /dev/null 2>&1; then + basedir_win="$(wslpath -w "$basedir" 2> /dev/null)" + if [ $? -ne 0 ] || [ -z "$basedir_win" ]; then + basedir_win="$basedir" + else + exe=".exe" + fi + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/typescript@5.9.3/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/typescript@5.9.3/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -n "$exe" ] && [ -x "$basedir/node.exe" ]; then + exec "$basedir/node.exe" "$basedir_win/../typescript/bin/tsc" "$@" +elif [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@" +elif command -v node >/dev/null 2>&1; then + exec node "$basedir/../typescript/bin/tsc" "$@" +elif [ -n "$exe" ] && command -v node.exe >/dev/null 2>&1; then + exec node.exe "$basedir_win/../typescript/bin/tsc" "$@" +else + exec node "$basedir/../typescript/bin/tsc" "$@" +fi +# cmd-shim-target=C:/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/typescript/bin/tsc diff --git a/node_modules.corrupt/.bin/tsc.CMD b/node_modules.corrupt/.bin/tsc.CMD new file mode 100644 index 00000000..b75c712e --- /dev/null +++ b/node_modules.corrupt/.bin/tsc.CMD @@ -0,0 +1,12 @@ +@SETLOCAL +@IF NOT DEFINED NODE_PATH ( + @SET "NODE_PATH=C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\typescript@5.9.3\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules" +) ELSE ( + @SET "NODE_PATH=C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\typescript@5.9.3\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules;%NODE_PATH%" +) +@IF EXIST "%~dp0\node.exe" ( + "%~dp0\node.exe" "%~dp0\..\typescript\bin\tsc" %* +) ELSE ( + @SET PATHEXT=%PATHEXT:;.JS;=;% + node "%~dp0\..\typescript\bin\tsc" %* +) diff --git a/node_modules.corrupt/.bin/tsc.ps1 b/node_modules.corrupt/.bin/tsc.ps1 new file mode 100644 index 00000000..39ded0f1 --- /dev/null +++ b/node_modules.corrupt/.bin/tsc.ps1 @@ -0,0 +1,41 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +$pathsep=":" +$env_node_path=$env:NODE_PATH +$new_node_path="C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\typescript@5.9.3\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" + $pathsep=";" +} else { + $new_node_path="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/typescript@5.9.3/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules" +} +if ([string]::IsNullOrEmpty($env_node_path)) { + $env:NODE_PATH=$new_node_path +} else { + $env:NODE_PATH="$new_node_path$pathsep$env_node_path" +} + +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../typescript/bin/tsc" $args + } else { + & "$basedir/node$exe" "$basedir/../typescript/bin/tsc" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../typescript/bin/tsc" $args + } else { + & "node$exe" "$basedir/../typescript/bin/tsc" $args + } + $ret=$LASTEXITCODE +} +$env:NODE_PATH=$env_node_path +exit $ret diff --git a/node_modules.corrupt/.bin/tsserver b/node_modules.corrupt/.bin/tsserver new file mode 100644 index 00000000..a2267b79 --- /dev/null +++ b/node_modules.corrupt/.bin/tsserver @@ -0,0 +1,43 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") +basedir_win="$basedir" +exe="" +msys="" + +case `uname -a` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir_win=`cygpath -w "$basedir"` + fi + exe=".exe" + msys="true" + ;; + *WSL2*) + if command -v wslpath > /dev/null 2>&1; then + basedir_win="$(wslpath -w "$basedir" 2> /dev/null)" + if [ $? -ne 0 ] || [ -z "$basedir_win" ]; then + basedir_win="$basedir" + else + exe=".exe" + fi + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/typescript@5.9.3/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/typescript@5.9.3/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -n "$exe" ] && [ -x "$basedir/node.exe" ]; then + exec "$basedir/node.exe" "$basedir_win/../typescript/bin/tsserver" "$@" +elif [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@" +elif command -v node >/dev/null 2>&1; then + exec node "$basedir/../typescript/bin/tsserver" "$@" +elif [ -n "$exe" ] && command -v node.exe >/dev/null 2>&1; then + exec node.exe "$basedir_win/../typescript/bin/tsserver" "$@" +else + exec node "$basedir/../typescript/bin/tsserver" "$@" +fi +# cmd-shim-target=C:/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/typescript/bin/tsserver diff --git a/node_modules.corrupt/.bin/tsserver.CMD b/node_modules.corrupt/.bin/tsserver.CMD new file mode 100644 index 00000000..ef44ee18 --- /dev/null +++ b/node_modules.corrupt/.bin/tsserver.CMD @@ -0,0 +1,12 @@ +@SETLOCAL +@IF NOT DEFINED NODE_PATH ( + @SET "NODE_PATH=C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\typescript@5.9.3\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules" +) ELSE ( + @SET "NODE_PATH=C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\typescript@5.9.3\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules;%NODE_PATH%" +) +@IF EXIST "%~dp0\node.exe" ( + "%~dp0\node.exe" "%~dp0\..\typescript\bin\tsserver" %* +) ELSE ( + @SET PATHEXT=%PATHEXT:;.JS;=;% + node "%~dp0\..\typescript\bin\tsserver" %* +) diff --git a/node_modules.corrupt/.bin/tsserver.ps1 b/node_modules.corrupt/.bin/tsserver.ps1 new file mode 100644 index 00000000..77b1c9a7 --- /dev/null +++ b/node_modules.corrupt/.bin/tsserver.ps1 @@ -0,0 +1,41 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +$pathsep=":" +$env_node_path=$env:NODE_PATH +$new_node_path="C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\typescript@5.9.3\node_modules\typescript\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\typescript@5.9.3\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" + $pathsep=";" +} else { + $new_node_path="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/typescript@5.9.3/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules" +} +if ([string]::IsNullOrEmpty($env_node_path)) { + $env:NODE_PATH=$new_node_path +} else { + $env:NODE_PATH="$new_node_path$pathsep$env_node_path" +} + +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../typescript/bin/tsserver" $args + } else { + & "$basedir/node$exe" "$basedir/../typescript/bin/tsserver" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../typescript/bin/tsserver" $args + } else { + & "node$exe" "$basedir/../typescript/bin/tsserver" $args + } + $ret=$LASTEXITCODE +} +$env:NODE_PATH=$env_node_path +exit $ret diff --git a/node_modules.corrupt/.bin/vite b/node_modules.corrupt/.bin/vite new file mode 100644 index 00000000..3ddb91f3 --- /dev/null +++ b/node_modules.corrupt/.bin/vite @@ -0,0 +1,43 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") +basedir_win="$basedir" +exe="" +msys="" + +case `uname -a` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir_win=`cygpath -w "$basedir"` + fi + exe=".exe" + msys="true" + ;; + *WSL2*) + if command -v wslpath > /dev/null 2>&1; then + basedir_win="$(wslpath -w "$basedir" 2> /dev/null)" + if [ $? -ne 0 ] || [ -z "$basedir_win" ]; then + basedir_win="$basedir" + else + exe=".exe" + fi + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vite@8.1.5_@types+node@24.13.3_yaml@2.9.0/node_modules/vite/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vite@8.1.5_@types+node@24.13.3_yaml@2.9.0/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vite@8.1.5_@types+node@24.13.3_yaml@2.9.0/node_modules/vite/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vite@8.1.5_@types+node@24.13.3_yaml@2.9.0/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -n "$exe" ] && [ -x "$basedir/node.exe" ]; then + exec "$basedir/node.exe" "$basedir_win/../vite/bin/vite.js" "$@" +elif [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../vite/bin/vite.js" "$@" +elif command -v node >/dev/null 2>&1; then + exec node "$basedir/../vite/bin/vite.js" "$@" +elif [ -n "$exe" ] && command -v node.exe >/dev/null 2>&1; then + exec node.exe "$basedir_win/../vite/bin/vite.js" "$@" +else + exec node "$basedir/../vite/bin/vite.js" "$@" +fi +# cmd-shim-target=C:/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/vite/bin/vite.js diff --git a/node_modules.corrupt/.bin/vite.CMD b/node_modules.corrupt/.bin/vite.CMD new file mode 100644 index 00000000..fcc8570e --- /dev/null +++ b/node_modules.corrupt/.bin/vite.CMD @@ -0,0 +1,12 @@ +@SETLOCAL +@IF NOT DEFINED NODE_PATH ( + @SET "NODE_PATH=C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vite@8.1.5_@types+node@24.13.3_yaml@2.9.0\node_modules\vite\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vite@8.1.5_@types+node@24.13.3_yaml@2.9.0\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules" +) ELSE ( + @SET "NODE_PATH=C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vite@8.1.5_@types+node@24.13.3_yaml@2.9.0\node_modules\vite\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vite@8.1.5_@types+node@24.13.3_yaml@2.9.0\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules;%NODE_PATH%" +) +@IF EXIST "%~dp0\node.exe" ( + "%~dp0\node.exe" "%~dp0\..\vite\bin\vite.js" %* +) ELSE ( + @SET PATHEXT=%PATHEXT:;.JS;=;% + node "%~dp0\..\vite\bin\vite.js" %* +) diff --git a/node_modules.corrupt/.bin/vite.ps1 b/node_modules.corrupt/.bin/vite.ps1 new file mode 100644 index 00000000..7f321ffb --- /dev/null +++ b/node_modules.corrupt/.bin/vite.ps1 @@ -0,0 +1,41 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +$pathsep=":" +$env_node_path=$env:NODE_PATH +$new_node_path="C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vite@8.1.5_@types+node@24.13.3_yaml@2.9.0\node_modules\vite\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vite@8.1.5_@types+node@24.13.3_yaml@2.9.0\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" + $pathsep=";" +} else { + $new_node_path="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vite@8.1.5_@types+node@24.13.3_yaml@2.9.0/node_modules/vite/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vite@8.1.5_@types+node@24.13.3_yaml@2.9.0/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules" +} +if ([string]::IsNullOrEmpty($env_node_path)) { + $env:NODE_PATH=$new_node_path +} else { + $env:NODE_PATH="$new_node_path$pathsep$env_node_path" +} + +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../vite/bin/vite.js" $args + } else { + & "$basedir/node$exe" "$basedir/../vite/bin/vite.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../vite/bin/vite.js" $args + } else { + & "node$exe" "$basedir/../vite/bin/vite.js" $args + } + $ret=$LASTEXITCODE +} +$env:NODE_PATH=$env_node_path +exit $ret diff --git a/node_modules.corrupt/.bin/vitest b/node_modules.corrupt/.bin/vitest new file mode 100644 index 00000000..8bc82916 --- /dev/null +++ b/node_modules.corrupt/.bin/vitest @@ -0,0 +1,43 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") +basedir_win="$basedir" +exe="" +msys="" + +case `uname -a` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir_win=`cygpath -w "$basedir"` + fi + exe=".exe" + msys="true" + ;; + *WSL2*) + if command -v wslpath > /dev/null 2>&1; then + basedir_win="$(wslpath -w "$basedir" 2> /dev/null)" + if [ $? -ne 0 ] || [ -z "$basedir_win" ]; then + basedir_win="$basedir" + else + exe=".exe" + fi + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e/node_modules/vitest/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e/node_modules/vitest/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -n "$exe" ] && [ -x "$basedir/node.exe" ]; then + exec "$basedir/node.exe" "$basedir_win/../vitest/vitest.mjs" "$@" +elif [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../vitest/vitest.mjs" "$@" +elif command -v node >/dev/null 2>&1; then + exec node "$basedir/../vitest/vitest.mjs" "$@" +elif [ -n "$exe" ] && command -v node.exe >/dev/null 2>&1; then + exec node.exe "$basedir_win/../vitest/vitest.mjs" "$@" +else + exec node "$basedir/../vitest/vitest.mjs" "$@" +fi +# cmd-shim-target=C:/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/vitest/vitest.mjs diff --git a/node_modules.corrupt/.bin/vitest.CMD b/node_modules.corrupt/.bin/vitest.CMD new file mode 100644 index 00000000..9e89fdf5 --- /dev/null +++ b/node_modules.corrupt/.bin/vitest.CMD @@ -0,0 +1,12 @@ +@SETLOCAL +@IF NOT DEFINED NODE_PATH ( + @SET "NODE_PATH=C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e\node_modules\vitest\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules" +) ELSE ( + @SET "NODE_PATH=C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e\node_modules\vitest\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules;%NODE_PATH%" +) +@IF EXIST "%~dp0\node.exe" ( + "%~dp0\node.exe" "%~dp0\..\vitest\vitest.mjs" %* +) ELSE ( + @SET PATHEXT=%PATHEXT:;.JS;=;% + node "%~dp0\..\vitest\vitest.mjs" %* +) diff --git a/node_modules.corrupt/.bin/vitest.ps1 b/node_modules.corrupt/.bin/vitest.ps1 new file mode 100644 index 00000000..827286a5 --- /dev/null +++ b/node_modules.corrupt/.bin/vitest.ps1 @@ -0,0 +1,41 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +$pathsep=":" +$env_node_path=$env:NODE_PATH +$new_node_path="C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e\node_modules\vitest\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" + $pathsep=";" +} else { + $new_node_path="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e/node_modules/vitest/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules" +} +if ([string]::IsNullOrEmpty($env_node_path)) { + $env:NODE_PATH=$new_node_path +} else { + $env:NODE_PATH="$new_node_path$pathsep$env_node_path" +} + +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../vitest/vitest.mjs" $args + } else { + & "$basedir/node$exe" "$basedir/../vitest/vitest.mjs" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../vitest/vitest.mjs" $args + } else { + & "node$exe" "$basedir/../vitest/vitest.mjs" $args + } + $ret=$LASTEXITCODE +} +$env:NODE_PATH=$env_node_path +exit $ret diff --git a/node_modules.corrupt/.bin/vue-tsc b/node_modules.corrupt/.bin/vue-tsc new file mode 100644 index 00000000..07c182b7 --- /dev/null +++ b/node_modules.corrupt/.bin/vue-tsc @@ -0,0 +1,43 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") +basedir_win="$basedir" +exe="" +msys="" + +case `uname -a` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir_win=`cygpath -w "$basedir"` + fi + exe=".exe" + msys="true" + ;; + *WSL2*) + if command -v wslpath > /dev/null 2>&1; then + basedir_win="$(wslpath -w "$basedir" 2> /dev/null)" + if [ $? -ne 0 ] || [ -z "$basedir_win" ]; then + basedir_win="$basedir" + else + exe=".exe" + fi + fi + ;; +esac + +if [ -z "$NODE_PATH" ]; then + export NODE_PATH="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vue-tsc@3.3.8_typescript@5.9.3/node_modules/vue-tsc/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vue-tsc@3.3.8_typescript@5.9.3/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules" +else + export NODE_PATH="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vue-tsc@3.3.8_typescript@5.9.3/node_modules/vue-tsc/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vue-tsc@3.3.8_typescript@5.9.3/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules:$NODE_PATH" +fi +if [ -n "$exe" ] && [ -x "$basedir/node.exe" ]; then + exec "$basedir/node.exe" "$basedir_win/../vue-tsc/bin/vue-tsc.js" "$@" +elif [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../vue-tsc/bin/vue-tsc.js" "$@" +elif command -v node >/dev/null 2>&1; then + exec node "$basedir/../vue-tsc/bin/vue-tsc.js" "$@" +elif [ -n "$exe" ] && command -v node.exe >/dev/null 2>&1; then + exec node.exe "$basedir_win/../vue-tsc/bin/vue-tsc.js" "$@" +else + exec node "$basedir/../vue-tsc/bin/vue-tsc.js" "$@" +fi +# cmd-shim-target=C:/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/vue-tsc/bin/vue-tsc.js diff --git a/node_modules.corrupt/.bin/vue-tsc.CMD b/node_modules.corrupt/.bin/vue-tsc.CMD new file mode 100644 index 00000000..b9797275 --- /dev/null +++ b/node_modules.corrupt/.bin/vue-tsc.CMD @@ -0,0 +1,12 @@ +@SETLOCAL +@IF NOT DEFINED NODE_PATH ( + @SET "NODE_PATH=C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vue-tsc@3.3.8_typescript@5.9.3\node_modules\vue-tsc\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vue-tsc@3.3.8_typescript@5.9.3\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules" +) ELSE ( + @SET "NODE_PATH=C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vue-tsc@3.3.8_typescript@5.9.3\node_modules\vue-tsc\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vue-tsc@3.3.8_typescript@5.9.3\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules;%NODE_PATH%" +) +@IF EXIST "%~dp0\node.exe" ( + "%~dp0\node.exe" "%~dp0\..\vue-tsc\bin\vue-tsc.js" %* +) ELSE ( + @SET PATHEXT=%PATHEXT:;.JS;=;% + node "%~dp0\..\vue-tsc\bin\vue-tsc.js" %* +) diff --git a/node_modules.corrupt/.bin/vue-tsc.ps1 b/node_modules.corrupt/.bin/vue-tsc.ps1 new file mode 100644 index 00000000..62a715cf --- /dev/null +++ b/node_modules.corrupt/.bin/vue-tsc.ps1 @@ -0,0 +1,41 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +$pathsep=":" +$env_node_path=$env:NODE_PATH +$new_node_path="C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vue-tsc@3.3.8_typescript@5.9.3\node_modules\vue-tsc\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\vue-tsc@3.3.8_typescript@5.9.3\node_modules;C:\Users\BY-OY\Desktop\code\chongchong-global-dev\apps\admin-web\node_modules\.pnpm\node_modules" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" + $pathsep=";" +} else { + $new_node_path="/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vue-tsc@3.3.8_typescript@5.9.3/node_modules/vue-tsc/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/vue-tsc@3.3.8_typescript@5.9.3/node_modules:/mnt/c/Users/BY-OY/Desktop/code/chongchong-global-dev/apps/admin-web/node_modules/.pnpm/node_modules" +} +if ([string]::IsNullOrEmpty($env_node_path)) { + $env:NODE_PATH=$new_node_path +} else { + $env:NODE_PATH="$new_node_path$pathsep$env_node_path" +} + +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../vue-tsc/bin/vue-tsc.js" $args + } else { + & "$basedir/node$exe" "$basedir/../vue-tsc/bin/vue-tsc.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../vue-tsc/bin/vue-tsc.js" $args + } else { + & "node$exe" "$basedir/../vue-tsc/bin/vue-tsc.js" $args + } + $ret=$LASTEXITCODE +} +$env:NODE_PATH=$env_node_path +exit $ret diff --git a/node_modules.corrupt/.modules.yaml b/node_modules.corrupt/.modules.yaml new file mode 100644 index 00000000..17e72f22 --- /dev/null +++ b/node_modules.corrupt/.modules.yaml @@ -0,0 +1,743 @@ +{ + "hoistedDependencies": { + "undici-types@7.18.2": { + "undici-types": "private" + }, + "@rolldown/pluginutils@1.0.1": { + "@rolldown/pluginutils": "private" + }, + "@vue/compiler-dom@3.5.40": { + "@vue/compiler-dom": "private" + }, + "js-beautify@1.15.4": { + "js-beautify": "private" + }, + "vue-component-type-helpers@3.3.8": { + "vue-component-type-helpers": "private" + }, + "@vue/server-renderer@3.5.40": { + "@vue/server-renderer": "private" + }, + "follow-redirects@1.16.0(debug@4.4.3)": { + "follow-redirects": "private" + }, + "form-data@4.0.6": { + "form-data": "private" + }, + "https-proxy-agent@5.0.1": { + "https-proxy-agent": "private" + }, + "proxy-from-env@2.1.0": { + "proxy-from-env": "private" + }, + "@ctrl/tinycolor@4.2.0": { + "@ctrl/tinycolor": "private" + }, + "@element-plus/icons-vue@2.3.2(vue@3.5.40(typescript@5.9.3))": { + "@element-plus/icons-vue": "private" + }, + "@floating-ui/dom@1.8.0": { + "@floating-ui/dom": "private" + }, + "@sxzz/popperjs-es@2.11.8": { + "@popperjs/core": "private" + }, + "@types/lodash@4.17.24": { + "@types/lodash": "private" + }, + "@types/lodash-es@4.17.12": { + "@types/lodash-es": "private" + }, + "@vueuse/core@14.3.0(vue@3.5.40(typescript@5.9.3))": { + "@vueuse/core": "private" + }, + "async-validator@4.2.5": { + "async-validator": "private" + }, + "dayjs@1.11.21": { + "dayjs": "private" + }, + "lodash@4.18.1": { + "lodash": "private" + }, + "lodash-es@4.18.1": { + "lodash-es": "private" + }, + "lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.18.1)(lodash@4.18.1)": { + "lodash-unified": "private" + }, + "memoize-one@6.0.0": { + "memoize-one": "private" + }, + "normalize-wheel-es@1.2.0": { + "normalize-wheel-es": "private" + }, + "@asamuzakjp/css-color@5.1.11": { + "@asamuzakjp/css-color": "private" + }, + "@asamuzakjp/dom-selector@7.1.1": { + "@asamuzakjp/dom-selector": "private" + }, + "@bramus/specificity@2.4.2": { + "@bramus/specificity": "private" + }, + "@csstools/css-syntax-patches-for-csstree@1.1.7(css-tree@3.2.1)": { + "@csstools/css-syntax-patches-for-csstree": "private" + }, + "@exodus/bytes@1.15.1": { + "@exodus/bytes": "private" + }, + "css-tree@3.2.1": { + "css-tree": "private" + }, + "data-urls@7.0.0": { + "data-urls": "private" + }, + "decimal.js@10.6.0": { + "decimal.js": "private" + }, + "html-encoding-sniffer@6.0.0": { + "html-encoding-sniffer": "private" + }, + "is-potential-custom-element-name@1.0.1": { + "is-potential-custom-element-name": "private" + }, + "lru-cache@11.5.2": { + "lru-cache": "private" + }, + "parse5@8.0.1": { + "parse5": "private" + }, + "saxes@6.0.0": { + "saxes": "private" + }, + "symbol-tree@3.2.4": { + "symbol-tree": "private" + }, + "tough-cookie@6.0.2": { + "tough-cookie": "private" + }, + "undici@7.29.0": { + "undici": "private" + }, + "w3c-xmlserializer@5.0.0": { + "w3c-xmlserializer": "private" + }, + "webidl-conversions@8.0.1": { + "webidl-conversions": "private" + }, + "whatwg-mimetype@5.0.0": { + "whatwg-mimetype": "private" + }, + "whatwg-url@16.0.1": { + "whatwg-url": "private" + }, + "xml-name-validator@5.0.0": { + "xml-name-validator": "private" + }, + "@vue/devtools-api@8.2.1": { + "@vue/devtools-api": "private" + }, + "nostics@1.2.0": { + "nostics": "private" + }, + "local-pkg@1.2.1": { + "local-pkg": "private" + }, + "magic-string@0.30.21": { + "magic-string": "private" + }, + "picomatch@4.0.5": { + "picomatch": "private" + }, + "unimport@5.7.0": { + "unimport": "private" + }, + "unplugin@2.3.11": { + "unplugin": "private" + }, + "unplugin-utils@0.3.2": { + "unplugin-utils": "private" + }, + "chokidar@5.0.0": { + "chokidar": "private" + }, + "mlly@1.8.2": { + "mlly": "private" + }, + "obug@2.1.4": { + "obug": "private" + }, + "tinyglobby@0.2.17": { + "tinyglobby": "private" + }, + "lightningcss@1.33.0": { + "lightningcss": "private" + }, + "postcss@8.5.23": { + "postcss": "private" + }, + "rolldown@1.1.5": { + "rolldown": "private" + }, + "yaml@2.9.0": { + "yaml": "private" + }, + "@vitest/expect@4.1.10": { + "@vitest/expect": "private" + }, + "@vitest/mocker@4.1.10(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))": { + "@vitest/mocker": "private" + }, + "@vitest/pretty-format@4.1.10": { + "@vitest/pretty-format": "private" + }, + "@vitest/runner@4.1.10": { + "@vitest/runner": "private" + }, + "@vitest/snapshot@4.1.10": { + "@vitest/snapshot": "private" + }, + "@vitest/spy@4.1.10": { + "@vitest/spy": "private" + }, + "@vitest/utils@4.1.10": { + "@vitest/utils": "private" + }, + "es-module-lexer@2.3.1": { + "es-module-lexer": "private" + }, + "expect-type@1.4.0": { + "expect-type": "private" + }, + "pathe@2.0.3": { + "pathe": "private" + }, + "std-env@4.2.0": { + "std-env": "private" + }, + "tinybench@2.9.0": { + "tinybench": "private" + }, + "tinyexec@1.2.4": { + "tinyexec": "private" + }, + "tinyrainbow@3.1.0": { + "tinyrainbow": "private" + }, + "why-is-node-running@2.3.0": { + "why-is-node-running": "private" + }, + "@babel/generator@8.0.0": { + "@babel/generator": "private" + }, + "@vue-macros/common@3.1.4(vue@3.5.40(typescript@5.9.3))": { + "@vue-macros/common": "private" + }, + "ast-walker-scope@0.9.0": { + "ast-walker-scope": "private" + }, + "json5@2.2.3": { + "json5": "private" + }, + "muggle-string@0.4.1": { + "muggle-string": "private" + }, + "scule@1.3.0": { + "scule": "private" + }, + "@vue/compiler-sfc@3.5.40": { + "@vue/compiler-sfc": "private" + }, + "@volar/typescript@2.4.28": { + "@volar/typescript": "private" + }, + "@vue/language-core@3.3.8": { + "@vue/language-core": "private" + }, + "@vue/runtime-dom@3.5.40": { + "@vue/runtime-dom": "private" + }, + "@vue/shared@3.5.40": { + "@vue/shared": "private" + }, + "@asamuzakjp/generational-cache@1.0.1": { + "@asamuzakjp/generational-cache": "private" + }, + "@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)": { + "@csstools/css-calc": "private" + }, + "@csstools/css-color-parser@4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)": { + "@csstools/css-color-parser": "private" + }, + "@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)": { + "@csstools/css-parser-algorithms": "private" + }, + "@csstools/css-tokenizer@4.0.0": { + "@csstools/css-tokenizer": "private" + }, + "@asamuzakjp/nwsapi@2.3.9": { + "@asamuzakjp/nwsapi": "private" + }, + "bidi-js@1.0.3": { + "bidi-js": "private" + }, + "@babel/parser@8.0.4": { + "@babel/parser": "private" + }, + "@babel/types@8.0.4": { + "@babel/types": "private" + }, + "@jridgewell/gen-mapping@0.3.13": { + "@jridgewell/gen-mapping": "private" + }, + "@jridgewell/trace-mapping@0.3.31": { + "@jridgewell/trace-mapping": "private" + }, + "@types/jsesc@2.5.1": { + "@types/jsesc": "private" + }, + "jsesc@3.1.0": { + "jsesc": "private" + }, + "@floating-ui/core@1.8.0": { + "@floating-ui/core": "private" + }, + "@floating-ui/utils@0.2.12": { + "@floating-ui/utils": "private" + }, + "@standard-schema/spec@1.1.0": { + "@standard-schema/spec": "private" + }, + "@types/chai@5.2.3": { + "@types/chai": "private" + }, + "chai@6.2.2": { + "chai": "private" + }, + "estree-walker@3.0.3": { + "estree-walker": "private" + }, + "convert-source-map@2.0.0": { + "convert-source-map": "private" + }, + "@volar/language-core@2.4.28": { + "@volar/language-core": "private" + }, + "path-browserify@1.0.1": { + "path-browserify": "private" + }, + "vscode-uri@3.1.0": { + "vscode-uri": "private" + }, + "@vue/compiler-core@3.5.40": { + "@vue/compiler-core": "private" + }, + "@vue/compiler-ssr@3.5.40": { + "@vue/compiler-ssr": "private" + }, + "source-map-js@1.2.1": { + "source-map-js": "private" + }, + "@vue/devtools-kit@8.2.1": { + "@vue/devtools-kit": "private" + }, + "alien-signals@3.2.1": { + "alien-signals": "private" + }, + "@vue/reactivity@3.5.40": { + "@vue/reactivity": "private" + }, + "@vue/runtime-core@3.5.40": { + "@vue/runtime-core": "private" + }, + "csstype@3.2.3": { + "csstype": "private" + }, + "ast-kit@2.2.0": { + "ast-kit": "private" + }, + "magic-string-ast@1.0.3": { + "magic-string-ast": "private" + }, + "@types/web-bluetooth@0.0.21": { + "@types/web-bluetooth": "private" + }, + "@vueuse/metadata@14.3.0": { + "@vueuse/metadata": "private" + }, + "@vueuse/shared@14.3.0(vue@3.5.40(typescript@5.9.3))": { + "@vueuse/shared": "private" + }, + "readdirp@5.0.0": { + "readdirp": "private" + }, + "mdn-data@2.27.1": { + "mdn-data": "private" + }, + "debug@4.4.3": { + "debug": "private" + }, + "asynckit@0.4.0": { + "asynckit": "private" + }, + "combined-stream@1.0.8": { + "combined-stream": "private" + }, + "es-set-tostringtag@2.1.0": { + "es-set-tostringtag": "private" + }, + "hasown@2.0.4": { + "hasown": "private" + }, + "mime-types@2.1.35": { + "mime-types": "private" + }, + "agent-base@6.0.2": { + "agent-base": "private" + }, + "config-chain@1.1.13": { + "config-chain": "private" + }, + "editorconfig@1.0.7": { + "editorconfig": "private" + }, + "glob@10.5.0": { + "glob": "private" + }, + "js-cookie@3.0.8": { + "js-cookie": "private" + }, + "nopt@7.2.1": { + "nopt": "private" + }, + "detect-libc@2.1.2": { + "detect-libc": "private" + }, + "lightningcss-win32-x64-msvc@1.33.0": { + "lightningcss-win32-x64-msvc": "private" + }, + "pkg-types@2.3.1": { + "pkg-types": "private" + }, + "quansync@0.2.11": { + "quansync": "private" + }, + "@jridgewell/sourcemap-codec@1.5.5": { + "@jridgewell/sourcemap-codec": "private" + }, + "acorn@8.17.0": { + "acorn": "private" + }, + "ufo@1.6.4": { + "ufo": "private" + }, + "entities@8.0.0": { + "entities": "private" + }, + "nanoid@3.3.16": { + "nanoid": "private" + }, + "picocolors@1.1.1": { + "picocolors": "private" + }, + "@oxc-project/types@0.139.0": { + "@oxc-project/types": "private" + }, + "@rolldown/binding-win32-x64-msvc@1.1.5": { + "@rolldown/binding-win32-x64-msvc": "private" + }, + "xmlchars@2.2.0": { + "xmlchars": "private" + }, + "fdir@6.5.0(picomatch@4.0.5)": { + "fdir": "private" + }, + "tldts@7.4.9": { + "tldts": "private" + }, + "escape-string-regexp@5.0.0": { + "escape-string-regexp": "private" + }, + "strip-literal@3.1.0": { + "strip-literal": "private" + }, + "@jridgewell/remapping@2.3.5": { + "@jridgewell/remapping": "private" + }, + "webpack-virtual-modules@0.6.2": { + "webpack-virtual-modules": "private" + }, + "tr46@6.0.0": { + "tr46": "private" + }, + "siginfo@2.0.0": { + "siginfo": "private" + }, + "stackback@0.0.2": { + "stackback": "private" + }, + "@babel/helper-string-parser@8.0.0": { + "@babel/helper-string-parser": "private" + }, + "@babel/helper-validator-identifier@8.0.4": { + "@babel/helper-validator-identifier": "private" + }, + "@csstools/color-helpers@6.1.0": { + "@csstools/color-helpers": "private" + }, + "@types/deep-eql@4.0.2": { + "@types/deep-eql": "private" + }, + "assertion-error@2.0.1": { + "assertion-error": "private" + }, + "@volar/source-map@2.4.28": { + "@volar/source-map": "private" + }, + "@vue/devtools-shared@8.2.1": { + "@vue/devtools-shared": "private" + }, + "birpc@2.9.0": { + "birpc": "private" + }, + "hookable@5.5.3": { + "hookable": "private" + }, + "perfect-debounce@2.1.0": { + "perfect-debounce": "private" + }, + "require-from-string@2.0.2": { + "require-from-string": "private" + }, + "delayed-stream@1.0.0": { + "delayed-stream": "private" + }, + "ini@1.3.8": { + "ini": "private" + }, + "proto-list@1.2.4": { + "proto-list": "private" + }, + "ms@2.1.3": { + "ms": "private" + }, + "@one-ini/wasm@0.1.1": { + "@one-ini/wasm": "private" + }, + "commander@10.0.1": { + "commander": "private" + }, + "minimatch@9.0.9": { + "minimatch": "private" + }, + "semver@7.8.5": { + "semver": "private" + }, + "es-errors@1.3.0": { + "es-errors": "private" + }, + "get-intrinsic@1.3.0": { + "get-intrinsic": "private" + }, + "has-tostringtag@1.0.2": { + "has-tostringtag": "private" + }, + "@types/estree@1.0.9": { + "@types/estree": "private" + }, + "foreground-child@3.3.1": { + "foreground-child": "private" + }, + "jackspeak@3.4.3": { + "jackspeak": "private" + }, + "minipass@7.1.3": { + "minipass": "private" + }, + "package-json-from-dist@1.0.1": { + "package-json-from-dist": "private" + }, + "path-scurry@1.11.1": { + "path-scurry": "private" + }, + "function-bind@1.1.2": { + "function-bind": "private" + }, + "mime-db@1.52.0": { + "mime-db": "private" + }, + "abbrev@2.0.0": { + "abbrev": "private" + }, + "confbox@0.1.8": { + "confbox": "private" + }, + "exsolve@1.1.0": { + "exsolve": "private" + }, + "js-tokens@9.0.1": { + "js-tokens": "private" + }, + "tldts-core@7.4.9": { + "tldts-core": "private" + }, + "punycode@2.3.1": { + "punycode": "private" + }, + "@jridgewell/resolve-uri@3.1.2": { + "@jridgewell/resolve-uri": "private" + }, + "cross-spawn@7.0.6": { + "cross-spawn": "private" + }, + "signal-exit@4.1.0": { + "signal-exit": "private" + }, + "call-bind-apply-helpers@1.0.2": { + "call-bind-apply-helpers": "private" + }, + "es-define-property@1.0.1": { + "es-define-property": "private" + }, + "es-object-atoms@1.1.2": { + "es-object-atoms": "private" + }, + "get-proto@1.0.1": { + "get-proto": "private" + }, + "gopd@1.2.0": { + "gopd": "private" + }, + "has-symbols@1.1.0": { + "has-symbols": "private" + }, + "math-intrinsics@1.1.0": { + "math-intrinsics": "private" + }, + "@isaacs/cliui@8.0.2": { + "@isaacs/cliui": "private" + }, + "@pkgjs/parseargs@0.11.0": { + "@pkgjs/parseargs": "private" + }, + "brace-expansion@2.1.2": { + "brace-expansion": "private" + }, + "string-width@5.1.2": { + "string-width": "private" + }, + "string-width@4.2.3": { + "string-width-cjs": "private" + }, + "strip-ansi@7.2.0": { + "strip-ansi": "private" + }, + "strip-ansi@6.0.1": { + "strip-ansi-cjs": "private" + }, + "wrap-ansi@8.1.0": { + "wrap-ansi": "private" + }, + "wrap-ansi@7.0.0": { + "wrap-ansi-cjs": "private" + }, + "balanced-match@1.0.2": { + "balanced-match": "private" + }, + "path-key@3.1.1": { + "path-key": "private" + }, + "shebang-command@2.0.0": { + "shebang-command": "private" + }, + "which@2.0.2": { + "which": "private" + }, + "dunder-proto@1.0.1": { + "dunder-proto": "private" + }, + "shebang-regex@3.0.0": { + "shebang-regex": "private" + }, + "emoji-regex@8.0.0": { + "emoji-regex": "private" + }, + "is-fullwidth-code-point@3.0.0": { + "is-fullwidth-code-point": "private" + }, + "eastasianwidth@0.2.0": { + "eastasianwidth": "private" + }, + "ansi-regex@5.0.1": { + "ansi-regex": "private" + }, + "isexe@2.0.0": { + "isexe": "private" + }, + "ansi-styles@4.3.0": { + "ansi-styles": "private" + }, + "color-convert@2.0.1": { + "color-convert": "private" + }, + "color-name@1.1.4": { + "color-name": "private" + } + }, + "hoistPattern": [ + "*" + ], + "included": { + "dependencies": true, + "devDependencies": true, + "optionalDependencies": true + }, + "injectedDeps": {}, + "layoutVersion": 5, + "nodeLinker": "isolated", + "packageManager": "pnpm@11.17.0", + "pendingBuilds": [], + "publicHoistPattern": [], + "prunedAt": "Thu, 20 Aug 2026 06:47:32 GMT", + "registries": { + "default": "https://registry.npmjs.org/", + "@jsr": "https://npm.jsr.io/" + }, + "skipped": [ + "@emnapi/core@1.11.1", + "@emnapi/runtime@1.11.1", + "@emnapi/wasi-threads@1.2.2", + "@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)", + "@rolldown/binding-android-arm64@1.1.5", + "@rolldown/binding-darwin-arm64@1.1.5", + "@rolldown/binding-darwin-x64@1.1.5", + "@rolldown/binding-freebsd-x64@1.1.5", + "@rolldown/binding-linux-arm-gnueabihf@1.1.5", + "@rolldown/binding-linux-arm64-gnu@1.1.5", + "@rolldown/binding-linux-arm64-musl@1.1.5", + "@rolldown/binding-linux-ppc64-gnu@1.1.5", + "@rolldown/binding-linux-s390x-gnu@1.1.5", + "@rolldown/binding-linux-x64-gnu@1.1.5", + "@rolldown/binding-linux-x64-musl@1.1.5", + "@rolldown/binding-openharmony-arm64@1.1.5", + "@rolldown/binding-wasm32-wasi@1.1.5", + "@rolldown/binding-win32-arm64-msvc@1.1.5", + "@tybys/wasm-util@0.10.3", + "fsevents@2.3.3", + "lightningcss-android-arm64@1.33.0", + "lightningcss-darwin-arm64@1.33.0", + "lightningcss-darwin-x64@1.33.0", + "lightningcss-freebsd-x64@1.33.0", + "lightningcss-linux-arm-gnueabihf@1.33.0", + "lightningcss-linux-arm64-gnu@1.33.0", + "lightningcss-linux-arm64-musl@1.33.0", + "lightningcss-linux-x64-gnu@1.33.0", + "lightningcss-linux-x64-musl@1.33.0", + "lightningcss-win32-arm64-msvc@1.33.0", + "tslib@2.8.1" + ], + "storeDir": "C:\\Users\\BY-OY\\AppData\\Local\\pnpm\\store\\v11", + "virtualStoreDir": "C:\\Users\\BY-OY\\Desktop\\code\\chongchong-global-dev\\apps\\admin-web\\node_modules\\.pnpm", + "virtualStoreDirMaxLength": 60 +} \ No newline at end of file diff --git a/node_modules.corrupt/.package-map.json b/node_modules.corrupt/.package-map.json new file mode 100644 index 00000000..55036b2d --- /dev/null +++ b/node_modules.corrupt/.package-map.json @@ -0,0 +1 @@ +{"packages":{".":{"url":"..","dependencies":{"@chongchong/admin-web":".","@chongchong/shared":"shared","@lucide/vue":"@lucide/vue@1.27.0(vue@3.5.40(typescript@5.9.3))","@types/node":"@types/node@24.13.3","@types/sortablejs":"@types/sortablejs@1.15.9","@vitejs/plugin-vue":"@vitejs/plugin-vue@6.0.8(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3))","@vue/test-utils":"@vue/test-utils@2.4.11(@vue/compiler-dom@3.5.40)(@vue/server-renderer@3.5.40)(vue@3.5.40(typescript@5.9.3))","axios":"axios@1.18.1(debug@4.4.3)","element-plus":"element-plus@2.14.3(vue@3.5.40(typescript@5.9.3))","jsdom":"jsdom@29.1.1","pinia":"pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@5.9.3)(vue@3.5.40(typescript@5.9.3))","sortablejs":"sortablejs@1.15.7","typescript":"typescript@5.9.3","unplugin-auto-import":"unplugin-auto-import@21.0.0(@vueuse/core@14.3.0(vue@3.5.40(typescript@5.9.3)))","unplugin-vue-components":"unplugin-vue-components@32.1.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3))","vite":"vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)","vitest":"vitest@4.1.10(@types/node@24.13.3)(jsdom@29.1.1)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))","vue":"vue@3.5.40(typescript@5.9.3)","vue-router":"vue-router@5.2.0(@vue/compiler-sfc@3.5.40)(pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@5.9.3)(vue@3.5.40(typescript@5.9.3)))(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3))","vue-tsc":"vue-tsc@3.3.8(typescript@5.9.3)"}},"@asamuzakjp/css-color@5.1.11":{"url":"./.pnpm/@asamuzakjp+css-color@5.1.11/node_modules/@asamuzakjp/css-color","dependencies":{"@asamuzakjp/css-color":"@asamuzakjp/css-color@5.1.11","@asamuzakjp/generational-cache":"@asamuzakjp/generational-cache@1.0.1","@csstools/css-calc":"@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)","@csstools/css-color-parser":"@csstools/css-color-parser@4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)","@csstools/css-parser-algorithms":"@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)","@csstools/css-tokenizer":"@csstools/css-tokenizer@4.0.0"}},"@asamuzakjp/dom-selector@7.1.1":{"url":"./.pnpm/@asamuzakjp+dom-selector@7.1.1/node_modules/@asamuzakjp/dom-selector","dependencies":{"@asamuzakjp/dom-selector":"@asamuzakjp/dom-selector@7.1.1","@asamuzakjp/generational-cache":"@asamuzakjp/generational-cache@1.0.1","@asamuzakjp/nwsapi":"@asamuzakjp/nwsapi@2.3.9","bidi-js":"bidi-js@1.0.3","css-tree":"css-tree@3.2.1","is-potential-custom-element-name":"is-potential-custom-element-name@1.0.1"}},"@asamuzakjp/generational-cache@1.0.1":{"url":"./.pnpm/@asamuzakjp+generational-cache@1.0.1/node_modules/@asamuzakjp/generational-cache","dependencies":{"@asamuzakjp/generational-cache":"@asamuzakjp/generational-cache@1.0.1"}},"@asamuzakjp/nwsapi@2.3.9":{"url":"./.pnpm/@asamuzakjp+nwsapi@2.3.9/node_modules/@asamuzakjp/nwsapi","dependencies":{"@asamuzakjp/nwsapi":"@asamuzakjp/nwsapi@2.3.9"}},"@babel/generator@8.0.0":{"url":"./.pnpm/@babel+generator@8.0.0/node_modules/@babel/generator","dependencies":{"@babel/generator":"@babel/generator@8.0.0","@babel/parser":"@babel/parser@8.0.4","@babel/types":"@babel/types@8.0.4","@jridgewell/gen-mapping":"@jridgewell/gen-mapping@0.3.13","@jridgewell/trace-mapping":"@jridgewell/trace-mapping@0.3.31","@types/jsesc":"@types/jsesc@2.5.1","jsesc":"jsesc@3.1.0"}},"@babel/helper-string-parser@7.29.7":{"url":"./.pnpm/@babel+helper-string-parser@7.29.7/node_modules/@babel/helper-string-parser","dependencies":{"@babel/helper-string-parser":"@babel/helper-string-parser@7.29.7"}},"@babel/helper-string-parser@8.0.0":{"url":"./.pnpm/@babel+helper-string-parser@8.0.0/node_modules/@babel/helper-string-parser","dependencies":{"@babel/helper-string-parser":"@babel/helper-string-parser@8.0.0"}},"@babel/helper-validator-identifier@7.29.7":{"url":"./.pnpm/@babel+helper-validator-identifier@7.29.7/node_modules/@babel/helper-validator-identifier","dependencies":{"@babel/helper-validator-identifier":"@babel/helper-validator-identifier@7.29.7"}},"@babel/helper-validator-identifier@8.0.4":{"url":"./.pnpm/@babel+helper-validator-identifier@8.0.4/node_modules/@babel/helper-validator-identifier","dependencies":{"@babel/helper-validator-identifier":"@babel/helper-validator-identifier@8.0.4"}},"@babel/parser@7.29.7":{"url":"./.pnpm/@babel+parser@7.29.7/node_modules/@babel/parser","dependencies":{"@babel/parser":"@babel/parser@7.29.7","@babel/types":"@babel/types@7.29.7"}},"@babel/parser@8.0.4":{"url":"./.pnpm/@babel+parser@8.0.4/node_modules/@babel/parser","dependencies":{"@babel/parser":"@babel/parser@8.0.4","@babel/types":"@babel/types@8.0.4"}},"@babel/types@7.29.7":{"url":"./.pnpm/@babel+types@7.29.7/node_modules/@babel/types","dependencies":{"@babel/helper-string-parser":"@babel/helper-string-parser@7.29.7","@babel/helper-validator-identifier":"@babel/helper-validator-identifier@7.29.7","@babel/types":"@babel/types@7.29.7"}},"@babel/types@8.0.4":{"url":"./.pnpm/@babel+types@8.0.4/node_modules/@babel/types","dependencies":{"@babel/helper-string-parser":"@babel/helper-string-parser@8.0.0","@babel/helper-validator-identifier":"@babel/helper-validator-identifier@8.0.4","@babel/types":"@babel/types@8.0.4"}},"@bramus/specificity@2.4.2":{"url":"./.pnpm/@bramus+specificity@2.4.2/node_modules/@bramus/specificity","dependencies":{"@bramus/specificity":"@bramus/specificity@2.4.2","css-tree":"css-tree@3.2.1"}},"@csstools/color-helpers@6.1.0":{"url":"./.pnpm/@csstools+color-helpers@6.1.0/node_modules/@csstools/color-helpers","dependencies":{"@csstools/color-helpers":"@csstools/color-helpers@6.1.0"}},"@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)":{"url":"./.pnpm/@csstools+css-calc@3.3.0_@c_4dbc5b05e8dbfe1f32044d24572a798f/node_modules/@csstools/css-calc","dependencies":{"@csstools/css-calc":"@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)","@csstools/css-parser-algorithms":"@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)","@csstools/css-tokenizer":"@csstools/css-tokenizer@4.0.0"}},"@csstools/css-color-parser@4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)":{"url":"./.pnpm/@csstools+css-color-parser@_effeb5cd45da44eb6c8c04960cd886da/node_modules/@csstools/css-color-parser","dependencies":{"@csstools/color-helpers":"@csstools/color-helpers@6.1.0","@csstools/css-calc":"@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)","@csstools/css-color-parser":"@csstools/css-color-parser@4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)","@csstools/css-parser-algorithms":"@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)","@csstools/css-tokenizer":"@csstools/css-tokenizer@4.0.0"}},"@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)":{"url":"./.pnpm/@csstools+css-parser-algori_b9ad755ebdc6dc54abc499015fcb7df0/node_modules/@csstools/css-parser-algorithms","dependencies":{"@csstools/css-parser-algorithms":"@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)","@csstools/css-tokenizer":"@csstools/css-tokenizer@4.0.0"}},"@csstools/css-syntax-patches-for-csstree@1.1.7(css-tree@3.2.1)":{"url":"./.pnpm/@csstools+css-syntax-patche_bc9c53d3df72bff55db1794ca8fff262/node_modules/@csstools/css-syntax-patches-for-csstree","dependencies":{"@csstools/css-syntax-patches-for-csstree":"@csstools/css-syntax-patches-for-csstree@1.1.7(css-tree@3.2.1)","css-tree":"css-tree@3.2.1"}},"@csstools/css-tokenizer@4.0.0":{"url":"./.pnpm/@csstools+css-tokenizer@4.0.0/node_modules/@csstools/css-tokenizer","dependencies":{"@csstools/css-tokenizer":"@csstools/css-tokenizer@4.0.0"}},"@ctrl/tinycolor@4.2.0":{"url":"./.pnpm/@ctrl+tinycolor@4.2.0/node_modules/@ctrl/tinycolor","dependencies":{"@ctrl/tinycolor":"@ctrl/tinycolor@4.2.0"}},"@element-plus/icons-vue@2.3.2(vue@3.5.40(typescript@5.9.3))":{"url":"./.pnpm/@element-plus+icons-vue@2.3.2_vue@3.5.40_typescript@5.9.3_/node_modules/@element-plus/icons-vue","dependencies":{"@element-plus/icons-vue":"@element-plus/icons-vue@2.3.2(vue@3.5.40(typescript@5.9.3))","vue":"vue@3.5.40(typescript@5.9.3)"}},"@emnapi/core@1.11.1":{"url":"./.pnpm/@emnapi+core@1.11.1/node_modules/@emnapi/core","dependencies":{"@emnapi/core":"@emnapi/core@1.11.1","@emnapi/wasi-threads":"@emnapi/wasi-threads@1.2.2","tslib":"tslib@2.8.1"}},"@emnapi/runtime@1.11.1":{"url":"./.pnpm/@emnapi+runtime@1.11.1/node_modules/@emnapi/runtime","dependencies":{"@emnapi/runtime":"@emnapi/runtime@1.11.1","tslib":"tslib@2.8.1"}},"@emnapi/wasi-threads@1.2.2":{"url":"./.pnpm/@emnapi+wasi-threads@1.2.2/node_modules/@emnapi/wasi-threads","dependencies":{"@emnapi/wasi-threads":"@emnapi/wasi-threads@1.2.2","tslib":"tslib@2.8.1"}},"@exodus/bytes@1.15.1":{"url":"./.pnpm/@exodus+bytes@1.15.1/node_modules/@exodus/bytes","dependencies":{"@exodus/bytes":"@exodus/bytes@1.15.1"}},"@floating-ui/core@1.8.0":{"url":"./.pnpm/@floating-ui+core@1.8.0/node_modules/@floating-ui/core","dependencies":{"@floating-ui/core":"@floating-ui/core@1.8.0","@floating-ui/utils":"@floating-ui/utils@0.2.12"}},"@floating-ui/dom@1.8.0":{"url":"./.pnpm/@floating-ui+dom@1.8.0/node_modules/@floating-ui/dom","dependencies":{"@floating-ui/core":"@floating-ui/core@1.8.0","@floating-ui/dom":"@floating-ui/dom@1.8.0","@floating-ui/utils":"@floating-ui/utils@0.2.12"}},"@floating-ui/utils@0.2.12":{"url":"./.pnpm/@floating-ui+utils@0.2.12/node_modules/@floating-ui/utils","dependencies":{"@floating-ui/utils":"@floating-ui/utils@0.2.12"}},"@isaacs/cliui@8.0.2":{"url":"./.pnpm/@isaacs+cliui@8.0.2/node_modules/@isaacs/cliui","dependencies":{"@isaacs/cliui":"@isaacs/cliui@8.0.2","string-width":"string-width@5.1.2","string-width-cjs":"string-width@4.2.3","strip-ansi":"strip-ansi@7.2.0","strip-ansi-cjs":"strip-ansi@6.0.1","wrap-ansi":"wrap-ansi@8.1.0","wrap-ansi-cjs":"wrap-ansi@7.0.0"}},"@jridgewell/gen-mapping@0.3.13":{"url":"./.pnpm/@jridgewell+gen-mapping@0.3.13/node_modules/@jridgewell/gen-mapping","dependencies":{"@jridgewell/gen-mapping":"@jridgewell/gen-mapping@0.3.13","@jridgewell/sourcemap-codec":"@jridgewell/sourcemap-codec@1.5.5","@jridgewell/trace-mapping":"@jridgewell/trace-mapping@0.3.31"}},"@jridgewell/remapping@2.3.5":{"url":"./.pnpm/@jridgewell+remapping@2.3.5/node_modules/@jridgewell/remapping","dependencies":{"@jridgewell/gen-mapping":"@jridgewell/gen-mapping@0.3.13","@jridgewell/remapping":"@jridgewell/remapping@2.3.5","@jridgewell/trace-mapping":"@jridgewell/trace-mapping@0.3.31"}},"@jridgewell/resolve-uri@3.1.2":{"url":"./.pnpm/@jridgewell+resolve-uri@3.1.2/node_modules/@jridgewell/resolve-uri","dependencies":{"@jridgewell/resolve-uri":"@jridgewell/resolve-uri@3.1.2"}},"@jridgewell/sourcemap-codec@1.5.5":{"url":"./.pnpm/@jridgewell+sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec","dependencies":{"@jridgewell/sourcemap-codec":"@jridgewell/sourcemap-codec@1.5.5"}},"@jridgewell/trace-mapping@0.3.31":{"url":"./.pnpm/@jridgewell+trace-mapping@0.3.31/node_modules/@jridgewell/trace-mapping","dependencies":{"@jridgewell/resolve-uri":"@jridgewell/resolve-uri@3.1.2","@jridgewell/sourcemap-codec":"@jridgewell/sourcemap-codec@1.5.5","@jridgewell/trace-mapping":"@jridgewell/trace-mapping@0.3.31"}},"@lucide/vue@1.27.0(vue@3.5.40(typescript@5.9.3))":{"url":"./.pnpm/@lucide+vue@1.27.0_vue@3.5.40_typescript@5.9.3_/node_modules/@lucide/vue","dependencies":{"@lucide/vue":"@lucide/vue@1.27.0(vue@3.5.40(typescript@5.9.3))","vue":"vue@3.5.40(typescript@5.9.3)"}},"@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)":{"url":"./.pnpm/@napi-rs+wasm-runtime@1.1.6_4cb1ecf19345c264451f9776fa68df68/node_modules/@napi-rs/wasm-runtime","dependencies":{"@emnapi/core":"@emnapi/core@1.11.1","@emnapi/runtime":"@emnapi/runtime@1.11.1","@napi-rs/wasm-runtime":"@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)","@tybys/wasm-util":"@tybys/wasm-util@0.10.3"}},"@one-ini/wasm@0.1.1":{"url":"./.pnpm/@one-ini+wasm@0.1.1/node_modules/@one-ini/wasm","dependencies":{"@one-ini/wasm":"@one-ini/wasm@0.1.1"}},"@oxc-project/types@0.139.0":{"url":"./.pnpm/@oxc-project+types@0.139.0/node_modules/@oxc-project/types","dependencies":{"@oxc-project/types":"@oxc-project/types@0.139.0"}},"@pkgjs/parseargs@0.11.0":{"url":"./.pnpm/@pkgjs+parseargs@0.11.0/node_modules/@pkgjs/parseargs","dependencies":{"@pkgjs/parseargs":"@pkgjs/parseargs@0.11.0"}},"@rolldown/binding-android-arm64@1.1.5":{"url":"./.pnpm/@rolldown+binding-android-arm64@1.1.5/node_modules/@rolldown/binding-android-arm64","dependencies":{"@rolldown/binding-android-arm64":"@rolldown/binding-android-arm64@1.1.5"}},"@rolldown/binding-darwin-arm64@1.1.5":{"url":"./.pnpm/@rolldown+binding-darwin-arm64@1.1.5/node_modules/@rolldown/binding-darwin-arm64","dependencies":{"@rolldown/binding-darwin-arm64":"@rolldown/binding-darwin-arm64@1.1.5"}},"@rolldown/binding-darwin-x64@1.1.5":{"url":"./.pnpm/@rolldown+binding-darwin-x64@1.1.5/node_modules/@rolldown/binding-darwin-x64","dependencies":{"@rolldown/binding-darwin-x64":"@rolldown/binding-darwin-x64@1.1.5"}},"@rolldown/binding-freebsd-x64@1.1.5":{"url":"./.pnpm/@rolldown+binding-freebsd-x64@1.1.5/node_modules/@rolldown/binding-freebsd-x64","dependencies":{"@rolldown/binding-freebsd-x64":"@rolldown/binding-freebsd-x64@1.1.5"}},"@rolldown/binding-linux-arm-gnueabihf@1.1.5":{"url":"./.pnpm/@rolldown+binding-linux-arm-gnueabihf@1.1.5/node_modules/@rolldown/binding-linux-arm-gnueabihf","dependencies":{"@rolldown/binding-linux-arm-gnueabihf":"@rolldown/binding-linux-arm-gnueabihf@1.1.5"}},"@rolldown/binding-linux-arm64-gnu@1.1.5":{"url":"./.pnpm/@rolldown+binding-linux-arm64-gnu@1.1.5/node_modules/@rolldown/binding-linux-arm64-gnu","dependencies":{"@rolldown/binding-linux-arm64-gnu":"@rolldown/binding-linux-arm64-gnu@1.1.5"}},"@rolldown/binding-linux-arm64-musl@1.1.5":{"url":"./.pnpm/@rolldown+binding-linux-arm64-musl@1.1.5/node_modules/@rolldown/binding-linux-arm64-musl","dependencies":{"@rolldown/binding-linux-arm64-musl":"@rolldown/binding-linux-arm64-musl@1.1.5"}},"@rolldown/binding-linux-ppc64-gnu@1.1.5":{"url":"./.pnpm/@rolldown+binding-linux-ppc64-gnu@1.1.5/node_modules/@rolldown/binding-linux-ppc64-gnu","dependencies":{"@rolldown/binding-linux-ppc64-gnu":"@rolldown/binding-linux-ppc64-gnu@1.1.5"}},"@rolldown/binding-linux-s390x-gnu@1.1.5":{"url":"./.pnpm/@rolldown+binding-linux-s390x-gnu@1.1.5/node_modules/@rolldown/binding-linux-s390x-gnu","dependencies":{"@rolldown/binding-linux-s390x-gnu":"@rolldown/binding-linux-s390x-gnu@1.1.5"}},"@rolldown/binding-linux-x64-gnu@1.1.5":{"url":"./.pnpm/@rolldown+binding-linux-x64-gnu@1.1.5/node_modules/@rolldown/binding-linux-x64-gnu","dependencies":{"@rolldown/binding-linux-x64-gnu":"@rolldown/binding-linux-x64-gnu@1.1.5"}},"@rolldown/binding-linux-x64-musl@1.1.5":{"url":"./.pnpm/@rolldown+binding-linux-x64-musl@1.1.5/node_modules/@rolldown/binding-linux-x64-musl","dependencies":{"@rolldown/binding-linux-x64-musl":"@rolldown/binding-linux-x64-musl@1.1.5"}},"@rolldown/binding-openharmony-arm64@1.1.5":{"url":"./.pnpm/@rolldown+binding-openharmony-arm64@1.1.5/node_modules/@rolldown/binding-openharmony-arm64","dependencies":{"@rolldown/binding-openharmony-arm64":"@rolldown/binding-openharmony-arm64@1.1.5"}},"@rolldown/binding-wasm32-wasi@1.1.5":{"url":"./.pnpm/@rolldown+binding-wasm32-wasi@1.1.5/node_modules/@rolldown/binding-wasm32-wasi","dependencies":{"@emnapi/core":"@emnapi/core@1.11.1","@emnapi/runtime":"@emnapi/runtime@1.11.1","@napi-rs/wasm-runtime":"@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)","@rolldown/binding-wasm32-wasi":"@rolldown/binding-wasm32-wasi@1.1.5"}},"@rolldown/binding-win32-arm64-msvc@1.1.5":{"url":"./.pnpm/@rolldown+binding-win32-arm64-msvc@1.1.5/node_modules/@rolldown/binding-win32-arm64-msvc","dependencies":{"@rolldown/binding-win32-arm64-msvc":"@rolldown/binding-win32-arm64-msvc@1.1.5"}},"@rolldown/binding-win32-x64-msvc@1.1.5":{"url":"./.pnpm/@rolldown+binding-win32-x64-msvc@1.1.5/node_modules/@rolldown/binding-win32-x64-msvc","dependencies":{"@rolldown/binding-win32-x64-msvc":"@rolldown/binding-win32-x64-msvc@1.1.5"}},"@rolldown/pluginutils@1.0.1":{"url":"./.pnpm/@rolldown+pluginutils@1.0.1/node_modules/@rolldown/pluginutils","dependencies":{"@rolldown/pluginutils":"@rolldown/pluginutils@1.0.1"}},"@standard-schema/spec@1.1.0":{"url":"./.pnpm/@standard-schema+spec@1.1.0/node_modules/@standard-schema/spec","dependencies":{"@standard-schema/spec":"@standard-schema/spec@1.1.0"}},"@sxzz/popperjs-es@2.11.8":{"url":"./.pnpm/@sxzz+popperjs-es@2.11.8/node_modules/@sxzz/popperjs-es","dependencies":{"@sxzz/popperjs-es":"@sxzz/popperjs-es@2.11.8"}},"@tybys/wasm-util@0.10.3":{"url":"./.pnpm/@tybys+wasm-util@0.10.3/node_modules/@tybys/wasm-util","dependencies":{"@tybys/wasm-util":"@tybys/wasm-util@0.10.3","tslib":"tslib@2.8.1"}},"@types/chai@5.2.3":{"url":"./.pnpm/@types+chai@5.2.3/node_modules/@types/chai","dependencies":{"@types/chai":"@types/chai@5.2.3","@types/deep-eql":"@types/deep-eql@4.0.2","assertion-error":"assertion-error@2.0.1"}},"@types/deep-eql@4.0.2":{"url":"./.pnpm/@types+deep-eql@4.0.2/node_modules/@types/deep-eql","dependencies":{"@types/deep-eql":"@types/deep-eql@4.0.2"}},"@types/estree@1.0.9":{"url":"./.pnpm/@types+estree@1.0.9/node_modules/@types/estree","dependencies":{"@types/estree":"@types/estree@1.0.9"}},"@types/jsesc@2.5.1":{"url":"./.pnpm/@types+jsesc@2.5.1/node_modules/@types/jsesc","dependencies":{"@types/jsesc":"@types/jsesc@2.5.1"}},"@types/lodash-es@4.17.12":{"url":"./.pnpm/@types+lodash-es@4.17.12/node_modules/@types/lodash-es","dependencies":{"@types/lodash":"@types/lodash@4.17.24","@types/lodash-es":"@types/lodash-es@4.17.12"}},"@types/lodash@4.17.24":{"url":"./.pnpm/@types+lodash@4.17.24/node_modules/@types/lodash","dependencies":{"@types/lodash":"@types/lodash@4.17.24"}},"@types/node@24.13.3":{"url":"./.pnpm/@types+node@24.13.3/node_modules/@types/node","dependencies":{"@types/node":"@types/node@24.13.3","undici-types":"undici-types@7.18.2"}},"@types/sortablejs@1.15.9":{"url":"./.pnpm/@types+sortablejs@1.15.9/node_modules/@types/sortablejs","dependencies":{"@types/sortablejs":"@types/sortablejs@1.15.9"}},"@types/web-bluetooth@0.0.21":{"url":"./.pnpm/@types+web-bluetooth@0.0.21/node_modules/@types/web-bluetooth","dependencies":{"@types/web-bluetooth":"@types/web-bluetooth@0.0.21"}},"@vitejs/plugin-vue@6.0.8(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3))":{"url":"./.pnpm/@vitejs+plugin-vue@6.0.8_vi_aff8e940ee635d9cd9071146b659acb0/node_modules/@vitejs/plugin-vue","dependencies":{"@rolldown/pluginutils":"@rolldown/pluginutils@1.0.1","@vitejs/plugin-vue":"@vitejs/plugin-vue@6.0.8(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3))","vite":"vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)","vue":"vue@3.5.40(typescript@5.9.3)"}},"@vitest/expect@4.1.10":{"url":"./.pnpm/@vitest+expect@4.1.10/node_modules/@vitest/expect","dependencies":{"@standard-schema/spec":"@standard-schema/spec@1.1.0","@types/chai":"@types/chai@5.2.3","@vitest/expect":"@vitest/expect@4.1.10","@vitest/spy":"@vitest/spy@4.1.10","@vitest/utils":"@vitest/utils@4.1.10","chai":"chai@6.2.2","tinyrainbow":"tinyrainbow@3.1.0"}},"@vitest/mocker@4.1.10(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))":{"url":"./.pnpm/@vitest+mocker@4.1.10_vite@_4de309d5b8dbdc98c8d0abe1489ccfc6/node_modules/@vitest/mocker","dependencies":{"@vitest/mocker":"@vitest/mocker@4.1.10(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))","@vitest/spy":"@vitest/spy@4.1.10","estree-walker":"estree-walker@3.0.3","magic-string":"magic-string@0.30.21","vite":"vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)"}},"@vitest/pretty-format@4.1.10":{"url":"./.pnpm/@vitest+pretty-format@4.1.10/node_modules/@vitest/pretty-format","dependencies":{"@vitest/pretty-format":"@vitest/pretty-format@4.1.10","tinyrainbow":"tinyrainbow@3.1.0"}},"@vitest/runner@4.1.10":{"url":"./.pnpm/@vitest+runner@4.1.10/node_modules/@vitest/runner","dependencies":{"@vitest/runner":"@vitest/runner@4.1.10","@vitest/utils":"@vitest/utils@4.1.10","pathe":"pathe@2.0.3"}},"@vitest/snapshot@4.1.10":{"url":"./.pnpm/@vitest+snapshot@4.1.10/node_modules/@vitest/snapshot","dependencies":{"@vitest/pretty-format":"@vitest/pretty-format@4.1.10","@vitest/snapshot":"@vitest/snapshot@4.1.10","@vitest/utils":"@vitest/utils@4.1.10","magic-string":"magic-string@0.30.21","pathe":"pathe@2.0.3"}},"@vitest/spy@4.1.10":{"url":"./.pnpm/@vitest+spy@4.1.10/node_modules/@vitest/spy","dependencies":{"@vitest/spy":"@vitest/spy@4.1.10"}},"@vitest/utils@4.1.10":{"url":"./.pnpm/@vitest+utils@4.1.10/node_modules/@vitest/utils","dependencies":{"@vitest/pretty-format":"@vitest/pretty-format@4.1.10","@vitest/utils":"@vitest/utils@4.1.10","convert-source-map":"convert-source-map@2.0.0","tinyrainbow":"tinyrainbow@3.1.0"}},"@volar/language-core@2.4.28":{"url":"./.pnpm/@volar+language-core@2.4.28/node_modules/@volar/language-core","dependencies":{"@volar/language-core":"@volar/language-core@2.4.28","@volar/source-map":"@volar/source-map@2.4.28"}},"@volar/source-map@2.4.28":{"url":"./.pnpm/@volar+source-map@2.4.28/node_modules/@volar/source-map","dependencies":{"@volar/source-map":"@volar/source-map@2.4.28"}},"@volar/typescript@2.4.28":{"url":"./.pnpm/@volar+typescript@2.4.28/node_modules/@volar/typescript","dependencies":{"@volar/language-core":"@volar/language-core@2.4.28","@volar/typescript":"@volar/typescript@2.4.28","path-browserify":"path-browserify@1.0.1","vscode-uri":"vscode-uri@3.1.0"}},"@vue-macros/common@3.1.4(vue@3.5.40(typescript@5.9.3))":{"url":"./.pnpm/@vue-macros+common@3.1.4_vue@3.5.40_typescript@5.9.3_/node_modules/@vue-macros/common","dependencies":{"@vue-macros/common":"@vue-macros/common@3.1.4(vue@3.5.40(typescript@5.9.3))","@vue/compiler-sfc":"@vue/compiler-sfc@3.5.40","ast-kit":"ast-kit@2.2.0","local-pkg":"local-pkg@1.2.1","magic-string-ast":"magic-string-ast@1.0.3","unplugin-utils":"unplugin-utils@0.3.2","vue":"vue@3.5.40(typescript@5.9.3)"}},"@vue/compiler-core@3.5.40":{"url":"./.pnpm/@vue+compiler-core@3.5.40/node_modules/@vue/compiler-core","dependencies":{"@babel/parser":"@babel/parser@7.29.7","@vue/compiler-core":"@vue/compiler-core@3.5.40","@vue/shared":"@vue/shared@3.5.40","entities":"entities@7.0.1","estree-walker":"estree-walker@2.0.2","source-map-js":"source-map-js@1.2.1"}},"@vue/compiler-dom@3.5.40":{"url":"./.pnpm/@vue+compiler-dom@3.5.40/node_modules/@vue/compiler-dom","dependencies":{"@vue/compiler-core":"@vue/compiler-core@3.5.40","@vue/compiler-dom":"@vue/compiler-dom@3.5.40","@vue/shared":"@vue/shared@3.5.40"}},"@vue/compiler-sfc@3.5.40":{"url":"./.pnpm/@vue+compiler-sfc@3.5.40/node_modules/@vue/compiler-sfc","dependencies":{"@babel/parser":"@babel/parser@7.29.7","@vue/compiler-core":"@vue/compiler-core@3.5.40","@vue/compiler-dom":"@vue/compiler-dom@3.5.40","@vue/compiler-sfc":"@vue/compiler-sfc@3.5.40","@vue/compiler-ssr":"@vue/compiler-ssr@3.5.40","@vue/shared":"@vue/shared@3.5.40","estree-walker":"estree-walker@2.0.2","magic-string":"magic-string@0.30.21","postcss":"postcss@8.5.23","source-map-js":"source-map-js@1.2.1"}},"@vue/compiler-ssr@3.5.40":{"url":"./.pnpm/@vue+compiler-ssr@3.5.40/node_modules/@vue/compiler-ssr","dependencies":{"@vue/compiler-dom":"@vue/compiler-dom@3.5.40","@vue/compiler-ssr":"@vue/compiler-ssr@3.5.40","@vue/shared":"@vue/shared@3.5.40"}},"@vue/devtools-api@8.2.1":{"url":"./.pnpm/@vue+devtools-api@8.2.1/node_modules/@vue/devtools-api","dependencies":{"@vue/devtools-api":"@vue/devtools-api@8.2.1","@vue/devtools-kit":"@vue/devtools-kit@8.2.1"}},"@vue/devtools-kit@8.2.1":{"url":"./.pnpm/@vue+devtools-kit@8.2.1/node_modules/@vue/devtools-kit","dependencies":{"@vue/devtools-kit":"@vue/devtools-kit@8.2.1","@vue/devtools-shared":"@vue/devtools-shared@8.2.1","birpc":"birpc@2.9.0","hookable":"hookable@5.5.3","perfect-debounce":"perfect-debounce@2.1.0"}},"@vue/devtools-shared@8.2.1":{"url":"./.pnpm/@vue+devtools-shared@8.2.1/node_modules/@vue/devtools-shared","dependencies":{"@vue/devtools-shared":"@vue/devtools-shared@8.2.1"}},"@vue/language-core@3.3.8":{"url":"./.pnpm/@vue+language-core@3.3.8/node_modules/@vue/language-core","dependencies":{"@volar/language-core":"@volar/language-core@2.4.28","@vue/compiler-dom":"@vue/compiler-dom@3.5.40","@vue/language-core":"@vue/language-core@3.3.8","@vue/shared":"@vue/shared@3.5.40","alien-signals":"alien-signals@3.2.1","muggle-string":"muggle-string@0.4.1","path-browserify":"path-browserify@1.0.1","picomatch":"picomatch@4.0.5"}},"@vue/reactivity@3.5.40":{"url":"./.pnpm/@vue+reactivity@3.5.40/node_modules/@vue/reactivity","dependencies":{"@vue/reactivity":"@vue/reactivity@3.5.40","@vue/shared":"@vue/shared@3.5.40"}},"@vue/runtime-core@3.5.40":{"url":"./.pnpm/@vue+runtime-core@3.5.40/node_modules/@vue/runtime-core","dependencies":{"@vue/reactivity":"@vue/reactivity@3.5.40","@vue/runtime-core":"@vue/runtime-core@3.5.40","@vue/shared":"@vue/shared@3.5.40"}},"@vue/runtime-dom@3.5.40":{"url":"./.pnpm/@vue+runtime-dom@3.5.40/node_modules/@vue/runtime-dom","dependencies":{"@vue/reactivity":"@vue/reactivity@3.5.40","@vue/runtime-core":"@vue/runtime-core@3.5.40","@vue/runtime-dom":"@vue/runtime-dom@3.5.40","@vue/shared":"@vue/shared@3.5.40","csstype":"csstype@3.2.3"}},"@vue/server-renderer@3.5.40":{"url":"./.pnpm/@vue+server-renderer@3.5.40/node_modules/@vue/server-renderer","dependencies":{"@vue/compiler-ssr":"@vue/compiler-ssr@3.5.40","@vue/runtime-dom":"@vue/runtime-dom@3.5.40","@vue/server-renderer":"@vue/server-renderer@3.5.40","@vue/shared":"@vue/shared@3.5.40"}},"@vue/shared@3.5.40":{"url":"./.pnpm/@vue+shared@3.5.40/node_modules/@vue/shared","dependencies":{"@vue/shared":"@vue/shared@3.5.40"}},"@vue/test-utils@2.4.11(@vue/compiler-dom@3.5.40)(@vue/server-renderer@3.5.40)(vue@3.5.40(typescript@5.9.3))":{"url":"./.pnpm/@vue+test-utils@2.4.11_@vue_e8c95f6be4ba3aa4aa11ed14b41f32fd/node_modules/@vue/test-utils","dependencies":{"@vue/compiler-dom":"@vue/compiler-dom@3.5.40","@vue/server-renderer":"@vue/server-renderer@3.5.40","@vue/test-utils":"@vue/test-utils@2.4.11(@vue/compiler-dom@3.5.40)(@vue/server-renderer@3.5.40)(vue@3.5.40(typescript@5.9.3))","js-beautify":"js-beautify@1.15.4","vue":"vue@3.5.40(typescript@5.9.3)","vue-component-type-helpers":"vue-component-type-helpers@3.3.8"}},"@vueuse/core@14.3.0(vue@3.5.40(typescript@5.9.3))":{"url":"./.pnpm/@vueuse+core@14.3.0_vue@3.5.40_typescript@5.9.3_/node_modules/@vueuse/core","dependencies":{"@types/web-bluetooth":"@types/web-bluetooth@0.0.21","@vueuse/core":"@vueuse/core@14.3.0(vue@3.5.40(typescript@5.9.3))","@vueuse/metadata":"@vueuse/metadata@14.3.0","@vueuse/shared":"@vueuse/shared@14.3.0(vue@3.5.40(typescript@5.9.3))","vue":"vue@3.5.40(typescript@5.9.3)"}},"@vueuse/metadata@14.3.0":{"url":"./.pnpm/@vueuse+metadata@14.3.0/node_modules/@vueuse/metadata","dependencies":{"@vueuse/metadata":"@vueuse/metadata@14.3.0"}},"@vueuse/shared@14.3.0(vue@3.5.40(typescript@5.9.3))":{"url":"./.pnpm/@vueuse+shared@14.3.0_vue@3.5.40_typescript@5.9.3_/node_modules/@vueuse/shared","dependencies":{"@vueuse/shared":"@vueuse/shared@14.3.0(vue@3.5.40(typescript@5.9.3))","vue":"vue@3.5.40(typescript@5.9.3)"}},"abbrev@2.0.0":{"url":"./.pnpm/abbrev@2.0.0/node_modules/abbrev","dependencies":{"abbrev":"abbrev@2.0.0"}},"acorn@8.17.0":{"url":"./.pnpm/acorn@8.17.0/node_modules/acorn","dependencies":{"acorn":"acorn@8.17.0"}},"agent-base@6.0.2":{"url":"./.pnpm/agent-base@6.0.2/node_modules/agent-base","dependencies":{"agent-base":"agent-base@6.0.2","debug":"debug@4.4.3"}},"alien-signals@3.2.1":{"url":"./.pnpm/alien-signals@3.2.1/node_modules/alien-signals","dependencies":{"alien-signals":"alien-signals@3.2.1"}},"ansi-regex@5.0.1":{"url":"./.pnpm/ansi-regex@5.0.1/node_modules/ansi-regex","dependencies":{"ansi-regex":"ansi-regex@5.0.1"}},"ansi-regex@6.2.2":{"url":"./.pnpm/ansi-regex@6.2.2/node_modules/ansi-regex","dependencies":{"ansi-regex":"ansi-regex@6.2.2"}},"ansi-styles@4.3.0":{"url":"./.pnpm/ansi-styles@4.3.0/node_modules/ansi-styles","dependencies":{"ansi-styles":"ansi-styles@4.3.0","color-convert":"color-convert@2.0.1"}},"ansi-styles@6.2.3":{"url":"./.pnpm/ansi-styles@6.2.3/node_modules/ansi-styles","dependencies":{"ansi-styles":"ansi-styles@6.2.3"}},"assertion-error@2.0.1":{"url":"./.pnpm/assertion-error@2.0.1/node_modules/assertion-error","dependencies":{"assertion-error":"assertion-error@2.0.1"}},"ast-kit@2.2.0":{"url":"./.pnpm/ast-kit@2.2.0/node_modules/ast-kit","dependencies":{"@babel/parser":"@babel/parser@7.29.7","ast-kit":"ast-kit@2.2.0","pathe":"pathe@2.0.3"}},"ast-walker-scope@0.9.0":{"url":"./.pnpm/ast-walker-scope@0.9.0/node_modules/ast-walker-scope","dependencies":{"@babel/parser":"@babel/parser@7.29.7","@babel/types":"@babel/types@7.29.7","ast-kit":"ast-kit@2.2.0","ast-walker-scope":"ast-walker-scope@0.9.0"}},"async-validator@4.2.5":{"url":"./.pnpm/async-validator@4.2.5/node_modules/async-validator","dependencies":{"async-validator":"async-validator@4.2.5"}},"asynckit@0.4.0":{"url":"./.pnpm/asynckit@0.4.0/node_modules/asynckit","dependencies":{"asynckit":"asynckit@0.4.0"}},"axios@1.18.1(debug@4.4.3)":{"url":"./.pnpm/axios@1.18.1_debug@4.4.3/node_modules/axios","dependencies":{"axios":"axios@1.18.1(debug@4.4.3)","follow-redirects":"follow-redirects@1.16.0(debug@4.4.3)","form-data":"form-data@4.0.6","https-proxy-agent":"https-proxy-agent@5.0.1","proxy-from-env":"proxy-from-env@2.1.0"}},"balanced-match@1.0.2":{"url":"./.pnpm/balanced-match@1.0.2/node_modules/balanced-match","dependencies":{"balanced-match":"balanced-match@1.0.2"}},"bidi-js@1.0.3":{"url":"./.pnpm/bidi-js@1.0.3/node_modules/bidi-js","dependencies":{"bidi-js":"bidi-js@1.0.3","require-from-string":"require-from-string@2.0.2"}},"birpc@2.9.0":{"url":"./.pnpm/birpc@2.9.0/node_modules/birpc","dependencies":{"birpc":"birpc@2.9.0"}},"brace-expansion@2.1.2":{"url":"./.pnpm/brace-expansion@2.1.2/node_modules/brace-expansion","dependencies":{"balanced-match":"balanced-match@1.0.2","brace-expansion":"brace-expansion@2.1.2"}},"call-bind-apply-helpers@1.0.2":{"url":"./.pnpm/call-bind-apply-helpers@1.0.2/node_modules/call-bind-apply-helpers","dependencies":{"call-bind-apply-helpers":"call-bind-apply-helpers@1.0.2","es-errors":"es-errors@1.3.0","function-bind":"function-bind@1.1.2"}},"chai@6.2.2":{"url":"./.pnpm/chai@6.2.2/node_modules/chai","dependencies":{"chai":"chai@6.2.2"}},"chokidar@5.0.0":{"url":"./.pnpm/chokidar@5.0.0/node_modules/chokidar","dependencies":{"chokidar":"chokidar@5.0.0","readdirp":"readdirp@5.0.0"}},"color-convert@2.0.1":{"url":"./.pnpm/color-convert@2.0.1/node_modules/color-convert","dependencies":{"color-convert":"color-convert@2.0.1","color-name":"color-name@1.1.4"}},"color-name@1.1.4":{"url":"./.pnpm/color-name@1.1.4/node_modules/color-name","dependencies":{"color-name":"color-name@1.1.4"}},"combined-stream@1.0.8":{"url":"./.pnpm/combined-stream@1.0.8/node_modules/combined-stream","dependencies":{"combined-stream":"combined-stream@1.0.8","delayed-stream":"delayed-stream@1.0.0"}},"commander@10.0.1":{"url":"./.pnpm/commander@10.0.1/node_modules/commander","dependencies":{"commander":"commander@10.0.1"}},"confbox@0.1.8":{"url":"./.pnpm/confbox@0.1.8/node_modules/confbox","dependencies":{"confbox":"confbox@0.1.8"}},"confbox@0.2.4":{"url":"./.pnpm/confbox@0.2.4/node_modules/confbox","dependencies":{"confbox":"confbox@0.2.4"}},"config-chain@1.1.13":{"url":"./.pnpm/config-chain@1.1.13/node_modules/config-chain","dependencies":{"config-chain":"config-chain@1.1.13","ini":"ini@1.3.8","proto-list":"proto-list@1.2.4"}},"convert-source-map@2.0.0":{"url":"./.pnpm/convert-source-map@2.0.0/node_modules/convert-source-map","dependencies":{"convert-source-map":"convert-source-map@2.0.0"}},"cross-spawn@7.0.6":{"url":"./.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn","dependencies":{"cross-spawn":"cross-spawn@7.0.6","path-key":"path-key@3.1.1","shebang-command":"shebang-command@2.0.0","which":"which@2.0.2"}},"css-tree@3.2.1":{"url":"./.pnpm/css-tree@3.2.1/node_modules/css-tree","dependencies":{"css-tree":"css-tree@3.2.1","mdn-data":"mdn-data@2.27.1","source-map-js":"source-map-js@1.2.1"}},"csstype@3.2.3":{"url":"./.pnpm/csstype@3.2.3/node_modules/csstype","dependencies":{"csstype":"csstype@3.2.3"}},"data-urls@7.0.0":{"url":"./.pnpm/data-urls@7.0.0/node_modules/data-urls","dependencies":{"data-urls":"data-urls@7.0.0","whatwg-mimetype":"whatwg-mimetype@5.0.0","whatwg-url":"whatwg-url@16.0.1"}},"dayjs@1.11.21":{"url":"./.pnpm/dayjs@1.11.21/node_modules/dayjs","dependencies":{"dayjs":"dayjs@1.11.21"}},"debug@4.4.3":{"url":"./.pnpm/debug@4.4.3/node_modules/debug","dependencies":{"debug":"debug@4.4.3","ms":"ms@2.1.3"}},"decimal.js@10.6.0":{"url":"./.pnpm/decimal.js@10.6.0/node_modules/decimal.js","dependencies":{"decimal.js":"decimal.js@10.6.0"}},"delayed-stream@1.0.0":{"url":"./.pnpm/delayed-stream@1.0.0/node_modules/delayed-stream","dependencies":{"delayed-stream":"delayed-stream@1.0.0"}},"detect-libc@2.1.2":{"url":"./.pnpm/detect-libc@2.1.2/node_modules/detect-libc","dependencies":{"detect-libc":"detect-libc@2.1.2"}},"dunder-proto@1.0.1":{"url":"./.pnpm/dunder-proto@1.0.1/node_modules/dunder-proto","dependencies":{"call-bind-apply-helpers":"call-bind-apply-helpers@1.0.2","dunder-proto":"dunder-proto@1.0.1","es-errors":"es-errors@1.3.0","gopd":"gopd@1.2.0"}},"eastasianwidth@0.2.0":{"url":"./.pnpm/eastasianwidth@0.2.0/node_modules/eastasianwidth","dependencies":{"eastasianwidth":"eastasianwidth@0.2.0"}},"editorconfig@1.0.7":{"url":"./.pnpm/editorconfig@1.0.7/node_modules/editorconfig","dependencies":{"@one-ini/wasm":"@one-ini/wasm@0.1.1","commander":"commander@10.0.1","editorconfig":"editorconfig@1.0.7","minimatch":"minimatch@9.0.9","semver":"semver@7.8.5"}},"element-plus@2.14.3(vue@3.5.40(typescript@5.9.3))":{"url":"./.pnpm/element-plus@2.14.3_vue@3.5.40_typescript@5.9.3_/node_modules/element-plus","dependencies":{"@ctrl/tinycolor":"@ctrl/tinycolor@4.2.0","@element-plus/icons-vue":"@element-plus/icons-vue@2.3.2(vue@3.5.40(typescript@5.9.3))","@floating-ui/dom":"@floating-ui/dom@1.8.0","@popperjs/core":"@sxzz/popperjs-es@2.11.8","@types/lodash":"@types/lodash@4.17.24","@types/lodash-es":"@types/lodash-es@4.17.12","@vueuse/core":"@vueuse/core@14.3.0(vue@3.5.40(typescript@5.9.3))","async-validator":"async-validator@4.2.5","dayjs":"dayjs@1.11.21","element-plus":"element-plus@2.14.3(vue@3.5.40(typescript@5.9.3))","lodash":"lodash@4.18.1","lodash-es":"lodash-es@4.18.1","lodash-unified":"lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.18.1)(lodash@4.18.1)","memoize-one":"memoize-one@6.0.0","normalize-wheel-es":"normalize-wheel-es@1.2.0","vue":"vue@3.5.40(typescript@5.9.3)","vue-component-type-helpers":"vue-component-type-helpers@3.3.8"}},"emoji-regex@8.0.0":{"url":"./.pnpm/emoji-regex@8.0.0/node_modules/emoji-regex","dependencies":{"emoji-regex":"emoji-regex@8.0.0"}},"emoji-regex@9.2.2":{"url":"./.pnpm/emoji-regex@9.2.2/node_modules/emoji-regex","dependencies":{"emoji-regex":"emoji-regex@9.2.2"}},"entities@7.0.1":{"url":"./.pnpm/entities@7.0.1/node_modules/entities","dependencies":{"entities":"entities@7.0.1"}},"entities@8.0.0":{"url":"./.pnpm/entities@8.0.0/node_modules/entities","dependencies":{"entities":"entities@8.0.0"}},"es-define-property@1.0.1":{"url":"./.pnpm/es-define-property@1.0.1/node_modules/es-define-property","dependencies":{"es-define-property":"es-define-property@1.0.1"}},"es-errors@1.3.0":{"url":"./.pnpm/es-errors@1.3.0/node_modules/es-errors","dependencies":{"es-errors":"es-errors@1.3.0"}},"es-module-lexer@2.3.1":{"url":"./.pnpm/es-module-lexer@2.3.1/node_modules/es-module-lexer","dependencies":{"es-module-lexer":"es-module-lexer@2.3.1"}},"es-object-atoms@1.1.2":{"url":"./.pnpm/es-object-atoms@1.1.2/node_modules/es-object-atoms","dependencies":{"es-errors":"es-errors@1.3.0","es-object-atoms":"es-object-atoms@1.1.2"}},"es-set-tostringtag@2.1.0":{"url":"./.pnpm/es-set-tostringtag@2.1.0/node_modules/es-set-tostringtag","dependencies":{"es-errors":"es-errors@1.3.0","es-set-tostringtag":"es-set-tostringtag@2.1.0","get-intrinsic":"get-intrinsic@1.3.0","has-tostringtag":"has-tostringtag@1.0.2","hasown":"hasown@2.0.4"}},"escape-string-regexp@5.0.0":{"url":"./.pnpm/escape-string-regexp@5.0.0/node_modules/escape-string-regexp","dependencies":{"escape-string-regexp":"escape-string-regexp@5.0.0"}},"estree-walker@2.0.2":{"url":"./.pnpm/estree-walker@2.0.2/node_modules/estree-walker","dependencies":{"estree-walker":"estree-walker@2.0.2"}},"estree-walker@3.0.3":{"url":"./.pnpm/estree-walker@3.0.3/node_modules/estree-walker","dependencies":{"@types/estree":"@types/estree@1.0.9","estree-walker":"estree-walker@3.0.3"}},"expect-type@1.4.0":{"url":"./.pnpm/expect-type@1.4.0/node_modules/expect-type","dependencies":{"expect-type":"expect-type@1.4.0"}},"exsolve@1.1.0":{"url":"./.pnpm/exsolve@1.1.0/node_modules/exsolve","dependencies":{"exsolve":"exsolve@1.1.0"}},"fdir@6.5.0(picomatch@4.0.5)":{"url":"./.pnpm/fdir@6.5.0_picomatch@4.0.5/node_modules/fdir","dependencies":{"fdir":"fdir@6.5.0(picomatch@4.0.5)","picomatch":"picomatch@4.0.5"}},"follow-redirects@1.16.0(debug@4.4.3)":{"url":"./.pnpm/follow-redirects@1.16.0_debug@4.4.3/node_modules/follow-redirects","dependencies":{"debug":"debug@4.4.3","follow-redirects":"follow-redirects@1.16.0(debug@4.4.3)"}},"foreground-child@3.3.1":{"url":"./.pnpm/foreground-child@3.3.1/node_modules/foreground-child","dependencies":{"cross-spawn":"cross-spawn@7.0.6","foreground-child":"foreground-child@3.3.1","signal-exit":"signal-exit@4.1.0"}},"form-data@4.0.6":{"url":"./.pnpm/form-data@4.0.6/node_modules/form-data","dependencies":{"asynckit":"asynckit@0.4.0","combined-stream":"combined-stream@1.0.8","es-set-tostringtag":"es-set-tostringtag@2.1.0","form-data":"form-data@4.0.6","hasown":"hasown@2.0.4","mime-types":"mime-types@2.1.35"}},"fsevents@2.3.3":{"url":"./.pnpm/fsevents@2.3.3/node_modules/fsevents","dependencies":{"fsevents":"fsevents@2.3.3"}},"function-bind@1.1.2":{"url":"./.pnpm/function-bind@1.1.2/node_modules/function-bind","dependencies":{"function-bind":"function-bind@1.1.2"}},"get-intrinsic@1.3.0":{"url":"./.pnpm/get-intrinsic@1.3.0/node_modules/get-intrinsic","dependencies":{"call-bind-apply-helpers":"call-bind-apply-helpers@1.0.2","es-define-property":"es-define-property@1.0.1","es-errors":"es-errors@1.3.0","es-object-atoms":"es-object-atoms@1.1.2","function-bind":"function-bind@1.1.2","get-intrinsic":"get-intrinsic@1.3.0","get-proto":"get-proto@1.0.1","gopd":"gopd@1.2.0","has-symbols":"has-symbols@1.1.0","hasown":"hasown@2.0.4","math-intrinsics":"math-intrinsics@1.1.0"}},"get-proto@1.0.1":{"url":"./.pnpm/get-proto@1.0.1/node_modules/get-proto","dependencies":{"dunder-proto":"dunder-proto@1.0.1","es-object-atoms":"es-object-atoms@1.1.2","get-proto":"get-proto@1.0.1"}},"glob@10.5.0":{"url":"./.pnpm/glob@10.5.0/node_modules/glob","dependencies":{"foreground-child":"foreground-child@3.3.1","glob":"glob@10.5.0","jackspeak":"jackspeak@3.4.3","minimatch":"minimatch@9.0.9","minipass":"minipass@7.1.3","package-json-from-dist":"package-json-from-dist@1.0.1","path-scurry":"path-scurry@1.11.1"}},"gopd@1.2.0":{"url":"./.pnpm/gopd@1.2.0/node_modules/gopd","dependencies":{"gopd":"gopd@1.2.0"}},"has-symbols@1.1.0":{"url":"./.pnpm/has-symbols@1.1.0/node_modules/has-symbols","dependencies":{"has-symbols":"has-symbols@1.1.0"}},"has-tostringtag@1.0.2":{"url":"./.pnpm/has-tostringtag@1.0.2/node_modules/has-tostringtag","dependencies":{"has-symbols":"has-symbols@1.1.0","has-tostringtag":"has-tostringtag@1.0.2"}},"hasown@2.0.4":{"url":"./.pnpm/hasown@2.0.4/node_modules/hasown","dependencies":{"function-bind":"function-bind@1.1.2","hasown":"hasown@2.0.4"}},"hookable@5.5.3":{"url":"./.pnpm/hookable@5.5.3/node_modules/hookable","dependencies":{"hookable":"hookable@5.5.3"}},"html-encoding-sniffer@6.0.0":{"url":"./.pnpm/html-encoding-sniffer@6.0.0/node_modules/html-encoding-sniffer","dependencies":{"@exodus/bytes":"@exodus/bytes@1.15.1","html-encoding-sniffer":"html-encoding-sniffer@6.0.0"}},"https-proxy-agent@5.0.1":{"url":"./.pnpm/https-proxy-agent@5.0.1/node_modules/https-proxy-agent","dependencies":{"agent-base":"agent-base@6.0.2","debug":"debug@4.4.3","https-proxy-agent":"https-proxy-agent@5.0.1"}},"ini@1.3.8":{"url":"./.pnpm/ini@1.3.8/node_modules/ini","dependencies":{"ini":"ini@1.3.8"}},"is-fullwidth-code-point@3.0.0":{"url":"./.pnpm/is-fullwidth-code-point@3.0.0/node_modules/is-fullwidth-code-point","dependencies":{"is-fullwidth-code-point":"is-fullwidth-code-point@3.0.0"}},"is-potential-custom-element-name@1.0.1":{"url":"./.pnpm/is-potential-custom-element-name@1.0.1/node_modules/is-potential-custom-element-name","dependencies":{"is-potential-custom-element-name":"is-potential-custom-element-name@1.0.1"}},"isexe@2.0.0":{"url":"./.pnpm/isexe@2.0.0/node_modules/isexe","dependencies":{"isexe":"isexe@2.0.0"}},"jackspeak@3.4.3":{"url":"./.pnpm/jackspeak@3.4.3/node_modules/jackspeak","dependencies":{"@isaacs/cliui":"@isaacs/cliui@8.0.2","@pkgjs/parseargs":"@pkgjs/parseargs@0.11.0","jackspeak":"jackspeak@3.4.3"}},"js-beautify@1.15.4":{"url":"./.pnpm/js-beautify@1.15.4/node_modules/js-beautify","dependencies":{"config-chain":"config-chain@1.1.13","editorconfig":"editorconfig@1.0.7","glob":"glob@10.5.0","js-beautify":"js-beautify@1.15.4","js-cookie":"js-cookie@3.0.8","nopt":"nopt@7.2.1"}},"js-cookie@3.0.8":{"url":"./.pnpm/js-cookie@3.0.8/node_modules/js-cookie","dependencies":{"js-cookie":"js-cookie@3.0.8"}},"js-tokens@9.0.1":{"url":"./.pnpm/js-tokens@9.0.1/node_modules/js-tokens","dependencies":{"js-tokens":"js-tokens@9.0.1"}},"jsdom@29.1.1":{"url":"./.pnpm/jsdom@29.1.1/node_modules/jsdom","dependencies":{"@asamuzakjp/css-color":"@asamuzakjp/css-color@5.1.11","@asamuzakjp/dom-selector":"@asamuzakjp/dom-selector@7.1.1","@bramus/specificity":"@bramus/specificity@2.4.2","@csstools/css-syntax-patches-for-csstree":"@csstools/css-syntax-patches-for-csstree@1.1.7(css-tree@3.2.1)","@exodus/bytes":"@exodus/bytes@1.15.1","css-tree":"css-tree@3.2.1","data-urls":"data-urls@7.0.0","decimal.js":"decimal.js@10.6.0","html-encoding-sniffer":"html-encoding-sniffer@6.0.0","is-potential-custom-element-name":"is-potential-custom-element-name@1.0.1","jsdom":"jsdom@29.1.1","lru-cache":"lru-cache@11.5.2","parse5":"parse5@8.0.1","saxes":"saxes@6.0.0","symbol-tree":"symbol-tree@3.2.4","tough-cookie":"tough-cookie@6.0.2","undici":"undici@7.29.0","w3c-xmlserializer":"w3c-xmlserializer@5.0.0","webidl-conversions":"webidl-conversions@8.0.1","whatwg-mimetype":"whatwg-mimetype@5.0.0","whatwg-url":"whatwg-url@16.0.1","xml-name-validator":"xml-name-validator@5.0.0"}},"jsesc@3.1.0":{"url":"./.pnpm/jsesc@3.1.0/node_modules/jsesc","dependencies":{"jsesc":"jsesc@3.1.0"}},"json5@2.2.3":{"url":"./.pnpm/json5@2.2.3/node_modules/json5","dependencies":{"json5":"json5@2.2.3"}},"lightningcss-android-arm64@1.33.0":{"url":"./.pnpm/lightningcss-android-arm64@1.33.0/node_modules/lightningcss-android-arm64","dependencies":{"lightningcss-android-arm64":"lightningcss-android-arm64@1.33.0"}},"lightningcss-darwin-arm64@1.33.0":{"url":"./.pnpm/lightningcss-darwin-arm64@1.33.0/node_modules/lightningcss-darwin-arm64","dependencies":{"lightningcss-darwin-arm64":"lightningcss-darwin-arm64@1.33.0"}},"lightningcss-darwin-x64@1.33.0":{"url":"./.pnpm/lightningcss-darwin-x64@1.33.0/node_modules/lightningcss-darwin-x64","dependencies":{"lightningcss-darwin-x64":"lightningcss-darwin-x64@1.33.0"}},"lightningcss-freebsd-x64@1.33.0":{"url":"./.pnpm/lightningcss-freebsd-x64@1.33.0/node_modules/lightningcss-freebsd-x64","dependencies":{"lightningcss-freebsd-x64":"lightningcss-freebsd-x64@1.33.0"}},"lightningcss-linux-arm-gnueabihf@1.33.0":{"url":"./.pnpm/lightningcss-linux-arm-gnueabihf@1.33.0/node_modules/lightningcss-linux-arm-gnueabihf","dependencies":{"lightningcss-linux-arm-gnueabihf":"lightningcss-linux-arm-gnueabihf@1.33.0"}},"lightningcss-linux-arm64-gnu@1.33.0":{"url":"./.pnpm/lightningcss-linux-arm64-gnu@1.33.0/node_modules/lightningcss-linux-arm64-gnu","dependencies":{"lightningcss-linux-arm64-gnu":"lightningcss-linux-arm64-gnu@1.33.0"}},"lightningcss-linux-arm64-musl@1.33.0":{"url":"./.pnpm/lightningcss-linux-arm64-musl@1.33.0/node_modules/lightningcss-linux-arm64-musl","dependencies":{"lightningcss-linux-arm64-musl":"lightningcss-linux-arm64-musl@1.33.0"}},"lightningcss-linux-x64-gnu@1.33.0":{"url":"./.pnpm/lightningcss-linux-x64-gnu@1.33.0/node_modules/lightningcss-linux-x64-gnu","dependencies":{"lightningcss-linux-x64-gnu":"lightningcss-linux-x64-gnu@1.33.0"}},"lightningcss-linux-x64-musl@1.33.0":{"url":"./.pnpm/lightningcss-linux-x64-musl@1.33.0/node_modules/lightningcss-linux-x64-musl","dependencies":{"lightningcss-linux-x64-musl":"lightningcss-linux-x64-musl@1.33.0"}},"lightningcss-win32-arm64-msvc@1.33.0":{"url":"./.pnpm/lightningcss-win32-arm64-msvc@1.33.0/node_modules/lightningcss-win32-arm64-msvc","dependencies":{"lightningcss-win32-arm64-msvc":"lightningcss-win32-arm64-msvc@1.33.0"}},"lightningcss-win32-x64-msvc@1.33.0":{"url":"./.pnpm/lightningcss-win32-x64-msvc@1.33.0/node_modules/lightningcss-win32-x64-msvc","dependencies":{"lightningcss-win32-x64-msvc":"lightningcss-win32-x64-msvc@1.33.0"}},"lightningcss@1.33.0":{"url":"./.pnpm/lightningcss@1.33.0/node_modules/lightningcss","dependencies":{"detect-libc":"detect-libc@2.1.2","lightningcss":"lightningcss@1.33.0","lightningcss-android-arm64":"lightningcss-android-arm64@1.33.0","lightningcss-darwin-arm64":"lightningcss-darwin-arm64@1.33.0","lightningcss-darwin-x64":"lightningcss-darwin-x64@1.33.0","lightningcss-freebsd-x64":"lightningcss-freebsd-x64@1.33.0","lightningcss-linux-arm-gnueabihf":"lightningcss-linux-arm-gnueabihf@1.33.0","lightningcss-linux-arm64-gnu":"lightningcss-linux-arm64-gnu@1.33.0","lightningcss-linux-arm64-musl":"lightningcss-linux-arm64-musl@1.33.0","lightningcss-linux-x64-gnu":"lightningcss-linux-x64-gnu@1.33.0","lightningcss-linux-x64-musl":"lightningcss-linux-x64-musl@1.33.0","lightningcss-win32-arm64-msvc":"lightningcss-win32-arm64-msvc@1.33.0","lightningcss-win32-x64-msvc":"lightningcss-win32-x64-msvc@1.33.0"}},"local-pkg@1.2.1":{"url":"./.pnpm/local-pkg@1.2.1/node_modules/local-pkg","dependencies":{"local-pkg":"local-pkg@1.2.1","mlly":"mlly@1.8.2","pkg-types":"pkg-types@2.3.1","quansync":"quansync@0.2.11"}},"lodash-es@4.18.1":{"url":"./.pnpm/lodash-es@4.18.1/node_modules/lodash-es","dependencies":{"lodash-es":"lodash-es@4.18.1"}},"lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.18.1)(lodash@4.18.1)":{"url":"./.pnpm/lodash-unified@1.0.3_@types_168785b94d783e1b7a7274df40d5f9d9/node_modules/lodash-unified","dependencies":{"@types/lodash-es":"@types/lodash-es@4.17.12","lodash":"lodash@4.18.1","lodash-es":"lodash-es@4.18.1","lodash-unified":"lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.18.1)(lodash@4.18.1)"}},"lodash@4.18.1":{"url":"./.pnpm/lodash@4.18.1/node_modules/lodash","dependencies":{"lodash":"lodash@4.18.1"}},"lru-cache@10.4.3":{"url":"./.pnpm/lru-cache@10.4.3/node_modules/lru-cache","dependencies":{"lru-cache":"lru-cache@10.4.3"}},"lru-cache@11.5.2":{"url":"./.pnpm/lru-cache@11.5.2/node_modules/lru-cache","dependencies":{"lru-cache":"lru-cache@11.5.2"}},"magic-string-ast@1.0.3":{"url":"./.pnpm/magic-string-ast@1.0.3/node_modules/magic-string-ast","dependencies":{"magic-string":"magic-string@0.30.21","magic-string-ast":"magic-string-ast@1.0.3"}},"magic-string@0.30.21":{"url":"./.pnpm/magic-string@0.30.21/node_modules/magic-string","dependencies":{"@jridgewell/sourcemap-codec":"@jridgewell/sourcemap-codec@1.5.5","magic-string":"magic-string@0.30.21"}},"math-intrinsics@1.1.0":{"url":"./.pnpm/math-intrinsics@1.1.0/node_modules/math-intrinsics","dependencies":{"math-intrinsics":"math-intrinsics@1.1.0"}},"mdn-data@2.27.1":{"url":"./.pnpm/mdn-data@2.27.1/node_modules/mdn-data","dependencies":{"mdn-data":"mdn-data@2.27.1"}},"memoize-one@6.0.0":{"url":"./.pnpm/memoize-one@6.0.0/node_modules/memoize-one","dependencies":{"memoize-one":"memoize-one@6.0.0"}},"mime-db@1.52.0":{"url":"./.pnpm/mime-db@1.52.0/node_modules/mime-db","dependencies":{"mime-db":"mime-db@1.52.0"}},"mime-types@2.1.35":{"url":"./.pnpm/mime-types@2.1.35/node_modules/mime-types","dependencies":{"mime-db":"mime-db@1.52.0","mime-types":"mime-types@2.1.35"}},"minimatch@9.0.9":{"url":"./.pnpm/minimatch@9.0.9/node_modules/minimatch","dependencies":{"brace-expansion":"brace-expansion@2.1.2","minimatch":"minimatch@9.0.9"}},"minipass@7.1.3":{"url":"./.pnpm/minipass@7.1.3/node_modules/minipass","dependencies":{"minipass":"minipass@7.1.3"}},"mlly@1.8.2":{"url":"./.pnpm/mlly@1.8.2/node_modules/mlly","dependencies":{"acorn":"acorn@8.17.0","mlly":"mlly@1.8.2","pathe":"pathe@2.0.3","pkg-types":"pkg-types@1.3.1","ufo":"ufo@1.6.4"}},"ms@2.1.3":{"url":"./.pnpm/ms@2.1.3/node_modules/ms","dependencies":{"ms":"ms@2.1.3"}},"muggle-string@0.4.1":{"url":"./.pnpm/muggle-string@0.4.1/node_modules/muggle-string","dependencies":{"muggle-string":"muggle-string@0.4.1"}},"nanoid@3.3.16":{"url":"./.pnpm/nanoid@3.3.16/node_modules/nanoid","dependencies":{"nanoid":"nanoid@3.3.16"}},"nopt@7.2.1":{"url":"./.pnpm/nopt@7.2.1/node_modules/nopt","dependencies":{"abbrev":"abbrev@2.0.0","nopt":"nopt@7.2.1"}},"normalize-wheel-es@1.2.0":{"url":"./.pnpm/normalize-wheel-es@1.2.0/node_modules/normalize-wheel-es","dependencies":{"normalize-wheel-es":"normalize-wheel-es@1.2.0"}},"nostics@1.2.0":{"url":"./.pnpm/nostics@1.2.0/node_modules/nostics","dependencies":{"nostics":"nostics@1.2.0"}},"obug@2.1.4":{"url":"./.pnpm/obug@2.1.4/node_modules/obug","dependencies":{"obug":"obug@2.1.4"}},"package-json-from-dist@1.0.1":{"url":"./.pnpm/package-json-from-dist@1.0.1/node_modules/package-json-from-dist","dependencies":{"package-json-from-dist":"package-json-from-dist@1.0.1"}},"parse5@8.0.1":{"url":"./.pnpm/parse5@8.0.1/node_modules/parse5","dependencies":{"entities":"entities@8.0.0","parse5":"parse5@8.0.1"}},"path-browserify@1.0.1":{"url":"./.pnpm/path-browserify@1.0.1/node_modules/path-browserify","dependencies":{"path-browserify":"path-browserify@1.0.1"}},"path-key@3.1.1":{"url":"./.pnpm/path-key@3.1.1/node_modules/path-key","dependencies":{"path-key":"path-key@3.1.1"}},"path-scurry@1.11.1":{"url":"./.pnpm/path-scurry@1.11.1/node_modules/path-scurry","dependencies":{"lru-cache":"lru-cache@10.4.3","minipass":"minipass@7.1.3","path-scurry":"path-scurry@1.11.1"}},"pathe@2.0.3":{"url":"./.pnpm/pathe@2.0.3/node_modules/pathe","dependencies":{"pathe":"pathe@2.0.3"}},"perfect-debounce@2.1.0":{"url":"./.pnpm/perfect-debounce@2.1.0/node_modules/perfect-debounce","dependencies":{"perfect-debounce":"perfect-debounce@2.1.0"}},"picocolors@1.1.1":{"url":"./.pnpm/picocolors@1.1.1/node_modules/picocolors","dependencies":{"picocolors":"picocolors@1.1.1"}},"picomatch@4.0.5":{"url":"./.pnpm/picomatch@4.0.5/node_modules/picomatch","dependencies":{"picomatch":"picomatch@4.0.5"}},"pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@5.9.3)(vue@3.5.40(typescript@5.9.3))":{"url":"./.pnpm/pinia@4.0.2_@vue+devtools-a_b92da3656e156e155ff60832373d6152/node_modules/pinia","dependencies":{"@vue/devtools-api":"@vue/devtools-api@8.2.1","nostics":"nostics@1.2.0","pinia":"pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@5.9.3)(vue@3.5.40(typescript@5.9.3))","typescript":"typescript@5.9.3","vue":"vue@3.5.40(typescript@5.9.3)"}},"pkg-types@1.3.1":{"url":"./.pnpm/pkg-types@1.3.1/node_modules/pkg-types","dependencies":{"confbox":"confbox@0.1.8","mlly":"mlly@1.8.2","pathe":"pathe@2.0.3","pkg-types":"pkg-types@1.3.1"}},"pkg-types@2.3.1":{"url":"./.pnpm/pkg-types@2.3.1/node_modules/pkg-types","dependencies":{"confbox":"confbox@0.2.4","exsolve":"exsolve@1.1.0","pathe":"pathe@2.0.3","pkg-types":"pkg-types@2.3.1"}},"postcss@8.5.23":{"url":"./.pnpm/postcss@8.5.23/node_modules/postcss","dependencies":{"nanoid":"nanoid@3.3.16","picocolors":"picocolors@1.1.1","postcss":"postcss@8.5.23","source-map-js":"source-map-js@1.2.1"}},"proto-list@1.2.4":{"url":"./.pnpm/proto-list@1.2.4/node_modules/proto-list","dependencies":{"proto-list":"proto-list@1.2.4"}},"proxy-from-env@2.1.0":{"url":"./.pnpm/proxy-from-env@2.1.0/node_modules/proxy-from-env","dependencies":{"proxy-from-env":"proxy-from-env@2.1.0"}},"punycode@2.3.1":{"url":"./.pnpm/punycode@2.3.1/node_modules/punycode","dependencies":{"punycode":"punycode@2.3.1"}},"quansync@0.2.11":{"url":"./.pnpm/quansync@0.2.11/node_modules/quansync","dependencies":{"quansync":"quansync@0.2.11"}},"readdirp@5.0.0":{"url":"./.pnpm/readdirp@5.0.0/node_modules/readdirp","dependencies":{"readdirp":"readdirp@5.0.0"}},"require-from-string@2.0.2":{"url":"./.pnpm/require-from-string@2.0.2/node_modules/require-from-string","dependencies":{"require-from-string":"require-from-string@2.0.2"}},"rolldown@1.1.5":{"url":"./.pnpm/rolldown@1.1.5/node_modules/rolldown","dependencies":{"@oxc-project/types":"@oxc-project/types@0.139.0","@rolldown/binding-android-arm64":"@rolldown/binding-android-arm64@1.1.5","@rolldown/binding-darwin-arm64":"@rolldown/binding-darwin-arm64@1.1.5","@rolldown/binding-darwin-x64":"@rolldown/binding-darwin-x64@1.1.5","@rolldown/binding-freebsd-x64":"@rolldown/binding-freebsd-x64@1.1.5","@rolldown/binding-linux-arm-gnueabihf":"@rolldown/binding-linux-arm-gnueabihf@1.1.5","@rolldown/binding-linux-arm64-gnu":"@rolldown/binding-linux-arm64-gnu@1.1.5","@rolldown/binding-linux-arm64-musl":"@rolldown/binding-linux-arm64-musl@1.1.5","@rolldown/binding-linux-ppc64-gnu":"@rolldown/binding-linux-ppc64-gnu@1.1.5","@rolldown/binding-linux-s390x-gnu":"@rolldown/binding-linux-s390x-gnu@1.1.5","@rolldown/binding-linux-x64-gnu":"@rolldown/binding-linux-x64-gnu@1.1.5","@rolldown/binding-linux-x64-musl":"@rolldown/binding-linux-x64-musl@1.1.5","@rolldown/binding-openharmony-arm64":"@rolldown/binding-openharmony-arm64@1.1.5","@rolldown/binding-wasm32-wasi":"@rolldown/binding-wasm32-wasi@1.1.5","@rolldown/binding-win32-arm64-msvc":"@rolldown/binding-win32-arm64-msvc@1.1.5","@rolldown/binding-win32-x64-msvc":"@rolldown/binding-win32-x64-msvc@1.1.5","@rolldown/pluginutils":"@rolldown/pluginutils@1.0.1","rolldown":"rolldown@1.1.5"}},"saxes@6.0.0":{"url":"./.pnpm/saxes@6.0.0/node_modules/saxes","dependencies":{"saxes":"saxes@6.0.0","xmlchars":"xmlchars@2.2.0"}},"scule@1.3.0":{"url":"./.pnpm/scule@1.3.0/node_modules/scule","dependencies":{"scule":"scule@1.3.0"}},"semver@7.8.5":{"url":"./.pnpm/semver@7.8.5/node_modules/semver","dependencies":{"semver":"semver@7.8.5"}},"shared":{"url":"../shared","dependencies":{}},"shebang-command@2.0.0":{"url":"./.pnpm/shebang-command@2.0.0/node_modules/shebang-command","dependencies":{"shebang-command":"shebang-command@2.0.0","shebang-regex":"shebang-regex@3.0.0"}},"shebang-regex@3.0.0":{"url":"./.pnpm/shebang-regex@3.0.0/node_modules/shebang-regex","dependencies":{"shebang-regex":"shebang-regex@3.0.0"}},"siginfo@2.0.0":{"url":"./.pnpm/siginfo@2.0.0/node_modules/siginfo","dependencies":{"siginfo":"siginfo@2.0.0"}},"signal-exit@4.1.0":{"url":"./.pnpm/signal-exit@4.1.0/node_modules/signal-exit","dependencies":{"signal-exit":"signal-exit@4.1.0"}},"sortablejs@1.15.7":{"url":"./.pnpm/sortablejs@1.15.7/node_modules/sortablejs","dependencies":{"sortablejs":"sortablejs@1.15.7"}},"source-map-js@1.2.1":{"url":"./.pnpm/source-map-js@1.2.1/node_modules/source-map-js","dependencies":{"source-map-js":"source-map-js@1.2.1"}},"stackback@0.0.2":{"url":"./.pnpm/stackback@0.0.2/node_modules/stackback","dependencies":{"stackback":"stackback@0.0.2"}},"std-env@4.2.0":{"url":"./.pnpm/std-env@4.2.0/node_modules/std-env","dependencies":{"std-env":"std-env@4.2.0"}},"string-width@4.2.3":{"url":"./.pnpm/string-width@4.2.3/node_modules/string-width","dependencies":{"emoji-regex":"emoji-regex@8.0.0","is-fullwidth-code-point":"is-fullwidth-code-point@3.0.0","string-width":"string-width@4.2.3","strip-ansi":"strip-ansi@6.0.1"}},"string-width@5.1.2":{"url":"./.pnpm/string-width@5.1.2/node_modules/string-width","dependencies":{"eastasianwidth":"eastasianwidth@0.2.0","emoji-regex":"emoji-regex@9.2.2","string-width":"string-width@5.1.2","strip-ansi":"strip-ansi@7.2.0"}},"strip-ansi@6.0.1":{"url":"./.pnpm/strip-ansi@6.0.1/node_modules/strip-ansi","dependencies":{"ansi-regex":"ansi-regex@5.0.1","strip-ansi":"strip-ansi@6.0.1"}},"strip-ansi@7.2.0":{"url":"./.pnpm/strip-ansi@7.2.0/node_modules/strip-ansi","dependencies":{"ansi-regex":"ansi-regex@6.2.2","strip-ansi":"strip-ansi@7.2.0"}},"strip-literal@3.1.0":{"url":"./.pnpm/strip-literal@3.1.0/node_modules/strip-literal","dependencies":{"js-tokens":"js-tokens@9.0.1","strip-literal":"strip-literal@3.1.0"}},"symbol-tree@3.2.4":{"url":"./.pnpm/symbol-tree@3.2.4/node_modules/symbol-tree","dependencies":{"symbol-tree":"symbol-tree@3.2.4"}},"tinybench@2.9.0":{"url":"./.pnpm/tinybench@2.9.0/node_modules/tinybench","dependencies":{"tinybench":"tinybench@2.9.0"}},"tinyexec@1.2.4":{"url":"./.pnpm/tinyexec@1.2.4/node_modules/tinyexec","dependencies":{"tinyexec":"tinyexec@1.2.4"}},"tinyglobby@0.2.17":{"url":"./.pnpm/tinyglobby@0.2.17/node_modules/tinyglobby","dependencies":{"fdir":"fdir@6.5.0(picomatch@4.0.5)","picomatch":"picomatch@4.0.5","tinyglobby":"tinyglobby@0.2.17"}},"tinyrainbow@3.1.0":{"url":"./.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow","dependencies":{"tinyrainbow":"tinyrainbow@3.1.0"}},"tldts-core@7.4.9":{"url":"./.pnpm/tldts-core@7.4.9/node_modules/tldts-core","dependencies":{"tldts-core":"tldts-core@7.4.9"}},"tldts@7.4.9":{"url":"./.pnpm/tldts@7.4.9/node_modules/tldts","dependencies":{"tldts":"tldts@7.4.9","tldts-core":"tldts-core@7.4.9"}},"tough-cookie@6.0.2":{"url":"./.pnpm/tough-cookie@6.0.2/node_modules/tough-cookie","dependencies":{"tldts":"tldts@7.4.9","tough-cookie":"tough-cookie@6.0.2"}},"tr46@6.0.0":{"url":"./.pnpm/tr46@6.0.0/node_modules/tr46","dependencies":{"punycode":"punycode@2.3.1","tr46":"tr46@6.0.0"}},"tslib@2.8.1":{"url":"./.pnpm/tslib@2.8.1/node_modules/tslib","dependencies":{"tslib":"tslib@2.8.1"}},"typescript@5.9.3":{"url":"./.pnpm/typescript@5.9.3/node_modules/typescript","dependencies":{"typescript":"typescript@5.9.3"}},"ufo@1.6.4":{"url":"./.pnpm/ufo@1.6.4/node_modules/ufo","dependencies":{"ufo":"ufo@1.6.4"}},"undici-types@7.18.2":{"url":"./.pnpm/undici-types@7.18.2/node_modules/undici-types","dependencies":{"undici-types":"undici-types@7.18.2"}},"undici@7.29.0":{"url":"./.pnpm/undici@7.29.0/node_modules/undici","dependencies":{"undici":"undici@7.29.0"}},"unimport@5.7.0":{"url":"./.pnpm/unimport@5.7.0/node_modules/unimport","dependencies":{"acorn":"acorn@8.17.0","escape-string-regexp":"escape-string-regexp@5.0.0","estree-walker":"estree-walker@3.0.3","local-pkg":"local-pkg@1.2.1","magic-string":"magic-string@0.30.21","mlly":"mlly@1.8.2","pathe":"pathe@2.0.3","picomatch":"picomatch@4.0.5","pkg-types":"pkg-types@2.3.1","scule":"scule@1.3.0","strip-literal":"strip-literal@3.1.0","tinyglobby":"tinyglobby@0.2.17","unimport":"unimport@5.7.0","unplugin":"unplugin@2.3.11","unplugin-utils":"unplugin-utils@0.3.2"}},"unplugin-auto-import@21.0.0(@vueuse/core@14.3.0(vue@3.5.40(typescript@5.9.3)))":{"url":"./.pnpm/unplugin-auto-import@21.0.0_407d79210ed26e1b67c9bae89ae794e7/node_modules/unplugin-auto-import","dependencies":{"@vueuse/core":"@vueuse/core@14.3.0(vue@3.5.40(typescript@5.9.3))","local-pkg":"local-pkg@1.2.1","magic-string":"magic-string@0.30.21","picomatch":"picomatch@4.0.5","unimport":"unimport@5.7.0","unplugin":"unplugin@2.3.11","unplugin-auto-import":"unplugin-auto-import@21.0.0(@vueuse/core@14.3.0(vue@3.5.40(typescript@5.9.3)))","unplugin-utils":"unplugin-utils@0.3.2"}},"unplugin-utils@0.3.2":{"url":"./.pnpm/unplugin-utils@0.3.2/node_modules/unplugin-utils","dependencies":{"pathe":"pathe@2.0.3","picomatch":"picomatch@4.0.5","unplugin-utils":"unplugin-utils@0.3.2"}},"unplugin-vue-components@32.1.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3))":{"url":"./.pnpm/unplugin-vue-components@32._5895c473a797c7a0430a04f9edbf0e54/node_modules/unplugin-vue-components","dependencies":{"chokidar":"chokidar@5.0.0","local-pkg":"local-pkg@1.2.1","magic-string":"magic-string@0.30.21","mlly":"mlly@1.8.2","obug":"obug@2.1.4","picomatch":"picomatch@4.0.5","tinyglobby":"tinyglobby@0.2.17","unplugin":"unplugin@3.3.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))","unplugin-utils":"unplugin-utils@0.3.2","unplugin-vue-components":"unplugin-vue-components@32.1.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3))","vue":"vue@3.5.40(typescript@5.9.3)"}},"unplugin@2.3.11":{"url":"./.pnpm/unplugin@2.3.11/node_modules/unplugin","dependencies":{"@jridgewell/remapping":"@jridgewell/remapping@2.3.5","acorn":"acorn@8.17.0","picomatch":"picomatch@4.0.5","unplugin":"unplugin@2.3.11","webpack-virtual-modules":"webpack-virtual-modules@0.6.2"}},"unplugin@3.3.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))":{"url":"./.pnpm/unplugin@3.3.0_rolldown@1.1_f6b35aa598b76edb8152c0573cfac818/node_modules/unplugin","dependencies":{"@jridgewell/remapping":"@jridgewell/remapping@2.3.5","picomatch":"picomatch@4.0.5","rolldown":"rolldown@1.1.5","unplugin":"unplugin@3.3.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))","vite":"vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)","webpack-virtual-modules":"webpack-virtual-modules@0.6.2"}},"vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)":{"url":"./.pnpm/vite@8.1.5_@types+node@24.13.3_yaml@2.9.0/node_modules/vite","dependencies":{"@types/node":"@types/node@24.13.3","fsevents":"fsevents@2.3.3","lightningcss":"lightningcss@1.33.0","picomatch":"picomatch@4.0.5","postcss":"postcss@8.5.23","rolldown":"rolldown@1.1.5","tinyglobby":"tinyglobby@0.2.17","vite":"vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)","yaml":"yaml@2.9.0"}},"vitest@4.1.10(@types/node@24.13.3)(jsdom@29.1.1)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))":{"url":"./.pnpm/vitest@4.1.10_@types+node@2_684c6d116269d8b9a57007d2e711980e/node_modules/vitest","dependencies":{"@types/node":"@types/node@24.13.3","@vitest/expect":"@vitest/expect@4.1.10","@vitest/mocker":"@vitest/mocker@4.1.10(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))","@vitest/pretty-format":"@vitest/pretty-format@4.1.10","@vitest/runner":"@vitest/runner@4.1.10","@vitest/snapshot":"@vitest/snapshot@4.1.10","@vitest/spy":"@vitest/spy@4.1.10","@vitest/utils":"@vitest/utils@4.1.10","es-module-lexer":"es-module-lexer@2.3.1","expect-type":"expect-type@1.4.0","jsdom":"jsdom@29.1.1","magic-string":"magic-string@0.30.21","obug":"obug@2.1.4","pathe":"pathe@2.0.3","picomatch":"picomatch@4.0.5","std-env":"std-env@4.2.0","tinybench":"tinybench@2.9.0","tinyexec":"tinyexec@1.2.4","tinyglobby":"tinyglobby@0.2.17","tinyrainbow":"tinyrainbow@3.1.0","vite":"vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)","vitest":"vitest@4.1.10(@types/node@24.13.3)(jsdom@29.1.1)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))","why-is-node-running":"why-is-node-running@2.3.0"}},"vscode-uri@3.1.0":{"url":"./.pnpm/vscode-uri@3.1.0/node_modules/vscode-uri","dependencies":{"vscode-uri":"vscode-uri@3.1.0"}},"vue-component-type-helpers@3.3.8":{"url":"./.pnpm/vue-component-type-helpers@3.3.8/node_modules/vue-component-type-helpers","dependencies":{"vue-component-type-helpers":"vue-component-type-helpers@3.3.8"}},"vue-router@5.2.0(@vue/compiler-sfc@3.5.40)(pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@5.9.3)(vue@3.5.40(typescript@5.9.3)))(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3))":{"url":"./.pnpm/vue-router@5.2.0_@vue+compi_b4a151216dd2fb3ddc479aca26abbdbb/node_modules/vue-router","dependencies":{"@babel/generator":"@babel/generator@8.0.0","@vue-macros/common":"@vue-macros/common@3.1.4(vue@3.5.40(typescript@5.9.3))","@vue/compiler-sfc":"@vue/compiler-sfc@3.5.40","@vue/devtools-api":"@vue/devtools-api@8.2.1","ast-walker-scope":"ast-walker-scope@0.9.0","chokidar":"chokidar@5.0.0","json5":"json5@2.2.3","local-pkg":"local-pkg@1.2.1","magic-string":"magic-string@0.30.21","mlly":"mlly@1.8.2","muggle-string":"muggle-string@0.4.1","nostics":"nostics@1.2.0","pathe":"pathe@2.0.3","picomatch":"picomatch@4.0.5","pinia":"pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@5.9.3)(vue@3.5.40(typescript@5.9.3))","scule":"scule@1.3.0","tinyglobby":"tinyglobby@0.2.17","unplugin":"unplugin@3.3.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))","unplugin-utils":"unplugin-utils@0.3.2","vite":"vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)","vue":"vue@3.5.40(typescript@5.9.3)","vue-router":"vue-router@5.2.0(@vue/compiler-sfc@3.5.40)(pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@5.9.3)(vue@3.5.40(typescript@5.9.3)))(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3))","yaml":"yaml@2.9.0"}},"vue-tsc@3.3.8(typescript@5.9.3)":{"url":"./.pnpm/vue-tsc@3.3.8_typescript@5.9.3/node_modules/vue-tsc","dependencies":{"@volar/typescript":"@volar/typescript@2.4.28","@vue/language-core":"@vue/language-core@3.3.8","typescript":"typescript@5.9.3","vue-tsc":"vue-tsc@3.3.8(typescript@5.9.3)"}},"vue@3.5.40(typescript@5.9.3)":{"url":"./.pnpm/vue@3.5.40_typescript@5.9.3/node_modules/vue","dependencies":{"@vue/compiler-dom":"@vue/compiler-dom@3.5.40","@vue/compiler-sfc":"@vue/compiler-sfc@3.5.40","@vue/runtime-dom":"@vue/runtime-dom@3.5.40","@vue/server-renderer":"@vue/server-renderer@3.5.40","@vue/shared":"@vue/shared@3.5.40","typescript":"typescript@5.9.3","vue":"vue@3.5.40(typescript@5.9.3)"}},"w3c-xmlserializer@5.0.0":{"url":"./.pnpm/w3c-xmlserializer@5.0.0/node_modules/w3c-xmlserializer","dependencies":{"w3c-xmlserializer":"w3c-xmlserializer@5.0.0","xml-name-validator":"xml-name-validator@5.0.0"}},"webidl-conversions@8.0.1":{"url":"./.pnpm/webidl-conversions@8.0.1/node_modules/webidl-conversions","dependencies":{"webidl-conversions":"webidl-conversions@8.0.1"}},"webpack-virtual-modules@0.6.2":{"url":"./.pnpm/webpack-virtual-modules@0.6.2/node_modules/webpack-virtual-modules","dependencies":{"webpack-virtual-modules":"webpack-virtual-modules@0.6.2"}},"whatwg-mimetype@5.0.0":{"url":"./.pnpm/whatwg-mimetype@5.0.0/node_modules/whatwg-mimetype","dependencies":{"whatwg-mimetype":"whatwg-mimetype@5.0.0"}},"whatwg-url@16.0.1":{"url":"./.pnpm/whatwg-url@16.0.1/node_modules/whatwg-url","dependencies":{"@exodus/bytes":"@exodus/bytes@1.15.1","tr46":"tr46@6.0.0","webidl-conversions":"webidl-conversions@8.0.1","whatwg-url":"whatwg-url@16.0.1"}},"which@2.0.2":{"url":"./.pnpm/which@2.0.2/node_modules/which","dependencies":{"isexe":"isexe@2.0.0","which":"which@2.0.2"}},"why-is-node-running@2.3.0":{"url":"./.pnpm/why-is-node-running@2.3.0/node_modules/why-is-node-running","dependencies":{"siginfo":"siginfo@2.0.0","stackback":"stackback@0.0.2","why-is-node-running":"why-is-node-running@2.3.0"}},"wrap-ansi@7.0.0":{"url":"./.pnpm/wrap-ansi@7.0.0/node_modules/wrap-ansi","dependencies":{"ansi-styles":"ansi-styles@4.3.0","string-width":"string-width@4.2.3","strip-ansi":"strip-ansi@6.0.1","wrap-ansi":"wrap-ansi@7.0.0"}},"wrap-ansi@8.1.0":{"url":"./.pnpm/wrap-ansi@8.1.0/node_modules/wrap-ansi","dependencies":{"ansi-styles":"ansi-styles@6.2.3","string-width":"string-width@5.1.2","strip-ansi":"strip-ansi@7.2.0","wrap-ansi":"wrap-ansi@8.1.0"}},"xml-name-validator@5.0.0":{"url":"./.pnpm/xml-name-validator@5.0.0/node_modules/xml-name-validator","dependencies":{"xml-name-validator":"xml-name-validator@5.0.0"}},"xmlchars@2.2.0":{"url":"./.pnpm/xmlchars@2.2.0/node_modules/xmlchars","dependencies":{"xmlchars":"xmlchars@2.2.0"}},"yaml@2.9.0":{"url":"./.pnpm/yaml@2.9.0/node_modules/yaml","dependencies":{"yaml":"yaml@2.9.0"}}}} diff --git a/node_modules.corrupt/.pnpm-workspace-state-v1.json b/node_modules.corrupt/.pnpm-workspace-state-v1.json new file mode 100644 index 00000000..10d7c6db --- /dev/null +++ b/node_modules.corrupt/.pnpm-workspace-state-v1.json @@ -0,0 +1,29 @@ +{ + "lastValidatedTimestamp": 1787208452958, + "projects": {}, + "pnpmfiles": [], + "settings": { + "autoInstallPeers": true, + "dedupeDirectDeps": false, + "dedupeInjectedDeps": true, + "dedupePeerDependents": true, + "dedupePeers": false, + "dev": true, + "excludeLinksFromLockfile": false, + "hoistPattern": [ + "*" + ], + "hoistWorkspacePackages": true, + "injectWorkspacePackages": false, + "linkWorkspacePackages": false, + "minimumReleaseAge": 1440, + "minimumReleaseAgeIgnoreMissingTime": true, + "nodeLinker": "isolated", + "optional": true, + "peersSuffixMaxLength": 1000, + "preferWorkspacePackages": false, + "production": true, + "publicHoistPattern": [] + }, + "filteredInstall": false +} diff --git a/node_modules.corrupt/.pnpm/lock.yaml b/node_modules.corrupt/.pnpm/lock.yaml new file mode 100644 index 00000000..f9855f2d --- /dev/null +++ b/node_modules.corrupt/.pnpm/lock.yaml @@ -0,0 +1,2657 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@chongchong/shared': + specifier: link:./shared + version: link:./shared + '@lucide/vue': + specifier: ^1.27.0 + version: 1.27.0(vue@3.5.40(typescript@5.9.3)) + axios: + specifier: ^1.18.1 + version: 1.18.1(debug@4.4.3) + element-plus: + specifier: ^2.14.3 + version: 2.14.3(vue@3.5.40(typescript@5.9.3)) + pinia: + specifier: ^4.0.2 + version: 4.0.2(@vue/devtools-api@8.2.1)(typescript@5.9.3)(vue@3.5.40(typescript@5.9.3)) + sortablejs: + specifier: ^1.15.7 + version: 1.15.7 + vue: + specifier: ^3.5.40 + version: 3.5.40(typescript@5.9.3) + vue-router: + specifier: ^5.2.0 + version: 5.2.0(@vue/compiler-sfc@3.5.40)(pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@5.9.3)(vue@3.5.40(typescript@5.9.3)))(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3)) + devDependencies: + '@types/node': + specifier: ^24.10.0 + version: 24.13.3 + '@types/sortablejs': + specifier: ^1.15.9 + version: 1.15.9 + '@vitejs/plugin-vue': + specifier: ^6.0.8 + version: 6.0.8(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3)) + '@vue/test-utils': + specifier: ^2.4.11 + version: 2.4.11(@vue/compiler-dom@3.5.40)(@vue/server-renderer@3.5.40)(vue@3.5.40(typescript@5.9.3)) + jsdom: + specifier: ^29.1.1 + version: 29.1.1 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + unplugin-auto-import: + specifier: ^21.0.0 + version: 21.0.0(@vueuse/core@14.3.0(vue@3.5.40(typescript@5.9.3))) + unplugin-vue-components: + specifier: ^32.1.0 + version: 32.1.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3)) + vite: + specifier: ^8.1.5 + version: 8.1.5(@types/node@24.13.3)(yaml@2.9.0) + vitest: + specifier: ^4.1.10 + version: 4.1.10(@types/node@24.13.3)(jsdom@29.1.1)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)) + vue-tsc: + specifier: ^3.3.8 + version: 3.3.8(typescript@5.9.3) + +packages: + + '@asamuzakjp/css-color@5.1.11': + resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/dom-selector@7.1.1': + resolution: {integrity: sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/generational-cache@1.0.1': + resolution: {integrity: sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + + '@babel/generator@8.0.0': + resolution: {integrity: sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@8.0.0': + resolution: {integrity: sha512-6mJgmFFFIIO82vvoLt9XtRC7/TkzXfts1t/SpRX4IHSzMgqoPYCWesVu1udUPUWioAE/2fcG6WuI8zrkE1gwrg==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@8.0.4': + resolution: {integrity: sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/parser@8.0.4': + resolution: {integrity: sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==} + engines: {node: ^22.18.0 || >=24.11.0} + hasBin: true + + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + engines: {node: '>=6.9.0'} + + '@babel/types@8.0.4': + resolution: {integrity: sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@bramus/specificity@2.4.2': + resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} + hasBin: true + + '@csstools/color-helpers@6.1.0': + resolution: {integrity: sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==} + engines: {node: '>=20.19.0'} + + '@csstools/css-calc@3.3.0': + resolution: {integrity: sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-color-parser@4.1.10': + resolution: {integrity: sha512-UZhQLIUyJaaMepqehrCODwCg2KW25vFvLWBmqYFaPclYvvxzj/sG8LBOhBFCp11i9uE7t1EyS+RAoV9tztPFyw==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-parser-algorithms@4.0.0': + resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.7': + resolution: {integrity: sha512-fQ+05118eQS1cofO3aJpB5efgpBZMvIzwr/sbC8kDLVA5XLG8q1kJV5yzrUAI1f7lvhPnm8fgIjzFB8/O/5Dig==} + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true + + '@csstools/css-tokenizer@4.0.0': + resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + engines: {node: '>=20.19.0'} + + '@ctrl/tinycolor@4.2.0': + resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==} + engines: {node: '>=14'} + + '@element-plus/icons-vue@2.3.2': + resolution: {integrity: sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==} + peerDependencies: + vue: ^3.2.0 + + '@emnapi/core@1.11.1': + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + + '@exodus/bytes@1.15.1': + resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@noble/hashes': ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + '@noble/hashes': + optional: true + + '@floating-ui/core@1.8.0': + resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==} + + '@floating-ui/dom@1.8.0': + resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==} + + '@floating-ui/utils@0.2.12': + resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@lucide/vue@1.27.0': + resolution: {integrity: sha512-LKDEZJ0Uo9UaT4vxBMYVwXeK/0dGcWCTdav1AK/aGD/jYsDPtiVvOgfM7jPlx9BVeyGZ1Uf0aQhHA++rmbe7rw==} + peerDependencies: + vue: '>=3.0.1' + + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@one-ini/wasm@0.1.1': + resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + + '@oxc-project/types@0.139.0': + resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@rolldown/binding-android-arm64@1.1.5': + resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.1.5': + resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.1.5': + resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.1.5': + resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.1.5': + resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.1.5': + resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.1.5': + resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.1.5': + resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.1.5': + resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.1.5': + resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.1.5': + resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.1.5': + resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.1.5': + resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.1.5': + resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@sxzz/popperjs-es@2.11.8': + resolution: {integrity: sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==} + + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/jsesc@2.5.1': + resolution: {integrity: sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==} + + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash@4.17.24': + resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} + + '@types/node@24.13.3': + resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==} + + '@types/sortablejs@1.15.9': + resolution: {integrity: sha512-7HP+rZGE2p886PKV9c9OJzLBI6BBJu1O7lJGYnPyG3fS4/duUCcngkNCjsLwIMV+WMqANe3tt4irrXHSIe68OQ==} + + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + + '@vitejs/plugin-vue@6.0.8': + resolution: {integrity: sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + vue: ^3.2.25 + + '@vitest/expect@4.1.10': + resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} + + '@vitest/mocker@4.1.10': + resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.10': + resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} + + '@vitest/runner@4.1.10': + resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} + + '@vitest/snapshot@4.1.10': + resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} + + '@vitest/spy@4.1.10': + resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} + + '@vitest/utils@4.1.10': + resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} + + '@volar/language-core@2.4.28': + resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} + + '@volar/source-map@2.4.28': + resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==} + + '@volar/typescript@2.4.28': + resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==} + + '@vue-macros/common@3.1.4': + resolution: {integrity: sha512-/5Fv+6DgIcM9ajY05ZmKBv+LMX1M9A0X+IUwDRVdt67ciw8OV9bvG2r34p3RiEadlsQybjhKPRKNXDC8Bp23cw==} + engines: {node: '>=20.19.0'} + peerDependencies: + vue: ^2.7.0 || ^3.2.25 + peerDependenciesMeta: + vue: + optional: true + + '@vue/compiler-core@3.5.40': + resolution: {integrity: sha512-39E8IgOhTbVDnoJFMKc2DvYnypcZwUqgUhQkccva/0m6FUwtIKSGV7n1hpVmYcFaoRAwf9pBcwnKlCEsN63ZEQ==} + + '@vue/compiler-dom@3.5.40': + resolution: {integrity: sha512-pwkx4vqlqOspFstrcmzwkKLePVMD3PT65imRzLhanU2V1Fj4K13g6OXjanOyzw3aTAuRk84BOmY8f3rEHqPaVA==} + + '@vue/compiler-sfc@3.5.40': + resolution: {integrity: sha512-gIf497P4kpuALcvs5n3AEg1Vdn0pSY4XbjASIfHNYF1/MP3T2Mf2STERTubysBxCRxzJGJYtF/O7vwJrxFB3Vw==} + + '@vue/compiler-ssr@3.5.40': + resolution: {integrity: sha512-rrE5xiXG663+vHCHa3J9p2z5OcBRjXmoqenprJxAFQxg5pSshzeBiCE6pu46axapRJ2Adk0YDA2BRZVjiHXnhg==} + + '@vue/devtools-api@8.2.1': + resolution: {integrity: sha512-6u4vXBlIBAC1wMplIZgpyPn7uh/s4Bf6F5bMzvLv+EdJ0aHs/+4B7Ygv864EStQSjRbsRzTko/kUG1A1IejQ3A==} + + '@vue/devtools-kit@8.2.1': + resolution: {integrity: sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==} + + '@vue/devtools-shared@8.2.1': + resolution: {integrity: sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==} + + '@vue/language-core@3.3.8': + resolution: {integrity: sha512-ieGT8jJdhhy0mGzStZhsg/qPw5bQZJg5yF+3+XU6saf4sM7yo9ZXy3h+nCwrm2+b4qS/SypkNdR2jAF3uei9tA==} + + '@vue/reactivity@3.5.40': + resolution: {integrity: sha512-B7ot9UlUZOi1zbq61/LvE88ZLTV8IlajTdiZTAEiDQgrnIMIZoPr9kGw0Zw46ObW62O9+H/Be3kMbfb7kYPQZA==} + + '@vue/runtime-core@3.5.40': + resolution: {integrity: sha512-KAZLweuZ6uUJPK1PMSQPgBU5gCjgrrfjUhSglmU9NhH+Zjepa8cnwSydPWDWHDwOgY4g3VcZ+PljbiHlURNCbw==} + + '@vue/runtime-dom@3.5.40': + resolution: {integrity: sha512-ZfrX8ssZQds900L9pr8AuK05ddnMsR4MPMZr8cPN9GoqoPWcXLhjvvbIA2SMv+7a97sJ1vv9pj/zxK0Cq/eEFQ==} + + '@vue/server-renderer@3.5.40': + resolution: {integrity: sha512-XNJym9WpevhTVt1HuwOrCRJ5Q+9z4BjTMrDtjTrvx74SmUll8spNTw6whWJa9mEkO4PKn5TihI/bm/8ds2QVJw==} + + '@vue/shared@3.5.40': + resolution: {integrity: sha512-WxnBtruIqOoV3rA4jeKDWzrYI5h7Cp4+pjwDi8kWGHz+IslhiN+wguLVVhtv2l8VoU02rzDCVfDjgCl1lNpZVg==} + + '@vue/test-utils@2.4.11': + resolution: {integrity: sha512-GDqaqZsA6m2E5vNzej0aYiIb6BX8xV9pNSbbbXKOfEYwg7ZNblVX8suyqmUBThq8VIrgAJNxn+z72hVtUeiWHA==} + peerDependencies: + '@vue/compiler-dom': 3.x + '@vue/server-renderer': 3.x + vue: 3.x + peerDependenciesMeta: + '@vue/server-renderer': + optional: true + + '@vueuse/core@14.3.0': + resolution: {integrity: sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==} + peerDependencies: + vue: ^3.5.0 + + '@vueuse/metadata@14.3.0': + resolution: {integrity: sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==} + + '@vueuse/shared@14.3.0': + resolution: {integrity: sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==} + peerDependencies: + vue: ^3.5.0 + + abbrev@2.0.0: + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + acorn@8.17.0: + resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + alien-signals@3.2.1: + resolution: {integrity: sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-kit@2.2.0: + resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==} + engines: {node: '>=20.19.0'} + + ast-walker-scope@0.9.0: + resolution: {integrity: sha512-IJdzo2vLiElBxKzwS36VsCue/62d6IdWjnPB2v3nuPKeWGynp6FF/CYoLa5i/3jXH/z97ZDdsXz6abpgM6w07A==} + engines: {node: '>=20.19.0'} + + async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.18.1: + resolution: {integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + + birpc@2.9.0: + resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==} + + brace-expansion@2.1.2: + resolution: {integrity: sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + confbox@0.2.4: + resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} + + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + data-urls@7.0.0: + resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + dayjs@1.11.21: + resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + editorconfig@1.0.7: + resolution: {integrity: sha512-e0GOtq/aTQhVdNyDU9e02+wz9oDDM+SIOQxWME2QRjzRX5yyLAuHDE+0aE8vHb9XRC8XD37eO2u57+F09JqFhw==} + engines: {node: '>=14'} + hasBin: true + + element-plus@2.14.3: + resolution: {integrity: sha512-pJcvxcpZjYruNzuJhAeVwnbYjfNgzBKnWHwSVEhwzM2/kcLI3brzmtIBxtPqd4hQWJfD1PRnjoc1WipLw2eBGg==} + peerDependencies: + vue: ^3.3.7 + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + entities@8.0.0: + resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} + engines: {node: '>=20.19.0'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@2.3.1: + resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} + engines: {node: '>=12.0.0'} + + exsolve@1.1.0: + resolution: {integrity: sha512-D+42+T12DdIlJM3uepa55qGiL3sYdLBOxIl2ifQCzCHz4c7eiolaHsi3BIqEr7JxBzxv2pYZQX9kw16ziMcEmw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} + engines: {node: '>= 6'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + html-encoding-sniffer@6.0.0: + resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + js-beautify@1.15.4: + resolution: {integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==} + engines: {node: '>=14'} + hasBin: true + + js-cookie@3.0.8: + resolution: {integrity: sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==} + + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + + jsdom@29.1.1: + resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + + local-pkg@1.2.1: + resolution: {integrity: sha512-++gUqRDEvcnN6Zhqrr+y/CkVEHhlrR96vZn3nZZPYzMcBUyBtTKzB9NadClFIsIVSsu+3i9tfk/erqy9kAmt7Q==} + engines: {node: '>=14'} + + lodash-es@4.18.1: + resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} + + lodash-unified@1.0.3: + resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==} + peerDependencies: + '@types/lodash-es': '*' + lodash: '*' + lodash-es: '*' + + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} + engines: {node: 20 || >=22} + + magic-string-ast@1.0.3: + resolution: {integrity: sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==} + engines: {node: '>=20.19.0'} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + + memoize-one@6.0.0: + resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + nanoid@3.3.16: + resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nopt@7.2.1: + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + normalize-wheel-es@1.2.0: + resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==} + + nostics@1.2.0: + resolution: {integrity: sha512-FGqEfhQjrvo1lL8KFifdTQiNwwQHJxC1jtYE1Rc54qF/jxONUNL+kC9gS1krX8Q65PgrQ5fCqH/I4NhWBvdSqg==} + + obug@2.1.4: + resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} + engines: {node: '>=12.20.0'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parse5@8.0.1: + resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + perfect-debounce@2.1.0: + resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + pinia@4.0.2: + resolution: {integrity: sha512-yKVVA7bSj5oRZFp/Ab9wLlmyb5gPUYEiIm4ryiWTe/xe7PtkRdMVOp1X1ggvq0c6Uj7Q0Du1HnV2mtAwM0Ks1g==} + peerDependencies: + '@vue/devtools-api': ^8.1.5 + typescript: '>=5.6.0' + vue: ^3.5.11 + peerDependenciesMeta: + typescript: + optional: true + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + pkg-types@2.3.1: + resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==} + + postcss@8.5.23: + resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==} + engines: {node: ^10 || ^12 || >=14} + + proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + rolldown@1.1.5: + resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + + scule@1.3.0: + resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sortablejs@1.15.7: + resolution: {integrity: sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@4.2.0: + resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + + tldts-core@7.4.9: + resolution: {integrity: sha512-DxKfPBI52p2msTEu7MPhdpdDTBhhVQg1a/8PjQckeyAvO13eMYElX545grIp6nnTGIMZlRvFZPvFhvI/WIz2Vg==} + + tldts@7.4.9: + resolution: {integrity: sha512-3kZ8wQQ/k5DrChD4X4FVvr2D7E5uoRgAqkPyLpSCGUvqOvqu+JEdr3mwMUaVWb+vMHZaKhF5fp2PBigKsui7hA==} + hasBin: true + + tough-cookie@6.0.2: + resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} + engines: {node: '>=16'} + + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + undici@7.29.0: + resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} + engines: {node: '>=20.18.1'} + + unimport@5.7.0: + resolution: {integrity: sha512-njnL6sp8lEA8QQbZrt+52p/g4X0rw3bnGGmUcJnt1jeG8+iiqO779aGz0PirCtydAIVcuTBRlJ52F0u46z309Q==} + engines: {node: '>=18.12.0'} + + unplugin-auto-import@21.0.0: + resolution: {integrity: sha512-vWuC8SwqJmxZFYwPojhOhOXDb5xFhNNcEVb9K/RFkyk/3VnfaOjzitWN7v+8DEKpMjSsY2AEGXNgt6I0yQrhRQ==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@nuxt/kit': ^4.0.0 + '@vueuse/core': '*' + peerDependenciesMeta: + '@nuxt/kit': + optional: true + '@vueuse/core': + optional: true + + unplugin-utils@0.3.2: + resolution: {integrity: sha512-xVToRh2CTmLk2HnEG7ac4rl1MJTT3RFkpS8B++/SnB0kXvuaavD+n3m/vrzyWQOdJNSZQACnbz01pnppbwV5BA==} + engines: {node: '>=20.19.0'} + + unplugin-vue-components@32.1.0: + resolution: {integrity: sha512-YiUkSxuRjab18XFOrX5VsIxXzccrfmHVGsGeJgSgklb829DQmCy9E4vvDUE4tuvZZdxyFJZX0Oc4TPnnxiiMyg==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@nuxt/kit': ^3.2.2 || ^4.0.0 + vue: ^3.0.0 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + + unplugin@2.3.11: + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.0'} + + unplugin@3.3.0: + resolution: {integrity: sha512-qa66K+crbfyE6JK10GjvbJeRrOsuC/JpbnHctfyp/i4oBTxWOzJfRZyDiOk1PtErMFRu8JhsU/wPvOdBNWe5Rg==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@farmfe/core': '*' + '@rspack/core': '*' + bun-types-no-globals: '*' + esbuild: '*' + rolldown: '*' + rollup: '*' + unloader: '*' + vite: '*' + webpack: '*' + peerDependenciesMeta: + '@farmfe/core': + optional: true + '@rspack/core': + optional: true + bun-types-no-globals: + optional: true + esbuild: + optional: true + rolldown: + optional: true + rollup: + optional: true + unloader: + optional: true + vite: + optional: true + webpack: + optional: true + + vite@8.1.5: + resolution: {integrity: sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.3.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@4.1.10: + resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.10 + '@vitest/browser-preview': 4.1.10 + '@vitest/browser-webdriverio': 4.1.10 + '@vitest/coverage-istanbul': 4.1.10 + '@vitest/coverage-v8': 4.1.10 + '@vitest/ui': 4.1.10 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + vue-component-type-helpers@3.3.8: + resolution: {integrity: sha512-troqCMmQodQDqUqn63NQaFi+CDSclSe7sc8VEBFqf5GFLqmGR2Ph3P2WEC7qwpRVyEWsTi/aAr4vyOe/B1hU3g==} + + vue-router@5.2.0: + resolution: {integrity: sha512-QAC5i0LEb1GLG0LXDQmHu8L7FX12j0KwU/JTKmLQUJMrn04gQdKP6Du+p0QwpHb3iy71vBlqnHQ8WAfOSAWhqw==} + peerDependencies: + '@pinia/colada': '>=0.21.2' + '@vue/compiler-sfc': ^3.5.34 || ^4.0.0 + pinia: ^3.0.4 || ^4.0.2 + vite: ^7.3.0 || ^8.0.0 + vue: ^3.5.34 || ^4.0.0 + peerDependenciesMeta: + '@pinia/colada': + optional: true + '@vue/compiler-sfc': + optional: true + pinia: + optional: true + vite: + optional: true + + vue-tsc@3.3.8: + resolution: {integrity: sha512-xXmYlVQpcwJDWyGlqbHrGVOl1h3UOsASymRibrHc+iy9j/UNnOrOn4u+fntHz4D6Cs74RtapeqVV6CzJeg+UlA==} + hasBin: true + peerDependencies: + typescript: '>=5.0.0' + + vue@3.5.40: + resolution: {integrity: sha512-+8PJ4SJXdn/cHGImF4CKdxlWHIN5Dkt7DoufRREM6h6uVCx2m7QxgcEQmmzyOK8A9mcafg7sFbJFYsdFVubTig==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + whatwg-mimetype@5.0.0: + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + engines: {node: '>=20'} + + whatwg-url@16.0.1: + resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true + +snapshots: + + '@asamuzakjp/css-color@5.1.11': + dependencies: + '@asamuzakjp/generational-cache': 1.0.1 + '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@asamuzakjp/dom-selector@7.1.1': + dependencies: + '@asamuzakjp/generational-cache': 1.0.1 + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + + '@asamuzakjp/generational-cache@1.0.1': {} + + '@asamuzakjp/nwsapi@2.3.9': {} + + '@babel/generator@8.0.0': + dependencies: + '@babel/parser': 8.0.4 + '@babel/types': 8.0.4 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@types/jsesc': 2.5.1 + jsesc: 3.1.0 + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-string-parser@8.0.0': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-identifier@8.0.4': {} + + '@babel/parser@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/parser@8.0.4': + dependencies: + '@babel/types': 8.0.4 + + '@babel/types@7.29.7': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@babel/types@8.0.4': + dependencies: + '@babel/helper-string-parser': 8.0.0 + '@babel/helper-validator-identifier': 8.0.4 + + '@bramus/specificity@2.4.2': + dependencies: + css-tree: 3.2.1 + + '@csstools/color-helpers@6.1.0': {} + + '@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-color-parser@4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/color-helpers': 6.1.0 + '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.7(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 + + '@csstools/css-tokenizer@4.0.0': {} + + '@ctrl/tinycolor@4.2.0': {} + + '@element-plus/icons-vue@2.3.2(vue@3.5.40(typescript@5.9.3))': + dependencies: + vue: 3.5.40(typescript@5.9.3) + + '@emnapi/core@1.11.1': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.11.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@exodus/bytes@1.15.1': {} + + '@floating-ui/core@1.8.0': + dependencies: + '@floating-ui/utils': 0.2.12 + + '@floating-ui/dom@1.8.0': + dependencies: + '@floating-ui/core': 1.8.0 + '@floating-ui/utils': 0.2.12 + + '@floating-ui/utils@0.2.12': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@lucide/vue@1.27.0(vue@3.5.40(typescript@5.9.3))': + dependencies: + vue: 3.5.40(typescript@5.9.3) + + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@one-ini/wasm@0.1.1': {} + + '@oxc-project/types@0.139.0': {} + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@rolldown/binding-android-arm64@1.1.5': + optional: true + + '@rolldown/binding-darwin-arm64@1.1.5': + optional: true + + '@rolldown/binding-darwin-x64@1.1.5': + optional: true + + '@rolldown/binding-freebsd-x64@1.1.5': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.1.5': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-x64-musl@1.1.5': + optional: true + + '@rolldown/binding-openharmony-arm64@1.1.5': + optional: true + + '@rolldown/binding-wasm32-wasi@1.1.5': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.1.5': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.1.5': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@standard-schema/spec@1.1.0': {} + + '@sxzz/popperjs-es@2.11.8': {} + + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.9': {} + + '@types/jsesc@2.5.1': {} + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.24 + + '@types/lodash@4.17.24': {} + + '@types/node@24.13.3': + dependencies: + undici-types: 7.18.2 + + '@types/sortablejs@1.15.9': {} + + '@types/web-bluetooth@0.0.21': {} + + '@vitejs/plugin-vue@6.0.8(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3))': + dependencies: + '@rolldown/pluginutils': 1.0.1 + vite: 8.1.5(@types/node@24.13.3)(yaml@2.9.0) + vue: 3.5.40(typescript@5.9.3) + + '@vitest/expect@4.1.10': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.1.10(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))': + dependencies: + '@vitest/spy': 4.1.10 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.1.5(@types/node@24.13.3)(yaml@2.9.0) + + '@vitest/pretty-format@4.1.10': + dependencies: + tinyrainbow: 3.1.0 + + '@vitest/runner@4.1.10': + dependencies: + '@vitest/utils': 4.1.10 + pathe: 2.0.3 + + '@vitest/snapshot@4.1.10': + dependencies: + '@vitest/pretty-format': 4.1.10 + '@vitest/utils': 4.1.10 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.1.10': {} + + '@vitest/utils@4.1.10': + dependencies: + '@vitest/pretty-format': 4.1.10 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + + '@volar/language-core@2.4.28': + dependencies: + '@volar/source-map': 2.4.28 + + '@volar/source-map@2.4.28': {} + + '@volar/typescript@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vue-macros/common@3.1.4(vue@3.5.40(typescript@5.9.3))': + dependencies: + '@vue/compiler-sfc': 3.5.40 + ast-kit: 2.2.0 + local-pkg: 1.2.1 + magic-string-ast: 1.0.3 + unplugin-utils: 0.3.2 + optionalDependencies: + vue: 3.5.40(typescript@5.9.3) + + '@vue/compiler-core@3.5.40': + dependencies: + '@babel/parser': 7.29.7 + '@vue/shared': 3.5.40 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.40': + dependencies: + '@vue/compiler-core': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/compiler-sfc@3.5.40': + dependencies: + '@babel/parser': 7.29.7 + '@vue/compiler-core': 3.5.40 + '@vue/compiler-dom': 3.5.40 + '@vue/compiler-ssr': 3.5.40 + '@vue/shared': 3.5.40 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.23 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.40': + dependencies: + '@vue/compiler-dom': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/devtools-api@8.2.1': + dependencies: + '@vue/devtools-kit': 8.2.1 + + '@vue/devtools-kit@8.2.1': + dependencies: + '@vue/devtools-shared': 8.2.1 + birpc: 2.9.0 + hookable: 5.5.3 + perfect-debounce: 2.1.0 + + '@vue/devtools-shared@8.2.1': {} + + '@vue/language-core@3.3.8': + dependencies: + '@volar/language-core': 2.4.28 + '@vue/compiler-dom': 3.5.40 + '@vue/shared': 3.5.40 + alien-signals: 3.2.1 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + picomatch: 4.0.5 + + '@vue/reactivity@3.5.40': + dependencies: + '@vue/shared': 3.5.40 + + '@vue/runtime-core@3.5.40': + dependencies: + '@vue/reactivity': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/runtime-dom@3.5.40': + dependencies: + '@vue/reactivity': 3.5.40 + '@vue/runtime-core': 3.5.40 + '@vue/shared': 3.5.40 + csstype: 3.2.3 + + '@vue/server-renderer@3.5.40': + dependencies: + '@vue/compiler-ssr': 3.5.40 + '@vue/runtime-dom': 3.5.40 + '@vue/shared': 3.5.40 + + '@vue/shared@3.5.40': {} + + '@vue/test-utils@2.4.11(@vue/compiler-dom@3.5.40)(@vue/server-renderer@3.5.40)(vue@3.5.40(typescript@5.9.3))': + dependencies: + '@vue/compiler-dom': 3.5.40 + js-beautify: 1.15.4 + vue: 3.5.40(typescript@5.9.3) + vue-component-type-helpers: 3.3.8 + optionalDependencies: + '@vue/server-renderer': 3.5.40 + + '@vueuse/core@14.3.0(vue@3.5.40(typescript@5.9.3))': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 14.3.0 + '@vueuse/shared': 14.3.0(vue@3.5.40(typescript@5.9.3)) + vue: 3.5.40(typescript@5.9.3) + + '@vueuse/metadata@14.3.0': {} + + '@vueuse/shared@14.3.0(vue@3.5.40(typescript@5.9.3))': + dependencies: + vue: 3.5.40(typescript@5.9.3) + + abbrev@2.0.0: {} + + acorn@8.17.0: {} + + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + alien-signals@3.2.1: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.3: {} + + assertion-error@2.0.1: {} + + ast-kit@2.2.0: + dependencies: + '@babel/parser': 7.29.7 + pathe: 2.0.3 + + ast-walker-scope@0.9.0: + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + ast-kit: 2.2.0 + + async-validator@4.2.5: {} + + asynckit@0.4.0: {} + + axios@1.18.1(debug@4.4.3): + dependencies: + follow-redirects: 1.16.0(debug@4.4.3) + form-data: 4.0.6 + https-proxy-agent: 5.0.1 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + - supports-color + + balanced-match@1.0.2: {} + + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + + birpc@2.9.0: {} + + brace-expansion@2.1.2: + dependencies: + balanced-match: 1.0.2 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + chai@6.2.2: {} + + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@10.0.1: {} + + confbox@0.1.8: {} + + confbox@0.2.4: {} + + config-chain@1.1.13: + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + + convert-source-map@2.0.0: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + + csstype@3.2.3: {} + + data-urls@7.0.0: + dependencies: + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + transitivePeerDependencies: + - '@noble/hashes' + + dayjs@1.11.21: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decimal.js@10.6.0: {} + + delayed-stream@1.0.0: {} + + detect-libc@2.1.2: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + editorconfig@1.0.7: + dependencies: + '@one-ini/wasm': 0.1.1 + commander: 10.0.1 + minimatch: 9.0.9 + semver: 7.8.5 + + element-plus@2.14.3(vue@3.5.40(typescript@5.9.3)): + dependencies: + '@ctrl/tinycolor': 4.2.0 + '@element-plus/icons-vue': 2.3.2(vue@3.5.40(typescript@5.9.3)) + '@floating-ui/dom': 1.8.0 + '@popperjs/core': '@sxzz/popperjs-es@2.11.8' + '@types/lodash': 4.17.24 + '@types/lodash-es': 4.17.12 + '@vueuse/core': 14.3.0(vue@3.5.40(typescript@5.9.3)) + async-validator: 4.2.5 + dayjs: 1.11.21 + lodash: 4.18.1 + lodash-es: 4.18.1 + lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.18.1)(lodash@4.18.1) + memoize-one: 6.0.0 + normalize-wheel-es: 1.2.0 + vue: 3.5.40(typescript@5.9.3) + vue-component-type-helpers: 3.3.8 + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + entities@7.0.1: {} + + entities@8.0.0: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@2.3.1: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + escape-string-regexp@5.0.0: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + expect-type@1.4.0: {} + + exsolve@1.1.0: {} + + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + + follow-redirects@1.16.0(debug@4.4.3): + optionalDependencies: + debug: 4.4.3 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.6: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.4 + mime-types: 2.1.35 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + gopd@1.2.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + hookable@5.5.3: {} + + html-encoding-sniffer@6.0.0: + dependencies: + '@exodus/bytes': 1.15.1 + transitivePeerDependencies: + - '@noble/hashes' + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + ini@1.3.8: {} + + is-fullwidth-code-point@3.0.0: {} + + is-potential-custom-element-name@1.0.1: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + js-beautify@1.15.4: + dependencies: + config-chain: 1.1.13 + editorconfig: 1.0.7 + glob: 10.5.0 + js-cookie: 3.0.8 + nopt: 7.2.1 + + js-cookie@3.0.8: {} + + js-tokens@9.0.1: {} + + jsdom@29.1.1: + dependencies: + '@asamuzakjp/css-color': 5.1.11 + '@asamuzakjp/dom-selector': 7.1.1 + '@bramus/specificity': 2.4.2 + '@csstools/css-syntax-patches-for-csstree': 1.1.7(css-tree@3.2.1) + '@exodus/bytes': 1.15.1 + css-tree: 3.2.1 + data-urls: 7.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 6.0.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.2 + parse5: 8.0.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.2 + undici: 7.29.0 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.1 + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - '@noble/hashes' + + jsesc@3.1.0: {} + + json5@2.2.3: {} + + lightningcss-android-arm64@1.33.0: + optional: true + + lightningcss-darwin-arm64@1.33.0: + optional: true + + lightningcss-darwin-x64@1.33.0: + optional: true + + lightningcss-freebsd-x64@1.33.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + + lightningcss-linux-arm64-musl@1.33.0: + optional: true + + lightningcss-linux-x64-gnu@1.33.0: + optional: true + + lightningcss-linux-x64-musl@1.33.0: + optional: true + + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + + lightningcss-win32-x64-msvc@1.33.0: + optional: true + + lightningcss@1.33.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + + local-pkg@1.2.1: + dependencies: + mlly: 1.8.2 + pkg-types: 2.3.1 + quansync: 0.2.11 + + lodash-es@4.18.1: {} + + lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.18.1)(lodash@4.18.1): + dependencies: + '@types/lodash-es': 4.17.12 + lodash: 4.18.1 + lodash-es: 4.18.1 + + lodash@4.18.1: {} + + lru-cache@10.4.3: {} + + lru-cache@11.5.2: {} + + magic-string-ast@1.0.3: + dependencies: + magic-string: 0.30.21 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + math-intrinsics@1.1.0: {} + + mdn-data@2.27.1: {} + + memoize-one@6.0.0: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.1.2 + + minipass@7.1.3: {} + + mlly@1.8.2: + dependencies: + acorn: 8.17.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.4 + + ms@2.1.3: {} + + muggle-string@0.4.1: {} + + nanoid@3.3.16: {} + + nopt@7.2.1: + dependencies: + abbrev: 2.0.0 + + normalize-wheel-es@1.2.0: {} + + nostics@1.2.0: {} + + obug@2.1.4: {} + + package-json-from-dist@1.0.1: {} + + parse5@8.0.1: + dependencies: + entities: 8.0.0 + + path-browserify@1.0.1: {} + + path-key@3.1.1: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + + pathe@2.0.3: {} + + perfect-debounce@2.1.0: {} + + picocolors@1.1.1: {} + + picomatch@4.0.5: {} + + pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@5.9.3)(vue@3.5.40(typescript@5.9.3)): + dependencies: + '@vue/devtools-api': 8.2.1 + nostics: 1.2.0 + vue: 3.5.40(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.2 + pathe: 2.0.3 + + pkg-types@2.3.1: + dependencies: + confbox: 0.2.4 + exsolve: 1.1.0 + pathe: 2.0.3 + + postcss@8.5.23: + dependencies: + nanoid: 3.3.16 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + proto-list@1.2.4: {} + + proxy-from-env@2.1.0: {} + + punycode@2.3.1: {} + + quansync@0.2.11: {} + + readdirp@5.0.0: {} + + require-from-string@2.0.2: {} + + rolldown@1.1.5: + dependencies: + '@oxc-project/types': 0.139.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.1.5 + '@rolldown/binding-darwin-arm64': 1.1.5 + '@rolldown/binding-darwin-x64': 1.1.5 + '@rolldown/binding-freebsd-x64': 1.1.5 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.5 + '@rolldown/binding-linux-arm64-gnu': 1.1.5 + '@rolldown/binding-linux-arm64-musl': 1.1.5 + '@rolldown/binding-linux-ppc64-gnu': 1.1.5 + '@rolldown/binding-linux-s390x-gnu': 1.1.5 + '@rolldown/binding-linux-x64-gnu': 1.1.5 + '@rolldown/binding-linux-x64-musl': 1.1.5 + '@rolldown/binding-openharmony-arm64': 1.1.5 + '@rolldown/binding-wasm32-wasi': 1.1.5 + '@rolldown/binding-win32-arm64-msvc': 1.1.5 + '@rolldown/binding-win32-x64-msvc': 1.1.5 + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + scule@1.3.0: {} + + semver@7.8.5: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + sortablejs@1.15.7: {} + + source-map-js@1.2.1: {} + + stackback@0.0.2: {} + + std-env@4.2.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 + + symbol-tree@3.2.4: {} + + tinybench@2.9.0: {} + + tinyexec@1.2.4: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + + tinyrainbow@3.1.0: {} + + tldts-core@7.4.9: {} + + tldts@7.4.9: + dependencies: + tldts-core: 7.4.9 + + tough-cookie@6.0.2: + dependencies: + tldts: 7.4.9 + + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + + tslib@2.8.1: + optional: true + + typescript@5.9.3: {} + + ufo@1.6.4: {} + + undici-types@7.18.2: {} + + undici@7.29.0: {} + + unimport@5.7.0: + dependencies: + acorn: 8.17.0 + escape-string-regexp: 5.0.0 + estree-walker: 3.0.3 + local-pkg: 1.2.1 + magic-string: 0.30.21 + mlly: 1.8.2 + pathe: 2.0.3 + picomatch: 4.0.5 + pkg-types: 2.3.1 + scule: 1.3.0 + strip-literal: 3.1.0 + tinyglobby: 0.2.17 + unplugin: 2.3.11 + unplugin-utils: 0.3.2 + + unplugin-auto-import@21.0.0(@vueuse/core@14.3.0(vue@3.5.40(typescript@5.9.3))): + dependencies: + local-pkg: 1.2.1 + magic-string: 0.30.21 + picomatch: 4.0.5 + unimport: 5.7.0 + unplugin: 2.3.11 + unplugin-utils: 0.3.2 + optionalDependencies: + '@vueuse/core': 14.3.0(vue@3.5.40(typescript@5.9.3)) + + unplugin-utils@0.3.2: + dependencies: + pathe: 2.0.3 + picomatch: 4.0.5 + + unplugin-vue-components@32.1.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3)): + dependencies: + chokidar: 5.0.0 + local-pkg: 1.2.1 + magic-string: 0.30.21 + mlly: 1.8.2 + obug: 2.1.4 + picomatch: 4.0.5 + tinyglobby: 0.2.17 + unplugin: 3.3.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)) + unplugin-utils: 0.3.2 + vue: 3.5.40(typescript@5.9.3) + transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - bun-types-no-globals + - esbuild + - rolldown + - rollup + - unloader + - vite + - webpack + + unplugin@2.3.11: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.17.0 + picomatch: 4.0.5 + webpack-virtual-modules: 0.6.2 + + unplugin@3.3.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)): + dependencies: + '@jridgewell/remapping': 2.3.5 + picomatch: 4.0.5 + webpack-virtual-modules: 0.6.2 + optionalDependencies: + rolldown: 1.1.5 + vite: 8.1.5(@types/node@24.13.3)(yaml@2.9.0) + + vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0): + dependencies: + lightningcss: 1.33.0 + picomatch: 4.0.5 + postcss: 8.5.23 + rolldown: 1.1.5 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 24.13.3 + fsevents: 2.3.3 + yaml: 2.9.0 + + vitest@4.1.10(@types/node@24.13.3)(jsdom@29.1.1)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)): + dependencies: + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + es-module-lexer: 2.3.1 + expect-type: 1.4.0 + magic-string: 0.30.21 + obug: 2.1.4 + pathe: 2.0.3 + picomatch: 4.0.5 + std-env: 4.2.0 + tinybench: 2.9.0 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.0 + vite: 8.1.5(@types/node@24.13.3)(yaml@2.9.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.13.3 + jsdom: 29.1.1 + transitivePeerDependencies: + - msw + + vscode-uri@3.1.0: {} + + vue-component-type-helpers@3.3.8: {} + + vue-router@5.2.0(@vue/compiler-sfc@3.5.40)(pinia@4.0.2(@vue/devtools-api@8.2.1)(typescript@5.9.3)(vue@3.5.40(typescript@5.9.3)))(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))(vue@3.5.40(typescript@5.9.3)): + dependencies: + '@babel/generator': 8.0.0 + '@vue-macros/common': 3.1.4(vue@3.5.40(typescript@5.9.3)) + '@vue/devtools-api': 8.2.1 + ast-walker-scope: 0.9.0 + chokidar: 5.0.0 + json5: 2.2.3 + local-pkg: 1.2.1 + magic-string: 0.30.21 + mlly: 1.8.2 + muggle-string: 0.4.1 + nostics: 1.2.0 + pathe: 2.0.3 + picomatch: 4.0.5 + scule: 1.3.0 + tinyglobby: 0.2.17 + unplugin: 3.3.0(rolldown@1.1.5)(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)) + unplugin-utils: 0.3.2 + vue: 3.5.40(typescript@5.9.3) + yaml: 2.9.0 + optionalDependencies: + '@vue/compiler-sfc': 3.5.40 + pinia: 4.0.2(@vue/devtools-api@8.2.1)(typescript@5.9.3)(vue@3.5.40(typescript@5.9.3)) + vite: 8.1.5(@types/node@24.13.3)(yaml@2.9.0) + transitivePeerDependencies: + - '@farmfe/core' + - '@rspack/core' + - bun-types-no-globals + - esbuild + - rolldown + - rollup + - unloader + - webpack + + vue-tsc@3.3.8(typescript@5.9.3): + dependencies: + '@volar/typescript': 2.4.28 + '@vue/language-core': 3.3.8 + typescript: 5.9.3 + + vue@3.5.40(typescript@5.9.3): + dependencies: + '@vue/compiler-dom': 3.5.40 + '@vue/compiler-sfc': 3.5.40 + '@vue/runtime-dom': 3.5.40 + '@vue/server-renderer': 3.5.40 + '@vue/shared': 3.5.40 + optionalDependencies: + typescript: 5.9.3 + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + webidl-conversions@8.0.1: {} + + webpack-virtual-modules@0.6.2: {} + + whatwg-mimetype@5.0.0: {} + + whatwg-url@16.0.1: + dependencies: + '@exodus/bytes': 1.15.1 + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + + yaml@2.9.0: {} diff --git a/package.json b/package.json index c53005ad..c5494404 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "build": "vue-tsc --noEmit && vite build", "typecheck": "vue-tsc --noEmit", "test": "vitest run", + "test:phase4:development": "node scripts/phase4-development-frontend-acceptance.mjs", "preview": "vite preview --port 4173" }, "dependencies": { diff --git a/scripts/phase4-development-frontend-acceptance.mjs b/scripts/phase4-development-frontend-acceptance.mjs new file mode 100644 index 00000000..7321b557 --- /dev/null +++ b/scripts/phase4-development-frontend-acceptance.mjs @@ -0,0 +1,49 @@ +import { existsSync, readFileSync } from 'node:fs' +import { spawnSync } from 'node:child_process' + +function option(name) { + const index = process.argv.indexOf(name) + return index >= 0 ? process.argv[index + 1] : '' +} + +function normalizeOrigin(value, name) { + if (!value) throw new Error(`缺少 ${name}`) + const url = new URL(value) + if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.pathname !== '/') { + throw new Error(`${name} 必须是无账号、无路径的 HTTP(S) origin`) + } + return url.origin +} + +function acceptancePassword() { + if (process.env.CHONGCHONG_ADMIN_ACCEPTANCE_PASSWORD) return process.env.CHONGCHONG_ADMIN_ACCEPTANCE_PASSWORD + const file = 'C:/Users/BY-OY/.codex/chongchong-global-dev-acceptance.env' + if (!existsSync(file)) return '' + const match = readFileSync(file, 'utf8').match(/^CHONGCHONG_ADMIN_ACCEPTANCE_PASSWORD=(.*)$/m) + return match?.[1]?.trim() || '' +} + +const environment = option('--environment') +if (environment !== 'development') throw new Error('本入口仅允许显式指定 --environment development') +const gateway = normalizeOrigin(option('--gateway') || process.env.ADMIN_DEVELOPMENT_GATEWAY, '--gateway') +const overseasGateway = normalizeOrigin(option('--overseas-gateway') || process.env.ADMIN_DEVELOPMENT_OVERSEAS_GATEWAY, '--overseas-gateway') +const password = acceptancePassword() +if (!password) throw new Error('缺少 CHONGCHONG_ADMIN_ACCEPTANCE_PASSWORD 或本机开发验收凭据文件') + +const result = spawnSync('pnpm', ['exec', 'vitest', 'run', '--config', 'vitest.phase4-development.config.ts'], { + cwd: process.cwd(), + stdio: 'inherit', + shell: process.platform === 'win32', + env: { + ...process.env, + ADMIN_PHASE4_LIVE: '1', + ADMIN_ACCEPTANCE_USERNAME: process.env.ADMIN_ACCEPTANCE_USERNAME || 'platform_admin', + ADMIN_ACCEPTANCE_PASSWORD: password, + ADMIN_DEVELOPMENT_GATEWAY: gateway, + ADMIN_DEVELOPMENT_OVERSEAS_GATEWAY: overseasGateway, + VITE_API_BASE_URL: `${gateway}/api`, + VITE_OVERSEAS_API_BASE_URL: `${overseasGateway}/api`, + }, +}) +if (result.error) throw result.error +process.exit(result.status ?? 1) diff --git a/scripts/phase4-development-frontend-contract.test.mjs b/scripts/phase4-development-frontend-contract.test.mjs new file mode 100644 index 00000000..04f14f9e --- /dev/null +++ b/scripts/phase4-development-frontend-contract.test.mjs @@ -0,0 +1,34 @@ +import assert from 'node:assert/strict' +import { readFileSync } from 'node:fs' +import test from 'node:test' + +const runner = readFileSync(new URL('./phase4-development-frontend-acceptance.mjs', import.meta.url), 'utf8') +const suite = readFileSync(new URL('./phase4-development-frontend.acceptance.ts', import.meta.url), 'utf8') + +test('development runner requires an explicit development environment and gateways', () => { + assert.match(runner, /--environment/) + assert.match(runner, /environment !== 'development'/) + assert.match(runner, /--gateway/) + assert.match(runner, /--overseas-gateway/) + assert.match(runner, /shell: process\.platform === 'win32'/) + assert.match(runner, /if \(result\.error\) throw result\.error/) + assert.doesNotMatch(runner, /ADMIN_ACCEPTANCE_PASSWORD\s*[:=]\s*['"][^'"]+['"]/) +}) + +test('live suite uses production auth clients and domain adapters', () => { + assert.match(suite, /useAuthStore/) + assert.match(suite, /clearOverseasAccessToken/) + assert.match(suite, /createQuote/) + assert.match(suite, /createUsTruckOrder/) + assert.match(suite, /createLocalLooseboardOrder/) + assert.match(suite, /listLastMileOrders/) + assert.match(suite, /listDispatchCandidates/) + assert.match(suite, /listCarrierScheduleQueries/) +}) + +test('live suite owns marker resources and redacts credentials from trace reports', () => { + assert.match(suite, /ADMIN-FRONT-P4-/) + assert.match(suite, /password\|token\|authorization/i) + assert.match(suite, /createdResources/) + assert.match(suite, /coverageGaps/) +}) diff --git a/scripts/phase4-development-frontend.acceptance.ts b/scripts/phase4-development-frontend.acceptance.ts new file mode 100644 index 00000000..dc3360be --- /dev/null +++ b/scripts/phase4-development-frontend.acceptance.ts @@ -0,0 +1,285 @@ +import { afterAll, beforeAll, describe, expect, it } from 'vitest' +import axios, { type AxiosInstance, type InternalAxiosRequestConfig } from 'axios' +import { mkdirSync, writeFileSync } from 'node:fs' +import { resolve } from 'node:path' +import { createPinia, setActivePinia } from 'pinia' +import { createMemoryHistory, createRouter } from 'vue-router' +import { defineComponent, nextTick } from 'vue' +import { mount, type VueWrapper } from '@vue/test-utils' +import ElementPlus from 'element-plus' +import { http, ApiResponseError } from '@/shared/api/http' +import { clearOverseasAccessToken, overseasHttp } from '@/shared/api/overseasHttp' +import { useAuthStore } from '@/core/auth/auth' +import { listPlatformTenants } from '@/modules/iam/api/platformIam' +import { + changeExchangeRateStatus, changeQuoteStatus, changeVehicleStatus, createExchangeRate, createQuote, createVehicle, + exportExchangeRates, exportQuotes, exportVehicles, getExchangeRate, getQuote, getVehicle, listExchangeRates, + listQuoteWarehouseOptions, listQuotes, listVehicles, updateExchangeRate, updateQuote, updateVehicle, +} from '@/modules/overseas-master-data/api/overseasMasterData' +import { + createLocalLooseboardOrder, createUsTruckOrder, getLocalLooseboardOrder, getUsTruckOrder, + listLocalLooseboardOrders, listOverseasPurchaseCustomerOptions, listOverseasPurchases, + listOverseasPurchaseWarehouseOptions, listUsTruckOrders, updateLocalLooseboardOrder, updateUsTruckOrder, +} from '@/modules/overseas-business/api/platformOverseasBusiness' +import { listLastMileOrders, getLastMileOrder } from '@/modules/overseas-warehouse/api/lastMileOrders' +import { listInboundOrders } from '@/modules/overseas-warehouse/api/inboundOrders' +import { getInboundPlan } from '@/modules/overseas-warehouse/api/inboundPlans' +import { listDispatchCandidates, listDispatchDrafts, listDispatches } from '@/modules/overseas-warehouse/api/dispatches' +import { getInventorySummary, listInventoryBalances, listInventoryLedger, listInventoryPositions } from '@/modules/overseas-warehouse/api/inventory' +import { createPallet, getPallet, listCustomerWarehouses, listPallets, updatePallet } from '@/modules/overseas-warehouse/api/pallets' +import { listRelabelOrders } from '@/modules/overseas-warehouse/api/relabelOrders' +import { getCarrierScheduleQuery, listCarrierScheduleQueries } from '@/modules/port-schedules/api/platformCarrierScheduleQueries' +import OverseasQuotesView from '@/modules/overseas-master-data/pages/OverseasQuotesView.vue' +import PurchaseOrdersView from '@/modules/overseas-business/pages/PurchaseOrdersView.vue' +import TransportOrdersView from '@/modules/overseas-business/pages/TransportOrdersView.vue' +import LastMileOrdersView from '@/modules/overseas-warehouse/pages/LastMileOrdersView.vue' +import InboundOrdersView from '@/modules/overseas-warehouse/pages/InboundOrdersView.vue' +import InventoryView from '@/modules/overseas-warehouse/pages/InventoryView.vue' +import DispatchesView from '@/modules/overseas-warehouse/pages/DispatchesView.vue' +import RelabelOrdersView from '@/modules/overseas-warehouse/pages/RelabelOrdersView.vue' + +type Region = 'domestic' | 'overseas' +interface TraceStep { region: Region; method: string; path: string; params: unknown; body: unknown; httpStatus: number; code?: string; requestId?: string; traceId?: string; authorization: boolean } +interface CoverageGap { area: string; reason: string } + +const enabled = process.env.ADMIN_PHASE4_LIVE === '1' +const marker = `ADMIN-FRONT-P4-${new Date().toISOString().replace(/\D/g, '').slice(0, 14)}` +const traces: TraceStep[] = [] +const coverageGaps: CoverageGap[] = [] +const createdResources: Record = {} +const wrappers: VueWrapper[] = [] + +function redact(value: unknown): unknown { + if (Array.isArray(value)) return value.map(redact) + if (!value || typeof value !== 'object') return value + return Object.fromEntries(Object.entries(value as Record).map(([key, item]) => [key, /password|token|authorization/i.test(key) ? '[REDACTED]' : redact(item)])) +} +function parsed(value: unknown) { + if (typeof value !== 'string') return value + try { return JSON.parse(value) } catch { return value } +} +function envelope(value: unknown) { + const body = parsed(value) as { code?: unknown; requestId?: unknown; traceId?: unknown } | null + return body && typeof body === 'object' ? body : null +} +function installTracingAdapter(client: AxiosInstance, region: Region) { + const nodeAdapter = axios.getAdapter('http') + client.defaults.adapter = async (config: InternalAxiosRequestConfig) => { + try { + const response = await nodeAdapter(config) + const body = envelope(response.data) + traces.push({ region, method: String(config.method || 'GET').toUpperCase(), path: String(config.url || ''), params: redact(config.params), body: redact(parsed(config.data)), httpStatus: response.status, code: body?.code == null ? undefined : String(body.code), requestId: body?.requestId == null ? undefined : String(body.requestId), traceId: body?.traceId == null ? undefined : String(body.traceId), authorization: Boolean(config.headers?.Authorization) }) + return response + } catch (error) { + if (axios.isAxiosError(error)) { + const body = envelope(error.response?.data) + traces.push({ region, method: String(config.method || 'GET').toUpperCase(), path: String(config.url || ''), params: redact(config.params), body: redact(parsed(config.data)), httpStatus: error.response?.status || 0, code: body?.code == null ? undefined : String(body.code), requestId: body?.requestId == null ? undefined : String(body.requestId), traceId: body?.traceId == null ? undefined : String(body.traceId), authorization: Boolean(config.headers?.Authorization) }) + } + throw error + } + } +} +function gap(area: string, reason: string) { coverageGaps.push({ area, reason }) } +function numericId(value: unknown) { return /^[1-9]\d*$/.test(String(value ?? '')) } +function expectPage(value: { records: unknown[]; page: number; size: number; total: number; pages: number }) { + expect(Array.isArray(value.records)).toBe(true); expect(value.page).toBeGreaterThanOrEqual(1); expect(value.size).toBeGreaterThan(0); expect(value.total).toBeGreaterThanOrEqual(value.records.length); expect(value.pages).toBeGreaterThanOrEqual(0) +} +async function expectConflict(action: () => Promise) { + await expect(action()).rejects.toSatisfy((error: unknown) => { + if (error instanceof ApiResponseError) return error.code.endsWith('409') + if (!axios.isAxiosError(error)) return false + const response = parsed(error.response?.data) as { code?: unknown } | undefined + return error.response?.status === 409 || String(response?.code || '').endsWith('409') + }) +} +function futureDate(days: number) { return new Date(Date.now() + days * 86_400_000).toISOString().slice(0, 10) } + +async function masterDataLifecycle() { + const options = await listQuoteWarehouseOptions() + const quotePage = await listQuotes({ page: 1, size: 20 }) + expectPage(quotePage) + if (options.length) { + const quote = await createQuote({ name: `${marker} 报价`, warehouseId: options[0].warehouseId, providerName: `${marker} Provider`, currency: 'USD', effectiveStart: '2098-01-01', effectiveEnd: '2098-12-31', versionCode: marker.slice(-32), warehouseFees: [{ item: 'Storage QA', billingUnit: 'PALLET', unitPrice: 1.25, minimumCharge: 2.5, remark: marker }], transitPrices: [], remark: marker }) + const id = quote.summary.id + createdResources.quote = id + let detail = await getQuote(id) + const stale = detail.summary.recordVersion + detail = await updateQuote(id, { recordVersion: stale, name: `${marker} 报价-编辑`, providerName: detail.summary.providerName, currency: detail.summary.currency, effectiveStart: detail.summary.effectiveStart, effectiveEnd: detail.summary.effectiveEnd || '2098-12-31', warehouseFees: detail.warehouseFees, transitPrices: detail.transitPrices, remark: `${marker} edited` }) + await expectConflict(() => updateQuote(id, { recordVersion: stale, name: 'STALE', providerName: detail.summary.providerName, currency: detail.summary.currency, effectiveStart: detail.summary.effectiveStart, effectiveEnd: detail.summary.effectiveEnd || '2098-12-31', warehouseFees: detail.warehouseFees, transitPrices: detail.transitPrices, remark: marker })) + detail = await changeQuoteStatus(id, 'ACTIVE', detail.summary.recordVersion) + expect(detail.summary.status).toBe('ACTIVE') + expect((await exportQuotes({ keyword: marker })).size).toBeGreaterThan(0) + detail = await changeQuoteStatus(id, 'INACTIVE', detail.summary.recordVersion) + expect(detail.summary.status).toBe('INACTIVE') + } else gap('海外报价', 'warehouse-options 为空,未猜测仓库 ID,跳过报价写生命周期') + + let exchangeMonth = '' + for (let index = 0; index < 24 && !exchangeMonth; index += 1) { + const month = `${2097 + Math.floor(index / 12)}-${String(index % 12 + 1).padStart(2, '0')}` + const page = await listExchangeRates({ page: 1, size: 20, monthFrom: month, monthTo: month }) + if (!page.total) exchangeMonth = month + } + if (!exchangeMonth) throw new Error('安全汇率月份池已占满') + let rate = await createExchangeRate({ month: exchangeMonth, usdToCnyAverage: 7.123456, remark: marker }) + createdResources.exchangeRate = exchangeMonth + const staleRate = rate.recordVersion + rate = await updateExchangeRate(exchangeMonth, { recordVersion: staleRate, usdToCnyAverage: 7.234567, remark: `${marker} edited` }) + await expectConflict(() => updateExchangeRate(exchangeMonth, { recordVersion: staleRate, usdToCnyAverage: 7.9, remark: 'STALE' })) + rate = await getExchangeRate(exchangeMonth) + rate = await changeExchangeRateStatus(exchangeMonth, 'INACTIVE', rate.recordVersion, `${marker} cleanup`) + expect(rate.status).toBe('INACTIVE') + expect((await exportExchangeRates({ monthFrom: exchangeMonth, monthTo: exchangeMonth })).size).toBeGreaterThan(0) + + let vehicle = await createVehicle({ plateNumber: `QA-${marker.slice(-18)}`, model: 'Phase4 Front QA', fuelConsumptionPer100Km: 18.5, mileageKm: 100, driverOrDispatchCompany: marker, phone: '+1-213-555-0188', region: 'OVERSEAS', ownership: 'OWNED', status: 'IN_SERVICE', remark: marker }) + createdResources.vehicle = vehicle.id + const staleVehicle = vehicle.recordVersion + vehicle = await updateVehicle(vehicle.id, { recordVersion: staleVehicle, plateNumber: vehicle.plateNumber, model: 'Phase4 Front QA Edited', fuelConsumptionPer100Km: 18.75, mileageKm: 101, driverOrDispatchCompany: marker, phone: vehicle.phone, region: vehicle.region, ownership: vehicle.ownership, remark: `${marker} edited` }) + await expectConflict(() => updateVehicle(vehicle.id, { recordVersion: staleVehicle, plateNumber: vehicle.plateNumber, model: 'STALE', fuelConsumptionPer100Km: 19, mileageKm: 102, driverOrDispatchCompany: marker, phone: vehicle.phone, region: vehicle.region, ownership: vehicle.ownership, remark: 'STALE' })) + vehicle = await getVehicle(vehicle.id) + vehicle = await changeVehicleStatus(vehicle.id, 'INACTIVE', vehicle.recordVersion) + expect(vehicle.status).toBe('INACTIVE') + expect((await exportVehicles({ keyword: vehicle.plateNumber })).size).toBeGreaterThan(0) + expectPage(await listVehicles({ page: 1, size: 20, keyword: marker })) +} + +async function cleanupTransport(path: string, customerId: string, version: number) { + await overseasHttp.patch(`${path}/status`, { version, status: 'CANCELLED', remark: `${marker} cleanup` }, { params: { customerId } }) +} +async function overseasBusinessLifecycle() { + const customers = (await listPlatformTenants({ page: 1, size: 200, status: 'ACTIVE' })).records.filter(item => item.status === 'ACTIVE') + const active = customers.find(item => numericId(item.id)) + if (!active) { gap('卡车/散板', 'IAM 无 ACTIVE 客户'); return } + const customerId = String(active.id) + expect(Array.isArray(await listOverseasPurchaseCustomerOptions())).toBe(true) + expect(Array.isArray(await listOverseasPurchaseWarehouseOptions())).toBe(true) + expectPage(await listOverseasPurchases({ page: 1, size: 20 })) + const common = { origin: `${marker}-ORIGIN`, originAddress: 'Long Beach', destination: `${marker}-DEST`, destinationAddress: 'Ontario', containerType: '40HQ', packageCount: 2, totalWeightKg: 100, totalVolumeCbm: 2.5, budgetAmount: 88, currency: 'USD', contactName: '四期前端验收', contactInfo: '13800000000', requestedDate: futureDate(7), remark: marker } + let truck = await createUsTruckOrder(customerId, { ...common, transportType: 'PORT_PICKUP', palletCount: 1, idempotencyKey: `${marker}-truck` }) + createdResources.truck = truck.orderNo + try { + truck = await getUsTruckOrder(truck.orderNo, customerId) + const stale = truck.version + truck = await updateUsTruckOrder(truck.orderNo, customerId, { ...common, transportType: 'PORT_PICKUP', palletCount: 1, destination: `${marker}-DEST-EDIT`, version: stale }) + await expectConflict(() => updateUsTruckOrder(truck.orderNo, customerId, { ...common, transportType: 'PORT_PICKUP', palletCount: 1, destination: 'STALE', version: stale })) + } finally { + truck = await getUsTruckOrder(truck.orderNo, customerId) + if (truck.status === 'PENDING_REVIEW') await cleanupTransport(`/platform/v1/last-leg/us-truck-orders/${encodeURIComponent(truck.orderNo)}`, customerId, truck.version) + } + expectPage(await listUsTruckOrders({ page: 1, size: 20, customerId })) + + let loose = await createLocalLooseboardOrder(customerId, { transportMode: 'SHARED_TRUCK', palletRequired: 'YES', transportType: 'WAREHOUSE_TO_WAREHOUSE', ...common, idempotencyKey: `${marker}-looseboard` }) + createdResources.looseboard = loose.orderNo + try { + loose = await getLocalLooseboardOrder(loose.orderNo, customerId) + const stale = loose.version + loose = await updateLocalLooseboardOrder(loose.orderNo, customerId, { transportMode: loose.transportMode, palletRequired: loose.palletRequired, transportType: loose.transportType, ...common, destination: `${marker}-DEST-EDIT`, version: stale }) + await expectConflict(() => updateLocalLooseboardOrder(loose.orderNo, customerId, { transportMode: loose.transportMode, palletRequired: loose.palletRequired, transportType: loose.transportType, ...common, destination: 'STALE', version: stale })) + } finally { + loose = await getLocalLooseboardOrder(loose.orderNo, customerId) + if (loose.status === 'PENDING_ACCEPTANCE') await cleanupTransport(`/platform/v1/last-leg/local-looseboard-orders/${encodeURIComponent(loose.orderNo)}`, customerId, loose.version) + } + expectPage(await listLocalLooseboardOrders({ page: 1, size: 20, customerId })) +} + +async function overseasWarehouseCoverage() { + const lastMile = await listLastMileOrders({ page: 1, size: 20 }); expectPage(lastMile) + if (lastMile.records[0]) await getLastMileOrder(String(lastMile.records[0].id)) + const inbound = await listInboundOrders({ page: 1, size: 20 }); expectPage(inbound) + if (inbound.records[0]) await getInboundPlan(inbound.records[0].planNo, inbound.records[0].customerId) + expectPage(await listDispatches({ page: 1, size: 20 })) + expect(Array.isArray(await listDispatchCandidates({}))).toBe(true) + expect(Array.isArray(await listDispatchDrafts())).toBe(true) + const inventoryQuery = { page: 1, size: 20 } + const balances = await listInventoryBalances(inventoryQuery); expectPage(balances) + await getInventorySummary(inventoryQuery) + await listInventoryLedger({ page: 1, size: 20 }) + if (balances.records[0]) await listInventoryPositions(String(balances.records[0].id), 1, 20) + expectPage(await listRelabelOrders({ page: 1, size: 20 })) + const warehouses = (await listCustomerWarehouses()).records.filter(item => item.status === 'ACTIVE') + if (!warehouses.length) { gap('公共托盘', '实际海外仓为空,跳过前端托盘写生命周期'); return } + const warehouse = warehouses[0] + const payload = { palletCode: `QA-${marker.slice(-20)}`, palletType: 'STANDARD', fbaWarehouseCode: 'ONT8', capacityCbm: 2.5, unitPrice: 10, status: 'IDLE', remark: marker } + const palletId = await createPallet(warehouse.id, payload) + createdResources.pallet = palletId + try { + const pallet = await getPallet(warehouse.id, palletId) + await updatePallet(warehouse.id, palletId, { ...payload, capacityCbm: 2.75, remark: `${marker} edited`, version: pallet.version }) + await expectConflict(() => updatePallet(warehouse.id, palletId, { ...payload, capacityCbm: 3, remark: 'STALE', version: pallet.version })) + expectPage(await listPallets(warehouse.id, { page: 1, size: 20, keyword: payload.palletCode })) + } + finally { + const current = await getPallet(warehouse.id, palletId) + if (current.status !== 'SCRAPPED') await updatePallet(warehouse.id, palletId, { ...payload, status: 'SCRAPPED', remark: `${marker} cleanup`, version: current.version }) + } + gap('FBA预约/智能预排/换标新增', '没有本轮 marker 入仓计划和托盘候选;为避免操作历史数据,本轮只自动覆盖列表、详情、候选和草稿查询') +} + +async function carrierCoverage() { + const page = await listCarrierScheduleQueries({ page: 1, size: 20 }) + expectPage(page) + if (page.records[0]) await getCarrierScheduleQuery(page.records[0].query.id) + else gap('船节点人工补录', '环境无真实查询任务;未创建或修改历史任务') +} + +async function waitForTrace(method: string, path: string, start: number) { + const deadline = Date.now() + 20_000 + while (Date.now() < deadline) { + if (traces.slice(start).some(item => item.method === method && item.path.startsWith(path))) return + await new Promise(resolve => setTimeout(resolve, 50)) + } + throw new Error(`页面未发出 ${method} ${path}`) +} +async function mountPage(component: Parameters[0], method: string, path: string, props?: Record) { + const start = traces.length + const router = createRouter({ history: createMemoryHistory(), routes: [{ path: '/:pathMatch(.*)*', component: defineComponent({ template: '
' }) }] }) + await router.push('/'); await router.isReady() + const wrapper = mount(component, { attachTo: document.body, props, global: { plugins: [ElementPlus, router, setActivePinia(createPinia())] } }) + wrappers.push(wrapper) + await waitForTrace(method, path, start) + await nextTick() + expect(wrapper.text()).not.toContain('服务暂时不可用') +} +async function pageRequestCoverage() { + await mountPage(OverseasQuotesView, 'GET', '/platform/v1/last-leg/master-data/overseas-quotes') + await mountPage(PurchaseOrdersView, 'GET', '/platform/v1/last-leg/overseas-procurements') + await mountPage(TransportOrdersView, 'GET', '/platform/v1/last-leg/us-truck-orders', { domain: 'truck' }) + await mountPage(TransportOrdersView, 'GET', '/platform/v1/last-leg/local-looseboard-orders', { domain: 'looseboard' }) + await mountPage(LastMileOrdersView, 'GET', '/platform/v1/last-leg/orders') + await mountPage(InboundOrdersView, 'GET', '/platform/v1/last-leg/inbound-plans') + await mountPage(InventoryView, 'GET', '/platform/v1/last-leg/inventory/balances') + await mountPage(DispatchesView, 'GET', '/platform/v1/last-leg/dispatches') + await mountPage(RelabelOrdersView, 'GET', '/platform/v1/last-leg/relabel-applications') +} + +describe.skipIf(!enabled).sequential('phase4 development frontend acceptance', () => { + beforeAll(async () => { + Object.defineProperty(window, 'matchMedia', { writable: true, value: () => ({ matches: false, addEventListener() {}, removeEventListener() {} }) }) + globalThis.ResizeObserver = class { observe() {}; unobserve() {}; disconnect() {} } + installTracingAdapter(http, 'domestic'); installTracingAdapter(overseasHttp, 'overseas') + const pinia = createPinia(); setActivePinia(pinia) + const auth = useAuthStore(pinia) + await auth.login(process.env.ADMIN_ACCEPTANCE_USERNAME || 'platform_admin', process.env.ADMIN_ACCEPTANCE_PASSWORD || '') + expect(localStorage.getItem('cc-admin-token')).toBeTruthy() + clearOverseasAccessToken() + await listVehicles({ page: 1, size: 1 }) + expect(traces.some(item => item.region === 'domestic' && item.path === '/auth/refresh')).toBe(true) + expect(traces.some(item => item.region === 'overseas' && item.authorization)).toBe(true) + }) + it('runs marker-owned adapter lifecycles and real page requests', async () => { + await masterDataLifecycle() + await overseasBusinessLifecycle() + await overseasWarehouseCoverage() + await carrierCoverage() + await pageRequestCoverage() + expect(traces.length).toBeGreaterThan(20) + }) + afterAll(() => { + wrappers.splice(0).forEach(wrapper => wrapper.unmount()) + const reportDir = resolve(process.cwd(), 'reports') + mkdirSync(reportDir, { recursive: true }) + const report = { generatedAt: new Date().toISOString(), marker, summary: { requests: traces.length, coverageGaps: coverageGaps.length }, traces, coverageGaps, createdResources } + const file = resolve(reportDir, `phase4-frontend-development-${marker.replace(/[^A-Za-z0-9-]/g, '')}.json`) + writeFileSync(file, `${JSON.stringify(report, null, 2)}\n`, 'utf8') + console.info(`PHASE4_FRONTEND_REPORT=${file}`) + }) +}) diff --git a/src/app/components/AdminSidebarMenu.test.ts b/src/app/components/AdminSidebarMenu.test.ts index 8b259de6..116661c4 100644 --- a/src/app/components/AdminSidebarMenu.test.ts +++ b/src/app/components/AdminSidebarMenu.test.ts @@ -1,4 +1,6 @@ -import { mount } from '@vue/test-utils' +import { flushPromises, mount } from '@vue/test-utils' +import { defineComponent } from 'vue' +import { createMemoryHistory, createRouter } from 'vue-router' import { describe, expect, it } from 'vitest' import { adminNavigation, filterAdminNavigation, type AdminNavigationNode } from '@/core/navigation/adminNavigation' import AdminSidebarMenu from './AdminSidebarMenu.vue' @@ -19,10 +21,12 @@ const visibleNavigation = filterAdminNavigation(adminNavigation, new Set([ ])) const stubs = { - 'el-menu': { + 'el-menu': defineComponent({ props: ['defaultActive', 'defaultOpeneds', 'collapse'], - template: '', - }, + emits: ['select'], + methods: { updateActiveIndex() {} }, + template: '', + }), 'el-sub-menu': { props: ['index'], template: '
', @@ -34,10 +38,20 @@ const stubs = { } describe('AdminSidebarMenu', () => { + function routerPlugin() { + return createRouter({ + history: createMemoryHistory(), + routes: [ + { path: '/', component: { template: '

' } }, + { path: '/warehouses', component: { template: '

' } }, + ], + }) + } + it('renders the visible phase-one modules and forwards the active route', () => { const wrapper = mount(AdminSidebarMenu, { props: { items: visibleNavigation, activePath: '/system/users', collapsed: false }, - global: { stubs }, + global: { stubs, plugins: [routerPlugin()] }, }) expect(wrapper.get('nav').attributes('data-active')).toBe('/system/users') @@ -62,7 +76,7 @@ describe('AdminSidebarMenu', () => { it('forwards desktop collapse state to Element Plus', () => { const wrapper = mount(AdminSidebarMenu, { props: { items: visibleNavigation, activePath: '/', collapsed: true }, - global: { stubs }, + global: { stubs, plugins: [routerPlugin()] }, }) expect(wrapper.get('nav').attributes('data-collapsed')).toBe('true') @@ -72,7 +86,7 @@ describe('AdminSidebarMenu', () => { const items = filterAdminNavigation(adminNavigation, new Set(['platform:permission:list'])) const wrapper = mount(AdminSidebarMenu, { props: { items, activePath: '/', collapsed: false }, - global: { stubs }, + global: { stubs, plugins: [routerPlugin()] }, }) expect(wrapper.text()).toContain('菜单权限') @@ -100,7 +114,7 @@ describe('AdminSidebarMenu', () => { }] const wrapper = mount(AdminSidebarMenu, { props: { items, activePath: '/tracking', collapsed: false }, - global: { stubs }, + global: { stubs, plugins: [routerPlugin()] }, }) expect(wrapper.findAll('[data-kind="group"]')).toHaveLength(2) @@ -110,7 +124,7 @@ describe('AdminSidebarMenu', () => { it('recreates the menu when asynchronously loaded groups change', async () => { const wrapper = mount(AdminSidebarMenu, { props: { items: [adminNavigation[0]], activePath: '/dashboard', collapsed: false }, - global: { stubs }, + global: { stubs, plugins: [routerPlugin()] }, }) const initialMenu = wrapper.get('nav').element @@ -119,4 +133,17 @@ describe('AdminSidebarMenu', () => { expect(wrapper.get('nav').element).not.toBe(initialMenu) expect(wrapper.text()).toContain('系统管理') }) + + it('navigates explicitly when a leaf menu item is selected', async () => { + const router = routerPlugin() + await router.push('/') + const wrapper = mount(AdminSidebarMenu, { + props: { items: visibleNavigation, activePath: '/', collapsed: false }, + global: { stubs, plugins: [router] }, + }) + + await wrapper.get('nav').trigger('click') + await flushPromises() + expect(router.currentRoute.value.path).toBe('/warehouses') + }) }) diff --git a/src/app/components/AdminSidebarMenu.vue b/src/app/components/AdminSidebarMenu.vue index 7577593e..b34e9ec6 100644 --- a/src/app/components/AdminSidebarMenu.vue +++ b/src/app/components/AdminSidebarMenu.vue @@ -1,5 +1,7 @@ diff --git a/src/modules/container-loading/pages/ContainersView.test.ts b/src/modules/container-loading/pages/ContainersView.test.ts index 4f41fc2f..b2742151 100644 --- a/src/modules/container-loading/pages/ContainersView.test.ts +++ b/src/modules/container-loading/pages/ContainersView.test.ts @@ -9,13 +9,14 @@ import ContainersView from './ContainersView.vue' import { listAllPlatformWarehouses } from '@/modules/warehouses' import { listPlatformPartners } from '@/modules/master-data' import { listSuppliers } from '@/modules/suppliers' -import { getOceanBooking, listOceanBookings } from '@/modules/ocean-bookings' -import { getContainer, getContainerOverview, listContainers } from '../api/platformContainerLoading' +import { getOceanBooking, listOceanBookingLinkCandidates, listOceanBookings } from '@/modules/ocean-bookings' +import { getContainer, getContainerOverview, listContainers, updateContainer } from '../api/platformContainerLoading' +import AppDialog from '@/shared/components/AppDialog.vue' vi.mock('@/modules/warehouses', () => ({ listAllPlatformWarehouses: vi.fn() })) vi.mock('@/modules/master-data', () => ({ listPlatformPartners: vi.fn() })) vi.mock('@/modules/suppliers', () => ({ listSuppliers: vi.fn() })) -vi.mock('@/modules/ocean-bookings', () => ({ getOceanBooking: vi.fn(), listOceanBookings: vi.fn(), listWarehouseLogisticsChannels: vi.fn() })) +vi.mock('@/modules/ocean-bookings', () => ({ getOceanBooking: vi.fn(), listOceanBookingLinkCandidates: vi.fn(), listOceanBookings: vi.fn(), listWarehouseLogisticsChannels: vi.fn() })) vi.mock('@/modules/iam', () => ({ listPlatformTenants: vi.fn().mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 0 }) })) const accessCan = vi.hoisted(() => vi.fn()) vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: accessCan }) })) @@ -38,9 +39,10 @@ describe('ContainersView', () => { vi.mocked(listPlatformPartners).mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 1 }) vi.mocked(listSuppliers).mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 1 }) vi.mocked(listOceanBookings).mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 1 }) + vi.mocked(listOceanBookingLinkCandidates).mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 0 }) vi.mocked(getOceanBooking).mockResolvedValue({} as never) - vi.mocked(listContainers).mockResolvedValue({ records: [{ id: '9001', planId: null, bookingNo: 'BK-1', cabinetNo: 'CB-1', containerNo: 'MSCU-1', warehouseId: '8', warehouseName: '义乌仓', channelCode: 'ZBYHK', channelName: '美森正班海卡包税', containerType: '40HC', planStatus: 'WAIT_LOADING', version: 0, billOfLadingNo: null, vesselName: null, voyageNo: null, shippingCompanyId: null, shippingCompanyName: null, departurePortCode: null, departurePortName: '宁波', destinationPortCode: null, destinationPortName: '长滩', destinationWarehouseCode: null, destinationWarehouseName: null, capacityCbm: 76, maxWeightKg: 28000, terminalTruckingCompany: null, loadingAt: null, estimatedSailingAt: null, actualSailingAt: null, estimatedPortArrivalAt: null, actualPortArrivalAt: null, estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null }], page: 1, size: 20, total: 1, pages: 1 }) - vi.mocked(getContainer).mockResolvedValue({ id: '9001', planId: null, bookingNo: 'BK-1', cabinetNo: 'CB-1', containerNo: 'MSCU-1', warehouseId: '8', warehouseName: '义乌仓', channelCode: 'ZBYHK', channelName: '美森正班海卡包税', containerType: '40HC', planStatus: 'WAIT_LOADING', version: 0, billOfLadingNo: null, vesselName: null, voyageNo: null, shippingCompanyId: null, shippingCompanyName: null, departurePortCode: null, departurePortName: '宁波', destinationPortCode: null, destinationPortName: '长滩', destinationWarehouseCode: null, destinationWarehouseName: null, capacityCbm: 76, maxWeightKg: 28000, terminalTruckingCompany: null, loadingAt: null, estimatedSailingAt: null, actualSailingAt: null, estimatedPortArrivalAt: null, actualPortArrivalAt: null, estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null }) + vi.mocked(listContainers).mockResolvedValue({ records: [{ id: '9001', planId: null, bookingNo: 'BK-1', cabinetNo: 'CB-1', containerNo: 'MSCU-1', sourceType: 'SIMULATION', oceanBookingId: null, warehouseId: '8', warehouseName: '义乌仓', channelCode: 'ZBYHK', channelName: '美森正班海卡包税', containerType: '40HC', planStatus: 'WAIT_LOADING', version: 0, billOfLadingNo: null, vesselName: null, voyageNo: null, shippingCompanyId: null, shippingCompanyName: null, departurePortCode: null, departurePortName: '宁波', destinationPortCode: null, destinationPortName: '长滩', destinationWarehouseCode: null, destinationWarehouseName: null, capacityCbm: 76, maxWeightKg: 28000, terminalTruckingCompanyId: null, terminalTruckingCompany: null, loadingAt: null, estimatedSailingAt: null, actualSailingAt: null, estimatedPortArrivalAt: null, actualPortArrivalAt: null, estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null }], page: 1, size: 20, total: 1, pages: 1 }) + vi.mocked(getContainer).mockResolvedValue({ id: '9001', planId: null, bookingNo: 'BK-1', cabinetNo: 'CB-1', containerNo: 'MSCU-1', sourceType: 'SIMULATION', oceanBookingId: null, warehouseId: '8', warehouseName: '义乌仓', channelCode: 'ZBYHK', channelName: '美森正班海卡包税', containerType: '40HC', planStatus: 'WAIT_LOADING', version: 0, billOfLadingNo: null, vesselName: null, voyageNo: null, shippingCompanyId: null, shippingCompanyName: null, departurePortCode: null, departurePortName: '宁波', destinationPortCode: null, destinationPortName: '长滩', destinationWarehouseCode: null, destinationWarehouseName: null, capacityCbm: 76, maxWeightKg: 28000, terminalTruckingCompanyId: null, terminalTruckingCompany: null, loadingAt: null, estimatedSailingAt: null, actualSailingAt: null, estimatedPortArrivalAt: null, actualPortArrivalAt: null, estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null }) vi.mocked(getContainerOverview).mockResolvedValue({ container: { id: '9001', bookingNo: 'BK-1', cabinetNo: 'CB-1', containerNo: 'MSCU-1', status: 'WAIT_LOADING', warehouseId: '8', warehouseName: '义乌仓', voyageNo: null, vesselName: null, version: 0 }, loadingPlanId: null, pda: null, documents: [], exception: { active: false, reason: null, markedBy: null, markedByName: null, markedAt: null }, exceptionHistory: [], timeline: [] }) }) @@ -75,7 +77,7 @@ describe('ContainersView', () => { billOfLadingNo: null, vesselName: null, voyageNo: null, shippingCompanyId: null, shippingCompanyName: null, departurePortCode: null, departurePortName: '宁波', destinationPortCode: null, destinationPortName: '长滩', destinationWarehouseCode: null, destinationWarehouseName: null, capacityCbm: 76, maxWeightKg: 28000, - terminalTruckingCompany: null, loadingAt: null, estimatedSailingAt: null, actualSailingAt: null, + terminalTruckingCompanyId: null, terminalTruckingCompany: null, loadingAt: null, estimatedSailingAt: null, actualSailingAt: null, estimatedPortArrivalAt: null, actualPortArrivalAt: null, estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null, } vi.mocked(listContainers).mockResolvedValueOnce({ @@ -104,7 +106,7 @@ describe('ContainersView', () => { billOfLadingNo: null, vesselName: null, voyageNo: null, shippingCompanyId: null, shippingCompanyName: null, departurePortCode: null, departurePortName: '宁波', destinationPortCode: null, destinationPortName: '长滩', destinationWarehouseCode: null, destinationWarehouseName: null, capacityCbm: 76, maxWeightKg: 28000, - terminalTruckingCompany: null, loadingAt: null, estimatedSailingAt: null, actualSailingAt: null, + terminalTruckingCompanyId: null, terminalTruckingCompany: null, loadingAt: null, estimatedSailingAt: null, actualSailingAt: null, estimatedPortArrivalAt: null, actualPortArrivalAt: null, estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null, } vi.mocked(listContainers).mockResolvedValueOnce({ @@ -211,7 +213,8 @@ describe('ContainersView', () => { expect(detail).toContain(' { @@ -235,15 +238,15 @@ describe('ContainersView', () => { expect(source).toContain(':loading="loading" stripe preference-key="container-loading-table"') }) - it('uploads clearance documents from a file picker without exposing file ids', () => { + it('keeps document uploads on the routed detail page without duplicate list implementations', () => { const source = readFileSync(resolve(process.cwd(), 'src/modules/container-loading/pages/ContainersView.vue'), 'utf8') - expect(source).toContain(' { @@ -264,17 +267,159 @@ describe('ContainersView', () => { expect(source).not.toContain('v-model="form.maxWeightKg"') }) - it('links a simulation to a released requirement and records the port container number', () => { - const source = readFileSync(resolve(process.cwd(), 'src/modules/container-loading/pages/ContainersView.vue'), 'utf8') - expect(source).toContain("listOceanBookings({ page: 1, size: 200, status: 'RELEASED' })") - expect(source).toContain('booking.containerRequirements') - expect(source).toContain('booking.containers.filter((container) => container.requirementId === requirement.requirementId).length') - expect(source).toContain('请输入港口取得的真实集装箱号') - expect(source).toContain('oceanBookingId: candidate.oceanBookingId, requirementId: candidate.requirementId, containerNo') - expect(source).toContain(':disabled="candidate.disabled"') - expect(source).not.toContain('realContainerBookingId') - expect(source).not.toContain('MERGED') - expect(source).not.toContain('解除订舱关联') + it('filters OB-260825-0183 for CAB-260825-0215 because the real warehouses differ', async () => { + vi.mocked(listContainers).mockResolvedValue({ records: [{ + id: '215', planId: null, bookingNo: 'CB-260825-0215', cabinetNo: 'CAB-260825-0215', containerNo: null, + sourceType: 'SIMULATION', oceanBookingId: null, warehouseId: '193000000000200002', warehouseName: '东莞仓', + channelCode: 'EXX_RAIL_NY', channelName: '纽约铁路', containerType: '45HC', planStatus: 'EDITING', + capacityCbm: 86, maxWeightKg: 29000, version: 7, + }], page: 1, size: 20, total: 1, pages: 1 } as never) + vi.mocked(listOceanBookingLinkCandidates).mockResolvedValueOnce({ records: [], page: 1, size: 200, total: 0, pages: 0 }) + const router = createTestRouter() + await router.push('/'); await router.isReady() + const wrapper = mount(ContainersView, { attachTo: document.body, global: { plugins: [ElementPlus, router] } }) + await flushPromises() + await wrapper.find('button[aria-label="更多货柜操作"]').trigger('click') + await flushPromises() + Array.from(document.body.querySelectorAll('.el-dropdown-menu__item')) + .filter((item) => item.textContent?.includes('关联已放舱订舱')).at(-1)!.click() + await flushPromises() + + expect(listOceanBookingLinkCandidates).toHaveBeenCalledWith({ warehouseId: '193000000000200002', channelCode: 'EXX_RAIL_NY', containerType: '45HC', page: 1, size: 200 }) + expect((wrapper.vm as unknown as { linkCandidates: unknown[] }).linkCandidates).toEqual([]) + expect(readFileSync(resolve(process.cwd(), 'src/modules/container-loading/pages/ContainersView.vue'), 'utf8')) + .toContain('暂无符合当前装柜仓库、物流渠道和柜型的已放舱需求') + expect(getOceanBooking).not.toHaveBeenCalled() + wrapper.unmount() + }) + + it('keeps a three-field match selectable when only capacity snapshots differ and blocks duplicate waves', async () => { + let resolveCandidates!: (value: Awaited>) => void + vi.mocked(listContainers).mockResolvedValue({ records: [{ + id: '315', planId: null, bookingNo: 'CB-CAPACITY-SNAPSHOT', cabinetNo: 'CAB-CAPACITY-SNAPSHOT', containerNo: null, + sourceType: 'SIMULATION', oceanBookingId: null, warehouseId: '193000000000200002', warehouseName: '东莞仓', + channelCode: 'EXX_RAIL_NY', channelName: '纽约铁路', containerType: '45HC', planStatus: 'WAIT_LOADING', + capacityCbm: 86, maxWeightKg: 29000, version: 7, + }], page: 1, size: 20, total: 1, pages: 1 } as never) + vi.mocked(listOceanBookingLinkCandidates).mockReturnValueOnce(new Promise((resolve) => { resolveCandidates = resolve })) + const router = createTestRouter() + await router.push('/'); await router.isReady() + const wrapper = mount(ContainersView, { attachTo: document.body, global: { plugins: [ElementPlus, router] } }) + await flushPromises() + await wrapper.find('button[aria-label="更多货柜操作"]').trigger('click') + await flushPromises() + const linkAction = Array.from(document.body.querySelectorAll('.el-dropdown-menu__item')) + .filter((item) => item.textContent?.includes('关联已放舱订舱')).at(-1)! + + linkAction.click() + linkAction.click() + + expect(listOceanBookingLinkCandidates).toHaveBeenCalledTimes(1) + expect(listOceanBookingLinkCandidates).toHaveBeenCalledWith({ warehouseId: '193000000000200002', channelCode: 'EXX_RAIL_NY', containerType: '45HC', page: 1, size: 200 }) + expect(getOceanBooking).not.toHaveBeenCalled() + resolveCandidates({ records: [{ oceanBookingId: '315', bookingNo: 'OB-CAPACITY-SNAPSHOT', requirementId: '45315', containerType: '45HC', capacityCbm: 85, maxWeightKg: 28500, requiredQuantity: 1, allocatedQuantity: 0, remainingQuantity: 1, customerName: '客户', warehouseName: '东莞仓', channelName: '纽约铁路' }], page: 1, size: 200, total: 1, pages: 1 }) + await flushPromises() + expect(document.body.textContent).toContain('OB-CAPACITY-SNAPSHOT · 45HC × 1') + expect((wrapper.vm as unknown as { linkCandidates: Array<{ disabled: boolean }> }).linkCandidates[0]?.disabled).toBe(false) + wrapper.unmount() + }) + + it('discards a candidate response from a closed link session', async () => { + let resolveFirst!: (value: Awaited>) => void + let resolveSecond!: (value: Awaited>) => void + vi.mocked(listOceanBookingLinkCandidates) + .mockReturnValueOnce(new Promise((resolve) => { resolveFirst = resolve })) + .mockReturnValueOnce(new Promise((resolve) => { resolveSecond = resolve })) + const router = createTestRouter() + await router.push('/'); await router.isReady() + const wrapper = mount(ContainersView, { attachTo: document.body, global: { plugins: [ElementPlus, router] } }) + await flushPromises() + + await wrapper.find('button[aria-label="更多货柜操作"]').trigger('click') + await flushPromises() + Array.from(document.body.querySelectorAll('.el-dropdown-menu__item')) + .filter((item) => item.textContent?.includes('关联已放舱订舱')).at(-1)!.click() + await flushPromises() + wrapper.findAllComponents(AppDialog) + .find((dialog) => dialog.props('title') === '关联已放舱订舱')!.vm.$emit('update:modelValue', false) + await flushPromises() + + await wrapper.find('button[aria-label="更多货柜操作"]').trigger('click') + await flushPromises() + Array.from(document.body.querySelectorAll('.el-dropdown-menu__item')) + .filter((item) => item.textContent?.includes('关联已放舱订舱')).at(-1)!.click() + resolveSecond({ records: [{ oceanBookingId: '303', bookingNo: 'OB-LATEST', requirementId: '404', containerType: '40HC', capacityCbm: 76, maxWeightKg: 28000, requiredQuantity: 1, allocatedQuantity: 0, remainingQuantity: 1, customerName: '客户', warehouseName: '义乌仓', channelName: '美森正班海卡包税' }], page: 1, size: 200, total: 1, pages: 1 }) + await flushPromises() + resolveFirst({ records: [{ oceanBookingId: '101', bookingNo: 'OB-STALE', requirementId: '202', containerType: '40HC', capacityCbm: 76, maxWeightKg: 28000, requiredQuantity: 1, allocatedQuantity: 0, remainingQuantity: 1, customerName: '客户', warehouseName: '义乌仓', channelName: '美森正班海卡包税' }], page: 1, size: 200, total: 1, pages: 1 }) + await flushPromises() + + expect(listOceanBookingLinkCandidates).toHaveBeenCalledTimes(2) + const candidateLabels = (wrapper.vm as unknown as { linkCandidates: Array<{ label: string }> }).linkCandidates.map((candidate) => candidate.label) + expect(candidateLabels.some((label) => label.includes('OB-LATEST'))).toBe(true) + expect(candidateLabels.some((label) => label.includes('OB-STALE'))).toBe(false) + wrapper.unmount() + }) + + it('backfills a legacy trucking supplier name and submits the frozen id-name pair', async () => { + vi.mocked(listSuppliers).mockResolvedValue({ records: [{ id: '9007199254740998', tenantId: '1', name: '测试拖车供应商', category: 'TRUCKING', region: 'CN', legalRepresentative: '张三', contactName: '李四', phone: '13800000000', email: null, address: null, businessLicenseNo: null, licenseFileId: null, status: 'ACTIVE', settlementPeriod: 'MONTHLY_30', remark: null, createdBy: null, createdAt: '2026-08-25T10:00:00', updatedBy: null, updatedAt: '2026-08-25T10:00:00', deleted: false, version: 0 }], page: 1, size: 200, total: 1, pages: 1 }) + vi.mocked(getContainer).mockResolvedValueOnce({ id: '9001', containerType: '40HC', warehouseId: '8', terminalTruckingCompanyId: null, terminalTruckingCompany: '测试拖车供应商' } as never) + vi.mocked(updateContainer).mockResolvedValue({} as never) + const router = createTestRouter() + await router.push('/'); await router.isReady() + const wrapper = mount(ContainersView, { global: { plugins: [ElementPlus, router] } }) + await flushPromises() + + await wrapper.findAll('button').find((button) => button.text().includes('编辑运输信息'))!.trigger('click') + await flushPromises() + await wrapper.findAll('button').find((button) => button.text().trim() === '确定')!.trigger('click') + await flushPromises() + + expect(updateContainer).toHaveBeenCalledWith('9001', 0, expect.objectContaining({ + terminalTruckingCompanyId: '9007199254740998', + terminalTruckingCompany: '测试拖车供应商', + })) + }) + + it('clears the trucking supplier id and name together', async () => { + vi.mocked(listSuppliers).mockResolvedValue({ records: [{ id: '9007199254740998', tenantId: '1', name: '测试拖车供应商', category: 'TRUCKING', region: 'CN', legalRepresentative: '张三', contactName: '李四', phone: '13800000000', email: null, address: null, businessLicenseNo: null, licenseFileId: null, status: 'ACTIVE', settlementPeriod: 'MONTHLY_30', remark: null, createdBy: null, createdAt: '2026-08-25T10:00:00', updatedBy: null, updatedAt: '2026-08-25T10:00:00', deleted: false, version: 0 }], page: 1, size: 200, total: 1, pages: 1 }) + vi.mocked(getContainer).mockResolvedValueOnce({ id: '9001', containerType: '40HC', warehouseId: '8', terminalTruckingCompanyId: '9007199254740998', terminalTruckingCompany: '测试拖车供应商' } as never) + vi.mocked(updateContainer).mockResolvedValue({} as never) + const router = createTestRouter() + await router.push('/'); await router.isReady() + const wrapper = mount(ContainersView, { global: { plugins: [ElementPlus, router] } }) + await flushPromises() + + await wrapper.findAll('button').find((button) => button.text().includes('编辑运输信息'))!.trigger('click') + await flushPromises() + const truckingSelect = wrapper.findAllComponents({ name: 'ElSelect' }).find((select) => select.props('placeholder') === '请选择拖车供应商') + truckingSelect!.vm.$emit('update:modelValue', '') + await flushPromises() + await wrapper.findAll('button').find((button) => button.text().trim() === '确定')!.trigger('click') + await flushPromises() + + expect(updateContainer).toHaveBeenCalledWith('9001', 0, expect.objectContaining({ + terminalTruckingCompanyId: null, + terminalTruckingCompany: null, + })) + }) + + it('blocks saving a legacy trucking supplier name that no longer matches an active option', async () => { + vi.mocked(getContainer).mockResolvedValueOnce({ id: '9001', containerType: '40HC', warehouseId: '8', terminalTruckingCompanyId: null, terminalTruckingCompany: '已停用拖车供应商' } as never) + vi.mocked(updateContainer).mockClear() + const router = createTestRouter() + await router.push('/'); await router.isReady() + const wrapper = mount(ContainersView, { global: { plugins: [ElementPlus, router] } }) + await flushPromises() + + await wrapper.findAll('button').find((button) => button.text().includes('编辑运输信息'))!.trigger('click') + await flushPromises() + const truckingSelect = wrapper.findAllComponents({ name: 'ElSelect' }).find((select) => select.props('placeholder') === '请选择拖车供应商') + expect(truckingSelect?.props('modelValue')).toBe('') + await wrapper.findAll('button').find((button) => button.text().trim() === '确定')!.trigger('click') + await flushPromises() + + expect(updateContainer).not.toHaveBeenCalled() + expect(wrapper.text()).toContain('原拖车供应商已不可用,请重新选择合作中的拖车供应商') }) }) diff --git a/src/modules/container-loading/pages/ContainersView.vue b/src/modules/container-loading/pages/ContainersView.vue index b259e8e8..f6c865e9 100644 --- a/src/modules/container-loading/pages/ContainersView.vue +++ b/src/modules/container-loading/pages/ContainersView.vue @@ -2,14 +2,13 @@ import { computed, onMounted, reactive, ref, watch } from 'vue' import { useRouter } from 'vue-router' import { Boxes, Check, Eye, FileText, FileUp, Link2, ListChecks, MoreHorizontal, Pencil, Plus, Sparkles, TriangleAlert } from '@lucide/vue' -import { ElMessage, type FormInstance, type FormRules, type UploadFile } from 'element-plus' +import { ElMessage, type FormInstance, type FormRules } from 'element-plus' import { useAccessPreviewStore } from '@/core/access/accessPreview' import { listPlatformTenants, type PlatformTenantResource } from '@/modules/iam' import { listAllPlatformWarehouses, type PlatformWarehouseSummaryResource } from '@/modules/warehouses' import { listPlatformPartners, type PlatformPartnerResource } from '@/modules/master-data' import { listSuppliers, type Supplier } from '@/modules/suppliers' -import { getOceanBooking, listOceanBookings, listWarehouseLogisticsChannels, type OceanBookingResource, type OceanLogisticsChannel } from '@/modules/ocean-bookings' -import { uploadLoadingDeclaration } from '@/modules/loading-lists' +import { listOceanBookingLinkCandidates, listOceanBookings, listWarehouseLogisticsChannels, type OceanBookingResource, type OceanLogisticsChannel } from '@/modules/ocean-bookings' import AdminPage from '@/shared/components/AdminPage.vue' import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue' import AppDialog from '@/shared/components/AppDialog.vue' @@ -19,9 +18,8 @@ import LoadErrorState from '@/shared/components/LoadErrorState.vue' import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue' import { CONTAINER_SPECIFICATIONS, applyContainerSpecification, containerSpecification } from '@/shared/domain/containerSpecifications' import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http' -import ContainerOverviewPanel from '../components/ContainerOverviewPanel.vue' -import { cancelContainerException, completeContainerClearance, createContainerSimulation, downloadContainerDocument, downloadContainerPdaPhoto, getContainer, getContainerClearance, getContainerOverview, linkContainerOceanBooking, listContainers, markContainerException, updateContainer, updateContainerTransport, uploadContainerClearance, uploadContainerDocument } from '../api/platformContainerLoading' -import type { ContainerBookingResource, ContainerDocumentStatus, ContainerDocumentType, ContainerOverview, ContainerOverviewDocument, ContainerPdaPhoto, ContainerPlanStatus, ContainerSaveRequest, ContainerSimulationCreateRequest } from '../types' +import { createContainerSimulation, getContainer, linkContainerOceanBooking, listContainers, updateContainer, updateContainerTransport } from '../api/platformContainerLoading' +import type { ContainerBookingResource, ContainerDocumentStatus, ContainerPlanStatus, ContainerSaveRequest, ContainerSimulationCreateRequest } from '../types' type Filters = QueryModel & { customerId: string; keyword: string; containerType: string; status: ContainerPlanStatus | ''; sailingRange: string[] } type ContainerForm = ContainerSaveRequest & Pick & { id: string; version: number } @@ -47,31 +45,7 @@ const pageSize = ref(20) const total = ref(0) const filters = ref({ customerId: '', keyword: '', containerType: '', status: '', sailingRange: [] }) const applied = ref({ ...filters.value }) -const detailOpen = ref(false) -const detailLoading = ref(false) -const detailError = ref(null) const detail = ref(null) -const detailTarget = ref(null) -const clearanceDocument = ref(null) -const clearanceLoading = ref(false) -const clearanceActionLoading = ref(false) -const clearanceError = ref(null) -const clearanceFile = ref(null) -const clearanceDialogOpen = ref(false) -const overview = ref(null) -const overviewError = ref(null) -const documentDialogOpen = ref(false) -const documentType = ref('DELIVERY_ORDER') -const documentFile = ref(null) -const documentSaving = ref(false) -const documentError = ref(null) -const documentDownloading = ref(false) -const photoBusyId = ref(null) -const photoError = ref(null) -const exceptionDialogOpen = ref(false) -const exceptionReason = ref('') -const exceptionSaving = ref(false) -const exceptionError = ref(null) const editorOpen = ref(false) const editorError = ref(null) const saving = ref(false) @@ -92,8 +66,10 @@ const linkCandidateKey = ref('') const linkContainerNo = ref('') const linkCandidates = ref>([]) const selectedTruckingSupplierId = ref('') +const unresolvedTruckingSupplierName = ref(null) let listSequence = 0 let detailSequence = 0 +let linkSequence = 0 function emptyForm(): ContainerForm { return { @@ -101,7 +77,7 @@ function emptyForm(): ContainerForm { billOfLadingNo: null, vesselName: null, voyageNo: null, containerType: '40HC', shippingCompanyId: null, shippingCompanyName: null, departurePortCode: null, departurePortName: null, destinationPortCode: null, destinationPortName: null, destinationWarehouseCode: null, destinationWarehouseName: null, - capacityCbm: 76, maxWeightKg: 28000, terminalTruckingCompany: null, loadingAt: null, + capacityCbm: 76, maxWeightKg: 28000, terminalTruckingCompanyId: null, terminalTruckingCompany: null, loadingAt: null, estimatedSailingAt: null, actualSailingAt: null, estimatedPortArrivalAt: null, actualPortArrivalAt: null, estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null, } @@ -110,7 +86,7 @@ const form = reactive(emptyForm()) const rules: FormRules = { warehouseId: [{ required: true, message: '请选择装柜仓库', trigger: 'change' }], containerType: [{ required: true, message: '请选择柜型', trigger: 'change' }], - terminalTruckingCompany: [{ validator: (_rule, value, callback) => callback(!value || selectedTruckingSupplierId.value ? undefined : new Error('请选择有效的合作中拖车供应商')), trigger: 'change' }], + terminalTruckingCompany: [{ validator: (_rule, value, callback) => callback(unresolvedTruckingSupplierName.value || (value && !selectedTruckingSupplierId.value) ? new Error('请选择有效的合作中拖车供应商') : undefined), trigger: 'change' }], } const canView = computed(() => access.can('platform:firstleg:container:list')) @@ -121,9 +97,6 @@ const canCustomsManage = computed(() => access.can('platform:firstleg:customs:ma const canViewPreload = computed(() => access.can('platform:firstleg:preload:list')) const canViewLoadingList = computed(() => access.can('platform:firstleg:loading-list:list')) const editorTitle = computed(() => form.id ? '编辑' : '新增') -const selectedOverviewDocument = computed(() => overview.value?.documents.find((item) => item.documentType === documentType.value) || null) -const documentDialogTitle = computed(() => ({ DELIVERY_ORDER: 'DO 资料', PICKUP_ORDER: 'PU 资料', DESTINATION_CLEARANCE: '目的港清关资料', CUSTOMS_DECLARATION: '报关资料' })[documentType.value]) -const exceptionDialogTitle = computed(() => overview.value?.exception.active ? '取消货柜异常' : '标记货柜异常') const transportOnly = computed(() => Boolean(form.id) && detail.value?.planStatus === 'LOADING') const shippingCompanies = computed(() => partners.value.filter((partner) => partner.status === 'ACTIVE' && partner.types.includes('CARRIER'))) const truckingCompanies = computed(() => truckingSuppliers.value.filter((supplier) => supplier.status === 'ACTIVE' && supplier.category === 'TRUCKING')) @@ -173,7 +146,7 @@ const columns: DataTableColumn[] = [ { key: 'exceptionActive', label: '异常', width: 90, formatter: (row: ContainerBookingResource) => row.exceptionActive ? '异常' : '正常' }, { key: 'cabinetNo', label: '柜次号', minWidth: 180, slotName: 'cabinet' }, { key: 'destinationClearanceDocumentStatus', label: '清关资料', width: 110, formatter: (row: ContainerBookingResource) => documentStatusText(row.destinationClearanceDocumentStatus) }, - { key: 'customsDeclarationDocumentStatus', label: '报关资料', width: 110, formatter: (row: ContainerBookingResource) => documentStatusText(row.customsDeclarationDocumentStatus) }, + { key: 'customsDeclarationDocumentStatus', label: '国内出口报关附件', minWidth: 150, formatter: (row: ContainerBookingResource) => documentStatusText(row.customsDeclarationDocumentStatus) }, { key: 'deliveryOrderDocumentStatus', label: 'DO资料', width: 100, formatter: (row: ContainerBookingResource) => documentStatusText(row.deliveryOrderDocumentStatus) }, { key: 'pickupOrderDocumentStatus', label: 'PU资料', width: 100, formatter: (row: ContainerBookingResource) => documentStatusText(row.pickupOrderDocumentStatus) }, { key: 'oceanBooking', label: '真实订舱', minWidth: 170, slotName: 'oceanBooking' }, @@ -205,10 +178,30 @@ function replaceForm(source: ContainerBookingResource | null) { Object.assign(form, emptyForm(), source || {}) const specification = containerSpecification(form.containerType) if (specification) applyContainerSpecification(form, specification.type) - selectedTruckingSupplierId.value = truckingCompanies.value.find((supplier) => supplier.name === form.terminalTruckingCompany)?.id || '' + reconcileTruckingSupplier() +} +function reconcileTruckingSupplier() { + const supplierId = optional(form.terminalTruckingCompanyId) + const supplierName = optional(form.terminalTruckingCompany) || unresolvedTruckingSupplierName.value + const supplier = supplierId + ? truckingCompanies.value.find((item) => item.id === supplierId) + : truckingCompanies.value.find((item) => item.name === supplierName) + selectedTruckingSupplierId.value = supplier?.id || '' + unresolvedTruckingSupplierName.value = supplier ? null : supplierName + if (supplier) { + form.terminalTruckingCompanyId = supplier.id + form.terminalTruckingCompany = supplier.name + } else if (!supplierName) { + form.terminalTruckingCompanyId = null + form.terminalTruckingCompany = null + } else { + form.terminalTruckingCompanyId = null + form.terminalTruckingCompany = supplierName + } } function payload(): ContainerSaveRequest { const selectedWarehouse = warehouses.value.find((warehouse) => String(warehouse.id) === form.warehouseId) + const selectedTruckingSupplier = truckingCompanies.value.find((supplier) => supplier.id === selectedTruckingSupplierId.value) return { containerNo: optional(form.containerNo), warehouseId: form.warehouseId, @@ -219,7 +212,9 @@ function payload(): ContainerSaveRequest { departurePortCode: optional(form.departurePortCode), departurePortName: optional(form.departurePortName), destinationPortCode: optional(form.destinationPortCode), destinationPortName: optional(form.destinationPortName), destinationWarehouseCode: optional(form.destinationWarehouseCode), destinationWarehouseName: optional(form.destinationWarehouseName), - capacityCbm: form.capacityCbm, maxWeightKg: form.maxWeightKg, terminalTruckingCompany: optional(form.terminalTruckingCompany), + capacityCbm: form.capacityCbm, maxWeightKg: form.maxWeightKg, + terminalTruckingCompanyId: selectedTruckingSupplier?.id || null, + terminalTruckingCompany: selectedTruckingSupplier?.name || null, loadingAt: form.loadingAt, estimatedSailingAt: form.estimatedSailingAt, actualSailingAt: form.actualSailingAt, estimatedPortArrivalAt: form.estimatedPortArrivalAt, actualPortArrivalAt: form.actualPortArrivalAt, estimatedWarehouseArrivalAt: form.estimatedWarehouseArrivalAt, actualWarehouseArrivalAt: form.actualWarehouseArrivalAt, @@ -230,8 +225,11 @@ function partnerLabel(partner: PlatformPartnerResource) { return `${partner.partnerName}${partner.partnerCode ? `(${partner.partnerCode})` : ''}` } function selectTruckingSupplier(supplierId: string) { + if (!supplierId && unresolvedTruckingSupplierName.value) return const supplier = truckingCompanies.value.find((item) => item.id === supplierId) selectedTruckingSupplierId.value = supplier?.id || '' + unresolvedTruckingSupplierName.value = null + form.terminalTruckingCompanyId = supplier?.id || null form.terminalTruckingCompany = supplier?.name || null } function portLabel(port: PortOption) { @@ -300,7 +298,10 @@ async function loadBusinessOptions() { ]) if (partnerResult.status === 'fulfilled') partners.value = partnerResult.value else errors.push(getApiErrorDetails(partnerResult.reason, '船公司与拖车公司加载失败').message) - if (supplierResult.status === 'fulfilled') truckingSuppliers.value = supplierResult.value.records.filter((supplier) => supplier.category === 'TRUCKING' && supplier.status === 'ACTIVE') + if (supplierResult.status === 'fulfilled') { + truckingSuppliers.value = supplierResult.value.records.filter((supplier) => supplier.category === 'TRUCKING' && supplier.status === 'ACTIVE') + if (form.id) reconcileTruckingSupplier() + } else errors.push(getApiErrorDetails(supplierResult.reason, '拖车供应商加载失败').message) if (bookingResult.status === 'fulfilled') oceanBookings.value = bookingResult.value else errors.push(getApiErrorDetails(bookingResult.reason, '港口候选加载失败').message) @@ -351,14 +352,19 @@ async function saveSimulation() { } catch (error) { simulationError.value = getApiErrorDetails(error, '模拟柜创建失败') } finally { simulationSaving.value = false } } -async function loadReleasedBookings() { - const first = await listOceanBookings({ page: 1, size: 200, status: 'RELEASED' }) - if (first.pages <= 1) return first.records - const rest = await Promise.all(Array.from({ length: first.pages - 1 }, (_, index) => listOceanBookings({ page: index + 2, size: 200, status: 'RELEASED' }))) - return [first, ...rest].flatMap((result) => result.records) -} async function openLink(source: object) { + if (linkLoading.value) return const row = source as ContainerBookingResource + const warehouseId = optional(row.warehouseId) + const channelCode = optional(row.channelCode) + if (!warehouseId || !channelCode || !optional(row.containerType)) { + linkTarget.value = row + linkCandidates.value = [] + linkError.value = { message: '当前模拟柜缺少仓库、渠道或柜型,无法查询可关联订舱' } + linkOpen.value = true + return + } + const sequence = ++linkSequence linkTarget.value = row linkCandidateKey.value = '' linkContainerNo.value = '' @@ -367,27 +373,23 @@ async function openLink(source: object) { linkOpen.value = true linkLoading.value = true try { - const bookings = await loadReleasedBookings() - const details = await Promise.all(bookings.map((booking) => getOceanBooking(booking.id))) - linkCandidates.value = details.flatMap((booking) => booking.containerRequirements - .map((requirement) => ({ ...requirement, remainingQuantity: Math.max(0, Number(requirement.quantity) - booking.containers.filter((container) => container.requirementId === requirement.requirementId).length) })) - .filter((requirement) => Boolean(requirement.requirementId) && Number(requirement.remainingQuantity) > 0) - .map((requirement) => { - const specificationMatches = booking.warehouseId === row.warehouseId - && booking.channelCode === row.channelCode - && requirement.containerType === row.containerType - && Number(requirement.capacityCbm) === Number(row.capacityCbm) - && Number(requirement.maxWeightKg) === Number(row.maxWeightKg) - return { - key: `${booking.id}:${requirement.requirementId}`, - oceanBookingId: booking.id, - requirementId: String(requirement.requirementId), - disabled: !specificationMatches, - label: `${booking.bookingNo || '订舱号待补'} · ${requirement.containerType} × ${requirement.remainingQuantity} · ${booking.customerName || '未关联客户'} · ${booking.warehouseName || '仓库待补'} · ${booking.channelName || '渠道待补'}${specificationMatches ? '' : '(与当前柜规格不一致)'}`, - } - })) - } catch (error) { linkError.value = getApiErrorDetails(error, '已放舱订舱候选加载失败') } - finally { linkLoading.value = false } + const result = await listOceanBookingLinkCandidates({ + warehouseId, channelCode, containerType: row.containerType, + page: 1, size: 200, + }) + if (sequence !== linkSequence || linkTarget.value?.id !== row.id) return + linkCandidates.value = result.records.map((candidate) => ({ + key: `${candidate.oceanBookingId}:${candidate.requirementId}`, + oceanBookingId: candidate.oceanBookingId, + requirementId: candidate.requirementId, + disabled: false, + label: `${candidate.bookingNo} · ${candidate.containerType} × ${candidate.remainingQuantity} · ${candidate.customerName} · ${candidate.warehouseName} · ${candidate.channelName}`, + })) + } catch (error) { + if (sequence === linkSequence) linkError.value = getApiErrorDetails(error, '已放舱订舱候选加载失败') + } finally { + if (sequence === linkSequence) linkLoading.value = false + } } async function saveLink() { const target = linkTarget.value @@ -434,86 +436,6 @@ function handleMoreAction(command: string, source: object) { if (command === 'overview') { openDetail(row); return } if (['exception', 'documents'].includes(command)) void router.push({ name: 'container-detail', params: { containerId: row.id }, query: { action: command } }) } -function openDocumentDialog(type: string) { - if (!['DELIVERY_ORDER', 'PICKUP_ORDER'].includes(type)) { - if (type === 'DESTINATION_CLEARANCE' && detailTarget.value) void openClearance(detailTarget.value) - return - } - documentType.value = type as ContainerDocumentType - documentFile.value = null - documentError.value = null - documentDialogOpen.value = true -} -function selectDocumentFile(uploadFile: UploadFile) { documentFile.value = uploadFile.raw ?? null; documentError.value = null } -function removeDocumentFile() { documentFile.value = null } -async function saveDocument() { - if (!detailTarget.value || !overview.value || !documentFile.value) { documentError.value = { message: '请选择需要上传的资料文件', code: 'FILE_REQUIRED' }; return } - documentSaving.value = true; documentError.value = null - try { - const version = selectedOverviewDocument.value?.version || 0 - if (documentType.value === 'DESTINATION_CLEARANCE') await uploadContainerClearance(detailTarget.value.id, documentFile.value, version, '上传目的港清关资料') - else if (documentType.value === 'CUSTOMS_DECLARATION') { - if (!overview.value.loadingPlanId) throw new Error('missing loading plan') - await uploadLoadingDeclaration(overview.value.loadingPlanId, detailTarget.value.warehouseId, documentFile.value, version, '上传装柜清单报关资料') - } else await uploadContainerDocument(detailTarget.value.id, documentType.value, documentFile.value, version, `上传${documentDialogTitle.value}`) - overview.value = await getContainerOverview(detailTarget.value.id) - documentDialogOpen.value = false; documentFile.value = null; ElMessage.success(`${documentDialogTitle.value}已上传`) - } catch (error) { documentError.value = getApiErrorDetails(error, `${documentDialogTitle.value}上传失败`) } - finally { documentSaving.value = false } -} -async function saveBlob(blob: Blob, fileName: string) { - const url = URL.createObjectURL(blob) - const anchor = document.createElement('a') - anchor.href = url; anchor.download = fileName || '货柜资料'; anchor.click() - URL.revokeObjectURL(url) -} -async function downloadDocument(item: ContainerOverviewDocument) { - if (!detailTarget.value) return - documentDownloading.value = true - if (!['DELIVERY_ORDER', 'PICKUP_ORDER'].includes(item.documentType)) return - try { await saveBlob(await downloadContainerDocument(detailTarget.value.id, item.documentType as 'DELIVERY_ORDER' | 'PICKUP_ORDER', item.fileId), item.fileName); ElMessage.success('资料下载已开始') } - catch (error) { ElMessage.error(getApiErrorDetails(error, '资料下载失败').message) } - finally { documentDownloading.value = false } -} -async function previewPhoto(photo: ContainerPdaPhoto) { - photoBusyId.value = photo.evidenceId; photoError.value = null - try { - const url = URL.createObjectURL(await downloadContainerPdaPhoto(photo.downloadPath)) - window.open(url, '_blank', 'noopener,noreferrer') - window.setTimeout(() => URL.revokeObjectURL(url), 60_000) - } catch (error) { photoError.value = getApiErrorDetails(error, '装柜照片加载失败') } - finally { photoBusyId.value = null } -} -function openExceptionDialog() { exceptionReason.value = ''; exceptionError.value = null; exceptionDialogOpen.value = true } -async function saveException() { - if (!detailTarget.value || !detail.value || !overview.value || !exceptionReason.value.trim()) { exceptionError.value = { message: '请输入异常原因或取消备注', code: 'REASON_REQUIRED' }; return } - exceptionSaving.value = true; exceptionError.value = null - try { - const action = overview.value.exception.active ? cancelContainerException : markContainerException - await action(detailTarget.value.id, overview.value.container.version, exceptionReason.value.trim()) - overview.value = await getContainerOverview(detailTarget.value.id) - exceptionDialogOpen.value = false; ElMessage.success(overview.value.exception.active ? '货柜已标记异常' : '货柜异常已取消') - } catch (error) { exceptionError.value = getApiErrorDetails(error, '货柜异常处理失败') } - finally { exceptionSaving.value = false } -} -async function openClearance(source: object) { - const row = source as ContainerBookingResource - detailTarget.value = row - clearanceDialogOpen.value = true; clearanceError.value = null; clearanceFile.value = null; clearanceLoading.value = true - try { clearanceDocument.value = await getContainerClearance(row.id) } catch (error) { clearanceError.value = getApiErrorDetails(error, '清关资料加载失败') } finally { clearanceLoading.value = false } -} -function selectClearanceFile(uploadFile: UploadFile) { clearanceFile.value = uploadFile.raw ?? null; clearanceError.value = null } -function removeClearanceFile() { clearanceFile.value = null } -async function uploadClearance() { - if (!detailTarget.value || !clearanceFile.value) { clearanceError.value = { message: '请选择清关资料文件', code: 'FILE_REQUIRED' }; return } - clearanceActionLoading.value = true; clearanceError.value = null - try { clearanceDocument.value = await uploadContainerClearance(detailTarget.value.id, clearanceFile.value, clearanceDocument.value?.version || 0, '上传目的港清关资料'); clearanceFile.value = null; clearanceDialogOpen.value = false; ElMessage.success('清关资料已上传') } catch (error) { clearanceError.value = getApiErrorDetails(error, '清关资料上传失败') } finally { clearanceActionLoading.value = false } -} -async function completeClearance() { - if (!detailTarget.value || !clearanceDocument.value) return - clearanceActionLoading.value = true; clearanceError.value = null - try { clearanceDocument.value = await completeContainerClearance(detailTarget.value.id, clearanceDocument.value.version, '确认目的港清关完成'); ElMessage.success('已完成清关') } catch (error) { clearanceError.value = getApiErrorDetails(error, '清关完成失败') } finally { clearanceActionLoading.value = false } -} async function openEdit(source: object) { const row = source as ContainerBookingResource editorError.value = null @@ -521,6 +443,10 @@ async function openEdit(source: object) { catch (error) { ElMessage.error(getApiErrorDetails(error, '货柜详情加载失败').message) } } async function save() { + if (unresolvedTruckingSupplierName.value) { + editorError.value = { message: '原拖车供应商已不可用,请重新选择合作中的拖车供应商' } + return + } if (!(await formRef.value?.validate().catch(() => false))) return saving.value = true editorError.value = null @@ -564,6 +490,11 @@ function goContainerProcess(source: object) { watch([page, pageSize], ([nextPage, nextSize], [previousPage, previousSize]) => { if (nextPage !== previousPage || nextSize !== previousSize) void loadRows() }) +watch(linkOpen, (open) => { + if (open) return + linkSequence += 1 + linkLoading.value = false +}) onMounted(() => { void Promise.all([loadCustomers(), loadWarehouses(), loadBusinessOptions(), loadRows()]) }) @@ -597,12 +528,6 @@ onMounted(() => { void Promise.all([loadCustomers(), loadWarehouses(), loadBusin - 选择文件 - - 选择文件 - - - @@ -616,8 +541,8 @@ onMounted(() => { void Promise.all([loadCustomers(), loadWarehouses(), loadBusin - -

仓库、渠道、柜型、容量和限重必须与当前模拟柜一致;不一致的候选不可选择。

+ +

仓库、渠道和柜型必须与当前模拟柜一致;容量和限重仅展示柜型固定快照,不影响关联资格。

@@ -652,7 +577,6 @@ onMounted(() => { void Promise.all([loadCustomers(), loadWarehouses(), loadBusin diff --git a/src/modules/overseas-business/contract.test.ts b/src/modules/overseas-business/contract.test.ts index 020d6b62..be382783 100644 --- a/src/modules/overseas-business/contract.test.ts +++ b/src/modules/overseas-business/contract.test.ts @@ -6,61 +6,48 @@ const read = (path: string) => readFileSync(resolve(process.cwd(), `src/modules/ describe('overseas business real contract pages', () => { it('keeps operation columns first and renders no sample records', () => { - const purchase = read('pages/PurchaseOrdersView.vue') - const transport = read('pages/TransportOrdersView.vue') - const purchaseColumns = purchase.slice(purchase.indexOf('const columns')) - const truckColumns = transport.slice(transport.indexOf('const truckColumns')) - const looseboardColumns = transport.slice(transport.indexOf('const looseboardColumns')) + const purchase = read('pages/PurchaseOrdersView.vue'); const transport = read('pages/TransportOrdersView.vue') + const purchaseColumns = purchase.slice(purchase.indexOf('const columns')); const truckColumns = transport.slice(transport.indexOf('const truckColumns')); const looseboardColumns = transport.slice(transport.indexOf('const looseboardColumns')) expect(purchaseColumns.indexOf("key: 'actions'")).toBeLessThan(purchaseColumns.indexOf("key: 'orderNo'")) expect(truckColumns.indexOf("key: 'actions'")).toBeLessThan(truckColumns.indexOf("key: 'orderNo'")) expect(looseboardColumns.indexOf("key: 'actions'")).toBeLessThan(looseboardColumns.indexOf("key: 'orderNo'")) - expect(purchase).toContain('const rows = ref([])') - expect(transport).toContain('const rows = ref>([])') expect(`${purchase}${transport}`).not.toMatch(/OPO\d|TK\d|LB\d/) }) - it('gives every formal list a stable query preference key', () => { - const purchase = read('pages/PurchaseOrdersView.vue') - const transport = read('pages/TransportOrdersView.vue') - expect(purchase.match(/]*\/>/)?.[0]).toContain('preference-key="overseas-business-purchases-query"') - expect(transport.match(/]*\/>/)?.[0]).toContain(':preference-key="queryPreferenceKey"') - expect(transport).toContain("'overseas-business-truck-query'") - expect(transport).toContain("'overseas-business-looseboard-query'") - }) - - it('loads procurement list/detail and saves only the backend update contract', () => { - const list = read('pages/PurchaseOrdersView.vue') - const detail = read('pages/PurchaseOrderDetailView.vue') - const edit = read('pages/PurchaseOrderEditView.vue') - expect(list).toContain('listOverseasPurchases') - expect(list).toContain("query: { customerId: row.customerId }") - expect(detail).toContain('getOverseasPurchase(purchaseId.value, customerId.value)') - expect(edit).toContain('updateOverseasPurchase(purchaseId.value, customerId.value, payload)') - expect(edit).toContain('inboundQuantity: inboundEditable.value ? form.inboundQuantity : undefined') - expect(edit).toContain("form.status === 'APPROVED'") + it('loads procurement candidates, operations and three-state PATCH fields', () => { + const list = read('pages/PurchaseOrdersView.vue'); const detail = read('pages/PurchaseOrderDetailView.vue'); const edit = read('pages/PurchaseOrderEditView.vue') + expect(list).toContain('listOverseasPurchaseCustomerOptions') + expect(edit).toContain('listOverseasPurchaseWarehouseOptions') + expect(detail).toContain('detail?.histories || []') + expect(detail).not.toContain('outbounds') + expect(edit).toContain('estimatedArrivalAt: form.estimatedArrivalAt || null') + expect(edit).toContain('purchaseWarehouseId: form.purchaseWarehouseId || null') expect(edit).not.toMatch(/payload[^\n]*(outboundQuantity|status):/) - expect(`${list}${detail}${edit}`).toContain('LoadErrorState') }) - it('loads truck list/detail but keeps unsupported writes and looseboard blocked', () => { - const list = read('pages/TransportOrdersView.vue') - const form = read('pages/TransportOrderFormView.vue') - expect(list).toContain('listUsTruckOrders') - expect(list).toContain("query: { customerId: row.customerId }") - expect(form).toContain('getUsTruckOrder(orderId.value, customerId.value)') - expect(form).not.toMatch(/createUsTruck|updateUsTruck/) - expect(form).toContain('平台创建/普通编辑端点待后端补齐') - expect(list).toContain('本土散板接口待后端补齐') - expect(form).toContain('disabled> { + const api = read('api/platformOverseasBusiness.ts'); const list = read('pages/TransportOrdersView.vue'); const form = read('pages/TransportOrderFormView.vue') + expect(api).toContain("const looseboardBasePath = '/platform/v1/last-leg/local-looseboard-orders'") + expect(api).toContain('createUsTruckOrder') + expect(api).toContain('updateUsTruckOrder') + expect(api).toContain('createLocalLooseboardOrder') + expect(api).toContain('updateLocalLooseboardOrder') + expect(api).not.toContain('createOverseasPurchase') + expect(api).not.toMatch(/\/merchant\/|receive-pallets|\/status/) + expect(list).toContain('listLocalLooseboardOrders') + expect(form).toContain('listPlatformTenants') + expect(form).not.toContain('ContractPendingNotice') }) - it('keeps unsaved-work protection on both prototype-backed forms', () => { - const purchaseEdit = read('pages/PurchaseOrderEditView.vue') - const transportForm = read('pages/TransportOrderFormView.vue') + it('keeps state-constrained editing and unsaved-work protection', () => { + const purchaseEdit = read('pages/PurchaseOrderEditView.vue'); const transportList = read('pages/TransportOrdersView.vue'); const transportForm = read('pages/TransportOrderFormView.vue') expect(purchaseEdit).toContain('useUnsavedWorkRegistration') - expect(purchaseEdit).toContain(':min="form.outboundQuantity"') expect(transportForm).toContain('useUnsavedWorkRegistration') - expect(transportForm).toContain("message: '请输入起运地'") - expect(transportForm).toContain("message: '请输入目的地'") + expect(transportList).toContain("row.status === 'PENDING_ACCEPTANCE'") + expect(transportList).toContain("row.status === 'PENDING_REVIEW'") + expect(transportForm).toContain("form.status === 'PENDING_ACCEPTANCE'") + expect(transportForm).toContain("form.status === 'PENDING_REVIEW'") + expect(transportForm).toContain('idempotencyKey: form.idempotencyKey') + expect(transportForm.match(/idempotencyKey:\s*newIdempotencyKey\(\)/g)).toHaveLength(1) }) }) diff --git a/src/modules/overseas-business/pages/OverseasBusinessViews.test.ts b/src/modules/overseas-business/pages/OverseasBusinessViews.test.ts new file mode 100644 index 00000000..94f39b5a --- /dev/null +++ b/src/modules/overseas-business/pages/OverseasBusinessViews.test.ts @@ -0,0 +1,79 @@ +import ElementPlus from 'element-plus' +import { createPinia, setActivePinia } from 'pinia' +import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils' +import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { ApiResponseError } from '@/shared/api/http' +import { useAccessPreviewStore } from '@/core/access/accessPreview' +import { useAuthStore } from '@/core/auth/auth' +import { listPlatformTenants } from '@/modules/iam' +import type { LocalLooseboardDetail, LocalLooseboardOrder, LocalTransportDetail, LocalTransportOrder, OverseasPurchaseDetail } from '../types' +import { + createLocalLooseboardOrder, createUsTruckOrder, getLocalLooseboardOrder, getOverseasPurchase, getUsTruckOrder, + listLocalLooseboardOrders, listOverseasPurchaseCustomerOptions, listOverseasPurchaseWarehouseOptions, + listOverseasPurchases, listUsTruckOrders, updateLocalLooseboardOrder, updateOverseasPurchase, updateUsTruckOrder, +} from '../api/platformOverseasBusiness' +import PurchaseOrdersView from './PurchaseOrdersView.vue' +import PurchaseOrderDetailView from './PurchaseOrderDetailView.vue' +import PurchaseOrderEditView from './PurchaseOrderEditView.vue' +import TransportOrdersView from './TransportOrdersView.vue' +import TransportOrderFormView from './TransportOrderFormView.vue' + +const routing = vi.hoisted(() => ({ push: vi.fn(), route: { params: {} as Record, query: {} as Record } })) +vi.mock('vue-router', () => ({ useRoute: () => routing.route, useRouter: () => ({ push: routing.push }) })) +vi.mock('@/modules/iam', () => ({ listPlatformTenants: vi.fn() })) +vi.mock('../api/platformOverseasBusiness', () => ({ + listOverseasPurchases: vi.fn(), getOverseasPurchase: vi.fn(), updateOverseasPurchase: vi.fn(), listOverseasPurchaseCustomerOptions: vi.fn(), listOverseasPurchaseWarehouseOptions: vi.fn(), + listUsTruckOrders: vi.fn(), getUsTruckOrder: vi.fn(), createUsTruckOrder: vi.fn(), updateUsTruckOrder: vi.fn(), + listLocalLooseboardOrders: vi.fn(), getLocalLooseboardOrder: vi.fn(), createLocalLooseboardOrder: vi.fn(), updateLocalLooseboardOrder: vi.fn(), +})) +vi.mock('@/core/unsaved-work/useUnsavedWorkRegistration', () => ({ useUnsavedWorkRegistration: () => ({ captureBaseline: vi.fn() }) })) + +class ResizeObserverStub implements ResizeObserver { observe() {} unobserve() {} disconnect() {} } +function memoryStorage(): Storage { const values = new Map(); return { get length() { return values.size }, clear: () => values.clear(), getItem: (key) => values.get(key) ?? null, key: (index) => [...values.keys()][index] ?? null, removeItem: (key) => values.delete(key), setItem: (key, value) => values.set(key, value) } } + +const purchase: OverseasPurchaseDetail = { + id: '9007199254740993', orderNo: 'OP-100', customerId: '10001', customerName: '客户甲', purchaseCategory: '家居', productName: '置物架', productSpecification: '黑色', productUrl: 'https://example.test/product', + purchaseQuantity: 20, budgetUnitPrice: '12.50', currency: 'USD', purchaseWarehouseId: '20001', purchaseWarehouseName: '洛杉矶采购仓', inboundQuantity: 10, inventoryQuantity: 10, status: 'APPROVED', version: 3, + createdAt: '2026-08-01T10:00:00', updatedAt: '2026-08-02T10:00:00', receivingAddress: 'LA', contactName: 'Alice', contactPhone: '10086', domesticCarrier: null, domesticTrackingNo: null, + overseasCarrier: 'UPS', overseasTrackingNo: 'UPS-1', estimatedArrivalAt: '2026-08-25T12:00:00', remark: '采购备注', createdBy: '7', reviewedBy: '8', reviewRemark: null, reviewedAt: '2026-08-02T09:00:00', + histories: [{ operationType: 'UPDATE', fromStatus: 'APPROVED', toStatus: 'APPROVED', operatorId: '7', changeDetail: '{"remark":"采购备注"}', remark: null, createdAt: '2026-08-02T10:00:00' }], +} +const truck: LocalTransportOrder = { id: '9007199254740995', customerId: '10002', orderNo: 'TK-200', transportType: 'PORT_PICKUP', origin: 'Long Beach', destination: 'Ontario', containerType: '40HQ', palletCount: 2, packageCount: 20, receivedPalletCount: 0, allocatedPalletCount: 0, shippedPalletCount: 0, totalWeightKg: '1200.000', totalVolumeCbm: '16.500', budgetAmount: '850.00', currency: 'USD', contactName: 'Bob', contactInfo: '10010', requestedDate: '2026-08-28', status: 'PENDING_REVIEW', version: 1, createdAt: '2026-08-01T10:00:00', updatedAt: '2026-08-02T10:00:00' } +const truckDetail: LocalTransportDetail = { ...truck, originAddress: 'Pier A', destinationAddress: 'Warehouse B', remark: null, createdBy: '7', pallets: [], histories: [] } +const looseboard: LocalLooseboardOrder = { id: '9007199254740997', customerId: '10003', orderNo: 'LB-300', transportMode: 'SHARED_TRUCK', palletRequired: 'YES', transportType: 'WAREHOUSE_TO_WAREHOUSE', origin: 'LA', destination: 'ONT', containerType: null, packageCount: 8, totalWeightKg: '80.5', totalVolumeCbm: '3.2', budgetAmount: '50.00', currency: 'USD', contactName: null, contactInfo: null, requestedDate: null, status: 'PENDING_ACCEPTANCE', version: 0, createdAt: '2026-08-01T10:00:00', updatedAt: '2026-08-01T10:00:00' } +const looseboardDetail: LocalLooseboardDetail = { ...looseboard, originAddress: null, destinationAddress: null, remark: null, createdBy: '7', histories: [] } + +function activatePermissions() { const pinia = createPinia(); setActivePinia(pinia); const auth = useAuthStore(); auth.token = 'test-token'; auth.permissions = ['platform:overseas-business:purchase:list', 'platform:overseas-business:purchase:edit', 'platform:overseas-business:truck:list', 'platform:overseas-business:truck:create', 'platform:overseas-business:truck:edit', 'platform:overseas-business:looseboard:list', 'platform:overseas-business:looseboard:create', 'platform:overseas-business:looseboard:edit']; useAccessPreviewStore().initializeAfterLogin(); return pinia } +function mountPage(component: Parameters[0], props?: Record) { const pinia = activatePermissions(); return mount(component, { attachTo: document.body, props, global: { plugins: [pinia, ElementPlus] } }) } +enableAutoUnmount(afterEach); afterAll(() => vi.unstubAllGlobals()) + +describe('overseas business mounted pages', () => { + beforeEach(() => { + vi.stubGlobal('ResizeObserver', ResizeObserverStub); vi.stubGlobal('localStorage', memoryStorage()); vi.stubGlobal('sessionStorage', memoryStorage()); document.body.innerHTML = '' + routing.push.mockReset(); routing.route.params = {}; routing.route.query = {} + vi.mocked(listOverseasPurchases).mockReset().mockResolvedValue({ records: [purchase], page: 1, size: 20, total: 1, pages: 1 }); vi.mocked(getOverseasPurchase).mockReset().mockResolvedValue(purchase); vi.mocked(updateOverseasPurchase).mockReset().mockResolvedValue({ ...purchase, version: 4 }) + vi.mocked(listOverseasPurchaseCustomerOptions).mockReset().mockResolvedValue([{ customerId: '10001', customerName: '客户甲' }]); vi.mocked(listOverseasPurchaseWarehouseOptions).mockReset().mockResolvedValue([{ warehouseId: '20001', warehouseCode: 'LAX', warehouseName: '洛杉矶采购仓', countryCode: 'US' }]) + vi.mocked(listUsTruckOrders).mockReset().mockResolvedValue({ records: [truck], page: 1, size: 20, total: 1, pages: 1 }); vi.mocked(getUsTruckOrder).mockReset().mockResolvedValue(truckDetail); vi.mocked(createUsTruckOrder).mockReset().mockResolvedValue(truckDetail); vi.mocked(updateUsTruckOrder).mockReset().mockResolvedValue(truckDetail) + vi.mocked(listLocalLooseboardOrders).mockReset().mockResolvedValue({ records: [looseboard], page: 1, size: 20, total: 1, pages: 1 }); vi.mocked(getLocalLooseboardOrder).mockReset().mockResolvedValue(looseboardDetail); vi.mocked(createLocalLooseboardOrder).mockReset().mockResolvedValue(looseboardDetail); vi.mocked(updateLocalLooseboardOrder).mockReset().mockResolvedValue(looseboardDetail) + vi.mocked(listPlatformTenants).mockReset().mockResolvedValue({ records: [{ id: '10001', tenantName: '可选客户', status: 'ACTIVE' } as never], page: 1, size: 200, total: 1, pages: 1 }) + }) + + it('mounts procurement list with customer candidates and real data', async () => { const wrapper = mountPage(PurchaseOrdersView); await flushPromises(); expect(listOverseasPurchaseCustomerOptions).toHaveBeenCalled(); expect(listOverseasPurchases).toHaveBeenCalledWith({ page: 1, size: 20, customerId: '', orderNo: '', purchaseCategory: '', productName: '' }); expect(wrapper.text()).toContain('OP-100'); expect(wrapper.text()).toContain('已通过') }) + it('paginates procurement results', async () => { vi.mocked(listOverseasPurchases).mockResolvedValue({ records: [purchase], page: 1, size: 20, total: 40, pages: 2 }); const wrapper = mountPage(PurchaseOrdersView); await flushPromises(); await wrapper.find('button[aria-label="第 2 页"]').trigger('click'); await flushPromises(); expect(listOverseasPurchases).toHaveBeenLastCalledWith(expect.objectContaining({ page: 2 })) }) + it('renders procurement empty and traceable 403 states', async () => { vi.mocked(listOverseasPurchases).mockResolvedValueOnce({ records: [], page: 1, size: 20, total: 0, pages: 0 }); let wrapper = mountPage(PurchaseOrdersView); await flushPromises(); expect(wrapper.text()).toContain('暂无符合筛选条件的海外采购订单'); wrapper.unmount(); vi.mocked(listOverseasPurchases).mockRejectedValue(new ApiResponseError('forbidden', 'A0403', 403, null, 'REQ-403')); wrapper = mountPage(PurchaseOrdersView); await flushPromises(); expect(wrapper.text()).toContain('当前账号无权访问该数据'); expect(wrapper.text()).toContain('REQ-403') }) + it('mounts procurement detail operation history', async () => { routing.route.params = { purchaseId: 'OP-100' }; routing.route.query = { customerId: '10001' }; const wrapper = mountPage(PurchaseOrderDetailView); await flushPromises(); expect(getOverseasPurchase).toHaveBeenCalledWith('OP-100', '10001'); expect(wrapper.text()).toContain('操作流水'); expect(wrapper.text()).toContain('编辑') }) + it('submits procurement explicit null clears and keeps a 409 visible without local overwrite', async () => { routing.route.params = { purchaseId: 'OP-100' }; routing.route.query = { customerId: '10001' }; vi.mocked(updateOverseasPurchase).mockRejectedValue(new ApiResponseError('订单版本冲突,请刷新后重试', 'B0409', 409)); const wrapper = mountPage(PurchaseOrderEditView); await flushPromises(); const productUrl = wrapper.findAll('.el-form-item').find((item) => item.text().startsWith('商品链接'))!.find('input'); const domesticCarrier = wrapper.findAll('.el-form-item').find((item) => item.text().startsWith('国内承运商'))!.find('input'); await productUrl.setValue(''); await domesticCarrier.setValue(''); wrapper.findComponent({ name: 'ElSelect' }).vm.$emit('update:modelValue', null); wrapper.findComponent({ name: 'ElDatePicker' }).vm.$emit('update:modelValue', null); await wrapper.vm.$nextTick(); await wrapper.findAll('button').find((button) => button.text().trim() === '保存')?.trigger('click'); await flushPromises(); expect(updateOverseasPurchase).toHaveBeenCalledWith('OP-100', '10001', expect.objectContaining({ version: 3, productUrl: null, domesticCarrier: null, estimatedArrivalAt: null, purchaseWarehouseId: null })); expect(document.body.textContent).toContain('订单版本冲突,请刷新后重试'); expect((productUrl.element as HTMLInputElement).value).toBe(''); expect((domesticCarrier.element as HTMLInputElement).value).toBe(''); expect(routing.push).not.toHaveBeenCalled() }) + it('keeps procurement list usable when customer candidates fail', async () => { vi.mocked(listOverseasPurchaseCustomerOptions).mockRejectedValue(new Error('candidate unavailable')); const wrapper = mountPage(PurchaseOrdersView); await flushPromises(); expect(listOverseasPurchases).toHaveBeenCalled(); expect(wrapper.text()).toContain('OP-100'); expect(wrapper.text()).not.toContain('candidate unavailable') }) + it('loads procurement edit data but blocks unsafe warehouse selection when candidates fail', async () => { routing.route.params = { purchaseId: 'OP-100' }; routing.route.query = { customerId: '10001' }; vi.mocked(listOverseasPurchaseWarehouseOptions).mockRejectedValue(new Error('candidate unavailable')); const wrapper = mountPage(PurchaseOrderEditView); await flushPromises(); expect(getOverseasPurchase).toHaveBeenCalledWith('OP-100', '10001'); expect(wrapper.text()).toContain('采购仓候选加载失败'); expect(wrapper.text()).toContain('OP-100') }) + it('mounts truck list with enabled create and supported types', async () => { const wrapper = mountPage(TransportOrdersView, { domain: 'truck' }); await flushPromises(); expect(listUsTruckOrders).toHaveBeenCalled(); expect(wrapper.text()).toContain('TK-200'); expect(wrapper.text()).toContain('港口提柜'); expect(wrapper.findAll('button').find((button) => button.text().includes('新增订单'))?.attributes('disabled')).toBeUndefined() }) + it('renders truck load failure without samples', async () => { vi.mocked(listUsTruckOrders).mockRejectedValue(new Error('hidden')); const wrapper = mountPage(TransportOrdersView, { domain: 'truck' }); await flushPromises(); expect(wrapper.text()).toContain('本土卡车订单加载失败'); expect(wrapper.text()).not.toContain('TK-200') }) + it('loads and submits pending-review truck edit', async () => { routing.route.params = { orderId: 'TK-200' }; routing.route.query = { customerId: '10002' }; const wrapper = mountPage(TransportOrderFormView, { domain: 'truck' }); await flushPromises(); await wrapper.findAll('button').find((button) => button.text().includes('保存修改'))?.trigger('click'); await flushPromises(); expect(getUsTruckOrder).toHaveBeenCalledWith('TK-200', '10002'); expect(updateUsTruckOrder).toHaveBeenCalledWith('TK-200', '10002', expect.objectContaining({ version: 1, transportType: 'PORT_PICKUP', palletCount: 2 })) }) + it('keeps truck edit form and version unchanged after a 409', async () => { routing.route.params = { orderId: 'TK-200' }; routing.route.query = { customerId: '10002' }; vi.mocked(updateUsTruckOrder).mockRejectedValue(new ApiResponseError('订单版本冲突', 'B0409', 409)); const wrapper = mountPage(TransportOrderFormView, { domain: 'truck' }); await flushPromises(); const destination = wrapper.find('input[placeholder="城市 / 州"]'); await destination.setValue('Ontario-MARKER-EDIT'); await wrapper.findAll('button').find((button) => button.text().includes('保存修改'))?.trigger('click'); await flushPromises(); expect(updateUsTruckOrder).toHaveBeenCalledWith('TK-200', '10002', expect.objectContaining({ version: 1, destination: 'Ontario-MARKER-EDIT' })); expect((destination.element as HTMLInputElement).value).toBe('Ontario-MARKER-EDIT'); expect(document.body.textContent).toContain('订单版本冲突'); expect(routing.push).not.toHaveBeenCalled() }) + it('mounts truck create with explicit customer selector and enabled submit', async () => { const wrapper = mountPage(TransportOrderFormView, { domain: 'truck' }); await flushPromises(); expect(listPlatformTenants).toHaveBeenCalledWith({ page: 1, size: 200, status: 'ACTIVE' }); expect(wrapper.text()).toContain('客户信息'); expect(wrapper.text()).toContain('请选择客户'); expect(wrapper.findAll('button').find((button) => button.text().includes('提交订单'))?.attributes('disabled')).toBeUndefined() }) + it('reuses one idempotency key and preserves truck create input after retries fail', async () => { vi.mocked(createUsTruckOrder).mockRejectedValue(new ApiResponseError('temporary failure', 'S0500', 500)); const wrapper = mountPage(TransportOrderFormView, { domain: 'truck' }); await flushPromises(); const selects = wrapper.findAllComponents({ name: 'ElSelect' }); selects[0].vm.$emit('update:modelValue', '10001'); wrapper.findComponent({ name: 'ElRadioGroup' }).vm.$emit('update:modelValue', 'PORT_PICKUP'); const origin = wrapper.find('input[placeholder="城市 / 港口 / 州"]'); const destination = wrapper.find('input[placeholder="城市 / 州"]'); await origin.setValue('LA-MARKER'); await destination.setValue('ONT-MARKER'); await wrapper.findAll('.el-form-item').find((item) => item.text().startsWith('联系人'))!.find('input').setValue('联系人'); await wrapper.findAll('.el-form-item').find((item) => item.text().startsWith('联系方式'))!.find('input').setValue('13800000000'); await wrapper.findAll('.el-form-item').find((item) => item.text().startsWith('总重量'))!.find('input').setValue('100'); await wrapper.findAll('.el-form-item').find((item) => item.text().startsWith('总体积'))!.find('input').setValue('2.5'); wrapper.findComponent({ name: 'ElDatePicker' }).vm.$emit('update:modelValue', '2026-08-31'); await wrapper.vm.$nextTick(); const submit = wrapper.findAll('button').find((button) => button.text().includes('提交订单')); await submit?.trigger('click'); await flushPromises(); await submit?.trigger('click'); await flushPromises(); expect(createUsTruckOrder).toHaveBeenCalledTimes(2); const keys = vi.mocked(createUsTruckOrder).mock.calls.map((call) => call[1].idempotencyKey); expect(keys[0]).toBeTruthy(); expect(keys[1]).toBe(keys[0]); expect((origin.element as HTMLInputElement).value).toBe('LA-MARKER'); expect((destination.element as HTMLInputElement).value).toBe('ONT-MARKER'); expect(document.body.textContent).toContain('服务暂时不可用'); expect(routing.push).not.toHaveBeenCalled() }) + it('loads the real looseboard list', async () => { const wrapper = mountPage(TransportOrdersView, { domain: 'looseboard' }); await flushPromises(); expect(listLocalLooseboardOrders).toHaveBeenCalledWith({ page: 1, size: 20, routeKeyword: '', status: '' }); expect(wrapper.text()).toContain('LB-300'); expect(wrapper.text()).toContain('待接单'); expect(listUsTruckOrders).not.toHaveBeenCalled() }) + it('loads and submits pending-acceptance looseboard edit with PUT adapter', async () => { routing.route.params = { orderId: 'LB-300' }; routing.route.query = { customerId: '10003' }; const wrapper = mountPage(TransportOrderFormView, { domain: 'looseboard' }); await flushPromises(); await wrapper.findAll('button').find((button) => button.text().includes('保存修改'))?.trigger('click'); await flushPromises(); expect(getLocalLooseboardOrder).toHaveBeenCalledWith('LB-300', '10003'); expect(updateLocalLooseboardOrder).toHaveBeenCalledWith('LB-300', '10003', expect.objectContaining({ version: 0, transportMode: 'SHARED_TRUCK', palletRequired: 'YES' })) }) + it('keeps looseboard edit form and version unchanged after a 409', async () => { routing.route.params = { orderId: 'LB-300' }; routing.route.query = { customerId: '10003' }; vi.mocked(updateLocalLooseboardOrder).mockRejectedValue(new ApiResponseError('订单版本冲突', 'B0409', 409)); const wrapper = mountPage(TransportOrderFormView, { domain: 'looseboard' }); await flushPromises(); const destination = wrapper.find('input[placeholder="城市 / 州"]'); await destination.setValue('ONT-MARKER-EDIT'); await wrapper.findAll('button').find((button) => button.text().includes('保存修改'))?.trigger('click'); await flushPromises(); expect(updateLocalLooseboardOrder).toHaveBeenCalledWith('LB-300', '10003', expect.objectContaining({ version: 0, destination: 'ONT-MARKER-EDIT' })); expect((destination.element as HTMLInputElement).value).toBe('ONT-MARKER-EDIT'); expect(document.body.textContent).toContain('订单版本冲突'); expect(routing.push).not.toHaveBeenCalled() }) + it('mounts looseboard create without a detail route or pending notice', async () => { const wrapper = mountPage(TransportOrderFormView, { domain: 'looseboard' }); await flushPromises(); expect(wrapper.text()).toContain('客户信息'); expect(wrapper.text()).toContain('请选择客户'); expect(wrapper.text()).not.toContain('接口能力待后端补齐'); expect(wrapper.findAll('button').find((button) => button.text().includes('提交订单'))?.attributes('disabled')).toBeUndefined() }) + it('reuses one idempotency key and preserves looseboard create input after retries fail', async () => { vi.mocked(createLocalLooseboardOrder).mockRejectedValue(new ApiResponseError('temporary failure', 'S0500', 500)); const wrapper = mountPage(TransportOrderFormView, { domain: 'looseboard' }); await flushPromises(); const selects = wrapper.findAllComponents({ name: 'ElSelect' }); selects[0].vm.$emit('update:modelValue', '10001'); const groups = wrapper.findAllComponents({ name: 'ElRadioGroup' }); groups[0].vm.$emit('update:modelValue', 'SHARED_TRUCK'); groups[1].vm.$emit('update:modelValue', 'YES'); groups[2].vm.$emit('update:modelValue', 'WAREHOUSE_TO_WAREHOUSE'); const origin = wrapper.find('input[placeholder="城市 / 港口 / 州"]'); const destination = wrapper.find('input[placeholder="城市 / 州"]'); await origin.setValue('LA-MARKER'); await destination.setValue('ONT-MARKER'); await wrapper.findAll('.el-form-item').find((item) => item.text().startsWith('总重量'))!.find('input').setValue('80'); await wrapper.findAll('.el-form-item').find((item) => item.text().startsWith('总体积'))!.find('input').setValue('1.8'); await wrapper.vm.$nextTick(); const submit = wrapper.findAll('button').find((button) => button.text().includes('提交订单')); await submit?.trigger('click'); await flushPromises(); await submit?.trigger('click'); await flushPromises(); expect(createLocalLooseboardOrder).toHaveBeenCalledTimes(2); const keys = vi.mocked(createLocalLooseboardOrder).mock.calls.map((call) => call[1].idempotencyKey); expect(keys[0]).toBeTruthy(); expect(keys[1]).toBe(keys[0]); expect((origin.element as HTMLInputElement).value).toBe('LA-MARKER'); expect((destination.element as HTMLInputElement).value).toBe('ONT-MARKER'); expect(routing.push).not.toHaveBeenCalled() }) +}) diff --git a/src/modules/overseas-business/pages/PurchaseOrderDetailView.vue b/src/modules/overseas-business/pages/PurchaseOrderDetailView.vue index fd938c5b..75d2e433 100644 --- a/src/modules/overseas-business/pages/PurchaseOrderDetailView.vue +++ b/src/modules/overseas-business/pages/PurchaseOrderDetailView.vue @@ -9,7 +9,7 @@ import DetailPageLayout from '@/shared/components/DetailPageLayout.vue' import LoadErrorState from '@/shared/components/LoadErrorState.vue' import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http' import { getOverseasPurchase } from '../api/platformOverseasBusiness' -import type { OverseasProcurementOutbound, OverseasPurchaseDetail, OverseasPurchaseStatus } from '../types' +import type { OverseasBusinessHistory, OverseasPurchaseDetail, OverseasPurchaseStatus } from '../types' const route = useRoute(); const router = useRouter() const purchaseId = computed(() => typeof route.params.purchaseId === 'string' ? route.params.purchaseId : '') @@ -17,18 +17,19 @@ const customerId = computed(() => typeof route.query.customerId === 'string' ? r const detail = ref(null); const loading = ref(false); const loadError = ref(null) const statusLabels: Record = { PENDING_REVIEW: '待审核', APPROVED: '已通过', REJECTED: '已拒绝' } const productFields = computed(() => [['客户名称', detail.value?.customerName], ['采购仓库', detail.value?.purchaseWarehouseName], ['采购品类', detail.value?.purchaseCategory], ['商品名称', detail.value?.productName], ['商品规格', detail.value?.productSpecification], ['商品链接', detail.value?.productUrl]] as const) -const stockFields = computed(() => [['入库量', detail.value?.inboundQuantity], ['出库量', detail.value?.outboundQuantity], ['库存量', detail.value?.inventoryQuantity], ['库存状态', detail.value ? (detail.value.inventoryQuantity > 0 ? '在库' : '无库存') : null]] as const) +const stockFields = computed(() => [['入库量', detail.value?.inboundQuantity], ['库存量', detail.value?.inventoryQuantity], ['库存状态', detail.value ? (detail.value.inventoryQuantity > 0 ? '在库' : '无库存') : null]] as const) const orderFields = computed(() => [['订单编号', detail.value?.orderNo], ['采购数量', detail.value?.purchaseQuantity], ['预算单价', detail.value ? formatAmount(detail.value.budgetUnitPrice, detail.value.currency) : null], ['订单状态', detail.value ? statusLabels[detail.value.status] : null], ['联系人', detail.value?.contactName], ['联系电话', detail.value?.contactPhone], ['收货地址', detail.value?.receivingAddress], ['订单备注', detail.value?.remark]] as const) const courierFields = computed(() => [['国内承运商', detail.value?.domesticCarrier], ['国内运单号', detail.value?.domesticTrackingNo], ['海外承运商', detail.value?.overseasCarrier], ['海外运单号', detail.value?.overseasTrackingNo], ['预计到达时间', formatDateTime(detail.value?.estimatedArrivalAt)]] as const) -const outboundColumns: DataTableColumn[] = [ - { key: 'outboundAt', label: '时间', minWidth: 155, formatter: (row: OverseasProcurementOutbound) => formatDateTime(row.outboundAt) }, - { key: 'documentType', label: '单据类型', width: 110, formatter: () => '采购出库' }, - { key: 'outboundNo', prop: 'outboundNo', label: '关联单号', minWidth: 160 }, - { key: 'quantity', prop: 'quantity', label: '出库量', width: 95, align: 'right' }, - { key: 'carrier', prop: 'carrier', label: '承运商', minWidth: 120 }, - { key: 'trackingNo', prop: 'trackingNo', label: '运单号', minWidth: 150 }, +const historyColumns: DataTableColumn[] = [ + { key: 'createdAt', label: '时间', minWidth: 155, formatter: (row: OverseasBusinessHistory) => formatDateTime(row.createdAt) }, + { key: 'operationType', label: '操作类型', width: 110, formatter: (row: OverseasBusinessHistory) => operationLabels[row.operationType || ''] || row.operationType || '—' }, + { key: 'status', label: '状态变化', minWidth: 150, formatter: (row: OverseasBusinessHistory) => row.fromStatus ? `${statusLabel(row.fromStatus)} → ${statusLabel(row.toStatus)}` : statusLabel(row.toStatus) }, + { key: 'changeDetail', prop: 'changeDetail', label: '变更明细', minWidth: 260 }, + { key: 'operatorId', prop: 'operatorId', label: '操作人', minWidth: 120 }, { key: 'remark', prop: 'remark', label: '备注', minWidth: 180 }, ] +const operationLabels: Record = { CREATE: '创建', REVIEW: '审核', UPDATE: '编辑' } +function statusLabel(status?: string | null) { return status ? (statusLabels[status as OverseasPurchaseStatus] || status) : '—' } function display(value: unknown) { return value === null || value === undefined || value === '' ? '—' : String(value) } function formatDateTime(value?: string | null) { return value ? value.replace('T', ' ').slice(0, 16) : '—' } function formatAmount(value: string | null, currency: string) { return value == null ? '—' : `${Number(value).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ${currency}` } @@ -51,7 +52,7 @@ watch([purchaseId, customerId], () => { void load() }, { immediate: true })

库存信息

{{ field[0] }}
{{ display(field[1]) }}

订单信息

{{ field[0] }}
{{ display(field[1]) }}

快递信息

{{ field[0] }}
{{ display(field[1]) }}
-

进销存明细

当前接口仅返回采购出库记录,完整入库流水与结存流水字段待后端补齐。
+

操作流水

展示创建、审核和编辑变更;四期不承载采购出库。
diff --git a/src/modules/overseas-business/pages/PurchaseOrderEditView.vue b/src/modules/overseas-business/pages/PurchaseOrderEditView.vue index 93ac2786..61e05ce2 100644 --- a/src/modules/overseas-business/pages/PurchaseOrderEditView.vue +++ b/src/modules/overseas-business/pages/PurchaseOrderEditView.vue @@ -11,13 +11,13 @@ import LoadErrorState from '@/shared/components/LoadErrorState.vue' import OperationErrorToast from '@/shared/components/OperationErrorToast.vue' import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http' import { useUnsavedWorkRegistration } from '@/core/unsaved-work/useUnsavedWorkRegistration' -import { getOverseasPurchase, updateOverseasPurchase } from '../api/platformOverseasBusiness' +import { getOverseasPurchase, listOverseasPurchaseWarehouseOptions, updateOverseasPurchase } from '../api/platformOverseasBusiness' import { overseasBusinessPermissions } from '../permissions' -import type { OverseasPurchaseStatus, UpdateOverseasPurchaseRequest } from '../types' +import type { OverseasPurchaseStatus, OverseasPurchaseWarehouseOption, UpdateOverseasPurchaseRequest } from '../types' interface PurchaseEditModel { orderNo: string; purchaseCategory: string; productName: string; productSpecification: string | null; productUrl: string | null - inboundQuantity: number; outboundQuantity: number; status: OverseasPurchaseStatus; purchaseWarehouseId: string | null; purchaseWarehouseName: string | null + inboundQuantity: number; status: OverseasPurchaseStatus; purchaseWarehouseId: string | null domesticCarrier: string | null; domesticTrackingNo: string | null; overseasCarrier: string | null; overseasTrackingNo: string | null estimatedArrivalAt: string | null; remark: string | null; version: number } @@ -26,7 +26,8 @@ const purchaseId = computed(() => typeof route.params.purchaseId === 'string' ? const customerId = computed(() => typeof route.query.customerId === 'string' ? route.query.customerId : '') const formRef = ref(); const loading = ref(false); const saving = ref(false) const loadError = ref(null); const submitError = ref(null) -const initial = (): PurchaseEditModel => ({ orderNo: '', purchaseCategory: '', productName: '', productSpecification: null, productUrl: null, inboundQuantity: 0, outboundQuantity: 0, status: 'PENDING_REVIEW', purchaseWarehouseId: null, purchaseWarehouseName: null, domesticCarrier: null, domesticTrackingNo: null, overseasCarrier: null, overseasTrackingNo: null, estimatedArrivalAt: null, remark: null, version: 0 }) +const warehouses = ref([]); const warehousesLoading = ref(false); const warehousesError = ref('') +const initial = (): PurchaseEditModel => ({ orderNo: '', purchaseCategory: '', productName: '', productSpecification: null, productUrl: null, inboundQuantity: 0, status: 'PENDING_REVIEW', purchaseWarehouseId: null, domesticCarrier: null, domesticTrackingNo: null, overseasCarrier: null, overseasTrackingNo: null, estimatedArrivalAt: null, remark: null, version: 0 }) const form = reactive(initial()) const rules: FormRules = { purchaseCategory: [{ required: true, message: '请输入采购品类', trigger: 'blur' }], @@ -36,28 +37,34 @@ const rules: FormRules = { const statusLabels: Record = { PENDING_REVIEW: '待审核', APPROVED: '已通过', REJECTED: '已拒绝' } const inboundEditable = computed(() => form.status === 'APPROVED') const { captureBaseline } = useUnsavedWorkRegistration({ key: 'overseas-purchase-editor', label: computed(() => '编辑海外采购订单'), isOpen: computed(() => true), model: form, requiredPermission: computed(() => overseasBusinessPermissions.purchaseEdit) }) -function optional(value: string | null) { return value?.trim() || null } +async function loadWarehouses() { + warehousesLoading.value = true; warehousesError.value = '' + try { warehouses.value = await listOverseasPurchaseWarehouseOptions() } + catch { warehouses.value = []; warehousesError.value = '采购仓候选加载失败,请稍后重试' } + finally { warehousesLoading.value = false } +} async function load() { Object.assign(form, initial()); loadError.value = null; submitError.value = null if (!purchaseId.value || !customerId.value) { loadError.value = { message: '缺少采购订单号或客户标识,请从采购订单列表重新进入' }; captureBaseline(); return } loading.value = true try { const detail = await getOverseasPurchase(purchaseId.value, customerId.value) - Object.assign(form, { orderNo: detail.orderNo, purchaseCategory: detail.purchaseCategory, productName: detail.productName, productSpecification: detail.productSpecification, productUrl: detail.productUrl, inboundQuantity: detail.inboundQuantity, outboundQuantity: detail.outboundQuantity, status: detail.status, purchaseWarehouseId: detail.purchaseWarehouseId, purchaseWarehouseName: detail.purchaseWarehouseName, domesticCarrier: detail.domesticCarrier, domesticTrackingNo: detail.domesticTrackingNo, overseasCarrier: detail.overseasCarrier, overseasTrackingNo: detail.overseasTrackingNo, estimatedArrivalAt: detail.estimatedArrivalAt, remark: detail.remark, version: detail.version }) + Object.assign(form, { orderNo: detail.orderNo, purchaseCategory: detail.purchaseCategory, productName: detail.productName, productSpecification: detail.productSpecification, productUrl: detail.productUrl, inboundQuantity: detail.inboundQuantity, status: detail.status, purchaseWarehouseId: detail.purchaseWarehouseId, domesticCarrier: detail.domesticCarrier, domesticTrackingNo: detail.domesticTrackingNo, overseasCarrier: detail.overseasCarrier, overseasTrackingNo: detail.overseasTrackingNo, estimatedArrivalAt: detail.estimatedArrivalAt, remark: detail.remark, version: detail.version }) + if (detail.purchaseWarehouseId && !warehouses.value.some((item) => item.warehouseId === detail.purchaseWarehouseId)) warehouses.value.push({ warehouseId: detail.purchaseWarehouseId, warehouseCode: '', warehouseName: detail.purchaseWarehouseName || '当前采购仓', countryCode: '' }) captureBaseline() } catch (error) { loadError.value = getApiErrorDetails(error, '海外采购订单加载失败') } finally { loading.value = false } } async function save() { if (!await formRef.value?.validate().catch(() => false)) return saving.value = true; submitError.value = null - const payload: UpdateOverseasPurchaseRequest = { version: form.version, purchaseCategory: form.purchaseCategory.trim(), productName: form.productName.trim(), productSpecification: optional(form.productSpecification), productUrl: optional(form.productUrl), inboundQuantity: inboundEditable.value ? form.inboundQuantity : undefined, purchaseWarehouseId: optional(form.purchaseWarehouseId), purchaseWarehouseName: optional(form.purchaseWarehouseName), domesticCarrier: optional(form.domesticCarrier), domesticTrackingNo: optional(form.domesticTrackingNo), overseasCarrier: optional(form.overseasCarrier), overseasTrackingNo: optional(form.overseasTrackingNo), estimatedArrivalAt: form.estimatedArrivalAt || null, remark: optional(form.remark) } + const payload: UpdateOverseasPurchaseRequest = { version: form.version, purchaseCategory: form.purchaseCategory.trim(), productName: form.productName.trim(), productSpecification: form.productSpecification?.trim() || null, productUrl: form.productUrl?.trim() || null, inboundQuantity: inboundEditable.value ? form.inboundQuantity : undefined, purchaseWarehouseId: form.purchaseWarehouseId || null, domesticCarrier: form.domesticCarrier?.trim() || null, domesticTrackingNo: form.domesticTrackingNo?.trim() || null, overseasCarrier: form.overseasCarrier?.trim() || null, overseasTrackingNo: form.overseasTrackingNo?.trim() || null, estimatedArrivalAt: form.estimatedArrivalAt || null, remark: form.remark?.trim() || null } try { const updated = await updateOverseasPurchase(purchaseId.value, customerId.value, payload) form.version = updated.version; captureBaseline(); ElMessage.success('海外采购订单已保存') await router.push({ name: 'overseas-business-purchase-detail', params: { purchaseId: updated.orderNo }, query: { customerId: updated.customerId } }) } catch (error) { submitError.value = getApiErrorDetails(error, '海外采购订单保存失败') } finally { saving.value = false } } -watch([purchaseId, customerId], () => { void load() }, { immediate: true }) +watch([purchaseId, customerId], () => { void loadWarehouses().then(load) }, { immediate: true }) diff --git a/src/modules/overseas-business/pages/PurchaseOrdersView.vue b/src/modules/overseas-business/pages/PurchaseOrdersView.vue index 5a6be192..d548d43f 100644 --- a/src/modules/overseas-business/pages/PurchaseOrdersView.vue +++ b/src/modules/overseas-business/pages/PurchaseOrdersView.vue @@ -1,5 +1,5 @@