Typecho CF 添加标签总览页

本站基于 Typecho CF 搭建,默认主题没有标签总览页,所有标签只能逐个点开。本文记录如何新增一个 /tag/ 标签总览页,以彩色标签云展示。

一、新建页面文件

在 src/pages/tag/ 目录下新建 index.astro。该目录下已存在 [slug].astro(用于单个标签页 /tag/xxx/),而 index.astro 优先级更高,两者不冲突。

---
import Base from '@/layouts/Base.astro';
import { createContext } from '@/lib/context';
import { prepareIndexData } from '@/lib/page-data';
import { schema } from '@/db';
import { eq } from 'drizzle-orm';

const ctx = await createContext(Astro.locals, Astro.request); const { db, options, urls, user, isLoggedIn, pluginCtx } = ctx;

const data = await prepareIndexData(ctx, Astro.request.url, Astro.locals, Astro.url); const pages = data?.pages; const sidebarData = data?.sidebarData;

const allTags = await db .select({ mid: schema.metas.mid, name: schema.metas.name, slug: schema.metas.slug, }) .from(schema.metas) .where(eq(schema.metas.type, 'tag'));

const relationships = await db .select({ mid: schema.relationships.mid, cid: schema.relationships.cid, }) .from(schema.relationships);

const tagCountMap = {}; relationships.forEach((r) => { tagCountMap[r.mid] = (tagCountMap[r.mid] || 0) + 1; });

const tagsWithColor = allTags.map((tag) => { const count = tagCountMap[tag.mid] || 0; let hash = 0; const name = tag.name || ''; for (let i = 0; i < name.length; i++) { hash = name.charCodeAt(i) + ((hash << 5) - hash); } const hue = Math.abs(hash) % 360; return { ...tag, count, bgColor: hsl(${hue}, 70%, 92%), textColor: hsl(${hue}, 65%, 35%), };

});

二、彩色标签云展示

页面主体用 flex 布局,把标签渲染成彩色圆角药丸:

<div class="tag-cloud">
  {tagsWithColor.map((tag) => (
    <a
      href={`${urls.siteUrl}/tag/${tag.slug}/`}
      class="tag-pill"
      style={`background: ${tag.bgColor}; color: ${tag.textColor};`}
    >
      {tag.name}
      <span>({tag.count})</span>
    </a>
  ))}
</div>

配套样式:

.tag-cloud {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding: 20px 0;
}
.tag-pill {
  display: inline-block;
  padding: 6px 14px;
  border-radius: 999px;
  text-decoration: none;
  font-size: 14px;
  transition: all 0.2s;
}
.tag-pill:hover {
  transform: translateY(-2px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

三、修改 [slug].astro

打开 src/pages/tag/[slug].astro,找到这一行:

if (!slug) return Astro.redirect('/');

因为 index.astro 会优先匹配 /tag/,这行重定向已经用不到,注释掉即可:

// if (!slug) return Astro.redirect('/');

四、加入导航栏

在 src/pages/archive.astro 和 src/themes/typocho-theme-note/components/Archive.astro 的导航栏里加一行:

<a href={urls.siteUrl + '/tag/'}>标签</a>

五、最终效果

访问 https://hbw.me/tag/:

  • 所有标签以彩色药丸展示
  • 每个标签带文章数
  • 颜色按标签名哈希生成,同名标签颜色稳定
  • 点击进入对应标签页 /tag/xxx/

导航栏也加入「标签」按钮,方便访问。

标签: 主题, tag

添加新评论