| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- <template>
- <div class="search-form">
- <!-- 使用 Form 组件 -->
- <Form ref="formRef" :config="searchConfig" :model-value="searchData" @update:model-value="handleFormUpdate"
- :inline="inline" :size="size" :label-width="labelWidth" v-bind="$attrs">
- <!-- 省市区域选择器 slot -->
- <template #areaSelect="{ value, formData }">
- <AddressSelect v-model="formData.areaIds" style="width: 180px" />
- </template>
- </Form>
- <!-- 操作按钮 -->
- <div v-if="showButtons" class="search-buttons">
- <el-button type="primary" :icon="Search" :loading="loading" @click="handleSearch">
- {{ searchText }}
- </el-button>
- <el-button :icon="Refresh" @click="handleReset">
- {{ resetText }}
- </el-button>
- <el-button v-if="showExpand" type="text" :icon="expandCollapse ? ArrowUp : ArrowDown" @click="toggleExpand">
- {{ expandCollapse ? "收起" : "展开" }}
- </el-button>
- </div>
- </div>
- </template>
- <script setup>
- import { ref, reactive, watch, computed, onMounted } from "vue";
- import { Search, Refresh, ArrowUp, ArrowDown } from "@element-plus/icons-vue";
- import Form from "@/components/Form/index.vue";
- import AddressSelect from "@/components/AddressSelect/index.vue";
- const props = defineProps({
- // 表单配置(从父组件传入)
- config: {
- type: Array,
- default: () => [],
- },
- // 搜索数据
- modelValue: {
- type: Object,
- default: () => ({}),
- },
- // 是否内联
- inline: {
- type: Boolean,
- default: true,
- },
- // 尺寸
- size: {
- type: String,
- default: "default",
- },
- // 标签宽度
- labelWidth: {
- type: String,
- default: "auto",
- },
- // 是否显示按钮
- showButtons: {
- type: Boolean,
- default: true,
- },
- // 搜索按钮文本
- searchText: {
- type: String,
- default: "搜索",
- },
- // 重置按钮文本
- resetText: {
- type: String,
- default: "重置",
- },
- // 是否显示展开/收起
- showExpand: {
- type: Boolean,
- default: false,
- },
- // 展开时显示的字段数量
- expandCount: {
- type: Number,
- default: 3,
- },
- // 加载状态
- loading: {
- type: Boolean,
- default: false,
- },
- // 搜索处理函数(从父组件传入)
- onSearch: {
- type: Function,
- default: null,
- },
- // 重置处理函数(从父组件传入)
- onReset: {
- type: Function,
- default: null,
- },
- });
- const emit = defineEmits([
- "update:modelValue",
- "search",
- "reset",
- "expand-change",
- ]);
- const formRef = ref();
- const searchData = reactive({});
- const expandCollapse = ref(true);
- // 处理Form组件update:model-value事件
- const handleFormUpdate = (newData) => {
- Object.assign(searchData, newData);
- };
- // 监听父组件传入的modelValue变化,同步到searchData
- watch(
- () => props.modelValue,
- (newValue) => {
- if (newValue) {
- Object.assign(searchData, newValue);
- }
- },
- { immediate: true, deep: true }
- );
- // 监听searchData变化,同步回父组件
- watch(
- searchData,
- (newData) => {
- emit("update:modelValue", { ...newData });
- },
- { deep: true }
- );
- // 强制监听searchData中的areaIds字段
- watch(
- () => searchData.areaIds,
- (newAreaIds, oldAreaIds) => {
- if (newAreaIds !== oldAreaIds) {
- emit("update:modelValue", { ...searchData });
- }
- },
- { immediate: false, deep: true }
- );
- // 计算属性 - 筛选出可搜索的字段
- const searchConfig = computed(() => {
- let config = props.config.filter((item) => item.search !== false);
- if (props.showExpand && !expandCollapse.value) {
- config = config.slice(0, props.expandCount);
- }
- return config;
- });
- // 搜索处理
- const handleSearch = () => {
- const params = { ...searchData };
- // 过滤空值
- Object.keys(params).forEach((key) => {
- if (
- params[key] === "" ||
- params[key] === null ||
- params[key] === undefined
- ) {
- delete params[key];
- }
- });
- // 如果父组件传入了搜索处理函数,则调用
- if (props.onSearch) {
- props.onSearch(params);
- }
- emit("search", params);
- };
- // 重置处理
- const handleReset = () => {
- formRef.value.resetFields();
- // 如果父组件传入了重置处理函数,则调用
- if (props.onReset) {
- props.onReset();
- }
- emit("reset");
- emit("search", {});
- };
- // 展开/收起切换
- const toggleExpand = () => {
- expandCollapse.value = !expandCollapse.value;
- emit("expand-change", expandCollapse.value);
- };
- // 监听外部数据变化
- watch(
- () => props.modelValue,
- (newVal) => {
- Object.assign(searchData, newVal);
- },
- { deep: true, immediate: true }
- );
- // 监听搜索数据变化
- watch(
- searchData,
- (newVal) => {
- emit("update:modelValue", { ...newVal });
- },
- { deep: true }
- );
- // 暴露方法
- defineExpose({
- formRef,
- handleSearch,
- handleReset,
- toggleExpand,
- });
- </script>
- <style scoped>
- .search-form {
- background: var(--el-bg-color);
- padding: 18px;
- border-radius: 4px;
- margin-bottom: 16px;
- }
- .search-buttons {
- margin-top: 18px;
- text-align: left;
- }
- .search-buttons .el-button {
- margin-right: 10px;
- }
- </style>
|