import { useEffect, useState, type ReactNode } from "react"; import { AnimatePresence, motion } from "motion/react"; import { BriefcaseBusiness, ChevronRight, CircleUserRound, HelpCircle, LogOut, Mail, MapPinned, Moon, Eye, EyeOff, Phone, Settings, Shield, Sun, User, X, } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { useTheme } from "@/components/ThemeProvider"; import { useIsMobileViewport } from "@/hooks/useIsMobileViewport"; import { useIsWecomBrowser } from "@/hooks/useIsWecomBrowser"; import { clearAuth, getCurrentUser, getProfileOverview, updateCurrentUserProfile, updateCurrentUserPassword, type ProfileOverview, type UpdateCurrentUserProfilePayload, type UpdateCurrentUserPasswordPayload, type UserProfile, } from "@/lib/auth"; type MenuItem = { key: "personal" | "security" | "help"; icon: typeof User; label: string; color: string; bg: string; }; type EditableProfileForm = UpdateCurrentUserProfilePayload; const MENU_ITEMS: MenuItem[] = [ { key: "personal", icon: User, label: "个人资料", color: "text-blue-500 dark:text-blue-400", bg: "bg-blue-50 dark:bg-blue-500/10" }, { key: "security", icon: Shield, label: "账号安全", color: "text-emerald-500 dark:text-emerald-400", bg: "bg-emerald-50 dark:bg-emerald-500/10" }, { key: "help", icon: HelpCircle, label: "帮助中心", color: "text-violet-500 dark:text-violet-400", bg: "bg-violet-50 dark:bg-violet-500/10" }, ]; const EMPTY_FORM: EditableProfileForm = { displayName: "", email: "", phone: "", }; const EMPTY_PASSWORD_FORM: SecurityForm = { oldPassword: "", newPassword: "", confirmPassword: "", }; type SecurityForm = UpdateCurrentUserPasswordPayload & { confirmPassword: string; }; function displayText(value?: string | null) { return value && value.trim() ? value : "无"; } function numericValue(value?: number | null) { return typeof value === "number" && Number.isFinite(value) ? value : 0; } function PageModal({ title, subtitle, onClose, children, footer, }: { title: string; subtitle?: string; onClose: () => void; children: ReactNode; footer?: ReactNode; }) { return ( <>

{title}

{subtitle ?

{subtitle}

: null}
{children}
{footer ?
{footer}
: null}
); } export default function Profile() { const { theme, setTheme } = useTheme(); const navigate = useNavigate(); const isMobileViewport = useIsMobileViewport(); const isWecomBrowser = useIsWecomBrowser(); const disableMobileMotion = isMobileViewport || isWecomBrowser; const [overview, setOverview] = useState(null); const [currentUser, setCurrentUser] = useState(null); const [profileDrawerOpen, setProfileDrawerOpen] = useState(false); const [securityDrawerOpen, setSecurityDrawerOpen] = useState(false); const [form, setForm] = useState(EMPTY_FORM); const [detailLoading, setDetailLoading] = useState(false); const [saving, setSaving] = useState(false); const [error, setError] = useState(""); const [securityForm, setSecurityForm] = useState(EMPTY_PASSWORD_FORM); const [securitySaving, setSecuritySaving] = useState(false); const [securityError, setSecurityError] = useState(""); const [securitySuccess, setSecuritySuccess] = useState(""); const [showOldPassword, setShowOldPassword] = useState(false); const [showNewPassword, setShowNewPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false); useEffect(() => { let ignore = false; async function loadProfileData() { try { const me = await getCurrentUser(); const overviewData = await getProfileOverview().catch(() => null); if (ignore) { return; } setCurrentUser(me); setOverview(overviewData); } catch { if (ignore) { return; } setOverview(null); setCurrentUser(null); } } void loadProfileData(); return () => { ignore = true; }; }, []); const handleLogout = () => { clearAuth(); navigate("/login", { replace: true }); }; const handleNavigateToMonthlyOpportunity = () => { navigate("/opportunities"); }; const handleNavigateToMonthlyExpansion = () => { navigate("/expansion"); }; const handleOpenProfile = async () => { setDetailLoading(true); setError(""); try { const me = currentUser ?? await getCurrentUser(); const latestOverview = overview ?? await getProfileOverview().catch(() => null); setCurrentUser(me); setOverview(latestOverview); setForm({ userId: me.userId, username: me.username, displayName: me.displayName || "", email: me.email || "", phone: me.phone || "", pwdResetRequired: me.pwdResetRequired, isPlatformAdmin: me.isPlatformAdmin, orgId: undefined, }); setProfileDrawerOpen(true); } catch (loadError) { setError(loadError instanceof Error ? loadError.message : "获取个人资料失败"); setProfileDrawerOpen(true); } finally { setDetailLoading(false); } }; const handleCloseProfile = () => { if (saving) { return; } setProfileDrawerOpen(false); setError(""); }; const handleSave = async () => { if (saving) { return; } setSaving(true); setError(""); try { await updateCurrentUserProfile({ ...form, email: form.email || undefined, phone: form.phone || undefined, }); const me = await getCurrentUser(); const overviewData = await getProfileOverview().catch(() => overview); setCurrentUser(me); setOverview(overviewData); setForm({ userId: me.userId, username: me.username, displayName: me.displayName || "", email: me.email || "", phone: me.phone || "", pwdResetRequired: me.pwdResetRequired, isPlatformAdmin: me.isPlatformAdmin, orgId: undefined, }); sessionStorage.setItem("userProfile", JSON.stringify(me)); setProfileDrawerOpen(false); } catch (saveError) { setError(saveError instanceof Error ? saveError.message : "保存失败"); } finally { setSaving(false); } }; const handleOpenSecurity = () => { setSecurityForm(EMPTY_PASSWORD_FORM); setSecurityError(""); setSecuritySuccess(""); setShowOldPassword(false); setShowNewPassword(false); setShowConfirmPassword(false); setSecurityDrawerOpen(true); }; const handleCloseSecurity = () => { if (securitySaving) { return; } setSecurityDrawerOpen(false); setSecurityError(""); setSecuritySuccess(""); }; const handleOpenHelp = () => { window.alert("请联系系统管理员!"); }; const handleUpdatePassword = async () => { if (securitySaving) { return; } if (!securityForm.oldPassword || !securityForm.newPassword || !securityForm.confirmPassword) { setSecurityError("请完整填写旧密码、新密码和确认密码"); setSecuritySuccess(""); return; } if (securityForm.newPassword !== securityForm.confirmPassword) { setSecurityError("两次输入的新密码不一致"); setSecuritySuccess(""); return; } if (securityForm.newPassword.length < 6) { setSecurityError("新密码长度不能少于6位"); setSecuritySuccess(""); return; } setSecuritySaving(true); setSecurityError(""); setSecuritySuccess(""); try { await updateCurrentUserPassword({ oldPassword: securityForm.oldPassword, newPassword: securityForm.newPassword, }); clearAuth(); navigate("/login", { replace: true }); } catch (saveError) { setSecurityError(saveError instanceof Error ? saveError.message : "密码修改失败"); } finally { setSecuritySaving(false); } }; const roleNames = displayText(overview?.jobTitle); const orgNames = displayText(overview?.deptName); const displayName = displayText(currentUser?.displayName || overview?.realName); const avatarText = displayName === "无" ? "无" : displayName.slice(0, 1); const currentEmail = displayText(currentUser?.email); const currentPhone = displayText(currentUser?.phone); return (

我的

查看个人信息、账号安全设置和本月工作概览。

{avatarText}

{displayName}

部门:{orgNames}

岗位:{roleNames}

  • {MENU_ITEMS.map((item) => (
  • ))}
退出登录 {profileDrawerOpen ? (
)} > {error && !currentUser ? (
{error}
) : (
{(form.displayName || currentUser?.displayName || "无").slice(0, 1)}
{displayText(currentUser?.displayName)}

部门:{orgNames}

岗位:{roleNames}

账号:{displayText(currentUser?.username)}
岗位信息

岗位:{roleNames}

状态:{displayText(overview?.accountStatus)}

组织信息

部门:{orgNames}

入职天数:{numericValue(overview?.onboardingDays)}

当前手机号:{currentPhone}
当前邮箱:{currentEmail}
{detailLoading ? (
正在加载个人资料...
) : null} {error ? (
{error}
) : null}
)} ) : null} {securityDrawerOpen ? ( )} >

为了账号安全,请先输入当前密码,再设置新密码。

{securityError ? (
{securityError}
) : null} {securitySuccess ? (
{securitySuccess}
) : null}
) : null} ); }