mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-07 02:46:55 +08:00
update alert
This commit is contained in:
@@ -22,7 +22,9 @@ const accountInfo = useAccount()
|
|||||||
<NTag :type="accountInfo?.eventFetcherOnline ? (accountInfo?.eventFetcherStatus == 'ok' ? 'success' : 'warning') : 'error'">
|
<NTag :type="accountInfo?.eventFetcherOnline ? (accountInfo?.eventFetcherStatus == 'ok' ? 'success' : 'warning') : 'error'">
|
||||||
{{ accountInfo?.eventFetcherOnline ? (accountInfo?.eventFetcherStatus == 'ok' ? '正常' : `异常: ${accountInfo.eventFetcherStatus}`) : '未连接' }}
|
{{ accountInfo?.eventFetcherOnline ? (accountInfo?.eventFetcherStatus == 'ok' ? '正常' : `异常: ${accountInfo.eventFetcherStatus}`) : '未连接' }}
|
||||||
</NTag>
|
</NTag>
|
||||||
|
<template v-if="accountInfo?.eventFetcherOnline != true">
|
||||||
<NDivider vertical />
|
<NDivider vertical />
|
||||||
<NButton v-if="accountInfo?.eventFetcherOnline != true" type="info" size="small" tag="a" href="https://www.yuque.com/megghy/dez70g/vfvcyv3024xvaa1p" target="_blank"> 关于 EVENT-FETCHER </NButton>
|
<NButton type="info" size="small" tag="a" href="https://www.yuque.com/megghy/dez70g/vfvcyv3024xvaa1p" target="_blank"> 关于 EVENT-FETCHER </NButton>
|
||||||
|
</template>
|
||||||
</NAlert>
|
</NAlert>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -161,11 +161,11 @@ export default class DanmakuClient {
|
|||||||
sc: [],
|
sc: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Start(): Promise<boolean> {
|
public async Start(): Promise<{ success: boolean; message: string }> {
|
||||||
if (!this.client) {
|
if (!this.client) {
|
||||||
console.log('[OPEN-LIVE] 正在启动弹幕客户端')
|
console.log('[OPEN-LIVE] 正在启动弹幕客户端')
|
||||||
const result = await this.initClient()
|
const result = await this.initClient()
|
||||||
if (result) {
|
if (result.success) {
|
||||||
this.timer = setInterval(() => {
|
this.timer = setInterval(() => {
|
||||||
this.sendHeartbeat()
|
this.sendHeartbeat()
|
||||||
}, 20 * 1000)
|
}, 20 * 1000)
|
||||||
@@ -173,7 +173,10 @@ export default class DanmakuClient {
|
|||||||
return result
|
return result
|
||||||
} else {
|
} else {
|
||||||
console.warn('[OPEN-LIVE] 弹幕客户端已被启动过')
|
console.warn('[OPEN-LIVE] 弹幕客户端已被启动过')
|
||||||
return false
|
return {
|
||||||
|
success: false,
|
||||||
|
message: '弹幕客户端已被启动过',
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Stop() {
|
public Stop() {
|
||||||
@@ -194,7 +197,8 @@ export default class DanmakuClient {
|
|||||||
}
|
}
|
||||||
private sendHeartbeat() {
|
private sendHeartbeat() {
|
||||||
if (this.client) {
|
if (this.client) {
|
||||||
(this.authInfo ? QueryPostAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'heartbeat', this.authInfo) : QueryGetAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'heartbeat-internal')).then((data) => {
|
const query = this.authInfo ? QueryPostAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'heartbeat', this.authInfo) : QueryGetAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'heartbeat-internal')
|
||||||
|
query.then((data) => {
|
||||||
if (data.code != 200) {
|
if (data.code != 200) {
|
||||||
console.error('[OPEN-LIVE] 心跳失败: ' + data.message)
|
console.error('[OPEN-LIVE] 心跳失败: ' + data.message)
|
||||||
this.client.stop()
|
this.client.stop()
|
||||||
@@ -239,40 +243,56 @@ export default class DanmakuClient {
|
|||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
private async initClient() {
|
private async initClient(): Promise<{ success: boolean; message: string }> {
|
||||||
const auth = await this.getAuthInfo()
|
const auth = await this.getAuthInfo()
|
||||||
if (auth) {
|
if (auth.data) {
|
||||||
const chatClient = new ChatClientDirectOpenLive(auth)
|
const chatClient = new ChatClientDirectOpenLive(auth.data)
|
||||||
//chatClient.msgHandler = this;
|
//chatClient.msgHandler = this;
|
||||||
chatClient.CMD_CALLBACK_MAP = this.CMD_CALLBACK_MAP
|
chatClient.CMD_CALLBACK_MAP = this.CMD_CALLBACK_MAP
|
||||||
chatClient.start()
|
chatClient.start()
|
||||||
console.log('[OPEN-LIVE] 已连接房间: ' + auth.anchor_info.room_id)
|
this.roomAuthInfo.value = auth.data
|
||||||
this.roomAuthInfo.value = auth
|
|
||||||
this.client = chatClient
|
this.client = chatClient
|
||||||
return true
|
console.log('[OPEN-LIVE] 已连接房间: ' + auth.data.anchor_info.room_id)
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: '',
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('[OPEN-LIVE] 无法开启场次')
|
console.log('[OPEN-LIVE] 无法开启场次')
|
||||||
return false
|
return {
|
||||||
|
success: false,
|
||||||
|
message: auth.message,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async getAuthInfo() {
|
}
|
||||||
|
private async getAuthInfo(): Promise<{ data: OpenLiveInfo | null; message: string }> {
|
||||||
try {
|
try {
|
||||||
const data = await QueryPostAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'start', this.authInfo?.Code ? this.authInfo : undefined)
|
const data = await QueryPostAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'start', this.authInfo?.Code ? this.authInfo : undefined)
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
console.log('[OPEN-LIVE] 已获取场次信息')
|
console.log('[OPEN-LIVE] 已获取场次信息')
|
||||||
return data.data
|
return {
|
||||||
|
data: data.data,
|
||||||
|
message: '',
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error('无法获取场次数据: ' + data.message)
|
console.error('无法获取场次数据: ' + data.message)
|
||||||
return null
|
return {
|
||||||
|
data: null,
|
||||||
|
message: data.message,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: null,
|
||||||
|
message: err?.toString() || '未知错误',
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CMD_CALLBACK_MAP = {
|
private CMD_CALLBACK_MAP = {
|
||||||
LIVE_OPEN_PLATFORM_DM: this.onDanmaku,
|
LIVE_OPEN_PLATFORM_DM: this.onDanmaku.bind(this),
|
||||||
LIVE_OPEN_PLATFORM_SEND_GIFT: this.onGift,
|
LIVE_OPEN_PLATFORM_SEND_GIFT: this.onGift.bind(this),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
37
src/main.ts
37
src/main.ts
@@ -1,26 +1,33 @@
|
|||||||
import { QueryGetAPI } from '@/api/query'
|
import { QueryGetAPI } from '@/api/query'
|
||||||
import { BASE_API } from '@/data/constants'
|
import { BASE_API } from '@/data/constants'
|
||||||
import { createApp } from 'vue'
|
import { createApp, h } from 'vue'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import { GetSelfAccount } from './api/account'
|
import { GetSelfAccount } from './api/account'
|
||||||
import { GetNotifactions } from './data/notifactions'
|
import { GetNotifactions } from './data/notifactions'
|
||||||
|
import { NText, createDiscreteApi } from 'naive-ui'
|
||||||
let currentVersion
|
|
||||||
QueryGetAPI(BASE_API + 'vtsuru/version').then((version) => {
|
|
||||||
if (version.code == 200) {
|
|
||||||
currentVersion = version.data
|
|
||||||
const savedVersion = localStorage.getItem('Version')
|
|
||||||
|
|
||||||
if (currentVersion && savedVersion && savedVersion !== currentVersion) {
|
|
||||||
alert('发现新的版本更新, 请按 Ctrl+F5 强制刷新页面')
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem('Version', currentVersion)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
createApp(App).use(router).mount('#app')
|
createApp(App).use(router).mount('#app')
|
||||||
|
|
||||||
GetSelfAccount()
|
GetSelfAccount()
|
||||||
GetNotifactions()
|
GetNotifactions()
|
||||||
|
let currentVersion: string
|
||||||
|
const { notification } = createDiscreteApi(['notification'])
|
||||||
|
QueryGetAPI<string>(BASE_API + 'vtsuru/version').then((version) => {
|
||||||
|
if (version.code == 200) {
|
||||||
|
currentVersion = version.data
|
||||||
|
const savedVersion = localStorage.getItem('Version')
|
||||||
|
|
||||||
|
if (currentVersion && savedVersion && savedVersion !== currentVersion) {
|
||||||
|
//alert('发现新的版本更新, 请按 Ctrl+F5 强制刷新页面')
|
||||||
|
notification.info({
|
||||||
|
title: '发现新的版本更新',
|
||||||
|
content: '请按 Ctrl+F5 强制刷新页面',
|
||||||
|
duration: 5000,
|
||||||
|
meta: () => h(NText, { depth: 3 }, () => currentVersion),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage.setItem('Version', currentVersion)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|||||||
@@ -183,19 +183,21 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
{
|
{
|
||||||
path: 'live-lottery',
|
path: 'live-lottery',
|
||||||
name: 'manage-liveLottery',
|
name: 'manage-liveLottery',
|
||||||
component: () => import('@/views/manage/LiveLotteryManage.vue'),
|
component: () => import('@/views/open_live/OpenLottery.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '直播抽奖',
|
title: '直播抽奖',
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
|
danmaku: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'song-request',
|
path: 'song-request',
|
||||||
name: 'manage-songRequest',
|
name: 'manage-songRequest',
|
||||||
component: () => import('@/views/manage/SongRequestManage.vue'),
|
component: () => import('@/views/open_live/MusicRequest.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '弹幕点歌',
|
title: '弹幕点歌',
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
|
danmaku: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -18,26 +18,36 @@ import {
|
|||||||
NAlert,
|
NAlert,
|
||||||
NBackTop,
|
NBackTop,
|
||||||
NCountdown,
|
NCountdown,
|
||||||
|
NTooltip,
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
import { h, onMounted, ref } from 'vue'
|
import { h, onMounted, ref } from 'vue'
|
||||||
import { BrowsersOutline, Chatbox, Moon, MusicalNote, Sunny, AnalyticsSharp } from '@vicons/ionicons5'
|
import { BrowsersOutline, Chatbox, Moon, MusicalNote, Sunny, AnalyticsSharp } from '@vicons/ionicons5'
|
||||||
import { CalendarClock24Filled, Lottery24Filled, VehicleShip24Filled, VideoAdd20Filled } from '@vicons/fluent'
|
import { CalendarClock24Filled, Chat24Filled, Info24Filled, Lottery24Filled, VehicleShip24Filled, VideoAdd20Filled } from '@vicons/fluent'
|
||||||
import { isLoadingAccount, useAccount } from '@/api/account'
|
import { isLoadingAccount, useAccount } from '@/api/account'
|
||||||
import RegisterAndLogin from '@/components/RegisterAndLogin.vue'
|
import RegisterAndLogin from '@/components/RegisterAndLogin.vue'
|
||||||
import { RouterLink } from 'vue-router'
|
import { RouterLink, useRoute } from 'vue-router'
|
||||||
import { useElementSize, useStorage } from '@vueuse/core'
|
import { useElementSize, useStorage } from '@vueuse/core'
|
||||||
import { ACCOUNT_API_URL } from '@/data/constants'
|
import { ACCOUNT_API_URL } from '@/data/constants'
|
||||||
import { QueryGetAPI } from '@/api/query'
|
import { QueryGetAPI } from '@/api/query'
|
||||||
import { FunctionTypes, ThemeType } from '@/api/api-models'
|
import { FunctionTypes, ThemeType } from '@/api/api-models'
|
||||||
import { isDarkMode } from '@/Utils'
|
import { isDarkMode } from '@/Utils'
|
||||||
|
import DanmakuLayout from './manage/DanmakuLayout.vue'
|
||||||
|
import { computed } from '@vue/reactivity'
|
||||||
|
|
||||||
const accountInfo = useAccount()
|
const accountInfo = useAccount()
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
const windowWidth = window.innerWidth
|
const windowWidth = window.innerWidth
|
||||||
const sider = ref()
|
const sider = ref()
|
||||||
const { width } = useElementSize(sider)
|
const { width } = useElementSize(sider)
|
||||||
const themeType = useStorage('Settings.Theme', ThemeType.Auto)
|
const themeType = useStorage('Settings.Theme', ThemeType.Auto)
|
||||||
|
const type = computed(() => {
|
||||||
|
if (route.meta.danmaku) {
|
||||||
|
return 'danmaku'
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
})
|
||||||
|
|
||||||
const canResendEmail = ref(false)
|
const canResendEmail = ref(false)
|
||||||
|
|
||||||
@@ -151,6 +161,65 @@ const menuOptions = [
|
|||||||
icon: renderIcon(Lottery24Filled),
|
icon: renderIcon(Lottery24Filled),
|
||||||
//disabled: accountInfo.value?.isEmailVerified == false,
|
//disabled: accountInfo.value?.isEmailVerified == false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: () =>
|
||||||
|
h(NText, () => [
|
||||||
|
'弹幕相关',
|
||||||
|
h(
|
||||||
|
NTooltip,
|
||||||
|
{
|
||||||
|
style: 'padding: 0;',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
trigger: () => h(NIcon, { component: Info24Filled }),
|
||||||
|
default: () =>
|
||||||
|
h(
|
||||||
|
NAlert,
|
||||||
|
{
|
||||||
|
type: 'warning',
|
||||||
|
size: 'small',
|
||||||
|
title: '可用性警告',
|
||||||
|
style: 'max-width: 600px;',
|
||||||
|
},
|
||||||
|
() =>
|
||||||
|
h('div', {}, [
|
||||||
|
'当浏览器在后台运行时, 定时器和 Websocket 连接将受到严格限制, 这会导致弹幕接收功能无法正常工作 (详见',
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
text: true,
|
||||||
|
tag: 'a',
|
||||||
|
href: 'https://developer.chrome.com/blog/background_tabs/',
|
||||||
|
target: '_blank',
|
||||||
|
type: 'info',
|
||||||
|
},
|
||||||
|
'此文章'
|
||||||
|
),
|
||||||
|
'), 虽然本站已经针对此问题做出了处理, 一般情况下即使掉线了也会重连, 不过还是有可能会遗漏事件',
|
||||||
|
h('br'),
|
||||||
|
'为避免这种情况, 建议注册本站账后使用',
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
type: 'primary',
|
||||||
|
text: true,
|
||||||
|
size: 'small',
|
||||||
|
tag: 'a',
|
||||||
|
href: 'https://www.yuque.com/megghy/dez70g/vfvcyv3024xvaa1p',
|
||||||
|
target: '_blank',
|
||||||
|
},
|
||||||
|
'VtsuruEventFetcher'
|
||||||
|
),
|
||||||
|
', 否则请在使用功能时尽量保持网页在前台运行',
|
||||||
|
])
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
key: 'manage-danmaku',
|
||||||
|
icon: renderIcon(Chat24Filled),
|
||||||
|
//disabled: accountInfo.value?.isEmailVerified == false,
|
||||||
|
children: [
|
||||||
{
|
{
|
||||||
label: () =>
|
label: () =>
|
||||||
h(
|
h(
|
||||||
@@ -175,12 +244,14 @@ const menuOptions = [
|
|||||||
name: 'manage-songRequest',
|
name: 'manage-songRequest',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ default: () => '弹幕点歌' }
|
{ default: () => '点歌' }
|
||||||
),
|
),
|
||||||
key: 'manage-songRequest',
|
key: 'manage-songRequest',
|
||||||
icon: renderIcon(MusicalNote),
|
icon: renderIcon(MusicalNote),
|
||||||
//disabled: accountInfo.value?.isEmailVerified == false,
|
//disabled: accountInfo.value?.isEmailVerified == false,
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
async function resendEmail() {
|
async function resendEmail() {
|
||||||
@@ -226,7 +297,7 @@ onMounted(() => {
|
|||||||
<NIcon :component="Moon" />
|
<NIcon :component="Moon" />
|
||||||
</template>
|
</template>
|
||||||
</NSwitch>
|
</NSwitch>
|
||||||
<NButton size="small" style="right: 0px; position: relative" type="primary" @click="$router.push({ name: 'user-index', params: { id: accountInfo.name } })"> 回到主页 </NButton>
|
<NButton size="small" style="right: 0px; position: relative" type="primary" @click="$router.push({ name: 'user-index', params: { id: accountInfo?.name } })"> 回到主页 </NButton>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</template>
|
</template>
|
||||||
</NPageHeader>
|
</NPageHeader>
|
||||||
@@ -260,9 +331,10 @@ onMounted(() => {
|
|||||||
<NScrollbar style="height: calc(100vh - 50px)">
|
<NScrollbar style="height: calc(100vh - 50px)">
|
||||||
<NLayout>
|
<NLayout>
|
||||||
<div style="box-sizing: border-box; padding: 20px; min-width: 300px">
|
<div style="box-sizing: border-box; padding: 20px; min-width: 300px">
|
||||||
<RouterView v-slot="{ Component }" v-if="accountInfo?.isEmailVerified">
|
<RouterView v-if="accountInfo?.isEmailVerified" v-slot="{ Component, route }">
|
||||||
<KeepAlive>
|
<KeepAlive>
|
||||||
<Suspense>
|
<DanmakuLayout v-if="route.meta.danmaku" :component="Component" />
|
||||||
|
<Suspense v-else>
|
||||||
<component :is="Component" />
|
<component :is="Component" />
|
||||||
<template #fallback>
|
<template #fallback>
|
||||||
<NSpin show />
|
<NSpin show />
|
||||||
|
|||||||
@@ -80,12 +80,16 @@ const menuOptions = [
|
|||||||
function renderIcon(icon: unknown) {
|
function renderIcon(icon: unknown) {
|
||||||
return () => h(NIcon, null, { default: () => h(icon as any) })
|
return () => h(NIcon, null, { default: () => h(icon as any) })
|
||||||
}
|
}
|
||||||
|
const danmakuClientError = ref<string>()
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
authInfo.value = route.query as unknown as AuthInfo
|
authInfo.value = route.query as unknown as AuthInfo
|
||||||
if (authInfo.value?.Code) {
|
if (authInfo.value?.Code) {
|
||||||
client.value = new DanmakuClient(authInfo.value)
|
client.value = new DanmakuClient(authInfo.value)
|
||||||
await client.value.Start()
|
const result = await client.value.Start()
|
||||||
|
if (!result.success) {
|
||||||
|
message.error('无法启动弹幕客户端: ' + result.message)
|
||||||
|
danmakuClientError.value = result.message
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
message.error('你不是从幻星平台访问此页面, 或未提供对应参数, 无法使用此功能')
|
message.error('你不是从幻星平台访问此页面, 或未提供对应参数, 无法使用此功能')
|
||||||
}
|
}
|
||||||
@@ -159,6 +163,9 @@ onUnmounted(() => {
|
|||||||
</NSpace>
|
</NSpace>
|
||||||
</NLayoutSider>
|
</NLayoutSider>
|
||||||
<NLayoutContent style="height: 100%; padding: 10px" :native-scrollbar="false">
|
<NLayoutContent style="height: 100%; padding: 10px" :native-scrollbar="false">
|
||||||
|
<NAlert v-if="danmakuClientError" type="error" title="无法启动弹幕客户端">
|
||||||
|
{{ danmakuClientError }}
|
||||||
|
</NAlert>
|
||||||
<RouterView v-if="client?.roomAuthInfo.value" v-slot="{ Component }">
|
<RouterView v-if="client?.roomAuthInfo.value" v-slot="{ Component }">
|
||||||
<KeepAlive>
|
<KeepAlive>
|
||||||
<component :is="Component" :room-info="client?.roomAuthInfo" :client="client" :code="authInfo.Code" />
|
<component :is="Component" :room-info="client?.roomAuthInfo" :client="client" :code="authInfo.Code" />
|
||||||
|
|||||||
35
src/views/manage/DanmakuLayout.vue
Normal file
35
src/views/manage/DanmakuLayout.vue
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useAccount } from '@/api/account'
|
||||||
|
import DanmakuClient from '@/data/DanmakuClient'
|
||||||
|
import { NAlert, NSpin, useMessage } from 'naive-ui'
|
||||||
|
import { VNode, onMounted, onUnmounted, ref } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
component: VNode
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const accountInfo = useAccount()
|
||||||
|
const message = useMessage()
|
||||||
|
|
||||||
|
let client = new DanmakuClient(null)
|
||||||
|
const isClientLoading = ref(true)
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const result = await client.Start()
|
||||||
|
if (!result.success) {
|
||||||
|
message.error('无法启动弹幕客户端: ' + result.message)
|
||||||
|
}
|
||||||
|
isClientLoading.value = false
|
||||||
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
client.Stop()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NAlert v-if="accountInfo?.isBiliVerified != true" type="info"> 尚未进行Bilibili认证 </NAlert>
|
||||||
|
<NSpin v-else-if="isClientLoading" show />
|
||||||
|
<KeepAlive v-else>
|
||||||
|
<component :is="component" :client="client" :room-info="client.roomAuthInfo?.value" :code="accountInfo?.biliAuthCode"/>
|
||||||
|
</KeepAlive>
|
||||||
|
</template>
|
||||||
@@ -66,7 +66,7 @@ const lotteryHistory = useStorage<LotteryHistory[]>('LotteryHistory', [])
|
|||||||
|
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
const notification = useNotification()
|
const notification = useNotification()
|
||||||
const token = ref()
|
const token = ref('')
|
||||||
const turnstile = ref()
|
const turnstile = ref()
|
||||||
const defaultOption = {
|
const defaultOption = {
|
||||||
resultCount: 1,
|
resultCount: 1,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const accountInfo = useAccount()
|
|||||||
</template>
|
</template>
|
||||||
</NCard>
|
</NCard>
|
||||||
<NCard hoverable embedded size="small" title="弹幕点歌" style="width: 300px">
|
<NCard hoverable embedded size="small" title="弹幕点歌" style="width: 300px">
|
||||||
通过弹幕或者SC进行点歌, 注册后可以保存和导出 (开发中
|
通过弹幕或者SC进行点歌, 注册后可以保存和导出 (这个是歌势用的点歌, 不是拿来放歌的那种!)
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<NButton @click="$router.push({ name: 'open-live-song-request', query: $route.query })" type="primary"> 前往使用 </NButton>
|
<NButton @click="$router.push({ name: 'open-live-song-request', query: $route.query })" type="primary"> 前往使用 </NButton>
|
||||||
</template>
|
</template>
|
||||||
@@ -30,7 +30,7 @@ const accountInfo = useAccount()
|
|||||||
</NSpace>
|
</NSpace>
|
||||||
<br />
|
<br />
|
||||||
<NAlert v-if="accountInfo?.eventFetcherOnline != true" type="warning" title="可用性警告" style="max-width: 600px; margin: 0 auto">
|
<NAlert v-if="accountInfo?.eventFetcherOnline != true" type="warning" title="可用性警告" style="max-width: 600px; margin: 0 auto">
|
||||||
当浏览器在后台运行时定时器和 Websocket 连接将受到严格限制, 这会导致弹幕接收功能无法正常工作 (详见
|
当浏览器在后台运行时, 定时器和 Websocket 连接将受到严格限制, 这会导致弹幕接收功能无法正常工作 (详见
|
||||||
<NButton text tag="a" href="https://developer.chrome.com/blog/background_tabs/" target="_blank" type="info">此文章</NButton>), 虽然本站已经针对此问题做出了处理, 一般情况下即使掉线了也会重连,
|
<NButton text tag="a" href="https://developer.chrome.com/blog/background_tabs/" target="_blank" type="info">此文章</NButton>), 虽然本站已经针对此问题做出了处理, 一般情况下即使掉线了也会重连,
|
||||||
不过还是有可能会遗漏事件
|
不过还是有可能会遗漏事件
|
||||||
<br />
|
<br />
|
||||||
|
|||||||
@@ -317,10 +317,8 @@ onMounted(async () => {
|
|||||||
message.info('从历史记录中加载 ' + users.length + ' 位用户')
|
message.info('从历史记录中加载 ' + users.length + ' 位用户')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (props.client) {
|
props.client?.on('danmaku', onDanmaku)
|
||||||
props.client.on('danmaku', onDanmaku)
|
props.client?.on('gift', onGift)
|
||||||
props.client.on('gift', onGift)
|
|
||||||
}
|
|
||||||
timer = setInterval(updateUsers, 1000 * 10)
|
timer = setInterval(updateUsers, 1000 * 10)
|
||||||
})
|
})
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user