blob: 27717cabf1e1a7e7147f47ea91044fd12220c900 [file] [log] [blame]
2230100980aaf0d2025-06-05 23:20:05 +08001// export default PublishSeed;
2import React, { useState, useRef, useEffect } from 'react';
223010095b28c672025-04-10 20:12:45 +08003import axios from 'axios';
2230100964011632025-06-04 21:57:22 +08004import Header from '../../components/Header';
5import './PublishSeed.css';
6import { useUser } from '../../context/UserContext';
223010091e2aea72025-06-08 16:35:54 +08007import { uploadFile } from '../../api/file';
223010095b28c672025-04-10 20:12:45 +08008
9const PublishSeed = () => {
10 const [title, setTitle] = useState('');
11 const [description, setDescription] = useState('');
12 const [tags, setTags] = useState([]);
13 const [category, setCategory] = useState('movie');
223010095b28c672025-04-10 20:12:45 +080014 const [message, setMessage] = useState('');
15 const [isLoading, setIsLoading] = useState(false);
22301009df48f962025-06-05 13:40:44 +080016 const [fileName, setFileName] = useState('');
2230100980aaf0d2025-06-05 23:20:05 +080017 const [imageFile, setImageFile] = useState(null);
18 const [previewUrl, setPreviewUrl] = useState('');
223010095b28c672025-04-10 20:12:45 +080019
2230100980aaf0d2025-06-05 23:20:05 +080020 const fileInputRef = useRef(null);
21 const imageInputRef = useRef(null);
22301009df48f962025-06-05 13:40:44 +080022 const { user } = useUser();
2230100964011632025-06-04 21:57:22 +080023
2230100980aaf0d2025-06-05 23:20:05 +080024 useEffect(() => {
25 console.log('[DEBUG] 当前用户:', user);
26 }, [user]);
27
223010095b28c672025-04-10 20:12:45 +080028 const handleTagsChange = (e) => {
2230100980aaf0d2025-06-05 23:20:05 +080029 console.log('[DEBUG] 标签输入变化:', e.target.value);
30 setTags(e.target.value.split(',').map(tag => tag.trim()).filter(Boolean));
223010095b28c672025-04-10 20:12:45 +080031 };
32
22301009df48f962025-06-05 13:40:44 +080033 const handleFileButtonClick = () => {
2230100980aaf0d2025-06-05 23:20:05 +080034 console.log('[DEBUG] 触发文件选择按钮点击');
35 fileInputRef.current?.click();
36 };
37
38 const handleImageButtonClick = () => {
39 console.log('[DEBUG] 触发封面图片选择按钮点击');
40 imageInputRef.current?.click();
22301009df48f962025-06-05 13:40:44 +080041 };
42
223010095b28c672025-04-10 20:12:45 +080043 const handleFileChange = (e) => {
2230100980aaf0d2025-06-05 23:20:05 +080044 console.log('[DEBUG] 种子文件选择变化:', e.target.files);
22301009df48f962025-06-05 13:40:44 +080045 const selectedFile = e.target.files[0];
46 if (selectedFile) {
2230100980aaf0d2025-06-05 23:20:05 +080047 setFileName(selectedFile.name);
22301009df48f962025-06-05 13:40:44 +080048 }
223010095b28c672025-04-10 20:12:45 +080049 };
50
2230100980aaf0d2025-06-05 23:20:05 +080051 const handleImageChange = (e) => {
52 console.log('[DEBUG] 封面图片选择变化:', e.target.files);
53 const img = e.target.files[0];
54 if (!img) return;
55 setImageFile(img);
56 setPreviewUrl(URL.createObjectURL(img));
57 };
22301009df48f962025-06-05 13:40:44 +080058
2230100980aaf0d2025-06-05 23:20:05 +080059 const handleSubmit = async (e) => {
60 console.log('[DEBUG] handleSubmit 被触发', e);
61 e.preventDefault();
22301009df48f962025-06-05 13:40:44 +080062
223010095b28c672025-04-10 20:12:45 +080063 setIsLoading(true);
64 setMessage('');
65
2230100980aaf0d2025-06-05 23:20:05 +080066 const currentFile = fileInputRef.current?.files[0];
67 console.log('[DEBUG] 当前选择文件:', currentFile);
68
69 if (!user || !user.userId) {
70 console.log('[DEBUG] 用户未登录,阻止上传');
2230100964011632025-06-04 21:57:22 +080071 setMessage('请先登录');
72 setIsLoading(false);
73 return;
74 }
75
22301009df48f962025-06-05 13:40:44 +080076 if (!currentFile || !currentFile.name.toLowerCase().endsWith('.torrent')) {
2230100980aaf0d2025-06-05 23:20:05 +080077 console.log('[DEBUG] 文件校验失败');
2230100964011632025-06-04 21:57:22 +080078 setMessage('请上传一个 .torrent 文件');
79 setIsLoading(false);
80 return;
81 }
82
223010095b28c672025-04-10 20:12:45 +080083 const formData = new FormData();
22301009df48f962025-06-05 13:40:44 +080084 formData.append('file', currentFile);
223010095b28c672025-04-10 20:12:45 +080085 formData.append('title', title);
86 formData.append('description', description);
223010095b28c672025-04-10 20:12:45 +080087 formData.append('category', category);
2230100980aaf0d2025-06-05 23:20:05 +080088 formData.append('tags', tags.join(',')); // 逗号分隔字符串
89 formData.append('uploader', user.userId);
2230100980aaf0d2025-06-05 23:20:05 +080090 if (imageFile) {
2230100999cf3162025-06-06 00:19:25 +080091 formData.append('coverImage', imageFile);
2230100980aaf0d2025-06-05 23:20:05 +080092 }
223010095b28c672025-04-10 20:12:45 +080093
94 try {
2230100980aaf0d2025-06-05 23:20:05 +080095 console.log('[DEBUG] 发送上传请求...');
2230100964011632025-06-04 21:57:22 +080096 const response = await axios.post('/seeds/upload', formData, {
2230100980aaf0d2025-06-05 23:20:05 +080097 // axios 会自动处理 multipart/form-data Content-Type 边界,不用手动设置
98 // headers: { 'Content-Type': 'multipart/form-data' },
223010095b28c672025-04-10 20:12:45 +080099 });
2230100980aaf0d2025-06-05 23:20:05 +0800100 console.log('[DEBUG] 请求成功,响应:', response.data);
223010095b28c672025-04-10 20:12:45 +0800101
2230100980aaf0d2025-06-05 23:20:05 +0800102 if (response.data.status === 'success') {
223010095b28c672025-04-10 20:12:45 +0800103 setMessage('种子上传成功');
104 } else {
2230100980aaf0d2025-06-05 23:20:05 +0800105 setMessage(response.data.message || '上传失败,请稍后再试');
223010095b28c672025-04-10 20:12:45 +0800106 }
107 } catch (error) {
22301009df48f962025-06-05 13:40:44 +0800108 console.error('[handleSubmit] 上传失败:', error);
223010095b28c672025-04-10 20:12:45 +0800109 setMessage('上传失败,发生了错误');
110 } finally {
111 setIsLoading(false);
112 }
113 };
114
115 return (
223010091e2aea72025-06-08 16:35:54 +0800116 <div className="ps-container">
2230100964011632025-06-04 21:57:22 +0800117 <Header />
223010091e2aea72025-06-08 16:35:54 +0800118 <div className="ps-card">
119 {message && <div className="ps-message">{message}</div>}
2230100980aaf0d2025-06-05 23:20:05 +0800120 <form
223010091e2aea72025-06-08 16:35:54 +0800121 className="ps-form"
2230100980aaf0d2025-06-05 23:20:05 +0800122 onSubmit={(e) => {
123 console.log('[DEBUG] form onSubmit 触发');
124 handleSubmit(e);
125 }}
126 encType="multipart/form-data"
127 >
223010091e2aea72025-06-08 16:35:54 +0800128 <div>
129 <label className="ps-label">标题</label>
2230100964011632025-06-04 21:57:22 +0800130 <input
223010091e2aea72025-06-08 16:35:54 +0800131 className="ps-input-text"
2230100964011632025-06-04 21:57:22 +0800132 type="text"
133 value={title}
2230100980aaf0d2025-06-05 23:20:05 +0800134 onChange={(e) => {
135 console.log('[DEBUG] 标题输入变化:', e.target.value);
136 setTitle(e.target.value);
137 }}
2230100964011632025-06-04 21:57:22 +0800138 required
139 />
140 </div>
223010095b28c672025-04-10 20:12:45 +0800141
223010091e2aea72025-06-08 16:35:54 +0800142 <div>
143 <label className="ps-label">描述</label>
2230100964011632025-06-04 21:57:22 +0800144 <textarea
223010091e2aea72025-06-08 16:35:54 +0800145 className="ps-textarea"
2230100964011632025-06-04 21:57:22 +0800146 value={description}
2230100980aaf0d2025-06-05 23:20:05 +0800147 onChange={(e) => {
148 console.log('[DEBUG] 描述输入变化:', e.target.value);
149 setDescription(e.target.value);
150 }}
2230100964011632025-06-04 21:57:22 +0800151 required
152 />
153 </div>
223010095b28c672025-04-10 20:12:45 +0800154
223010091e2aea72025-06-08 16:35:54 +0800155 <div>
156 <label className="ps-label">标签 (逗号分隔)</label>
2230100964011632025-06-04 21:57:22 +0800157 <input
223010091e2aea72025-06-08 16:35:54 +0800158 className="ps-input-text"
2230100964011632025-06-04 21:57:22 +0800159 type="text"
160 value={tags.join(', ')}
161 onChange={handleTagsChange}
162 placeholder="例如:科幻, 动作"
163 required
164 />
165 </div>
223010095b28c672025-04-10 20:12:45 +0800166
223010091e2aea72025-06-08 16:35:54 +0800167 <div>
168 <label className="ps-label">分类</label>
2230100964011632025-06-04 21:57:22 +0800169 <select
223010091e2aea72025-06-08 16:35:54 +0800170 className="ps-select"
2230100964011632025-06-04 21:57:22 +0800171 value={category}
2230100980aaf0d2025-06-05 23:20:05 +0800172 onChange={(e) => {
173 console.log('[DEBUG] 分类选择变化:', e.target.value);
174 setCategory(e.target.value);
175 }}
2230100964011632025-06-04 21:57:22 +0800176 required
177 >
178 <option value="movie">电影</option>
179 <option value="tv">电视剧</option>
180 <option value="music">音乐</option>
22301111a289e262025-06-07 22:38:46 +0800181 <option value="anime">动漫</option>
182 <option value="game">游戏</option>
183 <option value="variety">综艺</option>
184 <option value="software">软件</option>
185 <option value="sports">体育</option>
186 <option value="study">学习</option>
187 <option value="documentary">纪录片</option>
188 <option value="other">其他</option>
2230100964011632025-06-04 21:57:22 +0800189 </select>
190 </div>
223010095b28c672025-04-10 20:12:45 +0800191
223010091e2aea72025-06-08 16:35:54 +0800192 <div>
193 <label className="ps-label">种子文件</label>
2230100980aaf0d2025-06-05 23:20:05 +0800194 <div
223010091e2aea72025-06-08 16:35:54 +0800195 className="ps-seed-file-label"
2230100980aaf0d2025-06-05 23:20:05 +0800196 onClick={handleFileButtonClick}
197 style={{ cursor: 'pointer' }}
198 >
Krishyaf1d0ea82025-05-03 17:01:58 +0800199 点击选择文件
22301009df48f962025-06-05 13:40:44 +0800200 </div>
201 <input
202 type="file"
203 accept=".torrent"
204 ref={fileInputRef}
205 onChange={handleFileChange}
223010091e2aea72025-06-08 16:35:54 +0800206 className="ps-seed-file-input"
22301009df48f962025-06-05 13:40:44 +0800207 />
223010091e2aea72025-06-08 16:35:54 +0800208 {fileName && <div style={{ marginTop: '5px', color: '#5F4437' }}>{fileName}</div>}
2230100964011632025-06-04 21:57:22 +0800209 </div>
223010095b28c672025-04-10 20:12:45 +0800210
223010091e2aea72025-06-08 16:35:54 +0800211 <div>
212 <label className="ps-label">封面图</label>
213 <div>
214 <button
215 type="button"
216 onClick={handleImageButtonClick}
217 className="ps-cover-upload-button"
218 >
2230100980aaf0d2025-06-05 23:20:05 +0800219 上传图片
220 </button>
221 <input
222 type="file"
223 accept="image/*"
224 ref={imageInputRef}
225 onChange={handleImageChange}
223010091e2aea72025-06-08 16:35:54 +0800226 className="ps-cover-upload-input"
2230100980aaf0d2025-06-05 23:20:05 +0800227 />
228 </div>
229 {previewUrl && (
230 <div style={{ marginTop: '10px' }}>
231 <img
232 src={previewUrl}
233 alt="封面预览"
223010091e2aea72025-06-08 16:35:54 +0800234 className="ps-img-preview"
2230100980aaf0d2025-06-05 23:20:05 +0800235 />
236 </div>
237 )}
2230100964011632025-06-04 21:57:22 +0800238 </div>
223010095b28c672025-04-10 20:12:45 +0800239
223010091e2aea72025-06-08 16:35:54 +0800240 <div className="ps-upload-button">
2230100980aaf0d2025-06-05 23:20:05 +0800241 <button
242 type="submit"
243 disabled={isLoading}
244 onClick={() => console.log('[DEBUG] 上传按钮 onClick 触发')}
245 >
2230100964011632025-06-04 21:57:22 +0800246 {isLoading ? '正在上传...' : '上传种子'}
247 </button>
248 </div>
249 </form>
Krishyac0f7e9b2025-04-22 15:28:28 +0800250 </div>
223010095b28c672025-04-10 20:12:45 +0800251 </div>
252 );
253};
254
255export default PublishSeed;