hy-app 0.1.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.
Files changed (206) hide show
  1. package/README.md +42 -0
  2. package/api/http.ts +138 -0
  3. package/api/index.ts +1 -0
  4. package/common/index.ts +1 -0
  5. package/common/versionControl.ts +102 -0
  6. package/components/dialog/TheDialog.vue +128 -0
  7. package/components/dialog/index.ts +38 -0
  8. package/components/hy-address-picker/hy-address-picker.vue +262 -0
  9. package/components/hy-address-picker/props.ts +27 -0
  10. package/components/hy-address-picker/typing.d.ts +98 -0
  11. package/components/hy-avatar/hy-avatar.vue +217 -0
  12. package/components/hy-avatar/props.ts +20 -0
  13. package/components/hy-avatar/typing.d.ts +64 -0
  14. package/components/hy-back-top/hy-back-top.vue +71 -0
  15. package/components/hy-back-top/props.ts +23 -0
  16. package/components/hy-back-top/typing.d.ts +49 -0
  17. package/components/hy-badge/hy-badge.vue +155 -0
  18. package/components/hy-badge/props.ts +19 -0
  19. package/components/hy-badge/typing.d.ts +60 -0
  20. package/components/hy-button/hy-button.vue +394 -0
  21. package/components/hy-button/props.ts +36 -0
  22. package/components/hy-button/typing.d.ts +125 -0
  23. package/components/hy-card/hy-card.vue +198 -0
  24. package/components/hy-card/props.ts +29 -0
  25. package/components/hy-card/typing.d.ts +112 -0
  26. package/components/hy-cell/hy-cell.vue +268 -0
  27. package/components/hy-cell/props.ts +20 -0
  28. package/components/hy-cell/typing.d.ts +98 -0
  29. package/components/hy-check-button/hy-check-button.vue +71 -0
  30. package/components/hy-check-button/props.ts +20 -0
  31. package/components/hy-check-button/typing.d.ts +79 -0
  32. package/components/hy-checkbox/hy-checkbox.vue +299 -0
  33. package/components/hy-checkbox/props.ts +28 -0
  34. package/components/hy-checkbox/typing.d.ts +77 -0
  35. package/components/hy-datetime-picker/hy-datetime-picker.vue +584 -0
  36. package/components/hy-datetime-picker/props.ts +36 -0
  37. package/components/hy-datetime-picker/typing.d.ts +135 -0
  38. package/components/hy-divider/hy-divider.vue +164 -0
  39. package/components/hy-divider/props.ts +21 -0
  40. package/components/hy-divider/typing.d.ts +64 -0
  41. package/components/hy-empty/hy-empty.vue +122 -0
  42. package/components/hy-empty/props.ts +21 -0
  43. package/components/hy-empty/typing.d.ts +68 -0
  44. package/components/hy-folding-panel/hy-folding-panel.vue +94 -0
  45. package/components/hy-folding-panel/props.ts +17 -0
  46. package/components/hy-folding-panel/typing.d.ts +59 -0
  47. package/components/hy-form/hy-form.vue +372 -0
  48. package/components/hy-form/props.ts +15 -0
  49. package/components/hy-form/typing.d.ts +51 -0
  50. package/components/hy-grid/hy-grid.vue +126 -0
  51. package/components/hy-grid/props.ts +16 -0
  52. package/components/hy-grid/typing.d.ts +62 -0
  53. package/components/hy-icon/hy-icon.vue +207 -0
  54. package/components/hy-icon/props.ts +24 -0
  55. package/components/hy-icon/typing.d.ts +80 -0
  56. package/components/hy-input/hy-input.vue +402 -0
  57. package/components/hy-input/props.ts +41 -0
  58. package/components/hy-input/typing.d.ts +148 -0
  59. package/components/hy-line/hy-line.vue +44 -0
  60. package/components/hy-line/props.ts +12 -0
  61. package/components/hy-line/typing.d.ts +32 -0
  62. package/components/hy-line-progress/hy-line-progress.vue +118 -0
  63. package/components/hy-line-progress/props.ts +12 -0
  64. package/components/hy-line-progress/typing.d.ts +28 -0
  65. package/components/hy-list/hy-list.vue +250 -0
  66. package/components/hy-list/props.ts +18 -0
  67. package/components/hy-list/typing.d.ts +50 -0
  68. package/components/hy-login/ThePhoneLogin.vue +106 -0
  69. package/components/hy-login/TheUserLogin.vue +391 -0
  70. package/components/hy-login/hy-login.vue +283 -0
  71. package/components/hy-login/props.ts +32 -0
  72. package/components/hy-login/typing.d.ts +60 -0
  73. package/components/hy-modal/hy-modal.vue +240 -0
  74. package/components/hy-modal/props.ts +24 -0
  75. package/components/hy-modal/typing.d.ts +70 -0
  76. package/components/hy-navbar/hy-navbar.vue +194 -0
  77. package/components/hy-navbar/props.ts +24 -0
  78. package/components/hy-navbar/typing.d.ts +81 -0
  79. package/components/hy-notice-bar/hy-column-notice.vue +130 -0
  80. package/components/hy-notice-bar/hy-notice-bar.vue +82 -0
  81. package/components/hy-notice-bar/hy-row-notice.vue +182 -0
  82. package/components/hy-notice-bar/props.ts +19 -0
  83. package/components/hy-notice-bar/typing.d.ts +56 -0
  84. package/components/hy-number-step/hy-number-step.vue +428 -0
  85. package/components/hy-number-step/props.ts +29 -0
  86. package/components/hy-number-step/typing.d.ts +104 -0
  87. package/components/hy-overlay/hy-overlay.vue +54 -0
  88. package/components/hy-overlay/props.ts +10 -0
  89. package/components/hy-overlay/typing.d.ts +24 -0
  90. package/components/hy-picker/hy-picker.vue +499 -0
  91. package/components/hy-picker/props.ts +30 -0
  92. package/components/hy-picker/typing.d.ts +115 -0
  93. package/components/hy-popup/hy-popup.vue +269 -0
  94. package/components/hy-popup/props.ts +21 -0
  95. package/components/hy-popup/typing.d.ts +68 -0
  96. package/components/hy-price/hy-price.vue +86 -0
  97. package/components/hy-price/props.ts +13 -0
  98. package/components/hy-price/typing.d.ts +36 -0
  99. package/components/hy-qrcode/hy-qrcode.vue +153 -0
  100. package/components/hy-qrcode/props.ts +20 -0
  101. package/components/hy-qrcode/qrcode.js +1364 -0
  102. package/components/hy-qrcode/typing.d.ts +64 -0
  103. package/components/hy-radio/hy-radio.vue +319 -0
  104. package/components/hy-radio/props.ts +28 -0
  105. package/components/hy-radio/typing.d.ts +85 -0
  106. package/components/hy-rate/hy-rate.vue +261 -0
  107. package/components/hy-rate/props.ts +18 -0
  108. package/components/hy-rate/typing.d.ts +60 -0
  109. package/components/hy-read-more/hy-read-more.vue +134 -0
  110. package/components/hy-read-more/props.ts +20 -0
  111. package/components/hy-read-more/typing.d.ts +44 -0
  112. package/components/hy-safe-bottom/hy-safe-bottom.vue +64 -0
  113. package/components/hy-scroll-list/hy-scroll-list.vue +146 -0
  114. package/components/hy-scroll-list/props.ts +12 -0
  115. package/components/hy-scroll-list/typing.d.ts +28 -0
  116. package/components/hy-search/hy-search.vue +294 -0
  117. package/components/hy-search/props.ts +29 -0
  118. package/components/hy-search/typing.d.ts +109 -0
  119. package/components/hy-slider/hy-slider.vue +511 -0
  120. package/components/hy-slider/props.ts +21 -0
  121. package/components/hy-slider/typing.d.ts +68 -0
  122. package/components/hy-steps/hy-steps.vue +352 -0
  123. package/components/hy-steps/props.ts +15 -0
  124. package/components/hy-steps/typing.d.ts +58 -0
  125. package/components/hy-subsection/hy-subsection.vue +272 -0
  126. package/components/hy-subsection/props.ts +16 -0
  127. package/components/hy-subsection/typing.d.ts +44 -0
  128. package/components/hy-swiper/hy-swiper-indicator.vue +105 -0
  129. package/components/hy-swiper/hy-swiper.vue +242 -0
  130. package/components/hy-swiper/props.ts +30 -0
  131. package/components/hy-swiper/typing.d.ts +107 -0
  132. package/components/hy-switch/hy-switch.vue +168 -0
  133. package/components/hy-switch/props.ts +16 -0
  134. package/components/hy-switch/typing.d.ts +48 -0
  135. package/components/hy-tabs/hy-tabs.vue +416 -0
  136. package/components/hy-tabs/props.ts +26 -0
  137. package/components/hy-tabs/typing.d.ts +86 -0
  138. package/components/hy-tag/hy-tag.vue +374 -0
  139. package/components/hy-tag/props.ts +22 -0
  140. package/components/hy-tag/typing.d.ts +76 -0
  141. package/components/hy-textarea/hy-textarea.vue +229 -0
  142. package/components/hy-textarea/props.ts +26 -0
  143. package/components/hy-textarea/typing.d.ts +27 -0
  144. package/components/hy-tooltip/hy-tooltip.vue +332 -0
  145. package/components/hy-tooltip/props.ts +17 -0
  146. package/components/hy-tooltip/typing.d.ts +52 -0
  147. package/components/hy-transition/hy-transition.vue +150 -0
  148. package/components/hy-transition/index.scss +113 -0
  149. package/components/hy-transition/props.ts +10 -0
  150. package/components/hy-transition/typing.d.ts +36 -0
  151. package/components/hy-upload/hy-upload.vue +557 -0
  152. package/components/hy-upload/props.ts +29 -0
  153. package/components/hy-upload/typing.d.ts +147 -0
  154. package/components/hy-warn/hy-warn.vue +228 -0
  155. package/components/hy-warn/props.ts +14 -0
  156. package/components/hy-warn/typing.d.ts +40 -0
  157. package/components/hy-waterfall/hy-waterfall.vue +51 -0
  158. package/components/hy-waterfall/props.ts +10 -0
  159. package/components/hy-waterfall/typing.d.ts +20 -0
  160. package/components/index.ts +162 -0
  161. package/components/message/TheMessage.vue +169 -0
  162. package/components/message/index.ts +54 -0
  163. package/components/u-form/form.js +22 -0
  164. package/components/u-form/hy-form.vue +324 -0
  165. package/components/u-form/props.js +49 -0
  166. package/components/u-form/schema.js +1451 -0
  167. package/components/u-form/u-form.vue +267 -0
  168. package/components/u-form/utils.js +65 -0
  169. package/components/u-form-item/formItem.js +24 -0
  170. package/components/u-form-item/hy-form-item.vue +360 -0
  171. package/components/u-form-item/props.js +57 -0
  172. package/components/u-form-item/u-form-item.vue +294 -0
  173. package/components/yk-dialog/yk-dialog.vue +129 -0
  174. package/components/yk-tabbar/props.ts +49 -0
  175. package/components/yk-tabbar/yk-tabbar.vue +224 -0
  176. package/config/color.ts +6 -0
  177. package/config/icon.ts +366 -0
  178. package/config/index.ts +2 -0
  179. package/global/index.ts +6 -0
  180. package/global/register-properties.ts +37 -0
  181. package/index.ts +8 -0
  182. package/libs/css/common.scss +0 -0
  183. package/libs/css/iconfont.css +379 -0
  184. package/libs/css/iconfont.ttf +0 -0
  185. package/libs/css/mixin.scss +15 -0
  186. package/package.json +42 -0
  187. package/public/icons/error.png +0 -0
  188. package/public/icons/success.png +0 -0
  189. package/public/icons/warning.png +0 -0
  190. package/store/index.ts +1 -0
  191. package/store/userInfo.ts +25 -0
  192. package/theme.scss +94 -0
  193. package/typing/index.ts +7 -0
  194. package/typing/modules/common.d.ts +50 -0
  195. package/typing/modules/dialog.ts +17 -0
  196. package/typing/modules/enum.ts +67 -0
  197. package/typing/modules/form.ts +161 -0
  198. package/typing/modules/http.ts +68 -0
  199. package/typing/modules/icon.d.ts +366 -0
  200. package/typing/modules/img.ts +15 -0
  201. package/typing/modules/rect.ts +10 -0
  202. package/utils/address.json +5890 -0
  203. package/utils/base64.ts +119 -0
  204. package/utils/index.ts +3 -0
  205. package/utils/inside.ts +310 -0
  206. package/utils/utils.ts +446 -0
@@ -0,0 +1,169 @@
1
+ <template>
2
+ <Transition name="fade">
3
+ <view class="dialog dialog-shade" v-if="show">
4
+ <view class="dialog-container" v-if="show">
5
+ <image class="dialog-container__icon" :src="param.icon"></image>
6
+ <view class="dialog-container__title">{{ param.title }}</view>
7
+ <view class="dialog-container__content">{{ param.content }}</view>
8
+
9
+ <view class="dialog-container__btn">
10
+ <u-button
11
+ v-if="param.showCancel"
12
+ :text="param.cancelText"
13
+ :color="param.cancelColor"
14
+ :shape="param.shape"
15
+ size="large"
16
+ @click="result(false)"
17
+ ></u-button>
18
+ <u-button
19
+ :text="param.confirmText"
20
+ :color="param.confirmColor"
21
+ :shape="param.shape"
22
+ size="large"
23
+ @click="result(true)"
24
+ ></u-button>
25
+ </view>
26
+ </view>
27
+ </view>
28
+ </Transition>
29
+ </template>
30
+
31
+ <script lang="ts" setup>
32
+ import { ref, toRefs } from "vue";
33
+ import DialogService from "./index";
34
+ /**
35
+ * @用途
36
+ * @author Pino
37
+ * @创建时间 2023-01-11 15:19
38
+ **/
39
+
40
+ export interface DialogParam {
41
+ icon?: string;
42
+ title?: string;
43
+ content?: string;
44
+ confirmText?: string;
45
+ cancelText?: string;
46
+ shape?: "circle" | "square";
47
+ confirmColor?: string;
48
+ cancelColor?: string;
49
+ showCancel?: boolean;
50
+ result?: Function; // 回调用户操作结果
51
+ }
52
+ // const props = withDefaults(defineProps<DialogParam>(), {
53
+ // icon: "https://pic1.imgdb.cn/item/67a74cbdd0e0a243d4fd160b.png",
54
+ // title: "提示",
55
+ // content: "",
56
+ // confirmText: "确认",
57
+ // cancelText: "取消",
58
+ // shape: "circle",
59
+ // confirmColor: "#906FFE",
60
+ // cancelColor: "",
61
+ // showCancel: false,
62
+ // result: () => {}
63
+ // });
64
+ const show = ref(false);
65
+ const param = ref<DialogParam>({
66
+ icon: "https://pic1.imgdb.cn/item/67a74cbdd0e0a243d4fd160b.png",
67
+ title: "提示",
68
+ content: "",
69
+ confirmText: "确认",
70
+ cancelText: "取消",
71
+ shape: "circle",
72
+ confirmColor: "#906FFE",
73
+ cancelColor: "",
74
+ showCancel: false,
75
+ result: () => {}
76
+ });
77
+
78
+ const open = (options: DialogParam) => {
79
+ show.value = true;
80
+ param.value = Object.assign(param.value, options);
81
+ };
82
+
83
+ const close = () => {
84
+ show.value = false;
85
+ DialogService.close();
86
+ };
87
+
88
+ const result = (isSure: boolean) => {
89
+ if (param.value.result) {
90
+ param.value.result({
91
+ confirm: isSure,
92
+ cancel: !isSure
93
+ });
94
+ }
95
+ close();
96
+ };
97
+
98
+ defineExpose({ open, close }); // 暴露方法供外部调用
99
+ </script>
100
+
101
+ <style lang="scss" scoped>
102
+ /* Vue Transition */
103
+ .fade-enter-active,
104
+ .fade-leave-active {
105
+ transition: opacity 0.3s ease;
106
+ }
107
+
108
+ .fade-enter-from,
109
+ .fade-leave-to {
110
+ opacity: 0;
111
+ }
112
+ .dialog {
113
+ position: fixed;
114
+ z-index: 999999;
115
+ &-shade {
116
+ top: 0;
117
+ width: 100%;
118
+ height: 100%;
119
+ background: rgba(0, 0, 0, 0.5);
120
+ }
121
+ &-container {
122
+ position: absolute;
123
+ transform: translate(-50%, -50%);
124
+ left: 50%;
125
+ top: 50%;
126
+ border-radius: 40px;
127
+ background: #ffffff;
128
+ width: 90%;
129
+ padding: 40px 20px;
130
+ text-align: center;
131
+ animation: slideIn 0.4s ease;
132
+ @keyframes slideIn {
133
+ from {
134
+ transform: translate(-50%, 50%);
135
+ opacity: 0;
136
+ }
137
+ to {
138
+ transform: translate(-50%, -50%);
139
+ opacity: 1;
140
+ }
141
+ }
142
+
143
+ &__icon {
144
+ width: 140px;
145
+ height: 140px;
146
+ position: absolute;
147
+ top: -110px;
148
+ left: 50%;
149
+ transform: translateX(-50%);
150
+ }
151
+
152
+ &__title {
153
+ margin: 20px 0;
154
+ font-size: 50rpx;
155
+ }
156
+ &__content {
157
+ margin: 20px 0;
158
+ font-size: 30rpx;
159
+ color: #c3d8db;
160
+ }
161
+ &__btn {
162
+ display: flex;
163
+ .u-button {
164
+ margin: 30px 10px 20px;
165
+ }
166
+ }
167
+ }
168
+ }
169
+ </style>
@@ -0,0 +1,54 @@
1
+ import { createVNode, render } from "vue";
2
+ import Dialog, { DialogParam } from "./TheMessage.vue";
3
+
4
+ let instance: any = null;
5
+
6
+ const successIcon = "https://pic1.imgdb.cn/item/67a74cbdd0e0a243d4fd160b.png";
7
+ const errorIcon = "https://pic1.imgdb.cn/item/67b03ba3d0e0a243d4ff9078.png";
8
+ const warningIcon = "https://pic1.imgdb.cn/item/67b03ba3d0e0a243d4ff9079.png";
9
+ /**
10
+ * @description 创建div添加dialog组件
11
+ * */
12
+ const mountDialog = () => {
13
+ if (!instance) {
14
+ const container = document.createElement("div");
15
+ document.body.appendChild(container); // 先添加到 body
16
+ instance = createVNode(Dialog);
17
+ render(instance, container);
18
+ }
19
+ };
20
+ /**
21
+ * @description 打开传参
22
+ * */
23
+ const openParams = (options: DialogParam, icon: string) => {
24
+ instance.component.exposed.open(
25
+ Object.assign(
26
+ {
27
+ icon
28
+ },
29
+ options
30
+ )
31
+ );
32
+ };
33
+
34
+ const DialogService = {
35
+ success(options: DialogParam) {
36
+ mountDialog();
37
+ openParams(options, successIcon);
38
+ },
39
+ error(options: DialogParam) {
40
+ mountDialog();
41
+ openParams(options, errorIcon);
42
+ },
43
+ warning(options: DialogParam) {
44
+ mountDialog();
45
+ openParams(options, warningIcon);
46
+ },
47
+ close() {
48
+ if (instance) {
49
+ instance.component.exposed.close();
50
+ }
51
+ }
52
+ };
53
+
54
+ export default DialogService;
@@ -0,0 +1,22 @@
1
+ /*
2
+ * @Author : LQ
3
+ * @Description :
4
+ * @version : 1.0
5
+ * @Date : 2021-08-20 16:44:21
6
+ * @LastAuthor : LQ
7
+ * @lastTime : 2021-08-20 17:03:49
8
+ * @FilePath : /u-view2.0/uview-ui/libs/config/props/form.js
9
+ */
10
+ export default {
11
+ // form 组件
12
+ form: {
13
+ model: {},
14
+ rules: {},
15
+ errorType: 'message',
16
+ borderBottom: true,
17
+ labelPosition: 'left',
18
+ labelWidth: 45,
19
+ labelAlign: 'left',
20
+ labelStyle: {}
21
+ }
22
+ }
@@ -0,0 +1,324 @@
1
+ <template>
2
+ <view class="u-form">
3
+ <slot />
4
+ </view>
5
+ </template>
6
+
7
+ <script setup>
8
+ // import { props } from "./props.js";
9
+ import Schema from "./schema";
10
+ import { getProperty, setProperty } from "./utils";
11
+ import { deepClone, error } from "../../utils";
12
+ import {
13
+ ref,
14
+ defineProps,
15
+ computed,
16
+ onMounted,
17
+ watch,
18
+ nextTick,
19
+ inject
20
+ } from "vue";
21
+
22
+ // 去除警告信息
23
+ Schema.warning = function () {};
24
+
25
+ /**
26
+ * Form 表单
27
+ * @description 此组件一般用于表单场景,可以配置Input输入框,Select弹出框,进行表单验证等。
28
+ * @tutorial https://ijry.github.io/uview-plus/components/form.html
29
+ * @property {Object} model 当前form的需要验证字段的集合
30
+ * @property {Object | Function | Array} rules 验证规则
31
+ * @property {String} errorType 错误的提示方式,见上方说明 ( 默认 message )
32
+ * @property {Boolean} borderBottom 是否显示表单域的下划线边框 ( 默认 true )
33
+ * @property {String} labelPosition 表单域提示文字的位置,left-左侧,top-上方 ( 默认 'left' )
34
+ * @property {String | Number} labelWidth 提示文字的宽度,单位px ( 默认 45 )
35
+ * @property {String} labelAlign lable字体的对齐方式 ( 默认 ‘left' )
36
+ * @property {Object} labelStyle lable的样式,对象形式
37
+ * @example <up-formlabelPosition="left" :model="model1" :rules="rules" ref="form1"></up-form>
38
+ */
39
+
40
+ import defProps from "./form";
41
+ const props = defineProps({
42
+ // 当前form的需要验证字段的集合
43
+ model: {
44
+ type: Object,
45
+ default: () => defProps.form.model
46
+ },
47
+ // 验证规则
48
+ rules: {
49
+ type: [Object, Function, Array],
50
+ default: () => defProps.form.rules
51
+ },
52
+ // 有错误时的提示方式,message-提示信息,toast-进行toast提示
53
+ // border-bottom-下边框呈现红色,none-无提示
54
+ errorType: {
55
+ type: String,
56
+ default: () => defProps.form.errorType
57
+ },
58
+ // 是否显示表单域的下划线边框
59
+ borderBottom: {
60
+ type: Boolean,
61
+ default: () => defProps.form.borderBottom
62
+ },
63
+ // label的位置,left-左边,top-上边
64
+ labelPosition: {
65
+ type: String,
66
+ default: () => defProps.form.labelPosition
67
+ },
68
+ // label的宽度,单位px
69
+ labelWidth: {
70
+ type: [String, Number],
71
+ default: () => defProps.form.labelWidth
72
+ },
73
+ // lable字体的对齐方式
74
+ labelAlign: {
75
+ type: String,
76
+ default: () => defProps.form.labelAlign
77
+ },
78
+ // lable的样式,对象形式
79
+ labelStyle: {
80
+ type: Object,
81
+ default: () => defProps.form.labelStyle
82
+ }
83
+ });
84
+
85
+ // 响应式数据
86
+ const formRules = ref({});
87
+ const validator = ref(null);
88
+ const originalModel = ref(null);
89
+ const children = ref([]);
90
+
91
+ const formItemRef = inject("formItemRef");
92
+
93
+ // 手动设置校验的规则,如果规则中有函数的话,微信小程序中会过滤掉,所以只能手动调用设置规则
94
+ const setRules = (rules) => {
95
+ // 判断是否有规则
96
+ if (Object.keys(rules).length === 0) return;
97
+ if (
98
+ process.env.NODE_ENV === "development" &&
99
+ Object.keys(props.model).length === 0
100
+ ) {
101
+ error("设置rules,model必须设置!如果已经设置,请刷新页面。");
102
+ return;
103
+ }
104
+ formRules.value = rules;
105
+ // 重新将规则赋予Validator
106
+ validator.value = new Schema(rules);
107
+ };
108
+
109
+ // 监听规则的变化
110
+ watch(
111
+ () => props.rules,
112
+ (n) => {
113
+ setRules(n);
114
+ },
115
+ { immediate: true }
116
+ );
117
+
118
+ // 监听属性的变化,通知子组件u-form-item重新获取信息
119
+ const propsChange = computed(() => {
120
+ return [
121
+ props.errorType,
122
+ props.borderBottom,
123
+ props.labelPosition,
124
+ props.labelWidth,
125
+ props.labelAlign,
126
+ props.labelStyle
127
+ ];
128
+ });
129
+
130
+ watch(propsChange.value, (n) => {
131
+ if (children.value?.length) {
132
+ children.value.forEach((child) => {
133
+ // 判断子组件(u-form-item)如果有updateParentData方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
134
+ typeof child.updateParentData === "function" && child.updateParentData();
135
+ });
136
+ }
137
+ });
138
+
139
+ // 监听model的初始值作为重置表单的快照
140
+ watch(
141
+ () => props.model,
142
+ (n) => {
143
+ if (!originalModel.value) {
144
+ originalModel.value = deepClone(n);
145
+ }
146
+ },
147
+ { immediate: true }
148
+ );
149
+
150
+ // 清空所有u-form-item组件的内容,本质上是调用了u-form-item组件中的resetField()方法
151
+ const resetFields = () => {
152
+ resetModel();
153
+ };
154
+
155
+ // 重置model为初始值的快照
156
+ const resetModel = (obj) => {
157
+ // 历遍所有u-form-item,根据其prop属性,还原model的原始快照
158
+ children.value.forEach((child) => {
159
+ const prop = child?.prop;
160
+ const value = getProperty(originalModel.value, prop);
161
+ setProperty(props.model, prop, value);
162
+ });
163
+ };
164
+
165
+ // 清空校验结果
166
+ const clearValidate = (props) => {
167
+ props = [].concat(props);
168
+ formItemRef.children.forEach((child) => {
169
+ // 如果u-form-item的prop在props数组中,则清除对应的校验结果信息
170
+ if (props[0] === undefined || props.includes(child.prop)) {
171
+ child.message = null;
172
+ }
173
+ });
174
+ };
175
+
176
+ // 对部分表单字段进行校验
177
+ const validateField = async (value, callback, event = null, options) => {
178
+ // $nextTick是必须的,否则model的变更,可能会延后于此方法的执行
179
+ await nextTick();
180
+ // 校验错误信息,返回给回调方法,用于存放所有form-item的错误信息
181
+ const errorsRes = [];
182
+ // 如果为字符串,转为数组
183
+ value = [].concat(value);
184
+ // 历遍children所有子form-item
185
+ const promises = formItemRef.children.map((child) => {
186
+ return new Promise((resolve, reject) => {
187
+ // 用于存放form-item的错误信息
188
+ const childErrors = [];
189
+ if (value.includes(child.prop)) {
190
+ // 获取对应的属性,通过类似'a.b.c'的形式
191
+ const propertyVal = getProperty(props.model, child.prop);
192
+ // 属性链数组
193
+ const propertyChain = child.prop.split(".");
194
+ const propertyName = propertyChain[propertyChain.length - 1];
195
+
196
+ let rule = [];
197
+ if (child.itemRules && child.itemRules.length > 0) {
198
+ rule = child.itemRules;
199
+ } else {
200
+ rule = formRules.value[child.prop];
201
+ }
202
+ // 如果不存在对应的规则,直接返回,否则校验器会报错
203
+ if (!rule) {
204
+ resolve();
205
+ return;
206
+ }
207
+ // rule规则可为数组形式,也可为对象形式,此处拼接成为数组
208
+ const rules = [].concat(rule);
209
+
210
+ // 对rules数组进行校验
211
+ if (!rules.length) {
212
+ resolve();
213
+ }
214
+ for (let i = 0; i < rules.length; i++) {
215
+ const ruleItem = rules[i];
216
+ // 将u-form-item的触发器转为数组形式
217
+ const trigger = [].concat(ruleItem?.trigger);
218
+ // 如果是有传入触发事件,但是此form-item却没有配置此触发器的话,不执行校验操作
219
+ if (event && !trigger.includes(event)) {
220
+ resolve();
221
+ continue;
222
+ }
223
+ // 实例化校验对象,传入构造规则
224
+ const validator = new Schema({
225
+ [propertyName]: ruleItem
226
+ });
227
+ validator.validate(
228
+ {
229
+ [propertyName]: propertyVal
230
+ },
231
+ (errors, fields) => {
232
+ if (Array.isArray(errors)) {
233
+ errors.forEach((element) => {
234
+ element.prop = child.prop;
235
+ });
236
+ errorsRes.push(...errors);
237
+ childErrors.push(...errors);
238
+ }
239
+ //没有配置,或者配置了showErrorMsg为true时候,才修改子组件message,默认没有配置
240
+ if (!options || options?.showErrorMsg === true) {
241
+ child.message = childErrors[0]?.message
242
+ ? childErrors[0].message
243
+ : null;
244
+ }
245
+ if (i === rules.length - 1) {
246
+ resolve(errorsRes);
247
+ }
248
+ }
249
+ );
250
+ }
251
+ } else {
252
+ resolve({});
253
+ }
254
+ });
255
+ });
256
+
257
+ // 使用Promise.all来等待所有Promise完成
258
+ Promise.all(promises)
259
+ .then((results) => {
260
+ // 执行回调函数
261
+ typeof callback === "function" && callback(errorsRes);
262
+ })
263
+ .catch((error) => {
264
+ console.error("An error occurred:", error);
265
+ });
266
+ };
267
+
268
+ // 校验全部数据
269
+ const validate = (options) => {
270
+ // 开发环境才提示,生产环境不会提示
271
+ if (
272
+ process.env.NODE_ENV === "development" &&
273
+ Object.keys(formRules.value).length === 0
274
+ ) {
275
+ error("未设置rules,请看文档说明!如果已经设置,请刷新页面。");
276
+ return;
277
+ }
278
+ return new Promise((resolve, reject) => {
279
+ console.log(formItemRef);
280
+ // $nextTick是必须的,否则model的变更,可能会延后于validate方法
281
+ nextTick(() => {
282
+ // 获取所有form-item的prop,交给validateField方法进行校验
283
+ const formItemProps = formItemRef.children.map((item) => item.prop);
284
+ // console.log(formItemProps)
285
+ validateField(
286
+ formItemProps,
287
+ (errors) => {
288
+ if (errors.length) {
289
+ // 如果错误提示方式为toast,则进行提示
290
+ props.errorType === "toast" &&
291
+ uni.showToast({
292
+ title: String(errors[0].message),
293
+ icon: "none"
294
+ });
295
+ reject(errors);
296
+ } else {
297
+ resolve(true);
298
+ }
299
+ },
300
+ null,
301
+ options
302
+ );
303
+ });
304
+ });
305
+ };
306
+
307
+ // 存储当前form下的所有u-form-item的实例
308
+ // 不能定义在data中,否则微信小程序会造成循环引用而报错
309
+ onMounted(() => {
310
+ children.value = [];
311
+ });
312
+
313
+ // 提供给子组件使用
314
+ defineExpose({
315
+ setRules,
316
+ resetFields,
317
+ resetModel,
318
+ clearValidate,
319
+ validateField,
320
+ validate
321
+ });
322
+ </script>
323
+
324
+ <style lang="scss" scoped></style>
@@ -0,0 +1,49 @@
1
+ export const defineMixin = (options) => {
2
+ return options;
3
+ };
4
+ import defProps from "./form";
5
+ export const props = defineMixin({
6
+ props: {
7
+ // 当前form的需要验证字段的集合
8
+ model: {
9
+ type: Object,
10
+ default: () => defProps.form.model
11
+ },
12
+ // 验证规则
13
+ rules: {
14
+ type: [Object, Function, Array],
15
+ default: () => defProps.form.rules
16
+ },
17
+ // 有错误时的提示方式,message-提示信息,toast-进行toast提示
18
+ // border-bottom-下边框呈现红色,none-无提示
19
+ errorType: {
20
+ type: String,
21
+ default: () => defProps.form.errorType
22
+ },
23
+ // 是否显示表单域的下划线边框
24
+ borderBottom: {
25
+ type: Boolean,
26
+ default: () => defProps.form.borderBottom
27
+ },
28
+ // label的位置,left-左边,top-上边
29
+ labelPosition: {
30
+ type: String,
31
+ default: () => defProps.form.labelPosition
32
+ },
33
+ // label的宽度,单位px
34
+ labelWidth: {
35
+ type: [String, Number],
36
+ default: () => defProps.form.labelWidth
37
+ },
38
+ // lable字体的对齐方式
39
+ labelAlign: {
40
+ type: String,
41
+ default: () => defProps.form.labelAlign
42
+ },
43
+ // lable的样式,对象形式
44
+ labelStyle: {
45
+ type: Object,
46
+ default: () => defProps.form.labelStyle
47
+ }
48
+ }
49
+ });