使用vxe-table将后端返回的多个表格数据整合为一个对比性的表格

703 阅读1分钟

- 需求说明:

后端一个接口返回所有表格(具体几个表格需要根据select框选择框选择定,具体就是几列,也就是返回了几个表格都是动态的,根据接口确定)的数据,返回的表格list是静态表格的json数据,前端需要将其整合为一个对比表格。拿汽车之家的页面做一个说明:

企业微信截图_1687765433475.png

把实现好的页面做一个说明:

image.png

后端返回数据:返回的数据是类似于一个静态表格的数据,需要前端来整合数据

image.png

image.png

- 功能说明:

  1. 根据select框下的选项查出对应的源端对应的值
  2. 全表查询模糊匹配
  3. 隐藏参数值相同
  4. 隐藏参数值为空

- 主要实现:

<vxe-grid v-bind="gridOptions" :cell-style="cellStyle" :row-style="rowStyle" :column-config="{ resizable: true, minWidth: 160 }" :tooltip-config="{theme: 'light', enterable: true}" show-overflow @cell-dblclick="celldblclick"> </vxe-grid>
 const getTable = () => {
    gridOptions.columns = [
      {
        field: 'Variable_name',
        title: 'Variable_name',
        width: 260,
      },
    ]
    gridOptions.data = [];
    mysql_variables({
      servers: source.value.join(',')
      // servers: '10.9.21.54:10000,10.9.21.12:3306'
    }).then(res => {
      if (res.code == 200) {
        var tableList = res.data;
        var tableAll = [];
        tableList.forEach((value, i) => { //数组循环
          // console.log(value, 'valuevaluevalue');
          for (var pl in value) {    //数组对象遍历,获取到列名数据
            // console.log(pl); //获取key
            gridOptions.columns.push({
              field: pl,
              title: pl,
            })
            //获取到表格内的数据
            const tableRow = value[pl].map((item, index) => {
              return {
                Variable_name: item.Variable_name,
                [pl]: item.Value,
              }
            })
            tableAll.push(tableRow)
          }

        })
        // 数据集合,剥离出表格数据

        let _arr = tableAll.reduce((prev, next) => {
          return prev.length > next.length ? prev : next
        })
        _arr.forEach((itm) => {
          for (let i = 0; i < tableAll.length; i++) {
            tableAll[i].forEach(item => {
              if (item.Variable_name == itm.Variable_name) {
                for (var pl in item) {
                  itm[pl] = item[pl]
                }

              }

            });
          }
        });


        tableData.value = _arr


        //筛选出参数值一致的数组
        sameTable.value = [];
        //筛选出参数值为空的数组
        nullTable.value = [];
        var nullData = []
        _arr.forEach(ele => {
          let itemArr = []
          let itemRow = JSON.parse(JSON.stringify(ele));
          delete itemRow.Variable_name;
          delete itemRow._X_ROW_KEY;
          for (let key in itemRow) {
            itemArr.push(itemRow[key])
          }
          let newList = Array.from(new Set(itemArr))
          if (newList.length > 1) {
            sameTable.value.push(ele)
          } else if (newList.length == 1 && newList[0] == '') {
            nullData.push(ele)
          }
        })

        nullTable.value = _arr.filter(item => nullData.indexOf(item) === -1);

        // 处理数据选项板块
        if (sameVal.value == true) {
          gridOptions.data = sameTable.value;
        } else if (nullVal.value == true && sameVal.value == false) {
          gridOptions.data = nullTable.value;
        } else {
          gridOptions.data = _arr;
        }
      }
    })
  }

- 具体实现

<template>
  <div class="container">
    <div class="header_search">
      <div class="search_son">
        <div>
          <span>选择源端:</span>
          <el-select v-model="source" multiple filterable collapse-tags collapse-tags-tooltip placeholder="请选择"
            style="width:380px;" @visible-change="sourceChange" @remove-tag="removeSource" @blur="sourceBlur">
            <el-option v-for="item in sourceOptions" :key="item.ftype"
              :label="`${item.fserver_host}:${item.fserver_port}:${item.frole}:${item.fstate}`"
              :value="`${item.fserver_host}:${item.fserver_port}`" />
          </el-select>
        </div>
        <div style="margin-left:20px">
          <span> 全表搜索:</span>
          <vxe-input v-model="filterName" type="search" clearable placeholder="试试全表搜索" @keyup="searchEvent"
            style="width:340px;" @clear="searchEvent"></vxe-input>
        </div>
        <div style="margin-left:20px">
          <el-checkbox :disabled="source.length<2" v-model="sameVal" size="large"
            @change="getTable">隐藏参数值相同</el-checkbox>
          <el-checkbox :disabled="source.length==0" v-model="nullVal" size="large"
            @change="getTable">隐藏参数值为空</el-checkbox>
        </div>
      </div>

    </div>
    <div class="header_search">
      <div class="search_son">
        <el-icon style="margin-right:10px;font-weight: bold;">
          <InfoFilled color="#f56c6c" size="16" />
        </el-icon>
        <span style="color: #f56c6c;font-weight: bold;">双击参数的值可进行修改噢!(双击
          Variable_name值可复制值至粘贴板)</span>
      </div>
    </div>
    <!-- 展示表格,先展示一个表格 -->
    <div style="margin-top: 5px;height:74vh">
      <vxe-grid v-bind="gridOptions" :cell-style="cellStyle" :row-style="rowStyle"
        :column-config="{ resizable: true, minWidth: 160 }" :tooltip-config="{theme: 'light', enterable: true}"
        show-overflow @cell-dblclick="celldblclick">
      </vxe-grid>


    </div>
  </div>

</template>

<script setup>
  import { ref, computed, reactive, toRefs, onMounted, defineProps } from 'vue'
  import { mysql_detail, mysql_variables, modify_cnf } from '@/api/mysql';
  import { useStore } from 'vuex';
  import { useRoute } from 'vue-router';
  import XEUtils from 'xe-utils'


  const props = defineProps({
    // 父组件 v-model 没有指定参数名,则默认是 modelValue
    activeName: {
      type: String,
      default: 'basicInform'
    }
  })
  onMounted(() => {

    setTimeout(() => {
      if (localStorage.getItem('mysql_activeName') == 'paramManage') {
        // getTable();
        getSorceIpPort();
      }
    }, 20)
  });
  watch(
    () => props.activeName, (newVal, oldVal) => {
      if (newVal == 'paramManage') {
        // getTable();
        getSorceIpPort();
      }
    }
  )
  // 参数定义
  const route = useRoute();
  const source = ref([])
  const sourceOptions = ref([])
  const filterName = ref('')
  const sameVal = ref(false)
  const nullVal = ref(false)
  const tableData = ref([])
  const sameTable = ref([])
  const nullTable = ref([])
  const slotLable = ref([])
  const gridOptions = reactive({
    border: true,
    // 'max-height': 700,
    height: 'auto',
    align: 'left',
    columnConfig: {
      resizable: true
    },
    columns: [],
    data: []
  })

  // 方法区

  const rowStyle = ({
    row, rowIndex, $rowIndex, column, columnIndex, $columnIndex
  }) => {
    var rowValue = [];
    if (row.Variable_name) {

      let comRow = JSON.parse(JSON.stringify(row));
      delete comRow.Variable_name;
      delete comRow._X_ROW_KEY;
      for (let key in comRow) {
        rowValue.push(comRow[key])
      }
      if (rowValue.length + 1 < gridOptions.columns.length) {
        return {
          backgroundColor: '#f56c6c1a'
        }
        // return 'warning-row'
      }
      let newList = Array.from(new Set(rowValue))
      if (newList.length > 1) {
        // return 'warning-row'
        return {
          backgroundColor: '#f56c6c1a'
        }
      }
      // if (newList[0] == '') {
      //   return {
      //     backgroundColor: '#f56c6c1a'
      //   }
      // }

    }
    return {}
  }
  const cellStyle = ({
    row, rowIndex, $rowIndex, column, columnIndex, $columnIndex
  }) => {
    if (columnIndex == 0) {
      // console.log(column.field);
      return {
        fontWeight: 'bolder',
      }
    }
  }
  const removeSource = (e) => {
    if (source.value.length == 0) {
      gridOptions.columns = [];
      gridOptions.data = [];
    }
  }
  const sourceBlur = (e) => {
    if (source.value.length == 0) {
      gridOptions.columns = [];
      gridOptions.data = [];
    }
  }
  const sourceChange = (e) => {
    // console.log(source.value, '选择的内容项=====');
    if (!e && source.value.length != 0) {
      getTable()
    }


  }
  const getSorceIpPort = () => {
    mysql_detail({
      InstanceName: route.name,
      Line: '',
    }).then(res => {
      if (res.code == 200) {
        //获取ip_port
        sourceOptions.value = res.data
      }
    })

  }
  const getTable = () => {
    gridOptions.columns = [
      {
        field: 'Variable_name',
        title: 'Variable_name',
        width: 260,
      },
    ]
    gridOptions.data = [];
    mysql_variables({
      servers: source.value.join(',')
      // servers: '10.9.21.54:10000,10.9.21.12:3306'
    }).then(res => {
      if (res.code == 200) {
        var tableList = res.data;
        var tableAll = [];
        tableList.forEach((value, i) => { //数组循环
          // console.log(value, 'valuevaluevalue');
          for (var pl in value) {    //数组对象遍历,获取到列名数据
            // console.log(pl); //获取key
            gridOptions.columns.push({
              field: pl,
              title: pl,
            })
            //获取到表格内的数据
            const tableRow = value[pl].map((item, index) => {
              return {
                Variable_name: item.Variable_name,
                [pl]: item.Value,
              }
            })
            tableAll.push(tableRow)
          }

        })
        // 数据集合,剥离出表格数据

        let _arr = tableAll.reduce((prev, next) => {
          return prev.length > next.length ? prev : next
        })
        _arr.forEach((itm) => {
          for (let i = 0; i < tableAll.length; i++) {
            tableAll[i].forEach(item => {
              if (item.Variable_name == itm.Variable_name) {
                for (var pl in item) {
                  itm[pl] = item[pl]
                }

              }

            });
          }
        });


        tableData.value = _arr


        //筛选出参数值一致的数组
        sameTable.value = [];
        //筛选出参数值为空的数组
        nullTable.value = [];
        var nullData = []
        _arr.forEach(ele => {
          let itemArr = []
          let itemRow = JSON.parse(JSON.stringify(ele));
          delete itemRow.Variable_name;
          delete itemRow._X_ROW_KEY;
          for (let key in itemRow) {
            itemArr.push(itemRow[key])
          }
          let newList = Array.from(new Set(itemArr))
          if (newList.length > 1) {
            sameTable.value.push(ele)
          } else if (newList.length == 1 && newList[0] == '') {
            nullData.push(ele)
          }
          // for (let k = 0; k < newList.length; k++) {
          //   if (newList[k] == '') {
          //     nullData.push(ele)
          //   }
          // }
        })

        nullTable.value = _arr.filter(item => nullData.indexOf(item) === -1);

        // 处理数据选项板块
        if (sameVal.value == true) {
          gridOptions.data = sameTable.value;
        } else if (nullVal.value == true && sameVal.value == false) {
          gridOptions.data = nullTable.value;
        } else {
          gridOptions.data = _arr;
        }
      }
    })
  }


  const searchEvent = () => {
    sameVal.value = false;
    nullVal.value = false;
    const filterVal = String(filterName.value).trim().toLowerCase()
    if (filterVal) {
      const filterRE = new RegExp(filterVal, 'gi')
      const searchProps = gridOptions.columns.map(item => {
        return item.field
      })
      const rest = tableData.value.filter(item => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1))
      gridOptions.data = rest.map(row => {
        const item = Object.assign({}, row)
        searchProps.forEach(key => {
          item[key] = String(item[key]).replace(filterRE, match => match)
        })
        return item
      })
    } else {
      gridOptions.data = tableData.value
    }
  }
  //双击复制单元格内容
  const celldblclick = ({ row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, $event }) => {

    if (columnIndex == 0) {
      var save = function (e) {
        e.clipboardData.setData('text/plain', row[column.property]);
        e.preventDefault();//阻止默认行为
      }
      document.addEventListener('copy', save);
      document.execCommand("copy");
      document.removeEventListener('copy', save);
      // this.$message({message: '复制成功', type:'success'}) //加提示
      ElMessage({
        type: 'success',
        message: 'Variable_name值已复制至剪切板'
      })
    } else {
      ElMessageBox.prompt(`修改【${column.property}】下的${row.Variable_name}值:`, `提示`, {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputValue: row[column.property],
      })
        .then(({ value }) => {
          console.log(value, '输入的值=====');
          modify_cnf({
            ServerPort: column.property.split(':')[1],
            ParamName: row.Variable_name,
            Value: value,
            ServerHost: column.property.split(':')[0],
          }).then(res => {
            if (res.code == 200) {
              ElMessage({
                type: 'success',
                message: `修改成功`,
              })
              getTable();
            } else {
              ElMessage({
                type: 'error',
                message: `修改失败`,
              })
            }

          })

        })
        .catch(() => {
          // ElMessage({
          //   type: 'info',
          //   message: 'Input canceled',
          // })
        })
    }

  }
</script>

<style lang="scss" scoped>
  .container {
    width: 100%;
  }

  .header_search {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: space-between;
  }

  .search_son {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
  }
</style>