document.addEventListener('DOMContentLoaded', () => { const addBtn = document.getElementById('add-btn'); const addForm = document.getElementById('add-form'); const cancelBtn = document.getElementById('cancel-btn'); const saveBtn = document.getElementById('save-btn'); const envSelect = document.getElementById('env-select'); const clientInput = document.getElementById('client-input'); const usernameInput = document.getElementById('username-input'); const passwordInput = document.getElementById('password-input'); const rulesList = document.getElementById('rules-list'); const rulesContainer = document.querySelector('.rules-container'); const formTitle = document.getElementById('form-title'); const editingIdInput = document.getElementById('editing-id'); const loginView = document.getElementById('login-view'); const registerView = document.getElementById('register-view'); const appView = document.getElementById('app-view'); const authLoginBtn = document.getElementById('auth-login-btn'); const authRegBtn = document.getElementById('auth-reg-btn'); const goToRegister = document.getElementById('go-to-register'); const goToLogin = document.getElementById('go-to-login'); const logoutBtn = document.getElementById('logout-btn'); if (logoutBtn) { logoutBtn.addEventListener('click', (e) => { e.preventDefault(); if (confirm('确定要退出当前同步账号吗?')) { chrome.storage.local.remove(['quickPurgeUser'], () => { currentUser = null; rules = []; renderRules(); // 立即清空界面显示的 rules showView('login'); }); } }); } const ENV_CONFIG = { DD_PP: { domain: 'app135148.dingtalkoxm.com', url: 'https://app135148.dingtalkoxm.com/user/login' }, DD_ATS: { domain: 'app135149.dingtalkoxm.com', url: 'https://app135149.dingtalkoxm.com/login' }, STD_PP: { domain: 'core.mokahr.com', url: 'https://core.mokahr.com' }, STD_ATS: { domain: 'app.mokahr.com', url: 'https://app.mokahr.com' } }; const API_BASE = 'https://sqd.zhouzishen.cn/api'; // 已更新为您的生产服务器地址 let currentUser = null; let rules = []; let dragStartIndex = -1; // --- 工具函数 --- function hasChinese(str) { return /[\u4E00-\u9FA5]/.test(str); } // --- Auth View Controllers --- function showView(viewName) { if (loginView) loginView.classList.add('hidden'); if (registerView) registerView.classList.add('hidden'); if (appView) appView.classList.add('hidden'); if (viewName === 'app') { if (appView) appView.classList.remove('hidden'); } else { if (viewName === 'login' && loginView) loginView.classList.remove('hidden'); else if (viewName === 'register' && registerView) registerView.classList.remove('hidden'); } } if (goToRegister) goToRegister.addEventListener('click', (e) => { e.preventDefault(); showView('register'); }); if (goToLogin) goToLogin.addEventListener('click', (e) => { e.preventDefault(); showView('login'); }); if (authRegBtn) { authRegBtn.addEventListener('click', async () => { const username = document.getElementById('auth-reg-username').value.trim(); const password = document.getElementById('auth-reg-password').value; const inviteCode = document.getElementById('auth-reg-invite').value.trim(); if (!username || !password || !inviteCode) return alert('请填写完整信息'); if (hasChinese(username) || hasChinese(password) || hasChinese(inviteCode)) { return alert('账号、密码和邀请码不允许包含中文字符'); } authRegBtn.textContent = '注册中...'; try { const res = await fetch(`${API_BASE}/register`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password, inviteCode }) }); const data = await res.json(); if (data.code === 0) { alert('注册成功,请使用该账号登录'); document.getElementById('auth-login-username').value = username; document.getElementById('auth-login-password').value = password; showView('login'); } else alert(data.msg); } catch (e) { alert('请求失败,请确保本地服务器已启动运行。' + e); } finally { authRegBtn.textContent = '注册'; } }); } if (authLoginBtn) { authLoginBtn.addEventListener('click', async () => { const username = document.getElementById('auth-login-username').value.trim(); const password = document.getElementById('auth-login-password').value; if (!username || !password) return alert('请输入账号和密码'); if (hasChinese(username) || hasChinese(password)) { return alert('账号和密码格式不正确(不能包含中文)'); } authLoginBtn.textContent = '登录中...'; try { const res = await fetch(`${API_BASE}/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); const data = await res.json(); if (data.code === 0) { currentUser = { username, password }; rules = processLoadedRules(data.data.rules || []); chrome.storage.local.set({ quickPurgeUser: { username, password, rules } }, () => { showView('app'); renderRules(); }); } else alert(data.msg); } catch (e) { alert('请求失败,请确保本地服务器已启动运行。' + e); } finally { authLoginBtn.textContent = '登录'; } }); } // Load Init from local cache function loadAndInitBaseApp() { if (typeof chrome !== 'undefined' && chrome.storage) { chrome.storage.local.get(['quickPurgeUser'], async (result) => { const user = result.quickPurgeUser; if (user && user.username && user.password) { currentUser = user; rules = processLoadedRules(user.rules || []); showView('app'); // Proceed to app UI renderRules(); // 静默发起登录获取云端最新数据 try { const res = await fetch(`${API_BASE}/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: user.username, password: user.password }) }); const data = await res.json(); if (data.code === 0) { rules = processLoadedRules(data.data.rules || []); chrome.storage.local.set({ quickPurgeUser: { ...currentUser, rules } }); renderRules(); } } catch (e) { console.log("Offline mode, using local storage cache fallback."); } } else { showView('login'); // Not logged in } }); } else { showView('login'); } } function processLoadedRules(rawRules) { return rawRules.map(rule => { if (rule.env === 'PP') rule.env = 'DD_PP'; if (rule.env === 'ATS') rule.env = 'DD_ATS'; return rule; }); } function saveRules() { if (typeof chrome !== 'undefined' && chrome.storage && currentUser) { chrome.storage.local.set({ quickPurgeUser: { ...currentUser, rules } }, () => { renderRules(); // 异步防抖提交到自建服务云端 fetch(`${API_BASE}/sync`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: currentUser.username, rules }) }).catch(e => console.error("Sync error:", e)); }); } else { renderRules(); } } function toggleAddForm(mode = 'add', ruleId = null) { if (mode === 'edit') { const rule = rules.find(r => r.id === ruleId); if (rule) { formTitle.textContent = '编辑配置'; editingIdInput.value = rule.id; envSelect.value = rule.env; clientInput.value = rule.clientName; usernameInput.value = rule.username; passwordInput.value = rule.password; addForm.classList.remove('hidden'); rulesContainer.classList.add('hidden'); addBtn.classList.add('hidden'); // Optional: hide add btn while editing } } else { formTitle.textContent = '添加配置'; editingIdInput.value = ''; resetForm(); addForm.classList.toggle('hidden'); if (addForm.classList.contains('hidden')) { rulesContainer.classList.remove('hidden'); addBtn.classList.remove('hidden'); } else { rulesContainer.classList.add('hidden'); addBtn.classList.add('hidden'); } } if (!addForm.classList.contains('hidden')) { clientInput.focus(); } } addBtn.addEventListener('click', () => toggleAddForm('add')); cancelBtn.addEventListener('click', () => { addForm.classList.add('hidden'); rulesContainer.classList.remove('hidden'); addBtn.classList.remove('hidden'); resetForm(); }); function resetForm() { editingIdInput.value = ''; envSelect.value = 'DD_PP'; clientInput.value = ''; usernameInput.value = ''; passwordInput.value = ''; } saveBtn.addEventListener('click', () => { const env = envSelect.value; const clientName = clientInput.value.trim(); const username = usernameInput.value.trim(); const password = passwordInput.value; const editingId = editingIdInput.value; if (!clientName || !username || !password) { alert('请填写完整的客户名称、账号和密码!'); return; } if (editingId) { // Update existing rule const index = rules.findIndex(r => r.id === editingId); if (index !== -1) { rules[index] = { ...rules[index], env: env, clientName: clientName, username: username, password: password }; } } else { // Add new rule rules.push({ id: Date.now().toString(), env: env, clientName: clientName, username: username, password: password }); } saveRules(); addForm.classList.add('hidden'); rulesContainer.classList.remove('hidden'); addBtn.classList.remove('hidden'); resetForm(); }); function renderRules() { rulesList.innerHTML = ''; if (rules.length === 0) { rulesList.innerHTML = `
暂无账号配置,点击上方 "+" 添加
`; return; } rules.forEach((rule, index) => { const li = document.createElement('li'); li.className = 'rule-item'; li.setAttribute('draggable', 'true'); li.setAttribute('data-index', index.toString()); li.innerHTML = `
${rule.clientName} ${rule.env.replace('_', ' ')}
帐号: ${rule.username}
`; addDragEvents(li); rulesList.appendChild(li); }); 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); } }); }); document.querySelectorAll('.btn-edit').forEach(btn => { btn.addEventListener('click', (e) => { e.stopPropagation(); const id = e.currentTarget.getAttribute('data-id'); toggleAddForm('edit', id); }); }); document.querySelectorAll('.btn-delete').forEach(btn => { btn.addEventListener('click', (e) => { e.stopPropagation(); const id = e.currentTarget.getAttribute('data-id'); if (confirm('确定要删除此配置吗?')) { rules = rules.filter(r => r.id !== id); saveRules(); } }); }); } // --- Drag and Drop functionality --- function addDragEvents(item) { item.addEventListener('dragstart', (e) => { dragStartIndex = parseInt(e.currentTarget.getAttribute('data-index')); e.currentTarget.classList.add('dragging'); // Set empty ghost image if (e.dataTransfer) { e.dataTransfer.effectAllowed = 'move'; // Need to set data to allow dragging in Firefox e.dataTransfer.setData('text/plain', dragStartIndex); } }); item.addEventListener('dragend', (e) => { e.currentTarget.classList.remove('dragging'); }); item.addEventListener('dragover', (e) => { e.preventDefault(); // Allow drop return false; }); item.addEventListener('dragenter', (e) => { e.preventDefault(); }); item.addEventListener('drop', (e) => { e.stopPropagation(); const dragEndIndex = parseInt(e.currentTarget.closest('.rule-item').getAttribute('data-index')); if (dragStartIndex !== dragEndIndex) { swapItems(dragStartIndex, dragEndIndex); } return false; }); } function swapItems(fromIndex, toIndex) { // Array manipulation for drag sorting const itemOne = rules[fromIndex]; rules.splice(fromIndex, 1); rules.splice(toIndex, 0, itemOne); saveRules(); } function executePurgeAndLogin(rule, element) { const originalContent = element.innerHTML; element.innerHTML = `
清理中...
`; if (typeof chrome !== 'undefined' && chrome.runtime) { const config = ENV_CONFIG[rule.env]; chrome.runtime.sendMessage({ action: "purgeAndRedirect", domain: config.domain, targetUrl: config.url, username: rule.username, password: rule.password }, (response) => { // Return text after a short delay setTimeout(() => { if (element) element.innerHTML = originalContent; }, 1500); }); } } loadAndInitBaseApp(); });