11import useSWR from 'swr' ;
22import { cn } from '@/fronted/lib/utils' ;
33import 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 图标
66import { Button } from '@/fronted/components/ui/button' ;
77import TimeUtil from '@/common/utils/TimeUtil' ;
88import { Progress } from '@/fronted/components/ui/progress' ;
@@ -15,22 +15,41 @@ import {
1515import UrlUtil from '@/common/utils/UrlUtil' ;
1616import WatchHistoryVO from '@/common/types/WatchHistoryVO' ;
1717import 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' ;
1821
1922const api = window . electron ;
2023
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 ;
2430 onSelected : ( ) => void ;
2531} ) => {
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 ,
2740 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+ } ) ;
2945 }
3046 ) ;
47+
3148 console . log ( 'video' , video ) ;
49+
3250 const [ hover , setHover ] = React . useState ( false ) ;
3351 const [ contextMenu , setContextMenu ] = React . useState ( false ) ;
52+
3453 return (
3554 < ContextMenu
3655 onOpenChange = { ( open ) => {
@@ -44,71 +63,102 @@ const ProjectListCard = ({ video, onSelected }: {
4463 className = { cn ( '' ) }
4564 onClick = { onSelected }
4665 >
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+
6295 < 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+ ) }
66106 </ div >
107+
108+ { /* 进度条 */ }
67109 < Progress
68110 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+ ) }
70114 />
71115
72-
116+ { /* 悬浮时展示删除按钮 */ }
73117 { hover && (
74118 < 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"
78122 onClick = { async ( e ) => {
79123 e . stopPropagation ( ) ;
80124 console . log ( 'swrdelete' , video . id ) ;
81125 await api . call ( 'watch-history/group-delete' , video . id ) ;
82126 await swrApiMutate ( 'watch-history/list' ) ;
83127 } }
84128 >
85- < Trash2
86- className = { 'w-3 h-3' }
87- />
129+ < Trash2 className = "w-3 h-3" />
88130 </ Button >
89131 ) }
90132 </ div >
91133
92134 < 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 >
95142 </ div >
96143 </ ContextMenuTrigger >
97144 < ContextMenuContent >
98145 < ContextMenuItem
99146 onClick = { async ( ) => {
100147 await api . call ( 'system/open-folder' , video . basePath ) ;
101148 } }
102- > Show In Explorer</ ContextMenuItem >
149+ >
150+ Show In Explorer
151+ </ ContextMenuItem >
103152 < ContextMenuItem
104153 onClick = { async ( ) => {
105154 await api . call ( 'watch-history/group-delete' , video . id ) ;
106155 await swrApiMutate ( 'watch-history/list' ) ;
107156 } }
108- > Delete</ ContextMenuItem >
157+ >
158+ Delete
159+ </ ContextMenuItem >
109160 </ ContextMenuContent >
110161 </ ContextMenu >
111-
112162 ) ;
113163} ;
114164
0 commit comments