mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-07 02:46:55 +08:00
add 'pinky' template
This commit is contained in:
3
default.d.ts
vendored
3
default.d.ts
vendored
@@ -2,3 +2,6 @@ declare module 'vue3-aplayer' {
|
|||||||
const content: any
|
const content: any
|
||||||
export = content
|
export = content
|
||||||
}
|
}
|
||||||
|
declare module 'file-saver' {
|
||||||
|
export function saveAs(blob: Blob | null | undefined, fileName: string): void
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"grapheme-splitter": "^1.0.4",
|
"grapheme-splitter": "^1.0.4",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
"linqts": "^1.15.0",
|
"linqts": "^1.15.0",
|
||||||
|
"mitt": "^3.0.1",
|
||||||
"qrcode.vue": "^3.4.1",
|
"qrcode.vue": "^3.4.1",
|
||||||
"universal-cookie": "^4.0.4",
|
"universal-cookie": "^4.0.4",
|
||||||
"vite": "^4.3.9",
|
"vite": "^4.3.9",
|
||||||
|
|||||||
10
src/App.vue
10
src/App.vue
@@ -2,7 +2,7 @@
|
|||||||
<NMessageProvider>
|
<NMessageProvider>
|
||||||
<NNotificationProvider>
|
<NNotificationProvider>
|
||||||
<NConfigProvider :theme-overrides="themeOverrides" :theme="theme" style="height: 100vh" :locale="zhCN" :date-locale="dateZhCN">
|
<NConfigProvider :theme-overrides="themeOverrides" :theme="theme" style="height: 100vh" :locale="zhCN" :date-locale="dateZhCN">
|
||||||
<NElement style="height: 100vh;">
|
<NElement style="height: 100vh">
|
||||||
<ViewerLayout v-if="layout == 'viewer'" />
|
<ViewerLayout v-if="layout == 'viewer'" />
|
||||||
<ManageLayout v-else-if="layout == 'manage'" />
|
<ManageLayout v-else-if="layout == 'manage'" />
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@@ -19,15 +19,19 @@ import ViewerLayout from '@/views/ViewerLayout.vue'
|
|||||||
import ManageLayout from '@/views/ManageLayout.vue'
|
import ManageLayout from '@/views/ManageLayout.vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { NConfigProvider, NMessageProvider, NNotificationProvider, zhCN, dateZhCN, useOsTheme, darkTheme, NElement } from 'naive-ui'
|
import { NConfigProvider, NMessageProvider, NNotificationProvider, zhCN, dateZhCN, useOsTheme, darkTheme, NElement } from 'naive-ui'
|
||||||
import { computed } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { useStorage } from '@vueuse/core'
|
import { useStorage } from '@vueuse/core'
|
||||||
import { ThemeType } from './api/api-models'
|
import { ThemeType, UserInfo } from './api/api-models'
|
||||||
|
import { useUser } from './api/user'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const layout = computed(() => {
|
const layout = computed(() => {
|
||||||
if (route.path.startsWith('/user')) {
|
if (route.path.startsWith('/user')) {
|
||||||
|
document.title = route.meta.title + ' · ' + route.params.id + ' · VTsuru'
|
||||||
return 'viewer'
|
return 'viewer'
|
||||||
} else if (route.path.startsWith('/manage')) {
|
} else if (route.path.startsWith('/manage')) {
|
||||||
|
document.title = route.meta.title + ' · 管理 · VTsuru'
|
||||||
return 'manage'
|
return 'manage'
|
||||||
} else {
|
} else {
|
||||||
return ''
|
return ''
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ export async function GetSelfAccount() {
|
|||||||
localStorage.removeItem('JWT_Token')
|
localStorage.removeItem('JWT_Token')
|
||||||
console.warn('[vtsuru] Cookie 已失效, 需要重新登陆')
|
console.warn('[vtsuru] Cookie 已失效, 需要重新登陆')
|
||||||
message.error('Cookie 已失效, 需要重新登陆')
|
message.error('Cookie 已失效, 需要重新登陆')
|
||||||
|
setTimeout(() => {
|
||||||
location.reload()
|
location.reload()
|
||||||
|
}, 1500);
|
||||||
} else {
|
} else {
|
||||||
console.warn('[vtsuru] ' + result.message)
|
console.warn('[vtsuru] ' + result.message)
|
||||||
message.error(result.message)
|
message.error(result.message)
|
||||||
|
|||||||
40
src/components/SaveCompoent.vue
Normal file
40
src/components/SaveCompoent.vue
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { saveAs } from 'file-saver'
|
||||||
|
import html2canvas from 'html2canvas'
|
||||||
|
import { NButton, useMessage } from 'naive-ui'
|
||||||
|
|
||||||
|
const message = useMessage()
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
compoent: any
|
||||||
|
fileName: string
|
||||||
|
buttonText?: string
|
||||||
|
}>()
|
||||||
|
function saveCompoent() {
|
||||||
|
if (!props.compoent) {
|
||||||
|
message.error('未找到要保存的组件')
|
||||||
|
}
|
||||||
|
html2canvas(props.compoent, {
|
||||||
|
width: props.compoent.clientWidth, //dom 原始宽度
|
||||||
|
height: props.compoent.clientHeight,
|
||||||
|
backgroundColor: null,
|
||||||
|
scrollY: 0, // html2canvas默认绘制视图内的页面,需要把scrollY,scrollX设置为0
|
||||||
|
scrollX: 0,
|
||||||
|
useCORS: true, //支持跨域,但好像没什么用
|
||||||
|
allowTaint: true, //允许跨域(默认false)
|
||||||
|
scale: window.devicePixelRatio,
|
||||||
|
}).then((canvas) => {
|
||||||
|
canvas.toBlob(
|
||||||
|
(data) => {
|
||||||
|
saveAs(data, props.fileName + '.png')
|
||||||
|
},
|
||||||
|
'image/png',
|
||||||
|
1
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NButton type="primary" secondary @click="saveCompoent"> {{ buttonText ?? '保存为图片' }} </NButton>
|
||||||
|
</template>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ref } from 'vue'
|
import { defineAsyncComponent, ref } from 'vue'
|
||||||
|
|
||||||
const debugAPI = import.meta.env.VITE_DEBUG_API
|
const debugAPI = import.meta.env.VITE_DEBUG_API
|
||||||
const releseAPI = `https://vtsuru.suki.club/api/`
|
const releseAPI = `https://vtsuru.suki.club/api/`
|
||||||
@@ -21,3 +21,14 @@ export const QUESTION_API_URL = `${BASE_API}qa/`
|
|||||||
export const LOTTERY_API_URL = `${BASE_API}lottery/`
|
export const LOTTERY_API_URL = `${BASE_API}lottery/`
|
||||||
export const HISTORY_API_URL = `${BASE_API}history/`
|
export const HISTORY_API_URL = `${BASE_API}history/`
|
||||||
export const SCHEDULE_API_URL = `${BASE_API}schedule/`
|
export const SCHEDULE_API_URL = `${BASE_API}schedule/`
|
||||||
|
|
||||||
|
export const ScheduleTemplateMap = {
|
||||||
|
'': { name: '默认', compoent: defineAsyncComponent(() => import('@/views/view/scheduleTemplate/DefaultScheduleTemplate.vue')) },
|
||||||
|
pinky: { name: '粉粉', compoent: defineAsyncComponent(() => import('@/views/view/scheduleTemplate/PinkySchedule.vue')) },
|
||||||
|
} as { [key: string]: { name: string; compoent: any } }
|
||||||
|
export const SongListTemplateMap = {
|
||||||
|
'': { name: '默认', compoent: defineAsyncComponent(() => import('@/views/view/songListTemplate/DefaultSongListTemplate.vue')) },
|
||||||
|
} as { [key: string]: { name: string; compoent: any } }
|
||||||
|
export const IndexTemplateMap = {
|
||||||
|
'': { name: '默认', compoent: defineAsyncComponent(() => import('@/views/view/indexTemplate/DefaultIndexTemplate.vue')) },
|
||||||
|
} as { [key: string]: { name: string; compoent: any } }
|
||||||
|
|||||||
13
src/mitt.ts
Normal file
13
src/mitt.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import mitt, { Emitter } from 'mitt'
|
||||||
|
|
||||||
|
declare type MittType<T = any> = {
|
||||||
|
onOpenTemplateSettings: {
|
||||||
|
template: string,
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 类型
|
||||||
|
const emitter: Emitter<MittType> = mitt<MittType>()
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
export default emitter
|
||||||
@@ -42,7 +42,7 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
name: 'user-questionBox',
|
name: 'user-questionBox',
|
||||||
component: () => import('@/views/view/QuestionBoxView.vue'),
|
component: () => import('@/views/view/QuestionBoxView.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '棉花糖 (提问箱',
|
title: '提问箱',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -65,48 +65,72 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
name: 'manage-index',
|
name: 'manage-index',
|
||||||
component: () => import('@/views/manage/DashboardView.vue'),
|
component: () => import('@/views/manage/DashboardView.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '管理',
|
title: '面板',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'song-list',
|
path: 'song-list',
|
||||||
name: 'manage-songList',
|
name: 'manage-songList',
|
||||||
component: () => import('@/views/manage/SongListManageView.vue'),
|
component: () => import('@/views/manage/SongListManageView.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '歌单',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'question-box',
|
path: 'question-box',
|
||||||
name: 'manage-questionBox',
|
name: 'manage-questionBox',
|
||||||
component: () => import('@/views/manage/QuestionBoxManageView.vue'),
|
component: () => import('@/views/manage/QuestionBoxManageView.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '提问箱',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'lottery',
|
path: 'lottery',
|
||||||
name: 'manage-lottery',
|
name: 'manage-lottery',
|
||||||
component: () => import('@/views/manage/LotteryView.vue'),
|
component: () => import('@/views/manage/LotteryView.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '动态抽奖',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'bili-verify',
|
path: 'bili-verify',
|
||||||
name: 'manage-biliVerify',
|
name: 'manage-biliVerify',
|
||||||
component: () => import('@/views/manage/BiliVerifyView.vue'),
|
component: () => import('@/views/manage/BiliVerifyView.vue'),
|
||||||
|
meta: {
|
||||||
|
title: 'Bilibili认证',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'history',
|
path: 'history',
|
||||||
name: 'manage-history',
|
name: 'manage-history',
|
||||||
component: () => import('@/views/manage/HistoryView.vue'),
|
component: () => import('@/views/manage/HistoryView.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '数据跟踪',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'schedule',
|
path: 'schedule',
|
||||||
name: 'manage-schedule',
|
name: 'manage-schedule',
|
||||||
component: () => import('@/views/manage/ScheduleManageView.vue'),
|
component: () => import('@/views/manage/ScheduleManageView.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '日程',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'event',
|
path: 'event',
|
||||||
name: 'manage-event',
|
name: 'manage-event',
|
||||||
component: () => import('@/views/manage/EventView.vue'),
|
component: () => import('@/views/manage/EventView.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '事件记录',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'video-collect',
|
path: 'video-collect',
|
||||||
name: 'manage-videoCollect',
|
name: 'manage-videoCollect',
|
||||||
component: () => import('@/views/manage/VideoCollectManageView.vue'),
|
component: () => import('@/views/manage/VideoCollectManageView.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '视频征集',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import { NButton, NCard, NDivider, NLayoutContent, NSpace, NText, NTimeline, NTi
|
|||||||
</NSpace>
|
</NSpace>
|
||||||
<NDivider title-placement="left"> 更新日志 </NDivider>
|
<NDivider title-placement="left"> 更新日志 </NDivider>
|
||||||
<NTimeline>
|
<NTimeline>
|
||||||
|
<NTimelineItem type="info" title="功能更新" content="日程表添加 '粉粉' 模板" time="2023-10-27" />
|
||||||
<NTimelineItem type="info" title="功能更新" content="提问箱新增公开选项" time="2023-10-26" />
|
<NTimelineItem type="info" title="功能更新" content="提问箱新增公开选项" time="2023-10-26" />
|
||||||
<NTimelineItem type="success" title="功能添加" content="提问箱分享卡片" time="2023-10-25" />
|
<NTimelineItem type="success" title="功能添加" content="提问箱分享卡片" time="2023-10-25" />
|
||||||
<NTimelineItem type="success" title="功能添加" content="舰长及SC记录" time="2023-10-24" line-type="dashed" />
|
<NTimelineItem type="success" title="功能添加" content="舰长及SC记录" time="2023-10-24" line-type="dashed" />
|
||||||
|
|||||||
@@ -1,6 +1,26 @@
|
|||||||
<!-- eslint-disable vue/component-name-in-template-casing -->
|
<!-- eslint-disable vue/component-name-in-template-casing -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { NAvatar, NIcon, NLayout, NLayoutHeader, NLayoutSider, NMenu, NSpace, NText, NButton, NResult, NPageHeader, NSwitch, NModal, NEllipsis, MenuOption, NSpin, NLayoutContent, NBackTop } from 'naive-ui'
|
import {
|
||||||
|
NAvatar,
|
||||||
|
NIcon,
|
||||||
|
NLayout,
|
||||||
|
NLayoutHeader,
|
||||||
|
NLayoutSider,
|
||||||
|
NMenu,
|
||||||
|
NSpace,
|
||||||
|
NText,
|
||||||
|
NButton,
|
||||||
|
NResult,
|
||||||
|
NPageHeader,
|
||||||
|
NSwitch,
|
||||||
|
NModal,
|
||||||
|
NEllipsis,
|
||||||
|
MenuOption,
|
||||||
|
NSpin,
|
||||||
|
NLayoutContent,
|
||||||
|
NBackTop,
|
||||||
|
NScrollbar,
|
||||||
|
} from 'naive-ui'
|
||||||
import { computed, h, onMounted, ref } from 'vue'
|
import { computed, h, onMounted, ref } from 'vue'
|
||||||
import { BookOutline as BookIcon, Chatbox, Home, Moon, MusicalNote, PersonOutline as PersonIcon, Sunny, WineOutline as WineIcon } from '@vicons/ionicons5'
|
import { BookOutline as BookIcon, Chatbox, Home, Moon, MusicalNote, PersonOutline as PersonIcon, Sunny, WineOutline as WineIcon } from '@vicons/ionicons5'
|
||||||
import { GetInfo, useUser, useUserWithUId } from '@/api/user'
|
import { GetInfo, useUser, useUserWithUId } from '@/api/user'
|
||||||
@@ -49,10 +69,8 @@ async function RequestBiliUserData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const result = await GetInfo(id.value?.toString())
|
userInfo.value = await useUser(id.value?.toString())
|
||||||
if (result.code == 200) {
|
if (!userInfo.value) {
|
||||||
userInfo.value = result.data
|
|
||||||
} else {
|
|
||||||
notfount.value = true
|
notfount.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,10 +199,14 @@ onMounted(async () => {
|
|||||||
class="viewer-page-content"
|
class="viewer-page-content"
|
||||||
:style="`box-shadow:${isDarkMode() ? 'rgb(28 28 28 / 9%) 5px 5px 6px inset, rgba(139, 139, 139, 0.09) -5px -5px 6px inset' : 'inset 5px 5px 6px #8b8b8b17, inset -5px -5px 6px #8b8b8b17;'}`"
|
:style="`box-shadow:${isDarkMode() ? 'rgb(28 28 28 / 9%) 5px 5px 6px inset, rgba(139, 139, 139, 0.09) -5px -5px 6px inset' : 'inset 5px 5px 6px #8b8b8b17, inset -5px -5px 6px #8b8b8b17;'}`"
|
||||||
>
|
>
|
||||||
<RouterView v-if="userInfo" v-slot="{ Component }">
|
<RouterView v-if="userInfo" v-slot="{ Component, route }">
|
||||||
|
<Transition name="fade" mode="out-in">
|
||||||
<KeepAlive>
|
<KeepAlive>
|
||||||
|
<div :key="route.name">
|
||||||
<component :is="Component" :bili-info="biliUserInfo" :user-info="userInfo" />
|
<component :is="Component" :bili-info="biliUserInfo" :user-info="userInfo" />
|
||||||
|
</div>
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
|
</Transition>
|
||||||
</RouterView>
|
</RouterView>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<NSpin show />
|
<NSpin show />
|
||||||
@@ -206,5 +228,6 @@ onMounted(async () => {
|
|||||||
padding: 15px;
|
padding: 15px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -79,26 +79,27 @@ const exportType = ref<'json' | 'xml' | 'csv'>('csv')
|
|||||||
|
|
||||||
async function onDateChange() {
|
async function onDateChange() {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
await QueryGetAPI<EventModel[]>(BASE_API + 'event/get', {
|
const data = await get()
|
||||||
|
events.value = data
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
async function get() {
|
||||||
|
try {
|
||||||
|
const data = await QueryGetAPI<EventModel[]>(BASE_API + 'event/get', {
|
||||||
start: selectedDate.value[0],
|
start: selectedDate.value[0],
|
||||||
end: selectedDate.value[1],
|
end: selectedDate.value[1],
|
||||||
})
|
})
|
||||||
.then((data) => {
|
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
events.value = new List(data.data).OrderByDescending((d) => d.time).ToArray()
|
|
||||||
message.success('已获取数据')
|
message.success('已获取数据')
|
||||||
//selectedType.value = type
|
return new List(data.data).OrderByDescending((d) => d.time).ToArray()
|
||||||
} else {
|
} else {
|
||||||
message.error('获取数据失败: ' + data.message)
|
message.error('获取数据失败: ' + data.message)
|
||||||
|
return []
|
||||||
}
|
}
|
||||||
})
|
} catch (err) {
|
||||||
.catch((err) => {
|
|
||||||
console.error(err)
|
|
||||||
message.error('获取数据失败')
|
message.error('获取数据失败')
|
||||||
})
|
return []
|
||||||
.finally(() => {
|
}
|
||||||
isLoading.value = false
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
function GetSCColor(price: number): string {
|
function GetSCColor(price: number): string {
|
||||||
if (price === 0) return `#2a60b2`
|
if (price === 0) return `#2a60b2`
|
||||||
@@ -219,7 +220,13 @@ onMounted(() => {
|
|||||||
<NAvatar round lazy borderd :size="64" :src="AVATAR_URL + item.uId" :img-props="{ referrerpolicy: 'no-referrer' }" style="box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2)" />
|
<NAvatar round lazy borderd :size="64" :src="AVATAR_URL + item.uId" :img-props="{ referrerpolicy: 'no-referrer' }" style="box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2)" />
|
||||||
<NSpace>
|
<NSpace>
|
||||||
<NTag size="tiny" v-if="selectedType == EventType.Guard" :bordered="false"> {{ item.msg }} </NTag>
|
<NTag size="tiny" v-if="selectedType == EventType.Guard" :bordered="false"> {{ item.msg }} </NTag>
|
||||||
<NTag size="tiny" round :color="{ color: selectedType == EventType.Guard ? GetGuardColor(item.price) : GetSCColor(item.price), textColor: 'white', borderColor: isDarkMode() ? 'white' : '#00000000' }"> {{ item.price }} </NTag>
|
<NTag
|
||||||
|
size="tiny"
|
||||||
|
round
|
||||||
|
:color="{ color: selectedType == EventType.Guard ? GetGuardColor(item.price) : GetSCColor(item.price), textColor: 'white', borderColor: isDarkMode() ? 'white' : '#00000000' }"
|
||||||
|
>
|
||||||
|
{{ item.price }}
|
||||||
|
</NTag>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
<NText>
|
<NText>
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
|
|||||||
@@ -360,10 +360,9 @@ onMounted(() => {
|
|||||||
<NCard :bordered="false" size="small">
|
<NCard :bordered="false" size="small">
|
||||||
<template #header>
|
<template #header>
|
||||||
<NSpace align="center">
|
<NSpace align="center">
|
||||||
<NTag size="small" type="warning" :bordered="false">
|
<NText depth="3">
|
||||||
{{ item.target.name }}
|
|
||||||
</NTag>
|
|
||||||
回复
|
回复
|
||||||
|
</NText>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</template>
|
</template>
|
||||||
{{ item.answer.message }}
|
{{ item.answer.message }}
|
||||||
|
|||||||
@@ -1,33 +1,98 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useAccount } from '@/api/account'
|
import { useAccount } from '@/api/account'
|
||||||
import { NButton, NCard, NCheckbox, NCheckboxGroup, NDivider, NForm, NSelect, NSpace, NSwitch, NTabPane, NTabs, SelectOption, useMessage } from 'naive-ui'
|
import { NButton, NCard, NCheckbox, NCheckboxGroup, NDivider, NForm, NModal, NSelect, NSpace, NSpin, NSwitch, NTabPane, NTabs, SelectOption, useMessage } from 'naive-ui'
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { Ref, computed, h, onMounted, ref, defineAsyncComponent } from 'vue'
|
||||||
import { useRequest } from 'vue-request'
|
|
||||||
import { FunctionTypes, ScheduleWeekInfo, SongFrom, SongLanguage, SongsInfo } from '@/api/api-models'
|
import { FunctionTypes, ScheduleWeekInfo, SongFrom, SongLanguage, SongsInfo } from '@/api/api-models'
|
||||||
import { QueryPostAPI } from '@/api/query'
|
import { QueryPostAPI } from '@/api/query'
|
||||||
import { ACCOUNT_API_URL, FETCH_API } from '@/data/constants'
|
import { ACCOUNT_API_URL, FETCH_API, IndexTemplateMap, ScheduleTemplateMap, SongListTemplateMap } from '@/data/constants'
|
||||||
import ScheduleView from '../view/ScheduleView.vue'
|
|
||||||
import UserIndexView from '../view/UserIndexView.vue'
|
interface TemplateDefineTypes {
|
||||||
import SongListView from '../view/SongListView.vue'
|
TemplateMap: { [name: string]: { name: string; compoent: any } }
|
||||||
|
Options: SelectOption[]
|
||||||
|
Data: any
|
||||||
|
Selected: Ref<string>
|
||||||
|
}
|
||||||
|
|
||||||
const accountInfo = useAccount()
|
const accountInfo = useAccount()
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
|
||||||
const templateOptions = [
|
const isSaving = ref(false)
|
||||||
|
|
||||||
|
const templates = {
|
||||||
|
index: {
|
||||||
|
TemplateMap: IndexTemplateMap,
|
||||||
|
Options: Object.entries(IndexTemplateMap).map((v) => ({
|
||||||
|
label: v[1].name,
|
||||||
|
value: v[0],
|
||||||
|
})),
|
||||||
|
Data: null,
|
||||||
|
Selected: ref(accountInfo.value?.settings.indexTemplate ?? ''),
|
||||||
|
},
|
||||||
|
schedule: {
|
||||||
|
TemplateMap: ScheduleTemplateMap,
|
||||||
|
Options: Object.entries(ScheduleTemplateMap).map((v) => ({
|
||||||
|
label: v[1].name,
|
||||||
|
value: v[0],
|
||||||
|
})),
|
||||||
|
Data: [
|
||||||
{
|
{
|
||||||
label: '主页',
|
year: 2023,
|
||||||
value: 'index',
|
week: 30,
|
||||||
|
days: [
|
||||||
|
{
|
||||||
|
title: '唱唱歌!',
|
||||||
|
tag: '歌回',
|
||||||
|
tagColor: '#61B589',
|
||||||
|
time: '10:00 AM',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '歌单',
|
title: '玩点游戏',
|
||||||
value: 'songlist',
|
tag: '游戏',
|
||||||
|
tagColor: '#A36565',
|
||||||
|
time: '20:00 PM',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '日程表',
|
title: 'Title 3',
|
||||||
value: 'schedule',
|
tag: 'Tag 3',
|
||||||
|
tagColor: '#7BCDEF',
|
||||||
|
time: '11:00 PM',
|
||||||
},
|
},
|
||||||
] as SelectOption[]
|
{
|
||||||
const fakeSongList = [
|
title: null,
|
||||||
|
tag: null,
|
||||||
|
tagColor: null,
|
||||||
|
time: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: null,
|
||||||
|
tag: null,
|
||||||
|
tagColor: null,
|
||||||
|
time: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: null,
|
||||||
|
tag: null,
|
||||||
|
tagColor: null,
|
||||||
|
time: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: null,
|
||||||
|
tag: null,
|
||||||
|
tagColor: null,
|
||||||
|
time: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
] as ScheduleWeekInfo[],
|
||||||
|
Selected: ref(accountInfo.value?.settings.scheduleTemplate ?? ''),
|
||||||
|
},
|
||||||
|
songlist: {
|
||||||
|
TemplateMap: SongListTemplateMap,
|
||||||
|
Options: Object.entries(SongListTemplateMap).map((v) => ({
|
||||||
|
label: v[1].name,
|
||||||
|
value: v[0],
|
||||||
|
})),
|
||||||
|
Data: [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
key: 'song1',
|
key: 'song1',
|
||||||
@@ -83,91 +148,33 @@ const fakeSongList = [
|
|||||||
createTime: Date.now(),
|
createTime: Date.now(),
|
||||||
updateTime: Date.now(),
|
updateTime: Date.now(),
|
||||||
},
|
},
|
||||||
] as SongsInfo[]
|
] as SongsInfo[],
|
||||||
const fakeSchedule = [
|
Selected: ref(accountInfo.value?.settings.songListTemplate ?? ''),
|
||||||
|
},
|
||||||
|
} as { [type: string]: TemplateDefineTypes }
|
||||||
|
|
||||||
|
const templateOptions = [
|
||||||
{
|
{
|
||||||
year: 2023,
|
label: '主页',
|
||||||
week: 30,
|
value: 'index',
|
||||||
days: [
|
|
||||||
{
|
|
||||||
title: '唱唱歌!',
|
|
||||||
tag: '歌回',
|
|
||||||
tagColor: '#61B589',
|
|
||||||
time: '10:00',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '玩点游戏',
|
label: '歌单',
|
||||||
tag: '游戏',
|
value: 'songlist',
|
||||||
tagColor: '#A36565',
|
|
||||||
time: '20:00',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Title 3',
|
label: '日程表',
|
||||||
tag: 'Tag 3',
|
value: 'schedule',
|
||||||
tagColor: '#7BCDEF',
|
|
||||||
time: '12:00 PM',
|
|
||||||
},
|
},
|
||||||
{
|
] as SelectOption[]
|
||||||
title: null,
|
const selectedOption = ref('index')
|
||||||
tag: null,
|
|
||||||
tagColor: null,
|
|
||||||
time: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: null,
|
|
||||||
tag: null,
|
|
||||||
tagColor: null,
|
|
||||||
time: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: null,
|
|
||||||
tag: null,
|
|
||||||
tagColor: null,
|
|
||||||
time: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: null,
|
|
||||||
tag: null,
|
|
||||||
tagColor: null,
|
|
||||||
time: null,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
] as ScheduleWeekInfo[]
|
|
||||||
const selectedOption = ref(templateOptions[0].value)
|
|
||||||
const selectedTab = ref('general')
|
const selectedTab = ref('general')
|
||||||
|
|
||||||
const scheduleTemplateOptions = [
|
const selectedTemplateData = computed(() => templates[selectedOption.value])
|
||||||
{
|
|
||||||
label: '默认',
|
|
||||||
value: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '粉粉',
|
|
||||||
value: 'PinkySchedule',
|
|
||||||
},
|
|
||||||
] as SelectOption[]
|
|
||||||
const selectedScheduleTemplate = ref(accountInfo.value?.settings.scheduleTemplate ?? scheduleTemplateOptions[0].value?.toString())
|
|
||||||
const songListTemplateOptions = [
|
|
||||||
{
|
|
||||||
label: '默认',
|
|
||||||
value: '',
|
|
||||||
},
|
|
||||||
] as SelectOption[]
|
|
||||||
const selectedSongListTemplate = ref(accountInfo.value?.settings.songListTemplate ?? songListTemplateOptions[0].value)
|
|
||||||
|
|
||||||
const biliUserInfo = ref()
|
const biliUserInfo = ref()
|
||||||
|
const settingModalVisiable = ref(false)
|
||||||
|
|
||||||
function UpdateEnableFunction(func: FunctionTypes, enable: boolean) {
|
|
||||||
if (accountInfo.value) {
|
|
||||||
if (enable) {
|
|
||||||
//从account.value?.settings.enableFunctions中移除指定的func
|
|
||||||
accountInfo.value.settings.enableFunctions = accountInfo.value?.settings.enableFunctions.filter((f) => f != func)
|
|
||||||
} else {
|
|
||||||
accountInfo.value.settings.enableFunctions.push(func)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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) => {
|
||||||
@@ -184,6 +191,7 @@ async function RequestBiliUserData() {
|
|||||||
}
|
}
|
||||||
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) {
|
||||||
|
isSaving.value = true
|
||||||
//UpdateEnableFunction(meta.value as FunctionTypes, meta.actionType == 'check')
|
//UpdateEnableFunction(meta.value as FunctionTypes, meta.actionType == 'check')
|
||||||
await QueryPostAPI(ACCOUNT_API_URL + 'update-setting', accountInfo.value?.settings)
|
await QueryPostAPI(ACCOUNT_API_URL + 'update-setting', accountInfo.value?.settings)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
@@ -200,15 +208,19 @@ async function SaveComboGroupSetting(value: (string | number)[], meta: { actionT
|
|||||||
console.error(err)
|
console.error(err)
|
||||||
message.error('修改失败')
|
message.error('修改失败')
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
isSaving.value = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function SaveComboSetting(value: boolean) {
|
async function SaveComboSetting() {
|
||||||
if (accountInfo.value) {
|
if (accountInfo.value) {
|
||||||
|
isSaving.value = true
|
||||||
//UpdateEnableFunction(meta.value as FunctionTypes, meta.actionType == 'check')
|
//UpdateEnableFunction(meta.value as FunctionTypes, meta.actionType == 'check')
|
||||||
await QueryPostAPI(ACCOUNT_API_URL + 'update-setting', accountInfo.value?.settings)
|
await QueryPostAPI(ACCOUNT_API_URL + 'update-setting', accountInfo.value?.settings)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.code == 200) {
|
if (data.code == 200) {
|
||||||
//message.success('保存成功')
|
message.success('已保存')
|
||||||
} else {
|
} else {
|
||||||
message.error('修改失败')
|
message.error('修改失败')
|
||||||
}
|
}
|
||||||
@@ -217,19 +229,35 @@ async function SaveComboSetting(value: boolean) {
|
|||||||
console.error(err)
|
console.error(err)
|
||||||
message.error('修改失败')
|
message.error('修改失败')
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
isSaving.value = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const componentType = computed(() => {
|
async function SaveTemplateSetting() {
|
||||||
|
if (accountInfo.value) {
|
||||||
switch (selectedOption.value) {
|
switch (selectedOption.value) {
|
||||||
case 'index':
|
case 'index': {
|
||||||
return UserIndexView
|
accountInfo.value.settings.indexTemplate = selectedTemplateData.value.Selected.value ?? ''
|
||||||
case 'songlist':
|
break
|
||||||
return SongListView
|
|
||||||
case 'schedule':
|
|
||||||
return ScheduleView
|
|
||||||
default:
|
|
||||||
return UserIndexView
|
|
||||||
}
|
}
|
||||||
|
case 'songlist': {
|
||||||
|
accountInfo.value.settings.songListTemplate = selectedTemplateData.value.Selected.value ?? ''
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'schedule': {
|
||||||
|
accountInfo.value.settings.scheduleTemplate = selectedTemplateData.value.Selected.value ?? ''
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await SaveComboSetting()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function onOpenTemplateSettings() {
|
||||||
|
settingModalVisiable.value = true
|
||||||
|
}
|
||||||
|
const buttonGroup = computed(() => {
|
||||||
|
return h(NSpace, () => [h(NButton, { type: 'primary', onClick: () => SaveTemplateSetting() }, () => '设为展示模板'), h(NButton, { type: 'info', onClick: onOpenTemplateSettings }, () => '模板设置')])
|
||||||
})
|
})
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
RequestBiliUserData()
|
RequestBiliUserData()
|
||||||
@@ -238,6 +266,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NCard v-if="accountInfo" title="设置" :style="`${selectedTab === 'general' ? '' : 'min-height: 800px;'}`">
|
<NCard v-if="accountInfo" title="设置" :style="`${selectedTab === 'general' ? '' : 'min-height: 800px;'}`">
|
||||||
|
<NSpin :show="isSaving">
|
||||||
<NTabs>
|
<NTabs>
|
||||||
<NTabPane tab="常规" name="general">
|
<NTabPane tab="常规" name="general">
|
||||||
<NDivider style="margin: 0"> 启用功能 </NDivider>
|
<NDivider style="margin: 0"> 启用功能 </NDivider>
|
||||||
@@ -260,20 +289,23 @@ onMounted(() => {
|
|||||||
<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>
|
||||||
<NDivider style="margin: 5px 0 5px 0" title-placement="left"> 模板 </NDivider>
|
<NDivider style="margin: 5px 0 5px 0" title-placement="left"> 模板 </NDivider>
|
||||||
<template v-if="selectedOption == 'index'">
|
<div>
|
||||||
<NSelect style="width: 150px" />
|
<NSpace>
|
||||||
<UserIndexView :user-info="accountInfo" :bili-info="biliUserInfo" />
|
<NSelect style="width: 150px" :options="selectedTemplateData.Options" v-model:value="selectedTemplateData.Selected.value" />
|
||||||
</template>
|
<component :is="buttonGroup" />
|
||||||
<template v-else-if="selectedOption == 'songlist'">
|
</NSpace>
|
||||||
<NSelect :options="songListTemplateOptions" v-model:value="selectedSongListTemplate" style="width: 150px" />
|
<NDivider />
|
||||||
<SongListView :user-info="accountInfo" :bili-info="biliUserInfo" :fake-data="fakeSongList" :is-self="false" />
|
<component
|
||||||
</template>
|
:is="selectedTemplateData.TemplateMap[selectedTemplateData.Selected.value].compoent"
|
||||||
<template v-else-if="selectedOption == 'schedule'">
|
:user-info="accountInfo"
|
||||||
<NSelect :options="scheduleTemplateOptions" v-model:value="selectedScheduleTemplate" style="width: 150px" />
|
:bili-info="biliUserInfo"
|
||||||
<ScheduleView :user-info="accountInfo" :bili-info="biliUserInfo" :fake-data="fakeSchedule" :is-self="false" :template="selectedScheduleTemplate" />
|
:current-data="selectedTemplateData.Data"
|
||||||
</template>
|
/>
|
||||||
|
</div>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</NTabPane>
|
</NTabPane>
|
||||||
</NTabs>
|
</NTabs>
|
||||||
|
</NSpin>
|
||||||
</NCard>
|
</NCard>
|
||||||
|
<NModal preset="card" v-model:show="settingModalVisiable" closable style="width: 600px; max-width: 90vw" title="模板设置"> 开发中... </NModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<NSpin v-if="isLoading" show />
|
<NSpin v-if="isLoading" show />
|
||||||
<component v-else v-bind="$attrs" :is="componentType" :user-info="userInfo" :currentData="currentData" />
|
<component v-else :is="ScheduleTemplateMap[componentType ?? ''].compoent" :bili-info="biliInfo" :user-info="userInfo" :currentData="currentData" v-bind="$attrs" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ScheduleWeekInfo } from '@/api/api-models'
|
import { ScheduleWeekInfo } from '@/api/api-models'
|
||||||
import DefaultScheduleTemplate from '@/views/view/scheduleTemplate/DefaultScheduleTemplate.vue'
|
|
||||||
import { computed, onMounted, ref, watch } from 'vue'
|
|
||||||
import { UserInfo } from '@/api/api-models'
|
import { UserInfo } from '@/api/api-models'
|
||||||
import { QueryGetAPI } from '@/api/query'
|
import { QueryGetAPI } from '@/api/query'
|
||||||
import { SCHEDULE_API_URL } from '@/data/constants'
|
import { SCHEDULE_API_URL, ScheduleTemplateMap } from '@/data/constants'
|
||||||
import { NSpin, useMessage } from 'naive-ui'
|
import { NSpin, useMessage } from 'naive-ui'
|
||||||
import PinkySchedule from './scheduleTemplate/PinkySchedule.vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@@ -22,19 +20,7 @@ const props = defineProps<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const componentType = computed(() => {
|
const componentType = computed(() => {
|
||||||
const type = props.template ?? props.userInfo?.extra?.templateTypes['schedule']?.toLowerCase()
|
return props.template ?? props.userInfo?.extra?.templateTypes['schedule']?.toLowerCase()
|
||||||
if (props.userInfo) {
|
|
||||||
switch (type?.toLocaleLowerCase()) {
|
|
||||||
case 'test':
|
|
||||||
return DefaultScheduleTemplate
|
|
||||||
case 'pinkyschedule':
|
|
||||||
return PinkySchedule
|
|
||||||
default:
|
|
||||||
return DefaultScheduleTemplate
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return DefaultScheduleTemplate
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
const currentData = ref<ScheduleWeekInfo[]>()
|
const currentData = ref<ScheduleWeekInfo[]>()
|
||||||
const isLoading = ref(true)
|
const isLoading = ref(true)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<NSpin v-if="isLoading" show />
|
<NSpin v-if="isLoading" show />
|
||||||
<component v-else :is="componentType" :user-info="userInfo" :currentData="currentData" />
|
<component v-else :is="componentType" :user-info="userInfo" :bili-info="biliInfo" :currentData="currentData" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const width = window.innerWidth
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
userInfo: UserInfo | undefined
|
userInfo: UserInfo | undefined
|
||||||
biliInfo: any | undefined
|
biliInfo: any | undefined
|
||||||
|
currentData: any
|
||||||
}>()
|
}>()
|
||||||
function navigate(url: string) {
|
function navigate(url: string) {
|
||||||
window.open(url, '_blank')
|
window.open(url, '_blank')
|
||||||
@@ -24,6 +25,9 @@ function navigate(url: string) {
|
|||||||
:size="width > 750 ? 175 : 100"
|
:size="width > 750 ? 175 : 100"
|
||||||
round
|
round
|
||||||
bordered
|
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)' }"
|
: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">
|
<NSpace align="baseline" justify="center">
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const accountInfo = useAccount()
|
|||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
userInfo: UserInfo | undefined
|
userInfo: UserInfo | undefined
|
||||||
|
biliInfo: any | undefined
|
||||||
currentData: ScheduleWeekInfo[] | undefined
|
currentData: ScheduleWeekInfo[] | undefined
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,23 +1,167 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ScheduleWeekInfo, UserInfo } from '@/api/api-models';
|
import { ScheduleWeekInfo, UserInfo } from '@/api/api-models'
|
||||||
|
import { getYear, getWeek, startOfWeek } from 'date-fns'
|
||||||
|
import { NDivider, NSelect, NSpace } from 'naive-ui'
|
||||||
|
import { computed, onMounted, ref } from 'vue'
|
||||||
|
import SaveCompoent from '@/components/SaveCompoent.vue'
|
||||||
|
|
||||||
defineProps<{
|
const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
|
||||||
|
const table = ref()
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
userInfo: UserInfo | undefined
|
userInfo: UserInfo | undefined
|
||||||
|
biliInfo: any | undefined
|
||||||
currentData: ScheduleWeekInfo[] | undefined
|
currentData: ScheduleWeekInfo[] | undefined
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const currentWeek = computed(() => {
|
||||||
|
if (props.currentData?.length == 1) {
|
||||||
|
return props.currentData[0]
|
||||||
|
}
|
||||||
|
return props.currentData?.find((item) => {
|
||||||
|
if (selectedDate.value) {
|
||||||
|
return item.year + '-' + item.week === selectedDate.value
|
||||||
|
}
|
||||||
|
return isTodayInWeek(item.year, item.week)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const options = computed(() => {
|
||||||
|
return props.currentData?.map((item) => {
|
||||||
|
return {
|
||||||
|
label: item.year + '年' + item.week + '周',
|
||||||
|
value: item.year + '-' + item.week,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const selectedDate = ref<string>()
|
||||||
|
|
||||||
|
function isTodayInWeek(year: number, week: number): boolean {
|
||||||
|
const today = new Date()
|
||||||
|
const todayYear = getYear(today)
|
||||||
|
const todayWeek = getWeek(today, { weekStartsOn: 1 })
|
||||||
|
|
||||||
|
return todayYear === year && todayWeek === week
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (currentWeek.value) {
|
||||||
|
selectedDate.value = currentWeek.value.year + '-' + currentWeek.value.week
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="schedule-template pinky">
|
<NSpace>
|
||||||
<div v-for="item in currentData" :key="item.week">
|
<NSelect :options="options" v-model:value="selectedDate" style="max-width: 200px" placeholder="选择其他周表" />
|
||||||
test
|
<SaveCompoent :compoent="table" :file-name="`周表_${selectedDate}_${userInfo?.name}`" />
|
||||||
|
</NSpace>
|
||||||
|
<NDivider />
|
||||||
|
<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" :key="index">
|
||||||
|
<div class="schedule-template pinky header">
|
||||||
|
<span class="schedule-template pinky week">
|
||||||
|
{{ days[index] }}
|
||||||
|
</span>
|
||||||
|
<span class="schedule-template pinky time">
|
||||||
|
{{ item.time }}
|
||||||
|
</span>
|
||||||
|
<span class="schedule-template pinky tag">
|
||||||
|
{{ item.tag }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="schedule-template pinky day-content-container">
|
||||||
|
<span v-if="item.tag" class="schedule-template pinky day-content" id="work">
|
||||||
|
{{ item.title }}
|
||||||
|
</span>
|
||||||
|
<span v-else class="schedule-template pinky day-content" id="rest"> 休息 </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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.schedule-template pinky {
|
.schedule-template.pinky.container {
|
||||||
background-color: #ebf0fa;
|
--pinky-font-color-dark: #dba2a2c9;
|
||||||
|
--pinky-border-color-dark: #eeb9b9;
|
||||||
|
width: 540px;
|
||||||
|
height: 700px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background-color: #faebeb;
|
||||||
background-image: linear-gradient(90deg, #ffffff 10%, rgba(0, 0, 0, 0) 10%), linear-gradient(#ffffff 10%, rgba(0, 0, 0, 0) 10%);
|
background-image: linear-gradient(90deg, #ffffff 10%, rgba(0, 0, 0, 0) 10%), linear-gradient(#ffffff 10%, rgba(0, 0, 0, 0) 10%);
|
||||||
background-size: 20px 20px;
|
background-size: 20px 20px;
|
||||||
|
border: 3px solid #e0cbcb;
|
||||||
|
}
|
||||||
|
.schedule-template.pinky.day-container {
|
||||||
|
display: flex;
|
||||||
|
width: 500px;
|
||||||
|
margin-top: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
.schedule-template.pinky.day-content-container {
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 15px;
|
||||||
|
border: 3px solid var(--pinky-border-color-dark);
|
||||||
|
border-top: none;
|
||||||
|
border-left: none;
|
||||||
|
background-color: #f5dadac9;
|
||||||
|
}
|
||||||
|
.schedule-template.pinky.header {
|
||||||
|
position: relative;
|
||||||
|
height: 30px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #dba2a2c9;
|
||||||
|
top: 2px;
|
||||||
|
}
|
||||||
|
.schedule-template.pinky.week {
|
||||||
|
position: relative;
|
||||||
|
left: 5px;
|
||||||
|
}
|
||||||
|
.schedule-template.pinky.time {
|
||||||
|
position: relative;
|
||||||
|
left: 15px;
|
||||||
|
}
|
||||||
|
.schedule-template.pinky.tag {
|
||||||
|
position: absolute;
|
||||||
|
text-align: right;
|
||||||
|
right: 5px;
|
||||||
|
}
|
||||||
|
.schedule-template.pinky.day-content {
|
||||||
|
position: relative;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 550;
|
||||||
|
color: #af8080c9;
|
||||||
|
}
|
||||||
|
.schedule-template.pinky.day-content#rest {
|
||||||
|
color: #cfb7b7c9;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.schedule-template.pinky.title-container {
|
||||||
|
position: relative;
|
||||||
|
background: #fdf8f8c9;
|
||||||
|
width: 400px;
|
||||||
|
height: 70px;
|
||||||
|
left: 70px;
|
||||||
|
top: 20px;
|
||||||
|
border-radius: 20px;
|
||||||
|
border: 3px solid var(--pinky-border-color-dark);
|
||||||
|
border-top: none;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
.schedule-template.pinky.title {
|
||||||
|
position: relative;
|
||||||
|
top: -5px;
|
||||||
|
font-size: 50px;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--pinky-font-color-dark);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const accountInfo = useAccount()
|
|||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
userInfo: UserInfo | undefined
|
userInfo: UserInfo | undefined
|
||||||
|
biliInfo: any | undefined
|
||||||
currentData: SongsInfo[] | undefined
|
currentData: SongsInfo[] | undefined
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -2210,6 +2210,11 @@ minimist@^1.2.0, minimist@^1.2.6:
|
|||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||||
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||||
|
|
||||||
|
mitt@^3.0.1:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1"
|
||||||
|
integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==
|
||||||
|
|
||||||
mkdirp@~1.0.4:
|
mkdirp@~1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||||
|
|||||||
Reference in New Issue
Block a user