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