hy-app 0.3.14 → 0.3.16
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.
- package/components/hy-checkbox-group/hy-checkbox-group.vue +6 -4
- package/components/hy-checkbox-item/hy-checkbox-item.vue +47 -24
- package/components/hy-checkbox-item/typing.d.ts +3 -2
- package/components/hy-form/hy-form.vue +2 -7
- package/components/hy-form-item/hy-form-item.vue +204 -201
- package/components/hy-form-item/typing.d.ts +20 -14
- package/package.json +2 -2
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script setup lang="ts">
|
|
8
|
-
import { computed, provide } from "vue";
|
|
8
|
+
import { computed, provide, toRefs } from "vue";
|
|
9
9
|
import type { CSSProperties, PropType } from "vue";
|
|
10
10
|
import { bem } from "../../utils";
|
|
11
11
|
import type { ICheckBoxGroupEmits } from "./typing";
|
|
@@ -98,8 +98,8 @@ const bemClass = computed(() => {
|
|
|
98
98
|
return bem("checkbox-group", props, ["placement"]);
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
...props,
|
|
101
|
+
const context = {
|
|
102
|
+
...toRefs(props),
|
|
103
103
|
setCheckedStatus(value: string | number) {
|
|
104
104
|
let arr = [...props.modelValue];
|
|
105
105
|
if (props.modelValue?.includes(value)) {
|
|
@@ -110,7 +110,9 @@ provide("hy-checkbox-group", {
|
|
|
110
110
|
emit("update:modelValue", arr);
|
|
111
111
|
emit("change", arr);
|
|
112
112
|
},
|
|
113
|
-
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
provide("hy-checkbox-group", context);
|
|
114
116
|
</script>
|
|
115
117
|
|
|
116
118
|
<style lang="scss" scoped>
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
@tap.stop="wrapperClickHandler"
|
|
5
5
|
:style="checkboxStyle"
|
|
6
6
|
:class="[
|
|
7
|
-
`hy-checkbox--label__${checkboxGroup?.iconPlacement}`,
|
|
8
|
-
checkboxGroup?.borderBottom &&
|
|
9
|
-
checkboxGroup?.placement === 'column' &&
|
|
7
|
+
`hy-checkbox--label__${checkboxGroup?.iconPlacement?.value}`,
|
|
8
|
+
checkboxGroup?.borderBottom?.value &&
|
|
9
|
+
checkboxGroup?.placement?.value === 'column' &&
|
|
10
10
|
'hy-border__bottom',
|
|
11
11
|
]"
|
|
12
12
|
>
|
|
@@ -21,9 +21,12 @@
|
|
|
21
21
|
class="hy-checkbox--icon-wrap__icon"
|
|
22
22
|
:name="IconConfig.CHECK_MASK"
|
|
23
23
|
:size="
|
|
24
|
-
addUnit(
|
|
24
|
+
addUnit(
|
|
25
|
+
sizeType[checkboxGroup?.size?.value] ??
|
|
26
|
+
checkboxGroup?.iconSize?.value,
|
|
27
|
+
)
|
|
25
28
|
"
|
|
26
|
-
:color="checkboxGroup?.iconColor || '#ffffff'"
|
|
29
|
+
:color="checkboxGroup?.iconColor?.value || '#ffffff'"
|
|
27
30
|
/>
|
|
28
31
|
</slot>
|
|
29
32
|
</view>
|
|
@@ -38,9 +41,10 @@
|
|
|
38
41
|
<slot name="label">
|
|
39
42
|
<text
|
|
40
43
|
:style="{
|
|
41
|
-
color: checkboxGroup?.labelColor,
|
|
44
|
+
color: checkboxGroup?.labelColor?.value,
|
|
42
45
|
fontSize: addUnit(
|
|
43
|
-
sizeType[checkboxGroup?.size] ??
|
|
46
|
+
sizeType[checkboxGroup?.size?.value] ??
|
|
47
|
+
checkboxGroup?.labelSize?.value,
|
|
44
48
|
),
|
|
45
49
|
}"
|
|
46
50
|
>
|
|
@@ -67,7 +71,7 @@ import { computed, watch, ref, reactive, inject } from "vue";
|
|
|
67
71
|
import type { CSSProperties } from "vue";
|
|
68
72
|
import { addUnit, error } from "../../utils";
|
|
69
73
|
import { IconConfig } from "../../config";
|
|
70
|
-
import type {
|
|
74
|
+
import type { ICheckboxGroupContext } from "./typing";
|
|
71
75
|
// 组件
|
|
72
76
|
import HyIcon from "../hy-icon/hy-icon.vue";
|
|
73
77
|
|
|
@@ -101,7 +105,7 @@ const props = defineProps({
|
|
|
101
105
|
});
|
|
102
106
|
|
|
103
107
|
// 注入表单上下文
|
|
104
|
-
const checkboxGroup = inject<
|
|
108
|
+
const checkboxGroup = inject<ICheckboxGroupContext>("hy-checkbox-group");
|
|
105
109
|
const isChecked = ref(false);
|
|
106
110
|
const sizeType: AnyObject = reactive({
|
|
107
111
|
small: 14,
|
|
@@ -113,27 +117,44 @@ watch(
|
|
|
113
117
|
() => props.checked,
|
|
114
118
|
(newValue) => {
|
|
115
119
|
isChecked.value = newValue;
|
|
116
|
-
if (props.checked)
|
|
117
|
-
|
|
120
|
+
if (props.checked) checkboxGroup?.setCheckedStatus(props.value);
|
|
121
|
+
},
|
|
122
|
+
{ immediate: true },
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
watch(
|
|
126
|
+
() => checkboxGroup?.modelValue.value,
|
|
127
|
+
(newVal) => {
|
|
128
|
+
if (newVal?.length) {
|
|
129
|
+
isChecked.value = newVal.includes(props.value);
|
|
130
|
+
} else {
|
|
131
|
+
isChecked.value = false;
|
|
118
132
|
}
|
|
119
133
|
},
|
|
120
134
|
{ immediate: true },
|
|
121
135
|
);
|
|
122
136
|
|
|
123
|
-
const isDisabled = (): boolean =>
|
|
137
|
+
const isDisabled = (): boolean =>
|
|
138
|
+
checkboxGroup?.disabled?.value || props.disabled;
|
|
124
139
|
|
|
125
140
|
const checkboxStyle = computed(() => {
|
|
126
141
|
const style: CSSProperties = {};
|
|
127
|
-
if (
|
|
142
|
+
if (
|
|
143
|
+
checkboxGroup?.borderBottom?.value &&
|
|
144
|
+
checkboxGroup?.placement?.value === "row"
|
|
145
|
+
) {
|
|
128
146
|
error(
|
|
129
147
|
"检测到您将borderBottom设置为true,需要同时将hy-checkbox-group的placement设置为column才有效",
|
|
130
148
|
);
|
|
131
149
|
}
|
|
132
150
|
// 当父组件设置了显示下边框并且排列形式为纵向时,给内容和边框之间加上一定间隔
|
|
133
|
-
if (
|
|
151
|
+
if (
|
|
152
|
+
checkboxGroup?.borderBottom?.value &&
|
|
153
|
+
checkboxGroup?.placement?.value === "column"
|
|
154
|
+
) {
|
|
134
155
|
style.paddingBottom = "8px";
|
|
135
156
|
}
|
|
136
|
-
return Object.assign(style, checkboxGroup?.customStyle);
|
|
157
|
+
return Object.assign(style, checkboxGroup?.customStyle?.value);
|
|
137
158
|
});
|
|
138
159
|
/**
|
|
139
160
|
* @description 定义icon的Class类名
|
|
@@ -141,7 +162,7 @@ const checkboxStyle = computed(() => {
|
|
|
141
162
|
const iconClasses = computed(() => {
|
|
142
163
|
let classes: string[] = [];
|
|
143
164
|
// 组件的形状
|
|
144
|
-
classes.push("hy-checkbox--icon-wrap--" + checkboxGroup?.shape);
|
|
165
|
+
classes.push("hy-checkbox--icon-wrap--" + checkboxGroup?.shape?.value);
|
|
145
166
|
if (isDisabled()) {
|
|
146
167
|
classes.push("hy-checkbox--icon-wrap--disabled");
|
|
147
168
|
}
|
|
@@ -163,18 +184,20 @@ const iconWrapStyle = computed(() => {
|
|
|
163
184
|
const style: CSSProperties = {};
|
|
164
185
|
style.backgroundColor =
|
|
165
186
|
isChecked.value && !isDisabled()
|
|
166
|
-
? checkboxGroup?.activeColor
|
|
187
|
+
? checkboxGroup?.activeColor?.value
|
|
167
188
|
: !isDisabled()
|
|
168
189
|
? "#ffffff"
|
|
169
190
|
: "";
|
|
170
191
|
style.borderColor =
|
|
171
192
|
isChecked.value && !isDisabled()
|
|
172
|
-
? checkboxGroup?.activeColor
|
|
173
|
-
: checkboxGroup?.inactiveColor;
|
|
174
|
-
if (checkboxGroup?.size) {
|
|
175
|
-
style.width = addUnit(
|
|
193
|
+
? checkboxGroup?.activeColor?.value
|
|
194
|
+
: checkboxGroup?.inactiveColor?.value;
|
|
195
|
+
if (checkboxGroup?.size?.value) {
|
|
196
|
+
style.width = addUnit(
|
|
197
|
+
sizeType[checkboxGroup.size.value] ?? checkboxGroup.size.value,
|
|
198
|
+
);
|
|
176
199
|
style.height = addUnit(
|
|
177
|
-
sizeType[checkboxGroup.size] ?? checkboxGroup.size,
|
|
200
|
+
sizeType[checkboxGroup.size.value] ?? checkboxGroup.size.value,
|
|
178
201
|
);
|
|
179
202
|
}
|
|
180
203
|
return style;
|
|
@@ -195,7 +218,7 @@ const iconClickHandler = (e: Event) => {
|
|
|
195
218
|
* */
|
|
196
219
|
const wrapperClickHandler = (e: Event) => {
|
|
197
220
|
e.stopPropagation();
|
|
198
|
-
if (checkboxGroup?.labelDisabled || isDisabled()) return;
|
|
221
|
+
if (checkboxGroup?.labelDisabled?.value || isDisabled()) return;
|
|
199
222
|
setCheckedStatus();
|
|
200
223
|
};
|
|
201
224
|
/**
|
|
@@ -203,7 +226,7 @@ const wrapperClickHandler = (e: Event) => {
|
|
|
203
226
|
* */
|
|
204
227
|
const labelClickHandler = (e: Event) => {
|
|
205
228
|
e.stopPropagation();
|
|
206
|
-
if (checkboxGroup?.labelDisabled || isDisabled()) return;
|
|
229
|
+
if (checkboxGroup?.labelDisabled?.value || isDisabled()) return;
|
|
207
230
|
setCheckedStatus();
|
|
208
231
|
};
|
|
209
232
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type HyCheckboxGroupProps from "@/package/components/hy-checkbox-group/typing";
|
|
2
|
+
import type { ToRefs } from "vue";
|
|
2
3
|
|
|
3
|
-
export interface
|
|
4
|
-
setCheckedStatus: (name: string) => void;
|
|
4
|
+
export interface ICheckboxGroupContext extends ToRefs<HyCheckboxGroupProps> {
|
|
5
|
+
setCheckedStatus: (name: string | number) => void;
|
|
5
6
|
}
|
|
@@ -16,11 +16,10 @@ export default {
|
|
|
16
16
|
</script>
|
|
17
17
|
|
|
18
18
|
<script setup lang="ts">
|
|
19
|
-
import { provide, reactive, ref } from "vue";
|
|
19
|
+
import { provide, reactive, ref, toRefs } from "vue";
|
|
20
20
|
import type { PropType } from "vue";
|
|
21
21
|
import type { FormItemRule } from "./typing";
|
|
22
22
|
import { clearVal, isArray } from "../../utils";
|
|
23
|
-
import type { AppType } from "vite";
|
|
24
23
|
|
|
25
24
|
/**
|
|
26
25
|
* 表单组件父组件,需要搭配hy-form-item
|
|
@@ -73,13 +72,9 @@ const errors = reactive<Record<string, string>>({});
|
|
|
73
72
|
|
|
74
73
|
// 表单上下文
|
|
75
74
|
const formContext = {
|
|
75
|
+
...toRefs(props),
|
|
76
76
|
formData,
|
|
77
77
|
errors,
|
|
78
|
-
rules: props.rules,
|
|
79
|
-
border: props.border,
|
|
80
|
-
labelWidth: props.labelWidth,
|
|
81
|
-
labelPosition: props.labelPosition,
|
|
82
|
-
labelAlign: props.labelAlign,
|
|
83
78
|
addFormItem: (item: any) => {
|
|
84
79
|
formItems.value.push(item);
|
|
85
80
|
},
|
|
@@ -1,201 +1,204 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<view
|
|
3
|
-
class="hy-form-item"
|
|
4
|
-
:class="[
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
</
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
import {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
//
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (!
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
//
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
formContext
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
1
|
+
<template>
|
|
2
|
+
<view
|
|
3
|
+
class="hy-form-item"
|
|
4
|
+
:class="[
|
|
5
|
+
`hy-form-item--${labelPosition}`,
|
|
6
|
+
formContext.border && 'hy-border__bottom',
|
|
7
|
+
]"
|
|
8
|
+
>
|
|
9
|
+
<view v-if="label" class="hy-form-item__label" :style="labelStyle">
|
|
10
|
+
<text v-if="isRequired" class="hy-form-item__label--required">*</text>
|
|
11
|
+
{{ label }}
|
|
12
|
+
</view>
|
|
13
|
+
<view class="hy-form-item__content">
|
|
14
|
+
<slot></slot>
|
|
15
|
+
<view v-if="errorMessage" class="hy-form-item__error">
|
|
16
|
+
{{ errorMessage }}
|
|
17
|
+
</view>
|
|
18
|
+
</view>
|
|
19
|
+
</view>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script lang="ts">
|
|
23
|
+
export default {
|
|
24
|
+
name: "hy-form-item",
|
|
25
|
+
options: {
|
|
26
|
+
addGlobalClass: true,
|
|
27
|
+
virtualHost: true,
|
|
28
|
+
styleIsolation: "shared",
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<script setup lang="ts">
|
|
34
|
+
import { computed, inject, onMounted, onUnmounted, provide, ref } from "vue";
|
|
35
|
+
import type { PropType } from "vue";
|
|
36
|
+
import type { IFormContext } from "./typing";
|
|
37
|
+
import { addUnit } from "../../utils";
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 表单组件子组件,需要搭配hy-form
|
|
41
|
+
* @displayName hy-form-item
|
|
42
|
+
*/
|
|
43
|
+
defineOptions({});
|
|
44
|
+
|
|
45
|
+
const props = defineProps({
|
|
46
|
+
/**
|
|
47
|
+
* 标签文本
|
|
48
|
+
*/
|
|
49
|
+
label: String,
|
|
50
|
+
/**
|
|
51
|
+
* 表单字段名
|
|
52
|
+
*/
|
|
53
|
+
prop: String,
|
|
54
|
+
/**
|
|
55
|
+
* 是否必填
|
|
56
|
+
*/
|
|
57
|
+
required: {
|
|
58
|
+
type: Boolean,
|
|
59
|
+
default: false,
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* 验证规则
|
|
63
|
+
*/
|
|
64
|
+
rules: Object as PropType<any>,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const emit = defineEmits<{
|
|
68
|
+
change: [value: any];
|
|
69
|
+
blur: [value: any];
|
|
70
|
+
}>();
|
|
71
|
+
|
|
72
|
+
// 注入表单上下文
|
|
73
|
+
const formContext = inject<IFormContext>("formContext");
|
|
74
|
+
const formItem = {
|
|
75
|
+
// 处理子组件事件
|
|
76
|
+
handleChange(value: any) {
|
|
77
|
+
if (props.prop && formContext) {
|
|
78
|
+
formContext.setFieldValue(props.prop, value);
|
|
79
|
+
validate("change");
|
|
80
|
+
}
|
|
81
|
+
emit("change", value);
|
|
82
|
+
},
|
|
83
|
+
handleBlur(value: any) {
|
|
84
|
+
if (props.prop && formContext) {
|
|
85
|
+
validate("blur");
|
|
86
|
+
}
|
|
87
|
+
emit("blur", value);
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
provide("formItem", formItem);
|
|
91
|
+
|
|
92
|
+
// 当前组件的引用
|
|
93
|
+
const formItemRef = ref();
|
|
94
|
+
|
|
95
|
+
// 错误信息
|
|
96
|
+
const errorMessage = computed(() => {
|
|
97
|
+
if (!formContext || !props.prop) return "";
|
|
98
|
+
return formContext.errors[props.prop] || "";
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// 是否必填
|
|
102
|
+
const isRequired = computed(() => {
|
|
103
|
+
if (props.required) return true;
|
|
104
|
+
if (!formContext || !props.prop) return false;
|
|
105
|
+
|
|
106
|
+
const fieldRules = formContext.rules?.value?.[props.prop];
|
|
107
|
+
if (!fieldRules) return false;
|
|
108
|
+
|
|
109
|
+
const rules = Array.isArray(fieldRules) ? fieldRules : [fieldRules];
|
|
110
|
+
return rules.some((rule) => rule.required);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// 标签样式
|
|
114
|
+
const labelStyle = computed(() => {
|
|
115
|
+
if (!formContext) return {};
|
|
116
|
+
|
|
117
|
+
const style: Record<string, any> = {};
|
|
118
|
+
|
|
119
|
+
if (formContext.labelWidth?.value !== "auto") {
|
|
120
|
+
style.width = addUnit(formContext.labelWidth?.value);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (formContext.labelAlign?.value) {
|
|
124
|
+
style.textAlign = formContext.labelAlign.value;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return style;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// 标签位置
|
|
131
|
+
const labelPosition = computed(() => {
|
|
132
|
+
return formContext?.labelPosition?.value || "left";
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// 监听表单数据变化
|
|
136
|
+
// watch(
|
|
137
|
+
// () => formContext?.formData[props.prop],
|
|
138
|
+
// (newVal) => {
|
|
139
|
+
// if (props.prop && formContext) {
|
|
140
|
+
// formContext.setFieldValue(props.prop, newVal)
|
|
141
|
+
// validate('change')
|
|
142
|
+
// }
|
|
143
|
+
// },
|
|
144
|
+
// { immediate: true },
|
|
145
|
+
// )
|
|
146
|
+
|
|
147
|
+
// 验证字段
|
|
148
|
+
const validate = (trigger?: "blur" | "change") => {
|
|
149
|
+
if (!formContext || !props.prop) return true;
|
|
150
|
+
|
|
151
|
+
const value = formContext.getFieldValue(props.prop);
|
|
152
|
+
return formContext.validateField(props.prop, value, trigger);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// 重置字段
|
|
156
|
+
const resetField = () => {
|
|
157
|
+
if (!formContext || !props.prop) return;
|
|
158
|
+
|
|
159
|
+
formContext.setFieldValue(props.prop, undefined);
|
|
160
|
+
formContext.validateField(props.prop, undefined);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// 清除验证
|
|
164
|
+
const clearValidate = () => {
|
|
165
|
+
if (!formContext || !props.prop) return;
|
|
166
|
+
|
|
167
|
+
delete formContext.errors[props.prop];
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// 组件挂载时注册到表单
|
|
171
|
+
onMounted(() => {
|
|
172
|
+
if (formContext) {
|
|
173
|
+
formContext.addFormItem({
|
|
174
|
+
props: props,
|
|
175
|
+
validate,
|
|
176
|
+
resetField,
|
|
177
|
+
clearValidate,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// 组件卸载时从表单中移除
|
|
183
|
+
onUnmounted(() => {
|
|
184
|
+
if (formContext) {
|
|
185
|
+
formContext.removeFormItem({
|
|
186
|
+
props: props,
|
|
187
|
+
validate,
|
|
188
|
+
resetField,
|
|
189
|
+
clearValidate,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// 暴露方法给父组件
|
|
195
|
+
defineExpose({
|
|
196
|
+
validate,
|
|
197
|
+
resetField,
|
|
198
|
+
clearValidate,
|
|
199
|
+
});
|
|
200
|
+
</script>
|
|
201
|
+
|
|
202
|
+
<style lang="scss" scoped>
|
|
203
|
+
@import "./index.scss";
|
|
204
|
+
</style>
|
|
@@ -1,40 +1,46 @@
|
|
|
1
|
-
import HyFormSimpleProps from
|
|
1
|
+
import HyFormSimpleProps from "../hy-form/typing";
|
|
2
|
+
import type { ToRefs } from "vue";
|
|
2
3
|
|
|
3
|
-
export interface
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
export interface IFormContext extends ToRefs<HyFormSimpleProps> {
|
|
5
|
+
formData: AnyObject;
|
|
6
|
+
errors: Record<string, string>;
|
|
7
|
+
addFormItem: (item: any) => void;
|
|
8
|
+
removeFormItem: (item: any) => void;
|
|
9
|
+
validateField: (
|
|
10
|
+
field: string,
|
|
11
|
+
value: any,
|
|
12
|
+
trigger?: "blur" | "change",
|
|
13
|
+
) => boolean;
|
|
14
|
+
setFieldValue: (field: string, value: any) => void;
|
|
15
|
+
getFieldValue: (field: string) => any;
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
export interface FormItemContext {
|
|
13
19
|
/**
|
|
14
20
|
* 失去焦点触发表单校验
|
|
15
21
|
* */
|
|
16
|
-
handleBlur: (value: string | number) => void
|
|
22
|
+
handleBlur: (value: string | number) => void;
|
|
17
23
|
/**
|
|
18
24
|
* 值改变触发表单校验
|
|
19
25
|
* */
|
|
20
|
-
handleChange: (value: string | number) => void
|
|
26
|
+
handleChange: (value: string | number) => void;
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
export default interface HyFormItemProps {
|
|
24
30
|
/**
|
|
25
31
|
* 标签文本
|
|
26
32
|
*/
|
|
27
|
-
label?: string
|
|
33
|
+
label?: string;
|
|
28
34
|
/**
|
|
29
35
|
* 表单字段名
|
|
30
36
|
*/
|
|
31
|
-
prop?: string
|
|
37
|
+
prop?: string;
|
|
32
38
|
/**
|
|
33
39
|
* 是否必填
|
|
34
40
|
*/
|
|
35
|
-
required?: boolean
|
|
41
|
+
required?: boolean;
|
|
36
42
|
/**
|
|
37
43
|
* 验证规则
|
|
38
44
|
*/
|
|
39
|
-
rules?: any
|
|
45
|
+
rules?: any;
|
|
40
46
|
}
|