feat: tailor 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-06 07:30:32 +08:00
parent 571be69571
commit ec35927fa5
3 changed files with 71 additions and 11 deletions

View File

@@ -4,6 +4,12 @@
## 2026-04-05
### 直播录制表单开始按当前项目和平台推荐默认标题与导入样例
- `新增录制源` 现在会按当前项目和当前平台自动带出更合理的默认录制名称,不再每次都从空白标题开始。
- `编辑录制源` 的占位标题也会跟着当前项目和平台变化,方便快速补齐那些原本没有手工命名的录制源。
- `导入 URL 配置` 会按当前偏好平台切换导入样例和说明文案,让抖音/快手场景在第一眼看到的例子就更贴近当前工作流。
### 导入主页、导入当前对标、加入跟踪表单补齐上下文摘要
- `导入主页 / 导入当前对标 / 加入跟踪` 这三张仍需用户补信息的表单,现在和 `导入作品 / 导入文本 / 上传视频` 一样,都会在顶部展示 `当前项目 / 默认 Agent / 默认知识库` 的上下文摘要。

View File

@@ -444,6 +444,30 @@ function recommendRealCutObjective(sourceJob) {
return "保留高信息密度片段,输出适合短视频平台的粗剪结果";
}
function recommendLiveRecorderTitle(project, platform) {
const normalized = normalizePlatformValue(platform, "kuaishou");
const projectName = String(project?.name || "").trim();
const platformName = platformLabel(normalized);
if (projectName) return `${brief(projectName, 12)} · ${platformName}直播跟踪`;
return `${platformName}直播跟踪`;
}
function recommendLiveRecorderImportSamples(platform) {
const normalized = normalizePlatformValue(platform, "kuaishou");
if (normalized === "douyin") {
return [
"https://live.douyin.com/1234567890",
"# 关闭的源会以 # 开头",
"原画, https://live.douyin.com/9988776655, 抖音主场跟踪"
].join("\n");
}
return [
"https://live.kuaishou.com/u/abcdef",
"# 关闭的源会以 # 开头",
"高清, https://live.kuaishou.com/u/abcdef, 快手主场跟踪"
].join("\n");
}
function formatDateTime(value) {
if (!value) return "-";
const date = new Date(value);
@@ -11605,6 +11629,9 @@ function openLiveRecorderCreateAction() {
const status = getIntegrationDetail("live_recorder");
const project = getSelectedProject() || appState.dashboard?.projects?.[0] || null;
const assistants = getAssistantOptions(project?.id || "");
const defaultAssistantId = getSelectedAssistant()?.id || assistants[0]?.value || "";
const defaultPlatform = normalizePlatformValue(getPreferredPlatform(), "kuaishou");
const defaultTitle = recommendLiveRecorderTitle(project, defaultPlatform);
openActionModal({
title: "新增录制源",
description: status.reachable
@@ -11612,11 +11639,12 @@ function openLiveRecorderCreateAction() {
: "当前 NAS 录制服务不可达,先检查集成健康。",
submitLabel: "保存录制源",
fields: [
{ name: "context", label: "当前上下文", type: "html", html: renderIntakeActionContextHtml(project?.id || "", defaultAssistantId) },
{ type: "html", label: "当前租户", html: renderLiveRecorderSummaryHtml() },
{ name: "projectId", label: "归属项目", type: "select", value: project?.id || "", options: getProjectOptions() },
{ name: "assistantId", label: "关联 Agent", type: "select", value: assistants[0]?.value || "", options: [{ value: "", label: "暂不绑定" }, ...assistants] },
{ name: "platform", label: "平台", type: "select", value: "kuaishou", options: getPlatformOptions() },
{ name: "title", label: "录制名称", placeholder: "例如A 类目直播跟踪" },
{ name: "assistantId", label: "关联 Agent", type: "select", value: defaultAssistantId, options: [{ value: "", label: "暂不绑定" }, ...assistants] },
{ name: "platform", label: "平台", type: "select", value: defaultPlatform, options: getPlatformOptions() },
{ name: "title", label: "录制名称", value: defaultTitle, placeholder: defaultTitle },
{ name: "quality", label: "清晰度", type: "select", value: "原画", options: ["原画", "蓝光", "超清", "高清", "标清", "流畅"].map((item) => ({ value: item, label: item })) },
{ name: "sourceUrl", label: "直播源", type: "url", placeholder: "https://..." },
{ name: "autoStart", label: "导入后立即开始", type: "checkbox", value: true }
@@ -11659,11 +11687,14 @@ function openLiveRecorderSourceAction(sourceId) {
}
const currentProject = getSelectedProject() || safeArray(appState.dashboard?.projects).find((item) => item.id === source.project_id) || appState.dashboard?.projects?.[0] || null;
const assistants = getAssistantOptions(currentProject?.id || source.project_id || "");
const defaultAssistantId = source.assistant_id || getSelectedAssistant()?.id || assistants[0]?.value || "";
const titlePlaceholder = recommendLiveRecorderTitle(currentProject, source.platform || "kuaishou");
openActionModal({
title: "编辑录制源",
description: "可以更新项目归属、Agent、标题、清晰度和启停状态链接本身若要变更请删除后重建。",
submitLabel: "保存修改",
fields: [
{ name: "context", label: "当前上下文", type: "html", html: renderIntakeActionContextHtml(currentProject?.id || source.project_id || "", defaultAssistantId) },
{
type: "html",
label: "源信息",
@@ -11682,8 +11713,8 @@ function openLiveRecorderSourceAction(sourceId) {
`
},
{ name: "projectId", label: "归属项目", type: "select", value: source.project_id || currentProject?.id || "", options: getProjectOptions() },
{ name: "assistantId", label: "关联 Agent", type: "select", value: source.assistant_id || "", options: [{ value: "", label: "暂不绑定" }, ...assistants] },
{ name: "title", label: "录制名称", value: source.title || "", placeholder: "例如A 类目直播跟踪" },
{ name: "assistantId", label: "关联 Agent", type: "select", value: defaultAssistantId, options: [{ value: "", label: "暂不绑定" }, ...assistants] },
{ name: "title", label: "录制名称", value: source.title || "", placeholder: titlePlaceholder },
{ name: "quality", label: "清晰度", type: "select", value: source.quality || "原画", options: ["原画", "蓝光", "超清", "高清", "标清", "流畅"].map((item) => ({ value: item, label: item })) },
{ name: "enabled", label: "启用录制源", type: "checkbox", value: Boolean(source.enabled) }
],
@@ -11706,16 +11737,17 @@ function openLiveRecorderSourceAction(sourceId) {
}
function openLiveRecorderImportAction() {
const samples = [
"https://live.douyin.com/1234567890",
"# 关闭的源会以 # 开头",
"高清, https://live.kuaishou.com/u/abcdef, 测试录制源"
].join("\n");
const project = getSelectedProject() || appState.dashboard?.projects?.[0] || null;
const assistants = getAssistantOptions(project?.id || "");
const defaultAssistantId = getSelectedAssistant()?.id || assistants[0]?.value || "";
const defaultPlatform = normalizePlatformValue(getPreferredPlatform(), "kuaishou");
const samples = recommendLiveRecorderImportSamples(defaultPlatform);
openActionModal({
title: "导入 URL 配置",
description: "按行粘贴直播源,支持用逗号附带清晰度和标题,注释行会被视为停用源。",
description: `按行粘贴${platformLabel(defaultPlatform)}直播源,支持用逗号附带清晰度和标题,注释行会被视为停用源。`,
submitLabel: "导入并同步",
fields: [
{ name: "context", label: "当前上下文", type: "html", html: renderIntakeActionContextHtml(project?.id || "", defaultAssistantId) },
{
name: "raw",
label: "配置文本",

View File

@@ -1145,6 +1145,9 @@ test("input-heavy intake sheets surface current context and smarter defaults", (
const generateCopy = extractBetween(APP, "function openGenerateCopyAction(defaults = {})", "function openCreateAiVideoAction(defaults = {})");
const createAiVideo = extractBetween(APP, "function openCreateAiVideoAction(defaults = {})", "function openCreateRealCutAction(defaults = {})");
const createRealCut = extractBetween(APP, "function openCreateRealCutAction(defaults = {})", "function openLiveRecorderAction()");
const liveRecorderCreate = extractBetween(APP, "function openLiveRecorderCreateAction()", "function openLiveRecorderSourceAction(sourceId)");
const liveRecorderSource = extractBetween(APP, "function openLiveRecorderSourceAction(sourceId)", "function openLiveRecorderImportAction()");
const liveRecorderImport = extractBetween(APP, "function openLiveRecorderImportAction()", "async function toggleLiveRecorderSourceAction(");
const reviewAction = extractBetween(APP, "function openReviewAction(defaults = {})", "document.addEventListener(\"click\", async (event) => {");
assert.match(APP, /function renderIntakeActionContextHtml\(/);
assert.match(APP, /function renderSourceJobContextHtml\(job\)/);
@@ -1155,6 +1158,8 @@ test("input-heavy intake sheets surface current context and smarter defaults", (
assert.match(APP, /function recommendAiVideoShotDuration\(sourceJob\)/);
assert.match(APP, /function recommendDerivativeJobTitle\(sourceJob, suffix, fallback\)/);
assert.match(APP, /function recommendRealCutObjective\(sourceJob\)/);
assert.match(APP, /function recommendLiveRecorderTitle\(project, platform\)/);
assert.match(APP, /function recommendLiveRecorderImportSamples\(platform\)/);
assert.match(importHomepage, /label: "当前上下文", type: "html"/);
assert.match(importHomepage, /const defaultAssistantId = getSelectedAssistant\(\)\?\.id \|\| assistants\[0\]\?\.value \|\| ""/);
assert.match(importHomepage, /renderIntakeActionContextHtml\(project\.id, defaultAssistantId\)/);
@@ -1199,6 +1204,23 @@ test("input-heavy intake sheets surface current context and smarter defaults", (
assert.match(createRealCut, /value: defaults\.targetDurationSec \|\| recommendRealCutDuration\(sourceJob\)/);
assert.match(createRealCut, /recommendAspectRatioForPlatform\(defaultPlatform\)/);
assert.match(createRealCut, /value: defaults\.objective \|\| recommendRealCutObjective\(sourceJob\)/);
assert.match(liveRecorderCreate, /label: "当前上下文", type: "html"/);
assert.match(liveRecorderCreate, /const defaultAssistantId = getSelectedAssistant\(\)\?\.id \|\| assistants\[0\]\?\.value \|\| ""/);
assert.match(liveRecorderCreate, /const defaultPlatform = normalizePlatformValue\(getPreferredPlatform\(\), "kuaishou"\)/);
assert.match(liveRecorderCreate, /const defaultTitle = recommendLiveRecorderTitle\(project, defaultPlatform\)/);
assert.match(liveRecorderCreate, /renderIntakeActionContextHtml\(project\?\.id \|\| "", defaultAssistantId\)/);
assert.match(liveRecorderCreate, /value: defaultTitle, placeholder: defaultTitle/);
assert.match(liveRecorderSource, /label: "当前上下文", type: "html"/);
assert.match(liveRecorderSource, /const defaultAssistantId = source\.assistant_id \|\| getSelectedAssistant\(\)\?\.id \|\| assistants\[0\]\?\.value \|\| ""/);
assert.match(liveRecorderSource, /const titlePlaceholder = recommendLiveRecorderTitle\(currentProject, source\.platform \|\| "kuaishou"\)/);
assert.match(liveRecorderSource, /renderIntakeActionContextHtml\(currentProject\?\.id \|\| source\.project_id \|\| "", defaultAssistantId\)/);
assert.match(liveRecorderSource, /placeholder: titlePlaceholder/);
assert.match(liveRecorderImport, /label: "当前上下文", type: "html"/);
assert.match(liveRecorderImport, /const defaultAssistantId = getSelectedAssistant\(\)\?\.id \|\| assistants\[0\]\?\.value \|\| ""/);
assert.match(liveRecorderImport, /const defaultPlatform = normalizePlatformValue\(getPreferredPlatform\(\), "kuaishou"\)/);
assert.match(liveRecorderImport, /const samples = recommendLiveRecorderImportSamples\(defaultPlatform\)/);
assert.match(liveRecorderImport, /renderIntakeActionContextHtml\(project\?\.id \|\| "", defaultAssistantId\)/);
assert.match(liveRecorderImport, /按行粘贴\$\{platformLabel\(defaultPlatform\)\}直播源/);
assert.match(reviewAction, /label: "当前上下文", type: "html"/);
assert.match(reviewAction, /const defaultAssistantId = getSelectedAssistant\(\)\?\.id \|\| assistants\[0\]\?\.value \|\| ""/);
assert.match(reviewAction, /renderIntakeActionContextHtml\(project\.id, defaultAssistantId\)/);