This commit is contained in:
dengqichen 2024-12-24 10:36:37 +08:00
parent b9d559a683
commit 7ad20a0cbd
5 changed files with 90 additions and 73 deletions

View File

@ -117,18 +117,6 @@ const EnvironmentModal: React.FC<EnvironmentModalProps> = ({
/>
</Form.Item>
<Form.Item
name="deployType"
label="部署方式"
rules={[{required: true, message: '请选择部署方式'}]}
>
<Select
placeholder="请选择部署方式"
options={deployTypeOptions}
style={{width: '100%'}}
/>
</Form.Item>
<Form.Item
name="envDesc"
label="环境描述"

View File

@ -31,26 +31,6 @@ const buildTypeMap = {
},
};
const deployTypeMap = {
[DeployTypeEnum.K8S]: {
label: 'Kubernetes集群部署',
color: '#1890ff',
icon: <CloudServerOutlined/>,
description: '部署到Kubernetes容器编排平台'
},
[DeployTypeEnum.DOCKER]: {
label: 'Docker容器部署',
color: '#13c2c2',
icon: <RocketOutlined/>,
description: '部署为Docker独立容器'
},
[DeployTypeEnum.VM]: {
label: '虚拟机部署',
color: '#faad14',
icon: <SettingOutlined/>,
description: '部署到传统虚拟机环境'
},
};
const EnvironmentList: React.FC = () => {
const [environments, setEnvironments] = useState<Environment[]>([]);
@ -96,8 +76,6 @@ const EnvironmentList: React.FC = () => {
const EnvironmentCard = ({environment}: { environment: Environment }) => {
const buildType = buildTypeMap[environment.buildType];
const deployType = deployTypeMap[environment.deployType];
return (
<Card
hoverable

View File

@ -4,6 +4,8 @@ import type {ProjectGroup} from '../types';
import type {Environment} from '../../../Environment/List/types';
import {createProjectGroup, updateProjectGroup} from '../service';
import {getEnvironmentList} from '../../../Environment/List/service';
import {BuildTypeEnum} from "../../../Environment/List/types";
import {ProjectGroupTypeEnum} from "../types";
interface ProjectGroupModalProps {
visible: boolean;
@ -12,6 +14,11 @@ interface ProjectGroupModalProps {
initialValues?: ProjectGroup;
}
const buildProjectGroupTypes = [
{label: '产品', value: ProjectGroupTypeEnum.PRODUCT},
{label: '项目', value: ProjectGroupTypeEnum.PROJECT}
];
const ProjectGroupModal: React.FC<ProjectGroupModalProps> = ({
visible,
onCancel,
@ -90,6 +97,17 @@ const ProjectGroupModal: React.FC<ProjectGroupModalProps> = ({
layout="vertical"
initialValues={{projectGroupStatus: 'ENABLE', sort: 0}}
>
<Form.Item
name="type"
label="项目组类型"
rules={[{required: true, message: '请选择项目组类型'}]}
>
<Select
placeholder="请选择项目组类型"
options={buildProjectGroupTypes}
style={{width: '100%'}}
/>
</Form.Item>
<Form.Item
name="projectGroupCode"
label="项目组编码"
@ -141,6 +159,13 @@ const ProjectGroupModal: React.FC<ProjectGroupModalProps> = ({
<Radio value="DISABLE"></Radio>
</Radio.Group>
</Form.Item>
<Form.Item
name="sort"
label="排序"
rules={[{required: true, message: '请输入排序值'}]}
>
<InputNumber min={0} placeholder="请输入排序值" style={{width: '100%'}}/>
</Form.Item>
</Form>
</Modal>
);

View File

@ -61,32 +61,33 @@ const ProjectList: React.FC = () => {
setModalVisible(true);
};
const getProjectTypeInfo = (code: string) => {
if (code.toUpperCase().includes('DEMO')) {
return {
type: 'DEMO',
label: '示例项目组',
color: '#1890ff',
icon: <RocketOutlined/>,
description: '用于演示和测试的项目组'
};
const getProjectTypeInfo = (type: string) => {
switch (type) {
case 'PRODUCT':
return {
type: 'PRODUCT',
label: '产品项目组',
color: '#1890ff',
icon: <RocketOutlined/>,
description: '产品相关的项目组'
};
case 'PLATFORM':
return {
type: 'PLATFORM',
label: '平台项目组',
color: '#52c41a',
icon: <EnvironmentOutlined/>,
description: '平台相关的项目组'
};
default:
return {
type: 'BUSINESS',
label: '业务项目组',
color: '#722ed1',
icon: <TeamOutlined/>,
description: '业务相关的项目组'
};
}
if (code.toUpperCase().includes('PLATFORM')) {
return {
type: 'PLATFORM',
label: '平台项目组',
color: '#52c41a',
icon: <EnvironmentOutlined/>,
description: '平台相关的核心项目组'
};
}
return {
type: 'BUSINESS',
label: '业务项目组',
color: '#722ed1',
icon: <TeamOutlined/>,
description: '具体业务相关的项目组'
};
};
const filteredProjects = projects.filter(project => {
@ -97,13 +98,13 @@ const ProjectList: React.FC = () => {
) : true;
const matchesType = projectType === 'ALL' ? true :
getProjectTypeInfo(project.projectGroupCode).type === projectType;
getProjectTypeInfo(project.type).type === projectType;
return matchesSearch && matchesType;
});
const ProjectCard = ({project}: { project: ProjectGroup }) => {
const typeInfo = getProjectTypeInfo(project.projectGroupCode);
const ProjectCard = ({projectGroup}: { projectGroup: ProjectGroup }) => {
const typeInfo = getProjectTypeInfo(projectGroup.type);
const Icon = typeInfo.icon;
return (
@ -146,7 +147,7 @@ const ProjectList: React.FC = () => {
alignItems: 'center',
gap: '8px'
}}>
{project.projectGroupName}
{projectGroup.projectGroupName}
<Tag
color={typeInfo.color}
style={{
@ -172,7 +173,7 @@ const ProjectList: React.FC = () => {
display: '-webkit-box',
}}
>
{project.projectGroupDesc || '暂无描述'}
{projectGroup.projectGroupDesc || '暂无描述'}
</Text>
</div>
<div style={{
@ -205,7 +206,7 @@ const ProjectList: React.FC = () => {
borderRadius: '6px',
letterSpacing: '0.5px',
}}>
{project.projectGroupCode}
{projectGroup.projectGroupCode}
</div>
</div>
@ -213,7 +214,7 @@ const ProjectList: React.FC = () => {
<Col span={8}>
<Statistic
title={<Text type="secondary" style={{fontSize: '13px'}}></Text>}
value={2}
value={projectGroup.environments.length}
prefix={<EnvironmentOutlined/>}
valueStyle={{fontSize: '16px', color: typeInfo.color}}
/>
@ -221,7 +222,7 @@ const ProjectList: React.FC = () => {
<Col span={8}>
<Statistic
title={<Text type="secondary" style={{fontSize: '13px'}}></Text>}
value={5}
value={projectGroup.applications.length}
prefix={<TeamOutlined/>}
valueStyle={{fontSize: '16px', color: typeInfo.color}}
/>
@ -229,7 +230,6 @@ const ProjectList: React.FC = () => {
<Col span={8}>
<Statistic
title={<Text type="secondary" style={{fontSize: '13px'}}></Text>}
value={5}
prefix={<TeamOutlined/>}
valueStyle={{fontSize: '16px', color: typeInfo.color}}
/>
@ -242,7 +242,7 @@ const ProjectList: React.FC = () => {
<Button
type="primary"
icon={<EditOutlined/>}
onClick={() => handleEdit(project)}
onClick={() => handleEdit(projectGroup)}
style={{
borderRadius: '6px',
background: typeInfo.color,
@ -254,7 +254,7 @@ const ProjectList: React.FC = () => {
<Popconfirm
title="确定要删除该项目组吗?"
description="删除后将无法恢复,请谨慎操作"
onConfirm={() => handleDelete(project.id)}
onConfirm={() => handleDelete(projectGroup.id)}
>
<Button
danger
@ -312,6 +312,21 @@ const ProjectList: React.FC = () => {
style={{width: '100%'}}
/>
</Col>
<Col>
<Select
placeholder="项目组类型"
style={{ width: 200 }}
value={projectType}
onChange={setProjectType}
options={[
{ label: '全部类型', value: 'ALL' },
{ label: '产品项目组', value: 'PRODUCT' },
{ label: '平台项目组', value: 'PLATFORM' },
{ label: '业务项目组', value: 'BUSINESS' }
]}
size="large"
/>
</Col>
</Row>
</div>
@ -319,7 +334,7 @@ const ProjectList: React.FC = () => {
<Row gutter={[24, 24]}>
{filteredProjects.map(project => (
<Col xs={24} sm={12} md={8} lg={6} key={project.id}>
<ProjectCard project={project}/>
<ProjectCard projectGroup={project}/>
</Col>
))}
<Col xs={24} sm={12} md={8} lg={6}>

View File

@ -1,20 +1,31 @@
import { BaseResponse, BaseRequest, BaseQuery } from '@/types/base';
import { Environment } from '../../Environment/List/types';
import {BaseResponse, BaseRequest, BaseQuery} from '@/types/base';
import {Environment} from '../../Environment/List/types';
import {Application} from "@/pages/Deploy/Application/List/types";
export enum ProjectGroupTypeEnum {
PRODUCT = 'PRODUCT',
PROJECT = 'PROJECT'
}
// 项目基础信息
export interface ProjectGroup extends BaseResponse {
tenantCode: string;
type: ProjectGroupTypeEnum;
projectGroupCode: string;
projectGroupName: string;
projectGroupDesc?: string;
projectGroupStatus: 'ENABLE' | 'DISABLE';
environments: Environment[];
applications: Application[];
sort: number;
}
// 创建项目请求参数
export interface CreateProjectGroupRequest extends BaseRequest {
tenantCode: string;
type: ProjectGroupTypeEnum;
projectGroupCode: string;
projectGroupName: string;
projectGroupDesc?: string;