feat: highlight intake and recorder status in production
This commit is contained in:
@@ -689,3 +689,4 @@
|
|||||||
- 首页 `1 主 2 次` 动作里把 `视频录制` 抬成了高频次级动作,当前项目有生产任务时能更快进入录制维护入口。
|
- 首页 `1 主 2 次` 动作里把 `视频录制` 抬成了高频次级动作,当前项目有生产任务时能更快进入录制维护入口。
|
||||||
- `AI 视频` 表单开始直接显示“当前项目最近使用的视频引擎”,像 `Seedance 2.0 · seedance-2.0-pro` 这类信息会在打开表单时直接可见,并保留跳到火山配置状态的入口。
|
- `AI 视频` 表单开始直接显示“当前项目最近使用的视频引擎”,像 `Seedance 2.0 · seedance-2.0-pro` 这类信息会在打开表单时直接可见,并保留跳到火山配置状态的入口。
|
||||||
- `生产中心` 现在把 `导入主页 / 导入作品 / 导入文本 / 上传视频` 这批接入入口统一接进了顶部动作区和生产队列工作流卡,不用离开生产中心也能开始接入素材。
|
- `生产中心` 现在把 `导入主页 / 导入作品 / 导入文本 / 上传视频` 这批接入入口统一接进了顶部动作区和生产队列工作流卡,不用离开生产中心也能开始接入素材。
|
||||||
|
- `生产中心` 的 `生产队列` 首屏现在会直接显示 `接入与录制` 概况:最近内容源同步条数、录制源数量、录制服务状态,以及一组直达 `导入主页 / 导入作品 / 视频录制` 的动作。
|
||||||
|
|||||||
@@ -7559,7 +7559,7 @@ function renderPlaybookScreen() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderProductionMobileTaskDeck({ activeTab, activeJobs, failedJobs, recoverableCount, works, recentDocs }) {
|
function renderProductionMobileTaskDeck({ activeTab, activeJobs, failedJobs, recoverableCount, works, recentDocs, contentSyncCount = 0, recorderSourceCount = 0, recorderRunning = false }) {
|
||||||
const taskCards = [];
|
const taskCards = [];
|
||||||
if (activeTab === "recovery") {
|
if (activeTab === "recovery") {
|
||||||
const nextRecoverable = failedJobs.find((item) => item.recovery.recoverable) || null;
|
const nextRecoverable = failedJobs.find((item) => item.recovery.recoverable) || null;
|
||||||
@@ -7663,18 +7663,17 @@ function renderProductionMobileTaskDeck({ activeTab, activeJobs, failedJobs, rec
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
if (topJob) {
|
taskCards.push(`
|
||||||
taskCards.push(`
|
<div class="task-item compact">
|
||||||
<div class="task-item compact">
|
<h4>接入与录制</h4>
|
||||||
<h4>${escapeHtml(topJob.title)}</h4>
|
<p>${escapeHtml(`最近内容源同步 ${formatNumber(contentSyncCount)} 条 · 录制源 ${formatNumber(recorderSourceCount)} 个${recorderRunning ? ",录制服务正在运行。" : ",录制服务待确认。"} `)}</p>
|
||||||
<p>${escapeHtml(brief(topJob.style_summary || topJob.transcript_text || topJob.error || "暂无摘要", 84))}</p>
|
<div class="task-meta">
|
||||||
<div class="task-meta">
|
${actionTag("导入主页", "open-import-homepage")}
|
||||||
<span class="tag ${statusTone(topJob.status)}">${escapeHtml(topJob.status)}</span>
|
${actionTag("导入作品", "open-import-video-link")}
|
||||||
<span class="tag">${escapeHtml(topJob.line_type || "analysis")}</span>
|
${actionTag("视频录制", "focus-live-recorder-maintenance")}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`);
|
</div>
|
||||||
}
|
`);
|
||||||
}
|
}
|
||||||
return `
|
return `
|
||||||
<div class="mobile-only production-mobile-task-deck">
|
<div class="mobile-only production-mobile-task-deck">
|
||||||
@@ -7696,6 +7695,9 @@ function renderProductionScreen() {
|
|||||||
const recoverableCount = failedJobs.filter((item) => item.recovery.recoverable).length;
|
const recoverableCount = failedJobs.filter((item) => item.recovery.recoverable).length;
|
||||||
const recentDocs = appState.documents.slice(0, 3);
|
const recentDocs = appState.documents.slice(0, 3);
|
||||||
const works = getProductionWorks(6);
|
const works = getProductionWorks(6);
|
||||||
|
const contentSyncCount = jobs.filter((item) => item.line_type === "content_source_sync").length;
|
||||||
|
const recorderSourceCount = safeArray(appState.liveRecorderSources).length;
|
||||||
|
const recorderRunning = Boolean(appState.liveRecorderStatus?.running);
|
||||||
const isMobileUi = isMobileViewport();
|
const isMobileUi = isMobileViewport();
|
||||||
const productionHandoffAttrs = buildMainAgentHandoffAttrs({
|
const productionHandoffAttrs = buildMainAgentHandoffAttrs({
|
||||||
sourceScreen: "production",
|
sourceScreen: "production",
|
||||||
@@ -7735,12 +7737,13 @@ function renderProductionScreen() {
|
|||||||
<div class="queue-card"><h4>分析任务</h4><p>最近 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "analysis").length))} 条</p></div>
|
<div class="queue-card"><h4>分析任务</h4><p>最近 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "analysis").length))} 条</p></div>
|
||||||
<div class="queue-card"><h4>实拍剪辑</h4><p>最近 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "real_cut").length))} 条</p></div>
|
<div class="queue-card"><h4>实拍剪辑</h4><p>最近 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "real_cut").length))} 条</p></div>
|
||||||
<div class="queue-card"><h4>AI 视频</h4><p>最近 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "ai_video").length))} 条</p></div>
|
<div class="queue-card"><h4>AI 视频</h4><p>最近 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "ai_video").length))} 条</p></div>
|
||||||
<div class="queue-card"><h4>内容源同步</h4><p>最近 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "content_source_sync").length))} 条</p></div>
|
<div class="queue-card"><h4>接入与录制</h4><p>同步 ${escapeHtml(formatNumber(contentSyncCount))} 条 · 录制源 ${escapeHtml(formatNumber(recorderSourceCount))} 个</p></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mobile-only compact-summary-row" style="margin-top:14px;">
|
<div class="mobile-only compact-summary-row" style="margin-top:14px;">
|
||||||
<span class="tag blue">分析 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "analysis").length))}</span>
|
<span class="tag blue">分析 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "analysis").length))}</span>
|
||||||
<span class="tag">实拍 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "real_cut").length))}</span>
|
<span class="tag">实拍 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "real_cut").length))}</span>
|
||||||
<span class="tag green">AI 视频 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "ai_video").length))}</span>
|
<span class="tag green">AI 视频 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "ai_video").length))}</span>
|
||||||
|
<span class="tag ${recorderRunning ? "green" : "orange"}">录制 ${escapeHtml(formatNumber(recorderSourceCount))}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
${renderQuotaBlockingNotice()}
|
${renderQuotaBlockingNotice()}
|
||||||
@@ -7788,7 +7791,10 @@ function renderProductionScreen() {
|
|||||||
failedJobs,
|
failedJobs,
|
||||||
recoverableCount,
|
recoverableCount,
|
||||||
works,
|
works,
|
||||||
recentDocs
|
recentDocs,
|
||||||
|
contentSyncCount,
|
||||||
|
recorderSourceCount,
|
||||||
|
recorderRunning
|
||||||
})}
|
})}
|
||||||
${renderDetailTabs("productionDetailTab", tabs)}
|
${renderDetailTabs("productionDetailTab", tabs)}
|
||||||
${activeTab === "queue" ? `
|
${activeTab === "queue" ? `
|
||||||
|
|||||||
@@ -496,12 +496,19 @@ test("mobile discovery and production simplify duplicated top-level actions", ()
|
|||||||
|
|
||||||
test("production queue promotes intake entrypoints so import flows are reachable without leaving production", () => {
|
test("production queue promotes intake entrypoints so import flows are reachable without leaving production", () => {
|
||||||
const production = extractBetween(APP, "function renderProductionScreen()", "function renderReviewScreen()");
|
const production = extractBetween(APP, "function renderProductionScreen()", "function renderReviewScreen()");
|
||||||
|
const mobileDeck = extractBetween(APP, "function renderProductionMobileTaskDeck(", "function renderProductionScreen()");
|
||||||
assert.match(production, /const intakeEntryActionsHtml =/);
|
assert.match(production, /const intakeEntryActionsHtml =/);
|
||||||
assert.match(production, /<h4>接入素材<\/h4>/);
|
assert.match(production, /<h4>接入素材<\/h4>/);
|
||||||
assert.match(production, /把主页、作品链接、文本素材或本地视频先接进项目/);
|
assert.match(production, /把主页、作品链接、文本素材或本地视频先接进项目/);
|
||||||
assert.match(production, /先从导入主页、作品、文本或上传视频开始接入素材/);
|
assert.match(production, /先从导入主页、作品、文本或上传视频开始接入素材/);
|
||||||
|
assert.match(production, /<h4>接入与录制<\/h4>/);
|
||||||
|
assert.match(production, /同步 .* 条 · 录制源 .* 个/);
|
||||||
|
assert.match(production, /录制 \${escapeHtml\(formatNumber\(recorderSourceCount\)\)}/);
|
||||||
assert.match(production, /actionTag\("导入作品", "open-import-video-link"\)/);
|
assert.match(production, /actionTag\("导入作品", "open-import-video-link"\)/);
|
||||||
assert.match(production, /actionTag\("上传视频", "open-upload-video"\)/);
|
assert.match(production, /actionTag\("上传视频", "open-upload-video"\)/);
|
||||||
|
assert.match(mobileDeck, /<h4>接入与录制<\/h4>/);
|
||||||
|
assert.match(mobileDeck, /actionTag\("导入主页", "open-import-homepage"\)/);
|
||||||
|
assert.match(mobileDeck, /actionTag\("视频录制", "focus-live-recorder-maintenance"\)/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("discovery page promotes selected-account actions into direct execute flows", () => {
|
test("discovery page promotes selected-account actions into direct execute flows", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user