Update PACS DICOM navigation and summaries
This commit is contained in:
@@ -41,7 +41,8 @@ const app = {
|
||||
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
||||
const BODY_PARTS = ["head_neck", "chest", "upper_abdomen", "lower_abdomen", "pelvis"];
|
||||
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
const BODY_PARTS = ["head_neck", "chest", "upper_abdomen", "abdomen_pelvis"];
|
||||
const WINDOW_PRESETS = {
|
||||
bone: { wl: 500, ww: 1800 },
|
||||
soft: { wl: 50, ww: 360 },
|
||||
@@ -139,8 +140,7 @@ function partLabel(value) {
|
||||
head_neck: "头颈部",
|
||||
chest: "胸部",
|
||||
upper_abdomen: "上腹部",
|
||||
lower_abdomen: "下腹部",
|
||||
pelvis: "盆腔",
|
||||
abdomen_pelvis: "腹盆部",
|
||||
}[value] || value;
|
||||
}
|
||||
|
||||
@@ -443,6 +443,23 @@ function initialCtNumber() {
|
||||
return new URLSearchParams(location.search).get("ct_number") || "";
|
||||
}
|
||||
|
||||
function siblingSystemUrl(port, params = {}) {
|
||||
const url = new URL(window.location.href);
|
||||
url.port = String(port);
|
||||
url.pathname = "/";
|
||||
url.search = "";
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
if (value) url.searchParams.set(key, value);
|
||||
});
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
function openSiblingSystem(kind) {
|
||||
const ctNumber = app.study?.ct_number || initialCtNumber();
|
||||
const port = kind === "registration" ? 8109 : 8108;
|
||||
window.open(siblingSystemUrl(port, { ct_number: ctNumber }), "_blank");
|
||||
}
|
||||
|
||||
async function loadStudies(preferredCtNumber = "") {
|
||||
const q = encodeURIComponent($("studySearch").value.trim());
|
||||
app.studies = sortStudies(await json(`/api/studies?q=${q}&limit=500`));
|
||||
@@ -1323,7 +1340,8 @@ async function renderSettingsPage() {
|
||||
<div>
|
||||
<div class="settings-title"><h3>检查摘要</h3><span>${refresh.running ? "刷新中" : "待命"}</span></div>
|
||||
<dl>
|
||||
<dt>计划刷新</dt><dd>每天 04:00</dd>
|
||||
<dt>计划刷新</dt><dd>每天 04:00(北京时间,全量)</dd>
|
||||
<dt>下次刷新</dt><dd>${escapeHtml(refresh.next_scheduled_at || "-")}</dd>
|
||||
<dt>最近开始</dt><dd>${escapeHtml(refresh.started_at || "-")}</dd>
|
||||
<dt>最近完成</dt><dd>${escapeHtml(refresh.finished_at || "-")}</dd>
|
||||
<dt>状态</dt><dd>${escapeHtml(refresh.message || "-")}</dd>
|
||||
@@ -1382,6 +1400,15 @@ async function refreshSummariesNow() {
|
||||
button.disabled = true;
|
||||
button.textContent = "已开始刷新";
|
||||
await json("/api/settings/refresh-summaries", { method: "POST", body: JSON.stringify({}) });
|
||||
let refresh = {};
|
||||
for (let i = 0; i < 300; i += 1) {
|
||||
await sleep(2000);
|
||||
const settings = await json("/api/settings");
|
||||
refresh = settings.summary_refresh || {};
|
||||
button.textContent = refresh.running ? refresh.message || "刷新中" : "刷新完成";
|
||||
if (!refresh.running) break;
|
||||
}
|
||||
await loadStudies(app.study?.ct_number || initialCtNumber());
|
||||
await renderSettingsPage();
|
||||
}
|
||||
|
||||
@@ -1455,6 +1482,8 @@ function wire() {
|
||||
$("loginForm").addEventListener("submit", login);
|
||||
$("logoutBtn").addEventListener("click", logout);
|
||||
$("settingsBtn").addEventListener("click", openSettings);
|
||||
$("registrationLinkBtn").addEventListener("click", () => openSiblingSystem("registration"));
|
||||
$("relationLinkBtn").addEventListener("click", () => openSiblingSystem("relation"));
|
||||
$("backToViewer").addEventListener("click", () => showViewerPage(true));
|
||||
$("infoBtn").addEventListener("click", openInfo);
|
||||
$("aiClassify").addEventListener("click", runAI);
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-actions">
|
||||
<button id="registrationLinkBtn" class="ghost-btn nav-btn" type="button">进入配准系统</button>
|
||||
<button id="relationLinkBtn" class="ghost-btn nav-btn accent" type="button">数据库关联可视化</button>
|
||||
<div id="dbStatus" class="status-pill offline">数据库</div>
|
||||
<button id="settingsBtn" class="ghost-btn">设置</button>
|
||||
<button id="logoutBtn" class="dark-btn">退出</button>
|
||||
@@ -60,8 +62,7 @@
|
||||
<button data-study-part-filter="head_neck">头颈部</button>
|
||||
<button data-study-part-filter="chest">胸部</button>
|
||||
<button data-study-part-filter="upper_abdomen">上腹部</button>
|
||||
<button data-study-part-filter="lower_abdomen">下腹部</button>
|
||||
<button data-study-part-filter="pelvis">盆腔</button>
|
||||
<button data-study-part-filter="abdomen_pelvis">腹盆部</button>
|
||||
</div>
|
||||
<input id="studySearch" class="search" placeholder="搜索检查号 / 姓名" />
|
||||
<div id="studyList" class="study-list"></div>
|
||||
@@ -136,8 +137,7 @@
|
||||
<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>
|
||||
<label><input type="checkbox" value="abdomen_pelvis" />腹盆部</label>
|
||||
</div>
|
||||
<div id="phaseBox" class="phase-box">
|
||||
<span>上腹部期相</span>
|
||||
|
||||
@@ -242,6 +242,22 @@ button:disabled {
|
||||
background: #070a10;
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
min-width: 118px;
|
||||
color: #d8e8ff;
|
||||
}
|
||||
|
||||
.nav-btn.accent {
|
||||
border-color: rgba(25, 212, 194, 0.42);
|
||||
color: #c7fff7;
|
||||
background: rgba(25, 212, 194, 0.08);
|
||||
}
|
||||
|
||||
.nav-btn.accent:hover {
|
||||
border-color: rgba(25, 212, 194, 0.72);
|
||||
background: rgba(25, 212, 194, 0.14);
|
||||
}
|
||||
|
||||
.workspace {
|
||||
height: calc(100vh - 66px);
|
||||
display: grid;
|
||||
|
||||
Reference in New Issue
Block a user