Add series count sorting
This commit is contained in:
@@ -42,7 +42,7 @@ uvicorn app:app --host 127.0.0.1 --port 8107
|
|||||||
- 影像操作:支持鼠标滚轮缩放、拖拽平移、按钮缩放和复位。
|
- 影像操作:支持鼠标滚轮缩放、拖拽平移、按钮缩放和复位。
|
||||||
- 图像叠层:可显示/隐藏患者、检查、方向、张数、窗宽窗位和缩放信息。
|
- 图像叠层:可显示/隐藏患者、检查、方向、张数、窗宽窗位和缩放信息。
|
||||||
- DICOM 信息:查看患者、检查、序列、像素间距、切片间距等元数据。
|
- DICOM 信息:查看患者、检查、序列、像素间距、切片间距等元数据。
|
||||||
- 序列列表:默认按拍摄时间升序排序,可切换降序;少于 80 张且未标注部位的序列默认略过。
|
- 序列列表:默认按拍摄时间升序排序,可切换时间升降序或张数升降序;略过序列固定在最下方,并在略过分组内继续按当前排序规则排列。
|
||||||
- 序列标注:选择略过、平扫 CT、头颈部、胸部、上腹部、下腹部、盆腔;点击后自动保存;上腹部需继续选择动脉期、门静脉期或无法判别。
|
- 序列标注:选择略过、平扫 CT、头颈部、胸部、上腹部、下腹部、盆腔;点击后自动保存;上腹部需继续选择动脉期、门静脉期或无法判别。
|
||||||
- AI 识别:配置 Kimi 后,可把序列张数及轴位原始、矢状位重建、冠状位重建代表图像传入 AI,自动给出部位、期相和备注建议。
|
- AI 识别:配置 Kimi 后,可把序列张数及轴位原始、矢状位重建、冠状位重建代表图像传入 AI,自动给出部位、期相和备注建议。
|
||||||
- 设置:支持用户创建、角色权限展示、数据库状态和 AI 配置查看。
|
- 设置:支持用户创建、角色权限展示、数据库状态和 AI 配置查看。
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const app = {
|
|||||||
saveTimer: null,
|
saveTimer: null,
|
||||||
pendingImage: null,
|
pendingImage: null,
|
||||||
drag: null,
|
drag: null,
|
||||||
seriesSort: "asc",
|
seriesSort: "timeAsc",
|
||||||
showOverlay: true,
|
showOverlay: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -173,8 +173,12 @@ function sortSeries(list) {
|
|||||||
const skipA = a.annotation?.skipped ? 1 : 0;
|
const skipA = a.annotation?.skipped ? 1 : 0;
|
||||||
const skipB = b.annotation?.skipped ? 1 : 0;
|
const skipB = b.annotation?.skipped ? 1 : 0;
|
||||||
if (skipA !== skipB) return skipA - skipB;
|
if (skipA !== skipB) return skipA - skipB;
|
||||||
const result = timeKey(a).localeCompare(timeKey(b)) || String(a.series_number || "").localeCompare(String(b.series_number || ""), undefined, { numeric: true });
|
const timeResult = timeKey(a).localeCompare(timeKey(b)) || String(a.series_number || "").localeCompare(String(b.series_number || ""), undefined, { numeric: true });
|
||||||
return app.seriesSort === "asc" ? result : -result;
|
const countResult = Number(a.count || 0) - Number(b.count || 0) || timeResult;
|
||||||
|
if (app.seriesSort === "timeDesc") return -timeResult;
|
||||||
|
if (app.seriesSort === "countAsc") return countResult;
|
||||||
|
if (app.seriesSort === "countDesc") return -countResult;
|
||||||
|
return timeResult;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -762,8 +766,9 @@ function wireImageGestures() {
|
|||||||
|
|
||||||
function setSort(direction) {
|
function setSort(direction) {
|
||||||
app.seriesSort = direction;
|
app.seriesSort = direction;
|
||||||
$("sortAsc").classList.toggle("active", direction === "asc");
|
document.querySelectorAll("[data-sort]").forEach((button) => {
|
||||||
$("sortDesc").classList.toggle("active", direction === "desc");
|
button.classList.toggle("active", button.dataset.sort === direction);
|
||||||
|
});
|
||||||
app.series = sortSeries(app.series);
|
app.series = sortSeries(app.series);
|
||||||
renderSeries();
|
renderSeries();
|
||||||
if (app.activeSeries) {
|
if (app.activeSeries) {
|
||||||
@@ -783,8 +788,9 @@ function wire() {
|
|||||||
app.showOverlay = !app.showOverlay;
|
app.showOverlay = !app.showOverlay;
|
||||||
updateOverlay();
|
updateOverlay();
|
||||||
});
|
});
|
||||||
$("sortAsc").addEventListener("click", () => setSort("asc"));
|
document.querySelectorAll("[data-sort]").forEach((button) => {
|
||||||
$("sortDesc").addEventListener("click", () => setSort("desc"));
|
button.addEventListener("click", () => setSort(button.dataset.sort));
|
||||||
|
});
|
||||||
$("studySearch").addEventListener("input", () => {
|
$("studySearch").addEventListener("input", () => {
|
||||||
clearTimeout(app.searchTimer);
|
clearTimeout(app.searchTimer);
|
||||||
app.searchTimer = setTimeout(loadStudies, 250);
|
app.searchTimer = setTimeout(loadStudies, 250);
|
||||||
|
|||||||
@@ -54,8 +54,10 @@
|
|||||||
<div class="pane-head">
|
<div class="pane-head">
|
||||||
<h2>序列</h2>
|
<h2>序列</h2>
|
||||||
<div class="series-head-tools">
|
<div class="series-head-tools">
|
||||||
<button id="sortAsc" class="sort-btn active">时间 ↑</button>
|
<button id="sortTimeAsc" class="sort-btn active" data-sort="timeAsc">时间 ↑</button>
|
||||||
<button id="sortDesc" class="sort-btn">时间 ↓</button>
|
<button id="sortTimeDesc" class="sort-btn" data-sort="timeDesc">时间 ↓</button>
|
||||||
|
<button id="sortCountAsc" class="sort-btn" data-sort="countAsc">张数 ↑</button>
|
||||||
|
<button id="sortCountDesc" class="sort-btn" data-sort="countDesc">张数 ↓</button>
|
||||||
<span id="seriesCount">0</span>
|
<span id="seriesCount">0</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -287,17 +287,21 @@ button:disabled {
|
|||||||
.series-head-tools {
|
.series-head-tools {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
flex-wrap: wrap;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
|
max-width: 330px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sort-btn {
|
.sort-btn {
|
||||||
height: 26px;
|
height: 26px;
|
||||||
padding: 0 8px;
|
min-width: 56px;
|
||||||
|
padding: 0 7px;
|
||||||
border: 1px solid var(--stroke);
|
border: 1px solid var(--stroke);
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
background: #0b0f16;
|
background: #0b0f16;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
font-size: 12px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sort-btn.active {
|
.sort-btn.active {
|
||||||
|
|||||||
Reference in New Issue
Block a user