@idooel/components 0.0.2-beta.3 → 0.0.2-beta.30

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 (113) hide show
  1. package/README.md +98 -98
  2. package/dist/@idooel/components.esm.js +3622 -1592
  3. package/dist/@idooel/components.umd.js +3676 -1647
  4. package/jsconfig.json +7 -7
  5. package/package.json +64 -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 +239 -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 +393 -319
  48. package/packages/icon/index.js +4 -4
  49. package/packages/icon/src/index.vue +31 -31
  50. package/packages/index.js +159 -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 +271 -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/README.md +0 -0
  67. package/packages/models/tree-table-model/index.js +4 -4
  68. package/packages/models/tree-table-model/src/index.vue +964 -689
  69. package/packages/pagination/index.js +5 -0
  70. package/packages/pagination/src/index.vue +372 -0
  71. package/packages/radio/index.js +4 -4
  72. package/packages/radio/src/index.vue +56 -56
  73. package/packages/select/index.js +4 -4
  74. package/packages/select/src/index.vue +113 -105
  75. package/packages/select-entity/index.js +4 -4
  76. package/packages/select-entity/src/index.vue +119 -119
  77. package/packages/table/index.js +4 -4
  78. package/packages/table/src/action.vue +176 -172
  79. package/packages/table/src/index.vue +605 -319
  80. package/packages/tabs/index.js +4 -4
  81. package/packages/tabs/src/index.vue +55 -55
  82. package/packages/text/index.js +4 -4
  83. package/packages/text/src/index.vue +47 -47
  84. package/packages/text-editor/index.js +4 -4
  85. package/packages/text-editor/src/index.vue +72 -72
  86. package/packages/textarea/index.js +4 -4
  87. package/packages/textarea/src/index.vue +57 -57
  88. package/packages/theme/form.scss +21 -21
  89. package/packages/theme/index.scss +43 -43
  90. package/packages/theme/overrid.scss +7 -7
  91. package/packages/theme/styleClass.scss +2 -2
  92. package/packages/theme/variables.scss +55 -55
  93. package/packages/timeline/index.js +4 -4
  94. package/packages/timeline/src/index.vue +257 -257
  95. package/packages/tpl/index.js +4 -4
  96. package/packages/tpl/src/index.vue +55 -55
  97. package/packages/tree/index.js +4 -4
  98. package/packages/tree/src/TreeNode.vue +29 -29
  99. package/packages/tree/src/index.vue +101 -101
  100. package/packages/tree-select/index.js +4 -4
  101. package/packages/tree-select/src/index.vue +142 -142
  102. package/packages/upload/index.js +4 -4
  103. package/packages/upload/src/index.vue +998 -494
  104. package/packages/utils/README.md +172 -0
  105. package/packages/utils/index.js +66 -62
  106. package/packages/utils/runtime-context/dataPoolAPI.js +501 -0
  107. package/packages/utils/runtime-context/globalDataPool.js +279 -0
  108. package/packages/utils/runtime-context/index.js +76 -0
  109. package/packages/utils/runtime-context/modelSchema.js +174 -0
  110. package/scripts/rollup.config.js +42 -42
  111. package/scripts/rollup.esm.config.js +11 -11
  112. package/scripts/rollup.umd.config.js +17 -14
  113. package/vitest.config.js +17 -0
@@ -1,320 +1,394 @@
1
- <template>
2
- <div class="ele__form--wrapper">
3
- <a-form :form="form" layout="vertical" class="ant-advanced-search-form">
4
- <a-row :gutter="24">
5
- <template v-for="ele in elements">
6
- <a-col v-if="executeExpression(ele._show)" :span="ele.span" :key="ele.name">
7
- <template v-if="ele.type == 'Input'">
8
- <a-form-item :label="`${ele.label}:`">
9
- <ele-input
10
- @change="onChange($event, ele)"
11
- :disabled="executeExpression(ele._disabled)"
12
- :max-length="ele.maxLength"
13
- v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
14
- style="width:100%;">
15
- </ele-input>
16
- </a-form-item>
17
- </template>
18
- <template v-else-if="ele.type == 'Textarea'">
19
- <a-form-item :label="`${ele.label}:`">
20
- <ele-textarea
21
- @change="onChange($event, ele)"
22
- :max-length="ele.maxLength"
23
- :autosize="ele.autosize"
24
- :disabled="executeExpression(ele._disabled)"
25
- :allow-clear="ele.allowClear"
26
- :placeholder="ele.placeholder"
27
- v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
28
- style="width:100%;">
29
- </ele-textarea>
30
- </a-form-item>
31
- </template>
32
- <template v-else-if="ele.type == 'Select'">
33
- <a-form-item :label="`${ele.label}:`">
34
- <ele-select
35
- :data-source="ele.optionList"
36
- :disabled="executeExpression(ele._disabled)"
37
- :multiple="ele.multiple"
38
- :mode="ele.mode"
39
- :code="ele.code"
40
- :init="ele.init"
41
- :url="ele.url"
42
- :params="ele.params"
43
- @change="onChange($event, ele)"
44
- v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
45
- style="width:100%;">
46
- </ele-select>
47
- </a-form-item>
48
- </template>
49
- <template v-else-if="ele.type == 'ele-upload'">
50
- <a-form-item :label="`${ele.label}:`">
51
- <ele-upload v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
52
- :ext="ele.ext"
53
- :multiple="ele.multiple"
54
- :accept="ele.accept"
55
- :extensions="ele.extensions"
56
- :size="ele.size"
57
- :icon="ele.icon"
58
- :url="ele.url"
59
- :message="ele.message"
60
- style="width:100%;">
61
- </ele-upload>
62
- </a-form-item>
63
- </template>
64
- <template v-else-if="ele.type == 'ele-date-range'">
65
- <a-form-item :label="`${ele.label}:`">
66
- <ele-date-range
67
- :disabled="executeExpression(ele._disabled)"
68
- v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
69
- style="width:100%;">
70
- </ele-date-range>
71
- </a-form-item>
72
- </template>
73
- <template v-else-if="ele.type == 'ele-date'">
74
- <a-form-item :label="`${ele.label}:`">
75
- <ele-date
76
- :format="ele.format"
77
- :mode="ele.mode"
78
- :show-time="ele.showTime"
79
- :show-today="ele.showToday"
80
- :value-format="ele.valueFormat"
81
- :disabled="executeExpression(ele._disabled)"
82
- v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
83
- style="width:100%;">
84
- </ele-date>
85
- </a-form-item>
86
- </template>
87
- <template v-else-if="ele.type == 'SelectEntity'">
88
- <a-form-item :label="`${ele.label}:`">
89
- <ele-select-entity
90
- v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
91
- style="width:100%;">
92
- </ele-select-entity>
93
- </a-form-item>
94
- </template>
95
- <template v-else-if="ele.type == 'InputNumber' || ele.type == 'ele-input-number'">
96
- <a-form-item :label="`${ele.label}:`">
97
- <ele-input-number
98
- @change="onChange($event, ele)"
99
- :precision="ele.precision"
100
- :disabled="executeExpression(ele._disabled)"
101
- v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
102
- v-bind="ele.props"
103
- style="width:100%;">
104
- </ele-input-number>
105
- </a-form-item>
106
- </template>
107
- <template v-else-if="ele.type == 'Checkbox'">
108
- <a-form-item :label="`${ele.label}:`">
109
- <ele-checkbox
110
- :data-source="ele.optionList"
111
- :disabled="executeExpression(ele._disabled)"
112
- v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
113
- style="width:100%;">
114
- </ele-checkbox>
115
- </a-form-item>
116
- </template>
117
- <template v-else-if="ele.type == 'Radio'">
118
- <a-form-item :label="`${ele.label}:`">
119
- <ele-radio
120
- @change="onChange($event, ele)"
121
- :disabled="executeExpression(ele._disabled)"
122
- :data-source="ele.optionList"
123
- v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
124
- style="width:100%;">
125
- </ele-radio>
126
- </a-form-item>
127
- </template>
128
- <template v-else-if="ele.type == 'ele-form-img-crop'">
129
- <a-form-item :label="`${ele.label}:`">
130
- <ele-form-img-crop
131
- @change="onChange($event, ele)"
132
- :width="ele.width"
133
- :height="ele.height"
134
- :modal-title="ele.modalTitle"
135
- :cropper-config="ele.cropperConfig"
136
- :uploadFileConfig="ele.uploadFileConfig"
137
- :oper-text="ele.operText"
138
- :disabled="executeExpression(ele._disabled)"
139
- v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
140
- style="width:100%;">
141
- </ele-form-img-crop>
142
- </a-form-item>
143
- </template>
144
- <template v-else-if="ele.type == 'ele-tree-select'">
145
- <a-form-item :label="`${ele.label}:`">
146
- <ele-tree-select
147
- @change="onChange($event, ele)"
148
- :disabled="executeExpression(ele._disabled)"
149
- v-bind="ele.meta"
150
- v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
151
- style="width:100%;">
152
- </ele-tree-select>
153
- </a-form-item>
154
- </template>
155
- <template v-else-if="ele.type == 'ele-select-entity-modal-table'">
156
- <a-form-item :label="`${ele.label}:`">
157
- <ele-select-entity-modal-table
158
- @change="onChange($event, ele)"
159
- :disabled="executeExpression(ele._disabled)"
160
- v-bind="ele.meta"
161
- v-decorator="[ele.name, { rules: rebuildRules(ele.rules) }]"
162
- style="width:100%;">
163
- </ele-select-entity-modal-table>
164
- </a-form-item>
165
- </template>
166
- </a-col>
167
- </template>
168
- </a-row>
169
- </a-form>
170
- </div>
171
- </template>
172
-
173
- <script>
174
- import { parse } from '@idooel/expression'
175
- import { type } from '@idooel/shared'
176
- import { CONTEXT } from '../../utils'
177
- export default {
178
- name: 'ele-form',
179
- props: {
180
- value: {
181
- type: Object,
182
- default: () => ({})
183
- },
184
- disabled: {
185
- type: [Boolean, String],
186
- default: '_routeMeta.disabled'
187
- },
188
- formName: {
189
- type: [Number, String],
190
- default: 'coordinated'
191
- },
192
- elements: {
193
- type: Array,
194
- default: () => []
195
- }
196
- },
197
- data () {
198
- return {
199
- formModel: {}
200
- }
201
- },
202
- inject: {
203
- [CONTEXT]: {
204
- default: () => (() => ({}))
205
- }
206
- },
207
- computed: {
208
- contextData () {
209
- return this[CONTEXT].call(this)
210
- },
211
- globalDisabled () {
212
- return this.executeExpression(this.disabled)
213
- },
214
- form () {
215
- const ref = this.$form.createForm(this, { name: this.formName })
216
- return ref
217
- },
218
- exposedMethods () {
219
- return {
220
- setFieldsValue: this.setFieldsValue,
221
- getFieldsValue: this.getFieldsValue
222
- }
223
- }
224
- },
225
- created () {
226
- this.setDefaultValues()
227
- },
228
- methods: {
229
- setFormModel (props = {}) {
230
- this.formModel = props
231
- this.dispatchExpression()
232
- },
233
- rebuildRules (rules = []) {
234
- //TODO
235
- rules.map(rule => {
236
- const { validator } = rule
237
- if (validator) {
238
- validator.formModel = this.getFieldsValue()
239
- validator.exposed = this.exposedMethods
240
- }
241
- })
242
- return rules
243
- },
244
- dispatchExpression () {
245
- this.evalDisabledExpression()
246
- this.evalShowExpression()
247
- },
248
- evalDisabledExpression () {
249
- this.elements.forEach(ele => {
250
- if (this.globalDisabled) return this.$set(ele, '_disabled', true)
251
- const { disabled } = ele
252
- const ret = this.executeExpression(disabled)
253
- this.$set(ele, '_disabled', ret)
254
- })
255
- },
256
- evalShowExpression () {
257
- this.elements.forEach(ele => {
258
- const { show = true } = ele
259
- const ret = this.executeExpression(show)
260
- this.$set(ele, '_show', ret)
261
- })
262
- },
263
- executeExpression (expression) {
264
- if (type.isBool(expression)) return expression
265
- if (type.isEmpty(expression)) return false
266
- return parse(expression, { ...this.getFieldsValue(), ...this.formModel, _route: this.$route.query, _routeMeta: this.$route.meta })
267
- },
268
- onChange (value, props) {
269
- const { name } = props
270
- this.$set(this.formModel, name, value)
271
- this.dispatchExpression()
272
- this.setFieldsValue({ [name]: value })
273
- this.$emit('change', { value, props, exposed: { ...this.exposedMethods } })
274
- },
275
- collectDefaultValues () {
276
- const ret = this.elements.reduce((ret, props) => {
277
- const { name, defaultValue } = props
278
- if (defaultValue) {
279
- ret[name] = defaultValue
280
- }
281
- return ret
282
- }, {})
283
- return ret
284
- },
285
- //TODO deprecated in the future, need to be implemented in the outer component
286
- setDefaultValues () {
287
- const defaultValues = this.collectDefaultValues()
288
- this.setFormModel(defaultValues)
289
- this.setFieldsValue(defaultValues)
290
- },
291
- validateFields () {
292
- let ret = false
293
- this.form.validateFields((error, values) => {
294
- ret = !error
295
- })
296
- return ret
297
- },
298
- setFieldsValue (props = {}) {
299
- this.$nextTick(() => {
300
- this.form.setFieldsValue(props)
301
- })
302
- },
303
- getFieldsValue (fieldNames) {
304
- return this.form.getFieldsValue(fieldNames)
305
- }
306
- },
307
- mounted() {
308
- this.$emit('x:mounted', { setFormModel: this.setFormModel })
309
- this.dispatchExpression()
310
- }
311
- }
312
- </script>
313
-
314
- <style lang="scss" scoped>
315
- .ele__form--wrapper {
316
- background: #fff;
317
- .ant-form-item {
318
- }
319
- }
1
+ <template>
2
+ <div class="ele__form--wrapper">
3
+ <a-form :form="form" layout="vertical" class="ant-advanced-search-form">
4
+ <a-row :gutter="24">
5
+ <template v-for="ele in elements">
6
+ <a-col v-if="ele._show" :span="ele.span" :key="`${ele.name}_${ele._rulesVersion || 0}`">
7
+ <template v-if="ele.type == 'ele-input' || ele.type == 'Input'">
8
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
9
+ <ele-input
10
+ @change="onChange($event, ele)"
11
+ :disabled="ele._disabled"
12
+ :max-length="ele.maxLength"
13
+ v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
14
+ style="width:100%;">
15
+ </ele-input>
16
+ </a-form-item>
17
+ </template>
18
+ <template v-else-if="ele.type == 'ele-textarea' || ele.type == 'Textarea'">
19
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
20
+ <ele-textarea
21
+ @change="onChange($event, ele)"
22
+ :max-length="ele.maxLength"
23
+ :autosize="ele.autosize"
24
+ :disabled="ele._disabled"
25
+ :allow-clear="ele.allowClear"
26
+ :placeholder="ele.placeholder"
27
+ v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
28
+ style="width:100%;">
29
+ </ele-textarea>
30
+ </a-form-item>
31
+ </template>
32
+ <template v-else-if="ele.type == 'ele-select' || ele.type == 'Select'">
33
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
34
+ <ele-select
35
+ :data-source="ele.optionList"
36
+ :disabled="ele._disabled"
37
+ :multiple="ele.multiple"
38
+ :mode="ele.mode"
39
+ :code="ele.code"
40
+ :init="ele.init"
41
+ :url="ele.url"
42
+ :params="ele.params"
43
+ @change="onChange($event, ele)"
44
+ v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
45
+ style="width:100%;">
46
+ </ele-select>
47
+ </a-form-item>
48
+ </template>
49
+ <template v-else-if="ele.type == 'ele-upload'">
50
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
51
+ <ele-upload v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
52
+ :ext="ele.ext"
53
+ :multiple="ele.multiple"
54
+ :accept="ele.accept"
55
+ :extensions="ele.extensions"
56
+ :size="ele.size"
57
+ :icon="ele.icon"
58
+ :url="ele.url"
59
+ :message="ele.message"
60
+ style="width:100%;">
61
+ </ele-upload>
62
+ </a-form-item>
63
+ </template>
64
+ <template v-else-if="ele.type == 'ele-date-range'">
65
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
66
+ <ele-date-range
67
+ :disabled="ele._disabled"
68
+ v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
69
+ style="width:100%;">
70
+ </ele-date-range>
71
+ </a-form-item>
72
+ </template>
73
+ <template v-else-if="ele.type == 'ele-date'">
74
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
75
+ <ele-date
76
+ :format="ele.format"
77
+ :mode="ele.mode"
78
+ :show-time="ele.showTime"
79
+ :show-today="ele.showToday"
80
+ :value-format="ele.valueFormat"
81
+ :disabled="ele._disabled"
82
+ v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
83
+ style="width:100%;">
84
+ </ele-date>
85
+ </a-form-item>
86
+ </template>
87
+ <template v-else-if="ele.type == 'ele-select-entity' || ele.type == 'SelectEntity'">
88
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
89
+ <ele-select-entity
90
+ v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
91
+ style="width:100%;">
92
+ </ele-select-entity>
93
+ </a-form-item>
94
+ </template>
95
+ <template v-else-if="ele.type == 'InputNumber' || ele.type == 'ele-input-number'">
96
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
97
+ <ele-input-number
98
+ @change="onChange($event, ele)"
99
+ :precision="ele.precision"
100
+ :disabled="ele._disabled"
101
+ v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
102
+ v-bind="ele.props"
103
+ style="width:100%;">
104
+ </ele-input-number>
105
+ </a-form-item>
106
+ </template>
107
+ <template v-else-if="ele.type == 'ele-Checkbox' || ele.type == 'Checkbox'">
108
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
109
+ <ele-checkbox
110
+ :data-source="ele.optionList"
111
+ :disabled="ele._disabled"
112
+ v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
113
+ style="width:100%;">
114
+ </ele-checkbox>
115
+ </a-form-item>
116
+ </template>
117
+ <template v-else-if="ele.type == 'ele-radio' || ele.type == 'Radio'">
118
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
119
+ <ele-radio
120
+ @change="onChange($event, ele)"
121
+ :disabled="ele._disabled"
122
+ :data-source="ele.optionList"
123
+ v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
124
+ style="width:100%;">
125
+ </ele-radio>
126
+ </a-form-item>
127
+ </template>
128
+ <template v-else-if="ele.type == 'ele-form-img-crop'">
129
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
130
+ <ele-form-img-crop
131
+ @change="onChange($event, ele)"
132
+ :width="ele.width"
133
+ :height="ele.height"
134
+ :modal-title="ele.modalTitle"
135
+ :cropper-config="ele.cropperConfig"
136
+ :uploadFileConfig="ele.uploadFileConfig"
137
+ :oper-text="ele.operText"
138
+ :disabled="ele._disabled"
139
+ v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
140
+ style="width:100%;">
141
+ </ele-form-img-crop>
142
+ </a-form-item>
143
+ </template>
144
+ <template v-else-if="ele.type == 'ele-tree-select'">
145
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
146
+ <ele-tree-select
147
+ @change="onChange($event, ele)"
148
+ :disabled="ele._disabled"
149
+ v-bind="ele.meta"
150
+ v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
151
+ style="width:100%;">
152
+ </ele-tree-select>
153
+ </a-form-item>
154
+ </template>
155
+ <template v-else-if="ele.type == 'ele-select-entity-modal-table'">
156
+ <a-form-item :label="`${ele.label}:`" :required="ele._required">
157
+ <ele-select-entity-modal-table
158
+ @change="onChange($event, ele)"
159
+ :disabled="ele._disabled"
160
+ v-bind="ele.meta"
161
+ v-decorator="[ele.name, { rules: rebuildRules(ele) }]"
162
+ style="width:100%;">
163
+ </ele-select-entity-modal-table>
164
+ </a-form-item>
165
+ </template>
166
+ </a-col>
167
+ </template>
168
+ </a-row>
169
+ </a-form>
170
+ </div>
171
+ </template>
172
+
173
+ <script>
174
+ import { parse } from '@idooel/expression'
175
+ import { type } from '@idooel/shared'
176
+ import { CONTEXT } from '../../utils'
177
+ export default {
178
+ name: 'ele-form',
179
+ props: {
180
+ value: {
181
+ type: Object,
182
+ default: () => ({})
183
+ },
184
+ disabled: {
185
+ type: [Boolean, String],
186
+ default: '_routeMeta.disabled'
187
+ },
188
+ formName: {
189
+ type: [Number, String],
190
+ default: 'coordinated'
191
+ },
192
+ elements: {
193
+ type: Array,
194
+ default: () => []
195
+ }
196
+ },
197
+ data () {
198
+ return {
199
+ formModel: {}
200
+ }
201
+ },
202
+ inject: {
203
+ [CONTEXT]: {
204
+ default: () => (() => ({}))
205
+ }
206
+ },
207
+ computed: {
208
+ contextData () {
209
+ return this[CONTEXT].call(this)
210
+ },
211
+ globalDisabled () {
212
+ return this.executeExpression(this.disabled)
213
+ },
214
+ form () {
215
+ const ref = this.$form.createForm(this, { name: this.formName, onFieldsChange: this.onFieldsChange })
216
+ return ref
217
+ },
218
+ exposedMethods () {
219
+ return {
220
+ setFieldsValue: this.setFieldsValue,
221
+ getFieldsValue: this.getFieldsValue
222
+ }
223
+ }
224
+ },
225
+ created () {
226
+ this.setDefaultValues()
227
+ },
228
+ methods: {
229
+ onFieldsChange () {
230
+ this.executeOptionListExpression()
231
+ this.dispatchExpression()
232
+ },
233
+ executeOptionListExpression () {
234
+ this.elements.forEach(ele => {
235
+ if (ele.optionList) {
236
+ const optionList = this.evalOptionListExpression(ele.optionList)
237
+ this.$set(ele, 'optionList', optionList)
238
+ }
239
+ })
240
+ },
241
+ evalOptionListExpression (optionList = []) {
242
+ const executeExpression = (expression) => {
243
+ if (type.isBool(expression)) return expression
244
+ if (type.isEmpty(expression)) return true
245
+ const ret = parse(expression, { ...this.formModel, ...this.getFieldsValue(), _route: this.$route.query, _routeMeta: this.$route.meta })
246
+ return ret
247
+ }
248
+ return optionList.map(item => {
249
+ const { show } = item
250
+ return { ...item, _show: executeExpression(show) }
251
+ })
252
+ },
253
+ setFormModel (props = {}) {
254
+ this.formModel = props
255
+ this.dispatchExpression()
256
+ },
257
+ rebuildRules (ele) {
258
+ const { rules = [] } = ele
259
+ const nextRules = rules.map(rule => {
260
+ const nextRule = { ...rule }
261
+ const { validator, required } = nextRule
262
+ // 支持 validator 函数
263
+ if (validator) {
264
+ nextRule.validator = (rule, value, cb) => {
265
+ validator.formModel = this.getFieldsValue()
266
+ validator.exposed = this.exposedMethods
267
+ return validator(rule, value, cb)
268
+ }
269
+ }
270
+ // 支持 rules 内部的 required 表达式
271
+ if (required !== undefined && type.isStr(required)) {
272
+ nextRule.required = this.executeExpression(required)
273
+ }
274
+ return nextRule
275
+ })
276
+ // 支持顶层 required 表达式(优先级高于 rules 内部)
277
+ const { required } = ele
278
+ if (required !== undefined) {
279
+ const isRequired = this.executeExpression(required)
280
+ const hasRequiredRule = nextRules.some(r => Object.keys(r).includes('required'))
281
+ if (!hasRequiredRule) {
282
+ nextRules.unshift({ required: isRequired, message: `${ele.label}是必填项` })
283
+ } else {
284
+ nextRules.forEach(r => {
285
+ if (Object.keys(r).includes('required')) {
286
+ r.required = isRequired
287
+ }
288
+ })
289
+ }
290
+ }
291
+ return nextRules
292
+ },
293
+ dispatchExpression () {
294
+ this.evalDisabledExpression()
295
+ this.evalShowExpression()
296
+ this.evalRequiredExpression()
297
+ },
298
+ evalRequiredExpression () {
299
+ this.elements.forEach(ele => {
300
+ // 优先使用顶层 required 表达式
301
+ let requiredExpr = ele.required
302
+ // 如果顶层没有,则从 rules 中查找
303
+ if (requiredExpr === undefined && ele.rules) {
304
+ const requiredRule = ele.rules.find(r => r.required !== undefined)
305
+ if (requiredRule) {
306
+ requiredExpr = requiredRule.required
307
+ }
308
+ }
309
+ if (requiredExpr !== undefined) {
310
+ const ret = this.executeExpression(requiredExpr)
311
+ const oldRequired = ele._required
312
+ this.$set(ele, '_required', ret)
313
+ // 初始化或状态变化时更新版本号,强制组件重新渲染
314
+ if (oldRequired === undefined || oldRequired !== ret) {
315
+ const currentVersion = ele._rulesVersion || 0
316
+ this.$set(ele, '_rulesVersion', currentVersion + 1)
317
+ }
318
+ }
319
+ })
320
+ },
321
+ evalDisabledExpression () {
322
+ this.elements.forEach(ele => {
323
+ if (this.globalDisabled) return this.$set(ele, '_disabled', true)
324
+ const { disabled } = ele
325
+ const ret = this.executeExpression(disabled)
326
+ this.$set(ele, '_disabled', ret)
327
+ })
328
+ },
329
+ evalShowExpression () {
330
+ this.elements.forEach(ele => {
331
+ const { show = true } = ele
332
+ const ret = this.executeExpression(show)
333
+ this.$set(ele, '_show', ret)
334
+ })
335
+ },
336
+ executeExpression (expression) {
337
+ if (type.isBool(expression)) return expression
338
+ if (type.isEmpty(expression)) return false
339
+ const scope = { ...this.formModel, ...this.getFieldsValue(), _route: this.$route.query, _routeMeta: this.$route.meta }
340
+ return parse(expression, scope)
341
+ },
342
+ onChange (value, props) {
343
+ const { name } = props
344
+ this.$set(this.formModel, name, value)
345
+ this.dispatchExpression()
346
+ this.setFieldsValue({ [name]: value })
347
+ this.$emit('change', { value, props, exposed: { ...this.exposedMethods } })
348
+ },
349
+ collectDefaultValues () {
350
+ const ret = this.elements.reduce((ret, props) => {
351
+ const { name, defaultValue } = props
352
+ if (defaultValue) {
353
+ ret[name] = defaultValue
354
+ }
355
+ return ret
356
+ }, {})
357
+ return ret
358
+ },
359
+ //TODO deprecated in the future, need to be implemented in the outer component
360
+ setDefaultValues () {
361
+ const defaultValues = this.collectDefaultValues()
362
+ this.setFormModel(defaultValues)
363
+ this.setFieldsValue(defaultValues)
364
+ },
365
+ validateFields () {
366
+ return new Promise((resolve) => {
367
+ this.form.validateFields((error, values) => {
368
+ resolve(!error)
369
+ })
370
+ })
371
+ },
372
+ setFieldsValue (props = {}) {
373
+ this.$nextTick(() => {
374
+ this.form.setFieldsValue(props)
375
+ })
376
+ },
377
+ getFieldsValue (fieldNames) {
378
+ return this.form.getFieldsValue(fieldNames)
379
+ }
380
+ },
381
+ mounted() {
382
+ this.$emit('x:mounted', { setFormModel: this.setFormModel })
383
+ this.dispatchExpression()
384
+ }
385
+ }
386
+ </script>
387
+
388
+ <style lang="scss" scoped>
389
+ .ele__form--wrapper {
390
+ background: #fff;
391
+ .ant-form-item {
392
+ }
393
+ }
320
394
  </style>