Merge pull request #7411 from 2betop/crud-reload

fix: 修复crud 中 drawer 动作后不刷新问题   Close: #6903
This commit is contained in:
hsm-lv 2023-07-10 11:09:33 +08:00 committed by GitHub
commit 1314d93c30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 701 additions and 125 deletions

63
.vscode/launch.json vendored
View File

@ -1,71 +1,18 @@
{ {
// 使 IntelliSense "version": "1.0.0",
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [ "configurations": [
{ {
"type": "node", "type": "node",
"request": "launch", "request": "launch",
"name": "Jest All", "name": "Jest: current file",
//"env": { "NODE_ENV": "test" },
"program": "${workspaceFolder}/node_modules/.bin/jest", "program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["--runInBand"], "args": ["${fileBasenameNoExtension}"],
"sourceMaps": true,
"console": "integratedTerminal", "console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true, "disableOptimisticBPs": true,
"runtimeExecutable": "/usr/local/bin/node",
"windows": { "windows": {
"program": "${workspaceFolder}/node_modules/jest/bin/jest", "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."
} }
] ]
} }

View File

@ -160,7 +160,12 @@ export class RootRenderer extends React.Component<RootRendererProps> {
window.open(mailto); window.open(mailto);
} else if (action.actionType === 'dialog') { } else if (action.actionType === 'dialog') {
store.setCurrentAction(action); 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') { } else if (action.actionType === 'drawer') {
store.setCurrentAction(action); store.setCurrentAction(action);
store.openDrawer(ctx, undefined, undefined, delegate); store.openDrawer(ctx, undefined, undefined, delegate);
@ -323,9 +328,14 @@ export class RootRenderer extends React.Component<RootRendererProps> {
actionType: 'dialog', actionType: 'dialog',
dialog: dialog dialog: dialog
}); });
store.openDialog(ctx, undefined, confirmed => { store.openDialog(
ctx,
undefined,
confirmed => {
resolve(confirmed); resolve(confirmed);
}); },
this.context as any
);
}); });
} }

View File

@ -58,6 +58,8 @@ export interface ScopedComponentType extends React.Component<RendererProps> {
} }
export interface IScopedContext { export interface IScopedContext {
rendererType?: string;
component?: ScopedComponentType;
parent?: AliasIScopedContext; parent?: AliasIScopedContext;
children?: AliasIScopedContext[]; children?: AliasIScopedContext[];
registerComponent: (component: ScopedComponentType) => void; registerComponent: (component: ScopedComponentType) => void;
@ -69,6 +71,10 @@ export interface IScopedContext {
send: (target: string, ctx: RendererData) => void; send: (target: string, ctx: RendererData) => void;
close: (target: string) => void; close: (target: string) => void;
closeById: (target: string) => void; closeById: (target: string) => void;
getComponentsByRefPath: (
session: string,
path: string
) => ScopedComponentType[];
} }
type AliasIScopedContext = IScopedContext; type AliasIScopedContext = IScopedContext;
@ -78,14 +84,18 @@ export const ScopedContext = React.createContext(rootScopedContext);
function createScopedTools( function createScopedTools(
path?: string, path?: string,
parent?: AliasIScopedContext, parent?: AliasIScopedContext,
env?: RendererEnv env?: RendererEnv,
rendererType?: string
): IScopedContext { ): IScopedContext {
const components: Array<ScopedComponentType> = []; const components: Array<ScopedComponentType> = [];
const self = { const self: IScopedContext = {
rendererType,
component: undefined,
parent, parent,
registerComponent(component: ScopedComponentType) { registerComponent(component: ScopedComponentType) {
// 不要把自己注册在自己的 Scoped 上,自己的 Scoped 是给子节点们注册的。 // 不要把自己注册在自己的 Scoped 上,自己的 Scoped 是给子节点们注册的。
if (component.props.$path === path && parent) { if (component.props.$path === path && parent) {
self.component = component;
return parent.registerComponent(component); return parent.registerComponent(component);
} }
@ -404,7 +414,8 @@ export function HocScoped<
env: RendererEnv; env: RendererEnv;
} }
>( >(
ComposedComponent: React.ComponentType<T> ComposedComponent: React.ComponentType<T>,
rendererType?: string
): React.ComponentType< ): React.ComponentType<
T & { T & {
scopeRef?: (ref: any) => void; scopeRef?: (ref: any) => void;
@ -430,7 +441,8 @@ export function HocScoped<
this.scoped = createScopedTools( this.scoped = createScopedTools(
this.props.$path, this.props.$path,
context, context,
this.props.env this.props.env,
rendererType
); );
const scopeRef = props.scopeRef; const scopeRef = props.scopeRef;

View File

@ -186,7 +186,7 @@ export function registerRenderer(config: RendererConfig): RendererConfig {
} }
if (config.isolateScope) { if (config.isolateScope) {
config.component = Scoped(config.component); config.component = Scoped(config.component, config.type);
} }
const idx = findIndex( const idx = findIndex(

View File

@ -1146,7 +1146,12 @@ export default class Form extends React.Component<FormProps, object> {
action.target && action.target &&
this.reloadTarget(filterTarget(action.target, values), values); this.reloadTarget(filterTarget(action.target, values), values);
} else if (action.actionType === 'dialog') { } 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') { } else if (action.actionType === 'drawer') {
store.openDrawer(data); store.openDrawer(data);
} else if (isEffectiveApi(action.api || api, values)) { } else if (isEffectiveApi(action.api || api, values)) {
@ -1275,7 +1280,12 @@ export default class Form extends React.Component<FormProps, object> {
return this.validate(true, throwErrors); return this.validate(true, throwErrors);
} else if (action.actionType === 'dialog') { } else if (action.actionType === 'dialog') {
store.setCurrentAction(action); 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') { } else if (action.actionType === 'drawer') {
store.setCurrentAction(action); store.setCurrentAction(action);
store.openDrawer(data); store.openDrawer(data);
@ -1444,9 +1454,14 @@ export default class Form extends React.Component<FormProps, object> {
actionType: 'dialog', actionType: 'dialog',
dialog: dialog dialog: dialog
}); });
store.openDialog(ctx, undefined, confirmed => { store.openDialog(
ctx,
undefined,
confirmed => {
resolve(confirmed); resolve(confirmed);
}); },
this.context as any
);
}); });
} }

View File

@ -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);
});

View File

@ -702,7 +702,8 @@ export default class CRUD extends React.Component<CRUDProps, any> {
prevIndex: idx - 1, prevIndex: idx - 1,
index: idx index: idx
}, },
action.callback action.callback,
delegate || (this.context as any)
); );
} else if (action.actionType === 'ajax') { } else if (action.actionType === 'ajax') {
store.setCurrentAction(action); store.setCurrentAction(action);
@ -1130,9 +1131,14 @@ export default class CRUD extends React.Component<CRUDProps, any> {
actionType: 'dialog', actionType: 'dialog',
dialog: dialog dialog: dialog
}); });
store.openDialog(ctx, undefined, confirmed => { store.openDialog(
ctx,
undefined,
confirmed => {
resolve(confirmed); resolve(confirmed);
}); },
this.context as any
);
}); });
} }

View File

@ -426,9 +426,14 @@ export default class Dialog extends React.Component<DialogProps> {
actionType: 'dialog', actionType: 'dialog',
dialog: dialog dialog: dialog
}); });
store.openDialog(ctx, undefined, confirmed => { store.openDialog(
ctx,
undefined,
confirmed => {
resolve(confirmed); resolve(confirmed);
}); },
this.context as any
);
}); });
} }
@ -898,7 +903,12 @@ export class DialogRenderer extends Dialog {
} }
} else if (action.actionType === 'dialog') { } else if (action.actionType === 'dialog') {
store.setCurrentAction(action); 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') { } else if (action.actionType === 'drawer') {
store.setCurrentAction(action); store.setCurrentAction(action);
store.openDrawer(data); store.openDrawer(data);
@ -1000,16 +1010,18 @@ export class DialogRenderer extends Dialog {
...rest: Array<any> ...rest: Array<any>
) { ) {
super.handleDialogConfirm(values, action, ...rest); super.handleDialogConfirm(values, action, ...rest);
const scoped = this.context as IScopedContext;
const store = this.props.store; const store = this.props.store;
const scoped = store.getDialogScoped() || (this.context as IScopedContext);
const dialogAction = store.action as ActionObject; const dialogAction = store.action as ActionObject;
const reload = action.reload ?? dialogAction.reload; const reload = action.reload ?? dialogAction.reload;
if (reload) { if (reload) {
scoped.reload(reload, store.data); scoped.reload(reload, store.data);
} else if (scoped.component?.reload) {
scoped.component.reload();
} else { } else {
// 没有设置,则自动让页面中 crud 刷新。 // 没有设置,则自动让页面中 crud 刷新。
scoped (this.context as IScopedContext)
.getComponents() .getComponents()
.filter((item: any) => item.props.type === 'crud') .filter((item: any) => item.props.type === 'crud')
.forEach((item: any) => item.reload && item.reload()); .forEach((item: any) => item.reload && item.reload());
@ -1022,19 +1034,20 @@ export class DialogRenderer extends Dialog {
...rest: Array<any> ...rest: Array<any>
) { ) {
super.handleDrawerConfirm(values, action); super.handleDrawerConfirm(values, action);
const scoped = this.context as IScopedContext;
const store = this.props.store; const store = this.props.store;
const scoped = store.getDialogScoped() || (this.context as IScopedContext);
const drawerAction = store.action as ActionObject; const drawerAction = store.action as ActionObject;
const reload = action.reload ?? drawerAction.reload;
// 稍等会,等动画结束。 // 稍等会,等动画结束。
setTimeout(() => { setTimeout(() => {
if (drawerAction.reload) { if (reload) {
scoped.reload(drawerAction.reload, store.data); scoped.reload(reload, store.data);
} else if (action.reload) { } else if (scoped.component?.reload) {
scoped.reload(action.reload, store.data); scoped.component.reload();
} else { } else {
// 没有设置,则自动让页面中 crud 刷新。 // 没有设置,则自动让页面中 crud 刷新。
scoped (this.context as IScopedContext)
.getComponents() .getComponents()
.filter((item: any) => item.props.type === 'crud') .filter((item: any) => item.props.type === 'crud')
.forEach((item: any) => item.reload && item.reload()); .forEach((item: any) => item.reload && item.reload());

View File

@ -525,9 +525,14 @@ export default class Drawer extends React.Component<DrawerProps> {
actionType: 'dialog', actionType: 'dialog',
dialog: dialog dialog: dialog
}); });
store.openDialog(ctx, undefined, confirmed => { store.openDialog(
ctx,
undefined,
confirmed => {
resolve(confirmed); resolve(confirmed);
}); },
this.context as any
);
}); });
} }
@ -827,7 +832,12 @@ export class DrawerRenderer extends Drawer {
store.openDrawer(data); store.openDrawer(data);
} else if (action.actionType === 'dialog') { } else if (action.actionType === 'dialog') {
store.setCurrentAction(action); 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') { } else if (action.actionType === 'reload') {
store.setCurrentAction(action); store.setCurrentAction(action);
action.target && scoped.reload(action.target, data); action.target && scoped.reload(action.target, data);
@ -913,16 +923,19 @@ export class DrawerRenderer extends Drawer {
...rest: Array<any> ...rest: Array<any>
) { ) {
super.handleDialogConfirm(values, action, ...rest); super.handleDialogConfirm(values, action, ...rest);
const scoped = this.context as IScopedContext;
const store = this.props.store; const store = this.props.store;
const scoped = store.getDialogScoped() || (this.context as IScopedContext);
const dialogAction = store.action as ActionObject; const dialogAction = store.action as ActionObject;
const reload = action.reload ?? dialogAction.reload; const reload = action.reload ?? dialogAction.reload;
if (reload) { if (reload) {
scoped.reload(reload, store.data); scoped.reload(reload, store.data);
} else if (scoped.component?.reload) {
scoped.component.reload();
} else { } else {
// 没有设置,则自动让页面中 crud 刷新。 // 没有设置,则自动让页面中 crud 刷新。
scoped (this.context as IScopedContext)
.getComponents() .getComponents()
.filter((item: any) => item.props.type === 'crud') .filter((item: any) => item.props.type === 'crud')
.forEach((item: any) => item.reload && item.reload()); .forEach((item: any) => item.reload && item.reload());
@ -935,19 +948,20 @@ export class DrawerRenderer extends Drawer {
...rest: Array<any> ...rest: Array<any>
) { ) {
super.handleDrawerConfirm(values, action); super.handleDrawerConfirm(values, action);
const scoped = this.context as IScopedContext;
const store = this.props.store; const store = this.props.store;
const scoped = store.getDialogScoped() || (this.context as IScopedContext);
const drawerAction = store.action as ActionObject; const drawerAction = store.action as ActionObject;
const reload = action.reload ?? drawerAction.reload;
// 稍等会,等动画结束。 // 稍等会,等动画结束。
setTimeout(() => { setTimeout(() => {
if (drawerAction.reload) { if (reload) {
scoped.reload(drawerAction.reload, store.data); scoped.reload(reload, store.data);
} else if (action.reload) { } else if (scoped.component?.reload) {
scoped.reload(action.reload, store.data); scoped.component.reload();
} else { } else {
// 没有设置,则自动让页面中 crud 刷新。 // 没有设置,则自动让页面中 crud 刷新。
scoped (this.context as IScopedContext)
.getComponents() .getComponents()
.filter((item: any) => item.props.type === 'crud') .filter((item: any) => item.props.type === 'crud')
.forEach((item: any) => item.reload && item.reload()); .forEach((item: any) => item.reload && item.reload());

View File

@ -484,7 +484,12 @@ export default class Page extends React.Component<PageProps> {
if (action.actionType === 'dialog') { if (action.actionType === 'dialog') {
store.setCurrentAction(action); 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') { } else if (action.actionType === 'drawer') {
store.setCurrentAction(action); store.setCurrentAction(action);
store.openDrawer(ctx, undefined, undefined, delegate); store.openDrawer(ctx, undefined, undefined, delegate);
@ -664,9 +669,14 @@ export default class Page extends React.Component<PageProps> {
actionType: 'dialog', actionType: 'dialog',
dialog: dialog dialog: dialog
}); });
store.openDialog(ctx, undefined, confirmed => { store.openDialog(
ctx,
undefined,
confirmed => {
resolve(confirmed); resolve(confirmed);
}); },
this.context as any
);
}); });
} }
@ -1066,9 +1076,11 @@ export class PageRenderer extends Page {
if (reload) { if (reload) {
scoped.reload(reload, store.data); scoped.reload(reload, store.data);
} else if (scoped?.component?.reload) {
scoped.component.reload();
} else { } else {
// 没有设置,则自动让页面中 crud 刷新。 // 没有设置,则自动让页面中 crud 刷新。
scoped (this.context as IScopedContext)
.getComponents() .getComponents()
.filter((item: any) => item.props.type === 'crud') .filter((item: any) => item.props.type === 'crud')
.forEach((item: any) => item.reload && item.reload()); .forEach((item: any) => item.reload && item.reload());
@ -1091,9 +1103,10 @@ export class PageRenderer extends Page {
setTimeout(() => { setTimeout(() => {
if (reload) { if (reload) {
scoped.reload(reload, store.data); scoped.reload(reload, store.data);
} else if (scoped?.component?.reload) {
scoped.component.reload();
} else { } else {
// 没有设置,则自动让页面中 crud 刷新。 (this.context as IScopedContext)
scoped
.getComponents() .getComponents()
.filter((item: any) => item.props.type === 'crud') .filter((item: any) => item.props.type === 'crud')
.forEach((item: any) => item.reload && item.reload()); .forEach((item: any) => item.reload && item.reload());

View File

@ -695,9 +695,14 @@ export default class Service extends React.Component<ServiceProps> {
actionType: 'dialog', actionType: 'dialog',
dialog: dialog dialog: dialog
}); });
store.openDialog(ctx, undefined, confirmed => { store.openDialog(
ctx,
undefined,
confirmed => {
resolve(confirmed); resolve(confirmed);
}); },
this.context as any
);
}); });
} }

View File

@ -650,7 +650,12 @@ export default class Wizard extends React.Component<WizardProps, WizardState> {
this.form.reset(); this.form.reset();
} else if (action.actionType === 'dialog') { } else if (action.actionType === 'dialog') {
store.setCurrentAction(action); 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') { } else if (action.actionType === 'ajax') {
if (!action.api) { if (!action.api) {
return env.alert(`当 actionType 为 ajax 时,请设置 api 属性`); return env.alert(`当 actionType 为 ajax 时,请设置 api 属性`);
@ -743,9 +748,14 @@ export default class Wizard extends React.Component<WizardProps, WizardState> {
actionType: 'dialog', actionType: 'dialog',
dialog: dialog dialog: dialog
}); });
store.openDialog(ctx, undefined, confirmed => { store.openDialog(
ctx,
undefined,
confirmed => {
resolve(confirmed); resolve(confirmed);
}); },
this.context as any
);
}); });
} }