fix: 优化自定义筛选组件和逻辑 (#486)
<!-- Note --> <!-- This is a template for submitting a new feature. Use the bug fix template if you're submitting a bug fix pull request by adding `template=bug_fix.md` to your pull request URL. --> # Description <!-- Describe the new feature or modification to an existing feature clearly and consciously. --> # Motivation <!-- Explain the reason for adding or modifying this feature. --> # Key changes <!-- Provide a technically detailed description of the key changes made. --> - Frontend - Backend # Test plan ## Suggestions <!-- Provide any suggestions or recommendations for improvements in the testing plan. --> ## Underlying risk <!-- Identify any potential risks or issues that may arise from the new feature or modification. --> # Showcase <!-- Including any screenshots of the new feature or modification. --> Co-authored-by: sealday <sealday@gmail.com> Co-authored-by: bai.jingfeng <bai.jingfeng@foxmail.com> Reviewed-on: daoyoucloud/tachycode#486 Co-authored-by: wjh <wwwjh0710@163.com> Co-committed-by: wjh <wwwjh0710@163.com>
This commit is contained in:
parent
610fee7035
commit
aa2542b706
@ -9,89 +9,45 @@ import {
|
|||||||
useFilterBlock,
|
useFilterBlock,
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import flat from 'flat';
|
import flat from 'flat';
|
||||||
|
import { hasDuplicateKeys } from '../utils';
|
||||||
|
|
||||||
export const removeNullCondition = (filter, fieldSchema?) => {
|
export const removeNullCondition = (filter, fieldSchema?) => {
|
||||||
const filterSchema = fieldSchema ? fieldSchema['x-filter-rules'] : '';
|
const filterSchema = fieldSchema ? fieldSchema['x-filter-rules'] : '';
|
||||||
const filterSchemaItem = flat(filterSchema || '');
|
const filterSchemaItem = flat(filterSchema || '');
|
||||||
const filterItem = {};
|
|
||||||
const items = flat(filter || {});
|
const items = flat(filter || {});
|
||||||
const values = {};
|
const values = {};
|
||||||
let isFilterCustom = false;
|
const isCustomFilter = filterSchema?.$and?.length || filterSchema?.$or?.length;
|
||||||
if (filterSchema && (filterSchema.$and?.length || filterSchema.$or?.length)) {
|
const isFilterCustom = isCustomFilter ? hasDuplicateKeys(items, filterSchemaItem) : false;
|
||||||
for (const key in items) {
|
|
||||||
for (const filterItems in filterSchemaItem) {
|
|
||||||
if (key.includes(filterItems)) {
|
|
||||||
isFilterCustom = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isFilterCustom) {
|
if (!isFilterCustom) {
|
||||||
if (Object.keys(items).filter((item) => item.includes('custom')).length) {
|
if (isCustomFilter) {
|
||||||
if (filterSchema && (filterSchema.$and?.length || filterSchema.$or?.length)) {
|
|
||||||
for (const filterKey in filterSchemaItem) {
|
for (const filterKey in filterSchemaItem) {
|
||||||
const match = filterSchemaItem[filterKey]?.slice(11, -2);
|
const match = filterSchemaItem[filterKey]?.slice(11, -2);
|
||||||
const collection = match?.split('.')[0];
|
const collection = match?.split('.')[0];
|
||||||
if (Object.keys(items).filter((item) => item.includes(collection)).length) {
|
const filterItems = Object.keys(items).filter((item) => item.includes(collection))[0];
|
||||||
for (const key in items) {
|
if (filterItems) {
|
||||||
if (key.includes('custom')) {
|
filterSchemaItem[filterKey] = items[filterItems];
|
||||||
if (key.includes(collection)) {
|
|
||||||
if (key.includes(match)) {
|
|
||||||
if (Object.keys(items[key]).length) {
|
|
||||||
filterSchemaItem[filterKey] = items[key];
|
|
||||||
filterItem[match] = items[key];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key.includes(collection)) delete items[key];
|
for (const item in items) {
|
||||||
else {
|
if (!item.includes('custom')) {
|
||||||
const value = items[key];
|
values[item] = items[item];
|
||||||
if (value != null && !isEmpty(value)) {
|
|
||||||
values[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
values[key] = items[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (Object.keys(items).filter((item) => !item.includes('custom')).length) {
|
|
||||||
const filterItem = Object.keys(items).filter((item) => !item.includes('custom'));
|
|
||||||
filterItem.forEach((key) => {
|
|
||||||
values[key] = items[key];
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const item in filterSchemaItem) {
|
for (const item in filterSchemaItem) {
|
||||||
for (const key in filterItem) {
|
|
||||||
if (filterSchemaItem[item].includes(key)) {
|
|
||||||
filterSchemaItem[item] = filterItem[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (filterSchemaItem[item].includes('$nFilter')) {
|
if (filterSchemaItem[item].includes('$nFilter')) {
|
||||||
delete filterSchemaItem[item];
|
delete filterSchemaItem[item];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const flatValue = flat.unflatten(values);
|
const flatValue = flat.unflatten(values);
|
||||||
const flatFieldSchema = flat.unflatten(filterSchemaItem);
|
const flatFieldSchema = flat.unflatten(filterSchemaItem);
|
||||||
|
flatValue['$and'] = flatValue['$and']?.filter(Boolean);
|
||||||
return {
|
return {
|
||||||
$and: [flatValue, flatFieldSchema],
|
$and: [flatValue, flatFieldSchema],
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
for (const key in items) {
|
for (const key in items) {
|
||||||
if (!key.includes('custom')) {
|
|
||||||
const value = items[key];
|
const value = items[key];
|
||||||
if (value != null && !isEmpty(value)) {
|
if (!key.includes('custom') && value != null && !isEmpty(value)) {
|
||||||
values[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return flat.unflatten(values);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (const key in items) {
|
|
||||||
const value = items[key];
|
|
||||||
if (value != null && !isEmpty(value)) {
|
|
||||||
values[key] = value;
|
values[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,13 +79,11 @@ export const useFilterBlockActionProps = () => {
|
|||||||
getDataBlocks().map(async (block) => {
|
getDataBlocks().map(async (block) => {
|
||||||
const target = targets.find((target) => target.uid === block.uid);
|
const target = targets.find((target) => target.uid === block.uid);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
const param = block.service.params?.[0] || {};
|
const param = block.service.params?.[0] || {};
|
||||||
for (const key in form.values) {
|
for (const key in form.values) {
|
||||||
if (
|
if (
|
||||||
(typeof form.values[key] === 'object' &&
|
(typeof form.values[key] === 'object' &&
|
||||||
!form.values[key]?.length &&
|
(JSON.stringify(form.values[key]) === '{}' || JSON.stringify(form.values[key]) === '[]')) ||
|
||||||
!Object.keys(form.values[key]).length) ||
|
|
||||||
!form.values[key]
|
!form.values[key]
|
||||||
) {
|
) {
|
||||||
delete form.values[key];
|
delete form.values[key];
|
||||||
|
@ -5,6 +5,7 @@ import { useCollectionManager, useRequest } from '@nocobase/client';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
const AssociationCascader = connect((props) => {
|
const AssociationCascader = connect((props) => {
|
||||||
|
const { fieldNames } = props;
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const collection = fieldSchema['collectionName'];
|
const collection = fieldSchema['collectionName'];
|
||||||
const associationField = props.associationField;
|
const associationField = props.associationField;
|
||||||
@ -36,8 +37,8 @@ const AssociationCascader = connect((props) => {
|
|||||||
return acc;
|
return acc;
|
||||||
}, {}) || {};
|
}, {}) || {};
|
||||||
const options = Object.entries(dict).map(([key, values]) => ({
|
const options = Object.entries(dict).map(([key, values]) => ({
|
||||||
name: key,
|
[fieldNames.label]: key,
|
||||||
id: key,
|
[fieldNames.value]: key,
|
||||||
children: values.map((value) => ({ name: value, id: value })),
|
children: values.map((value) => ({ name: value, id: value })),
|
||||||
}));
|
}));
|
||||||
return options;
|
return options;
|
||||||
|
@ -1,25 +1,17 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { AutoComplete as AntdAutoComplete } from 'antd';
|
import { AutoComplete as AntdAutoComplete } from 'antd';
|
||||||
import { useFieldSchema, useForm } from '@formily/react';
|
import { connect, useFieldSchema, useForm } from '@formily/react';
|
||||||
import { useAPIClient, useDesigner, useRequest } from '@nocobase/client';
|
import { useAPIClient, useDesigner, useRequest } from '@nocobase/client';
|
||||||
import { useAsyncEffect } from 'ahooks';
|
import { useAsyncEffect } from 'ahooks';
|
||||||
|
import { fuzzysearch } from '../../utils';
|
||||||
|
|
||||||
export const AutoComplete = (props) => {
|
export const AutoComplete = connect((props) => {
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const comdef = fieldSchema['default'];
|
const fieldNames = props.fieldNames || fieldSchema['x-component-props'].fieldNames;
|
||||||
const { fieldNames } = fieldSchema['x-component-props'];
|
const fieldFilter = props.params;
|
||||||
const fieldFilter = fieldSchema['x-component-props']['params'];
|
|
||||||
const [defultValue, setDefultValue] = useState([]);
|
const [defultValue, setDefultValue] = useState([]);
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
const [options, setOptions] = useState([]);
|
const [options, setOptions] = useState([]);
|
||||||
const form = useForm();
|
|
||||||
const autoValue = form.values['custom'] ? form.values['custom'][fieldSchema['collectionName']] : '';
|
|
||||||
const [value, setValue] = useState(autoValue);
|
|
||||||
if (!autoValue && value) {
|
|
||||||
setValue('');
|
|
||||||
setOptions(defultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
useAsyncEffect(async () => {
|
useAsyncEffect(async () => {
|
||||||
const defultOptions = await api.request({
|
const defultOptions = await api.request({
|
||||||
url: fieldSchema['collectionName'] + ':list',
|
url: fieldSchema['collectionName'] + ':list',
|
||||||
@ -33,55 +25,28 @@ export const AutoComplete = (props) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
changLable(defultValue);
|
changLable(defultValue);
|
||||||
}, [fieldNames.label]);
|
}, [fieldNames?.label]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setValue(comdef);
|
|
||||||
}, [comdef]);
|
|
||||||
const changLable = (defultOptions) => {
|
const changLable = (defultOptions) => {
|
||||||
if (defultOptions) {
|
if (defultOptions) {
|
||||||
const item = defultOptions.map((item) => {
|
const items = [];
|
||||||
item['label'] = item[fieldNames.label];
|
defultOptions.forEach((item) => {
|
||||||
item['value'] = item[fieldNames.value];
|
if (!items.filter((option) => option[fieldNames.value] === item[fieldNames.value]).length) {
|
||||||
return item;
|
items.push(item);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
setDefultValue(item);
|
setDefultValue(items);
|
||||||
setOptions(item);
|
setOptions(items);
|
||||||
}
|
|
||||||
};
|
|
||||||
if (!form.values['custom']) {
|
|
||||||
form.values['custom'] = {};
|
|
||||||
}
|
|
||||||
const onSearch = (data) => {
|
|
||||||
if (data) {
|
|
||||||
const searchValue = defultValue.filter((item) => item.label.includes(data));
|
|
||||||
if (searchValue.length) {
|
|
||||||
setOptions(searchValue);
|
|
||||||
} else {
|
|
||||||
setOptions([]);
|
|
||||||
}
|
|
||||||
const valueLabel = options.filter((item) => item.value === data)[0];
|
|
||||||
if (valueLabel) {
|
|
||||||
form.values.custom[fieldSchema['collectionName']] = valueLabel.label;
|
|
||||||
setValue(valueLabel.label);
|
|
||||||
} else {
|
|
||||||
form.values.custom[fieldSchema['collectionName']] = data;
|
|
||||||
setValue(data);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
form.values.custom[fieldSchema['collectionName']] = {};
|
|
||||||
setValue(data);
|
|
||||||
setOptions(defultValue);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<AntdAutoComplete
|
<AntdAutoComplete
|
||||||
value={value}
|
{...props}
|
||||||
defaultValue={comdef}
|
|
||||||
options={options}
|
options={options}
|
||||||
onSearch={onSearch}
|
filterOption={(inputValue, option) => fuzzysearch(inputValue, option[fieldNames.value].toString())}
|
||||||
onChange={onSearch}
|
|
||||||
allowClear
|
allowClear
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
AutoComplete.displayName = 'AutoComplete';
|
||||||
|
export default AutoComplete;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { CloseCircleFilled, CloseOutlined, LoadingOutlined } from '@ant-design/icons';
|
import { CloseCircleFilled, CloseOutlined, LoadingOutlined } from '@ant-design/icons';
|
||||||
import { connect, mapProps, mapReadPretty, useFieldSchema } from '@formily/react';
|
import { connect, mapProps, mapReadPretty, useFieldSchema, useForm } from '@formily/react';
|
||||||
import { isValid, toArr } from '@formily/shared';
|
import { isValid, toArr } from '@formily/shared';
|
||||||
import { isPlainObject } from '@nocobase/utils/client';
|
import { isPlainObject } from '@nocobase/utils/client';
|
||||||
import type { SelectProps } from 'antd';
|
import type { SelectProps } from 'antd';
|
||||||
@ -24,11 +24,10 @@ const ObjectSelect = (props: Props) => {
|
|||||||
const { value, options, onChange, fieldNames, mode, loading, rawOptions, defaultValue, ...others } = props;
|
const { value, options, onChange, fieldNames, mode, loading, rawOptions, defaultValue, ...others } = props;
|
||||||
const [defoptions, setDefOptions] = useState();
|
const [defoptions, setDefOptions] = useState();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const comDefult = fieldSchema.default;
|
|
||||||
const collectionName = fieldSchema['collectionName'];
|
const collectionName = fieldSchema['collectionName'];
|
||||||
const filterField = fieldSchema['x-component-props']['params'];
|
const filterField = others?.['params'];
|
||||||
const fieldName = fieldSchema['x-component-props'].fieldNames;
|
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
|
const form = useForm();
|
||||||
useAsyncEffect(async () => {
|
useAsyncEffect(async () => {
|
||||||
if (collectionName) {
|
if (collectionName) {
|
||||||
const defValue = await api.request({
|
const defValue = await api.request({
|
||||||
@ -39,16 +38,13 @@ const ObjectSelect = (props: Props) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const changOptions = defValue?.data?.data.map((value) => {
|
const changOptions = defValue?.data?.data.map((value) => {
|
||||||
value['label'] = value[fieldName.label];
|
value['label'] = value[fieldNames.label];
|
||||||
value['value'] = value[fieldNames.label];
|
value['value'] = value[fieldNames.value];
|
||||||
return value;
|
return value;
|
||||||
});
|
});
|
||||||
setDefOptions(changOptions);
|
setDefOptions(changOptions);
|
||||||
}
|
}
|
||||||
}, [filterField?.filter, collectionName]);
|
}, [filterField?.filter, collectionName]);
|
||||||
useEffect(() => {
|
|
||||||
onChange?.(comDefult);
|
|
||||||
}, [fieldSchema.default]);
|
|
||||||
const toValue = (v: any) => {
|
const toValue = (v: any) => {
|
||||||
if (isEmptyObject(v)) {
|
if (isEmptyObject(v)) {
|
||||||
return;
|
return;
|
||||||
@ -58,15 +54,12 @@ const ObjectSelect = (props: Props) => {
|
|||||||
.map((val) => {
|
.map((val) => {
|
||||||
return isPlainObject(val) ? val[fieldNames.value] : val;
|
return isPlainObject(val) ? val[fieldNames.value] : val;
|
||||||
});
|
});
|
||||||
const currentOptions = getCurrentOptions(values, options, fieldNames)?.map((val) => {
|
const filterOption = defoptions ? defoptions : options;
|
||||||
if (collectionName) {
|
const currentOptions = getCurrentOptions(values, filterOption, fieldNames)?.map((val) => {
|
||||||
return val[fieldName.label];
|
|
||||||
} else {
|
|
||||||
return {
|
return {
|
||||||
label: val[fieldNames.label],
|
label: val[fieldNames.label],
|
||||||
value: val[fieldNames.value],
|
value: val[fieldNames.value],
|
||||||
};
|
};
|
||||||
}
|
|
||||||
});
|
});
|
||||||
if (['tags', 'multiple'].includes(mode) || props.multiple) {
|
if (['tags', 'multiple'].includes(mode) || props.multiple) {
|
||||||
return currentOptions;
|
return currentOptions;
|
||||||
@ -83,7 +76,7 @@ const ObjectSelect = (props: Props) => {
|
|||||||
role="button"
|
role="button"
|
||||||
data-testid={`select-object-${mode || 'single'}`}
|
data-testid={`select-object-${mode || 'single'}`}
|
||||||
value={toValue(value)}
|
value={toValue(value)}
|
||||||
defaultValue={toValue(defaultValue) || comDefult}
|
defaultValue={toValue(defaultValue)}
|
||||||
allowClear={{
|
allowClear={{
|
||||||
clearIcon: <CloseCircleFilled role="button" aria-label="icon-close-select" />,
|
clearIcon: <CloseCircleFilled role="button" aria-label="icon-close-select" />,
|
||||||
}}
|
}}
|
||||||
@ -106,17 +99,17 @@ const ObjectSelect = (props: Props) => {
|
|||||||
onChange={(changed) => {
|
onChange={(changed) => {
|
||||||
const current = getCurrentOptions(
|
const current = getCurrentOptions(
|
||||||
toArr(changed).map((v) => v.value),
|
toArr(changed).map((v) => v.value),
|
||||||
rawOptions || options,
|
defoptions || rawOptions || options,
|
||||||
fieldNames,
|
fieldNames,
|
||||||
);
|
);
|
||||||
if (collectionName) {
|
|
||||||
onChange?.(changed['label']);
|
|
||||||
} else {
|
|
||||||
if (['tags', 'multiple'].includes(mode as string) || props.multiple) {
|
if (['tags', 'multiple'].includes(mode as string) || props.multiple) {
|
||||||
onChange?.(current);
|
onChange?.(current);
|
||||||
} else {
|
} else {
|
||||||
onChange?.(current.shift() || null);
|
onChange?.(current.shift() || null);
|
||||||
}
|
}
|
||||||
|
if (collectionName) {
|
||||||
|
const name = fieldSchema['name'].toString().split('.')[1];
|
||||||
|
form.values['custom'][name] = changed?.['value'];
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
mode={mode}
|
mode={mode}
|
||||||
|
@ -41,7 +41,6 @@ import {
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { SchemaSettingsRemove } from '../../schema-settings/SchemaSettingsRemove';
|
import { SchemaSettingsRemove } from '../../schema-settings/SchemaSettingsRemove';
|
||||||
import { tval, useTranslation } from '../../locale';
|
import { tval, useTranslation } from '../../locale';
|
||||||
import { ContractsController } from 'packages/plugins/@hera/plugin-rental/dist/server/actions';
|
|
||||||
|
|
||||||
const FieldComponentProps: React.FC = observer(
|
const FieldComponentProps: React.FC = observer(
|
||||||
(props) => {
|
(props) => {
|
||||||
@ -296,7 +295,7 @@ export const FilterCustomItemInitializer: React.FC<{
|
|||||||
...(defaultSchema['x-component-props'] || {}),
|
...(defaultSchema['x-component-props'] || {}),
|
||||||
fieldNames: {
|
fieldNames: {
|
||||||
label: 'name',
|
label: 'name',
|
||||||
value: 'id',
|
value: 'name',
|
||||||
},
|
},
|
||||||
associationField,
|
associationField,
|
||||||
},
|
},
|
||||||
|
@ -43,13 +43,7 @@ export const SchemaSettingsRemove: FC<SchemaSettingsRemoveProps> = (props) => {
|
|||||||
}
|
}
|
||||||
await dn.remove(null, options);
|
await dn.remove(null, options);
|
||||||
await confirm?.onOk?.();
|
await confirm?.onOk?.();
|
||||||
if (fieldSchema['collectionName']) {
|
|
||||||
delete form.values['custom'][fieldSchema['collectionName']];
|
|
||||||
} else {
|
|
||||||
if (form.values['custom']?.[fieldName]) {
|
|
||||||
delete form.values['custom'][fieldName];
|
delete form.values['custom'][fieldName];
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const key in form.fields) {
|
for (const key in form.fields) {
|
||||||
if (key.includes(name) && form.fields[key].title === title) {
|
if (key.includes(name) && form.fields[key].title === title) {
|
||||||
delete form.fields[key];
|
delete form.fields[key];
|
||||||
|
@ -176,19 +176,15 @@ export const EditDefaultValue = () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
onSubmit={(defaultValue) => {
|
onSubmit={({ default: { value } }) => {
|
||||||
let value;
|
field.setValue(value);
|
||||||
if (defaultValue.default && !defaultValue.custom) {
|
|
||||||
value = defaultValue.default.value?.value ? defaultValue.default.value.value : defaultValue.default.value;
|
|
||||||
} else if (defaultValue.custom) {
|
|
||||||
value = defaultValue.custom[collectionName];
|
|
||||||
}
|
|
||||||
field.setInitialValue(value);
|
|
||||||
fieldSchema['default'] = value;
|
fieldSchema['default'] = value;
|
||||||
|
fieldSchema['x-component-props']['defaultValue'] = value;
|
||||||
dn.emit('patch', {
|
dn.emit('patch', {
|
||||||
schema: {
|
schema: {
|
||||||
'x-uid': fieldSchema['x-uid'],
|
'x-uid': fieldSchema['x-uid'],
|
||||||
default: value,
|
['x-component-props']: fieldSchema['x-component-props'],
|
||||||
|
default: fieldSchema.default,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
dn.refresh();
|
dn.refresh();
|
||||||
@ -343,6 +339,7 @@ export const EditTitleField = () => {
|
|||||||
...collectionField?.uiSchema?.['x-component-props']?.['fieldNames'],
|
...collectionField?.uiSchema?.['x-component-props']?.['fieldNames'],
|
||||||
...field.componentProps.fieldNames,
|
...field.componentProps.fieldNames,
|
||||||
label,
|
label,
|
||||||
|
value: label,
|
||||||
};
|
};
|
||||||
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
|
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
|
||||||
fieldSchema['x-component-props']['fieldNames'] = fieldNames;
|
fieldSchema['x-component-props']['fieldNames'] = fieldNames;
|
||||||
@ -507,14 +504,11 @@ export const SchemaSettingComponent = () => {
|
|||||||
onChange={(mode) => {
|
onChange={(mode) => {
|
||||||
field.component = mode;
|
field.component = mode;
|
||||||
fieldSchema['x-component'] = mode;
|
fieldSchema['x-component'] = mode;
|
||||||
fieldSchema.default = '';
|
|
||||||
const schema = {
|
|
||||||
['x-uid']: fieldSchema['x-uid'],
|
|
||||||
['x-component']: mode,
|
|
||||||
default: '',
|
|
||||||
};
|
|
||||||
void dn.emit('patch', {
|
void dn.emit('patch', {
|
||||||
schema,
|
schema: {
|
||||||
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
|
['x-component']: fieldSchema['x-component'],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
dn.refresh();
|
dn.refresh();
|
||||||
}}
|
}}
|
||||||
@ -524,8 +518,8 @@ export const SchemaSettingComponent = () => {
|
|||||||
|
|
||||||
export const SchemaSettingCollection = () => {
|
export const SchemaSettingCollection = () => {
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const field = useField();
|
|
||||||
const collections = useCollectionManager();
|
const collections = useCollectionManager();
|
||||||
|
const field = useField<Field>();
|
||||||
const options = collections?.dataSource['options']?.collections.map((value) => {
|
const options = collections?.dataSource['options']?.collections.map((value) => {
|
||||||
return {
|
return {
|
||||||
label: value.title,
|
label: value.title,
|
||||||
@ -540,16 +534,25 @@ export const SchemaSettingCollection = () => {
|
|||||||
options={options}
|
options={options}
|
||||||
value={fieldSchema['collectionName']}
|
value={fieldSchema['collectionName']}
|
||||||
onChange={(name) => {
|
onChange={(name) => {
|
||||||
|
field.setValue('');
|
||||||
fieldSchema['collectionName'] = name;
|
fieldSchema['collectionName'] = name;
|
||||||
fieldSchema['name'] = 'custom.' + name;
|
|
||||||
fieldSchema.default = '';
|
fieldSchema.default = '';
|
||||||
const schema = {
|
fieldSchema['x-component-props'] = {
|
||||||
['x-uid']: fieldSchema['x-uid'],
|
...fieldSchema['x-component-props'],
|
||||||
collectionName: name,
|
fieldNames: {
|
||||||
name: 'custom.' + name,
|
label: 'name',
|
||||||
default: '',
|
value: 'name',
|
||||||
|
},
|
||||||
|
defaultValue: '',
|
||||||
};
|
};
|
||||||
void dn.emit('patch', { schema });
|
void dn.emit('patch', {
|
||||||
|
schema: {
|
||||||
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
|
collectionName: fieldSchema['collectionName'],
|
||||||
|
['x-component-props']: fieldSchema['x-component-props'],
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
dn.refresh();
|
dn.refresh();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
33
packages/plugins/@hera/plugin-core/src/client/utils.ts
Normal file
33
packages/plugins/@hera/plugin-core/src/client/utils.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
export function fuzzysearch(needle: string, haystack: string): boolean {
|
||||||
|
const hlen = haystack.length;
|
||||||
|
const nlen = needle.length;
|
||||||
|
if (nlen > hlen) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (nlen === hlen) {
|
||||||
|
return needle === haystack;
|
||||||
|
}
|
||||||
|
outer: for (let i = 0, j = 0; i < nlen; i++) {
|
||||||
|
const nch = needle.charCodeAt(i);
|
||||||
|
while (j < hlen) {
|
||||||
|
if (haystack.charCodeAt(j++) === nch) {
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数组去重
|
||||||
|
const getArrayOfNoDuplicateValue = (arr: Array<string | number>): Array<string | number> => {
|
||||||
|
return [...new Set(arr)];
|
||||||
|
};
|
||||||
|
|
||||||
|
// 判断两个对象是否包含有相同的key
|
||||||
|
export function hasDuplicateKeys(A: Object, B: Object): boolean {
|
||||||
|
const keysA = getArrayOfNoDuplicateValue(Object.keys(A));
|
||||||
|
const keysB = getArrayOfNoDuplicateValue(Object.keys(B));
|
||||||
|
const keysA_B = getArrayOfNoDuplicateValue([...keysA, ...keysB]);
|
||||||
|
return keysA_B.length < keysA.length + keysB.length;
|
||||||
|
}
|
@ -235,7 +235,7 @@ SELECT
|
|||||||
records r
|
records r
|
||||||
WHERE
|
WHERE
|
||||||
r.contract_id = COALESCE(main.id, c.id)
|
r.contract_id = COALESCE(main.id, c.id)
|
||||||
AND s.end_date + INTERVAL '1 day' >= r.date
|
AND s.end_date >= r.date
|
||||||
) AS records,
|
) AS records,
|
||||||
(
|
(
|
||||||
SELECT
|
SELECT
|
||||||
|
Loading…
Reference in New Issue
Block a user