refactor: 统一主体与镜头目录并优化筛选工具栏布局

This commit is contained in:
GouJ
2026-09-01 17:21:13 +08:00
parent a35f5fe82d
commit 70ab4ba48f
12 changed files with 496 additions and 251 deletions
+63
View File
@@ -0,0 +1,63 @@
import { mount, type VueWrapper } from '@vue/test-utils'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { NButton } from 'naive-ui'
import { readFileSync } from 'node:fs'
import DirectoryItem from './DirectoryItem.vue'
let wrapper: VueWrapper | undefined
afterEach(() => wrapper?.unmount())
describe('统一目录条目', () => {
it('编号、长标题和多项状态各占独立层级,沿用 Naive 按钮', () => {
const title = '雨夜霓虹街全景与记忆当铺外的人群和闪烁灯牌'
wrapper = mount(DirectoryItem, {
props: { active: false },
slots: {
eyebrow: 'BEAT 2 / SHOT 3',
default: title,
meta: '<span class="directory-status">设计已保存</span><span class="directory-status">待状态</span>'
}
})
expect(wrapper.getComponent(NButton).props()).toMatchObject({ quaternary: true, block: true })
expect(wrapper.get('button').attributes('type')).toBe('button')
expect(wrapper.get('.directory-item-eyebrow').text()).toBe('BEAT 2 / SHOT 3')
expect(wrapper.get('.directory-item-title').text()).toBe(title)
expect(wrapper.get('.directory-item-meta').findAll('.directory-status')).toHaveLength(2)
expect(wrapper.find('.truncate').exists()).toBe(false)
expect(wrapper.findAll('.directory-item-body > span')).toHaveLength(3)
})
it('点击透传给业务层,选中态与无障碍属性保持同步', async () => {
const onClick = vi.fn<() => void>()
wrapper = mount(DirectoryItem, { props: { active: false }, attrs: { onClick }, slots: { default: '林默' } })
await wrapper.get('button').trigger('click')
expect(onClick).toHaveBeenCalledOnce()
expect(wrapper.attributes('aria-current')).toBeUndefined()
await wrapper.setProps({ active: true })
expect(wrapper.get('button').classes()).toContain('selected')
expect(wrapper.attributes('aria-current')).toBe('true')
expect(wrapper.find('.directory-item-eyebrow').exists()).toBe(false)
expect(wrapper.find('.directory-item-meta').exists()).toBe(false)
})
it('显式保护最小高度、留白、换行和窄屏横向条目,避免旧按钮样式重新挤压目录', () => {
// DOM 环境不计算视觉几何;这些约束不能替代浏览器验收。
const css = readFileSync('src/admin.css', 'utf8')
expect(css).toMatch(/\.n-button\.directory-item\s*\{[^}]*min-height:\s*88px;[^}]*padding:\s*12px 14px/)
expect(css).toMatch(/\.directory-item-body\s*\{[^}]*flex-direction:\s*column;[^}]*gap:\s*7px/)
expect(css).toMatch(/\.directory-item-title\s*\{[^}]*overflow-wrap:\s*anywhere/)
expect(css).toMatch(/\.directory-list-content\s*\{[^}]*flex-direction:\s*row;[^}]*width:\s*max-content/)
expect(css).toContain('grid-template-columns: clamp(240px, 22%, 280px) minmax(0, 1fr)')
})
it('导出工具栏与筛选器使用受约束的网格,不让 Tabs 和 Select 默认宽度强制换行', () => {
const css = readFileSync('src/admin.css', 'utf8')
expect(css).toMatch(/\.result-toolbar\s*\{[^}]*grid-template-columns:\s*minmax\(0, 1fr\) auto/)
expect(css).toMatch(
/\.form-image-filters\s*\{[^}]*grid-template-columns:\s*minmax\(200px, 360px\) 152px minmax\(260px, 1fr\) auto/
)
expect(css).toMatch(
/@container \(max-width: 900px\)\s*\{\s*\.form-image-filters\s*\{[^}]*minmax\(0, 1fr\) 152px/
)
})
})