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 | 10 | import { componentMap } from '../componentMap'; |
11 | 11 | import { BasicHelp } from '/@/components/Basic'; |
12 | 12 | |
13 | - import { isBoolean, isFunction } from '/@/utils/is'; | |
13 | + import { isBoolean, isFunction, isNull } from '/@/utils/is'; | |
14 | 14 | import { getSlot } from '/@/utils/helper/tsxHelper'; |
15 | 15 | import { createPlaceholderMessage, setComponentRuleType } from '../helper'; |
16 | 16 | import { upperFirst, cloneDeep } from 'lodash-es'; |
... | ... | @@ -141,15 +141,47 @@ |
141 | 141 | } |
142 | 142 | |
143 | 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 | 177 | if ((!rules || rules.length === 0) && required) { |
146 | - rules = [{ required, type: 'string' }]; | |
178 | + rules = [{ required, validator }]; | |
147 | 179 | } |
148 | 180 | |
149 | 181 | const requiredRuleIndex: number = rules.findIndex( |
150 | 182 | (rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator') |
151 | 183 | ); |
152 | - const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps; | |
184 | + | |
153 | 185 | if (requiredRuleIndex !== -1) { |
154 | 186 | const rule = rules[requiredRuleIndex]; |
155 | 187 | const { isShow } = getShow(); |
... | ... | @@ -160,12 +192,8 @@ |
160 | 192 | if (!Reflect.has(rule, 'type')) { |
161 | 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 | 198 | if (component.includes('Input') || component.includes('Textarea')) { |
171 | 199 | rule.whitespace = true; | ... | ... |
src/components/Tree/src/index.vue
... | ... | @@ -59,17 +59,15 @@ |
59 | 59 | const [createContextMenu] = useContextMenu(); |
60 | 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 | 72 | const getBindValues = computed(() => { |
75 | 73 | let propsData = { |
... | ... | @@ -92,9 +90,8 @@ |
92 | 90 | onCheck: (v: CheckKeys) => { |
93 | 91 | state.checkedKeys = v; |
94 | 92 | const rawVal = toRaw(v); |
95 | - emit('change', rawVal); | |
96 | - emit('check', rawVal); | |
97 | 93 | emit('update:value', rawVal); |
94 | + emit('check', rawVal); | |
98 | 95 | }, |
99 | 96 | onRightClick: handleRightClick, |
100 | 97 | }; |
... | ... | @@ -110,13 +107,8 @@ |
110 | 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 | 113 | function getIcon(params: Recordable, icon?: string) { |
122 | 114 | if (!icon) { |
... | ... | @@ -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 | 238 | // watchEffect(() => { |
238 | 239 | // console.log('======================'); |
239 | 240 | // console.log(props.value); |
... | ... | @@ -292,9 +293,11 @@ |
292 | 293 | return null; |
293 | 294 | } |
294 | 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 | 302 | const propsData = omit(item, 'title'); |
300 | 303 | const icon = getIcon({ ...item, level }, item.icon); | ... | ... |