feat: add search panel

This commit is contained in:
2025-12-17 15:32:42 +08:00
parent 2f03dcf8d8
commit 920bbc4c5a
5 changed files with 105 additions and 45 deletions

View File

@@ -0,0 +1,24 @@
<script setup>
const props = defineProps({
label: { type: String, required: true },
forId: { type: String, default: '' },
colClass: { type: String, default: 'col-span-12 md:col-span-6 lg:col-span-4' },
labelClass: { type: String, default: 'w-28 text-right' }
});
</script>
<template>
<div :class="props.colClass">
<div class="flex items-center gap-3">
<label v-if="props.forId" :for="props.forId"
class="text-sm font-medium text-surface-900 dark:text-surface-0" :class="props.labelClass">
{{ props.label }}
</label>
<span v-else class="text-sm font-medium text-surface-900 dark:text-surface-0" :class="props.labelClass">{{
props.label }}</span>
<div class="flex-1 min-w-0">
<slot />
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,44 @@
<script setup>
import { Comment, computed, ref, useSlots } from 'vue';
const props = defineProps({
collapsedCount: { type: Number, default: 3 },
initialExpanded: { type: Boolean, default: false },
loading: { type: Boolean, default: false }
});
const emit = defineEmits(['search', 'reset']);
const slots = useSlots();
const expanded = ref(props.initialExpanded);
const fieldNodes = computed(() => {
const nodes = slots.default ? slots.default() : [];
return (nodes || []).filter((n) => n && n.type !== Comment);
});
const canToggle = computed(() => fieldNodes.value.length > props.collapsedCount);
const visibleFields = computed(() => (expanded.value ? fieldNodes.value : fieldNodes.value.slice(0, props.collapsedCount)));
function onToggle() {
expanded.value = !expanded.value;
}
</script>
<template>
<div class="mb-4 p-4 rounded border border-surface-200 dark:border-surface-700 bg-surface-0 dark:bg-surface-900">
<div class="flex flex-col lg:flex-row lg:items-end gap-4 lg:gap-6">
<div class="flex-1 grid grid-cols-12 gap-x-6 gap-y-4 items-end">
<template v-for="(node, idx) in visibleFields" :key="idx">
<component :is="node" />
</template>
</div>
<div class="flex items-center justify-end gap-2 lg:flex-none">
<Button label="查询" icon="pi pi-search" :loading="props.loading" @click="emit('search')" />
<Button label="重置" icon="pi pi-refresh" severity="secondary" outlined :disabled="props.loading" @click="emit('reset')" />
<Button v-if="canToggle" :label="expanded ? '收起' : '展开'" :icon="expanded ? 'pi pi-angle-up' : 'pi pi-angle-down'" iconPos="right" severity="secondary" text :disabled="props.loading" @click="onToggle" />
</div>
</div>
</div>
</template>