From b3038603e8f452f8eaff55fd2bd35a43f51fccae Mon Sep 17 00:00:00 2001 From: xy <10816187@qq.com> Date: Fri, 14 Aug 2026 21:08:45 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E5=86=99filter=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=20=E6=9B=B4=E6=96=B0=E4=B8=BAsearch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/IndexSidebar.astro | 4 +- src/components/IndexView.astro | 20 +- .../{PostList.astro => Post/Item.astro} | 145 ++--- src/components/Post/List.astro | 31 ++ src/components/Post/Pagination.astro | 60 +++ src/pages/filter.astro | 505 ------------------ src/pages/post/[...slug].astro | 2 +- src/pages/search.astro | 202 +++++++ src/types/post.ts | 3 +- tsconfig.json | 2 +- 10 files changed, 350 insertions(+), 624 deletions(-) rename src/components/{PostList.astro => Post/Item.astro} (50%) create mode 100644 src/components/Post/List.astro create mode 100644 src/components/Post/Pagination.astro delete mode 100644 src/pages/filter.astro create mode 100644 src/pages/search.astro diff --git a/src/components/IndexSidebar.astro b/src/components/IndexSidebar.astro index 55134ad..9d6a3a9 100644 --- a/src/components/IndexSidebar.astro +++ b/src/components/IndexSidebar.astro @@ -23,7 +23,7 @@ const { data: tags } = categories.map((category) => (
  • {category.name} @@ -45,7 +45,7 @@ const { data: tags } = tags.map((tag) => ( {tag.name} diff --git a/src/components/IndexView.astro b/src/components/IndexView.astro index b4522c8..7d8178a 100644 --- a/src/components/IndexView.astro +++ b/src/components/IndexView.astro @@ -1,7 +1,8 @@ --- -import type { Post } from "@/types/post"; +import type {Post} from "@/types/post"; import IndexSidebar from "@/components/IndexSidebar.astro"; -import PostList from "@/components/PostList.astro"; +import PostList from "@/components/Post/List.astro"; +import Pagination from "@/components/Post/Pagination.astro"; interface Props { posts: Post[]; @@ -9,13 +10,16 @@ interface Props { totalPage: number; } -const { posts, page, totalPage } = Astro.props; +const {posts, page, totalPage} = Astro.props; ---
    - - +
    + + +
    +
    @@ -26,6 +30,12 @@ const { posts, page, totalPage } = Astro.props; gap: 28px; } + .post-container{ + display: flex; + flex-direction: column; + gap: 32px; + } + @media (max-width: 860px) { .container { flex-direction: column; diff --git a/src/components/PostList.astro b/src/components/Post/Item.astro similarity index 50% rename from src/components/PostList.astro rename to src/components/Post/Item.astro index 5cf68e9..d806112 100644 --- a/src/components/PostList.astro +++ b/src/components/Post/Item.astro @@ -1,88 +1,54 @@ --- +import type {Post} from '@/types'; import Eye from "@/assets/icon/eye.png?url"; import Folder from "@/assets/icon/folder.png?url"; import Calendar from "@/assets/icon/calendar.png?url"; -import type {Post} from "@/types/post"; -import {formatDatetime} from "@/lib/format.ts"; import LazyImage from "@/components/LazyImage.astro"; +import {formatDatetime} from "@/lib/format.ts"; interface Props { - posts: Post[] - page: number - totalPage: number + post: Post } -const {posts, page, totalPage} = Astro.props - -posts.map((post) => { - post.published_at = formatDatetime(post.published_at, 'YYYY-MM-DD') -}) +const {post} = Astro.props; +const published_at = formatDatetime(post.published_at, 'YYYY-MM-DD') --- -
    -
    - {posts.map(post => ( - -
    -
    - -
    -
    - - - - {totalPage > 1 && - } -
    + +

    + {post.title} +

    +
    + {post.summary} +
    +
    + {post.tags.map(tag => +
    {tag.name}
    )} +
    + + + diff --git a/src/components/Post/List.astro b/src/components/Post/List.astro new file mode 100644 index 0000000..3fc0dee --- /dev/null +++ b/src/components/Post/List.astro @@ -0,0 +1,31 @@ +--- +import type {Post} from "@/types/post"; +import PostItem from '@/components/Post/Item.astro' + +interface Props { + posts: Post[] +} + +const {posts} = Astro.props +--- + +
    +
    + {posts.map(post => ( + + ))} +
    +
    + + diff --git a/src/components/Post/Pagination.astro b/src/components/Post/Pagination.astro new file mode 100644 index 0000000..3d8f61b --- /dev/null +++ b/src/components/Post/Pagination.astro @@ -0,0 +1,60 @@ +--- +interface Props { + page: number + totalPage: number +} + +const {page, totalPage} = Astro.props +--- + + +{totalPage > 1 && +} + + diff --git a/src/pages/filter.astro b/src/pages/filter.astro deleted file mode 100644 index 0a404cc..0000000 --- a/src/pages/filter.astro +++ /dev/null @@ -1,505 +0,0 @@ ---- -import Layout from "@/layouts/Layout.astro"; -import Calendar from "@/assets/icon/calendar.png?url"; -import Eye from "@/assets/icon/eye.png?url"; -import Folder from "@/assets/icon/folder.png?url"; -import { formatDatetime } from "@/lib/format.ts"; -import { createHttp } from "@/lib/request"; -import type { CategoriesStats, Post, Tag } from "@/types"; -import LazyImage from "@/components/LazyImage.astro"; - -const http = createHttp(Astro.request.headers); - -const searchParams = Astro.url.searchParams; -const type = searchParams.get("type") ?? ""; -const code = searchParams.get("code") ?? ""; - -/** - * 搜索接口返回结构:tags 为 base64 编码的 JSON 字符串、 - * 阅读数字段为 views,且不含 cover / content,这里做归一化 - */ -type SearchPost = Omit & { - views: number; - tags: string; - cover?: string; - content?: string; -}; - -const decodeTags = (raw: string): Tag[] => { - try { - return JSON.parse(Buffer.from(raw, "base64").toString("utf8")) as Tag[]; - } catch { - return []; - } -}; - -const normalizePost = (post: SearchPost): Post => ({ - ...post, - view: post.views, - tags: decodeTags(post.tags), - cover: post.cover ?? "", - content: post.content ?? "", -}); - -const [{ data: categories }, { data: allTags }, { data: rawPosts }] = await Promise.all([ - http.get>("categories/stats"), - http.get>("posts/tags"), - http.get>("posts/search", { - searchParams: { - category_code: type === "category" ? code : "", - tag_code: type === "tag" ? code : "", - }, - }), -]); - -const searchPosts = rawPosts.map(normalizePost); - -const category = - type === "category" ? categories.find((item) => item.code === code) : undefined; - -/** 展示全部标签,按名称排序 */ -const tags = [...allTags].sort((a, b) => a.name.localeCompare(b.name, "zh-CN")); - -const tag = type === "tag" ? tags.find((item) => item.code === code) : undefined; -const valid = Boolean(category || tag); - -const posts = searchPosts; - -const filterLabel = category ? "分类" : tag ? "标签" : ""; -const filterTitle = category?.name ?? tag?.name ?? ""; -const count = category ? category.post_count : posts.length; - -const pageTitle = valid ? `${filterLabel}:${filterTitle}` : "筛选"; -const pageDescription = valid - ? `${filterLabel}「${filterTitle}」下的文章,共 ${count} 篇` - : "按分类或标签筛选文章"; - -const filterUrl = (type: string, code: string) => - `/filter?type=${type}&code=${encodeURIComponent(code)}`; - -const isActive = (targetType: string, targetCode: string) => - type === targetType && code === targetCode; ---- - - -
    -
    -
    - { - valid ? ( - <> - {filterLabel} -

    {filterTitle}

    - 共 {count} 篇 - - ) : ( - <> -

    未找到该筛选条件

    -

    请从下方分类或标签进入

    - - ) - } - 返回首页 -
    - - - - { - valid && - (posts.length > 0 ? ( - - ) : ( -
    -

    无数据

    -
    - )) - } -
    -
    -
    - - diff --git a/src/pages/post/[...slug].astro b/src/pages/post/[...slug].astro index 432c2e3..416ab79 100644 --- a/src/pages/post/[...slug].astro +++ b/src/pages/post/[...slug].astro @@ -69,7 +69,7 @@ const published_at = formatDatetime(data.published_at, "YYYY 年 M 月 D 日"); d="M509.618 415.795c-42.695 0-77.253 38.372-77.253 85.738 0 47.352 34.558 86.22 77.253 86.22 42.667 0 76.716-38.867 76.716-86.22 0-47.352-34.049-85.738-76.716-85.738z m1.9-177.9c-211.548 0-383.265 159.859-383.265 274.587 0 114.727 171.717 273.624 383.266 273.624 212.484 0 384.227-162.522 384.227-273.624 0-111.088-171.743-274.587-384.227-274.587z m-1.446 452.006c-89.7 0-162.134-81.71-162.134-181.903 0-101.157 72.435-182.397 162.134-182.397 90.183 0 163.1 81.241 163.1 182.397 0 100.206-72.917 181.903-163.1 181.903z" p-id="5123"> - {data.view} + {data.view_count} diff --git a/src/pages/search.astro b/src/pages/search.astro new file mode 100644 index 0000000..518bf50 --- /dev/null +++ b/src/pages/search.astro @@ -0,0 +1,202 @@ +--- +import Layout from '@/layouts/Layout.astro' +import type {CategoriesStats, Post, Tag} from "@/types"; +import {createHttp} from "@/lib/request.ts"; +import PostList from "@/components/Post/List.astro"; + +const http = createHttp(Astro.request.headers); + +const searchParams = Astro.url.searchParams; +const t = searchParams.get("t") ?? ""; +const c = searchParams.get("c") ?? ""; + +const [{data: categories}, {data: tags}, {data: posts}] = await Promise.all([ + http.get>("categories/stats"), + http.get>("posts/tags"), + http.get>("posts/search", { + searchParams: { + category_code: c ?? "", + tag_code: t ?? "", + } + }), +] as const) + +let f_count = 0 +const findCategory = categories.find(item => { + if (item.code === c) { + f_count++ + } + return item.code === c +}) + +const findTag = tags.find(item => { + if (item.code === t) { + f_count++ + } + return item.code === t +}) + +const count = posts.length + +const pageTitle = + f_count === 0 ? "所有文章" : [findCategory?.name, findTag?.name,] + .filter(Boolean) + .join(" · ") + +const pageDescription = + f_count === 0 + ? "浏览全部文章,按分类和标签筛选你感兴趣的内容。" + : `浏览${pageTitle}相关文章,共 ${count} 篇。` + +const buildSearchUrl = (type: 'category' | 'tag', code: string) => { + const params = { + t: t, + c: c, + } + + if (type === 'category') { + params.c = c === code ? "" : code + } else { + params.t = t === code ? "" : code + } + + const searchParams = new URLSearchParams( + Object.entries(params).filter(([, value]) => value !== '') + ); + + const query = searchParams.toString(); + + return query ? `/search?${query}` : '/search'; +} +--- + +
    +
    +

    + {pageTitle} +

    +
    {count}
    +
    + +
    + + + +
    + + {posts.length > 0 ? + : +
    没有找到相关文章
    } +
    +
    + + + diff --git a/src/types/post.ts b/src/types/post.ts index 4f9276c..ac9e139 100644 --- a/src/types/post.ts +++ b/src/types/post.ts @@ -3,6 +3,7 @@ export type Tag = { code: string name: string } + export type Post = { title: string; summary: string; @@ -12,7 +13,7 @@ export type Post = { category_code: string; category_id?: number; published_at: string; - view: number; + view_count: number; content: string; tags: Tag[] } diff --git a/tsconfig.json b/tsconfig.json index 6730ec2..806bbd6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,4 +17,4 @@ "jsx": "preserve", "jsxImportSource": "solid-js" } -} \ No newline at end of file +}