blob: 6990da78c92c9e2da84b728f21117da6dc82362b [file] [log] [blame]
86133ec55c542025-04-21 11:51:32 +08001import React, { useRef, useState } from 'react';
2import { PlusOutlined, EditOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons';
3import {
4 Button,
5 Modal,
6 message,
7 Drawer,
8 Form,
9 Input,
10 InputNumber,
11 DatePicker,
12 Card,
13 Layout,
14} from 'antd';
15import {
16 ProTable,
17 ActionType,
18 ProColumns,
19 ProDescriptions,
20 ProDescriptionsItemProps,
21} from '@ant-design/pro-components';
22import type { BtTorrent } from './data';
23import {
24 listBtTorrent,
25 getBtTorrent,
26 addBtTorrent,
27 updateBtTorrent,
28 removeBtTorrent,
29} from './service';
30
31const { Content } = Layout;
32
33const BtTorrentPage: React.FC = () => {
34 const actionRef = useRef<ActionType>();
35 const [form] = Form.useForm();
36 const [modalVisible, setModalVisible] = useState(false);
37 const [drawerVisible, setDrawerVisible] = useState(false);
38 const [current, setCurrent] = useState<Partial<BtTorrent>>({});
39
40 const columns: ProColumns<BtTorrent>[] = [
41 {
42 title: '种子ID',
43 dataIndex: 'torrentId',
44 hideInForm: true,
45 render: (dom, entity) => (
46 <a
47 onClick={async () => {
48 const res = await getBtTorrent(entity.torrentId!);
49 setCurrent(res);
50 setDrawerVisible(true);
51 }}
52 >
53 {dom}
54 </a>
55 ),
56 },
57 { title: '名称', dataIndex: 'name' },
58 { title: 'infoHash', dataIndex: 'infoHash' },
59 { title: '大小 (bytes)', dataIndex: 'length', valueType: 'digit' },
60 { title: '分片大小', dataIndex: 'pieceLength', valueType: 'digit' },
61 { title: '片段数', dataIndex: 'piecesCount', valueType: 'digit' },
62 { title: '创建工具', dataIndex: 'createdBy', hideInSearch: true },
63 { title: '上传时间', dataIndex: 'uploadTime', valueType: 'dateTime', hideInSearch: true },
64 {
65 title: '操作',
66 valueType: 'option',
67 render: (_, record) => [
68 <Button key="view" type="link" icon={<EyeOutlined />} onClick={() => {
69 setCurrent(record);
70 setDrawerVisible(true);
71 }}>查看</Button>,
72 <Button key="edit" type="link" icon={<EditOutlined />} onClick={() => {
73 setCurrent(record);
74 form.setFieldsValue(record);
75 setModalVisible(true);
76 }}>编辑</Button>,
77 <Button key="delete" type="link" icon={<DeleteOutlined />} danger onClick={() => {
78 Modal.confirm({
79 title: '删除确认',
80 content: '确定删除该种子?',
81 onOk: async () => {
82 await removeBtTorrent([record.torrentId!]);
83 message.success('删除成功');
84 actionRef.current?.reload();
85 },
86 });
87 }}>删除</Button>,
88 ],
89 },
90 ];
91
92 const handleSubmit = async () => {
93 const values = await form.validateFields();
94 if (current?.torrentId) {
95 await updateBtTorrent({ ...current, ...values });
96 message.success('更新成功');
97 } else {
98 await addBtTorrent(values as BtTorrent);
99 message.success('新增成功');
100 }
101 setModalVisible(false);
102 form.resetFields();
103 actionRef.current?.reload();
104 };
105
106 return (
107 <Content>
108 <Card bordered={false}>
109 <ProTable<BtTorrent>
110 headerTitle="种子列表"
111 actionRef={actionRef}
112 rowKey="torrentId"
113 search={{ labelWidth: 100 }}
114 toolBarRender={() => [
115 <Button
116 key="add"
117 type="primary"
118 icon={<PlusOutlined />}
119 onClick={() => {
120 form.resetFields();
121 setCurrent({});
122 setModalVisible(true);
123 }}
124 >
125 新增
126 </Button>,
127 ]}
128 request={async (params) => {
129 const res = await listBtTorrent(params);
130 return { data: res.rows || res.data || [], success: true };
131 }}
132 columns={columns}
133 />
134
135 {/* 编辑/新增弹窗 */}
136 <Modal
137 title={current?.torrentId ? '编辑种子' : '新增种子'}
138 open={modalVisible}
139 onOk={handleSubmit}
140 onCancel={() => setModalVisible(false)}
141 destroyOnClose
142 >
143 <Form form={form} layout="vertical">
144 <Form.Item name="name" label="名称" rules={[{ required: true }]}>
145 <Input />
146 </Form.Item>
147 <Form.Item name="infoHash" label="infoHash" rules={[{ required: true }]}>
148 <Input />
149 </Form.Item>
150 <Form.Item name="length" label="总大小 (bytes)" rules={[{ required: true }]}>
151 <InputNumber style={{ width: '100%' }} />
152 </Form.Item>
153 <Form.Item name="pieceLength" label="分片大小" rules={[{ required: true }]}>
154 <InputNumber style={{ width: '100%' }} />
155 </Form.Item>
156 <Form.Item name="piecesCount" label="片段数">
157 <InputNumber style={{ width: '100%' }} />
158 </Form.Item>
159 <Form.Item name="createdBy" label="创建工具">
160 <Input />
161 </Form.Item>
162 </Form>
163 </Modal>
164
165 {/* 详情抽屉 */}
166 <Drawer
167 width={500}
168 open={drawerVisible}
169 onClose={() => setDrawerVisible(false)}
170 title="种子详情"
171 >
172 {current && (
173 <ProDescriptions<BtTorrent>
174 column={1}
175 title={current.name}
176 request={async () => ({ data: current })}
177 columns={columns as ProDescriptionsItemProps<BtTorrent>[]}
178 />
179 )}
180 </Drawer>
181 </Card>
182 </Content>
183 );
184};
185
186export default BtTorrentPage;