diff --git a/apps/web/src/pages/editing-planner/components/PipConfigPanel/components/LayerConfig.tsx b/apps/web/src/pages/editing-planner/components/PipConfigPanel/components/LayerConfig.tsx new file mode 100644 index 000000000..e37c3bd47 --- /dev/null +++ b/apps/web/src/pages/editing-planner/components/PipConfigPanel/components/LayerConfig.tsx @@ -0,0 +1,242 @@ +import React from "react" +import type { PipLayer, PipGridPosition, PipAnimType, PipSlideDirection } from "../types" +import { GRID_POSITIONS, ANIM_OPTIONS, SLIDE_DIR_OPTIONS } from "../constants" + +export interface LayerConfigProps { + layer: PipLayer + totalDuration: number + onUpdate: (id: string, partial: Partial) => void + onGridClick: (pos: PipGridPosition) => void + onWidthChange: (val: number) => void + onHeightChange: (val: number) => void +} + +export const LayerConfig: React.FC = ({ + layer, + totalDuration, + onUpdate, + onGridClick, + onWidthChange, + onHeightChange, +}) => { + return ( +
+ {/* ── 素材类型 ── */} +
+ +
+ + +
+
+ + {/* ── 素材 URL ── */} +
+ + onUpdate(layer.id, { material_url: e.target.value })} + /> +
+ + {/* ── 位置:九宫格 + 坐标 ── */} +
+ +
+
+ {GRID_POSITIONS.map((pos) => ( + + ))} +
+
+
+ + onUpdate(layer.id, { x: Number(e.target.value) })} + /> +
+
+ + onUpdate(layer.id, { y: Number(e.target.value) })} + /> +
+
+
+
+ + {/* ── 尺寸 ── */} +
+ +
+ 宽 + onWidthChange(Number(e.target.value))} + /> + {layer.width}% +
+
+ 高 + onHeightChange(Number(e.target.value))} + /> + {layer.height}% +
+
onUpdate(layer.id, { aspect_lock: !layer.aspect_lock })} + > + {layer.aspect_lock ? "🔒" : "🔓"} + {layer.aspect_lock ? "已锁定比例" : "锁定宽高比"} +
+
+ + {/* ── 圆角 ── */} +
+ +
+ onUpdate(layer.id, { border_radius: Number(e.target.value) })} + /> + {layer.border_radius}% +
+
+ + {/* ── 透明度 ── */} +
+ +
+ onUpdate(layer.id, { opacity: Number(e.target.value) })} + /> + {layer.opacity}% +
+
+ + {/* ── 时间 ── */} +
+ +
+
+ + onUpdate(layer.id, { start_time: Number(e.target.value) })} + /> +
+
+ + onUpdate(layer.id, { duration: Number(e.target.value) })} + /> +
+
+
+ + {/* ── 入场动画 ── */} +
+ + +
+ + {/* 滑入方向(仅 slide_in 时显示) */} + {layer.animation === "slide_in" && ( +
+ + +
+ )} +
+ ) +}