diff --git a/src/app/DomesticOutboundListLayout.test.ts b/src/app/DomesticOutboundListLayout.test.ts index 888cdd21..56b5c209 100644 --- a/src/app/DomesticOutboundListLayout.test.ts +++ b/src/app/DomesticOutboundListLayout.test.ts @@ -42,7 +42,8 @@ describe('domestic outbound list responsive contracts', () => { const listLayout = source('src/shared/components/ListPageLayout.vue') expect(queryToolbar).toContain('@media (max-width: 720px)') - expect(queryToolbar).toContain('.query-toolbar__field { width: 100%; }') + expect(queryToolbar).toContain('.query-toolbar__field { width: 100%; flex: 0 0 auto; }') + expect(queryToolbar).toContain('.query-toolbar__control { width: 100%; flex: 0 0 auto; }') expect(queryToolbar).toContain('grid-template-columns: repeat(auto-fit, minmax(120px, 1fr))') expect(dataTable).toContain('@media (max-width: 720px)') expect(dataTable).toContain('flex-direction: column') diff --git a/src/shared/components/QueryToolbar.test.ts b/src/shared/components/QueryToolbar.test.ts index e9addd5e..ed4d8b5b 100644 --- a/src/shared/components/QueryToolbar.test.ts +++ b/src/shared/components/QueryToolbar.test.ts @@ -73,7 +73,56 @@ describe('QueryToolbar layout preferences', () => { expect(wrapper.find('.query-toolbar__tail .query-toolbar__actions').exists()).toBe(true) const source = readFileSync(resolve(process.cwd(), 'src/shared/components/QueryToolbar.vue'), 'utf8') - expect(source).toContain('.query-toolbar__tail { display: flex; align-items: flex-end; width: auto; flex: 0 0 auto; gap: 10px; }') + expect(source).toContain('.query-toolbar__tail { display: flex; width: auto; max-width: 100%; min-width: 0; flex: 0 1 auto; align-items: flex-end; flex-wrap: wrap; gap: 10px; }') + expect(source).not.toContain('.query-toolbar__filters { display: contents; }') + }) + + it('derives compact widths by field type while explicit business widths win', () => { + const compactFields: QueryField[] = [ + { key: 'status', type: 'select', label: '短状态' }, + { key: 'date', type: 'date', label: '日期' }, + { key: 'keyword', type: 'input', label: '长关键词' }, + { key: 'range', type: 'daterange', label: '日期范围' }, + { key: 'warehouse', type: 'select', label: '业务显式宽度', width: 236 }, + ] + const wrapper = mountToolbar({ + modelValue: { status: '', date: '', keyword: '', range: [], warehouse: '' }, + fields: compactFields, + availableFields: compactFields, + }) + const styles = wrapper.findAll('.query-toolbar__field').map((field) => field.attributes('style')) + expect(styles).toEqual([ + '--query-field-width: 180px;', + '--query-field-width: 180px;', + '--query-field-width: 260px;', + '--query-field-width: 300px;', + '--query-field-width: 236px;', + ]) + }) + + it('keeps a short status and long keyword left aligned without stretching or desktop overflow', () => { + const mixedFields: QueryField[] = [ + { key: 'status', type: 'select', label: '状态' }, + { key: 'keyword', type: 'input', label: '订单号/入仓码/客户名称' }, + ] + const wrapper = mountToolbar({ + modelValue: { status: '', keyword: '' }, + fields: mixedFields, + availableFields: mixedFields, + }) + const renderedFields = wrapper.findAll('.query-toolbar__field') + expect(renderedFields[0].attributes('style')).toBe('--query-field-width: 180px;') + expect(renderedFields[1].attributes('style')).toBe('--query-field-width: 260px;') + expect(renderedFields[1].classes()).toContain('query-toolbar__tail') + expect(renderedFields[1].find('.query-toolbar__actions').exists()).toBe(true) + + const source = readFileSync(resolve(process.cwd(), 'src/shared/components/QueryToolbar.vue'), 'utf8') + expect(source).toContain('justify-content: flex-start; flex-wrap: wrap;') + expect(source).toContain('flex: 0 0 var(--query-field-width)') + expect(source).toContain('overflow-x: clip') + expect(source).toContain('@media (max-width: 720px)') + expect(source).toContain('.query-toolbar__field { width: 100%; flex: 0 0 auto; }') + expect(source).toContain('.query-toolbar__control { width: 100%; flex: 0 0 auto; }') }) it('submits the current filters once when Enter is released in a text input', async () => { diff --git a/src/shared/components/QueryToolbar.vue b/src/shared/components/QueryToolbar.vue index e995330d..4145b589 100644 --- a/src/shared/components/QueryToolbar.vue +++ b/src/shared/components/QueryToolbar.vue @@ -133,9 +133,16 @@ function datePickerType(field: QueryField): 'date' | 'daterange' { return field.type === 'daterange' ? 'daterange' : 'date' } +const defaultFieldWidths: Record = { + select: 180, + date: 180, + input: 260, + daterange: 300, +} + function fieldStyle(field: QueryField) { - if (field.width === undefined) return undefined - const width = typeof field.width === 'number' ? `${field.width}px` : field.width + const fieldWidth = field.width ?? defaultFieldWidths[field.type] + const width = typeof fieldWidth === 'number' ? `${fieldWidth}px` : fieldWidth return { '--query-field-width': width } } @@ -245,12 +252,13 @@ defineExpose({ search, reset })