feat: 重构用户角色系统为管理员标识

- 将用户角色字段从role改为is_admin布尔值
- 更新相关API权限检查逻辑
- 修改数据库schema和迁移文件
- 调整前端用户显示逻辑
- 添加API响应工具函数
- 优化权限检查中间件
- 重构英雄组件为原子组件
This commit is contained in:
张翔
2026-03-12 20:45:43 +08:00
parent b207bfa7af
commit f357330ba8
22 changed files with 1078 additions and 552 deletions
+64 -48
View File
@@ -1,23 +1,17 @@
import { NextRequest, NextResponse } from 'next/server';
import { NextRequest } from 'next/server';
import { db } from '@/db';
import { siteConfig } from '@/db/schema';
import { auth } from '@/lib/auth';
import { hasPermission } from '@/lib/auth/permissions';
import { checkIsAdmin, getAdminUserId } from '@/lib/auth/check-permission';
import { forbidden, success, notFound, validationError, badRequest, handleApiError } from '@/lib/api-response';
import { eq, and } from 'drizzle-orm';
import { nanoid } from 'nanoid';
export async function GET(request: NextRequest) {
try {
const session = await auth();
const { isAdmin } = await checkIsAdmin();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'config', 'read')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin) {
return forbidden();
}
const { searchParams } = new URL(request.url);
@@ -32,10 +26,10 @@ export async function GET(request: NextRequest) {
.limit(1);
if (config.length === 0) {
return NextResponse.json({ error: '配置不存在' }, { status: 404 });
return notFound('配置不存在');
}
return NextResponse.json(config[0]);
return success(config[0]);
}
const conditions = [];
@@ -61,35 +55,29 @@ export async function GET(request: NextRequest) {
return acc;
}, {} as Record<string, typeof configs>);
return NextResponse.json({
return success({
configs: groupedConfigs,
flat: configs,
});
} catch (error) {
console.error('获取配置失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
export async function POST(request: NextRequest) {
try {
const session = await auth();
const { isAdmin } = await checkIsAdmin();
const userId = await getAdminUserId();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'config', 'update')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin || !userId) {
return forbidden();
}
const body = await request.json();
const { key, value, category, description } = body;
if (!key || !value || !category) {
return NextResponse.json({ error: '缺少必要字段' }, { status: 400 });
return validationError('缺少必要字段', { required: ['key', 'value', 'category'] });
}
const existing = await db
@@ -107,12 +95,12 @@ export async function POST(request: NextRequest) {
value,
description: description || existing[0]!.description,
updatedAt: now,
updatedBy: session.user.id,
updatedBy: userId,
})
.where(eq(siteConfig.key, key))
.returning();
return NextResponse.json(updated[0]);
return success(updated[0], 200);
}
const newConfig = await db
@@ -124,36 +112,30 @@ export async function POST(request: NextRequest) {
category,
description: description || null,
updatedAt: now,
updatedBy: session.user.id,
updatedBy: userId,
})
.returning();
return NextResponse.json(newConfig[0], { status: 201 });
return success(newConfig[0], 201);
} catch (error) {
console.error('创建/更新配置失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
export async function PUT(request: NextRequest) {
try {
const session = await auth();
const { isAdmin } = await checkIsAdmin();
const userId = await getAdminUserId();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'config', 'update')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin || !userId) {
return forbidden();
}
const body = await request.json();
const { configs } = body as { configs: Array<{ key: string; value: unknown; description?: string }> };
if (!Array.isArray(configs)) {
return NextResponse.json({ error: '无效的数据格式' }, { status: 400 });
return badRequest('无效的数据格式');
}
const now = new Date();
@@ -173,7 +155,7 @@ export async function PUT(request: NextRequest) {
value: config.value,
description: config.description || existing[0]!.description,
updatedAt: now,
updatedBy: session.user.id,
updatedBy: userId,
})
.where(eq(siteConfig.key, config.key))
.returning();
@@ -188,16 +170,50 @@ export async function PUT(request: NextRequest) {
category: 'general',
description: config.description || null,
updatedAt: now,
updatedBy: session.user.id,
updatedBy: userId,
})
.returning();
results.push(created[0]);
}
}
return NextResponse.json({ success: true, updated: results.length });
return success(results);
} catch (error) {
console.error('批量更新配置失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
export async function DELETE(request: NextRequest) {
try {
const { isAdmin } = await checkIsAdmin();
if (!isAdmin) {
return forbidden();
}
const { searchParams } = new URL(request.url);
const key = searchParams.get('key');
if (!key) {
return badRequest('缺少 key 参数');
}
const existing = await db
.select()
.from(siteConfig)
.where(eq(siteConfig.key, key))
.limit(1);
if (existing.length === 0) {
return notFound('配置不存在');
}
await db
.delete(siteConfig)
.where(eq(siteConfig.key, key));
return success({ success: true });
} catch (error) {
return handleApiError(error);
}
}
+26 -45
View File
@@ -1,9 +1,9 @@
import { NextRequest, NextResponse } from 'next/server';
import { NextRequest } from 'next/server';
import { db } from '@/db';
import { content, contentVersions } from '@/db/schema';
import { auth } from '@/lib/auth';
import { hasPermission } from '@/lib/auth/permissions';
import { checkIsAdmin, getAdminUserId } from '@/lib/auth/check-permission';
import { createAuditLog } from '@/lib/audit';
import { forbidden, notFound, success, handleApiError } from '@/lib/api-response';
import { eq } from 'drizzle-orm';
import { nanoid } from 'nanoid';
@@ -12,16 +12,10 @@ export async function GET(
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
const { isAdmin } = await checkIsAdmin();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'content', 'read')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin) {
return forbidden();
}
const { id } = await params;
@@ -33,7 +27,7 @@ export async function GET(
.limit(1);
if (item.length === 0) {
return NextResponse.json({ error: '内容不存在' }, { status: 404 });
return notFound('内容不存在');
}
const versions = await db
@@ -42,13 +36,12 @@ export async function GET(
.where(eq(contentVersions.contentId, id))
.orderBy(contentVersions.version);
return NextResponse.json({
return success({
...item[0],
versions,
});
} catch (error) {
console.error('获取内容详情失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
@@ -57,16 +50,11 @@ export async function PUT(
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
const { isAdmin } = await checkIsAdmin();
const userId = await getAdminUserId();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'content', 'update')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin || !userId) {
return forbidden();
}
const { id } = await params;
@@ -79,7 +67,7 @@ export async function PUT(
.limit(1);
if (existingContent.length === 0) {
return NextResponse.json({ error: '内容不存在' }, { status: 404 });
return notFound('内容不存在');
}
const current = existingContent[0]!;
@@ -107,7 +95,7 @@ export async function PUT(
},
to: body,
},
changedBy: session.user.id,
changedBy: userId,
changedAt: now,
});
@@ -138,7 +126,7 @@ export async function PUT(
.returning();
await createAuditLog({
userId: session.user.id,
userId,
action: 'update',
resourceType: 'content',
resourceId: id,
@@ -147,10 +135,9 @@ export async function PUT(
},
});
return NextResponse.json(updated[0]);
return success(updated[0]);
} catch (error) {
console.error('更新内容失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
@@ -159,16 +146,11 @@ export async function DELETE(
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
const { isAdmin } = await checkIsAdmin();
const userId = await getAdminUserId();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'content', 'delete')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin || !userId) {
return forbidden();
}
const { id } = await params;
@@ -180,14 +162,14 @@ export async function DELETE(
.limit(1);
if (existingContent.length === 0) {
return NextResponse.json({ error: '内容不存在' }, { status: 404 });
return notFound('内容不存在');
}
await db.delete(contentVersions).where(eq(contentVersions.contentId, id));
await db.delete(content).where(eq(content.id, id));
await createAuditLog({
userId: session.user.id,
userId,
action: 'delete',
resourceType: 'content',
resourceId: id,
@@ -196,9 +178,8 @@ export async function DELETE(
},
});
return NextResponse.json({ success: true });
return success({ success: true });
} catch (error) {
console.error('删除内容失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
+18 -31
View File
@@ -1,24 +1,18 @@
import { NextRequest, NextResponse } from 'next/server';
import { NextRequest } from 'next/server';
import { db } from '@/db';
import { content } from '@/db/schema';
import { auth } from '@/lib/auth';
import { hasPermission } from '@/lib/auth/permissions';
import { checkIsAdmin, getAdminUserId } from '@/lib/auth/check-permission';
import { createAuditLog } from '@/lib/audit';
import { forbidden, badRequest, success, handleApiError, validationError } from '@/lib/api-response';
import { eq, desc, and, like, sql } from 'drizzle-orm';
import { nanoid } from 'nanoid';
export async function GET(request: NextRequest) {
try {
const session = await auth();
const { isAdmin } = await checkIsAdmin();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'content', 'read')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin) {
return forbidden();
}
const { searchParams } = new URL(request.url);
@@ -61,7 +55,7 @@ export async function GET(request: NextRequest) {
const total = countResult[0]?.count || 0;
return NextResponse.json({
return success({
items,
pagination: {
page,
@@ -71,30 +65,24 @@ export async function GET(request: NextRequest) {
},
});
} catch (error) {
console.error('获取内容列表失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
export async function POST(request: NextRequest) {
try {
const session = await auth();
const { isAdmin } = await checkIsAdmin();
const userId = await getAdminUserId();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'content', 'create')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin || !userId) {
return forbidden();
}
const body = await request.json();
const { type, title, slug, excerpt, contentBody, coverImage, category, tags, status: contentStatus, metadata } = body;
if (!type || !title || !slug) {
return NextResponse.json({ error: '缺少必要字段' }, { status: 400 });
return validationError('缺少必要字段', { required: ['type', 'title', 'slug'] });
}
const existingContent = await db
@@ -104,7 +92,7 @@ export async function POST(request: NextRequest) {
.limit(1);
if (existingContent.length > 0) {
return NextResponse.json({ error: 'Slug 已存在' }, { status: 400 });
return badRequest('Slug 已存在');
}
const now = new Date();
@@ -122,7 +110,7 @@ export async function POST(request: NextRequest) {
tags: tags || [],
status: contentStatus || 'draft',
publishedAt: contentStatus === 'published' ? now : null,
authorId: session.user.id,
authorId: userId,
metadata: metadata || null,
createdAt: now,
updatedAt: now,
@@ -130,7 +118,7 @@ export async function POST(request: NextRequest) {
.returning();
await createAuditLog({
userId: session.user.id,
userId,
action: 'create',
resourceType: 'content',
resourceId: newContent[0]!.id,
@@ -141,9 +129,8 @@ export async function POST(request: NextRequest) {
},
});
return NextResponse.json(newContent[0], { status: 201 });
return success(newContent[0], 201);
} catch (error) {
console.error('创建内容失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
+23 -33
View File
@@ -1,21 +1,16 @@
import { NextRequest, NextResponse } from 'next/server';
import { auth } from '@/lib/auth';
import { hasPermission } from '@/lib/auth/permissions';
import { NextRequest } from 'next/server';
import { checkIsAdmin, getAdminUserId } from '@/lib/auth/check-permission';
import { createAuditLog } from '@/lib/audit';
import { uploadFile, deleteFile } from '@/lib/upload';
import { forbidden, badRequest, notFound, success, handleApiError } from '@/lib/api-response';
export async function POST(request: NextRequest) {
try {
const session = await auth();
const { isAdmin } = await checkIsAdmin();
const userId = await getAdminUserId();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'content', 'create')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin || !userId) {
return forbidden();
}
const formData = await request.formData();
@@ -23,16 +18,16 @@ export async function POST(request: NextRequest) {
const type = (formData.get('type') as 'image' | 'document') || 'image';
if (!file) {
return NextResponse.json({ error: '未找到文件' }, { status: 400 });
return badRequest('未找到文件');
}
const result = await uploadFile(file, {
type,
userId: session.user.id,
userId,
});
await createAuditLog({
userId: session.user.id,
userId,
action: 'upload',
resourceType: 'file',
resourceId: result.id,
@@ -44,7 +39,7 @@ export async function POST(request: NextRequest) {
},
});
return NextResponse.json({
return success({
success: true,
file: result,
});
@@ -52,43 +47,38 @@ export async function POST(request: NextRequest) {
console.error('文件上传失败:', error);
if (error instanceof Error) {
return NextResponse.json({ error: error.message }, { status: 400 });
return badRequest(error.message);
}
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
export async function DELETE(request: NextRequest) {
try {
const session = await auth();
const { isAdmin } = await checkIsAdmin();
const userId = await getAdminUserId();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'content', 'delete')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin || !userId) {
return forbidden();
}
const { searchParams } = new URL(request.url);
const fileUrl = searchParams.get('url');
if (!fileUrl) {
return NextResponse.json({ error: '缺少文件 URL' }, { status: 400 });
return badRequest('缺少文件 URL');
}
const success = await deleteFile(fileUrl);
const result = await deleteFile(fileUrl);
if (!success) {
return NextResponse.json({ error: '文件不存在或删除失败' }, { status: 404 });
if (!result) {
return notFound('文件不存在或删除失败');
}
return NextResponse.json({ success: true });
return success({ success: true });
} catch (error) {
console.error('文件删除失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
+39 -61
View File
@@ -1,8 +1,8 @@
import { NextRequest, NextResponse } from 'next/server';
import { NextRequest } from 'next/server';
import { db } from '@/db';
import { users } from '@/db/schema';
import { auth } from '@/lib/auth';
import { hasPermission } from '@/lib/auth/permissions';
import { checkIsAdmin } from '@/lib/auth/check-permission';
import { forbidden, notFound, success, handleApiError } from '@/lib/api-response';
import { eq } from 'drizzle-orm';
import bcrypt from 'bcryptjs';
@@ -11,26 +11,24 @@ export async function GET(
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
const { isAdmin, userId } = await checkIsAdmin();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'users', 'read')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin) {
return forbidden();
}
const { id } = await params;
if (id !== userId) {
return forbidden('只能查看自己的信息');
}
const user = await db
.select({
id: users.id,
email: users.email,
name: users.name,
role: users.role,
isAdmin: users.isAdmin,
createdAt: users.createdAt,
updatedAt: users.updatedAt,
})
@@ -39,13 +37,12 @@ export async function GET(
.limit(1);
if (user.length === 0) {
return NextResponse.json({ error: '用户不存在' }, { status: 404 });
return notFound('用户不存在');
}
return NextResponse.json({ user: user[0] });
return success({ user: user[0] });
} catch (error) {
console.error('获取用户详情失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
@@ -54,21 +51,20 @@ export async function PUT(
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
const { isAdmin, userId } = await checkIsAdmin();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'users', 'update')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin) {
return forbidden();
}
const { id } = await params;
if (id !== userId) {
return forbidden('只能修改自己的信息');
}
const body = await request.json();
const { email, name, password, role } = body;
const { email, name, password } = body;
const existingUser = await db
.select()
@@ -77,16 +73,15 @@ export async function PUT(
.limit(1);
if (existingUser.length === 0) {
return NextResponse.json({ error: '用户不存在' }, { status: 404 });
return notFound('用户不存在');
}
const updateData: Record<string, any> = {
const updateData: Record<string, unknown> = {
updatedAt: new Date(),
};
if (email) updateData.email = email;
if (name) updateData.name = name;
if (role) updateData.role = role;
if (password) {
updateData.passwordHash = await bcrypt.hash(password, 10);
}
@@ -97,18 +92,16 @@ export async function PUT(
.where(eq(users.id, id))
.returning();
return NextResponse.json({
return success({
user: {
id: updated[0]!.id,
email: updated[0]!.email,
name: updated[0]!.name,
role: updated[0]!.role,
createdAt: updated[0]!.createdAt,
}
isAdmin: updated[0]!.isAdmin,
},
});
} catch (error) {
console.error('更新用户失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
@@ -117,39 +110,24 @@ export async function DELETE(
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
const { isAdmin, userId } = await checkIsAdmin();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'users', 'delete')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin) {
return forbidden();
}
const { id } = await params;
if (session.user.id === id) {
return NextResponse.json({ error: '不能删除自己的账号' }, { status: 400 });
if (id !== userId) {
return forbidden('不能删除其他用户');
}
const existingUser = await db
.select()
.from(users)
.where(eq(users.id, id))
.limit(1);
await db
.delete(users)
.where(eq(users.id, id));
if (existingUser.length === 0) {
return NextResponse.json({ error: '用户不存在' }, { status: 404 });
}
await db.delete(users).where(eq(users.id, id));
return NextResponse.json({ success: true });
return success({ success: true });
} catch (error) {
console.error('删除用户失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}
+11 -80
View File
@@ -1,24 +1,16 @@
import { NextRequest, NextResponse } from 'next/server';
import { NextRequest } from 'next/server';
import { db } from '@/db';
import { users } from '@/db/schema';
import { auth } from '@/lib/auth';
import { hasPermission } from '@/lib/auth/permissions';
import { eq } from 'drizzle-orm';
import { nanoid } from 'nanoid';
import bcrypt from 'bcryptjs';
import { checkIsAdmin } from '@/lib/auth/check-permission';
import { forbidden, success, handleApiError } from '@/lib/api-response';
import { desc } from 'drizzle-orm';
export async function GET(_request: NextRequest) {
try {
const session = await auth();
const { isAdmin } = await checkIsAdmin();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'users', 'read')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
if (!isAdmin) {
return forbidden();
}
const allUsers = await db
@@ -26,77 +18,16 @@ export async function GET(_request: NextRequest) {
id: users.id,
email: users.email,
name: users.name,
role: users.role,
isAdmin: users.isAdmin,
createdAt: users.createdAt,
updatedAt: users.updatedAt,
})
.from(users)
.orderBy(users.createdAt);
.orderBy(desc(users.createdAt));
return NextResponse.json({ users: allUsers });
return success({ users: allUsers });
} catch (error) {
console.error('获取用户列表失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
}
}
export async function POST(request: NextRequest) {
try {
const session = await auth();
if (!session?.user) {
return NextResponse.json({ error: '未授权' }, { status: 401 });
}
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
if (!hasPermission(userRole, 'users', 'create')) {
return NextResponse.json({ error: '无权限' }, { status: 403 });
}
const body = await request.json();
const { email, name, password, role } = body;
if (!email || !name || !password || !role) {
return NextResponse.json({ error: '缺少必填字段' }, { status: 400 });
}
const existingUser = await db
.select()
.from(users)
.where(eq(users.email, email))
.limit(1);
if (existingUser.length > 0) {
return NextResponse.json({ error: '邮箱已被使用' }, { status: 400 });
}
const hashedPassword = await bcrypt.hash(password, 10);
const newUser = await db
.insert(users)
.values({
id: nanoid(),
email,
name,
passwordHash: hashedPassword,
role,
createdAt: new Date(),
updatedAt: new Date(),
})
.returning();
return NextResponse.json({
user: {
id: newUser[0]!.id,
email: newUser[0]!.email,
name: newUser[0]!.name,
role: newUser[0]!.role,
createdAt: newUser[0]!.createdAt,
}
});
} catch (error) {
console.error('创建用户失败:', error);
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
return handleApiError(error);
}
}