md-iview 1.0.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. package/README.md +2 -0
  2. package/package.json +116 -0
  3. package/src/components/libs/util.js +117 -0
  4. package/src/components/md-error-page/403.less +92 -0
  5. package/src/components/md-error-page/403.vue +34 -0
  6. package/src/components/md-error-page/404.less +60 -0
  7. package/src/components/md-error-page/404.vue +34 -0
  8. package/src/components/md-error-page/500.less +73 -0
  9. package/src/components/md-error-page/500.vue +36 -0
  10. package/src/components/md-error-page/demo/index.less +22 -0
  11. package/src/components/md-error-page/demo/index.vue +97 -0
  12. package/src/components/md-form-item/index.js +3 -0
  13. package/src/components/md-icon/icon.vue +77 -0
  14. package/src/components/md-icon/icons.js +5 -0
  15. package/src/components/md-icon/index.js +11 -0
  16. package/src/components/md-icon/style/index.less +1 -0
  17. package/src/components/md-loading/index.js +55 -0
  18. package/src/components/md-loading/index.vue +53 -0
  19. package/src/components/md-loading/md-loading.js +38 -0
  20. package/src/components/md-print/demo/index.vue +260 -0
  21. package/src/components/md-print/index.js +123 -0
  22. package/src/components/md-rich-editor/index.vue +69 -0
  23. package/src/components/md-rich-editor/module/image-extend/index.js +216 -0
  24. package/src/components/md-scroll-bar/demo/index.vue +102 -0
  25. package/src/components/md-scroll-bar/index.js +3 -0
  26. package/src/components/md-scroll-bar/index.less +90 -0
  27. package/src/components/md-scroll-bar/index.vue +250 -0
  28. package/src/components/md-select/index.js +7 -0
  29. package/src/components/md-select/select.vue +841 -0
  30. package/src/components/md-shrinkable-menu/components/sidebarMenu.vue +167 -0
  31. package/src/components/md-shrinkable-menu/components/sidebarMenuShrink.vue +119 -0
  32. package/src/components/md-shrinkable-menu/demo/data/cachePage.js +1 -0
  33. package/src/components/md-shrinkable-menu/demo/data/currentPath.js +9 -0
  34. package/src/components/md-shrinkable-menu/demo/data/menu.js +575 -0
  35. package/src/components/md-shrinkable-menu/demo/data/menu2.js +1017 -0
  36. package/src/components/md-shrinkable-menu/demo/data/pageTagsList.js +153 -0
  37. package/src/components/md-shrinkable-menu/demo/index.less +297 -0
  38. package/src/components/md-shrinkable-menu/demo/index.vue +285 -0
  39. package/src/components/md-shrinkable-menu/index.vue +112 -0
  40. package/src/components/md-shrinkable-menu/sidebar.vue +195 -0
  41. package/src/components/md-shrinkable-menu/styles/menu.less +5 -0
  42. package/src/components/md-shrinkable-menu/styles/sidebar.less +363 -0
  43. package/src/components/md-split-pane/demo/index.vue +101 -0
  44. package/src/components/md-split-pane/index.js +3 -0
  45. package/src/components/md-split-pane/index.less +93 -0
  46. package/src/components/md-split-pane/index.vue +230 -0
  47. package/src/components/md-table/action-tooltip.vue +45 -0
  48. package/src/components/md-table/can-edit-v2.vue +823 -0
  49. package/src/components/md-table/can-edit.vue +723 -0
  50. package/src/components/md-table/custom-cell.vue +71 -0
  51. package/src/components/md-table/date-picker-cell-v2.vue +48 -0
  52. package/src/components/md-table/date-picker-cell.vue +39 -0
  53. package/src/components/md-table/demo/data/search.js +67 -0
  54. package/src/components/md-table/demo/data/table2csv.js +200 -0
  55. package/src/components/md-table/demo/data/table2excel.js +239 -0
  56. package/src/components/md-table/demo/data/table_data.js +251 -0
  57. package/src/components/md-table/demo/editable-table.vue +144 -0
  58. package/src/components/md-table/demo/exportable-table.vue +124 -0
  59. package/src/components/md-table/demo/widgets/header-search.vue +88 -0
  60. package/src/components/md-table/drop-down-cell-v2.vue +87 -0
  61. package/src/components/md-table/drop-down-cell.vue +81 -0
  62. package/src/components/md-table/editable-expand.vue +143 -0
  63. package/src/components/md-table/expand.vue +97 -0
  64. package/src/components/md-table/index.vue +53 -0
  65. package/src/components/md-table/iview-table/cell.vue +99 -0
  66. package/src/components/md-table/iview-table/expand.js +21 -0
  67. package/src/components/md-table/iview-table/export-csv.js +76 -0
  68. package/src/components/md-table/iview-table/header.js +16 -0
  69. package/src/components/md-table/iview-table/index.js +2 -0
  70. package/src/components/md-table/iview-table/mixin.js +31 -0
  71. package/src/components/md-table/iview-table/table-body.vue +101 -0
  72. package/src/components/md-table/iview-table/table-head.vue +311 -0
  73. package/src/components/md-table/iview-table/table-tr.vue +31 -0
  74. package/src/components/md-table/iview-table/table.vue +1026 -0
  75. package/src/components/md-table/iview-table/util.js +93 -0
  76. package/src/components/md-table/libs/table2excel.js +100 -0
  77. package/src/components/md-table/select-cell-v2.vue +64 -0
  78. package/src/components/md-table/select-cell.vue +46 -0
  79. package/src/components/md-table/table.less +76 -0
  80. package/src/components/md-toolbar/index.vue +171 -0
  81. package/src/components/md-tree/index.js +2 -0
  82. package/src/components/md-tree/node.vue +238 -0
  83. package/src/components/md-tree/render.js +17 -0
  84. package/src/components/md-tree/tree.vue +241 -0
  85. package/src/components/utilities/can.js +35 -0
  86. package/src/directives/index.js +34 -0
  87. package/src/directives/resize.js +27 -0
  88. package/src/directives/scroll.js +27 -0
  89. package/src/directives/style/bg-color.js +23 -0
  90. package/src/directives/style/color.js +23 -0
  91. package/src/directives/style/font-size.js +23 -0
  92. package/src/directives/style/height.js +23 -0
  93. package/src/directives/style/lineHeight.js +23 -0
  94. package/src/directives/style/margin.js +48 -0
  95. package/src/directives/style/opacity.js +23 -0
  96. package/src/directives/style/padding.js +48 -0
  97. package/src/directives/style/width.js +24 -0
  98. package/src/index.js +442 -0
  99. package/src/locale/lang.js +5 -0
  100. package/src/mixins/colorable.js +51 -0
  101. package/src/style/color/bezierEasing.less +110 -0
  102. package/src/style/color/colorPalette.less +75 -0
  103. package/src/style/color/colors.less +146 -0
  104. package/src/style/color/tinyColor.less +1184 -0
  105. package/src/style/common.less +72 -0
  106. package/src/style/components/_ripple.less +60 -0
  107. package/src/style/components/_shrinkable-menu.less +46 -0
  108. package/src/style/components/_toolbar.less +96 -0
  109. package/src/style/components/index.less +3 -0
  110. package/src/style/components/rich-editor.less +6 -0
  111. package/src/style/index.less +10 -0
  112. package/src/style/theme.less +155 -0
  113. package/src/utils/color.js +46 -0
  114. package/src/utils/console.js +105 -0
  115. package/src/utils/load.js +79 -0
  116. package/src/utils/mask.js +139 -0
  117. package/src/utils/mixins.js +5 -0
  118. package/src/utils/validate.js +271 -0
@@ -0,0 +1,1026 @@
1
+ <template>
2
+ <div :class="wrapClasses" :style="styles">
3
+ <div :class="classes">
4
+ <div :class="[prefixCls + '-title']" v-if="showSlotHeader" ref="title">
5
+ <slot name="header"></slot>
6
+ </div>
7
+ <div :class="[prefixCls + '-header']" v-if="showHeader" ref="header" @mousewheel="handleMouseWheel">
8
+ <table-head
9
+ :prefix-cls="prefixCls"
10
+ :styleObject="tableHeaderStyle"
11
+ :columns="cloneColumns"
12
+ :column-rows="columnRows"
13
+ :obj-data="objData"
14
+ :columns-width="columnsWidth"
15
+ :data="rebuildData"
16
+ @on-drag-move="handleDragMove"
17
+ @on-drag-up="handleDragUp"
18
+ @on-drag-down="handleDragDown"></table-head>
19
+ </div>
20
+ <div :class="[prefixCls + '-body']" :style="bodyStyle" ref="body" @scroll="handleBodyScroll"
21
+ v-show="!((!!localeNoDataText && (!data || data.length === 0)) || (!!localeNoFilteredDataText && (!rebuildData || rebuildData.length === 0)))">
22
+ <table-body
23
+ ref="tbody"
24
+ :prefix-cls="prefixCls"
25
+ :styleObject="tableStyle"
26
+ :columns="cloneColumns"
27
+ :data="rebuildData"
28
+ :columns-width="columnsWidth"
29
+ :obj-data="objData"></table-body>
30
+ </div>
31
+ <div
32
+ :class="[prefixCls + '-tip']" :style="bodyStyle" @scroll="handleBodyScroll"
33
+ v-show="((!!localeNoDataText && (!data || data.length === 0)) || (!!localeNoFilteredDataText && (!rebuildData || rebuildData.length === 0)))">
34
+ <table cellspacing="0" cellpadding="0" border="0">
35
+ <tbody>
36
+ <tr>
37
+ <td :style="{'height':bodyStyle.height,'width':`${this.headerWidth}px`}">
38
+ <span v-html="localeNoDataText" v-if="!data || data.length === 0"></span>
39
+ <span v-html="localeNoFilteredDataText" v-else></span>
40
+ </td>
41
+ </tr>
42
+ </tbody>
43
+ </table>
44
+ </div>
45
+ <div :class="[prefixCls + '-fixed']" :style="fixedTableStyle" v-if="isLeftFixed">
46
+ <div :class="fixedHeaderClasses" v-if="showHeader">
47
+ <table-head
48
+ fixed="left"
49
+ :prefix-cls="prefixCls"
50
+ :styleObject="fixedTableStyle"
51
+ :columns="leftFixedColumns"
52
+ :column-rows="columnRows"
53
+ :fixed-column-rows="leftFixedColumnRows"
54
+ :obj-data="objData"
55
+ :columns-width="columnsWidth"
56
+ :data="rebuildData"
57
+ @on-drag-move="handleDragMove"
58
+ @on-drag-up="handleDragUp"
59
+ @on-drag-down="handleDragDown"></table-head>
60
+ </div>
61
+ <div :class="[prefixCls + '-fixed-body']" :style="fixedBodyStyle" ref="fixedBody"
62
+ @mousewheel="handleFixedMousewheel" @DOMMouseScroll="handleFixedMousewheel">
63
+ <table-body
64
+ fixed="left"
65
+ :prefix-cls="prefixCls"
66
+ :styleObject="fixedTableStyle"
67
+ :columns="leftFixedColumns"
68
+ :data="rebuildData"
69
+ :columns-width="columnsWidth"
70
+ :obj-data="objData"></table-body>
71
+ </div>
72
+ </div>
73
+ <div :class="[prefixCls + '-fixed-right']" :style="fixedRightTableStyle" v-if="isRightFixed">
74
+ <div :class="fixedHeaderClasses" v-if="showHeader">
75
+ <table-head
76
+ fixed="right"
77
+ :prefix-cls="prefixCls"
78
+ :styleObject="fixedRightTableStyle"
79
+ :columns="rightFixedColumns"
80
+ :column-rows="columnRows"
81
+ :fixed-column-rows="rightFixedColumnRows"
82
+ :obj-data="objData"
83
+ :columns-width="columnsWidth"
84
+ :data="rebuildData"
85
+ @on-drag-move="handleDragMove"
86
+ @on-drag-up="handleDragUp"
87
+ @on-drag-down="handleDragDown"></table-head>
88
+ </div>
89
+ <div :class="[prefixCls + '-fixed-body']" :style="fixedBodyStyle" ref="fixedRightBody"
90
+ @mousewheel="handleFixedMousewheel" @DOMMouseScroll="handleFixedMousewheel">
91
+ <table-body
92
+ fixed="right"
93
+ :prefix-cls="prefixCls"
94
+ :styleObject="fixedRightTableStyle"
95
+ :columns="rightFixedColumns"
96
+ :data="rebuildData"
97
+ :columns-width="columnsWidth"
98
+ :obj-data="objData"></table-body>
99
+ </div>
100
+ </div>
101
+ <div :class="[prefixCls + '-fixed-right-header']" :style="fixedRightHeaderStyle" v-if="isRightFixed"></div>
102
+ <div :class="[prefixCls + '-footer']" v-if="showSlotFooter" ref="footer">
103
+ <slot name="footer"></slot>
104
+ </div>
105
+
106
+
107
+ </div>
108
+ <!--列拖动时的线条-->
109
+ <div v-show="isDragging" class="v-table-drag-line" :style="{'left':dragX+'px'}"></div>
110
+ <Spin fix size="large" v-if="loading">
111
+ <slot name="loading"></slot>
112
+ </Spin>
113
+ </div>
114
+ </template>
115
+ <script>
116
+ import tableHead from './table-head.vue';
117
+ import tableBody from './table-body.vue';
118
+ import Spin from 'iview/src/components/spin/spin.vue';
119
+
120
+ // import { oneOf, getStyle, deepCopy, getScrollBarSize } from '../../utils/assist';
121
+ import {oneOf, getStyle, deepCopy, getScrollBarSize} from 'iview/src/utils/assist';
122
+ import {on, off} from 'iview/src/utils/dom';
123
+ import Csv from 'iview/src/utils/csv';
124
+ import ExportCsv from './export-csv';
125
+ import Locale from 'iview/src/mixins/locale';
126
+ import elementResizeDetectorMaker from 'element-resize-detector';
127
+ import {getAllColumns, convertToRows, convertColumnOrder, getRandomStr} from './util';
128
+
129
+ const prefixCls = 'ivu-table';
130
+
131
+ let rowKey = 1;
132
+ let columnKey = 1;
133
+
134
+ export default {
135
+ name: 'Table',
136
+ mixins: [Locale],
137
+ components: {tableHead, tableBody, Spin},
138
+ props: {
139
+ data: {
140
+ type: Array,
141
+ default() {
142
+ return [];
143
+ }
144
+ },
145
+ columns: {
146
+ type: Array,
147
+ default() {
148
+ return [];
149
+ }
150
+ },
151
+ size: {
152
+ validator(value) {
153
+ return oneOf(value, ['small', 'large', 'default']);
154
+ }
155
+ },
156
+ width: {
157
+ type: [Number, String]
158
+ },
159
+ height: {
160
+ type: [Number, String]
161
+ },
162
+ stripe: {
163
+ type: Boolean,
164
+ default: false
165
+ },
166
+ border: {
167
+ type: Boolean,
168
+ default: false
169
+ },
170
+ showHeader: {
171
+ type: Boolean,
172
+ default: true
173
+ },
174
+ highlightRow: {
175
+ type: Boolean,
176
+ default: false
177
+ },
178
+ rowClassName: {
179
+ type: Function,
180
+ default() {
181
+ return '';
182
+ }
183
+ },
184
+ context: {
185
+ type: Object
186
+ },
187
+ noDataText: {
188
+ type: String
189
+ },
190
+ noFilteredDataText: {
191
+ type: String
192
+ },
193
+ disabledHover: {
194
+ type: Boolean
195
+ },
196
+ loading: {
197
+ type: Boolean,
198
+ default: false
199
+ }
200
+ },
201
+ data() {
202
+ const colsWithId = this.makeColumnsId(this.columns);
203
+ return {
204
+ ready: false,
205
+ tableWidth: 0,
206
+ columnsWidth: {},
207
+ prefixCls: prefixCls,
208
+ compiledUids: [],
209
+ objData: this.makeObjData(), // checkbox or highlight-row
210
+ rebuildData: [], // for sort or filter
211
+ cloneColumns: this.makeColumns(colsWithId),
212
+ columnRows: this.makeColumnRows(false, colsWithId),
213
+ leftFixedColumnRows: this.makeColumnRows('left', colsWithId),
214
+ rightFixedColumnRows: this.makeColumnRows('right', colsWithId),
215
+ allColumns: getAllColumns(colsWithId), // for multiple table-head, get columns that have no children
216
+ showSlotHeader: true,
217
+ showSlotFooter: true,
218
+ bodyHeight: 0,
219
+ scrollBarWidth: getScrollBarSize(),
220
+ currentContext: this.context,
221
+ cloneData: deepCopy(this.data), // when Cell has a button to delete row data, clickCurrentRow will throw an error, so clone a data
222
+ showVerticalScrollBar: false,
223
+ showHorizontalScrollBar: false,
224
+ headerWidth: 0,
225
+ headerHeight: 0,
226
+ isDragging: false,
227
+ dragIndex: null,
228
+ dragX: 0,
229
+ dragWidth: 0,
230
+ isResize:true
231
+ };
232
+ },
233
+ computed: {
234
+ localeNoDataText() {
235
+ if (this.noDataText === undefined) {
236
+ return this.t('i.table.noDataText');
237
+ } else {
238
+ return this.noDataText;
239
+ }
240
+ },
241
+ localeNoFilteredDataText() {
242
+ if (this.noFilteredDataText === undefined) {
243
+ return this.t('i.table.noFilteredDataText');
244
+ } else {
245
+ return this.noFilteredDataText;
246
+ }
247
+ },
248
+ wrapClasses() {
249
+ return [
250
+ `${prefixCls}-wrapper`,
251
+ {
252
+ [`${prefixCls}-hide`]: !this.ready,
253
+ [`${prefixCls}-with-header`]: this.showSlotHeader,
254
+ [`${prefixCls}-with-footer`]: this.showSlotFooter
255
+ }
256
+ ];
257
+ },
258
+ classes() {
259
+ return [
260
+ `${prefixCls}`,
261
+ {
262
+ [`${prefixCls}-${this.size}`]: !!this.size,
263
+ [`${prefixCls}-border`]: this.border,
264
+ [`${prefixCls}-stripe`]: this.stripe,
265
+ [`${prefixCls}-with-fixed-top`]: !!this.height
266
+ }
267
+ ];
268
+ },
269
+ fixedHeaderClasses() {
270
+ return [
271
+ `${prefixCls}-fixed-header`,
272
+ {
273
+ [`${prefixCls}-fixed-header-with-empty`]: !this.rebuildData.length
274
+ }
275
+ ];
276
+ },
277
+ styles() {
278
+ let style = {};
279
+ if (this.height) {
280
+ const height = parseInt(this.height);
281
+ style.height = `${height}px`;
282
+ }
283
+ if (this.width) style.width = `${this.width}px`;
284
+ return style;
285
+ },
286
+ tableStyle() {
287
+ let style = {};
288
+ if (this.tableWidth !== 0) {
289
+ let width = '';
290
+ if (this.bodyHeight === 0) {
291
+ width = this.tableWidth;
292
+ } else {
293
+ width = this.tableWidth - (this.showVerticalScrollBar ? this.scrollBarWidth : 0);
294
+ }
295
+ // const width = this.bodyHeight === 0 ? this.tableWidth : this.tableWidth - this.scrollBarWidth;
296
+ style.width = `${width}px`;
297
+ }
298
+ return style;
299
+ },
300
+ tableHeaderStyle() {
301
+ let style = {};
302
+ if (this.tableWidth !== 0) {
303
+ let width = '';
304
+ width = this.tableWidth;
305
+ style.width = `${width}px`;
306
+ }
307
+ return style;
308
+ },
309
+ fixedTableStyle() {
310
+ let style = {};
311
+ let width = 0;
312
+ this.leftFixedColumns.forEach((col) => {
313
+ if (col.fixed && col.fixed === 'left') width += col._width;
314
+ });
315
+ style.width = `${width}px`;
316
+ return style;
317
+ },
318
+ fixedRightTableStyle() {
319
+ let style = {};
320
+ let width = 0;
321
+ this.rightFixedColumns.forEach((col) => {
322
+ if (col.fixed && col.fixed === 'right') width += col._width;
323
+ });
324
+ //width += this.scrollBarWidth;
325
+ style.width = `${width}px`;
326
+ style.right = `${this.showVerticalScrollBar ? this.scrollBarWidth : 0}px`;
327
+ return style;
328
+ },
329
+ fixedRightHeaderStyle() {
330
+ let style = {};
331
+ let width = 0;
332
+ let height = this.headerHeight + 1;
333
+ if (this.showVerticalScrollBar) {
334
+ width = this.scrollBarWidth;
335
+ }
336
+ style.width = `${width}px`;
337
+ style.height = `${height}px`;
338
+ return style;
339
+ },
340
+ bodyStyle() {
341
+ let style = {};
342
+ if (this.bodyHeight !== 0) {
343
+ const height = this.bodyHeight;
344
+ style.height = `${height}px`;
345
+ }
346
+ return style;
347
+ },
348
+ fixedBodyStyle() {
349
+ let style = {};
350
+ if (this.bodyHeight !== 0) {
351
+ let height = this.bodyHeight - (this.showHorizontalScrollBar ? this.scrollBarWidth : 0);
352
+ style.height = this.showHorizontalScrollBar ? `${height}px` : `${height - 1}px`;
353
+ }
354
+ return style;
355
+ },
356
+ leftFixedColumns() {
357
+ return convertColumnOrder(this.cloneColumns, 'left');
358
+ },
359
+ rightFixedColumns() {
360
+ return convertColumnOrder(this.cloneColumns, 'right');
361
+ },
362
+ isLeftFixed() {
363
+ return this.columns.some(col => col.fixed && col.fixed === 'left');
364
+ },
365
+ isRightFixed() {
366
+ return this.columns.some(col => col.fixed && col.fixed === 'right');
367
+ }
368
+ },
369
+ methods: {
370
+ handleDragMove(val) {
371
+ this.dragX = val;
372
+ },
373
+ handleDragUp(val) {
374
+ this.isDragging = false;
375
+ let tableSize = 0;
376
+ this.cloneColumns.forEach(cell => {
377
+ let cellWidth = cell.width || cell._width;
378
+ tableSize = tableSize + cellWidth;
379
+ })
380
+ this.tableWidth = tableSize;
381
+ let bodyContentEl = this.$refs.tbody.$el;
382
+ let bodyEl = bodyContentEl.parentElement;
383
+ this.isResize = false;
384
+ if (bodyEl.offsetWidth < tableSize) {
385
+ bodyEl.classList.add(this.prefixCls + '-overflowX');
386
+ } else {
387
+ bodyEl.classList.remove(this.prefixCls + '-overflowX');
388
+ this.handleResize();
389
+ }
390
+ },
391
+ handleDragDown(val) {
392
+ this.dragX = val;
393
+ this.isDragging = true;
394
+ },
395
+ rowClsName(index) {
396
+ return this.rowClassName(this.data[index], index);
397
+ },
398
+ handleResize() {
399
+ //let tableWidth = parseInt(getStyle(this.$el, 'width')) - 1;
400
+ let tableWidth = this.$el.offsetWidth - 1;
401
+ let columnsWidth = {};
402
+ let sumMinWidth = 0;
403
+ let hasWidthColumns = [];
404
+ let noWidthColumns = [];
405
+ let maxWidthColumns = [];
406
+ let noMaxWidthColumns = [];
407
+
408
+ this.cloneColumns.forEach((col) => {
409
+ if (col.width) {
410
+ hasWidthColumns.push(col);
411
+ } else {
412
+ noWidthColumns.push(col);
413
+ if (col.minWidth) {
414
+ sumMinWidth += col.minWidth;
415
+ }
416
+ if (col.maxWidth) {
417
+ maxWidthColumns.push(col);
418
+ } else {
419
+ noMaxWidthColumns.push(col);
420
+ }
421
+ }
422
+ col._width = null;
423
+ });
424
+
425
+
426
+ let unUsableWidth = hasWidthColumns.map(cell => cell.width).reduce((a, b) => a + b, 0);
427
+ let usableWidth = tableWidth - unUsableWidth - sumMinWidth - (this.showVerticalScrollBar ? this.scrollBarWidth : 0) - 1;
428
+ let usableLength = noWidthColumns.length;
429
+ let columnWidth = 0;
430
+ if (usableWidth > 0 && usableLength > 0) {
431
+ columnWidth = parseInt(usableWidth / usableLength);
432
+ }
433
+
434
+
435
+ for (let i = 0; i < this.cloneColumns.length; i++) {
436
+ const column = this.cloneColumns[i];
437
+ let width = columnWidth + (column.minWidth ? column.minWidth : 0);
438
+ if (column.width) {
439
+ width = column.width;
440
+ } else {
441
+ if (column._width) {
442
+ width = column._width;
443
+ } else {
444
+ if (column.minWidth > width) {
445
+ width = column.minWidth;
446
+ } else if (column.maxWidth < width) {
447
+ width = column.maxWidth;
448
+ }
449
+
450
+ if (usableWidth > 0) {
451
+ usableWidth -= width - (column.minWidth ? column.minWidth : 0);
452
+ usableLength--;
453
+ if (usableLength > 0) {
454
+ columnWidth = parseInt(usableWidth / usableLength);
455
+ } else {
456
+ columnWidth = 0;
457
+ }
458
+ } else {
459
+ columnWidth = 0;
460
+ }
461
+ }
462
+ }
463
+
464
+ column._width = width;
465
+
466
+ columnsWidth[column._index] = {
467
+ width: width
468
+ };
469
+
470
+ }
471
+
472
+ if (usableWidth > 0) {
473
+ usableLength = noMaxWidthColumns.length;
474
+ columnWidth = parseInt(usableWidth / usableLength);
475
+ for (let i = 0; i < noMaxWidthColumns.length; i++) {
476
+ const column = noMaxWidthColumns[i];
477
+ let width = column._width + columnWidth;
478
+ if (usableLength > 1) {
479
+ usableLength--;
480
+ usableWidth -= columnWidth;
481
+ columnWidth = parseInt(usableWidth / usableLength);
482
+ } else {
483
+ columnWidth = 0;
484
+ }
485
+
486
+ column._width = width;
487
+
488
+ columnsWidth[column._index] = {
489
+ width: width
490
+ };
491
+
492
+ }
493
+ }
494
+
495
+
496
+ this.tableWidth = this.cloneColumns.map(cell => cell._width).reduce((a, b) => a + b, 0) + (this.showVerticalScrollBar ? this.scrollBarWidth : 0) + 1;
497
+ this.columnsWidth = columnsWidth;
498
+ this.fixedHeader();
499
+ },
500
+ handleMouseIn(_index) {
501
+ if (this.disabledHover) return;
502
+ if (this.objData[_index]._isHover) return;
503
+ this.objData[_index]._isHover = true;
504
+ },
505
+ handleMouseOut(_index) {
506
+ if (this.disabledHover) return;
507
+ this.objData[_index]._isHover = false;
508
+ },
509
+ // 通用处理 highlightCurrentRow 和 clearCurrentRow
510
+ handleCurrentRow(type, _index) {
511
+ let oldIndex = -1;
512
+ for (let i in this.objData) {
513
+ if (this.objData[i]._isHighlight) {
514
+ oldIndex = parseInt(i);
515
+ this.objData[i]._isHighlight = false;
516
+ }
517
+ }
518
+ if (type === 'highlight') this.objData[_index]._isHighlight = true;
519
+ const oldData = oldIndex < 0 ? null : JSON.parse(JSON.stringify(this.cloneData[oldIndex]));
520
+ const newData = type === 'highlight' ? JSON.parse(JSON.stringify(this.cloneData[_index])) : null;
521
+ this.$emit('on-current-change', newData, oldData);
522
+ },
523
+ highlightCurrentRow(_index) {
524
+ if (!this.highlightRow || this.objData[_index]._isHighlight) return;
525
+ this.handleCurrentRow('highlight', _index);
526
+ },
527
+ clearCurrentRow() {
528
+ if (!this.highlightRow) return;
529
+ this.handleCurrentRow('clear');
530
+ },
531
+ clickCurrentRow(_index) {
532
+ this.highlightCurrentRow(_index);
533
+ this.$emit('on-row-click', JSON.parse(JSON.stringify(this.cloneData[_index])), _index);
534
+ },
535
+ dblclickCurrentRow(_index) {
536
+ this.highlightCurrentRow(_index);
537
+ this.$emit('on-row-dblclick', JSON.parse(JSON.stringify(this.cloneData[_index])), _index);
538
+ },
539
+ getSelection() {
540
+ let selectionIndexes = [];
541
+ for (let i in this.objData) {
542
+ if (this.objData[i]._isChecked) selectionIndexes.push(parseInt(i));
543
+ }
544
+ return JSON.parse(JSON.stringify(this.data.filter((data, index) => selectionIndexes.indexOf(index) > -1)));
545
+ },
546
+ toggleSelect(_index) {
547
+ let data = {};
548
+
549
+ for (let i in this.objData) {
550
+ if (parseInt(i) === _index) {
551
+ data = this.objData[i];
552
+ break;
553
+ }
554
+ }
555
+ const status = !data._isChecked;
556
+
557
+ this.objData[_index]._isChecked = status;
558
+
559
+ const selection = this.getSelection();
560
+ this.$emit(status ? 'on-select' : 'on-select-cancel', selection, JSON.parse(JSON.stringify(this.data[_index])));
561
+ this.$emit('on-selection-change', selection);
562
+ },
563
+ toggleExpand(_index) {
564
+ let data = {};
565
+
566
+ for (let i in this.objData) {
567
+ if (parseInt(i) === _index) {
568
+ data = this.objData[i];
569
+ break;
570
+ }
571
+ }
572
+ const status = !data._isExpanded;
573
+ this.objData[_index]._isExpanded = status;
574
+ this.$emit('on-expand', JSON.parse(JSON.stringify(this.cloneData[_index])), status);
575
+ },
576
+ selectAll(status) {
577
+ // this.rebuildData.forEach((data) => {
578
+ // if(this.objData[data._index]._isDisabled){
579
+ // this.objData[data._index]._isChecked = false;
580
+ // }else{
581
+ // this.objData[data._index]._isChecked = status;
582
+ // }
583
+
584
+ // });
585
+ for (const data of this.rebuildData) {
586
+ if (this.objData[data._index]._isDisabled) {
587
+ continue;
588
+ } else {
589
+ this.objData[data._index]._isChecked = status;
590
+ }
591
+ }
592
+ const selection = this.getSelection();
593
+ if (status) {
594
+ this.$emit('on-select-all', selection);
595
+ }
596
+ this.$emit('on-selection-change', selection);
597
+ },
598
+
599
+ fixedHeader() {
600
+ if (this.height) {
601
+ this.$nextTick(() => {
602
+ const titleHeight = parseInt(getStyle(this.$refs.title, 'height')) || 0;
603
+ const headerHeight = parseInt(getStyle(this.$refs.header, 'height')) || 0;
604
+ const footerHeight = parseInt(getStyle(this.$refs.footer, 'height')) || 0;
605
+ this.bodyHeight = this.height - titleHeight - headerHeight - footerHeight;
606
+ this.$nextTick(() => this.fixedBody());
607
+ });
608
+ } else {
609
+
610
+ this.bodyHeight = 0;
611
+ this.$nextTick(() => this.fixedBody());
612
+ }
613
+ },
614
+ fixedBody() {
615
+ if (this.$refs.header) {
616
+ this.headerWidth = this.$refs.header.children[0].offsetWidth;
617
+ this.headerHeight = this.$refs.header.children[0].offsetHeight;
618
+ //this.showHorizontalScrollBar = this.headerWidth>this.$refs.header.offsetWidth;
619
+ }
620
+
621
+ if (!this.$refs.tbody || !this.data || this.data.length === 0) {
622
+ this.showVerticalScrollBar = false;
623
+ } else {
624
+ let bodyContentEl = this.$refs.tbody.$el;
625
+ let bodyEl = bodyContentEl.parentElement;
626
+ let bodyContentHeight = bodyContentEl.offsetHeight;
627
+ let bodyHeight = bodyEl.offsetHeight;
628
+
629
+ this.showHorizontalScrollBar = bodyEl.offsetWidth < bodyContentEl.offsetWidth + (this.showVerticalScrollBar ? this.scrollBarWidth : 0);
630
+ this.showVerticalScrollBar = this.bodyHeight ? bodyHeight - (this.showHorizontalScrollBar ? this.scrollBarWidth : 0) < bodyContentHeight : false;
631
+
632
+ if (this.showVerticalScrollBar) {
633
+ bodyEl.classList.add(this.prefixCls + '-overflowY');
634
+ } else {
635
+ bodyEl.classList.remove(this.prefixCls + '-overflowY');
636
+ }
637
+ if (this.showHorizontalScrollBar) {
638
+ bodyEl.classList.add(this.prefixCls + '-overflowX');
639
+ } else {
640
+ bodyEl.classList.remove(this.prefixCls + '-overflowX');
641
+ }
642
+ }
643
+ },
644
+
645
+ hideColumnFilter() {
646
+ this.cloneColumns.forEach((col) => col._filterVisible = false);
647
+ },
648
+ handleBodyScroll(event) {
649
+ if (this.showHeader) this.$refs.header.scrollLeft = event.target.scrollLeft;
650
+ if (this.isLeftFixed) this.$refs.fixedBody.scrollTop = event.target.scrollTop;
651
+ if (this.isRightFixed) this.$refs.fixedRightBody.scrollTop = event.target.scrollTop;
652
+ this.hideColumnFilter();
653
+ },
654
+ handleFixedMousewheel(event) {
655
+ let deltaY = event.deltaY;
656
+ if (!deltaY && event.detail) {
657
+ deltaY = event.detail * 40;
658
+ }
659
+ if (!deltaY && event.wheelDeltaY) {
660
+ deltaY = -event.wheelDeltaY;
661
+ }
662
+ if (!deltaY && event.wheelDelta) {
663
+ deltaY = -event.wheelDelta;
664
+ }
665
+ if (!deltaY) return;
666
+ const body = this.$refs.body;
667
+ const currentScrollTop = body.scrollTop;
668
+ if (deltaY < 0 && currentScrollTop !== 0) {
669
+ event.preventDefault();
670
+ }
671
+ if (deltaY > 0 && body.scrollHeight - body.clientHeight > currentScrollTop) {
672
+ event.preventDefault();
673
+ }
674
+ //body.scrollTop += deltaY;
675
+ let step = 0;
676
+ let timeId = setInterval(() => {
677
+ step += 5;
678
+ if (deltaY > 0) {
679
+ body.scrollTop += 2;
680
+ } else {
681
+ body.scrollTop -= 2;
682
+ }
683
+ if (step >= Math.abs(deltaY)) {
684
+ clearInterval(timeId);
685
+ }
686
+ }, 5);
687
+ },
688
+ handleMouseWheel(event) {
689
+ const deltaX = event.deltaX;
690
+ const $body = this.$refs.body;
691
+
692
+ if (deltaX > 0) {
693
+ $body.scrollLeft = $body.scrollLeft + 10;
694
+ } else {
695
+ $body.scrollLeft = $body.scrollLeft - 10;
696
+ }
697
+ },
698
+ sortData(data, type, index) {
699
+ const key = this.cloneColumns[index].key;
700
+ data.sort((a, b) => {
701
+ if (this.cloneColumns[index].sortMethod) {
702
+ return this.cloneColumns[index].sortMethod(a[key], b[key], type);
703
+ } else {
704
+ if (type === 'asc') {
705
+ return a[key] > b[key] ? 1 : -1;
706
+ } else if (type === 'desc') {
707
+ return a[key] < b[key] ? 1 : -1;
708
+ }
709
+ }
710
+ });
711
+ return data;
712
+ },
713
+ handleSort(_index, type) {
714
+ const index = this.GetOriginalIndex(_index);
715
+ this.cloneColumns.forEach((col) => col._sortType = 'normal');
716
+
717
+ const key = this.cloneColumns[index].key;
718
+ if (this.cloneColumns[index].sortable !== 'custom') { // custom is for remote sort
719
+ if (type === 'normal') {
720
+ this.rebuildData = this.makeDataWithFilter();
721
+ } else {
722
+ this.rebuildData = this.sortData(this.rebuildData, type, index);
723
+ }
724
+ }
725
+ this.cloneColumns[index]._sortType = type;
726
+
727
+ this.$emit('on-sort-change', {
728
+ column: JSON.parse(JSON.stringify(this.allColumns[this.cloneColumns[index]._index])),
729
+ key: key,
730
+ order: type
731
+ });
732
+ },
733
+ handleFilterHide(index) { // clear checked that not filter now
734
+ if (!this.cloneColumns[index]._isFiltered) this.cloneColumns[index]._filterChecked = [];
735
+ },
736
+ filterData(data, column) {
737
+ return data.filter((row) => {
738
+ //如果定义了远程过滤方法则忽略此方法
739
+ if (typeof column.filterRemote === 'function') return true;
740
+
741
+ let status = !column._filterChecked.length;
742
+ for (let i = 0; i < column._filterChecked.length; i++) {
743
+ status = column.filterMethod(column._filterChecked[i], row);
744
+ if (status) break;
745
+ }
746
+ return status;
747
+ });
748
+ },
749
+ filterOtherData(data, index) {
750
+ let column = this.cloneColumns[index];
751
+ if (typeof column.filterRemote === 'function') {
752
+ column.filterRemote.call(this.$parent, column._filterChecked, column.key, column);
753
+ }
754
+
755
+ this.cloneColumns.forEach((col, colIndex) => {
756
+ if (colIndex !== index) {
757
+ data = this.filterData(data, col);
758
+ }
759
+ });
760
+ return data;
761
+ },
762
+ handleFilter(index) {
763
+ const column = this.cloneColumns[index];
764
+ let filterData = this.makeDataWithSort();
765
+
766
+ // filter others first, after filter this column
767
+ filterData = this.filterOtherData(filterData, index);
768
+ this.rebuildData = this.filterData(filterData, column);
769
+
770
+ this.cloneColumns[index]._isFiltered = true;
771
+ this.cloneColumns[index]._filterVisible = false;
772
+ this.$emit('on-filter-change', column);
773
+ },
774
+ /**
775
+ * #2832
776
+ * 应该区分当前表头的 column 是左固定还是右固定
777
+ * 否则执行到 $parent 时,方法的 index 与 cloneColumns 的 index 是不对应的
778
+ * 左固定和右固定,要区分对待
779
+ * 所以,此方法用来获取正确的 index
780
+ * */
781
+ GetOriginalIndex(_index) {
782
+ return this.cloneColumns.findIndex(item => item._index === _index);
783
+ },
784
+ handleFilterSelect(_index, value) {
785
+ const index = this.GetOriginalIndex(_index);
786
+ this.cloneColumns[index]._filterChecked = [value];
787
+ this.handleFilter(index);
788
+ },
789
+ handleFilterReset(_index) {
790
+ const index = this.GetOriginalIndex(_index);
791
+ this.cloneColumns[index]._isFiltered = false;
792
+ this.cloneColumns[index]._filterVisible = false;
793
+ this.cloneColumns[index]._filterChecked = [];
794
+
795
+ let filterData = this.makeDataWithSort();
796
+ filterData = this.filterOtherData(filterData, index);
797
+ this.rebuildData = filterData;
798
+ this.$emit('on-filter-change', this.cloneColumns[index]);
799
+ },
800
+ makeData() {
801
+ let data = deepCopy(this.data);
802
+ data.forEach((row, index) => {
803
+ row._index = index;
804
+ row._rowKey = rowKey++;
805
+ });
806
+ return data;
807
+ },
808
+ makeDataWithSort() {
809
+ let data = this.makeData();
810
+ let sortType = 'normal';
811
+ let sortIndex = -1;
812
+ let isCustom = false;
813
+
814
+ for (let i = 0; i < this.cloneColumns.length; i++) {
815
+ if (this.cloneColumns[i]._sortType !== 'normal') {
816
+ sortType = this.cloneColumns[i]._sortType;
817
+ sortIndex = i;
818
+ isCustom = this.cloneColumns[i].sortable === 'custom';
819
+ break;
820
+ }
821
+ }
822
+ if (sortType !== 'normal' && !isCustom) data = this.sortData(data, sortType, sortIndex);
823
+ return data;
824
+ },
825
+ makeDataWithFilter() {
826
+ let data = this.makeData();
827
+ this.cloneColumns.forEach(col => data = this.filterData(data, col));
828
+ return data;
829
+ },
830
+ makeDataWithSortAndFilter() {
831
+ let data = this.makeDataWithSort();
832
+ this.cloneColumns.forEach(col => data = this.filterData(data, col));
833
+ return data;
834
+ },
835
+ makeObjData() {
836
+ let data = {};
837
+ this.data.forEach((row, index) => {
838
+ const newRow = deepCopy(row);// todo 直接替换
839
+ newRow._isHover = false;
840
+ if (newRow._disabled) {
841
+ newRow._isDisabled = newRow._disabled;
842
+ } else {
843
+ newRow._isDisabled = false;
844
+ }
845
+ if (newRow._checked) {
846
+ newRow._isChecked = newRow._checked;
847
+ } else {
848
+ newRow._isChecked = false;
849
+ }
850
+ if (newRow._expanded) {
851
+ newRow._isExpanded = newRow._expanded;
852
+ } else {
853
+ newRow._isExpanded = false;
854
+ }
855
+ if (newRow._highlight) {
856
+ newRow._isHighlight = newRow._highlight;
857
+ } else {
858
+ newRow._isHighlight = false;
859
+ }
860
+ data[index] = newRow;
861
+ });
862
+ return data;
863
+ },
864
+ // 修改列,设置一个隐藏的 id,便于后面的多级表头寻找对应的列,否则找不到
865
+ makeColumnsId(columns) {
866
+ return columns.map(item => {
867
+ if ('children' in item) item.children = this.makeColumnsId(item.children);
868
+ item.__id = getRandomStr(6);
869
+ return item;
870
+ });
871
+ },
872
+ makeColumns(cols) {
873
+ // 在 data 时,this.allColumns 暂时为 undefined
874
+ let columns = deepCopy(getAllColumns(cols));
875
+ let left = [];
876
+ let right = [];
877
+ let center = [];
878
+
879
+ columns.forEach((column, index) => {
880
+ column._index = index;
881
+ column._columnKey = columnKey++;
882
+ column._width = column.width ? column.width : ''; // update in handleResize()
883
+ column._sortType = 'normal';
884
+ column._filterVisible = false;
885
+ column._isFiltered = false;
886
+ column._filterChecked = [];
887
+
888
+ if ('filterMultiple' in column) {
889
+ column._filterMultiple = column.filterMultiple;
890
+ } else {
891
+ column._filterMultiple = true;
892
+ }
893
+ if ('filteredValue' in column) {
894
+ column._filterChecked = column.filteredValue;
895
+ column._isFiltered = true;
896
+ }
897
+
898
+ if ('sortType' in column) {
899
+ column._sortType = column.sortType;
900
+ }
901
+
902
+ if (column.fixed && column.fixed === 'left') {
903
+ left.push(column);
904
+ } else if (column.fixed && column.fixed === 'right') {
905
+ right.push(column);
906
+ } else {
907
+ center.push(column);
908
+ }
909
+ });
910
+ return left.concat(center).concat(right);
911
+ },
912
+ // create a multiple table-head
913
+ makeColumnRows(fixedType, cols) {
914
+ return convertToRows(cols, fixedType);
915
+ },
916
+ exportCsv(params) {
917
+ if (params.filename) {
918
+ if (params.filename.indexOf('.csv') === -1) {
919
+ params.filename += '.csv';
920
+ }
921
+ } else {
922
+ params.filename = 'table.csv';
923
+ }
924
+
925
+ let columns = [];
926
+ let datas = [];
927
+ if (params.columns && params.data) {
928
+ columns = params.columns;
929
+ datas = params.data;
930
+ } else {
931
+ columns = this.allColumns;
932
+ if (!('original' in params)) params.original = true;
933
+ datas = params.original ? this.data : this.rebuildData;
934
+ }
935
+
936
+ let noHeader = false;
937
+ if ('noHeader' in params) noHeader = params.noHeader;
938
+
939
+ const data = Csv(columns, datas, params, noHeader);
940
+ if (params.callback) params.callback(data);
941
+ else ExportCsv.download(params.filename, data);
942
+ }
943
+ },
944
+ created() {
945
+ if (!this.context) this.currentContext = this.$parent;
946
+ this.showSlotHeader = this.$slots.header !== undefined;
947
+ this.showSlotFooter = this.$slots.footer !== undefined;
948
+ this.rebuildData = this.makeDataWithSortAndFilter();
949
+
950
+ },
951
+ mounted() {
952
+ this.handleResize();
953
+ this.$nextTick(() => this.ready = true);
954
+
955
+ on(window, 'resize', this.handleResize);
956
+ this.observer = elementResizeDetectorMaker();
957
+ this.observer.listenTo(this.$el, ()=>{
958
+ if (this.isResize) {
959
+ this.handleResize()
960
+ }
961
+ });
962
+
963
+ this.$on('on-visible-change', (val) => {
964
+ if (val) {
965
+ this.handleResize();
966
+ }
967
+ });
968
+ },
969
+ beforeDestroy() {
970
+ off(window, 'resize', this.handleResize);
971
+ this.observer.removeListener(this.$el, this.handleResize);
972
+ },
973
+ watch: {
974
+ data: {
975
+ handler() {
976
+ const oldDataLen = this.rebuildData.length;
977
+ this.objData = this.makeObjData();
978
+ this.rebuildData = this.makeDataWithSortAndFilter();
979
+ this.handleResize();
980
+ if (!oldDataLen) {
981
+ this.fixedHeader();
982
+ }
983
+ // here will trigger before clickCurrentRow, so use async
984
+ setTimeout(() => {
985
+ this.cloneData = deepCopy(this.data);
986
+ }, 0);
987
+ },
988
+ deep: true
989
+ },
990
+ columns: {
991
+ handler() {
992
+ // todo 这里有性能问题,可能是左右固定计算属性影响的
993
+ const colsWithId = this.makeColumnsId(this.columns);
994
+ this.allColumns = getAllColumns(colsWithId);
995
+ this.cloneColumns = this.makeColumns(colsWithId);
996
+
997
+ this.columnRows = this.makeColumnRows(false, colsWithId);
998
+ this.leftFixedColumnRows = this.makeColumnRows('left', colsWithId);
999
+ this.rightFixedColumnRows = this.makeColumnRows('right', colsWithId);
1000
+ this.rebuildData = this.makeDataWithSortAndFilter();
1001
+ this.handleResize();
1002
+ },
1003
+ deep: true
1004
+ },
1005
+ height() {
1006
+ this.handleResize();
1007
+ },
1008
+ showHorizontalScrollBar() {
1009
+ this.handleResize();
1010
+ },
1011
+ showVerticalScrollBar() {
1012
+ this.handleResize();
1013
+ }
1014
+ }
1015
+ };
1016
+ </script>
1017
+
1018
+ <style lang="less">
1019
+ .v-table-drag-line {
1020
+ position: absolute;
1021
+ border-right: 1px solid #d9d9d9;
1022
+ top: 0;
1023
+ bottom: 0;
1024
+ left: 0;
1025
+ }
1026
+ </style>