提交 src/components/CommonStaticTable/index.vue

pull/6/head
李强 2021-03-29 01:59:38 +08:00
parent 0c3a73b647
commit 7c27a476d9
1 changed files with 465 additions and 0 deletions

View File

@ -0,0 +1,465 @@
<!--
@description: 封装组件
-->
<template>
<div style="padding-left: 10px;">
<el-row v-if="topLayout" style="margin-bottom: 20px">
<el-col v-if="topLayoutLeft" :span="18">
<div class="grid-content bg-purple">
<el-input
v-model="searchForm.search"
:disabled="tableLoading"
:size="$ELEMENT.size"
:placeholder="filterPlaceholder"
clearable
style="width: 200px;"
@keyup.enter.native="handleSearchFormSubmit"/>
<el-button
:size="$ELEMENT.size"
type="primary"
title="过滤"
@click="handleSearchFormSubmit">
<common-icon value="svg:icon-filter"/>
</el-button>
<el-button
v-show="isFilter"
:size="$ELEMENT.size"
type="info"
title="取消过滤"
style="margin-left: 0;"
@click="handleCancelFilter">
<common-icon value="svg:icon-unfilter"/>
</el-button>
<slot name="button"/>
</div>
</el-col>
<el-col v-if="topLayoutRight" :span="6">
<div class="grid-content bg-purple-light" style="text-align: right">
<slot name="tools"/>
<el-button
:size="$ELEMENT.size"
name="refresh"
type="info"
title="导出数据"
@click="handleExportTableData">
<svg-icon icon-class="icon-excel" style="font-size: 1em"/>
</el-button>
<el-popover
placement="bottom"
width="200"
trigger="click">
<div style="width: 50px;">
<el-checkbox-group v-model="showFields">
<el-checkbox
v-for="(field, index) in fields"
:key="index"
:label="field"
:checked="field.show"
style="width: 100%"
@change="handleSelectField($event, field)">{{ field.label }}</el-checkbox>
</el-checkbox-group>
</div>
<el-button
slot="reference"
:size="$ELEMENT.size"
name="refresh"
type="info"
icon="el-icon-s-fold"
title="设置显示的字段"/>
</el-popover>
</div>
</el-col>
</el-row>
<el-table
v-loading="tableLoading"
ref="table"
:data="filterData"
:span-method="spanMethod"
:max-height="maxHeight"
:row-key="getRowKeys"
:stripe="stripe"
:fit="fit"
:border="border"
:empty-text="emptyText"
:highlight-current-row="highlightCurrentRow"
:show-overflow-tooltip="showOverflowTooltip"
@cell-click="handleCellClick"
@cell-dblclick="handleCellDbClick"
@header-click="handleHeaderClick"
@row-click="handleRowClick"
@row-dblclick="handleRowDblClick"
@selection-change="handleSelectionChange">
<el-table-column
v-if="selection"
:reserve-selection="true"
type="selection"
width="50"/>
<template v-for="field in fields">
<el-table-column
v-if="field.show"
:key="field.prop"
:prop="field.prop"
:label="field.label"
:sortable="field.sortable"
:width="field.width || ''"
show-overflow-tooltip>
<template slot-scope="scope">
<slot :name="field.prop" :values="scope.row" :prop="field.prop" :field="field">
<span v-html="formatColumnData(scope.row, field)"/>
</slot>
</template>
</el-table-column>
</template>
<slot name="column"/>
</el-table>
<el-row>
<el-col :span="6" style="margin-top: 20px">
<span>已选择:<span style="color: #ff00ff;font-weight: bold;">{{ multipleSelection.length }}</span></span>
<el-button
v-show="multipleSelection.length"
type="info"
size="mini"
title="清空多选"
@click="clearMultipleSelection">清空</el-button>
</el-col>
<el-col :span="18" style="margin-top: 20px; text-align: right">
<span>总计:<span style="color: #ff00ff;font-weight: bold;">{{ filterData.length }}</span></span>
</el-col>
</el-row>
</div>
</template>
<script>
import moment from 'moment';
import * as Utils from '@/utils';
export default {
name: 'CommonStaticTable',
props: {
value: {
type: Array,
default: () => []
},
spanMethod: {
type: Function,
default: null
},
data: {
type: Array,
default: () => []
},
initSelected: {
type: Array,
default: () => []
},
// eslint-disable-next-line vue/require-prop-types
maxHeight: {
default: 700
},
stripe: {
type: Boolean,
default: true
},
fit: {
type: Boolean,
default: true
},
highlightCurrentRow: {
type: Boolean,
default: true
},
showOverflowTooltip: {
type: Boolean,
default: true
},
border: {
type: Boolean,
default: false
},
emptyText: {
type: String,
default: '暂无数据'
},
topLayout: {
type: Array,
default: () => {
return ['left', 'right'];
}
},
bottomLayout: {
type: Array,
default: () => {
return ['left', 'right'];
}
},
fields: {
//
type: Array,
default: () => {
return [];
}
},
selection: {
// (, false)
type: Boolean,
default: false
},
// api
api: {
type: Function,
default: null
},
params: {
type: Object,
default: () => {
return {};
}
}
},
data() {
return {
tableEditable: true,
showFields: [], //
filterFields: [], //
filterPlaceholder: '过滤', //
buttonTagList: [], //
excelDialogVisible: false,
tableLoading: false,
advancedSearchForm: {},
advancedSearchFields: [],
rowKey: null,
multipleSelection: [],
excelHeader: [],
excelData: [],
searchForm: {
search: ''
},
getRowKeys: row => {
if (this.rowKey) {
return row[this.rowKey];
}
return row.id || row.uuid;
},
exportFields: [],
tableData: [],
filterData: [],
isFilter: false
};
},
computed: {
topLayoutLeft() {
return this.topLayout.indexOf('left') >= 0;
},
topLayoutRight() {
return this.topLayout.indexOf('right') >= 0;
}
},
watch: {
data: {
handler: function(newData, oldData) {
this.handleChangeTableData(newData);
},
immediate: true
}
},
mounted() {
},
created() {
this.initComponentData();
this.initData();
this.initSelect();
},
methods: {
initData() {
if (Utils.isFunction(this.api)) {
this.listInterfaceData();
}
},
initSelect() {
for (const row of this.initSelected) {
this.$refs['table'].toggleRowSelection(row, true);
}
},
initComponentData() {
this.fields.forEach(field => {
field.show = (!!field.show);
field.type = (field.type || 'string').toLocaleLowerCase();
field.label = field.label || field.prop;
field.search = (!!field.search);
field.sortable = (!!field.sortable);
field.unique = (!!field.unique);
field.width = field.width || '';
if (field.type === 'choices') {
if (Utils.isArray(field.choices) && field.choices.length > 0) {
if (!Utils.isObj(field.choices[0])) {
field.choices = field.choices.map(value => {
return {
label: value,
value: value
};
});
}
}
}
field.unique = (!!field.unique);
if (field.unique) {
this.rowKey = field.prop;
}
});
this.filterFields = this.fields.filter(field => field.search).map(field => field.prop);
if (this.filterFields.length) {
const text = this.fields.filter(field => field.search).map(field => field.label).join('、');
this.filterPlaceholder = `${text} 过滤`;
}
},
listInterfaceData() {
this.tableLoading = true;
this.api(this.params).then(response => {
this.tableLoading = false;
this.handleChangeTableData(response.data);
}).catch(() => {
this.tableLoading = false;
});
},
formatColumnData(row, field) {
const type = field.type || 'string';
const prop = field.prop;
if (field.formatter && typeof field.formatter === 'function') {
return field.formatter(row, prop, type);
}
if (type === 'string') {
return row[prop];
} else if (type === 'datetime') {
return this.formatDatetime(row[prop]);
} else if (type === 'date') {
return this.formatDate(row[prop]);
} else if (type === 'time') {
return this.formatTime(row[prop]);
} else if (type.startsWith('bool')) {
return row[prop] ? '是' : '否';
} else if (type === 'choices') {
const choices = field.choices;
return this.formatChoices(choices, row[prop]);
} else {
return row[prop];
}
},
formatChoices(choices, value) {
for (const choice of choices) {
if (choice.value === value) {
return choice.label;
}
}
return value;
},
formatDatetime(datetime) {
return moment(datetime).format('YYYY-MM-DD HH:mm:ss');
},
formatDate(date) {
return moment(date).format('YYYY-MM-DD');
},
formatTime(time) {
return moment(time).format('HH:mm:ss');
},
getMultipleSelection() {
return this.multipleSelection || [];
},
clearMultipleSelection() {
this.$refs.table.clearSelection();
},
clearSelection() {
this.$refs.table.clearSelection();
},
clearFilter() {
//
this.searchForm.search = '';
this.filterData = Array.from(this.tableData);
},
handleSelectField(e, field) {
field.show = e;
},
handleChangeTableData(data) {
this.tableData = Array.from(data);
this.filterData = Array.from(this.filterHandler(this.tableData));
},
// ,
handleExportTableData() {
this.excelDialogVisible = true;
this.exportFields = this.fields.map(field => {
return { prop: field.prop, label: field.label, show: field.show };
});
this.excelHeader = this.showFields.map(field => field['prop']);
},
//
handleSelectionChange(val) {
this.$emit('selection-change', val);
this.multipleSelection = val;
},
handleSortChange(val) {
this.sort.prop = val.prop;
this.sort.order = val.order;
this.getTableData();
},
filterHandler(data) {
if (!data) {
data = this.tableData || [];
}
const search = this.searchForm.search.trim();
if (!search.length || !this.filterFields.length) {
this.isFilter = false;
return data;
}
const filterData = data.filter(row => {
for (const field of this.filterFields) {
if (row[field] && row[field].indexOf(search) >= 0) {
return true;
}
}
return false;
});
this.isFilter = true;
return filterData;
},
handleCellClick(row, column, cell, event) {
this.$emit('cell-click', row, column, cell, event);
},
handleCellDbClick(row, column, cell, event) {
this.$emit('cell-dblclick', row, column, cell, event);
},
handleRowClick(row, column, event) {
this.$emit('row-click', row, column, event);
},
handleRowDblClick(row, column, event) {
this.$emit('row-dblclick', row, column, event);
},
handleHeaderClick(column, event) {
this.$emit('header-click', column, event);
},
toggleRowSelection(row, selected = true) {
this.$refs.table.toggleRowSelection(row, selected);
},
toggleFilter() {
//
this.filterData = Array.from(this.filterHandler());
},
handleSearchFormSubmit() {
this.toggleFilter();
},
handleCancelFilter() {
this.isFilter = false;
this.clearFilter();
}
}
};
</script>
<style scoped>
.picker {
width: 240px;
}
.el-pagination {
padding: 5px;
}
.right_pagination {
text-align: right;
padding-top: 20px;
}
</style>