diff --git a/AGENTS.md b/AGENTS.md
index 3fad531f..8cf47f16 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -3,9 +3,8 @@
## 快速读取顺序
1. 由“模块快速路由”选最小模块并读最近 `AGENTS.md`,按 `routes.ts → pages/ → api/types/stores/composables` 下钻,不扫描全部 `src/`。
-2. 视觉、布局/交互承载变更或真实页面验收先读 `../../docs/Admin-Client前端原型还原验收规则.md`;需原型依据再读 `../../docs/悦/货代SAAS平台后台/AGENTS.md` 并定位片段。纯文案、逻辑或单元测试不触发。
- 样式优化另读 `../../docs/Admin高密度界面规范.md` 的“样式维护边界”“新模块接入规则”,保留已确认密度、彩色页签、业务语义及承载。国内仓、客户管理为样板;新增菜单按本轮范围显式接入,货柜入口见 `../../docs/Admin货柜管理样式核对记录.md`。
- 蓝白样式接入见 [样板指南](../../docs/界面参考/蓝白卡片式工作台风格参考.md)。
+2. Admin 样式唯一入口为 [Admin 界面规范](../../docs/Admin高密度界面规范.md#按任务阅读),按任务只读对应章节;提示小字、加载布局、蓝白风格及密度不再分散查多份规范。样板目录仅在需要视觉参考时查,模块核对记录仅在核对范围、业务例外或验收证据时查。
+ 视觉、布局/交互承载变更或真实页面验收再读 [前端验收规则](../../docs/Admin-Client前端原型还原验收规则.md);需原型依据再读 `../../docs/悦/货代SAAS平台后台/AGENTS.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` 对应章节。
@@ -99,7 +98,7 @@
- 接入真实接口时删除对应模拟路径,不允许生产逻辑静默回退假数据。客户专属写操作显式选择客户,长整型 ID 按字符串透传,不从本地存储推断。
- 订舱代理、拖车承运商和报关代理提交服务端供应商 ID,从公共供应商列表选择 `ACTIVE` 且类别/范围匹配的记录;参数变化同步检查 API、类型、表单、展示、Mock/Fixture、测试和 OpenAPI。
- 删除、停用、改权限等高风险操作必须有确认、处理中、成功和失败反馈;失败保留用户上下文。日志、提示和示例不得包含真实账号、Token、隐私或生产数据。
-- 页面和交互必须服从对应原型及验收规则;Admin 当前只验收 `1920×1080`、`100%` 缩放。标准列表和共享组件实现继续读 `src/shared/components/AGENTS.md`。
+- 页面外观遵循 Admin 界面规范,业务及操作承载核对当前契约、逐操作确认与原型证据;Admin 当前只验收 `1920×1080`、`100%` 缩放。标准列表和共享组件实现继续读 `src/shared/components/AGENTS.md`。
## 开发验收身份
diff --git a/src/modules/appointment-calendar/AppointmentConfirmationCargo.test.ts b/src/modules/appointment-calendar/AppointmentConfirmationCargo.test.ts
new file mode 100644
index 00000000..931cac25
--- /dev/null
+++ b/src/modules/appointment-calendar/AppointmentConfirmationCargo.test.ts
@@ -0,0 +1,98 @@
+import { flushPromises, mount } from '@vue/test-utils'
+import { beforeEach, expect, it, vi } from 'vitest'
+import { ElMessageBox } from 'element-plus'
+import AppointmentConfirmationCargo from './AppointmentConfirmationCargo.vue'
+import { resolvePlanningOrder, resolvePlanningSource, type ResolvedPlanningSource } from './planningApi'
+import { getCargoVerification, saveCargoVerification, type CargoVerificationContext } from './cargoVerificationApi'
+
+const access = vi.hoisted(() => ({ read: true }))
+vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: () => access.read }) }))
+vi.mock('element-plus', () => ({ ElMessage: { warning: vi.fn(), success: vi.fn() }, ElMessageBox: { confirm: vi.fn() } }))
+vi.mock('./planningApi', () => ({ resolvePlanningOrder: vi.fn(), resolvePlanningSource: vi.fn() }))
+vi.mock('./cargoVerificationApi', () => ({ getCargoVerification: vi.fn(), saveCargoVerification: vi.fn() }))
+const source: ResolvedPlanningSource['source'] = { sourceKey: 'BOOKING:BK-TEST', customerId: 'customer-1', orderId: '9007199254740993', inboundCode: 'IN-TEST', bookingNo: 'BK-TEST', containerNo: null, originWarehouseId: 'warehouse-1', originWarehouseName: '测试仓', destinationKey: 'FBA:ONT8', destinationWarehouseCode: 'ONT8', packages: 20, sourceVersion: 'BOOKING:1/ORDER:1', canFollowup: true, blockReasons: [] }
+const resolved: ResolvedPlanningSource = { source, coverage: { status: 'PENDING', appointments: [], missingFields: ['FBA_SHIPMENT_REFERENCES'], changeReviewRequired: false } }
+const context: CargoVerificationContext = { source, verification: null, allocatedPackages: 20, unknownAllocationCount: 0, effectivePackages: 20, availablePackages: 0, sourceChanged: false, allowedActions: ['VERIFY_CARGO'], blockReasons: [] }
+const lookup = { orderId: source.orderId!, customerId: source.customerId, destinationKey: source.destinationKey }
+function render(active = true, disabled = false) {
+ return mount(AppointmentConfirmationCargo, { props: { sources: [lookup], active, disabled }, global: { stubs: {
+ ElButton: { props: ['disabled', 'nativeType'], template: '' },
+ InlineHelp: { template: '' }, ApiErrorMeta: true,
+ LoadErrorState: { props: ['message'], template: '
{{ message }}
' },
+ } } })
+}
+beforeEach(() => {
+ vi.clearAllMocks(); access.read = true
+ vi.mocked(resolvePlanningOrder).mockResolvedValue(resolved)
+ vi.mocked(resolvePlanningSource).mockResolvedValue(resolved)
+ vi.mocked(getCargoVerification).mockResolvedValue(context)
+ vi.mocked(saveCargoVerification).mockResolvedValue({ version: 1, sourceVersion: source.sourceVersion, destinationKey: source.destinationKey, sourcePackages: 20, packageCount: 20, shipmentReferences: ['FBA-TEST'], remark: null, operatorName: '测试员', verifiedAt: '2026-10-21T03:00:00Z' })
+})
+it('names the missing material and supplements the canonical booking inside the appointment', async () => {
+ const wrapper = render(); await flushPromises()
+ expect(resolvePlanningOrder).toHaveBeenCalledWith(lookup)
+ expect(wrapper.text()).toContain('IN-TEST'); expect(wrapper.text()).toContain('缺少本票 FBA 货件号或追踪号')
+ expect(wrapper.text()).toContain('不能代替货件号'); expect(wrapper.text()).not.toContain(source.orderId)
+ await wrapper.findAll('button').find(button => button.text() === '在此补齐资料')!.trigger('click'); await flushPromises()
+ expect((wrapper.get('input[type=number]').element as HTMLInputElement).value).toBe('20')
+ await wrapper.get('form').trigger('submit'); await flushPromises()
+ expect(saveCargoVerification).not.toHaveBeenCalled()
+ await wrapper.get('textarea[aria-label="本票货件号"]').setValue('FBA-TEST')
+ vi.mocked(resolvePlanningOrder).mockResolvedValue({ ...resolved, coverage: { ...resolved.coverage, missingFields: [] } })
+ await wrapper.get('form').trigger('submit'); await flushPromises()
+ expect(saveCargoVerification).toHaveBeenCalledWith(source, expect.objectContaining({ packageCount: 20, shipmentReferences: ['FBA-TEST'], expectedSourceVersion: source.sourceVersion }))
+ expect(wrapper.text()).toContain('资料齐全,无需重复填写')
+ expect(wrapper.emitted('ready')?.at(-1)).toEqual([true]); wrapper.unmount()
+})
+it('leaves pending arrangements lazy and reads only when formal confirmation is selected', async () => {
+ const wrapper = render(false); await flushPromises()
+ expect(resolvePlanningOrder).not.toHaveBeenCalled()
+ await wrapper.setProps({ active: true }); await flushPromises()
+ expect(resolvePlanningOrder).toHaveBeenCalledTimes(1); wrapper.unmount()
+})
+it('does not ask for known materials to be entered again', async () => {
+ vi.mocked(resolvePlanningOrder).mockResolvedValue({ ...resolved, coverage: { ...resolved.coverage, missingFields: [] } })
+ const wrapper = render(); await flushPromises()
+ expect(wrapper.text()).toContain('资料齐全,无需重复填写')
+ expect(wrapper.findAll('button').some(button => button.text() === '在此补齐资料')).toBe(false)
+ expect(wrapper.emitted('ready')?.at(-1)).toEqual([true]); wrapper.unmount()
+})
+it('retains unsaved inputs when the appointment mode changes and blocks leaving an unknown save outcome', async () => {
+ const wrapper = render(); await flushPromises()
+ await wrapper.findAll('button').find(button => button.text() === '在此补齐资料')!.trigger('click'); await flushPromises()
+ await wrapper.get('textarea[aria-label="本票货件号"]').setValue('FBA-KEEP')
+ await wrapper.setProps({ active: false })
+ expect(wrapper.get('textarea[aria-label="本票货件号"]').isVisible()).toBe(true)
+ vi.mocked(ElMessageBox.confirm).mockRejectedValueOnce(new Error('keep editing'))
+ expect(await wrapper.vm.canLeave()).toBe(false)
+ vi.mocked(saveCargoVerification).mockRejectedValueOnce(new Error('connection lost'))
+ await wrapper.get('form').trigger('submit'); await flushPromises()
+ expect(await wrapper.vm.canLeave()).toBe(false)
+ const payload = vi.mocked(saveCargoVerification).mock.calls[0]![1]
+ await wrapper.get('form').trigger('submit'); await flushPromises()
+ expect(saveCargoVerification).toHaveBeenNthCalledWith(2, source, payload); wrapper.unmount()
+})
+it('reports unknown quantity and unmaterialized cargo without inventing values', async () => {
+ vi.mocked(resolvePlanningOrder).mockResolvedValue({ ...resolved, source: { ...source, orderId: null } })
+ vi.mocked(getCargoVerification).mockResolvedValue({ ...context, effectivePackages: null })
+ const wrapper = render(); await flushPromises()
+ expect(wrapper.text()).toContain('缺少本票箱数'); expect(wrapper.text()).toContain('原来货登记完成实收关联')
+ expect(wrapper.findAll('button').some(button => button.text() === '在此补齐资料')).toBe(false)
+ expect(wrapper.emitted('ready')?.at(-1)).toEqual([false]); wrapper.unmount()
+})
+it('keeps failed reads blocked, supports retry, and denies reads without permission', async () => {
+ vi.mocked(resolvePlanningOrder).mockRejectedValueOnce(new Error('network lost'))
+ const wrapper = render(); await flushPromises()
+ expect(wrapper.find('[role=alert]').exists()).toBe(true)
+ expect(wrapper.emitted('ready')?.at(-1)).toEqual([false])
+ await wrapper.get('[role=alert] button').trigger('click'); await flushPromises()
+ expect(resolvePlanningOrder).toHaveBeenCalledTimes(2); wrapper.unmount()
+ vi.clearAllMocks(); access.read = false
+ const denied = render(); await flushPromises()
+ expect(resolvePlanningOrder).not.toHaveBeenCalled(); expect(denied.text()).toContain('查看权限'); denied.unmount()
+})
+it('keeps the supplement action disabled for read-only appointment views', async () => {
+ const wrapper = render(true, true); await flushPromises()
+ expect(wrapper.findAll('button').find(button => button.text() === '在此补齐资料')!.attributes('disabled')).toBeDefined()
+ expect(saveCargoVerification).not.toHaveBeenCalled(); wrapper.unmount()
+})
diff --git a/src/modules/appointment-calendar/AppointmentConfirmationCargo.vue b/src/modules/appointment-calendar/AppointmentConfirmationCargo.vue
new file mode 100644
index 00000000..1e45c0db
--- /dev/null
+++ b/src/modules/appointment-calendar/AppointmentConfirmationCargo.vue
@@ -0,0 +1,85 @@
+
+
+
+ 正式确认前:核对本次送仓货物
+ 重新核对资料
+ 本票总箱数用于校验预约货量;FBA 货件号或追踪号用于识别送的是哪批货。外部约号只代表仓库的预约确认号,不能代替货件号。
+
+ | 操作 | 入仓码 / 外接登记号 | 本票总箱数 | 需要补充的资料 |
+
+ | 在此补齐资料— |
+ {{ row.resolved.source.inboundCode || row.resolved.source.bookingNo || '未提供业务编号' }} |
+ {{ row.cargo.effectivePackages ?? '待补充' }} |
+ {{ issues(row).join(';') || '资料齐全,无需重复填写' }} |
+
+
+
+
+ 收起补充资料
+
+ 请先在上表补齐并保存资料,再点击“保存预约安排”。暂时拿不到资料,可先选择“先保存安排,等待对方确认”。
+
+
diff --git a/src/modules/appointment-calendar/AppointmentCreatePanel.vue b/src/modules/appointment-calendar/AppointmentCreatePanel.vue
index b08d5eed..8da2ea1d 100644
--- a/src/modules/appointment-calendar/AppointmentCreatePanel.vue
+++ b/src/modules/appointment-calendar/AppointmentCreatePanel.vue
@@ -42,13 +42,13 @@ const columns: DataTableColumn[] = [
{ prop: 'originWarehouseName', label: '起运仓', minWidth: 140, slotName: 'origin' },
{ prop: 'destinationWarehouseCode', label: '目的FBA仓', width: 110 },
{ prop: 'packages', label: '箱数', width: 80 },
- { key: 'eligibility', label: '预约资格', minWidth: 130, slotName: 'eligibility' },
+ { key: 'eligibility', label: '预约资格', minWidth: 260, singleLine: false, slotName: 'eligibility' },
]
function key(row: PlanningCargo) { return JSON.stringify([row.customerId, row.sourceKey]) }
function reason(row: PlanningCargo) {
if (row.detained) return '货物暂扣中'
if (row.mixedDestinations) return '多个目的地,需先核对'
- if (row.hasActiveAppointment) return '已有有效预约'
+ if (row.hasActiveAppointment) return '已有预约安排,请到入库单编辑原预约'
const anchor = selectedRows.value[0]
if (anchor && (anchor.originWarehouseId !== row.originWarehouseId || anchor.destinationWarehouseCode !== row.destinationWarehouseCode)) return '请选择同起运仓、同目的仓'
if (selectedRows.value.length >= 100 && !selected.value[key(row)]) return '每次最多选择100票'
diff --git a/src/modules/appointment-calendar/CargoVerificationForm.vue b/src/modules/appointment-calendar/CargoVerificationForm.vue
index 4c9f587d..5b02ec3d 100644
--- a/src/modules/appointment-calendar/CargoVerificationForm.vue
+++ b/src/modules/appointment-calendar/CargoVerificationForm.vue
@@ -10,15 +10,16 @@ import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
import { getCargoVerification, saveCargoVerification, type CargoVerificationContext, type CargoVerificationSource, type SaveCargoVerification } from './cargoVerificationApi'
import { rejectedCommand, useWorkDraft } from './useWorkDraft'
-const props = defineProps<{ source: CargoVerificationSource }>()
+const props = defineProps<{ source: CargoVerificationSource; confirmation?: boolean; disabled?: boolean }>()
const emit = defineEmits<{ saved: [] }>()
const access = useAccessPreviewStore()
const context = ref(null), loading = ref(false), saving = ref(false)
const error = ref(null), saveError = ref(null), pending = ref(null)
const form = reactive({ packages: '', references: '', remark: '' }), baseline = ref(JSON.stringify(form))
const dirty = computed(() => JSON.stringify(form) !== baseline.value)
-useWorkDraft(dirty, computed(() => saving.value || !!pending.value))
-const canWrite = computed(() => access.can('platform:overseas-warehouse:inbound-order:fba-appointment') && context.value?.allowedActions.includes('VERIFY_CARGO'))
+const canLeave = useWorkDraft(dirty, computed(() => saving.value || !!pending.value))
+defineExpose({ canLeave })
+const canWrite = computed(() => !props.disabled && access.can('platform:overseas-warehouse:inbound-order:fba-appointment') && context.value?.allowedActions.includes('VERIFY_CARGO'))
async function load(preserve = false) {
loading.value = true; error.value = null
if (!access.can('platform:appointment:list') || !access.can('platform:overseas-warehouse:last-mile-order:list')) { error.value = { message: '当前账号没有该货源的读取权限,请联系预约负责人处理。' }; loading.value = false; return }
@@ -26,7 +27,7 @@ async function load(preserve = false) {
context.value = await getCargoVerification(props.source)
if (!preserve) {
const record = context.value.verification
- Object.assign(form, { packages: record?.packageCount == null ? '' : String(record.packageCount), references: record?.shipmentReferences.join('\n') || '', remark: record?.remark || '' })
+ Object.assign(form, { packages: context.value.effectivePackages == null ? '' : String(context.value.effectivePackages), references: record?.shipmentReferences.join('\n') || '', remark: record?.remark || '' })
baseline.value = JSON.stringify(form)
}
} catch (cause) { error.value = getApiErrorDetails(cause, '核实资料读取失败') }
@@ -39,6 +40,7 @@ async function save() {
if (count !== null && (!Number.isSafeInteger(count) || count < 1)) { ElMessage.warning('核实箱数须为正整数,暂未核实可留空'); return }
if (count !== null && (count < context.value.allocatedPackages || (context.value.source.packages != null && count > context.value.source.packages))) { ElMessage.warning('核实箱数不能低于已分配量,也不能超过已知原箱数'); return }
const references = [...new Set(form.references.split(/\r?\n/).map(value => value.trim()).filter(Boolean))]
+ if (props.confirmation && (count === null || !references.length)) { ElMessage.warning('请填写本票箱数,以及至少一个 FBA 货件号或追踪号;外部约号不能代替货件号'); return }
if (references.length > 100 || references.some(value => value.length > 128)) { ElMessage.warning('最多填写100条货件号,每条不超过128字'); return }
pending.value = { destinationKey: context.value.source.destinationKey, expectedSourceVersion: context.value.source.sourceVersion, expectedVersion: Number(context.value.verification?.version || 0), packageCount: count, shipmentReferences: references, remark: form.remark.trim() || null, idempotencyKey: crypto.randomUUID() }
}
@@ -56,14 +58,15 @@ onMounted(() => load())
- 核实货物资料未约成也可保存;只用于预约核实,保留原订单资料。
+ {{ confirmation ? '补齐本票送仓资料' : '核实货物资料' }}未约成也可保存;只用于预约核实,保留原订单资料。
+ 请向客户或货物负责人取得本票完整的 FBA 货件号或追踪号,每行一个;不要填写预约外部约号。下方保存只补充货物资料,完成后还需保存预约安排。
正在读取货物资料…
- - 原票
- {{ context.source.inboundCode || context.source.bookingNo || '—' }}
- 目的仓
- {{ context.source.destinationWarehouseCode || '—' }}
- 原箱数
- {{ context.source.packages ?? '待核实' }}
- 已分配
- {{ context.allocatedPackages }} 箱;另有 {{ context.unknownAllocationCount }} 项数量未知
- 可分配
- {{ context.availablePackages ?? '待核实' }}
+ - 原票
- {{ context.source.inboundCode || context.source.bookingNo || '—' }}
- 目的仓
- {{ context.source.destinationWarehouseCode || '—' }}
- 原箱数
- {{ context.source.packages ?? '待核实' }}
- 已分配
- {{ context.allocatedPackages }} 箱;另有 {{ context.unknownAllocationCount }} 项数量未知
- 可分配
- {{ context.availablePackages ?? '待核实' }}
原货源已变化,请核对当前原票和已分配量后重新保存。
{{ reason }}
-
+
diff --git a/src/modules/appointment-calendar/index.ts b/src/modules/appointment-calendar/index.ts
index b6fce0af..fddb4e09 100644
--- a/src/modules/appointment-calendar/index.ts
+++ b/src/modules/appointment-calendar/index.ts
@@ -1,2 +1,4 @@
export { appointmentReturnTarget, appointmentReturnQuery } from './workNavigation'
export { default as TripAppointmentPanel } from './TripAppointmentPanel.vue'
+export { default as AppointmentConfirmationCargo } from './AppointmentConfirmationCargo.vue'
+export type { PlanningSourceLookup } from './planningApi'
diff --git a/src/modules/overseas-business/PROTOTYPE_MATRIX.md b/src/modules/overseas-business/PROTOTYPE_MATRIX.md
index a3a70d4e..9a32ffa6 100644
--- a/src/modules/overseas-business/PROTOTYPE_MATRIX.md
+++ b/src/modules/overseas-business/PROTOTYPE_MATRIX.md
@@ -37,6 +37,13 @@
删除和文件预览在三类正式页面中均未定义,不自行补充承载方式;海外采购审核按当前对话确认的承载方式实现。
+### 2026-10-21 本土卡车审核详情页头修复
+
+| 页面 | 操作 | 确认依据与布局 | 当前实现 | 修复结论与验收 |
+|---|---|---|---|---|
+| 本土卡车详情 | 从列表点击审核、查看详情 | 用户截图 `codex-clipboard-515ba915-7b67-48de-9914-62cec7371ec5.png` 红框;当前详情密度规范要求返回、编号、状态及操作合并页头 | 标题、状态/刷新、审核/取消拆成三行,标题使用浏览器默认字号 | 接入公共详情页头与连续白底容器:左侧返回、订单号及单一状态徽标,右侧刷新与原业务操作;保留完整编号;待人工 1920×1080、100% 截图确认 |
+| 本土卡车详情 | 审核、取消及后续命令 | 本表已确认的居中操作确认弹框 | `TruckOrderActions` 保留既有表单、权限及提交保护 | 只移动页头入口,弹框承载、尺寸和命令保持现状;按既有行为测试回归 |
+
## 本土卡车需求字段调整
依据本轮客户端截图及用户确认,同步平台订单字段;规则唯一见 `docs/海外仓业务/README.md`“美国本土卡独立下单”。
@@ -113,3 +120,13 @@
| ProcurementNodeActions | 采购详情中的节点命令居中弹框 | 自定义footer绕过AppDialog默认操作区容器;三项操作加入density-actions底部容器,允许换行并保持间距 | 定向回归通过;待人工1920×1080、100%截图确认 |
保持既有命令、草稿、未知结果核对、权限与提交条件;只新增操作区容器。公共AppDialog的直接按钮footer修复由公共样式写者维护,本域未修改公共组件。
+
+## 2026-10-21 本土运输表单布局修复
+
+| 页面 | 操作 | 依据与现有承载 | 当前问题与修复结论 | 验收 |
+|---|---|---|---|---|
+| 本土卡车 | 新增 | 用户截图 `codex-clipboard-1a93aa11-88f2-4e90-8130-030fa91185f5.png`;既有独立路由及上文统一运输表单矩阵 | 移除居中窄表单的宽度限制及重复分区内距,铺满内容区;接入公共密度表单与分区,保留运输双列、货物三列和字段顺序 | 自动检查通过;待人工 1920×1080、100% 截图确认 |
+| 本土卡车 | 编辑 | 既有独立编辑路由,与新增复用运输表单 | 同步宽度、密度与分区;保留回显、状态限制及提交逻辑 | 同上 |
+| 本土散板 | 新增、编辑 | 既有独立路由,与卡车复用运输表单 | 同步布局修复,保留运输双列、货物四列及散板专属字段 | 同上 |
+
+本次仅调整 Admin 运输表单展示,不改采购编辑的宽度或 Client 表单。在 `apps/admin-web` 经 `local-check.ps1` 执行:`pnpm exec vitest run src/modules/overseas-business/pages/OverseasBusinessViews.test.ts src/modules/overseas-business/contract.test.ts src/styles/adminDensity.test.ts`,3 文件 115 项通过;`pnpm typecheck`、`pnpm build` 通过。共享完整 `pnpm test`(任务名 `Admin restored dispatch full regression`,13:55:33–14:05:50)退出码 0,覆盖本次未再变化的运输表单源码;其他在途排车变更由对应任务验证,不据此推定其最新快照通过。视觉仍待人工截图确认。
diff --git a/src/modules/overseas-business/components/TransportDemandForm.vue b/src/modules/overseas-business/components/TransportDemandForm.vue
index 17f020b4..b9d0c36a 100644
--- a/src/modules/overseas-business/components/TransportDemandForm.vue
+++ b/src/modules/overseas-business/components/TransportDemandForm.vue
@@ -1,7 +1,9 @@
-
+
-
- 运输信息
+
@@ -39,9 +40,8 @@ defineExpose({
-
-
- 货物信息
+
+
@@ -50,9 +50,8 @@ defineExpose({
-
-
- 费用与时效
+
+
@@ -63,8 +62,8 @@ defineExpose({
-
-