@ddwl/ddwl-ui 1.2.3-beta.1 → 1.2.3-beta.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 (144) hide show
  1. package/dist/app.common.js +30684 -0
  2. package/dist/app.css +18 -0
  3. package/dist/app.umd.js +30703 -0
  4. package/dist/app.umd.min.js +18 -0
  5. package/dist/demo.html +1 -0
  6. package/package.json +5 -4
  7. package/src/assets/video-play.jpeg +0 -0
  8. package/src/lib/install/index.js +14 -0
  9. package/src/lib/slots/buttonGroup.vue +113 -0
  10. package/src/lib/slots/dict.vue +46 -0
  11. package/src/lib/slots/file.vue +36 -0
  12. package/src/lib/slots/icon.vue +74 -0
  13. package/src/lib/slots/index.js +11 -0
  14. package/src/lib/theme/alert.css +1 -0
  15. package/src/lib/theme/aside.css +1 -0
  16. package/src/lib/theme/autocomplete.css +1 -0
  17. package/src/lib/theme/avatar.css +1 -0
  18. package/src/lib/theme/backtop.css +1 -0
  19. package/src/lib/theme/badge.css +1 -0
  20. package/src/lib/theme/base.css +1 -0
  21. package/src/lib/theme/breadcrumb-item.css +0 -0
  22. package/src/lib/theme/breadcrumb.css +1 -0
  23. package/src/lib/theme/button-group.css +0 -0
  24. package/src/lib/theme/button.css +1 -0
  25. package/src/lib/theme/calendar.css +1 -0
  26. package/src/lib/theme/card.css +1 -0
  27. package/src/lib/theme/carousel-item.css +1 -0
  28. package/src/lib/theme/carousel.css +1 -0
  29. package/src/lib/theme/cascader-panel.css +1 -0
  30. package/src/lib/theme/cascader.css +1 -0
  31. package/src/lib/theme/checkbox-button.css +0 -0
  32. package/src/lib/theme/checkbox-group.css +0 -0
  33. package/src/lib/theme/checkbox.css +1 -0
  34. package/src/lib/theme/col.css +1 -0
  35. package/src/lib/theme/collapse-item.css +0 -0
  36. package/src/lib/theme/collapse.css +1 -0
  37. package/src/lib/theme/color-picker.css +1 -0
  38. package/src/lib/theme/container.css +1 -0
  39. package/src/lib/theme/date-picker.css +1 -0
  40. package/src/lib/theme/descriptions-item.css +1 -0
  41. package/src/lib/theme/descriptions.css +1 -0
  42. package/src/lib/theme/dialog.css +1 -0
  43. package/src/lib/theme/display.css +1 -0
  44. package/src/lib/theme/divider.css +1 -0
  45. package/src/lib/theme/drawer.css +1 -0
  46. package/src/lib/theme/dropdown-item.css +0 -0
  47. package/src/lib/theme/dropdown-menu.css +0 -0
  48. package/src/lib/theme/dropdown.css +1 -0
  49. package/src/lib/theme/empty.css +1 -0
  50. package/src/lib/theme/fonts/element-icons.ttf +0 -0
  51. package/src/lib/theme/fonts/element-icons.woff +0 -0
  52. package/src/lib/theme/footer.css +1 -0
  53. package/src/lib/theme/form-item.css +0 -0
  54. package/src/lib/theme/form.css +1 -0
  55. package/src/lib/theme/header.css +1 -0
  56. package/src/lib/theme/icon.css +1 -0
  57. package/src/lib/theme/image.css +1 -0
  58. package/src/lib/theme/index.css +1 -0
  59. package/src/lib/theme/infinite-scroll.css +0 -0
  60. package/src/lib/theme/infiniteScroll.css +0 -0
  61. package/src/lib/theme/input-number.css +1 -0
  62. package/src/lib/theme/input.css +1 -0
  63. package/src/lib/theme/link.css +1 -0
  64. package/src/lib/theme/loading.css +1 -0
  65. package/src/lib/theme/main.css +1 -0
  66. package/src/lib/theme/menu-item-group.css +0 -0
  67. package/src/lib/theme/menu-item.css +0 -0
  68. package/src/lib/theme/menu.css +1 -0
  69. package/src/lib/theme/message-box.css +1 -0
  70. package/src/lib/theme/message.css +1 -0
  71. package/src/lib/theme/notification.css +1 -0
  72. package/src/lib/theme/option-group.css +1 -0
  73. package/src/lib/theme/option.css +1 -0
  74. package/src/lib/theme/page-header.css +1 -0
  75. package/src/lib/theme/pagination.css +1 -0
  76. package/src/lib/theme/popconfirm.css +1 -0
  77. package/src/lib/theme/popover.css +1 -0
  78. package/src/lib/theme/popper.css +1 -0
  79. package/src/lib/theme/progress.css +1 -0
  80. package/src/lib/theme/radio-button.css +1 -0
  81. package/src/lib/theme/radio-group.css +1 -0
  82. package/src/lib/theme/radio.css +1 -0
  83. package/src/lib/theme/rate.css +1 -0
  84. package/src/lib/theme/reset.css +1 -0
  85. package/src/lib/theme/result.css +1 -0
  86. package/src/lib/theme/row.css +1 -0
  87. package/src/lib/theme/scrollbar.css +1 -0
  88. package/src/lib/theme/select-dropdown.css +1 -0
  89. package/src/lib/theme/select.css +1 -0
  90. package/src/lib/theme/skeleton-item.css +1 -0
  91. package/src/lib/theme/skeleton.css +1 -0
  92. package/src/lib/theme/slider.css +1 -0
  93. package/src/lib/theme/spinner.css +1 -0
  94. package/src/lib/theme/step.css +1 -0
  95. package/src/lib/theme/steps.css +1 -0
  96. package/src/lib/theme/submenu.css +0 -0
  97. package/src/lib/theme/switch.css +1 -0
  98. package/src/lib/theme/tab-pane.css +0 -0
  99. package/src/lib/theme/table-column.css +1 -0
  100. package/src/lib/theme/table.css +1 -0
  101. package/src/lib/theme/tabs.css +1 -0
  102. package/src/lib/theme/tag.css +1 -0
  103. package/src/lib/theme/time-picker.css +1 -0
  104. package/src/lib/theme/time-select.css +1 -0
  105. package/src/lib/theme/timeline-item.css +1 -0
  106. package/src/lib/theme/timeline.css +1 -0
  107. package/src/lib/theme/tooltip.css +1 -0
  108. package/src/lib/theme/transfer.css +1 -0
  109. package/src/lib/theme/tree.css +1 -0
  110. package/src/lib/theme/upload.css +1 -0
  111. package/src/main.js +70 -0
  112. package/src/packages/button/index.vue +36 -0
  113. package/src/packages/checkbox-group/index.vue +57 -0
  114. package/src/packages/descriptions/index.vue +124 -0
  115. package/src/packages/dialog/index.vue +172 -0
  116. package/src/packages/dialog-confirm/index.vue +99 -0
  117. package/src/packages/drawer/index.vue +136 -0
  118. package/src/packages/file-preview/index.vue +275 -0
  119. package/src/packages/file-preview/static/audio.png +0 -0
  120. package/src/packages/file-preview/static/video.png +0 -0
  121. package/src/packages/filter-tree/index.vue +292 -0
  122. package/src/packages/form/index.vue +149 -0
  123. package/src/packages/form-item/index.vue +199 -0
  124. package/src/packages/import-file/index.vue +173 -0
  125. package/src/packages/menu/index.vue +66 -0
  126. package/src/packages/menu/menuItem.vue +90 -0
  127. package/src/packages/popconfirm/index.vue +39 -0
  128. package/src/packages/radio-group/index.vue +57 -0
  129. package/src/packages/render/index.vue +14 -0
  130. package/src/packages/search-form/index.vue +257 -0
  131. package/src/packages/search-input/index.vue +68 -0
  132. package/src/packages/search-table/index.vue +93 -0
  133. package/src/packages/select/index.vue +74 -0
  134. package/src/packages/svg-icon/index.vue +43 -0
  135. package/src/packages/table/drag.png +0 -0
  136. package/src/packages/table/index.vue +453 -0
  137. package/src/packages/upload/index.vue +350 -0
  138. package/src/utils/constant.js +4 -0
  139. package/src/utils/index.js +77 -0
  140. package/src/utils/treeLib.js +190 -0
  141. package/dist/index.html +0 -1
  142. package/dist/js/app.js +0 -1
  143. package/dist/js/chunk-vendors.js +0 -17
  144. package/dist/static/css/app.2ec4a629.css +0 -1
@@ -0,0 +1,292 @@
1
+ <!-- eslint-disable vue/no-template-shadow -->
2
+ <!-- 多功能筛选树 -->
3
+ <template>
4
+ <div class="d-filter-tree">
5
+ <slot name="header" />
6
+ <el-input
7
+ v-if="filterable"
8
+ v-model="searchContent"
9
+ type="text"
10
+ :placeholder="placeholder"
11
+ suffix-icon="el-icon-search"
12
+ />
13
+ <el-tree
14
+ ref="tree"
15
+ class="filter-tree mt16"
16
+ :data="data"
17
+ :node-key="nodeKey"
18
+ :expand-on-click-node="false"
19
+ highlight-current
20
+ :props="props"
21
+ :filter-node-method="filterNode"
22
+ :default-expanded-keys="defaultExpandIds"
23
+ v-bind="$attrs"
24
+ @node-click="nodeClick"
25
+ @node-expand="(data)=>handleNodeToggle(data,true)"
26
+ @node-collapse="(data)=>handleNodeToggle(data,false)"
27
+ v-on="$listeners"
28
+ >
29
+ <span
30
+ slot-scope="{ node, data }"
31
+ class="d-filter-tree-node"
32
+ >
33
+ <span class="node-label ellipsis">
34
+ <slot
35
+ name="label"
36
+ :data="data"
37
+ >{{ node.label }}</slot>
38
+ </span>
39
+ <span class="mr8">
40
+ <slot name="button" :node="node"></slot>
41
+ <el-button
42
+ v-if="showNodeButton('append', data)"
43
+ type="text"
44
+ icon="el-icon-plus"
45
+ @click.stop="append(node)"
46
+ />
47
+ <el-button
48
+ v-if="showNodeButton('edit', data)"
49
+ type="text"
50
+ icon="el-icon-edit"
51
+ @click.stop="edit(node)"
52
+ />
53
+ <el-button
54
+ v-if="showNodeButton('remove', data)"
55
+ type="text"
56
+ icon="el-icon-delete"
57
+ @click.stop="remove(node)"
58
+ />
59
+ </span>
60
+ </span>
61
+ </el-tree>
62
+ </div>
63
+ </template>
64
+
65
+ <script>
66
+ import { getNodeByKey, getFirstVaildNode, flatTree } from '@/utils/treeLib'
67
+
68
+ export default {
69
+ name: 'DFilterTree',
70
+ components: {},
71
+ props: {
72
+ data: {
73
+ default: () => [],
74
+ type: Array
75
+ },
76
+ nodeKey: {
77
+ default: 'id',
78
+ type: String
79
+ },
80
+ // 默认选中第一个匹配的节点,如果有指定currentKey,则优先选中该节点
81
+ // eg: { key: 'id', vlaue: true }
82
+ currentDefault: {
83
+ default: null,
84
+ type: Function
85
+ },
86
+ // 选中的节点值
87
+ currentKey: {
88
+ default: '',
89
+ type: [String, Number]
90
+ },
91
+ props: {
92
+ default: () => ({}),
93
+ type: Object
94
+ },
95
+ filterable: {
96
+ default: true,
97
+ type: Boolean
98
+ },
99
+ showButtons: {
100
+ default: false,
101
+ type: Boolean
102
+ },
103
+ placeholder: {
104
+ default: '请输入查询内容',
105
+ type: String
106
+ },
107
+ buttonProps: {
108
+ type: Object,
109
+ default: () => ({
110
+ append: false,
111
+ edit: false,
112
+ remove: false
113
+ })
114
+ },
115
+ searchKey: {
116
+ type: String,
117
+ default: 'search'
118
+ }
119
+ },
120
+ data () {
121
+ return {
122
+ searchContent: '',
123
+ defaultExpandIds: [],
124
+ first: true
125
+ }
126
+ },
127
+ computed: {
128
+ showNodeButton () {
129
+ return (type, data) => {
130
+ if (this.buttonProps[type]) {
131
+ if (typeof this.buttonProps[type] === 'function') {
132
+ return this.buttonProps[type](data)
133
+ } else {
134
+ return true
135
+ }
136
+ } else {
137
+ return false
138
+ }
139
+ }
140
+ }
141
+ },
142
+ watch: {
143
+ data: {
144
+ handler () {
145
+ if (this.data && this.data.length) {
146
+ let node
147
+ if (this.currentKey) {
148
+ node = getNodeByKey(this.data, this.currentKey, { key: this.nodeKey })
149
+ } else if (this.currentDefault) {
150
+ // 获取需要默认选中的节点
151
+ const props = {
152
+ key: this.nodeKey
153
+ }
154
+ this.props.label && (props.label = this.props.label)
155
+ this.props.children && (props.children = this.props.children)
156
+ node = getFirstVaildNode(this.data, this.currentDefault, props)
157
+ }
158
+ this.$nextTick(() => {
159
+ if (node) {
160
+ this.$refs.tree.setCurrentKey(node[this.nodeKey])
161
+ this.$emit('node-change', node)
162
+ this.first && this.handleNodeToggle(node, true)
163
+ }
164
+ this.first = false // 只在第一次有数据时执行默认展开
165
+ })
166
+ }
167
+ },
168
+ immediate: true
169
+ },
170
+ searchContent (val) {
171
+ this.$refs.tree.filter(val)
172
+ }
173
+ },
174
+ created () {},
175
+ methods: {
176
+ // 树的过滤methods
177
+ filterNode (value, data) {
178
+ if (!value) return true
179
+ return (data[this.searchKey] || data[(this.props && this.props.label) || 'label']).indexOf(value) !== -1
180
+ },
181
+ // 树节点触发点击
182
+ nodeClick (node) {
183
+ this.$emit('node-change', node)
184
+ },
185
+ append (node) {
186
+ this.$emit('node-append', node)
187
+ },
188
+ edit (node) {
189
+ this.$emit('node-edit', node)
190
+ },
191
+ remove (node) {
192
+ this.$emit('node-remove', node)
193
+ },
194
+ // 树节点展开/关闭
195
+ handleNodeToggle (data, isExpanded) {
196
+ if (isExpanded) {
197
+ // 展开节点
198
+ if (!this.defaultExpandIds.includes(data[this.nodeKey])) {
199
+ this.defaultExpandIds.push(data[this.nodeKey])
200
+ }
201
+ } else {
202
+ // 关闭节点
203
+ const index = this.defaultExpandIds.indexOf(data[this.nodeKey])
204
+ if (index > -1) {
205
+ this.defaultExpandIds.splice(index, 1)
206
+ }
207
+ }
208
+ this.removeExpandChildIds(data)
209
+ },
210
+ removeExpandChildIds (data) {
211
+ const ids = (flatTree(data.children || [], { key: this.nodeKey }) || []).map(node => node[this.nodeKey])
212
+ this.defaultExpandIds = this.defaultExpandIds.filter(id => !ids.includes(id))
213
+ },
214
+ expandNode (id) {
215
+ const node = getNodeByKey(this.data, id, { key: this.nodeKey })
216
+ if (node) this.handleNodeToggle(node, true)
217
+ },
218
+ // el-tree methods
219
+ updateKeyChildren (...args) {
220
+ this.$refs.tree.updateKeyChildren(...args)
221
+ },
222
+ getCheckedNodes (...args) {
223
+ return this.$refs.tree.getCheckedNodes(...args)
224
+ },
225
+ setCheckedNodes (...args) {
226
+ this.$refs.tree.setCheckedNodes(...args)
227
+ },
228
+ getCheckedKeys (...args) {
229
+ return this.$refs.tree.getCheckedKeys(...args)
230
+ },
231
+ setCheckedKeys (...args) {
232
+ this.$refs.tree.setCheckedKeys(...args)
233
+ },
234
+ setChecked (...args) {
235
+ this.$refs.tree.setChecked(...args)
236
+ },
237
+ getHalfCheckedNodes (...args) {
238
+ return this.$refs.tree.getHalfCheckedNodes(...args)
239
+ },
240
+ getHalfCheckedKeys (...args) {
241
+ return this.$refs.tree.getHalfCheckedKeys(...args)
242
+ },
243
+ getCurrentKey (...args) {
244
+ return this.$refs.tree.getCurrentKey(...args)
245
+ },
246
+ getCurrentNode (...args) {
247
+ return this.$refs.tree.getCurrentNode(...args)
248
+ },
249
+ setCurrentKey (...args) {
250
+ this.$refs.tree.setCurrentKey(...args)
251
+ },
252
+ setCurrentNode (...args) {
253
+ this.$refs.tree.setCurrentNode(...args)
254
+ },
255
+ getNode (...args) {
256
+ return this.$refs.tree.getNode(...args)
257
+ }
258
+ }
259
+ }
260
+ </script>
261
+
262
+ <style lang='scss' scoped>
263
+ .d-filter-tree {
264
+ display: flex;
265
+ flex-direction: column;
266
+ height: 100%;
267
+ font-size: 14px;
268
+ .d-filter-tree-buttons {
269
+ display: flex;
270
+ justify-content: space-between;
271
+ & > div {
272
+ cursor: pointer;
273
+ color: #3786FD;
274
+ }
275
+ }
276
+ .d-filter-tree-node {
277
+ display: flex;
278
+ align-items: center;
279
+ flex: 1;
280
+ overflow: hidden;
281
+ width: 100%;
282
+ .node-label {
283
+ flex: 1;
284
+ overflow: hidden;
285
+ }
286
+ }
287
+ .filter-tree {
288
+ flex: 1;
289
+ overflow: auto;
290
+ }
291
+ }
292
+ </style>
@@ -0,0 +1,149 @@
1
+ <!-- 表单 -->
2
+ <template>
3
+ <el-form
4
+ ref="form"
5
+ v-bind="$attrs"
6
+ :model="source"
7
+ >
8
+ <el-row
9
+ style="display: flex;flex-wrap: wrap;"
10
+ :gutter="16"
11
+ :class="!grid && 'flex'"
12
+ >
13
+ <template v-for="item in config">
14
+ <component
15
+ :is="grid ? 'el-col' : 'div'"
16
+ v-if="!item.hide"
17
+ :key="item.prop"
18
+ :class="item.className"
19
+ :span="item.span || 24"
20
+ >
21
+ <el-form-item
22
+ class="d-form-item"
23
+ :class="{ 'custom-form-item-top': item.direction === 'vertical' || direction === 'vertical' }"
24
+ :label="item.label"
25
+ :prop="item.prop"
26
+ :label-width="(item.direction === 'line' || direction === 'line') ? (item.labelWidth || labelWidth) : '100%'"
27
+ :rules="item.rules || (item.required ? [{ required: true, message: placeholder(item) }] : null)"
28
+ v-bind="item.itemProps"
29
+ >
30
+ <span slot="label">
31
+ <span v-if="!item.labelRender">{{ item.label }}</span>
32
+ <form-label-render v-else :scope="item" :render="item.labelRender" />
33
+ </span>
34
+ <span v-if="item.preText" class="mr8">{{ item.preText }}</span>
35
+ <slot v-if="item.component === 'slot'" :name="item.slotName" />
36
+ <div
37
+ v-else-if="item.component === 'text'"
38
+ :class="item.innerClass"
39
+ :style="item.style"
40
+ >
41
+ {{ item.text || source[item.prop] }}
42
+ </div>
43
+ <template v-else>
44
+ <form-item :ref="item.prop" v-model="source[item.prop]" :config="item" />
45
+ </template>
46
+ <span v-if="item.sufText" class="ml8">{{ item.sufText }}</span>
47
+ </el-form-item>
48
+ </component>
49
+ </template>
50
+ </el-row>
51
+ </el-form>
52
+ </template>
53
+
54
+ <script>
55
+ import FormItem from '../form-item/index'
56
+ import FormLabelRender from '../render'
57
+
58
+ export default {
59
+ name: 'DForm',
60
+ components: {
61
+ FormItem,
62
+ FormLabelRender
63
+ },
64
+ model: {
65
+ prop: 'modelValue',
66
+ event: 'change'
67
+ },
68
+ props: {
69
+ config: {
70
+ type: Array,
71
+ default: () => []
72
+ },
73
+ labelWidth: {
74
+ default: '120px',
75
+ type: String
76
+ },
77
+ modelValue: {
78
+ type: Object,
79
+ default: () => ({})
80
+ },
81
+ grid: {
82
+ type: Boolean,
83
+ default: true
84
+ },
85
+ direction: {
86
+ type: String,
87
+ default: 'vertical'
88
+ }
89
+ },
90
+ data () {
91
+ return {}
92
+ },
93
+ computed: {
94
+ source: {
95
+ get () {
96
+ return this.modelValue
97
+ },
98
+ set (value) {
99
+ this.$emit('change', value)
100
+ }
101
+ },
102
+ placeholder () {
103
+ return ({ component, label }) => {
104
+ // 默认给组件添加placeholder,可自定义
105
+ if (component === 'el-input' || component === 'el-input-number') {
106
+ return `请输入${label}`
107
+ } else {
108
+ return `请选择${label}`
109
+ }
110
+ }
111
+ }
112
+ },
113
+ methods: {
114
+ resetFields () {
115
+ this.$refs.form.resetFields()
116
+ },
117
+ clearValidate () {
118
+ this.$refs.form.clearValidate()
119
+ },
120
+ async validate () {
121
+ const valid = await this.$refs.form.validate()
122
+ return valid
123
+ }
124
+ }
125
+ }
126
+ </script>
127
+
128
+ <style lang="scss" scoped>
129
+ .d-form-item {
130
+ :deep(.el-form-item__content) {
131
+ display: flex;
132
+ .search-item {
133
+ flex: 1;
134
+ overflow: hidden;
135
+ }
136
+ }
137
+ }
138
+ .custom-form-item-top {
139
+ display: flex;
140
+ flex-direction: column;
141
+
142
+ :deep(.el-form-item__label) {
143
+ text-align: left;
144
+ }
145
+ :deep(.el-form-item__content) {
146
+ margin-left: 0 !important;
147
+ }
148
+ }
149
+ </style>
@@ -0,0 +1,199 @@
1
+ <!-- eslint-disable vue/valid-v-for -->
2
+ <template>
3
+ <div class="search-item">
4
+ <div>
5
+ <span
6
+ v-if="config.prefix"
7
+ class="mr6"
8
+ >{{ config.prefix }}</span>
9
+ <el-radio-group
10
+ v-if="config.component === 'el-radio-group'"
11
+ v-model="value"
12
+ :disabled="!!config.disabled"
13
+ v-bind="config.props"
14
+ v-on="config.listeners"
15
+ @change="change"
16
+ >
17
+ <el-radio
18
+ v-for="radio in config.options"
19
+ :key="radio.value"
20
+ :label="radio.value"
21
+ :disabled="!!radio.disabled"
22
+ >
23
+ {{ radio.label }}
24
+ </el-radio>
25
+ </el-radio-group>
26
+ <component
27
+ :is="config.component"
28
+ v-else
29
+ :ref="config.prop"
30
+ v-model.trim="value"
31
+ :style="{
32
+ width: config.width
33
+ }"
34
+ :clearable="clearable(config)"
35
+ :maxlength="config.maxlength || maxlength(config)"
36
+ :disabled="!!config.disabled"
37
+ :placeholder="config.placeholder || placeholder(config)"
38
+ v-bind="config.props"
39
+ v-on="config.listeners"
40
+ @change="change"
41
+ >
42
+ <template
43
+ v-for="s in slots"
44
+ :slot="s.slotName"
45
+ >
46
+ <form-item-render
47
+ :scope="config"
48
+ :render="s.render"
49
+ />
50
+ </template>
51
+ <template v-if="config.component === 'el-checkbox-group'">
52
+ <el-checkbox
53
+ v-for="(checkbox, checkboxIndex) in config.options"
54
+ :key="checkboxIndex"
55
+ :label="checkbox.value"
56
+ >
57
+ {{ checkbox.label }}
58
+ </el-checkbox>
59
+ </template>
60
+
61
+ <template v-if="config.component === 'el-select'">
62
+ <el-option
63
+ v-for="(option, optionIndex) in config.options"
64
+ :key="optionIndex"
65
+ :label="option.label"
66
+ :value="option.value"
67
+ :disabled="!!option.disabled"
68
+ />
69
+ </template>
70
+ <span
71
+ v-if="config.suffix"
72
+ class="ml6"
73
+ >{{ config.suffix }}</span>
74
+ </component>
75
+ </div>
76
+ </div>
77
+ </template>
78
+
79
+ <script>
80
+ import FormItemRender from '../render'
81
+
82
+ export default {
83
+ name: 'DFormItem',
84
+ components: { FormItemRender },
85
+ model: {
86
+ prop: 'modelValue',
87
+ event: 'change'
88
+ },
89
+ props: {
90
+ config: {
91
+ require: true,
92
+ type: Object,
93
+ default: () => {}
94
+ },
95
+ modelValue: {
96
+ type: [Number, String, Boolean, Object, Array],
97
+ default: ''
98
+ }
99
+ },
100
+ data () {
101
+ return {}
102
+ },
103
+ computed: {
104
+ value: {
105
+ get () {
106
+ return this.modelValue
107
+ },
108
+ set (value) {
109
+ this.$emit('change', value)
110
+ }
111
+ },
112
+ slots () {
113
+ return Object.entries(this.config.slots || []).map(([key, value]) => ({
114
+ slotName: key,
115
+ render: value
116
+ }))
117
+ },
118
+ clearable () {
119
+ return (config) => {
120
+ // 优先取配置项clearable
121
+ if (config.clearable !== undefined) {
122
+ return !!config.clearable
123
+ } else {
124
+ return true
125
+ }
126
+ }
127
+ },
128
+ maxlength () {
129
+ return (config) => {
130
+ if (config.component === 'el-input') {
131
+ if (config.props && config.props.type === 'textarea') {
132
+ return 500
133
+ } else {
134
+ return 50
135
+ }
136
+ } else {
137
+ return 99999
138
+ }
139
+ }
140
+ },
141
+ placeholder () {
142
+ return ({ component, label }) => {
143
+ // 默认给组件添加placeholder,可自定义
144
+ if (component === 'el-input' || component === 'el-input-number') {
145
+ return `请输入${label}`
146
+ } else {
147
+ return `请选择${label}`
148
+ }
149
+ }
150
+ }
151
+ },
152
+ methods: {
153
+ /**
154
+ * @description: 普通选择器和级联选择器输出勾选Item节点数据
155
+ * @param {*} value
156
+ * @return {*} data: 输出结构和value数据结构一致,对应value中的节点data
157
+ */
158
+ change (value) {
159
+ if (this.config.onChange) {
160
+ let data = null
161
+
162
+ // 处理级联选择器
163
+ if (this.config.component === 'el-cascader') {
164
+ this.$nextTick(() => {
165
+ // el-cascader搜索勾选bug,需要nextTick后才能正常使用getCheckedNodes
166
+ data = this.$refs[this.config.prop].getCheckedNodes()
167
+ const emitPath = (this.config.props && this.config.props.props && this.config.props.props.emitPath !== undefined) ? this.config.props.props.emitPath : true
168
+ const multiple = this.config.props && this.config.props.props && this.config.props.props.multiple
169
+ if (emitPath) {
170
+ if (multiple) {
171
+ data = value.map(arr => data.find(node => arr[arr.length - 1] === node.value).pathNodes)
172
+ } else {
173
+ data = data[data.length - 1].pathNodes
174
+ }
175
+ } else {
176
+ if (multiple) {
177
+ data = value.map(item => data.find(node => item === node.value))
178
+ } else {
179
+ data = data[data.length - 1]
180
+ }
181
+ }
182
+ this.config.onChange(value, data)
183
+ })
184
+ } else if (this.config.component === 'el-select') { // 处理下拉选择器
185
+ data = this.config.options
186
+ if (Array.isArray(value)) {
187
+ data = data.filter(i => value.includes(i.value)) || []
188
+ } else {
189
+ data = data.find(i => value === i.value) || {}
190
+ }
191
+ this.config.onChange(value, data)
192
+ } else {
193
+ this.config.onChange(value)
194
+ }
195
+ }
196
+ }
197
+ }
198
+ }
199
+ </script>