blob: 2f5bddba0a03dd1cb9087340ef4b96aa4fd4cb49 [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';
22301009207e2db2025-06-09 00:27:28 +08008import AuthButton from '../../components/AuthButton';
223010095b28c672025-04-10 20:12:45 +08009
10const PublishSeed = () => {
11 const [title, setTitle] = useState('');
12 const [description, setDescription] = useState('');
13 const [tags, setTags] = useState([]);
14 const [category, setCategory] = useState('movie');
223010095b28c672025-04-10 20:12:45 +080015 const [message, setMessage] = useState('');
16 const [isLoading, setIsLoading] = useState(false);
22301009df48f962025-06-05 13:40:44 +080017 const [fileName, setFileName] = useState('');
2230100980aaf0d2025-06-05 23:20:05 +080018 const [imageFile, setImageFile] = useState(null);
19 const [previewUrl, setPreviewUrl] = useState('');
223010095b28c672025-04-10 20:12:45 +080020
2230100980aaf0d2025-06-05 23:20:05 +080021 const fileInputRef = useRef(null);
22 const imageInputRef = useRef(null);
22301009df48f962025-06-05 13:40:44 +080023 const { user } = useUser();
2230100964011632025-06-04 21:57:22 +080024
2230100980aaf0d2025-06-05 23:20:05 +080025 useEffect(() => {
26 console.log('[DEBUG] 当前用户:', user);
27 }, [user]);
28
223010095b28c672025-04-10 20:12:45 +080029 const handleTagsChange = (e) => {
2230100980aaf0d2025-06-05 23:20:05 +080030 console.log('[DEBUG] 标签输入变化:', e.target.value);
31 setTags(e.target.value.split(',').map(tag => tag.trim()).filter(Boolean));
223010095b28c672025-04-10 20:12:45 +080032 };
33
22301009df48f962025-06-05 13:40:44 +080034 const handleFileButtonClick = () => {
2230100980aaf0d2025-06-05 23:20:05 +080035 console.log('[DEBUG] 触发文件选择按钮点击');
36 fileInputRef.current?.click();
37 };
38
39 const handleImageButtonClick = () => {
40 console.log('[DEBUG] 触发封面图片选择按钮点击');
41 imageInputRef.current?.click();
22301009df48f962025-06-05 13:40:44 +080042 };
43
223010095b28c672025-04-10 20:12:45 +080044 const handleFileChange = (e) => {
2230100980aaf0d2025-06-05 23:20:05 +080045 console.log('[DEBUG] 种子文件选择变化:', e.target.files);
22301009df48f962025-06-05 13:40:44 +080046 const selectedFile = e.target.files[0];
47 if (selectedFile) {
2230100980aaf0d2025-06-05 23:20:05 +080048 setFileName(selectedFile.name);
22301009df48f962025-06-05 13:40:44 +080049 }
223010095b28c672025-04-10 20:12:45 +080050 };
51
2230100980aaf0d2025-06-05 23:20:05 +080052 const handleImageChange = (e) => {
53 console.log('[DEBUG] 封面图片选择变化:', e.target.files);
54 const img = e.target.files[0];
55 if (!img) return;
56 setImageFile(img);
57 setPreviewUrl(URL.createObjectURL(img));
58 };
22301009df48f962025-06-05 13:40:44 +080059
2230100980aaf0d2025-06-05 23:20:05 +080060 const handleSubmit = async (e) => {
61 console.log('[DEBUG] handleSubmit 被触发', e);
62 e.preventDefault();
22301009df48f962025-06-05 13:40:44 +080063
223010095b28c672025-04-10 20:12:45 +080064 setIsLoading(true);
65 setMessage('');
66
2230100980aaf0d2025-06-05 23:20:05 +080067 const currentFile = fileInputRef.current?.files[0];
68 console.log('[DEBUG] 当前选择文件:', currentFile);
69
70 if (!user || !user.userId) {
71 console.log('[DEBUG] 用户未登录,阻止上传');
2230100964011632025-06-04 21:57:22 +080072 setMessage('请先登录');
73 setIsLoading(false);
74 return;
75 }
76
22301009df48f962025-06-05 13:40:44 +080077 if (!currentFile || !currentFile.name.toLowerCase().endsWith('.torrent')) {
2230100980aaf0d2025-06-05 23:20:05 +080078 console.log('[DEBUG] 文件校验失败');
2230100964011632025-06-04 21:57:22 +080079 setMessage('请上传一个 .torrent 文件');
80 setIsLoading(false);
81 return;
82 }
83
223010095b28c672025-04-10 20:12:45 +080084 const formData = new FormData();
22301009df48f962025-06-05 13:40:44 +080085 formData.append('file', currentFile);
223010095b28c672025-04-10 20:12:45 +080086 formData.append('title', title);
87 formData.append('description', description);
223010095b28c672025-04-10 20:12:45 +080088 formData.append('category', category);
2230100980aaf0d2025-06-05 23:20:05 +080089 formData.append('tags', tags.join(',')); // 逗号分隔字符串
90 formData.append('uploader', user.userId);
2230100980aaf0d2025-06-05 23:20:05 +080091 if (imageFile) {
2230100999cf3162025-06-06 00:19:25 +080092 formData.append('coverImage', imageFile);
2230100980aaf0d2025-06-05 23:20:05 +080093 }
223010095b28c672025-04-10 20:12:45 +080094
22301009cbd5aac2025-06-09 23:08:53 +080095 try {
2230100980aaf0d2025-06-05 23:20:05 +080096 console.log('[DEBUG] 发送上传请求...');
22301009cbd5aac2025-06-09 23:08:53 +080097 const response = await axios.post('/seeds/upload', formData);
98
2230100980aaf0d2025-06-05 23:20:05 +080099 console.log('[DEBUG] 请求成功,响应:', response.data);
223010095b28c672025-04-10 20:12:45 +0800100
22301009207e2db2025-06-09 00:27:28 +0800101 if (response.data.code === 0) {
223010095b28c672025-04-10 20:12:45 +0800102 setMessage('种子上传成功');
22301009cbd5aac2025-06-09 23:08:53 +0800103 } else if (response.data.code === 401) {
104 setMessage('未登录或登录已过期,请重新登录');
223010095b28c672025-04-10 20:12:45 +0800105 } else {
2230100980aaf0d2025-06-05 23:20:05 +0800106 setMessage(response.data.message || '上传失败,请稍后再试');
223010095b28c672025-04-10 20:12:45 +0800107 }
108 } catch (error) {
22301009df48f962025-06-05 13:40:44 +0800109 console.error('[handleSubmit] 上传失败:', error);
22301009cbd5aac2025-06-09 23:08:53 +0800110
111 if (error.response?.status === 401 || error.response?.data?.code === 401) {
112 setMessage('未登录或登录已过期,请重新登录');
113 } else {
114 setMessage(error.response?.data?.msg || '上传失败,发生了错误');
115 }
223010095b28c672025-04-10 20:12:45 +0800116 } finally {
117 setIsLoading(false);
118 }
22301009cbd5aac2025-06-09 23:08:53 +0800119
223010095b28c672025-04-10 20:12:45 +0800120 };
121
122 return (
223010091e2aea72025-06-08 16:35:54 +0800123 <div className="ps-container">
2230100964011632025-06-04 21:57:22 +0800124 <Header />
223010091e2aea72025-06-08 16:35:54 +0800125 <div className="ps-card">
126 {message && <div className="ps-message">{message}</div>}
2230100980aaf0d2025-06-05 23:20:05 +0800127 <form
223010091e2aea72025-06-08 16:35:54 +0800128 className="ps-form"
2230100980aaf0d2025-06-05 23:20:05 +0800129 onSubmit={(e) => {
130 console.log('[DEBUG] form onSubmit 触发');
131 handleSubmit(e);
132 }}
133 encType="multipart/form-data"
134 >
223010091e2aea72025-06-08 16:35:54 +0800135 <div>
136 <label className="ps-label">标题</label>
2230100964011632025-06-04 21:57:22 +0800137 <input
223010091e2aea72025-06-08 16:35:54 +0800138 className="ps-input-text"
2230100964011632025-06-04 21:57:22 +0800139 type="text"
140 value={title}
2230100980aaf0d2025-06-05 23:20:05 +0800141 onChange={(e) => {
142 console.log('[DEBUG] 标题输入变化:', e.target.value);
143 setTitle(e.target.value);
144 }}
2230100964011632025-06-04 21:57:22 +0800145 required
146 />
147 </div>
223010095b28c672025-04-10 20:12:45 +0800148
223010091e2aea72025-06-08 16:35:54 +0800149 <div>
150 <label className="ps-label">描述</label>
2230100964011632025-06-04 21:57:22 +0800151 <textarea
223010091e2aea72025-06-08 16:35:54 +0800152 className="ps-textarea"
2230100964011632025-06-04 21:57:22 +0800153 value={description}
2230100980aaf0d2025-06-05 23:20:05 +0800154 onChange={(e) => {
155 console.log('[DEBUG] 描述输入变化:', e.target.value);
156 setDescription(e.target.value);
157 }}
2230100964011632025-06-04 21:57:22 +0800158 required
159 />
160 </div>
223010095b28c672025-04-10 20:12:45 +0800161
223010091e2aea72025-06-08 16:35:54 +0800162 <div>
163 <label className="ps-label">标签 (逗号分隔)</label>
2230100964011632025-06-04 21:57:22 +0800164 <input
223010091e2aea72025-06-08 16:35:54 +0800165 className="ps-input-text"
2230100964011632025-06-04 21:57:22 +0800166 type="text"
167 value={tags.join(', ')}
168 onChange={handleTagsChange}
169 placeholder="例如:科幻, 动作"
170 required
171 />
172 </div>
223010095b28c672025-04-10 20:12:45 +0800173
223010091e2aea72025-06-08 16:35:54 +0800174 <div>
175 <label className="ps-label">分类</label>
2230100964011632025-06-04 21:57:22 +0800176 <select
223010091e2aea72025-06-08 16:35:54 +0800177 className="ps-select"
2230100964011632025-06-04 21:57:22 +0800178 value={category}
2230100980aaf0d2025-06-05 23:20:05 +0800179 onChange={(e) => {
180 console.log('[DEBUG] 分类选择变化:', e.target.value);
181 setCategory(e.target.value);
182 }}
2230100964011632025-06-04 21:57:22 +0800183 required
184 >
185 <option value="movie">电影</option>
186 <option value="tv">电视剧</option>
187 <option value="music">音乐</option>
22301111a289e262025-06-07 22:38:46 +0800188 <option value="anime">动漫</option>
189 <option value="game">游戏</option>
190 <option value="variety">综艺</option>
191 <option value="software">软件</option>
192 <option value="sports">体育</option>
193 <option value="study">学习</option>
194 <option value="documentary">纪录片</option>
195 <option value="other">其他</option>
2230100964011632025-06-04 21:57:22 +0800196 </select>
197 </div>
223010095b28c672025-04-10 20:12:45 +0800198
223010091e2aea72025-06-08 16:35:54 +0800199 <div>
200 <label className="ps-label">种子文件</label>
2230100980aaf0d2025-06-05 23:20:05 +0800201 <div
223010091e2aea72025-06-08 16:35:54 +0800202 className="ps-seed-file-label"
2230100980aaf0d2025-06-05 23:20:05 +0800203 onClick={handleFileButtonClick}
204 style={{ cursor: 'pointer' }}
205 >
Krishyaf1d0ea82025-05-03 17:01:58 +0800206 点击选择文件
22301009df48f962025-06-05 13:40:44 +0800207 </div>
208 <input
209 type="file"
210 accept=".torrent"
211 ref={fileInputRef}
212 onChange={handleFileChange}
223010091e2aea72025-06-08 16:35:54 +0800213 className="ps-seed-file-input"
22301009df48f962025-06-05 13:40:44 +0800214 />
223010091e2aea72025-06-08 16:35:54 +0800215 {fileName && <div style={{ marginTop: '5px', color: '#5F4437' }}>{fileName}</div>}
2230100964011632025-06-04 21:57:22 +0800216 </div>
223010095b28c672025-04-10 20:12:45 +0800217
223010091e2aea72025-06-08 16:35:54 +0800218 <div>
219 <label className="ps-label">封面图</label>
220 <div>
221 <button
222 type="button"
223 onClick={handleImageButtonClick}
224 className="ps-cover-upload-button"
225 >
2230100980aaf0d2025-06-05 23:20:05 +0800226 上传图片
227 </button>
228 <input
229 type="file"
230 accept="image/*"
231 ref={imageInputRef}
232 onChange={handleImageChange}
223010091e2aea72025-06-08 16:35:54 +0800233 className="ps-cover-upload-input"
2230100980aaf0d2025-06-05 23:20:05 +0800234 />
235 </div>
236 {previewUrl && (
237 <div style={{ marginTop: '10px' }}>
238 <img
239 src={previewUrl}
240 alt="封面预览"
223010091e2aea72025-06-08 16:35:54 +0800241 className="ps-img-preview"
2230100980aaf0d2025-06-05 23:20:05 +0800242 />
243 </div>
244 )}
2230100964011632025-06-04 21:57:22 +0800245 </div>
223010095b28c672025-04-10 20:12:45 +0800246
223010091e2aea72025-06-08 16:35:54 +0800247 <div className="ps-upload-button">
22301009207e2db2025-06-09 00:27:28 +0800248 <AuthButton
249   roles={["cookie", "chocolate", "ice-cream"]}
2230100980aaf0d2025-06-05 23:20:05 +0800250 type="submit"
251 disabled={isLoading}
252 onClick={() => console.log('[DEBUG] 上传按钮 onClick 触发')}
253 >
2230100964011632025-06-04 21:57:22 +0800254 {isLoading ? '正在上传...' : '上传种子'}
22301009207e2db2025-06-09 00:27:28 +0800255 </AuthButton>
2230100964011632025-06-04 21:57:22 +0800256 </div>
257 </form>
Krishyac0f7e9b2025-04-22 15:28:28 +0800258 </div>
223010095b28c672025-04-10 20:12:45 +0800259 </div>
260 );
261};
262
263export default PublishSeed;