Merge branch 'main' into next

This commit is contained in:
nocobase[bot]
2026-07-08 01:20:54 +00:00
2 changed files with 59 additions and 4 deletions
@@ -60,7 +60,9 @@ type FlowPageProps = {
type FlowPageViewContext = FlowEngineContext & {
view?: {
inputArgs?: {
filterByTk?: unknown;
isMobileLayout?: unknown;
sourceId?: unknown;
};
};
};
@@ -102,6 +104,10 @@ export const FlowPage = React.memo((props: FlowPageProps & Record<string, unknow
subType: 'object',
use: pageModelClass,
};
const isRuntimeRecordScopedPage =
!flowEngine.context.flowSettingsEnabled &&
(typeof ctx?.view?.inputArgs?.filterByTk !== 'undefined' ||
typeof ctx?.view?.inputArgs?.sourceId !== 'undefined');
if (shouldInjectDefaultChildTab) {
const tabTitle = defaultTabTitle || flowEngine.translate?.('Details');
options['subModels'] = {
@@ -128,7 +134,9 @@ export const FlowPage = React.memo((props: FlowPageProps & Record<string, unknow
},
};
}
const data = await flowEngine.loadOrCreateModel(options, { skipSave: !flowEngine.context.flowSettingsEnabled });
const data =
(isRuntimeRecordScopedPage && (await flowEngine.loadModel({ ...options, refresh: true }))) ||
(await flowEngine.loadOrCreateModel(options, { skipSave: !flowEngine.context.flowSettingsEnabled }));
if (data?.uid && onModelLoaded) {
data.context.addDelegate(ctx);
bindViewLayoutState(data, ctx);
@@ -9,7 +9,7 @@
import { render, waitFor } from '@testing-library/react';
import React from 'react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { FlowPage } from '../FlowPage';
type TestContextProperty = {
@@ -71,10 +71,15 @@ const createPageModel = (): TestPageModel => {
};
const mocks = vi.hoisted(() => ({
flowSettingsEnabled: false,
loadModel: vi.fn(),
loadOrCreateModel: vi.fn(),
rendererMobileStates: [] as boolean[],
rendererProps: undefined as RendererProps | undefined,
model: undefined as TestPageModel | undefined,
viewFilterByTk: undefined as unknown,
viewInputMobileLayout: true as boolean | undefined,
viewSourceId: undefined as unknown,
contextMobileLayout: undefined as boolean | undefined,
}));
@@ -94,15 +99,20 @@ vi.mock('@nocobase/flow-engine', async () => {
}),
useFlowEngine: vi.fn(() => ({
getModelClassAsync: vi.fn(async () => TestPageModelClass),
loadOrCreateModel: vi.fn(async () => mocks.model),
context: {},
loadModel: mocks.loadModel,
loadOrCreateModel: mocks.loadOrCreateModel,
context: {
flowSettingsEnabled: mocks.flowSettingsEnabled,
},
translate: vi.fn((value: string) => value),
})),
useFlowModelById: vi.fn(() => mocks.model),
useFlowViewContext: vi.fn(() => ({
view: {
inputArgs: {
...(typeof mocks.viewFilterByTk !== 'undefined' ? { filterByTk: mocks.viewFilterByTk } : {}),
...(typeof mocks.viewInputMobileLayout === 'boolean' ? { isMobileLayout: mocks.viewInputMobileLayout } : {}),
...(typeof mocks.viewSourceId !== 'undefined' ? { sourceId: mocks.viewSourceId } : {}),
},
},
...(typeof mocks.contextMobileLayout === 'boolean' ? { isMobileLayout: mocks.contextMobileLayout } : {}),
@@ -154,11 +164,21 @@ vi.mock('ahooks', async () => {
});
describe('FlowPage', () => {
beforeEach(() => {
mocks.loadModel.mockImplementation(async () => null);
mocks.loadOrCreateModel.mockImplementation(async () => mocks.model);
});
afterEach(() => {
mocks.flowSettingsEnabled = false;
mocks.loadModel.mockReset();
mocks.loadOrCreateModel.mockReset();
mocks.rendererMobileStates = [];
mocks.rendererProps = undefined;
mocks.model = undefined;
mocks.viewFilterByTk = undefined;
mocks.viewInputMobileLayout = true;
mocks.viewSourceId = undefined;
mocks.contextMobileLayout = undefined;
});
@@ -203,4 +223,31 @@ describe('FlowPage', () => {
expect(mocks.rendererMobileStates[0]).toBe(expected);
},
);
it('reloads runtime page models for record scoped views', async () => {
mocks.model = createPageModel();
mocks.viewFilterByTk = 1;
mocks.loadModel.mockImplementation(async () => mocks.model);
render(<FlowPage onModelLoaded={vi.fn()} />);
await waitFor(() => {
expect(mocks.loadModel).toHaveBeenCalled();
});
expect(mocks.loadModel.mock.calls[0]?.[0]).toMatchObject({ refresh: true });
expect(mocks.loadOrCreateModel).not.toHaveBeenCalled();
});
it('keeps configured page model cache behavior in flow settings mode', async () => {
mocks.flowSettingsEnabled = true;
mocks.model = createPageModel();
mocks.viewFilterByTk = 1;
render(<FlowPage onModelLoaded={vi.fn()} />);
await waitFor(() => {
expect(mocks.loadOrCreateModel).toHaveBeenCalled();
});
expect(mocks.loadModel).not.toHaveBeenCalled();
});
});