feat: update AGENTS.md with new components and API details; enhance FileContent.vue with Plyr video support; add VideoPlayer.vue for video playback; improve MilkdownEditor.vue for video file handling; refine TTSPlayer.vue volume controls; optimize settings store for localStorage; implement video upload support in uploadBlock.js; create utility functions for Plyr player management.

This commit is contained in:
“ydy0615”
2026-06-13 11:03:40 +08:00
parent 2283020e51
commit 4813196b0a
16 changed files with 767 additions and 275 deletions
+20
View File
@@ -9,6 +9,11 @@ export const DEFAULT_UPLOAD_BLOCK_TYPES = [
'toml',
'yaml',
'images',
'mp4',
'webm',
'mov',
'avi',
'mkv',
]
const TYPE_ALIAS = {
@@ -29,6 +34,11 @@ const TYPE_ALIAS = {
'[images]': 'images',
image: 'images',
images: 'images',
mp4: 'mp4',
webm: 'webm',
mov: 'mov',
avi: 'avi',
mkv: 'mkv',
}
const TYPE_LABELS = {
@@ -40,6 +50,11 @@ const TYPE_LABELS = {
toml: 'TOML',
yaml: 'YAML',
images: '图片',
mp4: 'MP4',
webm: 'WebM',
mov: 'MOV',
avi: 'AVI',
mkv: 'MKV',
}
const TYPE_ACCEPT_MAP = {
@@ -76,6 +91,11 @@ const TYPE_ACCEPT_MAP = {
'application/x-yaml',
],
images: ['image/*'],
mp4: ['.mp4', 'video/mp4'],
webm: ['.webm', 'video/webm'],
mov: ['.mov', 'video/quicktime'],
avi: ['.avi', 'video/x-msvideo'],
mkv: ['.mkv', 'video/x-matroska'],
}
const IMAGE_EXT_RE = /\.(png|jpe?g|gif|webp|bmp|svg|heic|heif|avif)$/i
+101
View File
@@ -0,0 +1,101 @@
import Plyr from 'plyr'
import 'plyr/dist/plyr.css'
/**
* 创建 Plyr 播放器实例
* @param {HTMLVideoElement} videoEl - 视频 DOM 元素
* @param {Object} options - Plyr 配置选项
* @returns {Plyr|null} 播放器实例或 null
*/
export function createPlayer(videoEl, options = {}) {
if (!(videoEl instanceof HTMLVideoElement)) {
console.warn('createPlayer: videoEl 必须是 HTMLVideoElement')
return null
}
const defaultOptions = {
controls: [
'play-large',
'play',
'progress',
'current-time',
'mute',
'volume',
'settings',
'pip',
'airplay',
'fullscreen'
],
settings: ['quality', 'speed', 'loop'],
speed: {
selected: 1,
options: [0.5, 1, 1.5, 2]
},
autoplay: false,
preload: 'auto',
muted: false,
toggleControls: true,
resetOnEnd: true,
disableContextMenu: false,
quality: {
default: 720,
options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],
forced: true
},
tooltips: {
controls: true,
seek: false
},
hideControls: true,
storage: {
key: 'plyr'
},
locales: {},
icons: typeof Plyr !== 'undefined' ? Plyr.icons : undefined,
}
try {
const player = new Plyr(videoEl, { ...defaultOptions, ...options })
return player
} catch (error) {
console.error('Plyr 初始化失败:', error)
return null
}
}
/**
* 销毁 Plyr 播放器实例
* @param {Plyr|null} player - 播放器实例
*/
export function destroyPlayer(player) {
if (!player || typeof player.destroy !== 'function') {
console.warn('destroyPlayer: 无效的播放器实例')
return
}
try {
player.destroy()
} catch (error) {
console.error('销毁播放器失败:', error)
}
}
/**
* 检查浏览器是否支持 Plyr
* @returns {boolean}
*/
export function isPlyrSupported() {
return 'HTMLVideoElement' in window && 'requestFullscreen' in document
}
/**
* 获取 Plyr CSS 变量配置(用于主题定制)
* @returns {Object}
*/
export function getPlyrThemeVars() {
return {
'--plyr-color-main': '#0969da',
'--plyr-control-opacity': '1',
'--plyr-video-control-color-hover': '#0969da',
}
}