(function () { function handleForbidden(res) { if (res && Number(res.code) === 403) { top.location.href = baseUrl + "/"; return true; } return false; } new Vue({ el: "#app", data: function () { return { loading: false, saving: false, passwordDialogVisible: false, passwordSaving: false, mfaDialogVisible: false, mfaDialogMode: "enable", mfaSetupLoading: false, mfaSubmitting: false, passkeyDialogVisible: false, passkeyDialogMode: "register", passkeySubmitting: false, form: { id: "", roleName: "", username: "", mobile: "", createTime$: "", mfaAllow: 0, mfaAllow$: "否", mfaEnabled: 0, mfaEnabled$: "否", mfaBoundTime$: "", mfaMaskedSecret: "", passkeyBound: false, passkeyName: "", passkeyBoundTime$: "", passkeyLastUsedTime$: "", passkeyTransports: "" }, passwordForm: { oldPassword: "", password: "", rePassword: "" }, mfaForm: { currentPassword: "", code: "" }, mfaSetup: { secret: "", qrCode: "", otpAuth: "" }, passkeyForm: { name: "", currentPassword: "" }, rules: { username: [ { required: true, message: "请输入名称", trigger: "blur" } ], mobile: [ { required: true, message: "请输入账号", trigger: "blur" } ] }, passwordRules: { oldPassword: [ { required: true, message: "请输入当前密码", trigger: "blur" } ], password: [ { required: true, message: "请输入新密码", trigger: "blur" }, { validator: function (rule, value, callback) { if (!value) { callback(new Error("请输入新密码")); return; } if (String(value).length < 4) { callback(new Error("不能少于4个字符")); return; } if (value === this.passwordForm.oldPassword) { callback(new Error("与旧密码不能相同")); return; } callback(); }.bind(this), trigger: "blur" } ], rePassword: [ { required: true, message: "请再次输入新密码", trigger: "blur" }, { validator: function (rule, value, callback) { if (value !== this.passwordForm.password) { callback(new Error("密码不一致")); return; } callback(); }.bind(this), trigger: "blur" } ] }, mfaRules: { currentPassword: [ { required: true, message: "请输入当前密码", trigger: "blur" } ], code: [ { required: true, message: "请输入6位验证码", trigger: "blur" }, { validator: function (rule, value, callback) { if (!/^\d{6}$/.test(String(value || "").trim())) { callback(new Error("请输入6位数字验证码")); return; } callback(); }, trigger: "blur" } ] }, passkeyRules: { currentPassword: [ { required: true, message: "请输入当前密码", trigger: "blur" } ] } }; }, created: function () { this.loadDetail(); }, methods: { loadDetail: function () { var vm = this; vm.loading = true; $.ajax({ url: baseUrl + "/user/detail/auth", headers: { token: localStorage.getItem("token") }, method: "POST", success: function (res) { if (handleForbidden(res)) { return; } if (Number(res.code) !== 200) { vm.$message.error(res.msg || "资料加载失败"); return; } var user = res.data || {}; vm.form = Object.assign({}, vm.form, user); }, error: function () { vm.$message.error("资料加载失败"); }, complete: function () { vm.loading = false; } }); }, openPasswordDialog: function () { this.passwordForm = { oldPassword: "", password: "", rePassword: "" }; this.passwordDialogVisible = true; if (this.$refs.passwordForm) { this.$nextTick(function () { this.$refs.passwordForm.clearValidate(); }); } }, closePasswordDialog: function () { this.passwordDialogVisible = false; }, handlePasswordSave: function () { var vm = this; vm.$refs.passwordForm.validate(function (valid) { if (!valid) { return false; } vm.submitPasswordSave(); return true; }); }, submitPasswordSave: function () { var vm = this; vm.passwordSaving = true; $.ajax({ url: baseUrl + "/user/password/update/auth", headers: { token: localStorage.getItem("token") }, data: { oldPassword: hex_md5(vm.passwordForm.oldPassword), password: hex_md5(vm.passwordForm.password) }, method: "POST", success: function (res) { if (handleForbidden(res)) { return; } if (Number(res.code) !== 200) { vm.$message.error(res.msg || "密码修改失败"); return; } vm.passwordDialogVisible = false; vm.$alert("密码修改成功,请重新登录", "提示", { confirmButtonText: "确定", callback: function () { localStorage.removeItem("token"); top.location.href = baseUrl + "/"; } }); }, error: function () { vm.$message.error("密码修改失败"); }, complete: function () { vm.passwordSaving = false; } }); }, openMfaEnableDialog: function () { if (Number(this.form.mfaAllow) !== 1) { this.$message.warning("当前账号未开通MFA使用权限"); return; } this.mfaDialogMode = "enable"; this.resetMfaDialogState(); this.mfaDialogVisible = true; this.loadMfaSetup(); }, openMfaDisableDialog: function () { this.mfaDialogMode = "disable"; this.resetMfaDialogState(); this.mfaDialogVisible = true; }, closeMfaDialog: function () { this.mfaDialogVisible = false; this.resetMfaDialogState(); }, resetMfaDialogState: function () { this.mfaSubmitting = false; this.mfaSetupLoading = false; this.mfaForm = { currentPassword: "", code: "" }; this.mfaSetup = { secret: "", qrCode: "", otpAuth: "" }; if (this.$refs.mfaForm) { this.$refs.mfaForm.clearValidate(); } }, loadMfaSetup: function () { var vm = this; vm.mfaSetupLoading = true; $.ajax({ url: baseUrl + "/user/mfa/setup/auth", headers: { token: localStorage.getItem("token") }, method: "POST", success: function (res) { if (handleForbidden(res)) { return; } if (Number(res.code) !== 200) { vm.$message.error(res.msg || "MFA配置加载失败"); return; } vm.mfaSetup = Object.assign({}, vm.mfaSetup, res.data || {}); }, error: function () { vm.$message.error("MFA配置加载失败"); }, complete: function () { vm.mfaSetupLoading = false; } }); }, handleMfaSubmit: function () { var vm = this; if (!vm.$refs.mfaForm) { return; } vm.$refs.mfaForm.validate(function (valid) { if (!valid) { return false; } if (vm.mfaDialogMode === "enable" && !vm.mfaSetup.secret) { vm.$message.error("MFA密钥尚未生成,请稍后重试"); return false; } vm.submitMfaAction(); return true; }); }, submitMfaAction: function () { var vm = this; vm.mfaSubmitting = true; $.ajax({ url: baseUrl + (vm.mfaDialogMode === "enable" ? "/user/mfa/enable/auth" : "/user/mfa/disable/auth"), headers: { token: localStorage.getItem("token") }, data: { currentPassword: hex_md5(vm.mfaForm.currentPassword), code: vm.mfaForm.code, secret: vm.mfaSetup.secret }, method: "POST", success: function (res) { if (handleForbidden(res)) { return; } if (Number(res.code) !== 200) { vm.$message.error(res.msg || "MFA操作失败"); return; } vm.$message.success(vm.mfaDialogMode === "enable" ? "MFA已启用" : "MFA已停用"); vm.closeMfaDialog(); vm.loadDetail(); }, error: function () { vm.$message.error("MFA操作失败"); }, complete: function () { vm.mfaSubmitting = false; } }); }, openPasskeyRegisterDialog: function () { if (!window.WCS_WEBAUTHN || !window.WCS_WEBAUTHN.isSupported()) { this.$message.error(this.resolvePasskeyErrorMessage({ message: window.isSecureContext ? "not-supported" : "secure-context" }, "当前环境不支持通行密钥")); return; } this.passkeyDialogMode = "register"; this.resetPasskeyDialogState(); this.passkeyDialogVisible = true; }, openPasskeyRemoveDialog: function () { this.passkeyDialogMode = "remove"; this.resetPasskeyDialogState(); this.passkeyDialogVisible = true; }, closePasskeyDialog: function () { this.passkeyDialogVisible = false; this.resetPasskeyDialogState(); }, resetPasskeyDialogState: function () { this.passkeySubmitting = false; this.passkeyForm = { name: "", currentPassword: "" }; if (this.$refs.passkeyForm) { this.$refs.passkeyForm.clearValidate(); } }, handlePasskeySubmit: function () { var vm = this; if (!vm.$refs.passkeyForm) { return; } vm.$refs.passkeyForm.validate(function (valid) { if (!valid) { return false; } if (vm.passkeyDialogMode === "register") { vm.submitPasskeyRegister(); } else { vm.submitPasskeyRemove(); } return true; }); }, submitPasskeyRegister: function () { var vm = this; if (!window.WCS_WEBAUTHN || !window.WCS_WEBAUTHN.isSupported()) { vm.$message.error(vm.resolvePasskeyErrorMessage({ message: window.isSecureContext ? "not-supported" : "secure-context" }, "当前环境不支持通行密钥")); return; } vm.passkeySubmitting = true; $.ajax({ url: baseUrl + "/user/passkey/register/options/auth", headers: { token: localStorage.getItem("token") }, method: "POST", success: function (res) { if (handleForbidden(res)) { return; } if (Number(res.code) !== 200) { vm.passkeySubmitting = false; vm.$message.error(res.msg || "通行密钥配置加载失败"); return; } vm.executePasskeyRegister(res.data || {}); }, error: function () { vm.passkeySubmitting = false; vm.$message.error("通行密钥配置加载失败"); } }); }, executePasskeyRegister: function (optionsPayload) { var vm = this; window.WCS_WEBAUTHN.register(optionsPayload).then(function (credential) { $.ajax({ url: baseUrl + "/user/passkey/register/finish/auth", headers: { token: localStorage.getItem("token") }, data: { ticket: optionsPayload.ticket, currentPassword: hex_md5(vm.passkeyForm.currentPassword), name: vm.passkeyForm.name, credentialId: credential.credentialId, clientDataJSON: credential.clientDataJSON, authenticatorData: credential.authenticatorData, publicKey: credential.publicKey, publicKeyAlgorithm: credential.publicKeyAlgorithm, transports: credential.transports }, method: "POST", success: function (res) { if (handleForbidden(res)) { return; } if (Number(res.code) !== 200) { vm.$message.error(res.msg || "通行密钥绑定失败"); return; } vm.$message.success("通行密钥已绑定"); vm.closePasskeyDialog(); vm.loadDetail(); }, error: function () { vm.$message.error("通行密钥绑定失败"); }, complete: function () { vm.passkeySubmitting = false; } }); }).catch(function (err) { vm.passkeySubmitting = false; vm.$message.error(vm.resolvePasskeyErrorMessage(err, "通行密钥绑定失败")); }); }, submitPasskeyRemove: function () { var vm = this; vm.passkeySubmitting = true; $.ajax({ url: baseUrl + "/user/passkey/remove/auth", headers: { token: localStorage.getItem("token") }, data: { currentPassword: hex_md5(vm.passkeyForm.currentPassword) }, method: "POST", success: function (res) { if (handleForbidden(res)) { return; } if (Number(res.code) !== 200) { vm.$message.error(res.msg || "通行密钥解绑失败"); return; } vm.$message.success("通行密钥已解绑"); vm.closePasskeyDialog(); vm.loadDetail(); }, error: function () { vm.$message.error("通行密钥解绑失败"); }, complete: function () { vm.passkeySubmitting = false; } }); }, resolvePasskeyErrorMessage: function (err, fallback) { var message = err && err.message ? String(err.message) : ""; if (message === "secure-context") { return "通行密钥仅支持在 HTTPS 或 localhost 环境下使用"; } if (message === "not-supported" || message === "extension-unsupported" || message === "public-key-missing") { return "当前浏览器不支持通行密钥,请使用最新版 Chrome、Edge 或 Safari"; } if (err && err.name === "NotAllowedError") { return "已取消通行密钥操作或验证超时"; } return fallback || "通行密钥操作失败"; }, copySecret: function () { var vm = this; var text = vm.mfaSetup.secret || ""; if (!text) { return; } if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(text).then(function () { vm.$message.success("密钥已复制"); }).catch(function () { vm.fallbackCopy(text); }); return; } vm.fallbackCopy(text); }, fallbackCopy: function (text) { try { var textarea = document.createElement("textarea"); textarea.value = text; textarea.style.position = "fixed"; textarea.style.opacity = "0"; document.body.appendChild(textarea); textarea.select(); document.execCommand("copy"); document.body.removeChild(textarea); this.$message.success("密钥已复制"); } catch (err) { this.$message.error("复制失败"); } }, handleSave: function () { var vm = this; vm.$refs.profileForm.validate(function (valid) { if (!valid) { return false; } vm.$confirm("确定修改资料吗?", "提示", { type: "warning", confirmButtonText: "确定", cancelButtonText: "取消" }).then(function () { vm.submitSave(); }).catch(function () { }); return true; }); }, submitSave: function () { var vm = this; vm.saving = true; $.ajax({ url: baseUrl + "/user/update/auth", headers: { token: localStorage.getItem("token") }, data: { id: vm.form.id, username: vm.form.username, mobile: vm.form.mobile }, method: "POST", success: function (res) { if (handleForbidden(res)) { return; } if (Number(res.code) !== 200) { vm.$message.error(res.msg || "保存失败"); return; } vm.$message.success(res.msg || "修改成功"); localStorage.setItem("username", vm.form.username || ""); if (window.parent && window.parent.document) { var usernameNode = window.parent.document.getElementById("person-username"); if (usernameNode) { usernameNode.textContent = localStorage.getItem("username"); } } }, error: function () { vm.$message.error("保存失败"); }, complete: function () { vm.saving = false; } }); } } }); })();