From 080ec2789514bb95e7b26a083cd95b5fa83be386 Mon Sep 17 00:00:00 2001 From: oliver Date: Mon, 15 Jun 2026 23:32:51 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=E4=BF=AE=E6=94=B9=E8=B7=B3=E8=BF=87?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- desktop.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/desktop.js b/desktop.js index 86b5b229..780e4d50 100755 --- a/desktop.js +++ b/desktop.js @@ -2506,10 +2506,14 @@ else { autoUpdate = (autoUpdate == 'true'); } -// PWA 应用 -if (!location.href.match(/((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?::(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))/) && !location.href.match('localhost') && !(new URL(location.href)).searchParams.get('develop')) { +const urlParams = new URL(location.href).searchParams; +if (urlParams.get('skip_login') !== '1') { $('#loginback').css('opacity', '1'); $('#loginback').css('display', 'flex'); +} + +// PWA 应用 +if (!location.href.match(/((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?::(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))/) && !location.href.match('localhost') && !urlParams.get('develop')) { shownotice('about'); navigator.serviceWorker.register('sw.js', { updateViaCache: 'none', scope: './' }).then(reg => { From 52bfcac07a8eb9d297704155f769c67cf36561db Mon Sep 17 00:00:00 2001 From: oliver Date: Tue, 16 Jun 2026 14:05:24 +0800 Subject: [PATCH 2/3] feat(auth): add configurable password login for Tauri Add password input and error handling to the login screen, with a shared login completion flow. Introduce settings UI controls for viewing and updating the login password so Tauri users can enable, change, or clear password protection.feat(auth): add configurable password login for Tauri Add password input and error handling to the login screen, with a shared login completion flow. Introduce settings UI controls for viewing and updating the login password so Tauri users can enable, change, or clear password protection. --- apps/style/login.css | 31 +++++++++ apps/style/setting.css | 23 +++++++ desktop.html | 29 +++++---- desktop.js | 144 +++++++++++++++++++++++++++++++++++++++++ tauri/tauri_api.js | 12 ++++ 5 files changed, 225 insertions(+), 14 deletions(-) diff --git a/apps/style/login.css b/apps/style/login.css index b04ee0b2..238460f7 100755 --- a/apps/style/login.css +++ b/apps/style/login.css @@ -45,6 +45,37 @@ transition: 80ms; } +#login-password { + display: none; + width: 220px; + margin-bottom: 10px; + padding: 7px 10px; + color: #fff; + background-color: #eeeeee40; + border: 2px solid #ffffff50; + border-radius: 6px; + outline: none; + text-align: center; +} + +#login-password::placeholder { + color: #ffffffaa; +} + +#login-error { + display: none; + min-height: 18px; + margin-bottom: 8px; + color: #fff; + font-size: 14px; + text-shadow: 0 1px 3px #000; +} + +#loginback.tauri-password #login-password, +#loginback.tauri-password #login-error { + display: block; +} + :root.corner_squ #login { corner-shape: squircle; border-radius: 15px; diff --git a/apps/style/setting.css b/apps/style/setting.css index 61e111bb..1e6ad0f7 100755 --- a/apps/style/setting.css +++ b/apps/style/setting.css @@ -283,6 +283,29 @@ box-shadow: 0 1px 2px 1px var(--s3d); } +.setting-password { + display: grid; + gap: 10px; +} + +.setting-password>div>p:first-child { + font-size: 18px; +} + +.setting-password>div>p:last-child { + color: var(--text2); +} + +.setting-password>.button { + width: max-content; + padding: 5px 18px; +} + +.setting-password>.button.disabled { + pointer-events: none; + opacity: 0.6; +} + .checkbox { width: 40px; height: 20px; diff --git a/desktop.html b/desktop.html index 7f0611aa..82796224 100755 --- a/desktop.html +++ b/desktop.html @@ -188,19 +188,9 @@
Administrator
-
+ +
+
登录
@@ -1558,7 +1548,18 @@

请求记录

您的微软账户

订阅、账单等

您的账户信息

电子邮件、日历和联系人使用的帐户

-

登录选项

Windows Hello、安全密钥、密码、动态锁

+ +

电子邮件和账户

电子邮件、日历和联系人使用的帐户

家庭

管理您的家庭群组、编辑帐户类型和设备权限

Windows 备份

备份您的文件、应用程序、首选项以跨设备恢复它们

diff --git a/desktop.js b/desktop.js index 780e4d50..23612357 100755 --- a/desktop.js +++ b/desktop.js @@ -189,6 +189,149 @@ function stop(e) { e.stopPropagation(); return false; } + +let loginPasswordHasPassword = false; + +function win12FinishLogin() { + $('#login').css('opacity', '0'); + $('#login-password').css('opacity', '0'); + $('#login-error').css('opacity', '0'); + $('#login-welc').css('opacity', '1'); + setTimeout(() => { + $('#loginback').addClass('close'); + setTimeout(() => { + $('#loginback').css('opacity', '0'); + }, 500); + setTimeout(() => { + $('#loginback').css('display', 'none'); + }, 2000); + if (use_music) { + document.querySelector('audio#startup-music').play(); + } + }, 2000); +} + +function setLoginError(text) { + $('#login-error').text(text); +} + +async function initLoginPassword() { + if (window.win12Native && window.win12Native.isTauri() && (new URL(location.href)).searchParams.get('skip_login') !== '1') { + try { + const status = await window.win12Native.getLoginPasswordStatus(); + loginPasswordHasPassword = !!(status && status.has_password); + if (loginPasswordHasPassword) { + $('#loginback').addClass('tauri-password'); + $('#login-password').attr('placeholder', '密码'); + $('#login-password').focus(); + } + else { + $('#loginback').removeClass('tauri-password'); + } + } + catch (e) { + setLoginError('无法读取本地密码状态'); + } + } +} + +async function win12LoginSubmit() { + if (!(window.win12Native && window.win12Native.isTauri())) { + win12FinishLogin(); + return; + } + + if (!loginPasswordHasPassword) { + win12FinishLogin(); + return; + } + + const password = $('#login-password').val(); + if (!password) { + setLoginError('请输入密码'); + $('#login-password').focus(); + return; + } + + $('#login').css('pointer-events', 'none'); + setLoginError('正在验证'); + + try { + const result = await window.win12Native.verifyLoginPassword(password); + if (result && result.ok) { + $('#login-password').val(''); + win12FinishLogin(); + return; + } + setLoginError('密码错误'); + $('#login-password').val('').focus(); + } + catch (e) { + setLoginError(String(e)); + } + finally { + $('#login').css('pointer-events', 'auto'); + } +} + +async function win12RefreshPasswordSettingStatus() { + if (!(window.win12Native && window.win12Native.isTauri())) { + $('#setting-password-status').text('仅 Tauri App 可用'); + $('#setting-password-current').hide(); + $('#setting-password-new').prop('disabled', true); + $('#setting-password-submit').addClass('disabled'); + return; + } + + try { + const status = await window.win12Native.getLoginPasswordStatus(); + loginPasswordHasPassword = !!(status && status.has_password); + $('#setting-password-status').text(loginPasswordHasPassword ? '已设置密码' : '未设置密码'); + $('#setting-password-current')[loginPasswordHasPassword ? 'show' : 'hide'](); + $('#setting-password-current').val(''); + $('#setting-password-new').val('').prop('disabled', false); + $('#setting-password-submit').removeClass('disabled'); + } + catch (e) { + $('#setting-password-status').text(String(e)); + } +} + +async function win12SetLoginPassword() { + if (!(window.win12Native && window.win12Native.isTauri())) { + $('#setting-password-status').text('仅 Tauri App 可用'); + return; + } + + const currentPassword = $('#setting-password-current').val(); + const newPassword = $('#setting-password-new').val(); + if (!newPassword) { + $('#setting-password-status').text('请输入新密码'); + $('#setting-password-new').focus(); + return; + } + if (loginPasswordHasPassword && !currentPassword) { + $('#setting-password-status').text('请输入当前密码'); + $('#setting-password-current').focus(); + return; + } + + $('#setting-password-submit').addClass('disabled'); + $('#setting-password-status').text('正在保存'); + + try { + await window.win12Native.setLoginPassword(loginPasswordHasPassword ? currentPassword : null, newPassword); + $('#setting-password-status').text('密码已保存'); + await win12RefreshPasswordSettingStatus(); + } + catch (e) { + $('#setting-password-status').text(String(e)); + } + finally { + $('#setting-password-submit').removeClass('disabled'); + } +} + $('input,textarea,*[contenteditable=true]').on('contextmenu', (e) => { stop(e); return true; @@ -2413,6 +2556,7 @@ document.getElementsByTagName('body')[0].onload = () => { $('#loadback').css('display', 'none'); }, 1000); apps.webapps.init(); + initLoginPassword(); //getdata if (localStorage.getItem('theme') == 'dark') { $(':root').addClass('dark'); diff --git a/tauri/tauri_api.js b/tauri/tauri_api.js index d3aa6810..1c1f0739 100644 --- a/tauri/tauri_api.js +++ b/tauri/tauri_api.js @@ -6,4 +6,16 @@ window.win12Native = { if (!this.isTauri()) return null; return await window.__TAURI__.core.invoke("get_battery_info"); }, + async getLoginPasswordStatus() { + if (!this.isTauri()) return null; + return await window.__TAURI__.core.invoke("get_login_password_status"); + }, + async verifyLoginPassword(password) { + if (!this.isTauri()) return { ok: true }; + return await window.__TAURI__.core.invoke("verify_login_password", { password }); + }, + async setLoginPassword(currentPassword, newPassword) { + if (!this.isTauri()) return null; + return await window.__TAURI__.core.invoke("set_login_password", { currentPassword, newPassword }); + }, }; From 062ad182d93cd56ab3634370f55ed0d7facbee76 Mon Sep 17 00:00:00 2001 From: oliver Date: Tue, 16 Jun 2026 14:08:55 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=E6=B8=85=E9=99=A4=E5=AF=86=E7=A0=81?= =?UTF-8?q?=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- desktop.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/desktop.js b/desktop.js index 23612357..7165fd99 100755 --- a/desktop.js +++ b/desktop.js @@ -290,6 +290,7 @@ async function win12RefreshPasswordSettingStatus() { $('#setting-password-current')[loginPasswordHasPassword ? 'show' : 'hide'](); $('#setting-password-current').val(''); $('#setting-password-new').val('').prop('disabled', false); + $('#setting-password-new').attr('placeholder', loginPasswordHasPassword ? '新密码(留空清除密码)' : '新密码'); $('#setting-password-submit').removeClass('disabled'); } catch (e) { @@ -305,7 +306,7 @@ async function win12SetLoginPassword() { const currentPassword = $('#setting-password-current').val(); const newPassword = $('#setting-password-new').val(); - if (!newPassword) { + if (!loginPasswordHasPassword && !newPassword) { $('#setting-password-status').text('请输入新密码'); $('#setting-password-new').focus(); return; @@ -317,12 +318,13 @@ async function win12SetLoginPassword() { } $('#setting-password-submit').addClass('disabled'); - $('#setting-password-status').text('正在保存'); + const clearingPassword = loginPasswordHasPassword && !newPassword; + $('#setting-password-status').text(clearingPassword ? '正在清除' : '正在保存'); try { await window.win12Native.setLoginPassword(loginPasswordHasPassword ? currentPassword : null, newPassword); - $('#setting-password-status').text('密码已保存'); await win12RefreshPasswordSettingStatus(); + $('#setting-password-status').text(clearingPassword ? '密码已清空' : '密码已保存'); } catch (e) { $('#setting-password-status').text(String(e));