const { ipcRenderer } = require('electron'); const { chromium } = require('playwright'); let browser = null; let page = null; const loginForm = document.getElementById('loginForm'); const attendanceButtons = document.getElementById('attendanceButtons'); const userInfo = document.getElementById('userInfo'); const statusDiv = document.getElementById('status'); const usernameInput = document.getElementById('username'); const passwordInput = document.getElementById('password'); const rememberCheckbox = document.getElementById('remember'); // User info elements const userNameSpan = document.getElementById('userName'); const checkInTimeSpan = document.getElementById('checkInTime'); const checkOutTimeSpan = document.getElementById('checkOutTime'); // Load saved credentials async function loadSavedCredentials() { const credentials = await ipcRenderer.invoke('get-credentials'); if (credentials) { usernameInput.value = credentials.username || ''; passwordInput.value = credentials.password || ''; rememberCheckbox.checked = true; } } loadSavedCredentials(); async function initBrowser() { if (!browser) { browser = await chromium.launch({ headless: true, // 使用无头模式 slowMo: 50 // 保留较小的延迟以确保稳定性 }); } if (!page) { page = await browser.newPage(); await page.setDefaultTimeout(60000); await page.setDefaultNavigationTimeout(60000); } } async function updateAttendanceStatus() { try { const userInfo = await page.evaluate(() => { const rows = document.querySelectorAll('#Table1 tbody tr'); if (rows.length > 1) { const row = rows[1]; return { name: row.children[1].textContent.trim(), checkInTime: row.children[2].children[0].children[0].children[0].children[2].children[1].textContent.trim(), checkOutTime: row.children[2].children[0].children[0].children[0].children[3].children[1].textContent.trim() }; } return null; }); if (userInfo) { userNameSpan.textContent = userInfo.name; checkInTimeSpan.textContent = userInfo.checkInTime; checkOutTimeSpan.textContent = userInfo.checkOutTime; // 更新按钮状态 const checkInBtn = document.getElementById('checkInBtn'); const checkOutBtn = document.getElementById('checkOutBtn'); if (userInfo.checkInTime === '00:00' || userInfo.checkInTime === '') { checkInBtn.disabled = false; checkInBtn.textContent = '上班打卡'; } else { checkInBtn.disabled = true; checkInBtn.textContent = '已打卡'; } if (userInfo.checkOutTime === '00:00' && userInfo.checkInTime !== '00:00') { checkOutBtn.disabled = false; checkOutBtn.textContent = '下班打卡'; } else { checkOutBtn.disabled = true; checkOutBtn.textContent = userInfo.checkOutTime === '00:00' ? '未到下班时间' : '已打卡'; } } } catch (error) { console.error('获取考勤状态失败:', error); } } async function login() { try { await initBrowser(); statusDiv.textContent = '正在登录...'; // 导航到登录页面 await page.goto('http://hy.zhushitrade.cn/groupware/index.asp', { waitUntil: 'networkidle', timeout: 60000 }); // 等待输入框出现 await page.waitForSelector('#userId', { timeout: 60000 }); await page.waitForSelector('#userPassword', { timeout: 60000 }); // 清除现有输入 await page.evaluate(() => { document.getElementById('userId').value = ''; document.getElementById('userPassword').value = ''; }); // 输入凭据 await page.fill('#userId', usernameInput.value); await page.fill('#userPassword', passwordInput.value); if (rememberCheckbox.checked) { await ipcRenderer.invoke('save-credentials', { username: usernameInput.value, password: passwordInput.value }); } // 点击登录并等待响应 const navigationPromise = page.waitForNavigation({ waitUntil: 'networkidle', timeout: 60000 }); await page.click('#btn_login'); await navigationPromise; // 验证登录是否成功 const currentUrl = page.url(); if (currentUrl.includes('index.asp')) { statusDiv.textContent = '登录失败: 可能是用户名或密码错误'; return; } // 更新用户信息和考勤状态 await updateAttendanceStatus(); statusDiv.textContent = '登录成功'; loginForm.style.display = 'none'; userInfo.style.display = 'block'; attendanceButtons.style.display = 'block'; } catch (error) { console.error('登录错误:', error); statusDiv.textContent = '登录失败: ' + (error.message || '网络连接问题,请检查网络后重试'); // 如果是超时错误,尝试重新初始化浏览器 if (error.name === 'TimeoutError') { try { if (browser) { await browser.close(); } browser = null; page = null; } catch (closeError) { console.error('关闭浏览器失败:', closeError); } } } } async function checkIn() { try { if (!page) { statusDiv.textContent = '请先登录'; return; } statusDiv.textContent = '正在打卡...'; await page.goto('http://hy.zhushitrade.cn/groupware/editCheckWork.asp?action=onDuty', { waitUntil: 'networkidle', timeout: 60000 }); await page.waitForTimeout(2000); await updateAttendanceStatus(); statusDiv.textContent = '上班打卡成功'; } catch (error) { console.error('打卡错误:', error); statusDiv.textContent = '打卡失败: ' + (error.message || '请检查网络连接'); } } async function checkOut() { try { if (!page) { statusDiv.textContent = '请先登录'; return; } statusDiv.textContent = '正在打卡...'; await page.goto('http://hy.zhushitrade.cn/groupware/editcheckwork.asp?action=offDuty', { waitUntil: 'networkidle', timeout: 60000 }); await page.waitForTimeout(2000); await updateAttendanceStatus(); statusDiv.textContent = '下班打卡成功'; } catch (error) { console.error('打卡错误:', error); statusDiv.textContent = '打卡失败: ' + (error.message || '请检查网络连接'); } } // 定时更新考勤状态 setInterval(async () => { if (page && userInfo.style.display === 'block') { await updateAttendanceStatus(); } }, 60000); // 每分钟更新一次 // Event Listeners document.getElementById('loginBtn').addEventListener('click', login); document.getElementById('checkInBtn').addEventListener('click', checkIn); document.getElementById('checkOutBtn').addEventListener('click', checkOut); // Cleanup on window close window.addEventListener('beforeunload', async () => { if (browser) { await browser.close(); } });