diff --git a/packages/core/client/src/flow/models/data-blocks/form/QuickEditForm.tsx b/packages/core/client/src/flow/models/data-blocks/form/QuickEditForm.tsx
index a32a7d8889..b4e619ef55 100644
--- a/packages/core/client/src/flow/models/data-blocks/form/QuickEditForm.tsx
+++ b/packages/core/client/src/flow/models/data-blocks/form/QuickEditForm.tsx
@@ -23,27 +23,28 @@ import {
import { Button, InputRef, Skeleton } from 'antd';
import _ from 'lodash';
import React, { createRef } from 'react';
+import { SkeletonFallback } from '../../../components/SkeletonFallback';
import { DataBlockModel } from '../../base/BlockModel';
export class QuickEditForm extends DataBlockModel {
form: Form;
fieldPath: string;
+
declare resource: SingleRecordResource;
declare collection: Collection;
static async open(options: {
target: any;
- flowEngine: FlowEngine;
dataSourceKey: string;
collectionName: string;
fieldPath: string;
filterByTk: string;
}) {
- const { flowEngine, dataSourceKey, collectionName, fieldPath, target, filterByTk } = options;
- const model = flowEngine.createModel({
+ const { target, dataSourceKey, collectionName, fieldPath, filterByTk } = options;
+ const model = this.flowEngine.createModel({
use: 'QuickEditForm',
stepParams: {
- initial: {
+ propsFlow: {
step1: {
dataSourceKey,
collectionName,
@@ -52,81 +53,75 @@ export class QuickEditForm extends DataBlockModel {
},
},
}) as QuickEditForm;
- await model.open({ target, filterByTk });
- options.flowEngine.removeModel(model.uid);
+
+ await this.flowEngine.context.popover.open({
+ target,
+ placement: 'rightTop',
+ content: (popover) => {
+ return (
+ }
+ model={model}
+ sharedContext={{ currentView: popover }}
+ extraContext={{ filterByTk }}
+ />
+ );
+ },
+ });
}
- async open({ target, filterByTk }: { target: any; filterByTk: string }) {
- await this.applyFlow('initial', { filterByTk });
- return new Promise((resolve, reject) => {
- const inputRef = createRef();
- const popover = this.ctx.globals.popover.open({
- target,
- content: (
-
- ),
- onRendered: () => {
- setTimeout(() => {
- // 聚焦 Popover 内第一个 input 或 textarea
- const el = document.querySelector(
- '.quick-edit-form input, .quick-edit-form textarea, .quick-edit-form select',
- ) as HTMLInputElement | HTMLTextAreaElement | null;
- el?.focus();
- }, 200);
- // inputRef.current.focus();
- },
- placement: 'rightTop',
- });
- });
+ render() {
+ return (
+
+ );
}
}
QuickEditForm.registerFlow({
- key: 'initial',
+ key: 'propsFlow',
+ auto: true,
steps: {
step1: {
async handler(ctx, params) {
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 49c965e706..68639826d1 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
@@ -164,7 +164,6 @@ export class TableModel extends DataBlockModel {
try {
await QuickEditForm.open({
target: ref.current,
- flowEngine: this.flowEngine,
dataSourceKey: this.collection.dataSourceKey,
collectionName: this.collection.name,
fieldPath: dataIndex,
diff --git a/packages/core/flow-engine/src/flowEngine.ts b/packages/core/flow-engine/src/flowEngine.ts
index aabc73534b..a12ad3722c 100644
--- a/packages/core/flow-engine/src/flowEngine.ts
+++ b/packages/core/flow-engine/src/flowEngine.ts
@@ -226,6 +226,7 @@ export class FlowEngine {
if (this.modelClasses.has(name)) {
console.warn(`FlowEngine: Model class with name '${name}' is already registered and will be overwritten.`);
}
+ (modelClass as typeof FlowModel).flowEngine = this; // 绑定 FlowEngine 实例到 Model 类
this.modelClasses.set(name, modelClass);
}
@@ -316,7 +317,7 @@ export class FlowEngine {
if (uid && this.modelInstances.has(uid)) {
return this.modelInstances.get(uid) as T;
}
- const modelInstance = new (ModelClass as ModelConstructor)({ ...options, flowEngine: this } as any);
+ const modelInstance = new (ModelClass as ModelConstructor)({ ...options } as any);
modelInstance.onInit(options);
diff --git a/packages/core/flow-engine/src/models/flowModel.tsx b/packages/core/flow-engine/src/models/flowModel.tsx
index d6be7878a3..9755356a2d 100644
--- a/packages/core/flow-engine/src/models/flowModel.tsx
+++ b/packages/core/flow-engine/src/models/flowModel.tsx
@@ -39,11 +39,13 @@ const modelMetas = new WeakMap();
const modelFlows = new WeakMap>();
export class FlowModel {
+ public static flowEngine: FlowEngine;
+
public readonly uid: string;
public sortIndex: number;
public props: IModelComponentProps = {};
public stepParams: StepParams = {};
- public flowEngine: FlowEngine;
+ // public flowEngine: FlowEngine;
public parent: ParentFlowModel;
public subModels: Structure['subModels'];
private _options: FlowModelOptions;
@@ -72,9 +74,12 @@ export class FlowModel {
private observerDispose: () => void;
constructor(options: FlowModelOptions) {
- if (options?.flowEngine?.getModel(options.uid)) {
+ if (!this.flowEngine) {
+ throw new Error('FlowModel must be initialized with a FlowEngine instance.');
+ }
+ if (this.flowEngine.getModel(options.uid)) {
// 此时 new FlowModel 并不创建新实例,而是返回已存在的实例,避免重复创建同一个model实例
- return options.flowEngine.getModel(options.uid);
+ return this.flowEngine.getModel(options.uid);
}
if (!options.uid) {
@@ -85,7 +90,6 @@ export class FlowModel {
this.props = options.props || {};
this.stepParams = options.stepParams || {};
this.subModels = {};
- this.flowEngine = options.flowEngine;
this.sortIndex = options.sortIndex || 0;
this._options = options;
@@ -132,6 +136,11 @@ export class FlowModel {
return modelMetas.get(this);
}
+ get flowEngine() {
+ // 取静态属性 flowEngine
+ return (this.constructor as typeof FlowModel).flowEngine;
+ }
+
private createSubModels(subModels: Record) {
Object.entries(subModels || {}).forEach(([key, value]) => {
if (Array.isArray(value)) {
@@ -162,7 +171,7 @@ export class FlowModel {
* @param {FlowEngine} flowEngine FlowEngine实例
*/
setFlowEngine(flowEngine: FlowEngine): void {
- this.flowEngine = flowEngine;
+ // this.flowEngine = flowEngine;
}
static define(meta: FlowModelMeta) {
diff --git a/packages/core/flow-engine/src/views/useDrawer.tsx b/packages/core/flow-engine/src/views/useDrawer.tsx
index 36271a7754..ac1320ee7e 100644
--- a/packages/core/flow-engine/src/views/useDrawer.tsx
+++ b/packages/core/flow-engine/src/views/useDrawer.tsx
@@ -40,8 +40,6 @@ export function useDrawer() {
// 支持 content 为函数,传递 currentDrawer
const content = typeof config.content === 'function' ? config.content(currentDrawer) : config.content;
- console.log('useDrawer open', config, content);
-
const drawer = (
(({ afterClose, content, placement, rect, ...props }, ref) => {
+ const [visible, setVisible] = React.useState(true);
+ const [config, setConfig] = React.useState({ content, placement, rect, ...props });
+
+ React.useImperativeHandle(ref, () => ({
+ destroy: () => setVisible(false),
+ update: (newConfig: any) => setConfig((prev) => ({ ...prev, ...newConfig })),
+ close: (result?: any) => setVisible(false),
+ }));
+
+ // 关闭后触发 afterClose
+ React.useEffect(() => {
+ if (!visible) {
+ afterClose?.();
+ }
+ }, [visible, afterClose]);
+
+ return (
+ document.body}
+ onOpenChange={(nextOpen) => {
+ setVisible(nextOpen);
+ if (!nextOpen) {
+ afterClose?.();
+ }
+ }}
+ {...config}
+ >
+
+
+ );
+});
+
export function usePopover() {
- const holderRef = React.useRef(null);
+ const holderRef = React.useRef(null);
const open = (config) => {
uuid += 1;
- const { target, placement = 'rightTop', content, onRendered, ...rest } = config;
- const popoverRef = React.createRef<{ destroy: () => void; update: (config: any) => void }>();
+ const { target, placement = 'rightTop', content, ...rest } = config;
+ const popoverRef = React.createRef();
// 计算目标位置
const rect = target?.getBoundingClientRect?.() ?? { top: 0, left: 0 };
// eslint-disable-next-line prefer-const
let closeFunc: (() => void) | undefined;
- const PopoverComponent = (props) => {
- const [open, setOpen] = React.useState(true);
- React.useEffect(() => {
- onRendered?.();
- }, []);
- return (
- setOpen(open)}
- content={content}
- placement={placement}
- getPopupContainer={() => document.body}
- {...rest}
- >
-
-
- );
- };
+ let resolvePromise: (value?: any) => void;
+ const promise = new Promise((resolve) => {
+ resolvePromise = resolve;
+ });
- const popover = ;
- // eslint-disable-next-line prefer-const
+ // 构造 currentPopover 实例
+ const currentPopover = {
+ destroy: () => popoverRef.current?.destroy(),
+ update: (newConfig) => popoverRef.current?.update(newConfig),
+ close: (result?: any) => {
+ resolvePromise?.(result);
+ popoverRef.current?.close(result);
+ },
+ };
+ const children = typeof content === 'function' ? content(currentPopover) : content;
+
+ const popover = (
+ {
+ closeFunc?.();
+ config.onClose?.();
+ resolvePromise?.(config.result);
+ }}
+ {...rest}
+ />
+ );
closeFunc = holderRef.current?.patchElement(popover);
- return {
- destroy: () => closeFunc?.(),
- // update: (newConfig) => ... // 可选:实现更新逻辑
- };
+ return Object.assign(promise, currentPopover);
};
const api = React.useMemo(() => ({ open }), []);