@ebiz/designer-components 0.0.25 → 0.0.27

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,587 @@
1
+ <template>
2
+ <t-form-item
3
+ :class="['ebiz-s-form-item', className]"
4
+ :for="forAttr"
5
+ :help="help"
6
+ :label="label"
7
+ :name="name"
8
+ :style="customStyle"
9
+ :rules="rules"
10
+ :label-width="labelWidth"
11
+ :label-align="labelAlign"
12
+ :status="status"
13
+ @validate="handleValidate"
14
+ >
15
+ <!-- 输入框 -->
16
+ <template v-if="type === 'input'">
17
+ <t-input
18
+ v-model="computedModelValue"
19
+ :placeholder="placeholder || '请输入'"
20
+ :disabled="disabled"
21
+ :readonly="readonly"
22
+ :clearable="clearable"
23
+ :max-length="maxLength"
24
+ :max-character="maxCharacter"
25
+ :show-limit-number="showLimitNumber"
26
+ @change="handleChange"
27
+ />
28
+ </template>
29
+
30
+ <!-- 数字输入框 -->
31
+ <template v-else-if="type === 'number'">
32
+ <t-input-number
33
+ v-model="computedModelValue"
34
+ :placeholder="placeholder || '请输入'"
35
+ :disabled="disabled"
36
+ :readonly="readonly"
37
+ :max="max"
38
+ :min="min"
39
+ :step="step"
40
+ :format="format"
41
+ @change="handleChange"
42
+ />
43
+ </template>
44
+
45
+ <!-- 文本域 -->
46
+ <template v-else-if="type === 'textarea'">
47
+ <t-textarea
48
+ v-model="computedModelValue"
49
+ :placeholder="placeholder || '请输入'"
50
+ :disabled="disabled"
51
+ :readonly="readonly"
52
+ :autosize="autosize"
53
+ :maxlength="maxLength"
54
+ :max-character="maxCharacter"
55
+ :show-limit-number="showLimitNumber"
56
+ @change="handleChange"
57
+ />
58
+ </template>
59
+
60
+ <!-- 选择器 -->
61
+ <template v-else-if="type === 'select'">
62
+ <t-select
63
+ v-model="computedModelValue"
64
+ :options="options"
65
+ :placeholder="placeholder || '请选择'"
66
+ :disabled="disabled"
67
+ :clearable="clearable"
68
+ :filterable="filterable"
69
+ :multiple="multiple"
70
+ :loading="loading"
71
+ @change="handleChange"
72
+ />
73
+ </template>
74
+
75
+ <!-- 日期选择器 -->
76
+ <template v-else-if="type === 'date'">
77
+ <t-date-picker
78
+ v-model="computedModelValue"
79
+ :placeholder="placeholder || '请选择日期'"
80
+ :disabled="disabled"
81
+ :clearable="clearable"
82
+ :format="dateFormat || 'YYYY-MM-DD'"
83
+ :mode="dateMode || 'date'"
84
+ @change="handleChange"
85
+ />
86
+ </template>
87
+
88
+ <!-- 时间选择器 -->
89
+ <template v-else-if="type === 'time'">
90
+ <t-time-picker
91
+ v-model="computedModelValue"
92
+ :placeholder="placeholder || '请选择时间'"
93
+ :disabled="disabled"
94
+ :clearable="clearable"
95
+ :format="timeFormat || 'HH:mm:ss'"
96
+ @change="handleChange"
97
+ />
98
+ </template>
99
+
100
+ <!-- 单选框组 -->
101
+ <template v-else-if="type === 'radio'">
102
+ <t-radio-group
103
+ v-model="computedModelValue"
104
+ :disabled="disabled"
105
+ :options="options"
106
+ @change="handleChange"
107
+ />
108
+ </template>
109
+
110
+ <!-- 复选框组 -->
111
+ <template v-else-if="type === 'checkbox'">
112
+ <t-checkbox-group
113
+ v-model="computedModelValue"
114
+ :disabled="disabled"
115
+ :options="options"
116
+ :max="max"
117
+ @change="handleChange"
118
+ />
119
+ </template>
120
+
121
+ <!-- 开关 -->
122
+ <template v-else-if="type === 'switch'">
123
+ <t-switch
124
+ v-model="computedModelValue"
125
+ :disabled="disabled"
126
+ @change="handleChange"
127
+ />
128
+ </template>
129
+
130
+ <!-- 滑块 -->
131
+ <template v-else-if="type === 'slider'">
132
+ <t-slider
133
+ v-model="computedModelValue"
134
+ :disabled="disabled"
135
+ :max="max"
136
+ :min="min"
137
+ :step="step"
138
+ :range="range"
139
+ :marks="marks"
140
+ @change="handleChange"
141
+ />
142
+ </template>
143
+
144
+ <!-- 上传 -->
145
+ <template v-else-if="type === 'upload'">
146
+ <t-upload
147
+ v-model="computedModelValue"
148
+ :disabled="disabled"
149
+ :accept="accept"
150
+ :multiple="multiple"
151
+ :max="max"
152
+ :action="action"
153
+ :headers="headers"
154
+ :with-credentials="withCredentials"
155
+ :before-upload="beforeUpload"
156
+ :format-response="formatResponse"
157
+ :theme="uploadTheme || 'file'"
158
+ @change="handleChange"
159
+ />
160
+ </template>
161
+
162
+ <!-- 级联选择器 -->
163
+ <template v-else-if="type === 'cascader'">
164
+ <t-cascader
165
+ v-model="computedModelValue"
166
+ :disabled="disabled"
167
+ :options="options"
168
+ :placeholder="placeholder || '请选择'"
169
+ :clearable="clearable"
170
+ :filterable="filterable"
171
+ :multiple="multiple"
172
+ @change="handleChange"
173
+ />
174
+ </template>
175
+
176
+ <!-- 树形选择器 -->
177
+ <template v-else-if="type === 'tree-select'">
178
+ <t-tree-select
179
+ v-model="computedModelValue"
180
+ :disabled="disabled"
181
+ :data="treeData || options"
182
+ :placeholder="placeholder || '请选择'"
183
+ :clearable="clearable"
184
+ :filterable="filterable"
185
+ :multiple="multiple"
186
+ @change="handleChange"
187
+ />
188
+ </template>
189
+
190
+ <!-- 颜色选择器 -->
191
+ <template v-else-if="type === 'color-picker'">
192
+ <t-color-picker
193
+ v-model="computedModelValue"
194
+ :disabled="disabled"
195
+ :clearable="clearable"
196
+ @change="handleChange"
197
+ />
198
+ </template>
199
+
200
+ <!-- 默认插槽,用于自定义控件 -->
201
+ <template v-else>
202
+ <slot>
203
+ <div class="custom-control">
204
+ <slot name="default"></slot>
205
+ </div>
206
+ </slot>
207
+ </template>
208
+ </t-form-item>
209
+ </template>
210
+
211
+ <script>
212
+ /**
213
+ * @displayName PC端表单项
214
+ * @description PC端表单项组件,基于TDesign FormItem封装,支持多种控件类型
215
+ * @category 表单组件
216
+ * @name EbizSFormItem
217
+ */
218
+ export default {
219
+ name: "EbizSFormItem"
220
+ }
221
+ </script>
222
+
223
+ <script setup>
224
+ import { defineProps, defineEmits, computed } from 'vue';
225
+ import {
226
+ FormItem as TFormItem,
227
+ Input as TInput,
228
+ InputNumber as TInputNumber,
229
+ Textarea as TTextarea,
230
+ Select as TSelect,
231
+ DatePicker as TDatePicker,
232
+ TimePicker as TTimePicker,
233
+ RadioGroup as TRadioGroup,
234
+ CheckboxGroup as TCheckboxGroup,
235
+ Switch as TSwitch,
236
+ Slider as TSlider,
237
+ Upload as TUpload,
238
+ Cascader as TCascader,
239
+ TreeSelect as TTreeSelect,
240
+ ColorPicker as TColorPicker
241
+ } from 'tdesign-vue-next';
242
+
243
+ const props = defineProps({
244
+ /**
245
+ * 组件类型
246
+ * @options input|number|textarea|select|date|time|radio|checkbox|switch|slider|upload|cascader|tree-select|color-picker
247
+ */
248
+ type: {
249
+ type: String,
250
+ default: 'input',
251
+ validator: (val) => [
252
+ 'input', 'number', 'textarea', 'select', 'date', 'time', 'radio',
253
+ 'checkbox', 'switch', 'slider', 'upload', 'cascader', 'tree-select',
254
+ 'color-picker'
255
+ ].includes(val)
256
+ },
257
+ /**
258
+ * 绑定的值
259
+ */
260
+ modelValue: {
261
+ type: [String, Number, Boolean, Array, Object],
262
+ default: undefined
263
+ },
264
+ /**
265
+ * 表单项标签
266
+ */
267
+ label: {
268
+ type: String,
269
+ default: ''
270
+ },
271
+ /**
272
+ * 表单项字段名,唯一标识
273
+ */
274
+ name: {
275
+ type: String,
276
+ default: ''
277
+ },
278
+ /**
279
+ * html元素原生属性for
280
+ */
281
+ forAttr: {
282
+ type: String,
283
+ default: undefined
284
+ },
285
+ /**
286
+ * 表单项帮助文本
287
+ */
288
+ help: {
289
+ type: [String, Function],
290
+ default: ''
291
+ },
292
+ /**
293
+ * 是否禁用
294
+ */
295
+ disabled: {
296
+ type: Boolean,
297
+ default: false
298
+ },
299
+ /**
300
+ * 是否只读
301
+ */
302
+ readonly: {
303
+ type: Boolean,
304
+ default: false
305
+ },
306
+ /**
307
+ * 表单项规则
308
+ */
309
+ rules: {
310
+ type: [Array, Object],
311
+ default: undefined
312
+ },
313
+ /**
314
+ * 自定义样式
315
+ */
316
+ customStyle: {
317
+ type: [String, Object],
318
+ default: ''
319
+ },
320
+ /**
321
+ * 自定义类名
322
+ */
323
+ className: {
324
+ type: String,
325
+ default: ''
326
+ },
327
+ /**
328
+ * 表单项标签宽度
329
+ */
330
+ labelWidth: {
331
+ type: [String, Number],
332
+ default: undefined
333
+ },
334
+ /**
335
+ * 表单项标签对齐方式
336
+ * @options left|right|top
337
+ */
338
+ labelAlign: {
339
+ type: String,
340
+ default: undefined,
341
+ validator: (val) => ['left', 'right', 'top'].includes(val)
342
+ },
343
+ /**
344
+ * 表单项状态
345
+ * @options default|success|warning|error
346
+ */
347
+ status: {
348
+ type: String,
349
+ default: undefined,
350
+ validator: (val) => ['default', 'success', 'warning', 'error'].includes(val)
351
+ },
352
+ /**
353
+ * 占位文本
354
+ */
355
+ placeholder: {
356
+ type: String,
357
+ default: ''
358
+ },
359
+ /**
360
+ * 是否可清空
361
+ */
362
+ clearable: {
363
+ type: Boolean,
364
+ default: true
365
+ },
366
+ /**
367
+ * 最大长度
368
+ */
369
+ maxLength: {
370
+ type: Number,
371
+ default: undefined
372
+ },
373
+ /**
374
+ * 最大字符数
375
+ */
376
+ maxCharacter: {
377
+ type: Number,
378
+ default: undefined
379
+ },
380
+ /**
381
+ * 是否显示字数限制
382
+ */
383
+ showLimitNumber: {
384
+ type: Boolean,
385
+ default: false
386
+ },
387
+ /**
388
+ * 选项数据,用于select, radio, checkbox等
389
+ */
390
+ options: {
391
+ type: Array,
392
+ default: () => []
393
+ },
394
+ /**
395
+ * 树形数据,用于tree-select
396
+ */
397
+ treeData: {
398
+ type: Array,
399
+ default: undefined
400
+ },
401
+ /**
402
+ * 是否支持过滤
403
+ */
404
+ filterable: {
405
+ type: Boolean,
406
+ default: false
407
+ },
408
+ /**
409
+ * 是否支持多选
410
+ */
411
+ multiple: {
412
+ type: Boolean,
413
+ default: false
414
+ },
415
+ /**
416
+ * 加载状态
417
+ */
418
+ loading: {
419
+ type: Boolean,
420
+ default: false
421
+ },
422
+ /**
423
+ * 日期格式
424
+ */
425
+ dateFormat: {
426
+ type: String,
427
+ default: 'YYYY-MM-DD'
428
+ },
429
+ /**
430
+ * 日期选择器模式
431
+ * @options date|week|month|quarter|year
432
+ */
433
+ dateMode: {
434
+ type: String,
435
+ default: 'date',
436
+ validator: (val) => ['date', 'week', 'month', 'quarter', 'year'].includes(val)
437
+ },
438
+ /**
439
+ * 时间格式
440
+ */
441
+ timeFormat: {
442
+ type: String,
443
+ default: 'HH:mm:ss'
444
+ },
445
+ /**
446
+ * 最大值
447
+ */
448
+ max: {
449
+ type: Number,
450
+ default: undefined
451
+ },
452
+ /**
453
+ * 最小值
454
+ */
455
+ min: {
456
+ type: Number,
457
+ default: undefined
458
+ },
459
+ /**
460
+ * 步长
461
+ */
462
+ step: {
463
+ type: Number,
464
+ default: 1
465
+ },
466
+ /**
467
+ * 格式化函数
468
+ */
469
+ format: {
470
+ type: Function,
471
+ default: undefined
472
+ },
473
+ /**
474
+ * 文本域自适应高度
475
+ */
476
+ autosize: {
477
+ type: [Boolean, Object],
478
+ default: false
479
+ },
480
+ /**
481
+ * 滑块是否为范围选择
482
+ */
483
+ range: {
484
+ type: Boolean,
485
+ default: false
486
+ },
487
+ /**
488
+ * 滑块刻度标记
489
+ */
490
+ marks: {
491
+ type: Object,
492
+ default: () => ({})
493
+ },
494
+ /**
495
+ * 上传接受的文件类型
496
+ */
497
+ accept: {
498
+ type: String,
499
+ default: ''
500
+ },
501
+ /**
502
+ * 上传接口地址
503
+ */
504
+ action: {
505
+ type: String,
506
+ default: ''
507
+ },
508
+ /**
509
+ * 上传请求头
510
+ */
511
+ headers: {
512
+ type: Object,
513
+ default: () => ({})
514
+ },
515
+ /**
516
+ * 上传是否携带cookie
517
+ */
518
+ withCredentials: {
519
+ type: Boolean,
520
+ default: false
521
+ },
522
+ /**
523
+ * 上传前的钩子函数
524
+ */
525
+ beforeUpload: {
526
+ type: Function,
527
+ default: undefined
528
+ },
529
+ /**
530
+ * 上传响应格式化函数
531
+ */
532
+ formatResponse: {
533
+ type: Function,
534
+ default: undefined
535
+ },
536
+ /**
537
+ * 上传组件主题
538
+ * @options file|image|image-flow
539
+ */
540
+ uploadTheme: {
541
+ type: String,
542
+ default: 'file',
543
+ validator: (val) => ['file', 'image', 'image-flow'].includes(val)
544
+ }
545
+ });
546
+
547
+ const emit = defineEmits([
548
+ 'update:modelValue',
549
+ 'change',
550
+ 'validate'
551
+ ]);
552
+
553
+ // 计算属性处理v-model双向绑定
554
+ const computedModelValue = computed({
555
+ get: () => props.modelValue,
556
+ set: (val) => {
557
+ emit('update:modelValue', val);
558
+ }
559
+ });
560
+
561
+ /**
562
+ * 值变更事件
563
+ * @param {*} val 新值
564
+ */
565
+ const handleChange = (val) => {
566
+ emit('change', val);
567
+ };
568
+
569
+ /**
570
+ * 验证事件
571
+ * @param {Object} validateResult 验证结果
572
+ */
573
+ const handleValidate = (validateResult) => {
574
+ emit('validate', validateResult);
575
+ };
576
+ </script>
577
+
578
+ <style scoped>
579
+ .ebiz-s-form-item {
580
+ width: 100%;
581
+ margin-bottom: 24px;
582
+ }
583
+
584
+ .custom-control {
585
+ width: 100%;
586
+ }
587
+ </style>