| import React, { useRef, useState } from 'react'; |
| import { PlusOutlined, EditOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons'; |
| import { |
| Button, |
| Modal, |
| message, |
| Drawer, |
| Form, |
| Input, |
| InputNumber, |
| DatePicker, |
| Card, |
| Layout, |
| } from 'antd'; |
| import { |
| ProTable, |
| ActionType, |
| ProColumns, |
| ProDescriptions, |
| ProDescriptionsItemProps, |
| } from '@ant-design/pro-components'; |
| import type { BtTorrent } from './data'; |
| import { |
| listBtTorrent, |
| getBtTorrent, |
| addBtTorrent, |
| updateBtTorrent, |
| removeBtTorrent, |
| } from './service'; |
| |
| const { Content } = Layout; |
| |
| const BtTorrentPage: React.FC = () => { |
| const actionRef = useRef<ActionType>(); |
| const [form] = Form.useForm(); |
| const [modalVisible, setModalVisible] = useState(false); |
| const [drawerVisible, setDrawerVisible] = useState(false); |
| const [current, setCurrent] = useState<Partial<BtTorrent>>({}); |
| |
| const columns: ProColumns<BtTorrent>[] = [ |
| { |
| title: '种子ID', |
| dataIndex: 'torrentId', |
| hideInForm: true, |
| render: (dom, entity) => ( |
| <a |
| onClick={async () => { |
| const res = await getBtTorrent(entity.torrentId!); |
| setCurrent(res); |
| setDrawerVisible(true); |
| }} |
| > |
| {dom} |
| </a> |
| ), |
| }, |
| { title: '名称', dataIndex: 'name' }, |
| { title: 'infoHash', dataIndex: 'infoHash' }, |
| { title: '大小 (bytes)', dataIndex: 'length', valueType: 'digit' }, |
| { title: '分片大小', dataIndex: 'pieceLength', valueType: 'digit' }, |
| { title: '片段数', dataIndex: 'piecesCount', valueType: 'digit' }, |
| { title: '创建工具', dataIndex: 'createdBy', hideInSearch: true }, |
| { title: '上传时间', dataIndex: 'uploadTime', valueType: 'dateTime', hideInSearch: true }, |
| { |
| title: '操作', |
| valueType: 'option', |
| render: (_, record) => [ |
| <Button key="view" type="link" icon={<EyeOutlined />} onClick={() => { |
| setCurrent(record); |
| setDrawerVisible(true); |
| }}>查看</Button>, |
| <Button key="edit" type="link" icon={<EditOutlined />} onClick={() => { |
| setCurrent(record); |
| form.setFieldsValue(record); |
| setModalVisible(true); |
| }}>编辑</Button>, |
| <Button key="delete" type="link" icon={<DeleteOutlined />} danger onClick={() => { |
| Modal.confirm({ |
| title: '删除确认', |
| content: '确定删除该种子?', |
| onOk: async () => { |
| await removeBtTorrent([record.torrentId!]); |
| message.success('删除成功'); |
| actionRef.current?.reload(); |
| }, |
| }); |
| }}>删除</Button>, |
| ], |
| }, |
| ]; |
| |
| const handleSubmit = async () => { |
| const values = await form.validateFields(); |
| if (current?.torrentId) { |
| await updateBtTorrent({ ...current, ...values }); |
| message.success('更新成功'); |
| } else { |
| await addBtTorrent(values as BtTorrent); |
| message.success('新增成功'); |
| } |
| setModalVisible(false); |
| form.resetFields(); |
| actionRef.current?.reload(); |
| }; |
| |
| return ( |
| <Content> |
| <Card bordered={false}> |
| <ProTable<BtTorrent> |
| headerTitle="种子列表" |
| actionRef={actionRef} |
| rowKey="torrentId" |
| search={{ labelWidth: 100 }} |
| toolBarRender={() => [ |
| <Button |
| key="add" |
| type="primary" |
| icon={<PlusOutlined />} |
| onClick={() => { |
| form.resetFields(); |
| setCurrent({}); |
| setModalVisible(true); |
| }} |
| > |
| 新增 |
| </Button>, |
| ]} |
| request={async (params) => { |
| const res = await listBtTorrent(params); |
| return { data: res.rows || res.data || [], success: true }; |
| }} |
| columns={columns} |
| /> |
| |
| {/* 编辑/新增弹窗 */} |
| <Modal |
| title={current?.torrentId ? '编辑种子' : '新增种子'} |
| open={modalVisible} |
| onOk={handleSubmit} |
| onCancel={() => setModalVisible(false)} |
| destroyOnClose |
| > |
| <Form form={form} layout="vertical"> |
| <Form.Item name="name" label="名称" rules={[{ required: true }]}> |
| <Input /> |
| </Form.Item> |
| <Form.Item name="infoHash" label="infoHash" rules={[{ required: true }]}> |
| <Input /> |
| </Form.Item> |
| <Form.Item name="length" label="总大小 (bytes)" rules={[{ required: true }]}> |
| <InputNumber style={{ width: '100%' }} /> |
| </Form.Item> |
| <Form.Item name="pieceLength" label="分片大小" rules={[{ required: true }]}> |
| <InputNumber style={{ width: '100%' }} /> |
| </Form.Item> |
| <Form.Item name="piecesCount" label="片段数"> |
| <InputNumber style={{ width: '100%' }} /> |
| </Form.Item> |
| <Form.Item name="createdBy" label="创建工具"> |
| <Input /> |
| </Form.Item> |
| </Form> |
| </Modal> |
| |
| {/* 详情抽屉 */} |
| <Drawer |
| width={500} |
| open={drawerVisible} |
| onClose={() => setDrawerVisible(false)} |
| title="种子详情" |
| > |
| {current && ( |
| <ProDescriptions<BtTorrent> |
| column={1} |
| title={current.name} |
| request={async () => ({ data: current })} |
| columns={columns as ProDescriptionsItemProps<BtTorrent>[]} |
| /> |
| )} |
| </Drawer> |
| </Card> |
| </Content> |
| ); |
| }; |
| |
| export default BtTorrentPage; |