blob: 941167b9ba8b7c98103c6ba4c4503d6b95473b16 [file] [log] [blame]
LaoeGaoci388f7762025-05-29 22:24:35 +08001'use client';
LaoeGaocia82dfe92025-04-01 20:17:11 +08002
LaoeGaoci388f7762025-05-29 22:24:35 +08003import React, { useEffect, useState, useRef } from "react";
4import { Button } from 'primereact/button';
5import { Card } from 'primereact/card';
6import { Image } from 'primereact/image';
7import { Carousel } from 'primereact/carousel';
8// 页面跳转
9import { useRouter } from 'next/navigation';
10// 消息提醒
11import { Toast } from 'primereact/toast';
12// 评分图标
13import { Fire } from '@icon-park/react';
14// 接口传输
15import axios from 'axios';
LaoeGaocid0773912025-06-09 00:38:40 +080016import { useLocalStorage } from './hook/useLocalStorage';
LaoeGaoci388f7762025-05-29 22:24:35 +080017// 样式
18import './main.scss';
LaoeGaocid0773912025-06-09 00:38:40 +080019
20interface User {
21 Id: number;
22}
23
LaoeGaoci388f7762025-05-29 22:24:35 +080024// 模组列表数据
25interface Mod {
26 resourceId: number;
27 resourceName: string;
28 resourcePicture: string;
29 likes: number;
30}
31interface ModList {
32 records: Mod[];
33}
34// 地图列表数据
35interface Map {
36 resourceId: number;
37 resourceName: string;
38 resourcePicture: string;
39 likes: number;
40}
41interface MapList {
42 records: Mod[];
43}
44// 帖子列表数据
45interface Modpack {
46 resourceId: number;
47 resourceName: string;
48 resourcePicture: string;
49 likes: number;
50}
51interface ModpackList {
52 records: Modpack[];
53}
54// 帖子列表数据
55interface Texture {
56 resourceId: number;
57 resourceName: string;
58 resourcePicture: string;
59 likes: number;
60}
61interface TextureList {
62 records: Texture[];
63}
64// 热门资源幻灯片数据
65interface HotResource {
66 resourceId: number;
67 resourceName: string;
68 resourcePicture: string;
LaoeGaoci388f7762025-05-29 22:24:35 +080069}
70interface HotResourceList {
71 records: HotResource[];
72}
73// 站点统计数据
74interface Stats {
75 threadCount: number;
76 downloadCount: number;
77 authorCount: number;
78 resourceCount: number;
79}
80// 悬赏列表
81interface Reward {
82 rewardId: number;
83 userId: number;
84 rewardPicture: string;
85 rewardName: string;
86 createdAt: string;
87 rewardDescription: string;
88 price: number;
89}
90interface RewardList {
91 total: number; // 总记录数
92 records: Reward[];
93}
94// 主页
LaoeGaocia82dfe92025-04-01 20:17:11 +080095export default function Home() {
LaoeGaocid0773912025-06-09 00:38:40 +080096 const user = useLocalStorage<User>('user');
97 const userId: number = user?.Id ?? -1;
98
LaoeGaoci388f7762025-05-29 22:24:35 +080099 // 模组列表
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();
LaoeGaocia82dfe92025-04-01 20:17:11 +0800121
LaoeGaoci388f7762025-05-29 22:24:35 +0800122
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 {
LaoeGaocid0773912025-06-09 00:38:40 +0800137 const response = await axios.get<RewardList>(process.env.PUBLIC_URL + `/reward`, {
LaoeGaoci388f7762025-05-29 22:24:35 +0800138 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 {
LaoeGaocid0773912025-06-09 00:38:40 +0800151 const response = await axios.get<HotResourceList>(process.env.PUBLIC_URL + `/resource/hot/slide`);
LaoeGaoci388f7762025-05-29 22:24:35 +0800152 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 {
LaoeGaocid0773912025-06-09 00:38:40 +0800163 const response = await axios.get<Stats>(process.env.PUBLIC_URL + `/total/info`);
LaoeGaoci388f7762025-05-29 22:24:35 +0800164 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 {
LaoeGaocid0773912025-06-09 00:38:40 +0800176 const response = await axios.get<ModList>(process.env.PUBLIC_URL + `/resource/recommend`, {
177 params: { userId, pageNumber: 1, rows: 3, type: '模组' }
LaoeGaoci388f7762025-05-29 22:24:35 +0800178 });
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 {
LaoeGaocid0773912025-06-09 00:38:40 +0800188 const response = await axios.get<MapList>(process.env.PUBLIC_URL + `/resource/recommend`, {
189 params: { userId, pageNumber: 1, rows: 3, type: '地图' }
LaoeGaoci388f7762025-05-29 22:24:35 +0800190 });
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 {
LaoeGaocid0773912025-06-09 00:38:40 +0800200 const response = await axios.get<ModpackList>(process.env.PUBLIC_URL + `/resource/recommend`, {
201 params: { userId, pageNumber: 1, rows: 3, type: '整合包' }
LaoeGaoci388f7762025-05-29 22:24:35 +0800202 });
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 {
LaoeGaocid0773912025-06-09 00:38:40 +0800212 const response = await axios.get<TextureList>(process.env.PUBLIC_URL + `/resource/recommend`, {
213 params: { userId, pageNumber: 1, rows: 3, type: '材质包' }
LaoeGaoci388f7762025-05-29 22:24:35 +0800214 });
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 />
LaoeGaocia82dfe92025-04-01 20:17:11 +0800240 </div>
LaoeGaoci388f7762025-05-29 22:24:35 +0800241 <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')}
LaoeGaocia82dfe92025-04-01 20:17:11 +0800255 />
LaoeGaoci388f7762025-05-29 22:24:35 +0800256 </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/模组')}
LaoeGaocia82dfe92025-04-01 20:17:11 +0800285 />
LaoeGaoci388f7762025-05-29 22:24:35 +0800286 </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/地图')}
LaoeGaocia82dfe92025-04-01 20:17:11 +0800315 />
LaoeGaoci388f7762025-05-29 22:24:35 +0800316 </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>
LaoeGaocia82dfe92025-04-01 20:17:11 +0800397 </div>
398 );
399}