feat: direct-execute copy generation from job details
This commit is contained in:
@@ -418,6 +418,12 @@
|
||||
- 任务恢复链里的失败提示统一成“先补信息 / 需人工处理”,不再弹出“暂不支持自动恢复”这类生硬口径。
|
||||
- `额度` 页把“后续再接真实套餐”改成当前就能落地的套餐表达,明确按预算、动作池和项目阶段去配置套餐。
|
||||
|
||||
### 文案生成也并进 direct-execute
|
||||
|
||||
- `任务详情 -> 用摘要写文案` 和旧的 `job-to-generate-copy` 现在都会直接走 `OneLiner` 执行器,不再先弹回传统文案表单。
|
||||
- 这条链执行成功后,会把本轮生成结果直接回写到 `Agent -> 最近生成`,并自动回到对应锚点,用户不用再自己寻找结果。
|
||||
- 前端回归新增了这条 direct-execute 与结果回写断言,避免后续又退回“执行了但最近生成不更新”的半成品状态。
|
||||
|
||||
### 套餐档位与恢复引导继续补齐
|
||||
|
||||
- `额度` 页和租户额度编辑弹层新增了 `套餐档位` 与 `预算预警阈值`,现在能直接按试用、增长、规模、自定义四档去配置项目套餐。
|
||||
|
||||
@@ -2472,11 +2472,16 @@ async function runDirectWorkbenchAction(executorKey, options = {}) {
|
||||
payload: options.payload || {},
|
||||
showResultModal: false
|
||||
});
|
||||
await followRecommendedActionResult(result, {
|
||||
platform,
|
||||
refreshWorkbench: options.refreshWorkbench !== false,
|
||||
discoveryFocus: options.discoveryFocus || ""
|
||||
});
|
||||
if (typeof options.afterResult === "function") {
|
||||
await options.afterResult(result);
|
||||
}
|
||||
if (options.followRecommendedAction !== false) {
|
||||
await followRecommendedActionResult(result, {
|
||||
platform,
|
||||
refreshWorkbench: options.refreshWorkbench !== false,
|
||||
discoveryFocus: options.discoveryFocus || ""
|
||||
});
|
||||
}
|
||||
return result;
|
||||
} catch (error) {
|
||||
presentActionFailure(error, options.errorTitle || "执行失败");
|
||||
@@ -8127,6 +8132,19 @@ function extractGeneratedCopy(payload) {
|
||||
return brief(raw, 2400);
|
||||
}
|
||||
|
||||
function cacheGeneratedCopyResult(payload, options = {}) {
|
||||
const executionPayload = payload?.payload || payload || {};
|
||||
const assistantId = executionPayload.assistant_id || options.assistantId || getSelectedAssistant()?.id || "";
|
||||
const assistant = safeArray(appState.assistants).find((item) => item.id === assistantId) || getSelectedAssistant() || null;
|
||||
appState.lastGeneratedCopy = {
|
||||
assistantId: assistantId || "",
|
||||
assistantName: assistant?.name || options.assistantName || "当前 Agent",
|
||||
prompt: String(options.prompt || options.brief || executionPayload.brief || "").trim(),
|
||||
content: extractGeneratedCopy(executionPayload),
|
||||
usedDocuments: safeArray(executionPayload.used_documents).slice(0, 3)
|
||||
};
|
||||
}
|
||||
|
||||
function buildRecommendedActionAttrs(recommendedAction, landing = {}) {
|
||||
const action = recommendedAction && typeof recommendedAction === "object" ? recommendedAction : {};
|
||||
const attrs = [];
|
||||
@@ -11088,7 +11106,7 @@ function openJobDetailAction(jobId) {
|
||||
) : ""}
|
||||
${canDeriveAiVideo(job) ? renderPipelineJobTag("aiVideo", job, "继续做 AI 视频") : ""}
|
||||
${canDeriveRealCut(job) ? renderPipelineJobTag("realCut", job, "继续做实拍剪辑") : ""}
|
||||
${actionTag("用摘要写文案", "job-to-generate-copy", `data-job-id="${escapeHtml(job.id)}"`)}
|
||||
${actionTag("用摘要写文案", "direct-generate-copy", `data-job-id="${escapeHtml(job.id)}"`)}
|
||||
</div>
|
||||
`
|
||||
},
|
||||
@@ -12354,6 +12372,26 @@ document.addEventListener("click", async (event) => {
|
||||
openGenerateCopyAction();
|
||||
return;
|
||||
}
|
||||
if (name === "direct-generate-copy") {
|
||||
const jobId = action.dataset.jobId || "";
|
||||
const detail = appState.lastJobDetail?.job?.id === jobId ? appState.lastJobDetail.job : null;
|
||||
const brief = detail ? `基于任务「${detail.title}」的结果,生成一版可发布的短视频文案。参考摘要:${getJobSeedBrief(detail)}` : "";
|
||||
closeActionModal();
|
||||
await runDirectWorkbenchAction("generate-copy", {
|
||||
busyLabel: "正在生成文案...",
|
||||
errorTitle: "生成文案失败",
|
||||
followRecommendedAction: false,
|
||||
payload: {
|
||||
source_job_id: jobId,
|
||||
brief
|
||||
},
|
||||
afterResult: async (result) => {
|
||||
cacheGeneratedCopyResult(result, { brief });
|
||||
focusRecentGeneratedCopy();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (name === "open-ai-video") {
|
||||
openCreateAiVideoAction();
|
||||
return;
|
||||
@@ -12521,7 +12559,20 @@ document.addEventListener("click", async (event) => {
|
||||
const jobId = action.dataset.jobId || "";
|
||||
const detail = appState.lastJobDetail?.job?.id === jobId ? appState.lastJobDetail.job : null;
|
||||
closeActionModal();
|
||||
openGenerateCopyAction({ sourceJob: detail, brief: detail ? `基于任务「${detail.title}」的结果,生成一版可发布的短视频文案。参考摘要:${getJobSeedBrief(detail)}` : "" });
|
||||
const brief = detail ? `基于任务「${detail.title}」的结果,生成一版可发布的短视频文案。参考摘要:${getJobSeedBrief(detail)}` : "";
|
||||
await runDirectWorkbenchAction("generate-copy", {
|
||||
busyLabel: "正在生成文案...",
|
||||
errorTitle: "生成文案失败",
|
||||
followRecommendedAction: false,
|
||||
payload: {
|
||||
source_job_id: jobId,
|
||||
brief
|
||||
},
|
||||
afterResult: async (result) => {
|
||||
cacheGeneratedCopyResult(result, { brief });
|
||||
focusRecentGeneratedCopy();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (name === "create-project") {
|
||||
|
||||
@@ -381,6 +381,19 @@ test("tracking refresh and top-video analysis flows expose async feedback inside
|
||||
assert.ok(!clickActions.includes('else if (backendSupports("/v2/oneliner/sessions"))'));
|
||||
});
|
||||
|
||||
test("job detail and follow-up flows use direct generate-copy execution and persist recent copy results", () => {
|
||||
const jobDetail = extractBetween(APP, "function openJobDetailAction(jobId) {", "function openRecoverJobAction(");
|
||||
const clickActions = extractBetween(APP, "document.addEventListener(\"click\", async (event) => {", "document.addEventListener(\"submit\", async (event) => {");
|
||||
|
||||
assert.match(APP, /function cacheGeneratedCopyResult\(payload, options = \{\}\)/);
|
||||
assert.match(jobDetail, /actionTag\("用摘要写文案", "direct-generate-copy"/);
|
||||
assert.match(clickActions, /name === "direct-generate-copy"[\s\S]*runDirectWorkbenchAction\("generate-copy"/);
|
||||
assert.match(clickActions, /name === "direct-generate-copy"[\s\S]*followRecommendedAction:\s*false/);
|
||||
assert.match(clickActions, /name === "direct-generate-copy"[\s\S]*cacheGeneratedCopyResult\(result,\s*\{\s*brief\s*\}\)/);
|
||||
assert.match(clickActions, /name === "direct-generate-copy"[\s\S]*focusRecentGeneratedCopy\(\)/);
|
||||
assert.match(clickActions, /name === "job-to-generate-copy"[\s\S]*runDirectWorkbenchAction\("generate-copy"/);
|
||||
});
|
||||
|
||||
test("discovery and production screens expose compact mobile flow summaries", () => {
|
||||
const discovery = extractBetween(APP, "function renderDiscoveryScreen()", "function renderTrackingScreen()");
|
||||
const production = extractBetween(APP, "function renderProductionScreen()", "function renderReviewScreen()");
|
||||
|
||||
Reference in New Issue
Block a user