Files
mini-programs/src/user_pages/follow/index.tsx
2026-02-14 12:59:21 +08:00

350 lines
11 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import { View, Text, ScrollView } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { GeneralNavbar } from '@/components';
import FollowUserCard from '@/components/FollowUserCard';
import { FollowService, FollowUser } from '@/services/followService';
import { withAuth } from '@/components';
import './index.scss';
import CommonDialog from '@/components/CommonDialog'
import { useUserActions, useUserInfo } from "@/store/userStore";
// 标签页类型
type TabType = 'mutual_follow' | 'following' | 'follower' | 'recommend';
// 标签页配置
const TAB_CONFIG = [
{ key: 'mutual_follow' as TabType, label: '互相关注' },
{ key: 'following' as TabType, label: '关注' },
{ key: 'follower' as TabType, label: '粉丝' },
{ key: 'recommend' as TabType, label: '推荐' }
];
const FollowPage: React.FC = () => {
const { fetchUserInfo } = useUserActions();
const userInfo = useUserInfo();
// 获取页面参数,支持指定默认标签页
const instance = Taro.getCurrentInstance();
const default_tab = (instance.router?.params?.tab as TabType) || 'mutual_follow';
// 当前激活的标签页 - 根据设计稿默认显示互相关注
const [active_tab, set_active_tab] = useState<TabType>(default_tab);
// 用户列表数据
const [user_lists, set_user_lists] = useState<Record<TabType, FollowUser[]>>({
mutual_follow: [],
following: [],
follower: [],
recommend: []
});
// 加载状态 - 根据默认标签页设置初始加载状态
const [loading_states, set_loading_states] = useState<Record<TabType, boolean>>(() => ({
mutual_follow: default_tab === 'mutual_follow',
following: default_tab === 'following',
follower: default_tab === 'follower',
recommend: default_tab === 'recommend'
}));
// 分页信息
const [page_info, set_page_info] = useState<Record<TabType, { page: number; total: number; has_more: boolean }>>(() => ({
mutual_follow: { page: 1, total: 0, has_more: true },
following: { page: 1, total: 0, has_more: true },
follower: { page: 1, total: 0, has_more: true },
recommend: { page: 1, total: 0, has_more: true }
}));
// 加载用户列表
const load_user_list = async (tab: TabType, is_refresh: boolean = false) => {
const current_page = is_refresh ? 1 : page_info[tab].page;
const page_size = tab === 'recommend' ? 10 : 20;
// 设置加载状态
set_loading_states(prev => ({ ...prev, [tab]: true }));
try {
const response = await FollowService.get_follow_list(tab, current_page, page_size);
// 调试日志
console.log(`加载${TAB_CONFIG.find(t => t.key === tab)?.label}数据:`, response);
// 更新用户列表
set_user_lists(prev => ({
...prev,
[tab]: is_refresh ? response.list : [...(prev[tab] || []), ...response.list]
}));
// 更新分页信息
set_page_info(prev => ({
...prev,
[tab]: {
page: current_page + 1,
total: response.total,
has_more: response.list.length === page_size && (current_page * page_size) < response.total
}
}));
} catch (error) {
console.warn(`加载${TAB_CONFIG.find(t => t.key === tab)?.label}列表失败:`, error);
Taro.showToast({
title: '加载失败',
icon: 'none'
});
} finally {
set_loading_states(prev => ({ ...prev, [tab]: false }));
}
};
// 处理标签页切换
const handle_tab_change = (tab: TabType) => {
if (tab === active_tab) return;
set_active_tab(tab);
// 每次切换tab都重新加载数据
load_user_list(tab, true);
};
const updateFollowStatus = (user_id: number, is_following: boolean) => {
// 更新用户列表中的关注状态
set_user_lists(prev => {
const new_lists = { ...prev };
// 更新所有标签页中的用户状态
Object.keys(new_lists).forEach(tab_key => {
const tab = tab_key as TabType;
if (new_lists[tab] && Array.isArray(new_lists[tab])) {
new_lists[tab] = new_lists[tab].map(user => {
if (user.id === user_id) {
// 根据操作结果更新状态
let new_status = user.follow_status;
if (is_following) {
if (user.follow_status === 'follower') {
new_status = 'mutual_follow';
} else if (user.follow_status === 'recommend') {
new_status = 'following';
}
} else {
if (user.follow_status === 'mutual_follow') {
new_status = 'follower';
} else if (user.follow_status === 'following') {
new_status = 'recommend';
}
}
return { ...user, follow_status: new_status };
}
return user;
});
}
});
return new_lists;
});
};
// 处理关注状态变化
const handle_follow_change = async (user_id: number, is_following: boolean) => {
try {
if (is_following) {
await FollowService.follow_user(user_id);
updateFollowStatus(user_id, is_following);
fetchUserInfo()
// Taro.showToast({
// title: '关注成功',
// icon: 'success'
// });
} else {
showDeleteConfirm(user_id);
return;
// Taro.showToast({
// title: '取消关注成功',
// icon: 'success'
// });
}
} catch (error) {
console.warn('关注操作失败:', error);
Taro.showToast({
title: '操作失败',
icon: 'none'
});
}
};
// 处理下拉刷新
const handle_refresh = () => {
load_user_list(active_tab, true);
};
// 处理加载更多
const handle_load_more = () => {
if (page_info[active_tab]?.has_more && !loading_states[active_tab]) {
load_user_list(active_tab, false);
}
};
// 处理屏蔽成功
const handle_block_success = (user_id: number) => {
// 从当前列表中移除被屏蔽的用户
set_user_lists(prev => {
const new_lists = { ...prev };
if (new_lists[active_tab] && Array.isArray(new_lists[active_tab])) {
new_lists[active_tab] = new_lists[active_tab].filter(user => user.id !== user_id);
}
return new_lists;
});
// 重新加载当前标签页的列表
load_user_list(active_tab, true);
};
// 初始化加载
useEffect(() => {
try {
load_user_list(default_tab, true);
} catch (error) {
console.warn('初始化加载失败:', error);
Taro.showToast({
title: '初始化失败',
icon: 'none'
});
}
}, [default_tab]);
// 取消关注确认弹窗状态
const [deleteConfirm, setDeleteConfirm] = useState<{
visible: boolean;
userId: number | null;
}>({
visible: false,
userId: null
})
// 取消关注确认弹窗
const showDeleteConfirm = (userId: number | null) => {
setDeleteConfirm({
visible: true,
userId: userId
})
}
// 关闭取消关注确认弹窗
const closeDeleteConfirm = () => {
setDeleteConfirm({
visible: false,
userId: null
})
}
// 确认取消关注
const confirmUnfollow = async () => {
try {
await FollowService.unfollow_user(deleteConfirm.userId!);
closeDeleteConfirm();
updateFollowStatus(deleteConfirm.userId!, false);
fetchUserInfo()
// Taro.showToast({
// title: '取消关注成功',
// icon: 'success'
// });
} catch (error) {
console.warn('取消关注失败:', error);
Taro.showToast({
title: '操作失败',
icon: 'none'
});
}
}
return (
<View className="follow_page">
{/* 自定义导航栏 */}
<GeneralNavbar
title={userInfo.nickname}
titlePosition="left"
showBack={true}
/>
{/* 标签页导航 */}
<View className="tab_navigation">
{TAB_CONFIG.map(tab => (
<View
key={tab.key}
className={`tab_item ${active_tab === tab.key ? 'active' : ''}`}
onClick={() => handle_tab_change(tab.key)}
>
<Text className="tab_text">{tab.label}</Text>
{tab.key === 'recommend' && (
<View className="recommend_icon" onClick={(e) => {
e.stopPropagation();
Taro.showModal({
title: '推荐说明',
content: '我们会向你推荐一些可能感兴趣的球友,帮你更快遇见同样热爱运动的人。推荐基于公开信息与社区互动,仅用于球友推荐,不涉及个人隐私。',
showCancel: false,
confirmText: '确认',
confirmColor: '#000',
})
}}>
{/* 推荐图标 SVG */}
<View className="icon_container">
<View className="star_icon" />
</View>
</View>
)}
</View>
))}
</View>
{/* 用户列表 */}
<ScrollView
className="user_list_container"
scrollY
refresherEnabled
refresherBackground="#FAFAFA"
refresherTriggered={loading_states[active_tab]}
onRefresherRefresh={handle_refresh}
onScrollToLower={handle_load_more}
lowerThreshold={100}
>
{user_lists[active_tab]?.map(user => (
<FollowUserCard
key={user.id}
user={user}
tabKey={active_tab}
onFollowChange={handle_follow_change}
onBlockSuccess={handle_block_success}
/>
)) || []}
{/* 加载状态提示 */}
{loading_states[active_tab] && (user_lists[active_tab]?.length || 0) === 0 && (
<View className="loading_tip">
<Text>...</Text>
</View>
)}
{/* 空状态提示 */}
{!loading_states[active_tab] && (user_lists[active_tab]?.length || 0) === 0 && (
<View className="empty_tip">
<Text>{TAB_CONFIG.find(t => t.key === active_tab)?.label}</Text>
</View>
)}
{/* 加载更多提示 */}
{(user_lists[active_tab]?.length || 0) > 0 && !page_info[active_tab]?.has_more && (
<View className="load_more_tip">
<Text></Text>
</View>
)}
</ScrollView>
{/* 取消关注确认弹窗 */}
<CommonDialog
visible={deleteConfirm.visible}
cancelText="取消"
confirmText="不再关注"
onCancel={closeDeleteConfirm}
onConfirm={confirmUnfollow}
contentTitle="不再关注该球友?"
contentDesc=""
/>
</View>
);
};
export default withAuth(FollowPage);