1
1
import useSWR from 'swr' ;
2
2
import { cn } from '@/fronted/lib/utils' ;
3
3
import React from 'react' ;
4
- import { SWR_KEY , swrApiMutate , swrMutate } from '@/fronted/lib/swr-util' ;
5
- import { Film , ListVideo , Trash2 } from 'lucide-react' ;
4
+ import { SWR_KEY , swrApiMutate } from '@/fronted/lib/swr-util' ;
5
+ import { Film , ListVideo , Trash2 , Music } from 'lucide-react' ; // 注意这里导入了 Music 图标
6
6
import { Button } from '@/fronted/components/ui/button' ;
7
7
import TimeUtil from '@/common/utils/TimeUtil' ;
8
8
import { Progress } from '@/fronted/components/ui/progress' ;
@@ -15,22 +15,41 @@ import {
15
15
import UrlUtil from '@/common/utils/UrlUtil' ;
16
16
import WatchHistoryVO from '@/common/types/WatchHistoryVO' ;
17
17
import PathUtil from '@/common/utils/PathUtil' ;
18
+ import FileUtil from '@/backend/utils/FileUtil' ;
19
+ import MediaUtil from '@/common/utils/MediaUtil' ;
20
+ import MusicCard from '@/fronted/components/fileBowser/music-card' ;
18
21
19
22
const api = window . electron ;
20
23
21
- const ProjectListCard = ( { video, onSelected } : {
22
- video : WatchHistoryVO ,
23
- className ?: string
24
+ const ProjectListCard = ( {
25
+ video,
26
+ onSelected
27
+ } : {
28
+ video : WatchHistoryVO ;
29
+ className ?: string ;
24
30
onSelected : ( ) => void ;
25
31
} ) => {
26
- const { data : url } = useSWR ( [ SWR_KEY . SPLIT_VIDEO_THUMBNAIL , video . basePath , video . fileName , video . current_position ] ,
32
+ // 1. 检测是否是 mp3
33
+ const isAudio = MediaUtil . isAudio ( video . fileName ) ;
34
+
35
+ // 2. 如果是 mp3,就不调用生成缩略图的接口,把 key 设为 null
36
+ const { data : url } = useSWR (
37
+ ! isAudio
38
+ ? [ SWR_KEY . SPLIT_VIDEO_THUMBNAIL , video . basePath , video . fileName , video . current_position ]
39
+ : null ,
27
40
async ( [ _key , path , file , time ] ) => {
28
- return await api . call ( 'split-video/thumbnail' , { filePath : PathUtil . join ( path , file ) , time } ) ;
41
+ return await api . call ( 'split-video/thumbnail' , {
42
+ filePath : PathUtil . join ( path , file ) ,
43
+ time
44
+ } ) ;
29
45
}
30
46
) ;
47
+
31
48
console . log ( 'video' , video ) ;
49
+
32
50
const [ hover , setHover ] = React . useState ( false ) ;
33
51
const [ contextMenu , setContextMenu ] = React . useState ( false ) ;
52
+
34
53
return (
35
54
< ContextMenu
36
55
onOpenChange = { ( open ) => {
@@ -44,71 +63,102 @@ const ProjectListCard = ({ video, onSelected }: {
44
63
className = { cn ( '' ) }
45
64
onClick = { onSelected }
46
65
>
47
- < div className = { cn ( 'relative w-full rounded-lg overflow-hidden border-none' ) } >
48
- { url ? < img
49
- src = { UrlUtil . file ( url ) }
50
- style = { {
51
- aspectRatio : '16/9'
52
- } }
53
- className = { cn ( 'w-full object-cover' , ( hover || contextMenu ) && 'filter brightness-75' ) }
54
- alt = { video . fileName }
55
- /> : < div
56
- style = { {
57
- aspectRatio : '16/9'
58
- } }
59
- className = { 'w-full bg-gray-500 flex items-center justify-center' } >
60
- < Film className = { 'w-8 h-8' } />
61
- </ div > }
66
+ < div
67
+ className = { cn ( 'relative w-full rounded-lg overflow-hidden border-none' ) }
68
+ >
69
+ { /* 3. 判断如果是 mp3,优先展示 Music 图标,否则还是原先逻辑 */ }
70
+ { isAudio ? (
71
+ < MusicCard fileName = { video . fileName } />
72
+ ) : url ? (
73
+ < img
74
+ src = { UrlUtil . file ( url ) }
75
+ style = { {
76
+ aspectRatio : '16/9'
77
+ } }
78
+ className = { cn (
79
+ 'w-full object-cover' ,
80
+ ( hover || contextMenu ) && 'filter brightness-75'
81
+ ) }
82
+ alt = { video . fileName }
83
+ />
84
+ ) : (
85
+ < div
86
+ style = { {
87
+ aspectRatio : '16/9'
88
+ } }
89
+ className = "w-full bg-gray-500 flex items-center justify-center"
90
+ >
91
+ < Film className = "w-8 h-8" />
92
+ </ div >
93
+ ) }
94
+
62
95
< div
63
- className = { cn ( 'absolute bottom-2 right-2 text-white bg-black bg-opacity-80 rounded-md p-1 py-0.5 text-xs flex' ) } >
64
- { ! video . isFolder ? TimeUtil . secondToTimeStrCompact ( video ?. duration ) : < >
65
- < ListVideo className = { 'w-4 h-4' } /> </ > }
96
+ className = { cn (
97
+ 'absolute bottom-2 right-2 text-white bg-black bg-opacity-80 rounded-md p-1 py-0.5 text-xs flex'
98
+ ) }
99
+ >
100
+ { /* 如果是文件夹,就用 ListVideo 图标;如果不是文件夹,就展示时长 */ }
101
+ { ! video . isFolder ? (
102
+ TimeUtil . secondToTimeStrCompact ( video ?. duration )
103
+ ) : (
104
+ < ListVideo className = "w-4 h-4" />
105
+ ) }
66
106
</ div >
107
+
108
+ { /* 进度条 */ }
67
109
< Progress
68
110
className = { cn ( 'absolute bottom-0 left-0 w-full rounded-none h-1 bg-gray-500' ) }
69
- value = { Math . floor ( ( video ?. current_position || 0 ) / ( video ?. duration || 1 ) * 100 ) }
111
+ value = { Math . floor (
112
+ ( ( video ?. current_position || 0 ) / ( video ?. duration || 1 ) ) * 100
113
+ ) }
70
114
/>
71
115
72
-
116
+ { /* 悬浮时展示删除按钮 */ }
73
117
{ hover && (
74
118
< Button
75
- className = { ' absolute top-2 right-2 w-6 h-6 bg-background' }
76
- size = { ' icon' }
77
- variant = { ' ghost' }
119
+ className = " absolute top-2 right-2 w-6 h-6 bg-background"
120
+ size = " icon"
121
+ variant = " ghost"
78
122
onClick = { async ( e ) => {
79
123
e . stopPropagation ( ) ;
80
124
console . log ( 'swrdelete' , video . id ) ;
81
125
await api . call ( 'watch-history/group-delete' , video . id ) ;
82
126
await swrApiMutate ( 'watch-history/list' ) ;
83
127
} }
84
128
>
85
- < Trash2
86
- className = { 'w-3 h-3' }
87
- />
129
+ < Trash2 className = "w-3 h-3" />
88
130
</ Button >
89
131
) }
90
132
</ div >
91
133
92
134
< div
93
- className = { cn ( 'w-full line-clamp-2 break-words' , ( hover || contextMenu ) && 'underline' ) }
94
- > { video . fileName } </ div >
135
+ className = { cn (
136
+ 'w-full line-clamp-2 break-words' ,
137
+ ( hover || contextMenu ) && 'underline'
138
+ ) }
139
+ >
140
+ { video . fileName }
141
+ </ div >
95
142
</ div >
96
143
</ ContextMenuTrigger >
97
144
< ContextMenuContent >
98
145
< ContextMenuItem
99
146
onClick = { async ( ) => {
100
147
await api . call ( 'system/open-folder' , video . basePath ) ;
101
148
} }
102
- > Show In Explorer</ ContextMenuItem >
149
+ >
150
+ Show In Explorer
151
+ </ ContextMenuItem >
103
152
< ContextMenuItem
104
153
onClick = { async ( ) => {
105
154
await api . call ( 'watch-history/group-delete' , video . id ) ;
106
155
await swrApiMutate ( 'watch-history/list' ) ;
107
156
} }
108
- > Delete</ ContextMenuItem >
157
+ >
158
+ Delete
159
+ </ ContextMenuItem >
109
160
</ ContextMenuContent >
110
161
</ ContextMenu >
111
-
112
162
) ;
113
163
} ;
114
164
0 commit comments