mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
196 lines
4.4 KiB
Vue
196 lines
4.4 KiB
Vue
<script lang="ts" setup>
|
|
import DropdownTransition from '@theme-plume/DropdownTransition.vue'
|
|
import PostItem from '@theme-plume/PostItem.vue'
|
|
import { usePageFrontmatter } from '@vuepress/client'
|
|
import type { PropType } from 'vue'
|
|
import { nextTick, onMounted, toRefs, watch } from 'vue'
|
|
import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router'
|
|
import type { PlumeThemeHomeFrontmatter } from '../../shared/index.js'
|
|
import type { PostListData } from '../composables/index.js'
|
|
import { usePostList } from '../composables/index.js'
|
|
import { scrollTo } from '../utils/index.js'
|
|
import Pagination from './Pagination.vue'
|
|
|
|
const props = defineProps({
|
|
postList: {
|
|
type: Array as PropType<PostListData | undefined>,
|
|
required: false,
|
|
default: () => undefined,
|
|
},
|
|
})
|
|
const router = useRouter()
|
|
const frontmatter = usePageFrontmatter<PlumeThemeHomeFrontmatter>()
|
|
|
|
const propsRef = toRefs(props)
|
|
const { postList, total, page, setPostListPage, resetPostIndex } = usePostList()
|
|
|
|
watch(
|
|
[propsRef.postList],
|
|
([newPostList]) => {
|
|
newPostList && resetPostIndex(newPostList as unknown as PostListData)
|
|
},
|
|
{ immediate: true }
|
|
)
|
|
|
|
const route = useRoute()
|
|
let offsetHeight = 0
|
|
onBeforeRouteUpdate((to, from) => {
|
|
if (__VUEPRESS_SSR__) return
|
|
if (to.fullPath === from.fullPath) return
|
|
setPostListPage((to.query.p as unknown as number) || 1)
|
|
const { home, banner, mobileBanner } = frontmatter.value
|
|
let top = 0
|
|
if (home && (banner || mobileBanner)) {
|
|
offsetHeight =
|
|
offsetHeight ||
|
|
document.querySelector<HTMLElement>('.navbar-wrapper')?.offsetHeight ||
|
|
0
|
|
top = document.documentElement.clientHeight - offsetHeight
|
|
}
|
|
setTimeout(() => scrollTo(document, top), 0)
|
|
})
|
|
|
|
onMounted(async () => {
|
|
if (__VUEPRESS_SSR__) return
|
|
await nextTick()
|
|
setPostListPage((route.query.p as unknown as number) || 1)
|
|
})
|
|
const togglePage = (currentPage: number): void => {
|
|
router.push({
|
|
path: route.path,
|
|
query: {
|
|
...route.query,
|
|
p: currentPage,
|
|
},
|
|
})
|
|
}
|
|
</script>
|
|
<template>
|
|
<div class="post-list-wrapper">
|
|
<DropdownTransition>
|
|
<div>
|
|
<PostItem
|
|
v-for="(post, index) in postList"
|
|
:key="post.path"
|
|
:post="post"
|
|
:index="index"
|
|
></PostItem>
|
|
</div>
|
|
</DropdownTransition>
|
|
<Pagination :page="page" :total="total" @toggle-page="togglePage" />
|
|
</div>
|
|
</template>
|
|
<style lang="scss">
|
|
@import '../styles/_variables';
|
|
.post-list-wrapper {
|
|
flex: 1;
|
|
padding-top: 2rem;
|
|
|
|
.post-list-item {
|
|
> div {
|
|
position: relative;
|
|
padding: 1.25rem 1.5rem;
|
|
background-color: var(--c-bg-container);
|
|
border-radius: var(--p-around);
|
|
margin-bottom: 2.25rem;
|
|
// box-shadow: var(--shadow);
|
|
transition: box-shadow var(--t-color);
|
|
overflow: hidden;
|
|
|
|
&.sticky {
|
|
background-color: var(--c-bg-sticky);
|
|
}
|
|
|
|
// &:hover {
|
|
// box-shadow: var(--shadow-lg);
|
|
// }
|
|
}
|
|
|
|
.top-icon {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 2.65rem;
|
|
height: 2.65rem;
|
|
color: var(--c-brand);
|
|
}
|
|
}
|
|
|
|
.post-banner {
|
|
position: relative;
|
|
height: 18.75rem;
|
|
margin: -1.25rem -1.5rem 1.25rem -1.5rem;
|
|
overflow: hidden;
|
|
cursor: pointer;
|
|
|
|
> div {
|
|
width: 100%;
|
|
height: 100%;
|
|
background-position: center;
|
|
background-size: cover;
|
|
background-repeat: no-repeat;
|
|
transform: scale(100%);
|
|
transition: transform var(--t-transform);
|
|
|
|
&:hover {
|
|
transform: scale(120%);
|
|
}
|
|
}
|
|
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 1.5rem;
|
|
width: 0;
|
|
height: 0;
|
|
border: solid 1.25rem;
|
|
border-color: transparent transparent var(--c-bg-container) transparent;
|
|
z-index: 1;
|
|
}
|
|
}
|
|
|
|
h3 {
|
|
width: 100%;
|
|
margin-top: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
|
|
a {
|
|
color: var(--c-text);
|
|
}
|
|
}
|
|
|
|
.post-excerpt {
|
|
padding-top: 1.25rem;
|
|
|
|
:first-child {
|
|
margin-top: 0;
|
|
}
|
|
:last-child {
|
|
margin-bottom: 1rem;
|
|
}
|
|
}
|
|
|
|
.post-more {
|
|
text-align: right;
|
|
|
|
a {
|
|
display: inline-block;
|
|
padding: 0.5rem 0.75rem;
|
|
border-radius: var(--p-around);
|
|
background-color: var(--c-bg);
|
|
color: var(--c-brand);
|
|
}
|
|
}
|
|
}
|
|
|
|
@media (max-width: $MQMobile) {
|
|
.post-list-wrapper {
|
|
.post-list-item {
|
|
border-radius: 0;
|
|
}
|
|
}
|
|
}
|
|
</style>
|