增加GIT代码检测节点

This commit is contained in:
dengqichen 2025-12-04 16:26:36 +08:00
parent d65e82b0e8
commit e03671c5de
5 changed files with 251 additions and 12 deletions

View File

@ -395,6 +395,46 @@ const TeamApplicationDialog: React.FC<TeamApplicationDialogProps> = ({
return;
}
// 源Git级联验证
if (formData.codeSourceSystemId) {
if (!formData.codeSourceProjectId) {
toast({
variant: 'destructive',
title: '请选择源仓库项目',
description: '已选择源Git系统必须选择对应的仓库项目',
});
return;
}
if (!formData.branch) {
toast({
variant: 'destructive',
title: '请选择源分支',
description: '已选择源Git系统必须选择对应的分支',
});
return;
}
}
// 目标Git级联验证
if (formData.targetGitSystemId) {
if (!formData.targetGitProjectId) {
toast({
variant: 'destructive',
title: '请选择目标仓库项目',
description: '已选择目标Git系统必须选择对应的仓库项目',
});
return;
}
if (!formData.targetBranch) {
toast({
variant: 'destructive',
title: '请选择目标分支',
description: '已选择目标Git系统必须选择对应的分支',
});
return;
}
}
setSaving(true);
try {
await onSave({

View File

@ -16,6 +16,7 @@ import { Separator } from '@/components/ui/separator';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { PaginatedTable, type ColumnDef, type SearchFieldDef, type PaginatedTableRef } from '@/components/ui/paginated-table';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import {
DropdownMenu,
DropdownMenuContent,
@ -153,22 +154,47 @@ const TeamList: React.FC = () => {
{
key: 'developmentMode',
title: '开发模式',
width: '160px',
width: '120px',
render: (_, record) => {
const modeOption = DEVELOPMENT_MODE_OPTIONS.find(opt => opt.value === record.developmentMode);
// 根据不同模式设置颜色
const getBadgeVariant = (mode: string) => {
switch (mode) {
case 'STANDARD': return 'outline' as const;
case 'SYNC_MODE': return 'default' as const; // 蓝色
case 'ARTIFACT_DELIVERY': return 'secondary' as const; // 灰色
default: return 'outline' as const;
}
};
return (
<div className="space-y-1">
<Badge variant="outline" className="inline-flex">
{modeOption?.label || record.developmentMode}
</Badge>
{record.enableGitSyncCheck && (
<div className="text-xs text-muted-foreground">
<Badge variant="secondary" className="text-xs">
Git同步检测
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Badge
variant={getBadgeVariant(record.developmentMode)}
className="cursor-help inline-flex items-center gap-1"
>
{modeOption?.label || record.developmentMode}
{record.enableGitSyncCheck && (
<span className="text-xs">🔄</span>
)}
</Badge>
</div>
)}
</div>
</TooltipTrigger>
<TooltipContent side="right" className="max-w-xs">
<div className="space-y-1 text-xs">
<div className="font-semibold">{modeOption?.label}</div>
<div className="text-muted-foreground">{modeOption?.description}</div>
{record.enableGitSyncCheck && (
<div className="text-blue-600 border-t pt-1 mt-1">
Git同步检测
</div>
)}
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
},
},

View File

@ -0,0 +1,167 @@
import {ConfigurableNodeDefinition, NodeType, NodeCategory, defineNodeOutputs} from './types';
import {DataSourceType} from '@/domain/dataSource';
/**
* Git同步检测节点定义
*
*/
export const GitSyncCheckNodeDefinition: ConfigurableNodeDefinition = {
nodeCode: "GIT_SYNC_CHECK",
nodeName: "Git同步检测",
nodeType: NodeType.GIT_SYNC_CHECK,
category: NodeCategory.TASK,
description: "检测源分支与目标分支的同步状态",
// 渲染配置
renderConfig: {
shape: 'rounded-rect',
size: {width: 140, height: 48},
icon: {
type: 'emoji',
content: '🔄', // 同步图标
size: 32
},
theme: {
primary: '#3b82f6', // 蓝色主题与Git同步的视觉一致
secondary: '#2563eb',
selectedBorder: '#3b82f6',
hoverBorder: '#60a5fa',
gradient: ['#ffffff', '#dbeafe']
},
handles: {
input: true,
output: true
},
features: {
showBadge: true,
showHoverMenu: true
}
},
// 输入配置Schema
inputMappingSchema: {
type: "object",
title: "输入",
description: "Git同步检测配置",
properties: {
continueOnFailure: {
type: "boolean",
title: "失败后继续",
description: "true: 发现差异时标记为FAILURE但继续执行false: 发现差异时抛出BpmnError终止流程",
default: true
},
sourceGitSystemId: {
type: "number",
title: "源Git系统",
description: "内网Git系统数据源或变量",
"x-dataSource": DataSourceType.GIT_REPOSITORIES,
"x-allow-variable": true
},
sourceGitProjectId: {
type: "number",
title: "源Git项目",
description: "源仓库项目ID输入变量如 ${teamApplication.codeSourceProjectId}",
"x-allow-variable": true,
"x-placeholder": "${teamApplication.codeSourceProjectId}"
},
sourceBranch: {
type: "string",
title: "源分支",
description: "源分支名称(输入变量,如 ${teamApplication.branch}",
"x-allow-variable": true,
"x-placeholder": "${teamApplication.branch}"
},
targetGitSystemId: {
type: "number",
title: "目标Git系统",
description: "客户Git系统数据源或变量",
"x-dataSource": DataSourceType.GIT_REPOSITORIES,
"x-allow-variable": true
},
targetGitProjectId: {
type: "number",
title: "目标Git项目",
description: "目标仓库项目ID输入变量如 ${teamApplication.targetGitProjectId}",
"x-allow-variable": true,
"x-placeholder": "${teamApplication.targetGitProjectId}"
},
targetBranch: {
type: "string",
title: "目标分支",
description: "目标分支名称(输入变量,如 ${teamApplication.targetBranch}",
"x-allow-variable": true,
"x-placeholder": "${teamApplication.targetBranch}"
}
},
required: ["sourceGitSystemId", "sourceGitProjectId", "sourceBranch", "targetGitSystemId", "targetGitProjectId", "targetBranch"]
},
// 输出定义
outputs: defineNodeOutputs(
{
name: "hasDifference",
title: "是否存在差异",
type: "boolean",
description: "源分支和目标分支是否存在代码差异",
example: true,
required: true
},
{
name: "commitsAhead",
title: "源分支领先提交数",
type: "number",
description: "源分支比目标分支多出的提交数量",
example: 5,
required: true
},
{
name: "commitsBehind",
title: "目标分支领先提交数",
type: "number",
description: "目标分支比源分支多出的提交数量",
example: 0,
required: true
},
{
name: "differenceCommits",
title: "差异提交列表",
type: "array",
description: "差异提交详情列表最多显示20条",
example: [
{
"commitId": "a3f5e8d",
"message": "feat: 添加新功能",
"author": "张三",
"commitTime": "2025-12-04 10:30:00"
}
],
required: false
},
{
name: "sourceLatestCommit",
title: "源分支最新提交SHA",
type: "string",
description: "源分支最新提交的完整SHA值",
example: "a3f5e8d2c4b1a5e9f2d3e7b8c9d1a2f3e4b5c6d7",
required: true
},
{
name: "targetLatestCommit",
title: "目标分支最新提交SHA",
type: "string",
description: "目标分支最新提交的完整SHA值",
example: "b2e4c7f8d1a3e5b9c2d6f9a8e7d1c4b5a3f6e8d2",
required: true
},
{
name: "checkDetail",
title: "检查结果详情",
type: "string",
description: "检查结果的详细说明(用于通知模板)",
example: "源分支 'develop' 领先目标分支 'master' 5个提交需要同步代码",
required: true
}
)
};
// ✅ 不再需要单独的渲染组件,使用 BaseNode 即可

View File

@ -8,6 +8,7 @@ import BaseNode from './components/BaseNode';
import { StartEventNodeDefinition } from './StartEventNode';
import { EndEventNodeDefinition } from './EndEventNode';
import { JenkinsBuildNodeDefinition } from './JenkinsBuildNode';
import { GitSyncCheckNodeDefinition } from './GitSyncCheckNode';
import { NotificationNodeDefinition } from './NotificationNode';
import { ApprovalNodeDefinition } from './ApprovalNode';
import { HttpRequestNodeDefinition } from './HttpRequestNode';
@ -21,6 +22,7 @@ export const NODE_DEFINITIONS: WorkflowNodeDefinition[] = [
StartEventNodeDefinition,
EndEventNodeDefinition,
JenkinsBuildNodeDefinition,
GitSyncCheckNodeDefinition,
NotificationNodeDefinition,
ApprovalNodeDefinition,
HttpRequestNodeDefinition,
@ -35,6 +37,7 @@ export const nodeTypes = {
START_EVENT: BaseNode,
END_EVENT: BaseNode,
JENKINS_BUILD: BaseNode,
GIT_SYNC_CHECK: BaseNode,
NOTIFICATION: BaseNode,
APPROVAL: BaseNode,
HTTP_REQUEST: BaseNode,
@ -52,6 +55,7 @@ export {
StartEventNodeDefinition,
EndEventNodeDefinition,
JenkinsBuildNodeDefinition,
GitSyncCheckNodeDefinition,
NotificationNodeDefinition,
ApprovalNodeDefinition,
HttpRequestNodeDefinition,

View File

@ -18,6 +18,7 @@ export enum NodeType {
NOTIFICATION = 'NOTIFICATION',
APPROVAL = 'APPROVAL',
HTTP_REQUEST = 'HTTP_REQUEST',
GIT_SYNC_CHECK = 'GIT_SYNC_CHECK',
GATEWAY_NODE = 'GATEWAY_NODE',
SUB_PROCESS = 'SUB_PROCESS',
CALL_ACTIVITY = 'CALL_ACTIVITY'
@ -35,6 +36,7 @@ export const NODE_CATEGORY_MAP: Record<NodeType, NodeCategory> = {
[NodeType.NOTIFICATION]: NodeCategory.TASK,
[NodeType.APPROVAL]: NodeCategory.TASK,
[NodeType.HTTP_REQUEST]: NodeCategory.TASK,
[NodeType.GIT_SYNC_CHECK]: NodeCategory.TASK,
[NodeType.GATEWAY_NODE]: NodeCategory.GATEWAY,
[NodeType.SUB_PROCESS]: NodeCategory.CONTAINER,
[NodeType.CALL_ACTIVITY]: NodeCategory.CONTAINER,