Quellcode durchsuchen

feat(PostCard): 添加标签云组件和日期格式化功能

- 新增 TagCloud 组件用于展示文章标签,支持点击事件和暗色模式适配
- 添加日期格式化工具函数 formateDateAccurateToDay
- 移除 PostCard 中旧的标签样式,改用新的 TagCloud 组件
- 添加颜色处理工具 lightenHexColor 用于暗色模式下标签颜色调整
Sakulin vor 2 Monaten
Ursprung
Commit
929be39e0c
3 geänderte Dateien mit 102 neuen und 12 gelöschten Zeilen
  1. 8 12
      src/components/PostCard.vue
  2. 55 0
      src/components/TagCloud.vue
  3. 39 0
      src/utils/index.ts

+ 8 - 12
src/components/PostCard.vue

@@ -1,21 +1,26 @@
 <script setup lang="ts">
 import type { PostSketch } from '@/models'
+import TagCloud from './TagCloud.vue'
+import { formateDateAccurateToDay } from '@/utils'
 
 const props = defineProps<{
   target: PostSketch
-}>()
+}>();
+
+
 </script>
 
 <template>
   <div class="post-item">
     <h2 class="title">{{ props.target.title }}</h2>
     <div class="meta">
-      <span class="date">{{ props.target.createdAt }}</span>
+      <span class="date">{{ formateDateAccurateToDay(props.target.createdAt) }}</span>
       <span class="cate">日志</span>
     </div>
     <p>
       {{ props.target.description }}
     </p>
+    <TagCloud :tags="props.target.tags" />
   </div>
 </template>
 
@@ -98,14 +103,5 @@ const props = defineProps<{
   opacity: 0.7;
 }
 
-/* tagcloud */
-.post-item .tag-cloud a {
-  color: inherit;
-  border: 1px solid;
-  border-radius: 50px;
-  padding: 0 16px;
-  display: inline-block;
-  margin: 3px 0;
-  margin-right: 6px;
-}
+
 </style>

+ 55 - 0
src/components/TagCloud.vue

@@ -0,0 +1,55 @@
+<script setup lang="ts">
+import type { Tag } from '@/models'
+import { lightenHexColor } from '@/utils/'
+
+const props = defineProps<{
+  tags: Tag[]
+  onClick?: (tag: Tag) => void
+}>()
+
+function handleClick(tag: Tag) {
+  if (props.onClick) {
+    props.onClick(tag)
+  }
+}
+
+function getColorStyle(tag: Tag) {
+  let color = tag.color;
+
+  if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
+    color = lightenHexColor(color);
+  }
+
+  return {
+    color: color,
+    borderColor: color,
+  }
+}
+</script>
+
+<template>
+  <div>
+    <div
+      class="tag"
+      v-for="tag in props.tags"
+      :key="tag.id"
+      @click="handleClick(tag)"
+      :style="getColorStyle(tag)"
+    >
+      {{ tag.name }}
+    </div>
+  </div>
+</template>
+
+<style scoped>
+.tag {
+  color: inherit;
+  border: 1px solid;
+  border-radius: 50px;
+  padding: 0 16px;
+  display: inline-block;
+  margin: 3px 0;
+  margin-right: 6px;
+  cursor: pointer;
+}
+</style>

+ 39 - 0
src/utils/index.ts

@@ -0,0 +1,39 @@
+/**
+ * 将类似 #123456 的十六进制颜色字符串变亮
+ * @param hexColor - 十六进制颜色字符串,格式为 #RRGGBB
+ * @param percent - 变亮的百分比,范围从 0 到 100,默认值为 20
+ * @returns 变亮后的十六进制颜色字符串
+ */
+export function lightenHexColor(hexColor: string, percent: number = 20): string {
+  // 去除颜色字符串前面的 # 符号
+  const color = hexColor.replace('#', '')
+  // 将颜色字符串转换为 RGB 分量
+  let r = parseInt(color.substring(0, 2), 16)
+  let g = parseInt(color.substring(2, 4), 16)
+  let b = parseInt(color.substring(4, 6), 16)
+
+  // 计算变亮后的 RGB 分量
+  r = Math.min(255, Math.round(r + (255 - r) * (percent / 100)))
+  g = Math.min(255, Math.round(g + (255 - g) * (percent / 100)))
+  b = Math.min(255, Math.round(b + (255 - b) * (percent / 100)))
+
+  // 将 RGB 分量转换回十六进制字符串
+  const toHex = (c: number) => {
+    const hex = c.toString(16)
+    return hex.length === 1 ? '0' + hex : hex
+  }
+
+  return '#' + toHex(r) + toHex(g) + toHex(b)
+}
+
+export function formateDateAccurateToDay(date: Date | string | number): string {
+  const _date = new Date(date)
+  const year = _date.getFullYear()
+  const month = _date.getMonth() + 1
+  const day = _date.getDate()
+  if (year !== new Date().getFullYear()) {
+    return `${year} 年 ${month} 月 ${day} 日`
+  } else {
+    return `${month} 月 ${day} 日`
+  }
+}