fix: 修复匹配详情提示及公积金可选路径问题
修复匹配详情中“用户自填未经核验”等来源说明,清理未参与项的橙色注意提示,修正贷款统计口径文案;补充公积金完整可选路径提取逻辑,确保明确无额外时长要求的公积金分支可正确识别并通过。
This commit is contained in:
@@ -3,27 +3,51 @@ import { assessmentApiPayload, draftText } from '@/services/assessment.uts'
|
||||
import { assessmentRequestKey } from '@/services/assessment-flow.uts'
|
||||
import { contributionLabels, contributionCodes, contributionLabel } from '@/services/contribution.uts'
|
||||
import { yuanToWan } from '@/services/money.uts'
|
||||
import { provinceCodeForName } from '@/services/cities.uts'
|
||||
import { FinancingGradeView, financingGradeFrom } from '@/packages/finance/services/financing-grade.uts'
|
||||
|
||||
export type AssessmentRecord = { id: string, type: string, status: string, statusLabel: string, message: string, city: string, submittedAt: string, taskId: string, stage: string, canRetry: boolean, revisionId: string, revisionNo: number, hasReport: boolean, publishedRevisionId: string }
|
||||
export type AssessmentPage = { items: AssessmentRecord[], hasMore: boolean, nextCursor: string }
|
||||
export type AssessmentField = { label: string, value: string }
|
||||
export type ArchiveSection = { id: string, icon: string, title: string, note: string, fields: AssessmentField[], provided: number }
|
||||
export type AssessmentDetail = { record: AssessmentRecord, fields: AssessmentField[], sections: ArchiveSection[] }
|
||||
export type ArchiveCompleteness = { percent: number | null, description: string }
|
||||
export type ArchiveField = { fieldKey: string, label: string, value: string, isMissing: boolean }
|
||||
export type ArchiveSection = { id: string, icon: string, title: string, note: string, fields: ArchiveField[], provided: number }
|
||||
export type AssessmentDetail = { record: AssessmentRecord, fields: ArchiveField[], sections: ArchiveSection[] }
|
||||
export type ArchiveCompleteness = { assessmentId: string, revisionId: string, percent: number | null, description: string, notApplicableFields: string[] }
|
||||
|
||||
const archiveAmountKeys = ['totalDebtBalance', 'monthlyLoanPayment', 'creditCardTotalLimit', 'creditCardUsedLimit']
|
||||
|
||||
// 档案只消费报告中已保存的完整度,不用当前表单规则重算旧评估,也不把缺失当作0%。
|
||||
export async function fetchArchiveCompleteness(id: string, revisionId: string = ''): Promise<ArchiveCompleteness> {
|
||||
const report = await requestJson('/assessments/' + encodeURIComponent(id) + '/report', 'GET', revisionParams(revisionId))
|
||||
if (report.getString('assessmentId') != id) throw new Error('报告与当前档案不一致')
|
||||
if (revisionId.length > 0 && report.getString('revisionId') != revisionId) throw new Error('报告版本不一致,请重新选择。')
|
||||
if (report.getNumber('resultVersion') == 1) return { percent: null, description: '这份旧版报告未计算完整度,已提交资料仍可查看。' }
|
||||
const result: ArchiveCompleteness = { assessmentId: id, revisionId: draftText(report, 'revisionId'), percent: null, description: '这份报告尚未评定资料完整度。', notApplicableFields: [] }
|
||||
if (report.getNumber('resultVersion') == 1) { result.description = '这份旧版报告未计算完整度,已提交资料仍可查看。'; return result }
|
||||
if (report.getNumber('resultVersion') != 2) throw new Error('报告格式暂不支持')
|
||||
const completeness = report['completeness'] as UTSJSONObject | null
|
||||
if (completeness == null || completeness.getString('status') != 'evaluated') return { percent: null, description: '这份报告尚未评定资料完整度。' }
|
||||
if (completeness == null || completeness.getString('status') != 'evaluated') return result
|
||||
const percent = completeness.getNumber('percent')
|
||||
if (percent == null || !Number.isInteger(percent) || percent < 0 || percent > 100) throw new Error('完整度数据暂不可读取')
|
||||
return { percent, description: '反映本次评估时的资料填写情况,不代表信用评分或审批结果。' }
|
||||
result.percent = percent; result.description = '反映本次评估时的资料填写情况,不代表信用评分或审批结果。'
|
||||
const items = completeness['items'] as UTSJSONObject[] | null
|
||||
if (items != null && Array.isArray(items)) archiveAmountKeys.forEach((key: string) => {
|
||||
const matching = items.filter((item: UTSJSONObject): boolean => item != null && item['fieldKey'] == key)
|
||||
if (matching.length == 1 && matching[0]['state'] == 'not_applicable') result.notApplicableFields.push(key)
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
// 只投影同版报告已经保存的不适用项,原档案与编辑回填继续保留原值。
|
||||
export function archiveSections(detail: AssessmentDetail, completeness: ArchiveCompleteness | null): ArchiveSection[] {
|
||||
if (completeness == null || completeness.assessmentId != detail.record.id
|
||||
|| completeness.revisionId.length == 0 || completeness.revisionId != detail.record.revisionId) return detail.sections
|
||||
return detail.sections.map((section: ArchiveSection): ArchiveSection => ({
|
||||
id: section.id, icon: section.icon, title: section.title, note: section.note, provided: section.provided,
|
||||
fields: section.fields.map((field: ArchiveField): ArchiveField => {
|
||||
if (!field.isMissing || !archiveAmountKeys.includes(field.fieldKey) || !completeness!.notApplicableFields.includes(field.fieldKey)) return field
|
||||
return { fieldKey: field.fieldKey, label: field.label, value: '不适用', isMissing: field.isMissing }
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
function validAssessmentId(value: string): boolean { return /^[1-9][0-9]{0,9}$/.test(value) }
|
||||
@@ -112,6 +136,7 @@ export async function fetchAnalysisReport(id: string, revisionId: string = ''):
|
||||
let value = raw == null ? '未填写' : (typeof raw == 'number' ? (raw as number).toString() : draftText(fact, 'value'))
|
||||
if (fact['value'] != null && fact['unit'] == 'yuan') value = yuanToWan(value) + ' 万元'
|
||||
if (fact['value'] != null && fact['unit'] == 'month') value += ' 个月'
|
||||
if (fact['value'] != null && fact['unit'] == 'age') value += ' 岁'
|
||||
if (fact['state'] == 'invalid') value = '格式需核实'
|
||||
const enumLabels: UTSJSONObject = { six_months_plus: '连续缴纳6个月以上', under_six_months: '缴纳不足6个月', none: '无' }
|
||||
if (['socialSecurity', 'housingFund'].includes(draftText(fact, 'fieldKey'))) value = contributionLabel(value)
|
||||
@@ -194,15 +219,18 @@ export async function createAssessment(payload: UTSJSONObject): Promise<string>
|
||||
if (value.length > 0 && !/^[0-9]{1,4}$/.test(value)) throw new Error('数量与经营月数须为0至9999的整数')
|
||||
form[key] = value.length == 0 ? null : parseInt(value)
|
||||
})
|
||||
if (draftText(values, 'loanCountScope') == 'all_loans') form['loanCountScope'] = 'all_loans'
|
||||
form['maritalStatus'] = enumValue(draftText(values, 'maritalStatus'), ['已婚', '未婚', '离异', '丧偶'], ['married', 'single', 'divorced', 'widowed'])
|
||||
const socialKeys = ['socialSecurity', 'housingFund']
|
||||
socialKeys.forEach((key: string) => { form[key] = enumValue(draftText(values, key), contributionLabels, contributionCodes) })
|
||||
const ownershipKeys = ['house', 'car']
|
||||
ownershipKeys.forEach((key: string) => { form[key] = enumValue(draftText(values, key), ['有', '无'], ['yes', 'no']) })
|
||||
const provinceCode = provinceCodeForName(draftText(values, 'city').trim())
|
||||
const cityNames = ['深圳市', '广州市', '北京市', '上海市', '杭州市']
|
||||
const cityCodes = ['440300', '440100', '110100', '310100', '330100']
|
||||
const cityIndex = cityNames.indexOf(draftText(values, 'city'))
|
||||
form['cityCode'] = cityIndex < 0 ? null : cityCodes[cityIndex]
|
||||
form['cityCode'] = provinceCode != null || cityIndex < 0 ? null : cityCodes[cityIndex]
|
||||
if (provinceCode != null) form['provinceCode'] = provinceCode
|
||||
// 卡片资料单独保存,确认页明示暂不绑定评估;只发送自填信息,绝不把本机路径或附件送入分析。
|
||||
const body: UTSJSONObject = { inputVersion: 3, type: values['type'], moneyUnit: 'yuan', form, documents: [] as UTSJSONObject[], consentIds: [] as string[] }
|
||||
if (editId.length > 0) body['baseRevisionId'] = baseRevision
|
||||
@@ -252,7 +280,7 @@ export async function fetchAssessmentDetail(id: string, revisionId: string = '')
|
||||
const record = recordFrom(result, id, revisionId)
|
||||
const form = result['form'] as UTSJSONObject | null
|
||||
if (form == null) throw new Error('评估详情不完整')
|
||||
const fields: AssessmentField[] = []
|
||||
const fields: ArchiveField[] = []
|
||||
const enterprise = result['type'] == 'enterprise'
|
||||
const sections: ArchiveSection[] = [
|
||||
{ id: 'basic', icon: 'file-text', title: '基本信息', note: enterprise ? '企业与联系人信息' : '身份与联系方式', fields: [], provided: 0 },
|
||||
@@ -260,14 +288,16 @@ export async function fetchAssessmentDetail(id: string, revisionId: string = '')
|
||||
{ id: 'assets', icon: 'asset', title: '资产与负债', note: '贷款、信用卡额度与房车情况', fields: [], provided: 0 },
|
||||
{ id: 'authorization', icon: 'authorization', title: '资料与授权', note: '私有资料与外部查询授权', fields: [], provided: 0 }
|
||||
]
|
||||
const addField = (section: number, label: string, value: string, provided: boolean) => {
|
||||
const field: AssessmentField = { label, value }
|
||||
const addField = (section: number, fieldKey: string, label: string, value: string, provided: boolean, isMissing: boolean) => {
|
||||
const field: ArchiveField = { fieldKey, label, value, isMissing }
|
||||
fields.push(field); sections[section].fields.push(field)
|
||||
if (provided) sections[section].provided++
|
||||
}
|
||||
const keys = ['name', 'phone', 'city', 'idCard', 'enterpriseName', 'businessCode', 'occupation', 'company', 'operatingMonths', 'monthlyIncome', 'annualRevenue', 'creditLoanCount', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardCount', 'creditCardTotalLimit', 'creditCardUsedLimit', 'maritalStatus', 'socialSecurity', 'housingFund', 'house', 'car', 'socialSecurityBase', 'housingFundBase']
|
||||
const labels = ['姓名 / 联系人', '手机号', '城市', '身份证号', '企业名称', '信用代码', '职业 / 行业', '工作单位', '经营月数', '月收入', '年营收', '信用贷款笔数', '欠款总余额', '贷款月还款金额', '信用卡张数', '信用卡总额度', '信用卡已用额度', '婚姻状况', '社保缴纳', '公积金缴纳', '是否有房', '是否有车', '社保月缴存基数', '公积金月缴存基数']
|
||||
labels[11] = draftText(form, 'loanCountScope') == 'all_loans' ? '贷款笔数' : '信用贷款笔数(旧口径)'
|
||||
const moneyKeys = ['monthlyIncome', 'annualRevenue', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardTotalLimit', 'creditCardUsedLimit', 'socialSecurityBase', 'housingFundBase']
|
||||
if (form.getString('provinceCode') != null) labels[2] = '所在省份'
|
||||
const enumLabels: UTSJSONObject = { married: '已婚', single: '未婚', divorced: '离异', widowed: '丧偶', yes: '有', no: '无', six_months_plus: '连续缴纳6个月以上', under_six_months: '缴纳不足6个月', none: '未缴纳' }
|
||||
keys.forEach((key: string, index: number) => {
|
||||
const raw = form[key]
|
||||
@@ -282,7 +312,7 @@ export async function fetchAssessmentDetail(id: string, revisionId: string = '')
|
||||
const incomeKeys = ['occupation', 'company', 'operatingMonths', 'monthlyIncome', 'annualRevenue', 'socialSecurity', 'housingFund', 'socialSecurityBase', 'housingFundBase']
|
||||
const assetKeys = ['creditLoanCount', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardCount', 'creditCardTotalLimit', 'creditCardUsedLimit', 'house', 'car']
|
||||
// “无”及数值0都是已填写,不能用真值判断遗漏零负债、零经营月数。
|
||||
addField(incomeKeys.includes(key) ? 1 : (assetKeys.includes(key) ? 2 : 0), labels[index], value, raw != null && value.length > 0)
|
||||
addField(incomeKeys.includes(key) ? 1 : (assetKeys.includes(key) ? 2 : 0), key, labels[index], value, raw != null && value.length > 0, raw == null)
|
||||
})
|
||||
return { record, fields, sections }
|
||||
}
|
||||
@@ -300,6 +330,7 @@ export async function fetchAssessmentEdit(id: string): Promise<UTSJSONObject> {
|
||||
const form = result['form'] as UTSJSONObject | null
|
||||
if (form == null || Array.isArray(form) || typeof form != 'object' || result.getString('moneyUnit') != 'yuan') throw new Error('修改资料不完整,请返回档案重新读取。')
|
||||
const payload: UTSJSONObject = { type: result['type'], editAssessmentId: id, baseRevisionId: result['revisionId'], step: 0 }
|
||||
payload['loanCountScope'] = draftText(form, 'loanCountScope') == 'all_loans' ? 'all_loans' : ''
|
||||
const money = ['monthlyIncome', 'annualRevenue', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardTotalLimit', 'creditCardUsedLimit', 'socialSecurityBase', 'housingFundBase']
|
||||
const labels: UTSJSONObject = { married: '已婚', single: '未婚', divorced: '离异', widowed: '丧偶', yes: '有', no: '无', six_months_plus: '连续缴纳 6 个月以上', under_six_months: '缴纳不足 6 个月', none: '未缴纳' }
|
||||
const enums = ['maritalStatus', 'house', 'car', 'socialSecurity', 'housingFund']
|
||||
|
||||
Reference in New Issue
Block a user