266 lines
7.5 KiB
TypeScript
266 lines
7.5 KiB
TypeScript
import { useEffect, useState } from "react";
|
||
import { View, Text, Image } from "@tarojs/components";
|
||
import img from "@/config/images";
|
||
import { useGlobalState } from "@/store/global";
|
||
import { useUserInfo } from "@/store/userStore";
|
||
import { useListState } from "@/store/listStore";
|
||
import { Input } from "@nutui/nutui-react-taro";
|
||
import Taro from "@tarojs/taro";
|
||
import "./index.scss";
|
||
import { getCurrentFullPath } from "@/utils";
|
||
import { CityPicker as PopupPicker } from "@/components/Picker";
|
||
|
||
interface IProps {
|
||
config?: {
|
||
showInput?: boolean;
|
||
inputLeftIcon?: string;
|
||
iconPath?: string;
|
||
leftIconClick?: () => void;
|
||
title?: string; // 显示标题(用于"我的"页面等)
|
||
showTitle?: boolean; // 是否显示标题模式
|
||
};
|
||
onCityPickerVisibleChange?: (visible: boolean) => void; // 城市选择器显示/隐藏回调
|
||
onScrollToTop?: () => void; // 滚动到顶部回调
|
||
}
|
||
|
||
function CityPicker(props) {
|
||
const { visible, setVisible, cities, area, setArea, onCityChange } = props;
|
||
console.log(cities, "cities");
|
||
const [value, setValue] = useState(area);
|
||
|
||
function onChange(value: any) {
|
||
console.log(value, "value");
|
||
setValue(value);
|
||
setArea(value);
|
||
// 切换城市时触发接口调用
|
||
if (onCityChange) {
|
||
onCityChange(value);
|
||
}
|
||
}
|
||
return (
|
||
visible && (
|
||
<PopupPicker
|
||
options={cities}
|
||
visible={visible}
|
||
setvisible={setVisible}
|
||
value={value}
|
||
onChange={onChange}
|
||
style={{ zIndex: 9991 }}
|
||
/>
|
||
)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 首页专用导航栏组件
|
||
* 支持三种模式:
|
||
* 1. Logo + 城市选择 + 球局数量(默认模式)
|
||
* 2. 搜索输入框模式(showInput = true)
|
||
* 3. 标题模式(showTitle = true,用于"我的"页面等)
|
||
*/
|
||
const HomeNavbar = (props: IProps) => {
|
||
const { config, onCityPickerVisibleChange, onScrollToTop } = props;
|
||
const {
|
||
showInput = false,
|
||
inputLeftIcon,
|
||
leftIconClick,
|
||
title,
|
||
showTitle = false,
|
||
} = config || {};
|
||
const { getLocationLoading, statusNavbarHeightInfo } = useGlobalState();
|
||
const {
|
||
gamesNum,
|
||
searchValue,
|
||
cities,
|
||
area,
|
||
updateArea,
|
||
fetchGetGamesCount,
|
||
refreshBothLists,
|
||
} = useListState();
|
||
const { statusBarHeight = 0, navBarHeight = 44 } =
|
||
statusNavbarHeightInfo || {};
|
||
|
||
const [cityPopupVisible, setCityPopupVisible] = useState(false);
|
||
|
||
// 监听城市选择器状态变化,通知父组件
|
||
useEffect(() => {
|
||
onCityPickerVisibleChange?.(cityPopupVisible);
|
||
}, [cityPopupVisible]);
|
||
|
||
const userInfo = useUserInfo();
|
||
const province = (userInfo as any)?.province || "";
|
||
const city = (userInfo as any)?.city || "";
|
||
// const district = (userInfo as any)?.district || "";
|
||
|
||
useEffect(() => {
|
||
updateArea(["中国", province, city]);
|
||
}, [province, city]);
|
||
|
||
// const currentAddress = city + district;
|
||
|
||
const handleInputClick = () => {
|
||
const currentPagePath = getCurrentFullPath();
|
||
if (currentPagePath === "/game_pages/searchResult/index") {
|
||
(Taro as any).navigateBack();
|
||
} else {
|
||
(Taro as any).navigateTo({
|
||
url: "/game_pages/search/index",
|
||
});
|
||
}
|
||
};
|
||
|
||
// 点击logo
|
||
const handleLogoClick = () => {
|
||
// 如果当前在列表页,点击后页面回到顶部
|
||
if (getCurrentFullPath() === "/main_pages/index") {
|
||
// 使用父组件传递的滚动方法(适配 ScrollView)
|
||
if (onScrollToTop) {
|
||
onScrollToTop();
|
||
} else {
|
||
// 降级方案:使用页面滚动(兼容旧版本)
|
||
(Taro as any).pageScrollTo({
|
||
scrollTop: 0,
|
||
duration: 300,
|
||
});
|
||
}
|
||
}
|
||
(Taro as any).redirectTo({
|
||
url: "/main_pages/index", // 列表页
|
||
});
|
||
};
|
||
|
||
const handleInputLeftIconClick = () => {
|
||
if (leftIconClick) {
|
||
leftIconClick();
|
||
} else {
|
||
handleLogoClick();
|
||
}
|
||
};
|
||
|
||
const navbarStyle = {
|
||
height: `${navBarHeight}px`,
|
||
};
|
||
|
||
function handleToggleCity() {
|
||
setCityPopupVisible(true);
|
||
}
|
||
|
||
const area_city = area.at(-1);
|
||
|
||
// 处理城市切换
|
||
const handleCityChange = async (_newArea: any) => {
|
||
// 切换城市后,同时更新两个列表接口获取数据
|
||
if (refreshBothLists) {
|
||
await refreshBothLists();
|
||
}
|
||
// 更新球局数量
|
||
if (fetchGetGamesCount) {
|
||
await fetchGetGamesCount();
|
||
}
|
||
};
|
||
|
||
return (
|
||
<View
|
||
className="homeNavbar"
|
||
style={{
|
||
position: "fixed",
|
||
top: 0,
|
||
left: 0,
|
||
width: "100%",
|
||
height: `${navBarHeight}px`,
|
||
paddingTop: `${statusBarHeight}px`,
|
||
backgroundColor: "transparent",
|
||
zIndex: 99,
|
||
}}
|
||
>
|
||
<View className="listNavWrapper">
|
||
{/* 标题模式(用于"我的"页面等) */}
|
||
{showTitle && (
|
||
<View className="titleNavContainer" style={navbarStyle}>
|
||
<View className="titleNavContent">
|
||
<Text className="titleNavText">{title || "我的"}</Text>
|
||
</View>
|
||
</View>
|
||
)}
|
||
|
||
{/* 首页logo 导航*/}
|
||
{!showTitle && (
|
||
<View
|
||
className={`listNavContainer toggleElement firstElement hidden
|
||
${!showInput ? "visible" : ""}`}
|
||
style={navbarStyle}
|
||
>
|
||
<View className="listNavContentWrapper">
|
||
{/* logo */}
|
||
<Image
|
||
src={img.ICON_LOGO}
|
||
className="listNavLogo"
|
||
onClick={handleLogoClick}
|
||
/>
|
||
<View className="listNavLine" />
|
||
<View className="listNavContent">
|
||
<View className="listNavCityWrapper" onClick={handleToggleCity}>
|
||
{/* 位置 */}
|
||
<Text className="listNavCity">{area_city}</Text>
|
||
{!getLocationLoading && area_city && (
|
||
<Image src={img.ICON_CHANGE} className="listNavChange" />
|
||
)}
|
||
</View>
|
||
<View className="listNavInfoWrapper">
|
||
<Text className="listNavInfo">附近{gamesNum}场球局</Text>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
)}
|
||
|
||
{/* 搜索导航 */}
|
||
{!showTitle && (
|
||
<View
|
||
className={`inputCustomerNavbarContainer toggleElement secondElement hidden ${
|
||
showInput && "visible"
|
||
} ${showInput ? "inputCustomerNavbarShowInput" : ""}`}
|
||
style={navbarStyle}
|
||
>
|
||
<View className="navContent">
|
||
{/* logo */}
|
||
<Image
|
||
src={inputLeftIcon || img.ICON_LIST_INPUT_LOGO}
|
||
className="logo"
|
||
onClick={handleInputLeftIconClick}
|
||
/>
|
||
{/* 搜索框 */}
|
||
<View className="searchContainer">
|
||
<Image
|
||
className="searchIcon icon16"
|
||
src={img.ICON_LIST_SEARCH_SEARCH}
|
||
/>
|
||
<Input
|
||
placeholder="搜索球局和场地"
|
||
className="navbarInput"
|
||
clearable={false}
|
||
disabled
|
||
value={searchValue}
|
||
onClick={handleInputClick}
|
||
/>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
)}
|
||
</View>
|
||
{cityPopupVisible && !showTitle && (
|
||
<CityPicker
|
||
visible={cityPopupVisible}
|
||
setVisible={setCityPopupVisible}
|
||
cities={cities}
|
||
area={area}
|
||
setArea={updateArea}
|
||
onCityChange={handleCityChange}
|
||
/>
|
||
)}
|
||
</View>
|
||
);
|
||
};
|
||
|
||
export default HomeNavbar;
|