import { tt } from '@/utils/i18nfun.uts' // 视频内容类型扩展 export type VideoContent = { id: string title: string summary: string | null content: string author: string published_at: string quality_score: number category_id: string original_language: string source_url: string | null tags: string[] | null created_at: string updated_at: string // 视频特有字段 content_type: 'video' video_url: string video_duration: number video_poster: string video_width: number video_height: number video_size: number video_format: string video_quality: string allow_danmu: boolean allow_download: boolean // 统计数据 view_count: number like_count: number favorite_count: number share_count: number comment_count: number danmu_count: number play_completion_rate: number average_play_duration: number // 用户状态 is_liked?: boolean is_favorited?: boolean } // 弹幕类型 export type DanmuData = { id: string content_id: string user_id: string user_name: string text: string time_point: number color: string font_size: number position_type: 'scroll' | 'top' | 'bottom' speed: number is_visible: boolean status: string created_at: string } // 弹幕发送数据 export type DanmuSendData = { text: string time_point: number color?: string font_size?: number position_type?: 'scroll' | 'top' | 'bottom' speed?: number } // 用户交互类型 export type UserInteraction = { id: string user_id: string content_id: string interaction_type: 'like' | 'favorite' | 'share' | 'view' | 'download' interaction_data?: any created_at: string } // 视频评论类型 export type VideoComment = { id: string content_id: string user_id: string user_name: string parent_id: string | null reply_to_user_id: string | null reply_to_user_name: string | null content: string like_count: number reply_count: number status: string is_pinned: boolean level: number created_at: string updated_at: string is_liked_by_user?: boolean } // 播放记录类型 export type PlayRecord = { id: string content_id: string user_id: string play_position: number play_duration: number play_percentage: number is_completed: boolean device_type: string resolution: string play_speed: number created_at: string updated_at: string } // 视频页面状态 export type VideoPageState = { loading: boolean error: string | null danmu_loading: boolean comment_loading: boolean sending_danmu: boolean posting_comment: boolean } // 弹幕配置 export type DanmuConfig = { enabled: boolean opacity: number font_size: number speed: number show_area: number // 显示区域百分比 max_count: number // 同时显示最大数量 filter_enabled: boolean // 是否开启弹幕过滤 filter_keywords: string[] // 过滤关键词 } // 视频播放器状态 export type VideoPlayerState = { playing: boolean current_time: number duration: number volume: number playback_rate: number fullscreen: boolean quality: string loading: boolean error: string | null } // 分享选项 export type ShareOption = { platform: string name: string icon: string color: string } // 视频质量选项 export const VIDEO_QUALITY_OPTIONS = [ { value: '360p', text: 'mt.video.quality.360p' }, { value: '480p', text: 'mt.video.quality.480p' }, { value: '720p', text: 'mt.video.quality.720p' }, { value: '1080p', text: 'mt.video.quality.1080p' }, { value: '4k', text: 'mt.video.quality.4k' } ] // 播放速度选项 export const PLAYBACK_RATE_OPTIONS = [ { value: 0.5, text: '0.5x' }, { value: 0.75, text: '0.75x' }, { value: 1.0, text: 'mt.video.speed.normal' }, { value: 1.25, text: '1.25x' }, { value: 1.5, text: '1.5x' }, { value: 2.0, text: '2.0x' } ] // 弹幕位置选项 export const DANMU_POSITION_OPTIONS = [ { value: 'scroll', text: 'mt.video.danmu.position.scroll' }, { value: 'top', text: 'mt.video.danmu.position.top' }, { value: 'bottom', text: 'mt.video.danmu.position.bottom' } ] // 弹幕颜色选项 export const DANMU_COLOR_OPTIONS = [ '#FFFFFF', '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF', '#FFA500', '#FFC0CB', '#800080' ] // 分享平台选项 export const SHARE_PLATFORM_OPTIONS: ShareOption[] = [ { platform: 'wechat', name: 'mt.share.wechat', icon: '💬', color: '#07C160' }, { platform: 'weibo', name: 'mt.share.weibo', icon: '📱', color: '#E6162D' }, { platform: 'qq', name: 'mt.share.qq', icon: '🐧', color: '#12B7F5' }, { platform: 'link', name: 'mt.share.copyLink', icon: '🔗', color: '#666666' } ] // 工具函数 // 格式化视频时长 export const formatVideoDuration = (seconds: number): string => { const hours = Math.floor(seconds / 3600) const minutes = Math.floor((seconds % 3600) / 60) const secs = Math.floor(seconds % 60) if (hours > 0) { return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}` } else { return `${minutes}:${secs.toString().padStart(2, '0')}` } } // 格式化文件大小 export const formatFileSize = (bytes: number): string => { if (bytes === 0) return '0 B' const k = 1024 const sizes = ['B', 'KB', 'MB', 'GB', 'TB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i] } // 格式化播放次数 export const formatViewCount = (count: number): string => { if (count < 1000) return count.toString() if (count < 10000) return (count / 1000).toFixed(1) + 'K' if (count < 1000000) return Math.floor(count / 10000) + tt('mt.video.unit.wan') return (count / 1000000).toFixed(1) + 'M' } // 获取视频质量显示文本 export const getVideoQualityText = (quality: string): string => { const option = VIDEO_QUALITY_OPTIONS.find(opt => opt.value === quality) return option ? tt(option.text) : quality } // 获取弹幕位置显示文本 export const getDanmuPositionText = (position: string): string => { const option = DANMU_POSITION_OPTIONS.find(opt => opt.value === position) return option ? tt(option.text) : position } // 获取分享平台显示文本 export const getSharePlatformText = (platform: string): string => { const option = SHARE_PLATFORM_OPTIONS.find(opt => opt.platform === platform) return option ? tt(option.name) : platform } // 弹幕校验结果类型 export type DanmuValidateResult = { valid: boolean; error?: string }; // 验证弹幕内容 export function validateDanmuText(text: string): DanmuValidateResult { if ( text.trim().length === 0) { return { valid: false, error: tt('mt.video.danmu.error.empty') }; } if (text.length > 100) { return { valid: false, error: tt('mt.video.danmu.error.tooLong') }; } // 检查是否包含敏感词 const sensitiveWords = ['spam', 'advertisement']; // 简化示例 const hasSensitive = sensitiveWords.some(word => text.toLowerCase().includes(word)); if (hasSensitive) { return { valid: false, error: tt('mt.video.danmu.error.sensitive') }; } return { valid: true }; } // 计算弹幕显示时间 export const calculateDanmuDisplayTime = (textLength: number, speed: number): number => { // 基础显示时间 + 文本长度影响 / 速度 return Math.max(3, (5 + textLength * 0.1) / speed) }