139 lines
6.5 KiB
Vue
139 lines
6.5 KiB
Vue
<script lang="ts" setup>
|
|
import {computed, onMounted, ref} from "vue";
|
|
import ArticleCard from "@/components/card/ArticleCard.vue";
|
|
import {getBlogRecentPost} from "@/api/blog.ts";
|
|
import NavBar from "@/components/nav/NavBar.vue";
|
|
import IntroCard from "@/components/card/IntroCard.vue";
|
|
import CardTitle from "@/components/card/CardTitle.vue";
|
|
import SectionCard from "@/components/card/SectionCard.vue";
|
|
import {getActivity} from "@/api/git.ts";
|
|
import GitCard from "@/components/card/GitCard.vue";
|
|
import emitter from "@/utils/mitt.ts";
|
|
import {getAssetURL} from "@/utils/function.ts";
|
|
|
|
const recentPosts = ref<IPost[] | null>(null);
|
|
const recentActivities = ref<IActivity[] | null>(null);
|
|
const isLoading = ref({
|
|
blog: true,
|
|
git: true
|
|
});
|
|
const isError = ref({
|
|
blog: false,
|
|
git: false
|
|
});
|
|
|
|
const hasPosts = computed(() => (recentPosts.value ?? []).length > 0);
|
|
const hasActivities = computed(() => (recentActivities.value ?? []).length > 0);
|
|
const postsData = computed(() => {
|
|
if (!recentPosts.value) return [];
|
|
if (recentPosts.value.length > 4)
|
|
return recentPosts.value.slice(0, 4)
|
|
return recentPosts.value
|
|
})
|
|
const activitiesData = computed((): IActivity<IContent>[] => {
|
|
if (!recentActivities.value) return [];
|
|
return recentActivities.value.map(item => {
|
|
try {
|
|
return {
|
|
...item,
|
|
content: JSON.parse(item.content)
|
|
}
|
|
} catch (e) {
|
|
return null
|
|
}
|
|
}).filter(item => item !== null)
|
|
})
|
|
|
|
|
|
const reloadPosts = async () => {
|
|
try {
|
|
isLoading.value.blog = true
|
|
const postData = await getBlogRecentPost();
|
|
recentPosts.value = postData.data.dataSet
|
|
isLoading.value.blog = false
|
|
} catch (e) {
|
|
isLoading.value.blog = false
|
|
isError.value.blog = true
|
|
}
|
|
}
|
|
|
|
const reloadActivities = async () => {
|
|
try {
|
|
isLoading.value.git = true
|
|
recentActivities.value = await getActivity()
|
|
isLoading.value.git = false
|
|
} catch (e) {
|
|
isLoading.value.git = false
|
|
isError.value.git = true
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
await reloadPosts()
|
|
await reloadActivities()
|
|
|
|
emitter.emit('startLoading', false)
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<nav-bar/>
|
|
|
|
<div class="container mx-auto xl:max-w-screen-xl">
|
|
<!-- 个人介绍 -->
|
|
<intro-card/>
|
|
|
|
<!-- 博客部分 -->
|
|
<section class="w-full px-4 sm:px-0">
|
|
<!-- 标题部分 -->
|
|
<card-title :icon="['fas', 'blog']" main-color="bg-rose-500" sub-color="bg-rose-600" title="最新博文"
|
|
url="/blog/"/>
|
|
|
|
<section-card :empty="!hasPosts" :error="isError.blog" :loading="isLoading.blog" @reload="reloadPosts">
|
|
<template v-slot:default>
|
|
<div class="grid w-full grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
|
<article-card v-for="item in postsData" :key="item.cid" :post="item"/>
|
|
</div>
|
|
</template>
|
|
</section-card>
|
|
</section>
|
|
|
|
<!-- Git部分 -->
|
|
<section class="my-4 w-full px-4 sm:px-0">
|
|
<card-title :icon="['fas', 'code']" main-color="bg-green-500" sub-color="bg-green-600" title="最近活动"
|
|
url="/git/"/>
|
|
|
|
<section-card :empty="!hasActivities" :error="isError.git" :loading="isLoading.git" @reload="reloadActivities">
|
|
<template v-slot:default>
|
|
<div class="grid w-full grid-cols-1 gap-4 lg:grid-cols-2">
|
|
<git-card v-for="item in activitiesData" :key="item.id" :commit="item"/>
|
|
</div>
|
|
</template>
|
|
</section-card>
|
|
</section>
|
|
</div>
|
|
|
|
|
|
<footer class="mt-8 flex w-full items-end bg-gradient-to-t from-white py-4 min-h-48">
|
|
<div class="container mx-auto">
|
|
<p class="text-center leading-8">©2024 All rights reserved.</p>
|
|
<!-- <a class="flex items-center justify-center" href="https://www.upyun.com/?utm_source=lianmeng&utm_medium=referral">-->
|
|
<!-- 本网站由<img :src="getAssetURL('upyun.png')" alt="又拍云" class="h-8 w-auto">提供CDN加速/云储存服务-->
|
|
<!-- </a>-->
|
|
<div class="flex justify-center gap-4">
|
|
<a href="https://beian.miit.gov.cn/" target="_blank">
|
|
<img alt="苏ICP备2022016243号-1"
|
|
src="https://img.shields.io/badge/%E8%8B%8FICP%E5%A4%87-2022016243%E5%8F%B7--1-green?style=for-the-badge">
|
|
</a>
|
|
<a href="https://beian.mps.gov.cn/#/query/webSearch?code=32050602011641" rel="noreferrer" target="_blank">
|
|
<img alt="苏公网安备32050602011641"
|
|
src="https://img.shields.io/badge/%E8%8B%8F%E5%85%AC%E7%BD%91%E5%AE%89%E5%A4%87-32050602011641-blue?style=for-the-badge&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACQAAAAoCAYAAACWwljjAAAFQklEQVRYw%2B3Wa1BUdRjH8SOpMeg4WhZGpDIxiaaTeUFgWrxE4AVRQJGlRRAVIV1JkbgMgQLi5AVBQSVLSp0xlEAUKBEEFZCrCstll8UV2AV2YbmoGCrYv31%2BR95UL5pmmtamZ%2Bbz6rz5nvOc%2F5zDcX9jGLs%2FiTxuyvIlWYkRFeTHA2HVRFtzfhthTG5KuH96%2FvUgNlC4mMgyw1NJit%2FaAXLKazYje9xtIMZ%2FOZz50gW%2B9hcNkvoLEemEPbnrSP47QYwxQ5Ifv54RqzcXwFFvSyjaOhfavN8F7Y5ZcC%2FHH9JOB4LNa9Zw5YA76OZV8vIGMdZtSp7cDrtOnOavYiQhTAiPwi1AMtIQaqyngsxpBtw2GAGDKfaQmpUAa6xc4Vfp4UtEdzAMycsT9JQ1Tyctl%2F2eEkuTlYysF%2FrCUNxMqDEzgTqzSXBnpgnIHCzgjvEEuD52DLBr3rA1MAaWmNtB582wdtIljZ9G9D%2BIPU6aTxIPBjHCcXvg3CEh9K2fDLWvjIH6D6fwTIyheuwEqLUyhzLOALq8pkN%2BbgRw3HY4FBsMzxojZxP9DequLjAlQwVrbpIjhyIY4UYGQ%2FbuhdBqPxlk3Gion2IMDQIz3kJe%2FZS34I7uHkmD7VSQVgYDNyIAwsNCgfXGXoOBPjP9DKrOCAogA2etGTmTHAMcFwFZye7wS5QlVHGjoEw4A2qPCUBZ6AzNcQ5Q%2FYYRdO%2BYB1U3dsDwypLio4FJ3ECryIzWz6Cm3NgTRHN8HiPF6eHAGSbAdh8feFZkB7krzaHE9h2o85sDsiAbkIsXQMN%2Be2CtGyF0kzdwXCgU5%2B%2BD%2FouLQFV4OEU%2Fg2Q%2FiNuIPNaKkQflAWBqexxGjhLDVUcL6IwSQN3SGVChe6FJg9dckCx6D1QBliDZLIAxo7eA8eyv4KE0BJqTrHkZvnL9DJKn%2BTwmt0NsGGHZy2Dn3kQYfsQ53Hh4%2Fr4RNGz8AIpdzKEuaAF0RC2E57MmQgE3ATjuM%2FCPiANW7AqSfQJQ5vk362eQKmd3JrmXsoSRocpNIMnbB9zbceDIWUPmuHFQNMkISqa9DpUvNK6YDpW2s8DfwBK48WFQnhMCgzUBoLy0BrRVe5P0NWjPLdKUsJiR1tR1wGp8IeZwMgx%2FSrgRvjxuAziNcwLvyathLOcJHLflhRDYGRYFrNET2rJ5yvPLoas0tOj%2FoL8UpC4JHyTSU%2B6MNCS4gvKoAB5WiKG%2BMAQSg0WwLXQ%2FZJ3xhao0FxB5hYCbUwAEfhEF3Td8QP2dAOQnPwFlxgrolUVq9TPoaX%2BZB2nLc2Gk6awj1MU78HZZwJMid2Byb550JQwVO0NfxlJgdz14vWKeRAiK6DlQF28PLZdcoLNcBIO92bb6GTQ8Q%2F13RURT6tlH2gvXMlITLYD6uI%2Bgp2ozdF0VQXumM6ivCqGvahM8kPiDItkeGo8tB025GFQ3xFrSr06zI3%2F4yde7oN7m0sWk5eKWDqK5JWJQvAHac9ygq3Adr9gTNNc3QG85rzPfHe5%2F7wDtPwuhp%2FZz6CjyhaZzwi6ivfetHdH%2FoP77%2B3PJQOsuRnqkQdCa4wWqyx6gyecpL64GTaEX7ycXUJz4GJp1B4O0X%2FHg0Xp1tFV%2B8Ei1k6c5coHofxBrrzQinbKYo0SVJ%2Bwn6iurGHlY5gY911aDJnMFaHXXiDp9GQyvtKfUA9QFTtBZ7gPdit0tpFd9OpwwFmlA9D%2Fo9yNLDpxIKmI8PMnNSNtviCLVpYTITzrXEGWaq4qos0WgOPdpCenIF%2BeRrurjB4k0PXopYZG6gMg%2FD%2FgNBUxhAbSAmKMAAAAASUVORK5CYII%3D">
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</template>
|
|
|
|
<style scoped>
|
|
|
|
</style> |