Add Docker PACS DICOM web viewer

This commit is contained in:
Codex
2026-05-27 08:43:33 +08:00
parent f3e3cfff1d
commit 9c478ed392
10 changed files with 2577 additions and 0 deletions

View File

@@ -0,0 +1,156 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>PACS DICOM Viewer</title>
<link rel="stylesheet" href="/static/styles.css" />
</head>
<body>
<div id="loginOverlay" class="login-overlay">
<form id="loginForm" class="login-panel">
<div class="brand-mark">PACS</div>
<h1>DICOM 阅片标注</h1>
<label>
<span>账号</span>
<input id="username" autocomplete="username" value="admin" />
</label>
<label>
<span>密码</span>
<input id="password" type="password" autocomplete="current-password" value="123456" />
</label>
<button type="submit">登录</button>
<p id="loginError"></p>
</form>
</div>
<div class="app-shell">
<header class="topbar">
<div class="product">
<div class="logo-dot"></div>
<div>
<strong>PACS DICOM Viewer</strong>
<span id="activeStudyLabel">未选择检查</span>
</div>
</div>
<div class="top-actions">
<div id="dbStatus" class="status-pill offline">数据库</div>
<button id="settingsBtn" class="ghost-btn">设置</button>
<button id="logoutBtn" class="dark-btn">退出</button>
</div>
</header>
<main class="workspace">
<aside class="study-pane">
<div class="pane-head">
<h2>检查列表</h2>
<span id="studyCount">0</span>
</div>
<input id="studySearch" class="search" placeholder="搜索检查号 / 姓名" />
<div id="studyList" class="study-list"></div>
</aside>
<section class="series-pane">
<div class="pane-head">
<h2>序列</h2>
<span id="seriesCount">0</span>
</div>
<div id="seriesGrid" class="series-grid"></div>
</section>
<section class="viewer-pane">
<div class="viewer-toolbar">
<div class="segmented" data-group="plane">
<button data-plane="axial" class="active">横断面</button>
<button data-plane="sagittal">矢状面</button>
<button data-plane="coronal">冠状面</button>
</div>
<div class="segmented" data-group="window">
<button data-window="default" class="active">默认</button>
<button data-window="bone">骨窗</button>
<button data-window="soft">软组织</button>
<button data-window="contrast">高对比</button>
</div>
<div class="tool-row">
<button id="rotateLeft">↶ 左转</button>
<button id="rotateRight">↷ 右转</button>
<button id="zoomOut"> 缩小</button>
<button id="zoomIn">+ 放大</button>
<button id="resetView">↺ 复位</button>
<button id="infoBtn">DICOM 信息</button>
</div>
</div>
<div class="viewer-stage">
<div class="image-wrap">
<img id="dicomImage" alt="" />
<div id="imageEmpty" class="image-empty"></div>
<div class="slice-rail">
<input id="sliceSlider" type="range" min="0" max="0" value="0" orient="vertical" />
<span id="sliceText">0 / 0</span>
</div>
</div>
<aside class="annotation-panel">
<div class="annotation-head">
<div>
<h2>部位标注</h2>
<span id="saveState">未保存</span>
</div>
<button id="aiClassify" class="ghost-btn ai-btn">AI 识别</button>
</div>
<div class="part-grid">
<label class="skip-option"><input type="checkbox" value="skip" />略过</label>
<label><input type="checkbox" value="head_neck" />头颈部</label>
<label><input type="checkbox" value="chest" />胸部</label>
<label><input type="checkbox" value="upper_abdomen" />上腹部</label>
<label><input type="checkbox" value="lower_abdomen" />下腹部</label>
<label><input type="checkbox" value="pelvis" />盆腔</label>
</div>
<div id="phaseBox" class="phase-box">
<span>上腹部期相</span>
<div class="phase-options">
<label><input name="phase" type="radio" value="arterial" />动脉期</label>
<label><input name="phase" type="radio" value="portal_venous" />门静脉期</label>
<label><input name="phase" type="radio" value="unknown" />无法判别</label>
</div>
</div>
<div class="annotation-actions">
<input id="annotationNotes" class="note-input" placeholder="备注" />
<button id="saveAnnotation" class="primary-btn">保存标注</button>
</div>
</aside>
</div>
</section>
</main>
</div>
<div id="infoModal" class="modal hidden">
<div class="modal-card">
<div class="modal-head">
<div>
<h2>DICOM 详细信息</h2>
<span>基础元数据、图像矩阵、空间距离</span>
</div>
<button class="icon-btn" data-close="infoModal">×</button>
</div>
<div id="infoContent" class="info-grid"></div>
</div>
</div>
<div id="settingsModal" class="modal hidden">
<div class="modal-card settings-card">
<div class="modal-head">
<div>
<h2>设置</h2>
<span>用户、权限、AI 与数据源</span>
</div>
<button class="icon-btn" data-close="settingsModal">×</button>
</div>
<div id="settingsContent" class="settings-content"></div>
</div>
</div>
<script src="/static/app.js"></script>
</body>
</html>