fix
This commit is contained in:
parent
8908f0c9c1
commit
455d929ba5
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { SegmentContextMenu } from './SegmentContextMenu'
|
import { SegmentContextMenu } from './SegmentContextMenu'
|
||||||
import { SegmentTooltip } from './SegmentTooltip'
|
import { SegmentTooltip } from './SegmentTooltip'
|
||||||
|
import { ResourceCategoryServiceV2, ResourceCategoryV2 } from '../../services/resourceCategoryServiceV2'
|
||||||
|
|
||||||
export interface TrackSegment {
|
export interface TrackSegment {
|
||||||
id: string
|
id: string
|
||||||
|
|
@ -40,7 +41,6 @@ export const TrackTimeline: React.FC<TrackTimelineProps> = ({
|
||||||
onSegmentNameChange
|
onSegmentNameChange
|
||||||
}) => {
|
}) => {
|
||||||
const [editingSegmentId, setEditingSegmentId] = React.useState<string | null>(null)
|
const [editingSegmentId, setEditingSegmentId] = React.useState<string | null>(null)
|
||||||
const [editingName, setEditingName] = React.useState('')
|
|
||||||
const [contextMenu, setContextMenu] = React.useState<{
|
const [contextMenu, setContextMenu] = React.useState<{
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
position: { x: number; y: number }
|
position: { x: number; y: number }
|
||||||
|
|
@ -48,6 +48,31 @@ export const TrackTimeline: React.FC<TrackTimelineProps> = ({
|
||||||
}>({ isOpen: false, position: { x: 0, y: 0 }, segment: null })
|
}>({ isOpen: false, position: { x: 0, y: 0 }, segment: null })
|
||||||
const [hoveredSegment, setHoveredSegment] = React.useState<TrackSegment | null>(null)
|
const [hoveredSegment, setHoveredSegment] = React.useState<TrackSegment | null>(null)
|
||||||
const [mousePosition, setMousePosition] = React.useState({ x: 0, y: 0 })
|
const [mousePosition, setMousePosition] = React.useState({ x: 0, y: 0 })
|
||||||
|
const [categories, setCategories] = React.useState<ResourceCategoryV2[]>([])
|
||||||
|
const [loadingCategories, setLoadingCategories] = React.useState(false)
|
||||||
|
|
||||||
|
// 加载分类数据
|
||||||
|
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])
|
||||||
|
|
||||||
|
// 组件挂载时加载分类
|
||||||
|
React.useEffect(() => {
|
||||||
|
loadCategories()
|
||||||
|
}, [loadCategories])
|
||||||
|
|
||||||
const getSegmentColor = (type: string) => {
|
const getSegmentColor = (type: string) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'video': return 'bg-blue-500 hover:bg-blue-600'
|
case 'video': return 'bg-blue-500 hover:bg-blue-600'
|
||||||
|
|
@ -85,9 +110,13 @@ export const TrackTimeline: React.FC<TrackTimelineProps> = ({
|
||||||
return `${minutes}:${secs.padStart(5, '0')}`
|
return `${minutes}:${secs.padStart(5, '0')}`
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSegmentDoubleClick = (segment: TrackSegment) => {
|
const handleSegmentDoubleClick = async (segment: TrackSegment) => {
|
||||||
setEditingSegmentId(segment.id)
|
setEditingSegmentId(segment.id)
|
||||||
setEditingName(segment.name)
|
|
||||||
|
// 确保分类数据已加载
|
||||||
|
if (categories.length === 0 && !loadingCategories) {
|
||||||
|
await loadCategories()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSegmentRightClick = (e: React.MouseEvent, segment: TrackSegment) => {
|
const handleSegmentRightClick = (e: React.MouseEvent, segment: TrackSegment) => {
|
||||||
|
|
@ -101,26 +130,14 @@ export const TrackTimeline: React.FC<TrackTimelineProps> = ({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleNameSubmit = (segmentId: string) => {
|
const handleCategorySelect = (segmentId: string, categoryTitle: string) => {
|
||||||
if (onSegmentNameChange && editingName.trim()) {
|
if (onSegmentNameChange && categoryTitle) {
|
||||||
onSegmentNameChange(segmentId, editingName.trim())
|
onSegmentNameChange(segmentId, categoryTitle)
|
||||||
}
|
}
|
||||||
setEditingSegmentId(null)
|
setEditingSegmentId(null)
|
||||||
setEditingName('')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleNameCancel = () => {
|
|
||||||
setEditingSegmentId(null)
|
|
||||||
setEditingName('')
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleKeyDown = (e: React.KeyboardEvent, segmentId: string) => {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
handleNameSubmit(segmentId)
|
|
||||||
} else if (e.key === 'Escape') {
|
|
||||||
handleNameCancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSegmentMouseEnter = (e: React.MouseEvent, segment: TrackSegment) => {
|
const handleSegmentMouseEnter = (e: React.MouseEvent, segment: TrackSegment) => {
|
||||||
setHoveredSegment(segment)
|
setHoveredSegment(segment)
|
||||||
|
|
@ -141,10 +158,14 @@ export const TrackTimeline: React.FC<TrackTimelineProps> = ({
|
||||||
setContextMenu({ isOpen: false, position: { x: 0, y: 0 }, segment: null })
|
setContextMenu({ isOpen: false, position: { x: 0, y: 0 }, segment: null })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleContextMenuEdit = () => {
|
const handleContextMenuEdit = async () => {
|
||||||
if (contextMenu.segment) {
|
if (contextMenu.segment) {
|
||||||
setEditingSegmentId(contextMenu.segment.id)
|
setEditingSegmentId(contextMenu.segment.id)
|
||||||
setEditingName(contextMenu.segment.name)
|
|
||||||
|
// 确保分类数据已加载
|
||||||
|
if (categories.length === 0 && !loadingCategories) {
|
||||||
|
await loadCategories()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,16 +226,38 @@ export const TrackTimeline: React.FC<TrackTimelineProps> = ({
|
||||||
title={`${segment.name}\n类型: ${segment.type}\n开始: ${formatTime(segment.start_time)}\n结束: ${formatTime(segment.end_time)}\n时长: ${formatTime(segment.duration)}${segment.resource_path ? `\n资源: ${segment.resource_path}` : ''}`}
|
title={`${segment.name}\n类型: ${segment.type}\n开始: ${formatTime(segment.start_time)}\n结束: ${formatTime(segment.end_time)}\n时长: ${formatTime(segment.duration)}${segment.resource_path ? `\n资源: ${segment.resource_path}` : ''}`}
|
||||||
>
|
>
|
||||||
{editingSegmentId === segment.id ? (
|
{editingSegmentId === segment.id ? (
|
||||||
<input
|
<div className="w-full relative" onClick={(e) => e.stopPropagation()}>
|
||||||
type="text"
|
{loadingCategories ? (
|
||||||
value={editingName}
|
<div className="w-full bg-white text-gray-900 border border-gray-300 rounded px-2 py-1 text-sm">
|
||||||
onChange={(e) => setEditingName(e.target.value)}
|
加载分类中...
|
||||||
onBlur={() => handleNameSubmit(segment.id)}
|
</div>
|
||||||
onKeyDown={(e) => handleKeyDown(e, segment.id)}
|
) : (
|
||||||
className="w-full bg-transparent text-inherit border-none outline-none"
|
<select
|
||||||
autoFocus
|
value=""
|
||||||
onClick={(e) => e.stopPropagation()}
|
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} className="flex items-center">
|
||||||
|
{category.title}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="truncate flex-1">
|
<div className="truncate flex-1">
|
||||||
{segment.name}
|
{segment.name}
|
||||||
|
|
|
||||||
|
|
@ -400,7 +400,6 @@ const TemplateDetailPageV2: React.FC = () => {
|
||||||
<h2 className="text-lg font-semibold text-gray-900 mb-4">轨道时间轴</h2>
|
<h2 className="text-lg font-semibold text-gray-900 mb-4">轨道时间轴</h2>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{templateDetail.tracks.map((track) => {
|
{templateDetail.tracks.map((track) => {
|
||||||
console.log(track)
|
|
||||||
return (
|
return (
|
||||||
<TrackTimeline
|
<TrackTimeline
|
||||||
key={track.id}
|
key={track.id}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue