feat(flows): 新增流程编辑器基础功能与相关组件

feat(backend): 添加流程模型与服务支持
feat(frontend): 实现流程编辑器UI与交互
feat(assets): 添加流程节点图标资源
feat(plugins): 实现上下文菜单和运行时插件
feat(components): 新增基础节点和侧边栏组件
feat(routes): 添加流程相关路由配置
feat(models): 创建流程和运行日志数据模型
feat(services): 实现流程服务层逻辑
feat(migration): 添加流程相关数据库迁移
feat(config): 更新前端配置支持流程编辑器
feat(utils): 增强axios错误处理和工具函数
This commit is contained in:
2025-09-15 00:27:13 +08:00
parent 9da3978f91
commit b0963e5e37
291 changed files with 17947 additions and 86 deletions

View File

@ -0,0 +1,168 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { useCallback, useEffect, useState } from 'react';
import {
FlowNodeFormData,
FormModelV2,
FreeOperationType,
HistoryService,
TransformData,
useCurrentEntity,
usePlayground,
useService,
} from '@flowgram.ai/free-layout-editor';
import { CommentEditorFormField } from '../constant';
export const useSize = () => {
const node = useCurrentEntity();
const nodeMeta = node.getNodeMeta();
const playground = usePlayground();
const historyService = useService(HistoryService);
const { size = { width: 240, height: 150 } } = nodeMeta;
const transform = node.getData(TransformData);
const formModel = node.getData(FlowNodeFormData).getFormModel<FormModelV2>();
const formSize = formModel.getValueIn<{ width: number; height: number }>(
CommentEditorFormField.Size
);
const [width, setWidth] = useState(formSize?.width ?? size.width);
const [height, setHeight] = useState(formSize?.height ?? size.height);
// 初始化表单值
useEffect(() => {
const initSize = formModel.getValueIn<{ width: number; height: number }>(
CommentEditorFormField.Size
);
if (!initSize) {
formModel.setValueIn(CommentEditorFormField.Size, {
width,
height,
});
}
}, [formModel, width, height]);
// 同步表单外部值变化:初始化/undo/redo/协同
useEffect(() => {
const disposer = formModel.onFormValuesChange(({ name }) => {
if (name !== CommentEditorFormField.Size) {
return;
}
const newSize = formModel.getValueIn<{ width: number; height: number }>(
CommentEditorFormField.Size
);
if (!newSize) {
return;
}
setWidth(newSize.width);
setHeight(newSize.height);
});
return () => disposer.dispose();
}, [formModel]);
const onResize = useCallback(() => {
const resizeState = {
width,
height,
originalWidth: width,
originalHeight: height,
positionX: transform.position.x,
positionY: transform.position.y,
offsetX: 0,
offsetY: 0,
};
const resizing = (delta: { top: number; right: number; bottom: number; left: number }) => {
if (!resizeState) {
return;
}
const { zoom } = playground.config;
const top = delta.top / zoom;
const right = delta.right / zoom;
const bottom = delta.bottom / zoom;
const left = delta.left / zoom;
const minWidth = 120;
const minHeight = 80;
const newWidth = Math.max(minWidth, resizeState.originalWidth + right - left);
const newHeight = Math.max(minHeight, resizeState.originalHeight + bottom - top);
// 如果宽度或高度小于最小值,则不更新偏移量
const newOffsetX =
(left > 0 || right < 0) && newWidth <= minWidth
? resizeState.offsetX
: left / 2 + right / 2;
const newOffsetY =
(top > 0 || bottom < 0) && newHeight <= minHeight ? resizeState.offsetY : top;
const newPositionX = resizeState.positionX + newOffsetX;
const newPositionY = resizeState.positionY + newOffsetY;
resizeState.width = newWidth;
resizeState.height = newHeight;
resizeState.offsetX = newOffsetX;
resizeState.offsetY = newOffsetY;
// 更新状态
setWidth(newWidth);
setHeight(newHeight);
// 更新偏移量
transform.update({
position: {
x: newPositionX,
y: newPositionY,
},
});
};
const resizeEnd = () => {
historyService.transact(() => {
historyService.pushOperation(
{
type: FreeOperationType.dragNodes,
value: {
ids: [node.id],
value: [
{
x: resizeState.positionX + resizeState.offsetX,
y: resizeState.positionY + resizeState.offsetY,
},
],
oldValue: [
{
x: resizeState.positionX,
y: resizeState.positionY,
},
],
},
},
{
noApply: true,
}
);
formModel.setValueIn(CommentEditorFormField.Size, {
width: resizeState.width,
height: resizeState.height,
});
});
};
return {
resizing,
resizeEnd,
};
}, [node, width, height, transform, playground, formModel, historyService]);
return {
width,
height,
onResize,
};
};