22301009 | df48f96 | 2025-06-05 13:40:44 +0800 | [diff] [blame] | 1 | import React, { useState, useRef } from 'react'; |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 2 | import axios from 'axios'; |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 3 | import Header from '../../components/Header'; |
| 4 | import './PublishSeed.css'; |
| 5 | import { useUser } from '../../context/UserContext'; |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 6 | |
| 7 | const PublishSeed = () => { |
| 8 | const [title, setTitle] = useState(''); |
| 9 | const [description, setDescription] = useState(''); |
| 10 | const [tags, setTags] = useState([]); |
| 11 | const [category, setCategory] = useState('movie'); |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 12 | const [imageUrl, setImageUrl] = useState(''); |
| 13 | const [message, setMessage] = useState(''); |
| 14 | const [isLoading, setIsLoading] = useState(false); |
22301009 | df48f96 | 2025-06-05 13:40:44 +0800 | [diff] [blame] | 15 | const [fileName, setFileName] = useState(''); |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 16 | |
22301009 | df48f96 | 2025-06-05 13:40:44 +0800 | [diff] [blame] | 17 | const fileInputRef = useRef(null); // ✅ 获取 input file 引用 |
| 18 | const { user } = useUser(); |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 19 | |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 20 | const handleTagsChange = (e) => { |
| 21 | setTags(e.target.value.split(',').map(tag => tag.trim())); |
| 22 | }; |
| 23 | |
22301009 | df48f96 | 2025-06-05 13:40:44 +0800 | [diff] [blame] | 24 | const handleFileButtonClick = () => { |
| 25 | fileInputRef.current?.click(); // 点击隐藏的 input |
| 26 | }; |
| 27 | |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 28 | const handleFileChange = (e) => { |
22301009 | df48f96 | 2025-06-05 13:40:44 +0800 | [diff] [blame] | 29 | const selectedFile = e.target.files[0]; |
| 30 | if (selectedFile) { |
| 31 | setFileName(selectedFile.name); // 仅展示文件名 |
| 32 | } |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 33 | }; |
| 34 | |
| 35 | const handleSubmit = async (e) => { |
| 36 | e.preventDefault(); |
22301009 | df48f96 | 2025-06-05 13:40:44 +0800 | [diff] [blame] | 37 | console.log('[handleSubmit] 表单提交开始'); |
| 38 | |
| 39 | const currentFile = fileInputRef.current?.files[0]; // ✅ 获取文件 |
| 40 | console.log('[handleSubmit] currentFile:', currentFile); |
| 41 | |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 42 | setIsLoading(true); |
| 43 | setMessage(''); |
| 44 | |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 45 | if (!user || !user.id) { |
| 46 | setMessage('请先登录'); |
| 47 | setIsLoading(false); |
| 48 | return; |
| 49 | } |
| 50 | |
22301009 | df48f96 | 2025-06-05 13:40:44 +0800 | [diff] [blame] | 51 | if (!currentFile || !currentFile.name.toLowerCase().endsWith('.torrent')) { |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 52 | setMessage('请上传一个 .torrent 文件'); |
| 53 | setIsLoading(false); |
| 54 | return; |
| 55 | } |
| 56 | |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 57 | const formData = new FormData(); |
22301009 | df48f96 | 2025-06-05 13:40:44 +0800 | [diff] [blame] | 58 | formData.append('file', currentFile); |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 59 | formData.append('title', title); |
| 60 | formData.append('description', description); |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 61 | formData.append('category', category); |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 62 | formData.append('imageUrl', imageUrl); |
22301009 | df48f96 | 2025-06-05 13:40:44 +0800 | [diff] [blame] | 63 | formData.append('tags', tags.join(',')); |
| 64 | formData.append('uploader', user.id); |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 65 | |
| 66 | try { |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 67 | const response = await axios.post('/seeds/upload', formData, { |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 68 | headers: { |
| 69 | 'Content-Type': 'multipart/form-data', |
| 70 | }, |
| 71 | }); |
| 72 | |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 73 | if (response.data.code === 0) { |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 74 | setMessage('种子上传成功'); |
| 75 | } else { |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 76 | setMessage(response.data.msg || '上传失败,请稍后再试'); |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 77 | } |
| 78 | } catch (error) { |
22301009 | df48f96 | 2025-06-05 13:40:44 +0800 | [diff] [blame] | 79 | console.error('[handleSubmit] 上传失败:', error); |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 80 | setMessage('上传失败,发生了错误'); |
| 81 | } finally { |
| 82 | setIsLoading(false); |
| 83 | } |
| 84 | }; |
| 85 | |
| 86 | return ( |
| 87 | <div className="publish-seed-container"> |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 88 | <Header /> |
Krishya | c0f7e9b | 2025-04-22 15:28:28 +0800 | [diff] [blame] | 89 | <div className="pub-card"> |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 90 | {message && <div className="message">{message}</div>} |
| 91 | <form onSubmit={handleSubmit} encType="multipart/form-data"> |
| 92 | <div className="title-tag"> |
| 93 | <label>标题</label> |
| 94 | <input |
| 95 | type="text" |
| 96 | value={title} |
| 97 | onChange={(e) => setTitle(e.target.value)} |
| 98 | required |
| 99 | /> |
| 100 | </div> |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 101 | |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 102 | <div className="discription"> |
| 103 | <label>描述</label> |
| 104 | <textarea |
| 105 | value={description} |
| 106 | onChange={(e) => setDescription(e.target.value)} |
| 107 | required |
| 108 | /> |
| 109 | </div> |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 110 | |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 111 | <div className="title-tag"> |
| 112 | <label>标签 (逗号分隔)</label> |
| 113 | <input |
| 114 | type="text" |
| 115 | value={tags.join(', ')} |
| 116 | onChange={handleTagsChange} |
| 117 | placeholder="例如:科幻, 动作" |
| 118 | required |
| 119 | /> |
| 120 | </div> |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 121 | |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 122 | <div className="pub-categoty"> |
| 123 | <label>分类</label> |
| 124 | <select |
| 125 | value={category} |
| 126 | onChange={(e) => setCategory(e.target.value)} |
| 127 | required |
| 128 | > |
| 129 | <option value="movie">电影</option> |
| 130 | <option value="tv">电视剧</option> |
| 131 | <option value="music">音乐</option> |
| 132 | </select> |
| 133 | </div> |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 134 | |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 135 | <div className="seed-file"> |
| 136 | <label>种子文件</label> |
22301009 | df48f96 | 2025-06-05 13:40:44 +0800 | [diff] [blame] | 137 | <div className="seed-file-label" onClick={handleFileButtonClick}> |
Krishya | f1d0ea8 | 2025-05-03 17:01:58 +0800 | [diff] [blame] | 138 | 点击选择文件 |
22301009 | df48f96 | 2025-06-05 13:40:44 +0800 | [diff] [blame] | 139 | </div> |
| 140 | <input |
| 141 | type="file" |
| 142 | accept=".torrent" |
| 143 | ref={fileInputRef} |
| 144 | onChange={handleFileChange} |
| 145 | style={{ display: 'none' }} |
| 146 | /> |
| 147 | {fileName && <div style={{ marginTop: '5px' }}>{fileName}</div>} |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 148 | </div> |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 149 | |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 150 | <div className="form-group"> |
| 151 | <label>封面图URL</label> |
| 152 | <input |
| 153 | type="url" |
| 154 | value={imageUrl} |
| 155 | onChange={(e) => setImageUrl(e.target.value)} |
| 156 | placeholder="例如:http://example.com/images/cover.jpg" |
| 157 | required |
| 158 | style={{ |
| 159 | padding: '1%', |
| 160 | width: '100%', |
| 161 | borderRadius: '6px', |
| 162 | border: '1px solid #e0c4a1', |
| 163 | backgroundColor: '#fff5f5', |
| 164 | color: '#5F4437', |
| 165 | fontSize: '1rem', |
| 166 | marginBottom: '2%', |
| 167 | }} |
| 168 | /> |
| 169 | </div> |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 170 | |
22301009 | 6401163 | 2025-06-04 21:57:22 +0800 | [diff] [blame] | 171 | <div className="upload-button"> |
| 172 | <button type="submit" disabled={isLoading}> |
| 173 | {isLoading ? '正在上传...' : '上传种子'} |
| 174 | </button> |
| 175 | </div> |
| 176 | </form> |
Krishya | c0f7e9b | 2025-04-22 15:28:28 +0800 | [diff] [blame] | 177 | </div> |
22301009 | 5b28c67 | 2025-04-10 20:12:45 +0800 | [diff] [blame] | 178 | </div> |
| 179 | ); |
| 180 | }; |
| 181 | |
| 182 | export default PublishSeed; |