工作台:对话式选题完善 ==OPTS== 候选 chips(编导词定稿+分支追问)
This commit is contained in:
1 parent
383532719d
commit
01a1301a4a
3 files changed
+51
-13
No files matched your search
@@ -349,14 +349,29 @@ async function confirmAiScript(accountName, btn) {
|
||||
const n = Math.round(Number(durNum.value));
|
||||
w.dur = (Number.isFinite(n) && n > 0) ? n + '秒' : '';
|
||||
});
|
||||
/* —— 对话流渲染 —— */
|
||||
/* —— 对话流渲染(09-07:AI 消息可携带 ==OPTS== 候选,渲染为可点选 chips;点击即以该候选作为用户输入发送) —— */
|
||||
const renderDialog = () => {
|
||||
const el = q('#reqDialog');
|
||||
el.innerHTML = convo.length
|
||||
? 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 会引导你补齐创意 / 创新·爆点 / 痛点爽点 / 叙事结构等需求(落点要素可留空,由 AI 按账号设定与选题补齐,共鸣与情节结尾由 AI 依痛点爽点发挥);每条输入都会即时更新上方的创作需求框。支持上传附件。Enter 发送,Shift+Enter 换行。</div>`;
|
||||
? convo.map((c, ci) => {
|
||||
if (c.role === 'u') return `<div class="req-msg mine"><div class="req-bubble">${esc(c.text)}</div></div>`;
|
||||
const opts = (Array.isArray(c.opts) && c.opts.length)
|
||||
? `<div class="req-opts">${c.opts.map((o) => `<button type="button" class="req-opt-chip" data-i="${ci}" data-opt="${esc(o)}">${esc(o)}</button>`).join('')}</div>`
|
||||
: '';
|
||||
return `<div class="req-msg ai"><div class="req-bubble">${esc(c.text)}</div>${opts}</div>`;
|
||||
}).join('')
|
||||
: `<div class="req-dialog-empty">在这里输入一个初步想法,AI 会引导你补齐创意 / 创新·爆点 / 痛点爽点 / 叙事结构等需求(落点要素可留空,由 AI 按账号设定与选题补齐,共鸣与情节结尾由 AI 依痛点爽点发挥);每条输入都会即时更新上方的创作需求框,AI 追问时会给出可点选的候选。支持上传附件。Enter 发送,Shift+Enter 换行。</div>`;
|
||||
el.querySelectorAll('.req-opt-chip').forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
if (busy) return;
|
||||
const ci = Number(btn.dataset.i);
|
||||
const opt = btn.dataset.opt || '';
|
||||
if (!opt || !Number.isFinite(ci) || !convo[ci]) return;
|
||||
if (convo[ci].role === 'ai') convo[ci].opts = []; // 点过的候选即时收起
|
||||
renderDialog();
|
||||
sendTurn(opt);
|
||||
});
|
||||
});
|
||||
el.scrollTop = el.scrollHeight;
|
||||
};
|
||||
const setBusy = (b) => {
|
||||
@@ -443,14 +458,20 @@ async function confirmAiScript(accountName, btn) {
|
||||
if (r.error) throw new Error(r.error);
|
||||
const answer = String(r.answer || '').trim();
|
||||
const ri = answer.lastIndexOf('==REQ==');
|
||||
const reply = (ri >= 0 ? answer.slice(0, ri) : answer).trim();
|
||||
const head = (ri >= 0 ? answer.slice(0, ri) : answer).trim();
|
||||
// 09-07:==OPTS== 候选段(位于正文与 ==REQ== 之间,每行一个可点选短句)→ 渲染为 chips
|
||||
const oi = head.lastIndexOf('==OPTS==');
|
||||
const reply = (oi >= 0 ? head.slice(0, oi) : head).trim();
|
||||
const opts = oi >= 0
|
||||
? head.slice(oi + '==OPTS=='.length).split('\n').map((s) => s.trim()).filter((s) => s && !s.startsWith('==')).slice(0, 6)
|
||||
: [];
|
||||
const fields = ri >= 0 ? parseReqSheet(answer.slice(ri + '==REQ=='.length)) : {};
|
||||
let updated = 0;
|
||||
for (const k of Object.keys(fields)) {
|
||||
const v = String(fields[k] || '').trim();
|
||||
if (v && w[k] !== v) { w[k] = v; updated++; }
|
||||
}
|
||||
if (reply) convo.push({ role: 'ai', text: reply });
|
||||
if (reply || opts.length) convo.push({ role: 'ai', text: reply || '(已记录本轮信息,继续补充或点选上方候选)', opts });
|
||||
renderSheet();
|
||||
renderDialog();
|
||||
showToast(updated > 0 ? `✅ 需求已更新 ${updated} 项` : (ri >= 0 ? '✅ 已记录(本次无新变更)' : '⚠️ 本次未返回结构化需求,可换种说法再试'));
|
||||
|
||||
@@ -266,6 +266,17 @@ main { height: calc(100vh - 54px); }
|
||||
}
|
||||
.req-msg.mine .req-bubble { background: var(--primary); color: #fff; border-bottom-right-radius: 3px; }
|
||||
.req-msg.ai .req-bubble { background: #f0f2f5; color: var(--text); border-bottom-left-radius: 3px; }
|
||||
/* 09-07:AI 追问候选 chips(==OPTS== 段渲染;置于 AI 气泡下方,点击即作为用户输入发送) */
|
||||
.req-msg.ai { flex-wrap: wrap; column-gap: 8px; }
|
||||
.req-msg.ai .req-bubble + .req-opts { margin-top: 6px; }
|
||||
.req-opts { display: flex; flex-wrap: wrap; gap: 6px; max-width: 92%; }
|
||||
.req-opt-chip {
|
||||
display: inline-flex; align-items: center;
|
||||
background: #fff; border: 1px solid var(--border); border-radius: 999px;
|
||||
padding: 4px 12px; font-size: 13px; color: var(--text); cursor: pointer;
|
||||
line-height: 1.4; transition: border-color .15s, color .15s, background .15s;
|
||||
}
|
||||
.req-opt-chip:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-soft); }
|
||||
/* 底部功能条:输入框(圆角块内嵌 textarea + 底部工具栏:回形针 · ✓ 提交创作 · ↑ 发送) */
|
||||
.req-bar { flex: none; display: flex; align-items: flex-end; gap: 10px; }
|
||||
.req-create {
|
||||
|
||||
Reference in new issue
Block a user