@longhongguo/form-create-ant-design-vue 3.2.44 → 3.2.45

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.
@@ -0,0 +1,336 @@
1
+ <template>
2
+ <!-- 单个展示模式 -->
3
+ <div
4
+ v-if="!multiple"
5
+ class="fc-cus-select fc-cus-select-single"
6
+ :class="{
7
+ 'fc-cus-select-disabled': disabled
8
+ }"
9
+ :style="style"
10
+ :tabindex="disabled ? -1 : 0"
11
+ >
12
+ <div class="fc-cus-select-selector">
13
+ <span
14
+ v-if="displayValue"
15
+ class="fc-cus-select-selection-item"
16
+ :title="displayLabel"
17
+ >
18
+ {{ displayLabel }}
19
+ </span>
20
+ <span v-else class="fc-cus-select-selection-placeholder">
21
+ {{ placeholder || '请选择' }}
22
+ </span>
23
+ <span v-if="showClear" class="fc-cus-select-clear" @click="clearValue">
24
+ <span
25
+ role="img"
26
+ aria-label="close-circle"
27
+ class="anticon anticon-close-circle"
28
+ >
29
+ <svg
30
+ focusable="false"
31
+ data-icon="close-circle"
32
+ width="1em"
33
+ height="1em"
34
+ fill="currentColor"
35
+ aria-hidden="true"
36
+ fill-rule="evenodd"
37
+ viewBox="64 64 896 896"
38
+ >
39
+ <path
40
+ d="M512 64c247.4 0 448 200.6 448 448S759.4 960 512 960 64 759.4 64 512 264.6 64 512 64zm127.98 274.82h-.04l-.08.06L512 466.75 384.14 338.88c-.04-.05-.06-.06-.08-.06a.12.12 0 00-.07 0c-.03 0-.05.01-.09.05l-45.02 45.02a.2.2 0 00-.05.09.12.12 0 000 .07v.02a.27.27 0 00.06.06L466.75 512 338.88 639.86c-.05.04-.06.06-.06.08a.12.12 0 000 .07c0 .03.01.05.05.09l45.02 45.02a.2.2 0 00.09.05.12.12 0 00.07 0c.02 0 .04-.01.08-.05L512 557.25l127.86 127.87c.04.04.06.05.08.05a.12.12 0 00.07 0c.03 0 .05-.01.09-.05l45.02-45.02a.2.2 0 00.05-.09.12.12 0 000-.07v-.02a.27.27 0 00-.05-.06L557.25 512l127.87-127.86c.04-.04.05-.06.05-.08a.12.12 0 000-.07c0-.03-.01-.05-.05-.09l-45.02-45.02a.2.2 0 00-.09-.05.12.12 0 00-.07 0z"
41
+ ></path>
42
+ </svg>
43
+ </span>
44
+ </span>
45
+ <span v-else class="fc-cus-select-arrow">
46
+ <span role="img" aria-label="down" class="anticon anticon-down">
47
+ <svg
48
+ focusable="false"
49
+ data-icon="down"
50
+ width="1em"
51
+ height="1em"
52
+ fill="currentColor"
53
+ aria-hidden="true"
54
+ viewBox="64 64 896 896"
55
+ >
56
+ <path
57
+ d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
58
+ ></path>
59
+ </svg>
60
+ </span>
61
+ </span>
62
+ </div>
63
+ </div>
64
+
65
+ <!-- 多个展示模式 -->
66
+ <div
67
+ v-else
68
+ class="fc-cus-select fc-cus-select-multiple"
69
+ :class="{
70
+ 'fc-cus-select-disabled': disabled
71
+ }"
72
+ :style="style"
73
+ :tabindex="disabled ? -1 : 0"
74
+ >
75
+ <div class="fc-cus-select-selector">
76
+ <div class="fc-cus-select-selection-overflow">
77
+ <!-- 显示的 tags -->
78
+ <div
79
+ v-for="(item, index) in displayItems"
80
+ :key="index"
81
+ class="fc-cus-select-selection-overflow-item"
82
+ style="opacity: 1"
83
+ >
84
+ <span class="fc-cus-select-selection-item" :title="item.label">
85
+ <span class="fc-cus-select-selection-item-content">{{
86
+ item.label
87
+ }}</span>
88
+ <span
89
+ class="fc-cus-select-selection-item-remove"
90
+ @click="removeItem(item.value, $event)"
91
+ >
92
+ <span role="img" aria-label="close" class="anticon anticon-close">
93
+ <svg
94
+ focusable="false"
95
+ data-icon="close"
96
+ width="1em"
97
+ height="1em"
98
+ fill="currentColor"
99
+ aria-hidden="true"
100
+ fill-rule="evenodd"
101
+ viewBox="64 64 896 896"
102
+ >
103
+ <path
104
+ d="M799.86 166.31c.02 0 .04.02.08.06l57.69 57.7c.04.03.05.05.06.08a.12.12 0 010 .06c0 .03-.02.05-.06.09L569.93 512l287.7 287.7c.04.04.05.06.06.09a.12.12 0 010 .07c0 .02-.02.04-.06.08l-57.7 57.69c-.03.04-.05.05-.07.06a.12.12 0 01-.07 0c-.03 0-.05-.02-.09-.06L512 569.93l-287.7 287.7c-.04.04-.06.05-.09.06a.12.12 0 01-.07 0c-.02 0-.04-.02-.08-.06l-57.69-57.7c-.04-.03-.05-.05-.06-.07a.12.12 0 010-.07c0-.03.02-.05.06-.09L454.07 512l-287.7-287.7c-.04-.04-.05-.06-.06-.09a.12.12 0 010-.07c0-.02.02-.04.06-.08l57.7-57.69c.03-.04.05-.05.07-.06a.12.12 0 01.07 0c.03 0 .05.02.09.06L512 454.07l287.7-287.7c.04-.04.06-.05.09-.06a.12.12 0 01.07 0z"
105
+ ></path>
106
+ </svg>
107
+ </span>
108
+ </span>
109
+ </span>
110
+ </div>
111
+
112
+ <!-- 折叠提示 -->
113
+ <div
114
+ v-if="remainingCount > 0"
115
+ class="fc-cus-select-selection-overflow-item"
116
+ style="opacity: 1"
117
+ >
118
+ <span class="fc-cus-select-selection-item">
119
+ <span class="fc-cus-select-selection-item-content">
120
+ +{{ remainingCount }}
121
+ </span>
122
+ </span>
123
+ </div>
124
+
125
+ <!-- 空值占位符 -->
126
+ <span v-if="!hasValue" class="fc-cus-select-selection-placeholder">
127
+ {{ placeholder || '请选择' }}
128
+ </span>
129
+ </div>
130
+ <span v-if="showClear" class="fc-cus-select-clear" @click="clearValue">
131
+ <span
132
+ role="img"
133
+ aria-label="close-circle"
134
+ class="anticon anticon-close-circle"
135
+ >
136
+ <svg
137
+ focusable="false"
138
+ data-icon="close-circle"
139
+ width="1em"
140
+ height="1em"
141
+ fill="currentColor"
142
+ aria-hidden="true"
143
+ fill-rule="evenodd"
144
+ viewBox="64 64 896 896"
145
+ >
146
+ <path
147
+ d="M512 64c247.4 0 448 200.6 448 448S759.4 960 512 960 64 759.4 64 512 264.6 64 512 64zm127.98 274.82h-.04l-.08.06L512 466.75 384.14 338.88c-.04-.05-.06-.06-.08-.06a.12.12 0 00-.07 0c-.03 0-.05.01-.09.05l-45.02 45.02a.2.2 0 00-.05.09.12.12 0 000 .07v.02a.27.27 0 00.06.06L466.75 512 338.88 639.86c-.05.04-.06.06-.06.08a.12.12 0 000 .07c0 .03.01.05.05.09l45.02 45.02a.2.2 0 00.09.05.12.12 0 00.07 0c.02 0 .04-.01.08-.05L512 557.25l127.86 127.87c.04.04.06.05.08.05a.12.12 0 00.07 0c.03 0 .05-.01.09-.05l45.02-45.02a.2.2 0 00.05-.09.12.12 0 000-.07v-.02a.27.27 0 00-.05-.06L557.25 512l127.87-127.86c.04-.04.05-.06.05-.08a.12.12 0 000-.07c0-.03-.01-.05-.05-.09l-45.02-45.02a.2.2 0 00-.09-.05.12.12 0 00-.07 0z"
148
+ ></path>
149
+ </svg>
150
+ </span>
151
+ </span>
152
+ <span v-else class="fc-cus-select-arrow">
153
+ <span role="img" aria-label="down" class="anticon anticon-down">
154
+ <svg
155
+ focusable="false"
156
+ data-icon="down"
157
+ width="1em"
158
+ height="1em"
159
+ fill="currentColor"
160
+ aria-hidden="true"
161
+ viewBox="64 64 896 896"
162
+ >
163
+ <path
164
+ d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
165
+ ></path>
166
+ </svg>
167
+ </span>
168
+ </span>
169
+ </div>
170
+ </div>
171
+ </template>
172
+
173
+ <script>
174
+ import { defineComponent } from 'vue'
175
+
176
+ export default defineComponent({
177
+ name: 'CusSelect',
178
+ props: {
179
+ // 当前值:单个时为字符串/数字,多个时为数组(支持 v-model)
180
+ modelValue: {
181
+ type: [String, Number, Array],
182
+ default: null
183
+ },
184
+ // 选项列表
185
+ options: {
186
+ type: Array,
187
+ default: () => []
188
+ },
189
+ // 是否多选
190
+ multiple: {
191
+ type: Boolean,
192
+ default: false
193
+ },
194
+ // 最多显示的 tag 数量(多选模式下有效)
195
+ maxTagCount: {
196
+ type: Number,
197
+ default: undefined // 不限制时显示所有
198
+ },
199
+ // 占位符
200
+ placeholder: {
201
+ type: String,
202
+ default: ''
203
+ },
204
+ // 是否禁用样式
205
+ disabled: {
206
+ type: Boolean,
207
+ default: false
208
+ },
209
+ // 自定义样式
210
+ style: {
211
+ type: [String, Object],
212
+ default: () => ({ width: '100%' })
213
+ },
214
+ // 选项的 value 字段名
215
+ valueKey: {
216
+ type: String,
217
+ default: 'value'
218
+ },
219
+ // 选项的 label 字段名
220
+ labelKey: {
221
+ type: String,
222
+ default: 'label'
223
+ },
224
+ // 是否允许清除
225
+ allowClear: {
226
+ type: Boolean,
227
+ default: false
228
+ }
229
+ },
230
+ emits: ['update:modelValue', 'change'],
231
+ computed: {
232
+ // 统一处理值(支持 v-model)
233
+ currentValue: {
234
+ get() {
235
+ return this.modelValue
236
+ },
237
+ set(val) {
238
+ // 触发 update:modelValue 事件以支持 v-model
239
+ this.$emit('update:modelValue', val)
240
+ this.$emit('change', val)
241
+ }
242
+ },
243
+ // 是否有值
244
+ hasValue() {
245
+ const val = this.currentValue
246
+ if (this.multiple) {
247
+ return Array.isArray(val) && val.length > 0
248
+ } else {
249
+ return val !== null && val !== undefined && val !== ''
250
+ }
251
+ },
252
+ // 单个模式:显示的值
253
+ displayValue() {
254
+ if (!this.hasValue) return null
255
+ return this.currentValue
256
+ },
257
+ // 单个模式:显示的标签
258
+ displayLabel() {
259
+ if (!this.displayValue) return ''
260
+ return this.getLabel(this.displayValue)
261
+ },
262
+ // 多个模式:所有选中的项(包含 label 的对象数组)
263
+ allSelectedItems() {
264
+ const val = this.currentValue
265
+ if (!this.multiple || !Array.isArray(val) || val.length === 0) {
266
+ return []
267
+ }
268
+ return val.map((v) => ({
269
+ value: v,
270
+ label: this.getLabel(v)
271
+ }))
272
+ },
273
+ // 多个模式:显示的项(根据 maxTagCount 限制)
274
+ displayItems() {
275
+ const items = this.allSelectedItems
276
+ if (this.maxTagCount === undefined || this.maxTagCount === null) {
277
+ return items
278
+ }
279
+ return items.slice(0, this.maxTagCount)
280
+ },
281
+ // 多个模式:剩余未显示的项数量
282
+ remainingCount() {
283
+ if (this.maxTagCount === undefined || this.maxTagCount === null) {
284
+ return 0
285
+ }
286
+ const total = this.allSelectedItems.length
287
+ return Math.max(0, total - this.maxTagCount)
288
+ },
289
+ // 是否显示清除图标
290
+ showClear() {
291
+ return this.allowClear && this.hasValue && !this.disabled
292
+ }
293
+ },
294
+ methods: {
295
+ // 根据 value 查找对应的 option
296
+ findOptionByValue(val) {
297
+ if (!this.options || this.options.length === 0) {
298
+ return null
299
+ }
300
+ return this.options.find((opt) => {
301
+ const optValue = typeof opt === 'object' ? opt[this.valueKey] : opt
302
+ return optValue === val || String(optValue) === String(val)
303
+ })
304
+ },
305
+ // 获取显示的 label
306
+ getLabel(val) {
307
+ const option = this.findOptionByValue(val)
308
+ if (option) {
309
+ return typeof option === 'object' ? option[this.labelKey] : option
310
+ }
311
+ // 如果找不到对应的 option,直接显示 value
312
+ return String(val)
313
+ },
314
+ // 删除单个项(多选模式)
315
+ removeItem(itemValue, event) {
316
+ if (this.disabled) return
317
+ event.stopPropagation()
318
+ const val = this.currentValue
319
+ if (this.multiple && Array.isArray(val)) {
320
+ const newValue = val.filter((v) => v !== itemValue)
321
+ this.currentValue = newValue
322
+ }
323
+ },
324
+ // 清除所有值
325
+ clearValue(event) {
326
+ if (this.disabled) return
327
+ event.stopPropagation()
328
+ if (this.multiple) {
329
+ this.currentValue = []
330
+ } else {
331
+ this.currentValue = null
332
+ }
333
+ }
334
+ }
335
+ })
336
+ </script>
@@ -0,0 +1,91 @@
1
+ <template>
2
+ <div>
3
+ <CusSelect
4
+ :model-value="modelValue"
5
+ :options="options"
6
+ :multiple="multiple"
7
+ :max-tag-count="maxTagCount"
8
+ :placeholder="placeholder"
9
+ :disabled="disabled"
10
+ :style="style"
11
+ :valueKey="valueKey"
12
+ :labelKey="labelKey"
13
+ :allowClear="allowClear"
14
+ @update:model-value="handleUpdate"
15
+ @change="handleChange"
16
+ />
17
+ </div>
18
+ </template>
19
+
20
+ <script>
21
+ import { defineComponent } from 'vue'
22
+ import CusSelect from '../CusSelect/index.vue'
23
+
24
+ export default defineComponent({
25
+ name: 'CusStoreSelect',
26
+ components: {
27
+ CusSelect
28
+ },
29
+ props: {
30
+ // 当前值:单个时为字符串/数字,多个时为数组(支持 v-model)
31
+ modelValue: {
32
+ type: [String, Number, Array],
33
+ default: null
34
+ },
35
+ // 选项列表
36
+ options: {
37
+ type: Array,
38
+ default: () => []
39
+ },
40
+ // 是否多选
41
+ multiple: {
42
+ type: Boolean,
43
+ default: false
44
+ },
45
+ // 最多显示的 tag 数量(多选模式下有效)
46
+ maxTagCount: {
47
+ type: Number,
48
+ default: undefined // 不限制时显示所有
49
+ },
50
+ // 占位符
51
+ placeholder: {
52
+ type: String,
53
+ default: '请选择'
54
+ },
55
+ // 是否禁用样式
56
+ disabled: {
57
+ type: Boolean,
58
+ default: false
59
+ },
60
+ // 自定义样式
61
+ style: {
62
+ type: [String, Object],
63
+ default: () => ({ width: '100%' })
64
+ },
65
+ // 选项的 value 字段名
66
+ valueKey: {
67
+ type: String,
68
+ default: 'value'
69
+ },
70
+ // 选项的 label 字段名
71
+ labelKey: {
72
+ type: String,
73
+ default: 'label'
74
+ },
75
+ // 是否允许清除
76
+ allowClear: {
77
+ type: Boolean,
78
+ default: false
79
+ }
80
+ },
81
+ emits: ['update:modelValue', 'change'],
82
+ methods: {
83
+ handleUpdate(value) {
84
+ this.$emit('update:modelValue', value)
85
+ },
86
+ handleChange(value) {
87
+ this.$emit('change', value)
88
+ }
89
+ }
90
+ })
91
+ </script>
@@ -3,5 +3,15 @@ import frame from '@form-create/component-antdv-frame/src/index'
3
3
  import group from '@form-create/component-antdv-group/src/index'
4
4
  import subForm from '@form-create/component-subform/src/index'
5
5
  import QuestionCircleOutlined from './icon/QuestionCircleOutlined.vue'
6
+ import CusSelect from './CusSelect/index.vue'
7
+ import CusStoreSelect from './CusStoreSelect/index.vue'
6
8
 
7
- export default [upload, frame, group, subForm, QuestionCircleOutlined]
9
+ export default [
10
+ upload,
11
+ frame,
12
+ group,
13
+ subForm,
14
+ QuestionCircleOutlined,
15
+ CusSelect,
16
+ CusStoreSelect
17
+ ]
package/src/core/maker.js CHANGED
@@ -84,10 +84,16 @@ function useUpload(maker) {
84
84
  maker.uploadFile = maker.file
85
85
  }
86
86
 
87
+ function useCusStoreSelect(maker) {
88
+ maker.cusStoreSelect = creatorFactory('cusStoreSelect')
89
+ maker.storeSelect = maker.cusStoreSelect
90
+ }
91
+
87
92
  useAlias(maker)
88
93
  useSlider(maker)
89
94
  useFrame(maker)
90
95
  useUpload(maker)
91
96
  useSelect(maker)
97
+ useCusStoreSelect(maker)
92
98
 
93
99
  export default maker
@@ -1,11 +1,12 @@
1
1
  export default {
2
- autoComplete: 'value',
3
- cascader: 'value',
4
- inputNumber: 'value',
5
- inputPassword: 'value',
6
- textarea: 'value',
7
- rate: 'value',
8
- slider: 'value',
9
- treeSelect: 'value',
10
- switch: 'checked',
2
+ autoComplete: 'value',
3
+ cascader: 'value',
4
+ inputNumber: 'value',
5
+ inputPassword: 'value',
6
+ textarea: 'value',
7
+ rate: 'value',
8
+ slider: 'value',
9
+ treeSelect: 'value',
10
+ switch: 'checked',
11
+ cusStoreSelect: 'modelValue'
11
12
  }
@@ -0,0 +1,17 @@
1
+ import { hasProperty } from '@form-create/utils/lib/type'
2
+
3
+ export default {
4
+ name: 'cusStoreSelect',
5
+ modelField: 'modelValue',
6
+ mergeProp(ctx) {
7
+ const props = ctx.prop.props
8
+ // 确保 options 存在
9
+ if (!hasProperty(props, 'options')) {
10
+ props.options = ctx.prop.options || []
11
+ }
12
+ },
13
+ render(children, ctx) {
14
+ // 使用默认渲染
15
+ return ctx.$render.defaultRender(ctx, children)
16
+ }
17
+ }
@@ -10,6 +10,7 @@ import tree from './tree'
10
10
  import row from './row'
11
11
  import rangePicker from './rangePicker'
12
12
  import timeRangePicker from './timeRangePicker'
13
+ import cusStoreSelect from './cusStoreSelect'
13
14
 
14
15
  export default [
15
16
  checkbox,
@@ -23,5 +24,6 @@ export default [
23
24
  radio,
24
25
  select,
25
26
  cascader,
26
- row
27
+ row,
28
+ cusStoreSelect
27
29
  ]