diff --git a/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx b/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx
index 1b4a85600f..44df1010c5 100644
--- a/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx
+++ b/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx
@@ -1,15 +1,15 @@
-import { ISchema, useField, useFieldSchema, connect, mapProps } from '@formily/react';
+import { ISchema, connect, mapProps, useField, useFieldSchema } from '@formily/react';
import { isValid, uid } from '@formily/shared';
-import { Menu, Tree as AntdTree } from 'antd';
+import { Tree as AntdTree, Menu } from 'antd';
import { cloneDeep } from 'lodash';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useDesignable } from '../..';
-import { useCollection, useCollectionManager, useCollectionFieldsOptions } from '../../../collection-manager';
+import { useCollection, useCollectionFieldsOptions, useCollectionManager } from '../../../collection-manager';
import { OpenModeSchemaItems } from '../../../schema-items';
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
-import { useLinkageAction } from './hooks';
import { useCollectionState } from '../../../schema-settings/DataTemplates/hooks/useCollectionState';
+import { useLinkageAction } from './hooks';
import { requestSettingsSchema } from './utils';
const Tree = connect(
@@ -70,7 +70,7 @@ export const ActionDesigner = (props) => {
const isDelete = fieldSchema?.parent['x-component'] === 'CollectionField';
const isDraggable = fieldSchema?.parent['x-component'] !== 'CollectionField';
const isDuplicateAction = fieldSchema['x-action'] === 'duplicate';
- const { collectionList, getEnableFieldTree, onLoadData, onCheck } = useCollectionState(name);
+ const { collectionList, getEnableFieldTree, getOnLoadData, getOnCheck } = useCollectionState(name);
const duplicateValues = cloneDeep(fieldSchema['x-component-props'].duplicateFields || []);
const options = useCollectionFieldsOptions(name, 1, ['id']);
useEffect(() => {
@@ -236,11 +236,11 @@ export const ActionDesigner = (props) => {
/>
)}
{isLinkageAction && }
- {isDuplicateAction && [
+ {isDuplicateAction && (
{
checkable: true,
checkStrictly: true,
selectable: false,
- loadData: onLoadData,
- onCheck,
+ loadData: '{{ getOnLoadData($self) }}',
+ onCheck: '{{ getOnCheck($self) }}',
rootStyle: {
padding: '8px 0',
border: '1px solid #d9d9d9',
@@ -328,8 +328,8 @@ export const ActionDesigner = (props) => {
});
dn.refresh();
}}
- />,
- ]}
+ />
+ )}
{isUpdateModePopupAction && (
{
const { useProps, formSchema, designerCtx } = props;
const { defaultValues, collectionName } = useProps();
- const { collectionList, getEnableFieldTree, onLoadData, onCheck } = useCollectionState(collectionName);
+ const { collectionList, getEnableFieldTree, getOnLoadData, getOnCheck } = useCollectionState(collectionName);
const { getCollection, getCollectionField } = useCollectionManager();
const { t } = useTranslation();
@@ -73,6 +72,8 @@ export const FormDataTemplates = observer(
getFieldNames,
getFilter,
getResource,
+ getOnLoadData,
+ getOnCheck,
collectionName,
}),
[],
@@ -171,8 +172,8 @@ export const FormDataTemplates = observer(
checkable: true,
checkStrictly: true,
selectable: false,
- loadData: onLoadData,
- onCheck,
+ loadData: '{{ getOnLoadData($self) }}',
+ onCheck: '{{ getOnCheck($self) }}',
rootStyle: {
padding: '8px 0',
border: '1px solid #d9d9d9',
diff --git a/packages/core/client/src/schema-settings/DataTemplates/hooks/useCollectionState.ts b/packages/core/client/src/schema-settings/DataTemplates/hooks/useCollectionState.ts
index 8a08146cba..f9e1ec95fd 100644
--- a/packages/core/client/src/schema-settings/DataTemplates/hooks/useCollectionState.ts
+++ b/packages/core/client/src/schema-settings/DataTemplates/hooks/useCollectionState.ts
@@ -1,19 +1,14 @@
import { ArrayField } from '@formily/core';
-import { error } from '@nocobase/utils/client';
-import _ from 'lodash';
import React, { useCallback, useState } from 'react';
import { useCollectionManager } from '../../../collection-manager';
import { useCompile } from '../../../schema-component';
import { TreeNode } from '../TreeLabel';
export const useCollectionState = (currentCollectionName: string) => {
- const { getCollectionFields, getAllCollectionsInheritChain, getCollection, getCollectionFieldsOptions } =
- useCollectionManager();
+ const { getCollectionFields, getAllCollectionsInheritChain, getCollection } = useCollectionManager();
const [collectionList] = useState(getCollectionList);
const compile = useCompile();
- let dataFields: ArrayField = {} as any;
-
function getCollectionList() {
const collections = getAllCollectionsInheritChain(currentCollectionName);
return collections.map((name) => ({ label: getCollection(name)?.title, value: name }));
@@ -120,12 +115,7 @@ export const useCollectionState = (currentCollectionName: string) => {
.filter(Boolean);
};
- /**
- * fields: 通过在 x-reactions 字段中传递 $self 得到的,相当于 useField 的返回值,目的是修改其中的状态页面会更新
- */
- const getEnableFieldTree = useCallback((collectionName: string, fields: ArrayField) => {
- dataFields = fields;
-
+ const getEnableFieldTree = useCallback((collectionName: string) => {
if (!collectionName) {
return [];
}
@@ -138,49 +128,38 @@ export const useCollectionState = (currentCollectionName: string) => {
}
}, []);
- const onLoadData = useCallback((node) => {
- return new Promise((resolve) => {
- if (node.children.length) {
- node.children.forEach((child) => {
- loadChildren({ node: child, traverseAssociations, traverseFields, systemKeys, dataFields });
- });
- return resolve(void 0);
- }
+ const getOnLoadData = useCallback((fields: ArrayField) => {
+ return (node) => {
+ return new Promise((resolve) => {
+ if (node.children.length) {
+ node.children.forEach((child) => {
+ loadChildren({ node: child, traverseAssociations, traverseFields, systemKeys, fields });
+ });
+ return resolve(void 0);
+ }
- loadChildren({ node, traverseAssociations, traverseFields, systemKeys, dataFields });
- resolve(void 0);
- });
+ loadChildren({ node, traverseAssociations, traverseFields, systemKeys, fields });
+ resolve(void 0);
+ });
+ };
}, []);
- const onCheck = useCallback((checkedKeys, { node, checked }) => {
- if (checked) {
- // let parentKey = node.key.split('.').slice(0, -1).join('.');
-
- try {
- // 当子节点被选中时,也选中所有祖先节点,提高用户辨识度
- // while (parentKey) {
- // if (parentKey) {
- // checkedKeys.checked = _.uniq([...checkedKeys.checked, parentKey]);
- // }
- // parentKey = parentKey.split('.').slice(0, -1).join('.');
- // }
- } catch (err) {
- error(err);
- }
- }
-
- dataFields.value = checkedKeys;
+ const getOnCheck = useCallback((fields: ArrayField) => {
+ return (checkedKeys) => {
+ fields.value = checkedKeys;
+ };
}, []);
return {
collectionList,
getEnableFieldTree,
- onLoadData,
- onCheck,
+ getOnLoadData,
+ getOnCheck,
};
};
// 广度优先遍历查找一个 key 相等的节点并返回
+// 注意:返回的 node 是一个响应式对象,修改它的属性会触发页面更新
function findNode(treeData, item) {
const queue = [...treeData];
while (queue.length) {
@@ -194,8 +173,8 @@ function findNode(treeData, item) {
}
}
-function loadChildren({ node, traverseAssociations, traverseFields, systemKeys, dataFields }) {
- const activeNode = findNode(dataFields.componentProps.treeData, node);
+function loadChildren({ node, traverseAssociations, traverseFields, systemKeys, fields }) {
+ const activeNode = findNode(fields.componentProps.treeData, node);
let children = [];
// 多对多和多对一只展示关系字段