Files
mcn-short-video/.workbuddy/memory/2026-08-28.md
T
maogeigei 268ce29aae feat(账号分析+工作台): 功能三自动联动生成设定卡+双向联动维护+玫瑰金配色定稿+首页数据预览/周榜优化+CDP验证脚本
- mcn-dou-analysis: 功能三产出设定后自动生成设定卡(Step7); 设定md与卡片SVG双向联动维护规则固化(06文档+03文档+SKILL.md); 浅色系配色定稿玫瑰金(#D6A3A9→#9A5563)+背景文字提亮规则; 新增06生成账号设定卡片文档+模板样例
- mcn-work-shop: 首页数据预览条/周榜预览表加宽/改名AI脚本诊断/tab切换/添加账号弹窗等优化
- 新增 cdp-*.mjs 验证脚本14个(可复用); .gitignore 忽略运行日志/截图/tmp
2026-08-31 15:27:54 +08:00

32 KiB
Raw Blame History

2026-08-28 工作日志

MCN工作台 帮助页排版优化(09:43-09:51)

  • 用户反馈功能帮助页排版乱,先截图诊断(browser-harness + 独立 Chrome 9223)
  • P0 根因:.qa-row 用 display:flex 横排 + .q { white-space:nowrap },长问法撑满宽度,.a 被挤成竖排一字一行(「写脚本」卡的回答竖排炸裂)
  • 修复(public/style.css 2 块):
    • .func-grid → grid-template-columns: 1fr 单列,5 卡片各独占一行(原 2+2+1 孤卡)
    • .qa-row 改上下排:q 橙色一行(block + normal 换行),a 灰缩进 1.2em 一行
  • 数据与点击复制逻辑零改动

帮助页补返回按钮(09:50-09:53)

  • 帮助页缺 page-toolbar 返回按钮(数据页都有),用户指出
  • renderHelp() 顶部加 <button data-back>←</button> + 「功能帮助」标题;router help 分支绑定 [data-back] → #/
  • 复用现有 .page-toolbar/.page-title CSS

周榜改名 + 保存确认弹窗(09:53-10:00)

  • 「抖音周榜」→「账号周榜」:app.js(首页卡片/首页h3/CRUMB_TITLES/router titles/注释)+ data-pages.js(页title×2)+ style.css 注释;dsh-data.js 的「抖音周榜_」文件名正则不能改(匹配磁盘真实数据文件名)
  • 功能列「导入」→「保存」:app.js 首页预览 + data-pages.js 周榜页;title「保存并分析该账号」
  • 新增 confirmSaveAccount(name, url)(app.js 工具区):点击保存 → modal 确认弹窗(账号名高亮 .confirm-target + URL + 确认保存/取消)→ 确认后 firePrompt 提交 /api/run(任务名「保存指令」,prompt 改「保存并分析」);两处周榜共用
  • 新增样式 .confirm-target/.confirm-url;弹窗图标用 refresh(无 save 图标)
  • 验证(browser-harness 实测):首页/周榜页名称、保存按钮数(10/20)、弹窗出现 → 取消关闭(⚠️ 检测须用 .modal-mask:not([hidden]),设置弹窗常驻 DOM 会误报)

环境备忘

  • browser-harness 调用:BU_CDP_URL=http://127.0.0.1:9223 PYTHONPATH='C:\Users\maidou\.dsh\skills\browser-harness\src' D:\miniconda3\envs\browser-harness\python.exe -m browser_harness.run(截图用 capture_screenshot(path=..., full=..., max_dim=...),无 shot 函数)
  • 独立 Chrome:chrome.exe --remote-debugging-port=9223 --user-data-dir=C:\Users\maidou\.workbuddy\tmp\bh-chrome-9223

全按钮确认弹窗 + 执行中状态(09:57-10:30)

  • 用户要求:所有按钮点击后需弹窗确认才执行;执行中按钮变「执行中」禁点,直到任务完成;弹窗提示词参考 dsh-plugin-mcn(client.js 的 confirm* state + busy/disabled + 轮询模式)
  • 盘点 8 处触发 AI 任务的按钮:保存(首页周榜 data-rk-import + 周榜页 data-import,已有弹窗)+ 创作(账号列表 data-create)+ 改写(账号详情/写脚本页 data-rewrite ×2)+ 解析(data-analyze)+ 提炼(data-extract)+ 复盘(data-review-row)
  • 后端(server.js):新增 GET /api/run/status?id=——读 workbuddy.db 三表判定状态:runtime_state.running=1 或 automation_runs.status=IN_PROGRESS→running;PENDING_REVIEW→pending;DONE/COMPLETED/SUCCESS/FINISHED→done;ERROR/CANCELLED/FAILED/INTERRUPTED→error;无记录→queued;自动化不存在→notfound。⚠️ workbuddy.db 打开必须 { readOnly: true }
  • 前端(app.js):confirmRun(opts) 通用确认弹窗(title/desc/target/url/prompt/label/btn)+ executeTask(opts) 提交+按钮「执行中…」禁用(.btn-busy)+ 5s 轮询状态(30min 上限)→ done/error 恢复按钮+toast;confirmSaveAccount 改为包装 confirmRun(传 btn);data-pages.js 6 处 firePrompt 全改 confirmRun(提示词沿用原 prompt,弹窗 desc 参考 dsh 文案)
  • 验证(browser-harness 实测):7 类按钮弹窗全部出现(保存账号/创作脚本/改写脚本/解析视频/提炼账号设定/复盘评分);保存按钮完整链路:确认→「执行中…」disabled→轮询2次→恢复「保存」可点;⚠️ 测试技巧:覆盖 window.api 模拟 /api/run 假 id + /api/run/status 状态序列(前N次 running 后 done),避免产生真实任务;钩子条件必须区分 status URL(无 opts GET)与 POST
  • firePrompt 保留定义无调用;服务已重启(旧进程 19732 无新接口,新进程绑定 127.0.0.1:8899,20604 MiPCAudio 占 0.0.0.0 不动)

热门账号页列表优化(10:22-10:30)

  • 筛选项整体右对齐:类型/赛道/搜索/重置 包进 .toolbar-right(margin-left:auto),赛道移到搜索左边
  • 列改动:AI内容→AI制作;定位/内容→账号定位(.cell-loc max-width:110px 缩窄 + th width:110px);操作列加 th-act 居中
  • 收藏按钮实装(原来纯展示无交互):fav-btn 点击 → POST /api/dsh/account-favorite → 写库 → toast → load() 刷新(favorite DESC 排序变化);⚠️ 工作台 db 是只读连接(getDb readOnly:true),写操作用独立可写连接(setFavorite 单独 new DatabaseSync(DSH_DB) 用完即关,勿改只读连接)

热门账号改名关注账号 + is_ai 漏标修复 + 任务完成自动刷新(10:29-10:40)

  • 改名「关注账号」:首页卡片/页标题/面包屑/弹窗文案(添加到关注账号)/复盘页生成方式(关注账号创作)全改;hot_accounts 表名不动(dsh schema 一致)
  • 旧梦留声机 is_ai 漏标修复(方案A):is_ai="否" 但 bio「账号由AI❤️生成」+ content「AI 生成+…」+ 视频 tags「#ai创作浪潮计划,#内容由ai生成」+ dsh 原库人设卡「群像型AI温情剧情账号」四方矛盾;全库仅此 1 例漏标。修工作台库 UPDATE hot_accounts SET is_ai='是' WHERE id=1629(用户选方案A,dsh 原库未动);教训:is_ai 判定历史逻辑没覆盖 bio「AI❤️生成」类标记
  • 任务完成自动刷新:executeTask done 分支 → refreshCurrentPage()(当前 hash 是数据页/首页 → router() 重渲染),toast 改「任务执行完成,页面已自动刷新」;配合收藏的局部 load() 刷新,实现"改动后无需手动刷新"
  • ⚠️ browser-harness 验证轮询链路时:后台标签 setTimeout 会被 Chrome 节流导致轮询计数卡住(polls 不增长、按钮不恢复)——前台用户不受影响;验证 refreshCurrentPage 用 DOM marker(重渲染后元素消失)直测,避开时序

关注账号 AI脚本按钮 + AI 生成选题(10:41-10:55)

  • 用户指示:创作按钮改「AI脚本」;弹窗加选题输入区(手输 / 右下角 AI 按钮结合人设生成选题);"不用看dsh,脚本创作技能中有生成选题功能"——选题生成复用技能 S5 方法论 + Dify 接口
  • 技能 Dify 配置:scripts/MCN_CYLG_API.py 调 https://mydify.youmanvideo.com/v1/chat-messages(blocking 即时返回,answer 字段);env:DIFY_MCN_CYLG_KEY(必)/DIFY_MCN_MODEL(默认gemini)/DIFY_URL;用户提供 key app-0vRaxPhvVOqzFQIa5eFzFdjD 已内置脚本(新增 DEFAULT_CYLG_KEY 常量,env 优先脚本兜底,第117行 api_key 读取改兜底);⚠️ 接口文档提醒:curl 中文 query 会被 CDN 拦截推荐 Python;search 模式(联网)60s 超时,recall 模式(is_online=0)47-55s 稳定返回
  • 后端(server.js 新增 POST /api/ai/topics):查工作台库账号 content(500字)+ persona summary(500字)→ 构造 S5 选题方法 prompt(跳出行为框架/保留结构性符号/目标体感/3个选题每行一条)→ Dify recall 调用(100s abort)→ 返回 topics;key 读取链:env → 技能脚本 DEFAULT_CYLG_KEY 正则提取
  • 前端(data-pages.js):confirmAiScript(accountName, btn) 弹窗——标题 AI脚本 + desc + textarea(.ai-topic-input)+ 右下角 AI 按钮(.ai-topic-btn,点击加载态…/disabled);AI 按钮 POST /api/ai/topics 填入输入框;确认后选题非空则 prompt 拼「选题方向:{topic}」;按钮「创作」→「AI脚本」
  • 实测:接口返回旧梦留声机选题(困在1998年的爷爷/隔辈亲情,人设结合生效);弹窗 UI + AI 生成 55s 填入 1267 字 + 按钮恢复 + 取消关闭全通过

工作台 08-28 下午迭代(12:14-12:23)

  • 账号详情页:tab 样式多轮调整(胶囊→直角→下划线式定稿:无背景/蓝色文字/2px 直线下划线/border-radius:0——圆角根因是顶栏 .tab 残留 8px 未覆盖);视频列表加「账号视频列表」标题(上方间隔20px);视频ID 列缩窄(.td-id 13px 紧凑,187→165px);「定位/内容」→「账号定位」
  • 固化「改完必重开页面」到 SKILL.md(用户强调 + 明确要求固化到 skill):工作台章节新增第 7 点硬性约定——改动完成后最后一步必须 present_files 重开对应页面(带 hash),因内置浏览器无 CDP 端口无法模拟 F5;同步写入 MEMORY.md 工作方式约定首条;SKILL.md frontmatter updated_at→08-28 + last_change 摘要(08-28 工作台迭代)
  • ⚠️ 教训:数据页 .tabs/.tab 会继承顶栏同名类样式(margin-left:20px、border-radius:8px),必须显式覆盖;用户对 tab 最终定稿=下划线式无背景无圆角

工作台 08-28 下午 UI 迭代 2(14:44-15:31)

  • 改名链路:周榜功能列「关注→分析」、功能名「关注账号→重点账号→账号列表」全链路联动(卡片/标题/面包屑/弹窗/复盘 GEN 枚举);重点账号列表「收藏」列→「关注」
  • 账号列表:重置按钮图标化(svgIcon refresh + title);去掉年龄/账号定位列(14→12列);账号名去加粗(.link.strong→.link);所有列表可点击链接深蓝 #2f6fed→浅蓝 #4a90e2(.link/.title-plain:hover/.md-body a)
  • AI写脚本弹窗:按钮「AI脚本→AI写脚本」+ 标题联动;选题输入框 84→168px;按账号是否有设定动态文案(按钮带 data-acc-id → 查 /api/dsh/account-persona → 有设定「基于当前账号设定生成脚本」/无「先进行账号设定分析」,prompt 同步联动;测试占位内容排除)
  • 设置弹窗:标题「项目地址设置→项目文件地址」、添加→确认、关闭按钮→右上角 ×(modal-title-row);desc 去掉「可添加其他项目地址」;placeholder→桌面具体路径 C:\Users\maidou\Desktop\MCNSkill项目
  • 路由记忆误伤修复(15:30):boot() 原在 URL 无 hash 时恢复 localStorage 上次路由(#/accounts)→ 用户访问 http://localhost:8899 根地址被强制跳 accounts;改为无 hash 一律回首页,带 hash 正常路由,删除自动恢复逻辑(saveRoute 保留)
  • ⚠️ 时间戳参数教训:为强制内置浏览器刷新加的 ?v=xxx 会让地址栏带尾巴、用户反感——改用干净 URL 重开 + 用户手动 F5;内置浏览器无 CDP 无法模拟刷新

工作台 08-28 下午 UI 迭代 3(15:31-16:30,会话总结恢复)

  • 返回层级修复:bindBack 固定 #/ → history.back() + 250ms hash 未变回首页兜底(视频详情返回不再误跳首页)
  • 账号详情页:page-detail + detail-body 内容区右移 10px(返回/tab 原位);账号信息 info-card 卡片化 + info-row 按行分组(行1:抖音号/年龄、行2:赛道/AI制作/地区、行3:作品数/粉丝/获赞/获取视频、行4:简介、行5:账号定位;行内左对齐 flex:0 0 auto、列间距 80px);账号定位 10 行 clamp + 展开/收起(.clamp-text/.clamp-btn);「账号视频列表」→「视频列表」;评论/分享 fmtWan(过万保留 1 位小数);无设定状态 .empty-state 居中排版(图标+标题+说明+btn-view 按钮,弃深蓝实心按钮)
  • 视频列表:发布时间移至首列 + 后端 ORDER BY v.publish_time IS NULL, v.publish_time DESC, v.id DESC;操作列统一「AI改写」(已解析 .btn-view 蓝字/未解析黑色,parsed 标志),弹窗按解析状态提示处理方式
  • AI写脚本页:标题 .title-plain data-ext 新标签开原视频;已改写列「N 查看」按钮(0 时「—」不可点,去对号);操作列「AI改写」+ th-act 居中
  • 查看弹窗重构:rw-stack/rw-sec 垂直三板块(源脚本/AI脚本/AI分镜提示词)等高(flex:1 + min-height:0);版本切换在对应板块右下 .rw-sec-foot;标题 fmtTitleQ(书名号只包标题主体 + # 后内容整体换行);弹窗 height: calc(100vh - 60px) 固定高度(max-height 在内容不足时不生效);关闭按钮右上(modal-title-row ×)
  • 首页卡片小字 4 张卡片 desc 定稿:账号周榜「三方数据 · 赛道/日期筛选」、账号列表「关注的账号 + 视频列表」、AI写脚本「AI生成脚本+分镜提示词」、AI写作复盘「检查清单+复盘报告」
  • boot() 删除 setInterval 20s 静默刷新(仅保留任务触发 refreshCurrentPage)

S9 格式修正:A 格式动作叙述去括号(17:02-17:15,用户确认后修改)

  • 背景:用户贴《留守包裹》A 格式脚本,质疑对白表演标注 (打开行李箱…) 与独立动作叙述 (娃儿们涌上来…) 都用括号
  • 影响分析:括号使用点——A 格式①对白行表演标注②独立动作叙述(本次去括号);B 格式角色名同行标注+纯动作/空镜括号(不动,07 指南 95/104 行);C 格式 (口播·语气)+B-roll 方括号(不动);D 格式画面描述/配乐/台词标注全括号(不动,07 指南 182 行)
  • 修改(源 + dsh 副本同步,共 3 文件 9 处):9_生成短视频脚本.md 5 处(处理规则 A 格式模板/场次书写规范表「动作叙述」行/System Prompt A 格式规则/禁止行为新增「不得给独立动作叙述段落套括号(A 格式)」/输出模板 A 格式)+ 07_脚本格式选择指南.md 2 处(A 格式内容格式+核心规则补「独立动作叙述段落不加括号」)+ 创作流程规范.md 2 处(A 格式模板+动作叙述规则)
  • 规则表述:括号仅用于对白行表演标注(A 格式另起一行 (动作/表情/语气)、画外 (画外)、B/C 格式角色名同行);A 格式无台词动作/场景连续叙述(多人行为/情绪反应/场景转换)裸写自然段落
  • 验证:三文件源与 dsh diff 一致;B/D 括号规则保留;全 V1.0 无 (动作叙述 模板残留(10 文件两处为文字描述非模板)
  • SKILL.md frontmatter:源+dsh 更新 last_change,dsh 的 updated_at/deployed_at → 08-28

工作台查看弹窗改横排三列 + 源脚本响应式收起(17:30-17:40)

  • 用户澄清需求:查看改写弹窗三板块(源脚本/AI脚本/AI分镜提示词)应为横着并排(左右三列),不是竖排;弹窗宽度不够时源脚本可收起不展示
  • 改 style.css(mcn-work-shop/public/):.rw-stack flex-direction column→row;.rw-sec 补 min-width:0(防内容撑破);新增 @media (max-width:1100px) 隐藏 .rw-sec:first-child(源脚本列收起,剩两列平分)
  • 验证(CDP 9223 + Emulation.setDeviceMetricsOverride):宽视口 2560px → row 三列各 341px(left 748/1102/1455);窄视口 1000px → 源脚本 disp:none,AI脚本+分镜各 428px 平分
  • ⚠️ 教训:goto_url 同 URL(hash 路由)不触发重新加载,验证 CSS 改动必须 location.reload() 强制刷新

AI写脚本列表账号可点击(17:35-17:40)

  • 用户需求:AI写脚本列表点击账号可查看账号详情
  • 改 data-pages.js renderRewrites 账号列:纯文本 → <a class="link" href="#/account/${v.account_id}">(复用 renderAccounts 的账号详情链接写法;接口 v.* 已含 account_id)
  • 验证(CDP):20 行账号全部变链接(首个 #/account/1631 白昼小熊),点击 → hash #/account/1631 → 页面标题「白昼小熊」渲染成功
  • 工具栏右对齐(toolbar-right + margin-right:10px,同账号列表页)+ 全部列表页功能栏与表格间距 14→24px(.page-toolbar margin-bottom 全局)
  • 写脚本页说明文字移出工具栏:.toolbar-note 小字 12px 右对齐放功能栏下(-14px 上贴工具栏,距表 16px)
  • 改写弹窗三列内容区等高:源脚本列补空 .rw-sec-foot 占位 + .rw-sec-foot min-height 46px + verCtrl 始终渲染 foot(len=1 显示「X 1/1」,len=0 空占位)→ 三列 body 均 1055px 等高
  • 源脚本默认收起:let showSrc=false 控制源脚本列 rw-sec-hidden(display:none);标题行加「源脚本/收起源脚本」切换按钮(data-src-toggle,.src-on 高亮态),点击重渲染弹窗;删除原 @media(max-width:1100px) 媒体查询(JS 接管);默认两列 518px 平分,展开后三列 341px

查看弹窗 AI分镜列常显 + 生成分镜按钮 + 源脚本按钮图标化(12:25-12:45)

  • 用户需求:AI分镜提示词区域默认展示(没有内容也空着);下面功能区域提供生成按钮;原脚本按钮变成图标
  • 改 data-pages.js openRewriteCompare:
    1. AI分镜列去掉 ${visibleSb.length ? ... : ''} 条件包裹 → 始终渲染 .rw-sec;无分镜时 body 显示 <div class="dim">(暂无分镜提示词)</div>
    2. foot 按状态分流:有分镜=verCtrl('s',...)(分镜 1/N + 上/下一版);无分镜=<button data-gen-sb>⚡ 生成分镜</button>
    3. data-gen-sb 点击 → confirmRun({title:'生成分镜', desc/prompt:'将基于该 AI 改写脚本展开成 AI 分镜提示词(按分镜技能生成镜头级描述)', label:'分镜指令', btn:genSb})(复用改写按钮同款任务触发链路)
    4. 源脚本按钮文字 → svgIcon('file-text', 14, 'currentColor') 图标(title 提示「展开源脚本/收起源脚本」切换;.src-on 高亮态保留)
  • 验证(CDP 9223 #/rewrites 标签页):v189 行(rewrite 21 有 2 分镜)→ 3 列常显、分镜 1/2+上/下一版、源脚本图标按钮(无文字)、展开后三列 body 1055px 等高 / foot 46px / 各 341px 等宽;v190 行(rewrite 25 无分镜)→ 空态 dim「(暂无分镜提示词)」+ foot「生成分镜」按钮(zap 图标)、AI脚本与分镜列 body 均 1031px 等高、点按钮弹出「生成分镜」确认弹窗(title/desc/target 正确)
  • 测试脚本用完即删(cdp-test*.mjs + 截图),工作区无残留

已有分镜的 AI 脚本提供「重新生成」按钮(17:56-18:00)

  • 用户需求:已经生成分镜的 AI 脚本,foot 也提供按钮可重新生成分镜
  • 改 data-pages.js:verCtrl(p, idx, len, label, genLabel) 增加可选第5参——有值时 foot 尾部追加 <button data-${p}gen>⟳ {genLabel}</button>(refresh 图标 14px currentColor);分镜列调用 verCtrl('s', sbIdx, visibleSb.length, '分镜', '重新生成')(AI脚本列 verCtrl('v',...) 不传,不受影响)
  • 事件:抽出通用 fireGenSb(btn, regenerate) → confirmRun({title: regenerate?'重新生成分镜':'生成分镜', prompt 文案 regenerate 时加「重新」});[data-gen-sb](无分镜,zap 图标)与 [data-sgen](有分镜,refresh 图标)两个按钮绑定复用
  • 验证(CDP 9223):v189 行(2 分镜)foot=「分镜 1/2 ← 上一版 下一版 → ⟳ 重新生成」(无溢出,count margin-right:auto 推右),点按钮弹「重新生成分镜」确认窗;v190 行(无分镜)仍只显「⚡ 生成分镜」不受影响

查看弹窗 AI脚本↔AI分镜 场次联动滚动(17:59-18:30)

  • 用户需求:滑动 AI脚本 滑到哪一场,右边 AI分镜提示词对应滚动到那一场
  • 数据结构:AI脚本场标题=**场N:…**(renderMarkdown→<p><strong>);分镜块=段N(x-y秒)|场M:…(一场可拆多段:场2前半/后半),renderSbBlocks→.sb-block/.sb-head
  • 改 data-pages.js renderModal(仅 visibleSb.length>0 时绑定):sync()——①AI脚本列 strong,h1-h4 过滤 /场\s*\d/ 得场标题数组(DOM 顺序=文档顺序)②limit=aiBody.scrollTop+60,找最后一个 rect.top-aiTop+scrollTop <= limit 的标题=当前场 ③正则提取场号 N ④分镜列 .sb-block 中 find 第一个 head 匹配 场N(?=前半|后半|[::]|\s|$) 的块 ⑤sbBody.scrollTop = target.rect.top - sbBody.rect.top + sbBody.scrollTop(不用 offsetTop,防 offsetParent 歧义);aiBody.addEventListener('scroll', sync, {passive:true}) + 打开时 sync() 一次
  • ⚠️ rAF 教训(重要):初版用 requestAnimationFrame(sync) 节流,CDP 9223 tab visibilityState=hidden rAF 不触发→联动失效;改为直接同步调用 sync(计算量小:30 strong + 8 块,性能无碍)。CDP 验证场景禁依赖 rAF
  • ⚠️ 测试脚本转义教训:bash heredoc 写 .mjs 里 /场\s*\d/ 单反斜杠 → Node 解析 JS 字符串时 \s→s(无效转义丢反斜杠)→ 正则变 场s*\d 不匹配,误判 2 小时;JS 字符串里正则必须写 \\s(Edit 工具直写文件的正则字面量不受影响,产品代码一直是对的)
  • 验证(CDP reload 后):S0 打开弹窗初始对齐场1(sbScrollTop 12);滑到场3→分镜 4392 可见「场3:老屋堂屋·当天傍晚」;场5→8528「场5:老屋灶房·高三深夜」;回场1→12;四条链路全过

场次联动回退单向 + 修复段名格式正则 bug(18:30-19:05)

  • 用户明确:不要双向联动,只允许 AI脚本为主导的联动——删 syncAi 反向逻辑与 sbBody.addEventListener('scroll', syncAi),仅保留 syncSb(AI脚本列滚动 → 分镜列对齐)
  • 🐛 P0 真 bug(本次核心):syncSb 里分镜块匹配正则 场N(?=前半|后半|[::]|\s|$) 只兼容「场N:标题」冒号格式与「前半/后半」段名;video 190 实际 head 是「场1前段/场3中段/场3中后段/场4末段」(前段/后段/中段/中后段/末段 5 种段名)→ 正则完全不匹配 → target 永远 undefined → 联动失效(之前会话验证的「场3:老屋堂屋」是冒号格式数据,掩盖了此 bug)
  • 修复:new RegExp('场' + m[1] + '(?![0-9])')——负向前瞻防 场1 误匹配 场10,兼容全部段名格式与冒号格式
  • 验证(CDP #/rewrites 页 video 190 rewrite 22,18 分镜块):
    • ① AI脚本主导:滚 400/800(limit 未跨场2标题 t=887)→ 仍对齐场1(正确);滚 1200(limit 1260 > 887)→ 分镜列 12→2473 对齐场2前段 ✅
    • ② 分镜列独立:分镜列 600→3073,AI脚本列 1200 纹丝不动 ✅(无反向联动)
    • ③ 跳底:AI列 5621 → 分镜列 17480 对齐场6前段(场6 t=5567 ≤ limit 5681)✅
  • ⚠️ CDP 新教训:scrollTop 赋值不触发 scroll 事件监听(fired 0;Chrome 将 scroll 事件异步/合并派发),dispatchEvent(new Event('scroll')) 才触发(fired 1);验证脚本必须设置 scrollTop 后手动补发 scroll 事件;真实用户滚轮不受影响(真实滚动正常派发事件)
  • 测试脚本:保留 cdp-verify-oneway2.mjs(最终验证版),其余 cdp-probe/debug/regex/event 探针已删

视频标题去首尾引号(18:34-18:45)

  • 用户反馈:video 190「他守住的不止是那份快递…」标题带引号,要去掉
  • 根因:fmtTitleQ 只清了尾部引号([\s"“”']+$),开头引号没处理 → 弹窗显示 《"他守住…》;列表页完整标题(含 #标签)的引号在 # 前,也不在字符串首尾
  • 修复(app.js + data-pages.js):
    • app.js 新增 2 个工具:stripTitleQuotes(s)(清整串首尾引号:英文/中文双引号/单引号/「『」』,仅首尾中间保留)+ cleanTitle(t)(# 前主体去引号、# 标签原样保留——列表页完整标题用)
    • fmtTitleQ 改调 stripTitleQuotes(弹窗);列表页/视频详情/改写按钮 payload/首页最近脚本 8 处显示改调 cleanTitle
  • 验证(CDP):列表页 他守住的不止是那份快递,还守住了留守孩子们的那份期待#AI创作浪潮计划… 无引号;弹窗 《他守住的不止是那份快递…》⏎#… 无引号 ✅
  • 工具函数定义在 app.js 顶层(先加载),data-pages.js 直接复用(全局 lexical scope 共享)

查看改写弹窗宽度自适应(18:38-18:40)

  • 用户需求:「已改写 → N 查看」弹窗距网页左右各 50px,视口变宽弹窗跟着变宽,最大 1400px
  • 改 style.css 347 行:.rw-modal width min(1100px, 95vw) → min(1400px, calc(100% - 100px))(全局 border-box,100% 相对 mask fixed inset:0 视口宽,不含滚动条)
  • 验证(CDP 多视口):1200→1085(视口-100,左右 50/50);1400→1285;1600/1920/2200→1400 封顶居中 ✅

移植 dsh「热门账号→导入」功能到工作台(19:15-19:35)

  • 用户需求:「账号列表页就是dsh插件 热门账号,里面还有个导入功能看看能否移植过来」
  • dsh 原链路调研(dsh-plugin-douyin-accounts/client.js + dsh-plugin-mcn/index.js):弹窗两种方式(方式一账号名/抖音号/地址 3 输入框、方式二本地文件夹路径)→ POST /mcn/api/external/stage(账号模式浏览器采集+AI会话确认,browserTaskRunning 409 互斥;目录模式直接 stage)→ preview(AI 确认前扫描比对不写库)→ import 写库
  • 移植设计(工作台不直连 dsh /mcn 接口):前端加「导入账号」按钮 + 同款弹窗 → 复用 executeTask 提交 prompt 任务到 /api/run(左侧 mcn-workshop 会话栏可见,与「保存并分析」同构)→ WorkBuddy AI 执行导入 → 轮询完成自动刷新;确认环节由弹窗「提交导入」承担(dsh 的 AI 会话确认 → 工作台的 executeTask 任务模式)
  • 改动:app.js 新增 download 图标 + openImportAccounts(btn)(弹窗两种方式、空校验 toast「请填写抖音账号信息或文件夹路径」、prompt 按目录/账号两种拼法、label「导入指令」);data-pages.js renderAccounts 工具栏加「导入账号」按钮(svgIcon download);style.css 补 .import-form 4 类样式;帮助页「账号分析」组加问法「把抖音账号「俊希」导入账号列表」
  • 验证(CDP 9223 + fetch mock 零副作用):弹窗打开→4 输入框齐全→空提交 toast 校验→填账号提交→弹窗关闭+按钮「执行中…」+ /api/run prompt 正确→mock done 轮询→按钮恢复「导入」✅;帮助页问法 13 条含导入 ✅
  • ⚠️ 两个坑:①页面有常驻隐藏 #settingsModal(index.html 静态弹窗),DOM 选择器查弹窗必须 .modal-mask:not([hidden])(否则匹配到设置弹窗误判);②fetch mock 判断顺序必须 /api/run/status 在前(includes('/api/run') 会先吞掉 status 请求)
  • 验证脚本保留 cdp-verify-import.mjs(含 fetch mock 模式,可复用)

查看弹窗:展开源脚本按钮移入 AI脚本 标题 + 弹窗最大宽度 1600(18:48-19:00)

  • 用户需求:①「展开原脚本」按钮图标放到 AI脚本 标题右边,间隔 10px(原在弹窗顶部 modal-title-row)②弹窗最大宽度 1400→1600
  • 改 data-pages.js:modal-title-row 删 data-src-toggle(保留标题+×);AI脚本列 .rw-sec-head 内追加 <button class="btn btn-sm btn-view rw-src-toggle" data-src-toggle>${svgIcon('file-text')}(src-on 高亮态保留)
  • 改 style.css:.rw-sec-head 加 display:flex; align-items:center; gap:10px(标题右侧放操作按钮,间隔 10px);.rw-modal width min(1400px,…) → min(1600px, calc(100% - 100px)),注释同步
  • 验证(CDP #/rewrites):按钮在 AI脚本 head 内、与文字 gap=10px 精确、垂直对齐、顶栏无残留 ✅;点击展开源脚本列 + title 切「收起源脚本」✅;宽度 1200→1085 / 1500→1380 / 1700→1564 / 2000→1600 封顶居中 ✅
  • ⚠️ 左右边距探针:right:65 不是 bug——mask(fixed inset:0) 宽=clientWidth 1185(不含滚动条),弹窗 calc(100%-100)=1085 在 mask 内精确居中左右各 50;15px 是页面右侧 classic 滚动条区域,滚动条左缘到弹窗恰 50px;无滚动条页面左右严格 50/50
  • 验证脚本保留 cdp-verify-srcbtn1600.mjs

关闭服务 + 以本地为准同步仓库(18:51-18:55)

  • 关闭服务:工作台 node 服务 PID 28424(127.0.0.1:8899)taskkill 停止;0.0.0.0:8899 的 20604 是 MiPCAudio.exe 占位不动;Git Bash taskkill //PID 参数会被 MSYS 转换报错,改 PowerShell Stop-Process
  • 提交(ab97842,155 文件):工作台导入功能/弹窗优化 + 短视频提示词生成 138 文件整体移入 project/短视频脚本创作/V1.0/subskill/mcn-video-prompt/(git 识别为 R100 纯重命名保留历史,与 mcn-dou-analysis 同构);未提交项有意排除:.workbuddy/tmp/(edge-cdp 调试临时)、server.log、cdp-wheel*.mjs(旧滚轮探针)
  • 以本地为准推送(用户明确「不用拉取 直接同步」):git pull 走 22 端口超时 + 沙箱拦截 ~/.ssh 读取被用户拒 → 改用 GIT_SSH_COMMAND="ssh -p 222 -o StrictHostKeyChecking=accept-new" git push origin main ✅ fast-forward 成功(9b0c198..ab97842),这次 push 后 origin/main 跟踪引用未丢失(refs/remotes/origin/main 正常)

账号周榜 5 数值列加宽(17:56-18:00)

  • 用户需求:「账号周榜 列表中 下面的列宽度可以在大一些:综合得分 / 新增粉丝 / 新增点赞 / 新增评论 / 新增分享」
  • 改 data-pages.js(renderRanking):const WIDE = new Set(['comprehensiveScore','newFans','newLikes','newComments','newShares']) → sortable() 工厂给命中 key 的 th 追加 th-wide class
  • 改 style.css(.sortable:hover 后):.th-wide { min-width: 110px; }(表格为 auto 布局,数值列加 min-width 即可增宽,不影响内容列)
  • 验证(CDP #/ranking 只读测量):5 列均带 th-wide、实测宽 122px ≥110px ✅、computed min-width 110px;对照列不受影响(rank 56 / 赛道 90 / followers 98 / 功能 77);20 行数据正常渲染
  • 验证脚本保留 cdp-verify-rankwide.mjs(含列宽测量 + computed style 校验,可复用)

旧梦留声机账号设定卡 + 功能六固化(17:50-18:00 前段多轮迭代,本段收尾)

  • SVG 迭代定版:桌面/MCNSkill项目/旧梦留声机/旧梦留声机账号设定卡.svg,viewBox 0 0 680 1716 深棕红渐变底(#2B0F0A→#1A0805)+ 顶部浅米大框(280px 主标题+16px 副题「账号设定卡」)+ 内容路线 6 格浅米卡 + 核心气质 12 chips + 六大内容基因 186×130(GENE 0X 珊瑚红小标签)+ 色彩体系 5 色卡 h=80 + 角色类型库 186×130(中文名+英文代号大写斜体)+ 情绪图条形(76/32/64/112/84/52/72 底边对齐 y=1452)+ 小字总结行 y=1506 + 红线清单 6 条 2×3 + 版权
  • 功能六固化(生成账号设定卡片):新建 references/feature/06_生成账号设定卡片.md(输入/产出/五步方式含①.5读模板样例/模块裁剪适配表/配色适配/要求配色规范表/格式/7条避坑/完成汇报)+ references/样例/(模板_旧梦留声机账号设定卡.svg + 参考PNG,源+dsh 两副本)+ SKILL.md 功能总览五大→六大 + 新增「八、功能六」章节 + 部署禁用说明(功能六无连带文件)
  • 收尾完善(本次):①SKILL.md 2.2 技能库路径表补录「功能六流程」+「账号设定卡模板样例」两行(源+dsh);②R. REPayer→R. REPAYER 大小写统一(模板源/dsh/桌面成品三处,其余代号全大写)
  • 验证:源技能 vs dsh 副本 SKILL.md/模板SVG/06功能文件三组 diff 全一致;REPayer 全库零残留
  • 沉淀要点(供下次生成其他账号设定卡):先读 references/样例/ 模板(复用版式骨架与样式常量,内容全替换);角色英文代号=大写首字母缩写+单词全大写;情绪图条形底边对齐峰谷差≥40px;文字垂直居中 y=中心;批量移动坐标用脚本统一加减防双重偏移;红线全量;改完必 present_files 预览确认