# Admin Web Instructions ## 快速读取顺序 1. 用“模块快速路由”选择最小业务模块,进入后读取该目录最近的 `AGENTS.md`;按 `routes.ts → pages/ → api/types/stores/composables` 下钻,不先扫描全部 `src/`。 2. 页面、布局或交互任务同时读取 `../../docs/Admin-Client前端原型还原验收规则.md` 和后台原型 `../../docs/悦/货代SAAS平台后台/AGENTS.md`。 订单样板和国内仓样式统一还须读取 `../../docs/Admin高密度界面规范.md`;以其已确认密度与彩色页签为视觉基线,逐操作保留业务语义和承载方式,公共样式按已确认菜单范围接入。 3. 标准列表或公共组件任务读取 `src/shared/components/AGENTS.md`;国内/海外 HTTP、Token 或刷新任务读取 `src/shared/api/AGENTS.md`;Finance 任务读取 `src/modules/finance/AGENTS.md`;海外仓全流程任务先读 `../../docs/海外仓业务/README.md`。 4. 平台/客户层级与权限公共语义读取 `../../docs/平台客户层级与权限契约.md`;双区域 API、海外 Token 和跨区事件读取 `../../docs/跨区域认证与服务通信契约.md`。 ## 项目定位与技术基线 - 本项目是虫虫出海内部运营后台,仅服务平台员工;不承载企业客户自助、官网、小程序、独立 APP 或 PDA 作业。 - 使用 Vue 3、TypeScript 严格模式、Vite、Vue Router、Pinia、Element Plus、Axios 和 Lucide Vue;保持 ES Module、现有无分号风格和 `@` 对 `src/` 的别名。 - 不用 `any` 绕过业务模型。模块专属类型留在模块,本应用多模块稳定复用的类型放 `src/shared/`;服务端契约以 Controller/OpenAPI 为准。 - Element Plus 使用现有自动导入;Vue API 显式导入。`src/auto-imports.d.ts`、`src/components.d.ts` 是生成声明,不手工维护业务内容。 - 不更换框架、路由、状态管理、组件库或构建工具,除非任务明确要求并完成影响评估。 ## 目录与依赖方向 | 目录 | 职责 | |---|---| | `src/app/` | 应用装配、布局、根路由、全局守卫和启动;不承载业务 | | `src/core/` | 认证、访问控制、导航、路由安全等全应用能力;不得依赖业务模块 | | `src/modules/` | 稳定业务领域的页面、API、类型、组件和模块路由;新增业务页面不放根级 `views/` | | `src/shared/` | 无业务归属的 HTTP、组件和工具;只有真实跨模块复用才上移 | | `src/prototype/` | 未纳入当前迭代的原型实现;正式模块不得依赖 | | `src/styles/` | 设计令牌和全局样式,优先复用 `--cc-*` 变量 | - 依赖方向为 `app → modules/core/shared`、`modules → core/shared`、`core → shared`、`shared → 无上层依赖`。模块间只通过对方公开入口或契约协作,不引用其他模块的页面和内部目录。 - 路由级页面放 `modules/*/pages/`,模块路由放 `modules/*/routes.ts` 并由 `app/router/index.ts` 装配;新增模块同步维护 `core/navigation/adminNavigation.ts`。 - 领域接口放 `modules/*/api/`;国内、海外公共客户端分别为 `shared/api/http.ts`、`shared/api/overseasHttp.ts`,具体 Token 与刷新规则见 `shared/api/AGENTS.md`。 - `VITE_API_BASE_URL`、`VITE_OVERSEAS_API_BASE_URL` 分别控制国内、海外浏览器前缀;开发代理上游只由 Vite 读取。环境变量变化同步 `.env.example`,不提交真实地址或凭据。 ## 模块快速路由 表中 `modules/`、`core/`、`shared/`、`app/` 和 `main.ts` 均相对 `src/`;裸文件名沿用同一单元格最近目录。模块细节只在最近指引维护,应用层保留入口。 | 业务 | 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/`、`auth/`、`file/`、`firstleg/customerstatistics/`;公司联系电话只作企业联系信息,不修改管理员/成员登录手机号且不要求跨企业唯一。审核必填资质仅营业执照与统一社会信用代码;法人身份证选填,可随资质包提交,也可在已有营业执照后单独补传或替换 | | 供应商、国内整柜 | `modules/suppliers/`、`modules/domestic-containers/` | Backend `warehouse/` 及对应 OpenAPI | | 平台仓库与仓储资源 | 仓库主档 `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` | 国内 `CN_FIRSTLEG_PDA_OPERATOR` 与海外 `OVERSEAS_WAREHOUSE_PDA_OPERATOR` 互斥;只有海外角色必须且只能绑定一个 `overseasWarehouseId`,候选来自国内 Warehouse 平台仓库 API 的公共 `OVERSEAS + ACTIVE + RECEIVING` 收货仓 | | 消息中心 | `modules/notifications/` | Backend `iam/.../notification/`;仅顶部消息中心,不进入左侧菜单 | | 订单列表、批量审核预览、详情、商品图片与入库费用 | `modules/unified-orders/`、`modules/first-leg-orders/`;平台商品图片由 `modules/unified-orders/api/unifiedOrders.ts` 按客户与 fileId 下载 | `order/`、`firstleg/`、Finance;图片读取归 `file/` 的 `PlatformProductImageController`。Order 状态为 `SUBMITTED` 时统一列表必须保持 `PENDING_REVIEW/APPROVE_ORDER`,不得被已存在的 Firstleg 准备中入库投影覆盖。批量审核弹框通过 `unifiedOrders.ts` 的 `/orders/first-leg/batch-review-preview` 一次取回全部预览,按服务端 `canApprove/blockReason` 展示,不逐票请求详情或用内部 ID 作标题 | | 客户原始申报资料编辑与渠道变更 | `modules/unified-orders/components/OrderDeclarationEditorDialog.vue`、`api/unifiedOrders.ts`、`pages/UnifiedOrdersView.vue` | 使用订单版本和货物 `itemNo` 整体提交,不允许增删货物行;只编辑客户申报快照,不覆盖仓库/PDA 实测、测量审核或计费事实。渠道变化需二次确认并由 Backend `order/` 联查 `firstleg/` 的分柜、同柜、装柜与重新计价门禁;国内收货仓或中转仓变化必须重新下单 | | 入库扣货、解除与凭证历史 | `modules/unified-orders/pages/UnifiedOrdersView.vue`、`modules/inbounds/core/api.ts`、`types.ts` | 页面只消费服务端 `holdFlag/currentHoldReason/canHold/canRelease/actionBlockReason/history`;扣货与解除提交当前入库版本、幂等键、必填原因和可选凭证,凭证下载只走 Firstleg 授权入口。Backend `firstleg/` 的 `InboundHoldService`、`InboundHoldGuard`、`InboundHoldEvidenceService`,文件归 `file/` | | 入库、测量、称重库位状态、客户箱规策略与计价主数据 | 测量弹框/工作区 `modules/inbounds/measurement/InboundMeasurementDialog.vue`、`InboundMeasurementPanel.vue`,称重 `modules/inbounds/weight/components/WeightOcrPanel.vue`;主数据 `modules/fba-pricing/`、`modules/dimension-config/`、`modules/customers/components/CustomerBillingRulesPanel.vue`、`modules/fee-items/` | 客户固定四档箱规,默认计算方式为 `ADD/MULTIPLY`;测量行可选实际尺寸、箱规尺寸策略或客户默认尺寸系数,保存后以 Backend `firstleg/` 返回的外箱尺寸、体积重和计费基数为准,不在页面独立重算。费用确认的实际箱数、毛重和体积优先汇总当前 `actualMeasurementRows`,不得用可能滞后的工作区顶层合计覆盖明细。称重页在每张图片卡片只展示服务端 `locationCode/slotStatus/sharedOverflow`,不渲染或自行推导整票预留引导;删除图片须提示槽位仍归本票保留,不得按图片数组下标推导托盘或库位 | | 一件代发托盘打印 | `modules/unified-orders/pages/UnifiedOrdersView.vue` 的“托盘打印”页签、`modules/inbounds/core/DropshipPalletPrintPanel.vue`、`core/api.ts` | 仅一件代发订单展示;测量审核预生成托盘码后由 Admin 电脑端打印,支持本票全部托盘合并打印和单托补打。PDA 只扫码组托,不承担 PDF 下载或打印机连接 | | 入库单扣货、解除、凭证与历史 | `modules/inbounds/pages/InboundOrdersView.vue`、详情工作区、`modules/inbounds/core/api.ts` | 列表展示服务端 `holdFlag/currentHoldReason` 并支持筛选;详情只按 `canHold/canRelease/actionBlockReason` 开放操作。扣货与解除提交当前 `version`、原因和独立幂等键,可选凭证先按明确客户与入库单上传;历史文件只调用专用下载入口,不把上传成功但未提交命令的文件冒充扣货证据 | | 客户专属价格簿、柜级阶梯运费与受控调价 | 列表/上传 `modules/fba-pricing/carrier-rates/pages/CarrierRatesView.vue`,版本详情/仓库映射/确认 `modules/fba-pricing/carrier-rates/pages/CarrierRateDetailView.vue`,路由 `modules/fba-pricing/routes.ts`;`modules/inbounds/fee/`、`modules/unified-orders/components/InboundFeeDetailManager.vue` | 列表与上传后按 `versionId` 进入 `fba-carrier-rate-detail` 独立详情页,价格行只读;回归入口 `modules/fba-pricing/carrier-rates/pages/CarrierRatesView.test.ts`。价格簿页面显式选择公共报价或具体客户;列表、上传、确认只作用于该 `customerId`,不得混合版本。计价优先消费客户专属 ACTIVE 版本,无专属版本才回退公共 ACTIVE;柜级阶梯金额和各客户分摊只展示服务端结果。调整计费量只能在服务端返回的上下 10% 范围内并提交当前费用版本、原因与二次确认;私人仓尾程派送费使用稳定 `PRIVATE_LAST_MILE_DELIVERY` 代码且只对 `PRIVATE` 目的地开放;一件代发须在预装确认前完成试算,计价后保持服务端 `WAIT_PALLETIZE` 状态 | | 财务、客户资金账户与柜级公共费用分摊 | `modules/finance/`,继续读该目录 `AGENTS.md`;客户账户 `pages/FinanceCustomerAccountsView.vue`,柜费 `modules/loading-lists/components/ContainerFeesPanel.vue`、`api/containerFees.ts` | `finance/`、`firstleg/`、`file/`、`docs/财务管理/`;实际、冻结、可用余额、授信与流水只消费 Finance 权威结果,充值审核和手工充扣携带版本与幂等键。跨客户公共柜费只按服务端柜内客户/订单事实分摊,金额必须守恒,创建与审核、驳回、调整、作废均整组原子处理 | | 货柜双工作台、排柜、预装/装柜清单、真实柜号后补与整柜报关 | 国内 `modules/container-loading/pages/DomesticContainersView.vue`、海外 `OverseasContainersView.vue`,共享详情实现 `ContainerDetailView.vue`;预装详情 `modules/loading-lists/pages/PreloadPlanDetailView.vue`,资料/PDA 证据 `components/ContainerOverviewPanel.vue`,报关 `components/ContainerCustomsPanel.vue` | 国内“送柜报关”只消费 `/containers/domestic` 与服务端 `allowedActions`,承载模拟柜、订舱关联、智能装柜;模拟柜创建选择与智能装柜一致的 9 类计划渠道,未关联订舱前实际渠道为空,订舱关联候选按计划渠道组匹配、装柜清单页签、出口报关和国内出仓;创建柜次时自动生成唯一预装计划,预装详情先调用 `/loading-plans/{planId}/lifecycle`,完成后深链进入国内货柜详情的装柜清单页签,不再注册独立正式清单导航和路由。订舱关联允许真实集装箱号为空,但 PDA 最终完成前必须补齐;全买单柜继续使用 `complete-all-buy`。海外“清关提柜”只消费 `/containers/overseas`,承载船节点、目的港清关、DO/PU、码头车队、提柜和还空;还空截止事实由服务端基于卸柜完成时间加 72 小时计算,前端不重算。两端统一使用 `containerBookingId`,列表范围由服务端 `scope=ACTIVE/HISTORY` 分页,禁止浏览器筛选或本地推导写资格。后端为 `LoadingListService`、`firstleg/customs/container/`、`firstleg/terminaldrayage/`,文件归 `file/` | | 合柜报关 / 同柜不可拆组 | `modules/unified-orders/api/coLoadGroups.ts`、`pages/UnifiedOrdersView.vue`;装柜消费 `modules/container-loading/pages/SmartLoadingWorkbenchView.vue` | 前端只提交订单 ID;Backend `firstleg/loading/coload/` 展开并冻结每票全部可用入仓片段。成员数是入仓片段数,不等于订单票数;只要求同国内仓、同渠道,允许跨客户及不同目的仓港;分配、移除、取消均整组处理 | | 全局智能装柜工作台、入仓码候选与箱数分配 | `modules/container-loading/components/SmartLoadingDialog.vue` 内嵌 `pages/GlobalSmartLoadingView.vue`,柜次页 `SmartLoadingWorkbenchView.vue`,以及 `smartLoadingChannelGroups.ts`、`smartLoadingItems.ts`、`api/platformContainerLoading.ts`;全局页当前不注册独立路由 | Backend `firstleg/` 的 `/inbound-candidates`、`/containers`、`/inbound-assignments`、`/plans/{planId}/pending-review-assignments`、`/group-assignments`、`/unpicked-items`。`orderStatuses` 最多四项且未传表示全部未完成状态;候选状态多选覆盖待审核、待测量、待分柜、装柜中,状态只用于筛选展示,按钮资格以服务端 `canAssign` 为准;待审核/待测量可提前占位但不得提前确认预装或启动 PDA。计划箱数编辑上限、已用和未用展示只消费服务端 `totalPackageCount/remainingPackageCount`,不得从候选页或本地规格重新拼算。人工加入允许跨渠道,智能推荐仍按柜次渠道。柜次容量和限重取服务端字段;同柜组作为单卡整组分页、分配和移除,任一成员已拣时整组保留 | | 国内货柜履约订舱资料、打印、关联候选与出仓前船期 | `modules/ocean-bookings/` 的 `components/OceanBookingDocumentsPanel.vue`、`OceanBookingPrintDialog.vue`,以及 `modules/container-loading/`、`modules/port-schedules/` | 订舱草稿按当前版本维护资料,放舱后资料与表单只读;打印对草稿与已放舱订舱均开放,按当前已保存资料生成,未填写字段显示“—”。`platformOceanBookings.ts` 的 `/link-candidates` 只消费服务端分页,`containerCount` 是柜型需求 `quantity` 总和;Backend `firstleg/oceanbooking/`、`file/`、`print/`、`firstleg/portschedule/` | | 订舱级拖车预约 | `modules/trucking/api/platformTrucking.ts` 的 `/candidates`、`components/TruckAppointmentForm.vue`、`pages/TruckAppointmentCreateView.vue`、`TruckAppointmentsView.vue` | 表单只选择服务端返回的 `RELEASED` 订舱与拖车供应商,不选择或提交客户、柜次、装柜计划或真实集装箱号;提单号和仓库由订舱冻结事实带入。一个订舱最多一张非终态拖车单,重复创建转入现有单继续编辑;PDA 完成不自动推进拖车。附件为平台作用域且不重复提单文件;Backend `TruckAppointmentService`、`truck-appointments-v1.yaml` | | 目的港码头拖车与还空预警 | 海外清关提柜工作台/详情 `modules/container-loading/pages/OverseasContainersView.vue`、`OverseasContainerDetailView.vue`,API `modules/container-loading/api/terminalDrayages.ts` | 按 `containerBookingId` 读取服务端状态、`allowedActions` 和历史,不能复用订舱级拖车表单或自行推进状态;实际到港后选择 `ACTIVE + TRUCKING` 车队,再预约提柜、确认实际提柜与实际还柜。还空截止、超时天/小时只展示服务端基于权威卸柜完成时间加 72 小时计算的结果;Backend `firstleg/terminaldrayage/`、`terminal-drayage-v1.yaml` 列表消费 `SEND_PICKUP_EMAIL`,邮件记录通过 `terminalDrayages.ts` 查询与重试;发送及换队成功只提示已入队,发送权限复用码头车队编辑权限。 | | 历史报关协同与国内出仓 | `modules/customs/`、`modules/outbound-dispatch/` | `modules/customs/` 是历史报关案件/清单/代理提交与回执入口;装柜完成后的整柜退税/买单资料从货柜详情进入,不在旧模块复制;Backend `firstleg/outbound/dispatch/`、`firstleg/customs/`、`file/` | | 主数据、下载、退避任务重试、审计 | `modules/master-data/`、`modules/downloads/pages/DownloadCenterView.vue`、`modules/audit/` | File 导出任务返回 `attemptCount/maxAttempts/nextRetryAt`;仅失败或已进入自动退避的等待任务显示重试,等待任务重试用于立即执行当前投递,不创建新任务;联查 `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/`;预计节点只展示不推进实际进度,手工实际节点必须严格向后追加并防重复,十节点标准见 `../../docs/海外仓业务/船节点标准化契约.md` | | 海外排车、出库与派送 | `modules/overseas-warehouse/AGENTS.md` | 按模块表定位排车、出库、派送页面及 API;履约边界在模块内维护 | | 海外异常退回与客户回访 | `modules/overseas-warehouse/AGENTS.md` | 派送异常退回区别于退货库存;页面、API 与原子推进约束见模块指引 | 全量验收按业务从 `../../docs/订单与客户/`、`入库测量与计费/`、`国内货柜履约/`、`财务管理/` 选择最小契约;海外仓业务开发先读 `../../docs/海外仓业务/README.md`。进度、排期或验收状态问题再读取进度表和报告。 散货托盘码打印:`modules/loading-lists/components/PalletLabelPrintDialog.vue`、`modules/loading-lists/api/platformLoadingLists.ts`,由货柜详情与装柜清单详情进入;先调用 `/pallet-labels/prepare` 获取服务端按 FBA 仓分组的冻结清单,再通过 `/pallet-labels/print` 下载 PDF。托盘码使用“真实柜号-FBA 地址内部编号-三位序号”,页面同时展示 FBA 仓码和内部编号;支持全部打印或按仓指定张数补打,一件代发托盘不在该清单,前端不生成或重新编号托盘码。 ## 海外模块内部快速索引(海外仓全流程) - 海外仓的尾程订单控制与柜级入仓计划转换、退货库存、排车出库、异常回访:读取 `src/modules/overseas-warehouse/AGENTS.md`,字段与流程仅在该模块维护。 | 关键词 | 页面/路由入口 | API 与联查 | |---|---|---| | 海外采购 | `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/` | ## 业务、安全与共享装配 - 当前只有平台、客户两级;Admin 不显示“租户”。平台仓库是公共主数据,不与客户绑定;客户筛选不得缩小仓库候选。完整语义见平台客户层级与权限契约。 - 新建客户时,公司联系电话同时初始化首个管理员登录手机号;创建后公司联系电话只属于企业资料,与首个管理员、成员及平台用户登录手机号独立。编辑客户资料不得提交账号手机号变更,账号手机号改动统一走用户管理并由 IAM/Auth 撤销对应会话。 - 菜单、列表路由和详情只读统一使用 `*:list`,写操作使用独立权限;前端守卫不能替代服务端鉴权。供应商固定使用 `platform:supplier:list`。 - 平台用户选择 `OVERSEAS_WAREHOUSE_PDA_OPERATOR` 时必须选择唯一实际海外收货仓,其他角色不得提交 `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。 - 删除、停用、改权限等高风险操作必须有确认、处理中、成功和失败反馈;失败保留用户上下文。日志、提示和示例不得包含真实账号、Token、隐私或生产数据。 - 页面和交互必须服从对应原型及验收规则;Admin 当前只验收 `1920×1080`、`100%` 缩放。标准列表和共享组件实现继续读 `src/shared/components/AGENTS.md`。 ## 开发验收身份 - 开发环境人工验收身份为 `platform_admin`。密码从未提交的 `CHONGCHONG_ADMIN_ACCEPTANCE_PASSWORD` 或 `C:/Users/BY-OY/.codex/chongchong-global-dev-acceptance.env` 读取;缺失时再向用户索取,不写入仓库、日志或快照。 - 由人工操作真实页面并截图,AI 核对加载、空态、错误态、权限和桌面布局;缺少截图时标记“待人工截图确认”,不自行批量取证。 ## 命令与质量门禁 在 `apps/admin-web` 执行: ```bash pnpm install pnpm dev pnpm test pnpm typecheck pnpm build ``` - 普通变更至少运行 `pnpm typecheck` 和受影响测试;交付前运行 `pnpm test` 与 `pnpm build`。当前没有 lint 脚本,不声称 lint 通过。 - 不手工修改 `dist/`、`node_modules/` 或生成声明;依赖变化同步 `package.json` 与锁文件。 - 测试环境全量验收入口为 `../../baiyue-firstleg/scripts/admin-test-env-acceptance.mjs`,模块说明见同仓库 `scripts/admin-test-env-modules/README.md`;它会写入或停用测试数据,只有本轮明确授权才能运行。 - `pnpm test/typecheck` 和本地回归脚本不代表真实服务验收完成;HTTP 验收后仍由人工完成页面和截图确认。