表格实现高级搜索,并封装高级搜索组件

1.项目中有个页面客户提到使用高级搜索,需要仿照jeecgboot3的高级搜索框,(下载的代码里面没有这个组件,应该是要收费,所以只好自己看人家的效果,然后自己手动封装一个)即左侧的条件为从表格的表头动态获取,中间的方式为等于/模糊,右侧的输入框为查询内容,点即最右侧的 + 可以新增一列,点击最右侧的 - 删除一列,若是条件都删除,通过新增按钮,在新增一列,后来客户又提了新的需求,说是要加个筛选条件关系,如 并且(多个条件必须同时满足) 和 或(多个条件,有一个满足就行)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

高级搜索组件代码
advancedQuery.vue

<template>
  <a-modal v-model:visible="props.visibleSearch" title="高级查询" @ok="handleOk" :width="700" @cancel="handleCancel">
    <template #footer>
      <div style="display: flex; justify-content: space-between">
        <span>
          <a-button key="reset" @click="resetSearch">重置</a-button>
          <a-button key="save" @click="saveSearch">保存查询</a-button>
        </span>
        <span>
          <a-button key="back" @click="handleCancel">关闭</a-button>
          <a-button key="submit" type="primary" @click="confirm">确定</a-button>
        </span>
      </div>
    </template>
    <div style="display: flex; justify-content:flex-start;margin-top:10px;padding:0 20px;align-items:center;">
      <div style="margin-right:10px;">筛选条件并列关系:</div>
      <div>
        <a-select v-model:value="relation" placeholder="请选择关系" allowClear style="width: 160px">
          <a-select-option v-for="(item, index) in relationData" :key="index" :label="item.text" :value="item.value">{{ item.text }}</a-select-option>
        </a-select>
      </div>
    </div>
    <div style="min-height: 200px" v-if="childList.length > 0">
      <div style="margin: 20px" v-for="(item, index) in childList" :key="index">
        <a-select v-model:value="item.field" placeholder="请选择字段" allowClear style="width: 160px; margin-right: 10px">
          <a-select-option v-for="(item, index) in props.fieldData" :key="index" :label="item.title" :value="item.key">{{
            item.title
          }}</a-select-option>
        </a-select>
        <a-select v-model:value="item.condition" placeholder="请选择" allowClear style="width: 120px; margin-right: 10px">
          <a-select-option v-for="(item, index) in props.filedCondition" :key="index" :label="item.text" :value="item.value">{{
            item.text
          }}</a-select-option>
        </a-select>
        <a-input v-model:value="item.fieldValue" style="width: 120px; margin-right: 10px"></a-input>
        <a-button style="margin-right: 10px" @click="addRowCustom"><Icon icon="ant-design:plus-outlined"></Icon></a-button>
        <a-button @click="delRowCustom(index)"><Icon icon="ant-design:minus-circle-outlined"></Icon></a-button>
      </div>
    </div>
    <div v-else style="min-height: 200px">
      <a-empty />
      <div style="display: flex; justify-content: center; align-items: center"
        >没有任何查询条件 <a-divider type="vertical" /> <span style="color: #3e90ff; cursor: pointer" @click="addRowCustom">点击新增</span></div
      >
    </div>
  </a-modal>
</template>
<script lang="ts" setup>
import { computed, reactive, ref, defineEmits, defineProps } from 'vue';
const emits = defineEmits(['close', 'reset', 'confirm']);
// const resetEmits=defineEmits(['reset'])
const props = defineProps({
  fieldData: {
    type: Array,
    default: [],
  }, //字段
  visibleSearch: {
    type: Boolean,
    default: false,
  },
  // Boolean,//条件
  filedCondition: {
    type: Array,
    default: [],
  }, //
  relation: {
    type: Number,
    default: 0,
  },
});

const relation=ref(0);
// relation.value=props.relation;

const relationData = [
  { value: 0, text: 'or' },
  { value: 1, text: 'and' },
];

const visible = ref(false);
visible.value = props.visibleSearch;
let childList = ref([{}]);
function addRowCustom() {
  childList.value.push({});
}
function delRowCustom(index) {
  childList.value.splice(index, 1);
}

function confirm() {
  let obj={
    childList:childList.value,
    relation:relation.value,
  }
  console.log(childList.value, 'childList++');
  emits('confirm', obj);
}

function resetSearch() {
  // console.log("重置按钮")
  const obj = '';
  relation.value=0;
  childList.value = [{}];
  emits('reset', obj);
}
function saveSearch() {
  console.log('保存按钮');
}

function handleCancel() {
  const obj = ref({
    visible: false,
  });
  emits('close', obj);
}
</script>

使用高级搜索组件
html部分

<advancedQuery
      @close="handleCancel"
      @reset="resetSearch"
      @confirm="handleOk"
      :fieldData="columns"
      :filedCondition="conditionData"
      :visibleSearch="visible"
    ></advancedQuery>

js部分

import advancedQuery from '/@/components/advancedQuery.vue'; //引入高级查询组件

const dataSource=ref([]);
const columns = [
  {
    title: '数量',
    dataIndex: 'qty',
    key: 'qty',
    align: 'center',
    ellipsis: true,
    width: 80,
  },
  {
    title: '供应商编码',
    dataIndex: 'vendorCode',
    key: 'vendorCode',
    align: 'center',
    ellipsis: true,
    width: 120,
  },
  {
    title: '产品名称',
    dataIndex: 'productName',
    key: 'productName',
    align: 'center',
    ellipsis: true,
    width: 120,
  },
  {
    title: '物料编号',
    dataIndex: 'productCode',
    key: 'productCode',
    align: 'center',
    ellipsis: true,
    width: 120,
  },
  {
    title: '产品上级名称',
    dataIndex: 'productParent',
    key: 'productParent',
    align: 'center',
    ellipsis: true,
    width: 120,
  },
  {
    title: '产品上级图号',
    dataIndex: 'productParentFig',
    key: 'productParentFig',
    align: 'center',
    ellipsis: true,
    width: 120,
  },
  {
    title: '产品下级',
    dataIndex: 'productChild',
    key: 'productChild',
    align: 'center',
    ellipsis: true,
    width: 120,
  },
  {
    title: '产品状态',
    dataIndex: 'productState',
    key: 'productState',
    align: 'center',
    ellipsis: true,
    width: 120,
  },
  {
    title: '材质',
    dataIndex: 'material',
    key: 'material',
    align: 'center',
    ellipsis: true,
    width: 100,
  },
  {
    title: '表面处理',
    dataIndex: 'surfaceDeal',
    key: 'surfaceDeal',
    align: 'center',
    ellipsis: true,
    width: 100,
  },
  {
    title: '热处理',
    dataIndex: 'headDeal',
    key: 'headDeal',
    align: 'center',
    ellipsis: true,
    width: 100,
  },
  {
    title: '技术编号',
    dataIndex: 'techNo',
    key: 'techNo',
    align: 'center',
    ellipsis: true,
    width: 100,
  },
  {
    title: '备注',
    dataIndex: 'remark',
    key: 'remark',
    align: 'center',
    ellipsis: true,
    width: 100,
  },
];
const visible = ref(false);
const relation = ref(0);

const conditionArr = ref([]); //查询条件

const conditionData = ref();
conditionData.value = [
  { value: 1, text: '等于' },
  { value: 2, text: '模糊' },
  // { value: 3, text: '以..开始' },
  // { value: 4, text: '以..结尾' },
  // { value: 5, text: '在...中' },
  // { value: 6, text: '不等于' },
  // { value: 7, text: '大于' },
  // { value: 8, text: '大于等于' },
];

function advancedSearch() {
  visible.value = true;
}
function handleOk(obj) {
  console.log(obj, '组件传值');
  let arr = obj.childList;
  relation.value = obj.relation;
  if (JSON.stringify(arr[0]) == '{}') {
    conditionArr.value = [];
  } else {
    conditionArr.value = arr;
  }
  visible.value = false;
  let inData = JSON.parse(sessionStorage.getItem('inData'));
  if (inData) {
    dataSource.value = inData;
  }
  let temp = inData;
  if(relation.value==0){
    let temp3 = [];
    if(conditionArr.value.length>0){
      for (let item of dataSource.value) {
        for (let j of conditionArr.value) {
          if (j.condition == 1) {
            if (item[j.field] == j.fieldValue) {
              temp3.push(item)
            }
          } else if (j.condition == 2) {
            if (item[j.field].toString().indexOf(j.fieldValue) != -1) {
              temp3.push(item);
            }
          }
        }
      }
      dataSource.value = reduce(temp3, 'productCode');
    }
  }else if(relation.value==1){
    for (let i = 0; i < conditionArr.value.length; i++) {
      let temp2 = [];
      for (let j = 0; j < temp.length; j++) {
        if (conditionArr.value[i].condition == 1) {
          if (temp[j][conditionArr.value[i].field] == conditionArr.value[i].fieldValue) {
            temp2.push(temp[j]);
          }
        }
        if (conditionArr.value[i].condition == 2) {
          if (temp[j][conditionArr.value[i].field].toString().indexOf(conditionArr.value[i].fieldValue.toString()) != -1) {
            temp2.push(temp[j]);
          }
        }
      }
      let mixed = [];
      temp.forEach((item) => {
        temp2.forEach((items) => {
          if (item.productCode == items.productCode) {
            mixed.push(item);
          }
        });
      });
      temp = mixed;
    }
    dataSource.value=temp;
  }
  console.log(dataSource.value,'dataSource++')
}

function resetSearch() {
  relation.value = 0;
  conditionArr.value = [];
}
function saveSearch() {
  console.log('保存按钮');
}

function handleCancel() {
  visible.value = false;
}



  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue左树右表封装组件是一种常用的组件封装技术,用于展示有树形结构和表格结构的数据。它将左侧的树形结构和右侧的表格结构结合在一起,方便用户对数据进行查看和操作。 该组件通常包含以下两个主要部分: 1. 左侧树形结构:在左侧展示树形结构,用于展示数据的层级关系。用户可以通过点击树节点来展开或折叠子节点。树形结构的节点通常具有不同的图标或样式,以便区分不同的节点类型或状态。 2. 右侧表格结构:在右侧展示以表格形式呈现的数据。表格通常包含多列,每列对应数据的一个属性。用户可以通过排序、筛选或搜索等方式来对表格数据进行操作。 组件封装可以提供一些可配置的参数,以便根据实际需求进行定制。例如,可以通过传递数据源、树节点的渲染函数、表格列的定义等参数来实现组件的灵活性。 使用Vue左树右表封装组件可以带来一些好处。首先,它将树形结构和表格结构有机地结合在一起,提供了直观、便捷的数据展示和操作方式。其次,组件封装可以提高代码的重用性和可维护性,使开发过程更加高效。最后,通过合理的设计,该组件还可以实现一些高级功能,如拖拽排序、批量操作等,进一步提升用户体验。 综上所述,Vue左树右表封装组件是一种非常实用的组件封装技术,能够方便地展示和操作有树形和表格结构的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coderdwy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值