Files
his/MD/test/06_business_logic_complex.py
华佗 bc92620f66 fix: 修复前端路由名重复导致的404问题 + E2E测试20/20通过
根因分析:
- 后端菜单配置存在30+个重复路由名(如Record/Enhanced/Charge等)
- Vue Router不允许重名路由,addRoute抛出异常
- permission.js的catch直接调用logOut(),导致所有页面重定向到登录页

修复内容:
1. permission.js: addRoute时try-catch重名错误,跳过而非登出
2. permission store: filterAsyncRouter中添加路由名自动去重逻辑
3. 新增src/api/anesthesia.js: 麻醉模块API文件缺失修复
4. 修正test-data.ts中所有错误路由路径,匹配实际菜单配置

验证: workflow-full.spec.ts 20/20通过, login.spec.ts 4/4通过
2026-06-08 00:18:34 +08:00

1264 lines
55 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
HealthLink-HIS 三甲医院复杂业务逻辑全流程测试
覆盖: 门诊全流程、住院全流程、手术全流程、药品全流程、多角色协作、权限隔离
使用真实API调用验证业务逻辑正确性
"""
import requests
import json
import time
import sys
from datetime import datetime, timedelta
BASE_URL = "http://localhost:18082/healthlink-his"
RESULTS = []
PASSED = 0
FAILED = 0
ERRORS = []
# ======================== 测试用户 ========================
USERS = {
"admin": {"username": "admin", "password": "admin123", "role": "超级管理员"},
"doctor": {"username": "doctor1", "password": "123456", "role": "医生"},
"jzys": {"username": "jzys", "password": "123456", "role": "急诊医生"},
"jzhs": {"username": "jzhs", "password": "123456", "role": "急诊护士"},
"nkhs": {"username": "nkhs1", "password": "123456", "role": "内科护士"},
"ssshs": {"username": "ssshs1", "password": "123456", "role": "手术室护士"},
"pharmacist": {"username": "yjk1", "password": "123456", "role": "药师"},
"tech": {"username": "医技员", "password": "123456", "role": "医技"},
"finance": {"username": "sfy", "password": "123456", "role": "收费员"},
"consultant": {"username": "hzzj1", "password": "123456", "role": "会诊专家"},
}
# 缓存每个用户的token
TOKEN_CACHE = {}
def login(username, password):
"""登录并缓存token"""
if username in TOKEN_CACHE and TOKEN_CACHE[username]:
return TOKEN_CACHE[username]
try:
resp = requests.post(f"{BASE_URL}/login", json={
"username": username, "password": password, "tenantId": "1"
}, timeout=10)
data = resp.json()
if data.get("code") == 200 and data.get("token"):
TOKEN_CACHE[username] = data["token"]
return data["token"]
except Exception as e:
print(f" ⚠️ 登录失败 {username}: {e}")
return None
def api(method, path, token=None, data=None, params=None, expected_code=200, desc=""):
"""统一API调用"""
headers = {"Content-Type": "application/json"}
if token:
headers["Authorization"] = f"Bearer {token}"
url = f"{BASE_URL}{path}"
try:
if method == "GET":
resp = requests.get(url, headers=headers, params=params, timeout=30)
elif method == "POST":
resp = requests.post(url, headers=headers, json=data, timeout=30)
elif method == "PUT":
resp = requests.put(url, headers=headers, json=data, timeout=30)
elif method == "DELETE":
resp = requests.delete(url, headers=headers, timeout=30)
else:
return None
result = resp.json() if resp.headers.get("content-type", "").startswith("application/json") else {"code": resp.status_code, "msg": resp.text[:200]}
actual_code = result.get("code", resp.status_code)
success = actual_code == expected_code
return {"success": success, "code": actual_code, "data": result.get("data"), "msg": result.get("msg", ""), "raw": result}
except requests.exceptions.Timeout:
return {"success": False, "code": 0, "msg": "请求超时", "data": None}
except Exception as e:
return {"success": False, "code": 0, "msg": str(e)[:200], "data": None}
def record(test_id, name, passed, details="", data_flow=""):
"""记录测试结果"""
global PASSED, FAILED
status = "" if passed else ""
if passed:
PASSED += 1
else:
FAILED += 1
RESULTS.append({"id": test_id, "name": name, "passed": passed, "details": details})
flow_str = f" 📊 数据流: {data_flow}" if data_flow else ""
print(f" {status} [{test_id}] {name}" + (f"{details}" if details else ""))
if flow_str:
print(flow_str)
# ======================== 1. 登录认证测试 ========================
def test_auth():
print("\n" + "="*60)
print("📋 模块一: 登录认证与Token管理")
print("="*60)
# TC-AUTH-001: 管理员正常登录
token = login("admin", "admin123")
record("TC-AUTH-001", "管理员正常登录", token is not None,
f"获取token: {'' if token else ''}", "admin → /login → token")
# TC-AUTH-002: 错误密码登录
result = api("POST", "/login", data={"username": "admin", "password": "wrong", "tenantId": "1"}, expected_code=500)
record("TC-AUTH-002", "错误密码拒绝登录", not result["success"],
f"返回: code={result['code']}", "admin(错误密码) → /login → 500")
# TC-AUTH-003: 获取用户信息
result = api("GET", "/getInfo", token=token)
record("TC-AUTH-003", "获取当前用户信息", result["success"],
f"用户: {result['data'].get('user', {}).get('nickName', 'N/A') if result['data'] else 'N/A'}",
"token → /getInfo → 用户信息")
# TC-AUTH-004: 多角色登录
all_tokens = {}
for key, user in USERS.items():
t = login(user["username"], user["password"])
all_tokens[key] = t
record(f"TC-AUTH-004-{key}", f"{user['role']}({user['username']})登录", t is not None,
f"token: {'' if t else ''}")
# TC-AUTH-005: 获取菜单路由
result = api("GET", "/getRouters", token=token)
menu_count = len(result["data"]) if result["data"] else 0
record("TC-AUTH-005", "获取菜单路由树", result["success"] and menu_count > 0,
f"一级菜单: {menu_count}", "/getRouters → 菜单树")
return all_tokens
# ======================== 2. 系统管理测试 ========================
def test_system(tokens):
print("\n" + "="*60)
print("📋 模块二: 系统管理")
print("="*60)
admin_token = tokens.get("admin")
if not admin_token:
print(" ⚠️ 跳过: 管理员未登录")
return
# TC-SYS-001: 用户列表
result = api("GET", "/system/user/list", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
user_count = result["data"].get("total", 0) if result["data"] else 0
record("TC-SYS-001", "用户列表分页查询", result["success"] and user_count > 0,
f"总用户数: {user_count}", "/system/user/list → 分页数据")
# TC-SYS-002: 角色列表
result = api("GET", "/system/role/list", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
role_count = result["data"].get("total", 0) if result["data"] else 0
record("TC-SYS-002", "角色列表分页查询", result["success"] and role_count > 0,
f"总角色数: {role_count}", "/system/role/list → 分页数据")
# TC-SYS-003: 部门树
result = api("GET", "/system/dept/list", token=admin_token)
dept_count = len(result["data"]) if result["data"] else 0
record("TC-SYS-003", "部门树查询", result["success"],
f"部门数: {dept_count}", "/system/dept/list → 部门树")
# TC-SYS-004: 数据字典查询
result = api("GET", "/system/dict/type/list", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
dict_count = result["data"].get("total", 0) if result["data"] else 0
record("TC-SYS-004", "数据字典类型查询", result["success"],
f"字典类型数: {dict_count}", "/system/dict/type/list → 字典类型")
# TC-SYS-005: 数据字典数据查询
result = api("GET", "/system/dict/data/list", token=admin_token,
params={"dictType": "sys_user_sex", "pageNum": 1, "pageSize": 10})
record("TC-SYS-005", "数据字典数据查询", result["success"],
f"性别字典数据: {len(result['data'].get('rows', [])) if result['data'] else 0}",
"/system/dict/data/list → 性别字典")
# TC-SYS-006: 系统配置查询
result = api("GET", "/system/config/list", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-SYS-006", "系统配置查询", result["success"],
f"配置数: {result['data'].get('total', 0) if result['data'] else 0}",
"/system/config/list → 配置项")
# TC-SYS-007: 通知公告列表
result = api("GET", "/system/notice/list", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-SYS-007", "通知公告列表", result["success"],
f"公告数: {result['data'].get('total', 0) if result['data'] else 0}",
"/system/notice/list → 公告列表")
# ======================== 3. 门诊全流程测试 ========================
def test_outpatient(tokens):
print("\n" + "="*60)
print("📋 模块三: 门诊全流程 (挂号→就诊→开方→收费→取药)")
print("="*60)
finance_token = tokens.get("finance")
doctor_token = tokens.get("doctor")
pharmacist_token = tokens.get("pharmacist")
if not all([finance_token, doctor_token, pharmacist_token]):
print(" ⚠️ 跳过: 关键角色未登录")
return
# --- 3.1 收费挂号 ---
# TC-OP-001: 查询挂号科室
result = api("GET", "/charge-manage/register/init", token=finance_token)
record("TC-OP-001", "挂号初始化-科室列表", result["success"],
"获取科室数据", "/charge-manage/register/init → 科室列表")
# TC-OP-002: 查询挂号医生
result = api("GET", "/charge-manage/register/init", token=finance_token)
record("TC-OP-002", "挂号初始化-医生列表", result["success"],
"获取医生数据", "/charge-manage/register/init → 医生列表")
# TC-OP-003: 查询患者列表
result = api("GET", "/doctor-station/main/patient-list", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-OP-003", "医生站-患者列表", result["success"],
f"患者数: {result['data'].get('total', 0) if result['data'] else 0}",
"/doctor-station/main/patient-list → 患者列表")
# --- 3.2 医生诊疗 ---
# TC-OP-004: 医生站待诊列表
result = api("GET", "/doctor-station/main/pending-list", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-OP-004", "医生站-待诊列表", result["success"],
f"待诊: {result['data'].get('total', 0) if result['data'] else 0}",
"/doctor-station/main/pending-list → 待诊列表")
# TC-OP-005: 医嘱列表
result = api("GET", "/doctor-station/advice/list", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-OP-005", "医生站-医嘱列表", result["success"],
f"医嘱数: {result['data'].get('total', 0) if result['data'] else 0}",
"/doctor-station/advice/list → 医嘱列表")
# TC-OP-006: 诊断列表
result = api("GET", "/doctor-station/diagnosis/list", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-OP-006", "医生站-诊断列表", result["success"],
f"诊断数: {result['data'].get('total', 0) if result['data'] else 0}",
"/doctor-station/diagnosis/list → 诊断列表")
# --- 3.3 药品管理 ---
# TC-OP-007: 待发药列表
result = api("GET", "/pharmacy-manage/pending-medication/pending-medication-page",
token=pharmacist_token, params={"pageNum": 1, "pageSize": 10})
record("TC-OP-007", "药房-待发药列表", result["success"],
f"待发药: {result['data'].get('total', 0) if result['data'] else 0}",
"/pharmacy-manage/pending-medication/pending-medication-page → 待发药")
# TC-OP-008: 西药发药
result = api("GET", "/pharmacy-manage/western-medicine-dispense/init",
token=pharmacist_token)
record("TC-OP-008", "药房-西药发药初始化", result["success"],
"获取西药发药数据", "/pharmacy-manage/western-medicine-dispense/init → 发药初始化")
# TC-OP-009: 药品追溯
result = api("GET", "/drugtrace/code/page", token=pharmacist_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-OP-009", "药品追溯码查询", result["success"],
f"追溯码: {result['data'].get('total', 0) if result['data'] else 0}",
"/drugtrace/code/page → 追溯码列表")
# --- 3.4 收费结算 ---
# TC-OP-010: 门诊收费列表
result = api("GET", "/charge-manage/charge/list", token=finance_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-OP-010", "门诊收费列表", result["success"],
f"收费记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/charge-manage/charge/list → 收费列表")
# TC-OP-011: 退费列表
result = api("GET", "/charge-manage/refund/list", token=finance_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-OP-011", "门诊退费列表", result["success"],
f"退费记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/charge-manage/refund/list → 退费列表")
# TC-OP-012: 门诊病历记录
result = api("GET", "/charge-manage/charge/clinic-record", token=finance_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-OP-012", "门诊病历记录", result["success"],
f"病历数: {result['data'].get('total', 0) if result['data'] else 0}",
"/charge-manage/charge/clinic-record → 病历记录")
# ======================== 4. 住院全流程测试 ========================
def test_inpatient(tokens):
print("\n" + "="*60)
print("📋 模块四: 住院全流程 (入院→医嘱→护理→手术→出院)")
print("="*60)
doctor_token = tokens.get("doctor")
nurse_token = tokens.get("nkhs")
if not all([doctor_token, nurse_token]):
print(" ⚠️ 跳过: 关键角色未登录")
return
# TC-IN-001: 住院登记列表
result = api("GET", "/inhospital-charge/register/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-IN-001", "住院登记列表", result["success"],
f"住院登记: {result['data'].get('total', 0) if result['data'] else 0}",
"/inhospital-charge/register/page → 住院登记列表")
# TC-IN-002: 患者首页
result = api("GET", "/patient-home-manage/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-IN-002", "住院患者首页列表", result["success"],
f"在院患者: {result['data'].get('total', 0) if result['data'] else 0}",
"/patient-home-manage/page → 在院患者列表")
# TC-IN-003: 预交金管理
result = api("GET", "/deposit-manage/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-IN-003", "预交金管理列表", result["success"],
f"预交金记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/deposit-manage/page → 预交金列表")
# TC-IN-004: 护理记录
result = api("GET", "/nursing-record/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-IN-004", "护理记录列表", result["success"],
f"护理记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/nursing-record/page → 护理记录")
# TC-IN-005: 生命体征
result = api("GET", "/vital-signs/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-IN-005", "生命体征记录", result["success"],
f"体征记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/vital-signs/page → 生命体征")
# TC-IN-006: 生命体征图表
result = api("GET", "/vital-signs-chart/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-IN-006", "生命体征图表", result["success"],
"图表数据", "/vital-signs-chart/page → 图表")
# TC-IN-007: 医嘱执行
result = api("GET", "/inhospitalnursestation/nursebilling/execute/list",
token=nurse_token, params={"pageNum": 1, "pageSize": 10})
record("TC-IN-007", "医嘱执行列表", result["success"],
f"执行医嘱: {result['data'].get('total', 0) if result['data'] else 0}",
"/inhospitalnursestation/nursebilling/execute/list → 医嘱执行")
# TC-IN-008: 护理交班
result = api("GET", "/api/v1/nursing/handoff/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-IN-008", "护理交班记录", result["success"],
f"交班记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/nursing/handoff/page → 交班记录")
# TC-IN-009: 护理评估
result = api("GET", "/api/v1/nursing/assessment/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-IN-009", "护理评估列表", result["success"],
f"评估记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/nursing/assessment/page → 评估列表")
# TC-IN-010: 护理计划
result = api("GET", "/care-plan/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-IN-010", "护理计划列表", result["success"],
f"护理计划: {result['data'].get('total', 0) if result['data'] else 0}",
"/care-plan/page → 护理计划")
# TC-IN-011: 出院管理
result = api("GET", "/discharge/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-IN-011", "出院管理列表", result["success"],
f"出院记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/discharge/page → 出院列表")
# ======================== 5. 手术全流程测试 ========================
def test_surgery(tokens):
print("\n" + "="*60)
print("📋 模块五: 手术全流程 (申请→讨论→排程→执行)")
print("="*60)
doctor_token = tokens.get("doctor")
nurse_token = tokens.get("ssshs")
if not all([doctor_token, nurse_token]):
print(" ⚠️ 跳过: 关键角色未登录")
return
# TC-SUR-001: 手术申请列表
result = api("GET", "/clinical-manage/surgery/surgery-page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-SUR-001", "手术申请列表", result["success"],
f"手术申请: {result['data'].get('total', 0) if result['data'] else 0}",
"/clinical-manage/surgery/surgery-page → 手术申请")
# TC-SUR-002: 术前讨论
result = api("GET", "/preop-discussion/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-SUR-002", "术前讨论列表", result["success"],
f"讨论记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/preop-discussion/page → 术前讨论")
# TC-SUR-003: 手术排程
result = api("GET", "/clinical-manage/surgery-schedule/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-SUR-003", "手术排程列表", result["success"],
f"排程记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/clinical-manage/surgery-schedule/page → 手术排程")
# TC-SUR-004: 手术安全核查
result = api("GET", "/surgery-safety-check/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-SUR-004", "手术安全核查", result["success"],
f"核查记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/surgery-safety-check/page → 安全核查")
# TC-SUR-005: 麻醉记录
result = api("GET", "/api/v1/anesthesia/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-SUR-005", "麻醉记录列表", result["success"],
f"麻醉记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/anesthesia/page → 麻醉记录")
# TC-SUR-006: 麻醉增强
result = api("GET", "/anesthesia-enhanced/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-SUR-006", "麻醉增强管理", result["success"],
f"增强记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/anesthesia-enhanced/page → 麻醉增强")
# TC-SUR-007: 手术室管理
result = api("GET", "/base-data-manage/operating-room/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-SUR-007", "手术室管理", result["success"],
f"手术室: {result['data'].get('total', 0) if result['data'] else 0}",
"/base-data-manage/operating-room/page → 手术室列表")
# TC-SUR-008: 手术室排班
result = api("GET", "/schedule-pool/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-SUR-008", "手术室排班", result["success"],
f"排班记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/schedule-pool/page → 手术室排班")
# ======================== 6. 医技检查全流程 ========================
def test_inspection(tokens):
print("\n" + "="*60)
print("📋 模块六: 医技检查全流程 (申请→采样→检验→报告)")
print("="*60)
tech_token = tokens.get("tech")
doctor_token = tokens.get("doctor")
if not all([tech_token, doctor_token]):
print(" ⚠️ 跳过: 关键角色未登录")
return
# TC-INS-001: 检验申请单
result = api("GET", "/reg-doctorstation/request-form/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INS-001", "检验申请单列表", result["success"],
f"申请单: {result['data'].get('total', 0) if result['data'] else 0}",
"/reg-doctorstation/request-form/page → 申请单列表")
# TC-INS-002: 标本采集
result = api("GET", "/inspection/collection/page", token=tech_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INS-002", "标本采集列表", result["success"],
f"采集记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/inspection/collection/page → 标本采集")
# TC-INS-003: 检验仪器
result = api("GET", "/inspection/instrument/information-page", token=tech_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INS-003", "检验仪器列表", result["success"],
f"仪器: {result['data'].get('total', 0) if result['data'] else 0}",
"/inspection/instrument/information-page → 仪器列表")
# TC-INS-004: 检验标本
result = api("GET", "/inspection/specimen/information-page", token=tech_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INS-004", "检验标本列表", result["success"],
f"标本: {result['data'].get('total', 0) if result['data'] else 0}",
"/inspection/specimen/information-page → 标本列表")
# TC-INS-005: 检验观察
result = api("GET", "/inspection/observation/information-page", token=tech_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INS-005", "检验观察结果", result["success"],
f"观察: {result['data'].get('total', 0) if result['data'] else 0}",
"/inspection/observation/information-page → 观察结果")
# TC-INS-006: 检验科配置
result = api("GET", "/inspection/lisConfig/init-page", token=tech_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INS-006", "检验科配置", result["success"],
"配置信息", "/inspection/lisConfig/init-page → 检验配置")
# TC-INS-007: 标本条码
result = api("GET", "/specimen-barcode/page", token=tech_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INS-007", "标本条码管理", result["success"],
f"条码: {result['data'].get('total', 0) if result['data'] else 0}",
"/specimen-barcode/page → 条码管理")
# TC-INS-008: 影像管理
result = api("GET", "/radiology-enhanced/page", token=tech_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INS-008", "影像增强管理", result["success"],
f"影像: {result['data'].get('total', 0) if result['data'] else 0}",
"/radiology-enhanced/page → 影像管理")
# TC-INS-009: 影像对比
result = api("GET", "/radiology-comparison/page", token=tech_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INS-009", "影像对比管理", result["success"],
f"对比: {result['data'].get('total', 0) if result['data'] else 0}",
"/radiology-comparison/page → 影像对比")
# TC-INS-010: 3D重建
result = api("GET", "/reconstruction/page", token=tech_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INS-010", "3D重建管理", result["success"],
f"重建: {result['data'].get('total', 0) if result['data'] else 0}",
"/reconstruction/page → 3D重建")
# ======================== 7. 院感管理测试 ========================
def test_infection(tokens):
print("\n" + "="*60)
print("📋 模块七: 院感管理")
print("="*60)
nurse_token = tokens.get("nkhs")
tech_token = tokens.get("tech")
if not nurse_token:
print(" ⚠️ 跳过: 护士未登录")
return
# TC-INF-001: 院感监测
result = api("GET", "/infection-enhanced/surveillance/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INF-001", "院感监测列表", result["success"],
f"监测: {result['data'].get('total', 0) if result['data'] else 0}",
"/infection-enhanced/surveillance/page → 院感监测")
# TC-INF-002: 院感预警
result = api("GET", "/infection-enhanced/warning/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INF-002", "院感预警列表", result["success"],
f"预警: {result['data'].get('total', 0) if result['data'] else 0}",
"/infection-enhanced/warning/page → 院感预警")
# TC-INF-003: 耐药监测
result = api("GET", "/infection-enhanced/mdr/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INF-003", "耐药监测列表", result["success"],
f"耐药: {result['data'].get('total', 0) if result['data'] else 0}",
"/infection-enhanced/mdr/page → 耐药监测")
# TC-INF-004: 职业暴露
result = api("GET", "/infection-enhanced/exposure/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INF-004", "职业暴露列表", result["success"],
f"暴露: {result['data'].get('total', 0) if result['data'] else 0}",
"/infection-enhanced/exposure/page → 职业暴露")
# TC-INF-005: 手卫生
result = api("GET", "/infection-enhanced/hand-hygiene/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INF-005", "手卫生管理", result["success"],
f"手卫生: {result['data'].get('total', 0) if result['data'] else 0}",
"/infection-enhanced/hand-hygiene/page → 手卫生")
# TC-INF-006: 环境监测
result = api("GET", "/infection-enhanced/env-monitor/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INF-006", "环境监测列表", result["success"],
f"环境监测: {result['data'].get('total', 0) if result['data'] else 0}",
"/infection-enhanced/env-monitor/page → 环境监测")
# TC-INF-007: 传染病直报
result = api("GET", "/api/v1/epidemic/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-INF-007", "传染病直报列表", result["success"],
f"直报: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/epidemic/page → 传染病直报")
# ======================== 8. 质量管理测试 ========================
def test_quality(tokens):
print("\n" + "="*60)
print("📋 模块八: 质量管理")
print("="*60)
admin_token = tokens.get("admin")
doctor_token = tokens.get("doctor")
if not admin_token:
print(" ⚠️ 跳过: 管理员未登录")
return
# TC-QA-001: 质量增强
result = api("GET", "/quality-enhanced/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-QA-001", "质量增强管理", result["success"],
f"质量记录: {result['data'].get('total', 0) if result['data'] else 0}",
"/quality-enhanced/page → 质量管理")
# TC-QA-002: 质量统计
result = api("GET", "/quality-enhanced/statistics", token=admin_token)
record("TC-QA-002", "质量统计", result["success"],
"统计数据", "/quality-enhanced/statistics → 质量统计")
# TC-QA-003: 质量缺陷
result = api("GET", "/quality-enhanced/defect/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-QA-003", "质量缺陷列表", result["success"],
f"缺陷: {result['data'].get('total', 0) if result['data'] else 0}",
"/quality-enhanced/defect/page → 缺陷列表")
# TC-QA-004: 处方点评
result = api("GET", "/api/v1/review/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-QA-004", "处方点评列表", result["success"],
f"点评: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/review/page → 处方点评")
# TC-QA-005: 合理用药
result = api("GET", "/api/v1/rational-drug/interaction-rule/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-QA-005", "合理用药规则", result["success"],
f"规则: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/rational-drug/interaction-rule/page → 用药规则")
# TC-QA-006: 合理用药统计
result = api("GET", "/api/v1/rational-drug/statistics", token=admin_token)
record("TC-QA-006", "合理用药统计", result["success"],
"统计数据", "/api/v1/rational-drug/statistics → 用药统计")
# TC-QA-007: 病历质量
result = api("GET", "/api/v1/emr-quality/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-QA-007", "病历质量列表", result["success"],
f"病历质量: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/emr-quality/page → 病历质量")
# TC-QA-008: 危急值管理
result = api("GET", "/api/v1/critical-value/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-QA-008", "危急值管理", result["success"],
f"危急值: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/critical-value/page → 危急值管理")
# TC-QA-009: 临床路径
result = api("GET", "/clinical-pathway/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-QA-009", "临床路径管理", result["success"],
f"临床路径: {result['data'].get('total', 0) if result['data'] else 0}",
"/clinical-pathway/page → 临床路径")
# TC-QA-010: 医嘱闭环
result = api("GET", "/api/v1/order-closed-loop/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-QA-010", "医嘱闭环管理", result["success"],
f"闭环: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/order-closed-loop/page → 医嘱闭环")
# ======================== 9. 中医管理测试 ========================
def test_tcm(tokens):
print("\n" + "="*60)
print("📋 模块九: 中医管理")
print("="*60)
doctor_token = tokens.get("doctor")
if not doctor_token:
print(" ⚠️ 跳过: 医生未登录")
return
# TC-TCM-001: 中医传统诊疗
result = api("GET", "/api/v1/tcm/traditional/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-TCM-001", "中医传统诊疗列表", result["success"],
f"诊疗: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/tcm/traditional/page → 中医诊疗")
# TC-TCM-002: 中医体质辨识
result = api("GET", "/api/v1/tcm/constitution/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-TCM-002", "中医体质辨识", result["success"],
f"体质: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/tcm/constitution/page → 体质辨识")
# TC-TCM-003: 壮医特色
result = api("GET", "/api/v1/tcm/zuang-medicine/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-TCM-003", "壮医特色诊疗", result["success"],
f"壮医: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/tcm/zuang-medicine/page → 壮医诊疗")
# TC-TCM-004: 中医处方
result = api("GET", "/doctor-station/chinese-medical/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-TCM-004", "中医处方列表", result["success"],
f"处方: {result['data'].get('total', 0) if result['data'] else 0}",
"/doctor-station/chinese-medical/page → 中医处方")
# ======================== 10. 急诊管理测试 ========================
def test_emergency(tokens):
print("\n" + "="*60)
print("📋 模块十: 急诊管理")
print("="*60)
jzys_token = tokens.get("jzys")
jzhs_token = tokens.get("jzhs")
if not all([jzys_token, jzhs_token]):
print(" ⚠️ 跳过: 急诊角色未登录")
return
# TC-EM-001: 急诊分诊
result = api("GET", "/emergency/triage/page", token=jzys_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-EM-001", "急诊分诊列表", result["success"],
f"分诊: {result['data'].get('total', 0) if result['data'] else 0}",
"/emergency/triage/page → 急诊分诊")
# TC-EM-002: 分诊叫号
result = api("GET", "/triage/queue/list", token=jzhs_token)
record("TC-EM-002", "分诊叫号队列", result["success"],
"叫号队列", "/triage/queue/list → 叫号队列")
# TC-EM-003: 急诊医生站
result = api("GET", "/emergency/page", token=jzys_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-EM-003", "急诊患者列表", result["success"],
f"急诊患者: {result['data'].get('total', 0) if result['data'] else 0}",
"/emergency/page → 急诊患者")
# TC-EM-004: 急诊护士站
result = api("GET", "/emergency/nurse/page", token=jzhs_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-EM-004", "急诊护理列表", result["success"],
f"急诊护理: {result['data'].get('total', 0) if result['data'] else 0}",
"/emergency/nurse/page → 急诊护理")
# ======================== 11. 会诊管理测试 ========================
def test_consultation(tokens):
print("\n" + "="*60)
print("📋 模块十一: 会诊管理")
print("="*60)
doctor_token = tokens.get("doctor")
consultant_token = tokens.get("consultant")
if not all([doctor_token, consultant_token]):
print(" ⚠️ 跳过: 关键角色未登录")
return
# TC-CS-001: 会诊申请
result = api("GET", "/consultation/application/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-CS-001", "会诊申请列表", result["success"],
f"会诊申请: {result['data'].get('total', 0) if result['data'] else 0}",
"/consultation/application/page → 会诊申请")
# TC-CS-002: 会诊确认
result = api("GET", "/consultation/confirmation/page", token=consultant_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-CS-002", "会诊确认列表", result["success"],
f"会诊确认: {result['data'].get('total', 0) if result['data'] else 0}",
"/consultation/confirmation/page → 会诊确认")
# TC-CS-003: 会诊反馈
result = api("GET", "/consultation/feedback/page", token=consultant_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-CS-003", "会诊反馈列表", result["success"],
f"会诊反馈: {result['data'].get('total', 0) if result['data'] else 0}",
"/consultation/feedback/page → 会诊反馈")
# TC-CS-004: 会诊超时提醒
result = api("GET", "/consultation/timeout/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-CS-004", "会诊超时提醒", result["success"],
f"超时: {result['data'].get('total', 0) if result['data'] else 0}",
"/consultation/timeout/page → 会诊超时")
# ======================== 12. 病案管理测试 ========================
def test_medical_record(tokens):
print("\n" + "="*60)
print("📋 模块十二: 病案管理")
print("="*60)
admin_token = tokens.get("admin")
if not admin_token:
print(" ⚠️ 跳过: 管理员未登录")
return
# TC-MR-001: 病案首页
result = api("GET", "/api/v1/mr-homepage/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-MR-001", "病案首页列表", result["success"],
f"病案: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/mr-homepage/page → 病案首页")
# TC-MR-002: DRG分析
result = api("GET", "/drg-analysis/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-MR-002", "DRG分析列表", result["success"],
f"DRG: {result['data'].get('total', 0) if result['data'] else 0}",
"/drg-analysis/page → DRG分析")
# TC-MR-003: 病案归档
result = api("GET", "/emr-archive/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-MR-003", "病案归档列表", result["success"],
f"归档: {result['data'].get('total', 0) if result['data'] else 0}",
"/emr-archive/page → 病案归档")
# TC-MR-004: 病案质控
result = api("GET", "/api/v1/emr-quality/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-MR-004", "病案质控列表", result["success"],
f"质控: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/emr-quality/page → 病案质控")
# ======================== 13. 经营分析测试 ========================
def test_analytics(tokens):
print("\n" + "="*60)
print("📋 模块十三: 经营分析")
print("="*60)
admin_token = tokens.get("admin")
if not admin_token:
print(" ⚠️ 跳过: 管理员未登录")
return
# TC-AN-001: 经营分析
result = api("GET", "/business-analytics/overview", token=admin_token)
record("TC-AN-001", "经营分析概览", result["success"],
"经营数据", "/business-analytics/overview → 经营概览")
# TC-AN-002: 药品库存预警
result = api("GET", "/pharmacy-stock-alert/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-AN-002", "药品库存预警", result["success"],
f"预警: {result['data'].get('total', 0) if result['data'] else 0}",
"/pharmacy-stock-alert/page → 库存预警")
# TC-AN-003: 药品效期管理
result = api("GET", "/drug-expiry/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-AN-003", "药品效期管理", result["success"],
f"效期: {result['data'].get('total', 0) if result['data'] else 0}",
"/drug-expiry/page → 效期管理")
# TC-AN-004: DRG绩效
result = api("GET", "/drg-analysis/performance", token=admin_token)
record("TC-AN-004", "DRG绩效分析", result["success"],
"绩效数据", "/drg-analysis/performance → DRG绩效")
# TC-AN-005: 科室收入统计
result = api("GET", "/report-manage/department-revenue-statistics", token=admin_token)
record("TC-AN-005", "科室收入统计", result["success"],
"收入数据", "/report-manage/department-revenue-statistics → 收入统计")
# TC-AN-006: 门诊收入
result = api("GET", "/report-manage/charge/init", token=admin_token)
record("TC-AN-006", "门诊收费报表", result["success"],
"报表数据", "/report-manage/charge/init → 门诊收费报表")
# TC-AN-007: 挂号统计
result = api("GET", "/report-manage/register/init", token=admin_token)
record("TC-AN-007", "挂号统计报表", result["success"],
"统计数据", "/report-manage/register/init → 挂号统计")
# ======================== 14. 权限隔离测试 ========================
def test_permission_isolation(tokens):
print("\n" + "="*60)
print("📋 模块十四: 权限隔离验证")
print("="*60)
# 不同角色应该不能访问管理功能
test_cases = [
# (角色key, 应该无权访问的路径, 描述)
("doctor", "/system/user/list", "医生→用户管理(应拒)"),
("doctor", "/system/role/list", "医生→角色管理(应拒)"),
("nurse", "/system/config/list", "护士→系统配置(应拒)"),
("pharmacist", "/system/user/list", "药师→用户管理(应拒)"),
("finance", "/system/role/list", "收费员→角色管理(应拒)"),
]
for i, (user_key, path, desc) in enumerate(test_cases):
token = tokens.get(user_key)
if not token:
record(f"TC-PERM-{i+1:03d}", f"{desc}(未登录)", False, "跳过")
continue
result = api("GET", path, token=token, expected_code=200)
# 如果返回200说明没有权限隔离这是一个已知问题
if result["success"]:
record(f"TC-PERM-{i+1:03d}", f"{desc}", False,
f"⚠️ 返回200 - 权限未隔离", f"{user_key}{path} → 200(应403)")
else:
record(f"TC-PERM-{i+1:03d}", f"{desc}", True,
f"已隔离(code={result['code']})", f"{user_key}{path}{result['code']}")
# ======================== 15. 跨模块数据一致性测试 ========================
def test_cross_module(tokens):
print("\n" + "="*60)
print("📋 模块十五: 跨模块数据一致性")
print("="*60)
admin_token = tokens.get("admin")
if not admin_token:
print(" ⚠️ 跳过: 管理员未登录")
return
# TC-XMOD-001: 门诊→住院数据联动
result = api("GET", "/cross-module/patient-transfer", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-XMOD-001", "门诊→住院数据联动", result["success"],
"数据联动", "/cross-module/patient-transfer → 门诊转住院")
# TC-XMOD-002: 医嘱→药房联动
result = api("GET", "/cross-module/advice-drug-link", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-XMOD-002", "医嘱→药房联动", result["success"],
"医嘱药品联动", "/cross-module/advice-drug-link → 医嘱药品")
# TC-XMOD-003: 检查→报告联动
result = api("GET", "/cross-module/exam-report-link", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-XMOD-003", "检查→报告联动", result["success"],
"检查报告联动", "/cross-module/exam-report-link → 检查报告")
# TC-XMOD-004: 收费→医保联动
result = api("GET", "/cross-module/charge-yb-link", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-XMOD-004", "收费→医保联动", result["success"],
"收费医保联动", "/cross-module/charge-yb-link → 收费医保")
# TC-XMOD-005: 护理→医嘱联动
result = api("GET", "/cross-module/nursing-advice-link", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-XMOD-005", "护理→医嘱联动", result["success"],
"护理医嘱联动", "/cross-module/nursing-advice-link → 护理医嘱")
# TC-XMOD-006: 手术→麻醉联动
result = api("GET", "/cross-module/surgery-anesthesia-link", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-XMOD-006", "手术→麻醉联动", result["success"],
"手术麻醉联动", "/cross-module/surgery-anesthesia-link → 手术麻醉")
# ======================== 16. 银行卡/三part支付测试 ========================
def test_payment(tokens):
print("\n" + "="*60)
print("📋 模块十六: 支付与结算")
print("="*60)
finance_token = tokens.get("finance")
if not finance_token:
print(" ⚠️ 跳过: 收费员未登录")
return
# TC-PAY-001: 患者建卡
result = api("GET", "/charge/patientCardRenewal/init", token=finance_token)
record("TC-PAY-001", "患者建卡初始化", result["success"],
"建卡数据", "/charge/patientCardRenewal/init → 建卡初始化")
# TC-PAY-002: 三part支付
result = api("GET", "/three-part/pay/page", token=finance_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-PAY-002", "三方支付列表", result["success"],
f"支付: {result['data'].get('total', 0) if result['data'] else 0}",
"/three-part/pay/page → 三方支付")
# TC-PAY-003: 预交金管理
result = api("GET", "/inhospital-charge/advance-payment/page", token=finance_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-PAY-003", "住院预交金列表", result["success"],
f"预交金: {result['data'].get('total', 0) if result['data'] else 0}",
"/inhospital-charge/advance-payment/page → 预交金")
# TC-PAY-004: 医保目录
result = api("GET", "/yb-management/catalog/page", token=finance_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-PAY-004", "医保目录管理", result["success"],
f"医保目录: {result['data'].get('total', 0) if result['data'] else 0}",
"/yb-management/catalog/page → 医保目录")
# ======================== 17. 传染病直报测试 ========================
def test_epidemic(tokens):
print("\n" + "="*60)
print("📋 模块十七: 传染病直报")
print("="*60)
nurse_token = tokens.get("nkhs")
if not nurse_token:
print(" ⚠️ 跳过: 护士未登录")
return
# TC-EPI-001: 传染病报告列表
result = api("GET", "/api/v1/epidemic/page", token=nurse_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-EPI-001", "传染病报告列表", result["success"],
f"报告: {result['data'].get('total', 0) if result['data'] else 0}",
"/api/v1/epidemic/page → 传染病报告")
# TC-EPI-002: 传染病统计
result = api("GET", "/api/v1/epidemic/statistics", token=nurse_token)
record("TC-EPI-002", "传染病统计", result["success"],
"统计数据", "/api/v1/epidemic/statistics → 传染病统计")
# ======================== 18. 电子病历测试 ========================
def test_emr(tokens):
print("\n" + "="*60)
print("📋 模块十八: 电子病历(EMR)")
print("="*60)
doctor_token = tokens.get("doctor")
admin_token = tokens.get("admin")
if not doctor_token:
print(" ⚠️ 跳过: 医生未登录")
return
# TC-EMR-001: 病历列表
result = api("GET", "/doctor-station/emr/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-EMR-001", "电子病历列表", result["success"],
f"病历: {result['data'].get('total', 0) if result['data'] else 0}",
"/doctor-station/emr/page → 病历列表")
# TC-EMR-002: 病历模板
result = api("GET", "/doctor-station/emr/template-page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-EMR-002", "病历模板列表", result["success"],
f"模板: {result['data'].get('total', 0) if result['data'] else 0}",
"/doctor-station/emr/template-page → 病历模板")
# TC-EMR-003: CDA文档
if admin_token:
result = api("GET", "/fhir-cda/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-EMR-003", "CDA文档列表", result["success"],
f"CDA: {result['data'].get('total', 0) if result['data'] else 0}",
"/fhir-cda/page → CDA文档")
# TC-EMR-004: 知情同意
result = api("GET", "/informed-consent/page", token=doctor_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-EMR-004", "知情同意列表", result["success"],
f"同意书: {result['data'].get('total', 0) if result['data'] else 0}",
"/informed-consent/page → 知情同意")
# ======================== 19. 基础数据管理测试 ========================
def test_base_data(tokens):
print("\n" + "="*60)
print("📋 模块十九: 基础数据管理")
print("="*60)
admin_token = tokens.get("admin")
if not admin_token:
print(" ⚠️ 跳过: 管理员未登录")
return
# TC-BD-001: 组织管理
result = api("GET", "/base-data-manage/organization/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-BD-001", "组织管理", result["success"],
f"组织: {result['data'].get('total', 0) if result['data'] else 0}",
"/base-data-manage/organization/page → 组织列表")
# TC-BD-002: 科室管理
result = api("GET", "/base-data-manage/location/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-BD-002", "科室管理", result["success"],
f"科室: {result['data'].get('total', 0) if result['data'] else 0}",
"/base-data-manage/location/page → 科室列表")
# TC-BD-003: 人员管理
result = api("GET", "/base-data-manage/practitioner/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-BD-003", "人员管理", result["success"],
f"人员: {result['data'].get('total', 0) if result['data'] else 0}",
"/base-data-manage/practitioner/page → 人员列表")
# TC-BD-004: ICD10编码
result = api("GET", "/icd10/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-BD-004", "ICD10编码管理", result["success"],
f"ICD10: {result['data'].get('total', 0) if result['data'] else 0}",
"/icd10/page → ICD10列表")
# TC-BD-005: 数据字典管理
result = api("GET", "/dict-dictionary/definition/page", token=admin_token,
params={"pageNum": 1, "pageSize": 10})
record("TC-BD-005", "数据字典管理", result["success"],
f"字典: {result['data'].get('total', 0) if result['data'] else 0}",
"/dict-dictionary/definition/page → 字典列表")
# ======================== 20. 报表管理测试 ========================
def test_reports(tokens):
print("\n" + "="*60)
print("📋 模块二十: 报表管理")
print("="*60)
admin_token = tokens.get("admin")
if not admin_token:
print(" ⚠️ 跳过: 管理员未登录")
return
report_endpoints = [
("/report-manage/report/statistics", "报表统计"),
("/report-manage/report/init", "报表首页"),
("/report-manage/report-statistics/page", "报表统计列表"),
]
for i, (path, name) in enumerate(report_endpoints):
result = api("GET", path, token=admin_token, params={"pageNum": 1, "pageSize": 10})
record(f"TC-RPT-{i+1:03d}", name, result["success"],
f"数据: {'' if result['data'] else ''}",
f"{path}{name}")
# ======================== 主函数 ========================
def main():
global PASSED, FAILED
print("=" * 70)
print("🏥 HealthLink-HIS 三甲医院复杂业务逻辑全流程测试")
print(f"📅 测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"🌐 测试环境: {BASE_URL}")
print("=" * 70)
# 1. 登录认证
tokens = test_auth()
# 2. 系统管理
test_system(tokens)
# 3. 门诊全流程
test_outpatient(tokens)
# 4. 住院全流程
test_inpatient(tokens)
# 5. 手术全流程
test_surgery(tokens)
# 6. 医技检查
test_inspection(tokens)
# 7. 院感管理
test_infection(tokens)
# 8. 质量管理
test_quality(tokens)
# 9. 中医管理
test_tcm(tokens)
# 10. 急诊管理
test_emergency(tokens)
# 11. 会诊管理
test_consultation(tokens)
# 12. 病案管理
test_medical_record(tokens)
# 13. 经营分析
test_analytics(tokens)
# 14. 权限隔离
test_permission_isolation(tokens)
# 15. 跨模块数据一致性
test_cross_module(tokens)
# 16. 支付与结算
test_payment(tokens)
# 17. 传染病直报
test_epidemic(tokens)
# 18. 电子病历
test_emr(tokens)
# 19. 基础数据管理
test_base_data(tokens)
# 20. 报表管理
test_reports(tokens)
# 汇总
total = PASSED + FAILED
pass_rate = (PASSED / total * 100) if total > 0 else 0
print("\n" + "=" * 70)
print("📊 测试结果汇总")
print("=" * 70)
print(f" 总用例数: {total}")
print(f" 通过: ✅ {PASSED}")
print(f" 失败: ❌ {FAILED}")
print(f" 通过率: {pass_rate:.1f}%")
print()
if FAILED > 0:
print("❌ 失败用例:")
for r in RESULTS:
if not r["passed"]:
print(f" - [{r['id']}] {r['name']}: {r['details']}")
# 输出JSON报告
report = {
"test_time": datetime.now().isoformat(),
"environment": BASE_URL,
"total": total,
"passed": PASSED,
"failed": FAILED,
"pass_rate": f"{pass_rate:.1f}%",
"results": RESULTS,
}
report_path = "/root/.openclaw/workspace/his-repo/MD/test/reports/06_business_logic_complex_report.json"
import os
os.makedirs(os.path.dirname(report_path), exist_ok=True)
with open(report_path, "w", encoding="utf-8") as f:
json.dump(report, f, ensure_ascii=False, indent=2)
print(f"\n📄 报告已保存: {report_path}")
return 0 if FAILED == 0 else 1
if __name__ == "__main__":
sys.exit(main())