feat: 添加歌曲列表分页功能和键盘快捷键支持

- 在 SongList 组件中实现分页功能,支持上一页和下一页操作
- 添加键盘快捷键,允许用户通过方向键进行翻页
- 优化组件结构,增强可读性和用户体验
This commit is contained in:
2025-04-28 04:04:21 +08:00
parent 00ce0fc7e1
commit 8b908f5ac9
13 changed files with 1712 additions and 913 deletions

View File

@@ -16,6 +16,7 @@ const props = defineProps<{
userInfo: UserInfo | undefined
biliInfo: any | undefined
currentData?: any
config?: any
}>()
const isLoading = ref(true)
const message = useMessage()

View File

@@ -4,9 +4,9 @@ import { SongsInfo } from '@/api/api-models'
import SongList from '@/components/SongList.vue'
import { SongListConfigType } from '@/data/TemplateTypes'
import LiveRequestOBS from '@/views/obs/LiveRequestOBS.vue'
import { CloudAdd20Filled } from '@vicons/fluent'
import { CloudAdd20Filled, ChevronLeft24Filled, ChevronRight24Filled } from '@vicons/fluent'
import { NButton, NCard, NCollapse, NCollapseItem, NDivider, NIcon, NTooltip, useMessage } from 'naive-ui'
import { h, ref } from 'vue'
import { h, ref, onMounted, onUnmounted } from 'vue'
const accountInfo = useAccount()
@@ -16,6 +16,50 @@ const emits = defineEmits(['requestSong'])
const isLoading = ref('')
const message = useMessage()
const songListRef = ref<InstanceType<typeof SongList> | null>(null)
// 处理翻页逻辑
const handlePrevPage = () => {
if (songListRef.value) {
songListRef.value.prevPage()
}
}
const handleNextPage = () => {
if (songListRef.value) {
songListRef.value.nextPage()
}
}
// 键盘快捷键处理函数
const handleKeyDown = (event: KeyboardEvent) => {
// 忽略在输入框内的按键
if (event.target instanceof HTMLInputElement ||
event.target instanceof HTMLTextAreaElement ||
event.target instanceof HTMLSelectElement) {
return
}
// 左方向键 - 上一页
if (event.key === 'ArrowLeft') {
handlePrevPage()
event.preventDefault()
}
// 右方向键 - 下一页
else if (event.key === 'ArrowRight') {
handleNextPage()
event.preventDefault()
}
}
// 添加和移除事件监听器
onMounted(() => {
window.addEventListener('keydown', handleKeyDown)
})
onUnmounted(() => {
window.removeEventListener('keydown', handleKeyDown)
})
const buttons = (song: SongsInfo) => [
accountInfo.value?.id != props.userInfo?.id
@@ -55,25 +99,89 @@ const buttons = (song: SongsInfo) => [
</script>
<template>
<NDivider style="margin-top: 10px" />
<SongList
v-if="data"
:songs="data ?? []"
:is-self="accountInfo?.id == userInfo?.id"
:extra-button="buttons"
v-bind="$attrs"
/>
<NCollapse v-if="userInfo?.canRequestSong">
<NCollapseItem title="点歌列表">
<NCard
size="small"
embedded
<div class="song-list-container">
<NDivider style="margin-top: 10px" />
<!-- 左侧翻页按钮 -->
<div class="page-button page-button-left">
<NButton
circle
secondary
size="large"
title="上一页 (←)"
@click="handlePrevPage"
>
<div style="height: 400px; width: 700px; max-width: 100%; position: relative; margin: 0 auto">
<LiveRequestOBS :id="userInfo?.id" />
</div>
</NCard>
</NCollapseItem>
</NCollapse>
<NDivider />
<template #icon>
<NIcon :component="ChevronLeft24Filled" />
</template>
</NButton>
</div>
<!-- 右侧翻页按钮 -->
<div class="page-button page-button-right">
<NButton
circle
secondary
size="large"
title="下一页 (→)"
@click="handleNextPage"
>
<template #icon>
<NIcon :component="ChevronRight24Filled" />
</template>
</NButton>
</div>
<SongList
v-if="data"
ref="songListRef"
:songs="data ?? []"
:is-self="accountInfo?.id == userInfo?.id"
:extra-button="buttons"
v-bind="$attrs"
/>
<NCollapse v-if="userInfo?.canRequestSong">
<NCollapseItem title="点歌列表">
<NCard
size="small"
embedded
>
<div style="height: 400px; width: 700px; max-width: 100%; position: relative; margin: 0 auto">
<LiveRequestOBS :id="userInfo?.id" />
</div>
</NCard>
</NCollapseItem>
</NCollapse>
<NDivider />
</div>
</template>
<style scoped>
.song-list-container {
position: relative;
}
.page-button {
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 10;
}
.page-button-left {
left: -20px;
}
.page-button-right {
right: -20px;
}
@media (max-width: 768px) {
.page-button-left {
left: 0;
}
.page-button-right {
right: 0;
}
}
</style>