hy-app 0.5.2 → 0.5.4

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