feat(pl): 运费结算审批分流与车辆挂车号等 PL 能力完善

拆分运费审批/出款页面,补充结算发票附件与菜单 SQL,并同步前后端模型与车辆相关展示。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-06-28 21:00:31 +08:00
1 parent 66d5a8714b
commit 98aec80d71
37 files changed
+1362 -195

No files matched your search

+7 -2
View File
@@ -6,11 +6,16 @@ const SITE_INSTRUCTION = '说明:请打开链接上传现场附件并填写备
type SiteSummaryRecord = {
productName?: string
productText?: string
batchNo?: string
planNo?: string
siteUrl?: string
}
function formatSiteSummaryProductLine(record: SiteSummaryRecord) {
return record.productText || record.productName || '—'
}
export function buildSiteSummaryFromInventoryLinks(options: {
planNo?: string
licensePlate?: string
@@ -33,13 +38,13 @@ export function buildSiteSummaryFromInventoryLinks(options: {
if (validRecords.length === 1) {
const record = validRecords[0]
lines.push(`产品:${record.productName || '—'}`)
lines.push(`产品:${formatSiteSummaryProductLine(record)}`)
if (record.batchNo) lines.push(`出入库单号:${record.batchNo}`)
lines.push(`现场链接:${record.siteUrl}`)
} else {
lines.push('')
validRecords.forEach((record, index) => {
lines.push(`【${index + 1}】${record.productName || '产品'}`)
lines.push(`【${index + 1}】${formatSiteSummaryProductLine(record)}`)
if (record.batchNo) lines.push(`出入库单号:${record.batchNo}`)
lines.push(`现场链接:${record.siteUrl}`)
if (index < validRecords.length - 1) lines.push('')
@@ -6,6 +6,24 @@ export type AttachmentDownloadItem = {
fileName?: string
}
/** 将 JSON 数组或逗号分隔的附件 URL 统一为逗号分隔字符串 */
export function normalizeAttachmentUrls(raw?: string | null): string {
if (!raw) return ''
const trimmed = String(raw).trim()
if (!trimmed) return ''
if (trimmed.startsWith('[')) {
try {
const parsed = JSON.parse(trimmed)
if (Array.isArray(parsed)) {
return parsed.map((url) => String(url).trim()).filter(Boolean).join(',')
}
} catch {
/* ignore */
}
}
return trimmed
}
function triggerAnchorDownload(href: string, fileName: string) {
const a = document.createElement('a')
a.href = href
+13 -2
View File
@@ -51,6 +51,14 @@ export function getPlanProductQuantity(product: {
return String(qty)
}
export function getPlanProductPlannedQuantity(product: {
quantity?: number | string | null
}) {
const qty = product.quantity
if (qty === undefined || qty === null || qty === '') return '—'
return String(qty)
}
export function formatPlanProductListText(
product: {
productName?: string
@@ -62,11 +70,14 @@ export function formatPlanProductListText(
inboundEstimateQty?: number | string | null
outboundEstimateQty?: number | string | null
},
getUnitLabel?: (unit: string) => string
getUnitLabel?: (unit: string) => string,
options?: { usePlannedQuantity?: boolean }
) {
const name = product.productName || '—'
const spec = getPlanProductSpec(product)
const qty = getPlanProductQuantity(product)
const qty = options?.usePlannedQuantity
? getPlanProductPlannedQuantity(product)
: getPlanProductQuantity(product)
const unitRaw = product.unit || ''
const unit = unitRaw ? (getUnitLabel ? getUnitLabel(unitRaw) || unitRaw : unitRaw) : ''