auto-save 2026-05-14 00:48 (+4, ~3)
This commit is contained in:
@@ -2691,6 +2691,13 @@
|
||||
"type": "session-heartbeat",
|
||||
"message": "Claude 会话活跃 · 最近命令:claude · 3 项未提交变更 · 最近提交:auto-save 2026-05-14 00:37 (+1, ~2)",
|
||||
"files_changed": 3
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-14T00:43:18+08:00",
|
||||
"type": "commit",
|
||||
"message": "auto-save 2026-05-14 00:42 (+4, ~3)",
|
||||
"hash": "042efdc",
|
||||
"files_changed": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
13
.playwright-mcp/page-2026-05-13T16-45-57-495Z.yml
Normal file
13
.playwright-mcp/page-2026-05-13T16-45-57-495Z.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e6] [cursor=pointer]:
|
||||
- button "Open Next.js Dev Tools" [ref=e7]:
|
||||
- img [ref=e8]
|
||||
- generic [ref=e13]:
|
||||
- button "Open issues overlay" [ref=e14]:
|
||||
- generic [ref=e15]:
|
||||
- generic [ref=e16]: "0"
|
||||
- generic [ref=e17]: "1"
|
||||
- generic [ref=e18]: Issue
|
||||
- button "Collapse issues badge" [ref=e19]:
|
||||
- img [ref=e20]
|
||||
- 'heading "Application error: a client-side exception has occurred while loading localhost (see the browser console for more information)." [level=2] [ref=e24]'
|
||||
131
.playwright-mcp/page-2026-05-13T16-45-59-775Z.yml
Normal file
131
.playwright-mcp/page-2026-05-13T16-45-59-775Z.yml
Normal file
@@ -0,0 +1,131 @@
|
||||
- generic [ref=e1]:
|
||||
- generic [active]:
|
||||
- generic [ref=e27]:
|
||||
- generic [ref=e28]:
|
||||
- generic [ref=e29]:
|
||||
- navigation [ref=e30]:
|
||||
- button "previous" [disabled] [ref=e31]:
|
||||
- img "previous" [ref=e32]
|
||||
- generic [ref=e34]:
|
||||
- generic [ref=e35]: 1/
|
||||
- text: "1"
|
||||
- button "next" [disabled] [ref=e36]:
|
||||
- img "next" [ref=e37]
|
||||
- img
|
||||
- generic [ref=e39]:
|
||||
- link "Next.js 16.0.7 (stale) Turbopack" [ref=e40] [cursor=pointer]:
|
||||
- /url: https://nextjs.org/docs/messages/version-staleness
|
||||
- img [ref=e41]
|
||||
- generic "There is a newer version (16.2.6) available, upgrade recommended!" [ref=e43]: Next.js 16.0.7 (stale)
|
||||
- generic [ref=e44]: Turbopack
|
||||
- img
|
||||
- dialog "Runtime ReferenceError" [ref=e46]:
|
||||
- generic [ref=e49]:
|
||||
- generic [ref=e50]:
|
||||
- generic [ref=e51]:
|
||||
- generic [ref=e53]: Runtime ReferenceError
|
||||
- generic [ref=e54]:
|
||||
- button "Copy Error Info" [ref=e55] [cursor=pointer]:
|
||||
- img [ref=e56]
|
||||
- button "No related documentation found" [disabled] [ref=e58]:
|
||||
- img [ref=e59]
|
||||
- link "Learn more about enabling Node.js inspector for server code with Chrome DevTools" [ref=e61] [cursor=pointer]:
|
||||
- /url: https://nextjs.org/docs/app/building-your-application/configuring/debugging#server-side-code
|
||||
- img [ref=e62]
|
||||
- generic [ref=e74]: Cannot access 'pinnedNodes' before initialization
|
||||
- generic [ref=e76]:
|
||||
- paragraph [ref=e78]:
|
||||
- text: Call Stack
|
||||
- generic [ref=e79]: "13"
|
||||
- generic [ref=e80]:
|
||||
- generic [ref=e81]:
|
||||
- text: Home
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e82] [cursor=pointer]:
|
||||
- img [ref=e83]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/_377ebb54._.js (6845:9)
|
||||
- generic [ref=e85]:
|
||||
- generic [ref=e86]:
|
||||
- text: Object.react_stack_bottom_frame
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e87] [cursor=pointer]:
|
||||
- img [ref=e88]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/e559b_next_dist_compiled_react-dom_e6182150._.js (14816:24)
|
||||
- generic [ref=e90]:
|
||||
- generic [ref=e91]:
|
||||
- text: renderWithHooks
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e92] [cursor=pointer]:
|
||||
- img [ref=e93]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/e559b_next_dist_compiled_react-dom_e6182150._.js (4645:24)
|
||||
- generic [ref=e95]:
|
||||
- generic [ref=e96]:
|
||||
- text: updateFunctionComponent
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e97] [cursor=pointer]:
|
||||
- img [ref=e98]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/e559b_next_dist_compiled_react-dom_e6182150._.js (6106:21)
|
||||
- generic [ref=e100]:
|
||||
- generic [ref=e101]:
|
||||
- text: beginWork
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e102] [cursor=pointer]:
|
||||
- img [ref=e103]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/e559b_next_dist_compiled_react-dom_e6182150._.js (6702:24)
|
||||
- generic [ref=e105]:
|
||||
- generic [ref=e106]:
|
||||
- text: runWithFiberInDEV
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e107] [cursor=pointer]:
|
||||
- img [ref=e108]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/e559b_next_dist_compiled_react-dom_e6182150._.js (959:74)
|
||||
- generic [ref=e110]:
|
||||
- generic [ref=e111]:
|
||||
- text: performUnitOfWork
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e112] [cursor=pointer]:
|
||||
- img [ref=e113]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/e559b_next_dist_compiled_react-dom_e6182150._.js (9556:97)
|
||||
- generic [ref=e115]:
|
||||
- generic [ref=e116]:
|
||||
- text: workLoopSync
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e117] [cursor=pointer]:
|
||||
- img [ref=e118]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/e559b_next_dist_compiled_react-dom_e6182150._.js (9450:40)
|
||||
- generic [ref=e120]:
|
||||
- generic [ref=e121]:
|
||||
- text: renderRootSync
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e122] [cursor=pointer]:
|
||||
- img [ref=e123]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/e559b_next_dist_compiled_react-dom_e6182150._.js (9434:13)
|
||||
- generic [ref=e125]:
|
||||
- generic [ref=e126]:
|
||||
- text: performWorkOnRoot
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e127] [cursor=pointer]:
|
||||
- img [ref=e128]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/e559b_next_dist_compiled_react-dom_e6182150._.js (9099:47)
|
||||
- generic [ref=e130]:
|
||||
- generic [ref=e131]:
|
||||
- text: performWorkOnRootViaSchedulerTask
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e132] [cursor=pointer]:
|
||||
- img [ref=e133]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/e559b_next_dist_compiled_react-dom_e6182150._.js (10224:9)
|
||||
- generic [ref=e135]:
|
||||
- generic [ref=e136]:
|
||||
- text: MessagePort.performWorkUntilDeadline
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e137] [cursor=pointer]:
|
||||
- img [ref=e138]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/e559b_next_dist_compiled_4535dad2._.js (2647:64)
|
||||
- generic [ref=e140]:
|
||||
- generic [ref=e141]:
|
||||
- text: ClientPageRoot
|
||||
- button "Sourcemapping failed. Click to log cause of error." [ref=e142] [cursor=pointer]:
|
||||
- img [ref=e143]
|
||||
- text: file:///Users/kangwan/Projects/business/20260512-20260512-skg-tk-%E4%BA%8C%E5%88%9B%E9%AA%8C%E8%AF%81/web/.next/dev/static/chunks/e559b_next_dist_03f6cd6c._.js (2202:50)
|
||||
- generic [ref=e145]: "1"
|
||||
- generic [ref=e146]: "2"
|
||||
- generic [ref=e6] [cursor=pointer]:
|
||||
- button "Open Next.js Dev Tools" [ref=e7]:
|
||||
- img [ref=e8]
|
||||
- generic [ref=e13]:
|
||||
- button "Open issues overlay" [ref=e14]:
|
||||
- generic [ref=e15]:
|
||||
- generic [ref=e16]: "0"
|
||||
- generic [ref=e17]: "1"
|
||||
- generic [ref=e18]: Issue
|
||||
- button "Collapse issues badge" [ref=e19]:
|
||||
- img [ref=e20]
|
||||
- 'heading "Application error: a client-side exception has occurred while loading localhost (see the browser console for more information)." [level=2] [ref=e24]'
|
||||
17
.playwright-mcp/page-2026-05-13T16-46-28-588Z.yml
Normal file
17
.playwright-mcp/page-2026-05-13T16-46-28-588Z.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- main [ref=e3]:
|
||||
- application [ref=e6]:
|
||||
- img
|
||||
- generic "Control Panel" [ref=e9]:
|
||||
- button "Zoom In" [ref=e10] [cursor=pointer]:
|
||||
- img [ref=e11]
|
||||
- button "Zoom Out" [ref=e13] [cursor=pointer]:
|
||||
- img [ref=e14]
|
||||
- button "Fit View" [ref=e16] [cursor=pointer]:
|
||||
- img [ref=e17]
|
||||
- button "Toggle Interactivity" [ref=e19] [cursor=pointer]:
|
||||
- img [ref=e20]
|
||||
- img "Mini Map" [ref=e23]
|
||||
- region "Notifications alt+T"
|
||||
- button "Open Next.js Dev Tools" [ref=e30] [cursor=pointer]:
|
||||
- img [ref=e31]
|
||||
449
.playwright-mcp/page-2026-05-13T16-46-30-804Z.yml
Normal file
449
.playwright-mcp/page-2026-05-13T16-46-30-804Z.yml
Normal file
@@ -0,0 +1,449 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e29] [cursor=pointer]:
|
||||
- button "Open Next.js Dev Tools" [ref=e30]:
|
||||
- img [ref=e31]
|
||||
- generic [ref=e36]:
|
||||
- button "Open issues overlay" [ref=e37]:
|
||||
- generic [ref=e38]:
|
||||
- generic [ref=e39]: "0"
|
||||
- generic [ref=e40]: "1"
|
||||
- generic [ref=e41]: Issue
|
||||
- button "Collapse issues badge" [ref=e42]:
|
||||
- img [ref=e43]
|
||||
- main [ref=e46]:
|
||||
- button "切到明亮主题" [ref=e48]:
|
||||
- img [ref=e49]
|
||||
- generic [ref=e55]:
|
||||
- generic [ref=e58]:
|
||||
- generic [ref=e59]:
|
||||
- img [ref=e60]
|
||||
- generic [ref=e65]: 分镜头编排
|
||||
- generic [ref=e66]: 0 分镜 · 0 元素
|
||||
- generic [ref=e67]: · 组织分镜画面 → 为生成视频做准备
|
||||
- button "展开编排" [disabled] [ref=e69]:
|
||||
- img [ref=e70]
|
||||
- text: 展开编排
|
||||
- application [ref=e73]:
|
||||
- generic [ref=e75]:
|
||||
- generic:
|
||||
- generic:
|
||||
- img:
|
||||
- group "Edge from input to keyframe" [ref=e76] [cursor=pointer]
|
||||
- img:
|
||||
- group "Edge from input to asr" [ref=e79] [cursor=pointer]
|
||||
- img:
|
||||
- group "Edge from asr to translate"
|
||||
- img:
|
||||
- group "Edge from translate to rewrite" [ref=e82] [cursor=pointer]
|
||||
- img:
|
||||
- group "Edge from keyframe to storyboard" [ref=e85] [cursor=pointer]
|
||||
- img:
|
||||
- group "Edge from rewrite to storyboard" [ref=e88] [cursor=pointer]
|
||||
- img:
|
||||
- group "Edge from storyboard to videogen" [ref=e91] [cursor=pointer]
|
||||
- img:
|
||||
- group "Edge from videogen to compose" [ref=e94] [cursor=pointer]
|
||||
- img:
|
||||
- group "Edge from rewrite to compose" [ref=e97] [cursor=pointer]
|
||||
- generic:
|
||||
- group [ref=e100]:
|
||||
- generic [ref=e101]:
|
||||
- generic [ref=e102]:
|
||||
- button "再上传一个视频" [ref=e103]:
|
||||
- img [ref=e104]
|
||||
- generic [ref=e105]:
|
||||
- button "64.5s" [ref=e106]:
|
||||
- generic [ref=e108]: 64.5s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 1080×1920
|
||||
- generic: 64.5s
|
||||
- generic [ref=e109]:
|
||||
- button "72.4s" [ref=e110]:
|
||||
- generic [ref=e112]: 72.4s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 576×1024
|
||||
- generic: 72.4s
|
||||
- generic [ref=e113]:
|
||||
- button "64.5s" [ref=e114]:
|
||||
- generic [ref=e116]: 64.5s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 1080×1920
|
||||
- generic: 64.5s
|
||||
- generic [ref=e117]:
|
||||
- button "71.4s" [ref=e118]:
|
||||
- generic [ref=e120]: 71.4s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 1080×1920
|
||||
- generic: 71.4s
|
||||
- generic [ref=e121]:
|
||||
- button "72.4s" [ref=e122]:
|
||||
- generic [ref=e124]: 72.4s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 576×1024
|
||||
- generic: 72.4s
|
||||
- generic [ref=e125]:
|
||||
- button "71.4s" [ref=e126]:
|
||||
- generic [ref=e128]: 71.4s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 1080×1920
|
||||
- generic: 71.4s
|
||||
- generic [ref=e129]:
|
||||
- button "71.4s" [ref=e130]:
|
||||
- generic [ref=e132]: 71.4s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 1080×1920
|
||||
- generic: 71.4s
|
||||
- generic [ref=e133]:
|
||||
- button "71.4s" [ref=e134]:
|
||||
- generic [ref=e136]: 71.4s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 1080×1920
|
||||
- generic: 71.4s
|
||||
- generic [ref=e137]:
|
||||
- button "71.4s" [ref=e138]:
|
||||
- generic [ref=e140]: 71.4s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 1080×1920
|
||||
- generic: 71.4s
|
||||
- generic [ref=e141]:
|
||||
- button "71.4s" [ref=e142]:
|
||||
- generic [ref=e144]: 71.4s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 1080×1920
|
||||
- generic: 71.4s
|
||||
- generic [ref=e145]:
|
||||
- button "8.0s" [ref=e146]:
|
||||
- generic [ref=e148]: 8.0s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 640×360
|
||||
- generic: 8.0s
|
||||
- generic [ref=e149]:
|
||||
- button "8.0s" [ref=e150]:
|
||||
- generic [ref=e152]: 8.0s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 640×360
|
||||
- generic: 8.0s
|
||||
- generic [ref=e153]:
|
||||
- button "8.0s" [ref=e154]:
|
||||
- generic [ref=e156]: 8.0s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 640×360
|
||||
- generic: 8.0s
|
||||
- generic [ref=e157]:
|
||||
- button "8.0s" [ref=e158]:
|
||||
- generic [ref=e160]: 8.0s
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 640×360
|
||||
- generic: 8.0s
|
||||
- button "…" [ref=e162]:
|
||||
- img [ref=e164]
|
||||
- generic [ref=e166]: …
|
||||
- button "…" [ref=e168]:
|
||||
- img [ref=e170]
|
||||
- generic [ref=e172]: …
|
||||
- button "…" [ref=e174]:
|
||||
- img [ref=e176]
|
||||
- generic [ref=e178]: …
|
||||
- generic [ref=e179]:
|
||||
- generic [ref=e180]:
|
||||
- img [ref=e182]
|
||||
- generic [ref=e185]: 输入 · Input
|
||||
- generic [ref=e186]:
|
||||
- img [ref=e187]
|
||||
- button "钉住 · 锁定位置与尺寸" [ref=e191]:
|
||||
- img [ref=e192]
|
||||
- generic [ref=e195]:
|
||||
- generic [ref=e196]: STEP 1 · 视频就绪 · 完成
|
||||
- textbox "再加一个 TK 链接" [ref=e197]
|
||||
- generic [ref=e198]:
|
||||
- button "+ 加链接" [disabled] [ref=e199]
|
||||
- button "再传一个" [ref=e200]:
|
||||
- img [ref=e201]
|
||||
- text: 再传一个
|
||||
- generic [ref=e204]:
|
||||
- generic [ref=e205]: 1080×1920 · 64.5s
|
||||
- generic [ref=e206]: 🔗 链接
|
||||
- button "重新解析" [ref=e207]
|
||||
- generic "拖动调整宽度" [ref=e209]
|
||||
- generic "拖动调整大小(宽 × 高)" [ref=e210]
|
||||
- group [ref=e211]:
|
||||
- generic [ref=e212]:
|
||||
- generic [ref=e213]:
|
||||
- generic [ref=e214]:
|
||||
- button "frame 9 1.7s" [ref=e215]:
|
||||
- img "frame 9" [ref=e216]
|
||||
- generic [ref=e217]: 1.7s
|
||||
- button "📋" [ref=e218]
|
||||
- button "删除该关键帧" [ref=e219]:
|
||||
- img [ref=e220]
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 分镜 10
|
||||
- generic: 1.66s
|
||||
- generic [ref=e223]:
|
||||
- button "frame 0 ✨ 24.7s" [ref=e224]:
|
||||
- img "frame 0" [ref=e225]
|
||||
- generic "已清洗" [ref=e227]: ✨
|
||||
- generic [ref=e228]: 24.7s
|
||||
- button "📋" [ref=e229]
|
||||
- button "删除该关键帧" [ref=e230]:
|
||||
- img [ref=e231]
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 分镜 1
|
||||
- generic: 24.73s
|
||||
- generic [ref=e234]:
|
||||
- button "frame 1 33.6s" [ref=e235]:
|
||||
- img "frame 1" [ref=e236]
|
||||
- generic [ref=e237]: 33.6s
|
||||
- button "📋" [ref=e238]
|
||||
- button "删除该关键帧" [ref=e239]:
|
||||
- img [ref=e240]
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 分镜 2
|
||||
- generic: 33.61s
|
||||
- generic [ref=e243]:
|
||||
- button "frame 2 37.7s" [ref=e244]:
|
||||
- img "frame 2" [ref=e245]
|
||||
- generic [ref=e246]: 37.7s
|
||||
- button "📋" [ref=e247]
|
||||
- button "删除该关键帧" [ref=e248]:
|
||||
- img [ref=e249]
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 分镜 3
|
||||
- generic: 37.70s
|
||||
- generic [ref=e252]:
|
||||
- button "frame 3 39.4s" [ref=e253]:
|
||||
- img "frame 3" [ref=e254]
|
||||
- generic [ref=e255]: 39.4s
|
||||
- button "📋" [ref=e256]
|
||||
- button "删除该关键帧" [ref=e257]:
|
||||
- img [ref=e258]
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 分镜 4
|
||||
- generic: 39.42s
|
||||
- generic [ref=e261]:
|
||||
- button "frame 4 1 43.1s" [ref=e262]:
|
||||
- img "frame 4" [ref=e263]
|
||||
- generic "1 个元素已抠图" [ref=e265]: "1"
|
||||
- generic [ref=e266]: 43.1s
|
||||
- button "📋" [ref=e267]
|
||||
- button "删除该关键帧" [ref=e268]:
|
||||
- img [ref=e269]
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 分镜 5
|
||||
- generic: 43.13s
|
||||
- generic [ref=e272]:
|
||||
- button "frame 5 45.0s" [ref=e273]:
|
||||
- img "frame 5" [ref=e274]
|
||||
- generic [ref=e275]: 45.0s
|
||||
- button "📋" [ref=e276]
|
||||
- button "删除该关键帧" [ref=e277]:
|
||||
- img [ref=e278]
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 分镜 6
|
||||
- generic: 45.05s
|
||||
- generic [ref=e281]:
|
||||
- button "frame 6 53.6s" [ref=e282]:
|
||||
- img "frame 6" [ref=e283]
|
||||
- generic [ref=e284]: 53.6s
|
||||
- button "📋" [ref=e285]
|
||||
- button "删除该关键帧" [ref=e286]:
|
||||
- img [ref=e287]
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 分镜 7
|
||||
- generic: 53.60s
|
||||
- generic [ref=e290]:
|
||||
- button "frame 7 56.0s" [ref=e291]:
|
||||
- img "frame 7" [ref=e292]
|
||||
- generic [ref=e293]: 56.0s
|
||||
- button "📋" [ref=e294]
|
||||
- button "删除该关键帧" [ref=e295]:
|
||||
- img [ref=e296]
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 分镜 8
|
||||
- generic: 55.96s
|
||||
- generic [ref=e299]:
|
||||
- button "frame 8 58.4s" [ref=e300]:
|
||||
- img "frame 8" [ref=e301]
|
||||
- generic [ref=e302]: 58.4s
|
||||
- button "📋" [ref=e303]
|
||||
- button "删除该关键帧" [ref=e304]:
|
||||
- img [ref=e305]
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 分镜 9
|
||||
- generic: 58.39s
|
||||
- generic [ref=e308]:
|
||||
- generic [ref=e310]:
|
||||
- img [ref=e312]
|
||||
- generic [ref=e316]: 镜头拆解 · 元素提取
|
||||
- generic [ref=e317]:
|
||||
- img [ref=e318]
|
||||
- button "钉住 · 锁定位置与尺寸" [ref=e322]:
|
||||
- img [ref=e323]
|
||||
- generic [ref=e326]:
|
||||
- generic [ref=e327]: STEP 2 · 0/10 入编排 · 完成
|
||||
- generic [ref=e328]:
|
||||
- text: 自动 10 张 ·
|
||||
- generic [ref=e329]: 1 已清洗
|
||||
- text: ·
|
||||
- generic [ref=e330]: 1/2 已抠图
|
||||
- text: 点缩略图 → 清洗水印 / 提取可借鉴元素 → 改造成 SKG 画面素材
|
||||
- generic "拖动调整宽度" [ref=e332]
|
||||
- generic "拖动调整大小(宽 × 高)" [ref=e333]
|
||||
- group [ref=e334]:
|
||||
- generic [ref=e335]:
|
||||
- generic [ref=e337]:
|
||||
- img [ref=e339]
|
||||
- generic [ref=e342]: 声音文案 · ASR
|
||||
- button "钉住 · 锁定位置与尺寸" [ref=e345]:
|
||||
- img [ref=e346]
|
||||
- generic [ref=e349]:
|
||||
- generic [ref=e350]: STEP 3 · 可选文案轨 · 待运行
|
||||
- generic [ref=e351]: Gemini 2.5 · 英文带时间戳分段
|
||||
- generic "拖动调整宽度" [ref=e353]
|
||||
- generic "拖动调整大小(宽 × 高)" [ref=e354]
|
||||
- group [ref=e355]:
|
||||
- generic [ref=e356]:
|
||||
- generic [ref=e358]:
|
||||
- img [ref=e360]
|
||||
- generic [ref=e364]: 翻译理解 · Translate
|
||||
- button "钉住 · 锁定位置与尺寸" [ref=e367]:
|
||||
- img [ref=e368]
|
||||
- generic [ref=e371]:
|
||||
- generic [ref=e372]: STEP 4 · EN → ZH · 待运行
|
||||
- generic [ref=e373]: 中文翻译 · 段落级 · 实时输出
|
||||
- generic "拖动调整宽度" [ref=e375]
|
||||
- generic "拖动调整大小(宽 × 高)" [ref=e376]
|
||||
- group [ref=e377]:
|
||||
- generic [ref=e378]:
|
||||
- generic [ref=e380]:
|
||||
- button "透明骷髅" [ref=e381]:
|
||||
- img "透明骷髅" [ref=e382]
|
||||
- button "📋" [ref=e383]
|
||||
- generic:
|
||||
- generic:
|
||||
- generic:
|
||||
- generic: 分镜 5
|
||||
- generic: 43.13s
|
||||
- generic [ref=e384]:
|
||||
- generic [ref=e386]:
|
||||
- img [ref=e388]
|
||||
- generic [ref=e393]: 元素改造 · Storyboard
|
||||
- generic [ref=e394]:
|
||||
- img [ref=e395]
|
||||
- button "钉住 · 锁定位置与尺寸" [ref=e399]:
|
||||
- img [ref=e400]
|
||||
- generic [ref=e403]:
|
||||
- generic [ref=e404]: STEP 6 · 参考元素 → SKG 画面 · 完成
|
||||
- generic [ref=e405]:
|
||||
- text: 不是复刻原视频:先把参考图里的主体 / 场景 / 动作 / 道具拆出来,再替换成 SKG 产品画面。
|
||||
- generic [ref=e406]: 已有 1 个提取元素 · 0 个分镜进入编排
|
||||
- button "进入分镜编排" [disabled] [ref=e407]
|
||||
- generic "拖动调整宽度" [ref=e409]
|
||||
- generic "拖动调整大小(宽 × 高)" [ref=e410]
|
||||
- group [ref=e411]:
|
||||
- generic [ref=e412]:
|
||||
- generic [ref=e414]:
|
||||
- img [ref=e416]
|
||||
- generic [ref=e420]: 产品文案 · Rewrite
|
||||
- button "钉住 · 锁定位置与尺寸" [ref=e423]:
|
||||
- img [ref=e424]
|
||||
- generic [ref=e427]:
|
||||
- generic [ref=e428]: STEP 5 · 接 SKG 卖点 · 待运行
|
||||
- textbox "粘贴 SKG 产品信息 / 关键卖点(可作为视频脚本和镜头动作参考)" [disabled] [ref=e429]
|
||||
- generic [ref=e430]: 下一冲刺接入
|
||||
- generic "拖动调整宽度" [ref=e432]
|
||||
- generic "拖动调整大小(宽 × 高)" [ref=e433]
|
||||
- group [ref=e434]:
|
||||
- generic [ref=e436]:
|
||||
- generic [ref=e438]:
|
||||
- img [ref=e440]
|
||||
- generic [ref=e442]: 生成视频 · Video Gen
|
||||
- button "钉住 · 锁定位置与尺寸" [ref=e445]:
|
||||
- img [ref=e446]
|
||||
- generic [ref=e449]:
|
||||
- generic [ref=e450]: STEP 7 · 首帧 + 动作 prompt · 待运行
|
||||
- generic [ref=e451]:
|
||||
- generic [ref=e452]: Seedance
|
||||
- generic [ref=e453]: Kling
|
||||
- generic [ref=e454]: Veo 3
|
||||
- generic "拖动调整宽度" [ref=e456]
|
||||
- generic "拖动调整大小(宽 × 高)" [ref=e457]
|
||||
- group [ref=e458]:
|
||||
- generic [ref=e459]:
|
||||
- generic [ref=e461]:
|
||||
- img [ref=e463]
|
||||
- generic [ref=e467]: 合成成品 · Compose
|
||||
- button "钉住 · 锁定位置与尺寸" [ref=e470]:
|
||||
- img [ref=e471]
|
||||
- generic [ref=e474]:
|
||||
- generic [ref=e475]: STEP 8 · ffmpeg + 字幕 · 待运行
|
||||
- generic [ref=e476]:
|
||||
- text: 视频片段 + 字幕 / TTS
|
||||
- text: → 最终 mp4 输出
|
||||
- generic "拖动调整宽度" [ref=e477]
|
||||
- generic "拖动调整大小(宽 × 高)" [ref=e478]
|
||||
- img
|
||||
- generic "Control Panel" [ref=e479]:
|
||||
- button "Zoom In" [ref=e480] [cursor=pointer]:
|
||||
- img [ref=e481]
|
||||
- button "Zoom Out" [ref=e483] [cursor=pointer]:
|
||||
- img [ref=e484]
|
||||
- button "Fit View" [ref=e486] [cursor=pointer]:
|
||||
- img [ref=e487]
|
||||
- button "Toggle Interactivity" [ref=e489] [cursor=pointer]:
|
||||
- img [ref=e490]
|
||||
- img "Mini Map" [ref=e493]
|
||||
- region "Notifications alt+T":
|
||||
- list:
|
||||
- listitem [ref=e503]:
|
||||
- img [ref=e505]
|
||||
- generic [ref=e508]: 📥 视频已就绪 — 请点 Input 节点里的「点这里开始解析」按钮
|
||||
- alert [ref=e509]
|
||||
@@ -64,6 +64,18 @@ function loadNodeSizes(): Record<string, NodeSize> {
|
||||
}
|
||||
}
|
||||
|
||||
const NODE_PINS_KEY = "skg-tk:node-pins:v1"
|
||||
|
||||
function loadNodePins(): string[] {
|
||||
if (typeof window === "undefined") return []
|
||||
try {
|
||||
const raw = window.localStorage.getItem(NODE_PINS_KEY)
|
||||
return raw ? JSON.parse(raw) : []
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
const EDGES_RAW: Array<[string, string]> = [
|
||||
["input", "keyframe"],
|
||||
["input", "asr"],
|
||||
@@ -412,6 +424,16 @@ export default function Home() {
|
||||
return () => { if (pollRef.current) clearInterval(pollRef.current) }
|
||||
}, [job?.id, job?.status, job?.generated_videos?.map((v) => `${v.id}:${v.status}:${v.progress}`).join("|")])
|
||||
|
||||
const [pinnedNodes, setPinnedNodes] = useState<Set<string>>(() => new Set(loadNodePins()))
|
||||
const handleToggleNodePin = useCallback((id: string) => {
|
||||
setPinnedNodes((prev) => {
|
||||
const next = new Set(prev)
|
||||
if (next.has(id)) next.delete(id); else next.add(id)
|
||||
try { window.localStorage.setItem(NODE_PINS_KEY, JSON.stringify([...next])) } catch {}
|
||||
return next
|
||||
})
|
||||
}, [])
|
||||
|
||||
const nodeData: NodeData = useMemo(() => ({
|
||||
job,
|
||||
jobs,
|
||||
@@ -444,7 +466,9 @@ export default function Home() {
|
||||
setWorkbenchOpen(true)
|
||||
},
|
||||
onCopyImage: handleCopyImage,
|
||||
}), [job, jobs, activeJobId, submitting, analyzing, selectedFrames, expandedFrame, framePanelScale, framePanelPinned, handleSubmit, handleUpload, handleAnalyze, handleToggleFrame, handleOpenFramePanel, handleFramePanelScaleChange, handleAddManualFrame, handleSwitchJob, setJob, handleDeleteFrame, handleDeleteGenerated, handleDeleteVideo, handleCopyImage])
|
||||
pinnedNodes,
|
||||
onToggleNodePin: handleToggleNodePin,
|
||||
}), [job, jobs, activeJobId, submitting, analyzing, selectedFrames, expandedFrame, framePanelScale, framePanelPinned, handleSubmit, handleUpload, handleAnalyze, handleToggleFrame, handleOpenFramePanel, handleFramePanelScaleChange, handleAddManualFrame, handleSwitchJob, setJob, handleDeleteFrame, handleDeleteGenerated, handleDeleteVideo, handleCopyImage, pinnedNodes, handleToggleNodePin])
|
||||
|
||||
// 用 useNodesState 让 ReactFlow 自己管位置(避免轮询时重置 drag)
|
||||
const savedSizes = useMemo(() => loadNodeSizes(), [])
|
||||
@@ -453,12 +477,13 @@ export default function Home() {
|
||||
const s = savedSizes[n.id] ?? {}
|
||||
const w = s.w ?? n.w
|
||||
const h = s.h
|
||||
const isPinned = pinnedNodes.has(n.id)
|
||||
return {
|
||||
id: n.id,
|
||||
type: n.type,
|
||||
position: { x: n.x, y: n.y },
|
||||
data: nodeData,
|
||||
draggable: true,
|
||||
draggable: !isPinned,
|
||||
width: w,
|
||||
...(typeof h === "number" ? { height: h } : {}),
|
||||
style: { width: w, ...(typeof h === "number" ? { height: h } : {}) },
|
||||
@@ -466,6 +491,13 @@ export default function Home() {
|
||||
}),
|
||||
)
|
||||
|
||||
// pinned 变化时同步每个节点 draggable
|
||||
useEffect(() => {
|
||||
setNodes((prev) => prev.map((n) =>
|
||||
n.id === KEYFRAME_PANEL_ID ? n : { ...n, draggable: !pinnedNodes.has(n.id) },
|
||||
))
|
||||
}, [pinnedNodes, setNodes])
|
||||
|
||||
// 持久化每个节点宽 / 高到 localStorage(KeyframePanelNode 自己管尺寸,不写回)
|
||||
useEffect(() => {
|
||||
const sizes: Record<string, NodeSize> = {}
|
||||
|
||||
@@ -46,6 +46,8 @@ export interface NodeData {
|
||||
onOpenStoryboard?: (frameIdx: number) => void // 打开分镜头编排专属面板
|
||||
onOpenWorkbench?: (frameIdx?: number) => void // 展开顶部分镜编排内嵌面板
|
||||
onCopyImage?: (ref: ImageRef) => void // 复制图片到全局剪贴板(粘贴到分镜头编排插槽)
|
||||
pinnedNodes?: Set<string> // 已钉住的节点 id 集合 — 钉住后位置 + 尺寸锁定
|
||||
onToggleNodePin?: (id: string) => void
|
||||
}
|
||||
|
||||
/* ---- 状态映射工具 ---- */
|
||||
@@ -234,6 +236,8 @@ export function InputNode({ data, selected }: NodeProps<{ data: NodeData }> | an
|
||||
subtitle={isDownloading ? "STEP 1 · 下载中" : hasVideo ? "STEP 1 · 视频就绪" : "STEP 1"}
|
||||
selected={selected}
|
||||
hasTarget={false}
|
||||
pinned={d.pinnedNodes?.has("input")}
|
||||
onTogglePin={() => d.onToggleNodePin?.("input")}
|
||||
>
|
||||
{/* URL + 上传入口 — 一直显示(即使已有视频,也可以继续加新的) */}
|
||||
<>
|
||||
@@ -499,6 +503,8 @@ export function KeyframeNode({ data, selected }: any) {
|
||||
title="镜头拆解 · 元素提取"
|
||||
subtitle={`STEP 2 · ${frames.length ? `${d.selectedFrames.size}/${frames.length} 入编排` : "等待抽取"}`}
|
||||
selected={selected}
|
||||
pinned={d.pinnedNodes?.has("keyframe")}
|
||||
onTogglePin={() => d.onToggleNodePin?.("keyframe")}
|
||||
>
|
||||
{frames.length > 0 ? (() => {
|
||||
const cleanedCount = frames.filter((x) => x.cleaned_url).length
|
||||
@@ -726,6 +732,8 @@ export function ASRNode({ data, selected }: any) {
|
||||
title="声音文案 · ASR"
|
||||
subtitle="STEP 3 · 可选文案轨"
|
||||
selected={selected}
|
||||
pinned={d.pinnedNodes?.has("asr")}
|
||||
onTogglePin={() => d.onToggleNodePin?.("asr")}
|
||||
>
|
||||
<div className="text-[11.5px] text-[var(--text-soft)]">
|
||||
Gemini 2.5 · 英文带时间戳分段
|
||||
@@ -767,6 +775,8 @@ export function TranslateNode({ data, selected }: any) {
|
||||
title="翻译理解 · Translate"
|
||||
subtitle="STEP 4 · EN → ZH"
|
||||
selected={selected}
|
||||
pinned={d.pinnedNodes?.has("translate")}
|
||||
onTogglePin={() => d.onToggleNodePin?.("translate")}
|
||||
>
|
||||
<div className="text-[11.5px] text-[var(--text-soft)]">
|
||||
中文翻译 · 段落级 · 实时输出
|
||||
@@ -785,7 +795,8 @@ export function TranslateNode({ data, selected }: any) {
|
||||
/* ============================================================
|
||||
7. RewriteNode (placeholder)
|
||||
============================================================ */
|
||||
export function RewriteNode({ selected }: any) {
|
||||
export function RewriteNode({ data, selected }: any) {
|
||||
const d: NodeData = data
|
||||
return (
|
||||
<NodeShell
|
||||
type="ai" status="pending"
|
||||
@@ -793,6 +804,8 @@ export function RewriteNode({ selected }: any) {
|
||||
title="产品文案 · Rewrite"
|
||||
subtitle="STEP 5 · 接 SKG 卖点"
|
||||
selected={selected}
|
||||
pinned={d.pinnedNodes?.has("rewrite")}
|
||||
onTogglePin={() => d.onToggleNodePin?.("rewrite")}
|
||||
>
|
||||
<textarea
|
||||
placeholder="粘贴 SKG 产品信息 / 关键卖点(可作为视频脚本和镜头动作参考)"
|
||||
@@ -929,6 +942,8 @@ export function StoryboardNode({ data, selected }: any) {
|
||||
title="元素改造 · Storyboard"
|
||||
subtitle={`STEP 6 · 参考元素 → SKG 画面${storyboardCount > 0 ? ` · ${storyboardCount} 分镜` : ""}`}
|
||||
selected={selected}
|
||||
pinned={d.pinnedNodes?.has("storyboard")}
|
||||
onTogglePin={() => d.onToggleNodePin?.("storyboard")}
|
||||
>
|
||||
<div className="text-[11.5px] leading-relaxed text-[var(--text-soft)]">
|
||||
不是复刻原视频:先把参考图里的主体 / 场景 / 动作 / 道具拆出来,再替换成 SKG 产品画面。
|
||||
@@ -1103,6 +1118,8 @@ export function VideoGenNode({ data, selected }: any) {
|
||||
title="生成视频 · Video Gen"
|
||||
subtitle={`STEP 7 · 首帧 + 动作 prompt${videos.length > 0 ? ` · ${videos.length} 个视频任务` : ""}`}
|
||||
selected={selected}
|
||||
pinned={d.pinnedNodes?.has("videogen")}
|
||||
onTogglePin={() => d.onToggleNodePin?.("videogen")}
|
||||
>
|
||||
<div className="grid grid-cols-3 gap-1.5 text-[10.5px]">
|
||||
{["Seedance", "Kling", "Veo 3"].map((m) => (
|
||||
@@ -1124,7 +1141,8 @@ export function VideoGenNode({ data, selected }: any) {
|
||||
/* ============================================================
|
||||
10. ComposeNode (placeholder)
|
||||
============================================================ */
|
||||
export function ComposeNode({ selected }: any) {
|
||||
export function ComposeNode({ data, selected }: any) {
|
||||
const d: NodeData = data
|
||||
return (
|
||||
<NodeShell
|
||||
type="output" status="pending"
|
||||
@@ -1133,6 +1151,8 @@ export function ComposeNode({ selected }: any) {
|
||||
subtitle="STEP 8 · ffmpeg + 字幕"
|
||||
selected={selected}
|
||||
hasSource={false}
|
||||
pinned={d.pinnedNodes?.has("compose")}
|
||||
onTogglePin={() => d.onToggleNodePin?.("compose")}
|
||||
>
|
||||
<div className="text-[11.5px] text-[var(--text-soft)] leading-relaxed">
|
||||
视频片段 + 字幕 / TTS<br />→ 最终 mp4 输出
|
||||
|
||||
Reference in New Issue
Block a user