evui 3.3.36 → 3.3.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +40 -40
  3. package/dist/evui.common.js +1907 -1832
  4. package/dist/evui.common.js.map +1 -1
  5. package/dist/evui.umd.js +1907 -1832
  6. package/dist/evui.umd.js.map +1 -1
  7. package/dist/evui.umd.min.js +1 -1
  8. package/dist/evui.umd.min.js.map +1 -1
  9. package/dist/img/{EVUI.7f3588fb.svg → EVUI.b82ee81a.svg} +292 -292
  10. package/dist/img/{icon_mysql.7ea26d5d.svg → icon_mysql.1085fdc9.svg} +78 -78
  11. package/dist/img/{icon_oracle.9009b108.svg → icon_oracle.0572d3ee.svg} +13 -13
  12. package/dist/img/{icon_postgresql.f8fffba9.svg → icon_postgresql.ee12bde8.svg} +58 -58
  13. package/package.json +61 -61
  14. package/src/common/emitter.js +20 -20
  15. package/src/common/utils.debounce.js +223 -223
  16. package/src/common/utils.js +134 -134
  17. package/src/common/utils.table.js +78 -78
  18. package/src/common/utils.throttle.js +83 -83
  19. package/src/common/utils.tree.js +18 -18
  20. package/src/components/button/Button.vue +198 -198
  21. package/src/components/button/index.js +7 -7
  22. package/src/components/buttonGroup/ButtonGroup.vue +11 -11
  23. package/src/components/buttonGroup/index.js +7 -7
  24. package/src/components/calendar/Calendar.vue +661 -661
  25. package/src/components/calendar/index.js +7 -7
  26. package/src/components/calendar/uses.js +1272 -1272
  27. package/src/components/chart/Chart.vue +189 -192
  28. package/src/components/chart/chart.core.js +870 -870
  29. package/src/components/chart/element/element.bar.js +524 -524
  30. package/src/components/chart/element/element.bar.time.js +156 -156
  31. package/src/components/chart/element/element.heatmap.js +533 -533
  32. package/src/components/chart/element/element.line.js +339 -339
  33. package/src/components/chart/element/element.pie.js +197 -197
  34. package/src/components/chart/element/element.scatter.js +184 -184
  35. package/src/components/chart/element/element.tip.js +550 -542
  36. package/src/components/chart/helpers/helpers.canvas.js +265 -265
  37. package/src/components/chart/helpers/helpers.constant.js +206 -206
  38. package/src/components/chart/helpers/helpers.util.js +346 -338
  39. package/src/components/chart/index.js +9 -9
  40. package/src/components/chart/model/index.js +4 -4
  41. package/src/components/chart/model/model.series.js +93 -93
  42. package/src/components/chart/model/model.store.js +977 -967
  43. package/src/components/chart/plugins/plugins.interaction.js +769 -769
  44. package/src/components/chart/plugins/plugins.legend.gradient.js +602 -602
  45. package/src/components/chart/plugins/plugins.legend.js +1155 -1151
  46. package/src/components/chart/plugins/plugins.pie.js +254 -254
  47. package/src/components/chart/plugins/plugins.title.js +56 -56
  48. package/src/components/chart/plugins/plugins.tooltip.js +692 -692
  49. package/src/components/chart/scale/scale.js +848 -848
  50. package/src/components/chart/scale/scale.linear.js +38 -38
  51. package/src/components/chart/scale/scale.logarithmic.js +128 -128
  52. package/src/components/chart/scale/scale.step.js +336 -336
  53. package/src/components/chart/scale/scale.time.category.js +277 -277
  54. package/src/components/chart/scale/scale.time.js +48 -48
  55. package/src/components/chart/style/chart.scss +312 -312
  56. package/src/components/chart/uses.js +264 -252
  57. package/src/components/checkbox/Checkbox.vue +200 -200
  58. package/src/components/checkbox/index.js +7 -7
  59. package/src/components/checkboxGroup/CheckboxGroup.vue +44 -44
  60. package/src/components/checkboxGroup/index.js +7 -7
  61. package/src/components/contextMenu/ContextMenu.vue +80 -80
  62. package/src/components/contextMenu/MenuList.vue +149 -149
  63. package/src/components/contextMenu/index.js +7 -7
  64. package/src/components/contextMenu/uses.js +203 -203
  65. package/src/components/datePicker/DatePicker.vue +437 -437
  66. package/src/components/datePicker/index.js +7 -7
  67. package/src/components/datePicker/uses.js +419 -419
  68. package/src/components/grid/Grid.vue +827 -827
  69. package/src/components/grid/grid.filter.window.vue +493 -493
  70. package/src/components/grid/grid.pagination.vue +75 -75
  71. package/src/components/grid/grid.summary.vue +265 -265
  72. package/src/components/grid/grid.toolbar.vue +26 -26
  73. package/src/components/grid/index.js +11 -11
  74. package/src/components/grid/style/grid.scss +263 -263
  75. package/src/components/grid/uses.js +1002 -1007
  76. package/src/components/icon/Icon.vue +49 -49
  77. package/src/components/icon/index.js +8 -8
  78. package/src/components/inputNumber/InputNumber.vue +212 -212
  79. package/src/components/inputNumber/index.js +7 -7
  80. package/src/components/inputNumber/uses.js +217 -217
  81. package/src/components/loading/Loading.vue +125 -125
  82. package/src/components/loading/index.js +7 -7
  83. package/src/components/menu/Menu.vue +68 -68
  84. package/src/components/menu/MenuItem.vue +187 -187
  85. package/src/components/menu/index.js +7 -7
  86. package/src/components/message/Message.vue +223 -223
  87. package/src/components/message/index.js +31 -31
  88. package/src/components/messageBox/MessageBox.vue +358 -358
  89. package/src/components/messageBox/index.js +22 -22
  90. package/src/components/notification/Notification.vue +316 -316
  91. package/src/components/notification/index.js +49 -49
  92. package/src/components/pagination/Pagination.vue +271 -271
  93. package/src/components/pagination/index.js +7 -7
  94. package/src/components/pagination/pageButton.vue +30 -30
  95. package/src/components/progress/Progress.vue +139 -139
  96. package/src/components/progress/index.js +7 -7
  97. package/src/components/radio/Radio.vue +159 -159
  98. package/src/components/radio/index.js +7 -7
  99. package/src/components/radioGroup/RadioGroup.vue +41 -41
  100. package/src/components/radioGroup/index.js +7 -7
  101. package/src/components/scheduler/Scheduler.vue +149 -149
  102. package/src/components/scheduler/index.js +7 -7
  103. package/src/components/scheduler/uses.js +183 -183
  104. package/src/components/select/Select.vue +440 -440
  105. package/src/components/select/index.js +7 -7
  106. package/src/components/select/uses.js +270 -270
  107. package/src/components/slider/Slider.vue +505 -505
  108. package/src/components/slider/index.js +7 -7
  109. package/src/components/slider/uses.js +390 -390
  110. package/src/components/tabPanel/TabPanel.vue +74 -74
  111. package/src/components/tabPanel/index.js +7 -7
  112. package/src/components/tabs/Tabs.vue +517 -517
  113. package/src/components/tabs/index.js +7 -7
  114. package/src/components/textField/TextField.vue +375 -375
  115. package/src/components/textField/index.js +7 -7
  116. package/src/components/timePicker/TimePicker.vue +352 -352
  117. package/src/components/timePicker/index.js +7 -7
  118. package/src/components/toggle/Toggle.vue +115 -115
  119. package/src/components/toggle/index.js +7 -7
  120. package/src/components/tree/Tree.vue +313 -313
  121. package/src/components/tree/TreeNode.vue +293 -293
  122. package/src/components/tree/index.js +7 -7
  123. package/src/components/treeGrid/TreeGrid.vue +758 -758
  124. package/src/components/treeGrid/TreeGridNode.vue +275 -275
  125. package/src/components/treeGrid/index.js +9 -9
  126. package/src/components/treeGrid/style/treeGrid.scss +261 -261
  127. package/src/components/treeGrid/treeGrid.toolbar.vue +26 -26
  128. package/src/components/treeGrid/uses.js +867 -867
  129. package/src/components/window/Window.vue +329 -329
  130. package/src/components/window/index.js +7 -7
  131. package/src/components/window/uses.js +899 -899
  132. package/src/directives/clickoutside.js +90 -90
  133. package/src/main.js +116 -116
  134. package/src/style/components/input.scss +108 -108
  135. package/src/style/functions.scss +3 -3
  136. package/src/style/index.scss +6 -6
  137. package/src/style/lib/fonts/EVUI.svg +292 -292
  138. package/src/style/lib/icon.css +888 -888
  139. package/src/style/mixins.scss +94 -94
  140. package/src/style/themes.scss +67 -67
  141. package/src/style/variables.scss +22 -22
@@ -1,827 +1,827 @@
1
- <template>
2
- <div
3
- v-if="$slots.toolbar"
4
- class="toolbar-wrapper"
5
- :style="`width: ${gridWidth};`"
6
- >
7
- <!-- Toolbar -->
8
- <toolbar>
9
- <template #toolbarWrapper>
10
- <slot
11
- name="toolbar"
12
- :item="{ onSearch: onSearch }"
13
- />
14
- </template>
15
- </toolbar>
16
- </div>
17
- <div
18
- ref="grid-wrapper"
19
- v-resize="onResize"
20
- v-observe-visibility="{
21
- callback: onShow,
22
- once: true,
23
- }"
24
- v-bind="$attrs"
25
- class="grid-wrapper"
26
- :style="`width: ${gridWidth}; height: ${gridHeight};`"
27
- >
28
- <!-- Table -->
29
- <div
30
- v-cloak
31
- ref="grid"
32
- :class="{
33
- 'ev-grid': true,
34
- table: true,
35
- adjust: adjust,
36
- 'non-header': !showHeader,
37
- 'ev-grid--empty': !viewStore.length,
38
- }"
39
- >
40
- <!-- Header -->
41
- <div
42
- v-show="showHeader"
43
- ref="header"
44
- :class="{
45
- 'table-header': true,
46
- 'non-border': !!borderStyle,
47
- }"
48
- >
49
- <ul class="column-list">
50
- <!-- Header Checkbox -->
51
- <li
52
- v-if="useCheckbox.use"
53
- :class="{
54
- 'column': true,
55
- 'non-border': !!borderStyle,
56
- }"
57
- :style="`width: ${minWidth}px;`"
58
- >
59
- <ev-checkbox
60
- v-if="useCheckbox.use && useCheckbox.headerCheck && useCheckbox.mode !== 'single'"
61
- v-model="isHeaderChecked"
62
- @change="onCheckAll"
63
- />
64
- </li>
65
- <!-- Column List -->
66
- <template
67
- v-for="(column, index) in orderedColumns"
68
- :key="index"
69
- >
70
- <li
71
- v-if="!column.hide"
72
- :data-index="index"
73
- :class="{
74
- column: true,
75
- render: isRenderer(column),
76
- 'non-border': !!borderStyle,
77
- [column.field]: column.field,
78
- }"
79
- :style="{
80
- width: `${column.width}px`,
81
- 'min-width': `${isRenderer(column) ? rendererMinWidth : minWidth}px`,
82
- 'margin-right': (orderedColumns.length - 1 === index
83
- && hasVerticalScrollBar && hasHorizontalScrollBar) ? `${scrollWidth}px` : '0px',
84
- }"
85
- >
86
- <!-- Filter Status -->
87
- <span
88
- v-if="isFiltering && filterList[column.field]?.find(item => item.use)"
89
- class="column-filter-status"
90
- >
91
- <ev-icon icon="ev-icon-filter"/>
92
- </span>
93
- <!-- Column Name -->
94
- <span
95
- :title="column.caption"
96
- class="column-name"
97
- @click.stop="onSort(column)"
98
- >
99
- {{ column.caption }}
100
- </span>
101
- <!-- Sort Icon -->
102
- <template v-if="sortField === column.field">
103
- <ev-icon
104
- v-if="sortOrder === 'desc'"
105
- icon="ev-icon-triangle-down"
106
- />
107
- <ev-icon
108
- v-if="sortOrder === 'asc'"
109
- icon="ev-icon-triangle-up"
110
- />
111
- </template>
112
- <!-- Filter Button -->
113
- <span
114
- v-if="isFiltering"
115
- class="column-filter"
116
- @click.capture="onClickFilter(column)"
117
- >
118
- <ev-icon icon="ev-icon-hamburger2"/>
119
- </span>
120
- <!-- Column Resize -->
121
- <span
122
- class="column-resize"
123
- @mousedown.stop.left="onColumnResize(index, $event)"
124
- />
125
- </li>
126
- </template>
127
- </ul>
128
- </div>
129
- <!-- Body -->
130
- <div
131
- ref="body"
132
- :class="{
133
- 'table-body': true,
134
- 'bottom-border': !!viewStore.length,
135
- stripe: stripeStyle,
136
- 'non-border': !!borderStyle,
137
- }"
138
- @scroll="onScroll"
139
- @contextmenu="onContextMenu($event)"
140
- @contextmenu.prevent="menu.show"
141
- >
142
- <!-- vScroll Top -->
143
- <div
144
- :style="`height: ${vScrollTopHeight}px;`"
145
- class="vscroll-spacer"
146
- />
147
- <table ref="table">
148
- <tbody>
149
- <!-- Row List -->
150
- <tr
151
- v-for="(row, rowIndex) in viewStore"
152
- :key="rowIndex"
153
- :data-index="row[0]"
154
- :class="{
155
- row: true,
156
- selected: row[3],
157
- 'non-border': !!borderStyle && borderStyle !== 'rows',
158
- highlight: row[0] === highlightIdx,
159
- }"
160
- @click="onRowClick($event, row)"
161
- @dblclick="onRowDblClick($event, row)"
162
- >
163
- <!-- Row Checkbox -->
164
- <td
165
- v-if="useCheckbox.use"
166
- :class="{
167
- cell: true,
168
- 'row-checkbox': true,
169
- 'non-border': !!borderStyle,
170
- }"
171
- :style="`width: ${minWidth}px; height: ${rowHeight}px;`"
172
- >
173
- <ev-checkbox
174
- v-model="row[1]"
175
- class="row-checkbox-input"
176
- @change="onCheck($event, row)"
177
- />
178
- </td>
179
- <!-- Cell -->
180
- <template
181
- v-for="(column, cellIndex) in orderedColumns"
182
- :key="cellIndex"
183
- >
184
- <td
185
- v-if="!column.hide"
186
- :data-name="column.field"
187
- :data-index="column.index"
188
- :class="{
189
- cell: true,
190
- [column.type]: column.type,
191
- [column.align]: column.align,
192
- render: isRenderer(column),
193
- 'non-border': !!borderStyle,
194
- [column.field]: column.field,
195
- }"
196
- :style="{
197
- width: `${column.width}px`,
198
- height: `${rowHeight}px`,
199
- 'line-height': `${rowHeight}px`,
200
- 'min-width': `${isRenderer(column) ? rendererMinWidth : minWidth}px`,
201
- }"
202
- >
203
- <!-- Cell Renderer -->
204
- <div v-if="!!$slots[column.field]">
205
- <slot
206
- :name="column.field"
207
- :item="{ row, column }"
208
- />
209
- </div>
210
- <!-- Cell Value -->
211
- <template v-else>
212
- <div :title="getConvertValue(column, row[2][column.index])">
213
- {{ getConvertValue(column, row[2][column.index]) }}
214
- </div>
215
- </template>
216
- </td>
217
- </template>
218
- </tr>
219
- <tr v-if="!viewStore.length">
220
- <td class="is-empty">No records</td>
221
- </tr>
222
- </tbody>
223
- </table>
224
- <!-- vScroll Bottom -->
225
- <div
226
- :style="`height: ${vScrollBottomHeight}px;`"
227
- class="vscroll-spacer"
228
- />
229
- <!-- Context Menu -->
230
- <ev-context-menu
231
- ref="menu"
232
- :items="contextMenuItems"
233
- />
234
- </div>
235
- <!-- Resize Line -->
236
- <div
237
- v-show="showResizeLine"
238
- ref="resizeLine"
239
- class="table-resize-line"
240
- />
241
- <!-- Filter Window -->
242
- <filter-window
243
- v-show="showFilterWindow"
244
- :is-show="showFilterWindow"
245
- :target-column="currentFilter.column"
246
- :filter-items="currentFilter.items"
247
- @apply-filter="onApplyFilter"
248
- @before-close="onCloseFilterWindow"
249
- />
250
- </div>
251
- </div>
252
- <!-- Summary -->
253
- <grid-summary
254
- v-if="useSummary"
255
- :ordered-columns="orderedColumns"
256
- :stores="stores"
257
- :use-checkbox="useCheckbox.use"
258
- :style-option="{
259
- borderStyle,
260
- minWidth,
261
- rowHeight,
262
- }"
263
- :scroll-left="summaryScroll"
264
- />
265
- <!-- Pagination -->
266
- <grid-pagination
267
- v-if="usePage && !isInfinite"
268
- v-model="currentPage"
269
- :total="pageTotal"
270
- :per-page="perPage"
271
- :visible-page="visiblePage"
272
- :show-page-info="showPageInfo"
273
- :order="order"
274
- />
275
- </template>
276
-
277
- <script>
278
- import { reactive, toRefs, computed, watch, onMounted, onActivated, nextTick, ref } from 'vue';
279
- import Toolbar from './grid.toolbar';
280
- import FilterWindow from './grid.filter.window';
281
- import GridPagination from './grid.pagination';
282
- import GridSummary from './grid.summary';
283
- import {
284
- commonFunctions,
285
- scrollEvent,
286
- resizeEvent,
287
- clickEvent,
288
- checkEvent,
289
- sortEvent,
290
- filterEvent,
291
- contextMenuEvent,
292
- storeEvent,
293
- pagingEvent,
294
- } from './uses';
295
-
296
- export default {
297
- name: 'EvGrid',
298
- components: {
299
- Toolbar,
300
- FilterWindow,
301
- GridPagination,
302
- GridSummary,
303
- },
304
- props: {
305
- columns: {
306
- type: [Array],
307
- default: () => [],
308
- },
309
- rows: {
310
- type: [Array],
311
- default: () => [],
312
- },
313
- width: {
314
- type: [String, Number],
315
- default: '100%',
316
- },
317
- height: {
318
- type: [String, Number],
319
- default: '100%',
320
- },
321
- selected: {
322
- type: [Array],
323
- default: () => [],
324
- },
325
- checked: {
326
- type: [Array],
327
- default: () => [],
328
- },
329
- option: {
330
- type: Object,
331
- default: () => ({}),
332
- },
333
- },
334
- emits: {
335
- 'update:selected': null,
336
- 'click-row': null,
337
- 'dblclick-row': null,
338
- 'update:checked': null,
339
- 'check-row': null,
340
- 'check-all': null,
341
- 'page-change': null,
342
- },
343
- setup(props) {
344
- // const ROW_INDEX = 0;
345
- const ROW_CHECK_INDEX = 1;
346
- const ROW_DATA_INDEX = 2;
347
- const ROW_SELECT_INDEX = 3;
348
- const {
349
- isRenderer,
350
- getComponentName,
351
- getConvertValue,
352
- getColumnIndex,
353
- setPixelUnit,
354
- } = commonFunctions();
355
- const showHeader = computed(() => (props.option.showHeader ?? true));
356
- const useSummary = computed(() => (props.option?.useSummary || false));
357
- const stripeStyle = computed(() => (props.option.style?.stripe || false));
358
- const borderStyle = computed(() => (props.option.style?.border || ''));
359
- const highlightIdx = computed(() => (props.option.style?.highlight ?? -1));
360
- const rowMinHeight = props.option.rowMinHeight || 35;
361
- const elementInfo = reactive({
362
- body: null,
363
- header: null,
364
- table: null,
365
- resizeLine: null,
366
- 'grid-wrapper': null,
367
- });
368
- const filterInfo = reactive({
369
- filterList: {},
370
- isFiltering: computed(() => (props.option.useFilter ?? false)),
371
- setFiltering: false,
372
- showFilterWindow: false,
373
- currentFilter: {
374
- column: {},
375
- items: [],
376
- },
377
- isSearch: false,
378
- searchWord: '',
379
- });
380
- const stores = reactive({
381
- viewStore: [],
382
- originStore: [],
383
- filterStore: [],
384
- pagingStore: [],
385
- store: computed(() => {
386
- const store = filterInfo.isFiltering ? stores.filterStore : stores.originStore;
387
- return filterInfo.isSearch ? stores.searchStore : store;
388
- }),
389
- orderedColumns: computed(() =>
390
- (props.columns.map((column, index) => ({ index, ...column })))),
391
- });
392
- const pageInfo = reactive({
393
- usePage: computed(() => (props.option.page?.use || false)),
394
- useClient: props.option.page?.useClient || false,
395
- isInfinite: computed(() => (props.option.page?.isInfinite || false)),
396
- startIndex: 0,
397
- prevPage: 0,
398
- currentPage: 0,
399
- pageTotal: computed(() => (props.option.page?.total || 0)),
400
- perPage: computed(() => (props.option.page?.perPage || 20)),
401
- visiblePage: computed(() => (props.option.page?.visiblePage || 8)),
402
- order: computed(() => (props.option.page?.order || 'center')),
403
- showPageInfo: computed(() => (props.option.page?.showPageInfo || false)),
404
- isClientPaging: computed(() =>
405
- pageInfo.useClient && pageInfo.usePage && !pageInfo.isInfinite),
406
- isHighlight: false,
407
- highlightPage: 0,
408
- });
409
- const checkInfo = reactive({
410
- prevCheckedRow: [],
411
- isHeaderChecked: false,
412
- checkedRows: props.checked,
413
- useCheckbox: computed(() => (props.option.useCheckbox || {})),
414
- });
415
- const scrollInfo = reactive({
416
- lastScroll: {
417
- top: 0,
418
- left: 0,
419
- },
420
- vScrollTopHeight: 0,
421
- vScrollBottomHeight: 0,
422
- hasVerticalScrollBar: false,
423
- hasHorizontalScrollBar: false,
424
- });
425
- const selectInfo = reactive({
426
- selectedRow: props.selected,
427
- useSelect: computed(() => props.option?.useSelection?.use ?? true),
428
- limitCount: computed(() => {
429
- let limit = props.option?.useSelection?.limitCount;
430
- limit = !!limit && limit >= 2 ? limit : 0;
431
- return limit;
432
- }),
433
- multiple: computed(() => props.option?.useSelection?.multiple ?? false),
434
- });
435
- const sortInfo = reactive({
436
- isSorting: false,
437
- sortField: '',
438
- sortOrder: 'desc',
439
- });
440
- const contextInfo = reactive({
441
- menu: null,
442
- contextMenuItems: [],
443
- customContextMenu: props.option.customContextMenu || [],
444
- });
445
- const resizeInfo = reactive({
446
- minWidth: 40,
447
- rendererMinWidth: 80,
448
- iconWidth: 42,
449
- showResizeLine: false,
450
- adjust: props.option.adjust || false,
451
- columnWidth: props.option.columnWidth || 80,
452
- scrollWidth: props.option.scrollWidth || 17,
453
- rowHeight: computed(() =>
454
- (props.option.rowHeight > rowMinHeight ? props.option.rowHeight : rowMinHeight)),
455
- gridWidth: computed(() => (props.width ? setPixelUnit(props.width) : '100%')),
456
- gridHeight: computed(() => (props.height ? setPixelUnit(props.height) : '100%')),
457
- });
458
- const clearCheckInfo = () => {
459
- checkInfo.checkedRows = [];
460
- checkInfo.isHeaderChecked = false;
461
- stores.store.forEach((row) => {
462
- row[ROW_CHECK_INDEX] = false;
463
- });
464
- };
465
- const clearSelectInfo = () => {
466
- selectInfo.selectedRow = [];
467
- stores.store.forEach((row) => {
468
- row[ROW_SELECT_INDEX] = false;
469
- });
470
- };
471
- const {
472
- getPagingData,
473
- updatePagingInfo,
474
- changePage,
475
- } = pagingEvent({
476
- stores,
477
- pageInfo,
478
- sortInfo,
479
- filterInfo,
480
- elementInfo,
481
- clearCheckInfo,
482
- });
483
- const summaryScroll = ref(0);
484
- const {
485
- updateVScroll,
486
- updateHScroll,
487
- onScroll,
488
- } = scrollEvent({
489
- scrollInfo,
490
- stores,
491
- elementInfo,
492
- resizeInfo,
493
- pageInfo,
494
- summaryScroll,
495
- getPagingData,
496
- updatePagingInfo,
497
- });
498
-
499
- const {
500
- onRowClick,
501
- onRowDblClick,
502
- } = clickEvent({ selectInfo });
503
-
504
- const {
505
- onCheck,
506
- onCheckAll,
507
- } = checkEvent({ checkInfo, stores, pageInfo, getPagingData, updatePagingInfo });
508
-
509
- const {
510
- onSort,
511
- setSort,
512
- } = sortEvent({ sortInfo, stores, getColumnIndex, updatePagingInfo });
513
-
514
- const {
515
- onClickFilter,
516
- onCloseFilterWindow,
517
- onApplyFilter,
518
- setFilter,
519
- onSearch,
520
- } = filterEvent({
521
- filterInfo,
522
- stores,
523
- checkInfo,
524
- pageInfo,
525
- getColumnIndex,
526
- getConvertValue,
527
- updateVScroll,
528
- getPagingData,
529
- updatePagingInfo,
530
- });
531
-
532
- const {
533
- setStore,
534
- } = storeEvent({
535
- selectInfo,
536
- checkInfo,
537
- stores,
538
- sortInfo,
539
- filterInfo,
540
- elementInfo,
541
- setSort,
542
- setFilter,
543
- updateVScroll,
544
- });
545
-
546
- const {
547
- calculatedColumn,
548
- onResize,
549
- onShow,
550
- onColumnResize,
551
- } = resizeEvent({
552
- resizeInfo,
553
- elementInfo,
554
- checkInfo,
555
- stores,
556
- filterInfo,
557
- isRenderer,
558
- updateVScroll,
559
- updateHScroll,
560
- });
561
-
562
- const {
563
- setContextMenu,
564
- onContextMenu,
565
- } = contextMenuEvent({ contextInfo, stores, filterInfo, selectInfo, setStore });
566
-
567
- onMounted(() => {
568
- calculatedColumn();
569
- setStore(props.rows);
570
- });
571
- onActivated(() => {
572
- onResize();
573
- });
574
- watch(
575
- () => props.columns,
576
- () => {
577
- sortInfo.isSorting = false;
578
- sortInfo.sortField = '';
579
- setSort();
580
- }, { deep: true },
581
- );
582
- watch(
583
- () => sortInfo.isSorting,
584
- (value) => {
585
- if (value) {
586
- setStore(stores.originStore, false);
587
- sortInfo.isSorting = !value;
588
- if (pageInfo.isClientPaging) {
589
- pageInfo.currentPage = 1;
590
- stores.pagingStore = getPagingData();
591
- clearCheckInfo();
592
- }
593
- }
594
- },
595
- );
596
- watch(
597
- () => filterInfo.setFiltering,
598
- (value) => {
599
- if (value) {
600
- setStore([], false);
601
- filterInfo.setFiltering = !value;
602
- }
603
- },
604
- );
605
- watch(
606
- () => props.rows,
607
- (value) => {
608
- setStore(value);
609
- if (filterInfo.isSearch) {
610
- onSearch(filterInfo.searchWord);
611
- }
612
- }, { deep: true },
613
- );
614
- watch(
615
- () => props.checked,
616
- (value) => {
617
- checkInfo.checkedRows = value;
618
- },
619
- );
620
- watch(
621
- () => checkInfo.checkedRows,
622
- (value) => {
623
- checkInfo.isHeaderChecked = false;
624
- let store = stores.store;
625
- if (pageInfo.isClientPaging) {
626
- store = getPagingData();
627
- }
628
- if (store.length) {
629
- store.forEach((row) => {
630
- row[ROW_CHECK_INDEX] = value.includes(row[ROW_DATA_INDEX]);
631
- });
632
- checkInfo.isHeaderChecked = value.length === store.length;
633
- }
634
- updateVScroll();
635
- },
636
- );
637
- watch(
638
- () => props.selected,
639
- (value) => {
640
- if (selectInfo.useSelect) {
641
- selectInfo.selectedRow = value;
642
- }
643
- },
644
- );
645
- watch(
646
- () => selectInfo.selectedRow,
647
- (value) => {
648
- if (selectInfo.useSelect) {
649
- stores.store.forEach((row) => {
650
- row[ROW_SELECT_INDEX] = value.includes(row[ROW_DATA_INDEX]);
651
- });
652
- updateVScroll();
653
- }
654
- },
655
- );
656
- watch(
657
- () => highlightIdx.value,
658
- async (index) => {
659
- await nextTick();
660
- if (index >= 0) {
661
- if (pageInfo.usePage && !pageInfo.isInfinite) {
662
- pageInfo.highlightPage = Math.ceil(index / pageInfo.perPage) || 1;
663
- if (pageInfo.highlightPage !== pageInfo.currentPage) {
664
- pageInfo.currentPage = pageInfo.highlightPage;
665
- pageInfo.isHighlight = true;
666
- return;
667
- }
668
- }
669
- elementInfo.body.scrollTop = resizeInfo.rowHeight * highlightIdx.value;
670
- }
671
- },
672
- );
673
- watch(
674
- () => checkInfo.useCheckbox.mode,
675
- () => {
676
- clearCheckInfo();
677
- },
678
- );
679
- watch(
680
- () => selectInfo.useSelect,
681
- () => {
682
- clearSelectInfo();
683
- },
684
- );
685
- watch(
686
- () => selectInfo.multiple,
687
- () => {
688
- clearSelectInfo();
689
- },
690
- );
691
- watch(
692
- () => props.checked.length,
693
- (checkedSize) => {
694
- if (!checkedSize) {
695
- clearCheckInfo();
696
- }
697
- },
698
- );
699
- watch(
700
- () => [props.option.columnWidth, resizeInfo.gridWidth],
701
- () => {
702
- resizeInfo.columnWidth = props.option.columnWidth;
703
- const gridWrapper = elementInfo['grid-wrapper'];
704
- gridWrapper.style.width = resizeInfo.gridWidth;
705
- gridWrapper.style.height = resizeInfo.gridHeight;
706
- stores.orderedColumns.map((column) => {
707
- const item = column;
708
-
709
- if (!props.columns[column.index].width && !item.resized) {
710
- item.width = 0;
711
- }
712
-
713
- return item;
714
- });
715
- onResize();
716
- },
717
- );
718
- watch(
719
- () => filterInfo.isFiltering,
720
- () => {
721
- stores.filterStore = [];
722
- setStore([], false);
723
- },
724
- );
725
- watch(
726
- () => props.option.searchValue,
727
- (value) => {
728
- if (value !== undefined) {
729
- onSearch(value?.value ?? value);
730
- if (pageInfo.isClientPaging) {
731
- clearCheckInfo();
732
- clearSelectInfo();
733
- }
734
- }
735
- }, { immediate: true },
736
- );
737
- watch(
738
- () => props.option.page?.currentPage,
739
- (value) => {
740
- const current = !value ? 1 : value;
741
- pageInfo.currentPage = !props.option.page?.isInfinite ? current : 1;
742
- }, { immediate: true },
743
- );
744
- watch(
745
- () => pageInfo.currentPage,
746
- (current, before) => {
747
- nextTick(() => {
748
- changePage(before);
749
- if (pageInfo.isClientPaging && current !== before) {
750
- clearCheckInfo();
751
- clearSelectInfo();
752
- }
753
- updateVScroll();
754
- if (current === pageInfo.highlightPage && pageInfo.isHighlight) {
755
- elementInfo.body.scrollTop = resizeInfo.rowHeight * highlightIdx.value;
756
- pageInfo.isHighlight = !pageInfo.isHighlight;
757
- }
758
- });
759
- },
760
- );
761
- return {
762
- summaryScroll,
763
- showHeader,
764
- stripeStyle,
765
- borderStyle,
766
- highlightIdx,
767
- useSummary,
768
- stores,
769
- ...toRefs(elementInfo),
770
- ...toRefs(stores),
771
- ...toRefs(filterInfo),
772
- ...toRefs(scrollInfo),
773
- ...toRefs(pageInfo),
774
- ...toRefs(resizeInfo),
775
- ...toRefs(selectInfo),
776
- ...toRefs(checkInfo),
777
- ...toRefs(sortInfo),
778
- ...toRefs(contextInfo),
779
- isRenderer,
780
- getComponentName,
781
- getConvertValue,
782
- getColumnIndex,
783
- setPixelUnit,
784
- updateVScroll,
785
- updateHScroll,
786
- onScroll,
787
- calculatedColumn,
788
- onResize,
789
- onShow,
790
- onColumnResize,
791
- onRowClick,
792
- onRowDblClick,
793
- onCheck,
794
- onCheckAll,
795
- onSort,
796
- setSort,
797
- onClickFilter,
798
- onCloseFilterWindow,
799
- onApplyFilter,
800
- setFilter,
801
- setStore,
802
- setContextMenu,
803
- onContextMenu,
804
- onSearch,
805
- };
806
- },
807
- };
808
- </script>
809
-
810
- <style lang="scss" scoped>
811
- @import 'style/grid.scss';
812
- .postgresql {
813
- background: url('../../../docs/assets/images/icon_postgresql.svg') no-repeat center center;
814
- }
815
-
816
- .oracle {
817
- background: url('../../../docs/assets/images/icon_oracle.svg') no-repeat center center;
818
- }
819
-
820
- .mongodb {
821
- background: url('../../../docs/assets/images/icon_mongodb.svg') no-repeat center center;
822
- }
823
-
824
- .mysql {
825
- background: url('../../../docs/assets/images/icon_mysql.svg') no-repeat center center;
826
- }
827
- </style>
1
+ <template>
2
+ <div
3
+ v-if="$slots.toolbar"
4
+ class="toolbar-wrapper"
5
+ :style="`width: ${gridWidth};`"
6
+ >
7
+ <!-- Toolbar -->
8
+ <toolbar>
9
+ <template #toolbarWrapper>
10
+ <slot
11
+ name="toolbar"
12
+ :item="{ onSearch: onSearch }"
13
+ />
14
+ </template>
15
+ </toolbar>
16
+ </div>
17
+ <div
18
+ ref="grid-wrapper"
19
+ v-resize="onResize"
20
+ v-observe-visibility="{
21
+ callback: onShow,
22
+ once: true,
23
+ }"
24
+ v-bind="$attrs"
25
+ class="grid-wrapper"
26
+ :style="`width: ${gridWidth}; height: ${gridHeight};`"
27
+ >
28
+ <!-- Table -->
29
+ <div
30
+ v-cloak
31
+ ref="grid"
32
+ :class="{
33
+ 'ev-grid': true,
34
+ table: true,
35
+ adjust: adjust,
36
+ 'non-header': !showHeader,
37
+ 'ev-grid--empty': !viewStore.length,
38
+ }"
39
+ >
40
+ <!-- Header -->
41
+ <div
42
+ v-show="showHeader"
43
+ ref="header"
44
+ :class="{
45
+ 'table-header': true,
46
+ 'non-border': !!borderStyle,
47
+ }"
48
+ >
49
+ <ul class="column-list">
50
+ <!-- Header Checkbox -->
51
+ <li
52
+ v-if="useCheckbox.use"
53
+ :class="{
54
+ 'column': true,
55
+ 'non-border': !!borderStyle,
56
+ }"
57
+ :style="`width: ${minWidth}px;`"
58
+ >
59
+ <ev-checkbox
60
+ v-if="useCheckbox.use && useCheckbox.headerCheck && useCheckbox.mode !== 'single'"
61
+ v-model="isHeaderChecked"
62
+ @change="onCheckAll"
63
+ />
64
+ </li>
65
+ <!-- Column List -->
66
+ <template
67
+ v-for="(column, index) in orderedColumns"
68
+ :key="index"
69
+ >
70
+ <li
71
+ v-if="!column.hide"
72
+ :data-index="index"
73
+ :class="{
74
+ column: true,
75
+ render: isRenderer(column),
76
+ 'non-border': !!borderStyle,
77
+ [column.field]: column.field,
78
+ }"
79
+ :style="{
80
+ width: `${column.width}px`,
81
+ 'min-width': `${isRenderer(column) ? rendererMinWidth : minWidth}px`,
82
+ 'margin-right': (orderedColumns.length - 1 === index
83
+ && hasVerticalScrollBar && hasHorizontalScrollBar) ? `${scrollWidth}px` : '0px',
84
+ }"
85
+ >
86
+ <!-- Filter Status -->
87
+ <span
88
+ v-if="isFiltering && filterList[column.field]?.find(item => item.use)"
89
+ class="column-filter-status"
90
+ >
91
+ <ev-icon icon="ev-icon-filter"/>
92
+ </span>
93
+ <!-- Column Name -->
94
+ <span
95
+ :title="column.caption"
96
+ class="column-name"
97
+ @click.stop="onSort(column)"
98
+ >
99
+ {{ column.caption }}
100
+ </span>
101
+ <!-- Sort Icon -->
102
+ <template v-if="sortField === column.field">
103
+ <ev-icon
104
+ v-if="sortOrder === 'desc'"
105
+ icon="ev-icon-triangle-down"
106
+ />
107
+ <ev-icon
108
+ v-if="sortOrder === 'asc'"
109
+ icon="ev-icon-triangle-up"
110
+ />
111
+ </template>
112
+ <!-- Filter Button -->
113
+ <span
114
+ v-if="isFiltering"
115
+ class="column-filter"
116
+ @click.capture="onClickFilter(column)"
117
+ >
118
+ <ev-icon icon="ev-icon-hamburger2"/>
119
+ </span>
120
+ <!-- Column Resize -->
121
+ <span
122
+ class="column-resize"
123
+ @mousedown.stop.left="onColumnResize(index, $event)"
124
+ />
125
+ </li>
126
+ </template>
127
+ </ul>
128
+ </div>
129
+ <!-- Body -->
130
+ <div
131
+ ref="body"
132
+ :class="{
133
+ 'table-body': true,
134
+ 'bottom-border': !!viewStore.length,
135
+ stripe: stripeStyle,
136
+ 'non-border': !!borderStyle,
137
+ }"
138
+ @scroll="onScroll"
139
+ @contextmenu="onContextMenu($event)"
140
+ @contextmenu.prevent="menu.show"
141
+ >
142
+ <!-- vScroll Top -->
143
+ <div
144
+ :style="`height: ${vScrollTopHeight}px;`"
145
+ class="vscroll-spacer"
146
+ />
147
+ <table ref="table">
148
+ <tbody>
149
+ <!-- Row List -->
150
+ <tr
151
+ v-for="(row, rowIndex) in viewStore"
152
+ :key="rowIndex"
153
+ :data-index="row[0]"
154
+ :class="{
155
+ row: true,
156
+ selected: row[3],
157
+ 'non-border': !!borderStyle && borderStyle !== 'rows',
158
+ highlight: row[0] === highlightIdx,
159
+ }"
160
+ @click="onRowClick($event, row)"
161
+ @dblclick="onRowDblClick($event, row)"
162
+ >
163
+ <!-- Row Checkbox -->
164
+ <td
165
+ v-if="useCheckbox.use"
166
+ :class="{
167
+ cell: true,
168
+ 'row-checkbox': true,
169
+ 'non-border': !!borderStyle,
170
+ }"
171
+ :style="`width: ${minWidth}px; height: ${rowHeight}px;`"
172
+ >
173
+ <ev-checkbox
174
+ v-model="row[1]"
175
+ class="row-checkbox-input"
176
+ @change="onCheck($event, row)"
177
+ />
178
+ </td>
179
+ <!-- Cell -->
180
+ <template
181
+ v-for="(column, cellIndex) in orderedColumns"
182
+ :key="cellIndex"
183
+ >
184
+ <td
185
+ v-if="!column.hide"
186
+ :data-name="column.field"
187
+ :data-index="column.index"
188
+ :class="{
189
+ cell: true,
190
+ [column.type]: column.type,
191
+ [column.align]: column.align,
192
+ render: isRenderer(column),
193
+ 'non-border': !!borderStyle,
194
+ [column.field]: column.field,
195
+ }"
196
+ :style="{
197
+ width: `${column.width}px`,
198
+ height: `${rowHeight}px`,
199
+ 'line-height': `${rowHeight}px`,
200
+ 'min-width': `${isRenderer(column) ? rendererMinWidth : minWidth}px`,
201
+ }"
202
+ >
203
+ <!-- Cell Renderer -->
204
+ <div v-if="!!$slots[column.field]">
205
+ <slot
206
+ :name="column.field"
207
+ :item="{ row, column }"
208
+ />
209
+ </div>
210
+ <!-- Cell Value -->
211
+ <template v-else>
212
+ <div :title="getConvertValue(column, row[2][column.index])">
213
+ {{ getConvertValue(column, row[2][column.index]) }}
214
+ </div>
215
+ </template>
216
+ </td>
217
+ </template>
218
+ </tr>
219
+ <tr v-if="!viewStore.length">
220
+ <td class="is-empty">No records</td>
221
+ </tr>
222
+ </tbody>
223
+ </table>
224
+ <!-- vScroll Bottom -->
225
+ <div
226
+ :style="`height: ${vScrollBottomHeight}px;`"
227
+ class="vscroll-spacer"
228
+ />
229
+ <!-- Context Menu -->
230
+ <ev-context-menu
231
+ ref="menu"
232
+ :items="contextMenuItems"
233
+ />
234
+ </div>
235
+ <!-- Resize Line -->
236
+ <div
237
+ v-show="showResizeLine"
238
+ ref="resizeLine"
239
+ class="table-resize-line"
240
+ />
241
+ <!-- Filter Window -->
242
+ <filter-window
243
+ v-show="showFilterWindow"
244
+ :is-show="showFilterWindow"
245
+ :target-column="currentFilter.column"
246
+ :filter-items="currentFilter.items"
247
+ @apply-filter="onApplyFilter"
248
+ @before-close="onCloseFilterWindow"
249
+ />
250
+ </div>
251
+ </div>
252
+ <!-- Summary -->
253
+ <grid-summary
254
+ v-if="useSummary"
255
+ :ordered-columns="orderedColumns"
256
+ :stores="stores"
257
+ :use-checkbox="useCheckbox.use"
258
+ :style-option="{
259
+ borderStyle,
260
+ minWidth,
261
+ rowHeight,
262
+ }"
263
+ :scroll-left="summaryScroll"
264
+ />
265
+ <!-- Pagination -->
266
+ <grid-pagination
267
+ v-if="usePage && !isInfinite"
268
+ v-model="currentPage"
269
+ :total="pageTotal"
270
+ :per-page="perPage"
271
+ :visible-page="visiblePage"
272
+ :show-page-info="showPageInfo"
273
+ :order="order"
274
+ />
275
+ </template>
276
+
277
+ <script>
278
+ import { reactive, toRefs, computed, watch, onMounted, onActivated, nextTick, ref } from 'vue';
279
+ import Toolbar from './grid.toolbar';
280
+ import FilterWindow from './grid.filter.window';
281
+ import GridPagination from './grid.pagination';
282
+ import GridSummary from './grid.summary';
283
+ import {
284
+ commonFunctions,
285
+ scrollEvent,
286
+ resizeEvent,
287
+ clickEvent,
288
+ checkEvent,
289
+ sortEvent,
290
+ filterEvent,
291
+ contextMenuEvent,
292
+ storeEvent,
293
+ pagingEvent,
294
+ } from './uses';
295
+
296
+ export default {
297
+ name: 'EvGrid',
298
+ components: {
299
+ Toolbar,
300
+ FilterWindow,
301
+ GridPagination,
302
+ GridSummary,
303
+ },
304
+ props: {
305
+ columns: {
306
+ type: [Array],
307
+ default: () => [],
308
+ },
309
+ rows: {
310
+ type: [Array],
311
+ default: () => [],
312
+ },
313
+ width: {
314
+ type: [String, Number],
315
+ default: '100%',
316
+ },
317
+ height: {
318
+ type: [String, Number],
319
+ default: '100%',
320
+ },
321
+ selected: {
322
+ type: [Array],
323
+ default: () => [],
324
+ },
325
+ checked: {
326
+ type: [Array],
327
+ default: () => [],
328
+ },
329
+ option: {
330
+ type: Object,
331
+ default: () => ({}),
332
+ },
333
+ },
334
+ emits: {
335
+ 'update:selected': null,
336
+ 'click-row': null,
337
+ 'dblclick-row': null,
338
+ 'update:checked': null,
339
+ 'check-row': null,
340
+ 'check-all': null,
341
+ 'page-change': null,
342
+ },
343
+ setup(props) {
344
+ // const ROW_INDEX = 0;
345
+ const ROW_CHECK_INDEX = 1;
346
+ const ROW_DATA_INDEX = 2;
347
+ const ROW_SELECT_INDEX = 3;
348
+ const {
349
+ isRenderer,
350
+ getComponentName,
351
+ getConvertValue,
352
+ getColumnIndex,
353
+ setPixelUnit,
354
+ } = commonFunctions();
355
+ const showHeader = computed(() => (props.option.showHeader ?? true));
356
+ const useSummary = computed(() => (props.option?.useSummary || false));
357
+ const stripeStyle = computed(() => (props.option.style?.stripe || false));
358
+ const borderStyle = computed(() => (props.option.style?.border || ''));
359
+ const highlightIdx = computed(() => (props.option.style?.highlight ?? -1));
360
+ const rowMinHeight = props.option.rowMinHeight || 35;
361
+ const elementInfo = reactive({
362
+ body: null,
363
+ header: null,
364
+ table: null,
365
+ resizeLine: null,
366
+ 'grid-wrapper': null,
367
+ });
368
+ const filterInfo = reactive({
369
+ filterList: {},
370
+ isFiltering: computed(() => (props.option.useFilter ?? false)),
371
+ setFiltering: false,
372
+ showFilterWindow: false,
373
+ currentFilter: {
374
+ column: {},
375
+ items: [],
376
+ },
377
+ isSearch: false,
378
+ searchWord: '',
379
+ });
380
+ const stores = reactive({
381
+ viewStore: [],
382
+ originStore: [],
383
+ filterStore: [],
384
+ pagingStore: [],
385
+ store: computed(() => {
386
+ const store = filterInfo.isFiltering ? stores.filterStore : stores.originStore;
387
+ return filterInfo.isSearch ? stores.searchStore : store;
388
+ }),
389
+ orderedColumns: computed(() =>
390
+ (props.columns.map((column, index) => ({ index, ...column })))),
391
+ });
392
+ const pageInfo = reactive({
393
+ usePage: computed(() => (props.option.page?.use || false)),
394
+ useClient: props.option.page?.useClient || false,
395
+ isInfinite: computed(() => (props.option.page?.isInfinite || false)),
396
+ startIndex: 0,
397
+ prevPage: 0,
398
+ currentPage: 0,
399
+ pageTotal: computed(() => (props.option.page?.total || 0)),
400
+ perPage: computed(() => (props.option.page?.perPage || 20)),
401
+ visiblePage: computed(() => (props.option.page?.visiblePage || 8)),
402
+ order: computed(() => (props.option.page?.order || 'center')),
403
+ showPageInfo: computed(() => (props.option.page?.showPageInfo || false)),
404
+ isClientPaging: computed(() =>
405
+ pageInfo.useClient && pageInfo.usePage && !pageInfo.isInfinite),
406
+ isHighlight: false,
407
+ highlightPage: 0,
408
+ });
409
+ const checkInfo = reactive({
410
+ prevCheckedRow: [],
411
+ isHeaderChecked: false,
412
+ checkedRows: props.checked,
413
+ useCheckbox: computed(() => (props.option.useCheckbox || {})),
414
+ });
415
+ const scrollInfo = reactive({
416
+ lastScroll: {
417
+ top: 0,
418
+ left: 0,
419
+ },
420
+ vScrollTopHeight: 0,
421
+ vScrollBottomHeight: 0,
422
+ hasVerticalScrollBar: false,
423
+ hasHorizontalScrollBar: false,
424
+ });
425
+ const selectInfo = reactive({
426
+ selectedRow: props.selected,
427
+ useSelect: computed(() => props.option?.useSelection?.use ?? true),
428
+ limitCount: computed(() => {
429
+ let limit = props.option?.useSelection?.limitCount;
430
+ limit = !!limit && limit >= 2 ? limit : 0;
431
+ return limit;
432
+ }),
433
+ multiple: computed(() => props.option?.useSelection?.multiple ?? false),
434
+ });
435
+ const sortInfo = reactive({
436
+ isSorting: false,
437
+ sortField: '',
438
+ sortOrder: 'desc',
439
+ });
440
+ const contextInfo = reactive({
441
+ menu: null,
442
+ contextMenuItems: [],
443
+ customContextMenu: props.option.customContextMenu || [],
444
+ });
445
+ const resizeInfo = reactive({
446
+ minWidth: 40,
447
+ rendererMinWidth: 80,
448
+ iconWidth: 42,
449
+ showResizeLine: false,
450
+ adjust: props.option.adjust || false,
451
+ columnWidth: props.option.columnWidth || 80,
452
+ scrollWidth: props.option.scrollWidth || 17,
453
+ rowHeight: computed(() =>
454
+ (props.option.rowHeight > rowMinHeight ? props.option.rowHeight : rowMinHeight)),
455
+ gridWidth: computed(() => (props.width ? setPixelUnit(props.width) : '100%')),
456
+ gridHeight: computed(() => (props.height ? setPixelUnit(props.height) : '100%')),
457
+ });
458
+ const clearCheckInfo = () => {
459
+ checkInfo.checkedRows = [];
460
+ checkInfo.isHeaderChecked = false;
461
+ stores.store.forEach((row) => {
462
+ row[ROW_CHECK_INDEX] = false;
463
+ });
464
+ };
465
+ const clearSelectInfo = () => {
466
+ selectInfo.selectedRow = [];
467
+ stores.store.forEach((row) => {
468
+ row[ROW_SELECT_INDEX] = false;
469
+ });
470
+ };
471
+ const {
472
+ getPagingData,
473
+ updatePagingInfo,
474
+ changePage,
475
+ } = pagingEvent({
476
+ stores,
477
+ pageInfo,
478
+ sortInfo,
479
+ filterInfo,
480
+ elementInfo,
481
+ clearCheckInfo,
482
+ });
483
+ const summaryScroll = ref(0);
484
+ const {
485
+ updateVScroll,
486
+ updateHScroll,
487
+ onScroll,
488
+ } = scrollEvent({
489
+ scrollInfo,
490
+ stores,
491
+ elementInfo,
492
+ resizeInfo,
493
+ pageInfo,
494
+ summaryScroll,
495
+ getPagingData,
496
+ updatePagingInfo,
497
+ });
498
+
499
+ const {
500
+ onRowClick,
501
+ onRowDblClick,
502
+ } = clickEvent({ selectInfo });
503
+
504
+ const {
505
+ onCheck,
506
+ onCheckAll,
507
+ } = checkEvent({ checkInfo, stores, pageInfo, getPagingData, updatePagingInfo });
508
+
509
+ const {
510
+ onSort,
511
+ setSort,
512
+ } = sortEvent({ sortInfo, stores, getColumnIndex, updatePagingInfo });
513
+
514
+ const {
515
+ onClickFilter,
516
+ onCloseFilterWindow,
517
+ onApplyFilter,
518
+ setFilter,
519
+ onSearch,
520
+ } = filterEvent({
521
+ filterInfo,
522
+ stores,
523
+ checkInfo,
524
+ pageInfo,
525
+ getColumnIndex,
526
+ getConvertValue,
527
+ updateVScroll,
528
+ getPagingData,
529
+ updatePagingInfo,
530
+ });
531
+
532
+ const {
533
+ setStore,
534
+ } = storeEvent({
535
+ selectInfo,
536
+ checkInfo,
537
+ stores,
538
+ sortInfo,
539
+ filterInfo,
540
+ elementInfo,
541
+ setSort,
542
+ setFilter,
543
+ updateVScroll,
544
+ });
545
+
546
+ const {
547
+ calculatedColumn,
548
+ onResize,
549
+ onShow,
550
+ onColumnResize,
551
+ } = resizeEvent({
552
+ resizeInfo,
553
+ elementInfo,
554
+ checkInfo,
555
+ stores,
556
+ filterInfo,
557
+ isRenderer,
558
+ updateVScroll,
559
+ updateHScroll,
560
+ });
561
+
562
+ const {
563
+ setContextMenu,
564
+ onContextMenu,
565
+ } = contextMenuEvent({ contextInfo, stores, filterInfo, selectInfo, setStore });
566
+
567
+ onMounted(() => {
568
+ calculatedColumn();
569
+ setStore(props.rows);
570
+ });
571
+ onActivated(() => {
572
+ onResize();
573
+ });
574
+ watch(
575
+ () => props.columns,
576
+ () => {
577
+ sortInfo.isSorting = false;
578
+ sortInfo.sortField = '';
579
+ setSort();
580
+ }, { deep: true },
581
+ );
582
+ watch(
583
+ () => sortInfo.isSorting,
584
+ (value) => {
585
+ if (value) {
586
+ setStore(stores.originStore, false);
587
+ sortInfo.isSorting = !value;
588
+ if (pageInfo.isClientPaging) {
589
+ pageInfo.currentPage = 1;
590
+ stores.pagingStore = getPagingData();
591
+ clearCheckInfo();
592
+ }
593
+ }
594
+ },
595
+ );
596
+ watch(
597
+ () => filterInfo.setFiltering,
598
+ (value) => {
599
+ if (value) {
600
+ setStore([], false);
601
+ filterInfo.setFiltering = !value;
602
+ }
603
+ },
604
+ );
605
+ watch(
606
+ () => props.rows,
607
+ (value) => {
608
+ setStore(value);
609
+ if (filterInfo.isSearch) {
610
+ onSearch(filterInfo.searchWord);
611
+ }
612
+ }, { deep: true },
613
+ );
614
+ watch(
615
+ () => props.checked,
616
+ (value) => {
617
+ checkInfo.checkedRows = value;
618
+ },
619
+ );
620
+ watch(
621
+ () => checkInfo.checkedRows,
622
+ (value) => {
623
+ checkInfo.isHeaderChecked = false;
624
+ let store = stores.store;
625
+ if (pageInfo.isClientPaging) {
626
+ store = getPagingData();
627
+ }
628
+ if (store.length) {
629
+ store.forEach((row) => {
630
+ row[ROW_CHECK_INDEX] = value.includes(row[ROW_DATA_INDEX]);
631
+ });
632
+ checkInfo.isHeaderChecked = value.length === store.length;
633
+ }
634
+ updateVScroll();
635
+ },
636
+ );
637
+ watch(
638
+ () => props.selected,
639
+ (value) => {
640
+ if (selectInfo.useSelect) {
641
+ selectInfo.selectedRow = value;
642
+ }
643
+ },
644
+ );
645
+ watch(
646
+ () => selectInfo.selectedRow,
647
+ (value) => {
648
+ if (selectInfo.useSelect) {
649
+ stores.store.forEach((row) => {
650
+ row[ROW_SELECT_INDEX] = value.includes(row[ROW_DATA_INDEX]);
651
+ });
652
+ updateVScroll();
653
+ }
654
+ },
655
+ );
656
+ watch(
657
+ () => highlightIdx.value,
658
+ async (index) => {
659
+ await nextTick();
660
+ if (index >= 0) {
661
+ if (pageInfo.usePage && !pageInfo.isInfinite) {
662
+ pageInfo.highlightPage = Math.ceil(index / pageInfo.perPage) || 1;
663
+ if (pageInfo.highlightPage !== pageInfo.currentPage) {
664
+ pageInfo.currentPage = pageInfo.highlightPage;
665
+ pageInfo.isHighlight = true;
666
+ return;
667
+ }
668
+ }
669
+ elementInfo.body.scrollTop = resizeInfo.rowHeight * highlightIdx.value;
670
+ }
671
+ },
672
+ );
673
+ watch(
674
+ () => checkInfo.useCheckbox.mode,
675
+ () => {
676
+ clearCheckInfo();
677
+ },
678
+ );
679
+ watch(
680
+ () => selectInfo.useSelect,
681
+ () => {
682
+ clearSelectInfo();
683
+ },
684
+ );
685
+ watch(
686
+ () => selectInfo.multiple,
687
+ () => {
688
+ clearSelectInfo();
689
+ },
690
+ );
691
+ watch(
692
+ () => props.checked.length,
693
+ (checkedSize) => {
694
+ if (!checkedSize) {
695
+ clearCheckInfo();
696
+ }
697
+ },
698
+ );
699
+ watch(
700
+ () => [props.option.columnWidth, resizeInfo.gridWidth],
701
+ () => {
702
+ resizeInfo.columnWidth = props.option.columnWidth;
703
+ const gridWrapper = elementInfo['grid-wrapper'];
704
+ gridWrapper.style.width = resizeInfo.gridWidth;
705
+ gridWrapper.style.height = resizeInfo.gridHeight;
706
+ stores.orderedColumns.map((column) => {
707
+ const item = column;
708
+
709
+ if (!props.columns[column.index].width && !item.resized) {
710
+ item.width = 0;
711
+ }
712
+
713
+ return item;
714
+ });
715
+ onResize();
716
+ },
717
+ );
718
+ watch(
719
+ () => filterInfo.isFiltering,
720
+ () => {
721
+ stores.filterStore = [];
722
+ setStore([], false);
723
+ },
724
+ );
725
+ watch(
726
+ () => props.option.searchValue,
727
+ (value) => {
728
+ if (value !== undefined) {
729
+ onSearch(value?.value ?? value);
730
+ if (pageInfo.isClientPaging) {
731
+ clearCheckInfo();
732
+ clearSelectInfo();
733
+ }
734
+ }
735
+ }, { immediate: true },
736
+ );
737
+ watch(
738
+ () => props.option.page?.currentPage,
739
+ (value) => {
740
+ const current = !value ? 1 : value;
741
+ pageInfo.currentPage = !props.option.page?.isInfinite ? current : 1;
742
+ }, { immediate: true },
743
+ );
744
+ watch(
745
+ () => pageInfo.currentPage,
746
+ (current, before) => {
747
+ nextTick(() => {
748
+ changePage(before);
749
+ if (pageInfo.isClientPaging && current !== before) {
750
+ clearCheckInfo();
751
+ clearSelectInfo();
752
+ }
753
+ updateVScroll();
754
+ if (current === pageInfo.highlightPage && pageInfo.isHighlight) {
755
+ elementInfo.body.scrollTop = resizeInfo.rowHeight * highlightIdx.value;
756
+ pageInfo.isHighlight = !pageInfo.isHighlight;
757
+ }
758
+ });
759
+ },
760
+ );
761
+ return {
762
+ summaryScroll,
763
+ showHeader,
764
+ stripeStyle,
765
+ borderStyle,
766
+ highlightIdx,
767
+ useSummary,
768
+ stores,
769
+ ...toRefs(elementInfo),
770
+ ...toRefs(stores),
771
+ ...toRefs(filterInfo),
772
+ ...toRefs(scrollInfo),
773
+ ...toRefs(pageInfo),
774
+ ...toRefs(resizeInfo),
775
+ ...toRefs(selectInfo),
776
+ ...toRefs(checkInfo),
777
+ ...toRefs(sortInfo),
778
+ ...toRefs(contextInfo),
779
+ isRenderer,
780
+ getComponentName,
781
+ getConvertValue,
782
+ getColumnIndex,
783
+ setPixelUnit,
784
+ updateVScroll,
785
+ updateHScroll,
786
+ onScroll,
787
+ calculatedColumn,
788
+ onResize,
789
+ onShow,
790
+ onColumnResize,
791
+ onRowClick,
792
+ onRowDblClick,
793
+ onCheck,
794
+ onCheckAll,
795
+ onSort,
796
+ setSort,
797
+ onClickFilter,
798
+ onCloseFilterWindow,
799
+ onApplyFilter,
800
+ setFilter,
801
+ setStore,
802
+ setContextMenu,
803
+ onContextMenu,
804
+ onSearch,
805
+ };
806
+ },
807
+ };
808
+ </script>
809
+
810
+ <style lang="scss" scoped>
811
+ @import 'style/grid.scss';
812
+ .postgresql {
813
+ background: url('../../../docs/assets/images/icon_postgresql.svg') no-repeat center center;
814
+ }
815
+
816
+ .oracle {
817
+ background: url('../../../docs/assets/images/icon_oracle.svg') no-repeat center center;
818
+ }
819
+
820
+ .mongodb {
821
+ background: url('../../../docs/assets/images/icon_mongodb.svg') no-repeat center center;
822
+ }
823
+
824
+ .mysql {
825
+ background: url('../../../docs/assets/images/icon_mysql.svg') no-repeat center center;
826
+ }
827
+ </style>