1
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
batchApprovePlatformUnifiedOrders,
|
||||
addPlatformUnifiedOrderNote,
|
||||
getPlatformUnifiedOrder,
|
||||
downloadPlatformProductImage,
|
||||
listPlatformUnifiedOrders,
|
||||
listPlatformUnifiedOrderFeeDetails,
|
||||
} from './unifiedOrders'
|
||||
@@ -90,6 +91,14 @@ describe('unified orders API contract', () => {
|
||||
expect(http.get).toHaveBeenCalledWith('/platform/v1/orders/90001', { params: { tenantId: '208' } })
|
||||
})
|
||||
|
||||
it('downloads a tenant-scoped product image for platform order details', async () => {
|
||||
const image = new Blob(['image'], { type: 'image/png' })
|
||||
vi.mocked(http.get).mockResolvedValue(image)
|
||||
|
||||
await expect(downloadPlatformProductImage('208/1', '90001')).resolves.toBe(image)
|
||||
expect(http.get).toHaveBeenCalledWith('/platform/v1/files/product-images/208%2F1/90001', { responseType: 'blob' })
|
||||
})
|
||||
|
||||
it('uses the explicit first-leg approval boundary for pending review', async () => {
|
||||
vi.mocked(http.post).mockResolvedValue({ data: null })
|
||||
|
||||
|
||||
@@ -395,6 +395,13 @@ export async function getPlatformUnifiedOrder(tenantId: string, orderId: string)
|
||||
return { ...result, summary: normalizeRow(result.summary) }
|
||||
}
|
||||
|
||||
export function downloadPlatformProductImage(tenantId: string, fileId: string) {
|
||||
return http.get<Blob, Blob>(
|
||||
`/platform/v1/files/product-images/${encodeURIComponent(tenantId)}/${encodeURIComponent(fileId)}`,
|
||||
{ responseType: 'blob' },
|
||||
)
|
||||
}
|
||||
|
||||
export function approvePlatformUnifiedOrder(tenantId: string, orderId: string) {
|
||||
return http.post<ApiEnvelope<void>, ApiEnvelope<void>>(
|
||||
`/platform/v1/orders/first-leg/${orderId}/approve`,
|
||||
|
||||
@@ -114,4 +114,20 @@ describe('UnifiedOrdersView list request coordination', () => {
|
||||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(4)
|
||||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ page: 1, size: 50 }))
|
||||
})
|
||||
|
||||
it('does not turn a cleared full-container filter into false', async () => {
|
||||
const wrapper = mountView()
|
||||
await flushPromises()
|
||||
const toolbar = wrapper.getComponent({ name: 'QueryToolbar' })
|
||||
const selected = { ...toolbar.props('modelValue'), fullContainer: 'true' }
|
||||
toolbar.vm.$emit('update:modelValue', selected)
|
||||
toolbar.vm.$emit('search')
|
||||
await flushPromises()
|
||||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ fullContainer: true }))
|
||||
|
||||
toolbar.vm.$emit('update:modelValue', { ...selected, fullContainer: undefined })
|
||||
toolbar.vm.$emit('search')
|
||||
await flushPromises()
|
||||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ fullContainer: undefined }))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -5,6 +5,7 @@ import { ArrowLeft, Box, ChevronDown, ChevronUp, CircleCheck, Eye, GitBranch, Hi
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import {
|
||||
getPlatformUnifiedOrder,
|
||||
downloadPlatformProductImage,
|
||||
approvePlatformUnifiedOrder,
|
||||
batchApprovePlatformUnifiedOrders,
|
||||
addPlatformUnifiedOrderNote,
|
||||
@@ -137,6 +138,7 @@ const measurementPreviewError = ref<ApiErrorDetails | null>(null)
|
||||
const measurementPreviewUrl = ref('')
|
||||
const measurementPreviewTitle = ref('测量图片')
|
||||
const measurementCollapsed = reactive({ customer: false, outer: false, actual: false })
|
||||
const cargoImagePreviewUrls = new Set<string>()
|
||||
const measurementDialogOpen = ref(false)
|
||||
const smartLoadingOpen = ref(false)
|
||||
const measurementOrder = ref<UnifiedOrderResource | null>(null)
|
||||
@@ -296,8 +298,10 @@ function trimmed(value: string) {
|
||||
return value.trim() || undefined
|
||||
}
|
||||
|
||||
function optionalBoolean(value: string) {
|
||||
return value === '' ? undefined : value === 'true'
|
||||
function optionalBoolean(value: string | null | undefined) {
|
||||
if (value === 'true') return true
|
||||
if (value === 'false') return false
|
||||
return undefined
|
||||
}
|
||||
|
||||
function selectStatus(status: UnifiedOrderMainStatus | '') {
|
||||
@@ -449,6 +453,29 @@ function cargoImage(cargo: Record<string, unknown>) {
|
||||
return typeof value === 'string' && value ? value : ''
|
||||
}
|
||||
|
||||
function releaseCargoImagePreviews() {
|
||||
cargoImagePreviewUrls.forEach((url) => URL.revokeObjectURL(url))
|
||||
cargoImagePreviewUrls.clear()
|
||||
}
|
||||
|
||||
async function loadCargoImagePreviews(resource: UnifiedOrderDetailResource, serial: number) {
|
||||
const tenantId = String(resource.summary.tenantId || '')
|
||||
if (!tenantId) return
|
||||
await Promise.all((resource.order?.cargoes ?? []).map(async (cargo) => {
|
||||
const fileId = cargo.productImageFileId
|
||||
if (fileId === null || fileId === undefined || fileId === '') return
|
||||
try {
|
||||
const blob = await downloadPlatformProductImage(tenantId, String(fileId))
|
||||
if (serial !== detailRequestSerial || detailRouteKey.value !== `${tenantId}:${orderId.value}`) return
|
||||
const url = URL.createObjectURL(blob)
|
||||
cargo.imageUrl = url
|
||||
cargoImagePreviewUrls.add(url)
|
||||
} catch {
|
||||
// Historical files may have been removed; keep the remaining cargo fields visible.
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
function feeReviewLabel(value: string | null | undefined) {
|
||||
return unifiedOrderReviewStatusLabel(value)
|
||||
}
|
||||
@@ -823,6 +850,7 @@ function runMoreAction(command: string | number | object, row: UnifiedOrderResou
|
||||
}
|
||||
|
||||
function closeDetail() {
|
||||
releaseCargoImagePreviews()
|
||||
detail.value = null
|
||||
detailError.value = null
|
||||
void router.push({ name: 'unified-orders' })
|
||||
@@ -845,12 +873,14 @@ async function loadDetail(force = false) {
|
||||
measurementLoadedKey.value = ''
|
||||
measurementPreviewOpen.value = false
|
||||
releaseMeasurementPreview()
|
||||
releaseCargoImagePreviews()
|
||||
detailLoading.value = true
|
||||
detailError.value = null
|
||||
try {
|
||||
const response = await getPlatformUnifiedOrder(tenantId, orderId.value)
|
||||
if (serial !== detailRequestSerial || requestKey !== detailRouteKey.value) return
|
||||
detail.value = response
|
||||
await loadCargoImagePreviews(response, serial)
|
||||
} catch (error) {
|
||||
if (serial !== detailRequestSerial || requestKey !== detailRouteKey.value) return
|
||||
detail.value = null
|
||||
@@ -886,6 +916,7 @@ onMounted(() => {
|
||||
onBeforeUnmount(() => {
|
||||
measurementRequestSerial += 1
|
||||
releaseMeasurementPreview()
|
||||
releaseCargoImagePreviews()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user