Commit bc82d1a397beff68ba86365d7d54bb70b3520f9f

Authored by Netfan
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
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);