refactor(login): move match-route logic to dedicated service and fix import

- 提取登录回跳、产品对比的路由匹配逻辑至独立的 match-route.uts 服务
- 修复登录页面导入对比服务的错误,改为导入新的 match-route 模块
- 保持原有的路由参数校验和跳转逻辑不变,仅重构代码结构
This commit is contained in:
hujun
2026-10-12 09:28:09 +08:00
parent 25cb06b71c
commit b418969e92
39 changed files with 49277 additions and 119 deletions
+3 -30
View File
@@ -1,21 +1,11 @@
import { getSession } from '@/services/api.uts'
import { validRecordId, MatchDetail, MatchReason } from './matches.uts'
import { MatchDetail, MatchReason } from './matches.uts'
import { parseCompareIds } from '@/services/match-route.uts'
export { parseCompareIds, compareQuery, matchReturnPath } from '@/services/match-route.uts'
let scope = ''
let selected: string[] = []
export function parseCompareIds(raw: string): string[] {
if (raw.length == 0) return []
const ids = raw.split(',')
if (ids.length > 3) throw new Error('每次最多对比3个产品,请返回重新选择。')
const seen: string[] = []
ids.forEach((id: string) => {
if (!validRecordId(id) || seen.includes(id)) throw new Error('对比产品编号无效或重复,请返回重新选择。')
seen.push(id)
})
return ids
}
// 只缓存少量选择ID,不持久化产品或个人事实;换账号、会话或评估后立即隔离。
export function compareSelection(assessmentId: string, revisionId: string = ''): string[] {
const session = getSession()
@@ -27,23 +17,6 @@ export function saveCompareSelection(assessmentId: string, ids: string[], revisi
compareSelection(assessmentId, revisionId)
selected = parseCompareIds(ids.join(','))
}
export function compareQuery(assessmentId: string, ids: string[], revisionId: string = ''): string {
return '?assessmentId=' + encodeURIComponent(assessmentId) + '&productIds=' + ids.join(',') + (revisionId.length > 0 ? '&revisionId=' + revisionId : '')
}
// 登录回跳只接受已声明页面与编号,不接受任意URL。
export function matchReturnPath(page: string, assessmentId: string, rawIds: string, revisionId: string, productId: string = '', group: string = 'eligible', tab: string = 'explanation', from: string = ''): string {
if (!['matches','product','compare'].includes(page) || (revisionId.length > 0 && !validRecordId(revisionId))) return ''
if (assessmentId.length > 0 ? !validRecordId(assessmentId) : page != 'product') return ''
let ids: string[] = []
try { ids = parseCompareIds(rawIds) } catch (err) { return '' }
if (assessmentId.length == 0 && (revisionId.length > 0 || ids.length > 0)) return ''
if (page == 'matches' && !['eligible','ineligible','unknown'].includes(group)) return ''
if (page == 'product' && (!validRecordId(productId) || !['explanation','details','conditions'].includes(tab) || (assessmentId.length == 0 && tab == 'explanation') || !['','matches','product','compare','report','next-step','archive'].includes(from))) return ''
const query = assessmentId.length > 0 ? compareQuery(assessmentId, ids, revisionId) : '?'
if (page == 'matches') return '/packages/finance/matches/matches' + query + '&group=' + group
if (page == 'compare') return '/packages/finance/compare/compare' + query
return '/packages/finance/product/product' + query + (assessmentId.length > 0 ? '&' : '') + 'productId=' + productId + '&tab=' + tab + '&from=' + from
}
export function sameMatchSnapshot(a: MatchDetail, b: MatchDetail): boolean {
return a.assessmentId == b.assessmentId && a.revisionId == b.revisionId && a.resultVersion == b.resultVersion && a.snapshotId == b.snapshotId && a.ruleVersion == b.ruleVersion && a.orderingVersion == b.orderingVersion
}
@@ -0,0 +1,43 @@
export type FinancingDimension = { key: string, label: string, score: number, maximum: number, basis: string }
export type FinancingGradeView = { status: string, grade: string, label: string, score: string, weightedScore: string, capacityScore: number, completenessPercent: number, capacityWeight: number, completenessWeight: number, dimensions: FinancingDimension[], limitations: string[], notice: string }
// 只读取该版报告保存的等级;旧报告不借用当前规则在客户端补算。
export function financingGradeFrom(raw: UTSJSONObject | null): FinancingGradeView {
const empty: FinancingGradeView = { status: 'unavailable', grade: '', label: '本次未评级', score: '', weightedScore: '', capacityScore: 0, completenessPercent: 0, capacityWeight: 80, completenessWeight: 20, dimensions: [], limitations: [], notice: '这份报告未计算综合等级,可重新评估获取。' }
if (raw == null) return empty
const fail = (): void => { throw new Error('融资等级数据暂不可读取,请重新加载。') }
const status = raw.getString('status') ?? ''
if (!['evaluated', 'insufficient_data', 'needs_verification', 'policy_unconfirmed'].includes(status) || raw.getString('verificationStatus') != 'not_verified' || (raw.getString('policyVersion') ?? '').length == 0) fail()
empty.status = status
empty.label = raw.getString('label') ?? '本次未评级'
empty.notice = raw.getString('notice') ?? ''
const limitations = raw['limitations'] as string[] | null
if (limitations == null || !Array.isArray(limitations) || limitations.some((item: string): boolean => typeof item != 'string')) fail()
empty.limitations = limitations!
if (status != 'evaluated') {
if (raw['grade'] != null || raw['score'] != null) fail()
return empty
}
const grade = raw.getString('grade') ?? ''
const score = raw.getString('score') ?? ''
const weighted = raw.getString('weightedScore') ?? ''
const capacity = raw.getNumber('capacityScore'); const complete = raw.getNumber('completenessPercent')
const capacityWeight = raw.getNumber('capacityWeight'); const completeWeight = raw.getNumber('completenessWeight')
if (!['A+', 'A', 'A-', 'B+', 'B', 'B-', 'C+', 'C', 'C-', 'D+', 'D', 'D-'].includes(grade)
|| !/^(?:100|[1-9]?[0-9])\.[0-9]{2}$/.test(score) || !/^(?:100|[1-9]?[0-9])\.[0-9]{2}$/.test(weighted) || parseFloat(score) > 100 || parseFloat(weighted) > 100 || parseFloat(score) > parseFloat(weighted)
|| capacity == null || !Number.isInteger(capacity) || capacity < 0 || capacity > 100 || complete == null || !Number.isInteger(complete) || complete < 0 || complete > 100
|| capacityWeight == null || completeWeight == null || !Number.isInteger(capacityWeight) || !Number.isInteger(completeWeight) || capacityWeight < 1 || completeWeight < 1 || capacityWeight + completeWeight != 100) fail()
const dimensions = raw['dimensions'] as UTSJSONObject[] | null
if (dimensions == null || !Array.isArray(dimensions) || dimensions.length != 5) fail()
const keys: string[] = []
let sum = 0; let maximumSum = 0
empty.dimensions = dimensions!.map((item: UTSJSONObject): FinancingDimension => {
const key = item.getString('key') ?? ''; const points = item.getNumber('score'); const maximum = item.getNumber('maximum')
if (!['repayment', 'debt', 'income', 'supplement', 'assets'].includes(key) || keys.includes(key) || points == null || maximum == null || !Number.isInteger(points) || !Number.isInteger(maximum) || points < 0 || points > maximum || maximum < 1) fail()
keys.push(key); sum += points!; maximumSum += maximum!
return { key, label: item.getString('label') ?? '', score: points!, maximum: maximum!, basis: item.getString('basis') ?? '' }
})
if (sum != capacity || maximumSum != 100) fail()
empty.grade = grade; empty.score = score; empty.weightedScore = weighted; empty.capacityScore = capacity!; empty.completenessPercent = complete!; empty.capacityWeight = capacityWeight!; empty.completenessWeight = completeWeight!
return empty
}
+57 -13
View File
@@ -1,7 +1,9 @@
import { getSession, requestJson } from '@/services/api.uts'
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 { 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 }
@@ -44,10 +46,48 @@ export async function retryAssessment(id: string, requestId: string): Promise<vo
}
export type ReportMatching = { status: string, snapshotId: string, ruleVersion: string, orderingVersion: string, eligible: string, ineligible: string, unknown: string }
export type AnalysisReport = { revisionId: string, revisionNo: number, isPreviousResult: boolean, currentStatus: string, version: number, generatedAt: string, completenessPercent: number | null, matching: ReportMatching, summary: string, facts: AssessmentField[], observations: string[], suggestions: string[], suggestionSummaries: string[], dataGaps: string[], disclaimer: string, matchingMessage: string, modelCode: string, demand: AssessmentField[], completenessText: string, completenessItems: AssessmentField[], readinessLabel: string, readinessBasis: string[], warnings: string[] }
export type AnalysisReport = { revisionId: string, revisionNo: number, isPreviousResult: boolean, currentStatus: string, version: number, generatedAt: string, completenessPercent: number | null, matching: ReportMatching, summary: string, facts: AssessmentField[], observations: string[], suggestions: string[], priorityItems: string[], dataGaps: string[], disclaimer: string, matchingMessage: string, modelCode: string, demand: AssessmentField[], completenessText: string, completenessItems: AssessmentField[], readinessLabel: string, readinessBasis: string[], warnings: string[], financingGrade: FinancingGradeView }
function reportPriorityItems(improvements: UTSJSONObject[], fields: UTSJSONObject[], basis: UTSJSONObject[]): string[] {
const items: string[] = []; const covered: string[] = []
// 仅用冻结证据中的明确问题标识合并;普通事实引用不表示同一个问题。
improvements.forEach((item: UTSJSONObject) => {
const text = draftText(item, 'text').trim()
if (text.length == 0) return
const keys: string[] = []
const refs = item['evidenceRefs'] as string[]
refs.forEach((ref: string) => {
let related: string[] = []
if (ref.startsWith('fact:')) {
const field = fields.find((entry: UTSJSONObject): boolean => draftText(entry, 'fieldKey') == ref.slice(5))
if (field != null && ['missing', 'invalid'].includes(draftText(field, 'state'))) related = [draftText(field, 'state') + ':' + ref.slice(5)]
} else if (ref.startsWith('readiness:')) {
const entry = basis.find((value: UTSJSONObject): boolean => draftText(value, 'basisId') == ref.slice(10))
if (entry != null && ['MISSING_FIELD', 'INVALID_FIELD'].includes(draftText(entry, 'code'))) {
const kind = draftText(entry, 'code') == 'MISSING_FIELD' ? 'missing' : 'invalid'
related = (entry['fieldRefs'] as string[]).map((key: string): string => kind + ':' + key)
} else if (entry != null && (entry['issueRefs'] as string[]).length > 0) related = [ref]
}
related.forEach((key: string) => { if (!keys.includes(key)) keys.push(key) })
})
if (!items.includes(text) && (keys.length == 0 || keys.some((key: string): boolean => !covered.includes(key)))) items.push(text)
keys.forEach((key: string) => { if (!covered.includes(key)) covered.push(key) })
})
fields.forEach((field: UTSJSONObject) => {
const state = draftText(field, 'state'); const key = state + ':' + draftText(field, 'fieldKey')
const label = draftText(field, 'label').trim()
if (!['missing', 'invalid'].includes(state) || covered.includes(key) || label.length == 0) return
const text = (state == 'missing' ? '补充' : '核实') + label
if (!items.includes(text)) items.push(text)
covered.push(key)
})
return items
}
export async function fetchAnalysisReport(id: string, revisionId: string = ''): Promise<AnalysisReport> {
const result = await requestJson('/assessments/' + encodeURIComponent(id) + '/report', 'GET', revisionParams(revisionId))
const version = result['resultVersion'] as number
const financingGrade = financingGradeFrom(version == 2 ? result['financingGrade'] as UTSJSONObject | null : null)
if (revisionId.length > 0 && result.getString('revisionId') != revisionId) throw new Error('报告版本不一致,请重新选择。')
if (result['assessmentId'] != id || (version != 1 && version != 2) || (version == 1 && result['reportType'] != 'self_reported_analysis') || (version == 2 && result['reportType'] != 'financing_needs_analysis')) throw new Error('报告格式不支持')
const date = new Date(draftText(result, 'generatedAt'))
@@ -74,6 +114,7 @@ export async function fetchAnalysisReport(id: string, revisionId: string = ''):
if (fact['value'] != null && fact['unit'] == 'month') 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)
if (enumLabels[value] != null) value = enumLabels[value] as string
// v2的需求在独立区块展示,避免用途代码和同一金额重复出现。
if (version == 2 && ['requestedAmountYuan', 'requestedTermMonths', 'purposeCode'].includes(draftText(fact, 'fieldKey'))) return
@@ -108,17 +149,18 @@ export async function fetchAnalysisReport(id: string, revisionId: string = ''):
}).filter((label: string): boolean => label.length > 0)
return draftText(item, 'text') + (labels.length > 0 ? '(依据:' + labels.join(';') + ')' : '')
})
return { revisionId: draftText(result, 'revisionId'), revisionNo: result.getNumber('revisionNo') ?? 1, isPreviousResult: result.getBoolean('isPreviousResult') ?? false, currentStatus: draftText(result, 'currentStatus'), version, generatedAt, completenessPercent, matching, summary: draftText(result, 'summary'), facts, observations: explain('strengths'), suggestions: explain('improvements'), suggestionSummaries: (result['improvements'] as UTSJSONObject[]).map((item: UTSJSONObject): string => draftText(item, 'text')), dataGaps: explain('riskWarnings'),
return { revisionId: draftText(result, 'revisionId'), revisionNo: result.getNumber('revisionNo') ?? 1, isPreviousResult: result.getBoolean('isPreviousResult') ?? false, currentStatus: draftText(result, 'currentStatus'), version, generatedAt, completenessPercent, matching, summary: draftText(result, 'summary'), facts, observations: explain('strengths'), suggestions: explain('improvements'), priorityItems: reportPriorityItems(result['improvements'] as UTSJSONObject[], items, basis), dataGaps: explain('riskWarnings'),
// 新报告展示服务端冻结结果的统计;旧报告无此字段时保留原提示,不重算历史。
disclaimer: draftText(result, 'disclaimer'), matchingMessage: draftText(result, 'matchingMessage').length > 0 ? draftText(result, 'matchingMessage') : '产品资料及匹配规则尚未就绪,本报告未执行产品匹配。', modelCode: draftText(result, 'modelCode'),
demand, completenessText, completenessItems, readinessLabel: readiness['status'] == 'evaluated' ? draftText(readiness, 'label') : '未评定',
demand, completenessText, completenessItems, financingGrade, readinessLabel: readiness['status'] == 'evaluated' ? draftText(readiness, 'label') : '未评定',
readinessBasis: basis.map((item: UTSJSONObject): string => draftText(item, 'message')), warnings: result['systemWarnings'] as string[] }
}
const observations = (result['observations'] as UTSJSONObject[]).map((item: UTSJSONObject): string => {
const fact = rawFacts.find((entry: UTSJSONObject): boolean => entry['id'] == item['factId'])
return (fact == null ? '' : draftText(fact, 'label') + ':') + draftText(item, 'text')
})
return { revisionId: draftText(result, 'revisionId'), revisionNo: result.getNumber('revisionNo') ?? 1, isPreviousResult: result.getBoolean('isPreviousResult') ?? false, currentStatus: draftText(result, 'currentStatus'), version, generatedAt, completenessPercent: null, matching, summary: draftText(result, 'summary'), facts, observations, suggestions: result['suggestions'] as string[], suggestionSummaries: result['suggestions'] as string[], dataGaps: result['dataGaps'] as string[], disclaimer: draftText(result, 'disclaimer'), matchingMessage: draftText(result, 'matchingMessage'), modelCode: draftText(result, 'modelCode'), demand: [], completenessText: '旧版报告未计算资料完整度', completenessItems: [], readinessLabel: '未评定', readinessBasis: [], warnings: [] }
const legacySuggestions = (result['suggestions'] as string[]).map((text: string): string => text.trim())
return { revisionId: draftText(result, 'revisionId'), revisionNo: result.getNumber('revisionNo') ?? 1, isPreviousResult: result.getBoolean('isPreviousResult') ?? false, currentStatus: draftText(result, 'currentStatus'), version, generatedAt, completenessPercent: null, matching, summary: draftText(result, 'summary'), facts, observations, suggestions: result['suggestions'] as string[], priorityItems: legacySuggestions.filter((text: string, index: number): boolean => text.length > 0 && legacySuggestions.indexOf(text) == index), dataGaps: result['dataGaps'] as string[], disclaimer: draftText(result, 'disclaimer'), matchingMessage: draftText(result, 'matchingMessage'), modelCode: draftText(result, 'modelCode'), demand: [], completenessText: '旧版报告未计算资料完整度', completenessItems: [], readinessLabel: '未评定', readinessBasis: [], warnings: [], financingGrade }
}
function enumValue(value: string, labels: string[], codes: string[]): string | null {
@@ -140,7 +182,7 @@ export async function createAssessment(payload: UTSJSONObject): Promise<string>
const values = assessmentApiPayload(payload)
const form = new UTSJSONObject()
const textKeys = ['name', 'idCard', 'phone', 'city', 'occupation', 'company', 'enterpriseName', 'businessCode']
const moneyKeys = ['monthlyIncome', 'annualRevenue', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardTotalLimit', 'creditCardUsedLimit']
const moneyKeys = ['monthlyIncome', 'annualRevenue', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardTotalLimit', 'creditCardUsedLimit', 'socialSecurityBase', 'housingFundBase']
textKeys.concat(moneyKeys).forEach((key: string) => { const value = draftText(values, key).trim(); form[key] = value.length == 0 ? null : value })
if (form['idCard'] != null) form['idCard'] = (form['idCard'] as string).toUpperCase()
if (form['businessCode'] != null) form['businessCode'] = (form['businessCode'] as string).toUpperCase()
@@ -152,7 +194,7 @@ export async function createAssessment(payload: UTSJSONObject): Promise<string>
})
form['maritalStatus'] = enumValue(draftText(values, 'maritalStatus'), ['已婚', '未婚', '离异', '丧偶'], ['married', 'single', 'divorced', 'widowed'])
const socialKeys = ['socialSecurity', 'housingFund']
socialKeys.forEach((key: string) => { form[key] = enumValue(draftText(values, key), ['连续缴纳 6 个月以上', '缴纳不足 6 个月', '未缴纳'], ['six_months_plus', 'under_six_months', 'none']) })
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 cityNames = ['深圳市', '广州市', '北京市', '上海市', '杭州市']
@@ -221,20 +263,21 @@ export async function fetchAssessmentDetail(id: string, revisionId: string = '')
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']
const labels = ['姓名 / 联系人', '手机号', '城市', '身份证号', '企业名称', '信用代码', '职业 / 行业', '工作单位', '经营月数', '月收入', '年营收', '信用贷款笔数', '欠款总余额', '贷款月还款金额', '信用卡张数', '信用卡总额度', '信用卡已用额度', '婚姻状况', '社保缴纳', '公积金缴纳', '是否有房', '是否有车']
const moneyKeys = ['monthlyIncome', 'annualRevenue', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardTotalLimit', 'creditCardUsedLimit']
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 = ['姓名 / 联系人', '手机号', '城市', '身份证号', '企业名称', '信用代码', '职业 / 行业', '工作单位', '经营月数', '月收入', '年营收', '信用贷款笔数', '欠款总余额', '贷款月还款金额', '信用卡张数', '信用卡总额度', '信用卡已用额度', '婚姻状况', '社保缴纳', '公积金缴纳', '是否有房', '是否有车', '社保月缴存基数', '公积金月缴存基数']
const moneyKeys = ['monthlyIncome', 'annualRevenue', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardTotalLimit', 'creditCardUsedLimit', 'socialSecurityBase', 'housingFundBase']
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]
let value = raw == null ? '未填写' : (typeof raw == 'number' ? (raw as number).toString() : raw as string)
if (raw != null && moneyKeys.includes(key)) value = yuanToWan(value) + ' 万元'
if (raw != null && key == 'operatingMonths') value += ' 个月'
if (['socialSecurity', 'housingFund'].includes(key)) value = contributionLabel(value)
if (['maritalStatus', 'socialSecurity', 'housingFund', 'house', 'car'].includes(key) && enumLabels[value] != null) value = enumLabels[value] as string
const personalOnly = ['idCard', 'company', 'monthlyIncome', 'maritalStatus', 'socialSecurity', 'housingFund']
const personalOnly = ['idCard', 'company', 'monthlyIncome', 'maritalStatus', 'socialSecurity', 'housingFund', 'socialSecurityBase', 'housingFundBase']
const enterpriseOnly = ['enterpriseName', 'businessCode', 'operatingMonths', 'annualRevenue']
if ((result['type'] == 'enterprise' && personalOnly.includes(key)) || (result['type'] == 'personal' && enterpriseOnly.includes(key))) return
const incomeKeys = ['occupation', 'company', 'operatingMonths', 'monthlyIncome', 'annualRevenue', 'socialSecurity', 'housingFund']
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)
@@ -255,14 +298,15 @@ 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 }
const money = ['monthlyIncome', 'annualRevenue', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardTotalLimit', 'creditCardUsedLimit']
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']
const keys = ['name', 'idCard', 'phone', 'city', 'occupation', 'company', 'enterpriseName', 'businessCode', 'monthlyIncome', 'annualRevenue', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardTotalLimit', 'creditCardUsedLimit', 'creditLoanCount', 'creditCardCount', 'operatingMonths', 'maritalStatus', 'house', 'car', 'socialSecurity', 'housingFund']
const keys = ['name', 'idCard', 'phone', 'city', 'occupation', 'company', 'enterpriseName', 'businessCode', 'monthlyIncome', 'annualRevenue', 'totalDebtBalance', 'monthlyLoanPayment', 'creditCardTotalLimit', 'creditCardUsedLimit', 'creditLoanCount', 'creditCardCount', 'operatingMonths', 'maritalStatus', 'house', 'car', 'socialSecurity', 'housingFund', 'socialSecurityBase', 'housingFundBase']
keys.forEach((key: string) => {
const raw = form[key]
let value = raw == null ? '' : (typeof raw == 'number' ? (raw as number).toString() : raw as string)
if (value.length > 0 && money.includes(key)) value = yuanToWan(value)
if (['socialSecurity', 'housingFund'].includes(key)) value = contributionLabel(value)
if (enums.includes(key) && labels[value] != null) value = labels[value] as string
payload[key] = value
})