/** * 运输计划管理 API */ 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 { 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>('/transport/carrier', { params }), get: (id: string) => request.get(`/transport/carrier/${id}`), create: (data: Partial) => request.post('/transport/carrier', data), update: (id: string, data: Partial) => request.put(`/transport/carrier/${id}`, data), /** @deprecated 承运商审核已移除,后端接口已禁用 */ approve: (id: string) => request.post(`/transport/carrier/${id}/approve`), reject: (id: string, data?: { remark?: string }) => request.post(`/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 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 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>('/transport/vehicle', { params }), get: (id: string) => request.get(`/transport/vehicle/${id}`), create: (data: VehiclePayload) => request.post('/transport/vehicle', data), update: (id: string, data: Partial) => request.put(`/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 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 certList?: CertRow[] } export interface PersonnelQuery { q?: string status?: string personnelAffiliation?: string page?: number pageSize?: number } export const personnelApi = { list: (params?: PersonnelQuery) => request.get>('/transport/personnel', { params }), get: (id: string) => request.get(`/transport/personnel/${id}`), create: (data: PersonnelPayload) => request.post('/transport/personnel', data), update: (id: string, data: Partial) => request.put(`/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('/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('/transport/paste-recognize/commit', data) } // 运输通用地址库 export interface TransportAddress { id: string addressName: string fullAddress: string lng: number lat: number contactName?: string contactPhone?: 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 status?: string remark?: string } export const transportAddressApi = { list: (params?: TransportAddressQuery) => request.get>('/transport/address', { params }), listAll: (params?: { q?: string }) => request.get>('/transport/address/all', { params }), get: (id: string) => request.get(`/transport/address/${id}`), create: (data: TransportAddressPayload) => request.post('/transport/address', data), update: (id: string, data: Partial) => request.put(`/transport/address/${id}`, data), delete: (id: string) => request.delete(`/transport/address/${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 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): 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, page: params?.page, pageSize: params?.pageSize }) const { list, total } = pickBxPageResult(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) => { 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) => { 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 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 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 pickupLng?: number | null pickupLat?: number | null pickupTime?: string pickupNotes?: string destinationAddress?: string destinationLng?: number | null destinationLat?: number | null deliveryTime?: 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 notifyMessage?: string followUserId?: string followUserName?: string hazardCertReady?: number hazardCertReadyBy?: string hazardCertReadyTime?: string remark?: string createBy?: string createTime: string products?: PlanProduct[] } export interface PlanQuery { q?: string planNo?: string planType?: string followStatus?: string transportStatus?: string archiveStatus?: string customerName?: string productName?: 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 pickupLng?: number | null pickupLat?: number | null pickupTime?: string pickupNotes?: string destinationAddress?: string destinationLng?: number | null destinationLat?: number | null 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> export interface PlanArchiveProductItem { id: string actualQty: number } export interface PlanArchiveFreightBlock { hasFreight: number distanceKm?: number freightType?: string freightPrice?: number freightAmount?: number transportQty?: number hasInvoice?: number } export interface PlanArchiveBody { products: PlanArchiveProductItem[] freight?: PlanArchiveFreightBlock } export interface PlanDriverFeedbackUpdateBody { feedbackQty?: number | null feedbackRemark?: string | null feedbackImages?: string[] feedbackTime?: string | null } export interface PlanSiteFeedbackUpdateBody { siteFeedbackRemark?: string | null siteFeedbackImages?: string[] siteFeedbackTime?: string | null } export const planApi = { list: (params?: PlanQuery) => request.get('/transport/plan/', { params }), get: (id: string) => request.get(`/transport/plan/${id}`), countByContract: (contractIds: string[]) => request.get<{ counts: Record }>('/transport/plan/count-by-contract', { params: { contractIds: contractIds.join(',') } }), create: (data: Partial) => request.post('/transport/plan/', data), createFull: (data: PlanCreateFullPayload) => request.post('/transport/plan/create-full', data), update: (id: string, data: PlanUpdatePayload) => request.put(`/transport/plan/${id}`, data), updateProductCerts: ( id: string, products: Array<{ id: string purchaseCertUrl?: string transportCertUrl?: string legalUseCertUrl?: string }> ) => request.patch(`/transport/plan/${id}/product-certs`, { products }), setHazardCertReady: (id: string, ready: boolean) => request.patch(`/transport/plan/${id}/hazard-cert-ready`, { ready }), cancel: (id: string) => request.post(`/transport/plan/${id}/cancel`), getArrangeInfo: (id: string) => request.get(`/transport/plan/${id}/arrange-info`), archive: (id: string, data?: PlanArchiveBody) => request.post(`/transport/plan/${id}/archive`, data), updateDriverFeedback: (id: string, data: PlanDriverFeedbackUpdateBody) => request.patch(`/transport/plan/${id}/driver-feedback`, data), updateSiteFeedback: (id: string, linkId: string, data: PlanSiteFeedbackUpdateBody) => request.patch(`/transport/plan/${id}/site-feedback/${linkId}`, data), delete: (id: string) => request.delete(`/transport/plan/${id}`), createFromContract: (data: { contractId: string; planDate: string; followUserId?: string; followUserName?: string }) => request.post('/transport/plan/create-from-contract', data), getInboundSlipTemplate: (id: string) => request.get(`/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(`/transport/plan/${id}/delivery-slip-template`), saveDeliverySlipTemplate: (id: string, slipTemplateContent: string) => request.put(`/transport/plan/${id}/delivery-slip-template`, { slipTemplateContent }), getSubpackSlipTemplate: (id: string) => request.get(`/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(`/transport/plan/${id}/subpack-slip-no`) } // ============================================================================= // 运输管理 API // ============================================================================= 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 remark?: string createTime: string } export interface TransportArrange { vehicleId: string driverId: string carrierId?: string transportMedium?: string pickupAddress?: string pickupLng?: number | null pickupLat?: number | null pickupTime?: string pickupNotes?: string destinationAddress?: string destinationLng?: number | null destinationLat?: number | null 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 TransportIoOrderBrief { kind: string orderId: string orderNo: string siteAccessToken?: string siteUrl?: string status?: string } export interface PlanArrangeInfo { 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 } export interface PlIoOrderItem { id: string orderId: string planProductId: string productId?: string productNo?: string productName?: string specification?: string unit?: string unitLabel?: string planQty?: number actualQty?: number qtySource?: string packageSpec?: 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 pickupNotes?: string destinationName?: string destinationAddress?: string destinationLng?: number | null destinationLat?: number | null deliveryTime?: 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 page?: number pageSize?: number } export interface PlIoOrderListResponse { total: number list: PlIoOrder[] } export const inboundOrderApi = { list: (params?: PlIoOrderQuery) => request.get('/transport/inbound/', { params }), get: (id: string) => request.get(`/transport/inbound/${id}`), getByPlan: (planId: string) => request.get(`/transport/inbound/by-plan/${planId}`), patch: (id: string, data: Record) => request.patch(`/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('/transport/outbound/', { params }), get: (id: string) => request.get(`/transport/outbound/${id}`), getByPlan: (planId: string) => request.get(`/transport/outbound/by-plan/${planId}`), patch: (id: string, data: Record) => request.patch(`/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('/transport/order/', { params }), get: (id: string) => request.get(`/transport/order/${id}`), create: (data: Partial & { planIds?: string[] }) => request.post('/transport/order/', data), arrange: (planId: string, data: TransportArrange) => request.post(`/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/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(`/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 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 } 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('/transport/freight/unsettled-plans', { params }), getByTransport: (transportId: string) => request.get(`/transport/freight/by-transport/${transportId}`), list: (params?: FreightSettlementQuery) => request.get('/transport/freight/', { params }), get: (id: string) => request.get(`/transport/freight/${id}`), create: (data: { planIds?: string[]; transportIds?: string[] }) => request.post('/transport/freight/', data), update: (id: string, data: FreightSettlementUpdateBody) => request.put(`/transport/freight/${id}`, data), cancel: (id: string) => request.post(`/transport/freight/${id}/cancel`), delete: (id: string) => request.delete(`/transport/freight/${id}`), submitApproval: (id: string, data: FreightSettlementSubmitBody) => request.post(`/transport/freight/${id}/submit-approval`, data), processApproval: (approvalId: string, data: FreightSettlementApprovalBody) => request.post(`/transport/freight/approval/${approvalId}`, data), withdrawApproval: (id: string) => request.post(`/transport/freight/${id}/withdraw-approval`), getApprovalFlow: (id: string) => request.get(`/transport/freight/${id}/approval-flow`), disburse: (id: string, data: FreightSettlementDisburseBody) => request.post(`/transport/freight/${id}/disburse`, data), /** @deprecated 请使用 submitApproval */ submit: (id: string) => request.post(`/transport/freight/${id}/submit`), /** @deprecated 请使用 processApproval */ approve: (id: string) => request.post(`/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 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('/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('/transport/inventory/warnings', { params: { status } }), updateWarning: (id: string, data: { status: string; resolveRemark?: string }) => request.put(`/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('/transport/inventory/document-reminders', { params: { status } }), documentReminderStats: () => request.get('/transport/inventory/document-reminders/stats'), updateDocumentReminder: (id: string, data: { status: string; remark?: string }) => request.put(`/transport/inventory/document-reminders/${id}`, data) } export interface PlMenuBadgeStats { counts: Record } export const menuBadgeApi = { stats: (codes?: string[]) => request.get('/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) => request.get('/transport/vehicle-recharge-apply/', { params }), get: (id: string) => request.get(`/transport/vehicle-recharge-apply/${id}`), create: (data: Partial) => request.post('/transport/vehicle-recharge-apply/', data), update: (id: string, data: Partial) => request.put(`/transport/vehicle-recharge-apply/${id}`, data), cancel: (id: string) => request.post(`/transport/vehicle-recharge-apply/${id}/cancel`), delete: (ids: string) => request.delete(`/transport/vehicle-recharge-apply/${ids}`), pendingOptions: () => request.get('/transport/vehicle-recharge-apply/pending-options') } export const vehicleRechargeRecordApi = { disburseBoard: (params?: Record) => request.get( '/transport/vehicle-recharge-record/disburse-board', { params } ), list: (params?: Record) => request.get('/transport/vehicle-recharge-record/', { params }), get: (id: string) => request.get(`/transport/vehicle-recharge-record/${id}`), create: (data: Partial) => request.post('/transport/vehicle-recharge-record/', data), update: (id: string, data: Partial) => request.put(`/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) => request.get('/transport/vehicle-maintenance-apply/', { params }), get: (id: string) => request.get(`/transport/vehicle-maintenance-apply/${id}`), create: (data: Partial) => request.post('/transport/vehicle-maintenance-apply/', data), update: (id: string, data: Partial) => request.put(`/transport/vehicle-maintenance-apply/${id}`, data), cancel: (id: string) => request.post(`/transport/vehicle-maintenance-apply/${id}/cancel`), delete: (ids: string) => request.delete(`/transport/vehicle-maintenance-apply/${ids}`), reminders: (licensePlate: string, excludeApplyId?: string) => request.get('/transport/vehicle-maintenance-apply/reminders', { params: { licensePlate, excludeApplyId } }) } export const vehicleMaintenanceProcessApi = { processBoard: (params?: Record) => request.get( '/transport/vehicle-maintenance-process/process-board', { params } ), get: (id: string) => request.get(`/transport/vehicle-maintenance-process/${id}`), create: (data: Partial) => request.post('/transport/vehicle-maintenance-process/', data), update: (id: string, data: Partial) => request.put(`/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) => request.get('/transport/vehicle-urea-apply/', { params }), get: (id: string) => request.get(`/transport/vehicle-urea-apply/${id}`), create: (data: Partial) => request.post('/transport/vehicle-urea-apply/', data), update: (id: string, data: Partial) => request.put(`/transport/vehicle-urea-apply/${id}`, data), cancel: (id: string) => request.post(`/transport/vehicle-urea-apply/${id}/cancel`), delete: (ids: string) => request.delete(`/transport/vehicle-urea-apply/${ids}`) } export const vehicleUreaDisburseApi = { disburseBoard: (params?: Record) => request.get( '/transport/vehicle-urea-disburse/disburse-board', { params } ), get: (id: string) => request.get(`/transport/vehicle-urea-disburse/${id}`), create: (data: Partial) => request.post('/transport/vehicle-urea-disburse/', data), update: (id: string, data: Partial) => request.put(`/transport/vehicle-urea-disburse/${id}`, data), delete: (ids: string) => request.delete(`/transport/vehicle-urea-disburse/${ids}`) }