mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-10 20:36:55 +08:00
重构多个组件以优化代码格式和可读性,删除不必要的文件,更新类型定义,添加数据分析路由
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import { useAccount } from '@/api/account'
|
||||
import { QAInfo, UserInfo } from '@/api/api-models'
|
||||
import { QueryGetAPI, QueryPostAPI } from '@/api/query'
|
||||
import { QUESTION_API_URL, TURNSTILE_KEY } from '@/data/constants'
|
||||
import { AVATAR_URL, QUESTION_API_URL, TURNSTILE_KEY } from '@/data/constants'
|
||||
import GraphemeSplitter from 'grapheme-splitter'
|
||||
import {
|
||||
NAlert,
|
||||
@@ -264,7 +264,7 @@ onUnmounted(() => {
|
||||
</NCard>
|
||||
<template v-if="item.answer" #footer>
|
||||
<NSpace align="center" :size="6" :wrap="false">
|
||||
<NAvatar :src="biliInfo?.face + '@64w'" circle :size="45" :img-props="{ referrerpolicy: 'no-referrer' }" />
|
||||
<NAvatar :src="AVATAR_URL + userInfo?.biliId + '?size=64'" circle :size="45" :img-props="{ referrerpolicy: 'no-referrer' }" />
|
||||
<NDivider vertical />
|
||||
<NText style="font-size: 16px">
|
||||
{{ item.answer?.message }}
|
||||
|
||||
@@ -1,24 +1,41 @@
|
||||
<template>
|
||||
<NSpin v-if="isLoading" show />
|
||||
<component
|
||||
v-else
|
||||
:is="ScheduleTemplateMap[componentType ?? ''].compoent"
|
||||
:bili-info="biliInfo"
|
||||
:user-info="userInfo"
|
||||
:data="currentData"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
<div v-else>
|
||||
<NDivider style="margin: 16px 0 16px 0" title-placement="left">
|
||||
订阅链接
|
||||
<NTooltip>
|
||||
<template #trigger>
|
||||
<NIcon>
|
||||
<TagQuestionMark16Filled />
|
||||
</NIcon>
|
||||
</template>
|
||||
通过订阅链接可以订阅日程表到日历软件中
|
||||
</NTooltip>
|
||||
</NDivider>
|
||||
<NFlex align="center">
|
||||
<NInputGroup style="max-width: 400px;">
|
||||
<NInput :value="`${SCHEDULE_API_URL}${userInfo?.id}.ics`" readonly />
|
||||
<NButton secondary @click="copyToClipboard(`${SCHEDULE_API_URL}${userInfo?.id}.ics`)">
|
||||
复制
|
||||
</NButton>
|
||||
</NInputGroup>
|
||||
</NFlex>
|
||||
<NDivider />
|
||||
<component :is="ScheduleTemplateMap[componentType ?? ''].compoent" :bili-info="biliInfo"
|
||||
:user-info="userInfo" :data="currentData" v-bind="$attrs" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ScheduleWeekInfo, UserInfo } from '@/api/api-models'
|
||||
import { QueryGetAPI } from '@/api/query'
|
||||
import { SCHEDULE_API_URL, ScheduleTemplateMap } from '@/data/constants'
|
||||
import { NSpin, useMessage } from 'naive-ui'
|
||||
import { copyToClipboard } from '@/Utils'
|
||||
import { TagQuestionMark16Filled } from '@vicons/fluent'
|
||||
import { NButton, NDivider, NFlex, NInput, NInputGroup, NSpin, NTooltip, useMessage } from 'naive-ui'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
biliInfo: any | undefined
|
||||
userInfo: UserInfo | undefined
|
||||
template?: string | undefined
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
<template>
|
||||
<NSpin v-if="isLoading" show />
|
||||
<component v-else ref="dynamicConfigRef" :config="selectedTemplateConfig?.name ? currentConfig : undefined"
|
||||
:is="SongListTemplateMap[componentType ?? '']?.compoent" :user-info="userInfo" :bili-info="biliInfo"
|
||||
:data="currentData" :live-request-settings="settings" :live-request-active="songsActive" @request-song="requestSong"
|
||||
v-bind="$attrs" />
|
||||
<NSpin
|
||||
v-if="isLoading"
|
||||
show
|
||||
/>
|
||||
<component
|
||||
:is="SongListTemplateMap[componentType ?? '']?.compoent"
|
||||
v-else
|
||||
ref="dynamicConfigRef"
|
||||
:config="selectedTemplateConfig?.name ? currentConfig : undefined"
|
||||
:user-info="userInfo"
|
||||
:bili-info="biliInfo"
|
||||
:data="currentData"
|
||||
:live-request-settings="settings"
|
||||
:live-request-active="songsActive"
|
||||
v-bind="$attrs"
|
||||
@request-song="requestSong"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@@ -23,7 +35,6 @@ const nextRequestTime = useStorage('SongList.NextRequestTime', new Date())
|
||||
const minRequestTime = 30
|
||||
|
||||
const props = defineProps<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
biliInfo: any | undefined
|
||||
userInfo: UserInfo | undefined
|
||||
template?: string | undefined
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<component :is="componentType" :user-info="userInfo" :bili-info="biliInfo" />
|
||||
<component
|
||||
:is="componentType"
|
||||
:user-info="userInfo"
|
||||
:bili-info="biliInfo"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@@ -8,7 +12,6 @@ import DefaultIndexTemplate from '@/views/view/indexTemplate/DefaultIndexTemplat
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
biliInfo: any | undefined
|
||||
userInfo: UserInfo | undefined
|
||||
template?: string | undefined
|
||||
|
||||
@@ -7,7 +7,6 @@ import { NEmpty, NFlex, NList, NListItem, NSpin, useMessage } from 'naive-ui'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
biliInfo: any | undefined
|
||||
userInfo: UserInfo
|
||||
template?: string | undefined
|
||||
@@ -42,10 +41,21 @@ async function get() {
|
||||
<template>
|
||||
<NSpin :show="isLoading">
|
||||
<NFlex justify="center">
|
||||
<NEmpty v-if="videoTables.length == 0" description="没有正在进行的征集表" />
|
||||
<NEmpty
|
||||
v-if="videoTables.length == 0"
|
||||
description="没有正在进行的征集表"
|
||||
/>
|
||||
<NList v-else>
|
||||
<NListItem v-for="item in videoTables" :key="item.id">
|
||||
<VideoCollectInfoCard :item="item" canClick style="width: 500px; max-width: 70vw" from="user" />
|
||||
<NListItem
|
||||
v-for="item in videoTables"
|
||||
:key="item.id"
|
||||
>
|
||||
<VideoCollectInfoCard
|
||||
:item="item"
|
||||
can-click
|
||||
style="width: 500px; max-width: 70vw"
|
||||
from="user"
|
||||
/>
|
||||
</NListItem>
|
||||
</NList>
|
||||
</NFlex>
|
||||
|
||||
@@ -54,24 +54,44 @@ function delReply(id: number) {
|
||||
:src="VTSURU_API_URL + 'user-face/' + item.user.id + '?size=64'"
|
||||
:img-props="{ referrerpolicy: 'no-referrer' }"
|
||||
/>
|
||||
<NFlex vertical style="flex: 1" :size="2">
|
||||
<NFlex
|
||||
vertical
|
||||
style="flex: 1"
|
||||
:size="2"
|
||||
>
|
||||
<NFlex align="center">
|
||||
<NTag v-if="item.isDeleted" type="warning" :bordered="false"> 已删除 </NTag>
|
||||
<NTag
|
||||
v-if="item.isDeleted"
|
||||
type="warning"
|
||||
:bordered="false"
|
||||
>
|
||||
已删除
|
||||
</NTag>
|
||||
<NText>
|
||||
{{ item.user.name }}
|
||||
</NText>
|
||||
<NText depth="3">
|
||||
<NTooltip>
|
||||
<template #trigger>
|
||||
<NTime :time="item.sendAt" type="relative" />
|
||||
<NTime
|
||||
:time="item.sendAt"
|
||||
type="relative"
|
||||
/>
|
||||
</template>
|
||||
<NTime :time="item.sendAt" />
|
||||
</NTooltip>
|
||||
</NText>
|
||||
</NFlex>
|
||||
<div class="editor-content-view" v-html="item.content"></div>
|
||||
<div
|
||||
class="editor-content-view"
|
||||
v-html="item.content"
|
||||
/>
|
||||
|
||||
<NCard v-if="item.replies.length > 0" size="small" style="margin-bottom: 10px">
|
||||
<NCard
|
||||
v-if="item.replies.length > 0"
|
||||
size="small"
|
||||
style="margin-bottom: 10px"
|
||||
>
|
||||
<NFlex vertical>
|
||||
<ForumReplyItem
|
||||
v-for="reply in item.replies"
|
||||
@@ -79,7 +99,7 @@ function delReply(id: number) {
|
||||
:item="reply"
|
||||
:comment="item"
|
||||
:topic="topic"
|
||||
showReplyButton
|
||||
show-reply-button
|
||||
:reply-to="reply.replyTo ? item.replies.find((r) => r.id === reply.replyTo) : undefined"
|
||||
:reply-to-id="reply.replyTo"
|
||||
@delete="delReply"
|
||||
@@ -91,6 +111,9 @@ function delReply(id: number) {
|
||||
<template #trigger>
|
||||
<NButton
|
||||
size="small"
|
||||
text
|
||||
:loading="useForum.isLikeLoading"
|
||||
:disabled="!canOprate"
|
||||
@click="
|
||||
useForum.LikeComment(item.id, !item.isLiked).then((success) => {
|
||||
if (success) {
|
||||
@@ -99,12 +122,12 @@ function delReply(id: number) {
|
||||
}
|
||||
})
|
||||
"
|
||||
text
|
||||
:loading="useForum.isLikeLoading"
|
||||
:disabled="!canOprate"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="item.isLiked ? Heart : HeartOutline" :color="item.isLiked ? '#dd484f' : ''" />
|
||||
<NIcon
|
||||
:component="item.isLiked ? Heart : HeartOutline"
|
||||
:color="item.isLiked ? '#dd484f' : ''"
|
||||
/>
|
||||
</template>
|
||||
{{ item.likeCount }}
|
||||
</NButton>
|
||||
@@ -113,7 +136,12 @@ function delReply(id: number) {
|
||||
</NTooltip>
|
||||
<NTooltip>
|
||||
<template #trigger>
|
||||
<NButton size="small" @click="useForum.SetReplyingComment(item)" text :disabled="!canOprate">
|
||||
<NButton
|
||||
size="small"
|
||||
text
|
||||
:disabled="!canOprate"
|
||||
@click="useForum.SetReplyingComment(item)"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="ArrowReply16Filled" />
|
||||
</template>
|
||||
@@ -122,12 +150,19 @@ function delReply(id: number) {
|
||||
</template>
|
||||
回复
|
||||
</NTooltip>
|
||||
<NFlex style="flex: 1" justify="end">
|
||||
<NFlex
|
||||
style="flex: 1"
|
||||
justify="end"
|
||||
>
|
||||
<NTooltip v-if="item.user.id === accountInfo.id || topic.isAdmin">
|
||||
<template #trigger>
|
||||
<NPopconfirm @positive-click="delComment(item.id)">
|
||||
<template #trigger>
|
||||
<NButton size="small" text :disabled="!canOprate">
|
||||
<NButton
|
||||
size="small"
|
||||
text
|
||||
:disabled="!canOprate"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon
|
||||
:component="Delete24Filled"
|
||||
@@ -145,9 +180,16 @@ function delReply(id: number) {
|
||||
<template #trigger>
|
||||
<NPopconfirm @positive-click="restoreComment(item.id)">
|
||||
<template #trigger>
|
||||
<NButton size="small" text :disabled="!canOprate">
|
||||
<NButton
|
||||
size="small"
|
||||
text
|
||||
:disabled="!canOprate"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="SyncCircleSharp" color="#7f7f7f" />
|
||||
<NIcon
|
||||
:component="SyncCircleSharp"
|
||||
color="#7f7f7f"
|
||||
/>
|
||||
</template>
|
||||
</NButton>
|
||||
</template>
|
||||
|
||||
@@ -72,12 +72,33 @@ function onDropdownSelect(key: string) {
|
||||
|
||||
<template>
|
||||
<NFlex align="center">
|
||||
<NFlex align="center" :wrap="false">
|
||||
<NTag v-if="item.isDeleted" size="small" round :bordered="false"> 已删除 </NTag>
|
||||
<NTag v-if="item.isPinned" size="small" round :bordered="false">
|
||||
<NIcon :component="Star24Filled" color="#dba913" />
|
||||
<NFlex
|
||||
align="center"
|
||||
:wrap="false"
|
||||
>
|
||||
<NTag
|
||||
v-if="item.isDeleted"
|
||||
size="small"
|
||||
round
|
||||
:bordered="false"
|
||||
>
|
||||
已删除
|
||||
</NTag>
|
||||
<NTag size="small" style="color: gray">
|
||||
<NTag
|
||||
v-if="item.isPinned"
|
||||
size="small"
|
||||
round
|
||||
:bordered="false"
|
||||
>
|
||||
<NIcon
|
||||
:component="Star24Filled"
|
||||
color="#dba913"
|
||||
/>
|
||||
</NTag>
|
||||
<NTag
|
||||
size="small"
|
||||
style="color: gray"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="Chat24Regular" />
|
||||
</template>
|
||||
@@ -90,17 +111,29 @@ function onDropdownSelect(key: string) {
|
||||
{{ item.title }}
|
||||
</NText>
|
||||
</NFlex>
|
||||
<NFlex style="flex: 1; color: gray; font-size: small" justify="end" align="center">
|
||||
<NFlex
|
||||
style="flex: 1; color: gray; font-size: small"
|
||||
justify="end"
|
||||
align="center"
|
||||
>
|
||||
<template v-if="item.latestRepliedBy">
|
||||
<span>
|
||||
<NIcon :component="ArrowReply24Filled" size="15" />
|
||||
<NIcon
|
||||
:component="ArrowReply24Filled"
|
||||
size="15"
|
||||
/>
|
||||
@{{ item.latestRepliedBy.name }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else> @{{ item.user?.name }} 发布于 </template>
|
||||
<template v-else>
|
||||
@{{ item.user?.name }} 发布于
|
||||
</template>
|
||||
<NTooltip>
|
||||
<template #trigger>
|
||||
<NTime :time="item.createAt" type="relative" />
|
||||
<NTime
|
||||
:time="item.createAt"
|
||||
type="relative"
|
||||
/>
|
||||
</template>
|
||||
<NTime :time="item.createAt" />
|
||||
</NTooltip>
|
||||
|
||||
@@ -28,13 +28,24 @@ const emits = defineEmits<{
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NFlex align="center" class="forum-reply-item">
|
||||
<NFlex :wrap="false" align="center">
|
||||
<NFlex
|
||||
align="center"
|
||||
class="forum-reply-item"
|
||||
>
|
||||
<NFlex
|
||||
:wrap="false"
|
||||
align="center"
|
||||
>
|
||||
<NTooltip v-if="replyTo">
|
||||
<template #trigger>
|
||||
<NIcon :component="ArrowReply16Filled" />
|
||||
</template>
|
||||
<ForumReplyItem :item="replyTo" :comment="comment" :topic="topic" :show-reply-button="false" />
|
||||
<ForumReplyItem
|
||||
:item="replyTo"
|
||||
:comment="comment"
|
||||
:topic="topic"
|
||||
:show-reply-button="false"
|
||||
/>
|
||||
</NTooltip>
|
||||
<NAvatar
|
||||
:src="getUserAvatarUrl(item.user.id)"
|
||||
@@ -43,16 +54,31 @@ const emits = defineEmits<{
|
||||
round
|
||||
style="margin-top: -3px; min-width: 28px; min-height: 28px"
|
||||
/>
|
||||
<NText strong depth="3" style="white-space: nowrap">
|
||||
<NText
|
||||
strong
|
||||
depth="3"
|
||||
style="white-space: nowrap"
|
||||
>
|
||||
{{ item.user.name }}
|
||||
</NText>
|
||||
</NFlex>
|
||||
{{ item.content }}
|
||||
<NFlex justify="end" align="center" :wrap="false" style="flex: 1">
|
||||
<NFlex
|
||||
justify="end"
|
||||
align="center"
|
||||
:wrap="false"
|
||||
style="flex: 1"
|
||||
>
|
||||
<NTooltip>
|
||||
<template #trigger>
|
||||
<NText depth="3" style="font-size: small; min-width: 50px">
|
||||
<NTime :time="item.sendAt" type="relative" />
|
||||
<NText
|
||||
depth="3"
|
||||
style="font-size: small; min-width: 50px"
|
||||
>
|
||||
<NTime
|
||||
:time="item.sendAt"
|
||||
type="relative"
|
||||
/>
|
||||
</NText>
|
||||
</template>
|
||||
<NTime :time="item.sendAt" />
|
||||
@@ -61,10 +87,10 @@ const emits = defineEmits<{
|
||||
<template #trigger>
|
||||
<NButton
|
||||
size="tiny"
|
||||
@click="useForum.SetReplyingComment(comment, item)"
|
||||
round
|
||||
secondary
|
||||
:disabled="!canOprate"
|
||||
@click="useForum.SetReplyingComment(comment, item)"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="ArrowReply16Filled" />
|
||||
|
||||
@@ -57,7 +57,6 @@ type PostReplyModel = {
|
||||
}
|
||||
|
||||
const { biliInfo, userInfo } = defineProps<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
biliInfo: any | undefined
|
||||
userInfo: UserInfo | undefined
|
||||
}>()
|
||||
@@ -169,14 +168,32 @@ onMounted(async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-if="!topic.id"> </template>
|
||||
<template v-if="!topic.id" />
|
||||
<template v-else>
|
||||
<div size="small" embedded style="max-width: 1500px; margin: 0 auto">
|
||||
<div
|
||||
size="small"
|
||||
embedded
|
||||
style="max-width: 1500px; margin: 0 auto"
|
||||
>
|
||||
<NBackTop />
|
||||
<NBadge class="back-forum-badge" style="width: 100%; left: 0" type="info" :offset="[3, 3]">
|
||||
<NBadge
|
||||
class="back-forum-badge"
|
||||
style="width: 100%; left: 0"
|
||||
type="info"
|
||||
:offset="[3, 3]"
|
||||
>
|
||||
<NCard size="small">
|
||||
<NFlex align="center" :wrap="false">
|
||||
<NTag v-if="topic.isDeleted" type="warning" :bordered="false"> 已删除 </NTag>
|
||||
<NFlex
|
||||
align="center"
|
||||
:wrap="false"
|
||||
>
|
||||
<NTag
|
||||
v-if="topic.isDeleted"
|
||||
type="warning"
|
||||
:bordered="false"
|
||||
>
|
||||
已删除
|
||||
</NTag>
|
||||
<NText style="font-size: large; font-weight: bold; text-align: center; width: 100%">
|
||||
<NEllipsis style="width: 100%">
|
||||
{{ topic.title }}
|
||||
@@ -187,9 +204,15 @@ onMounted(async () => {
|
||||
<template #value>
|
||||
<NTooltip>
|
||||
<template #trigger>
|
||||
<NButton text @click="() => $router.push({ name: 'user-forum', params: { id: userInfo?.name } })">
|
||||
<NButton
|
||||
text
|
||||
@click="() => $router.push({ name: 'user-forum', params: { id: userInfo?.name } })"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="ArrowCircleLeft12Regular" color="white" />
|
||||
<NIcon
|
||||
:component="ArrowCircleLeft12Regular"
|
||||
color="white"
|
||||
/>
|
||||
</template>
|
||||
</NButton>
|
||||
</template>
|
||||
@@ -197,9 +220,15 @@ onMounted(async () => {
|
||||
</NTooltip>
|
||||
</template>
|
||||
</NBadge>
|
||||
<NCard content-style="padding: 0 12px 0 12px;" embedded>
|
||||
<NCard
|
||||
content-style="padding: 0 12px 0 12px;"
|
||||
embedded
|
||||
>
|
||||
<template #header>
|
||||
<NFlex align="center" :size="5">
|
||||
<NFlex
|
||||
align="center"
|
||||
:size="5"
|
||||
>
|
||||
<NAvatar
|
||||
:src="VTSURU_API_URL + 'user-face/' + topic?.user?.id + '?size=64'"
|
||||
:img-props="{ referrerpolicy: 'no-referrer' }"
|
||||
@@ -212,7 +241,10 @@ onMounted(async () => {
|
||||
<NTooltip>
|
||||
<template #trigger>
|
||||
<NText depth="3">
|
||||
<NTime :time="topic.createAt" type="relative" />
|
||||
<NTime
|
||||
:time="topic.createAt"
|
||||
type="relative"
|
||||
/>
|
||||
</NText>
|
||||
</template>
|
||||
<NTime :time="topic.createAt" />
|
||||
@@ -228,7 +260,11 @@ onMounted(async () => {
|
||||
<NFlex>
|
||||
<NTooltip>
|
||||
<template #trigger>
|
||||
<NButton size="small" :bordered="topic.isLiked" text>
|
||||
<NButton
|
||||
size="small"
|
||||
:bordered="topic.isLiked"
|
||||
text
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="Eye24Regular" />
|
||||
</template>
|
||||
@@ -241,6 +277,11 @@ onMounted(async () => {
|
||||
<template #trigger>
|
||||
<NButton
|
||||
size="small"
|
||||
:bordered="topic.isLiked"
|
||||
secondary
|
||||
:type="topic.isLiked ? 'primary' : 'default'"
|
||||
:loading="useForum.isLikeLoading"
|
||||
:disabled="!canOprate"
|
||||
@click="
|
||||
useForum.LikeTopic(topic.id, !topic.isLiked).then((success) => {
|
||||
if (success) {
|
||||
@@ -249,14 +290,12 @@ onMounted(async () => {
|
||||
}
|
||||
})
|
||||
"
|
||||
:bordered="topic.isLiked"
|
||||
secondary
|
||||
:type="topic.isLiked ? 'primary' : 'default'"
|
||||
:loading="useForum.isLikeLoading"
|
||||
:disabled="!canOprate"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="topic.isLiked ? Heart : HeartOutline" :color="topic.isLiked ? '#dd484f' : ''" />
|
||||
<NIcon
|
||||
:component="topic.isLiked ? Heart : HeartOutline"
|
||||
:color="topic.isLiked ? '#dd484f' : ''"
|
||||
/>
|
||||
</template>
|
||||
{{ topic.likeCount }}
|
||||
</NButton>
|
||||
@@ -265,7 +304,12 @@ onMounted(async () => {
|
||||
</NTooltip>
|
||||
<NTooltip>
|
||||
<template #trigger>
|
||||
<NButton size="small" @click="showCommentModal = true" secondary :disabled="!canOprate">
|
||||
<NButton
|
||||
size="small"
|
||||
secondary
|
||||
:disabled="!canOprate"
|
||||
@click="showCommentModal = true"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="Comment24Regular" />
|
||||
</template>
|
||||
@@ -274,12 +318,19 @@ onMounted(async () => {
|
||||
</template>
|
||||
评论
|
||||
</NTooltip>
|
||||
<NFlex style="flex: 1" justify="end">
|
||||
<NFlex
|
||||
style="flex: 1"
|
||||
justify="end"
|
||||
>
|
||||
<NTooltip v-if="topic?.user?.id === accountInfo.id || topic.isAdmin">
|
||||
<template #trigger>
|
||||
<NPopconfirm @positive-click="delTopic(topic.id)">
|
||||
<template #trigger>
|
||||
<NButton size="small" text :disabled="!canOprate">
|
||||
<NButton
|
||||
size="small"
|
||||
text
|
||||
:disabled="!canOprate"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon
|
||||
:component="Delete24Filled"
|
||||
@@ -297,9 +348,16 @@ onMounted(async () => {
|
||||
<template #trigger>
|
||||
<NPopconfirm @positive-click="restoreTopic(topic.id)">
|
||||
<template #trigger>
|
||||
<NButton size="small" text :disabled="!canOprate">
|
||||
<NButton
|
||||
size="small"
|
||||
text
|
||||
:disabled="!canOprate"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="SyncCircleSharp" color="#7f7f7f" />
|
||||
<NIcon
|
||||
:component="SyncCircleSharp"
|
||||
color="#7f7f7f"
|
||||
/>
|
||||
</template>
|
||||
</NButton>
|
||||
</template>
|
||||
@@ -311,12 +369,24 @@ onMounted(async () => {
|
||||
</NFlex>
|
||||
</NFlex>
|
||||
</template>
|
||||
<div class="editor-content-view" v-html="topic.content"></div>
|
||||
<div
|
||||
class="editor-content-view"
|
||||
v-html="topic.content"
|
||||
/>
|
||||
</NCard>
|
||||
<NDivider>
|
||||
<NButton @click="showCommentModal = true" type="primary" :disabled="!canOprate">发送评论</NButton>
|
||||
<NButton
|
||||
type="primary"
|
||||
:disabled="!canOprate"
|
||||
@click="showCommentModal = true"
|
||||
>
|
||||
发送评论
|
||||
</NButton>
|
||||
</NDivider>
|
||||
<NFlex align="center" justify="center">
|
||||
<NFlex
|
||||
align="center"
|
||||
justify="center"
|
||||
>
|
||||
<NPagination
|
||||
v-if="comments && (comments?.data?.length ?? 0) > 0"
|
||||
v-model:page="pn"
|
||||
@@ -326,15 +396,34 @@ onMounted(async () => {
|
||||
@update:page="refreshComments"
|
||||
/>
|
||||
</NFlex>
|
||||
<br />
|
||||
<NEmpty v-if="!comments || !comments.data || comments.data.length === 0" description="暂无评论" />
|
||||
<NList v-else hoverable bordered size="small">
|
||||
<NListItem v-for="item in comments.data" :key="item.id">
|
||||
<ForumCommentItem :item="item" :topic="topic" @delete="onDeleteComment" />
|
||||
<br>
|
||||
<NEmpty
|
||||
v-if="!comments || !comments.data || comments.data.length === 0"
|
||||
description="暂无评论"
|
||||
/>
|
||||
<NList
|
||||
v-else
|
||||
hoverable
|
||||
bordered
|
||||
size="small"
|
||||
>
|
||||
<NListItem
|
||||
v-for="item in comments.data"
|
||||
:key="item.id"
|
||||
>
|
||||
<ForumCommentItem
|
||||
:item="item"
|
||||
:topic="topic"
|
||||
@delete="onDeleteComment"
|
||||
/>
|
||||
</NListItem>
|
||||
</NList>
|
||||
<br />
|
||||
<NFlex v-if="(comments?.data?.length ?? 0) > 5" align="center" justify="center">
|
||||
<br>
|
||||
<NFlex
|
||||
v-if="(comments?.data?.length ?? 0) > 5"
|
||||
align="center"
|
||||
justify="center"
|
||||
>
|
||||
<NPagination
|
||||
v-if="comments && (comments?.data.length ?? 0) > 0"
|
||||
v-model:page="pn"
|
||||
@@ -347,15 +436,41 @@ onMounted(async () => {
|
||||
<NDivider />
|
||||
</div>
|
||||
</template>
|
||||
<NModal v-model:show="showCommentModal" preset="card" style="width: 1000px; max-width: 90vw; height: auto">
|
||||
<template #header> 发送评论 </template>
|
||||
<VEditor v-model:value="currentCommentContent.content" :max-length="1111" ref="editorRef" />
|
||||
<NButton type="primary" @click="postComment" :loading="!token || useForum.isLoading"> 发布 </NButton>
|
||||
<NModal
|
||||
v-model:show="showCommentModal"
|
||||
preset="card"
|
||||
style="width: 1000px; max-width: 90vw; height: auto"
|
||||
>
|
||||
<template #header>
|
||||
发送评论
|
||||
</template>
|
||||
<VEditor
|
||||
ref="editorRef"
|
||||
v-model:value="currentCommentContent.content"
|
||||
:max-length="1111"
|
||||
/>
|
||||
<NButton
|
||||
type="primary"
|
||||
:loading="!token || useForum.isLoading"
|
||||
@click="postComment"
|
||||
>
|
||||
发布
|
||||
</NButton>
|
||||
</NModal>
|
||||
<NModal v-model:show="useForum.showReplyModal" preset="card" style="width: 1000px; max-width: 90vw; height: auto">
|
||||
<template #header> 发送回复 </template>
|
||||
<NModal
|
||||
v-model:show="useForum.showReplyModal"
|
||||
preset="card"
|
||||
style="width: 1000px; max-width: 90vw; height: auto"
|
||||
>
|
||||
<template #header>
|
||||
发送回复
|
||||
</template>
|
||||
<template v-if="useForum.replyingReply">
|
||||
<NCard size="small" title="正在回复" embedded>
|
||||
<NCard
|
||||
size="small"
|
||||
title="正在回复"
|
||||
embedded
|
||||
>
|
||||
<ForumReplyItem
|
||||
v-if="useForum.replyingReply && useForum.replyingComment"
|
||||
:item="useForum.replyingReply"
|
||||
@@ -374,9 +489,18 @@ onMounted(async () => {
|
||||
show-count
|
||||
/>
|
||||
<NDivider />
|
||||
<NButton type="primary" @click="postReply" :loading="!token || useForum.isLoading"> 发布 </NButton>
|
||||
<NButton
|
||||
type="primary"
|
||||
:loading="!token || useForum.isLoading"
|
||||
@click="postReply"
|
||||
>
|
||||
发布
|
||||
</NButton>
|
||||
</NModal>
|
||||
<TurnstileVerify ref="turnstile" v-model="token" />
|
||||
<TurnstileVerify
|
||||
ref="turnstile"
|
||||
v-model="token"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -27,7 +27,6 @@ import ForumCommentItem from './ForumCommentItem.vue'
|
||||
import { useAccount } from '@/api/account'
|
||||
|
||||
const { biliInfo, userInfo } = defineProps<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
biliInfo: any | undefined
|
||||
userInfo: UserInfo | undefined
|
||||
}>()
|
||||
@@ -102,22 +101,57 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NAlert v-if="!forumInfo" type="error"> 用户未创建粉丝讨论区 </NAlert>
|
||||
<NAlert
|
||||
v-if="!forumInfo"
|
||||
type="error"
|
||||
>
|
||||
用户未创建粉丝讨论区
|
||||
</NAlert>
|
||||
<NCard
|
||||
v-else-if="
|
||||
(forumInfo.level < ForumUserLevels.Member && forumInfo.settings.requireApply) ||
|
||||
forumInfo.settings.allowedViewerLevel > forumInfo.level
|
||||
forumInfo.settings.allowedViewerLevel > forumInfo.level
|
||||
"
|
||||
>
|
||||
<NAlert type="warning"> 你需要成为成员才能访问 {{ forumInfo.name }} </NAlert>
|
||||
<br />
|
||||
<NAlert v-if="forumInfo.isApplied" type="success"> 已申请, 正在等待管理员审核 </NAlert>
|
||||
<NCard v-else title="加入该讨论区">
|
||||
<NAlert v-if="!accountInfo.id" type="error"> 需要登录后才能够加入 </NAlert>
|
||||
<NAlert v-else-if="forumInfo.settings.requireApply" type="warning"> 申请需要审核 </NAlert>
|
||||
<NAlert v-else type="success"> 该讨论区可直接加入 </NAlert>
|
||||
<NAlert type="warning">
|
||||
你需要成为成员才能访问 {{ forumInfo.name }}
|
||||
</NAlert>
|
||||
<br>
|
||||
<NAlert
|
||||
v-if="forumInfo.isApplied"
|
||||
type="success"
|
||||
>
|
||||
已申请, 正在等待管理员审核
|
||||
</NAlert>
|
||||
<NCard
|
||||
v-else
|
||||
title="加入该讨论区"
|
||||
>
|
||||
<NAlert
|
||||
v-if="!accountInfo.id"
|
||||
type="error"
|
||||
>
|
||||
需要登录后才能够加入
|
||||
</NAlert>
|
||||
<NAlert
|
||||
v-else-if="forumInfo.settings.requireApply"
|
||||
type="warning"
|
||||
>
|
||||
申请需要审核
|
||||
</NAlert>
|
||||
<NAlert
|
||||
v-else
|
||||
type="success"
|
||||
>
|
||||
该讨论区可直接加入
|
||||
</NAlert>
|
||||
<NDivider />
|
||||
<NButton type="primary" @click="ApplyToForum" :loading="useForum.isLoading" :disabled="!accountInfo.id">
|
||||
<NButton
|
||||
type="primary"
|
||||
:loading="useForum.isLoading"
|
||||
:disabled="!accountInfo.id"
|
||||
@click="ApplyToForum"
|
||||
>
|
||||
{{ forumInfo.settings.requireApply ? '申请' : '' }}加入
|
||||
</NButton>
|
||||
</NCard>
|
||||
@@ -127,41 +161,90 @@ onUnmounted(() => {
|
||||
<NCard size="small">
|
||||
<template #header>
|
||||
<NFlex justify="center">
|
||||
<NText style="font-size: large">{{ forumInfo.name }}</NText>
|
||||
<NText style="font-size: large">
|
||||
{{ forumInfo.name }}
|
||||
</NText>
|
||||
</NFlex>
|
||||
</template>
|
||||
</NCard>
|
||||
<NFlex>
|
||||
<NCard style="max-width: 300px">
|
||||
<NFlex vertical>
|
||||
<NButton @click="showPostTopicModal = true"> 发布话题 </NButton>
|
||||
<NCard v-if="forumInfo.isAdmin" size="small" title="管理员">
|
||||
|
||||
</NCard>
|
||||
<NButton @click="showPostTopicModal = true">
|
||||
发布话题
|
||||
</NButton>
|
||||
<NCard
|
||||
v-if="forumInfo.isAdmin"
|
||||
size="small"
|
||||
title="管理员"
|
||||
/>
|
||||
</NFlex>
|
||||
</NCard>
|
||||
<NList bordered style="flex: 1" size="small" hoverable clickable>
|
||||
<NListItem v-for="item in topics?.data ?? []" :key="item.id">
|
||||
<a :href="`${$route.path}/topic/${item.id}`" target="_blank">
|
||||
<ForumPreviewItem :item="item" :forum="forumInfo" />
|
||||
<NList
|
||||
bordered
|
||||
style="flex: 1"
|
||||
size="small"
|
||||
hoverable
|
||||
clickable
|
||||
>
|
||||
<NListItem
|
||||
v-for="item in topics?.data ?? []"
|
||||
:key="item.id"
|
||||
>
|
||||
<a
|
||||
:href="`${$route.path}/topic/${item.id}`"
|
||||
target="_blank"
|
||||
>
|
||||
<ForumPreviewItem
|
||||
:item="item"
|
||||
:forum="forumInfo"
|
||||
/>
|
||||
</a>
|
||||
</NListItem>
|
||||
</NList>
|
||||
</NFlex>
|
||||
</NFlex>
|
||||
<NModal preset="card" v-model:show="showPostTopicModal" style="width: 800px; max-width: 95%">
|
||||
<NModal
|
||||
v-model:show="showPostTopicModal"
|
||||
preset="card"
|
||||
style="width: 800px; max-width: 95%"
|
||||
>
|
||||
<template #header>
|
||||
发布话题
|
||||
<NDivider vertical />
|
||||
<NText depth="3" style="font-size: small"> 保存于 <NTime :time="lastBackupTopic" format="HH:mm:ss" /> </NText>
|
||||
<NText
|
||||
depth="3"
|
||||
style="font-size: small"
|
||||
>
|
||||
保存于 <NTime
|
||||
:time="lastBackupTopic"
|
||||
format="HH:mm:ss"
|
||||
/>
|
||||
</NText>
|
||||
</template>
|
||||
<NFlex vertical>
|
||||
<NInput v-model:value="currentPostTopicModel.title" placeholder="标题" />
|
||||
<VEditor v-model:value="currentPostTopicModel.content" :max-length="2333" ref="editor" />
|
||||
<NButton type="primary" @click="postTopic" :loading="!token || useForum.isLoading"> 发布 </NButton>
|
||||
<NInput
|
||||
v-model:value="currentPostTopicModel.title"
|
||||
placeholder="标题"
|
||||
/>
|
||||
<VEditor
|
||||
ref="editor"
|
||||
v-model:value="currentPostTopicModel.content"
|
||||
:max-length="2333"
|
||||
/>
|
||||
<NButton
|
||||
type="primary"
|
||||
:loading="!token || useForum.isLoading"
|
||||
@click="postTopic"
|
||||
>
|
||||
发布
|
||||
</NButton>
|
||||
</NFlex>
|
||||
</NModal>
|
||||
<TurnstileVerify ref="turnstile" v-model="token" />
|
||||
<TurnstileVerify
|
||||
ref="turnstile"
|
||||
v-model="token"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -72,46 +72,103 @@ export const Config: TemplateConfig<ConfigType> = {
|
||||
<NDivider />
|
||||
<template v-if="userInfo?.biliId">
|
||||
<template v-if="userInfo?.id == accountInfo?.id">
|
||||
<NButton type="primary"
|
||||
@click="$router.push({ name: 'manage-index', query: { tab: 'setting', setting: 'index' } })">
|
||||
<NButton
|
||||
type="primary"
|
||||
@click="$router.push({ name: 'manage-index', query: { tab: 'setting', setting: 'index' } })"
|
||||
>
|
||||
自定义个人主页
|
||||
</NButton>
|
||||
<NDivider />
|
||||
</template>
|
||||
<template v-if="indexInfo?.notification">
|
||||
<NCard size="small" content-style="text-align: center">
|
||||
<NCard
|
||||
size="small"
|
||||
content-style="text-align: center"
|
||||
>
|
||||
{{ indexInfo?.notification }}
|
||||
</NCard>
|
||||
<br />
|
||||
<br>
|
||||
</template>
|
||||
|
||||
<NSpace justify="center" align="center" vertical>
|
||||
<NAvatar v-if="biliInfo" :src="biliInfo?.face" :size="width > 750 ? 175 : 100" round bordered :img-props="{
|
||||
referrerpolicy: 'no-referrer',
|
||||
}"
|
||||
:style="{ boxShadow: isDarkMode ? 'rgb(195 192 192 / 35%) 0px 5px 20px' : '0 5px 15px rgba(0, 0, 0, 0.2)' }" />
|
||||
<NSpace align="baseline" justify="center">
|
||||
<NText strong style="font-size: 32px"> {{ biliInfo?.name }} </NText>
|
||||
<NText strong style="font-size: 20px" depth="3"> ({{ userInfo?.name }}) </NText>
|
||||
<NSpace
|
||||
justify="center"
|
||||
align="center"
|
||||
vertical
|
||||
>
|
||||
<NAvatar
|
||||
v-if="biliInfo"
|
||||
:src="biliInfo?.face"
|
||||
:size="width > 750 ? 175 : 100"
|
||||
round
|
||||
bordered
|
||||
:img-props="{
|
||||
referrerpolicy: 'no-referrer',
|
||||
}"
|
||||
:style="{ boxShadow: isDarkMode ? 'rgb(195 192 192 / 35%) 0px 5px 20px' : '0 5px 15px rgba(0, 0, 0, 0.2)' }"
|
||||
/>
|
||||
<NSpace
|
||||
align="baseline"
|
||||
justify="center"
|
||||
>
|
||||
<NText
|
||||
strong
|
||||
style="font-size: 32px"
|
||||
>
|
||||
{{ biliInfo?.name }}
|
||||
</NText>
|
||||
<NText
|
||||
strong
|
||||
style="font-size: 20px"
|
||||
depth="3"
|
||||
>
|
||||
({{ userInfo?.name }})
|
||||
</NText>
|
||||
</NSpace>
|
||||
<NText strong depth="3" style="font-size: medium">
|
||||
<NText
|
||||
strong
|
||||
depth="3"
|
||||
style="font-size: medium"
|
||||
>
|
||||
{{ userInfo?.biliId }}
|
||||
</NText>
|
||||
<NText strong depth="2" style="font-size: medium">
|
||||
<NText
|
||||
strong
|
||||
depth="2"
|
||||
style="font-size: medium"
|
||||
>
|
||||
{{ biliInfo?.sign }}
|
||||
</NText>
|
||||
</NSpace>
|
||||
<NDivider />
|
||||
<NSpace align="center" justify="center">
|
||||
<NButton type="primary" @click="navigate('https://space.bilibili.com/' + userInfo?.biliId)"> 个人主页 </NButton>
|
||||
<NButton type="primary" secondary @click="navigate('https://live.bilibili.com/' + userInfo?.biliRoomId)">
|
||||
<NSpace
|
||||
align="center"
|
||||
justify="center"
|
||||
>
|
||||
<NButton
|
||||
type="primary"
|
||||
@click="navigate('https://space.bilibili.com/' + userInfo?.biliId)"
|
||||
>
|
||||
个人主页
|
||||
</NButton>
|
||||
<NButton
|
||||
type="primary"
|
||||
secondary
|
||||
@click="navigate('https://live.bilibili.com/' + userInfo?.biliRoomId)"
|
||||
>
|
||||
直播间
|
||||
</NButton>
|
||||
<template v-if="Object.keys(indexInfo.links || {}).length > 0">
|
||||
<NFlex align="center">
|
||||
<NDivider vertical />
|
||||
<NButton type="info" secondary tag="a" :href="link[1]" target="_blank"
|
||||
v-for="link in Object.entries(indexInfo.links || {})" :key="link[0] + link[1]">
|
||||
<NButton
|
||||
v-for="link in Object.entries(indexInfo.links || {})"
|
||||
:key="link[0] + link[1]"
|
||||
type="info"
|
||||
secondary
|
||||
tag="a"
|
||||
:href="link[1]"
|
||||
target="_blank"
|
||||
>
|
||||
{{ link[0] }}
|
||||
</NButton>
|
||||
</NFlex>
|
||||
@@ -122,13 +179,25 @@ export const Config: TemplateConfig<ConfigType> = {
|
||||
<NText>相关视频</NText>
|
||||
</NDivider>
|
||||
<NFlex justify="center">
|
||||
<SimpleVideoCard v-for="video in indexInfo.videos" :video="video" :key="video.id" />
|
||||
<SimpleVideoCard
|
||||
v-for="video in indexInfo.videos"
|
||||
:key="video.id"
|
||||
:video="video"
|
||||
/>
|
||||
</NFlex>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<NSpace justify="center" align="center">
|
||||
<NText strong style="font-size: 32px"> {{ userInfo?.name }} </NText>
|
||||
<NSpace
|
||||
justify="center"
|
||||
align="center"
|
||||
>
|
||||
<NText
|
||||
strong
|
||||
style="font-size: 32px"
|
||||
>
|
||||
{{ userInfo?.name }}
|
||||
</NText>
|
||||
未认证
|
||||
</NSpace>
|
||||
</template>
|
||||
|
||||
@@ -11,6 +11,11 @@ defineProps<ScheduleConfigType>()
|
||||
|
||||
<template>
|
||||
<NDivider style="margin-top: 10px" />
|
||||
<ScheduleList v-if="data" :schedules="data ?? []" :is-self="false" v-bind="$attrs" />
|
||||
<ScheduleList
|
||||
v-if="data"
|
||||
:schedules="data ?? []"
|
||||
:is-self="false"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
<NDivider />
|
||||
</template>
|
||||
|
||||
@@ -48,17 +48,28 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<NSpace>
|
||||
<NSelect :options="options" v-model:value="selectedDate" style="width: 200px" placeholder="选择其他周表" />
|
||||
<SaveCompoent :compoent="table" :file-name="`周表_${selectedDate}_${userInfo?.name}`" />
|
||||
<NSelect
|
||||
v-model:value="selectedDate"
|
||||
:options="options"
|
||||
style="width: 200px"
|
||||
placeholder="选择其他周表"
|
||||
/>
|
||||
<SaveCompoent
|
||||
:compoent="table"
|
||||
:file-name="`周表_${selectedDate}_${userInfo?.name}`"
|
||||
/>
|
||||
</NSpace>
|
||||
<NDivider />
|
||||
<div ref="table" class="schedule-template pinky container">
|
||||
<div
|
||||
ref="table"
|
||||
class="schedule-template pinky container"
|
||||
>
|
||||
<div class="schedule-template pinky day-container">
|
||||
<div
|
||||
class="schedule-template pinky day-item"
|
||||
:id="index.toString()"
|
||||
v-for="(item, index) in currentWeek?.days"
|
||||
:id="index.toString()"
|
||||
:key="index"
|
||||
class="schedule-template pinky day-item"
|
||||
>
|
||||
<div class="schedule-template pinky header">
|
||||
<span class="schedule-template pinky week">
|
||||
@@ -72,15 +83,25 @@ onMounted(() => {
|
||||
</span>
|
||||
</div>
|
||||
<div class="schedule-template pinky day-content-container">
|
||||
<span v-if="item.tag" class="schedule-template pinky day-content" id="work">
|
||||
<span
|
||||
v-if="item.tag"
|
||||
id="work"
|
||||
class="schedule-template pinky day-content"
|
||||
>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-else class="schedule-template pinky day-content" id="rest"> 休息 </span>
|
||||
<span
|
||||
v-else
|
||||
id="rest"
|
||||
class="schedule-template pinky day-content"
|
||||
> 休息 </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="schedule-template pinky title-container">
|
||||
<div class="schedule-template pinky title">S C H E D U L E</div>
|
||||
<div class="schedule-template pinky title">
|
||||
S C H E D U L E
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -56,11 +56,19 @@ const buttons = (song: SongsInfo) => [
|
||||
|
||||
<template>
|
||||
<NDivider style="margin-top: 10px" />
|
||||
<SongList v-if="data" :songs="data ?? []" :is-self="accountInfo?.id == userInfo?.id" :extraButton="buttons"
|
||||
v-bind="$attrs" />
|
||||
<SongList
|
||||
v-if="data"
|
||||
:songs="data ?? []"
|
||||
:is-self="accountInfo?.id == userInfo?.id"
|
||||
:extra-button="buttons"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
<NCollapse v-if="userInfo?.canRequestSong">
|
||||
<NCollapseItem title="点歌列表">
|
||||
<NCard size="small" embedded>
|
||||
<NCard
|
||||
size="small"
|
||||
embedded
|
||||
>
|
||||
<div style="height: 400px; width: 700px; max-width: 100%; position: relative; margin: 0 auto">
|
||||
<LiveRequestOBS :id="userInfo?.id" />
|
||||
</div>
|
||||
|
||||
@@ -100,65 +100,126 @@ function loadMore() {
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<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%' }">
|
||||
<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" />
|
||||
<SongPlayer
|
||||
v-if="selectedSong"
|
||||
v-model:is-lrc-loading="isLrcLoading"
|
||||
:song="selectedSong"
|
||||
/>
|
||||
</NCollapseTransition>
|
||||
<NDivider> 标签 </NDivider>
|
||||
<NSpace>
|
||||
<NButton v-for="tag in tags" :key="tag" size="small" secondary
|
||||
<NButton
|
||||
v-for="tag in tags"
|
||||
:key="tag"
|
||||
size="small"
|
||||
secondary
|
||||
:type="selectedTag == tag ? 'primary' : 'default'"
|
||||
@click="selectedTag == tag ? (selectedTag = '') : (selectedTag = tag)">
|
||||
@click="selectedTag == tag ? (selectedTag = '') : (selectedTag = tag)"
|
||||
>
|
||||
{{ tag }}
|
||||
</NButton>
|
||||
</NSpace>
|
||||
<NDivider> 搜索歌曲 </NDivider>
|
||||
<NSpace vertical>
|
||||
<NInput v-model:value="searchKeyword" placeholder="歌名" clearable />
|
||||
<NSelect v-model:value="selectedAuthor" :options="authors.map((a) => {
|
||||
return { label: a, value: a }
|
||||
})
|
||||
" placeholder="选择歌手" clearable />
|
||||
<NInput
|
||||
v-model:value="searchKeyword"
|
||||
placeholder="歌名"
|
||||
clearable
|
||||
/>
|
||||
<NSelect
|
||||
v-model:value="selectedAuthor"
|
||||
:options="authors.map((a) => {
|
||||
return { label: a, value: a }
|
||||
})
|
||||
"
|
||||
placeholder="选择歌手"
|
||||
clearable
|
||||
/>
|
||||
<NDivider />
|
||||
<LiveRequestOBS v-if="userInfo?.extra?.enableFunctions.includes(FunctionTypes.SongRequest)" />
|
||||
</NSpace>
|
||||
</NCard>
|
||||
<NEmpty v-if="!data || 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">
|
||||
<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">
|
||||
<NEmpty
|
||||
v-if="!data || 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"
|
||||
>
|
||||
<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">
|
||||
<NSpace
|
||||
:wrap="false"
|
||||
align="center"
|
||||
>
|
||||
<div
|
||||
:style="`border-radius: 4px; background-color: ${item.options ? '#bd5757' : '#577fb8'}; width: 7px; height: 20px`">
|
||||
</div>
|
||||
:style="`border-radius: 4px; background-color: ${item.options ? '#bd5757' : '#577fb8'}; width: 7px; height: 20px`"
|
||||
/>
|
||||
<NEllipsis>
|
||||
{{ item.name }}
|
||||
</NEllipsis>
|
||||
</NSpace>
|
||||
</template>
|
||||
<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)">
|
||||
<NText depth="3" :style="{ color: selectedAuthor == author ? '#82bcd3' : '' }">
|
||||
<NSpace
|
||||
v-if="(item.author?.length ?? 0) > 0"
|
||||
:size="0"
|
||||
>
|
||||
<div
|
||||
v-for="(author, index) in item.author"
|
||||
:key="author"
|
||||
>
|
||||
<NButton
|
||||
size="small"
|
||||
text
|
||||
@click="selectedAuthor == author ? (selectedAuthor = undefined) : (selectedAuthor = author)"
|
||||
>
|
||||
<NText
|
||||
depth="3"
|
||||
:style="{ color: selectedAuthor == author ? '#82bcd3' : '' }"
|
||||
>
|
||||
{{ author }}
|
||||
</NText>
|
||||
<NDivider v-if="index < (item.author?.length ?? 0) - 1" vertical />
|
||||
<NDivider
|
||||
v-if="index < (item.author?.length ?? 0) - 1"
|
||||
vertical
|
||||
/>
|
||||
</NButton>
|
||||
</div>
|
||||
</NSpace>
|
||||
@@ -170,15 +231,41 @@ 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
|
||||
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
|
||||
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>
|
||||
</NSpace>
|
||||
@@ -186,11 +273,18 @@ function loadMore() {
|
||||
</NSpace>
|
||||
</template>
|
||||
<template #action>
|
||||
<NSpace align="center" :wrap="false">
|
||||
<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"
|
||||
type="success"
|
||||
:loading="isLrcLoading == item.key"
|
||||
@click="selectedSong = item"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="Play24Filled" />
|
||||
</template>
|
||||
@@ -200,13 +294,17 @@ function loadMore() {
|
||||
</NTooltip>
|
||||
<NTooltip>
|
||||
<template #trigger>
|
||||
<NButton size="small" @click="() => {
|
||||
<NButton
|
||||
size="small"
|
||||
:type="liveRequestSettings?.allowFromWeb == false || item.options ? 'warning' : 'info'"
|
||||
:loading="isLoading == item.key"
|
||||
@click="() => {
|
||||
isLoading = item.key
|
||||
emits('requestSong', item)
|
||||
isLoading = ''
|
||||
}
|
||||
" :type="liveRequestSettings?.allowFromWeb == false || item.options ? 'warning' : 'info'"
|
||||
:loading="isLoading == item.key">
|
||||
"
|
||||
>
|
||||
<template #icon>
|
||||
<NIcon :component="CloudAdd20Filled" />
|
||||
</template>
|
||||
@@ -221,26 +319,44 @@ function loadMore() {
|
||||
}}
|
||||
</NTooltip>
|
||||
|
||||
<NPopover v-if="(item.tags?.length ?? 0) > 3" trigger="hover">
|
||||
<NPopover
|
||||
v-if="(item.tags?.length ?? 0) > 3"
|
||||
trigger="hover"
|
||||
>
|
||||
<template #trigger>
|
||||
<NButton size="small" secondary :type="item.tags?.includes(selectedTag) ? 'primary' : 'default'">
|
||||
<NButton
|
||||
size="small"
|
||||
secondary
|
||||
:type="item.tags?.includes(selectedTag) ? 'primary' : 'default'"
|
||||
>
|
||||
标签
|
||||
</NButton>
|
||||
</template>
|
||||
<NSpace :wrap="false">
|
||||
<NButton v-for="tag in item.tags" size="tiny" :key="tag"
|
||||
<NButton
|
||||
v-for="tag in item.tags"
|
||||
:key="tag"
|
||||
size="tiny"
|
||||
:type="selectedTag == tag ? 'primary' : 'default'"
|
||||
@click="() => (selectedTag == tag ? (selectedTag = '') : (selectedTag = tag))"
|
||||
:type="selectedTag == tag ? 'primary' : 'default'">
|
||||
>
|
||||
<NEllipsis style="max-width: 50px">
|
||||
{{ tag }}
|
||||
</NEllipsis>
|
||||
</NButton>
|
||||
</NSpace>
|
||||
</NPopover>
|
||||
<NSpace v-else :wrap="false">
|
||||
<NButton v-for="tag in item.tags" size="tiny" :key="tag"
|
||||
<NSpace
|
||||
v-else
|
||||
:wrap="false"
|
||||
>
|
||||
<NButton
|
||||
v-for="tag in item.tags"
|
||||
:key="tag"
|
||||
size="tiny"
|
||||
:type="selectedTag == tag ? 'primary' : 'default'"
|
||||
@click="() => (selectedTag == tag ? (selectedTag = '') : (selectedTag = tag))"
|
||||
:type="selectedTag == tag ? 'primary' : 'default'">
|
||||
>
|
||||
<NEllipsis style="max-width: 50px">
|
||||
{{ tag }}
|
||||
</NEllipsis>
|
||||
@@ -253,7 +369,12 @@ function loadMore() {
|
||||
</NGrid>
|
||||
<NDivider />
|
||||
<NSpace justify="center">
|
||||
<NButton v-if="data.length > index" @click="loadMore"> 加载更多 </NButton>
|
||||
<NButton
|
||||
v-if="data.length > index"
|
||||
@click="loadMore"
|
||||
>
|
||||
加载更多
|
||||
</NButton>
|
||||
</NSpace>
|
||||
</NScrollbar>
|
||||
</div>
|
||||
|
||||
@@ -36,33 +36,42 @@ export const Config: TemplateConfig<TraditionalConfigType> = {
|
||||
|
||||
<template>
|
||||
WIP...
|
||||
<div :style="{
|
||||
backgroundImage: `${props.config?.background ? 'url(' + FILE_BASE_URL + props.config?.background[0] + ')' : ''}`,
|
||||
height: '100%', 'max-width': '100%',
|
||||
minHeight: '400px',
|
||||
backgroundSize: 'cover',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
position: 'relative',
|
||||
}">
|
||||
<div :style="{
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
<div
|
||||
:style="{
|
||||
backgroundImage: `${props.config?.background ? 'url(' + FILE_BASE_URL + props.config?.background[0] + ')' : ''}`,
|
||||
height: '100%', 'max-width': '100%',
|
||||
minHeight: '400px',
|
||||
backdropFilter: 'blur(10px)',
|
||||
backgroundSize: 'cover',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}">
|
||||
<div style="
|
||||
position: 'relative',
|
||||
}"
|
||||
>
|
||||
<div
|
||||
:style="{
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
minHeight: '400px',
|
||||
backdropFilter: 'blur(10px)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}"
|
||||
>
|
||||
<div
|
||||
style="
|
||||
border-radius: 20px;
|
||||
border: 3px solid var(--pinky-border-color-dark);
|
||||
height: 50px;
|
||||
width: 400px;
|
||||
">
|
||||
<div v-for="song in props.data" :key="song.id">
|
||||
"
|
||||
>
|
||||
<div
|
||||
v-for="song in props.data"
|
||||
:key="song.id"
|
||||
>
|
||||
{{ song.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user