Files
shanxia2.0/web-admin/src/api/pl/index.ts
T
zlwuandCursor 9c3c53c705 feat(web-admin): pass address library notes through apply payload
Allow load/delivery sections to receive notes when an address is selected.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 11:59:09 +08:00

2008 lines
57 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 运输计划管理 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'
// =============================================================================
// 基础数据 API
// =============================================================================
export interface PlListResponse<T> {
total: number
list: T[]
}
// 承运商
export interface Carrier {
id: string
carrierName: string
contactName?: string
contactPhone?: string
status: string
remark?: string
businessLicenseUrls?: string
roadTransportLicenseUrls?: string
transportAgreementUrls?: string
transportAgreementExpireDate?: string
auditStatus?: string
auditBy?: string
auditTime?: string
auditRemark?: string
qualificationComplete?: boolean
transportAgreementExpired?: boolean
createTime: string
}
export interface CarrierQuery {
q?: string
status?: string
auditStatus?: string
page?: number
pageSize?: number
}
export const carrierApi = {
list: (params?: CarrierQuery) =>
request.get<PlListResponse<Carrier>>('/transport/carrier', { params }),
export: (data: Record<string, any>) =>
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),
/** @deprecated 承运商审核已移除,后端接口已禁用 */
approve: (id: string) => request.post<Carrier>(`/transport/carrier/${id}/approve`),
reject: (id: string, data?: { remark?: string }) =>
request.post<Carrier>(`/transport/carrier/${id}/reject`, data ?? {}),
delete: (id: string) => request.delete(`/transport/carrier/${id}`)
}
// 证书行(嵌套保存)
export interface CertRow {
certId?: string
vehiclePart?: 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
trailerNo?: string
defaultDriverId?: string
defaultDriverName?: string
personnelSummary?: string
loadCapacity?: number
vehicleStatus: string
remark?: string
photoUrls?: string
certList?: CertRead[]
createTime: string
}
export interface VehicleDetail extends Vehicle {
personnelList: VehiclePersonnelRow[]
certList: CertRead[]
}
export interface VehiclePayload {
vehicleType: string
carrierId?: string
carrierName?: string
licensePlate: string
trailerNo?: string
loadCapacity?: number | null
vehicleStatus: string
remark?: string
photoUrls?: string
personnelList?: VehiclePersonnelRow[]
certList?: CertRow[]
}
export interface VehicleQuery {
q?: string
vehicleType?: string
carrierId?: string
vehicleStatus?: string
excludeIneligibleCarrier?: boolean
page?: number
pageSize?: number
}
export const vehicleApi = {
list: (params?: VehicleQuery) =>
request.get<PlListResponse<Vehicle>>('/transport/vehicle', { params }),
export: (data: Record<string, any>) =>
request.post('/transport/vehicle/export', data, { responseType: 'blob' }),
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
personnelType: string
personnelAffiliation: string
status: string
remark?: string
photoUrls?: string
nearestExpireDate?: string
certList?: CertRead[]
createTime: string
}
export interface PersonnelDetail extends Personnel {
certList: CertRead[]
}
export interface PersonnelPayload {
personnelName: string
phoneNo?: string
age?: number | null
idCardNo?: string
personnelType: string
personnelAffiliation: string
status: string
remark?: string
photoUrls?: string
certList?: CertRow[]
}
export interface PersonnelQuery {
q?: string
status?: string
personnelAffiliation?: string
/** driver | escort;不传则不过滤类型 */
personnelType?: string
page?: number
pageSize?: number
}
export const personnelApi = {
list: (params?: PersonnelQuery) =>
request.get<PlListResponse<Personnel>>('/transport/personnel', { params }),
export: (data: Record<string, any>) =>
request.post('/transport/personnel/export', data, { responseType: 'blob' }),
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}`)
}
export interface PersonnelCertOcrResult {
certNo?: string | null
expireDate?: string | null
expireDateRaw?: string | null
monthlyUsed: number
monthlyLimit: number
}
export const personnelCertOcrApi = {
recognize: (data: { certName: string; attachmentUrl?: string; attachmentUrls?: string }) =>
request.post<PersonnelCertOcrResult>('/transport/ocr/recognize-cert', data)
}
export type PasteConflictAction = 'reuse' | 'overwrite' | 'cancel'
export type PasteRecognizeMode = 'vehicle_bundle' | 'personnel_first'
export interface PasteConflictItem {
key: 'vehicle' | 'driver' | 'escort'
existingId: string
action: PasteConflictAction
}
export interface PastePersonnelPayload {
personnelName: string
phoneNo?: string
idCardNo?: string
personnelType: 'driver' | 'escort'
}
export interface PasteVehiclePayload {
licensePlate: string
trailerNo?: string
loadCapacity?: number | null
carrierId?: string
carrierName?: string
}
export interface PasteCommitBody {
mode: PasteRecognizeMode
createVehicle?: boolean
vehicle?: PasteVehiclePayload | null
driver?: PastePersonnelPayload | null
escort?: PastePersonnelPayload | null
conflicts?: PasteConflictItem[]
}
export interface PasteCommitResult {
vehicleId?: string | null
driverId?: string | null
escortId?: string | null
}
export const pasteRecognizeApi = {
commit: (data: PasteCommitBody) =>
request.post<PasteCommitResult>('/transport/paste-recognize/commit', data)
}
// 运输通用地址库
export interface TransportAddress {
id: string
addressName: string
fullAddress: string
lng: number
lat: number
contactName?: string
contactPhone?: string
notes?: string
status: string
remark?: string
createTime: string
updateTime: string
}
export interface TransportAddressQuery {
q?: string
status?: string
page?: number
pageSize?: number
}
export interface TransportAddressPayload {
addressName: string
fullAddress: string
lng: number
lat: number
contactName?: string
contactPhone?: string
notes?: string
status?: string
remark?: string
}
export const transportAddressApi = {
list: (params?: TransportAddressQuery) =>
request.get<PlListResponse<TransportAddress>>('/transport/address', { params }),
export: (data: Record<string, any>) =>
request.post('/transport/address/export', data, { responseType: 'blob' }),
listAll: (params?: { q?: string }) =>
/** 选择器:仅按地址名称、详细地址模糊检索(不含联系人/电话) */
request.get<PlListResponse<TransportAddress>>('/transport/address/all', { params }),
get: (id: string) => request.get<TransportAddress>(`/transport/address/${id}`),
create: (data: TransportAddressPayload) =>
request.post<TransportAddress>('/transport/address', data),
update: (id: string, data: Partial<TransportAddressPayload>) =>
request.put<TransportAddress>(`/transport/address/${id}`, data),
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
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
page?: number
pageSize?: number
}
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 = {
export: (data: Record<string, any>) =>
request.post('/transport/driver/export', data, { responseType: 'blob' }),
list: async (params?: DriverQuery) => {
const res = await personnelApi.list({
q: params?.q,
page: params?.page,
pageSize: params?.pageSize
})
const { list, total } = pickBxPageResult<Personnel>(res)
return {
...res,
data: {
total,
list: list.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 PlanDocumentAttachmentItem {
url: string
label: string
}
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
/** 本段归档品牌数量(与归档弹窗填写一致) */
brandQtys?: Array<{ brandId: string; brandName?: string; qty: number; unitPrice?: 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 {
id: string
planId: string
productId: string
productNo: string
productName: string
brandMode?: string
brandId?: string
brandName?: string
/** 归档品牌数量明细 */
brandQtys?: PlanArchiveBrandQtyItem[]
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
legalUseCertUrl?: 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
createDate: string
planDate?: string | null
belongsCompany: string
planType: string
followStatus: string
transportStatus: string
archiveStatus: string
completeStatus: string
contractId?: string
contractNo?: string
supplierContracts?: PlanContractLink[]
demanderContracts?: PlanContractLink[]
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
pickupLng?: number | null
pickupLat?: number | null
pickupTime?: string
pickupContact?: string
pickupNotes?: string
destinationAddress?: string
destinationLng?: number | null
destinationLat?: number | null
deliveryTime?: string
deliveryContact?: string
destinationNotes?: string
vehicleId?: string
licensePlate?: string
trailerNo?: string
driverId?: string
driverName?: string
personnelSummary?: string
resourceSnapshot?: TransportResourceSnapshot
transportId?: string
transportNo?: string
totalAmount: number
freightAmount: number
freightRemark?: string
notifyMessage?: string
followUserId?: string
followUserName?: string
hazardCertReady?: number
hazardCertReadyBy?: string
hazardCertReadyTime?: string
erpEntered?: number
remark?: string
createBy?: string
createTime: string
products?: PlanProduct[]
/** 列表:是否显示「复制给司机」 */
canCopyToDriver?: boolean
/** 列表:是否显示「复制给现场」 */
canCopyToSite?: boolean
/** 列表:是否显示「复制磅单二维码」 */
canCopyPoundQrcode?: boolean
/** 列表:单据附件(司机/现场/出入库现场等) */
documentAttachments?: PlanDocumentAttachmentItem[]
/** 装货段 */
load?: PlanLoad | null
/** 送货段列表 */
deliveries?: PlanDelivery[]
/** 列表:装货客户名称 */
loadCustomerName?: string
/** 列表:送货客户摘要 */
deliveryCustomerSummary?: string
/** 保存告警(如数量不平衡,HTTP 200 仍返回) */
warnings?: string[]
}
export interface PlanQuery {
q?: string
planNo?: string
planType?: string
followStatus?: string
/** 排除的跟进状态,多个以英文逗号分隔 */
excludeFollowStatus?: string
transportStatus?: string
archiveStatus?: string
customerName?: string
productName?: string
licensePlate?: string
planDateFrom?: string
planDateTo?: string
/** 1=仅含易制毒/易制爆产品的计划 */
hasHazardProduct?: number
/** incomplete=至少一张必需危化证书未上传 */
certUploadStatus?: string
/** 0=未确认齐备 1=已确认齐备 */
hazardCertReady?: number
/** CRM 合同 ID:仅返回关联该合同的计划 */
contractId?: 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
createDate: string
planDate?: string | null
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
freightRemark?: string
pickupAddress?: string
pickupLng?: number | null
pickupLat?: number | null
pickupTime?: string
pickupContact?: string
pickupNotes?: string
destinationAddress?: string
destinationLng?: number | null
destinationLat?: number | null
deliveryTime?: string
deliveryContact?: string
destinationNotes?: string
followUserId?: string
followUserName?: string
remark?: string
saveMode?: 'draft' | 'formal'
supplierContracts?: PlanContractLink[]
demanderContracts?: PlanContractLink[]
load?: PlanLoad
deliveries?: PlanDelivery[]
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 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
qty: number
/** 本品牌单价(金额 = qty * unitPrice) */
unitPrice?: number
}
export interface TransportDriverProductFeedback {
planProductId: string
productName: string
productNo?: string
model?: string
unit?: string
packageSpec?: string
brandMode?: string
brandId?: string
brandName?: string
actualQty?: number
brandSummary?: string
brandQtys?: PlanArchiveBrandQtyItem[]
}
export interface PlanArchiveProductItem {
id: string
actualQty?: number
inboundQty?: number
inboundPrice?: number
outboundQty?: number
outboundPrice?: number
brandQtys?: PlanArchiveBrandQtyItem[]
}
export interface PlanArchiveStopProductItem {
id: string
inboundQty?: number
inboundPrice?: number
outboundQty?: number
outboundPrice?: number
brandQtys?: PlanArchiveBrandQtyItem[]
}
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
freightAmount?: number
transportQty?: number
hasInvoice?: number
}
export interface PlanArchiveStopFeedbackAttachmentItem {
stopType: 'load' | 'delivery'
stopId: string
attachmentUrls: string[]
}
export interface PlanArchiveFeedbacksBlock {
driverStops?: PlanArchiveStopFeedbackAttachmentItem[]
siteStops?: PlanArchiveStopFeedbackAttachmentItem[]
}
export interface PlanArchiveBody {
products?: PlanArchiveProductItem[]
load?: PlanArchiveLoadBlock
deliveries?: PlanArchiveDeliveryBlock[]
freight?: PlanArchiveFreightBlock
feedbacks?: PlanArchiveFeedbacksBlock
}
export interface PlanDriverFeedbackProductItem {
planProductId: string
actualQty: number
brandQtys?: PlanArchiveBrandQtyItem[]
}
export interface PlanDriverFeedbackUpdateBody {
feedbackQty?: number | null
feedbackRemark?: string | null
feedbackImages?: string[]
feedbackTime?: string | null
products?: PlanDriverFeedbackProductItem[]
}
export interface PlanSiteFeedbackUpdateBody {
siteFeedbackRemark?: string | null
siteFeedbackImages?: string[]
siteFeedbackTime?: string | null
}
export interface PlanContractGapItem {
id: string
planNo: string
planDate?: string
planType?: string
followStatus: string
supplierId?: string
supplierName?: string
customerId?: string
customerName?: string
gapSides: Array<'supplier' | 'demander'>
supplierContractExempt: boolean
demanderContractExempt: boolean
supplierContracts: PlanContractLink[]
demanderContracts: PlanContractLink[]
products?: PlanProduct[]
/** 段次合同完善:装货段 */
load?: PlanLoad
/** 段次合同完善:送货段列表 */
deliveries?: PlanDelivery[]
}
export interface PlanContractGapQuery {
page?: number
pageSize?: number
planNo?: string
gapType?: 'supplier' | 'demander' | 'both' | ''
customerKeyword?: string
planDateFrom?: string
planDateTo?: string
q?: string
}
export interface ContractProductArrangeQtyPlanItem {
planId: string
planNo?: string
planDate?: string | null
planQty: number
planType?: string | null
belongsCompany?: string | null
supplierName?: string | null
customerName?: string | null
licensePlate?: string | null
driverName?: string | null
followUserName?: string | null
followStatus?: string
transportStatus?: string
archiveStatus?: string
createTime?: string | null
}
export interface ContractProductArrangeQtyDetail {
contractId: string
contractNo?: string | null
customerName?: string | null
productId: string
productName?: string | null
hasFixedQty: boolean
contractQty?: number | null
arrangedQty: number
availableQty?: number | null
plans: ContractProductArrangeQtyPlanItem[]
}
export const planApi = {
list: (params?: PlanQuery) => request.get<PlanListResponse>('/transport/plan/', { params }),
export: (data: Record<string, any>) =>
request.post('/transport/plan/export', data, { responseType: 'blob' }),
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(',') }
}),
/** 表单可安排数量 / 问号弹窗 */
getContractProductArrangeQty: (params: {
contractId: string
productId: string
excludePlanId?: string
}) =>
request.get<ContractProductArrangeQtyDetail>(
'/transport/plan/contract-product-arrange-qty',
{ params }
),
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
legalUseCertUrl?: string
}>
) => request.patch<Plan>(`/transport/plan/${id}/product-certs`, { products }),
setHazardCertReady: (id: string, ready: boolean) =>
request.patch<Plan>(`/transport/plan/${id}/hazard-cert-ready`, { ready }),
setErpEntered: (id: string, entered: boolean) =>
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`),
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`),
archive: (id: string, data?: PlanArchiveBody) =>
request.post<Plan>(`/transport/plan/${id}/archive`, data),
archiveDraft: (id: string, data: PlanArchiveBody) =>
request.post<Plan>(`/transport/plan/${id}/archive-draft`, data),
updateDriverFeedback: (id: string, data: PlanDriverFeedbackUpdateBody) =>
request.patch<Plan>(`/transport/plan/${id}/driver-feedback`, data),
updateSiteFeedback: (id: string, linkId: string, data: PlanSiteFeedbackUpdateBody) =>
request.patch<Plan>(`/transport/plan/${id}/site-feedback/${linkId}`, data),
delete: (id: string) => request.delete(`/transport/plan/${id}`),
createFromContract: (data: {
contractId: string
planDate?: string | null
createDate?: string
followUserId?: string
followUserName?: string
}) => 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) =>
request.put(`/transport/plan/${id}/inbound-slip-template`, { slipTemplateContent }),
getDeliverySlipTemplate: (id: string) =>
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) =>
request.put(`/transport/plan/${id}/subpack-slip-template`, { slipTemplateContent }),
ensureSubpackSlipNo: (id: string) =>
request.post<string>(`/transport/plan/${id}/subpack-slip-no`),
listContractGaps: (params?: PlanContractGapQuery) =>
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[]) =>
request.put<PlanContractGapItem>(`/transport/plan/${id}/contracts/${side}`, { contracts }),
updateStopContracts: (
id: string,
data: { stopType: 'load' | 'delivery'; stopId: string; contracts: PlanContractLink[] }
) => request.put<PlanContractGapItem>(`/transport/plan/${id}/stop-contracts`, data)
}
// =============================================================================
// 运输管理 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
vehicleId?: string
licensePlate?: string
trailerNo?: string
driverId?: string
driverName?: string
driverPhone?: string
resourceSnapshot?: TransportResourceSnapshot
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
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
carrierId?: string
transportMedium?: string
pickupAddress?: string
pickupLng?: number | null
pickupLat?: number | null
pickupTime?: string
pickupContact?: string
pickupNotes?: string
destinationAddress?: string
destinationLng?: number | null
destinationLat?: number | null
deliveryTime?: string
deliveryContact?: string
destinationNotes?: string
distanceKm?: number
unit?: string
freightType: string
freightPrice?: number
freightAmount?: number
hasInvoice?: number
remark?: string
generateDibangPlan?: boolean
stopDibangOptions?: TransportStopDibangOption[]
}
export interface TransportInventoryLink {
planProductId: string
productName: string
dbPurchasePlanId: string
dbInventoryId: string
batchNo: string
planNo: string
stopType?: 'load' | 'delivery'
stopId?: 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 TransportIoOrderBrief {
kind: string
orderId: string
orderNo: string
siteAccessToken?: string
siteUrl?: string
status?: string
}
export interface PlanArrangeInfo {
requiresSiteLink?: boolean
driverUrl?: string
licensePlate?: string
siteRecords?: TransportSiteLink[]
inventoryRecords?: TransportInventoryLink[]
ioOrder?: TransportIoOrderBrief
}
export interface TransportArrangeResult extends Transport {
driverAccessToken?: string
driverUrl?: string
siteRecords?: TransportSiteLink[]
inventoryRecords?: TransportInventoryLink[]
ioOrder?: TransportIoOrderBrief
contractQtyReminder?: ContractQtyReminder
}
export interface ContractQtyReminderItem {
contractId: string
contractNo?: string
contractType?: string
customerName?: string
stopKind: string
productId: string
productName?: string
model?: string
unit?: string
mode: 'remaining' | 'framework_cumulative' | string
contractQty?: number
arrangedTotalQty: number
remainingQty?: number
thisPlanQty: number
}
export interface ContractQtyReminder {
items: ContractQtyReminderItem[]
}
export interface PlIoOrderItem {
id: string
orderId: string
planProductId: string
productId?: string
productNo?: string
productName?: string
aliasName?: string
brandSummary?: string
brandName?: string
brandMode?: string
brandId?: string
brandOptions?: Array<{ brandId: string; brandName?: string }>
brandQtys?: PlanArchiveBrandQtyItem[]
specification?: string
unit?: string
unitLabel?: string
planQty?: number
actualQty?: number
qtySource?: string
categoryName?: string
packageSpec?: string
deliveryMethod?: string
remark?: string
}
export interface PlIoOrder {
id: string
orderNo: string
planId: string
transportId: string
status: string
partnerCompany?: string
vehicleNo?: string
planNo?: string
planDate?: string
businessType?: string
planRemark?: string
pickupAddress?: string
pickupLng?: number | null
pickupLat?: number | null
pickupTime?: string
pickupContact?: string
pickupNotes?: string
destinationName?: string
destinationAddress?: string
destinationLng?: number | null
destinationLat?: number | null
deliveryTime?: string
deliveryContact?: string
destinationNotes?: string
siteAccessToken?: string
siteUrl?: string
siteFeedbackRemark?: string
siteFeedbackImages?: string[]
siteFeedbackTime?: string
siteFirstSubmittedAt?: string
remark?: string
productSummary?: string
actualQtyTotal?: number
kind: string
items?: PlIoOrderItem[]
createTime?: string
updateTime?: string
}
export interface PlIoOrderQuery {
orderNo?: string
planNo?: string
status?: string
partnerCompany?: string
vehicleNo?: string
q?: string
planDateFrom?: string
planDateTo?: string
page?: number
pageSize?: number
}
export interface PlIoOrderListResponse {
total: number
list: PlIoOrder[]
}
export const inboundOrderApi = {
list: (params?: PlIoOrderQuery) =>
request.get<PlIoOrderListResponse>('/transport/inbound/', { params }),
export: (data: Record<string, any>) =>
request.post('/transport/inbound/export', data, { responseType: 'blob' }),
get: (id: string) => request.get<PlIoOrder>(`/transport/inbound/${id}`),
getByPlan: (planId: string) =>
request.get<PlIoOrder | null>(`/transport/inbound/by-plan/${planId}`),
patch: (id: string, data: Record<string, unknown>) =>
request.patch<PlIoOrder>(`/transport/inbound/${id}`, data),
siteUrl: (id: string) =>
request.get<{ siteUrl?: string; siteAccessToken?: string }>(`/transport/inbound/${id}/site-url`)
}
export const outboundOrderApi = {
list: (params?: PlIoOrderQuery) =>
request.get<PlIoOrderListResponse>('/transport/outbound/', { params }),
export: (data: Record<string, any>) =>
request.post('/transport/outbound/export', data, { responseType: 'blob' }),
get: (id: string) => request.get<PlIoOrder>(`/transport/outbound/${id}`),
getByPlan: (planId: string) =>
request.get<PlIoOrder | null>(`/transport/outbound/by-plan/${planId}`),
patch: (id: string, data: Record<string, unknown>) =>
request.patch<PlIoOrder>(`/transport/outbound/${id}`, data),
siteUrl: (id: string) =>
request.get<{ siteUrl?: string; siteAccessToken?: string }>(
`/transport/outbound/${id}/site-url`
)
}
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 }),
export: (data: Record<string, any>) =>
request.post('/transport/order/export', data, { responseType: 'blob' }),
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 UnsettledPlanItem {
id: string
planNo: string
planDate: string
planType: string
customerName?: string
supplierName?: string
licensePlate?: string
transportCompany?: string
freightAmount: number
freightRemark?: string
archiveTime?: string
transportId: string
transportNo?: string
driverName?: string
transportMedium?: string
startPoint?: string
endPoint?: string
}
export interface UnsettledPlanQuery {
q?: string
carrierId?: string
planType?: string
licensePlate?: string
page?: number
pageSize?: number
}
export interface UnsettledPlanListResponse {
total: number
list: UnsettledPlanItem[]
}
export interface SettlementPlanSummary {
id: string
planNo: string
planDate?: string
licensePlate?: string
freightAmount?: number
freightRemark?: string
}
export interface SettlementApprovalFlowItem {
id: string
step: number
stepName?: string
approverId: string
approverName?: string
approvalType?: string
approvalResult: string
approvalOpinion?: string
approvalTime?: string
isCurrent: number
}
export interface RemittanceVoucher {
id: string
settlementId: string
remittanceDate?: string
remittanceAmount?: number
voucherUrls?: string
remark?: string
createTime?: string
}
export interface FreightSettlementBrief {
id: string
settlementNo: string
invoiceAmount?: number
invoiceNo?: string
invoiceDate?: string
invoiceAttachmentUrls?: string
settlementStatus: string
}
export interface FreightSettlement {
id: string
settlementNo: string
totalFreight: number
invoiceAmount?: number
invoiceNo?: string
invoiceDate?: string
invoiceAttachmentUrls?: string
settlementStatus: string
remark?: string
createBy?: string
createTime: string
updateTime?: string
planCount?: number
licensePlateSummary?: string
currentApproverName?: string
canApprove?: boolean
canWithdraw?: boolean
currentApprovalId?: string
approvalFinishedTime?: string
disburseTime?: string
disburseAmount?: number
submitterName?: string
transports?: Transport[]
plans?: SettlementPlanSummary[]
approvalFlow?: SettlementApprovalFlowItem[]
approvalHistory?: SettlementApprovalFlowItem[]
vouchers?: RemittanceVoucher[]
}
export interface FreightSettlementQuery {
q?: string
carrierId?: string
settlementStatus?: string
tab?: 'bills' | 'approval_pending' | 'approval_done' | 'disburse' | 'settled'
page?: number
pageSize?: number
}
export interface FreightSettlementListResponse {
total: number
list: FreightSettlement[]
}
export interface FreightSettlementSubmitBody {
approvalType: 'sequential' | 'parallel' | 'or'
approverIds: string[]
remark?: string
}
export interface FreightSettlementApprovalBody {
action: 'approve' | 'reject'
comment?: string
}
export interface FreightSettlementDisburseBody {
remittanceDate: string
remittanceAmount: number
voucherUrls: string[]
remark?: string
}
export interface FreightSettlementUpdateBody {
invoiceNo?: string
invoiceDate?: string
invoiceAmount?: number
invoiceAttachmentUrls?: string
remark?: string
transportIds?: string[]
}
export const freightApi = {
listUnsettledPlans: (params?: UnsettledPlanQuery) =>
request.get<UnsettledPlanListResponse>('/transport/freight/unsettled-plans', { params }),
exportUnsettledPlans: (data: Record<string, any>) =>
request.post('/transport/freight/unsettled-plans/export', data, { responseType: 'blob' }),
getByTransport: (transportId: string) =>
request.get<FreightSettlementBrief | null>(`/transport/freight/by-transport/${transportId}`),
list: (params?: FreightSettlementQuery) =>
request.get<FreightSettlementListResponse>('/transport/freight/', { params }),
export: (data: Record<string, any>) =>
request.post('/transport/freight/export', data, { responseType: 'blob' }),
get: (id: string) => request.get<FreightSettlement>(`/transport/freight/${id}`),
create: (data: { planIds?: string[]; transportIds?: string[] }) =>
request.post<FreightSettlement>('/transport/freight/', data),
update: (id: string, data: FreightSettlementUpdateBody) =>
request.put<FreightSettlement>(`/transport/freight/${id}`, data),
cancel: (id: string) => request.post<FreightSettlement>(`/transport/freight/${id}/cancel`),
delete: (id: string) => request.delete(`/transport/freight/${id}`),
submitApproval: (id: string, data: FreightSettlementSubmitBody) =>
request.post<FreightSettlement>(`/transport/freight/${id}/submit-approval`, data),
processApproval: (approvalId: string, data: FreightSettlementApprovalBody) =>
request.post<FreightSettlement>(`/transport/freight/approval/${approvalId}`, data),
withdrawApproval: (id: string) =>
request.post<FreightSettlement>(`/transport/freight/${id}/withdraw-approval`),
getApprovalFlow: (id: string) =>
request.get<SettlementApprovalFlowItem[]>(`/transport/freight/${id}/approval-flow`),
disburse: (id: string, data: FreightSettlementDisburseBody) =>
request.post<FreightSettlement>(`/transport/freight/${id}/disburse`, data),
/** @deprecated 请使用 submitApproval */
submit: (id: string) => request.post<FreightSettlement>(`/transport/freight/${id}/submit`),
/** @deprecated 请使用 processApproval */
approve: (id: string) => request.post<FreightSettlement>(`/transport/freight/${id}/approve`)
}
// =============================================================================
// 盘存统计 API
// =============================================================================
export interface InventoryRecord {
id: string
productId: string
brandId?: string
brandName?: 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
brandId?: string
brandName?: 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
brandId?: string
brandName?: 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 DocumentReminderStats {
expiredPendingCount: number
}
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 }),
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 }
),
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
brandId?: string
brandName?: string
lowStockWarning?: number
highStockWarning?: number
}) => request.post('/transport/inventory/warning-threshold', data),
documentReminders: (status?: string) =>
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: () =>
request.get<DocumentReminderStats>('/transport/inventory/document-reminders/stats'),
updateDocumentReminder: (id: string, data: { status: string; remark?: string }) =>
request.put<DocumentReminder>(`/transport/inventory/document-reminders/${id}`, data)
}
export interface PlMenuBadgeStats {
counts: Record<string, number>
}
export const menuBadgeApi = {
stats: (codes?: string[]) =>
request.get<PlMenuBadgeStats>('/transport/menu-badges/stats', {
params: codes?.length ? { codes: codes.join(',') } : undefined
})
}
// =============================================================================
// ETC/加油充值 API
// =============================================================================
export interface VehicleRechargeApply {
id: string
applyNo: string
licensePlate: string
rechargeType: 'etc' | 'fuel'
applyDate: string
odometerKm?: number | null
attachmentUrls?: string
applicantId: string
applicantName?: string
status: 'pending' | 'disbursed' | 'cancelled'
remark?: string
createTime?: string
updateTime?: string
}
export interface VehicleRechargeApplyListResponse {
items: VehicleRechargeApply[]
total: number
page: number
pageSize: number
}
export interface VehicleRechargeApplyOption {
id: string
applyNo: string
licensePlate: string
rechargeType: 'etc' | 'fuel'
}
export interface VehicleRechargeRecord {
id: string
rechargeOrderNo: string
rechargeDate: string
rechargeType: 'etc' | 'fuel'
cardNo?: string
gasStation?: string
amount: number
attachmentUrls?: string
applyId?: string
applyNo?: string
licensePlate?: string
remark?: string
createBy?: string
createByName?: string
createTime?: string
updateTime?: string
}
export interface VehicleRechargeRecordListResponse {
items: VehicleRechargeRecord[]
total: number
page: number
pageSize: number
}
export interface VehicleRechargeDisburseBoardItem {
applyId: string
applyNo: string
licensePlate: string
rechargeType: 'etc' | 'fuel'
applyDate: string
odometerKm?: number | null
applicantName?: string
applyStatus: 'pending' | 'disbursed' | 'cancelled'
applyRemark?: string
recordId?: string
rechargeOrderNo?: string
rechargeDate?: string
cardNo?: string
gasStation?: string
amount?: number | null
recordCreateByName?: string
recordRemark?: string
}
export interface VehicleRechargeDisburseBoardListResponse {
items: VehicleRechargeDisburseBoardItem[]
total: number
page: number
pageSize: number
}
export const vehicleRechargeApplyApi = {
list: (params?: Record<string, unknown>) =>
request.get<VehicleRechargeApplyListResponse>('/transport/vehicle-recharge-apply/', { params }),
export: (data: Record<string, any>) =>
request.post('/transport/vehicle-recharge-apply/export', data, { responseType: 'blob' }),
get: (id: string) => request.get<VehicleRechargeApply>(`/transport/vehicle-recharge-apply/${id}`),
create: (data: Partial<VehicleRechargeApply>) =>
request.post<VehicleRechargeApply>('/transport/vehicle-recharge-apply/', data),
update: (id: string, data: Partial<VehicleRechargeApply>) =>
request.put<VehicleRechargeApply>(`/transport/vehicle-recharge-apply/${id}`, data),
cancel: (id: string) =>
request.post<VehicleRechargeApply>(`/transport/vehicle-recharge-apply/${id}/cancel`),
delete: (ids: string) => request.delete(`/transport/vehicle-recharge-apply/${ids}`),
pendingOptions: () =>
request.get<VehicleRechargeApplyOption[]>('/transport/vehicle-recharge-apply/pending-options')
}
export const vehicleRechargeRecordApi = {
disburseBoard: (params?: Record<string, unknown>) =>
request.get<VehicleRechargeDisburseBoardListResponse>(
'/transport/vehicle-recharge-record/disburse-board',
{ params }
),
export: (data: Record<string, any>) =>
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}`),
create: (data: Partial<VehicleRechargeRecord>) =>
request.post<VehicleRechargeRecord>('/transport/vehicle-recharge-record/', data),
update: (id: string, data: Partial<VehicleRechargeRecord>) =>
request.put<VehicleRechargeRecord>(`/transport/vehicle-recharge-record/${id}`, data),
delete: (ids: string) => request.delete(`/transport/vehicle-recharge-record/${ids}`)
}
// =============================================================================
// 车辆维保 API
// =============================================================================
export interface VehicleMaintenanceApply {
id: string
applyNo: string
licensePlate: string
applicantId: string
applicantName?: string
applyDate: string
maintenanceType: string
startDate: string
expectedPickupDate?: string | null
maintenanceContent?: string
shopAddress?: string
attachmentUrls?: string
status: 'pending' | 'processed' | 'cancelled'
remark?: string
createTime?: string
updateTime?: string
}
export interface VehicleMaintenanceApplyListResponse {
items: VehicleMaintenanceApply[]
total: number
page: number
pageSize: number
}
export interface VehicleMaintenanceApplyReminder {
id: string
applyNo: string
licensePlate: string
maintenanceType: string
applyDate: string
startDate: string
expectedPickupDate?: string | null
maintenanceContent?: string
shopAddress?: string
}
export interface VehicleMaintenanceProcess {
id: string
processNo: string
applyId?: string
applyNo?: string
licensePlate?: string
amount?: number | null
handlerId: string
handlerName?: string
processDate: string
attachmentUrls?: string
remark?: string
createBy?: string
createByName?: string
createTime?: string
updateTime?: string
}
export interface VehicleMaintenanceProcessBoardItem {
applyId: string
applyNo: string
licensePlate: string
maintenanceType: string
applyDate: string
startDate: string
expectedPickupDate?: string | null
maintenanceContent?: string
shopAddress?: string
applicantName?: string
applyStatus: 'pending' | 'processed' | 'cancelled'
applyRemark?: string
processId?: string
processNo?: string
processDate?: string
amount?: number | null
handlerName?: string
processRemark?: string
}
export interface VehicleMaintenanceProcessBoardListResponse {
items: VehicleMaintenanceProcessBoardItem[]
total: number
page: number
pageSize: number
}
export const vehicleMaintenanceApplyApi = {
list: (params?: Record<string, unknown>) =>
request.get<VehicleMaintenanceApplyListResponse>('/transport/vehicle-maintenance-apply/', {
params
}),
export: (data: Record<string, any>) =>
request.post('/transport/vehicle-maintenance-apply/export', data, { responseType: 'blob' }),
get: (id: string) =>
request.get<VehicleMaintenanceApply>(`/transport/vehicle-maintenance-apply/${id}`),
create: (data: Partial<VehicleMaintenanceApply>) =>
request.post<VehicleMaintenanceApply>('/transport/vehicle-maintenance-apply/', data),
update: (id: string, data: Partial<VehicleMaintenanceApply>) =>
request.put<VehicleMaintenanceApply>(`/transport/vehicle-maintenance-apply/${id}`, data),
cancel: (id: string) =>
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 }
}
)
}
export const vehicleMaintenanceProcessApi = {
processBoard: (params?: Record<string, unknown>) =>
request.get<VehicleMaintenanceProcessBoardListResponse>(
'/transport/vehicle-maintenance-process/process-board',
{ params }
),
export: (data: Record<string, any>) =>
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>) =>
request.post<VehicleMaintenanceProcess>('/transport/vehicle-maintenance-process/', data),
update: (id: string, data: Partial<VehicleMaintenanceProcess>) =>
request.put<VehicleMaintenanceProcess>(`/transport/vehicle-maintenance-process/${id}`, data),
delete: (ids: string) => request.delete(`/transport/vehicle-maintenance-process/${ids}`)
}
// =============================================================================
// 车辆尿素 API
// =============================================================================
export interface VehicleUreaApply {
id: string
applyNo: string
licensePlate: string
applicantId: string
applicantName?: string
applyDate: string
warehouseInDate: string
unit: string
quantity: number
applyAmount: number
attachmentUrls?: string
status: 'pending' | 'disbursed' | 'cancelled'
remark?: string
createTime?: string
updateTime?: string
}
export interface VehicleUreaApplyListResponse {
items: VehicleUreaApply[]
total: number
page: number
pageSize: number
}
export interface VehicleUreaDisburse {
id: string
disburseNo: string
applyId?: string
applyNo?: string
licensePlate?: string
amount: number
handlerId: string
handlerName?: string
disburseDate: string
attachmentUrls?: string
remark?: string
createBy?: string
createByName?: string
createTime?: string
updateTime?: string
}
export interface VehicleUreaDisburseBoardItem {
applyId: string
applyNo: string
licensePlate: string
applyDate: string
warehouseInDate: string
unit: string
quantity: number
applyAmount: number
applicantName?: string
applyStatus: 'pending' | 'disbursed' | 'cancelled'
applyRemark?: string
disburseId?: string
disburseNo?: string
disburseDate?: string
amount?: number | null
handlerName?: string
disburseRemark?: string
}
export interface VehicleUreaDisburseBoardListResponse {
items: VehicleUreaDisburseBoardItem[]
total: number
page: number
pageSize: number
}
export const vehicleUreaApplyApi = {
list: (params?: Record<string, unknown>) =>
request.get<VehicleUreaApplyListResponse>('/transport/vehicle-urea-apply/', { params }),
export: (data: Record<string, any>) =>
request.post('/transport/vehicle-urea-apply/export', data, { responseType: 'blob' }),
get: (id: string) => request.get<VehicleUreaApply>(`/transport/vehicle-urea-apply/${id}`),
create: (data: Partial<VehicleUreaApply>) =>
request.post<VehicleUreaApply>('/transport/vehicle-urea-apply/', data),
update: (id: string, data: Partial<VehicleUreaApply>) =>
request.put<VehicleUreaApply>(`/transport/vehicle-urea-apply/${id}`, data),
cancel: (id: string) =>
request.post<VehicleUreaApply>(`/transport/vehicle-urea-apply/${id}/cancel`),
delete: (ids: string) => request.delete(`/transport/vehicle-urea-apply/${ids}`)
}
export const vehicleUreaDisburseApi = {
disburseBoard: (params?: Record<string, unknown>) =>
request.get<VehicleUreaDisburseBoardListResponse>(
'/transport/vehicle-urea-disburse/disburse-board',
{ params }
),
export: (data: Record<string, any>) =>
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),
update: (id: string, data: Partial<VehicleUreaDisburse>) =>
request.put<VehicleUreaDisburse>(`/transport/vehicle-urea-disburse/${id}`, data),
delete: (ids: string) => request.delete(`/transport/vehicle-urea-disburse/${ids}`)
}