feat: complete phase three admin loading workflow

This commit is contained in:
2026-08-10 12:05:20 +08:00
parent bbe93ca235
commit 2915e6d599
7 changed files with 191 additions and 80 deletions
+76 -16
View File
@@ -2,7 +2,25 @@ import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
const inboundBasePath = '/platform/v1/inbounds'
export interface OutboundGateItem { code: string; name: string; passed: boolean; actual?: string | null; requirement?: string | null }
export interface OutboundDispatchAggregate {
orderId: number | string | null
orderNo: string | null
inboundId: number | string | null
inboundCode: string | null
containerBookingId: number | string | null
containerNo: string | null
oceanBookingId: number | string | null
oceanBookingStatus: string | null
truckAppointmentId: number | string | null
truckAppointmentStatus: string | null
customsStatus?: string | null
sailingStatus?: string | null
gate: { passed: boolean; items: OutboundGateItem[] } | null
}
export type PreloadStatus = 'PENDING' | 'CONFIRMING' | 'CONFIRMED' | string
/** 五类装柜取证。旧接口仍使用 PHOTO_STEP_* / SEAL 编码,页面统一映射为业务名称。 */
export type EvidenceType = 'PHOTO_STEP_1' | 'PHOTO_STEP_2' | 'PHOTO_STEP_3' | 'PHOTO_STEP_4' | 'SEAL'
export interface PreloadItem {
@@ -50,8 +68,13 @@ export interface Evidence {
sealNo: string | null
remark: string | null
version: number
status: 'ACTIVE' | 'VOIDED' | string
createdAt: string | null
updatedAt: string | null
voidReason?: string | null
voidedBy?: number | string | null
voidedByName?: string | null
voidedAt?: string | null
}
export interface EvidenceList {
@@ -90,15 +113,23 @@ export interface UpsertEvidenceRequest {
remark?: string
}
export interface UploadEvidenceResult {
fileId: number | string
fileName: string | null
contentType?: string | null
sizeBytes?: number | null
}
export interface VoidEvidenceRequest {
expectedVersion: number
reason: string
}
export interface CompleteLoadingRequest {
expectedVersion: number
remark?: string
}
export interface CompleteDeliveryRequest {
expectedVersion: number
remark?: string
}
function query(tenantId: string | number) {
return { tenantId: String(tenantId) }
@@ -119,6 +150,15 @@ export async function getPreload(tenantId: string | number, inboundId: string |
return unwrapApiResponse(response)
}
export async function getOutboundDispatch(tenantId: string | number, orderId?: string | number, inboundId?: string | number) {
const response = await http.get<ApiEnvelope<OutboundDispatchAggregate[]>, ApiEnvelope<OutboundDispatchAggregate[]>>(
'/platform/v1/first-leg/outbound-dispatches',
{ params: { tenantId: String(tenantId), ...(orderId ? { orderId: String(orderId) } : {}), ...(inboundId ? { inboundId: String(inboundId) } : {}) } },
)
const result = unwrapApiResponse(response)
return result?.[0] || null
}
export async function smartSplit(
tenantId: string | number,
inboundId: string | number,
@@ -204,6 +244,38 @@ export async function upsertEvidence(
return unwrapApiResponse(response)
}
/** 真实 File 服务上传;返回的 fileId 才能提交证据,不接受本地文件名冒充。 */
export async function uploadEvidenceFile(
tenantId: string | number,
inboundId: string | number,
evidenceType: EvidenceType,
file: File,
) {
const body = new FormData()
body.append('evidenceType', evidenceType)
body.append('file', file)
const response = await http.post<ApiEnvelope<UploadEvidenceResult>, ApiEnvelope<UploadEvidenceResult>>(
`/platform/v1/files/loading-evidence/${tenantId}/${inboundId}`,
body,
{ headers: { 'Content-Type': 'multipart/form-data' } },
)
return unwrapApiResponse(response)
}
export async function voidEvidence(
tenantId: string | number,
inboundId: string | number,
evidenceId: string | number,
request: VoidEvidenceRequest,
) {
const response = await http.post<ApiEnvelope<LoadingActionResponse>, ApiEnvelope<LoadingActionResponse>>(
`${inboundBasePath}/${inboundId}/loading/evidence/${evidenceId}/void`,
request,
writeOptions('evidence-void', inboundId, tenantId),
)
return unwrapApiResponse(response)
}
export async function completeLoading(
tenantId: string | number,
inboundId: string | number,
@@ -215,15 +287,3 @@ export async function completeLoading(
)
return unwrapApiResponse(response)
}
export async function completeDelivery(
tenantId: string | number,
inboundId: string | number,
request: CompleteDeliveryRequest,
) {
const response = await http.post<ApiEnvelope<LoadingActionResponse>, ApiEnvelope<LoadingActionResponse>>(
`${inboundBasePath}/${inboundId}/delivery/complete`, request,
writeOptions('delivery-complete', inboundId, tenantId),
)
return unwrapApiResponse(response)
}