refactor(linkage-rule): linkage rules condition support toMany association fields (#1924)

* refactor: linkage rule support to many association field

* refactor: linkage rule support toMany

* fix:  support toMany association field

* fix:  support toMany association field

* fix: operator support toMany association field

* refactor: useLinkageCollectionFilterOptions
This commit is contained in:
katherinehhh 2023-05-29 11:22:04 +08:00 committed by GitHub
parent 4296db5859
commit c0f9c8116a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 9 deletions

View File

@ -203,7 +203,7 @@ export const useCollectionFilterOptions = (collectionName: string) => {
export const useLinkageCollectionFilterOptions = (collectionName: string) => {
const { getCollectionFields, getInterface } = useCollectionManager();
const fields = getCollectionFields(collectionName).filter((v) => !['o2m', 'm2m'].includes(v.interface));
const fields = getCollectionFields(collectionName);
const field2option = (field, depth) => {
if (!field.interface) {
return;
@ -233,7 +233,12 @@ export const useLinkageCollectionFilterOptions = (collectionName: string) => {
option['children'] = children;
}
if (nested) {
const targetFields = getCollectionFields(field.target).filter((v) => !['o2m', 'm2m'].includes(v.interface));
const targetFields = getCollectionFields(field.target).filter((v) => {
if (['hasMany', 'belongsToMany'].includes(field.type)) {
return !['hasOne', 'hasMany', 'belongsTo', 'belongsToMany'].includes(v.type);
}
return !['hasMany', 'belongsToMany'].includes(v.type);
});
const options = getOptions(targetFields, depth + 1).filter(Boolean);
option['children'] = option['children'] || [];
option['children'].push(...options);

View File

@ -35,6 +35,9 @@ http://ricostacruz.com/cheatsheets/umdjs.html
}
return a;
}
function areArraysEqual(arr1, arr2) {
return JSON.stringify(arr1) === JSON.stringify(arr2);
}
var jsonLogic = {};
var operations = {
@ -42,9 +45,18 @@ http://ricostacruz.com/cheatsheets/umdjs.html
return a === b;
},
$match: function (a, b) {
if (Array.isArray(a) && Array.isArray(b) && a.some((element) => Array.isArray(element))) {
return a.some(
(subArray) => subArray?.length === b.length && subArray?.every((element, index) => element === b[index]),
);
}
return JSON.stringify(a) === JSON.stringify(b);
},
$eq: function (a, b) {
if (Array.isArray(a) && Array.isArray(b)) return areArraysEqual(a, b);
if (Array.isArray(a)) {
return a.includes(b);
}
return a === b;
},
$ne: function (a, b) {
@ -54,12 +66,14 @@ http://ricostacruz.com/cheatsheets/umdjs.html
return a !== b;
},
$gt: function (a, b) {
if (Array.isArray(a)) return a.some((k) => k > b);
return a > b;
},
$gte: function (a, b) {
return a >= b;
},
$lt: function (a, b, c) {
if (Array.isArray(a)) return a.some((k) => k < b);
return c === undefined ? a < b : a < b && b < c;
},
$lte: function (a, b, c) {
@ -72,6 +86,7 @@ http://ricostacruz.com/cheatsheets/umdjs.html
return jsonLogic.truthy(a);
},
$empty: function (a) {
if (Array.isArray(a)) return a.some((k) => !jsonLogic.truthy(k));
return !jsonLogic.truthy(a);
},
$notExists: function (a) {
@ -86,6 +101,9 @@ http://ricostacruz.com/cheatsheets/umdjs.html
},
$in: function (a, b) {
if (!b || typeof b.indexOf === 'undefined') return false;
if (Array.isArray(a) && Array.isArray(b)) {
return b.some((elementB) => a.includes(elementB));
}
return b.indexOf(a) !== -1;
},
$notIn: function (a, b) {
@ -94,22 +112,30 @@ http://ricostacruz.com/cheatsheets/umdjs.html
},
$includes: function (a, b) {
if (!a || typeof a.indexOf === 'undefined') return false;
if (Array.isArray(a)) return a.some((element) => element?.includes(b));
return a.indexOf(b) !== -1;
},
$notIncludes: function (a, b) {
if (!a || typeof a.indexOf === 'undefined') return false;
if (Array.isArray(a)) return !a.some((element) => element.includes(b));
return !(a.indexOf(b) !== -1);
},
$anyOf: function (a, b) {
if (a.length === 0) {
return false;
}
return b.every((item) => a.includes(item));
if (Array.isArray(a) && Array.isArray(b) && a.some((element) => Array.isArray(element))) {
return a.some((subArray) => subArray.some((element) => b.includes(element)));
}
return a.some((element) => b.includes(element));
},
$noneOf: function (a, b) {
if (a.length === 0) {
return true;
}
if (Array.isArray(a) && Array.isArray(b) && a.some((element) => Array.isArray(element))) {
return a.some((subArray) => subArray.every((element) => !b.some((bElement) => element.includes(bElement))));
}
return b.some((item) => !a.includes(item));
},
$notMatch: function (a, b) {
@ -125,9 +151,11 @@ http://ricostacruz.com/cheatsheets/umdjs.html
return false;
},
$isTruly: function (a) {
if (Array.isArray(a)) return a.some((k) => k === true || k === 1);
return a === true || a === 1;
},
$isFalsy: function (a) {
if (Array.isArray(a)) return a.some((k) => !jsonLogic.truthy(k));
return !jsonLogic.truthy(a);
},
cat: function () {

View File

@ -1,5 +1,5 @@
import flat from 'flat';
import _, { every, findIndex, some } from 'lodash';
import _, { every, findIndex, some, isArray } from 'lodash';
import moment from 'moment';
import { useCurrentUserContext } from '../../../user';
import jsonLogic from '../../common/utils/logic';
@ -57,11 +57,25 @@ function getInnermostKeyAndValue(obj) {
return null;
}
const getFieldValue = (fieldPath, values) => {
const v = fieldPath[0];
const h = fieldPath[1];
const regex = new RegExp('^' + v + '\\..+\\.' + h + '$'); // 构建匹配的正则表达式
const matchedValues = [];
const data = flat.flatten(values, { maxDepth: 3 });
for (var key in data) {
if (regex.test(key)) {
matchedValues.push(data[key]);
}
}
return matchedValues;
};
const getValue = (str: string, values) => {
const regex = /{{(.*?)}}/;
const matches = str?.match?.(regex);
if (matches) {
return getVariableValue(str, flat(values));
return getVariableValue(str, values);
} else {
return str;
}
@ -69,7 +83,14 @@ const getValue = (str: string, values) => {
const getVariableValue = (str, values) => {
const regex = /{{[^.]+\.([^}]+)}}/;
const match = regex.exec(str);
return values[match?.[1]];
const targetField = match?.[1]?.split('.') || [];
const isArrayField = isArray(values[targetField[0]]);
if (isArrayField && targetField.length > 1) {
//对多关系字段
return getFieldValue(targetField, values);
} else {
return flat(values)[match?.[1]];
}
};
const getTargetField = (obj) => {
const keys = getAllKeys(obj);
@ -110,9 +131,17 @@ export const conditionAnalyse = (rules, values) => {
return true;
}
try {
const currentValue = targetField.length > 1 ? flat(values)?.[targetField.join('.')] : values?.[targetField[0]];
const result = jsonLogic.apply({ [operator]: [currentValue, value] });
return result;
const isArrayField = isArray(values[targetField[0]]);
if (isArrayField && targetField.length > 1) {
//对多关系字段比较
const currentValue = getFieldValue(targetField, values);
const result = jsonLogic.apply({ [operator]: [currentValue, value] });
return result;
} else {
const currentValue = targetField.length > 1 ? flat(values)?.[targetField.join('.')] : values?.[targetField[0]];
const result = jsonLogic.apply({ [operator]: [currentValue, value] });
return result;
}
} catch (error) {
console.error(error);
}