207 lines
5.1 KiB
TypeScript
207 lines
5.1 KiB
TypeScript
import ListItem from "../../components/ListItem";
|
|
import List from "../../components/List";
|
|
import Bubble from "../../components/Bubble/example";
|
|
import Range from "../../components/Range/example";
|
|
import Menu from "../../components/Menu/example";
|
|
import CityFilter from "../../components/CityFilter/example";
|
|
import SearchBar from "../../components/SearchBar";
|
|
import FilterPopup from "./FilterPopup";
|
|
import "./index.scss";
|
|
import { useEffect } from "react";
|
|
import Taro from "@tarojs/taro";
|
|
import {
|
|
useTennisMatches,
|
|
useTennisLoading,
|
|
useTennisError,
|
|
useTennisLastRefresh,
|
|
useTennisActions,
|
|
} from "../../store/listStore";
|
|
|
|
const ListPage = () => {
|
|
// 从 store 获取数据和方法
|
|
const matches = useTennisMatches();
|
|
const loading = useTennisLoading();
|
|
const error = useTennisError();
|
|
const lastRefreshTime = useTennisLastRefresh();
|
|
const { fetchMatches, refreshMatches, clearError } = useTennisActions();
|
|
|
|
useEffect(() => {
|
|
// 页面加载时获取数据
|
|
fetchMatches();
|
|
}, [fetchMatches]);
|
|
|
|
// 下拉刷新处理函数 - 使用Taro生命周期钩子
|
|
Taro.usePullDownRefresh(() => {
|
|
console.log("触发下拉刷新");
|
|
|
|
// 调用 store 的刷新方法
|
|
refreshMatches()
|
|
.then(() => {
|
|
// 刷新完成后停止下拉刷新动画
|
|
Taro.stopPullDownRefresh();
|
|
|
|
// 显示刷新成功提示
|
|
Taro.showToast({
|
|
title: "刷新成功",
|
|
icon: "success",
|
|
duration: 1500,
|
|
});
|
|
})
|
|
.catch(() => {
|
|
// 刷新失败时也停止动画
|
|
Taro.stopPullDownRefresh();
|
|
|
|
Taro.showToast({
|
|
title: "刷新失败",
|
|
icon: "error",
|
|
duration: 1500,
|
|
});
|
|
});
|
|
});
|
|
|
|
// 错误处理
|
|
useEffect(() => {
|
|
if (error) {
|
|
Taro.showToast({
|
|
title: error,
|
|
icon: "error",
|
|
duration: 2000,
|
|
});
|
|
// 3秒后自动清除错误
|
|
setTimeout(() => {
|
|
clearError();
|
|
}, 3000);
|
|
}
|
|
}, [error, clearError]);
|
|
|
|
// 格式化时间显示
|
|
const formatRefreshTime = (timeString: string | null) => {
|
|
if (!timeString) return "";
|
|
const date = new Date(timeString);
|
|
const now = new Date();
|
|
const diff = now.getTime() - date.getTime();
|
|
const minutes = Math.floor(diff / 60000);
|
|
|
|
if (minutes < 1) return "刚刚";
|
|
if (minutes < 60) return `${minutes}分钟前`;
|
|
const hours = Math.floor(minutes / 60);
|
|
if (hours < 24) return `${hours}小时前`;
|
|
return date.toLocaleDateString();
|
|
};
|
|
|
|
// 加载状态显示
|
|
if (loading && matches.length === 0) {
|
|
return (
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
height: "200px",
|
|
fontSize: "14px",
|
|
color: "#999",
|
|
}}
|
|
>
|
|
<div style={{ marginBottom: "10px" }}>加载中...</div>
|
|
<div style={{ fontSize: "12px", color: "#ccc" }}>
|
|
正在获取网球比赛数据
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// 错误状态显示
|
|
if (error && matches.length === 0) {
|
|
return (
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
height: "200px",
|
|
fontSize: "14px",
|
|
color: "#999",
|
|
}}
|
|
>
|
|
<div style={{ marginBottom: "10px" }}>加载失败</div>
|
|
<div style={{ marginBottom: "15px", fontSize: "12px", color: "#ccc" }}>
|
|
{error}
|
|
</div>
|
|
<button
|
|
onClick={() => fetchMatches()}
|
|
style={{
|
|
padding: "8px 16px",
|
|
fontSize: "12px",
|
|
color: "#fff",
|
|
backgroundColor: "#007aff",
|
|
border: "none",
|
|
borderRadius: "4px",
|
|
}}
|
|
>
|
|
重试
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<SearchBar />
|
|
{/* 综合筛选 */}
|
|
<div>
|
|
<FilterPopup />
|
|
</div>
|
|
{/* 筛选 */}
|
|
<div>
|
|
{/* 全城筛选 */}
|
|
<CityFilter />
|
|
{/* 智能排序 */}
|
|
<Menu />
|
|
</div>
|
|
|
|
|
|
|
|
{/* 列表内容 */}
|
|
<List>
|
|
{matches.map((match, index) => (
|
|
<ListItem key={match.id || index} {...match} />
|
|
))}
|
|
</List>
|
|
|
|
{/* 空状态 */}
|
|
{!loading && matches.length === 0 && (
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
height: "200px",
|
|
fontSize: "14px",
|
|
color: "#999",
|
|
}}
|
|
>
|
|
<div style={{ marginBottom: "10px" }}>暂无比赛数据</div>
|
|
<button
|
|
onClick={() => fetchMatches()}
|
|
style={{
|
|
padding: "8px 16px",
|
|
fontSize: "12px",
|
|
color: "#fff",
|
|
backgroundColor: "#007aff",
|
|
border: "none",
|
|
borderRadius: "4px",
|
|
}}
|
|
>
|
|
重新加载
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ListPage;
|