Bladeren bron

fix(tree): typo(#615)

* perf(form): schema required prop support array and strictly tree

* fix(tree): event 'change' triggered correctly
Netfan 3 jaren geleden
bovenliggende
commit
bc82d1a397
2 gewijzigde bestanden met toevoegingen van 62 en 31 verwijderingen
  1. 36 8
      src/components/Form/src/components/FormItem.vue
  2. 26 23
      src/components/Tree/src/index.vue

+ 36 - 8
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;

+ 26 - 23
src/components/Tree/src/index.vue

@@ -59,17 +59,15 @@
       const [createContextMenu] = useContextMenu();
       const { prefixCls } = useDesign('basic-tree');
 
-      const getReplaceFields = computed(
-        (): Required<ReplaceFields> => {
-          const { replaceFields } = props;
-          return {
-            children: 'children',
-            title: 'title',
-            key: 'key',
-            ...replaceFields,
-          };
-        }
-      );
+      const getReplaceFields = computed((): Required<ReplaceFields> => {
+        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);