diff --git a/app/api/roles/users/route.ts b/app/api/roles/users/route.ts index ed78dda..f6e8a24 100644 --- a/app/api/roles/users/route.ts +++ b/app/api/roles/users/route.ts @@ -1,43 +1,49 @@ import { createDb } from "@/lib/db" -import { userRoles, users } from "@/lib/schema" +import { users } from "@/lib/schema" import { eq } from "drizzle-orm" export const runtime = "edge" -export async function GET(request: Request) { - const url = new URL(request.url) - const email = url.searchParams.get('email') +export async function POST(request: Request) { + try { + const json = await request.json() + const { searchText } = json as { searchText: string } - if (!email) { - return Response.json( - { error: "邮箱地址不能为空" }, - { status: 400 } - ) - } + if (!searchText) { + return Response.json({ error: "请提供用户名或邮箱地址" }, { status: 400 }) + } - const db = createDb() - - const user = await db.query.users.findFirst({ - where: eq(users.email, email), - }) + const db = createDb() - if (!user) { - return Response.json({ user: null }) - } + const user = await db.query.users.findFirst({ + where: searchText.includes('@') ? eq(users.email, searchText) : eq(users.username, searchText), + with: { + userRoles: { + with: { + role: true + } + } + } + }); - const userRole = await db.query.userRoles.findFirst({ - where: eq(userRoles.userId, user.id), - with: { - role: true + if (!user) { + return Response.json({ error: "未找到用户" }, { status: 404 }) } - }) - return Response.json({ - user: { - id: user.id, - name: user.name, - email: user.email, - role: userRole?.role.name - } - }) + return Response.json({ + user: { + id: user.id, + name: user.name, + username: user.username, + email: user.email, + role: user.userRoles[0]?.role.name + } + }) + } catch (error) { + console.error("Failed to find user:", error) + return Response.json( + { error: "查询用户失败" }, + { status: 500 } + ) + } } \ No newline at end of file diff --git a/app/components/profile/profile-card.tsx b/app/components/profile/profile-card.tsx index ea8bb2c..d45f2d4 100644 --- a/app/components/profile/profile-card.tsx +++ b/app/components/profile/profile-card.tsx @@ -58,7 +58,9 @@ export function ProfileCard({ user }: ProfileCardProps) { }

- {user.email} + { + user.email ? user.email : `用户名: ${user.username}` + }

{user.roles && (
diff --git a/app/components/profile/promote-panel.tsx b/app/components/profile/promote-panel.tsx index e51e724..8265029 100644 --- a/app/components/profile/promote-panel.tsx +++ b/app/components/profile/promote-panel.tsx @@ -8,20 +8,34 @@ import { useToast } from "@/components/ui/use-toast" import { ROLES } from "@/lib/permissions" export function PromotePanel() { - const [email, setEmail] = useState("") + const [searchText, setSearchText] = useState("") const [loading, setLoading] = useState(false) const [action, setAction] = useState<"promote" | "demote">("promote") const { toast } = useToast() const handleAction = async () => { - if (!email) return + if (!searchText) return setLoading(true) try { - const res = await fetch(`/api/roles/users?email=${encodeURIComponent(email)}`) - const data = await res.json() as { user?: { id: string; name?: string; email: string; role?: string }; error?: string } + const res = await fetch("/api/roles/users", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ searchText }) + }) + const data = await res.json() as { + user?: { + id: string + name?: string + username?: string + email: string + role?: string + } + error?: string + } + + if (!res.ok) throw new Error(data.error || "未知错误") - if (!res.ok) throw new Error(data.error || '未知错误') if (!data.user) { toast({ title: "未找到用户", @@ -61,9 +75,9 @@ export function PromotePanel() { toast({ title: action === "promote" ? "册封成功" : "贬为平民", - description: `已将 ${data.user.email} ${action === "promote" ? "册封为骑士" : "贬为平民"}` + description: `已将 ${data.user.email || data.user.username} ${action === "promote" ? "册封为骑士" : "贬为平民"}` }) - setEmail("") + setSearchText("") } catch (error) { toast({ @@ -86,9 +100,9 @@ export function PromotePanel() {
setEmail(e.target.value)} + placeholder="输入用户名或邮箱" + value={searchText} + onChange={(e) => setSearchText(e.target.value)} disabled={loading} />
@@ -98,7 +112,7 @@ export function PromotePanel() { setAction("promote") handleAction() }} - disabled={!email || loading} + disabled={!searchText || loading} className="flex-1 sm:flex-initial gap-2" > {loading && action === "promote" ? ( @@ -113,7 +127,7 @@ export function PromotePanel() { setAction("demote") handleAction() }} - disabled={!email || loading} + disabled={!searchText || loading} variant="destructive" className="flex-1 sm:flex-initial gap-2" > diff --git a/app/lib/schema.ts b/app/lib/schema.ts index 1d80ae6..ed21e30 100644 --- a/app/lib/schema.ts +++ b/app/lib/schema.ts @@ -85,10 +85,6 @@ export const roles = sqliteTable("role", { updatedAt: integer("updated_at", { mode: "timestamp" }).$defaultFn(() => new Date()), }); -export const rolesRelations = relations(roles, ({ many }) => ({ - userRoles: many(userRoles), -})); - export const userRoles = sqliteTable("user_role", { userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }), roleId: text("role_id").notNull().references(() => roles.id, { onDelete: "cascade" }), @@ -106,4 +102,12 @@ export const userRolesRelations = relations(userRoles, ({ one }) => ({ fields: [userRoles.roleId], references: [roles.id], }), -})); \ No newline at end of file +})); + +export const usersRelations = relations(users, ({ many }) => ({ + userRoles: many(userRoles), +})); + +export const rolesRelations = relations(roles, ({ many }) => ({ + userRoles: many(userRoles), +})); \ No newline at end of file