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

<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>