提交
This commit is contained in:
1 parent
135dd550b6
commit
2a4767a014
76 files changed
+25160
-2306
No files matched your search
@@ -0,0 +1,135 @@
|
||||
/** 分期缴费:期数对齐、应缴日/金额计算(与 ProtocolFormDialog 逻辑一致) */
|
||||
|
||||
export function addMonthsYmd(dateStr: string, months: number): string {
|
||||
const compact = String(dateStr || '').replace(/-/g, '')
|
||||
if (compact.length !== 8) return ''
|
||||
const y = parseInt(compact.slice(0, 4), 10)
|
||||
const m = parseInt(compact.slice(4, 6), 10) - 1
|
||||
const d = parseInt(compact.slice(6, 8), 10)
|
||||
const date = new Date(y, m + months, d)
|
||||
const yy = date.getFullYear()
|
||||
const mm = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const dd = String(date.getDate()).padStart(2, '0')
|
||||
return `${yy}${mm}${dd}`
|
||||
}
|
||||
|
||||
export function calcInstallmentDueAmounts(
|
||||
contractAmount: number | null | undefined,
|
||||
count: number
|
||||
): number[] {
|
||||
if (contractAmount == null || !count || count < 1) return []
|
||||
const totalCents = Math.round(Number(contractAmount) * 100)
|
||||
const baseCents = Math.floor(totalCents / count)
|
||||
const amounts: number[] = []
|
||||
let sumCents = 0
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (i === count - 1) {
|
||||
amounts.push((totalCents - sumCents) / 100)
|
||||
} else {
|
||||
amounts.push(baseCents / 100)
|
||||
sumCents += baseCents
|
||||
}
|
||||
}
|
||||
return amounts
|
||||
}
|
||||
|
||||
type PaymentLike = Record<string, unknown> | null | undefined
|
||||
type DetailLike = Record<string, any>
|
||||
|
||||
/**
|
||||
* 分期模式下按 installmentCount 补齐缺失期次(保留已有明细数据),仅用于编辑表单。
|
||||
*/
|
||||
export function alignFqPaymentDetailsForDisplay(
|
||||
payment: PaymentLike,
|
||||
details: DetailLike[]
|
||||
): DetailLike[] {
|
||||
if (!payment || payment.payMode !== 'fq') return details
|
||||
const count = Number(payment.installmentCount)
|
||||
if (!count || count < 1) return details
|
||||
|
||||
const rows = [...details]
|
||||
const byNo = new Map<number, DetailLike>()
|
||||
const unnumbered: DetailLike[] = []
|
||||
for (const row of rows) {
|
||||
const no = row.installmentNo
|
||||
if (no != null && no !== '') {
|
||||
byNo.set(Number(no), row)
|
||||
} else {
|
||||
unnumbered.push(row)
|
||||
}
|
||||
}
|
||||
|
||||
const needed = new Set(Array.from({ length: count }, (_, i) => i + 1))
|
||||
const have = new Set(byNo.keys())
|
||||
let missing = false
|
||||
for (const n of needed) {
|
||||
if (!have.has(n)) {
|
||||
missing = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!missing && rows.length >= count) {
|
||||
return sortFqPaymentDetails(rows).slice(0, count)
|
||||
}
|
||||
|
||||
const contract = payment.contractAmount != null ? Number(payment.contractAmount) : null
|
||||
const amounts = calcInstallmentDueAmounts(contract, count)
|
||||
const startDate = String(payment.installmentStartDate || '')
|
||||
const interval = Number(payment.installmentIntervalMonths || 0)
|
||||
|
||||
const result: DetailLike[] = []
|
||||
for (let i = 0; i < count; i++) {
|
||||
const no = i + 1
|
||||
if (byNo.has(no)) {
|
||||
result.push(byNo.get(no)!)
|
||||
continue
|
||||
}
|
||||
if (i < unnumbered.length) {
|
||||
const raw = { ...unnumbered[i], installmentNo: no }
|
||||
if (!raw.installmentDueDate && startDate && interval) {
|
||||
raw.installmentDueDate = addMonthsYmd(startDate, i * interval)
|
||||
}
|
||||
result.push(raw)
|
||||
continue
|
||||
}
|
||||
result.push({
|
||||
installmentNo: no,
|
||||
installmentDueDate:
|
||||
startDate && interval ? addMonthsYmd(startDate, i * interval) : '',
|
||||
dueAmount: amounts[i] ?? null,
|
||||
payStatus: 'dfj',
|
||||
transferType: '',
|
||||
transferAmount: null,
|
||||
attachments: []
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export function sortFqPaymentDetails(details: DetailLike[]): DetailLike[] {
|
||||
return [...details].sort((a, b) => {
|
||||
const na = a.installmentNo != null && a.installmentNo !== '' ? Number(a.installmentNo) : 9999
|
||||
const nb = b.installmentNo != null && b.installmentNo !== '' ? Number(b.installmentNo) : 9999
|
||||
if (na !== nb) return na - nb
|
||||
return Number(a.orderNum || 0) - Number(b.orderNum || 0)
|
||||
})
|
||||
}
|
||||
|
||||
/** 编辑表单:将缴费明细行数与分期期数对齐(不覆盖已有行) */
|
||||
export function syncFqPaymentDetailRowCount(
|
||||
payment: {
|
||||
payMode: string
|
||||
installmentCount: number | null
|
||||
contractAmount: number | null
|
||||
installmentStartDate: string
|
||||
installmentIntervalMonths: number | null
|
||||
},
|
||||
paymentDetails: DetailLike[]
|
||||
): void {
|
||||
if (payment.payMode !== 'fq') return
|
||||
const count = Number(payment.installmentCount)
|
||||
if (!count || count < 1) return
|
||||
|
||||
const aligned = alignFqPaymentDetailsForDisplay(payment, paymentDetails)
|
||||
paymentDetails.splice(0, paymentDetails.length, ...aligned)
|
||||
}
|
||||
@@ -78,5 +78,5 @@ export function formatPaymentAmount(v: unknown) {
|
||||
if (v == null || v === '') return '-'
|
||||
const n = Number(v)
|
||||
if (Number.isNaN(n)) return String(v)
|
||||
return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
||||
return '¥' + n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
export function workOrderStatusLabel(v: string) {
|
||||
const m: Record<string, string> = {
|
||||
dpz: '待配置',
|
||||
ypz: '已配置',
|
||||
ywc: '已完成'
|
||||
}
|
||||
return m[v] || v || '—'
|
||||
}
|
||||
|
||||
export function taskTypeLabel(v: string) {
|
||||
const m: Record<string, string> = {
|
||||
sysz: '实验室自检',
|
||||
dsfjc: '第三方检测'
|
||||
}
|
||||
return m[v] || v || '—'
|
||||
}
|
||||
|
||||
export function taskStatusLabel(v: string) {
|
||||
const m: Record<string, string> = {
|
||||
dzx: '待执行',
|
||||
jxz: '进行中',
|
||||
ywc: '已完成'
|
||||
}
|
||||
return m[v] || v || '—'
|
||||
}
|
||||
Reference in new issue
Block a user