blob: 88d662932f97ea0f6a3f7f925003c089ff96e8b6 [file] [log] [blame]
'use client';
import React, { useEffect, useState, useRef } from "react";
import { Card } from 'primereact/card';
import { Image } from 'primereact/image';
import { Button } from 'primereact/button';
import { InputText } from 'primereact/inputtext';
// 页面跳转
import { useRouter } from 'next/navigation';
// 消息提醒
import { Toast } from 'primereact/toast';
// 分页
import { Paginator, type PaginatorPageChangeEvent } from 'primereact/paginator';
// 评分图标
import { Fire } from '@icon-park/react';
// 接口传输
import axios from 'axios';
// 标签
import { Tag } from 'primereact/tag';
import { Sidebar } from 'primereact/sidebar';
// 防抖函数
import { debounce } from 'lodash';
// 样式
import './classification.scss';
// 热门资源数据
interface HotResource {
resourceId: number;
resourceName: string;
resourcePicture: string;
resourceSummary: string;
lastUpdateTime: string;
hot: number;
gamePlayList: { gameplayName: string }[];
}
interface HotResourceList {
total: number;
records: HotResource[];
}
// 主页
export default function ClassificationResource() {
// 热门资源列表
const [hotResources, setHotResources] = useState<HotResource[]>([]);
const [totalHotResource, setTotalHotResource] = useState(0);
const [visibleRight, setVisibleRight] = useState<boolean>(false);
// 消息提醒
const toast = useRef<Toast>(null);
const router = useRouter();
// 当前选中的 classify
const [selectedClassify, setSelectedClassify] = useState<string>('模组');
const [selectedGameplay, setSelectedGameplay] = useState<string[]>([]);
const [selectedVersions, setSelectedVersions] = useState<string[]>([]);
const [searchValue, setSearchValue] = useState<string>('');
const debouncedSearch = useRef(
debounce((value: string) => {
setSearchValue(value);
}, 600)
).current;
// 分页
const [first, setFirst] = useState(0);
const [rows, setRows] = useState(5);
const onPageChange = (event: PaginatorPageChangeEvent) => {
setFirst(event.first);
setRows(event.rows);
};
// 获取帖子列表
useEffect(() => {
handleSearch();
}, [first, rows,searchValue]);
const handleSearch = async () => {
try {
const pageNumber = first / rows + 1;
console.log(searchValue + " 当前页: " + pageNumber + "rows: " + rows + "selectedClassify: " + selectedClassify + "selectedGameplay: " + selectedGameplay + "selectedVersions: " + selectedVersions);
const response = await axios.get<HotResourceList>(process.env.PUBLIC_URL + `/resource/search`, {
params: {
userId: 22301145,
pageNumber,
rows,
classify: selectedClassify,
gameplayList: selectedGameplay.join(','),
versionList: selectedVersions.join(','),
searchValue
}
});
setHotResources(response.data.records);
setTotalHotResource(response.data.total);
setVisibleRight(false);
} catch (err) {
console.error('搜索资源失败', err);
toast.current?.show({ severity: 'error', summary: 'error', detail: '搜索资源失败' });
}
};
return (
<div className="HotResource">
<div className="header">
<div className="searchBar">
<i className="pi pi-search" />
<InputText type="search" className="search-helper" placeholder="搜索你感兴趣的帖子" onChange={(e) => { const target = e.target as HTMLInputElement; debouncedSearch(target.value); }} />
</div>
<Button label="查看分类" className="classificationButton" onClick={() => setVisibleRight(true)} />
</div>
{/* 全部社区 */}
<div className="all-resources-list">
{hotResources.map((hotResource) => (
<Card key={hotResource.resourceId} className="all-resources-card" onClick={() => router.push(`/resource/resource-detail/${hotResource.resourceId}`)}>
<Image alt="avatar" src={process.env.NEXT_PUBLIC_NGINX_URL + "hotResource/" + hotResource.resourcePicture} className="resource-avatar" width="250" height="140" />
<div className="resource-header">
<div className="resource-content">
<h3>{hotResource.resourceName}</h3>
<div className="tags">
{hotResource.gamePlayList.map((tag, index) => (
<Tag key={index} value={tag.gameplayName} />
))}
</div>
</div>
<div className="resources-states">
<div className="state-item">
<Fire theme="outline" size="16" fill="#FF8D1A" />
<span>热度: {hotResource.hot}</span>
</div>
<div className="state-item">
<span>最新更新时间: {hotResource.lastUpdateTime}</span>
</div>
</div>
</div>
</Card>
))}
</div>
{totalHotResource > 5 && (<Paginator className="Paginator" first={first} rows={rows} totalRecords={totalHotResource} rowsPerPageOptions={[5, 10]} onPageChange={onPageChange} />)}
<Sidebar className="sidebar" visible={visibleRight} position="right" onHide={() => setVisibleRight(false)}>
<div className="sidebar-content">
<h3>分类</h3>
<div className="filter-section">
{['模组', '地图', '整合包', '材质包'].map((item) => (
<Button key={item} label={item} className={selectedClassify === item ? 'p-button-primary' : 'p-button-text'} onClick={() => setSelectedClassify(item)} />
))}
</div>
<h3>主要玩法</h3>
<div className="filter-section">
{['不限', '科技', '魔法', '建筑', '风景', '竞技', '生存', '冒险', '跑酷', '艺术', '剧情', '社交', '策略', '极限'].map((gameplay) => (
<Button
key={gameplay}
label={gameplay}
className={selectedGameplay.includes(gameplay) ? 'p-button-primary' : 'p-button-text'}
onClick={() => {
if (selectedGameplay.includes(gameplay)) {
setSelectedGameplay(selectedGameplay.filter((g) => g !== gameplay));
} else {
setSelectedGameplay([...selectedGameplay, gameplay]);
}
}}
/>
))}
</div>
<h3>游戏版本</h3>
<div className="filter-section">
{['不限', '1.20.1', '1.20.4', '1.7.3', '1.12.1', '1.19.2', '1.18.3', '1.20.3', '1.19.1', '1.18.6'].map((ver) => (
<Button
key={ver}
label={ver}
className={selectedVersions.includes(ver) ? 'p-button-primary' : 'p-button-text'}
onClick={() => {
if (selectedVersions.includes(ver)) {
setSelectedVersions(selectedVersions.filter((v) => v !== ver));
} else {
setSelectedVersions([...selectedVersions, ver]);
}
}}
/>
))}
</div>
<div className="filter-confirm">
<Button label="确定" icon="pi pi-check" onClick={handleSearch} />
</div>
</div>
</Sidebar>
</div>
);
}