feat(plugin): 评估量表插件骨架 — assessment_scale + assessment_response + PHQ-9 默认数据

- 创建 erp-plugin-assessment cdylib crate
- 实现 Guest trait(init/on_tenant_created/handle_event)
- on_tenant_created 自动插入 PHQ-9 抑郁筛查量表
- plugin.toml 声明 2 实体 + 4 权限 + 触发事件
This commit is contained in:
iven
2026-04-28 12:12:47 +08:00
parent ade8497c2d
commit 96c9a8ada9
4 changed files with 308 additions and 0 deletions

View File

@@ -17,6 +17,7 @@ members = [
"crates/erp-plugin-itops",
"crates/erp-health",
"crates/erp-ai",
"crates/erp-plugin-assessment",
]
[workspace.package]

View File

@@ -0,0 +1,13 @@
[package]
name = "erp-plugin-assessment"
version = "0.1.0"
edition = "2024"
description = "标准化医学评估量表插件PHQ-9、GAD-7 等)"
[lib]
crate-type = ["cdylib"]
[dependencies]
wit-bindgen = "0.55"
serde = { workspace = true }
serde_json = { workspace = true }

View File

@@ -0,0 +1,149 @@
# 评估量表 — plugin.toml
[metadata]
id = "assessment"
name = "评估量表"
version = "0.1.0"
description = "标准化医学评估量表PHQ-9、GAD-7 等)"
author = "HMS"
min_platform_version = "0.1.0"
[[permissions]]
code = "assessment_scale.list"
name = "查看评估量表"
description = "查看评估量表列表和详情"
[[permissions]]
code = "assessment_scale.manage"
name = "管理评估量表"
description = "创建、编辑、删除评估量表"
[[permissions]]
code = "assessment_response.list"
name = "查看评估结果"
description = "查看患者评估答卷"
[[permissions]]
code = "assessment_response.manage"
name = "管理评估结果"
description = "提交、编辑评估答卷"
[[schema.entities]]
name = "assessment_scale"
display_name = "评估量表"
[[schema.entities.fields]]
name = "scale_code"
field_type = "string"
required = true
display_name = "量表编码"
unique = true
ui_widget = "select"
options = ["PHQ-9", "GAD-7", "SF-36", "MMSE", "ADL", "IADL"]
[[schema.entities.fields]]
name = "title"
field_type = "string"
required = true
display_name = "量表名称"
searchable = true
[[schema.entities.fields]]
name = "description"
field_type = "string"
display_name = "描述"
ui_widget = "textarea"
[[schema.entities.fields]]
name = "questions_json"
field_type = "json"
required = true
display_name = "题目定义JSON"
[[schema.entities.fields]]
name = "scoring_rules_json"
field_type = "json"
required = true
display_name = "评分规则JSON"
[[schema.entities.fields]]
name = "status"
field_type = "string"
required = true
display_name = "状态"
default = "active"
ui_widget = "select"
options = ["active", "inactive"]
[[schema.entities]]
name = "assessment_response"
display_name = "评估答卷"
[[schema.entities.fields]]
name = "scale_id"
field_type = "uuid"
required = true
display_name = "量表"
ui_widget = "entity_select"
ref_entity = "assessment_scale"
ref_plugin = "assessment"
[[schema.entities.fields]]
name = "patient_id"
field_type = "uuid"
required = true
display_name = "患者 ID"
[[schema.entities.fields]]
name = "answers_json"
field_type = "json"
required = true
display_name = "答案JSON"
[[schema.entities.fields]]
name = "total_score"
field_type = "integer"
required = true
display_name = "总分"
[[schema.entities.fields]]
name = "severity_level"
field_type = "string"
required = true
display_name = "严重程度"
ui_widget = "select"
options = ["normal", "mild", "moderate", "moderate_severe", "severe"]
[[schema.entities.fields]]
name = "assessed_by"
field_type = "uuid"
display_name = "评估人"
[[schema.entities.fields]]
name = "status"
field_type = "string"
required = true
display_name = "状态"
default = "completed"
ui_widget = "select"
options = ["draft", "completed", "reviewed"]
[[schema.entities.relations]]
entity = "assessment_scale"
foreign_key = "scale_id"
on_delete = "restrict"
name = "scale"
type = "belongs_to"
display_field = "title"
[[trigger_events]]
name = "assessment_completed"
display_name = "评估完成"
description = "患者完成评估量表,触发评分计算和后续流程"
entity = "assessment_response"
on = "create"
[[ui.pages]]
type = "crud"
label = "评估量表"
icon = "FormOutlined"

View File

@@ -0,0 +1,145 @@
//! 评估量表插件 — 标准化医学评估PHQ-9, GAD-7 等)
use serde_json::json;
wit_bindgen::generate!({
path: "../erp-plugin-prototype/wit/plugin.wit",
world: "plugin-world",
});
use crate::erp::plugin::host_api;
use crate::exports::erp::plugin::plugin_api::Guest;
struct AssessmentPlugin;
impl Guest for AssessmentPlugin {
fn init() -> Result<(), String> {
host_api::log_write("info", "AssessmentPlugin initialized");
Ok(())
}
fn on_tenant_created(tenant_id: String) -> Result<(), String> {
host_api::log_write(
"info",
&format!("AssessmentPlugin: tenant {} created, inserting default scales", tenant_id),
);
insert_phq9_scale(&tenant_id)?;
Ok(())
}
fn handle_event(event_type: String, payload: Vec<u8>) -> Result<(), String> {
host_api::log_write(
"debug",
&format!("AssessmentPlugin received: {}", event_type),
);
if event_type == "assessment_completed" {
let data: serde_json::Value =
serde_json::from_slice(&payload).map_err(|e| format!("解析失败: {}", e))?;
host_api::log_write(
"info",
&format!("评估完成: scale_id={}, patient_id={}",
data["scale_id"].as_str().unwrap_or("?"),
data["patient_id"].as_str().unwrap_or("?")
),
);
}
Ok(())
}
}
/// 插入 PHQ-9 抑郁筛查量表默认数据
fn insert_phq9_scale(tenant_id: &str) -> Result<(), String> {
let questions = json!([
{"id": 1, "text": "做事时提不起劲或没有兴趣", "options": [
{"label": "完全不会", "score": 0},
{"label": "好几天", "score": 1},
{"label": "一半以上的天数", "score": 2},
{"label": "几乎每天", "score": 3}
]},
{"id": 2, "text": "感到心情低落、沮丧或绝望", "options": [
{"label": "完全不会", "score": 0},
{"label": "好几天", "score": 1},
{"label": "一半以上的天数", "score": 2},
{"label": "几乎每天", "score": 3}
]},
{"id": 3, "text": "入睡困难、睡不安稳或睡眠过多", "options": [
{"label": "完全不会", "score": 0},
{"label": "好几天", "score": 1},
{"label": "一半以上的天数", "score": 2},
{"label": "几乎每天", "score": 3}
]},
{"id": 4, "text": "感觉疲倦或没有活力", "options": [
{"label": "完全不会", "score": 0},
{"label": "好几天", "score": 1},
{"label": "一半以上的天数", "score": 2},
{"label": "几乎每天", "score": 3}
]},
{"id": 5, "text": "食欲不振或吃太多", "options": [
{"label": "完全不会", "score": 0},
{"label": "好几天", "score": 1},
{"label": "一半以上的天数", "score": 2},
{"label": "几乎每天", "score": 3}
]},
{"id": 6, "text": "觉得自己很糟,或觉得自己失败了,或让自己和家人失望", "options": [
{"label": "完全不会", "score": 0},
{"label": "好几天", "score": 1},
{"label": "一半以上的天数", "score": 2},
{"label": "几乎每天", "score": 3}
]},
{"id": 7, "text": "对事物专注有困难(例如阅读或看电视)", "options": [
{"label": "完全不会", "score": 0},
{"label": "好几天", "score": 1},
{"label": "一半以上的天数", "score": 2},
{"label": "几乎每天", "score": 3}
]},
{"id": 8, "text": "动作或说话速度缓慢到别人可以察觉,或正好相反——烦躁不安地动来动去", "options": [
{"label": "完全不会", "score": 0},
{"label": "好几天", "score": 1},
{"label": "一半以上的天数", "score": 2},
{"label": "几乎每天", "score": 3}
]},
{"id": 9, "text": "有不如死掉或者用某种方式伤害自己的念头", "options": [
{"label": "完全不会", "score": 0},
{"label": "好几天", "score": 1},
{"label": "一半以上的天数", "score": 2},
{"label": "几乎每天", "score": 3}
]}
]);
let scoring_rules = json!([
{"min": 0, "max": 4, "level": "normal", "label": "无抑郁症状"},
{"min": 5, "max": 9, "level": "mild", "label": "轻度抑郁"},
{"min": 10, "max": 14, "level": "moderate", "label": "中度抑郁"},
{"min": 15, "max": 19, "level": "moderate_severe", "label": "中重度抑郁"},
{"min": 20, "max": 27, "level": "severe", "label": "重度抑郁"}
]);
let data = json!({
"scale_code": "PHQ-9",
"title": "PHQ-9 患者健康问卷(抑郁筛查)",
"description": "Patient Health Questionnaire-9用于抑郁症状筛查和严重程度评估",
"questions_json": questions,
"scoring_rules_json": scoring_rules,
"status": "active",
"tenant_id": tenant_id,
});
let result = host_api::db_insert("assessment_scale", data.to_string().as_bytes())
.map_err(|e| format!("插入 PHQ-9 默认量表失败: {}", e))?;
let record: serde_json::Value =
serde_json::from_slice(&result).map_err(|e| format!("解析结果失败: {}", e))?;
host_api::log_write(
"info",
&format!("PHQ-9 默认量表已创建: id={}", record["id"].as_str().unwrap_or("?")),
);
Ok(())
}
export!(AssessmentPlugin);