组件文档
组件架构概览
OFPlayer 的组件系统遵循以下设计原则:
- 单向数据流 - Props 向下,Events 向上
- 逻辑与视图分离 - 业务逻辑在 Composables/Stores,组件仅负责展示
- 组件组合 - 通过插槽和组合实现复用
- 可访问性 - 使用 ARIA 属性增强无障碍访问
页面组件
PlayerPage.vue
位置: src/pages/PlayerPage.vue
路由: /
职责: 主播放器页面,是应用的核心页面
功能:
- 连接
ofplayerApp与 UI 组件 - 管理沉浸式播放视图的显示
- 协调各面板的数据流
使用的应用 API:
const {
libraries, playlists, tracks, currentTrack,
isPlaying, currentTime, duration, volume,
selectTrack, togglePlayback, playNext, playPrevious,
// ...更多
} = useOFPlayerApp()
ProductPage.vue
位置: src/pages/ProductPage.vue
路由: /product
职责: 产品介绍/营销页面
DownloadPage.vue
位置: src/pages/DownloadPage.vue
路由: /download
职责: 下载页面
PrivacyPage.vue
位置: src/pages/PrivacyPage.vue
路由: /privacy
职责: 隐私政策页面
核心 UI 组件
PlayerPanel.vue
位置: src/components/PlayerPanel.vue
职责: 中心面板,包含曲目列表、搜索/排序/过滤、播放控制
Props 接口:
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
tracks |
Array |
[] |
当前显示的曲目列表 |
currentLibrary |
Object |
null |
当前库对象 |
libraries |
Array |
[] |
所有库列表 |
playlists |
Array |
[] |
所有播放列表 |
currentCollection |
Object |
null |
当前集合(播放列表/智能视图) |
currentTrackId |
String |
null |
当前播放曲目 ID |
currentTrack |
Object |
null |
当前播放曲目对象 |
hasAnyTracks |
Boolean |
false |
是否有任何曲目 |
isPlaying |
Boolean |
false |
是否正在播放 |
currentTime |
Number |
0 |
当前播放位置(秒) |
duration |
Number |
0 |
曲目时长(秒) |
volume |
Number |
0.8 |
音量(0-1) |
searchQuery |
String |
'' |
搜索查询 |
sortOption |
String |
'recent' |
排序选项 |
typeFilter |
String |
'all' |
类型过滤器 |
showTechnicalMetadata |
Boolean |
true |
是否显示技术元数据 |
Events 接口:
| Event | 参数 | 说明 |
|---|---|---|
select-track |
trackId: string |
选择曲目 |
toggle-playback |
- | 切换播放状态 |
play-previous |
- | 播放上一首 |
play-next |
- | 播放下一首 |
seek |
time: number |
定位到时间点 |
set-volume |
volume: number |
设置音量 |
set-search-query |
query: string |
设置搜索查询 |
set-sort-option |
option: string |
设置排序选项 |
set-type-filter |
filter: string |
设置类型过滤 |
add-track-to-playlist |
{ trackId, playlistId } |
添加曲目到播放列表 |
remove-track-from-playlist |
{ trackId, playlistId } |
从播放列表移除曲目 |
delete-track |
trackId: string |
删除曲目 |
toggle-favorite |
trackId: string |
切换收藏状态 |
open-immersive-player |
- | 打开沉浸式播放视图 |
play-group |
tracks: Array |
播放一组曲目 |
内部功能:
- 虚拟列表(超过 90 首曲目时自动启用)
- 搜索过滤
- 排序(最近、标题、艺术家、专辑、时长等)
- 类型过滤(按文件格式)
- 曲目操作菜单(添加到播放列表、删除等)
- Inspector 面板(显示曲目详细元数据)
LibraryPanel.vue
位置: src/components/LibraryPanel.vue
职责: 左侧边栏,包含库选择器、播放列表、智能视图、导入、设置
Props 接口:
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
libraries |
Array |
[] |
库列表 |
playlists |
Array |
[] |
播放列表 |
smartCollections |
Array |
[] |
智能集合列表 |
activeLibrary |
String |
'local' |
当前活跃库 ID |
activeCollection |
String |
'all-tracks' |
当前活跃集合 key |
multiSourceGateState |
String |
'enabled' |
多源功能门控状态 |
Events 接口:
| Event | 参数 | 说明 |
|---|---|---|
import-files |
files: File[] |
导入文件 |
set-active-library |
libraryId: string |
切换活跃库 |
set-active-collection |
collectionKey: string |
切换活跃集合 |
open-settings |
- | 打开设置 |
create-library |
name: string |
创建库 |
rename-library |
(id, name) |
重命名库 |
delete-library |
id: string |
删除库 |
create-playlist |
name: string |
创建播放列表 |
rename-playlist |
(id, name) |
重命名播放列表 |
delete-playlist |
id: string |
删除播放列表 |
open-upgrade-dialog |
- | 打开升级对话框 |
内部功能:
- 库列表展示与切换
- 播放列表管理(创建、重命名、删除)
- 智能视图展示
- 文件导入触发
- 外部链接(官网、下载)
SettingsModal.vue
位置: src/components/SettingsModal.vue
职责: 设置对话框
功能:
- 主题切换
- 语言切换
- 音量偏好
- 元数据显示选项
- 数据导出/清除
- 遥测同意
DialogModal.vue
位置: src/components/DialogModal.vue
职责: 通用对话框组件
Props 接口:
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
isOpen |
Boolean |
false |
是否打开 |
title |
String |
'' |
对话框标题 |
message |
String |
'' |
对话框消息 |
inputLabel |
String |
'' |
输入框标签 |
inputValue |
String |
'' |
输入框值 |
showInput |
Boolean |
false |
是否显示输入框 |
isDanger |
Boolean |
false |
是否为危险操作 |
confirmLabel |
String |
'Confirm' |
确认按钮文本 |
cancelLabel |
String |
'Cancel' |
取消按钮文本 |
hint |
String |
'' |
提示文本 |
hintLinkLabel |
String |
'' |
提示链接文本 |
hintRoute |
String |
'' |
提示链接路由 |
Events 接口:
| Event | 参数 | 说明 |
|---|---|---|
close |
- | 关闭对话框 |
confirm |
value?: string |
确认(可能携带输入值) |
MenuDropdown.vue
位置: src/components/MenuDropdown.vue
职责: 下拉菜单组件
Props 接口:
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
isOpen |
Boolean |
false |
是否打开 |
anchorEl |
HTMLElement |
null |
锚点元素(用于定位) |
items |
Array |
[] |
菜单项列表 |
菜单项结构:
{
key: string, // 唯一标识
label: string, // 显示文本
disabled?: boolean // 是否禁用
}
Events 接口:
| Event | 参数 | 说明 |
|---|---|---|
close |
- | 关闭菜单 |
select |
item: Object |
选择菜单项 |
TrackPlaylistDialog.vue
位置: src/components/TrackPlaylistDialog.vue
职责: 添加曲目到播放列表的对话框
Props 接口:
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
isOpen |
Boolean |
false |
是否打开 |
track |
Object |
null |
要添加的曲目 |
libraries |
Array |
[] |
库列表 |
playlists |
Array |
[] |
播放列表 |
preferredLibraryId |
String |
null |
默认选中的库 |
preferredPlaylistId |
String |
null |
默认选中的播放列表 |
Events 接口:
| Event | 参数 | 说明 |
|---|---|---|
close |
- | 关闭对话框 |
confirm |
{ trackId, playlistId } |
确认添加 |
AlbumBrowserPanel.vue
位置: src/components/AlbumBrowserPanel.vue
职责: 专辑/艺术家浏览面板(便当盒网格视图)
Props 接口:
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
browserKind |
String |
- | 浏览类型(‘album’ / ‘artist’) |
groups |
Array |
[] |
分组数据 |
currentTrackId |
String |
null |
当前播放曲目 ID |
isPlaying |
Boolean |
false |
是否正在播放 |
searchQuery |
String |
'' |
搜索查询 |
Events 接口:
| Event | 参数 | 说明 |
|---|---|---|
select-track |
track: Object |
选择曲目 |
play-group |
tracks: Array |
播放一组曲目 |
cover-changed |
- | 封面变化 |
LyricsPanel.vue
位置: src/components/LyricsPanel.vue
职责: 歌词显示面板
ImmersivePlayerView.vue
位置: src/components/ImmersivePlayerView.vue
职责: 沉浸式播放视图(全屏)
LyricsPlayerView.vue
位置: src/components/LyricsPlayerView.vue
职责: 歌词专注播放视图
OnboardingGuide.vue
位置: src/components/OnboardingGuide.vue
职责: 首次运行引导
TelemetryConsentDialog.vue
位置: src/components/TelemetryConsentDialog.vue
职责: 遥测同意对话框
StartupBadge.vue
位置: src/components/StartupBadge.vue
职责: 开发模式启动徽章
Monetization 组件
UpgradeDialog.vue
位置: src/components/monetize/UpgradeDialog.vue
职责: 升级对话框(Pro 功能)
ProBadge.vue
位置: src/components/monetize/ProBadge.vue
职责: Pro 徽章标识
PlanCard.vue
位置: src/components/monetize/PlanCard.vue
职责: 套餐卡片
FeatureGateNotice.vue
位置: src/components/monetize/FeatureGateNotice.vue
职责: 功能门控提示
组件使用示例
基本用法
<script setup>
import { useOFPlayerApp } from '../app/ofplayerApp'
const {
tracks, currentTrack, isPlaying,
selectTrack, togglePlayback
} = useOFPlayerApp()
</script>
<template>
<PlayerPanel
:tracks="tracks"
:current-track="currentTrack"
:is-playing="isPlaying"
@select-track="selectTrack"
@toggle-playback="togglePlayback"
/>
</template>
创建新组件
<script setup>
import { computed } from 'vue'
import { useOFPlayerApp } from '../app/ofplayerApp'
const props = defineProps({
// 定义 Props
})
const emit = defineEmits([
// 定义 Events
])
const ofplayer = useOFPlayerApp()
// 使用应用状态
const currentTrack = computed(() => ofplayer.currentTrack.value)
</script>
<template>
<!-- 组件模板 -->
</template>