import { useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { useAuth } from "../App";
import { SideRail } from "../components/SideRail";
import { Button, Field, InlineAlert } from "../components/ui";
import { ApiError, api } from "../lib/client";
import type { User } from "../lib/types";
/**
* 账号设置:昵称、邮箱、登录密码、退出登录。
*
* 邮箱是**账号名**(能拿它 + 密码登录),不是"通知地址"的附属品,
* 所以放在基本信息里、和手机号并列,而不是藏在通知偏好里。
*/
/** 小节标题:一行标题 + 一句"这是干嘛的",比光秃秃的 h2 省解释。 */
function SectionLabel({ hint, children }: { hint?: string; children: React.ReactNode }) {
return (
{children}
{hint ?
{hint}
: null}
);
}
export function AccountPage() {
const { user, loading, reload, signOut } = useAuth();
const navigate = useNavigate();
const [nickname, setNickname] = useState("");
const [email, setEmail] = useState("");
const [profileBusy, setProfileBusy] = useState(false);
const [profileMsg, setProfileMsg] = useState(null);
const [profileError, setProfileError] = useState(null);
const [oldPassword, setOldPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [confirm, setConfirm] = useState("");
const [pwdBusy, setPwdBusy] = useState(false);
const [pwdMsg, setPwdMsg] = useState(null);
const [pwdError, setPwdError] = useState(null);
useEffect(() => {
if (!loading && !user) navigate("/login", { replace: true });
}, [loading, user, navigate]);
useEffect(() => {
if (user?.nickname) setNickname(user.nickname);
setEmail(user?.email ?? "");
}, [user?.nickname, user?.email]);
const hasPassword = Boolean(user?.has_password);
const nicknameChanged = nickname.trim() !== (user?.nickname ?? "");
const emailChanged = email.trim() !== (user?.email ?? "");
async function saveProfile(event: React.FormEvent) {
event.preventDefault();
setProfileBusy(true);
setProfileMsg(null);
setProfileError(null);
try {
// 只发改过的字段:邮箱留空表示"解绑",不能因为没动它就被清掉
const patch: { nickname?: string; email?: string } = {};
if (nicknameChanged) patch.nickname = nickname.trim();
if (emailChanged) patch.email = email.trim();
await api.patch("/auth/me", patch);
await reload();
setProfileMsg(
emailChanged && !email.trim()
? "邮箱已解绑,之后不能用邮箱登录"
: "资料已更新",
);
} catch (err) {
setProfileError(err instanceof ApiError ? err.message : "保存失败");
} finally {
setProfileBusy(false);
}
}
async function savePassword(event: React.FormEvent) {
event.preventDefault();
setPwdMsg(null);
setPwdError(null);
if (newPassword !== confirm) {
setPwdError("两次输入的新密码不一样");
return;
}
setPwdBusy(true);
try {
await api.post("/auth/password", {
password: newPassword,
...(hasPassword ? { old_password: oldPassword } : {}),
});
await reload();
setOldPassword("");
setNewPassword("");
setConfirm("");
setPwdMsg(hasPassword ? "密码已修改,下次可用新密码登录" : "密码已设置,之后可以用密码登录");
} catch (err) {
setPwdError(err instanceof ApiError ? err.message : "保存失败");
} finally {
setPwdBusy(false);
}
}
return (
账号设置
这里改的是你自己:昵称、登录密码、退出登录。工作区里的成员与权限在各自的工作区里管。
登录密码
{hasPassword
? "已设置密码。登录页可以选「密码」进入;改密码要先输当前密码。"
: "还没有设置密码。现在只能用手机号 + 验证码登录;设一个密码,换手机或短信不通时也能进。"}
退出
退出只会清掉这台浏览器里的令牌;工作区里的数据不受影响。
{user?.platform_admin ? (
系统设置
发信邮箱(SMTP)在那儿改:填完可以当场发一封测试邮件,确认通道通不通。
改完即时生效,不用登服务器改配置、也不用重启。
打开系统设置 →
) : null}
);
}