From 6df6f6dabc4f48913eed43b2fff893fbc4e718c8 Mon Sep 17 00:00:00 2001
From: ouyangxq <775153912@qq.com>
Date: Sat, 3 Oct 2026 20:37:03 +0800
Subject: [PATCH] fix(fleet): refresh negotiated price controls when reopening
booking
---
.../components/TripBookingPanel.test.ts | 24 ++++++++++++++++---
.../components/TripBookingPanel.vue | 2 +-
2 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/src/modules/overseas-master-data/components/TripBookingPanel.test.ts b/src/modules/overseas-master-data/components/TripBookingPanel.test.ts
index 521ad9f4..e96efd5f 100644
--- a/src/modules/overseas-master-data/components/TripBookingPanel.test.ts
+++ b/src/modules/overseas-master-data/components/TripBookingPanel.test.ts
@@ -4,6 +4,7 @@ import TripBookingPanel from './TripBookingPanel.vue'
import * as api from '../api/tripBookings'
import type { FleetTrip } from '../tripTypes'
import type { TripBooking } from '../bookingTypes'
+import type { Component } from 'vue'
const access = vi.hoisted(() => ({ writable: true, quote: true }))
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: (permission: string) => permission === 'platform:fleet:quote:list' ? access.quote : access.writable }) }))
vi.mock('element-plus', () => ({ ElMessage: { success: vi.fn(), warning: vi.fn() }, ElMessageBox: { confirm: vi.fn().mockResolvedValue(undefined) } }))
@@ -12,14 +13,14 @@ const row: TripBooking = { bookingNo: 'FB-1', tripNo: 'TR-1', customerId: '9', c
cargo: { destinationKey: 'FBA:ONT8', cargoName: null, packageCount: 10, palletSpaces: 2, weightKg: 100, volumeCbm: 1, priceBasis: 'PALLET', unitPrice: 50, currency: 'USD', contactName: null, contactPhone: null, remark: null } }
const trip = { tripNo: 'TR-1', status: 'PLANNED', recordVersion: 4, stops: [{ name: '起点' }, { name: 'ONT8', destinationKey: 'FBA:ONT8' }] } as FleetTrip
const wrappers: VueWrapper[] = []
-function mount() {
+function mount(realNumber?: Component, realInput?: Component) {
const field = { props: ['modelValue'], emits: ['update:modelValue'], template: '' }
const wrapper = shallowMount(TripBookingPanel, { props: { trip }, global: { stubs: {
DataTable: { props: ['data'], template: '
' },
- AppDialog: { name: 'AppDialog', props: ['modelValue', 'showConfirm'], emits: ['confirm', 'update:modelValue'], template: '
' },
+ AppDialog: { name: 'AppDialog', props: { modelValue: Boolean, showConfirm: Boolean, destroyOnClose: Boolean }, emits: ['confirm', 'update:modelValue'], template: realNumber ? '
' : '
' },
ElButton: { props: ['disabled'], template: '' },
ElForm: { template: '
' }, ElFormItem: { template: '
' },
- ElSelect: { ...field, name: 'ElSelect' }, ElInputNumber: { ...field, name: 'ElInputNumber' }, ElInput: field, ElOption: true,
+ ElSelect: { ...field, name: 'ElSelect' }, ElInputNumber: realNumber || { ...field, name: 'ElInputNumber' }, ElInput: realInput || field, ElOption: true,
LoadErrorState: true, ApiErrorMeta: true,
} } }); wrappers.push(wrapper); return wrapper
}
@@ -33,6 +34,23 @@ it('confirms using both current versions and updates the parent version without
expect(wrapper.emitted('changed')?.[0]).toEqual([5]); expect(api.listTripBookings).toHaveBeenCalledOnce()
expect(wrapper.findAll('button').some(node => node.text() === '确认承运')).toBe(false)
})
+it('reopens saved negotiated price in a fresh numeric control while retaining its separate quote source', async () => {
+ const { ElInputNumber, ElInput } = await vi.importActual('element-plus')
+ const initial = { ...row, cargo: { ...row.cargo, unitPrice: 16 }, quoteSource: { ...source, quotedUnitPrice: 16 } }
+ const saved = { ...initial, cargo: { ...initial.cargo, unitPrice: 9 }, agreedAmount: 18, recordVersion: 1 }
+ vi.mocked(api.listTripBookings).mockResolvedValue({ tripRecordVersion: 4, records: [initial] })
+ vi.mocked(api.updateTripBooking).mockResolvedValue({ tripRecordVersion: 5, booking: saved, replayed: false })
+ const wrapper = mount(ElInputNumber, ElInput); await flushPromises()
+ await button(wrapper, '编辑').trigger('click'); await flushPromises()
+ const price = wrapper.findAllComponents({ name: 'ElInputNumber' })[4]!
+ await price.find('input').setValue('9'); await flushPromises()
+ wrapper.findComponent({ name: 'AppDialog' }).vm.$emit('confirm'); await flushPromises()
+ expect(wrapper.findAllComponents({ name: 'ElInputNumber' })).toHaveLength(0)
+ await button(wrapper, '详情').trigger('click'); await flushPromises()
+ expect(wrapper.findAllComponents({ name: 'ElInputNumber' })[4]!.find('input').element.value).toBe('9.00')
+ expect(wrapper.text()).toContain('来源单价:16.00 USD')
+ expect(wrapper.text()).toContain('约定运费:18.00 USD')
+})
it('keeps inquiry estimates and contacts optional and retries the same uncertain create command', async () => {
vi.mocked(api.createTripBooking).mockRejectedValueOnce(new Error('network')).mockResolvedValueOnce({ tripRecordVersion: 5, booking: row, replayed: true })
const wrapper = mount(); await flushPromises(); await button(wrapper, '登记外接询价').trigger('click'); await flushPromises()
diff --git a/src/modules/overseas-master-data/components/TripBookingPanel.vue b/src/modules/overseas-master-data/components/TripBookingPanel.vue
index cd9a48b4..bc17e4e5 100644
--- a/src/modules/overseas-master-data/components/TripBookingPanel.vue
+++ b/src/modules/overseas-master-data/components/TripBookingPanel.vue
@@ -151,7 +151,7 @@ onBeforeUnmount(() => { generation++; searchSequence++; quoteSequence++; clearTi
{{ row.incomingNo || '尚未登记来货' }}
{{ row.dispatchNo || '尚未关联排车' }}
{{ row.agreedAmount == null ? '待报价' : `${row.agreedAmount.toFixed(2)} ${row.cargo.currency || ''}` }}
-
+