fix hub load

This commit is contained in:
2024-11-21 02:21:28 +08:00
parent 537ea7bbe6
commit a59a6f54e5
10 changed files with 66 additions and 26 deletions

2
default.d.ts vendored
View File

@@ -1,4 +1,5 @@
import { LoadingBarProviderInst, MessageProviderInst } from "naive-ui" import { LoadingBarProviderInst, MessageProviderInst } from "naive-ui"
import { useRoute } from "vue-router"
declare module 'vue3-aplayer' { declare module 'vue3-aplayer' {
const content: any const content: any
@@ -17,5 +18,6 @@ declare global {
interface Window { interface Window {
$message: MessageProviderInst, $message: MessageProviderInst,
$loadingBar: LoadingBarProviderInst $loadingBar: LoadingBarProviderInst
$route: ReturnType<typeof useRoute>
} }
} }

View File

@@ -182,7 +182,19 @@ export function downloadConfigDirect(name: string) {
name: name name: name
}) })
} }
export async function DownloadConfig<T>(name: string) { export type ConfigStatus = 'success' | 'error' | 'notfound'
export async function DownloadConfig<T>(name: string): Promise<
| {
msg: undefined
status: ConfigStatus
data: T
}
| {
msg: string
status: ConfigStatus
data: undefined
}
> {
try { try {
const resp = await QueryGetAPI<string>(VTSURU_API_URL + 'get-config', { const resp = await QueryGetAPI<string>(VTSURU_API_URL + 'get-config', {
name: name name: name
@@ -191,18 +203,21 @@ export async function DownloadConfig<T>(name: string) {
console.log('已获取配置文件: ' + name) console.log('已获取配置文件: ' + name)
return { return {
msg: undefined, msg: undefined,
status: 'success',
data: JSON.parse(resp.data) as T data: JSON.parse(resp.data) as T
} }
} else if (resp.code == 404) { } else if (resp.code == 404) {
console.error(`未找到名为 ${name} 的配置文件`) console.error(`未找到名为 ${name} 的配置文件`)
return { return {
msg: `未找到名为 ${name} 的配置文件, 需要先上传`, msg: `未找到名为 ${name} 的配置文件, 需要先上传`,
status: 'notfound',
data: undefined data: undefined
} }
} else { } else {
console.error(`无法获取配置文件 [${name}]: ` + resp.message) console.error(`无法获取配置文件 [${name}]: ` + resp.message)
return { return {
msg: `无法获取配置文件 [${name}]: ` + resp.message, msg: `无法获取配置文件 [${name}]: ` + resp.message,
status: 'error',
data: undefined data: undefined
} }
} }
@@ -210,6 +225,7 @@ export async function DownloadConfig<T>(name: string) {
console.error(`无法获取配置文件 [${name}]: ` + err) console.error(`无法获取配置文件 [${name}]: ` + err)
return { return {
msg: `无法获取配置文件 [${name}]: ` + err, msg: `无法获取配置文件 [${name}]: ` + err,
status: 'error',
data: undefined data: undefined
} }
} }

View File

@@ -1,19 +1,27 @@
<script setup lang="ts"> <script setup lang="ts">
import { useAccount } from '@/api/account';
import { useLoadingBarStore } from '@/store/useLoadingBarStore' import { useLoadingBarStore } from '@/store/useLoadingBarStore'
import { useLoadingBar, useMessage } from 'naive-ui' import { useStorage } from '@vueuse/core';
import { NSpin, useLoadingBar, useMessage } from 'naive-ui'
import { onMounted } from 'vue' import { onMounted } from 'vue'
import { useRoute } from 'vue-router';
const cookie = useStorage('JWT_Token', '')
const accountInfo = useAccount()
// Setup code // Setup code
onMounted(() => { onMounted(() => {
window.$loadingBar = useLoadingBar() window.$loadingBar = useLoadingBar()
window.$message = useMessage() window.$message = useMessage()
window.$route = useRoute()
const providerStore = useLoadingBarStore() const providerStore = useLoadingBarStore()
providerStore.setLoadingBar(window.$loadingBar) providerStore.setLoadingBar(window.$loadingBar)
}) })
</script> </script>
<template> <template>
<div style="height: 100vh"> <NSpin v-if="($route.query.token || cookie) && accountInfo.id < 1" style="margin: 0 auto;" />
<div v-else style="height: 100vh">
<slot></slot> <slot></slot>
</div> </div>
</template> </template>

View File

@@ -99,11 +99,14 @@ abstract class BaseRTCClient {
} }
public processData(conn: DataConnection, data: RTCData) { public processData(conn: DataConnection, data: RTCData) {
//console.log(data) //console.log(data)
if (data.Key == 'Heartbeat') { // 心跳 if (data.Key == 'Heartbeat') {
// 心跳
return return
} else if (data.Key == 'VTsuru.RTCEvent.On') { // 添加事件 } else if (data.Key == 'VTsuru.RTCEvent.On') {
// 添加事件
this.handledEvents[conn.peer].push(data.Data) this.handledEvents[conn.peer].push(data.Data)
} else if (data.Key == 'VTsuru.RTCEvent.Off') { // 移除事件 } else if (data.Key == 'VTsuru.RTCEvent.Off') {
// 移除事件
const i = this.handledEvents[conn.peer].indexOf(data.Data) const i = this.handledEvents[conn.peer].indexOf(data.Data)
if (i > -1) { if (i > -1) {
this.handledEvents[conn.peer].splice(i, 1) this.handledEvents[conn.peer].splice(i, 1)
@@ -127,12 +130,14 @@ abstract class BaseRTCClient {
) )
} }
public Init() { public async Init() {
if (!this.isInited) { if (!this.isInited) {
this.isInited = true this.isInited = true
await this.vhub.on('RTCOffline', (id: string) =>
this.onConnectionClose(id)
)
this.connectRTC() this.connectRTC()
} }
this.vhub.on('RTCOffline', (id: string) => this.onConnectionClose(id))
return this return this
} }
} }
@@ -170,8 +175,8 @@ export class SlaveRTCClient extends BaseRTCClient {
c?.on('data', (data) => this.processData(c, data as RTCData)) c?.on('data', (data) => this.processData(c, data as RTCData))
c?.on('close', () => this.onConnectionClose(c.peer)) c?.on('close', () => this.onConnectionClose(c.peer))
} }
public Init() { public async Init() {
super.Init() await super.Init()
this.vhub?.on('MasterOnline', (data: string) => this.connectToMaster(data)) this.vhub?.on('MasterOnline', (data: string) => this.connectToMaster(data))
setTimeout(() => { setTimeout(() => {
this.connectToAllMaster() this.connectToAllMaster()

View File

@@ -101,7 +101,6 @@ QueryGetAPI<string>(BASE_API_URL + 'vtsuru/version')
//加载其他数据 //加载其他数据
await GetSelfAccount() await GetSelfAccount()
const account = useAccount() const account = useAccount()
const vhub = useVTsuruHub().Init(account.value.token)
const useAuth = useAuthStore() const useAuth = useAuthStore()
if (account.value.id) { if (account.value.id) {
if (account.value.biliUserAuthInfo && !useAuth.currentToken) { if (account.value.biliUserAuthInfo && !useAuth.currentToken) {

View File

@@ -1,3 +1,4 @@
import { useAccount } from '@/api/account'
import DanmakuClient, { AuthInfo, RoomAuthInfo } from '@/data/DanmakuClient' import DanmakuClient, { AuthInfo, RoomAuthInfo } from '@/data/DanmakuClient'
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
@@ -18,6 +19,7 @@ export const useDanmakuClient = defineStore('DanmakuClient', () => {
() => status.value === 'running' || status.value === 'listening' () => status.value === 'running' || status.value === 'listening'
) )
const authInfo = ref<RoomAuthInfo>() const authInfo = ref<RoomAuthInfo>()
const accountInfo = useAccount()
let existOtherClient = false let existOtherClient = false
let isInitializing = false let isInitializing = false
@@ -75,7 +77,7 @@ export const useDanmakuClient = defineStore('DanmakuClient', () => {
async (lock) => { async (lock) => {
if (lock) { if (lock) {
status.value = 'initializing' status.value = 'initializing'
bc = new BroadcastChannel('vtsuru.danmaku') bc = new BroadcastChannel('vtsuru.danmaku.' + accountInfo.value?.id)
bc.onmessage = (event) => { bc.onmessage = (event) => {
const message: BCMessage = event.data as BCMessage const message: BCMessage = event.data as BCMessage
const data = message.data ? JSON.parse(message.data) : {} const data = message.data ? JSON.parse(message.data) : {}
@@ -83,7 +85,7 @@ export const useDanmakuClient = defineStore('DanmakuClient', () => {
case 'check-client': case 'check-client':
sendBCMessage('response-client-status', { sendBCMessage('response-client-status', {
status: status.value, status: status.value,
auth: authInfo.value auth: authInfo.value,
}) })
break break
case 'response-client-status': case 'response-client-status':

View File

@@ -9,7 +9,9 @@ export const useWebRTC = defineStore('WebRTC', () => {
const accountInfo = useAccount() const accountInfo = useAccount()
let isInitializing = false let isInitializing = false
function Init(type: 'master' | 'slave'): MasterRTCClient | SlaveRTCClient | undefined { function Init(
type: 'master' | 'slave'
): MasterRTCClient | SlaveRTCClient | undefined {
if (isInitializing) { if (isInitializing) {
return return
} }
@@ -30,7 +32,7 @@ export const useWebRTC = defineStore('WebRTC', () => {
accountInfo.value.id.toString(), accountInfo.value.id.toString(),
accountInfo.value.token accountInfo.value.token
) )
masterClient.value.Init() await masterClient.value.Init()
return masterClient return masterClient
} }
} else { } else {
@@ -41,7 +43,7 @@ export const useWebRTC = defineStore('WebRTC', () => {
accountInfo.value.id?.toString(), accountInfo.value.id?.toString(),
accountInfo.value.token accountInfo.value.token
) )
slaveClient.value.Init() await slaveClient.value.Init()
return slaveClient return slaveClient
} }
} }

View File

@@ -13,14 +13,16 @@ export const useVTsuruHub = defineStore('VTsuruHub', () => {
const signalRClient = ref<signalR.HubConnection>() const signalRClient = ref<signalR.HubConnection>()
const isInited = ref(false) const isInited = ref(false)
const isIniting = ref(false) const isIniting = ref(false)
let token = '' const accountInfo = useAccount()
async function connectSignalR() { async function connectSignalR() {
if (isIniting.value) return if (isIniting.value) return
isIniting.value = true isIniting.value = true
while (!accountInfo.value.id || accountInfo.value.id < 1)
await new Promise((resolve) => setTimeout(resolve, 1000))
//console.log('[Components-Event] 正在连接到 VTsuru 服务器...') //console.log('[Components-Event] 正在连接到 VTsuru 服务器...')
const connection = new HubConnectionBuilder() const connection = new HubConnectionBuilder()
.withUrl(BASE_HUB_URL + 'main?token=' + token, { .withUrl(BASE_HUB_URL + 'main?token=' + accountInfo.value.token, {
skipNegotiation: true, skipNegotiation: true,
transport: HttpTransportType.WebSockets, transport: HttpTransportType.WebSockets,
logger: LogLevel.Error logger: LogLevel.Error
@@ -91,9 +93,8 @@ export const useVTsuruHub = defineStore('VTsuruHub', () => {
signalRClient.value?.onreconnected(listener) signalRClient.value?.onreconnected(listener)
} }
function Init(_token: string) { function Init() {
token = _token if (!isInited.value && !isIniting.value) {
if (!isInited.value) {
connectSignalR() connectSignalR()
} }
return useVTsuruHub() return useVTsuruHub()

View File

@@ -39,6 +39,6 @@ function mount() {
</template> </template>
<NInput v-model:value="customCss" placeholder="css" @update:value="s => danmujiRef?.setCss(s.toString())" /> <NInput v-model:value="customCss" placeholder="css" @update:value="s => danmujiRef?.setCss(s.toString())" />
<DanmujiOBS ref="danmujiRef" :customCss="customCss" style="width: 400px;height: 700px;" /> <DanmujiOBS ref="danmujiRef" :customCss="customCss" style="width: 400px;height: 700px;" :isOBS="false" />
</div> </div>
</template> </template>

View File

@@ -17,6 +17,8 @@ import { useWebRTC } from '@/store/useRTC';
import { QueryGetAPI } from '@/api/query'; import { QueryGetAPI } from '@/api/query';
import { OPEN_LIVE_API_URL, VTSURU_API_URL } from '@/data/constants'; import { OPEN_LIVE_API_URL, VTSURU_API_URL } from '@/data/constants';
import { CustomChart } from 'echarts/charts'; import { CustomChart } from 'echarts/charts';
import { useRoute } from 'vue-router';
import { NAlert } from 'naive-ui';
export interface DanmujiConfig { export interface DanmujiConfig {
minGiftPrice: number, minGiftPrice: number,
@@ -42,15 +44,16 @@ export interface DanmujiConfig {
} }
defineExpose({ setCss }) defineExpose({ setCss })
const props = defineProps<{ const { customCss, isOBS = true } = defineProps<{
customCss?: string customCss?: string
isOBS?: boolean
}>() }>()
const messageRender = ref() const messageRender = ref()
const client = await useDanmakuClient().initClient() const client = await useDanmakuClient().initClient()
const pronunciationConverter = new pronunciation.PronunciationConverter() const pronunciationConverter = new pronunciation.PronunciationConverter()
const accountInfo = useAccount() const accountInfo = useAccount()
const route = useRoute()
const defaultConfig: DanmujiConfig = { const defaultConfig: DanmujiConfig = {
minGiftPrice: 0.1, minGiftPrice: 0.1,
@@ -389,7 +392,7 @@ onMounted(async () => {
config.value = result.data as DanmujiConfig config.value = result.data as DanmujiConfig
break break
} }
else { else if (result.status == 'error') {
await new Promise(resolve => setTimeout(resolve, 1000)) await new Promise(resolve => setTimeout(resolve, 1000))
} }
} }
@@ -406,5 +409,7 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<MessageRender ref="messageRender" :customCss="customCss" :showGiftName="config.showGiftName" style="height: 100%; width: 100%"/> <NAlert v-if="!$route.query.token && isOBS" type="error"> 未携带token参数 </NAlert>
<MessageRender v-else ref="messageRender" :customCss="customCss" :showGiftName="config.showGiftName"
style="height: 100%; width: 100%" />
</template> </template>