class TodoComponent extends HTMLElement { static { // 添加静态初始化标志 this.isInitializing = false; } constructor() { super(); this.attachShadow({ mode: 'open' }); this.todos = []; this.selectedProject = null; this.selectedSubproject = null; this.expandedProjects = new Set(); this.users = []; this.currentUser = null; this.editingTodo = null; // 当前正在编辑的待办事项 this.isInitialized = false; // 添加初始化标志 } // 初始化组件 async initialize() { // 检查是否正在初始化 if (TodoComponent.isInitializing) { return; } if (this.isInitialized) { return; } TodoComponent.isInitializing = true; try { await Promise.all([ this.fetchTodos(), this.fetchUsers(), this.getCurrentUser() ]); this.isInitialized = true; this.render(); } catch (error) { console.error('初始化组件时发生错误:', error); this.showError('初始化失败,请刷新页面重试'); } finally { TodoComponent.isInitializing = false; } } async fetchTodos() { try { const response = await fetch('/api/todos'); if (!response.ok) { throw new Error('获取待办事项失败'); } this.todos = await response.json(); } catch (error) { console.error('获取待办事项时发生错误:', error); this.showError('获取待办事项失败,请稍后重试'); } } async fetchUsers() { try { const response = await fetch('/api/users'); if (!response.ok) { throw new Error('获取用户数据失败'); } const data = await response.json(); this.users = data.users || []; } catch (error) { console.error('获取用户数据时发生错误:', error); this.showError('获取用户数据失败,请稍后重试'); } } getCurrentUser() { try { const userStr = localStorage.getItem('userInfo'); if (userStr) { this.currentUser = JSON.parse(userStr); } else { console.log('未找到登录用户信息'); } } catch (error) { console.error('获取当前用户信息时发生错误:', error); this.showError('获取用户信息失败'); } } showError(message) { const errorDiv = document.createElement('div'); errorDiv.className = 'error-message'; errorDiv.textContent = message; this.shadowRoot.appendChild(errorDiv); } // 构建项目树结构 buildProjectTree() { const tree = {}; this.todos.forEach(todo => { const project = todo.project || '其它'; const subproject = todo.subproject || '其它'; if (!tree[project]) { tree[project] = { name: project, subprojects: {} }; } if (!tree[project].subprojects[subproject]) { tree[project].subprojects[subproject] = { name: subproject, todos: [] }; } tree[project].subprojects[subproject].todos.push(todo); }); return tree; } // 渲染项目树 renderProjectTree(tree) { const treeContainer = document.createElement('div'); treeContainer.className = 'project-tree'; Object.values(tree).forEach(project => { const projectNode = document.createElement('div'); projectNode.className = 'project-node'; const projectHeader = document.createElement('div'); projectHeader.className = 'project-header'; projectHeader.innerHTML = `