diff --git a/src/elderly/components/MediaPlayer.tsx b/src/elderly/components/MediaPlayer.tsx new file mode 100644 index 0000000..dc31d51 --- /dev/null +++ b/src/elderly/components/MediaPlayer.tsx @@ -0,0 +1,300 @@ +import React, { useState, useEffect } from 'react'; +import { ThumbsUp, ThumbsDown, X, Grid3x3 } from 'lucide-react'; +import * as mediaService from '../services/mediaService'; +import { MediaLibraryGrid } from './MediaLibraryGrid'; + +interface MediaPlayerProps { + familyId: string; + elderlyId: number; + currentMood?: string; + onClose?: () => void; +} + +/** + * 老人端媒体播放器组件 + * 自动获取推荐媒体并播放,支持点赞/点踩反馈 + */ +export const MediaPlayer: React.FC = ({ + familyId, + elderlyId, + currentMood, + onClose, +}) => { + const [recommendedMedia, setRecommendedMedia] = useState([]); + const [currentIndex, setCurrentIndex] = useState(0); + const [loading, setLoading] = useState(true); + const [playStartTime, setPlayStartTime] = useState(null); + const [hasGivenFeedback, setHasGivenFeedback] = useState(false); + const [showGrid, setShowGrid] = useState(false); + + // 加载推荐媒体 + useEffect(() => { + loadRecommendedMedia(); + }, [familyId, elderlyId, currentMood]); + + // 记录播放开始时间 + useEffect(() => { + if (currentMedia) { + setPlayStartTime(new Date()); + setHasGivenFeedback(false); + } + }, [currentIndex]); + + const loadRecommendedMedia = async () => { + try { + setLoading(true); + const media = await mediaService.getRecommendedMedia( + familyId, + elderlyId, + currentMood + ); + setRecommendedMedia(media); + // 如果有媒体,记录第一个的播放 + if (media.length > 0) { + recordPlayStart(media[0].id); + } + } catch (error) { + console.error('加载推荐媒体失败:', error); + } finally { + setLoading(false); + } + }; + + // 记录播放开始(不等待完成) + const recordPlayStart = async (mediaId: number) => { + try { + await mediaService.recordMediaPlay(mediaId, { + elderly_id: elderlyId, + duration_watched: 0, + completed: 0, + triggered_by: 'auto', + mood_before: currentMood, + }); + console.log('播放记录已创建, mediaId:', mediaId); + } catch (error) { + console.error('记录播放开始失败:', error); + } + }; + + const currentMedia = recommendedMedia[currentIndex]; + + // 记录播放 + const recordPlay = async (completed: boolean = false) => { + if (!currentMedia || !playStartTime) return; + + const durationWatched = Math.floor((new Date().getTime() - playStartTime.getTime()) / 1000); + + try { + await mediaService.recordMediaPlay(currentMedia.id, { + elderly_id: elderlyId, + duration_watched: durationWatched, + completed: completed ? 1 : 0, + triggered_by: 'auto', + mood_before: currentMood, + }); + } catch (error) { + console.error('记录播放失败:', error); + } + }; + + // 处理反馈 + const handleFeedback = async (type: 'like' | 'dislike') => { + if (!currentMedia || hasGivenFeedback) return; + + try { + await mediaService.submitFeedback(currentMedia.id, { + elderly_id: elderlyId, + feedback_type: type, + }); + setHasGivenFeedback(true); + + // 自动切换到下一个 + setTimeout(() => { + handleNext(); + }, 1000); + } catch (error) { + console.error('提交反馈失败:', error); + } + }; + + // 下一个媒体 + const handleNext = async () => { + await recordPlay(true); + + if (currentIndex < recommendedMedia.length - 1) { + const nextIndex = currentIndex + 1; + setCurrentIndex(nextIndex); + // 记录下一个媒体的播放 + recordPlayStart(recommendedMedia[nextIndex].id); + } else { + // 已经是最后一个,重新加载 + await loadRecommendedMedia(); + setCurrentIndex(0); + } + }; + + // 关闭播放器 + const handleClose = async () => { + await recordPlay(false); + onClose?.(); + }; + + if (loading) { + return ( +
+
正在加载...
+
+ ); + } + + if (!currentMedia) { + return ( +
+
+

暂时没有推荐的照片或视频

+ +
+
+ ); + } + + return ( +
+ {/* 数字人小圆圈头像 - 左上角 */} +
+
+ {/* 数字人圆圈 */} +
+
👤
+
+ + {/* 提示文字 */} +
+

随时问我

+
+
+
+ + {/* 标题和进度 - 顶部中间 */} +
+

+ {currentMedia.title} +

+ {recommendedMedia.length > 1 && ( +

+ {currentIndex + 1} / {recommendedMedia.length} +

+ )} +
+ + {/* 媒体内容区 */} +
+ {currentMedia.media_type === 'photo' ? ( + {currentMedia.title} + ) : ( +
+ + {/* 底部操作栏 - 悬浮 */} +
+
+ {/* 喜欢按钮 */} + + + {/* 不喜欢按钮 */} + + + {/* 显示全部按钮 */} + {recommendedMedia.length > 1 && ( + + )} + + {/* 关闭按钮 */} + +
+
+ + {/* 网格视图弹窗 */} + {showGrid && ( + ({ + id: m.id.toString(), + url: mediaService.getMediaUrl(m.file_path), + thumbnailUrl: m.thumbnail_path ? mediaService.getThumbnailUrl(m.thumbnail_path) : undefined, + type: m.media_type, + caption: m.title, + tags: m.tags || [] + }))} + currentIndex={currentIndex} + onSelect={(index) => { + setCurrentIndex(index); + setShowGrid(false); + }} + onClose={() => setShowGrid(false)} + /> + )} +
+ ); +};