blob: 6cb5a413ad097aeb0390daea5e99f2226fc124cf [file] [log] [blame]
import React, { useEffect, useState } from 'react';
import { PlusOutlined, UploadOutlined } from '@ant-design/icons';
import {
Form,
Input,
Button,
Select,
Upload,
message,
Tag,
Space,
Typography,
Modal,
} from 'antd';
import{
getCategories,
addTorrent,
uploadTorrentFile
} from '../../services/bt/index';
const { Option } = Select;
const { TextArea } = Input;
const { Title } = Typography;
const TorrentUpload: React.FC = () => {
const [categories, setCategories] = useState<{ id: number; name: string }[]>([]);
const [tagOptions, setTagOptions] = useState<string[]>([]);
const [customTags, setCustomTags] = useState<string[]>([]);
const [fileList, setFileList] = useState<any[]>([]);
const [uploading, setUploading] = useState(false);
const [form] = Form.useForm();
const [tagInputVisible, setTagInputVisible] = useState(false);
const [tagInputValue, setTagInputValue] = useState('');
useEffect(() => {
getCategories().then((res) => {
if (Array.isArray(res.data)) {
setCategories(res.data);
setTagOptions(res.data.map((cat: { name: string }) => cat.name));
}
});
}, []);
const handleTagClose = (removedTag: string) => {
setCustomTags(customTags.filter(tag => tag !== removedTag));
};
const showTagInput = () => setTagInputVisible(true);
const handleTagInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setTagInputValue(e.target.value);
};
const handleTagInputConfirm = () => {
if (
tagInputValue &&
!customTags.includes(tagInputValue) &&
!tagOptions.includes(tagInputValue)
) {
setCustomTags([...customTags, tagInputValue]);
}
setTagInputVisible(false);
setTagInputValue('');
};
const beforeUpload = (file: File) => {
const isTorrent = file.name.endsWith('.torrent');
if (!isTorrent) {
message.error('只能上传.torrent文件');
}
setFileList([file]);
return false;
};
const handleSubmit = async (values: any) => {
if (fileList.length === 0) {
message.error('请上传.torrent文件');
return;
}
setUploading(true);
try {
// 1. 添加种子基本信息
const addRes = await addTorrent({
...values,
category: Number(values.category),
description: values.description,
name: values.name,
title: values.title,
subheading: values.subheading || '',
remark: values.remark || '',
});
if (!addRes?.id) {
throw new Error('种子信息添加失败');
}
// 2. 上传.torrent文件
await uploadTorrentFile(fileList[0], addRes.id);
message.success('种子上传成功');
form.resetFields();
setFileList([]);
setCustomTags([]);
} catch (err: any) {
message.error(err.message || '上传失败');
} finally {
setUploading(false);
}
};
return (
<div
style={{
width: '100%',
margin: '64px auto',
padding: '56px 64px 48px 64px',
background: 'linear-gradient(135deg, #232526 0%, #414345 100%)',
borderRadius: 24,
boxShadow: '0 16px 48px 0 rgba(31, 38, 135, 0.18)',
color: '#fff',
position: 'relative',
overflow: 'hidden',
}}
>
<div
style={{
position: 'absolute',
top: -100,
right: -100,
width: 260,
height: 260,
background: 'radial-gradient(circle, #667eea55 0%, transparent 80%)',
zIndex: 0,
}}
/>
<div
style={{
position: 'absolute',
bottom: -80,
left: -80,
width: 200,
height: 200,
background: 'radial-gradient(circle, #764ba255 0%, transparent 80%)',
zIndex: 0,
}}
/>
<Title
level={2}
style={{
color: '#fff',
textAlign: 'center',
marginBottom: 48,
letterSpacing: 2,
fontWeight: 700,
zIndex: 1,
position: 'relative',
fontSize: 32,
}}
>
星空PT - 上传资源
</Title>
<Form
form={form}
layout="horizontal"
labelCol={{ span: 5 }}
wrapperCol={{ span: 16 }}
onFinish={handleSubmit}
initialValues={{ anonymous: 0 }}
style={{ zIndex: 1, position: 'relative' }}
>
<Form.Item
label={<span style={{ fontWeight: 500 }}>主标题</span>}
name="title"
rules={[{ required: true, message: '请输入主标题' }]}
>
<Input
placeholder="请输入主标题"
size="large"
style={{
background: 'rgba(255,255,255,0.06)',
border: '1px solid #333',
color: '#fff',
}}
/>
</Form.Item>
<Form.Item label={<span style={{ fontWeight: 500 }}>副标题</span>} name="subheading">
<Input
placeholder="可选,副标题"
size="large"
style={{
background: 'rgba(255,255,255,0.06)',
border: '1px solid #333',
color: '#fff',
}}
/>
</Form.Item>
<Form.Item
label={<span style={{ fontWeight: 500 }}>种子名称</span>}
name="name"
rules={[{ required: true, message: '请输入种子名称' }]}
>
<Input
placeholder="请输入种子名称"
size="large"
style={{
background: 'rgba(255,255,255,0.06)',
border: '1px solid #333',
color: '#fff',
}}
/>
</Form.Item>
<Form.Item
label={<span style={{ fontWeight: 500 }}>分类</span>}
name="category"
rules={[{ required: true, message: '请选择分类' }]}
>
<Select
placeholder="请选择分类"
size="large"
dropdownStyle={{ background: '#232526', color: '#fff' }}
style={{
background: 'rgba(255,255,255,0.06)',
border: '1px solid #333',
color: '#fff',
}}
>
{categories.map((cat) => (
<Option key={cat.id} value={cat.id}>
{cat.name}
</Option>
))}
</Select>
</Form.Item>
<Form.Item label={<span style={{ fontWeight: 500 }}>标签</span>}>
<Space wrap>
{customTags.map((tag) => (
<Tag
key={tag}
closable
color="geekblue"
onClose={() => handleTagClose(tag)}
style={{
marginBottom: 4,
fontSize: 15,
padding: '4px 12px',
borderRadius: 8,
}}
>
{tag}
</Tag>
))}
{tagInputVisible ? (
<Input
size="small"
style={{
width: 120,
background: 'rgba(255,255,255,0.08)',
color: '#fff',
border: '1px solid #333',
}}
value={tagInputValue}
onChange={handleTagInputChange}
onBlur={handleTagInputConfirm}
onPressEnter={handleTagInputConfirm}
autoFocus
/>
) : (
<Tag
onClick={showTagInput}
style={{
background: 'rgba(255,255,255,0.08)',
border: '1px dashed #1890ff',
cursor: 'pointer',
color: '#1890ff',
fontSize: 15,
borderRadius: 8,
padding: '4px 12px',
}}
>
<PlusOutlined /> 自定义标签
</Tag>
)}
</Space>
</Form.Item>
<Form.Item
label={<span style={{ fontWeight: 500 }}>描述</span>}
name="description"
rules={[{ required: true, message: '请输入描述' }]}
>
<TextArea
rows={6}
placeholder="请输入种子描述,支持Markdown"
style={{
background: 'rgba(255,255,255,0.06)',
border: '1px solid #333',
color: '#fff',
fontSize: 15,
}}
/>
</Form.Item>
<Form.Item label={<span style={{ fontWeight: 500 }}>备注</span>} name="remark">
<Input
placeholder="可选,备注信息"
size="large"
style={{
background: 'rgba(255,255,255,0.06)',
border: '1px solid #333',
color: '#fff',
}}
/>
</Form.Item>
<Form.Item
label={<span style={{ fontWeight: 500 }}>匿名上传</span>}
name="anonymous"
valuePropName="checked"
>
<Select
size="large"
style={{
background: 'rgba(255,255,255,0.06)',
border: '1px solid #333',
color: '#fff',
}}
>
<Option value={0}>否</Option>
<Option value={1}>是</Option>
</Select>
</Form.Item>
<Form.Item
label={<span style={{ fontWeight: 500 }}>上传.torrent文件</span>}
required
>
<Upload
beforeUpload={beforeUpload}
fileList={fileList}
onRemove={() => setFileList([])}
accept=".torrent"
maxCount={1}
showUploadList={{ showRemoveIcon: true }}
customRequest={() => {}}
>
<Button
icon={<UploadOutlined />}
size="large"
style={{
background: 'linear-gradient(90deg, #667eea 0%, #764ba2 100%)',
border: 'none',
color: '#fff',
fontWeight: 500,
}}
>
选择.torrent文件
</Button>
</Upload>
</Form.Item>
<Form.Item wrapperCol={{ span: 16, offset: 5 }}>
<Button
type="primary"
htmlType="submit"
loading={uploading}
block
size="large"
style={{
background: 'linear-gradient(90deg, #667eea 0%, #764ba2 100%)',
border: 'none',
fontWeight: 600,
letterSpacing: 2,
fontSize: 18,
marginTop: 8,
boxShadow: '0 4px 16px 0 rgba(118,75,162,0.15)',
}}
>
上传
</Button>
</Form.Item>
</Form>
</div>
);
};
export default TorrentUpload;