feat: refresh live recorder sheet defaults
Some checks failed
StoryForge CI / Baseline checks (push) Has been cancelled
StoryForge CI / Backend tests (push) Has been cancelled
StoryForge CI / Web tests (push) Has been cancelled

This commit is contained in:
kris
2026-04-07 12:57:00 +08:00
parent 76affab96b
commit cc58e2f03d

View File

@@ -654,6 +654,93 @@ function bindLiveRecorderSheetRecommendations(fields, options = {}) {
sync(); sync();
} }
function bindLiveRecorderSheetRecommendations(fields, options = {}) {
const projectSelect = fields.querySelector('[data-action-field="projectId"]');
const assistantSelect = fields.querySelector('[data-action-field="assistantId"]');
const platformSelect = fields.querySelector('[data-action-field="platform"]');
const titleInput = fields.querySelector('[data-action-field="title"]');
const rawTextarea = fields.querySelector('[data-action-field="raw"]');
const contextHtml = fields.querySelector('[data-action-field="context"] .sheet-html');
const defaultPlatform = options.defaultPlatform || "kuaishou";
const defaultAssistantId = options.defaultAssistantId || "";
const keepAutoValue = (field, value) => {
if (!(field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement) || !String(value || "").trim()) return;
field.placeholder = String(value);
if (field.dataset.recommendationMode === "manual") return;
field.dataset.recommendationApplying = "1";
field.value = String(value);
field.dataset.recommendationMode = "auto";
delete field.dataset.recommendationApplying;
};
const bindManualEscape = (field) => {
if (!(field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement)) return;
field.dataset.recommendationMode = field.dataset.recommendationMode || "auto";
field.addEventListener("input", () => {
if (field.dataset.recommendationApplying === "1") return;
field.dataset.recommendationMode = "manual";
});
};
bindManualEscape(titleInput);
bindManualEscape(rawTextarea);
const getProject = () => {
const projectId = projectSelect instanceof HTMLSelectElement ? projectSelect.value : "";
return safeArray(appState.dashboard?.projects).find((item) => item.id === projectId)
|| getSelectedProject()
|| null;
};
const getPlatform = () => normalizePlatformValue(
platformSelect instanceof HTMLSelectElement ? platformSelect.value : getPreferredPlatform(),
defaultPlatform
);
const syncAssistantOptions = () => {
if (!(assistantSelect instanceof HTMLSelectElement) || !(projectSelect instanceof HTMLSelectElement)) return;
const currentValue = assistantSelect.value || "";
const assistants = getAssistantOptions(projectSelect.value || "");
const fallbackValue = assistants.some((item) => item.value === currentValue)
? currentValue
: assistants.some((item) => item.value === defaultAssistantId)
? defaultAssistantId
: assistants[0]?.value || "";
assistantSelect.innerHTML = [{ value: "", label: "暂不绑定" }, ...assistants].map((item) => `
<option value="${escapeHtml(item.value)}">${escapeHtml(item.label)}</option>
`).join("");
assistantSelect.value = fallbackValue;
};
const syncContext = () => {
if (!(contextHtml instanceof HTMLElement)) return;
const project = getProject();
const assistantId = assistantSelect instanceof HTMLSelectElement ? assistantSelect.value : defaultAssistantId;
contextHtml.innerHTML = renderIntakeActionContextHtml(project?.id || "", assistantId);
};
const syncTitle = () => {
const project = getProject();
const platform = getPlatform();
const recommended = recommendLiveRecorderTitle(project, platform);
if (titleInput instanceof HTMLInputElement) {
keepAutoValue(titleInput, recommended);
}
};
const syncRawSamples = () => {
if (!(rawTextarea instanceof HTMLTextAreaElement)) return;
keepAutoValue(rawTextarea, recommendLiveRecorderImportSamples(getPlatform()));
};
const syncDescription = () => {
if (!(options.description instanceof HTMLElement)) return;
options.description.textContent = `按行粘贴${platformLabel(getPlatform())}直播源,支持用逗号附带清晰度和标题,注释行会被视为停用源。`;
};
const sync = () => {
syncAssistantOptions();
syncContext();
syncTitle();
syncRawSamples();
syncDescription();
};
projectSelect?.addEventListener("change", sync);
assistantSelect?.addEventListener("change", syncContext);
platformSelect?.addEventListener("change", sync);
sync();
}
function formatDateTime(value) { function formatDateTime(value) {
if (!value) return "-"; if (!value) return "-";
const date = new Date(value); const date = new Date(value);
@@ -11949,7 +12036,7 @@ function openLiveRecorderCreateAction() {
{ name: "autoStart", label: "导入后立即开始", type: "checkbox", value: true } { name: "autoStart", label: "导入后立即开始", type: "checkbox", value: true }
], ],
onOpen: ({ fields }) => { onOpen: ({ fields }) => {
bindLiveRecorderSheetRecommendations(fields, { defaultPlatform }); bindLiveRecorderSheetRecommendations(fields, { defaultPlatform, defaultAssistantId });
}, },
onSubmit: async (values) => { onSubmit: async (values) => {
if (!values.sourceUrl?.trim()) throw new Error("请填写直播源链接"); if (!values.sourceUrl?.trim()) throw new Error("请填写直播源链接");
@@ -12021,7 +12108,10 @@ function openLiveRecorderSourceAction(sourceId) {
{ name: "enabled", label: "启用录制源", type: "checkbox", value: Boolean(source.enabled) } { name: "enabled", label: "启用录制源", type: "checkbox", value: Boolean(source.enabled) }
], ],
onOpen: ({ fields }) => { onOpen: ({ fields }) => {
bindLiveRecorderSheetRecommendations(fields, { defaultPlatform: source.platform || "kuaishou" }); bindLiveRecorderSheetRecommendations(fields, {
defaultPlatform: source.platform || "kuaishou",
defaultAssistantId
});
}, },
onSubmit: async (values) => { onSubmit: async (values) => {
const saved = await storyforgeFetch(`/v2/live-recorder/sources/${encodeURIComponent(source.id)}`, { const saved = await storyforgeFetch(`/v2/live-recorder/sources/${encodeURIComponent(source.id)}`, {
@@ -12064,18 +12154,7 @@ function openLiveRecorderImportAction() {
} }
], ],
onOpen: ({ fields, description }) => { onOpen: ({ fields, description }) => {
bindLiveRecorderSheetRecommendations(fields, { defaultPlatform }); bindLiveRecorderSheetRecommendations(fields, { defaultPlatform, description });
const platformSelect = fields.querySelector('[data-action-field="platform"]');
const syncDescription = () => {
if (!(description instanceof HTMLElement)) return;
const platform = normalizePlatformValue(
platformSelect instanceof HTMLSelectElement ? platformSelect.value : getPreferredPlatform(),
defaultPlatform
);
description.textContent = `按行粘贴${platformLabel(platform)}直播源,支持用逗号附带清晰度和标题,注释行会被视为停用源。`;
};
platformSelect?.addEventListener("change", syncDescription);
syncDescription();
}, },
onSubmit: async (values) => { onSubmit: async (values) => {
if (!String(values.raw || "").trim()) throw new Error("请先粘贴配置文本"); if (!String(values.raw || "").trim()) throw new Error("请先粘贴配置文本");