From e03671c5de2e787fb4b5e04949a3d22c4934a0b1 Mon Sep 17 00:00:00 2001 From: dengqichen Date: Thu, 4 Dec 2025 16:26:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0GIT=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A3=80=E6=B5=8B=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../List/components/TeamApplicationDialog.tsx | 40 +++++ frontend/src/pages/Deploy/Team/List/index.tsx | 50 ++++-- .../Design/nodes/GitSyncCheckNode.tsx | 167 ++++++++++++++++++ .../src/pages/Workflow/Design/nodes/index.ts | 4 + .../src/pages/Workflow/Design/nodes/types.ts | 2 + 5 files changed, 251 insertions(+), 12 deletions(-) create mode 100644 frontend/src/pages/Workflow/Design/nodes/GitSyncCheckNode.tsx diff --git a/frontend/src/pages/Deploy/Team/List/components/TeamApplicationDialog.tsx b/frontend/src/pages/Deploy/Team/List/components/TeamApplicationDialog.tsx index 48c14757..8367eb6d 100644 --- a/frontend/src/pages/Deploy/Team/List/components/TeamApplicationDialog.tsx +++ b/frontend/src/pages/Deploy/Team/List/components/TeamApplicationDialog.tsx @@ -395,6 +395,46 @@ const TeamApplicationDialog: React.FC = ({ 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({ diff --git a/frontend/src/pages/Deploy/Team/List/index.tsx b/frontend/src/pages/Deploy/Team/List/index.tsx index f81cb044..e61c9386 100644 --- a/frontend/src/pages/Deploy/Team/List/index.tsx +++ b/frontend/src/pages/Deploy/Team/List/index.tsx @@ -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 ( -
- - {modeOption?.label || record.developmentMode} - - {record.enableGitSyncCheck && ( -
- - Git同步检测 + + + + + {modeOption?.label || record.developmentMode} + {record.enableGitSyncCheck && ( + 🔄 + )} -
- )} -
+ + +
+
{modeOption?.label}
+
{modeOption?.description}
+ {record.enableGitSyncCheck && ( +
+ ✓ 已启用Git同步检测 +
+ )} +
+
+ + ); }, }, diff --git a/frontend/src/pages/Workflow/Design/nodes/GitSyncCheckNode.tsx b/frontend/src/pages/Workflow/Design/nodes/GitSyncCheckNode.tsx new file mode 100644 index 00000000..8aa216fe --- /dev/null +++ b/frontend/src/pages/Workflow/Design/nodes/GitSyncCheckNode.tsx @@ -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 即可 diff --git a/frontend/src/pages/Workflow/Design/nodes/index.ts b/frontend/src/pages/Workflow/Design/nodes/index.ts index 7db40301..3ecbfa69 100644 --- a/frontend/src/pages/Workflow/Design/nodes/index.ts +++ b/frontend/src/pages/Workflow/Design/nodes/index.ts @@ -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, diff --git a/frontend/src/pages/Workflow/Design/nodes/types.ts b/frontend/src/pages/Workflow/Design/nodes/types.ts index 315f9971..31f0e567 100644 --- a/frontend/src/pages/Workflow/Design/nodes/types.ts +++ b/frontend/src/pages/Workflow/Design/nodes/types.ts @@ -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.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,