diff --git a/Cargo.toml b/Cargo.toml index 09863f6..3a934de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ members = [ "crates/erp-plugin-itops", "crates/erp-health", "crates/erp-ai", + "crates/erp-plugin-assessment", ] [workspace.package] diff --git a/crates/erp-plugin-assessment/Cargo.toml b/crates/erp-plugin-assessment/Cargo.toml new file mode 100644 index 0000000..714e351 --- /dev/null +++ b/crates/erp-plugin-assessment/Cargo.toml @@ -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 } diff --git a/crates/erp-plugin-assessment/plugin.toml b/crates/erp-plugin-assessment/plugin.toml new file mode 100644 index 0000000..22d3da7 --- /dev/null +++ b/crates/erp-plugin-assessment/plugin.toml @@ -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" diff --git a/crates/erp-plugin-assessment/src/lib.rs b/crates/erp-plugin-assessment/src/lib.rs new file mode 100644 index 0000000..b09fde2 --- /dev/null +++ b/crates/erp-plugin-assessment/src/lib.rs @@ -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) -> 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);