feat: recommend smarter defaults for creative sheets
This commit is contained in:
@@ -21,6 +21,12 @@
|
||||
- `生成文案` 和 `写复盘` 也会优先继承来源任务的平台,避免用户再手工改一次平台。
|
||||
- 这样从任务详情或主 Agent 结果卡继续往下做时,表单第一眼就知道自己承接的是哪条任务。
|
||||
|
||||
### 高优先级创作表单开始自动推荐更合理的默认值
|
||||
|
||||
- `生成文案` 现在会按当前平台自动给出更合适的默认受众,而不再一律写成“创业者”。
|
||||
- `创建 AI 视频` 会按来源任务自动推荐风格、画幅和单镜头时长;`创建实拍剪辑` 会自动推荐目标时长和画幅。
|
||||
- 这样从主 Agent、任务详情或最近完成任务继续往下做时,表单默认值会更贴近当前任务本身,而不是每次都从通用模板起步。
|
||||
|
||||
### 主 Agent 抖音相似搜索与对标关系 live 修复
|
||||
|
||||
- 修复 `search-similar-accounts` / `save-benchmark-link` 在抖音 live 数据上错误按 `project_id` 查询账号导致的 500。
|
||||
|
||||
@@ -384,6 +384,52 @@ function renderSourceJobContextHtml(job) {
|
||||
`;
|
||||
}
|
||||
|
||||
function recommendAudienceForPlatform(platform) {
|
||||
const normalized = normalizePlatformValue(platform, "douyin");
|
||||
if (normalized === "bilibili") return "深度内容观众";
|
||||
if (normalized === "xiaohongshu") return "兴趣消费人群";
|
||||
if (normalized === "kuaishou") return "成交导向受众";
|
||||
if (normalized === "wechat_video") return "私域关系链用户";
|
||||
return "创业者";
|
||||
}
|
||||
|
||||
function recommendAspectRatioForPlatform(platform) {
|
||||
const normalized = normalizePlatformValue(platform, "douyin");
|
||||
return normalized === "bilibili" ? "16:9" : "9:16";
|
||||
}
|
||||
|
||||
function recommendCreativeStyle(sourceJob) {
|
||||
const style = String(sourceJob?.artifacts?.style || sourceJob?.style || "").trim();
|
||||
if (style) return style;
|
||||
if (String(sourceJob?.job_type || "").includes("review")) return "structured";
|
||||
return "realistic";
|
||||
}
|
||||
|
||||
function recommendRealCutDuration(sourceJob) {
|
||||
const candidate = Number(
|
||||
sourceJob?.artifacts?.target_duration_sec
|
||||
|| sourceJob?.artifacts?.duration
|
||||
|| sourceJob?.result?.target_duration_sec
|
||||
|| 0
|
||||
);
|
||||
if (Number.isFinite(candidate) && candidate > 0) {
|
||||
return Math.max(10, Math.min(300, Math.round(candidate)));
|
||||
}
|
||||
return 60;
|
||||
}
|
||||
|
||||
function recommendAiVideoShotDuration(sourceJob) {
|
||||
const candidate = Number(
|
||||
sourceJob?.artifacts?.duration
|
||||
|| sourceJob?.result?.duration
|
||||
|| 0
|
||||
);
|
||||
if (Number.isFinite(candidate) && candidate > 0) {
|
||||
return Math.max(3, Math.min(12, Math.round(candidate)));
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
|
||||
function formatDateTime(value) {
|
||||
if (!value) return "-";
|
||||
const date = new Date(value);
|
||||
@@ -11328,6 +11374,7 @@ function openGenerateCopyAction(defaults = {}) {
|
||||
const assistant = getSelectedAssistant() || requireSelectedAssistant();
|
||||
const sourceJob = defaults.sourceJob || null;
|
||||
const project = getSelectedProject();
|
||||
const defaultPlatform = normalizePlatformValue(defaults.platform || sourceJob?.platform || "douyin");
|
||||
openActionModal({
|
||||
title: "生成文案",
|
||||
description: "用当前 Agent 和知识库生成一版短视频文案。",
|
||||
@@ -11336,8 +11383,8 @@ function openGenerateCopyAction(defaults = {}) {
|
||||
{ name: "context", label: "当前上下文", type: "html", html: renderIntakeActionContextHtml(project?.id || "", assistant.id) },
|
||||
...(sourceJob ? [{ name: "sourceJobContext", label: "来源任务", type: "html", html: renderSourceJobContextHtml(sourceJob) }] : []),
|
||||
{ name: "brief", label: "创作需求", type: "textarea", rows: 5, value: defaults.brief || getJobSeedBrief(sourceJob), placeholder: "例如:给创业者写一条 60 字内的短视频开场文案" },
|
||||
{ name: "platform", label: "平台", type: "select", value: normalizePlatformValue(defaults.platform || sourceJob?.platform || "douyin"), options: getPlatformOptions() },
|
||||
{ name: "audience", label: "受众", value: "创业者" },
|
||||
{ name: "platform", label: "平台", type: "select", value: defaultPlatform, options: getPlatformOptions() },
|
||||
{ name: "audience", label: "受众", value: defaults.audience || recommendAudienceForPlatform(defaultPlatform) },
|
||||
{ name: "extraRequirements", label: "额外要求", placeholder: "例如:强结论开头,结尾带 CTA" }
|
||||
],
|
||||
onSubmit: async (values) => {
|
||||
@@ -11376,6 +11423,7 @@ function openCreateAiVideoAction(defaults = {}) {
|
||||
const kb = getProjectKnowledgeBases(project.id)[0];
|
||||
const defaultAssistantId = assistant?.id || "";
|
||||
const sourceJob = defaults.sourceJob || null;
|
||||
const defaultPlatform = normalizePlatformValue(defaults.platform || sourceJob?.platform || "douyin");
|
||||
const defaultVideoProvider = String(
|
||||
defaults.videoProvider || defaults.video_provider || sourceJob?.artifacts?.video_provider || "doubao"
|
||||
).trim() || "doubao";
|
||||
@@ -11408,12 +11456,12 @@ function openCreateAiVideoAction(defaults = {}) {
|
||||
value: defaultVideoModel,
|
||||
placeholder: "例如:seedance-2.0-pro",
|
||||
},
|
||||
{ name: "style", label: "风格", value: defaults.style || "realistic" },
|
||||
{ name: "style", label: "风格", value: defaults.style || recommendCreativeStyle(sourceJob) },
|
||||
{
|
||||
name: "aspectRatio",
|
||||
label: "画幅",
|
||||
type: "select",
|
||||
value: defaults.aspectRatio || defaults.aspect_ratio || sourceJob?.artifacts?.aspect_ratio || "9:16",
|
||||
value: defaults.aspectRatio || defaults.aspect_ratio || sourceJob?.artifacts?.aspect_ratio || recommendAspectRatioForPlatform(defaultPlatform),
|
||||
options: [
|
||||
{ value: "9:16", label: "9:16 竖屏" },
|
||||
{ value: "16:9", label: "16:9 横屏" },
|
||||
@@ -11421,7 +11469,7 @@ function openCreateAiVideoAction(defaults = {}) {
|
||||
],
|
||||
},
|
||||
{ name: "shots", label: "镜头数", type: "number", value: defaults.shots || 4, min: 1, max: 12 },
|
||||
{ name: "duration", label: "单镜头秒数", type: "number", value: defaults.duration || 5, min: 3, max: 12 },
|
||||
{ name: "duration", label: "单镜头秒数", type: "number", value: defaults.duration || recommendAiVideoShotDuration(sourceJob), min: 3, max: 12 },
|
||||
{
|
||||
name: "cameraLanguage",
|
||||
label: "镜头语言",
|
||||
@@ -11498,6 +11546,7 @@ function openCreateRealCutAction(defaults = {}) {
|
||||
const project = requireSelectedProject();
|
||||
const sourceJob = defaults.sourceJob || null;
|
||||
const assistant = getSelectedAssistant();
|
||||
const defaultPlatform = normalizePlatformValue(defaults.platform || sourceJob?.platform || "douyin");
|
||||
openActionModal({
|
||||
title: "创建实拍剪辑任务",
|
||||
description: "基于已完成的源任务,把素材发到 cutvideo。",
|
||||
@@ -11507,8 +11556,8 @@ function openCreateRealCutAction(defaults = {}) {
|
||||
...(sourceJob ? [{ name: "sourceJobContext", label: "来源任务", type: "html", html: renderSourceJobContextHtml(sourceJob) }] : []),
|
||||
{ name: "title", label: "任务标题", value: defaults.title || (sourceJob ? `${sourceJob.title} · 实拍剪辑` : ""), placeholder: "例如:创业素材粗剪" },
|
||||
{ name: "sourceJobId", label: "源任务", type: "select", value: defaults.sourceJobId || sourceJob?.id || getCompletedJobOptions()[0]?.value || "", options: getCompletedJobOptions() },
|
||||
{ name: "targetDurationSec", label: "目标时长(秒)", type: "number", value: defaults.targetDurationSec || 60, min: 10, max: 300 },
|
||||
{ name: "aspectRatio", label: "画幅", value: defaults.aspectRatio || "9:16" },
|
||||
{ name: "targetDurationSec", label: "目标时长(秒)", type: "number", value: defaults.targetDurationSec || recommendRealCutDuration(sourceJob), min: 10, max: 300 },
|
||||
{ name: "aspectRatio", label: "画幅", value: defaults.aspectRatio || sourceJob?.artifacts?.aspect_ratio || recommendAspectRatioForPlatform(defaultPlatform) },
|
||||
{ name: "objective", label: "目标", type: "textarea", rows: 4, value: defaults.objective || "", placeholder: "例如:保留高信息密度片段,输出适合短视频平台的粗剪结果" }
|
||||
],
|
||||
onSubmit: async (values) => {
|
||||
|
||||
@@ -1148,6 +1148,11 @@ test("input-heavy intake sheets surface current context and smarter defaults", (
|
||||
const reviewAction = extractBetween(APP, "function openReviewAction(defaults = {})", "document.addEventListener(\"click\", async (event) => {");
|
||||
assert.match(APP, /function renderIntakeActionContextHtml\(/);
|
||||
assert.match(APP, /function renderSourceJobContextHtml\(job\)/);
|
||||
assert.match(APP, /function recommendAudienceForPlatform\(platform\)/);
|
||||
assert.match(APP, /function recommendAspectRatioForPlatform\(platform\)/);
|
||||
assert.match(APP, /function recommendCreativeStyle\(sourceJob\)/);
|
||||
assert.match(APP, /function recommendRealCutDuration\(sourceJob\)/);
|
||||
assert.match(APP, /function recommendAiVideoShotDuration\(sourceJob\)/);
|
||||
assert.match(importHomepage, /label: "当前上下文", type: "html"/);
|
||||
assert.match(importHomepage, /const defaultAssistantId = getSelectedAssistant\(\)\?\.id \|\| assistants\[0\]\?\.value \|\| ""/);
|
||||
assert.match(importHomepage, /renderIntakeActionContextHtml\(project\.id, defaultAssistantId\)/);
|
||||
@@ -1173,14 +1178,22 @@ test("input-heavy intake sheets surface current context and smarter defaults", (
|
||||
assert.match(generateCopy, /label: "当前上下文", type: "html"/);
|
||||
assert.match(generateCopy, /renderIntakeActionContextHtml\(project\?\.id \|\| "", assistant\.id\)/);
|
||||
assert.match(generateCopy, /sourceJob \? \[\{ name: "sourceJobContext", label: "来源任务", type: "html", html: renderSourceJobContextHtml\(sourceJob\) \}\] : \[\]/);
|
||||
assert.match(generateCopy, /normalizePlatformValue\(defaults\.platform \|\| sourceJob\?\.platform \|\| "douyin"\)/);
|
||||
assert.match(generateCopy, /const defaultPlatform = normalizePlatformValue\(defaults\.platform \|\| sourceJob\?\.platform \|\| "douyin"\)/);
|
||||
assert.match(generateCopy, /value: defaults\.audience \|\| recommendAudienceForPlatform\(defaultPlatform\)/);
|
||||
assert.match(createAiVideo, /label: "当前上下文", type: "html"/);
|
||||
assert.match(createAiVideo, /const defaultAssistantId = assistant\?\.id \|\| ""/);
|
||||
assert.match(createAiVideo, /const defaultPlatform = normalizePlatformValue\(defaults\.platform \|\| sourceJob\?\.platform \|\| "douyin"\)/);
|
||||
assert.match(createAiVideo, /renderIntakeActionContextHtml\(project\.id, defaultAssistantId\)/);
|
||||
assert.match(createAiVideo, /sourceJob \? \[\{ name: "sourceJobContext", label: "来源任务", type: "html", html: renderSourceJobContextHtml\(sourceJob\) \}\] : \[\]/);
|
||||
assert.match(createAiVideo, /value: defaults\.style \|\| recommendCreativeStyle\(sourceJob\)/);
|
||||
assert.match(createAiVideo, /recommendAspectRatioForPlatform\(defaultPlatform\)/);
|
||||
assert.match(createAiVideo, /value: defaults\.duration \|\| recommendAiVideoShotDuration\(sourceJob\)/);
|
||||
assert.match(createRealCut, /label: "当前上下文", type: "html"/);
|
||||
assert.match(createRealCut, /const defaultPlatform = normalizePlatformValue\(defaults\.platform \|\| sourceJob\?\.platform \|\| "douyin"\)/);
|
||||
assert.match(createRealCut, /renderIntakeActionContextHtml\(project\.id, assistant\?\.id \|\| ""\)/);
|
||||
assert.match(createRealCut, /sourceJob \? \[\{ name: "sourceJobContext", label: "来源任务", type: "html", html: renderSourceJobContextHtml\(sourceJob\) \}\] : \[\]/);
|
||||
assert.match(createRealCut, /value: defaults\.targetDurationSec \|\| recommendRealCutDuration\(sourceJob\)/);
|
||||
assert.match(createRealCut, /recommendAspectRatioForPlatform\(defaultPlatform\)/);
|
||||
assert.match(reviewAction, /label: "当前上下文", type: "html"/);
|
||||
assert.match(reviewAction, /const defaultAssistantId = getSelectedAssistant\(\)\?\.id \|\| assistants\[0\]\?\.value \|\| ""/);
|
||||
assert.match(reviewAction, /renderIntakeActionContextHtml\(project\.id, defaultAssistantId\)/);
|
||||
|
||||
Reference in New Issue
Block a user