This commit is contained in:
zlwu committed 2026-08-27 14:23:18 +08:00
1 parent e56d227fe8
commit 4611dbc2b2
237 files changed
+1384060 -24942

No files matched your search

+225 -28
View File
@@ -1,6 +1,7 @@
/**
* 运输计划管理 API
*/
import { ElMessage } from 'element-plus'
import request from '@/utils/http/bx'
import { pickBxList, pickBxPageResult } from '@/utils/http/bx'
import type { TransportResourceSnapshot } from '@/utils/pl-transport-resource-snapshot'
@@ -50,7 +51,8 @@ export const carrierApi = {
request.post('/transport/carrier/export', data, { responseType: 'blob' }),
get: (id: string) => request.get<Carrier>(`/transport/carrier/${id}`),
create: (data: Partial<Carrier>) => request.post<Carrier>('/transport/carrier', data),
update: (id: string, data: Partial<Carrier>) => request.put<Carrier>(`/transport/carrier/${id}`, data),
update: (id: string, data: Partial<Carrier>) =>
request.put<Carrier>(`/transport/carrier/${id}`, data),
/** @deprecated 承运商审核已移除,后端接口已禁用 */
approve: (id: string) => request.post<Carrier>(`/transport/carrier/${id}/approve`),
reject: (id: string, data?: { remark?: string }) =>
@@ -310,6 +312,23 @@ export const transportAddressApi = {
delete: (id: string) => request.delete(`/transport/address/${id}`)
}
export type CustomerStopPrefStopType = 'load' | 'delivery'
export interface CustomerStopPref {
customerId: string
stopType: CustomerStopPrefStopType
address?: string
lng?: number | null
lat?: number | null
contact?: string
notes?: string
}
export const customerStopPrefApi = {
get: (params: { customerId: string; stopType: CustomerStopPrefStopType }) =>
request.get<CustomerStopPref | null>('/transport/customer-stop-pref', { params })
}
// 司机(兼容旧 API,映射至 personnel)
export interface Driver {
id: string
@@ -401,6 +420,68 @@ export interface PlanDocumentAttachmentItem {
export interface PlanContractLink {
contractId: string
contractNo?: string
stopId?: string
}
/** 装货/送货段产品行 */
export interface PlanStopProduct {
id?: string
planProductId?: string
productId: string
productNo: string
productName: string
model?: string
unit: string
packageSpec?: string
deliveryMethod?: string
planQty?: number
inboundQty?: number
inboundPrice?: number
inboundAmount?: number
outboundQty?: number
outboundPrice?: number
outboundAmount?: number
remark?: string
}
/** 装货段(计划 1:1) */
export interface PlanLoad {
id?: string
planId?: string
customerId?: string
customerName?: string
address?: string
lng?: number | null
lat?: number | null
loadTime?: string
contact?: string
notes?: string
generateDibang?: number
dibangDirection?: string
remark?: string
products?: PlanStopProduct[]
contracts?: PlanContractLink[]
}
/** 送货段(计划 1:N) */
export interface PlanDelivery {
id?: string
planId?: string
seq?: number
customerId?: string
customerName?: string
address?: string
lng?: number | null
lat?: number | null
deliveryTime?: string
contact?: string
notes?: string
generateDibang?: number
dibangDirection?: string
remark?: string
deliveryMethod?: string
products?: PlanStopProduct[]
contracts?: PlanContractLink[]
}
export interface PlanProduct {
@@ -494,6 +575,7 @@ export interface Plan {
transportNo?: string
totalAmount: number
freightAmount: number
freightRemark?: string
notifyMessage?: string
followUserId?: string
followUserName?: string
@@ -505,8 +587,6 @@ export interface Plan {
createBy?: string
createTime: string
products?: PlanProduct[]
supplierContracts?: PlanContractLink[]
demanderContracts?: PlanContractLink[]
/** 列表:是否显示「复制给司机」 */
canCopyToDriver?: boolean
/** 列表:是否显示「复制给现场」 */
@@ -515,6 +595,16 @@ export interface Plan {
canCopyPoundQrcode?: boolean
/** 列表:单据附件(司机/现场/出入库现场等) */
documentAttachments?: PlanDocumentAttachmentItem[]
/** 装货段 */
load?: PlanLoad | null
/** 送货段列表 */
deliveries?: PlanDelivery[]
/** 列表:装货客户名称 */
loadCustomerName?: string
/** 列表:送货客户摘要 */
deliveryCustomerSummary?: string
/** 保存告警(如数量不平衡,HTTP 200 仍返回) */
warnings?: string[]
}
export interface PlanQuery {
@@ -577,6 +667,7 @@ export interface PlanCreateFullPayload {
deliveryMethod?: string
settlementMethod?: string
hasFreight: number
freightRemark?: string
pickupAddress?: string
pickupLng?: number | null
pickupLat?: number | null
@@ -594,6 +685,8 @@ export interface PlanCreateFullPayload {
remark?: string
supplierContracts?: PlanContractLink[]
demanderContracts?: PlanContractLink[]
load?: PlanLoad
deliveries?: PlanDelivery[]
products: Array<{
productId: string
productNo: string
@@ -617,6 +710,19 @@ export interface PlanCreateFullPayload {
export type PlanUpdatePayload = Partial<Omit<PlanCreateFullPayload, 'contractId'>>
/** 展示计划保存返回的告警(数量不平衡等) */
export function showPlanSaveWarnings(plan?: Pick<Plan, 'warnings'> | null) {
const warnings = plan?.warnings
if (!warnings?.length) return
const seen = new Set<string>()
for (const msg of warnings) {
const text = (msg || '').trim()
if (!text || seen.has(text)) continue
seen.add(text)
ElMessage.warning(text)
}
}
export interface PlanArchiveBrandQtyItem {
brandId: string
brandName?: string
@@ -648,8 +754,27 @@ export interface PlanArchiveProductItem {
brandQtys?: PlanArchiveBrandQtyItem[]
}
export interface PlanArchiveStopProductItem {
id: string
inboundQty?: number
inboundPrice?: number
outboundQty?: number
outboundPrice?: number
}
export interface PlanArchiveLoadBlock {
stopId: string
products: PlanArchiveStopProductItem[]
}
export interface PlanArchiveDeliveryBlock {
stopId: string
products: PlanArchiveStopProductItem[]
}
export interface PlanArchiveFreightBlock {
hasFreight: number
freightRemark?: string
distanceKm?: number
freightType?: string
freightPrice?: number
@@ -659,7 +784,9 @@ export interface PlanArchiveFreightBlock {
}
export interface PlanArchiveBody {
products: PlanArchiveProductItem[]
products?: PlanArchiveProductItem[]
load?: PlanArchiveLoadBlock
deliveries?: PlanArchiveDeliveryBlock[]
freight?: PlanArchiveFreightBlock
}
@@ -722,7 +849,8 @@ export const planApi = {
params: { contractIds: contractIds.join(',') }
}),
create: (data: Partial<Plan>) => request.post<Plan>('/transport/plan/', data),
createFull: (data: PlanCreateFullPayload) => request.post<Plan>('/transport/plan/create-full', data),
createFull: (data: PlanCreateFullPayload) =>
request.post<Plan>('/transport/plan/create-full', data),
update: (id: string, data: PlanUpdatePayload) => request.put<Plan>(`/transport/plan/${id}`, data),
updateProductCerts: (
id: string,
@@ -739,11 +867,11 @@ export const planApi = {
request.patch<Plan>(`/transport/plan/${id}/erp-entered`, { entered }),
cancel: (id: string) => request.post<Plan>(`/transport/plan/${id}/cancel`),
waitNotice: (id: string) => request.post<Plan>(`/transport/plan/${id}/wait-notice`),
cancelWaitNotice: (id: string) =>
request.post<Plan>(`/transport/plan/${id}/cancel-wait-notice`),
cancelWaitNotice: (id: string) => request.post<Plan>(`/transport/plan/${id}/cancel-wait-notice`),
forceFollowStatus: (id: string, followStatus: string) =>
request.post<Plan>(`/transport/plan/${id}/force-follow-status`, { followStatus }),
getArrangeInfo: (id: string) => request.get<PlanArrangeInfo>(`/transport/plan/${id}/arrange-info`),
getArrangeInfo: (id: string) =>
request.get<PlanArrangeInfo>(`/transport/plan/${id}/arrange-info`),
archive: (id: string, data?: PlanArchiveBody) =>
request.post<Plan>(`/transport/plan/${id}/archive`, data),
updateDriverFeedback: (id: string, data: PlanDriverFeedbackUpdateBody) =>
@@ -757,8 +885,7 @@ export const planApi = {
createDate?: string
followUserId?: string
followUserName?: string
}) =>
request.post<Plan>('/transport/plan/create-from-contract', data),
}) => request.post<Plan>('/transport/plan/create-from-contract', data),
getInboundSlipTemplate: (id: string) =>
request.get<string>(`/transport/plan/${id}/inbound-slip-template`),
saveInboundSlipTemplate: (id: string, slipTemplateContent: string) =>
@@ -767,6 +894,20 @@ export const planApi = {
request.get<string>(`/transport/plan/${id}/delivery-slip-template`),
saveDeliverySlipTemplate: (id: string, slipTemplateContent: string) =>
request.put(`/transport/plan/${id}/delivery-slip-template`, { slipTemplateContent }),
getPrintDeliverySlip: (id: string, customerId?: string) =>
request.get<{
planId: string
planNo: string
planDate?: string
customerId?: string
receivingUnit?: string
receiveContact?: string
deliveryAddress?: string
products?: PlanStopProduct[]
customers?: { customerId: string; customerName: string; deliveryCount: number }[]
}>(`/transport/plan/${id}/print-delivery-slip`, {
params: customerId ? { customerId } : undefined
}),
getSubpackSlipTemplate: (id: string) =>
request.get<string>(`/transport/plan/${id}/subpack-slip-template`),
saveSubpackSlipTemplate: (id: string, slipTemplateContent: string) =>
@@ -777,11 +918,7 @@ export const planApi = {
request.get<PlListResponse<PlanContractGapItem>>('/transport/plan/contract-gaps', { params }),
exportContractGaps: (data: Record<string, any>) =>
request.post('/transport/plan/contract-gaps/export', data, { responseType: 'blob' }),
updateSideContracts: (
id: string,
side: 'supplier' | 'demander',
contracts: PlanContractLink[]
) =>
updateSideContracts: (id: string, side: 'supplier' | 'demander', contracts: PlanContractLink[]) =>
request.put<PlanContractGapItem>(`/transport/plan/${id}/contracts/${side}`, { contracts })
}
@@ -789,6 +926,29 @@ export const planApi = {
// 运输管理 API
// =============================================================================
export interface TransportStopFeedback {
stopType: 'load' | 'delivery'
stopId: string
label: string
customerName: string
businessType?: string
quantity?: number
attachmentUrls?: string[]
products?: {
stopProductId: string
planProductId?: string
productName?: string
model?: string
unit?: string
packageSpec?: string
quantity?: number
actualQty?: number
brandQtys?: { brandId: string; brandName?: string; qty: number }[]
}[]
remark?: string
feedbackTime?: string
}
export interface Transport {
id: string
transportNo: string
@@ -820,10 +980,18 @@ export interface Transport {
feedbackImages?: string
feedbackRemark?: string
driverProductFeedbacks?: TransportDriverProductFeedback[]
driverStopFeedbacks?: TransportStopFeedback[]
siteStopFeedbacks?: TransportStopFeedback[]
remark?: string
createTime: string
}
export interface TransportStopDibangOption {
stopType: 'load' | 'delivery'
stopId: string
generateDibang: boolean
}
export interface TransportArrange {
vehicleId: string
driverId?: string
@@ -849,6 +1017,7 @@ export interface TransportArrange {
hasInvoice?: number
remark?: string
generateDibangPlan?: boolean
stopDibangOptions?: TransportStopDibangOption[]
}
export interface TransportInventoryLink {
@@ -858,6 +1027,8 @@ export interface TransportInventoryLink {
dbInventoryId: string
batchNo: string
planNo: string
stopType?: 'load' | 'delivery'
stopId?: string
}
export interface TransportSiteLink {
@@ -883,6 +1054,7 @@ export interface TransportIoOrderBrief {
}
export interface PlanArrangeInfo {
requiresSiteLink?: boolean
driverUrl?: string
licensePlate?: string
siteRecords?: TransportSiteLink[]
@@ -1029,7 +1201,8 @@ export interface TransportListResponse {
}
export const transportApi = {
list: (params?: TransportQuery) => request.get<TransportListResponse>('/transport/order/', { params }),
list: (params?: TransportQuery) =>
request.get<TransportListResponse>('/transport/order/', { params }),
export: (data: Record<string, any>) =>
request.post('/transport/order/export', data, { responseType: 'blob' }),
get: (id: string) => request.get<Transport>(`/transport/order/${id}`),
@@ -1044,8 +1217,13 @@ export const transportApi = {
),
submitApproval: (id: string, approverIds: string[]) =>
request.post<Transport>(`/transport/order/${id}/submit-approval`, { approverIds }),
scanFeedback: (data: { transportNo: string; verifyCode?: string; feedbackQty?: number; feedbackImages?: string[]; feedbackRemark?: string }) =>
request.post('/transport/order/scan/feedback', data),
scanFeedback: (data: {
transportNo: string
verifyCode?: string
feedbackQty?: number
feedbackImages?: string[]
feedbackRemark?: string
}) => request.post('/transport/order/scan/feedback', data),
getApprovals: (id: string) => request.get<any[]>(`/transport/order/${id}/approvals`)
}
@@ -1063,6 +1241,7 @@ export interface UnsettledPlanItem {
licensePlate?: string
transportCompany?: string
freightAmount: number
freightRemark?: string
archiveTime?: string
transportId: string
transportNo?: string
@@ -1092,6 +1271,7 @@ export interface SettlementPlanSummary {
planDate?: string
licensePlate?: string
freightAmount?: number
freightRemark?: string
}
export interface SettlementApprovalFlowItem {
@@ -1321,7 +1501,10 @@ export const inventoryApi = {
exportLedger: (data: Record<string, any>) =>
request.post('/transport/inventory/ledger/export', data, { responseType: 'blob' }),
transactions: (params?: any) =>
request.get<{ total: number; list: InventoryTransaction[] }>('/transport/inventory/transactions', { params }),
request.get<{ total: number; list: InventoryTransaction[] }>(
'/transport/inventory/transactions',
{ params }
),
summary: (params: { groupBy: string; dateFrom: string; dateTo: string; productId?: string }) =>
request.get<{ list: any[] }>('/transport/inventory/summary', { params }),
warnings: (status?: string) =>
@@ -1336,7 +1519,9 @@ export const inventoryApi = {
highStockWarning?: number
}) => request.post('/transport/inventory/warning-threshold', data),
documentReminders: (status?: string) =>
request.get<DocumentReminder[]>('/transport/inventory/document-reminders', { params: { status } }),
request.get<DocumentReminder[]>('/transport/inventory/document-reminders', {
params: { status }
}),
exportDocumentReminders: (data: Record<string, any>) =>
request.post('/transport/inventory/document-reminders/export', data, { responseType: 'blob' }),
documentReminderStats: () =>
@@ -1467,10 +1652,15 @@ export const vehicleRechargeRecordApi = {
{ params }
),
export: (data: Record<string, any>) =>
request.post('/transport/vehicle-recharge-record/disburse-board/export', data, { responseType: 'blob' }),
request.post('/transport/vehicle-recharge-record/disburse-board/export', data, {
responseType: 'blob'
}),
list: (params?: Record<string, unknown>) =>
request.get<VehicleRechargeRecordListResponse>('/transport/vehicle-recharge-record/', { params }),
get: (id: string) => request.get<VehicleRechargeRecord>(`/transport/vehicle-recharge-record/${id}`),
request.get<VehicleRechargeRecordListResponse>('/transport/vehicle-recharge-record/', {
params
}),
get: (id: string) =>
request.get<VehicleRechargeRecord>(`/transport/vehicle-recharge-record/${id}`),
create: (data: Partial<VehicleRechargeRecord>) =>
request.post<VehicleRechargeRecord>('/transport/vehicle-recharge-record/', data),
update: (id: string, data: Partial<VehicleRechargeRecord>) =>
@@ -1583,9 +1773,12 @@ export const vehicleMaintenanceApplyApi = {
request.post<VehicleMaintenanceApply>(`/transport/vehicle-maintenance-apply/${id}/cancel`),
delete: (ids: string) => request.delete(`/transport/vehicle-maintenance-apply/${ids}`),
reminders: (licensePlate: string, excludeApplyId?: string) =>
request.get<VehicleMaintenanceApplyReminder[]>('/transport/vehicle-maintenance-apply/reminders', {
params: { licensePlate, excludeApplyId }
})
request.get<VehicleMaintenanceApplyReminder[]>(
'/transport/vehicle-maintenance-apply/reminders',
{
params: { licensePlate, excludeApplyId }
}
)
}
export const vehicleMaintenanceProcessApi = {
@@ -1595,7 +1788,9 @@ export const vehicleMaintenanceProcessApi = {
{ params }
),
export: (data: Record<string, any>) =>
request.post('/transport/vehicle-maintenance-process/process-board/export', data, { responseType: 'blob' }),
request.post('/transport/vehicle-maintenance-process/process-board/export', data, {
responseType: 'blob'
}),
get: (id: string) =>
request.get<VehicleMaintenanceProcess>(`/transport/vehicle-maintenance-process/${id}`),
create: (data: Partial<VehicleMaintenanceProcess>) =>
@@ -1701,7 +1896,9 @@ export const vehicleUreaDisburseApi = {
{ params }
),
export: (data: Record<string, any>) =>
request.post('/transport/vehicle-urea-disburse/disburse-board/export', data, { responseType: 'blob' }),
request.post('/transport/vehicle-urea-disburse/disburse-board/export', data, {
responseType: 'blob'
}),
get: (id: string) => request.get<VehicleUreaDisburse>(`/transport/vehicle-urea-disburse/${id}`),
create: (data: Partial<VehicleUreaDisburse>) =>
request.post<VehicleUreaDisburse>('/transport/vehicle-urea-disburse/', data),
+50 -1
View File
@@ -24,6 +24,44 @@ export interface PublicIoOrderItem {
brandQtys?: BrandQtyItem[]
}
export interface PublicIoOrderStopProduct {
stopProductId: string
planProductId?: string
productName?: string
aliasName?: string | null
model?: string
packageSpec?: string
unit?: string
quantity?: number
actualQty?: number
remark?: string
brandMode?: string | null
brandId?: string | null
brandName?: string | null
brandOptions?: { brandId: string; brandName: string }[]
brandQtys?: BrandQtyItem[]
}
export interface PublicIoOrderStop {
stopType: 'load' | 'delivery'
stopId: string
seq?: number
label: string
customerName: string
address?: string
contact?: string
notes?: string
lng?: number | null
lat?: number | null
businessType?: string
planQty?: number
showProductQty?: boolean
attachmentUrls?: string[]
products?: PublicIoOrderStopProduct[]
remark?: string
feedbackTime?: string
}
export interface PublicIoOrderPage {
title?: string
orderNo?: string
@@ -53,6 +91,7 @@ export interface PublicIoOrderPage {
voided: boolean
archived?: boolean
items: PublicIoOrderItem[]
stops?: PublicIoOrderStop[]
}
export interface PublicIoOrderHistoryProduct {
@@ -122,7 +161,17 @@ export function createPublicIoOrderApi(kind: 'inbound' | 'outbound') {
status: 'in_progress' | 'completed' | 'voided'
remark?: string
images?: string[]
items: { id: string; actualQty: number; brandQtys?: BrandQtyItem[] }[]
items?: { id: string; actualQty: number; brandQtys?: BrandQtyItem[] }[]
stops?: {
stopType: 'load' | 'delivery'
stopId: string
attachmentUrls?: string[]
products: {
stopProductId: string
actualQty: number
brandQtys?: BrandQtyItem[]
}[]
}[]
}
) => publicPlPost<{ success: boolean }>(`${base}/${token}/feedback`, data),
uploadAttachment: (token: string, file: File) =>
@@ -0,0 +1,41 @@
import { publicPlGet, publicPlPost, publicPlUpload } from '@/utils/http/public-pl'
import type {
PublicTransportHistoryPage,
PublicTransportStop,
PublicUploadResult
} from '@/api/pl/public-transport'
export interface PublicTransportSitePage {
planNo: string
planDate?: string
licensePlate?: string
vehicleNo?: string
planVoided?: boolean
planArchived?: boolean
stops: PublicTransportStop[]
}
export const publicTransportSiteApi = {
getPage: (token: string) =>
publicPlGet<PublicTransportSitePage>(`/public/pl/transport-site/${token}`),
getHistory: (token: string, date: string, keyword?: string) => {
const params = new URLSearchParams({ date })
const q = (keyword || '').trim()
if (q) params.set('q', q)
return publicPlGet<PublicTransportHistoryPage>(
`/public/pl/transport-site/${token}/history?${params.toString()}`
)
},
saveFeedback: (
token: string,
data: {
stopType: 'load' | 'delivery'
stopId: string
quantity?: number
attachmentUrls?: string[]
remark?: string
}
) => publicPlPost<{ success: boolean }>(`/public/pl/transport-site/${token}/feedback`, data),
uploadAttachment: (token: string, file: File) =>
publicPlUpload<PublicUploadResult>(`/public/pl/transport-site/${token}/attachments`, file)
}
+74 -2
View File
@@ -29,6 +29,44 @@ export interface PublicTransportPersonnel {
role?: string
}
export interface PublicTransportStopProduct {
stopProductId: string
planProductId?: string
productName: string
aliasName?: string | null
model?: string
packageSpec?: string
unit?: string
quantity?: number
remark?: string
brandMode?: string | null
brandId?: string | null
brandName?: string | null
brandOptions?: { brandId: string; brandName: string }[]
actualQty?: number | null
brandQtys?: BrandQtyItem[]
}
export interface PublicTransportStop {
stopType: 'load' | 'delivery'
stopId: string
seq?: number
label: string
customerName: string
address?: string
contact?: string
notes?: string
lng?: number | null
lat?: number | null
businessType?: string
planQty?: number | null
quantity?: number | null
products?: PublicTransportStopProduct[]
attachmentUrls?: string[]
remark?: string
feedbackTime?: string
}
export interface PublicTransportPage {
planNo: string
planDate?: string
@@ -51,6 +89,7 @@ export interface PublicTransportPage {
driverPhone?: string
otherPersonnel?: PublicTransportPersonnel[]
products: PublicTransportProduct[]
stops?: PublicTransportStop[]
feedbackRemark?: string
feedbackImages: string[]
feedbackQty?: number | null
@@ -72,18 +111,39 @@ export interface PublicTransportHistoryProduct {
unit?: string
}
export interface PublicTransportHistoryStopProduct {
productName: string
model?: string
packageSpec?: string
quantity?: number | null
unit?: string
}
export interface PublicTransportHistoryStop {
stopType: 'load' | 'delivery'
seq?: number
label: string
customerName: string
address?: string
stopTime?: string
products?: PublicTransportHistoryStopProduct[]
}
export interface PublicTransportHistoryRecord {
planId: string
planNo: string
transportId: string
driverAccessToken?: string
driverUrl?: string
siteAccessToken?: string
siteUrl?: string
licensePlate?: string
pickupTime?: string
deliveryTime?: string
pickupAddress?: string
destinationAddress?: string
products?: PublicTransportHistoryProduct[]
stops?: PublicTransportHistoryStop[]
planVoided?: boolean
planArchived?: boolean
statusLabel?: string
@@ -92,6 +152,7 @@ export interface PublicTransportHistoryRecord {
export interface PublicTransportHistoryPage {
licensePlate?: string
date: string
keyword?: string
records: PublicTransportHistoryRecord[]
}
@@ -106,9 +167,20 @@ export const publicTransportApi = {
data: {
feedbackImages?: string[]
feedbackRemark?: string
products: { planProductId: string; actualQty: number; brandQtys?: BrandQtyItem[] }[]
products?: { planProductId: string; actualQty: number; brandQtys?: BrandQtyItem[] }[]
}
) => publicPlPost<{ success: boolean }>(`/public/pl/transport/${token}/feedback`, data),
uploadAttachment: (token: string, file: File) =>
publicPlUpload<PublicUploadResult>(`/public/pl/transport/${token}/attachments`, file)
publicPlUpload<PublicUploadResult>(`/public/pl/transport/${token}/attachments`, file),
saveDriverStopFeedback: (
token: string,
data: {
stopType: 'load' | 'delivery'
stopId: string
attachmentUrls: string[]
products?: { stopProductId: string; actualQty: number; brandQtys?: BrandQtyItem[] }[]
remark?: string
}
) =>
publicPlPost<{ success: boolean }>(`/public/pl/transport/${token}/driver-feedback`, data)
}