<template> <el-row class="el-table-self"> <el-table ref="selftab" v-loading="listLoading" :row-key="rowKey" :size="tabSize" :summary-method="getSummaries" :show-summary="showSummary" :span-method="spanMethod" :data="tableData" :show-overflow-tooltip="true" :highlight-current-row="highLight" :max-height="maxHeight || maxTableHeight" :height="tableHeight" :header-row-class-name="headerClass" :row-style="rowStyle" :expand-row-keys="expands" :cell-style="cellStyle" style="width: 100%" :default-expand-all="defaultExpandAll" :style="{ fontSize: fontSize + 'px' }" :header-cell-style="{ fontSize: fontSize + 'px' }" @row-click="rowClick" @sort-change="sortChange" @select="selectChange" @selection-change="selectionChange" @select-all="selectAll" @cell-click="cellClick" > <el-table-column v-if="tabType" :type="tabType" width="55" align="center" :label="tabLabel" :selectable="selecTable" :index="tabIndex" ></el-table-column> <template v-for="(column, index) in columns"> <template v-if="!column.hidden"> <template v-if="!column.type && !column.operType"> <el-table-column :key="index" :show-overflow-tooltip="true" :fixed="column.fixed" :prop="column.value" :label="column.label" :width="column.width" :min-width="column.minWidth" align="center" :sortable="column.sortable" :formatter="column.formatter" :class-name="column.className" :label-class-name="column.labelClassName" /> </template> <template v-else> <!-- 复杂表头 --> <template v-if="column.type === 'complex'"> <el-table-column :key="index" :fixed="column.fixed" :prop="column.value" :label="column.label" :width="column.width" align="center" > <template v-for="(col2, col2Index) in column.list"> <template v-if="!col2.hidden"> <!-- 文本 --> <template v-if="!col2.type && !col2.operType"> <el-table-column :key="col2Index" :show-overflow-tooltip="true" :prop="col2.value" :label="col2.label" :width="col2.width" align="center" :formatter="col2.formatter" :class-name="col2.className" /> </template> <!-- 按钮 --> <template v-else> <el-table-column :key="col2Index" :label="col2.label" :width="col2.width" :prop="col2.value" align="center" > <template slot-scope="scope"> <template v-if=" col2.type === 'button' || col2.operType === 'button' " > <template v-for="(op, opIndex) in col2.operations"> <template v-if="!op.isHidden || !op.isHidden(scope.row)" > <el-button :key="opIndex" :disabled=" op.formatter ? op.formatter(scope.row).disabled : false " :style="op.style" :type=" op.formatter ? op.formatter(scope.row).type : op.type || '' " :icon="op.icon" @click="op.func(scope.row, scope.$index)" > {{ op.formatter ? op.formatter(scope.row).label : op.label ? op.label : scope.row[col2.value] }} </el-button> </template> </template> </template> <template v-if="col2.operType === 'input'"> <template v-if="col2.type === 'number'"> <el-input-number v-if=" col2.showInput ? col2.showInput : scope.row.showInput " v-model="scope.row[col2.value]" :controls="false" :min="col2.min || scope.row['min'] || 0" :precision="col2.precision" :disabled="col2.disabled || disabled" @change=" col2.func ? col2.func(scope.row, scope.$index) : {} " @input=" handleEdit( scope.$index, scope.row[col2.value], scope.row, col2.value ) " @blur=" col2.blurFunc ? col2.blurFunc(scope.row, scope.$index) : {} " @keydown.native.enter=" col2.enterFunc ? col2.enterFunc(scope.row, scope.$index) : {} " /> <span v-else class="tableSpan"> {{ scope.row[col2.value] }} </span> </template> <template v-else> <el-input v-if=" col2.showInput ? col2.showInput : scope.row.showInput " v-model="scope.row[col2.value]" :autofocus="scope.row[col2.autofocus]" :disabled="disabled" :size="col2.size" @input=" handleEdit( scope.$index, scope.row[col2.value], scope.row, col2.value ) " @blur=" col2.blurFunc ? col2.blurFunc(scope.row, scope.$index) : {} " @keydown.native.enter=" col2.enterFunc ? col2.enterFunc(scope.row, scope.$index) : {} " /> <span v-else class="tableSpan"> {{ scope.row[col2.value] }} </span> </template> </template> <template v-else-if="col2.operType === 'select'"> <el-select v-model="scope.row[col2.value]" filterable clearable placeholder="请选择" no-data-text=" " no-match-text=" " :disabled="disabled" :remote="col2.remote" :allow-create="col2.allowCreate" :remote-method="col2.remoteMethod" @change=" col2.enterFunc ? col2.enterFunc(scope.row, scope.$index) : changeProject( scope.row[col2.value], scope.$index ) " @focus="changeSelect(scope.row)" > <el-option v-for="item in col2.opts ? col2.opts : scope.row.opts" :key="item.value" :label="item.label" :value=" col2.isSelect ? item.selectValue : item.value " ></el-option> </el-select> </template> </template> </el-table-column> </template> </template> </template> </el-table-column> </template> <template v-else> <el-table-column :key="index" :fixed="column.fixed" :prop="column.value" :label="column.label" :sortable="column.sortable" :width="column.width" :min-width="column.minWidth" align="center" > <template slot="header" slot-scope="scope"> <span>{{ column.label }}</span> <el-checkbox v-if=" column.tabType === 'selection' && column.operType === 'checkbox' " v-model="column['checkAll']" style="margin-left: 4px" @change="handleCheckAllChange($event, column)" ></el-checkbox> </template> <template slot-scope="scope"> <!-- 按钮 --> <template v-if=" column.type === 'button' || column.operType === 'button' " > <template v-for="(op, opIndex) in column.operations"> <template v-if="!op.isHidden || !op.isHidden(scope.row)"> <el-dropdown v-if="op.type === 'dropdown'" :key="opIndex" size="large" style="margin: 0 10px" trigger="click" > <el-button type="primary" :size="size"> {{ op.title || "更多操作" }} <i class="el-icon-arrow-down el-icon--right"></i> </el-button> <el-dropdown-menu slot="dropdown"> <el-dropdown-item v-for="(child, childIndex) in op.children" :key="childIndex" :disabled=" child.formatter ? child.formatter(scope.row).disabled : false " :style=" child.formatter ? child.formatter(scope.row).style : child.style || '' " :type=" child.formatter ? child.formatter(scope.row).type : child.type || '' " :icon="child.icon" @click.native=" child.func(scope.row, scope.$index) " > {{ child.formatter ? child.formatter(scope.row).label : child.label }} </el-dropdown-item> </el-dropdown-menu> </el-dropdown> <div v-else-if="op.type === 'switch'" :key="opIndex" class="switch-cell" :disabled=" op.formatter ? op.formatter(scope.row).disabled : false " @click="handleSwitch(scope.row, scope.$index, op)" > <el-switch v-model="scope.row[column.value]" :active-value="op.activeValue" :inactive-value="op.inactiveValue" ></el-switch> </div> <template v-else> <template v-if=" op.formatter && op.formatter(scope.row).type == 'none' " ></template> <el-button v-else :key="opIndex" :size="size" :disabled=" op.formatter ? op.formatter(scope.row).disabled : false " :style="op.style" :type=" op.formatter ? op.formatter(scope.row).type : op.type || '' " :icon="op.icon" @click="op.func(scope.row, scope.$index)" > {{ op.formatter ? op.formatter(scope.row).label : op.label ? op.label : scope.row[column.value] }} </el-button> </template> </template> </template> </template> <template v-if="column.operType === 'svg'"> <template v-for="(operate, operIndex) in column.operations.formatter ? column.operations.formatter(scope.row) : column.operations" > <template v-if="!operate.isHidden || !operate.isHidden(scope.row)" > <el-tooltip v-if="operate.tips" :key="operIndex + Date.parse(new Date())" effect="dark" :open-delay="200" placement="top-start" > <span slot="content">{{ operate.tips }}</span> <svg-icon :style="operate.style" :icon-class="operate.iconClass" class="tab-svg" @click.native=" operate.func ? operate.func(scope.row, scope.$index) : {} " ></svg-icon> </el-tooltip> <svg-icon v-else :key="operIndex + Date.parse(new Date())" :style="operate.style" :icon-class="operate.iconClass" class="tab-svg" @click.native="operate.func(scope.row, scope.$index)" ></svg-icon> </template> </template> </template> <template v-if="column.operType === 'input'"> <template v-if="column.type === 'number'"> <el-input-number v-if=" column.showInput ? column.showInput : scope.row.showInput " v-model="scope.row[column.value]" :controls="false" :min="column.min || scope.row['min'] || 0" :precision="column.precision" :disabled="column.disabled || disabled" :style="{ width: column.inputWidth + 'px', }" @change=" column.func ? column.func(scope.row, scope.$index) : {} " @input=" handleEdit( scope.$index, scope.row[column.value], scope.row, column.value ) " @blur=" column.blurFunc ? column.blurFunc(scope.row, scope.$index) : {} " @keydown.native.enter=" column.enterFunc ? column.enterFunc(scope.row, scope.$index) : {} " /> <span v-else class="tableSpan"> {{ scope.row[column.value] }} </span> </template> <template v-else> <el-input v-if=" column.showInput ? column.showInput : scope.row.showInput " v-model="scope.row[column.value]" :autofocus="scope.row[column.autofocus]" :disabled="column.disabled || disabled" :size="column.size" @input=" handleEdit( scope.$index, scope.row[column.value], scope.row, column.value ) " @blur=" column.blurFunc ? column.blurFunc(scope.row, scope.$index) : {} " @keydown.native.enter=" column.enterFunc ? column.enterFunc(scope.row, scope.$index) : {} " /> <span v-else class="tableSpan"> {{ scope.row[column.value] }} </span> </template> </template> <template v-if="column.operType === 'date'"> <el-date-picker v-if="column.showDate" v-model="scope.row[column.value]" align="center" :picker-options="column.options" :type="column.dateType || 'date'" :placeholder="scope.row[column.placeholder]" :disabled="disabled" :format="column.format" :value-format="column.valueFormat" :size="column.size" ></el-date-picker> <span v-else class="tableSpan"> {{ scope.row[column.value] }} </span> </template> <template v-if="column.operType === 'textarea'"> <el-input v-model="scope.row[column.value]" type="textarea" :placeholder="column.placeholder" :rows="column.rows" :autosize="column.autosize" :minlength="column.minlength" :maxlength="column.maxlength" :show-word-limit="column.showLimit" ></el-input> </template> <template v-else-if="column.operType === 'select'"> <el-select v-model="scope.row[column.value]" filterable placeholder="请选择" no-data-text=" " no-match-text=" " :disabled="disabled" :remote="column.remote" :allow-create="column.allowCreate" :remote-method="column.remoteMethod" @change=" column.enterFunc ? column.enterFunc(scope.row, scope.$index) : changeProject(scope.row[column.value], scope.$index) " @focus=" column.focusFunc ? column.focusFunc(scope.row, scope.$index) : {} " > <el-option v-for="item in column.opts ? column.opts : scope.row.opts" :key="item.value" :label="item.label" :value="column.isSelect ? item.selectValue : item.value" ></el-option> </el-select> </template> <template v-if="column.operType === 'checkbox'"> <el-checkbox v-model="scope.row[column.value]" ></el-checkbox> </template> <!-- 模糊查询输入 --> <el-autocomplete v-else-if="column.operType === 'autocomplete'" v-model="scope.row[column.value]" :popper-class=" column.popperClass ? column.popperClass : 'my-autocomplete' " :fetch-suggestions="column.searchFunc" :placeholder="column.placeholder ? column.placeholder : ''" :trigger-on-focus="false" clearable @select=" column.selectFun ? column.selectFun($event, scope.$index) : {} " @input=" column.inputFunc ? column.inputFunc( scope.row, scope.$index, column.value ) : {} " @blur=" column.changeFunc ? column.changeFunc( scope.row, scope.$index, column.value ) : {} " > <template slot-scope="{ item }"> <div class="name">{{ item.name }}</div> <span class="desc">{{ item.desc }}</span> </template> </el-autocomplete> <!-- <template v-else-if="column.operType === 'check-inputs'"> <el-input v-model="scope.row[column.value]" style="width:33%" @blur="column.bigFunc(scope.row,scope.$index)" /> {{column.formatter1(scope.row)}} <template v-if="scope.row['isTiny'] === 1"> <el-input v-model="scope.row[column.value2]" style="width:33%" @blur="column.smallFunc(scope.row,scope.$index)" /> {{column.formatter2(scope.row)}} </template> </template> <template v-else-if="column.operType === 'label'"> <span>{{scope.row[column.value]}}</span> </template>--> <template v-else-if="column.operType === 'upload'"> <el-button v-if="!scope.row.imgUrl" style="float: left" type="primary" @click="column.func(scope.$index)" >上传</el-button > <span v-if="scope.row.imgUrl" style=" float: left; line-height: 32px; margin-left: 5px; cursor: pointer; color: #409eff; " @click="column.enlargeFunc(scope.row.imgUrl)" >{{ scope.row.imgUrl }}</span > <el-button v-if="scope.row.imgUrl" style="float: left; margin-left: 5px" type="primary" @click="column.delFunc(scope.row, scope.$index)" >删除</el-button > </template> <!-- 图片 --> <template v-if="column.operType === 'img'"> <img class="imgs" :src="scope.row[column.value]" :style="column.style" @click=" column.imgFun ? column.imgFun(scope.row, scope.$index) : '' " /> </template> <!-- 消息 --> <template v-if="column.operType === 'txt'"> <div :style="column.style1"> {{ scope.row[column.value1] }} </div> <div :style="column.style2"> {{ scope.row[column.value2] }} </div> </template> <!-- html --> <template v-if="column.type === 'html'"> <div class="highlight" v-html="scope.row[column.value]" ></div> </template> <template v-if="column.type === 'switch'"> <el-switch v-model="scope.row[column.value]" :active-value="0" :inactive-value="1" @change="column.func(scope.row, scope.$index)" ></el-switch> </template> <!-- 展开列表 --> <template v-if="column.tabType === 'expand'"> <el-form label-position="right" class="demo-table-expand" label-width="130px" > <template v-for="(expand, index) in column.expandColumns"> <el-form-item v-if="!expand.hidden" :key="index" :label="`【${expand.label}】`" > <!-- 字体高亮 --> <div v-if="scope.row[expand.value]" class="el-alert el-alert--info is-light" > <div class="el-alert__content highlight" v-html="scope.row[expand.value]" ></div> </div> </el-form-item> </template> </el-form> </template> </template> </el-table-column> </template> </template> </template> </template> </el-table> <div v-if="pageSize && totalCounts > 0" class="pagination-footer"> <span class="description">{{ description }}</span> <el-pagination background :current-page="currentPage" :page-sizes="pageSizes" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="totalCounts" @size-change="handleSizeChange" @current-change="handleCurrentChange" ></el-pagination> </div> </el-row> </template> <script> import resize from "./resize.js" import { mapGetters } from "vuex" export default { name: "ElTableSelf", // filters: { // statusFilter(status) { // const typeMap = ['warm', 'success', 'danger'] // return typeMap[status] // }, // statusFilter2(status) { // const typeMap = ['danger', 'success'] // return typeMap[status] // } // }, mixins: [resize], props: { listLoading: Boolean, // tab 加载层 rowKey: Function | String, expands: Array, highLight: { type: Boolean, default: true }, headerClass: { type: String, default: "default" }, // 头部背景色Class名称,默认default tabType: String, // 对应列的类型,selection/index/expand tabLabel: String, tableHeight: Number, // 表格的高度 maxHeight: Number, // 表格的最大高度 tabSize: { type: String }, tableData: Array, // 表格数据 columns: Array, // 表格列配置数据,{vlaue:对应数据对象中的属性,label:对应的是标题文字,fixed:列是否固定,width:列宽, sortable:是否可排序,formatter:列格式化, className:对应的是列的样式类名} sortChange: { type: Function, default: () => {} }, // 点击列表头进行排序 { column, prop, order } description: String, // 分页脚底左侧的数据说明 totalCount: [Number, String], // 表格数据总数 pageSizes: Array, // 决定每页显示的条数[10,15,20,25] pageSize: Number, spanMethod: Function, operType: { type: String, default: "button" }, getSummaries: Function, showSummary: { type: Boolean, default: false }, size: { type: String, default: "small" }, type: { type: String, default: "text" }, currentPage: { type: Number, default: 1 }, selecTable: Function, disabled: { type: Boolean, default: false }, tabIndex: Function, cellStyle: Function, rowStyle: Function, defaultExpandAll: Boolean, }, computed: { totalCounts() { return this.totalCount - 0 }, ...mapGetters({ fontSize: "table/fontSize", roles: "user/roles", }), }, methods: { // switch点击 handleSwitch(row, index, op) { const disabled = op.formatter ? op.formatter(row).disabled : false if (disabled) return if (op.func) op.func(row, index) }, // 自定义头部 全选 handleCheckAllChange(val, column) { this.tableData.forEach((item) => { item[column.value] = val ? true : false }) }, // 切换页面显示条数 handleSizeChange(val) { this.$emit("pageSizeChange", val) }, // 跳转页码 handleCurrentChange(val) { this.$emit("currentPageChange", val) }, // 复选框事件 selectionChange(selections) { this.$emit("selectionChange", selections) }, // 复选框选中当前行事件 selectChange(selections, row) { this.$emit("selectChange", selections, row) }, // 行点击 rowClick(row, event) { this.$emit("rowClick", row, event) }, // 行点击 cellClick(row, column, cell, event) { this.$emit("cellClick", row, column, cell, event) }, // 收费的输入 handleEdit(index, value, row, pro) { this.$emit("number", index, value, row, pro) }, changeProject(row, index) { this.$emit("project", row, index) }, changeSelect(row) { this.$emit("changeSelect", row) }, // 全选事件 selectAll(selections) { this.$emit("selectAll", selections) }, // 远程搜索 remoteMethod(val) { this.$emit("remoteMethod", val) }, clearSort() { this.$refs.selftab.clearSort() }, }, } </script> <style lang="scss" scoped> .highlight { ::v-deep em { font-weight: bold; font-style: normal; color: #f56c6c; } } .el-table-self { border: 1px solid #f6f6f6; margin-top: 20px; .tab-svg { width: 24px; height: 24px; margin: 0 2px; cursor: pointer; vertical-align: middle; } .demo-table-expand { .el-form-item { margin-bottom: 10px; width: 70%; ::v-deep .el-form-item__label, ::v-deep.el-form-item__content { font-weight: bold; line-height: 25px; } } } } .pagination-footer { .description { float: left; margin-left: 20px; margin-top: 12px; font-size: 14px; } .el-pagination { margin-top: 8px; margin-bottom: 8px; } } .el-table__empty-block { position: relative; min-height: 60px; text-align: center; width: 100%; height: 100%; } .el-table__empty-text { position: absolute; left: 50%; width: 110px; height: 110px; top: 50%; line-height: 220px; -ms-transform: translate(-50%, -50%); transform: translate(-50%, -50%); color: #5e7382; background-position: center center; background-repeat: no-repeat; background-size: cover; } .tableSpan { display: inline-block; width: 100%; height: 100%; cursor: pointer; } .isPlan { font-size: 12px; color: #fff; padding: 2px 5px; background: #c1242a; border-radius: 3px; } .imgs { vertical-align: top; } ::v-deep .default { th { background-color: #f6f6f6 !important; color: #586276; } } ::v-deep .el-table__footer-wrapper tbody td { background: oldlace !important; } .el-autocomplete-suggestion.my-autocomplete { .desc { font-size: 12px; color: #b4b4b4; } } .switch-cell { position: relative; &::after { position: absolute; content: "."; cursor: pointer; height: 100%; width: 100%; top: 0; left: 0; z-index: 1; } &[disabled]::after { cursor: not-allowed; } } </style>