Files
blogflare/src/routes/admin/posts/[id]/+page.server.ts
T

96 lines
3.5 KiB
TypeScript

import { error, fail, redirect } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ params, platform }) => {
const db = platform?.env?.DB;
const postId = params.id;
if (!db) {
throw error(500, '数据库未连接');
}
try {
const post = await db.prepare(
'SELECT id, title, slug, content, cover, category_id, published_at, updated_at FROM posts WHERE id = ?'
).bind(postId).first<{ id: number; title: string; slug: string; content: string; cover: string | null; category_id: number | null; published_at?: string; updated_at?: string }>();
if (!post) {
throw error(404, '文章不存在');
}
const { results: allTags } = await db.prepare('SELECT id, name FROM tags ORDER BY name ASC').all();
const { results: allCategories } = await db.prepare('SELECT id, name FROM categories ORDER BY name ASC').all();
const { results: selectedTagRows } = await db.prepare('SELECT tag_id FROM post_tags WHERE post_id = ?').bind(postId).all();
const selectedTagIds = selectedTagRows.map((r: any) => r.tag_id as number);
return {
post,
tags: allTags as unknown as { id: number; name: string }[],
categories: allCategories as unknown as { id: number; name: string }[],
selectedTagIds
};
} catch (err: any) {
if (err?.status === 404) throw err;
console.error('Error loading post for edit:', err);
throw error(500, '读取文章详情失败');
}
};
export const actions: Actions = {
update: async ({ params, request, platform }) => {
const db = platform?.env?.DB;
const postId = params.id;
if (!db) return fail(500, { error: '数据库未连接' });
const formData = await request.formData();
const title = formData.get('title')?.toString().trim();
const slug = formData.get('slug')?.toString().trim() || '';
const content = formData.get('content')?.toString() || '';
const cover = formData.get('cover')?.toString().trim() || null;
const categoryId = formData.get('category_id') ? Number(formData.get('category_id')) : null;
const selectedTags = formData.getAll('tags').map(t => Number(t));
const publishedAt = formData.get('published_at')?.toString().trim();
const updatedAt = formData.get('updated_at')?.toString().trim() || new Date().toISOString();
if (!title || !slug || !content) {
return fail(400, { error: '标题、URL 别名和文章正文为必填项' });
}
try {
// 更新文章表
if (publishedAt) {
await db.prepare(
`UPDATE posts
SET title = ?, slug = ?, content = ?, cover = ?, category_id = ?, published_at = ?, updated_at = ?
WHERE id = ?`
).bind(title, slug, content, cover, categoryId, publishedAt, updatedAt, postId).run();
} else {
await db.prepare(
`UPDATE posts
SET title = ?, slug = ?, content = ?, cover = ?, category_id = ?, updated_at = ?
WHERE id = ?`
).bind(title, slug, content, cover, categoryId, updatedAt, postId).run();
}
// 清除原有标签并重新绑定
await db.prepare('DELETE FROM post_tags WHERE post_id = ?').bind(postId).run();
if (selectedTags.length > 0) {
for (const tagId of selectedTags) {
await db.prepare('INSERT INTO post_tags (post_id, tag_id) VALUES (?, ?)').bind(postId, tagId).run();
}
}
} catch (err: any) {
console.error('Error updating post:', err);
if (err?.message?.includes('UNIQUE constraint failed')) {
return fail(400, { error: 'URL 别名 (Slug) 已被其他文章占用' });
}
return fail(500, { error: '保存修改失败' });
}
throw redirect(303, '/admin/posts');
}
};