Show SV metadata for postprocess results
This commit is contained in:
@@ -28,6 +28,56 @@ function formatBytes(bytes) {
|
||||
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
||||
}
|
||||
|
||||
function formatGain(value) {
|
||||
const number = Number(value);
|
||||
return Number.isFinite(number) ? number.toFixed(3) : "";
|
||||
}
|
||||
|
||||
function svSummary(meta = {}) {
|
||||
const s = formatGain(meta.s_gain);
|
||||
const v = formatGain(meta.v_gain);
|
||||
if (!s || !v) return "";
|
||||
return `S ${s} · V ${v}`;
|
||||
}
|
||||
|
||||
function updateGainLabels() {
|
||||
$("sGainValue").textContent = formatGain($("sGain").value);
|
||||
$("vGainValue").textContent = formatGain($("vGain").value);
|
||||
}
|
||||
|
||||
function setOnlyPostprocessor(processor) {
|
||||
[...$("postList").querySelectorAll("input[type=checkbox]")].forEach((input) => {
|
||||
input.checked = input.value === processor;
|
||||
});
|
||||
}
|
||||
|
||||
function setSelectIfOption(selectId, value) {
|
||||
const select = $(selectId);
|
||||
if ([...select.options].some((option) => option.value === value)) {
|
||||
select.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
function applySvFromResult(item) {
|
||||
const meta = item.meta || {};
|
||||
const sGain = Number(meta.s_gain);
|
||||
const vGain = Number(meta.v_gain);
|
||||
if (!Number.isFinite(sGain) || !Number.isFinite(vGain)) return;
|
||||
|
||||
$("sGain").value = Math.min(2.5, Math.max(0, sGain));
|
||||
$("vGain").value = Math.min(2.5, Math.max(0, vGain));
|
||||
updateGainLabels();
|
||||
setOnlyPostprocessor("manual_sv");
|
||||
if (item.source) {
|
||||
setSelectIfOption("postSource", item.source);
|
||||
}
|
||||
if (item.reference) {
|
||||
setSelectIfOption("referenceImage", item.reference);
|
||||
}
|
||||
$("logBox").textContent = `已载入 ${item.name} 的参数:S=${formatGain(sGain)},V=${formatGain(vGain)}\n可在左侧手动微调后点击“生成后处理”。`;
|
||||
setJobState("SV Ready", "done");
|
||||
}
|
||||
|
||||
function renderImages() {
|
||||
const box = $("imageList");
|
||||
box.innerHTML = "";
|
||||
@@ -104,14 +154,26 @@ async function selectImage(name) {
|
||||
await refreshResults();
|
||||
}
|
||||
|
||||
function resultCard(title, path, exists = true) {
|
||||
function resultCard(title, path, exists = true, item = null) {
|
||||
const card = document.createElement("article");
|
||||
card.className = "result-card";
|
||||
const summary = item ? svSummary(item.meta) : "";
|
||||
card.className = `result-card ${summary ? "clickable" : ""}`;
|
||||
const badge = exists ? '<span class="badge ok">ready</span>' : '<span class="badge pending">未生成</span>';
|
||||
const body = exists
|
||||
? `<div class="image-frame"><img src="${assetUrl(path)}" alt="${title}" loading="lazy" /></div>`
|
||||
? `<div class="image-frame"><img src="${assetUrl(path)}" alt="${title}" loading="lazy" /></div>${summary ? `<div class="sv-strip"><span>${summary}</span><small>点击载入</small></div>` : ""}`
|
||||
: '<div class="image-frame"><span class="missing">暂无结果</span></div>';
|
||||
card.innerHTML = `<header><h3>${title}</h3>${badge}</header>${body}`;
|
||||
if (summary && item) {
|
||||
card.tabIndex = 0;
|
||||
card.title = "点击将这组 S/V 载入左侧手动调整";
|
||||
card.addEventListener("click", () => applySvFromResult(item));
|
||||
card.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter" || event.key === " ") {
|
||||
event.preventDefault();
|
||||
applySvFromResult(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
return card;
|
||||
}
|
||||
|
||||
@@ -148,7 +210,7 @@ async function refreshResults() {
|
||||
grid.appendChild(resultCard(item.label, item.path, item.exists));
|
||||
});
|
||||
results.postprocess.forEach((item) => {
|
||||
grid.appendChild(resultCard(item.name, item.path, true));
|
||||
grid.appendChild(resultCard(item.name, item.path, true, item));
|
||||
});
|
||||
updatePostSourceOptions(results);
|
||||
}
|
||||
@@ -253,12 +315,9 @@ function bindControls() {
|
||||
$("downloadCurrentBtn").addEventListener("click", downloadCurrent);
|
||||
$("downloadAllBtn").addEventListener("click", downloadAll);
|
||||
$("refreshBtn").addEventListener("click", refreshResults);
|
||||
$("sGain").addEventListener("input", () => {
|
||||
$("sGainValue").textContent = `${Math.round(Number($("sGain").value) * 100)}%`;
|
||||
});
|
||||
$("vGain").addEventListener("input", () => {
|
||||
$("vGainValue").textContent = `${Math.round(Number($("vGain").value) * 100)}%`;
|
||||
});
|
||||
$("sGain").addEventListener("input", updateGainLabels);
|
||||
$("vGain").addEventListener("input", updateGainLabels);
|
||||
updateGainLabels();
|
||||
}
|
||||
|
||||
async function init() {
|
||||
|
||||
@@ -318,6 +318,17 @@ h1 {
|
||||
background: rgba(255, 250, 241, 0.82);
|
||||
}
|
||||
|
||||
.result-card.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.result-card.clickable:hover,
|
||||
.result-card.clickable:focus {
|
||||
outline: 2px solid rgba(31, 107, 87, 0.36);
|
||||
outline-offset: 2px;
|
||||
border-color: rgba(31, 107, 87, 0.55);
|
||||
}
|
||||
|
||||
.result-card header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -372,6 +383,32 @@ h1 {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.sv-strip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
min-height: 36px;
|
||||
padding: 7px 10px;
|
||||
border-top: 1px solid var(--line);
|
||||
background: rgba(31, 107, 87, 0.09);
|
||||
color: var(--green-dark);
|
||||
font-size: 12px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.sv-strip span {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.sv-strip small {
|
||||
flex: 0 0 auto;
|
||||
color: var(--muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.missing {
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
|
||||
Reference in New Issue
Block a user