diff --git a/README.md b/README.md index ae782cf..f640655 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,9 @@ - 固定三列:**待办 / 进行中 / 已完成** - 快速新增、拖拽排序、详情编辑、删除撤销 - 搜索与筛选(关键词 / 优先级 / 标签 / 今日到期 / 逾期) -- **今日视图**:按紧急度汇总今天要做的事,含本周完成等统计 -- 键盘快捷键 +- **今日视图**:按紧急度分组汇总(逾期 / 今天到期 / 进行中 / 待办),含本周完成等统计 +- 键盘快捷键;任务卡片可用方向键换列与调序 +- **深色模式**:跟随系统 / 浅色 / 深色三态 - 导出导入 JSON + 启动自动备份 - **可安装为 PWA,支持离线使用** @@ -44,7 +45,15 @@ npm run dev | `?` | 打开快捷键帮助 | | `Esc` | 关闭当前面板 | -在输入框内输入时不会触发快捷键。 +卡片获得焦点(`Tab` 或点击)后: + +| 按键 | 作用 | +|---|---| +| `←` `→` | 把卡片移到上一列 / 下一列 | +| `↑` `↓` | 在列内上移 / 下移 | +| `Enter` | 打开任务详情 | + +在输入框内输入时不会触发全局快捷键。方向键移动在筛选态下只允许跨列(列内排序需要看到完整列表才有意义)。 --- @@ -55,11 +64,13 @@ npm run dev | 视图 | 路径 | 组织方式 | |---|---|---| | 看板 | `/` | 按**状态**:待办 / 进行中 / 已完成 | -| 今日 | `/today` | 按**紧急度**:已逾期 → 今天到期 → 进行中 | +| 今日 | `/today` | 按**紧急度**:已逾期 → 今天到期 → 进行中 → 待办 | -今日视图顶部有四张统计卡片(今日待办 / 逾期 / 今天到期 / 本周完成),下方是可直接勾选完成的待办列表。 +今日视图顶部有四张统计卡片(逾期 / 今天到期 / 进行中 / 本周完成),下方是可直接勾选完成的待办列表。 -分组是**互斥**的:一张卡片只会出现在一组里,归属优先级为「逾期 > 今天到期 > 进行中」,所以你能一眼数清今天到底有几件事。已完成和已归档的任务不会出现在今日视图。 +分组是**互斥**的:一张卡片只会出现在一组里,归属优先级为「逾期 > 今天到期 > 进行中 > 待办」,所以你能一眼数清今天到底有几件事。已完成和已归档的任务不会出现在今日视图。 + +只要任务未完成且未归档,就一定会出现在某个分组里 —— 包括没设截止日期的待办(归入「待办」组)。 --- @@ -177,8 +188,8 @@ scripts/ # 图标生成等辅助脚本 ## 测试 -- 单元测试:437 个用例,覆盖 `src/` 下的纯逻辑与组件行为,行覆盖率约 97%。 -- 端到端测试:23 个用例,分两组运行 —— 交互类跑 dev server,PWA 类跑生产构建(Service Worker 只在构建产物中生成)。覆盖「新增 → 拖拽 → 完成 → 刷新保持」「导出 → 清空 → 导入还原」「删除撤销」「搜索筛选」「键盘快捷键」「今日视图」「离线打开」等主链路,每个用例使用独立的浏览器上下文。 +- 单元测试:480 个用例,覆盖 `src/` 下的纯逻辑与组件行为,行覆盖率约 96%。 +- 端到端测试:25 个用例,分两组运行 —— 交互类跑 dev server,PWA 类跑生产构建(Service Worker 只在构建产物中生成)。覆盖「新增 → 拖拽 → 完成 → 刷新保持」「导出 → 清空 → 导入还原」「删除撤销」「搜索筛选」「键盘快捷键与方向键移动」「深色模式切换」「今日视图」「离线打开」等主链路,每个用例使用独立的浏览器上下文。 ```bash npm run test:coverage @@ -202,5 +213,6 @@ PLAYWRIGHT_CHANNEL=chromium npm run test:e2e # 用自带 Chromium(需先 npx - 标签是字符串数组,重命名标签需要逐个任务修改。 - 看板列固定为三列,不支持自定义。 - 归档阈值固定为「已完成超过 7 天」,暂不可配置。 -- 今日视图的分组规则固定(逾期 > 今天到期 > 进行中),不可自定义。 +- 今日视图的分组规则固定(逾期 > 今天到期 > 进行中 > 待办),不可自定义。 - 统计只覆盖本周完成数等基础指标,没有趋势图或历史留存。 +- 深色模式只跟随系统或手动三态切换,没有按时间段自动切换。 diff --git a/e2e/board.spec.ts b/e2e/board.spec.ts index 5f78a12..cca4dde 100644 --- a/e2e/board.spec.ts +++ b/e2e/board.spec.ts @@ -113,3 +113,39 @@ test('输入框内输入不会触发快捷键', async ({ page }) => { await expect(search).toBeFocused() await expect(search).toHaveValue('n') }) + +test('深色模式可切换并在刷新后保持', async ({ page }) => { + await page.goto('/') + const html = page.locator('html') + const themeButton = page.getByRole('button', { name: /主题/ }) + + await expect(html).not.toHaveClass(/dark/) + + // 系统 → 浅色 → 深色 + await themeButton.click() + await expect(html).not.toHaveClass(/dark/) + await themeButton.click() + await expect(html).toHaveClass(/dark/) + + await page.reload() + await expect(html).toHaveClass(/dark/) + + // 再点一次回到跟随系统 + await themeButton.click() + await expect(html).not.toHaveClass(/dark/) +}) + +test('键盘方向键可以移动任务卡片', async ({ page }) => { + await addTask(page, '键盘移动我') + const card = page.locator('article').filter({ hasText: '键盘移动我' }) + await card.focus() + + await page.keyboard.press('ArrowRight') + await expect(page.locator('[data-column-id="doing"] article')).toHaveCount(1) + + await page.keyboard.press('ArrowLeft') + await expect(page.locator('[data-column-id="todo"] article')).toHaveCount(1) + + await page.reload() + await expect(page.locator('[data-column-id="todo"] article')).toHaveCount(1) +}) diff --git a/e2e/pwa.spec.ts b/e2e/pwa.spec.ts index 0d2893a..d3c2843 100644 --- a/e2e/pwa.spec.ts +++ b/e2e/pwa.spec.ts @@ -106,7 +106,7 @@ test('离线时深链 /today 也能打开(navigateFallback 生效)', async ( await page.goto('/today') await expect(page.getByRole('heading', { name: '今日' })).toBeVisible() - await expect(page.getByText('今日待办')).toBeVisible() + await expect(page.getByText('本周完成')).toBeVisible() await context.setOffline(false) }) diff --git a/e2e/today.spec.ts b/e2e/today.spec.ts index 2e443ed..edd58a1 100644 --- a/e2e/today.spec.ts +++ b/e2e/today.spec.ts @@ -34,7 +34,7 @@ test('导航可在看板与今日之间切换', async ({ page }) => { await page.getByRole('link', { name: '今日' }).click() await expect(page.getByRole('heading', { name: '今日' })).toBeVisible() - await expect(page.getByText('今日待办')).toBeVisible() + await expect(page.getByText('本周完成')).toBeVisible() await page.getByRole('link', { name: '看板' }).click() await expect(page.getByText('共 0 个任务')).toBeVisible() @@ -58,13 +58,15 @@ test('今日视图汇总今天到期与进行中的任务', async ({ page }) => await expect(page.getByRole('heading', { level: 2, name: /进行中/ })).toBeVisible() }) -test('未开始且无截止日期的任务不进入今日视图', async ({ page }) => { +test('未开始且无截止日期的任务出现在「待办」组', async ({ page }) => { await addTask(page, '以后再说') await page.getByRole('link', { name: '今日' }).click() - await expect(page.locator('article')).toHaveCount(0) - await expect(page.getByText('今天没有待办事项')).toBeVisible() + // 早期版本这类任务在今日视图里完全消失,是一个真实的缺口 + await expect(page.locator('article')).toHaveCount(1) + await expect(page.locator('article').filter({ hasText: '以后再说' })).toBeVisible() + await expect(page.getByRole('heading', { level: 2, name: /待办/ })).toBeVisible() }) test('今日视图可以勾选完成', async ({ page }) => { diff --git a/index.html b/index.html index 1e7a138..0aa1bcf 100644 --- a/index.html +++ b/index.html @@ -12,6 +12,22 @@
在输入框内输入时不会触发快捷键。
+ 在输入框内输入时不会触发快捷键。 +
暂无任务