feat: 修改密码+密码可见切换+所有项目tab
- 新增 POST /api/auth/change-password 修改密码接口 - 修改密码弹窗,三次密码输入均带眼睛切换可见 - 业务模块新增「所有项目」tab,展示全部项目 - 版本号 v1.0.0.15
This commit is contained in:
@@ -166,3 +166,89 @@ window.deleteUser = async (uid, username) => {
|
||||
toast("删除失败:" + e.message, "error");
|
||||
}
|
||||
};
|
||||
|
||||
// 修改密码弹窗
|
||||
window.openChangePwdModal = () => {
|
||||
const overlay = document.createElement("div");
|
||||
overlay.id = "changePwdOverlay";
|
||||
overlay.className = "fixed inset-0 bg-black/40 z-[9999] flex items-center justify-center p-4";
|
||||
overlay.innerHTML = `
|
||||
<div class="bg-white rounded-xl shadow-2xl w-full max-w-sm">
|
||||
<div class="flex items-center justify-between px-6 py-4 border-b border-slate-200">
|
||||
<h2 class="text-lg font-semibold text-slate-800">修改密码</h2>
|
||||
<button class="text-slate-400 hover:text-slate-700" onclick="closeChangePwdModal()"><i data-lucide="x"></i></button>
|
||||
</div>
|
||||
<form class="p-6 grid gap-4" onsubmit="doChangePwd(event)" novalidate>
|
||||
<label class="block">
|
||||
<span class="text-sm text-slate-500 mb-1 block">旧密码</span>
|
||||
<div class="relative">
|
||||
<input type="password" name="old_password" required class="form-ctrl pr-10" placeholder="输入旧密码">
|
||||
<button type="button" class="absolute right-2 top-1/2 -translate-y-1/2 text-slate-400 hover:text-slate-600 p-1" onclick="togglePwdEye(this)"><i data-lucide="eye-off" style="width:16px;height:16px"></i></button>
|
||||
</div>
|
||||
</label>
|
||||
<label class="block">
|
||||
<span class="text-sm text-slate-500 mb-1 block">新密码</span>
|
||||
<div class="relative">
|
||||
<input type="password" name="new_password" required minlength="6" class="form-ctrl pr-10" placeholder="至少6位">
|
||||
<button type="button" class="absolute right-2 top-1/2 -translate-y-1/2 text-slate-400 hover:text-slate-600 p-1" onclick="togglePwdEye(this)"><i data-lucide="eye-off" style="width:16px;height:16px"></i></button>
|
||||
</div>
|
||||
</label>
|
||||
<label class="block">
|
||||
<span class="text-sm text-slate-500 mb-1 block">确认新密码</span>
|
||||
<div class="relative">
|
||||
<input type="password" name="confirm_password" required minlength="6" class="form-ctrl pr-10" placeholder="再次输入新密码">
|
||||
<button type="button" class="absolute right-2 top-1/2 -translate-y-1/2 text-slate-400 hover:text-slate-600 p-1" onclick="togglePwdEye(this)"><i data-lucide="eye-off" style="width:16px;height:16px"></i></button>
|
||||
</div>
|
||||
</label>
|
||||
<div class="flex justify-end gap-3 pt-2">
|
||||
<button type="button" class="btn btn-ghost btn-sm px-6" onclick="closeChangePwdModal()">取消</button>
|
||||
<button type="submit" class="btn btn-primary btn-sm px-8">确认修改</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>`;
|
||||
overlay.addEventListener("click", (e) => { if (e.target === overlay) closeChangePwdModal(); });
|
||||
document.body.appendChild(overlay);
|
||||
if (window.lucide) lucide.createIcons();
|
||||
};
|
||||
|
||||
window.togglePwdEye = (btn) => {
|
||||
const input = btn.parentElement.querySelector("input");
|
||||
const icon = btn.querySelector("i");
|
||||
if (input.type === "password") {
|
||||
input.type = "text";
|
||||
icon.setAttribute("data-lucide", "eye");
|
||||
} else {
|
||||
input.type = "password";
|
||||
icon.setAttribute("data-lucide", "eye-off");
|
||||
}
|
||||
if (window.lucide) lucide.createIcons({ elements: [icon] });
|
||||
};
|
||||
|
||||
window.closeChangePwdModal = () => {
|
||||
const el = document.getElementById("changePwdOverlay");
|
||||
if (el) el.remove();
|
||||
};
|
||||
|
||||
window.doChangePwd = async (e) => {
|
||||
e.preventDefault();
|
||||
const form = e.target;
|
||||
const fd = new FormData(form);
|
||||
const oldPwd = fd.get("old_password");
|
||||
const newPwd = fd.get("new_password");
|
||||
const confirmPwd = fd.get("confirm_password");
|
||||
if (newPwd !== confirmPwd) { toast("两次输入的新密码不一致", "error"); return; }
|
||||
if (newPwd.length < 6) { toast("新密码至少需要6位", "error"); return; }
|
||||
try {
|
||||
const resp = await fetch("/api/auth/change-password", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ old_password: oldPwd, new_password: newPwd }),
|
||||
});
|
||||
const data = await resp.json();
|
||||
if (!resp.ok) { toast(data.error || "修改失败", "error"); return; }
|
||||
closeChangePwdModal();
|
||||
toast("密码修改成功", "success");
|
||||
} catch (err) {
|
||||
toast("请求失败:" + err.message, "error");
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user