sh-view 2.8.0 → 2.8.2

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 (91) hide show
  1. package/.eslintrc.js +25 -20
  2. package/other.js +8 -8
  3. package/package.json +9 -6
  4. package/packages/components/index.js +91 -91
  5. package/packages/components/sh-alert/alert.ts +30 -0
  6. package/packages/components/sh-alert/index.vue +143 -168
  7. package/packages/components/sh-badge/index.vue +242 -242
  8. package/packages/components/sh-calendar/index.vue +650 -650
  9. package/packages/components/sh-card/index.vue +148 -148
  10. package/packages/components/sh-code-editor/index.vue +19 -19
  11. package/packages/components/sh-col/index.vue +92 -92
  12. package/packages/components/sh-corner/index.vue +230 -230
  13. package/packages/components/sh-count-to/index.vue +131 -131
  14. package/packages/components/sh-date/index.vue +301 -301
  15. package/packages/components/sh-drawer/index.vue +579 -579
  16. package/packages/components/sh-drawer/scrollbar.js +78 -78
  17. package/packages/components/sh-empty/index.vue +42 -42
  18. package/packages/components/sh-form/js/props.js +76 -76
  19. package/packages/components/sh-form/js/useForm.js +229 -229
  20. package/packages/components/sh-header/index.vue +261 -260
  21. package/packages/components/sh-icon/css/default/ionicons.svg +869 -869
  22. package/packages/components/sh-icon/css/font/iconfont.json +247 -247
  23. package/packages/components/sh-icon/index.vue +41 -41
  24. package/packages/components/sh-image/index.vue +133 -133
  25. package/packages/components/sh-list/index.vue +146 -146
  26. package/packages/components/sh-loading/index.vue +53 -53
  27. package/packages/components/sh-modal/index.vue +188 -188
  28. package/packages/components/sh-noticebar/index.vue +215 -215
  29. package/packages/components/sh-poptip/index.vue +597 -597
  30. package/packages/components/sh-progress/index.vue +276 -276
  31. package/packages/components/sh-pull-refresh/index.vue +289 -289
  32. package/packages/components/sh-result/index.vue +114 -114
  33. package/packages/components/sh-row/index.vue +66 -66
  34. package/packages/components/sh-split/components/trigger.vue +33 -33
  35. package/packages/components/sh-split/index.vue +342 -342
  36. package/packages/components/sh-table/components/importModal.vue +363 -363
  37. package/packages/components/sh-table/components/sh-column.vue +68 -68
  38. package/packages/components/sh-table/js/excel_to_json.js +313 -313
  39. package/packages/components/sh-table/js/props.js +305 -305
  40. package/packages/components/sh-table/js/tableMethods.js +167 -167
  41. package/packages/components/sh-table/js/useTable.js +636 -636
  42. package/packages/components/sh-table/table.vue +217 -217
  43. package/packages/components/sh-tabs/index.vue +426 -426
  44. package/packages/components/sh-tag/index.vue +168 -168
  45. package/packages/components/sh-toolbar/index.vue +182 -182
  46. package/packages/components/sh-tree/components/table-tree.vue +289 -289
  47. package/packages/components/sh-tree/mixin/treeProps.js +122 -122
  48. package/packages/components/sh-upload/index.vue +535 -535
  49. package/packages/components/sh-water-fall/index.vue +80 -80
  50. package/packages/components/sh-water-mark/index.vue +96 -96
  51. package/packages/css/index.js +4 -4
  52. package/packages/directive/index.js +19 -19
  53. package/packages/directive/module/click-out.js +14 -14
  54. package/packages/directive/module/draggable.js +42 -42
  55. package/packages/directive/module/line-clamp.js +22 -22
  56. package/packages/directive/module/prevent-click.js +18 -18
  57. package/packages/directive/module/resize.js +14 -14
  58. package/packages/directive/module/ripple.js +166 -166
  59. package/packages/index.js +39 -39
  60. package/packages/mixin/index.js +86 -86
  61. package/packages/other/sh-cron-modal/components/cron-content.vue +294 -294
  62. package/packages/other/sh-cron-modal/index.vue +81 -81
  63. package/packages/other/sh-cron-modal/mixin/cron-emits.js +1 -1
  64. package/packages/other/sh-cron-modal/mixin/cron-props.js +9 -9
  65. package/packages/other/sh-cron-modal/tabs/cron-week-box.vue +126 -126
  66. package/packages/other/sh-menu/index.vue +326 -326
  67. package/packages/other/sh-menu/menu-group-content.vue +136 -136
  68. package/packages/other/sh-menu/menu-item-content.vue +71 -71
  69. package/packages/other/sh-menu-card/index.vue +250 -250
  70. package/packages/other/sh-menu-card/menu-box.vue +87 -87
  71. package/packages/other/sh-preview/components/sh-excel.vue +163 -163
  72. package/packages/other/sh-preview/js/data-hook.js +41 -41
  73. package/packages/other/sh-preview/js/data-props.js +15 -15
  74. package/packages/other/sh-system-tip/index.vue +115 -115
  75. package/packages/utils/resize.js +69 -70
  76. package/packages/utils/transfer-queue.js +12 -12
  77. package/packages/vxeTable/index.js +193 -184
  78. package/packages/vxeTable/plugins/export.js +450 -450
  79. package/packages/vxeTable/render/cell/vxe-render-img.vue +27 -27
  80. package/packages/vxeTable/render/cell/vxe-render-table.vue +51 -51
  81. package/packages/vxeTable/render/cell/vxe-render-time.vue +44 -44
  82. package/packages/vxeTable/render/cell/vxe-render-tree.vue +70 -70
  83. package/packages/vxeTable/render/filters/vxe-filter-input.vue +26 -26
  84. package/packages/vxeTable/render/filters/vxe-filter-time.vue +26 -26
  85. package/packages/vxeTable/render/globalRenders.jsx +514 -514
  86. package/packages/vxeTable/render/mixin/cell-hooks.js +198 -198
  87. package/packages/vxeTable/render/mixin/cell-props.js +23 -23
  88. package/packages/vxeTable/render/mixin/filter-hooks.js +46 -46
  89. package/tsconfig.json +25 -0
  90. package/types/component.d.ts +1 -0
  91. package/types/index.ts +0 -0
@@ -1,636 +1,636 @@
1
- import { computed, reactive, ref, watch } from 'vue'
2
- import { columnDefaultFilterMethod, tableFooterCompute, getTransfarFields, getFieldsRules, turnColumnItemFilters } from './tableMethods'
3
-
4
- // 记录自定义参数,传给vxe要过滤掉
5
- let omitProps = [
6
- 'dataSourse',
7
- 'disabled',
8
- 'customLayout',
9
- 'columnObj',
10
- 'globalConfig',
11
- 'footerCalculate',
12
- 'tableName',
13
- 'queryData',
14
- 'onToolbarBtnAddBefore',
15
- 'onToolbarBtnDeleteBefore',
16
- 'onExportMethod',
17
- 'onPrintMethod'
18
- ]
19
- const globalConfigDefault = {
20
- tableName: '',
21
- title: false, // 是否显示 tableName
22
- selectType: '', // 是否选择框 空 radio checkbox
23
- seq: false, // 是否展示序号列
24
- ghost: false, // 是否开启透明
25
- search: false, // 表格是否开启查询,默认不开启,根据columns配置字段 search 为 true
26
- globalFilter: false, // 表格是否开启全局过滤
27
- zoom: false, // 表格是否开启缩放
28
- formToggleNum: 4,
29
- formToggle: true
30
- }
31
- const exportAndPrintDefault = {
32
- mode: 'current',
33
- original: false,
34
- message: true,
35
- isHeader: true,
36
- isColgroup: true,
37
- isFooter: false,
38
- isMerge: false,
39
- isAllExpand: true,
40
- download: true,
41
- useStyle: false,
42
- columnFilterMethod: columnDefaultFilterMethod
43
- }
44
- const toolsList = [
45
- { status: 'primary', code: 'addRow', content: '新增行' },
46
- { status: 'danger', code: 'deleteRow', content: '删除行' },
47
- { status: 'primary', code: 'import', icon: 'vxe-icon-upload', content: '导入' },
48
- { status: 'success', code: 'export', icon: 'vxe-icon-download', content: '导出' },
49
- { status: 'warning', code: 'print', icon: 'vxe-icon-print', content: '打印' }
50
- ]
51
- // 表头默认值
52
- const columnObjDefault = { minWidth: 120, sortable: true, filter: true }
53
- // 表头默认列
54
- const columnsMapDefault = {
55
- checkbox: { title: '', type: 'checkbox', width: 60, align: 'center', fixed: 'left', sortable: false, resizable: false, className: 'table-row-checkbox' },
56
- radio: { title: '单选', type: 'radio', width: 60, align: 'center', fixed: 'left', sortable: false, resizable: false, className: 'table-row-radio' },
57
- seq: { title: '序号', type: 'seq', width: 70, align: 'center', fixed: 'left', sortable: false, resizable: false, className: 'table-row-seq' }
58
- }
59
-
60
- export default function (props, context, proxy, isGrid) {
61
- const { $vUtils, $vxePluginNames } = proxy
62
- const { emit, slots } = context
63
-
64
- const tableRef = ref()
65
- const renderKey = ref(1) // 渲染key值
66
- const selectedRowKeys = ref([]) // table选中keys
67
- const selectionRows = ref([]) // table选中records
68
- const tableColumnsFixed = ref([]) // 表格格式化后表头
69
- const tableFilterData = ref(null) // 表格全表搜索数据
70
- const tableColumnsFlat = ref([]) // 多层转一维后表头
71
- const tableFormItems = ref([]) // 根据表格表头生成表单项配置
72
- const tableEditRules = ref({}) // 表格根据表头自动生成验证规则
73
- const tableFilterText = ref('') // 全局过滤关键字
74
- const tableCurrentRowData = ref(null) // 表格当前高亮行
75
- const tableRowDefaultData = ref({}) // 根据表头生成行默认值
76
-
77
- const wrapHeight = computed(() => ([100, '100%', 'auto'].includes(props.height) ? '100%' : 'auto'))
78
- const hasTree = computed(() => props.columns.some(_ => _.treeNode))
79
- const tableVmConfig = computed(() => ({ size: props.size }))
80
- const tableGlobalConfig = computed(() => Object.assign({}, globalConfigDefault, props.globalConfig))
81
- const tableTools = computed(() => {
82
- let tools = props.globalConfig?.tools || []
83
- return toolsList.filter(tool => tools.includes(tool.code))
84
- })
85
- const tableViewData = computed(() => tableFilterData.value || props.dataSourse)
86
- const tablePrevColumns = computed(() => {
87
- let prevColumns = []
88
- const { seq, selectType } = tableGlobalConfig.value
89
- if (selectType) prevColumns.push(columnsMapDefault[selectType])
90
- if (seq) prevColumns.push(columnsMapDefault.seq)
91
- return prevColumns
92
- })
93
- const tableColumns = computed(() => {
94
- return tablePrevColumns.value.concat(tableColumnsFixed.value)
95
- })
96
- const tableColumnObjConfig = computed(() => Object.assign({}, columnObjDefault, props.columnObj))
97
- const tableColumnConfig = computed(() => Object.assign({ isCurrent: false, isHover: true, resizable: true }, props.columnConfig))
98
- const tablePagerConfig = computed(() =>
99
- Object.assign({ enabled: Boolean(props.pagerConfig), total: 0, className: 'sh-table-footer', slots: { left: 'pagerLeft', right: 'pagerRight' } }, props.pagerConfig)
100
- )
101
- const tableCheckboxConfig = computed(() => {
102
- return Object.assign({ range: !hasTree.value }, props.checkboxConfig)
103
- })
104
- const tableTreeConfig = computed(() => {
105
- return hasTree.value ? Object.assign({}, props.treeConfig) : null
106
- })
107
- const tableSeqConfig = computed(() => {
108
- return {
109
- seqMethod: ({ $table, seq, $seq, $$seq, $rowIndex }) => {
110
- const tablePage = tablePagerConfig.value.enabled
111
- if ($$seq) {
112
- return $$seq
113
- } else if (tablePage) {
114
- const pageStart = (+tablePagerConfig.value.pageSize || 50) * ((+tablePagerConfig.value.currentPage || 1) - 1)
115
- return hasTree.value && $seq ? Number(pageStart) + Number($seq) + '.' + seq : Number(pageStart) + Number(seq)
116
- } else if (hasTree.value) {
117
- return $seq ? $seq + '.' + seq : seq
118
- }
119
- return seq === -1 ? $rowIndex + 1 : seq
120
- }
121
- }
122
- })
123
- const tableExportConfig = computed(() =>
124
- Object.assign(
125
- {
126
- filename: tableGlobalConfig.value.tableName,
127
- sheetName: 'sheet1',
128
- type: 'xlsx',
129
- types: ['xlsx', 'csv', 'pdf', 'html', 'xml', 'txt'],
130
- beforeExportMethod: obj => getExportPrintDataByOption(obj, 'export')
131
- },
132
- exportAndPrintDefault,
133
- props.exportConfig
134
- )
135
- )
136
- const tablePrintConfig = computed(() =>
137
- Object.assign(
138
- {
139
- filename: tableGlobalConfig.value.tableName,
140
- sheetName: tableGlobalConfig.value.tableName,
141
- beforePrintMethod: obj => getExportPrintDataByOption(obj, 'print')
142
- },
143
- exportAndPrintDefault,
144
- props.printConfig
145
- )
146
- )
147
- const tableEditConfig = computed(() =>
148
- Object.assign({ enabled: !props.disabled, showStatus: !props.disabled, showUpdateStatus: !props.disabled, showInsertStatus: !props.disabled }, props.editConfig)
149
- )
150
- const tableQueryConfig = computed(() => {
151
- let otherConfig = isGrid ? { transformitem: false, items: tableFormItems.value } : { items: props.columns }
152
- return Object.assign(
153
- { data: props.queryData, rules: tableEditRules.value, validConfig: props.validConfig, globalConfig: tableGlobalConfig.value, valid: false, footer: true },
154
- otherConfig,
155
- tableVmConfig.value
156
- )
157
- })
158
- const tableFilterConfig = computed(() => Object.assign({ clearable: true, type: 'search', placeholder: '全局关键字搜索' }, tableVmConfig.value))
159
- const tableSlots = computed(() => {
160
- let disSlots = ['head', 'form', 'formLeft', 'formRight', 'toolbar', 'toolbarLeft', 'toolbarRight', 'pagerLeft', 'pagerRight']
161
- return Object.keys(slots).filter(key => !disSlots.includes(key))
162
- })
163
- const tableBindConfig = computed(() => {
164
- let defaultProps = { footerMethod: tableFooterMethod, footerSpanMethod: tableFooterSpanMethod }
165
- let tableProps = $vUtils.omit(props, (val, key) => {
166
- return omitProps.includes(key) || $vUtils.isNone(val)
167
- })
168
- let shProps = {
169
- data: tableViewData.value,
170
- stripe: props.stripe && !tableTreeConfig.value,
171
- columnConfig: tableColumnConfig.value,
172
- checkboxConfig: tableCheckboxConfig.value,
173
- treeConfig: tableTreeConfig.value,
174
- seqConfig: tableSeqConfig.value,
175
- editConfig: tableEditConfig.value,
176
- editRules: tableEditRules.value,
177
- exportConfig: tableExportConfig.value,
178
- printConfig: tablePrintConfig.value
179
- }
180
- return Object.assign(defaultProps, tableProps, shProps)
181
- })
182
- const importBindConfig = reactive({
183
- modalConfig: { modelValue: false, title: '导入报表', width: '900', showFooter: false, transfer: false },
184
- needValidate: true,
185
- columns: props.columns,
186
- importConfig: props.importConfig,
187
- importRules: tableEditRules.value
188
- })
189
-
190
- // 获取选中数据
191
- const getSelectionData = () => {
192
- return selectionRows.value || []
193
- }
194
- // 获取全部数据
195
- // visible为true获取视图数据
196
- const getFullData = params => {
197
- const { visible = false, deleteXid = false } = params || {}
198
- let data = $vUtils.clone(tableRef.value.getTableData().fullData, true)
199
- const columns = tableRef.value.getColumns()
200
- let rnameColumns = columns.filter(col => col.rname)
201
- rnameColumns.forEach(col => {
202
- let { property, rname, rprops } = col
203
- data.forEach(row => {
204
- let cellValue = $vUtils.get(row, property)
205
- let { rvalue, rtext } = $vUtils.formatRender(cellValue, property, row, rname, rprops, proxy)
206
- $vUtils.set(row, property, visible ? rtext : rvalue)
207
- if (deleteXid) delete row._XID
208
- })
209
- })
210
- return data
211
- }
212
- // 表格打印、导出统一导出前渲染数据
213
- const getExportPrintDataByOption = (obj = {}, type) => {
214
- let { options, content } = obj
215
- let { data, columns, mode, original } = options
216
- if (!data) {
217
- options.data = mode === 'selected' ? getSelectionData() : getFullData({ visible: !original })
218
- }
219
- return type === 'print' ? content : obj
220
- }
221
-
222
- // 默认求底部绑定方法vxe
223
- const tableFooterMethod = ({ columns, data }) => {
224
- const { footerCalculate } = props
225
- let footerData = []
226
- let footerCalculateList = footerCalculate.calculate || []
227
- footerCalculateList.forEach(key => {
228
- footerData.push(tableFooterCompute(columns, data, key, footerCalculate[key]))
229
- })
230
- return footerData
231
- }
232
- const tableFooterSpanMethod = ({ $rowIndex, column, $columnIndex, data }) => {
233
- let colspan = tablePrevColumns.value.length || 1
234
- if (column.type === 'seq') {
235
- return { rowspan: 1, colspan: colspan }
236
- } else if (column.type === 'checkbox' || column.type === 'radio') {
237
- return { rowspan: 1, colspan: 0 }
238
- }
239
- return { rowspan: 1, colspan: 1 }
240
- }
241
-
242
- // -------- 表格
243
- // 当前行变化
244
- const onCurrentChange = params => {
245
- tableCurrentRowData.value = params
246
- emit('current-change', params)
247
- }
248
- // 单选框变化
249
- const onRadioChange = params => {
250
- selectionRows.value = [params.row]
251
- emit('radio-change', selectionRows.value, params)
252
- }
253
- // 复选框变化
254
- const onSelectionChange = params => {
255
- let { records } = params
256
- if (tableTreeConfig.value && tableTreeConfig.value?.transform) {
257
- let keyField = tableTreeConfig.value?.rowField || props.rowConfig.keyField || '_XID'
258
- let keyRowChild = '_X_ROW_CHILD'
259
- let childRowsKeys = []
260
- $vUtils.eachTree(records, row => {
261
- if (row[keyRowChild] && row[keyRowChild].length > 0) {
262
- row[keyRowChild].forEach(child => {
263
- childRowsKeys.push(child[keyField])
264
- })
265
- }
266
- })
267
- records = records.filter(row => !childRowsKeys.includes(row[keyField]))
268
- }
269
- selectionRows.value = records
270
- emit('selection-change', selectionRows.value, params)
271
- }
272
- // 单元格点击事件
273
- const onCellClick = params => {
274
- emit('cell-click', params)
275
- }
276
- // 单元格双击事件
277
- const onCellDblClick = params => {
278
- emit('cell-dblclick', params)
279
- }
280
- // 单元格双击事件
281
- const onHeaderCellClick = params => {
282
- emit('header-cell-click', params)
283
- }
284
- // 排序变化事件
285
- const onSortChange = params => {
286
- emit('sort-change', params)
287
- }
288
- // 过滤变化事件
289
- const onFilterChange = params => {
290
- emit('filter-change', params)
291
- }
292
- // 当行展开或收起时会触发该事件
293
- const onToggleRowExpand = params => {
294
- emit('toggle-row-expand', params)
295
- }
296
- // 当树节点展开或收起时会触发该事件
297
- const onToggleTreeExpand = params => {
298
- emit('toggle-tree-expand', params)
299
- }
300
- // 只对 edit-config 配置时有效,单元格编辑状态下被关闭时会触发该事件
301
- const onEditClosed = params => {
302
- // 此操作火狐浏览器(bug(vxe):编辑后不触发渲染器的blur问题)
303
- const userAgent = navigator.userAgent
304
- if (userAgent.indexOf('Firefox') !== -1) {
305
- let { row, column } = params
306
- let editModel = $vUtils.get(column, 'params.__RowEditModelValue')
307
- if (editModel !== undefined) {
308
- if (['$vMoney'].includes(column.rname) && !$vUtils.isNone(editModel)) editModel = $vUtils.multiply(editModel, column.rprops.moneyUnit || 1)
309
- let { rvalue, rtext } = $vUtils.formatRender(editModel, column.property, row, column.rname, column.rprops, proxy, true)
310
- editModel = rvalue
311
- $vUtils.set(row, column.property, editModel)
312
- delete column.params.__RowEditModelValue
313
- }
314
- }
315
- emit('edit-closed', params)
316
- }
317
- // 只对 edit-config 配置时有效,单元格被激活编辑时会触发该事件
318
- const onEditActived = params => {
319
- emit('edit-actived', params)
320
- }
321
- // 滚动事件
322
- const onScroll = params => {
323
- emit('scroll', params)
324
- }
325
- // 如果与工具栏关联,在自定义列按钮被手动点击后会触发该事件
326
- const onCustom = params => {
327
- emit('custom', params)
328
- }
329
- // 分页变化触发
330
- const onPageChange = params => {
331
- selectionRows.value = []
332
- emit('page-change', params)
333
- }
334
-
335
- // -------- 工具栏
336
- // 只对 toolbar.buttons 配置时有效,当左侧按钮被点击时会后触发该事件
337
- const onToolbarButtonClick = params => {
338
- emit('toolbar-button-click', params)
339
- }
340
- // 只对 toolbar.tools 配置时有效,当右侧工具被点击时会后触发该事件
341
- const onToolbarToolClick = params => {
342
- emit('toolbar-tool-click', params)
343
- }
344
-
345
- // -------- 搜索
346
- // 表单展开全部/收起切换事件
347
- const onFormCollapsed = value => {
348
- setTimeout(() => {
349
- tableRef.value.recalculate(true)
350
- })
351
- }
352
- const onFormSubmit = () => {
353
- emit('form-submit', props.queryData)
354
- }
355
- // 表单重置
356
- const onFormReset = params => {
357
- emit('form-reset', params)
358
- }
359
- // 表单项编辑回调
360
- const onFormEditClosed = (obj, renderbox, $form) => {
361
- emit('form-edit-closed', obj, renderbox, $form)
362
- }
363
- // 表单校验不通过
364
- const onFormSubmitInvalid = obj => {
365
- emit('form-submit-invalid', obj)
366
- }
367
-
368
- // // vxe组件方法可通过 tableRef 调用
369
- // 表格导入方法
370
- const setImportData = params => {
371
- emit('import-confirm', params)
372
- }
373
-
374
- // 初始化生成新表头数据
375
- const initTableColumns = (columns = []) => {
376
- let rules = getFieldsRules(columns)
377
- initEditRules(rules)
378
- if (isGrid) {
379
- let { columnsArr, columnsFlatArr, formItemsArr } = getTransfarFields(columns, tableColumnObjConfig.value, tableGlobalConfig.value.search)
380
- tableColumnsFlat.value = columnsFlatArr
381
- tableFormItems.value = formItemsArr
382
- tableColumnsFixed.value = $vUtils.clone(columnsArr, true)
383
- }
384
- }
385
- // 初始化验证规则
386
- const initEditRules = rules => {
387
- if (rules && $vUtils.isPlainObject(rules)) {
388
- Object.keys(rules).forEach(key => {
389
- if (tableEditRules.value[key]) {
390
- tableEditRules.value[key] = Array.from(new Set(tableEditRules.value[key].concat(rules[key])))
391
- } else {
392
- tableEditRules.value[key] = rules[key]
393
- }
394
- })
395
- }
396
- }
397
- // 初始化表头配置默认值
398
- const initColsDefaultValue = () => {
399
- let colsDefaultValue = {}
400
- let colsFormulaValue = {}
401
- $vUtils.eachTree(props.columns, item => {
402
- let columnProps = item.renderProps || item.editRender?.props || item.cellRender?.props || {}
403
- if (!$vUtils.isNone(columnProps.defaultValue)) {
404
- colsDefaultValue[item.field] = columnProps.defaultValue
405
- }
406
- if (!$vUtils.isNone(columnProps.formula)) {
407
- colsFormulaValue[item.field] = columnProps.formula
408
- }
409
- })
410
- tableRowDefaultData.value = colsDefaultValue
411
- if (Array.isArray(props.dataSourse)) {
412
- props.dataSourse.forEach(row => {
413
- if (Object.keys(colsDefaultValue).length > 0) {
414
- Object.keys(colsDefaultValue).forEach(defaultKey => {
415
- if ($vUtils.isNone($vUtils.get(row, defaultKey))) {
416
- $vUtils.set(row, defaultKey, colsDefaultValue[defaultKey])
417
- }
418
- })
419
- }
420
- if (Object.keys(colsFormulaValue).length > 0) {
421
- Object.keys(colsFormulaValue).forEach(formulaKey => {
422
- let formulaValue = $vUtils.calculate(colsFormulaValue[formulaKey], row)
423
- $vUtils.set(row, formulaKey, formulaValue)
424
- })
425
- }
426
- })
427
- }
428
- }
429
-
430
- // 全局搜索输入框事件
431
- const handleTableFilter = obj => {
432
- let filterText = tableFilterText.value
433
- let filterData = null
434
- if (filterText) {
435
- let searchFields = []
436
- let tableColumnsAll = tableRef.value.getColumns()
437
- tableColumnsAll.forEach(col => {
438
- let renderObj = col.cellRender || col.editRender || col.itemRender
439
- let noSearchArr = ['$vGlobalOption', '$vImg', '$vCheckbox', '$vRadio', '$vUpload', '$vCode', 'seq', 'checkbox', 'radio']
440
- if (col.property && renderObj && renderObj.name && !noSearchArr.includes(renderObj.name) && !noSearchArr.includes(col.type)) {
441
- searchFields.push({ rkey: col.property, rname: renderObj.name, rprops: Object.assign({}, renderObj.props, col.rprops) })
442
- }
443
- })
444
- filterData = $vUtils.searchTree(props.dataSourse, row => {
445
- return searchFields.some(item => {
446
- let cellValue = $vUtils.get(row, item.rkey)
447
- let { rtext } = $vUtils.formatRender(cellValue, item.rkey, row, item.rname, item.rprops, proxy)
448
- return $vUtils.trim(rtext).toLowerCase().indexOf(filterText) > -1
449
- })
450
- })
451
- }
452
- if (tableFilterData.value === null && !filterText) {
453
- return
454
- }
455
- tableFilterData.value = filterData
456
- }
457
- // 表格验证方法
458
- const validate = (rows = true) => {
459
- return tableRef.value.validate(rows)
460
- }
461
- // 刷新表格视图
462
- const refreshRender = () => {
463
- renderKey.value++
464
- }
465
- // 表格工具按钮点击
466
- const handleTableTool = ({ code }) => {
467
- switch (code) {
468
- case 'addRow':
469
- handleTableAddRow(null, undefined, true)
470
- break
471
- case 'deleteRow':
472
- handleTableDeleteRow(null, true)
473
- break
474
- case 'import':
475
- handleTableImportBtn()
476
- break
477
- case 'export':
478
- handleTableExportBtn()
479
- break
480
- case 'print':
481
- handleTablePrintBtn()
482
- break
483
- }
484
- }
485
- // 表格导出按钮
486
- const handleTableExportBtn = options => {
487
- if (typeof props.onExportMethod === 'function') {
488
- return props.onExportMethod(options)
489
- }
490
- return tableRef.value.openExport(options)
491
- }
492
- // 表格导入按钮
493
- const handleTableImportBtn = () => {
494
- importBindConfig.modalConfig.modelValue = true
495
- }
496
- // 表格打印按鈕
497
- const handleTablePrintBtn = options => {
498
- if (typeof props.onPrintMethod === 'function') {
499
- return props.onPrintMethod(options)
500
- }
501
- return tableRef.value.openPrint(options)
502
- }
503
-
504
- // 自定义操作列点击事件
505
- const handleGoptionClick = async (btnObj, dataObj) => {
506
- if (btnObj.code === 'delete' || btnObj.idConfirm) {
507
- await proxy.msgconfirm({ content: btnObj.ConfirmContent || `确定${btnObj.content}吗?` })
508
- }
509
- emit('globaloption', btnObj, dataObj)
510
- }
511
- // 新增行按钮
512
- const handleTableAddRow = async (rows, index = -1, isTool = false) => {
513
- let addRows = rows ? $vUtils.clone(rows, true) : tableRowDefaultData.value
514
- if (!isTool && typeof props.onToolbarBtnAddBefore === 'function') {
515
- addRows = await props.onToolbarBtnAddBefore(addRows)
516
- }
517
- // 删除主键,以防排序冲突
518
- let mainKeyField = props.rowConfig?.keyField || '_XID'
519
- if (Array.isArray(addRows)) {
520
- addRows.forEach(item => {
521
- delete item[mainKeyField]
522
- })
523
- } else {
524
- delete addRows[mainKeyField]
525
- }
526
- let { row: newRow } = await tableRef.value.insertAt(addRows, index)
527
- await tableRef.value.setActiveRow(newRow)
528
- if (isTool) emit('toolbaroption', 'add', newRow, tableRef.value)
529
- }
530
- // 删除行按钮
531
- const handleTableDeleteRow = async (rows, isTool = false) => {
532
- let deleteRows = rows
533
- if (isTool) {
534
- let selectedRows = getSelectionData()
535
- if (selectedRows.length < 1) {
536
- proxy.msgwarning('请选择要删除的行!')
537
- return
538
- }
539
- deleteRows = selectedRows
540
- await proxy.msgconfirm({ content: `确定删除吗?` })
541
- } else if (typeof props.onToolbarBtnDeleteBefore === 'function') {
542
- let result = await props.onToolbarBtnDeleteBefore(deleteRows)
543
- if (!result) return
544
- }
545
- await tableRef.value.remove(deleteRows)
546
- if (selectionRows.value && selectionRows.value.length > 0) {
547
- let keyField = props.rowConfig.keyField || proxy.$vTableSetup.table.rowConfig.keyField
548
- selectionRows.value = selectionRows.value.filter(sr => !deleteRows.find(dr => dr[keyField] === sr[keyField]))
549
- }
550
- if (isTool) emit('toolbaroption', 'delete', deleteRows, tableRef.value)
551
- }
552
-
553
- watch(
554
- () => props.columns,
555
- value => {
556
- initTableColumns(value)
557
- },
558
- {
559
- deep: true,
560
- immediate: true
561
- }
562
- )
563
- watch(
564
- () => props.dataSourse,
565
- value => {
566
- initColsDefaultValue()
567
- selectionRows.value = []
568
- },
569
- {
570
- immediate: true
571
- }
572
- )
573
- watch(
574
- () => props.editRules,
575
- value => {
576
- initEditRules(value)
577
- },
578
- {
579
- deep: true,
580
- immediate: true
581
- }
582
- )
583
-
584
- return {
585
- slots,
586
- tableRef,
587
- renderKey,
588
- wrapHeight,
589
- tableGlobalConfig,
590
- tablePrevColumns,
591
- tableColumns,
592
- tableColumnObjConfig,
593
- tablePagerConfig,
594
- tableQueryConfig,
595
- tableFilterText,
596
- tableFilterConfig,
597
- tableFilterData,
598
- tableTools,
599
- tableSlots,
600
- selectionRows,
601
- tableBindConfig,
602
- importBindConfig,
603
- onCurrentChange,
604
- onRadioChange,
605
- onSelectionChange,
606
- onCellClick,
607
- onCellDblClick,
608
- onHeaderCellClick,
609
- onSortChange,
610
- onFilterChange,
611
- onToggleRowExpand,
612
- onToggleTreeExpand,
613
- onEditClosed,
614
- onEditActived,
615
- onScroll,
616
- onCustom,
617
- onPageChange,
618
- onToolbarButtonClick,
619
- onToolbarToolClick,
620
- handleGoptionClick,
621
- onFormSubmit,
622
- onFormReset,
623
- onFormCollapsed,
624
- onFormEditClosed,
625
- handleTableFilter,
626
- handleTableTool,
627
- setImportData,
628
- refreshRender,
629
- validate,
630
- getSelectionData,
631
- getFullData,
632
- handleTableAddRow,
633
- handleTableDeleteRow,
634
- turnColumnItemFilters
635
- }
636
- }
1
+ import { computed, reactive, ref, watch } from 'vue'
2
+ import { columnDefaultFilterMethod, tableFooterCompute, getTransfarFields, getFieldsRules, turnColumnItemFilters } from './tableMethods'
3
+
4
+ // 记录自定义参数,传给vxe要过滤掉
5
+ let omitProps = [
6
+ 'dataSourse',
7
+ 'disabled',
8
+ 'customLayout',
9
+ 'columnObj',
10
+ 'globalConfig',
11
+ 'footerCalculate',
12
+ 'tableName',
13
+ 'queryData',
14
+ 'onToolbarBtnAddBefore',
15
+ 'onToolbarBtnDeleteBefore',
16
+ 'onExportMethod',
17
+ 'onPrintMethod'
18
+ ]
19
+ const globalConfigDefault = {
20
+ tableName: '',
21
+ title: false, // 是否显示 tableName
22
+ selectType: '', // 是否选择框 空 radio checkbox
23
+ seq: false, // 是否展示序号列
24
+ ghost: false, // 是否开启透明
25
+ search: false, // 表格是否开启查询,默认不开启,根据columns配置字段 search 为 true
26
+ globalFilter: false, // 表格是否开启全局过滤
27
+ zoom: false, // 表格是否开启缩放
28
+ formToggleNum: 4,
29
+ formToggle: true
30
+ }
31
+ const exportAndPrintDefault = {
32
+ mode: 'current',
33
+ original: false,
34
+ message: true,
35
+ isHeader: true,
36
+ isColgroup: true,
37
+ isFooter: false,
38
+ isMerge: false,
39
+ isAllExpand: true,
40
+ download: true,
41
+ useStyle: false,
42
+ columnFilterMethod: columnDefaultFilterMethod
43
+ }
44
+ const toolsList = [
45
+ { status: 'primary', code: 'addRow', content: '新增行' },
46
+ { status: 'danger', code: 'deleteRow', content: '删除行' },
47
+ { status: 'primary', code: 'import', icon: 'vxe-icon-upload', content: '导入' },
48
+ { status: 'success', code: 'export', icon: 'vxe-icon-download', content: '导出' },
49
+ { status: 'warning', code: 'print', icon: 'vxe-icon-print', content: '打印' }
50
+ ]
51
+ // 表头默认值
52
+ const columnObjDefault = { minWidth: 120, sortable: true, filter: true }
53
+ // 表头默认列
54
+ const columnsMapDefault = {
55
+ checkbox: { title: '', type: 'checkbox', width: 60, align: 'center', fixed: 'left', sortable: false, resizable: false, className: 'table-row-checkbox' },
56
+ radio: { title: '单选', type: 'radio', width: 60, align: 'center', fixed: 'left', sortable: false, resizable: false, className: 'table-row-radio' },
57
+ seq: { title: '序号', type: 'seq', width: 70, align: 'center', fixed: 'left', sortable: false, resizable: false, className: 'table-row-seq' }
58
+ }
59
+
60
+ export default function (props, context, proxy, isGrid) {
61
+ const { $vUtils, $vxePluginNames } = proxy
62
+ const { emit, slots } = context
63
+
64
+ const tableRef = ref()
65
+ const renderKey = ref(1) // 渲染key值
66
+ const selectedRowKeys = ref([]) // table选中keys
67
+ const selectionRows = ref([]) // table选中records
68
+ const tableColumnsFixed = ref([]) // 表格格式化后表头
69
+ const tableFilterData = ref(null) // 表格全表搜索数据
70
+ const tableColumnsFlat = ref([]) // 多层转一维后表头
71
+ const tableFormItems = ref([]) // 根据表格表头生成表单项配置
72
+ const tableEditRules = ref({}) // 表格根据表头自动生成验证规则
73
+ const tableFilterText = ref('') // 全局过滤关键字
74
+ const tableCurrentRowData = ref(null) // 表格当前高亮行
75
+ const tableRowDefaultData = ref({}) // 根据表头生成行默认值
76
+
77
+ const wrapHeight = computed(() => ([100, '100%', 'auto'].includes(props.height) ? '100%' : 'auto'))
78
+ const hasTree = computed(() => props.columns.some(_ => _.treeNode))
79
+ const tableVmConfig = computed(() => ({ size: props.size }))
80
+ const tableGlobalConfig = computed(() => Object.assign({}, globalConfigDefault, props.globalConfig))
81
+ const tableTools = computed(() => {
82
+ let tools = props.globalConfig?.tools || []
83
+ return toolsList.filter(tool => tools.includes(tool.code))
84
+ })
85
+ const tableViewData = computed(() => tableFilterData.value || props.dataSourse)
86
+ const tablePrevColumns = computed(() => {
87
+ let prevColumns = []
88
+ const { seq, selectType } = tableGlobalConfig.value
89
+ if (selectType) prevColumns.push(columnsMapDefault[selectType])
90
+ if (seq) prevColumns.push(columnsMapDefault.seq)
91
+ return prevColumns
92
+ })
93
+ const tableColumns = computed(() => {
94
+ return tablePrevColumns.value.concat(tableColumnsFixed.value)
95
+ })
96
+ const tableColumnObjConfig = computed(() => Object.assign({}, columnObjDefault, props.columnObj))
97
+ const tableColumnConfig = computed(() => Object.assign({ isCurrent: false, isHover: true, resizable: true }, props.columnConfig))
98
+ const tablePagerConfig = computed(() =>
99
+ Object.assign({ enabled: Boolean(props.pagerConfig), total: 0, className: 'sh-table-footer', slots: { left: 'pagerLeft', right: 'pagerRight' } }, props.pagerConfig)
100
+ )
101
+ const tableCheckboxConfig = computed(() => {
102
+ return Object.assign({ range: !hasTree.value }, props.checkboxConfig)
103
+ })
104
+ const tableTreeConfig = computed(() => {
105
+ return hasTree.value ? Object.assign({}, props.treeConfig) : null
106
+ })
107
+ const tableSeqConfig = computed(() => {
108
+ return {
109
+ seqMethod: ({ $table, seq, $seq, $$seq, $rowIndex }) => {
110
+ const tablePage = tablePagerConfig.value.enabled
111
+ if ($$seq) {
112
+ return $$seq
113
+ } else if (tablePage) {
114
+ const pageStart = (+tablePagerConfig.value.pageSize || 50) * ((+tablePagerConfig.value.currentPage || 1) - 1)
115
+ return hasTree.value && $seq ? Number(pageStart) + Number($seq) + '.' + seq : Number(pageStart) + Number(seq)
116
+ } else if (hasTree.value) {
117
+ return $seq ? $seq + '.' + seq : seq
118
+ }
119
+ return seq === -1 ? $rowIndex + 1 : seq
120
+ }
121
+ }
122
+ })
123
+ const tableExportConfig = computed(() =>
124
+ Object.assign(
125
+ {
126
+ filename: tableGlobalConfig.value.tableName,
127
+ sheetName: 'sheet1',
128
+ type: 'xlsx',
129
+ types: ['xlsx', 'csv', 'pdf', 'html', 'xml', 'txt'],
130
+ beforeExportMethod: obj => getExportPrintDataByOption(obj, 'export')
131
+ },
132
+ exportAndPrintDefault,
133
+ props.exportConfig
134
+ )
135
+ )
136
+ const tablePrintConfig = computed(() =>
137
+ Object.assign(
138
+ {
139
+ filename: tableGlobalConfig.value.tableName,
140
+ sheetName: tableGlobalConfig.value.tableName,
141
+ beforePrintMethod: obj => getExportPrintDataByOption(obj, 'print')
142
+ },
143
+ exportAndPrintDefault,
144
+ props.printConfig
145
+ )
146
+ )
147
+ const tableEditConfig = computed(() =>
148
+ Object.assign({ enabled: !props.disabled, showStatus: !props.disabled, showUpdateStatus: !props.disabled, showInsertStatus: !props.disabled }, props.editConfig)
149
+ )
150
+ const tableQueryConfig = computed(() => {
151
+ let otherConfig = isGrid ? { transformitem: false, items: tableFormItems.value } : { items: props.columns }
152
+ return Object.assign(
153
+ { data: props.queryData, rules: tableEditRules.value, validConfig: props.validConfig, globalConfig: tableGlobalConfig.value, valid: false, footer: true },
154
+ otherConfig,
155
+ tableVmConfig.value
156
+ )
157
+ })
158
+ const tableFilterConfig = computed(() => Object.assign({ clearable: true, type: 'search', placeholder: '全局关键字搜索' }, tableVmConfig.value))
159
+ const tableSlots = computed(() => {
160
+ let disSlots = ['head', 'form', 'formLeft', 'formRight', 'toolbar', 'toolbarLeft', 'toolbarRight', 'pagerLeft', 'pagerRight']
161
+ return Object.keys(slots).filter(key => !disSlots.includes(key))
162
+ })
163
+ const tableBindConfig = computed(() => {
164
+ let defaultProps = { footerMethod: tableFooterMethod, footerSpanMethod: tableFooterSpanMethod }
165
+ let tableProps = $vUtils.omit(props, (val, key) => {
166
+ return omitProps.includes(key) || $vUtils.isNone(val)
167
+ })
168
+ let shProps = {
169
+ data: tableViewData.value,
170
+ stripe: props.stripe && !tableTreeConfig.value,
171
+ columnConfig: tableColumnConfig.value,
172
+ checkboxConfig: tableCheckboxConfig.value,
173
+ treeConfig: tableTreeConfig.value,
174
+ seqConfig: tableSeqConfig.value,
175
+ editConfig: tableEditConfig.value,
176
+ editRules: tableEditRules.value,
177
+ exportConfig: tableExportConfig.value,
178
+ printConfig: tablePrintConfig.value
179
+ }
180
+ return Object.assign(defaultProps, tableProps, shProps)
181
+ })
182
+ const importBindConfig = reactive({
183
+ modalConfig: { modelValue: false, title: '导入报表', width: '900', showFooter: false, transfer: false },
184
+ needValidate: true,
185
+ columns: props.columns,
186
+ importConfig: props.importConfig,
187
+ importRules: tableEditRules.value
188
+ })
189
+
190
+ // 获取选中数据
191
+ const getSelectionData = () => {
192
+ return selectionRows.value || []
193
+ }
194
+ // 获取全部数据
195
+ // visible为true获取视图数据
196
+ const getFullData = params => {
197
+ const { visible = false, deleteXid = false } = params || {}
198
+ let data = $vUtils.clone(tableRef.value.getTableData().fullData, true)
199
+ const columns = tableRef.value.getColumns()
200
+ let rnameColumns = columns.filter(col => col.rname)
201
+ rnameColumns.forEach(col => {
202
+ let { property, rname, rprops } = col
203
+ data.forEach(row => {
204
+ let cellValue = $vUtils.get(row, property)
205
+ let { rvalue, rtext } = $vUtils.formatRender(cellValue, property, row, rname, rprops, proxy)
206
+ $vUtils.set(row, property, visible ? rtext : rvalue)
207
+ if (deleteXid) delete row._XID
208
+ })
209
+ })
210
+ return data
211
+ }
212
+ // 表格打印、导出统一导出前渲染数据
213
+ const getExportPrintDataByOption = (obj = {}, type) => {
214
+ let { options, content } = obj
215
+ let { data, columns, mode, original } = options
216
+ if (!data) {
217
+ options.data = mode === 'selected' ? getSelectionData() : getFullData({ visible: !original })
218
+ }
219
+ return type === 'print' ? content : obj
220
+ }
221
+
222
+ // 默认求底部绑定方法vxe
223
+ const tableFooterMethod = ({ columns, data }) => {
224
+ const { footerCalculate } = props
225
+ let footerData = []
226
+ let footerCalculateList = footerCalculate.calculate || []
227
+ footerCalculateList.forEach(key => {
228
+ footerData.push(tableFooterCompute(columns, data, key, footerCalculate[key]))
229
+ })
230
+ return footerData
231
+ }
232
+ const tableFooterSpanMethod = ({ $rowIndex, column, $columnIndex, data }) => {
233
+ let colspan = tablePrevColumns.value.length || 1
234
+ if (column.type === 'seq') {
235
+ return { rowspan: 1, colspan: colspan }
236
+ } else if (column.type === 'checkbox' || column.type === 'radio') {
237
+ return { rowspan: 1, colspan: 0 }
238
+ }
239
+ return { rowspan: 1, colspan: 1 }
240
+ }
241
+
242
+ // -------- 表格
243
+ // 当前行变化
244
+ const onCurrentChange = params => {
245
+ tableCurrentRowData.value = params
246
+ emit('current-change', params)
247
+ }
248
+ // 单选框变化
249
+ const onRadioChange = params => {
250
+ selectionRows.value = [params.row]
251
+ emit('radio-change', selectionRows.value, params)
252
+ }
253
+ // 复选框变化
254
+ const onSelectionChange = params => {
255
+ let { records } = params
256
+ if (tableTreeConfig.value && tableTreeConfig.value?.transform) {
257
+ let keyField = tableTreeConfig.value?.rowField || props.rowConfig.keyField || '_XID'
258
+ let keyRowChild = '_X_ROW_CHILD'
259
+ let childRowsKeys = []
260
+ $vUtils.eachTree(records, row => {
261
+ if (row[keyRowChild] && row[keyRowChild].length > 0) {
262
+ row[keyRowChild].forEach(child => {
263
+ childRowsKeys.push(child[keyField])
264
+ })
265
+ }
266
+ })
267
+ records = records.filter(row => !childRowsKeys.includes(row[keyField]))
268
+ }
269
+ selectionRows.value = records
270
+ emit('selection-change', selectionRows.value, params)
271
+ }
272
+ // 单元格点击事件
273
+ const onCellClick = params => {
274
+ emit('cell-click', params)
275
+ }
276
+ // 单元格双击事件
277
+ const onCellDblClick = params => {
278
+ emit('cell-dblclick', params)
279
+ }
280
+ // 单元格双击事件
281
+ const onHeaderCellClick = params => {
282
+ emit('header-cell-click', params)
283
+ }
284
+ // 排序变化事件
285
+ const onSortChange = params => {
286
+ emit('sort-change', params)
287
+ }
288
+ // 过滤变化事件
289
+ const onFilterChange = params => {
290
+ emit('filter-change', params)
291
+ }
292
+ // 当行展开或收起时会触发该事件
293
+ const onToggleRowExpand = params => {
294
+ emit('toggle-row-expand', params)
295
+ }
296
+ // 当树节点展开或收起时会触发该事件
297
+ const onToggleTreeExpand = params => {
298
+ emit('toggle-tree-expand', params)
299
+ }
300
+ // 只对 edit-config 配置时有效,单元格编辑状态下被关闭时会触发该事件
301
+ const onEditClosed = params => {
302
+ // 此操作火狐浏览器(bug(vxe):编辑后不触发渲染器的blur问题)
303
+ const userAgent = navigator.userAgent
304
+ if (userAgent.indexOf('Firefox') !== -1) {
305
+ let { row, column } = params
306
+ let editModel = $vUtils.get(column, 'params.__RowEditModelValue')
307
+ if (editModel !== undefined) {
308
+ if (['$vMoney'].includes(column.rname) && !$vUtils.isNone(editModel)) editModel = $vUtils.multiply(editModel, column.rprops.moneyUnit || 1)
309
+ let { rvalue, rtext } = $vUtils.formatRender(editModel, column.property, row, column.rname, column.rprops, proxy, true)
310
+ editModel = rvalue
311
+ $vUtils.set(row, column.property, editModel)
312
+ delete column.params.__RowEditModelValue
313
+ }
314
+ }
315
+ emit('edit-closed', params)
316
+ }
317
+ // 只对 edit-config 配置时有效,单元格被激活编辑时会触发该事件
318
+ const onEditActived = params => {
319
+ emit('edit-actived', params)
320
+ }
321
+ // 滚动事件
322
+ const onScroll = params => {
323
+ emit('scroll', params)
324
+ }
325
+ // 如果与工具栏关联,在自定义列按钮被手动点击后会触发该事件
326
+ const onCustom = params => {
327
+ emit('custom', params)
328
+ }
329
+ // 分页变化触发
330
+ const onPageChange = params => {
331
+ selectionRows.value = []
332
+ emit('page-change', params)
333
+ }
334
+
335
+ // -------- 工具栏
336
+ // 只对 toolbar.buttons 配置时有效,当左侧按钮被点击时会后触发该事件
337
+ const onToolbarButtonClick = params => {
338
+ emit('toolbar-button-click', params)
339
+ }
340
+ // 只对 toolbar.tools 配置时有效,当右侧工具被点击时会后触发该事件
341
+ const onToolbarToolClick = params => {
342
+ emit('toolbar-tool-click', params)
343
+ }
344
+
345
+ // -------- 搜索
346
+ // 表单展开全部/收起切换事件
347
+ const onFormCollapsed = value => {
348
+ setTimeout(() => {
349
+ tableRef.value.recalculate(true)
350
+ })
351
+ }
352
+ const onFormSubmit = () => {
353
+ emit('form-submit', props.queryData)
354
+ }
355
+ // 表单重置
356
+ const onFormReset = params => {
357
+ emit('form-reset', params)
358
+ }
359
+ // 表单项编辑回调
360
+ const onFormEditClosed = (obj, renderbox, $form) => {
361
+ emit('form-edit-closed', obj, renderbox, $form)
362
+ }
363
+ // 表单校验不通过
364
+ const onFormSubmitInvalid = obj => {
365
+ emit('form-submit-invalid', obj)
366
+ }
367
+
368
+ // // vxe组件方法可通过 tableRef 调用
369
+ // 表格导入方法
370
+ const setImportData = params => {
371
+ emit('import-confirm', params)
372
+ }
373
+
374
+ // 初始化生成新表头数据
375
+ const initTableColumns = (columns = []) => {
376
+ let rules = getFieldsRules(columns)
377
+ initEditRules(rules)
378
+ if (isGrid) {
379
+ let { columnsArr, columnsFlatArr, formItemsArr } = getTransfarFields(columns, tableColumnObjConfig.value, tableGlobalConfig.value.search)
380
+ tableColumnsFlat.value = columnsFlatArr
381
+ tableFormItems.value = formItemsArr
382
+ tableColumnsFixed.value = $vUtils.clone(columnsArr, true)
383
+ }
384
+ }
385
+ // 初始化验证规则
386
+ const initEditRules = rules => {
387
+ if (rules && $vUtils.isPlainObject(rules)) {
388
+ Object.keys(rules).forEach(key => {
389
+ if (tableEditRules.value[key]) {
390
+ tableEditRules.value[key] = Array.from(new Set(tableEditRules.value[key].concat(rules[key])))
391
+ } else {
392
+ tableEditRules.value[key] = rules[key]
393
+ }
394
+ })
395
+ }
396
+ }
397
+ // 初始化表头配置默认值
398
+ const initColsDefaultValue = () => {
399
+ let colsDefaultValue = {}
400
+ let colsFormulaValue = {}
401
+ $vUtils.eachTree(props.columns, item => {
402
+ let columnProps = item.renderProps || item.editRender?.props || item.cellRender?.props || {}
403
+ if (!$vUtils.isNone(columnProps.defaultValue)) {
404
+ colsDefaultValue[item.field] = columnProps.defaultValue
405
+ }
406
+ if (!$vUtils.isNone(columnProps.formula)) {
407
+ colsFormulaValue[item.field] = columnProps.formula
408
+ }
409
+ })
410
+ tableRowDefaultData.value = colsDefaultValue
411
+ if (Array.isArray(props.dataSourse)) {
412
+ props.dataSourse.forEach(row => {
413
+ if (Object.keys(colsDefaultValue).length > 0) {
414
+ Object.keys(colsDefaultValue).forEach(defaultKey => {
415
+ if ($vUtils.isNone($vUtils.get(row, defaultKey))) {
416
+ $vUtils.set(row, defaultKey, colsDefaultValue[defaultKey])
417
+ }
418
+ })
419
+ }
420
+ if (Object.keys(colsFormulaValue).length > 0) {
421
+ Object.keys(colsFormulaValue).forEach(formulaKey => {
422
+ let formulaValue = $vUtils.calculate(colsFormulaValue[formulaKey], row)
423
+ $vUtils.set(row, formulaKey, formulaValue)
424
+ })
425
+ }
426
+ })
427
+ }
428
+ }
429
+
430
+ // 全局搜索输入框事件
431
+ const handleTableFilter = obj => {
432
+ let filterText = tableFilterText.value
433
+ let filterData = null
434
+ if (filterText) {
435
+ let searchFields = []
436
+ let tableColumnsAll = tableRef.value.getColumns()
437
+ tableColumnsAll.forEach(col => {
438
+ let renderObj = col.cellRender || col.editRender || col.itemRender
439
+ let noSearchArr = ['$vGlobalOption', '$vImg', '$vCheckbox', '$vRadio', '$vUpload', '$vCode', 'seq', 'checkbox', 'radio']
440
+ if (col.property && renderObj && renderObj.name && !noSearchArr.includes(renderObj.name) && !noSearchArr.includes(col.type)) {
441
+ searchFields.push({ rkey: col.property, rname: renderObj.name, rprops: Object.assign({}, renderObj.props, col.rprops) })
442
+ }
443
+ })
444
+ filterData = $vUtils.searchTree(props.dataSourse, row => {
445
+ return searchFields.some(item => {
446
+ let cellValue = $vUtils.get(row, item.rkey)
447
+ let { rtext } = $vUtils.formatRender(cellValue, item.rkey, row, item.rname, item.rprops, proxy)
448
+ return $vUtils.trim(rtext).toLowerCase().indexOf(filterText) > -1
449
+ })
450
+ })
451
+ }
452
+ if (tableFilterData.value === null && !filterText) {
453
+ return
454
+ }
455
+ tableFilterData.value = filterData
456
+ }
457
+ // 表格验证方法
458
+ const validate = (rows = true) => {
459
+ return tableRef.value.validate(rows)
460
+ }
461
+ // 刷新表格视图
462
+ const refreshRender = () => {
463
+ renderKey.value++
464
+ }
465
+ // 表格工具按钮点击
466
+ const handleTableTool = ({ code }) => {
467
+ switch (code) {
468
+ case 'addRow':
469
+ handleTableAddRow(null, undefined, true)
470
+ break
471
+ case 'deleteRow':
472
+ handleTableDeleteRow(null, true)
473
+ break
474
+ case 'import':
475
+ handleTableImportBtn()
476
+ break
477
+ case 'export':
478
+ handleTableExportBtn()
479
+ break
480
+ case 'print':
481
+ handleTablePrintBtn()
482
+ break
483
+ }
484
+ }
485
+ // 表格导出按钮
486
+ const handleTableExportBtn = options => {
487
+ if (typeof props.onExportMethod === 'function') {
488
+ return props.onExportMethod(options)
489
+ }
490
+ return tableRef.value.openExport(options)
491
+ }
492
+ // 表格导入按钮
493
+ const handleTableImportBtn = () => {
494
+ importBindConfig.modalConfig.modelValue = true
495
+ }
496
+ // 表格打印按鈕
497
+ const handleTablePrintBtn = options => {
498
+ if (typeof props.onPrintMethod === 'function') {
499
+ return props.onPrintMethod(options)
500
+ }
501
+ return tableRef.value.openPrint(options)
502
+ }
503
+
504
+ // 自定义操作列点击事件
505
+ const handleGoptionClick = async (btnObj, dataObj) => {
506
+ if (btnObj.code === 'delete' || btnObj.idConfirm) {
507
+ await proxy.msgconfirm({ content: btnObj.ConfirmContent || `确定${btnObj.content}吗?` })
508
+ }
509
+ emit('globaloption', btnObj, dataObj)
510
+ }
511
+ // 新增行按钮
512
+ const handleTableAddRow = async (rows, index = -1, isTool = false) => {
513
+ let addRows = rows ? $vUtils.clone(rows, true) : tableRowDefaultData.value
514
+ if (!isTool && typeof props.onToolbarBtnAddBefore === 'function') {
515
+ addRows = await props.onToolbarBtnAddBefore(addRows)
516
+ }
517
+ // 删除主键,以防排序冲突
518
+ let mainKeyField = props.rowConfig?.keyField || '_XID'
519
+ if (Array.isArray(addRows)) {
520
+ addRows.forEach(item => {
521
+ delete item[mainKeyField]
522
+ })
523
+ } else {
524
+ delete addRows[mainKeyField]
525
+ }
526
+ let { row: newRow } = await tableRef.value.insertAt(addRows, index)
527
+ await tableRef.value.setActiveRow(newRow)
528
+ if (isTool) emit('toolbaroption', 'add', newRow, tableRef.value)
529
+ }
530
+ // 删除行按钮
531
+ const handleTableDeleteRow = async (rows, isTool = false) => {
532
+ let deleteRows = rows
533
+ if (isTool) {
534
+ let selectedRows = getSelectionData()
535
+ if (selectedRows.length < 1) {
536
+ proxy.msgwarning('请选择要删除的行!')
537
+ return
538
+ }
539
+ deleteRows = selectedRows
540
+ await proxy.msgconfirm({ content: `确定删除吗?` })
541
+ } else if (typeof props.onToolbarBtnDeleteBefore === 'function') {
542
+ let result = await props.onToolbarBtnDeleteBefore(deleteRows)
543
+ if (!result) return
544
+ }
545
+ await tableRef.value.remove(deleteRows)
546
+ if (selectionRows.value && selectionRows.value.length > 0) {
547
+ let keyField = props.rowConfig.keyField || proxy.$vTableSetup.table.rowConfig.keyField
548
+ selectionRows.value = selectionRows.value.filter(sr => !deleteRows.find(dr => dr[keyField] === sr[keyField]))
549
+ }
550
+ if (isTool) emit('toolbaroption', 'delete', deleteRows, tableRef.value)
551
+ }
552
+
553
+ watch(
554
+ () => props.columns,
555
+ value => {
556
+ initTableColumns(value)
557
+ },
558
+ {
559
+ deep: true,
560
+ immediate: true
561
+ }
562
+ )
563
+ watch(
564
+ () => props.dataSourse,
565
+ value => {
566
+ initColsDefaultValue()
567
+ selectionRows.value = []
568
+ },
569
+ {
570
+ immediate: true
571
+ }
572
+ )
573
+ watch(
574
+ () => props.editRules,
575
+ value => {
576
+ initEditRules(value)
577
+ },
578
+ {
579
+ deep: true,
580
+ immediate: true
581
+ }
582
+ )
583
+
584
+ return {
585
+ slots,
586
+ tableRef,
587
+ renderKey,
588
+ wrapHeight,
589
+ tableGlobalConfig,
590
+ tablePrevColumns,
591
+ tableColumns,
592
+ tableColumnObjConfig,
593
+ tablePagerConfig,
594
+ tableQueryConfig,
595
+ tableFilterText,
596
+ tableFilterConfig,
597
+ tableFilterData,
598
+ tableTools,
599
+ tableSlots,
600
+ selectionRows,
601
+ tableBindConfig,
602
+ importBindConfig,
603
+ onCurrentChange,
604
+ onRadioChange,
605
+ onSelectionChange,
606
+ onCellClick,
607
+ onCellDblClick,
608
+ onHeaderCellClick,
609
+ onSortChange,
610
+ onFilterChange,
611
+ onToggleRowExpand,
612
+ onToggleTreeExpand,
613
+ onEditClosed,
614
+ onEditActived,
615
+ onScroll,
616
+ onCustom,
617
+ onPageChange,
618
+ onToolbarButtonClick,
619
+ onToolbarToolClick,
620
+ handleGoptionClick,
621
+ onFormSubmit,
622
+ onFormReset,
623
+ onFormCollapsed,
624
+ onFormEditClosed,
625
+ handleTableFilter,
626
+ handleTableTool,
627
+ setImportData,
628
+ refreshRender,
629
+ validate,
630
+ getSelectionData,
631
+ getFullData,
632
+ handleTableAddRow,
633
+ handleTableDeleteRow,
634
+ turnColumnItemFilters
635
+ }
636
+ }