|
|
@ -1,21 +1,12 @@ |
|
|
|
<template> |
|
|
|
<Simplebar @scroll="handleScroll"> |
|
|
|
<div class="header"> |
|
|
|
<!-- 头部导航菜单 --> |
|
|
|
<div class="headerMenu" v-if="show_menu"> |
|
|
|
<a-menu v-model:selectedKeys="current" mode="horizontal" :items="items" style="border-bottom: none;" |
|
|
|
@click="jumpMenu" /> |
|
|
|
<a-input-search v-model:value="searchValue" placeholder="search" style="width: 200px" @search="onSearch" /> |
|
|
|
</div> |
|
|
|
<NavigateMenu /> |
|
|
|
<!-- 作者名字 --> |
|
|
|
<div class="author" v-if="show_author">{{ author }}</div> |
|
|
|
|
|
|
|
<!-- 轮播 --> |
|
|
|
<div class="carousel" v-if="show_carousel"> |
|
|
|
<a-carousel autoplay> |
|
|
|
<div class="img"><img src="/src/assets/images/nav1.png" alt=""></div> |
|
|
|
<div class="img"><img src="/src/assets/images/nav10.png" alt=""></div> |
|
|
|
<div class="img"><img src="/src/assets/images/nav13.png" alt=""></div> |
|
|
|
</a-carousel> |
|
|
|
</div> |
|
|
|
<CarouselImg /> |
|
|
|
<!-- 操作按钮滚动 --> |
|
|
|
<div class="anchorDown" v-if="show_anchornDown"> |
|
|
|
<a-button type="link" shape="circle" size="large" @click="downScroll"> |
|
|
@ -24,48 +15,18 @@ |
|
|
|
</template> |
|
|
|
</a-button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 主要内容区域 --> |
|
|
|
<div class="mainContainer" :style="mainCss"> |
|
|
|
<div class="leftBar"> |
|
|
|
<!-- <a-card hoverable> |
|
|
|
<template #cover> |
|
|
|
<img alt="example" src="/src/assets/images/头像.jpg" /> |
|
|
|
</template> |
|
|
|
<h1>sunfree</h1> |
|
|
|
<div class="cardText"></div> |
|
|
|
<div class="button-group"> |
|
|
|
<a-button v-for="(button, index) in buttons" :key="index" shape="circle" size="large" |
|
|
|
@click="handleClick(button.url)"> |
|
|
|
<component :is="button.icon" /> |
|
|
|
</a-button> |
|
|
|
</div> |
|
|
|
<div class="fold-panel"> |
|
|
|
<a-collapse v-model:activeKey="activeKey" :bordered="false" expandIconPosition="end"> |
|
|
|
<template #expandIcon="{ isActive }"> |
|
|
|
<caret-right-outlined :rotate="isActive ? 90 : 0" /> |
|
|
|
</template> |
|
|
|
<a-collapse-panel v-for="classtic in classticlist" :key=classtic.id :header=classtic.header |
|
|
|
:style="customStyle"> |
|
|
|
<p>{{ classtic.text }}</p> |
|
|
|
</a-collapse-panel> |
|
|
|
</a-collapse> |
|
|
|
</div> |
|
|
|
</a-card> --> |
|
|
|
<LeftSiteInfo/> |
|
|
|
<LeftSiteInfo /> |
|
|
|
<ComLink /> |
|
|
|
</div> |
|
|
|
<RouterView /> |
|
|
|
<div class="rightBar"> |
|
|
|
<a-card hoverable> |
|
|
|
<div class="statistic"> |
|
|
|
<a-row> |
|
|
|
<a-col :span="8" v-for="statistic in statistics" :key="statistic.id"> |
|
|
|
<a-statistic :title=statistic.title :value=statistic.counts /> |
|
|
|
</a-col> |
|
|
|
</a-row> |
|
|
|
</div> |
|
|
|
</a-card> |
|
|
|
<StatisticCount /> |
|
|
|
<a-card hoverable> |
|
|
|
<template #cover> |
|
|
|
<div class="heatmap" style="border-right: rgba(0, 0, 0, 0.5);"> |
|
|
@ -158,12 +119,10 @@ |
|
|
|
</Simplebar> |
|
|
|
</template> |
|
|
|
<script lang="ts" setup> |
|
|
|
import { h, reactive, ref, nextTick, toRefs, computed } from 'vue'; |
|
|
|
import type { MenuProps } from 'ant-design-vue'; |
|
|
|
import { HomeOutlined, HighlightOutlined, ProfileOutlined, CameraOutlined, UsergroupDeleteOutlined, DownCircleOutlined } from '@ant-design/icons-vue'; |
|
|
|
import { reactive, ref, nextTick, toRefs } from 'vue'; |
|
|
|
import { DownCircleOutlined } from '@ant-design/icons-vue'; |
|
|
|
import Typed from 'typed.js'; |
|
|
|
import { onMounted, watch } from 'vue'; |
|
|
|
import { CaretRightOutlined } from '@ant-design/icons-vue'; |
|
|
|
import 'APlayer/dist/APlayer.min.css'; |
|
|
|
import APlayer from 'APlayer'; |
|
|
|
import { get } from "@/tools/request" |
|
|
@ -174,112 +133,106 @@ import type { classticInterface, labelInterface } from '@/api/admin'; |
|
|
|
import type { homePageInterface } from '@/api'; |
|
|
|
import ComLink from './ComLink.vue'; |
|
|
|
import LeftSiteInfo from "./LeftSiteInfo.vue" |
|
|
|
const router = useRouter() |
|
|
|
const route = useRoute() |
|
|
|
import StatisticCount from "./StatisticCount.vue" |
|
|
|
import NavigateMenu from './header/NavigateMenu.vue'; |
|
|
|
import { homePageStore } from '@/stores'; |
|
|
|
import CarouselImg from './header/CarouselImg.vue'; |
|
|
|
const author = ref("SunFree.") |
|
|
|
/** |
|
|
|
* 隐藏参数 |
|
|
|
*/ |
|
|
|
const idShow = reactive({ |
|
|
|
show_menu: false, |
|
|
|
show_carousel: true, |
|
|
|
show_author: true, |
|
|
|
show_anchornDown: true |
|
|
|
}) |
|
|
|
const { idShow } = homePageStore() |
|
|
|
const { show_menu, show_carousel, show_author, show_anchornDown } = toRefs(idShow) |
|
|
|
|
|
|
|
const mainCss = reactive({ |
|
|
|
marginTop: "0px" |
|
|
|
}) |
|
|
|
const current = ref<string[]>(['home']); |
|
|
|
const items = ref<MenuProps['items']>([ |
|
|
|
{ |
|
|
|
key: 'home', |
|
|
|
icon: () => h(HomeOutlined), |
|
|
|
label: '首页', |
|
|
|
title: '首页', |
|
|
|
|
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'blog', |
|
|
|
icon: () => h(HighlightOutlined), |
|
|
|
label: '博客', |
|
|
|
title: '博客', |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'diary', |
|
|
|
icon: () => h(ProfileOutlined), |
|
|
|
label: '日记', |
|
|
|
title: '日记', |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'album', |
|
|
|
icon: () => h(CameraOutlined), |
|
|
|
label: '相册', |
|
|
|
title: '相册', |
|
|
|
children: [ |
|
|
|
{ |
|
|
|
label: '相册1', |
|
|
|
key: 'album1', |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: '相册2', |
|
|
|
key: 'album2', |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: '相册3', |
|
|
|
key: 'album3', |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: '相册4', |
|
|
|
key: 'album4', |
|
|
|
}, |
|
|
|
], |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'chart', |
|
|
|
icon: () => h(UsergroupDeleteOutlined), |
|
|
|
label: '收支图', |
|
|
|
title: '收支图', |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'aboutme', |
|
|
|
icon: () => h(UsergroupDeleteOutlined), |
|
|
|
label: '关于sunfree', |
|
|
|
title: '关于sunfree', |
|
|
|
}, |
|
|
|
]); |
|
|
|
const searchValue = ref("") |
|
|
|
const jumpMenu = ({ key }: { key: string }) => { |
|
|
|
router.push(`/${key}`) |
|
|
|
}; |
|
|
|
const updateCarouselVisibility = (routeName: any) => { |
|
|
|
handleScrollEnabled.value = false; |
|
|
|
if (scrollbar.value) { |
|
|
|
scrollbar.value.scrollTop = 0; |
|
|
|
} |
|
|
|
if (routeName === 'home') { |
|
|
|
handleScrollEnabled.value = true; |
|
|
|
show_carousel.value = true; |
|
|
|
show_menu.value = false |
|
|
|
} else { |
|
|
|
show_menu.value = true; |
|
|
|
show_author.value = false; |
|
|
|
show_carousel.value = false; |
|
|
|
show_anchornDown.value = false; |
|
|
|
mainCss.marginTop = '48px'; |
|
|
|
} |
|
|
|
}; |
|
|
|
router.beforeEach((to, _, next) => { |
|
|
|
updateCarouselVisibility(to.name); |
|
|
|
next(); |
|
|
|
}); |
|
|
|
// const current = ref<string[]>(['home']); |
|
|
|
// const items = ref<MenuProps['items']>([ |
|
|
|
// { |
|
|
|
// key: 'home', |
|
|
|
// icon: () => h(HomeOutlined), |
|
|
|
// label: '首页', |
|
|
|
// title: '首页', |
|
|
|
|
|
|
|
// }, |
|
|
|
// { |
|
|
|
// key: 'blog', |
|
|
|
// icon: () => h(HighlightOutlined), |
|
|
|
// label: '博客', |
|
|
|
// title: '博客', |
|
|
|
// }, |
|
|
|
// { |
|
|
|
// key: 'diary', |
|
|
|
// icon: () => h(ProfileOutlined), |
|
|
|
// label: '日记', |
|
|
|
// title: '日记', |
|
|
|
// }, |
|
|
|
// { |
|
|
|
// key: 'album', |
|
|
|
// icon: () => h(CameraOutlined), |
|
|
|
// label: '相册', |
|
|
|
// title: '相册', |
|
|
|
// children: [ |
|
|
|
// { |
|
|
|
// label: '相册1', |
|
|
|
// key: 'album1', |
|
|
|
// }, |
|
|
|
// { |
|
|
|
// label: '相册2', |
|
|
|
// key: 'album2', |
|
|
|
// }, |
|
|
|
// { |
|
|
|
// label: '相册3', |
|
|
|
// key: 'album3', |
|
|
|
// }, |
|
|
|
// { |
|
|
|
// label: '相册4', |
|
|
|
// key: 'album4', |
|
|
|
// }, |
|
|
|
// ], |
|
|
|
// }, |
|
|
|
// { |
|
|
|
// key: 'chart', |
|
|
|
// icon: () => h(UsergroupDeleteOutlined), |
|
|
|
// label: '收支图', |
|
|
|
// title: '收支图', |
|
|
|
// }, |
|
|
|
// { |
|
|
|
// key: 'aboutme', |
|
|
|
// icon: () => h(UsergroupDeleteOutlined), |
|
|
|
// label: '关于sunfree', |
|
|
|
// title: '关于sunfree', |
|
|
|
// }, |
|
|
|
// ]); |
|
|
|
// const searchValue = ref("") |
|
|
|
// const jumpMenu = ({ key }: { key: string }) => { |
|
|
|
// router.push(`/${key}`) |
|
|
|
// }; |
|
|
|
// const updateCarouselVisibility = (routeName: any) => { |
|
|
|
// handleScrollEnabled.value = false; |
|
|
|
// if (scrollbar.value) { |
|
|
|
// scrollbar.value.scrollTop = 0; |
|
|
|
// } |
|
|
|
// if (routeName === 'home') { |
|
|
|
// handleScrollEnabled.value = true; |
|
|
|
// show_carousel.value = true; |
|
|
|
// show_menu.value = false |
|
|
|
// } else { |
|
|
|
// show_menu.value = true; |
|
|
|
// show_author.value = false; |
|
|
|
// show_carousel.value = false; |
|
|
|
// show_anchornDown.value = false; |
|
|
|
// mainCss.marginTop = '48px'; |
|
|
|
// } |
|
|
|
// }; |
|
|
|
// router.beforeEach((to, _, next) => { |
|
|
|
// updateCarouselVisibility(to.name); |
|
|
|
// next(); |
|
|
|
// }); |
|
|
|
// 查询功能 |
|
|
|
const articleTitle = ref<string>(''); |
|
|
|
const onSearch = (searchValue: string) => { |
|
|
|
console.log('use value', searchValue); |
|
|
|
console.log('or use this.value', articleTitle.value); |
|
|
|
}; |
|
|
|
// const articleTitle = ref<string>(''); |
|
|
|
// const onSearch = (searchValue: string) => { |
|
|
|
// console.log('use value', searchValue); |
|
|
|
// console.log('or use this.value', articleTitle.value); |
|
|
|
// }; |
|
|
|
|
|
|
|
/** |
|
|
|
* 滚动条操作 |
|
|
@ -375,63 +328,63 @@ const downScroll = () => { |
|
|
|
* 右侧栏 |
|
|
|
*/ |
|
|
|
// 统计 |
|
|
|
const createData = new Date('2024-07-12'); |
|
|
|
const currentDate = ref(new Date()); |
|
|
|
const getDateOnly = (date: Date) => { |
|
|
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate()); |
|
|
|
}; |
|
|
|
|
|
|
|
// 计算相差的天数 |
|
|
|
const daysDifference = computed(() => { |
|
|
|
const oneDay = 24 * 60 * 60 * 1000; // 一天的毫秒数 |
|
|
|
const diffTime = Math.abs(getDateOnly(currentDate.value).getTime() - getDateOnly(createData).getTime()); |
|
|
|
return Math.floor(diffTime / oneDay); // 使用Math.floor确保是整天数 |
|
|
|
}); |
|
|
|
const diaryTotal = ref(); |
|
|
|
const blogTotal = ref(); |
|
|
|
const diaryList = async () => { |
|
|
|
try { |
|
|
|
const response = await get('/diarys/list'); |
|
|
|
diaryTotal.value = response.data.data.total; // 更新总数 |
|
|
|
} catch (error) { |
|
|
|
console.error('Failed to fetch data', error); |
|
|
|
} |
|
|
|
}; |
|
|
|
const blogList = async () => { |
|
|
|
try { |
|
|
|
const response = await get("/blogs/list"); |
|
|
|
if (response) { |
|
|
|
blogTotal.value = response.data.data.total; |
|
|
|
} else { |
|
|
|
console.log("bloglist is not exits") |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.log("bloglist is error") |
|
|
|
} |
|
|
|
// const createData = new Date('2024-07-12'); |
|
|
|
// const currentDate = ref(new Date()); |
|
|
|
// const getDateOnly = (date: Date) => { |
|
|
|
// return new Date(date.getFullYear(), date.getMonth(), date.getDate()); |
|
|
|
// }; |
|
|
|
|
|
|
|
// // 计算相差的天数 |
|
|
|
// const daysDifference = computed(() => { |
|
|
|
// const oneDay = 24 * 60 * 60 * 1000; // 一天的毫秒数 |
|
|
|
// const diffTime = Math.abs(getDateOnly(currentDate.value).getTime() - getDateOnly(createData).getTime()); |
|
|
|
// return Math.floor(diffTime / oneDay); // 使用Math.floor确保是整天数 |
|
|
|
// }); |
|
|
|
// const diaryTotal = ref(); |
|
|
|
// const blogTotal = ref(); |
|
|
|
// const diaryList = async () => { |
|
|
|
// try { |
|
|
|
// const response = await get('/diarys/list'); |
|
|
|
// diaryTotal.value = response.data.data.total; // 更新总数 |
|
|
|
// } catch (error) { |
|
|
|
// console.error('Failed to fetch data', error); |
|
|
|
// } |
|
|
|
// }; |
|
|
|
// const blogList = async () => { |
|
|
|
// try { |
|
|
|
// const response = await get("/blogs/list"); |
|
|
|
// if (response) { |
|
|
|
// blogTotal.value = response.data.data.total; |
|
|
|
// } else { |
|
|
|
// console.log("bloglist is not exits") |
|
|
|
// } |
|
|
|
// } catch (error) { |
|
|
|
// console.log("bloglist is error") |
|
|
|
// } |
|
|
|
|
|
|
|
} |
|
|
|
// } |
|
|
|
|
|
|
|
// 更新当前时间 |
|
|
|
const updateCurrentDate = () => { |
|
|
|
currentDate.value = new Date(); |
|
|
|
}; |
|
|
|
const statistics = reactive([ |
|
|
|
{ |
|
|
|
id: "1", |
|
|
|
title: "DAYS", |
|
|
|
counts: daysDifference |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: "2", |
|
|
|
title: "DIARYS", |
|
|
|
counts: diaryTotal |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: "3", |
|
|
|
title: "BLOGS", |
|
|
|
counts: blogTotal |
|
|
|
}, |
|
|
|
]) |
|
|
|
// // 更新当前时间 |
|
|
|
// const updateCurrentDate = () => { |
|
|
|
// currentDate.value = new Date(); |
|
|
|
// }; |
|
|
|
// const statistics = reactive([ |
|
|
|
// { |
|
|
|
// id: "1", |
|
|
|
// title: "DAYS", |
|
|
|
// counts: daysDifference |
|
|
|
// }, |
|
|
|
// { |
|
|
|
// id: "2", |
|
|
|
// title: "DIARYS", |
|
|
|
// counts: diaryTotal |
|
|
|
// }, |
|
|
|
// { |
|
|
|
// id: "3", |
|
|
|
// title: "BLOGS", |
|
|
|
// counts: blogTotal |
|
|
|
// }, |
|
|
|
// ]) |
|
|
|
// 日历热力图 |
|
|
|
const heat = ref(null); |
|
|
|
|
|
|
@ -577,14 +530,14 @@ const labelList = async () => { |
|
|
|
} |
|
|
|
onMounted(() => { |
|
|
|
// classticList() |
|
|
|
blogList() |
|
|
|
// blogList() |
|
|
|
labelList() |
|
|
|
diaryList() |
|
|
|
// diaryList() |
|
|
|
// comLinkList() |
|
|
|
statisticList() |
|
|
|
updateCurrentDate(); |
|
|
|
// updateCurrentDate(); |
|
|
|
homePageList() |
|
|
|
setInterval(updateCurrentDate, 24 * 60 * 60 * 1000); |
|
|
|
// setInterval(updateCurrentDate, 24 * 60 * 60 * 1000); |
|
|
|
createEcharts(heat, heatMapData); |
|
|
|
nextTick(() => { |
|
|
|
const authorElement = document.querySelector('.author'); |
|
|
@ -650,54 +603,38 @@ onMounted(() => { |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
watch( |
|
|
|
() => route.name, |
|
|
|
(newRouteName) => { |
|
|
|
updateCarouselVisibility(newRouteName); |
|
|
|
|
|
|
|
if (newRouteName) { |
|
|
|
// 尝试从菜单项中找到与当前路由名称匹配的项 |
|
|
|
const menuItem = items.value?.find((item: any) => { |
|
|
|
// 这里可以根据实际情况来匹配路由名称或路径 |
|
|
|
// 例如,可以根据 route.name 或 route.path 来匹配 |
|
|
|
if (newRouteName === 'blogdetail') { |
|
|
|
return item.key === 'blog'; // 匹配博客详情页,选中博客菜单 |
|
|
|
} else if (newRouteName === 'diarydetail') { |
|
|
|
return item.key === 'diary'; // 匹配日记详情页,选中日记菜单 |
|
|
|
} else { |
|
|
|
return item.key === newRouteName; // 默认匹配路由名称 |
|
|
|
} |
|
|
|
}); |
|
|
|
// watch( |
|
|
|
// () => route.name, |
|
|
|
// (newRouteName) => { |
|
|
|
// updateCarouselVisibility(newRouteName); |
|
|
|
|
|
|
|
// if (newRouteName) { |
|
|
|
// // 尝试从菜单项中找到与当前路由名称匹配的项 |
|
|
|
// const menuItem = items.value?.find((item: any) => { |
|
|
|
// // 这里可以根据实际情况来匹配路由名称或路径 |
|
|
|
// // 例如,可以根据 route.name 或 route.path 来匹配 |
|
|
|
// if (newRouteName === 'blogdetail') { |
|
|
|
// return item.key === 'blog'; // 匹配博客详情页,选中博客菜单 |
|
|
|
// } else if (newRouteName === 'diarydetail') { |
|
|
|
// return item.key === 'diary'; // 匹配日记详情页,选中日记菜单 |
|
|
|
// } else { |
|
|
|
// return item.key === newRouteName; // 默认匹配路由名称 |
|
|
|
// } |
|
|
|
// }); |
|
|
|
|
|
|
|
if (menuItem) { |
|
|
|
current.value = [menuItem.key as string]; |
|
|
|
} else { |
|
|
|
current.value = ['home']; // 找不到对应的菜单项,默认选中 'home' |
|
|
|
} |
|
|
|
} else { |
|
|
|
current.value = ['home']; // 如果 route.name 不存在,默认选中 'home' |
|
|
|
} |
|
|
|
}, |
|
|
|
{ immediate: true } |
|
|
|
); |
|
|
|
// if (menuItem) { |
|
|
|
// current.value = [menuItem.key as string]; |
|
|
|
// } else { |
|
|
|
// current.value = ['home']; // 找不到对应的菜单项,默认选中 'home' |
|
|
|
// } |
|
|
|
// } else { |
|
|
|
// current.value = ['home']; // 如果 route.name 不存在,默认选中 'home' |
|
|
|
// } |
|
|
|
// }, |
|
|
|
// { immediate: true } |
|
|
|
// ); |
|
|
|
</script> |
|
|
|
<style scoped> |
|
|
|
.headerMenu { |
|
|
|
display: flex; |
|
|
|
justify-content: center; |
|
|
|
align-items: center; |
|
|
|
width: 100%; |
|
|
|
height: 48px; |
|
|
|
border-bottom: 1px solid rgba(5, 5, 5, 0.06); |
|
|
|
position: fixed; |
|
|
|
background-color: white; |
|
|
|
transform: translateX(-50%); |
|
|
|
top: 0; |
|
|
|
left: 50%; |
|
|
|
z-index: 999; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 作者名称 */ |
|
|
|
.author { |
|
|
@ -731,10 +668,6 @@ watch( |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.carousel img { |
|
|
|
height: 100vh; |
|
|
|
width: 100vw; |
|
|
|
} |
|
|
|
|
|
|
|
.anchorDown { |
|
|
|
position: absolute; |
|
|
@ -806,9 +739,6 @@ watch( |
|
|
|
margin: 0; |
|
|
|
} |
|
|
|
|
|
|
|
.statistic { |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
|
|
|
|
.footer { |
|
|
|
display: flex; |
|
|
|
xxxxxxxxxx