remove: 删除待办与任务管理系统重构相关文档,清理过时内容
This commit is contained in:
@@ -1,41 +0,0 @@
|
||||
|
||||
### 待办
|
||||
- 1、打印任务功能
|
||||
- 2、任务中英文切换
|
||||
- 3、记录创建日期,用于 Completed 分类中的排序
|
||||
|
||||
|
||||
### 进行中
|
||||
|
||||
- V1.0 #1、拆分成 html、cs、js
|
||||
- V1.0 #2、将Json文件 改名为backup-tasks-yyyy-mm-dd.json
|
||||
|
||||
|
||||
### 已完成
|
||||
|
||||
### V1.0
|
||||
|
||||
```yaml
|
||||
|
||||
```
|
||||
|
||||
### V0.3
|
||||
|
||||
```yaml
|
||||
- 1、【待办事项】添加隐藏任务功能
|
||||
```
|
||||
|
||||
### V0.2
|
||||
|
||||
```yaml
|
||||
- 1、数据保存到本地。Json 文件格式
|
||||
- 2、去除按钮 【检测到期按钮提醒】,保留刷新时自动检测
|
||||
- 3、已完成栏,可以隐藏任务功能
|
||||
```
|
||||
|
||||
### V0.1
|
||||
|
||||
```yaml
|
||||
- 1、时间轴的内容可以编辑,修改,添加
|
||||
- 2、添加软件图标
|
||||
```
|
||||
@@ -1,191 +0,0 @@
|
||||
# 任务管理系统重构 TODO
|
||||
|
||||
> 分支:`dev-refactor` 目标:在**不改变任何现有功能与数据格式**的前提下,把单文件架构重构为模块化、可维护的结构。
|
||||
> 原则:小步提交,每个阶段完成后跑一遍「回归测试清单」再进入下一阶段。
|
||||
|
||||
---
|
||||
|
||||
## 一、现状分析
|
||||
|
||||
| 文件 | 行数 | 问题概述 |
|
||||
|------|------|----------|
|
||||
| `src/index.html` | 311 | 内联 onclick、3 份重复的排序下拉、favicon 重复 4 次 |
|
||||
| `src/script.js` | 1788 | 单文件巨石:状态、i18n、渲染、存储、导入导出全部混在一起,约 30 个全局函数 |
|
||||
| `src/styles.css` | 432 | 颜色硬编码、选择器重复定义、存在疑似死代码 |
|
||||
|
||||
### 主要问题清单
|
||||
|
||||
1. **全局可变状态散落**:`tasks`、`currentLang`、`sortOrders`、`showHiddenCompletedTasks`、`showHiddenTodoTasks`、`currentEditingTaskId`、`pendingImportData`、`idCounter` 共 8 个全局变量,任何函数都能直接改。
|
||||
2. **内联事件处理**:HTML 和 JS 模板字符串里大量 `onclick="xxx()"`,迫使所有函数必须挂在全局作用域。
|
||||
3. **成对重复代码**(completed / todo 两套几乎相同的逻辑):
|
||||
- `toggleShowHiddenCompletedTasks` / `toggleShowHiddenTodoTasks`(script.js:1665 / 1728)
|
||||
- `updateShowHiddenCompletedTasksUI` / `updateShowHiddenTodoTasksUI`(script.js:1682 / 1745)
|
||||
- `save/loadShowHiddenCompletedTasks` / `save/loadShowHiddenTodoTasks`(script.js:1708 / 1771)
|
||||
- `renderTasks` 内部对 completed 和 todo 的隐藏任务处理两段几乎一样(script.js:630-667)
|
||||
4. **HTML 重复**:三列的排序 `<select>` 各 13 个 option 完全相同(index.html:72-86 / 99-113 / 132-146);favicon 的 data-URI 重复 4 次(index.html:9-12)。
|
||||
5. **i18n 内嵌**:约 240 行翻译对象直接写在 script.js:162-403,`{count}` 占位符靠手工 `.replace()`。
|
||||
6. **渲染方式**:整列 `innerHTML` 全量重绘,每次保存/通知都调 `renderAllTasks()`,导致时间轴展开状态丢失。
|
||||
7. **职责重叠**:`renderTasks` 和 `updateTaskCounts` 都在写计数 DOM(script.js:640-666 与 831-859),结果一致但逻辑双份。
|
||||
8. **业务种子数据硬编码**:`loadInitialTasks()`(script.js:417-513)内嵌 5 条真实业务任务。
|
||||
9. **排序逻辑重复**:`priorityOrder` 映射定义了 3 次(script.js:562 / 605 / 608),number-asc/desc、priority-asc/desc 成对复制。
|
||||
10. **无工程化设施**:无 ESLint / Prettier / 测试 / 构建脚本。
|
||||
|
||||
### 顺带发现的小 bug / 待改进点(重构中一并处理)
|
||||
|
||||
- [x] `exportData()` 失败时错用 `importError` 文案(script.js:1491)→ 应新增 `exportError` 翻译键
|
||||
- [x] `exportData()` 中残留调试 `console.log`(script.js:1453-1457)→ 删除
|
||||
- [x] 时间轴区块只在 `timeline.length > 0` 时渲染(script.js:793),**没有任何时间轴条目的任务无法手动添加第一条**→ 补充入口
|
||||
- [x] `sortTasks(tasks, ...)` 参数名遮蔽全局 `tasks`(script.js:549)→ 重命名参数
|
||||
- [x] `normalizeTask` 未校验 `language` 字段 → 补充白名单 `['zh','en']`
|
||||
- [x] 每次重渲染后时间轴折叠状态丢失 → 渲染前记录展开的 taskId,渲染后恢复
|
||||
- [x] CSS:`.timeline-item` 重复定义(styles.css:87 与 276)→ 合并;确认 `.status-title`(styles.css:270)、`.tasks-hidden-notice`(styles.css:346)是否未使用,未使用则删除
|
||||
- [x] `saveTask` 附近缩进混乱(script.js:907-1010 有多余空格)→ 统一格式化
|
||||
|
||||
---
|
||||
|
||||
## 二、目标目录结构
|
||||
|
||||
采用**原生 ES Modules,无构建工具**。
|
||||
⚠️ 注意:ES Modules 无法通过 `file://` 直接打开,开发和使用需本地静态服务器(VSCode Live Server 或 `npx serve src`)。如果必须保留「双击 html 直接用」的能力,改用方案 B:保持多个普通 `<script>` 标签按依赖顺序加载(模块拆分方式不变,只是不用 import/export)。**开工前先确认选哪个方案。**
|
||||
|
||||
```
|
||||
src/
|
||||
├── index.html
|
||||
├── css/
|
||||
│ └── styles.css # 后续可再拆 base / components / responsive
|
||||
└── js/
|
||||
├── main.js # 入口:DOMContentLoaded 初始化、顶层事件绑定
|
||||
├── config.js # 常量:状态列表、排序方式、优先级映射、localStorage 键名、导出版本号
|
||||
├── utils.js # escapeHtml、formatLocalDate、ID 生成、日期解析
|
||||
├── i18n/
|
||||
│ ├── zh.js
|
||||
│ ├── en.js
|
||||
│ └── index.js # t(key, params) 翻译函数、applyTranslations()、toggleLanguage()
|
||||
├── storage.js # localStorage 统一读写 + 容错(唯一接触 localStorage 的模块)
|
||||
├── store.js # 应用状态(tasks、sortOrders、showHidden…)+ 受控的变更接口
|
||||
├── task-model.js # normalizeTask / normalizeTasks / isValidId / 校验
|
||||
├── sort.js # sortTasks 与各比较器
|
||||
├── render.js # renderAllTasks / renderTasks / createTaskCard / createTimeline / 计数
|
||||
├── modal.js # 任务编辑模态框:打开、填充、保存
|
||||
├── timeline.js # 时间轴 CRUD + 系统条目
|
||||
├── import-export.js # 导出、导入、validateImportData、合并去重
|
||||
└── notify.js # showNotification / checkDueDates
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、重构步骤
|
||||
|
||||
### 阶段 0:准备(半天)
|
||||
|
||||
- [x] 确认模块方案:**A. ES Modules + 本地服务器**(推荐)或 B. 普通脚本多文件
|
||||
- [x] 手工做一次完整功能走查,按「回归测试清单」录一遍基准行为(必要时截图)
|
||||
- [ ] 导出一份当前 localStorage 数据(用现有导出功能生成 backup-tasks-*.json)作为兼容性测试样本
|
||||
- [x] 添加 `.editorconfig`、ESLint(flat config)+ Prettier;先只做检查不大规模改格式
|
||||
- [ ] git tag 一个重构前基线(如 `pre-refactor`)
|
||||
|
||||
### 阶段 1:文件拆分(先搬家,不改逻辑)
|
||||
|
||||
> 本阶段只移动代码 + 加 import/export,函数体一行不改。每搬完一个模块提交一次。
|
||||
|
||||
- [x] 建立 `src/js/`、`src/css/` 目录,index.html 引用路径同步更新
|
||||
- [x] `utils.js` ← script.js:8-69(generateId、escapeHtml、parseDueDateEnd、getDueDateState、isValidId、generateUniqueId)
|
||||
- [x] `task-model.js` ← script.js:71-152(normalizeTask、normalizeTasks、normalizeSortOrders、validStatuses、validSortOrders)
|
||||
- [x] `i18n/zh.js`、`i18n/en.js` ← script.js:162-403 的翻译对象
|
||||
- [x] `storage.js` ← saveTasks/loadTasks(516-538)、saveSortOrders/loadSortOrders(1421-1441)、show-hidden 的 4 个 save/load(1708-1725、1771-1788)
|
||||
- [x] `sort.js` ← sortTasks(549-622)
|
||||
- [x] `render.js` ← renderAllTasks、renderTasks、applySearchFilter、createTaskCard、createTimeline、updateTaskCounts(541-859、1106-1194)
|
||||
- [x] `modal.js` ← openTaskModal、populateForm、updateProgressDisplay、saveTask、editTask、deleteTask(862-1027)
|
||||
- [x] `timeline.js` ← toggleTimeline 至 addSystemTimelineEntry(1197-1381)
|
||||
- [x] `import-export.js` ← exportData 至 executeImport(1444-1662)
|
||||
- [x] `notify.js` ← showNotification(1085-1103)、checkDueDates(1030-1053)
|
||||
- [x] `main.js` ← DOMContentLoaded 初始化(406-414)+ loadInitialTasks(417-513,暂时原样保留)
|
||||
- [x] 过渡措施:内联 onclick 仍需全局函数,在 main.js 里临时 `window.xxx = xxx` 挂出所有被 HTML 引用的函数(阶段 2 已移除,无全局挂载残留)
|
||||
- [x] 删除旧 `src/script.js`,全功能回归一遍(旧脚本已删除,完整人工回归已通过)
|
||||
|
||||
### 阶段 2:去内联事件,改事件委托
|
||||
|
||||
- [x] index.html 中静态元素的 `onclick` / `onchange` / `onkeyup` 全部移除,改在 main.js 里 `addEventListener` 绑定(添加任务、导出、导入、语言切换、搜索、排序下拉、眼睛按钮、保存任务、确认导入、进度滑块、文件 input)
|
||||
- [x] 任务卡片内动态按钮改为 `data-action="pin|hide|edit|delete|toggle-timeline|…"` + `data-task-id` 属性,在三个列容器上做**事件委托**(click 一个监听器搞定)
|
||||
- [x] 时间轴的添加/编辑/删除/键盘事件同样走委托(`data-action` + `data-timeline-id`)
|
||||
- [x] 移除阶段 1 的所有 `window.xxx` 临时挂载
|
||||
- [x] 回归:重点测所有按钮、Enter 添加时间轴、Ctrl+Enter 保存、Esc 取消
|
||||
|
||||
### 阶段 3:消除重复
|
||||
|
||||
- [x] **HTML**:排序 `<select>` 的 13 个 option 改为 JS 根据 `config.js` 中的排序定义生成,三列共用;favicon 只保留一个 `<link>`
|
||||
- [x] **show-hidden 逻辑合并**:completed/todo 两套 toggle/updateUI/save/load 合并为按 status 参数化的一套(状态改为 `showHidden = { completed: false, todo: false }`,localStorage 仍写原有两个键保持兼容)
|
||||
- [x] **renderTasks** 中 completed/todo 的隐藏处理合并为一段参数化逻辑;**计数只由 `updateTaskCounts` 负责**,renderTasks 不再写计数 DOM
|
||||
- [x] **sort.js**:`PRIORITY_ORDER` 常量只定义一次;number/priority/dueDate 的 asc/desc 用「比较器 + 方向系数」实现,消除成对复制
|
||||
- [x] `config.js` 收敛所有魔法值:状态数组、优先级数组、localStorage 键名(`tasks`、`taskSortOrders`、`showHiddenCompletedTasks`、`showHiddenTodoTasks`、`tasksInitialized`、`tasksCorruptedBackup`)、导出版本号 `"1.0"`、到期预警天数 3
|
||||
|
||||
### 阶段 4:状态与存储收敛
|
||||
|
||||
- [x] `store.js`:所有状态私有化,暴露读取接口和语义化变更方法(addTask、updateTask、removeTask、togglePin、toggleHidden、setSortOrder…),变更方法内部统一调用 storage 持久化
|
||||
- [x] `storage.js`:统一 try/catch 容错模式(现在 loadTasks/loadSortOrders/loadShowHidden* 三种写法各不相同),保留「损坏数据备份到 tasksCorruptedBackup」行为
|
||||
- [x] 各模块不再直接改 `tasks` 数组,全部经 store 接口
|
||||
|
||||
### 阶段 5:i18n 完善
|
||||
|
||||
- [x] `t(key, params)` 支持 `{count}` 等占位符插值,替换所有手工 `.replace('{count}', …)`
|
||||
- [x] `applyTranslations()` 抽出(现在的 toggleLanguage 内 data-key 扫描逻辑),初始化时也调用一次(为后续记住语言偏好做准备)
|
||||
- [x] 新增 `exportError` 键,修复导出失败文案 bug
|
||||
- [ ] 可选:语言偏好持久化到 localStorage(新键,注意不影响旧数据)
|
||||
|
||||
### 阶段 6:渲染层改进
|
||||
|
||||
- [x] 渲染前记录已展开时间轴的 taskId 集合,渲染后恢复展开状态(修复现状缺陷)
|
||||
- [x] 无时间轴条目的卡片也渲染「添加条目」入口(修复现状缺陷)
|
||||
- [x] 精细化重渲染:单任务变更(置顶/隐藏/时间轴操作)只重渲染受影响列,而非三列全刷
|
||||
- [x] createTaskCard 保持模板字符串方案即可,但拆出 createPriorityBadge、createDueDateBlock 等小函数,保证每段可读
|
||||
|
||||
### 阶段 7:数据清理
|
||||
|
||||
- [x] `loadInitialTasks` 的 5 条业务种子任务移到 `js/seed-data.js`(保留首次初始化种子行为)
|
||||
- [x] 删除 exportData 中的调试 console.log
|
||||
- [x] `normalizeTask` 补充 language 字段白名单校验
|
||||
|
||||
### 阶段 8:CSS 整理
|
||||
|
||||
- [x] 顶部定义 CSS 自定义属性:主色、三列状态色、优先级色、到期警示色(当前 #007bff / #28a745 / #ffc107 / #dc3545 / #fd7e14 等散落各处)
|
||||
- [x] 合并重复的 `.timeline-item` 定义;grep 验证并删除未使用的 `.status-title`、`.tasks-hidden-notice`、`.show-tasks-btn`
|
||||
- [x] 按「基础 / 任务卡片 / 时间轴 / 模态框 / 响应式」重排分区注释(是否拆成多文件视方案 A/B 决定)
|
||||
|
||||
### 阶段 9:质量保障
|
||||
|
||||
- [x] ESLint + Prettier 全量通过,修掉参数遮蔽(sortTasks)等告警
|
||||
- [x] 纯函数单元测试(Vitest + jsdom,可选但推荐):`normalizeTask`、`normalizeTasks`(ID 去重)、`sortTasks` 全部 13 种排序、`getDueDateState`(过期/临期/边界日)、`validateImportData`、合并导入去重逻辑
|
||||
- [x] 使用版本 1.0 旧格式 fixture 做**导入兼容性测试**(覆盖模式 + 合并模式)
|
||||
- [x] 使用重构前格式的完整 localStorage 快照测试 6 个旧键与任务字段无损恢复
|
||||
|
||||
### 阶段 10:文档收尾
|
||||
|
||||
- [x] 更新 / 新建 README:项目结构说明、本地运行方式(如需服务器要写清楚)、数据存储说明(localStorage 键 + 导出格式)
|
||||
- [x] CHANGELOG 记录重构版本
|
||||
- [x] 合并 `dev-refactor` → `main` 前完整跑一遍下方回归清单
|
||||
|
||||
---
|
||||
|
||||
## 四、回归测试清单(每阶段结束必跑)
|
||||
|
||||
- [x] 添加任务:标题必填校验、进度滑块联动、隐藏勾选生效
|
||||
- [x] 编辑任务:进展/状态/进度/负责人/到期日/优先级变更均自动生成时间轴系统条目
|
||||
- [x] 删除任务:confirm 确认后删除
|
||||
- [x] 三列各 13 种排序均正确,刷新后排序偏好保留;置顶任务在任何排序下都靠前
|
||||
- [x] 搜索:实时过滤三列卡片
|
||||
- [x] 隐藏/显示:卡片眼睛按钮、列头眼睛按钮、计数随显示模式变化、「全部已隐藏」提示文案
|
||||
- [x] 时间轴:展开/收起、添加(按钮 + Enter)、编辑(Ctrl+Enter 保存、Esc 取消)、删除
|
||||
- [x] 导出:文件名 `backup-tasks-yyyy-mm-dd.json`、内容含 version/exportDate/taskCount/tasks/sortOrders
|
||||
- [x] 导入:非法文件报错;信息弹窗显示版本/数量/时间;覆盖模式全替换;合并模式按 标题|状态|创建时间 去重并提示跳过数
|
||||
- [x] 中英切换:所有 data-key 文本、placeholder、页面标题、html lang、卡片内动态文本
|
||||
- [x] 到期提醒:加载时对过期 / 3 天内到期的未完成任务弹通知
|
||||
- [x] 容错:手工向 localStorage 写坏数据 → 提示 + 原始数据备份到 `tasksCorruptedBackup`
|
||||
- [x] 首次访问(清空 localStorage):种子任务加载一次,`tasksInitialized` 置位
|
||||
- [x] 移动端(<768px / <576px):按钮缩放、文字隐藏、操作按钮可点
|
||||
|
||||
## 五、风险与约束
|
||||
|
||||
1. **localStorage 兼容是红线**:6 个键名与数据结构不得变更,老用户数据必须无缝迁移。
|
||||
2. **方案 A(ES Modules)改变使用方式**:`file://` 直接打开会失效,需和使用场景确认后再定。
|
||||
3. **内联事件改造面广**:HTML 静态元素 + JS 动态模板两处都有,漏改一处即功能失效,必须逐区域回归。
|
||||
4. **无自动化测试兜底**(阶段 9 之前):靠回归清单人工保障,所以每阶段步子要小、提交要勤。
|
||||
Reference in New Issue
Block a user