style: 统一主体列表搜索与统计布局
This commit is contained in:
@@ -146,9 +146,36 @@ describe('拆解页内容滚动', () => {
|
||||
const list = wrapper!.get('.subject-record-list')
|
||||
expect(list.classes()).toContain('record-list')
|
||||
expect(list.findAll(':scope > article')).toHaveLength(30)
|
||||
await wrapper!.get('input[aria-label="搜索主体"]').setValue('主体 30')
|
||||
const toolbar = wrapper!.get('.subject-list-toolbar')
|
||||
expect(toolbar.element.firstElementChild).toBe(toolbar.get('.subject-list-search').element)
|
||||
expect(toolbar.element.lastElementChild).toBe(toolbar.get('.subject-list-count').element)
|
||||
expect(toolbar.get('.n-input__prefix svg').attributes('aria-hidden')).toBe('true')
|
||||
expect(toolbar.find(':scope > svg').exists()).toBe(false)
|
||||
expect(toolbar.get('[role="status"]').text()).toBe('共 30 个主体')
|
||||
const input = toolbar.get('input[aria-label="搜索主体"]')
|
||||
await input.setValue('主体 30')
|
||||
expect(list.findAll(':scope > article')).toHaveLength(1)
|
||||
expect(list.get(':scope > article h3').text()).toContain('主体 30')
|
||||
expect(toolbar.get('[role="status"]').text()).toBe('匹配 1 / 30 个主体')
|
||||
await input.setValue('不存在的主体')
|
||||
expect(toolbar.get('[role="status"]').text()).toBe('匹配 0 / 30 个主体')
|
||||
expect(wrapper!.text()).toContain('没有匹配的主体')
|
||||
await input.setValue('')
|
||||
expect(toolbar.get('[role="status"]').text()).toBe('共 30 个主体')
|
||||
expect(wrapper!.findAll('.subject-record-list > article')).toHaveLength(30)
|
||||
})
|
||||
|
||||
it('主体搜索与统计靠左居中,窄内容区可换行,输入框不再使用外置图标容器', () => {
|
||||
// DOM 环境不计算布局,保护输入框宽度、主题统计色与窄屏换行的样式契约。
|
||||
const css = readFileSync('src/admin.css', 'utf8')
|
||||
expect(css).toMatch(
|
||||
/\.subject-list-toolbar\s*\{[^}]*display:\s*flex;[^}]*flex-wrap:\s*wrap;[^}]*align-items:\s*center;[^}]*justify-content:\s*flex-start;/
|
||||
)
|
||||
expect(css).toMatch(
|
||||
/\.subject-list-search\.n-input\s*\{[^}]*flex:\s*0 1 260px;[^}]*min-width:\s*0;[^}]*max-width:\s*100%;/
|
||||
)
|
||||
expect(css).toMatch(/\.subject-list-count\s*\{[^}]*color:\s*var\(--app-muted\);/)
|
||||
expect(css + readFileSync('src/styles.css', 'utf8')).not.toContain('.search-field')
|
||||
})
|
||||
|
||||
it('只为主体斑马纹空白行添加主题化悬停底色,不覆盖已有条纹和操作状态', () => {
|
||||
|
||||
@@ -19,16 +19,20 @@ const filtered = computed(() =>
|
||||
|
||||
<template>
|
||||
<div class="p-5 lg:p-7">
|
||||
<div class="mb-5 flex items-center justify-between gap-3">
|
||||
<p class="text-sm text-muted">{{ subjects.length }} 个主体</p>
|
||||
<div class="search-field">
|
||||
<Search :size="14" /><NInput
|
||||
placeholder="搜索名称或引用"
|
||||
aria-label="搜索主体"
|
||||
:input-props="{ 'aria-label': '搜索主体' }"
|
||||
v-model:value="search"
|
||||
></NInput>
|
||||
</div>
|
||||
<div class="subject-list-toolbar">
|
||||
<NInput
|
||||
class="subject-list-search"
|
||||
placeholder="搜索名称或引用"
|
||||
aria-label="搜索主体"
|
||||
:input-props="{ 'aria-label': '搜索主体' }"
|
||||
v-model:value="search"
|
||||
clearable
|
||||
><template #prefix><Search :size="14" aria-hidden="true" /></template
|
||||
></NInput>
|
||||
<p class="subject-list-count" role="status">
|
||||
<template v-if="search.trim()">匹配 {{ filtered.length }} / {{ subjects.length }} 个主体</template>
|
||||
<template v-else>共 {{ subjects.length }} 个主体</template>
|
||||
</p>
|
||||
</div>
|
||||
<div v-if="filtered.length" class="record-list subject-record-list">
|
||||
<article v-for="subject in filtered" :key="subject.profileId">
|
||||
|
||||
Reference in New Issue
Block a user