feat: implement account archiving system and brand logo upgrade
This commit is contained in:
28
popup.css
28
popup.css
@@ -34,14 +34,26 @@ body {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
background: linear-gradient(90deg, #2563eb, #3b82f6);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
filter: drop-shadow(0 2px 4px rgba(59, 130, 246, 0.2));
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.logo:hover {
|
||||
transform: scale(1.05) rotate(2deg);
|
||||
}
|
||||
|
||||
#archive-toggle {
|
||||
color: var(--text-secondary);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
#archive-toggle:hover {
|
||||
opacity: 1;
|
||||
background: rgba(100, 116, 139, 0.1);
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
|
||||
39
popup.html
39
popup.html
@@ -11,7 +11,29 @@
|
||||
<body>
|
||||
<div id="app-view">
|
||||
<div class="header">
|
||||
<h1>清速登</h1>
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<button id="archive-toggle" class="icon-btn" title="查看已归档项目" style="padding: 4px;">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M21 8v13H3V8M1 3h22v5H1V3zm10 8h2" />
|
||||
</svg>
|
||||
</button>
|
||||
<div class="logo">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 2L2 7L12 12L22 7L12 2Z" fill="url(#logo-grad)" stroke="white" stroke-width="1.5"
|
||||
stroke-linejoin="round" />
|
||||
<path d="M2 17L12 22L22 17" stroke="url(#logo-grad)" stroke-width="1.5" stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
<path d="M2 12L12 17L22 12" stroke="url(#logo-grad)" stroke-width="1.5" stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
<defs>
|
||||
<linearGradient id="logo-grad" x1="2" y1="2" x2="22" y2="22" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3b82f6" />
|
||||
<stop offset="1" stop-color="#8b5cf6" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#" id="logout-btn"
|
||||
style="font-size: 11px; color: var(--text-secondary); text-decoration: none; margin-right: 8px;">切换账号</a>
|
||||
@@ -22,6 +44,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main-view-content">
|
||||
<div id="add-form" class="hidden">
|
||||
<h2 id="form-title">添加配置</h2>
|
||||
<input type="hidden" id="editing-id" />
|
||||
@@ -55,6 +78,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="archive-view-content" class="hidden">
|
||||
<div
|
||||
style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; border-bottom: 1px dashed var(--border-color); padding-bottom: 8px;">
|
||||
<h2 style="font-size: 13px; margin: 0; color: var(--text-secondary); font-weight: 500;">已归档账号</h2>
|
||||
<button id="back-to-main" class="secondary-btn" style="padding: 2px 8px; font-size: 11px;">返回列表</button>
|
||||
</div>
|
||||
<div class="rules-container">
|
||||
<ul id="archive-list">
|
||||
<!-- Archived rules will be inserted here -->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 登录视图 -->
|
||||
<div id="login-view" class="view-container">
|
||||
<div class="auth-box">
|
||||
|
||||
101
popup.js
101
popup.js
@@ -21,6 +21,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const goToRegister = document.getElementById('go-to-register');
|
||||
const goToLogin = document.getElementById('go-to-login');
|
||||
const logoutBtn = document.getElementById('logout-btn');
|
||||
const archiveToggle = document.getElementById('archive-toggle');
|
||||
const backToMain = document.getElementById('back-to-main');
|
||||
const mainViewContent = document.getElementById('main-view-content');
|
||||
const archiveViewContent = document.getElementById('archive-view-content');
|
||||
const archiveList = document.getElementById('archive-list');
|
||||
|
||||
if (logoutBtn) {
|
||||
logoutBtn.addEventListener('click', (e) => {
|
||||
@@ -294,8 +299,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
function renderRules() {
|
||||
rulesList.innerHTML = '';
|
||||
const activeRules = rules.filter(r => !r.archived);
|
||||
|
||||
if (rules.length === 0) {
|
||||
if (activeRules.length === 0) {
|
||||
rulesList.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
@@ -308,7 +314,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
return;
|
||||
}
|
||||
|
||||
rules.forEach((rule, index) => {
|
||||
activeRules.forEach((rule, index) => {
|
||||
const li = document.createElement('li');
|
||||
li.className = 'rule-item';
|
||||
li.setAttribute('draggable', 'true');
|
||||
@@ -331,8 +337,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button class="icon-btn btn-delete" data-id="${rule.id}" title="删除此配置">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/></svg>
|
||||
<button class="icon-btn btn-delete" data-id="${rule.id}" title="归档此配置">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M20 7l-8 8-4-4m12 4v5a2 2 0 01-2 2H6a2 2 0 01-2-2V9a2 2 0 012-2h5" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
@@ -341,21 +349,75 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
rulesList.appendChild(li);
|
||||
});
|
||||
|
||||
attachRuleEvents();
|
||||
}
|
||||
|
||||
function renderArchive() {
|
||||
archiveList.innerHTML = '';
|
||||
const archivedRules = rules.filter(r => r.archived);
|
||||
|
||||
if (archivedRules.length === 0) {
|
||||
archiveList.innerHTML = '<div class="empty-state" style="padding: 20px 0;"><span>暂无归档内容</span></div>';
|
||||
return;
|
||||
}
|
||||
|
||||
archivedRules.forEach(rule => {
|
||||
const li = document.createElement('li');
|
||||
li.className = 'rule-item';
|
||||
li.innerHTML = `
|
||||
<div class="rule-info">
|
||||
<div class="rule-domain">${rule.clientName} <span class="rule-env env-${rule.env.toLowerCase().replace('_', '-')}">${rule.env.replace('_', ' ')}</span></div>
|
||||
<div class="rule-acc">帐号: ${rule.username}</div>
|
||||
</div>
|
||||
<div class="rule-actions">
|
||||
<button class="icon-btn btn-restore" data-id="${rule.id}" title="恢复到主列表">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>
|
||||
</button>
|
||||
<button class="icon-btn btn-delete-perm" data-id="${rule.id}" title="彻底删除">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
archiveList.appendChild(li);
|
||||
});
|
||||
|
||||
document.querySelectorAll('.btn-restore').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
const id = e.currentTarget.getAttribute('data-id');
|
||||
const index = rules.findIndex(r => r.id === id);
|
||||
if (index !== -1) {
|
||||
rules[index].archived = false;
|
||||
saveRules();
|
||||
renderArchive();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('.btn-delete-perm').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
const id = e.currentTarget.getAttribute('data-id');
|
||||
if (confirm('确定要彻底删除此配置吗?此操作不可撤销。')) {
|
||||
rules = rules.filter(r => r.id !== id);
|
||||
saveRules();
|
||||
renderArchive();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function attachRuleEvents() {
|
||||
document.querySelectorAll('.rule-info').forEach(infoArea => {
|
||||
infoArea.addEventListener('click', (e) => {
|
||||
const id = e.currentTarget.getAttribute('data-id');
|
||||
const rule = rules.find(r => r.id === id);
|
||||
if (rule) {
|
||||
executePurgeAndLogin(rule, e.currentTarget);
|
||||
}
|
||||
if (rule) executePurgeAndLogin(rule, e.currentTarget);
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('.btn-edit').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const id = e.currentTarget.getAttribute('data-id');
|
||||
toggleAddForm('edit', id);
|
||||
toggleAddForm('edit', e.currentTarget.getAttribute('data-id'));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -363,14 +425,31 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const id = e.currentTarget.getAttribute('data-id');
|
||||
if (confirm('确定要删除此配置吗?')) {
|
||||
rules = rules.filter(r => r.id !== id);
|
||||
const index = rules.findIndex(r => r.id === id);
|
||||
if (index !== -1) {
|
||||
rules[index].archived = true;
|
||||
saveRules();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (archiveToggle) {
|
||||
archiveToggle.addEventListener('click', () => {
|
||||
mainViewContent.classList.add('hidden');
|
||||
archiveViewContent.classList.remove('hidden');
|
||||
renderArchive();
|
||||
});
|
||||
}
|
||||
|
||||
if (backToMain) {
|
||||
backToMain.addEventListener('click', () => {
|
||||
archiveViewContent.classList.add('hidden');
|
||||
mainViewContent.classList.remove('hidden');
|
||||
renderRules();
|
||||
});
|
||||
}
|
||||
|
||||
// --- Drag and Drop functionality ---
|
||||
function addDragEvents(item) {
|
||||
item.addEventListener('dragstart', (e) => {
|
||||
|
||||
Reference in New Issue
Block a user