style: 重做界面视觉与信息层级

先截图审视现状,再针对性修改。主要问题与改动如下。

工具栏
- 标签筛选从「平铺全部标签」改为下拉面板,标签多时不再换行挤爆工具栏
- 备份与快捷键帮助移到导航栏 —— 它们是应用级操作,不该挤在看板工具栏里,
  顺带修好了「? 帮助只在看板可用」的问题
- 到期统计(今日到期 / 逾期)合并为可点击的筛选入口,去掉两个独立控件
- 移动端工具栏从占半屏降到三行紧凑布局

卡片
- 优先级从彩色胶囊改为左侧色条,扫视一列时比读文字更快分辨轻重
- 元信息改为「优先级 · 日期 · 标签」的轻量文本行,不再三种胶囊叠在一起
- 完成态用勾选图标 + 降低不透明度

布局
- 今日视图限宽居中(max-w-3xl):此前 1440px 下卡片被拉满整屏,
  标题与元信息之间出现大片空白
- 修复移动端卡片被压成细条:TaskCard 的 overflow-hidden(用于裁切左侧色条)
  会让 flex 项的最小尺寸解析为 0,补 shrink-0 修正;
  同时改为移动端按内容高度堆叠、桌面端列内滚动

其他
- 导航栏品牌改用看板图标,消除「看板」重复出现两次
- 统一卡片阴影、圆角与键盘焦点样式
- 新增 scripts/screenshot.mjs,便于后续对照审视视觉改动

验证:单元测试 452 个、端到端测试 23 个全部通过,lint 与构建无错误。
This commit is contained in:
chenshoulin
2026-10-18 14:05:06 +08:00
parent 4e064e82ea
commit 442cbbd734
23 changed files with 981 additions and 333 deletions
+38 -7
View File
@@ -1,25 +1,33 @@
import { flushPromises, mount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import { createMemoryHistory, createRouter } from 'vue-router'
import { describe, expect, it } from 'vitest'
import { routes } from '@/router'
import { useUiStore } from '@/stores/ui'
import AppNav from './AppNav.vue'
async function setup(initialPath = '/') {
const pinia = createPinia()
setActivePinia(pinia)
const router = createRouter({ history: createMemoryHistory(), routes })
await router.push(initialPath)
await router.isReady()
const wrapper = mount(AppNav, { global: { plugins: [router] }, attachTo: document.body })
return { wrapper, router }
const wrapper = mount(AppNav, {
global: { plugins: [pinia, router] },
attachTo: document.body,
})
return { wrapper, router, ui: useUiStore() }
}
describe('AppNav', () => {
it('渲染看板与今日两个入口', () => {
return setup().then(({ wrapper }) => {
expect(wrapper.findAll('a').map((node) => node.text())).toEqual(['看板', '今日'])
})
describe('AppNav 导航', () => {
it('渲染看板与今日两个入口', async () => {
const { wrapper } = await setup()
expect(wrapper.findAll('a').map((node) => node.text())).toEqual(['看板', '今日'])
})
it('当前路由的入口标记 aria-current', async () => {
@@ -53,3 +61,26 @@ describe('AppNav', () => {
expect(wrapper.find('nav').attributes('aria-label')).toBe('主导航')
})
})
describe('AppNav 应用级操作', () => {
it('点击「备份」打开备份面板', async () => {
const { wrapper, ui } = await setup()
expect(ui.backupOpen).toBe(false)
const backupButton = wrapper.findAll('button').find((node) => node.text() === '备份')
await backupButton?.trigger('click')
expect(ui.backupOpen).toBe(true)
})
it('点击 ? 打开快捷键帮助', async () => {
const { wrapper, ui } = await setup()
await wrapper.find('button[aria-label="快捷键帮助"]').trigger('click')
expect(ui.helpOpen).toBe(true)
})
it('应用级操作在看板与今日视图下都可用', async () => {
const { wrapper } = await setup('/today')
expect(wrapper.findAll('button').map((node) => node.text())).toContain('备份')
})
})