el-table封装

<template>
  <div :class="['md-table', noPadding ? 'no-padding' : '']" :style="tableStyle" ref="refTable" v-resize="handleResize">
    <!-- {{ defultSelectRadioIndex }}
    {{ clickRowIndex }} -->
    <action-bar
      v-if="action"
      v-bind="$attrs"
      :tableName="tableName"
      :getRowIndex="getRowIndex"
      :selectionItemsInfo="multipleSelection"
      :isReportTable="isReportTable"
      :topBtnPosition="topBtnPosition"
      :isExport="isExport"
      :exportCode="exportCode"
      :listManageCode="listManageCode"
      :menuCodePrifixListManage="menuCodePrifixListManage"
      @handlerChange="handlerChange"
      @handlerExport="handlerExport"
      ref="actionBar"
    >
      <slot name="after"></slot>
      <slot name="btn"></slot>
      <slot name="right"></slot>
    </action-bar>

    <div class="table-container">
      <el-table
        ref="elTable"
        class="tableClass"
        border
        v-bind="$attrs"
        v-on="$listeners"
        v-loading="loading || innerLoading"
        :row-key="rowKey"
        :lazy="lazy"
        :load="loadFunction"
        :tree-props="treeProps"
        :data="data"
        :row-class-name="tableRowClassName"
        :cell-style="cellStyle"
        :element-loading-text="loadingText"
        :span-method="this.merge ? this.mergeMethod : this.spanMethod"
        :height="customHeight || height"
        @row-click="handleRowClick"
        @cell-click="handleCellClick"
        @select="tableSelect"
        @select-all="tableSelectAll"
        @selection-change="handleSelectionChange"
        @header-dragend="headerDragend"
        @sort-change="handleSortChange"
        @expand-change="expandChange"
      >
        <!-- 多选框配置 -->
        <el-table-column
          v-if="isSelection"
          :reserve-selection="reserveSelection"
          type="selection"
          width="35"
          :selectable="typeof selectable === 'function' ? selectable : renderSelectable"
        >
        </el-table-column>

        <!-- 单选配置 -->
        <el-table-column v-if="isSelectRadio" width="35" show-overflow-tooltip="false">
          <template slot-scope="scope">
            <el-radio v-if="clickRowIndex === scope.$index"></el-radio>
            <el-radio v-else :value="false" :disabled="selectDisabled || scope.row.selectRadioDisabled"></el-radio>
          </template>
        </el-table-column>

        <!-- 索引配置:从 1 开始计算 -->
        <el-table-column
          :label="isCustomizeNoLable ? customizeNoLable : $t('basic.NoH')"
          v-if="showIndex"
          type="index"
          :index="indexMethod"
          :width="column.length > 0 ? customizeNoLableWidth : fullTableWidth"
        >
          <template slot-scope="scope">
            {{ (customIndexMethod && customIndexMethod(scope)) || scope.$index + 1 }}
          </template>
        </el-table-column>

        <!-- 自定义 el-table-column -->
        <template v-for="(item, index) in filterColumn">
          <el-table-column
            v-bind="item"
            v-if="item.childrenHeader"
            :label="$t(item.customLabel) || $t(item.label) || item.label"
          >
            <el-table-column
              v-for="(cItem, cIndex) in item.childrenHeader"
              v-bind="cItem"
              :key="cIndex"
              :label="$t(cItem.customLabel) || $t(cItem.label) || cItem.label"
            >
            </el-table-column>
          </el-table-column>
          <el-table-column
            v-bind="item"
            v-else
            :key="item.prop + '##' + index"
            :label="$t(item.customLabel) || $t(item.label) || item.label"
            :show-overflow-tooltip="setShowOverFlow(item)"
          >
            <template slot-scope="scope">
              <template
                v-if="
                  !item.formViewDisabled &&
                  (item.viewAlways || formViewMethod(scope, index) || scope.$index === editTableRowIndex) &&
                  !(typeof item.hidden === 'function' ? item.hidden(scope.row) : item.hidden)
                "
              >
                <slot
                  v-if="item.slotName"
                  :name="item.slotName"
                  :row="scope.row"
                  :column="item"
                  :$index="scope.$index"
                ></slot>
                <div v-else-if="item.html" v-html="renderHtml(item, scope)"></div>
                <component
                  :is="typeof item.render === 'function' ? handleRendel(item.render, scope) : item.render"
                  :scope="scope"
                  v-else-if="item.render"
                ></component>

                <mingdu-form
                  v-else-if="item.formView && Object.keys(item.formView).length > 0"
                  :form-view="cloneDeep(item.formView)"
                  class="tableForm"
                  form-table
                  ref="mdform"
                  :key="index + '#' + scope.$index"
                  :form-data="scope.row"
                  :editTableRowIndex="editTableRowIndex"
                  :table-row-index="scope.$index"
                  :table-col-index="index"
                  label-width="0"
                  :form-item-min-width="(item.formViewConfig && item.formViewConfig.formItemMinWidth) || 40"
                  v-bind="item.formViewConfig"
                  :columns="12"
                ></mingdu-form>
                <span
                  style="white-space: break-spaces !important"
                  v-else
                  v-html="renderCellHtml(item, scope)"
                  v-tableTooltip
                ></span>
              </template>
              <component
                :is="
                  typeof item.formatterRender === 'function'
                    ? handleRendel(item.formatterRender, scope)
                    : item.formatterRender
                "
                :scope="scope"
                v-else-if="item.formatterRender"
              ></component>
              <span
                style="white-space: break-spaces !important"
                v-else
                v-html="renderCellHtml(item, scope)"
                v-tableTooltip
              ></span>
              <component
                :is="typeof item.renderRight === 'function' ? handleRendel(item.renderRight, scope) : item.renderRight"
                :scope="scope"
              ></component>
            </template>
          </el-table-column>
        </template>

        <!-- data数据为空时的插槽配置 -->
        <template slot="empty">
          <template v-if="!loading">
            <template v-if="Number(emptyImageSize) > 0">
              <el-empty :description="emptyText" :image-size="Number(emptyImageSize)"></el-empty>
            </template>
            <template v-else>
              <span>{{ emptyText }}</span>
            </template>
          </template>
        </template>

        <!-- 操作列配置 -->
        <el-table-column
          v-if="isOperation && column.length > 0"
          class-name="class-name"
          :fixed="fixed"
          :label="$t('操作')"
          :showOverflowTooltip="false"
          :resizable="false"
          :width="operationWidth"
        >
          <slot name="operation" slot-scope="scope" :value="scope"></slot>
        </el-table-column>
      </el-table>
    </div>

    <!-- 分页配置 -->
    <pages
      v-model="page.page"
      v-if="pagination && isPageNum === 1"
      :page="currentPage"
      :pageSize.sync="page.limit"
      :total="totalNumber || data.length"
      v-bind="$attrs"
      v-on="$listeners"
    />

    <!-- 拖拽组 -->
    <customColumn
      ref="customColumn"
      :column="keyList"
      :tableName="tableName"
      :customListGlobalMenuCode="customListGlobalMenuCode"
    ></customColumn>
  </div>
</template>

<script>
/**
 * 基于element ui table二次封装,几乎支持原table所有的功能
 * 文档地址:https://github.liubing.me/lb-element-table/zh/
 */
import { cloneDeep } from 'lodash'
import draggable from 'vuedraggable'

import pages from '@/components/page/pages'
import { getSelectData, optionsConfigs } from '@/common/getBasicDate.js'

import page from './page'
import actionBar from './action-bar'
import customColumn from './customColumn'
import i18n from '@/lang'

export default {
  mixins: [page],
  props: {
    rowKey: {
      type: String,
      default: 'id'
    },
    lazy: {
      type: Boolean,
      default: false
    },
    loadFunction: {
      type: Function,
      default: () => ({})
    },
    indexMethod: {
      type: Function
    },
    customIndexMethod: {
      type: Function
    },
    treeProps: {
      typa: Object,
      default: () => ({})
    },
    selectable: {
      type: Function | String,
      default: () => ({})
    },
    fixed: {
      type: String | Boolean,
      default: 'right'
    },
    selectionItems: {
      type: Array,
      default: () => []
    },
    column: {
      type: Array,
      default: (_) => []
    },
    data: Array,
    spanMethod: Function,
    expandChange: Function,
    exportCode: '', // 导出按钮 权限编码
    listManageCode: '', // 列表管理按钮 权限编码
    menuCodePrifixListManage: '', //  列表管理权限自定义前缀, 有了该值不取路由名
    cellStyle: {
      type: Object | Function,
      default: () => {
        'color: inherit'
      }
    },
    //自定义行class
    setTableRowClassName: {
      type: Function
    },
    pagination: {
      // 是否分页
      type: Boolean,
      default: true
    },
    total: {
      type: Number,
      default: 0
    },
    showIndex: {
      // 是否显示序号列
      type: Boolean,
      default: true
    },
    action: {
      // 是否操作菜单
      type: Boolean,
      default: true
    },
    paginationTop: {
      type: String,
      default: '15px'
    },
    paginationAlign: {
      type: String,
      default: 'right'
    },
    merge: Array,
    isHeight: {
      // 是否自动设置表格高度
      type: Boolean,
      default: true
    },
    reserveSelection: {
      // 是否缓存选中数据
      type: Boolean,
      default: false
    },
    needClearSelection: {
      // 是否需要清空多选数据
      type: Boolean,
      default: true
    },
    isOperation: {
      // 是否操作列
      type: Boolean,
      default: false
    },
    operationWidth: {
      // 操作列宽度
      type: String | Number,
      default: 100
    },
    isSelection: {
      // 是否选择
      type: Boolean,
      default: true
    },
    isRowclick: {
      // 是否可以选中单行
      type: Boolean,
      default: true
    },
    height: {
      // 表格高度
      type: Number / String,
      default: '100%'
    },
    isPageNum: {
      type: Number,
      default: 1
    },
    tableName: String,
    highlightCurrentRow: {
      type: Boolean,
      default: true
    },
    isSelectStyle: {
      type: Boolean,
      default: true
    },
    isSelectOnlyOne: {
      // 是否单选
      type: Boolean,
      default: false
    },
    selectForm: {
      // 查询条件
      type: Object,
      default: () => {
        return {}
      }
    },
    isReportTable: {
      // 是否打表格
      type: Boolean,
      default: false
    },
    topBtnPosition: {
      // 表格上方button的位置,left/right,默认展示在右边
      type: String,
      default: 'right'
    },
    // 行内编辑时正在编辑的行
    editTableRowIndex: {
      type: Number,
      default: -1
    },
    /**
     * 控制自定义表单类单元格的方法,返回true显示当前单元格
     *@param {paraName}
     */
    formViewShowMethod: {
      type: Function
      // default: () => {
      //   return () => {
      //     return true
      //   }
      // }
    },
    loading: {
      // 是否加载中
      type: Boolean,
      default: false
    },
    isCustomizeNoLable: {
      // 是否自定义序号lable
      type: Boolean,
      default: false
    },
    loadingText: {
      // 加载中的文案
      type: String,
      default: i18n.t('拼命加载中') + '...'
    },
    emptyText: {
      // 数据为空时的文案
      type: String,
      default: i18n.t('暂无数据')
    },
    emptyTextColor: {
      type: String,
      default: ''
    },
    customizeNoLable: {
      type: String,
      default: ''
    },
    customizeNoLableWidth: {
      type: String,
      default: '55'
    },
    emptyImageSize: {
      type: [Number, String],
      default: 80
    },
    // 是否设置padding样式为0px,默认不设置
    noPadding: {
      type: Boolean,
      default: false
    },
    // 是否显示单选列
    isSelectRadio: {
      type: Boolean,
      default: false
    },
    //单选radio是否能点击取消选中
    canSelectRadioCancel: {
      type: Boolean,
      default: false
    },
    defultSelectRadioIndex: {
      // 默认选择的单选行
      type: Number,
      default: 0
    },
    // 单选是否禁止选择
    selectDisabled: {
      type: Boolean,
      default: false
    },
    isExport: {
      type: Boolean,
      default: false
    },
    pageParams: {
      type: Object,
      default: () => ({})
    },
    // 是否选中第一行数据
    defaultSelectedFirstRow: {
      type: Boolean,
      default: true
    },
    // 表格来源于哪个组件页面
    from: {
      type: String,
      default: ''
    },
    // 单元格默认显示的文字
    defaultText: {
      type: String,
      default: 'N/A'
    },
    clickRowToSelect: {
      //是否可以在点击行的时候选中行
      type: Boolean,
      default: true
    },
    autoRowClick: {
      //是否data变化时默认执行选中首行rowClick方法
      type: Boolean,
      default: true
    }
  },
  model: {
    prop: 'selectionItems',
    event: 'changeSelection'
  },
  components: {
    actionBar,
    pages,
    draggable,
    customColumn
  },
  data() {
    return {
      customHeight: 0,
      mergeLine: {},
      mergeIndex: {},
      targetRow: {},
      selectRow: {},
      getRowIndex: '',
      enabled: true,
      totalNumber: this.total,
      multipleSelection: [],
      innerLoading: false,
      groupCodeData: {},
      clickRowIndex: -1,
      fullTableWidth: '100%',
      timer: null
    }
  },
  beforeDestroy() {
    if (this.timer) {
      clearTimeout(this.timer)
    }
  },
  // async created() {
  //   await this.setTableMaxWidth()
  // },
  async created() {
    await this.handelTableColumngGroupCode()
    this.getMergeArr(this.data, this.merge)

    this.clickRowIndex = this.$props.defaultSelectedFirstRow ? 0 : -1
  },
  activated() {
    this.doLayout()
    this.handelTableColumngGroupCode()
  },
  deactivated() {
    if (this.selectionItems && this.selectionItems.length > 1) {
      this.clearSelection()
    }
  },
  watch: {
    total: {
      handler(nVal) {
        this.totalNumber = nVal
      },
      immediate: true
    },
    merge() {
      this.getMergeArr(this.data, this.merge)
    },
    dataLength() {
      this.getMergeArr(this.data, this.merge)
      this.doLayout()
    },
    column() {
      this.doLayout()
    },
    defultSelectRadioIndex: {
      handler(nVal) {
        if (this.data) {
          this.clickRowIndex = nVal
        }
      },
      deep: true,
      immediate: true
    },
    clickRowIndex: {
      handler(nVal) {
        // console.log('watch =>', nVal, this.selectionItems, this.data[nVal])
        // 设置单选时的默认选中数据
        if (this.isSelectRadio && nVal === 0 && this.data.length > 0) {
          // this.selectionItems.push(this.data[nVal])
          this.chooseSingleItem(this.data, this.data[nVal])
        }
      },
      deep: true,
      immediate: true
    },
    // 监听 data 数据,设置已选中数据的状态
    data: {
      handler(nVal) {
        // console.log('watch data =>', this.from, nVal, this.selectionItems)
        if (this.$refs.elTable) {
          this.$nextTick(() => {
            const selected = cloneDeep(this.selectionItems)
            if (Array.isArray(nVal) && Array.isArray(selected) && selected.length > 0) {
              const selectedKeys = selected.map((e) => e[this.rowKey])
              nVal.forEach((item) => {
                // 判断列表数据是否能被选中,如果被选中了但是这条数据已被设置为不可选中,则将此数据取消选中
                const key = item[this.rowKey]
                if (selectedKeys.includes(key) && item.selectable !== false) {
                  this.$refs.elTable.toggleRowSelection(item, true)
                } else {
                  this.$refs.elTable.toggleRowSelection(item, false)
                }
              })
            }

            // 设置单选时的选中数据
            if (this.autoRowClick && this.isSelectRadio && nVal.length > 0) {
              this.chooseSingleItem(this.data, this.data[this.clickRowIndex])
              this.$emit('rowClick', cloneDeep(this.data[this.clickRowIndex]))
            }
          })
        }
      },
      deep: true,
      immediate: true
    },
    // 监听 selectionItems 数据,设置已选中数据的状态
    selectionItems: {
      handler(nVal) {
        // console.log('watch selectionItems =>', this.from, this.data, nVal)
        this.$nextTick(() => {
          if (this.$refs.elTable) {
            const array = this.data
            if (Array.isArray(nVal) && Array.isArray(array) && array.length > 0) {
              const selectedKeys = nVal.map((e) => e[this.rowKey])
              array.forEach((item) => {
                // 判断列表数据是否能被选中,如果被选中了但是这条数据已被设置为不可选中,则将此数据取消选中
                const key = item[this.rowKey]
                if (selectedKeys.includes(key) && item.selectable !== false) {
                  this.$refs.elTable.toggleRowSelection(item, true)
                } else {
                  this.$refs.elTable.toggleRowSelection(item, false)
                }
              })
            }
          }
        })
      },
      deep: true,
      immediate: true
    },
    pageParams: {
      handler(nVal) {
        // console.log('watch pageParams =>', nVal)
        // 同步更新分页信息
        this.page.page = nVal.startPagePos ?? 1
        this.page.limit = nVal.limit ?? 20
      },
      deep: true,
      immediate: true
    }
  },
  computed: {
    tableStyle() {
      let value = ' 1fr '

      // 判断是否开启 action
      if (this.action) {
        value = 'auto' + value
      }
      // 判断是否开启 pagination
      if (this.pagination) {
        value = value + 'auto'
      }

      return {
        'grid-template-rows': value
      }
    },
    customListGlobalMenuCode() {
      //列表自定义全局操作权限menuCode,和后端统一规则,tableName取的当前路由name
      if (this.$attrs.isListManage && this.tableName) {
        const tableName =
          this.tableName.indexOf('-') === -1 ? this.tableName : this.tableName.substring(0, this.tableName.indexOf('-'))
        return tableName + 'GlobalList'
      } else {
        return ''
      }
    },
    currentPage() {
      return this.page.page
    },
    keyList() {
      let tableName = this.tableName
      if (tableName && this.tableConfig[tableName] && this.tableConfig[tableName].length > 0) {
        const saveColumn = this.tableConfig[tableName]
        const column = this.$deepCopy(this.column)
        let newArr = []
        column.forEach((item, index) => {
          let tarIndex = saveColumn.findIndex((p) => p.prop === item.prop)
          let tar = saveColumn.find((p) => p.prop === item.prop)
          if (tarIndex > -1) {
            tar.sortIndex = tarIndex
            tar.label = item.label
            for (let i in item) {
              if (!tar.hasOwnProperty(i)) {
                tar[i] = item[i]
              }
              //列表中有formView使用代码中的formView配置,不用自定义列表的formView
              if (i === 'formView') {
                tar[i] = item[i]
              }
            }
            newArr.push(tar)
          } else {
            item.sortIndex = 9999
            item.width = null
            if (!item.hasOwnProperty('display')) {
              item.display = 'Y'
            }
            if (!item.hasOwnProperty('adaption')) {
              item.adaption = 'Y'
            }
            newArr.push(item)
          }
        })
        // 按照保存的排序
        return this.sortFunc(newArr, 'sortIndex')
      } else {
        const column = this.$deepCopy(this.column)
        return column.map((i) => {
          if (!i.width && !i.minWidth && i.label?.length > 4) {
            i.minWidth = i.label.length * 15
          }
          return i
        })
      }
    },
    filterColumn() {
      //避免列拖动顺序后无法改变宽度
      this.keyList.forEach((i, k) => {
        i.resizable = true
        if (k === this.keyList.length - 1) {
          i.resizable = false
        }
      })
      // this.keyList[this.keyList.length - 1].resizable = false
      return this.keyList.filter((item) => (item.display === 'Y' || !item.display) && !item.hiddenColumn)
    },
    /**
     * 来自 Karen 的帅气注释 2022-06-01 15:33:17
     * 获取展示列
     */
    showKeys() {
      if (this.tableName && this.tableConfig[this.tableName]) {
        return this.tableConfig[this.tableName].filter((item) => item.display === 'Y' || !item.display)
      } else {
        return []
      }
    },
    tableConfig() {
      return this.$store?.state?.tableConfig ?? {}
    },
    dataLength() {
      return (this.data && this.data.length) || 0
    },
    theme() {
      return this.$store.state.theme
    }
  },
  methods: {
    cloneDeep,
    clearTableSort() {
      this.$refs.elTable.clearSort()
    },
    async handleResize() {
      if (this.column.length === 0) {
        await this.setTableMaxWidth()
      }
    },
    setTableMaxWidth() {
      const refTable = this.$refs.refTable
      if (refTable) {
        const rect = refTable.getBoundingClientRect()
        const width = rect && rect.width ? rect.width : 1000
        const paddingWidth = 20 // table padding width
        const checkboxWitdh = 35 // checkbox column width
        const borderWidth = 2 // border width
        this.fullTableWidth = width - paddingWidth - checkboxWitdh - borderWidth + 'px'
      }
    },
    // 排序
    sortFunc(array, key) {
      return array.sort(function (a, b) {
        let x = key ? a[key] : a
        let y = key ? b[key] : b
        return x < y ? -1 : x > y ? 1 : 0
      })
    },
    renderText(param) {
      if (param === undefined || param === null || param === '') {
        return this.defaultText
      }

      return param
    },
    /**
     * 渲染单元格内容
     * @param { Object } item
     * @param { Object } scope
     */
    renderHtml(item, scope) {
      const result = typeof item.html === 'function' ? item.html(scope) : item.html
      return this.renderText(result)
    },
    /**
     * 渲染单元格内容
     * @param { Object } item
     * @param { Object } scope
     */
    renderCellHtml(item, scope) {
      const result =
        item.formViewFormatter && typeof item.formViewFormatter === 'function'
          ? item.formViewFormatter(scope.row[item.prop], scope.row, item.formView)
          : item.formatter
          ? item.formatter(scope.row)
          : this.changeHandler(scope.row[item.prop])
      return this.renderText(result)
    },
    /**
     * 更新selectionItems数据值
     * @param { Array } array 当前表格的数据
     * @param { Object } item 选择后需要更新的数据项
     */
    chooseSingleItem(array = [], item = {}) {
      this.selectionItems.splice(0, array.length)
      this.$set(this.selectionItems, 0, item)
    },
    handleSelectionChange(selection) {
      // console.log(111, this.from, selection)
      this.multipleSelection = this.$deepCopy(selection)
      this.$emit('changeSelection', selection)
    },
    // 渲染当前行是否能被选中
    renderSelectable(row, index) {
      // console.log('render Selectable =>', index, row, row.selectable)
      return row && row.selectable === false ? false : true
    },
    // 打开innerLoading
    opLoading() {
      if (!this.isOpenLoading) {
        return
      }
      if (!this.innerLoading) {
        this.innerLoading = true
      }
    },
    // 关闭innerLoading
    closeLoading() {
      this.innerLoading = false
    },
    initIndex(index = 0) {
      // const index = this.clickRowIndex
      // console.log('initIndex =>', index)

      this.getRowIndex = ''
      this.targetRow = {}
      this.clickRowIndex = index
    },
    /**
     * 初始化表格数据:设置是否默认选中第一行数据
     */
    initTableData(flag = false) {
      this.$nextTick(() => {
        // console.log('init tableData =>', this.from, flag, this.defaultSelectedFirstRow, this.data)
        if (flag) {
          if (this.data.length > 0) {
            const item = this.data[0]

            this.targetRow = item
            this.clickRowIndex = 0
            this.$refs.elTable.toggleRowSelection(item, true)
          } else {
            this.clickRowIndex = -1
            this.getRowIndex = ''
            this.targetRow = {}
          }
        } else {
          this.clickRowIndex = -1
          this.getRowIndex = ''
          this.targetRow = {}
        }
      })
    },
    setPage() {
      this.page.page -= 1
    },
    initPage() {
      this.page.page = 1
    },
    setTotal(total) {
      this.totalNumber = total
    },
    toggleSelection(rows) {
      if (rows) {
        rows.forEach((row) => {
          this.$refs.elTable && this.$refs.elTable?.toggleRowSelection(row)
        })
      } else {
        this.$refs.elTable && this.$refs.elTable?.clearSelection()
      }
    },
    /**
     * 来自 Karen 的帅气注释 2022-05-25 13:20:16
     * 单选
     */
    tableSelect(selection, row) {
      console.log('%c 第878行', 'color: red; font-size: 2em')
      console.log(selection)
      // console.log(222, this.from, selection, row)
      row.className = 'normal'
      // if (!this.isSelectOnlyOne) {
      if (selection.length !== 1) {
        this.$emit('rowClick', {})
      }
      if (selection.length === 1) {
        this.$emit('rowClick', cloneDeep(selection[0]))
      }
      // }
      selection.forEach((item) => {
        item.className = 'tableSelectedRowBgColor'
      })
      // this.$emit('changeSelection', selection)
      this.$emit('tableSelect', selection, row)
    },
    /**
     * 来自 Karen 的帅气注释 2022-06-24 14:06:12
     *
     */
    tableSelectAll(selection) {
      this.$emit('rowClick', {})
      if (!selection.length) {
        this.$refs.elTable.data.forEach((item) => {
          item.className = 'normal'
        })
      } else {
        selection.forEach((item) => {
          item.className = 'tableSelectedRowBgColor'
        })
      }
      this.$emit('tableSelectAll', selection)
    },
    tableRowClassName({ row, rowIndex }) {
      if (this.setTableRowClassName) {
        return this.setTableRowClassName({ row, rowIndex })
      }
      // 返回选中样式
      return row.className
    },
    handleRowClick(row) {
      this.resetPickStyle()
      // console.log('diapatch row Click =>', row)
      if ((!this.isSelection && !this.isSelectRadio) || !this.isRowclick) {
        return
      }
      console.log('this.needClearSelection', this.needClearSelection)

      if (!this.isSelectRadio) {
        this.needClearSelection && this.clearSelection()
        if (this.selectable && typeof this.selectable === 'function') {
          //当前行可选
          if (
            this.clickRowToSelect &&
            this.selectable(
              row,
              this.data.findIndex((i) => i == row)
            )
          ) {
            this.$refs.elTable.toggleRowSelection(row)
          }
        } else {
          if (this.clickRowToSelect) {
            this.$refs.elTable.toggleRowSelection(row)
          }
        }
      }

      this.targetRow = row
      this.getRowIndex = row.rowIndex
      let cloneRow = cloneDeep(row)
      if (!this.selectDisabled && !row.selectRadioDisabled) {
        if (this.canSelectRadioCancel) {
          if (this.clickRowIndex === this.data.findIndex((i) => i == row)) {
            //重复选择选中数据则取消,不用setTimeout会出现点击同一条数据的radio时,选中或者取消状态无法更新
            this.timer = setTimeout(() => {
              this.clickRowIndex = -1
            }, 0)
            cloneRow = {}
          } else {
            this.timer = setTimeout(() => {
              this.clickRowIndex = this.data.findIndex((i) => i == row)
            }, 0)
          }
        } else {
          this.clickRowIndex = this.data.findIndex((i) => i == row)
        }
        // console.log('%c 第778行', 'color:red;font-size:2em')
        // console.log(this.clickRowIndex)
      }
      this.$emit('rowClick', cloneRow)
      if (this.clickRowToSelect) {
        row.className = 'tableSelectedRowBgColor'

        // 修改于 2023年2月27日17:15:21
        // let ids = this.selectionItems.map((item) => item.id)
        // let lists = this.$deepCopy(this.selectionItems)
        // if (ids.indexOf(row.id) === -1) {
        //   lists.push(row)
        // }
        this.chooseSingleItem(this.data, row) // 设置selectionItems的值
      }
    },
    handleCellClick(row, column, cell, event) {
      this.$emit('cellClick', row, column, cell, event)
    },
    changeTableSort({ column, order, prop }) {
      if (order === null) {
      } else {
      }
    },
    resetPickStyle() {
      this.$refs.elTable.data.forEach((item) => {
        item.className = 'normal'
      })
    },
    clearSelection() {
      console.log('clear Selection')

      this.resetPickStyle()
      this.$emit('changeSelection', [])
      this.$refs.elTable && this.$refs.elTable.clearSelection()
    },
    toggleRowSelection(row, selected) {
      this.$refs.elTable && this.$refs.elTable.toggleRowSelection(row, selected)
    },
    toggleAllSelection() {
      this.$refs.elTable && this.$refs.elTable.toggleAllSelection()
    },
    toggleRowExpansion(row, expanded) {
      this.$refs.elTable && this.$refs.elTable.toggleRowExpansion(row, expanded)
    },
    setCurrentRow(row, value) {
      this.$nextTick(() => {
        if (row) {
          let tar = this.$refs.elTable.data.find((item) => item.id === row.id)
          if (tar) {
            // 选中
            this.$refs.elTable.data.forEach((item) => {
              if (item.id === tar) {
                item.className = 'tableSelectedRowBgColor'
                this.$refs.elTable.toggleRowSelection(item)
              }
            })
          }
        }
        if (row) {
          this.$refs.elTable.data.forEach((item) => {
            if (item.id === row.id) {
              item.className = 'tableSelectedRowBgColor'
              this.$refs.elTable.toggleRowSelection(item, value)
            }
          })
        } else {
        }
      })
    },
    clearSort() {
      this.$refs.elTable && this.$refs.elTable.clearSort()
    },
    clearFilter(columnKey) {
      this.$refs.elTable && this.$refs.elTable.clearFilter(columnKey)
    },
    headerDragend() {
      // this.$refs.elTable && this.$refs.elTable.doLayout()
      this.doLayout()
    },
    handleSortChange({ column, prop, order }) {
      // console.log('column, prop, order', column, prop, order)
      let label = prop
      if (prop.indexOf('#') >= 0 || prop.indexOf('_') >= 0) {
        label = prop.split('#')[1] || prop.split('_')[1] || ''
      }
      this.$emit('sortChange', order ? label + ':' + order.replace('ending', '') : '')
    },
    doLayout() {
      this.$nextTick(() => {
        this.$refs.elTable && this.$refs.elTable.doLayout()
      })
    },
    sort(prop, order) {
      this.$refs.elTable && this.$refs.elTable.sort(prop, order)
    },
    paginationCurrentChange(val) {
      this.$emit('p-current-change', val)
    },
    getMergeArr(tableData, merge) {
      if (!merge) return
      this.mergeLine = {}
      this.mergeIndex = {}
      merge.forEach((item, k) => {
        tableData.forEach((data, i) => {
          if (i === 0) {
            this.mergeIndex[item] = this.mergeIndex[item] || []
            this.mergeIndex[item].push(1)
            this.mergeLine[item] = 0
          } else {
            if (data[item] === tableData[i - 1][item]) {
              this.mergeIndex[item][this.mergeLine[item]] += 1
              this.mergeIndex[item].push(0)
            } else {
              this.mergeIndex[item].push(1)
              this.mergeLine[item] = i
            }
          }
        })
      })
    },
    mergeMethod({ row, column, rowIndex, columnIndex }) {
      const index = this.merge.indexOf(column.property)
      if (index > -1) {
        const _row = this.mergeIndex[this.merge[index]][rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
    },
    handlerChange(name) {
      if (name === 'config') {
        this.$refs.customColumn.isShow = true
      } else {
        this.$emit('handlerChange', name, this.multipleSelection)
      }
    },
    handlerExport(exportForm) {
      this.$emit('reportClick')
    },
    dataURLtoBlob(base64Str) {
      let bstr = atob(base64Str),
        n = bstr.length,
        u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      // 下载的是excel格式的文件
      return new Blob([u8arr], { type: 'application/vnd.ms-excel' })
    },
    findSelectForm(vm) {
      if (vm.selectForm) {
        return vm.selectForm
      } else {
        return this.findSelectForm(vm.$parent)
      }
    },
    findRefs(vm, refName) {
      if (vm.$refs[refName]) {
        return vm.$refs[refName]
      } else {
        return this.findRefs(vm.$parent, refName)
      }
    },
    //
    /**
     * 转义< 防止v-html解析不出来用户输入的内容
     */
    changeHandler(val) {
      if (typeof val === 'string') {
        return val?.replace(/[<]/g, '&lt')
      } else {
        return val
      }
    },
    /**
     * 表单校验
     *@param {paraName}
     */
    async formValidate() {
      let ref = this.$refs.mdform
      let allCalibrationCompleted = true // 是否全部校验成功
      for (let i in ref) {
        ref[i].$refs.elform.validate((valid) => {
          if (valid) {
            // console.log('success submit!!')
          } else {
            allCalibrationCompleted = false
            // console.log('error submit!!')
            return false
          }
        })
      }
      return allCalibrationCompleted
    },
    formViewMethod(scope, columnIndex) {
      if (this.formViewShowMethod && typeof this.formViewShowMethod === 'function') {
        return this.formViewShowMethod({
          row: scope.row,
          column: scope.column,
          rowIndex: scope.$index,
          columnIndex
        })
      }
      return true
    },
    /**
     * 重载列配置里面的render函数
     *@param {paraName}
     */
    handleRendel(renderFunc, scope) {
      let cel = this.$createElement
      return {
        render: () => renderFunc(cel, scope)
      }
    },
    // 解析groupcode
    async handelTableColumngGroupCode() {
      // console.log('%c 第726行', 'color:red;font-size:2em')
      // console.log(this.column)

      for (let i of this.column) {
        if (i && i.groupCode && i.prop && !i.formatter) {
          if (i.groupCode in optionsConfigs) {
            let options = this.groupCodeData[i.groupCode]
            if (!options) {
              options = await getSelectData(i.groupCode, i.params)
              this.groupCodeData[i.groupCode] = options
            }
            this.$set(i, 'formatter', (row, column, cellValue, index) => {
              let v = (row && row[i.prop]) ?? ''
              return this.handleValue(i.groupCode, v)
            })
          } else {
            // 字典类型的后端转译
            this.$set(i, 'formatter', (row, column, cellValue, index) => {
              return (row && row[i.prop + 'Desc']) ?? row[i.prop] ?? ''
            })
          }
        }

        if (i && i.linkSetField && !i.formatter) {
          // 关联的显示字段
          this.$set(i, 'formatter', (row, column, cellValue, index) => {
            return (row && row[i.linkSetField]) ?? row[i.prop] ?? ''
          })
        }
      }
      // console.log('this.column', this.column);
    },
    handleValue(groupCode, value) {
      if (typeof value === 'string' && value.includes(',')) {
        let arr = value.split(',')
        return arr
          .map((v) => {
            return this.groupCodeData[groupCode]?.find((i) => i.value == v)?.label ?? v
          })
          .filter((i) => !!i)
          .join(',')
      } else {
        return this.groupCodeData[groupCode]?.find((i) => i.value == value)?.label ?? value
      }
    },
    setShowOverFlow(column) {
      // console.log('column', column)
      let showOverFlow = true
      if (column.formView) {
        //拿到formView的第一个属性
        const firstProperty = Object.keys(column.formView)[0]
        const firstPropertyValue = column.formView[firstProperty]
        if (firstPropertyValue.itemtype === 'Checkbox' || column?.viewAlways) {
          //组件不需要showOverFlow
          showOverFlow = false
        }
      }
      if (column.hasOwnProperty('showOverflowTooltip') && column.showOverflowTooltip === false) {
        showOverFlow = false
      }
      if (this.editTableRowIndex !== -1) {
        showOverFlow = false
      }
      return showOverFlow
    }
  }
}
</script>

<style lang="scss" scoped>
::v-deep .el-empty__description {
  margin-top: 0;
  p {
    font-size: 12px;
  }
}
.md-table {
  &.no-padding {
    padding: 0 !important;
  }
  width: 100%;
  padding: 10px;
  height: 100%;
  // display: flex;
  // flex-direction: column;
  display: grid;
  grid-template-rows: auto;
  /deep/ .el-table--mini .el-table__cell {
    padding: 2px 0;
  }

  .table-container {
    width: 100%;
    height: 100%;
    overflow: hidden;
  }
}
.customClass thead {
  tr {
    .el-checkbox {
      display: none !important;
    }
  }
}

.class-name {
  background: #ffffff;
}

*::-webkit-scrollbar {
  width: 8px;
  height: 8px;
  background-color: transparent;
}

/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
*::-webkit-scrollbar-track {
  background-color: #fff;
}

/*定义滚动条轨道 内阴影+圆角*/
*::-webkit-scrollbar-thumb {
  background-color: rgba(170, 179, 192, 0.6);
  border-radius: 10px;
}

/*定义滑块 内阴影+圆角*/
/*.scrollbarHide::-webkit-scrollbar{display: none}*/
/*.scrollbarShow::-webkit-scrollbar{display: block}*/
.tableSelectedRowBgColor td {
  /*background-color: var(--theme_item_color)!important;*/
  background-color: #aab3c0 !important;
  /*color: #ffffff!important;*/
  /*border: none!important;*/
}

.tableClass {
  ::v-deep .el-table__fixed {
    height: 100% !important; //设置高优先,以覆盖内联样式
  }
  ::v-deep .el-table__fixed-right {
    height: 100% !important; //设置高优先,以覆盖内联样式
  }
  // ::v-deep .el-table__body {
  //   width: 100% !important;
  // }
}

::v-deep .tableForm {
  .el-form-item .el-form-item__label {
    padding: 0px;
  }
  .el-input--small .el-input__inner {
    height: 26px;
    line-height: 26px;
    padding: 0 2px;
  }
  .el-form-item__error {
    position: sticky;
  }
}

::v-deep .el-loading-spinner .path {
  stroke: #909399 !important;
}
::v-deep .el-loading-text {
  color: #909399 !important;
}

::v-deep .el-table {
  //解决操作列覆盖了下方滚动条,无法进行点击或拖动
  .el-table__fixed-right {
    // height: auto !important; // 此处的important表示优先于element.style
    bottom: 17px; // 改为自动高度后,设置与父容器的底部距离,则高度会动态改变
  }
  .el-table__body-wrapper.is-scrolling-none ~ .el-table__fixed-right,
  .el-table__body-wrapper.is-scrolling-none ~ .el-table__fixed {
    height: 100% !important;
    box-shadow: none !important;
  }
}
</style>

posted @ 2024-09-27 16:02  一bottle陈  阅读(22)  评论(0编辑  收藏  举报