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