作者:974294341-bit | 技术栈:Spring Boot 3 / Vue3 / MySQL·H2 | 标准:MZ/T 039-2013

  1. 为什么写这篇
    起因很朴素:动手做这个项目前,在 B 站刷到两个"老年人能力评估系统"的视频,一个是微信小程序版、一个是机构 Web 版。看演示挺像回事,但点进去只有解说,没有源码、没有题库、没有打分逻辑。
    作为一个想真正搞懂"它到底怎么算出来'失能等级'"的人,光看演示没用。于是我做了三件事:

  2. 逆向这两个系统的设计与架构(设计级,非反编译);

  3. 扒标准——找到民政部《老年人能力评估》MZ/T 039-2013,把"22 题怎么评、等级怎么定"搞透;

  4. 自己落地一套能跑的系统:电脑端管理后台 + 后端评估引擎(手机端原生 App 下轮做)。
    这篇博客就是这条链路的完整记录,重点放在评估算法怎么工程化和踩过的坑,而不是堆界面截图。

  5. 逆向对象:两个系统的真实面貌
    两个 B 站链接都是搜索聚合落地页,拿不到源码,所以做的是设计级逆向——基于公开描述 + 国标框架还原架构。结论如下:
    系统 A(教学演示向)
    系统 B(机构专业向)
    形态
    微信小程序(C 端)+ Web 后台
    Web 系统(机构/医养场景)
    角色
    老人 / 自评师 / 管理员(3 类)
    评估员 / 管理员
    技术栈
    Spring + Vue3 + Bootstrap + 小程序
    同类 Web(框架未明示)
    评估类型
    单一(国标能力评估)
    多量表(能力/认知/营养…)
    特色
    自评 + 评估师建议 + 统计看板
    AI 处方 + 详细/简易双报告
    定位
    轻量/教学演示
    专业评估/干预闭环
    关键启发来自系统 B:它"支持多种评估类型"的本质,是把量表配置化——一套表结构能吃下所有量表,加新量表 = 插几条数据,不碰代码。这一点我直接吸收进了自己的设计。

  6. 标准深挖:评估到底怎么算
    拿到 MZ/T 039-2013 标准后,核心模型非常清晰,是一个四层结构:
    22 个二级指标(逐项 0~4 评分)
    ↓ 求和
    4 个一级指标
    ↓ 按得分区间划级
    一级指标等级(0 能力完好 ~ 3 重度受损)
    ↓ 组合判定(ADL 权重最高)
    综合能力等级(0 能力完好 ~ 3 重度失能)

2.1 4 个一级指标 + 22 个二级指标
一级指标
满分
二级指标(数量)
日常生活活动(ADL)
40
进食、洗澡、修饰、穿衣、大便控制、小便控制、如厕、床椅转移、平地行走、上下楼梯(10)
精神状态
8
认知功能、攻击行为、抑郁症状(3)
感知觉与沟通
10
意识水平、视力、听力、沟通交流(4)
社会参与
20
生活能力、工作能力、时间/空间定向、人物定向、社会交往能力(5)
多数项目 04 分(4=完好,0=完全丧失);部分损伤类项目(攻击行为、抑郁、视力、听力、意识)只用 02 档。

2.2 综合等级判定(2013 版核心)
不是简单取平均分,日常生活活动(ADL)权重最高。判定规则:

  • 0 级 能力完好:4 个维度全为 0 级
  • 1 级 轻度失能:出现 1 级且无更高
  • 2 级 中度失能:出现 2 级(或 ADL=1 且其他有 ≥1 项为 2 级)
  • 3 级 重度失能:任一维度=3 级(或 ADL=2 且其他 ≥2 项为 2/3 级;或 ADL=3)

2.3 一个易踩的版本坑
MZ/T 039-2013(2013 版)和 GB/T 42195-2022(2022 版)不是一回事:

  • 2013 版 = 22 题、能力分 4 级(0~3)
  • 2022 版 = 26 题、能力分 5 级(新增"完全失能"4 级)
    拿源码后第一件事,就是确认它吃的是哪一版,决定题库是 22 还是 26、等级是 4 还是 5 档。我这里先按 2013 版实现。
  1. 关键决策:不要小程序,要原生 App
    用户(也是我自己做项目时的硬性要求)明确:电脑端 + 手机端 App,不要微信小程序。
    手机端技术选型当时对比了三种:
    方案
    优点
    缺点
    结论
    Flutter
    一套代码出 Android+iOS 真机,最像"正经 App"
    多学一门 Dart
    最省事但非首选
    Android Kotlin 原生
    与 Java 后端生态近、项目演示有说服力
    只有 Android,无 iOS
    选定(下轮做)
    React Native
    前端 React 复用
    与现成 Vue 后台不共用
    排除
    最终落地节奏:后端 Spring Boot + 电脑端 Vue 管理后台先跑通,手机端 Android(Kotlin + Retrofit + Compose)复用同一套 REST API,不改后端。

  2. 工程落地(核心)
    项目路径:elder-assessment-engine/,约 1266 行代码,结构如下:
    elder-assessment-engine/
    ├── pom.xml # Spring Boot 3 / Java 17
    ├── sql/elder_assessment_mzt039_2013.sql # 生产建表 + 22 题选项 JSON
    ├── src/main/java/com/example/elder/
    │ ├── assessment/AssessmentEngine.java # ★ 评估算法核心
    │ ├── entity/ # Elder, Scale, ScaleItem, ScaleResult, ScaleAnswer...
    │ ├── repo/ # Spring Data JPA
    │ ├── service/ # 评估业务
    │ ├── controller/ # /api/scale, /api/elders, /api/assessments
    │ ├── config/ # CORS + 启动种子数据
    │ └── dto/
    └── frontend/ # Vue3 + Vite + Element Plus
    └── src/views/ # ElderList(建档) / Assessment(22题表单) / Report(双报告)

4.1 评估引擎(最重要的一块)
把"四层模型"直接写成纯 Java 方法,不依赖框架,方便独立测试。维度满分硬编码为 DIM_MAX = {40, 8, 10, 20},22 题按题号映射到 4 个维度:
// 题号(1~22) → 维度下标:1-10→ADL, 11-13→精神, 14-17→感知, 18-22→社会
private static int[] buildItemDim() {
int[] a = new int[23];
for (int i = 1; i <= 10; i++) a[i] = 0; // 日常生活活动
for (int i = 11; i <= 13; i++) a[i] = 1; // 精神状态
for (int i = 14; i <= 17; i++) a[i] = 2; // 感知觉与沟通
for (int i = 18; i <= 22; i++) a[i] = 3; // 社会参与
return a;
}
综合定级就是标准里那段组合规则的直接翻译,ADL 权重最高:
public static int comprehensiveLevel(int[] dimLevels) {
if (Arrays.stream(dimLevels).allMatch(l -> l == 0)) return 0; // 全 0 → 完好
int adl = dimLevels[0];
if (adl == 3) return 3; // ADL 重度 → 综合重度
if (Arrays.stream(dimLevels).anyMatch(l -> l == 3)) return 3; // 任一维度重度
int othersGE2 = 0;
for (int i = 1; i < 4; i++) if (dimLevels[i] >= 2) othersGE2++;
if (adl == 2 && othersGE2 >= 2) return 3; // ADL 中度 + 其他≥2项中度
if (Arrays.stream(dimLevels).anyMatch(l -> l == 2)) return 2; // 任一中度
if (adl == 1 && othersGE2 >= 1) return 2;
if (Arrays.stream(dimLevels).anyMatch(l -> l == 1)) return 1; // 任一轻度
return 0;
}
主入口 assess(answers, thresholds):题号→分值 + 各维度等级阈值 → 返回四个维度原始分、维度等级、综合等级与名称。

4.2 后端 Spring Boot

  • 表设计沿用"多量表配置化"思路:scale / scale_dimension / scale_item / scale_result / scale_answer / scale_dimension_level。当前只挂了 MZ/T 039-2013 一张量表,但结构能无缝扩展认知、营养等量表。
  • REST API(前端直接消费):
    • GET /api/scale —— 拉取评估表单(维度+题目+选项)
    • GET/POST/PUT /api/elders —— 老人建档管理
    • POST /api/assessments —— 提交 22 题答案,返回定级结果
    • GET /api/assessments/{id}/report —— 详细/简易双报告
  • dev 用 H2 内存库 + 启动自动种子(4 维度 / 22 题 / 等级阈值 / 演示老人),开箱即跑;application-prod.yml 切 MySQL。

4.3 电脑端 Vue3 管理后台
三个页面串起完整业务流:
老人管理(建档) → 去评估(22 题表单, 按维度分组渲染) → 提交 → 查看报告(详细/简易)
技术:Vue3 + Vite + Element Plus,vite build 通过(1666 模块,exit 0),所有 SFC 编译正常。

  1. 踩坑与校准(干货)

5.1 定级阈值不能拍脑袋 ⚠️
维度原始分 → 维度等级,需要阈值(如 ADL ≥36 为 0 级)。我代码里留了 thresholds 注入点,但默认值只是"按满分百分比"的近似(90% / 75% / 50%)。
上线前必须做:用你标准附录《一级指标等级划分》的精确分值覆盖 scale_dimension_level 表,否则定级结果可能与官方不一致。这是整个系统最容易"看起来对、实际错"的地方。

5.2 本机环境的两个真实坑

  • PATH 里的 java/javac 是坏的(指向一个不完整的 JDK),编译要显式用可用的 JDK 17,且务必带 -encoding UTF-8,否则中文注释直接 GBK 报错。
  • Maven 全量构建在本环境受限(中央仓库被代理拦截),所以后端我做了"引擎独立编译 + 前端完整构建"两级验证,没有硬跑 mvn package。代码是标准 Spring Boot 写法,你本机 mvn spring-boot:run 即可。

5.3 "AI 处方"是医疗敏感词
系统 B 的卖点"AI 处方",在医养语境下本质是干预/照护方案,不是开药。若要做:

  • 干预项来自人工维护的目录(可审计),LLM 只做自然语言润色,不自主诊断;
  • 输出需人工审核留痕(auditor_id),无资质场景不做诊断。否则合规风险很大。
  1. 验证结果
    验证项
    结果
    评估引擎独立编译(JDK 17, UTF-8)
    ✅ 通过
    前端 npm install + vite build(1666 模块)
    ✅ 通过
    后端全量 mvn 打包
    ⚠️ 本环境受限,未跑;标准写法,本机可启

  2. 本地运行

后端(默认 H2 内存库,:8080)

cd elder-assessment-engine
mvn spring-boot:run

电脑端(:5173,已配 /api 代理到 8080)

cd elder-assessment-engine/frontend
npm install && npm run dev
体验路径:老人管理 → 新建 → 去评估 → 答 22 题 → 提交 → 看详细/简易报告。

  1. 后续规划

  2. 手机端 Android 原生 App(Kotlin + Retrofit + Compose):复用现有 /api/*,无需改后端,下一轮做。

  3. 扩展多量表 + AI 处方引擎:接系统 B 的设计——规则引擎出干预项、LLM 做文案润色、人工审核留痕。

  4. 升级 GB/T 42195-2022:若目标系统实为 2022 版,扩题库到 26 题、等级到 5 档。

  5. 小结
    这次从"看两个视频"到"自己写出能跑的评估引擎",最大的体会是:项目里的"智能评估"剥掉包装,核心就是"一套标准 + 一张题库表 + 一段定级函数"。把国标吃透、把算法写成可单测的纯函数,比堆界面有价值得多。
    逆向的价值不在"抄",在于逼自己把别人的演示翻译成可验证的工程实现——然后你会发现,很多"高大上"的系统,骨架也就这么大。
    源码已落地于 elder-assessment-engine/,欢迎按需取用、校准阈值后用于学习或二次开发。

posted on 2026-11-03 10:55  chenyun_922  阅读(0)  评论(0)    收藏  举报