Files
mini-programs/src/pages/list/index.tsx
2025-08-18 00:36:57 +08:00

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;