Files
jiang13-bbs/frontend/app/u/[id]/PasswordForm.tsx
freefire 24c6dea38c feat: 完成头像上传、站点主题配置与UI优化
- 新增附件模型与上传服务,拆分头像上传/管理逻辑
- 重构用户资料接口,移除直接修改头像字段,改用专用上传接口
- 添加站点公开设置API与管理员外观配置页
- 全局替换hover背景为accent-soft,优化交互一致性
- 完善头像组件,支持图片加载失败回退与src更新重置
- 新增用户状态事件总线,解决同页头像更新不及时问题
- 调整依赖包顺序与CI依赖版本
- 重构板块列表接口,新增帖子计数
- 迁移账号设置到用户主页tab,合并重复代码
2026-09-15 01:06:12 +08:00

109 lines
3.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { Check } from "lucide-react";
import { apiChangePassword } from "@/lib/api";
/**
* 修改密码表单:提交成功后后端已递增 TokenVersion 并清除全部登录 cookie,
* 刷新 layout 使 Header 回到游客态,随后跳转登录页重新登录。
*/
export default function PasswordForm() {
const router = useRouter();
const [oldPassword, setOldPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [submitting, setSubmitting] = useState(false);
const [error, setError] = useState("");
const [success, setSuccess] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError("");
if (newPassword.length < 6) {
setError("新密码至少 6 位");
return;
}
if (newPassword !== confirmPassword) {
setError("两次输入的新密码不一致");
return;
}
setSubmitting(true);
try {
const res = await apiChangePassword(oldPassword, newPassword);
if (res.message) {
setSuccess(true);
router.refresh();
setTimeout(() => router.push("/login"), 1500);
} else {
setError(res.error || "修改失败");
}
} catch {
setError("网络错误,请重试");
} finally {
setSubmitting(false);
}
};
return (
<form onSubmit={handleSubmit} className="panel p-5 sm:p-6 space-y-4">
{success && (
<div className="alert-ok flex items-center gap-2" role="status">
<Check size={15} /> 密码修改成功,正在跳转登录页...
</div>
)}
{error && <div className="alert-error" role="alert">{error}</div>}
<div>
<label className="field-label" htmlFor="pwd-old">当前密码</label>
<input
id="pwd-old"
type="password"
value={oldPassword}
onChange={(e) => setOldPassword(e.target.value)}
required
autoComplete="current-password"
className="field"
/>
</div>
<div>
<label className="field-label" htmlFor="pwd-new">新密码(至少 6 位)</label>
<input
id="pwd-new"
type="password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
required
minLength={6}
autoComplete="new-password"
className="field"
/>
</div>
<div>
<label className="field-label" htmlFor="pwd-confirm">确认新密码</label>
<input
id="pwd-confirm"
type="password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
minLength={6}
autoComplete="new-password"
className="field"
/>
</div>
<div className="flex justify-end pt-1 border-t" style={{ borderColor: "var(--line)" }}>
<button
type="submit"
disabled={submitting || success}
className="btn btn-primary w-full sm:w-auto"
>
{submitting ? "提交中..." : "修改密码"}
</button>
</div>
</form>
);
}