修复设计计算错误并优化分享
This commit is contained in:
parent
dd21623cb5
commit
30cdd05914
5 changed files with 916 additions and 28 deletions
|
|
@ -1703,6 +1703,13 @@ A+B</textarea>
|
|||
<option value="true" data-i18n="design_wobble_allow"></option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span data-i18n="design_fixed_target_policy"></span>
|
||||
<select id="designFixedTargetPolicy">
|
||||
<option value="exclude_from_optimization" data-i18n="design_fixed_target_exclude"></option>
|
||||
<option value="include" data-i18n="design_fixed_target_include"></option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="toggle-row" id="designTabToggle">
|
||||
<button class="secondary panel-toggle active" type="button" data-design-tab="targets" data-i18n="design_tab_targets"></button>
|
||||
|
|
@ -2221,6 +2228,9 @@ A+B</textarea>
|
|||
design_wobble_label: "Wobble mutations",
|
||||
design_wobble_allow: "允许",
|
||||
design_wobble_prohibit: "禁止",
|
||||
design_fixed_target_policy: "固定目标策略",
|
||||
design_fixed_target_exclude: "剥离出优化",
|
||||
design_fixed_target_include: "参与优化",
|
||||
design_tab_targets: "Target Tubes",
|
||||
design_tab_hard: "Hard Constraints",
|
||||
design_tab_soft: "Soft Constraints",
|
||||
|
|
@ -2440,6 +2450,7 @@ A+B</textarea>
|
|||
design_ensemble_defect: "Ensemble defect",
|
||||
design_trials_used: "试验数",
|
||||
design_seed: "最佳种子",
|
||||
design_fixed_excluded: "固定目标剥离",
|
||||
design_constraint: "约束",
|
||||
design_definition: "输入定义",
|
||||
design_sequence: "设计序列",
|
||||
|
|
@ -2568,6 +2579,9 @@ A+B</textarea>
|
|||
design_wobble_label: "Wobble Mutations",
|
||||
design_wobble_allow: "Allow",
|
||||
design_wobble_prohibit: "Prohibit",
|
||||
design_fixed_target_policy: "Fixed Target Policy",
|
||||
design_fixed_target_exclude: "Exclude from Optimization",
|
||||
design_fixed_target_include: "Include in Optimization",
|
||||
design_tab_targets: "Target Tubes",
|
||||
design_tab_hard: "Hard Constraints",
|
||||
design_tab_soft: "Soft Constraints",
|
||||
|
|
@ -2787,6 +2801,7 @@ A+B</textarea>
|
|||
design_ensemble_defect: "Ensemble Defect",
|
||||
design_trials_used: "Trials",
|
||||
design_seed: "Best Seed",
|
||||
design_fixed_excluded: "Fixed Targets Excluded",
|
||||
design_constraint: "Constraint",
|
||||
design_definition: "Input Definition",
|
||||
design_sequence: "Designed Sequence",
|
||||
|
|
@ -3803,9 +3818,14 @@ A+B</textarea>
|
|||
const result = entry?.result && typeof entry.result === "object" ? entry.result : null;
|
||||
return {
|
||||
id: String(entry.id || entry.job_id || `${Date.now()}-${index}-${Math.random().toString(16).slice(2)}`),
|
||||
job_id: entry.job_id || null,
|
||||
status: entry.status || (result ? "success" : "input_only"),
|
||||
created_at: entry.created_at_iso || entry.created_at || new Date().toISOString(),
|
||||
updated_at: entry.updated_at || null,
|
||||
elapsed_seconds: entry.elapsed_seconds ?? null,
|
||||
payload,
|
||||
result,
|
||||
error: entry.error || null,
|
||||
result_summary: buildHistorySummary(payload, entry.result_summary || {}),
|
||||
};
|
||||
}
|
||||
|
|
@ -4050,6 +4070,7 @@ A+B</textarea>
|
|||
document.getElementById("designSeed").value = payload.design?.seed ?? 0;
|
||||
document.getElementById("designWobble").value = String(payload.design?.wobble_mutations ?? false);
|
||||
document.getElementById("designMaxTimeHours").value = ((payload.design?.max_time_seconds ?? 0) / 3600);
|
||||
document.getElementById("designFixedTargetPolicy").value = payload.design?.fixed_target_policy ?? "exclude_from_optimization";
|
||||
const payloadCompute = Array.isArray(payload.compute) ? payload.compute : [];
|
||||
document.querySelectorAll(".check input").forEach((input) => {
|
||||
input.checked = payloadCompute.includes(input.value);
|
||||
|
|
@ -4094,28 +4115,50 @@ A+B</textarea>
|
|||
} else {
|
||||
lastPayload = payload;
|
||||
lastResult = null;
|
||||
renderEmptyState();
|
||||
if (["queued", "running", "cancel_requested"].includes(item.status)) {
|
||||
const label = item.status === "queued"
|
||||
? t("status_queued")
|
||||
: (item.status === "cancel_requested" ? t("status_canceling") : t("status_polling"));
|
||||
results.innerHTML = `<div class="result-card"><h3>${escapeHtml(label)}</h3><p>${t("history_job_id")}: ${escapeHtml(item.job_id || item.id || "-")}</p></div>`;
|
||||
setStatus(formatStatus(label));
|
||||
} else {
|
||||
renderEmptyState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sharedJobIsActive(item) {
|
||||
return ["queued", "running", "cancel_requested"].includes(item?.status);
|
||||
}
|
||||
|
||||
async function fetchSharedItem(shareId, { poll = false } = {}) {
|
||||
const suffix = poll ? "?poll=1" : "";
|
||||
const { response, data } = await fetchJsonOrThrow(`/api/shares/${encodeURIComponent(shareId)}${suffix}`);
|
||||
if (!response.ok || data.status !== "success") {
|
||||
throw new Error(data?.error || `Share request failed with HTTP ${response.status}`);
|
||||
}
|
||||
const item = normalizeHistoryEntry(data.share, 0);
|
||||
if (!item) throw new Error("Shared record is invalid.");
|
||||
return item;
|
||||
}
|
||||
|
||||
async function loadSharedHistoryFromUrl() {
|
||||
const pathMatch = window.location.pathname.match(/^\/share\/([A-Za-z0-9_-]{8,128})$/);
|
||||
const shareId = pathMatch?.[1] || new URLSearchParams(window.location.search).get("share");
|
||||
if (!shareId) return;
|
||||
document.body.classList.add("share-mode");
|
||||
try {
|
||||
const { response, data } = await fetchJsonOrThrow(`/api/shares/${encodeURIComponent(shareId)}`);
|
||||
if (!response.ok || data.status !== "success") {
|
||||
throw new Error(data?.error || `Share request failed with HTTP ${response.status}`);
|
||||
}
|
||||
const item = normalizeHistoryEntry(data.share, 0);
|
||||
if (!item) throw new Error("Shared record is invalid.");
|
||||
item.error = data.share.error || null;
|
||||
let item = await fetchSharedItem(shareId);
|
||||
applyHistoryItem(item);
|
||||
document.querySelectorAll(".control-panel input, .control-panel select, .control-panel textarea, .control-panel button").forEach((node) => {
|
||||
if (!node.closest(".toolbar") && !node.matches("[data-design-tab]")) node.disabled = true;
|
||||
});
|
||||
setStatus(formatStatus(t("history_shared_loaded")));
|
||||
while (sharedJobIsActive(item)) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1500));
|
||||
item = await fetchSharedItem(shareId, { poll: true });
|
||||
applyHistoryItem(item);
|
||||
}
|
||||
} catch (error) {
|
||||
setStatus(`${t("history_share_failed")}: ${error.message}`, true);
|
||||
}
|
||||
|
|
@ -4133,7 +4176,7 @@ A+B</textarea>
|
|||
<div class="compact-actions">
|
||||
<button class="secondary" data-history-load="${item.job_id}" type="button">${t("history_load")}</button>
|
||||
<button class="secondary" data-history-export="${item.job_id}" type="button">${t("history_export_one")}</button>
|
||||
${["success", "error", "input_only", "canceled"].includes(item.status) ? `<button class="secondary" data-history-share="${item.job_id}" type="button">${t("history_share")}</button>` : ""}
|
||||
<button class="secondary" data-history-share="${item.job_id}" type="button">${t("history_share")}</button>
|
||||
${["queued", "running", "cancel_requested"].includes(item.status) ? "" : `<button class="secondary" data-history-delete="${item.job_id}" type="button">${t("history_delete")}</button>`}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -4329,6 +4372,7 @@ A+B</textarea>
|
|||
seed: Number(document.getElementById("designSeed").value),
|
||||
wobble_mutations: document.getElementById("designWobble").value === "true",
|
||||
max_time_seconds: Math.round(Number(document.getElementById("designMaxTimeHours").value || 0) * 3600),
|
||||
fixed_target_policy: document.getElementById("designFixedTargetPolicy").value,
|
||||
},
|
||||
hard_constraints: getHardConstraints(),
|
||||
soft_constraints: getSoftConstraints(),
|
||||
|
|
@ -4519,6 +4563,7 @@ A+B</textarea>
|
|||
|
||||
function renderDesignSummaryCard(result) {
|
||||
const stats = result.design?.stats || {};
|
||||
const excludedFixedCount = result.design?.optimization?.excluded_fixed_targets?.length || 0;
|
||||
return `
|
||||
<div class="result-card">
|
||||
<h3>${t("design_summary_card")}</h3>
|
||||
|
|
@ -4526,6 +4571,7 @@ A+B</textarea>
|
|||
<div><strong>${t("design_ensemble_defect")}</strong><span class="metric-value">${Number(result.design?.ensemble_defect || 0).toFixed(6)}</span></div>
|
||||
<div><strong>${t("design_trials_used")}</strong><span class="metric-value">${result.options?.trials ?? 1}</span></div>
|
||||
<div><strong>${t("design_seed")}</strong><span class="metric-value">${stats.seed ?? "-"}</span></div>
|
||||
<div><strong>${t("design_fixed_excluded")}</strong><span class="metric-value">${excludedFixedCount}</span></div>
|
||||
<div><strong>${t("summary_elapsed")}</strong><span class="metric-value">${stats.design_time ? `${Number(stats.design_time).toFixed(3)} s` : "-"}</span></div>
|
||||
</div>
|
||||
<div class="compact-actions" style="margin-top: 12px;">
|
||||
|
|
@ -6130,6 +6176,7 @@ A+B</textarea>
|
|||
document.getElementById("designSeed").value = example.design?.seed ?? 0;
|
||||
document.getElementById("designWobble").value = String(example.design?.wobble_mutations ?? false);
|
||||
document.getElementById("designMaxTimeHours").value = ((example.design?.max_time_seconds ?? 0) / 3600);
|
||||
document.getElementById("designFixedTargetPolicy").value = example.design?.fixed_target_policy ?? "exclude_from_optimization";
|
||||
document.getElementById("complexesText").value = example.complexes_text;
|
||||
const exampleCompute = Array.isArray(example.compute) ? example.compute : [];
|
||||
document.querySelectorAll(".check input").forEach((input) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue