Commit bc82d1a397beff68ba86365d7d54bb70b3520f9f
Committed by
GitHub
1 parent
f455fb97
fix(tree): typo(#615)
* perf(form): schema required prop support array and strictly tree * fix(tree): event 'change' triggered correctly
Showing
2 changed files
with
62 additions
and
31 deletions
src/components/Form/src/components/FormItem.vue
@@ -10,7 +10,7 @@ | @@ -10,7 +10,7 @@ | ||
10 | import { componentMap } from '../componentMap'; | 10 | import { componentMap } from '../componentMap'; |
11 | import { BasicHelp } from '/@/components/Basic'; | 11 | import { BasicHelp } from '/@/components/Basic'; |
12 | 12 | ||
13 | - import { isBoolean, isFunction } from '/@/utils/is'; | 13 | + import { isBoolean, isFunction, isNull } from '/@/utils/is'; |
14 | import { getSlot } from '/@/utils/helper/tsxHelper'; | 14 | import { getSlot } from '/@/utils/helper/tsxHelper'; |
15 | import { createPlaceholderMessage, setComponentRuleType } from '../helper'; | 15 | import { createPlaceholderMessage, setComponentRuleType } from '../helper'; |
16 | import { upperFirst, cloneDeep } from 'lodash-es'; | 16 | import { upperFirst, cloneDeep } from 'lodash-es'; |
@@ -141,15 +141,47 @@ | @@ -141,15 +141,47 @@ | ||
141 | } | 141 | } |
142 | 142 | ||
143 | let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[]; | 143 | let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[]; |
144 | + const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps; | ||
145 | + | ||
146 | + const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel') | ||
147 | + ? rulesMessageJoinLabel | ||
148 | + : globalRulesMessageJoinLabel; | ||
149 | + const defaultMsg = createPlaceholderMessage(component) + `${joinLabel ? label : ''}`; | ||
150 | + | ||
151 | + function validator(rule: any, value: any) { | ||
152 | + const msg = rule.message || defaultMsg; | ||
153 | + if (value === undefined || isNull(value)) { | ||
154 | + // 空值 | ||
155 | + return Promise.reject(msg); | ||
156 | + } else if (Array.isArray(value) && value.length === 0) { | ||
157 | + // 数组类型 | ||
158 | + return Promise.reject(msg); | ||
159 | + } else if (typeof value === 'string' && value.trim() === '') { | ||
160 | + // 空字符串 | ||
161 | + return Promise.reject(msg); | ||
162 | + } else if ( | ||
163 | + typeof value === 'object' && | ||
164 | + Reflect.has(value, 'checked') && | ||
165 | + Reflect.has(value, 'halfChecked') && | ||
166 | + Array.isArray(value.checked) && | ||
167 | + Array.isArray(value.halfChecked) && | ||
168 | + value.checked.length === 0 && | ||
169 | + value.halfChecked.length === 0 | ||
170 | + ) { | ||
171 | + // 非关联选择的tree组件 | ||
172 | + return Promise.reject(msg); | ||
173 | + } | ||
174 | + return Promise.resolve(); | ||
175 | + } | ||
144 | 176 | ||
145 | if ((!rules || rules.length === 0) && required) { | 177 | if ((!rules || rules.length === 0) && required) { |
146 | - rules = [{ required, type: 'string' }]; | 178 | + rules = [{ required, validator }]; |
147 | } | 179 | } |
148 | 180 | ||
149 | const requiredRuleIndex: number = rules.findIndex( | 181 | const requiredRuleIndex: number = rules.findIndex( |
150 | (rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator') | 182 | (rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator') |
151 | ); | 183 | ); |
152 | - const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps; | 184 | + |
153 | if (requiredRuleIndex !== -1) { | 185 | if (requiredRuleIndex !== -1) { |
154 | const rule = rules[requiredRuleIndex]; | 186 | const rule = rules[requiredRuleIndex]; |
155 | const { isShow } = getShow(); | 187 | const { isShow } = getShow(); |
@@ -160,12 +192,8 @@ | @@ -160,12 +192,8 @@ | ||
160 | if (!Reflect.has(rule, 'type')) { | 192 | if (!Reflect.has(rule, 'type')) { |
161 | rule.type = component === 'InputNumber' ? 'number' : 'string'; | 193 | rule.type = component === 'InputNumber' ? 'number' : 'string'; |
162 | } | 194 | } |
163 | - const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel') | ||
164 | - ? rulesMessageJoinLabel | ||
165 | - : globalRulesMessageJoinLabel; | ||
166 | 195 | ||
167 | - rule.message = | ||
168 | - rule.message || createPlaceholderMessage(component) + `${joinLabel ? label : ''}`; | 196 | + rule.message = rule.message || defaultMsg; |
169 | 197 | ||
170 | if (component.includes('Input') || component.includes('Textarea')) { | 198 | if (component.includes('Input') || component.includes('Textarea')) { |
171 | rule.whitespace = true; | 199 | rule.whitespace = true; |
src/components/Tree/src/index.vue
@@ -59,17 +59,15 @@ | @@ -59,17 +59,15 @@ | ||
59 | const [createContextMenu] = useContextMenu(); | 59 | const [createContextMenu] = useContextMenu(); |
60 | const { prefixCls } = useDesign('basic-tree'); | 60 | const { prefixCls } = useDesign('basic-tree'); |
61 | 61 | ||
62 | - const getReplaceFields = computed( | ||
63 | - (): Required<ReplaceFields> => { | ||
64 | - const { replaceFields } = props; | ||
65 | - return { | ||
66 | - children: 'children', | ||
67 | - title: 'title', | ||
68 | - key: 'key', | ||
69 | - ...replaceFields, | ||
70 | - }; | ||
71 | - } | ||
72 | - ); | 62 | + const getReplaceFields = computed((): Required<ReplaceFields> => { |
63 | + const { replaceFields } = props; | ||
64 | + return { | ||
65 | + children: 'children', | ||
66 | + title: 'title', | ||
67 | + key: 'key', | ||
68 | + ...replaceFields, | ||
69 | + }; | ||
70 | + }); | ||
73 | 71 | ||
74 | const getBindValues = computed(() => { | 72 | const getBindValues = computed(() => { |
75 | let propsData = { | 73 | let propsData = { |
@@ -92,9 +90,8 @@ | @@ -92,9 +90,8 @@ | ||
92 | onCheck: (v: CheckKeys) => { | 90 | onCheck: (v: CheckKeys) => { |
93 | state.checkedKeys = v; | 91 | state.checkedKeys = v; |
94 | const rawVal = toRaw(v); | 92 | const rawVal = toRaw(v); |
95 | - emit('change', rawVal); | ||
96 | - emit('check', rawVal); | ||
97 | emit('update:value', rawVal); | 93 | emit('update:value', rawVal); |
94 | + emit('check', rawVal); | ||
98 | }, | 95 | }, |
99 | onRightClick: handleRightClick, | 96 | onRightClick: handleRightClick, |
100 | }; | 97 | }; |
@@ -110,13 +107,8 @@ | @@ -110,13 +107,8 @@ | ||
110 | return searchState.startSearch && searchState.searchData?.length === 0; | 107 | return searchState.startSearch && searchState.searchData?.length === 0; |
111 | }); | 108 | }); |
112 | 109 | ||
113 | - const { | ||
114 | - deleteNodeByKey, | ||
115 | - insertNodeByKey, | ||
116 | - filterByLevel, | ||
117 | - updateNodeByKey, | ||
118 | - getAllKeys, | ||
119 | - } = useTree(treeDataRef, getReplaceFields); | 110 | + const { deleteNodeByKey, insertNodeByKey, filterByLevel, updateNodeByKey, getAllKeys } = |
111 | + useTree(treeDataRef, getReplaceFields); | ||
120 | 112 | ||
121 | function getIcon(params: Recordable, icon?: string) { | 113 | function getIcon(params: Recordable, icon?: string) { |
122 | if (!icon) { | 114 | if (!icon) { |
@@ -234,6 +226,15 @@ | @@ -234,6 +226,15 @@ | ||
234 | } | 226 | } |
235 | ); | 227 | ); |
236 | 228 | ||
229 | + watch( | ||
230 | + () => state.checkedKeys, | ||
231 | + () => { | ||
232 | + const v = toRaw(state.checkedKeys); | ||
233 | + emit('update:value', v); | ||
234 | + emit('change', v); | ||
235 | + } | ||
236 | + ); | ||
237 | + | ||
237 | // watchEffect(() => { | 238 | // watchEffect(() => { |
238 | // console.log('======================'); | 239 | // console.log('======================'); |
239 | // console.log(props.value); | 240 | // console.log(props.value); |
@@ -292,9 +293,11 @@ | @@ -292,9 +293,11 @@ | ||
292 | return null; | 293 | return null; |
293 | } | 294 | } |
294 | return data.map((item) => { | 295 | return data.map((item) => { |
295 | - const { title: titleField, key: keyField, children: childrenField } = unref( | ||
296 | - getReplaceFields | ||
297 | - ); | 296 | + const { |
297 | + title: titleField, | ||
298 | + key: keyField, | ||
299 | + children: childrenField, | ||
300 | + } = unref(getReplaceFields); | ||
298 | 301 | ||
299 | const propsData = omit(item, 'title'); | 302 | const propsData = omit(item, 'title'); |
300 | const icon = getIcon({ ...item, level }, item.icon); | 303 | const icon = getIcon({ ...item, level }, item.icon); |