feat: 完善协议缴费分期、样本编码搜索与鸿蒙附件选择

支持移动端样本编码远程关键字检索、分期起始日刷新与鸿蒙微信附件选取,并同步收款账户选择、角色页与相关设计文档。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-10-22 09:23:17 +08:00
1 parent 6e2656f999
commit 063727a7d8
45 files changed
+42669 -34713

No files matched your search

@@ -0,0 +1,23 @@
import { describe, it } from 'node:test'
import assert from 'node:assert/strict'
import { calcStandardFqDueDate } from './protocol-payment-installment'
describe('calcStandardFqDueDate', () => {
it('builds six periods as start, +1 year, then +half year', () => {
const start = '20261021'
assert.deepEqual(
[0, 1, 2, 3, 4, 5].map((i) => calcStandardFqDueDate(start, i)),
['20261021', '20271021', '20280421', '20281021', '20290421', '20291021']
)
})
it('clamps month-end when adding half a year', () => {
assert.equal(calcStandardFqDueDate('20260831', 2), '20280229')
assert.equal(calcStandardFqDueDate('20260831', 1), '20270831')
})
it('returns empty for an invalid start date', () => {
assert.equal(calcStandardFqDueDate('', 0), '')
assert.equal(calcStandardFqDueDate('2026-10-21', -1), '')
})
})
@@ -215,6 +215,30 @@ export function calcFqInstallmentDueDate(
return base
}
/** 按日历加月,月末超出时落到该月最后一天 */
function addCalendarMonthsYmd(dateStr: string, months: number): string {
const compact = String(dateStr || '').replace(/-/g, '')
if (compact.length !== 8 || !Number.isFinite(months)) return ''
const y = Number(compact.slice(0, 4))
const monthIndex = Number(compact.slice(4, 6)) - 1 + Math.trunc(months)
const ny = y + Math.floor(monthIndex / 12)
const nm = monthIndex % 12
const lastDay = new Date(ny, nm + 1, 0).getDate()
const nd = Math.min(Number(compact.slice(6, 8)), lastDay)
return `${ny}${String(nm + 1).padStart(2, '0')}${String(nd).padStart(2, '0')}`
}
/**
* 分期默认应缴日(与每期间隔、提前天数无关):
* 第 1 期 = 开始日,第 2 期 = 第 1 期 + 1 年,第 3 期起每期在上一期基础上 + 半年。
*/
export function calcStandardFqDueDate(startDate: string, index: number): string {
const start = String(startDate || '').replace(/-/g, '')
if (start.length !== 8 || !Number.isInteger(index) || index < 0) return ''
if (index === 0) return start
return addCalendarMonthsYmd(start, 12 + (index - 1) * 6)
}
export function calcInstallmentDueAmounts(
contractAmount: number | null | undefined,
count: number