You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6.3 KiB
6.3 KiB
时间轴分镜时长编辑器 - 实施记录
任务: 在分镜轨道的分镜块中添加可点击的时长编辑器
日期: 2026-01-28
状态: ✅ 已完成
📋 任务上下文
需求描述
用户需要在时间轴分镜块的更多菜单按钮前添加一个时长显示(如 5s),点击后弹出 Popover 来输入具体的时长数值,以便快速更改分镜时长。
设计方案
选择方案1:紧凑型内联编辑器
- 紧凑、不占空间
- 操作流畅,符合用户心智模型
- 视觉统一,融入现有设计系统
- 实现简单,代码量少
✅ 已完成步骤
1. 创建 DurationEditor 组件 ✅
文件: client/src/components/features/timeline/DurationEditor.tsx
功能特性:
- 可点击的时长标签(等宽字体,Hover 高亮)
- Popover 弹出输入框
- 自动聚焦并全选内容
- Enter 确认 / Esc 取消
- 失焦自动应用
- 最小时长验证(0.5s)
- 错误提示显示
- 防止事件冒泡
样式:
- 使用
globals.css主题变量 - 等宽字体 (
font-mono) - 紧凑型 Popover (
w-32) - 上方弹出 (
side="top") - 右对齐 (
align="end")
2. 集成到 TimelineItem 组件 ✅
文件: client/src/components/features/timeline/TimelineItem.tsx
修改内容:
- 导入
DurationEditor组件 - 在分镜块右侧替换原有时长文字
- 仅在分镜轨道显示编辑器
- 条件渲染:
trackType === 'storyboard'&&onResizeRight存在 - 时长变化回调:调用
onResizeRight+onDragEnd - 保持非分镜轨道原有显示
3. 代码质量检查 ✅
- Linter 检查通过(无错误)
- TypeScript 类型检查通过
- 组件 Props 接口完整
- 事件处理正确(阻止冒泡)
4. 文档记录 ✅
- Changelog:
docs/client/changelogs/2026-01-28-timeline-duration-editor.md - 实施计划:
docs/计划/timeline-duration-editor-implementation.md
🎯 实施细节
核心实现逻辑
DurationEditor 组件:
// 时长标签 → Popover Trigger
<button onClick={() => setOpen(true)}>
{duration.toFixed(1)}s
</button>
// Popover 内容
<PopoverContent>
<Input
type="number"
value={inputValue}
onChange={handleInputChange}
onKeyDown={(e) => {
if (e.key === 'Enter') applyDuration();
if (e.key === 'Escape') cancelEdit();
}}
onBlur={applyDuration}
/>
</PopoverContent>
TimelineItem 集成:
// 分镜轨道:使用 DurationEditor
{trackType === 'storyboard' && (
<DurationEditor
duration={endTime - startTime}
onDurationChange={(newDuration) => {
const newEndTime = startTime + newDuration;
onResizeRight(id, newEndTime);
onDragEnd?.(id); // 持久化
}}
/>
)}
// 其他轨道:保持原有显示
{trackType !== 'storyboard' && (
<span>{formatDuration(endTime - startTime)}</span>
)}
状态管理流程
用户点击时长标签
↓
Popover 打开,输入框自动聚焦并全选
↓
用户输入新时长(实时验证)
↓
按 Enter / 失焦
↓
验证通过 → onDurationChange 回调
↓
计算新 endTime = startTime + newDuration
↓
调用 onResizeRight(id, newEndTime)
↓
调用 onDragEnd(id) 持久化到后端
↓
Popover 关闭
🔍 验证清单
功能验证
- 在开发环境启动项目
- 打开时间轴,找到分镜轨道
- 点击分镜块右侧的时长标签(如
5.0s) - 验证 Popover 正常弹出
- 验证输入框自动聚焦并全选
- 输入新时长值(如
8) - 按 Enter 确认
- 验证分镜块宽度同步更新
- 验证时长标签显示新值(
8.0s)
边界情况验证
- 输入小于 0.5 的值,验证错误提示
- 输入非数字(如
abc),验证错误提示 - 按 Esc 取消,验证时长不变
- 点击 Popover 外部,验证自动应用并关闭
- 分镜块宽度很小时(< 10%),验证时长标签隐藏
交互验证
- Hover 时长标签,验证高亮效果
- 点击时长标签时不触发分镜块拖拽
- 拖拽分镜时 Popover 自动关闭(如果打开)
- 与更多菜单按钮布局正常(间距合理)
兼容性验证
- 非分镜轨道(video/sound/subtitle 等)仍显示原有时长文字
- 锁定轨道时时长编辑器禁用
- 不影响其他分镜块功能(选中、拖拽、调整)
📊 实施结果
新增文件
client/src/components/features/timeline/DurationEditor.tsx(156 行)docs/client/changelogs/2026-01-28-timeline-duration-editor.md(168 行)docs/计划/timeline-duration-editor-implementation.md(本文件)
修改文件
client/src/components/features/timeline/TimelineItem.tsx- 导入
DurationEditor(+1 行) - 替换时长显示逻辑 (+13 行, -3 行)
- 导入
代码统计
- 新增代码: ~170 行
- 修改代码: ~10 行
- 组件数: +1 (DurationEditor)
🎉 成果总结
实现的功能
✅ 分镜块显示可点击的时长标签
✅ 点击弹出 Popover 进行时长编辑
✅ 支持键盘快捷操作(Enter/Esc)
✅ 实时验证和错误提示
✅ 符合项目设计系统(使用主题变量)
✅ 完整的文档记录
用户价值
- 效率提升: 直接输入时长,比拖拽调整更快速精确
- 减少操作: 无需切换到属性面板
- 即时反馈: 在时间轴上直接看到效果
- 专业友好: 支持键盘快捷键
技术亮点
- 组件化: 独立的
DurationEditor组件,易于复用 - 类型安全: 完整的 TypeScript 类型定义
- 事件隔离: 正确处理事件冒泡,不影响拖拽
- 主题统一: 使用项目
globals.css变量 - 性能优化: 延迟失焦处理,避免冲突
🚀 后续优化建议
-
增强功能(可选)
- 添加 ±0.5s / ±1s 快捷按钮
- 批量编辑多个分镜时长
- 智能时长建议(基于素材)
-
交互优化
- 添加时长预览动画
- 支持拖拽滑块调整时长
- 显示时长历史记录
-
可访问性
- 添加 ARIA 标签
- 支持屏幕阅读器
- 键盘导航优化
实施者: AI Assistant
完成时间: 2026-01-28
执行模式: 研究 → 构思 → 计划 → 执行 → 评审