85 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Vue
		
	
	
		
		
			
		
	
	
			85 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Vue
		
	
	
|  | <template> | ||
|  |   <el-form :model="modelValue" :label-width="labelWidth" @submit.prevent="emits('submit')"> | ||
|  |     <el-row :class="className"> | ||
|  |       <template v-if="options && options.length"> | ||
|  |         <form-items-renderer v-model="modelValue" :options="options" :span="6" :collapse="collapse" :auto-generate-required="false"> | ||
|  |           <template v-for="(_, name) in slots" :key="name" #[name]="slotProps"> | ||
|  |             <slot :name="name" v-bind="slotProps" /> | ||
|  |           </template> | ||
|  |         </form-items-renderer> | ||
|  |       </template> | ||
|  |       <template v-else> | ||
|  |         <slot :collapse="collapse"></slot> | ||
|  |       </template> | ||
|  |       <el-col :span="showCollapseButton ? (collapse ? 6 : span) : span"> | ||
|  |         <el-form-item label-width="10px" class="end"> | ||
|  |           <el-button type="primary" native-type="submit"> 搜索 </el-button> | ||
|  |           <el-button native-type="reset" @click="emits('submit')"> | ||
|  |             重置 | ||
|  |           </el-button> | ||
|  |           <template v-if="showCollapseButton"> | ||
|  |             <el-button v-if="collapse" :icon="ArrowDown" link text type="primary" @click="changeSearchCollapse"> | ||
|  |               展开 | ||
|  |             </el-button> | ||
|  |             <el-button v-if="!collapse" :icon="ArrowUp" link text type="primary" @click="changeSearchCollapse"> | ||
|  |               收起 | ||
|  |             </el-button> | ||
|  |           </template> | ||
|  |         </el-form-item> | ||
|  |       </el-col> | ||
|  |       <el-col v-if="slots.button" :span="24"> | ||
|  |         <el-form-item label-width="0"> | ||
|  |           <slot name="button"></slot> | ||
|  |         </el-form-item> | ||
|  |       </el-col> | ||
|  |     </el-row> | ||
|  |   </el-form> | ||
|  | </template> | ||
|  | 
 | ||
|  | <script setup> | ||
|  | import { nextTick, onMounted, ref, useSlots, watch } from "vue"; | ||
|  | import { uniqueId } from "lodash-es"; | ||
|  | import { ArrowDown, ArrowUp } from "@element-plus/icons-vue"; | ||
|  | import { ElForm, ElRow, ElCol, ElFormItem, ElButton } from "element-plus"; | ||
|  | import "element-plus/es/components/form/style/css"; | ||
|  | import "element-plus/es/components/row/style/css"; | ||
|  | import "element-plus/es/components/col/style/css"; | ||
|  | import "element-plus/es/components/form-item/style/css"; | ||
|  | import "element-plus/es/components/button/style/css"; | ||
|  | import FormItemsRenderer from "../form_builder/form_items_renderer.vue"; | ||
|  | 
 | ||
|  | const slots = useSlots(); | ||
|  | defineOptions({ | ||
|  |   name: "AppSearch", | ||
|  | }); | ||
|  | const props = defineProps({ | ||
|  |   labelWidth: { type: String, default: "110px" }, | ||
|  |   options: { type: Array, default: () => [] }, | ||
|  | }); | ||
|  | const modelValue = defineModel({ type: Object, required: true }); | ||
|  | const emits = defineEmits(["submit"]); | ||
|  | const className = ref(uniqueId("_")); | ||
|  | const span = ref(6); | ||
|  | const showCollapseButton = ref(false); | ||
|  | const collapse = ref(true); | ||
|  | const changeSearchCollapse = () => { | ||
|  |   collapse.value = !collapse.value; | ||
|  | }; | ||
|  | onMounted(() => { | ||
|  |   watch( | ||
|  |     () => props.options, | ||
|  |     async () => { | ||
|  |       await nextTick(); | ||
|  |       const colEl = document.querySelectorAll(`.${className.value} .el-col`); | ||
|  |       const colElLength = colEl.length; | ||
|  |       const excludeLast = colElLength - (slots.button ? 2 : 1); | ||
|  |       span.value = { 0: 24, 1: 18, 2: 12, 3: 6 }[excludeLast % 4]; | ||
|  |       showCollapseButton.value = excludeLast > 3; | ||
|  |     }, | ||
|  |     { immediate: true } | ||
|  |   ); | ||
|  | }); | ||
|  | </script> | ||
|  | 
 | ||
|  | <style scoped lang="scss"></style> |