670 lines
18 KiB
TypeScript
670 lines
18 KiB
TypeScript
/**
|
||
* 运输计划管理 API
|
||
*/
|
||
import request from '@/utils/http/bx'
|
||
|
||
// =============================================================================
|
||
// 基础数据 API
|
||
// =============================================================================
|
||
|
||
// 承运商
|
||
export interface Carrier {
|
||
id: string
|
||
carrierName: string
|
||
contactName?: string
|
||
contactPhone?: string
|
||
status: string
|
||
remark?: string
|
||
createTime: string
|
||
}
|
||
|
||
export interface CarrierQuery {
|
||
q?: string
|
||
status?: string
|
||
}
|
||
|
||
export const carrierApi = {
|
||
list: (params?: CarrierQuery) => request.get<Carrier[]>('/transport/carrier', { params }),
|
||
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),
|
||
delete: (id: string) => request.delete(`/transport/carrier/${id}`)
|
||
}
|
||
|
||
// 证书行(嵌套保存)
|
||
export interface CertRow {
|
||
certId?: string
|
||
certName: string
|
||
certNo?: string
|
||
expireDate?: string
|
||
remindDays?: number
|
||
attachmentUrls?: string
|
||
}
|
||
|
||
export interface CertRead extends CertRow {
|
||
id: string
|
||
ownerType: string
|
||
ownerId: string
|
||
status: string
|
||
createTime?: string
|
||
}
|
||
|
||
// 车辆-人员关联行
|
||
export interface VehiclePersonnelRow {
|
||
personnelId?: string
|
||
personnelName: string
|
||
phoneNo?: string
|
||
age?: number | null
|
||
role: string
|
||
isDefault?: number
|
||
remark?: string
|
||
}
|
||
|
||
// 车辆
|
||
export interface Vehicle {
|
||
id: string
|
||
vehicleType: string
|
||
carrierId?: string
|
||
carrierName?: string
|
||
licensePlate: string
|
||
defaultDriverId?: string
|
||
defaultDriverName?: string
|
||
personnelSummary?: string
|
||
loadCapacity?: number
|
||
vehicleStatus: string
|
||
remark?: string
|
||
createTime: string
|
||
}
|
||
|
||
export interface VehicleDetail extends Vehicle {
|
||
personnelList: VehiclePersonnelRow[]
|
||
certList: CertRead[]
|
||
}
|
||
|
||
export interface VehiclePayload {
|
||
vehicleType: string
|
||
carrierId?: string
|
||
carrierName?: string
|
||
licensePlate: string
|
||
loadCapacity?: number | null
|
||
vehicleStatus: string
|
||
remark?: string
|
||
personnelList?: VehiclePersonnelRow[]
|
||
certList?: CertRow[]
|
||
}
|
||
|
||
export interface VehicleQuery {
|
||
q?: string
|
||
vehicleType?: string
|
||
carrierId?: string
|
||
vehicleStatus?: string
|
||
}
|
||
|
||
export const vehicleApi = {
|
||
list: (params?: VehicleQuery) => request.get<Vehicle[]>('/transport/vehicle', { params }),
|
||
get: (id: string) => request.get<VehicleDetail>(`/transport/vehicle/${id}`),
|
||
create: (data: VehiclePayload) => request.post<VehicleDetail>('/transport/vehicle', data),
|
||
update: (id: string, data: Partial<VehiclePayload>) =>
|
||
request.put<VehicleDetail>(`/transport/vehicle/${id}`, data),
|
||
delete: (id: string) => request.delete(`/transport/vehicle/${id}`)
|
||
}
|
||
|
||
// 人员
|
||
export interface Personnel {
|
||
id: string
|
||
personnelName: string
|
||
phoneNo?: string
|
||
age?: number
|
||
idCardNo?: string
|
||
status: string
|
||
remark?: string
|
||
nearestExpireDate?: string
|
||
createTime: string
|
||
}
|
||
|
||
export interface PersonnelDetail extends Personnel {
|
||
certList: CertRead[]
|
||
}
|
||
|
||
export interface PersonnelPayload {
|
||
personnelName: string
|
||
phoneNo?: string
|
||
age?: number | null
|
||
idCardNo?: string
|
||
status: string
|
||
remark?: string
|
||
certList?: CertRow[]
|
||
}
|
||
|
||
export interface PersonnelQuery {
|
||
q?: string
|
||
status?: string
|
||
}
|
||
|
||
export const personnelApi = {
|
||
list: (params?: PersonnelQuery) => request.get<Personnel[]>('/transport/personnel', { params }),
|
||
get: (id: string) => request.get<PersonnelDetail>(`/transport/personnel/${id}`),
|
||
create: (data: PersonnelPayload) => request.post<PersonnelDetail>('/transport/personnel', data),
|
||
update: (id: string, data: Partial<PersonnelPayload>) =>
|
||
request.put<PersonnelDetail>(`/transport/personnel/${id}`, data),
|
||
delete: (id: string) => request.delete(`/transport/personnel/${id}`)
|
||
}
|
||
|
||
// 司机(兼容旧 API,映射至 personnel)
|
||
export interface Driver {
|
||
id: string
|
||
driverName: string
|
||
phoneNo?: string
|
||
idCardNo?: string
|
||
drivingLicenseNo?: string
|
||
drivingLicenseExpire?: string
|
||
vehicleLicenseNo?: string
|
||
vehicleLicenseExpire?: string
|
||
hazmatCertNo?: string
|
||
hazmatCertExpire?: string
|
||
remark?: string
|
||
createTime: string
|
||
}
|
||
|
||
export interface DriverQuery {
|
||
q?: string
|
||
}
|
||
|
||
function personnelToDriver(p: Personnel): Driver {
|
||
return {
|
||
id: p.id,
|
||
driverName: p.personnelName,
|
||
phoneNo: p.phoneNo,
|
||
idCardNo: p.idCardNo,
|
||
remark: p.remark,
|
||
createTime: p.createTime
|
||
}
|
||
}
|
||
|
||
function driverToPersonnelPayload(data: Partial<Driver>): PersonnelPayload {
|
||
return {
|
||
personnelName: data.driverName || '',
|
||
phoneNo: data.phoneNo,
|
||
idCardNo: data.idCardNo,
|
||
status: '1',
|
||
remark: data.remark
|
||
}
|
||
}
|
||
|
||
export const driverApi = {
|
||
list: async (params?: DriverQuery) => {
|
||
const res = await personnelApi.list({ q: params?.q })
|
||
const rows = (res.data ?? res) as Personnel[]
|
||
return { ...res, data: rows.map(personnelToDriver) }
|
||
},
|
||
get: async (id: string) => {
|
||
const res = await personnelApi.get(id)
|
||
const detail = (res.data ?? res) as PersonnelDetail
|
||
return { ...res, data: personnelToDriver(detail) }
|
||
},
|
||
create: async (data: Partial<Driver>) => {
|
||
const res = await personnelApi.create(driverToPersonnelPayload(data))
|
||
const detail = (res.data ?? res) as PersonnelDetail
|
||
return { ...res, data: personnelToDriver(detail) }
|
||
},
|
||
update: async (id: string, data: Partial<Driver>) => {
|
||
const res = await personnelApi.update(id, driverToPersonnelPayload(data))
|
||
const detail = (res.data ?? res) as PersonnelDetail
|
||
return { ...res, data: personnelToDriver(detail) }
|
||
},
|
||
delete: (id: string) => personnelApi.delete(id)
|
||
}
|
||
|
||
// =============================================================================
|
||
// 计划管理 API
|
||
// =============================================================================
|
||
|
||
export interface PlanProduct {
|
||
id: string
|
||
planId: string
|
||
productId: string
|
||
productNo: string
|
||
productName: string
|
||
model?: string
|
||
unit: string
|
||
categoryName?: string
|
||
packageSpec?: string
|
||
deliveryMethod?: string
|
||
quantity?: number
|
||
actualQty?: number
|
||
taxRate?: number
|
||
taxPrice?: number
|
||
taxAmount?: number
|
||
taxSubtotal?: number
|
||
isExplosive: number
|
||
isToxic: number
|
||
purchaseCertUrl?: string
|
||
transportCertUrl?: string
|
||
inboundEstimateQty?: number
|
||
inboundQty?: number
|
||
inboundPrice?: number
|
||
inboundAmount?: number
|
||
outboundEstimateQty?: number
|
||
outboundQty?: number
|
||
outboundPrice?: number
|
||
outboundAmount?: number
|
||
remark?: string
|
||
}
|
||
|
||
export interface Plan {
|
||
id: string
|
||
planNo: string
|
||
planDate: string
|
||
belongsCompany: string
|
||
planType: string
|
||
followStatus: string
|
||
transportStatus: string
|
||
archiveStatus: string
|
||
completeStatus: string
|
||
contractId?: string
|
||
contractNo?: string
|
||
supplierId?: string
|
||
supplierName?: string
|
||
destinationId?: string
|
||
destinationName?: string
|
||
customerId?: string
|
||
customerName?: string
|
||
contactName?: string
|
||
contactPhone?: string
|
||
partyA?: string
|
||
partyB?: string
|
||
contractStartDate?: string
|
||
contractEndDate?: string
|
||
deliveryMethod?: string
|
||
settlementMethod?: string
|
||
hasFreight: number
|
||
pickupAddress?: string
|
||
pickupTime?: string
|
||
pickupNotes?: string
|
||
destinationAddress?: string
|
||
deliveryTime?: string
|
||
destinationNotes?: string
|
||
vehicleId?: string
|
||
licensePlate?: string
|
||
driverId?: string
|
||
driverName?: string
|
||
transportId?: string
|
||
transportNo?: string
|
||
totalAmount: number
|
||
freightAmount: number
|
||
notifyMessage?: string
|
||
followUserId?: string
|
||
followUserName?: string
|
||
remark?: string
|
||
createTime: string
|
||
products?: PlanProduct[]
|
||
}
|
||
|
||
export interface PlanQuery {
|
||
q?: string
|
||
planNo?: string
|
||
planType?: string
|
||
followStatus?: string
|
||
transportStatus?: string
|
||
archiveStatus?: string
|
||
customerName?: string
|
||
planDateFrom?: string
|
||
planDateTo?: string
|
||
page?: number
|
||
pageSize?: number
|
||
}
|
||
|
||
export interface PlanListResponse {
|
||
total: number
|
||
list: Plan[]
|
||
}
|
||
|
||
export interface PlanTransportCreateBlock {
|
||
vehicleId: string
|
||
driverId?: string
|
||
carrierId?: string
|
||
distanceKm?: number
|
||
freightType: string
|
||
transportQty?: number
|
||
freightPrice?: number
|
||
freightAmount?: number
|
||
hasInvoice?: number
|
||
remark?: string
|
||
}
|
||
|
||
export interface PlanCreateFullPayload {
|
||
contractId: string
|
||
planDate: string
|
||
belongsCompany: string
|
||
planType: string
|
||
contractNo?: string
|
||
supplierId?: string
|
||
supplierName?: string
|
||
destinationId?: string
|
||
destinationName?: string
|
||
customerId?: string
|
||
customerName?: string
|
||
contactName?: string
|
||
contactPhone?: string
|
||
partyA?: string
|
||
partyB?: string
|
||
contractStartDate?: string
|
||
contractEndDate?: string
|
||
deliveryMethod?: string
|
||
settlementMethod?: string
|
||
hasFreight: number
|
||
pickupAddress?: string
|
||
pickupTime?: string
|
||
pickupNotes?: string
|
||
destinationAddress?: string
|
||
deliveryTime?: string
|
||
destinationNotes?: string
|
||
followUserId?: string
|
||
followUserName?: string
|
||
remark?: string
|
||
products: Array<{
|
||
productId: string
|
||
productNo: string
|
||
productName: string
|
||
model?: string
|
||
unit: string
|
||
categoryName?: string
|
||
packageSpec?: string
|
||
deliveryMethod?: string
|
||
quantity?: number
|
||
actualQty?: number
|
||
taxPrice?: number
|
||
taxAmount?: number
|
||
taxSubtotal?: number
|
||
remark?: string
|
||
isExplosive?: number
|
||
isToxic?: number
|
||
}>
|
||
transport?: PlanTransportCreateBlock
|
||
}
|
||
|
||
export type PlanUpdatePayload = Partial<Omit<PlanCreateFullPayload, 'contractId'>>
|
||
|
||
export const planApi = {
|
||
list: (params?: PlanQuery) => request.get<PlanListResponse>('/transport/plan/', { params }),
|
||
get: (id: string) => request.get<Plan>(`/transport/plan/${id}`),
|
||
countByContract: (contractIds: string[]) =>
|
||
request.get<{ counts: Record<string, number> }>('/transport/plan/count-by-contract', {
|
||
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),
|
||
update: (id: string, data: PlanUpdatePayload) => request.put<Plan>(`/transport/plan/${id}`, data),
|
||
updateProductCerts: (
|
||
id: string,
|
||
products: Array<{ id: string; purchaseCertUrl?: string; transportCertUrl?: string }>
|
||
) => request.patch<Plan>(`/transport/plan/${id}/product-certs`, { products }),
|
||
cancel: (id: string) => request.post<Plan>(`/transport/plan/${id}/cancel`),
|
||
getArrangeInfo: (id: string) => request.get<PlanArrangeInfo>(`/transport/plan/${id}/arrange-info`),
|
||
archive: (id: string) => request.post<Plan>(`/transport/plan/${id}/archive`),
|
||
delete: (id: string) => request.delete(`/transport/plan/${id}`),
|
||
createFromContract: (data: { contractId: string; planDate: string; followUserId?: string; followUserName?: string }) =>
|
||
request.post<Plan>('/transport/plan/create-from-contract', data)
|
||
}
|
||
|
||
// =============================================================================
|
||
// 运输管理 API
|
||
// =============================================================================
|
||
|
||
export interface Transport {
|
||
id: string
|
||
transportNo: string
|
||
vehicleId?: string
|
||
licensePlate?: string
|
||
driverId?: string
|
||
driverName?: string
|
||
driverPhone?: string
|
||
carrierId?: string
|
||
carrierName?: string
|
||
transportMedium?: string
|
||
startPoint?: string
|
||
endPoint?: string
|
||
distanceKm?: number
|
||
unit?: string
|
||
transportQty?: number
|
||
freightPrice?: number
|
||
freightAmount: number
|
||
freightType: string
|
||
hasInvoice: number
|
||
qrCode?: string
|
||
qrExpireDate?: string
|
||
transportStatus: string
|
||
approvalStatus: string
|
||
feedbackTime?: string
|
||
feedbackQty?: number
|
||
feedbackImages?: string
|
||
feedbackRemark?: string
|
||
remark?: string
|
||
createTime: string
|
||
}
|
||
|
||
export interface TransportArrange {
|
||
vehicleId: string
|
||
driverId: string
|
||
carrierId?: string
|
||
transportMedium?: string
|
||
pickupAddress?: string
|
||
pickupTime?: string
|
||
pickupNotes?: string
|
||
destinationAddress?: string
|
||
deliveryTime?: string
|
||
destinationNotes?: string
|
||
distanceKm?: number
|
||
unit?: string
|
||
freightType: string
|
||
freightPrice?: number
|
||
freightAmount?: number
|
||
hasInvoice?: number
|
||
remark?: string
|
||
generateDibangPlan?: boolean
|
||
}
|
||
|
||
export interface TransportInventoryLink {
|
||
planProductId: string
|
||
productName: string
|
||
dbPurchasePlanId: string
|
||
dbInventoryId: string
|
||
batchNo: string
|
||
planNo: string
|
||
}
|
||
|
||
export interface TransportSiteLink {
|
||
planProductId: string
|
||
productName: string
|
||
siteLinkId: string
|
||
planNo: string
|
||
businessType: string
|
||
siteAccessToken?: string
|
||
siteUrl?: string
|
||
siteFeedbackRemark?: string
|
||
siteFeedbackImages?: string[]
|
||
siteFeedbackTime?: string
|
||
}
|
||
|
||
export interface PlanArrangeInfo {
|
||
driverUrl?: string
|
||
licensePlate?: string
|
||
siteRecords?: TransportSiteLink[]
|
||
inventoryRecords?: TransportInventoryLink[]
|
||
}
|
||
|
||
export interface TransportArrangeResult extends Transport {
|
||
driverAccessToken?: string
|
||
driverUrl?: string
|
||
siteRecords?: TransportSiteLink[]
|
||
inventoryRecords?: TransportInventoryLink[]
|
||
}
|
||
|
||
export interface TransportQuery {
|
||
q?: string
|
||
transportNo?: string
|
||
transportStatus?: string
|
||
approvalStatus?: string
|
||
vehicleId?: string
|
||
driverId?: string
|
||
page?: number
|
||
pageSize?: number
|
||
}
|
||
|
||
export interface TransportListResponse {
|
||
total: number
|
||
list: Transport[]
|
||
}
|
||
|
||
export const transportApi = {
|
||
list: (params?: TransportQuery) => request.get<TransportListResponse>('/transport/order/', { params }),
|
||
get: (id: string) => request.get<Transport>(`/transport/order/${id}`),
|
||
create: (data: Partial<Transport> & { planIds?: string[] }) =>
|
||
request.post<Transport>('/transport/order/', data),
|
||
arrange: (planId: string, data: TransportArrange) =>
|
||
request.post<TransportArrangeResult>(`/transport/order/arrange/${planId}`, data),
|
||
generateQrcode: (id: string, expireDays?: number) =>
|
||
request.get<{ transportId: string; transportNo: string; qrCode: string; expireDate?: string }>(
|
||
`/transport/order/${id}/qrcode`,
|
||
{ params: { expireDays } }
|
||
),
|
||
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),
|
||
getApprovals: (id: string) => request.get<any[]>(`/transport/order/${id}/approvals`)
|
||
}
|
||
|
||
// =============================================================================
|
||
// 运费结算 API
|
||
// =============================================================================
|
||
|
||
export interface FreightSettlement {
|
||
id: string
|
||
settlementNo: string
|
||
totalFreight: number
|
||
invoiceAmount?: number
|
||
invoiceNo?: string
|
||
invoiceDate?: string
|
||
settlementStatus: string
|
||
remark?: string
|
||
createTime: string
|
||
transports?: Transport[]
|
||
}
|
||
|
||
export interface FreightSettlementQuery {
|
||
q?: string
|
||
settlementStatus?: string
|
||
page?: number
|
||
pageSize?: number
|
||
}
|
||
|
||
export interface FreightSettlementListResponse {
|
||
total: number
|
||
list: FreightSettlement[]
|
||
}
|
||
|
||
export const freightApi = {
|
||
list: (params?: FreightSettlementQuery) =>
|
||
request.get<FreightSettlementListResponse>('/transport/freight/', { params }),
|
||
get: (id: string) => request.get<FreightSettlement>(`/transport/freight/${id}`),
|
||
create: (transportIds: string[]) =>
|
||
request.post<FreightSettlement>('/transport/freight/', { transportIds }),
|
||
update: (id: string, data: Partial<FreightSettlement>) =>
|
||
request.put<FreightSettlement>(`/transport/freight/${id}`, data),
|
||
submit: (id: string) => request.post<FreightSettlement>(`/transport/freight/${id}/submit`),
|
||
approve: (id: string) => request.post<FreightSettlement>(`/transport/freight/${id}/approve`)
|
||
}
|
||
|
||
// =============================================================================
|
||
// 盘存统计 API
|
||
// =============================================================================
|
||
|
||
export interface InventoryRecord {
|
||
id: string
|
||
productId: string
|
||
productNo: string
|
||
productName: string
|
||
model?: string
|
||
unit: string
|
||
stockQty: number
|
||
stockAmount: number
|
||
lowStockWarning?: number
|
||
highStockWarning?: number
|
||
createTime: string
|
||
}
|
||
|
||
export interface InventoryTransaction {
|
||
id: string
|
||
productId: string
|
||
productName: string
|
||
transactionType: string
|
||
planId?: string
|
||
planNo?: string
|
||
qty: number
|
||
unitPrice: number
|
||
amount: number
|
||
stockAfter: number
|
||
createTime: string
|
||
}
|
||
|
||
export interface InventoryWarning {
|
||
id: string
|
||
productId: string
|
||
productName: string
|
||
warningType: string
|
||
currentQty: number
|
||
thresholdValue: number
|
||
status: string
|
||
resolveTime?: string
|
||
resolveRemark?: string
|
||
createTime: string
|
||
}
|
||
|
||
export interface DocumentReminder {
|
||
id: string
|
||
certId?: string
|
||
ownerType?: string
|
||
ownerId?: string
|
||
ownerLabel?: string
|
||
driverId?: string
|
||
driverName?: string
|
||
documentType: string
|
||
documentNo?: string
|
||
expireDate: string
|
||
daysRemaining: number
|
||
status: string
|
||
remark?: string
|
||
createTime: string
|
||
}
|
||
|
||
export interface InventoryLedgerQuery {
|
||
productName?: string
|
||
page?: number
|
||
pageSize?: number
|
||
}
|
||
|
||
export interface InventoryLedgerResponse {
|
||
total: number
|
||
list: InventoryRecord[]
|
||
}
|
||
|
||
export const inventoryApi = {
|
||
ledger: (params?: InventoryLedgerQuery) =>
|
||
request.get<InventoryLedgerResponse>('/transport/inventory/ledger', { params }),
|
||
transactions: (params?: any) =>
|
||
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) =>
|
||
request.get<InventoryWarning[]>('/transport/inventory/warnings', { params: { status } }),
|
||
updateWarning: (id: string, data: { status: string; resolveRemark?: string }) =>
|
||
request.put<InventoryWarning>(`/transport/inventory/warnings/${id}`, data),
|
||
setWarningThreshold: (data: { productId: string; lowStockWarning?: number; highStockWarning?: number }) =>
|
||
request.post('/transport/inventory/warning-threshold', data),
|
||
documentReminders: (status?: string) =>
|
||
request.get<DocumentReminder[]>('/transport/inventory/document-reminders', { params: { status } }),
|
||
updateDocumentReminder: (id: string, data: { status: string; remark?: string }) =>
|
||
request.put<DocumentReminder>(`/transport/inventory/document-reminders/${id}`, data)
|
||
}
|