| import React, { useEffect, useState } from 'react'; |
| import axios from 'axios'; |
| import './InterestGroup.css'; |
| import Header from '../../components/Header'; // 导入 Header 组件 |
| |
| const API_BASE = process.env.REACT_APP_API_BASE; |
| |
| const InterestGroup = () => { |
| const [groups, setGroups] = useState([]); |
| const [loading, setLoading] = useState(true); |
| const [error, setError] = useState(null); |
| const [category, setCategory] = useState(''); |
| const [name, setName] = useState(''); |
| const [page, setPage] = useState(1); |
| const [size, setSize] = useState(10); |
| const [totalPages, setTotalPages] = useState(1); |
| const [sortBy, setSortBy] = useState('member_count'); // 默认按照成员数排序 |
| const [joinStatus, setJoinStatus] = useState({}); // 存储每个小组的加入状态 |
| |
| useEffect(() => { |
| // 请求兴趣小组列表 |
| const fetchGroups = async () => { |
| try { |
| setLoading(true); |
| setError(null); |
| const response = await axios.get(`${API_BASE}/echo/groups`, { |
| params: { |
| category, |
| name, |
| page, |
| size, |
| sort_by: sortBy |
| } |
| }); |
| |
| if (response.data.status === 'success') { |
| setGroups(response.data.items); |
| setTotalPages(response.data.total_pages); // 更新总页数 |
| } else { |
| setError('获取兴趣小组列表失败'); |
| } |
| } catch (err) { |
| setError('请求失败,请稍后再试'); |
| } finally { |
| setLoading(false); |
| } |
| }; |
| |
| fetchGroups(); |
| }, [category, name, page, size, sortBy]); |
| |
| const handleCategoryChange = (e) => { |
| setCategory(e.target.value); |
| setPage(1); // 重置为第一页 |
| }; |
| |
| const handleSearchChange = (e) => { |
| setName(e.target.value); |
| setPage(1); // 重置为第一页 |
| }; |
| |
| const handleSortChange = (e) => { |
| setSortBy(e.target.value); |
| }; |
| |
| const handlePageChange = (newPage) => { |
| if (newPage > 0 && newPage <= totalPages) { |
| setPage(newPage); |
| } |
| }; |
| |
| // 加入兴趣小组 |
| const handleJoinGroup = async (groupId) => { |
| const userId = 1; // 假设用户ID为1,可以根据实际情况获取 |
| |
| try { |
| const response = await axios.post(`${API_BASE}/echo/groups/${groupId}/join`, { |
| user_id: userId |
| }); |
| |
| if (response.data.status === 'success') { |
| setJoinStatus(prevState => ({ |
| ...prevState, |
| [groupId]: '加入成功' |
| })); |
| } else { |
| setJoinStatus(prevState => ({ |
| ...prevState, |
| [groupId]: '加入失败' |
| })); |
| } |
| } catch (error) { |
| setJoinStatus(prevState => ({ |
| ...prevState, |
| [groupId]: '请求失败,请稍后再试' |
| })); |
| } |
| }; |
| |
| const handleSearch = () => { |
| // 触发搜索逻辑,通过修改 name 状态重新请求数据 |
| setPage(1); |
| }; |
| |
| return ( |
| <div className="interest-group-container"> |
| {/* Header 组件放在页面最上方 */} |
| <Header /> |
| <div className="interest-group-card"> |
| {/* <h1>兴趣小组列表</h1> */} |
| {/* 水平排列的筛选、搜索和排序容器 */} |
| <div className="filter-search-sort-container"> |
| {/* 分类筛选 */} |
| <div className="filter"> |
| <label>分类:</label> |
| <select onChange={handleCategoryChange} value={category} style={{ width: '150px' }}> |
| <option value="">全部</option> |
| <option value="影视">影视</option> |
| <option value="游戏">游戏</option> |
| <option value="学习">学习</option> |
| <option value="体育">体育</option> |
| <option value="其他">其他</option> |
| </select> |
| </div> |
| |
| {/* 排序 */} |
| <div className="sort"> |
| <label>排序:</label> |
| <select onChange={handleSortChange} value={sortBy} style={{ width: '150px' }}> |
| <option value="member_count">按成员数排序</option> |
| <option value="name">按名称排序</option> |
| <option value="category">按分类排序</option> |
| </select> |
| </div> |
| |
| {/* 搜索框 */} |
| <div className="search"> |
| <input |
| type="text" |
| value={name} |
| onChange={handleSearchChange} |
| placeholder="输入小组名称搜索" |
| /> |
| <button onClick={handleSearch} style={{ backgroundColor: '#BA929A', color: 'white' , padding: '5px 10px'}}>搜索</button> |
| </div> |
| </div> |
| |
| {/* 加载中提示 */} |
| {loading && <p>加载中...</p>} |
| |
| {/* 错误提示 */} |
| {error && <p className="error">{error}</p>} |
| |
| {/* 小组列表 */} |
| {!loading && !error && ( |
| <div className="group-list"> |
| {groups.map((group) => ( |
| <div className="group-item" key={group.group_id}> |
| <div className="group-content"> |
| <img |
| style={{ width: '40%', height: '40%'}} |
| src={group.cover_image} |
| alt={group.name} |
| className="group-cover" |
| /> |
| <div |
| className="group-info-right" |
| style={{ |
| display: 'flex', |
| flexDirection: 'column', |
| alignItems: 'flex-start', |
| gap: '4px', // 控制元素之间的垂直间距 |
| }} |
| > |
| <h3 style={{ margin: 0 }}>{group.name}</h3> |
| <p style={{ color: '#BA929A', margin: 0 }}>{group.member_count}人加入了小组</p> |
| <button |
| onClick={() => handleJoinGroup(group.group_id)} |
| disabled={joinStatus[group.group_id] === '加入成功'} |
| style={{ |
| background: 'none', |
| color: '#007bff', |
| padding: 0, |
| marginTop: '4px', |
| /*左对齐*/ |
| textAlign: 'left', |
| marginLeft: '0', |
| cursor: joinStatus[group.group_id] === '加入成功' ? 'default' : 'pointer', |
| }} |
| > |
| {joinStatus[group.group_id] === '加入成功' ? '已加入' : '+加入小组'} |
| </button> |
| </div> |
| |
| </div> |
| <div className="group-description"> |
| <p>{group.description}</p> |
| </div> |
| <p>分类:{group.category}</p> |
| |
| </div> |
| ))} |
| </div> |
| )} |
| |
| {/* 分页 */} |
| <div className="pagination"> |
| <button onClick={() => handlePageChange(page - 1)} disabled={page <= 1}> |
| 上一页 |
| </button> |
| <span>第 {page} 页 / 共 {totalPages} 页</span> |
| <button |
| onClick={() => handlePageChange(page + 1)} |
| disabled={page >= totalPages} |
| > |
| 下一页 |
| </button> |
| </div> |
| </div> |
| </div> |
| ); |
| }; |
| |
| export default InterestGroup; |