diff --git a/packages/core/client/src/schema-component/antd/association-select/useServiceOptions.ts b/packages/core/client/src/schema-component/antd/association-select/useServiceOptions.ts index 069c0241b..80755ee0a 100644 --- a/packages/core/client/src/schema-component/antd/association-select/useServiceOptions.ts +++ b/packages/core/client/src/schema-component/antd/association-select/useServiceOptions.ts @@ -1,45 +1,76 @@ import { useFieldSchema } from '@formily/react'; -import { useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { useCollection, useCollectionManager } from '../../../collection-manager'; import { useRecord } from '../../../record-provider'; export default function useServiceOptions(props) { - const { action = 'list', service, value } = props; + const { action = 'list', service, fieldNames } = props; const params = service?.params || {}; const fieldSchema = useFieldSchema(); const { getField } = useCollection(); const { getCollectionFields } = useCollectionManager(); const record = useRecord(); + const recordValue = record[fieldSchema.name]; + + const normalizeValues = useCallback( + (obj) => { + if (obj && typeof obj === 'object') { + return obj[fieldNames.value]; + } + return obj; + }, + [fieldNames.value], + ); + + const value = useMemo(() => { + if (recordValue === undefined || recordValue === null) { + return; + } + if (Array.isArray(recordValue)) { + return recordValue.map(normalizeValues); + } else { + return normalizeValues(recordValue); + } + }, [recordValue, normalizeValues]); const collectionField = useMemo(() => { return getField(fieldSchema.name); }, [fieldSchema.name]); + const sourceValue = record?.[collectionField?.sourceKey]; const filter = useMemo(() => { - if (!collectionField) return params?.filter; - let extraFilter = {}; - if (['oho', 'o2m'].includes(collectionField.interface)) { - const eqValue = record?.[collectionField.sourceKey]; - extraFilter = { - $or: [ - { - [collectionField.foreignKey]: { - $is: null, - }, - }, - eqValue !== undefined && eqValue !== null - ? { - [collectionField.foreignKey]: { - $eq: eqValue, - }, - } - : null, - ].filter(Boolean), - }; - } - - return params?.filter ? { $and: [extraFilter, params?.filter] } : extraFilter; - }, [params?.filter, getCollectionFields, collectionField]); + const isOToAny = ['oho', 'o2m'].includes(collectionField?.interface); + return { + $or: [ + { + $and: [ + isOToAny + ? { + [collectionField.foreignKey]: { + $is: null, + }, + } + : null, + params?.filter, + ], + }, + isOToAny && sourceValue !== undefined && sourceValue !== null + ? { + [collectionField.foreignKey]: { + $eq: sourceValue, + }, + } + : null, + value + ? { + [fieldNames.value]: { + [Array.isArray(value) ? '$in' : '$eq']: value, + }, + } + : null, + ], + }; + }, [params?.filter, getCollectionFields, collectionField, sourceValue, value, fieldNames.value]); return useMemo(() => { return { diff --git a/packages/core/client/src/schema-component/antd/remote-select/RemoteSelect.tsx b/packages/core/client/src/schema-component/antd/remote-select/RemoteSelect.tsx index 051ecbb20..979527f0d 100644 --- a/packages/core/client/src/schema-component/antd/remote-select/RemoteSelect.tsx +++ b/packages/core/client/src/schema-component/antd/remote-select/RemoteSelect.tsx @@ -1,7 +1,7 @@ import { LoadingOutlined } from '@ant-design/icons'; import { connect, mapProps, mapReadPretty } from '@formily/react'; import { SelectProps } from 'antd'; -import React, { useMemo } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import { ResourceActionOptions, useRequest } from '../../../api-client'; import { useCompile } from '../../hooks'; import { defaultFieldNames, Select } from '../select'; @@ -17,10 +17,11 @@ export type RemoteSelectProps
= SelectProps
& {
const InternalRemoteSelect = connect(
(props: RemoteSelectProps) => {
- const { fieldNames = {}, service = {}, wait = 300, ...others } = props;
+ const { fieldNames = {}, service = {}, wait = 300, value, objectValue, ...others } = props;
const compile = useCompile();
+ const firstRun = useRef(false);
- const { data, run } = useRequest(
+ const { data, run, loading } = useRequest(
{
action: 'list',
...service,
@@ -35,11 +36,27 @@ const InternalRemoteSelect = connect(
},
},
{
+ manual: true,
debounceWait: wait,
- refreshDeps: [service, fieldNames.label, fieldNames.value],
},
);
+ const runDep = useMemo(
+ () =>
+ JSON.stringify({
+ service,
+ fieldNames,
+ }),
+ [service, fieldNames],
+ );
+
+ useEffect(() => {
+ // Lazy load
+ if (firstRun.current) {
+ run();
+ }
+ }, [runDep]);
+
const onSearch = async (search) => {
run({
filter: {
@@ -55,14 +72,39 @@ const InternalRemoteSelect = connect(
});
};
+ const normalizeOptions = useCallback(
+ (obj) => {
+ if (objectValue || typeof obj === 'object') {
+ return { ...obj, [fieldNames.label]: compile(obj[fieldNames.label]) };
+ }
+ return { [fieldNames.value]: obj, [fieldNames.label]: obj };
+ },
+ [objectValue, fieldNames.value],
+ );
+
const options = useMemo(() => {
+ if (!data?.data?.length) {
+ return value !== undefined && value !== null
+ ? Array.isArray(value)
+ ? value.map(normalizeOptions)
+ : [normalizeOptions(value)]
+ : [];
+ }
return (
data?.data?.map((item) => ({
...item,
[fieldNames.label]: compile(item[fieldNames.label]),
})) || []
);
- }, [data, fieldNames.label]);
+ }, [data, fieldNames.label, objectValue, value]);
+
+ const onDropdownVisibleChange = () => {
+ if (firstRun.current) {
+ return;
+ }
+ run();
+ firstRun.current = true;
+ };
return (
);
@@ -79,7 +125,6 @@ const InternalRemoteSelect = connect(
mapProps(
{
dataSource: 'options',
- loading: true,
},
(props, field) => {
return {
diff --git a/packages/core/client/src/schema-component/antd/select/Select.tsx b/packages/core/client/src/schema-component/antd/select/Select.tsx
index a93e7d11d..97aa779ce 100644
--- a/packages/core/client/src/schema-component/antd/select/Select.tsx
+++ b/packages/core/client/src/schema-component/antd/select/Select.tsx
@@ -77,7 +77,6 @@ const InternalSelect = connect(
}
return v;
};
- console.log('props', props);
if (objectValue) {
return