mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-07 02:46:55 +08:00
update url, improve queue and songrequest
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { ACCOUNT_API_URL, BASE_API } from '@/data/constants'
|
import { ACCOUNT_API_URL, BASE_API } from '@/data/constants'
|
||||||
import { APIRoot, AccountInfo, FunctionTypes } from './api-models'
|
import { APIRoot, AccountInfo, FunctionTypes } from './api-models'
|
||||||
import { QueryPostAPI } from '@/api/query'
|
import { QueryGetAPI, QueryPostAPI } from '@/api/query'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useLocalStorage } from '@vueuse/core'
|
import { useLocalStorage } from '@vueuse/core'
|
||||||
import { createDiscreteApi } from 'naive-ui'
|
import { createDiscreteApi } from 'naive-ui'
|
||||||
@@ -19,7 +19,7 @@ export async function GetSelfAccount() {
|
|||||||
if (result.code == 200) {
|
if (result.code == 200) {
|
||||||
ACCOUNT.value = result.data
|
ACCOUNT.value = result.data
|
||||||
isLoadingAccount.value = false
|
isLoadingAccount.value = false
|
||||||
console.log('[vtsuru] 已获取账户信息')
|
//console.log('[vtsuru] 已获取账户信息')
|
||||||
if (!isSameDay(new Date(), cookieRefreshDate.value)) {
|
if (!isSameDay(new Date(), cookieRefreshDate.value)) {
|
||||||
refreshCookie()
|
refreshCookie()
|
||||||
}
|
}
|
||||||
@@ -38,8 +38,15 @@ export async function GetSelfAccount() {
|
|||||||
}
|
}
|
||||||
isLoadingAccount.value = false
|
isLoadingAccount.value = false
|
||||||
}
|
}
|
||||||
|
export function UpdateAccountLoop() {
|
||||||
|
setInterval(() => {
|
||||||
|
if (ACCOUNT.value) {
|
||||||
|
GetSelfAccount()
|
||||||
|
}
|
||||||
|
}, 60 * 1000)
|
||||||
|
}
|
||||||
function refreshCookie() {
|
function refreshCookie() {
|
||||||
QueryPostAPI<string>(`${ACCOUNT_API_URL()}refresh-token`).then((data) => {
|
QueryPostAPI<string>(`${ACCOUNT_API_URL}refresh-token`).then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
cookie.value = data.data
|
cookie.value = data.data
|
||||||
cookieRefreshDate.value = Date.now()
|
cookieRefreshDate.value = Date.now()
|
||||||
@@ -48,17 +55,17 @@ function refreshCookie() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
export async function SaveAccountSettings() {
|
export async function SaveAccountSettings() {
|
||||||
return await QueryPostAPI(ACCOUNT_API_URL() + 'update-setting', ACCOUNT.value?.settings)
|
return await QueryPostAPI(ACCOUNT_API_URL + 'update-setting', ACCOUNT.value?.settings)
|
||||||
}
|
}
|
||||||
export async function SaveEnableFunctions(functions: FunctionTypes[]) {
|
export async function SaveEnableFunctions(functions: FunctionTypes[]) {
|
||||||
return await QueryPostAPI(ACCOUNT_API_URL() + 'update-enable-functions', functions)
|
return await QueryPostAPI(ACCOUNT_API_URL + 'update-enable-functions', functions)
|
||||||
}
|
}
|
||||||
export function useAccount() {
|
export function useAccount() {
|
||||||
return ACCOUNT
|
return ACCOUNT
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function Register(name: string, email: string, password: string, token: string): Promise<APIRoot<string>> {
|
export async function Register(name: string, email: string, password: string, token: string): Promise<APIRoot<string>> {
|
||||||
return QueryPostAPI<string>(`${ACCOUNT_API_URL()}register`, {
|
return QueryPostAPI<string>(`${ACCOUNT_API_URL}register`, {
|
||||||
name,
|
name,
|
||||||
email,
|
email,
|
||||||
password,
|
password,
|
||||||
@@ -67,11 +74,22 @@ export async function Register(name: string, email: string, password: string, to
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function Login(nameOrEmail: string, password: string): Promise<APIRoot<string>> {
|
export async function Login(nameOrEmail: string, password: string): Promise<APIRoot<string>> {
|
||||||
return QueryPostAPI<string>(`${ACCOUNT_API_URL()}login`, {
|
return QueryPostAPI<string>(`${ACCOUNT_API_URL}login`, {
|
||||||
nameOrEmail,
|
nameOrEmail,
|
||||||
password,
|
password,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export async function Self(): Promise<APIRoot<AccountInfo>> {
|
export async function Self(): Promise<APIRoot<AccountInfo>> {
|
||||||
return QueryPostAPI<AccountInfo>(`${ACCOUNT_API_URL()}self`)
|
return QueryPostAPI<AccountInfo>(`${ACCOUNT_API_URL}self`)
|
||||||
|
}
|
||||||
|
export async function AddBiliBlackList(id: number, name: string): Promise<APIRoot<unknown>> {
|
||||||
|
return QueryGetAPI<AccountInfo>(`${ACCOUNT_API_URL}black-list/add-bili`, {
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export async function DelBiliBlackList(id: number): Promise<APIRoot<unknown>> {
|
||||||
|
return QueryGetAPI<AccountInfo>(`${ACCOUNT_API_URL}black-list/del-bili`, {
|
||||||
|
id: id,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,28 @@ export interface AccountInfo extends UserInfo {
|
|||||||
eventFetcherStatus: string
|
eventFetcherStatus: string
|
||||||
|
|
||||||
nextSendEmailTime?: number
|
nextSendEmailTime?: number
|
||||||
isServerFetcherOnline:boolean
|
isServerFetcherOnline: boolean
|
||||||
|
blackList: number[]
|
||||||
|
biliBlackList: { [key: number]: string }
|
||||||
|
streamerInfo?: StreamerModel
|
||||||
|
}
|
||||||
|
export interface StreamerModel{
|
||||||
|
name: string;
|
||||||
|
uId: number;
|
||||||
|
roomId: number;
|
||||||
|
faceUrl: string;
|
||||||
|
title: string;
|
||||||
|
coverUrl: string;
|
||||||
|
frameUrl: string;
|
||||||
|
area: string;
|
||||||
|
parentArea: string;
|
||||||
|
lastStreamAt: number;
|
||||||
|
totalDanmakuCount: number;
|
||||||
|
totalIncome: number;
|
||||||
|
totalStreamCount: number;
|
||||||
|
totalStreamTime: number;
|
||||||
|
lastDanmakuCount: number;
|
||||||
|
isStreaming: boolean;
|
||||||
}
|
}
|
||||||
export enum BiliAuthCodeStatusType {
|
export enum BiliAuthCodeStatusType {
|
||||||
NotBind,
|
NotBind,
|
||||||
@@ -72,6 +93,7 @@ export interface UserSetting {
|
|||||||
}
|
}
|
||||||
export interface Setting_SongRequest {
|
export interface Setting_SongRequest {
|
||||||
orderPrefix: string
|
orderPrefix: string
|
||||||
|
enableOnStreaming: boolean
|
||||||
onlyAllowSongList: boolean
|
onlyAllowSongList: boolean
|
||||||
queueMaxSize: number
|
queueMaxSize: number
|
||||||
allowAllDanmaku: boolean
|
allowAllDanmaku: boolean
|
||||||
@@ -90,9 +112,12 @@ export interface Setting_SongRequest {
|
|||||||
zongduCooldownSecond: number
|
zongduCooldownSecond: number
|
||||||
tiduCooldownSecond: number
|
tiduCooldownSecond: number
|
||||||
jianzhangCooldownSecond: number
|
jianzhangCooldownSecond: number
|
||||||
|
|
||||||
|
showRequireInfo: boolean
|
||||||
}
|
}
|
||||||
export interface Setting_Queue {
|
export interface Setting_Queue {
|
||||||
keyword: string
|
keyword: string
|
||||||
|
enableOnStreaming: boolean
|
||||||
matchType: KeywordMatchType
|
matchType: KeywordMatchType
|
||||||
sortType?: QueueSortType
|
sortType?: QueueSortType
|
||||||
queueMaxSize: number
|
queueMaxSize: number
|
||||||
@@ -116,6 +141,8 @@ export interface Setting_Queue {
|
|||||||
zongduCooldownSecond: number
|
zongduCooldownSecond: number
|
||||||
tiduCooldownSecond: number
|
tiduCooldownSecond: number
|
||||||
jianzhangCooldownSecond: number
|
jianzhangCooldownSecond: number
|
||||||
|
|
||||||
|
showRequireInfo: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum KeywordMatchType {
|
export enum KeywordMatchType {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export async function useUser(id: string | undefined = undefined) {
|
|||||||
}
|
}
|
||||||
export async function useUserWithUId(id: number) {
|
export async function useUserWithUId(id: number) {
|
||||||
if (!USERS.value[id.toString()]) {
|
if (!USERS.value[id.toString()]) {
|
||||||
const result = await QueryGetAPI<UserInfo>(`${USER_API_URL()}info`, {
|
const result = await QueryGetAPI<UserInfo>(`${USER_API_URL}info`, {
|
||||||
uId: id,
|
uId: id,
|
||||||
})
|
})
|
||||||
if (result.code == 200) {
|
if (result.code == 200) {
|
||||||
@@ -41,7 +41,7 @@ export async function useUserWithUId(id: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function GetInfo(id: string): Promise<APIRoot<UserInfo>> {
|
export async function GetInfo(id: string): Promise<APIRoot<UserInfo>> {
|
||||||
return QueryGetAPI<UserInfo>(`${USER_API_URL()}info`, {
|
return QueryGetAPI<UserInfo>(`${USER_API_URL}info`, {
|
||||||
id: id,
|
id: id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ function onLoginButtonClick() {
|
|||||||
await QueryPostAPI<{
|
await QueryPostAPI<{
|
||||||
account: AccountInfo
|
account: AccountInfo
|
||||||
token: string
|
token: string
|
||||||
}>(ACCOUNT_API_URL() + 'login', {
|
}>(ACCOUNT_API_URL + 'login', {
|
||||||
nameOrEmail: loginModel.value.account,
|
nameOrEmail: loginModel.value.account,
|
||||||
password: loginModel.value.password,
|
password: loginModel.value.password,
|
||||||
})
|
})
|
||||||
@@ -180,7 +180,7 @@ function onLoginButtonClick() {
|
|||||||
}
|
}
|
||||||
async function onForgetPassword() {
|
async function onForgetPassword() {
|
||||||
canSendForgetPassword.value = false
|
canSendForgetPassword.value = false
|
||||||
await QueryGetAPI(ACCOUNT_API_URL() + 'reset-password', { email: inputForgetPasswordValue.value }, [['Turnstile', token.value]])
|
await QueryGetAPI(ACCOUNT_API_URL + 'reset-password', { email: inputForgetPasswordValue.value }, [['Turnstile', token.value]])
|
||||||
.then(async (data) => {
|
.then(async (data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('已发送密码重置链接到你的邮箱, 请检查')
|
message.success('已发送密码重置链接到你的邮箱, 请检查')
|
||||||
|
|||||||
@@ -393,7 +393,7 @@ function renderCell(value: string | number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function updateSong() {
|
async function updateSong() {
|
||||||
await QueryPostAPI<SongsInfo>(SONG_API_URL() + 'update', {
|
await QueryPostAPI<SongsInfo>(SONG_API_URL + 'update', {
|
||||||
key: updateSongModel.value.key,
|
key: updateSongModel.value.key,
|
||||||
song: updateSongModel.value,
|
song: updateSongModel.value,
|
||||||
}).then((data) => {
|
}).then((data) => {
|
||||||
@@ -407,7 +407,7 @@ async function updateSong() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
async function delSong(song: SongsInfo) {
|
async function delSong(song: SongsInfo) {
|
||||||
await QueryGetAPI<SongsInfo>(SONG_API_URL() + 'del', {
|
await QueryGetAPI<SongsInfo>(SONG_API_URL + 'del', {
|
||||||
key: song.key,
|
key: song.key,
|
||||||
}).then((data) => {
|
}).then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ function OnPlayMusic(song: SongsInfo) {
|
|||||||
}
|
}
|
||||||
async function GetLyric(song: SongsInfo) {
|
async function GetLyric(song: SongsInfo) {
|
||||||
emits('update:isLrcLoading', song.key)
|
emits('update:isLrcLoading', song.key)
|
||||||
QueryGetAPI<{ lyric: string; tlyric: string }>(SONG_API_URL() + 'get-netease-lyric', { id: song.id })
|
QueryGetAPI<{ lyric: string; tlyric: string }>(SONG_API_URL + 'get-netease-lyric', { id: song.id })
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
console.log(mergeLyrics(data.data.lyric, data.data.tlyric))
|
console.log(mergeLyrics(data.data.lyric, data.data.tlyric))
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ export default class DanmakuClient {
|
|||||||
}
|
}
|
||||||
private sendHeartbeat() {
|
private sendHeartbeat() {
|
||||||
if (this.client) {
|
if (this.client) {
|
||||||
const query = this.authInfo ? QueryPostAPI<OpenLiveInfo>(OPEN_LIVE_API_URL() + 'heartbeat', this.authInfo) : QueryGetAPI<OpenLiveInfo>(OPEN_LIVE_API_URL() + 'heartbeat-internal')
|
const query = this.authInfo ? QueryPostAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'heartbeat', this.authInfo) : QueryGetAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'heartbeat-internal')
|
||||||
query.then((data) => {
|
query.then((data) => {
|
||||||
if (data.code != 200) {
|
if (data.code != 200) {
|
||||||
console.error('[OPEN-LIVE] 心跳失败')
|
console.error('[OPEN-LIVE] 心跳失败')
|
||||||
@@ -267,7 +267,7 @@ export default class DanmakuClient {
|
|||||||
}
|
}
|
||||||
private async getAuthInfo(): Promise<{ data: OpenLiveInfo | null; message: string }> {
|
private async getAuthInfo(): Promise<{ data: OpenLiveInfo | null; message: string }> {
|
||||||
try {
|
try {
|
||||||
const data = await QueryPostAPI<OpenLiveInfo>(OPEN_LIVE_API_URL() + 'start', this.authInfo?.Code ? this.authInfo : undefined)
|
const data = await QueryPostAPI<OpenLiveInfo>(OPEN_LIVE_API_URL + 'start', this.authInfo?.Code ? this.authInfo : undefined)
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
console.log('[OPEN-LIVE] 已获取场次信息')
|
console.log('[OPEN-LIVE] 已获取场次信息')
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -14,22 +14,22 @@ export const FETCH_API = 'https://fetch.vtsuru.live/'
|
|||||||
|
|
||||||
export const TURNSTILE_KEY = '0x4AAAAAAAETUSAKbds019h0'
|
export const TURNSTILE_KEY = '0x4AAAAAAAETUSAKbds019h0'
|
||||||
|
|
||||||
export const USER_API_URL = () => `${BASE_API()}user/`
|
export const USER_API_URL = { toString: () => `${BASE_API()}user/` }
|
||||||
export const ACCOUNT_API_URL = () => `${BASE_API()}account/`
|
export const ACCOUNT_API_URL = { toString: () => `${BASE_API()}account/` }
|
||||||
export const BILI_API_URL = () => `${BASE_API()}bili/`
|
export const BILI_API_URL = { toString: () => `${BASE_API()}bili/` }
|
||||||
export const SONG_API_URL = () => `${BASE_API()}song-list/`
|
export const SONG_API_URL = { toString: () => `${BASE_API()}song-list/` }
|
||||||
export const NOTIFACTION_API_URL = () => `${BASE_API()}notifaction/`
|
export const NOTIFACTION_API_URL = { toString: () => `${BASE_API()}notifaction/` }
|
||||||
export const QUESTION_API_URL = () => `${BASE_API()}qa/`
|
export const QUESTION_API_URL = { toString: () => `${BASE_API()}qa/` }
|
||||||
export const LOTTERY_API_URL = () => `${BASE_API()}lottery/`
|
export const LOTTERY_API_URL = { toString: () => `${BASE_API()}lottery/` }
|
||||||
export const HISTORY_API_URL = () => `${BASE_API()}history/`
|
export const HISTORY_API_URL = { toString: () => `${BASE_API()}history/` }
|
||||||
export const SCHEDULE_API_URL = () => `${BASE_API()}schedule/`
|
export const SCHEDULE_API_URL = { toString: () => `${BASE_API()}schedule/` }
|
||||||
export const VIDEO_COLLECT_API_URL = () => `${BASE_API()}video-collect/`
|
export const VIDEO_COLLECT_API_URL = { toString: () => `${BASE_API()}video-collect/` }
|
||||||
export const OPEN_LIVE_API_URL = () => `${BASE_API()}open-live/`
|
export const OPEN_LIVE_API_URL = { toString: () => `${BASE_API()}open-live/` }
|
||||||
export const SONG_REQUEST_API_URL = () => `${BASE_API()}song-request/`
|
export const SONG_REQUEST_API_URL = { toString: () => `${BASE_API()}song-request/` }
|
||||||
export const QUEUE_API_URL = () => `${BASE_API()}queue/`
|
export const QUEUE_API_URL = { toString: () => `${BASE_API()}queue/` }
|
||||||
export const EVENT_API_URL = () => `${BASE_API()}event/`
|
export const EVENT_API_URL = { toString: () => `${BASE_API()}event/` }
|
||||||
export const LIVE_API_URL = () => `${BASE_API()}live/`
|
export const LIVE_API_URL = { toString: () => `${BASE_API()}live/` }
|
||||||
export const FEEDBACK_API_URL = () => `${BASE_API()}feedback/`
|
export const FEEDBACK_API_URL = { toString: () => `${BASE_API()}feedback/` }
|
||||||
|
|
||||||
export const ScheduleTemplateMap = {
|
export const ScheduleTemplateMap = {
|
||||||
'': { name: '默认', compoent: defineAsyncComponent(() => import('@/views/view/scheduleTemplate/DefaultScheduleTemplate.vue')) },
|
'': { name: '默认', compoent: defineAsyncComponent(() => import('@/views/view/scheduleTemplate/DefaultScheduleTemplate.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>(SONG_REQUEST_API_URL() + 'get-active')
|
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
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { BASE_API, apiFail } from '@/data/constants'
|
|||||||
import { createApp, h } from 'vue'
|
import { createApp, h } from 'vue'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import { GetSelfAccount } from './api/account'
|
import { GetSelfAccount, UpdateAccountLoop } from './api/account'
|
||||||
import { GetNotifactions } from './data/notifactions'
|
import { GetNotifactions } from './data/notifactions'
|
||||||
import { NText, createDiscreteApi } from 'naive-ui'
|
import { NText, createDiscreteApi } from 'naive-ui'
|
||||||
|
|
||||||
@@ -38,4 +38,5 @@ QueryGetAPI<string>(BASE_API() + 'vtsuru/version')
|
|||||||
//加载其他数据
|
//加载其他数据
|
||||||
GetSelfAccount()
|
GetSelfAccount()
|
||||||
GetNotifactions()
|
GetNotifactions()
|
||||||
|
UpdateAccountLoop()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function changePassword() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
QueryGetAPI(ACCOUNT_API_URL() + 'verify/reset-password', {
|
QueryGetAPI(ACCOUNT_API_URL + 'verify/reset-password', {
|
||||||
key: key.value,
|
key: key.value,
|
||||||
password: password.value,
|
password: password.value,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,7 +4,28 @@ import { FeedbackStatus, FeedbackType, ResponseFeedbackModel } from '@/api/api-m
|
|||||||
import { QueryGetAPI, QueryPostAPI } from '@/api/query'
|
import { QueryGetAPI, QueryPostAPI } from '@/api/query'
|
||||||
import { FEEDBACK_API_URL } from '@/data/constants'
|
import { FEEDBACK_API_URL } from '@/data/constants'
|
||||||
import { List } from 'linqts'
|
import { List } from 'linqts'
|
||||||
import { NButton, NCard, NCheckbox, NDivider, NEllipsis, NEmpty, NForm, NGrid, NGridItem, NInput, NModal, NRadioButton, NRadioGroup, NSpace, NSpin, NTag, NText, NTooltip, useMessage } from 'naive-ui'
|
import {
|
||||||
|
NButton,
|
||||||
|
NCard,
|
||||||
|
NCheckbox,
|
||||||
|
NDivider,
|
||||||
|
NEllipsis,
|
||||||
|
NEmpty,
|
||||||
|
NForm,
|
||||||
|
NGrid,
|
||||||
|
NGridItem,
|
||||||
|
NInput,
|
||||||
|
NModal,
|
||||||
|
NRadioButton,
|
||||||
|
NRadioGroup,
|
||||||
|
NSpace,
|
||||||
|
NSpin,
|
||||||
|
NTag,
|
||||||
|
NText,
|
||||||
|
NTime,
|
||||||
|
NTooltip,
|
||||||
|
useMessage,
|
||||||
|
} from 'naive-ui'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
interface FeedbackModel {
|
interface FeedbackModel {
|
||||||
@@ -43,7 +64,7 @@ const newFeedback = ref<FeedbackModel>({
|
|||||||
|
|
||||||
async function get() {
|
async function get() {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<ResponseFeedbackModel[]>(FEEDBACK_API_URL() + 'get')
|
const data = await QueryGetAPI<ResponseFeedbackModel[]>(FEEDBACK_API_URL + 'get')
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
return new List(data.data).OrderByDescending((s) => s.createAt).ToArray()
|
return new List(data.data).OrderByDescending((s) => s.createAt).ToArray()
|
||||||
} else {
|
} else {
|
||||||
@@ -60,7 +81,7 @@ async function add() {
|
|||||||
message.error('反馈内容不能为空')
|
message.error('反馈内容不能为空')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await QueryPostAPI<ResponseFeedbackModel>(FEEDBACK_API_URL() + 'add', newFeedback.value)
|
await QueryPostAPI<ResponseFeedbackModel>(FEEDBACK_API_URL + 'add', newFeedback.value)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('发送成功, 感谢你的反馈!')
|
message.success('发送成功, 感谢你的反馈!')
|
||||||
@@ -78,8 +99,11 @@ async function add() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NSpace>
|
<NSpace align="center">
|
||||||
<NButton @click="showAddModal = true" type="info">添加反馈</NButton>
|
<NButton @click="showAddModal = true" type="info">添加反馈</NButton>
|
||||||
|
<NText depth="3">
|
||||||
|
或者直接加群 873260337 说也可以
|
||||||
|
</NText>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
<NDivider>
|
<NDivider>
|
||||||
<NTooltip>
|
<NTooltip>
|
||||||
@@ -96,7 +120,7 @@ async function add() {
|
|||||||
<NSpace v-else>
|
<NSpace v-else>
|
||||||
<NCard v-for="item in selectedFeedback" v-bind:key="item.createAt" size="small" embedded style="min-width: 300px">
|
<NCard v-for="item in selectedFeedback" v-bind:key="item.createAt" size="small" embedded style="min-width: 300px">
|
||||||
<template #header>
|
<template #header>
|
||||||
<NTag v-if="item.status == FeedbackStatus.Padding" :bordered="false"> 等待中 </NTag>
|
<NTag v-if="item.status == FeedbackStatus.Padding" :bordered="false"> 等待 </NTag>
|
||||||
<NTag v-else-if="item.status == FeedbackStatus.Progressing" type="success">
|
<NTag v-else-if="item.status == FeedbackStatus.Progressing" type="success">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<NSpin :size="12" />
|
<NSpin :size="12" />
|
||||||
@@ -113,6 +137,15 @@ async function add() {
|
|||||||
{{ item.userName }}
|
{{ item.userName }}
|
||||||
</NEllipsis>
|
</NEllipsis>
|
||||||
</template>
|
</template>
|
||||||
|
<NDivider vertical />
|
||||||
|
<NTooltip>
|
||||||
|
<template #trigger>
|
||||||
|
<NText depth="3" style="font-size: small">
|
||||||
|
<NTime :time="item.createAt" type="relative" />
|
||||||
|
</NText>
|
||||||
|
</template>
|
||||||
|
<NTime :time="item.createAt" />
|
||||||
|
</NTooltip>
|
||||||
</template>
|
</template>
|
||||||
<template #header-extra>
|
<template #header-extra>
|
||||||
<NTag v-if="item.type == FeedbackType.Opinion" :bordered="false" size="small" type="info" :color="{ color: '#5f877d', textColor: 'white' }"> 建议 </NTag>
|
<NTag v-if="item.type == FeedbackType.Opinion" :bordered="false" size="small" type="info" :color="{ color: '#5f877d', textColor: 'white' }"> 建议 </NTag>
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ const menuOptions = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
async function resendEmail() {
|
async function resendEmail() {
|
||||||
await QueryGetAPI(ACCOUNT_API_URL() + 'send-verify-email')
|
await QueryGetAPI(ACCOUNT_API_URL + 'send-verify-email')
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
canResendEmail.value = false
|
canResendEmail.value = false
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const isLoading = ref(false)
|
|||||||
|
|
||||||
async function VerifyAccount() {
|
async function VerifyAccount() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
await QueryGetAPI<AccountInfo>(ACCOUNT_API_URL() + 'verify', {
|
await QueryGetAPI<AccountInfo>(ACCOUNT_API_URL + 'verify', {
|
||||||
target: route.query.target,
|
target: route.query.target,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const totalTime = computed(() => {
|
|||||||
|
|
||||||
async function get() {
|
async function get() {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<VideoCollectDetail>(VIDEO_COLLECT_API_URL() + 'get', { id: route.params.id })
|
const data = await QueryGetAPI<VideoCollectDetail>(VIDEO_COLLECT_API_URL + 'get', { id: route.params.id })
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
return data.data
|
return data.data
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const isLoading = ref(false)
|
|||||||
|
|
||||||
async function get() {
|
async function get() {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<VideoCollectDetail>(VIDEO_COLLECT_API_URL() + 'get', { id: route.params.id })
|
const data = await QueryGetAPI<VideoCollectDetail>(VIDEO_COLLECT_API_URL + 'get', { id: route.params.id })
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
return data.data.table
|
return data.data.table
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ async function add() {
|
|||||||
}
|
}
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
addModel.value.id = table.value?.id ?? route.params.id.toString()
|
addModel.value.id = table.value?.id ?? route.params.id.toString()
|
||||||
await QueryPostAPI(VIDEO_COLLECT_API_URL() + 'add', addModel.value, [['Turnstile', token.value]])
|
await QueryPostAPI(VIDEO_COLLECT_API_URL + 'add', addModel.value, [['Turnstile', token.value]])
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('已成功推荐视频')
|
message.success('已成功推荐视频')
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const roomId = ref()
|
|||||||
const timer = ref()
|
const timer = ref()
|
||||||
|
|
||||||
function onStartVerify() {
|
function onStartVerify() {
|
||||||
QueryGetAPI(BILI_API_URL() + 'verify', {
|
QueryGetAPI(BILI_API_URL + 'verify', {
|
||||||
uId: uId.value,
|
uId: uId.value,
|
||||||
}).then((data) => {
|
}).then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
@@ -34,7 +34,7 @@ async function checkStatus() {
|
|||||||
uId: number
|
uId: number
|
||||||
roomId: number
|
roomId: number
|
||||||
endTime: number
|
endTime: number
|
||||||
}>(BILI_API_URL() + 'status')
|
}>(BILI_API_URL + 'status')
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
//正在进行认证
|
//正在进行认证
|
||||||
roomId.value ??= data.data.roomId
|
roomId.value ??= data.data.roomId
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import VueTurnstile from 'vue-turnstile'
|
|||||||
import { BiliAuthCodeStatusType } from '@/api/api-models'
|
import { BiliAuthCodeStatusType } from '@/api/api-models'
|
||||||
import EventFetcherStatusCard from '@/components/EventFetcherStatusCard.vue'
|
import EventFetcherStatusCard from '@/components/EventFetcherStatusCard.vue'
|
||||||
|
|
||||||
const token = ref()
|
const token = ref('')
|
||||||
const turnstile = ref()
|
const turnstile = ref()
|
||||||
|
|
||||||
const accountInfo = useAccount()
|
const accountInfo = useAccount()
|
||||||
@@ -38,7 +38,7 @@ function logout() {
|
|||||||
}
|
}
|
||||||
function resetBili() {
|
function resetBili() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
QueryGetAPI(ACCOUNT_API_URL() + 'reset-bili')
|
QueryGetAPI(ACCOUNT_API_URL + 'reset-bili')
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('已解绑 Bilibili 账号')
|
message.success('已解绑 Bilibili 账号')
|
||||||
@@ -55,7 +55,7 @@ function resetBili() {
|
|||||||
}
|
}
|
||||||
function resetEmail() {
|
function resetEmail() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
QueryGetAPI(ACCOUNT_API_URL() + 'reset-email', { email: newEmailAddress.value, code: newEmailVerifyCode.value })
|
QueryGetAPI(ACCOUNT_API_URL + 'reset-email', { email: newEmailAddress.value, code: newEmailVerifyCode.value })
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('已将邮箱改绑为 ' + newEmailAddress.value)
|
message.success('已将邮箱改绑为 ' + newEmailAddress.value)
|
||||||
@@ -71,7 +71,7 @@ function resetEmail() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
function sendEmailVerifyCode() {
|
function sendEmailVerifyCode() {
|
||||||
QueryGetAPI(ACCOUNT_API_URL() + 'reset-email/code', { email: newEmailAddress.value })
|
QueryGetAPI(ACCOUNT_API_URL + 'reset-email/code', { email: newEmailAddress.value })
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('发送成功, 请检查目标邮箱. 如果没有收到, 请检查垃圾邮件')
|
message.success('发送成功, 请检查目标邮箱. 如果没有收到, 请检查垃圾邮件')
|
||||||
@@ -92,7 +92,7 @@ async function resetPassword() {
|
|||||||
message.error('两次密码不一致')
|
message.error('两次密码不一致')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await QueryGetAPI(ACCOUNT_API_URL() + 'verify/reset-password', { password: newPassword.value })
|
await QueryGetAPI(ACCOUNT_API_URL + 'verify/reset-password', { password: newPassword.value })
|
||||||
.then(async (data) => {
|
.then(async (data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('密码已修改')
|
message.success('密码已修改')
|
||||||
@@ -118,7 +118,7 @@ async function BindBili() {
|
|||||||
uid: number
|
uid: number
|
||||||
uface: string
|
uface: string
|
||||||
room_id: number
|
room_id: number
|
||||||
}>(ACCOUNT_API_URL() + 'bind-bili', { code: biliCode.value }, [['Turnstile', token.value]])
|
}>(ACCOUNT_API_URL + 'bind-bili', { code: biliCode.value }, [['Turnstile', token.value]])
|
||||||
.then(async (data) => {
|
.then(async (data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('已绑定, 如无特殊情况请勿刷新身份码, 如果刷新了且还需要使用本站直播相关功能请更新身份码')
|
message.success('已绑定, 如无特殊情况请勿刷新身份码, 如果刷新了且还需要使用本站直播相关功能请更新身份码')
|
||||||
@@ -148,7 +148,7 @@ async function ChangeBili() {
|
|||||||
uid: number
|
uid: number
|
||||||
uface: string
|
uface: string
|
||||||
room_id: number
|
room_id: number
|
||||||
}>(ACCOUNT_API_URL() + 'change-bili', { code: biliCode.value }, [['Turnstile', token.value]])
|
}>(ACCOUNT_API_URL + 'change-bili', { code: biliCode.value }, [['Turnstile', token.value]])
|
||||||
.then(async (data) => {
|
.then(async (data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('已更新身份码')
|
message.success('已更新身份码')
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ async function getFansHistory() {
|
|||||||
time: number
|
time: number
|
||||||
count: number
|
count: number
|
||||||
}[]
|
}[]
|
||||||
>(HISTORY_API_URL() + 'fans')
|
>(HISTORY_API_URL + 'fans')
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
fansHistory.value = data.data
|
fansHistory.value = data.data
|
||||||
@@ -50,7 +50,7 @@ async function getGuardsHistory() {
|
|||||||
time: number
|
time: number
|
||||||
count: number
|
count: number
|
||||||
}[]
|
}[]
|
||||||
>(HISTORY_API_URL() + 'guards')
|
>(HISTORY_API_URL + 'guards')
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
guardHistory.value = data.data
|
guardHistory.value = data.data
|
||||||
@@ -71,7 +71,7 @@ async function getUpstatHistory() {
|
|||||||
likes: number
|
likes: number
|
||||||
}
|
}
|
||||||
}[]
|
}[]
|
||||||
>(HISTORY_API_URL() + 'upstat')
|
>(HISTORY_API_URL + 'upstat')
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
upstatHistory.value = data.data
|
upstatHistory.value = data.data
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const liveInfo = ref<ResponseLiveDetail | undefined>(await get())
|
|||||||
|
|
||||||
async function get() {
|
async function get() {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<ResponseLiveDetail>(LIVE_API_URL() + 'get', {
|
const data = await QueryGetAPI<ResponseLiveDetail>(LIVE_API_URL + 'get', {
|
||||||
id: route.params.id,
|
id: route.params.id,
|
||||||
useEmoji: true,
|
useEmoji: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const defaultDanmakusCount = ref(0)
|
|||||||
|
|
||||||
async function getAll() {
|
async function getAll() {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<ResponseLiveInfoModel[]>(LIVE_API_URL() + 'get-all')
|
const data = await QueryGetAPI<ResponseLiveInfoModel[]>(LIVE_API_URL + 'get-all')
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
return data.data
|
return data.data
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ const shareUrl = computed(() => 'https://vtsuru.live/user/' + accountInfo.value?
|
|||||||
|
|
||||||
async function GetRecieveQAInfo() {
|
async function GetRecieveQAInfo() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
await QueryGetAPI<QAInfo[]>(QUESTION_API_URL() + 'get-recieve')
|
await QueryGetAPI<QAInfo[]>(QUESTION_API_URL + 'get-recieve')
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
if (data.data.length > 0) {
|
if (data.data.length > 0) {
|
||||||
@@ -91,7 +91,7 @@ async function GetRecieveQAInfo() {
|
|||||||
}
|
}
|
||||||
async function GetSendQAInfo() {
|
async function GetSendQAInfo() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
await QueryGetAPI<QAInfo[]>(QUESTION_API_URL() + 'get-send')
|
await QueryGetAPI<QAInfo[]>(QUESTION_API_URL + 'get-send')
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
sendQuestions.value = data.data
|
sendQuestions.value = data.data
|
||||||
@@ -109,7 +109,7 @@ async function GetSendQAInfo() {
|
|||||||
}
|
}
|
||||||
async function reply() {
|
async function reply() {
|
||||||
isRepling.value = true
|
isRepling.value = true
|
||||||
await QueryPostAPI<QAInfo>(QUESTION_API_URL() + 'reply', {
|
await QueryPostAPI<QAInfo>(QUESTION_API_URL + 'reply', {
|
||||||
Id: currentQuestion.value?.id,
|
Id: currentQuestion.value?.id,
|
||||||
Message: replyMessage.value,
|
Message: replyMessage.value,
|
||||||
})
|
})
|
||||||
@@ -134,7 +134,7 @@ async function reply() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
async function read(question: QAInfo, read: boolean) {
|
async function read(question: QAInfo, read: boolean) {
|
||||||
await QueryGetAPI(QUESTION_API_URL() + 'read', {
|
await QueryGetAPI(QUESTION_API_URL + 'read', {
|
||||||
id: question.id,
|
id: question.id,
|
||||||
read: read ? 'true' : 'false',
|
read: read ? 'true' : 'false',
|
||||||
})
|
})
|
||||||
@@ -150,7 +150,7 @@ async function read(question: QAInfo, read: boolean) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
async function favorite(question: QAInfo, fav: boolean) {
|
async function favorite(question: QAInfo, fav: boolean) {
|
||||||
await QueryGetAPI(QUESTION_API_URL() + 'favorite', {
|
await QueryGetAPI(QUESTION_API_URL + 'favorite', {
|
||||||
id: question.id,
|
id: question.id,
|
||||||
favorite: fav,
|
favorite: fav,
|
||||||
})
|
})
|
||||||
@@ -167,7 +167,7 @@ async function favorite(question: QAInfo, fav: boolean) {
|
|||||||
}
|
}
|
||||||
async function setPublic(pub: boolean) {
|
async function setPublic(pub: boolean) {
|
||||||
isChangingPublic.value = true
|
isChangingPublic.value = true
|
||||||
await QueryGetAPI(QUESTION_API_URL() + 'public', {
|
await QueryGetAPI(QUESTION_API_URL + 'public', {
|
||||||
id: currentQuestion.value?.id,
|
id: currentQuestion.value?.id,
|
||||||
public: pub,
|
public: pub,
|
||||||
})
|
})
|
||||||
@@ -187,12 +187,12 @@ async function setPublic(pub: boolean) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
async function blacklist(question: QAInfo) {
|
async function blacklist(question: QAInfo) {
|
||||||
await QueryGetAPI(ACCOUNT_API_URL() + 'black-list/add', {
|
await QueryGetAPI(ACCOUNT_API_URL + 'black-list/add', {
|
||||||
id: question.sender.id,
|
id: question.sender.id,
|
||||||
})
|
})
|
||||||
.then(async (data) => {
|
.then(async (data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
await QueryGetAPI(QUESTION_API_URL() + 'del', {
|
await QueryGetAPI(QUESTION_API_URL + 'del', {
|
||||||
id: question.id,
|
id: question.id,
|
||||||
}).then((data) => {
|
}).then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ const selectedScheduleWeek = ref(Number(format(Date.now(), 'w')) + 1)
|
|||||||
|
|
||||||
async function get() {
|
async function get() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
await QueryGetAPI<ScheduleWeekInfo[]>(SCHEDULE_API_URL() + 'get', {
|
await QueryGetAPI<ScheduleWeekInfo[]>(SCHEDULE_API_URL + 'get', {
|
||||||
id: accountInfo.value?.id ?? -1,
|
id: accountInfo.value?.id ?? -1,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
@@ -137,7 +137,7 @@ async function get() {
|
|||||||
const isFetching = ref(false)
|
const isFetching = ref(false)
|
||||||
async function addSchedule() {
|
async function addSchedule() {
|
||||||
isFetching.value = true
|
isFetching.value = true
|
||||||
await QueryPostAPI(SCHEDULE_API_URL() + 'update', {
|
await QueryPostAPI(SCHEDULE_API_URL + 'update', {
|
||||||
year: selectedScheduleYear.value,
|
year: selectedScheduleYear.value,
|
||||||
week: selectedScheduleWeek.value,
|
week: selectedScheduleWeek.value,
|
||||||
})
|
})
|
||||||
@@ -166,7 +166,7 @@ async function onCopySchedule() {
|
|||||||
}
|
}
|
||||||
async function onUpdateSchedule() {
|
async function onUpdateSchedule() {
|
||||||
isFetching.value = true
|
isFetching.value = true
|
||||||
await QueryPostAPI(SCHEDULE_API_URL() + 'update', {
|
await QueryPostAPI(SCHEDULE_API_URL + 'update', {
|
||||||
year: updateScheduleModel.value.year,
|
year: updateScheduleModel.value.year,
|
||||||
week: updateScheduleModel.value.week,
|
week: updateScheduleModel.value.week,
|
||||||
day: selectedDay.value,
|
day: selectedDay.value,
|
||||||
@@ -191,7 +191,7 @@ async function onUpdateSchedule() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
async function onDeleteSchedule(schedule: ScheduleWeekInfo) {
|
async function onDeleteSchedule(schedule: ScheduleWeekInfo) {
|
||||||
await QueryGetAPI(SCHEDULE_API_URL() + 'del', {
|
await QueryGetAPI(SCHEDULE_API_URL + 'del', {
|
||||||
year: schedule.year,
|
year: schedule.year,
|
||||||
week: schedule.week,
|
week: schedule.week,
|
||||||
}).then((data) => {
|
}).then((data) => {
|
||||||
|
|||||||
@@ -1,6 +1,26 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SaveAccountSettings, SaveEnableFunctions, useAccount } from '@/api/account'
|
import { DelBiliBlackList, 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,
|
||||||
|
NEmpty,
|
||||||
|
NForm,
|
||||||
|
NList,
|
||||||
|
NListItem,
|
||||||
|
NModal,
|
||||||
|
NSelect,
|
||||||
|
NSpace,
|
||||||
|
NSpin,
|
||||||
|
NSwitch,
|
||||||
|
NTabPane,
|
||||||
|
NTabs,
|
||||||
|
NText,
|
||||||
|
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, SongRequestOption, SongsInfo } from '@/api/api-models'
|
import { FunctionTypes, ScheduleWeekInfo, SongFrom, SongLanguage, SongRequestOption, SongsInfo } from '@/api/api-models'
|
||||||
import { QueryPostAPI } from '@/api/query'
|
import { QueryPostAPI } from '@/api/query'
|
||||||
@@ -124,7 +144,7 @@ const templates = {
|
|||||||
scMinPrice: 30,
|
scMinPrice: 30,
|
||||||
fanMedalMinLevel: 5,
|
fanMedalMinLevel: 5,
|
||||||
needJianzhang: true,
|
needJianzhang: true,
|
||||||
} as SongRequestOption
|
} as SongRequestOption,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
@@ -190,15 +210,14 @@ const biliUserInfo = ref()
|
|||||||
const settingModalVisiable = ref(false)
|
const settingModalVisiable = ref(false)
|
||||||
|
|
||||||
async function RequestBiliUserData() {
|
async function RequestBiliUserData() {
|
||||||
await fetch(FETCH_API + `https://account.bilibili.com/api/member/getCardByMid?mid=10021741`)
|
await fetch(FETCH_API + `https://account.bilibili.com/api/member/getCardByMid?mid=10021741`).then(async (respone) => {
|
||||||
.then(async (respone) => {
|
let data = await respone.json()
|
||||||
let data = await respone.json()
|
if (data.code == 0) {
|
||||||
if (data.code == 0) {
|
biliUserInfo.value = data.card
|
||||||
biliUserInfo.value = data.card
|
} else {
|
||||||
} else {
|
throw new Error('Bili User API Error: ' + data.message)
|
||||||
throw new Error('Bili User API Error: ' + data.message)
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
async function SaveComboGroupSetting(value: (string | number)[], meta: { actionType: 'check' | 'uncheck'; value: string | number }) {
|
async function SaveComboGroupSetting(value: (string | number)[], meta: { actionType: 'check' | 'uncheck'; value: string | number }) {
|
||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
@@ -268,6 +287,24 @@ function onOpenTemplateSettings() {
|
|||||||
const buttonGroup = computed(() => {
|
const buttonGroup = computed(() => {
|
||||||
return h(NSpace, () => [h(NButton, { type: 'primary', onClick: () => SaveTemplateSetting() }, () => '设为展示模板'), h(NButton, { type: 'info', onClick: onOpenTemplateSettings }, () => '模板设置')])
|
return h(NSpace, () => [h(NButton, { type: 'primary', onClick: () => SaveTemplateSetting() }, () => '设为展示模板'), h(NButton, { type: 'info', onClick: onOpenTemplateSettings }, () => '模板设置')])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function unblockUser(id: number) {
|
||||||
|
DelBiliBlackList(id)
|
||||||
|
.then((data) => {
|
||||||
|
if (data.code == 200) {
|
||||||
|
message.success(`[${id}] 已移除黑名单`)
|
||||||
|
if (accountInfo.value) {
|
||||||
|
delete accountInfo.value.biliBlackList[id]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.error(data.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
message.error(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
onActivated(() => {
|
onActivated(() => {
|
||||||
if (route.query.tab) {
|
if (route.query.tab) {
|
||||||
selectedTab.value = route.query.tab.toString()
|
selectedTab.value = route.query.tab.toString()
|
||||||
@@ -304,6 +341,22 @@ onMounted(async () => {
|
|||||||
<NCheckbox v-model:checked="accountInfo.settings.questionBox.allowUnregistedUser" @update:checked="SaveComboSetting"> 允许未注册用户提问 </NCheckbox>
|
<NCheckbox v-model:checked="accountInfo.settings.questionBox.allowUnregistedUser" @update:checked="SaveComboSetting"> 允许未注册用户提问 </NCheckbox>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</NTabPane>
|
</NTabPane>
|
||||||
|
<NTabPane tab="黑名单" name="blacklist">
|
||||||
|
<NList v-if="accountInfo.biliBlackList && Object.keys(accountInfo.biliBlackList).length > 0">
|
||||||
|
<NListItem v-for="item in Object.entries(accountInfo.biliBlackList)" :key="item[0]">
|
||||||
|
<NSpace align="center">
|
||||||
|
<NText>
|
||||||
|
{{ item[1] }}
|
||||||
|
</NText>
|
||||||
|
<NText depth="3">
|
||||||
|
{{ item[0] }}
|
||||||
|
</NText>
|
||||||
|
<NButton type="error" @click="unblockUser(Number(item[0]))" size="small"> 移除 </NButton>
|
||||||
|
</NSpace>
|
||||||
|
</NListItem>
|
||||||
|
</NList>
|
||||||
|
<NEmpty v-else />
|
||||||
|
</NTabPane>
|
||||||
<NTabPane tab="模板" name="template">
|
<NTabPane tab="模板" name="template">
|
||||||
<NSpace vertical>
|
<NSpace vertical>
|
||||||
<NSpace align="center"> 页面 <NSelect :options="templateOptions" v-model:value="selectedOption" style="width: 150px" /> </NSpace>
|
<NSpace align="center"> 页面 <NSelect :options="templateOptions" v-model:value="selectedOption" style="width: 150px" /> </NSpace>
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ async function addSongs(songsShoudAdd: SongsInfo[], from: SongFrom) {
|
|||||||
|
|
||||||
async function getNeteaseSongList() {
|
async function getNeteaseSongList() {
|
||||||
isModalLoading.value = true
|
isModalLoading.value = true
|
||||||
await QueryGetAPI<SongsInfo[]>(SONG_API_URL() + 'get-netease-list', {
|
await QueryGetAPI<SongsInfo[]>(SONG_API_URL + 'get-netease-list', {
|
||||||
id: neteaseSongListId.value,
|
id: neteaseSongListId.value,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
@@ -329,7 +329,7 @@ async function getFivesingSongUrl(song: SongsInfo): Promise<string> {
|
|||||||
const isLoading = ref(true)
|
const isLoading = ref(true)
|
||||||
async function getSongs() {
|
async function getSongs() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
await QueryGetAPI<any>(SONG_API_URL() + 'get', {
|
await QueryGetAPI<any>(SONG_API_URL + 'get', {
|
||||||
id: accountInfo.value?.id,
|
id: accountInfo.value?.id,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ const acceptVideos = computed(() => {
|
|||||||
|
|
||||||
async function getData() {
|
async function getData() {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<VideoCollectDetail>(VIDEO_COLLECT_API_URL() + 'get', { id: route.params.id })
|
const data = await QueryGetAPI<VideoCollectDetail>(VIDEO_COLLECT_API_URL + 'get', { id: route.params.id })
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
updateModel.value = {
|
updateModel.value = {
|
||||||
id: data.data.table.id,
|
id: data.data.table.id,
|
||||||
@@ -200,7 +200,7 @@ const rejectButtonGroup = (v: VideoInfo) =>
|
|||||||
])
|
])
|
||||||
function setStatus(status: VideoStatus, video: VideoInfo) {
|
function setStatus(status: VideoStatus, video: VideoInfo) {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
QueryGetAPI(VIDEO_COLLECT_API_URL() + 'set-status', {
|
QueryGetAPI(VIDEO_COLLECT_API_URL + 'set-status', {
|
||||||
id: videoDetail.value.table.id,
|
id: videoDetail.value.table.id,
|
||||||
bvid: video.bvid,
|
bvid: video.bvid,
|
||||||
status: status,
|
status: status,
|
||||||
@@ -235,7 +235,7 @@ function dateDisabled(ts: number) {
|
|||||||
function updateTable() {
|
function updateTable() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
updateModel.value.id = videoDetail.value.table.id
|
updateModel.value.id = videoDetail.value.table.id
|
||||||
QueryPostAPI<VideoCollectTable>(VIDEO_COLLECT_API_URL() + 'update', updateModel.value)
|
QueryPostAPI<VideoCollectTable>(VIDEO_COLLECT_API_URL + 'update', updateModel.value)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('更新成功')
|
message.success('更新成功')
|
||||||
@@ -253,7 +253,7 @@ function updateTable() {
|
|||||||
}
|
}
|
||||||
function deleteTable() {
|
function deleteTable() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
QueryGetAPI(VIDEO_COLLECT_API_URL() + 'del', {
|
QueryGetAPI(VIDEO_COLLECT_API_URL + 'del', {
|
||||||
id: videoDetail.value.table.id,
|
id: videoDetail.value.table.id,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
@@ -275,7 +275,7 @@ function deleteTable() {
|
|||||||
}
|
}
|
||||||
function closeTable() {
|
function closeTable() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
QueryGetAPI(VIDEO_COLLECT_API_URL() + 'finish', {
|
QueryGetAPI(VIDEO_COLLECT_API_URL + 'finish', {
|
||||||
id: videoDetail.value.table.id,
|
id: videoDetail.value.table.id,
|
||||||
finish: !videoDetail.value.table.isFinish,
|
finish: !videoDetail.value.table.isFinish,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ const isLoading2 = ref(false)
|
|||||||
async function get() {
|
async function get() {
|
||||||
try {
|
try {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
const data = await QueryGetAPI<VideoCollectTable[]>(VIDEO_COLLECT_API_URL() + 'get-all')
|
const data = await QueryGetAPI<VideoCollectTable[]>(VIDEO_COLLECT_API_URL + 'get-all')
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
//videoTables.value = data.data
|
//videoTables.value = data.data
|
||||||
return data.data
|
return data.data
|
||||||
@@ -112,7 +112,7 @@ async function get() {
|
|||||||
function createTable() {
|
function createTable() {
|
||||||
formRef.value?.validate().then(async () => {
|
formRef.value?.validate().then(async () => {
|
||||||
isLoading2.value = true
|
isLoading2.value = true
|
||||||
QueryPostAPI<VideoCollectTable>(VIDEO_COLLECT_API_URL() + 'create', createVideoModel.value)
|
QueryPostAPI<VideoCollectTable>(VIDEO_COLLECT_API_URL + 'create', createVideoModel.value)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
videoTables.value.push(data.data)
|
videoTables.value.push(data.data)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const isMoreThanContainer = computed(() => {
|
|||||||
|
|
||||||
async function getUsers() {
|
async function getUsers() {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<UpdateLiveLotteryUsersModel>(LOTTERY_API_URL() + 'live/get-users', {
|
const data = await QueryGetAPI<UpdateLiveLotteryUsersModel>(LOTTERY_API_URL + 'live/get-users', {
|
||||||
code: currentCode.value,
|
code: currentCode.value,
|
||||||
})
|
})
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ const activeItems = computed(() => {
|
|||||||
|
|
||||||
async function get() {
|
async function get() {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<{ queue: ResponseQueueModel[]; setting: Setting_Queue }>(QUEUE_API_URL() + 'get-active-and-settings', {
|
const data = await QueryGetAPI<{ queue: ResponseQueueModel[]; setting: Setting_Queue }>(QUEUE_API_URL + 'get-active-and-settings', {
|
||||||
id: currentId.value,
|
id: currentId.value,
|
||||||
})
|
})
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
@@ -111,7 +111,7 @@ onUnmounted(() => {
|
|||||||
<img class="queue-singing-avatar" :src="AVATAR_URL + progressing?.user?.uid" referrerpolicy="no-referrer" />
|
<img class="queue-singing-avatar" :src="AVATAR_URL + progressing?.user?.uid" referrerpolicy="no-referrer" />
|
||||||
<p class="queue-singing-name">{{ progressing?.user?.name }}</p>
|
<p class="queue-singing-name">{{ progressing?.user?.name }}</p>
|
||||||
</template>
|
</template>
|
||||||
<div v-else class="queue-singing-empty">空闲中</div>
|
<div v-else class="queue-singing-empty">等待中</div>
|
||||||
<div class="queue-singing-suffix"></div>
|
<div class="queue-singing-suffix"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="queue-content" ref="listContainerRef">
|
<div class="queue-content" ref="listContainerRef">
|
||||||
@@ -122,12 +122,15 @@ onUnmounted(() => {
|
|||||||
:from="(item.from as number)"
|
:from="(item.from as number)"
|
||||||
:status="(item.status as number)"
|
:status="(item.status as number)"
|
||||||
:payment="item.giftPrice ?? 0"
|
:payment="item.giftPrice ?? 0"
|
||||||
v-for="item in activeItems"
|
v-for="(item, index) in activeItems"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:style="`height: ${itemHeight}px`"
|
:style="`height: ${itemHeight}px`"
|
||||||
>
|
>
|
||||||
|
<div class="queue-list-item-index" :index="index + 1">
|
||||||
|
{{ index + 1 }}
|
||||||
|
</div>
|
||||||
<div class="queue-list-item-level" :has-level="(item.user?.fans_medal_level ?? 0) > 0">
|
<div class="queue-list-item-level" :has-level="(item.user?.fans_medal_level ?? 0) > 0">
|
||||||
{{ item.user?.fans_medal_level }}
|
{{ `${item.user?.fans_medal_name} ${item.user?.fans_medal_level}` }}
|
||||||
</div>
|
</div>
|
||||||
<div class="queue-list-item-user-name">
|
<div class="queue-list-item-user-name">
|
||||||
{{ item.user?.name }}
|
{{ item.user?.name }}
|
||||||
@@ -140,7 +143,7 @@ onUnmounted(() => {
|
|||||||
<NEmpty class="queue-empty" description="暂无人排队" />
|
<NEmpty class="queue-empty" description="暂无人排队" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="queue-footer" ref="footerRef">
|
<div class="queue-footer" ref="footerRef" v-if="settings.showRequireInfo">
|
||||||
<Vue3Marquee :key="key" ref="footerListRef" class="queue-footer-marquee" :pause="footerSize.width < footerListSize.width" :duration="20">
|
<Vue3Marquee :key="key" ref="footerListRef" class="queue-footer-marquee" :pause="footerSize.width < footerListSize.width" :duration="20">
|
||||||
<span class="queue-tag" type="prefix">
|
<span class="queue-tag" type="prefix">
|
||||||
<div class="queue-tag-key">关键词</div>
|
<div class="queue-tag-key">关键词</div>
|
||||||
@@ -204,7 +207,7 @@ onUnmounted(() => {
|
|||||||
text-shadow: 0 0 10px #ca7b7b6e, 0 0 20px #ffffff8e, 0 0 30px #61606086, 0 0 40px rgba(64, 156, 179, 0.555);
|
text-shadow: 0 0 10px #ca7b7b6e, 0 0 20px #ffffff8e, 0 0 30px #61606086, 0 0 40px rgba(64, 156, 179, 0.555);
|
||||||
}
|
}
|
||||||
.queue-header-count {
|
.queue-header-count {
|
||||||
color: #ffffffbd;
|
color: #ffffff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
@@ -321,6 +324,16 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
.queue-list-item-index {
|
||||||
|
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;
|
||||||
|
}
|
||||||
.queue-list-item-level {
|
.queue-list-item-level {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const activeSongs = computed(() => {
|
|||||||
|
|
||||||
async function get() {
|
async function get() {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<{ songs: SongRequestInfo[]; setting: Setting_SongRequest }>(SONG_REQUEST_API_URL() + 'get-active-and-settings', {
|
const data = await QueryGetAPI<{ songs: SongRequestInfo[]; setting: Setting_SongRequest }>(SONG_REQUEST_API_URL + 'get-active-and-settings', {
|
||||||
id: currentId.value,
|
id: currentId.value,
|
||||||
})
|
})
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
@@ -103,13 +103,16 @@ onUnmounted(() => {
|
|||||||
<div class="song-request-content" ref="listContainerRef">
|
<div class="song-request-content" ref="listContainerRef">
|
||||||
<template v-if="activeSongs.length > 0">
|
<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;`">
|
<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`">
|
<span class="song-request-list-item" :from="(song.from as number)" :status="(song.status as number)" v-for="(song, index) in activeSongs" :key="song.id" :style="`height: ${itemHeight}px`">
|
||||||
|
<div class="song-request-list-item-index" :index="index + 1">
|
||||||
|
{{ index + 1 }}
|
||||||
|
</div>
|
||||||
<div class="song-request-list-item-song-name">
|
<div class="song-request-list-item-song-name">
|
||||||
{{ song.songName }}
|
{{ song.songName }}
|
||||||
</div>
|
</div>
|
||||||
<p class="song-request-list-item-name">{{ song.from == SongRequestFrom.Manual ? '主播添加' : song.user?.name }}</p>
|
<p class="song-request-list-item-name">{{ song.from == SongRequestFrom.Manual ? '主播添加' : song.user?.name }}</p>
|
||||||
<div class="song-request-list-item-level" :has-level="(song.user?.fans_medal_level ?? 0) > 0">
|
<div class="song-request-list-item-level" :has-level="(song.user?.fans_medal_level ?? 0) > 0">
|
||||||
{{ song.user?.fans_medal_level }}
|
{{ `${song.user?.fans_medal_name} ${song.user?.fans_medal_level}` }}
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
</Vue3Marquee>
|
</Vue3Marquee>
|
||||||
@@ -118,7 +121,7 @@ onUnmounted(() => {
|
|||||||
<NEmpty class="song-request-empty" description="暂无人点歌" />
|
<NEmpty class="song-request-empty" description="暂无人点歌" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="song-request-footer" ref="footerRef">
|
<div class="song-request-footer" v-if="settings.showRequireInfo" ref="footerRef">
|
||||||
<Vue3Marquee :key="key" ref="footerListRef" class="song-request-footer-marquee" :pause="footerSize.width < footerListSize.width" :duration="20">
|
<Vue3Marquee :key="key" ref="footerListRef" class="song-request-footer-marquee" :pause="footerSize.width < footerListSize.width" :duration="20">
|
||||||
<span class="song-request-tag" type="prefix">
|
<span class="song-request-tag" type="prefix">
|
||||||
<div class="song-request-tag-key">前缀</div>
|
<div class="song-request-tag-key">前缀</div>
|
||||||
@@ -290,6 +293,16 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
.song-request-list-item-index {
|
||||||
|
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 {
|
.song-request-list-item-level {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SaveAccountSettings, SaveEnableFunctions, useAccount } from '@/api/account'
|
import { AddBiliBlackList, SaveAccountSettings, SaveEnableFunctions, useAccount } from '@/api/account'
|
||||||
import {
|
import {
|
||||||
EventDataTypes,
|
EventDataTypes,
|
||||||
EventModel,
|
EventModel,
|
||||||
@@ -16,7 +16,18 @@ import {
|
|||||||
import { QueryGetAPI, QueryPostAPI, QueryPostAPIWithParams } from '@/api/query'
|
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 { OPEN_LIVE_API_URL, SONG_API_URL, SONG_REQUEST_API_URL } from '@/data/constants'
|
import { OPEN_LIVE_API_URL, SONG_API_URL, SONG_REQUEST_API_URL } from '@/data/constants'
|
||||||
import { Check24Filled, Checkmark12Regular, Delete24Filled, Dismiss12Filled, Dismiss16Filled, Info24Filled, Mic24Filled, PeopleQueue24Filled, Play24Filled } from '@vicons/fluent'
|
import {
|
||||||
|
Check24Filled,
|
||||||
|
Checkmark12Regular,
|
||||||
|
Delete24Filled,
|
||||||
|
Dismiss12Filled,
|
||||||
|
Dismiss16Filled,
|
||||||
|
Info24Filled,
|
||||||
|
Mic24Filled,
|
||||||
|
PeopleQueue24Filled,
|
||||||
|
Play24Filled,
|
||||||
|
PresenceBlocked16Regular,
|
||||||
|
} from '@vicons/fluent'
|
||||||
import { ReloadCircleSharp } from '@vicons/ionicons5'
|
import { ReloadCircleSharp } from '@vicons/ionicons5'
|
||||||
import { useStorage } from '@vueuse/core'
|
import { useStorage } from '@vueuse/core'
|
||||||
import { format, isSameDay } from 'date-fns'
|
import { format, isSameDay } from 'date-fns'
|
||||||
@@ -99,6 +110,7 @@ const notice = useNotification()
|
|||||||
|
|
||||||
const isWarnMessageAutoClose = useStorage('SongRequest.Settings.WarnMessageAutoClose', false)
|
const isWarnMessageAutoClose = useStorage('SongRequest.Settings.WarnMessageAutoClose', false)
|
||||||
const volumn = useStorage('Settings.Volumn', 0.5)
|
const volumn = useStorage('Settings.Volumn', 0.5)
|
||||||
|
const isReverse = useStorage('SongRequest.Settings.Reverse', false)
|
||||||
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const showOBSModal = ref(false)
|
const showOBSModal = ref(false)
|
||||||
@@ -128,7 +140,7 @@ const props = defineProps<{
|
|||||||
const localActiveSongs = useStorage('SongRequest.ActiveSongs', [] as SongRequestInfo[])
|
const localActiveSongs = useStorage('SongRequest.ActiveSongs', [] as SongRequestInfo[])
|
||||||
const originSongs = ref<SongRequestInfo[]>(await getAllSong())
|
const originSongs = ref<SongRequestInfo[]>(await getAllSong())
|
||||||
const songs = computed(() => {
|
const songs = computed(() => {
|
||||||
return originSongs.value.filter((s) => {
|
const result = originSongs.value.filter((s) => {
|
||||||
if (filterName.value) {
|
if (filterName.value) {
|
||||||
if (filterNameContains.value) {
|
if (filterNameContains.value) {
|
||||||
if (!s.user?.name.toLowerCase().includes(filterName.value.toLowerCase())) {
|
if (!s.user?.name.toLowerCase().includes(filterName.value.toLowerCase())) {
|
||||||
@@ -148,6 +160,11 @@ const songs = computed(() => {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
if (isReverse.value) {
|
||||||
|
return result.reverse()
|
||||||
|
} else {
|
||||||
|
return result
|
||||||
|
}
|
||||||
})
|
})
|
||||||
const activeSongs = computed(() => {
|
const activeSongs = computed(() => {
|
||||||
return (accountInfo ? songs.value : localActiveSongs.value)
|
return (accountInfo ? songs.value : localActiveSongs.value)
|
||||||
@@ -180,7 +197,7 @@ const table = ref()
|
|||||||
async function getAllSong() {
|
async function getAllSong() {
|
||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<SongRequestInfo[]>(SONG_REQUEST_API_URL() + 'get-all', {
|
const data = await QueryGetAPI<SongRequestInfo[]>(SONG_REQUEST_API_URL + 'get-all', {
|
||||||
id: accountInfo.value.id,
|
id: accountInfo.value.id,
|
||||||
})
|
})
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
@@ -200,8 +217,12 @@ async function getAllSong() {
|
|||||||
}
|
}
|
||||||
async function addSong(danmaku: EventModel) {
|
async function addSong(danmaku: EventModel) {
|
||||||
console.log(`[OPEN-LIVE-Song-Request] 收到 [${danmaku.name}] 的点歌${danmaku.type == EventDataTypes.SC ? 'SC' : '弹幕'}: ${danmaku.msg}`)
|
console.log(`[OPEN-LIVE-Song-Request] 收到 [${danmaku.name}] 的点歌${danmaku.type == EventDataTypes.SC ? 'SC' : '弹幕'}: ${danmaku.msg}`)
|
||||||
|
if (settings.value.enableOnStreaming && accountInfo.value?.streamerInfo?.isStreaming != true) {
|
||||||
|
message.info('当前未在直播中, 无法添加点歌请求. 或者关闭设置中的仅允许直播时加入')
|
||||||
|
return
|
||||||
|
}
|
||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
await QueryPostAPI<SongRequestInfo>(SONG_REQUEST_API_URL() + 'try-add', danmaku).then((data) => {
|
await QueryPostAPI<SongRequestInfo>(SONG_REQUEST_API_URL + 'try-add', danmaku).then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success(`[${danmaku.name}] 添加曲目: ${data.data.songName}`)
|
message.success(`[${danmaku.name}] 添加曲目: ${data.data.songName}`)
|
||||||
if (data.message != 'EventFetcher') originSongs.value.unshift(data.data)
|
if (data.message != 'EventFetcher') originSongs.value.unshift(data.data)
|
||||||
@@ -246,7 +267,7 @@ async function addSongManual() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
await QueryPostAPIWithParams<SongRequestInfo>(SONG_REQUEST_API_URL() + 'add', {
|
await QueryPostAPIWithParams<SongRequestInfo>(SONG_REQUEST_API_URL + 'add', {
|
||||||
name: newSongName.value,
|
name: newSongName.value,
|
||||||
}).then((data) => {
|
}).then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
@@ -300,7 +321,7 @@ async function updateSongStatus(song: SongRequestInfo, status: SongRequestStatus
|
|||||||
statusString2 = '演唱中'
|
statusString2 = '演唱中'
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
await QueryGetAPI(SONG_REQUEST_API_URL() + statusString, {
|
await QueryGetAPI(SONG_REQUEST_API_URL + statusString, {
|
||||||
id: song.id,
|
id: song.id,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
@@ -397,7 +418,7 @@ async function onUpdateFunctionEnable() {
|
|||||||
async function updateSettings() {
|
async function updateSettings() {
|
||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
await QueryPostAPI(SONG_REQUEST_API_URL() + 'update-setting', settings.value)
|
await QueryPostAPI(SONG_REQUEST_API_URL + 'update-setting', settings.value)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('已保存')
|
message.success('已保存')
|
||||||
@@ -433,7 +454,7 @@ async function deleteSongs(values: SongRequestInfo[]) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
async function deactiveAllSongs() {
|
async function deactiveAllSongs() {
|
||||||
await QueryGetAPI(SONG_REQUEST_API_URL() + 'deactive')
|
await QueryGetAPI(SONG_REQUEST_API_URL + 'deactive')
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('已全部取消')
|
message.success('已全部取消')
|
||||||
@@ -651,7 +672,7 @@ function GetGuardColor(level: number | null | undefined): string {
|
|||||||
async function updateActive() {
|
async function updateActive() {
|
||||||
if (!accountInfo.value) return
|
if (!accountInfo.value) return
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<SongRequestInfo[]>(SONG_REQUEST_API_URL() + 'get-active', {
|
const data = await QueryGetAPI<SongRequestInfo[]>(SONG_REQUEST_API_URL + 'get-active', {
|
||||||
id: accountInfo.value?.id,
|
id: accountInfo.value?.id,
|
||||||
})
|
})
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
@@ -672,6 +693,26 @@ async function updateActive() {
|
|||||||
}
|
}
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
}
|
}
|
||||||
|
function blockUser(item: SongRequestInfo) {
|
||||||
|
if (item.from != SongRequestFrom.Danmaku) {
|
||||||
|
message.error(`[${item.user?.name}] 不是来自弹幕的用户`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (item.user) {
|
||||||
|
AddBiliBlackList(item.user.uid, item.user.name)
|
||||||
|
.then((data) => {
|
||||||
|
if (data.code == 200) {
|
||||||
|
message.success(`[${item.user?.name}] 已添加到黑名单`)
|
||||||
|
updateSongStatus(item, SongRequestStatus.Cancel)
|
||||||
|
} else {
|
||||||
|
message.error(data.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
message.error(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
const isLrcLoading = ref('')
|
const isLrcLoading = ref('')
|
||||||
|
|
||||||
let timer: any
|
let timer: any
|
||||||
@@ -681,6 +722,8 @@ onMounted(() => {
|
|||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
settings.value = accountInfo.value.settings.songRequest
|
settings.value = accountInfo.value.settings.songRequest
|
||||||
}
|
}
|
||||||
|
props.client.on('danmaku', onGetDanmaku)
|
||||||
|
props.client.on('sc', onGetSC)
|
||||||
init()
|
init()
|
||||||
})
|
})
|
||||||
onActivated(() => {
|
onActivated(() => {
|
||||||
@@ -688,8 +731,6 @@ onActivated(() => {
|
|||||||
})
|
})
|
||||||
function init() {
|
function init() {
|
||||||
dispose()
|
dispose()
|
||||||
props.client.on('danmaku', onGetDanmaku)
|
|
||||||
props.client.on('sc', onGetSC)
|
|
||||||
timer = setInterval(() => {
|
timer = setInterval(() => {
|
||||||
updateKey.value++
|
updateKey.value++
|
||||||
}, 1000)
|
}, 1000)
|
||||||
@@ -698,8 +739,6 @@ function init() {
|
|||||||
}, 2000)
|
}, 2000)
|
||||||
}
|
}
|
||||||
function dispose() {
|
function dispose() {
|
||||||
props.client.off('danmaku', onGetDanmaku)
|
|
||||||
props.client.off('sc', onGetSC)
|
|
||||||
clearInterval(timer)
|
clearInterval(timer)
|
||||||
clearInterval(updateActiveTimer)
|
clearInterval(updateActiveTimer)
|
||||||
}
|
}
|
||||||
@@ -707,6 +746,8 @@ onDeactivated(() => {
|
|||||||
dispose()
|
dispose()
|
||||||
})
|
})
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
props.client.off('danmaku', onGetDanmaku)
|
||||||
|
props.client.off('sc', onGetSC)
|
||||||
dispose()
|
dispose()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@@ -759,6 +800,7 @@ onUnmounted(() => {
|
|||||||
<NInput placeholder="手动添加" v-model:value="newSongName" />
|
<NInput placeholder="手动添加" v-model:value="newSongName" />
|
||||||
<NButton type="primary" @click="addSongManual"> 添加 </NButton>
|
<NButton type="primary" @click="addSongManual"> 添加 </NButton>
|
||||||
</NInputGroup>
|
</NInputGroup>
|
||||||
|
<NCheckbox v-model:checked="isReverse"> 倒序 </NCheckbox>
|
||||||
<NPopconfirm @positive-click="deactiveAllSongs">
|
<NPopconfirm @positive-click="deactiveAllSongs">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<NButton type="error"> 全部取消 </NButton>
|
<NButton type="error"> 全部取消 </NButton>
|
||||||
@@ -869,6 +911,21 @@ onUnmounted(() => {
|
|||||||
</template>
|
</template>
|
||||||
已完成演唱
|
已完成演唱
|
||||||
</NTooltip>
|
</NTooltip>
|
||||||
|
<NTooltip v-if="song.from == SongRequestFrom.Danmaku">
|
||||||
|
<template #trigger>
|
||||||
|
<NPopconfirm @positive-click="blockUser(song)">
|
||||||
|
<template #trigger>
|
||||||
|
<NButton circle type="warning" style="height: 30px; width: 30px" :loading="isLoading">
|
||||||
|
<template #icon>
|
||||||
|
<NIcon :component="PresenceBlocked16Regular" />
|
||||||
|
</template>
|
||||||
|
</NButton>
|
||||||
|
</template>
|
||||||
|
确定拉黑 {{ song.user?.name }} 吗
|
||||||
|
</NPopconfirm>
|
||||||
|
</template>
|
||||||
|
拉黑用户
|
||||||
|
</NTooltip>
|
||||||
<NTooltip>
|
<NTooltip>
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<NButton circle type="error" style="height: 30px; width: 30px" :loading="isLoading" @click="updateSongStatus(song, SongRequestStatus.Cancel)">
|
<NButton circle type="error" style="height: 30px; width: 30px" :loading="isLoading" @click="updateSongStatus(song, SongRequestStatus.Cancel)">
|
||||||
@@ -941,6 +998,7 @@ onUnmounted(() => {
|
|||||||
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
||||||
</NInputGroup>
|
</NInputGroup>
|
||||||
<NSpace align="center">
|
<NSpace align="center">
|
||||||
|
<NCheckbox v-model:checked="settings.enableOnStreaming" @update:checked="updateSettings" :disabled="!configCanEdit"> 仅在直播时才允许加入 </NCheckbox>
|
||||||
<NCheckbox v-model:checked="settings.allowAllDanmaku" @update:checked="updateSettings" :disabled="!configCanEdit"> 允许所有弹幕点歌 </NCheckbox>
|
<NCheckbox v-model:checked="settings.allowAllDanmaku" @update:checked="updateSettings" :disabled="!configCanEdit"> 允许所有弹幕点歌 </NCheckbox>
|
||||||
<template v-if="!settings.allowAllDanmaku">
|
<template v-if="!settings.allowAllDanmaku">
|
||||||
<NCheckbox v-model:checked="settings.needWearFanMedal" @update:checked="updateSettings" :disabled="!configCanEdit"> 需要拥有粉丝牌 </NCheckbox>
|
<NCheckbox v-model:checked="settings.needWearFanMedal" @update:checked="updateSettings" :disabled="!configCanEdit"> 需要拥有粉丝牌 </NCheckbox>
|
||||||
@@ -1003,6 +1061,8 @@ onUnmounted(() => {
|
|||||||
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
||||||
</NInputGroup>
|
</NInputGroup>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
|
<NDivider> OBS </NDivider>
|
||||||
|
<NCheckbox v-model:checked="settings.showRequireInfo" :disabled="!configCanEdit" @update:checked="updateSettings"> 显示底部的需求信息 </NCheckbox>
|
||||||
<NDivider> 其他 </NDivider>
|
<NDivider> 其他 </NDivider>
|
||||||
<NCheckbox v-model:checked="isWarnMessageAutoClose"> 自动关闭点歌失败时的提示消息 </NCheckbox>
|
<NCheckbox v-model:checked="isWarnMessageAutoClose"> 自动关闭点歌失败时的提示消息 </NCheckbox>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ const props = defineProps<{
|
|||||||
|
|
||||||
async function getUsers() {
|
async function getUsers() {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<UpdateLiveLotteryUsersModel>(LOTTERY_API_URL() + 'live/get-users', {
|
const data = await QueryGetAPI<UpdateLiveLotteryUsersModel>(LOTTERY_API_URL + 'live/get-users', {
|
||||||
code: props.code,
|
code: props.code,
|
||||||
})
|
})
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
@@ -114,7 +114,7 @@ async function getUsers() {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
function updateUsers() {
|
function updateUsers() {
|
||||||
QueryPostAPI(LOTTERY_API_URL() + 'live/update-users', {
|
QueryPostAPI(LOTTERY_API_URL + 'live/update-users', {
|
||||||
code: props.code,
|
code: props.code,
|
||||||
users: originUsers.value,
|
users: originUsers.value,
|
||||||
resultUsers: resultUsers.value,
|
resultUsers: resultUsers.value,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SaveEnableFunctions, useAccount } from '@/api/account'
|
import { AddBiliBlackList, SaveEnableFunctions, useAccount } from '@/api/account'
|
||||||
import {
|
import {
|
||||||
EventDataTypes,
|
EventDataTypes,
|
||||||
EventModel,
|
EventModel,
|
||||||
@@ -31,6 +31,7 @@ import {
|
|||||||
Mic24Filled,
|
Mic24Filled,
|
||||||
PeopleQueue24Filled,
|
PeopleQueue24Filled,
|
||||||
Play24Filled,
|
Play24Filled,
|
||||||
|
PresenceBlocked16Regular,
|
||||||
} from '@vicons/fluent'
|
} from '@vicons/fluent'
|
||||||
import { ReloadCircleSharp } from '@vicons/ionicons5'
|
import { ReloadCircleSharp } from '@vicons/ionicons5'
|
||||||
import { useStorage } from '@vueuse/core'
|
import { useStorage } from '@vueuse/core'
|
||||||
@@ -82,6 +83,7 @@ import QueueOBS from '../obs/QueueOBS.vue'
|
|||||||
|
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
keyword: '排队',
|
keyword: '排队',
|
||||||
|
enableOnStreaming: false,
|
||||||
queueMaxSize: 10,
|
queueMaxSize: 10,
|
||||||
allowAllDanmaku: true,
|
allowAllDanmaku: true,
|
||||||
allowFromWeb: true,
|
allowFromWeb: true,
|
||||||
@@ -90,7 +92,7 @@ const defaultSettings = {
|
|||||||
needTidu: false,
|
needTidu: false,
|
||||||
needZongdu: false,
|
needZongdu: false,
|
||||||
allowGift: true,
|
allowGift: true,
|
||||||
giftNames: ['小花花'],
|
giftNames: [],
|
||||||
minGiftPrice: 0.1,
|
minGiftPrice: 0.1,
|
||||||
allowIncreaseByAnyPayment: true,
|
allowIncreaseByAnyPayment: true,
|
||||||
allowIncreasePaymentBySendGift: true,
|
allowIncreasePaymentBySendGift: true,
|
||||||
@@ -103,6 +105,7 @@ const defaultSettings = {
|
|||||||
matchType: KeywordMatchType.Contains,
|
matchType: KeywordMatchType.Contains,
|
||||||
sortType: QueueSortType.TimeFirst,
|
sortType: QueueSortType.TimeFirst,
|
||||||
giftFilterType: QueueGiftFilterType.Or,
|
giftFilterType: QueueGiftFilterType.Or,
|
||||||
|
showRequireInfo: true,
|
||||||
} as Setting_Queue
|
} as Setting_Queue
|
||||||
const STATUS_MAP = {
|
const STATUS_MAP = {
|
||||||
[QueueStatus.Waiting]: '等待中',
|
[QueueStatus.Waiting]: '等待中',
|
||||||
@@ -117,6 +120,7 @@ const message = useMessage()
|
|||||||
const notice = useNotification()
|
const notice = useNotification()
|
||||||
|
|
||||||
const isWarnMessageAutoClose = useStorage('Queue.Settings.WarnMessageAutoClose', false)
|
const isWarnMessageAutoClose = useStorage('Queue.Settings.WarnMessageAutoClose', false)
|
||||||
|
const isReverse = useStorage('Queue.Settings.Reverse', false)
|
||||||
const volumn = useStorage('Settings.Volumn', 0.5)
|
const volumn = useStorage('Settings.Volumn', 0.5)
|
||||||
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
@@ -169,6 +173,9 @@ const queue = computed(() => {
|
|||||||
list = list.OrderByDescending((q) => q.giftPrice ?? 0).ThenByDescending((q) => q.createAt)
|
list = list.OrderByDescending((q) => q.giftPrice ?? 0).ThenByDescending((q) => q.createAt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isReverse.value) {
|
||||||
|
list = list.Reverse()
|
||||||
|
}
|
||||||
return list.ToArray()
|
return list.ToArray()
|
||||||
})
|
})
|
||||||
const historySongs = computed(() => {
|
const historySongs = computed(() => {
|
||||||
@@ -191,7 +198,7 @@ const table = ref()
|
|||||||
async function getAll() {
|
async function getAll() {
|
||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<ResponseQueueModel[]>(QUEUE_API_URL() + 'get-all', {
|
const data = await QueryGetAPI<ResponseQueueModel[]>(QUEUE_API_URL + 'get-all', {
|
||||||
id: accountInfo.value.id,
|
id: accountInfo.value.id,
|
||||||
})
|
})
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
@@ -214,8 +221,12 @@ async function add(danmaku: EventModel) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
console.log(`[OPEN-LIVE-QUEUE] 收到 [${danmaku.name}] 的排队请求`)
|
console.log(`[OPEN-LIVE-QUEUE] 收到 [${danmaku.name}] 的排队请求`)
|
||||||
|
if (settings.value.enableOnStreaming && accountInfo.value?.streamerInfo?.isStreaming != true) {
|
||||||
|
message.info('当前未在直播中, 无法添加排队请求. 或者关闭设置中的仅允许直播时加入')
|
||||||
|
return
|
||||||
|
}
|
||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
await QueryPostAPI<ResponseQueueModel>(QUEUE_API_URL() + 'try-add', danmaku).then((data) => {
|
await QueryPostAPI<ResponseQueueModel>(QUEUE_API_URL + 'try-add', danmaku).then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
if (data.message != 'EventFetcher') {
|
if (data.message != 'EventFetcher') {
|
||||||
//如果存在则替换, 否则插入最后
|
//如果存在则替换, 否则插入最后
|
||||||
@@ -269,7 +280,7 @@ async function addManual() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
await QueryPostAPIWithParams<ResponseQueueModel>(QUEUE_API_URL() + 'add', {
|
await QueryPostAPIWithParams<ResponseQueueModel>(QUEUE_API_URL + 'add', {
|
||||||
name: newQueueName.value,
|
name: newQueueName.value,
|
||||||
}).then((data) => {
|
}).then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
@@ -302,7 +313,7 @@ async function updateStatus(queueData: ResponseQueueModel, status: QueueStatus)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
await QueryGetAPI(QUEUE_API_URL() + 'set-status', {
|
await QueryGetAPI(QUEUE_API_URL + 'set-status', {
|
||||||
id: queueData.id,
|
id: queueData.id,
|
||||||
status: status,
|
status: status,
|
||||||
})
|
})
|
||||||
@@ -313,7 +324,7 @@ async function updateStatus(queueData: ResponseQueueModel, status: QueueStatus)
|
|||||||
if (status > QueueStatus.Progressing) {
|
if (status > QueueStatus.Progressing) {
|
||||||
queueData.finishAt = Date.now()
|
queueData.finishAt = Date.now()
|
||||||
}
|
}
|
||||||
message.success(`已更新队列状态为: ${STATUS_MAP[status]}`)
|
message.success(`已更新 [${queueData.user?.name}] 队列状态为: ${STATUS_MAP[status]}`)
|
||||||
} else {
|
} else {
|
||||||
console.log(`[OPEN-LIVE-QUEUE] 更新队列状态失败: ${data.message}`)
|
console.log(`[OPEN-LIVE-QUEUE] 更新队列状态失败: ${data.message}`)
|
||||||
message.error(`更新队列状态失败: ${data.message}`)
|
message.error(`更新队列状态失败: ${data.message}`)
|
||||||
@@ -424,7 +435,7 @@ async function onUpdateFunctionEnable() {
|
|||||||
async function updateSettings() {
|
async function updateSettings() {
|
||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
await QueryPostAPI(QUEUE_API_URL() + 'update-setting', settings.value)
|
await QueryPostAPI(QUEUE_API_URL + 'update-setting', settings.value)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('已保存')
|
message.success('已保存')
|
||||||
@@ -461,7 +472,7 @@ async function deleteQueue(values: ResponseQueueModel[]) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
async function deactiveAllSongs() {
|
async function deactiveAllSongs() {
|
||||||
await QueryGetAPI(QUEUE_API_URL() + 'deactive')
|
await QueryGetAPI(QUEUE_API_URL + 'deactive')
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
message.success('已全部取消')
|
message.success('已全部取消')
|
||||||
@@ -663,7 +674,7 @@ function GetGuardColor(level: number | null | undefined): string {
|
|||||||
async function updateActive() {
|
async function updateActive() {
|
||||||
if (!accountInfo.value) return
|
if (!accountInfo.value) return
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<ResponseQueueModel[]>(QUEUE_API_URL() + 'get-active', {
|
const data = await QueryGetAPI<ResponseQueueModel[]>(QUEUE_API_URL + 'get-active', {
|
||||||
id: accountInfo.value?.id,
|
id: accountInfo.value?.id,
|
||||||
})
|
})
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
@@ -688,6 +699,26 @@ async function updateActive() {
|
|||||||
}
|
}
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
}
|
}
|
||||||
|
function blockUser(item: ResponseQueueModel) {
|
||||||
|
if (item.from != QueueFrom.Danmaku) {
|
||||||
|
message.error(`[${item.user?.name}] 不是来自弹幕的用户`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (item.user) {
|
||||||
|
AddBiliBlackList(item.user.uid, item.user.name)
|
||||||
|
.then((data) => {
|
||||||
|
if (data.code == 200) {
|
||||||
|
message.success(`[${item.user?.name}] 已添加到黑名单`)
|
||||||
|
updateStatus(item, QueueStatus.Cancel)
|
||||||
|
} else {
|
||||||
|
message.error(data.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
message.error(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
let timer: any
|
let timer: any
|
||||||
let updateActiveTimer: any
|
let updateActiveTimer: any
|
||||||
const updateKey = ref(0)
|
const updateKey = ref(0)
|
||||||
@@ -695,6 +726,8 @@ onMounted(() => {
|
|||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
settings.value = accountInfo.value.settings.queue
|
settings.value = accountInfo.value.settings.queue
|
||||||
}
|
}
|
||||||
|
props.client.on('danmaku', onGetDanmaku)
|
||||||
|
props.client.on('gift', onGetGift)
|
||||||
init()
|
init()
|
||||||
})
|
})
|
||||||
onActivated(() => {
|
onActivated(() => {
|
||||||
@@ -702,8 +735,6 @@ onActivated(() => {
|
|||||||
})
|
})
|
||||||
function init() {
|
function init() {
|
||||||
dispose()
|
dispose()
|
||||||
props.client.on('danmaku', onGetDanmaku)
|
|
||||||
props.client.on('gift', onGetGift)
|
|
||||||
timer = setInterval(() => {
|
timer = setInterval(() => {
|
||||||
updateKey.value++
|
updateKey.value++
|
||||||
}, 1000)
|
}, 1000)
|
||||||
@@ -712,8 +743,6 @@ function init() {
|
|||||||
}, 2000)
|
}, 2000)
|
||||||
}
|
}
|
||||||
function dispose() {
|
function dispose() {
|
||||||
props.client.off('danmaku', onGetDanmaku)
|
|
||||||
props.client.off('gift', onGetGift)
|
|
||||||
clearInterval(timer)
|
clearInterval(timer)
|
||||||
clearInterval(updateActiveTimer)
|
clearInterval(updateActiveTimer)
|
||||||
}
|
}
|
||||||
@@ -721,6 +750,8 @@ onDeactivated(() => {
|
|||||||
dispose()
|
dispose()
|
||||||
})
|
})
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
props.client.off('danmaku', onGetDanmaku)
|
||||||
|
props.client.off('gift', onGetGift)
|
||||||
dispose()
|
dispose()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@@ -784,6 +815,7 @@ onUnmounted(() => {
|
|||||||
<NRadioButton :value="QueueSortType.PaymentFist"> 付费价格优先 </NRadioButton>
|
<NRadioButton :value="QueueSortType.PaymentFist"> 付费价格优先 </NRadioButton>
|
||||||
<NRadioButton :value="QueueSortType.GuardFirst"> 舰长优先 (按等级) </NRadioButton>
|
<NRadioButton :value="QueueSortType.GuardFirst"> 舰长优先 (按等级) </NRadioButton>
|
||||||
</NRadioGroup>
|
</NRadioGroup>
|
||||||
|
<NCheckbox v-model:checked="isReverse"> 倒序 </NCheckbox>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</NCard>
|
</NCard>
|
||||||
<NDivider> 共 {{ queue.length }} 人 </NDivider>
|
<NDivider> 共 {{ queue.length }} 人 </NDivider>
|
||||||
@@ -867,6 +899,21 @@ onUnmounted(() => {
|
|||||||
</template>
|
</template>
|
||||||
已完成
|
已完成
|
||||||
</NTooltip>
|
</NTooltip>
|
||||||
|
<NTooltip v-if="queueData.from == QueueFrom.Danmaku">
|
||||||
|
<template #trigger>
|
||||||
|
<NPopconfirm @positive-click="blockUser(queueData)">
|
||||||
|
<template #trigger>
|
||||||
|
<NButton circle type="warning" style="height: 30px; width: 30px" :loading="isLoading">
|
||||||
|
<template #icon>
|
||||||
|
<NIcon :component="PresenceBlocked16Regular" />
|
||||||
|
</template>
|
||||||
|
</NButton>
|
||||||
|
</template>
|
||||||
|
确定拉黑 {{ queueData.user?.name }} 吗
|
||||||
|
</NPopconfirm>
|
||||||
|
</template>
|
||||||
|
拉黑用户
|
||||||
|
</NTooltip>
|
||||||
<NTooltip>
|
<NTooltip>
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<NButton circle type="error" style="height: 30px; width: 30px" :loading="isLoading" @click="updateStatus(queueData, QueueStatus.Cancel)">
|
<NButton circle type="error" style="height: 30px; width: 30px" :loading="isLoading" @click="updateStatus(queueData, QueueStatus.Cancel)">
|
||||||
@@ -937,6 +984,7 @@ onUnmounted(() => {
|
|||||||
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
||||||
</NInputGroup>
|
</NInputGroup>
|
||||||
<NSpace align="center">
|
<NSpace align="center">
|
||||||
|
<NCheckbox v-model:checked="settings.enableOnStreaming" @update:checked="updateSettings" :disabled="!configCanEdit"> 仅在直播时才允许加入 </NCheckbox>
|
||||||
<NCheckbox v-model:checked="settings.allowAllDanmaku" @update:checked="updateSettings" :disabled="!configCanEdit"> 允许所有用户加入 </NCheckbox>
|
<NCheckbox v-model:checked="settings.allowAllDanmaku" @update:checked="updateSettings" :disabled="!configCanEdit"> 允许所有用户加入 </NCheckbox>
|
||||||
<template v-if="!settings.allowAllDanmaku">
|
<template v-if="!settings.allowAllDanmaku">
|
||||||
<NInputGroup style="width: 270px">
|
<NInputGroup style="width: 270px">
|
||||||
@@ -979,7 +1027,9 @@ onUnmounted(() => {
|
|||||||
</NRadioGroup>
|
</NRadioGroup>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<NCheckbox v-model:checked="settings.allowIncreasePaymentBySendGift" @update:checked="updateSettings" :disabled="!configCanEdit"> 在队列中时允许继续发送礼物累计付费量 (仅限上方设定的礼物) </NCheckbox>
|
<NCheckbox v-model:checked="settings.allowIncreasePaymentBySendGift" @update:checked="updateSettings" :disabled="!configCanEdit">
|
||||||
|
在队列中时允许继续发送礼物累计付费量 (仅限上方设定的礼物)
|
||||||
|
</NCheckbox>
|
||||||
<NCheckbox v-model:checked="settings.allowIncreasePaymentBySendGift" @update:checked="updateSettings" :disabled="!configCanEdit"> 允许发送任意礼物来叠加付费量 </NCheckbox>
|
<NCheckbox v-model:checked="settings.allowIncreasePaymentBySendGift" @update:checked="updateSettings" :disabled="!configCanEdit"> 允许发送任意礼物来叠加付费量 </NCheckbox>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
<NDivider> 冷却 (单位: 秒) </NDivider>
|
<NDivider> 冷却 (单位: 秒) </NDivider>
|
||||||
@@ -1006,6 +1056,8 @@ onUnmounted(() => {
|
|||||||
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
<NButton @click="updateSettings" type="info" :disabled="!configCanEdit">确定</NButton>
|
||||||
</NInputGroup>
|
</NInputGroup>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
|
<NDivider> OBS </NDivider>
|
||||||
|
<NCheckbox v-model:checked="settings.showRequireInfo" :disabled="!configCanEdit" @update:checked="updateSettings"> 显示底部的需求信息 </NCheckbox>
|
||||||
<NDivider> 其他 </NDivider>
|
<NDivider> 其他 </NDivider>
|
||||||
<NCheckbox v-model:checked="isWarnMessageAutoClose"> 自动关闭加入队列失败时的提示消息 </NCheckbox>
|
<NCheckbox v-model:checked="isWarnMessageAutoClose"> 自动关闭加入队列失败时的提示消息 </NCheckbox>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ function OnFileListChange(files: UploadFileInfo[]) {
|
|||||||
}
|
}
|
||||||
function getPublicQuestions() {
|
function getPublicQuestions() {
|
||||||
isGetting.value = true
|
isGetting.value = true
|
||||||
QueryGetAPI<QAInfo[]>(QUESTION_API_URL() + 'get-public', {
|
QueryGetAPI<QAInfo[]>(QUESTION_API_URL + 'get-public', {
|
||||||
id: userInfo?.id,
|
id: userInfo?.id,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const errMessage = ref('')
|
|||||||
|
|
||||||
async function get() {
|
async function get() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
await QueryGetAPI<ScheduleWeekInfo[]>(SCHEDULE_API_URL() + 'get', {
|
await QueryGetAPI<ScheduleWeekInfo[]>(SCHEDULE_API_URL + 'get', {
|
||||||
id: props.userInfo?.id,
|
id: props.userInfo?.id,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const settings = ref<Setting_SongRequest>({} as Setting_SongRequest)
|
|||||||
|
|
||||||
async function getSongRequestInfo() {
|
async function getSongRequestInfo() {
|
||||||
try {
|
try {
|
||||||
const data = await QueryGetAPI<{ songs: SongRequestInfo[]; setting: Setting_SongRequest }>(SONG_REQUEST_API_URL() + 'get-active-and-settings', {
|
const data = await QueryGetAPI<{ songs: SongRequestInfo[]; setting: Setting_SongRequest }>(SONG_REQUEST_API_URL + 'get-active-and-settings', {
|
||||||
id: props.userInfo?.id,
|
id: props.userInfo?.id,
|
||||||
})
|
})
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
@@ -56,7 +56,7 @@ async function getSongRequestInfo() {
|
|||||||
}
|
}
|
||||||
async function getSongs() {
|
async function getSongs() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
await QueryGetAPI<SongsInfo[]>(SONG_API_URL() + 'get', {
|
await QueryGetAPI<SongsInfo[]>(SONG_API_URL + 'get', {
|
||||||
id: props.userInfo?.id,
|
id: props.userInfo?.id,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
@@ -85,7 +85,7 @@ async function requestSong(song: SongsInfo) {
|
|||||||
} else {
|
} else {
|
||||||
if (props.userInfo) {
|
if (props.userInfo) {
|
||||||
try {
|
try {
|
||||||
const data = await QueryPostAPIWithParams(SONG_REQUEST_API_URL() + 'add-from-web', {
|
const data = await QueryPostAPIWithParams(SONG_REQUEST_API_URL + 'add-from-web', {
|
||||||
target: props.userInfo?.id,
|
target: props.userInfo?.id,
|
||||||
song: song.key,
|
song: song.key,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user