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