LaoeGaoci | 388f776 | 2025-05-29 22:24:35 +0800 | [diff] [blame^] | 1 | 'use client'; |
LaoeGaoci | a82dfe9 | 2025-04-01 20:17:11 +0800 | [diff] [blame] | 2 | |
LaoeGaoci | 388f776 | 2025-05-29 22:24:35 +0800 | [diff] [blame^] | 3 | import React, { useEffect, useState, useRef } from "react"; |
| 4 | import { Button } from 'primereact/button'; |
| 5 | import { Card } from 'primereact/card'; |
| 6 | import { Image } from 'primereact/image'; |
| 7 | import { Carousel } from 'primereact/carousel'; |
| 8 | // 页面跳转 |
| 9 | import { useRouter } from 'next/navigation'; |
| 10 | // 消息提醒 |
| 11 | import { Toast } from 'primereact/toast'; |
| 12 | // 评分图标 |
| 13 | import { Fire } from '@icon-park/react'; |
| 14 | // 接口传输 |
| 15 | import axios from 'axios'; |
| 16 | |
| 17 | // 样式 |
| 18 | import './main.scss'; |
| 19 | // 模组列表数据 |
| 20 | interface Mod { |
| 21 | resourceId: number; |
| 22 | resourceName: string; |
| 23 | resourcePicture: string; |
| 24 | likes: number; |
| 25 | } |
| 26 | interface ModList { |
| 27 | records: Mod[]; |
| 28 | } |
| 29 | // 地图列表数据 |
| 30 | interface Map { |
| 31 | resourceId: number; |
| 32 | resourceName: string; |
| 33 | resourcePicture: string; |
| 34 | likes: number; |
| 35 | } |
| 36 | interface MapList { |
| 37 | records: Mod[]; |
| 38 | } |
| 39 | // 帖子列表数据 |
| 40 | interface Modpack { |
| 41 | resourceId: number; |
| 42 | resourceName: string; |
| 43 | resourcePicture: string; |
| 44 | likes: number; |
| 45 | } |
| 46 | interface ModpackList { |
| 47 | records: Modpack[]; |
| 48 | } |
| 49 | // 帖子列表数据 |
| 50 | interface Texture { |
| 51 | resourceId: number; |
| 52 | resourceName: string; |
| 53 | resourcePicture: string; |
| 54 | likes: number; |
| 55 | } |
| 56 | interface TextureList { |
| 57 | records: Texture[]; |
| 58 | } |
| 59 | // 热门资源幻灯片数据 |
| 60 | interface HotResource { |
| 61 | resourceId: number; |
| 62 | resourceName: string; |
| 63 | resourcePicture: string; |
| 64 | likes: number; |
| 65 | dowloads: number; |
| 66 | seeds: number; |
| 67 | } |
| 68 | interface HotResourceList { |
| 69 | records: HotResource[]; |
| 70 | } |
| 71 | // 站点统计数据 |
| 72 | interface Stats { |
| 73 | threadCount: number; |
| 74 | downloadCount: number; |
| 75 | authorCount: number; |
| 76 | resourceCount: number; |
| 77 | } |
| 78 | // 悬赏列表 |
| 79 | interface Reward { |
| 80 | rewardId: number; |
| 81 | userId: number; |
| 82 | rewardPicture: string; |
| 83 | rewardName: string; |
| 84 | createdAt: string; |
| 85 | rewardDescription: string; |
| 86 | price: number; |
| 87 | } |
| 88 | interface RewardList { |
| 89 | total: number; // 总记录数 |
| 90 | records: Reward[]; |
| 91 | } |
| 92 | // 主页 |
LaoeGaoci | a82dfe9 | 2025-04-01 20:17:11 +0800 | [diff] [blame] | 93 | export default function Home() { |
LaoeGaoci | 388f776 | 2025-05-29 22:24:35 +0800 | [diff] [blame^] | 94 | // 模组列表 |
| 95 | const [mods, setMods] = useState<Mod[]>([]); |
| 96 | // 悬赏列表 |
| 97 | const [reward, setReweard] = useState<Reward[]>([]); |
| 98 | // 地图列表 |
| 99 | const [maps, setMaps] = useState<Map[]>([]); |
| 100 | // 整合包列表 |
| 101 | const [modpacks, setModpacks] = useState<Modpack[]>([]); |
| 102 | // 材质包列表 |
| 103 | const [textures, setTextures] = useState<Texture[]>([]); |
| 104 | // 热门资源列表 |
| 105 | const [hotResources, setHotResources] = useState<HotResource[]>([]); |
| 106 | // 站点统计信息 |
| 107 | const [stats, setStats] = useState<Stats>({ |
| 108 | threadCount: 0, |
| 109 | downloadCount: 0, |
| 110 | authorCount: 0, |
| 111 | resourceCount: 0 |
| 112 | }); |
| 113 | // 消息提醒 |
| 114 | const toast = useRef<Toast>(null); |
| 115 | const router = useRouter(); |
LaoeGaoci | a82dfe9 | 2025-04-01 20:17:11 +0800 | [diff] [blame] | 116 | |
LaoeGaoci | 388f776 | 2025-05-29 22:24:35 +0800 | [diff] [blame^] | 117 | |
| 118 | // 获取帖子列表 |
| 119 | useEffect(() => { |
| 120 | fetchHotResources(); |
| 121 | fetchRewards(); |
| 122 | fetchstats(); |
| 123 | fetchRecommendMods(); |
| 124 | fetchRecommendMaps(); |
| 125 | fetchRecommendModpacks(); |
| 126 | fetchRecommendTextures(); |
| 127 | }, []); |
| 128 | |
| 129 | // 获取悬赏列表 |
| 130 | const fetchRewards = async () => { |
| 131 | try { |
| 132 | const response = await axios.get<RewardList>(process.env.PUBLIC_URL +`/reward`, { |
| 133 | params: { pageNumber: 1, rows: 5, searchValue: '', option: '' } |
| 134 | }); |
| 135 | console.log('获取悬赏列表:', response.data.records); |
| 136 | setReweard(response.data.records); |
| 137 | } catch (err) { |
| 138 | console.error('获取悬赏失败', err); |
| 139 | toast.current?.show({ severity: 'error', summary: 'error', detail: '获取悬赏失败' }); |
| 140 | } |
| 141 | }; |
| 142 | |
| 143 | // 获取热门资源幻灯片 |
| 144 | const fetchHotResources = async () => { |
| 145 | try { |
| 146 | const response = await axios.get<HotResourceList>(process.env.PUBLIC_URL +`/resource/hot`, { |
| 147 | params: { pageNumber: 1, rows: 3, searchValue: '', type: '' } |
| 148 | }); |
| 149 | console.log('获取热门社区幻灯片:', response.data.records); |
| 150 | setHotResources(response.data.records); |
| 151 | } catch (err) { |
| 152 | console.error('获取Mod失败', err); |
| 153 | toast.current?.show({ severity: 'error', summary: 'error', detail: '获取Mod失败' }); |
| 154 | } |
| 155 | }; |
| 156 | |
| 157 | // 获取全站数据 |
| 158 | const fetchstats = async () => { |
| 159 | try { |
| 160 | const response = await axios.get<Stats>(process.env.PUBLIC_URL +`/total/info`); |
| 161 | console.log('获取全站数据:', response.data); |
| 162 | setStats(response.data); |
| 163 | } catch (err) { |
| 164 | console.error('获取数据失败', err); |
| 165 | toast.current?.show({ severity: 'error', summary: 'error', detail: '获取数据失败' }); |
| 166 | } |
| 167 | }; |
| 168 | |
| 169 | |
| 170 | // 获取推荐模组、地图、整合包、材质包 |
| 171 | const fetchRecommendMods = async () => { |
| 172 | try { |
| 173 | const response = await axios.get<ModList>(process.env.PUBLIC_URL +`/resource/recommend`, { |
| 174 | params: { userId: 22301145, pageNumber: 1, rows: 3, type: '模组' } |
| 175 | }); |
| 176 | console.log('获取模组列表:', response.data.records); |
| 177 | setMods(response.data.records); |
| 178 | } catch (err) { |
| 179 | console.error('获取Mod失败', err); |
| 180 | toast.current?.show({ severity: 'error', summary: 'error', detail: '获取Mod失败' }); |
| 181 | } |
| 182 | }; |
| 183 | const fetchRecommendMaps = async () => { |
| 184 | try { |
| 185 | const response = await axios.get<MapList>(process.env.PUBLIC_URL +`/resource/recommend`, { |
| 186 | params: { userId: 22301145, pageNumber: 1, rows: 3, type: '地图' } |
| 187 | }); |
| 188 | console.log('获取模组列表:', response.data.records); |
| 189 | setMaps(response.data.records); |
| 190 | } catch (err) { |
| 191 | console.error('获取地图失败', err); |
| 192 | toast.current?.show({ severity: 'error', summary: 'error', detail: '获取地图失败' }); |
| 193 | } |
| 194 | }; |
| 195 | const fetchRecommendModpacks = async () => { |
| 196 | try { |
| 197 | const response = await axios.get<ModpackList>(process.env.PUBLIC_URL +`/resource/recommend`, { |
| 198 | params: { userId: 22301145, pageNumber: 1, rows: 3, type: '整合包' } |
| 199 | }); |
| 200 | console.log('获取模组列表:', response.data.records); |
| 201 | setModpacks(response.data.records); |
| 202 | } catch (err) { |
| 203 | console.error('获取整合包失败', err); |
| 204 | toast.current?.show({ severity: 'error', summary: 'error', detail: '获取整合包失败' }); |
| 205 | } |
| 206 | }; |
| 207 | const fetchRecommendTextures = async () => { |
| 208 | try { |
| 209 | const response = await axios.get<TextureList>(process.env.PUBLIC_URL +`/resource/recommend`, { |
| 210 | params: { userId: 22301145, pageNumber: 1, rows: 3, type: '材质包' } |
| 211 | }); |
| 212 | console.log('获取模组列表:', response.data.records); |
| 213 | setTextures(response.data.records); |
| 214 | } catch (err) { |
| 215 | console.error('获取材质包失败', err); |
| 216 | toast.current?.show({ severity: 'error', summary: 'error', detail: '获取材质包失败' }); |
| 217 | } |
| 218 | }; |
| 219 | return ( |
| 220 | <div className="Home"> |
| 221 | {/* 轮播图部分 */} |
| 222 | <div className="main-header"> |
| 223 | <div className="carousel-wrapper"> |
| 224 | <Carousel |
| 225 | value={hotResources} |
| 226 | numVisible={1} |
| 227 | numScroll={1} |
| 228 | showIndicators={false} |
| 229 | showNavigators={true} |
| 230 | className="custom-carousel" |
| 231 | itemTemplate={(hotResource) => ( |
| 232 | <div className="carousel-item" onClick={() => router.push(`/resource/resource-detail/${hotResource.resourceId}`)}> |
| 233 | <Image alt="slide" src={process.env.NEXT_PUBLIC_NGINX_URL + hotResource.resourcePicture} className="carousel-avatar" width="700" height="350" /> |
| 234 | </div> |
| 235 | )} |
| 236 | /> |
LaoeGaoci | a82dfe9 | 2025-04-01 20:17:11 +0800 | [diff] [blame] | 237 | </div> |
LaoeGaoci | 388f776 | 2025-05-29 22:24:35 +0800 | [diff] [blame^] | 238 | <div className="rewards-panel"> |
| 239 | <h2>悬赏排行</h2> |
| 240 | <div className="rewards-list"> |
| 241 | {reward.map((item) => ( |
| 242 | <div key={item.rewardId} className="reward-item" onClick={() => router.push(`/reward/reward-detail/${item.rewardId}`)}> |
| 243 | <span className="reward-title">{item.rewardName}</span> |
| 244 | <span className="reward-price">${item.price}</span> |
| 245 | </div> |
| 246 | ))} |
| 247 | </div> |
| 248 | <Button |
| 249 | label="查看全部悬赏" |
| 250 | className="view-all-button" |
| 251 | onClick={() => router.push('/reward')} |
LaoeGaoci | a82dfe9 | 2025-04-01 20:17:11 +0800 | [diff] [blame] | 252 | /> |
LaoeGaoci | 388f776 | 2025-05-29 22:24:35 +0800 | [diff] [blame^] | 253 | </div> |
| 254 | </div> |
| 255 | {/* 站点统计信息 */} |
| 256 | <div className="site-stats"> |
| 257 | <div className="stat-item"> |
| 258 | <span className="stat-value">{stats.threadCount}</span> |
| 259 | <span className="stat-label">总帖子数</span> |
| 260 | </div> |
| 261 | <div className="stat-item"> |
| 262 | <span className="stat-value">{stats.downloadCount}</span> |
| 263 | <span className="stat-label">下载总数</span> |
| 264 | </div> |
| 265 | <div className="stat-item"> |
| 266 | <span className="stat-value">{stats.authorCount}</span> |
| 267 | <span className="stat-label">人数统计</span> |
| 268 | </div> |
| 269 | <div className="stat-item"> |
| 270 | <span className="stat-value">{stats.resourceCount}</span> |
| 271 | <span className="stat-label">内容总数</span> |
| 272 | </div> |
| 273 | </div> |
| 274 | {/* 推荐模组列表 */} |
| 275 | <div className="recommended-mods"> |
| 276 | <div className="section-header"> |
| 277 | <h1>推荐模组资源</h1> |
| 278 | <Button |
| 279 | label="显示更多" |
| 280 | link |
| 281 | onClick={() => router.push('/resource/recommend/模组')} |
LaoeGaoci | a82dfe9 | 2025-04-01 20:17:11 +0800 | [diff] [blame] | 282 | /> |
LaoeGaoci | 388f776 | 2025-05-29 22:24:35 +0800 | [diff] [blame^] | 283 | </div> |
| 284 | <div className="resource-grid"> |
| 285 | {mods.map((mod) => ( |
| 286 | <Card key={mod.resourceId} className="resource-card" onClick={() => router.push(`/resource/resource-detail/${mod.resourceId}`)}> |
| 287 | <Image |
| 288 | src={process.env.NEXT_PUBLIC_NGINX_URL + mod.resourcePicture} |
| 289 | alt={mod.resourceName} |
| 290 | width="368" |
| 291 | height="200" |
| 292 | /> |
| 293 | <div className="card-content"> |
| 294 | <h3>{mod.resourceName}</h3> |
| 295 | <div className="view-count"> |
| 296 | <Fire theme="outline" size="16" fill="#FF8D1A" /> |
| 297 | <span>{mod.likes}</span> |
| 298 | </div> |
| 299 | </div> |
| 300 | </Card> |
| 301 | ))} |
| 302 | </div> |
| 303 | </div> |
| 304 | {/* 推荐地图列表 */} |
| 305 | <div className="recommended-maps"> |
| 306 | <div className="section-header"> |
| 307 | <h1>推荐地图资源</h1> |
| 308 | <Button |
| 309 | label="显示更多" |
| 310 | link |
| 311 | onClick={() => router.push('/resource/recommend/地图')} |
LaoeGaoci | a82dfe9 | 2025-04-01 20:17:11 +0800 | [diff] [blame] | 312 | /> |
LaoeGaoci | 388f776 | 2025-05-29 22:24:35 +0800 | [diff] [blame^] | 313 | </div> |
| 314 | <div className="resource-grid"> |
| 315 | {maps.map((map) => ( |
| 316 | <Card key={map.resourceId} className="resource-card" onClick={() => router.push(`/resource/resource-detail/${map.resourceId}`)}> |
| 317 | <Image |
| 318 | src={process.env.NEXT_PUBLIC_NGINX_URL + map.resourcePicture} |
| 319 | alt={map.resourceName} |
| 320 | width="368" |
| 321 | height="200" |
| 322 | /> |
| 323 | <div className="card-content"> |
| 324 | <h3>{map.resourceName}</h3> |
| 325 | <div className="view-count"> |
| 326 | <Fire theme="outline" size="16" fill="#FF8D1A" /> |
| 327 | <span>{map.likes}</span> |
| 328 | </div> |
| 329 | </div> |
| 330 | </Card> |
| 331 | ))} |
| 332 | </div> |
| 333 | </div> |
| 334 | {/* 推荐材质包列表 */} |
| 335 | <div className="recommended-textures"> |
| 336 | <div className="section-header"> |
| 337 | <h1>推荐材质包资源</h1> |
| 338 | <Button |
| 339 | label="显示更多" |
| 340 | link |
| 341 | onClick={() => router.push('/resource/recommend/材质包')} |
| 342 | /> |
| 343 | </div> |
| 344 | <div className="resource-grid"> |
| 345 | {textures.map((texture) => ( |
| 346 | <Card key={texture.resourceId} className="resource-card" onClick={() => router.push(`/resource/resource-detail/${texture.resourceId}`)}> |
| 347 | <Image |
| 348 | src={process.env.NEXT_PUBLIC_NGINX_URL + texture.resourcePicture} |
| 349 | alt={texture.resourceName} |
| 350 | width="368" |
| 351 | height="200" |
| 352 | /> |
| 353 | <div className="card-content"> |
| 354 | <h3>{texture.resourceName}</h3> |
| 355 | <div className="view-count"> |
| 356 | <Fire theme="outline" size="16" fill="#FF8D1A" /> |
| 357 | <span>{texture.likes}</span> |
| 358 | </div> |
| 359 | </div> |
| 360 | </Card> |
| 361 | ))} |
| 362 | </div> |
| 363 | </div> |
| 364 | {/* 推荐整合包列表 */} |
| 365 | <div className="recommended-Modpacks"> |
| 366 | <div className="section-header"> |
| 367 | <h1>推荐整合包资源</h1> |
| 368 | <Button |
| 369 | label="显示更多" |
| 370 | link |
| 371 | onClick={() => router.push('/resource/recommend/整合包')} |
| 372 | /> |
| 373 | </div> |
| 374 | <div className="resource-grid"> |
| 375 | {modpacks.map((modpack) => ( |
| 376 | <Card key={modpack.resourceId} className="resource-card" onClick={() => router.push(`/resource/${modpack.resourceId}`)}> |
| 377 | <Image |
| 378 | src={process.env.NEXT_PUBLIC_NGINX_URL + modpack.resourcePicture} |
| 379 | alt={modpack.resourceName} |
| 380 | width="368" |
| 381 | height="200" |
| 382 | /> |
| 383 | <div className="card-content"> |
| 384 | <h3>{modpack.resourceName}</h3> |
| 385 | <div className="view-count"> |
| 386 | <Fire theme="outline" size="16" fill="#FF8D1A" /> |
| 387 | <span>{modpack.likes}</span> |
| 388 | </div> |
| 389 | </div> |
| 390 | </Card> |
| 391 | ))} |
| 392 | </div> |
| 393 | </div> |
LaoeGaoci | a82dfe9 | 2025-04-01 20:17:11 +0800 | [diff] [blame] | 394 | </div> |
| 395 | ); |
| 396 | } |