fix
This commit is contained in:
parent
455d929ba5
commit
61a6cdb5ba
|
|
@ -0,0 +1,190 @@
|
||||||
|
# 轨道片段名称编辑 - 分类选择功能
|
||||||
|
|
||||||
|
## 功能概述
|
||||||
|
|
||||||
|
将轨道片段的名称编辑功能从文本输入框改为下拉选择,用户可以从素材分类中选择,选择后将分类名称赋值给片段名称。
|
||||||
|
|
||||||
|
## 功能特点
|
||||||
|
|
||||||
|
### 1. 下拉选择替代文本输入
|
||||||
|
- **原功能**:双击片段显示文本输入框,手动输入名称
|
||||||
|
- **新功能**:双击片段显示下拉选择框,从预设分类中选择
|
||||||
|
|
||||||
|
### 2. 分类数据集成
|
||||||
|
- 自动加载用户的素材分类数据
|
||||||
|
- 支持云端和本地分类
|
||||||
|
- 只显示激活状态的分类
|
||||||
|
|
||||||
|
### 3. 选择选项
|
||||||
|
- **选择分类**:从分类列表中选择,将分类名称赋值给片段
|
||||||
|
- **保持原名称**:选择此项保持片段原有名称不变
|
||||||
|
- **取消编辑**:点击空白处或失去焦点取消编辑
|
||||||
|
|
||||||
|
## 技术实现
|
||||||
|
|
||||||
|
### 1. 组件修改
|
||||||
|
**文件**: `src/components/timeline/TrackTimeline.tsx`
|
||||||
|
|
||||||
|
#### 新增状态管理
|
||||||
|
```typescript
|
||||||
|
const [categories, setCategories] = React.useState<ResourceCategoryV2[]>([])
|
||||||
|
const [loadingCategories, setLoadingCategories] = React.useState(false)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 分类数据加载
|
||||||
|
```typescript
|
||||||
|
const loadCategories = React.useCallback(async () => {
|
||||||
|
if (loadingCategories) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
setLoadingCategories(true)
|
||||||
|
const result = await ResourceCategoryServiceV2.getAllCategories({
|
||||||
|
include_cloud: true
|
||||||
|
})
|
||||||
|
setCategories(result)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to load categories:', error)
|
||||||
|
} finally {
|
||||||
|
setLoadingCategories(false)
|
||||||
|
}
|
||||||
|
}, [loadingCategories])
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 分类选择处理
|
||||||
|
```typescript
|
||||||
|
const handleCategorySelect = (segmentId: string, categoryTitle: string) => {
|
||||||
|
if (onSegmentNameChange && categoryTitle) {
|
||||||
|
onSegmentNameChange(segmentId, categoryTitle)
|
||||||
|
}
|
||||||
|
setEditingSegmentId(null)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. UI 组件替换
|
||||||
|
|
||||||
|
#### 原文本输入框
|
||||||
|
```typescript
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={editingName}
|
||||||
|
onChange={(e) => setEditingName(e.target.value)}
|
||||||
|
onBlur={() => handleNameSubmit(segment.id)}
|
||||||
|
onKeyDown={(e) => handleKeyDown(e, segment.id)}
|
||||||
|
className="w-full bg-transparent text-inherit border-none outline-none"
|
||||||
|
autoFocus
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 新下拉选择框
|
||||||
|
```typescript
|
||||||
|
<select
|
||||||
|
value=""
|
||||||
|
onChange={(e) => {
|
||||||
|
if (e.target.value) {
|
||||||
|
handleCategorySelect(segment.id, e.target.value)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onBlur={() => setEditingSegmentId(null)}
|
||||||
|
className="w-full bg-white text-gray-900 border border-gray-300 rounded px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 cursor-pointer"
|
||||||
|
autoFocus
|
||||||
|
size={Math.min(categories.length + 2, 8)}
|
||||||
|
>
|
||||||
|
<option value="">选择分类...</option>
|
||||||
|
<option value={segment.name} className="text-gray-600">
|
||||||
|
保持原名称: {segment.name}
|
||||||
|
</option>
|
||||||
|
{categories
|
||||||
|
.filter(category => category.is_active)
|
||||||
|
.map((category) => (
|
||||||
|
<option key={category.id} value={category.title}>
|
||||||
|
{category.title}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 数据流程
|
||||||
|
|
||||||
|
1. **组件初始化**:自动加载分类数据
|
||||||
|
2. **编辑触发**:双击或右键编辑片段
|
||||||
|
3. **分类加载**:确保分类数据已加载
|
||||||
|
4. **显示选择**:展示下拉选择框
|
||||||
|
5. **选择处理**:用户选择分类,更新片段名称
|
||||||
|
6. **状态重置**:关闭编辑状态
|
||||||
|
|
||||||
|
## 用户体验改进
|
||||||
|
|
||||||
|
### 1. 操作简化
|
||||||
|
- **减少输入**:无需手动输入,直接选择
|
||||||
|
- **标准化**:确保名称的一致性和规范性
|
||||||
|
- **快速选择**:预设选项,提高效率
|
||||||
|
|
||||||
|
### 2. 视觉反馈
|
||||||
|
- **加载状态**:显示"加载分类中..."提示
|
||||||
|
- **选项分组**:保持原名称选项与分类选项分开
|
||||||
|
- **样式优化**:下拉框样式适配片段容器
|
||||||
|
|
||||||
|
### 3. 交互优化
|
||||||
|
- **自动聚焦**:下拉框自动获得焦点
|
||||||
|
- **点击外部取消**:失去焦点自动取消编辑
|
||||||
|
- **键盘支持**:支持键盘导航选择
|
||||||
|
|
||||||
|
## 兼容性考虑
|
||||||
|
|
||||||
|
### 1. 向后兼容
|
||||||
|
- 保持原有的 `onSegmentNameChange` 回调接口
|
||||||
|
- 支持现有的片段数据结构
|
||||||
|
- 不影响其他组件的使用
|
||||||
|
|
||||||
|
### 2. 错误处理
|
||||||
|
- 分类加载失败时的降级处理
|
||||||
|
- 网络异常时的用户提示
|
||||||
|
- 空分类列表的处理
|
||||||
|
|
||||||
|
### 3. 性能优化
|
||||||
|
- 分类数据缓存,避免重复加载
|
||||||
|
- 异步加载,不阻塞界面渲染
|
||||||
|
- 限制下拉框高度,避免界面溢出
|
||||||
|
|
||||||
|
## 使用示例
|
||||||
|
|
||||||
|
### 基本使用
|
||||||
|
```typescript
|
||||||
|
<TrackTimeline
|
||||||
|
track={track}
|
||||||
|
totalDuration={totalDuration}
|
||||||
|
currentTime={currentTime}
|
||||||
|
onSegmentNameChange={(segmentId, newName) => {
|
||||||
|
// 处理片段名称更改
|
||||||
|
console.log(`片段 ${segmentId} 名称更改为: ${newName}`)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 完整示例
|
||||||
|
参见 `test_track_timeline_category_select.tsx` 文件中的完整测试示例。
|
||||||
|
|
||||||
|
## 后续优化建议
|
||||||
|
|
||||||
|
### 1. 功能增强
|
||||||
|
- 支持创建新分类
|
||||||
|
- 分类颜色显示
|
||||||
|
- 分类搜索过滤
|
||||||
|
- 最近使用分类
|
||||||
|
|
||||||
|
### 2. 用户体验
|
||||||
|
- 键盘快捷键支持
|
||||||
|
- 批量重命名功能
|
||||||
|
- 拖拽排序支持
|
||||||
|
- 撤销/重做功能
|
||||||
|
|
||||||
|
### 3. 数据管理
|
||||||
|
- 分类使用统计
|
||||||
|
- 智能推荐分类
|
||||||
|
- 分类同步机制
|
||||||
|
- 离线模式支持
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
通过将片段名称编辑从文本输入改为分类选择,提高了用户操作的便利性和名称的标准化程度。这个改进不仅简化了用户操作,还为后续的素材管理和分类功能奠定了基础。
|
||||||
|
|
@ -53,8 +53,6 @@ export const TrackTimeline: React.FC<TrackTimelineProps> = ({
|
||||||
|
|
||||||
// 加载分类数据
|
// 加载分类数据
|
||||||
const loadCategories = React.useCallback(async () => {
|
const loadCategories = React.useCallback(async () => {
|
||||||
if (loadingCategories) return
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setLoadingCategories(true)
|
setLoadingCategories(true)
|
||||||
const result = await ResourceCategoryServiceV2.getAllCategories({
|
const result = await ResourceCategoryServiceV2.getAllCategories({
|
||||||
|
|
@ -66,12 +64,12 @@ export const TrackTimeline: React.FC<TrackTimelineProps> = ({
|
||||||
} finally {
|
} finally {
|
||||||
setLoadingCategories(false)
|
setLoadingCategories(false)
|
||||||
}
|
}
|
||||||
}, [loadingCategories])
|
}, [])
|
||||||
|
|
||||||
// 组件挂载时加载分类
|
// 组件挂载时加载分类
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
loadCategories()
|
loadCategories()
|
||||||
}, [loadCategories])
|
}, [])
|
||||||
|
|
||||||
const getSegmentColor = (type: string) => {
|
const getSegmentColor = (type: string) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue