valaxy-theme-hairy 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,17 +1,30 @@
1
1
  <script lang="ts" setup>
2
2
  import { useFrontmatter } from 'valaxy'
3
- import { computed } from 'vue'
3
+ import { computed, inject, nextTick, ref } from 'vue'
4
+ import { useRouter } from 'vue-router'
4
5
  import { toArr } from '../utils'
5
6
  import { useCurrentCategory } from '../hooks/useCategory'
6
7
 
7
8
  const frontmatter = useFrontmatter()
8
9
  const paths = computed(() => toArr(frontmatter.value.categories).filter(Boolean) as string[])
9
10
  const category = useCurrentCategory(paths)
10
- const posts = computed(() => category.value.posts || [])
11
+ const posts = computed(() => {
12
+ const result = category.value.posts || []
13
+ return result.sort((a, b) => (a.date || 1) > (b.date || 1) ? 1 : -1)
14
+ })
15
+ const router = useRouter()
16
+
17
+ const active = inject('HairyUserTab:active', ref(''))
11
18
 
12
19
  function isCurrent(title = '') {
13
20
  return frontmatter.value.title === title
14
21
  }
22
+
23
+ async function changePost(path = '') {
24
+ router.push(path)
25
+ await nextTick()
26
+ active.value = 'aside'
27
+ }
15
28
  </script>
16
29
 
17
30
  <template>
@@ -20,7 +33,7 @@ function isCurrent(title = '') {
20
33
  On this Series
21
34
  </div>
22
35
  <ul class="va-toc relative z-1">
23
- <a v-for="(item, index) of posts" :key="index" class="va-toc-item" @click="$router.push(item.path || '')">
36
+ <a v-for="(item, index) of posts" :key="index" class="va-toc-item" @click="changePost(item.path)">
24
37
  <a class="outline-link" :class="[isCurrent(item.title) && 'active']">{{ index + 1 }}.{{ item.title }}</a>
25
38
  </a>
26
39
  </ul>
@@ -1,24 +1,51 @@
1
1
  <script lang="ts" setup>
2
- import type { Ref } from 'vue'
3
- import { computed } from 'vue'
2
+ import { computed, defineProps, ref, withDefaults } from 'vue'
4
3
  import type { Post } from 'valaxy'
5
4
  import { usePostList } from 'valaxy'
5
+ import { usePostLayout } from '../hooks/usePostLayout'
6
6
 
7
7
  const props = withDefaults(defineProps<{
8
8
  type?: string
9
9
  posts?: Post[]
10
+ curPage?: number
11
+ pagination?: boolean
10
12
  }>(), {
13
+ curPage: 1,
14
+ pagination: false,
11
15
  })
16
+ const layout = usePostLayout()
12
17
 
13
- const routes = usePostList() as any as Ref<Post[]>
14
- const posts = computed(() => props.posts || routes.value)
18
+ const pageSize = ref(7)
19
+ const routes = usePostList({ type: props.type || '' })
20
+ const posts = computed<any[]>(() => props.posts || routes.value)
21
+ const pagePosts = computed(() => posts.value.slice((props.curPage - 1) * pageSize.value, props.curPage * pageSize.value))
22
+ const displayedPosts = computed(() => props.pagination ? pagePosts.value : posts.value)
15
23
  </script>
16
24
 
17
25
  <template>
18
- <ul class="divide-y divide-gray-200 dark:divide-gray-700">
19
- <Transition v-for="post, i in posts" :key="i" name="fade">
20
- <HairyArticleText :post="post" />
21
- </Transition>
22
- </ul>
26
+ <HairyPostImageList v-if="layout.includes('image')" :posts="displayedPosts" />
27
+ <HairyPostTextsList v-else :posts="displayedPosts" />
28
+ <ValaxyPagination v-if="pagination" :cur-page="curPage" :page-size="pageSize" :total="posts.length" />
23
29
  </template>
24
30
 
31
+ <style lang="scss">
32
+ .pagination {
33
+ font-size: 16px;
34
+ }
35
+
36
+ .pagination .prev.active,
37
+ .pagination .next.active,
38
+ .pagination .page-number.active {
39
+ font-weight: normal;
40
+ background: transparent;
41
+ color: var(--hy-c-primary);
42
+ cursor: default;
43
+ }
44
+
45
+ .pagination .prev:hover,
46
+ .pagination .next:hover,
47
+ .pagination .page-number:hover {
48
+ color: var(--va-c-bg);
49
+ background: rgba(143, 230, 213, 0.8);
50
+ }
51
+ </style>
@@ -0,0 +1,23 @@
1
+ <script lang="ts" setup>
2
+ import type { Ref } from 'vue'
3
+ import { computed } from 'vue'
4
+ import type { Post } from 'valaxy'
5
+ import { usePostList } from 'valaxy'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ type?: string
9
+ posts?: Post[]
10
+ }>(), {})
11
+
12
+ const routes = usePostList() as any as Ref<Post[]>
13
+ const posts = computed(() => props.posts || routes.value)
14
+ </script>
15
+
16
+ <template>
17
+ <ul class="divide-y divide-gray-200 dark:divide-gray-700">
18
+ <Transition v-for="post, i in posts" :key="i" name="fade">
19
+ <HairyArticleText :post="post" />
20
+ </Transition>
21
+ </ul>
22
+ </template>
23
+
@@ -1,8 +1,23 @@
1
1
  <script lang="ts" setup>
2
- import { useCategory, usePostList, useTag } from 'valaxy'
3
- const category = useCategory()
2
+ import { usePostList, useTag } from 'valaxy'
3
+ import { computed } from 'vue'
4
+ import { toArr } from '../utils'
4
5
  const posts = usePostList()
5
6
  const tags = useTag()
7
+
8
+ const total = computed(() => {
9
+ const categories = posts.value.map(v => toArr(v.categories || [])).filter(v => v.length)
10
+ const maps: string[] = []
11
+ for (const category of categories) {
12
+ let caches: string[] = []
13
+ for (const iterator of category) {
14
+ caches.push(iterator)
15
+ maps.push(caches.join('-'))
16
+ }
17
+ caches = []
18
+ }
19
+ return new Set(maps).size
20
+ })
6
21
  </script>
7
22
 
8
23
  <template>
@@ -11,7 +26,7 @@ const tags = useTag()
11
26
  文章
12
27
  </HairyUserStats>
13
28
  <div class="w-1px bg-gray bg-opacity-50" />
14
- <HairyUserStats :count="category.total" @click="$router.push('/categories/')">
29
+ <HairyUserStats :count="total" @click="$router.push('/categories/')">
15
30
  分类
16
31
  </HairyUserStats>
17
32
  <div class="w-1px bg-gray bg-opacity-50" />
@@ -2,9 +2,9 @@
2
2
  import { ElTabPane, ElTabs } from 'element-plus/es/components/tabs/index'
3
3
  import 'element-plus/es/components/tabs/style/index'
4
4
  import 'element-plus/es/components/tab-pane/style/index'
5
- import { ref } from 'vue'
6
-
5
+ import { provide, ref } from 'vue'
7
6
  const active = ref('aside')
7
+ provide('HairyUserTab:active', active)
8
8
  </script>
9
9
 
10
10
  <template>
@@ -27,17 +27,21 @@ export function useYearArchives() {
27
27
  const [year, month] = [days.format('YYYY'), days.format('MM')]
28
28
  if (!maps[year])
29
29
  maps[year] = {}
30
- if (!maps[year][month]) { maps[year][month] = { count: 1, posts: [post] } }
30
+ if (!maps[year][month]) { maps[year][month] = { count: 1, posts: [post as any] } }
31
31
  else {
32
32
  maps[year][month].count++
33
- maps[year][month].posts.push(post)
33
+ maps[year][month].posts.unshift(post as any)
34
34
  }
35
35
  }
36
36
  for (const [year, months] of Object.entries(maps)) {
37
37
  for (const [month, { count, posts }] of Object.entries(months))
38
- items.push({ year, month, count, posts })
38
+ items.unshift({ year, month, count, posts })
39
39
  }
40
- return items
40
+ return items.sort((a, b) => {
41
+ const aTime = `${a.year}-${a.month}`
42
+ const bTime = `${b.year}-${b.month}`
43
+ return bTime > aTime ? 1 : -1
44
+ })
41
45
  })
42
46
  return archives
43
47
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valaxy-theme-hairy",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
4
4
  "packageManager": "pnpm@7.5.0",
5
5
  "author": {
6
6
  "email": "wwu710632@gmail.com",
@@ -33,7 +33,6 @@ const post = computed(() => months.value.flatMap(item => item.posts))
33
33
  {{ month }}月
34
34
  </HairyBreadcrumbItem>
35
35
  </HairyBreadcrumb>
36
-
37
36
  <el-timeline>
38
37
  <el-timeline-item
39
38
  v-for="(item, index) in post"
@@ -26,15 +26,21 @@ const posts = usePostList()
26
26
  size="large"
27
27
  >
28
28
  <div class="activity inline-flex items-center">
29
- <HairyLink @click="$router.push(getArchiveLink(activity.year))">
29
+ <HairyLink class="text-size-8" @click="$router.push(getArchiveLink(activity.year))">
30
30
  {{ activity.year }}
31
31
  </HairyLink>
32
- <span class="text-gray-5 text-size-5 mx-2">/</span>
33
- <HairyLink @click="$router.push(getArchiveLink(activity.year, activity.month))">
32
+ <span class="text-gray-5 mx-2">/</span>
33
+ <HairyLink class="text-size-8" @click="$router.push(getArchiveLink(activity.year, activity.month))">
34
34
  {{ activity.month }}
35
35
  </HairyLink>
36
36
  <span class="text-gray-5 text-size-5 ml-1">({{ activity.count }}篇)</span>
37
37
  </div>
38
+ <HairyTimelinePostItem v-for="(item, index) in activity.posts.slice(0, 2)" :key="index" :post="item" />
39
+ <div v-if="activity.posts.length > 2">
40
+ <HairyLink @click="$router.push(getArchiveLink(activity.year))">
41
+ ....
42
+ </HairyLink>
43
+ </div>
38
44
  </el-timeline-item>
39
45
  </el-timeline>
40
46
  </template>
@@ -22,18 +22,20 @@ const router = useRouter()
22
22
 
23
23
  const paths = computed(() => props.categories.split('/').filter(Boolean))
24
24
  const current = useCurrentCategory(paths)
25
-
26
25
  const posts = useCategoryPost(paths)
27
26
 
28
27
  const i18n = useI18n()
29
28
 
29
+ const s = '/'
30
+
30
31
  const getBreadcrumbPath = (index: number) => {
31
- if (paths.value[index] === paths.value[paths.value.length - 1])
32
+ const paths = props.categories.split('/').filter(Boolean)
33
+ if (paths[index] === paths[paths.length - 1])
32
34
  return ''
33
- return `/categories/${paths.value.slice(0, index)}`
35
+ return `/categories/${paths.slice(0, index + 1).join('/')}`
34
36
  }
35
37
  const displayCategory = (key: string) => {
36
- router.push({ path: `/categories/${[...paths.value, key].join('/')}` })
38
+ router.push({ path: `/categories/${[key, ...paths.value].reverse().join('/')}` })
37
39
  }
38
40
  </script>
39
41
 
@@ -45,10 +47,11 @@ const displayCategory = (key: string) => {
45
47
  <HairyBreadcrumbItem :to="paths.length && '/categories/' || ''">
46
48
  全部
47
49
  </HairyBreadcrumbItem>
48
- <HairyBreadcrumbItem v-for="(key, index) in paths" :key="key" :to="getBreadcrumbPath(index)">
50
+ <HairyBreadcrumbItem v-for="(key, index) in categories.split(s)" :key="key" :to="getBreadcrumbPath(index)">
49
51
  {{ i18n.t(key) }}
50
52
  </HairyBreadcrumbItem>
51
53
  </HairyBreadcrumb>
54
+
52
55
  <div class="grid__view dark:text-gray-3 flex-wrap">
53
56
  <template v-for="([key, item]) in current.children" :key="key">
54
57
  <div
package/pages/index.vue CHANGED
@@ -1,11 +1,5 @@
1
- <script lang="ts" setup>
2
- import { usePostLayout } from '../hooks/usePostLayout'
3
- const layout = usePostLayout()
4
- </script>
5
-
6
1
  <template>
7
- <HairyPostImageList v-if="layout.includes('image')" />
8
- <HairyPostList v-else />
2
+ <HairyPostList :pagination="true" />
9
3
  </template>
10
4
 
11
5
  <route lang="yaml">
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ defineProps<{ page: string }>()
3
+ </script>
4
+
5
+ <template>
6
+ <HairyPostList :pagination="true" :cur-page="parseInt(page)" />
7
+ </template>
8
+
9
+ <route lang="yaml">
10
+ meta:
11
+ layout: home
12
+ </route>
@@ -4,7 +4,7 @@ import { useRouter } from 'vue-router'
4
4
  const router = useRouter()
5
5
 
6
6
  const { tags, getTagStyle } = useTags({
7
- primary: 'red',
7
+ primary: '#1bc9a6',
8
8
  })
9
9
 
10
10
  const displayTag = (tag: string) => {
@@ -17,7 +17,7 @@ const displayTag = (tag: string) => {
17
17
  <div text="center" class="text-size-2.5em pt-10 mb-5">
18
18
  目前共计 {{ Array.from(tags).length }} 个标签
19
19
  </div>
20
- <div text="center">
20
+ <div text="center" class="max-w-7xl flex flex-wrap justify-center items-center gap-2">
21
21
  <a v-for="[key, tag] in Array.from(tags).sort()" :key="key" class="post-tag cursor-pointer" :style="getTagStyle(tag.count)" p="1" @click="displayTag(key.toString())">
22
22
  {{ key }}
23
23
  </a>
@@ -29,3 +29,13 @@ const displayTag = (tag: string) => {
29
29
  meta:
30
30
  layout: tags
31
31
  </route>
32
+
33
+ <style lang="scss" scoped>
34
+ a {
35
+ color: var(--yun-tag-color);
36
+ &:hover {
37
+ --un-text-opacity: 1;
38
+ color: var(--hy-c-primary-dark);
39
+ }
40
+ }
41
+ </style>