Skip to content

Commit

Permalink
update nav
Browse files Browse the repository at this point in the history
  • Loading branch information
gusibi committed Oct 5, 2024
1 parent f2deeb4 commit ef2a334
Show file tree
Hide file tree
Showing 17 changed files with 209 additions and 58 deletions.
4 changes: 2 additions & 2 deletions components/CommentBox.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="mb-4 border border-gray-200 dark:border-gray-700 rounded-md">
<div class="mb-4 rounded-lg border border-gray-200 dark:border-gray-700 ">
<div v-if="user" class="p-3">
<div class="flex items-start space-x-3">
<img :src="user.user_metadata.avatar_url" :alt="user.user_metadata.full_name" class="w-8 h-8 rounded-full">
Expand All @@ -13,7 +13,7 @@
</div>
<div v-else class="p-3 bg-gray-50 dark:bg-gray-800 text-center">
<p class="text-gray-600 dark:text-gray-400 mb-2 text-sm">Sign in to comment</p>
<button @click="login" class="px-4 py-2 bg-gray-800 hover:bg-gray-900 focus:ring-4 focus:ring-gray-300 text-white font-medium rounded-md text-sm transition duration-300 ease-in-out"> Sign in </button>
<button @click="login" class="px-4 py-2 bg-gray-800 hover:bg-gray-900 focus:ring-4 focus:ring-gray-300 text-white font-medium rounded-md text-sm transition duration-300 ease-in-out"> Sign in With Github </button>
</div>
</div>
</template>
Expand Down
2 changes: 1 addition & 1 deletion components/Pagination.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6">
<div class="bg-card-light dark:bg-card-dark rounded-lg shadow-xl overflow-hidden flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 mt-6 sm:px-6">
<div class="flex flex-1 justify-between sm:hidden">
<a href="#" @click.prevent="onPageChange(currentPage - 1)" :class="[currentPage === 1 ? 'cursor-not-allowed opacity-50' : 'hover:bg-gray-50', 'relative inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700']" :aria-disabled="currentPage === 1"> Previous </a>
<a href="#" @click.prevent="onPageChange(currentPage + 1)" :class="[currentPage === totalPages ? 'cursor-not-allowed opacity-50' : 'hover:bg-gray-50', 'relative ml-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700']" :aria-disabled="currentPage === totalPages"> Next </a>
Expand Down
2 changes: 1 addition & 1 deletion components/RepoTimeline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<h1 v-if="!isMemePost(post.labels)" class="text-xl font-medium">
<NuxtLink :to="`${post.html_url}`" class="hover:underline">{{ post.title }}</NuxtLink>
</h1>
<div class="prose dark:prose-invert max-w-none" v-html="$md(truncatedBody(post.body))" />
<div class="pt-4 prose dark:prose-invert max-w-none" v-html="$md(truncatedBody(post.body))" />
</div>
<!-- 底部信息栏 -->
<div class="pb-6 pt-3 flex justify-between items-center text-sm">
Expand Down
30 changes: 27 additions & 3 deletions composables/useBannerContent.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
import { ref } from 'vue'
import { ref, provide, inject } from 'vue'

export const useBannerContent = () => {
const bannerContentSymbol = Symbol('bannerContent')

export function useBannerContent() {
const bannerContent = ref('')
const bannerImageUrl = ref('/banner2.jpeg') // 默认背景图

const setBannerContent = (content: string) => {
bannerContent.value = content
}

const setBannerImage = (url: string) => {
bannerImageUrl.value = url
}

provide(bannerContentSymbol, {
bannerContent,
bannerImageUrl,
setBannerContent,
setBannerImage
})

return {
bannerContent,
setBannerContent
bannerImageUrl,
setBannerContent,
setBannerImage
}
}

export function useBannerContentInjection() {
const bannerContext = inject(bannerContentSymbol)
if (!bannerContext) {
throw new Error('useBannerContentInjection must be used within a component that has called useBannerContent')
}
return bannerContext
}
86 changes: 79 additions & 7 deletions layouts/default.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,80 @@
<template>
<div class="min-h-screen flex flex-col bg-background-light dark:bg-background-dark text-text-light dark:text-text-dark transition-colors duration-300">
<header class="bg-primary dark:bg-secondary">
<header class="fixed top-0 left-0 right-0 z-50 bg-primary dark:bg-secondary">
<nav class="max-w-content mx-auto px-4 py-2 flex justify-between items-center">
<div class="flex items-center cursor-pointer" @click="navigateToHome">
<img class="w-8 h-8 rounded-full mr-2" src="https://avatars.githubusercontent.com/u/1282277?v=4" alt="古思乱讲 Avatar" />
<div class="text-white dark:text-white text-xl font-bold">古思乱讲</div>
</div>
<button class="text-primary dark:text-white text-2xl" @click="toggleNightMode" aria-label="Toggle night mode">{{ nightModeIcon }}</button>
<div class="flex items-center space-x-4">
<div class="hidden md:flex items-center space-x-4">
<a href="/repo" class="text-white hover:text-gray-200 hover:scale-110 flex items-center">
<svg class="w-5 h-5 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9"></path>
</svg> Explore </a>
<a href="/api/rss.xml" class="text-white hover:text-gray-200 hover:scale-110 flex items-center">
<svg class="w-5 h-5 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 5c7.18 0 13 5.82 13 13M6 11a7 7 0 017 7m-6 0a1 1 0 11-2 0 1 1 0 012 0z"></path>
</svg> RSS </a>
<div class="relative group">
<button class="text-white hover:text-gray-200 hover:scale-110 flex items-center">
<svg class="w-5 h-5 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"></path>
</svg> 友情链接 <svg class="w-4 h-4 ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div class="absolute right-0 mt-2 w-48 bg-white bg-opacity-80 rounded-md shadow-lg opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-300 z-50">
<a href="https://blog.gusibi.mobi" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">古思乱想</a>
<a href="https://imageguardai.gusibi.mobi" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">ImageGuardAI</a>
<a href="https://watermark.gusibi.mobi" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">watermark</a>
</div>
</div>
</div>
<button class="text-white dark:text-white text-2xl" @click="toggleNightMode" aria-label="Toggle night mode">{{ nightModeIcon }}</button>
<button class="md:hidden text-white" @click="toggleMobileMenu">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16m-7 6h7"></path>
</svg>
</button>
</div>
</nav>
</header>
<!-- Mobile sidebar -->
<div v-if="mobileMenuOpen" class="fixed inset-0 z-50 bg-black bg-opacity-50" @click="toggleMobileMenu"></div>
<div :class="['fixed top-0 right-0 w-64 h-full bg-primary dark:bg-secondary bg-opacity-50 transform transition-transform duration-300 ease-in-out z-50', mobileMenuOpen ? 'translate-x-0' : 'translate-x-full']">
<div class="p-4">
<button class="text-white mb-4" @click="toggleMobileMenu">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
<a href="/api/rss.xml" class="block text-white py-2 flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 5c7.18 0 13 5.82 13 13M6 11a7 7 0 017 7m-6 0a1 1 0 11-2 0 1 1 0 012 0z"></path>
</svg> RSS </a>
<a href="/repo" class="block text-white py-2 flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9"></path>
</svg> Explore </a>
<div class="py-2">
<button class="text-white flex items-center" @click="toggleMobileFriendLinks">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"></path>
</svg> 友情链接 <svg class="w-4 h-4 ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div v-if="mobileFriendLinksOpen" class="ml-7 mt-2">
<a href="https://blog.gusibi.mobi" class="block text-white py-1">古思乱想</a>
<a href="https://imageguardai.gusibi.mobi" class="block text-white py-1">ImageGuardAI</a>
<a href="https://watermark.gusibi.mobi" class="block text-white py-1">watermark</a>
</div>
</div>
</div>
</div>
<div class="relative h-64 overflow-hidden">
<img class="w-full h-full object-cover" src="/banner2.jpeg" alt="Site Banner" />
<img class="w-full h-full object-cover blur-sm" :src="bannerImageUrl" alt="Site Banner" />
<div class="absolute inset-0 flex items-center justify-center dark:bg-black dark:bg-opacity-50">
<div v-html="bannerContent"></div>
</div>
Expand All @@ -22,9 +86,7 @@
<div class="max-w-content mx-auto px-4 text-center">
<div class="mb-2">
<a href="https://momo.gusibi.mobi" class="mr-4 hover:underline">本站地址</a>
<a href="/api/rss.xml" class="mr-4 hover:underline">RSS</a>
<a href="/sitemap.xml" class="mr-4 hover:underline">SiteMap</a>
<a href="/repo" class="mr-4 hover:underline">RepoList</a>
</div>
<div class="text-sm text-gray-500">Design by <a href="https://github.com/gusibi/path-meme-web">gusibi@path-meme</a></div>
</div>
Expand All @@ -42,9 +104,10 @@ import { ref, onMounted, useHead } from '#imports'
import { useRouter } from 'vue-router'
const router = useRouter()
const { bannerContent } = useBannerContent()
const { bannerContent, bannerImageUrl } = useBannerContent()
const nightModeIcon = ref('🌙')
const mobileMenuOpen = ref(false)
const mobileFriendLinksOpen = ref(false)
const floatingTimeLabel = ref<HTMLElement | null>(null)
const toggleNightMode = () => {
Expand All @@ -53,6 +116,15 @@ const toggleNightMode = () => {
localStorage.setItem('nightMode', document.documentElement.classList.contains('dark').toString())
}
const toggleMobileMenu = () => {
mobileMenuOpen.value = !mobileMenuOpen.value
}
const toggleMobileFriendLinks = () => {
mobileFriendLinksOpen.value = !mobileFriendLinksOpen.value
}
const navigateToHome = (event: Event) => {
event.preventDefault()
router.push('/')
Expand Down
5 changes: 2 additions & 3 deletions pages/blog/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,13 @@
<script setup lang="ts">
import { useAsyncData } from '#app'
import { useRoute } from 'vue-router'
import { useBannerContent } from '~/composables/useBannerContent'
import { useBannerContentInjection } from '~/composables/useBannerContent'
const { setBannerContent } = useBannerContentInjection()
import { useSupabaseUser } from '#imports'
const user = useSupabaseUser()
const route = useRoute()
const { setBannerContent } = useBannerContent()
const { data: postData } = await useAsyncData('post', () =>
$fetch(`/api/blog-posts/${route.params.id}`)
)
Expand Down
7 changes: 4 additions & 3 deletions pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { useBannerContent } from '~/composables/useBannerContent'
import { useBannerContentInjection } from '~/composables/useBannerContent'
const { setBannerContent, setBannerImage } = useBannerContentInjection()
const config = useRuntimeConfig()
const blogPosts = ref([])
const currentPage = ref(1)
const totalItems = ref(0)
const perPage = ref(parseInt(config.public.perPageSize) || 20)
const { setBannerContent } = useBannerContent()
const fetchBlogPosts = async (page = 1) => {
const { data: fetchedData } = await useAsyncData('blogPosts', () =>
Expand All @@ -37,5 +37,6 @@ const onPageChange = async (page: number) => {
await fetchBlogPosts(page)
}
// 设置 banner 内容
setBannerContent('<h1 class="text-4xl font-extrabold text-center text-white mb-6">Welcome to My Blog</h1>')
setBannerContent('<h1 class="text-4xl font-extrabold text-center text-white mb-6">古思乱讲</h1>')
setBannerImage('/banner2.jpeg')
</script>
27 changes: 22 additions & 5 deletions pages/repo/[repo_owner]/[repo_name]/blog/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<main class="container max-w-content mx-auto px-4 ">
<article v-if="post" class="bg-card-light dark:bg-card-dark rounded-lg shadow-xl overflow-hidden">
<div class="px-6 py-6">
<h1 class="text-3xl font-bold mb-4 text-gray-900 dark:text-white">{{ post.title }}</h1>
<!-- <h1 class="text-3xl font-bold mb-4 text-gray-900 dark:text-white">{{ post.title }}</h1> -->
<div class="mb-4 flex justify-center items-center text-sm text-gray-600 dark:text-gray-400">
<PostLabels :labels="post.labels" :repo-url="post.repo_url" />
</div>
Expand Down Expand Up @@ -42,13 +42,13 @@
<script setup lang="ts">
import { useAsyncData } from '#app'
import { useRoute } from 'vue-router'
import { useBannerContent } from '~/composables/useBannerContent'
import { useSupabaseUser } from '#imports'
import { useBannerContentInjection } from '~/composables/useBannerContent'
const { setBannerContent, setBannerImage } = useBannerContentInjection()
const user = useSupabaseUser()
const route = useRoute()
const { setBannerContent } = useBannerContent()
const { data: postData } = await useAsyncData('post', () =>
$fetch(`/api/repo/${route.params.repo_owner}/${route.params.repo_name}/issues/${route.params.id}`)
Expand Down Expand Up @@ -111,6 +111,23 @@ const handleCommentSubmission = async (newComment: any) => {
}
if (post.value) {
setBannerContent(`<h1 class="text-4xl font-extrabold text-center text-white mb-6">${post.value.title}</h1>`)
setBannerContent(`
<div class="text-center text-white">
<div class="mb-2">
<a href="/repo/${route.params.repo_owner}/${route.params.repo_name}" class="text-lg font-semibold hover:underline">
${route.params.repo_owner}/${route.params.repo_name}
</a>
</div>
<h1 class="text-4xl font-extrabold mb-4">${post.value.title}</h1>
<div class="flex items-center justify-center">
<img src="${post.value.avatar_url}" alt="${post.value.author}" class="w-10 h-10 rounded-full mr-3">
<div class="text-left">
<div class="font-medium">${post.value.author}</div>
<div class="text-sm opacity-75">${formatDate(post.value.created_at)}</div>
</div>
</div>
</div>
`)
setBannerImage('/banner3.jpeg')
}
</script>
</script>
6 changes: 3 additions & 3 deletions pages/repo/[repo_owner]/[repo_name]/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { useBannerContent } from '~/composables/useBannerContent'
import { useBannerContentInjection } from '~/composables/useBannerContent'
const { setBannerContent } = useBannerContentInjection()
const config = useRuntimeConfig()
import { useRoute } from 'vue-router'
Expand All @@ -18,7 +19,6 @@ const repoInfo = ref({})
const currentPage = ref(1)
const totalItems = ref(0)
const perPage = ref(parseInt(config.public.perPageSize) || 20)
const { setBannerContent } = useBannerContent()
const fetchBlogPosts = async (page = 1) => {
const { data: fetchedData } = await useAsyncData('blogPosts', () =>
Expand All @@ -44,5 +44,5 @@ const onPageChange = async (page: number) => {
await fetchBlogPosts(page)
}
// 设置 banner 内容
setBannerContent('<h1 class="text-4xl font-extrabold text-center text-white mb-6">Welcome to My Blog</h1>')
setBannerContent('')
</script>
43 changes: 31 additions & 12 deletions pages/repo/[repo_owner]/[repo_name]/tag/[name].vue
Original file line number Diff line number Diff line change
@@ -1,26 +1,45 @@
<template>
<div class="container mx-auto px-4">
<RepoTimeline :blogPosts="blogPosts" />
<RepoTimeline :blogPosts="blogPosts" :current-page="currentPage" :total-items="totalItems" :per-page="perPage" @page-change="onPageChange" />
</div>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router'
import { useBannerContent } from '~/composables/useBannerContent'
import { useBannerContentInjection } from '~/composables/useBannerContent'
const { setBannerContent, setBannerImage } = useBannerContentInjection()
const route = useRoute()
const { setBannerContent } = useBannerContent()
const config = useRuntimeConfig()
const { data: fetchedBlogPosts } = await useAsyncData('taggedPosts', () =>
$fetch(`/api/repo/${route.params.repo_owner}/${route.params.repo_name}/blog-posts`, {
params: { tag: route.params.name }
})
)
const blogPosts = ref([])
// 当数据获取完成后,更新 blogPosts
blogPosts.value = fetchedBlogPosts.value?.blogPosts || []
const currentPage = ref(1)
const totalItems = ref(0)
const perPage = ref(parseInt(config.public.perPageSize) || 20)
const fetchBlogPosts = async (page = 1) => {
const { data: fetchedData } = await useAsyncData('blogPosts', () =>
$fetch(`/api/repo/${config.public.repoOwner}/${config.public.repoName}/blog-posts`, {
params: { page, perPage: perPage.value, tag: route.params.name }
})
)
blogPosts.value = fetchedData.value?.blogPosts || []
totalItems.value = fetchedData.value?.pagination.totalItems || 0
perPage.value = fetchedData.value?.pagination.perPage || 20
currentPage.value = fetchedData.value?.pagination.currentPage || 1
}
console.log(blogPosts.value)
// Fetch initial data
await fetchBlogPosts()
// console.log(totalItems.value, perPage.value, currentPage.value)
// Handle page changes
const onPageChange = async (page: number) => {
await fetchBlogPosts(page)
}
setBannerContent(`<h1 class="text-4xl font-extrabold text-center text-white mb-6">Posts tagged with "${route.params.name}"</h1>`)
setBannerImage("/banner3.jpeg")
</script>
6 changes: 3 additions & 3 deletions pages/repo/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useBannerContent } from '~/composables/useBannerContent'
import { useBannerContentInjection } from '~/composables/useBannerContent'
const { setBannerContent, setBannerImage } = useBannerContentInjection()
const repos = ref([])
const { setBannerContent } = useBannerContent()
// 使用 useAsyncData 来获取仓库数据
const { data: reposData } = await useAsyncData('reposData', () =>
Expand All @@ -25,4 +24,5 @@ repos.value = reposData.value.repos || []
// 设置 banner 内容
setBannerContent('<h1 class="text-4xl font-extrabold text-center text-white mb-6">My Repositories</h1>')
setBannerImage("/repo-banner.jpeg")
</script>
Loading

0 comments on commit ef2a334

Please sign in to comment.