mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-07 02:46:55 +08:00
add song request
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { ACCOUNT_API_URL, BASE_API } from '@/data/constants'
|
import { ACCOUNT_API_URL, BASE_API } from '@/data/constants'
|
||||||
import { APIRoot, AccountInfo } from './api-models'
|
import { APIRoot, AccountInfo, FunctionTypes } from './api-models'
|
||||||
import { QueryPostAPI } from '@/api/query'
|
import { QueryPostAPI } from '@/api/query'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useLocalStorage } from '@vueuse/core'
|
import { useLocalStorage } from '@vueuse/core'
|
||||||
@@ -47,6 +47,12 @@ function refreshCookie() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
export async function SaveAccountSettings() {
|
||||||
|
return await QueryPostAPI(ACCOUNT_API_URL + 'update-setting', ACCOUNT.value?.settings)
|
||||||
|
}
|
||||||
|
export async function SaveEnableFunctions(functions: FunctionTypes[]) {
|
||||||
|
return await QueryPostAPI(ACCOUNT_API_URL + 'update-enable-functions', functions)
|
||||||
|
}
|
||||||
export function useAccount() {
|
export function useAccount() {
|
||||||
return ACCOUNT
|
return ACCOUNT
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,16 +60,39 @@ export interface Setting_QuestionBox {
|
|||||||
export interface UserSetting {
|
export interface UserSetting {
|
||||||
sendEmail: Setting_SendEmail
|
sendEmail: Setting_SendEmail
|
||||||
questionBox: Setting_QuestionBox
|
questionBox: Setting_QuestionBox
|
||||||
|
songRequest: Setting_SongRequest
|
||||||
enableFunctions: FunctionTypes[]
|
enableFunctions: FunctionTypes[]
|
||||||
|
|
||||||
indexTemplate: string | null,
|
indexTemplate: string | null
|
||||||
songListTemplate: string | null
|
songListTemplate: string | null
|
||||||
scheduleTemplate: string | null
|
scheduleTemplate: string | null
|
||||||
}
|
}
|
||||||
|
export interface Setting_SongRequest {
|
||||||
|
orderPrefix: string
|
||||||
|
onlyAllowSongList: boolean
|
||||||
|
queueMaxSize: number
|
||||||
|
allowAllDanmaku: boolean
|
||||||
|
allowFromWeb: boolean
|
||||||
|
needWearFanMedal: boolean
|
||||||
|
needJianzhang: boolean
|
||||||
|
needTidu: boolean
|
||||||
|
needZongdu: boolean
|
||||||
|
allowSC: boolean
|
||||||
|
scIgnoreLimit: boolean
|
||||||
|
scMinPrice: number
|
||||||
|
fanMedalMinLevel: number
|
||||||
|
allowReorderSong: boolean
|
||||||
|
enableCooldown: boolean
|
||||||
|
cooldownSecond: number
|
||||||
|
zongduCooldownSecond: number
|
||||||
|
tiduCooldownSecond: number
|
||||||
|
jianzhangCooldownSecond: number
|
||||||
|
}
|
||||||
export enum FunctionTypes {
|
export enum FunctionTypes {
|
||||||
SongList,
|
SongList,
|
||||||
QuestionBox,
|
QuestionBox,
|
||||||
Schedule,
|
Schedule,
|
||||||
|
SongRequest,
|
||||||
}
|
}
|
||||||
export interface SongAuthorInfo {
|
export interface SongAuthorInfo {
|
||||||
name: string
|
name: string
|
||||||
@@ -167,7 +190,7 @@ export interface VideoCollectCreateModel {
|
|||||||
endAt: number
|
endAt: number
|
||||||
maxVideoCount: number
|
maxVideoCount: number
|
||||||
}
|
}
|
||||||
export interface VideoCollectTable{
|
export interface VideoCollectTable {
|
||||||
id: string
|
id: string
|
||||||
shortId: string
|
shortId: string
|
||||||
name: string
|
name: string
|
||||||
@@ -190,17 +213,16 @@ export interface VideoCollectVideo {
|
|||||||
length: number
|
length: number
|
||||||
watched?: boolean
|
watched?: boolean
|
||||||
}
|
}
|
||||||
export enum VideoFrom{
|
export enum VideoFrom {
|
||||||
Collect,
|
Collect,
|
||||||
Spam
|
Spam,
|
||||||
}
|
}
|
||||||
export enum VideoStatus
|
export enum VideoStatus {
|
||||||
{
|
|
||||||
Pending,
|
Pending,
|
||||||
Accepted,
|
Accepted,
|
||||||
Rejected,
|
Rejected,
|
||||||
}
|
}
|
||||||
export interface VideoSender{
|
export interface VideoSender {
|
||||||
sendAt: number
|
sendAt: number
|
||||||
sender?: string
|
sender?: string
|
||||||
senderId?: number
|
senderId?: number
|
||||||
@@ -247,9 +269,9 @@ export interface OpenLiveLotteryUserInfo {
|
|||||||
fans_medal_wearing_status: boolean //该房间粉丝勋章佩戴情况
|
fans_medal_wearing_status: boolean //该房间粉丝勋章佩戴情况
|
||||||
guard_level: number
|
guard_level: number
|
||||||
}
|
}
|
||||||
export enum OpenLiveLotteryType{
|
export enum OpenLiveLotteryType {
|
||||||
Waiting,
|
Waiting,
|
||||||
Result
|
Result,
|
||||||
}
|
}
|
||||||
export interface UpdateLiveLotteryUsersModel {
|
export interface UpdateLiveLotteryUsersModel {
|
||||||
users: OpenLiveLotteryUserInfo[]
|
users: OpenLiveLotteryUserInfo[]
|
||||||
@@ -257,6 +279,7 @@ export interface UpdateLiveLotteryUsersModel {
|
|||||||
type: OpenLiveLotteryType
|
type: OpenLiveLotteryType
|
||||||
}
|
}
|
||||||
export interface SongRequestInfo {
|
export interface SongRequestInfo {
|
||||||
|
id: number
|
||||||
songName: string
|
songName: string
|
||||||
song?: SongsInfo
|
song?: SongsInfo
|
||||||
status: SongRequestStatus
|
status: SongRequestStatus
|
||||||
@@ -264,14 +287,16 @@ export interface SongRequestInfo {
|
|||||||
scPrice?: number
|
scPrice?: number
|
||||||
user?: SongRequestUserInfo
|
user?: SongRequestUserInfo
|
||||||
createAt: number
|
createAt: number
|
||||||
|
finishAt?:number
|
||||||
|
isInLocal?: boolean
|
||||||
}
|
}
|
||||||
export interface SongRequestUserInfo {
|
export interface SongRequestUserInfo {
|
||||||
name: string
|
name: string
|
||||||
uId: number
|
uid: number
|
||||||
guardLevel: number
|
guard_level: number
|
||||||
fansMedalLevel: number
|
fans_medal_level: number
|
||||||
fansMedalName: string
|
fans_medal_name: string
|
||||||
fansMedalWearingStatus: boolean
|
fans_medal_wearing_status: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SongRequestFrom {
|
export enum SongRequestFrom {
|
||||||
@@ -287,3 +312,23 @@ export enum SongRequestStatus {
|
|||||||
Finish,
|
Finish,
|
||||||
Cancel,
|
Cancel,
|
||||||
}
|
}
|
||||||
|
export interface EventModel {
|
||||||
|
type: EventDataTypes
|
||||||
|
name: string
|
||||||
|
avatar: string
|
||||||
|
uid: number
|
||||||
|
msg: string
|
||||||
|
time: number
|
||||||
|
num: number
|
||||||
|
price: number
|
||||||
|
guard_level: number
|
||||||
|
fans_medal_level: number
|
||||||
|
fans_medal_name: string
|
||||||
|
fans_medal_wearing_status: boolean
|
||||||
|
}
|
||||||
|
export enum EventDataTypes {
|
||||||
|
Guard,
|
||||||
|
SC,
|
||||||
|
Gift,
|
||||||
|
Message,
|
||||||
|
}
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ export default class DanmakuClient {
|
|||||||
chatClient.start()
|
chatClient.start()
|
||||||
console.log('[OPEN-LIVE] 已连接房间: ' + auth.anchor_info.room_id)
|
console.log('[OPEN-LIVE] 已连接房间: ' + auth.anchor_info.room_id)
|
||||||
this.roomAuthInfo.value = auth
|
this.roomAuthInfo.value = auth
|
||||||
|
this.client = chatClient
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
console.log('[OPEN-LIVE] 无法开启场次')
|
console.log('[OPEN-LIVE] 无法开启场次')
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ export const HISTORY_API_URL = `${BASE_API}history/`
|
|||||||
export const SCHEDULE_API_URL = `${BASE_API}schedule/`
|
export const SCHEDULE_API_URL = `${BASE_API}schedule/`
|
||||||
export const VIDEO_COLLECT_API_URL = `${BASE_API}video-collect/`
|
export const VIDEO_COLLECT_API_URL = `${BASE_API}video-collect/`
|
||||||
export const OPEN_LIVE_API_URL = `${BASE_API}open-live/`
|
export const OPEN_LIVE_API_URL = `${BASE_API}open-live/`
|
||||||
|
export const SONG_REQUEST_API_URL = `${BASE_API}song-request/`
|
||||||
|
export const EVENT_API_URL = `${BASE_API}event/`
|
||||||
|
|
||||||
export const ScheduleTemplateMap = {
|
export const ScheduleTemplateMap = {
|
||||||
'': { name: '默认', compoent: defineAsyncComponent(() => import('@/views/view/scheduleTemplate/DefaultScheduleTemplate.vue')) },
|
'': { name: '默认', compoent: defineAsyncComponent(() => import('@/views/view/scheduleTemplate/DefaultScheduleTemplate.vue')) },
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { QueryGetAPI } from '@/api/query'
|
import { QueryGetAPI } from '@/api/query'
|
||||||
import { useRequest } from 'vue-request'
|
import { useRequest } from 'vue-request'
|
||||||
import { NOTIFACTION_API_URL, isBackendUsable } from './constants'
|
import { NOTIFACTION_API_URL, SONG_REQUEST_API_URL, isBackendUsable } from './constants'
|
||||||
import { NotifactionInfo } from '@/api/api-models'
|
import { NotifactionInfo } from '@/api/api-models'
|
||||||
import { useAccount } from '@/api/account'
|
import { useAccount } from '@/api/account'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
@@ -10,7 +10,7 @@ const n = ref<NotifactionInfo>()
|
|||||||
let isLoading = false
|
let isLoading = false
|
||||||
function get() {
|
function get() {
|
||||||
if (isLoading) return
|
if (isLoading) return
|
||||||
QueryGetAPI<NotifactionInfo>(NOTIFACTION_API_URL + 'get')
|
QueryGetAPI<NotifactionInfo>(SONG_REQUEST_API_URL + 'get-active')
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
n.value = data.data
|
n.value = data.data
|
||||||
|
|||||||
@@ -233,6 +233,14 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
title: '直播抽奖',
|
title: '直播抽奖',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'song-request',
|
||||||
|
name: 'obs-song-request',
|
||||||
|
component: () => import('@/views/obs/SongRequestOBS.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '弹幕点歌',
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ const iconColor = 'white'
|
|||||||
<div class="index-background">
|
<div class="index-background">
|
||||||
<NSpace vertical justify="center" align="center" style="padding-top: 30px">
|
<NSpace vertical justify="center" align="center" style="padding-top: 30px">
|
||||||
<NSpace justify="center" align="center" :size="width > 700 ? 50 : 0">
|
<NSpace justify="center" align="center" :size="width > 700 ? 50 : 0">
|
||||||
<vtb />
|
|
||||||
<NSpace vertical justify="center">
|
<NSpace vertical justify="center">
|
||||||
<NGradientText
|
<NGradientText
|
||||||
size="3rem"
|
size="3rem"
|
||||||
|
|||||||
@@ -29,8 +29,9 @@ import {
|
|||||||
useMessage,
|
useMessage,
|
||||||
NDivider,
|
NDivider,
|
||||||
NTag,
|
NTag,
|
||||||
|
NAlert,
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
import { ref, onMounted, h } from 'vue'
|
import { ref, onMounted, h, onUnmounted } from 'vue'
|
||||||
import { RouterLink, useRoute } from 'vue-router'
|
import { RouterLink, useRoute } from 'vue-router'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -89,6 +90,9 @@ onMounted(async () => {
|
|||||||
message.error('你不是从幻星平台访问此页面, 或未提供对应参数, 无法使用此功能')
|
message.error('你不是从幻星平台访问此页面, 或未提供对应参数, 无法使用此功能')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
client.value?.Stop()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -108,7 +112,7 @@ onMounted(async () => {
|
|||||||
<NPageHeader :subtitle="($route.meta.title as string) ?? ''">
|
<NPageHeader :subtitle="($route.meta.title as string) ?? ''">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<NSpace align="center">
|
<NSpace align="center">
|
||||||
<NTag :type="client ? 'success' : 'warning'"> {{ client ? `已连接 | ${client.roomAuthInfo.value?.anchor_info.uname}` : '未连接' }} </NTag>
|
<NTag :type="client?.roomAuthInfo.value ? 'success' : 'warning'"> {{ client?.roomAuthInfo.value ? `已连接 | ${client.roomAuthInfo.value?.anchor_info.uname}` : '未连接' }} </NTag>
|
||||||
<NSwitch :default-value="!isDarkMode()" @update:value="(value: string & number & boolean) => themeType = value ? ThemeType.Light : ThemeType.Dark">
|
<NSwitch :default-value="!isDarkMode()" @update:value="(value: string & number & boolean) => themeType = value ? ThemeType.Light : ThemeType.Dark">
|
||||||
<template #checked>
|
<template #checked>
|
||||||
<NIcon :component="Sunny" />
|
<NIcon :component="Sunny" />
|
||||||
@@ -120,7 +124,9 @@ onMounted(async () => {
|
|||||||
</NSpace>
|
</NSpace>
|
||||||
</template>
|
</template>
|
||||||
<template #title>
|
<template #title>
|
||||||
|
<NButton text tag="a" @click="$router.push({ name: 'open-live-index', query: $route.query })">
|
||||||
<NText strong style="font-size: 1.4rem; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); text-justify: auto"> VTSURU | 开放平台 </NText>
|
<NText strong style="font-size: 1.4rem; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); text-justify: auto"> VTSURU | 开放平台 </NText>
|
||||||
|
</NButton>
|
||||||
</template>
|
</template>
|
||||||
</NPageHeader>
|
</NPageHeader>
|
||||||
</NLayoutHeader>
|
</NLayoutHeader>
|
||||||
@@ -152,21 +158,23 @@ onMounted(async () => {
|
|||||||
</NText>
|
</NText>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</NLayoutSider>
|
</NLayoutSider>
|
||||||
<NLayoutContent yle="height: 100%" :native-scrollbar="false">
|
<NLayoutContent style="height: 100%; padding: 10px" :native-scrollbar="false">
|
||||||
<RouterView v-if="client?.roomAuthInfo" 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" />
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
</RouterView>
|
</RouterView>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
<NAlert type="info" title="正在请求弹幕客户端认证信息...">
|
||||||
<NSpin show />
|
<NSpin show />
|
||||||
|
</NAlert>
|
||||||
</template>
|
</template>
|
||||||
<NBackTop />
|
<NBackTop />
|
||||||
</NLayoutContent>
|
</NLayoutContent>
|
||||||
</NLayout>
|
</NLayout>
|
||||||
<NLayoutFooter style="height: 30px" bordered>
|
<NLayoutFooter style="height: 30px" bordered>
|
||||||
<NSpace justify="center" align="center" style="height: 100%">
|
<NSpace justify="center" align="center" style="height: 100%">
|
||||||
<NButton text tag="a" href="/" target="_blank" type="info" secondary> vtsuru.live </NButton>
|
<NButton text tag="a" href="/" target="_blank" type="info"> vtsuru.live </NButton>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</NLayoutFooter>
|
</NLayoutFooter>
|
||||||
</NLayout>
|
</NLayout>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useAccount } from '@/api/account'
|
import { SaveAccountSettings, SaveEnableFunctions, useAccount } from '@/api/account'
|
||||||
import { NButton, NCard, NCheckbox, NCheckboxGroup, NDivider, NForm, NModal, NSelect, NSpace, NSpin, NSwitch, NTabPane, NTabs, SelectOption, useMessage } from 'naive-ui'
|
import { NButton, NCard, NCheckbox, NCheckboxGroup, NDivider, NForm, NModal, NSelect, NSpace, NSpin, NSwitch, NTabPane, NTabs, SelectOption, useMessage } from 'naive-ui'
|
||||||
import { Ref, computed, h, onMounted, ref, defineAsyncComponent, onActivated } from 'vue'
|
import { Ref, computed, h, onMounted, ref, defineAsyncComponent, onActivated } from 'vue'
|
||||||
import { FunctionTypes, ScheduleWeekInfo, SongFrom, SongLanguage, SongsInfo } from '@/api/api-models'
|
import { FunctionTypes, ScheduleWeekInfo, SongFrom, SongLanguage, SongsInfo } from '@/api/api-models'
|
||||||
@@ -195,7 +195,7 @@ async function SaveComboGroupSetting(value: (string | number)[], meta: { actionT
|
|||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
isSaving.value = true
|
isSaving.value = true
|
||||||
//UpdateEnableFunction(meta.value as FunctionTypes, meta.actionType == 'check')
|
//UpdateEnableFunction(meta.value as FunctionTypes, meta.actionType == 'check')
|
||||||
await QueryPostAPI(ACCOUNT_API_URL + 'update-setting', accountInfo.value?.settings)
|
await SaveEnableFunctions(accountInfo.value.settings.enableFunctions)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
//message.success('保存成功')
|
//message.success('保存成功')
|
||||||
@@ -216,10 +216,10 @@ async function SaveComboGroupSetting(value: (string | number)[], meta: { actionT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function SaveComboSetting() {
|
async function SaveComboSetting() {
|
||||||
if (accountInfo.value) {
|
|
||||||
isSaving.value = true
|
isSaving.value = true
|
||||||
|
if (accountInfo.value) {
|
||||||
//UpdateEnableFunction(meta.value as FunctionTypes, meta.actionType == 'check')
|
//UpdateEnableFunction(meta.value as FunctionTypes, meta.actionType == 'check')
|
||||||
await QueryPostAPI(ACCOUNT_API_URL + 'update-setting', accountInfo.value?.settings)
|
await SaveAccountSettings()
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('已保存')
|
message.success('已保存')
|
||||||
|
|||||||
323
src/views/obs/SongRequestOBS.vue
Normal file
323
src/views/obs/SongRequestOBS.vue
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { Setting_SongRequest, SongRequestFrom, SongRequestInfo, SongRequestStatus } from '@/api/api-models'
|
||||||
|
import { QueryGetAPI } from '@/api/query'
|
||||||
|
import { AVATAR_URL, SONG_REQUEST_API_URL } from '@/data/constants'
|
||||||
|
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'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id?: number
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const message = useMessage()
|
||||||
|
const route = useRoute()
|
||||||
|
const currentId = computed(() => {
|
||||||
|
return props.id ?? route.query.id
|
||||||
|
})
|
||||||
|
|
||||||
|
const listContainerRef = ref()
|
||||||
|
const footerRef = ref()
|
||||||
|
const footerListRef = ref()
|
||||||
|
const { height, width } = useElementSize(listContainerRef)
|
||||||
|
const footerSize = useElementSize(footerRef)
|
||||||
|
const footerListSize = useElementSize(footerListRef)
|
||||||
|
const itemHeight = 40
|
||||||
|
|
||||||
|
const key = ref(Date.now())
|
||||||
|
|
||||||
|
const songs = ref<SongRequestInfo[]>([])
|
||||||
|
const settings = ref<Setting_SongRequest>({} as Setting_SongRequest)
|
||||||
|
const singing = computed(() => {
|
||||||
|
return songs.value.find((s) => s.status == SongRequestStatus.Singing)
|
||||||
|
})
|
||||||
|
const activeSongs = computed(() => {
|
||||||
|
return songs.value.filter((s) => s.status == SongRequestStatus.Waiting)
|
||||||
|
})
|
||||||
|
|
||||||
|
async function get() {
|
||||||
|
try {
|
||||||
|
const data = await QueryGetAPI<{ songs: SongRequestInfo[]; setting: Setting_SongRequest }>(SONG_REQUEST_API_URL + 'get-active-and-settings', {
|
||||||
|
id: currentId.value,
|
||||||
|
})
|
||||||
|
if (data.code == 200) {
|
||||||
|
return data.data
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
return {} as { songs: SongRequestInfo[]; setting: Setting_SongRequest }
|
||||||
|
}
|
||||||
|
const isMoreThanContainer = computed(() => {
|
||||||
|
return songs.value.length * itemHeight > height.value
|
||||||
|
})
|
||||||
|
const allowGuardTypes = computed(() => {
|
||||||
|
const types = []
|
||||||
|
if (settings.value.needTidu) {
|
||||||
|
types.push('提督')
|
||||||
|
}
|
||||||
|
if (settings.value.needZongdu) {
|
||||||
|
types.push('总督')
|
||||||
|
}
|
||||||
|
if (settings.value.needJianzhang) {
|
||||||
|
types.push('舰长')
|
||||||
|
}
|
||||||
|
return types
|
||||||
|
})
|
||||||
|
async function update() {
|
||||||
|
const r = await get()
|
||||||
|
if (r) {
|
||||||
|
songs.value = r.songs
|
||||||
|
settings.value = r.setting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let timer: any
|
||||||
|
onMounted(() => {
|
||||||
|
update()
|
||||||
|
timer = setInterval(update, 2000)
|
||||||
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearInterval(timer)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="song-request-background" v-bind="$attrs">
|
||||||
|
<p class="song-request-header">点歌</p>
|
||||||
|
<NDivider class="song-request-divider">
|
||||||
|
<p class="song-request-header-count">已有 {{ activeSongs.length ?? 0 }} 首</p>
|
||||||
|
</NDivider>
|
||||||
|
<div class="song-request-singing-container" :singing="songs.findIndex((s) => s.status == SongRequestStatus.Singing) > -1">
|
||||||
|
<div class="song-request-singing-prefix"></div>
|
||||||
|
<template v-if="singing">
|
||||||
|
<img class="song-request-singing-avatar" :src="AVATAR_URL + singing?.user?.uid" />
|
||||||
|
<p class="song-request-singing-song-name">{{ singing?.songName }}</p>
|
||||||
|
<p class="song-request-singing-name">{{ singing?.user?.name }}</p>
|
||||||
|
</template>
|
||||||
|
<div v-else class="song-request-singing-empty">暂未演唱</div>
|
||||||
|
<div class="song-request-singing-suffix"></div>
|
||||||
|
</div>
|
||||||
|
<div class="song-request-content" ref="listContainerRef">
|
||||||
|
<template v-if="activeSongs.length > 0">
|
||||||
|
<Vue3Marquee class="song-request-list" :key="key" vertical :pause="!isMoreThanContainer" :duration="20" :style="`height: ${height}px;width: ${width}px;`">
|
||||||
|
<span class="song-request-list-item" :from="(song.from as number)" :status="(song.status as number)" v-for="song in activeSongs" :key="song.id" :style="`height: ${itemHeight}px`">
|
||||||
|
<div class="song-request-list-item-song-name">
|
||||||
|
{{ song.songName }}
|
||||||
|
</div>
|
||||||
|
<div class="song-request-list-item-level" :has-level="(song.user?.fans_medal_level ?? 0) > 0">
|
||||||
|
{{ song.user?.fans_medal_level }}
|
||||||
|
</div>
|
||||||
|
<p class="song-request-list-item-name">{{ song.from == SongRequestFrom.Manual ? '主播添加' : song.user?.name }}</p>
|
||||||
|
</span>
|
||||||
|
</Vue3Marquee>
|
||||||
|
</template>
|
||||||
|
<div v-else style="position: relative; top: 20%">
|
||||||
|
<NEmpty class="song-request-empty" description="暂无人点歌" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="song-request-footer" ref="footerRef">
|
||||||
|
<Vue3Marquee :key="key" ref="footerListRef" class="song-request-footer-marquee" :pause="footerSize.width < footerListSize.width" :duration="20">
|
||||||
|
<span class="song-request-tag" type="prefix">
|
||||||
|
<div class="song-request-tag-key">前缀</div>
|
||||||
|
<div class="song-request-tag-value">
|
||||||
|
{{ settings.orderPrefix }}
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<span class="song-request-tag" type="prefix">
|
||||||
|
<div class="song-request-tag-key">允许</div>
|
||||||
|
<div class="song-request-tag-value">
|
||||||
|
{{ settings.allowAllDanmaku ? '所有弹幕' : allowGuardTypes.length > 0 ? allowGuardTypes.join(',') : '无' }}
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<span class="song-request-tag" type="sc">
|
||||||
|
<div class="song-request-tag-key">SC点歌</div>
|
||||||
|
<div class="song-request-tag-value">
|
||||||
|
{{ settings.allowSC ? '> ¥' + settings.scMinPrice : '不允许' }}
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<span class="song-request-tag" type="fan-madel">
|
||||||
|
<div class="song-request-tag-key">粉丝牌</div>
|
||||||
|
<div class="song-request-tag-value">
|
||||||
|
{{ settings.needWearFanMedal ? (settings.fanMedalMinLevel > 0 ? '> ' + settings.fanMedalMinLevel : '佩戴') : '无需' }}
|
||||||
|
</div>
|
||||||
|
</span></Vue3Marquee
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.song-request-background {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100px;
|
||||||
|
min-width: 100px;
|
||||||
|
background-color: #0f0f0f48;
|
||||||
|
border-radius: 10px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.song-request-header {
|
||||||
|
margin: 0;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0 0 10px #ca7b7b6e, 0 0 20px #ffffff8e, 0 0 30px #61606086, 0 0 40px rgba(64, 156, 179, 0.555);
|
||||||
|
}
|
||||||
|
.song-request-header-count {
|
||||||
|
color: #ffffffbd;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.song-request-divider {
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-top: -15px;
|
||||||
|
margin-bottom: -15px;
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
.song-request-singing-container {
|
||||||
|
height: 35px;
|
||||||
|
margin: 0 10px 0 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
.song-request-singing-empty {
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
color: #ffffffbe;
|
||||||
|
}
|
||||||
|
.song-request-singing-prefix {
|
||||||
|
border: 2px solid rgb(231, 231, 231);
|
||||||
|
height: 30px;
|
||||||
|
width: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
.song-request-singing-container[singing='true'] .song-request-singing-prefix {
|
||||||
|
background-color: #75c37f;
|
||||||
|
animation: animated-border 3s linear infinite;
|
||||||
|
}
|
||||||
|
.song-request-singing-container[singing='false'] .song-request-singing-prefix {
|
||||||
|
background-color: #c37575;
|
||||||
|
}
|
||||||
|
.song-request-singing-avatar {
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 50%;
|
||||||
|
/* 添加无限旋转动画 */
|
||||||
|
animation: rotate 20s linear infinite;
|
||||||
|
}
|
||||||
|
.song-request-singing-song-name {
|
||||||
|
font-size: large;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.song-request-singing-name {
|
||||||
|
font-size: 12px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
@keyframes rotate {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.n-divider__line {
|
||||||
|
background-color: #ffffffd5;
|
||||||
|
}
|
||||||
|
.song-request-content {
|
||||||
|
background-color: #0f0f0f4f;
|
||||||
|
margin: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
.marquee {
|
||||||
|
justify-items: left;
|
||||||
|
}
|
||||||
|
.song-request-list-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: left;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
.song-request-list-item-song-name {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 手动添加 */
|
||||||
|
.song-request-list-item[from='0'] .song-request-list-item-name {
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #c6e4d9;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.song-request-list-item[from='0'] .song-request-list-item-avatar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 弹幕点歌 */
|
||||||
|
.song-request-list-item[from='1'] {
|
||||||
|
}
|
||||||
|
.song-request-list-item-name {
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgba(204, 204, 204, 0.993);
|
||||||
|
}
|
||||||
|
.song-request-list-item-level {
|
||||||
|
text-align: center;
|
||||||
|
height: 18px;
|
||||||
|
padding: 2px;
|
||||||
|
min-width: 15px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #0f0f0f48;
|
||||||
|
color: rgba(204, 204, 204, 0.993);
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.song-request-list-item-level[has-level='false'] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.song-request-footer {
|
||||||
|
margin: 0 5px 5px 5px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #0f0f0f4f;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.song-request-tag {
|
||||||
|
display: flex;
|
||||||
|
margin: 5px 0 5px 5px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #0f0f0f4f;
|
||||||
|
padding: 4px;
|
||||||
|
padding-right: 6px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: left;
|
||||||
|
}
|
||||||
|
.song-request-tag-key {
|
||||||
|
font-style: italic;
|
||||||
|
color: rgb(211, 211, 211);
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.song-request-tag-value {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
@keyframes animated-border {
|
||||||
|
0% {
|
||||||
|
box-shadow: 0 0 0px #589580;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 0 6px rgba(255, 255, 255, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,46 +1,970 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useAccount } from '@/api/account'
|
import { SaveAccountSettings, SaveEnableFunctions, useAccount } from '@/api/account'
|
||||||
import { SongRequestInfo } from '@/api/api-models'
|
import { EventDataTypes, EventModel, FunctionTypes, OpenLiveInfo, Setting_SongRequest, SongRequestFrom, SongRequestInfo, SongRequestStatus, SongRequestUserInfo } from '@/api/api-models'
|
||||||
|
import { QueryGetAPI, QueryPostAPI, QueryPostAPIWithParams } from '@/api/query'
|
||||||
import DanmakuClient, { AuthInfo, DanmakuInfo, RoomAuthInfo, SCInfo } from '@/data/DanmakuClient'
|
import DanmakuClient, { AuthInfo, DanmakuInfo, RoomAuthInfo, SCInfo } from '@/data/DanmakuClient'
|
||||||
import { NList, NTabPane, NTabs, useMessage } from 'naive-ui'
|
import { OPEN_LIVE_API_URL, SONG_REQUEST_API_URL } from '@/data/constants'
|
||||||
import { onMounted, onUnmounted, ref } from 'vue'
|
import { Check24Filled, Checkmark12Regular, Delete24Filled, Dismiss12Filled, Dismiss16Filled, Info24Filled, Mic24Filled, PeopleQueue24Filled } from '@vicons/fluent'
|
||||||
|
import { ReloadCircleSharp } from '@vicons/ionicons5'
|
||||||
|
import { useStorage } from '@vueuse/core'
|
||||||
|
import { format, isSameDay } from 'date-fns'
|
||||||
|
import { ca } from 'date-fns/locale'
|
||||||
|
import { number } from 'echarts'
|
||||||
|
import { List } from 'linqts'
|
||||||
|
import {
|
||||||
|
DataTableColumns,
|
||||||
|
NAlert,
|
||||||
|
NButton,
|
||||||
|
NCard,
|
||||||
|
NCheckbox,
|
||||||
|
NCollapse,
|
||||||
|
NCollapseItem,
|
||||||
|
NDataTable,
|
||||||
|
NDivider,
|
||||||
|
NEllipsis,
|
||||||
|
NEmpty,
|
||||||
|
NIcon,
|
||||||
|
NInput,
|
||||||
|
NInputGroup,
|
||||||
|
NInputGroupLabel,
|
||||||
|
NInputNumber,
|
||||||
|
NLi,
|
||||||
|
NList,
|
||||||
|
NListItem,
|
||||||
|
NModal,
|
||||||
|
NPopconfirm,
|
||||||
|
NSpace,
|
||||||
|
NSpin,
|
||||||
|
NSwitch,
|
||||||
|
NTabPane,
|
||||||
|
NTabs,
|
||||||
|
NTag,
|
||||||
|
NText,
|
||||||
|
NTime,
|
||||||
|
NTooltip,
|
||||||
|
NUl,
|
||||||
|
useMessage,
|
||||||
|
useNotification,
|
||||||
|
} from 'naive-ui'
|
||||||
|
import { computed, h, onMounted, onUnmounted, ref } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
import LiveLotteryOBS from '../obs/LiveLotteryOBS.vue'
|
||||||
|
import SongRequestOBS from '../obs/SongRequestOBS.vue'
|
||||||
|
|
||||||
|
const defaultSettings = {
|
||||||
|
orderPrefix: '点歌',
|
||||||
|
onlyAllowSongList: false,
|
||||||
|
queueMaxSize: 10,
|
||||||
|
allowAllDanmaku: true,
|
||||||
|
allowFromWeb: true,
|
||||||
|
needWearFanMedal: false,
|
||||||
|
needJianzhang: false,
|
||||||
|
needTidu: false,
|
||||||
|
needZongdu: false,
|
||||||
|
allowSC: true,
|
||||||
|
scIgnoreLimit: true,
|
||||||
|
scMinPrice: 30,
|
||||||
|
fanMedalMinLevel: 0,
|
||||||
|
allowReorderSong: false,
|
||||||
|
enableCooldown: false,
|
||||||
|
cooldownSecond: 1200,
|
||||||
|
zongduCooldownSecond: 300,
|
||||||
|
tiduCooldownSecond: 600,
|
||||||
|
jianzhangCooldownSecond: 900,
|
||||||
|
} as Setting_SongRequest
|
||||||
|
const STATUS_MAP = {
|
||||||
|
[SongRequestStatus.Waiting]: '等待中',
|
||||||
|
[SongRequestStatus.Singing]: '演唱中',
|
||||||
|
[SongRequestStatus.Finish]: '已演唱',
|
||||||
|
[SongRequestStatus.Cancel]: '已取消',
|
||||||
|
}
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const accountInfo = useAccount()
|
const accountInfo = useAccount()
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
const notice = useNotification()
|
||||||
|
|
||||||
|
const isWarnMessageAutoClose = useStorage('SongRequest.Settings.WarnMessageAutoClose', false)
|
||||||
|
|
||||||
|
const isLoading = ref(false)
|
||||||
|
const showOBSModal = ref(false)
|
||||||
|
|
||||||
|
const settings = computed({
|
||||||
|
get: () => {
|
||||||
|
if (accountInfo.value) {
|
||||||
|
return accountInfo.value.settings.songRequest
|
||||||
|
}
|
||||||
|
return defaultSettings
|
||||||
|
},
|
||||||
|
set: (value) => {
|
||||||
|
if (accountInfo.value) {
|
||||||
|
accountInfo.value.settings.songRequest = value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
client: DanmakuClient
|
client: DanmakuClient
|
||||||
roomInfo: RoomAuthInfo
|
roomInfo: RoomAuthInfo
|
||||||
code: string | undefined
|
code: string | undefined
|
||||||
|
isOpenLive?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const activeSongs = ref<SongRequestInfo[]>([])
|
const localActiveSongs = useStorage('SongRequest.ActiveSongs', [] as SongRequestInfo[])
|
||||||
|
const songs = ref<SongRequestInfo[]>(await getAllSong())
|
||||||
|
const activeSongs = computed(() => {
|
||||||
|
return (accountInfo ? songs.value : localActiveSongs.value)
|
||||||
|
.sort((a, b) => b.status - a.status)
|
||||||
|
.filter((song) => {
|
||||||
|
return song.status == SongRequestStatus.Waiting || song.status == SongRequestStatus.Singing
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const historySongs = computed(() => {
|
||||||
|
return (accountInfo ? songs.value : localActiveSongs.value)
|
||||||
|
.sort((a, b) => a.status - b.status)
|
||||||
|
.filter((song) => {
|
||||||
|
return song.status == SongRequestStatus.Finish || song.status == SongRequestStatus.Cancel
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const newSongName = ref('')
|
||||||
|
|
||||||
|
const defaultPrefix = useStorage('Settings.SongRequest.DefaultPrefix', '点歌')
|
||||||
|
const configCanEdit = computed(() => {
|
||||||
|
return accountInfo.value != null && accountInfo.value != undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
const table = ref()
|
||||||
|
|
||||||
|
async function getAllSong() {
|
||||||
|
if (accountInfo.value) {
|
||||||
|
try {
|
||||||
|
const data = await QueryGetAPI<SongRequestInfo[]>(SONG_REQUEST_API_URL + 'get-all', {
|
||||||
|
id: accountInfo.value.id,
|
||||||
|
})
|
||||||
|
if (data.code == 200) {
|
||||||
|
console.log('[OPEN-LIVE-Song-Request] 已获取所有数据')
|
||||||
|
return new List(data.data).OrderByDescending((s) => s.createAt).ToArray()
|
||||||
|
} else {
|
||||||
|
message.error('无法获取数据: ' + data.message)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
message.error('无法获取数据')
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
} else {
|
||||||
|
return localActiveSongs.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function getActiveSong() {
|
||||||
|
if (accountInfo.value) {
|
||||||
|
try {
|
||||||
|
const data = await QueryGetAPI<SongRequestInfo[]>(SONG_REQUEST_API_URL + 'get-active', {
|
||||||
|
id: accountInfo.value.id,
|
||||||
|
})
|
||||||
|
if (data.code == 200) {
|
||||||
|
console.log('[OPEN-LIVE-Song-Request] 已获取点歌队列')
|
||||||
|
return data.data
|
||||||
|
} else {
|
||||||
|
message.error('无法获取点歌队列: ' + data.message)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
} else {
|
||||||
|
return localActiveSongs.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function addSong(danmaku: EventModel) {
|
||||||
|
console.log(`[OPEN-LIVE-Song-Request] 收到 [${danmaku.name}] 的点歌${danmaku.type == EventDataTypes.SC ? 'SC' : '弹幕'}: ${danmaku.msg}`)
|
||||||
|
if (accountInfo.value) {
|
||||||
|
await QueryPostAPI<SongRequestInfo>(SONG_REQUEST_API_URL + 'try-add', danmaku)
|
||||||
|
.then((data) => {
|
||||||
|
if (data.code == 200) {
|
||||||
|
message.success(`[${danmaku.name}] 添加曲目: ${data.data.songName}`)
|
||||||
|
songs.value.unshift(data.data)
|
||||||
|
} else {
|
||||||
|
//message.error(`[${danmaku.name}] 添加曲目失败: ${data.message}`)
|
||||||
|
const time = Date.now()
|
||||||
|
notice.warning({
|
||||||
|
title: danmaku.name + ' 点歌失败',
|
||||||
|
description: data.message,
|
||||||
|
duration: isWarnMessageAutoClose.value ? 3000 : 0,
|
||||||
|
meta: () => h(NTime, { type: 'relative', time: time, key: updateKey.value }),
|
||||||
|
})
|
||||||
|
console.log(`[OPEN-LIVE-Song-Request] [${danmaku.name}] 添加曲目失败: ${data.message}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const songData = {
|
||||||
|
songName: danmaku.msg.trim().substring(settings.value.orderPrefix.length),
|
||||||
|
song: undefined,
|
||||||
|
status: SongRequestStatus.Waiting,
|
||||||
|
from: danmaku.type == EventDataTypes.Message ? SongRequestFrom.Danmaku : SongRequestFrom.SC,
|
||||||
|
scPrice: danmaku.type == EventDataTypes.SC ? danmaku.price : 0,
|
||||||
|
user: {
|
||||||
|
name: danmaku.name,
|
||||||
|
uid: danmaku.uid,
|
||||||
|
fans_medal_level: danmaku.fans_medal_level,
|
||||||
|
fans_medal_name: danmaku.fans_medal_name,
|
||||||
|
fans_medal_wearing_status: danmaku.fans_medal_wearing_status,
|
||||||
|
guard_level: danmaku.guard_level,
|
||||||
|
} as SongRequestUserInfo,
|
||||||
|
createAt: Date.now(),
|
||||||
|
isInLocal: true,
|
||||||
|
id: songs.value.length == 0 ? 1 : new List(songs.value).Max((s) => s.id) + 1,
|
||||||
|
} as SongRequestInfo
|
||||||
|
localActiveSongs.value.unshift(songData)
|
||||||
|
message.success(`[${danmaku.name}] 添加曲目: ${songData.songName}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function addSongManual() {
|
||||||
|
if (!newSongName.value) {
|
||||||
|
message.error('请输入曲目名')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (accountInfo.value) {
|
||||||
|
await QueryPostAPIWithParams<SongRequestInfo>(SONG_REQUEST_API_URL + 'add', {
|
||||||
|
name: newSongName.value,
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
if (data.code == 200) {
|
||||||
|
message.success(`已手动添加曲目: ${data.data.songName}`)
|
||||||
|
activeSongs.value.unshift(data.data)
|
||||||
|
newSongName.value = ''
|
||||||
|
console.log(`[OPEN-LIVE-Song-Request] 已手动添加曲目: ${data.data.songName}`)
|
||||||
|
} else {
|
||||||
|
message.error(`手动添加曲目失败: ${data.message}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const songData = {
|
||||||
|
songName: newSongName.value,
|
||||||
|
song: undefined,
|
||||||
|
status: SongRequestStatus.Waiting,
|
||||||
|
from: SongRequestFrom.Manual,
|
||||||
|
scPrice: undefined,
|
||||||
|
user: undefined,
|
||||||
|
createAt: Date.now(),
|
||||||
|
isInLocal: true,
|
||||||
|
id: songs.value.length == 0 ? 1 : new List(songs.value).Max((s) => s.id) + 1,
|
||||||
|
} as SongRequestInfo
|
||||||
|
localActiveSongs.value.unshift(songData)
|
||||||
|
message.success(`已手动添加曲目: ${songData.songName}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function updateSongStatus(song: SongRequestInfo, status: SongRequestStatus) {
|
||||||
|
if (!configCanEdit.value) {
|
||||||
|
song.status = status
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isLoading.value = true
|
||||||
|
let statusString = ''
|
||||||
|
let statusString2 = ''
|
||||||
|
switch (status) {
|
||||||
|
case SongRequestStatus.Waiting:
|
||||||
|
statusString = 'active'
|
||||||
|
statusString2 = '等待中'
|
||||||
|
break
|
||||||
|
case SongRequestStatus.Cancel:
|
||||||
|
statusString = 'cancel'
|
||||||
|
statusString2 = '已取消'
|
||||||
|
break
|
||||||
|
case SongRequestStatus.Finish:
|
||||||
|
statusString = 'finish'
|
||||||
|
statusString2 = '已完成'
|
||||||
|
break
|
||||||
|
case SongRequestStatus.Singing:
|
||||||
|
statusString = 'singing'
|
||||||
|
statusString2 = '演唱中'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
await QueryGetAPI(SONG_REQUEST_API_URL + statusString, {
|
||||||
|
id: song.id,
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
if (data.code == 200) {
|
||||||
|
console.log(`[OPEN-LIVE-Song-Request] 更新曲目状态: ${song.songName} -> ${statusString}`)
|
||||||
|
song.status = status
|
||||||
|
if (status > SongRequestStatus.Singing) {
|
||||||
|
song.finishAt = Date.now()
|
||||||
|
}
|
||||||
|
message.success(`已更新曲目状态为: ${statusString2}`)
|
||||||
|
} else {
|
||||||
|
console.log(`[OPEN-LIVE-Song-Request] 更新曲目状态失败: ${data.message}`)
|
||||||
|
message.error(`更新曲目状态失败: ${data.message}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
message.error(`更新曲目状态失败`)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
isLoading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function onGetDanmaku(danmaku: DanmakuInfo) {
|
function onGetDanmaku(danmaku: DanmakuInfo) {
|
||||||
console.log(danmaku)
|
if (checkMessage(danmaku.msg)) {
|
||||||
|
addSong({
|
||||||
|
msg: danmaku.msg,
|
||||||
|
type: EventDataTypes.Message,
|
||||||
|
time: danmaku.timestamp,
|
||||||
|
uid: danmaku.uid,
|
||||||
|
name: danmaku.uname,
|
||||||
|
avatar: danmaku.uface,
|
||||||
|
fans_medal_level: danmaku.fans_medal_level,
|
||||||
|
fans_medal_name: danmaku.fans_medal_name,
|
||||||
|
fans_medal_wearing_status: danmaku.fans_medal_wearing_status,
|
||||||
|
guard_level: danmaku.guard_level,
|
||||||
|
num: 1,
|
||||||
|
price: 0,
|
||||||
|
} as EventModel)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function onGetSC(danmaku: SCInfo) {
|
function onGetSC(danmaku: SCInfo) {
|
||||||
console.log(danmaku)
|
if (settings.value.allowSC && checkMessage(danmaku.message)) {
|
||||||
|
addSong({
|
||||||
|
msg: danmaku.message,
|
||||||
|
type: EventDataTypes.SC,
|
||||||
|
time: danmaku.timestamp,
|
||||||
|
uid: danmaku.uid,
|
||||||
|
name: danmaku.uname,
|
||||||
|
fans_medal_level: danmaku.fans_medal_level,
|
||||||
|
fans_medal_name: danmaku.fans_medal_name,
|
||||||
|
fans_medal_wearing_status: danmaku.fans_medal_wearing_status,
|
||||||
|
guard_level: danmaku.guard_level,
|
||||||
|
avatar: danmaku.uface,
|
||||||
|
num: 1,
|
||||||
|
price: danmaku.rmb,
|
||||||
|
} as EventModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function checkMessage(msg: string) {
|
||||||
|
return msg
|
||||||
|
.trim()
|
||||||
|
.toLowerCase()
|
||||||
|
.startsWith(accountInfo.value ? settings.value.orderPrefix : defaultPrefix.value)
|
||||||
|
}
|
||||||
|
async function onUpdateFunctionEnable() {
|
||||||
|
if (accountInfo.value) {
|
||||||
|
const oldValue = JSON.parse(JSON.stringify(accountInfo.value.settings.enableFunctions))
|
||||||
|
if (accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.SongRequest)) {
|
||||||
|
accountInfo.value.settings.enableFunctions = accountInfo.value.settings.enableFunctions.filter((f) => f != FunctionTypes.SongRequest)
|
||||||
|
} else {
|
||||||
|
accountInfo.value.settings.enableFunctions.push(FunctionTypes.SongRequest)
|
||||||
|
}
|
||||||
|
if (!accountInfo.value.settings.songRequest.orderPrefix) {
|
||||||
|
accountInfo.value.settings.songRequest.orderPrefix = defaultPrefix.value
|
||||||
|
}
|
||||||
|
await SaveEnableFunctions(accountInfo.value?.settings.enableFunctions)
|
||||||
|
.then((data) => {
|
||||||
|
if (data.code == 200) {
|
||||||
|
message.success(`已${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.SongRequest) ? '启用' : '禁用'}点歌功能`)
|
||||||
|
} else {
|
||||||
|
if (accountInfo.value) {
|
||||||
|
accountInfo.value.settings.enableFunctions = oldValue
|
||||||
|
}
|
||||||
|
message.error(`点歌功能${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.SongRequest) ? '启用' : '禁用'}失败: ${data.message}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
message.error(`点歌功能${accountInfo.value?.settings.enableFunctions.includes(FunctionTypes.SongRequest) ? '启用' : '禁用'}失败: ${err}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function updateSettings() {
|
||||||
|
if (accountInfo.value) {
|
||||||
|
isLoading.value = true
|
||||||
|
await QueryPostAPI(SONG_REQUEST_API_URL + 'update-setting', settings.value)
|
||||||
|
.then((data) => {
|
||||||
|
if (data.code == 200) {
|
||||||
|
message.success('已保存')
|
||||||
|
} else {
|
||||||
|
message.error('保存失败: ' + data.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
message.error('保存失败')
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
isLoading.value = false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
message.success('完成')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function deleteSongs(values: SongRequestInfo[]) {
|
||||||
|
await QueryPostAPI(
|
||||||
|
SONG_REQUEST_API_URL + 'del',
|
||||||
|
values.map((s) => s.id)
|
||||||
|
)
|
||||||
|
.then((data) => {
|
||||||
|
if (data.code == 200) {
|
||||||
|
message.success('删除成功')
|
||||||
|
songs.value = songs.value.filter((s) => !values.includes(s))
|
||||||
|
} else {
|
||||||
|
message.error('删除失败: ' + data.message)
|
||||||
|
console.error('删除失败: ' + data.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
message.error('删除失败')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
async function deactiveAllSongs() {
|
||||||
|
await QueryGetAPI(SONG_REQUEST_API_URL + 'deactive')
|
||||||
|
.then((data) => {
|
||||||
|
if (data.code == 200) {
|
||||||
|
message.success('已全部取消')
|
||||||
|
songs.value.forEach((s) => {
|
||||||
|
if (s.status <= SongRequestStatus.Singing) {
|
||||||
|
s.status = SongRequestStatus.Cancel
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
message.error('取消失败: ' + data.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
message.error('取消失败')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const statusFilterOptions = computed(() => {
|
||||||
|
return Object.values(SongRequestStatus)
|
||||||
|
.filter((t) => /^\d+$/.test(t.toString()))
|
||||||
|
.map((t) => {
|
||||||
|
return {
|
||||||
|
label: STATUS_MAP[t as SongRequestStatus],
|
||||||
|
value: t,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '曲名',
|
||||||
|
key: 'songName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户名',
|
||||||
|
key: 'user.name',
|
||||||
|
render: (data) => {
|
||||||
|
return h(
|
||||||
|
NTooltip,
|
||||||
|
{ trigger: 'hover' },
|
||||||
|
{
|
||||||
|
trigger: () => h(NTag, { bordered: false, size: 'small' }, data.from == SongRequestFrom.Manual ? () => h(NText, { italic: true }, () => '手动添加') : () => data.user?.name),
|
||||||
|
default: () => (data.from == SongRequestFrom.Manual ? '就是主播自己' : data.user?.uid),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '来自',
|
||||||
|
key: 'from',
|
||||||
|
render(data) {
|
||||||
|
let fromType: 'info' | 'success' | 'default' | 'error'
|
||||||
|
switch (data.from) {
|
||||||
|
case SongRequestFrom.Danmaku: {
|
||||||
|
fromType = 'info'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case SongRequestFrom.SC: {
|
||||||
|
fromType = 'error'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case SongRequestFrom.Web: {
|
||||||
|
fromType = 'success'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case SongRequestFrom.Manual: {
|
||||||
|
fromType = 'default'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return h(NTag, { size: 'small', type: fromType }, () => {
|
||||||
|
switch (data.from) {
|
||||||
|
case SongRequestFrom.Danmaku: {
|
||||||
|
return '弹幕'
|
||||||
|
}
|
||||||
|
case SongRequestFrom.SC: {
|
||||||
|
return 'SuperChat | ' + data.scPrice
|
||||||
|
}
|
||||||
|
case SongRequestFrom.Manual: {
|
||||||
|
return '手动添加'
|
||||||
|
}
|
||||||
|
case SongRequestFrom.Web: {
|
||||||
|
return '网页添加'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
key: 'status',
|
||||||
|
filter(value, row) {
|
||||||
|
return ~row.status == value
|
||||||
|
},
|
||||||
|
filterOptions: statusFilterOptions.value,
|
||||||
|
render(data) {
|
||||||
|
let statusType: 'info' | 'success' | 'warning' | 'error'
|
||||||
|
switch (data.status) {
|
||||||
|
case SongRequestStatus.Singing: {
|
||||||
|
statusType = 'success'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case SongRequestStatus.Waiting: {
|
||||||
|
statusType = 'warning'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case SongRequestStatus.Finish: {
|
||||||
|
statusType = 'info'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case SongRequestStatus.Cancel: {
|
||||||
|
statusType = 'error'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return h(NTag, { type: statusType, size: 'small' }, () => STATUS_MAP[data.status])
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
key: 'time',
|
||||||
|
sorter: (a, b) => a.createAt - b.createAt,
|
||||||
|
render: (data) => {
|
||||||
|
return h(NTime, { time: data.createAt })
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'manage',
|
||||||
|
width: 100,
|
||||||
|
render(data) {
|
||||||
|
return h(
|
||||||
|
NSpace,
|
||||||
|
{
|
||||||
|
justify: 'center',
|
||||||
|
size: 10,
|
||||||
|
},
|
||||||
|
() => [
|
||||||
|
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)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: () => h(NIcon, { component: ReloadCircleSharp }),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
default: () => '重新放回等待列表',
|
||||||
|
})
|
||||||
|
: undefined,
|
||||||
|
h(
|
||||||
|
NPopconfirm,
|
||||||
|
{ onPositiveClick: () => deleteSongs([data]) },
|
||||||
|
{
|
||||||
|
trigger: () =>
|
||||||
|
h(NTooltip, null, {
|
||||||
|
trigger: () =>
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
size: 'small',
|
||||||
|
type: 'error',
|
||||||
|
circle: true,
|
||||||
|
loading: isLoading.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: () => h(NIcon, { component: Delete24Filled }),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
default: () => '删除记录',
|
||||||
|
}),
|
||||||
|
default: () => '确定删除?',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as DataTableColumns<SongRequestInfo>
|
||||||
|
|
||||||
|
function GetSCColor(price: number): string {
|
||||||
|
if (price === 0) return `#2a60b2`
|
||||||
|
if (price > 0 && price < 30) return `#2a60b2`
|
||||||
|
if (price >= 30 && price < 50) return `#2a60b2`
|
||||||
|
if (price >= 50 && price < 100) return `#427d9e`
|
||||||
|
if (price >= 100 && price < 500) return `#c99801`
|
||||||
|
if (price >= 500 && price < 1000) return `#e09443`
|
||||||
|
if (price >= 1000 && price < 2000) return `#e54d4d`
|
||||||
|
if (price >= 2000) return `#ab1a32`
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
function GetGuardColor(level: number | null | undefined): string {
|
||||||
|
if (level) {
|
||||||
|
switch (level) {
|
||||||
|
case 1: {
|
||||||
|
return 'rgb(122, 4, 35)'
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
return 'rgb(157, 155, 255)'
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
return 'rgb(104, 136, 241)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let timer: any
|
||||||
|
const updateKey = ref(0)
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
if (accountInfo.value) {
|
||||||
|
settings.value = accountInfo.value.settings.songRequest
|
||||||
|
}
|
||||||
props.client.on('danmaku', onGetDanmaku)
|
props.client.on('danmaku', onGetDanmaku)
|
||||||
props.client.on('sc', onGetSC)
|
props.client.on('sc', onGetSC)
|
||||||
|
timer = setInterval(() => {
|
||||||
|
updateKey.value++
|
||||||
|
}, 1000)
|
||||||
})
|
})
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
props.client.off('danmaku', onGetDanmaku)
|
props.client.off('danmaku', onGetDanmaku)
|
||||||
props.client.off('sc', onGetSC)
|
props.client.off('sc', onGetSC)
|
||||||
|
clearInterval(timer)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
开发中...
|
<NAlert type="info" v-if="accountInfo"> 启用点歌功能 <NSwitch :value="accountInfo?.settings.enableFunctions.includes(FunctionTypes.SongRequest)" @update:value="onUpdateFunctionEnable" /> </NAlert>
|
||||||
<NTabs animated>
|
<NAlert type="warning" v-else title="你尚未注册并登录 VTsuru.live, 大部分规则设置将不可用 (因为我懒得在前段重写一遍逻辑">
|
||||||
|
<NButton @click="$router.push({ name: 'manage-index' })" type="primary"> 前往登录或注册 </NButton>
|
||||||
|
</NAlert>
|
||||||
|
<br />
|
||||||
|
<NCard size="small">
|
||||||
|
<NTooltip>
|
||||||
|
<template #trigger>
|
||||||
|
<NButton @click="showOBSModal = true" type="primary" :disabled="!accountInfo"> OBS 组件 </NButton>
|
||||||
|
</template>
|
||||||
|
{{ configCanEdit ? '' : '登陆后才可以使用此功能' }}
|
||||||
|
</NTooltip>
|
||||||
|
</NCard>
|
||||||
|
<br />
|
||||||
|
<NCard>
|
||||||
|
<NTabs v-if="!accountInfo || accountInfo.settings.enableFunctions.includes(FunctionTypes.SongRequest)" animated>
|
||||||
<NTabPane name="list" tab="列表">
|
<NTabPane name="list" tab="列表">
|
||||||
<NList> </NList>
|
<NCard size="small">
|
||||||
|
<NSpace align="center">
|
||||||
|
<NTag type="success" :bordered="false">
|
||||||
|
<template #icon>
|
||||||
|
<NIcon :component="PeopleQueue24Filled" />
|
||||||
|
</template>
|
||||||
|
队列 | {{ activeSongs.filter((s) => s.status == SongRequestStatus.Waiting).length }}
|
||||||
|
</NTag>
|
||||||
|
<NTag type="success" :bordered="false">
|
||||||
|
<template #icon>
|
||||||
|
<NIcon :component="PeopleQueue24Filled" />
|
||||||
|
</template>
|
||||||
|
今日已演唱 | {{ songs.filter((s) => s.status != SongRequestStatus.Cancel && isSameDay(s.finishAt ?? 0, Date.now())).length }} 首
|
||||||
|
</NTag>
|
||||||
|
<NInputGroup>
|
||||||
|
<NInput placeholder="手动添加" v-model:value="newSongName" />
|
||||||
|
<NButton type="primary" @click="addSongManual"> 添加 </NButton>
|
||||||
|
</NInputGroup>
|
||||||
|
<NPopconfirm @positive-click="deactiveAllSongs">
|
||||||
|
<template #trigger>
|
||||||
|
<NButton type="error"> 全部取消 </NButton>
|
||||||
|
</template>
|
||||||
|
确定全部取消吗?
|
||||||
|
</NPopconfirm>
|
||||||
|
</NSpace>
|
||||||
|
</NCard>
|
||||||
|
<NDivider> 共 {{ activeSongs.length }} 首 </NDivider>
|
||||||
|
<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%;`">
|
||||||
|
<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>
|
||||||
|
<NText strong style="font-size: 18px">
|
||||||
|
{{ song.songName }}
|
||||||
|
</NText>
|
||||||
|
<template v-if="song.from == SongRequestFrom.Manual">
|
||||||
|
<NTag size="small" :bordered="false"> 手动添加 </NTag>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<NTooltip>
|
||||||
|
<template #trigger>
|
||||||
|
<NTag size="small" :bordered="false" type="info">
|
||||||
|
<NText italic depth="3">
|
||||||
|
{{ song.user?.name }}
|
||||||
|
</NText>
|
||||||
|
</NTag>
|
||||||
|
</template>
|
||||||
|
{{ song.user?.uid }}
|
||||||
|
</NTooltip>
|
||||||
|
</template>
|
||||||
|
<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">
|
||||||
|
{{ song.user?.fans_medal_level }}
|
||||||
|
</NText>
|
||||||
|
</NTag>
|
||||||
|
<span style="color: #577fb8">
|
||||||
|
{{ song.user?.fans_medal_name }}
|
||||||
|
</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) }">
|
||||||
|
{{ 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.scPrice ?? 0) }"> SC | {{ song.scPrice }} </NTag>
|
||||||
|
<NTooltip>
|
||||||
|
<template #trigger>
|
||||||
|
<NText style="font-size: small">
|
||||||
|
<NTime :time="song.createAt" type="relative" :key="updateKey" />
|
||||||
|
</NText>
|
||||||
|
</template>
|
||||||
|
<NTime :time="song.createAt" />
|
||||||
|
</NTooltip>
|
||||||
|
</NSpace>
|
||||||
|
<NSpace justify="end" align="center">
|
||||||
|
<audio v-if="song.song" :src="song.song?.url" controls style="width: 300px; height: 30px; margin-bottom: -5px"></audio>
|
||||||
|
<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="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"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<NIcon :component="Mic24Filled" />
|
||||||
|
</template>
|
||||||
|
</NButton>
|
||||||
|
</template>
|
||||||
|
{{
|
||||||
|
songs.findIndex((s) => s.id != song.id && s.status == SongRequestStatus.Singing) > -1
|
||||||
|
? '还有其他正在演唱的歌曲'
|
||||||
|
: song.status == SongRequestStatus.Waiting && song.id
|
||||||
|
? '开始演唱'
|
||||||
|
: '停止演唱'
|
||||||
|
}}
|
||||||
|
</NTooltip>
|
||||||
|
<NTooltip>
|
||||||
|
<template #trigger>
|
||||||
|
<NButton circle type="success" style="height: 30px; width: 30px" :loading="isLoading" @click="updateSongStatus(song, SongRequestStatus.Finish)">
|
||||||
|
<template #icon>
|
||||||
|
<NIcon :component="Checkmark12Regular" />
|
||||||
|
</template>
|
||||||
|
</NButton>
|
||||||
|
</template>
|
||||||
|
已完成演唱
|
||||||
|
</NTooltip>
|
||||||
|
<NTooltip>
|
||||||
|
<template #trigger>
|
||||||
|
<NButton circle type="error" style="height: 30px; width: 30px" :loading="isLoading" @click="updateSongStatus(song, SongRequestStatus.Cancel)">
|
||||||
|
<template #icon>
|
||||||
|
<NIcon :component="Dismiss16Filled" />
|
||||||
|
</template>
|
||||||
|
</NButton>
|
||||||
|
</template>
|
||||||
|
移出队列
|
||||||
|
</NTooltip>
|
||||||
|
</NSpace>
|
||||||
|
</NSpace>
|
||||||
|
</NCard>
|
||||||
|
</NListItem>
|
||||||
|
</NList>
|
||||||
|
<NEmpty v-else description="暂无曲目" />
|
||||||
|
</NTabPane>
|
||||||
|
<NTabPane name="history" tab="历史">
|
||||||
|
<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">
|
||||||
|
<NDivider> 规则 </NDivider>
|
||||||
|
<NSpace vertical>
|
||||||
|
<NInputGroup style="width: 250px">
|
||||||
|
<NInputGroupLabel> 点歌弹幕前缀 </NInputGroupLabel>
|
||||||
|
<template v-if="configCanEdit">
|
||||||
|
<NInput v-model:value="settings.orderPrefix" />
|
||||||
|
<NButton @click="updateSettings" type="primary">确定</NButton>
|
||||||
|
</template>
|
||||||
|
<NInput v-else v-model:value="defaultPrefix" />
|
||||||
|
</NInputGroup>
|
||||||
|
|
||||||
|
<NInputGroup style="width: 250px">
|
||||||
|
<NInputGroupLabel> 最大队列长度 </NInputGroupLabel>
|
||||||
|
<NInputNumber v-model:value="settings.queueMaxSize" :disabled="!configCanEdit" />
|
||||||
|
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
||||||
|
</NInputGroup>
|
||||||
|
<NSpace align="center">
|
||||||
|
<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>
|
||||||
|
<NInputGroup v-if="settings.needWearFanMedal" style="width: 250px">
|
||||||
|
<NInputGroupLabel> 最低粉丝牌等级 </NInputGroupLabel>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
</template>
|
||||||
|
</NSpace>
|
||||||
|
<NSpace align="center">
|
||||||
|
<NCheckbox v-model:checked="settings.allowSC" @update:checked="updateSettings" :disabled="!configCanEdit"> 允许通过 SuperChat 点歌 </NCheckbox>
|
||||||
|
<span v-if="settings.allowSC">
|
||||||
|
<NCheckbox v-model:checked="settings.allowSC" @update:checked="updateSettings" :disabled="!configCanEdit"> SC点歌无视限制 </NCheckbox>
|
||||||
|
<NTooltip>
|
||||||
|
<template #trigger>
|
||||||
|
<NIcon :component="Info24Filled" />
|
||||||
|
</template>
|
||||||
|
包含冷却时间, 队列长度, 重复点歌等
|
||||||
|
</NTooltip>
|
||||||
|
</span>
|
||||||
|
<NInputGroup v-if="settings.allowSC" style="width: 250px">
|
||||||
|
<NInputGroupLabel> 最低SC价格 </NInputGroupLabel>
|
||||||
|
<NInputNumber v-model:value="settings.scMinPrice" :disabled="!configCanEdit" />
|
||||||
|
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
||||||
|
</NInputGroup>
|
||||||
|
</NSpace>
|
||||||
|
<NSpace>
|
||||||
|
<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>
|
||||||
|
</NSpace>
|
||||||
|
<NDivider> 冷却 (单位: 秒) </NDivider>
|
||||||
|
<NCheckbox v-model:checked="settings.enableCooldown" @update:checked="updateSettings" :disabled="!configCanEdit"> 启用点歌冷却 </NCheckbox>
|
||||||
|
<NSpace v-if="settings.enableCooldown">
|
||||||
|
<NInputGroup style="width: 250px">
|
||||||
|
<NInputGroupLabel> 普通弹幕 </NInputGroupLabel>
|
||||||
|
<NInputNumber v-model:value="settings.cooldownSecond" :disabled="!configCanEdit" />
|
||||||
|
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
||||||
|
</NInputGroup>
|
||||||
|
<NInputGroup style="width: 220px">
|
||||||
|
<NInputGroupLabel> 舰长 </NInputGroupLabel>
|
||||||
|
<NInputNumber v-model:value="settings.jianzhangCooldownSecond" :disabled="!configCanEdit" />
|
||||||
|
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
||||||
|
</NInputGroup>
|
||||||
|
<NInputGroup style="width: 220px">
|
||||||
|
<NInputGroupLabel> 提督 </NInputGroupLabel>
|
||||||
|
<NInputNumber v-model:value="settings.tiduCooldownSecond" :disabled="!configCanEdit" />
|
||||||
|
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
||||||
|
</NInputGroup>
|
||||||
|
<NInputGroup style="width: 220px">
|
||||||
|
<NInputGroupLabel> 总督 </NInputGroupLabel>
|
||||||
|
<NInputNumber v-model:value="settings.zongduCooldownSecond" :disabled="!configCanEdit" />
|
||||||
|
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
||||||
|
</NInputGroup>
|
||||||
|
</NSpace>
|
||||||
|
<NDivider> 其他 </NDivider>
|
||||||
|
<NCheckbox v-model:checked="isWarnMessageAutoClose"> 自动关闭点歌失败时的提示消息 </NCheckbox>
|
||||||
|
</NSpace>
|
||||||
|
</NSpin>
|
||||||
</NTabPane>
|
</NTabPane>
|
||||||
<NTabPane name="history" tab="历史"> </NTabPane>
|
|
||||||
</NTabs>
|
</NTabs>
|
||||||
|
</NCard>
|
||||||
|
<NModal v-model:show="showOBSModal" title="OBS组件" preset="card" style="width: 800px">
|
||||||
|
<NAlert title="这是什么? " type="info"> 将等待队列以及结果显示在OBS中 </NAlert>
|
||||||
|
<NDivider> 浏览 </NDivider>
|
||||||
|
<div style="height: 500px; width: 280px; position: relative; margin: 0 auto">
|
||||||
|
<SongRequestOBS :id="accountInfo?.id" />
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<NInput :value="'https://vtsuru.live/obs/song-request?id=' + accountInfo?.id" />
|
||||||
|
<NDivider />
|
||||||
|
<NCollapse>
|
||||||
|
<NCollapseItem title="使用说明">
|
||||||
|
<NUl>
|
||||||
|
<NLi>在 OBS 来源中添加源, 选择 浏览器</NLi>
|
||||||
|
<NLi>在 URL 栏填入上方链接</NLi>
|
||||||
|
<NLi>根据自己的需要调整宽度和高度 (这里是宽 280px 高 500px)</NLi>
|
||||||
|
<NLi>完事</NLi>
|
||||||
|
</NUl>
|
||||||
|
</NCollapseItem>
|
||||||
|
</NCollapse>
|
||||||
|
</NModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<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;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes animated-border-round {
|
||||||
|
0% {
|
||||||
|
box-shadow: 0 0 0px #589580;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 0 5px rgba(255, 255, 255, 0);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -333,7 +333,6 @@ onUnmounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NLayoutContent style="height: 100vh; padding: 20px">
|
|
||||||
<NResult v-if="!code && !accountInfo" status="403" title="403" description="该页面只能从幻星平台访问或者注册用户使用" />
|
<NResult v-if="!code && !accountInfo" status="403" title="403" description="该页面只能从幻星平台访问或者注册用户使用" />
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<NCard>
|
<NCard>
|
||||||
@@ -435,7 +434,17 @@ onUnmounted(() => {
|
|||||||
</NSpace>
|
</NSpace>
|
||||||
<NDivider style="margin: 20px 0 20px 0"> <template v-if="isStartLottery"> 进行抽取前需要先停止 </template> </NDivider>
|
<NDivider style="margin: 20px 0 20px 0"> <template v-if="isStartLottery"> 进行抽取前需要先停止 </template> </NDivider>
|
||||||
<NSpace justify="center">
|
<NSpace justify="center">
|
||||||
<NButton type="primary" secondary @click="startLottery" :loading="isLottering" :disabled="isStartLottery || isLotteried"> 进行抽取 </NButton>
|
<NButton
|
||||||
|
type="primary"
|
||||||
|
secondary
|
||||||
|
@click="startLottery"
|
||||||
|
:loading="isLottering"
|
||||||
|
:disabled="isStartLottery || isLotteried"
|
||||||
|
data-umami-event="Open-Live Use Lottery"
|
||||||
|
:data-umami-event-uid="client.roomAuthInfo.value?.anchor_info.uid"
|
||||||
|
>
|
||||||
|
进行抽取
|
||||||
|
</NButton>
|
||||||
<NButton type="info" secondary :disabled="isStartLottery || isLottering || !isLotteried" @click="reset"> 重置 </NButton>
|
<NButton type="info" secondary :disabled="isStartLottery || isLottering || !isLotteried" @click="reset"> 重置 </NButton>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
<NDivider style="margin: 10px 0 10px 0"> 共 {{ currentUsers?.length }} 人</NDivider>
|
<NDivider style="margin: 10px 0 10px 0"> 共 {{ currentUsers?.length }} 人</NDivider>
|
||||||
@@ -512,7 +521,7 @@ onUnmounted(() => {
|
|||||||
<NUl>
|
<NUl>
|
||||||
<NLi>在 OBS 来源中添加源, 选择 浏览器</NLi>
|
<NLi>在 OBS 来源中添加源, 选择 浏览器</NLi>
|
||||||
<NLi>在 URL 栏填入上方链接</NLi>
|
<NLi>在 URL 栏填入上方链接</NLi>
|
||||||
<NLi>根据自己的需要调整宽度和高度</NLi>
|
<NLi>根据自己的需要调整宽度和高度 (这里是宽 250px 高 400px)</NLi>
|
||||||
<NLi>完事</NLi>
|
<NLi>完事</NLi>
|
||||||
</NUl>
|
</NUl>
|
||||||
</NCollapseItem>
|
</NCollapseItem>
|
||||||
@@ -520,6 +529,4 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
<NDivider />
|
<NDivider />
|
||||||
</NModal>
|
</NModal>
|
||||||
</NLayoutContent>
|
|
||||||
</template>
|
</template>
|
||||||
@/data/DanmakuClient
|
|
||||||
|
|||||||
@@ -6,12 +6,7 @@ import svgLoader from 'vite-svg-loader'
|
|||||||
import mkcert from 'vite-plugin-mkcert'
|
import mkcert from 'vite-plugin-mkcert'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
server: {
|
plugins: [vue(), svgLoader()],
|
||||||
https: true, // 需要开启https服务
|
|
||||||
},
|
|
||||||
plugins: [vue(), svgLoader(), mkcert({
|
|
||||||
source: 'coding'
|
|
||||||
})],
|
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': path.resolve(__dirname, 'src'),
|
'@': path.resolve(__dirname, 'src'),
|
||||||
|
|||||||
373
yarn.lock
373
yarn.lock
@@ -16,9 +16,9 @@
|
|||||||
chalk "^2.4.2"
|
chalk "^2.4.2"
|
||||||
|
|
||||||
"@babel/eslint-parser@^7.21.3":
|
"@babel/eslint-parser@^7.21.3":
|
||||||
version "7.22.15"
|
version "7.23.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.22.15.tgz#263f059c476e29ca4972481a17b8b660cb025a34"
|
resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.23.3.tgz#7bf0db1c53b54da0c8a12627373554a0828479ca"
|
||||||
integrity sha512-yc8OOBIQk1EcRrpizuARSQS0TWAcOMpEJ1aafhNznaeYkeL+OhqnDObGFylB8ka8VFF/sZc+S4RzHyO+3LjQxg==
|
integrity sha512-9bTuNlyx7oSstodm1cR1bECj4fkiknsDa1YniISkJemMY3DGhJNYBECbe6QD/q54mp2J8VO66jW3/7uP//iFCw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1"
|
"@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1"
|
||||||
eslint-visitor-keys "^2.1.0"
|
eslint-visitor-keys "^2.1.0"
|
||||||
@@ -39,9 +39,9 @@
|
|||||||
js-tokens "^4.0.0"
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
"@babel/parser@^7.23.0":
|
"@babel/parser@^7.23.0":
|
||||||
version "7.23.0"
|
version "7.23.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.3.tgz#0ce0be31a4ca4f1884b5786057cadcb6c3be58f9"
|
||||||
integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
|
integrity sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==
|
||||||
|
|
||||||
"@babel/runtime@^7.21.0":
|
"@babel/runtime@^7.21.0":
|
||||||
version "7.23.2"
|
version "7.23.2"
|
||||||
@@ -183,14 +183,14 @@
|
|||||||
eslint-visitor-keys "^3.3.0"
|
eslint-visitor-keys "^3.3.0"
|
||||||
|
|
||||||
"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1":
|
"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1":
|
||||||
version "4.9.1"
|
version "4.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4"
|
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63"
|
||||||
integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==
|
integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==
|
||||||
|
|
||||||
"@eslint/eslintrc@^2.1.2":
|
"@eslint/eslintrc@^2.1.3":
|
||||||
version "2.1.2"
|
version "2.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396"
|
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.3.tgz#797470a75fe0fbd5a53350ee715e85e87baff22d"
|
||||||
integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==
|
integrity sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv "^6.12.4"
|
ajv "^6.12.4"
|
||||||
debug "^4.3.2"
|
debug "^4.3.2"
|
||||||
@@ -202,10 +202,10 @@
|
|||||||
minimatch "^3.1.2"
|
minimatch "^3.1.2"
|
||||||
strip-json-comments "^3.1.1"
|
strip-json-comments "^3.1.1"
|
||||||
|
|
||||||
"@eslint/js@8.52.0":
|
"@eslint/js@8.54.0":
|
||||||
version "8.52.0"
|
version "8.54.0"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.52.0.tgz#78fe5f117840f69dc4a353adf9b9cd926353378c"
|
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.54.0.tgz#4fab9a2ff7860082c304f750e94acd644cf984cf"
|
||||||
integrity sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==
|
integrity sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==
|
||||||
|
|
||||||
"@humanwhocodes/config-array@^0.11.13":
|
"@humanwhocodes/config-array@^0.11.13":
|
||||||
version "0.11.13"
|
version "0.11.13"
|
||||||
@@ -386,9 +386,9 @@
|
|||||||
integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==
|
integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==
|
||||||
|
|
||||||
"@types/json-schema@^7.0.9":
|
"@types/json-schema@^7.0.9":
|
||||||
version "7.0.14"
|
version "7.0.15"
|
||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.14.tgz#74a97a5573980802f32c8e47b663530ab3b6b7d1"
|
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
||||||
integrity sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==
|
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
||||||
|
|
||||||
"@types/json5@^0.0.29":
|
"@types/json5@^0.0.29":
|
||||||
version "0.0.29"
|
version "0.0.29"
|
||||||
@@ -396,43 +396,43 @@
|
|||||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||||
|
|
||||||
"@types/katex@^0.16.2":
|
"@types/katex@^0.16.2":
|
||||||
version "0.16.5"
|
version "0.16.6"
|
||||||
resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.16.5.tgz#76adc073ce58e860cb8c34b5673e1aea9a0172b0"
|
resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.16.6.tgz#6dd82f78a1a1d2eceeff6bb97ba98d7c062454cb"
|
||||||
integrity sha512-DD2Y3xMlTQvAnN6d8803xdgnOeYZ+HwMglb7/9YCf49J9RkJL53azf9qKa40MkEYhqVwxZ1GS2+VlShnz4Z1Bw==
|
integrity sha512-rZYO1HInM99rAFYNwGqbYPxHZHxu2IwZYKj4bJ4oh6edVrm1UId8mmbHIZLBtG253qU6y3piag0XYe/joNnwzQ==
|
||||||
|
|
||||||
"@types/lodash-es@^4.17.9":
|
"@types/lodash-es@^4.17.9":
|
||||||
version "4.17.10"
|
version "4.17.11"
|
||||||
resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.10.tgz#1b36a76ca9eda20c0263e19bbe1a3adb1b317707"
|
resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.11.tgz#6ff7878f90371256a6fed0b7b4707d5d940d945b"
|
||||||
integrity sha512-YJP+w/2khSBwbUSFdGsSqmDvmnN3cCKoPOL7Zjle6s30ZtemkkqhjVfFqGwPN7ASil5VyjE2GtyU/yqYY6mC0A==
|
integrity sha512-eCw8FYAWHt2DDl77s+AMLLzPn310LKohruumpucZI4oOFJkIgnlaJcy23OKMJxx4r9PeTF13Gv6w+jqjWQaYUg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/lodash" "*"
|
"@types/lodash" "*"
|
||||||
|
|
||||||
"@types/lodash@*", "@types/lodash@^4.14.198":
|
"@types/lodash@*", "@types/lodash@^4.14.198":
|
||||||
version "4.14.200"
|
version "4.14.201"
|
||||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.200.tgz#435b6035c7eba9cdf1e039af8212c9e9281e7149"
|
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.201.tgz#76f47cb63124e806824b6c18463daf3e1d480239"
|
||||||
integrity sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==
|
integrity sha512-y9euML0cim1JrykNxADLfaG0FgD1g/yTHwUs/Jg9ZIU7WKj2/4IW9Lbb1WZbvck78W/lfGXFfe+u2EGfIJXdLQ==
|
||||||
|
|
||||||
"@types/node@^20.2.5":
|
"@types/node@^20.2.5":
|
||||||
version "20.8.8"
|
version "20.9.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.8.tgz#adee050b422061ad5255fc38ff71b2bb96ea2a0e"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.2.tgz#002815c8e87fe0c9369121c78b52e800fadc0ac6"
|
||||||
integrity sha512-YRsdVxq6OaLfmR9Hy816IMp33xOBjfyOgUd77ehqg96CFywxAPbDbXvAsuN2KVg2HOT8Eh6uAfU+l4WffwPVrQ==
|
integrity sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types "~5.25.1"
|
undici-types "~5.26.4"
|
||||||
|
|
||||||
"@types/parse-json@^4.0.0":
|
"@types/parse-json@^4.0.0":
|
||||||
version "4.0.1"
|
version "4.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.1.tgz#27f7559836ad796cea31acb63163b203756a5b4e"
|
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239"
|
||||||
integrity sha512-3YmXzzPAdOTVljVMkTMBdBEvlOLg2cDQaDhnnhT3nT9uDbnJzjWhKlzb+desT12Y7tGqaN6d+AbozcKzyL36Ng==
|
integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==
|
||||||
|
|
||||||
"@types/semver@^7.3.12":
|
"@types/semver@^7.3.12":
|
||||||
version "7.5.4"
|
version "7.5.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.4.tgz#0a41252ad431c473158b22f9bfb9a63df7541cff"
|
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.5.tgz#deed5ab7019756c9c90ea86139106b0346223f35"
|
||||||
integrity sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==
|
integrity sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==
|
||||||
|
|
||||||
"@types/web-bluetooth@^0.0.18":
|
"@types/web-bluetooth@^0.0.20":
|
||||||
version "0.0.18"
|
version "0.0.20"
|
||||||
resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.18.tgz#74bd1c8fd3a2058cb6fc76b188fcded50a83d866"
|
resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz#f066abfcd1cbe66267cdbbf0de010d8a41b41597"
|
||||||
integrity sha512-v/ZHEj9xh82usl8LMR3GarzFY1IrbXJw5L4QfQhokjRV91q+SelFqxQWSep1ucXEZ22+dSTwLFkXeur25sPIbw==
|
integrity sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin@^5.4.0":
|
"@typescript-eslint/eslint-plugin@^5.4.0":
|
||||||
version "5.62.0"
|
version "5.62.0"
|
||||||
@@ -534,51 +534,51 @@
|
|||||||
integrity sha512-Iy1EUVRpX0WWxeu1VIReR1zsZLMc4fqpt223czR+Rpnrwu7pt46nbnC2ycO7ItI/uqDLJxnbcMC7FujKs9IfFA==
|
integrity sha512-Iy1EUVRpX0WWxeu1VIReR1zsZLMc4fqpt223czR+Rpnrwu7pt46nbnC2ycO7ItI/uqDLJxnbcMC7FujKs9IfFA==
|
||||||
|
|
||||||
"@vitejs/plugin-vue@^4.2.3":
|
"@vitejs/plugin-vue@^4.2.3":
|
||||||
version "4.4.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-4.4.0.tgz#8ae96573236cdb12de6850a6d929b5537ec85390"
|
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-4.5.0.tgz#b4569fcb1faac054eba4f5efc1aaf4d39f4379e5"
|
||||||
integrity sha512-xdguqb+VUwiRpSg+nsc2HtbAUSGak25DXYvpQQi4RVU1Xq1uworyoH/md9Rfd8zMmPR/pSghr309QNcftUVseg==
|
integrity sha512-a2WSpP8X8HTEww/U00bU4mX1QpLINNuz/2KMNpLsdu3BzOpak3AGI1CJYBTXcc4SPhaD0eNRUp7IyQK405L5dQ==
|
||||||
|
|
||||||
"@vue/compiler-core@3.3.7":
|
"@vue/compiler-core@3.3.8":
|
||||||
version "3.3.7"
|
version "3.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.3.7.tgz#865a5734c971686d9737d85a0c5a08de045b6162"
|
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.3.8.tgz#301bb60d0245265a88ed5b30e200fbf223acb313"
|
||||||
integrity sha512-pACdY6YnTNVLXsB86YD8OF9ihwpolzhhtdLVHhBL6do/ykr6kKXNYABRtNMGrsQXpEXXyAdwvWWkuTbs4MFtPQ==
|
integrity sha512-hN/NNBUECw8SusQvDSqqcVv6gWq8L6iAktUR0UF3vGu2OhzRqcOiAno0FmBJWwxhYEXRlQJT5XnoKsVq1WZx4g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/parser" "^7.23.0"
|
"@babel/parser" "^7.23.0"
|
||||||
"@vue/shared" "3.3.7"
|
"@vue/shared" "3.3.8"
|
||||||
estree-walker "^2.0.2"
|
estree-walker "^2.0.2"
|
||||||
source-map-js "^1.0.2"
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
"@vue/compiler-dom@3.3.7":
|
"@vue/compiler-dom@3.3.8":
|
||||||
version "3.3.7"
|
version "3.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.3.7.tgz#a245aa03f9bfcdb537a239bf02842072de0644c9"
|
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.3.8.tgz#09d832514b9b8d9415a3816b065d69dbefcc7e9b"
|
||||||
integrity sha512-0LwkyJjnUPssXv/d1vNJ0PKfBlDoQs7n81CbO6Q0zdL7H1EzqYRrTVXDqdBVqro0aJjo/FOa1qBAPVI4PGSHBw==
|
integrity sha512-+PPtv+p/nWDd0AvJu3w8HS0RIm/C6VGBIRe24b9hSyNWOAPEUosFZ5diwawwP8ip5sJ8n0Pe87TNNNHnvjs0FQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/compiler-core" "3.3.7"
|
"@vue/compiler-core" "3.3.8"
|
||||||
"@vue/shared" "3.3.7"
|
"@vue/shared" "3.3.8"
|
||||||
|
|
||||||
"@vue/compiler-sfc@3.3.7", "@vue/compiler-sfc@^3.2.20":
|
"@vue/compiler-sfc@3.3.8", "@vue/compiler-sfc@^3.2.20":
|
||||||
version "3.3.7"
|
version "3.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.3.7.tgz#219d04b3013c7b15fbc536e2279e07810b731cc2"
|
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.3.8.tgz#40b18e48aa00260950964d1d72157668521be0e1"
|
||||||
integrity sha512-7pfldWy/J75U/ZyYIXRVqvLRw3vmfxDo2YLMwVtWVNew8Sm8d6wodM+OYFq4ll/UxfqVr0XKiVwti32PCrruAw==
|
integrity sha512-WMzbUrlTjfYF8joyT84HfwwXo+8WPALuPxhy+BZ6R4Aafls+jDBnSz8PDz60uFhuqFbl3HxRfxvDzrUf3THwpA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/parser" "^7.23.0"
|
"@babel/parser" "^7.23.0"
|
||||||
"@vue/compiler-core" "3.3.7"
|
"@vue/compiler-core" "3.3.8"
|
||||||
"@vue/compiler-dom" "3.3.7"
|
"@vue/compiler-dom" "3.3.8"
|
||||||
"@vue/compiler-ssr" "3.3.7"
|
"@vue/compiler-ssr" "3.3.8"
|
||||||
"@vue/reactivity-transform" "3.3.7"
|
"@vue/reactivity-transform" "3.3.8"
|
||||||
"@vue/shared" "3.3.7"
|
"@vue/shared" "3.3.8"
|
||||||
estree-walker "^2.0.2"
|
estree-walker "^2.0.2"
|
||||||
magic-string "^0.30.5"
|
magic-string "^0.30.5"
|
||||||
postcss "^8.4.31"
|
postcss "^8.4.31"
|
||||||
source-map-js "^1.0.2"
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
"@vue/compiler-ssr@3.3.7":
|
"@vue/compiler-ssr@3.3.8":
|
||||||
version "3.3.7"
|
version "3.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.3.7.tgz#eff4a70f7ceb800d60e68d208b96a030c0f1b636"
|
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.3.8.tgz#136eed54411e4694815d961048a237191063fbce"
|
||||||
integrity sha512-TxOfNVVeH3zgBc82kcUv+emNHo+vKnlRrkv8YvQU5+Y5LJGJwSNzcmLUoxD/dNzv0bhQ/F0s+InlgV0NrApJZg==
|
integrity sha512-hXCqQL/15kMVDBuoBYpUnSYT8doDNwsjvm3jTefnXr+ytn294ySnT8NlsFHmTgKNjwpuFy7XVV8yTeLtNl/P6w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/compiler-dom" "3.3.7"
|
"@vue/compiler-dom" "3.3.8"
|
||||||
"@vue/shared" "3.3.7"
|
"@vue/shared" "3.3.8"
|
||||||
|
|
||||||
"@vue/devtools-api@^6.0.0-beta.11", "@vue/devtools-api@^6.5.0":
|
"@vue/devtools-api@^6.0.0-beta.11", "@vue/devtools-api@^6.5.0":
|
||||||
version "6.5.1"
|
version "6.5.1"
|
||||||
@@ -602,90 +602,90 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
vue-eslint-parser "^8.0.0"
|
vue-eslint-parser "^8.0.0"
|
||||||
|
|
||||||
"@vue/reactivity-transform@3.3.7":
|
"@vue/reactivity-transform@3.3.8":
|
||||||
version "3.3.7"
|
version "3.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.3.7.tgz#eb9f5110af5085079b851d162205394bc790d539"
|
resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.3.8.tgz#6d07649013b0be5c670f0ab6cc7ddd3150ad03f2"
|
||||||
integrity sha512-APhRmLVbgE1VPGtoLQoWBJEaQk4V8JUsqrQihImVqKT+8U6Qi3t5ATcg4Y9wGAPb3kIhetpufyZ1RhwbZCIdDA==
|
integrity sha512-49CvBzmZNtcHua0XJ7GdGifM8GOXoUMOX4dD40Y5DxI3R8OUhMlvf2nvgUAcPxaXiV5MQQ1Nwy09ADpnLQUqRw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/parser" "^7.23.0"
|
"@babel/parser" "^7.23.0"
|
||||||
"@vue/compiler-core" "3.3.7"
|
"@vue/compiler-core" "3.3.8"
|
||||||
"@vue/shared" "3.3.7"
|
"@vue/shared" "3.3.8"
|
||||||
estree-walker "^2.0.2"
|
estree-walker "^2.0.2"
|
||||||
magic-string "^0.30.5"
|
magic-string "^0.30.5"
|
||||||
|
|
||||||
"@vue/reactivity@3.3.7":
|
"@vue/reactivity@3.3.8":
|
||||||
version "3.3.7"
|
version "3.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.3.7.tgz#48b6671a45ba33039da2c0eb25ae702f924486a9"
|
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.3.8.tgz#cce8a03a3fd3539c3eeda53e277ba365d160dd4d"
|
||||||
integrity sha512-cZNVjWiw00708WqT0zRpyAgduG79dScKEPYJXq2xj/aMtk3SKvL3FBt2QKUlh6EHBJ1m8RhBY+ikBUzwc7/khg==
|
integrity sha512-ctLWitmFBu6mtddPyOKpHg8+5ahouoTCRtmAHZAXmolDtuZXfjL2T3OJ6DL6ezBPQB1SmMnpzjiWjCiMYmpIuw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/shared" "3.3.7"
|
"@vue/shared" "3.3.8"
|
||||||
|
|
||||||
"@vue/runtime-core@3.3.7":
|
"@vue/runtime-core@3.3.8":
|
||||||
version "3.3.7"
|
version "3.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.3.7.tgz#c1eece1c98f936dc69dd0667d11b464579b128fd"
|
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.3.8.tgz#fba5a632cbf2b5d29e171489570149cb6975dcdb"
|
||||||
integrity sha512-LHq9du3ubLZFdK/BP0Ysy3zhHqRfBn80Uc+T5Hz3maFJBGhci1MafccnL3rpd5/3wVfRHAe6c+PnlO2PAavPTQ==
|
integrity sha512-qurzOlb6q26KWQ/8IShHkMDOuJkQnQcTIp1sdP4I9MbCf9FJeGVRXJFr2mF+6bXh/3Zjr9TDgURXrsCr9bfjUw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/reactivity" "3.3.7"
|
"@vue/reactivity" "3.3.8"
|
||||||
"@vue/shared" "3.3.7"
|
"@vue/shared" "3.3.8"
|
||||||
|
|
||||||
"@vue/runtime-dom@3.3.7":
|
"@vue/runtime-dom@3.3.8":
|
||||||
version "3.3.7"
|
version "3.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.3.7.tgz#e7cf88cc01591fdf6e3164825554fdadc3137ffc"
|
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.3.8.tgz#e2d7aa795cf50914dda9a951887765a594b38af4"
|
||||||
integrity sha512-PFQU1oeJxikdDmrfoNQay5nD4tcPNYixUBruZzVX/l0eyZvFKElZUjW4KctCcs52nnpMGO6UDK+jF5oV4GT5Lw==
|
integrity sha512-Noy5yM5UIf9UeFoowBVgghyGGPIDPy1Qlqt0yVsUdAVbqI8eeMSsTqBtauaEoT2UFXUk5S64aWVNJN4MJ2vRdA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/runtime-core" "3.3.7"
|
"@vue/runtime-core" "3.3.8"
|
||||||
"@vue/shared" "3.3.7"
|
"@vue/shared" "3.3.8"
|
||||||
csstype "^3.1.2"
|
csstype "^3.1.2"
|
||||||
|
|
||||||
"@vue/server-renderer@3.3.7":
|
"@vue/server-renderer@3.3.8":
|
||||||
version "3.3.7"
|
version "3.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.3.7.tgz#0cc3dc6ad39a54693e6e8f853caa3c7bb43b0364"
|
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.3.8.tgz#9b1779010e75783edeed8fcfb97d9c95fc3ac5d2"
|
||||||
integrity sha512-UlpKDInd1hIZiNuVVVvLgxpfnSouxKQOSE2bOfQpBuGwxRV/JqqTCyyjXUWiwtVMyeRaZhOYYqntxElk8FhBhw==
|
integrity sha512-zVCUw7RFskvPuNlPn/8xISbrf0zTWsTSdYTsUTN1ERGGZGVnRxM2QZ3x1OR32+vwkkCm0IW6HmJ49IsPm7ilLg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/compiler-ssr" "3.3.7"
|
"@vue/compiler-ssr" "3.3.8"
|
||||||
"@vue/shared" "3.3.7"
|
"@vue/shared" "3.3.8"
|
||||||
|
|
||||||
"@vue/shared@3.3.7":
|
"@vue/shared@3.3.8":
|
||||||
version "3.3.7"
|
version "3.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.3.7.tgz#0091852fe5cc4237c8440fe32f3ab6bc920ae6d9"
|
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.3.8.tgz#f044942142e1d3a395f24132e6203a784838542d"
|
||||||
integrity sha512-N/tbkINRUDExgcPTBvxNkvHGu504k8lzlNQRITVnm6YjOjwa4r0nnbd4Jb01sNpur5hAllyRJzSK5PvB9PPwRg==
|
integrity sha512-8PGwybFwM4x8pcfgqEQFy70NaQxASvOC5DJwLQfpArw1UDfUXrJkdxD3BhVTMS+0Lef/TU7YO0Jvr0jJY8T+mw==
|
||||||
|
|
||||||
"@vueuse/core@10.5.0", "@vueuse/core@^10.1.2":
|
"@vueuse/core@10.6.1", "@vueuse/core@^10.1.2":
|
||||||
version "10.5.0"
|
version "10.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.5.0.tgz#04d1e6d26592bb997bb755a4830ea7583c3e8612"
|
resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.6.1.tgz#5b16d8238054c6983b6cb7cd77a78035f098dd89"
|
||||||
integrity sha512-z/tI2eSvxwLRjOhDm0h/SXAjNm8N5ld6/SC/JQs6o6kpJ6Ya50LnEL8g5hoYu005i28L0zqB5L5yAl8Jl26K3A==
|
integrity sha512-Pc26IJbqgC9VG1u6VY/xrXXfxD33hnvxBnKrLlA2LJlyHII+BSrRoTPJgGYq7qZOu61itITFUnm6QbacwZ4H8Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/web-bluetooth" "^0.0.18"
|
"@types/web-bluetooth" "^0.0.20"
|
||||||
"@vueuse/metadata" "10.5.0"
|
"@vueuse/metadata" "10.6.1"
|
||||||
"@vueuse/shared" "10.5.0"
|
"@vueuse/shared" "10.6.1"
|
||||||
vue-demi ">=0.14.6"
|
vue-demi ">=0.14.6"
|
||||||
|
|
||||||
"@vueuse/integrations@^10.1.2":
|
"@vueuse/integrations@^10.1.2":
|
||||||
version "10.5.0"
|
version "10.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vueuse/integrations/-/integrations-10.5.0.tgz#38f00bd5a1cd0160645f0c75efd5d9579061e3d6"
|
resolved "https://registry.yarnpkg.com/@vueuse/integrations/-/integrations-10.6.1.tgz#8358ced20d1a976422693ae3711ad29b70948504"
|
||||||
integrity sha512-fm5sXLCK0Ww3rRnzqnCQRmfjDURaI4xMsx+T+cec0ngQqHx/JgUtm8G0vRjwtonIeTBsH1Q8L3SucE+7K7upJQ==
|
integrity sha512-mPDupuofMJ4DPmtX/FfP1MajmWRzYDv8WSaTCo8LQ5kFznjWgmUQ16ApjYqgMquqffNY6+IRMdMgosLDRZOSZA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vueuse/core" "10.5.0"
|
"@vueuse/core" "10.6.1"
|
||||||
"@vueuse/shared" "10.5.0"
|
"@vueuse/shared" "10.6.1"
|
||||||
vue-demi ">=0.14.6"
|
vue-demi ">=0.14.6"
|
||||||
|
|
||||||
"@vueuse/metadata@10.5.0":
|
"@vueuse/metadata@10.6.1":
|
||||||
version "10.5.0"
|
version "10.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-10.5.0.tgz#7501a88cf5cbf7a515a03f0b8bbe3cecf30cad11"
|
resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-10.6.1.tgz#100faa0ced3c0ab4c014fb8e66e781e85e4eb88d"
|
||||||
integrity sha512-fEbElR+MaIYyCkeM0SzWkdoMtOpIwO72x8WsZHRE7IggiOlILttqttM69AS13nrDxosnDBYdyy3C5mR1LCxHsw==
|
integrity sha512-qhdwPI65Bgcj23e5lpGfQsxcy0bMjCAsUGoXkJ7DsoeDUdasbZ2DBa4dinFCOER3lF4gwUv+UD2AlA11zdzMFw==
|
||||||
|
|
||||||
"@vueuse/router@^10.1.2":
|
"@vueuse/router@^10.1.2":
|
||||||
version "10.5.0"
|
version "10.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vueuse/router/-/router-10.5.0.tgz#12f22e197abf833b9082f5d79d0916fd0a0e43a6"
|
resolved "https://registry.yarnpkg.com/@vueuse/router/-/router-10.6.1.tgz#34fccd572d4d679338415ec4b9ba4ce081615c1f"
|
||||||
integrity sha512-KboRSnSTaRBvKiwhCJ9RJHidaUMy5+5RyAwq46IPovVtKm9nIUfV0/F8dPwYx36rxAWn9iNWZUbKfu4cGW3XuA==
|
integrity sha512-9EMf30SownmxYKC3h36tl8uALSBGFkz3Dc2n+lQgJuyOYPIO/VotzDdkBxuEoHYKaCWw2JQa/S1q+t8NR26PvQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vueuse/shared" "10.5.0"
|
"@vueuse/shared" "10.6.1"
|
||||||
vue-demi ">=0.14.6"
|
vue-demi ">=0.14.6"
|
||||||
|
|
||||||
"@vueuse/shared@10.5.0":
|
"@vueuse/shared@10.6.1":
|
||||||
version "10.5.0"
|
version "10.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-10.5.0.tgz#b3ac8c190a5dae41db5e1b60fe304a9b4247393c"
|
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-10.6.1.tgz#1d9fc1e3f9083e45b59a693fc372bc50ad62a9e4"
|
||||||
integrity sha512-18iyxbbHYLst9MqU1X1QNdMHIjks6wC7XTVf0KNOv5es/Ms6gjVFCAAWTVP2JStuGqydg3DT+ExpFORUEi9yhg==
|
integrity sha512-TECVDTIedFlL0NUfHWncf3zF9Gc4VfdxfQc8JFwoVZQmxpONhLxFrlm0eHQeidHj4rdTPL3KXJa0TZCk1wnc5Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
vue-demi ">=0.14.6"
|
vue-demi ">=0.14.6"
|
||||||
|
|
||||||
@@ -695,9 +695,9 @@ acorn-jsx@^5.3.2:
|
|||||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||||
|
|
||||||
acorn@^8.9.0:
|
acorn@^8.9.0:
|
||||||
version "8.10.0"
|
version "8.11.2"
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b"
|
||||||
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
|
integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==
|
||||||
|
|
||||||
aggregate-error@^3.0.0:
|
aggregate-error@^3.0.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
@@ -864,9 +864,9 @@ available-typed-arrays@^1.0.5:
|
|||||||
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
|
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
|
||||||
|
|
||||||
axios@^1.2.2:
|
axios@^1.2.2:
|
||||||
version "1.6.0"
|
version "1.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102"
|
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2"
|
||||||
integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==
|
integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects "^1.15.0"
|
follow-redirects "^1.15.0"
|
||||||
form-data "^4.0.0"
|
form-data "^4.0.0"
|
||||||
@@ -1030,9 +1030,9 @@ cookie@^0.4.0:
|
|||||||
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
|
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
|
||||||
|
|
||||||
core-js@^3.8.3:
|
core-js@^3.8.3:
|
||||||
version "3.33.1"
|
version "3.33.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.33.1.tgz#ef3766cfa382482d0a2c2bc5cb52c6d88805da52"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.33.2.tgz#312bbf6996a3a517c04c99b9909cdd27138d1ceb"
|
||||||
integrity sha512-qVSq3s+d4+GsqN0teRCJtM6tdEEXyWxjzbhVrCHmBS5ZTM0FS2MOS0D13dUXAWDUN6a+lHI/N1hF9Ytz6iLl9Q==
|
integrity sha512-XeBzWI6QL3nJQiHmdzbAOiMYqjrb7hwU7A39Qhvd/POSa/t9E1AeZyEZx3fNvp/vtM8zXwhoL0FsiS0hD0pruQ==
|
||||||
|
|
||||||
cosmiconfig@^7.0.1:
|
cosmiconfig@^7.0.1:
|
||||||
version "7.1.0"
|
version "7.1.0"
|
||||||
@@ -1115,7 +1115,7 @@ cssesc@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
||||||
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
|
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
|
||||||
|
|
||||||
csso@^5.0.5:
|
csso@5.0.5:
|
||||||
version "5.0.5"
|
version "5.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6"
|
resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6"
|
||||||
integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==
|
integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==
|
||||||
@@ -1498,9 +1498,9 @@ eslint-plugin-prettier@^4.2.1:
|
|||||||
prettier-linter-helpers "^1.0.0"
|
prettier-linter-helpers "^1.0.0"
|
||||||
|
|
||||||
eslint-plugin-vue@^9.11.0:
|
eslint-plugin-vue@^9.11.0:
|
||||||
version "9.18.0"
|
version "9.18.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.18.0.tgz#2a2dbb3c67317e8c11ab56cafaa15a3a7eac6282"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.18.1.tgz#73cf29df7450ce5913296465f8d1dc545344920c"
|
||||||
integrity sha512-yUM8a2OD/7Qs0PiugkRaxgz5KBRvzMvWShity2UvVFAN0yk8029mGpTdg/TNARPiYzp335mEwDHwcAR8tQNe4g==
|
integrity sha512-7hZFlrEgg9NIzuVik2I9xSnJA5RsmOfueYgsUGUokEDLJ1LHtxO0Pl4duje1BriZ/jDWb+44tcIlC3yi0tdlZg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint-community/eslint-utils" "^4.4.0"
|
"@eslint-community/eslint-utils" "^4.4.0"
|
||||||
natural-compare "^1.4.0"
|
natural-compare "^1.4.0"
|
||||||
@@ -1546,14 +1546,14 @@ eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4
|
|||||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||||
|
|
||||||
eslint@^8.39.0:
|
eslint@^8.39.0:
|
||||||
version "8.52.0"
|
version "8.54.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.52.0.tgz#d0cd4a1fac06427a61ef9242b9353f36ea7062fc"
|
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.54.0.tgz#588e0dd4388af91a2e8fa37ea64924074c783537"
|
||||||
integrity sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==
|
integrity sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint-community/eslint-utils" "^4.2.0"
|
"@eslint-community/eslint-utils" "^4.2.0"
|
||||||
"@eslint-community/regexpp" "^4.6.1"
|
"@eslint-community/regexpp" "^4.6.1"
|
||||||
"@eslint/eslintrc" "^2.1.2"
|
"@eslint/eslintrc" "^2.1.3"
|
||||||
"@eslint/js" "8.52.0"
|
"@eslint/js" "8.54.0"
|
||||||
"@humanwhocodes/config-array" "^0.11.13"
|
"@humanwhocodes/config-array" "^0.11.13"
|
||||||
"@humanwhocodes/module-importer" "^1.0.1"
|
"@humanwhocodes/module-importer" "^1.0.1"
|
||||||
"@nodelib/fs.walk" "^1.2.8"
|
"@nodelib/fs.walk" "^1.2.8"
|
||||||
@@ -1663,9 +1663,9 @@ fast-diff@^1.1.2:
|
|||||||
integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==
|
integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==
|
||||||
|
|
||||||
fast-glob@^3.2.9:
|
fast-glob@^3.2.9:
|
||||||
version "3.3.1"
|
version "3.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4"
|
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
|
||||||
integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==
|
integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nodelib/fs.stat" "^2.0.2"
|
"@nodelib/fs.stat" "^2.0.2"
|
||||||
"@nodelib/fs.walk" "^1.2.3"
|
"@nodelib/fs.walk" "^1.2.3"
|
||||||
@@ -1723,9 +1723,9 @@ find-up@^5.0.0:
|
|||||||
path-exists "^4.0.0"
|
path-exists "^4.0.0"
|
||||||
|
|
||||||
flat-cache@^3.0.4:
|
flat-cache@^3.0.4:
|
||||||
version "3.1.1"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.1.tgz#a02a15fdec25a8f844ff7cc658f03dd99eb4609b"
|
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee"
|
||||||
integrity sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==
|
integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==
|
||||||
dependencies:
|
dependencies:
|
||||||
flatted "^3.2.9"
|
flatted "^3.2.9"
|
||||||
keyv "^4.5.3"
|
keyv "^4.5.3"
|
||||||
@@ -1959,9 +1959,9 @@ human-signals@^2.1.0:
|
|||||||
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
|
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
|
||||||
|
|
||||||
ignore@^5.2.0:
|
ignore@^5.2.0:
|
||||||
version "5.2.4"
|
version "5.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78"
|
||||||
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
|
integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==
|
||||||
|
|
||||||
import-fresh@^3.2.1:
|
import-fresh@^3.2.1:
|
||||||
version "3.3.0"
|
version "3.3.0"
|
||||||
@@ -2438,9 +2438,9 @@ naive-ui@^2.34.3:
|
|||||||
vueuc "^0.4.51"
|
vueuc "^0.4.51"
|
||||||
|
|
||||||
nanoid@^3.3.6:
|
nanoid@^3.3.6:
|
||||||
version "3.3.6"
|
version "3.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||||
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
|
||||||
|
|
||||||
natural-compare-lite@^1.4.0:
|
natural-compare-lite@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
@@ -2681,9 +2681,9 @@ proxy-from-env@^1.1.0:
|
|||||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||||
|
|
||||||
punycode@^2.1.0:
|
punycode@^2.1.0:
|
||||||
version "2.3.0"
|
version "2.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
|
||||||
integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
|
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
|
||||||
|
|
||||||
qrcode.vue@^3.4.1:
|
qrcode.vue@^3.4.1:
|
||||||
version "3.4.1"
|
version "3.4.1"
|
||||||
@@ -3043,15 +3043,16 @@ supports-preserve-symlinks-flag@^1.0.0:
|
|||||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||||
|
|
||||||
svgo@^3.0.2:
|
svgo@^3.0.2:
|
||||||
version "3.0.2"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.0.2.tgz#5e99eeea42c68ee0dc46aa16da093838c262fe0a"
|
resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.0.4.tgz#67b40a710743e358e8d19ec288de8f1e388afbb4"
|
||||||
integrity sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==
|
integrity sha512-T+Xul3JwuJ6VGXKo/p2ndqx1ibxNKnLTvRc1ZTWKCfyKS/GgNjRZcYsK84fxTsy/izr91g/Rwx6fGnVgaFSI5g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@trysound/sax" "0.2.0"
|
"@trysound/sax" "0.2.0"
|
||||||
commander "^7.2.0"
|
commander "^7.2.0"
|
||||||
css-select "^5.1.0"
|
css-select "^5.1.0"
|
||||||
css-tree "^2.2.1"
|
css-tree "^2.2.1"
|
||||||
csso "^5.0.5"
|
css-what "^6.1.0"
|
||||||
|
csso "5.0.5"
|
||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
|
|
||||||
tapable@^0.1.8:
|
tapable@^0.1.8:
|
||||||
@@ -3196,10 +3197,10 @@ unbox-primitive@^1.0.2:
|
|||||||
has-symbols "^1.0.3"
|
has-symbols "^1.0.3"
|
||||||
which-boxed-primitive "^1.0.2"
|
which-boxed-primitive "^1.0.2"
|
||||||
|
|
||||||
undici-types@~5.25.1:
|
undici-types@~5.26.4:
|
||||||
version "5.25.3"
|
version "5.26.5"
|
||||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.25.3.tgz#e044115914c85f0bcbb229f346ab739f064998c3"
|
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||||
integrity sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==
|
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||||
|
|
||||||
universal-cookie@^4.0.4:
|
universal-cookie@^4.0.4:
|
||||||
version "4.0.4"
|
version "4.0.4"
|
||||||
@@ -3210,9 +3211,9 @@ universal-cookie@^4.0.4:
|
|||||||
cookie "^0.4.0"
|
cookie "^0.4.0"
|
||||||
|
|
||||||
universal-user-agent@^6.0.0:
|
universal-user-agent@^6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
|
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.1.tgz#15f20f55da3c930c57bddbf1734c6654d5fd35aa"
|
||||||
integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==
|
integrity sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==
|
||||||
|
|
||||||
uri-js@^4.2.2:
|
uri-js@^4.2.2:
|
||||||
version "4.4.1"
|
version "4.4.1"
|
||||||
@@ -3349,11 +3350,9 @@ vue-router@4:
|
|||||||
"@vue/devtools-api" "^6.5.0"
|
"@vue/devtools-api" "^6.5.0"
|
||||||
|
|
||||||
vue-turnstile@^1.0.0:
|
vue-turnstile@^1.0.0:
|
||||||
version "1.0.4"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/vue-turnstile/-/vue-turnstile-1.0.4.tgz#c6dabdd33ccf96e8450a460b8d84922a75392948"
|
resolved "https://registry.yarnpkg.com/vue-turnstile/-/vue-turnstile-1.0.5.tgz#63e3905fc5a5ad199fa5224235a5b7807e7da454"
|
||||||
integrity sha512-yv6bMFLvw1OR+yvHkjxsIDWplGwlhK29WVAyaP8mQ8x3XvjotWFByIxRTeZldC+grTpCUEe0r3dDPNmczXqRtw==
|
integrity sha512-ayXZGL4aWeBOERPXS2Ufwkni1tJKNSUL3y+9bwDChyQHTJaqXBqWVnrgb+sL5ilnYnphnoBVqvGTmFjGzj6ZjQ==
|
||||||
dependencies:
|
|
||||||
vue "^3.2.45"
|
|
||||||
|
|
||||||
vue3-aplayer@^1.7.3:
|
vue3-aplayer@^1.7.3:
|
||||||
version "1.7.3"
|
version "1.7.3"
|
||||||
@@ -3367,16 +3366,16 @@ vue3-marquee@^4.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/vue3-marquee/-/vue3-marquee-4.1.0.tgz#145baa65dd40059358e4079d51ab596c2ccf1299"
|
resolved "https://registry.yarnpkg.com/vue3-marquee/-/vue3-marquee-4.1.0.tgz#145baa65dd40059358e4079d51ab596c2ccf1299"
|
||||||
integrity sha512-AkvpNC6+7CwvIBgiAr8qMs1XvhGhfSS2ahlMEp80YXAmDOP8nDdn/smQ6eWtusf+hLX21yTaSOoKGcill4bCRg==
|
integrity sha512-AkvpNC6+7CwvIBgiAr8qMs1XvhGhfSS2ahlMEp80YXAmDOP8nDdn/smQ6eWtusf+hLX21yTaSOoKGcill4bCRg==
|
||||||
|
|
||||||
vue@^3.2.13, vue@^3.2.45:
|
vue@^3.2.13:
|
||||||
version "3.3.7"
|
version "3.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/vue/-/vue-3.3.7.tgz#972a218682443a3819d121261b2bff914417f4f0"
|
resolved "https://registry.yarnpkg.com/vue/-/vue-3.3.8.tgz#532ff071af24f6a69e5ecc53a66858a9ee874ffc"
|
||||||
integrity sha512-YEMDia1ZTv1TeBbnu6VybatmSteGOS3A3YgfINOfraCbf85wdKHzscD6HSS/vB4GAtI7sa1XPX7HcQaJ1l24zA==
|
integrity sha512-5VSX/3DabBikOXMsxzlW8JyfeLKlG9mzqnWgLQLty88vdZL7ZJgrdgBOmrArwxiLtmS+lNNpPcBYqrhE6TQW5w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/compiler-dom" "3.3.7"
|
"@vue/compiler-dom" "3.3.8"
|
||||||
"@vue/compiler-sfc" "3.3.7"
|
"@vue/compiler-sfc" "3.3.8"
|
||||||
"@vue/runtime-dom" "3.3.7"
|
"@vue/runtime-dom" "3.3.8"
|
||||||
"@vue/server-renderer" "3.3.7"
|
"@vue/server-renderer" "3.3.8"
|
||||||
"@vue/shared" "3.3.7"
|
"@vue/shared" "3.3.8"
|
||||||
|
|
||||||
vueuc@^0.4.51:
|
vueuc@^0.4.51:
|
||||||
version "0.4.51"
|
version "0.4.51"
|
||||||
|
|||||||
Reference in New Issue
Block a user