962cbc8df3
CI / lint-and-build (push) Has been cancelled
- 支持修改名称、AccessKey ID/Secret、Region、Endpoint - 编辑时 Secret 留空表示不修改
206 lines
5.4 KiB
TypeScript
206 lines
5.4 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import {
|
|
Table,
|
|
Button,
|
|
Space,
|
|
Modal,
|
|
Form,
|
|
Input,
|
|
message,
|
|
Tag,
|
|
Popconfirm,
|
|
} from 'antd';
|
|
import { PlusOutlined, EditOutlined } from '@ant-design/icons';
|
|
import {
|
|
listAccounts,
|
|
createAccount,
|
|
updateAccount,
|
|
deleteAccount,
|
|
switchAccount,
|
|
Account,
|
|
AccountInput,
|
|
} from '../api/accounts';
|
|
|
|
export default function AccountsPage() {
|
|
const [accounts, setAccounts] = useState<Account[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
const [modalOpen, setModalOpen] = useState(false);
|
|
const [editingAccount, setEditingAccount] = useState<Account | null>(null);
|
|
const [form] = Form.useForm();
|
|
|
|
const fetchAccounts = async () => {
|
|
setLoading(true);
|
|
try {
|
|
const data = await listAccounts();
|
|
setAccounts(data);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchAccounts();
|
|
}, []);
|
|
|
|
const openCreateModal = () => {
|
|
setEditingAccount(null);
|
|
form.resetFields();
|
|
setModalOpen(true);
|
|
};
|
|
|
|
const openEditModal = (record: Account) => {
|
|
setEditingAccount(record);
|
|
form.setFieldsValue({
|
|
name: record.name,
|
|
accessKeyId: record.accessKeyId,
|
|
region: record.region,
|
|
endpoint: record.endpoint,
|
|
});
|
|
setModalOpen(true);
|
|
};
|
|
|
|
const closeModal = () => {
|
|
setModalOpen(false);
|
|
setEditingAccount(null);
|
|
form.resetFields();
|
|
};
|
|
|
|
const handleSubmit = async (values: AccountInput) => {
|
|
try {
|
|
if (editingAccount) {
|
|
const payload: Partial<AccountInput> = { ...values };
|
|
if (!payload.accessKeySecret) {
|
|
delete payload.accessKeySecret;
|
|
}
|
|
await updateAccount(editingAccount.id, payload);
|
|
message.success('账号更新成功');
|
|
} else {
|
|
await createAccount(values);
|
|
message.success('账号添加成功');
|
|
}
|
|
closeModal();
|
|
fetchAccounts();
|
|
} catch (error) {
|
|
message.error(editingAccount ? '更新失败' : '添加失败');
|
|
}
|
|
};
|
|
|
|
const handleDelete = async (id: string) => {
|
|
try {
|
|
await deleteAccount(id);
|
|
message.success('已删除');
|
|
fetchAccounts();
|
|
} catch (error) {
|
|
message.error('删除失败');
|
|
}
|
|
};
|
|
|
|
const handleSwitch = async (id: string) => {
|
|
try {
|
|
await switchAccount(id);
|
|
message.success('已切换当前账号');
|
|
fetchAccounts();
|
|
} catch (error) {
|
|
message.error('切换失败');
|
|
}
|
|
};
|
|
|
|
const columns = [
|
|
{ title: '名称', dataIndex: 'name' },
|
|
{ title: 'AccessKey ID', dataIndex: 'accessKeyId', ellipsis: true },
|
|
{ title: 'Region', dataIndex: 'region' },
|
|
{
|
|
title: '状态',
|
|
dataIndex: 'isActive',
|
|
render: (isActive: number) =>
|
|
isActive ? <Tag color="green">当前使用</Tag> : <Tag>备用</Tag>,
|
|
},
|
|
{
|
|
title: '操作',
|
|
key: 'action',
|
|
render: (_: unknown, record: Account) => (
|
|
<Space>
|
|
{!record.isActive && (
|
|
<Button type="link" onClick={() => handleSwitch(record.id)}>
|
|
切换
|
|
</Button>
|
|
)}
|
|
<Button type="link" icon={<EditOutlined />} onClick={() => openEditModal(record)}>
|
|
编辑
|
|
</Button>
|
|
<Popconfirm title="确认删除?" onConfirm={() => handleDelete(record.id)}>
|
|
<Button type="link" danger>
|
|
删除
|
|
</Button>
|
|
</Popconfirm>
|
|
</Space>
|
|
),
|
|
},
|
|
];
|
|
|
|
const modalTitle = editingAccount ? '编辑阿里云 VOD 账号' : '添加阿里云 VOD 账号';
|
|
|
|
return (
|
|
<div>
|
|
<div style={{ marginBottom: 16 }}>
|
|
<Button type="primary" icon={<PlusOutlined />} onClick={openCreateModal}>
|
|
添加账号
|
|
</Button>
|
|
</div>
|
|
|
|
<Table rowKey="id" columns={columns} dataSource={accounts} loading={loading} />
|
|
|
|
<Modal
|
|
title={modalTitle}
|
|
open={modalOpen}
|
|
onCancel={closeModal}
|
|
footer={null}
|
|
>
|
|
<Form form={form} layout="vertical" onFinish={handleSubmit}>
|
|
<Form.Item
|
|
label="名称"
|
|
name="name"
|
|
rules={[{ required: true, message: '请输入名称' }]}
|
|
>
|
|
<Input placeholder="用于区分不同账号" />
|
|
</Form.Item>
|
|
<Form.Item
|
|
label="AccessKey ID"
|
|
name="accessKeyId"
|
|
rules={[{ required: true, message: '请输入 AccessKey ID' }]}
|
|
>
|
|
<Input />
|
|
</Form.Item>
|
|
<Form.Item
|
|
label={editingAccount ? 'AccessKey Secret(留空则不修改)' : 'AccessKey Secret'}
|
|
name="accessKeySecret"
|
|
rules={[
|
|
{
|
|
required: !editingAccount,
|
|
message: '请输入 AccessKey Secret',
|
|
},
|
|
]}
|
|
>
|
|
<Input.Password />
|
|
</Form.Item>
|
|
<Form.Item
|
|
label="Region"
|
|
name="region"
|
|
rules={[{ required: true, message: '请输入 Region' }]}
|
|
>
|
|
<Input placeholder="如 cn-shanghai" />
|
|
</Form.Item>
|
|
<Form.Item label="Endpoint(可选)" name="endpoint">
|
|
<Input placeholder="默认 vod.{region}.aliyuncs.com" />
|
|
</Form.Item>
|
|
<Form.Item>
|
|
<Button type="primary" htmlType="submit" block>
|
|
保存
|
|
</Button>
|
|
</Form.Item>
|
|
</Form>
|
|
</Modal>
|
|
</div>
|
|
);
|
|
}
|