diff --git a/.memory/worklog.json b/.memory/worklog.json index d3669ca..1eeec9d 100644 --- a/.memory/worklog.json +++ b/.memory/worklog.json @@ -1,19 +1,5 @@ { "entries": [ - { - "files_changed": 0, - "hash": "", - "message": "项目创建: SKG AI 素材管线 - TK 二创验证", - "ts": "2026-05-12T00:00:00+08:00", - "type": "milestone" - }, - { - "files_changed": 7, - "hash": "56d435f", - "message": "init: project scaffold", - "ts": "2026-05-12T15:37:36+08:00", - "type": "commit" - }, { "files_changed": 4, "hash": "bbd41fa", @@ -3361,6 +3347,19 @@ "type": "session-heartbeat", "message": "Codex 会话活跃 · 最近命令:codex · 2 项未提交变更 · 最近提交:auto-save 2026-05-14 05:27 (~3)", "files_changed": 2 + }, + { + "ts": "2026-05-14T05:32:54+08:00", + "type": "commit", + "message": "auto-save 2026-05-14 05:32 (~4)", + "hash": "f3636a5", + "files_changed": 4 + }, + { + "ts": "2026-05-13T21:33:13Z", + "type": "session-heartbeat", + "message": "Claude 会话活跃 · 最近命令:claude · 2 项未提交变更 · 最近提交:auto-save 2026-05-14 05:32 (~4)", + "files_changed": 2 } ] } diff --git a/docs/source-analysis.html b/docs/source-analysis.html index 5426efe..4921de5 100644 --- a/docs/source-analysis.html +++ b/docs/source-analysis.html @@ -664,7 +664,7 @@ api/main.py

KeyElement

-

从关键帧里识别或手动添加的主体候选。Vision 给的是候选,用户可编辑、删除,并可基于它生成主体资产包。

+

从关键帧识别结果里确认出来的主体候选。Vision 给的是候选,用户可编辑、删除,并可基于它生成主体资产包。

KeyElement {
   id,
   name_zh, name_en, position,
@@ -788,7 +788,7 @@ SubjectAsset {
               
  • 手动按时间戳加关键帧。
  • 关键帧清洗水印,全图或区域清洗。
  • Vision 识别关键帧,输出 scene、objects、style、suggested_prompt,并作为主体候选来源。
  • -
  • 主体候选增改删、区域主体添加、主体资产包生成。
  • +
  • 主体候选确认、改名、删除和主体资产包生成。
  • 分镜工作台 4 图槽和改造说明自动保存。
  • nano-banana-pro image-to-image 生图。
  • @@ -846,8 +846,8 @@ SubjectAsset { UX
    -

    问题:面板标题仍叫“关键帧详情 · 元素提取”,里面还露出普通 cutout 抠图、AI 提取、元素清单等旧流程入口;“选用此帧”也无法说明它其实是在维护目标关键帧集合。

    -

    改动:KeyframePanelNode 标题改为“关键帧素材准备”;FrameLightbox 的主体页改成“主体识别 / 主体清单 / 主体资产包”,移除普通抠图列表和 AI 提取按钮;“选用此帧”改为“加入目标帧 / 目标帧 · 点击移出”。VisualLabNode 上方缩略图也不再展示普通抠图分组,只展示关键帧、场景图、主体包和视频任务。

    +

    问题:面板标题仍叫“关键帧详情 · 元素提取”,里面还露出普通 cutout 抠图、AI 提取、元素清单等旧流程入口;“选用此帧 / 加入目标帧”也无法说明实际价值,因为抽帧阶段已经筛过图,进入画面工作台的关键帧默认就应该参与素材准备。

    +

    改动:KeyframePanelNode 标题改为“关键帧素材准备”;FrameLightbox 的主体页改成“主体识别 / 主体清单 / 主体资产包”,移除普通抠图列表、AI 提取按钮和详情内的目标帧开关,改为只显示“已在素材准备流程”的状态说明;VisualLabNode 上方缩略图也不再展示普通抠图分组,只展示关键帧、场景图、主体包和视频任务。

    影响:web/components/lightbox.tsxweb/components/nodes/index.tsxdocs/source-analysis.html。底层旧 cutout 数据和接口暂保留兼容历史任务,但不再作为新素材准备流程的可见入口。

    @@ -859,7 +859,7 @@ SubjectAsset {

    问题:画面工作台从展示缩略图扩展为素材生产中枢后,关键帧、场景图、主体资产包和视频任务继续混在一个列表里会让流程不清晰;关键帧详情面板也把清洗、识别、场景和主体生成都堆在一屏。

    -

    改动:VisualLabNode 改成素材准备进度看板,显示目标关键帧、场景图、主体资产和分镜/视频四个入口。FrameLightbox 新增“原图/清洗、场景图、主体资产、审核”四个页签,素材审核信息从普通列表中拆出来。

    +

    改动:VisualLabNode 改成素材准备进度看板,显示关键帧素材、场景图、主体资产和分镜/视频四个入口。FrameLightbox 新增“原图/清洗、场景图、主体资产、审核”四个页签,素材审核信息从普通列表中拆出来。

    影响:web/components/nodes/index.tsxweb/components/lightbox.tsxdocs/source-analysis.html。这轮只重排工作台信息架构,批量自动准备队列仍留到下一阶段。

    diff --git a/web/components/lightbox.tsx b/web/components/lightbox.tsx index 7d9ab54..f78d179 100644 --- a/web/components/lightbox.tsx +++ b/web/components/lightbox.tsx @@ -62,8 +62,6 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o const [applying, setApplying] = useState(false) const [sceneGenerating, setSceneGenerating] = useState(false) const [subjectGenerating, setSubjectGenerating] = useState(null) - const [addingZh, setAddingZh] = useState(false) - const [addInput, setAddInput] = useState("") const [assetSize, setAssetSize] = useState("source") const [subjectKinds, setSubjectKinds] = useState>({}) const [subjectBackgrounds, setSubjectBackgrounds] = useState>({}) @@ -82,9 +80,6 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o const [regions, setRegions] = useState([]) const [draftRegion, setDraftRegion] = useState(null) // 当前正在拖的 const [dragStart, setDragStart] = useState<{ x: number; y: number } | null>(null) - const [subjectRegionPrompt, setSubjectRegionPrompt] = useState(false) - const [subjectRegionName, setSubjectRegionName] = useState("") - const [addingRegionSubject, setAddingRegionSubject] = useState(false) const imgWrapRef = useRef(null) useEffect(() => setMounted(true), []) @@ -94,8 +89,6 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o setRegions([]) setDraftRegion(null) setDragStart(null) - setSubjectRegionPrompt(false) - setSubjectRegionName("") }, [activeIndex]) useEffect(() => { @@ -201,26 +194,6 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o }) } - const handleAddRegionSubject = async () => { - if (regions.length !== 1 || !subjectRegionName.trim()) return - const r = regions[0] - setAddingRegionSubject(true) - try { - const added = await addElement(jobId, f.index, { - name_zh: subjectRegionName.trim(), - source: "region", - region: r, - }) - onJobUpdate?.(added) - toast.success(`「${subjectRegionName.trim()}」已加入主体清单`) - setCropMode(false); setRegions([]); setSubjectRegionPrompt(false); setSubjectRegionName("") - } catch (e) { - toast.error("添加主体失败:" + (e instanceof Error ? e.message : String(e))) - } finally { - setAddingRegionSubject(false) - } - } - // 画框 mouse handlers — 坐标基于 img wrapper 相对位置 const getRelXY = (clientX: number, clientY: number) => { const el = imgWrapRef.current @@ -284,14 +257,11 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o const handleAddElement = async (name_zh: string, name_en?: string, position?: string, source: "auto" | "manual" = "manual") => { const zh = name_zh.trim() if (!zh) return - setAddingZh(true) try { const updated = await addElement(jobId, f.index, { name_zh: zh, name_en, position, source }) onJobUpdate?.(updated) } catch (e) { toast.error("加入失败:" + (e instanceof Error ? e.message : String(e))) - } finally { - setAddingZh(false) } } @@ -472,92 +442,47 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o <> {/* 画框工具栏 */} {cropMode ? ( - subjectRegionPrompt ? ( -
    - setSubjectRegionName(e.target.value)} - onKeyDown={(e) => { - if (e.key === "Enter" && !e.nativeEvent.isComposing && subjectRegionName.trim()) { - e.preventDefault() - handleAddRegionSubject() - } - if (e.key === "Escape") { setSubjectRegionPrompt(false); setSubjectRegionName("") } - }} - placeholder="给这个主体起名(如:手持产品的人)" - className="w-full text-[11.5px] px-2 py-1.5 rounded-md bg-black/40 border border-violet-300/50 outline-none text-white placeholder:text-white/30 focus:ring-2 focus:ring-violet-400/40" - /> -
    - - -
    +
    +
    + {regions.length === 0 + ? "在图上拖动鼠标 → 框选要清洗的水印、字幕、平台 UI 或杂物" + : `已框 ${regions.length} 个 · 继续加框或点击「去掉」批量清洗`}
    - ) : ( -
    -
    - {regions.length === 0 - ? "在图上拖动鼠标 → 框选要处理的区域(可连续画多个)" - : `已框 ${regions.length} 个 · 继续加框 · 「去掉」批量清洗 · 单框可加入主体清单`} -
    -
    - - - - -
    +
    + + +
    - ) +
    ) : ( )} @@ -1050,34 +975,8 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
    )} - {/* 添加 */} -
    - setAddInput(ev.target.value)} - onKeyDown={(ev) => { - if (ev.key === "Enter" && !ev.nativeEvent.isComposing) { - ev.preventDefault() - if (addInput.trim() && !addingZh) { - handleAddElement(addInput) - setAddInput("") - } - } - }} - placeholder="添加主体候选 · 中文回车自动翻英文" - className="flex-1 text-[12px] px-2.5 py-1.5 rounded-md bg-black/40 border border-white/15 outline-none text-white placeholder:text-white/30 focus:ring-2 focus:ring-violet-400/40 focus:border-violet-400/40" - /> - -
    - 主体候选会持久化保存;主体资产包和场景图准备好后,再复制到「分镜头编排」。 + 主体候选来自识别结果;确认名称、类型和视角后生成主体资产包。