优化
This commit is contained in:
@@ -66,9 +66,9 @@ describe('platform container loading API', () => {
|
|||||||
it('normalizes every long id in candidates and plans', async () => {
|
it('normalizes every long id in candidates and plans', async () => {
|
||||||
vi.mocked(http.get)
|
vi.mocked(http.get)
|
||||||
.mockResolvedValueOnce({ code: '200', data: container })
|
.mockResolvedValueOnce({ code: '200', data: container })
|
||||||
.mockResolvedValueOnce({ code: '200', data: { records: [{ accountId: 1, inboundId: 2, orderId: 4, orderNo: 'ORD-1', inboundCode: 'IN-1', orderStatusSnapshot: 'WAIT_SPLIT', expectedArrivalAt: '2026-09-10T09:30:00', warehouseId: 5, destinationWarehouseId: 6, channelCode: 'NY_EXX', channelName: '纽约EXX海铁', customerName: '示例企业', goodsSummary: '服装、鞋类', availablePackageCount: '7', unitGrossWeightKg: '12.5', unitNetWeightKg: '11.8', averageUnitVolumeCbm: '0.187', availableVolumeCbm: '1.309', coLoadGroupId: 9007199254740999n, groupNo: 'CLG-9007199254740999', memberCount: '3', groupTotalBoxes: '21', locked: false, blockReason: null, groupMembers: [] }], page: '1', size: '20', total: '1', pages: '1' } })
|
.mockResolvedValueOnce({ code: '200', data: { records: [{ accountId: 1, inboundId: 2, orderId: 4, orderNo: 'ORD-1', inboundCode: 'IN-1', orderStatusSnapshot: 'WAIT_SPLIT', expectedArrivalAt: '2026-09-10T09:30:00', warehouseId: 5, destinationWarehouseId: 6, channelCode: 'NY_EXX', channelName: '纽约EXX海铁', customerName: '示例企业', goodsSummary: '服装、鞋类', availablePackageCount: '7', unitGrossWeightKg: '12.5', unitNetWeightKg: '11.8', averageUnitVolumeCbm: '0.187', availableVolumeCbm: '1.309', estimatedVolumeCbm: '2.5', coLoadGroupId: 9007199254740999n, groupNo: 'CLG-9007199254740999', memberCount: '3', groupTotalBoxes: '21', locked: false, blockReason: null, groupMembers: [] }], page: '1', size: '20', total: '1', pages: '1' } })
|
||||||
expect((await getContainer('9')).id).toBe(String(container.id))
|
expect((await getContainer('9')).id).toBe(String(container.id))
|
||||||
expect(await listSmartLoadingCandidates({ channelGroupCodes: ['EXX', 'HEDE'], warehouseId: '5', orderStatuses: ['PENDING_REVIEW', 'WAIT_MEASURE'], page: 1, size: 20 })).toMatchObject({ records: [{ accountId: '1', customerId: '1', inboundId: '2', inboundCode: 'IN-1', orderStatusSnapshot: 'WAIT_SPLIT', expectedArrivalAt: '2026-09-10T09:30:00', destinationWarehouseId: '6', channelCode: 'NY_EXX', channelName: '纽约EXX海铁', goodsSummary: '服装、鞋类', availablePackageCount: 7, unitGrossWeightKg: 12.5, unitNetWeightKg: 11.8, averageUnitVolumeCbm: 0.187, availableVolumeCbm: 1.309, coLoadGroupId: '9007199254740999', groupNo: 'CLG-9007199254740999', memberCount: 3, groupTotalBoxes: 21, locked: false, blockReason: null }], total: 1 })
|
expect(await listSmartLoadingCandidates({ channelGroupCodes: ['EXX', 'HEDE'], warehouseId: '5', orderStatuses: ['PENDING_REVIEW', 'WAIT_MEASURE'], page: 1, size: 20 })).toMatchObject({ records: [{ accountId: '1', customerId: '1', inboundId: '2', inboundCode: 'IN-1', orderStatusSnapshot: 'WAIT_SPLIT', expectedArrivalAt: '2026-09-10T09:30:00', destinationWarehouseId: '6', channelCode: 'NY_EXX', channelName: '纽约EXX海铁', goodsSummary: '服装、鞋类', availablePackageCount: 7, unitGrossWeightKg: 12.5, unitNetWeightKg: 11.8, averageUnitVolumeCbm: 0.187, availableVolumeCbm: 1.309, estimatedVolumeCbm: 2.5, coLoadGroupId: '9007199254740999', groupNo: 'CLG-9007199254740999', memberCount: 3, groupTotalBoxes: 21, locked: false, blockReason: null }], total: 1 })
|
||||||
const candidateParams = vi.mocked(http.get).mock.calls.at(-1)?.[1]?.params as URLSearchParams
|
const candidateParams = vi.mocked(http.get).mock.calls.at(-1)?.[1]?.params as URLSearchParams
|
||||||
expect(candidateParams.getAll('orderStatuses')).toEqual(['PENDING_REVIEW', 'WAIT_MEASURE'])
|
expect(candidateParams.getAll('orderStatuses')).toEqual(['PENDING_REVIEW', 'WAIT_MEASURE'])
|
||||||
expect(candidateParams.has('orderStatus')).toBe(false)
|
expect(candidateParams.has('orderStatus')).toBe(false)
|
||||||
@@ -115,7 +115,7 @@ describe('platform container loading API', () => {
|
|||||||
page: '1', size: '200', total: '1', pages: '1',
|
page: '1', size: '200', total: '1', pages: '1',
|
||||||
} })
|
} })
|
||||||
|
|
||||||
const result = await listSmartLoadingWorkbenchContainers({ channelGroupCodes: ['MATSON_CLX', 'EXX'], customerId: '12', inboundCode: 'IN-1', createdStart: '2026-09-01', createdEnd: '2026-09-03', orderStatuses: ['WAIT_SPLIT'], page: 1, size: 200 })
|
const result = await listSmartLoadingWorkbenchContainers({ channelGroupCodes: ['MATSON_CLX', 'EXX'], customerId: '12', inboundCode: 'IN-1', createdStart: '2026-09-01', createdEnd: '2026-09-03', expectedArrivalStart: '2026-09-04', expectedArrivalEnd: '2026-09-06', orderStatuses: ['WAIT_SPLIT'], page: 1, size: 200 })
|
||||||
|
|
||||||
expect(result).toMatchObject({ records: [{ bookingId: '9007199254740993', warehouseId: '8', planId: '9007199254740994', version: 2 }], total: 1 })
|
expect(result).toMatchObject({ records: [{ bookingId: '9007199254740993', warehouseId: '8', planId: '9007199254740994', version: 2 }], total: 1 })
|
||||||
const params = vi.mocked(http.get).mock.calls.at(-1)?.[1]?.params as URLSearchParams
|
const params = vi.mocked(http.get).mock.calls.at(-1)?.[1]?.params as URLSearchParams
|
||||||
@@ -124,6 +124,8 @@ describe('platform container loading API', () => {
|
|||||||
expect(params.get('inboundCode')).toBe('IN-1')
|
expect(params.get('inboundCode')).toBe('IN-1')
|
||||||
expect(params.get('createdStart')).toBe('2026-09-01')
|
expect(params.get('createdStart')).toBe('2026-09-01')
|
||||||
expect(params.get('createdEnd')).toBe('2026-09-03')
|
expect(params.get('createdEnd')).toBe('2026-09-03')
|
||||||
|
expect(params.get('expectedArrivalStart')).toBe('2026-09-04')
|
||||||
|
expect(params.get('expectedArrivalEnd')).toBe('2026-09-06')
|
||||||
expect(params.has('orderStatus')).toBe(false)
|
expect(params.has('orderStatus')).toBe(false)
|
||||||
expect(params.has('orderStatuses')).toBe(false)
|
expect(params.has('orderStatuses')).toBe(false)
|
||||||
expect(params.has('bookingId')).toBe(false)
|
expect(params.has('bookingId')).toBe(false)
|
||||||
|
|||||||
@@ -247,6 +247,7 @@ function smartLoadingQueryParams(query: SmartLoadingCandidateQuery, includeOrder
|
|||||||
const optionalParams: Array<[string, string | number | undefined]> = [
|
const optionalParams: Array<[string, string | number | undefined]> = [
|
||||||
['warehouseId', query.warehouseId], ['customerId', query.customerId], ['inboundCode', query.inboundCode],
|
['warehouseId', query.warehouseId], ['customerId', query.customerId], ['inboundCode', query.inboundCode],
|
||||||
['createdStart', query.createdStart], ['createdEnd', query.createdEnd],
|
['createdStart', query.createdStart], ['createdEnd', query.createdEnd],
|
||||||
|
['expectedArrivalStart', query.expectedArrivalStart], ['expectedArrivalEnd', query.expectedArrivalEnd],
|
||||||
['page', query.page], ['size', query.size],
|
['page', query.page], ['size', query.size],
|
||||||
]
|
]
|
||||||
for (const [key, value] of optionalParams) if (value !== undefined && value !== '') params.append(key, String(value))
|
for (const [key, value] of optionalParams) if (value !== undefined && value !== '') params.append(key, String(value))
|
||||||
@@ -275,6 +276,7 @@ export async function listSmartLoadingCandidates(query: SmartLoadingCandidateQue
|
|||||||
unitNetWeightKg: raw.unitNetWeightKg == null ? null : numberValue(raw.unitNetWeightKg),
|
unitNetWeightKg: raw.unitNetWeightKg == null ? null : numberValue(raw.unitNetWeightKg),
|
||||||
averageUnitVolumeCbm: raw.averageUnitVolumeCbm == null ? null : numberValue(raw.averageUnitVolumeCbm),
|
averageUnitVolumeCbm: raw.averageUnitVolumeCbm == null ? null : numberValue(raw.averageUnitVolumeCbm),
|
||||||
availableVolumeCbm: raw.availableVolumeCbm == null ? null : numberValue(raw.availableVolumeCbm),
|
availableVolumeCbm: raw.availableVolumeCbm == null ? null : numberValue(raw.availableVolumeCbm),
|
||||||
|
estimatedVolumeCbm: raw.estimatedVolumeCbm == null ? null : numberValue(raw.estimatedVolumeCbm),
|
||||||
groupMembers: raw.groupMembers.map((member) => ({
|
groupMembers: raw.groupMembers.map((member) => ({
|
||||||
...member, accountId: id(member.accountId), inboundId: id(member.inboundId), orderId: id(member.orderId),
|
...member, accountId: id(member.accountId), inboundId: id(member.inboundId), orderId: id(member.orderId),
|
||||||
availablePackageCount: numberValue(member.availablePackageCount),
|
availablePackageCount: numberValue(member.availablePackageCount),
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ const candidate = {
|
|||||||
warehouseId: '8', channelCode: 'ZBYHK', channelName: '美森正班海卡包税', destinationWarehouseId: '9',
|
warehouseId: '8', channelCode: 'ZBYHK', channelName: '美森正班海卡包税', destinationWarehouseId: '9',
|
||||||
destinationWarehouseCode: 'LAX9', destinationWarehouseName: 'LAX9', customerName: '另一企业', goodsSummary: '鞋类',
|
destinationWarehouseCode: 'LAX9', destinationWarehouseName: 'LAX9', customerName: '另一企业', goodsSummary: '鞋类',
|
||||||
availablePackageCount: 12, unitGrossWeightKg: 10, unitNetWeightKg: 9, averageUnitVolumeCbm: 0.2,
|
availablePackageCount: 12, unitGrossWeightKg: 10, unitNetWeightKg: 9, averageUnitVolumeCbm: 0.2,
|
||||||
availableVolumeCbm: 2.4, coLoadGroupId: null, groupNo: null, memberCount: null, groupTotalBoxes: null,
|
availableVolumeCbm: 2.4, estimatedVolumeCbm: 3.5, coLoadGroupId: null, groupNo: null, memberCount: null, groupTotalBoxes: null,
|
||||||
locked: null, blockReason: null,
|
locked: null, blockReason: null,
|
||||||
}
|
}
|
||||||
function candidatePage(records: unknown[], page = 1, size = 20, total = records.length) {
|
function candidatePage(records: unknown[], page = 1, size = 20, total = records.length) {
|
||||||
@@ -149,6 +149,8 @@ describe('GlobalSmartLoadingView', () => {
|
|||||||
expect(wrapper.text()).not.toContain('SKU-1')
|
expect(wrapper.text()).not.toContain('SKU-1')
|
||||||
expect(wrapper.text()).toContain('IN-1')
|
expect(wrapper.text()).toContain('IN-1')
|
||||||
expect(wrapper.text()).toContain('IN-2')
|
expect(wrapper.text()).toContain('IN-2')
|
||||||
|
expect(wrapper.text()).toContain('预估体积')
|
||||||
|
expect(wrapper.text()).toContain('3.5 m³')
|
||||||
expect(wrapper.text()).not.toContain('ORD-1')
|
expect(wrapper.text()).not.toContain('ORD-1')
|
||||||
expect(wrapper.text()).not.toContain('ORD-2')
|
expect(wrapper.text()).not.toContain('ORD-2')
|
||||||
expect(wrapper.get('.candidate-pane').text()).toContain('120 kg')
|
expect(wrapper.get('.candidate-pane').text()).toContain('120 kg')
|
||||||
@@ -411,7 +413,7 @@ describe('GlobalSmartLoadingView', () => {
|
|||||||
expect(source).toContain(': candidate.availablePackageCount')
|
expect(source).toContain(': candidate.availablePackageCount')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('filters candidates by creation range and multiple order statuses', async () => {
|
it('filters candidates by creation, expected-arrival range and multiple order statuses', async () => {
|
||||||
vi.mocked(listSmartLoadingCandidates)
|
vi.mocked(listSmartLoadingCandidates)
|
||||||
.mockResolvedValueOnce(candidatePage([
|
.mockResolvedValueOnce(candidatePage([
|
||||||
{ ...candidate, inboundId: '51', inboundCode: 'IN-MATCH', orderStatusSnapshot: 'WAIT_SPLIT', expectedArrivalAt: '2026-09-11T08:00:00' },
|
{ ...candidate, inboundId: '51', inboundCode: 'IN-MATCH', orderStatusSnapshot: 'WAIT_SPLIT', expectedArrivalAt: '2026-09-11T08:00:00' },
|
||||||
@@ -425,6 +427,7 @@ describe('GlobalSmartLoadingView', () => {
|
|||||||
|
|
||||||
wrapper.getComponent(QueryToolbar).vm.$emit('search', {
|
wrapper.getComponent(QueryToolbar).vm.$emit('search', {
|
||||||
customerId: '', inboundCode: '', orderStatuses: ['WAIT_SPLIT', 'LOADING'], createdRange: ['2026-09-10', '2026-09-12'],
|
customerId: '', inboundCode: '', orderStatuses: ['WAIT_SPLIT', 'LOADING'], createdRange: ['2026-09-10', '2026-09-12'],
|
||||||
|
expectedArrivalRange: ['2026-09-11', '2026-09-15'],
|
||||||
})
|
})
|
||||||
await flushPromises()
|
await flushPromises()
|
||||||
|
|
||||||
@@ -432,7 +435,7 @@ describe('GlobalSmartLoadingView', () => {
|
|||||||
expect(candidates).toContain('IN-MATCH')
|
expect(candidates).toContain('IN-MATCH')
|
||||||
expect(candidates).not.toContain('IN-WRONG-STATUS')
|
expect(candidates).not.toContain('IN-WRONG-STATUS')
|
||||||
expect(candidates).not.toContain('IN-WRONG-DATE')
|
expect(candidates).not.toContain('IN-WRONG-DATE')
|
||||||
expect(listSmartLoadingCandidates).toHaveBeenLastCalledWith({ channelGroupCodes: ['MATSON_CLX'], createdStart: '2026-09-10', createdEnd: '2026-09-12', orderStatuses: ['WAIT_SPLIT', 'LOADING'], page: 1, size: 20 })
|
expect(listSmartLoadingCandidates).toHaveBeenLastCalledWith({ channelGroupCodes: ['MATSON_CLX'], createdStart: '2026-09-10', createdEnd: '2026-09-12', expectedArrivalStart: '2026-09-11', expectedArrivalEnd: '2026-09-15', orderStatuses: ['WAIT_SPLIT', 'LOADING'], page: 1, size: 20 })
|
||||||
expect(listSmartLoadingWorkbenchContainers).toHaveBeenCalledTimes(containerRequestCount)
|
expect(listSmartLoadingWorkbenchContainers).toHaveBeenCalledTimes(containerRequestCount)
|
||||||
expect(listSmartLoadingWorkbenchContainers).toHaveBeenLastCalledWith({ channelGroupCodes: ['MATSON_CLX'], page: 1, size: 200 })
|
expect(listSmartLoadingWorkbenchContainers).toHaveBeenLastCalledWith({ channelGroupCodes: ['MATSON_CLX'], page: 1, size: 200 })
|
||||||
})
|
})
|
||||||
@@ -608,7 +611,7 @@ describe('GlobalSmartLoadingView', () => {
|
|||||||
await flushPromises()
|
await flushPromises()
|
||||||
|
|
||||||
const fields = wrapper.findComponent(QueryToolbar).props('fields') as Array<{ key: string; options?: Array<{ label: string; value: string }>; props?: Record<string, unknown> }>
|
const fields = wrapper.findComponent(QueryToolbar).props('fields') as Array<{ key: string; options?: Array<{ label: string; value: string }>; props?: Record<string, unknown> }>
|
||||||
expect(fields.map((field) => field.key)).toEqual(['warehouseId', 'customerId', 'inboundCode', 'createdRange', 'orderStatuses'])
|
expect(fields.map((field) => field.key)).toEqual(['warehouseId', 'customerId', 'inboundCode', 'createdRange', 'expectedArrivalRange', 'orderStatuses'])
|
||||||
expect(fields.find((field) => field.key === 'warehouseId')?.options).toEqual([
|
expect(fields.find((field) => field.key === 'warehouseId')?.options).toEqual([
|
||||||
{ label: '义乌仓', value: '8' },
|
{ label: '义乌仓', value: '8' },
|
||||||
{ label: '东莞仓', value: '18' },
|
{ label: '东莞仓', value: '18' },
|
||||||
@@ -915,6 +918,7 @@ describe('GlobalSmartLoadingView', () => {
|
|||||||
expect(source).toContain('.container-pane { max-height: min(58vh, 460px); }')
|
expect(source).toContain('.container-pane { max-height: min(58vh, 460px); }')
|
||||||
expect(source).toContain('min-height: 112px')
|
expect(source).toContain('min-height: 112px')
|
||||||
expect(source).toContain("label: '创建日期'")
|
expect(source).toContain("label: '创建日期'")
|
||||||
|
expect(source).toContain("label: '预计到货时间'")
|
||||||
expect(source).toContain("label: '订单状态'")
|
expect(source).toContain("label: '订单状态'")
|
||||||
expect(source).toContain('.smart-loading-query .query-toolbar__filters) { flex-wrap: nowrap; gap: 8px; overflow-x: auto; }')
|
expect(source).toContain('.smart-loading-query .query-toolbar__filters) { flex-wrap: nowrap; gap: 8px; overflow-x: auto; }')
|
||||||
expect(source).toContain('.smart-loading-query .query-toolbar__actions) { flex-wrap: nowrap; gap: 6px; }')
|
expect(source).toContain('.smart-loading-query .query-toolbar__actions) { flex-wrap: nowrap; gap: 6px; }')
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ const selectedCandidate = ref<SmartLoadingCandidateRow | null>(null)
|
|||||||
const assignForm = reactive({ packageCount: 1 })
|
const assignForm = reactive({ packageCount: 1 })
|
||||||
const quantityDrafts = reactive<Record<string, number>>({})
|
const quantityDrafts = reactive<Record<string, number>>({})
|
||||||
const planGroupsByInboundId = ref(new Map<string, SmartLoadingPlanCoLoadGroup>())
|
const planGroupsByInboundId = ref(new Map<string, SmartLoadingPlanCoLoadGroup>())
|
||||||
const query = ref<QueryModel>({ warehouseId: '', customerId: '', inboundCode: '', createdRange: [], orderStatuses: [] })
|
const query = ref<QueryModel>({ warehouseId: '', customerId: '', inboundCode: '', createdRange: [], expectedArrivalRange: [], orderStatuses: [] })
|
||||||
const appliedQuery = ref<QueryModel>({ ...query.value, orderStatuses: [] })
|
const appliedQuery = ref<QueryModel>({ ...query.value, orderStatuses: [] })
|
||||||
const candidatePage = ref(1)
|
const candidatePage = ref(1)
|
||||||
const candidatePageSize = ref(20)
|
const candidatePageSize = ref(20)
|
||||||
@@ -199,6 +199,7 @@ const queryFields = computed<QueryField[]>(() => [
|
|||||||
{ key: 'customerId', type: 'select', label: '客户', placeholder: '全部客户', width: 180, options: customers.value.filter((customer) => customer.status === 'ACTIVE').map((customer) => ({ label: customer.tenantName, value: String(customer.id) })), props: { filterable: true, loading: customersLoading.value } },
|
{ key: 'customerId', type: 'select', label: '客户', placeholder: '全部客户', width: 180, options: customers.value.filter((customer) => customer.status === 'ACTIVE').map((customer) => ({ label: customer.tenantName, value: String(customer.id) })), props: { filterable: true, loading: customersLoading.value } },
|
||||||
{ key: 'inboundCode', type: 'input', label: '入仓码', placeholder: '请输入入仓码', width: 210 },
|
{ key: 'inboundCode', type: 'input', label: '入仓码', placeholder: '请输入入仓码', width: 210 },
|
||||||
{ key: 'createdRange', type: 'daterange', label: '创建日期', placeholder: '请选择创建日期范围', width: 260 },
|
{ key: 'createdRange', type: 'daterange', label: '创建日期', placeholder: '请选择创建日期范围', width: 260 },
|
||||||
|
{ key: 'expectedArrivalRange', type: 'daterange', label: '预计到货时间', placeholder: '请选择预计到货时间范围', width: 260 },
|
||||||
{ key: 'orderStatuses', type: 'select', label: '订单状态', placeholder: '全部订单状态', width: 210, options: candidateOrderStatusOptions, props: { multiple: true, collapseTags: true, collapseTagsTooltip: true, maxCollapseTags: 2 } },
|
{ key: 'orderStatuses', type: 'select', label: '订单状态', placeholder: '全部订单状态', width: 210, options: candidateOrderStatusOptions, props: { multiple: true, collapseTags: true, collapseTagsTooltip: true, maxCollapseTags: 2 } },
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -229,6 +230,7 @@ const candidateColumns: DataTableColumn[] = [
|
|||||||
{ key: 'totalGrossWeightKg', label: '重量', width: 90, slotName: 'candidateTotalWeight' },
|
{ key: 'totalGrossWeightKg', label: '重量', width: 90, slotName: 'candidateTotalWeight' },
|
||||||
{ key: 'averageUnitVolumeCbm', label: '单箱体积', width: 80, slotName: 'averageUnitVolume' },
|
{ key: 'averageUnitVolumeCbm', label: '单箱体积', width: 80, slotName: 'averageUnitVolume' },
|
||||||
{ key: 'totalVolumeCbm', label: '体积', width: 90, slotName: 'candidateTotalVolume' },
|
{ key: 'totalVolumeCbm', label: '体积', width: 90, slotName: 'candidateTotalVolume' },
|
||||||
|
{ key: 'estimatedVolumeCbm', label: '预估体积', width: 100, slotName: 'estimatedVolume' },
|
||||||
]
|
]
|
||||||
const itemColumns: DataTableColumn[] = [
|
const itemColumns: DataTableColumn[] = [
|
||||||
{ key: 'actions', label: '操作', width: 90, fixed: 'left', slotName: 'actions' },
|
{ key: 'actions', label: '操作', width: 90, fixed: 'left', slotName: 'actions' },
|
||||||
@@ -300,6 +302,9 @@ function candidateQueryParams(): Parameters<typeof listSmartLoadingCandidates>[0
|
|||||||
const createdRange = Array.isArray(appliedQuery.value.createdRange)
|
const createdRange = Array.isArray(appliedQuery.value.createdRange)
|
||||||
? appliedQuery.value.createdRange.map((value) => String(value || '').slice(0, 10))
|
? appliedQuery.value.createdRange.map((value) => String(value || '').slice(0, 10))
|
||||||
: []
|
: []
|
||||||
|
const expectedArrivalRange = Array.isArray(appliedQuery.value.expectedArrivalRange)
|
||||||
|
? appliedQuery.value.expectedArrivalRange.map((value) => String(value || '').slice(0, 10))
|
||||||
|
: []
|
||||||
const params: Parameters<typeof listSmartLoadingCandidates>[0] = {
|
const params: Parameters<typeof listSmartLoadingCandidates>[0] = {
|
||||||
channelGroupCodes: [...selectedChannelCodes.value],
|
channelGroupCodes: [...selectedChannelCodes.value],
|
||||||
page: candidatePage.value,
|
page: candidatePage.value,
|
||||||
@@ -318,6 +323,10 @@ function candidateQueryParams(): Parameters<typeof listSmartLoadingCandidates>[0
|
|||||||
params.createdStart = createdRange[0]
|
params.createdStart = createdRange[0]
|
||||||
params.createdEnd = createdRange[1]
|
params.createdEnd = createdRange[1]
|
||||||
}
|
}
|
||||||
|
if (expectedArrivalRange.length === 2) {
|
||||||
|
params.expectedArrivalStart = expectedArrivalRange[0]
|
||||||
|
params.expectedArrivalEnd = expectedArrivalRange[1]
|
||||||
|
}
|
||||||
if (orderStatuses.length) params.orderStatuses = orderStatuses
|
if (orderStatuses.length) params.orderStatuses = orderStatuses
|
||||||
return params
|
return params
|
||||||
}
|
}
|
||||||
@@ -711,7 +720,8 @@ onMounted(() => { void load(); void loadCustomers() })
|
|||||||
<template #unitGrossWeight="{ row }">{{ formatMeasurement(row.unitGrossWeightKg, 'kg', 1) }}</template>
|
<template #unitGrossWeight="{ row }">{{ formatMeasurement(row.unitGrossWeightKg, 'kg', 1) }}</template>
|
||||||
<template #candidateTotalWeight="{ row }">{{ formatMeasurement(row.totalGrossWeightKg, 'kg', 1) }}</template>
|
<template #candidateTotalWeight="{ row }">{{ formatMeasurement(row.totalGrossWeightKg, 'kg', 1) }}</template>
|
||||||
<template #averageUnitVolume="{ row }">{{ formatMeasurement(row.averageUnitVolumeCbm, 'm³') }}</template>
|
<template #averageUnitVolume="{ row }">{{ formatMeasurement(row.averageUnitVolumeCbm, 'm³') }}</template>
|
||||||
<template #candidateTotalVolume="{ row }">{{ formatMeasurement(row.totalVolumeCbm, 'm³') }}</template>
|
<template #candidateTotalVolume="{ row }">{{ formatMeasurement(row.totalVolumeCbm, 'm³') }}</template>
|
||||||
|
<template #estimatedVolume="{ row }">{{ row.estimatedVolumeCbm == null ? '—' : `${formatNumber(Number(row.estimatedVolumeCbm))} m³` }}</template>
|
||||||
<template #cartonIdentityStatus><el-tag size="small" type="info" effect="plain">未核验</el-tag></template>
|
<template #cartonIdentityStatus><el-tag size="small" type="info" effect="plain">未核验</el-tag></template>
|
||||||
</DataTable>
|
</DataTable>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -251,6 +251,7 @@ export interface SmartLoadingCandidate {
|
|||||||
unitNetWeightKg: number | null
|
unitNetWeightKg: number | null
|
||||||
averageUnitVolumeCbm: number | null
|
averageUnitVolumeCbm: number | null
|
||||||
availableVolumeCbm: number | null
|
availableVolumeCbm: number | null
|
||||||
|
estimatedVolumeCbm: number | null
|
||||||
coLoadGroupId: string | null
|
coLoadGroupId: string | null
|
||||||
groupNo: string | null
|
groupNo: string | null
|
||||||
memberCount: number | null
|
memberCount: number | null
|
||||||
@@ -279,6 +280,8 @@ export interface SmartLoadingCandidateQuery {
|
|||||||
inboundCode?: string
|
inboundCode?: string
|
||||||
createdStart?: string
|
createdStart?: string
|
||||||
createdEnd?: string
|
createdEnd?: string
|
||||||
|
expectedArrivalStart?: string
|
||||||
|
expectedArrivalEnd?: string
|
||||||
orderStatuses?: Array<'PENDING_REVIEW' | 'WAIT_MEASURE' | 'WAIT_SPLIT' | 'LOADING'>
|
orderStatuses?: Array<'PENDING_REVIEW' | 'WAIT_MEASURE' | 'WAIT_SPLIT' | 'LOADING'>
|
||||||
page: number
|
page: number
|
||||||
size: number
|
size: number
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { listPlatformUnifiedOrders, updatePlatformUnifiedOrderPlanning } from '@
|
|||||||
import { createPlatformExportTask } from '@/modules/downloads'
|
import { createPlatformExportTask } from '@/modules/downloads'
|
||||||
import { showExportTaskCreatedDialog } from '@/shared/components/exportTaskCreatedDialog'
|
import { showExportTaskCreatedDialog } from '@/shared/components/exportTaskCreatedDialog'
|
||||||
import { ApiResponseError } from '@/shared/api/http'
|
import { ApiResponseError } from '@/shared/api/http'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
import UnifiedOrdersView from './UnifiedOrdersView.vue'
|
import UnifiedOrdersView from './UnifiedOrdersView.vue'
|
||||||
|
|
||||||
vi.mock('vue-router', () => ({
|
vi.mock('vue-router', () => ({
|
||||||
@@ -192,7 +193,8 @@ describe('UnifiedOrdersView list request coordination', () => {
|
|||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('edits arrival and estimated volume with the row version and preserves evidence on failure', async () => {
|
it('edits arrival and estimated volume and reports compact failure evidence through a message', async () => {
|
||||||
|
const errorMessage = vi.spyOn(ElMessage, 'error').mockImplementation(() => undefined as never)
|
||||||
vi.mocked(listPlatformUnifiedOrders).mockResolvedValue({
|
vi.mocked(listPlatformUnifiedOrders).mockResolvedValue({
|
||||||
records: [{
|
records: [{
|
||||||
orderId: '2089223263733518337', orderVersion: 7, tenantId: '2089176869176389634',
|
orderId: '2089223263733518337', orderVersion: 7, tenantId: '2089176869176389634',
|
||||||
@@ -225,7 +227,11 @@ describe('UnifiedOrdersView list request coordination', () => {
|
|||||||
expectedVersion: 8, expectedArrivalAt: '2026-09-12T16:00:00', estimatedVolumeCbm: 0.5,
|
expectedVersion: 8, expectedArrivalAt: '2026-09-12T16:00:00', estimatedVolumeCbm: 0.5,
|
||||||
})
|
})
|
||||||
expect(wrapper.getComponent({ name: 'ElDatePicker' }).props('modelValue')).toBe('2026-09-12T16:00:00')
|
expect(wrapper.getComponent({ name: 'ElDatePicker' }).props('modelValue')).toBe('2026-09-12T16:00:00')
|
||||||
expect(wrapper.text()).toContain('订单版本已变化')
|
expect(wrapper.text()).not.toContain('订单版本已变化')
|
||||||
expect(wrapper.text()).toContain('A0409 req-planning trace-planning')
|
expect(wrapper.find('.planning-error').exists()).toBe(false)
|
||||||
|
expect(errorMessage).toHaveBeenCalledWith(expect.objectContaining({
|
||||||
|
message: '订单版本已变化(错误码 A0409;Request ID req-planning;Trace ID trace-planning)',
|
||||||
|
showClose: true,
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -138,7 +138,9 @@ describe('UnifiedOrdersView contract', () => {
|
|||||||
expect(source).toContain("can('platform:order:declaration:edit')")
|
expect(source).toContain("can('platform:order:declaration:edit')")
|
||||||
expect(source).toContain('updatePlatformUnifiedOrderPlanning(String(row.tenantId), String(row.orderId)')
|
expect(source).toContain('updatePlatformUnifiedOrderPlanning(String(row.tenantId), String(row.orderId)')
|
||||||
expect(source).toContain('expectedVersion: row.orderVersion!')
|
expect(source).toContain('expectedVersion: row.orderVersion!')
|
||||||
expect(source).toContain('<ApiErrorMeta :details="planningDraft(row as UnifiedOrderResource).error!" />')
|
expect(source).toContain('ElMessage.error({')
|
||||||
|
expect(source).toContain('Request ID ${details.requestId}')
|
||||||
|
expect(source).not.toContain('class="planning-error"')
|
||||||
expect(columnSource).toContain("key: 'effectiveSailingAt', prop: 'effectiveSailingAt', label: '开船时间', minWidth: 180, slotName: 'field' }")
|
expect(columnSource).toContain("key: 'effectiveSailingAt', prop: 'effectiveSailingAt', label: '开船时间', minWidth: 180, slotName: 'field' }")
|
||||||
expect(columnSource).toContain("key: 'effectivePortArrivalAt', prop: 'effectivePortArrivalAt', label: '到港时间', minWidth: 180, slotName: 'field' }")
|
expect(columnSource).toContain("key: 'effectivePortArrivalAt', prop: 'effectivePortArrivalAt', label: '到港时间', minWidth: 180, slotName: 'field' }")
|
||||||
expect(source).toContain('preference-key="unified-orders-table-v2"')
|
expect(source).toContain('preference-key="unified-orders-table-v2"')
|
||||||
@@ -429,7 +431,7 @@ describe('UnifiedOrdersView contract', () => {
|
|||||||
|
|
||||||
it('clears an invalidated measurement loading state before refreshing order details', () => {
|
it('clears an invalidated measurement loading state before refreshing order details', () => {
|
||||||
const detailLoaderSource = source.slice(source.indexOf('async function loadDetail(force = false)'), source.indexOf('watch([page, pageSize]'))
|
const detailLoaderSource = source.slice(source.indexOf('async function loadDetail(force = false)'), source.indexOf('watch([page, pageSize]'))
|
||||||
expect(detailLoaderSource).toContain('measurementRequestSerial += 1\n measurementLoading.value = false')
|
expect(detailLoaderSource).toMatch(/measurementRequestSerial \+= 1\r?\n\s+measurementLoading\.value = false/)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('restores the saved outer-carton rule and server-calculated dimensions on re-entry', () => {
|
it('restores the saved outer-carton rule and server-calculated dimensions on re-entry', () => {
|
||||||
@@ -538,12 +540,11 @@ describe('UnifiedOrdersView contract', () => {
|
|||||||
expect(feeSection).not.toContain('String(detail.summary.inboundId)')
|
expect(feeSection).not.toContain('String(detail.summary.inboundId)')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('mounts downstream progress inside the existing order detail without opening unsafe writes', () => {
|
it('keeps downstream work out of each order detail after the order is linked to a container', () => {
|
||||||
expect(source).toContain('UnifiedOrderWorkflowPanel')
|
expect(source).not.toContain('UnifiedOrderWorkflowPanel')
|
||||||
expect(source).toContain("{ key: 'workflow', label: '后半程作业', icon: OrderFulfillmentIcon }")
|
expect(source).not.toContain("key: 'workflow'")
|
||||||
expect(source).toContain(':order-id="String(detail.summary.orderId)"')
|
expect(source).not.toContain('后半程作业')
|
||||||
expect(source).not.toContain(':show-delivery=')
|
expect(source).not.toContain("activeDetailTab === 'workflow'")
|
||||||
expect(source).toContain("detail.value?.summary.inboundId")
|
|
||||||
expect(routeSource).not.toContain('unified-order-workflow')
|
expect(routeSource).not.toContain('unified-order-workflow')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ import {
|
|||||||
firstLegTradeTermLabel,
|
firstLegTradeTermLabel,
|
||||||
firstLegTransportModeLabel,
|
firstLegTransportModeLabel,
|
||||||
} from '@/shared/utils/firstLegBusinessLabels'
|
} from '@/shared/utils/firstLegBusinessLabels'
|
||||||
import { UnifiedOrderWorkflowPanel } from '@/modules/unified-orders/workflows'
|
|
||||||
import { SmartLoadingDialog } from '@/modules/container-loading'
|
import { SmartLoadingDialog } from '@/modules/container-loading'
|
||||||
import {
|
import {
|
||||||
unifiedOrderHistoryActionLabel,
|
unifiedOrderHistoryActionLabel,
|
||||||
@@ -117,7 +116,6 @@ type PlanningDraft = {
|
|||||||
savedExpectedArrivalAt: string
|
savedExpectedArrivalAt: string
|
||||||
savedEstimatedVolumeCbm: number | null
|
savedEstimatedVolumeCbm: number | null
|
||||||
saving: boolean
|
saving: boolean
|
||||||
error: ApiErrorDetails | null
|
|
||||||
}
|
}
|
||||||
const planningDrafts = reactive<Record<string, PlanningDraft | undefined>>({})
|
const planningDrafts = reactive<Record<string, PlanningDraft | undefined>>({})
|
||||||
const customerLoading = ref(false)
|
const customerLoading = ref(false)
|
||||||
@@ -255,10 +253,6 @@ const detailTabs = [
|
|||||||
{ key: 'fulfillment', label: '拆分履约', icon: OrderFulfillmentIcon },
|
{ key: 'fulfillment', label: '拆分履约', icon: OrderFulfillmentIcon },
|
||||||
]
|
]
|
||||||
|
|
||||||
const detailTabOptions = computed(() => detail.value?.summary.inboundId
|
|
||||||
? [...detailTabs, { key: 'workflow', label: '后半程作业', icon: OrderFulfillmentIcon }]
|
|
||||||
: detailTabs)
|
|
||||||
|
|
||||||
const customerMeasurementColumns = [
|
const customerMeasurementColumns = [
|
||||||
{ key: 'itemNo', label: '#' }, { key: 'lengthCm', label: '箱规长(cm)' }, { key: 'widthCm', label: '箱规宽(cm)' },
|
{ key: 'itemNo', label: '#' }, { key: 'lengthCm', label: '箱规长(cm)' }, { key: 'widthCm', label: '箱规宽(cm)' },
|
||||||
{ key: 'heightCm', label: '箱规高(cm)' }, { key: 'packageCount', label: '箱数' }, { key: 'unitWeightKg', label: '每箱毛重' },
|
{ key: 'heightCm', label: '箱规高(cm)' }, { key: 'packageCount', label: '箱数' }, { key: 'unitWeightKg', label: '每箱毛重' },
|
||||||
@@ -634,7 +628,6 @@ function planningDraft(row: UnifiedOrderResource) {
|
|||||||
savedExpectedArrivalAt: row.expectedArrivalAt || '',
|
savedExpectedArrivalAt: row.expectedArrivalAt || '',
|
||||||
savedEstimatedVolumeCbm: row.estimatedVolumeCbm ?? null,
|
savedEstimatedVolumeCbm: row.estimatedVolumeCbm ?? null,
|
||||||
saving: false,
|
saving: false,
|
||||||
error: null,
|
|
||||||
}
|
}
|
||||||
planningDrafts[key] = draft
|
planningDrafts[key] = draft
|
||||||
}
|
}
|
||||||
@@ -647,18 +640,17 @@ async function savePlanning(row: UnifiedOrderResource) {
|
|||||||
const estimatedVolumeCbm = draft.estimatedVolumeCbm ?? null
|
const estimatedVolumeCbm = draft.estimatedVolumeCbm ?? null
|
||||||
draft.estimatedVolumeCbm = estimatedVolumeCbm
|
draft.estimatedVolumeCbm = estimatedVolumeCbm
|
||||||
if (!Number.isInteger(row.orderVersion)) {
|
if (!Number.isInteger(row.orderVersion)) {
|
||||||
draft.error = { message: '订单版本缺失,请刷新列表后重试' }
|
ElMessage.error('订单版本缺失,请刷新列表后重试')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (estimatedVolumeCbm !== null && (!Number.isFinite(estimatedVolumeCbm) || estimatedVolumeCbm <= 0)) {
|
if (estimatedVolumeCbm !== null && (!Number.isFinite(estimatedVolumeCbm) || estimatedVolumeCbm <= 0)) {
|
||||||
draft.error = { message: '预估体积必须大于 0,或清空该值' }
|
ElMessage.warning('预估体积必须大于 0,或清空该值')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (draft.expectedArrivalAt === draft.savedExpectedArrivalAt
|
if (draft.expectedArrivalAt === draft.savedExpectedArrivalAt
|
||||||
&& estimatedVolumeCbm === draft.savedEstimatedVolumeCbm) return
|
&& estimatedVolumeCbm === draft.savedEstimatedVolumeCbm) return
|
||||||
|
|
||||||
draft.saving = true
|
draft.saving = true
|
||||||
draft.error = null
|
|
||||||
try {
|
try {
|
||||||
const result = await updatePlatformUnifiedOrderPlanning(String(row.tenantId), String(row.orderId), {
|
const result = await updatePlatformUnifiedOrderPlanning(String(row.tenantId), String(row.orderId), {
|
||||||
expectedVersion: row.orderVersion!,
|
expectedVersion: row.orderVersion!,
|
||||||
@@ -672,7 +664,17 @@ async function savePlanning(row: UnifiedOrderResource) {
|
|||||||
draft.savedEstimatedVolumeCbm = estimatedVolumeCbm
|
draft.savedEstimatedVolumeCbm = estimatedVolumeCbm
|
||||||
ElMessage.success('订单运营预估已更新')
|
ElMessage.success('订单运营预估已更新')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
draft.error = getApiErrorDetails(error, '订单运营预估保存失败')
|
const details = getApiErrorDetails(error, '订单运营预估保存失败')
|
||||||
|
const evidence = [
|
||||||
|
details.code ? `错误码 ${details.code}` : '',
|
||||||
|
details.requestId ? `Request ID ${details.requestId}` : '',
|
||||||
|
details.traceId ? `Trace ID ${details.traceId}` : '',
|
||||||
|
].filter(Boolean).join(';')
|
||||||
|
ElMessage.error({
|
||||||
|
message: evidence ? `${details.message}(${evidence})` : details.message,
|
||||||
|
duration: 6_000,
|
||||||
|
showClose: true,
|
||||||
|
})
|
||||||
} finally {
|
} finally {
|
||||||
draft.saving = false
|
draft.saving = false
|
||||||
}
|
}
|
||||||
@@ -1938,7 +1940,7 @@ onBeforeUnmount(() => {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="detail-tabs" role="tablist" aria-label="订单详情模块">
|
<div class="detail-tabs" role="tablist" aria-label="订单详情模块">
|
||||||
<button v-for="tab in detailTabOptions" :id="`order-detail-tab-${tab.key}`" :key="tab.key" type="button" role="tab" :class="{ active: activeDetailTab === tab.key }" :aria-selected="activeDetailTab === tab.key" :aria-controls="`order-detail-panel-${tab.key}`" :tabindex="activeDetailTab === tab.key ? 0 : -1" @click="selectDetailTab(tab.key)"><component :is="tab.icon" :size="17" /><span>{{ tab.label }}</span></button>
|
<button v-for="tab in detailTabs" :id="`order-detail-tab-${tab.key}`" :key="tab.key" type="button" role="tab" :class="{ active: activeDetailTab === tab.key }" :aria-selected="activeDetailTab === tab.key" :aria-controls="`order-detail-panel-${tab.key}`" :tabindex="activeDetailTab === tab.key ? 0 : -1" @click="selectDetailTab(tab.key)"><component :is="tab.icon" :size="17" /><span>{{ tab.label }}</span></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section :id="`order-detail-panel-${activeDetailTab}`" class="detail-panel" role="tabpanel" :aria-labelledby="`order-detail-tab-${activeDetailTab}`" tabindex="0">
|
<section :id="`order-detail-panel-${activeDetailTab}`" class="detail-panel" role="tabpanel" :aria-labelledby="`order-detail-tab-${activeDetailTab}`" tabindex="0">
|
||||||
@@ -2089,18 +2091,6 @@ onBeforeUnmount(() => {
|
|||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="activeDetailTab === 'workflow'">
|
|
||||||
<UnifiedOrderWorkflowPanel
|
|
||||||
:tenant-id="String(detail.summary.tenantId)"
|
|
||||||
:inbound-id="String(detail.summary.inboundId)"
|
|
||||||
:inbound-code="detail.summary.inboundCode"
|
|
||||||
:order-id="String(detail.summary.orderId)"
|
|
||||||
:main-status="detail.summary.mainStatus"
|
|
||||||
:inbound-version="detail.summary.inboundVersion"
|
|
||||||
:picking-version="detail.summary.loading?.pickingVersion"
|
|
||||||
@updated="loadDetail(true)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="activeDetailTab === 'measurement'">
|
<template v-else-if="activeDetailTab === 'measurement'">
|
||||||
<div class="panel-title">
|
<div class="panel-title">
|
||||||
<div><h2>测量数据</h2><p>{{ detail.summary.measurement?.completedAt ? `完成于 ${formatDate(detail.summary.measurement.completedAt)}` : '尚未完成测量' }}</p></div>
|
<div><h2>测量数据</h2><p>{{ detail.summary.measurement?.completedAt ? `完成于 ${formatDate(detail.summary.measurement.completedAt)}` : '尚未完成测量' }}</p></div>
|
||||||
@@ -2319,10 +2309,6 @@ onBeforeUnmount(() => {
|
|||||||
/>
|
/>
|
||||||
<span v-else>{{ formatNumber((row as UnifiedOrderResource).estimatedVolumeCbm, 4) }}</span>
|
<span v-else>{{ formatNumber((row as UnifiedOrderResource).estimatedVolumeCbm, 4) }}</span>
|
||||||
<small v-if="planningDraft(row as UnifiedOrderResource).saving">保存中…</small>
|
<small v-if="planningDraft(row as UnifiedOrderResource).saving">保存中…</small>
|
||||||
<div v-if="planningDraft(row as UnifiedOrderResource).error" class="planning-error" role="alert">
|
|
||||||
<span>{{ planningDraft(row as UnifiedOrderResource).error?.message }}</span>
|
|
||||||
<ApiErrorMeta :details="planningDraft(row as UnifiedOrderResource).error!" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #expectedArrival="{ row }">
|
<template #expectedArrival="{ row }">
|
||||||
@@ -2343,10 +2329,6 @@ onBeforeUnmount(() => {
|
|||||||
/>
|
/>
|
||||||
<span v-else>{{ formatDate((row as UnifiedOrderResource).expectedArrivalAt) }}</span>
|
<span v-else>{{ formatDate((row as UnifiedOrderResource).expectedArrivalAt) }}</span>
|
||||||
<small v-if="planningDraft(row as UnifiedOrderResource).saving">保存中…</small>
|
<small v-if="planningDraft(row as UnifiedOrderResource).saving">保存中…</small>
|
||||||
<div v-if="planningDraft(row as UnifiedOrderResource).error" class="planning-error" role="alert">
|
|
||||||
<span>{{ planningDraft(row as UnifiedOrderResource).error?.message }}</span>
|
|
||||||
<ApiErrorMeta :details="planningDraft(row as UnifiedOrderResource).error!" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #field="{ row, column }"><LineClampText v-if="column.property === 'customerName'" :content="displayField(row as UnifiedOrderResource, column.property)" /><LineClampText v-else-if="['customerRemark', 'latestInternalNote'].includes(String(column.property))" :content="displayField(row as UnifiedOrderResource, column.property)" :lines="2" /><template v-else>{{ displayField(row as UnifiedOrderResource, column.property) }}</template></template>
|
<template #field="{ row, column }"><LineClampText v-if="column.property === 'customerName'" :content="displayField(row as UnifiedOrderResource, column.property)" /><LineClampText v-else-if="['customerRemark', 'latestInternalNote'].includes(String(column.property))" :content="displayField(row as UnifiedOrderResource, column.property)" :lines="2" /><template v-else>{{ displayField(row as UnifiedOrderResource, column.property) }}</template></template>
|
||||||
@@ -2497,8 +2479,6 @@ onBeforeUnmount(() => {
|
|||||||
.planning-volume-input,.planning-arrival-input { width: 100%; max-width: 100%; }
|
.planning-volume-input,.planning-arrival-input { width: 100%; max-width: 100%; }
|
||||||
.planning-cell :deep(.el-input__wrapper) { min-height: 32px; padding-right: 9px; padding-left: 9px; }
|
.planning-cell :deep(.el-input__wrapper) { min-height: 32px; padding-right: 9px; padding-left: 9px; }
|
||||||
.planning-cell :deep(.el-input__inner) { min-width: 0; text-align: left; }
|
.planning-cell :deep(.el-input__inner) { min-width: 0; text-align: left; }
|
||||||
.planning-error { min-width: 0; color: var(--el-color-danger); font-size: 11px; line-height: 1.35; white-space: normal; }
|
|
||||||
.planning-error :deep(.api-error-meta) { margin-top: 3px; }
|
|
||||||
.inbound-relation-cell { display: grid; min-width: 0; gap: 5px; }
|
.inbound-relation-cell { display: grid; min-width: 0; gap: 5px; }
|
||||||
.inbound-code-value { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
.inbound-code-value { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||||
.order-relation-link { width: fit-content; max-width: 100%; height: auto; justify-content: flex-start; padding: 0; font-size: 12px; }
|
.order-relation-link { width: fit-content; max-width: 100%; height: auto; justify-content: flex-start; padding: 0; font-size: 12px; }
|
||||||
|
|||||||
Reference in New Issue
Block a user