@ddwl/ddwl-ui 1.2.3-beta.1 → 1.2.3-beta.3

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