deploy-ease-platform/frontend/src/pages/Deploy/External/index.tsx
dengqichen 5e85c51bc4 1
2024-12-30 14:08:21 +08:00

344 lines
12 KiB
TypeScript

import React, {useState} from 'react';
import {Card, Table, Button, Space, Modal, Form, Input, message, Select, InputNumber, Switch, Tag, Tooltip} from 'antd';
import {PlusOutlined, EditOutlined, DeleteOutlined, SyncOutlined, CheckCircleOutlined, CloseCircleOutlined, LinkOutlined, MinusCircleOutlined} from '@ant-design/icons';
import type {ColumnsType} from 'antd/es/table';
import {useTableData} from '@/hooks/useTableData';
import * as service from './service';
import {SystemType, AuthType, SyncStatus, ExternalSystemResponse, ExternalSystemRequest, ExternalSystemQuery} from './types';
const ExternalPage: React.FC = () => {
const [form] = Form.useForm();
const [modalVisible, setModalVisible] = useState(false);
const [editingSystem, setEditingSystem] = useState<ExternalSystemResponse | null>(null);
const {
list,
loading,
pagination,
handleTableChange,
handleCreate,
handleUpdate,
handleDelete,
refresh
} = useTableData<ExternalSystemResponse, ExternalSystemQuery, ExternalSystemRequest, ExternalSystemRequest>({
service: {
list: service.getExternalSystemsPage,
create: service.createExternalSystem,
update: service.updateExternalSystem,
delete: service.deleteExternalSystem
},
config: {
message: {
createSuccess: '创建系统成功',
updateSuccess: '更新系统成功',
deleteSuccess: '删除系统成功'
}
}
});
const handleAdd = () => {
setEditingSystem(null);
form.resetFields();
form.setFieldsValue({
enabled: true,
sort: 1,
authType: AuthType.BASIC
});
setModalVisible(true);
};
const handleEdit = (record: ExternalSystemResponse) => {
setEditingSystem(record);
form.setFieldsValue({
...record,
password: undefined // 不显示密码
});
setModalVisible(true);
};
const handleTestConnection = async (id: number) => {
try {
const success = await service.testConnection(id);
message.success(success ? '连接成功' : '连接失败');
} catch (error) {
message.error('测试连接失败');
}
};
const handleStatusChange = async (id: number, enabled: boolean) => {
try {
await service.updateStatus(id, enabled);
message.success('更新状态成功');
refresh();
} catch (error) {
message.error('更新状态失败');
}
};
const handleSubmit = async () => {
try {
const values = await form.validateFields();
let success = false;
if (editingSystem) {
success = await handleUpdate(editingSystem.id, values);
} else {
success = await handleCreate(values);
}
if (success) {
setModalVisible(false);
}
} catch (error: any) {
// 如果是表单验证错误,不显示错误消息
if (!error.errorFields) {
// 如果是后端返回的错误,显示后端的错误消息
if (error.response?.data) {
message.error(error.response.data.message || '操作失败');
} else {
message.error(error.message || '操作失败');
}
}
}
};
const columns: ColumnsType<ExternalSystemResponse> = [
{
title: '系统名称',
dataIndex: 'name',
width: 200,
},
{
title: '系统类型',
dataIndex: 'type',
width: 120,
render: (type: SystemType) => {
const typeMap = {
[SystemType.JENKINS]: 'Jenkins',
[SystemType.GIT]: 'Git',
[SystemType.ZENTAO]: '禅道'
};
return typeMap[type];
}
},
{
title: '系统地址',
dataIndex: 'url',
width: 300,
render: (url: string) => (
<a href={url} target="_blank" rel="noopener noreferrer">
{url}
</a>
),
},
{
title: '认证方式',
dataIndex: 'authType',
width: 120,
render: (authType: AuthType) => {
const authTypeMap = {
[AuthType.BASIC]: '用户名密码',
[AuthType.TOKEN]: '令牌',
[AuthType.OAUTH]: 'OAuth2'
};
return authTypeMap[authType];
}
},
{
title: '最后连接时间',
dataIndex: 'lastConnectTime',
width: 150,
render: (time: string) => time || '-'
},
{
title: '状态',
dataIndex: 'enabled',
width: 100,
render: (enabled: boolean, record) => (
<Switch
checked={enabled}
onChange={(checked) => handleStatusChange(record.id, checked)}
checkedChildren="否"
unCheckedChildren="是"
/>
)
},
{
title: '操作',
key: 'action',
width: 280,
render: (_, record) => (
<Space>
<Button
type="link"
icon={<EditOutlined/>}
onClick={() => handleEdit(record)}
>
</Button>
<Button
type="link"
icon={<LinkOutlined/>}
onClick={() => handleTestConnection(record.id)}
>
</Button>
<Button
type="link"
danger
icon={<DeleteOutlined/>}
onClick={() => handleDelete(record.id)}
>
</Button>
</Space>
),
},
];
return (
<div>
<Card>
<div style={{marginBottom: 16}}>
<Button
type="primary"
icon={<PlusOutlined/>}
onClick={handleAdd}
>
</Button>
</div>
<Table
columns={columns}
dataSource={list}
rowKey="id"
loading={loading}
pagination={pagination}
onChange={handleTableChange}
/>
</Card>
<Modal
title={editingSystem ? '编辑系统' : '新增系统'}
open={modalVisible}
onOk={handleSubmit}
onCancel={() => setModalVisible(false)}
width={600}
>
<Form
form={form}
layout="vertical"
>
<Form.Item
name="name"
label="系统名称"
rules={[{required: true, message: '请输入系统名称'}]}
>
<Input placeholder="请输入系统名称"/>
</Form.Item>
<Form.Item
name="type"
label="系统类型"
rules={[{required: true, message: '请选择系统类型'}]}
>
<Select>
<Select.Option value={SystemType.JENKINS}>Jenkins</Select.Option>
<Select.Option value={SystemType.GIT}>Git</Select.Option>
<Select.Option value={SystemType.ZENTAO}></Select.Option>
</Select>
</Form.Item>
<Form.Item
name="url"
label="系统地址"
rules={[
{required: true, message: '请输入系统地址'},
{type: 'url', message: '请输入有效的URL'}
]}
>
<Input placeholder="请输入系统地址"/>
</Form.Item>
<Form.Item
name="authType"
label="认证方式"
rules={[{required: true, message: '请选择认证方式'}]}
>
<Select>
<Select.Option value={AuthType.BASIC}></Select.Option>
<Select.Option value={AuthType.TOKEN}></Select.Option>
<Select.Option value={AuthType.OAUTH}>OAuth2</Select.Option>
</Select>
</Form.Item>
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) => prevValues.authType !== currentValues.authType}
>
{({getFieldValue}) => {
const authType = getFieldValue('authType');
if (authType === AuthType.BASIC) {
return (
<>
<Form.Item
name="username"
label="用户名"
rules={[{required: true, message: '请输入用户名'}]}
>
<Input placeholder="请输入用户名"/>
</Form.Item>
<Form.Item
name="password"
label="密码"
rules={[{required: !editingSystem, message: '请输入密码'}]}
>
<Input.Password placeholder={editingSystem ? '不修改请留空' : '请输入密码'}/>
</Form.Item>
</>
);
}
if (authType === AuthType.TOKEN) {
return (
<Form.Item
name="token"
label="访问令牌"
rules={[{required: !editingSystem, message: '请输入访问令牌'}]}
>
<Input.Password placeholder={editingSystem ? '不修改请留空' : '请输入访问令牌'}/>
</Form.Item>
);
}
return null;
}}
</Form.Item>
<Form.Item
name="sort"
label="显示排序"
rules={[{required: true, message: '请输入显示排序'}]}
>
<InputNumber style={{width: '100%'}} min={0} placeholder="请输入显示排序"/>
</Form.Item>
<Form.Item
name="remark"
label="备注"
>
<Input.TextArea rows={4} placeholder="请输入备注"/>
</Form.Item>
<Form.Item
name="enabled"
label="是否禁用"
valuePropName="checked"
>
<Switch checkedChildren="否" unCheckedChildren="是"/>
</Form.Item>
</Form>
</Modal>
</div>
);
};
export default ExternalPage;