empty master
This commit is contained in:
parent
92c1162255
commit
67d534df27
276 changed files with 0 additions and 28368 deletions
|
@ -1,100 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<template v-if="renderType === 'index'">{{naturalIndex + 1}}</template>
|
||||
<template v-if="renderType === 'selection'">
|
||||
<Checkbox :checked="checked" @on-change="toggleSelect" :disabled="disabled"></Checkbox>
|
||||
</template>
|
||||
<template v-if="renderType === 'normal'">{{{ row[column.key] }}}</template>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Checkbox from '../checkbox/checkbox.vue';
|
||||
|
||||
export default {
|
||||
components: { Checkbox },
|
||||
props: {
|
||||
prefixCls: String,
|
||||
row: Object,
|
||||
column: Object,
|
||||
naturalIndex: Number, // index of rebuildData
|
||||
index: Number, // _index of data
|
||||
checked: Boolean,
|
||||
disabled: Boolean,
|
||||
fixed: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
renderType: '',
|
||||
uid: -1,
|
||||
content: this.$parent.$parent.content
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${this.prefixCls}-cell`,
|
||||
{
|
||||
[`${this.prefixCls}-hidden`]: !this.fixed && this.column.fixed && (this.column.fixed === 'left' || this.column.fixed === 'right'),
|
||||
[`${this.prefixCls}-cell-ellipsis`]: this.column.ellipsis || false
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
compile () {
|
||||
if (this.column.render) {
|
||||
const $parent = this.content;
|
||||
const template = this.column.render(this.row, this.column, this.index);
|
||||
const cell = document.createElement('div');
|
||||
cell.innerHTML = template;
|
||||
const _oldParentChildLen = $parent.$children.length;
|
||||
$parent.$compile(cell); // todo 这里无法触发 ready 钩子
|
||||
const _newParentChildLen = $parent.$children.length;
|
||||
|
||||
if (_oldParentChildLen !== _newParentChildLen) { // if render normal html node, do not tag
|
||||
this.uid = $parent.$children[$parent.$children.length - 1]._uid; // tag it, and delete when data or columns update
|
||||
}
|
||||
this.$el.innerHTML = '';
|
||||
this.$el.appendChild(cell);
|
||||
}
|
||||
},
|
||||
destroy () {
|
||||
const $parent = this.content;
|
||||
for (let i = 0; i < $parent.$children.length; i++) {
|
||||
if ($parent.$children[i]._uid === this.uid) {
|
||||
$parent.$children[i].$destroy();
|
||||
}
|
||||
}
|
||||
},
|
||||
toggleSelect () {
|
||||
this.$parent.$parent.toggleSelect(this.index);
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
if (this.column.type === 'index') {
|
||||
this.renderType = 'index';
|
||||
} else if (this.column.type === 'selection') {
|
||||
this.renderType = 'selection';
|
||||
} else if (this.column.render) {
|
||||
this.renderType = 'render';
|
||||
} else {
|
||||
this.renderType = 'normal';
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
this.compile();
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.destroy();
|
||||
},
|
||||
watch: {
|
||||
naturalIndex () {
|
||||
this.destroy();
|
||||
this.compile();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,77 +0,0 @@
|
|||
function has (browser) {
|
||||
const ua = navigator.userAgent;
|
||||
if (browser === 'ie') {
|
||||
const isIE = ua.indexOf('compatible') > -1 && ua.indexOf('MSIE') > -1;
|
||||
if (isIE) {
|
||||
const reIE = new RegExp('MSIE (\\d+\\.\\d+);');
|
||||
reIE.test(ua);
|
||||
return parseFloat(RegExp['$1']);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return ua.indexOf(browser) > -1;
|
||||
}
|
||||
}
|
||||
|
||||
const csv = {
|
||||
_isIE11 () {
|
||||
let iev = 0;
|
||||
const ieold = (/MSIE (\d+\.\d+);/.test(navigator.userAgent));
|
||||
const trident = !!navigator.userAgent.match(/Trident\/7.0/);
|
||||
const rv = navigator.userAgent.indexOf('rv:11.0');
|
||||
|
||||
if (ieold) {
|
||||
iev = Number(RegExp.$1);
|
||||
}
|
||||
if (navigator.appVersion.indexOf('MSIE 10') !== -1) {
|
||||
iev = 10;
|
||||
}
|
||||
if (trident && rv !== -1) {
|
||||
iev = 11;
|
||||
}
|
||||
|
||||
return iev === 11;
|
||||
},
|
||||
|
||||
_isEdge () {
|
||||
return /Edge/.test(navigator.userAgent);
|
||||
},
|
||||
|
||||
_getDownloadUrl (text) {
|
||||
const BOM = '\uFEFF';
|
||||
// Add BOM to text for open in excel correctly
|
||||
if (window.Blob && window.URL && window.URL.createObjectURL && !has('Safari')) {
|
||||
const csvData = new Blob([BOM + text], { type: 'text/csv' });
|
||||
return URL.createObjectURL(csvData);
|
||||
} else {
|
||||
return 'data:attachment/csv;charset=utf-8,' + BOM + encodeURIComponent(text);
|
||||
}
|
||||
},
|
||||
|
||||
download (filename, text) {
|
||||
if (has('ie') && has('ie') < 10) {
|
||||
// has module unable identify ie11 and Edge
|
||||
const oWin = window.top.open('about:blank', '_blank');
|
||||
oWin.document.charset = 'utf-8';
|
||||
oWin.document.write(text);
|
||||
oWin.document.close();
|
||||
oWin.document.execCommand('SaveAs', filename);
|
||||
oWin.close();
|
||||
} else if (has('ie') === 10 || this._isIE11() || this._isEdge()) {
|
||||
const BOM = '\uFEFF';
|
||||
const csvData = new Blob([BOM + text], { type: 'text/csv' });
|
||||
navigator.msSaveBlob(csvData, filename);
|
||||
} else {
|
||||
const link = document.createElement('a');
|
||||
link.download = filename;
|
||||
link.href = this._getDownloadUrl(text);
|
||||
link.target = '_blank';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default csv;
|
|
@ -1,2 +0,0 @@
|
|||
import Table from './table.vue';
|
||||
export default Table;
|
|
@ -1,39 +0,0 @@
|
|||
export default {
|
||||
methods: {
|
||||
alignCls (column, row = {}) {
|
||||
let cellClassName = '';
|
||||
if (row.cellClassName && column.key && row.cellClassName[column.key]) {
|
||||
cellClassName = row.cellClassName[column.key];
|
||||
}
|
||||
return [
|
||||
{
|
||||
[`${cellClassName}`]: cellClassName, // cell className
|
||||
[`${column.className}`]: column.className, // column className
|
||||
[`${this.prefixCls}-column-${column.align}`]: column.align,
|
||||
[`${this.prefixCls}-hidden`]: (this.fixed === 'left' && column.fixed !== 'left') || (this.fixed === 'right' && column.fixed !== 'right') || (!this.fixed && column.fixed && (column.fixed === 'left' || column.fixed === 'right'))
|
||||
}
|
||||
];
|
||||
},
|
||||
isPopperShow (column) {
|
||||
return column.filters && ((!this.fixed && !column.fixed) || (this.fixed === 'left' && column.fixed === 'left') || (this.fixed === 'right' && column.fixed === 'right'));
|
||||
},
|
||||
setCellWidth (column, index, top) {
|
||||
let width = '';
|
||||
if (column.width) {
|
||||
width = column.width;
|
||||
} else if (this.columnsWidth[column._index]) {
|
||||
width = this.columnsWidth[column._index].width;
|
||||
}
|
||||
// when browser has scrollBar,set a width to resolve scroll position bug
|
||||
if (this.columns.length === index + 1 && top && this.$parent.bodyHeight !== 0) {
|
||||
width += this.$parent.scrollBarWidth;
|
||||
}
|
||||
// when fixed type,reset first right fixed column's width
|
||||
if (this.fixed === 'right') {
|
||||
const firstFixedIndex = this.columns.findIndex((col) => col.fixed === 'right');
|
||||
if (firstFixedIndex === index) width += this.$parent.scrollBarWidth;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,83 +0,0 @@
|
|||
<template>
|
||||
<table cellspacing="0" cellpadding="0" border="0" :style="style">
|
||||
<colgroup>
|
||||
<col v-for="column in columns" :width="setCellWidth(column, $index, false)">
|
||||
</colgroup>
|
||||
<tbody :class="[prefixCls + '-tbody']">
|
||||
<tr
|
||||
v-for="(index, row) in data"
|
||||
:class="rowClasses(row._index)"
|
||||
@mouseenter.stop="handleMouseIn(row._index)"
|
||||
@mouseleave.stop="handleMouseOut(row._index)"
|
||||
@click.stop="clickCurrentRow(row._index)"
|
||||
@dblclick.stop="dblclickCurrentRow(row._index)">
|
||||
<td v-for="column in columns" :class="alignCls(column, row)">
|
||||
<Cell
|
||||
:fixed="fixed"
|
||||
:prefix-cls="prefixCls"
|
||||
:row="row"
|
||||
:column="column"
|
||||
:natural-index="index"
|
||||
:index="row._index"
|
||||
:checked="rowChecked(row._index)"
|
||||
:disabled="rowDisabled(row._index)"
|
||||
></Cell>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
<script>
|
||||
import Cell from './cell.vue';
|
||||
import Mixin from './mixin';
|
||||
|
||||
export default {
|
||||
mixins: [ Mixin ],
|
||||
components: { Cell },
|
||||
props: {
|
||||
prefixCls: String,
|
||||
style: Object,
|
||||
columns: Array,
|
||||
data: Array, // rebuildData
|
||||
objData: Object,
|
||||
columnsWidth: Object,
|
||||
fixed: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rowClasses (_index) {
|
||||
return [
|
||||
`${this.prefixCls}-row`,
|
||||
this.rowClsName(_index),
|
||||
{
|
||||
[`${this.prefixCls}-row-highlight`]: this.objData[_index] && this.objData[_index]._isHighlight,
|
||||
[`${this.prefixCls}-row-hover`]: this.objData[_index] && this.objData[_index]._isHover
|
||||
}
|
||||
];
|
||||
},
|
||||
rowChecked (_index) {
|
||||
return this.objData[_index] && this.objData[_index]._isChecked;
|
||||
},
|
||||
rowDisabled(_index){
|
||||
return this.objData[_index] && this.objData[_index]._isDisabled;
|
||||
},
|
||||
rowClsName (_index) {
|
||||
return this.$parent.rowClassName(this.objData[_index], _index);
|
||||
},
|
||||
handleMouseIn (_index) {
|
||||
this.$parent.handleMouseIn(_index);
|
||||
},
|
||||
handleMouseOut (_index) {
|
||||
this.$parent.handleMouseOut(_index);
|
||||
},
|
||||
clickCurrentRow (_index) {
|
||||
this.$parent.clickCurrentRow(_index);
|
||||
},
|
||||
dblclickCurrentRow (_index) {
|
||||
this.$parent.dblclickCurrentRow(_index);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,154 +0,0 @@
|
|||
<template>
|
||||
<table cellspacing="0" cellpadding="0" border="0" :style="styles">
|
||||
<colgroup>
|
||||
<col v-for="column in columns" :width="setCellWidth(column, $index, true)">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-for="(index, column) in columns" :class="alignCls(column)">
|
||||
<div :class="cellClasses(column)">
|
||||
<template v-if="column.type === 'selection'"><Checkbox :checked="isSelectAll" @on-change="selectAll"></Checkbox></template>
|
||||
<template v-else>
|
||||
{{{ renderHeader(column, $index) }}}
|
||||
<span :class="[prefixCls + '-sort']" v-if="column.sortable">
|
||||
<i class="ivu-icon ivu-icon-arrow-up-b" :class="{on: column._sortType === 'asc'}" @click="handleSort($index, 'asc')"></i>
|
||||
<i class="ivu-icon ivu-icon-arrow-down-b" :class="{on: column._sortType === 'desc'}" @click="handleSort($index, 'desc')"></i>
|
||||
</span>
|
||||
<Poptip
|
||||
v-if="isPopperShow(column)"
|
||||
:visible.sync="column._filterVisible"
|
||||
placement="bottom"
|
||||
@on-popper-hide="handleFilterHide($index)">
|
||||
<span :class="[prefixCls + '-filter']">
|
||||
<i class="ivu-icon ivu-icon-funnel" :class="{on: column._isFiltered}"></i>
|
||||
</span>
|
||||
<div slot="content" :class="[prefixCls + '-filter-list']" v-if="column._filterMultiple">
|
||||
<div :class="[prefixCls + '-filter-list-item']">
|
||||
<checkbox-group :model.sync="column._filterChecked">
|
||||
<checkbox v-for="item in column.filters" :value="item.value">{{ item.label }}</checkbox>
|
||||
</checkbox-group>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-filter-footer']">
|
||||
<i-button type="text" size="small" :disabled="!column._filterChecked.length" @click="handleFilter($index)">{{ t('i.table.confirmFilter') }}</i-button>
|
||||
<i-button type="text" size="small" @click="handleReset($index)">{{ t('i.table.resetFilter') }}</i-button>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="content" :class="[prefixCls + '-filter-list']" v-else>
|
||||
<ul :class="[prefixCls + '-filter-list-single']">
|
||||
<li
|
||||
:class="itemAllClasses(column)"
|
||||
@click="handleReset($index)">{{ t('i.table.clearFilter') }}</li>
|
||||
<li
|
||||
:class="itemClasses(column, item)"
|
||||
v-for="item in column.filters"
|
||||
@click="handleSelect(index, item.value)">{{ item.label }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Poptip>
|
||||
</template>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</template>
|
||||
<script>
|
||||
import CheckboxGroup from '../checkbox/checkbox-group.vue';
|
||||
import Checkbox from '../checkbox/checkbox.vue';
|
||||
import Poptip from '../poptip/poptip.vue';
|
||||
import iButton from '../button/button.vue';
|
||||
import Mixin from './mixin';
|
||||
import Locale from '../../mixins/locale';
|
||||
|
||||
export default {
|
||||
mixins: [ Mixin, Locale ],
|
||||
components: { CheckboxGroup, Checkbox, Poptip, iButton },
|
||||
props: {
|
||||
prefixCls: String,
|
||||
style: Object,
|
||||
columns: Array,
|
||||
objData: Object,
|
||||
data: Array, // rebuildData
|
||||
columnsWidth: Object,
|
||||
fixed: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
styles () {
|
||||
const style = Object.assign({}, this.style);
|
||||
const width = this.$parent.bodyHeight === 0 ? parseInt(this.style.width) : parseInt(this.style.width) + this.$parent.scrollBarWidth;
|
||||
style.width = `${width}px`;
|
||||
return style;
|
||||
},
|
||||
isSelectAll () {
|
||||
let isSelectAll = true;
|
||||
if (!this.data.length) isSelectAll = false;
|
||||
for (let i = 0; i < this.data.length; i++) {
|
||||
if (!this.objData[this.data[i]._index]._isChecked && !this.objData[this.data[i]._index]._isDisabled) {
|
||||
isSelectAll = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return isSelectAll;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cellClasses (column) {
|
||||
return [
|
||||
`${this.prefixCls}-cell`,
|
||||
{
|
||||
[`${this.prefixCls}-hidden`]: !this.fixed && column.fixed && (column.fixed === 'left' || column.fixed === 'right')
|
||||
}
|
||||
];
|
||||
},
|
||||
itemClasses (column, item) {
|
||||
return [
|
||||
`${this.prefixCls}-filter-select-item`,
|
||||
{
|
||||
[`${this.prefixCls}-filter-select-item-selected`]: column._filterChecked[0] === item.value
|
||||
}
|
||||
];
|
||||
},
|
||||
itemAllClasses (column) {
|
||||
return [
|
||||
`${this.prefixCls}-filter-select-item`,
|
||||
{
|
||||
[`${this.prefixCls}-filter-select-item-selected`]: !column._filterChecked.length
|
||||
}
|
||||
];
|
||||
},
|
||||
renderHeader (column, $index) {
|
||||
if ('renderHeader' in this.columns[$index]) {
|
||||
return this.columns[$index].renderHeader(column, $index);
|
||||
} else {
|
||||
return column.title || '#';
|
||||
}
|
||||
},
|
||||
selectAll () {
|
||||
const status = !this.isSelectAll;
|
||||
this.$parent.selectAll(status);
|
||||
},
|
||||
handleSort (index, type) {
|
||||
if (this.columns[index]._sortType === type) {
|
||||
type = 'normal';
|
||||
}
|
||||
this.$parent.handleSort(index, type);
|
||||
},
|
||||
handleFilter (index) {
|
||||
this.$parent.handleFilter(index);
|
||||
},
|
||||
handleSelect (index, value) {
|
||||
this.$parent.handleFilterSelect(index, value);
|
||||
},
|
||||
handleReset (index) {
|
||||
this.$parent.handleFilterReset(index);
|
||||
},
|
||||
handleFilterHide (index) {
|
||||
this.$parent.handleFilterHide(index);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,680 +0,0 @@
|
|||
<template>
|
||||
<div :class="wrapClasses" :style="styles">
|
||||
<div :class="classes">
|
||||
<div :class="[prefixCls + '-title']" v-if="showSlotHeader" v-el:title><slot name="header"></slot></div>
|
||||
<div :class="[prefixCls + '-header']" v-if="showHeader" v-el:header @mousewheel="handleMouseWheel">
|
||||
<table-head
|
||||
:prefix-cls="prefixCls"
|
||||
:style="tableStyle"
|
||||
:columns="cloneColumns"
|
||||
:obj-data="objData"
|
||||
:columns-width="columnsWidth"
|
||||
:data="rebuildData"></table-head>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-body']" :style="bodyStyle" v-el:body @scroll="handleBodyScroll"
|
||||
v-show="!((!!noDataText && (!data || data.length === 0)) || (!!noFilteredDataText && (!rebuildData || rebuildData.length === 0)))">
|
||||
<table-body
|
||||
v-ref:tbody
|
||||
:prefix-cls="prefixCls"
|
||||
:style="tableStyle"
|
||||
:columns="cloneColumns"
|
||||
:data="rebuildData"
|
||||
:columns-width="columnsWidth"
|
||||
:obj-data="objData"></table-body>
|
||||
</div>
|
||||
<div
|
||||
:class="[prefixCls + '-tip']"
|
||||
v-else>
|
||||
<table cellspacing="0" cellpadding="0" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td :style="{ 'height': bodyStyle.height }">
|
||||
{{{!data || data.length === 0 ? noDataText : noFilteredDataText}}}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-fixed']" :style="fixedTableStyle" v-if="isLeftFixed">
|
||||
<div :class="[prefixCls + '-fixed-header']" v-if="showHeader">
|
||||
<table-head
|
||||
fixed="left"
|
||||
:prefix-cls="prefixCls"
|
||||
:style="fixedTableStyle"
|
||||
:columns="leftFixedColumns"
|
||||
:obj-data="objData"
|
||||
:columns-width.sync="columnsWidth"
|
||||
:data="rebuildData"></table-head>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-fixed-body']" :style="fixedBodyStyle" v-el:fixed-body>
|
||||
<table-body
|
||||
fixed="left"
|
||||
:prefix-cls="prefixCls"
|
||||
:style="fixedTableStyle"
|
||||
:columns="leftFixedColumns"
|
||||
:data="rebuildData"
|
||||
:columns-width="columnsWidth"
|
||||
:obj-data="objData"></table-body>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-fixed-right']" :style="fixedRightTableStyle" v-if="isRightFixed">
|
||||
<div :class="[prefixCls + '-fixed-header']" v-if="showHeader">
|
||||
<table-head
|
||||
fixed="right"
|
||||
:prefix-cls="prefixCls"
|
||||
:style="fixedRightTableStyle"
|
||||
:columns="rightFixedColumns"
|
||||
:obj-data="objData"
|
||||
:columns-width.sync="columnsWidth"
|
||||
:data="rebuildData"></table-head>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-fixed-body']" :style="fixedBodyStyle" v-el:fixed-right-body>
|
||||
<table-body
|
||||
fixed="right"
|
||||
:prefix-cls="prefixCls"
|
||||
:style="fixedRightTableStyle"
|
||||
:columns="rightFixedColumns"
|
||||
:data="rebuildData"
|
||||
:columns-width="columnsWidth"
|
||||
:obj-data="objData"></table-body>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-footer']" v-if="showSlotFooter" v-el:footer><slot name="footer"></slot></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import tableHead from './table-head.vue';
|
||||
import tableBody from './table-body.vue';
|
||||
import { oneOf, getStyle, deepCopy, getScrollBarSize } from '../../utils/assist';
|
||||
import { t } from '../../locale';
|
||||
import Csv from '../../utils/csv';
|
||||
import ExportCsv from './export-csv';
|
||||
const prefixCls = 'ivu-table';
|
||||
|
||||
export default {
|
||||
components: { tableHead, tableBody },
|
||||
props: {
|
||||
data: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small', 'large', 'default']);
|
||||
}
|
||||
},
|
||||
width: {
|
||||
type: [Number, String]
|
||||
},
|
||||
height: {
|
||||
type: [Number, String]
|
||||
},
|
||||
stripe: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showHeader: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
highlightRow: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
rowClassName: {
|
||||
type: Function,
|
||||
default () {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
content: {
|
||||
type: Object
|
||||
},
|
||||
noDataText: {
|
||||
type: String,
|
||||
default () {
|
||||
return t('i.table.noDataText');
|
||||
}
|
||||
},
|
||||
noFilteredDataText: {
|
||||
type: String,
|
||||
default () {
|
||||
return t('i.table.noFilteredDataText');
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
ready: false,
|
||||
tableWidth: 0,
|
||||
columnsWidth: {},
|
||||
prefixCls: prefixCls,
|
||||
compiledUids: [],
|
||||
objData: this.makeObjData(), // checkbox or highlight-row
|
||||
rebuildData: [], // for sort or filter
|
||||
cloneColumns: this.makeColumns(),
|
||||
showSlotHeader: true,
|
||||
showSlotFooter: true,
|
||||
bodyHeight: 0,
|
||||
bodyRealHeight: 0,
|
||||
scrollBarWidth: getScrollBarSize()
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
wrapClasses () {
|
||||
return [
|
||||
`${prefixCls}-wrapper`,
|
||||
{
|
||||
[`${prefixCls}-hide`]: !this.ready,
|
||||
[`${prefixCls}-with-header`]: this.showSlotHeader,
|
||||
[`${prefixCls}-with-footer`]: this.showSlotFooter
|
||||
}
|
||||
];
|
||||
},
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-${this.size}`]: !!this.size,
|
||||
[`${prefixCls}-border`]: this.border,
|
||||
[`${prefixCls}-stripe`]: this.stripe,
|
||||
[`${prefixCls}-with-fixed-top`]: !!this.height
|
||||
}
|
||||
];
|
||||
},
|
||||
styles () {
|
||||
let style = {};
|
||||
if (this.height) {
|
||||
const height = (this.isLeftFixed || this.isRightFixed) ? parseInt(this.height) + this.scrollBarWidth : parseInt(this.height);
|
||||
style.height = `${height}px`;
|
||||
}
|
||||
if (this.width) style.width = `${this.width}px`;
|
||||
return style;
|
||||
},
|
||||
tableStyle () {
|
||||
let style = {};
|
||||
if (this.tableWidth !== 0) {
|
||||
let width = '';
|
||||
if (this.bodyHeight === 0) {
|
||||
width = this.tableWidth;
|
||||
} else {
|
||||
if (this.bodyHeight > this.bodyRealHeight) {
|
||||
width = this.tableWidth;
|
||||
} else {
|
||||
width = this.tableWidth - this.scrollBarWidth;
|
||||
}
|
||||
}
|
||||
// const width = this.bodyHeight === 0 ? this.tableWidth : this.tableWidth - this.scrollBarWidth;
|
||||
style.width = `${width}px`;
|
||||
}
|
||||
return style;
|
||||
},
|
||||
fixedTableStyle () {
|
||||
let style = {};
|
||||
let width = 0;
|
||||
this.leftFixedColumns.forEach((col) => {
|
||||
if (col.fixed && col.fixed === 'left') width += col._width;
|
||||
});
|
||||
style.width = `${width}px`;
|
||||
return style;
|
||||
},
|
||||
fixedRightTableStyle () {
|
||||
let style = {};
|
||||
let width = 0;
|
||||
this.rightFixedColumns.forEach((col) => {
|
||||
if (col.fixed && col.fixed === 'right') width += col._width;
|
||||
});
|
||||
width += this.scrollBarWidth;
|
||||
style.width = `${width}px`;
|
||||
return style;
|
||||
},
|
||||
bodyStyle () {
|
||||
let style = {};
|
||||
if (this.bodyHeight !== 0) {
|
||||
// add a height to resolve scroll bug when browser has a scrollBar in fixed type and height prop
|
||||
const height = (this.isLeftFixed || this.isRightFixed) ? this.bodyHeight + this.scrollBarWidth : this.bodyHeight;
|
||||
style.height = `${height}px`;
|
||||
}
|
||||
return style;
|
||||
},
|
||||
fixedBodyStyle () {
|
||||
let style = {};
|
||||
if (this.bodyHeight !== 0) {
|
||||
let height = this.bodyHeight + this.scrollBarWidth - 1;
|
||||
|
||||
if (this.width && this.width < this.tableWidth){
|
||||
height = this.bodyHeight;
|
||||
}
|
||||
// style.height = this.scrollBarWidth > 0 ? `${this.bodyHeight}px` : `${this.bodyHeight - 1}px`;
|
||||
style.height = this.scrollBarWidth > 0 ? `${height}px` : `${height - 1}px`;
|
||||
}
|
||||
return style;
|
||||
},
|
||||
leftFixedColumns () {
|
||||
let left = [];
|
||||
let other = [];
|
||||
this.cloneColumns.forEach((col) => {
|
||||
if (col.fixed && col.fixed === 'left') {
|
||||
left.push(col);
|
||||
} else {
|
||||
other.push(col);
|
||||
}
|
||||
});
|
||||
return left.concat(other);
|
||||
},
|
||||
rightFixedColumns () {
|
||||
let right = [];
|
||||
let other = [];
|
||||
this.cloneColumns.forEach((col) => {
|
||||
if (col.fixed && col.fixed === 'right') {
|
||||
right.push(col);
|
||||
} else {
|
||||
other.push(col);
|
||||
}
|
||||
});
|
||||
return right.concat(other);
|
||||
},
|
||||
isLeftFixed () {
|
||||
return this.columns.some(col => col.fixed && col.fixed === 'left');
|
||||
},
|
||||
isRightFixed () {
|
||||
return this.columns.some(col => col.fixed && col.fixed === 'right');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rowClsName (index) {
|
||||
return this.rowClassName(this.data[index], index);
|
||||
},
|
||||
handleResize () {
|
||||
this.$nextTick(() => {
|
||||
const allWidth = !this.columns.some(cell => !cell.width); // each column set a width
|
||||
if (allWidth) {
|
||||
this.tableWidth = this.columns.map(cell => cell.width).reduce((a, b) => a + b);
|
||||
} else {
|
||||
this.tableWidth = parseInt(getStyle(this.$el, 'width')) - 1;
|
||||
}
|
||||
this.columnsWidth = {};
|
||||
this.$nextTick(() => {
|
||||
let columnsWidth = {};
|
||||
let autoWidthIndex = -1;
|
||||
if (allWidth) autoWidthIndex = this.cloneColumns.findIndex(cell => !cell.width);//todo 这行可能有问题
|
||||
|
||||
if (this.data.length) {
|
||||
const $td = this.$refs.tbody.$el.querySelectorAll('tbody tr')[0].querySelectorAll('td');
|
||||
for (let i = 0; i < $td.length; i++) { // can not use forEach in Firefox
|
||||
const column = this.cloneColumns[i];
|
||||
|
||||
let width = parseInt(getStyle($td[i], 'width'));
|
||||
if (i === autoWidthIndex) {
|
||||
width = parseInt(getStyle($td[i], 'width')) - 1;
|
||||
}
|
||||
if (column.width) width = column.width;
|
||||
|
||||
this.cloneColumns[i]._width = width;
|
||||
|
||||
columnsWidth[column._index] = {
|
||||
width: width
|
||||
};
|
||||
}
|
||||
this.columnsWidth = columnsWidth;
|
||||
}
|
||||
});
|
||||
// get table real height,for fixed when set height prop,but height < table's height,show scrollBarWidth
|
||||
this.bodyRealHeight = parseInt(getStyle(this.$refs.tbody.$el, 'height'));
|
||||
});
|
||||
},
|
||||
handleMouseIn (_index) {
|
||||
if (this.objData[_index]._isHover) return;
|
||||
this.objData[_index]._isHover = true;
|
||||
},
|
||||
handleMouseOut (_index) {
|
||||
this.objData[_index]._isHover = false;
|
||||
},
|
||||
highlightCurrentRow (_index) {
|
||||
if (!this.highlightRow || this.objData[_index]._isHighlight) return;
|
||||
|
||||
let oldIndex = -1;
|
||||
for (let i in this.objData) {
|
||||
if (this.objData[i]._isHighlight) {
|
||||
oldIndex = parseInt(i);
|
||||
this.objData[i]._isHighlight = false;
|
||||
}
|
||||
}
|
||||
this.objData[_index]._isHighlight = true;
|
||||
const oldData = oldIndex < 0 ? null : JSON.parse(JSON.stringify(this.data[oldIndex]));
|
||||
this.$emit('on-current-change', JSON.parse(JSON.stringify(this.data[_index])), oldData);
|
||||
},
|
||||
clickCurrentRow (_index) {
|
||||
this.highlightCurrentRow (_index);
|
||||
this.$emit('on-row-click', JSON.parse(JSON.stringify(this.data[_index])));
|
||||
},
|
||||
dblclickCurrentRow (_index) {
|
||||
this.highlightCurrentRow (_index);
|
||||
this.$emit('on-row-dblclick', JSON.parse(JSON.stringify(this.data[_index])));
|
||||
},
|
||||
getSelection () {
|
||||
let selectionIndexes = [];
|
||||
for (let i in this.objData) {
|
||||
if (this.objData[i]._isChecked) selectionIndexes.push(parseInt(i));
|
||||
}
|
||||
return JSON.parse(JSON.stringify(this.data.filter((data, index) => selectionIndexes.indexOf(index) > -1)));
|
||||
},
|
||||
toggleSelect (_index) {
|
||||
let data = {};
|
||||
|
||||
for (let i in this.objData) {
|
||||
if (parseInt(i) === _index) {
|
||||
data = this.objData[i];
|
||||
}
|
||||
}
|
||||
const status = !data._isChecked;
|
||||
|
||||
this.objData[_index]._isChecked = status;
|
||||
|
||||
const selection = this.getSelection();
|
||||
if (status) {
|
||||
this.$emit('on-select', selection, JSON.parse(JSON.stringify(this.data[_index])));
|
||||
}
|
||||
this.$emit('on-selection-change', selection);
|
||||
},
|
||||
selectAll (status) {
|
||||
// this.rebuildData.forEach((data) => {
|
||||
// if(this.objData[data._index]._isDisabled){
|
||||
// this.objData[data._index]._isChecked = false;
|
||||
// }else{
|
||||
// this.objData[data._index]._isChecked = status;
|
||||
// }
|
||||
|
||||
// });
|
||||
for(const data of this.rebuildData){
|
||||
if(this.objData[data._index]._isDisabled){
|
||||
continue;
|
||||
}else{
|
||||
this.objData[data._index]._isChecked = status;
|
||||
}
|
||||
}
|
||||
const selection = this.getSelection();
|
||||
if (status) {
|
||||
this.$emit('on-select-all', selection);
|
||||
}
|
||||
this.$emit('on-selection-change', selection);
|
||||
},
|
||||
fixedHeader () {
|
||||
if (this.height) {
|
||||
this.$nextTick(() => {
|
||||
const titleHeight = parseInt(getStyle(this.$els.title, 'height')) || 0;
|
||||
const headerHeight = parseInt(getStyle(this.$els.header, 'height')) || 0;
|
||||
const footerHeight = parseInt(getStyle(this.$els.footer, 'height')) || 0;
|
||||
this.bodyHeight = this.height - titleHeight - headerHeight - footerHeight;
|
||||
});
|
||||
} else {
|
||||
this.bodyHeight = 0;
|
||||
}
|
||||
},
|
||||
hideColumnFilter () {
|
||||
this.cloneColumns.forEach((col) => col._filterVisible = false);
|
||||
},
|
||||
handleBodyScroll (event) {
|
||||
if (this.showHeader) this.$els.header.scrollLeft = event.target.scrollLeft;
|
||||
if (this.isLeftFixed) this.$els.fixedBody.scrollTop = event.target.scrollTop;
|
||||
if (this.isRightFixed) this.$els.fixedRightBody.scrollTop = event.target.scrollTop;
|
||||
this.hideColumnFilter();
|
||||
},
|
||||
handleMouseWheel (event) {
|
||||
const deltaX = event.deltaX;
|
||||
const $body = this.$els.body;
|
||||
|
||||
if (deltaX > 0) {
|
||||
$body.scrollLeft = $body.scrollLeft + 10;
|
||||
} else {
|
||||
$body.scrollLeft = $body.scrollLeft - 10;
|
||||
}
|
||||
},
|
||||
sortData (data, type, index) {
|
||||
const key = this.cloneColumns[index].key;
|
||||
data.sort((a, b) => {
|
||||
if (this.cloneColumns[index].sortMethod) {
|
||||
return this.cloneColumns[index].sortMethod(a[key], b[key], type);
|
||||
} else {
|
||||
if (type === 'asc') {
|
||||
return a[key] > b[key] ? 1 : -1;
|
||||
} else if (type === 'desc') {
|
||||
return a[key] < b[key] ? 1 : -1;
|
||||
}
|
||||
}
|
||||
});
|
||||
return data;
|
||||
},
|
||||
handleSort (index, type) {
|
||||
this.cloneColumns.forEach((col) => col._sortType = 'normal');
|
||||
|
||||
const key = this.cloneColumns[index].key;
|
||||
if (this.cloneColumns[index].sortable !== 'custom') { // custom is for remote sort
|
||||
if (type === 'normal') {
|
||||
this.rebuildData = this.makeDataWithFilter();
|
||||
} else {
|
||||
this.rebuildData = this.sortData(this.rebuildData, type, index);
|
||||
}
|
||||
}
|
||||
this.cloneColumns[index]._sortType = type;
|
||||
|
||||
this.$emit('on-sort-change', {
|
||||
column: JSON.parse(JSON.stringify(this.columns[this.cloneColumns[index]._index])),
|
||||
key: key,
|
||||
order: type
|
||||
});
|
||||
},
|
||||
handleFilterHide (index) { // clear checked that not filter now
|
||||
if (!this.cloneColumns[index]._isFiltered) this.cloneColumns[index]._filterChecked = [];
|
||||
},
|
||||
filterData (data, column) {
|
||||
return data.filter((row) => {
|
||||
let status = !column._filterChecked.length;
|
||||
for (let i = 0; i < column._filterChecked.length; i++) {
|
||||
status = column.filterMethod(column._filterChecked[i], row);
|
||||
if (status) break;
|
||||
}
|
||||
return status;
|
||||
});
|
||||
},
|
||||
filterOtherData (data, index) {
|
||||
this.cloneColumns.forEach((col, colIndex) => {
|
||||
if (colIndex !== index) {
|
||||
data = this.filterData(data, col);
|
||||
}
|
||||
});
|
||||
return data;
|
||||
},
|
||||
handleFilter (index) {
|
||||
const column = this.cloneColumns[index];
|
||||
let filterData = this.makeDataWithSort();
|
||||
|
||||
// filter others first, after filter this column
|
||||
filterData = this.filterOtherData(filterData, index);
|
||||
this.rebuildData = this.filterData(filterData, column);
|
||||
|
||||
this.cloneColumns[index]._isFiltered = true;
|
||||
this.cloneColumns[index]._filterVisible = false;
|
||||
},
|
||||
handleFilterSelect (index, value) {
|
||||
this.cloneColumns[index]._filterChecked = [value];
|
||||
this.handleFilter(index);
|
||||
},
|
||||
handleFilterReset (index) {
|
||||
this.cloneColumns[index]._isFiltered = false;
|
||||
this.cloneColumns[index]._filterVisible = false;
|
||||
this.cloneColumns[index]._filterChecked = [];
|
||||
|
||||
let filterData = this.makeDataWithSort();
|
||||
filterData = this.filterOtherData(filterData, index);
|
||||
this.rebuildData = filterData;
|
||||
},
|
||||
makeData () {
|
||||
let data = deepCopy(this.data);
|
||||
data.forEach((row, index) => row._index = index);
|
||||
return data;
|
||||
},
|
||||
makeDataWithSort () {
|
||||
let data = this.makeData();
|
||||
let sortType = 'normal';
|
||||
let sortIndex = -1;
|
||||
let isCustom = false;
|
||||
|
||||
for (let i = 0; i < this.cloneColumns.length; i++) {
|
||||
if (this.cloneColumns[i]._sortType !== 'normal') {
|
||||
sortType = this.cloneColumns[i]._sortType;
|
||||
sortIndex = i;
|
||||
isCustom = this.cloneColumns[i].sortable === 'custom';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sortType !== 'normal' && !isCustom) data = this.sortData(data, sortType, sortIndex);
|
||||
return data;
|
||||
},
|
||||
makeDataWithFilter () {
|
||||
let data = this.makeData();
|
||||
this.cloneColumns.forEach(col => data = this.filterData(data, col));
|
||||
return data;
|
||||
},
|
||||
makeDataWithSortAndFilter () {
|
||||
let data = this.makeDataWithSort();
|
||||
this.cloneColumns.forEach(col => data = this.filterData(data, col));
|
||||
return data;
|
||||
},
|
||||
makeObjData () {
|
||||
let data = {};
|
||||
this.data.forEach((row, index) => {
|
||||
const newRow = deepCopy(row);// todo 直接替换
|
||||
newRow._isHover = false;
|
||||
if(newRow._disabled){
|
||||
newRow._isDisabled = newRow._disabled;
|
||||
}else{
|
||||
newRow._isDisabled = false;
|
||||
}
|
||||
if (newRow._checked) {
|
||||
newRow._isChecked = newRow._checked;
|
||||
} else {
|
||||
newRow._isChecked = false;
|
||||
}
|
||||
if (newRow._highlight) {
|
||||
newRow._isHighlight = newRow._highlight;
|
||||
} else {
|
||||
newRow._isHighlight = false;
|
||||
}
|
||||
data[index] = newRow;
|
||||
});
|
||||
return data;
|
||||
},
|
||||
makeColumns () {
|
||||
let columns = deepCopy(this.columns);
|
||||
let left = [];
|
||||
let right = [];
|
||||
let center = [];
|
||||
|
||||
columns.forEach((column, index) => {
|
||||
column._index = index;
|
||||
column._width = column.width ? column.width : ''; // update in handleResize()
|
||||
column._sortType = 'normal';
|
||||
column._filterVisible = false;
|
||||
column._isFiltered = false;
|
||||
column._filterChecked = [];
|
||||
|
||||
if ('filterMultiple' in column) {
|
||||
column._filterMultiple = column.filterMultiple;
|
||||
} else {
|
||||
column._filterMultiple = true;
|
||||
}
|
||||
if ('filteredValue' in column) {
|
||||
column._filterChecked = column.filteredValue;
|
||||
column._isFiltered = true;
|
||||
}
|
||||
|
||||
if (column.fixed && column.fixed === 'left') {
|
||||
left.push(column);
|
||||
} else if (column.fixed && column.fixed === 'right') {
|
||||
right.push(column);
|
||||
} else {
|
||||
center.push(column);
|
||||
}
|
||||
});
|
||||
return left.concat(center).concat(right);
|
||||
},
|
||||
exportCsv (params) {
|
||||
if (params.filename) {
|
||||
if (params.filename.indexOf('.csv') === -1) {
|
||||
params.filename += '.csv';
|
||||
}
|
||||
} else {
|
||||
params.filename = 'table.csv';
|
||||
}
|
||||
|
||||
let columns = [];
|
||||
let datas = [];
|
||||
if (params.columns && params.data) {
|
||||
columns = params.columns;
|
||||
datas = params.data;
|
||||
} else {
|
||||
columns = this.columns;
|
||||
if (!('original' in params)) params.original = true;
|
||||
datas = params.original ? this.data : this.rebuildData;
|
||||
}
|
||||
|
||||
let noHeader = false;
|
||||
if ('noHeader' in params) noHeader = params.noHeader;
|
||||
|
||||
const data = Csv(columns, datas, ',', noHeader);
|
||||
ExportCsv.download(params.filename, data);
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
if (!this.content) this.content = this.$parent;
|
||||
this.showSlotHeader = this.$els.title.innerHTML.replace(/\n/g, '').replace(/<!--[\w\W\r\n]*?-->/gmi, '') !== '';
|
||||
this.showSlotFooter = this.$els.footer.innerHTML.replace(/\n/g, '').replace(/<!--[\w\W\r\n]*?-->/gmi, '') !== '';
|
||||
this.rebuildData = this.makeDataWithSortAndFilter();
|
||||
},
|
||||
ready () {
|
||||
this.handleResize();
|
||||
this.fixedHeader();
|
||||
this.$nextTick(() => this.ready = true);
|
||||
window.addEventListener('resize', this.handleResize, false);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('resize', this.handleResize, false);
|
||||
},
|
||||
watch: {
|
||||
data: {
|
||||
handler () {
|
||||
this.objData = this.makeObjData();
|
||||
this.rebuildData = this.makeDataWithSortAndFilter();
|
||||
this.handleResize();
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
columns: {
|
||||
handler () {
|
||||
// todo 这里有性能问题,可能是左右固定计算属性影响的
|
||||
this.cloneColumns = this.makeColumns();
|
||||
this.rebuildData = this.makeDataWithSortAndFilter();
|
||||
this.handleResize();
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
height () {
|
||||
this.fixedHeader();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue