From 22e60248d252a98a20918e101346f0c56d1c737e Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Wed, 21 Oct 2026 17:26:49 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/overseas-warehouse/AGENTS.md | 4 ++-- src/modules/overseas-warehouse/PROTOTYPE_MATRIX.md | 2 +- .../components/DispatchLoadingDocuments.test.ts | 10 ++++++++++ .../dispatchCommandRecovery.test.ts | 4 ++-- src/styles/adminDensity.css | 2 +- src/styles/adminDensity.test.ts | 12 +++++++++++- 6 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/modules/overseas-warehouse/AGENTS.md b/src/modules/overseas-warehouse/AGENTS.md index 6927236a..3cca352a 100644 --- a/src/modules/overseas-warehouse/AGENTS.md +++ b/src/modules/overseas-warehouse/AGENTS.md @@ -35,7 +35,7 @@ ## 履约硬边界 -- 排车详情固定四个彩色图标页签:车辆信息、排车信息、单据信息、关联订单明细。五个作业阶段及审核分区、逐动作Gate由服务端返回;取消独立于阶段。装车完成须真实PDA拣货核平,装车完成进入装车后,五张装车照片全部保存后自动生成派送单并进入派送中,无独立安排派送或发车确认;Admin和PDA共用正式版本化命令。已有单写入提交recordVersion(0合法)、原幂等键和完整载荷;未知结果保留原请求核对,成功后另读当前事实。 +- 排车详情固定四个彩色图标页签:车辆信息、排车信息、单据信息、关联订单明细。五个作业阶段及审核分区、逐动作Gate由服务端返回;取消独立于阶段。装车完成须真实PDA拣货核平,装车中可同步上传五张装车照片,确认装车完成且资料齐全自动生成派送单并进入派送中,资料未齐时留在装车后,无独立安排派送或发车确认;Admin和PDA共用正式版本化命令。已有单写入提交recordVersion(0合法)、原幂等键和完整载荷;未知结果保留原请求核对,成功后另读当前事实。 - 智能排车来源支持 `RELABEL`(待出库换标单),按服务端候选的`selection.relabelNo/sourceVersion`提交,不用展示订单号或原入仓号替代换标身份;沿用真实库存、托盘与箱唛,不生成新入库单。客户和仓库归属由服务端核验,不在前端拼接客户子排车。 - 托盘标签从 `pages/PalletsView.vue` → `api/pallets.ts` 的 `getPalletLabelPdf` 下载服务端 PDF,传该行仓库与托盘 ID,复用列表权限;不在前端生成标签或维护模板、尺寸、编码。模板/接口变化才查 [Print 指引](../../../../../baiyue-firstleg/print/AGENTS.md)的托盘入口及[标签维护](../../../../../docs/打印标签维护/README.md),纯按钮文案不追加打印资料。 @@ -54,7 +54,7 @@ | 货物计划与装车命令 | [对应条款](../../../../../docs/业务实现边界.md#admin-货物计划与装车命令) | | 取消与费用展示 | [对应条款](../../../../../docs/业务实现边界.md#admin-取消与费用展示) | | 业务导出 | [对应条款](../../../../../docs/业务实现边界.md#admin-业务导出) | -| 装车后资料入口 | [对应条款](../../../../../docs/业务实现边界.md#admin-装车后资料入口) | +| 装车照片与资料入口 | [对应条款](../../../../../docs/业务实现边界.md#admin-装车照片与资料入口) | ## 验证 diff --git a/src/modules/overseas-warehouse/PROTOTYPE_MATRIX.md b/src/modules/overseas-warehouse/PROTOTYPE_MATRIX.md index d6634241..42106cbf 100644 --- a/src/modules/overseas-warehouse/PROTOTYPE_MATRIX.md +++ b/src/modules/overseas-warehouse/PROTOTYPE_MATRIX.md @@ -428,4 +428,4 @@ | 页面 | 操作 | 原型/确认依据 | 承载与实现 | 验收 | |---|---|---|---|---| -| 排车列表:派送中、配送完成 | 管理资料 | 用户管理资料截图及同车/派送单资料共用确认;签收完成即可,其他可补 | 1100px居中可全屏弹框,签收文件/油耗图片/装车资料三个页签;按关联派送单切换,共用原派送资料编辑器;油耗沿本车附加照片保存 | 自动回归单独报告;1920×1080、100%待人工截图确认 | +| 排车列表:装车中、装车后、派送中、配送完成 | 管理资料 | 用户管理资料截图及同车/派送单资料共用确认;签收完成即可,其他可补 | 1100px居中可全屏弹框,签收文件/油耗图片/装车资料三个页签;装车中及装车后默认打开装车资料,可同步上传,确认装车且资料齐全后自动派送;按关联派送单切换,共用原派送资料编辑器;油耗沿本车附加照片保存 | 自动回归单独报告;1920×1080、100%待人工截图确认 | diff --git a/src/modules/overseas-warehouse/components/DispatchLoadingDocuments.test.ts b/src/modules/overseas-warehouse/components/DispatchLoadingDocuments.test.ts index 1bfc46a6..4e459d5e 100644 --- a/src/modules/overseas-warehouse/components/DispatchLoadingDocuments.test.ts +++ b/src/modules/overseas-warehouse/components/DispatchLoadingDocuments.test.ts @@ -61,3 +61,13 @@ it('shows existing photos without exposing upload for a read-only account', asyn expect(wrapper.find('input[type="file"]').exists()).toBe(false) expect(api.uploadLoadingPhoto).not.toHaveBeenCalled(); wrapper.unmount() }) + +it('allows saving photos while loading and keeps the loading stage', async () => { + vi.mocked(api.getLoadingDocuments).mockResolvedValue(data({ stage: 'LOADING' })) + vi.mocked(api.bindLoadingPhoto).mockResolvedValue(data({ stage: 'LOADING', recordVersion: '1', photos: [photo] })) + const wrapper = setup(); await flushPromises() + expect(wrapper.text()).toContain('可边装车边上传') + await upload(wrapper) + expect(wrapper.emitted('saved')).toHaveLength(1) + expect(wrapper.text()).toContain('可边装车边上传'); wrapper.unmount() +}) diff --git a/src/modules/overseas-warehouse/dispatchCommandRecovery.test.ts b/src/modules/overseas-warehouse/dispatchCommandRecovery.test.ts index 943c11a9..4484977f 100644 --- a/src/modules/overseas-warehouse/dispatchCommandRecovery.test.ts +++ b/src/modules/overseas-warehouse/dispatchCommandRecovery.test.ts @@ -3,11 +3,11 @@ import { ApiResponseError } from '@/shared/api/http' import { useDispatchCommandRecovery } from './dispatchCommandRecovery' import { command } from './dispatchTestFixtures' beforeEach(() => sessionStorage.clear()) -it('rejects a loading result that skips the loading documents stage', async () => { +it('rejects a loading result that has not completed loading', async () => { const owner = crypto.randomUUID(), recovery = useDispatchCommandRecovery(() => owner) recovery.begin('PC/1', 'LOADING_COMPLETE', { recordVersion: 0, idempotencyKey: 'key' }) const read = vi.fn() - await expect(recovery.execute(vi.fn().mockResolvedValue({ ...command('LOADING_COMPLETE'), stage: 'DELIVERING' }), read, vi.fn())).rejects.toThrow('装车后') + await expect(recovery.execute(vi.fn().mockResolvedValue({ ...command('LOADING_COMPLETE'), stage: 'LOADING' }), read, vi.fn())).rejects.toThrow('装车完成') expect(read).not.toHaveBeenCalled() expect(recovery.pending.value?.result).toBeNull() expect(recovery.pending.value?.body.idempotencyKey).toBe('key') diff --git a/src/styles/adminDensity.css b/src/styles/adminDensity.css index 820e1668..0725162d 100644 --- a/src/styles/adminDensity.css +++ b/src/styles/adminDensity.css @@ -33,7 +33,7 @@ .admin-density .el-empty__description { margin-top: 0; } .admin-density .el-empty__description p { font-size: var(--admin-font-body, 13px); } .admin-density-dialog .el-form-item__label { line-height: 22px; } -.admin-density-dialog .el-form--inline .el-form-item__label { align-items: center; } +.admin-density-dialog .el-form-item:not(.el-form-item--label-top) .el-form-item__label { align-items: center; } :is(.admin-density, .admin-density-dialog, .admin-density-drawer) .el-table th.el-table__cell { background: var(--cc-list-table-header-bg); color: var(--cc-list-table-header-text); diff --git a/src/styles/adminDensity.test.ts b/src/styles/adminDensity.test.ts index 15a8aff7..f248ec4f 100644 --- a/src/styles/adminDensity.test.ts +++ b/src/styles/adminDensity.test.ts @@ -1116,7 +1116,17 @@ describe('approved Admin density ownership', () => { cell.innerHTML = '
' expect(cell.querySelector('td')!.matches(stripeSelector)).toBe(false) expect(rules.get('.admin-density-dialog .el-descriptions__label.el-descriptions__cell')?.background).toBe('var(--admin-label-bg)') - expect(rules.get('.admin-density-dialog .el-form--inline .el-form-item__label')?.['align-items']).toBe('center') + const horizontalLabelSelector = '.admin-density-dialog .el-form-item:not(.el-form-item--label-top) .el-form-item__label' + expect(rules.get(horizontalLabelSelector)?.['align-items']).toBe('center') + const labelFixture = document.createElement('div') + labelFixture.innerHTML = '
' + const formItem = labelFixture.querySelector('.el-form-item')! + const label = labelFixture.querySelector('label')! + expect(label.matches(horizontalLabelSelector)).toBe(true) + formItem.className = 'el-form-item el-form-item--label-right' + expect(label.matches(horizontalLabelSelector)).toBe(true) + formItem.className = 'el-form-item el-form-item--label-top' + expect(label.matches(horizontalLabelSelector)).toBe(false) expect(rules.get('.admin-density-dialog.el-dialog.admin-density-workspace > .el-dialog__body')?.flex).toBe('1 1 auto') for (const tone of ['warning', 'purple', 'primary', 'success', 'danger']) { expect(rules.get(`:is(.admin-density, .admin-density-dialog) .density-action[data-tone="${tone}"]`)?.['--action-hover-bg']).toBe(`var(--admin-action-${tone}-hover)`)