主要记录下,里面有尾部汇总+汇总后自动跟随列拖动

使用方式:

:showFooter="true"
:footerData="[{field:'total',value:'计'},{field:'hsdj',value:'100'},{field:'wlmc',value:'200'},{field:'ggxhmc',value:'300'}]"

效果图1:自动把汇总数据对应相关列上

 效果图2:拖动列汇总跟随

 

通用Grid代码

<template>
  <div class="gridLayout">
    <!-- :print-config="{}" -->
    <vxe-grid
      border
      auto-resize
      resizable
      highlight-hover-row
      ref="vxe_table"
      height="auto"
      show-header-overflow
      :show-header="showHeader"
      :loading="loading"
      stripe
      :row-config="{ isCurrent: true, isHover: true }"
      :row-id="gridId"
      :toolbar-config="tableToolbar"
      :header-cell-class-name="headerCellClassName"
      columnKey
      :show-overflow="showOverflow"
      :columns="tableColumns"
      @cell-click="cellClick"
      @checkbox-all="checkboxAll"
      :show-footer="showFooter"
      :footer-method="footerMethod"
      :sort-config="sortConfig"
      @sort-change="sortChangeEvent"
      @checkbox-change="checkboxChange"
      :tree-config="treeConfig"
      :data="tableData"
      :span-method="mergeRowMethod"
      :radio-config="{ trigger: 'row' }"
      :checkbox-config="{ trigger: 'row' }"
      :edit-config="{
        trigger: 'click',
        mode: 'row',
      }"
      :export-config="{
        remote: true,
        exportMethod: this.exportMethod,
        mode: 'all',
        types: ['xlsx'],
        modes: ['all'],
      }"
      
      :row-style="rowStyle"
      :cell-style="cellStyle"
      :cell-class-name="cellClassName"
    >
      <!-- :merge-cells="mergeCells" -->
      <!-- , 'current', 'selected' -->
      <!-- :radio-config="{labelField: 'name', trigger: 'row'}" -->
      <!-- :checkbox-config="{checkField:this.multiple?'radio': 'checked', trigger: 'row'}" -->
      <!-- 分页组件 -->
      <template #pager>
        <slot name="pageSlot"></slot>
      </template>
      <!-- 表格按钮插槽 -->
      <template #toolbar_buttons>
        <slot name="leftBtnSlot"></slot>
      </template>
      <!-- 表格工具栏 -->
      <template #refresh_btn>
        <slot name="rightToolSlot"></slot>
        <!-- <div
        v-if="isExport"
        class="refresh-btns"
        title="导出数据excel"
        @click="exportData"
      >
        <i class="fa fa-table"></i>
      </div> -->
        <div class="refresh-btns" title="刷新" @click="refresh">
          <i class="vxe-icon--refresh"></i>
        </div>
        <div class="refresh-btns" @click="showModal" title="筛选数据">
          <i class="vxe-icon--funnel"></i>
        </div>
        <div class="refresh-btns" @click="autoLine" title="换行">
          <span class="icon iconfont icon-huanhang"></span>
        </div>
      </template>

      <!-- 财务固定资产column下拉工具栏     -->
      <template #dropDown_button="{ row }">
          <slot name="dropDown" :row="row"></slot>
      </template>
    </vxe-grid>

    <!-- 自定义显示列的模块 -->
    <custom-field
      ref="xGridChidrenColumn"
      :tableColumns="tableColumns"
      @on-submited="fieldSubmited"
    ></custom-field>
  </div>
</template>
<script>
import { deepClone } from "@/utils/deepClone";
import CustomField from "@/components/custom-field";
import Sortable from "sortablejs";
import de from "element-ui/src/locale/lang/de";
export default {
  name: "CommonVxeGrid", // 通用表格组件
  components: {
    CustomField,
  },
  data() {
    return {
      showOverflow: true,
      tableToolbar: {
        // 表格工具类
        perfect: true,
        // refresh: true, // 自定义刷新方法,官方方法逻辑冗余
        zoom: true,
        custom: true,
        //print: true,
        export: true,
        slots: {
          buttons: "toolbar_buttons", // 自定义左边按钮
          tools: "refresh_btn", // 自定义右边工具栏
        },
      },
      childrenColumn: [
        // 默认列数组
        {
          type: "seq",
          width: 60,
          slots: { default: "move_row", header: "name_header" },
        },
        { field: "title", title: "列名称", editRender: { name: "input" } },
        { field: "width", title: "宽度", editRender: { name: "input" } },
        {
          field: "visible",
          title: "显示",
          slots: { default: "visible_default" },
        },
      ],
      // 选中数组
      ids: [],
    };
  },
  props: {
    cellClassName:{
      default:()=>{
        return '' ;
      }
    },
    cellStyle:{
      type:Object,
      require:false,
      default:()=>{
        return {} ;
      }
    },
    rowStyle:{
      type:Object,
      require:false,
      default:()=>{
        return {} ;
      }
    },
    // mergeCells:{
    //   type:Array,
    //   require:false,
    //   default:()=>{
    //     return [] ;
    //   }
    // },
    showFooter: {
      // 是否显示表格尾部
      type: Boolean,
      default: () => {
        return false;
      },
    },
    footerData: {
      // 尾部数据
      type: Array,
      require: true,
      default: () => {
        return [];
      },
    },
    mergeFields: {
      // 合并字段
      type: Array,
      require: true,
      default: () => {
        return [];
      },
    },

    showHeader: {
      // 是否显示表格头部
      type: Boolean,
      default: () => {
        return true;
      },
    },
    loading: {
      // 表格是否显示加载中
      type: Boolean,
      default: () => {
        return true;
      },
    },
    gridId: {
      // 自定义行数据唯一主键的字段名(行数据必须要有唯一主键,默认自动生成)
      type: String,
      default: () => {
        return "pkid";
      },
    },
    tableColumns: {
      // 表格显示列数据
      type: Array,
      require: true,
      default: [[]],
    },
    tableData: {
      // 表格数据
      type: Array,
      require: true,
      default: [],
    },
    //树的属性
    treeConfig: {
      type: Object,
      default: () => {},
    },
    isExport: {
      // 是否开启导出
      type: Boolean,
      default: () => {
        return true;
      },
    },
    // showOverflow: {
    //   // 单元格内容是隐藏显示三点代替多余内容,默认不换行false,true换行
    //   type: Boolean,
    //   default: () => {
    //     return false;
    //   },
    // },
    sortConfig: {
      type: Object,
      default: () => ({
        multiple: false,
      }),
    },
    multiple: {
      // 控制单选和多选  true单选, false多选, 默认多选
      type: Boolean,
      default: () => {
        return false;
      },
    },
  },
  created() {
    this.columnDrop();
  },
  watch: {
    tableData: {
      handler(n, o) {},
      deep: true,
      immediate: true,
    },
    tableColumns: {
      handler(n, o) {
        this.tableColumns.forEach((E) => {
          if (E.type === "radio" || E.type === "checkbox") {
            E.align = "center";
          }
          // 多选
          if (this.multiple) {
            if (E.type === "radio") {
              E.type = "checkbox";
            }
          } else {
            if (E.type === "checkbox") {
              E.type = "radio";
            }
          }
        });
      },
      deep: true,
      immediate: true,
    },
  },
  beforeDestroy() {
    if (this.sortableVxe) {
      this.sortableVxe.destroy();
    }
  },
  methods: {
    headerCellClassName({ column }) {
      return "headerColor";
    },
    getSelectedData() {
      if (this.multiple == false) {
        return this.$refs.vxe_table.getRadioRecord(false);
      }
      return this.$refs.vxe_table.getCheckboxRecords(false);
    },
    // 通用行合并函数(将相同多列数据合并为一行)
    mergeRowMethod({ row, _rowIndex, column, visibleData }) {
      const fields = this.mergeFields;
      if (fields.length == 0) {
        return;
      }
      const cellValue = row[column.property];
      if (
        cellValue != undefined &&
        cellValue != null &&
        fields.includes(column.property)
      ) {
        const prevRow = visibleData[_rowIndex - 1];
        let nextRow = visibleData[_rowIndex + 1];
        //if (prevRow && prevRow[column.property] === cellValue) {
        if (prevRow && this.checkMergeFields(row, prevRow, column.property)) {
          return { rowspan: 0, colspan: 0 };
        } else {
          let countRowspan = 1;
          //while (nextRow && nextRow[column.property] === cellValue) {
          while (nextRow && this.checkMergeFields(row, nextRow, column.property)) {
            nextRow = visibleData[++countRowspan + _rowIndex];
          }
          if (countRowspan > 1) {
            return { rowspan: countRowspan, colspan: 1 };
          }
        }
      }
    },
    //循环判断前面的列,如果值不一样的话就不合并
    checkMergeFields(row, nextRow, property) {
      var ret = true;
      for (var i = 0; i < this.mergeFields.length; i++) {
        var field = this.mergeFields[i];
        if (nextRow[field] != row[field]) {
          ret = false;
          break;
        }
        if (field == property) {
          break;
        }
      }
 
      return ret;
    },
    autoLine() {
      this.showOverflow = !this.showOverflow;
    },
    footerMethod() {
      var cols = this.$refs.vxe_table.getColumns();
      var data = [this.footerData[0].value];
      for (var col of cols) {
        if (col.visible == false || col.field == undefined) continue;
        var val = "";
        for (var dt of this.footerData) {
          if (dt.field == col.field) {
            val = dt.value;
            break;
          }
        }
        data.push(val);
      }
      // 接收二维数组
      return [data];
    },
    // 单选配置
    checkMethod() {
      return true;
    },
    // 拖动列方法
    columnDrop() {
      this.$nextTick(() => {
        const $table = this.$refs.vxe_table;
        this.sortableVxe = Sortable.create(
          $table.$el.querySelector(
            ".body--wrapper>.vxe-table--header .vxe-header--row"
          ),
          {
            handle: ".vxe-header--column:not(.col--fixed)",
            onEnd: ({ item, newIndex, oldIndex }) => {
              const { fullColumn, tableColumn } = $table.getTableColumn();
              const targetThElem = item;
              const wrapperElem = targetThElem.parentNode;
              const newColumn = fullColumn[newIndex];
              if (newColumn.fixed) {
                // 错误的移动
                if (newIndex > oldIndex) {
                  wrapperElem.insertBefore(
                    targetThElem,
                    wrapperElem.children[oldIndex]
                  );
                } else {
                  wrapperElem.insertBefore(
                    wrapperElem.children[oldIndex],
                    targetThElem
                  );
                }
                return this.$XModal.message({
                  content: "固定列不允许拖动!",
                  status: "error",
                });
              }
              // 转换真实索引
              const oldColumnIndex = $table.getColumnIndex(
                tableColumn[oldIndex]
              );
              const newColumnIndex = $table.getColumnIndex(
                tableColumn[newIndex]
              );
              // 移动到目标列
              const currRow = fullColumn.splice(oldColumnIndex, 1)[0];
              fullColumn.splice(newColumnIndex, 0, currRow);
              $table.loadColumn(fullColumn);

              //更新合计
              setTimeout(() => {
                this.$refs.vxe_table.updateFooter();
              }, 100);
            },
          }
        );
      });
    },
    // 多选事件,备用方法
    checkboxChange({ records, row }) {},
    // 点击表格row 单元格事件
    cellClick({ row }) {
      // 多选
      if (this.multiple) {
        try {
          let arr = this.$refs.vxe_table.getCheckboxRecords(true);
          this.ids = arr.map((obj) => obj[this.gridId]);
          this.$emit("on-cell-row", { ids: this.ids, row: null, records: arr });
        } catch (error) {
          console.log(error);
        }
      } else {
        // 单选
        try {
          const item = this.$refs.vxe_table.getRadioRecord();
          this.$emit("on-cell-row", {
            ids: item[this.gridId],
            row: item,
            records: null,
          });
        } catch (error) {
          console.log(error);
        }
      }
    },
    // 表格全选事件
    checkboxAll({ records }) {
      this.ids = records.map((obj) => obj[this.gridId]);
      this.$emit("on-cell-row", { ids: this.ids, row: null, records });
    },
    // 表格重新排序事件
    sortChangeEvent({ sortList }) {
      this.$emit("on-change-sort", sortList);
    },
    // 自定义服务端导出
    exportMethod({ options }) {
      const $grid = this.$refs.vxe_table;
      // 传给服务端的参数
      const exportParam = {
        filename: options.filename,
        sheetName: options.sheetName,
        isHeader: options.isHeader,
        original: options.original,
        mode: options.mode,
        pager: 1,
        ids:
          options.mode === "selected"
            ? options.data.map((item) => item.id)
            : [],
        fields: options.columns.map((column) => {
          return {
            field: column.property,
            title: column.title,
          };
        }),
      };
      this.$emit("on-export", exportParam);
    },
    // 导出数据
    // exportData() {
    //   this.$refs.vxe_table.exportData({
    //     types: ["xlsx"],
    //     modes: ["current", "selected", "all"],
    //     filename: "导出" + this.parseTime(new Date().getTime()),
    //   });
    // },
    //刷新
    refresh() {
      this.$emit("on-refresh");
    },
    // 自定义列头显示字段
    showModal() {
      this.$refs.xGridChidrenColumn.open();
    },
    //自定义列调整完成
    fieldSubmited() {
      this.$emit("on-fieldSubmited");
    },
  },
};
</script>
<style lang="scss" scoped>
/* ::v-deep .vxe-header--column.headerColor{
   background-color: #009688;
   color:white;
 }*/
</style>

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐