// panel-auth-ui client bundle (ModuleLoader format, served by the client // module system). Registers an "账号与安全" section in the panel settings // with change-password and logout actions. Depends on the panel-auth host // plugin's /panel-auth/change-password and /panel-auth/logout endpoints. window.__ModuleLoader__.load({ id: "panel-auth-ui", factory: (require) => { const React = require("react") const inputStyle = { width: "100%", boxSizing: "border-box", padding: "9px 11px", fontSize: 14, borderRadius: 10, border: "1px solid var(--dsw-alias-border-l2, rgba(255,255,255,0.14))", background: "var(--dsw-alias-bg-module-platform, rgba(255,255,255,0.05))", color: "var(--dsw-alias-label-primary, #e8eaf2)", outline: "none", } const cardStyle = { border: "1px solid var(--dsw-alias-border-l2, rgba(255,255,255,0.12))", borderRadius: 16, padding: "18px 16px", } const titleStyle = { margin: "0 0 6px", fontSize: 15, fontWeight: 600, color: "var(--dsw-alias-label-primary, #e8eaf2)", } const hintStyle = { margin: "0 0 14px", fontSize: 12.5, color: "var(--dsw-alias-label-secondary, #9aa1b5)", } const buttonStyle = (tone) => ({ padding: "9px 16px", fontSize: 14, fontWeight: 600, borderRadius: 10, cursor: "pointer", border: tone === "danger" ? "1px solid rgba(248,113,113,0.5)" : "1px solid var(--dsw-alias-border-l2, rgba(255,255,255,0.16))", background: tone === "danger" ? "rgba(248,113,113,0.12)" : "var(--dsw-alias-bg-module-platform, rgba(255,255,255,0.06))", color: tone === "danger" ? "#f87171" : "var(--dsw-alias-label-primary, #e8eaf2)", }) const messageStyle = (ok) => ({ margin: "0 0 12px", padding: "8px 11px", fontSize: 12.5, borderRadius: 8, border: ok ? "1px solid rgba(74,222,128,0.4)" : "1px solid rgba(248,113,113,0.4)", background: ok ? "rgba(74,222,128,0.12)" : "rgba(248,113,113,0.12)", color: ok ? "#4ade80" : "#f87171", }) function Field(props) { return React.createElement( "label", { style: { display: "block", marginBottom: 12 } }, React.createElement("div", { style: { fontSize: 12, marginBottom: 6, color: "var(--dsw-alias-label-secondary, #9aa1b5)" } }, props.label), React.createElement("input", { type: "password", autoComplete: props.autoComplete || "off", value: props.value, onChange: (event) => props.onChange(event.target.value), style: inputStyle, }), ) } function PanelAuthSection() { const [oldPw, setOldPw] = React.useState("") const [newPw, setNewPw] = React.useState("") const [confirm, setConfirm] = React.useState("") const [busy, setBusy] = React.useState(false) const [message, setMessage] = React.useState(null) const submit = () => { if (busy) return if (!oldPw || !newPw) { setMessage({ ok: false, text: "请填写当前密码和新密码" }) return } if (newPw.length < 8) { setMessage({ ok: false, text: "新密码至少 8 位" }) return } if (newPw !== confirm) { setMessage({ ok: false, text: "两次输入的新密码不一致" }) return } setBusy(true) setMessage(null) fetch("/panel-auth/change-password", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ oldPassword: oldPw, newPassword: newPw }), }) .then((response) => response.json().then((data) => ({ ok: response.ok, data }))) .then(({ ok, data }) => { if (ok) { setOldPw("") setNewPw("") setConfirm("") setMessage({ ok: true, text: (data && data.message) || "密码已更新" }) } else { setMessage({ ok: false, text: (data && data.message) || "修改失败" }) } }) .catch(() => setMessage({ ok: false, text: "网络错误,请稍后再试" })) .finally(() => setBusy(false)) } const logout = () => { window.location.href = "/panel-auth/logout" } return React.createElement( "div", { style: { display: "flex", flexDirection: "column", gap: 18 } }, React.createElement( "section", { style: cardStyle }, React.createElement("h3", { style: titleStyle }, "修改密码"), React.createElement("p", { style: hintStyle }, "需要输入当前密码验证身份,修改后无需重新登录。"), React.createElement(Field, { label: "当前密码", autoComplete: "current-password", value: oldPw, onChange: setOldPw }), React.createElement(Field, { label: "新密码(至少 8 位)", autoComplete: "new-password", value: newPw, onChange: setNewPw }), React.createElement(Field, { label: "确认新密码", autoComplete: "new-password", value: confirm, onChange: setConfirm }), message === null ? null : React.createElement("div", { style: messageStyle(message.ok) }, message.text), React.createElement("button", { onClick: submit, disabled: busy, style: { ...buttonStyle("primary"), opacity: busy ? 0.6 : 1 } }, busy ? "提交中…" : "确认修改"), ), React.createElement( "section", { style: cardStyle }, React.createElement("h3", { style: titleStyle }, "退出登录"), React.createElement("p", { style: hintStyle }, "清除本浏览器的登录 Cookie 并返回登录页。"), React.createElement("button", { onClick: logout, style: buttonStyle("danger") }, "退出登录"), ), ) } return { apply(ctx) { const slots = ctx.get("slots") if (slots === undefined) return slots.inject("settings.section", () => slots.register( { name: "settings.section", id: "panel-auth", order: 30, label: () => "账号与安全" }, (props) => React.createElement(PanelAuthSection, { close: props.close }), )) }, } }, })