164 lines
4.5 KiB
Vue
164 lines
4.5 KiB
Vue
<script setup lang="ts">
|
|
import { computed, ref, useSlots } from 'vue';
|
|
import type { ComponentPublicInstance } from 'vue';
|
|
import type { FormInstance } from 'element-plus';
|
|
import { $t } from '@/locales';
|
|
|
|
defineOptions({ name: 'TableSearchPanel' });
|
|
|
|
interface Props {
|
|
model: object;
|
|
rules?: Record<string, App.Global.FormRule | App.Global.FormRule[]>;
|
|
formRef?: ((instance: FormInstance | null) => void) | null;
|
|
labelWidth?: string | number;
|
|
labelPosition?: 'left' | 'right' | 'top';
|
|
gutter?: number;
|
|
actionColLg?: number;
|
|
actionColMd?: number;
|
|
actionColSm?: number;
|
|
disabled?: boolean;
|
|
defaultExpanded?: boolean;
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
rules: undefined,
|
|
formRef: null,
|
|
labelWidth: 80,
|
|
labelPosition: 'right',
|
|
gutter: 24,
|
|
actionColLg: 6,
|
|
actionColMd: 24,
|
|
actionColSm: 24,
|
|
disabled: false,
|
|
defaultExpanded: false
|
|
});
|
|
|
|
interface Emits {
|
|
(e: 'reset'): void;
|
|
(e: 'search'): void;
|
|
}
|
|
|
|
const emit = defineEmits<Emits>();
|
|
|
|
const slots = useSlots();
|
|
const expanded = ref(props.defaultExpanded);
|
|
|
|
const hasExtra = computed(() => Boolean(slots.extra));
|
|
|
|
function handleReset() {
|
|
emit('reset');
|
|
}
|
|
|
|
function handleSearch() {
|
|
emit('search');
|
|
}
|
|
|
|
function toggleExpanded() {
|
|
if (!hasExtra.value) {
|
|
return;
|
|
}
|
|
|
|
expanded.value = !expanded.value;
|
|
}
|
|
|
|
function handleFormRef(instance: Element | ComponentPublicInstance | null) {
|
|
props.formRef?.(instance as FormInstance | null);
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<ElCard class="card-wrapper">
|
|
<ElForm
|
|
:ref="handleFormRef"
|
|
:model="props.model"
|
|
:rules="props.rules"
|
|
:label-position="props.labelPosition"
|
|
:label-width="props.labelWidth"
|
|
@submit.prevent
|
|
@keyup.enter="handleSearch"
|
|
>
|
|
<ElRow :gutter="props.gutter">
|
|
<slot />
|
|
|
|
<ElCol
|
|
v-if="!hasExtra"
|
|
class="table-search-panel__action-col"
|
|
:lg="props.actionColLg"
|
|
:md="props.actionColMd"
|
|
:sm="props.actionColSm"
|
|
>
|
|
<ElSpace class="w-full justify-end" alignment="end">
|
|
<ElButton :disabled="props.disabled" @click="handleReset">
|
|
<template #icon>
|
|
<icon-ic-round-refresh class="text-icon" />
|
|
</template>
|
|
{{ $t('common.reset') }}
|
|
</ElButton>
|
|
<ElButton type="primary" plain :disabled="props.disabled" @click="handleSearch">
|
|
<template #icon>
|
|
<icon-ic-round-search class="text-icon" />
|
|
</template>
|
|
{{ $t('common.search') }}
|
|
</ElButton>
|
|
</ElSpace>
|
|
</ElCol>
|
|
</ElRow>
|
|
|
|
<ElRow v-if="hasExtra && expanded" :gutter="props.gutter">
|
|
<slot name="extra" />
|
|
|
|
<ElCol
|
|
class="table-search-panel__action-col"
|
|
:lg="props.actionColLg"
|
|
:md="props.actionColMd"
|
|
:sm="props.actionColSm"
|
|
>
|
|
<ElSpace class="w-full justify-end" alignment="end">
|
|
<ElButton circle :disabled="props.disabled" @click="toggleExpanded">
|
|
<icon-mdi-chevron-double-up class="text-16px" />
|
|
</ElButton>
|
|
<ElButton :disabled="props.disabled" @click="handleReset">
|
|
<template #icon>
|
|
<icon-ic-round-refresh class="text-icon" />
|
|
</template>
|
|
{{ $t('common.reset') }}
|
|
</ElButton>
|
|
<ElButton type="primary" plain :disabled="props.disabled" @click="handleSearch">
|
|
<template #icon>
|
|
<icon-ic-round-search class="text-icon" />
|
|
</template>
|
|
{{ $t('common.search') }}
|
|
</ElButton>
|
|
</ElSpace>
|
|
</ElCol>
|
|
</ElRow>
|
|
|
|
<div v-if="hasExtra && !expanded" class="flex justify-end">
|
|
<ElSpace>
|
|
<ElButton circle :disabled="props.disabled" @click="toggleExpanded">
|
|
<icon-mdi-chevron-double-down class="text-16px" />
|
|
</ElButton>
|
|
<ElButton :disabled="props.disabled" @click="handleReset">
|
|
<template #icon>
|
|
<icon-ic-round-refresh class="text-icon" />
|
|
</template>
|
|
{{ $t('common.reset') }}
|
|
</ElButton>
|
|
<ElButton type="primary" plain :disabled="props.disabled" @click="handleSearch">
|
|
<template #icon>
|
|
<icon-ic-round-search class="text-icon" />
|
|
</template>
|
|
{{ $t('common.search') }}
|
|
</ElButton>
|
|
</ElSpace>
|
|
</div>
|
|
</ElForm>
|
|
</ElCard>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.table-search-panel__action-col {
|
|
margin-left: auto;
|
|
}
|
|
</style>
|