'字段名称更换'
This commit is contained in:
@@ -76,13 +76,16 @@ import { ElMessage } from 'element-plus';
|
||||
import { buildImageEntries, type ImageEntry, type StateAngles } from '@/utils/userArchiveImages';
|
||||
|
||||
const CONTENT_LABELS: Record<string, string> = {
|
||||
health_score: '评分',
|
||||
mild_abnormality: '色素',
|
||||
moderate_abnormality: '红区',
|
||||
normal_area: '肤色',
|
||||
severe_abnormality: '炎敏',
|
||||
health_score: '健康评分',
|
||||
predicted_age: '预测年龄',
|
||||
mild_abnormality: '轻微异常',
|
||||
moderate_abnormality: '中度异常',
|
||||
normal_area: '正常区域',
|
||||
severe_abnormality: '严重异常',
|
||||
};
|
||||
|
||||
const METRIC_KEYS_ORDER = ['health_score', 'predicted_age', 'mild_abnormality', 'moderate_abnormality', 'normal_area', 'severe_abnormality'];
|
||||
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
archiveId: number;
|
||||
@@ -127,14 +130,14 @@ const createTime = computed(() => detail.value?.create_time ?? '');
|
||||
|
||||
const metricRows = computed(() => {
|
||||
const c = detail.value?.contents;
|
||||
if (!c || typeof c !== 'object') return [];
|
||||
return Object.entries(c).map(([key, val]) => {
|
||||
return METRIC_KEYS_ORDER.map((key) => {
|
||||
const val = c?.[key];
|
||||
const n = Number(val);
|
||||
const pct = Number.isFinite(n) ? Math.min(100, Math.max(0, n)) : 0;
|
||||
return {
|
||||
key,
|
||||
label: CONTENT_LABELS[key] || key,
|
||||
value: String(val ?? '--'),
|
||||
value: val !== undefined && val !== null ? String(val) : '--',
|
||||
pct,
|
||||
};
|
||||
});
|
||||
|
||||
+12
-2
@@ -9,7 +9,12 @@ export const localStorage = {
|
||||
// 获取永久缓存
|
||||
get(key: string) {
|
||||
const json: any = window.localStorage.getItem(key);
|
||||
return JSON.parse(json);
|
||||
if (json === null || json === undefined) return null;
|
||||
try {
|
||||
return JSON.parse(json);
|
||||
} catch {
|
||||
return json; // 如果不是 JSON 格式,直接返回原始字符串
|
||||
}
|
||||
},
|
||||
// 移除永久缓存
|
||||
remove(key: string) {
|
||||
@@ -32,7 +37,12 @@ export const sessionStorage = {
|
||||
// 获取临时缓存
|
||||
get(key: string) {
|
||||
const json: any = window.sessionStorage.getItem(key);
|
||||
return JSON.parse(json);
|
||||
if (json === null || json === undefined) return null;
|
||||
try {
|
||||
return JSON.parse(json);
|
||||
} catch {
|
||||
return json; // 如果不是 JSON 格式,直接返回原始字符串
|
||||
}
|
||||
},
|
||||
// 移除临时缓存
|
||||
remove(key: string) {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="listData" border stripe style="width: 100%">
|
||||
<el-table-column prop="id" label="ID" align="center" width="80" />
|
||||
<el-table-column prop="name" label="名称" align="center">
|
||||
<template #default="{ row }">{{ row.name || '--' }}</template>
|
||||
</el-table-column>
|
||||
|
||||
@@ -109,13 +109,13 @@
|
||||
</div>
|
||||
|
||||
<aside class="metrics-aside">
|
||||
<div v-if="metricRecord" class="metric-card">
|
||||
<div v-if="firstRecord" class="metric-card" :class="{ 'metric-card--second': secondRecord }">
|
||||
<div class="metric-card-head">
|
||||
<h3>综合评估</h3>
|
||||
<p v-if="metricTimeHint" class="metric-sub">{{ metricTimeHint }}</p>
|
||||
<h3>综合评估(一)</h3>
|
||||
<p class="metric-sub">{{ firstRecord.create_time || '—' }}</p>
|
||||
</div>
|
||||
<div class="metric-card-body">
|
||||
<div v-for="m in metricRows(metricRecord)" :key="m.key" class="metric-row">
|
||||
<div v-for="m in metricRows(firstRecord)" :key="m.key" class="metric-row">
|
||||
<div class="metric-head">
|
||||
<span class="metric-name">{{ m.label }}</span>
|
||||
<span class="metric-num">{{ m.value }}</span>
|
||||
@@ -123,7 +123,25 @@
|
||||
<el-progress :percentage="m.pct" :color="progressColors" :stroke-width="8"
|
||||
:show-text="false" />
|
||||
</div>
|
||||
<div v-if="!metricRows(metricRecord).length" class="metric-empty">暂无评估数据</div>
|
||||
<div v-if="!metricRows(firstRecord).length" class="metric-empty">暂无评估数据</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="secondRecord" class="metric-card metric-card--b">
|
||||
<div class="metric-card-head">
|
||||
<h3>综合评估(二)</h3>
|
||||
<p class="metric-sub">{{ secondRecord.create_time || '—' }}</p>
|
||||
</div>
|
||||
<div class="metric-card-body">
|
||||
<div v-for="m in metricRows(secondRecord)" :key="m.key" class="metric-row">
|
||||
<div class="metric-head">
|
||||
<span class="metric-name">{{ m.label }}</span>
|
||||
<span class="metric-num">{{ m.value }}</span>
|
||||
</div>
|
||||
<el-progress :percentage="m.pct" :color="progressColors" :stroke-width="8"
|
||||
:show-text="false" />
|
||||
</div>
|
||||
<div v-if="!metricRows(secondRecord).length" class="metric-empty">暂无评估数据</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
@@ -146,14 +164,16 @@ import {
|
||||
} from '@/utils/userArchiveImages';
|
||||
|
||||
const CONTENT_LABELS: Record<string, string> = {
|
||||
health_score: '评分',
|
||||
mild_abnormality: '色素',
|
||||
moderate_abnormality: '红区',
|
||||
normal_area: '肤色',
|
||||
severe_abnormality: '炎敏',
|
||||
yumin: '肤质综合',
|
||||
health_score: '健康评分',
|
||||
predicted_age: '预测年龄',
|
||||
mild_abnormality: '轻微异常',
|
||||
moderate_abnormality: '中度异常',
|
||||
normal_area: '正常区域',
|
||||
severe_abnormality: '严重异常',
|
||||
};
|
||||
|
||||
const METRIC_KEYS_ORDER = ['health_score', 'predicted_age', 'mild_abnormality', 'moderate_abnormality', 'normal_area', 'severe_abnormality'];
|
||||
|
||||
const route = useRoute();
|
||||
const loading = ref(false);
|
||||
const thumbExpanded = ref(true);
|
||||
@@ -219,35 +239,16 @@ const hasTriple2 = computed(() => !!(c2Left.value || c2Front.value || c2Right.va
|
||||
const singleUrl1 = computed(() => c1Front.value || c1Left.value || c1Right.value || '');
|
||||
const singleUrl2 = computed(() => c2Front.value || c2Left.value || c2Right.value || '');
|
||||
|
||||
/** 同一人对比:评估指标只展示一份,优先用检测一有 contents,否则用检测二 */
|
||||
const metricRecord = computed(() => {
|
||||
const a = firstRecord.value;
|
||||
const b = secondRecord.value;
|
||||
const hasContents = (r: any) => r?.contents && typeof r.contents === 'object' && Object.keys(r.contents).length;
|
||||
if (a && hasContents(a)) return a;
|
||||
if (b && hasContents(b)) return b;
|
||||
return a ?? b ?? null;
|
||||
});
|
||||
|
||||
const metricTimeHint = computed(() => {
|
||||
const a = firstRecord.value?.create_time;
|
||||
const b = secondRecord.value?.create_time;
|
||||
if (secondRecord.value && a && b && a !== b) {
|
||||
return `检测一 ${a} · 检测二 ${b}`;
|
||||
}
|
||||
return metricRecord.value?.create_time || '';
|
||||
});
|
||||
|
||||
function metricRows(record: any) {
|
||||
const c = record?.contents;
|
||||
if (!c || typeof c !== 'object') return [];
|
||||
return Object.entries(c).map(([key, val]) => {
|
||||
return METRIC_KEYS_ORDER.map((key) => {
|
||||
const val = c?.[key];
|
||||
const n = Number(val);
|
||||
const pct = Number.isFinite(n) ? Math.min(100, Math.max(0, n)) : 0;
|
||||
return {
|
||||
key,
|
||||
label: CONTENT_LABELS[key] || key,
|
||||
value: String(val ?? '--'),
|
||||
value: val !== undefined && val !== null ? String(val) : '--',
|
||||
pct,
|
||||
};
|
||||
});
|
||||
@@ -740,6 +741,21 @@ html.dark .viewer-card {
|
||||
overflow: hidden;
|
||||
background: var(--el-bg-color);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
|
||||
margin-bottom: 16px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&--b {
|
||||
.metric-card-head {
|
||||
background: linear-gradient(180deg, rgba(64, 158, 255, 0.08) 0%, var(--el-fill-color-extra-light) 100%);
|
||||
}
|
||||
|
||||
.metric-num {
|
||||
color: $accent-blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.metric-card-head {
|
||||
|
||||
Reference in New Issue
Block a user