feat: 保存运输证件、报销付款和开发流程的当前实现。

补齐证书齐备、证件折算、移动用证和合同绑定,并带上报销批量发放、付款备注以及个人开发流程升级,便于继续讨论已安排计划的调整规则。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
wuzilongandCursor committed 2026-11-04 21:42:33 +08:00
1 parent 7325a0aa52
commit 8e9536332a
202 files changed
+19200 -2054

No files matched your search

+14
View File
@@ -267,6 +267,13 @@ export const paymentApi = {
pay(id: BxId, data?: { payRemark?: string; actualAmount?: number }) {
return bxRequest.post(`/payments/${id}/pay`, data)
},
batchPay(data: {
payRemark?: string
items: Array<{ id: BxId; actualAmount: number }>
attachmentIds?: Array<BxId>
}) {
return bxRequest.post('/payments/batch-pay', data)
},
offset(id: BxId, data: { advanceId: BxId; offsetAmount: number; remark?: string }) {
return bxRequest.post(`/payments/${id}/offset`, data)
},
@@ -304,6 +311,13 @@ export const paymentApi = {
issueAdvance(advanceId: BxId, data: { issueRemark?: string; actualAmount?: number }) {
return bxRequest.post(`/payments/advance/${advanceId}/issue`, data)
},
batchIssueAdvance(data: {
issueRemark?: string
items: Array<{ id: BxId; actualAmount: number }>
attachmentIds?: Array<BxId>
}) {
return bxRequest.post('/payments/advance/batch-issue', data)
},
advanceOffsetRecords(advanceId: BxId) {
return bxRequest.get(`/payments/advance/${advanceId}/offset-records`)
},
+8 -5
View File
@@ -740,7 +740,7 @@ export interface PlanCreateFullPayload {
followUserId?: string
followUserName?: string
remark?: string
saveMode?: 'draft' | 'formal'
saveMode?: 'draft' | 'formal' | 'rearrange'
supplierContracts?: PlanContractLink[]
demanderContracts?: PlanContractLink[]
load?: PlanLoad
@@ -1043,8 +1043,10 @@ export const planApi = {
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),
archive: (id: string, data?: PlanArchiveBody, config?: { skipErrorMessage?: boolean }) =>
request.post<Plan>(`/transport/plan/${id}/archive`, data, config),
markQuotaCertReady: (id: string) =>
request.post(`/transport/plan/${id}/quota-cert-ready`, {}, { skipErrorMessage: true }),
archiveDraft: (id: string, data: PlanArchiveBody) =>
request.post<Plan>(`/transport/plan/${id}/archive-draft`, data),
updateDriverFeedback: (id: string, data: PlanDriverFeedbackUpdateBody) =>
@@ -2288,9 +2290,10 @@ export const vehicleFuelRegisterApi = {
{},
{ params }
),
plateMonthSummary: () =>
plateMonthSummary: (month?: string) =>
request.get<VehicleFuelPlateMonthSummaryResponse>(
'/transport/vehicle-fuel-register/plate-month-summary'
'/transport/vehicle-fuel-register/plate-month-summary',
{ params: month ? { month } : undefined }
)
}
+131 -10
View File
@@ -20,7 +20,7 @@ export interface CertBody {
validUseText: string
entryMode: 'manual' | 'image_parse'
attachmentUrls?: string | null
status?: 'draft' | 'suspended' | 'void'
status?: 'draft' | 'suspended' | 'closed' | 'void'
remark?: string | null
orderNum?: number | null
buyerName?: string | null
@@ -49,7 +49,7 @@ export interface CertBody {
}
export interface QuotaCert extends Omit<CertBody, 'status'> {
id: string
status: 'draft' | 'active' | 'suspended' | 'void'
status: 'draft' | 'active' | 'suspended' | 'closed' | 'void'
bindingsEditable?: boolean
referencesEditable?: boolean
revision: number
@@ -60,6 +60,7 @@ export interface QuotaCert extends Omit<CertBody, 'status'> {
openingConfirmed: boolean
usagePolicy: 'once' | 'multiple' | 'needs_confirmation'
createTime?: string
certType?: CertType
}
export interface ScopeProduct {
id?: string
@@ -83,14 +84,24 @@ export interface ContractOption {
contractNo: string
contractName: string
contractType?: string
customerId?: string
customerName?: string
status?: string
signDate?: string | null
productSummary?: string
}
export interface ContractProduct {
id: string
productId: string
productName: string
productNo?: string
categoryName?: string
brandName?: string
model?: string
unit?: string
quantity?: string | number
packageSpec?: string
deliveryMethod?: string
}
export interface LegalDocument {
id: string
@@ -141,13 +152,22 @@ export const quotaCertApi = {
verify: (kind: CertType, id: string, body: { operationId: string; reason: string }) =>
request.post(`${base}/${kind}/${id}/verify`, body).then(pickBxData<QuotaCert>),
recognize: (kind: CertType, attachmentUrl: string) =>
request.post(`${base}/${kind}/recognize`, { attachmentUrl }, { timeout: 90000 }).then(
pickBxData<{
candidates: Partial<CertBody>
invalidFields: Record<string, string>
requiresConfirmation: boolean
}>
),
request
.post(
`${base}/${kind}/recognize`,
{ attachmentUrl },
{
timeout: 90000,
skipErrorMessage: true
}
)
.then(
pickBxData<{
candidates: Partial<CertBody>
invalidFields: Record<string, string>
requiresConfirmation: boolean
}>
),
contracts: (keyword = '') =>
request.get(`${base}/contracts`, { params: { keyword } }).then(pickBxData<ContractOption[]>),
products: (id: string) =>
@@ -184,11 +204,17 @@ export interface StopLegalDocument {
planNo: string
planDate?: string
licensePlate?: string
productNames?: string
supplierName?: string
customerName?: string
followStatus?: string
transportStatus: string
archiveStatus: string
requiredCount: number
uploadedCount: number
documentStatus: 'pending' | 'uploaded' | 'not_required'
legalUseCertUrl?: string | null
planProductIds?: string[]
items: StopLegalDocumentItem[]
legacyProducts: {
id: string
@@ -202,6 +228,14 @@ export const legalDocumentApi = {
listStops: (params: {
keyword?: string
planNo?: string
planDateFrom?: string
planDateTo?: string
licensePlate?: string
productNames?: string
supplierName?: string
customerName?: string
followStatusIn?: string
progress?: string
status?: 'pending' | 'uploaded'
contractId?: string
page?: number
@@ -244,6 +278,7 @@ export interface QuotaSourceOption {
sourceStopProductId: string
planProductId: string
productName: string
productNo?: string
model?: string
quantity: string | number
unit: string
@@ -288,6 +323,8 @@ export interface PlanQuota {
planNo: string
licensePlate?: string
canSaveConfiguration?: boolean
arrangeBlockMessage?: string
quotaCertWaived?: boolean
configuration: Partial<QuotaConfiguration>
sourceOptions: QuotaSourceOption[]
usages: Record<string, any>[]
@@ -317,8 +354,54 @@ export interface QuotaPreview extends Partial<QuotaContext> {
purchaseAllocations?: Record<string, any>[]
transportAllocations?: Record<string, any>[]
}
export interface CertReadyPlan {
id: string
planNo: string
planDate?: string | null
licensePlate?: string | null
supplierName?: string | null
customerName?: string | null
productNames?: string
followStatus?: string | null
quotaCertWaived: boolean
quotaCertWaivedByName?: string | null
quotaCertWaivedTime?: string | null
}
export const certReadyApi = {
list: (params: {
keyword?: string
waived?: string
planNo?: string
planDateFrom?: string
planDateTo?: string
licensePlate?: string
productNames?: string
supplierName?: string
customerName?: string
followStatusIn?: string
quotaCertWaivedIn?: string
quotaCertWaivedByName?: string
quotaCertWaivedTimeFrom?: string
quotaCertWaivedTimeTo?: string
page: number
pageSize: number
}) =>
request
.get(`${base}/plans/cert-ready`, { params })
.then(pickBxData<{ total: number; list: CertReadyPlan[] }>),
mark: (id: string) =>
request.post(`${base}/plans/${id}/cert-ready`).then(pickBxData<CertReadyPlan>)
}
export const planQuotaApi = {
get: (id: string) => request.get(`${base}/plans/${id}/usage`).then(pickBxData<PlanQuota>),
get: (id: string, arrangeCheck = false) =>
request
.get(
`${base}/plans/${id}/usage`,
arrangeCheck ? { params: { arrangeCheck: true } } : undefined
)
.then(pickBxData<PlanQuota>),
context: (id: string, body: QuotaConfiguration & QuotaPreviewVehicle) =>
request.post(`${base}/plans/${id}/context`, body).then(pickBxData<QuotaContext>),
preview: (id: string, body: QuotaConfiguration & QuotaPreviewVehicle) =>
@@ -380,6 +463,9 @@ export interface CertificateStatisticsSummary {
status: string
validFrom: string | null
validTo: string | null
salePartyName?: string | null
buyPartyName?: string | null
validUseText?: string | null
}
export interface StatisticsProduct {
id: string
@@ -399,6 +485,7 @@ export interface StatisticsBinding {
bindingId: string | null
linkStatus: string | null
scopeRevision: number | null
referenced?: boolean
contractReservedQty: QuotaQuantity
contractUsedQty: QuotaQuantity
products: StatisticsProduct[]
@@ -435,11 +522,45 @@ export interface CertificateStatistics extends CertificateStatisticsSummary {
}
export interface StatisticsQuery {
contractNo?: string
contractName?: string
contractTypeIn?: string
certCountOp?: string
certCount?: string
certCountMin?: string
certCountMax?: string
certNo?: string
keyword?: string
page?: number
pageSize?: number
certType?: CertType
certTypeIn?: string
productNameOnCert?: string
quantityUnitIn?: string
statusIn?: string
validFromFrom?: string
validFromTo?: string
validToFrom?: string
validToTo?: string
totalQtyOp?: string
totalQty?: string
totalQtyMin?: string
totalQtyMax?: string
reservedQtyOp?: string
reservedQty?: string
reservedQtyMin?: string
reservedQtyMax?: string
usedQtyOp?: string
usedQty?: string
usedQtyMin?: string
usedQtyMax?: string
availableQtyOp?: string
availableQty?: string
availableQtyMin?: string
availableQtyMax?: string
salePartyName?: string
buyPartyName?: string
validUseText?: string
expiryAlertIn?: string
}
export const quotaStatisticsApi = {
contracts: (params: StatisticsQuery) =>