From 5e3e106d915a1e169f686a54b979a29a931ac885 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sat, 6 Jun 2026 23:40:45 +0800 Subject: [PATCH] fix: sync login autofill fields --- src/pages/login.vue | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/pages/login.vue b/src/pages/login.vue index d488c443..cbc342b0 100644 --- a/src/pages/login.vue +++ b/src/pages/login.vue @@ -57,6 +57,9 @@ let mfaDialogController: ReturnType | null = null // 用户名称输入框 const usernameInput = ref() +// 登录自动填充同步的延时任务 +const autofillSyncTimerIds: number[] = [] + // 语言选择菜单 const langMenu = ref(false) @@ -121,6 +124,44 @@ const pluginAuthProviders = computed(() => ) const showPasskeyLogin = computed(() => !!systemPasskeyProvider.value?.enabled) +// 获取登录表单中的原生账号和密码输入框。 +function getLoginCredentialInputs() { + const formElement = refForm.value?.$el as HTMLFormElement | undefined + const root = formElement || document + + return { + username: root.querySelector('input[name="username"]'), + password: root.querySelector('input[name="password"]'), + } +} + +// 将密码管理器写入 DOM 的账号密码同步回响应式表单。 +function syncLoginCredentialValues() { + const { username, password } = getLoginCredentialInputs() + + if (username && username.value !== form.value.username) { + form.value.username = username.value + } + + if (password && password.value !== form.value.password) { + form.value.password = password.value + } +} + +// 清理尚未执行的登录自动填充同步任务。 +function clearLoginAutofillSyncTimers() { + autofillSyncTimerIds.forEach(timerId => window.clearTimeout(timerId)) + autofillSyncTimerIds.length = 0 +} + +// 延迟多次同步自动填充值,兼容只对聚焦字段派发事件的密码管理器。 +function scheduleLoginAutofillSync() { + clearLoginAutofillSyncTimers() + syncLoginCredentialValues() + autofillSyncTimerIds.push(window.setTimeout(syncLoginCredentialValues, 50)) + autofillSyncTimerIds.push(window.setTimeout(syncLoginCredentialValues, 250)) +} + // 生成 MFA 共享弹窗使用的最新 props。 function getMfaDialogProps() { return { @@ -667,6 +708,7 @@ onUnmounted(() => { manualAbortController.abort() manualAbortController = null } + clearLoginAutofillSyncTimers() }) @@ -733,6 +775,8 @@ onUnmounted(() => { autocomplete="username" :rules="[requiredValidator]" hide-details + @input="scheduleLoginAutofillSync" + @change="scheduleLoginAutofillSync" /> @@ -748,6 +792,8 @@ onUnmounted(() => { :rules="[requiredValidator]" hide-details @click:append-inner="isPasswordVisible = !isPasswordVisible" + @input="scheduleLoginAutofillSync" + @change="scheduleLoginAutofillSync" />