From b337c1590dfe125fb3a60b940c1f87ed0df6b531 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Fri, 7 Jul 2023 12:58:47 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dcrud=20=E4=B8=AD=20dra?= =?UTF-8?q?wer=20=E5=8A=A8=E4=BD=9C=E5=90=8E=E4=B8=8D=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20=20=20Close:=20#6903?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/launch.json | 85 +-- packages/amis-core/src/RootRenderer.tsx | 18 +- packages/amis-core/src/Scoped.tsx | 20 +- packages/amis-core/src/factory.tsx | 2 +- packages/amis-core/src/renderers/Form.tsx | 25 +- .../__tests__/renderers/CRUDReload.test.tsx | 531 ++++++++++++++++++ packages/amis/src/renderers/CRUD.tsx | 14 +- packages/amis/src/renderers/Dialog.tsx | 37 +- packages/amis/src/renderers/Drawer.tsx | 38 +- packages/amis/src/renderers/Page.tsx | 27 +- packages/amis/src/renderers/Service.tsx | 11 +- packages/amis/src/renderers/Wizard.tsx | 18 +- 12 files changed, 701 insertions(+), 125 deletions(-) create mode 100644 packages/amis/__tests__/renderers/CRUDReload.test.tsx diff --git a/.vscode/launch.json b/.vscode/launch.json index 2a9304def..674b93dc0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,71 +1,18 @@ { - // 使用 IntelliSense 了解相关属性。 - // 悬停以查看现有属性的描述。 - // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Jest All", - "program": "${workspaceFolder}/node_modules/.bin/jest", - "args": ["--runInBand"], - "sourceMaps": true, - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "disableOptimisticBPs": true, - "runtimeExecutable": "/usr/local/bin/node", - "windows": { - "program": "${workspaceFolder}/node_modules/jest/bin/jest", - } - }, - { - "type": "node", - "request": "launch", - "name": "Jest Current File", - "program": "${workspaceFolder}/node_modules/.bin/jest", - "args": [ - "--no-cache", - "--runInBand", - "${relativeFile}" - ], - "sourceMaps": true, - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "disableOptimisticBPs": true, - "runtimeExecutable": "/usr/local/bin/node", - "windows": { - "program": "${workspaceFolder}/node_modules/jest/bin/jest", - } - }, - { - "type": "node", - "request": "launch", - "name": "Jest Current File Specified test", - "program": "${workspaceFolder}/node_modules/.bin/jest", - "args": [ - "--no-cache", - "--runInBand", - "${relativeFile}", - "-t", - "${input:testName}" - ], - "sourceMaps": true, - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "disableOptimisticBPs": true, - "runtimeExecutable": "/usr/local/bin/node", - "windows": { - "program": "${workspaceFolder}/node_modules/jest/bin/jest", - } - } - ], - "inputs": [ - { - "id": "testName", - "type": "promptString", - "default": "", - "description": "Run only tests with a name that matches the regex pattern." + "version": "1.0.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Jest: current file", + //"env": { "NODE_ENV": "test" }, + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": ["${fileBasenameNoExtension}"], + "console": "integratedTerminal", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest/bin/jest" } - ] -} \ No newline at end of file + } + ] +} diff --git a/packages/amis-core/src/RootRenderer.tsx b/packages/amis-core/src/RootRenderer.tsx index f401f3775..c4df36dad 100644 --- a/packages/amis-core/src/RootRenderer.tsx +++ b/packages/amis-core/src/RootRenderer.tsx @@ -160,7 +160,12 @@ export class RootRenderer extends React.Component { window.open(mailto); } else if (action.actionType === 'dialog') { store.setCurrentAction(action); - store.openDialog(ctx, undefined, action.callback, delegate); + store.openDialog( + ctx, + undefined, + action.callback, + delegate || (this.context as any) + ); } else if (action.actionType === 'drawer') { store.setCurrentAction(action); store.openDrawer(ctx, undefined, undefined, delegate); @@ -323,9 +328,14 @@ export class RootRenderer extends React.Component { actionType: 'dialog', dialog: dialog }); - store.openDialog(ctx, undefined, confirmed => { - resolve(confirmed); - }); + store.openDialog( + ctx, + undefined, + confirmed => { + resolve(confirmed); + }, + this.context as any + ); }); } diff --git a/packages/amis-core/src/Scoped.tsx b/packages/amis-core/src/Scoped.tsx index 77005f72f..8cc4d4059 100644 --- a/packages/amis-core/src/Scoped.tsx +++ b/packages/amis-core/src/Scoped.tsx @@ -58,6 +58,8 @@ export interface ScopedComponentType extends React.Component { } export interface IScopedContext { + rendererType?: string; + component?: ScopedComponentType; parent?: AliasIScopedContext; children?: AliasIScopedContext[]; registerComponent: (component: ScopedComponentType) => void; @@ -69,6 +71,10 @@ export interface IScopedContext { send: (target: string, ctx: RendererData) => void; close: (target: string) => void; closeById: (target: string) => void; + getComponentsByRefPath: ( + session: string, + path: string + ) => ScopedComponentType[]; } type AliasIScopedContext = IScopedContext; @@ -78,14 +84,18 @@ export const ScopedContext = React.createContext(rootScopedContext); function createScopedTools( path?: string, parent?: AliasIScopedContext, - env?: RendererEnv + env?: RendererEnv, + rendererType?: string ): IScopedContext { const components: Array = []; - const self = { + const self: IScopedContext = { + rendererType, + component: undefined, parent, registerComponent(component: ScopedComponentType) { // 不要把自己注册在自己的 Scoped 上,自己的 Scoped 是给子节点们注册的。 if (component.props.$path === path && parent) { + self.component = component; return parent.registerComponent(component); } @@ -404,7 +414,8 @@ export function HocScoped< env: RendererEnv; } >( - ComposedComponent: React.ComponentType + ComposedComponent: React.ComponentType, + rendererType?: string ): React.ComponentType< T & { scopeRef?: (ref: any) => void; @@ -430,7 +441,8 @@ export function HocScoped< this.scoped = createScopedTools( this.props.$path, context, - this.props.env + this.props.env, + rendererType ); const scopeRef = props.scopeRef; diff --git a/packages/amis-core/src/factory.tsx b/packages/amis-core/src/factory.tsx index 059d07a46..44b20aae8 100644 --- a/packages/amis-core/src/factory.tsx +++ b/packages/amis-core/src/factory.tsx @@ -186,7 +186,7 @@ export function registerRenderer(config: RendererConfig): RendererConfig { } if (config.isolateScope) { - config.component = Scoped(config.component); + config.component = Scoped(config.component, config.type); } const idx = findIndex( diff --git a/packages/amis-core/src/renderers/Form.tsx b/packages/amis-core/src/renderers/Form.tsx index 1937d5b00..29faba7c2 100644 --- a/packages/amis-core/src/renderers/Form.tsx +++ b/packages/amis-core/src/renderers/Form.tsx @@ -1133,7 +1133,12 @@ export default class Form extends React.Component { action.target && this.reloadTarget(filterTarget(action.target, values), values); } else if (action.actionType === 'dialog') { - store.openDialog(data, undefined, action.callback); + store.openDialog( + data, + undefined, + action.callback, + delegate || (this.context as any) + ); } else if (action.actionType === 'drawer') { store.openDrawer(data); } else if (isEffectiveApi(action.api || api, values)) { @@ -1259,7 +1264,12 @@ export default class Form extends React.Component { this.validate(true); } else if (action.actionType === 'dialog') { store.setCurrentAction(action); - store.openDialog(data, undefined, action.callback); + store.openDialog( + data, + undefined, + action.callback, + delegate || (this.context as any) + ); } else if (action.actionType === 'drawer') { store.setCurrentAction(action); store.openDrawer(data); @@ -1428,9 +1438,14 @@ export default class Form extends React.Component { actionType: 'dialog', dialog: dialog }); - store.openDialog(ctx, undefined, confirmed => { - resolve(confirmed); - }); + store.openDialog( + ctx, + undefined, + confirmed => { + resolve(confirmed); + }, + this.context as any + ); }); } diff --git a/packages/amis/__tests__/renderers/CRUDReload.test.tsx b/packages/amis/__tests__/renderers/CRUDReload.test.tsx new file mode 100644 index 000000000..5e4684266 --- /dev/null +++ b/packages/amis/__tests__/renderers/CRUDReload.test.tsx @@ -0,0 +1,531 @@ +import {render, fireEvent, waitFor} from '@testing-library/react'; +import '../../src'; +import {render as amisRender} from '../../src'; +import {makeEnv, wait} from '../helper'; +jest.useRealTimers(); + +// 验证 crud 里面的 ajax 动作,结束后是否刷新 crud +test('CRUD reload ajax1', async () => { + let listApiCalledCount = 0; + const mockFetcher = jest.fn().mockImplementation((api: any) => { + if (/^\/api\/mock2\/sample\/\d+/.test(api.url)) { + return Promise.resolve({ + data: { + status: 0 + } + }); + } + + listApiCalledCount++; + return Promise.resolve({ + data: { + status: 0, + data: { + items: [{id: 1, a: 'a1', b: 'b1'}] + } + } + }); + }); + const {container} = render( + amisRender( + { + type: 'page', + body: { + type: 'crud', + api: '/api/mock2/sample', + columns: [ + { + name: 'id', + label: 'ID' + }, + { + name: 'a', + label: 'A' + }, + { + name: 'b', + label: 'B' + }, + { + label: '操作', + type: 'operation', + buttons: [ + { + label: '保存', + type: 'button', + actionType: 'ajax', + api: '/api/mock2/sample/${id}' + } + ] + } + ] + } + }, + {}, + makeEnv({fetcher: mockFetcher}) + ) + ); + await wait(200); + const saveBtn = container.querySelectorAll('tbody>tr button')[0]; + expect(saveBtn).toBeTruthy(); + fireEvent.click(saveBtn); + await waitFor(() => { + expect(mockFetcher).toBeCalledTimes(3); + }); + expect(listApiCalledCount).toBe(2); +}); + +// 如果配置了 reload none 则不刷新 +test('CRUD reload ajax2', async () => { + let listApiCalledCount = 0; + const mockFetcher = jest.fn().mockImplementation((api: any) => { + if (/^\/api\/mock2\/sample\/\d+/.test(api.url)) { + return Promise.resolve({ + data: { + status: 0 + } + }); + } + + listApiCalledCount++; + return Promise.resolve({ + data: { + status: 0, + data: { + items: [{id: 1, a: 'a1', b: 'b1'}] + } + } + }); + }); + const {container} = render( + amisRender( + { + type: 'page', + body: { + type: 'crud', + api: '/api/mock2/sample', + columns: [ + { + name: 'id', + label: 'ID' + }, + { + name: 'a', + label: 'A' + }, + { + name: 'b', + label: 'B' + }, + { + label: '操作', + type: 'operation', + buttons: [ + { + label: '保存', + type: 'button', + actionType: 'ajax', + api: '/api/mock2/sample/${id}' + }, + { + label: '保存2', + type: 'button', + actionType: 'ajax', + api: '/api/mock2/sample/${id}', + reload: 'none' + } + ] + } + ] + } + }, + {}, + makeEnv({fetcher: mockFetcher}) + ) + ); + await wait(200); + const saveBtn1 = container.querySelectorAll('tbody>tr button')[0]; + const saveBtn2 = container.querySelectorAll('tbody>tr button')[1]; + expect(saveBtn1).toBeTruthy(); + expect(saveBtn2).toBeTruthy(); + fireEvent.click(saveBtn2); + await waitFor(() => { + expect(mockFetcher).toBeCalledTimes(2); + }); + expect(listApiCalledCount).toBe(1); + fireEvent.click(saveBtn1); + await waitFor(() => { + expect(mockFetcher).toBeCalledTimes(4); + }); + expect(listApiCalledCount).toBe(2); +}); + +// dialog 提交后应该刷新 crud +test('CRUD reload dialog1', async () => { + let listApiCalledCount = 0; + const mockFetcher = jest.fn().mockImplementation((api: any) => { + if (/^\/api\/mock2\/sample\/\d+/.test(api.url)) { + return Promise.resolve({ + data: { + status: 0 + } + }); + } + + listApiCalledCount++; + return Promise.resolve({ + data: { + status: 0, + data: { + items: [{id: 1, a: 'a1', b: 'b1'}] + } + } + }); + }); + const {container, getByText}: any = render( + amisRender( + { + type: 'page', + body: { + type: 'crud', + api: '/api/mock2/sample', + columns: [ + { + name: 'id', + label: 'ID' + }, + { + name: 'a', + label: 'A' + }, + { + name: 'b', + label: 'B' + }, + { + label: '操作', + type: 'operation', + buttons: [ + { + label: 'OpenDialog', + type: 'button', + actionType: 'dialog', + dialog: { + body: { + type: 'form', + api: '/api/mock2/sample/${id}', + body: [ + { + type: 'input-text', + name: 'a', + label: 'A' + } + ] + } + } + } + ] + } + ] + } + }, + {}, + makeEnv({fetcher: mockFetcher, getModalContainer: () => container}) + ) + ); + await wait(200); + const saveBtn = container.querySelectorAll('tbody>tr button')[0]; + expect(saveBtn).toBeTruthy(); + fireEvent.click(saveBtn); + await wait(300); + + expect(getByText('确认')).toBeInTheDocument(); + fireEvent.click(getByText('取消')); + await wait(300); + + fireEvent.click(saveBtn); + await wait(300); + expect(getByText('确认')).toBeInTheDocument(); + + fireEvent.click(getByText('确认')); + await wait(500); + + expect(mockFetcher).toBeCalledTimes(3); + expect(listApiCalledCount).toBe(2); +}); + +// dialog 提交后如果配置列不刷新,则不刷新 +test('CRUD reload dialog2', async () => { + let listApiCalledCount = 0; + const mockFetcher = jest.fn().mockImplementation((api: any) => { + if (/^\/api\/mock2\/sample\/\d+/.test(api.url)) { + return Promise.resolve({ + data: { + status: 0 + } + }); + } + + listApiCalledCount++; + return Promise.resolve({ + data: { + status: 0, + data: { + items: [{id: 1, a: 'a1', b: 'b1'}] + } + } + }); + }); + const {container, getByText}: any = render( + amisRender( + { + type: 'page', + body: { + type: 'crud', + api: '/api/mock2/sample', + columns: [ + { + name: 'id', + label: 'ID' + }, + { + name: 'a', + label: 'A' + }, + { + name: 'b', + label: 'B' + }, + { + label: '操作', + type: 'operation', + buttons: [ + { + label: 'OpenDialog', + type: 'button', + actionType: 'dialog', + reload: 'none', + dialog: { + body: { + type: 'form', + api: '/api/mock2/sample/${id}', + body: [ + { + type: 'input-text', + name: 'a', + label: 'A' + } + ] + } + } + } + ] + } + ] + } + }, + {}, + makeEnv({fetcher: mockFetcher, getModalContainer: () => container}) + ) + ); + await wait(200); + const saveBtn = container.querySelectorAll('tbody>tr button')[0]; + expect(saveBtn).toBeTruthy(); + fireEvent.click(saveBtn); + await wait(300); + + fireEvent.click(saveBtn); + await wait(300); + expect(getByText('确认')).toBeInTheDocument(); + + fireEvent.click(getByText('确认')); + await wait(500); + + expect(mockFetcher).toBeCalledTimes(2); + expect(listApiCalledCount).toBe(1); +}); + +// drawer 提交后应该刷新 crud +test('CRUD reload drawer1', async () => { + let listApiCalledCount = 0; + const mockFetcher = jest.fn().mockImplementation((api: any) => { + if (/^\/api\/mock2\/sample\/\d+/.test(api.url)) { + return Promise.resolve({ + data: { + status: 0 + } + }); + } + + listApiCalledCount++; + return Promise.resolve({ + data: { + status: 0, + data: { + items: [{id: 1, a: 'a1', b: 'b1'}] + } + } + }); + }); + const {container, getByText}: any = render( + amisRender( + { + type: 'page', + body: { + type: 'crud', + api: '/api/mock2/sample', + columns: [ + { + name: 'id', + label: 'ID' + }, + { + name: 'a', + label: 'A' + }, + { + name: 'b', + label: 'B' + }, + { + label: '操作', + type: 'operation', + buttons: [ + { + label: 'openDrawer', + type: 'button', + actionType: 'drawer', + drawer: { + body: { + type: 'form', + api: '/api/mock2/sample/${id}', + body: [ + { + type: 'input-text', + name: 'a', + label: 'A' + } + ] + } + } + } + ] + } + ] + } + }, + {}, + makeEnv({fetcher: mockFetcher, getModalContainer: () => container}) + ) + ); + await wait(200); + const saveBtn = container.querySelectorAll('tbody>tr button')[0]; + expect(saveBtn).toBeTruthy(); + fireEvent.click(saveBtn); + await wait(300); + + expect(getByText('确认')).toBeInTheDocument(); + fireEvent.click(getByText('取消')); + await wait(300); + + fireEvent.click(saveBtn); + await wait(300); + expect(getByText('确认')).toBeInTheDocument(); + + fireEvent.click(getByText('确认')); + await wait(500); + + expect(mockFetcher).toBeCalledTimes(3); + expect(listApiCalledCount).toBe(2); +}); + +// dialog 提交后如果配置列不刷新,则不刷新 +test('CRUD reload drawer2', async () => { + let listApiCalledCount = 0; + const mockFetcher = jest.fn().mockImplementation((api: any) => { + if (/^\/api\/mock2\/sample\/\d+/.test(api.url)) { + return Promise.resolve({ + data: { + status: 0 + } + }); + } + + listApiCalledCount++; + return Promise.resolve({ + data: { + status: 0, + data: { + items: [{id: 1, a: 'a1', b: 'b1'}] + } + } + }); + }); + const {container, getByText}: any = render( + amisRender( + { + type: 'page', + body: { + type: 'crud', + api: '/api/mock2/sample', + columns: [ + { + name: 'id', + label: 'ID' + }, + { + name: 'a', + label: 'A' + }, + { + name: 'b', + label: 'B' + }, + { + label: '操作', + type: 'operation', + buttons: [ + { + label: 'openDrawer', + type: 'button', + actionType: 'drawer', + reload: 'none', + drawer: { + body: { + type: 'form', + api: '/api/mock2/sample/${id}', + body: [ + { + type: 'input-text', + name: 'a', + label: 'A' + } + ] + } + } + } + ] + } + ] + } + }, + {}, + makeEnv({fetcher: mockFetcher, getModalContainer: () => container}) + ) + ); + await wait(200); + const saveBtn = container.querySelectorAll('tbody>tr button')[0]; + expect(saveBtn).toBeTruthy(); + fireEvent.click(saveBtn); + await wait(300); + + fireEvent.click(saveBtn); + await wait(300); + expect(getByText('确认')).toBeInTheDocument(); + + fireEvent.click(getByText('确认')); + await wait(500); + + expect(mockFetcher).toBeCalledTimes(2); + expect(listApiCalledCount).toBe(1); +}); diff --git a/packages/amis/src/renderers/CRUD.tsx b/packages/amis/src/renderers/CRUD.tsx index 5468ee196..b34718a21 100644 --- a/packages/amis/src/renderers/CRUD.tsx +++ b/packages/amis/src/renderers/CRUD.tsx @@ -702,7 +702,8 @@ export default class CRUD extends React.Component { prevIndex: idx - 1, index: idx }, - action.callback + action.callback, + delegate || (this.context as any) ); } else if (action.actionType === 'ajax') { store.setCurrentAction(action); @@ -1130,9 +1131,14 @@ export default class CRUD extends React.Component { actionType: 'dialog', dialog: dialog }); - store.openDialog(ctx, undefined, confirmed => { - resolve(confirmed); - }); + store.openDialog( + ctx, + undefined, + confirmed => { + resolve(confirmed); + }, + this.context as any + ); }); } diff --git a/packages/amis/src/renderers/Dialog.tsx b/packages/amis/src/renderers/Dialog.tsx index f6ee7ac05..f82ff9032 100644 --- a/packages/amis/src/renderers/Dialog.tsx +++ b/packages/amis/src/renderers/Dialog.tsx @@ -426,9 +426,14 @@ export default class Dialog extends React.Component { actionType: 'dialog', dialog: dialog }); - store.openDialog(ctx, undefined, confirmed => { - resolve(confirmed); - }); + store.openDialog( + ctx, + undefined, + confirmed => { + resolve(confirmed); + }, + this.context as any + ); }); } @@ -898,7 +903,12 @@ export class DialogRenderer extends Dialog { } } else if (action.actionType === 'dialog') { store.setCurrentAction(action); - store.openDialog(data, undefined, action.callback); + store.openDialog( + data, + undefined, + action.callback, + delegate || (this.context as any) + ); } else if (action.actionType === 'drawer') { store.setCurrentAction(action); store.openDrawer(data); @@ -1000,16 +1010,18 @@ export class DialogRenderer extends Dialog { ...rest: Array ) { super.handleDialogConfirm(values, action, ...rest); - const scoped = this.context as IScopedContext; const store = this.props.store; + const scoped = store.getDialogScoped() || (this.context as IScopedContext); const dialogAction = store.action as ActionObject; const reload = action.reload ?? dialogAction.reload; if (reload) { scoped.reload(reload, store.data); + } else if (scoped.component?.reload) { + scoped.component.reload(); } else { // 没有设置,则自动让页面中 crud 刷新。 - scoped + (this.context as IScopedContext) .getComponents() .filter((item: any) => item.props.type === 'crud') .forEach((item: any) => item.reload && item.reload()); @@ -1022,19 +1034,20 @@ export class DialogRenderer extends Dialog { ...rest: Array ) { super.handleDrawerConfirm(values, action); - const scoped = this.context as IScopedContext; const store = this.props.store; + const scoped = store.getDialogScoped() || (this.context as IScopedContext); const drawerAction = store.action as ActionObject; + const reload = action.reload ?? drawerAction.reload; // 稍等会,等动画结束。 setTimeout(() => { - if (drawerAction.reload) { - scoped.reload(drawerAction.reload, store.data); - } else if (action.reload) { - scoped.reload(action.reload, store.data); + if (reload) { + scoped.reload(reload, store.data); + } else if (scoped.component?.reload) { + scoped.component.reload(); } else { // 没有设置,则自动让页面中 crud 刷新。 - scoped + (this.context as IScopedContext) .getComponents() .filter((item: any) => item.props.type === 'crud') .forEach((item: any) => item.reload && item.reload()); diff --git a/packages/amis/src/renderers/Drawer.tsx b/packages/amis/src/renderers/Drawer.tsx index f0e848f73..07500c721 100644 --- a/packages/amis/src/renderers/Drawer.tsx +++ b/packages/amis/src/renderers/Drawer.tsx @@ -525,9 +525,14 @@ export default class Drawer extends React.Component { actionType: 'dialog', dialog: dialog }); - store.openDialog(ctx, undefined, confirmed => { - resolve(confirmed); - }); + store.openDialog( + ctx, + undefined, + confirmed => { + resolve(confirmed); + }, + this.context as any + ); }); } @@ -827,7 +832,12 @@ export class DrawerRenderer extends Drawer { store.openDrawer(data); } else if (action.actionType === 'dialog') { store.setCurrentAction(action); - store.openDialog(data, undefined, action.callback); + store.openDialog( + data, + undefined, + action.callback, + delegate || (this.context as any) + ); } else if (action.actionType === 'reload') { store.setCurrentAction(action); action.target && scoped.reload(action.target, data); @@ -913,16 +923,19 @@ export class DrawerRenderer extends Drawer { ...rest: Array ) { super.handleDialogConfirm(values, action, ...rest); - const scoped = this.context as IScopedContext; + const store = this.props.store; + const scoped = store.getDialogScoped() || (this.context as IScopedContext); const dialogAction = store.action as ActionObject; const reload = action.reload ?? dialogAction.reload; if (reload) { scoped.reload(reload, store.data); + } else if (scoped.component?.reload) { + scoped.component.reload(); } else { // 没有设置,则自动让页面中 crud 刷新。 - scoped + (this.context as IScopedContext) .getComponents() .filter((item: any) => item.props.type === 'crud') .forEach((item: any) => item.reload && item.reload()); @@ -935,19 +948,20 @@ export class DrawerRenderer extends Drawer { ...rest: Array ) { super.handleDrawerConfirm(values, action); - const scoped = this.context as IScopedContext; const store = this.props.store; + const scoped = store.getDialogScoped() || (this.context as IScopedContext); const drawerAction = store.action as ActionObject; + const reload = action.reload ?? drawerAction.reload; // 稍等会,等动画结束。 setTimeout(() => { - if (drawerAction.reload) { - scoped.reload(drawerAction.reload, store.data); - } else if (action.reload) { - scoped.reload(action.reload, store.data); + if (reload) { + scoped.reload(reload, store.data); + } else if (scoped.component?.reload) { + scoped.component.reload(); } else { // 没有设置,则自动让页面中 crud 刷新。 - scoped + (this.context as IScopedContext) .getComponents() .filter((item: any) => item.props.type === 'crud') .forEach((item: any) => item.reload && item.reload()); diff --git a/packages/amis/src/renderers/Page.tsx b/packages/amis/src/renderers/Page.tsx index 248aa9722..d819287fc 100644 --- a/packages/amis/src/renderers/Page.tsx +++ b/packages/amis/src/renderers/Page.tsx @@ -484,7 +484,12 @@ export default class Page extends React.Component { if (action.actionType === 'dialog') { store.setCurrentAction(action); - store.openDialog(ctx, undefined, action.callback, delegate); + store.openDialog( + ctx, + undefined, + action.callback, + delegate || (this.context as any) + ); } else if (action.actionType === 'drawer') { store.setCurrentAction(action); store.openDrawer(ctx, undefined, undefined, delegate); @@ -664,9 +669,14 @@ export default class Page extends React.Component { actionType: 'dialog', dialog: dialog }); - store.openDialog(ctx, undefined, confirmed => { - resolve(confirmed); - }); + store.openDialog( + ctx, + undefined, + confirmed => { + resolve(confirmed); + }, + this.context as any + ); }); } @@ -1066,9 +1076,11 @@ export class PageRenderer extends Page { if (reload) { scoped.reload(reload, store.data); + } else if (scoped?.component?.reload) { + scoped.component.reload(); } else { // 没有设置,则自动让页面中 crud 刷新。 - scoped + (this.context as IScopedContext) .getComponents() .filter((item: any) => item.props.type === 'crud') .forEach((item: any) => item.reload && item.reload()); @@ -1091,9 +1103,10 @@ export class PageRenderer extends Page { setTimeout(() => { if (reload) { scoped.reload(reload, store.data); + } else if (scoped?.component?.reload) { + scoped.component.reload(); } else { - // 没有设置,则自动让页面中 crud 刷新。 - scoped + (this.context as IScopedContext) .getComponents() .filter((item: any) => item.props.type === 'crud') .forEach((item: any) => item.reload && item.reload()); diff --git a/packages/amis/src/renderers/Service.tsx b/packages/amis/src/renderers/Service.tsx index fc71ebfd7..eb1fb91e7 100644 --- a/packages/amis/src/renderers/Service.tsx +++ b/packages/amis/src/renderers/Service.tsx @@ -695,9 +695,14 @@ export default class Service extends React.Component { actionType: 'dialog', dialog: dialog }); - store.openDialog(ctx, undefined, confirmed => { - resolve(confirmed); - }); + store.openDialog( + ctx, + undefined, + confirmed => { + resolve(confirmed); + }, + this.context as any + ); }); } diff --git a/packages/amis/src/renderers/Wizard.tsx b/packages/amis/src/renderers/Wizard.tsx index 149e2fbec..8e6d36dec 100644 --- a/packages/amis/src/renderers/Wizard.tsx +++ b/packages/amis/src/renderers/Wizard.tsx @@ -650,7 +650,12 @@ export default class Wizard extends React.Component { this.form.reset(); } else if (action.actionType === 'dialog') { store.setCurrentAction(action); - store.openDialog(data, undefined, action.callback); + store.openDialog( + data, + undefined, + action.callback, + delegate || (this.context as any) + ); } else if (action.actionType === 'ajax') { if (!action.api) { return env.alert(`当 actionType 为 ajax 时,请设置 api 属性`); @@ -743,9 +748,14 @@ export default class Wizard extends React.Component { actionType: 'dialog', dialog: dialog }); - store.openDialog(ctx, undefined, confirmed => { - resolve(confirmed); - }); + store.openDialog( + ctx, + undefined, + confirmed => { + resolve(confirmed); + }, + this.context as any + ); }); }