mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-07 02:46:55 +08:00
fix hub load
This commit is contained in:
2
default.d.ts
vendored
2
default.d.ts
vendored
@@ -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>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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':
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
Reference in New Issue
Block a user