From a521faee7ba318daf99cf464c5ce6a2fed4d42b9 Mon Sep 17 00:00:00 2001 From: chenos Date: Sun, 29 Jun 2025 16:19:05 +0800 Subject: [PATCH] fix: improve code --- packages/core/client/src/flow/FlowPage.tsx | 34 +++++++++++++++---- .../client/src/flow/models/base/PageModel.tsx | 4 +-- .../src/flow/models/base/PageTabModel.tsx | 4 +-- .../data-blocks/table/TableColumnModel.tsx | 24 ++++++++++--- .../models/data-blocks/table/TableModel.tsx | 19 +++++++++-- packages/core/flow-engine/src/flowEngine.ts | 22 +++++++++--- .../core/flow-engine/src/models/flowModel.tsx | 2 +- 7 files changed, 84 insertions(+), 25 deletions(-) diff --git a/packages/core/client/src/flow/FlowPage.tsx b/packages/core/client/src/flow/FlowPage.tsx index 1f1a8a7910..5e46747d3a 100644 --- a/packages/core/client/src/flow/FlowPage.tsx +++ b/packages/core/client/src/flow/FlowPage.tsx @@ -15,15 +15,15 @@ import { useParams } from 'react-router-dom'; import { useKeepAlive } from '../route-switch'; import { SkeletonFallback } from './components/SkeletonFallback'; -function InternalFlowPage({ uid, sharedContext }) { +function InternalFlowPage({ uid, ...props }) { const model = useFlowModelById(uid); return ( } - showFlowSettings={{ showBackground: false, showBorder: false }} hideRemoveInSettings + showFlowSettings={{ showBackground: false, showBorder: false }} + {...props} /> ); } @@ -32,6 +32,7 @@ export const FlowRoute = () => { const layoutContentRef = useRef(null); const flowEngine = useFlowEngine(); const params = useParams(); + // console.log('FlowRoute params:', params); // const { active } = useKeepAlive(); const model = useMemo(() => { return flowEngine.createModel({ @@ -49,13 +50,13 @@ export const FlowRoute = () => { model.setSharedContext({ layoutContentElement: layoutContentRef.current, }); - model.dispatchEvent('click', { target: layoutContentRef.current }); - }, [model, params.name]); + model.dispatchEvent('click', { target: layoutContentRef.current, activeTab: params.tabUid }); + }, [model, params.name, params.tabUid]); return
; }; export const FlowPage = (props) => { - const { parentId, sharedContext } = props; + const { parentId, ...rest } = props; const flowEngine = useFlowEngine(); const { loading, data } = useRequest( async () => { @@ -71,6 +72,7 @@ export const FlowPage = (props) => { use: 'PageTabModel', subModels: { grid: { + async: true, use: 'BlockGridModel', }, }, @@ -88,5 +90,23 @@ export const FlowPage = (props) => { if (loading || !data?.uid) { return ; } - return ; + return ; +}; + +export const RemoteFlowModelRenderer = (props) => { + const { uid, parentId, ...rest } = props; + const flowEngine = useFlowEngine(); + const { loading, data } = useRequest( + async () => { + const data = await flowEngine.loadModel({ uid, parentId }); + return data; + }, + { + refreshDeps: [uid, parentId], + }, + ); + if (loading || !data?.uid) { + return ; + } + return ; }; diff --git a/packages/core/client/src/flow/models/base/PageModel.tsx b/packages/core/client/src/flow/models/base/PageModel.tsx index 1f96e390d0..57e480a07a 100644 --- a/packages/core/client/src/flow/models/base/PageModel.tsx +++ b/packages/core/client/src/flow/models/base/PageModel.tsx @@ -11,10 +11,10 @@ import { PlusOutlined } from '@ant-design/icons'; import { PageHeader } from '@ant-design/pro-layout'; import { uid } from '@formily/shared'; import { FlowModel, FlowModelRenderer, FlowSettingsButton } from '@nocobase/flow-engine'; +import { tval } from '@nocobase/utils/client'; import { Tabs } from 'antd'; import _ from 'lodash'; import React from 'react'; -import { tval } from '@nocobase/utils/client'; type PageModelStructure = { subModels: { @@ -29,7 +29,7 @@ export class PageModel extends FlowModel { } getItems() { - return this.subModels.tabs?.map((tab) => { + return this.mapSubModels('tabs', (tab) => { return { key: tab.uid, label: tab.props.label || 'Unnamed', diff --git a/packages/core/client/src/flow/models/base/PageTabModel.tsx b/packages/core/client/src/flow/models/base/PageTabModel.tsx index 74663fdbab..95ea066bc0 100644 --- a/packages/core/client/src/flow/models/base/PageTabModel.tsx +++ b/packages/core/client/src/flow/models/base/PageTabModel.tsx @@ -9,6 +9,7 @@ import { FlowModel, FlowModelRenderer } from '@nocobase/flow-engine'; import React from 'react'; +import { RemoteFlowModelRenderer } from '../../FlowPage'; import { BlockGridModel } from './GridModel'; export class PageTabModel extends FlowModel<{ @@ -17,10 +18,9 @@ export class PageTabModel extends FlowModel<{ }; }> { render() { - console.log('TabFlowModel render', this.uid); return (
- +
); } diff --git a/packages/core/client/src/flow/models/data-blocks/table/TableColumnModel.tsx b/packages/core/client/src/flow/models/data-blocks/table/TableColumnModel.tsx index 14e4179ad7..10fc4be813 100644 --- a/packages/core/client/src/flow/models/data-blocks/table/TableColumnModel.tsx +++ b/packages/core/client/src/flow/models/data-blocks/table/TableColumnModel.tsx @@ -8,10 +8,11 @@ */ import { QuestionCircleOutlined } from '@ant-design/icons'; +import { css } from '@emotion/css'; import { FlowsFloatContextMenu } from '@nocobase/flow-engine'; +import { tval } from '@nocobase/utils/client'; import { TableColumnProps, Tooltip } from 'antd'; import React from 'react'; -import { tval } from '@nocobase/utils/client'; import { FieldModel } from '../../base/FieldModel'; import { ReadPrettyFieldModel } from '../../fields/ReadPrettyField/ReadPrettyFieldModel'; @@ -24,9 +25,19 @@ export class TableColumnModel extends FieldModel { showBorder={false} settingsMenuLevel={2} > - {this.props.title} +
+ {this.props.title} +
); + console.log('TableColumnModel props:', this.props); return { ...this.props, ellipsis: true, @@ -43,7 +54,7 @@ export class TableColumnModel extends FieldModel { onCell: (record) => ({ record, width: this.props.width, - editable: this.props.editable || false, + editable: this.props.editable, dataIndex: this.props.dataIndex, title: this.props.title, // handleSave, @@ -120,6 +131,7 @@ TableColumnModel.registerFlow({ }; }, handler(ctx, params) { + console.log('editColumTitle params:', params); const title = ctx.globals.flowEngine.translate(params.title || ctx.model.collectionField?.title); ctx.model.setProps('title', title); }, @@ -162,8 +174,10 @@ TableColumnModel.registerFlow({ 'x-decorator': 'FormItem', }, }, - defaultParams: { - editable: false, + defaultParams(ctx) { + return { + editable: ctx.model.parent.props.editable || false, + }; }, handler(ctx, params) { ctx.model.setProps('editable', params.editable); diff --git a/packages/core/client/src/flow/models/data-blocks/table/TableModel.tsx b/packages/core/client/src/flow/models/data-blocks/table/TableModel.tsx index 63c0c9893d..dd4b81577f 100644 --- a/packages/core/client/src/flow/models/data-blocks/table/TableModel.tsx +++ b/packages/core/client/src/flow/models/data-blocks/table/TableModel.tsx @@ -109,7 +109,6 @@ export class TableModel extends DataBlockModel { }, ]} onModelCreated={async (model: TableColumnModel) => { - // model.setSharedContext({ currentBlockModel: this }); await model.applyAutoFlows(); }} onSubModelAdded={async (model: TableColumnModel) => { @@ -222,7 +221,6 @@ export class TableModel extends DataBlockModel { ); } @@ -240,7 +238,6 @@ export class TableModel extends DataBlockModel { ); } @@ -287,6 +284,22 @@ TableModel.registerFlow({ key: 'default', auto: true, steps: { + enableEditable: { + title: tval('Editable'), + uiSchema: { + editable: { + 'x-component': 'Switch', + 'x-decorator': 'FormItem', + }, + }, + defaultParams: { + editable: false, + }, + handler(ctx, params) { + console.log('enableEditable params:', params); + ctx.model.setProps('editable', params.editable); + }, + }, step1: { paramsRequired: true, hideInSettings: true, diff --git a/packages/core/flow-engine/src/flowEngine.ts b/packages/core/flow-engine/src/flowEngine.ts index 25993af49e..cafccdd070 100644 --- a/packages/core/flow-engine/src/flowEngine.ts +++ b/packages/core/flow-engine/src/flowEngine.ts @@ -8,6 +8,7 @@ */ import { observable } from '@formily/reactive'; import { FlowSettings } from './flowSettings'; +import { initFlowEngineLocale } from './locale'; import { FlowModel } from './models'; import { ReactView } from './ReactView'; import { @@ -20,7 +21,6 @@ import { ModelConstructor, } from './types'; import { isInheritedFrom } from './utils'; -import { initFlowEngineLocale } from './locale'; interface ApplyFlowCacheEntry { status: 'pending' | 'resolved' | 'rejected'; @@ -42,14 +42,26 @@ export class FlowEngine { private modelRepository: IFlowModelRepository | null = null; private _applyFlowCache = new Map(); - reactView: ReactView; + /** + * 实验性 API:用于在 FlowEngine 中集成 React 视图渲染能力。 + * 该属性未来可能发生重大变更或被移除,请谨慎依赖。 + * @experimental + */ + public reactView: ReactView; constructor() { this.reactView = new ReactView(this); this.flowSettings.registerScopes({ t: this.translate.bind(this) }); } - // 注册默认的 FlowModel + /** + * 设置模型仓库,用于持久化和查询模型实例。 + * 如果之前已设置过模型仓库,将会覆盖原有设置,并输出警告。 + * + * @param modelRepository 要设置的模型仓库实例,实现 IFlowModelRepository 接口。 + * @example + * flowEngine.setModelRepository(new MyFlowModelRepository()); + */ setModelRepository(modelRepository: IFlowModelRepository) { if (this.modelRepository) { console.warn('FlowEngine: Model repository is already set and will be overwritten.'); @@ -375,9 +387,9 @@ export class FlowEngine { return true; } - async loadModel(uid: string): Promise { + async loadModel(options): Promise { if (!this.ensureModelRepository()) return; - const data = await this.modelRepository.findOne({ uid }); + const data = await this.modelRepository.findOne(options); return data?.uid ? this.createModel(data as any) : null; } diff --git a/packages/core/flow-engine/src/models/flowModel.tsx b/packages/core/flow-engine/src/models/flowModel.tsx index 94d8868b47..48587e9f2e 100644 --- a/packages/core/flow-engine/src/models/flowModel.tsx +++ b/packages/core/flow-engine/src/models/flowModel.tsx @@ -901,7 +901,7 @@ export class FlowModel