Files
airz-uniapp/services/assessment.uts
T
hujun e5406c23a6 fix: 修复匹配详情提示及公积金可选路径问题
修复匹配详情中“用户自填未经核验”等来源说明,清理未参与项的橙色注意提示,修正贷款统计口径文案;补充公积金完整可选路径提取逻辑,确保明确无额外时长要求的公积金分支可正确识别并通过。
2026-10-19 16:11:59 +08:00

156 lines
12 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { getSession } from './api.uts'
import { readAssessmentFlow, writeAssessmentFlow, clearAssessmentFlow } from './assessment-flow.uts'
export { clearAssessmentFlow } from './assessment-flow.uts'
import { contributionBaseVisible, contributionBaseValid, contributionBaseYuan } from './contribution.uts'
import { wanAmountValid, wanToYuan, wanToCents } from './money.uts'
import { showAgreementNotice as openAgreementNotice } from './agreements.uts'
export type AssessmentForm = {
name: string, idCard: string, phone: string, city: string, maritalStatus: string,
occupation: string, company: string, monthlyIncome: string, socialSecurity: string,
housingFund: string, socialSecurityBase: string, housingFundBase: string, house: string, car: string, savings: string, creditCard: string,
creditLoanCount: string, loanCountScope: string, totalDebtBalance: string, monthlyLoanPayment: string,
creditCardCount: string, creditCardTotalLimit: string, creditCardUsedLimit: string,
otherAssets: string, enterpriseName: string, businessCode: string, annualRevenue: string, operatingYears: string, operatingMonths: string
}
export type SelectedDocument = { name: string, path: string, documentId: string, consentId: string, deletePending: boolean }
export type DataAuthorization = { key: string, name: string, selected: boolean }
export function emptyAssessmentForm(): AssessmentForm {
return { name: '', idCard: '', phone: '', city: '', maritalStatus: '', occupation: '', company: '', monthlyIncome: '', socialSecurity: '', housingFund: '', socialSecurityBase: '', housingFundBase: '', house: '', car: '', savings: '', creditCard: '', otherAssets: '', creditLoanCount: '', loanCountScope: 'all_loans', totalDebtBalance: '', monthlyLoanPayment: '', creditCardCount: '', creditCardTotalLimit: '', creditCardUsedLimit: '', enterpriseName: '', businessCode: '', annualRevenue: '', operatingYears: '', operatingMonths: '' }
}
export function draftText(saved: UTSJSONObject, key: string): string {
const value = saved[key]
return typeof value == 'string' ? value as string : ''
}
function flowToken(): string { const session = getSession(); return session == null ? '' : session['token'] as string }
export function activeAssessmentType(): string {
const current = readAssessmentFlow(flowToken())
return current == null ? 'personal' : draftText(current, 'type')
}
export function getAssessmentInput(type: string): UTSJSONObject | null {
const current = readAssessmentFlow(flowToken())
return current != null && current['type'] == type ? current : null
}
export function assessmentApiPayload(saved: UTSJSONObject): UTSJSONObject {
const normalized = saved
const result: UTSJSONObject = { ...normalized, moneyUnit: 'yuan' }
const keys = ['annualRevenue', 'monthlyIncome', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardTotalLimit', 'creditCardUsedLimit']
keys.forEach((key) => {
const value = draftText(normalized, key)
result[key] = value.length > 0 ? wanToYuan(value) : ''
})
const baseKeys = ['socialSecurityBase', 'housingFundBase']
baseKeys.forEach((key) => { const value = draftText(normalized, key); result[key] = value.length > 0 ? contributionBaseYuan(value) : '' })
return result
}
export function formFromInput(saved: UTSJSONObject): AssessmentForm {
return {
name: draftText(saved, 'name'), idCard: draftText(saved, 'idCard'), phone: draftText(saved, 'phone'), city: draftText(saved, 'city'), maritalStatus: draftText(saved, 'maritalStatus'),
occupation: draftText(saved, 'occupation'), company: draftText(saved, 'company'), monthlyIncome: draftText(saved, 'monthlyIncome'), socialSecurity: draftText(saved, 'socialSecurity'), housingFund: draftText(saved, 'housingFund'), socialSecurityBase: draftText(saved, 'socialSecurityBase'), housingFundBase: draftText(saved, 'housingFundBase'),
house: ownershipFromInput(saved, 'house'), car: ownershipFromInput(saved, 'car'), savings: draftText(saved, 'savings'), creditCard: draftText(saved, 'creditCard'), otherAssets: draftText(saved, 'otherAssets'),
creditLoanCount: draftText(saved, 'creditLoanCount'), loanCountScope: draftText(saved, 'loanCountScope') == 'all_loans' ? 'all_loans' : '', totalDebtBalance: draftText(saved, 'totalDebtBalance'), monthlyLoanPayment: draftText(saved, 'monthlyLoanPayment'),
creditCardCount: draftText(saved, 'creditCardCount'), creditCardTotalLimit: draftText(saved, 'creditCardTotalLimit'), creditCardUsedLimit: draftText(saved, 'creditCardUsedLimit'),
enterpriseName: draftText(saved, 'enterpriseName'), businessCode: draftText(saved, 'businessCode'), annualRevenue: draftText(saved, 'annualRevenue'), operatingYears: draftText(saved, 'operatingYears'), operatingMonths: draftText(saved, 'operatingMonths')
}
}
export function ownershipFromInput(saved: UTSJSONObject, key: string): string {
const value = draftText(saved, key)
if (value == '有' || value == '无') return value
if (value == '无房产' || value == '无车辆') return '无'
if (['全款房产', '按揭房产', '全款车辆', '按揭车辆'].includes(value)) return '有'
return ''
}
export function contributionValidationMessage(form: AssessmentForm): string {
const bases = [form.socialSecurityBase, form.housingFundBase]
const durations = [form.socialSecurity, form.housingFund]
const labels = ['社保', '公积金']
for (let i = 0; i < bases.length; i++) {
if (bases[i].length == 0) continue
if (!contributionBaseVisible(durations[i])) return labels[i] + '基数须与缴纳情况一致'
if (!contributionBaseValid(bases[i])) return labels[i] + '基数请输入大于 0 的万元金额,最多六位小数'
}
return ''
}
export function assetValidationMessage(form: AssessmentForm): string {
const counts = [form.creditLoanCount, form.creditCardCount]
const countLabels = ['贷款笔数', '银行信用卡张数']
for (let i = 0; i < counts.length; i++) {
if (counts[i].length > 0 && !/^[0-9]{1,4}$/.test(counts[i])) return countLabels[i] + '请输入非负整数'
}
const amounts = [form.totalDebtBalance, form.monthlyLoanPayment, form.creditCardTotalLimit, form.creditCardUsedLimit]
const amountLabels = ['欠款总余额', '贷款月还款金额', '总额度', '已使用总额度']
for (let i = 0; i < amounts.length; i++) {
if (amounts[i].length > 0 && !wanAmountValid(amounts[i])) return amountLabels[i] + '范围为 0–99999.999999 万元,最多六位小数'
}
if (form.creditLoanCount.length > 0 && form.loanCountScope != 'all_loans') return '历史贷款笔数仅统计信用贷款,请按全部未结清贷款重新确认'
if (form.loanCountScope == 'all_loans' && /^0{1,4}$/.test(form.creditLoanCount)
&& [form.totalDebtBalance, form.monthlyLoanPayment].some((value) => value.length > 0 && wanToCents(value) > 0)) return '贷款笔数为 0 时,欠款总余额和贷款月还款金额不能大于 0'
if (/^0{1,4}$/.test(form.creditCardCount)
&& [form.creditCardTotalLimit, form.creditCardUsedLimit].some((value) => value.length > 0 && wanToCents(value) > 0)) return '信用卡张数为 0 时,总额度和已使用总额度不能大于 0'
if (form.creditCardTotalLimit.length > 0 && form.creditCardUsedLimit.length > 0 && wanToCents(form.creditCardUsedLimit) > wanToCents(form.creditCardTotalLimit)) return '信用卡已使用额度不能大于总额度'
return ''
}
// 仅计算空金额是否适用;不补零、不更改任何已填内容,矛盾或无效金额不豁免同组字段。
export function assetNotApplicableFields(form: AssessmentForm): string[] {
const fields: string[] = []
const loanAmounts = [form.totalDebtBalance, form.monthlyLoanPayment]
if (form.loanCountScope == 'all_loans' && /^0{1,4}$/.test(form.creditLoanCount)
&& loanAmounts.every((value) => value.length == 0 || (wanAmountValid(value) && wanToCents(value) == 0))) {
if (form.totalDebtBalance.length == 0) fields.push('totalDebtBalance')
if (form.monthlyLoanPayment.length == 0) fields.push('monthlyLoanPayment')
}
const cardAmounts = [form.creditCardTotalLimit, form.creditCardUsedLimit]
if (/^0{1,4}$/.test(form.creditCardCount)
&& cardAmounts.every((value) => value.length == 0 || (wanAmountValid(value) && wanToCents(value) == 0))) {
if (form.creditCardTotalLimit.length == 0) fields.push('creditCardTotalLimit')
if (form.creditCardUsedLimit.length == 0) fields.push('creditCardUsedLimit')
}
return fields
}
export function documentsFromInput(saved: UTSJSONObject): SelectedDocument[] {
const results: SelectedDocument[] = []
const items = saved['documents'] as UTSJSONObject[] | null
if (items == null) return results
items.forEach((item) => {
const name = draftText(item, 'name'); const path = draftText(item, 'path')
const documentId = draftText(item, 'documentId'); const consentId = draftText(item, 'consentId')
if (name.length > 0 && (path.length > 0 || documentId.length > 0)) {
const document: SelectedDocument = { name, path, documentId, consentId, deletePending: item.getBoolean('deletePending') ?? false }; results.push(document)
}
})
return results
}
export function setAssessmentInput(type: string, step: number, form: AssessmentForm, documents: SelectedDocument[], authorizations: DataAuthorization[], documentConsent: boolean, dataConsent: boolean, editAssessmentId: string = '', baseRevisionId: string = ''): void {
const files: UTSJSONObject[] = documents.map((item): UTSJSONObject => ({ name: item.name, path: '', documentId: item.documentId, consentId: item.consentId, deletePending: item.deletePending }))
const grants: string[] = authorizations.filter((item) => item.selected).map((item) => item.key)
const payload: UTSJSONObject = {
type, step, editAssessmentId, baseRevisionId, moneyUnit: 'wan', name: form.name, idCard: form.idCard, phone: form.phone, city: form.city, maritalStatus: form.maritalStatus,
occupation: form.occupation, company: form.company, monthlyIncome: form.monthlyIncome, socialSecurity: form.socialSecurity, housingFund: form.housingFund, socialSecurityBase: form.socialSecurityBase, housingFundBase: form.housingFundBase,
house: form.house, car: form.car, savings: form.savings, creditCard: form.creditCard, otherAssets: form.otherAssets,
creditLoanCount: form.creditLoanCount, loanCountScope: form.loanCountScope, totalDebtBalance: form.totalDebtBalance, monthlyLoanPayment: form.monthlyLoanPayment,
creditCardCount: form.creditCardCount, creditCardTotalLimit: form.creditCardTotalLimit, creditCardUsedLimit: form.creditCardUsedLimit,
enterpriseName: form.enterpriseName, businessCode: form.businessCode, annualRevenue: form.annualRevenue, operatingYears: form.operatingYears, operatingMonths: form.operatingMonths,
documents: files, authorizations: grants, documentConsent, dataConsent
}
writeAssessmentFlow(flowToken(), payload)
}
export function showAgreementNotice(title: string): void {
openAgreementNotice(title)
}
export type AssessmentProgress = { percent: number, basicDone: boolean, incomeDone: boolean, assetsDone: boolean, authorizationSelected: boolean }
export function assessmentProgress(type: string): AssessmentProgress {
const saved = getAssessmentInput(type)
if (saved == null) return { percent: 0, basicDone: false, incomeDone: false, assetsDone: false, authorizationSelected: false }
const basic = type == 'enterprise' ? ['enterpriseName', 'businessCode', 'name', 'phone', 'city'] : ['name', 'idCard', 'phone', 'city', 'maritalStatus']
const income = type == 'enterprise' ? ['occupation', 'operatingMonths', 'annualRevenue'] : ['occupation', 'company', 'monthlyIncome', 'socialSecurity', 'housingFund']
const form = formFromInput(saved)
const notApplicable = assetNotApplicableFields(form)
const assets = ['house', 'car', 'creditLoanCount', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardCount', 'creditCardTotalLimit', 'creditCardUsedLimit'].filter((key) => !notApplicable.includes(key))
const keys = basic.concat(income).concat(assets)
const filled = keys.filter((key) => draftText(saved, key).trim().length > 0).length
const grants = saved['authorizations'] as string[] | null
return { percent: Math.round(filled / keys.length * 100), basicDone: basic.every((key) => draftText(saved, key).length > 0), incomeDone: income.every((key) => draftText(saved, key).length > 0), assetsDone: assets.every((key) => draftText(saved, key).trim().length > 0) && assetValidationMessage(form).length == 0, authorizationSelected: documentsFromInput(saved).length > 0 || (grants != null && grants.length > 0) }
}