From 7b8358005f9a5baf0ce25cd618ad54789647f9de Mon Sep 17 00:00:00 2001 From: seaHi Date: Wed, 7 Oct 2026 12:30:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=9C=A8=E5=90=8E?= =?UTF-8?q?=E5=8F=B0=E6=A0=87=E7=AD=BE=E9=A1=B5=E9=9D=A2=E9=80=9A=E8=BF=87?= =?UTF-8?q?=E7=82=B9=E5=87=BB=E6=96=87=E7=AB=A0=E6=95=B0=E9=87=8F=E6=8C=89?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E7=AD=9B=E9=80=89=E6=96=87=E7=AB=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/admin/posts/+page.server.ts | 103 +++++++++++++++++++------ src/routes/admin/posts/+page.svelte | 51 +++++++++++- src/routes/admin/tags/+page.svelte | 32 +++++++- 3 files changed, 159 insertions(+), 27 deletions(-) diff --git a/src/routes/admin/posts/+page.server.ts b/src/routes/admin/posts/+page.server.ts index b70d8d6..fd6fdf5 100644 --- a/src/routes/admin/posts/+page.server.ts +++ b/src/routes/admin/posts/+page.server.ts @@ -11,41 +11,93 @@ interface PostListRow { category?: string; series?: string; } -export const load: PageServerLoad = async ({ platform }) => { +export const load: PageServerLoad = async ({ url, platform }) => { const db = platform?.env?.DB; if (!db) { return { - posts: [] + posts: [], + filterTag: null }; } + const tagIdParam = url.searchParams.get('tagId'); + const tagId = tagIdParam ? parseInt(tagIdParam, 10) : null; + let filterTag: { id: number; name: string } | null = null; + + if (tagId && !Number.isNaN(tagId)) { + try { + const tagRes = await db + .prepare('SELECT id, name FROM tags WHERE id = ?') + .bind(tagId) + .first<{ id: number; name: string }>(); + if (tagRes) { + filterTag = tagRes; + } + } catch (err: any) { + console.error('Error fetching filter tag:', err); + } + } + try { let results: PostListRow[]; try { - const queryRes = await db - .prepare( - `SELECT p.id, p.title, p.slug, p.published_at as date, u.username as author, - c.name as category, s.name as series - FROM posts p - LEFT JOIN users u ON p.author_id = u.id - LEFT JOIN categories c ON p.category_id = c.id - LEFT JOIN series s ON p.series_id = s.id - ORDER BY p.published_at DESC` - ) - .all(); - results = queryRes.results; + if (filterTag) { + const queryRes = await db + .prepare( + `SELECT p.id, p.title, p.slug, p.published_at as date, u.username as author, + c.name as category, s.name as series + FROM posts p + INNER JOIN post_tags pt ON p.id = pt.post_id + LEFT JOIN users u ON p.author_id = u.id + LEFT JOIN categories c ON p.category_id = c.id + LEFT JOIN series s ON p.series_id = s.id + WHERE pt.tag_id = ? + ORDER BY p.published_at DESC` + ) + .bind(filterTag.id) + .all(); + results = queryRes.results; + } else { + const queryRes = await db + .prepare( + `SELECT p.id, p.title, p.slug, p.published_at as date, u.username as author, + c.name as category, s.name as series + FROM posts p + LEFT JOIN users u ON p.author_id = u.id + LEFT JOIN categories c ON p.category_id = c.id + LEFT JOIN series s ON p.series_id = s.id + ORDER BY p.published_at DESC` + ) + .all(); + results = queryRes.results; + } } catch (err: any) { // Fallback query if categories table or category_id column is missing - const queryRes = await db - .prepare( - `SELECT p.id, p.title, p.slug, p.published_at as date, u.username as author - FROM posts p - LEFT JOIN users u ON p.author_id = u.id - ORDER BY p.published_at DESC` - ) - .all(); - results = queryRes.results.map((r) => ({ ...r, category: '', series: '' })); + if (filterTag) { + const queryRes = await db + .prepare( + `SELECT p.id, p.title, p.slug, p.published_at as date, u.username as author + FROM posts p + INNER JOIN post_tags pt ON p.id = pt.post_id + LEFT JOIN users u ON p.author_id = u.id + WHERE pt.tag_id = ? + ORDER BY p.published_at DESC` + ) + .bind(filterTag.id) + .all(); + results = queryRes.results.map((r) => ({ ...r, category: '', series: '' })); + } else { + const queryRes = await db + .prepare( + `SELECT p.id, p.title, p.slug, p.published_at as date, u.username as author + FROM posts p + LEFT JOIN users u ON p.author_id = u.id + ORDER BY p.published_at DESC` + ) + .all(); + results = queryRes.results.map((r) => ({ ...r, category: '', series: '' })); + } } // Format date for display @@ -62,11 +114,12 @@ export const load: PageServerLoad = async ({ platform }) => { }); return { - posts: formattedPosts + posts: formattedPosts, + filterTag }; } catch (err: any) { console.error('Error fetching admin posts list:', err); - return { posts: [] }; + return { posts: [], filterTag }; } }; diff --git a/src/routes/admin/posts/+page.svelte b/src/routes/admin/posts/+page.svelte index 8998b30..5936c27 100644 --- a/src/routes/admin/posts/+page.svelte +++ b/src/routes/admin/posts/+page.svelte @@ -28,6 +28,17 @@ +{#if data.filterTag} +
+
+ 正在筛选{$page.data.aliases?.tag || '标签'}: + #{data.filterTag.name} + (共 {data.posts.length} 篇) +
+ +
+{/if} + {#if data.posts.length > 0}
{#if selectedIds.length > 0} @@ -66,7 +77,17 @@ {#if data.posts.length === 0}
-

还没有发布任何{$page.data.aliases?.post || '文章'}

+ {#if data.filterTag} +

+ {$page.data.aliases?.tag || '标签'} "{data.filterTag.name}" 下暂无关联{$page.data.aliases + ?.post || '文章'} +

+ + {:else} +

还没有发布任何{$page.data.aliases?.post || '文章'}

+ {/if}
{:else} @@ -197,4 +218,32 @@ text-decoration: underline; text-underline-offset: 4px; } + + .filter-banner { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + padding: 10px 16px; + background: rgba(0, 0, 0, 0.03); + border-left: 3px solid var(--accent-color, #419b38); + } + + .filter-info { + display: flex; + align-items: center; + gap: 8px; + font-size: 0.95rem; + color: var(--text-color); + } + + .filter-tag-badge { + font-weight: 600; + color: var(--accent-color, #419b38); + } + + .filter-count { + color: var(--text-muted, rgba(0, 0, 0, 0.6)); + font-size: 0.85rem; + } diff --git a/src/routes/admin/tags/+page.svelte b/src/routes/admin/tags/+page.svelte index b0dd0c9..b258338 100644 --- a/src/routes/admin/tags/+page.svelte +++ b/src/routes/admin/tags/+page.svelte @@ -1,4 +1,5 @@