Skip to content

Commit d4d4889

Browse files
committed
refactor: move nav config to app.config and update types interface
- Refactor navigation configuration to be managed in app.config.ts, removing the redundant sidebar script setup in ZSidebar.vue. - Implement date-fns for improved date formatting in Article.vue and blog.get.ts, enhancing readability and localization. - Update badges with margin and inline-flex styling in Badge.vue, and standardize the use of 'badge-text' class in Title.vue. - Replace NuxtLink with ZRawLink component across various components for better control over external links. - Optimize article list rendering by simplifying the article computed property in article.vue. - Ensure all lines in commit messages are under 100 characters for better readability and adherence to best practices. BREAKING CHANGE: Navigation configuration is now centralized in app.config.ts. Update your components to use appConfig.nav instead of local variables.
1 parent 50dd8d4 commit d4d4889

File tree

12 files changed

+115
-63
lines changed

12 files changed

+115
-63
lines changed

app.config.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,34 @@
1+
import type { NavGroup } from './types/nav'
2+
13
export default defineAppConfig({
24
author: {
35
name: '纸鹿本鹿',
46
},
57
description: '纸鹿至麓不知路,支炉制露不止漉。',
8+
footer: {
9+
copyright: ${new Date().getFullYear()} 纸鹿本鹿`,
10+
message: 'aka Zhilu, L33Z22L11',
11+
},
12+
nav: <NavGroup[]> [
13+
{
14+
title: '',
15+
list: [
16+
{ icon: 'ph:house-duotone', title: '主页', link: '/' },
17+
{ icon: 'ph:pen-nib-duotone', title: '文章', link: '/article' },
18+
// { icon: "ph:pen-nib-duotone", title: "文章", link: "https://blog.zhilu.cyou", external: true },
19+
// { icon: "ph:code-duotone", title: "项目", link: "/project" },
20+
{ icon: 'ph:code-duotone', title: '项目', link: 'https://github.com/L33Z22L11/#user-33976233-pinned-items-reorder-form', external: true },
21+
{ icon: 'ph:globe-duotone', title: '站点', link: '/site' },
22+
{ icon: 'ph:files-duotone', title: '日志', link: '/log' },
23+
],
24+
},
25+
{
26+
title: '社交',
27+
list: [
28+
{ icon: 'ri:qq-fill', title: '群: 169994096', link: 'https://jq.qq.com/?_wv=1027&k=lQfNSeEd', external: true },
29+
{ icon: 'ph:github-logo-duotone', title: 'Github', link: 'https://github.com/L33Z22L11', external: true },
30+
{ icon: 'ph:telegram-logo-duotone', title: 'Telegram', link: 'https://t.me/L33Z22L11', external: true },
31+
],
32+
},
33+
],
634
})

components/ZSidebar.vue

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,4 @@
11
<script setup lang="ts">
2-
const curYear = new Date().getFullYear()
3-
const nav = [
4-
{
5-
title: '',
6-
list: [
7-
{ icon: 'ph:house-duotone', title: '主页', link: '/' },
8-
{ icon: 'ph:pen-nib-duotone', title: '文章', link: '/article' },
9-
// { icon: "ph:pen-nib-duotone", title: "文章", link: "https://blog.zhilu.cyou", external: true },
10-
// { icon: "ph:code-duotone", title: "项目", link: "/project" },
11-
{ icon: 'ph:code-duotone', title: '项目', link: 'https://github.com/L33Z22L11/#user-33976233-pinned-items-reorder-form', external: true },
12-
{ icon: 'ph:globe-duotone', title: '站点', link: '/site' },
13-
{ icon: 'ph:files-duotone', title: '日志', link: '/log' },
14-
],
15-
},
16-
{
17-
title: '社交',
18-
list: [
19-
{ icon: 'ri:qq-fill', title: '群: 169994096', link: 'https://jq.qq.com/?_wv=1027&k=lQfNSeEd', external: true },
20-
{ icon: 'ph:github-logo-duotone', title: 'Github', link: 'https://github.com/L33Z22L11', external: true },
21-
{ icon: 'ph:telegram-logo-duotone', title: 'Telegram', link: 'https://t.me/L33Z22L11', external: true },
22-
],
23-
},
24-
]
252
const appConfig = useAppConfig()
263
const sidebarStore = useSidebarStore()
274
</script>
@@ -34,7 +11,7 @@ const sidebarStore = useSidebarStore()
3411
<Icon name="ph:x" class="close-sidebar" @click="sidebarStore.toggle()" />
3512
</header>
3613
<nav class="aside-nav">
37-
<template v-for="(group, groupIndex) in nav" :key="groupIndex">
14+
<template v-for="(group, groupIndex) in appConfig.nav" :key="groupIndex">
3815
<h2 v-if="group.title">
3916
{{ group.title }}
4017
</h2>
@@ -50,8 +27,7 @@ const sidebarStore = useSidebarStore()
5027
</template>
5128
</nav>
5229
<footer class="aside-footer">
53-
<p>© {{ curYear }} {{ appConfig.author.name }}</p>
54-
<p>aka Zhilu, L33Z22L11</p>
30+
<p>{{ appConfig.footer.copyright }}<br>{{ appConfig.footer.message }}</p>
5531
</footer>
5632
</aside>
5733
<Transition>

components/particle/Article.vue

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,36 @@
11
<script setup lang="ts">
2-
defineProps<{ article: any }>()
2+
import { format, formatDistanceToNow } from 'date-fns'
3+
import { zhCN } from 'date-fns/locale'
4+
import type FeedProps from '~/types/feed'
5+
6+
const props = defineProps<FeedProps>()
7+
8+
const tPublishedLabel = getPostTime(props.published)
9+
const tUpdatedLabel = getPostTime(props.updated)
10+
function getPostTime(date: string) {
11+
const postDate = new Date(date)
12+
const now = new Date()
13+
if (postDate.getTime() > now.getTime() - 1000 * 60 * 60 * 24 * 7) {
14+
return formatDistanceToNow(postDate, { addSuffix: true, locale: zhCN })
15+
}
16+
else if (postDate.getFullYear() === now.getFullYear()) {
17+
return format(postDate, 'M月d日')
18+
}
19+
else {
20+
return format(postDate, 'yy年M月d日')
21+
}
22+
}
323
</script>
424

525
<template>
6-
<a class="article-card" :href="article.link || article.id">
26+
<a class="article-card" :href="link.$href || id">
727
<div class="article-header">
8-
<time v-if="article.tPublishedLabel !== article.tUpdatedLabel" :datetime="article.updated">
9-
{{ article.tUpdatedLabel }}</time>
10-
<time :datetime="article.published">{{ article.tPublishedLabel }}</time>
28+
<time v-if="tPublishedLabel !== tUpdatedLabel" :datetime="updated">
29+
{{ tUpdatedLabel }}</time>
30+
<time :datetime="published">{{ tPublishedLabel }}</time>
1131
</div>
12-
<h2 class="article-title">{{ article.title }}</h2>
13-
<p class="article-descrption">{{ article.summary }}</p>
32+
<h2 class="article-title">{{ title }}</h2>
33+
<p class="article-descrption">{{ summary['#text'] || summary }}</p>
1434
</a>
1535
</template>
1636

components/particle/Badge.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ defineProps<{
3636
}
3737
3838
.badge-width-icon {
39+
margin-block: 2px;
3940
border-radius: 1em;
4041
font-size: 0.8em;
4142

components/particle/RawLink.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ defineProps<{ to?: string }>()
33
</script>
44

55
<template>
6-
<NuxtLink :to="to" :target="isExtLink(to) && '_blank'">
6+
<NuxtLink :to="to" :target="isExtLink(to) ? '_blank' : undefined">
77
<slot />
88
</NuxtLink>
99
</template>

nuxt.config.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,25 @@ export default defineNuxtConfig({
1717
titleTemplate: '%s %separator 纸鹿 (@L33Z22L11)',
1818
},
1919
},
20+
2021
components: [
2122
{ path: '~/components/particle', prefix: 'Z' },
2223
{ path: '~/components/zhilu', prefix: 'ZL' },
2324
'~/components',
2425
],
26+
2527
css: [
2628
'@/assets/main.scss',
2729
],
30+
2831
devtools: { enabled: false },
32+
2933
experimental: {
3034
viewTransition: true,
3135
},
36+
3237
srcDir: './',
38+
3339
vite: {
3440
css: {
3541
preprocessorOptions: {
@@ -39,16 +45,21 @@ export default defineNuxtConfig({
3945
},
4046
},
4147
},
48+
4249
vue: {
4350
propsDestructure: true,
4451
runtimeCompiler: true,
4552
},
53+
4654
modules: [
4755
'@nuxt/icon',
4856
'@nuxtjs/seo',
4957
'@pinia/nuxt',
5058
],
59+
5160
site: {
5261
url: 'https://zhilu.cyou',
5362
},
63+
64+
compatibilityDate: '2024-07-23',
5465
})

pages/article.vue

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,18 @@
11
<script setup lang="ts">
2-
import { format, formatDistanceToNow } from 'date-fns'
3-
import { zhCN } from 'date-fns/locale'
2+
import type FeedProps from '~/types/feed'
43
54
useHead({ title: '文章' })
65
definePageMeta({ headerText: '最近更新' })
76
87
const { data, error, status } = useLazyFetch('/api/feed/blog')
98
10-
const articles = computed(() =>
11-
data.value.map((feed: any) => ({
12-
...feed,
13-
tPublishedLabel: getPostTime(feed.published),
14-
tUpdatedLabel: getPostTime(feed.updated),
15-
})).slice(0, 11),
16-
)
17-
18-
function getPostTime(date: Date) {
19-
const postDate = new Date(date)
20-
const now = new Date()
21-
if (postDate.getTime() > now.getTime() - 1000 * 60 * 60 * 24 * 7) {
22-
return formatDistanceToNow(postDate, { addSuffix: true, locale: zhCN })
23-
}
24-
else if (postDate.getFullYear() === now.getFullYear()) {
25-
return format(postDate, 'M月d日')
26-
}
27-
else {
28-
return format(postDate, 'yy年M月d日')
29-
}
30-
}
9+
const articles = computed(() => data.value.slice(0, 11))
3110
</script>
3211

3312
<template>
3413
<ZTitle icon="👀">
3514
<span class="badge-text">来自博客
36-
<NuxtLink to="https://blog.zhilu.cyou"><mark>纸鹿摸鱼处</mark></NuxtLink>
15+
<ZRawLink to="https://blog.zhilu.cyou"><mark>纸鹿摸鱼处</mark></ZRawLink>
3716
的文章
3817
</span>
3918
</ZTitle>
@@ -45,7 +24,7 @@ function getPostTime(date: Date) {
4524
<p>{{ error }}</p>
4625
</template>
4726
<div v-else class="article-list">
48-
<ZArticle v-for="article in articles" :key="article.id" :article="article" />
27+
<ZArticle v-for="article in articles" :key="article.id" v-bind="article" />
4928
</div>
5029
<div class="article-more">
5130
<ZRawLink to="https://blog.zhilu.cyou/">

server/api/feed/blog.get.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { XMLParser } from 'fast-xml-parser'
2+
import type { validationOptions } from 'fast-xml-parser'
23

34
export default defineCachedEventHandler(async (_event) => {
45
const resp = await fetch('https://blog.zhilu.cyou/atom.xml')
5-
const rawXML = await resp.text()
6-
const objAtom = new XMLParser().parse(rawXML)
6+
const parseOptions: validationOptions = {
7+
ignoreAttributes: false,
8+
attributeNamePrefix: '$',
9+
}
10+
const objAtom = new XMLParser(parseOptions).parse(await resp.text())
711

812
// 不要 content
913
// const feed = objAtom.feed.entry.map((article: any) => {

types/feed.d.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export default interface FeedProps {
2+
[key: string]: any
3+
title: string
4+
link: {
5+
$href: string
6+
}
7+
id: string
8+
published: string
9+
updated: string
10+
summary: {
11+
'#text': string
12+
'$type': string
13+
}
14+
content?: {
15+
$src: string
16+
$type: string
17+
}
18+
category: {
19+
$term: string
20+
$scheme: string
21+
}[]
22+
}
File renamed without changes.

0 commit comments

Comments
 (0)