列表
This commit is contained in:
@@ -5,8 +5,6 @@ import "qweather-icons/font/qweather-icons.css";
|
|||||||
import { useDictionaryStore } from "./store/dictionaryStore";
|
import { useDictionaryStore } from "./store/dictionaryStore";
|
||||||
import { useGlobalStore } from "./store/global";
|
import { useGlobalStore } from "./store/global";
|
||||||
|
|
||||||
// import { getNavbarHeight } from "@/utils/getNavbarHeight";
|
|
||||||
|
|
||||||
interface AppProps {
|
interface AppProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
.customerNavbar {
|
.customerNavbar {
|
||||||
position: sticky;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
left: 0;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
background-color: #ffffff;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
@@ -9,12 +9,12 @@ interface IProps {
|
|||||||
const CustomNavbar = (props: IProps) => {
|
const CustomNavbar = (props: IProps) => {
|
||||||
const { children } = props;
|
const { children } = props;
|
||||||
const { statusNavbarHeightInfo } = useGlobalState();
|
const { statusNavbarHeightInfo } = useGlobalState();
|
||||||
const { statusBarHeight, navbarHeight } = statusNavbarHeightInfo;
|
const { statusBarHeight, navBarHeight } = statusNavbarHeightInfo;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
className={styles.customerNavbar}
|
className={styles.customerNavbar}
|
||||||
style={{ height: `${navbarHeight}px`, paddingTop: `${statusBarHeight}px`, }}
|
style={{ height: `${navBarHeight}px`, paddingTop: `${statusBarHeight}px`, }}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import Taro from "@tarojs/taro";
|
|||||||
|
|
||||||
const ListHeader = () => {
|
const ListHeader = () => {
|
||||||
const { statusNavbarHeightInfo } = useGlobalState();
|
const { statusNavbarHeightInfo } = useGlobalState();
|
||||||
const { statusBarHeight, navbarHeight, totalHeight } = statusNavbarHeightInfo;
|
const { statusBarHeight, navBarHeight, totalHeight } = statusNavbarHeightInfo;
|
||||||
const handleBack = () => {
|
const handleBack = () => {
|
||||||
Taro.navigateBack();
|
Taro.navigateBack();
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ const ListHeader = () => {
|
|||||||
<View
|
<View
|
||||||
className={styles.container}
|
className={styles.container}
|
||||||
style={{
|
style={{
|
||||||
height: `${navbarHeight}px`,
|
height: `${navBarHeight}px`,
|
||||||
paddingTop: `${statusBarHeight}px`,
|
paddingTop: `${statusBarHeight}px`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
--nutui-searchbar-content-border-radius: 44px;
|
--nutui-searchbar-content-border-radius: 44px;
|
||||||
--nutui-searchbar-input-text-color: #000000;
|
--nutui-searchbar-input-text-color: #000000;
|
||||||
--nutui-searchbar-input-padding: 0 0 0 10px;
|
--nutui-searchbar-input-padding: 0 0 0 10px;
|
||||||
--nutui-searchbar-padding: 10px 0 0 0;
|
--nutui-searchbar-padding: 10px 0 10px 0;
|
||||||
background-color: unset;
|
background-color: unset;
|
||||||
|
|
||||||
:global(.nut-searchbar-content) {
|
:global(.nut-searchbar-content) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.inputCustomerNavbarContainer {
|
.inputCustomerNavbarContainer {
|
||||||
padding-left: 17px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.navContent {
|
.navContent {
|
||||||
|
padding-left: 17px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { View, Image } from "@tarojs/components";
|
import { View, Image } from "@tarojs/components";
|
||||||
import img from "@/config/images";
|
import img from "@/config/images";
|
||||||
import { getCurrentLocation } from "@/utils/locationUtils";
|
|
||||||
import "./index.scss";
|
import "./index.scss";
|
||||||
import { useEffect } from "react";
|
|
||||||
import { useGlobalState } from "@/store/global";
|
import { useGlobalState } from "@/store/global";
|
||||||
import { useListState } from "@/store/listStore";
|
import { useListState } from "@/store/listStore";
|
||||||
import CustomNavbar from "@/components/CustomNavbar";
|
import CustomNavbar from "@/components/CustomNavbar";
|
||||||
@@ -15,25 +13,9 @@ interface IProps {
|
|||||||
|
|
||||||
const ListHeader = (props: IProps) => {
|
const ListHeader = (props: IProps) => {
|
||||||
const { icon } = props;
|
const { icon } = props;
|
||||||
const { updateState, statusNavbarHeightInfo } = useGlobalState();
|
const { statusNavbarHeightInfo } = useGlobalState();
|
||||||
const { searchValue } = useListState();
|
const { searchValue } = useListState();
|
||||||
const { statusBarHeight, navbarHeight } = statusNavbarHeightInfo;
|
const { statusBarHeight, navBarHeight } = statusNavbarHeightInfo;
|
||||||
|
|
||||||
// 获取位置信息
|
|
||||||
// const getCurrentLocal = () => {
|
|
||||||
// updateState({
|
|
||||||
// getLocationLoading: true,
|
|
||||||
// });
|
|
||||||
// getCurrentLocation().then((res) => {
|
|
||||||
// updateState({
|
|
||||||
// getLocationLoading: false,
|
|
||||||
// location: res || {},
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
// useEffect(() => {
|
|
||||||
// getCurrentLocal();
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
const handleInputClick = () => {
|
const handleInputClick = () => {
|
||||||
Taro.navigateTo({
|
Taro.navigateTo({
|
||||||
@@ -46,7 +28,7 @@ const ListHeader = (props: IProps) => {
|
|||||||
<View
|
<View
|
||||||
className="inputCustomerNavbarContainer"
|
className="inputCustomerNavbarContainer"
|
||||||
style={{
|
style={{
|
||||||
height: `${navbarHeight}px`,
|
height: `${navBarHeight}px`,
|
||||||
paddingTop: `${statusBarHeight}px`,
|
paddingTop: `${statusBarHeight}px`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
padding-bottom: 34px;
|
padding-bottom: 34px;
|
||||||
|
min-height: 100vh;
|
||||||
|
|
||||||
.recommendTextWrapper {
|
.recommendTextWrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.listNavContainer {
|
.listNavContainer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
.listNavLine {
|
.listNavLine {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
height: 25px;
|
height: 25px;
|
||||||
@@ -51,6 +54,7 @@
|
|||||||
.inputCustomerNavbarContainer {
|
.inputCustomerNavbarContainer {
|
||||||
padding-left: 17px;
|
padding-left: 17px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
@@ -99,6 +103,7 @@
|
|||||||
|
|
||||||
.inputCustomerNavbarShowInput {
|
.inputCustomerNavbarShowInput {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
@@ -124,20 +129,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 第一个元素样式 */
|
/* 第一个元素样式 */
|
||||||
.firstElement {
|
.firstElement {}
|
||||||
}
|
|
||||||
|
|
||||||
/* 第二个元素样式 */
|
/* 第二个元素样式 */
|
||||||
.secondElement {
|
.secondElement {
|
||||||
/* 初始状态:透明且稍微偏移 */
|
/* 初始状态:透明且稍微偏移 */
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(5px);
|
transform: translateY(-5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 隐藏状态 */
|
/* 隐藏状态 */
|
||||||
.hidden {
|
.hidden {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(5px);
|
transform: translateY(-5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 可见状态 */
|
/* 可见状态 */
|
||||||
|
|||||||
@@ -7,14 +7,13 @@ import CustomNavbar from "@/components/CustomNavbar";
|
|||||||
import { Input } from "@nutui/nutui-react-taro";
|
import { Input } from "@nutui/nutui-react-taro";
|
||||||
import Taro from "@tarojs/taro";
|
import Taro from "@tarojs/taro";
|
||||||
import "./index.scss";
|
import "./index.scss";
|
||||||
import { useMemo } from "react";
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
config?: {
|
config?: {
|
||||||
showInput: boolean;
|
showInput: boolean;
|
||||||
inputLeftIcon: string;
|
inputLeftIcon?: string;
|
||||||
iconPath?: string;
|
iconPath?: string;
|
||||||
leftIconClick: () => void;
|
leftIconClick?: () => void;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,10 +28,12 @@ const ListHeader = (props: IProps) => {
|
|||||||
getLocationLoading,
|
getLocationLoading,
|
||||||
statusNavbarHeightInfo,
|
statusNavbarHeightInfo,
|
||||||
} = useGlobalState();
|
} = useGlobalState();
|
||||||
const { gamesNum, searchValue, isShowInputCustomerNavBar } = useListState();
|
const { gamesNum, searchValue } = useListState();
|
||||||
const { navbarHeight } = statusNavbarHeightInfo;
|
const { navBarHeight } = statusNavbarHeightInfo;
|
||||||
|
|
||||||
const { city,district } = useUserInfo()
|
const userInfo = useUserInfo()
|
||||||
|
const city = (userInfo as any)?.city || ''
|
||||||
|
const district = (userInfo as any)?.district || ''
|
||||||
|
|
||||||
console.log("useUserInfo",city,district )
|
console.log("useUserInfo",city,district )
|
||||||
|
|
||||||
@@ -67,23 +68,17 @@ const ListHeader = (props: IProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const navbarStyle = {
|
const navbarStyle = {
|
||||||
height: `${navbarHeight}px`,
|
height: `${navBarHeight}px`,
|
||||||
paddingTop: `4px`,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const showInputNavBar = useMemo(() => {
|
|
||||||
return isShowInputCustomerNavBar || showInput;
|
|
||||||
}, [isShowInputCustomerNavBar, showInput]);
|
|
||||||
|
|
||||||
console.log("===showInputNavBar",showInputNavBar)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomNavbar>
|
<CustomNavbar>
|
||||||
<View className="listNavWrapper">
|
<View className="listNavWrapper">
|
||||||
{/* 首页logo 导航*/}
|
{/* 首页logo 导航*/}
|
||||||
<View
|
<View
|
||||||
className={`listNavContainer toggleElement firstElement hidden ${(!showInputNavBar && !showInput) && "visible"
|
className={`listNavContainer toggleElement firstElement hidden
|
||||||
}`}
|
${!showInput ? "visible" : ""}`}
|
||||||
style={navbarStyle}
|
style={navbarStyle}
|
||||||
>
|
>
|
||||||
<View className="listNavContentWrapper">
|
<View className="listNavContentWrapper">
|
||||||
@@ -110,8 +105,8 @@ const ListHeader = (props: IProps) => {
|
|||||||
</View>
|
</View>
|
||||||
{/* 搜索导航 */}
|
{/* 搜索导航 */}
|
||||||
<View
|
<View
|
||||||
className={`inputCustomerNavbarContainer toggleElement secondElement hidden ${(showInputNavBar || showInput) && "visible"
|
className={`inputCustomerNavbarContainer toggleElement secondElement hidden ${showInput && "visible"
|
||||||
} ${showInput && "inputCustomerNavbarShowInput"}`}
|
} ${showInput ? "inputCustomerNavbarShowInput" : ""}`}
|
||||||
style={navbarStyle}
|
style={navbarStyle}
|
||||||
>
|
>
|
||||||
<View className="navContent">
|
<View className="navContent">
|
||||||
@@ -128,8 +123,9 @@ const ListHeader = (props: IProps) => {
|
|||||||
src={img.ICON_LIST_SEARCH_SEARCH}
|
src={img.ICON_LIST_SEARCH_SEARCH}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
placeholder="搜索上海的球局和场地"
|
placeholder="搜索上球局和场地"
|
||||||
clearable={false}
|
// clearable={false}
|
||||||
|
disabled
|
||||||
value={searchValue}
|
value={searchValue}
|
||||||
onClick={handleInputClick}
|
onClick={handleInputClick}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -22,28 +22,32 @@ const ListPage = () => {
|
|||||||
|
|
||||||
const { totalHeight } = statusNavbarHeightInfo || {};
|
const { totalHeight } = statusNavbarHeightInfo || {};
|
||||||
const {
|
const {
|
||||||
isShowFilterPopup,
|
listPageState,
|
||||||
error,
|
|
||||||
matches,
|
|
||||||
recommendList,
|
|
||||||
loading,
|
loading,
|
||||||
getMatchesData,
|
error,
|
||||||
updateState,
|
searchValue,
|
||||||
filterCount,
|
|
||||||
updateFilterOptions, // 更新筛选条件
|
|
||||||
filterOptions,
|
|
||||||
clearFilterOptions,
|
|
||||||
distanceData,
|
distanceData,
|
||||||
quickFilterData,
|
quickFilterData,
|
||||||
distanceQuickFilter,
|
getMatchesData,
|
||||||
isScrollTop,
|
updateState,
|
||||||
searchValue,
|
updateListPageState,
|
||||||
isShowInputCustomerNavBar,
|
updateFilterOptions, // 更新筛选条件
|
||||||
|
clearFilterOptions,
|
||||||
initialFilterSearch,
|
initialFilterSearch,
|
||||||
loadMoreMatches,
|
loadMoreMatches,
|
||||||
fetchGetGamesCount
|
fetchGetGamesCount
|
||||||
} = store;
|
} = store;
|
||||||
|
|
||||||
|
const {
|
||||||
|
isShowFilterPopup,
|
||||||
|
data: matches,
|
||||||
|
recommendList,
|
||||||
|
filterCount,
|
||||||
|
filterOptions,
|
||||||
|
distanceQuickFilter,
|
||||||
|
isShowInputCustomerNavBar,
|
||||||
|
} = listPageState || {};
|
||||||
|
|
||||||
// 防抖的滚动处理函数
|
// 防抖的滚动处理函数
|
||||||
const handleScroll = useCallback((res) => {
|
const handleScroll = useCallback((res) => {
|
||||||
const currentScrollTop = res?.scrollTop || 0;
|
const currentScrollTop = res?.scrollTop || 0;
|
||||||
@@ -62,9 +66,13 @@ const ListPage = () => {
|
|||||||
scrollTimeoutRef.current = setTimeout(() => {
|
scrollTimeoutRef.current = setTimeout(() => {
|
||||||
// 只有在状态真正需要改变时才更新
|
// 只有在状态真正需要改变时才更新
|
||||||
if (shouldShowInputNav && !isShowInputCustomerNavBar) {
|
if (shouldShowInputNav && !isShowInputCustomerNavBar) {
|
||||||
updateState({ isShowInputCustomerNavBar: true });
|
updateListPageState({
|
||||||
|
isShowInputCustomerNavBar: true
|
||||||
|
});
|
||||||
} else if (shouldHideInputNav && isShowInputCustomerNavBar) {
|
} else if (shouldHideInputNav && isShowInputCustomerNavBar) {
|
||||||
updateState({ isShowInputCustomerNavBar: false });
|
updateListPageState({
|
||||||
|
isShowInputCustomerNavBar: false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
lastScrollTopRef.current = currentScrollTop;
|
lastScrollTopRef.current = currentScrollTop;
|
||||||
@@ -173,7 +181,9 @@ const ListPage = () => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const toggleShowPopup = () => {
|
const toggleShowPopup = () => {
|
||||||
updateState({ isShowFilterPopup: !isShowFilterPopup });
|
updateListPageState({
|
||||||
|
isShowFilterPopup: !isShowFilterPopup
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -188,7 +198,7 @@ const ListPage = () => {
|
|||||||
|
|
||||||
// 距离筛选
|
// 距离筛选
|
||||||
const handleDistanceOrQuickChange = (name, value) => {
|
const handleDistanceOrQuickChange = (name, value) => {
|
||||||
updateState({
|
updateListPageState({
|
||||||
distanceQuickFilter: {
|
distanceQuickFilter: {
|
||||||
...distanceQuickFilter,
|
...distanceQuickFilter,
|
||||||
[name]: value,
|
[name]: value,
|
||||||
@@ -203,24 +213,15 @@ const ListPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View ref={scrollContextRef}>
|
<>
|
||||||
{/* 自定义导航 */}
|
{/* 自定义导航 */}
|
||||||
<CustomerNavBar />
|
<CustomerNavBar
|
||||||
|
config={{
|
||||||
{/* <ShareCardCanvas /> */}
|
showInput: isShowInputCustomerNavBar,
|
||||||
<View className={styles.listPage}>
|
}}
|
||||||
<View
|
|
||||||
className={`${styles.listTopSearchWrapper} ${isScrollTop ? styles.isScroll : ""
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<SearchBar
|
|
||||||
handleFilterIcon={toggleShowPopup}
|
|
||||||
isSelect={filterCount > 0}
|
|
||||||
filterCount={filterCount}
|
|
||||||
onChange={handleSearchChange}
|
|
||||||
value={searchValue}
|
|
||||||
onInputClick={handleSearchClick}
|
|
||||||
/>
|
/>
|
||||||
|
<View ref={scrollContextRef}>
|
||||||
|
{/* <ShareCardCanvas /> */}
|
||||||
{/* 综合筛选 */}
|
{/* 综合筛选 */}
|
||||||
{isShowFilterPopup && (
|
{isShowFilterPopup && (
|
||||||
<View>
|
<View>
|
||||||
@@ -237,6 +238,20 @@ const ListPage = () => {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
{/* 列表内容 */}
|
||||||
|
<View className={styles.listPage} style={{ paddingTop: totalHeight }}>
|
||||||
|
<View
|
||||||
|
className={`${styles.listTopSearchWrapper}`}
|
||||||
|
>
|
||||||
|
<SearchBar
|
||||||
|
handleFilterIcon={toggleShowPopup}
|
||||||
|
isSelect={filterCount > 0}
|
||||||
|
filterCount={filterCount}
|
||||||
|
onChange={handleSearchChange}
|
||||||
|
value={searchValue}
|
||||||
|
onInputClick={handleSearchClick}
|
||||||
|
/>
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
{/* 筛选 */}
|
{/* 筛选 */}
|
||||||
<View className={styles.listTopFilterWrapper}
|
<View className={styles.listTopFilterWrapper}
|
||||||
@@ -264,8 +279,9 @@ const ListPage = () => {
|
|||||||
loadMoreMatches={loadMoreMatches}
|
loadMoreMatches={loadMoreMatches}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<GuideBar currentPage="list" />
|
|
||||||
</View>
|
</View>
|
||||||
|
<GuideBar currentPage="list" />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// import CustomerNavbarBack from "@/components/CustomerNavbarBack";
|
|
||||||
import { View, Image, Text } from "@tarojs/components";
|
import { View, Image, Text } from "@tarojs/components";
|
||||||
import { Input } from "@nutui/nutui-react-taro";
|
import { Input } from "@nutui/nutui-react-taro";
|
||||||
import { useEffect, useMemo, useRef } from "react";
|
import { useEffect, useMemo, useRef } from "react";
|
||||||
@@ -12,13 +11,17 @@ const ListSearch = () => {
|
|||||||
const {
|
const {
|
||||||
searchValue,
|
searchValue,
|
||||||
updateState,
|
updateState,
|
||||||
|
updateSearchPageState,
|
||||||
getSearchHistory,
|
getSearchHistory,
|
||||||
searchHistory = [],
|
|
||||||
clearHistory,
|
clearHistory,
|
||||||
searchSuggestion,
|
searchSuggestion,
|
||||||
|
} = useListState() || {};
|
||||||
|
|
||||||
|
const {
|
||||||
|
searchHistory = [],
|
||||||
suggestionList,
|
suggestionList,
|
||||||
isShowSuggestion,
|
isShowSuggestion,
|
||||||
} = useListState() || {};
|
} = useListState()?.searchPageState || {};
|
||||||
const ref = useRef<any>(null);
|
const ref = useRef<any>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -53,7 +56,7 @@ const ListSearch = () => {
|
|||||||
if (value) {
|
if (value) {
|
||||||
searchSuggestion(value);
|
searchSuggestion(value);
|
||||||
} else {
|
} else {
|
||||||
updateState({
|
updateSearchPageState({
|
||||||
isShowSuggestion: false,
|
isShowSuggestion: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -63,7 +66,10 @@ const ListSearch = () => {
|
|||||||
* @description 点击清空输入内容
|
* @description 点击清空输入内容
|
||||||
*/
|
*/
|
||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
updateState({ searchValue: "", isShowSuggestion: false });
|
updateState({ searchValue: "" });
|
||||||
|
updateSearchPageState({
|
||||||
|
isShowSuggestion: false
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,8 +92,8 @@ const ListSearch = () => {
|
|||||||
* @description 点击联想词
|
* @description 点击联想词
|
||||||
*/
|
*/
|
||||||
const handleSuggestionSearch = (val: string) => {
|
const handleSuggestionSearch = (val: string) => {
|
||||||
updateState({
|
updateState({ searchValue: val });
|
||||||
searchValue: val,
|
updateSearchPageState({
|
||||||
isShowSuggestion: false,
|
isShowSuggestion: false,
|
||||||
});
|
});
|
||||||
handleSearch(val);
|
handleSearch(val);
|
||||||
|
|||||||
@@ -13,22 +13,27 @@ import Taro from "@tarojs/taro";
|
|||||||
|
|
||||||
const SearchResult = () => {
|
const SearchResult = () => {
|
||||||
const {
|
const {
|
||||||
isShowFilterPopup,
|
searchPageState,
|
||||||
error,
|
|
||||||
distanceQuickFilter,
|
|
||||||
searchResultData,
|
|
||||||
recommendList,
|
|
||||||
loading,
|
loading,
|
||||||
updateState,
|
error,
|
||||||
filterCount,
|
|
||||||
updateFilterOptions, // 更新筛选条件
|
|
||||||
filterOptions,
|
|
||||||
clearFilterOptions,
|
|
||||||
distanceData,
|
distanceData,
|
||||||
quickFilterData,
|
quickFilterData,
|
||||||
|
updateState,
|
||||||
|
updateSearchPageState,
|
||||||
|
updateFilterOptions, // 更新筛选条件
|
||||||
|
clearFilterOptions,
|
||||||
loadMoreMatches,
|
loadMoreMatches,
|
||||||
getMatchesData
|
getMatchesData
|
||||||
} = useListStore() || {};
|
} = useListStore() || {};
|
||||||
|
|
||||||
|
const {
|
||||||
|
isShowFilterPopup,
|
||||||
|
distanceQuickFilter,
|
||||||
|
searchResultData,
|
||||||
|
recommendList,
|
||||||
|
filterCount,
|
||||||
|
filterOptions,
|
||||||
|
} = searchPageState || {};
|
||||||
const { statusNavbarHeightInfo } = useGlobalState() || {};
|
const { statusNavbarHeightInfo } = useGlobalState() || {};
|
||||||
const { totalHeight } = statusNavbarHeightInfo || {};
|
const { totalHeight } = statusNavbarHeightInfo || {};
|
||||||
const isSelect = filterCount > 0;
|
const isSelect = filterCount > 0;
|
||||||
@@ -36,11 +41,17 @@ const SearchResult = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const pages = Taro.getCurrentPages()
|
const pages = Taro.getCurrentPages()
|
||||||
const currentPage = pages?.[pages.length - 1];
|
const currentPage = pages?.[pages.length - 1];
|
||||||
updateState({currentPage, isSearchResult: true})
|
updateState({
|
||||||
|
currentPage,
|
||||||
|
isSearchResult: true
|
||||||
|
})
|
||||||
getMatchesData();
|
getMatchesData();
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
updateState({currentPage: '', isSearchResult: false})
|
updateState({
|
||||||
|
currentPage: '',
|
||||||
|
isSearchResult: false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -53,12 +64,23 @@ const SearchResult = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const toggleShowPopup = () => {
|
const toggleShowPopup = () => {
|
||||||
updateState({ isShowFilterPopup: !isShowFilterPopup });
|
updateSearchPageState({
|
||||||
|
isShowFilterPopup: !isShowFilterPopup
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 综合筛选确认
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const handleFilterConfirm = () => {
|
||||||
|
toggleShowPopup();
|
||||||
|
getMatchesData();
|
||||||
|
}
|
||||||
|
|
||||||
// 距离筛选
|
// 距离筛选
|
||||||
const handleDistanceOrQuickChange = (name, value) => {
|
const handleDistanceOrQuickChange = (name, value) => {
|
||||||
updateState({
|
updateSearchPageState({
|
||||||
distanceQuickFilter: {
|
distanceQuickFilter: {
|
||||||
...distanceQuickFilter,
|
...distanceQuickFilter,
|
||||||
[name]: value,
|
[name]: value,
|
||||||
@@ -75,7 +97,7 @@ const SearchResult = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="searchResultPage">
|
<>
|
||||||
{/* 自定义导航 */}
|
{/* 自定义导航 */}
|
||||||
<CustomerNavBar
|
<CustomerNavBar
|
||||||
config={{
|
config={{
|
||||||
@@ -84,6 +106,7 @@ const SearchResult = () => {
|
|||||||
leftIconClick: handleLeftIconClick
|
leftIconClick: handleLeftIconClick
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<View className="searchResultPage" style={{ paddingTop: totalHeight }}>
|
||||||
{/* 筛选 */}
|
{/* 筛选 */}
|
||||||
<View
|
<View
|
||||||
className="searchResultFilterWrapper"
|
className="searchResultFilterWrapper"
|
||||||
@@ -113,20 +136,18 @@ const SearchResult = () => {
|
|||||||
/>
|
/>
|
||||||
{isSelect && <Text className="filterCount">{filterCount}</Text>}
|
{isSelect && <Text className="filterCount">{filterCount}</Text>}
|
||||||
</View>
|
</View>
|
||||||
{/* 筛选弹框 */}
|
|
||||||
{/* 综合筛选 */}
|
{/* 综合筛选 */}
|
||||||
{isShowFilterPopup && (
|
{isShowFilterPopup && (
|
||||||
<View>
|
<View>
|
||||||
<FilterPopup
|
<FilterPopup
|
||||||
loading={loading}
|
loading={loading}
|
||||||
onCancel={toggleShowPopup}
|
onCancel={toggleShowPopup}
|
||||||
onConfirm={toggleShowPopup}
|
onConfirm={handleFilterConfirm}
|
||||||
onChange={handleUpdateFilterOptions}
|
onChange={handleUpdateFilterOptions}
|
||||||
filterOptions={filterOptions}
|
filterOptions={filterOptions}
|
||||||
onClear={clearFilterOptions}
|
onClear={clearFilterOptions}
|
||||||
visible={isShowFilterPopup}
|
visible={isShowFilterPopup}
|
||||||
onClose={toggleShowPopup}
|
onClose={toggleShowPopup}
|
||||||
// statusNavbarHeigh={0}
|
|
||||||
statusNavbarHeigh={statusNavbarHeightInfo?.totalHeight}
|
statusNavbarHeigh={statusNavbarHeightInfo?.totalHeight}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
@@ -143,6 +164,7 @@ const SearchResult = () => {
|
|||||||
loadMoreMatches={loadMoreMatches}
|
loadMoreMatches={loadMoreMatches}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ interface GlobalState {
|
|||||||
getLocationText: string;
|
getLocationText: string;
|
||||||
statusNavbarHeightInfo: {
|
statusNavbarHeightInfo: {
|
||||||
statusBarHeight: number;
|
statusBarHeight: number;
|
||||||
navbarHeight: number;
|
navBarHeight: number;
|
||||||
totalHeight: number;
|
totalHeight: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -33,18 +33,18 @@ export const useGlobalStore = create<GlobalStore>()((set, get) => ({
|
|||||||
// 状态栏和导航栏高度信息
|
// 状态栏和导航栏高度信息
|
||||||
statusNavbarHeightInfo: {
|
statusNavbarHeightInfo: {
|
||||||
statusBarHeight: 0,
|
statusBarHeight: 0,
|
||||||
navbarHeight: 0,
|
navBarHeight: 0,
|
||||||
totalHeight: 0,
|
totalHeight: 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取导航栏高度信息
|
// 获取导航栏高度信息
|
||||||
getNavbarHeightInfo: () => {
|
getNavbarHeightInfo: () => {
|
||||||
const { statusBarHeight, navbarHeight } = getNavbarHeight();
|
const { statusBarHeight, navBarHeight } = getNavbarHeight();
|
||||||
set({
|
set({
|
||||||
statusNavbarHeightInfo: {
|
statusNavbarHeightInfo: {
|
||||||
statusBarHeight,
|
statusBarHeight,
|
||||||
navbarHeight,
|
navBarHeight,
|
||||||
totalHeight: statusBarHeight + navbarHeight,
|
totalHeight: statusBarHeight + navBarHeight,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -40,32 +40,73 @@ const defaultPageOption = {
|
|||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 创建 store
|
// 页面状态默认值
|
||||||
const now = new Date();
|
const pageStateDefaultValue = {
|
||||||
export const useListStore = create<TennisStore>()((set, get) => ({
|
// 列表数据
|
||||||
currentPage: "",
|
data: [],
|
||||||
isSearchResult: false,
|
|
||||||
searchResultData: [],
|
|
||||||
dateRange: [now, new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000)], // 日期区间
|
|
||||||
// 初始状态
|
|
||||||
matches: [],
|
|
||||||
// 推荐列表
|
// 推荐列表
|
||||||
recommendList: [],
|
recommendList: [],
|
||||||
location: {
|
|
||||||
latitude: 0,
|
|
||||||
longitude: 0,
|
|
||||||
}, // 位置
|
|
||||||
// 是否加载中
|
|
||||||
loading: true,
|
|
||||||
error: null,
|
|
||||||
// 搜索的value
|
|
||||||
searchValue: "",
|
|
||||||
// 是否展示综合筛选弹窗
|
// 是否展示综合筛选弹窗
|
||||||
isShowFilterPopup: false,
|
isShowFilterPopup: false,
|
||||||
// 综合筛选项
|
// 综合筛选项
|
||||||
filterOptions: defaultFilterOptions,
|
filterOptions: defaultFilterOptions,
|
||||||
|
// 距离筛选和快捷筛选
|
||||||
|
distanceQuickFilter: defaultDistanceQuickFilter,
|
||||||
// 综合筛选 选择的筛选数量
|
// 综合筛选 选择的筛选数量
|
||||||
filterCount: 0,
|
filterCount: 0,
|
||||||
|
// 分页
|
||||||
|
pageOption: defaultPageOption,
|
||||||
|
// 球局数量
|
||||||
|
gamesNum: 0,
|
||||||
|
// 是否还有更多数据
|
||||||
|
isHasMoreData: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列表页状态
|
||||||
|
const listPageStateDefaultValue = {
|
||||||
|
...pageStateDefaultValue,
|
||||||
|
// 列表页是否显示搜索框自定义导航
|
||||||
|
isShowInputCustomerNavBar: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索页状态
|
||||||
|
const searchPageStateDefaultValue = {
|
||||||
|
...pageStateDefaultValue,
|
||||||
|
// 搜索结果数据
|
||||||
|
searchResultData: [],
|
||||||
|
// 联想词
|
||||||
|
suggestionList: [],
|
||||||
|
// 是否显示联想词
|
||||||
|
isShowSuggestion: false,
|
||||||
|
// 搜索历史数据
|
||||||
|
searchHistory: [],
|
||||||
|
// 搜索历史数据默认 Top 15
|
||||||
|
searchHistoryParams: {
|
||||||
|
page: 1,
|
||||||
|
pageSize: 15,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// const now = new Date();
|
||||||
|
|
||||||
|
// 公共属性
|
||||||
|
const commonStateDefaultValue = {
|
||||||
|
// 是否是搜索结果页
|
||||||
|
isSearchResult: false,
|
||||||
|
// 是否加载中
|
||||||
|
loading: true,
|
||||||
|
// 错误信息
|
||||||
|
error: null,
|
||||||
|
// 位置
|
||||||
|
location: {
|
||||||
|
latitude: 0,
|
||||||
|
longitude: 0,
|
||||||
|
},
|
||||||
|
// 搜索的value
|
||||||
|
searchValue: "",
|
||||||
|
// 日期区间
|
||||||
|
// dateRange: [now, new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000)],
|
||||||
|
|
||||||
// 距离筛选数据
|
// 距离筛选数据
|
||||||
distanceData: [
|
distanceData: [
|
||||||
{ id: 0, label: "全城", value: "" },
|
{ id: 0, label: "全城", value: "" },
|
||||||
@@ -79,8 +120,6 @@ export const useListStore = create<TennisStore>()((set, get) => ({
|
|||||||
{ label: "距离更近", value: "1" },
|
{ label: "距离更近", value: "1" },
|
||||||
{ label: "时间更近", value: "2" },
|
{ label: "时间更近", value: "2" },
|
||||||
],
|
],
|
||||||
// 距离筛选和快捷筛选
|
|
||||||
distanceQuickFilter: defaultDistanceQuickFilter,
|
|
||||||
|
|
||||||
// 气泡日期范围
|
// 气泡日期范围
|
||||||
dateRangeOptions: [
|
dateRangeOptions: [
|
||||||
@@ -97,42 +136,28 @@ export const useListStore = create<TennisStore>()((set, get) => ({
|
|||||||
{ id: 5, label: "晚上 18:00-22:00", value: "18:00-22:00" },
|
{ id: 5, label: "晚上 18:00-22:00", value: "18:00-22:00" },
|
||||||
{ id: 6, label: "夜间 22:00-24:00", value: "22:00-24:00" },
|
{ id: 6, label: "夜间 22:00-24:00", value: "22:00-24:00" },
|
||||||
],
|
],
|
||||||
// 球局数量
|
}
|
||||||
|
|
||||||
|
// 创建 store
|
||||||
|
export const useListStore = create<TennisStore>()((set, get) => ({
|
||||||
|
currentPage: "",
|
||||||
|
// 列表页
|
||||||
|
listPageState: listPageStateDefaultValue,
|
||||||
|
// 搜索及搜索结果页
|
||||||
|
searchPageState: searchPageStateDefaultValue,
|
||||||
|
|
||||||
|
...commonStateDefaultValue,
|
||||||
gamesNum: 0,
|
gamesNum: 0,
|
||||||
// 是否还有更多数据
|
|
||||||
isHasMoreData: true,
|
|
||||||
// 页面滚动距离顶部距离 是否大于0
|
|
||||||
isScrollTop: false,
|
|
||||||
// 搜索历史数据
|
|
||||||
searchHistory: [],
|
|
||||||
// 搜索历史数据默认 Top 15
|
|
||||||
searchHistoryParams: {
|
|
||||||
page: 1,
|
|
||||||
pageSize: 15,
|
|
||||||
},
|
|
||||||
// 联想词
|
|
||||||
suggestionList: [],
|
|
||||||
// 是否显示联想词
|
|
||||||
isShowSuggestion: false,
|
|
||||||
// 列表页是否显示搜索框自定义导航
|
|
||||||
isShowInputCustomerNavBar: false,
|
|
||||||
// 结果页是否显示搜索框自定义导航
|
|
||||||
isShowResultInputCustomerNavBar: false,
|
|
||||||
// 打开距离筛选框
|
|
||||||
isOpenDistancePopup: false,
|
|
||||||
// 打开快捷筛选框
|
|
||||||
isOpenQuickFilterPopup: false,
|
|
||||||
// 分页
|
|
||||||
pageOption: defaultPageOption,
|
|
||||||
|
|
||||||
// 组装搜索数据
|
// 组装搜索数据
|
||||||
getSearchParams: () => {
|
getSearchParams: () => {
|
||||||
const state = get();
|
const state = get();
|
||||||
const filterOptions = state?.filterOptions || {};
|
const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState;
|
||||||
const distanceQuickFilter = state?.distanceQuickFilter || {};
|
const filterOptions = currentPageState?.filterOptions || {};
|
||||||
|
const distanceQuickFilter = currentPageState?.distanceQuickFilter || {};
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
pageOption: state.pageOption,
|
pageOption: currentPageState?.pageOption,
|
||||||
seachOption: {
|
seachOption: {
|
||||||
...filterOptions,
|
...filterOptions,
|
||||||
title: state.searchValue,
|
title: state.searchValue,
|
||||||
@@ -147,30 +172,45 @@ export const useListStore = create<TennisStore>()((set, get) => ({
|
|||||||
return params;
|
return params;
|
||||||
},
|
},
|
||||||
|
|
||||||
// 设置搜索的列表结果
|
// 设置列表结果
|
||||||
setListData: (payload: IPayload & { isAppend?: boolean }) => {
|
setListData: (payload: IPayload & { isAppend?: boolean }) => {
|
||||||
const { isSearchResult } = get();
|
const state = get();
|
||||||
const { error, data, loading, count, isAppend = false } = payload;
|
const { error, data, loading, count, isAppend = false } = payload;
|
||||||
const saveKey = isSearchResult ? "searchResultData" : "matches";
|
|
||||||
const isHasMoreData = count > 0;
|
const isHasMoreData = count > 0;
|
||||||
|
|
||||||
if (isAppend) {
|
if (state.isSearchResult) {
|
||||||
// 追加数据到现有数组
|
// 更新搜索页状态
|
||||||
const currentData = get()[saveKey] || [];
|
const currentData = state.searchPageState?.searchResultData || [];
|
||||||
const newData = [...currentData, ...(data || [])];
|
const newData = isAppend ? [...currentData, ...(data || [])] : (data || []);
|
||||||
const saveData = { error, loading, count, isHasMoreData, [saveKey]: newData };
|
set({
|
||||||
set({...saveData});
|
searchPageState: {
|
||||||
|
...state.searchPageState,
|
||||||
|
searchResultData: newData,
|
||||||
|
isHasMoreData,
|
||||||
|
},
|
||||||
|
error,
|
||||||
|
loading,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// 替换整个数组
|
// 更新列表页状态
|
||||||
const saveData = { error, loading, count, isHasMoreData, [saveKey]: data };
|
const currentData = state.listPageState?.data || [];
|
||||||
set({...saveData});
|
const newData = isAppend ? [...currentData, ...(data || [])] : (data || []);
|
||||||
|
set({
|
||||||
|
listPageState: {
|
||||||
|
...state.listPageState,
|
||||||
|
data: newData,
|
||||||
|
isHasMoreData,
|
||||||
|
},
|
||||||
|
error,
|
||||||
|
loading,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取列表数据(常规搜索)
|
// 获取列表数据(常规搜索)
|
||||||
fetchMatches: async (params, isFirstLoad = false, isAppend = false) => {
|
fetchMatches: async (params, isFirstLoad = false, isAppend = false) => {
|
||||||
set({ loading: true, error: null });
|
set({ loading: true, error: null });
|
||||||
const { getSearchParams, setListData, distanceQuickFilter } = get();
|
const { getSearchParams, setListData } = get();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const searchParams = getSearchParams() || {};
|
const searchParams = getSearchParams() || {};
|
||||||
@@ -179,6 +219,12 @@ export const useListStore = create<TennisStore>()((set, get) => ({
|
|||||||
...params,
|
...params,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取当前页面的距离筛选
|
||||||
|
const state = get();
|
||||||
|
const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState;
|
||||||
|
console.log("===当前页面状态:", state.isSearchResult, currentPageState);
|
||||||
|
const distanceQuickFilter = currentPageState?.distanceQuickFilter || {};
|
||||||
|
|
||||||
// 是否选择了智能排序
|
// 是否选择了智能排序
|
||||||
const isIntegrate = distanceQuickFilter?.quick === "0";
|
const isIntegrate = distanceQuickFilter?.quick === "0";
|
||||||
let fetchFn = getGamesList;
|
let fetchFn = getGamesList;
|
||||||
@@ -193,7 +239,7 @@ export const useListStore = create<TennisStore>()((set, get) => ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("===fetchMatches 获取列表数据参数:", reqParams);
|
console.log("===获取列表数据参数:", reqParams);
|
||||||
const resData = (await fetchFn(reqParams)) || {};
|
const resData = (await fetchFn(reqParams)) || {};
|
||||||
const { data = {}, code } = resData;
|
const { data = {}, code } = resData;
|
||||||
if (code !== 0) {
|
if (code !== 0) {
|
||||||
@@ -245,11 +291,15 @@ export const useListStore = create<TennisStore>()((set, get) => ({
|
|||||||
// 获取历史搜索数据
|
// 获取历史搜索数据
|
||||||
getSearchHistory: async () => {
|
getSearchHistory: async () => {
|
||||||
try {
|
try {
|
||||||
const params = get()?.searchHistoryParams || {};
|
const state = get();
|
||||||
|
const params = state.searchPageState?.searchHistoryParams || {};
|
||||||
const resData = (await getSearchHistory(params)) || {};
|
const resData = (await getSearchHistory(params)) || {};
|
||||||
const searchHistory = resData?.data?.records || [];
|
const searchHistory = resData?.data?.records || [];
|
||||||
set({
|
set({
|
||||||
|
searchPageState: {
|
||||||
|
...state.searchPageState,
|
||||||
searchHistory,
|
searchHistory,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} catch (error) { }
|
} catch (error) { }
|
||||||
},
|
},
|
||||||
@@ -257,11 +307,15 @@ export const useListStore = create<TennisStore>()((set, get) => ({
|
|||||||
// 清空历史记录
|
// 清空历史记录
|
||||||
clearHistory: async () => {
|
clearHistory: async () => {
|
||||||
try {
|
try {
|
||||||
|
const state = get();
|
||||||
const params = {};
|
const params = {};
|
||||||
const resData = (await clearHistory(params)) || {};
|
const resData = (await clearHistory(params)) || {};
|
||||||
if (resData?.code === 0) {
|
if (resData?.code === 0) {
|
||||||
set({
|
set({
|
||||||
|
searchPageState: {
|
||||||
|
...state.searchPageState,
|
||||||
searchHistory: [],
|
searchHistory: [],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) { }
|
} catch (error) { }
|
||||||
@@ -270,17 +324,25 @@ export const useListStore = create<TennisStore>()((set, get) => ({
|
|||||||
// 获取联想
|
// 获取联想
|
||||||
searchSuggestion: async (val: string) => {
|
searchSuggestion: async (val: string) => {
|
||||||
try {
|
try {
|
||||||
|
const state = get();
|
||||||
const resData = (await searchSuggestion({ val, limit: 10 })) || {};
|
const resData = (await searchSuggestion({ val, limit: 10 })) || {};
|
||||||
const recommendations = resData?.data?.recommendations || [];
|
const recommendations = resData?.data?.recommendations || [];
|
||||||
const total = resData?.data?.total;
|
const total = resData?.data?.total;
|
||||||
set({
|
set({
|
||||||
|
searchPageState: {
|
||||||
|
...state.searchPageState,
|
||||||
suggestionList: recommendations,
|
suggestionList: recommendations,
|
||||||
isShowSuggestion: total > 0,
|
isShowSuggestion: total > 0,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
const state = get();
|
||||||
set({
|
set({
|
||||||
|
searchPageState: {
|
||||||
|
...state.searchPageState,
|
||||||
suggestionList: [],
|
suggestionList: [],
|
||||||
isShowSuggestion: true,
|
isShowSuggestion: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -292,67 +354,154 @@ export const useListStore = create<TennisStore>()((set, get) => ({
|
|||||||
|
|
||||||
// 更新综合筛选项
|
// 更新综合筛选项
|
||||||
updateFilterOptions: (payload: Record<string, any>) => {
|
updateFilterOptions: (payload: Record<string, any>) => {
|
||||||
const { filterOptions: preFilterOptions, fetchGetGamesCount } = get() || {};
|
const state = get();
|
||||||
const filterOptions = { ...preFilterOptions, ...payload };
|
const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState;
|
||||||
|
const filterOptions = { ...currentPageState?.filterOptions, ...payload };
|
||||||
const filterCount = Object.values(filterOptions).filter(Boolean).length;
|
const filterCount = Object.values(filterOptions).filter(Boolean).length;
|
||||||
console.log("===更新综合筛选项", filterOptions, filterCount);
|
|
||||||
|
if (state.isSearchResult) {
|
||||||
set({
|
set({
|
||||||
|
searchPageState: {
|
||||||
|
...state.searchPageState,
|
||||||
filterOptions,
|
filterOptions,
|
||||||
filterCount,
|
filterCount,
|
||||||
pageOption: defaultPageOption,
|
pageOption: defaultPageOption,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
set({
|
||||||
|
listPageState: {
|
||||||
|
...state.listPageState,
|
||||||
|
filterOptions,
|
||||||
|
filterCount,
|
||||||
|
pageOption: defaultPageOption,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
// 获取球局数量
|
// 获取球局数量
|
||||||
fetchGetGamesCount();
|
state.fetchGetGamesCount();
|
||||||
},
|
},
|
||||||
|
|
||||||
// 清空综合筛选选项
|
// 清空综合筛选选项
|
||||||
clearFilterOptions: () => {
|
clearFilterOptions: () => {
|
||||||
const { getMatchesData, fetchGetGamesCount } = get() || {};
|
const state = get();
|
||||||
|
const { getMatchesData, fetchGetGamesCount } = state;
|
||||||
|
|
||||||
|
if (state.isSearchResult) {
|
||||||
set({
|
set({
|
||||||
|
searchPageState: {
|
||||||
|
...state.searchPageState,
|
||||||
filterOptions: defaultFilterOptions,
|
filterOptions: defaultFilterOptions,
|
||||||
filterCount: 0,
|
filterCount: 0,
|
||||||
pageOption: defaultPageOption,
|
pageOption: defaultPageOption,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
set({
|
||||||
|
listPageState: {
|
||||||
|
...state.listPageState,
|
||||||
|
filterOptions: defaultFilterOptions,
|
||||||
|
filterCount: 0,
|
||||||
|
pageOption: defaultPageOption,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
getMatchesData();
|
getMatchesData();
|
||||||
fetchGetGamesCount();
|
fetchGetGamesCount();
|
||||||
},
|
},
|
||||||
|
|
||||||
// 加载更多数据
|
// 加载更多数据
|
||||||
loadMoreMatches: () => {
|
loadMoreMatches: () => {
|
||||||
const { pageOption, fetchMatches, isHasMoreData } = get() || {};
|
const state = get();
|
||||||
|
const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState;
|
||||||
|
const { pageOption, isHasMoreData } = currentPageState || {};
|
||||||
|
|
||||||
if (!isHasMoreData) {
|
if (!isHasMoreData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
set({
|
|
||||||
pageOption: {
|
const newPageOption = {
|
||||||
page: pageOption?.page + 1,
|
page: (pageOption?.page || 1) + 1,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (state.isSearchResult) {
|
||||||
|
set({
|
||||||
|
searchPageState: {
|
||||||
|
...state.searchPageState,
|
||||||
|
pageOption: newPageOption,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
set({
|
||||||
|
listPageState: {
|
||||||
|
...state.listPageState,
|
||||||
|
pageOption: newPageOption,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
// 加载更多时追加数据到现有数组
|
// 加载更多时追加数据到现有数组
|
||||||
fetchMatches({}, false, true);
|
state.fetchMatches({}, false, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
// 初始化搜索条件 重新搜索
|
// 初始化搜索条件 重新搜索
|
||||||
initialFilterSearch: async () => {
|
initialFilterSearch: async () => {
|
||||||
const { getMatchesData, fetchGetGamesCount } = get();
|
const state = get();
|
||||||
|
const { getMatchesData, fetchGetGamesCount } = state;
|
||||||
|
|
||||||
|
if (state.isSearchResult) {
|
||||||
set({
|
set({
|
||||||
|
searchPageState: {
|
||||||
|
...state.searchPageState,
|
||||||
distanceQuickFilter: defaultDistanceQuickFilter,
|
distanceQuickFilter: defaultDistanceQuickFilter,
|
||||||
filterOptions: defaultFilterOptions,
|
filterOptions: defaultFilterOptions,
|
||||||
pageOption: defaultPageOption,
|
pageOption: defaultPageOption,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
set({
|
||||||
|
listPageState: {
|
||||||
|
...state.listPageState,
|
||||||
|
distanceQuickFilter: defaultDistanceQuickFilter,
|
||||||
|
filterOptions: defaultFilterOptions,
|
||||||
|
pageOption: defaultPageOption,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
fetchGetGamesCount();
|
fetchGetGamesCount();
|
||||||
return await getMatchesData();
|
return await getMatchesData();
|
||||||
},
|
},
|
||||||
|
|
||||||
// 更新store数据
|
// 更新store数据
|
||||||
updateState: (payload: Record<string, any>) => {
|
updateState: (payload: Record<string, any>) => {
|
||||||
const state = get();
|
|
||||||
console.log("Store: 更新数据:", state);
|
|
||||||
set({
|
set({
|
||||||
...(payload || {}),
|
...(payload || {}),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 更新列表页状态中的特定字段
|
||||||
|
updateListPageState: (payload: Record<string, any>) => {
|
||||||
|
const state = get();
|
||||||
|
set({
|
||||||
|
listPageState: {
|
||||||
|
...state.listPageState,
|
||||||
|
...payload,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log("===更新列表页状态:", state);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新搜索页状态中的特定字段
|
||||||
|
updateSearchPageState: (payload: Record<string, any>) => {
|
||||||
|
const state = get();
|
||||||
|
set({
|
||||||
|
searchPageState: {
|
||||||
|
...state.searchPageState,
|
||||||
|
...payload,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log("===更新搜索页状态:", state);
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// 导出便捷的 hooks
|
// 导出便捷的 hooks
|
||||||
|
|||||||
@@ -1,13 +1,39 @@
|
|||||||
import Taro from "@tarojs/taro";
|
import Taro from "@tarojs/taro";
|
||||||
|
|
||||||
export const getNavbarHeight = (): { statusBarHeight: number; navbarHeight: number; totalHeight: number; } => {
|
export const getNavbarHeight = (): { statusBarHeight: number; navBarHeight: number; totalHeight: number; } => {
|
||||||
|
// 1. 获取系统信息,包含状态栏高度
|
||||||
const systemInfo = Taro.getSystemInfoSync();
|
const systemInfo = Taro.getSystemInfoSync();
|
||||||
const statusBarHeight = systemInfo?.statusBarHeight || 0;
|
const statusBarHeight = systemInfo.statusBarHeight || 0;
|
||||||
|
|
||||||
|
|
||||||
const isIOS = systemInfo.platform === "ios";
|
const isIOS = systemInfo.platform === "ios";
|
||||||
const navbarHeight = isIOS ? 44 : 48;
|
const isIPad = systemInfo.model?.toLowerCase().includes('ipad') ||
|
||||||
|
(systemInfo.platform === 'ios' && systemInfo.screenWidth >= 768);
|
||||||
|
|
||||||
|
// 2. 获取胶囊按钮位置信息(用于计算导航栏高度)
|
||||||
|
const menuButtonInfo = Taro.getMenuButtonBoundingClientRect();
|
||||||
|
|
||||||
|
let navBarHeight = 44 // 默认导航栏高度
|
||||||
|
|
||||||
|
if (menuButtonInfo && menuButtonInfo.top) {
|
||||||
|
// 计算导航栏高度公式
|
||||||
|
navBarHeight = (menuButtonInfo.top - statusBarHeight) * 2 + menuButtonInfo.height
|
||||||
|
} else {
|
||||||
|
// 胶囊按钮信息不可用时,使用默认值
|
||||||
|
if (isIPad) {
|
||||||
|
navBarHeight = 50; // iPad 上的导航栏高度通常更高
|
||||||
|
} else if (isIOS) {
|
||||||
|
navBarHeight = 44; // iPhone 导航栏高度
|
||||||
|
} else {
|
||||||
|
navBarHeight = 48; // Android 导航栏高度
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalHeight = statusBarHeight + navBarHeight;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusBarHeight,
|
statusBarHeight,
|
||||||
navbarHeight,
|
navBarHeight,
|
||||||
totalHeight: statusBarHeight + navbarHeight,
|
totalHeight,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -20,12 +20,45 @@ export interface IFilterOptions {
|
|||||||
playType?: string, // 玩法
|
playType?: string, // 玩法
|
||||||
distanceFilter?: string
|
distanceFilter?: string
|
||||||
}
|
}
|
||||||
|
// 页面状态接口
|
||||||
|
export interface PageState {
|
||||||
|
data: TennisMatch[]
|
||||||
|
recommendList: TennisMatch[]
|
||||||
|
isShowFilterPopup: boolean
|
||||||
|
filterOptions: IFilterOptions
|
||||||
|
distanceQuickFilter: {
|
||||||
|
distance: string
|
||||||
|
quick: string
|
||||||
|
}
|
||||||
|
filterCount: number
|
||||||
|
pageOption: {
|
||||||
|
page: number
|
||||||
|
pageSize: number
|
||||||
|
}
|
||||||
|
gamesNum: number
|
||||||
|
isHasMoreData: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列表页状态
|
||||||
|
export interface ListPageState extends PageState {
|
||||||
|
isShowInputCustomerNavBar: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索页状态
|
||||||
|
export interface SearchPageState extends PageState {
|
||||||
|
searchResultData: TennisMatch[]
|
||||||
|
suggestionList: string[]
|
||||||
|
isShowSuggestion: boolean
|
||||||
|
searchHistory: {id: number, title: string}[]
|
||||||
|
searchHistoryParams: Record<string, any>
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主状态接口
|
||||||
export interface ListState {
|
export interface ListState {
|
||||||
currentPage: string
|
currentPage: string
|
||||||
isSearchResult: boolean
|
isSearchResult: boolean
|
||||||
searchResultData: TennisMatch[]
|
listPageState: ListPageState
|
||||||
matches: TennisMatch[]
|
searchPageState: SearchPageState
|
||||||
recommendList: TennisMatch[]
|
|
||||||
location: {
|
location: {
|
||||||
latitude: number
|
latitude: number
|
||||||
longitude: number
|
longitude: number
|
||||||
@@ -33,32 +66,11 @@ export interface ListState {
|
|||||||
loading: boolean
|
loading: boolean
|
||||||
error: string | null
|
error: string | null
|
||||||
searchValue: string
|
searchValue: string
|
||||||
isShowFilterPopup: boolean
|
|
||||||
filterOptions: IFilterOptions
|
|
||||||
filterCount: number
|
|
||||||
distanceData: any[]
|
distanceData: any[]
|
||||||
quickFilterData: any[]
|
quickFilterData: any[]
|
||||||
distanceQuickFilter: {
|
|
||||||
distance: string
|
|
||||||
quick: string
|
|
||||||
}
|
|
||||||
timeBubbleData: BubbleOption[]
|
timeBubbleData: BubbleOption[]
|
||||||
dateRangeOptions: BubbleOption[]
|
dateRangeOptions: BubbleOption[]
|
||||||
gamesNum: number
|
gamesNum: number
|
||||||
isHasMoreData: boolean
|
|
||||||
isScrollTop: boolean
|
|
||||||
searchHistoryParams: Record<string, any>
|
|
||||||
searchHistory: {id: number, title: string}[]
|
|
||||||
suggestionList: string[]
|
|
||||||
isShowSuggestion: boolean
|
|
||||||
isShowInputCustomerNavBar: boolean
|
|
||||||
isShowResultInputCustomerNavBar: boolean
|
|
||||||
isOpenDistancePopup: boolean,
|
|
||||||
isOpenQuickFilterPopup: boolean,
|
|
||||||
pageOption: {
|
|
||||||
page: number
|
|
||||||
pageSize: number
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ListActions {
|
export interface ListActions {
|
||||||
@@ -67,6 +79,8 @@ export interface ListActions {
|
|||||||
getMatchesData: () => void
|
getMatchesData: () => void
|
||||||
clearError: () => void
|
clearError: () => void
|
||||||
updateState: (payload: Record<string, any>) => void
|
updateState: (payload: Record<string, any>) => void
|
||||||
|
updateListPageState: (payload: Record<string, any>) => void
|
||||||
|
updateSearchPageState: (payload: Record<string, any>) => void
|
||||||
updateFilterOptions: (payload: Record<string, any>) => void
|
updateFilterOptions: (payload: Record<string, any>) => void
|
||||||
clearFilterOptions: () => void
|
clearFilterOptions: () => void
|
||||||
getSearchHistory: () => Promise<void>
|
getSearchHistory: () => Promise<void>
|
||||||
|
|||||||
Reference in New Issue
Block a user