添加最近活动

This commit is contained in:
Jeffrey Hsu 2024-10-02 19:45:57 +08:00
parent 186086c0bd
commit c0a7097fd2
8 changed files with 152 additions and 20 deletions

View File

@ -2,12 +2,15 @@ import {request} from "@/utils/network.ts";
const TOKEN = "fb8aec429ea7d0a36f7238dbffda9d2d66c7b045" const TOKEN = "fb8aec429ea7d0a36f7238dbffda9d2d66c7b045"
export async function getActivity() { export async function getActivity(): Promise<IActivity[]> {
return request({ return request({
url: '/git/api/v1/users/cantyonion/activities/feeds', url: '/git/api/v1/users/cantyonion/activities/feeds',
method: 'get', method: 'get',
headers: { headers: {
Authorization: ` ${TOKEN}` Authorization: ` ${TOKEN}`,
},
params: {
limit: 4
} }
}) })
} }

View File

@ -10,7 +10,7 @@ defineProps<{
<template> <template>
<div class="mb-4 flex justify-between text-2xl font-bold text-white"> <div class="mb-4 flex justify-between text-2xl font-bold text-white">
<div :class="mainColor" class="flex w-max items-center justify-center overflow-hidden rounded-2xl bg-rose-500"> <div :class="[mainColor]" class="flex w-max items-center justify-center overflow-hidden rounded-2xl">
<div :class="[subColor]" class="flex h-full w-14 items-center justify-center rounded-2xl px-4 py-2 text-center"> <div :class="[subColor]" class="flex h-full w-14 items-center justify-center rounded-2xl px-4 py-2 text-center">
<font-awesome-icon :icon="icon"/> <font-awesome-icon :icon="icon"/>
</div> </div>

View File

@ -0,0 +1,76 @@
<script lang="ts" setup>
import {FontAwesomeIcon} from "@fortawesome/vue-fontawesome";
import {computed} from "vue";
const props = defineProps<{
commit: IActivity<IContent>
}>()
const icon = computed(() => {
switch (props.commit.op_type) {
case "merge_pull_request":
return ['fas', 'code-merge']
case "create_repo":
return ['fab', 'git-alt']
case "commit_repo":
default:
return ['fas', 'code-commit']
}
})
const time = computed(() => timeDifference(props.commit.created))
const timeDifference = (dateString: string): string => {
const targetDate = new Date(dateString);
const currentDate = new Date();
const diffInMillis = currentDate.getTime() - targetDate.getTime();
const minutes = Math.floor(diffInMillis / (1000 * 60));
const hours = Math.floor(diffInMillis / (1000 * 60 * 60));
const days = Math.floor(diffInMillis / (1000 * 60 * 60 * 24));
const months = Math.floor(diffInMillis / (1000 * 60 * 60 * 24 * 30));
const years = Math.floor(diffInMillis / (1000 * 60 * 60 * 24 * 365));
if (minutes < 60) {
return `${minutes} 分钟前`;
} else if (hours < 24) {
return `${hours} 小时前`;
} else if (days < 30) {
return `${days} 天前`;
} else if (months < 12) {
return `${months} 个月前`;
} else {
return `${years} 年前`;
}
}
</script>
<template>
<div class="container relative flex h-36 w-full overflow-hidden rounded-2xl hover:shadow-md transition-all">
<!-- 提交图标 -->
<div class="flex h-36 w-36 items-center justify-center bg-pink-300 text-5xl text-white">
<font-awesome-icon :icon="icon"/>
</div>
<!-- 内容 -->
<div class="flex-1 bg-white p-4 overflow-hidden">
<div class="text-2xl font-bold mr-12 truncate">
仓库{{ commit.repo.name }}
</div>
<span class="text-xl">{{ commit.content.HeadCommit.Message }}</span>
<span class="absolute top-0 right-0 m-4 bg-gray-300 px-2 rounded hidden sm:block">
{{ commit.content.HeadCommit.Sha1.slice(0, 10) }}
</span>
<span class="absolute bottom-0 right-0 m-4 bg-gray-300 px-2 rounded">
<font-awesome-icon :icon="['far', 'clock']" class="mr-1 text-sm"/>
{{ time }}
</span>
</div>
</div>
</template>
<style scoped>
</style>

View File

@ -22,7 +22,7 @@ const handleReload = () => {
</div> </div>
</slot> </slot>
</div> </div>
<div v-else> <div v-else class="w-full">
<!-- 错误处理 --> <!-- 错误处理 -->
<div v-if="error" class="flex h-56 flex-col items-center justify-center" @click="handleReload"> <div v-if="error" class="flex h-56 flex-col items-center justify-center" @click="handleReload">
<span class="mb-4 text-8xl"></span> <span class="mb-4 text-8xl"></span>

View File

@ -15,11 +15,11 @@ import {
faChevronRight, faChevronRight,
faCodeCommit faCodeCommit
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import {faWeibo, faQq, faGithubAlt, faSteamSymbol} from '@fortawesome/free-brands-svg-icons' import {faWeibo, faQq, faGithubAlt, faSteamSymbol, faGitAlt} from '@fortawesome/free-brands-svg-icons'
library.add( library.add(
faClock, faXmark, faBlog, faGauge, faCodeBranch, faCloud, faWeibo, faQq, faGithubAlt, faSteamSymbol, faChevronRight, faClock, faXmark, faBlog, faGauge, faCodeBranch, faCloud, faWeibo, faQq, faGithubAlt, faSteamSymbol, faChevronRight,
faCodeCommit faCodeCommit, faGitAlt
) )
createApp(App).use(router).component('font-awesome-icon', FontAwesomeIcon).mount('#app') createApp(App).use(router).component('font-awesome-icon', FontAwesomeIcon).mount('#app')

27
src/types/git.d.ts vendored Normal file
View File

@ -0,0 +1,27 @@
declare interface IActivity<T = string> {
id: string;
content: T
op_type: string
repo: {
name: string
html_url: string
}
created: string
}
declare interface IContent {
Commits: ICommit[]
HeadCommit: ICommit
CompareURL: string
Len: number
}
declare interface ICommit {
Sha1: string,
Message: string,
AuthorEmail: string,
AuthorName: string,
CommitterEmail: string,
CommitterName: string,
Timestamp: string
}

View File

@ -6,8 +6,11 @@ import NavBar from "@/components/nav/NavBar.vue";
import IntroCard from "@/components/card/IntroCard.vue"; import IntroCard from "@/components/card/IntroCard.vue";
import CardTitle from "@/components/card/CardTitle.vue"; import CardTitle from "@/components/card/CardTitle.vue";
import SectionCard from "@/components/card/SectionCard.vue"; import SectionCard from "@/components/card/SectionCard.vue";
import {getActivity} from "@/api/git.ts";
import GitCard from "@/components/card/GitCard.vue";
const recentPosts = ref<IPost[] | null>(null); const recentPosts = ref<IPost[] | null>(null);
const recentActivities = ref<IActivity[] | null>(null);
const isLoading = ref({ const isLoading = ref({
blog: true, blog: true,
git: true git: true
@ -18,12 +21,21 @@ const isError = ref({
}); });
const hasPosts = computed(() => (recentPosts.value ?? []).length > 0); const hasPosts = computed(() => (recentPosts.value ?? []).length > 0);
const hasActivities = computed(() => (recentActivities.value ?? []).length > 0);
const postsData = computed(() => { const postsData = computed(() => {
if (!recentPosts.value) return []; if (!recentPosts.value) return [];
if (recentPosts.value.length > 4) if (recentPosts.value.length > 4)
return recentPosts.value.slice(0, 4) return recentPosts.value.slice(0, 4)
return recentPosts.value return recentPosts.value
}) })
const activitiesData = computed((): IActivity<IContent>[] => {
if (!recentActivities.value) return [];
return recentActivities.value.map(obj => ({
...obj,
content: JSON.parse(obj.content)
}))
})
const reloadPosts = async () => { const reloadPosts = async () => {
try { try {
@ -37,15 +49,21 @@ const reloadPosts = async () => {
} }
} }
onMounted(async () => { const reloadActivities = async () => {
try { try {
const postData = await getBlogRecentPost(); isLoading.value.git = true
recentPosts.value = postData.data.dataSet recentActivities.value = await getActivity()
isLoading.value.blog = false console.log(recentActivities.value)
isLoading.value.git = false
} catch (e) { } catch (e) {
isLoading.value.blog = false isLoading.value.git = false
isError.value.blog = true isError.value.git = true
} }
}
onMounted(async () => {
await reloadPosts()
await reloadActivities()
}) })
</script> </script>
@ -75,6 +93,14 @@ onMounted(async () => {
<section class="my-4 w-full px-4 sm:px-0"> <section class="my-4 w-full px-4 sm:px-0">
<card-title :icon="['fas', 'code-commit']" main-color="bg-green-500" sub-color="bg-green-600" title="最近活动" <card-title :icon="['fas', 'code-commit']" main-color="bg-green-500" sub-color="bg-green-600" title="最近活动"
url="/git/"/> 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> </section>
</div> </div>