You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
570 lines
18 KiB
570 lines
18 KiB
<template>
|
|
<Simplebar @scroll="handleScroll">
|
|
<!-- 头部导航菜单 -->
|
|
<div class="headerMenu" v-if="show_menu">
|
|
<a-menu v-model:selectedKeys="current" mode="horizontal" :items="items" style="border-bottom: none;"
|
|
@click="menuClick" @select="menuSelect"/>
|
|
<a-input-search v-model:value="value" placeholder="search" style="width: 200px" @search="onSearch" />
|
|
</div>
|
|
<div class="author" v-if="show_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>
|
|
<!-- 操作按钮滚动 -->
|
|
<div class="anchorDown">
|
|
<a-button type="link" shape="circle" size="large" @click="downScroll">
|
|
<template #icon>
|
|
<DownCircleOutlined style="font-size: 35px;color: aliceblue;" spin />
|
|
</template>
|
|
</a-button>
|
|
</div>
|
|
|
|
<!-- 主要内容区域 -->
|
|
<div class="mainContainer" :style="mainCss">
|
|
<div class="leftBar">
|
|
<a-card hoverable>
|
|
<template #cover>
|
|
<img alt="example" :src="img" />
|
|
</template>
|
|
<h1>sunfree</h1>
|
|
<div class="cardText"></div>
|
|
<div class="button-group">
|
|
<a-button shape="circle" size="large" @click="gravatarClick">
|
|
<GravatarLined />
|
|
</a-button>
|
|
<a-button shape="circle" size="large">
|
|
<QQLined />
|
|
</a-button>
|
|
<a-button shape="circle" size="large">
|
|
<WechatLined />
|
|
</a-button>
|
|
<a-button shape="circle" size="large">
|
|
<MusicLined />
|
|
</a-button>
|
|
<a-button shape="circle" size="large">
|
|
<GitHubLined />
|
|
</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 key="1" header="内容1" :style="customStyle">
|
|
<p>{{ text }}</p>
|
|
</a-collapse-panel>
|
|
<a-collapse-panel key="2" header="内容2" :style="customStyle">
|
|
<p>{{ text }}</p>
|
|
</a-collapse-panel>
|
|
<a-collapse-panel key="3" header="内容3" :style="customStyle">
|
|
<p>{{ text }}</p>
|
|
</a-collapse-panel>
|
|
</a-collapse>
|
|
</div>
|
|
</a-card>
|
|
<a-card hoverable title="常用链接">
|
|
<div class="button-group">
|
|
<a-button type="dashed">Link</a-button>
|
|
<a-button type="dashed">Link</a-button>
|
|
<a-button type="dashed">Link</a-button>
|
|
<a-button type="dashed">Link</a-button>
|
|
<a-button type="dashed">Link</a-button>
|
|
<a-button type="dashed">Link</a-button>
|
|
<a-button type="dashed">Link</a-button>
|
|
<a-button type="dashed">Link</a-button>
|
|
<a-button type="dashed">Link</a-button>
|
|
<a-button type="dashed">Link</a-button>
|
|
<a-button type="dashed">Link</a-button>
|
|
<a-button type="dashed">Link</a-button>
|
|
</div>
|
|
</a-card>
|
|
</div>
|
|
<RouterView />
|
|
<div class="rightBar">
|
|
<a-card hoverable style="width: 400px;">
|
|
<template #cover>
|
|
<div id="aplayer" style="width: 400px;"></div>
|
|
<div class="heatmap" style="border-right: rgba(0, 0, 0, 0.5);">
|
|
<div ref="heat" style="height: 100%;"></div>
|
|
</div>
|
|
<div class="statistic">
|
|
<a-row>
|
|
<a-col :span="8">
|
|
<a-statistic title="DAYS" :value="112893" />
|
|
</a-col>
|
|
<a-col :span="8">
|
|
<a-statistic title="DIARYS" :value="112893" />
|
|
</a-col>
|
|
<a-col :span="8">
|
|
<a-statistic title="BLOGS" :value="112893" />
|
|
</a-col>
|
|
</a-row>
|
|
</div>
|
|
</template>
|
|
</a-card>
|
|
<a-card title="随机文章" :bordered="false" hoverable style="width: 400px;margin: 12px 0;">
|
|
sces
|
|
</a-card>
|
|
|
|
<a-card title="标签云" :bordered="false" hoverable style="width: 400px;margin: 12px 0;">
|
|
sces
|
|
</a-card>
|
|
</div>
|
|
</div>
|
|
|
|
</Simplebar>
|
|
</template>
|
|
<script lang="ts" setup>
|
|
import { h, reactive, ref,nextTick } from 'vue';
|
|
import { MenuProps } from 'ant-design-vue/es/menu';
|
|
import { HomeOutlined, HighlightOutlined, ProfileOutlined, CameraOutlined, UsergroupDeleteOutlined, DownCircleOutlined } from '@ant-design/icons-vue';
|
|
import { MusicLined, EmailLined, QQLined, WechatLined, GravatarLined, GitHubLined } from "@/assets"
|
|
import Typed from 'typed.js';
|
|
import { onMounted,watch } from 'vue';
|
|
import type { CSSProperties } from 'vue';
|
|
import { CaretRightOutlined } from '@ant-design/icons-vue';
|
|
import 'APlayer/dist/APlayer.min.css';
|
|
import APlayer from 'APlayer';
|
|
import { createEcharts } from "@/hooks/intex"
|
|
import { SettingOutlined, EditOutlined, EllipsisOutlined } from '@ant-design/icons-vue';
|
|
import { RiLiLined, YueDuLined, YanJingLined, XieZiLined } from '@/assets';
|
|
import { useRouter, useRoute } from 'vue-router';
|
|
const random = ref();
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const heat = ref(null);
|
|
const activeKey = ref(['']);
|
|
const text = `A dog is a type of domesticated animal.Known for its loyalty and faithfulness,it can be found as a welcome guest in many households across the world.`;
|
|
const customStyle =
|
|
'background: #F5F5F5;border-radius: 4px;margin-bottom: 12px;border: 0;overflow: hidden';
|
|
const scrollbar=ref<Element | null>(null);
|
|
onMounted(() => {
|
|
// 定义home页的博客标题名
|
|
new Typed('.author', {
|
|
strings: ['SunFree.'],
|
|
typeSpeed: 200,
|
|
backSpeed: 150,
|
|
loop: true,
|
|
loopCount: Infinity,
|
|
showCursor: false
|
|
});
|
|
// 定义个人座右铭
|
|
new Typed('.cardText', {
|
|
strings: ['做三流测试,品瀚霖人生!'],
|
|
typeSpeed: 200,
|
|
backSpeed: 150,
|
|
loop: true, // 开启循环
|
|
loopCount: Infinity, // 无限循环
|
|
showCursor: false // 取消光标
|
|
});
|
|
new APlayer({
|
|
container: document.getElementById('aplayer'),
|
|
mini: false,
|
|
autoplay: false,
|
|
theme: '#FADFA3',
|
|
loop: 'all',
|
|
order: 'random',
|
|
preload: 'auto',
|
|
volume: 0.7,
|
|
mutex: true,
|
|
listFolded: true,
|
|
listMaxHeight: 90,
|
|
lrcType: 3,
|
|
audio: [
|
|
{
|
|
name: 'name1',
|
|
artist: 'artist1',
|
|
url: 'url1.mp3',
|
|
cover: 'cover1.jpg',
|
|
lrc: 'lrc1.lrc',
|
|
theme: '#ebd0c2'
|
|
},
|
|
{
|
|
name: 'name2',
|
|
artist: 'artist2',
|
|
url: 'url2.mp3',
|
|
cover: 'cover2.jpg',
|
|
lrc: 'lrc2.lrc',
|
|
theme: '#46718b'
|
|
}
|
|
]
|
|
});
|
|
function generateDates(numDays: number) {
|
|
const dates = [];
|
|
const currentDate = new Date();
|
|
for (let i = 0; i < numDays; i++) {
|
|
const date = new Date(currentDate);
|
|
date.setDate(currentDate.getDate() - i);
|
|
dates.push(
|
|
{ date: date.toISOString().split('T')[0], blogCount: 0 }
|
|
); // 包含日期和评论数
|
|
}
|
|
return dates;
|
|
}
|
|
|
|
// 初始化60天的数据
|
|
const data = generateDates(60);
|
|
console.log(`output->`, data)
|
|
data[3].blogCount = 5;
|
|
data[15].blogCount = 10;
|
|
data[25].blogCount = 3;
|
|
|
|
// 重新排列数据
|
|
const newData = [];
|
|
for (let i = 0; i < 60; i += 15) {
|
|
// 取出每个15天的数据,并反转顺序
|
|
const chunk = data.slice(i, i + 15).reverse();
|
|
newData.push(...chunk);
|
|
}
|
|
|
|
const formattedData = newData.map((value, index) => [index % 15, Math.floor(index / 15), value.blogCount]);
|
|
const heatMapData = {
|
|
tooltip: {
|
|
position: 'top',
|
|
formatter: function (params: any) {
|
|
const item = newData[params.dataIndex];
|
|
if (item.blogCount > 0) {
|
|
return `${item.date}<br/>COMMENTS: ${item.blogCount}`;
|
|
} else {
|
|
return `${item.date}`;
|
|
}
|
|
}
|
|
},
|
|
grid: {
|
|
left: '0', // 左边距
|
|
right: '0', // 右边距
|
|
top: '0', // 上边距
|
|
bottom: '0',
|
|
},
|
|
xAxis: {
|
|
type: 'category',
|
|
data: Array.from({ length: 15 }, (_, i) => `Col ${i + 1}`),
|
|
splitArea: {
|
|
show: true
|
|
},
|
|
show: false
|
|
},
|
|
yAxis: {
|
|
type: 'category',
|
|
data: ['Row 1', 'Row 2', 'Row 3', 'Row 4'],
|
|
splitArea: {
|
|
show: false
|
|
},
|
|
show: false
|
|
},
|
|
visualMap: {
|
|
min: 0,
|
|
max: 10,
|
|
calculable: true,
|
|
orient: 'horizontal',
|
|
left: 'center',
|
|
bottom: '15%',
|
|
itemGap: 5,
|
|
show: false,
|
|
inRange: {
|
|
color: ['#ffffff', '#000000'] // 0评论是白色, 非0评论是黑色
|
|
}
|
|
},
|
|
series: [{
|
|
type: 'heatmap',
|
|
data: formattedData,
|
|
itemStyle: {
|
|
borderColor: 'rgba(0, 0, 0, 0.1)', // 设置边框颜色
|
|
borderWidth: 0.5, // 设置边框宽度
|
|
},
|
|
label: {
|
|
show: false,
|
|
},
|
|
emphasis: {
|
|
itemStyle: {
|
|
shadowBlur: 10,
|
|
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
|
borderColor: '#fff', // 鼠标悬停时的边框颜色
|
|
borderWidth: 2 // 鼠标悬停时的边框宽度
|
|
}
|
|
}
|
|
}]
|
|
};
|
|
createEcharts(heat, heatMapData);
|
|
scrollbar.value = document.querySelector('.simplebar-content-wrapper');
|
|
// const storedShowMenu = localStorage.getItem('show_menu');
|
|
// const storedShowCarousel = localStorage.getItem('show_carousel');
|
|
// const storedScrollPosition = localStorage.getItem('scrollPosition');
|
|
// const storedMainCssMarginTop = localStorage.getItem('mainCss_marginTop');
|
|
// if (storedShowMenu !== null) {
|
|
// show_menu.value = storedShowMenu === 'true';
|
|
// }
|
|
// if (storedShowCarousel !== null) {
|
|
// show_carousel.value = storedShowCarousel === 'true';
|
|
// }
|
|
// if (storedScrollPosition !== null && scrollbar.value) {
|
|
// scrollbar.value.scrollTop = parseInt(storedScrollPosition, 10);
|
|
// }
|
|
// if (storedMainCssMarginTop !== null) {
|
|
// mainCss.marginTop = storedMainCssMarginTop;
|
|
// }
|
|
|
|
})
|
|
|
|
// 导航菜单
|
|
const show_menu = ref(false);
|
|
const show_carousel = ref(true);
|
|
const show_author = ref(true)
|
|
const mainCss=reactive({
|
|
marginTop:"0px"
|
|
})
|
|
|
|
const items = ref<MenuProps['items']>([
|
|
{
|
|
key: 'home',
|
|
icon: () => h(HomeOutlined),
|
|
label: '首页',
|
|
title: '首页',
|
|
url: '/'
|
|
},
|
|
{
|
|
key: 'blog',
|
|
icon: () => h(HighlightOutlined),
|
|
label: '博客',
|
|
title: '博客',
|
|
url: "/blog"
|
|
},
|
|
{
|
|
key: 'diary',
|
|
icon: () => h(ProfileOutlined),
|
|
label: '日记',
|
|
title: '日记',
|
|
url: '/diary'
|
|
},
|
|
{
|
|
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: 'aboutme',
|
|
icon: () => h(UsergroupDeleteOutlined),
|
|
label: '关于sunfree',
|
|
title: '关于sunfree',
|
|
},
|
|
]);
|
|
const handleScrollEnabled = ref(true);
|
|
// 定义滚动条滚到一半显示导航菜单
|
|
const handleScroll = () => {
|
|
if (!handleScrollEnabled.value) return;
|
|
if (scrollbar.value) {
|
|
const scrollOffset = scrollbar.value.scrollTop;
|
|
const halfViewportHeight = scrollbar.value.clientHeight / 2;
|
|
show_menu.value = scrollOffset > halfViewportHeight;
|
|
}
|
|
};
|
|
|
|
const menuClick = ({ item }: { item: any }) => {
|
|
handleScrollEnabled.value=false
|
|
if (scrollbar.value) {
|
|
}
|
|
if (item.url=="/" || item.url=="/home") {
|
|
handleScrollEnabled.value=true
|
|
show_carousel.value=true
|
|
}else{
|
|
show_menu.value=true
|
|
show_carousel.value=false
|
|
scrollbar.value!.scrollTop=0
|
|
mainCss.marginTop="48px"
|
|
// localStorage.setItem('show_menu', 'true');
|
|
// localStorage.setItem('show_carousel', 'false');
|
|
// localStorage.setItem('scrollPosition', '0');
|
|
// localStorage.setItem('mainCss_marginTop', '48px');
|
|
}
|
|
router.push(item.url)
|
|
}
|
|
const current = ref<string[]>(['mail']);
|
|
|
|
|
|
// 点击按钮,实现滚动到视窗高度距离,如果已经滚动,只需要滚动视窗高度-已经滚动的距离
|
|
const downScroll = () => {
|
|
if (scrollbar.value) {
|
|
const scrollTop = scrollbar.value.scrollTop;
|
|
const viewportHeight = scrollbar.value.clientHeight;
|
|
const scrollDistance = viewportHeight - scrollTop -48;
|
|
|
|
setTimeout(() => {
|
|
scrollbar.value!.scrollBy({ top: scrollDistance, behavior: 'smooth' });
|
|
}, 300);
|
|
}
|
|
};
|
|
// 定义文章
|
|
// const articles=reactive({
|
|
// img:"",
|
|
|
|
// })
|
|
|
|
|
|
|
|
const value = ref<string>('');
|
|
const onSearch = (searchValue: string) => {
|
|
console.log('use value', searchValue);
|
|
console.log('or use this.value', value.value);
|
|
};
|
|
|
|
const img = ref("https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png")
|
|
|
|
const gravatarClick = () => {
|
|
window.open("https://www.baidu.com")
|
|
}
|
|
</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 {
|
|
position: absolute;
|
|
display: inline-block;
|
|
font-size: 100px;
|
|
font-family: 'Courier New', Courier, monospace;
|
|
background: linear-gradient(270deg, #f5f4f2, #d6cdc7, #4b4949);
|
|
background-size: 400% 400%;
|
|
-webkit-background-clip: text;
|
|
color: transparent;
|
|
background-clip: text;
|
|
animation: salon-light-animation 3s ease infinite;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
z-index: 999;
|
|
}
|
|
|
|
@keyframes salon-light-animation {
|
|
0% {
|
|
background-position: 0% 50%;
|
|
}
|
|
|
|
50% {
|
|
background-position: 100% 50%;
|
|
}
|
|
|
|
100% {
|
|
background-position: 0% 50%;
|
|
}
|
|
}
|
|
|
|
.carousel img{
|
|
height: 100vh;
|
|
width: 100vw;
|
|
}
|
|
.anchorDown {
|
|
position: absolute;
|
|
bottom: 100px;
|
|
left: 50%;
|
|
border-style: hidden;
|
|
transform: translateX(-50%);
|
|
}
|
|
|
|
.mainContainer {
|
|
display: flex;
|
|
justify-content: center;
|
|
padding-top: 48px;
|
|
background-color: rgba(5, 5, 5, 0.08);
|
|
}
|
|
|
|
.leftBar {
|
|
width: 15%;
|
|
}
|
|
|
|
.leftBar img {
|
|
/* 图片自适应容器并保持宽高比例 */
|
|
aspect-ratio: 1/1;
|
|
}
|
|
|
|
.leftBar>* {
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.leftBar h1 {
|
|
text-align: center;
|
|
font-family: Georgia, 'Times New Roman', Times, serif;
|
|
}
|
|
|
|
.leftBar .cardText {
|
|
min-height: 60px;
|
|
text-align: center;
|
|
}
|
|
|
|
.leftBar>:first-child .button-group {
|
|
display: flex;
|
|
margin: 0 12px 24px 12px;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.leftBar>:nth-child(2) .button-group {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.leftBar>:nth-child(2) .button-group>* {
|
|
width: 40%;
|
|
margin: 12px;
|
|
}
|
|
|
|
|
|
.rightBar {
|
|
width: 20%;
|
|
}
|
|
|
|
.aplayer {
|
|
margin: 0 0 24px 0;
|
|
}
|
|
|
|
.heatmap {
|
|
margin: 24px 0;
|
|
}
|
|
|
|
.statistic {
|
|
text-align: center;
|
|
}
|
|
|
|
.sitebar {
|
|
width: 400px;
|
|
}
|
|
</style>
|