组件开发-- 头部查询根据查询条件个数展开收起,查询按钮位置变化(CSS实现)

358 阅读3分钟

2024.1.23

页面头部表单查询要求

  1. 默认收起的的行数是2行,超过两行,显示展开的箭头,收起;
  2. 一行展示3个元素,如果单行元素低于2个,将按钮放置在末尾;
  3. 如果行数超过三行,按钮另起一行放在中间;
  4. 查询条件3-5个时,查询与重置第二行右侧,右对齐;
  5. 查询条件为3个时:查询与重置另起一行,居中对齐。

组件引用

<SelectForm
  :searchFormList="columns"
  :searchData="searchData.data"
  :on-search="handleSearch"
  :on-reset="handleReset"
  :on-change="handleChange"
/>
    
const searchData = reactive({
  data: {},
})

const columns = reactive([
  { label: '表单label1', prop: 'prop1', searchType: 'input' },
  { label: '表单label2', prop: 'prop2', searchType: 'input' },
  { label: '表单label3', prop: 'prop3', type: 'enum', enum: fileTaskType, searchType: 'select' },
  { label: '表单label4', prop: 'prop4', searchType: 'custom-select', type: 'enum', enum: fileTaskFlow },
  { label: '表单label5', prop: 'prop5', searchType: 'input' },
  { label: '表单label6', prop: 'prop6', type: 'switch', enum: SERVICE_STATUS, width: 120, searchType: 'select' },
  { label: '表单label7', prop: 'prop7', type: 'enum', enum: ENDDAYBATCH_TYPE, searchType: 'select' },
  { label: '表单label8', prop: 'prop8', searchType: 'input' },
])


const handleChange = (prop, val) => {
  searchData.data[prop] = val
}
const handleSearch = () => {
  pageable.pageNum = 1
  pageable.pageSize = 10
  getDataList()
}
const handleReset = () => {
  searchData.data = {}
  pageable.pageNum = 1
  pageable.pageSize = 10
  getDataList()
}

效果图

查询条件1个,查询按钮右对齐

image.png

查询条件2个,查询按钮右对齐 image.png

查询条件3个,查询按钮另起一行居中对齐 image.png

查询条件4个,查询按钮右对齐 image.png

查询条件5个,查询按钮右对齐 image.png

查询条件6个,查询按钮另起一行居中对齐 image.png

查询条件大于7个,显示展开收起按钮,和查询按钮一行展示,查询按钮居中对齐 image.png

收起条件 image.png

展开条件 image.png

组件代码SelectForm

<!--
 * @Author: SunnyYang
 * @Date: 2024-01-16 10:27:52
 * @LastEditors: SunnyYang
 * @LastEditTime: 2024-03-27 11:26:49
 * @Description: 
-->
<template>
  <div class="formContainer">
    <el-form class="searchContainer" :model="searchData" label-width="100px">
      <template v-for="(item, index) in searchFormList" :key="item.prop">
        <el-form-item v-if="item.searchType == 'input' && flodShow(index)" :label="item.label">
          <el-input v-model="searchData[item.prop]" placeholder="请输入" clearable />
        </el-form-item>

        <el-form-item v-if="item.searchType === 'select' && flodShow(index)" :label="item.label">
          <el-select v-model="searchData[item.prop]" placeholder="请选择" clearable>
            <el-option v-if="item.all" label="全部" value="" />
            <el-option
              v-for="stems in item.enum"
              :key="stems[selectValue]"
              :label="stems[selectLabel]"
              :value="stems[selectValue]"
            />
          </el-select>
        </el-form-item>

        <el-form-item v-if="item.searchType == 'number' && flodShow(index)" :label="item.label">
          <el-input v-model:number="searchData[item.prop]" placeholder="请输入" clearable />
        </el-form-item>

        <template v-if="item.searchType == 'custom-select' && flodShow(index)">
          <StepSecond
            :formData="searchData"
            :label="item.label"
            :initFled="{}"
            :handleSelect="onChange"
            :required="false"
          />
        </template>
      </template>

      <div v-if="searchFormList.length <= showLength" class="el-form-item el-form-btn">
        <el-button @click="onReset" style="width: 86px; margin-left: 16px">重置</el-button>
        <el-button type="primary" style="width: 86px" @click="onSearch">查询</el-button>
      </div>
    </el-form>

    <div v-if="searchFormList.length > showLength" class="el-form-search-box">
      <el-button class="el-form-search-arraw" link type="primary" @click="foldFilterConditions = !foldFilterConditions">
        <template #default>
          <template v-if="!foldFilterConditions">
            展开条件({{ searchFormList.length - showLength || 0 }})<el-icon class="el-icon--right"
              ><ArrowDown
            /></el-icon>
          </template>
          <template v-else>
            收起条件<el-icon class="el-icon--right"><ArrowUp /></el-icon>
          </template>
        </template>
      </el-button>
      <div class="el-form-search-btn">
        <el-button @click="onReset" style="width: 86px; margin-left: 16px">重置</el-button>
        <el-button type="primary" style="width: 86px" @click="onSearch">查询</el-button>
      </div>
    </div>
  </div>
</template>

<script setup name="SelectForm">
import { ref, watch } from 'vue'
import StepSecond from '@/views/interfaceRegister/addModules/StepSecond.vue'
const props = defineProps({
  searchFormList: {
    type: Array,
    default: () => [],
  },
  searchData: {
    type: Object,
    default: () => ({}),
  },
  selectLabel: {
    type: String,
    default: 'dataValue',
  },
  selectValue: {
    type: String,
    default: 'dataCode',
  },
  onReset: {
    type: Function,
    default: () => {},
  },
  onSearch: {
    type: Function,
    default: () => {},
  },
  onChange: {
    type: Function,
    default: () => {},
  },
  showLength: {
    type: Number,
    default: 6,
  },
})

//是否展示收起展开按钮
const foldFilterConditions = ref(false)

//超出showLength隐藏
const flodShow = (index) => {
  const value = index < props.showLength ? true : foldFilterConditions.value
  return value
}
</script>

<style scoped lang="scss">
.formContainer {
  padding-bottom: 20px;

  .el-form {
    display: flex;
    flex-wrap: wrap;
  }

  /*css实现效果---*/
  .el-form-item {
    flex: none;
    width: 33.3%;

    &.el-form-btn:nth-child(2),
    &.el-form-btn:nth-child(3),
    &.el-form-btn:nth-child(5),
    &.el-form-btn:nth-child(6) {
      flex: auto;
      justify-content: end;
    }
    &.el-form-btn:nth-child(4),
    &.el-form-btn:nth-child(7) {
      margin: 18px auto 0;
      width: auto;
    }
  }

  .el-form-search-box {
    display: flex;
    align-items: center;
    margin-top: 18px;
    margin-left: 16px;

    .el-form-search-arraw {
      width: 100px;
    }

    .el-form-search-btn {
      margin: 0 auto;
      width: auto;
    }
  }
  /*css实现效果---*/
}

/*input 添加 clearable属性 聚焦时宽度会变化*/
:deep(.el-input__wrapper) {
  position: relative;
  .el-input__inner {
    padding-right: 18px;
  }
  .el-input__suffix {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
  }
}
</style>