From ec9be40d6c6e01e26fb140b30e7b516d921b4ca6 Mon Sep 17 00:00:00 2001
From: shuaiplus <2327005759@qq.com>
Date: Thu, 26 Feb 2026 05:04:43 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E7=BD=91=E9=A1=B5?=
=?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=AB=AF=E6=A0=B7=E5=BC=8F=E5=92=8C=E5=B8=83?=
=?UTF-8?q?=E5=B1=80=EF=BC=8C=E6=8F=90=E5=8D=87=E7=94=A8=E6=88=B7=E4=BD=93?=
=?UTF-8?q?=E9=AA=8C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/handlers/web.ts | 380 +++++++++++++++++++++++++++-----------------
1 file changed, 237 insertions(+), 143 deletions(-)
diff --git a/src/handlers/web.ts b/src/handlers/web.ts
index f07fc03..c4d618a 100644
--- a/src/handlers/web.ts
+++ b/src/handlers/web.ts
@@ -13,213 +13,298 @@ function renderWebClientHTML(): string {
NodeWarden Web
@@ -403,12 +488,12 @@ function renderWebClientHTML(): string {
+ ' '
+ (state.pendingLogin ? ''
+ 'Two-step verification
Password is already verified.
'
+ (state.loginTotpError?'
'+esc(state.loginTotpError)+'
':'')
- + '
'
+ + '
'
+ '
'
: '')
+ ' '
@@ -426,7 +511,7 @@ function renderWebClientHTML(): string {
+ ' '
+ ' '
+ ' '
- + ' '
+ + ' '
+ ' '
+ ' '
+ '';
@@ -438,12 +523,12 @@ function renderWebClientHTML(): string {
for(var i=0;i'+esc(nameText)+'
'+esc(c.id)+'
';
+ rows += '';
}
- if(!rows) rows='';
+ if(!rows) rows='No items in this folder.
';
var c0=selectedCipher();
- var detail='Select an item to view details.
';
+ var detail='Select an item to view details.
';
if(c0){
var login = c0.login||{};
var fields=Array.isArray(c0.fields)?c0.fields:[];
@@ -463,10 +548,11 @@ function renderWebClientHTML(): string {
return ''
+ renderMsg()
- + 'Vault
'
- + '
'
- + '
'
- + '
';
+ + ''
+ + '
Vault
'
+ + '
'
+ + '
'
+ + '';
}
function renderSettingsTab(){
@@ -475,52 +561,58 @@ function renderWebClientHTML(): string {
var qr='https://api.qrserver.com/v1/create-qr-code/?size=180x180&data='+encodeURIComponent(buildTotpUri(secret));
return ''
+ renderMsg()
+ + 'Settings
'
+ ''
+ ''
- + 'TOTP Setup
Disable action prompts for master password.
';
+ + 'TOTP Setup
Disable action prompts for master password.
';
}
function renderTotpDisableModal(){
if(!state.totpDisableOpen) return '';
return ''
- + 'Disable TOTP
Enter master password to disable two-step verification.
'
- + (state.totpDisableError?'
'+esc(state.totpDisableError)+'
':'')
- + '
'
+ + '
Disable TOTP
Enter master password to disable two-step verification.
'
+ + (state.totpDisableError?'
'+esc(state.totpDisableError)+'
':'')
+ + '
'
+ '
';
}
function renderHelpTab(){
return ''
- + '
Upstream Sync
- Track upstream with a fork and scheduled sync workflow (recommended).
- Before merge: compare API routes, migration files, and auth logic changes.
- After merge: run local dev migration tests, then deploy Worker after validation.
'
- + '
Common Errors
- 401 Unauthorized: token expired or revoked, login again.
- 403 Account disabled: admin must unban user in User Management.
- 403 Invite invalid: invite expired/used/revoked, create a new invite.
- 429 Too many requests: wait retry seconds and avoid burst writes.
'
- + '
Troubleshooting
- Login OK but encrypted values shown: verify profile key and KDF settings are consistent.
- TOTP fails repeatedly: sync device time and re-scan QR using latest secret.
- Password change failed: ensure current password is correct and new password has at least 12 chars.
- Sync conflicts: refresh vault and retry one operation at a time.
';
+ + '
Help & Support
'
+ + '
Upstream Sync
- Track upstream with a fork and scheduled sync workflow (recommended).
- Before merge: compare API routes, migration files, and auth logic changes.
- After merge: run local dev migration tests, then deploy Worker after validation.
'
+ + '
Common Errors
- 401 Unauthorized: token expired or revoked, login again.
- 403 Account disabled: admin must unban user in User Management.
- 403 Invite invalid: invite expired/used/revoked, create a new invite.
- 429 Too many requests: wait retry seconds and avoid burst writes.
'
+ + '
Troubleshooting
- Login OK but encrypted values shown: verify profile key and KDF settings are consistent.
- TOTP fails repeatedly: sync device time and re-scan QR using latest secret.
- Password change failed: ensure current password is correct and new password has at least 12 chars.
- Sync conflicts: refresh vault and retry one operation at a time.
';
}
function renderAdminTab(){
var usersRows='';
for(var i=0;i
'+esc(u.email)+' | '+esc(u.name||'')+' | '+esc(u.role)+' | '+esc(u.status)+' | '
- + (canAct?'':'')
+ usersRows += ' | | '+esc(u.email)+' | '+esc(u.name||'')+' | '+esc(u.role)+' | '+esc(u.status)+' | '
+ + (canAct?'':'')
+ (canAct?' ':'')
+ ' |
';
}
- if(!usersRows) usersRows='| No users. |
';
+ if(!usersRows) usersRows='| No users found. |
';
var inviteRows='';
for(var j=0;j'+esc(inv.code)+' | '+esc(inv.status)+' | '+esc(inv.expiresAt)+' | '
- + ''
+ inviteRows += ' | '+esc(inv.code)+' | '+esc(inv.status)+' | '+esc(inv.expiresAt)+' | '
+ + ''
+ (inv.status==='active'?' ':'')
+ ' |
';
}
- if(!inviteRows) inviteRows='| No invites. |
';
+ if(!inviteRows) inviteRows='| No invites found. |
';
return ''
+ renderMsg()
- + ''
- + 'Users
| Email | Name | Role | Status | Action |
'+usersRows+'
'
- + 'Invites
| Code | Status | Expires At | Action |
'+inviteRows+'
';
+ + ''
+ + '
User Management
'
+ + ''
+ + ''
+ + ''
+ + 'Users
| Email | Name | Role | Status | Action |
'+usersRows+'
'
+ + 'Invites
| Code | Status | Expires At | Action |
'+inviteRows+'
';
}
function renderApp(){
@@ -534,18 +626,20 @@ function renderWebClientHTML(): string {
return ''
+ ''
+ ' '
+ + (showFolders?('
'):'')
+ '
'+content+''
+ '
'+renderTotpDisableModal()+'
';
}
function render(){
- if(state.phase==='loading'){ app.innerHTML=''; return; }
+ if(state.phase==='loading'){ app.innerHTML=''; return; }
if(state.phase==='register'){ app.innerHTML=renderRegisterScreen(); return; }
if(state.phase==='login'){ app.innerHTML=renderLoginScreen(); return; }
app.innerHTML=renderApp();