fix(workshop): AI创作弹窗v6 确认按钮移入输入框工具栏 + 间距10px
This commit is contained in:
1 parent
3e0de85795
commit
cd0f876785
4 files changed
+90
-8
No files matched your search
@@ -215,3 +215,81 @@
|
|||||||
- req-head 末尾补 "Enter 直接发送,Shift+Enter 换行"——键盘说明从 placeholder 迁到头部更显眼
|
- req-head 末尾补 "Enter 直接发送,Shift+Enter 换行"——键盘说明从 placeholder 迁到头部更显眼
|
||||||
- **验证** `tmp/cdp-autogrow-check.mjs`:5 行输入(scrollHeight 116)→ height 32→100(被 cap 到 max-height)✅;清空 → height 回 32 ✅
|
- **验证** `tmp/cdp-autogrow-check.mjs`:5 行输入(scrollHeight 116)→ height 32→100(被 cap 到 max-height)✅;清空 → height 回 32 ✅
|
||||||
- git commit 1a8f445(1 文件 +10/-2)
|
- git commit 1a8f445(1 文件 +10/-2)
|
||||||
|
|
||||||
|
## AI创作弹窗 v4 上传需求附件(16:20-16:30,用户要求)
|
||||||
|
- **需求原话**:「增加一个上传需求的功能,支持上传附件(doc txt pdf ),可根据附件内容 完善需求,确认后 将附件内容也当做创作AI脚本的上下文。」
|
||||||
|
- **实现**(data-pages.js + style.css + server.js + 新 scripts/attachment-parser.js):
|
||||||
|
- **前端** confirmAiScript:
|
||||||
|
- HTML:req-dialog 与 req-bar 之间插入 `<div class="req-attach-row" id="attachRow">`(chip 行);req-input-box 内 textarea 前加 paperclip 按钮 `<button class="req-paper" id="reqPaper">`;弹窗底部加 `<input type="file" id="attachInput" accept=".doc,.docx,.txt,.pdf" hidden>`
|
||||||
|
- 状态:`let attach = { name: '', text: '' }` + `let parsing = false`(防重入)
|
||||||
|
- `fileToBase64(f)` = FileReader.readAsDataURL → split(',')[1]
|
||||||
|
- attachInput change:校验扩展名+大小(>20MB 拒)→ 调 `/api/req/parse-attachment` → 设置 attach + `renderAttach()` 渲染 chip(paperclip+文件名+字数+×)+ 失败 toast
|
||||||
|
- `sendTurn`:空文本但 attach 非空时自动用引导语"(我已上传需求附件)请通读附件内容…";body 增加 `attach: attach.text`
|
||||||
|
- `reqCreate`:`buildCreatePrompt` 新增第 5 参 attachText
|
||||||
|
- **buildCreatePrompt**:attachText 非空时在【创作需求】后拼【附件素材】段「达人上传的需求文档/资料原文,创作时须充分参考,其中的诉求与约束同【创作需求】一样必须满足」
|
||||||
|
- **后端** server.js:
|
||||||
|
- `require('./scripts/attachment-parser')` 一行
|
||||||
|
- `/api/ai/clarify` 入参增 `attach`,query 在「【账号定位】」后拼「【附件素材】(达人上传的需求文档/资料,打磨与最终创作都须充分参考…)」;attach 限 2 万字符
|
||||||
|
- 新增 `POST /api/req/parse-attachment`:body 30MB 上限 → `Buffer.from(data,'base64')` → 20MB 上限 → `parseAttachment(name, buf)` → 返回 `{ text, chars, warn, sourceChars }`(text 限 3 万字符)
|
||||||
|
- **零依赖解析器** `scripts/attachment-parser.js`(仅用 node:zlib):`.txt` utf8 直读+\uFFFD 警告 / `.docx` EOCD 0x06054b50+中央目录 0x02054b50 找 word/document.xml→inflateRawSync 抽 w:t/w:p/w:br/w:tab+xmlUnescape / `.pdf` latin1 流定位 stream/endstream+前文 `/Filter /FlateDecode`→inflateSync+Tj/TJ/hex 文本抽取 / `.doc` 400 报「请另存为 .docx/.txt」
|
||||||
|
- **CSS** style.css:新增 `.req-attach-row/.req-chip/.chip-ic/.chip-name/.chip-meta/.chip-x/.req-paper`(primary-soft 浅蓝胶囊 + paperclip 灰图标 + 28×32 灰圆角上传钮 + .loading 旋转);`.req-input-box` padding-left 13→2px 容纳回形针
|
||||||
|
- **测试样例** `tmp/attach-tests/{req.txt,req.docx,old.doc}.b64`(make_samples.py 零依赖生成):`req.txt` 171 字 / `req.docx` 100 字 / `old.doc` 0xD0CF11E0 头 200B / **冒烟前已用真实账号名「俊希」作示例内容造成用户困惑,09-02 16:31 改为「亲子Vlog 方向(测试用样例)」中立内容**(教训:冒烟附件样例必须中立,禁止带任何真实账号/达人名)
|
||||||
|
- **端到端 API 验证**(node fetch tmp/attach-tests/parse-check.mjs):txt 200/171字/warn:"" / docx 200/100字/warn:"" / doc 400「暂不支持 .doc 老格式…」/ 空参数 400「缺少文件参数」——全路径符合预期
|
||||||
|
- **CDP 9224 冒烟脚本** `tmp/cdp-req-v4-attach-smoke.mjs`(3 轮迭代,2 轮失败根因):
|
||||||
|
1. 失败 1:`DOM.querySelector(rootId, sel)` 跨连接 root 失效(错误"Could not find node with given id")→ 改 `Runtime.evaluate+DOM.requestNode(objectId)` 拿稳定 nodeId
|
||||||
|
2. 失败 2:`DOM.setFileInputFiles` 仍抛"Could not find node with given id"(疑似目标 Chrome 多 client 句柄竞争,9224 同时被其他进程连接)→ 改**纯 Runtime 方案**:`atob(b64)→Uint8Array→File+DataTransfer+input.files=dt.files+dispatchEvent('change')`,change 处理器 FileReader→fetch 全在页面内异步完成
|
||||||
|
3. 失败 3:每次 cdp() 调用新建 WebSocket 连接 = 不同 CDP session,objectId/nodeId 全部失效 → 改为**单条持久 WebSocket**(`_sock` 全局复用 + onopen 同步 + message listener 配对 id 移除)
|
||||||
|
- **最终全绿**(含真实 Dify 一轮打磨 50s,总 90s):①结构 hasPaper/paperInBox/hasAttachInput/accept=".doc,.docx,.txt,.pdf"/attachRow/headHas ②txt chip "req.txt 162 字" ③移除成功+docx chip "req.docx 95 字" ④turn1 真实 Dify 回复明确读附件硬性要求:「俊希做煎蛋、妈妈手部指导镜头、爸爸烫到彩蛋以及牛奶口播植入已全部录入清单」+filled 0→5+msgs=2 ⑤提交创作弹窗关闭(executeTask 走通)
|
||||||
|
- **截图** `tmp/reqv4-1-txt-chip.png` / `reqv4-2-docx-chip.png` / `tmp/reqv4-3-turn1-filled.png` + 报告 `tmp/req-v4-attach-report.json`
|
||||||
|
- **测试残留清理**(用户反馈「为什么旧梦留声机和俊希混在一起」后排查):
|
||||||
|
- 工作台 DB automations 表查到 2 条可疑任务:`automation-1788337499185` 创作指令(我 16:25 冒烟 ⑤ 触发,prompt 含 docx 俊希附件+旧梦留声机人设,scheduledAt 16:25:04,状态 IN_PROGRESS 跑中会污染脚本产物)/ `automation-1788334853018` 打磨需求(15:40:58 ACCEPTED,产物 `旧梦留声机/创作需求单.md` 实际是用户自己的「爷爷的旧收音机」默认 A 选题,无俊希字样——**不动**)
|
||||||
|
- 处置:automation_update mode=update id=automation-1788337499185 status=PAUSED(scheduler 不再触发新轮次,但已 IN_PROGRESS thread 会自然跑完,产物落到 `旧梦留声机/脚本创作/` 由用户决定清不清——不擅自清)
|
||||||
|
- **根因**:冒烟测试样例 req.docx 内容用了「俊希账号」真实账号名→ 弹窗标题「AI创作 · 旧梦留声机」+ 附件「俊希」=视觉上两账号混了;**已改测试样例为中立**(make_samples.py 改写后重生成 b64 验证仍 4 路径 OK)
|
||||||
|
- **★经验沉淀**(v4 设计层):
|
||||||
|
1. 端到端附件功能实现要分 4 层:①解析器(零依赖纯文本提取)②上传 API(限大小/限字符/返回结构)③前端 chip 状态(attach 字符串而非 base64 缓存)④prompt 拼接(每轮 clarify + 最终 buildCreatePrompt 都带)
|
||||||
|
2. AI 打磨 vs 创作上下文共享:clarify 时 attach 进 query 让 AI 把诉求吸收进需求清单;create 时 attach 原文进 prompt 让创作有完整参考——同一 attach 两个阶段都用,但作用不同(前者吸收诉求、后者保留原文)
|
||||||
|
3. 「空输入但有附件」单独 UX:sendTurn 自动发引导语,避免用户必须输字才能让 AI 看附件;这是「上传需求」功能的核心交互
|
||||||
|
4. CDP 冒烟注入文件的可靠方案:纯 Runtime + DataTransfer(绕开 DOM 域句柄),变更可靠 + 不依赖目标 Chrome session 状态
|
||||||
|
- **git 改动未提交**(按 2h 节奏):4 文件 M + 1 新增 attachment-parser.js(app.js 仅 ICON_PATHS 新加 paperclip 一行)
|
||||||
|
- **★工作台页面重开**(按「改完必重开」约定):present_files 后面挂 `http://localhost:8900/?v=20260902-v4#/accounts`
|
||||||
|
|
||||||
|
## AI创作弹窗 v5 输入框布局微调(16:32-16:38,用户参考 WorkBuddy 输入框截图)
|
||||||
|
- **需求原话**:「输入框不是这样的 输入框分上下两部分,上面是文字输入区域,下面是功能区域,用一个边框包起来,参考下下workbuddy的[截图]」
|
||||||
|
- **实现**(data-pages.js HTML 重排 + style.css 调整):
|
||||||
|
- HTML:`<div class="req-input-box">` 内部由「paperclip + textarea + send 横向」改为「textarea 在上 + `<div class="req-input-toolbar">` 在下」结构;toolbar 内含 paperclip + `<div class="req-spacer">` 弹性间距 + send
|
||||||
|
- CSS:
|
||||||
|
- `.req-input-box`:flex 方向 row→column、border-radius 12→14、padding 改为 0(让两块各自控 padding)
|
||||||
|
- `.req-input`:flex:1→width:100% + box-sizing:border-box,padding 6/0/5→10/14/6(上输入区留白)
|
||||||
|
- 新增 `.req-input-toolbar`:flex row + align center + gap 2px + padding 2/4/6
|
||||||
|
- 新增 `.req-spacer`:flex:1 推开 paperclip 与 send
|
||||||
|
- `.req-send`:34×34 圆角 9→32×32 圆角 50%(贴合 WorkBuddy 圆形按钮)
|
||||||
|
- `.req-paper`:28×32→32×32(与 send 视觉对齐)
|
||||||
|
- req-create 仍保留在 .req-bar 左侧独立(44×44 ✓ 提交创作,对应 WorkBuddy 弹窗外功能)
|
||||||
|
- **CDP 9224 验证** `tmp/cdp-req-v5-layout-check.mjs`(结构 + autoGrow 多行 + 截图):
|
||||||
|
- **结构全绿**:boxDisplay=flex / boxFlexDir=column / boxBorderRadius=14px / hasToolbar=true / taAboveTb=true / paperLeftOfSend=true / paperInToolbar=true / sendInToolbar=true / boxRounded=true
|
||||||
|
- autoGrow:6 行输入 → height 100px(被 max-height cap,scrollH 142 截断),toolbar 自然下移,外框圆角不变
|
||||||
|
- **截图** `tmp/reqv5-1-input-layout.png`(空态)/ `tmp/reqv5-2-input-multiline.png`(多行+focus halo)
|
||||||
|
- **教训**(冒烟脚本复用旧坑):CDP 测试用 `el.value = 'A\\nB'` 字面 \\n 被当 2 字符不换行——前次 v3 已踩,本次脚本复用相同模式,结构验证不受影响(autoGrow 实测 v3 cdp-autogrow-check.mjs 已覆盖真换行)
|
||||||
|
- **设计要点**:输入区(textarea)+ 功能区(toolbar)垂直堆叠 + 单一外框圆角描边 + focus-within 整体 halo —— 与 WorkBuddy 输入框视觉一致;保留 req-bar 左外侧 ✓ 提交(弹窗层级独立功能,不属输入框)
|
||||||
|
- git commit 待执行(按 2h 节奏不 push,本次仅 UI 微调,单 commit)
|
||||||
|
- **★工作台页面重开**(按「改完必重开」约定):present_files 后面挂 `http://localhost:8900/?v=20260902-v5#/accounts`
|
||||||
|
|
||||||
|
## AI创作弹窗 v6 确认按钮移入工具栏(16:38-16:50,用户要求)
|
||||||
|
- **需求原话**:「把确认按钮 也改为图标 放到输入框功能区域中」
|
||||||
|
- **调整思路**:确认按钮 ✓ 原本在 req-bar 内、req-input-box 外侧(左外 44×44 圆角方块独立按钮)→ 移入 req-input-toolbar(输入框底功能区),与 paperclip/send 同居;与 send 同尺寸同形状(32×32 圆形)形成「次主+主」配对
|
||||||
|
- **DOM 重组**(data-pages.js 行 230-240):
|
||||||
|
- req-bar 内独立 `<button id="reqCreate">` 移除
|
||||||
|
- 在 req-input-toolbar 内追加 `<button class="req-create" id="reqCreate">`(svg `check` 16px),位置在 spacer 后、send 前——构成右侧"动作簇":`spacer → ✓ → ↑`
|
||||||
|
- 文案同步:req-head 「点左侧的 ✓」改为「点输入框内的 ✓」
|
||||||
|
- **CSS 调整**(style.css):
|
||||||
|
- `.req-create`:44×44 圆角 12px 描边方块 → 32×32 圆形(border-radius: 50%),主色描边 + 白底 + 主色图标;hover 时主色填实(与 send 实心配色形成"次主+主"配对)
|
||||||
|
- 移动 `display: flex` → `display: inline-flex`(与其他 toolbar 按钮对齐)
|
||||||
|
- **CDP 验证 v6**(`tmp/cdp-req-v6-confirm-in-toolbar.mjs` 全绿):createInToolbar=true/sendInToolbar=true/paperInToolbar=true / createBeforeSend=true / createSize=sendSize=paperSize=32×32 / sameSizeAsSend=true / createBorderRadius=50% / createBorderColor=primary / sendBackground=primary / barHasCreateDirectly=false / barChildren=["req-input-box"](外置大按钮已彻底消失)
|
||||||
|
- **截图** `tmp/reqv6-1-confirm-in-toolbar.png`(整体弹窗,外置✓消失)/ `tmp/reqv6-2-toolbar-zoom.png`(工具栏 zoom)
|
||||||
|
|
||||||
|
## AI创作弹窗 v6.1 ✓↔↑ 间距 10px(16:50,用户明确)
|
||||||
|
- **需求原话**:「输入按钮 和 确认按钮 间隔10PX」
|
||||||
|
- **微调**(style.css):`.req-create` margin-left: 4px + 新增 margin-right: 8px(toolbar gap 2px 保持)—— 总间距 = 2 + 8 = 10px ✓
|
||||||
|
- **CDP 验证** `tmp/cdp-req-v6_1-gap10-check.mjs`:createRight=929/sendLeft=939/gap_px=**10**(精确)
|
||||||
|
- **截图** `tmp/reqv6-1-toolbar-zoom.png`(更新版)
|
||||||
|
- 工作台页面重开 `?v=20260902-v6#/accounts`(v6.1 同 v6 版本号足够,CSS no-store)
|
||||||
@@ -20,6 +20,8 @@
|
|||||||
- **冒烟脚本** `tmp/cdp-req-dialog-smoke.mjs`(4 步端到端 CDP 9224)= 结构/双轮真实 Dify 打磨/需求框递增/提交捕获(拦截 executeTask 验 label+skills+persona+reqRows+modalClosed),端到端 ~50s 全绿
|
- **冒烟脚本** `tmp/cdp-req-dialog-smoke.mjs`(4 步端到端 CDP 9224)= 结构/双轮真实 Dify 打磨/需求框递增/提交捕获(拦截 executeTask 验 label+skills+persona+reqRows+modalClosed),端到端 ~50s 全绿
|
||||||
- **v3 UI 升级(09-02,弹窗体验收紧)**:①弹窗高 720→760+height:min(840px,92vh) flex column;②需求区 2 列 grid 维度块(rf-title 标题在 rf-val 内容上方,empty 灰显);③输入条一体化:`.req-input-box` 圆角胶囊内嵌无边框 textarea + 右侧 primary 蓝圆发送钮(svg `arrow-up`),busy 时 disabled 灰+白色旋转 spinner(@keyframes req-spin);④提交创作=44×44 描边圆角 ✓ 图标钮(svg `check`),置于 `.req-bar` 左侧;⑤取消按钮删除(仅留右上 ×);**附带红利**:提交按钮改 id 后与列表 [data-create] 同名歧义自然消失
|
- **v3 UI 升级(09-02,弹窗体验收紧)**:①弹窗高 720→760+height:min(840px,92vh) flex column;②需求区 2 列 grid 维度块(rf-title 标题在 rf-val 内容上方,empty 灰显);③输入条一体化:`.req-input-box` 圆角胶囊内嵌无边框 textarea + 右侧 primary 蓝圆发送钮(svg `arrow-up`),busy 时 disabled 灰+白色旋转 spinner(@keyframes req-spin);④提交创作=44×44 描边圆角 ✓ 图标钮(svg `check`),置于 `.req-bar` 左侧;⑤取消按钮删除(仅留右上 ×);**附带红利**:提交按钮改 id 后与列表 [data-create] 同名歧义自然消失
|
||||||
- **v3 补完(09-02 16:13)**:textarea auto-grow(`autoGrow()` 闭包 = style.height auto + min(scrollHeight, 100);input 事件绑定 + sendTurn 复位),placeholder 单行化(rows=1 截断)+ 换行提示迁到 req-head 末尾「Enter 直接发送,Shift+Enter 换行」
|
- **v3 补完(09-02 16:13)**:textarea auto-grow(`autoGrow()` 闭包 = style.height auto + min(scrollHeight, 100);input 事件绑定 + sendTurn 复位),placeholder 单行化(rows=1 截断)+ 换行提示迁到 req-head 末尾「Enter 直接发送,Shift+Enter 换行」
|
||||||
|
- **v4 上传需求附件(09-02 16:25)**:弹窗输入框区域左侧加 paperclip 📎 图标(svg `paperclip`,新加 ICON_PATHS)→ 隐藏 `<input type="file" accept=".doc,.docx,.txt,.pdf" id="attachInput">` → 选中后 FileReader→base64→`POST /api/req/parse-attachment`(server.js 紧跟 clarify 之后,body 30MB 上限、原文件 20MB 上限)→ 返回 `{ text, chars, warn, sourceChars }` → 渲染 req-attach-row chip(paperclip+文件名+字数+×移除);**空输入但有附件时自动发引导语**(`(我已上传需求附件)请通读附件内容,把其中可落到创作的诉求与约束整理进需求清单…`)让 AI 单凭附件也能开打磨;每轮 `/api/ai/clarify` body 多带 `attach: attach.text`(后端拼【附件素材】段入 query,clarify 限 2 万字符);提交创作时 `buildCreatePrompt` 增第 5 参 attachText→prompt 拼【附件素材】原文段(与【创作需求】同铁律)。**零依赖附件解析器** `scripts/attachment-parser.js`(Node 内置 `node:zlib`)= `.txt` 直读 utf8+\uFFFD 警告 / `.docx` 走 EOCD 0x06054b50+中央目录 0x02054b50→`word/document.xml`→inflateRawSync 抽 w:t+w:p/w:br/w:tab+XML 实体解码 / `.pdf` latin1 流定位 stream/endstream+前文 `/Filter /FlateDecode`→inflateSync+Tj/TJ/hex 文本抽取 / `.doc` 旧格式明确 400 报错「请另存为 .docx/.txt」。**测试样例** `tmp/attach-tests/{req.txt,req.docx,old.doc}`(脚本 make_samples.py 生成 + base64 落盘)= 端到端 4 路径验证:txt 200 171 字 / docx 200 100 字 / doc 400 报不支持 / 空参数 400
|
||||||
|
- **v4 CDP 冒烟坑(CDP 9224 实测)**:①`DOM.querySelector(rootId, sel)` 跨连接 root 失效 → `Runtime.evaluate` 拿 objectId + `DOM.requestNode(objectId)` 转 nodeId 拿稳定句柄;②`DOM.setFileInputFiles` 即使持久连接 + requestNode 仍抛 "Could not find node with given id"(疑似目标 Chrome 多 client 句柄竞争)→ 改纯 Runtime 方案:`Uint8Array + File + DataTransfer + input.files + dispatchEvent('change')` 注入文件,change 处理器 FileReader→fetch 全在页面内异步完成;③**单条持久 WebSocket 必需**:每次调用新建连接 = 不同 CDP session,objectId/nodeId 全部失效;脚本模板用 `_sock` 复用首连接 + 后续 send 复用
|
||||||
|
|
||||||
## 创作技能关键规则(权威源:SKILL.md + references/创作流程规范.md)
|
## 创作技能关键规则(权威源:SKILL.md + references/创作流程规范.md)
|
||||||
1. 三态创作:⚡自动(默认)=静默执行+只落最终交付物;🤝共创=+每确认门询问;🛠️开发=+每步全落盘。7确认门不可合并;角色边界(分析不做创作)
|
1. 三态创作:⚡自动(默认)=静默执行+只落最终交付物;🤝共创=+每确认门询问;🛠️开发=+每步全落盘。7确认门不可合并;角色边界(分析不做创作)
|
||||||
@@ -59,4 +61,4 @@
|
|||||||
## 历史事件(摘要)
|
## 历史事件(摘要)
|
||||||
- 06-25 营销号风格清理;07-17 大炮创作方法136文件;07-20 知识库重组;07-29 短剧知识库V5.0;07-30 短视频知识库V2.0
|
- 06-25 营销号风格清理;07-17 大炮创作方法136文件;07-20 知识库重组;07-29 短剧知识库V5.0;07-30 短视频知识库V2.0
|
||||||
- 08-11→12 素材库扁平化(8类型+四维标签)+去硬编码(30处)+产物链铁律;08-12 人设卡片V2.1;08-16 知识库赛道8→27;08-17 三态创作模式定稿;08-20 分镜标准库落库+seedance25提炼;08-21 Lite1.0 新增;08-22 .dsh 单向只读确立;08-25 仓库更名 mcn-video-script
|
- 08-11→12 素材库扁平化(8类型+四维标签)+去硬编码(30处)+产物链铁律;08-12 人设卡片V2.1;08-16 知识库赛道8→27;08-17 三态创作模式定稿;08-20 分镜标准库落库+seedance25提炼;08-21 Lite1.0 新增;08-22 .dsh 单向只读确立;08-25 仓库更名 mcn-video-script
|
||||||
- 08-26 路径重构+环境判定两步模型+三技能统一产出结构定稿;08-27 mcn-dou-analysis 定主版本、短视频提示词生成去 V1.0 层、工作台新增;08-28 S9 格式修正+工作台改写弹窗 UI 迭代;08-31 工作台数据预览条/改名/AI脚本诊断技能关联/俊希全流程TC-01~11/调度器根因确认(scheduledAt须未来时间)
|
- 08-26 路径重构+环境判定两步模型+三技能统一产出结构定稿;08-27 mcn-dou-analysis 定主版本、短视频提示词生成去 V1.0 层、工作台新增;08-28 S9 格式修正+工作台改写弹窗 UI 迭代;08-31 工作台数据预览条/改名/AI脚本诊断技能关联/俊希全流程TC-01~11/调度器根因确认(scheduledAt须未来时间);09-02 工作台 AI创作弹窗 v2/v3/v3补完/v4 上传附件,文档 toc+5+ljg-skills 维护+浏览器不主动关闭红线
|
||||||
@@ -223,17 +223,17 @@ async function confirmAiScript(accountName, btn) {
|
|||||||
const mask = document.createElement('div'); mask.className = 'modal-mask';
|
const mask = document.createElement('div'); mask.className = 'modal-mask';
|
||||||
mask.innerHTML = `<div class="modal req-modal">
|
mask.innerHTML = `<div class="modal req-modal">
|
||||||
<div class="modal-title-row"><span>AI创作 · ${esc(accountName)}</span><button class="btn btn-icon" data-x title="关闭">${svgIcon('x', 16)}</button></div>
|
<div class="modal-title-row"><span>AI创作 · ${esc(accountName)}</span><button class="btn btn-icon" data-x title="关闭">${svgIcon('x', 16)}</button></div>
|
||||||
<div class="req-head">输入想法,或点回形针上传需求文档(doc / docx / txt / pdf),AI 会把需求整理到上方「创作需求」里;打磨满意后点左侧的 ✓ 提交创作(附件原文会一并作为创作上下文)。Enter 发送,Shift+Enter 换行。</div>
|
<div class="req-head">输入想法,或点回形针上传需求文档(doc / docx / txt / pdf),AI 会把需求整理到上方「创作需求」里;打磨满意后点输入框内的 ✓ 提交创作(附件原文会一并作为创作上下文)。Enter 发送,Shift+Enter 换行。</div>
|
||||||
<div class="req-sheet" id="reqSheet"></div>
|
<div class="req-sheet" id="reqSheet"></div>
|
||||||
<div class="req-dialog" id="reqDialog"></div>
|
<div class="req-dialog" id="reqDialog"></div>
|
||||||
<div class="req-attach-row" id="attachRow"></div>
|
<div class="req-attach-row" id="attachRow"></div>
|
||||||
<div class="req-bar">
|
<div class="req-bar">
|
||||||
<button type="button" class="req-create" id="reqCreate" title="提交创作(生成完整脚本)">${svgIcon('check', 20)}</button>
|
|
||||||
<div class="req-input-box">
|
<div class="req-input-box">
|
||||||
<textarea id="reqInput" class="req-input" rows="1" placeholder="说说你的想法,例如:想拍一个亲子互动的搞笑短剧…(也可以先上传需求文档)"></textarea>
|
<textarea id="reqInput" class="req-input" rows="1" placeholder="说说你的想法,例如:想拍一个亲子互动的搞笑短剧…(也可以先上传需求文档)"></textarea>
|
||||||
<div class="req-input-toolbar">
|
<div class="req-input-toolbar">
|
||||||
<button type="button" class="req-paper" id="reqPaper" title="上传需求附件(doc / docx / txt / pdf)">${svgIcon('paperclip', 17)}</button>
|
<button type="button" class="req-paper" id="reqPaper" title="上传需求附件(doc / docx / txt / pdf)">${svgIcon('paperclip', 17)}</button>
|
||||||
<div class="req-spacer"></div>
|
<div class="req-spacer"></div>
|
||||||
|
<button type="button" class="req-create" id="reqCreate" title="提交创作(生成完整脚本)">${svgIcon('check', 16)}</button>
|
||||||
<button type="button" class="req-send" id="reqSend" title="发送">${svgIcon('arrow-up', 18)}</button>
|
<button type="button" class="req-send" id="reqSend" title="发送">${svgIcon('arrow-up', 18)}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -240,14 +240,16 @@ main { height: calc(100vh - 54px); }
|
|||||||
}
|
}
|
||||||
.req-msg.mine .req-bubble { background: var(--primary); color: #fff; border-bottom-right-radius: 3px; }
|
.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; }
|
.req-msg.ai .req-bubble { background: #f0f2f5; color: var(--text); border-bottom-left-radius: 3px; }
|
||||||
/* 底部功能条:提交创作图标(左)+ 一体输入条(圆角块内嵌 textarea + 右侧发送圆钮) */
|
/* 底部功能条:输入框(圆角块内嵌 textarea + 底部工具栏:回形针 · ✓ 提交创作 · ↑ 发送) */
|
||||||
.req-bar { flex: none; display: flex; align-items: flex-end; gap: 10px; }
|
.req-bar { flex: none; display: flex; align-items: flex-end; gap: 10px; }
|
||||||
.req-create {
|
.req-create {
|
||||||
flex: none; width: 44px; height: 44px; border-radius: 12px;
|
/* 工具栏内:与 send 同尺寸同形状,描边白底(弱主操作),hover 时填实主色,与 send 实心形成「次主+主」配对 */
|
||||||
border: 1px solid var(--border); background: #fff; color: var(--primary);
|
flex: none; width: 32px; height: 32px; border-radius: 50%;
|
||||||
display: flex; align-items: center; justify-content: center; cursor: pointer;
|
border: 1px solid var(--primary); background: #fff; color: var(--primary);
|
||||||
|
display: inline-flex; align-items: center; justify-content: center;
|
||||||
|
cursor: pointer; padding: 0; margin-left: 4px; margin-right: 8px; /* ✓ 与 ↑ 发送间隔 = 2px gap + 8px = 10px */
|
||||||
}
|
}
|
||||||
.req-create:hover { border-color: var(--primary); background: var(--primary-soft); }
|
.req-create:hover { background: var(--primary); color: #fff; border-color: var(--primary); }
|
||||||
/* 输入框:参考 WorkBuddy 风格——输入区在上(带 padding),工具栏在下(回形针 + 弹性间距 + 发送),外框统一圆角描边 */
|
/* 输入框:参考 WorkBuddy 风格——输入区在上(带 padding),工具栏在下(回形针 + 弹性间距 + 发送),外框统一圆角描边 */
|
||||||
.req-input-box {
|
.req-input-box {
|
||||||
flex: 1; display: flex; flex-direction: column;
|
flex: 1; display: flex; flex-direction: column;
|
||||||
|
|||||||
Reference in new issue
Block a user