1
This commit is contained in:
parent
ab3330fe95
commit
2d41b2793f
@ -240,36 +240,11 @@ const ApplicationList: React.FC = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer
|
<>
|
||||||
header={{
|
|
||||||
title: '应用管理',
|
|
||||||
subTitle: (
|
|
||||||
<Space>
|
|
||||||
<span>当前项目组:</span>
|
|
||||||
<Select
|
|
||||||
value={selectedProjectGroupId}
|
|
||||||
onChange={handleProjectChange}
|
|
||||||
style={{width: 200}}
|
|
||||||
options={projectGroups.map(project => ({
|
|
||||||
label: (
|
|
||||||
<Space>
|
|
||||||
{project.projectGroupName}
|
|
||||||
<Tag color={getProjectTypeInfo(project.type).color}>
|
|
||||||
{getProjectTypeInfo(project.type).label}
|
|
||||||
</Tag>
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
value: project.id,
|
|
||||||
}))}
|
|
||||||
/>
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ProTable<Application>
|
<ProTable<Application>
|
||||||
columns={columns}
|
columns={columns}
|
||||||
actionRef={actionRef}
|
actionRef={actionRef}
|
||||||
scroll={{x: 1300}}
|
scroll={{x: 'max-content'}}
|
||||||
cardBordered
|
cardBordered
|
||||||
request={async (params) => {
|
request={async (params) => {
|
||||||
if (!selectedProjectGroupId) {
|
if (!selectedProjectGroupId) {
|
||||||
@ -343,7 +318,7 @@ const ApplicationList: React.FC = () => {
|
|||||||
projectGroupId={selectedProjectGroupId}
|
projectGroupId={selectedProjectGroupId}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</PageContainer>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import React, {useEffect, useState} from 'react';
|
import React, {useEffect} from 'react';
|
||||||
import {Modal, Form, Input, Select, message} from 'antd';
|
import {Modal, Form, Input, InputNumber, Select, message} from 'antd';
|
||||||
import type {Environment} from '../types';
|
import type {Environment} from '../types';
|
||||||
import {BuildTypeEnum, DeployTypeEnum} from '../types';
|
import {BuildTypeEnum, DeployTypeEnum} from '../types';
|
||||||
import {createEnvironment, updateEnvironment} from '../service';
|
import {createEnvironment, updateEnvironment} from '../service';
|
||||||
|
import {getBuildTypeInfo, getDeployTypeInfo} from '../utils';
|
||||||
|
|
||||||
interface EnvironmentModalProps {
|
interface EnvironmentModalProps {
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
@ -12,105 +13,133 @@ interface EnvironmentModalProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const EnvironmentModal: React.FC<EnvironmentModalProps> = ({
|
const EnvironmentModal: React.FC<EnvironmentModalProps> = ({
|
||||||
visible,
|
visible,
|
||||||
onCancel,
|
onCancel,
|
||||||
onSuccess,
|
onSuccess,
|
||||||
initialValues,
|
initialValues,
|
||||||
}) => {
|
}) => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [loading, setLoading] = useState(false);
|
const isEdit = !!initialValues?.id;
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible) {
|
if (visible && initialValues) {
|
||||||
form.setFieldsValue(initialValues || {});
|
form.setFieldsValue(initialValues);
|
||||||
}
|
}
|
||||||
}, [visible, initialValues]);
|
}, [visible, initialValues, form]);
|
||||||
|
|
||||||
const handleOk = async () => {
|
const handleSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
const values = await form.validateFields();
|
const values = await form.validateFields();
|
||||||
setLoading(true);
|
if (isEdit) {
|
||||||
if (initialValues?.id) {
|
|
||||||
await updateEnvironment({
|
await updateEnvironment({
|
||||||
...values,
|
...values,
|
||||||
id: initialValues.id,
|
id: initialValues.id,
|
||||||
});
|
});
|
||||||
message.success('更新成功');
|
|
||||||
} else {
|
} else {
|
||||||
await createEnvironment(values);
|
await createEnvironment(values);
|
||||||
message.success('创建成功');
|
|
||||||
}
|
}
|
||||||
|
message.success(`${isEdit ? '更新' : '创建'}成功`);
|
||||||
|
form.resetFields();
|
||||||
onSuccess();
|
onSuccess();
|
||||||
onCancel();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Submit failed:', error);
|
message.error(`${isEdit ? '更新' : '创建'}失败`);
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={initialValues ? '编辑环境' : '新建环境'}
|
title={`${isEdit ? '编辑' : '新建'}环境`}
|
||||||
open={visible}
|
open={visible}
|
||||||
onOk={handleOk}
|
onCancel={() => {
|
||||||
onCancel={onCancel}
|
form.resetFields();
|
||||||
confirmLoading={loading}
|
onCancel();
|
||||||
destroyOnClose
|
}}
|
||||||
|
onOk={handleSubmit}
|
||||||
width={600}
|
width={600}
|
||||||
>
|
>
|
||||||
<Form
|
<Form
|
||||||
form={form}
|
form={form}
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
initialValues={initialValues || {sort: 0}}
|
initialValues={{
|
||||||
|
sort: 0,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Form.Item
|
|
||||||
name="envName"
|
|
||||||
label="环境名称"
|
|
||||||
rules={[
|
|
||||||
{required: true, message: '请输入环境名称'},
|
|
||||||
{max: 50, message: '环境名称最多50个字符'}
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input placeholder="请输入环境名称"/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="envCode"
|
name="envCode"
|
||||||
label="环境编码"
|
label="环境编码"
|
||||||
rules={[
|
rules={[
|
||||||
{required: true, message: '请输入环境编码'},
|
{required: true, message: '请输入环境编码'},
|
||||||
{max: 50, message: '环境编码最多50个字符'},
|
{max: 50, message: '环境编码长度不能超过50个字符'},
|
||||||
{
|
|
||||||
pattern: /^[A-Za-z0-9_-]+$/,
|
|
||||||
message: '环境编码只能包含字母、数字、下划线和连字符'
|
|
||||||
}
|
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input placeholder="请输入环境编码"/>
|
<Input placeholder="请输入环境编码"/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="envName"
|
||||||
|
label="环境名称"
|
||||||
|
rules={[
|
||||||
|
{required: true, message: '请输入环境名称'},
|
||||||
|
{max: 50, message: '环境名称长度不能超过50个字符'},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入环境名称"/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="envDesc"
|
name="envDesc"
|
||||||
label="环境描述"
|
label="环境描述"
|
||||||
rules={[{max: 200, message: '环境描述最多200个字符'}]}
|
rules={[{max: 200, message: '环境描述长度不能超过200个字符'}]}
|
||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea rows={4} placeholder="请输入环境描述"/>
|
||||||
placeholder="请输入环境描述"
|
</Form.Item>
|
||||||
rows={4}
|
|
||||||
showCount
|
<Form.Item
|
||||||
maxLength={200}
|
name="buildType"
|
||||||
/>
|
label="构建方式"
|
||||||
|
rules={[{required: true, message: '请选择构建方式'}]}
|
||||||
|
>
|
||||||
|
<Select placeholder="请选择构建方式">
|
||||||
|
{Object.values(BuildTypeEnum).map((type) => {
|
||||||
|
const typeInfo = getBuildTypeInfo(type);
|
||||||
|
return (
|
||||||
|
<Select.Option key={type} value={type}>
|
||||||
|
<div style={{ display: 'inline-flex', alignItems: 'center', gap: '4px', color: typeInfo.color }}>
|
||||||
|
{typeInfo.icon}
|
||||||
|
{typeInfo.label}
|
||||||
|
</div>
|
||||||
|
</Select.Option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="deployType"
|
||||||
|
label="部署方式"
|
||||||
|
rules={[{required: true, message: '请选择部署方式'}]}
|
||||||
|
>
|
||||||
|
<Select placeholder="请选择部署方式">
|
||||||
|
{Object.values(DeployTypeEnum).map((type) => {
|
||||||
|
const typeInfo = getDeployTypeInfo(type);
|
||||||
|
return (
|
||||||
|
<Select.Option key={type} value={type}>
|
||||||
|
<div style={{ display: 'inline-flex', alignItems: 'center', gap: '4px', color: typeInfo.color }}>
|
||||||
|
{typeInfo.icon}
|
||||||
|
{typeInfo.label}
|
||||||
|
</div>
|
||||||
|
</Select.Option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="sort"
|
name="sort"
|
||||||
label="排序"
|
label="排序"
|
||||||
tooltip="数字越小越靠前"
|
rules={[{required: true, message: '请输入排序号'}]}
|
||||||
initialValue={0}
|
|
||||||
>
|
>
|
||||||
<Input type="number" placeholder="请输入排序号"/>
|
<InputNumber min={0} max={999} style={{width: '100%'}}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
import React, {useState} from 'react';
|
import React, {useState} from 'react';
|
||||||
import {PageContainer} from '@ant-design/pro-layout';
|
import {PageContainer} from '@ant-design/pro-layout';
|
||||||
import {Button, message, Popconfirm, Space, Tag, Form, Input, Row, Col} from 'antd';
|
import {Button, message, Popconfirm, Space, Tag} from 'antd';
|
||||||
import {PlusOutlined, DeleteOutlined, EditOutlined, SearchOutlined, ReloadOutlined} from '@ant-design/icons';
|
import {PlusOutlined, EditOutlined, DeleteOutlined} from '@ant-design/icons';
|
||||||
import {getEnvironmentList, deleteEnvironment, getEnvironmentPage} from './service';
|
import {getEnvironmentPage, deleteEnvironment} from './service';
|
||||||
import type {Environment} from './types';
|
import type {Environment, EnvironmentQueryParams} from './types';
|
||||||
|
import {BuildTypeEnum, DeployTypeEnum} from './types';
|
||||||
|
import {getBuildTypeInfo, getDeployTypeInfo} from './utils';
|
||||||
import EnvironmentModal from './components/EnvironmentModal';
|
import EnvironmentModal from './components/EnvironmentModal';
|
||||||
import {ProTable} from '@ant-design/pro-components';
|
import {ProTable} from '@ant-design/pro-components';
|
||||||
import type {ProColumns} from '@ant-design/pro-components';
|
import type {ProColumns, ActionType} from '@ant-design/pro-components';
|
||||||
|
|
||||||
const EnvironmentList: React.FC = () => {
|
const EnvironmentList: React.FC = () => {
|
||||||
const [modalVisible, setModalVisible] = useState(false);
|
const [modalVisible, setModalVisible] = useState(false);
|
||||||
const [currentEnvironment, setCurrentEnvironment] = useState<Environment>();
|
const [currentEnvironment, setCurrentEnvironment] = useState<Environment>();
|
||||||
const actionRef = React.useRef();
|
const actionRef = React.useRef<ActionType>();
|
||||||
const [form] = Form.useForm();
|
|
||||||
|
|
||||||
const handleDelete = async (id: number) => {
|
const handleDelete = async (id: number) => {
|
||||||
try {
|
try {
|
||||||
@ -53,21 +54,57 @@ const EnvironmentList: React.FC = () => {
|
|||||||
title: '环境描述',
|
title: '环境描述',
|
||||||
dataIndex: 'envDesc',
|
dataIndex: 'envDesc',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
width: '30%',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '构建类型',
|
title: '构建方式',
|
||||||
dataIndex: 'buildType',
|
dataIndex: 'buildType',
|
||||||
width: 100,
|
width: 180,
|
||||||
render: (buildType) => (
|
render: (buildType) => {
|
||||||
<Tag color={buildType === 'JENKINS' ? 'blue' : 'green'}>
|
if (!buildType) return '-';
|
||||||
{buildType}
|
const typeInfo = getBuildTypeInfo(buildType as BuildTypeEnum);
|
||||||
</Tag>
|
return (
|
||||||
),
|
<Tag color={typeInfo.color} style={{ display: 'inline-flex', alignItems: 'center', gap: '4px' }}>
|
||||||
|
{typeInfo.icon}
|
||||||
|
{typeInfo.label}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
filters: [
|
||||||
|
{text: 'Jenkins构建', value: BuildTypeEnum.JENKINS},
|
||||||
|
{text: 'GitLab Runner构建', value: BuildTypeEnum.GITLAB_RUNNER},
|
||||||
|
{text: 'GitHub Action构建', value: BuildTypeEnum.GITHUB_ACTION},
|
||||||
|
],
|
||||||
|
filterMode: 'menu',
|
||||||
|
filtered: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '部署方式',
|
||||||
|
dataIndex: 'deployType',
|
||||||
|
width: 180,
|
||||||
|
render: (deployType) => {
|
||||||
|
if (!deployType) return '-';
|
||||||
|
const typeInfo = getDeployTypeInfo(deployType as DeployTypeEnum);
|
||||||
|
return (
|
||||||
|
<Tag color={typeInfo.color} style={{ display: 'inline-flex', alignItems: 'center', gap: '4px' }}>
|
||||||
|
{typeInfo.icon}
|
||||||
|
{typeInfo.label}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
filters: [
|
||||||
|
{text: 'Kubernetes集群部署', value: DeployTypeEnum.K8S},
|
||||||
|
{text: 'Docker容器部署', value: DeployTypeEnum.DOCKER},
|
||||||
|
{text: '虚拟机部署', value: DeployTypeEnum.VM},
|
||||||
|
],
|
||||||
|
filterMode: 'menu',
|
||||||
|
filtered: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '排序',
|
title: '排序',
|
||||||
dataIndex: 'sort',
|
dataIndex: 'sort',
|
||||||
width: 80,
|
width: 80,
|
||||||
|
align: 'center',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -76,30 +113,31 @@ const EnvironmentList: React.FC = () => {
|
|||||||
key: 'action',
|
key: 'action',
|
||||||
valueType: 'option',
|
valueType: 'option',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
render: (_, record) => (
|
align: 'center',
|
||||||
<Space>
|
render: (_, record) => [
|
||||||
|
<Button
|
||||||
|
key="edit"
|
||||||
|
type="link"
|
||||||
|
icon={<EditOutlined/>}
|
||||||
|
onClick={() => handleEdit(record)}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</Button>,
|
||||||
|
<Popconfirm
|
||||||
|
key="delete"
|
||||||
|
title="确定要删除该环境吗?"
|
||||||
|
description="删除后将无法恢复,请谨慎操作"
|
||||||
|
onConfirm={() => handleDelete(record.id)}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
icon={<EditOutlined/>}
|
danger
|
||||||
onClick={() => handleEdit(record)}
|
icon={<DeleteOutlined/>}
|
||||||
>
|
>
|
||||||
编辑
|
删除
|
||||||
</Button>
|
</Button>
|
||||||
<Popconfirm
|
</Popconfirm>
|
||||||
title="确定要删除该环境吗?"
|
],
|
||||||
description="删除后将无法恢复,请谨慎操作"
|
|
||||||
onConfirm={() => handleDelete(record.id)}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
danger
|
|
||||||
icon={<DeleteOutlined/>}
|
|
||||||
>
|
|
||||||
删除
|
|
||||||
</Button>
|
|
||||||
</Popconfirm>
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -108,13 +146,18 @@ const EnvironmentList: React.FC = () => {
|
|||||||
<ProTable<Environment>
|
<ProTable<Environment>
|
||||||
columns={columns}
|
columns={columns}
|
||||||
actionRef={actionRef}
|
actionRef={actionRef}
|
||||||
|
scroll={{x: 'max-content'}}
|
||||||
cardBordered
|
cardBordered
|
||||||
request={async (params) => {
|
request={async (params) => {
|
||||||
const {current, pageSize} = params;
|
const queryParams: EnvironmentQueryParams = {
|
||||||
const data = await getEnvironmentPage({
|
pageSize: params.pageSize,
|
||||||
current,
|
pageNum: params.current,
|
||||||
pageSize,
|
envCode: params.envCode as string,
|
||||||
});
|
envName: params.envName as string,
|
||||||
|
buildType: params.buildType as BuildTypeEnum,
|
||||||
|
deployType: params.deployType as DeployTypeEnum,
|
||||||
|
};
|
||||||
|
const data = await getEnvironmentPage(queryParams);
|
||||||
return {
|
return {
|
||||||
data: data.content || [],
|
data: data.content || [],
|
||||||
success: true,
|
success: true,
|
||||||
|
|||||||
@ -1,33 +1,33 @@
|
|||||||
import request from '@/utils/request';
|
import type {Environment, CreateEnvironmentRequest, UpdateEnvironmentRequest, EnvironmentQueryParams} from './types';
|
||||||
import type { CreateEnvironmentRequest, UpdateEnvironmentRequest, Environment, EnvironmentQuery } from './types';
|
import type {Page} from '@/types/base';
|
||||||
import type { Page } from '@/types/base';
|
import request from "@/utils/request";
|
||||||
|
|
||||||
const BASE_URL = '/api/v1/environments';
|
const BASE_URL = '/api/v1/environments';
|
||||||
|
|
||||||
|
// 获取环境分页列表
|
||||||
|
export const getEnvironmentPage = (params: EnvironmentQueryParams) =>
|
||||||
|
request.get<Page<Environment>>(`${BASE_URL}/page`, {params});
|
||||||
|
|
||||||
// 创建环境
|
// 创建环境
|
||||||
export const createEnvironment = (data: CreateEnvironmentRequest) =>
|
export const createEnvironment = (data: CreateEnvironmentRequest) =>
|
||||||
request.post<void>(BASE_URL, data);
|
request.post<Environment>(BASE_URL, data);
|
||||||
|
|
||||||
// 更新环境
|
// 更新环境
|
||||||
export const updateEnvironment = (data: UpdateEnvironmentRequest) =>
|
export const updateEnvironment = (data: UpdateEnvironmentRequest) =>
|
||||||
request.put<void>(`${BASE_URL}/${data.id}`, data);
|
request.put<Environment>(`${BASE_URL}/${data.id}`, data);
|
||||||
|
|
||||||
// 删除环境
|
// 删除环境
|
||||||
export const deleteEnvironment = (id: number) =>
|
export const deleteEnvironment = (id: number) =>
|
||||||
request.delete<void>(`${BASE_URL}/${id}`);
|
request.delete(`${BASE_URL}/${id}`);
|
||||||
|
|
||||||
// 获取环境详情
|
// 获取环境详情
|
||||||
export const getEnvironment = (id: number) =>
|
export const getEnvironment = (id: number) =>
|
||||||
request.get<Environment>(`${BASE_URL}/${id}`);
|
request.get<Environment>(`${BASE_URL}/${id}`);
|
||||||
|
|
||||||
// 分页查询环境列表
|
|
||||||
export const getEnvironmentPage = (params?: EnvironmentQuery) =>
|
|
||||||
request.get<Page<Environment>>(`${BASE_URL}/page`, { params });
|
|
||||||
|
|
||||||
// 获取所有环境列表
|
// 获取所有环境列表
|
||||||
export const getEnvironmentList = () =>
|
export const getEnvironmentList = () =>
|
||||||
request.get<Environment[]>(BASE_URL);
|
request.get<Environment[]>(BASE_URL);
|
||||||
|
|
||||||
// 条件查询环境列表
|
// 条件查询环境列表
|
||||||
export const getEnvironmentListByCondition = (params?: EnvironmentQuery) =>
|
export const getEnvironmentListByCondition = (params?: EnvironmentQueryParams) =>
|
||||||
request.get<Environment[]>(`${BASE_URL}/list`, { params });
|
request.get<Environment[]>(`${BASE_URL}/list`, { params });
|
||||||
|
|||||||
@ -1,32 +1,50 @@
|
|||||||
import type { BaseQuery } from '@/types/base';
|
import {BaseResponse, BaseRequest, BaseQuery} from '@/types/base';
|
||||||
|
|
||||||
|
// 构建方式枚举
|
||||||
export interface Environment {
|
export enum BuildTypeEnum {
|
||||||
id: number;
|
JENKINS = 'JENKINS',
|
||||||
envCode: string;
|
GITLAB_RUNNER = 'GITLAB_RUNNER',
|
||||||
envName: string;
|
GITHUB_ACTION = 'GITHUB_ACTION'
|
||||||
envDesc?: string;
|
|
||||||
sort: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateEnvironmentRequest {
|
// 部署方式枚举
|
||||||
projectId: number;
|
export enum DeployTypeEnum {
|
||||||
envCode: string;
|
K8S = 'K8S',
|
||||||
envName: string;
|
DOCKER = 'DOCKER',
|
||||||
envDesc?: string;
|
VM = 'VM'
|
||||||
sort: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateEnvironmentRequest {
|
// 环境基础信息
|
||||||
id: number;
|
export interface Environment extends BaseResponse {
|
||||||
envCode: string;
|
tenantCode: string;
|
||||||
envName: string;
|
envCode: string;
|
||||||
envDesc?: string;
|
envName: string;
|
||||||
sort: number;
|
envDesc?: string;
|
||||||
|
buildType: BuildTypeEnum;
|
||||||
|
deployType: DeployTypeEnum;
|
||||||
|
sort: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EnvironmentQuery extends BaseQuery {
|
// 创建环境请求参数
|
||||||
projectId?: number;
|
export interface CreateEnvironmentRequest extends BaseRequest {
|
||||||
envCode?: string;
|
tenantCode: string;
|
||||||
envName?: string;
|
envCode: string;
|
||||||
|
envName: string;
|
||||||
|
envDesc?: string;
|
||||||
|
buildType: BuildTypeEnum;
|
||||||
|
deployType: DeployTypeEnum;
|
||||||
|
sort: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新环境请求参数
|
||||||
|
export interface UpdateEnvironmentRequest extends CreateEnvironmentRequest {
|
||||||
|
id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页查询参数
|
||||||
|
export interface EnvironmentQueryParams extends BaseQuery {
|
||||||
|
envCode?: string;
|
||||||
|
envName?: string;
|
||||||
|
buildType?: BuildTypeEnum;
|
||||||
|
deployType?: DeployTypeEnum;
|
||||||
}
|
}
|
||||||
|
|||||||
76
frontend/src/pages/Deploy/Environment/List/utils.tsx
Normal file
76
frontend/src/pages/Deploy/Environment/List/utils.tsx
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
GithubOutlined,
|
||||||
|
GitlabOutlined,
|
||||||
|
CloudServerOutlined,
|
||||||
|
CloudOutlined,
|
||||||
|
DesktopOutlined,
|
||||||
|
ApiOutlined,
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import {BuildTypeEnum, DeployTypeEnum} from './types';
|
||||||
|
|
||||||
|
interface TypeInfo {
|
||||||
|
label: string;
|
||||||
|
color: string;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取构建方式信息
|
||||||
|
export const getBuildTypeInfo = (type: BuildTypeEnum): TypeInfo => {
|
||||||
|
switch (type) {
|
||||||
|
case BuildTypeEnum.JENKINS:
|
||||||
|
return {
|
||||||
|
label: 'Jenkins构建',
|
||||||
|
color: '#D24939',
|
||||||
|
icon: <ApiOutlined/>,
|
||||||
|
};
|
||||||
|
case BuildTypeEnum.GITLAB_RUNNER:
|
||||||
|
return {
|
||||||
|
label: 'GitLab Runner构建',
|
||||||
|
color: '#FC6D26',
|
||||||
|
icon: <GitlabOutlined/>,
|
||||||
|
};
|
||||||
|
case BuildTypeEnum.GITHUB_ACTION:
|
||||||
|
return {
|
||||||
|
label: 'GitHub Action构建',
|
||||||
|
color: '#2088FF',
|
||||||
|
icon: <GithubOutlined/>,
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return {
|
||||||
|
label: type || '未知',
|
||||||
|
color: '#666666',
|
||||||
|
icon: <ApiOutlined/>,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取部署方式信息
|
||||||
|
export const getDeployTypeInfo = (type: DeployTypeEnum): TypeInfo => {
|
||||||
|
switch (type) {
|
||||||
|
case DeployTypeEnum.K8S:
|
||||||
|
return {
|
||||||
|
label: 'Kubernetes集群部署',
|
||||||
|
color: '#326CE5',
|
||||||
|
icon: <CloudServerOutlined/>,
|
||||||
|
};
|
||||||
|
case DeployTypeEnum.DOCKER:
|
||||||
|
return {
|
||||||
|
label: 'Docker容器部署',
|
||||||
|
color: '#2496ED',
|
||||||
|
icon: <CloudOutlined/>,
|
||||||
|
};
|
||||||
|
case DeployTypeEnum.VM:
|
||||||
|
return {
|
||||||
|
label: '虚拟机部署',
|
||||||
|
color: '#F7B93E',
|
||||||
|
icon: <DesktopOutlined/>,
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return {
|
||||||
|
label: type || '未知',
|
||||||
|
color: '#666666',
|
||||||
|
icon: <CloudServerOutlined/>,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -100,7 +100,7 @@ const ProjectGroupList: React.FC = () => {
|
|||||||
<Tooltip title="环境数量">
|
<Tooltip title="环境数量">
|
||||||
<Space>
|
<Space>
|
||||||
<EnvironmentOutlined/>
|
<EnvironmentOutlined/>
|
||||||
{record.environments?.length || 0}
|
{record?.totalEnvironments || 0}
|
||||||
</Space>
|
</Space>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
),
|
),
|
||||||
@ -126,35 +126,42 @@ const ProjectGroupList: React.FC = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: 180,
|
width: 280,
|
||||||
key: 'action',
|
key: 'action',
|
||||||
valueType: 'option',
|
valueType: 'option',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render: (_, record) => (
|
render: (_, record) => [
|
||||||
<Space>
|
<Button
|
||||||
|
key="edit"
|
||||||
|
type="link"
|
||||||
|
icon={<EditOutlined/>}
|
||||||
|
onClick={() => handleEdit(record)}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</Button>,
|
||||||
|
<Button
|
||||||
|
key="bind"
|
||||||
|
type="link"
|
||||||
|
icon={<EnvironmentOutlined/>}
|
||||||
|
>
|
||||||
|
环境绑定
|
||||||
|
</Button>,
|
||||||
|
<Popconfirm
|
||||||
|
key="delete"
|
||||||
|
title="确定要删除该项目组吗?"
|
||||||
|
description="删除后将无法恢复,请谨慎操作"
|
||||||
|
onConfirm={() => handleDelete(record.id)}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
icon={<EditOutlined/>}
|
danger
|
||||||
onClick={() => handleEdit(record)}
|
icon={<DeleteOutlined/>}
|
||||||
>
|
>
|
||||||
编辑
|
删除
|
||||||
</Button>
|
</Button>
|
||||||
<Popconfirm
|
</Popconfirm>
|
||||||
title="确定要删除该项目组吗?"
|
],
|
||||||
description="删除后将无法恢复,请谨慎操作"
|
|
||||||
onConfirm={() => handleDelete(record.id)}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
danger
|
|
||||||
icon={<DeleteOutlined/>}
|
|
||||||
>
|
|
||||||
删除
|
|
||||||
</Button>
|
|
||||||
</Popconfirm>
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -163,6 +170,7 @@ const ProjectGroupList: React.FC = () => {
|
|||||||
<ProTable<ProjectGroup>
|
<ProTable<ProjectGroup>
|
||||||
columns={columns}
|
columns={columns}
|
||||||
actionRef={actionRef}
|
actionRef={actionRef}
|
||||||
|
scroll={{ x: 'max-content' }}
|
||||||
cardBordered
|
cardBordered
|
||||||
request={async (params) => {
|
request={async (params) => {
|
||||||
const queryParams: ProjectGroupQueryParams = {
|
const queryParams: ProjectGroupQueryParams = {
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export interface ProjectGroup extends BaseResponse {
|
|||||||
projectGroupName: string;
|
projectGroupName: string;
|
||||||
projectGroupDesc?: string;
|
projectGroupDesc?: string;
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
|
totalEnvironments: number;
|
||||||
totalApplications: number;
|
totalApplications: number;
|
||||||
sort: number;
|
sort: number;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user