@@ -422,23 +387,23 @@
{ name: '血常规', keys: ['hgb', 'wbc', 'plt'] }
];
var NUM = {
- bmi: { name: 'BMI', unit: 'kg/m²', ref: [18.5, 23.9], v: [23.1, 23.8, 24.5, 25.2, 25.8], badge: ['变化趋势', 'worse'] },
- sbp: { name: '收缩压', unit: 'mmHg', ref: [90, 139], v: [112, 115, 118, 116, 120], badge: ['平稳', 'stable'] },
- dbp: { name: '舒张压', unit: 'mmHg', ref: [60, 89], v: [72, 74, 73, 76, 78], badge: ['平稳', 'stable'] },
- tc: { name: '总胆固醇 TC', unit: 'mmol/L', ref: [3.1, 5.7], v: [4.62, 4.95, 5.36, 5.78, 6.10], badge: ['变化趋势', 'worse'] },
- tg: { name: '甘油三酯 TG', unit: 'mmol/L', ref: [0.4, 1.7], v: [1.20, 1.35, 1.55, 1.72, 2.08], badge: ['变化趋势', 'worse'] },
- hdl: { name: '高密度脂蛋白 HDL-C', unit: 'mmol/L', ref: [1.04, 1.55], v: [1.35, 1.30, 1.26, 1.22, 1.18], badge: ['平稳', 'stable'] },
- ldl: { name: '低密度脂蛋白 LDL-C', unit: 'mmol/L', ref: [0, 3.4], v: [2.80, 3.00, 3.10, 3.35, 3.92], badge: ['新增异常', 'new'] },
- glu: { name: '空腹血糖 GLU', unit: 'mmol/L', ref: [3.9, 6.1], v: [5.0, 5.1, 4.9, 5.3, 5.2], badge: ['平稳', 'stable'] },
- hba1c:{ name: '糖化血红蛋白 HbA1c', unit: '%', ref: [4.0, 6.0], v: [5.2, 5.3, 5.1, 5.4, 5.6], badge: ['平稳', 'stable'] },
- ua: { name: '尿酸 UA', unit: 'μmol/L', ref: [155, 357], v: [330, 362, 371, 380, 389], badge: ['连续异常', 'keep'] },
- crea: { name: '肌酐 CREA', unit: 'μmol/L', ref: [41, 73], v: [66, 68, 69, 70, 71], badge: ['平稳', 'stable'] },
- urea: { name: '尿素 UREA', unit: 'mmol/L', ref: [2.8, 7.2], v: [4.5, 5.0, 4.6, 5.2, 4.8], badge: ['平稳', 'stable'] },
- alt: { name: '丙氨酸氨基转移酶 ALT', unit: 'U/L', ref: [7, 40], v: [28, 31, 35, 42, 24.6], badge: ['转好', 'better'] },
- ast: { name: '天门冬氨酸氨基转移酶 AST', unit: 'U/L', ref: [13, 35], v: [24, 26, 28, 38, 22.4], badge: ['转好', 'better'] },
- hgb: { name: '血红蛋白 HGB', unit: 'g/L', ref: [115, 150], v: [140, 138, 141, 139, 136], badge: ['平稳', 'stable'] },
- wbc: { name: '白细胞计数 WBC', unit: '10^9/L', ref: [3.5, 9.5], v: [6.2, 6.5, 6.1, 6.9, 6.8], badge: ['平稳', 'stable'] },
- plt: { name: '血小板计数 PLT', unit: '10^9/L', ref: [125, 350], v: [220, 235, 240, 252, 248], badge: ['平稳', 'stable'] }
+ bmi: { name: 'BMI', unit: 'kg/m²', ref: [18.5, 23.9], v: [23.1, 23.8, 24.5, 25.2, 25.8] },
+ sbp: { name: '收缩压', unit: 'mmHg', ref: [90, 139], v: [112, 115, 118, 116, 120] },
+ dbp: { name: '舒张压', unit: 'mmHg', ref: [60, 89], v: [72, 74, 73, 76, 78] },
+ tc: { name: '总胆固醇 TC', unit: 'mmol/L', ref: [3.1, 5.7], v: [4.62, 4.95, 5.36, 5.78, 6.10] },
+ tg: { name: '甘油三酯 TG', unit: 'mmol/L', ref: [0.4, 1.7], v: [1.20, 1.35, 1.55, 1.72, 2.08] },
+ hdl: { name: '高密度脂蛋白 HDL-C', unit: 'mmol/L', ref: [1.04, 1.55], v: [1.35, 1.30, 1.26, 1.22, 1.18] },
+ ldl: { name: '低密度脂蛋白 LDL-C', unit: 'mmol/L', ref: [0, 3.4], v: [2.80, 3.00, 3.10, 3.35, 3.92] },
+ glu: { name: '空腹血糖 GLU', unit: 'mmol/L', ref: [3.9, 6.1], v: [5.0, 5.1, 4.9, 5.3, 5.2] },
+ hba1c:{ name: '糖化血红蛋白 HbA1c', unit: '%', ref: [4.0, 6.0], v: [5.2, 5.3, 5.1, 5.4, 5.6] },
+ ua: { name: '尿酸 UA', unit: 'μmol/L', ref: [155, 357], v: [360, 362, 371, 380, 389] },
+ crea: { name: '肌酐 CREA', unit: 'μmol/L', ref: [41, 73], v: [66, 68, 69, 70, 71] },
+ urea: { name: '尿素 UREA', unit: 'mmol/L', ref: [2.8, 7.2], v: [4.5, 5.0, 4.6, 5.2, 4.8] },
+ alt: { name: '丙氨酸氨基转移酶 ALT', unit: 'U/L', ref: [7, 40], v: [28, 31, 35, 42, 24.6] },
+ ast: { name: '天门冬氨酸氨基转移酶 AST', unit: 'U/L', ref: [13, 35], v: [24, 26, 28, 38, 22.4] },
+ hgb: { name: '血红蛋白 HGB', unit: 'g/L', ref: [115, 150], v: [140, 138, 141, 139, 136] },
+ wbc: { name: '白细胞计数 WBC', unit: '10^9/L', ref: [3.5, 9.5], v: [6.2, 6.5, 6.1, 6.9, 6.8] },
+ plt: { name: '血小板计数 PLT', unit: '10^9/L', ref: [125, 350], v: [220, 235, 240, 252, 248] }
};
// 定性项目:statuses 五年逐项状态(n 正常 / a 异常 / m 未检)
var QUAL = [
@@ -459,27 +424,39 @@
}
// 取指标在当前区间内的数值序列
function vals(it) { var r = range(); return it.v.slice(r.a, r.b + 1); }
- // 区间内是否呈不利走向(端点对比方向性变化),随所选区间动态计算
- function deltaWorse(key) {
- var it = NUM[key], vv = vals(it);
- if (vv.length < 2) return false;
- var first = vv[0], last = vv[vv.length - 1];
- var hi = it.ref[1], lo = it.ref[0];
- if (hi < Infinity && last > hi) return last > first;
- return last < lo ? last < first : false;
+ // 指标轨迹分类(唯一口径,同时用于指标卡徽章与总结卡统计)
+ // worse=异常趋势 new=新增异常 keep=持续异常 better=转好 stable=平稳
+ function classify(key) {
+ var it = NUM[key], vv = vals(it), n = vv.length;
+ var lo = it.ref[0], hi = it.ref[1];
+ var abn = vv.map(function (v) { return v < lo || v > hi; });
+ var lastAbn = abn[n - 1], firstAbn = abn[0];
+ if (!lastAbn) {
+ return abn.some(function (x) { return x; }) ? 'better' : 'stable';
+ }
+ // 末年异常
+ var tail = 0;
+ for (var i = n - 1; i >= 0 && abn[i]; i--) tail++;
+ if (tail === 1) return 'new'; // 仅末年越限:今年首次异常
+ if (firstAbn) return 'keep'; // 区间起点已异常:老问题持续
+ var first = vv[0], last = vv[n - 1];
+ if (last > hi) return last > first ? 'worse' : 'keep';
+ return last < first ? 'worse' : 'keep';
}
- // 组内排序权重:期末异常在前;区间内不利走向 > 期末新增 > 区间内全程异常 > 区间内转好 > 静态分级兜底
+ var BADGE = {
+ worse: { label: '异常趋势', cls: 'worse' },
+ new: { label: '新增异常', cls: 'new' },
+ keep: { label: '持续异常', cls: 'keep' },
+ better: { label: '转好', cls: 'better' },
+ stable: { label: '平稳', cls: 'stable' }
+ };
+ function badgeOf(key) { return BADGE[classify(key)]; }
+ // 组内排序权重:期末异常在前;异常 > 新增 > 持续 > 转好 > 平稳
function weight(key) {
- var it = NUM[key], r = range(), e = r.b, s = r.a;
- var lastAbn = isAbn(it, e), firstAbn = isAbn(it, s);
- var abn = lastAbn ? 0 : 1;
- var order;
- if (deltaWorse(key)) order = 0;
- else if (lastAbn && !firstAbn) order = 1;
- else if (lastAbn) order = 2;
- else if (!lastAbn && firstAbn) order = 3;
- else order = 4 + ({ worse: 0, new: 1, keep: 2, better: 3, stable: 4 }[it.badge[1]] || 4);
- return abn * 10 + order;
+ var it = NUM[key], r = range(), e = r.b;
+ var lastAbn = isAbn(it, e);
+ var order = { worse: 0, new: 1, keep: 2, better: 3, stable: 4 }[classify(key)];
+ return (lastAbn ? 0 : 1) * 10 + order;
}
// 缩略趋势线(纯内联 SVG,按所选区间取点,异常点标红)
function sparkline(item) {
@@ -497,20 +474,6 @@
return '
';
}
function fmtV(v) { return v >= 100 ? String(Math.round(v)) : String(v); }
- // 区间端点对比:返回 {last, delta, worse, newAbn, keepAbn, better, n}
- function endCompare(it) {
- var r = range(), vv = vals(it);
- var first = vv[0], last = vv[vv.length - 1];
- var hi = it.ref[1], lo = it.ref[0];
- var lastAbn = last < lo || last > hi, firstAbn = first < lo || first > hi;
- var worse = (hi < Infinity && last > hi) ? last > first : (last < lo ? last < first : false);
- var allAbn = vv.every(function (v) { return v < lo || v > hi; });
- return { r: r, last: last, delta: last - first, worse: worse, newAbn: lastAbn && !firstAbn, keepAbn: lastAbn && firstAbn && allAbn, better: !lastAbn && firstAbn };
- }
- function fmtDelta(it, d) {
- var dec = it.v[0] >= 100 || Math.abs(d) >= 10 ? 0 : (Math.abs(d) >= 1 ? 1 : 2);
- return (d > 0 ? '+' : '') + d.toFixed(dec);
- }
// ===== 渲染数值指标分组(大类折叠卡,默认全部展开;点击大类头可收起)=====
var filter = 'all';
@@ -530,9 +493,10 @@
if (!show) return;
shown++;
var arrow = abn ? (last > it.ref[1] ? ' ↑' : ' ↓') : '';
+ var badge = badgeOf(key);
cards += '
'
+ '
' + it.name + ''
- + '' + it.badge[0] + '
'
+ + '
' + badge.label + ''
+ '
'
+ '
' + fmtV(last) + arrow + '' + it.unit + '
'
+ '
参考 ' + it.ref[0] + '-' + it.ref[1] + '
'
@@ -598,32 +562,29 @@
document.getElementById('qualBody').innerHTML = html || '
该筛选条件下暂无定性项目
';
}
- // ===== AI 总结文案(按所选区间数据生成,模拟端点对比口径)=====
+ // ===== AI 总结文案(按所选区间 + classify 轨迹分类生成)=====
function buildSummary() {
var r = range();
- var nums = Object.keys(NUM).map(function (k) {
- var it = NUM[k];
- return { key: k, it: it, cmp: endCompare(it) };
+ var items = Object.keys(NUM).map(function (k) {
+ return { name: NUM[k].name, cls: classify(k) };
});
- var abnNums = nums.filter(function (x) { var l = x.cmp.last; return l < x.it.ref[0] || l > x.it.ref[1]; });
- var lead;
+ function by(cls) { return items.filter(function (x) { return x.cls === cls; }).map(function (x) { return x.name; }); }
+ var worse = by('worse'), added = by('new'), keep = by('keep'), better = by('better'), stable = by('stable');
+ var abnCount = worse.length + added.length + keep.length;
+ var lead, notes = [];
if (r.n === 1) {
- // 单年度:只报当年结果,不做趋势对比
- lead = r.ys[0] + ' 年度体检共 ' + abnNums.length + ' 项指标处于参考范围之外' +
- (abnNums.length ? ':' + abnNums.map(function (x) { return x.it.name; }).join('、') + '。' : '。');
+ lead = r.ys[0] + ' 年度体检共 ' + abnCount + ' 项指标处于参考范围之外' +
+ (abnCount ? ':' + worse.concat(added, keep).join('、') + '。' : '。');
} else {
- lead = '在 ' + r.ys[0] + '–' + r.ys[r.n - 1] + ' 共 ' + r.n + ' 次体检中,您的多项指标呈持续上行趋势:' +
- nums.filter(function (x) { return x.cmp.worse; }).map(function (x) { return x.it.name; }).join('、') +
- ' 较 ' + r.ys[0] + ' 年分别升高 ' +
- nums.filter(function (x) { return x.cmp.worse; }).map(function (x) { return fmtDelta(x.it, x.cmp.delta); }).join(' / ') +
- ';期末共 ' + abnNums.length + ' 项指标处于参考范围之外。';
+ var parts = [];
+ if (worse.length) parts.push(worse.join('、') + ' 较 ' + r.ys[0] + ' 年呈持续升高趋势');
+ if (added.length) parts.push(added.join('、') + ' 于 ' + r.ys[r.n - 1] + ' 年首次超出参考范围');
+ if (keep.length) parts.push(keep.join('、') + ' 多年持续偏高');
+ lead = '在 ' + r.ys[0] + '–' + r.ys[r.n - 1] + ' 共 ' + r.n + ' 次体检中,' + parts.join(';') +
+ '。期末共 ' + abnCount + ' 项指标处于参考范围之外。';
+ if (better.length) notes.push(better.join('、') + ' 已恢复至正常范围');
+ if (stable.length) notes.push('其余 ' + stable.length + ' 项指标持续平稳');
}
- var notes = r.n > 1 ? nums.filter(function (x) { return x.cmp.newAbn || x.cmp.keepAbn || x.cmp.better; }).map(function (x) {
- var y = r.n + ' 年间';
- if (x.cmp.newAbn) return x.it.name + y + '首次越限';
- if (x.cmp.keepAbn) return x.it.name + y + '持续高于正常范围';
- return x.it.name + y + '回归正常范围';
- }) : [];
var qualNotes = QUAL.map(function (q) {
var st = q.st.slice(r.a, r.b + 1);
var n = st.length, tail = 0, head = -1;
@@ -647,13 +608,6 @@
document.getElementById('heroTitle').textContent = r.n + ' 年纵向对比总结';
document.getElementById('heroRangeMeta').textContent =
r.ys[0] + ' - ' + r.ys[r.n - 1] + ' · 覆盖 ' + r.n + ' 次体检';
- var nums = Object.keys(NUM).map(function (k) { return { it: NUM[k], cmp: endCompare(NUM[k]) }; });
- document.getElementById('statAbn').textContent = nums.filter(function (x) {
- return x.cmp.last < x.it.ref[0] || x.cmp.last > x.it.ref[1];
- }).length;
- document.getElementById('statWorse').textContent = nums.filter(function (x) { return x.cmp.worse; }).length;
- document.getElementById('statNew').textContent = nums.filter(function (x) { return x.cmp.newAbn; }).length;
- document.getElementById('statBetter').textContent = nums.filter(function (x) { return x.cmp.better; }).length;
var sum = buildSummary();
document.getElementById('heroLead').textContent = sum.lead;
document.getElementById('heroNotes').textContent = sum.notes;
diff --git a/employee-app/health-checkup/my-appointments-all.html b/employee-app/health-checkup/my-appointments-all.html
index fbf8a81..9fac661 100644
--- a/employee-app/health-checkup/my-appointments-all.html
+++ b/employee-app/health-checkup/my-appointments-all.html
@@ -463,7 +463,7 @@
-
+