blob: 7287e82b26d6c66c3a642319480c29d8dcd9af78 [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 = () => {
2230100980aaf0d2025-06-05 23:20:05 +08009 console.log('[DEBUG] PublishSeed 组件渲染');
10
223010095b28c672025-04-10 20:12:45 +080011 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);
91
92 if (imageFile) {
93 formData.append('image_url', imageFile);
94 }
223010095b28c672025-04-10 20:12:45 +080095
96 try {
2230100980aaf0d2025-06-05 23:20:05 +080097 console.log('[DEBUG] 发送上传请求...');
2230100964011632025-06-04 21:57:22 +080098 const response = await axios.post('/seeds/upload', formData, {
2230100980aaf0d2025-06-05 23:20:05 +080099 // axios 会自动处理 multipart/form-data Content-Type 边界,不用手动设置
100 // headers: { 'Content-Type': 'multipart/form-data' },
223010095b28c672025-04-10 20:12:45 +0800101 });
2230100980aaf0d2025-06-05 23:20:05 +0800102 console.log('[DEBUG] 请求成功,响应:', response.data);
223010095b28c672025-04-10 20:12:45 +0800103
2230100980aaf0d2025-06-05 23:20:05 +0800104 if (response.data.status === 'success') {
223010095b28c672025-04-10 20:12:45 +0800105 setMessage('种子上传成功');
106 } else {
2230100980aaf0d2025-06-05 23:20:05 +0800107 setMessage(response.data.message || '上传失败,请稍后再试');
223010095b28c672025-04-10 20:12:45 +0800108 }
109 } catch (error) {
22301009df48f962025-06-05 13:40:44 +0800110 console.error('[handleSubmit] 上传失败:', error);
223010095b28c672025-04-10 20:12:45 +0800111 setMessage('上传失败,发生了错误');
112 } finally {
113 setIsLoading(false);
114 }
115 };
116
117 return (
118 <div className="publish-seed-container">
2230100964011632025-06-04 21:57:22 +0800119 <Header />
Krishyac0f7e9b2025-04-22 15:28:28 +0800120 <div className="pub-card">
2230100964011632025-06-04 21:57:22 +0800121 {message && <div className="message">{message}</div>}
2230100980aaf0d2025-06-05 23:20:05 +0800122 <form
123 onSubmit={(e) => {
124 console.log('[DEBUG] form onSubmit 触发');
125 handleSubmit(e);
126 }}
127 encType="multipart/form-data"
128 >
2230100964011632025-06-04 21:57:22 +0800129 <div className="title-tag">
130 <label>标题</label>
131 <input
132 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
2230100964011632025-06-04 21:57:22 +0800142 <div className="discription">
143 <label>描述</label>
144 <textarea
145 value={description}
2230100980aaf0d2025-06-05 23:20:05 +0800146 onChange={(e) => {
147 console.log('[DEBUG] 描述输入变化:', e.target.value);
148 setDescription(e.target.value);
149 }}
2230100964011632025-06-04 21:57:22 +0800150 required
151 />
152 </div>
223010095b28c672025-04-10 20:12:45 +0800153
2230100964011632025-06-04 21:57:22 +0800154 <div className="title-tag">
155 <label>标签 (逗号分隔)</label>
156 <input
157 type="text"
158 value={tags.join(', ')}
159 onChange={handleTagsChange}
160 placeholder="例如:科幻, 动作"
161 required
162 />
163 </div>
223010095b28c672025-04-10 20:12:45 +0800164
2230100964011632025-06-04 21:57:22 +0800165 <div className="pub-categoty">
166 <label>分类</label>
167 <select
168 value={category}
2230100980aaf0d2025-06-05 23:20:05 +0800169 onChange={(e) => {
170 console.log('[DEBUG] 分类选择变化:', e.target.value);
171 setCategory(e.target.value);
172 }}
2230100964011632025-06-04 21:57:22 +0800173 required
174 >
175 <option value="movie">电影</option>
176 <option value="tv">电视剧</option>
177 <option value="music">音乐</option>
178 </select>
179 </div>
223010095b28c672025-04-10 20:12:45 +0800180
2230100964011632025-06-04 21:57:22 +0800181 <div className="seed-file">
182 <label>种子文件</label>
2230100980aaf0d2025-06-05 23:20:05 +0800183 <div
184 className="seed-file-label"
185 onClick={handleFileButtonClick}
186 style={{ cursor: 'pointer' }}
187 >
Krishyaf1d0ea82025-05-03 17:01:58 +0800188 点击选择文件
22301009df48f962025-06-05 13:40:44 +0800189 </div>
190 <input
191 type="file"
192 accept=".torrent"
193 ref={fileInputRef}
194 onChange={handleFileChange}
195 style={{ display: 'none' }}
196 />
197 {fileName && <div style={{ marginTop: '5px' }}>{fileName}</div>}
2230100964011632025-06-04 21:57:22 +0800198 </div>
223010095b28c672025-04-10 20:12:45 +0800199
2230100964011632025-06-04 21:57:22 +0800200 <div className="form-group">
2230100980aaf0d2025-06-05 23:20:05 +0800201 <label>封面图</label>
202 <div className="cover-upload">
203 <button type="button" onClick={handleImageButtonClick}>
204 上传图片
205 </button>
206 <input
207 type="file"
208 accept="image/*"
209 ref={imageInputRef}
210 onChange={handleImageChange}
211 style={{ display: 'none' }}
212 />
213 </div>
214 {previewUrl && (
215 <div style={{ marginTop: '10px' }}>
216 <img
217 src={previewUrl}
218 alt="封面预览"
219 style={{ maxWidth: '100%', maxHeight: '200px' }}
220 />
221 </div>
222 )}
2230100964011632025-06-04 21:57:22 +0800223 </div>
223010095b28c672025-04-10 20:12:45 +0800224
2230100964011632025-06-04 21:57:22 +0800225 <div className="upload-button">
2230100980aaf0d2025-06-05 23:20:05 +0800226 <button
227 type="submit"
228 disabled={isLoading}
229 onClick={() => console.log('[DEBUG] 上传按钮 onClick 触发')}
230 >
2230100964011632025-06-04 21:57:22 +0800231 {isLoading ? '正在上传...' : '上传种子'}
232 </button>
233 </div>
234 </form>
Krishyac0f7e9b2025-04-22 15:28:28 +0800235 </div>
223010095b28c672025-04-10 20:12:45 +0800236 </div>
237 );
238};
239
240export default PublishSeed;