From b1937251f07db9dfa050271b17c5233810d29410 Mon Sep 17 00:00:00 2001 From: TYt50 <106930118+TYt50@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:27:34 +0800 Subject: [PATCH] . --- .gitignore | 1 + src/db/database.js | 25 ++++++++++++++----------- src/index.html | 9 +++++++-- src/renderer.js | 37 ++++++++++++++++++++++++++++++------- src/styles.css | 7 ++++++- 5 files changed, 58 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 639b3c9..e932326 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ node_modules/ # Database and user data (Portable data) accounts.db data/ +DB/ *.db-journal # Exports (Contains sensitive information) diff --git a/src/db/database.js b/src/db/database.js index ceb1913..714ae39 100644 --- a/src/db/database.js +++ b/src/db/database.js @@ -60,10 +60,11 @@ class AccountDatabase { ) `); - // 迁移: 添加 tags 和 vault_id 和 proxy 列 (如果不存在) + // 迁移: 添加 tags 和 vault_id 和 proxy 和 browser_id 列 (如果不存在) try { this.db.run(`ALTER TABLE accounts ADD COLUMN tags TEXT`); } catch (e) { } try { this.db.run(`ALTER TABLE accounts ADD COLUMN vault_id INTEGER`); } catch (e) { } try { this.db.run(`ALTER TABLE accounts ADD COLUMN proxy TEXT`); } catch (e) { } + try { this.db.run(`ALTER TABLE accounts ADD COLUMN browser_id TEXT`); } catch (e) { } // 创建默认资料库 (如果不存在) const defaultVault = this.db.exec("SELECT id FROM vaults WHERE name = '默认'"); @@ -107,10 +108,10 @@ class AccountDatabase { async getVaults() { await this.ready; const result = this.db.exec(` - SELECT v.*, COUNT(a.id) as account_count - FROM vaults v - LEFT JOIN accounts a ON a.vault_id = v.id - GROUP BY v.id + SELECT v.*, COUNT(a.id) as account_count + FROM vaults v + LEFT JOIN accounts a ON a.vault_id = v.id + GROUP BY v.id ORDER BY v.created_at ASC `); @@ -218,8 +219,8 @@ class AccountDatabase { await this.ready; this.db.run(` - INSERT INTO accounts (vault_id, name, username, password, totp_secret, tags, email, proxy, notes) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + INSERT INTO accounts (vault_id, name, username, password, totp_secret, tags, email, proxy, notes, browser_id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `, [ account.vault_id || null, account.name, @@ -229,7 +230,8 @@ class AccountDatabase { account.tags || '', account.email, account.proxy || '', - account.notes + account.notes, + account.browser_id || '' ]); this.save(); @@ -244,9 +246,9 @@ class AccountDatabase { await this.ready; this.db.run(` - UPDATE accounts - SET vault_id = ?, name = ?, username = ?, password = ?, totp_secret = ?, - tags = ?, email = ?, proxy = ?, notes = ?, updated_at = datetime('now') + UPDATE accounts + SET vault_id = ?, name = ?, username = ?, password = ?, totp_secret = ?, + tags = ?, email = ?, proxy = ?, notes = ?, browser_id = ?, updated_at = datetime('now') WHERE id = ? `, [ account.vault_id || null, @@ -258,6 +260,7 @@ class AccountDatabase { account.email, account.proxy || '', account.notes, + account.browser_id || '', id ]); diff --git a/src/index.html b/src/index.html index 5ff9a8f..6cbf63a 100644 --- a/src/index.html +++ b/src/index.html @@ -5,7 +5,7 @@ + content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; font-src 'self' data: https://cdnjs.cloudflare.com; connect-src 'self' http://localhost:12138 http://127.0.0.1:12138"> 2FA 账号管理器 @@ -108,6 +108,11 @@ +
+ + +
+
@@ -195,4 +200,4 @@ - \ No newline at end of file + diff --git a/src/renderer.js b/src/renderer.js index ed340e7..342f745 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -190,7 +190,7 @@ function renderVaultList() { } vaultList.innerHTML = vaults.map(v => ` -
${escapeHtml(v.name)} @@ -492,6 +492,11 @@ function renderAccounts() {
${tagsHtml || '无标签'}
+ ${acc.browser_id ? ` + + ` : ''} @@ -503,35 +508,35 @@ function renderAccounts() {
- + ${acc.username ? `
账号 ${escapeHtml(acc.username)}
` : ''} - + ${acc.password ? `
密码 ••••••••
` : ''} - + ${acc.email ? `
邮箱 ${escapeHtml(acc.email)}
` : ''} - + ${acc.proxy ? `
代理 ${escapeHtml(acc.proxy)}
` : ''} - + ${acc.totp_secret ? `
@@ -542,7 +547,7 @@ function renderAccounts() {
-
@@ -657,6 +662,7 @@ async function handleFormSubmit(e) { tags: tags, email: document.getElementById('email').value.trim(), proxy: document.getElementById('proxy').value.trim(), + browser_id: document.getElementById('browserId').value.trim(), notes: document.getElementById('notes').value.trim() }; @@ -695,6 +701,7 @@ function editAccount(id) { document.getElementById('totpSecret').value = acc.totp_secret || ''; document.getElementById('email').value = acc.email || ''; document.getElementById('proxy').value = acc.proxy || ''; + document.getElementById('browserId').value = acc.browser_id || ''; document.getElementById('tags').value = acc.tags || ''; document.getElementById('notes').value = acc.notes || ''; @@ -744,6 +751,22 @@ async function copyToClipboard(text) { } } +// 打开 Browser 浏览器环境 +async function openBrowser(idOrName) { + try { + const response = await fetch(`http://localhost:12138/api/open/${encodeURIComponent(idOrName)}`); + if (response.ok) { + showToast('正在启动 Browser 环境...', 'success'); + } else { + const error = await response.text(); + showToast(`启动失败: ${error}`, 'error'); + } + } catch (e) { + console.error('Open browser failed:', e); + showToast('无法连接 Browser API,请确保 Browser 已启动并开启 API 服务', 'error'); + } +} + // 生成随机名称 (不含符号的长用户名) function generateRandomName() { const firstName = firstNames[Math.floor(Math.random() * firstNames.length)]; diff --git a/src/styles.css b/src/styles.css index bb5cce4..20c615b 100644 --- a/src/styles.css +++ b/src/styles.css @@ -600,6 +600,11 @@ body { color: var(--danger); } +.card-action-btn.browser:hover { + background: rgba(59, 130, 246, 0.15); + color: var(--accent); +} + /* 信息行 - 点击复制 */ .info-row { display: flex; @@ -1302,4 +1307,4 @@ body { display: flex; align-items: center; gap: 8px; -} \ No newline at end of file +}