diff --git a/app/(account)/settings/page.tsx b/app/(account)/settings/page.tsx index 0bfb74d..2b48d7d 100644 --- a/app/(account)/settings/page.tsx +++ b/app/(account)/settings/page.tsx @@ -16,7 +16,9 @@ import { import { Separator } from "@/components/ui/separator" import { Switch } from "@/components/ui/switch" import { Textarea } from "@/components/ui/textarea" -import { notifySuccess } from "@/lib/toast" +import { getCurrentUserForLogin, switchCurrentRole, updateCurrentUser, uploadFile } from "@/lib/api" +import { toApiError } from "@/lib/errors" +import { notifyInfo, notifySuccess } from "@/lib/toast" import type { UserRole } from "@/lib/types" import type { ThemePreference } from "@/store/auth" import { useAuthStore } from "@/store/auth" @@ -26,18 +28,12 @@ import Link from "next/link" import { useRef, useState } from "react" export default function SettingsPage() { - const { - currentRole, - verifiedRoles, - switchRole, - user, - updateProfile, - notificationPrefs, - setNotificationPref, - } = useAuthStore() + const { currentRole, verifiedRoles, user, login, notificationPrefs, setNotificationPref } = + useAuthStore() const [nickname, setNickname] = useState(user?.nickname ?? "") const [bio, setBio] = useState(user?.bio ?? "") const [avatar, setAvatar] = useState(user?.avatar ?? "") + const [uploadingAvatar, setUploadingAvatar] = useState(false) const fileRef = useRef(null) const isRoleVerified = (role: UserRole) => verifiedRoles.includes(role) @@ -50,6 +46,53 @@ export default function SettingsPage() { setThemePreference(pref) } + async function handleAvatarFile(file: File, resetInput: () => void) { + setUploadingAvatar(true) + try { + const url = await uploadFile(file, "avatar") + setAvatar(url) + notifySuccess("头像已上传") + } catch (error) { + notifyInfo(toApiError(error).msg) + } finally { + setUploadingAvatar(false) + resetInput() + } + } + + async function handleProfileSave() { + if (!user) { + notifyInfo("请先登录") + return + } + + try { + const updated = await updateCurrentUser({ + nickname: nickname.trim() || user.nickname, + bio: bio.trim(), + avatar, + }) + login(updated, updated.verifiedRoles ?? [updated.role]) + notifySuccess("资料已保存") + } catch (error) { + notifyInfo(toApiError(error).msg) + } + } + + async function handleRoleChange(value: string) { + const role = value as UserRole + if (!isRoleVerified(role) || role === currentRole) return + + try { + await switchCurrentRole(role) + const updated = await getCurrentUserForLogin() + login(updated, updated.verifiedRoles ?? [updated.role]) + notifySuccess("身份已切换") + } catch (error) { + notifyInfo(toApiError(error).msg) + } + } + return (

个人设置

@@ -70,21 +113,26 @@ export default function SettingsPage() { accept="image/*" className="hidden" onChange={(event) => { - const file = event.target.files?.[0] + const target = event.currentTarget + const file = target.files?.[0] if (!file) return - setAvatar(URL.createObjectURL(file)) - event.target.value = "" + void handleAvatarFile(file, () => { + target.value = "" + }) }} />
-

点击更换头像,支持 JPG、PNG 格式

+

+ {uploadingAvatar ? "头像上传中..." : "点击上传头像,支持 JPG、PNG 格式"} +

@@ -117,12 +165,7 @@ export default function SettingsPage() {