From bc82d1a397beff68ba86365d7d54bb70b3520f9f Mon Sep 17 00:00:00 2001 From: Netfan Date: Tue, 18 May 2021 23:05:33 +0800 Subject: [PATCH] fix(tree): typo(#615) * perf(form): schema required prop support array and strictly tree * fix(tree): event 'change' triggered correctly --- .../Form/src/components/FormItem.vue | 44 ++++++++++++++--- src/components/Tree/src/index.vue | 49 ++++++++++--------- 2 files changed, 62 insertions(+), 31 deletions(-) diff --git a/src/components/Form/src/components/FormItem.vue b/src/components/Form/src/components/FormItem.vue index 44142713188..7c6cb3615c0 100644 --- a/src/components/Form/src/components/FormItem.vue +++ b/src/components/Form/src/components/FormItem.vue @@ -10,7 +10,7 @@ import { componentMap } from '../componentMap'; import { BasicHelp } from '/@/components/Basic'; - import { isBoolean, isFunction } from '/@/utils/is'; + import { isBoolean, isFunction, isNull } from '/@/utils/is'; import { getSlot } from '/@/utils/helper/tsxHelper'; import { createPlaceholderMessage, setComponentRuleType } from '../helper'; import { upperFirst, cloneDeep } from 'lodash-es'; @@ -141,15 +141,47 @@ } let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[]; + const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps; + + const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel') + ? rulesMessageJoinLabel + : globalRulesMessageJoinLabel; + const defaultMsg = createPlaceholderMessage(component) + `${joinLabel ? label : ''}`; + + function validator(rule: any, value: any) { + const msg = rule.message || defaultMsg; + if (value === undefined || isNull(value)) { + // 空值 + return Promise.reject(msg); + } else if (Array.isArray(value) && value.length === 0) { + // 数组类型 + return Promise.reject(msg); + } else if (typeof value === 'string' && value.trim() === '') { + // 空字符串 + return Promise.reject(msg); + } else if ( + typeof value === 'object' && + Reflect.has(value, 'checked') && + Reflect.has(value, 'halfChecked') && + Array.isArray(value.checked) && + Array.isArray(value.halfChecked) && + value.checked.length === 0 && + value.halfChecked.length === 0 + ) { + // 非关联选择的tree组件 + return Promise.reject(msg); + } + return Promise.resolve(); + } if ((!rules || rules.length === 0) && required) { - rules = [{ required, type: 'string' }]; + rules = [{ required, validator }]; } const requiredRuleIndex: number = rules.findIndex( (rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator') ); - const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps; + if (requiredRuleIndex !== -1) { const rule = rules[requiredRuleIndex]; const { isShow } = getShow(); @@ -160,12 +192,8 @@ if (!Reflect.has(rule, 'type')) { rule.type = component === 'InputNumber' ? 'number' : 'string'; } - const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel') - ? rulesMessageJoinLabel - : globalRulesMessageJoinLabel; - rule.message = - rule.message || createPlaceholderMessage(component) + `${joinLabel ? label : ''}`; + rule.message = rule.message || defaultMsg; if (component.includes('Input') || component.includes('Textarea')) { rule.whitespace = true; diff --git a/src/components/Tree/src/index.vue b/src/components/Tree/src/index.vue index f3b162731df..9d379a8d249 100644 --- a/src/components/Tree/src/index.vue +++ b/src/components/Tree/src/index.vue @@ -59,17 +59,15 @@ const [createContextMenu] = useContextMenu(); const { prefixCls } = useDesign('basic-tree'); - const getReplaceFields = computed( - (): Required => { - const { replaceFields } = props; - return { - children: 'children', - title: 'title', - key: 'key', - ...replaceFields, - }; - } - ); + const getReplaceFields = computed((): Required => { + const { replaceFields } = props; + return { + children: 'children', + title: 'title', + key: 'key', + ...replaceFields, + }; + }); const getBindValues = computed(() => { let propsData = { @@ -92,9 +90,8 @@ onCheck: (v: CheckKeys) => { state.checkedKeys = v; const rawVal = toRaw(v); - emit('change', rawVal); - emit('check', rawVal); emit('update:value', rawVal); + emit('check', rawVal); }, onRightClick: handleRightClick, }; @@ -110,13 +107,8 @@ return searchState.startSearch && searchState.searchData?.length === 0; }); - const { - deleteNodeByKey, - insertNodeByKey, - filterByLevel, - updateNodeByKey, - getAllKeys, - } = useTree(treeDataRef, getReplaceFields); + const { deleteNodeByKey, insertNodeByKey, filterByLevel, updateNodeByKey, getAllKeys } = + useTree(treeDataRef, getReplaceFields); function getIcon(params: Recordable, icon?: string) { if (!icon) { @@ -234,6 +226,15 @@ } ); + watch( + () => state.checkedKeys, + () => { + const v = toRaw(state.checkedKeys); + emit('update:value', v); + emit('change', v); + } + ); + // watchEffect(() => { // console.log('======================'); // console.log(props.value); @@ -292,9 +293,11 @@ return null; } return data.map((item) => { - const { title: titleField, key: keyField, children: childrenField } = unref( - getReplaceFields - ); + const { + title: titleField, + key: keyField, + children: childrenField, + } = unref(getReplaceFields); const propsData = omit(item, 'title'); const icon = getIcon({ ...item, level }, item.icon);