diff --git a/frontend/src/components/FormDesigner/components/ValidationRuleEditor.tsx b/frontend/src/components/FormDesigner/components/ValidationRuleEditor.tsx index 5dde7195..4ccd4f47 100644 --- a/frontend/src/components/FormDesigner/components/ValidationRuleEditor.tsx +++ b/frontend/src/components/FormDesigner/components/ValidationRuleEditor.tsx @@ -23,7 +23,7 @@ const ValidationRuleEditor: React.FC = ({ value = [], }; const newRules = [...value, newRule]; if (import.meta.env.DEV) { - console.log('➕ [ValidationRuleEditor] 添加验证规则:', newRules); + console.log('➕ [ValidationRuleEditor] 添加验证规则:', newRules); } onChange?.(newRules); }; @@ -31,7 +31,7 @@ const ValidationRuleEditor: React.FC = ({ value = [], const handleDeleteRule = (index: number) => { const newRules = value.filter((_, i) => i !== index); if (import.meta.env.DEV) { - console.log('🗑️ [ValidationRuleEditor] 删除验证规则:', newRules); + console.log('🗑️ [ValidationRuleEditor] 删除验证规则:', newRules); } onChange?.(newRules); }; @@ -40,7 +40,7 @@ const ValidationRuleEditor: React.FC = ({ value = [], const newRules = [...value]; newRules[index] = { ...newRules[index], [field]: fieldValue }; if (import.meta.env.DEV) { - console.log(`✏️ [ValidationRuleEditor] 修改验证规则 [${field}]:`, newRules); + console.log(`✏️ [ValidationRuleEditor] 修改验证规则 [${field}]:`, newRules); } onChange?.(newRules); }; diff --git a/frontend/src/components/ui/badge.tsx b/frontend/src/components/ui/badge.tsx index c8cd8851..7a67288a 100644 --- a/frontend/src/components/ui/badge.tsx +++ b/frontend/src/components/ui/badge.tsx @@ -4,7 +4,7 @@ import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" const badgeVariants = cva( - "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", { variants: { variant: { diff --git a/frontend/src/components/ui/dialog.tsx b/frontend/src/components/ui/dialog.tsx index bd5af875..32f1409f 100644 --- a/frontend/src/components/ui/dialog.tsx +++ b/frontend/src/components/ui/dialog.tsx @@ -47,7 +47,7 @@ const DialogOverlay = React.forwardRef< {children} - + Close diff --git a/frontend/src/components/ui/sheet.tsx b/frontend/src/components/ui/sheet.tsx index bdc84642..16d55f44 100644 --- a/frontend/src/components/ui/sheet.tsx +++ b/frontend/src/components/ui/sheet.tsx @@ -66,7 +66,7 @@ const SheetContent = React.forwardRef< > {children} {showClose && ( - + Close diff --git a/frontend/src/components/ui/toast.tsx b/frontend/src/components/ui/toast.tsx index f3b2ad6b..2e73c232 100644 --- a/frontend/src/components/ui/toast.tsx +++ b/frontend/src/components/ui/toast.tsx @@ -61,7 +61,7 @@ const ToastAction = React.forwardRef< = ({ {/* 部署按钮 */} - + + + +
+ +
+
+ {!environment.canDeploy && ( + +

您没有部署权限

+
+ )} +
+
{/* 部署表单对话框 */} = ({ // 审批信息 approval: { required: environment.requiresApproval ? 'true' : 'false', - userIds: environment.approvers?.map(a => a.userId.toString()).join(',') || '', + userNames: environment.approvers?.map(a => a.username) || [], }, // 通知信息(使用环境配置的通知设置) notification: { diff --git a/frontend/src/pages/Dashboard/index.tsx b/frontend/src/pages/Dashboard/index.tsx index 29d6a839..acfce387 100644 --- a/frontend/src/pages/Dashboard/index.tsx +++ b/frontend/src/pages/Dashboard/index.tsx @@ -78,19 +78,20 @@ const Dashboard: React.FC = () => { const response = await getDeployEnvironments(); - if (response && response.teams) { + // ✅ 新接口直接返回 teams 数组 + if (response && response.length > 0) { const prevTeamId = currentTeamId; const prevEnvId = currentEnvId; - setTeams(response.teams); + setTeams(response); if (isInitialLoad) { // 首次加载:默认选中第一个团队和第一个环境 - if (response.teams.length > 0) { - setCurrentTeamId(response.teams[0].teamId); + if (response.length > 0) { + setCurrentTeamId(response[0].teamId); - if (response.teams[0].environments.length > 0) { - setCurrentEnvId(response.teams[0].environments[0].environmentId); + if (response[0].environments.length > 0) { + setCurrentEnvId(response[0].environments[0].environmentId); } } setIsInitialLoad(false); @@ -98,12 +99,12 @@ const Dashboard: React.FC = () => { // 后续刷新:保持当前选中的团队和环境 // 如果之前选中的团队/环境仍然存在,保持选中 if (prevTeamId !== null) { - const teamExists = response.teams.some(t => t.teamId === prevTeamId); + const teamExists = response.some(t => t.teamId === prevTeamId); if (teamExists) { setCurrentTeamId(prevTeamId); if (prevEnvId !== null) { - const team = response.teams.find(t => t.teamId === prevTeamId); + const team = response.find(t => t.teamId === prevTeamId); const envExists = team?.environments.some(e => e.environmentId === prevEnvId); if (envExists) { setCurrentEnvId(prevEnvId); @@ -112,11 +113,11 @@ const Dashboard: React.FC = () => { setCurrentEnvId(team.environments[0].environmentId); } } - } else if (response.teams.length > 0) { + } else if (response.length > 0) { // 如果之前的团队不存在了,选择第一个团队 - setCurrentTeamId(response.teams[0].teamId); - if (response.teams[0].environments.length > 0) { - setCurrentEnvId(response.teams[0].environments[0].environmentId); + setCurrentTeamId(response[0].teamId); + if (response[0].environments.length > 0) { + setCurrentEnvId(response[0].environments[0].environmentId); } } } @@ -127,7 +128,7 @@ const Dashboard: React.FC = () => { let hasChanges = false; // 遍历所有团队、环境、应用,检查部署状态 - response.teams.forEach(team => { + response.forEach(team => { team.environments.forEach(env => { env.applications.forEach(app => { // 如果应用在 deploying 状态中,但最新状态不是 RUNNING,则移除 diff --git a/frontend/src/pages/Dashboard/types.ts b/frontend/src/pages/Dashboard/types.ts index 3b1dd85f..2fbb43bb 100644 --- a/frontend/src/pages/Dashboard/types.ts +++ b/frontend/src/pages/Dashboard/types.ts @@ -45,10 +45,12 @@ export interface ApplicationConfig { applicationName: string; applicationDesc?: string; branch: string; + deployBranch?: string; // 🆕 部署分支 deploySystemId?: number; deploySystemName?: string; deployJob?: string; workflowDefinitionId?: number; + workflowDefinitionFormId?: number; // 🆕 工作流表单ID workflowDefinitionName?: string; workflowDefinitionKey?: string; deployStatistics?: DeployStatistics; @@ -68,24 +70,31 @@ export interface DeployEnvironment { notificationEnabled: boolean; // 🆕 是否启用通知 notificationChannelId: number; // 🆕 通知渠道ID requireCodeReview: boolean; // 🆕 是否需要代码审查 + canDeploy: boolean; // 🆕 当前用户是否可以发起部署 + canApprove: boolean; // 🆕 当前用户是否可以审批部署 applications: ApplicationConfig[]; } +export interface TeamMember { + userId: number; + username: string; + realName: string; + roleInTeam: string; +} + export interface DeployTeam { teamId: number; teamCode: string; teamName: string; - teamRole: string | null; // ✅ 可能为 null description?: string; + ownerId: number; // 🆕 团队负责人ID + ownerName: string; // 🆕 团队负责人名称 + members: TeamMember[]; // 🆕 团队成员列表 environments: DeployEnvironment[]; } -export interface DeployEnvironmentsResponse { - userId: number; - username: string; - realName: string; - teams: DeployTeam[]; -} +// ✅ 新接口直接返回 teams 数组 +export type DeployEnvironmentsResponse = DeployTeam[]; export interface StartDeploymentRequest { teamApplicationId: number;