mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-06 18:36:55 +08:00
progessing on client
This commit is contained in:
@@ -6,17 +6,15 @@ import {
|
||||
BookCoins20Filled,
|
||||
Info24Filled,
|
||||
Lottery24Filled,
|
||||
MoneyOff24Filled,
|
||||
MoreHorizontal24Filled,
|
||||
TabletSpeaker24Filled,
|
||||
VehicleShip24Filled,
|
||||
VideoAdd20Filled,
|
||||
VideoAdd20Filled
|
||||
} from '@vicons/fluent'
|
||||
import { AnalyticsSharp, Calendar, Chatbox, ListCircle, MusicalNote } from '@vicons/ionicons5'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
import { NButton, NCard, NDivider, NEllipsis, NFlex, NGradientText, NGrid, NGridItem, NIcon, NNumberAnimation, NSpace, NText, NTooltip } from 'naive-ui'
|
||||
import { NButton, NDivider, NEllipsis, NFlex, NGradientText, NGrid, NGridItem, NIcon, NNumberAnimation, NSpace, NText, NTooltip } from 'naive-ui'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { stream } from 'xlsx'
|
||||
|
||||
const { width } = useWindowSize()
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useDanmakuClient } from '@/store/useDanmakuClient';
|
||||
// @ts-ignore
|
||||
import * as constants from './blivechat/constants';
|
||||
// @ts-ignore
|
||||
import * as chatModels from './blivechat/models';
|
||||
import * as chatModels from '../../data/chat/models';
|
||||
// @ts-ignore
|
||||
import * as pronunciation from './blivechat/utils/pronunciation'
|
||||
// @ts-ignore
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useElementSize } from '@vueuse/core'
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { Vue3Marquee } from 'vue3-marquee'
|
||||
import { NCard, NDivider, NEmpty, NSpace, NText, useMessage } from 'naive-ui'
|
||||
import { NCard, NDivider, NEmpty, NMessageProvider, NSpace, NText, useMessage } from 'naive-ui'
|
||||
import { List } from 'linqts'
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -25,6 +25,7 @@ const currentId = computed(() => {
|
||||
return props.id ?? route.query.id
|
||||
})
|
||||
|
||||
const cardRef = ref()
|
||||
const listContainerRef = ref()
|
||||
const { height, width } = useElementSize(listContainerRef)
|
||||
const itemHeight = 40
|
||||
@@ -140,7 +141,8 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="live-request-background" v-bind="$attrs">
|
||||
<NMessageProvider :to="cardRef" />
|
||||
<div ref="cardRef" class="live-request-background" v-bind="$attrs">
|
||||
<p class="live-request-header">{{ settings.obsTitle ?? '点播' }}</p>
|
||||
<NDivider class="live-request-divider">
|
||||
<p class="live-request-header-count">已有 {{ activeSongs.length ?? 0 }} 条</p>
|
||||
|
||||
@@ -1,12 +1,76 @@
|
||||
<script setup lang="ts">
|
||||
import { useWebFetcher } from '@/store/useWebFetcher'
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import { RPC } from '@mixer/postmessage-rpc'
|
||||
import DirectClient, { DirectClientAuthInfo } from '@/data/DanmakuClients/DirectClient';
|
||||
import OpenLiveClient from '@/data/DanmakuClients/OpenLiveClient';
|
||||
|
||||
const webFetcher = useWebFetcher()
|
||||
let rpc: RPC | undefined
|
||||
|
||||
type QueryData = {
|
||||
url: string;
|
||||
headers?: { [key: string]: string };
|
||||
body?: any;
|
||||
}
|
||||
|
||||
function onGetDanmaku(data: any) {
|
||||
rpc?.call('on-get-danmaku', data, false)
|
||||
}
|
||||
|
||||
let timer: any
|
||||
onMounted(async () => {
|
||||
await webFetcher.Start()
|
||||
if (window.parent) { //当是客户端组件时不自动启动, 需要客户端来启动以获取启动响应
|
||||
console.log('[web-fetcher-iframe] 当前为客户端组件')
|
||||
|
||||
rpc = new RPC({
|
||||
target: window.parent,
|
||||
serviceId: 'web-fetcher',
|
||||
origin: '*'
|
||||
})
|
||||
|
||||
rpc.expose('status', () => {
|
||||
return {
|
||||
status: webFetcher.isStarted ? 'running' : 'stopped',
|
||||
type: webFetcher.client?.type,
|
||||
roomId: webFetcher.client instanceof OpenLiveClient ?
|
||||
webFetcher.client.roomAuthInfo?.anchor_info.room_id :
|
||||
webFetcher.client instanceof DirectClient ?
|
||||
webFetcher.client.authInfo.roomId : -1,
|
||||
startedAt: webFetcher.startedAt,
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
rpc.expose('start', async (data: { type: 'openlive' | 'direct', directAuthInfo?: DirectClientAuthInfo, force: boolean }) => {
|
||||
console.log('[web-fetcher-iframe] 接收到 ' + (data.force ? '强制' : '') + '启动请求')
|
||||
if (data.force && webFetcher.isStarted) {
|
||||
webFetcher.Stop()
|
||||
}
|
||||
return await webFetcher.Start(data.type, data.directAuthInfo, true).then((result) => {
|
||||
webFetcher.client?.on('all', (data) => onGetDanmaku(data))
|
||||
})
|
||||
})
|
||||
rpc.expose('stop', () => {
|
||||
console.log('[web-fetcher-iframe] 接收到停止请求')
|
||||
webFetcher.Stop()
|
||||
})
|
||||
rpc.expose('call-hub', (data: {
|
||||
name: string;
|
||||
args: any[];
|
||||
}) => {
|
||||
return webFetcher.signalRClient?.invoke(data.name, ...data.args)
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
rpc?.call('ready', {}, false)
|
||||
}, 1000);
|
||||
|
||||
console.log('[web-fetcher-iframe] RPC 初始化完成')
|
||||
}
|
||||
else {
|
||||
await webFetcher.Start()
|
||||
}
|
||||
setTimeout(() => {
|
||||
// @ts-expect-error obs的东西
|
||||
if (!webFetcher.isStarted && window.obsstudio) {
|
||||
@@ -23,16 +87,18 @@ onMounted(async () => {
|
||||
})
|
||||
onUnmounted(() => {
|
||||
clearInterval(timer)
|
||||
if (window.parent) {
|
||||
webFetcher.client?.off('all', onGetDanmaku)
|
||||
|
||||
rpc?.destroy()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="web-fetcher-status"
|
||||
:style="{
|
||||
backgroundColor: webFetcher.isStarted ? '#6dc56d' : '#e34a4a',
|
||||
}"
|
||||
></div>
|
||||
<div class="web-fetcher-status" :style="{
|
||||
backgroundColor: webFetcher.isStarted ? '#6dc56d' : '#e34a4a',
|
||||
}"></div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@@ -45,6 +111,7 @@ onUnmounted(() => {
|
||||
animation: animated-border 3s infinite;
|
||||
transition: background-color 0.5s;
|
||||
}
|
||||
|
||||
@keyframes animated-border {
|
||||
0% {
|
||||
box-shadow: 0 0 0px #589580;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as models from './models'
|
||||
import * as models from '../../../data/chat/models'
|
||||
|
||||
export default {
|
||||
name: 'ImgShadow',
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
import { getUuid4Hex } from './utils'
|
||||
import * as constants from './constants'
|
||||
|
||||
export const DEFAULT_AVATAR_URL = 'https://i0.hdslb.com/bfs/face/member/noface.jpg@64w_64h'
|
||||
|
||||
export class AddTextMsg {
|
||||
constructor({
|
||||
avatarUrl = DEFAULT_AVATAR_URL,
|
||||
timestamp = new Date().getTime() / 1000,
|
||||
authorName = '',
|
||||
authorType = constants.AUTHOR_TYPE_NORMAL,
|
||||
content = '',
|
||||
privilegeType = 0,
|
||||
isGiftDanmaku = false,
|
||||
authorLevel = 1,
|
||||
isNewbie = false,
|
||||
isMobileVerified = true,
|
||||
medalLevel = 0,
|
||||
id = getUuid4Hex(),
|
||||
translation = '',
|
||||
emoticon = null
|
||||
} = {}) {
|
||||
this.avatarUrl = avatarUrl
|
||||
this.timestamp = timestamp
|
||||
this.authorName = authorName
|
||||
this.authorType = authorType
|
||||
this.content = content
|
||||
this.privilegeType = privilegeType
|
||||
this.isGiftDanmaku = isGiftDanmaku
|
||||
this.authorLevel = authorLevel
|
||||
this.isNewbie = isNewbie
|
||||
this.isMobileVerified = isMobileVerified
|
||||
this.medalLevel = medalLevel
|
||||
this.id = id
|
||||
this.translation = translation
|
||||
this.emoticon = emoticon
|
||||
}
|
||||
}
|
||||
|
||||
export class AddGiftMsg {
|
||||
constructor({
|
||||
id = getUuid4Hex(),
|
||||
avatarUrl = DEFAULT_AVATAR_URL,
|
||||
timestamp = new Date().getTime() / 1000,
|
||||
authorName = '',
|
||||
totalCoin = 0,
|
||||
totalFreeCoin = 0,
|
||||
giftName = '',
|
||||
num = 1
|
||||
} = {}) {
|
||||
this.id = id
|
||||
this.avatarUrl = avatarUrl
|
||||
this.timestamp = timestamp
|
||||
this.authorName = authorName
|
||||
this.totalCoin = totalCoin
|
||||
this.totalFreeCoin = totalFreeCoin
|
||||
this.giftName = giftName
|
||||
this.num = num
|
||||
}
|
||||
}
|
||||
|
||||
export class AddMemberMsg {
|
||||
constructor({
|
||||
id = getUuid4Hex(),
|
||||
avatarUrl = DEFAULT_AVATAR_URL,
|
||||
timestamp = new Date().getTime() / 1000,
|
||||
authorName = '',
|
||||
privilegeType = 1
|
||||
} = {}) {
|
||||
this.id = id
|
||||
this.avatarUrl = avatarUrl
|
||||
this.timestamp = timestamp
|
||||
this.authorName = authorName
|
||||
this.privilegeType = privilegeType
|
||||
}
|
||||
}
|
||||
|
||||
export class AddSuperChatMsg {
|
||||
constructor({
|
||||
id = getUuid4Hex(),
|
||||
avatarUrl = DEFAULT_AVATAR_URL,
|
||||
timestamp = new Date().getTime() / 1000,
|
||||
authorName = '',
|
||||
price = 0,
|
||||
content = '',
|
||||
translation = ''
|
||||
} = {}) {
|
||||
this.id = id
|
||||
this.avatarUrl = avatarUrl
|
||||
this.timestamp = timestamp
|
||||
this.authorName = authorName
|
||||
this.price = price
|
||||
this.content = content
|
||||
this.translation = translation
|
||||
}
|
||||
}
|
||||
|
||||
export class DelSuperChatMsg {
|
||||
constructor({ ids = [] } = {}) {
|
||||
this.ids = ids
|
||||
}
|
||||
}
|
||||
|
||||
export class UpdateTranslationMsg {
|
||||
constructor({ id = getUuid4Hex(), translation = '' } = {}) {
|
||||
this.id = id
|
||||
this.translation = translation
|
||||
}
|
||||
}
|
||||
|
||||
export const FATAL_ERROR_TYPE_AUTH_CODE_ERROR = 1
|
||||
export const FATAL_ERROR_TYPE_TOO_MANY_RETRIES = 2
|
||||
export const FATAL_ERROR_TYPE_TOO_MANY_CONNECTIONS = 3
|
||||
|
||||
export class ChatClientFatalError extends Error {
|
||||
constructor(type, message) {
|
||||
super(message)
|
||||
this.type = type
|
||||
}
|
||||
}
|
||||
|
||||
export class DebugMsg {
|
||||
constructor({ content = '' } = {}) {
|
||||
this.content = content
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
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 { CURRENT_HOST, MUSIC_REQUEST_API_URL, SONG_API_URL } from '@/data/constants'
|
||||
import { useDanmakuClient } from '@/store/useDanmakuClient'
|
||||
import { MusicRequestSettings, useMusicRequestProvider } from '@/store/useMusicRequest'
|
||||
@@ -44,6 +43,7 @@ import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { clearInterval, setInterval } from 'worker-timers'
|
||||
import MusicRequestOBS from '../obs/MusicRequestOBS.vue'
|
||||
import { RoomAuthInfo } from '@/data/DanmakuClients/OpenLiveClient'
|
||||
|
||||
type Music = {
|
||||
id: number
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useAccount } from '@/api/account';
|
||||
import { RoomAuthInfo } from '@/data/DanmakuClient';
|
||||
import { RoomAuthInfo } from '@/data/DanmakuClients/OpenLiveClient';
|
||||
import { NAlert, NButton, NCard, NDivider, NSpace } from 'naive-ui';
|
||||
|
||||
const props = defineProps<{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
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 { CURRENT_HOST, LOTTERY_API_URL } from '@/data/constants'
|
||||
import { useDanmakuClient } from '@/store/useDanmakuClient'
|
||||
import { Delete24Filled, Info24Filled } from '@vicons/fluent'
|
||||
@@ -45,6 +44,7 @@ import {
|
||||
import { h, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import LiveLotteryOBS from '../obs/LiveLotteryOBS.vue'
|
||||
import { DanmakuInfo, GiftInfo, RoomAuthInfo } from '@/data/DanmakuClients/OpenLiveClient'
|
||||
|
||||
interface LotteryOption {
|
||||
resultCount: number
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
Setting_Queue,
|
||||
} from '@/api/api-models'
|
||||
import { QueryGetAPI, QueryPostAPI, QueryPostAPIWithParams } from '@/api/query'
|
||||
import { RoomAuthInfo } from '@/data/DanmakuClient'
|
||||
import { CURRENT_HOST, QUEUE_API_URL } from '@/data/constants'
|
||||
import { useDanmakuClient } from '@/store/useDanmakuClient'
|
||||
import {
|
||||
@@ -70,6 +69,7 @@ import {
|
||||
import { computed, h, onActivated, onDeactivated, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import QueueOBS from '../obs/QueueOBS.vue'
|
||||
import { RoomAuthInfo } from '@/data/DanmakuClients/OpenLiveClient'
|
||||
|
||||
const defaultSettings = {
|
||||
keyword: '排队',
|
||||
|
||||
@@ -3,7 +3,7 @@ import { copyToClipboard } from '@/Utils'
|
||||
import { useAccount } from '@/api/account'
|
||||
import { EventDataTypes, EventModel } from '@/api/api-models'
|
||||
import { QueryGetAPI, QueryPostAPI } from '@/api/query'
|
||||
import { RoomAuthInfo } from '@/data/DanmakuClient'
|
||||
import { RoomAuthInfo } from '@/data/DanmakuClients/OpenLiveClient'
|
||||
import { FETCH_API, VTSURU_API_URL } from '@/data/constants'
|
||||
import { useDanmakuClient } from '@/store/useDanmakuClient'
|
||||
import { Info24Filled, Mic24Filled } from '@vicons/fluent'
|
||||
|
||||
Reference in New Issue
Block a user