| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- <template>
- <ElForm :inline="false" :model="formInline" class="demo-form-inline" label-width="100px">
- <ElRow :gutter="20">
- <ElCol v-for="(field, index) in fields" :key="index" :md="span">
- <ElFormItem :label="field.label">
- <component v-if="field.type === 'input'" is="el-input" v-model="formInline[field.model]"
- :placeholder="field.placeholder" clearable class="el-inputs" />
- <component v-else-if="field.type === 'select'" is="el-select" v-model="formInline[field.model]"
- :placeholder="field.placeholder" clearable class="el-inputs" v-bind="field">
- <el-option v-for="(item, index) in field.options" :key="index" :label="item[field.props?.label || 'label']"
- :value="item[field.props?.value || 'value']">
- <template #default="scope">
- <slot :name="`${field.model}-option`" :item="item" >
- {{ item[field.props?.label || 'label'] }}
- </slot>
- </template>
- </el-option>
- </component>
- <component v-else-if="field.type === 'cascader'" is="el-cascader" v-model="formInline[field.model]"
- :options="field.options" :props="field.props" :placement="field.placement" filterable clearable
- @change="field.onChange" class="el-inputs" />
- <component v-else-if="field.type === 'date'" is="el-date-picker" v-model="formInline[field.model]"
- :type="field.dateType" range-separator="至" :start-placeholder="field.startplaceholder"
- :format="field.format" :value-format="field.valueFormat" :time-format="field.timeFormat"
- :end-placeholder="field.endplaceholder" clearable @change="field.onChange" />
- </ElFormItem>
- </ElCol>
- <ElCol :md="isOffset ? span : span / 2" :offset="btnOffset">
- <ElFormItem>
- <div class="flex j-end" style="width: 100%;">
- <el-button type="primary" @click="handleSearch">
- <template #icon>
- <SvgIcon name="i-ep:search" />
- </template>
- 查询
- </el-button>
- <el-button type="default" @click="handleReset">重置</el-button>
- </div>
- </ElFormItem>
- </ElCol>
- </ElRow>
- </ElForm>
- </template>
- <script lang="ts" setup>
- import { ref, computed, onMounted, onUnmounted } from 'vue'
- const props = withDefaults(defineProps<{
- fields: Array<{
- label: string; // 字段标签
- model: string; // v-model 绑定的字段名
- type: string; // 字段类型 ('input', 'select', 'cascader', 'date')
- filterable?: boolean; // 是否支持筛选
- placeholder?: string; // 占位符
- options?: Array<{ [key: string]: any }>; // 选项列表
- props?: any; // Cascader 组件的其他 props
- onChange?: (value: any) => void; // 变化事件
- dateType?: string; // 日期选择器类型
- format?: string; // 日期格式
- valueFormat?: string; // 日期值格式
- timeFormat?: string; // 时间格式
- startplaceholder?: string; // 开始日期占位符
- endplaceholder?: string; // 结束日期占位符
- clearable?: boolean; // 是否可清空
- [key: string]: any,
- }>; // 字段信息数组
- formInline: any; // 表单数据
- onSearch: () => void; // 查询事件
- onReset: () => void; // 重置事件
- span?: number;
- isOffset?: boolean; // 是否正规化按钮位置,而不是紧贴formItem后面
- }>(), {
- span: 8,
- isOffset: false,
- filterable: false
- });
- const windowWidth = ref(window.innerWidth);
- onMounted(() => {
- window.addEventListener('resize', updateWindowWidth)
- });
- onUnmounted(() => {
- window.removeEventListener('resize', updateWindowWidth)
- });
- // 定义更新窗口宽度的函数
- const updateWindowWidth = () => {
- windowWidth.value = window.innerWidth;
- };
- // 计算按钮组的左侧偏移量
- const btnOffset = computed(() => {
- // 为了保持原有页面的样子
- if (!props.isOffset) return 0;
- // 因为栅格布局,代码使用的md,所以监听宽度
- if (windowWidth.value < 992) {
- return 0;
- }
- // 计算逻辑
- const items = props.fields.length;
- const columns = 24 / props.span; // 列布局
- const spanPerItem = props.span; // 每列的span
- const itemsOnLastRow = items % columns;
- if (itemsOnLastRow === 0) {
- // 如果刚好占满最后一行,按钮就需要另起一行,并偏移3个位置
- return (columns - 1) * spanPerItem;
- } else {
- // 如果最后一行没占满,计算需要空出的位置数量
- const emptySlots = columns - 1 - itemsOnLastRow;
- return emptySlots * spanPerItem;
- }
- });
- const handleSearch = () => {
- props.onSearch(); // 调用父组件的查询事件
- };
- const handleReset = () => {
- props.onReset(); // 调用父组件的重置事件
- };
- </script>
- <style lang="scss">
- .el-inputs {
- width: 100% !important;
- }
- </style>
|