封装了一个table组件(多功能)

199 阅读3分钟
<template>
	<div id="puilceTable">
		<el-form ref="formDataRef" :model="tableFormData" :rules="tableFormData.rule">
			<el-table v-if="refreshTable" ref="multipleTable"
				v-loading="localCorptable.loading" :height="localCorptable.height"
				:data="tableFormData.tableData"
				:stripe="localCorptable.style && localCorptable.style.stripe ? true : false"
				:row-key="localCorptable.rowKey"
				:default-expand-all="localCorptable.defaultExpandAll?true:false"
				:tree-props="localCorptable.treeProps?localCorptable.treeProps:{children: 'children', hasChildren: 'hasChildren'}"
				:lazy="localCorptable.lazy"
				:load="tableLoad"
				:empty-text="localCorptable.emptyText ? localCorptable.emptyText : '暂无数据'"
				:header-cell-style="localCorptable.style && localCorptable.style.heardeStyle ? localCorptable.style.heardeStyle : hStyle"
				:cell-style="localCorptable.style && localCorptable.style.cellStyle ? localCorptable.style.cellStyle : cStyle"
				@selection-change="handleSelectionChange($event, localCorptable.selection ? (localCorptable.selection === 'more' ? '1' : '0') : '0')"
				@select="selectRow"
				@select-all="selectAllRow"
			>
				<!-- 多选框 -->
				<el-table-column v-if="localCorptable.isselection" type="selection" :reserve-selection="localCorptable.reserve ? localCorptable.reserve : false" />
				<!-- 序号 -->
				<el-table-column v-if="localCorptable.sNumber ? localCorptable.sNumber : false" label="序号" width="50">
					<template slot-scope="scope">
						{{ localCorptable.pageObj ? (localCorptable.pageObj.current - 1) * localCorptable.pageObj.size + scope.$index + 1 : scope.$index + 1 }}
					</template>
				</el-table-column>
				<template v-for="(item, itemIndex) in localCorptable.header">
					<el-table-column
						v-if="item.formatter"
						:key="`formatter-${itemIndex}`"
						:formatter="item.formatter"
						:label="item.name"
						:min-width="item.width"
						:prop="item.field + tableFormData.tableData[item.field]"
						resizable
						:align="item.align ? item.align : 'center'"
						:show-overflow-tooltip="item.showOverflowTooltip==false?false:true"
						:fixed="item.fixed"
					/>

					<el-table-column
						v-else
						:key="`normal-${itemIndex}`"
						:label="item.name"
						:min-width="item.width"
						:prop="item.field + tableFormData.tableData[item.field]"
						resizable
						:align="item.align ? item.align: 'center'"
						:show-overflow-tooltip="item.showOverflowTooltip==false?false:true"
						:fixed="item.fixed"
					>
						<template v-if="item.headerSlot" slot="header">
							<slot :name="item.headerSlot_name" />
						</template>
						<template slot-scope="scope">
							<!-- 输入框 -->
							<el-form-item v-if="item.type == 'input' || item.type == 'inputNumber' || item.type == 'select'" :prop="'tableData.' + scope.$index + '.' + item.field" :rules="tableFormData.rule[item.field]">
								<el-input v-if="item.type == 'input'" v-model.trim="scope.row[item.field]" type="text" :placeholder="item.placeholder ? item.placeholder : '请输入' + item.name" :disabled="item.isDis" @input="inputChange($event, scope.row)">
									<template v-if="item.sonType && item.sonType.template">
										<div v-for="(i, j) in item.sonType.template" :key="j" :slot="i.slot">
											<span v-if="i.sonTypeunit">{{ scope.row[i.sonTypeunit] }}</span>
											<span v-else>{{ i.name }}</span>
										</div>
									</template>
									<el-select
										v-if="item.sonType.select"
										:slot="item.select.slot ? item.select.slot : 'append'"
										v-model="formdataObj[item.select.field]"
										:min="item.min || 0"
										:max="item.max || ''"
										filterable
										:multiple="item.select.mult"
										:placeholder="item.select.placeholder ? item.select.placeholder : '请选择' + item.select.name"
										:disabled="item.select.isDis"
										@change="SelectChange($event, item.select.field)"
									>
										<el-option v-for="(sItem, Sindex) in item.select.option" :key="Sindex" :label="sItem[item.select.label ? item.select.label : 'name']" :value="sItem[item.select.value ? item.select.value : 'code']" :disabled="sItem.isDis" /> </el-select
									></el-input>

								<el-input v-if="item.type == 'inputNumber'" v-model.trim="scope.row[item.field]" type="number" :placeholder="item.placeholder ? item.placeholder : '请输入' + item.name" :disabled="item.isDis" @input="inputChange($event, scope.row)">
									<template v-if="item.sonType && item.sonType.template">
										<div v-for="(i, j) in item.sonType.template" :key="j" :slot="i.slot">
											<span v-if="i.sonTypeunit">{{ scope.row[i.sonTypeunit] }}</span>
											<span v-else>{{ i.name }}</span>
										</div>
									</template>
									<el-select
										v-if="item.sonType && item.sonType.select"
										:slot="item.select.slot ? item.select.slot : 'append'"
										v-model="formdataObj[item.select.field]"
										:min="item.min || 0"
										:max="item.max || ''"
										filterable
										:multiple="item.select.mult"
										:placeholder="item.select.placeholder ? item.select.placeholder : '请选择' + item.select.name"
										:disabled="item.select.isDis"
										@change="SelectChange($event, item.select.field)"
									>
										<el-option v-for="(sItem, Sindex) in item.select.option" :key="Sindex" :label="sItem[item.select.label ? item.select.label : 'name']" :value="sItem[item.select.value ? item.select.value : 'code']" :disabled="sItem.isDis" /> </el-select
									></el-input>
								<!-- 下拉框 -->
								<el-select v-if="item.type == 'select'" v-model="scope.row[item.field]" filterable :disabled="item.isDis" @change="SelectChange(scope.row, item.field)">
									<el-option v-for="(sItem, Sindex) in scope.row[item.option]" :key="Sindex" :label="sItem[item.label ? item.label : 'name']" :value="sItem[item.value ? item.value : 'code']" :disabled="sItem.isDis" />
								</el-select>
							</el-form-item>
							<!-- 文字 -->
							<span v-if="!item.type && item.type != 'button'">{{ (scope.row[item.field]||scope.row[item.field]==0) ? (typeof scope.row[item.field] == 'object' ? scope.row[item.field].text : scope.row[item.field]) : '-' }}</span>
							<!-- 文字区别展示(增加样式) -->
							<span v-if="item.type && item.type == 'style'">
								<span :style="scope.row[item.field].style">{{ scope.row[item.field] instanceof Object ? scope.row[item.field].text : scope.row[item.field] }}</span>
							</span>
							<!-- tag -->
							<span v-if=" item.type == 'tag'">
								<el-tag :type="item.tagType" :style="scope.row[item.field].style">{{ scope.row[item.field] }}</el-tag>
							</span>
							<!-- 查看 -->
							<span v-if="item.type == 'btnText'" class="buttonClick textGrColor" @click="childByValue(scope.row, item.field)">{{ scope.row[item.field] != '' && scope.row[item.field] != null ? '点击查看' : '' }}</span>
							<!-- 是否必选必填(限制性展示) -->
							<span v-if="item.type == 'required'">
								<span :style="colorRequired">{{ scope.row.isRequired ? (scope.row.isRequired === true ? '(*)' : scope.row.isRequired) : '' }}</span>
								{{ scope.row[item.field] }}
							</span>
							<!-- 按钮 -->
							<span v-if="item.type == 'button'" class="buttonClick textGrColor" @click="childByValue(scope.row, item.field)">{{ scope.row[item.field] instanceof Object ? scope.row[item.field].text : scope.row[item.field] }}</span>
							<!-- 下载 -->
							<span v-if="item.type == 'downLoad'" class="buttonClick textDlColor" @click="childByValue(scope.row, item.field)">{{ scope.row[item.field] ? scope.row[item.field] : '下载文件' }}</span>
							<!-- 上传 -->
							<el-upload
								v-if="item.type == 'upload'"
								ref="upload"
								class="upload-demo"
								:accept="item.accept ? item.accept : '.png,.jpg,.jpeg,.pdf'"
								action="s"
								:show-file-list="false"
								:http-request="
									file => {
										return upLoadFile(file, scope.row, item.size)
									}
								"
							>
								<el-button type="text" class="textGrColor">上传文件</el-button>
							</el-upload>
							<!-- 时间 -->
							<span v-if="item.type == 'date'">{{ parseTime(scope.row[item.field]) }}</span>
							<!-- 插槽 -->
							<span v-if="item.type == 'slot'">
								<slot :name="item.slot_name" :row="scope.row" />
							</span>
						</template>
					</el-table-column>
				</template>

				<el-table-column v-if="localCorptable.operation" fixed="right" label="操作" :width="localCorptable.operationWidth" :align="item.align ? item.align : 'center'">
					<template #default="scope">
						<span v-for="(item, index) in btnFunc(scope.row, localCorptable.isoperaState)" :key="index" class="buttonS">
							<el-button v-if="item.genre !== 'upload'" type="text" size="small" :class="item.class" @click="childByValue(scope.row, item.mark)">
								{{ item.text }}
							</el-button>
							<el-upload
								v-else-if="item.genre === 'upload'"
								ref="upload"
								style="display: inline-block !important"
								class="upload-demo"
								:accept="item.accept ? item.accept : '.png,.jpg,.jpeg,.pdf'"
								action="s"
								:show-file-list="false"
								:http-request="
									file => {
										return upLoadFile(file, scope.row, item.size)
									}
								"
							>
								<el-button type="text" class="textGrColor">{{ item.text }}</el-button>
							</el-upload>
						</span>
					</template>
				</el-table-column>
			</el-table>
		</el-form>
		<span v-if="localCorptable.pageObj?.total>0">
			<el-pagination
				v-if="localCorptable.pageObj"
				background
				:current-page="localCorptable.pageObj.current"
				:page-sizes="localCorptable.pageObj.sizes && localCorptable.pageObj.sizes.length > 0 ? localCorptable.pageObj.sizes : [10, 20, 30, 40]"
				:page-size="localCorptable.pageObj.size"
				layout="total, sizes, prev, pager, next, jumper"
				:total="localCorptable.pageObj.total"
				@size-change="handleSizeChange"
				@current-change="handleCurrentChange"
			/>
		</span>
	</div>
</template>

<script>
export default {
  name: "PuilceTable",
  props: {
    corptable: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      refreshTable: true,
      localCorptable: { ...this.corptable }, // 深拷贝初始化
      itow: 1,
      keyValue: "",
      pageshow: true,
      isTypeValue: false,
      tableFormData: {
        tableData: [],
        rule: {}
      },
      echoTable: [],
      currentPage: 1,
      hStyle: {
        background: "#F3F6FF",
        color: "#000"
      },
      cStyle: {
        color: "#000"
      },
      colorRequired: {
        color: "red"
      },
      text: "*"
    }
  },
  watch: {
    corptable: {
      handler(newD) {
        this.localCorptable = { ...newD };
      },
      deep: true,
      immediate: true
    },
    localCorptable: {
      handler(newD) {
        this.tableFormData.tableData = newD.list
        this.echoTable = newD.echoTable
        if (newD.rules) this.tableFormData.rule = newD.rules
        else this.tableFormData.rule = {}
        this.$forceUpdate()
      },
      deep: true,
      immediate: true
    }
  },
  mounted() {
    this.getList()
  },
  methods: {
    // 多选回显
    multipleEcho() {
      if (this.localCorptable.reserve) {
        if (this.echoTable && this.echoTable.length > 0) {
          this.$refs.multipleTable.clearSelection()
          this.echoTable.forEach(item => {
            this.$refs.multipleTable.toggleRowSelection(item, true)
          })
        } else {
          this.$nextTick(() => {
            this.$refs.multipleTable.clearSelection()
          })
        }
      }
    },
    // 按钮权限
    btnFunc(_data, _isoperaState) {
      const perms = this.$route.meta.perms
      if (typeof _isoperaState === "string" || _isoperaState === undefined || _isoperaState == null || _isoperaState === "") {
        const _status = _data[_isoperaState !== undefined ? _isoperaState : "status"]

        let operation
        let newArr
        // 判断按钮对象是否为空,为空不在不在向下执行
        if (Object.prototype.toString.call(this.localCorptable.operation) === "[object Object]") {
          if (!this.localCorptable.operation[typeof _status === "object" ? _status.value : _status]) {
            return false
          }
        }
        if (perms.length > 0) {
          if (Object.prototype.toString.call(this.localCorptable.operation) === "[object Object]") {
            operation = this.localCorptable.operation[typeof _status === "object" ? _status.value : _status]
          } else {
            operation = this.localCorptable.operation
          }

          newArr = operation.filter(n => {
            return perms.indexOf(n) !== -1
          })
        } else {
          if (Object.prototype.toString.call(this.localCorptable.operation) === "[object Object]") {
            newArr = this.localCorptable.operation[typeof _status === "object" ? _status.value : _status]
          } else {
            newArr = this.localCorptable.operation
          }
        }
        return this.$bp.GetBp().filter(item => {
          return newArr.indexOf(item.mark) !== -1
        })
      } else if (_isoperaState instanceof Object) {
        const operation = [] // 用于和路由按钮权限标识匹配的数组
        let newArr = [] // 用于和按钮标识JSON文件匹配的数组
        const tco = this.localCorptable.operation // 页面规则对象
        const BtnLogo = Object.keys(tco) // 页面的规则对象根据key值转成数组
        let s // 用于接收替换后的规则
        BtnLogo.forEach(i => {
          _isoperaState.forEach((t, ind) => {
            // 根据页面传递过来的“状态字段”,用于把_data中的数据的“状态字段”的值替换到某一条规则当中
            const ReplaceField = JSON.stringify(_data[t] && typeof _data[t] === "object" ? _data[t].value : _data[t])
            if (ind === 0) s = tco[i].replace(new RegExp(t, "g"), ReplaceField) // 根据第一次状态字段的循环赋值给s
            if (ind > 0) s = s.replace(new RegExp(t, "g"), ReplaceField) // 从第二次开始,直接拿s值去做字符串替换(保证里面所有的判断规则的==号之前的值,都能替换成_data中对应的字段的值用于用于匹配==后面的值)
          })
          if (eval(s)) {
            operation.push(i)
          } //  接收到的规则用eval函数执行字符串,为true,则把BtnLogo中的对应的按钮标识push到operation数组中
        })

        if (perms.length > 0) {
                newArr = operation.filter(n => {
                  return perms.indexOf(n) !== -1
                })
        } else newArr = operation

          return this.$bp.GetBp().filter(item => {
            return newArr.indexOf(item.mark) !== -1
          }).length > 0
            ? this.$bp.GetBp().filter(item => {
                return newArr.indexOf(item.mark) !== -1
              })
            : [{ class: "notButton", mark: "", text: "--" }]
        }
    },
    // 表格树异步回调
    tableLoad(tree, treeNode, resolve) {
      this.$emit("tableLoad", { tree, treeNode, resolve })
    },
    // ---文件上传(文件上传控制大小)
    upLoadFile(parme, row, size) {
      const fileSize = Number(parme.file.size / 1024 / 1024)
      let isSize = ""
      // 默认上传大小为10mb
      if (this.isJudge(size)) isSize = size
      else isSize = 10
      if (fileSize > isSize) {
        this.$msgbox({
          title: "",
          message: "上传图片/文件不可以超过" + isSize + "MB!",
          type: "warning"
        })
        return false
      }
      this.$emit("childCallbackFunc", [parme, "upload", row])
    },
    // 选择多选框时的回调
    handleSelectionChange(val, type) {
      if (type === "0") {
        if (val.length > 1) {
          this.$refs.multipleTable.clearSelection()
          this.$refs.multipleTable.toggleRowSelection(val.pop())
          return
        } else {
          this.$emit("childCallbackFunc", [val, "multiSelect"])
        }
      } else {
        this.$emit("childCallbackFunc", [val, "multiSelect"])
      }
    },

    // 勾选父节点时,子层级一起勾选或一起取消勾选
    selectRow(selection, row) {
      this.setRowIsSelect(row)
      // const data = selection.some((item) => {
      //   return row[this.localCorptable.rowKey] === item[this.localCorptable.rowKey]
      // });
      // if (data) {
      //   // 勾选节点时
      //   if (row.children) {
      //     this.setChildren(row.children, true);
      //   } else {
      //   }
      // } else {
      //   // 取消勾选节点时
      //   if (row.children) {
      //     this.setChildren(row.children, false);
      //   }
      // }
    },
      // 复选框点击事件
      setRowIsSelect(row) {
        // 为空字符串则对应行半选态,点击则应该变为全选,则为true
        if (row.isSelect === "") {
          this.$refs.multipleTable.toggleRowSelection(row, true)
        }
        row.isSelect = !row.isSelect
        const _this = this
        // 判断操作的是子级点复选框还是父级点复选框,如果是父级点,则控制子级点的全选和不全选

        // 1、只是父级 2、既是子集,又是父级 3、只是子级
        const levelStatus = getCurrentLevel(row)

        if (levelStatus === 1) {
          // 操作的是父级,则所有子集同步父级状态
          selectAllChildren(row.children)
        } else {
          selectAllChildren(row.children)
          operateLastLevel(row)
        }
        // 判断当前操作行的层级状态
        function getCurrentLevel(row) {
          // 1、只是父级 2、既是子集,又是父级 3、只是子级
          if (row.categoryParentIds === undefined) {
            return 1
          } else if (row.categoryParentIds && !(row.children && row.children.length)) {
            return 3
          } else {
            return 2
          }
        }

        // 递归处理children子级数据的isSelect状态以及对选框状态
        function selectAllChildren(children) {
          if (children) {
            children && children.length && children.forEach((item) => {
              item.isSelect = row.isSelect
              _this.toggleRowSelection(item, row.isSelect)
              if (item.children && item.children.length) {
                selectAllChildren(item.children)
              }
            })
          } else {
            _this.toggleRowSelection(row, row.isSelect)
          }
        }
        // 子级向上操作父级状态
        function operateLastLevel(row) {
          // 操作的是子节点,则
          // 1、获取父节点
          // 2、判断子节点选中个数,如果全部选中则父节点设为选中状态,如果都不选中,则为不选中状态,如果部分选择,则设为不明确状态
          const item = getExplicitNode(_this.tableFormData.tableData, row.categoryId)
          if (item) {
            const selectStatusArr = getSelectStatus([], item.children)
            // 判断所有子集选中态,都为true则父级也选中,都为false则不选中,否则为半选
            const allSelected = selectStatusArr.every(selectItem => selectItem === true)
            const allUnselected = selectStatusArr.every(selectItem => selectItem === false)
            if (allSelected) {
              item.isSelect = true
              _this.toggleRowSelection(item, true)
            } else if (allUnselected) {
              item.isSelect = false
              _this.toggleRowSelection(item, false)
            } else {
              item.isSelect = ""
            }
            // 如果当前节点的parentId存在,则还有父级,继续递归往上一层操作
            if (item.categoryParentIds !== undefined) {
              operateLastLevel(item)
            }
          }
        }
        // 递归获取所有子级的选中状态数组
        function getSelectStatus(selectStatusArr, children) {
          if (!children || !children.length) {
            return selectStatusArr
          }
          children.forEach((child) => {
            selectStatusArr.push(child.isSelect)
            if (child.children && child.children.length) {
              getSelectStatus(selectStatusArr, child.children)
            }
          })
          return selectStatusArr
        }

        // 获取明确父级的节点
        function getExplicitNode(tableData, parentId) {
          let result = null
          function findNode(data) {
            for (let i = 0; i < data.length; i++) {
              if (data[i].id === parentId) {
                result = data[i]
                break
              }
              if (data[i].children && data[i].children.length) {
                findNode(data[i].children)
              }
            }
          }
          findNode(tableData)
          return result
        }
      },
      // 设置当前行的选中态
      toggleRowSelection(row, flag) {
        if (row) {
          this.$nextTick(() => {
            this.$refs.multipleTable &&
                this.$refs.multipleTable.toggleRowSelection(row, flag)
          })
        }
      },
    // 全选按钮
    selectAllRow(selection) {
      // 全选
      const isSelect = selection.some((item) => {
        const tableDataIds = this.tableFormData.tableData.map((data) => data[this.localCorptable.rowKey]);
        if (tableDataIds.indexOf(item[this.localCorptable.rowKey]) !== -1) {
          return true;
        } else {
          return false;
        }
      });
      // 全不选
      const isCancel = !this.tableFormData.tableData.every((item) => {
        const selectIds = selection.map((data) => data[this.localCorptable.rowKey]);
        if (selectIds.indexOf(item[this.localCorptable.rowKey]) !== -1) {
          return true;
        } else {
          return false;
        }
      });
      if (isSelect) {
        selection.map((item) => {
          if (item.children) {
            this.setChildren(item.children, true);
          }
        });
      }
      if (isCancel) {
        this.tableFormData.tableData.map((item) => {
          if (item.children) {
            this.setChildren(item.children, false);
          }
        });
      }
    },
    // 父节点含多个子层级
    setChildren(children, type) {
      children.map((item) => {
        this.toggleSelection(item, type);
        if (item.children) {
          this.setChildren(item.children, type);
        }
      });
    },
    toggleSelection(row, select) {
      if (row) {
        this.$nextTick(() => {
          this.$refs.multipleTable.toggleRowSelection(row, select);
        });
      }
    },

    // 调用父级方法
    childByValue(callback, type) {
      const modelName = this.getModelName()
      const modelId = this.getModelId()
      if (modelName && modelId) {
        const action = this.generateAction(callback, type, modelName, modelId)
        action ? eval("this.$parent." + action) : this.$emit("childCallbackFunc", [callback, type])
      } else {
        this.$emit("childCallbackFunc", [callback, type])
      }
    },
    // 监听当前页有多少条数据变化
    handleSizeChange(val) {
      // this.$emit('childCallbackFunc',[callback,type])
      this.$store.state.isPage = false
      this.isTypeValue = true
      // this.setLoad()
      this.$set(this.localCorptable.pageObj, "size", val)
      this.getList(this.$parent.queryData)
      this.$emit("childCallbackFunc", [val, "page"])
      this.$store.state.isPage = false
    },
    // 监听当前页变化
    handleCurrentChange(val) {
      this.$store.state.isPage = false
      this.isTypeValue = true
      // this.setLoad()
      this.$set(this.localCorptable.pageObj, "current", val)
      this.getList(this.$parent.queryData)
      this.$emit("childCallbackFunc", [val, "page"])
      this.$store.state.isPage = false
    },
    // 默认按钮事件
    generateAction(callback, type, modelName, modelId) {
      let action
      switch (type) {
        // 分页
        case "page":
          action = "get" + modelName + "ListPage()"
          break
        // 修改
        case "edit":
          action = "showEdit" + modelName + "Dialog(" + eval("callback." + modelId) + ")"
          break
        case "remove":
          action = "delete" + modelName + "(" + eval("callback." + modelId) + ")"
          break
      }
      return action
    },
    // 获取模块变量
    getModelName() {
      return this.$parent.modelName
    },
    // 获取模块Id
    getModelId() {
      return this.$parent.modelId
    },
    // 自动执行列表查询
    getList(query) {
      const modelName = this.getModelName()
      const modelId = this.getModelId()

      if (modelName && modelId) {
        // this.setLoad()
        eval("this.$parent.api." + "get" + modelName + "ListPage(" + JSON.stringify(Object.assign({}, this.localCorptable.pageObj, query)) + ")").then(res => {
          if (res.code !== 200) return this.$message.error(res.msg)

          if (res.data.records) {
            this.localCorptable.list = []
            this.localCorptable.list = res.data.records
            this.localCorptable.pageObj.total = res.data.total
            this.$forceUpdate()
          } else {
            this.localCorptable.list = res.data
          }
        })
      }
    },

    // 监听输入框
    inputChange(val, data) {
      this.$emit("childCallbackFunc", [val, "input", data])
      this.$forceUpdate()
    },
    SelectChange(row, field) {
      this.$emit("childCallbackFunc", [row, field])
      this.$forceUpdate()
    },
    // 执行循环判断表格form表单
    tableFromValidation() {
      let v = false
      this.$refs.formDataRef.validate(valid => {
        if (valid) v = true
        else v = false
      })
      return v
    },
    onEmpty() {
      this.$refs.multipleTable.clearSelection()
    }
  }
}
</script>

<style lang="scss" scoped>
#puilceTable {
  margin-top: 15px;
  .buttonClick {
    cursor: pointer;
  }
  ::v-deep .el-table thead {
    background: #f8f8f8;
    color: #000;
  }
  // .el-table th,
  // .el-table tr {
  //   // background-color: transparent !important;
  // }
  .el-table tr td:last-child {
    background-color: #fff;
  }
  .el-table__fixed::before,
  .el-table__fixed-right::before {
    background-color: transparent;
  }
  .el-table__fixed,
  .el-table__fixed-right {
    -webkit-box-shadow: 0 -10px 10px rgb(0, 0, 0, 0.12);
    box-shadow: 0 -10px 10px rgb(0, 0, 0, 0.12);
  }
  .buttonS {
    margin: 0 4px;
  }
  .el-checkbox__input.is-checked .el-checkbox__inner,
  .el-checkbox__input.is-indeterminate .el-checkbox__inner {
    background-color: #409eff;
    border-color: #409eff;
  }
  .el-table .cell.el-tooltip {
    .el-form-item {
      margin-bottom: 13px;
      .el-input {
        height: 30px;
        margin-top: 10px;
      }
      .el-input__icon {
        line-height: 30px;
      }
      .el-input__inner {
        height: 30px;
        padding: 0 5px;
      }
      .el-form-item__error {
        top: 85%;
      }
    }
  }
}
</style>

以下文章描述如何使用这个组件