.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@ node_modules/
|
||||
# Database and user data (Portable data)
|
||||
accounts.db
|
||||
data/
|
||||
DB/
|
||||
*.db-journal
|
||||
|
||||
# Exports (Contains sensitive information)
|
||||
|
||||
@@ -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 = '默认'");
|
||||
@@ -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();
|
||||
@@ -246,7 +248,7 @@ class AccountDatabase {
|
||||
this.db.run(`
|
||||
UPDATE accounts
|
||||
SET vault_id = ?, name = ?, username = ?, password = ?, totp_secret = ?,
|
||||
tags = ?, email = ?, proxy = ?, notes = ?, updated_at = datetime('now')
|
||||
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
|
||||
]);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
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">
|
||||
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">
|
||||
<title>2FA 账号管理器</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
@@ -108,6 +108,11 @@
|
||||
<input type="text" id="proxy" placeholder="如: socks5://127.0.0.1:1080">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="browserId">Browser ID</label>
|
||||
<input type="text" id="browserId" placeholder="Browser 环境 ID 或名称">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="tags">标签</label>
|
||||
<input type="text" id="tags" placeholder="用逗号分隔,如: 工作, 社交">
|
||||
|
||||
@@ -492,6 +492,11 @@ function renderAccounts() {
|
||||
<div class="card-header">
|
||||
${tagsHtml || '<span class="card-name-placeholder">无标签</span>'}
|
||||
<div class="card-actions">
|
||||
${acc.browser_id ? `
|
||||
<button class="card-action-btn browser" onclick="openBrowser('${escapeJs(acc.browser_id)}')" title="打开 Browser">
|
||||
<i class="fa-solid fa-arrow-up-right-from-square"></i>
|
||||
</button>
|
||||
` : ''}
|
||||
<button class="card-action-btn move" onclick="openMoveDialog(${acc.id})" title="迁移">
|
||||
<i class="fa-solid fa-arrow-right-arrow-left"></i>
|
||||
</button>
|
||||
@@ -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)];
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user