From 82e36f0b398f646551774663cc895f58977ffc04 Mon Sep 17 00:00:00 2001 From: dengqichen Date: Fri, 27 Dec 2024 17:40:23 +0800 Subject: [PATCH] 1 --- frontend/src/pages/Dashboard/index.tsx | 582 +++++++++++------- .../pages/Deploy/Application/List/service.ts | 4 + .../pages/Deploy/Application/List/types.ts | 6 + 3 files changed, 375 insertions(+), 217 deletions(-) diff --git a/frontend/src/pages/Dashboard/index.tsx b/frontend/src/pages/Dashboard/index.tsx index 044bf441..ee1dec2e 100644 --- a/frontend/src/pages/Dashboard/index.tsx +++ b/frontend/src/pages/Dashboard/index.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Progress } from "@/components/ui/progress"; @@ -20,90 +20,195 @@ import { ChevronRight, CheckCircle, AlertTriangle, - XCircle + XCircle, + Loader2, + ServerCrash, + Server } from "lucide-react"; +import { getEnvironmentList } from '@/pages/Deploy/Environment/List/service'; +import { getDevelopmentLanguages } from '@/pages/Deploy/Application/List/service'; +import { getDeploymentConfigPage } from '@/pages/Deploy/Deployment/List/service'; +import type { Environment } from '@/pages/Deploy/Environment/List/types'; +import type { DevelopmentLanguageType } from '@/pages/Deploy/Application/List/types'; +import type { DeploymentConfig, DeploymentConfigQueryParams } from '@/pages/Deploy/Deployment/List/types'; +import type { Page } from '@/types/base'; -// Mock环境数据 -const environments = [ - { - id: "dev", - name: "开发环境", - projectCount: 10, - status: "success", - lastDeployment: "10分钟前", - cpu: 60, - memory: 70, - storage: 50 - }, - { - id: "test", - name: "测试环境", - projectCount: 8, - status: "warning", - lastDeployment: "1小时前", - cpu: 80, - memory: 75, - storage: 60 - }, - { - id: "staging", - name: "预发环境", - projectCount: 5, - status: "success", - lastDeployment: "2小时前", - cpu: 40, - memory: 50, - storage: 30 - }, - { - id: "prod", - name: "生产环境", - projectCount: 12, - status: "error", - lastDeployment: "1天前", - cpu: 90, - memory: 85, - storage: 70 - } -]; +type EnvironmentStatus = 'success' | 'warning' | 'error'; -// Mock项目数据 -const projects = [ - { - id: 1, - name: "用户中心", - code: "user-center", - type: "微服务", - version: "v2.3.1", - status: "活跃", - buildStatus: "success", - lastDeployment: "30分钟前" - }, - { - id: 2, - name: "订单系统", - code: "order-system", - type: "后端服务", - version: "v1.7.0", - status: "活跃", - buildStatus: "error", - lastDeployment: "2小时前" - }, - { - id: 3, - name: "前端门户", - code: "frontend-portal", - type: "前端应用", - version: "v3.1.2", - status: "活跃", - buildStatus: "running", - lastDeployment: "1天前" - } -]; +// 扩展环境类型,添加监控数据 +interface EnhancedEnvironment extends Environment { + projectCount: number; + status: EnvironmentStatus; + lastDeployment: string; + cpu: number; + memory: number; + storage: number; +} + +const EmptyState: React.FC<{ title: string; description: string; icon: React.ReactNode }> = ({ + title, + description, + icon +}) => ( +
+
+ {icon} +
+

{title}

+

{description}

+
+); + +const LoadingState = () => ( +
+
+ +

加载中,请稍候...

+
+
+); const Dashboard: React.FC = () => { const [projectType, setProjectType] = useState(""); const [status, setStatus] = useState(""); + const [environments, setEnvironments] = useState([]); + const [loading, setLoading] = useState(true); + const [languages, setLanguages] = useState([]); + const [deployConfigs, setDeployConfigs] = useState([]); + const [searchText, setSearchText] = useState(""); + const [currentEnvId, setCurrentEnvId] = useState(); + + // 获取环境和语言数据 + useEffect(() => { + const fetchData = async () => { + try { + setLoading(true); + const [envResponse, langResponse] = await Promise.all([ + getEnvironmentList(), + getDevelopmentLanguages() + ]); + + if (envResponse) { + const enrichedEnvironments = envResponse.map(env => { + const randomStatus: EnvironmentStatus = Math.random() > 0.7 ? 'warning' : 'success'; + return { + ...env, + projectCount: 0, // 初始化为0,后续更新 + status: randomStatus, + lastDeployment: '暂无部署', + cpu: Math.floor(Math.random() * 40) + 40, + memory: Math.floor(Math.random() * 30) + 50, + storage: Math.floor(Math.random() * 40) + 30, + }; + }); + setEnvironments(enrichedEnvironments); + if (enrichedEnvironments.length > 0) { + setCurrentEnvId(enrichedEnvironments[0].id); + } + } + + if (langResponse) { + setLanguages(langResponse); + } + } catch (error) { + console.error('Failed to fetch data:', error); + } finally { + setLoading(false); + } + }; + + fetchData(); + }, []); + + // 获取部署配置数据 + useEffect(() => { + const fetchDeployConfigs = async () => { + if (!currentEnvId) return; + + try { + const queryParams: DeploymentConfigQueryParams = { + pageSize: 100, + pageNum: 1, + environmentId: currentEnvId, + workflowDefinitionId: 0 + }; + + const response = await getDeploymentConfigPage(queryParams); + + if (response) { + setDeployConfigs(response.content); + // 更新环境的项目数量 + setEnvironments(prevEnvs => + prevEnvs.map(env => + env.id === currentEnvId + ? { ...env, projectCount: response.totalElements } + : env + ) + ); + } + } catch (error) { + console.error('Failed to fetch deployment configs:', error); + } + }; + + fetchDeployConfigs(); + }, [currentEnvId]); + + const handleSearch = async () => { + if (!currentEnvId) return; + + try { + const queryParams: DeploymentConfigQueryParams = { + pageSize: 100, + pageNum: 1, + environmentId: currentEnvId, + workflowDefinitionId: 0, + enabled: status === 'active' ? true : status === 'paused' ? false : undefined + }; + + const response = await getDeploymentConfigPage(queryParams); + + if (response) { + // 在前端过滤开发语言 + const filteredConfigs = response.content.filter(config => { + if (projectType && config.languageType !== projectType) { + return false; + } + return true; + }); + setDeployConfigs(filteredConfigs); + } + } catch (error) { + console.error('Failed to search deployment configs:', error); + } + }; + + const handleReset = () => { + setSearchText(""); + setProjectType(""); + setStatus(""); + if (currentEnvId) { + const queryParams: DeploymentConfigQueryParams = { + pageSize: 100, + pageNum: 1, + environmentId: currentEnvId, + workflowDefinitionId: 0 + }; + + getDeploymentConfigPage(queryParams).then(response => { + if (response) { + setDeployConfigs(response.content); + } + }); + } + }; + + const handleTabChange = (envCode: string) => { + const env = environments.find(e => e.envCode === envCode); + if (env) { + setCurrentEnvId(env.id); + } + }; const getStatusIcon = (status: string) => { switch (status) { @@ -118,13 +223,11 @@ const Dashboard: React.FC = () => { } }; - const getBuildStatusBadge = (status: string) => { - const statusConfig = { - success: { className: "bg-green-100 text-green-800", text: "成功" }, - error: { className: "bg-red-100 text-red-800", text: "失败" }, - running: { className: "bg-blue-100 text-blue-800", text: "进行中" } - }; - const config = statusConfig[status as keyof typeof statusConfig] || statusConfig.running; + const getBuildStatusBadge = (enabled: boolean) => { + const config = enabled + ? { className: "bg-green-100 text-green-800", text: "活跃" } + : { className: "bg-red-100 text-red-800", text: "暂停" }; + return ( {config.text} @@ -132,149 +235,194 @@ const Dashboard: React.FC = () => { ); }; + if (loading) { + return ; + } + + const hasEnvironments = environments.length > 0; + const hasProjects = deployConfigs.length > 0; + return (

部署环境概览

-
- {environments.map((env) => ( - - - {env.name} - {getStatusIcon(env.status)} - - -
{env.projectCount}
-

个项目

-
-
- - 最近部署: {env.lastDeployment} -
-
-
- CPU - {env.cpu}% + + {!hasEnvironments ? ( + + + } + title="暂无环境数据" + description="当前系统中还没有配置任何环境。请先添加部署环境,然后开始使用部署功能。" + /> + + + ) : ( + <> +
+ {environments.map((env) => ( + + + {env.envName} + {getStatusIcon(env.status)} + + +
{env.projectCount}
+

个项目

+
+
+ + 最近部署: {env.lastDeployment} +
+
+
+ CPU + {env.cpu}% +
+ +
+
+
+ 内存 + {env.memory}% +
+ +
+
+
+ 存储 + {env.storage}% +
+ +
- -
-
-
- 内存 - {env.memory}% -
- -
-
-
- 存储 - {env.storage}% -
- -
-
- - - ))} -
- -
- -
- - {environments.map((env) => ( - - {env.name} - - ))} - + + + ))}
- {environments.map((env) => ( - -
-
- - - -
- - -
-
+
+ +
+ + {environments.map((env) => ( + + {env.envName} + + ))} +
-
- {projects.map((project) => ( - - -
-
-

{project.name}

-

{project.code}

-
- {getBuildStatusBadge(project.buildStatus)} -
-
-
-

类型

-

{project.type}

-
-
-

版本

-

{project.version}

-
-
-

状态

-

{project.status}

-
-
-

最近部署

-

{project.lastDeployment}

-
-
-
- -
-
-
- ))} -
- - ))} -
-
+
+
+ + {!hasProjects ? ( + + + } + title="暂无项目数据" + description="当前环境中还没有配置任何项目。请先创建项目,然后开始部署。" + /> + + + ) : ( +
+ {deployConfigs.map((config) => ( + + +
+
+

{config.application.appName}

+

{config.application.appCode}

+
+ {getBuildStatusBadge(config.enabled)} +
+
+
+

构建类型

+

{config.buildType}

+
+
+

开发语言

+

{config.languageType}

+
+
+

工作流

+

{config.publishedWorkflowDefinition?.name || '未配置'}

+
+
+

最近更新

+

{new Date(config.updateTime).toLocaleString()}

+
+
+
+ + +
+
+
+ ))} +
+ )} + + ))} + +
+ + )}
); }; diff --git a/frontend/src/pages/Deploy/Application/List/service.ts b/frontend/src/pages/Deploy/Application/List/service.ts index 04183e71..834fde12 100644 --- a/frontend/src/pages/Deploy/Application/List/service.ts +++ b/frontend/src/pages/Deploy/Application/List/service.ts @@ -1,6 +1,7 @@ import request from '@/utils/request'; import type { CreateApplicationRequest, UpdateApplicationRequest, Application, ApplicationQuery } from './types'; import type { Page } from '@/types/base'; +import {DevelopmentLanguageType} from "./types"; const BASE_URL = '/api/v1/applications'; @@ -31,3 +32,6 @@ export const getApplicationList = () => // 条件查询应用列表 export const getApplicationListByCondition = (params?: ApplicationQuery) => request.get(`${BASE_URL}/list`, { params }); + +export const getDevelopmentLanguages = () => + request.get(`${BASE_URL}/development-languages`); diff --git a/frontend/src/pages/Deploy/Application/List/types.ts b/frontend/src/pages/Deploy/Application/List/types.ts index e3b66e24..84075af7 100644 --- a/frontend/src/pages/Deploy/Application/List/types.ts +++ b/frontend/src/pages/Deploy/Application/List/types.ts @@ -40,4 +40,10 @@ export interface ApplicationQuery extends BaseQuery { appCode?: string; appName?: string; enabled?: boolean; + language?: string; +} + +export interface DevelopmentLanguageType { + code: string; + name: string; }