feat(test): 业务逻辑级测试脚本+测试报告

- 04_test_business_logic.py: 业务逻辑测试v1(111用例)
- 04_test_business_logic_v2.py: 修正API路径后v2(107用例,通过率31.8%)
- 测试报告: 揭示大量API路径不匹配和参数问题
- 测试数据: SQL脚本覆盖31个业务模块
- 测试流程: 30个业务流程图+API映射

测试发现的问题:
1. 多个Controller缺少/page端点
2. 部分接口需要必填参数(patientId, startTime等)
3. 部分接口响应格式非标准(rows嵌套为dict)
4. DB列名不匹配(create_by不存在等)
This commit is contained in:
2026-06-07 21:54:20 +08:00
parent 8c414a6a91
commit e31337b58a
7 changed files with 3050 additions and 0 deletions

476
MD/test/01_test_data.sql Normal file
View File

@@ -0,0 +1,476 @@
-- ============================================================
-- HealthLink-HIS 三甲医院全流程测试数据
-- 版本: v2.0 (JDK 25 + Spring Boot 4.0.6 + Vue 3)
-- 日期: 2026-06-07
-- 说明: 覆盖门诊/住院/药房/检验/影像/手术/麻醉/护理/院感/质控/中医/会诊全流程
-- 注意: 仅插入测试数据,不删除现有数据
-- ============================================================
SET search_path TO healthlink_his;
-- ============================
-- 一、基础数据(科室/人员/组织)
-- ============================
-- 1.1 测试科室(使用现有科室,补充缺失科室)
INSERT INTO sys_dept (dept_id, parent_id, ancestors, dept_name, order_num, leader, phone, email, status, del_flag, create_by, create_time)
VALUES
(1001, 0, '0', '门诊内科', 10, '张主任', '13800000001', 'mnk@hospital.com', '0', '0', 'admin', NOW()),
(1002, 0, '0', '门诊外科', 11, '李主任', '13800000002', 'mwk@hospital.com', '0', '0', 'admin', NOW()),
(1003, 0, '0', '儿科门诊', 12, '王主任', '13800000003', 'ek@hospital.com', '0', '0', 'admin', NOW()),
(1004, 0, '0', '妇产科', 13, '赵主任', '13800000004', 'fck@hospital.com', '0', '0', 'admin', NOW()),
(1005, 0, '0', 'ICU', 14, '刘主任', '13800000005', 'icu@hospital.com', '0', '0', 'admin', NOW()),
(1006, 0, '0', '急诊科', 15, '陈主任', '13800000006', 'jzk@hospital.com', '0', '0', 'admin', NOW()),
(1007, 0, '0', '手术室', 16, '孙主任', '13800000007', 'ss@hospital.com', '0', '0', 'admin', NOW()),
(1008, 0, '0', '药房', 17, '周主任', '13800000008', 'yf@hospital.com', '0', '0', 'admin', NOW()),
(1009, 0, '0', '检验科', 18, '吴主任', '13800000009', 'jyk@hospital.com', '0', '0', 'admin', NOW()),
(1010, 0, '0', '影像科', 19, '郑主任', '13800000010', 'yxk@hospital.com', '0', '0', 'admin', NOW()),
(1011, 0, '0', '门诊部', 20, '黄院长', '13800000011', 'mzb@hospital.com', '0', '0', 'admin', NOW()),
(1012, 0, '0', '住院部', 21, '杨院长', '13800000012', 'zyb@hospital.com', '0', '0', 'admin', NOW())
ON CONFLICT (dept_id) DO NOTHING;
-- 1.2 测试医生
INSERT INTO sys_user (user_id, user_name, nick_name, dept_id, email, phonenumber, sex, status, del_flag, create_by, create_time)
VALUES
(2001, 'doctor_zhang', '张三医生', 1001, 'zhangsan@hospital.com', '13900000001', '1', '0', '0', 'admin', NOW()),
(2002, 'doctor_li', '李四医生', 1002, 'lisi@hospital.com', '13900000002', '1', '0', '0', 'admin', NOW()),
(2003, 'doctor_wang', '王五医生', 1003, 'wangwu@hospital.com', '13900000003', '1', '0', '0', 'admin', NOW()),
(2004, 'doctor_zhao', '赵六医生', 1004, 'zhaoliu@hospital.com', '13900000004', '1', '0', '0', 'admin', NOW()),
(2005, 'doctor_liu', '刘七医生', 1005, 'liuqi@hospital.com', '13900000005', '1', '0', '0', 'admin', NOW()),
(2006, 'doctor_chen', '陈八医生', 1006, 'chenba@hospital.com', '13900000006', '1', '0', '0', 'admin', NOW()),
(2007, 'doctor_sun', '孙九医生', 1007, 'sunjiu@hospital.com', '13900000007', '1', '0', '0', 'admin', NOW()),
(2008, 'doctor_zhou', '周十医生', 1008, 'zhoushi@hospital.com', '13900000008', '1', '0', '0', 'admin', NOW()),
(2009, 'doctor_wu', '吴十一医生', 1009, 'wushiyi@hospital.com', '13900000009', '1', '0', '0', 'admin', NOW()),
(2010, 'doctor_zheng', '郑十二医生', 1010, 'zhengershi@hospital.com', '13900000010', '1', '0', '0', 'admin', NOW())
ON CONFLICT (user_id) DO NOTHING;
-- 1.3 测试护士
INSERT INTO sys_user (user_id, user_name, nick_name, dept_id, email, phonenumber, sex, status, del_flag, create_by, create_time)
VALUES
(3001, 'nurse_a', '护士A', 1001, 'nursea@hospital.com', '13700000001', '2', '0', '0', 'admin', NOW()),
(3002, 'nurse_b', '护士B', 1005, 'nurseb@hospital.com', '13700000002', '2', '0', '0', 'admin', NOW()),
(3003, 'nurse_c', '护士C', 1006, 'nursec@hospital.com', '13700000003', '2', '0', '0', 'admin', NOW()),
(3004, 'nurse_d', '护士D', 1007, 'nursed@hospital.com', '13700000004', '2', '0', '0', 'admin', NOW())
ON CONFLICT (user_id) DO NOTHING;
-- ============================
-- 二、测试患者数据
-- ============================
-- 2.1 门诊患者
INSERT INTO adm_patient (id, name, gender_enum, birth_date, phone, id_card, address, organization_id, tenant_id, delete_flag, create_by, create_time)
VALUES
(5001, '测试患者甲', 1, '1990-01-15 00:00:00+08', '13800138001', '450102199001011234', '广西南宁市青秀区民族大道100号', 1, 1, '0', 'admin', NOW()),
(5002, '测试患者乙', 2, '1985-05-20 00:00:00+08', '13800138002', '450102198505052345', '广西南宁市兴宁区朝阳路200号', 1, 1, '0', 'admin', NOW()),
(5003, '测试患者丙', 1, '2000-10-08 00:00:00+08', '13800138003', '450102200010103456', '广西南宁市西乡塘区大学路300号', 1, 1, '0', 'admin', NOW()),
(5004, '测试患者丁', 2, '1975-12-25 00:00:00+08', '13800138004', '450102197512124567', '广西南宁市良庆区银海大道400号', 1, 1, '0', 'admin', NOW()),
(5005, '测试患者戊', 1, '1965-03-10 00:00:00+08', '13800138005', '450102196503101234', '广西南宁市邕宁区蒲庙镇500号', 1, 1, '0', 'admin', NOW()),
(5006, '测试患者己', 2, '2015-08-18 00:00:00+08', '13800138006', '450102201508186789', '广西南宁市江南区星光大道600号', 1, 1, '0', 'admin', NOW()),
(5007, '急诊患者庚', 1, '1988-07-07 00:00:00+08', '13800138007', '450102198807071111', '广西南宁市青秀区东葛路700号', 1, 1, '0', 'admin', NOW()),
(5008, '急诊患者辛', 2, '1992-11-11 00:00:00+08', '13800138008', '450102199211112222', '广西南宁市青秀区凤岭北路800号', 1, 1, '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 三、就诊记录(门诊+住院)
-- ============================
-- 3.1 门诊就诊记录 (class_enum=1门诊, class_enum=2住院)
INSERT INTO adm_encounter (id, patient_id, status_enum, class_enum, type_enum, start_time, organization_id, tenant_id, delete_flag, create_by, create_time)
VALUES
-- 门诊就诊
(6001, 5001, 2, 1, 1, '2026-06-07 09:00:00+08', 1, 1, '0', 'admin', NOW()),
(6002, 5002, 2, 1, 1, '2026-06-07 09:30:00+08', 1, 1, '0', 'admin', NOW()),
(6003, 5003, 2, 1, 1, '2026-06-07 10:00:00+08', 1, 1, '0', 'admin', NOW()),
(6004, 5004, 2, 1, 1, '2026-06-07 10:30:00+08', 1, 1, '0', 'admin', NOW()),
(6005, 5005, 2, 1, 1, '2026-06-07 11:00:00+08', 1, 1, '0', 'admin', NOW()),
-- 住院就诊
(6006, 5001, 2, 2, 1, '2026-06-01 14:00:00+08', 1, 1, '0', 'admin', NOW()),
(6007, 5002, 2, 2, 1, '2026-06-02 08:00:00+08', 1, 1, '0', 'admin', NOW()),
(6008, 5004, 2, 2, 1, '2026-06-03 10:00:00+08', 1, 1, '0', 'admin', NOW()),
(6009, 5005, 4, 2, 1, '2026-06-04 09:00:00+08', 1, 1, '0', 'admin', NOW()),
(6010, 5006, 2, 1, 1, '2026-06-07 14:00:00+08', 1, 1, '0', 'admin', NOW()),
-- 急诊就诊
(6011, 5007, 2, 1, 1, '2026-06-07 02:30:00+08', 1, 1, '0', 'admin', NOW()),
(6012, 5008, 2, 1, 1, '2026-06-07 03:15:00+08', 1, 1, '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 四、诊断数据
-- ============================
INSERT INTO adm_encounter_diagnosis (id, encounter_id, patient_id, diagnosis_type_enum, delete_flag, create_by, create_time)
VALUES
(7001, 6001, 5001, 1, '0', 'admin', NOW()),
(7002, 6002, 5002, 1, '0', 'admin', NOW()),
(7003, 6006, 5001, 1, '0', 'admin', NOW()),
(7004, 6007, 5002, 1, '0', 'admin', NOW()),
(7005, 6008, 5004, 1, '0', 'admin', NOW()),
(7006, 6009, 5005, 1, '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 五、检查检验数据
-- ============================
-- 5.1 检查申请
INSERT INTO check_apply (id, apply_no, encounter_id, patient_id, patient_name, id_card, fee_type, apply_date, apply_dept_id, apply_doctor_id, diagnosis_desc, check_purpose, status, total_amount, create_time)
VALUES
(8001, 'CK20260607001', 6001, 5001, '测试患者甲', '450102199001011234', '1', '2026-06-07 09:15:00+08', 1010, 2001, '咳嗽咳痰3天', '排除肺炎', 1, 280.00, NOW()),
(8002, 'CK20260607002', 6002, 5002, '测试患者乙', '450102198505052345', '1', '2026-06-07 09:45:00+08', 1010, 2002, '头痛头晕1周', '排除颅内病变', 1, 560.00, NOW()),
(8003, 'CK20260607003', 6011, 5007, '急诊患者庚', '450102198807071111', '1', '2026-06-07 02:45:00+08', 1010, 2006, '外伤后腹痛2小时', '排除脏器损伤', 1, 420.00, NOW())
ON CONFLICT (id) DO NOTHING;
-- 5.2 检查项目明细
INSERT INTO check_apply_detail (id, apply_id, check_item_name, check_part, check_method, create_time)
VALUES
(9001, 8001, '胸部CT平扫', '胸部', 'CT', NOW()),
(9002, 8001, '血常规', '静脉血', '检验', NOW()),
(9003, 8002, '头颅MRI', '头部', 'MRI', NOW()),
(9004, 8002, '经颅多普勒', '头部', '超声', NOW()),
(9005, 8003, '腹部CT增强', '腹部', 'CT', NOW()),
(9006, 8003, '全血细胞计数', '静脉血', '检验', NOW())
ON CONFLICT (id) DO NOTHING;
-- 5.3 检验申请
INSERT INTO lab_apply (id, apply_no, patient_id, patient_name, apply_dept_code, apply_doc_code, apply_doc_name, apply_time, apply_status, delete_flag, create_by, create_time)
VALUES
(10001, 'LAB20260607001', 5001, '测试患者甲', '1009', '2009', '吴十一医生', '2026-06-07 09:20:00+08', '1', '0', 'admin', NOW()),
(10002, 'LAB20260607002', 5002, '测试患者乙', '1009', '2009', '吴十一医生', '2026-06-07 09:50:00+08', '1', '0', 'admin', NOW()),
(10003, 'LAB20260607003', 5006, '测试患者己', '1009', '2009', '吴十一医生', '2026-06-07 14:10:00+08', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 六、影像数据
-- ============================
INSERT INTO radiology_image_report (id, apply_no, patient_id, patient_name, report_status, create_time)
VALUES
(11001, 'CK20260607001', 5001, '测试患者甲', '1', NOW()),
(11002, 'CK20260607002', 5002, '测试患者乙', '1', NOW()),
(11003, 'CK20260607003', 5007, '急诊患者庚', '1', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 七、手术数据
-- ============================
INSERT INTO cli_surgery (id, patient_id, encounter_id, delete_flag, create_by, create_time)
VALUES
(12001, 5001, 6006, '0', 'admin', NOW()),
(12002, 5004, 6008, '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 八、麻醉数据
-- ============================
INSERT INTO anes_record (id, patient_id, encounter_id, delete_flag, create_by, create_time)
VALUES
(13001, 5001, 6006, '0', 'admin', NOW()),
(13002, 5004, 6008, '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 九、护理数据
-- ============================
-- 9.1 护理评估
INSERT INTO nursing_assessment (id, patient_id, encounter_id, assessment_type, assessment_score, risk_level, delete_flag, create_by, create_time)
VALUES
(14001, 5001, 6006, 'braden', 12, 'high', '0', 'admin', NOW()),
(14002, 5002, 6007, 'morse', 45, 'high', '0', 'admin', NOW()),
(14003, 5004, 6008, 'nrs2002', 4, 'at_risk', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- 9.2 护理记录
INSERT INTO nursing_vital_signs_chart (id, patient_id, encounter_id, temperature, pulse, respiration, blood_pressure_systolic, blood_pressure_diastolic, oxygen_saturation, delete_flag, create_by, create_time)
VALUES
(15001, 5001, 6006, 37.2, 78, 18, 125, 82, 98.5, '0', 'admin', NOW()),
(15002, 5002, 6007, 36.8, 72, 16, 130, 85, 99.0, '0', 'admin', NOW()),
(15003, 5004, 6008, 37.5, 85, 20, 140, 90, 97.5, '0', 'admin', NOW()),
(15004, 5005, 6009, 38.2, 92, 22, 150, 95, 96.0, '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 十、院感数据
-- ============================
INSERT INTO hir_infection_case (id, patient_id, encounter_id, infection_type, pathogen, report_date, delete_flag, create_by, create_time)
VALUES
(16001, 5001, 6006, '医院获得性肺炎', '铜绿假单胞菌', '2026-06-03 10:00:00+08', '0', 'admin', NOW()),
(16002, 5002, 6007, '导管相关血流感染', '金黄色葡萄球菌', '2026-06-05 14:00:00+08', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
INSERT INTO hir_hand_hygiene (id, dept_id, dept_name, month, total_opportunities, compliant_count, compliance_rate, delete_flag, create_by, create_time)
VALUES
(17001, 1005, 'ICU', '2026-06', 1200, 1140, 95.0, '0', 'admin', NOW()),
(17002, 1001, '门诊内科', '2026-06', 800, 720, 90.0, '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 十一、质控数据
-- ============================
INSERT INTO emr_quality_score (id, encounter_id, patient_id, quality_type, score, delete_flag, create_by, create_time)
VALUES
(18001, 6006, 5001, '运行质控', 92.5, '0', 'admin', NOW()),
(18002, 6007, 5002, '终末质控', 88.0, '0', 'admin', NOW()),
(18003, 6008, 5004, '运行质控', 95.0, '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 十二、中医数据
-- ============================
INSERT INTO tcm_constitution_assessment (id, patient_id, encounter_id, constitution_type, assessment_score, delete_flag, create_by, create_time)
VALUES
(19001, 5001, 6006, '气虚质', 65, '0', 'admin', NOW()),
(19002, 5002, 6007, '阳虚质', 70, '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
INSERT INTO tcm_prescription (id, prescription_name, prescription_type, composition, usage_method, delete_flag, create_by, create_time)
VALUES
(20001, '四君子汤', '补益剂', '人参、白术、茯苓、甘草', '水煎服,日一剂', '0', 'admin', NOW()),
(20002, '六味地黄丸', '补益剂', '熟地黄、山药、泽泻、牡丹皮、茯苓、山茱萸', '口服一次8丸一日3次', '0', 'admin', NOW()),
(20003, '小柴胡汤', '和解剂', '柴胡、黄芩、人参、半夏、甘草、生姜、大枣', '水煎服,日一剂', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 十三、会诊数据
-- ============================
INSERT INTO consultation_record (id, patient_id, encounter_id, consultation_type, requesting_dept, requested_dept, status, delete_flag, create_by, create_time)
VALUES
(21001, 5001, 6006, '科间会诊', 'ICU', '呼吸内科', '1', '0', 'admin', NOW()),
(21002, 5002, 6007, '全院会诊', 'ICU', '心内科', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 十四、临床路径数据
-- ============================
INSERT INTO clinical_pathway (id, pathway_name, disease_name, pathway_type, status, delete_flag, create_by, create_time)
VALUES
(22001, '社区获得性肺炎', '社区获得性肺炎', '内科', '1', '0', 'admin', NOW()),
(22002, '急性阑尾炎', '急性阑尾炎', '外科', '1', '0', 'admin', NOW()),
(22003, '2型糖尿病', '2型糖尿病', '内科', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 十五、危急值数据
-- ============================
INSERT INTO critical_value (id, patient_id, encounter_id, critical_item, critical_value, report_time, status, delete_flag, create_by, create_time)
VALUES
(23001, 5001, 6006, '血钾', '6.8mmol/L', '2026-06-03 15:30:00+08', '1', '0', 'admin', NOW()),
(23002, 5002, 6007, '血红蛋白', '52g/L', '2026-06-05 08:00:00+08', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 十六、电子病历数据
-- ============================
INSERT INTO doc_emr (id, encounter_id, patient_id, emr_type, emr_status, delete_flag, create_by, create_time)
VALUES
(24001, 6006, 5001, '入院记录', '1', '0', 'admin', NOW()),
(24002, 6007, 5002, '入院记录', '1', '0', 'admin', NOW()),
(24003, 6008, 5004, '入院记录', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 十七、处方数据
-- ============================
INSERT INTO med_medication_request (id, patient_id, encounter_id, request_type, status, delete_flag, create_by, create_time)
VALUES
(25001, 5001, 6006, '1', '1', '0', 'admin', NOW()),
(25002, 5002, 6007, '1', '1', '0', 'admin', NOW()),
(25003, 5004, 6008, '1', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 十八、药品库存数据
-- ============================
INSERT INTO pharmacy_stock_alert (id, medication_id, current_stock, minimum_stock, alert_level, delete_flag, create_by, create_time)
VALUES
(26001, 2037002083193978881, 50, 100, 'warning', '0', 'admin', NOW()),
(26002, 1983813501487038465, 10, 50, 'critical', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 十九、抗生素管理数据
-- ============================
INSERT INTO antibiotic_approval (id, patient_id, encounter_id, antibiotic_name, approval_status, delete_flag, create_by, create_time)
VALUES
(27001, 5001, 6006, '头孢曲松', '1', '0', 'admin', NOW()),
(27002, 5002, 6007, '万古霉素', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 二十、药品追溯数据
-- ============================
INSERT INTO drug_trace_code (id, drug_code, drug_name, batch_no, production_date, expiry_date, delete_flag, create_by, create_time)
VALUES
(28001, 'DRG001', '阿莫西林胶囊', 'B20260101', '2026-01-01', '2028-01-01', '0', 'admin', NOW()),
(28002, 'DRG002', '布洛芬缓释胶囊', 'B20260201', '2026-02-01', '2028-02-01', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 二十一、处方点评数据
-- ============================
INSERT INTO review_plan (id, plan_name, plan_type, review_period, status, delete_flag, create_by, create_time)
VALUES
(29001, '2026年6月处方点评', '月度', '2026-06', '1', '0', 'admin', NOW()),
(29002, '2026年第二季度处方点评', '季度', '2026-Q2', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 二十二、DRG分析数据
-- ============================
INSERT INTO drg_analysis_stats (id, encounter_id, drg_group, cost_weight, los_weight, delete_flag, create_by, create_time)
VALUES
(30001, 6006, 'ER1', 1.2, 1.0, '0', 'admin', NOW()),
(30002, 6007, 'FR1', 0.8, 0.9, '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 二十三、随访数据
-- ============================
INSERT INTO followup_plan (id, patient_id, encounter_id, followup_type, followup_date, status, delete_flag, create_by, create_time)
VALUES
(31001, 5001, 6006, '电话随访', '2026-06-14', '1', '0', 'admin', NOW()),
(31002, 5002, 6007, '门诊复查', '2026-06-20', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 二十四、知情同意数据
-- ============================
INSERT INTO sys_informed_consent (id, patient_id, encounter_id, consent_type, status, delete_flag, create_by, create_time)
VALUES
(32001, 5001, 6006, '手术知情同意书', '1', '0', 'admin', NOW()),
(32002, 5002, 6007, '麻醉知情同意书', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 二十五、消毒供应中心数据
-- ============================
INSERT INTO cssd_sterilize_batch (id, batch_no, sterilize_type, status, delete_flag, create_by, create_time)
VALUES
(33001, 'CSSD20260607001', '高压蒸汽', '1', '0', 'admin', NOW()),
(33002, 'CSSD20260607002', '低温等离子', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 二十六、EMPI主索引数据
-- ============================
INSERT INTO empi_person (id, name, gender_enum, birth_date, id_card, phone, delete_flag, create_by, create_time)
VALUES
(34001, '测试患者甲', 1, '1990-01-15', '450102199001011234', '13800138001', '0', 'admin', NOW()),
(34002, '测试患者乙', 2, '1985-05-20', '450102198505052345', '13800138002', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 二十七、ESB数据集成数据
-- ============================
INSERT INTO sys_esb_service_registry (id, service_name, service_code, service_type, status, delete_flag, create_by, create_time)
VALUES
(35001, '患者信息查询', 'PATIENT_QUERY', 'FHIR', '1', '0', 'admin', NOW()),
(35002, '检验结果查询', 'LAB_RESULT_QUERY', 'HL7', '1', '0', 'admin', NOW()),
(35003, '医嘱查询', 'ORDER_QUERY', 'FHIR', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 二十八、急诊绿色通道数据
-- ============================
INSERT INTO emergency_green_channel (id, patient_id, encounter_id, channel_type, status, delete_flag, create_by, create_time)
VALUES
(36001, 5007, 6011, '胸痛中心', '1', '0', 'admin', NOW()),
(36002, 5008, 6012, '卒中中心', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 二十九、病案首页数据
-- ============================
INSERT INTO mr_homepage (id, encounter_id, patient_id, homepage_status, delete_flag, create_by, create_time)
VALUES
(37001, 6009, 5005, '1', '0', 'admin', NOW()),
(37002, 6008, 5004, '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 三十、医嘱闭环数据
-- ============================
INSERT INTO order_main (id, encounter_id, patient_id, order_type, order_status, delete_flag, create_by, create_time)
VALUES
(38001, 6006, 5001, '1', '1', '0', 'admin', NOW()),
(38002, 6007, 5002, '1', '1', '0', 'admin', NOW()),
(38003, 6008, 5004, '2', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 三十一、护理质量指标数据
-- ============================
INSERT INTO nursing_quality_indicator (id, indicator_name, indicator_code, target_value, actual_value, indicator_period, delete_flag, create_by, create_time)
VALUES
(39001, '压疮发生率', 'NQ001', '0.5', '0.3', '2026-06', '0', 'admin', NOW()),
(39002, '跌倒发生率', 'NQ002', '1.0', '0.8', '2026-06', '0', 'admin', NOW()),
(39003, '导管滑脱率', 'NQ003', '0.5', '0.2', '2026-06', '0', 'admin', NOW()),
(39004, '给药差错率', 'NQ004', '0.1', '0.05', '2026-06', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 三十二、抗菌药物使用数据
-- ============================
INSERT INTO hir_antibiotic_usage (id, patient_id, encounter_id, antibiotic_name, usage_days, ddd_value, delete_flag, create_by, create_time)
VALUES
(40001, 5001, 6006, '头孢曲松', 7, 2.0, '0', 'admin', NOW()),
(40002, 5002, 6007, '万古霉素', 10, 1.5, '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 三十三、病案编码(DRG)数据
-- ============================
INSERT INTO mr_drg_grouping (id, encounter_id, drg_code, drg_name, cost_weight, delete_flag, create_by, create_time)
VALUES
(41001, 6009, 'ER1', '呼吸系统感染', 1.2, '0', 'admin', NOW()),
(41002, 6008, 'FR1', '急性阑尾炎', 0.8, '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 三十四、满意度调查数据
-- ============================
INSERT INTO satisfaction_survey (id, patient_id, encounter_id, survey_score, survey_type, delete_flag, create_by, create_time)
VALUES
(42001, 5005, 6009, 92, '出院患者', '0', 'admin', NOW()),
(42002, 5001, 6006, 88, '住院患者', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 三十五、交接班数据
-- ============================
INSERT INTO nursing_handoff (id, from_nurse_id, to_nurse_id, handoff_time, handoff_type, status, delete_flag, create_by, create_time)
VALUES
(43001, 3001, 3002, '2026-06-07 08:00:00+08', '白班转夜班', '1', '0', 'admin', NOW())
ON CONFLICT (id) DO NOTHING;
-- ============================
-- 完成!
-- ============================

1020
MD/test/04_test_business_logic.py Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,631 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
HealthLink-HIS 三甲医院全流程业务逻辑测试 v2
使用实际Controller中的正确API路径
"""
import requests, json, sys, os, time
from datetime import datetime
from typing import Dict, Any, List
BASE_URL = "http://localhost:18082/healthlink-his"
TOKEN = ""
class TestStats:
def __init__(self):
self.total = self.passed = self.failed = 0
self.results = []
def record(self, module, case_id, name, passed, detail=""):
self.total += 1
if passed: self.passed += 1
else: self.failed += 1
status = "✅ PASS" if passed else "❌ FAIL"
self.results.append({"module":module,"case_id":case_id,"name":name,"status":status,"detail":detail})
print(f" {status} [{module}] {case_id}: {name}")
if detail and not passed: print(f"{detail}")
def summary(self):
print(f"\n{'='*70}")
print(f"测试汇总: 总数={self.total}, 通过={self.passed}, 失败={self.failed}")
if self.total > 0: print(f"通过率: {self.passed*100/self.total:.1f}%")
print(f"{'='*70}")
return self.failed == 0
stats = TestStats()
def login():
r = requests.post(f"{BASE_URL}/login", json={"username":"admin","password":"admin123","tenantId":"1"})
return r.json().get("token","")
def H(): return {"Authorization":f"Bearer {TOKEN}","Content-Type":"application/json"}
def GET(p, params=None): return requests.get(f"{BASE_URL}{p}", headers=H(), params=params).json()
def POST(p, d=None): return requests.post(f"{BASE_URL}{p}", headers=H(), json=d).json()
def PUT(p, d=None): return requests.put(f"{BASE_URL}{p}", headers=H(), json=d).json()
def chk_resp(resp, mod, cid, name, code=200, fields=None, not_empty=None):
ok = True; detail = ""
if resp.get("code") != code:
ok = False; detail = f"code={resp.get('code')}, msg={resp.get('msg','')[:120]}"
if ok and fields:
for f in fields:
if f not in resp: ok = False; detail=f"缺少字段: {f}"; break
if ok and not_empty:
for f in not_empty:
v = resp.get(f)
if v is None or (isinstance(v,(list,dict)) and len(v)==0):
ok=False; detail=f"字段{f}为空"; break
stats.record(mod, cid, name, ok, detail)
return resp
def chk_page(resp, mod, cid, name, min_rows=0):
ok = True; detail = ""
if resp.get("code") != 200:
ok = False; detail = f"code={resp.get('code')}, msg={resp.get('msg','')[:120]}"
else:
rows = resp.get("rows", resp.get("data", []))
if not isinstance(rows, list):
ok = False; detail = f"rows类型异常: {type(rows)}"
elif len(rows) < min_rows:
ok = False; detail = f"rows={len(rows)}, 需要>={min_rows}"
stats.record(mod, cid, name, ok, detail)
return resp
# ============================
# 模块1: 系统登录认证
# ============================
def test_auth():
print(f"\n{'='*50}\n模块1: 系统登录认证\n{'='*50}")
r = POST("/login", {"username":"admin","password":"admin123","tenantId":"1"})
chk_resp(r, "认证","1.1","登录成功-返回token", 200, ["token"], ["token"])
r = POST("/login", {"username":"admin","password":"wrong","tenantId":"1"})
chk_resp(r, "认证","1.2","错误密码-应失败", 500)
r = GET("/getInfo")
chk_resp(r, "认证","1.3","获取用户信息", 200, ["user","roles"], ["user"])
r = GET("/getRouters")
chk_resp(r, "认证","1.4","获取路由菜单", 200, ["data"], ["data"])
# ============================
# 模块2: 门诊挂号 (实际路径: /charge-manage/register)
# ============================
def test_registration():
print(f"\n{'='*50}\n模块2: 门诊挂号流程\n{'='*50}")
# 2.1 挂号初始化 - 应返回选项数据
r = GET("/charge-manage/register/init")
chk_resp(r, "挂号","2.1","挂号初始化", 200)
# 2.2 当日挂号列表 (current-day-encounter)
r = GET("/charge-manage/register/current-day-encounter")
chk_resp(r, "挂号","2.2","当日挂号列表", 200)
# 2.3 患者元数据查询
r = GET("/charge-manage/register/patient-metadata", {"searchKey":"测试"})
chk_resp(r, "挂号","2.3","患者元数据查询", 200)
# 2.4 医生列表
r = GET("/charge-manage/register/all-doctors")
chk_resp(r, "挂号","2.4","全部医生列表", 200)
# ============================
# 模块3: 门诊医生站 (实际路径)
# ============================
def test_doctor_station():
print(f"\n{'='*50}\n模块3: 门诊医生站\n{'='*50}")
# 3.1 医生站初始化
r = GET("/doctor-station/main/init")
chk_resp(r, "医生站","3.1","医生站初始化", 200)
# 3.2 患者信息查询
r = GET("/doctor-station/main/patient-info")
chk_resp(r, "医生站","3.2","患者信息查询", 200)
# 3.3 接诊统计
r = GET("/doctor-station/main/reception-statistics")
chk_resp(r, "医生站","3.3","接诊统计", 200)
# 3.4 医嘱基础信息
r = GET("/doctor-station/advice/advice-base-info")
chk_resp(r, "医生站","3.4","医嘱基础信息", 200)
# 3.5 诊断初始化
r = GET("/doctor-station/diagnosis/init")
chk_resp(r, "医生站","3.5","诊断初始化", 200)
# 3.6 诊断定义分类
r = GET("/doctor-station/diagnosis/get-condition-definition-class")
chk_resp(r, "医生站","3.6","诊断定义分类", 200)
# 3.7 检查申请
r = GET("/doctor-station/inspection/init")
chk_resp(r, "医生站","3.7","检查申请初始化", 200)
# ============================
# 模块4: 收费管理 (实际路径)
# ============================
def test_charge():
print(f"\n{'='*50}\n模块4: 收费管理\n{'='*50}")
# 4.1 门诊收费初始化
r = GET("/charge-manage/charge/init")
chk_resp(r, "收费","4.1","门诊收费初始化", 200)
# 4.2 门诊收费-患者列表
r = GET("/charge-manage/charge/encounter-patient-page")
chk_resp(r, "收费","4.2","收费患者列表", 200)
# 4.3 退费初始化
r = GET("/charge-manage/refund/init")
chk_resp(r, "收费","4.3","退费初始化", 200)
# 4.4 退费患者列表
r = GET("/charge-manage/refund/encounter-patient-page")
chk_resp(r, "收费","4.4","退费患者列表", 200)
# 4.5 住院收费初始化
r = GET("/charge-manage/inpatient-charge/init")
chk_resp(r, "收费","4.5","住院收费初始化", 200)
# 4.6 住院收费-患者列表
r = GET("/charge-manage/inpatient-charge/encounter-patient-page")
chk_resp(r, "收费","4.6","住院收费患者列表", 200)
# 4.7 定价-患者信息
r = GET("/charge-manage/pricing/patient-info")
chk_resp(r, "收费","4.7","定价患者信息", 200)
# ============================
# 模块5: 住院管理 (实际路径)
# ============================
def test_inpatient():
print(f"\n{'='*50}\n模块5: 住院管理\n{'='*50}")
# 5.1 患者主页初始化
r = GET("/patient-home-manage/init")
chk_resp(r, "住院","5.1","患者主页初始化", 200)
# 5.2 空床查询
r = GET("/patient-home-manage/empty-bed")
chk_resp(r, "住院","5.2","空床查询", 200)
# 5.3 科室统计
r = GET("/patient-home-manage/caty")
chk_resp(r, "住院","5.3","科室统计", 200)
# 5.4 押金初始化
r = GET("/deposit-manage/init")
chk_resp(r, "住院","5.4","押金初始化", 200)
# 5.5 入院登记-按医生
r = GET("/inhospitalmanage/register/ward-list")
chk_resp(r, "住院","5.5","入院登记-病区列表", 200)
# 5.6 入院登记-床位数
r = GET("/inhospitalmanage/register/beds-num")
chk_resp(r, "住院","5.6","入院登记-床位数", 200)
# 5.7 入院登记-患者信息
r = GET("/inhospitalmanage/register/patient-info")
chk_resp(r, "住院","5.7","入院登记-患者信息", 200)
# ============================
# 模块6: 护理管理
# ============================
def test_nursing():
print(f"\n{'='*50}\n模块6: 护理管理\n{'='*50}")
# 6.1 护理评估列表
r = GET("/nursing-assessment-enhanced/page", {"pageNum":1,"pageSize":10})
chk_page(r, "护理","6.1","护理评估列表")
# 6.2 护理评估统计
r = GET("/nursing-assessment-enhanced/stats")
chk_resp(r, "护理","6.2","护理评估统计", 200)
# 6.3 Braden评估 - 验证分数计算
braden = {"patientName":"测试患者甲","encounterId":"6006",
"itemScores":json.dumps({"sensation":2,"moisture":2,"activity":1,"mobility":2,"nutrition":3,"friction":2}),
"detail":"压疮高危"}
r = POST("/nursing-assessment-enhanced/braden/assess", braden)
chk_resp(r, "护理","6.3","Braden评估-成功", 200)
# 6.4 Morse跌倒评估
morse = {"patientName":"测试患者乙","encounterId":"6007",
"itemScores":json.dumps({"history":15,"diagnosis":0,"ambulation":15,"iv":20,"gait":0,"mental":15}),
"detail":"跌倒高危"}
r = POST("/nursing-assessment-enhanced/morse/assess", morse)
chk_resp(r, "护理","6.4","Morse评估-成功", 200)
# 6.5 体征记录查询
r = GET("/vital-signs/record-search")
chk_resp(r, "护理","6.5","体征记录查询", 200)
# 6.6 体征图表
r = GET("/vital-signs-chart/page", {"pageNum":1,"pageSize":10})
chk_page(r, "护理","6.6","体征图表")
# 6.7 护理执行列表
r = GET("/nurse-station/advice-process/page", {"pageNum":1,"pageSize":10})
chk_page(r, "护理","6.7","护理执行列表")
# 6.8 护理质量
r = GET("/nursing-quality/page", {"pageNum":1,"pageSize":10})
chk_page(r, "护理","6.8","护理质量指标")
# ============================
# 模块7: 检验检查
# ============================
def test_inspection():
print(f"\n{'='*50}\n模块7: 检验检查\n{'='*50}")
endpoints = [
("7.1","标本采集","/inspection/collection/page"),
("7.2","检验观察","/inspection/observation/page"),
("7.3","标本定义","/inspection/specimen/page"),
("7.4","LIS配置","/inspection/lisConfig/page"),
("7.5","仪器管理","/inspection/instrument/page"),
("7.6","检验结果","/inspection/laboratory/page"),
("7.7","参考范围","/lab-ref-range/page"),
("7.8","检查申请","/exam/apply/page"),
]
for cid,name,path in endpoints:
r = GET(path, {"pageNum":1,"pageSize":10})
chk_page(r, "检验", cid, name)
# ============================
# 模块8: 影像检查
# ============================
def test_radiology():
print(f"\n{'='*50}\n模块8: 影像检查\n{'='*50}")
r = GET("/radiology-image/page", {"pageNum":1,"pageSize":10})
chk_page(r, "影像","8.1","影像列表")
r = GET("/radiology-enhanced/page", {"pageNum":1,"pageSize":10})
chk_page(r, "影像","8.2","影像增强")
r = GET("/radiology-comparison/page", {"pageNum":1,"pageSize":10})
chk_page(r, "影像","8.3","影像对比")
r = GET("/reconstruction/page", {"pageNum":1,"pageSize":10})
chk_page(r, "影像","8.4","3D重建")
# ============================
# 模块9: 手术麻醉
# ============================
def test_surgery():
print(f"\n{'='*50}\n模块9: 手术麻醉\n{'='*50}")
r = GET("/clinical-manage/surgery/page", {"pageNum":1,"pageSize":10})
chk_page(r, "手术","9.1","手术列表")
r = GET("/clinical-manage/surgery-schedule/page", {"pageNum":1,"pageSize":10})
chk_page(r, "手术","9.2","手术排程")
r = GET("/preop-discussion/page", {"pageNum":1,"pageSize":10})
chk_page(r, "手术","9.3","术前讨论")
r = GET("/surgery-safety-check/page", {"pageNum":1,"pageSize":10})
chk_page(r, "手术","9.4","安全核查")
r = GET("/api/v1/anesthesia/page", {"pageNum":1,"pageSize":10})
chk_page(r, "麻醉","9.5","麻醉记录")
r = GET("/anesthesia-enhanced/page", {"pageNum":1,"pageSize":10})
chk_page(r, "麻醉","9.6","麻醉增强")
# ============================
# 模块10: 院感管理
# ============================
def test_infection():
print(f"\n{'='*50}\n模块10: 院感管理\n{'='*50}")
r = GET("/infection-enhanced/surveillance/page", {"pageNum":1,"pageSize":10})
chk_page(r, "院感","10.1","院感监测")
r = GET("/infection-enhanced/warning/page", {"pageNum":1,"pageSize":10})
chk_page(r, "院感","10.2","院感预警")
r = GET("/infection-enhanced/resistance/page", {"pageNum":1,"pageSize":10})
chk_page(r, "院感","10.3","耐药监测")
r = GET("/infection-enhanced/exposure/page", {"pageNum":1,"pageSize":10})
chk_page(r, "院感","10.4","职业暴露")
r = GET("/infection-enhanced/hand-hygiene/page", {"pageNum":1,"pageSize":10})
chk_page(r, "院感","10.5","手卫生")
r = GET("/infection-enhanced/environment/page", {"pageNum":1,"pageSize":10})
chk_page(r, "院感","10.6","环境监测")
# ============================
# 模块11: 质量管理
# ============================
def test_quality():
print(f"\n{'='*50}\n模块11: 质量管理\n{'='*50}")
r = GET("/quality-enhanced/runtime/page", {"pageNum":1,"pageSize":10})
chk_page(r, "质控","11.1","运行质控")
r = GET("/api/v1/emr-quality/page", {"pageNum":1,"pageSize":10})
chk_page(r, "质控","11.2","终末质控")
r = GET("/quality-enhanced/statistics/page", {"pageNum":1,"pageSize":10})
chk_page(r, "质控","11.3","质量统计")
# ============================
# 模块12: 中医管理
# ============================
def test_tcm():
print(f"\n{'='*50}\n模块12: 中医管理\n{'='*50}")
r = GET("/api/v1/tcm/constitution/page", {"pageNum":1,"pageSize":10})
chk_page(r, "中医","12.1","中医体质", min_rows=1)
r = GET("/api/v1/tcm/prescriptions", {"pageNum":1,"pageSize":10})
rows = r.get("rows", r.get("data", []))
ok = isinstance(rows, list) and len(rows) >= 3
stats.record("中医","12.2","方剂列表>=3个", ok, "" if ok else f"实际={len(rows)}")
r = GET("/api/v1/tcm/statistics")
chk_resp(r, "中医","12.3","中医统计", 200)
# ============================
# 模块13: 会诊管理
# ============================
def test_consultation():
print(f"\n{'='*50}\n模块13: 会诊管理\n{'='*50}")
r = GET("/consultation/page", {"pageNum":1,"pageSize":10})
chk_page(r, "会诊","13.1","会诊记录")
r = GET("/cross-module/consult-feedback/page", {"pageNum":1,"pageSize":10})
chk_page(r, "会诊","13.2","会诊反馈")
r = GET("/cross-module/consulttimeout/page", {"pageNum":1,"pageSize":10})
chk_page(r, "会诊","13.3","会诊超时")
# ============================
# 模块14: 临床路径
# ============================
def test_pathway():
print(f"\n{'='*50}\n模块14: 临床路径\n{'='*50}")
r = GET("/clinical-pathway/page", {"pageNum":1,"pageSize":10})
rows = r.get("rows", r.get("data", []))
ok = isinstance(rows, list) and len(rows) >= 2
stats.record("路径","14.1","临床路径>=2条", ok, "" if ok else f"实际={len(rows)}")
# ============================
# 模块15: 危急值
# ============================
def test_critical():
print(f"\n{'='*50}\n模块15: 危急值管理\n{'='*50}")
r = GET("/api/v1/critical-value/page", {"pageNum":1,"pageSize":10})
chk_page(r, "危急值","15.1","危急值列表")
# ============================
# 模块16: 处方点评
# ============================
def test_review():
print(f"\n{'='*50}\n模块16: 处方点评\n{'='*50}")
r = GET("/api/v1/review/plans", {"pageNum":1,"pageSize":10})
chk_page(r, "点评","16.1","点评计划")
r = GET("/api/v1/review/records", {"pageNum":1,"pageSize":10})
chk_page(r, "点评","16.2","点评记录")
r = GET("/api/v1/review/statistics")
chk_resp(r, "点评","16.3","点评统计", 200)
# ============================
# 模块17: 合理用药
# ============================
def test_rational_drug():
print(f"\n{'='*50}\n模块17: 合理用药\n{'='*50}")
r = GET("/api/v1/rational-drug/page", {"pageNum":1,"pageSize":10})
chk_page(r, "用药","17.1","合理用药")
r = GET("/api/v1/rational-drug/interaction/page", {"pageNum":1,"pageSize":10})
chk_page(r, "用药","17.2","相互作用")
r = GET("/api/v1/rational-drug/statistics")
chk_resp(r, "用药","17.3","用药统计", 200)
r = GET("/api/v1/rational-drug/audit-log", {"pageNum":1,"pageSize":10})
chk_page(r, "用药","17.4","审计日志")
# ============================
# 模块18: 药品追溯
# ============================
def test_drug_trace():
print(f"\n{'='*50}\n模块18: 药品追溯\n{'='*50}")
r = GET("/drugtrace/page", {"pageNum":1,"pageSize":10})
chk_page(r, "追溯","18.1","药品追溯")
# ============================
# 模块19: EMPI
# ============================
def test_empi():
print(f"\n{'='*50}\n模块19: EMPI主索引\n{'='*50}")
r = GET("/api/v1/empi/page", {"pageNum":1,"pageSize":10})
chk_page(r, "EMPI","19.1","EMPI索引")
# ============================
# 模块20: ESB
# ============================
def test_esb():
print(f"\n{'='*50}\n模块20: ESB数据集成\n{'='*50}")
r = GET("/esb/message/page", {"pageNum":1,"pageSize":10})
chk_page(r, "ESB","20.1","ESB消息")
r = GET("/esb/registry/page", {"pageNum":1,"pageSize":10})
chk_page(r, "ESB","20.2","ESB服务注册")
# ============================
# 模块21: CA签名
# ============================
def test_ca():
print(f"\n{'='*50}\n模块21: 电子签名\n{'='*50}")
r = GET("/api/v1/ca-signature/page", {"pageNum":1,"pageSize":10})
chk_page(r, "CA","21.1","CA签名")
r = GET("/api/v1/ca-signature/statistics")
chk_resp(r, "CA","21.2","CA签名统计", 200)
# ============================
# 模块22: 病案管理
# ============================
def test_mr():
print(f"\n{'='*50}\n模块22: 病案管理\n{'='*50}")
r = GET("/api/v1/mr-homepage/page", {"pageNum":1,"pageSize":10})
chk_page(r, "病案","22.1","病案首页")
# ============================
# 模块23: 随访
# ============================
def test_followup():
print(f"\n{'='*50}\n模块23: 随访管理\n{'='*50}")
r = GET("/followup/page", {"pageNum":1,"pageSize":10})
chk_page(r, "随访","23.1","随访计划")
# ============================
# 模块24: 知情同意
# ============================
def test_consent():
print(f"\n{'='*50}\n模块24: 知情同意\n{'='*50}")
r = GET("/informed-consent/page", {"pageNum":1,"pageSize":10})
chk_page(r, "知情","24.1","知情同意")
# ============================
# 模块25: 消毒供应
# ============================
def test_cssd():
print(f"\n{'='*50}\n模块25: 消毒供应\n{'='*50}")
r = GET("/cssd/page", {"pageNum":1,"pageSize":10})
chk_page(r, "CSSD","25.1","消毒追溯")
# ============================
# 模块26: 急诊
# ============================
def test_emergency():
print(f"\n{'='*50}\n模块26: 急诊管理\n{'='*50}")
r = GET("/emergency/page", {"pageNum":1,"pageSize":10})
chk_page(r, "急诊","26.1","急诊记录")
r = GET("/triage/queue/page", {"pageNum":1,"pageSize":10})
chk_page(r, "急诊","26.2","分诊排队")
# ============================
# 模块27: 医保
# ============================
def test_insurance():
print(f"\n{'='*50}\n模块27: 医保管理\n{'='*50}")
r = GET("/yb-request/page", {"pageNum":1,"pageSize":10})
chk_page(r, "医保","27.1","医保请求")
# ============================
# 模块28: 抗菌药物
# ============================
def test_antibiotic():
print(f"\n{'='*50}\n模块28: 抗菌药物\n{'='*50}")
r = GET("/api/v1/antibiotic/page", {"pageNum":1,"pageSize":10})
chk_page(r, "抗菌","28.1","抗菌药物")
# ============================
# 模块29: DRG分析
# ============================
def test_drg():
print(f"\n{'='*50}\n模块29: DRG分析\n{'='*50}")
r = GET("/drg-analysis/page", {"pageNum":1,"pageSize":10})
chk_page(r, "DRG","29.1","DRG分析")
r = GET("/mr-drg/page", {"pageNum":1,"pageSize":10})
chk_page(r, "DRG","29.2","DRG分组")
# ============================
# 模块30: 经营分析
# ============================
def test_analytics():
print(f"\n{'='*50}\n模块30: 经营分析\n{'='*50}")
r = GET("/business-analytics/page", {"pageNum":1,"pageSize":10})
chk_page(r, "经营","30.1","经营分析")
# ============================
# 模块31: 系统管理
# ============================
def test_system():
print(f"\n{'='*50}\n模块31: 系统管理\n{'='*50}")
r = GET("/dict-dictionary/definition/page", {"pageNum":1,"pageSize":10})
chk_page(r, "系统","31.1","字典定义")
r = GET("/system/user/list")
data = r.get("data",[])
ok = isinstance(data, list) and len(data) > 0
stats.record("系统","31.2","用户列表非空", ok, "" if ok else "用户列表为空")
r = GET("/system/role/list")
data = r.get("data",[])
ok = isinstance(data, list) and len(data) > 0
stats.record("系统","31.3","角色列表非空", ok, "" if ok else "角色列表为空")
r = GET("/system/menu/list")
data = r.get("data",[])
ok = isinstance(data, list) and len(data) > 50
stats.record("系统","31.4","菜单>50条", ok, "" if ok else f"实际={len(data) if isinstance(data,list) else 'N/A'}")
r = GET("/system/dept/list")
data = r.get("data",[])
ok = isinstance(data, list) and len(data) > 5
stats.record("系统","31.5","部门>5个", ok, "" if ok else f"实际={len(data) if isinstance(data,list) else 'N/A'}")
# ============================
# 模块32: 药房管理
# ============================
def test_pharmacy():
print(f"\n{'='*50}\n模块32: 药房管理\n{'='*50}")
r = GET("/pharmacy-stock-alert/page", {"pageNum":1,"pageSize":10})
chk_page(r, "药房","32.1","库存预警")
r = GET("/pharmacy-manage/western-medicine-dispense/page", {"pageNum":1,"pageSize":10})
chk_page(r, "药房","32.2","西药发药")
r = GET("/pharmacy-manage/return-medicine/page", {"pageNum":1,"pageSize":10})
chk_page(r, "药房","32.3","退药管理")
# ============================
# 模块33: 报表管理
# ============================
def test_reports():
print(f"\n{'='*50}\n模块33: 报表管理\n{'='*50}")
r = GET("/report-manage/register/page", {"pageNum":1,"pageSize":10})
chk_page(r, "报表","33.1","挂号报表")
r = GET("/report-manage/charge/page", {"pageNum":1,"pageSize":10})
chk_page(r, "报表","33.2","收费报表")
r = GET("/report-manage/report-statistics/page", {"pageNum":1,"pageSize":10})
chk_page(r, "报表","33.3","经营统计")
# ============================
# 主入口
# ============================
if __name__ == "__main__":
print(f"{'='*70}")
print("HealthLink-HIS 三甲医院全流程业务逻辑测试 v2")
print(f"测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"测试环境: {BASE_URL}")
print(f"{'='*70}")
print("\n>>> 登录系统...")
TOKEN = login()
if not TOKEN:
print("❌ 登录失败!"); sys.exit(1)
print("✅ 登录成功")
for fn in [test_auth, test_registration, test_doctor_station, test_charge,
test_inpatient, test_nursing, test_inspection, test_radiology,
test_surgery, test_infection, test_quality, test_tcm,
test_consultation, test_pathway, test_critical, test_review,
test_rational_drug, test_drug_trace, test_empi, test_esb,
test_ca, test_mr, test_followup, test_consent, test_cssd,
test_emergency, test_insurance, test_antibiotic, test_drg,
test_analytics, test_system, test_pharmacy, test_reports]:
try: fn()
except Exception as e:
print(f" ❌ 异常: {fn.__name__}: {e}")
stats.record("异常", fn.__name__, "执行异常", False, str(e))
ok = stats.summary()
os.makedirs("MD/test/reports", exist_ok=True)
rp = f"MD/test/reports/biz_test_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md"
with open(rp, "w") as f:
f.write(f"# 业务逻辑测试报告\n\n")
f.write(f"**时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
f.write(f"**环境**: {BASE_URL}\n\n")
f.write(f"## 汇总\n\n- 总数: {stats.total}\n- 通过: {stats.passed}\n- 失败: {stats.failed}\n- 通过率: {stats.passed*100/stats.total:.1f}%\n\n" if stats.total else "")
f.write("## 详细\n\n| 模块 | 编号 | 测试项 | 状态 | 说明 |\n|------|------|--------|------|------|\n")
for r in stats.results:
f.write(f"| {r['module']} | {r['case_id']} | {r['name']} | {r['status']} | {r['detail']} |\n")
print(f"\n📄 报告: {rp}")
sys.exit(0 if ok else 1)

View File

@@ -0,0 +1,485 @@
# HealthLink-HIS 三甲医院全流程测试计划
## 1. 测试概述
**项目**: HealthLink-HIS 三甲医院信息系统
**版本**: v2.0 (JDK 25 + Spring Boot 4.0.6 + Vue 3 + Element Plus)
**测试范围**: 门诊、住院、药房、护理、检验、影像、手术、麻醉、院感、质控、中医等全流程
**测试环境**: 本地开发环境 (localhost:18082)
---
## 2. 测试数据准备
### 2.1 基础数据
```sql
-- 测试科室
INSERT INTO sys_dept (dept_name, parent_id, order_num) VALUES
('内科', 0, 1), ('外科', 0, 2), ('妇产科', 0, 3), ('儿科', 0, 4),
('ICU', 0, 5), ('急诊科', 0, 6), ('手术室', 0, 7), ('药房', 0, 8),
('检验科', 0, 9), ('影像科', 0, 10), ('门诊部', 0, 11), ('住院部', 0, 12);
-- 测试医生
INSERT INTO sys_user (user_name, nick_name, dept_id, email) VALUES
('zhangsan', '张三', 1, 'zhangsan@hospital.com'),
('lisi', '李四', 2, 'lisi@hospital.com'),
('wangwu', '王五', 3, 'wangwu@hospital.com'),
('zhaoliu', '赵六', 5, 'zhaoliu@hospital.com');
-- 测试护士
INSERT INTO sys_user (user_name, nick_name, dept_id) VALUES
('nurse1', '护士A', 1),
('nurse2', '护士B', 5);
-- 测试药品
INSERT INTO drug_info (drug_code, drug_name, drug_spec, drug_category) VALUES
('DRG001', '阿莫西林胶囊', '0.5g*24片', '抗生素'),
('DRG002', '布洛芬缓释胶囊', '0.3g*20粒', '解热镇痛'),
('DRG003', '奥美拉唑肠溶胶囊', '20mg*14粒', '消化系统'),
('DRG004', '氨氯地平片', '5mg*7片', '心血管'),
('DRG005', '头孢曲松注射液', '1g', '抗生素');
```
### 2.2 测试患者数据
```sql
-- 门诊患者
INSERT INTO patient_info (patient_name, id_card, gender, birth_date, phone) VALUES
('患者甲', '450102199001011234', 'M', '1990-01-01', '13800138001'),
('患者乙', '450102198505052345', 'F', '1985-05-05', '13800138002'),
('患者丙', '450102200010103456', 'M', '2000-10-10', '13800138003'),
('患者丁', '450102197512124567', 'F', '1975-12-12', '13800138004');
-- 住院患者
INSERT INTO inpatient_info (patient_id, bed_no, admission_date, diagnosis) VALUES
(1, 'ICU-01', '2026-06-01', '重症肺炎'),
(2, '内-01', '2026-06-03', '高血压3级'),
(3, '外-01', '2026-06-05', '急性阑尾炎');
```
---
## 3. 全流程测试用例
### 3.1 门诊就诊流程
#### 流程图
```
患者挂号 → 医生接诊 → 开具处方 → 药房发药 → 收费结算
↓ ↓ ↓ ↓ ↓
[挂号管理] [门诊医生站] [处方管理] [药房管理] [收费管理]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 挂号 | 创建挂号记录 | POST /api/v1/outpatient/registration | 返回挂号单号 |
| 2. 接诊 | 医生接诊患者 | POST /api/v1/outpatient/encounter | 创建就诊记录 |
| 3. 开方 | 开具处方 | POST /api/v1/outpatient/prescription | 返回处方号 |
| 4. 发药 | 药房发药 | POST /api/v1/pharmacy/dispense | 更新库存 |
| 5. 结算 | 收费结算 | POST /api/v1/charge/settle | 生成收费记录 |
#### 测试数据
```json
// 1. 挂号
{
"patientId": 1,
"doctorId": 1,
"deptId": 1,
"appointTime": "2026-06-07 09:00:00",
"regType": "普通"
}
// 2. 开方
{
"encounterId": 1001,
"patientId": 1,
"doctorId": 1,
"items": [
{"drugCode": "DRG001", "quantity": 2, "usage": "tid po"},
{"drugCode": "DRG002", "quantity": 1, "usage": "bid po"}
]
}
```
---
### 3.2 住院入院流程
#### 流程图
```
入院登记 → 护理评估 → 医嘱开具 → 执行医嘱 → 出院结算
↓ ↓ ↓ ↓ ↓
[入院管理] [护理评估] [医嘱管理] [护理执行] [出院管理]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 入院登记 | 创建入院记录 | POST /api/v1/inpatient/admission | 返回住院号 |
| 2. 护理评估 | Braden压疮评估 | POST /nursing-assessment-enhanced/braden/assess | 评估完成 |
| 3. 跌倒评估 | Morse跌倒评估 | POST /nursing-assessment-enhanced/morse/assess | 评估完成 |
| 4. 开医嘱 | 医生开具医嘱 | POST /api/v1/order/submit | 医嘱生效 |
| 5. 执行医嘱 | 护士执行医嘱 | POST /api/v1/order/execute | 执行完成 |
| 6. 出院结算 | 出院结算 | POST /api/v1/inpatient/discharge | 结算完成 |
#### 测试数据
```json
// 1. 入院登记
{
"patientId": 1,
"deptId": 5,
"bedNo": "ICU-01",
"admissionDate": "2026-06-07",
"diagnosis": "重症肺炎",
"admissionDoctor": "赵六"
}
// 2. Braden评估
{
"patientName": "患者甲",
"encounterId": 1001,
"itemScores": "{\"sensation\":2,\"moisture\":2,\"activity\":1,\"mobility\":2,\"nutrition\":3,\"friction\":2}",
"detail": "压疮高危患者"
}
// 3. Morse评估
{
"patientName": "患者甲",
"encounterId": 1001,
"itemScores": "{\"history\":15,\"diagnosis\":0,\"ambulation\":15,\"iv\":20,\"gait\":0,\"mental\":0}",
"detail": "跌倒高危患者"
}
```
---
### 3.3 药房管理流程
#### 流程图
```
采购入库 → 库存管理 → 处方审核 → 发药 → 库存预警
↓ ↓ ↓ ↓ ↓
[采购管理] [库存管理] [合理用药] [发药管理] [库存预警]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 采购入库 | 药品采购 | POST /api/v1/pharmacy/purchase | 库存增加 |
| 2. 库存查询 | 查询库存 | GET /api/v1/pharmacy/stock | 返回库存列表 |
| 3. 处方审核 | 审核处方 | POST /api/v1/rational-drug/audit | 审核完成 |
| 4. 发药 | 药房发药 | POST /api/v1/pharmacy/dispense | 库存减少 |
| 5. 库存预警 | 查询预警 | GET /pharmacystockalert/page | 返回预警列表 |
---
### 3.4 检验管理流程
#### 流程图
```
开具检验单 → 标本采集 → 标本接收 → 检验执行 → 报告审核 → 结果查看
↓ ↓ ↓ ↓ ↓ ↓
[检验申请] [标本管理] [标本接收] [检验执行] [报告审核] [结果查看]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 开检验单 | 申请检验 | POST /api/v1/inspection/apply | 返回申请单号 |
| 2. 标本采集 | 采集标本 | POST /api/v1/specimen/collect | 标本登记 |
| 3. 标本接收 | 接收标本 | POST /api/v1/specimen/receive | 状态更新 |
| 4. 检验执行 | 录入结果 | POST /api/v1/inspection/result | 结果保存 |
| 5. 报告审核 | 审核报告 | POST /api/v1/inspection/audit | 报告完成 |
---
### 3.5 影像检查流程
#### 流程图
```
开具检查单 → 预约排队 → 检查执行 → 报告编写 → 结果查看 → 历史对比
↓ ↓ ↓ ↓ ↓ ↓
[检查申请] [预约管理] [检查执行] [报告管理] [结果查看] [影像对比]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 开检查单 | 申请检查 | POST /api/v1/exam/apply | 返回申请单号 |
| 2. 预约检查 | 预约排队 | POST /api/v1/exam/appointment | 预约成功 |
| 3. 检查执行 | 执行检查 | POST /api/v1/exam/execute | 检查完成 |
| 4. 编写报告 | 编写报告 | POST /api/v1/exam/report | 报告保存 |
| 5. 历史对比 | 对比影像 | GET /radiology-comparison/compare | 返回对比数据 |
---
### 3.6 手术管理流程
#### 流程图
```
手术申请 → 术前讨论 → 手术排班 → 术前准备 → 手术执行 → 术后随访
↓ ↓ ↓ ↓ ↓ ↓
[手术申请] [术前讨论] [手术排班] [术前检查] [手术记录] [术后随访]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 手术申请 | 申请手术 | POST /api/v1/surgery/apply | 申请成功 |
| 2. 术前讨论 | 讨论记录 | POST /api/v1/surgery/discussion | 讨论完成 |
| 3. 手术排班 | 安排手术 | POST /api/v1/surgery/schedule | 排班成功 |
| 4. 术前准备 | 准备检查 | POST /api/v1/surgery/preop-check | 准备完成 |
| 5. 手术记录 | 记录手术 | POST /api/v1/surgery/record | 记录保存 |
| 6. 术后随访 | 随访记录 | POST /api/v1/anesthesia/followup | 随访完成 |
---
### 3.7 麻醉管理流程
#### 流程图
```
麻醉评估 → 麻醉记录 → 术中监测 → 术后随访 → 麻醉质控
↓ ↓ ↓ ↓ ↓
[麻醉评估] [麻醉记录] [生命体征] [术后随访] [质控统计]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 麻醉评估 | 评估患者 | POST /api/v1/anesthesia/record | 评估完成 |
| 2. 麻醉记录 | 记录麻醉 | POST /api/v1/anesthesia/record | 记录保存 |
| 3. 术中监测 | 记录体征 | POST /api/v1/anesthesia/vital-sign | 体征保存 |
| 4. 术后随访 | 随访记录 | POST /api/v1/anesthesia/followup | 随访完成 |
| 5. 质控统计 | 统计分析 | GET /anesthesia-enhanced/qc/stats | 返回统计 |
---
### 3.8 院感管理流程
#### 流程图
```
感染监测 → 暴发预警 → 疫情报告 → 干预措施 → 效果评估
↓ ↓ ↓ ↓ ↓
[感染监测] [暴发预警] [疫情报告] [干预措施] [效果评估]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 感染监测 | 目标性监测 | POST /infection/surveillance/add | 监测记录 |
| 2. 暴发预警 | 预警记录 | POST /infection/warning/add | 预警记录 |
| 3. 多重耐药 | 耐药监测 | POST /infection/resistant/add | 耐药记录 |
| 4. 职业暴露 | 暴露报告 | POST /infection/exposure/add | 暴露记录 |
| 5. 手卫生 | 手卫生监测 | POST /infection/hygiene/add | 手卫生记录 |
| 6. 环境监测 | 环境采样 | POST /infection/environment/add | 环境记录 |
---
### 3.9 质量管理流程
#### 流程图
```
运行质控 → 终末质控 → 缺陷记录 → 整改追踪 → 质量统计
↓ ↓ ↓ ↓ ↓
[运行质控] [终末质控] [缺陷管理] [整改追踪] [质量统计]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 运行质控 | 检查病历 | POST /api/v1/emr-quality/runtime-check/{id} | 检查结果 |
| 2. 终末质控 | 评分 | POST /api/v1/emr-quality/terminal-check/{id} | 评分结果 |
| 3. 缺陷记录 | 记录缺陷 | GET /api/v1/emr-quality/defect/{id} | 缺陷列表 |
| 4. 护理质量 | 质量指标 | GET /nursing-quality/summary | 质量统计 |
---
### 3.10 处方点评流程
#### 流程图
```
创建计划 → 自动筛查 → 人工点评 → 整改通知 → 统计分析
↓ ↓ ↓ ↓ ↓
[点评计划] [自动筛查] [人工点评] [整改通知] [统计排名]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 创建计划 | 创建点评计划 | POST /api/v1/review/plan | 计划创建 |
| 2. 自动筛查 | 筛选处方 | POST /api/v1/review/auto-screen | 筛选结果 |
| 3. 人工点评 | 点评处方 | POST /api/v1/review/record | 点评完成 |
| 4. 医生排名 | 排名统计 | GET /api/v1/review/ranking | 排名列表 |
---
### 3.11 临床路径管理流程
#### 流程图
```
路径定义 → 入径管理 → 执行监控 → 变异分析 → 效果评价
↓ ↓ ↓ ↓ ↓
[路径管理] [入径管理] [执行监控] [变异分析] [效果评价]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 路径定义 | 创建路径 | POST /clinical-pathway/add | 路径创建 |
| 2. 入径管理 | 患者入径 | POST /clinical-pathway/enter | 入径完成 |
| 3. 完成路径 | 完成治疗 | PUT /clinical-pathway/complete/{id} | 路径完成 |
| 4. 变异记录 | 记录变异 | PUT /clinical-pathway/vary/{id} | 变异记录 |
---
### 3.12 中医管理流程
#### 流程图
```
体质辨识 → 辨证论治 → 方剂开具 → 中药处方 → 疗效评价
↓ ↓ ↓ ↓ ↓
[体质辨识] [辨证论治] [方剂管理] [中药处方] [疗效评价]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 体质辨识 | 辨识体质 | POST /api/v1/tcm/constitution | 辨识完成 |
| 2. 查询方剂 | 查询方剂 | GET /api/v1/tcm/prescriptions | 方剂列表 |
| 3. 新增方剂 | 新增方剂 | POST /api/v1/tcm/prescription | 方剂创建 |
| 4. 统计查询 | 统计分析 | GET /api/v1/tcm/statistics | 统计结果 |
---
### 3.13 医嘱闭环管理流程
#### 流程图
```
医嘱开具 → 药师审核 → 护士执行 → 执行确认 → 闭环完成
↓ ↓ ↓ ↓ ↓
[医嘱管理] [处方审核] [护理执行] [执行确认] [闭环统计]
```
#### 测试步骤
| 步骤 | 操作 | API接口 | 预期结果 |
|------|------|---------|----------|
| 1. 执行医嘱 | 执行医嘱 | POST /api/v1/order-closed-loop/execute | 执行完成 |
| 2. 完成医嘱 | 完成医嘱 | POST /api/v1/order-closed-loop/complete | 闭环完成 |
| 3. 取消医嘱 | 取消医嘱 | POST /api/v1/order-closed-loop/cancel | 取消完成 |
| 4. 统计查询 | 统计分析 | GET /api/v1/order-closed-loop/statistics | 统计结果 |
---
## 4. 测试执行计划
### 4.1 测试顺序
| 阶段 | 模块 | 优先级 | 预计耗时 |
|------|------|--------|----------|
| Phase 1 | 基础数据 + 登录认证 | P0 | 30分钟 |
| Phase 2 | 门诊就诊流程 | P0 | 60分钟 |
| Phase 3 | 住院入院流程 | P0 | 60分钟 |
| Phase 4 | 药房管理流程 | P1 | 45分钟 |
| Phase 5 | 检验管理流程 | P1 | 45分钟 |
| Phase 6 | 影像检查流程 | P1 | 45分钟 |
| Phase 7 | 手术麻醉流程 | P1 | 60分钟 |
| Phase 8 | 院感管理流程 | P2 | 45分钟 |
| Phase 9 | 质量管理流程 | P2 | 45分钟 |
| Phase 10 | 处方点评流程 | P2 | 30分钟 |
| Phase 11 | 临床路径流程 | P2 | 30分钟 |
| Phase 12 | 中医管理流程 | P2 | 30分钟 |
| Phase 13 | 医嘱闭环流程 | P1 | 30分钟 |
### 4.2 测试验证点
每个测试用例需要验证:
1. **接口返回码**: 确认API返回200
2. **数据完整性**: 确认数据正确保存
3. **业务逻辑**: 确认流程正确执行
4. **异常处理**: 确认异常情况正确处理
5. **权限控制**: 确认权限正确验证
---
## 5. 测试报告模板
```markdown
### 测试报告
**测试日期**: 2026-06-07
**测试人员**: AI Agent
**测试环境**: 本地开发环境
#### 测试结果汇总
| 模块 | 测试用例数 | 通过数 | 失败数 | 通过率 |
|------|-----------|--------|--------|--------|
| 门诊就诊 | 5 | 5 | 0 | 100% |
| 住院入院 | 6 | 6 | 0 | 100% |
| 药房管理 | 5 | 5 | 0 | 100% |
| 检验管理 | 5 | 5 | 0 | 100% |
| 影像检查 | 6 | 6 | 0 | 100% |
| 手术麻醉 | 6 | 6 | 0 | 100% |
| 院感管理 | 6 | 6 | 0 | 100% |
| 质量管理 | 4 | 4 | 0 | 100% |
| 处方点评 | 4 | 4 | 0 | 100% |
| 临床路径 | 4 | 4 | 0 | 100% |
| 中医管理 | 4 | 4 | 0 | 100% |
| 医嘱闭环 | 4 | 4 | 0 | 100% |
| **总计** | **59** | **59** | **0** | **100%** |
#### 发现问题
| 序号 | 问题描述 | 严重程度 | 状态 |
|------|----------|----------|------|
| 1 | 无 | - | - |
#### 结论
所有测试用例全部通过,系统功能完整,可以交付使用。
```
---
## 6. 附录
### 6.1 API接口清单
| 模块 | 接口前缀 | 方法 |
|------|----------|------|
| 门诊管理 | /api/v1/outpatient | GET/POST |
| 住院管理 | /api/v1/inpatient | GET/POST |
| 药房管理 | /api/v1/pharmacy | GET/POST |
| 检验管理 | /api/v1/inspection | GET/POST |
| 影像管理 | /api/v1/exam | GET/POST |
| 手术管理 | /api/v1/surgery | GET/POST |
| 麻醉管理 | /api/v1/anesthesia | GET/POST |
| 护理管理 | /nursing-assessment-enhanced | GET/POST |
| 院感管理 | /infection | GET/POST |
| 质量管理 | /api/v1/emr-quality | GET/POST |
| 处方点评 | /api/v1/review | GET/POST |
| 临床路径 | /clinical-pathway | GET/POST |
| 中医管理 | /api/v1/tcm | GET/POST |
| 医嘱闭环 | /api/v1/order-closed-loop | GET/POST |
### 6.2 测试数据文件
- `test_data.sql` - SQL测试数据
- `test_api.json` - API测试数据
- `test_report.md` - 测试报告

View File

@@ -0,0 +1,128 @@
# 业务逻辑测试报告
**时间**: 2026-06-07 21:53:48
**环境**: http://localhost:18082/healthlink-his
## 汇总
- 总数: 107
- 通过: 34
- 失败: 73
- 通过率: 31.8%
## 详细
| 模块 | 编号 | 测试项 | 状态 | 说明 |
|------|------|--------|------|------|
| 认证 | 1.1 | 登录成功-返回token | ✅ PASS | |
| 认证 | 1.2 | 错误密码-应失败 | ✅ PASS | |
| 认证 | 1.3 | 获取用户信息 | ✅ PASS | |
| 认证 | 1.4 | 获取路由菜单 | ✅ PASS | |
| 挂号 | 2.1 | 挂号初始化 | ✅ PASS | |
| 挂号 | 2.2 | 当日挂号列表 | ✅ PASS | |
| 挂号 | 2.3 | 患者元数据查询 | ✅ PASS | |
| 挂号 | 2.4 | 全部医生列表 | ✅ PASS | |
| 医生站 | 3.1 | 医生站初始化 | ✅ PASS | |
| 医生站 | 3.2 | 患者信息查询 | ✅ PASS | |
| 医生站 | 3.3 | 接诊统计 | ❌ FAIL | code=500, msg=Required request parameter 'startTime' for method parameter type String is not present |
| 医生站 | 3.4 | 医嘱基础信息 | ✅ PASS | |
| 医生站 | 3.5 | 诊断初始化 | ✅ PASS | |
| 医生站 | 3.6 | 诊断定义分类 | ❌ FAIL | code=500, msg=Required request parameter 'patientId' for method parameter type Long is not present |
| 医生站 | 3.7 | 检查申请初始化 | ❌ FAIL | code=500, msg=No static resource doctor-station/inspection/init for request '/healthlink-his/doctor-station/inspection/init'. |
| 收费 | 4.1 | 门诊收费初始化 | ✅ PASS | |
| 收费 | 4.2 | 收费患者列表 | ✅ PASS | |
| 收费 | 4.3 | 退费初始化 | ✅ PASS | |
| 收费 | 4.4 | 退费患者列表 | ✅ PASS | |
| 收费 | 4.5 | 住院收费初始化 | ✅ PASS | |
| 收费 | 4.6 | 住院收费患者列表 | ✅ PASS | |
| 收费 | 4.7 | 定价患者信息 | ✅ PASS | |
| 住院 | 5.1 | 患者主页初始化 | ✅ PASS | |
| 住院 | 5.2 | 空床查询 | ✅ PASS | |
| 住院 | 5.3 | 科室统计 | ✅ PASS | |
| 住院 | 5.4 | 押金初始化 | ✅ PASS | |
| 住院 | 5.5 | 入院登记-病区列表 | ❌ FAIL | code=500, msg=No static resource inhospitalmanage/register/ward-list for request '/healthlink-his/inhospitalmanage/register/ward-list' |
| 住院 | 5.6 | 入院登记-床位数 | ❌ FAIL | code=500, msg=No static resource inhospitalmanage/register/beds-num for request '/healthlink-his/inhospitalmanage/register/beds-num'. |
| 住院 | 5.7 | 入院登记-患者信息 | ❌ FAIL | code=500, msg=No static resource inhospitalmanage/register/patient-info for request '/healthlink-his/inhospitalmanage/register/patient |
| 护理 | 6.1 | 护理评估列表 | ❌ FAIL | rows类型异常: <class 'dict'> |
| 护理 | 6.2 | 护理评估统计 | ✅ PASS | |
| 护理 | 6.3 | Braden评估-成功 | ✅ PASS | |
| 护理 | 6.4 | Morse评估-成功 | ✅ PASS | |
| 护理 | 6.5 | 体征记录查询 | ✅ PASS | |
| 护理 | 6.6 | 体征图表 | ❌ FAIL | rows类型异常: <class 'dict'> |
| 护理 | 6.7 | 护理执行列表 | ❌ FAIL | code=500, msg=No static resource nurse-station/advice-process/page for request '/healthlink-his/nurse-station/advice-process/page'. |
| 护理 | 6.8 | 护理质量指标 | ❌ FAIL | rows类型异常: <class 'dict'> |
| 检验 | 7.1 | 标本采集 | ❌ FAIL | code=500, msg=No static resource inspection/collection/page for request '/healthlink-his/inspection/collection/page'. |
| 检验 | 7.2 | 检验观察 | ❌ FAIL | code=500, msg=No static resource inspection/observation/page for request '/healthlink-his/inspection/observation/page'. |
| 检验 | 7.3 | 标本定义 | ❌ FAIL | code=500, msg=No static resource inspection/specimen/page for request '/healthlink-his/inspection/specimen/page'. |
| 检验 | 7.4 | LIS配置 | ❌ FAIL | code=500, msg=No static resource inspection/lisConfig/page for request '/healthlink-his/inspection/lisConfig/page'. |
| 检验 | 7.5 | 仪器管理 | ❌ FAIL | code=500, msg=No static resource inspection/instrument/page for request '/healthlink-his/inspection/instrument/page'. |
| 检验 | 7.6 | 检验结果 | ❌ FAIL | code=500, msg=请求参数类型不匹配,参数[id]要求类型为:'java.lang.Long',但输入值为:'page' |
| 检验 | 7.7 | 参考范围 | ❌ FAIL | rows类型异常: <class 'dict'> |
| 检验 | 7.8 | 检查申请 | ❌ FAIL | code=500, msg=未找到申请单信息 |
| 影像 | 8.1 | 影像列表 | ❌ FAIL | code=500, msg=No static resource radiology-image/page for request '/healthlink-his/radiology-image/page'. |
| 影像 | 8.2 | 影像增强 | ❌ FAIL | code=500, msg=No static resource radiology-enhanced/page for request '/healthlink-his/radiology-enhanced/page'. |
| 影像 | 8.3 | 影像对比 | ❌ FAIL | code=500, msg=No static resource radiology-comparison/page for request '/healthlink-his/radiology-comparison/page'. |
| 影像 | 8.4 | 3D重建 | ❌ FAIL | code=500, msg=No static resource reconstruction/page for request '/healthlink-his/reconstruction/page'. |
| 手术 | 9.1 | 手术列表 | ❌ FAIL | code=500, msg=No static resource clinical-manage/surgery/page for request '/healthlink-his/clinical-manage/surgery/page'. |
| 手术 | 9.2 | 手术排程 | ❌ FAIL | rows类型异常: <class 'dict'> |
| 手术 | 9.3 | 术前讨论 | ❌ FAIL | code=500, msg=
### Error querying database. Cause: org.postgresql.util.PSQLException: ERROR: column "delete_flag" does not exist
Po |
| 手术 | 9.4 | 安全核查 | ❌ FAIL | rows类型异常: <class 'dict'> |
| 麻醉 | 9.5 | 麻醉记录 | ❌ FAIL | code=500, msg=No static resource api/v1/anesthesia/page for request '/healthlink-his/api/v1/anesthesia/page'. |
| 麻醉 | 9.6 | 麻醉增强 | ❌ FAIL | code=500, msg=No static resource anesthesia-enhanced/page for request '/healthlink-his/anesthesia-enhanced/page'. |
| 院感 | 10.1 | 院感监测 | ❌ FAIL | rows类型异常: <class 'dict'> |
| 院感 | 10.2 | 院感预警 | ❌ FAIL | code=500, msg=No static resource infection-enhanced/warning/page for request '/healthlink-his/infection-enhanced/warning/page'. |
| 院感 | 10.3 | 耐药监测 | ❌ FAIL | code=500, msg=No static resource infection-enhanced/resistance/page for request '/healthlink-his/infection-enhanced/resistance/page'. |
| 院感 | 10.4 | 职业暴露 | ❌ FAIL | code=500, msg=No static resource infection-enhanced/exposure/page for request '/healthlink-his/infection-enhanced/exposure/page'. |
| 院感 | 10.5 | 手卫生 | ❌ FAIL | rows类型异常: <class 'dict'> |
| 院感 | 10.6 | 环境监测 | ❌ FAIL | code=500, msg=No static resource infection-enhanced/environment/page for request '/healthlink-his/infection-enhanced/environment/page' |
| 质控 | 11.1 | 运行质控 | ❌ FAIL | code=500, msg=No static resource quality-enhanced/runtime/page for request '/healthlink-his/quality-enhanced/runtime/page'. |
| 质控 | 11.2 | 终末质控 | ❌ FAIL | code=500, msg=No static resource api/v1/emr-quality/page for request '/healthlink-his/api/v1/emr-quality/page'. |
| 质控 | 11.3 | 质量统计 | ❌ FAIL | code=500, msg=No static resource quality-enhanced/statistics/page for request '/healthlink-his/quality-enhanced/statistics/page'. |
| 中医 | 12.1 | 中医体质 | ❌ FAIL | code=500, msg=No static resource api/v1/tcm/constitution/page for request '/healthlink-his/api/v1/tcm/constitution/page'. |
| 中医 | 12.2 | 方剂列表>=3个 | ✅ PASS | |
| 中医 | 12.3 | 中医统计 | ✅ PASS | |
| 会诊 | 13.1 | 会诊记录 | ❌ FAIL | code=500, msg=No static resource consultation/page for request '/healthlink-his/consultation/page'. |
| 会诊 | 13.2 | 会诊反馈 | ❌ FAIL | code=500, msg=No static resource cross-module/consult-feedback/page for request '/healthlink-his/cross-module/consult-feedback/page'. |
| 会诊 | 13.3 | 会诊超时 | ❌ FAIL | code=500, msg=No static resource cross-module/consulttimeout/page for request '/healthlink-his/cross-module/consulttimeout/page'. |
| 路径 | 14.1 | 临床路径>=2条 | ❌ FAIL | 实际=5 |
| 危急值 | 15.1 | 危急值列表 | ❌ FAIL | code=500, msg=No static resource api/v1/critical-value/page for request '/healthlink-his/api/v1/critical-value/page'. |
| 点评 | 16.1 | 点评计划 | ❌ FAIL | rows类型异常: <class 'dict'> |
| 点评 | 16.2 | 点评记录 | ❌ FAIL | rows类型异常: <class 'dict'> |
| 点评 | 16.3 | 点评统计 | ✅ PASS | |
| 用药 | 17.1 | 合理用药 | ❌ FAIL | code=500, msg=No static resource api/v1/rational-drug/page for request '/healthlink-his/api/v1/rational-drug/page'. |
| 用药 | 17.2 | 相互作用 | ❌ FAIL | code=500, msg=No static resource api/v1/rational-drug/interaction/page for request '/healthlink-his/api/v1/rational-drug/interaction/p |
| 用药 | 17.3 | 用药统计 | ✅ PASS | |
| 用药 | 17.4 | 审计日志 | ❌ FAIL | code=500, msg=No static resource api/v1/rational-drug/audit-log for request '/healthlink-his/api/v1/rational-drug/audit-log'. |
| 追溯 | 18.1 | 药品追溯 | ❌ FAIL | code=500, msg=No static resource drugtrace/page for request '/healthlink-his/drugtrace/page'. |
| EMPI | 19.1 | EMPI索引 | ❌ FAIL | code=500, msg=No static resource api/v1/empi/page for request '/healthlink-his/api/v1/empi/page'. |
| ESB | 20.1 | ESB消息 | ❌ FAIL | rows类型异常: <class 'dict'> |
| ESB | 20.2 | ESB服务注册 | ❌ FAIL | rows类型异常: <class 'dict'> |
| CA | 21.1 | CA签名 | ❌ FAIL | code=500, msg=No static resource api/v1/ca-signature/page for request '/healthlink-his/api/v1/ca-signature/page'. |
| CA | 21.2 | CA签名统计 | ✅ PASS | |
| 病案 | 22.1 | 病案首页 | ❌ FAIL | code=500, msg=请求参数类型不匹配,参数[id]要求类型为:'java.lang.Long',但输入值为:'page' |
| 随访 | 23.1 | 随访计划 | ❌ FAIL | code=500, msg=No static resource followup/page for request '/healthlink-his/followup/page'. |
| 知情 | 24.1 | 知情同意 | ❌ FAIL | rows类型异常: <class 'dict'> |
| CSSD | 25.1 | 消毒追溯 | ❌ FAIL | code=500, msg=No static resource cssd/page for request '/healthlink-his/cssd/page'. |
| 急诊 | 26.1 | 急诊记录 | ❌ FAIL | code=500, msg=No static resource emergency/page for request '/healthlink-his/emergency/page'. |
| 急诊 | 26.2 | 分诊排队 | ❌ FAIL | code=500, msg=No static resource index.html for request '/healthlink-his/index.html'. |
| 医保 | 27.1 | 医保请求 | ❌ FAIL | code=500, msg=No static resource yb-request/page for request '/healthlink-his/yb-request/page'. |
| 抗菌 | 28.1 | 抗菌药物 | ❌ FAIL | code=500, msg=No static resource api/v1/antibiotic/page for request '/healthlink-his/api/v1/antibiotic/page'. |
| DRG | 29.1 | DRG分析 | ❌ FAIL | code=500, msg=No static resource drg-analysis/page for request '/healthlink-his/drg-analysis/page'. |
| DRG | 29.2 | DRG分组 | ❌ FAIL | code=500, msg=
### Error querying database. Cause: org.postgresql.util.PSQLException: ERROR: column "create_by" does not exist
Posi |
| 经营 | 30.1 | 经营分析 | ❌ FAIL | rows类型异常: <class 'dict'> |
| 系统 | 31.1 | 字典定义 | ❌ FAIL | code=500, msg=No static resource dict-dictionary/definition/page for request '/healthlink-his/dict-dictionary/definition/page'. |
| 系统 | 31.2 | 用户列表非空 | ❌ FAIL | 用户列表为空 |
| 系统 | 31.3 | 角色列表非空 | ❌ FAIL | 角色列表为空 |
| 系统 | 31.4 | 菜单>50条 | ✅ PASS | |
| 系统 | 31.5 | 部门>5个 | ✅ PASS | |
| 药房 | 32.1 | 库存预警 | ❌ FAIL | rows类型异常: <class 'dict'> |
| 药房 | 32.2 | 西药发药 | ❌ FAIL | code=500, msg=No static resource pharmacy-manage/western-medicine-dispense/page for request '/healthlink-his/pharmacy-manage/western-m |
| 药房 | 32.3 | 退药管理 | ❌ FAIL | code=500, msg=No static resource pharmacy-manage/return-medicine/page for request '/healthlink-his/pharmacy-manage/return-medicine/pag |
| 报表 | 33.1 | 挂号报表 | ❌ FAIL | code=500, msg=No static resource report-manage/register/page for request '/healthlink-his/report-manage/register/page'. |
| 报表 | 33.2 | 收费报表 | ❌ FAIL | code=500, msg=No static resource report-manage/charge/page for request '/healthlink-his/report-manage/charge/page'. |
| 报表 | 33.3 | 经营统计 | ❌ FAIL | code=500, msg=No static resource report-manage/report-statistics/page for request '/healthlink-his/report-manage/report-statistics/pag |

View File

@@ -0,0 +1,148 @@
# HealthLink-HIS 业务逻辑测试报告
**测试时间**: 2026-06-07 21:51:00
**测试环境**: http://localhost:18082/healthlink-his
## 测试汇总
- 总测试数: 111
- 通过数: 21
- 失败数: 90
- 通过率: 18.9%
## 详细结果
| 模块 | 编号 | 测试项 | 状态 | 说明 |
|------|------|--------|------|------|
| 认证 | 1.1 | 登录成功验证 | ❌ FAIL | 响应缺少字段: permissions |
| 认证 | 1.2 | 错误密码应返回失败 | ✅ PASS | |
| 认证 | 1.3 | 获取用户信息 | ✅ PASS | |
| 认证 | 1.4 | 获取路由菜单 | ✅ PASS | |
| 认证 | 1.5 | 获取验证码 | ✅ PASS | |
| 挂号 | 2.1 | 挂号初始化-返回优先级选项 | ❌ FAIL | 响应缺少字段: priorityLevelOptionOptions |
| 挂号 | 2.2 | 挂号列表分页查询 | ❌ FAIL | code=500, msg=No static resource charge-manage/register/page for request '/healthlink-his/charge-manage/register/page'. |
| 挂号 | 2.3 | 查询患者-搜索'测试' | ❌ FAIL | 预期code=200, 实际code=500, msg=No static resource charge-manage/register/patient for request '/healthlink-his/charge-manage/register/patient'. |
| 挂号 | 2.4 | 查询不存在的患者 | ❌ FAIL | 预期code=200, 实际code=500, msg=No static resource charge-manage/register/patient for request '/healthlink-his/charge-manage/register/patient'. |
| 医生站 | 3.1 | 待诊患者列表 | ❌ FAIL | 预期code=200, 实际code=500, msg=No static resource doctor-station/main/patient-list for request '/healthlink-his/doctor-station/main/patient-list'. |
| 医生站 | 3.2 | 医嘱列表分页查询 | ❌ FAIL | code=500, msg=No static resource doctor-station/advice/page for request '/healthlink-his/doctor-station/advice/page'. |
| 医生站 | 3.3 | 诊断列表分页查询 | ❌ FAIL | code=500, msg=No static resource doctor-station/diagnosis/page for request '/healthlink-his/doctor-station/diagnosis/page'. |
| 医生站 | 3.4 | 检查申请列表 | ❌ FAIL | code=500, msg=No static resource doctor-station/inspection/page for request '/healthlink-his/doctor-station/inspection/page'. |
| 收费 | 4.1 | 收费初始化 | ✅ PASS | |
| 收费 | 4.2 | 收费记录分页查询 | ❌ FAIL | code=500, msg=No static resource charge-manage/charge/page for request '/healthlink-his/charge-manage/charge/page'. |
| 收费 | 4.3 | 退费记录分页查询 | ❌ FAIL | code=500, msg=No static resource charge-manage/refund/page for request '/healthlink-his/charge-manage/refund/page'. |
| 收费 | 4.4 | 收费定价列表 | ❌ FAIL | code=500, msg=No static resource charge-manage/pricing/page for request '/healthlink-his/charge-manage/pricing/page'. |
| 住院 | 5.1 | 入院登记列表 | ❌ FAIL | code=500, msg=No static resource inhospitalmanage/register/page for request '/healthlink-his/inhospitalmanage/register/page'. |
| 住院 | 5.2 | 患者主页初始化 | ✅ PASS | |
| 住院 | 5.3 | 空床查询 | ✅ PASS | |
| 住院 | 5.4 | 押金管理初始化 | ✅ PASS | |
| 住院 | 5.5 | 押金记录分页查询 | ❌ FAIL | code=500, msg=
### Error querying database. Cause: org.postgresql.util.PSQLException: ERROR: column t4.pay_enum does not exist
Hint: Perhaps you meant to reference the column "t6.pay_enum".
Position: 275
### The error may exist in URL [jar:nested:/root/.openclaw/workspace/his-repo/healthlink-his-server/healthlink-his-application/target/healthlink-his-application.jar/!BOOT-INF/classes/!/mapper/inpatientmanage/DepositMapper.xml]
### The error may involve com.healthlink.his.web.inpatientmanage.mapper.DepositMapper.getPage-Inline
### The error occurred while setting parameters
### SQL: SELECT COUNT(*) AS total FROM (SELECT T1.id AS patient_id, T1.name, T1.gender_enum, T1.birth_date, T3.location_id AS bed_location_id, T1.organization_id, COALESCE(SUM_TOTAL.total_price, 0) AS total_price, COALESCE(SUM_DEPOSIT.deposit, 0) AS deposit, T4.balance_amount, CASE T4.pay_enum WHEN '220100' THEN '微信' WHEN '220200' THEN '支付宝' WHEN '220300' THEN '银联' WHEN '220400' THEN '现金' ELSE '其他' END AS pay_way, T5.payment_enum, T5.tendered_amount, T7.bus_no, T7.status_enum, T6.after_balance, T6.pay_trans_date AS pay_time, T5.enterer_id FROM adm_patient AS T1 INNER JOIN adm_encounter AS T2 ON T2.patient_id = T1.id AND T2.class_enum = ? LEFT JOIN adm_encounter_location AS T3 ON T3.encounter_id = T2.id AND T3.form_enum = ? AND T3.delete_flag = '0' LEFT JOIN adm_account AS T4 ON T4.patient_id = T1.id AND T4.encounter_id = T2.id AND T4.delete_flag = '0' LEFT JOIN fin_payment_reconciliation AS T5 ON T5.patient_id = T1.id AND T5.encounter_id = T2.id AND T5.delete_flag = '0' LEFT JOIN fin_payment_rec_detail AS T6 ON T6.reconciliation_id = T5.id AND T6.delete_flag = '0' LEFT JOIN adm_invoice AS T7 ON T7.reconciliation_id = T6.reconciliation_id AND T7.patient_id = T1.id AND T7.delete_flag = '0' LEFT JOIN (SELECT patient_id, SUM(tendered_amount) AS total_price FROM fin_payment_reconciliation WHERE kind_enum = 2 GROUP BY patient_id) AS SUM_TOTAL ON SUM_TOTAL.patient_id = T1.id LEFT JOIN (SELECT patient_id, SUM(tendered_amount) AS deposit FROM fin_payment_reconciliation WHERE kind_enum = 1 GROUP BY patient_id) AS SUM_DEPOSIT ON SUM_DEPOSIT.patient_id = T1.id WHERE T1.delete_flag = '0' ORDER BY T6.pay_trans_date DESC) AS T8 WHERE (tenant_id = ?)
### Cause: org.postgresql.util.PSQLException: ERROR: column t4.pay_enum does not exist
Hint: Perhaps you meant to reference the column "t6.pay_enum".
Position: 275
; bad SQL grammar [] |
| 住院 | 5.6 | 住院收费记录 | ❌ FAIL | code=500, msg=No static resource charge-manage/inpatient-charge/page for request '/healthlink-his/charge-manage/inpatient-charge/page'. |
| 护理 | 6.1 | 护理评估列表 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 护理 | 6.2 | 护理评估统计 | ✅ PASS | |
| 护理 | 6.3 | Braden压疮评估-分数计算正确 | ✅ PASS | |
| 护理 | 6.4 | Morse跌倒评估-分数计算正确 | ✅ PASS | |
| 护理 | 6.5 | 护理记录患者列表 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 护理 | 6.6 | 体征记录查询 | ✅ PASS | |
| 护理 | 6.7 | 体征图表分页查询 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 护理 | 6.8 | 护理执行列表 | ❌ FAIL | code=500, msg=No static resource nurse-station/advice-process/page for request '/healthlink-his/nurse-station/advice-process/page'. |
| 护理 | 6.9 | 交接班记录查询 | ❌ FAIL | code=500, msg=No static resource nursing-handoff/page for request '/healthlink-his/nursing-handoff/page'. |
| 护理 | 6.10 | 护理质量指标查询 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 检验 | 7.1 | 标本采集列表 | ❌ FAIL | code=500, msg=No static resource inspection/collection/page for request '/healthlink-his/inspection/collection/page'. |
| 检验 | 7.2 | 检验观察定义列表 | ❌ FAIL | code=500, msg=No static resource inspection/observation/page for request '/healthlink-his/inspection/observation/page'. |
| 检验 | 7.3 | 标本定义列表 | ❌ FAIL | code=500, msg=No static resource inspection/specimen/page for request '/healthlink-his/inspection/specimen/page'. |
| 检验 | 7.4 | LIS配置列表 | ❌ FAIL | code=500, msg=No static resource inspection/lisConfig/page for request '/healthlink-his/inspection/lisConfig/page'. |
| 检验 | 7.5 | 仪器管理列表 | ❌ FAIL | code=500, msg=No static resource inspection/instrument/page for request '/healthlink-his/inspection/instrument/page'. |
| 检验 | 7.6 | 检验结果列表 | ❌ FAIL | code=500, msg=请求参数类型不匹配,参数[id]要求类型为:'java.lang.Long',但输入值为:'page' |
| 检验 | 7.7 | 参考范围列表 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 检验 | 7.8 | 检查申请列表 | ❌ FAIL | code=500, msg=No static resource index.html for request '/healthlink-his/index.html'. |
| 影像 | 8.1 | 影像列表查询 | ❌ FAIL | code=500, msg=No static resource index.html for request '/healthlink-his/index.html'. |
| 影像 | 8.2 | 影像增强列表 | ❌ FAIL | code=500, msg=No static resource index.html for request '/healthlink-his/index.html'. |
| 影像 | 8.3 | 影像对比列表 | ❌ FAIL | code=500, msg=No static resource index.html for request '/healthlink-his/index.html'. |
| 影像 | 8.4 | 3D重建列表 | ❌ FAIL | code=500, msg=No static resource reconstruction/3d/page for request '/healthlink-his/reconstruction/3d/page'. |
| 手术 | 9.1 | 手术列表查询 | ❌ FAIL | code=500, msg=No static resource clinical-manage/surgery/page for request '/healthlink-his/clinical-manage/surgery/page'. |
| 手术 | 9.2 | 手术排程列表 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 手术 | 9.3 | 术前讨论列表 | ❌ FAIL | code=500, msg=No static resource preopmanage/discussion/page for request '/healthlink-his/preopmanage/discussion/page'. |
| 手术 | 9.4 | 手术安全核查列表 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 手术 | 9.5 | 麻醉记录列表 | ❌ FAIL | code=500, msg=No static resource api/v1/anesthesia/page for request '/healthlink-his/api/v1/anesthesia/page'. |
| 手术 | 9.6 | 麻醉增强列表 | ❌ FAIL | code=500, msg=No static resource anesthesia-enhanced/page for request '/healthlink-his/anesthesia-enhanced/page'. |
| 手术 | 9.7 | 麻醉质控列表 | ❌ FAIL | code=500, msg=No static resource anesthesia-quality-control/page for request '/healthlink-his/anesthesia-quality-control/page'. |
| 院感 | 10.1 | 院感监测 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 院感 | 10.2 | 院感预警 | ❌ FAIL | code=500, msg=No static resource infection-enhanced/warning/page for request '/healthlink-his/infection-enhanced/warning/page'. |
| 院感 | 10.3 | 耐药监测 | ❌ FAIL | code=500, msg=No static resource infection-enhanced/resistance/page for request '/healthlink-his/infection-enhanced/resistance/page'. |
| 院感 | 10.4 | 职业暴露 | ❌ FAIL | code=500, msg=No static resource infection-enhanced/exposure/page for request '/healthlink-his/infection-enhanced/exposure/page'. |
| 院感 | 10.5 | 手卫生 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 院感 | 10.6 | 环境监测 | ❌ FAIL | code=500, msg=No static resource infection-enhanced/environment/page for request '/healthlink-his/infection-enhanced/environment/page'. |
| 质控 | 11.1 | 运行质控列表 | ❌ FAIL | code=500, msg=No static resource quality-enhanced/runtime/page for request '/healthlink-his/quality-enhanced/runtime/page'. |
| 质控 | 11.2 | 终末质控列表 | ❌ FAIL | code=500, msg=No static resource api/v1/emr-quality/page for request '/healthlink-his/api/v1/emr-quality/page'. |
| 质控 | 11.3 | 质量统计列表 | ❌ FAIL | code=500, msg=No static resource quality-enhanced/statistics/page for request '/healthlink-his/quality-enhanced/statistics/page'. |
| 中医 | 12.1 | 中医体质列表 | ❌ FAIL | code=500, msg=No static resource api/v1/tcm/constitution/page for request '/healthlink-his/api/v1/tcm/constitution/page'. |
| 中医 | 12.2 | 中医方剂列表-至少3个方剂 | ✅ PASS | |
| 中医 | 12.3 | 中医统计查询 | ✅ PASS | |
| 会诊 | 13.1 | 会诊记录列表 | ❌ FAIL | code=500, msg=No static resource consultation/page for request '/healthlink-his/consultation/page'. |
| 会诊 | 13.2 | 会诊反馈列表 | ❌ FAIL | code=500, msg=No static resource cross-module/consult-feedback/page for request '/healthlink-his/cross-module/consult-feedback/page'. |
| 会诊 | 13.3 | 会诊超时列表 | ❌ FAIL | code=500, msg=No static resource cross-module/consulttimeout/page for request '/healthlink-his/cross-module/consulttimeout/page'. |
| 路径 | 14.1 | 临床路径列表-至少3条路径 | ✅ PASS | |
| 危急值 | 15.1 | 危急值列表查询 | ✅ PASS | |
| 点评 | 16.1 | 点评计划列表 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 点评 | 16.2 | 点评记录列表 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 点评 | 16.3 | 点评统计查询 | ✅ PASS | |
| 用药 | 17.1 | 合理用药列表 | ❌ FAIL | code=500, msg=No static resource api/v1/rational-drug/page for request '/healthlink-his/api/v1/rational-drug/page'. |
| 用药 | 17.2 | 相互作用列表 | ❌ FAIL | code=500, msg=No static resource api/v1/rational-drug/interaction/page for request '/healthlink-his/api/v1/rational-drug/interaction/page'. |
| 用药 | 17.3 | 用药统计查询 | ✅ PASS | |
| 用药 | 17.4 | 审计日志列表 | ❌ FAIL | code=500, msg=No static resource api/v1/rational-drug/audit-log for request '/healthlink-his/api/v1/rational-drug/audit-log'. |
| 追溯 | 18.1 | 药品追溯列表 | ❌ FAIL | code=500, msg=No static resource drugtrace/page for request '/healthlink-his/drugtrace/page'. |
| EMPI | 19.1 | EMPI索引列表 | ❌ FAIL | code=500, msg=No static resource api/v1/empi/page for request '/healthlink-his/api/v1/empi/page'. |
| ESB | 20.1 | ESB消息列表 | ❌ FAIL | code=500, msg=No static resource esbmanage/message/page for request '/healthlink-his/esbmanage/message/page'. |
| ESB | 20.2 | ESB服务注册列表 | ❌ FAIL | code=500, msg=No static resource esbmanage/registry/page for request '/healthlink-his/esbmanage/registry/page'. |
| CA | 21.1 | CA签名列表 | ❌ FAIL | code=500, msg=No static resource api/v1/ca-signature/page for request '/healthlink-his/api/v1/ca-signature/page'. |
| CA | 21.2 | CA签名统计 | ✅ PASS | |
| 病案 | 22.1 | 病案首页列表 | ❌ FAIL | code=500, msg=请求参数类型不匹配,参数[id]要求类型为:'java.lang.Long',但输入值为:'page' |
| 病案 | 22.2 | 病案质量检查 | ❌ FAIL | code=500, msg=请求参数类型不匹配,参数[homepageId]要求类型为:'java.lang.Long',但输入值为:'page' |
| 随访 | 23.1 | 随访计划列表 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 知情 | 24.1 | 知情同意列表 | ❌ FAIL | code=500, msg=No static resource api/v1/informed-consent/page for request '/healthlink-his/api/v1/informed-consent/page'. |
| CSSD | 25.1 | 消毒追溯列表 | ❌ FAIL | code=500, msg=No static resource cssd/trace/page for request '/healthlink-his/cssd/trace/page'. |
| 急诊 | 26.1 | 急诊记录列表 | ❌ FAIL | code=500, msg=No static resource emergency/page for request '/healthlink-his/emergency/page'. |
| 急诊 | 26.2 | 分诊排队列表 | ❌ FAIL | code=500, msg=No static resource index.html for request '/healthlink-his/index.html'. |
| 医保 | 27.1 | 医保目录列表 | ❌ FAIL | code=500, msg=No static resource ybmanage/catalog/page for request '/healthlink-his/ybmanage/catalog/page'. |
| 抗菌 | 28.1 | 抗菌药物列表 | ❌ FAIL | code=500, msg=No static resource api/v1/antibiotic/page for request '/healthlink-his/api/v1/antibiotic/page'. |
| DRG | 29.1 | DRG分析列表 | ❌ FAIL | code=500, msg=No static resource api/v1/mr-homepage/drg/page for request '/healthlink-his/api/v1/mr-homepage/drg/page'. |
| DRG | 29.2 | DRG预警列表 | ❌ FAIL | code=500, msg=No static resource cross-module/enhanced-drg-alert/page for request '/healthlink-his/cross-module/enhanced-drg-alert/page'. |
| 经营 | 30.1 | 经营分析列表 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 系统 | 31.1 | 字典类型列表 | ❌ FAIL | code=500, msg=No static resource dict/type/page for request '/healthlink-his/dict/type/page'. |
| 系统 | 31.2 | 用户管理-列表非空 | ❌ FAIL | 用户列表为空,系统用户数据异常 |
| 系统 | 31.3 | 角色管理列表 | ❌ FAIL | code=500, msg=请求参数类型不匹配,参数[roleId]要求类型为:'java.lang.Long',但输入值为:'page' |
| 系统 | 31.4 | 菜单管理-菜单数量>50 | ✅ PASS | |
| 系统 | 31.5 | 部门管理-部门数量>5 | ✅ PASS | |
| 系统 | 31.6 | 岗位管理列表 | ❌ FAIL | code=500, msg=请求参数类型不匹配,参数[postId]要求类型为:'java.lang.Long',但输入值为:'page' |
| 系统 | 31.7 | 通知管理列表 | ❌ FAIL | code=500, msg=请求参数类型不匹配,参数[noticeId]要求类型为:'java.lang.Long',但输入值为:'page' |
| 系统 | 31.8 | 审计日志列表 | ❌ FAIL | code=500, msg=
### Error querying database. Cause: org.postgresql.util.PSQLException: ERROR: column "delete_flag" does not exist
Position: 51
### The error may exist in com/healthlink/his/sys/mapper/SysAuditLogMapper.java (best guess)
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT COUNT(*) AS total FROM sys_audit_log WHERE delete_flag = '0'
### Cause: org.postgresql.util.PSQLException: ERROR: column "delete_flag" does not exist
Position: 51
; bad SQL grammar [] |
| 系统 | 31.9 | 仪表盘数据 | ❌ FAIL | 预期code=200, 实际code=500, msg=请求参数类型不匹配,参数[id]要求类型为:'java.lang.Long',但输入值为:'data' |
| 药房 | 32.1 | 库存预警列表 | ❌ FAIL | rows不是数组类型: <class 'dict'> |
| 药房 | 32.2 | 西药发药列表 | ❌ FAIL | code=500, msg=No static resource pharmacy-manage/western-medicine-dispense/page for request '/healthlink-his/pharmacy-manage/western-medicine-dispense/page'. |
| 药房 | 32.3 | 退药管理列表 | ❌ FAIL | code=500, msg=No static resource pharmacy-manage/return-medicine/page for request '/healthlink-his/pharmacy-manage/return-medicine/page'. |
| 药房 | 32.4 | 药品详情列表 | ❌ FAIL | code=500, msg=No static resource pharmacy-manage/medication-details/page for request '/healthlink-his/pharmacy-manage/medication-details/page'. |
| 报表 | 33.1 | 挂号报表 | ❌ FAIL | code=500, msg=No static resource report-manage/register/page for request '/healthlink-his/report-manage/register/page'. |
| 报表 | 33.2 | 收费报表 | ❌ FAIL | code=500, msg=No static resource report-manage/charge/page for request '/healthlink-his/report-manage/charge/page'. |
| 报表 | 33.3 | 住院首页采集 | ❌ FAIL | code=500, msg=No static resource medicalRecordHomePage-manage/collection/page for request '/healthlink-his/medicalRecordHomePage-manage/collection/page'. |
| 报表 | 33.4 | 经营统计 | ❌ FAIL | code=500, msg=No static resource report-manage/report-statistics/page for request '/healthlink-his/report-manage/report-statistics/page'. |

162
MD/test/test_api.sh Executable file
View File

@@ -0,0 +1,162 @@
#!/bin/bash
# HealthLink-HIS 全流程API测试脚本
BASE_URL="http://localhost:18082/healthlink-his"
TOKEN=""
PASS=0
FAIL=0
TOTAL=0
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 登录获取Token
login() {
echo -e "${YELLOW}1. 登录认证${NC}"
TOKEN=$(curl -s -X POST "$BASE_URL/login" \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123","tenantId":"1"}' | \
python3 -c "import sys,json;print(json.load(sys.stdin).get('token',''))")
if [ -n "$TOKEN" ]; then
echo -e "${GREEN}✅ 登录成功${NC}"
PASS=$((PASS+1))
else
echo -e "${RED}❌ 登录失败${NC}"
FAIL=$((FAIL+1))
fi
TOTAL=$((TOTAL+1))
}
# 测试API
test_api() {
local name=$1
local method=$2
local path=$3
local data=$4
local response
if [ "$method" = "GET" ]; then
response=$(curl -s "$BASE_URL$path" -H "Authorization: Bearer $TOKEN")
else
response=$(curl -s -X POST "$BASE_URL$path" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$data")
fi
local code=$(echo "$response" | python3 -c "import sys,json;print(json.load(sys.stdin).get('code','ERROR'))" 2>/dev/null)
TOTAL=$((TOTAL+1))
if [ "$code" = "200" ]; then
echo -e "${GREEN}$name${NC}"
PASS=$((PASS+1))
else
echo -e "${RED}$name (Code: $code)${NC}"
FAIL=$((FAIL+1))
fi
}
echo "=========================================="
echo " HealthLink-HIS 全流程API测试"
echo "=========================================="
echo ""
# 1. 登录认证
login
# 2. 门诊就诊流程
echo ""
echo -e "${YELLOW}2. 门诊就诊流程${NC}"
test_api "门诊挂号" "POST" "/api/v1/outpatient/registration" '{"patientId":1,"doctorId":1,"deptId":1}'
test_api "门诊处方" "POST" "/api/v1/outpatient/prescription" '{"encounterId":1001,"patientId":1}'
# 3. 住院入院流程
echo ""
echo -e "${YELLOW}3. 住院入院流程${NC}"
test_api "入院登记" "POST" "/api/v1/inpatient/admission" '{"patientId":1,"deptId":5,"bedNo":"ICU-01"}'
test_api "护理评估(Braden)" "POST" "/nursing-assessment-enhanced/braden/assess" '{"patientName":"患者甲","encounterId":1001,"itemScores":"{\"sensation\":2,\"moisture\":2,\"activity\":1,\"mobility\":2,\"nutrition\":3,\"friction\":2}"}'
test_api "护理评估(Morse)" "POST" "/nursing-assessment-enhanced/morse/assess" '{"patientName":"患者甲","encounterId":1001,"itemScores":"{\"history\":15,\"diagnosis\":0,\"ambulation\":15,\"iv\":20,\"gait\":0,\"mental\":0}"}'
# 4. 药房管理流程
echo ""
echo -e "${YELLOW}4. 药房管理流程${NC}"
test_api "库存查询" "GET" "/pharmacystockalert/page?pageNo=1&pageSize=10" ""
test_api "库存预警" "GET" "/pharmacystockalert/summary" ""
# 5. 检验管理流程
echo ""
echo -e "${YELLOW}5. 检验管理流程${NC}"
test_api "检验申请" "GET" "/inspection/page?pageNo=1&pageSize=10" ""
# 6. 影像检查流程
echo ""
echo -e "${YELLOW}6. 影像检查流程${NC}"
test_api "影像对比" "GET" "/radiology-comparison/compare?patientId=1" ""
# 7. 手术麻醉流程
echo ""
echo -e "${YELLOW}7. 手术麻醉流程${NC}"
test_api "麻醉记录" "GET" "/anesthesia-enhanced/specimen/page?pageNo=1&pageSize=10" ""
test_api "麻醉质控" "GET" "/anesthesia-enhanced/qc/stats" ""
# 8. 院感管理流程
echo ""
echo -e "${YELLOW}8. 院感管理流程${NC}"
test_api "感染监测" "GET" "/infection/surveillance/page?pageNo=1&pageSize=10" ""
test_api "暴发预警" "GET" "/infection/warning/page?pageNo=1&pageSize=10" ""
test_api "多重耐药" "GET" "/infection/resistant/page?pageNo=1&pageSize=10" ""
test_api "职业暴露" "GET" "/infection/exposure/page?pageNo=1&pageSize=10" ""
test_api "手卫生" "GET" "/infection/hygiene/page?pageNo=1&pageSize=10" ""
test_api "环境监测" "GET" "/infection/environment/page?pageNo=1&pageSize=10" ""
# 9. 质量管理流程
echo ""
echo -e "${YELLOW}9. 质量管理流程${NC}"
test_api "护理质量" "GET" "/nursing-quality/page?pageNo=1&pageSize=10" ""
test_api "护理质量统计" "GET" "/nursing-quality/summary" ""
test_api "病历质量" "GET" "/api/v1/emr-quality/defect-statistics" ""
# 10. 处方点评流程
echo ""
echo -e "${YELLOW}10. 处方点评流程${NC}"
test_api "点评计划" "GET" "/api/v1/review/plans?pageNum=1&pageSize=10" ""
test_api "点评统计" "GET" "/api/v1/review/statistics" ""
# 11. 临床路径流程
echo ""
echo -e "${YELLOW}11. 临床路径流程${NC}"
test_api "路径管理" "GET" "/clinical-pathway/page?pageNo=1&pageSize=10" ""
# 12. 中医管理流程
echo ""
echo -e "${YELLOW}12. 中医管理流程${NC}"
test_api "中医方剂" "GET" "/api/v1/tcm/prescriptions" ""
test_api "中医统计" "GET" "/api/v1/tcm/statistics" ""
# 13. 医嘱闭环流程
echo ""
echo -e "${YELLOW}13. 医嘱闭环流程${NC}"
test_api "医嘱闭环" "GET" "/api/v1/order-closed-loop/list" ""
test_api "闭环统计" "GET" "/api/v1/order-closed-loop/statistics" ""
# 14. ESB管理
echo ""
echo -e "${YELLOW}14. ESB管理${NC}"
test_api "ESB监控" "GET" "/esb-reliability/monitor/stats" ""
# 汇总
echo ""
echo "=========================================="
echo " 测试结果汇总"
echo "=========================================="
echo -e "总测试数: $TOTAL"
echo -e "${GREEN}通过: $PASS${NC}"
echo -e "${RED}失败: $FAIL${NC}"
echo -e "通过率: $((PASS*100/TOTAL))%"
echo "=========================================="
exit $FAIL