feat(workshop): AI创作需求表单加入落点三字段(痛点爽点/共鸣共情/爆点) 共8行可空 v17

- REQ_FIELDS 5→8:idea/pain/relate/blow/form/plot/end/note,落点要素可选留空由 AI 补齐
- clarify 服务端模板同步 8 行,注释 5行→8行
- 需求区展开高度 400→560px 容纳 8 张卡片
This commit is contained in:
maogeigei committed 2026-09-02 18:44:23 +08:00
1 parent 84d4587384
commit fd25045182
4 files changed
+61 -10

No files matched your search

+50
View File
@@ -355,3 +355,53 @@
- **JS**(data-pages.js reqCreate 提交处理器):点击 ✓ 不再直接 executeTask → 先 `await loadPersona()` 再弹**确认弹窗**(modal-mask 内层 modal:标题「确认提交创作」+ 达人名 + 「S1-S11 全流程,自动模式」说明 + 已填需求清单 `reqLines`(n/10)+ 人设已加载/暂无 + 附件有无 + 取消/确认提交创作);点确认后才 `close()` + executeTask
- 语法 node --check 通过;纯静态资源 no-store,服务未重启;重开 `?v=20260902-v7#/accounts`
- git commit 未做(与 6cd96c9/c40bc22 一起攒到下次同步点)
## AI创作弹窗 v8:需求区默认折叠可点击展开(18:15-18:20,用户追加要求)
- **需求原话**:「需求内容部分 默认折叠」
- **HTML/JS**(data-pages.js):req-sheet 外包 `.req-sheet-box#reqSheetBox` 容器 → 顶部标题按钮 `#reqSheetToggle`(「创作需求」+ 计数 `#reqFilledCount` n/10 已填 + 右端箭头 `#reqCaret`)+ 内容 `#reqSheet`;renderSheet 每次重渲染更新 filled 计数、box 切换 `.has-filled` 装饰类(filled>0 标题前亮蓝点+计数徽标变主色);sheetToggle click 切 box `.open`、aria-expanded 同步;默认收起
- **CSS**(style.css,`.req-confirm-label` 前插入):`.req-sheet-box` 白底描边圆角容器;`.req-sheet-toggle` 整行可点击(hover 标题变主色);`.rst-count` 灰底圆角徽标 / `.has-filled` 变 primary-soft 底主色字;箭头 `.rst-caret svg` 收起态 rotate(180deg) 朝下(提示可展开)→ open 态转 0;折叠动画 `.req-sheet-box .req-sheet { max-height: 0; overflow: hidden; transition: max-height .2s }` → `.open` 恢复 max-height 340 + overflow auto
- 折叠用 max-height 动画(非 display none),内容 10 行需展开后内部滚动
- 语法 node --check 通过;纯静态 no-store 未重启;commit de77425(2 files 43+/1-);重开 `?v=20260902-2#/accounts`
## AI创作弹窗 v9:去重引导文案(18:25,用户问「两段引导是否重复可否留一」)
- **重复点**:顶部常驻 `.req-head`(输入→整理到创作需求框→✓提交创作)≈ 对话空态 `.req-dialog-empty`(输入初步想法→即时更新需求框)
- **定案**:保留空态引导(含维度清单、只在首屏出现不占常驻位)、删顶部常驻 req-head;快捷键与附件格式两处独有信息补进空态文案(「也可点回形针上传需求文档(doc / docx / txt / pdf)。Enter 发送,Shift+Enter 换行。」)
- **改动**:data-pages.js 删 req-head div(模板)→ dialog-empty 扩文案;style.css 删 .req-head 规则(仅 1 处引用,grep 验证零残留)
- commit e4cede2(2 files 1+/3-);重开 `?v=20260902-3#/accounts`
## AI创作弹窗 v10:需求框收窄为选题侧 6 字段(18:35,用户定「需求区重点是选题相关,账号设定不重复输入」)
- **定案**:REQ_FIELDS 10→6——删 mood 情绪基调 / aud 受众 / sym 结构性符号 / ad 广告植入(账号级,人设卡+内容规则已自动带入创作);保留 idea 一句话创意与选题 / form 叙事形态 / dur 时长目标 / plot 核心情节 / end 结尾落点 / note 其他约束(兜底)
- **data-pages.js**:REQ_FIELDS 数组、w 初始对象、空态引导文案(维度清单改「创意/形态/时长/情节/结尾」+ 明示「账号级设定(情绪基调/受众/植入等)已由账号设定提供,无需重复填写」)、各处注释 10→6、空值文案改「按账号设定与选题自决」
- **server.js**(/api/ai/clarify):模板删 4 行 → 6 行;行为要求新增第 5 条——「需求框只收集选题相关信息;账号级设定(情绪基调/目标受众/结构性符号/广告植入等)已由账号设定自动带入创作,不要向达人重复询问;仅当达人主动提出与账号设定不同的要求时记入『其他约束』」;注释 10→6
- 两端 node --check 通过;**server.js 改动 → 重启服务(taskkill PID 19936 → 后台重启 task CEiCmO),clarify 接口 curl 实测 200 返回正常**
- commit 3be2ff1(2 files 14+/12-);重开 `?v=20260902-4#/accounts`
## AI创作弹窗 v11:时长改功能选项下拉 + 字段改名(18:55,用户要求)
- **需求**:①「一句话创意与选题」改名「一句话创意」②时长目标移出需求栏 → 需求栏下方「功能选项」下拉(30/60/120/240/自定义)
- **data-pages.js**:REQ_FIELDS 6→5(idea 标签改「一句话创意」、删 dur);reqLines 末尾追加时长行 `- 时长目标:${dur}`(创作 prompt/确认弹窗仍含时长,reqMdOf 模板不含→AI 不再管时长);HTML 在 req-sheet-box 与 req-dialog 之间插 `.req-opts`(标签+select 30/60/120/240/自定义+自定义秒数输入);事件:选 custom 显示秒数输入(w.dur='45秒'),选固定值写 w.dur='60秒',默认「未指定(由 AI 定)」w.dur='';确认弹窗计数改「已填 x 项,含时长选项」(避免 lines>分母 6/5)
- **server.js** clarify 模板 6 行 → 5 行(删时长目标、idea 标签同步);注释同步
- **style.css**:.req-opts 白底描边圆角条(复用 .input-select)
- 两端 node --check 通过;server.js 改动 → 重启服务(taskkill 26488 → 后台 task 1lDwFM,8900:200)
- commit 17acaf1(3 files 50+/11-);重开 `?v=20260902-5#/accounts`
## AI创作弹窗 v12:需求字段卡片化(18:30-18:32,用户两轮澄清定稿)
- **需求**:维度名=卡片内小标题置左上角,内容在标题下方,卡片边框 padding 10px(用户二次澄清「标题在卡片左上角、padding 卡片边框10px、内容在卡片内标题下方」)
- **style.css**:`.req-field` 由横向(rf-title 104px 左标签 + rf-val 同行)→ flex column(rf-title 顶部小标题 + rf-val 下方,gap 4px)+ padding 10px;rf-title 去掉 width/左浮(12px 600 #5b6472);折叠展开 max-height 340→400(卡片变高)
- 纯 CSS,无需重启/改 JS;commit 504c92e(1 file 7+/7-);重开 `?v=20260902-6` 后又 `?v=20260902-7`(用户疑似看到旧缓存页,二次说明规格)
## AI创作弹窗 v13:时长选项细节(18:33-18:35,用户要求)
- ①opts 标签「时长目标」→「时长」;②默认选项「未指定(由 AI 定)」→「自动」;③修复秒数输入框 bug——`.req-dur-custom` CSS display:inline-flex 覆盖 hidden 属性导致输入框一直显示,补 `.req-dur-custom[hidden]{display:none}`,现仅选中「自定义…」才出现可直接输入
- reqLines 需求行标签同步「- 时长目标:」→「- 时长:」(创作 prompt 侧)
- 语法通过;commit cc59c1c(2 files 4+/3-);重开 `?v=20260902-8#/accounts`
## AI创作弹窗 v14:空值文案改「待完善」(18:35-18:37,用户要求)
- renderSheet 空字段占位「(待定 · 由 AI 按账号设定与选题自决)」→「待完善」;确认弹窗全空兜底「(未填写 · 由 AI 按人设自决)」→「(待完善)」;弹窗注释同步
- 语法通过;commit 8c5b66d(1 file 3+/3-);重开 `?v=20260902-9#/accounts`
## AI创作弹窗 v15:时长下拉收窄(18:36,用户要求)
- `.req-dur-sel` width 168→110px(紧凑适配「自定义…」最长选项);commit 12ba43c(1 file 1+/1-);重开 `?v=20260902-10#/accounts`
## AI创作弹窗 v16:空态引导精简(18:39,用户要求)
- 空态文案后半段「账号级设定(情绪基调/受众/植入等)已由账号设定提供,无需重复填写。也可点回形针上传需求文档(doc/docx/txt/pdf)」→ 一句「支持上传附件」(附件格式由纸夹按钮 title 承载)
- 现文案:输入初步想法+AI引导补齐创意/形态/情节/结尾+即时更新需求框+支持上传附件+快捷键
- commit 84d4587(1 file 1+/1-);重开 `?v=20260902-11#/accounts`
@@ -171,9 +171,10 @@ function bindBatchBar(container, opts) {
// 需求单字段顺序:弹窗需求框展示、AI 输出模板、创作 prompt 共用(值空 = 待 AI 按账号设定与选题自决)
// 09-02 v10:需求框定位=选题补充——只留本条视频选题侧字段 + 兜底「其他」;账号设定类(情绪基调/受众/结构性符号/广告植入)由人设卡提供,不在此重复收集
// 09-02 v11:dur 时长目标 移出需求栏 → 需求栏下方「功能选项」下拉(30/60/120/240/自定义),值由 w.dur 单独承载
// 09-02 v17:选题落点要素(痛点/爽点、共鸣/共情、爆点)加入需求框——创作流程需要但不是必填,空值由 AI 按账号设定与选题自决
const REQ_FIELDS = [
['idea', '一句话创意'], ['form', '叙事形态'],
['plot', '核心情节'], ['end', '结尾落点'], ['note', '其他约束'],
['idea', '一句话创意'], ['pain', '痛点/爽点'], ['relate', '共鸣/共情'], ['blow', '爆点'],
['form', '叙事形态'], ['plot', '核心情节'], ['end', '结尾落点'], ['note', '其他约束'],
];
// 需求 md 行 → 向导字段映射(parseReqSheet 用)
const REQ_LABEL_TO_KEY = Object.fromEntries(REQ_FIELDS.map(([k, label]) => [label, k]));
@@ -213,11 +214,11 @@ function buildCreatePrompt(accountName, w, personaBlock, hasPersona, attachText)
}
/* AI创作 弹窗(09-02 v2:需求框 + 输入框 对话式打磨)——
顶部=创作需求(5 行选题字段,随对话逐轮被 AI 更新,空值标「待完善」)+ 下方时长选项条
顶部=创作需求(8 行选题字段:创意+落点要素(痛点爽点/共鸣/爆点,可空)+形态/情节/结尾/其他,随对话逐轮被 AI 更新,空值标「待完善」)+ 下方时长选项条
中部=对话流(用户输入 vs AI 整理/追问),底部=输入框 + 提交创作 */
async function confirmAiScript(accountName, btn) {
const accId = btn && btn.dataset.accId ? btn.dataset.accId : '';
const w = { idea: '', form: '', dur: '', plot: '', end: '', note: '' };
const w = { idea: '', pain: '', relate: '', blow: '', form: '', dur: '', plot: '', end: '', note: '' };
const convo = []; // 对话流 { role: 'u' | 'ai', text }
let pHas = false, pContent = '';
let attach = { name: '', text: '' }; // 已上传需求附件(解析后的纯文本,打磨与创作共用)
@@ -280,7 +281,7 @@ async function confirmAiScript(accountName, btn) {
mask.querySelector('[data-x]').addEventListener('click', close);
const q = (s) => mask.querySelector(s);
/* —— 需求框渲染:5 个选题字段,维度名作标题、内容在下方 —— */
/* —— 需求框渲染:8 个选题字段(含落点要素,可空),维度名作标题、内容在下方 —— */
const renderSheet = () => {
const rows = REQ_FIELDS.map(([k, label]) => {
const v = String(w[k] || '').trim();
@@ -323,7 +324,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 会引导你补齐创意 / 形态 / 情节 / 结尾等选题需求;每条输入都会即时更新上方的创作需求框。支持上传附件。Enter 发送,Shift+Enter 换行。</div>`;
: `<div class="req-dialog-empty">在这里输入一个初步想法,AI 会引导你补齐创意 / 痛点爽点 / 共鸣 / 爆点 / 形态 / 情节 / 结尾等需求(落点要素可留空,由 AI 按账号设定与选题补齐);每条输入都会即时更新上方的创作需求框。支持上传附件。Enter 发送,Shift+Enter 换行。</div>`;
el.scrollTop = el.scrollHeight;
};
const setBusy = (b) => {
@@ -215,7 +215,7 @@ main { height: calc(100vh - 54px); }
/* 需求区:一个维度一张卡片(09-02 v12 改:维度名=卡片内小标题置左上角,内容在其下;卡片 padding 10px),超高内部滚动 */
.req-sheet {
flex: none; display: grid; grid-template-columns: 1fr; gap: 6px 0;
max-height: 400px; overflow: auto; align-content: start; padding: 2px;
max-height: 560px; overflow: auto; align-content: start; padding: 2px;
}
.req-field {
display: flex; flex-direction: column; gap: 4px;
@@ -247,7 +247,7 @@ main { height: calc(100vh - 54px); }
.req-sheet-toggle .rst-caret svg { transition: transform .2s ease; transform: rotate(180deg); } /* 收起(默认):箭头朝下提示可展开 */
.req-sheet-box.open .rst-caret svg { transform: rotate(0deg); }
.req-sheet-box .req-sheet { max-height: 0; overflow: hidden; padding: 0; transition: max-height .2s ease; }
.req-sheet-box.open .req-sheet { max-height: 400px; overflow: auto; padding: 2px; }
.req-sheet-box.open .req-sheet { max-height: 560px; overflow: auto; padding: 2px; } /* v17:8 张卡(含落点三字段)展开高度 400→560 */
/* 需求栏下方功能选项条(09-02 v11):时长目标下拉(30/60/120/240/自定义),与需求栏同宽同视觉层级 */
.req-opts { flex: none; display: flex; align-items: center; gap: 8px; background: #fff; border: 1px solid var(--border); border-radius: 10px; padding: 7px 10px; }
.req-opts .opts-label { flex: none; font-size: 13px; font-weight: 600; color: var(--text); }
@@ -704,8 +704,8 @@ const server = http.createServer((req, res) => {
+ '3. 若信息已基本齐备:用一两句话总结并提示用户可点击「提交创作」。\n'
+ '4. 输出必须严格分两段:第一段是对用户说的话(120 字以内,含必要时的问题);\n'
+ '然后另起一行单独输出 ==REQ==;\n'
+ '接着输出 5 行需求清单(仍未确定的项留空值,严禁编造),模板:\n'
+ '- 一句话创意:\n- 叙事形态:\n- 核心情节:\n- 结尾落点:\n- 其他约束:\n'
+ '接着输出 8 行需求清单(仍未确定的项留空值,严禁编造),模板:\n'
+ '- 一句话创意:\n- 痛点/爽点:\n- 共鸣/共情:\n- 爆点:\n- 叙事形态:\n- 核心情节:\n- 结尾落点:\n- 其他约束:\n'
+ '5. 需求框只收集本条视频的选题相关信息;账号级设定(情绪基调 / 目标受众 / 结构性符号 / 广告植入等)已由账号设定自动带入创作,不要向达人重复询问这些维度——仅当达人主动提出与账号设定不同的要求时,将其记入「其他约束」。';
// 4) Dify blocking 调用
const difyUrl = String(process.env.DIFY_URL || 'https://mydify.youmanvideo.com/v1').replace(/\/+$/, '');