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 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);
... ...