Files
basicBench/010/all.html
2026-03-22 00:43:56 +08:00

1019 lines
48 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>City General Hospital - HIS System V2.0</title>
<style>
/* === CSS Variables & Reset === */
:root {
--primary: #007bff; /* Medical Blue */
--secondary: #6c757d;
--success: #28a745;
--danger: #dc3545;
--warning: #ffc107;
--info: #17a2b8;
--light: #f8f9fa;
--dark: #343a40;
--border-color: #dee2e6;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: #f4f6f9;
color: #212529;
margin: 0;
font-size: 14px;
line-height: 1.5;
}
a { text-decoration: none; color: var(--primary); }
a:hover { text-decoration: underline; }
/* === Layout Refactor: Override Table Styles === */
table, tbody, tr, td { display: block; width: 100% !important; border: none !important; background: transparent !important; padding: 0 !important; }
/* Top Broadcast - Notification Bar */
body > table:first-of-type {
background: #fff3cd !important; color: #856404; padding: 10px 20px !important; border-bottom: 1px solid #ffeeba !important;
}
body > table:first-of-type font { color: #856404 !important; font-weight: bold; }
body > table:first-of-type font[size="2"] { font-size: 12px; font-weight: normal; margin-left: 10px; }
/* Header Area */
body > table:nth-of-type(2) { background: white !important; padding: 10px 20px !important; border-bottom: 1px solid var(--border-color) !important; box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
body > table:nth-of-type(2) tr { display: flex; justify-content: space-between; align-items: center; }
body > table:nth-of-type(2) td { width: auto !important; }
body > table:nth-of-type(2) font[size="5"] b { font-size: 20px; color: var(--primary); }
body > table:nth-of-type(2) td:last-child font { color: #666 !important; font-size: 13px; }
body > table:nth-of-type(2) a { color: var(--secondary) !important; margin-left: 10px; font-size: 12px; }
/* Nav Menu */
body > table:nth-of-type(3) { background: #343a40 !important; padding: 0 !important; }
body > table:nth-of-type(3) td { display: flex; gap: 0; padding: 0 !important; }
/* Nav Item Logic */
.nav-item {
color: rgba(255,255,255,0.7) !important; padding: 12px 20px;
border-right: 1px solid rgba(255,255,255,0.1); cursor: pointer;
}
.nav-item:hover { background: rgba(255,255,255,0.1); color: white !important; text-decoration: none; }
/* Active State */
.nav-item.active { background: var(--primary) !important; color: white !important; font-weight: bold; }
/* === 3-Column Grid Layout === */
.layout-table > tbody > tr {
display: grid; grid-template-columns: 240px 1fr 240px; gap: 20px; padding: 20px; max-width: 1600px; margin: 0 auto; align-items: start;
}
/* Left: Patient List */
.layout-table > tbody > tr > td:first-child {
background: white !important; border-radius: 4px; border: 1px solid var(--border-color) !important; overflow: hidden;
}
/* List Header */
.layout-table > tbody > tr > td:first-child table tr:first-child td {
background: #f8f9fa !important; padding: 10px 15px !important; border-bottom: 1px solid var(--border-color) !important;
}
.layout-table > tbody > tr > td:first-child table tr:first-child font { color: #333 !important; font-weight: bold; }
/* List Item */
.layout-table > tbody > tr > td:first-child table tr:not(:first-child) td {
padding: 15px !important; border-bottom: 1px solid #eee !important; cursor: pointer; transition: background 0.2s;
}
.layout-table > tbody > tr > td:first-child table tr:not(:first-child) td:hover { background: #f1f7ff !important; }
/* VIP Style */
.layout-table > tbody > tr > td:first-child table tr[bgcolor="#ffffcc"] td {
background: #fffbe6 !important; border-left: 3px solid var(--warning) !important;
}
/* Hide Ads */
.layout-table > tbody > tr > td:first-child table[bgcolor="#e0ffff"],
.layout-table > tbody > tr > td:first-child table[bgcolor="#ffe4e1"] { display: none !important; }
/* Center: Workspace */
.layout-table > tbody > tr > td:nth-child(2) {
background: transparent !important;
}
/* Patient Info Card */
.layout-table > tbody > tr > td:nth-child(2) > table:first-child {
background: white !important; padding: 20px !important; border-radius: 4px; border: 1px solid var(--border-color) !important; margin-bottom: 20px;
display: grid !important; grid-template-columns: 1fr 1fr; gap: 10px;
}
/* Title spans full width */
.layout-table > tbody > tr > td:nth-child(2) > table:first-child tr:first-child {
grid-column: 1 / -1; background: transparent !important; border-bottom: 1px solid #eee !important; padding-bottom: 10px !important; margin-bottom: 10px; font-size: 16px;
}
/* Info rows grid */
.layout-table > tbody > tr > td:nth-child(2) > table:first-child tr:not(:first-child) {
display: flex; gap: 10px; align-items: baseline;
}
/* Order Form */
.layout-table > tbody > tr > td:nth-child(2) form table {
background: white !important; border-radius: 4px; border: 1px solid var(--border-color) !important; overflow: hidden;
}
/* Form Header */
.layout-table > tbody > tr > td:nth-child(2) form table tr:first-child {
background: #f8f9fa !important; padding: 10px 15px !important; border-bottom: 1px solid var(--border-color) !important;
}
.layout-table > tbody > tr > td:nth-child(2) form table tr:nth-child(2) {
display: grid; grid-template-columns: 40px 1.5fr 1fr 2fr 80px; background: #fafafa; border-bottom: 1px solid var(--border-color); padding: 10px !important; font-weight: bold; font-size: 12px; color: #666;
}
/* Drug Row */
.layout-table > tbody > tr > td:nth-child(2) form table tr:not(:first-child):not(:nth-child(2)):not(:last-child) {
display: grid; grid-template-columns: 40px 1.5fr 1fr 2fr 80px; padding: 10px !important; border-bottom: 1px solid #eee; align-items: center;
}
/* Hide distraction rows */
.layout-table > tbody > tr > td:nth-child(2) form table tr[bgcolor="#ffebcd"] { display: none !important; }
/* Footer Buttons */
.layout-table > tbody > tr > td:nth-child(2) form table tr:last-child td {
padding: 15px !important; display: flex; gap: 10px; justify-content: flex-end; background: #f8f9fa !important;
}
/* Toast Styles */
.toast {
position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%);
background: #333; color: white; padding: 12px 24px; border-radius: 4px;
z-index: 2000; opacity: 0; transition: opacity 0.3s; pointer-events: none;
}
.toast.show { opacity: 1; }
/* Lab Reports */
.layout-table > tbody > tr > td:nth-child(2) > table:last-of-type {
background: white !important; margin-top: 20px; border: 1px solid var(--border-color) !important; border-radius: 4px; padding: 15px !important;
}
/* Hide upgrade notice */
.layout-table > tbody > tr > td:nth-child(2) > div { display: none !important; }
/* Right: Utilities */
.layout-table > tbody > tr > td:last-child {
background: white !important; padding: 20px !important; border-radius: 4px; border: 1px solid var(--border-color) !important;
}
/* Right Panel Headers */
.layout-table > tbody > tr > td:last-child table tr:first-child td {
background: transparent !important; color: #333 !important; font-weight: bold; border-bottom: 2px solid var(--primary) !important; padding-bottom: 5px !important; margin-bottom: 10px;
}
.layout-table > tbody > tr > td:last-child table tr:first-child font { color: #333 !important; }
/* Checkbox Spacing */
.layout-table > tbody > tr > td:last-child table tr:not(:first-child) td { padding: 5px 0 !important; }
/* Hide legacy links */
.layout-table > tbody > tr > td:last-child > p { display: none; }
.layout-table > tbody > tr > td:last-child > ul { display: none; }
/* Footer */
center:last-of-type {
margin-top: 40px; border-top: 1px solid var(--border-color); padding: 20px; color: #999; font-size: 12px;
}
hr { display: none; }
/* === Enhanced Dynamic Styles === */
.patient-row { cursor: pointer; transition: 0.2s; }
.patient-row:hover { background-color: #f1f7ff; }
.patient-row.active { background-color: #e3f2fd !important; border-left: 4px solid var(--primary) !important; }
.status-badge { padding: 2px 6px; border-radius: 4px; font-size: 11px; color: white; display:inline-block; margin-left:5px; }
.badge-signed { background-color: var(--success); }
.badge-draft { background-color: var(--secondary); }
.badge-vip { background-color: var(--warning); color: #856404; }
/* Modal Styles */
.modal-overlay {
position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000;
display: flex; justify-content: center; align-items: center; opacity: 0; pointer-events: none; transition: 0.2s;
}
.modal-overlay.show { opacity: 1; pointer-events: auto; }
.modal-box {
background: white; padding: 20px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2); width: 450px;
transform: translateY(-20px); transition: 0.3s;
}
.modal-overlay.show .modal-box { transform: translateY(0); }
.form-group { margin-bottom: 15px; }
.form-group label { display: block; margin-bottom: 5px; font-weight: bold; color: #333; }
.form-group input, .form-group select { width: 100%; padding: 8px; box-sizing: border-box; border: 1px solid #ccc; border-radius: 4px; font-size:14px; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border-width: 0; }
</style>
</head>
<body bgcolor="#e6e6e6" text="#000000" link="#000080" vlink="#800080" alink="#FF0000">
<!-- Add Drug Modal -->
<div id="drug-modal" class="modal-overlay" role="dialog" aria-modal="true" aria-labelledby="drug-modal-title">
<div class="modal-box">
<h3 id="drug-modal-title" style="margin-top:0; color:var(--primary); border-bottom:1px solid #eee; padding-bottom:10px;">New Order</h3>
<div class="form-group">
<label for="modal-drug-name">Drug Name</label>
<select id="modal-drug-name" onchange="updateDrugSpecs()" aria-label="Select drug name">
<option value="">-- Select --</option>
<option value="Aspirin">Aspirin Enteric-coated Tablets</option>
<option value="Atorvastatin">Atorvastatin Calcium Tablets</option>
<option value="Metoprolol">Metoprolol Succinate</option>
<option value="Cefradine">Cefradine Capsules</option>
<option value="Ibuprofen">Ibuprofen Sustained Release</option>
<option value="Insulin">Human Insulin Injection</option>
<option value="Omeprazole">Omeprazole Capsules</option>
<option value="Metformin">Metformin Hydrochloride</option>
</select>
</div>
<div class="form-group">
<label for="modal-drug-spec">Spec & Package</label>
<input type="text" id="modal-drug-spec" readonly style="background:#f5f5f5; color:#666;" aria-label="Drug specification">
</div>
<div class="form-group">
<label for="modal-drug-dose">Dosage</label>
<div style="display:flex; gap:10px;">
<input type="text" id="modal-drug-dose" placeholder="Dose (e.g. 100mg)" aria-label="Drug dosage">
<select id="modal-drug-freq" style="width:140px;" aria-label="Frequency">
<option value="qd">qd (once daily)</option>
<option value="bid">bid (twice daily)</option>
<option value="tid">tid (3 times daily)</option>
<option value="qid">qid (4 times daily)</option>
<option value="qn">qn (once nightly)</option>
<option value="prn">prn (as needed)</option>
</select>
</div>
</div>
<div class="form-group">
<label for="modal-drug-route">Route</label>
<select id="modal-drug-route" aria-label="Administration route">
<option value="PO">PO (Oral)</option>
<option value="IV">IV (Intravenous)</option>
<option value="IH">IH (Hypodermic)</option>
<option value="Inhale">Inhale (Inhalation)</option>
</select>
</div>
<div style="text-align:right; margin-top:20px; padding-top:10px; border-top:1px solid #eee;">
<button type="button" onclick="closeModal()" style="padding:8px 15px; margin-right:10px; background:white; border:1px solid #ccc; border-radius:4px; cursor:pointer;" aria-label="Cancel">Cancel</button>
<button type="button" onclick="confirmAddDrug()" style="padding:8px 15px; background:var(--primary); color:white; border:none; border-radius:4px; cursor:pointer;" aria-label="Confirm add drug">Confirm</button>
</div>
</div>
</div>
<!-- Confirmation Modal -->
<div id="confirm-modal" class="modal-overlay" role="dialog" aria-modal="true" aria-labelledby="confirm-title">
<div class="modal-box" style="width:400px;">
<h3 id="confirm-title" style="margin-top:0; color:var(--primary); border-bottom:1px solid #eee; padding-bottom:10px;">Confirm Action</h3>
<div id="confirm-message" style="padding:15px 0; color:#333; line-height:1.6;"></div>
<div style="text-align:right; margin-top:20px; padding-top:10px; border-top:1px solid #eee;">
<button type="button" onclick="closeConfirmModal()" style="padding:8px 15px; margin-right:10px; background:white; border:1px solid #ccc; border-radius:4px; cursor:pointer;" aria-label="Cancel">Cancel</button>
<button type="button" id="confirm-btn" onclick="executeConfirm()" style="padding:8px 15px; background:var(--danger); color:white; border:none; border-radius:4px; cursor:pointer;" aria-label="Confirm">Confirm</button>
</div>
</div>
</div>
<!-- Input Modal -->
<div id="input-modal" class="modal-overlay" role="dialog" aria-modal="true" aria-labelledby="input-title">
<div class="modal-box" style="width:400px;">
<h3 id="input-title" style="margin-top:0; color:var(--primary); border-bottom:1px solid #eee; padding-bottom:10px;">Enter Information</h3>
<div id="input-message" style="padding:10px 0; color:#333; font-size:13px;"></div>
<input type="text" id="input-field" style="width:100%; padding:8px; border:1px solid #ccc; border-radius:4px; margin:15px 0; box-sizing:border-box;" aria-label="Input field">
<div style="text-align:right; margin-top:20px; padding-top:10px; border-top:1px solid #eee;">
<button type="button" onclick="closeInputModal()" style="padding:8px 15px; margin-right:10px; background:white; border:1px solid #ccc; border-radius:4px; cursor:pointer;" aria-label="Cancel">Cancel</button>
<button type="button" id="input-btn" onclick="executeInput()" style="padding:8px 15px; background:var(--primary); color:white; border:none; border-radius:4px; cursor:pointer;" aria-label="Submit">Submit</button>
</div>
</div>
</div>
<div id="toast-container"></div>
<table width="100%" border="1" bgcolor="#ffcccc" cellpadding="5" role="region" aria-label="System broadcast">
<tr>
<td align="center">
<span style="color:red;"><strong>Broadcast:</strong> Attention all departments, emergency meeting on insurance cost control at 3 PM in the Admin Building.</span>
<br>
<span style="font-size:12px;">Posted: 2025-12-22 08:30</span>
</td>
</tr>
</table>
<br>
<table width="100%" border="0" bgcolor="#008080" cellpadding="10" role="banner">
<tr>
<td width="50%">
<h1 style="color:white; font-size:20px; margin:0;"><strong>City General Hospital - Doctor Station</strong></h1>
</td>
<td width="50%" align="right">
<span style="color:white;">
User: <strong>Dr. Li (Attending)</strong> | Dept: Cardiology<br>
<button onclick="modifyPassword()" style="background:none; border:none; color:yellow; cursor:pointer; text-decoration:underline;" aria-label="Change password">[Change Pwd]</button>
<button onclick="logout()" style="background:none; border:none; color:white; cursor:pointer; text-decoration:underline;" aria-label="Logout">[Logout]</button>
</span>
</td>
</tr>
</table>
<table width="100%" border="1" cellpadding="0" cellspacing="0" bgcolor="#343a40" role="navigation" aria-label="Module navigation">
<tr>
<td style="display:flex; padding:0;">
<button id="nav-btn-clinic" class="nav-item active" onclick="switchModule(this, 'clinic')" role="menuitem" aria-current="page" aria-label="Outpatient module">Outpatient</button>
<button id="nav-btn-inpatient" class="nav-item" onclick="switchModule(this, 'inpatient')" role="menuitem" aria-label="Inpatient module">Inpatient</button>
<button id="nav-btn-surgery" class="nav-item" onclick="switchModule(this, 'surgery')" role="menuitem" aria-label="Surgery module">Surgery</button>
<button id="nav-btn-lab" class="nav-item" onclick="switchModule(this, 'lab')" role="menuitem" aria-label="Lab results module">Lab Results</button>
<button id="nav-btn-pharmacy" class="nav-item" onclick="switchModule(this, 'pharmacy')" role="menuitem" aria-label="Pharmacy module">Pharmacy</button>
<button id="nav-btn-admin" class="nav-item" onclick="switchModule(this, 'admin')" role="menuitem" aria-label="Order admin module">Order Admin</button>
</td>
</tr>
</table>
<br>
<!-- Module: Clinic (Doctor Station) -->
<div id="module-clinic" class="main-module">
<table class="layout-table" width="100%" border="0" cellspacing="5" cellpadding="0">
<tr>
<td width="250" valign="top" bgcolor="#f0f0f0" style="height: 100%;">
<br>
<table width="100%" border="1" cellpadding="0" style="background:white; border-radius:4px; overflow:hidden; border-collapse:collapse;">
<tr><td bgcolor="#008080" style="padding:10px;"><font color="white"><b>Waiting List (<span id="patient-count">0</span>)</b></font></td></tr>
<tbody id="patient-list-container">
<!-- Dynamic Content -->
</tbody>
</table>
<div style="margin-top:20px; padding:15px; background:#fff3cd; border:1px solid #ffeeba; border-radius:4px; color:#856404; font-size:12px;">
<b>Shift Note:</b><br>
Emergency observation beds are full, please coordinate transfers.
</div>
</td>
<td valign="top">
<!-- Patient Info Header -->
<table width="100%" border="1" cellpadding="5" bgcolor="#ffffff" id="patient-info-card" style="margin-bottom:20px;">
<tr><td align="center" style="padding:40px; color:#999;">Loading patient info...</td></tr>
</table>
<!-- Order Entry Form -->
<div id="order-panel" style="display:none;">
<form onsubmit="event.preventDefault();">
<table width="100%" border="1" cellpadding="3" cellspacing="0">
<tr>
<td colspan="6" bgcolor="#dddddd" style="display:flex; justify-content:space-between; align-items:center;">
<b>Long-term Order Entry</b>
<span style="font-size:12px; color:#666;">Last refresh: <span id="last-sync-time">Just now</span></span>
</td>
</tr>
<thead style="background:#fafafa; color:#666; font-size:12px; font-weight:bold;">
<tr style="display:grid; grid-template-columns: 40px 1.5fr 1fr 2fr 100px 80px; padding:10px; border-bottom:1px solid #eee;">
<td>Sel</td>
<td>Drug Name</td>
<td>Spec</td>
<td>Dosage</td>
<td>Status</td>
<td>Action</td>
</tr>
</thead>
<tbody id="order-list-body">
<!-- Dynamic Orders -->
</tbody>
<tr>
<td colspan="6" align="right" style="padding:15px; border-top:1px solid #eee; background:#f8f9fa;">
<button type="button" onclick="openAddDrugModal()" style="padding:8px 16px; background:white; border:1px solid #ced4da; color:var(--primary); border-radius:4px; cursor:pointer; font-weight:500;">+ Add Drug</button>
<button type="button" onclick="signOrder()" style="padding:8px 16px; background:var(--primary); color:white; border:none; border-radius:4px; cursor:pointer; margin-left:10px; font-weight:500;">Sign Orders</button>
<button type="button" onclick="voidOrder()" style="padding:8px 16px; background:var(--danger); color:white; border:none; border-radius:4px; cursor:pointer; margin-left:5px; font-weight:500;">Void Item</button>
</td>
</tr>
</table>
</form>
</div>
<br>
<!-- Labs -->
<table width="100%" border="1" cellpadding="3" id="lab-panel" style="display:none; background:white; border-radius:4px;">
<tr><td bgcolor="#dddddd"><b>Lab / Exam Reports</b></td></tr>
<tr>
<td>
<ul style="padding-left:20px; margin:10px 0;" id="lab-list">
<!-- Dynamic Labs -->
</ul>
</td>
</tr>
</table>
</td>
<td width="200" valign="top" bgcolor="#f0f0f0">
<br>
<table width="100%" border="1" cellpadding="3">
<tr><td bgcolor="#008080"><font color="white"><b>Clinical Pathway</b></font></td></tr>
<tbody id="clinical-path-list">
<!-- Dynamic -->
</tbody>
</table>
<br>
<table width="100%" border="1" cellpadding="3">
<tr><td bgcolor="#008080"><font color="white"><b>Shift Roster</b></font></td></tr>
<tr><td>Mon: Dr. Zhang (Day)</td></tr>
<tr><td>Mon: Dr. Wang (Night)</td></tr>
<tr><td>Tue: Dr. Li (Day)</td></tr>
<tr><td>Tue: Dr. Zhao (Night)</td></tr>
</table>
<br>
<p><b>Quick Links:</b></p>
<ul>
<li><a href="javascript:void(0)" onclick="openOA()">OA System</a></li>
<li><a href="javascript:void(0)" onclick="openLibrary()">Medical Library</a></li>
</ul>
</td>
</tr>
</table>
</div>
<!-- Module: Inpatient -->
<div id="module-inpatient" class="main-module" style="display:none; padding:20px;">
<div style="background:white; padding:30px; border-radius:8px; text-align:center; border:1px solid #ddd;">
<h2 style="color:#007bff;">Inpatient Bed Management</h2>
<p style="color:#666;">Free Beds: 12 | ICU: Full</p>
<div style="margin-top:20px; display:grid; grid-template-columns:repeat(auto-fill, minmax(100px, 1fr)); gap:10px;">
<div style="background:#d4edda; padding:10px; border-radius:4px; color:#155724;">Bed 01 (Free)</div>
<div style="background:#f8d7da; padding:10px; border-radius:4px; color:#721c24;">Bed 02 (Occupied)</div>
<div style="background:#f8d7da; padding:10px; border-radius:4px; color:#721c24;">Bed 03 (Occupied)</div>
<div style="background:#d4edda; padding:10px; border-radius:4px; color:#155724;">Bed 04 (Free)</div>
<div style="background:#fff3cd; padding:10px; border-radius:4px; color:#856404;">Bed 05 (Reserved)</div>
</div>
</div>
</div>
<!-- Module: Surgery -->
<div id="module-surgery" class="main-module" style="display:none; padding:20px;">
<div style="background:white; padding:30px; border-radius:8px; border:1px solid #ddd;">
<h2 style="color:#007bff; border-bottom:1px solid #eee; padding-bottom:10px;">Surgery Schedule (2025-12-23)</h2>
<table width="100%" border="0" cellpadding="10">
<tr bgcolor="#f8f9fa" style="font-weight:bold;"><td>Time</td><td>OR</td><td>Patient</td><td>Procedure</td><td>Surgeon</td></tr>
<tr><td>08:00</td><td>OR-01</td><td>Zhang San</td><td>CABG</td><td>Dr. Liu</td></tr>
<tr><td>09:30</td><td>OR-03</td><td>Unknown</td><td>Appendectomy</td><td>Dr. Wang</td></tr>
<tr><td>13:00</td><td>OR-02</td><td>Li Si</td><td>Cataract Phaco</td><td>Dr. Zhang</td></tr>
</table>
</div>
</div>
<!-- Module: Lab -->
<div id="module-lab" class="main-module" style="display:none; padding:20px;">
<div style="background:white; padding:40px; border-radius:8px; text-align:center; border:1px solid #ddd;">
<h2 style="color:#17a2b8;">LIS Report Search</h2>
<input id="lab-search-input" type="text" placeholder="Enter Patient ID/Name..." style="padding:10px; width:300px; border:1px solid #ccc; border-radius:4px;">
<button onclick="searchLabReport()" style="padding:10px 20px; background:#17a2b8; color:white; border:none; border-radius:4px; cursor:pointer;">Search</button>
</div>
</div>
<!-- Module: Pharmacy -->
<div id="module-pharmacy" class="main-module" style="display:none; padding:20px;">
<div style="background:white; padding:30px; border-radius:8px; border:1px solid #ddd;">
<h2 style="color:#28a745;">Pharmacy Stock Alert</h2>
<table width="100%" border="0" cellpadding="8">
<tr style="border-bottom:2px solid #eee;"><td>Drug Name</td><td>Stock</td><td>Status</td><td>Action</td></tr>
<tr><td>Aspirin</td><td>12,000</td><td style="color:green">Sufficient</td><td>-</td></tr>
<tr><td>Insulin Inj</td><td>50</td><td style="color:red; font-weight:bold;">Low Stock</td><td><a id="btn-restock-insulin" href="javascript:void(0)" onclick="restockDrug('Insulin')">Request Restock</a></td></tr>
<tr><td>Cefradine</td><td>340</td><td style="color:orange">Normal</td><td>-</td></tr>
</table>
</div>
</div>
<!-- Module: Admin -->
<div id="module-admin" class="main-module" style="display:none; padding:20px;">
<div style="background:white; padding:30px; border-radius:8px; border:1px solid #ddd;">
<h2 style="color:#6c757d;">System Admin & Order Audit</h2>
<div id="admin-task-area">
<p>You have <b>3</b> orders waiting for approval.</p>
<button onclick="batchApproveOrders()" style="padding:8px 15px; background:#007bff; color:white; border:none; border-radius:4px; cursor:pointer;">Batch Approve</button>
<button onclick="batchRejectOrders()" style="padding:8px 15px; background:#dc3545; color:white; border:none; border-radius:4px; cursor:pointer;">Batch Reject</button>
</div>
</div>
</div>
<hr>
<center>
<font size="1">
Tech Support: Health Info Center | Tel: 8888-1234<br>
Copyright © 2025 City General Hospital
</font>
</center>
<script>
// -------------------------------------------------------------------------
// Mock Data
// -------------------------------------------------------------------------
const DRUG_DICT = {
'Aspirin': { name: 'Aspirin Enteric-coated Tablets', spec: '100mg*30 tabs' },
'Atorvastatin': { name: 'Atorvastatin Calcium Tablets', spec: '20mg*7 tabs' },
'Metoprolol': { name: 'Metoprolol Succinate', spec: '47.5mg*7 tabs' },
'Cefradine': { name: 'Cefradine Capsules', spec: '0.25g*24 caps' },
'Ibuprofen': { name: 'Ibuprofen Sustained Release', spec: '0.3g*10 caps' },
'Insulin': { name: 'Human Insulin Injection', spec: '3ml:300IU' },
'Omeprazole': { name: 'Omeprazole Capsules', spec: '20mg*14 caps' },
'Metformin': { name: 'Metformin Hydrochloride', spec: '0.5g*20 tabs' }
};
let PATIENTS = [
{
id: 101, name: "Zhang San", gender: "M", age: 45, type: "common",
complaint: "Chest tightness for 3 days",
diagnosis: "Coronary Heart Disease; Angina",
tags: ["Chest Pain", "Hypertension"],
allergies: ["Penicillin"],
insurance: "Provincial Insurance",
vitals: { bp: "140/90", hr: 88, t: 36.5 },
orders: [
{ id: 1, drug: "Aspirin", dose: "100mg", freq: "qd", route: "PO", status: "signed" },
{ id: 2, drug: "Atorvastatin", dose: "20mg", freq: "qn", route: "PO", status: "signed" }
],
labs: [
{ date: "2025-12-20", name: "ECG", result: "Sinus rhythm, slight ST depression", link: true},
{ date: "2025-12-20", name: "Echo", result: "Diastolic dysfunction, EF 55%", link: true},
{ date: "2025-12-19", name: "CBC", result: "WBC 6.5, Hb 135, PLT 210", link: false}
],
pathways: [
{ name: "Admission Education", checked: true },
{ name: "Sign Consent Form", checked: true },
{ name: "Physician Ward Round", checked: false },
{ name: "Pre-op Discussion", checked: false }
]
},
{
id: 102, name: "Li Si", gender: "F", age: 62, type: "common",
complaint: "Dizziness and nausea for 1 week",
diagnosis: "Hypertension (Grade 3); Cervical Spondylosis",
tags: ["Dizziness"],
allergies: ["None"],
insurance: "Rural Cooperative Medical Scheme",
vitals: { bp: "160/100", hr: 76, t: 36.8 },
orders: [
{ id: 3, drug: "Metoprolol", dose: "23.75mg", freq: "qd", route: "PO", status: "draft" }
],
labs: [
{ date: "2025-12-21", name: "Head CT", result: "No significant abnormality", link: true},
{ date: "2025-12-21", name: "Biochemistry", result: "TG 2.3mmol/L (High)", link: false}
],
pathways: [
{ name: "Admission Education", checked: true },
{ name: "BP Monitoring (Q4H)", checked: true },
{ name: "Fundus Exam", checked: false }
]
},
{
id: 103, name: "Mr. Wang", gender: "M", age: 50, type: "vip",
complaint: "Consultation on annual checkup report",
diagnosis: "Fatty Liver; Hyperuricemia",
tags: ["VIP", "Checkup"],
allergies: ["Sulfonamides"],
insurance: "Self-pay",
vitals: { bp: "130/85", hr: 80, t: 36.6 },
orders: [], // Empty initially
labs: [
{ date: "2025-12-22", name: "Liver Function", result: "ALT 55, AST 40", link: false},
{ date: "2025-12-22", name: "Abdominal Ultrasound", result: "Moderate fatty liver", link: true}
]
},
{
id: 104, name: "Zhao Liu", gender: "M", age: 28, type: "common",
complaint: "Acute stomach pain for 2 hours",
diagnosis: "Acute Gastritis",
tags: ["Emergency"],
allergies: ["None"],
insurance: "City Insurance",
vitals: { bp: "120/75", hr: 92, t: 37.2 },
orders: [
{ id: 4, drug: "Omeprazole", dose: "20mg", freq: "qd", route: "PO", status: "signed" }
],
labs: []
}
];
let currentPatientId = null;
// -------------------------------------------------------------------------
// Utils
// -------------------------------------------------------------------------
function showToast(msg, type = 'info') {
const container = document.getElementById('toast-container');
if(!container) return; // safety
const toast = document.createElement('div');
toast.className = 'toast';
toast.style.background = type === 'error' ? 'rgba(220, 53, 69, 0.9)' : 'rgba(0, 0, 0, 0.8)';
toast.innerText = msg;
container.appendChild(toast);
// Trigger reflow
void toast.offsetWidth;
toast.classList.add('show');
setTimeout(() => {
toast.classList.remove('show');
setTimeout(() => toast.remove(), 300);
}, 3000);
}
// -------------------------------------------------------------------------
// Custom Modal Functions
// -------------------------------------------------------------------------
let confirmCallback = null;
let inputCallback = null;
function showConfirm(message, callback) {
confirmCallback = callback;
document.getElementById('confirm-message').innerText = message;
document.getElementById('confirm-modal').classList.add('show');
}
function closeConfirmModal() {
document.getElementById('confirm-modal').classList.remove('show');
confirmCallback = null;
}
function executeConfirm() {
if(confirmCallback) {
confirmCallback();
}
closeConfirmModal();
}
function showInput(message, callback) {
inputCallback = callback;
document.getElementById('input-message').innerText = message;
document.getElementById('input-field').value = '';
document.getElementById('input-modal').classList.add('show');
document.getElementById('input-field').focus();
}
function closeInputModal() {
document.getElementById('input-modal').classList.remove('show');
inputCallback = null;
}
function executeInput() {
const value = document.getElementById('input-field').value;
if(inputCallback) {
inputCallback(value);
}
closeInputModal();
}
// Allow Enter key to submit input modal
document.addEventListener('DOMContentLoaded', () => {
const inputField = document.getElementById('input-field');
if(inputField) {
inputField.addEventListener('keypress', (e) => {
if(e.key === 'Enter' && document.getElementById('input-modal').classList.contains('show')) {
executeInput();
}
});
}
});
function switchModule(el, moduleName) {
// Toggle active state in Nav
document.querySelectorAll('.nav-item').forEach(item => item.classList.remove('active'));
if (el) el.classList.add('active');
// Hide all modules
document.querySelectorAll('.main-module').forEach(m => m.style.display = 'none');
// Show target module
const target = document.getElementById(`module-${moduleName}`);
if(target) {
target.style.display = 'block';
showToast(`Switched to [${moduleName === 'clinic' ? 'Outpatient' :
moduleName === 'inpatient' ? 'Inpatient' :
moduleName === 'surgery' ? 'Surgery' :
moduleName === 'lab' ? 'Lab Results' :
moduleName === 'pharmacy' ? 'Pharmacy' : 'Order Admin'}]`);
} else {
// Fallback
document.getElementById('module-clinic').style.display = 'block';
showToast(`Module [${moduleName}] is under maintenance`, "warning");
}
}
function logout() {
showConfirm("Are you sure you want to logout Current User (Dr. Zhang)?", () => {
showToast("Logging out...", "info");
setTimeout(() => location.reload(), 1000);
});
}
function openOA() { showToast("Opening OA System..."); }
function openLibrary() { showToast("Connecting to Medical Knowledge Base..."); }
function modifyPassword() { showToast("Please contact IT dept to reset password"); }
// -------------------------------------------------------------------------
// Core Logic
// -------------------------------------------------------------------------
// Initialize
window.onload = function() {
document.getElementById('patient-count').innerText = PATIENTS.length;
renderPatientList();
// Automatically select first patient
if(PATIENTS.length > 0) {
selectPatient(PATIENTS[0].id);
}
// Update time
document.getElementById('last-sync-time').innerText = new Date().toLocaleTimeString();
};
function renderPatientList() {
const tbody = document.getElementById('patient-list-container');
tbody.innerHTML = '';
PATIENTS.forEach(p => {
const tr = document.createElement('tr');
tr.id = `patient-row-${p.id}`;
tr.className = `patient-row ${currentPatientId === p.id ? 'active' : ''}`;
tr.onclick = () => selectPatient(p.id);
// Background color for VIP or special rows based on type/logic
let rowStyle = '';
if (p.type === 'vip') rowStyle = 'background-color:#fffbe6;';
// Name display formatting
let nameHtml = `<b>${p.id}. ${p.name} (${p.gender}, ${p.age}y)</b>`;
if (p.type === 'vip') nameHtml = `<font color="red"><b>VIP. ${p.name} (${p.gender}, ${p.age}y)</b></font>`;
const actionsHtml = `<div style="margin-top:5px;">
<a href="javascript:void(0)" style="font-size:12px;">[Consult]</a>
<a href="javascript:void(0)" style="font-size:12px; color:#999; margin-left:5px;">[Skip]</a>
</div>`;
tr.innerHTML = `
<td style="padding:15px; border-bottom:1px solid #eee; ${rowStyle}">
${nameHtml}<br>
<font size="2" color="#666">C/C: ${p.complaint}</font><br>
${actionsHtml}
</td>
`;
tbody.appendChild(tr);
});
}
function selectPatient(id) {
currentPatientId = id;
renderPatientList(); // Re-render to update highlight
const p = PATIENTS.find(x => x.id === id);
if(!p) return;
// Render Top Info
const infoCard = document.getElementById('patient-info-card');
const allergyHtml = p.allergies.includes("None") ? 'None' : `<font color="red" style="background:#ffe3e3; padding:2px 5px; border-radius:3px;">${p.allergies.join(',')}</font>`;
infoCard.innerHTML = `
<tr>
<td colspan="4" bgcolor="#cccccc"><b>Patient: ${p.name} (ID: 2025${p.id})</b> - <font color="#333">${p.diagnosis}</font></td>
</tr>
<tr>
<td width="15%"><b>Allergies:</b></td>
<td width="35%">${allergyHtml}</td>
<td width="15%"><b>Insurance:</b></td>
<td width="35%">${p.insurance}</td>
</tr>
<tr>
<td><b>Vitals:</b></td>
<td colspan="3">BP: ${p.vitals.bp} mmHg, HR: ${p.vitals.hr}, T: ${p.vitals.t}°C</td>
</tr>
`;
// Render Labs
const labList = document.getElementById('lab-list');
labList.innerHTML = '';
if (p.labs.length === 0) {
labList.innerHTML = '<li style="color:#999;font-style:italic;">No lab results</li>';
} else {
p.labs.forEach(lab => {
const safeLabName = lab.name.replace(/[^a-zA-Z0-9]/g, '-');
const linkPart = lab.link ? ` <a id="btn-view-lab-${safeLabName}" href="javascript:void(0)" onclick="viewLabImage('${lab.name}')" aria-label="View image for ${lab.name}">[View Image]</a>` : '';
const li = document.createElement('li');
li.style.marginBottom = '5px';
li.innerHTML = `${lab.date}: ${lab.name} - ${lab.result} ${linkPart}`;
labList.appendChild(li);
});
}
// Show Panels
document.getElementById('order-panel').style.display = 'block';
document.getElementById('lab-panel').style.display = 'block';
renderOrders();
renderClinicalPaths();
}
function renderClinicalPaths() {
const p = PATIENTS.find(x => x.id === currentPatientId);
const container = document.getElementById('clinical-path-list');
if(!container) return;
container.innerHTML = '';
if(!p.pathways || p.pathways.length === 0) {
container.innerHTML = '<tr><td colspan="2" style="color:#999; text-align:center;">No clinical pathway tasks</td></tr>';
return;
}
p.pathways.forEach((path, idx) => {
const tr = document.createElement('tr');
const isChecked = path.checked ? 'checked' : '';
const statusColor = path.checked ? 'green' : '#666';
tr.innerHTML = `
<td width="30" align="center">
<input type="checkbox" ${isChecked} disabled>
</td>
<td style="color:${statusColor};">${path.name}</td>
`;
container.appendChild(tr);
});
}
function renderOrders() {
const p = PATIENTS.find(x => x.id === currentPatientId);
const tbody = document.getElementById('order-list-body');
tbody.innerHTML = '';
if(p.orders.length === 0) {
tbody.innerHTML = '<tr><td colspan="6" align="center" style="padding:20px; color:#999;">No orders yet. Click "Add Drug" to start.</td></tr>';
return;
}
p.orders.forEach(order => {
const drugInfo = DRUG_DICT[order.drug] || { name: order.drug, spec: 'Unknown' };
let statusBadge = '';
let actionHtml = '';
if (order.status === 'signed') {
statusBadge = '<span class="status-badge badge-signed">Signed</span>';
actionHtml = '<span style="color:#ccc; font-size:12px;">Locked</span>'; // Simplify logic
} else {
statusBadge = '<span class="status-badge badge-draft">Draft</span>';
actionHtml = `<a href="javascript:void(0)" style="color:#dc3545;" onclick="removeOrder(${order.id})">Delete</a>`;
}
const tr = document.createElement('tr');
// Use grid style matching header
tr.style.display = 'grid';
tr.style.gridTemplateColumns = '40px 1.5fr 1fr 2fr 100px 80px';
tr.style.padding = '10px';
tr.style.borderBottom = '1px solid #eee';
tr.style.alignItems = 'center';
tr.innerHTML = `
<td align="center"><input type="checkbox" name="order-select" value="${order.id}"></td>
<td>${drugInfo.name}</td>
<td>${drugInfo.spec}</td>
<td>
${order.status === 'draft' ?
`<input type="text" value="${order.dose}" style="width:50px; border:1px solid #ddd; padding:2px;"> <span style="font-size:12px;">${order.freq}</span>` :
`<b>${order.dose}</b> ${order.freq} ${order.route}`
}
</td>
<td>${statusBadge}</td>
<td>${actionHtml}</td>
`;
tbody.appendChild(tr);
});
}
// -------------------------------------------------------------------------
// Actions
// -------------------------------------------------------------------------
function openAddDrugModal() {
document.getElementById('drug-modal').classList.add('show');
// Reset form
document.getElementById('modal-drug-spec').value = '';
document.getElementById('modal-drug-name').value = '';
document.getElementById('modal-drug-dose').value = '';
}
function closeModal() {
document.getElementById('drug-modal').classList.remove('show');
}
function updateDrugSpecs() {
const key = document.getElementById('modal-drug-name').value;
const specInput = document.getElementById('modal-drug-spec');
if(key && DRUG_DICT[key]) {
specInput.value = DRUG_DICT[key].spec;
} else {
specInput.value = '';
}
}
function confirmAddDrug() {
const key = document.getElementById('modal-drug-name').value;
const dose = document.getElementById('modal-drug-dose').value;
if(!key || !dose) {
showToast("Please complete drug and dosage info", "error");
return;
}
const freq = document.getElementById('modal-drug-freq').value;
const route = document.getElementById('modal-drug-route').value;
const p = PATIENTS.find(x => x.id === currentPatientId);
// Add new order
p.orders.push({
id: Date.now(),
drug: key,
dose: dose,
freq: freq,
route: route,
status: 'draft'
});
closeModal();
renderOrders();
showToast("Order Created (Draft)", "success");
}
function removeOrder(orderId) {
showConfirm("Are you sure you want to delete this order?", () => {
const p = PATIENTS.find(x => x.id === currentPatientId);
p.orders = p.orders.filter(o => o.id !== orderId);
renderOrders();
showToast("Order Deleted");
});
}
function signOrder() {
const p = PATIENTS.find(x => x.id === currentPatientId);
const drafts = p.orders.filter(o => o.status === 'draft');
if (drafts.length === 0) {
showToast("No draft orders to sign.", "warning");
return;
}
showInput(`Signing ${drafts.length} orders for patient [${p.name}].\n\nPlease enter E-Signature PIN:`, (pin) => {
if(pin) {
drafts.forEach(o => o.status = 'signed');
showToast("Orders Signed & Sent to Pharmacy.", "success");
renderOrders();
}
});
}
function voidOrder() {
showToast("Select signed orders to void, then submit for Medical Director approval.", "warning");
}
function viewLabImage(name) {
showToast(`Retrieving PACS Image: ${name}...`, "info");
}
// -------------------------------------------------------------------------
// Module Logic (New)
// -------------------------------------------------------------------------
function searchLabReport() {
const val = document.getElementById('lab-search-input').value;
if(!val) {
showToast("Please enter search keywords", "warning");
return;
}
showToast(`Searching LIS for [${val}]...`, "info");
setTimeout(() => {
showToast("No records found (Mock)", "error");
}, 1500);
}
function restockDrug(drugName) {
showConfirm(`Send restock request for [${drugName}]?`, () => {
showToast("Restock request sent to Supply Chain", "success");
});
}
function batchApproveOrders() {
showConfirm("Batch approve these 3 orders?", () => {
showToast("Batch Approval Complete", "success");
document.getElementById('admin-task-area').innerHTML = '<p style="color:green;">All pending tasks completed.</p>';
});
}
function batchRejectOrders() {
showInput("Enter Rejection Reason:", (reason) => {
if(reason) {
showToast(`3 Orders Rejected. Reason: ${reason}`, "info");
document.getElementById('admin-task-area').innerHTML = '<p style="color:green;">All pending tasks completed.</p>';
}
});
}
console.log("HIS System Loaded. Interface modernized.");
</script>
</body>
</html>