valaxy-theme-hairy 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +21 -21
- package/client/index.ts +1 -1
- package/components/HairyBody.vue +49 -49
- package/components/HairyCodepen.vue +40 -40
- package/components/HairyComment.vue +33 -33
- package/components/HairyContainer.vue +17 -17
- package/components/HairyDrawer.vue +44 -44
- package/components/HairyFooter.vue +62 -62
- package/components/HairyHeader.vue +32 -32
- package/components/HairyImage.vue +15 -15
- package/components/HairyImageGroup.vue +65 -65
- package/components/HairyNavbar.vue +56 -56
- package/components/HairyPageArchives.vue +59 -59
- package/components/HairyPageTags.vue +48 -48
- package/components/HairyPosts.vue +54 -54
- package/components/HairySearch.vue +201 -201
- package/components/HairySidebar.vue +30 -30
- package/components/HairyTabbar.vue +56 -56
- package/components/PageTags.vue +48 -48
- package/components/ValaxyMain.vue +45 -45
- package/components/navbar/HairyNav.vue +16 -16
- package/components/navbar/HairyNavExpand.vue +12 -12
- package/components/navbar/HairyNavItem.vue +35 -35
- package/components/navbar/HairyNavbarBackground.vue +7 -7
- package/components/navbar/HairyNavbarSearch.vue +8 -8
- package/components/navbar/HairyNavbarTitle.vue +15 -15
- package/components/navbar/HairyNavbarToggleDark.vue +22 -22
- package/components/parts/HairyBreadcrumb.vue +51 -51
- package/components/parts/HairyBreadcrumbItem.vue +11 -11
- package/components/parts/HairyFootFish.js +352 -352
- package/components/parts/HairyFootFish.vue +38 -38
- package/components/parts/HairyHeadHero.vue +34 -34
- package/components/parts/HairyHeadWaves.vue +67 -67
- package/components/parts/HairyImageGlobal.vue +51 -51
- package/components/parts/HairyImageViewer.vue +23 -23
- package/components/parts/HairyLink.vue +21 -21
- package/components/parts/HairyMenu.vue +16 -16
- package/components/parts/HairyMenuItem.vue +47 -47
- package/components/parts/HairyOutline.vue +99 -99
- package/components/parts/HairyOutlineItem.vue +48 -48
- package/components/parts/HairySocialLinks.vue +27 -27
- package/components/parts/HairyTimelineContent.vue +39 -39
- package/components/parts/HairyUserNav.vue +95 -95
- package/components/parts/HairyUserStats.vue +18 -18
- package/components/posts/HairyArticleImage.vue +126 -126
- package/components/posts/HairyArticleSeries.vue +89 -89
- package/components/posts/HairyArticleText.vue +43 -43
- package/components/posts/HairyPostFooter.vue +15 -15
- package/components/posts/HairyPostImageList.vue +27 -27
- package/components/posts/HairyPostTextsList.vue +22 -22
- package/components/posts/HairyPostToggleLayout.vue +36 -36
- package/components/third/HairyAlgoliaSearch.vue +17 -17
- package/components/third/HairyFuseSearch.vue +10 -10
- package/components/third/HairyFuseSearchDialog.vue +32 -32
- package/components/third/HairyFuseSearchDropdown.vue +77 -77
- package/components/third/HairyFuseSearchFooter.vue +28 -28
- package/components/third/HairyFuseSearchHeader.vue +30 -30
- package/components/third/HairyFuseSearchHit.vue +52 -52
- package/components/third/HairySearchBtnDisplay.vue +29 -29
- package/components/third/HairySearchBtnInput.vue +20 -20
- package/components/third/HairySearchBtnKeys.vue +19 -19
- package/components/third/HairySwiperCarousel.vue +45 -45
- package/composables/archives.ts +48 -48
- package/composables/category.ts +43 -43
- package/composables/config.ts +11 -11
- package/composables/dark.ts +13 -13
- package/composables/fuse.ts +60 -60
- package/composables/index.ts +7 -7
- package/composables/layout.ts +16 -16
- package/composables/outline.ts +49 -49
- package/composables/tags.ts +36 -36
- package/layouts/archive-month.vue +13 -13
- package/layouts/archive-year.vue +13 -13
- package/layouts/archives.vue +11 -11
- package/layouts/categories.vue +13 -13
- package/layouts/default.vue +13 -15
- package/layouts/home.vue +33 -33
- package/layouts/post.vue +54 -54
- package/layouts/tag.vue +10 -10
- package/layouts/tags.vue +10 -14
- package/library/loading.scss +535 -535
- package/library/loading.ts +60 -60
- package/library/scroll.ts +22 -22
- package/locales/en.yml +1 -1
- package/locales/zh-CN.yml +1 -1
- package/node/images/default.json +139 -139
- package/node/images/index.ts +46 -46
- package/node/images/shims.d.ts +8 -8
- package/node/index.ts +2 -2
- package/node/theme/index.ts +78 -78
- package/package.json +1 -1
- package/pages/archives/[year]/[month]/index.vue +48 -48
- package/pages/archives/[year]/index.vue +73 -73
- package/pages/archives/index.md +6 -0
- package/pages/categories/[...its].vue +108 -108
- package/pages/index.vue +8 -8
- package/pages/page/[page].vue +12 -12
- package/pages/tags/[tag]/index.vue +38 -38
- package/pages/tags/index.md +7 -0
- package/setup/main.ts +9 -9
- package/store/index.ts +1 -1
- package/store/modules/global.ts +12 -12
- package/styles/components/aplayer.scss +75 -75
- package/styles/components/index.scss +3 -3
- package/styles/components/markdown.scss +89 -89
- package/styles/components/nprogress.scss +15 -15
- package/styles/components/scrollbar.scss +25 -25
- package/styles/css-vars.scss +171 -171
- package/styles/element-plus/index.scss +1 -1
- package/styles/element-plus/tabs.scss +25 -25
- package/styles/element-plus/timeline.scss +18 -18
- package/styles/font-face.scss +19 -19
- package/styles/global.scss +38 -38
- package/styles/index.scss +3 -3
- package/tsconfig.json +27 -27
- package/types/index.d.ts +163 -163
- package/unocss.config.ts +43 -43
- package/utils/index.ts +37 -37
- package/valaxy.config.ts +26 -26
- package/pages/archives/index.vue +0 -6
- package/pages/tags/index.vue +0 -6
@@ -1,99 +1,99 @@
|
|
1
|
-
<script setup lang="ts">
|
2
|
-
import { ref } from 'vue'
|
3
|
-
import {
|
4
|
-
useActiveAnchor,
|
5
|
-
} from 'valaxy'
|
6
|
-
import { useOutline } from '../../composables'
|
7
|
-
|
8
|
-
const container = ref()
|
9
|
-
const marker = ref()
|
10
|
-
|
11
|
-
useActiveAnchor(container, marker)
|
12
|
-
|
13
|
-
const { headers, handleClick } = useOutline()
|
14
|
-
</script>
|
15
|
-
|
16
|
-
<template>
|
17
|
-
<div v-show="headers.length" ref="container">
|
18
|
-
<div class="content">
|
19
|
-
<div class="outline-title">
|
20
|
-
{{ 'On this page' }}
|
21
|
-
</div>
|
22
|
-
|
23
|
-
<div ref="marker" class="outline-marker" />
|
24
|
-
|
25
|
-
<nav aria-labelledby="doc-outline-aria-label">
|
26
|
-
<span id="doc-outline-aria-label" class="visually-hidden">
|
27
|
-
Table of Contents for current page
|
28
|
-
</span>
|
29
|
-
|
30
|
-
<HairyOutlineItem
|
31
|
-
class="va-toc relative z-1 css-i18n-toc"
|
32
|
-
:headers="headers"
|
33
|
-
:on-click="handleClick"
|
34
|
-
root
|
35
|
-
/>
|
36
|
-
</nav>
|
37
|
-
</div>
|
38
|
-
</div>
|
39
|
-
</template>
|
40
|
-
|
41
|
-
<style lang="scss" scoped>
|
42
|
-
.va-toc {
|
43
|
-
text-align: left;
|
44
|
-
}
|
45
|
-
|
46
|
-
.content {
|
47
|
-
position: relative;
|
48
|
-
padding-left: 16px;
|
49
|
-
font-size: 14px;
|
50
|
-
text-align: left;
|
51
|
-
}
|
52
|
-
|
53
|
-
.outline-marker {
|
54
|
-
position: absolute;
|
55
|
-
top: 32px;
|
56
|
-
left: -2px;
|
57
|
-
z-index: 0;
|
58
|
-
opacity: 0;
|
59
|
-
width: 4px;
|
60
|
-
height: 18px;
|
61
|
-
background-color: var(--va-c-brand);
|
62
|
-
transition: top 0.25s cubic-bezier(0, 1, 0.5, 1), background-color 0.5s, opacity 0.25s;
|
63
|
-
border-top-right-radius: 2px;
|
64
|
-
border-bottom-right-radius: 2px;
|
65
|
-
}
|
66
|
-
|
67
|
-
.outline-title {
|
68
|
-
letter-spacing: 0.4px;
|
69
|
-
line-height: 28px;
|
70
|
-
font-size: 14px;
|
71
|
-
font-weight: 600;
|
72
|
-
}
|
73
|
-
|
74
|
-
.outline-link {
|
75
|
-
display: block;
|
76
|
-
line-height: 28px;
|
77
|
-
color: var(--va-c-text-light);
|
78
|
-
white-space: nowrap;
|
79
|
-
overflow: hidden;
|
80
|
-
text-overflow: ellipsis;
|
81
|
-
transition: color 0.5s;
|
82
|
-
}
|
83
|
-
|
84
|
-
.outline-link:hover,
|
85
|
-
.outline-link.active {
|
86
|
-
color: var(--va-c-brand);
|
87
|
-
transition: color 0.25s;
|
88
|
-
}
|
89
|
-
|
90
|
-
.visually-hidden {
|
91
|
-
position: absolute;
|
92
|
-
width: 1px;
|
93
|
-
height: 1px;
|
94
|
-
white-space: nowrap;
|
95
|
-
clip: rect(0 0 0 0);
|
96
|
-
clip-path: inset(50%);
|
97
|
-
overflow: hidden;
|
98
|
-
}
|
99
|
-
</style>
|
1
|
+
<script setup lang="ts">
|
2
|
+
import { ref } from 'vue'
|
3
|
+
import {
|
4
|
+
useActiveAnchor,
|
5
|
+
} from 'valaxy'
|
6
|
+
import { useOutline } from '../../composables'
|
7
|
+
|
8
|
+
const container = ref()
|
9
|
+
const marker = ref()
|
10
|
+
|
11
|
+
useActiveAnchor(container, marker)
|
12
|
+
|
13
|
+
const { headers, handleClick } = useOutline()
|
14
|
+
</script>
|
15
|
+
|
16
|
+
<template>
|
17
|
+
<div v-show="headers.length" ref="container">
|
18
|
+
<div class="content">
|
19
|
+
<div class="outline-title">
|
20
|
+
{{ 'On this page' }}
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<div ref="marker" class="outline-marker" />
|
24
|
+
|
25
|
+
<nav aria-labelledby="doc-outline-aria-label">
|
26
|
+
<span id="doc-outline-aria-label" class="visually-hidden">
|
27
|
+
Table of Contents for current page
|
28
|
+
</span>
|
29
|
+
|
30
|
+
<HairyOutlineItem
|
31
|
+
class="va-toc relative z-1 css-i18n-toc"
|
32
|
+
:headers="headers"
|
33
|
+
:on-click="handleClick"
|
34
|
+
root
|
35
|
+
/>
|
36
|
+
</nav>
|
37
|
+
</div>
|
38
|
+
</div>
|
39
|
+
</template>
|
40
|
+
|
41
|
+
<style lang="scss" scoped>
|
42
|
+
.va-toc {
|
43
|
+
text-align: left;
|
44
|
+
}
|
45
|
+
|
46
|
+
.content {
|
47
|
+
position: relative;
|
48
|
+
padding-left: 16px;
|
49
|
+
font-size: 14px;
|
50
|
+
text-align: left;
|
51
|
+
}
|
52
|
+
|
53
|
+
.outline-marker {
|
54
|
+
position: absolute;
|
55
|
+
top: 32px;
|
56
|
+
left: -2px;
|
57
|
+
z-index: 0;
|
58
|
+
opacity: 0;
|
59
|
+
width: 4px;
|
60
|
+
height: 18px;
|
61
|
+
background-color: var(--va-c-brand);
|
62
|
+
transition: top 0.25s cubic-bezier(0, 1, 0.5, 1), background-color 0.5s, opacity 0.25s;
|
63
|
+
border-top-right-radius: 2px;
|
64
|
+
border-bottom-right-radius: 2px;
|
65
|
+
}
|
66
|
+
|
67
|
+
.outline-title {
|
68
|
+
letter-spacing: 0.4px;
|
69
|
+
line-height: 28px;
|
70
|
+
font-size: 14px;
|
71
|
+
font-weight: 600;
|
72
|
+
}
|
73
|
+
|
74
|
+
.outline-link {
|
75
|
+
display: block;
|
76
|
+
line-height: 28px;
|
77
|
+
color: var(--va-c-text-light);
|
78
|
+
white-space: nowrap;
|
79
|
+
overflow: hidden;
|
80
|
+
text-overflow: ellipsis;
|
81
|
+
transition: color 0.5s;
|
82
|
+
}
|
83
|
+
|
84
|
+
.outline-link:hover,
|
85
|
+
.outline-link.active {
|
86
|
+
color: var(--va-c-brand);
|
87
|
+
transition: color 0.25s;
|
88
|
+
}
|
89
|
+
|
90
|
+
.visually-hidden {
|
91
|
+
position: absolute;
|
92
|
+
width: 1px;
|
93
|
+
height: 1px;
|
94
|
+
white-space: nowrap;
|
95
|
+
clip: rect(0 0 0 0);
|
96
|
+
clip-path: inset(50%);
|
97
|
+
overflow: hidden;
|
98
|
+
}
|
99
|
+
</style>
|
@@ -1,48 +1,48 @@
|
|
1
|
-
<script setup lang="ts">
|
2
|
-
import type { MenuItem } from 'valaxy'
|
3
|
-
import { useI18n } from 'vue-i18n'
|
4
|
-
|
5
|
-
defineProps<{
|
6
|
-
headers: MenuItem[]
|
7
|
-
onClick: (e: MouseEvent) => void
|
8
|
-
root?: boolean
|
9
|
-
}>()
|
10
|
-
|
11
|
-
const { locale } = useI18n()
|
12
|
-
</script>
|
13
|
-
|
14
|
-
<template>
|
15
|
-
<ul :class="root ? 'root' : 'nested'">
|
16
|
-
<li v-for="{ children, link, title, lang } in headers" :key="link" class="va-toc-item" :lang="lang || locale">
|
17
|
-
<a class="outline-link" :href="link" @click="onClick">{{ title }}</a>
|
18
|
-
<template v-if="children?.length">
|
19
|
-
<HairyOutlineItem :headers="children" :on-click="onClick" />
|
20
|
-
</template>
|
21
|
-
</li>
|
22
|
-
</ul>
|
23
|
-
</template>
|
24
|
-
|
25
|
-
<style lang="scss" scoped>
|
26
|
-
.va-toc {
|
27
|
-
.va-toc-item {
|
28
|
-
.outline-link {
|
29
|
-
color: var(--va-c-text-light);
|
30
|
-
white-space: nowrap;
|
31
|
-
overflow: hidden;
|
32
|
-
text-overflow: ellipsis;
|
33
|
-
transition: color 0.5s;
|
34
|
-
|
35
|
-
&:hover,
|
36
|
-
&.active {
|
37
|
-
color: var(--va-c-primary-lighter);
|
38
|
-
transition: color 0.25s;
|
39
|
-
}
|
40
|
-
|
41
|
-
}
|
42
|
-
|
43
|
-
.nested {
|
44
|
-
padding-left: 0.8rem;
|
45
|
-
}
|
46
|
-
}
|
47
|
-
}
|
48
|
-
</style>
|
1
|
+
<script setup lang="ts">
|
2
|
+
import type { MenuItem } from 'valaxy'
|
3
|
+
import { useI18n } from 'vue-i18n'
|
4
|
+
|
5
|
+
defineProps<{
|
6
|
+
headers: MenuItem[]
|
7
|
+
onClick: (e: MouseEvent) => void
|
8
|
+
root?: boolean
|
9
|
+
}>()
|
10
|
+
|
11
|
+
const { locale } = useI18n()
|
12
|
+
</script>
|
13
|
+
|
14
|
+
<template>
|
15
|
+
<ul :class="root ? 'root' : 'nested'">
|
16
|
+
<li v-for="{ children, link, title, lang } in headers" :key="link" class="va-toc-item" :lang="lang || locale">
|
17
|
+
<a class="outline-link" :href="link" @click="onClick">{{ title }}</a>
|
18
|
+
<template v-if="children?.length">
|
19
|
+
<HairyOutlineItem :headers="children" :on-click="onClick" />
|
20
|
+
</template>
|
21
|
+
</li>
|
22
|
+
</ul>
|
23
|
+
</template>
|
24
|
+
|
25
|
+
<style lang="scss" scoped>
|
26
|
+
.va-toc {
|
27
|
+
.va-toc-item {
|
28
|
+
.outline-link {
|
29
|
+
color: var(--va-c-text-light);
|
30
|
+
white-space: nowrap;
|
31
|
+
overflow: hidden;
|
32
|
+
text-overflow: ellipsis;
|
33
|
+
transition: color 0.5s;
|
34
|
+
|
35
|
+
&:hover,
|
36
|
+
&.active {
|
37
|
+
color: var(--va-c-primary-lighter);
|
38
|
+
transition: color 0.25s;
|
39
|
+
}
|
40
|
+
|
41
|
+
}
|
42
|
+
|
43
|
+
.nested {
|
44
|
+
padding-left: 0.8rem;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
</style>
|
@@ -1,27 +1,27 @@
|
|
1
|
-
<script lang="ts" setup>
|
2
|
-
import { useSiteConfig } from 'valaxy'
|
3
|
-
|
4
|
-
const config = useSiteConfig()
|
5
|
-
</script>
|
6
|
-
|
7
|
-
<template>
|
8
|
-
<div class="links-of-author grid grid-cols-8 justify-center gap-1">
|
9
|
-
<a v-for="item, i in config.social" :key="i" class="links-of-author-item" rel="noopener" :href="item.link" :title="item.name" target="_blank" :style="`color:${item.color}`">
|
10
|
-
<div class="icon" :class="item.icon" />
|
11
|
-
</a>
|
12
|
-
</div>
|
13
|
-
</template>
|
14
|
-
|
15
|
-
<style lang="scss">
|
16
|
-
.links-of-author {
|
17
|
-
.icon {
|
18
|
-
width: 1.5rem;
|
19
|
-
height: 1.5rem;
|
20
|
-
}
|
21
|
-
|
22
|
-
&-item {
|
23
|
-
line-height: 1;
|
24
|
-
font-size: 0.9rem;
|
25
|
-
}
|
26
|
-
}
|
27
|
-
</style>
|
1
|
+
<script lang="ts" setup>
|
2
|
+
import { useSiteConfig } from 'valaxy'
|
3
|
+
|
4
|
+
const config = useSiteConfig()
|
5
|
+
</script>
|
6
|
+
|
7
|
+
<template>
|
8
|
+
<div class="links-of-author grid grid-cols-8 justify-center gap-1">
|
9
|
+
<a v-for="item, i in config.social" :key="i" class="links-of-author-item" rel="noopener" :href="item.link" :title="item.name" target="_blank" :style="`color:${item.color}`">
|
10
|
+
<div class="icon" :class="item.icon" />
|
11
|
+
</a>
|
12
|
+
</div>
|
13
|
+
</template>
|
14
|
+
|
15
|
+
<style lang="scss">
|
16
|
+
.links-of-author {
|
17
|
+
.icon {
|
18
|
+
width: 1.5rem;
|
19
|
+
height: 1.5rem;
|
20
|
+
}
|
21
|
+
|
22
|
+
&-item {
|
23
|
+
line-height: 1;
|
24
|
+
font-size: 0.9rem;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
</style>
|
@@ -1,39 +1,39 @@
|
|
1
|
-
<script lang="ts" setup>
|
2
|
-
import type { Post } from 'valaxy'
|
3
|
-
import dayjs from 'dayjs'
|
4
|
-
import { withDefaults } from 'vue'
|
5
|
-
import { last } from 'lodash-es'
|
6
|
-
import { useRouter } from 'vue-router'
|
7
|
-
import { useI18n } from 'vue-i18n'
|
8
|
-
import { toArray } from '../../utils'
|
9
|
-
|
10
|
-
withDefaults(
|
11
|
-
defineProps<{
|
12
|
-
post: Post
|
13
|
-
format?: string
|
14
|
-
}>(),
|
15
|
-
{
|
16
|
-
format: 'YYYY-MM-DD',
|
17
|
-
},
|
18
|
-
)
|
19
|
-
|
20
|
-
const i18n = useI18n()
|
21
|
-
|
22
|
-
const router = useRouter()
|
23
|
-
|
24
|
-
function displayCategory(keys: string | string[] = []) {
|
25
|
-
router.push({ path: `/categories/${toArray(keys).join('/')}` })
|
26
|
-
}
|
27
|
-
</script>
|
28
|
-
|
29
|
-
<template>
|
30
|
-
<div class="mb-1 text-size-3.5 mt-1.5 flex items-center">
|
31
|
-
<div class="mr-2.2 dark:text-gray-500 text-gray-400">
|
32
|
-
{{ dayjs(post.date).format(format) }}
|
33
|
-
</div>
|
34
|
-
<HairyLink v-if="post.categories?.length" bordered type="white" @click="displayCategory(post.categories)">
|
35
|
-
{{ i18n.t(last(toArray(post.categories)) || '') }}
|
36
|
-
</HairyLink>
|
37
|
-
</div>
|
38
|
-
<a class="cursor-pointer text-size-4" @click="$router.push(post.path || '')">{{ post.title }}</a>
|
39
|
-
</template>
|
1
|
+
<script lang="ts" setup>
|
2
|
+
import type { Post } from 'valaxy'
|
3
|
+
import dayjs from 'dayjs'
|
4
|
+
import { withDefaults } from 'vue'
|
5
|
+
import { last } from 'lodash-es'
|
6
|
+
import { useRouter } from 'vue-router'
|
7
|
+
import { useI18n } from 'vue-i18n'
|
8
|
+
import { toArray } from '../../utils'
|
9
|
+
|
10
|
+
withDefaults(
|
11
|
+
defineProps<{
|
12
|
+
post: Post
|
13
|
+
format?: string
|
14
|
+
}>(),
|
15
|
+
{
|
16
|
+
format: 'YYYY-MM-DD',
|
17
|
+
},
|
18
|
+
)
|
19
|
+
|
20
|
+
const i18n = useI18n()
|
21
|
+
|
22
|
+
const router = useRouter()
|
23
|
+
|
24
|
+
function displayCategory(keys: string | string[] = []) {
|
25
|
+
router.push({ path: `/categories/${toArray(keys).join('/')}` })
|
26
|
+
}
|
27
|
+
</script>
|
28
|
+
|
29
|
+
<template>
|
30
|
+
<div class="mb-1 text-size-3.5 mt-1.5 flex items-center">
|
31
|
+
<div class="mr-2.2 dark:text-gray-500 text-gray-400">
|
32
|
+
{{ dayjs(post.date).format(format) }}
|
33
|
+
</div>
|
34
|
+
<HairyLink v-if="post.categories?.length" bordered type="white" @click="displayCategory(post.categories)">
|
35
|
+
{{ i18n.t(last(toArray(post.categories)) || '') }}
|
36
|
+
</HairyLink>
|
37
|
+
</div>
|
38
|
+
<a class="cursor-pointer text-size-4" @click="$router.push(post.path || '')">{{ post.title }}</a>
|
39
|
+
</template>
|
@@ -1,95 +1,95 @@
|
|
1
|
-
<script lang="ts" setup>
|
2
|
-
import { usePostList, useTags } from 'valaxy'
|
3
|
-
import { computed, nextTick } from 'vue'
|
4
|
-
import { useRouter } from 'vue-router'
|
5
|
-
import { storeToRefs } from 'pinia'
|
6
|
-
import { toArray } from '../../utils'
|
7
|
-
import { useGlobalStore } from '../../store'
|
8
|
-
|
9
|
-
const posts = usePostList()
|
10
|
-
const tags = useTags()
|
11
|
-
const router = useRouter()
|
12
|
-
const { showDrawer } = storeToRefs(useGlobalStore())
|
13
|
-
|
14
|
-
const total = computed(() => {
|
15
|
-
const categories = posts.value.map(v => toArray(v.categories || [])).filter(v => v.length)
|
16
|
-
const maps: string[] = []
|
17
|
-
for (const category of categories) {
|
18
|
-
let caches: string[] = []
|
19
|
-
for (const iterator of category) {
|
20
|
-
caches.push(iterator)
|
21
|
-
maps.push(caches.join('-'))
|
22
|
-
}
|
23
|
-
caches = []
|
24
|
-
}
|
25
|
-
return new Set(maps).size
|
26
|
-
})
|
27
|
-
|
28
|
-
async function navigation(path: string) {
|
29
|
-
await router.push(path)
|
30
|
-
await nextTick()
|
31
|
-
showDrawer.value = false
|
32
|
-
}
|
33
|
-
</script>
|
34
|
-
|
35
|
-
<template>
|
36
|
-
<div class="flex justify-center mt-2">
|
37
|
-
<HairyUserStats :count="posts.length" @click="navigation('/archives/')">
|
38
|
-
文章
|
39
|
-
</HairyUserStats>
|
40
|
-
<div class="w-1px bg-gray bg-opacity-50" />
|
41
|
-
<HairyUserStats :count="total" @click="navigation('/categories/')">
|
42
|
-
分类
|
43
|
-
</HairyUserStats>
|
44
|
-
<div class="w-1px bg-gray bg-opacity-50" />
|
45
|
-
<HairyUserStats :count="tags.size" @click="navigation('/tags/')">
|
46
|
-
标签
|
47
|
-
</HairyUserStats>
|
48
|
-
</div>
|
49
|
-
<HairySocialLinks class="mt-5" />
|
50
|
-
<HairyMenu class="HairyUserMenu mt-5 flex-col h-auto" />
|
51
|
-
</template>
|
52
|
-
|
53
|
-
<style lang="scss">
|
54
|
-
.HairyUserMenu {
|
55
|
-
display: flex;
|
56
|
-
flex-direction: column;
|
57
|
-
gap: 6px;
|
58
|
-
.HairyMenuItem {
|
59
|
-
padding: 2px;
|
60
|
-
width: 100%;
|
61
|
-
border: 1px solid transparent;
|
62
|
-
border-radius: 10px;
|
63
|
-
transition: all 0.2s;
|
64
|
-
background-color: transparent;
|
65
|
-
user-select: none;
|
66
|
-
> div {
|
67
|
-
justify-content: center;
|
68
|
-
}
|
69
|
-
}
|
70
|
-
|
71
|
-
.HairyMenuItem:hover,
|
72
|
-
.HairyMenuItem.active {
|
73
|
-
background-color: #f4f4f5;
|
74
|
-
}
|
75
|
-
.HairyMenuItem:active {
|
76
|
-
background-color: #efefef;
|
77
|
-
}
|
78
|
-
|
79
|
-
.HairyMenuItem.active + .HairyMenuItem {
|
80
|
-
border-top-color: transparent;
|
81
|
-
}
|
82
|
-
.HairyMenuItem:hover + .HairyMenuItem {
|
83
|
-
border-top-color: transparent;
|
84
|
-
}
|
85
|
-
}
|
86
|
-
.dark .HairyUserMenu {
|
87
|
-
.HairyMenuItem:hover,
|
88
|
-
.HairyMenuItem.active {
|
89
|
-
background-color: #f4f4f50a;
|
90
|
-
}
|
91
|
-
.HairyMenuItem:active {
|
92
|
-
background-color: #f4f4f521;
|
93
|
-
}
|
94
|
-
}
|
95
|
-
</style>
|
1
|
+
<script lang="ts" setup>
|
2
|
+
import { usePostList, useTags } from 'valaxy'
|
3
|
+
import { computed, nextTick } from 'vue'
|
4
|
+
import { useRouter } from 'vue-router'
|
5
|
+
import { storeToRefs } from 'pinia'
|
6
|
+
import { toArray } from '../../utils'
|
7
|
+
import { useGlobalStore } from '../../store'
|
8
|
+
|
9
|
+
const posts = usePostList()
|
10
|
+
const tags = useTags()
|
11
|
+
const router = useRouter()
|
12
|
+
const { showDrawer } = storeToRefs(useGlobalStore())
|
13
|
+
|
14
|
+
const total = computed(() => {
|
15
|
+
const categories = posts.value.map(v => toArray(v.categories || [])).filter(v => v.length)
|
16
|
+
const maps: string[] = []
|
17
|
+
for (const category of categories) {
|
18
|
+
let caches: string[] = []
|
19
|
+
for (const iterator of category) {
|
20
|
+
caches.push(iterator)
|
21
|
+
maps.push(caches.join('-'))
|
22
|
+
}
|
23
|
+
caches = []
|
24
|
+
}
|
25
|
+
return new Set(maps).size
|
26
|
+
})
|
27
|
+
|
28
|
+
async function navigation(path: string) {
|
29
|
+
await router.push(path)
|
30
|
+
await nextTick()
|
31
|
+
showDrawer.value = false
|
32
|
+
}
|
33
|
+
</script>
|
34
|
+
|
35
|
+
<template>
|
36
|
+
<div class="flex justify-center mt-2">
|
37
|
+
<HairyUserStats :count="posts.length" @click="navigation('/archives/')">
|
38
|
+
文章
|
39
|
+
</HairyUserStats>
|
40
|
+
<div class="w-1px bg-gray bg-opacity-50" />
|
41
|
+
<HairyUserStats :count="total" @click="navigation('/categories/')">
|
42
|
+
分类
|
43
|
+
</HairyUserStats>
|
44
|
+
<div class="w-1px bg-gray bg-opacity-50" />
|
45
|
+
<HairyUserStats :count="tags.size" @click="navigation('/tags/')">
|
46
|
+
标签
|
47
|
+
</HairyUserStats>
|
48
|
+
</div>
|
49
|
+
<HairySocialLinks class="mt-5" />
|
50
|
+
<HairyMenu class="HairyUserMenu mt-5 flex-col h-auto" />
|
51
|
+
</template>
|
52
|
+
|
53
|
+
<style lang="scss">
|
54
|
+
.HairyUserMenu {
|
55
|
+
display: flex;
|
56
|
+
flex-direction: column;
|
57
|
+
gap: 6px;
|
58
|
+
.HairyMenuItem {
|
59
|
+
padding: 2px;
|
60
|
+
width: 100%;
|
61
|
+
border: 1px solid transparent;
|
62
|
+
border-radius: 10px;
|
63
|
+
transition: all 0.2s;
|
64
|
+
background-color: transparent;
|
65
|
+
user-select: none;
|
66
|
+
> div {
|
67
|
+
justify-content: center;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
.HairyMenuItem:hover,
|
72
|
+
.HairyMenuItem.active {
|
73
|
+
background-color: #f4f4f5;
|
74
|
+
}
|
75
|
+
.HairyMenuItem:active {
|
76
|
+
background-color: #efefef;
|
77
|
+
}
|
78
|
+
|
79
|
+
.HairyMenuItem.active + .HairyMenuItem {
|
80
|
+
border-top-color: transparent;
|
81
|
+
}
|
82
|
+
.HairyMenuItem:hover + .HairyMenuItem {
|
83
|
+
border-top-color: transparent;
|
84
|
+
}
|
85
|
+
}
|
86
|
+
.dark .HairyUserMenu {
|
87
|
+
.HairyMenuItem:hover,
|
88
|
+
.HairyMenuItem.active {
|
89
|
+
background-color: #f4f4f50a;
|
90
|
+
}
|
91
|
+
.HairyMenuItem:active {
|
92
|
+
background-color: #f4f4f521;
|
93
|
+
}
|
94
|
+
}
|
95
|
+
</style>
|
@@ -1,18 +1,18 @@
|
|
1
|
-
<script lang="ts" setup>
|
2
|
-
defineProps<{
|
3
|
-
count?: number
|
4
|
-
}>()
|
5
|
-
</script>
|
6
|
-
|
7
|
-
<template>
|
8
|
-
<div class="flex-center flex-col cursor-pointer hover:text-primary px-3 py-1">
|
9
|
-
<div class="font-bold leading-none">
|
10
|
-
{{ count || 0 }}
|
11
|
-
</div>
|
12
|
-
<div class="leading-none mt-1">
|
13
|
-
<slot />
|
14
|
-
</div>
|
15
|
-
</div>
|
16
|
-
</template>
|
17
|
-
|
18
|
-
<style lang="scss" scoped></style>
|
1
|
+
<script lang="ts" setup>
|
2
|
+
defineProps<{
|
3
|
+
count?: number
|
4
|
+
}>()
|
5
|
+
</script>
|
6
|
+
|
7
|
+
<template>
|
8
|
+
<div class="flex-center flex-col cursor-pointer hover:text-primary px-3 py-1">
|
9
|
+
<div class="font-bold leading-none">
|
10
|
+
{{ count || 0 }}
|
11
|
+
</div>
|
12
|
+
<div class="leading-none mt-1">
|
13
|
+
<slot />
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
</template>
|
17
|
+
|
18
|
+
<style lang="scss" scoped></style>
|