Files
PACS/DICOM_and_UPP配准/static/index.html
2026-05-28 11:58:59 +08:00

180 lines
7.2 KiB
HTML

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>DICOM / UPP 配准工作台</title>
<link rel="stylesheet" href="/static/styles.css" />
<script type="importmap">
{
"imports": {
"three": "/static/vendor/three.module.min.js"
}
}
</script>
</head>
<body>
<header class="topbar">
<div class="brand">
<span class="brand-mark"></span>
<div>
<h1>DICOM / UPP 配准工作台</h1>
<p id="brandSubtitle">DICOM 序列、STL family 与人工位姿锁定</p>
</div>
</div>
<div class="top-actions">
<button id="relationBtn" class="dark-btn accent" type="button">数据库关联</button>
<button id="viewerBtn" class="dark-btn" type="button">阅片系统</button>
<span id="dbStatus" class="status-pill">数据库</span>
<button id="refreshBtn" class="dark-btn" type="button">刷新</button>
<span id="userBadge" class="user-badge">未登录</span>
<button id="logoutBtn" class="dark-btn" type="button">退出</button>
</div>
</header>
<div id="topLoading" class="top-loading hidden"><span></span></div>
<main class="workspace">
<aside class="left-rail">
<section class="panel search-panel">
<div class="panel-head">
<h2>匹配检查</h2>
<span id="caseCount">0</span>
</div>
<input id="caseSearch" class="search-input" placeholder="搜索 CT号 / 姓名 / 模型" />
<div id="caseList" class="case-list"></div>
</section>
<section class="panel stacked-panel">
<div class="panel-head">
<h2>DICOM序列</h2>
<span id="seriesCount">0</span>
</div>
<div id="seriesList" class="series-list"></div>
</section>
<section class="panel stacked-panel">
<div class="panel-head">
<h2>STL模型</h2>
<span id="stlCount">0</span>
</div>
<div class="segmented small">
<button id="modeFile" class="active" type="button">单独</button>
<button id="modeFamily" type="button">Family</button>
</div>
<div id="familyRail" class="chip-rail"></div>
<div id="stlList" class="stl-list"></div>
</section>
<section class="panel registration-panel">
<div class="panel-head">
<h2>交互配准</h2>
<span id="saveState">未保存</span>
</div>
<div class="pose-grid" id="poseGrid"></div>
<textarea id="registrationNotes" class="notes" rows="2" placeholder="配准备注"></textarea>
<div class="action-grid">
<button id="resetPoseBtn" class="dark-btn" type="button">重置位姿</button>
<button id="saveRegistrationBtn" class="primary-btn" type="button">保存配准</button>
<button id="lockRegistrationBtn" class="warn-btn" type="button">保存并上锁</button>
<button id="unlockRegistrationBtn" class="dark-btn" type="button">解锁</button>
<button id="exportStlBtn" class="dark-btn" type="button">导出STL</button>
</div>
</section>
</aside>
<section class="viewer-shell">
<section class="panel hero-strip">
<div>
<h2 id="activeTitle">未选择 CT</h2>
<p id="activeMeta">从左侧选择一个 DICOM + STL 匹配检查</p>
</div>
<div class="hero-tags" id="activeTags"></div>
</section>
<section class="viewer-grid">
<article class="viewport-card dicom-card">
<div class="viewport-head">
<div>
<h3>DICOM</h3>
<span id="dicomMeta">未选择序列</span>
</div>
<div class="tool-row">
<select id="planeSelect">
<option value="axial">轴位</option>
<option value="sagittal">矢状位</option>
<option value="coronal">冠状位</option>
</select>
<select id="windowSelect">
<option value="default">默认</option>
<option value="soft">软组织</option>
<option value="bone">骨窗</option>
<option value="contrast">高对比</option>
</select>
</div>
</div>
<div class="image-stage" id="dicomStage">
<img id="dicomImage" alt="DICOM切片" />
<div id="dicomEmpty" class="empty-state">等待选择 DICOM 序列</div>
</div>
<div class="slice-row">
<input id="sliceSlider" type="range" min="0" max="0" value="0" />
<span id="sliceLabel">0 / 0</span>
</div>
</article>
<article class="viewport-card">
<div class="viewport-head">
<div>
<h3>STL拼接后</h3>
<span id="stlMeta">未加载模型</span>
</div>
<button id="fitStlBtn" class="icon-btn" title="重置三维视角" type="button">复位</button>
</div>
<div id="stlViewport" class="three-stage"></div>
</article>
<article class="viewport-card fusion-card">
<div class="viewport-head">
<div>
<h3>STL和DICOM融合</h3>
<span id="fusionMeta">位姿未保存</span>
</div>
<button id="fitFusionBtn" class="icon-btn" title="重置融合视角" type="button">复位</button>
</div>
<div id="fusionViewport" class="three-stage"></div>
</article>
<article class="viewport-card segmentation-card">
<div class="viewport-head">
<div>
<h3>DICOM分割</h3>
<span id="segmentationMeta">基于当前可见 STL 的预览</span>
</div>
<button id="toggleMaskBtn" class="icon-btn" title="显示或隐藏分割预览" type="button">显示</button>
</div>
<div class="segmentation-stage">
<img id="segmentationImage" alt="DICOM分割预览" />
<canvas id="maskCanvas"></canvas>
<div id="segmentationEmpty" class="empty-state">选择序列和 STL 后显示叠加预览</div>
</div>
</article>
</section>
</section>
</main>
<div id="loginOverlay" class="login-overlay">
<form id="loginForm" class="login-panel">
<span class="brand-mark"></span>
<h2>DICOM / UPP 配准工作台</h2>
<p>登录后进行 DICOM 与 STL 配准</p>
<input id="username" class="search-input" autocomplete="username" placeholder="账号" />
<input id="password" class="search-input" type="password" autocomplete="current-password" placeholder="密码" />
<button class="primary-btn" type="submit">登录</button>
<span id="loginError" class="error-line"></span>
</form>
</div>
<script type="module" src="/static/app.js"></script>
</body>
</html>