根因分析: - 后端菜单配置存在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通过
1264 lines
55 KiB
Python
1264 lines
55 KiB
Python
#!/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())
|