import { groupBy } from '@/tools'; export function fromAnalysisModel(mode: 'tongue' | 'face', data: Record): AnalysisModel; export function fromAnalysisModel(mode: 'pulse', data: Record): PulseAnalysisModel; export function fromAnalysisModel(mode: 'alcohol', data: Record): AlcoholAnalysisModel; export function fromAnalysisModel( mode: 'tongue' | 'face' | 'pulse' | 'alcohol', data: Record ): AnalysisModel | AlcoholAnalysisModel | PulseAnalysisModel { let model: AnalysisModel; switch (mode) { case 'tongue': model = fromTongueAnalysisModel(data); break; case 'face': model = fromFaceAnalysisModel(data); break; case 'pulse': return fromPulseAnalysisModel(data); case 'alcohol': return fromAlcoholAnalysisModel(data?.extendFlowData); } const group = groupBy(model.exception, (item) => item.cover ?? '') ?? {}; model.exceptionGroup = Object.entries(group).map(([key, exception]) => ({ key, exception })); return model; } export interface PulseAnalysisModel extends Pick>, 'measureId' | 'summaryLabel' | 'summaryValue'> { hand?: number; results?: string; url?: string; } export interface AlcoholAnalysisModel { condition: string; description: string; volume: [min: number, max?: number]; } export interface AnalysisModel { table: { columns: string[]; data: { exception: boolean; invalid?: boolean; columns: string[] }[]; }; exception: AnalysisException[]; exceptionGroup: { key: string; exception: AnalysisException[] }[]; cover: string[]; result: string; } export interface AnalysisException { title: string; cover?: string; description?: string; descriptions: { label: string; value: string }[]; tags: string[]; } function fromPulseAnalysisModel(data: Record): PulseAnalysisModel { const pulse = (function (value) { if (typeof value === 'string') try { value = JSON.parse(value); } catch (e) {} return typeof value === 'object' ? value : {}; })(data.pulseReport); const getSummary = (value?: string[]) => (Array.isArray(value) && value.length ? value : void 0); const summary = getSummary(pulse?.summary_desc?.summary) ?? getSummary(pulse?.summary_desc?.left?.summary) ?? getSummary(pulse?.summary_desc?.right?.summary) ?? []; return { measureId: data?.measureId, hand: pulse?.hand ?? 0, summaryValue: pulse?.summary, summaryLabel: pulse?.summary_desc, results: summary.join(','), url: pulse?.url ?? void 0, }; } function fromAlcoholAnalysisModel(data: Record): AlcoholAnalysisModel { const volume: [number, number] = data?.alcoholCapacity?.match(/(\d+)/g)?.slice(0, 2)?.filter(Boolean)?.map((v: string) => +v) ?? []; return { condition: data?.alcoholCondition, description: data?.alcoholCapacity, volume: volume.sort((a, b) => a - b), }; } function fromTongueAnalysisModel(data: Record): AnalysisModel { const exception: AnalysisException[] = []; const fromTongueException = fromAnalysisException(exception); const c1 = data?.upImg ?? data?.tongueImgUrl; const c2 = data?.downImg ?? data?.tongueBackImgUrl; return { table: { columns: ['舌象维度', '检测结果', '标准值'], data: [ fromTongueException(data?.tongueColor, '舌色'), fromTongueException(data?.tongueCoatingColor, '苔色'), fromTongueException(data?.tongueShape, '舌形'), fromTongueException(data?.tongueCoating, '苔质'), fromTongueException(data?.bodyFluid, '津液'), fromTongueException(data?.sublingualVein, '舌下'), ], }, exception, exceptionGroup: [], result: data?.tongueAnalysisResult ?? data?.tongue ?? '', cover: Object.assign([c1, c2].filter(Boolean), { ['舌上']: c1, ['舌下']: c2, }), }; } function fromFaceAnalysisModel(data: Record): AnalysisModel { const exception: AnalysisException[] = []; const fromFaceException = fromAnalysisException(exception, (label, value) => `${label}${value}`); const c1 = data?.faceImg ?? data?.faceImgUrl; const c2 = data?.faceLeft ?? data?.faceLeftImgUrl; const c3 = data?.faceRight ?? data?.faceRightImgUrl; return { table: { columns: ['面象维度', '检测结果', '标准值'], data: [ fromFaceException(data?.faceColor, '面色'), fromFaceException(data?.mainColor, '主色'), fromFaceException(data?.shine, '光泽'), fromFaceException(data?.leftBlackEye, '左黑眼圈'), fromFaceException(data?.rightBlackEye, '右黑眼圈'), fromFaceException(data?.lipColor, '唇色'), fromFaceException(data?.eyeContact, '眼神'), fromFaceException(data?.leftEyeColor, '左目色'), fromFaceException(data?.rightEyeColor, '右目色'), fromFaceException(data?.hecticCheek, '两颧红'), fromFaceException(data?.noseFold, '鼻褶'), fromFaceException(data?.cyanGlabella, '眉间/鼻柱青色'), fromFaceException(data?.faceSkinDefects, '面部皮损'), ], }, exception, exceptionGroup: [], result: data?.faceAnalysisResult ?? data?.face ?? '', cover: Object.assign([c1, c2, c3].filter(Boolean), { ['正面']: c1, ['左面']: c2, ['右面']: c3, }), }; } function fromAnalysisException(exception: AnalysisException[], $title = (label: string, value: string) => value) { return function (data: { actualList?: Record[]; standardValue?: string }, label: string) { let is = false; let invalid = false; const values = data?.actualList?.map((item) => { let title: string = item?.actualValue ?? ''; const suffix = item?.contrast ?? 's'; if (title.endsWith('不符合检测要求')) { invalid = true; } else if (suffix !== 's') { if (suffix !== 'r') title += ` (${suffix || ''}) `; is = true; exception.push({ title: $title(label, title), cover: item.splitImage, descriptions: [ item.features ? { label: '【特征】', value: item.features } : null, item.clinicalSignificance ? { label: '【临床意义】', value: item.clinicalSignificance } : null, ].filter((v) => !!v), tags: item.attrs ?? [], }); } return title; }) ?? []; return { exception: is, invalid, columns: [label, values.join('
'), data?.standardValue ?? ''] } }; }