feat: 更新直播请求相关组件和功能

- 在useLiveRequest.ts中使用FunctionTypes替代硬编码的功能标识
- 在SongListManageView.vue中添加调试信息输出
- 在ClassicRequestOBS.vue中优化歌曲请求列表的样式和动画效果
- 在SongRequestSettings.vue中新增OBS相关设置项,支持动态配置
This commit is contained in:
Megghy
2025-05-18 22:02:18 +08:00
parent 5db66e3861
commit 0d5a657d5c
4 changed files with 141 additions and 51 deletions

View File

@@ -8,6 +8,7 @@ import {
DanmakuUserInfo, DanmakuUserInfo,
EventDataTypes, EventDataTypes,
EventModel, EventModel,
FunctionTypes,
QueueSortType, QueueSortType,
SongRequestFrom, SongRequestFrom,
SongRequestInfo, SongRequestInfo,
@@ -392,10 +393,9 @@ export const useLiveRequest = defineStore('songRequest', () => {
} }
function checkMessage(msg: string) { function checkMessage(msg: string) {
if (accountInfo.value?.settings?.enableFunctions?.includes(6) != true) { if (accountInfo.value?.settings?.enableFunctions?.includes(FunctionTypes.LiveRequest) != true) {
return false return false
} }
const prefix = accountInfo.value?.settings?.songRequest?.orderPrefix || defaultPrefix.value const prefix = accountInfo.value?.settings?.songRequest?.orderPrefix || defaultPrefix.value
return msg.trim().toLowerCase().startsWith(prefix.toLowerCase()) return msg.trim().toLowerCase().startsWith(prefix.toLowerCase())
} }
@@ -424,6 +424,7 @@ export const useLiveRequest = defineStore('songRequest', () => {
} }
function onGetDanmaku(danmaku: EventModel) { function onGetDanmaku(danmaku: EventModel) {
console.log(checkMessage(danmaku.msg))
if (checkMessage(danmaku.msg)) { if (checkMessage(danmaku.msg)) {
addSong(danmaku) addSong(danmaku)
} }

View File

@@ -615,7 +615,12 @@ function parseExcelFile() {
* 解析多值字段(如作者、标签等) * 解析多值字段(如作者、标签等)
*/ */
function parseMultipleValues(value: string): string[] { function parseMultipleValues(value: string): string[] {
console.log(value)
if (!value) return [] if (!value) return []
// @ts-ignore
if (value instanceof Boolean) {
value = value.toString()
}
return value return value
?.replace('', '/') ?.replace('', '/')
.replace('', ',') .replace('', ',')

View File

@@ -142,7 +142,7 @@ onUnmounted(() => {
ref="listInnerRef" ref="listInnerRef"
class="live-request-list" class="live-request-list"
:class="{ animating: isMoreThanContainer }" :class="{ animating: isMoreThanContainer }"
:style="`width: ${width}px;`" :style="`width: ${width}px; --item-parent-width: ${width}px`"
> >
<div <div
v-for="(song, index) in activeSongs" v-for="(song, index) in activeSongs"
@@ -157,12 +157,15 @@ onUnmounted(() => {
> >
{{ index + 1 }} {{ index + 1 }}
</div> </div>
<div class="live-request-list-item-scroll-view">
<div class="live-request-list-item-inner-scroll">
<div class="live-request-list-item-song-name"> <div class="live-request-list-item-song-name">
{{ song.songName || '未知歌曲' }} {{ song.songName || '未知歌曲' }}
</div> </div>
<div <div
v-if="settings.showUserName" v-if="settings.showUserName"
class="live-request-list-item-name" class="live-request-list-item-name"
:from="song.from as number"
> >
{{ song.from == SongRequestFrom.Manual ? '主播添加' : song.user?.name || '未知用户' }} {{ song.from == SongRequestFrom.Manual ? '主播添加' : song.user?.name || '未知用户' }}
</div> </div>
@@ -175,6 +178,8 @@ onUnmounted(() => {
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
</template> </template>
<div <div
v-else v-else
@@ -420,55 +425,54 @@ onUnmounted(() => {
align-self: flex-start; align-self: flex-start;
position: relative; position: relative;
align-items: center; align-items: center;
justify-content: left;
gap: 5px;
padding: 4px 6px; padding: 4px 6px;
margin-bottom: 5px; margin-bottom: 5px;
background-color: rgba(0, 0, 0, 0.2); background-color: rgba(0, 0, 0, 0.2);
border-radius: 6px; border-radius: 6px;
min-height: 36px; min-height: 36px;
flex-wrap: wrap; overflow: hidden;
gap: 5px;
}
.live-request-list-item-scroll-view {
flex-grow: 1;
min-width: 0;
overflow: hidden;
position: relative;
}
.live-request-list-item-inner-scroll {
display: flex;
align-items: center;
gap: 5px;
width: max-content;
animation: item-horizontal-scroll 5s infinite alternate ease-in-out;
}
.live-request-list-item:hover .live-request-list-item-inner-scroll {
animation-play-state: paused;
}
@keyframes item-horizontal-scroll {
from {
transform: translateX(0px);
}
to {
transform: translateX(min(0px, calc(var(--item-parent-width) - 100% - 5px)));
}
} }
.live-request-list-item-song-name { .live-request-list-item-song-name {
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
max-width: 60%;
flex-grow: 1;
margin-right: 5px; margin-right: 5px;
} }
/* 只有在小屏幕/容器较窄时才允许换行 */
@media (max-width: 300px) {
.live-request-list-item-song-name {
white-space: normal;
max-width: 100%;
}
}
/* 手动添加 */
.live-request-list-item[from='0'] .live-request-list-item-name {
font-style: italic;
font-weight: bold;
color: #d2d8d6;
font-size: 12px;
}
.live-request-list-item[from='0'] .live-request-list-item-avatar {
display: none;
}
/* 弹幕点歌 */
.live-request-list-item[from='1'] {}
.live-request-list-item-name { .live-request-list-item-name {
font-style: italic; font-style: italic;
font-size: 12px; font-size: 12px;
color: rgba(204, 204, 204, 0.993); color: rgba(204, 204, 204, 0.993);
text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
margin-left: auto; margin-left: auto;
background-color: rgba(0, 0, 0, 0.2); background-color: rgba(0, 0, 0, 0.2);
@@ -487,6 +491,7 @@ onUnmounted(() => {
background-color: #0f0f0f48; background-color: #0f0f0f48;
color: rgba(204, 204, 204, 0.993); color: rgba(204, 204, 204, 0.993);
font-size: 12px; font-size: 12px;
flex-shrink: 0;
} }
.live-request-list-item-level { .live-request-list-item-level {
@@ -498,6 +503,7 @@ onUnmounted(() => {
background-color: rgba(0, 0, 0, 0.3); background-color: rgba(0, 0, 0, 0.3);
color: rgba(204, 204, 204, 0.993); color: rgba(204, 204, 204, 0.993);
font-size: 12px; font-size: 12px;
white-space: nowrap;
} }
.live-request-list-item-level[has-level='false'] { .live-request-list-item-level[has-level='false'] {

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { FunctionTypes } from '@/api/api-models'; import { FunctionTypes, Setting_LiveRequest } from '@/api/api-models';
import { useLiveRequest } from '@/composables/useLiveRequest'; import { useLiveRequest } from '@/composables/useLiveRequest';
import { SaveEnableFunctions, SaveSetting, useAccount } from '@/api/account' import { SaveEnableFunctions, SaveSetting, useAccount } from '@/api/account'
import { import {
@@ -15,7 +15,30 @@ import {
NSpin, NSpin,
useMessage useMessage
} from 'naive-ui'; } from 'naive-ui';
import { computed } from 'vue'; import { computed } from 'vue';
const defaultSettings = {
orderPrefix: '点播',
onlyAllowSongList: false,
queueMaxSize: 10,
allowAllDanmaku: true,
allowFromWeb: true,
needWearFanMedal: false,
needJianzhang: false,
needTidu: false,
needZongdu: false,
allowSC: true,
scIgnoreLimit: true,
scMinPrice: 30,
fanMedalMinLevel: 0,
allowReorderSong: false,
enableCooldown: false,
cooldownSecond: 1200,
zongduCooldownSecond: 300,
tiduCooldownSecond: 600,
jianzhangCooldownSecond: 900,
isReverse: false,
} as Setting_LiveRequest
// 使用useLiveRequest // 使用useLiveRequest
const liveRequest = useLiveRequest() const liveRequest = useLiveRequest()
@@ -30,6 +53,22 @@ const enableSongRequest = computed({
await updateEnableFunctions() await updateEnableFunctions()
} }
}) })
const configCanEdit = computed(() => {
return accountInfo.value != null && accountInfo.value != undefined
})
const settings = computed({
get: () => {
if (accountInfo.value.id) {
return accountInfo.value.settings.songRequest
}
return defaultSettings
},
set: (value) => {
if (accountInfo.value.id) {
accountInfo.value.settings.songRequest = value
}
},
})
// 控制歌曲请求功能开关 // 控制歌曲请求功能开关
async function updateEnableFunctions() { async function updateEnableFunctions() {
@@ -336,6 +375,45 @@ async function updateSettings() {
</NButton> </NButton>
</NInputGroup> </NInputGroup>
</NSpace> </NSpace>
<NDivider> OBS </NDivider>
<NSpace align="center">
<NInputGroup style="width: 220px">
<NInputGroupLabel> 标题 </NInputGroupLabel>
<template v-if="configCanEdit">
<NInput
v-model:value="settings.obsTitle"
placeholder="默认为 点播"
/>
<NButton
type="primary"
@click="updateSettings"
>
确定
</NButton>
</template>
</NInputGroup>
<NCheckbox
v-model:checked="settings.showRequireInfo"
:disabled="!configCanEdit"
@update:checked="updateSettings"
>
显示底部的需求信息
</NCheckbox>
<NCheckbox
v-model:checked="settings.showUserName"
:disabled="!configCanEdit"
@update:checked="updateSettings"
>
显示点播用户名
</NCheckbox>
<NCheckbox
v-model:checked="settings.showFanMadelInfo"
:disabled="!configCanEdit"
@update:checked="updateSettings"
>
显示点播用户粉丝牌
</NCheckbox>
</NSpace>
<NDivider> 警告消息 </NDivider> <NDivider> 警告消息 </NDivider>
<NSpace> <NSpace>
<NCheckbox <NCheckbox