hy-app 0.4.13 → 0.5.0

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 (211) hide show
  1. package/components/hy-action-sheet/hy-action-sheet.vue +155 -238
  2. package/components/hy-action-sheet/props.ts +68 -15
  3. package/components/hy-action-sheet/typing.d.ts +115 -115
  4. package/components/hy-address-picker/hy-address-picker.vue +185 -289
  5. package/components/hy-address-picker/props.ts +97 -21
  6. package/components/hy-address-picker/typing.d.ts +90 -89
  7. package/components/hy-avatar/hy-avatar.vue +121 -204
  8. package/components/hy-avatar/props.ts +76 -18
  9. package/components/hy-avatar/typing.d.ts +63 -62
  10. package/components/hy-back-top/hy-back-top.vue +65 -120
  11. package/components/hy-back-top/props.ts +57 -16
  12. package/components/hy-back-top/typing.d.ts +43 -42
  13. package/components/hy-badge/hy-badge.vue +66 -138
  14. package/components/hy-badge/props.ts +73 -17
  15. package/components/hy-badge/typing.d.ts +59 -58
  16. package/components/hy-button/hy-button.vue +226 -375
  17. package/components/hy-button/props.ts +129 -158
  18. package/components/hy-calendar/header.vue +48 -64
  19. package/components/hy-calendar/hy-calendar.vue +274 -438
  20. package/components/hy-calendar/month.vue +508 -516
  21. package/components/hy-calendar/props.ts +157 -35
  22. package/components/hy-calendar/typing.d.ts +129 -128
  23. package/components/hy-card/hy-card.vue +118 -240
  24. package/components/hy-card/index.scss +1 -2
  25. package/components/hy-card/props.ts +122 -27
  26. package/components/hy-card/typing.d.ts +119 -118
  27. package/components/hy-cell/hy-cell.vue +176 -258
  28. package/components/hy-cell/props.ts +71 -17
  29. package/components/hy-cell/typing.d.ts +87 -86
  30. package/components/hy-check-button/hy-check-button.vue +69 -139
  31. package/components/hy-check-button/props.ts +72 -18
  32. package/components/hy-check-button/typing.d.ts +74 -73
  33. package/components/hy-checkbox/hy-checkbox.vue +170 -263
  34. package/components/hy-checkbox/props.ts +94 -24
  35. package/components/hy-checkbox/typing.d.ts +72 -72
  36. package/components/hy-checkbox-group/hy-checkbox-group.vue +25 -100
  37. package/components/hy-checkbox-group/props.ts +80 -0
  38. package/components/hy-checkbox-group/typing.d.ts +65 -65
  39. package/components/hy-checkbox-item/hy-checkbox-item.vue +140 -177
  40. package/components/hy-checkbox-item/props.ts +24 -0
  41. package/components/hy-checkbox-item/typing.d.ts +4 -3
  42. package/components/hy-code-input/hy-code-input.vue +179 -262
  43. package/components/hy-code-input/props.ts +84 -18
  44. package/components/hy-code-input/typing.d.ts +71 -71
  45. package/components/hy-config-provider/hy-config-provider.vue +28 -50
  46. package/components/hy-config-provider/props.ts +26 -11
  47. package/components/hy-config-provider/typing.d.ts +20 -20
  48. package/components/hy-count-down/hy-count-down.vue +103 -131
  49. package/components/hy-count-down/props.ts +30 -8
  50. package/components/hy-count-down/typing.d.ts +25 -25
  51. package/components/hy-count-to/hy-count-to.vue +148 -213
  52. package/components/hy-count-to/props.ts +60 -15
  53. package/components/hy-count-to/typing.d.ts +46 -46
  54. package/components/hy-coupon/README.md +133 -0
  55. package/components/hy-coupon/hy-coupon.vue +180 -0
  56. package/components/hy-coupon/index.scss +553 -0
  57. package/components/hy-coupon/props.ts +129 -0
  58. package/components/hy-coupon/typing.d.ts +146 -0
  59. package/components/hy-datetime-picker/hy-datetime-picker.vue +415 -580
  60. package/components/hy-datetime-picker/props.ts +142 -32
  61. package/components/hy-datetime-picker/typing.d.ts +132 -132
  62. package/components/hy-divider/hy-divider.vue +90 -169
  63. package/components/hy-divider/props.ts +78 -19
  64. package/components/hy-divider/typing.d.ts +60 -60
  65. package/components/hy-dropdown/hy-dropdown.vue +37 -71
  66. package/components/hy-dropdown/props.ts +38 -15
  67. package/components/hy-dropdown/typing.d.ts +44 -44
  68. package/components/hy-dropdown-item/hy-dropdown-item.vue +141 -173
  69. package/components/hy-dropdown-item/props.ts +19 -8
  70. package/components/hy-empty/hy-empty.vue +75 -129
  71. package/components/hy-empty/props.ts +57 -15
  72. package/components/hy-empty/typing.d.ts +84 -84
  73. package/components/hy-flex/hy-flex.vue +33 -88
  74. package/components/hy-flex/props.ts +58 -0
  75. package/components/hy-flex/typing.d.ts +14 -16
  76. package/components/hy-float-button/hy-float-button.vue +289 -406
  77. package/components/hy-float-button/props.ts +109 -25
  78. package/components/hy-folding-panel/hy-folding-panel.vue +86 -374
  79. package/components/hy-folding-panel/props.ts +40 -15
  80. package/components/hy-folding-panel/typing.d.ts +52 -63
  81. package/components/hy-folding-panel-item/hy-folding-panel-item.vue +186 -228
  82. package/components/hy-folding-panel-item/index.scss +87 -0
  83. package/components/hy-folding-panel-item/props.ts +81 -0
  84. package/components/hy-folding-panel-item/typing.d.ts +23 -0
  85. package/components/hy-form/hy-form.vue +172 -212
  86. package/components/hy-form/props.ts +37 -0
  87. package/components/hy-form/typing.d.ts +68 -61
  88. package/components/hy-form-group/typing.d.ts +74 -74
  89. package/components/hy-form-item/hy-form-item.vue +100 -129
  90. package/components/hy-form-item/props.ts +25 -0
  91. package/components/hy-form-item/typing.d.ts +40 -37
  92. package/components/hy-grid/hy-grid.vue +76 -132
  93. package/components/hy-grid/props.ts +58 -16
  94. package/components/hy-grid/typing.d.ts +66 -66
  95. package/components/hy-icon/hy-icon.vue +84 -161
  96. package/components/hy-icon/props.ts +76 -22
  97. package/components/hy-icon/typing.d.ts +83 -82
  98. package/components/hy-image/hy-image.vue +142 -272
  99. package/components/hy-image/props.ts +105 -23
  100. package/components/hy-image/typing.d.ts +84 -87
  101. package/components/hy-input/hy-input.vue +230 -421
  102. package/components/hy-input/props.ts +183 -35
  103. package/components/hy-input/typing.d.ts +169 -169
  104. package/components/hy-line/hy-line.vue +34 -72
  105. package/components/hy-line/props.ts +41 -10
  106. package/components/hy-line/typing.d.ts +29 -29
  107. package/components/hy-line-progress/hy-line-progress.vue +66 -101
  108. package/components/hy-line-progress/props.ts +31 -10
  109. package/components/hy-line-progress/typing.d.ts +29 -29
  110. package/components/hy-list/hy-list.vue +151 -220
  111. package/components/hy-list/props.ts +67 -16
  112. package/components/hy-list/typing.d.ts +52 -52
  113. package/components/hy-loading/hy-loading.vue +63 -119
  114. package/components/hy-loading/props.ts +63 -15
  115. package/components/hy-loading/typing.d.ts +49 -49
  116. package/components/hy-menu/hy-menu.vue +124 -166
  117. package/components/hy-menu/props.ts +42 -10
  118. package/components/hy-menu/typing.d.ts +60 -60
  119. package/components/hy-modal/hy-modal.vue +127 -218
  120. package/components/hy-modal/props.ts +89 -24
  121. package/components/hy-navbar/hy-navbar.vue +104 -177
  122. package/components/hy-navbar/props.ts +76 -22
  123. package/components/hy-navbar/typing.d.ts +81 -81
  124. package/components/hy-notice-bar/hy-notice-bar.vue +67 -144
  125. package/components/hy-notice-bar/props.ts +80 -19
  126. package/components/hy-notice-bar/typing.d.ts +62 -62
  127. package/components/hy-notify/hy-notify.vue +128 -177
  128. package/components/hy-notify/props.ts +49 -12
  129. package/components/hy-notify/typing.d.ts +45 -41
  130. package/components/hy-number-step/hy-number-step.vue +281 -394
  131. package/components/hy-number-step/props.ts +110 -27
  132. package/components/hy-number-step/typing.d.ts +120 -120
  133. package/components/hy-overlay/hy-overlay.vue +39 -66
  134. package/components/hy-overlay/props.ts +31 -8
  135. package/components/hy-pagination/hy-pagination.vue +100 -155
  136. package/components/hy-pagination/props.ts +53 -13
  137. package/components/hy-picker/hy-picker.vue +309 -430
  138. package/components/hy-picker/index.scss +8 -12
  139. package/components/hy-picker/props.ts +110 -26
  140. package/components/hy-popover/hy-popover.vue +190 -252
  141. package/components/hy-popover/props.ts +48 -10
  142. package/components/hy-popup/hy-popup.vue +162 -248
  143. package/components/hy-popup/props.ts +82 -18
  144. package/components/hy-price/hy-price.vue +45 -104
  145. package/components/hy-price/props.ts +52 -12
  146. package/components/hy-price/typing.d.ts +41 -36
  147. package/components/hy-qrcode/hy-qrcode.vue +115 -185
  148. package/components/hy-qrcode/props.ts +68 -18
  149. package/components/hy-qrcode/typing.d.ts +67 -66
  150. package/components/hy-radio/hy-radio.vue +161 -259
  151. package/components/hy-radio/props.ts +95 -25
  152. package/components/hy-radio/typing.d.ts +85 -84
  153. package/components/hy-rate/hy-rate.vue +185 -270
  154. package/components/hy-rate/props.ts +76 -18
  155. package/components/hy-rate/typing.d.ts +61 -60
  156. package/components/hy-read-more/hy-read-more.vue +93 -136
  157. package/components/hy-read-more/props.ts +43 -13
  158. package/components/hy-scroll-list/hy-scroll-list.vue +81 -102
  159. package/components/hy-scroll-list/props.ts +22 -11
  160. package/components/hy-search/hy-search.vue +155 -284
  161. package/components/hy-search/props.ts +130 -25
  162. package/components/hy-signature/hy-signature.vue +491 -635
  163. package/components/hy-signature/props.ts +115 -26
  164. package/components/hy-signature/typing.d.ts +138 -138
  165. package/components/hy-slider/hy-slider.vue +388 -477
  166. package/components/hy-slider/props.ts +75 -19
  167. package/components/hy-steps/hy-steps.vue +212 -279
  168. package/components/hy-steps/props.ts +47 -13
  169. package/components/hy-submit-bar/hy-submit-bar.vue +137 -222
  170. package/components/hy-submit-bar/props.ts +89 -20
  171. package/components/hy-submit-bar/typing.d.ts +86 -85
  172. package/components/hy-subsection/hy-subsection.vue +132 -185
  173. package/components/hy-subsection/props.ts +50 -17
  174. package/components/hy-subsection/typing.d.ts +52 -52
  175. package/components/hy-swipe-action/hy-swipe-action.vue +228 -283
  176. package/components/hy-swipe-action/props.ts +43 -18
  177. package/components/hy-swipe-action/typing.d.ts +46 -46
  178. package/components/hy-swiper/hy-swiper.vue +159 -286
  179. package/components/hy-swiper/props.ts +126 -28
  180. package/components/hy-swiper/typing.d.ts +115 -115
  181. package/components/hy-switch/hy-switch.vue +112 -176
  182. package/components/hy-switch/props.ts +60 -15
  183. package/components/hy-switch/typing.d.ts +63 -63
  184. package/components/hy-tabBar/hy-tabBar.vue +64 -60
  185. package/components/hy-tabs/hy-tabs.vue +277 -380
  186. package/components/hy-tabs/props.ts +75 -18
  187. package/components/hy-tag/hy-tag.vue +111 -204
  188. package/components/hy-tag/props.ts +81 -19
  189. package/components/hy-text/hy-text.vue +200 -322
  190. package/components/hy-text/props.ts +107 -28
  191. package/components/hy-textarea/hy-textarea.vue +147 -256
  192. package/components/hy-textarea/props.ts +112 -25
  193. package/components/hy-textarea/typing.d.ts +42 -42
  194. package/components/hy-toast/hy-toast.vue +135 -143
  195. package/components/hy-tooltip/hy-tooltip.vue +220 -306
  196. package/components/hy-tooltip/props.ts +79 -15
  197. package/components/hy-transition/hy-transition.vue +111 -138
  198. package/components/hy-transition/props.ts +30 -8
  199. package/components/hy-upload/hy-upload.vue +320 -469
  200. package/components/hy-upload/props.ts +130 -27
  201. package/components/hy-warn/hy-warn.vue +80 -129
  202. package/components/hy-warn/props.ts +47 -12
  203. package/components/hy-waterfall/hy-waterfall.vue +139 -163
  204. package/components/hy-waterfall/props.ts +19 -7
  205. package/components/hy-watermark/hy-watermark.vue +762 -870
  206. package/components/hy-watermark/props.ts +103 -22
  207. package/global.d.ts +2 -0
  208. package/libs/css/theme.scss +3 -3
  209. package/package.json +2 -2
  210. package/web-types.json +1 -1
  211. package/components/hy-folding-panel/index.scss +0 -9
@@ -0,0 +1,81 @@
1
+ import type { CSSProperties, PropType } from 'vue'
2
+
3
+ const foldingPanelItemProps = {
4
+ /**
5
+ * 面板索引(由父组件自动设置)
6
+ */
7
+ index: {
8
+ type: [Number, String],
9
+ default: -1,
10
+ required: true
11
+ },
12
+ /**
13
+ * 面板标题
14
+ */
15
+ title: {
16
+ type: String,
17
+ default: ''
18
+ },
19
+ /**
20
+ * 右侧显示的值
21
+ */
22
+ value: {
23
+ type: String,
24
+ default: ''
25
+ },
26
+ /**
27
+ * 左侧图标
28
+ */
29
+ icon: {
30
+ type: String,
31
+ default: ''
32
+ },
33
+ /**
34
+ * 左侧图标颜色
35
+ */
36
+ iconColor: {
37
+ type: String,
38
+ default: ''
39
+ },
40
+ /**
41
+ * 左侧图标大小
42
+ */
43
+ iconSize: {
44
+ type: [Number, String],
45
+ default: ''
46
+ },
47
+ /**
48
+ * 面板内容
49
+ */
50
+ content: {
51
+ type: String,
52
+ default: ''
53
+ },
54
+ /**
55
+ * 是否禁用
56
+ */
57
+ disabled: {
58
+ type: Boolean,
59
+ default: false
60
+ },
61
+ /**
62
+ * 默认是否展开
63
+ */
64
+ defaultOpen: {
65
+ type: Boolean,
66
+ default: false
67
+ },
68
+ /**
69
+ * 内容区域最大高度
70
+ */
71
+ contentHeight: {
72
+ type: [Number, String],
73
+ default: 150
74
+ },
75
+ /**
76
+ * 自定义样式
77
+ */
78
+ customStyle: Object as PropType<CSSProperties>
79
+ }
80
+
81
+ export default foldingPanelItemProps
@@ -0,0 +1,23 @@
1
+ // 折叠面板项组件的事件接口
2
+ export interface IFoldingPanelItemEmits {
3
+ /**
4
+ * 点击面板时触发
5
+ */
6
+ (e: 'click', index: number | string): void
7
+ /**
8
+ * 面板打开时触发
9
+ */
10
+ (e: 'open', index: number | string): void
11
+ /**
12
+ * 面板关闭时触发
13
+ */
14
+ (e: 'close', index: number | string): void
15
+ /**
16
+ * 面板状态改变时触发
17
+ */
18
+ (e: 'change', expanded: boolean, index: number | string): void
19
+ /**
20
+ * 子项点击时通知父组件
21
+ */
22
+ (e: 'child-click', index: number | string): void
23
+ }
@@ -1,260 +1,220 @@
1
1
  <template>
2
- <view class="hy-form">
3
- <slot></slot>
4
- </view>
2
+ <view class="hy-form">
3
+ <slot></slot>
4
+ </view>
5
5
  </template>
6
6
 
7
7
  <script lang="ts">
8
8
  export default {
9
- name: "hy-form",
10
- options: {
11
- addGlobalClass: true,
12
- virtualHost: true,
13
- styleIsolation: "shared",
14
- },
15
- };
9
+ name: 'hy-form',
10
+ options: {
11
+ addGlobalClass: true,
12
+ virtualHost: true,
13
+ styleIsolation: 'shared'
14
+ }
15
+ }
16
16
  </script>
17
17
 
18
18
  <script setup lang="ts">
19
- import { provide, reactive, ref, toRefs } from "vue";
20
- import type { PropType } from "vue";
21
- import type { FormItemRule } from "./typing";
22
- import { clearVal, isArray } from "../../libs";
19
+ import { provide, reactive, ref, toRefs } from 'vue'
20
+ import { clearVal, isArray } from '../../libs'
21
+ import formProps from './props'
22
+ import type { IFormEmits } from './typing'
23
23
 
24
24
  /**
25
25
  * 表单组件父组件,需要搭配hy-form-item
26
26
  * @displayName hy-form
27
27
  */
28
- defineOptions({});
28
+ defineOptions({})
29
29
 
30
- const props = defineProps({
31
- /** 表单数据对象 */
32
- model: Object as PropType<AnyObject>,
33
- /** 表单校验规则 */
34
- rules: Object as PropType<FormItemRule>,
35
- /** 表单底部边框 */
36
- border: {
37
- type: Boolean,
38
- default: false,
39
- },
40
- /** label标签的宽度,单位rpx */
41
- labelWidth: {
42
- type: String,
43
- default: "auto",
44
- },
45
- /**
46
- * 标签位置
47
- * @values left,top
48
- * */
49
- labelPosition: {
50
- type: String as PropType<HyApp.LabelPosition>,
51
- default: "left",
52
- },
53
- /**
54
- * 标签位置
55
- * @values left,center,right
56
- * */
57
- labelAlign: {
58
- type: String as PropType<HyApp.ColumnCenterType>,
59
- default: "left",
60
- },
61
- });
62
-
63
- const emit = defineEmits<{
64
- submit: [data: Record<string, any>];
65
- validate: [valid: boolean, errors: Record<string, string>];
66
- }>();
30
+ const props = defineProps(formProps)
31
+ const emit = defineEmits<IFormEmits>()
67
32
 
68
33
  // 表单数据
69
- const formData = reactive(props.model || {});
70
- const formItems = ref<any[]>([]);
71
- const errors = reactive<Record<string, string>>({});
34
+ const formData = reactive(props.model || {})
35
+ const formItems = ref<any[]>([])
36
+ const errors = reactive<Record<string, string>>({})
72
37
 
73
38
  // 表单上下文
74
39
  const formContext = {
75
- ...toRefs(props),
76
- formData,
77
- errors,
78
- addFormItem: (item: any) => {
79
- formItems.value.push(item);
80
- },
81
- removeFormItem: (item: any) => {
82
- const index = formItems.value.indexOf(item);
83
- if (index > -1) {
84
- formItems.value.splice(index, 1);
85
- }
86
- },
87
- validateField: (field: string, value: any, trigger?: "blur" | "change") => {
88
- const fieldRules = props.rules?.[field];
89
- if (!fieldRules) return true;
90
-
91
- const rules = isArray(fieldRules) ? fieldRules : [fieldRules];
92
- let isValid = true;
93
- let errorMessage = "";
94
-
95
- for (const rule of rules) {
96
- // 检查触发时机
97
- if (
98
- (trigger && !rule.trigger) ||
99
- (trigger && rule.trigger && !rule.trigger.includes(trigger))
100
- ) {
101
- continue;
102
- }
103
-
104
- // 必填校验
105
- if (rule.required && (!value || value === "")) {
106
- errorMessage = rule.message || `${field} 是必填项`;
107
- isValid = false;
108
- break;
109
- }
110
-
111
- // 长度校验
112
- if (rule.min && String(value).length < rule.min) {
113
- errorMessage =
114
- rule.message || `${field} 长度不能少于 ${rule.min} 个字符`;
115
- isValid = false;
116
- break;
117
- }
118
-
119
- if (rule.max && String(value).length > rule.max) {
120
- errorMessage =
121
- rule.message || `${field} 长度不能超过 ${rule.max} 个字符`;
122
- isValid = false;
123
- break;
124
- }
125
-
126
- // 类型校验
127
- if (rule.type === "phone") {
128
- const phoneRegex = /^1[3-9]\d{9}$/;
129
- if (!phoneRegex.test(String(value))) {
130
- errorMessage = rule.message || "请输入正确的手机号";
131
- isValid = false;
132
- break;
40
+ ...toRefs(props),
41
+ formData,
42
+ errors,
43
+ addFormItem: (item: any) => {
44
+ formItems.value.push(item)
45
+ },
46
+ removeFormItem: (item: any) => {
47
+ const index = formItems.value.indexOf(item)
48
+ if (index > -1) {
49
+ formItems.value.splice(index, 1)
133
50
  }
134
- }
135
-
136
- if (rule.type === "email") {
137
- const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
138
- if (!emailRegex.test(String(value))) {
139
- errorMessage = rule.message || "请输入正确的邮箱格式";
140
- isValid = false;
141
- break;
51
+ },
52
+ validateField: (field: string, value: any, trigger?: 'blur' | 'change') => {
53
+ const fieldRules = props.rules?.[field]
54
+ if (!fieldRules) return true
55
+
56
+ const rules = isArray(fieldRules) ? fieldRules : [fieldRules]
57
+ let isValid = true
58
+ let errorMessage = ''
59
+
60
+ for (const rule of rules) {
61
+ // 检查触发时机
62
+ if (
63
+ (trigger && !rule.trigger) ||
64
+ (trigger && rule.trigger && !rule.trigger.includes(trigger))
65
+ ) {
66
+ continue
67
+ }
68
+
69
+ // 必填校验
70
+ if (rule.required && (!value || value === '')) {
71
+ errorMessage = rule.message || `${field} 是必填项`
72
+ isValid = false
73
+ break
74
+ }
75
+
76
+ // 长度校验
77
+ if (rule.min && String(value).length < rule.min) {
78
+ errorMessage = rule.message || `${field} 长度不能少于 ${rule.min} 个字符`
79
+ isValid = false
80
+ break
81
+ }
82
+
83
+ if (rule.max && String(value).length > rule.max) {
84
+ errorMessage = rule.message || `${field} 长度不能超过 ${rule.max} 个字符`
85
+ isValid = false
86
+ break
87
+ }
88
+
89
+ // 类型校验
90
+ if (rule.type === 'phone') {
91
+ const phoneRegex = /^1[3-9]\d{9}$/
92
+ if (!phoneRegex.test(String(value))) {
93
+ errorMessage = rule.message || '请输入正确的手机号'
94
+ isValid = false
95
+ break
96
+ }
97
+ }
98
+
99
+ if (rule.type === 'email') {
100
+ const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/
101
+ if (!emailRegex.test(String(value))) {
102
+ errorMessage = rule.message || '请输入正确的邮箱格式'
103
+ isValid = false
104
+ break
105
+ }
106
+ }
107
+
108
+ if (rule.type === 'password') {
109
+ const passwordRegex =
110
+ /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]).{8,}$/
111
+ if (!passwordRegex.test(String(value))) {
112
+ errorMessage = rule.message || '密码至少8个字符,包含大小写字母、数字和特殊符号'
113
+ isValid = false
114
+ break
115
+ }
116
+ }
117
+
118
+ // 自定义校验
119
+ if (rule.validator) {
120
+ const result = rule.validator(value)
121
+ if (result === false || typeof result === 'string') {
122
+ errorMessage =
123
+ typeof result === 'string' ? result : rule.message || `${field} 校验失败`
124
+ isValid = false
125
+ break
126
+ }
127
+ }
142
128
  }
143
- }
144
129
 
145
- if (rule.type === "password") {
146
- const passwordRegex =
147
- /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]).{8,}$/;
148
- if (!passwordRegex.test(String(value))) {
149
- errorMessage =
150
- rule.message || "密码至少8个字符,包含大小写字母、数字和特殊符号";
151
- isValid = false;
152
- break;
130
+ if (isValid) {
131
+ delete errors[field]
132
+ } else {
133
+ errors[field] = errorMessage
153
134
  }
154
- }
155
135
 
156
- // 自定义校验
157
- if (rule.validator) {
158
- const result = rule.validator(value);
159
- if (result === false || typeof result === "string") {
160
- errorMessage =
161
- typeof result === "string"
162
- ? result
163
- : rule.message || `${field} 校验失败`;
164
- isValid = false;
165
- break;
166
- }
167
- }
168
- }
169
-
170
- if (isValid) {
171
- delete errors[field];
172
- } else {
173
- errors[field] = errorMessage;
136
+ return isValid
137
+ },
138
+ setFieldValue: (field: string, value: any) => {
139
+ formData[field] = value
140
+ },
141
+ getFieldValue: (field: string) => {
142
+ return formData[field]
174
143
  }
175
-
176
- return isValid;
177
- },
178
- setFieldValue: (field: string, value: any) => {
179
- formData[field] = value;
180
- },
181
- getFieldValue: (field: string) => {
182
- return formData[field];
183
- },
184
- };
144
+ }
185
145
 
186
146
  // 提供表单上下文给子组件
187
- provide("formContext", formContext);
147
+ provide('formContext', formContext)
188
148
 
189
149
  // 验证所有字段
190
150
  const validate = () => {
191
- return new Promise((resolve, reject) => {
192
- let isValid = true;
193
- const allErrors: Record<string, string> = {};
194
-
195
- formItems.value.forEach((item) => {
196
- const field = item.props?.prop;
197
- if (field) {
198
- const value = formData[field];
199
- const fieldValid = formContext.validateField(field, value);
200
- if (!fieldValid) {
201
- isValid = false;
202
- allErrors[field] = errors[field];
151
+ return new Promise((resolve, reject) => {
152
+ let isValid = true
153
+ const allErrors: Record<string, string> = {}
154
+
155
+ formItems.value.forEach((item) => {
156
+ const field = item.props?.prop
157
+ if (field) {
158
+ const value = formData[field]
159
+ const fieldValid = formContext.validateField(field, value)
160
+ if (!fieldValid) {
161
+ isValid = false
162
+ allErrors[field] = errors[field]
163
+ }
164
+ }
165
+ })
166
+
167
+ emit('validate', isValid, allErrors)
168
+ if (isValid) {
169
+ resolve(isValid)
170
+ } else {
171
+ reject(allErrors)
203
172
  }
204
- }
205
- });
206
-
207
- emit("validate", isValid, allErrors);
208
- if (isValid) {
209
- resolve(isValid);
210
- } else {
211
- reject(allErrors);
212
- }
213
- });
214
- };
173
+ })
174
+ }
215
175
 
216
176
  // 重置表单
217
177
  const resetFields = () => {
218
- clearVal(formData);
219
- Object.keys(errors).forEach((key) => {
220
- delete errors[key];
221
- });
222
- };
178
+ clearVal(formData)
179
+ Object.keys(errors).forEach((key) => {
180
+ delete errors[key]
181
+ })
182
+ }
223
183
 
224
184
  // 清除验证
225
185
  const clearValidate = (fields?: string[]) => {
226
- if (fields) {
227
- fields.forEach((field) => {
228
- delete errors[field];
229
- });
230
- } else {
231
- Object.keys(errors).forEach((key) => {
232
- delete errors[key];
233
- });
234
- }
235
- };
186
+ if (fields) {
187
+ fields.forEach((field) => {
188
+ delete errors[field]
189
+ })
190
+ } else {
191
+ Object.keys(errors).forEach((key) => {
192
+ delete errors[key]
193
+ })
194
+ }
195
+ }
236
196
 
237
197
  // 提交表单
238
198
  const submit = async () => {
239
- if (await validate()) {
240
- emit("submit", { ...formData });
241
- return formData;
242
- }
243
- return false;
244
- };
199
+ if (await validate()) {
200
+ emit('submit', { ...formData })
201
+ return formData
202
+ }
203
+ return false
204
+ }
245
205
 
246
206
  defineExpose({
247
- validate,
248
- resetFields,
249
- clearValidate,
250
- submit,
251
- formData,
252
- errors,
253
- });
207
+ validate,
208
+ resetFields,
209
+ clearValidate,
210
+ submit,
211
+ formData,
212
+ errors
213
+ })
254
214
  </script>
255
215
 
256
216
  <style lang="scss" scoped>
257
217
  .hy-form {
258
- width: 100%;
218
+ width: 100%;
259
219
  }
260
220
  </style>
@@ -0,0 +1,37 @@
1
+ import type { PropType } from 'vue'
2
+ import type { FormItemRule } from './typing'
3
+
4
+ const formProps = {
5
+ /** 表单数据对象 */
6
+ model: Object as PropType<AnyObject>,
7
+ /** 表单校验规则 */
8
+ rules: Object as PropType<FormItemRule>,
9
+ /** 表单底部边框 */
10
+ border: {
11
+ type: Boolean,
12
+ default: false
13
+ },
14
+ /** label标签的宽度,单位rpx */
15
+ labelWidth: {
16
+ type: String,
17
+ default: 'auto'
18
+ },
19
+ /**
20
+ * 标签位置
21
+ * @values left,top
22
+ * */
23
+ labelPosition: {
24
+ type: String as PropType<HyApp.LabelPosition>,
25
+ default: 'left'
26
+ },
27
+ /**
28
+ * 标签位置
29
+ * @values left,center,right
30
+ * */
31
+ labelAlign: {
32
+ type: String as PropType<HyApp.ColumnCenterType>,
33
+ default: 'left'
34
+ }
35
+ }
36
+
37
+ export default formProps