页面样式优化

master
liuyx 2 years ago
parent 071afe3388
commit e4ba339b5c

@ -1,16 +1,25 @@
<template> <template>
<div <div
class="m-banner animate__animated animate__slideInDown" :style="{ background: 'url(' + bannerUrl + ') center center / cover no-repeat' }"
:style="{ background: 'url(' + props.bannerUrl + ') center center / cover no-repeat' }" class="m-banner animate__animated animate__fadeInDown"
></div> ></div>
</template> </template>
<script setup> <script setup>
import { defineProps } from 'vue' import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { getPageByName } from '@/api/page.js'
const props = defineProps({ const route = useRoute()
bannerUrl: String const bannerUrl = ref('')
onMounted(async () => {
bannerUrl.value = (await getPageByName(route.name)).data.bannerUrl
}) })
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped>
.animate__fadeInDown {
--animate-duration: 1.7s;
}
</style>

@ -1,90 +1,132 @@
<template> <template>
<el-card class="card-box" v-for="item in blogList" :key="item" shadow="hover"> <el-card class="card-box animate__animated animate__zoomIn" v-for="item in blogList" :key="item">
<div class="blog-item"> <div class="blog-item">
<el-row> <!-- 文章图片 -->
<!-- 文章图片 --> <div class="blog-cover-container">
<el-col :span="10"> <router-link :to="'/articles/' + item._id">
<router-link :to="'/articles/' + item.id"> <img :src="item.cover" alt="" class="cover" />
<img :src="item.firstPicture" alt="" class="first-picture" /> </router-link>
</router-link> </div>
</el-col> <!-- 文章标题和简述 -->
<!-- 文章标题和简述 --> <div class="blog-content">
<el-col :span="14"> <router-link :to="'/articles/' + item._id">
<div class="blog-container"> <div class="title">{{ item.title }}</div>
<router-link :to="'/articles/' + item.id"> </router-link>
<h3>{{ item.title }}</h3> <div class="blog-info">
</router-link> <span><svg-icon name="calendar" class="icon"></svg-icon>{{ item.createTime }}</span>
<div class="description">{{ item.description }}</div> <span class="separator">|</span>
</div> <span><svg-icon name="category" class="icon"></svg-icon>{{ item.category }}</span>
</el-col> <span class="separator">|</span>
</el-row> <span v-for="tag in item.tagList" :key="tag._id"
><svg-icon name="tag" class="icon"></svg-icon>{{ tag.name }}</span
>
</div>
<div class="description">{{ item.content }}</div>
</div>
</div> </div>
</el-card> </el-card>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue' import { ref, onMounted } from 'vue'
// import { Calendar, Memo, CollectionTag } from '@element-plus/icons-vue'
import { getArticleList } from '../api/article'
const blogList = ref([ const blogList = ref([])
{
id: 1, onMounted(() => {
firstPicture: 'https://w.wallhaven.cc/full/zy/wallhaven-zyxvqy.jpg', getBlogList()
title: '测试', })
description: '这是一篇测试文章'
}, const getBlogList = async () => {
{ const { data } = await getArticleList()
id: 1, blogList.value = data.articleList
firstPicture: 'https://w.wallhaven.cc/full/zy/wallhaven-zyxvqy.jpg', console.log(data)
title: '测试', }
description: '这是一篇测试文章'
},
{
id: 1,
firstPicture: 'https://w.wallhaven.cc/full/zy/wallhaven-zyxvqy.jpg',
title: '测试',
description: '这是一篇测试文章'
},
{
id: 1,
firstPicture: 'https://w.wallhaven.cc/full/zy/wallhaven-zyxvqy.jpg',
title: '测试',
description: '这是一篇测试文章'
},
{
id: 1,
firstPicture: 'https://w.wallhaven.cc/full/zy/wallhaven-zyxvqy.jpg',
title: '测试',
description: '这是一篇测试文章'
}
])
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.card-box { .card-box {
margin: 20px 0; margin-top: 10px;
} }
.blog-item { .blog-item {
display: flex; display: flex;
height: 256px;
// justify-content: center;
align-items: center; align-items: center;
.first-picture { .blog-cover-container {
overflow: hidden;
width: 70%;
height: 100%;
}
.cover {
width: 100%; width: 100%;
height: 100%; height: 100%;
box-sizing: border-box; box-sizing: border-box;
border-top-left-radius: 10px; border-top-left-radius: 11px;
border-bottom-left-radius: 10px; border-bottom-left-radius: 11px;
transform: scale(1); transform: scale(1);
transition: transform 1s ease 0s; transition: transform 1s ease 0s;
overflow: hidden; overflow: hidden;
} }
&:hover .first-picture { &:hover .cover {
transform: scale(1.1); transform: scale(1.1);
} }
.blog-container { .blog-content {
padding: 20px 20px 20px 40px; padding: 0 40px;
height: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
.title {
font-size: 1.35em;
&:hover {
color: #8e8cd8;
}
}
.blog-info {
font-size: 0.85em;
margin: 0.85em 0;
}
.separator {
margin: 0 8px;
font-weight: bold;
font-size: 16px;
}
.icon {
vertical-align: -0.33em;
font-size: 12px;
margin-right: 5px;
}
.description { .description {
margin-top: 15px; margin-top: 15px;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
@media screen and (max-width: 768px) {
.blog-item {
display: block;
height: inherit;
.blog-cover-container {
width: 100vw;
.cover {
border-radius: 11px 11px 0 0 !important;
}
}
.blog-content {
height: 202px;
padding: 20px 30px;
.description {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
}
} }
} }
} }

@ -1,90 +1,190 @@
<template> <template>
<header class="header" ref="menu"> <header class="header">
<el-menu <div>
:default-active="navActive" <router-link to="/" class="h-left">BLOG</router-link>
mode="horizontal" </div>
background-color="rgba(0, 0, 0, 0)" <div class="menu">
text-color="#000" <ul>
active-text-color="#FB3B49" <li>
@select="handleSelect" <router-link to="/">
router="true" <el-icon class="m-icon"><House /></el-icon>
> </router-link>
<el-menu-item index="/">首页</el-menu-item> </li>
<el-menu-item index="/tags">标签</el-menu-item> <li>
<el-menu-item index="/categories">分类</el-menu-item> <router-link to="/tags">
<el-menu-item index="/archives">归档</el-menu-item> <el-icon class="m-icon"><PriceTag /></el-icon>
<el-menu-item index="/about">关于我</el-menu-item> </router-link>
</el-menu> </li>
<div class="right-header"> <li>
<el-input v-model="input" placeholder="Please input" /> <router-link to="/categories">
<el-button type="primary" :icon="Search" circle /> <el-icon class="m-icon"><Collection /></el-icon>
<div>登录</div> </router-link>
</li>
<li>
<router-link to="/archives">
<el-icon class="m-icon"><Files /></el-icon>
</router-link>
</li>
<li>
<router-link to="/about">
<el-icon class="m-icon"><User /></el-icon>
</router-link>
</li>
<div class="bottom-strip"></div>
</ul>
</div>
<div class="mobile-menu" @click="mobileShow">
<svg-icon name="menu"></svg-icon>
</div> </div>
</header> </header>
<!-- 移动端展示 -->
<el-drawer v-model="mobileDrawer" size="60%" :show-close="false" :with-header="false">
<h1 class="drawer-header">BLOG</h1>
<div class="drawer-menu">
<router-link to="/">
<el-icon class="drawer-menu-icon"><House /></el-icon>
</router-link>
<router-link to="/tags">
<el-icon class="drawer-menu-icon"><PriceTag /></el-icon>
</router-link>
<router-link to="/categories">
<el-icon class="drawer-menu-icon"><Collection /></el-icon>
</router-link>
<router-link to="/archives">
<el-icon class="drawer-menu-icon"><Files /></el-icon>
</router-link>
<router-link to="/about">
<el-icon class="drawer-menu-icon"><User /></el-icon>
</router-link>
</div>
</el-drawer>
</template> </template>
<script setup> <script setup>
import { Search } from '@element-plus/icons-vue' import { House, PriceTag, Collection, Files, User } from '@element-plus/icons-vue'
import { ref, watch, onMounted } from 'vue' import { ref } from 'vue'
import { useRouter } from 'vue-router'
const menu = ref()
const navActive = ref('/')
const router = useRouter()
// 使el-menu const mobileDrawer = ref(false)
watch(router.currentRoute, () => {
navActive.value = router.currentRoute.value.path
console.log(navActive.value)
})
onMounted(() => { const mobileShow = () => {
// mobileDrawer.value = true
window.addEventListener('scroll', scrollTop, true)
})
//
const scrollTop = () => {
const scroll = document.documentElement.scrollTop || document.body.scrollTop
if (scroll > 0) {
menu.value.style.backgroundColor = '#fff'
menu.value.style.boxShadow = '0px 2px #eee'
} else {
menu.value.style.backgroundColor = 'rgba(0, 0, 0, 0)'
menu.value.style.boxShadow = 'none'
}
} }
// onMounted(() => {
// //
// window.addEventListener('scroll', scrollTop, true)
// })
// //
// const scrollTop = () => {
// const scroll = document.documentElement.scrollTop || document.body.scrollTop
// if (scroll > 0) {
// menu.value.style.backgroundColor = '#fff'
// menu.value.style.boxShadow = '0px 2px #eee'
// } else {
// menu.value.style.backgroundColor = 'rgba(0, 0, 0, 0)'
// menu.value.style.boxShadow = 'none'
// }
// }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.header { .header {
padding: 0 40px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
width: 100%; width: 100%;
// box-shadow: 0px 2px #eee;
// background-color: rgba(0, 0, 0, 0);
padding: 0 30px;
box-sizing: border-box; box-sizing: border-box;
position: fixed; position: absolute;
top: 0; top: 0;
z-index: 999; z-index: 999;
transition-duration: 0.7s; transition-duration: 0.7s;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3);
} }
.right-header { .h-left {
display: flex; width: 60%;
width: 40%; font: 100 30px '优设标题黑';
align-items: center; color: #eee;
justify-content: end; }
.el-input { .menu {
width: 50%; // width: 100%;
height: 50px;
position: relative;
top: 0;
& ul {
width: 100%;
height: 100%;
display: flex;
align-items: center;
}
& ul li {
width: 100%;
text-align: center;
list-style: none;
}
& ul li a {
color: #eee;
font: 100 20px '优设标题黑';
display: block;
width: 100%;
height: 100%;
margin-right: 30px;
}
& ul .bottom-strip {
position: absolute;
bottom: 0;
left: 0;
width: calc((100% / 5) * 1);
height: 5px;
border-radius: 2px;
transition: 0.45s;
}
& ul li:nth-child(1):hover ~ .bottom-strip {
left: calc(100% / 5 * 0);
background-color: rgb(250, 190, 250);
}
& ul li:nth-child(2):hover ~ .bottom-strip {
left: calc(100% / 5 * 1);
background-color: red;
}
& ul li:nth-child(3):hover ~ .bottom-strip {
left: calc(100% / 5 * 2);
background-color: #d18df8;
}
& ul li:nth-child(4):hover ~ .bottom-strip {
left: calc(100% / 5 * 3);
background-color: #ffb1b1;
}
& ul li:nth-child(5):hover ~ .bottom-strip {
left: calc(100% / 5 * 4);
background-color: #8da1f8;
} }
} }
.el-menu { .mobile-menu {
width: 60%; display: none;
} }
.el-menu-item { .drawer-header {
font-size: 17px; text-align: center;
font-weight: 600; margin-bottom: 20px;
}
.drawer-menu {
& a {
display: block;
padding: 10px 10px;
font-size: 18px;
}
.drawer-menu-icon {
margin-right: 1.2em;
vertical-align: -0.13em;
}
}
@media screen and (max-width: 768px) {
.menu {
display: none;
}
.mobile-menu {
display: block;
}
} }
</style> </style>

@ -0,0 +1,99 @@
<!--
* @Author: liuyx 1517482303@qq.com
* @Date: 2022-11-11 09:30:01
* @LastEditTime: 2022-12-19 07:42:44
* @Description: 主页右侧组件用于展示网站信息
-->
<template>
<div class="user-info">
<el-card class="animate__animated animate__zoomIn">
<!-- 头像 -->
<div class="avatar">
<el-avatar :size="100" :src="siteInfo.avatar" />
</div>
<!-- 名称 -->
<h2>{{ siteInfo.author }}</h2>
<!-- 简述 -->
<p>{{ siteInfo.intro }}</p>
<!-- 分类统计 -->
<div class="classification">
<div class="class-item">
<router-link to="/tags">
<div>标签</div>
<div class="class-item-nums">{{ tagNum }}</div>
</router-link>
</div>
<div class="class-item">
<router-link to="/categories">
<div>分类</div>
<div class="class-item-nums">{{ categoryNum }}</div>
</router-link>
</div>
<div class="class-item">
<router-link to="/archives">
<div>归档</div>
<div class="class-item-nums">{{ archiveNum }}</div>
</router-link>
</div>
</div>
<!-- 一些图标 -->
<div class="icons">
<a :href="siteInfo.github"><svg-icon name="github"></svg-icon></a>&nbsp;
<a :href="siteInfo.gitee"><svg-icon name="gitee"></svg-icon></a>
</div>
</el-card>
<el-card class="notice animate__animated animate__zoomIn">
<h3 style="margin-bottom: 10px"><svg-icon name="notice" /> 公告</h3>
{{ siteInfo.notice }}
</el-card>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { getSiteInfo } from '../api/site'
const siteInfo = ref({})
const tagNum = ref(0)
const categoryNum = ref(0)
const archiveNum = ref(0)
onMounted(() => {
getInfo()
})
const getInfo = async () => {
const { data } = await getSiteInfo()
console.log(data)
siteInfo.value = data
}
</script>
<style lang="scss" scoped>
.user-info {
padding: 10px;
text-align: center;
position: sticky;
top: 0px;
.avatar {
}
.classification {
display: flex;
padding: 20px 10px;
box-sizing: border-box;
.class-item {
width: 33.3%;
.class-item-nums {
line-height: 40px;
height: 40px;
}
}
}
.icons {
margin-top: 10px;
}
.notice {
text-align: left;
}
}
</style>

@ -1,82 +0,0 @@
<template>
<el-card shadow="hover" class="user-info">
<!-- 头像 -->
<div class="avatar">
<el-avatar :size="100" :src="userInfo.avatar" />
</div>
<!-- 名称 -->
<h2>{{ userInfo.name }}</h2>
<!-- 简述 -->
<p>{{ userInfo.description }}</p>
<!-- 分类统计 -->
<div class="classification">
<div class="class-item">
<router-link to="/tags">
<div>标签</div>
<div class="class-item-nums">{{ userInfo.tags }}</div>
</router-link>
</div>
<div class="class-item">
<router-link to="/categories">
<div>分类</div>
<div class="class-item-nums">{{ userInfo.categories }}</div>
</router-link>
</div>
<div class="class-item">
<router-link to="/archives">
<div>归档</div>
<div class="class-item-nums">{{ userInfo.archives }}</div>
</router-link>
</div>
</div>
<!-- 一些图标 -->
<div class="icons">
<a :href="userInfo.github"><svg-icon name="github"></svg-icon></a>&nbsp;
<a :href="userInfo.gitee"><svg-icon name="gitee"></svg-icon></a>
</div>
</el-card>
</template>
<script setup>
import { ref } from 'vue'
const userInfo = ref({
name: 'Liuyx',
avatar: 'https://liuyxcc.github.io/img/avatar.png',
description: '抓住现在,做好自己',
tags: 0,
categories: 0,
archives: 0,
github: 'https://github.com/liuyxcc',
gitee: 'https://gitee.com/liuyxcc'
})
</script>
<style lang="scss" scoped>
.el-card {
margin: 20px 0;
}
.user-info {
padding: 10px;
text-align: center;
position: sticky;
top: 10px;
.avatar {
}
.classification {
display: flex;
padding: 20px 10px;
box-sizing: border-box;
.class-item {
width: 33.3%;
.class-item-nums {
line-height: 40px;
height: 40px;
}
}
}
.icons {
margin-top: 10px;
}
}
</style>

@ -1,28 +1,22 @@
<template> <template>
<Banner :bannerUrl="data.bannerUrl" /> <Banner />
<div class="m-content"> <div class="m-content">
<el-card shadow="hover" class="aboutme"> <el-card shadow="hover" class="aboutme">
<v-md-preview :text="blog"></v-md-preview> <v-md-preview :text="content"></v-md-preview>
</el-card> </el-card>
</div> </div>
</template> </template>
<script setup> <script setup>
import Banner from '@/components/Banner.vue' import Banner from '@/components/Banner.vue'
import { ref } from 'vue' import { ref, onMounted } from 'vue'
import { getAboutContent } from '../../api/about'
const data = ref({ const content = ref('') //
bannerUrl: 'https://typora-lyx.oss-cn-guangzhou.aliyuncs.com/typora/wallhaven-p931d9.png'
})
const blog = `
## Welcome!
Hello欢迎来到我的个人博客 onMounted(async () => {
~~~js content.value = (await getAboutContent()).data.content
console.log('Hello World') })
~~~
`
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

@ -1,17 +1,43 @@
<template> <template>
<Banner :bannerUrl="data.bannerUrl" /> <Banner />
<div class="m-content"> <div class="m-content">
<el-card shadow="hover">Archives</el-card> <el-card>
<el-timeline>
<el-timeline-item
v-for="article in articleList"
:key="article._id"
:timestamp="article.createTime"
type="primary"
>
<router-link :to="'/articles/' + article._id">
{{ article.title }}
</router-link>
</el-timeline-item>
</el-timeline>
</el-card>
</div> </div>
</template> </template>
<script setup> <script setup>
import Banner from '@/components/Banner.vue' import Banner from '@/components/Banner.vue'
import { ref } from 'vue' import { ref, onMounted } from 'vue'
import { getArticleList } from '@/api/article.js'
const data = ref({ const articleList = ref([])
bannerUrl: 'https://typora-lyx.oss-cn-guangzhou.aliyuncs.com/typora/wallhaven-1p38v3.png'
onMounted(async () => {
const { data } = await getArticleList()
articleList.value = data.articleList
// console.log(articleList.value)
}) })
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped>
.el-timeline {
padding: 20px 40px;
font-size: 17px;
.el-timeline-item {
margin-top: 10px;
}
}
</style>

@ -1,66 +1,49 @@
<template> <template>
<div class="m-content"> <div
<el-row :gutter="20"> :style="{ background: 'url(' + article.cover + ') center center / cover no-repeat' }"
<el-col :span="18"> class="m-banner animate__animated animate__fadeInDown"
<el-card shadow="hover" class="article"> ></div>
<v-md-preview :text="blog" ref="preview"></v-md-preview> <div class="m-content article-container">
</el-card> <div class="article animate__animated animate__fadeInUp">
</el-col> <el-card>
<el-col :span="6"> <v-md-preview :text="article.content" ref="preview"></v-md-preview>
<el-card shadow="hover" class="directory"> </el-card>
<h3>目录</h3> </div>
<div class="dir-container animate__animated animate__fadeInUp">
<div class="directory">
<el-card>
<h3 style=""><svg-icon name="dir" class="dir-icon"></svg-icon> </h3>
<div <div
v-for="anchor in directory" v-for="anchor in directory"
:key="anchor" :key="anchor"
:style="{ padding: `10px 0 10px ${anchor.indent * 20}px` }" :style="{ padding: `10px 0 10px ${(anchor.indent * 20) / 1.5 + 10}px` }"
@click="handleAnchorClick(anchor)" @click="handleAnchorClick(anchor)"
:class="{ active: currentAhchor === anchor }"
> >
<a style="cursor: pointer">{{ anchor.title }}</a> <a class="anchor">{{ anchor.title }}</a>
</div> </div>
</el-card> </el-card>
</el-col> </div>
</el-row> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
const blog = ` import { useRoute } from 'vue-router'
## 二级标题 import { getArticleById } from '@/api/article'
这是一篇测试文章~
这是一篇测试文章~
这是一篇测试文章~
这是一篇测试文章~
这是一篇测试文章~
### 三级标题
1. a
2. b
3. c
#### 四级标题
~~~js
console.log('这是一篇测试文章~')
~~~
## 实现目录功能
> v-md-editor可太好用了完美
::: tip
居然还有tip功能Amazing
:::
`
const article = ref({})
const route = useRoute()
const preview = ref() const preview = ref()
const directory = ref([]) const directory = ref([])
const currentAhchor = ref({}) // anchor
onMounted(() => { onMounted(async () => {
console.log(preview.value.$el) await getArticle(route.params.articleId) // await
const anchors = preview.value.$el.querySelectorAll('h1,h2,h3,h4,h5,h6')
const anchors = preview.value.$el.querySelectorAll('h1, h2, h3, h4, h5, h6')
console.log(preview.value)
const titles = Array.from(anchors).filter((title) => !!title.innerText.trim()) const titles = Array.from(anchors).filter((title) => !!title.innerText.trim())
if (!titles.length) { if (!titles.length) {
directory.value = [] directory.value = []
@ -74,12 +57,16 @@ onMounted(() => {
lineIndex: el.getAttribute('data-v-md-line'), lineIndex: el.getAttribute('data-v-md-line'),
indent: hTags.indexOf(el.tagName) indent: hTags.indexOf(el.tagName)
})) }))
console.log(directory.value)
}) })
const getArticle = async (id) => {
const { data } = await getArticleById(id)
article.value = data
}
const handleAnchorClick = (anchor) => { const handleAnchorClick = (anchor) => {
const { lineIndex } = anchor const { lineIndex } = anchor
currentAhchor.value = anchor
const heading = preview.value.$el.querySelector(`[data-v-md-line="${lineIndex}"]`) const heading = preview.value.$el.querySelector(`[data-v-md-line="${lineIndex}"]`)
@ -87,18 +74,56 @@ const handleAnchorClick = (anchor) => {
preview.value.scrollToTarget({ preview.value.scrollToTarget({
target: heading, target: heading,
scrollContainer: window, scrollContainer: window,
top: 60 top: 25
}) })
} }
console.log(heading.scrollTop)
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.article { .article-container {
margin: 20px 0; display: flex;
.article {
width: 75%;
margin-right: 20px;
}
.dir-container {
width: 25%;
.directory {
position: sticky;
top: 10px;
& h3 {
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #000;
.dir-icon {
vertical-align: -0.33em;
}
}
.anchor {
cursor: pointer;
}
.active {
background-color: #00c4b6;
transition: all 1s ease-in-out;
}
}
}
}
@media screen and (max-width: 768px) {
.article-container {
display: block;
.article {
width: 100%;
}
.dir-container {
// width: 100%;
display: none;
}
}
} }
.directory { .animate__fadeInDown {
position: sticky; --animate-duration: 1.7s;
top: 10px;
} }
</style> </style>

@ -1,16 +1,34 @@
<template> <template>
<Banner :bannerUrl="data.bannerUrl" /> <Banner />
<div class="m-content"> <div class="m-content">
<el-card shadow="hover">Categories</el-card> <el-card shadow="hover">
<div class="m-tc-container">
<h1 class="m-tc-title">分类 - {{ categoryList.length }}</h1>
<div class="m-tc-content">
<router-link
v-for="category in categoryList"
:key="category._id"
:style="{ 'font-size': Math.floor(Math.random() * 10) + 18 + 'px' }"
:to="'/about'"
>
{{ category.name }}
</router-link>
</div>
</div>
</el-card>
</div> </div>
</template> </template>
<script setup> <script setup>
import Banner from '@/components/Banner.vue' import Banner from '@/components/Banner.vue'
import { ref } from 'vue' import { ref, onMounted } from 'vue'
import { getCategoryList } from '../../api/category'
const data = ref({ const categoryList = ref([])
bannerUrl: 'https://typora-lyx.oss-cn-guangzhou.aliyuncs.com/typora/wallhaven-kxw9o1.png'
onMounted(async () => {
const { data } = await getCategoryList()
categoryList.value = data
}) })
</script> </script>

@ -1,27 +1,278 @@
<!--
* @Author: liuyx 1517482303@qq.com
* @Date: 2022-11-10 08:03:12
* @LastEditTime: 2022-12-19 07:44:43
* @Description: 主页
-->
<template> <template>
<div class="home-banner animate__animated animate__fadeIn"></div> <div
<div class="m-content"> class="home-banner animate__animated animate__fadeIn animate__slow"
<el-row :gutter="20"> :style="{ background: 'url(' + bannerUrl + ') center center / cover no-repeat' }"
<el-col :span="18"> >
<BlogList /> <h1 class="site-name">{{ siteName }}</h1>
</el-col> </div>
<el-col :span="6" <div class="home-content">
><div class="grid-content ep-bg-purple" /> <div class="article-list">
<UserInfo /> <el-card
</el-col> class="card-box animate__animated animate__zoomIn"
</el-row> v-for="item in blogList"
:key="item"
>
<div class="article-item">
<!-- 文章图片 -->
<div class="cover-container">
<router-link :to="'/articles/' + item._id">
<img :src="item.cover" alt="" class="cover" />
</router-link>
</div>
<!-- 文章标题和简述 -->
<div class="article-content">
<router-link :to="'/articles/' + item._id">
<div class="title">{{ item.title }}</div>
</router-link>
<div class="article-info">
<span><svg-icon name="calendar" class="icon"></svg-icon>{{ item.createTime }}</span>
<span class="separator">|</span>
<span><svg-icon name="category" class="icon"></svg-icon>{{ item.category }}</span>
<span class="separator">|</span>
<span v-for="tag in item.tagList" :key="tag._id"
><svg-icon name="tag" class="icon"></svg-icon>{{ tag.name }}</span
>
</div>
<div class="description">{{ item.content }}</div>
</div>
</div>
</el-card>
</div>
<div class="site-info">
<div class="info-container">
<el-card class="animate__animated animate__zoomIn">
<!-- 头像 -->
<div class="avatar">
<el-avatar :size="100" :src="siteInfo.avatar" />
</div>
<!-- 名称 -->
<h2>{{ siteInfo.author }}</h2>
<!-- 简述 -->
<p>{{ siteInfo.intro }}</p>
<!-- 分类统计 -->
<div class="classification">
<div class="class-item">
<router-link to="/tags">
<div>标签</div>
<div class="class-item-nums">{{ tagNum }}</div>
</router-link>
</div>
<div class="class-item">
<router-link to="/categories">
<div>分类</div>
<div class="class-item-nums">{{ categoryNum }}</div>
</router-link>
</div>
<div class="class-item">
<router-link to="/archives">
<div>归档</div>
<div class="class-item-nums">{{ archiveNum }}</div>
</router-link>
</div>
</div>
<!-- 一些图标 -->
<div class="icons">
<a :href="siteInfo.github"><svg-icon name="github"></svg-icon></a>&nbsp;
<a :href="siteInfo.gitee"><svg-icon name="gitee"></svg-icon></a>
</div>
</el-card>
<el-card class="notice animate__animated animate__zoomIn">
<h3 style="margin-bottom: 10px"><svg-icon name="notice" /> 公告</h3>
{{ siteInfo.notice }}
</el-card>
</div>
</div>
</div> </div>
</template> </template>
<script setup> <script setup>
import BlogList from '../../components/BlogList.vue' import { ref, onMounted } from 'vue'
import UserInfo from '../../components/UserInfo.vue' import { getSiteInfo } from '../../api/site'
import { getArticleList } from '../../api/article'
import { getPageByName } from '@/api/page.js'
const siteName = ref('')
const blogList = ref([])
const siteInfo = ref({})
const tagNum = ref(0)
const categoryNum = ref(0)
const archiveNum = ref(0)
const bannerUrl = ref('')
onMounted(async () => {
const { data } = await getSiteInfo()
siteName.value = data.siteName
bannerUrl.value = (await getPageByName('首页')).data.bannerUrl
getBlogList()
getInfo()
})
const getBlogList = async () => {
const { data } = await getArticleList()
blogList.value = data.articleList
console.log(data)
}
const getInfo = async () => {
const { data } = await getSiteInfo()
console.log(data)
siteInfo.value = data
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.home-banner { .home-banner {
background: url('https://typora-lyx.oss-cn-guangzhou.aliyuncs.com/typora/wallhaven-x6l5vl.jpg') // background: url('http://cdn.liuyx.cc/wallhaven-m3dm1k.png') center center / cover no-repeat;
center center / cover no-repeat;
height: 100vh; height: 100vh;
position: relative;
display: flex;
justify-content: center;
align-items: center;
.site-name {
position: absolute;
top: 35%;
color: #eee;
letter-spacing: 5px;
}
}
.home-content {
display: flex;
margin: 20px auto;
}
@media screen and (min-width: 960px) {
.home-content {
width: 80%;
.article-list {
width: 75%;
padding-right: 10px;
}
.site-info {
width: 25%;
}
}
}
@media screen and (max-width: 768px) {
.home-content {
width: 100%;
display: block;
padding: 10px;
box-sizing: border-box;
}
}
.card-box {
margin-top: 10px;
}
.article-item {
display: flex;
height: 256px;
// justify-content: center;
align-items: center;
.cover-container {
overflow: hidden;
width: 70%;
height: 100%;
}
.cover {
width: 100%;
height: 100%;
box-sizing: border-box;
border-top-left-radius: 11px;
border-bottom-left-radius: 11px;
transform: scale(1);
transition: transform 1s ease 0s;
overflow: hidden;
}
&:hover .cover {
transform: scale(1.1);
}
.article-content {
padding: 0 40px;
width: 100%;
box-sizing: border-box;
.title {
font-size: 1.35em;
&:hover {
color: #8e8cd8;
}
}
.article-info {
font-size: 0.85em;
margin: 0.85em 0;
}
.separator {
margin: 0 8px;
font-weight: bold;
font-size: 16px;
}
.icon {
vertical-align: -0.33em;
font-size: 12px;
margin-right: 5px;
}
.description {
margin-top: 15px;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
@media screen and (max-width: 768px) {
.article-item {
display: block;
height: inherit;
.cover-container {
width: 100vw;
.cover {
border-radius: 11px 11px 0 0 !important;
}
}
.article-content {
height: 202px;
padding: 20px 30px;
.description {
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
.info-container {
padding: 10px;
text-align: center;
position: sticky;
top: 10px;
.avatar {
}
.classification {
display: flex;
padding: 20px 10px;
box-sizing: border-box;
.class-item {
width: 33.3%;
.class-item-nums {
line-height: 40px;
height: 40px;
}
}
}
.icons {
margin-top: 10px;
}
.notice {
text-align: left;
}
} }
</style> </style>

@ -1,16 +1,34 @@
<template> <template>
<Banner :bannerUrl="data.bannerUrl" /> <Banner />
<div class="m-content"> <div class="m-content">
<el-card shadow="hover">Tags</el-card> <el-card>
<div class="m-tc-container">
<h1 class="m-tc-title">标签 - {{ tagList.length }}</h1>
<div class="m-tc-content">
<router-link
v-for="tag in tagList"
:key="tag._id"
:style="{ 'font-size': Math.floor(Math.random() * 10) + 18 + 'px' }"
:to="'/about'"
>
{{ tag.name }}
</router-link>
</div>
</div>
</el-card>
</div> </div>
</template> </template>
<script setup> <script setup>
import Banner from '@/components/Banner.vue' import Banner from '@/components/Banner.vue'
import { ref } from 'vue' import { ref, onMounted } from 'vue'
import { getTagList } from '../../api/tag'
const data = ref({ const tagList = ref([])
bannerUrl: 'https://typora-lyx.oss-cn-guangzhou.aliyuncs.com/typora/wallhaven-kxw3p1.jpg'
onMounted(async () => {
const { data } = await getTagList()
tagList.value = data
}) })
</script> </script>

Loading…
Cancel
Save