fix: no voice in speech page; custom personal page redirect notworking. feat: sync sroll bar between question display page an obs component

This commit is contained in:
2024-11-23 18:46:37 +08:00
parent 14267bab3a
commit 47ade4a965
33 changed files with 838 additions and 1119 deletions

View File

@@ -15,7 +15,7 @@ import {
import { QueryGetAPI, QueryPostAPI, QueryPostAPIWithParams } from '@/api/query'
import SongPlayer from '@/components/SongPlayer.vue'
import { RoomAuthInfo } from '@/data/DanmakuClient'
import { SONG_REQUEST_API_URL } from '@/data/constants'
import { CURRENT_HOST, SONG_REQUEST_API_URL } from '@/data/constants'
import { useDanmakuClient } from '@/store/useDanmakuClient'
import {
Checkmark12Regular,
@@ -633,24 +633,24 @@ const columns = [
() => [
data.status == SongRequestStatus.Finish || data.status == SongRequestStatus.Cancel
? h(NTooltip, null, {
trigger: () =>
h(
NButton,
{
size: 'small',
type: 'info',
circle: true,
loading: isLoading.value,
onClick: () => {
updateSongStatus(data, SongRequestStatus.Waiting)
},
trigger: () =>
h(
NButton,
{
size: 'small',
type: 'info',
circle: true,
loading: isLoading.value,
onClick: () => {
updateSongStatus(data, SongRequestStatus.Waiting)
},
{
icon: () => h(NIcon, { component: ReloadCircleSharp }),
},
),
default: () => '重新放回等待列表',
})
},
{
icon: () => h(NIcon, { component: ReloadCircleSharp }),
},
),
default: () => '重新放回等待列表',
})
: undefined,
h(
NPopconfirm,
@@ -731,7 +731,7 @@ async function updateActive() {
message.error('无法获取点播队列: ' + data.message)
return []
}
} catch (err) {}
} catch (err) { }
}
function blockUser(item: SongRequestInfo) {
if (item.from != SongRequestFrom.Danmaku) {
@@ -793,15 +793,11 @@ onUnmounted(() => {
</script>
<template>
<NAlert
:type="accountInfo.settings.enableFunctions.includes(FunctionTypes.SongRequest) ? 'success' : 'warning'"
v-if="accountInfo.id"
>
<NAlert :type="accountInfo.settings.enableFunctions.includes(FunctionTypes.SongRequest) ? 'success' : 'warning'"
v-if="accountInfo.id">
启用弹幕点播功能
<NSwitch
:value="accountInfo?.settings.enableFunctions.includes(FunctionTypes.SongRequest)"
@update:value="onUpdateFunctionEnable"
/>
<NSwitch :value="accountInfo?.settings.enableFunctions.includes(FunctionTypes.SongRequest)"
@update:value="onUpdateFunctionEnable" />
<br />
<NText depth="3">
@@ -812,11 +808,7 @@ onUnmounted(() => {
则其需要保持此页面开启才能点播, 也不要同时开多个页面, 会导致点播重复 !(部署了则不影响)
</NText>
</NAlert>
<NAlert
type="warning"
v-else
title="你尚未注册并登录 VTsuru.live, 大部分规则设置将不可用 (因为我懒得在前段重写一遍逻辑"
>
<NAlert type="warning" v-else title="你尚未注册并登录 VTsuru.live, 大部分规则设置将不可用 (因为我懒得在前段重写一遍逻辑">
<NButton tag="a" href="/manage" target="_blank" type="primary"> 前往登录或注册 </NButton>
</NAlert>
<br />
@@ -832,11 +824,8 @@ onUnmounted(() => {
</NCard>
<br />
<NCard>
<NTabs
v-if="!accountInfo || accountInfo.settings.enableFunctions.includes(FunctionTypes.SongRequest)"
animated
display-directive="show:lazy"
>
<NTabs v-if="!accountInfo || accountInfo.settings.enableFunctions.includes(FunctionTypes.SongRequest)" animated
display-directive="show:lazy">
<NTabPane name="list" tab="列表">
<NCard size="small">
<NSpace align="center">
@@ -861,12 +850,8 @@ onUnmounted(() => {
<NInput placeholder="手动添加" v-model:value="newSongName" />
<NButton type="primary" @click="addSongManual"> 添加 </NButton>
</NInputGroup>
<NRadioGroup
v-model:value="settings.sortType"
:disabled="!configCanEdit"
@update:value="updateSettings"
type="button"
>
<NRadioGroup v-model:value="settings.sortType" :disabled="!configCanEdit" @update:value="updateSettings"
type="button">
<NRadioButton :value="QueueSortType.TimeFirst"> 加入时间优先 </NRadioButton>
<NRadioButton :value="QueueSortType.PaymentFist"> 付费价格优先 </NRadioButton>
<NRadioButton :value="QueueSortType.GuardFirst"> 舰长优先 (按等级) </NRadioButton>
@@ -893,17 +878,13 @@ onUnmounted(() => {
</Transition>
<NList v-if="activeSongs.length > 0" :show-divider="false" hoverable>
<NListItem v-for="song in activeSongs" :key="song.id" style="padding: 5px">
<NCard
embedded
size="small"
content-style="padding: 5px;"
:style="`${song.status == SongRequestStatus.Singing ? 'animation: animated-border 2.5s infinite;' : ''};height: 100%;`"
>
<NCard embedded size="small" content-style="padding: 5px;"
:style="`${song.status == SongRequestStatus.Singing ? 'animation: animated-border 2.5s infinite;' : ''};height: 100%;`">
<NSpace justify="space-between" align="center" style="height: 100%; margin: 0 5px 0 5px">
<NSpace align="center">
<div
:style="`border-radius: 4px; background-color: ${song.status == SongRequestStatus.Singing ? '#75c37f' : '#577fb8'}; width: 10px; height: 20px`"
></div>
:style="`border-radius: 4px; background-color: ${song.status == SongRequestStatus.Singing ? '#75c37f' : '#577fb8'}; width: 10px; height: 20px`">
</div>
<NText strong style="font-size: 18px">
{{ song.songName }}
</NText>
@@ -922,12 +903,10 @@ onUnmounted(() => {
{{ song.user?.uid }}
</NTooltip>
</template>
<NSpace
v-if="
(song.from == SongRequestFrom.Danmaku || song.from == SongRequestFrom.SC) &&
song.user?.fans_medal_wearing_status
"
>
<NSpace v-if="
(song.from == SongRequestFrom.Danmaku || song.from == SongRequestFrom.SC) &&
song.user?.fans_medal_wearing_status
">
<NTag size="tiny" round>
<NTag size="tiny" round :bordered="false">
<NText depth="3">
@@ -939,26 +918,16 @@ onUnmounted(() => {
</span>
</NTag>
</NSpace>
<NTag
v-if="(song.user?.guard_level ?? 0) > 0"
size="small"
:bordered="false"
:color="{ textColor: 'white', color: GetGuardColor(song.user?.guard_level) }"
>
<NTag v-if="(song.user?.guard_level ?? 0) > 0" size="small" :bordered="false"
:color="{ textColor: 'white', color: GetGuardColor(song.user?.guard_level) }">
{{ song.user?.guard_level == 1 ? '总督' : song.user?.guard_level == 2 ? '提督' : '舰长' }}
</NTag>
<NTag
v-if="song.from == SongRequestFrom.SC"
size="small"
:color="{ textColor: 'white', color: GetSCColor(song.price ?? 0) }"
>
<NTag v-if="song.from == SongRequestFrom.SC" size="small"
:color="{ textColor: 'white', color: GetSCColor(song.price ?? 0) }">
SC | {{ song.price }}
</NTag>
<NTag
v-if="song.from == SongRequestFrom.Gift"
size="small"
:color="{ textColor: 'white', color: GetSCColor(song.price ?? 0) }"
>
<NTag v-if="song.from == SongRequestFrom.Gift" size="small"
:color="{ textColor: 'white', color: GetSCColor(song.price ?? 0) }">
Gift | {{ song.price }}
</NTag>
<NTooltip>
@@ -973,13 +942,8 @@ onUnmounted(() => {
<NSpace justify="end" align="center">
<NTooltip v-if="song.song">
<template #trigger>
<NButton
circle
type="success"
style="height: 30px; width: 30px"
:loading="isLrcLoading == song?.song?.key"
@click="selectedSong = song.song"
>
<NButton circle type="success" style="height: 30px; width: 30px"
:loading="isLrcLoading == song?.song?.key" @click="selectedSong = song.song">
<template #icon>
<NIcon :component="Play24Filled" />
</template>
@@ -989,25 +953,17 @@ onUnmounted(() => {
</NTooltip>
<NTooltip>
<template #trigger>
<NButton
circle
type="primary"
style="height: 30px; width: 30px"
:disabled="
songs.findIndex((s) => s.id != song.id && s.status == SongRequestStatus.Singing) > -1
"
@click="
<NButton circle type="primary" style="height: 30px; width: 30px" :disabled="songs.findIndex((s) => s.id != song.id && s.status == SongRequestStatus.Singing) > -1
" @click="
updateSongStatus(
song,
song.status == SongRequestStatus.Singing
? SongRequestStatus.Waiting
: SongRequestStatus.Singing,
)
"
"
:style="`animation: ${song.status == SongRequestStatus.Waiting ? '' : 'loading 5s linear infinite'}`"
:secondary="song.status == SongRequestStatus.Singing"
:loading="isLoading"
>
:secondary="song.status == SongRequestStatus.Singing" :loading="isLoading">
<template #icon>
<NIcon :component="Mic24Filled" />
</template>
@@ -1023,13 +979,8 @@ onUnmounted(() => {
</NTooltip>
<NTooltip>
<template #trigger>
<NButton
circle
type="success"
style="height: 30px; width: 30px"
:loading="isLoading"
@click="updateSongStatus(song, SongRequestStatus.Finish)"
>
<NButton circle type="success" style="height: 30px; width: 30px" :loading="isLoading"
@click="updateSongStatus(song, SongRequestStatus.Finish)">
<template #icon>
<NIcon :component="Checkmark12Regular" />
</template>
@@ -1054,13 +1005,8 @@ onUnmounted(() => {
</NTooltip>
<NTooltip>
<template #trigger>
<NButton
circle
type="error"
style="height: 30px; width: 30px"
:loading="isLoading"
@click="updateSongStatus(song, SongRequestStatus.Cancel)"
>
<NButton circle type="error" style="height: 30px; width: 30px" :loading="isLoading"
@click="updateSongStatus(song, SongRequestStatus.Cancel)">
<template #icon>
<NIcon :component="Dismiss16Filled" />
</template>
@@ -1096,20 +1042,14 @@ onUnmounted(() => {
</NInputGroup>
</NSpace>
</NCard>
<NDataTable
size="small"
ref="table"
:columns="columns"
:data="songs"
:pagination="{
itemCount: songs.length,
pageSizes: [20, 50, 100],
showSizePicker: true,
prefix({ itemCount }) {
return `共 ${itemCount} 条记录`
},
}"
/>
<NDataTable size="small" ref="table" :columns="columns" :data="songs" :pagination="{
itemCount: songs.length,
pageSizes: [20, 50, 100],
showSizePicker: true,
prefix({ itemCount }) {
return `共 ${itemCount} 条记录`
},
}" />
</NTabPane>
<NTabPane name="setting" tab="设置">
<NSpin :show="isLoading">
@@ -1132,26 +1072,17 @@ onUnmounted(() => {
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
</NInputGroup>
<NSpace align="center">
<NCheckbox
v-model:checked="settings.enableOnStreaming"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.enableOnStreaming" @update:checked="updateSettings"
:disabled="!configCanEdit">
仅在直播时才允许加入
</NCheckbox>
<NCheckbox
v-model:checked="settings.allowAllDanmaku"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.allowAllDanmaku" @update:checked="updateSettings"
:disabled="!configCanEdit">
允许所有弹幕点播
</NCheckbox>
<template v-if="!settings.allowAllDanmaku">
<NCheckbox
v-model:checked="settings.needWearFanMedal"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.needWearFanMedal" @update:checked="updateSettings"
:disabled="!configCanEdit">
需要拥有粉丝牌
</NCheckbox>
<NInputGroup v-if="settings.needWearFanMedal" style="width: 250px">
@@ -1159,28 +1090,16 @@ onUnmounted(() => {
<NInputNumber v-model:value="settings.fanMedalMinLevel" :disabled="!configCanEdit" />
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
</NInputGroup>
<NCheckbox
v-if="!settings.allowAllDanmaku"
v-model:checked="settings.needJianzhang"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-if="!settings.allowAllDanmaku" v-model:checked="settings.needJianzhang"
@update:checked="updateSettings" :disabled="!configCanEdit">
只允许舰长
</NCheckbox>
<NCheckbox
v-if="!settings.allowAllDanmaku"
v-model:checked="settings.needTidu"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-if="!settings.allowAllDanmaku" v-model:checked="settings.needTidu"
@update:checked="updateSettings" :disabled="!configCanEdit">
只允许提督
</NCheckbox>
<NCheckbox
v-if="!settings.allowAllDanmaku"
v-model:checked="settings.needZongdu"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-if="!settings.allowAllDanmaku" v-model:checked="settings.needZongdu"
@update:checked="updateSettings" :disabled="!configCanEdit">
只允许总督
</NCheckbox>
</template>
@@ -1190,11 +1109,8 @@ onUnmounted(() => {
允许通过 SuperChat 点播
</NCheckbox>
<span v-if="settings.allowSC">
<NCheckbox
v-model:checked="settings.allowSC"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.allowSC" @update:checked="updateSettings"
:disabled="!configCanEdit">
SC 点播无视限制
</NCheckbox>
<NTooltip>
@@ -1273,29 +1189,20 @@ onUnmounted(() => {
</NSpace> -->
<NDivider> 点歌 </NDivider>
<NSpace>
<NCheckbox
v-model:checked="settings.onlyAllowSongList"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.onlyAllowSongList" @update:checked="updateSettings"
:disabled="!configCanEdit">
仅允许点
<NButton text tag="a" href="/manage/song-list" target="_blank" type="info"> 歌单 </NButton>
内的歌曲
</NCheckbox>
<NCheckbox
v-model:checked="settings.allowFromWeb"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.allowFromWeb" @update:checked="updateSettings"
:disabled="!configCanEdit">
允许通过网页点歌
</NCheckbox>
</NSpace>
<NDivider> 冷却 (单位: 秒) </NDivider>
<NCheckbox
v-model:checked="settings.enableCooldown"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.enableCooldown" @update:checked="updateSettings"
:disabled="!configCanEdit">
启用点播冷却
</NCheckbox>
<NSpace v-if="settings.enableCooldown">
@@ -1329,25 +1236,16 @@ onUnmounted(() => {
<NButton @click="updateSettings" type="primary">确定</NButton>
</template>
</NInputGroup>
<NCheckbox
v-model:checked="settings.showRequireInfo"
:disabled="!configCanEdit"
@update:checked="updateSettings"
>
<NCheckbox v-model:checked="settings.showRequireInfo" :disabled="!configCanEdit"
@update:checked="updateSettings">
显示底部的需求信息
</NCheckbox>
<NCheckbox
v-model:checked="settings.showUserName"
:disabled="!configCanEdit"
@update:checked="updateSettings"
>
<NCheckbox v-model:checked="settings.showUserName" :disabled="!configCanEdit"
@update:checked="updateSettings">
显示点播用户名
</NCheckbox>
<NCheckbox
v-model:checked="settings.showFanMadelInfo"
:disabled="!configCanEdit"
@update:checked="updateSettings"
>
<NCheckbox v-model:checked="settings.showFanMadelInfo" :disabled="!configCanEdit"
@update:checked="updateSettings">
显示点播用户粉丝牌
</NCheckbox>
</NSpace>
@@ -1368,7 +1266,7 @@ onUnmounted(() => {
<LiveRequestOBS :id="accountInfo?.id" />
</div>
<br />
<NInput :value="'https://vtsuru.live/obs/live-request?id=' + accountInfo?.id" />
<NInput :value="`${CURRENT_HOST}obs/live-request?id=` + accountInfo?.id" />
<NDivider />
<NCollapse>
<NCollapseItem title="使用说明">
@@ -1385,15 +1283,18 @@ onUnmounted(() => {
<style>
@keyframes loading {
/*以百分比来规定改变发生的时间 也可以通过"from"和"to",等价于0% 和 100%*/
0% {
/*rotate(2D旋转) scale(放大或者缩小) translate(移动) skew(翻转)*/
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes animated-border {
0% {
box-shadow: 0 0 0px #589580;
@@ -1403,6 +1304,7 @@ onUnmounted(() => {
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0);
}
}
@keyframes animated-border-round {
0% {
box-shadow: 0 0 0px #589580;

View File

@@ -3,7 +3,7 @@ import { DownloadConfig, UploadConfig, useAccount } from '@/api/account'
import { DanmakuUserInfo, EventModel, SongFrom, SongsInfo } from '@/api/api-models'
import { QueryGetAPI, QueryPostAPI } from '@/api/query'
import { RoomAuthInfo } from '@/data/DanmakuClient'
import { MUSIC_REQUEST_API_URL, SONG_API_URL } from '@/data/constants'
import { CURRENT_HOST, MUSIC_REQUEST_API_URL, SONG_API_URL } from '@/data/constants'
import { useDanmakuClient } from '@/store/useDanmakuClient'
import { MusicRequestSettings, useMusicRequestProvider } from '@/store/useMusicRequest'
import { useStorage } from '@vueuse/core'
@@ -103,10 +103,10 @@ const neteaseSongListId = computed(() => {
return Number(match[1])
}
}
} catch (err) {}
} catch (err) { }
try {
return Number(neteaseIdInput.value)
} catch {}
} catch { }
return null
})
const neteaseSongs = ref<SongsInfo[]>([])
@@ -149,7 +149,7 @@ async function searchMusic(keyword: string) {
}
return undefined
}
function switchTo() {}
function switchTo() { }
async function getNeteaseSongList() {
isLoading.value = true
await QueryGetAPI<SongsInfo[]>(SONG_API_URL + 'get-netease-list', {
@@ -387,14 +387,9 @@ onUnmounted(() => {
</NSpace>
<NDivider />
<NSpace align="center">
<NButton
@click="listening ? stopListen() : startListen()"
:type="listening ? 'error' : 'primary'"
:style="{ animation: listening ? 'animated-border 2.5s infinite' : '' }"
data-umami-event="Use Music Request"
:data-umami-event-uid="accountInfo?.biliId"
size="large"
>
<NButton @click="listening ? stopListen() : startListen()" :type="listening ? 'error' : 'primary'"
:style="{ animation: listening ? 'animated-border 2.5s infinite' : '' }" data-umami-event="Use Music Request"
:data-umami-event-uid="accountInfo?.biliId" size="large">
{{ listening ? '停止监听' : '开始监听' }}
</NButton>
<NButton @click="showOBSModal = true" type="info" size="small"> OBS组件 </NButton>
@@ -420,12 +415,8 @@ onUnmounted(() => {
<NButton @click="musicRquestStore.playMusic(item.music)" type="primary" secondary size="small">
播放
</NButton>
<NButton
@click="musicRquestStore.waitingMusics.splice(musicRquestStore.waitingMusics.indexOf(item), 1)"
type="error"
secondary
size="small"
>
<NButton @click="musicRquestStore.waitingMusics.splice(musicRquestStore.waitingMusics.indexOf(item), 1)"
type="error" secondary size="small">
取消
</NButton>
<NButton @click="blockMusic(item.music)" type="warning" secondary size="small"> 拉黑 </NButton>
@@ -455,26 +446,18 @@ onUnmounted(() => {
<NInputGroupLabel> 点歌弹幕前缀 </NInputGroupLabel>
<NInput v-model:value="settings.orderPrefix" />
</NInputGroup>
<NCheckbox
:checked="settings.orderCooldown != undefined"
@update:checked="
(checked: boolean) => {
settings.orderCooldown = checked ? 300 : undefined
}
"
>
<NCheckbox :checked="settings.orderCooldown != undefined" @update:checked="(checked: boolean) => {
settings.orderCooldown = checked ? 300 : undefined
}
">
是否启用点歌冷却
</NCheckbox>
<NInputGroup v-if="settings.orderCooldown" style="width: 200px">
<NInputGroupLabel> 冷却时间 () </NInputGroupLabel>
<NInputNumber
v-model:value="settings.orderCooldown"
@update:value="
(value) => {
if (!value || value <= 0) settings.orderCooldown = undefined
}
"
/>
<NInputNumber v-model:value="settings.orderCooldown" @update:value="(value) => {
if (!value || value <= 0) settings.orderCooldown = undefined
}
" />
</NInputGroup>
</NSpace>
<NSpace>
@@ -488,13 +471,9 @@ onUnmounted(() => {
</template>
获取和修改输出设备需要打开麦克风权限
</NTooltip>
<NSelect
v-model:value="settings.deviceId"
:options="deviceList"
:fallback-option="() => ({ label: '未选择', value: '' })"
style="min-width: 200px"
@update:value="musicRquestStore.setSinkId"
/>
<NSelect v-model:value="settings.deviceId" :options="deviceList"
:fallback-option="() => ({ label: '未选择', value: '' })" style="min-width: 200px"
@update:value="musicRquestStore.setSinkId" />
</NSpace>
</NSpace>
</NTabPane>
@@ -532,12 +511,8 @@ onUnmounted(() => {
<NList>
<NListItem v-for="item in settings.blacklist" :key="item">
<NSpace align="center" style="width: 100%">
<NButton
@click="settings.blacklist.splice(settings.blacklist.indexOf(item), 1)"
type="error"
secondary
size="small"
>
<NButton @click="settings.blacklist.splice(settings.blacklist.indexOf(item), 1)" type="error" secondary
size="small">
删除
</NButton>
<NText> {{ item }} </NText>
@@ -548,14 +523,8 @@ onUnmounted(() => {
</NTabs>
<NDivider style="height: 100px" />
<NModal v-model:show="showNeteaseModal" preset="card" :title="`获取歌单`" style="max-width: 600px">
<NInput
clearable
style="width: 100%"
autosize
:status="neteaseSongListId ? 'success' : 'error'"
v-model:value="neteaseIdInput"
placeholder="直接输入歌单Id或者网页链接"
>
<NInput clearable style="width: 100%" autosize :status="neteaseSongListId ? 'success' : 'error'"
v-model:value="neteaseIdInput" placeholder="直接输入歌单Id或者网页链接">
<template #suffix>
<NTag v-if="neteaseSongListId" type="success" size="small"> 歌单Id: {{ neteaseSongListId }} </NTag>
</template>
@@ -566,13 +535,8 @@ onUnmounted(() => {
</NButton>
<template v-if="neteaseSongsOptions.length > 0">
<NDivider style="margin: 10px" />
<NTransfer
style="height: 500px"
ref="transfer"
v-model:value="selectedNeteaseSongs"
:options="neteaseSongsOptions"
source-filterable
/>
<NTransfer style="height: 500px" ref="transfer" v-model:value="selectedNeteaseSongs"
:options="neteaseSongsOptions" source-filterable />
<NDivider style="margin: 10px" />
<NButton type="primary" @click="addNeteaseSongs" :loading="isLoading">
添加到歌单 | {{ selectedNeteaseSongs.length }} 首
@@ -586,7 +550,7 @@ onUnmounted(() => {
<MusicRequestOBS :id="accountInfo?.id" />
</div>
<br />
<NInput :value="'https://vtsuru.live/obs/music-request?id=' + accountInfo?.id" />
<NInput :value="`${CURRENT_HOST}obs/music-request?id=` + accountInfo?.id" />
<NDivider />
<NCollapse>
<NCollapseItem title="使用说明">
@@ -606,6 +570,7 @@ onUnmounted(() => {
max-height: 300px;
overflow-y: auto;
}
@keyframes animated-border {
0% {
box-shadow: 0 0 0px #589580;

View File

@@ -3,7 +3,7 @@ import { useAccount } from '@/api/account'
import { OpenLiveLotteryType, OpenLiveLotteryUserInfo, UpdateLiveLotteryUsersModel } from '@/api/api-models'
import { QueryGetAPI, QueryPostAPI } from '@/api/query'
import { DanmakuInfo, GiftInfo, RoomAuthInfo } from '@/data/DanmakuClient'
import { LOTTERY_API_URL } from '@/data/constants'
import { CURRENT_HOST, LOTTERY_API_URL } from '@/data/constants'
import { useDanmakuClient } from '@/store/useDanmakuClient'
import { Delete24Filled, Info24Filled } from '@vicons/fluent'
import { useLocalStorage, useStorage } from '@vueuse/core'
@@ -108,7 +108,7 @@ async function getUsers() {
if (data.code == 200) {
return data.data
}
} catch (err) {}
} catch (err) { }
return null
}
function updateUsers() {
@@ -181,7 +181,7 @@ function startLottery() {
if (currentUsers.value.length > lotteryOption.value.resultCount) {
console.log(
`[${currentUsers.value.length}] 移除` +
currentUsers.value.splice(getRandomInt(currentUsers.value.length), 1)[0].name,
currentUsers.value.splice(getRandomInt(currentUsers.value.length), 1)[0].name,
)
setTimeout(() => {
removeSingleUser()
@@ -199,7 +199,7 @@ function startLottery() {
while (currentUsers.value.length > lotteryOption.value.resultCount) {
console.log(
`[${currentUsers.value.length}] 移除` +
currentUsers.value.splice(getRandomInt(currentUsers.value.length), 1)[0].name,
currentUsers.value.splice(getRandomInt(currentUsers.value.length), 1)[0].name,
)
}
onFinishLottery()
@@ -210,7 +210,7 @@ function startLottery() {
while (currentUsers.value.length > half) {
console.log(
`[${currentUsers.value.length}] 移除` +
currentUsers.value.splice(getRandomInt(currentUsers.value.length), 1)[0].name,
currentUsers.value.splice(getRandomInt(currentUsers.value.length), 1)[0].name,
)
}
}
@@ -342,12 +342,7 @@ onUnmounted(() => {
</script>
<template>
<NResult
v-if="!code && !accountInfo"
status="403"
title="403"
description="该页面只能从幻星平台访问或者注册用户使用"
/>
<NResult v-if="!code && !accountInfo" status="403" title="403" description="该页面只能从幻星平台访问或者注册用户使用" />
<template v-else>
<NCard>
<template #header>
@@ -391,13 +386,8 @@ onUnmounted(() => {
<NCollapseTransition>
<NInputGroup v-if="lotteryOption.needFanMedal" style="max-width: 200px">
<NInputGroupLabel> 最低粉丝牌等级 </NInputGroupLabel>
<NInputNumber
v-model:value="lotteryOption.fanCardLevel"
min="1"
max="50"
:default-value="1"
:disabled="isLottering || isStartLottery"
/>
<NInputNumber v-model:value="lotteryOption.fanCardLevel" min="1" max="50" :default-value="1"
:disabled="isLottering || isStartLottery" />
</NInputGroup>
</NCollapseTransition>
<template v-if="lotteryOption.type == 'danmaku'">
@@ -405,21 +395,14 @@ onUnmounted(() => {
<template #trigger>
<NInputGroup style="max-width: 250px">
<NInputGroupLabel> 弹幕内容 </NInputGroupLabel>
<NInput
:disabled="isStartLottery"
v-model:value="lotteryOption.danmakuKeyword"
placeholder="留空则任何弹幕都可以"
/>
<NInput :disabled="isStartLottery" v-model:value="lotteryOption.danmakuKeyword"
placeholder="留空则任何弹幕都可以" />
</NInputGroup>
</template>
符合规则的弹幕才会被添加到抽奖队列中
</NTooltip>
<NRadioGroup
v-model:value="lotteryOption.danmakuFilterType"
name="判定类型"
:disabled="isLottering"
size="small"
>
<NRadioGroup v-model:value="lotteryOption.danmakuFilterType" name="判定类型" :disabled="isLottering"
size="small">
<NRadioButton :disabled="isStartLottery" value="all"> 完全一致 </NRadioButton>
<NRadioButton :disabled="isStartLottery" value="contains"> 包含 </NRadioButton>
<NRadioButton :disabled="isStartLottery" value="regex"> 正则 </NRadioButton>
@@ -428,11 +411,8 @@ onUnmounted(() => {
<template v-else-if="lotteryOption.type == 'gift'">
<NInputGroup style="max-width: 250px">
<NInputGroupLabel> 最低价格 </NInputGroupLabel>
<NInputNumber
:disabled="isStartLottery"
v-model:value="lotteryOption.giftMinPrice"
placeholder="留空则不限制"
/>
<NInputNumber :disabled="isStartLottery" v-model:value="lotteryOption.giftMinPrice"
placeholder="留空则不限制" />
</NInputGroup>
<NInputGroup style="max-width: 200px">
<NInputGroupLabel> 礼物名称 </NInputGroupLabel>
@@ -467,12 +447,8 @@ onUnmounted(() => {
</NCard>
<NCard v-if="originUsers" size="small">
<NSpace justify="center" align="center">
<NButton
type="primary"
@click="continueLottery"
:loading="isStartLottery"
:disabled="isStartLottery || isLotteried || !client"
>
<NButton type="primary" @click="continueLottery" :loading="isStartLottery"
:disabled="isStartLottery || isLotteried || !client">
开始
</NButton>
<NButton type="warning" :disabled="!isStartLottery" @click="pause"> 停止 </NButton>
@@ -482,15 +458,9 @@ onUnmounted(() => {
<template v-if="isStartLottery"> 进行抽取前需要先停止 </template>
</NDivider>
<NSpace justify="center">
<NButton
type="primary"
secondary
@click="startLottery"
:loading="isLottering"
:disabled="isStartLottery || isLotteried"
data-umami-event="Open-Live Use Lottery"
:data-umami-event-uid="client?.authInfo?.anchor_info?.uid"
>
<NButton type="primary" secondary @click="startLottery" :loading="isLottering"
:disabled="isStartLottery || isLotteried" data-umami-event="Open-Live Use Lottery"
:data-umami-event-uid="client?.authInfo?.anchor_info?.uid">
进行抽取
</NButton>
<NButton type="info" secondary :disabled="isStartLottery || isLottering || !isLotteried" @click="reset">
@@ -503,15 +473,8 @@ onUnmounted(() => {
<NCard size="small" :title="item.name" style="height: 155px" embedded>
<template #header>
<NSpace align="center" vertical :size="5">
<NAvatar
round
lazy
borderd
:size="64"
:src="item.avatar + '@64w_64h'"
:img-props="{ referrerpolicy: 'no-referrer' }"
style="box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2)"
/>
<NAvatar round lazy borderd :size="64" :src="item.avatar + '@64w_64h'"
:img-props="{ referrerpolicy: 'no-referrer' }" style="box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2)" />
<NSpace v-if="item.fans_medal_wearing_status">
<NTag size="tiny" round>
<NTag size="tiny" round :bordered="false">
@@ -526,12 +489,8 @@ onUnmounted(() => {
{{ item.name }}
</NSpace>
<NButton
style="position: absolute; right: 5px; top: 5px; color: #753e3e"
@click="removeUser(item)"
size="small"
circle
>
<NButton style="position: absolute; right: 5px; top: 5px; color: #753e3e" @click="removeUser(item)"
size="small" circle>
<template #icon>
<NIcon :component="Delete24Filled" />
</template>
@@ -572,21 +531,15 @@ onUnmounted(() => {
</NScrollbar>
<NEmpty v-else description="暂无记录" />
</NModal>
<NModal
v-model:show="showOBSModal"
preset="card"
title="OBS 组件"
style="max-width: 90%; width: 800px; max-height: 90vh"
closable
content-style="overflow: auto"
>
<NModal v-model:show="showOBSModal" preset="card" title="OBS 组件"
style="max-width: 90%; width: 800px; max-height: 90vh" closable content-style="overflow: auto">
<NAlert title="这是什么? " type="info"> 将等待队列以及结果显示在OBS中 </NAlert>
<NDivider> 浏览 </NDivider>
<div style="height: 400px; width: 250px; position: relative; margin: 0 auto">
<LiveLotteryOBS :code="code" />
</div>
<br />
<NInput :value="'https://vtsuru.live/obs/live-lottery?code=' + code" />
<NInput :value="`${CURRENT_HOST}obs/live-lottery?code=` + code" />
<NDivider />
<NCollapse>
<NCollapseItem title="使用说明">

View File

@@ -15,7 +15,7 @@ import {
} from '@/api/api-models'
import { QueryGetAPI, QueryPostAPI, QueryPostAPIWithParams } from '@/api/query'
import { RoomAuthInfo } from '@/data/DanmakuClient'
import { QUEUE_API_URL } from '@/data/constants'
import { CURRENT_HOST, QUEUE_API_URL } from '@/data/constants'
import { useDanmakuClient } from '@/store/useDanmakuClient'
import {
Checkmark12Regular,
@@ -610,24 +610,24 @@ const columns = [
() => [
data.status == QueueStatus.Finish || data.status == QueueStatus.Cancel
? h(NTooltip, null, {
trigger: () =>
h(
NButton,
{
size: 'small',
type: 'info',
circle: true,
loading: isLoading.value,
onClick: () => {
updateStatus(data, QueueStatus.Waiting)
},
trigger: () =>
h(
NButton,
{
size: 'small',
type: 'info',
circle: true,
loading: isLoading.value,
onClick: () => {
updateStatus(data, QueueStatus.Waiting)
},
{
icon: () => h(NIcon, { component: ReloadCircleSharp }),
},
),
default: () => '重新放回等待列表',
})
},
{
icon: () => h(NIcon, { component: ReloadCircleSharp }),
},
),
default: () => '重新放回等待列表',
})
: undefined,
h(
NPopconfirm,
@@ -702,7 +702,7 @@ async function updateActive() {
message.error('无法获取队列: ' + data.message)
return []
}
} catch (err) {}
} catch (err) { }
}
function blockUser(item: ResponseQueueModel) {
if (item.from != QueueFrom.Danmaku) {
@@ -762,15 +762,11 @@ onUnmounted(() => {
</script>
<template>
<NAlert
:type="accountInfo.settings.enableFunctions.includes(FunctionTypes.Queue) ? 'success' : 'warning'"
v-if="accountInfo.id"
>
<NAlert :type="accountInfo.settings.enableFunctions.includes(FunctionTypes.Queue) ? 'success' : 'warning'"
v-if="accountInfo.id">
启用弹幕队列功能
<NSwitch
:value="accountInfo?.settings.enableFunctions.includes(FunctionTypes.Queue)"
@update:value="onUpdateFunctionEnable"
/>
<NSwitch :value="accountInfo?.settings.enableFunctions.includes(FunctionTypes.Queue)"
@update:value="onUpdateFunctionEnable" />
<br />
<NText depth="3">
@@ -781,11 +777,7 @@ onUnmounted(() => {
则其需要保持此页面开启才能使用, 也不要同时开多个页面, 会导致重复 !(部署了则不影响)
</NText>
</NAlert>
<NAlert
type="warning"
v-else
title="你尚未注册并登录 VTsuru.live, 大部分规则设置将不可用 (因为我懒得在前段重写一遍逻辑"
>
<NAlert type="warning" v-else title="你尚未注册并登录 VTsuru.live, 大部分规则设置将不可用 (因为我懒得在前段重写一遍逻辑">
<NButton tag="a" href="/manage" target="_blank" type="primary"> 前往登录或注册 </NButton>
</NAlert>
<br />
@@ -801,11 +793,8 @@ onUnmounted(() => {
</NCard>
<br />
<NCard>
<NTabs
v-if="!accountInfo || accountInfo.settings.enableFunctions.includes(FunctionTypes.Queue)"
animated
display-directive="show:lazy"
>
<NTabs v-if="!accountInfo || accountInfo.settings.enableFunctions.includes(FunctionTypes.Queue)" animated
display-directive="show:lazy">
<NTabPane name="list" tab="列表">
<NCard size="small">
<NSpace align="center">
@@ -833,12 +822,8 @@ onUnmounted(() => {
</template>
确定全部取消吗?
</NPopconfirm>
<NRadioGroup
v-model:value="settings.sortType"
:disabled="!configCanEdit"
@update:value="updateSettings"
type="button"
>
<NRadioGroup v-model:value="settings.sortType" :disabled="!configCanEdit" @update:value="updateSettings"
type="button">
<NRadioButton :value="QueueSortType.TimeFirst"> 加入时间优先 </NRadioButton>
<NRadioButton :value="QueueSortType.PaymentFist"> 付费价格优先 </NRadioButton>
<NRadioButton :value="QueueSortType.GuardFirst"> 舰长优先 (按等级) </NRadioButton>
@@ -853,17 +838,12 @@ onUnmounted(() => {
<NDivider> {{ queue.length }} </NDivider>
<NList v-if="queue.length > 0" :show-divider="false" hoverable>
<NListItem v-for="(queueData, index) in queue" :key="queueData.id" style="padding: 5px">
<NCard
embedded
size="small"
content-style="padding: 5px;"
:style="`${queueData.status == QueueStatus.Progressing ? 'animation: animated-border 2.5s infinite;' : ''};height: 100%;`"
>
<NCard embedded size="small" content-style="padding: 5px;"
:style="`${queueData.status == QueueStatus.Progressing ? 'animation: animated-border 2.5s infinite;' : ''};height: 100%;`">
<NSpace justify="space-between" align="center" style="height: 100%; margin: 0 5px 0 5px">
<NSpace align="center">
<div
:style="`border-radius: 4px; background-color: ${queueData.status == QueueStatus.Progressing ? '#75c37f' : '#577fb8'}; width: 20px; height: 20px;text-align: center;color: white;`"
>
:style="`border-radius: 4px; background-color: ${queueData.status == QueueStatus.Progressing ? '#75c37f' : '#577fb8'}; width: 20px; height: 20px;text-align: center;color: white;`">
{{ index + 1 }}
</div>
<NText strong style="font-size: 18px">
@@ -877,12 +857,10 @@ onUnmounted(() => {
<template v-if="queueData.from == QueueFrom.Manual">
<NTag size="small" :bordered="false"> 手动添加 </NTag>
</template>
<NSpace
v-if="
(queueData.from == QueueFrom.Danmaku || queueData.from == QueueFrom.Gift) &&
queueData.user?.fans_medal_wearing_status
"
>
<NSpace v-if="
(queueData.from == QueueFrom.Danmaku || queueData.from == QueueFrom.Gift) &&
queueData.user?.fans_medal_wearing_status
">
<NTag size="tiny" round>
<NTag size="tiny" round :bordered="false">
<NText depth="3">
@@ -894,12 +872,8 @@ onUnmounted(() => {
</span>
</NTag>
</NSpace>
<NTag
v-if="(queueData.user?.guard_level ?? 0) > 0"
size="small"
:bordered="false"
:color="{ textColor: 'white', color: GetGuardColor(queueData.user?.guard_level) }"
>
<NTag v-if="(queueData.user?.guard_level ?? 0) > 0" size="small" :bordered="false"
:color="{ textColor: 'white', color: GetGuardColor(queueData.user?.guard_level) }">
{{ queueData.user?.guard_level == 1 ? '总督' : queueData.user?.guard_level == 2 ? '提督' : '舰长' }}
</NTag>
<NTag v-if="(queueData.giftPrice ?? 0) > 0" size="small" :bordered="false" type="error">
@@ -933,23 +907,15 @@ onUnmounted(() => {
<NSpace justify="end" align="center">
<NTooltip>
<template #trigger>
<NButton
circle
type="primary"
style="height: 30px; width: 30px"
:disabled="
queue.findIndex((s) => s.id != queueData.id && s.status == QueueStatus.Progressing) > -1
"
@click="
<NButton circle type="primary" style="height: 30px; width: 30px" :disabled="queue.findIndex((s) => s.id != queueData.id && s.status == QueueStatus.Progressing) > -1
" @click="
updateStatus(
queueData,
queueData.status == QueueStatus.Progressing ? QueueStatus.Waiting : QueueStatus.Progressing,
)
"
"
:style="`animation: ${queueData.status == QueueStatus.Waiting ? '' : 'loading 5s linear infinite'}`"
:secondary="queueData.status == QueueStatus.Progressing"
:loading="isLoading"
>
:secondary="queueData.status == QueueStatus.Progressing" :loading="isLoading">
<template #icon>
<NIcon :component="ClipboardTextLtr24Filled" />
</template>
@@ -965,13 +931,8 @@ onUnmounted(() => {
</NTooltip>
<NTooltip>
<template #trigger>
<NButton
circle
type="success"
style="height: 30px; width: 30px"
:loading="isLoading"
@click="updateStatus(queueData, QueueStatus.Finish)"
>
<NButton circle type="success" style="height: 30px; width: 30px" :loading="isLoading"
@click="updateStatus(queueData, QueueStatus.Finish)">
<template #icon>
<NIcon :component="Checkmark12Regular" />
</template>
@@ -996,13 +957,8 @@ onUnmounted(() => {
</NTooltip>
<NTooltip>
<template #trigger>
<NButton
circle
type="error"
style="height: 30px; width: 30px"
:loading="isLoading"
@click="updateStatus(queueData, QueueStatus.Cancel)"
>
<NButton circle type="error" style="height: 30px; width: 30px" :loading="isLoading"
@click="updateStatus(queueData, QueueStatus.Cancel)">
<template #icon>
<NIcon :component="Dismiss16Filled" />
</template>
@@ -1030,20 +986,14 @@ onUnmounted(() => {
</NInputGroup>
</NSpace>
</NCard>
<NDataTable
size="small"
ref="table"
:columns="columns"
:data="originQueue"
:pagination="{
itemCount: originQueue.length,
pageSizes: [20, 50, 100],
showSizePicker: true,
prefix({ itemCount }) {
return `共 ${itemCount} 条记录`
},
}"
/>
<NDataTable size="small" ref="table" :columns="columns" :data="originQueue" :pagination="{
itemCount: originQueue.length,
pageSizes: [20, 50, 100],
showSizePicker: true,
prefix({ itemCount }) {
return `共 ${itemCount} 条记录`
},
}" />
</NTabPane>
<NTabPane name="setting" tab="设置">
<NSpin :show="isLoading">
@@ -1058,12 +1008,8 @@ onUnmounted(() => {
</template>
<NInput v-else v-model:value="defaultKeyword" />
</NInputGroup>
<NRadioGroup
v-model:value="settings.matchType"
:disabled="!configCanEdit"
@update:value="updateSettings"
type="button"
>
<NRadioGroup v-model:value="settings.matchType" :disabled="!configCanEdit" @update:value="updateSettings"
type="button">
<NRadioButton :value="KeywordMatchType.Full"> 完全一致 </NRadioButton>
<NRadioButton :value="KeywordMatchType.Contains"> 包含 </NRadioButton>
<NRadioButton :value="KeywordMatchType.Regex"> 正则 </NRadioButton>
@@ -1075,18 +1021,12 @@ onUnmounted(() => {
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
</NInputGroup>
<NSpace align="center">
<NCheckbox
v-model:checked="settings.enableOnStreaming"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.enableOnStreaming" @update:checked="updateSettings"
:disabled="!configCanEdit">
仅在直播时才允许加入
</NCheckbox>
<NCheckbox
v-model:checked="settings.allowAllDanmaku"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.allowAllDanmaku" @update:checked="updateSettings"
:disabled="!configCanEdit">
允许所有用户加入
</NCheckbox>
<template v-if="!settings.allowAllDanmaku">
@@ -1095,38 +1035,23 @@ onUnmounted(() => {
<NInputNumber v-model:value="settings.fanMedalMinLevel" :disabled="!configCanEdit" min="0" />
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
</NInputGroup>
<NCheckbox
v-if="!settings.allowAllDanmaku"
v-model:checked="settings.needJianzhang"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-if="!settings.allowAllDanmaku" v-model:checked="settings.needJianzhang"
@update:checked="updateSettings" :disabled="!configCanEdit">
允许舰长
</NCheckbox>
<NCheckbox
v-if="!settings.allowAllDanmaku"
v-model:checked="settings.needTidu"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-if="!settings.allowAllDanmaku" v-model:checked="settings.needTidu"
@update:checked="updateSettings" :disabled="!configCanEdit">
允许提督
</NCheckbox>
<NCheckbox
v-if="!settings.allowAllDanmaku"
v-model:checked="settings.needZongdu"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-if="!settings.allowAllDanmaku" v-model:checked="settings.needZongdu"
@update:checked="updateSettings" :disabled="!configCanEdit">
允许总督
</NCheckbox>
</template>
</NSpace>
<NSpace align="center">
<NCheckbox
v-model:checked="settings.allowGift"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.allowGift" @update:checked="updateSettings"
:disabled="!configCanEdit">
允许通过发送礼物加入队列
</NCheckbox>
<template v-if="settings.allowGift">
@@ -1137,34 +1062,19 @@ onUnmounted(() => {
</NInputGroup>
<NSpace align="center">
礼物名
<NSelect
style="width: 250px"
v-model:value="settings.giftNames"
:disabled="!configCanEdit"
filterable
multiple
tag
placeholder="礼物名称,按回车确认"
:show-arrow="false"
:show="false"
@update:value="updateSettings"
/>
<NSelect style="width: 250px" v-model:value="settings.giftNames" :disabled="!configCanEdit" filterable
multiple tag placeholder="礼物名称,按回车确认" :show-arrow="false" :show="false"
@update:value="updateSettings" />
</NSpace>
<span>
<NRadioGroup
v-model:value="settings.giftFilterType"
:disabled="!configCanEdit"
@update:value="updateSettings"
>
<NRadioGroup v-model:value="settings.giftFilterType" :disabled="!configCanEdit"
@update:value="updateSettings">
<NRadioButton :value="QueueGiftFilterType.And"> 需同时满足礼物名和价格 </NRadioButton>
<NRadioButton :value="QueueGiftFilterType.Or"> 礼物名/价格 二选一 </NRadioButton>
</NRadioGroup>
</span>
<NCheckbox
v-model:checked="settings.sendGiftDirectJoin"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.sendGiftDirectJoin" @update:checked="updateSettings"
:disabled="!configCanEdit">
赠送礼物后自动加入队列
<NTooltip>
<template #trigger>
@@ -1174,36 +1084,24 @@ onUnmounted(() => {
</NTooltip>
</NCheckbox>
<NCheckbox
v-model:checked="settings.sendGiftIgnoreLimit"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.sendGiftIgnoreLimit" @update:checked="updateSettings"
:disabled="!configCanEdit">
赠送礼物后无视用户等级限制
</NCheckbox>
</template>
<NCheckbox
v-model:checked="settings.allowIncreasePaymentBySendGift"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.allowIncreasePaymentBySendGift" @update:checked="updateSettings"
:disabled="!configCanEdit">
在队列中时允许继续发送礼物累计付费量 (仅限上方设定的礼物)
</NCheckbox>
<NCheckbox
v-if="settings.allowIncreasePaymentBySendGift"
v-model:checked="settings.allowIncreaseByAnyPayment"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-if="settings.allowIncreasePaymentBySendGift"
v-model:checked="settings.allowIncreaseByAnyPayment" @update:checked="updateSettings"
:disabled="!configCanEdit">
允许发送任意礼物来叠加付费量
</NCheckbox>
</NSpace>
<NDivider> 冷却 (单位: 秒) </NDivider>
<NCheckbox
v-model:checked="settings.enableCooldown"
@update:checked="updateSettings"
:disabled="!configCanEdit"
>
<NCheckbox v-model:checked="settings.enableCooldown" @update:checked="updateSettings"
:disabled="!configCanEdit">
启用排队冷却
</NCheckbox>
<NSpace v-if="settings.enableCooldown">
@@ -1229,25 +1127,16 @@ onUnmounted(() => {
</NInputGroup>
</NSpace>
<NDivider> OBS </NDivider>
<NCheckbox
v-model:checked="settings.showRequireInfo"
:disabled="!configCanEdit"
@update:checked="updateSettings"
>
<NCheckbox v-model:checked="settings.showRequireInfo" :disabled="!configCanEdit"
@update:checked="updateSettings">
显示底部的需求信息
</NCheckbox>
<NCheckbox
v-model:checked="settings.showPayment"
:disabled="!configCanEdit"
@update:checked="updateSettings"
>
<NCheckbox v-model:checked="settings.showPayment" :disabled="!configCanEdit"
@update:checked="updateSettings">
显示付费信息
</NCheckbox>
<NCheckbox
v-model:checked="settings.showFanMadelInfo"
:disabled="!configCanEdit"
@update:checked="updateSettings"
>
<NCheckbox v-model:checked="settings.showFanMadelInfo" :disabled="!configCanEdit"
@update:checked="updateSettings">
显示用户粉丝牌
</NCheckbox>
<NDivider> 其他 </NDivider>
@@ -1267,7 +1156,7 @@ onUnmounted(() => {
<QueueOBS :id="accountInfo?.id" />
</div>
<br />
<NInput :value="'https://vtsuru.live/obs/queue?id=' + accountInfo?.id" />
<NInput :value="`${CURRENT_HOST}obs/queue?id=` + accountInfo?.id" />
<NDivider />
<NCollapse>
<NCollapseItem title="使用说明">
@@ -1284,15 +1173,18 @@ onUnmounted(() => {
<style>
@keyframes loading {
/*以百分比来规定改变发生的时间 也可以通过"from"和"to",等价于0% 和 100%*/
0% {
/*rotate(2D旋转) scale(放大或者缩小) translate(移动) skew(翻转)*/
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes animated-border {
0% {
box-shadow: 0 0 0px #589580;
@@ -1302,6 +1194,7 @@ onUnmounted(() => {
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0);
}
}
@keyframes animated-border-round {
0% {
box-shadow: 0 0 0px #589580;

View File

@@ -111,8 +111,6 @@ const speechSynthesisInfo = ref<{
}>()
const languageDisplayName = new Intl.DisplayNames(['zh'], { type: 'language' })
const voiceOptions = computed(() => {
const status = EasySpeech.status()
if (status.status != 'init: complete') return []
return new List(EasySpeech.voices())
.Select((v) => {
return {