blob: a3ac4ad4f42a1469bdf5970f2dde401b67569844 [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';
223010095b28c672025-04-10 20:12:45 +08007
8const PublishSeed = () => {
9 const [title, setTitle] = useState('');
10 const [description, setDescription] = useState('');
11 const [tags, setTags] = useState([]);
12 const [category, setCategory] = useState('movie');
223010095b28c672025-04-10 20:12:45 +080013 const [message, setMessage] = useState('');
14 const [isLoading, setIsLoading] = useState(false);
22301009df48f962025-06-05 13:40:44 +080015 const [fileName, setFileName] = useState('');
2230100980aaf0d2025-06-05 23:20:05 +080016 const [imageFile, setImageFile] = useState(null);
17 const [previewUrl, setPreviewUrl] = useState('');
223010095b28c672025-04-10 20:12:45 +080018
2230100980aaf0d2025-06-05 23:20:05 +080019 const fileInputRef = useRef(null);
20 const imageInputRef = useRef(null);
22301009df48f962025-06-05 13:40:44 +080021 const { user } = useUser();
2230100964011632025-06-04 21:57:22 +080022
2230100980aaf0d2025-06-05 23:20:05 +080023 useEffect(() => {
24 console.log('[DEBUG] 当前用户:', user);
25 }, [user]);
26
223010095b28c672025-04-10 20:12:45 +080027 const handleTagsChange = (e) => {
2230100980aaf0d2025-06-05 23:20:05 +080028 console.log('[DEBUG] 标签输入变化:', e.target.value);
29 setTags(e.target.value.split(',').map(tag => tag.trim()).filter(Boolean));
223010095b28c672025-04-10 20:12:45 +080030 };
31
22301009df48f962025-06-05 13:40:44 +080032 const handleFileButtonClick = () => {
2230100980aaf0d2025-06-05 23:20:05 +080033 console.log('[DEBUG] 触发文件选择按钮点击');
34 fileInputRef.current?.click();
35 };
36
37 const handleImageButtonClick = () => {
38 console.log('[DEBUG] 触发封面图片选择按钮点击');
39 imageInputRef.current?.click();
22301009df48f962025-06-05 13:40:44 +080040 };
41
223010095b28c672025-04-10 20:12:45 +080042 const handleFileChange = (e) => {
2230100980aaf0d2025-06-05 23:20:05 +080043 console.log('[DEBUG] 种子文件选择变化:', e.target.files);
22301009df48f962025-06-05 13:40:44 +080044 const selectedFile = e.target.files[0];
45 if (selectedFile) {
2230100980aaf0d2025-06-05 23:20:05 +080046 setFileName(selectedFile.name);
22301009df48f962025-06-05 13:40:44 +080047 }
223010095b28c672025-04-10 20:12:45 +080048 };
49
2230100980aaf0d2025-06-05 23:20:05 +080050 const handleImageChange = (e) => {
51 console.log('[DEBUG] 封面图片选择变化:', e.target.files);
52 const img = e.target.files[0];
53 if (!img) return;
54 setImageFile(img);
55 setPreviewUrl(URL.createObjectURL(img));
56 };
22301009df48f962025-06-05 13:40:44 +080057
2230100980aaf0d2025-06-05 23:20:05 +080058 const handleSubmit = async (e) => {
59 console.log('[DEBUG] handleSubmit 被触发', e);
60 e.preventDefault();
22301009df48f962025-06-05 13:40:44 +080061
223010095b28c672025-04-10 20:12:45 +080062 setIsLoading(true);
63 setMessage('');
64
2230100980aaf0d2025-06-05 23:20:05 +080065 const currentFile = fileInputRef.current?.files[0];
66 console.log('[DEBUG] 当前选择文件:', currentFile);
67
68 if (!user || !user.userId) {
69 console.log('[DEBUG] 用户未登录,阻止上传');
2230100964011632025-06-04 21:57:22 +080070 setMessage('请先登录');
71 setIsLoading(false);
72 return;
73 }
74
22301009df48f962025-06-05 13:40:44 +080075 if (!currentFile || !currentFile.name.toLowerCase().endsWith('.torrent')) {
2230100980aaf0d2025-06-05 23:20:05 +080076 console.log('[DEBUG] 文件校验失败');
2230100964011632025-06-04 21:57:22 +080077 setMessage('请上传一个 .torrent 文件');
78 setIsLoading(false);
79 return;
80 }
81
223010095b28c672025-04-10 20:12:45 +080082 const formData = new FormData();
22301009df48f962025-06-05 13:40:44 +080083 formData.append('file', currentFile);
223010095b28c672025-04-10 20:12:45 +080084 formData.append('title', title);
85 formData.append('description', description);
223010095b28c672025-04-10 20:12:45 +080086 formData.append('category', category);
2230100980aaf0d2025-06-05 23:20:05 +080087 formData.append('tags', tags.join(',')); // 逗号分隔字符串
88 formData.append('uploader', user.userId);
89
90 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 (
116 <div className="publish-seed-container">
2230100964011632025-06-04 21:57:22 +0800117 <Header />
Krishyac0f7e9b2025-04-22 15:28:28 +0800118 <div className="pub-card">
2230100964011632025-06-04 21:57:22 +0800119 {message && <div className="message">{message}</div>}
2230100980aaf0d2025-06-05 23:20:05 +0800120 <form
121 onSubmit={(e) => {
122 console.log('[DEBUG] form onSubmit 触发');
123 handleSubmit(e);
124 }}
125 encType="multipart/form-data"
126 >
2230100964011632025-06-04 21:57:22 +0800127 <div className="title-tag">
128 <label>标题</label>
129 <input
130 type="text"
131 value={title}
2230100980aaf0d2025-06-05 23:20:05 +0800132 onChange={(e) => {
133 console.log('[DEBUG] 标题输入变化:', e.target.value);
134 setTitle(e.target.value);
135 }}
2230100964011632025-06-04 21:57:22 +0800136 required
137 />
138 </div>
223010095b28c672025-04-10 20:12:45 +0800139
2230100964011632025-06-04 21:57:22 +0800140 <div className="discription">
141 <label>描述</label>
142 <textarea
143 value={description}
2230100980aaf0d2025-06-05 23:20:05 +0800144 onChange={(e) => {
145 console.log('[DEBUG] 描述输入变化:', e.target.value);
146 setDescription(e.target.value);
147 }}
2230100964011632025-06-04 21:57:22 +0800148 required
149 />
150 </div>
223010095b28c672025-04-10 20:12:45 +0800151
2230100964011632025-06-04 21:57:22 +0800152 <div className="title-tag">
153 <label>标签 (逗号分隔)</label>
154 <input
155 type="text"
156 value={tags.join(', ')}
157 onChange={handleTagsChange}
158 placeholder="例如:科幻, 动作"
159 required
160 />
161 </div>
223010095b28c672025-04-10 20:12:45 +0800162
2230100964011632025-06-04 21:57:22 +0800163 <div className="pub-categoty">
164 <label>分类</label>
165 <select
166 value={category}
2230100980aaf0d2025-06-05 23:20:05 +0800167 onChange={(e) => {
168 console.log('[DEBUG] 分类选择变化:', e.target.value);
169 setCategory(e.target.value);
170 }}
2230100964011632025-06-04 21:57:22 +0800171 required
172 >
173 <option value="movie">电影</option>
174 <option value="tv">电视剧</option>
175 <option value="music">音乐</option>
22301111a289e262025-06-07 22:38:46 +0800176 <option value="anime">动漫</option>
177 <option value="game">游戏</option>
178 <option value="variety">综艺</option>
179 <option value="software">软件</option>
180 <option value="sports">体育</option>
181 <option value="study">学习</option>
182 <option value="documentary">纪录片</option>
183 <option value="other">其他</option>
2230100964011632025-06-04 21:57:22 +0800184 </select>
185 </div>
223010095b28c672025-04-10 20:12:45 +0800186
2230100964011632025-06-04 21:57:22 +0800187 <div className="seed-file">
188 <label>种子文件</label>
2230100980aaf0d2025-06-05 23:20:05 +0800189 <div
190 className="seed-file-label"
191 onClick={handleFileButtonClick}
192 style={{ cursor: 'pointer' }}
193 >
Krishyaf1d0ea82025-05-03 17:01:58 +0800194 点击选择文件
22301009df48f962025-06-05 13:40:44 +0800195 </div>
196 <input
197 type="file"
198 accept=".torrent"
199 ref={fileInputRef}
200 onChange={handleFileChange}
201 style={{ display: 'none' }}
202 />
203 {fileName && <div style={{ marginTop: '5px' }}>{fileName}</div>}
2230100964011632025-06-04 21:57:22 +0800204 </div>
223010095b28c672025-04-10 20:12:45 +0800205
2230100964011632025-06-04 21:57:22 +0800206 <div className="form-group">
2230100980aaf0d2025-06-05 23:20:05 +0800207 <label>封面图</label>
208 <div className="cover-upload">
209 <button type="button" onClick={handleImageButtonClick}>
210 上传图片
211 </button>
212 <input
213 type="file"
214 accept="image/*"
215 ref={imageInputRef}
216 onChange={handleImageChange}
217 style={{ display: 'none' }}
218 />
219 </div>
220 {previewUrl && (
221 <div style={{ marginTop: '10px' }}>
222 <img
223 src={previewUrl}
224 alt="封面预览"
225 style={{ maxWidth: '100%', maxHeight: '200px' }}
226 />
227 </div>
228 )}
2230100964011632025-06-04 21:57:22 +0800229 </div>
223010095b28c672025-04-10 20:12:45 +0800230
2230100964011632025-06-04 21:57:22 +0800231 <div className="upload-button">
2230100980aaf0d2025-06-05 23:20:05 +0800232 <button
233 type="submit"
234 disabled={isLoading}
235 onClick={() => console.log('[DEBUG] 上传按钮 onClick 触发')}
236 >
2230100964011632025-06-04 21:57:22 +0800237 {isLoading ? '正在上传...' : '上传种子'}
238 </button>
239 </div>
240 </form>
Krishyac0f7e9b2025-04-22 15:28:28 +0800241 </div>
223010095b28c672025-04-10 20:12:45 +0800242 </div>
243 );
244};
245
246export default PublishSeed;