@idooel/components 0.0.2-beta.2 → 0.0.2-beta.21

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 (109) hide show
  1. package/README.md +98 -98
  2. package/dist/@idooel/components.esm.js +1931 -785
  3. package/dist/@idooel/components.umd.js +1956 -812
  4. package/jsconfig.json +7 -7
  5. package/package.json +61 -50
  6. package/packages/alert/index.js +4 -4
  7. package/packages/alert/src/index.vue +45 -45
  8. package/packages/batch-export/index.js +4 -4
  9. package/packages/batch-export/src/index.vue +104 -104
  10. package/packages/business-components/modal-fsm/index.js +4 -4
  11. package/packages/business-components/modal-fsm/src/index.vue +163 -163
  12. package/packages/business-components/modal-import/index.js +4 -4
  13. package/packages/business-components/modal-import/src/index.vue +222 -139
  14. package/packages/business-components/modal-timeline/index.js +4 -4
  15. package/packages/business-components/modal-timeline/src/index.vue +77 -77
  16. package/packages/business-components/tabs-sub-center/index.js +4 -4
  17. package/packages/business-components/tabs-sub-center/src/index.vue +116 -116
  18. package/packages/button/index.js +4 -4
  19. package/packages/button/src/index.vue +65 -65
  20. package/packages/checkbox/index.js +4 -4
  21. package/packages/checkbox/src/index.vue +52 -52
  22. package/packages/composite-components/button-group/index.js +4 -4
  23. package/packages/composite-components/button-group/src/index.vue +151 -151
  24. package/packages/composite-components/form-attachment/src/index.vue +14 -14
  25. package/packages/composite-components/form-img-crop/index.js +4 -4
  26. package/packages/composite-components/form-img-crop/src/index.vue +131 -131
  27. package/packages/composite-components/modal-confirm/index.js +4 -4
  28. package/packages/composite-components/modal-confirm/src/index.vue +103 -103
  29. package/packages/composite-components/modal-form/index.js +4 -4
  30. package/packages/composite-components/modal-form/src/index.vue +230 -230
  31. package/packages/composite-components/modal-img-crop/index.js +4 -4
  32. package/packages/composite-components/modal-img-crop/src/index.vue +298 -298
  33. package/packages/composite-components/modal-table/index.js +4 -4
  34. package/packages/composite-components/modal-table/src/index.vue +155 -155
  35. package/packages/composite-components/modal-tree/index.js +4 -4
  36. package/packages/composite-components/modal-tree/src/index.vue +75 -75
  37. package/packages/composite-components/search-area/index.js +4 -4
  38. package/packages/composite-components/search-area/src/index.vue +238 -237
  39. package/packages/composite-components/search-area/src/label.vue +35 -35
  40. package/packages/composite-components/select-entity-modal-table/index.js +4 -4
  41. package/packages/composite-components/select-entity-modal-table/src/index.vue +171 -171
  42. package/packages/date/index.js +4 -4
  43. package/packages/date/src/index.vue +112 -112
  44. package/packages/date-range/index.js +4 -4
  45. package/packages/date-range/src/index.vue +47 -47
  46. package/packages/form/index.js +4 -4
  47. package/packages/form/src/index.vue +319 -319
  48. package/packages/icon/index.js +4 -4
  49. package/packages/icon/src/index.vue +31 -31
  50. package/packages/index.js +156 -153
  51. package/packages/input/index.js +4 -4
  52. package/packages/input/src/index.vue +35 -35
  53. package/packages/input-number/index.js +4 -4
  54. package/packages/input-number/src/index.vue +23 -23
  55. package/packages/loading/index.js +4 -4
  56. package/packages/loading/src/index.vue +36 -36
  57. package/packages/meta/provider.js +4 -0
  58. package/packages/modal/index.js +4 -4
  59. package/packages/modal/src/index.vue +184 -184
  60. package/packages/models/form-group-model/index.js +4 -4
  61. package/packages/models/form-group-model/src/index.vue +273 -273
  62. package/packages/models/form-model/index.js +4 -4
  63. package/packages/models/form-model/src/index.vue +236 -232
  64. package/packages/models/step-model/index.js +4 -4
  65. package/packages/models/step-model/src/index.vue +224 -224
  66. package/packages/models/tree-table-model/index.js +4 -4
  67. package/packages/models/tree-table-model/src/index.vue +830 -689
  68. package/packages/radio/index.js +4 -4
  69. package/packages/radio/src/index.vue +56 -56
  70. package/packages/select/index.js +4 -4
  71. package/packages/select/src/index.vue +105 -105
  72. package/packages/select-entity/index.js +4 -4
  73. package/packages/select-entity/src/index.vue +119 -119
  74. package/packages/table/index.js +4 -4
  75. package/packages/table/src/action.vue +176 -172
  76. package/packages/table/src/index.vue +339 -309
  77. package/packages/tabs/index.js +4 -4
  78. package/packages/tabs/src/index.vue +55 -55
  79. package/packages/text/index.js +4 -4
  80. package/packages/text/src/index.vue +47 -47
  81. package/packages/text-editor/index.js +4 -4
  82. package/packages/text-editor/src/index.vue +72 -72
  83. package/packages/textarea/index.js +4 -4
  84. package/packages/textarea/src/index.vue +57 -57
  85. package/packages/theme/form.scss +21 -21
  86. package/packages/theme/index.scss +43 -43
  87. package/packages/theme/overrid.scss +7 -7
  88. package/packages/theme/styleClass.scss +2 -2
  89. package/packages/theme/variables.scss +55 -55
  90. package/packages/timeline/index.js +4 -4
  91. package/packages/timeline/src/index.vue +257 -257
  92. package/packages/tpl/index.js +4 -4
  93. package/packages/tpl/src/index.vue +55 -55
  94. package/packages/tree/index.js +4 -4
  95. package/packages/tree/src/TreeNode.vue +29 -29
  96. package/packages/tree/src/index.vue +101 -101
  97. package/packages/tree-select/index.js +4 -4
  98. package/packages/tree-select/src/index.vue +142 -142
  99. package/packages/upload/index.js +4 -4
  100. package/packages/upload/src/index.vue +998 -494
  101. package/packages/utils/index.js +66 -62
  102. package/packages/utils/runtime-context/dataPoolAPI.js +501 -0
  103. package/packages/utils/runtime-context/globalDataPool.js +279 -0
  104. package/packages/utils/runtime-context/index.js +76 -0
  105. package/packages/utils/runtime-context/modelSchema.js +174 -0
  106. package/scripts/rollup.config.js +42 -42
  107. package/scripts/rollup.esm.config.js +11 -11
  108. package/scripts/rollup.umd.config.js +17 -14
  109. package/vitest.config.js +17 -0
@@ -1,689 +1,830 @@
1
- <template>
2
- <section class="ele model__tree-table">
3
- <section class="model__tree-table--container" v-if="showTree">
4
- <div class="model__tree--title"></div>
5
- <section :ref="modelTreeWrapper" class="model__tree--wrapper" :style="{height: `${treeWrapperHeight}px`}">
6
- <ele-tree
7
- :tree-data="treeData"
8
- :defaultExpandedKeys="defaultExpandedKeys"
9
- :defaultSelectedKeys="defaultSelectedKeys"
10
- @select="selectTreeNode"
11
- :replace-fields="mapFields">
12
- </ele-tree>
13
- </section>
14
- </section>
15
- <section class="model__table--container" :ref="modelTableContainerRef">
16
- <div class="model__table--title" v-if="title">
17
- <template v-if="titleMode">
18
- <div :class="[`model__table-title--${titleMode}`]"></div>
19
- </template>
20
- <template v-else>
21
- <div class="model__table-title--text">{{ title }}</div>
22
- </template>
23
- </div>
24
- <section :ref="modelTableWrapper" class="model__table--wrapper">
25
- <ele-search-area :ref="searchArea" @search="onSearch" :data-source="searchMeta.elements"></ele-search-area>
26
- <div class="button-row__area">
27
- <ele-button-group class="model-table__button-group" v-on="overrideButtonGroupEvent" :ref="buttonGroup" @click="handleClickButtonGroup" :data-source="getButtonGroupElements"></ele-button-group>
28
- <slot name="tags"></slot>
29
- <slot v-if="$slots['sub-center']" name="sub-center"></slot>
30
- </div>
31
- <ele-table
32
- v-on="overrideTableEvent"
33
- :ref="tableRef"
34
- :row-selection="rowSelection"
35
- :loading="loading"
36
- :columns="columns"
37
- :total="total"
38
- :x="x"
39
- :y="y"
40
- :bordered="setBorder"
41
- :height="tableHeight"
42
- :width="tableWidth"
43
- :actions="actions"
44
- :pageSize="pageSize"
45
- :pageSizeOptions="pageSizeOptions"
46
- :data-source="tableData"
47
- @change-page="onChangePage"
48
- ></ele-table>
49
- </section>
50
- </section>
51
- <ele-modal-form v-model="modalFormValue" v-on="overrideModalFormEvent" :meta="modalFormMeta"></ele-modal-form>
52
- <ele-modal-fsm v-model="showFsmModal" :contextProp="fsmContextProp" :meta="fsmMeta" @cancel="handleCloseFsmModal"></ele-modal-fsm>
53
- <ele-modal-table
54
- :meta="modalTableMeta"
55
- v-model="modalTableValue"
56
- v-on="overrideModalTableEvent"
57
- ></ele-modal-table>
58
- </section>
59
- </template>
60
-
61
- <script>
62
- import { type, net, util } from '@idooel/shared'
63
- import { v4 as uuidv4 } from 'uuid'
64
- import { BUILT_IN_EVENT_NAMES, RESERVE_EVENT_NAMES, parseFieldMap, BUILT_IN_TRIGGER, CONTEXT } from '../../../utils'
65
- export default {
66
- name: 'ele-tree-table-model',
67
- props: {
68
- title: {
69
- type: [Object, String]
70
- },
71
- overHeight: {
72
- type: Number,
73
- default: 0
74
- },
75
- treeMeta: {
76
- type: Object,
77
- default: () => ({})
78
- },
79
- searchMeta: {
80
- type: Object,
81
- default: () => ({})
82
- },
83
- buttonGroupMeta: {
84
- typeof: Object,
85
- default: () => ({})
86
- },
87
- tableMeta: {
88
- type: Object,
89
- default: () => ({})
90
- },
91
- createMeta: {
92
- type: Object
93
- },
94
- editMeta: {
95
- type: Object
96
- }
97
- },
98
- provide () {
99
- return {
100
- requestTreeData: this.requestTreeData,
101
- requestTableData: this.requestTableData,
102
- [CONTEXT]: () => {
103
- return {
104
- exposed: this.exposed
105
- }
106
- }
107
- }
108
- },
109
- data () {
110
- return {
111
- tableHeight: 0,
112
- tableWidth: 0,
113
- modalFormMeta: {},
114
- modalFormValue: false,
115
- treeData: [],
116
- tableData: [],
117
- defaultExpandedKeys: [],
118
- defaultSelectedKeys: [],
119
- replaceFields: {
120
- title: 'title',
121
- children: 'children',
122
- key: 'id'
123
- },
124
- loading: false,
125
- total: 0,
126
- tableQuerys: {},
127
- resizeObserverModelTableWrapper: null,
128
- modelTableWrapperHeight: 0,
129
- currentTreeNodeData: {},
130
- currentRowData: {},
131
- treeWrapperHeight: 0,
132
- currentTableSelection: this.currentTableMode == 'radio' ? {} : [],
133
- showFsmModal: false,
134
- fsmMeta: {},
135
- fsmContextProp: {},
136
- modalTableValue: false,
137
- modalTableMeta: {}
138
- }
139
- },
140
- computed: {
141
- setBorder () {
142
- return this.tableMeta.bordered === false ? false : true
143
- },
144
- rowSelection () {
145
- if (!this.currentTableMode) return void 0
146
- return {
147
- columnTitle: this.currentSelectionColumn.columnTitle,
148
- fixed: true,
149
- type: this.currentTableMode,
150
- onChange: this.onChangeTableSelection
151
- }
152
- },
153
- currentSelectionColumn () {
154
- const { multiple } = this.tableMeta
155
- const target = this.columns.find(item => Object.keys(item).includes('multiple'))
156
- const isGlobalExistMultiple = Object.keys(this.tableMeta).includes('multiple')
157
- if (target) {
158
- return target
159
- } else if (isGlobalExistMultiple) {
160
- return { multiple }
161
- }
162
- return void 0
163
- },
164
- x () {
165
- const { x } = this.tableMeta
166
- return x
167
- },
168
- y () {
169
- const { y } = this.tableMeta
170
- return y
171
- },
172
- currentTableMode () {
173
- if (!this.currentSelectionColumn) return void 0
174
- const { multiple } = this.currentSelectionColumn
175
- if (type.isBool(multiple)) {
176
- if (multiple) {
177
- return 'checkbox'
178
- } else {
179
- return 'radio'
180
- }
181
- } else {
182
- return void 0
183
- }
184
- },
185
- modelTableContainerRef () {
186
- return uuidv4()
187
- },
188
- titleMode () {
189
- if (type.isObject(this.title)) {
190
- const { mode = '' } = this.title
191
- return mode
192
- }
193
- return void 0
194
- },
195
- tableRef () {
196
- return uuidv4()
197
- },
198
- exposed () {
199
- return {
200
- showModalForm: this.showModalForm,
201
- closeModalForm: this.closeModalForm,
202
- showModalTable: this.showModalTable,
203
- closeModalTable: this.closeModalTable,
204
- currentTableSelection: this.currentTableSelection,
205
- currentTreeNode: this.currentTreeNodeData,
206
- requestTableData: this.requestTableData,
207
- refreshTreeData: this.refreshTreeData,
208
- querys: this.tableQuerys,
209
- currentRowData: this.currentRowData,
210
- getCurrentRowData: this.getCurrentRowData,
211
- setCurrentRowData: this.setCurrentRowData,
212
- setCurrentTableSelection: this.setCurrentTableSelection,
213
- getCurrentTableSelection: this.getCurrentTableSelection,
214
- cleanCurrentModelEffect: this.cleanCurrentModelEffect,
215
- route: this.$route,
216
- _route: this.$route.query,
217
- _routeMeta: this.$route.meta
218
- }
219
- },
220
- overrideTableEvent () {
221
- const events = this.actions.reduce((ret, action) => {
222
- ret[action.eventName || action.key] = (e) => {
223
- this.setCurrentRowData(e.exposed.currentRowData)
224
- const { target } = action
225
- const targetMeta = this.findMetaByKey(target)
226
- const { mode } = targetMeta
227
- mode && this.dispatchTrigger({ mode, record: e.exposed.currentRowData, modeMeta: targetMeta })
228
- this.$emit(action.eventName || action.key, { ...e, currentTreeNode: this.currentTreeNodeData, exposed: { ...this.exposed, ...e.exposed } })
229
- }
230
- return ret
231
- }, {})
232
- return {
233
- ...this.$listeners,
234
- ...events,
235
- [BUILT_IN_EVENT_NAMES.EDIT]: this[BUILT_IN_EVENT_NAMES.EDIT],
236
- [BUILT_IN_EVENT_NAMES.SUBMIT]: this[BUILT_IN_EVENT_NAMES.SUBMIT]
237
- }
238
- },
239
- overrideModalFormEvent () {
240
- const { footerMeta } = this.modalFormMeta
241
- const { elements = [] } = footerMeta || {}
242
- const eles = type.isFunction(elements) ? elements.call(this) : elements
243
- const events = eles.reduce((ret, ele) => {
244
- ret[ele.eventName] = (e = {}) => {
245
- if (ele.eventName === 'cancel') {
246
- this.closeModalForm()
247
- } else {
248
- const { exposed = {} } = e
249
- this.$emit(`${ele.eventName || ele.key}`, { ...e, currentTreeNode: this.currentTreeNodeData, exposed: Object.assign({}, exposed )})
250
- }
251
- }
252
- return ret
253
- }, {})
254
- return {
255
- ...events
256
- }
257
- },
258
- overrideModalTableEvent () {
259
- const { footerMeta } = this.modalTableMeta
260
- const { elements = [] } = footerMeta || {}
261
- const eles = type.isFunction(elements) ? elements.call(this) : elements
262
- const events = eles.reduce((ret, ele) => {
263
- ret[ele.eventName] = (e = {}) => {
264
- if (ele.eventName === 'cancel') {
265
- this.closeModalTable()
266
- } else {
267
- const { exposed = {} } = e
268
- this.$emit(`${ele.eventName || ele.key}`, { ...e, currentTreeNode: this.currentTreeNodeData, exposed: Object.assign({}, exposed )})
269
- }
270
- }
271
- return ret
272
- }, {})
273
- return {
274
- ...events,
275
- exposed: this.exposed
276
- }
277
- },
278
- overrideButtonGroupEvent () {
279
- const events = this.getButtonGroupElements.reduce((ret, ele) => {
280
- ret[ele.eventName] = (e) => {
281
- this.$emit(ele.eventName || 'click', { ...e, currentTreeNode: this.currentTreeNodeData, exposed: Object.assign({}, e.exposed || {}, this.exposed)})
282
- }
283
- return ret
284
- }, {})
285
- return {
286
- ...this.$listeners,
287
- ...events,
288
- [BUILT_IN_EVENT_NAMES.CREATE]: this[BUILT_IN_EVENT_NAMES.CREATE],
289
- exposed: this.exposed
290
- }
291
- },
292
- showTree () {
293
- return !!Object.keys(this.treeMeta).length
294
- },
295
- buttonGroup () {
296
- return uuidv4()
297
- },
298
- searchArea () {
299
- return uuidv4()
300
- },
301
- modelTreeWrapper () {
302
- return uuidv4()
303
- },
304
- modelTableWrapper () {
305
- return uuidv4()
306
- },
307
- actions () {
308
- const { operations } = this.tableMeta
309
- if (operations) {
310
- return operations.elements
311
- } else {
312
- return []
313
- }
314
- },
315
- pageSize () {
316
- const { page = {} } = this.tableMeta
317
- return page.pageSize || 10
318
- },
319
- pageSizeOptions () {
320
- const { page = {} } = this.tableMeta
321
- return page.pageSizeOptions || ['10', '20', '30', '40']
322
- },
323
- columns () {
324
- const { columns, operations } = this.tableMeta
325
- if (type.get(columns) === 'array') {
326
- const columnsOptions = columns.map(item => {
327
- const { mode = 'text' } = item
328
- if (item.render) {
329
- return {
330
- ...item,
331
- customRender: (text, record, index) => {
332
- const { $createElement } = this
333
- return item.render.call(this,
334
- { h: $createElement, ctx: this },
335
- text ? typeof text == 'object' ? text[item.dataIndex] : text : '',
336
- record, index)
337
- }
338
- }
339
- } else if (mode !== BUILT_IN_TRIGGER.TEXT) {
340
- const { [`${mode}Meta`]: modeMeta } = item
341
- return {
342
- ...item,
343
- customRender: (text, record, index) => {
344
- return <span onClick={() => this.dispatchTrigger({ mode, record, modeMeta, index })} class={ mode }>{ text }</span>
345
- }
346
- }
347
- }
348
- return {
349
- ...item
350
- }
351
- })
352
- if (operations) {
353
- return [
354
- ...columnsOptions,
355
- {
356
- title: '操作',
357
- width: operations.width,
358
- key: 'action',
359
- fixed: 'right',
360
- scopedSlots: { customRender: 'action' }
361
- }
362
- ]
363
- }
364
- return columnsOptions
365
- } else {
366
- console.error('Error: columns is invalid, please check it')
367
- return []
368
- }
369
- },
370
- getButtonGroupElements () {
371
- const { elements } = this.buttonGroupMeta
372
- if (type.get(elements) === 'function') {
373
- return elements.call(this)
374
- } else if (type.get(elements) === 'array') {
375
- return elements
376
- } else {
377
- return []
378
- }
379
- },
380
- mapFields () {
381
- const { replaceFields = {} } = this.treeMeta
382
- const mapFields = type.isEmpty(replaceFields) ? this.replaceFields : replaceFields
383
- return mapFields
384
- }
385
- },
386
- async created () {
387
- if (this.showTree) {
388
- this.treeData = await this.requestTreeData()
389
- const [defaultTreeNode = {}] = this.treeData
390
- this.defaultExpandedKeys = [defaultTreeNode[this.mapFields.key]]
391
- this.defaultSelectedKeys = [defaultTreeNode[this.mapFields.key]]
392
- this.currentTreeNodeData = defaultTreeNode
393
- }
394
- const { params = {}, fieldMap = {}, overrideInit = false } = this.tableMeta
395
- const ctx = { ...this.currentTreeNodeData, _route: this.$route.query }
396
- const initQuerys = Object.assign({}, params, parseFieldMap(fieldMap, ctx))
397
- if (overrideInit) {
398
- this.$emit(RESERVE_EVENT_NAMES.INIT, { ...this.exposed })
399
- } else {
400
- this.tableData = await this.requestTableData(initQuerys)
401
- }
402
- },
403
- methods: {
404
- async refreshTreeData () {
405
- this.treeData = await this.requestTreeData()
406
- const [defaultTreeNode = {}] = this.treeData
407
- this.defaultExpandedKeys = [defaultTreeNode[this.mapFields.key]]
408
- this.defaultSelectedKeys = [defaultTreeNode[this.mapFields.key]]
409
- this.currentTreeNodeData = defaultTreeNode
410
- },
411
- dispatchTrigger ({ mode, record = {}, modeMeta = { } }) {
412
- switch (mode) {
413
- case BUILT_IN_TRIGGER.FSM:
414
- this[`${BUILT_IN_TRIGGER.FSM}Trigger`](record, modeMeta = type.isEmpty(modeMeta) ? {
415
- url: 'api-fsm/workbench/fsm/auditFlow',
416
- requestType: 'GET',
417
- fieldMap: {
418
- modelCode: 'modelCode',
419
- businessId: 'businessId'
420
- }
421
- } : modeMeta)
422
- break
423
- case BUILT_IN_TRIGGER.ELE_MODAL_FORM:
424
- this.modalFormMeta = modeMeta
425
- this.showModalForm(modeMeta)
426
- break
427
- case BUILT_IN_TRIGGER.ELE_MODAL_TABLE:
428
- this.modalTableMeta = modeMeta
429
- this.showModalTable(modeMeta)
430
- break
431
- default:
432
- break
433
- }
434
- },
435
- handleCloseFsmModal () {
436
- this.showFsmModal = false
437
- },
438
- [`${BUILT_IN_TRIGGER.FSM}Trigger`] (record, meta) {
439
- this.fsmMeta = meta
440
- this.fsmContextProp = record
441
- this.showFsmModal = true
442
- },
443
- onChangeTableSelection (_, selectedRows = []) {
444
- if (this.currentTableMode === 'radio') {
445
- this.setCurrentTableSelection(selectedRows)
446
- this.$emit('on-change-table-selection', this.currentTableSelection)
447
- this.$emit('x:refresh-exposed', { exposed: this.exposed })
448
- } else {
449
- this.setCurrentTableSelection(selectedRows)
450
- this.$emit('on-change-table-selection', this.currentTableSelection)
451
- this.$emit('x:refresh-exposed', { exposed: this.exposed })
452
- }
453
- },
454
- setCurrentTableSelection (props = {}) {
455
- if (this.currentTableMode === 'radio') {
456
- this.$set(this, 'currentTableSelection', (type.isArray(props) && props.length > 0) ? props[0] : type.isObject(props) ? props : {})
457
- } else {
458
- this.$set(this, 'currentTableSelection', type.isArray(props) ? props : [])
459
- }
460
- },
461
- getCurrentTableSelection () {
462
- return this.currentTableSelection
463
- },
464
- setCurrentRowData (props = {}) {
465
- this.currentRowData = props
466
- },
467
- getCurrentRowData () {
468
- return this.currentRowData
469
- },
470
- cleanCurrentModelEffect () {
471
- this.setCurrentTableSelection()
472
- this.setCurrentRowData({})
473
- },
474
- [BUILT_IN_EVENT_NAMES.SUBMIT] (props = {}) {
475
- this.cleanCurrentModelEffect()
476
- this.requestTableData()
477
- },
478
- [BUILT_IN_EVENT_NAMES.EDIT] (props = {}) {
479
- const { record = {} } = props
480
- this.currentRowData = record
481
- this.setCurrentRowData(record)
482
- this.modalFormMeta = this.editMeta
483
- this.modalFormValue = true
484
- },
485
- [BUILT_IN_EVENT_NAMES.CREATE] () {
486
- this.modalFormMeta = this.createMeta
487
- this.modalFormValue = true
488
- },
489
- showModalForm (modeMeta = {}) {
490
- if (type.isStr(modeMeta)) {
491
- const targetMeta = this.findMetaByKey(modeMeta)
492
- this.modalFormMeta = targetMeta
493
- } else {
494
- this.modalFormMeta = modeMeta
495
- }
496
- this.modalFormValue = true
497
- },
498
- showModalTable (modeMeta = {}) {
499
- console.log('showModalTable', modeMeta)
500
- if (type.isStr(modeMeta)) {
501
- const targetMeta = this.findMetaByKey(modeMeta)
502
- this.modalTableMeta = targetMeta
503
- } else {
504
- this.modalTableMeta = modeMeta
505
- }
506
- this.modalTableValue = true
507
- },
508
- closeModalForm () {
509
- this.modalFormValue = false
510
- },
511
- closeModalTable () {
512
- console.log('closeModalTable')
513
- this.modalTableValue = false
514
- },
515
- findMetaByKey (key) {
516
- return this.$attrs[key] || {}
517
- },
518
- handleClickButtonGroup (props) {
519
- const { eventName, target } = props
520
- const targetMeta = this.findMetaByKey(target)
521
- const { mode } = targetMeta
522
- mode && this.dispatchTrigger({ mode, modeMeta: targetMeta })
523
- this.$emit(eventName || 'click', { currentTreeNode: this.currentTreeNodeData })
524
- },
525
- watchViewPort () {
526
- const modelTableWrapper = this.$refs[this.modelTableWrapper]
527
- const { top } = modelTableWrapper.getBoundingClientRect()
528
- this.$refs[this.modelTreeWrapper].style.height = `calc(100vh - ${top}px)`
529
- },
530
- async onSearch (props) {
531
- const { overrideInit = false } = this.tableMeta
532
- this.tableQuerys = Object.assign(this.tableQuerys, props)
533
- if (overrideInit) {
534
- this.$emit(RESERVE_EVENT_NAMES.TREE_CHANGE, { ...this.exposed })
535
- } else {
536
- this.tableData = await this.requestTableData()
537
- }
538
- },
539
- async selectTreeNode (selectedKeys, e) {
540
- const { fieldMap } = this.tableMeta
541
- this.currentTreeNodeData = e.node.$vnode.data.props.dataRef || {}
542
- //@deprecated '_' namespace is deprecated, please use 'exposed' instead
543
- const execFieldMapRet = parseFieldMap(fieldMap, { ...this.currentTreeNodeData, exposed: this.exposed, _route: this.exposed._route })
544
- const { overrideInit = false } = this.tableMeta
545
- if (overrideInit) {
546
- this.$emit(RESERVE_EVENT_NAMES.TREE_CHANGE, { ...this.exposed })
547
- } else {
548
- this.tableData = await this.requestTableData(execFieldMapRet)
549
- }
550
- },
551
- async requestTreeData () {
552
- const { url, requestType = 'GET', params = {}, fieldMap = {} } = this.treeMeta
553
- const fieldMapRet = parseFieldMap(fieldMap, { ...this.currentTreeNodeData, _route: this.$route.query })
554
- const ret = await net[requestType.toLowerCase()](
555
- url,
556
- { ...params, ...fieldMapRet }
557
- ).then(resp => {
558
- const { data } = resp || {}
559
- return data
560
- })
561
- return ret
562
- },
563
- async onChangePage (page, pageSize) {
564
- this.tableData = await this.requestTableData({ currentPage: page, pageSize })
565
- },
566
- async requestTableData (props = {}) {
567
- const { url, requestType = 'GET', page = {} } = this.tableMeta
568
- const { pageSize = 10 } = page
569
- this.tableQuerys = Object.assign(this.tableQuerys, { currentPage: 1, pageSize }, props)
570
- this.$emit(RESERVE_EVENT_NAMES.WATCH, { ...this.exposed })
571
- this.loading = true
572
- const ret = await net[requestType.toLowerCase()](
573
- url,
574
- this.tableQuerys
575
- ).then(resp => {
576
- const { data = [], count } = resp || {}
577
- this.total = count
578
- this.loading = false
579
- return (data || []).map(item => {
580
- delete item.children
581
- return {
582
- key: uuidv4(),
583
- ...item
584
- }
585
- })
586
- })
587
- this.cleanCurrentModelEffect()
588
- this.tableData = ret
589
- return ret
590
- },
591
- refreshTreeStatus (props = {}) {},
592
- refreshTableStatus (props = {}) {},
593
- calculateTableHeight () {
594
- const currentViewportHeight = window.innerHeight
595
- const tableRef = this.$refs[this.tableRef]
596
- const { top: tableToTop, width } = tableRef.$el.getBoundingClientRect()
597
- this.tableWidth = width
598
- this.tableHeight = currentViewportHeight - tableToTop - this.overHeight
599
- },
600
- calculateTreeHeight () {
601
- if (!this.showTree) return
602
- const modelTableContainerRef = this.$refs[this.modelTableContainerRef]
603
- const { height } = modelTableContainerRef.getBoundingClientRect()
604
- this.treeWrapperHeight = height
605
- }
606
- },
607
- mounted () {
608
- this.calculateTableHeight()
609
- this.$nextTick(() => {
610
- this.calculateTreeHeight()
611
- })
612
- this.resizeObserverModelTableWrapper = new ResizeObserver(entries => {
613
- for (const _ of entries) {
614
- requestAnimationFrame(() => {
615
- this.calculateTableHeight()
616
- })
617
- }
618
- })
619
- this.resizeObserverModelTableWrapper.observe(this.$refs[this.modelTableWrapper])
620
- },
621
- destroyed () {
622
- this.resizeObserverModelTableWrapper.disconnect()
623
- }
624
- }
625
- </script>
626
-
627
- <style lang="scss" scoped>
628
- .ele {
629
- &.model__tree-table {
630
- background: transparent;
631
- display: flex;
632
- flex-direction: row;
633
- width: 100%;
634
- .model__tree-table--container {
635
- .model__tree--wrapper {
636
- width: 240px;
637
- background: #fff;
638
- flex-shrink: 0;
639
- padding: 16px;
640
- box-sizing: border-box;
641
- margin-right: 16px;
642
- overflow-y: auto;
643
- }
644
- }
645
- .model__table--container {
646
- width: 100%;
647
- min-width: 0;
648
- background: #fff;
649
- .model__table--title {
650
- .model__table-title--bar {
651
- width: 100%;
652
- height: 8px;
653
- background: var(--idooel-primary-color);
654
- border-top-left-radius: 4px;
655
- border-top-right-radius: 4px;
656
- }
657
- .model__table-title--text {
658
- text-align: left;
659
- padding: 16px;
660
- font-size: 16px;
661
- font-weight: bold;
662
- background: #fff;
663
- border-bottom: 1px solid;
664
- border-color: var(--idoole-black-016);
665
- }
666
- }
667
- .model__table--wrapper {
668
- background: #fff;
669
- .button-row__area {
670
- width: 100%;
671
- display: flex;
672
- flex-direction: row;
673
- align-items: center;
674
- justify-content: space-between;
675
- padding-top: 16px;
676
- padding-bottom: 8px;
677
- padding-right: 16px;
678
- }
679
- .g-table__wrapper {
680
- .fsm {
681
- cursor: pointer;
682
- color: var(--idooel-primary-color);
683
- }
684
- }
685
- }
686
- }
687
- }
688
- }
689
- </style>
1
+ <template>
2
+ <section class="ele model__tree-table">
3
+ <section class="model__tree-table--container" v-if="showTree">
4
+ <div class="model__tree--title"></div>
5
+ <section :ref="modelTreeWrapper" class="model__tree--wrapper" :style="{height: `${treeWrapperHeight}px`}">
6
+ <ele-tree
7
+ :tree-data="treeData"
8
+ :defaultExpandedKeys="defaultExpandedKeys"
9
+ :defaultSelectedKeys="defaultSelectedKeys"
10
+ @select="selectTreeNode"
11
+ :replace-fields="mapFields">
12
+ </ele-tree>
13
+ </section>
14
+ </section>
15
+ <section class="model__table--container" :ref="modelTableContainerRef">
16
+ <div class="model__table--title" v-if="title">
17
+ <template v-if="titleMode">
18
+ <div :class="[`model__table-title--${titleMode}`]"></div>
19
+ </template>
20
+ <template v-else>
21
+ <div class="model__table-title--text">{{ title }}</div>
22
+ </template>
23
+ </div>
24
+ <section :ref="modelTableWrapper" class="model__table--wrapper">
25
+ <ele-search-area :ref="searchArea" @search="onSearch" :data-source="searchMeta.elements"></ele-search-area>
26
+ <div class="button-row__area">
27
+ <ele-button-group class="model-table__button-group" v-on="overrideButtonGroupEvent" :ref="buttonGroup" @click="handleClickButtonGroup" :data-source="getButtonGroupElements"></ele-button-group>
28
+ <slot name="tags"></slot>
29
+ <slot v-if="$slots['sub-center']" name="sub-center"></slot>
30
+ </div>
31
+ <ele-table
32
+ v-on="overrideTableEvent"
33
+ :ref="tableRef"
34
+ :row-selection="rowSelection"
35
+ :loading="loading"
36
+ :columns="columns"
37
+ :total="total"
38
+ :x="x"
39
+ :y="y"
40
+ :bordered="setBorder"
41
+ :height="tableHeight"
42
+ :width="tableWidth"
43
+ :actions="actions"
44
+ :pageSize="pageSize"
45
+ :pageSizeOptions="pageSizeOptions"
46
+ :data-source="tableData"
47
+ @change-page="onChangePage"
48
+ ></ele-table>
49
+ </section>
50
+ </section>
51
+ <ele-modal-form v-model="modalFormValue" v-on="overrideModalFormEvent" :meta="modalFormMeta"></ele-modal-form>
52
+ <ele-modal-fsm v-model="showFsmModal" :contextProp="fsmContextProp" :meta="fsmMeta" @cancel="handleCloseFsmModal"></ele-modal-fsm>
53
+ <ele-modal-table
54
+ :meta="modalTableMeta"
55
+ v-model="modalTableValue"
56
+ v-on="overrideModalTableEvent"
57
+ ></ele-modal-table>
58
+ </section>
59
+ </template>
60
+
61
+ <script>
62
+ import { type, net } from '@idooel/shared'
63
+ import { v4 as uuidv4 } from 'uuid'
64
+ import { BUILT_IN_EVENT_NAMES, RESERVE_EVENT_NAMES, parseFieldMap, BUILT_IN_TRIGGER, CONTEXT } from '../../../utils'
65
+ import { createTreeTableModel } from '../../../utils/runtime-context'
66
+ export default {
67
+ name: 'ele-tree-table-model',
68
+ props: {
69
+ title: {
70
+ type: [Object, String]
71
+ },
72
+ overHeight: {
73
+ type: Number,
74
+ default: 0
75
+ },
76
+ treeMeta: {
77
+ type: Object,
78
+ default: () => ({})
79
+ },
80
+ searchMeta: {
81
+ type: Object,
82
+ default: () => ({})
83
+ },
84
+ buttonGroupMeta: {
85
+ typeof: Object,
86
+ default: () => ({})
87
+ },
88
+ tableMeta: {
89
+ type: Object,
90
+ default: () => ({})
91
+ },
92
+ createMeta: {
93
+ type: Object
94
+ },
95
+ editMeta: {
96
+ type: Object
97
+ }
98
+ },
99
+ provide () {
100
+ return {
101
+ requestTreeData: this.requestTreeData,
102
+ requestTableData: this.requestTableData,
103
+ keepAliveRefresh: this.keepAliveRefresh,
104
+ [CONTEXT]: () => {
105
+ return {
106
+ exposed: this.exposed
107
+ }
108
+ }
109
+ }
110
+ },
111
+ data () {
112
+ return {
113
+ tableHeight: 0,
114
+ tableWidth: 0,
115
+ modalFormMeta: {},
116
+ modalFormValue: false,
117
+ treeData: [],
118
+ tableData: [],
119
+ defaultExpandedKeys: [],
120
+ defaultSelectedKeys: [],
121
+ replaceFields: {
122
+ title: 'title',
123
+ children: 'children',
124
+ key: 'id'
125
+ },
126
+ loading: false,
127
+ total: 0,
128
+ tableQuerys: {},
129
+ resizeObserverModelTableWrapper: null,
130
+ modelTableWrapperHeight: 0,
131
+ currentTreeNodeData: {},
132
+ currentRowData: {},
133
+ treeWrapperHeight: 0,
134
+ currentTableSelection: this.currentTableMode == 'radio' ? {} : [],
135
+ showFsmModal: false,
136
+ fsmMeta: {},
137
+ fsmContextProp: {},
138
+ modalTableValue: false,
139
+ modalTableMeta: {},
140
+ dataPoolManager: null
141
+ }
142
+ },
143
+ computed: {
144
+ setBorder () {
145
+ return this.tableMeta.bordered === false ? false : true
146
+ },
147
+ rowSelection () {
148
+ if (!this.currentTableMode) return void 0
149
+ return {
150
+ columnTitle: this.currentSelectionColumn.columnTitle,
151
+ fixed: true,
152
+ type: this.currentTableMode,
153
+ onChange: this.onChangeTableSelection
154
+ }
155
+ },
156
+ currentSelectionColumn () {
157
+ const { multiple } = this.tableMeta
158
+ const target = this.columns.find(item => Object.keys(item).includes('multiple'))
159
+ const isGlobalExistMultiple = Object.keys(this.tableMeta).includes('multiple')
160
+ if (target) {
161
+ return target
162
+ } else if (isGlobalExistMultiple) {
163
+ return { multiple }
164
+ }
165
+ return void 0
166
+ },
167
+ x () {
168
+ const { x } = this.tableMeta
169
+ return x
170
+ },
171
+ y () {
172
+ const { y } = this.tableMeta
173
+ return y
174
+ },
175
+ currentTableMode () {
176
+ if (!this.currentSelectionColumn) return void 0
177
+ const { multiple } = this.currentSelectionColumn
178
+ if (type.isBool(multiple)) {
179
+ if (multiple) {
180
+ return 'checkbox'
181
+ } else {
182
+ return 'radio'
183
+ }
184
+ } else {
185
+ return void 0
186
+ }
187
+ },
188
+ modelTableContainerRef () {
189
+ return uuidv4()
190
+ },
191
+ titleMode () {
192
+ if (type.isObject(this.title)) {
193
+ const { mode = '' } = this.title
194
+ return mode
195
+ }
196
+ return void 0
197
+ },
198
+ tableRef () {
199
+ return uuidv4()
200
+ },
201
+ exposed () {
202
+ return {
203
+ showModalForm: this.showModalForm,
204
+ closeModalForm: this.closeModalForm,
205
+ showModalTable: this.showModalTable,
206
+ closeModalTable: this.closeModalTable,
207
+ currentTableSelection: this.currentTableSelection,
208
+ currentTreeNode: this.currentTreeNodeData,
209
+ requestTableData: this.requestTableData,
210
+ keepAliveRefresh: this.keepAliveRefresh,
211
+ refreshTreeData: this.refreshTreeData,
212
+ querys: this.tableQuerys,
213
+ currentRowData: this.getCurrentRowData(),
214
+ getCurrentRowData: this.getCurrentRowData,
215
+ setCurrentRowData: this.setCurrentRowData,
216
+ setCurrentTableSelection: this.setCurrentTableSelection,
217
+ getCurrentTableSelection: this.getCurrentTableSelection,
218
+ cleanCurrentModelEffect: this.cleanCurrentModelEffect,
219
+ route: this.$route,
220
+ _route: this.$route.query,
221
+ _routeMeta: this.$route.meta,
222
+ dataPool: this.model ? this.model.getDataPool() : null,
223
+ dataPoolManager: this.model || null
224
+ }
225
+ },
226
+ overrideTableEvent () {
227
+ const events = this.actions.reduce((ret, action) => {
228
+ ret[action.eventName || action.key] = (e) => {
229
+ this.setCurrentRowData(e.exposed.currentRowData)
230
+ const { target } = action
231
+ const targetMeta = this.findMetaByKey(target)
232
+ const { mode } = targetMeta
233
+ mode && this.dispatchTrigger({ mode, record: e.exposed.currentRowData, modeMeta: targetMeta })
234
+ this.$emit(action.eventName || action.key, { ...e, currentTreeNode: this.currentTreeNodeData, exposed: { ...this.exposed, ...e.exposed } })
235
+ }
236
+ return ret
237
+ }, {})
238
+ return {
239
+ ...this.$listeners,
240
+ ...events,
241
+ [BUILT_IN_EVENT_NAMES.EDIT]: this[BUILT_IN_EVENT_NAMES.EDIT],
242
+ [BUILT_IN_EVENT_NAMES.SUBMIT]: this[BUILT_IN_EVENT_NAMES.SUBMIT]
243
+ }
244
+ },
245
+ overrideModalFormEvent () {
246
+ const { footerMeta } = this.modalFormMeta
247
+ const { elements = [] } = footerMeta || {}
248
+ const eles = type.isFunction(elements) ? elements.call(this) : elements
249
+ const events = eles.reduce((ret, ele) => {
250
+ ret[ele.eventName] = (e = {}) => {
251
+ if (ele.eventName === 'cancel') {
252
+ this.closeModalForm()
253
+ } else {
254
+ const { exposed = {} } = e
255
+ this.$emit(`${ele.eventName || ele.key}`, { ...e, currentTreeNode: this.currentTreeNodeData, exposed: Object.assign({}, exposed )})
256
+ }
257
+ }
258
+ return ret
259
+ }, {})
260
+ return {
261
+ ...events
262
+ }
263
+ },
264
+ overrideModalTableEvent () {
265
+ const { footerMeta } = this.modalTableMeta
266
+ const { elements = [] } = footerMeta || {}
267
+ const eles = type.isFunction(elements) ? elements.call(this) : elements
268
+ const events = eles.reduce((ret, ele) => {
269
+ ret[ele.eventName] = (e = {}) => {
270
+ if (ele.eventName === 'cancel') {
271
+ this.closeModalTable()
272
+ } else {
273
+ const { exposed = {} } = e
274
+ this.$emit(`${ele.eventName || ele.key}`, { ...e, currentTreeNode: this.currentTreeNodeData, exposed: Object.assign({}, exposed )})
275
+ }
276
+ }
277
+ return ret
278
+ }, {})
279
+ return {
280
+ ...events,
281
+ exposed: this.exposed
282
+ }
283
+ },
284
+ overrideButtonGroupEvent () {
285
+ const events = this.getButtonGroupElements.reduce((ret, ele) => {
286
+ ret[ele.eventName] = (e) => {
287
+ this.$emit(ele.eventName || 'click', { ...e, currentTreeNode: this.currentTreeNodeData, exposed: Object.assign({}, e.exposed || {}, this.exposed)})
288
+ }
289
+ return ret
290
+ }, {})
291
+ return {
292
+ ...this.$listeners,
293
+ ...events,
294
+ [BUILT_IN_EVENT_NAMES.CREATE]: this[BUILT_IN_EVENT_NAMES.CREATE],
295
+ exposed: this.exposed
296
+ }
297
+ },
298
+ showTree () {
299
+ return !!Object.keys(this.treeMeta).length
300
+ },
301
+ buttonGroup () {
302
+ return uuidv4()
303
+ },
304
+ searchArea () {
305
+ return uuidv4()
306
+ },
307
+ modelTreeWrapper () {
308
+ return uuidv4()
309
+ },
310
+ modelTableWrapper () {
311
+ return uuidv4()
312
+ },
313
+ actions () {
314
+ const { operations } = this.tableMeta
315
+ if (operations) {
316
+ return operations.elements
317
+ } else {
318
+ return []
319
+ }
320
+ },
321
+ pageSize () {
322
+ const { page = {} } = this.tableMeta
323
+ return page.pageSize || 10
324
+ },
325
+ pageSizeOptions () {
326
+ const { page = {} } = this.tableMeta
327
+ return page.pageSizeOptions || ['10', '20', '30', '40']
328
+ },
329
+ columns () {
330
+ const { columns, operations } = this.tableMeta
331
+ if (type.get(columns) === 'array') {
332
+ const columnsOptions = columns.map(item => {
333
+ const { mode = 'text' } = item
334
+ if (item.render) {
335
+ return {
336
+ ...item,
337
+ customRender: (text, record, index) => {
338
+ const { $createElement } = this
339
+ return item.render.call(this,
340
+ { h: $createElement, ctx: this },
341
+ text ? typeof text == 'object' ? text[item.dataIndex] : text : '',
342
+ record, index)
343
+ }
344
+ }
345
+ } else if (mode !== BUILT_IN_TRIGGER.TEXT) {
346
+ const { [`${mode}Meta`]: modeMeta } = item
347
+ return {
348
+ ...item,
349
+ customRender: (text, record, index) => {
350
+ return <span onClick={() => this.dispatchTrigger({ mode, record, modeMeta, index })} class={ mode }>{ text }</span>
351
+ }
352
+ }
353
+ }
354
+ return {
355
+ ...item
356
+ }
357
+ })
358
+ if (operations) {
359
+ return [
360
+ ...columnsOptions,
361
+ {
362
+ title: '操作',
363
+ width: operations.width,
364
+ key: 'action',
365
+ fixed: 'right',
366
+ scopedSlots: { customRender: 'action' }
367
+ }
368
+ ]
369
+ }
370
+ return columnsOptions
371
+ } else {
372
+ console.error('Error: columns is invalid, please check it')
373
+ return []
374
+ }
375
+ },
376
+ getButtonGroupElements () {
377
+ const { elements } = this.buttonGroupMeta
378
+ if (type.get(elements) === 'function') {
379
+ return elements.call(this)
380
+ } else if (type.get(elements) === 'array') {
381
+ return elements
382
+ } else {
383
+ return []
384
+ }
385
+ },
386
+ mapFields () {
387
+ const { replaceFields = {} } = this.treeMeta
388
+ const mapFields = type.isEmpty(replaceFields) ? this.replaceFields : replaceFields
389
+ return mapFields
390
+ }
391
+ },
392
+ async created () {
393
+ // onSearch会初始化请求表格数据,所以不需要在这里请求表格数据
394
+ // 确保全局数据池已初始化
395
+ if (!window.__idooel_data_pool__) {
396
+ console.error('Global data pool not initialized. Please check if runtime-context/globalDataPool.js is properly imported.')
397
+ return
398
+ }
399
+
400
+ // 初始化数据池管理器(使用新的 runtime-context)
401
+ try {
402
+ this.model = createTreeTableModel('treeTableModel')
403
+
404
+ if (!this.model) {
405
+ throw new Error('Failed to create tree table model')
406
+ }
407
+ } catch (error) {
408
+ console.error('Error creating tree table model:', error)
409
+ this.model = null
410
+ return
411
+ }
412
+
413
+ // 初始化 currentRowData(尝试从共享命名空间获取)
414
+ this.initializeCurrentRowData()
415
+
416
+ // 订阅数据池变化
417
+ this.unsubscribe = this.model.subscribe('currentRowData', (event) => {
418
+ this.currentRowData = event.value || {}
419
+ this.$forceUpdate()
420
+ })
421
+
422
+ // 订阅共享数据变化
423
+ this.unsubscribeShared = this.model.subscribeShared((event) => {
424
+ // 当有新的共享数据时,更新当前组件的 currentRowData
425
+ if (event.value && Object.keys(event.value).length > 0) {
426
+ this.setCurrentRowData(event.value)
427
+ }
428
+ })
429
+
430
+ if (this.showTree) {
431
+ this.treeData = await this.requestTreeData()
432
+ const [defaultTreeNode = {}] = this.treeData
433
+ this.defaultExpandedKeys = [defaultTreeNode[this.mapFields.key]]
434
+ this.defaultSelectedKeys = [defaultTreeNode[this.mapFields.key]]
435
+ this.currentTreeNodeData = defaultTreeNode
436
+ const { params = {}, fieldMap = {}, overrideInit = false } = this.tableMeta
437
+ const currentRowData = this.getCurrentRowData()
438
+ const ctx = {
439
+ ...this.currentTreeNodeData,
440
+ _route: this.$route.query,
441
+ currentRowData: currentRowData
442
+ }
443
+
444
+ const initQuerys = Object.assign({}, params, parseFieldMap(fieldMap, ctx))
445
+ if (overrideInit) {
446
+ this.$emit(RESERVE_EVENT_NAMES.INIT, { ...this.exposed })
447
+ } else {
448
+ this.tableData = await this.requestTableData(initQuerys)
449
+ }
450
+ }
451
+ },
452
+ methods: {
453
+ initializeCurrentRowData () {
454
+ if (!this.model) {
455
+ console.warn('Model not initialized, skipping currentRowData initialization')
456
+ return
457
+ }
458
+
459
+ // 检查是否有来自父组件的共享数据(比如 modal table 场景)
460
+ const parentData = this.model.getSharedData()
461
+
462
+ if (parentData && Object.keys(parentData).length > 0) {
463
+ this.setCurrentRowData(parentData)
464
+ return
465
+ }
466
+
467
+ // 可以根据路由参数、props 或其他来源设置初始的 currentRowData
468
+ const { query } = this.$route
469
+
470
+ // 示例:如果路由中有特定参数,可以设置为 currentRowData
471
+ if (query.rowId || query.selectedId) {
472
+ // 这里可以根据实际需求从服务端或其他地方获取数据
473
+ // const presetData = { id: query.rowId, /* 其他字段 */ }
474
+ // this.setCurrentRowData(presetData)
475
+ }
476
+
477
+ // 目前保持空对象,等待用户选择行数据
478
+ },
479
+ async refreshTreeData () {
480
+ this.treeData = await this.requestTreeData()
481
+ const [defaultTreeNode = {}] = this.treeData
482
+ this.defaultExpandedKeys = [defaultTreeNode[this.mapFields.key]]
483
+ this.defaultSelectedKeys = [defaultTreeNode[this.mapFields.key]]
484
+ this.currentTreeNodeData = defaultTreeNode
485
+ },
486
+ dispatchTrigger ({ mode, record = {}, modeMeta = { } }) {
487
+ switch (mode) {
488
+ case BUILT_IN_TRIGGER.FSM:
489
+ this[`${BUILT_IN_TRIGGER.FSM}Trigger`](record, modeMeta = type.isEmpty(modeMeta) ? {
490
+ url: 'api-fsm/workbench/fsm/auditFlow',
491
+ requestType: 'GET',
492
+ fieldMap: {
493
+ modelCode: 'modelCode',
494
+ businessId: 'businessId'
495
+ }
496
+ } : modeMeta)
497
+ break
498
+ case BUILT_IN_TRIGGER.ELE_MODAL_FORM:
499
+ this.modalFormMeta = modeMeta
500
+ this.showModalForm(modeMeta)
501
+ break
502
+ case BUILT_IN_TRIGGER.ELE_MODAL_TABLE:
503
+ this.modalTableMeta = modeMeta
504
+ // 将当前行的 record 数据传递给 modal table
505
+ this.showModalTable(modeMeta, record)
506
+ break
507
+ default:
508
+ break
509
+ }
510
+ },
511
+ handleCloseFsmModal () {
512
+ this.showFsmModal = false
513
+ },
514
+ [`${BUILT_IN_TRIGGER.FSM}Trigger`] (record, meta) {
515
+ this.fsmMeta = meta
516
+ this.fsmContextProp = record
517
+ this.showFsmModal = true
518
+ },
519
+ onChangeTableSelection (_, selectedRows = []) {
520
+ if (this.currentTableMode === 'radio') {
521
+ this.setCurrentTableSelection(selectedRows)
522
+ this.$emit('on-change-table-selection', this.currentTableSelection)
523
+ this.$emit('x:refresh-exposed', { exposed: this.exposed })
524
+ } else {
525
+ this.setCurrentTableSelection(selectedRows)
526
+ this.$emit('on-change-table-selection', this.currentTableSelection)
527
+ this.$emit('x:refresh-exposed', { exposed: this.exposed })
528
+ }
529
+ },
530
+ setCurrentTableSelection (props = {}) {
531
+ if (this.currentTableMode === 'radio') {
532
+ this.$set(this, 'currentTableSelection', (type.isArray(props) && props.length > 0) ? props[0] : type.isObject(props) ? props : {})
533
+ } else {
534
+ this.$set(this, 'currentTableSelection', type.isArray(props) ? props : [])
535
+ }
536
+ },
537
+ getCurrentTableSelection () {
538
+ return this.currentTableSelection
539
+ },
540
+ setCurrentRowData (props = {}) {
541
+ this.currentRowData = props
542
+ if (this.model) {
543
+ this.model.setCurrentRowData(props)
544
+ } else {
545
+ console.warn('Model not initialized, cannot setCurrentRowData in model')
546
+ }
547
+ },
548
+ getCurrentRowData () {
549
+ if (this.model) {
550
+ return this.model.getCurrentRowData()
551
+ }
552
+ console.warn('Model not initialized, getCurrentRowData returning local data')
553
+ return this.currentRowData || {}
554
+ },
555
+ cleanCurrentModelEffect (clearRowData = true) {
556
+ this.setCurrentTableSelection()
557
+ if (clearRowData) {
558
+ this.setCurrentRowData({})
559
+ }
560
+ },
561
+ [BUILT_IN_EVENT_NAMES.SUBMIT] (props = {}) {
562
+ this.cleanCurrentModelEffect()
563
+ this.requestTableData()
564
+ },
565
+ [BUILT_IN_EVENT_NAMES.EDIT] (props = {}) {
566
+ const { record = {} } = props
567
+ this.setCurrentRowData(record)
568
+ this.modalFormMeta = this.editMeta
569
+ this.modalFormValue = true
570
+ },
571
+ [BUILT_IN_EVENT_NAMES.CREATE] () {
572
+ this.modalFormMeta = this.createMeta
573
+ this.modalFormValue = true
574
+ },
575
+ showModalForm (modeMeta = {}) {
576
+ if (type.isStr(modeMeta)) {
577
+ const targetMeta = this.findMetaByKey(modeMeta)
578
+ this.modalFormMeta = targetMeta
579
+ } else {
580
+ this.modalFormMeta = modeMeta
581
+ }
582
+ this.modalFormValue = true
583
+ },
584
+ showModalTable (modeMeta = {}, record = null) {
585
+ // 获取当前行数据并设置到共享命名空间
586
+ const currentRowData = record || this.getCurrentRowData()
587
+ if (this.model) {
588
+ this.model.setSharedData(currentRowData)
589
+ } else {
590
+ console.warn('Model not initialized, cannot setSharedData')
591
+ }
592
+
593
+ let targetMeta = modeMeta
594
+ if (type.isStr(modeMeta)) {
595
+ targetMeta = this.findMetaByKey(modeMeta)
596
+ }
597
+
598
+ // 解析 fieldMap 参数,使用完整的上下文包括 currentRowData
599
+ if (targetMeta && targetMeta.fieldMap) {
600
+ const { fieldMap, params = {} } = targetMeta
601
+
602
+ const ctx = {
603
+ ...this.currentTreeNodeData,
604
+ _route: this.$route.query,
605
+ ...currentRowData
606
+ }
607
+ const parsedParams = parseFieldMap(fieldMap, ctx)
608
+
609
+ // 将当前的 currentRowData 传递给 modal table,通过 params
610
+ targetMeta = {
611
+ ...targetMeta,
612
+ params: {
613
+ ...params,
614
+ ...parsedParams
615
+ }
616
+ }
617
+ }
618
+
619
+ this.modalTableMeta = targetMeta
620
+ this.modalTableValue = true
621
+ },
622
+ closeModalForm () {
623
+ this.modalFormValue = false
624
+ },
625
+ closeModalTable () {
626
+ this.modalTableValue = false
627
+ },
628
+ findMetaByKey (key) {
629
+ return this.$attrs[key] || {}
630
+ },
631
+ handleClickButtonGroup (props) {
632
+ const { eventName, target } = props
633
+ const targetMeta = this.findMetaByKey(target)
634
+ const { mode } = targetMeta
635
+ mode && this.dispatchTrigger({ mode, modeMeta: targetMeta })
636
+ this.$emit(eventName || 'click', { currentTreeNode: this.currentTreeNodeData })
637
+ },
638
+ async onSearch (props) {
639
+ const { overrideInit = false } = this.tableMeta
640
+ this.tableQuerys = Object.assign(this.tableQuerys, props)
641
+ if (overrideInit) {
642
+ this.$emit(RESERVE_EVENT_NAMES.TREE_CHANGE, { ...this.exposed })
643
+ } else {
644
+ const { initSearch = false } = props
645
+ if (this.showTree && initSearch) return
646
+ this.tableData = await this.requestTableData()
647
+ }
648
+ },
649
+ async selectTreeNode (selectedKeys, e) {
650
+ const { fieldMap } = this.tableMeta
651
+ this.currentTreeNodeData = e.node.$vnode.data.props.dataRef || {}
652
+ //@deprecated '_' namespace is deprecated, please use 'exposed' instead
653
+ const execFieldMapRet = parseFieldMap(fieldMap, { ...this.currentTreeNodeData, exposed: this.exposed, _route: this.exposed._route })
654
+ const { overrideInit = false } = this.tableMeta
655
+ if (overrideInit) {
656
+ this.$emit(RESERVE_EVENT_NAMES.TREE_CHANGE, { ...this.exposed })
657
+ } else {
658
+ this.tableData = await this.requestTableData(execFieldMapRet)
659
+ }
660
+ },
661
+ async requestTreeData () {
662
+ const { url, requestType = 'GET', params = {}, fieldMap = {} } = this.treeMeta
663
+ const fieldMapRet = parseFieldMap(fieldMap, { ...this.currentTreeNodeData, _route: this.$route.query })
664
+ const ret = await net[requestType.toLowerCase()](
665
+ url,
666
+ { ...params, ...fieldMapRet }
667
+ ).then(resp => {
668
+ const { data } = resp || {}
669
+ return data
670
+ })
671
+ return ret
672
+ },
673
+ async onChangePage (page, pageSize) {
674
+ this.tableData = await this.requestTableData({ currentPage: page, pageSize })
675
+ },
676
+ async requestTableData (props = {}) {
677
+ const { url, requestType = 'GET', page = {} } = this.tableMeta
678
+ this.tableQuerys = Object.assign(this.tableQuerys, { currentPage: this.tableQuerys.currentPage || 1, pageSize: this.tableQuerys.pageSize || 10 }, props)
679
+ this.$emit(RESERVE_EVENT_NAMES.WATCH, { ...this.exposed })
680
+ this.loading = true
681
+ const ret = await net[requestType.toLowerCase()](
682
+ url,
683
+ this.tableQuerys
684
+ ).then(resp => {
685
+ const { data = [], count } = resp || {}
686
+ this.total = count
687
+ this.loading = false
688
+ return (data || []).map(item => {
689
+ delete item.children
690
+ return {
691
+ key: uuidv4(),
692
+ ...item
693
+ }
694
+ })
695
+ })
696
+ this.cleanCurrentModelEffect(false) // 不清空 currentRowData,除非明确需要
697
+ this.tableData = ret
698
+ return ret
699
+ },
700
+ calculateTableHeight () {
701
+ const currentViewportHeight = window.innerHeight
702
+ const tableRef = this.$refs[this.tableRef]
703
+ const { top: tableToTop, width } = tableRef.$el.getBoundingClientRect()
704
+ this.tableWidth = width
705
+ this.tableHeight = currentViewportHeight - tableToTop - this.overHeight
706
+ },
707
+ calculateTreeHeight () {
708
+ if (!this.showTree) return
709
+ const modelTableContainerRef = this.$refs[this.modelTableContainerRef]
710
+ const { height } = modelTableContainerRef.getBoundingClientRect()
711
+ this.treeWrapperHeight = height
712
+ },
713
+ async keepAliveRefresh () {
714
+ // 重新计算表格高度(应对窗口大小变化)
715
+ this.$nextTick(() => {
716
+ this.calculateTableHeight()
717
+ if (this.showTree) {
718
+ this.calculateTreeHeight()
719
+ }
720
+ })
721
+ // 刷新列表数据
722
+ const { overrideInit = false } = this.tableMeta
723
+ if (overrideInit) {
724
+ // 如果使用自定义初始化模式,触发 INIT 事件
725
+ this.$emit(RESERVE_EVENT_NAMES.INIT, { ...this.exposed })
726
+ } else {
727
+ // 使用当前查询参数刷新表格数据
728
+ await this.requestTableData(this.tableQuerys)
729
+ }
730
+ }
731
+ },
732
+ mounted () {
733
+ this.calculateTableHeight()
734
+ this.$nextTick(() => {
735
+ this.calculateTreeHeight()
736
+ })
737
+ this.resizeObserverModelTableWrapper = new ResizeObserver(entries => {
738
+ for (const _ of entries) {
739
+ requestAnimationFrame(() => {
740
+ this.calculateTableHeight()
741
+ })
742
+ }
743
+ })
744
+ this.resizeObserverModelTableWrapper.observe(this.$refs[this.modelTableWrapper])
745
+ },
746
+ destroyed () {
747
+ this.resizeObserverModelTableWrapper.disconnect()
748
+ if (this.model) {
749
+ // 清理订阅
750
+ if (this.unsubscribe) {
751
+ this.unsubscribe()
752
+ }
753
+ if (this.unsubscribeShared) {
754
+ this.unsubscribeShared()
755
+ }
756
+ // 清理模型数据
757
+ if (this.model) {
758
+ this.model.cleanup()
759
+ }
760
+ }
761
+ },
762
+ async activated () {
763
+ await this.keepAliveRefresh()
764
+ }
765
+ }
766
+ </script>
767
+
768
+ <style lang="scss" scoped>
769
+ .ele {
770
+ &.model__tree-table {
771
+ background: transparent;
772
+ display: flex;
773
+ flex-direction: row;
774
+ width: 100%;
775
+ .model__tree-table--container {
776
+ .model__tree--wrapper {
777
+ width: 240px;
778
+ background: #fff;
779
+ flex-shrink: 0;
780
+ padding: 16px;
781
+ box-sizing: border-box;
782
+ margin-right: 16px;
783
+ overflow-y: auto;
784
+ }
785
+ }
786
+ .model__table--container {
787
+ width: 100%;
788
+ min-width: 0;
789
+ background: #fff;
790
+ .model__table--title {
791
+ .model__table-title--bar {
792
+ width: 100%;
793
+ height: 8px;
794
+ background: var(--idooel-primary-color);
795
+ border-top-left-radius: 4px;
796
+ border-top-right-radius: 4px;
797
+ }
798
+ .model__table-title--text {
799
+ text-align: left;
800
+ padding: 16px;
801
+ font-size: 16px;
802
+ font-weight: bold;
803
+ background: #fff;
804
+ border-bottom: 1px solid;
805
+ border-color: var(--idoole-black-016);
806
+ }
807
+ }
808
+ .model__table--wrapper {
809
+ background: #fff;
810
+ .button-row__area {
811
+ width: 100%;
812
+ display: flex;
813
+ flex-direction: row;
814
+ align-items: center;
815
+ justify-content: space-between;
816
+ padding-top: 16px;
817
+ padding-bottom: 8px;
818
+ padding-right: 16px;
819
+ }
820
+ .g-table__wrapper {
821
+ .fsm {
822
+ cursor: pointer;
823
+ color: var(--idooel-primary-color);
824
+ }
825
+ }
826
+ }
827
+ }
828
+ }
829
+ }
830
+ </style>