diff --git a/src/modules/appointment-calendar/PROTOTYPE_MATRIX.md b/src/modules/appointment-calendar/PROTOTYPE_MATRIX.md index 5e960099..1536d507 100644 --- a/src/modules/appointment-calendar/PROTOTYPE_MATRIX.md +++ b/src/modules/appointment-calendar/PROTOTYPE_MATRIX.md @@ -6,7 +6,7 @@ | 页面/组件 | 操作与承载 | 本次调整 | 验收 | |---|---|---|---| -| AppointmentCalendarView | 调整计划到仓,原520px居中弹框及全屏能力 | 1处日期时间选择器;分钟精度沿用原请求格式;标签宽度150px,说明图标与标签并排,控件沿用公共满宽样式 | 自动检查通过;待人工1920×1080、100%截图确认 | +| AppointmentCalendarView | 调整计划到仓,原520px居中弹框及全屏能力 | 1处日期时间选择器;分钟精度沿用原请求格式;标签宽度150px,说明图标与标签并排,控件沿用公共满宽样式 | 真实浏览器检查通过:日期面板、选值、空值禁用、全屏保值、未保存保护及放弃返回;未提交业务保存 | | WorkReceivingPanel | 原业务深链中的客户计划、后送与跟进,原表单 | 5处日期/日期时间输入;日期与秒精度的当地时间分别保存;调整开始/结束时段后仍清除原时差依据 | 自动检查通过;待人工截图确认 | | WorkCommandForm | 跟进、收货要求,原表单 | 3处日期、2处时间输入;跨日结束日期显式保留;不推断次日、不转换地点时区 | 自动检查通过;待人工截图确认 | | AppointmentBatchForm | 原分批/合并表单 | 2处可空目标日期,保留跨批分配、版本、幂等与原写权限 | 自动检查通过;待人工截图确认 | @@ -15,6 +15,8 @@ 自动验证:受影响7个测试文件88项通过;类型检查与生产构建通过。全量回归执行464个文件4203项,4201项通过,两项旧公共样式断言(标签宽度、追加样式类)更新后,该样式文件65项全部复验通过。后台业务模板原生日期/时间控件残留检查通过。本轮未部署TEST,未进行真实HTTP或人工页面截图验收。 +补充浏览器验收:用户明确要求打开页面后,使用已发布TEST页面,页面报告1920×1080、DPR1、visual scale1。TSTU5446539的默认计划、Element日期面板、快捷选值、全屏保值、清空禁用、未保存保护与放弃返回通过;原计划仍2026-10-01,未点击保存。MSCU7264017现已有入库计划,按冻结时间显示且无调整入口。本轮仅覆盖日历与调整到仓弹框,其余三表单仍待逐页操作;输入09:30的最终确认未单独完成,不计通过。证据见 `.logs/appointment-element-release-20261020/ui/result.json` 及同目录截图。 + ## 2026-10-20 蓝白工作台续批(写权已协调) 本次续批修改文件(相对本模块): diff --git a/src/modules/container-loading/pages/GlobalSmartLoadingView.test.ts b/src/modules/container-loading/pages/GlobalSmartLoadingView.test.ts index e87a3723..ee1de3f9 100644 --- a/src/modules/container-loading/pages/GlobalSmartLoadingView.test.ts +++ b/src/modules/container-loading/pages/GlobalSmartLoadingView.test.ts @@ -891,6 +891,41 @@ describe('GlobalSmartLoadingView', () => { expect(listSmartLoadingCandidates).toHaveBeenCalledWith({ channelGroupCodes: ['MATSON_CLX'], page: 1, size: 20 }) }) + it('keeps assignment failures and diagnostic IDs inside the open dialog without losing the quantity', async () => { + vi.spyOn(ElMessage, 'error').mockImplementation(() => undefined as never) + vi.mocked(assignSmartLoadingItem).mockRejectedValueOnce(new AxiosError( + 'forbidden', 'ERR_BAD_REQUEST', undefined, undefined, + { data: { code: 'A0403', message: 'Access denied', requestId: 'assign-request', traceId: 'assign-trace' }, status: 403, statusText: 'Forbidden', headers: {}, config: {} as never }, + )) + const wrapper = mount(GlobalSmartLoadingView, { attachTo: document.body, global: { plugins: [ElementPlus] } }) + await flushPromises() + await wrapper.get('.candidate-pane .el-table__body-wrapper').findAll('button').find(button => button.text() === '加入')!.trigger('click') + await flushPromises() + const popup = wrapper.getComponent(AppDialog) + const input = popup.getComponent(ElInputNumber) + input.vm.$emit('update:modelValue', 7) + await flushPromises() + + // 箱数与上方资料使用同一标签列,保留输入名称与原范围。 + const label = popup.get('label[for="global-loading-assignment-count"]') + expect(label.element.parentElement?.tagName).toBe('TH') + expect(label.element.parentElement?.nextElementSibling?.getAttribute('colspan')).toBe('3') + expect(popup.find('input#global-loading-assignment-count').exists()).toBe(true) + expect(input.props('max')).toBe(candidate.availablePackageCount) + popup.vm.$emit('confirm') + await flushPromises() + + expect(assignSmartLoadingItem).toHaveBeenCalledWith(plan.id, { inboundId: candidate.inboundId, packageCount: 7, expectedVersion: plan.version }) + expect(popup.props('modelValue')).toBe(true) + expect(input.props('modelValue')).toBe(7) + expect(popup.text()).toContain('加入当前柜次失败') + expect(popup.text()).toContain('当前账号无权访问该数据') + expect(popup.text()).toContain('assign-request') + expect(popup.text()).toContain('assign-trace') + expect(wrapper.get('.global-loading-page').findAll('.load-error-state')).toHaveLength(1) + wrapper.unmount() + }) + it('refreshes the latest plan after A0409 without losing the selected container', async () => { const warningMessage = vi.spyOn(ElMessage, 'warning').mockImplementation(() => undefined as never) const wrapper = mount(GlobalSmartLoadingView, { global: { plugins: [ElementPlus] } }) diff --git a/src/modules/container-loading/pages/GlobalSmartLoadingView.vue b/src/modules/container-loading/pages/GlobalSmartLoadingView.vue index 5770bf9c..c9b1e1af 100644 --- a/src/modules/container-loading/pages/GlobalSmartLoadingView.vue +++ b/src/modules/container-loading/pages/GlobalSmartLoadingView.vue @@ -494,6 +494,7 @@ function openAssign(source: object) { const candidate = candidateRow(source) if (candidateBlocked(candidate)) return selectedCandidate.value = candidate + mutationError.value = null assignForm.packageCount = candidate.coLoadGroupId ? Number(candidate.groupTotalBoxes || candidate.availablePackageCount) : candidate.availablePackageCount @@ -716,7 +717,7 @@ onMounted(() => { void load(); void loadCustomers() })