feat(workshop): AI创作需求框收窄为选题侧6字段(删情绪/受众/结构性符号/广告植入4账号设定字段,人设卡已覆盖,保留其他约束兜底)

This commit is contained in:
maogeigei committed 2026-09-02 18:22:28 +08:00
1 parent e4cede21f1
commit 3be2ff152d
2 files changed
+14 -12

No files matched your search

@@ -168,10 +168,11 @@ function bindBatchBar(container, opts) {
/* ============================================================
AI创作 需求打磨辅助(09-02 v2:弹窗内对话式——需求框 + 输入框,无跳会话/无文件回填/无选题按钮)
============================================================ */
// 需求单字段顺序:弹窗需求框展示、AI 输出模板、创作 prompt 共用(值空 = 待 AI 按人设自决)
// 需求单字段顺序:弹窗需求框展示、AI 输出模板、创作 prompt 共用(值空 = 待 AI 按账号设定与选题自决)
// 09-02 v10:需求框定位=选题补充——只留本条视频选题侧字段 + 兜底「其他」;账号设定类(情绪基调/受众/结构性符号/广告植入)由人设卡提供,不在此重复收集
const REQ_FIELDS = [
['idea', '一句话创意与选题'], ['form', '叙事形态'], ['dur', '时长目标'], ['mood', '情绪基调'], ['aud', '受众'],
['plot', '核心情节'], ['end', '结尾落点'], ['sym', '结构性符号'], ['ad', '广告植入'], ['note', '其他约束'],
['idea', '一句话创意与选题'], ['form', '叙事形态'], ['dur', '时长目标'],
['plot', '核心情节'], ['end', '结尾落点'], ['note', '其他约束'],
];
// 需求 md 行 → 向导字段映射(parseReqSheet 用)
const REQ_LABEL_TO_KEY = Object.fromEntries(REQ_FIELDS.map(([k, label]) => [label, k]));
@@ -187,7 +188,7 @@ function parseReqSheet(md) {
}
return out;
}
// 状态 → 10 行完整需求清单(供 AI 每轮保持同模板输出;空字段留空值)
// 状态 → 6 行完整需求清单(供 AI 每轮保持同模板输出;空字段留空值)
function reqMdOf(w) {
return REQ_FIELDS.map(([k, label]) => `- ${label}:${String(w[k] || '').trim()}`).join('\n');
}
@@ -208,11 +209,11 @@ function buildCreatePrompt(accountName, w, personaBlock, hasPersona, attachText)
}
/* AI创作 弹窗(09-02 v2:需求框 + 输入框 对话式打磨)——
顶部=创作需求(10 行字段,随对话逐轮被 AI 更新,空值标「待定·由 AI 按人设自决」)
顶部=创作需求(6 行选题字段,随对话逐轮被 AI 更新,空值标「待定·由 AI 按账号设定与选题自决」)
中部=对话流(用户输入 vs AI 整理/追问),底部=输入框 + 提交创作 */
async function confirmAiScript(accountName, btn) {
const accId = btn && btn.dataset.accId ? btn.dataset.accId : '';
const w = { idea: '', form: '', dur: '', mood: '', aud: '', plot: '', end: '', sym: '', ad: '', note: '' };
const w = { idea: '', form: '', dur: '', plot: '', end: '', note: '' };
const convo = []; // 对话流 { role: 'u' | 'ai', text }
let pHas = false, pContent = '';
let attach = { name: '', text: '' }; // 已上传需求附件(解析后的纯文本,打磨与创作共用)
@@ -261,11 +262,11 @@ async function confirmAiScript(accountName, btn) {
mask.querySelector('[data-x]').addEventListener('click', close);
const q = (s) => mask.querySelector(s);
/* —— 需求框渲染:10 个维度块,维度名作标题、内容在下方 —— */
/* —— 需求框渲染:6 个选题字段,维度名作标题、内容在下方 —— */
const renderSheet = () => {
const rows = REQ_FIELDS.map(([k, label]) => {
const v = String(w[k] || '').trim();
return `<div class="req-field${v ? '' : ' empty'}"><div class="rf-title">${label}</div><div class="rf-val">${v ? esc(v) : '(待定 · 由 AI 按人设自决)'}</div></div>`;
return `<div class="req-field${v ? '' : ' empty'}"><div class="rf-title">${label}</div><div class="rf-val">${v ? esc(v) : '(待定 · 由 AI 按账号设定与选题自决)'}</div></div>`;
}).join('');
q('#reqSheet').innerHTML = rows;
const filled = REQ_FIELDS.filter(([k]) => String(w[k] || '').trim()).length;
@@ -289,7 +290,7 @@ async function confirmAiScript(accountName, btn) {
? convo.map((c) => (c.role === 'u'
? `<div class="req-msg mine"><div class="req-bubble">${esc(c.text)}</div></div>`
: `<div class="req-msg ai"><div class="req-bubble">${esc(c.text)}</div></div>`)).join('')
: `<div class="req-dialog-empty">在这里输入一个初步想法,AI 会引导你补齐形态 / 时长 / 情绪 / 受众 / 情节 / 结尾 / 植入等需求;每条输入都会即时更新上方的创作需求框。也可点回形针上传需求文档(doc / docx / txt / pdf)。Enter 发送,Shift+Enter 换行。</div>`;
: `<div class="req-dialog-empty">在这里输入一个初步想法,AI 会引导你补齐创意 / 形态 / 时长 / 情节 / 结尾等选题需求;每条输入都会即时更新上方的创作需求框。账号级设定(情绪基调 / 受众 / 植入等)已由账号设定提供,无需重复填写。也可点回形针上传需求文档(doc / docx / txt / pdf)。Enter 发送,Shift+Enter 换行。</div>`;
el.scrollTop = el.scrollHeight;
};
const setBusy = (b) => {