mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-06 18:36:55 +08:00
feat: 更新直播请求相关组件和功能
- 在useLiveRequest.ts中使用FunctionTypes替代硬编码的功能标识 - 在SongListManageView.vue中添加调试信息输出 - 在ClassicRequestOBS.vue中优化歌曲请求列表的样式和动画效果 - 在SongRequestSettings.vue中新增OBS相关设置项,支持动态配置
This commit is contained in:
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(',', ',')
|
||||||
|
|||||||
@@ -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'] {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user