wht | 2bf8f80 | 2025-06-08 15:52:18 +0800 | [diff] [blame] | 1 | import React, { useState, useEffect } from "react"; |
wht | dc90a03 | 2025-06-08 03:03:52 +0800 | [diff] [blame] | 2 | import HelpIcon from "@mui/icons-material/Help"; |
wht | 3058782 | 2025-06-09 23:33:09 +0800 | [diff] [blame] | 3 | import PeopleIcon from "@mui/icons-material/People"; |
| 4 | import MonetizationOnIcon from "@mui/icons-material/MonetizationOn"; |
| 5 | import AccessTimeIcon from "@mui/icons-material/AccessTime"; |
| 6 | import CheckCircleIcon from "@mui/icons-material/CheckCircle"; |
wht | dc90a03 | 2025-06-08 03:03:52 +0800 | [diff] [blame] | 7 | import { useNavigate } from "react-router-dom"; |
wht | 2bf8f80 | 2025-06-08 15:52:18 +0800 | [diff] [blame] | 8 | import { API_BASE_URL } from "./config"; |
wht | 3058782 | 2025-06-09 23:33:09 +0800 | [diff] [blame] | 9 | import "./BegSeedPage.css"; |
wht | dc90a03 | 2025-06-08 03:03:52 +0800 | [diff] [blame] | 10 | |
| 11 | export default function BegSeedPage() { |
| 12 | const navigate = useNavigate(); |
| 13 | const now = new Date(); |
wht | 2bf8f80 | 2025-06-08 15:52:18 +0800 | [diff] [blame] | 14 | const [begSeedList, setBegSeedList] = useState([]); |
| 15 | const [loading, setLoading] = useState(true); |
| 16 | const [error, setError] = useState(null); |
wht | dc90a03 | 2025-06-08 03:03:52 +0800 | [diff] [blame] | 17 | const [showForm, setShowForm] = useState(false); |
wht | 2bf8f80 | 2025-06-08 15:52:18 +0800 | [diff] [blame] | 18 | const [refreshKey, setRefreshKey] = useState(0); // 用于强制重新渲染 |
wht | dc90a03 | 2025-06-08 03:03:52 +0800 | [diff] [blame] | 19 | const [formData, setFormData] = useState({ |
| 20 | info: "", |
| 21 | reward_magic: "", |
| 22 | deadline: "", |
| 23 | }); |
| 24 | |
wht | 2bf8f80 | 2025-06-08 15:52:18 +0800 | [diff] [blame] | 25 | // 从后端获取求种列表 |
| 26 | const fetchBegSeedList = async () => { |
| 27 | setLoading(true); |
| 28 | try { |
| 29 | const response = await fetch(`${API_BASE_URL}/api/begseed-list`); |
| 30 | if (!response.ok) { |
| 31 | throw new Error(`请求失败,状态码: ${response.status}`); |
| 32 | } |
| 33 | const data = await response.json(); |
| 34 | console.log("获取到的求种列表数据:", data); |
| 35 | |
| 36 | // 格式化数据以匹配前端期望的格式 |
| 37 | const formattedData = data.map(item => ({ |
| 38 | beg_id: item.beg_id || item.begid || item.id, |
| 39 | info: item.info || item.description || item.content, |
| 40 | beg_count: item.beg_count || item.begCount || 1, |
| 41 | reward_magic: item.reward_magic || item.rewardMagic || item.magic, |
| 42 | deadline: item.deadline || item.endtime, |
| 43 | has_match: item.has_match || item.hasMatch || item.completed || 0, |
| 44 | })); |
| 45 | |
| 46 | setBegSeedList(formattedData); |
| 47 | setError(null); |
| 48 | } catch (err) { |
| 49 | console.error('获取求种列表失败:', err); |
| 50 | setError(err.message); |
| 51 | // 如果API调用失败,使用默认数据 |
| 52 | setBegSeedList([ |
| 53 | { |
| 54 | beg_id: "beg001", |
| 55 | info: "求《三体》高清资源", |
| 56 | beg_count: 5, |
| 57 | reward_magic: 100, |
| 58 | deadline: "2025-06-10T23:59:59", |
| 59 | has_match: 0, |
| 60 | }, |
| 61 | { |
| 62 | beg_id: "beg002", |
| 63 | info: "求《灌篮高手》国语配音版", |
| 64 | beg_count: 3, |
| 65 | reward_magic: 50, |
| 66 | deadline: "2024-05-01T23:59:59", |
| 67 | has_match: 1, |
| 68 | }, |
| 69 | { |
| 70 | beg_id: "beg003", |
| 71 | info: "求《黑暗之魂3》PC版种子", |
| 72 | beg_count: 2, |
| 73 | reward_magic: 80, |
| 74 | deadline: "2024-04-01T23:59:59", |
| 75 | has_match: 0, |
| 76 | }, |
| 77 | ]); |
| 78 | } finally { |
| 79 | setLoading(false); |
| 80 | } |
| 81 | }; |
| 82 | |
| 83 | // 组件挂载时获取数据 |
| 84 | useEffect(() => { |
| 85 | fetchBegSeedList(); |
| 86 | }, []); |
| 87 | |
wht | dc90a03 | 2025-06-08 03:03:52 +0800 | [diff] [blame] | 88 | // 表单输入处理 |
| 89 | const handleFormChange = (e) => { |
| 90 | const { name, value } = e.target; |
| 91 | setFormData((prev) => ({ |
| 92 | ...prev, |
| 93 | [name]: value, |
| 94 | })); |
| 95 | }; |
| 96 | |
| 97 | // 提交新求种任务 |
wht | 2bf8f80 | 2025-06-08 15:52:18 +0800 | [diff] [blame] | 98 | const handleSubmit = async (e) => { |
wht | dc90a03 | 2025-06-08 03:03:52 +0800 | [diff] [blame] | 99 | e.preventDefault(); |
wht | 2bf8f80 | 2025-06-08 15:52:18 +0800 | [diff] [blame] | 100 | |
| 101 | // 获取用户ID |
| 102 | const match = document.cookie.match('(^|;)\\s*userId=([^;]+)'); |
| 103 | const userId = match ? match[2] : null; |
| 104 | |
| 105 | if (!userId) { |
| 106 | alert("请先登录后再发布求种任务"); |
| 107 | return; |
| 108 | } |
| 109 | |
| 110 | try { |
| 111 | const response = await fetch(`${API_BASE_URL}/api/create-begseed`, { |
| 112 | method: 'POST', |
| 113 | headers: { |
| 114 | 'Content-Type': 'application/json', |
| 115 | }, |
| 116 | body: JSON.stringify({ |
| 117 | userid: userId, |
| 118 | info: formData.info, |
| 119 | reward_magic: Number(formData.reward_magic), |
| 120 | deadline: formData.deadline, |
| 121 | }), |
| 122 | }); |
| 123 | |
| 124 | if (response.ok) { |
| 125 | // 成功创建,重新获取列表并强制重新渲染 |
| 126 | setLoading(true); // 显示加载状态 |
| 127 | await fetchBegSeedList(); |
| 128 | setShowForm(false); |
| 129 | setFormData({ info: "", reward_magic: "", deadline: "" }); |
| 130 | setRefreshKey(prev => prev + 1); // 强制重新渲染 |
| 131 | alert("发布成功!"); |
| 132 | } else { |
| 133 | const errorData = await response.json(); |
| 134 | alert(`发布失败: ${errorData.message || '未知错误'}`); |
| 135 | } |
| 136 | } catch (err) { |
| 137 | console.error('发布求种任务失败:', err); |
| 138 | // 如果后端调用失败,则使用前端演示逻辑 |
| 139 | // setLoading(true); // 显示加载状态 |
| 140 | // const newBegId = "beg" + Math.floor(Math.random() * 10000); |
| 141 | // setBegSeedList([ |
| 142 | // { |
| 143 | // beg_id: newBegId, |
| 144 | // info: formData.info, |
| 145 | // beg_count: 1, |
| 146 | // reward_magic: Number(formData.reward_magic), |
| 147 | // deadline: formData.deadline, |
| 148 | // has_match: 0, |
| 149 | // }, |
| 150 | // ...begSeedList, |
| 151 | // ]); |
| 152 | // setLoading(false); // 隐藏加载状态 |
| 153 | // setShowForm(false); |
| 154 | // setFormData({ info: "", reward_magic: "", deadline: "" }); |
| 155 | // setRefreshKey(prev => prev + 1); // 强制重新渲染 |
| 156 | // alert("发布成功(前端演示)"); |
| 157 | } |
wht | dc90a03 | 2025-06-08 03:03:52 +0800 | [diff] [blame] | 158 | }; |
| 159 | |
| 160 | return ( |
wht | 3058782 | 2025-06-09 23:33:09 +0800 | [diff] [blame] | 161 | <div className="begseed-container"> |
| 162 | <div className="begseed-content"> |
| 163 | <h1 className="begseed-title"> |
| 164 | <HelpIcon className="begseed-title-icon" style={{ fontSize: 42 }} /> |
| 165 | 求种列表 |
| 166 | </h1> |
| 167 | |
| 168 | {/* 加载状态 */} |
| 169 | {loading && ( |
| 170 | <div className="begseed-loading"> |
| 171 | 正在加载求种列表... |
| 172 | </div> |
| 173 | )} |
| 174 | |
| 175 | {/* 错误状态 */} |
| 176 | {error && ( |
| 177 | <div className="begseed-error"> |
| 178 | 加载失败: {error} (已显示默认数据) |
| 179 | </div> |
| 180 | )} |
| 181 | |
| 182 | <div className="begseed-publish-section"> |
| 183 | <button |
| 184 | onClick={() => setShowForm(true)} |
| 185 | disabled={loading} |
| 186 | className="begseed-publish-btn" |
| 187 | > |
| 188 | 发布求种任务 |
| 189 | </button> |
wht | 2bf8f80 | 2025-06-08 15:52:18 +0800 | [diff] [blame] | 190 | </div> |
wht | 3058782 | 2025-06-09 23:33:09 +0800 | [diff] [blame] | 191 | |
| 192 | {showForm && ( |
| 193 | <div className="begseed-form-container"> |
| 194 | <h3 className="begseed-form-title">发布求种任务</h3> |
| 195 | <form onSubmit={handleSubmit}> |
| 196 | <div className="begseed-form-group"> |
| 197 | <label className="begseed-form-label">求种信息:</label> |
| 198 | <input |
| 199 | type="text" |
| 200 | name="info" |
| 201 | value={formData.info} |
| 202 | onChange={handleFormChange} |
| 203 | required |
| 204 | className="begseed-form-input" |
| 205 | placeholder="请输入您要求种的资源信息" |
| 206 | /> |
| 207 | </div> |
| 208 | <div className="begseed-form-group"> |
| 209 | <label className="begseed-form-label">悬赏魔力值:</label> |
| 210 | <input |
| 211 | type="number" |
| 212 | name="reward_magic" |
| 213 | value={formData.reward_magic} |
| 214 | onChange={handleFormChange} |
| 215 | required |
| 216 | min={1} |
| 217 | className="begseed-form-input" |
| 218 | placeholder="请输入悬赏的魔力值" |
| 219 | /> |
| 220 | </div> |
| 221 | <div className="begseed-form-group"> |
| 222 | <label className="begseed-form-label">截止日期:</label> |
| 223 | <input |
| 224 | type="datetime-local" |
| 225 | name="deadline" |
| 226 | value={formData.deadline} |
| 227 | onChange={handleFormChange} |
| 228 | required |
| 229 | className="begseed-form-input" |
| 230 | /> |
| 231 | </div> |
| 232 | <div className="begseed-form-actions"> |
| 233 | <button type="submit" className="begseed-form-btn begseed-form-btn-primary"> |
| 234 | 提交 |
| 235 | </button> |
| 236 | <button |
| 237 | type="button" |
| 238 | onClick={() => setShowForm(false)} |
| 239 | className="begseed-form-btn begseed-form-btn-secondary" |
| 240 | > |
| 241 | 取消 |
| 242 | </button> |
| 243 | </div> |
| 244 | </form> |
| 245 | </div> |
| 246 | )} |
| 247 | |
| 248 | <div key={refreshKey} className="begseed-list"> |
| 249 | {begSeedList.map((beg) => { |
| 250 | const isExpired = new Date(beg.deadline) < now || beg.has_match === 1; |
| 251 | const isCompleted = beg.has_match === 1; |
| 252 | const isActive = !isExpired && !isCompleted; |
| 253 | |
| 254 | return ( |
| 255 | <div |
| 256 | key={beg.beg_id} |
| 257 | className={`begseed-card ${isExpired ? 'begseed-card-expired' : ''}`} |
| 258 | onClick={() => navigate(`/begseed/${beg.beg_id}`)} |
wht | dc90a03 | 2025-06-08 03:03:52 +0800 | [diff] [blame] | 259 | > |
wht | 3058782 | 2025-06-09 23:33:09 +0800 | [diff] [blame] | 260 | <div className="begseed-card-content"> |
| 261 | <div className="begseed-card-title"> |
| 262 | {beg.info} |
| 263 | </div> |
| 264 | |
| 265 | <div className="begseed-card-info"> |
| 266 | <PeopleIcon className="begseed-card-info-icon" /> |
| 267 | 求种人数:{beg.beg_count} |
| 268 | </div> |
| 269 | |
| 270 | <div className="begseed-card-info"> |
| 271 | <MonetizationOnIcon className="begseed-card-info-icon" /> |
| 272 | 悬赏魔力值:{beg.reward_magic} |
| 273 | </div> |
| 274 | |
| 275 | <div className="begseed-card-info"> |
| 276 | <AccessTimeIcon className="begseed-card-info-icon" /> |
| 277 | 截止时间:{new Date(beg.deadline).toLocaleString()} |
| 278 | </div> |
| 279 | |
| 280 | <div className="begseed-card-info"> |
| 281 | <CheckCircleIcon className="begseed-card-info-icon" /> |
| 282 | <span |
| 283 | className={`begseed-card-status ${ |
| 284 | isCompleted ? 'begseed-status-completed' : |
| 285 | isExpired ? 'begseed-status-expired' : |
| 286 | 'begseed-status-active' |
| 287 | }`} |
| 288 | > |
| 289 | {isCompleted ? "已完成" : isExpired ? "已过期" : "进行中"} |
| 290 | </span> |
| 291 | </div> |
| 292 | </div> |
| 293 | </div> |
| 294 | ); |
| 295 | })} |
wht | dc90a03 | 2025-06-08 03:03:52 +0800 | [diff] [blame] | 296 | </div> |
wht | dc90a03 | 2025-06-08 03:03:52 +0800 | [diff] [blame] | 297 | </div> |
| 298 | </div> |
| 299 | ); |
| 300 | } |