Files
mini-programs/src/user_pages/other/index.tsx
2025-12-04 16:53:43 +08:00

394 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState, useEffect, useCallback } from "react";
import { View, Text, ScrollView, Image } from "@tarojs/components";
import ListContainer from "@/container/listContainer";
import Taro from "@tarojs/taro";
import img from "@/config/images";
import "./index.scss";
// import GuideBar from "@/components/GuideBar";
import {
UserInfoCard,
// GameCard,
GameTabs,
// UserInfo,
GameRecord,
} from "@/components/UserInfo";
import { UserService, UserInfoType } from "@/services/userService";
import * as LoginService from "@/services/loginService";
import { useGlobalState } from "@/store/global";
import { GeneralNavbar } from "@/components";
import { useUserActions } from "@/store/userStore";
const OtherUserPage: React.FC = () => {
const { fetchUserInfo } = useUserActions();
// 获取页面参数
const instance = Taro.getCurrentInstance();
const user_id = instance.router?.params?.userid;
// 获取导航栏高度信息
const { statusNavbarHeightInfo } = useGlobalState() || {};
const { totalHeight = 98 } = statusNavbarHeightInfo || {};
// 用户数据
const [user_info, setUserInfo] = useState<Partial<UserInfoType>>({
id: user_id ? parseInt(user_id) : undefined,
gender: "",
nickname: "",
avatar_url: "",
join_date: "",
stats: {
following_count: 0,
followers_count: 0,
hosted_games_count: 0,
participated_games_count: 0,
},
tags: [],
bio: "",
city: "",
district: "",
occupation: "",
ntrp_level: "",
is_following: false,
ongoing_games: [],
personal_profile: "",
});
// 球局数据
const [game_records, setGameRecords] = useState<GameRecord[]>([]);
// 往期球局
const [ended_game_records, setEndedGameRecords] = useState<GameRecord[]>([]);
// 关注状态
const [is_following, setIsFollowing] = useState(false);
const [loading, set_loading] = useState(true);
// 当前激活的标签页
const [active_tab, setActiveTab] = useState<"hosted" | "participated">(
"hosted"
);
const [collapseProfile, setCollapseProfile] = useState(false);
// 进入页面时检查 user_id只在组件挂载时执行一次
useEffect(() => {
if (!user_id) {
Taro.showToast({
title: "用户不存在",
icon: "none",
duration: 2000,
});
Taro.navigateBack();
return;
}
}, []); // 空依赖数组,确保只在进入时执行一次
// 页面加载时获取用户信息
useEffect(() => {
const load_user_data = async () => {
if (user_id) {
try {
// const user_data = await UserService.get_user_info(user_id);
const res = await LoginService.getUserInfoById(user_id);
const { data: userData } = res;
// setUserInfo({...res.data as UserInfo, avatar: data.avatar_url || require("@/static/userInfo/default_avatar.svg")});
setUserInfo({
id: parseInt(user_id || "") || 0,
nickname: userData.nickname || "",
avatar_url: userData.avatar_url || "",
join_date: userData.subscribe_time
? `${new Date(userData.subscribe_time).getFullYear()}${
new Date(userData.subscribe_time).getMonth() + 1
}月加入`
: "",
stats: {
following_count: userData.stats?.following_count || 0,
followers_count: userData.stats?.followers_count || 0,
hosted_games_count: userData.stats?.hosted_games_count || 0,
participated_games_count:
userData.stats?.participated_games_count || 0,
},
personal_profile: userData.personal_profile || "",
province: userData.province || "",
city: userData.city || "",
district: userData.district || "",
occupation: userData.occupation || "",
ntrp_level: "",
phone: userData.phone || "",
gender: userData.gender || "",
birthday: userData.birthday || "",
});
setIsFollowing(userData.is_following || false);
} catch (error) {
console.error("加载用户数据失败:", error);
Taro.showToast({
title: "加载失败",
icon: "none",
});
}
}
};
load_user_data();
}, [user_id]);
// 分类球局数据(使用 useCallback 包装,避免每次渲染都创建新函数)
const classifyGameRecords = useCallback(
(
game_records: GameRecord[]
): { notEndGames: GameRecord[]; finishedGames: GameRecord[] } => {
const now = new Date().getTime();
return game_records.reduce(
(result, cur) => {
let { end_time } = cur;
end_time = end_time.replace(/\s/, "T");
new Date(end_time).getTime() > now
? result.notEndGames.push(cur)
: result.finishedGames.push(cur);
return result;
},
{
notEndGames: [] as GameRecord[],
finishedGames: [] as GameRecord[],
}
);
},
[]
);
// 加载球局数据(使用 useCallback 包装,避免每次渲染都创建新函数)
const load_game_data = useCallback(async () => {
if (!user_id) return;
try {
set_loading(true);
const games_data = await UserService.get_user_games(user_id, active_tab);
const sorted_games = games_data.sort((a, b) => {
return (
new Date(a.original_start_time.replace(/\s/, "T")).getTime() -
new Date(b.original_start_time.replace(/\s/, "T")).getTime()
);
});
const { notEndGames, finishedGames } = classifyGameRecords(sorted_games);
setGameRecords(notEndGames);
setEndedGameRecords(finishedGames);
} catch (error) {
console.error("加载球局数据失败:", error);
Taro.showToast({
title: "加载失败,请重试",
icon: "error",
duration: 2000,
});
} finally {
set_loading(false);
}
}, [user_id, active_tab, classifyGameRecords]);
useEffect(() => {
load_game_data();
}, [load_game_data]);
// 处理关注/取消关注(使用 useCallback 包装,避免每次渲染都创建新函数)
const handle_follow = useCallback(async () => {
if (!user_info.id) return;
try {
const new_follow_status = await UserService.toggle_follow(
user_info.id,
is_following
);
setIsFollowing(new_follow_status);
fetchUserInfo();
Taro.showToast({
title: new_follow_status ? "关注成功" : "已取消关注",
icon: "success",
duration: 1500,
});
} catch (error) {
console.error("关注操作失败:", error);
Taro.showToast({
title: "操作失败",
icon: "none",
});
}
}, [user_info.id, is_following, fetchUserInfo]);
// 处理发送消息(使用 useCallback 包装,避免每次渲染都创建新函数)
const handle_send_message = useCallback(() => {
if (!user_info.id) return;
Taro.navigateTo({
url: `/mode_user/message/chat/index?user_id=${user_info.id}&nickname=${
user_info.nickname || ""
}`,
});
}, [user_info.id, user_info.nickname]);
// 处理标签页切换(使用 useCallback 包装,避免每次渲染都创建新函数)
const handleOnTab = useCallback((tab) => {
setActiveTab(tab);
}, []);
// 处理滚动事件(使用 useCallback 包装,避免每次渲染都创建新函数)
const handleScroll = useCallback((event: any) => {
const scrollData = event.detail;
setCollapseProfile(scrollData.scrollTop > 1);
}, []);
// 处理球局详情
// const handle_game_detail = (game_id: string) => {
// Taro.navigateTo({
// url: `/game_pages/detail/index?id=${game_id}&from=personal`,
// });
// };
return (
<ScrollView
scrollY
className="other_user_page"
refresherBackground="#FAFAFA"
>
{/* <CustomNavbar>
<View className="navbar_content">
<View className="navbar_back" onClick={() => Taro.navigateBack()}>
<View className="back_icon" />
</View>
<Text className="navbar_title"></Text>
<View className="navbar_action">
</View>
</View>
</CustomNavbar> */}
{/* 顶部导航栏 */}
<GeneralNavbar
title=""
showBack={true}
showAvatar={false}
onBack={() => {
Taro.navigateBack();
}}
/>
{/* 主要内容 */}
<View
className="other_main_content"
style={{ paddingTop: `${totalHeight}px` }}
>
{/* 用户信息区域 */}
<View className="user_info_section">
<UserInfoCard
editable={false}
user_info={user_info}
is_current_user={false}
is_following={is_following}
collapseProfile={collapseProfile}
setMarginBottom={false}
on_follow={handle_follow}
on_message={handle_send_message}
onTab={handleOnTab}
/>
</View>
{/* 球局类型标签页 */}
<GameTabs
active_tab={active_tab}
on_tab_change={setActiveTab}
is_current_user={false}
/>
{/* 球局列表 */}
<View className="game_list_section">
{/* <View className="date_header">
<Text className="date_text">5月29日</Text>
<Text className="separator">/</Text>
<Text className="weekday_text">星期六</Text>
</View> */}
{/* 球局列表 */}
{/* <View className="game_list_section"> */}
<ScrollView scrollY refresherBackground="#FAFAFA">
<ListContainer
data={game_records}
recommendList={[]}
loading={loading}
error={null}
isShowNoData={game_records.length === 0}
errorImg="ICON_LIST_EMPTY_CARD"
emptyText="暂无球局信息"
loadMoreMatches={() => {}}
collapse={true}
style={{
paddingBottom: ended_game_records.length ? 0 : "90px",
overflow: "hidden",
}}
listLoadErrorWrapperHeight="fit-content"
listLoadErrorWidth="320px"
listLoadErrorHeight="152px"
listLoadErrorScale="1.2"
defaultShowNum={3}
/>
</ScrollView>
{/* </View> */}
{/* 球局卡片 */}
{/* <View className="game_cards">
{game_records.map((game) => (
<GameCard
key={game.id}
game={game}
on_click={handle_game_detail}
/>
))}
</View> */}
</View>
{/* 往期球局 */}
{ended_game_records.length ? (
<>
<View className="ended_game_text"></View>
<View className="game_list_section">
{/* <View className="date_header">
<Text className="date_text">5月29日</Text>
<Text className="separator">/</Text>
<Text className="weekday_text">星期六</Text>
</View> */}
{/* 球局列表 */}
{/* <View className="game_list_section"> */}
<ScrollView scrollY refresherBackground="#FAFAFA">
<ListContainer
data={ended_game_records}
recommendList={[]}
loading={loading}
error={null}
isShowNoData={ended_game_records.length === 0}
errorImg="ICON_LIST_EMPTY_CARD"
emptyText="暂无球局信息"
loadMoreMatches={() => {}}
collapse={true}
style={{ paddingBottom: "90px", overflow: "hidden" }}
listLoadErrorWrapperHeight="fit-content"
listLoadErrorWidth="320px"
listLoadErrorHeight="152px"
listLoadErrorScale="1.2"
defaultShowNum={3}
/>
</ScrollView>
{/* </View> */}
{/* 球局卡片 */}
{/* <View className="game_cards">
{game_records.map((game) => (
<GameCard
key={game.id}
game={game}
on_click={handle_game_detail}
/>
))}
</View> */}
</View>
</>
) : null}
</View>
{/* <GuideBar currentPage="personal" /> */}
</ScrollView>
);
};
export default OtherUserPage;