// 主应用类 class WorkListApp { constructor() { this.tasks = []; this.currentEditingTask = null; this.currentFilter = 'all'; this.excludedStatuses = new Set(); this.currentUser = null; this.init(); } // 初始化应用 async init() { // 先检查登录状态 await this.checkAuthStatus(); // 如果已登录,绑定事件并加载任务 if (this.currentUser) { this.bindEvents(); this.loadTasks(); this.setupDatePicker(); } } // 检查认证状态 async checkAuthStatus() { try { const response = await api.checkAuth(); if (response.authenticated) { this.currentUser = response.user; this.showMainApp(); } else { this.showLoginPage(); } } catch (error) { console.log('未登录:', error); this.showLoginPage(); } } // 显示登录页面 showLoginPage() { document.getElementById('loginPage').style.display = 'flex'; document.getElementById('mainApp').style.display = 'none'; // 绑定登录表单事件 const loginForm = document.getElementById('loginForm'); loginForm.addEventListener('submit', async (e) => { e.preventDefault(); await this.handleLogin(); }); } // 显示主应用页面 showMainApp() { document.getElementById('loginPage').style.display = 'none'; document.getElementById('mainApp').style.display = 'block'; // 显示用户名 if (this.currentUser) { document.getElementById('currentUsername').textContent = this.currentUser.username; } } // 处理登录 async handleLogin() { const username = document.getElementById('loginUsername').value; const password = document.getElementById('loginPassword').value; const errorDiv = document.getElementById('loginError'); try { errorDiv.style.display = 'none'; const response = await api.login(username, password); if (response.user) { this.currentUser = response.user; this.showMainApp(); // 绑定事件并加载任务 this.bindEvents(); this.loadTasks(); this.setupDatePicker(); } } catch (error) { errorDiv.textContent = error.message || '登录失败,请检查用户名和密码'; errorDiv.style.display = 'block'; } } // 处理登出 async handleLogout() { try { await api.logout(); this.currentUser = null; this.tasks = []; this.showLoginPage(); } catch (error) { console.error('登出失败:', error); alert('登出失败: ' + error.message); } } // 绑定事件 bindEvents() { // 登出按钮 const logoutBtn = document.getElementById('logoutBtn'); if (logoutBtn && !logoutBtn.hasAttribute('data-bound')) { logoutBtn.addEventListener('click', () => { this.handleLogout(); }); logoutBtn.setAttribute('data-bound', 'true'); } // 添加任务按钮 document.getElementById('addTaskBtn').addEventListener('click', () => { this.showTaskModal(); }); // 报表按钮 document.getElementById('reportBtn').addEventListener('click', () => { this.showReportModal(); }); // 时间历史按钮 document.getElementById('timeHistoryBtn').addEventListener('click', () => { this.showTimeHistoryModal(); }); // 模态框关闭 document.querySelectorAll('.close').forEach(closeBtn => { closeBtn.addEventListener('click', (e) => { const modal = e.target.closest('.modal'); this.hideModal(modal); }); }); // 点击模态框外部关闭 document.querySelectorAll('.modal').forEach(modal => { modal.addEventListener('click', (e) => { if (e.target === modal) { this.hideModal(modal); } }); }); // 任务表单 document.getElementById('saveBtn').addEventListener('click', () => { this.saveTask(); }); document.getElementById('cancelBtn').addEventListener('click', () => { this.hideModal(document.getElementById('taskModal')); }); // AI润色按钮 document.getElementById('polishBtn').addEventListener('click', () => { this.polishDescription(); }); // 润色相关按钮 document.getElementById('usePolishedBtn').addEventListener('click', () => { this.usePolishedDescription(); }); document.getElementById('discardPolishedBtn').addEventListener('click', () => { this.discardPolishedDescription(); }); // 报表加载按钮 document.getElementById('loadReportBtn').addEventListener('click', () => { this.loadReport(); }); // 历史记录加载按钮 document.getElementById('loadHistoryBtn').addEventListener('click', () => { this.loadTimeHistory(); }); // 任务历史加载按钮 document.getElementById('loadTaskHistoryBtn').addEventListener('click', () => { this.loadTaskTimeHistory(); }); // 任务筛选按钮 document.querySelectorAll('.filter-btn').forEach(btn => { btn.addEventListener('click', (event) => { const filter = event.currentTarget.dataset.filter; this.setTaskFilter(filter); }); }); // 排除状态按钮 document.querySelectorAll('.exclusion-btn').forEach(btn => { btn.addEventListener('click', (event) => { const status = event.currentTarget.dataset.status; this.toggleExcludeStatus(status); }); }); } // 设置日期选择器 setupDatePicker() { const dateInput = document.getElementById('reportDate'); const today = new Date().toISOString().split('T')[0]; dateInput.value = today; } // 显示加载提示 showLoading() { document.getElementById('loadingOverlay').style.display = 'flex'; } // 隐藏加载提示 hideLoading() { document.getElementById('loadingOverlay').style.display = 'none'; } // 显示模态框 showModal(modalId) { const modal = document.getElementById(modalId); modal.style.display = 'block'; document.body.style.overflow = 'hidden'; } // 隐藏模态框 hideModal(modal) { modal.style.display = 'none'; document.body.style.overflow = 'auto'; } // 显示任务模态框 showTaskModal(task = null) { this.currentEditingTask = task; const modal = document.getElementById('taskModal'); const form = document.getElementById('taskForm'); if (task) { // 编辑模式 document.getElementById('modalTitle').textContent = '编辑任务'; document.getElementById('taskTitle').value = task.title; document.getElementById('taskDescription').value = task.description || ''; document.getElementById('taskStatus').value = task.status; } else { // 新建模式 document.getElementById('modalTitle').textContent = '添加任务'; form.reset(); } // 隐藏润色内容 document.getElementById('polishedDescription').style.display = 'none'; this.showModal('taskModal'); } // 保存任务 async saveTask() { try { this.showLoading(); const formData = { title: document.getElementById('taskTitle').value.trim(), description: document.getElementById('taskDescription').value.trim(), status: document.getElementById('taskStatus').value }; if (!formData.title) { throw new Error('任务标题不能为空'); } let savedTask; if (this.currentEditingTask) { // 更新任务 savedTask = await api.updateTask(this.currentEditingTask.id, formData); } else { // 创建任务 savedTask = await api.createTask(formData); } this.hideModal(document.getElementById('taskModal')); await this.loadTasks(); this.showNotification('任务保存成功', 'success'); } catch (error) { console.error('保存任务失败:', error); this.showNotification(error.message || '保存任务失败', 'error'); } finally { this.hideLoading(); } } // 删除任务 async deleteTask(taskId) { if (!confirm('确定要删除这个任务吗?')) { return; } try { this.showLoading(); await api.deleteTask(taskId); await this.loadTasks(); this.showNotification('任务删除成功', 'success'); } catch (error) { console.error('删除任务失败:', error); this.showNotification(error.message || '删除任务失败', 'error'); } finally { this.hideLoading(); } } // 开始计时 async startTimer(taskId) { try { this.showLoading(); await taskTimer.startTimer(taskId); this.updateTaskStatusLocal(taskId, 'in_progress'); this.renderTasks(); this.updateStats(); this.showNotification('计时开始', 'success'); } catch (error) { console.error('开始计时失败:', error); this.showNotification(error.message || '开始计时失败', 'error'); } finally { this.hideLoading(); } } // 停止计时 async stopTimer(taskId) { try { this.showLoading(); await taskTimer.stopTimer(taskId); this.updateTaskStatusLocal(taskId, 'pending'); this.renderTasks(); this.updateStats(); this.showNotification('计时结束', 'success'); } catch (error) { console.error('停止计时失败:', error); this.showNotification(error.message || '停止计时失败', 'error'); } finally { this.hideLoading(); } } // AI润色描述 async polishDescription() { const description = document.getElementById('taskDescription').value.trim(); if (!description) { this.showNotification('请先输入任务描述', 'warning'); return; } try { this.showLoading(); // 如果有正在编辑的任务,使用其ID;否则提示用户先保存任务 if (!this.currentEditingTask) { this.showNotification('请先保存任务,然后再进行润色', 'warning'); return; } const result = await api.polishTaskDescription(this.currentEditingTask.id); // 显示润色结果 const polishedDiv = document.getElementById('polishedDescription'); const polishedText = polishedDiv.querySelector('.polished-text'); polishedText.textContent = result.polished; polishedDiv.style.display = 'block'; this.showNotification('AI润色完成', 'success'); } catch (error) { console.error('AI润色失败:', error); this.showNotification(error.message || 'AI润色失败', 'error'); } finally { this.hideLoading(); } } // 使用润色版本 usePolishedDescription() { const polishedText = document.querySelector('.polished-text').textContent; document.getElementById('taskDescription').value = polishedText; document.getElementById('polishedDescription').style.display = 'none'; this.showNotification('已使用润色版本', 'success'); } // 丢弃润色版本 discardPolishedDescription() { document.getElementById('polishedDescription').style.display = 'none'; } // 加载任务列表 async loadTasks() { try { this.tasks = await api.getTasks(); // 恢复未结束的计时器(需要在渲染之前) await taskTimer.restoreTimers(this.tasks); this.renderTasks(); this.updateStats(); } catch (error) { console.error('加载任务失败:', error); this.showNotification('加载任务失败', 'error'); } } // 设置任务状态筛选 setTaskFilter(filter = 'all') { const normalized = filter || 'all'; if (this.currentFilter !== normalized) { this.currentFilter = normalized; } this.renderTasks(); } // 更新筛选按钮状态 updateFilterButtons() { document.querySelectorAll('.filter-btn').forEach(btn => { const isActive = btn.dataset.filter === this.currentFilter; btn.classList.toggle('active', isActive); }); } // 切换排除状态 toggleExcludeStatus(status) { if (this.excludedStatuses.has(status)) { this.excludedStatuses.delete(status); } else { this.excludedStatuses.add(status); } this.renderTasks(); } // 更新排除按钮状态 updateExclusionButtons() { document.querySelectorAll('.exclusion-btn').forEach(btn => { const status = btn.dataset.status; btn.classList.toggle('active', this.excludedStatuses.has(status)); }); } // 获取筛选后的任务列表 getFilteredTasks() { if (this.currentFilter === 'all') { return this.tasks.filter(task => !this.excludedStatuses.has(task.status)); } return this.tasks .filter(task => task.status === this.currentFilter) .filter(task => !this.excludedStatuses.has(task.status)); } // 获取筛选名称 getFilterDisplayName(filter) { const map = { 'all': '全部任务', 'pending': '未开始任务', 'in_progress': '进行中任务', 'completed': '已完成任务' }; return map[filter] || '任务'; } // 渲染任务列表 renderTasks() { const taskList = document.getElementById('taskList'); this.updateFilterButtons(); this.updateExclusionButtons(); const filteredTasks = this.getFilteredTasks(); if (this.tasks.length === 0) { taskList.innerHTML = `
点击"添加任务"开始记录你的工作
试试切换其他状态,或者新建一条任务
${report.date} 没有记录任何工作时间
在指定时间段内没有找到任何工作时间记录
该任务在指定时间段内没有工作时间记录