fix: bug
This commit is contained in:
@@ -1,5 +1,16 @@
|
||||
const $ = (id) => document.getElementById(id);
|
||||
|
||||
function renderBodyPreview() {
|
||||
const raw = ($("body") && $("body").value) || "";
|
||||
const el = $("bodyPreview");
|
||||
if (!el) return;
|
||||
if (typeof marked !== "undefined" && marked.parse) {
|
||||
el.innerHTML = marked.parse(raw, { breaks: true });
|
||||
} else {
|
||||
el.textContent = raw;
|
||||
}
|
||||
}
|
||||
|
||||
const statusEl = $("status");
|
||||
const rewriteBtn = $("rewriteBtn");
|
||||
const wechatBtn = $("wechatBtn");
|
||||
@@ -13,6 +24,7 @@ function updateCounters() {
|
||||
$("sourceCount").textContent = `${countText($("sourceText").value)} 字`;
|
||||
$("summaryCount").textContent = `${countText($("summary").value)} 字`;
|
||||
$("bodyCount").textContent = `${countText($("body").value)} 字`;
|
||||
renderBodyPreview();
|
||||
}
|
||||
|
||||
function setLoading(button, loading, idleText, loadingText) {
|
||||
@@ -34,9 +46,36 @@ async function postJSON(url, body) {
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.detail || "请求失败");
|
||||
data._requestId = res.headers.get("X-Request-ID") || "";
|
||||
return data;
|
||||
}
|
||||
|
||||
function renderTrace(trace, headerRid) {
|
||||
const wrap = $("traceWrap");
|
||||
const pre = $("traceJson");
|
||||
const badge = $("traceBadge");
|
||||
if (!pre || !wrap) return;
|
||||
|
||||
if (!trace || Object.keys(trace).length === 0) {
|
||||
pre.textContent = headerRid
|
||||
? JSON.stringify({ request_id: headerRid, note: "响应中无 trace 字段" }, null, 2)
|
||||
: "(尚无数据)完成一次「AI 改写」后,这里会显示请求 ID、耗时、质检与降级原因。";
|
||||
if (badge) badge.textContent = "";
|
||||
return;
|
||||
}
|
||||
|
||||
const merged = { ...trace };
|
||||
if (headerRid && !merged.request_id) merged.request_id = headerRid;
|
||||
pre.textContent = JSON.stringify(merged, null, 2);
|
||||
|
||||
const mode = merged.mode || "";
|
||||
if (badge) {
|
||||
badge.textContent = mode === "ai" ? "AI" : mode === "fallback" ? "保底" : "";
|
||||
badge.className = "trace-badge " + (mode === "ai" ? "is-ai" : mode === "fallback" ? "is-fallback" : "");
|
||||
}
|
||||
wrap.open = true;
|
||||
}
|
||||
|
||||
$("rewriteBtn").addEventListener("click", async () => {
|
||||
const sourceText = $("sourceText").value.trim();
|
||||
if (sourceText.length < 20) {
|
||||
@@ -59,11 +98,22 @@ $("rewriteBtn").addEventListener("click", async () => {
|
||||
$("summary").value = data.summary || "";
|
||||
$("body").value = data.body_markdown || "";
|
||||
updateCounters();
|
||||
renderTrace(data.trace, data._requestId);
|
||||
const tr = data.trace || {};
|
||||
const modelLine = tr.model ? `模型 ${tr.model}` : "";
|
||||
if (data.mode === "fallback") {
|
||||
const note = (data.quality_notes || [])[0] || "当前为保底改写稿";
|
||||
setStatus(`改写完成(保底模式):${note}`, true);
|
||||
setStatus(
|
||||
`改写完成(保底模式,未使用或未通过千问长文):${note}${modelLine ? ` · ${modelLine}` : ""}`,
|
||||
true
|
||||
);
|
||||
} else if (tr.quality_soft_accept) {
|
||||
setStatus(
|
||||
`改写完成(AI,质检提示):${(data.quality_notes || []).join(";") || "见 quality_notes"} · ${modelLine || "AI"}`
|
||||
);
|
||||
statusEl.style.color = "#9a3412";
|
||||
} else {
|
||||
setStatus("改写完成,可直接发布。");
|
||||
setStatus(`改写完成(AI 洗稿)${modelLine ? ` · ${modelLine}` : ""}`);
|
||||
}
|
||||
} catch (e) {
|
||||
setStatus(`改写失败: ${e.message}`, true);
|
||||
@@ -111,4 +161,32 @@ $("imBtn").addEventListener("click", async () => {
|
||||
$(id).addEventListener("input", updateCounters);
|
||||
});
|
||||
|
||||
async function loadBackendConfig() {
|
||||
const el = $("backendConfig");
|
||||
if (!el) return;
|
||||
try {
|
||||
const res = await fetch("/api/config");
|
||||
const c = await res.json();
|
||||
if (!c.openai_configured) {
|
||||
el.textContent =
|
||||
"后端未配置 OPENAI_API_KEY:改写将使用本地保底稿,千问不会参与。请在 .env 中配置并重启容器。";
|
||||
el.style.color = "#b42318";
|
||||
return;
|
||||
}
|
||||
const name =
|
||||
c.provider === "dashscope"
|
||||
? "通义千问(DashScope 兼容接口)"
|
||||
: "OpenAI 兼容接口";
|
||||
const host = c.base_url_host ? ` · ${c.base_url_host}` : "";
|
||||
const to = c.openai_timeout_sec != null ? ` · 单轮最长等待 ${c.openai_timeout_sec}s` : "";
|
||||
el.textContent = `已接入:${c.openai_model} · ${name}${host}${to}`;
|
||||
el.style.color = "";
|
||||
} catch (e) {
|
||||
el.textContent = "无法读取 /api/config(请确认服务已启动)";
|
||||
el.style.color = "#b42318";
|
||||
}
|
||||
}
|
||||
|
||||
loadBackendConfig();
|
||||
updateCounters();
|
||||
renderTrace(null, "");
|
||||
|
||||
@@ -38,6 +38,11 @@ body {
|
||||
margin: 6px 0 0;
|
||||
}
|
||||
|
||||
.backend-config {
|
||||
margin: 8px 0 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.badge {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
@@ -161,11 +166,130 @@ button:disabled {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 13px;
|
||||
margin: 0 0 12px;
|
||||
}
|
||||
|
||||
.flow-hint {
|
||||
margin: 0 0 14px 18px;
|
||||
padding: 0;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.trace-wrap {
|
||||
margin-top: 12px;
|
||||
padding: 10px 12px;
|
||||
border: 1px dashed var(--line);
|
||||
border-radius: 10px;
|
||||
background: #f9fbf9;
|
||||
}
|
||||
|
||||
.trace-wrap summary {
|
||||
cursor: pointer;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.trace-badge {
|
||||
margin-left: 8px;
|
||||
font-size: 11px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 999px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.trace-badge.is-ai {
|
||||
background: #eaf7f0;
|
||||
color: #0f5f3d;
|
||||
border: 1px solid #cde6d7;
|
||||
}
|
||||
|
||||
.trace-badge.is-fallback {
|
||||
background: #fff4e6;
|
||||
color: #9a3412;
|
||||
border: 1px solid #fed7aa;
|
||||
}
|
||||
|
||||
.body-split {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 12px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.body-split textarea {
|
||||
min-height: 280px;
|
||||
}
|
||||
|
||||
.preview-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.markdown-preview {
|
||||
flex: 1;
|
||||
min-height: 280px;
|
||||
max-height: 480px;
|
||||
overflow: auto;
|
||||
padding: 12px 14px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 10px;
|
||||
background: #fafcfb;
|
||||
font-size: 14px;
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
.markdown-preview h2 {
|
||||
font-size: 1.15rem;
|
||||
margin: 1em 0 0.5em;
|
||||
color: var(--accent-2);
|
||||
}
|
||||
|
||||
.markdown-preview h3 {
|
||||
font-size: 1.05rem;
|
||||
margin: 0.9em 0 0.4em;
|
||||
}
|
||||
|
||||
.markdown-preview p {
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
.markdown-preview ul,
|
||||
.markdown-preview ol {
|
||||
margin: 0.4em 0 0.6em 1.2em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.markdown-preview li {
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
|
||||
.trace-json {
|
||||
margin: 10px 0 0;
|
||||
padding: 10px;
|
||||
max-height: 220px;
|
||||
overflow: auto;
|
||||
font-size: 11px;
|
||||
line-height: 1.45;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--line);
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.layout {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.body-split {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
|
||||
Reference in New Issue
Block a user