140 lines
5.4 KiB
JavaScript

class TodoTree {
static buildProjectTree(todos) {
const tree = {};
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;
}
static renderProjectTree(tree, {
expandedProjects,
selectedProject,
selectedSubproject,
showCompleted,
onProjectSelect,
onSubprojectSelect,
onExpandToggle,
onShowCompletedChange,
onShowAll,
onAddTodo
}) {
const treeContainer = document.createElement('div');
treeContainer.className = 'project-tree';
// 创建树内容容器
const treeContent = document.createElement('div');
treeContent.className = 'tree-content';
// 添加新增待办按钮
const addTodoButton = document.createElement('button');
addTodoButton.className = 'add-todo-button';
addTodoButton.textContent = '新增待办';
addTodoButton.addEventListener('click', onAddTodo);
treeContent.appendChild(addTodoButton);
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 = `
<div class="project-header-content">
<span class="expand-icon ${expandedProjects.has(project.name) ? 'expanded' : ''}">▶</span>
<span class="project-name">${project.name}</span>
<span class="todo-count">(${Object.values(project.subprojects).reduce((sum, sub) =>
sum + sub.todos.length, 0)})</span>
</div>
`;
projectHeader.addEventListener('click', () => {
onProjectSelect(project.name);
});
const expandButton = projectHeader.querySelector('.expand-icon');
expandButton.addEventListener('click', (e) => {
e.stopPropagation();
onExpandToggle(project.name);
});
const subprojectsContainer = document.createElement('div');
subprojectsContainer.className = 'subprojects-container';
subprojectsContainer.style.display = expandedProjects.has(project.name) ? 'block' : 'none';
Object.values(project.subprojects).forEach(subproject => {
const subprojectNode = document.createElement('div');
subprojectNode.className = 'subproject-node';
if (selectedProject === project.name && selectedSubproject === subproject.name) {
subprojectNode.classList.add('selected');
}
subprojectNode.innerHTML = `
<span class="subproject-name">${subproject.name}</span>
<span class="todo-count">(${subproject.todos.length})</span>
`;
subprojectNode.addEventListener('click', (e) => {
e.stopPropagation();
onSubprojectSelect(project.name, subproject.name);
});
subprojectsContainer.appendChild(subprojectNode);
});
projectNode.appendChild(projectHeader);
projectNode.appendChild(subprojectsContainer);
treeContent.appendChild(projectNode);
});
// 创建底部控制区域
const bottomControls = document.createElement('div');
bottomControls.className = 'bottom-controls';
// 添加显示已完成复选框
const showCompletedContainer = document.createElement('div');
showCompletedContainer.className = 'show-completed-container';
showCompletedContainer.innerHTML = `
<input type="checkbox" id="show-completed" ${showCompleted ? 'checked' : ''}>
<label for="show-completed">显示已完成</label>
`;
// 添加复选框事件监听
const checkbox = showCompletedContainer.querySelector('input');
checkbox.addEventListener('change', (e) => {
onShowCompletedChange(e.target.checked);
});
bottomControls.appendChild(showCompletedContainer);
// 添加显示全部按钮
const showAllButton = document.createElement('button');
showAllButton.className = 'show-all-button';
showAllButton.textContent = '显示全部';
showAllButton.addEventListener('click', onShowAll);
bottomControls.appendChild(showAllButton);
// 将树内容和底部控制区域添加到树容器
treeContainer.appendChild(treeContent);
treeContainer.appendChild(bottomControls);
return treeContainer;
}
}
export default TodoTree;