hy-app 0.2.18 → 0.3.1

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,5 @@
1
+ import HyFormSimple from './hy-form-simple.vue'
2
+ import HyFormItemSimple from './hy-form-item-simple.vue'
3
+
4
+ export { HyFormSimple, HyFormItemSimple }
5
+ export default HyFormSimple
@@ -1,77 +1,61 @@
1
- import type { FormColumnsType } from "../../typing";
2
- import type HyInputProps from "../hy-input/typing";
3
- import type HyTextareaProps from "../hy-textarea/typing";
4
- import type HySwitchProps from "../hy-switch/typing";
5
- import type HyPickerProps from "../hy-picker/typing";
6
- import type HyRadioProps from "../hy-radio/typing";
7
- import type HyCheckButtonProps from "../hy-check-button/typing";
8
-
9
- export default interface HyFormProps {
10
- /**
11
- * @description 表单域提示文字的位置
12
- * left - 左侧
13
- * top - 上方
14
- * */
15
- labelPosition?: "left" | "top";
16
- /**
17
- * @description label宽度
18
- * 数字 - 固定值
19
- * auto - 自适应
20
- * */
21
- labelWidth?: string | number;
22
- /**
23
- * @description 是否右对齐
24
- * */
25
- right?: boolean;
26
- /**
27
- * @description label字体的对齐方式
28
- * left - 左对齐
29
- * center - 中间对齐
30
- * right - 右对齐
31
- * */
32
- labelAlign?: HyApp.RowCenterType;
33
- /**
34
- * @description 显示冒号符号
35
- * */
36
- symbol?: boolean;
37
- /**
38
- * @description 显示底部下划线
39
- * */
40
- borderBottom?: boolean;
41
- /**
42
- * @description 当行内容高度
43
- * */
44
- itemHeight?: number | string;
45
- /**
46
- * @description 输入框属性api集合
47
- * */
48
- input?: Partial<HyInputProps>;
49
- /**
50
- * @description 文本域属性api集合
51
- * */
52
- textarea?: Partial<HyTextareaProps>;
53
- /**
54
- * @description 选择器属性api集合
55
- * */
56
- picker?: Partial<HyPickerProps>;
57
- /**
58
- * @description 开关属性api集合
59
- * */
60
- switchItem?: Partial<HySwitchProps>;
61
- /**
62
- * @description 单选属性api集合
63
- * */
64
- radio?: Partial<HyRadioProps>;
65
- /**
66
- * @description 选择按钮属性api集合
67
- * */
68
- checkButton?: Partial<HyCheckButtonProps>;
69
- /**
70
- * @description 表单配置
71
- * */
72
- columns: FormColumnsType[];
73
- /**
74
- * @description 表单值
75
- * */
76
- formData: Record<string, any>;
77
- }
1
+ export interface FormRule {
2
+ /**
3
+ * 是否必填
4
+ */
5
+ required?: boolean
6
+ /**
7
+ * 验证失败时的提示信息
8
+ */
9
+ message?: string
10
+ /**
11
+ * 自定义验证函数
12
+ */
13
+ validator?: (value: any) => boolean | string
14
+ /**
15
+ * 触发验证的时机
16
+ */
17
+ trigger?: ('blur' | 'change')[]
18
+ /**
19
+ * 最小长度
20
+ */
21
+ min?: number
22
+ /**
23
+ * 最大长度
24
+ */
25
+ max?: number
26
+ /**
27
+ * 验证类型
28
+ */
29
+ type?: 'phone' | 'email' | 'password'
30
+ }
31
+
32
+ export interface FormItemRule {
33
+ [key: string]: FormRule | FormRule[]
34
+ }
35
+
36
+ export default interface HyFormSimpleProps {
37
+ /**
38
+ * 表单数据对象
39
+ */
40
+ model?: Record<string, any>
41
+ /**
42
+ * 验证规则
43
+ */
44
+ rules?: FormItemRule
45
+ /**
46
+ * 标签宽度
47
+ */
48
+ labelWidth?: string | number
49
+ /**
50
+ * 标签位置
51
+ */
52
+ labelPosition?: 'left' | 'top'
53
+ /**
54
+ * 标签对齐方式
55
+ */
56
+ labelAlign?: 'left' | 'center' | 'right'
57
+ /**
58
+ * 表单列底部边框
59
+ * */
60
+ border: boolean
61
+ }
@@ -0,0 +1,464 @@
1
+ <template>
2
+ <view class="hy-form">
3
+ <view
4
+ :class="['hy-form--item', borderBottom && 'hy-border__bottom']"
5
+ v-for="item in columns"
6
+ :key="item.field"
7
+ >
8
+ <view v-if="item.label" class="hy-form--item__label" :style="labelStyle">
9
+ <text v-if="isRequired(item.rules)" style="color: red; font-size: 20px; line-height: 10px">
10
+ *
11
+ </text>
12
+ {{ item.label }}
13
+ <text v-if="symbol">:</text>
14
+ </view>
15
+ <view class="hy-form--item__container">
16
+ <view class="hy-form--item__container-content">
17
+ <!-- 输入框 -->
18
+ <view class="flex" v-if="isInput(item.type)">
19
+ <HyInput
20
+ v-model="formData[item.field]"
21
+ :type="item.type"
22
+ :disabled="item?.input?.disabled || input?.disabled"
23
+ :disabledColor="item?.input?.disabledColor || input?.disabledColor"
24
+ :maxlength="item?.input?.maxlength || input?.maxlength"
25
+ :password="item?.input?.password"
26
+ :clearable="item?.input?.clearable || input?.clearable"
27
+ :readonly="item?.input?.readonly || input?.readonly"
28
+ :placeholder="item?.input?.placeholder"
29
+ :placeholderClass="item?.input?.placeholderClass || input?.placeholderClass"
30
+ :placeholderStyle="item?.input?.placeholderStyle || input?.placeholderStyle"
31
+ :showWordLimit="item?.input?.showWordLimit || input?.showWordLimit"
32
+ :confirmType="item?.input?.confirmType || input?.confirmType"
33
+ :confirmHold="item?.input?.confirmHold || input?.confirmHold"
34
+ :holdKeyboard="item?.input?.holdKeyboard || input?.holdKeyboard"
35
+ :focus="item?.input?.focus || input?.focus"
36
+ :autoBlur="item?.input?.autoBlur || input?.autoBlur"
37
+ :selectionStart="item?.input?.selectionStart || input?.selectionStart"
38
+ :selectionEnd="item?.input?.selectionEnd || input?.selectionEnd"
39
+ :adjustPosition="item?.input?.adjustPosition || input?.adjustPosition"
40
+ :inputAlign="item?.input?.inputAlign || input?.inputAlign"
41
+ :fontSize="item?.input?.fontSize || input?.fontSize"
42
+ :color="item?.input?.color || input?.color"
43
+ :prefixIcon="item?.input?.prefixIcon || input?.prefixIcon"
44
+ :suffixIcon="item?.input?.suffixIcon || input?.suffixIcon"
45
+ :formatter="item?.input?.formatter || input?.formatter"
46
+ :shape="item?.input?.shape || input?.shape"
47
+ :border="item?.input?.border || input?.border"
48
+ :customStyle="errorStyle(!!errors[item.field])"
49
+ @change="handleChange($event, item)"
50
+ @blur="handleBlur($event, item)"
51
+ @onPrefix="item?.input?.onPrefix"
52
+ @onSuffix="item?.input?.onSuffix"
53
+ ></HyInput>
54
+ </view>
55
+ <!-- 输入框 -->
56
+
57
+ <!-- 上传 -->
58
+ <template v-if="item.type === FormTypeEnum.UPLOAD">
59
+ <HyUpload
60
+ :fileList="formData[item.field]"
61
+ :maxCount="item.maxCount"
62
+ :disabled="item.disabled"
63
+ />
64
+ </template>
65
+ <!-- 上传 -->
66
+
67
+ <!-- 详情 -->
68
+ <template v-if="item.type === FormTypeEnum.DETAIL">
69
+ <view class="detail">
70
+ {{ formData[item.field] }}
71
+ </view>
72
+ </template>
73
+ <!-- 详情 -->
74
+
75
+ <!-- 文本域 -->
76
+ <view class="flex" v-if="item.type === FormTypeEnum.TEXTAREA">
77
+ <HyTextarea
78
+ v-model="formData[item.field]"
79
+ :disabled="item?.textarea?.disabled || textarea?.disabled"
80
+ :maxlength="item?.textarea?.maxlength || textarea?.maxlength"
81
+ :placeholder="item?.textarea?.placeholder"
82
+ :placeholderClass="item?.textarea?.placeholderClass || textarea?.placeholderClass"
83
+ :placeholderStyle="item?.textarea?.placeholderStyle || textarea?.placeholderStyle"
84
+ :holdKeyboard="item?.textarea?.holdKeyboard || textarea?.holdKeyboard"
85
+ :focus="item?.textarea?.focus || textarea?.focus"
86
+ :selectionStart="item?.textarea?.selectionStart || textarea?.selectionStart"
87
+ :selectionEnd="item?.textarea?.selectionEnd || textarea?.selectionEnd"
88
+ :adjustPosition="item?.textarea?.adjustPosition || textarea?.adjustPosition"
89
+ :formatter="item?.textarea?.formatter || textarea?.formatter"
90
+ :border="item?.textarea?.border || textarea?.border"
91
+ :customStyle="errorStyle(!!errors[item.field])"
92
+ :height="textarea?.height || item?.textarea?.height"
93
+ @change="handleChange($event, item)"
94
+ @blur="handleBlur($event, item)"
95
+ ></HyTextarea>
96
+ </view>
97
+ <!-- 文本域 -->
98
+
99
+ <!-- 复选框/单选框 -->
100
+ <template v-if="item.type === FormTypeEnum.CHECK_BUTTON">
101
+ <hy-check-button
102
+ v-model="formData[item.field]"
103
+ :columns="item.actions"
104
+ :type="item?.checkButton?.type || checkButton?.type"
105
+ :shape="item?.checkButton?.shape || checkButton?.shape"
106
+ :size="item?.checkButton?.size || checkButton?.size"
107
+ :col="item?.checkButton?.col || checkButton?.col"
108
+ :gap="item?.checkButton?.gap || checkButton?.gap"
109
+ :fieldNames="item?.checkButton?.fieldNames || checkButton?.fieldNames"
110
+ :disabled="item?.checkButton?.size || checkButton?.disabled"
111
+ :selectType="item?.checkButton?.selectType || checkButton?.selectType"
112
+ ></hy-check-button>
113
+ </template>
114
+ <!-- 复选框/单选框 -->
115
+
116
+ <!-- 单选框 -->
117
+ <template v-if="item.type === FormTypeEnum.RADIO">
118
+ <HyRadio
119
+ v-model="formData[item.field]"
120
+ :columns="item.actions"
121
+ :fieldNames="item?.radio?.fieldNames || radio?.fieldNames"
122
+ :shape="item?.radio?.shape || radio?.shape"
123
+ :disabled="item?.radio?.disabled || radio?.disabled"
124
+ :size="item?.radio?.size || radio?.size"
125
+ :activeColor="item?.radio?.activeColor || radio?.activeColor"
126
+ :inactiveColor="item?.radio?.inactiveColor || radio?.inactiveColor"
127
+ :iconSize="item?.radio?.iconSize || radio?.iconSize"
128
+ :iconColor="item?.radio?.iconColor || radio?.iconColor"
129
+ :labelDisabled="item?.radio?.disabled || radio?.labelDisabled"
130
+ :placement="item?.radio?.placement || radio?.placement"
131
+ ></HyRadio>
132
+ </template>
133
+ <!-- 单选框 -->
134
+
135
+ <!-- 开关 -->
136
+ <template v-if="item.type === FormTypeEnum.SWITCH">
137
+ <HySwitch
138
+ v-model="formData[item.field]"
139
+ :loading="item?.switchItem?.loading || switchItem?.loading"
140
+ :disabled="item?.switchItem?.disabled || switchItem?.disabled"
141
+ :size="item?.switchItem?.size || switchItem?.size"
142
+ :activeColor="item?.switchItem?.activeColor || switchItem?.activeColor"
143
+ :inactiveColor="item?.switchItem?.inactiveColor || switchItem?.inactiveColor"
144
+ :activeValue="item?.switchItem?.activeValue || switchItem?.activeValue"
145
+ :inactiveValue="item?.switchItem?.inactiveValue || switchItem?.inactiveValue"
146
+ :activeIcon="item?.switchItem?.activeIcon || switchItem?.activeIcon"
147
+ :inactiveIcon="item?.switchItem?.inactiveIcon || switchItem?.inactiveIcon"
148
+ :space="item?.switchItem?.space || switchItem?.space"
149
+ ></HySwitch>
150
+ </template>
151
+ <!-- 开关 -->
152
+
153
+ <!-- 自定义选择器 -->
154
+ <template v-if="item.type === FormTypeEnum.SELECT">
155
+ <HyPicker
156
+ v-model="formData[item.field]"
157
+ :columns="item.select"
158
+ has-input
159
+ :separator="item?.picker?.separator || picker?.separator"
160
+ :itemHeight="item?.picker?.itemHeight || picker?.itemHeight"
161
+ :cancelText="item?.picker?.cancelText || picker?.cancelText"
162
+ :confirmText="item?.picker?.confirmText || picker?.confirmText"
163
+ :cancelColor="item?.picker?.cancelColor || picker?.cancelColor"
164
+ :confirmColor="item?.picker?.confirmColor || picker?.confirmColor"
165
+ :visibleItemCount="item?.picker?.visibleItemCount || picker?.visibleItemCount"
166
+ :closeOnClickOverlay="
167
+ item?.picker?.closeOnClickOverlay || picker?.closeOnClickOverlay
168
+ "
169
+ :title="item?.picker?.title || picker?.title"
170
+ :showToolbar="item?.picker?.showToolbar || picker?.showToolbar"
171
+ :customStyle="errorStyle(!!errors[item.field])"
172
+ :input="{
173
+ disabled: item?.picker?.input?.disabled || picker?.input?.disabled,
174
+ placeholder: item.picker?.input?.placeholder,
175
+ shape: item?.picker?.input?.shape || picker?.input?.shape,
176
+ border: item?.picker?.input?.border || picker?.input?.border,
177
+ customStyle: errorStyle(!!errors[item.field]),
178
+ }"
179
+ ></HyPicker>
180
+ </template>
181
+ <!-- 自定义选择器 -->
182
+
183
+ <!-- 时间选择器 -->
184
+ <template v-if="item.type === FormTypeEnum.DATE">
185
+ <HyDatetimePicker
186
+ v-model="formData[item.field]"
187
+ has-input
188
+ :mode="item.mode"
189
+ :separator="item?.picker?.separator || picker?.separator"
190
+ :itemHeight="item?.picker?.itemHeight || picker?.itemHeight"
191
+ :cancelText="item?.picker?.cancelText || picker?.cancelText"
192
+ :confirmText="item?.picker?.confirmText || picker?.confirmText"
193
+ :cancelColor="item?.picker?.cancelColor || picker?.cancelColor"
194
+ :confirmColor="item?.picker?.confirmColor || picker?.confirmColor"
195
+ :visibleItemCount="item?.picker?.visibleItemCount || picker?.visibleItemCount"
196
+ :closeOnClickOverlay="
197
+ item?.picker?.closeOnClickOverlay || picker?.closeOnClickOverlay
198
+ "
199
+ :title="item?.picker?.title || picker?.title"
200
+ :showToolbar="item?.picker?.showToolbar || picker?.showToolbar"
201
+ :customStyle="errorStyle(!!errors[item.field])"
202
+ :input="{
203
+ disabled: item?.picker?.input?.disabled || picker?.input?.disabled,
204
+ placeholder: item.picker?.input?.placeholder,
205
+ shape: item?.picker?.input?.shape || picker?.input?.shape,
206
+ border: item?.picker?.input?.border || picker?.input?.border,
207
+ customStyle: errorStyle(!!errors[item.field]),
208
+ }"
209
+ ></HyDatetimePicker>
210
+ </template>
211
+ <!-- 时间选择器 -->
212
+
213
+ <!-- 地址选择器 -->
214
+ <template v-if="item.type === FormTypeEnum.ADDRESS">
215
+ <HyAddressPicker
216
+ v-model="formData[item.field]"
217
+ has-input
218
+ :separator="item?.picker?.separator || picker?.separator"
219
+ :itemHeight="item?.picker?.itemHeight || picker?.itemHeight"
220
+ :cancelText="item?.picker?.cancelText || picker?.cancelText"
221
+ :confirmText="item?.picker?.confirmText || picker?.confirmText"
222
+ :cancelColor="item?.picker?.cancelColor || picker?.cancelColor"
223
+ :confirmColor="item?.picker?.confirmColor || picker?.confirmColor"
224
+ :visibleItemCount="item?.picker?.visibleItemCount || picker?.visibleItemCount"
225
+ :closeOnClickOverlay="
226
+ item?.picker?.closeOnClickOverlay || picker?.closeOnClickOverlay
227
+ "
228
+ :title="item?.picker?.title || picker?.title"
229
+ :showToolbar="item?.picker?.showToolbar || picker?.showToolbar"
230
+ :customStyle="errorStyle(!!errors[item.field])"
231
+ :input="{
232
+ disabled: item?.picker?.input?.disabled || picker?.input?.disabled,
233
+ placeholder: item.picker?.input?.placeholder,
234
+ shape: item?.picker?.input?.shape || picker?.input?.shape,
235
+ border: item?.picker?.input?.border || picker?.input?.border,
236
+ customStyle: errorStyle(!!errors[item.field]),
237
+ }"
238
+ ></HyAddressPicker>
239
+ </template>
240
+ <!-- 地址选择器 -->
241
+
242
+ <!-- 自定义插槽 -->
243
+ <view class="flex" v-if="item.type === FormTypeEnum.CUSTOM">
244
+ <slot
245
+ :name="item.field"
246
+ :record="item"
247
+ :errorStyle="errorStyle(!!errors[item.field])"
248
+ ></slot>
249
+ </view>
250
+ <!-- 自定义插槽 -->
251
+ </view>
252
+
253
+ <!-- 提示信息 -->
254
+ <HyTransition :show="!!errors[item.field]" mode="slide-left">
255
+ <view class="hy-form--item__container-warning">{{ errors[item.field] }}</view>
256
+ </HyTransition>
257
+ <!-- 提示信息 -->
258
+ </view>
259
+ </view>
260
+ </view>
261
+ </template>
262
+
263
+ <script lang="ts">
264
+ export default {
265
+ name: 'hy-form',
266
+ options: {
267
+ addGlobalClass: true,
268
+ virtualHost: true,
269
+ styleIsolation: 'shared',
270
+ },
271
+ }
272
+ </script>
273
+
274
+ <script setup lang="ts">
275
+ import { computed, reactive, toRefs } from 'vue'
276
+ import type { CSSProperties } from 'vue'
277
+ import type IProps from './typing'
278
+ import defaultProps from './props'
279
+ import { addUnit, error } from '../../utils'
280
+ import type { FormColumnsType, RulesVo } from '../../typing'
281
+ import { FormTypeEnum } from '../../typing'
282
+
283
+ // 组件
284
+ import HyInput from '../hy-input/hy-input.vue'
285
+ import HyPicker from '../hy-picker/hy-picker.vue'
286
+ import HyUpload from '../hy-upload/hy-upload.vue'
287
+ import HyTextarea from '../hy-textarea/hy-textarea.vue'
288
+ import HySwitch from '../hy-switch/hy-switch.vue'
289
+ import HyRadio from '../hy-radio/hy-radio.vue'
290
+ import HyDatetimePicker from '../hy-datetime-picker/hy-datetime-picker.vue'
291
+ import HyAddressPicker from '../hy-address-picker/hy-address-picker.vue'
292
+ import HyTransition from '../hy-transition/hy-transition.vue'
293
+ import HyCheckButton from '../hy-check-button/hy-check-button.vue'
294
+
295
+ const props = withDefaults(defineProps<IProps>(), defaultProps)
296
+ const { formData, columns, labelWidth, labelAlign, labelPosition, borderBottom } = toRefs(props)
297
+ const emit = defineEmits(['click'])
298
+
299
+ const labelPos = labelPosition.value === 'top' ? 'column' : 'row'
300
+ const isInput = (type: FormTypeEnum) =>
301
+ type === FormTypeEnum.TEXT || type === FormTypeEnum.NUMBER || type === FormTypeEnum.PASSWORD
302
+
303
+ /**
304
+ * @description 错误输入框样式
305
+ * */
306
+ const errorStyle = computed(() => {
307
+ return (err: boolean) => {
308
+ const style: CSSProperties = {}
309
+ if (err) {
310
+ style.background = '#dd6161'
311
+ }
312
+
313
+ return style
314
+ }
315
+ })
316
+
317
+ const isRequired = computed(() => {
318
+ return (temp: any) => {
319
+ if (Array.isArray(temp)) {
320
+ return temp.some((item) => item?.required)
321
+ } else {
322
+ return temp?.required
323
+ }
324
+ }
325
+ })
326
+
327
+ const errors: AnyObject = reactive({})
328
+
329
+ /**
330
+ * @description 标题行内样式
331
+ * */
332
+ const labelStyle = computed(() => {
333
+ return {
334
+ textAlign: labelAlign.value,
335
+ width: addUnit(labelWidth.value),
336
+ }
337
+ })
338
+
339
+ /**
340
+ * @description 错误信息校验
341
+ * */
342
+ const errorMsg = (rule: RulesVo, value: string): string => {
343
+ // 手机正则
344
+ const phoneExpression = /^1[3-9]\d{9}$/
345
+ // 邮箱正则
346
+ const emitExpression = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/
347
+ // 复杂密码正则
348
+ const passwordExpression =
349
+ /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]).{8,}$/
350
+ if (rule.required && !value) {
351
+ return rule.message!
352
+ } else if ((rule?.min || rule?.max) && (value.length < rule?.min! || value.length > rule?.max!)) {
353
+ return rule.message!
354
+ } else if (rule.type === 'phone' && !phoneExpression.test(String(value))) {
355
+ return rule.message || '请输入正确的手机号'
356
+ } else if (rule.type === 'email' && !emitExpression.test(String(value))) {
357
+ return rule.message || '请输入正确的邮箱格式'
358
+ } else if (rule.type === 'password' && !passwordExpression.test(String(value))) {
359
+ return rule.message || '至少8个字符串,并且包含大、小写字母、数字和特殊符号'
360
+ } else if (rule?.validator && !rule.validator(rule, value)) {
361
+ return rule.message || ''
362
+ } else {
363
+ return ''
364
+ }
365
+ }
366
+
367
+ /**
368
+ * @description 校验字段
369
+ * */
370
+ const validateField = (
371
+ rules: RulesVo | RulesVo[] | undefined,
372
+ value: string,
373
+ field: string,
374
+ event?: 'blur' | 'change',
375
+ ) => {
376
+ if (!rules) return
377
+
378
+ let errorMessage = ''
379
+
380
+ if (Array.isArray(rules)) {
381
+ // 遍历所有规则
382
+ for (const index in rules) {
383
+ // 判断是否有change事件或者blur事件
384
+ if (event && !rules[index]?.trigger?.includes(event)) continue
385
+ errorMessage = errorMsg(rules[index], value)
386
+ if (errorMessage) {
387
+ errors[field] = errorMessage
388
+ return
389
+ }
390
+ // 可以继续添加更多规则
391
+ }
392
+ } else {
393
+ // 必填校验
394
+ if (event && !rules?.trigger?.includes(event)) return
395
+ errorMessage = errorMsg(rules, value)
396
+ }
397
+
398
+ // 自定义校验规则
399
+ // if (rules.custom) {
400
+ // const customError = rules.custom(value);
401
+ // if (customError) {
402
+ // errorMessage = customError;
403
+ // }
404
+ // }
405
+
406
+ errors[field] = errorMessage
407
+ }
408
+
409
+ /**
410
+ * @description 提交表单
411
+ * */
412
+ const handleSubmit = () => {
413
+ return new Promise((resolve, reject) => {
414
+ let isValid = true
415
+
416
+ // 校验所有字段
417
+ props.columns.forEach((col) => {
418
+ validateField(col.rules, formData.value[col.field], col.field)
419
+ if (errors[col.field]) {
420
+ isValid = false
421
+ }
422
+ })
423
+
424
+ if (isValid) {
425
+ // alert("表单提交成功!");
426
+ resolve(formData.value)
427
+ } else {
428
+ reject()
429
+ error('表单校验失败,请检查输入!')
430
+ }
431
+ })
432
+ }
433
+
434
+ /**
435
+ * @description 输入值触发
436
+ * */
437
+ const handleChange = (event: string, temp: FormColumnsType) => {
438
+ if (isInput(temp.type) && temp?.input?.onChange) {
439
+ temp.input.onChange(event, temp)
440
+ }
441
+ validateField(temp.rules, event, temp.field, 'change')
442
+ }
443
+ /**
444
+ * @description 输入值触发
445
+ * */
446
+ const handleBlur = (event: string, temp: FormColumnsType) => {
447
+ if (isInput(temp.type) && temp?.input?.onBlur) {
448
+ temp.input.onBlur(event, temp)
449
+ }
450
+ validateField(temp.rules, event, temp.field, 'blur')
451
+ }
452
+
453
+ defineExpose({
454
+ validateField,
455
+ handleSubmit,
456
+ })
457
+ </script>
458
+
459
+ <style lang="scss" scoped>
460
+ @import './index.scss';
461
+ .hy-form--item {
462
+ flex-direction: v-bind(labelPos);
463
+ }
464
+ </style>
@@ -0,0 +1,77 @@
1
+ import type { FormColumnsType } from "../../typing";
2
+ import type HyInputProps from "../hy-input/typing";
3
+ import type HyTextareaProps from "../hy-textarea/typing";
4
+ import type HySwitchProps from "../hy-switch/typing";
5
+ import type HyPickerProps from "../hy-picker/typing";
6
+ import type HyRadioProps from "../hy-radio/typing";
7
+ import type HyCheckButtonProps from "../hy-check-button/typing";
8
+
9
+ export default interface HyFormProps {
10
+ /**
11
+ * @description 表单域提示文字的位置
12
+ * left - 左侧
13
+ * top - 上方
14
+ * */
15
+ labelPosition?: "left" | "top";
16
+ /**
17
+ * @description label宽度
18
+ * 数字 - 固定值
19
+ * auto - 自适应
20
+ * */
21
+ labelWidth?: string | number;
22
+ /**
23
+ * @description 是否右对齐
24
+ * */
25
+ right?: boolean;
26
+ /**
27
+ * @description label字体的对齐方式
28
+ * left - 左对齐
29
+ * center - 中间对齐
30
+ * right - 右对齐
31
+ * */
32
+ labelAlign?: HyApp.RowCenterType;
33
+ /**
34
+ * @description 显示冒号符号
35
+ * */
36
+ symbol?: boolean;
37
+ /**
38
+ * @description 显示底部下划线
39
+ * */
40
+ borderBottom?: boolean;
41
+ /**
42
+ * @description 当行内容高度
43
+ * */
44
+ itemHeight?: number | string;
45
+ /**
46
+ * @description 输入框属性api集合
47
+ * */
48
+ input?: Partial<HyInputProps>;
49
+ /**
50
+ * @description 文本域属性api集合
51
+ * */
52
+ textarea?: Partial<HyTextareaProps>;
53
+ /**
54
+ * @description 选择器属性api集合
55
+ * */
56
+ picker?: Partial<HyPickerProps>;
57
+ /**
58
+ * @description 开关属性api集合
59
+ * */
60
+ switchItem?: Partial<HySwitchProps>;
61
+ /**
62
+ * @description 单选属性api集合
63
+ * */
64
+ radio?: Partial<HyRadioProps>;
65
+ /**
66
+ * @description 选择按钮属性api集合
67
+ * */
68
+ checkButton?: Partial<HyCheckButtonProps>;
69
+ /**
70
+ * @description 表单配置
71
+ * */
72
+ columns: FormColumnsType[];
73
+ /**
74
+ * @description 表单值
75
+ * */
76
+ formData: Record<string, any>;
77
+ }