Files
akmon/pages/info/video-types.uts
2026-01-20 08:04:15 +08:00

278 lines
7.2 KiB
Plaintext

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)
}