mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-07 02:46:55 +08:00
update song-request to live-request, add questionbox tag support
This commit is contained in:
@@ -16,6 +16,7 @@ import {
|
||||
NInput,
|
||||
NList,
|
||||
NListItem,
|
||||
NSelect,
|
||||
NSpace,
|
||||
NText,
|
||||
NTime,
|
||||
@@ -47,6 +48,8 @@ const isSelf = computed(() => {
|
||||
const questionMessage = ref('')
|
||||
const fileList = ref<UploadFileInfo[]>([])
|
||||
const publicQuestions = ref<QAInfo[]>([])
|
||||
const tags = ref<string[]>([])
|
||||
const selectedTag = ref()
|
||||
|
||||
const isAnonymous = ref(true)
|
||||
const isSending = ref(false)
|
||||
@@ -57,7 +60,7 @@ function countGraphemes(value: string) {
|
||||
}
|
||||
async function SendQuestion() {
|
||||
if (countGraphemes(questionMessage.value) < 3) {
|
||||
message.error('内容最少需要10个字')
|
||||
message.error('内容最少需要3个字')
|
||||
return
|
||||
}
|
||||
isSending.value = true
|
||||
@@ -68,6 +71,7 @@ async function SendQuestion() {
|
||||
IsAnonymous: !accountInfo.value || isAnonymous.value,
|
||||
Message: questionMessage.value,
|
||||
ImageBase64: fileList.value?.length > 0 ? await getBase64(fileList.value[0].file) : undefined,
|
||||
Tag: selectedTag.value,
|
||||
},
|
||||
[['Turnstile', token.value]],
|
||||
)
|
||||
@@ -125,9 +129,29 @@ function getPublicQuestions() {
|
||||
isGetting.value = false
|
||||
})
|
||||
}
|
||||
function getTags() {
|
||||
isGetting.value = true
|
||||
QueryGetAPI<string[]>(QUESTION_API_URL + 'get-tags', {
|
||||
id: userInfo?.id,
|
||||
})
|
||||
.then((data) => {
|
||||
if (data.code == 200) {
|
||||
tags.value = data.data
|
||||
} else {
|
||||
message.error('获取标签失败:' + data.message)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
message.error('获取标签失败: ' + err)
|
||||
})
|
||||
.finally(() => {
|
||||
isGetting.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getPublicQuestions()
|
||||
getTags()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
@@ -140,6 +164,16 @@ onUnmounted(() => {
|
||||
<NCard embedded>
|
||||
<NSpace vertical>
|
||||
<NSpace align="center" justify="center">
|
||||
<NSelect
|
||||
v-model:value="selectedTag"
|
||||
placeholder="(可选) 要提问的话题"
|
||||
filterable
|
||||
clearable
|
||||
:options="tags.map((s) => ({ label: s, value: s }))"
|
||||
style="width: 200px"
|
||||
>
|
||||
<template #header> 不选的话则是默认话题 </template>
|
||||
</NSelect>
|
||||
<NInput
|
||||
:disabled="isSelf"
|
||||
show-count
|
||||
@@ -153,7 +187,7 @@ onUnmounted(() => {
|
||||
:max="1"
|
||||
accept=".png,.jpg,.jpeg,.gif,.svg,.webp,.ico"
|
||||
list-type="image-card"
|
||||
:disabled="!accountInfo || isSelf"
|
||||
:disabled="!accountInfo.id || isSelf"
|
||||
:default-upload="false"
|
||||
v-model:file-list="fileList"
|
||||
@update:file-list="OnFileListChange"
|
||||
@@ -163,19 +197,18 @@ onUnmounted(() => {
|
||||
</NSpace>
|
||||
<NDivider style="margin: 10px 0 10px 0" />
|
||||
<NSpace align="center">
|
||||
<NAlert v-if="!accountInfo && !isSelf" type="warning"> 只有注册用户才能够上传图片 </NAlert>
|
||||
<NAlert v-if="!accountInfo.id && !isSelf" type="warning"> 只有注册用户才能够上传图片 </NAlert>
|
||||
</NSpace>
|
||||
<NSpace vertical>
|
||||
<NCheckbox v-if="accountInfo" :disabled="isSelf" v-model:checked="isAnonymous" label="匿名提问" />
|
||||
<NSpace v-if="accountInfo.id" vertical>
|
||||
<NCheckbox :disabled="isSelf" v-model:checked="isAnonymous" label="匿名提问" />
|
||||
<NDivider style="margin: 10px 0 10px 0" />
|
||||
</NSpace>
|
||||
<NDivider style="margin: 10px 0 10px 0" />
|
||||
<NSpace justify="center">
|
||||
<NButton :disabled="isSelf" type="primary" :loading="isSending || !token" @click="SendQuestion">
|
||||
发送
|
||||
</NButton>
|
||||
<NButton
|
||||
v-if="accountInfo"
|
||||
:disabled="isSelf"
|
||||
:disabled="isSelf || !accountInfo.id"
|
||||
type="info"
|
||||
@click="$router.push({ name: 'manage-questionBox', query: { send: '1' } })"
|
||||
>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
:user-info="userInfo"
|
||||
:bili-info="biliInfo"
|
||||
:currentData="currentData"
|
||||
:song-request-settings="settings"
|
||||
:song-request-active="songsActive"
|
||||
:live-request-settings="settings"
|
||||
:live-request-active="songsActive"
|
||||
@request-song="requestSong"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useAccount } from '@/api/account'
|
||||
import { Setting_SongRequest, SongRequestInfo, SongsInfo, UserInfo } from '@/api/api-models'
|
||||
import { Setting_LiveRequest, SongRequestInfo, SongsInfo, UserInfo } from '@/api/api-models'
|
||||
import { QueryGetAPI, QueryPostAPIWithParams } from '@/api/query'
|
||||
import { SONG_API_URL, SONG_REQUEST_API_URL, SongListTemplateMap } from '@/data/constants'
|
||||
import { NSpin, useMessage } from 'naive-ui'
|
||||
@@ -40,11 +40,11 @@ const message = useMessage()
|
||||
|
||||
const errMessage = ref('')
|
||||
const songsActive = ref<SongRequestInfo[]>([])
|
||||
const settings = ref<Setting_SongRequest>({} as Setting_SongRequest)
|
||||
const settings = ref<Setting_LiveRequest>({} as Setting_LiveRequest)
|
||||
|
||||
async function getSongRequestInfo() {
|
||||
try {
|
||||
const data = await QueryGetAPI<{ songs: SongRequestInfo[]; setting: Setting_SongRequest }>(
|
||||
const data = await QueryGetAPI<{ songs: SongRequestInfo[]; setting: Setting_LiveRequest }>(
|
||||
SONG_REQUEST_API_URL + 'get-active-and-settings',
|
||||
{
|
||||
id: props.userInfo?.id,
|
||||
@@ -54,7 +54,7 @@ async function getSongRequestInfo() {
|
||||
return data.data
|
||||
}
|
||||
} catch (err) {}
|
||||
return {} as { songs: SongRequestInfo[]; setting: Setting_SongRequest }
|
||||
return {} as { songs: SongRequestInfo[]; setting: Setting_LiveRequest }
|
||||
}
|
||||
async function getSongs() {
|
||||
isLoading.value = true
|
||||
|
||||
15
src/views/view/VideoCollectView.vue
Normal file
15
src/views/view/VideoCollectView.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script lang="ts" setup>
|
||||
import { UserInfo } from '@/api/api-models'
|
||||
|
||||
const props = defineProps<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
biliInfo: any | undefined
|
||||
userInfo: UserInfo | undefined
|
||||
template?: string | undefined
|
||||
}>()
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
1
|
||||
</template>
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useAccount } from '@/api/account'
|
||||
import { Setting_SongRequest, SongRequestInfo, SongsInfo, UserInfo } from '@/api/api-models'
|
||||
import { Setting_LiveRequest, SongRequestInfo, SongsInfo, UserInfo } from '@/api/api-models'
|
||||
import SongList from '@/components/SongList.vue'
|
||||
import SongRequestOBS from '@/views/obs/SongRequestOBS.vue'
|
||||
import { CloudAdd20Filled } from '@vicons/fluent'
|
||||
@@ -13,7 +13,7 @@ const accountInfo = useAccount()
|
||||
const props = defineProps<{
|
||||
userInfo: UserInfo | undefined
|
||||
biliInfo: any | undefined
|
||||
songRequestSettings: Setting_SongRequest
|
||||
songRequestSettings: Setting_LiveRequest
|
||||
songRequestActive: SongRequestInfo[]
|
||||
currentData?: SongsInfo[] | undefined
|
||||
}>()
|
||||
@@ -48,7 +48,11 @@ const buttoms = (song: SongsInfo) => [
|
||||
},
|
||||
),
|
||||
default: () =>
|
||||
!props.songRequestSettings.allowFromWeb || song.options ? '点歌 | 用户不允许从网页点歌, 点击后将复制点歌内容到剪切板' : !accountInfo ? '点歌 | 你需要登录后才能点歌' : '点歌',
|
||||
!props.songRequestSettings.allowFromWeb || song.options
|
||||
? '点歌 | 用户不允许从网页点歌, 点击后将复制点歌内容到剪切板'
|
||||
: !accountInfo
|
||||
? '点歌 | 你需要登录后才能点歌'
|
||||
: '点歌',
|
||||
},
|
||||
)
|
||||
: undefined,
|
||||
@@ -57,7 +61,13 @@ const buttoms = (song: SongsInfo) => [
|
||||
|
||||
<template>
|
||||
<NDivider style="margin-top: 10px" />
|
||||
<SongList v-if="currentData" :songs="currentData ?? []" :is-self="accountInfo?.id == userInfo?.id" :extra-buttom="buttoms" v-bind="$attrs" />
|
||||
<SongList
|
||||
v-if="currentData"
|
||||
:songs="currentData ?? []"
|
||||
:is-self="accountInfo?.id == userInfo?.id"
|
||||
:extra-buttom="buttoms"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
<NCollapse v-if="userInfo?.canRequestSong">
|
||||
<NCollapseItem title="点歌列表">
|
||||
<NCard size="small" embedded>
|
||||
|
||||
@@ -1,19 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
import { GetGuardColor } from '@/Utils'
|
||||
import { useAccount } from '@/api/account'
|
||||
import { FunctionTypes, Setting_SongRequest, SongRequestInfo, SongsInfo, UserInfo } from '@/api/api-models'
|
||||
import { FunctionTypes, Setting_LiveRequest, SongRequestInfo, SongsInfo, UserInfo } from '@/api/api-models'
|
||||
import SongPlayer from '@/components/SongPlayer.vue'
|
||||
import SongRequestOBS from '@/views/obs/SongRequestOBS.vue'
|
||||
import { CloudAdd20Filled, Play24Filled } from '@vicons/fluent'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
import { throttle } from 'lodash'
|
||||
import { NButton, NCard, NCollapseTransition, NDivider, NEllipsis, NEmpty, NGrid, NGridItem, NIcon, NInput, NPopover, NScrollbar, NSelect, NSpace, NTag, NText, NTooltip } from 'naive-ui'
|
||||
import {
|
||||
NButton,
|
||||
NCard,
|
||||
NCollapseTransition,
|
||||
NDivider,
|
||||
NEllipsis,
|
||||
NEmpty,
|
||||
NGrid,
|
||||
NGridItem,
|
||||
NIcon,
|
||||
NInput,
|
||||
NPopover,
|
||||
NScrollbar,
|
||||
NSelect,
|
||||
NSpace,
|
||||
NTag,
|
||||
NText,
|
||||
NTooltip,
|
||||
} from 'naive-ui'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
userInfo: UserInfo | undefined
|
||||
biliInfo: any | undefined
|
||||
songRequestSettings: Setting_SongRequest
|
||||
songRequestSettings: Setting_LiveRequest
|
||||
songRequestActive: SongRequestInfo[]
|
||||
currentData: SongsInfo[] | undefined
|
||||
}>()
|
||||
@@ -86,14 +104,28 @@ function loadMore() {
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div :style="{ display: 'flex', justifyContent: 'center', flexDirection: windowSize.width.value > 900 ? 'row' : 'column', gap: '10px', width: '100%' }">
|
||||
<div
|
||||
:style="{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
flexDirection: windowSize.width.value > 900 ? 'row' : 'column',
|
||||
gap: '10px',
|
||||
width: '100%',
|
||||
}"
|
||||
>
|
||||
<NCard size="small" :style="{ width: windowSize.width.value > 900 ? '400px' : '100%' }">
|
||||
<NCollapseTransition>
|
||||
<SongPlayer v-if="selectedSong" :song="selectedSong" v-model:is-lrc-loading="isLrcLoading" />
|
||||
</NCollapseTransition>
|
||||
<NDivider> 标签 </NDivider>
|
||||
<NSpace>
|
||||
<NButton v-for="tag in tags" size="small" secondary :type="selectedTag == tag ? 'primary' : 'default'" @click="selectedTag == tag ? (selectedTag = '') : (selectedTag = tag)">
|
||||
<NButton
|
||||
v-for="tag in tags"
|
||||
size="small"
|
||||
secondary
|
||||
:type="selectedTag == tag ? 'primary' : 'default'"
|
||||
@click="selectedTag == tag ? (selectedTag = '') : (selectedTag = tag)"
|
||||
>
|
||||
{{ tag }}
|
||||
</NButton>
|
||||
</NSpace>
|
||||
@@ -111,17 +143,32 @@ function loadMore() {
|
||||
clearable
|
||||
/>
|
||||
<NDivider />
|
||||
<SongRequestOBS v-if="userInfo?.extra?.enableFunctions.includes(FunctionTypes.SongRequest)" :id="userInfo?.id" />
|
||||
<SongRequestOBS
|
||||
v-if="userInfo?.extra?.enableFunctions.includes(FunctionTypes.SongRequest)"
|
||||
:id="userInfo?.id"
|
||||
/>
|
||||
</NSpace>
|
||||
</NCard>
|
||||
<NEmpty v-if="!currentData || songs?.length == 0" description="暂无曲目" style="max-width: 0 auto" />
|
||||
<NScrollbar v-else ref="container" :style="{ flexGrow: 1, height: windowSize.width.value > 900 ? '90vh' : '800px', overflowY: 'auto', overflowX: 'hidden' }" @scroll="onScroll">
|
||||
<NScrollbar
|
||||
v-else
|
||||
ref="container"
|
||||
:style="{
|
||||
flexGrow: 1,
|
||||
height: windowSize.width.value > 900 ? '90vh' : '800px',
|
||||
overflowY: 'auto',
|
||||
overflowX: 'hidden',
|
||||
}"
|
||||
@scroll="onScroll"
|
||||
>
|
||||
<NGrid cols="1 600:2 900:3 1200:4" x-gap="10" y-gap="10" responsive="self">
|
||||
<NGridItem v-for="item in songs" :key="item.key">
|
||||
<NCard size="small" style="height: 200px; min-width: 300px">
|
||||
<template #header>
|
||||
<NSpace :wrap="false" align="center">
|
||||
<div :style="`border-radius: 4px; background-color: ${item.options ? '#bd5757' : '#577fb8'}; width: 7px; height: 20px`"></div>
|
||||
<div
|
||||
:style="`border-radius: 4px; background-color: ${item.options ? '#bd5757' : '#577fb8'}; width: 7px; height: 20px`"
|
||||
></div>
|
||||
<NEllipsis>
|
||||
{{ item.name }}
|
||||
</NEllipsis>
|
||||
@@ -130,7 +177,11 @@ function loadMore() {
|
||||
<NSpace vertical>
|
||||
<NSpace v-if="(item.author?.length ?? 0) > 0" :size="0">
|
||||
<div v-for="(author, index) in item.author" v-bind:key="author">
|
||||
<NButton size="small" text @click="selectedAuthor == author ? (selectedAuthor = undefined) : (selectedAuthor = author)">
|
||||
<NButton
|
||||
size="small"
|
||||
text
|
||||
@click="selectedAuthor == author ? (selectedAuthor = undefined) : (selectedAuthor = author)"
|
||||
>
|
||||
<NText depth="3" :style="{ color: selectedAuthor == author ? '#82bcd3' : '' }">
|
||||
{{ author }}
|
||||
</NText>
|
||||
@@ -146,11 +197,19 @@ function loadMore() {
|
||||
</NEllipsis>
|
||||
<template v-if="item.options">
|
||||
<NSpace>
|
||||
<NTag v-if="item.options?.scMinPrice" size="small" type="error" :bordered="false"> SC | {{ item.options?.scMinPrice }}</NTag>
|
||||
<NTag v-if="item.options?.fanMedalMinLevel" size="small" type="info" :bordered="false"> 粉丝牌 | {{ item.options?.fanMedalMinLevel }}</NTag>
|
||||
<NTag v-if="item.options?.needZongdu" size="small" :color="{ color: GetGuardColor(1) }"> 总督 </NTag>
|
||||
<NTag v-if="item.options?.scMinPrice" size="small" type="error" :bordered="false">
|
||||
SC | {{ item.options?.scMinPrice }}</NTag
|
||||
>
|
||||
<NTag v-if="item.options?.fanMedalMinLevel" size="small" type="info" :bordered="false">
|
||||
粉丝牌 | {{ item.options?.fanMedalMinLevel }}</NTag
|
||||
>
|
||||
<NTag v-if="item.options?.needZongdu" size="small" :color="{ color: GetGuardColor(1) }">
|
||||
总督
|
||||
</NTag>
|
||||
<NTag v-if="item.options?.needTidu" size="small" :color="{ color: GetGuardColor(2) }"> 提督 </NTag>
|
||||
<NTag v-if="item.options?.needJianzhang" size="small" :color="{ color: GetGuardColor(3) }"> 舰长 </NTag>
|
||||
<NTag v-if="item.options?.needJianzhang" size="small" :color="{ color: GetGuardColor(3) }">
|
||||
舰长
|
||||
</NTag>
|
||||
</NSpace>
|
||||
</template>
|
||||
</NSpace>
|
||||
@@ -159,7 +218,12 @@ function loadMore() {
|
||||
<NSpace align="center" :wrap="false">
|
||||
<NTooltip v-if="item.url">
|
||||
<template #trigger>
|
||||
<NButton size="small" @click="selectedSong = item" type="success" :loading="isLrcLoading == item.key">
|
||||
<NButton
|
||||
size="small"
|
||||
@click="selectedSong = item"
|
||||
type="success"
|
||||
:loading="isLrcLoading == item.key"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="Play24Filled" />
|
||||
</template>
|
||||
@@ -197,7 +261,9 @@ function loadMore() {
|
||||
|
||||
<NPopover v-if="(item.tags?.length ?? 0) > 3" trigger="hover">
|
||||
<template #trigger>
|
||||
<NButton size="small" secondary :type="item.tags?.includes(selectedTag) ? 'primary' : 'default'"> 标签 </NButton>
|
||||
<NButton size="small" secondary :type="item.tags?.includes(selectedTag) ? 'primary' : 'default'">
|
||||
标签
|
||||
</NButton>
|
||||
</template>
|
||||
<NSpace :wrap="false">
|
||||
<NButton
|
||||
|
||||
Reference in New Issue
Block a user