列表联调

This commit is contained in:
李瑞
2025-09-07 18:54:36 +08:00
parent 2d0d728969
commit 6feb7057af
28 changed files with 1225 additions and 740 deletions

View File

@@ -20,20 +20,20 @@ const ListHeader = (props: IProps) => {
const { statusBarHeight, navbarHeight } = statusNavbarHeightInfo;
// 获取位置信息
const getCurrentLocal = () => {
updateState({
getLocationLoading: true,
});
getCurrentLocation().then((res) => {
updateState({
getLocationLoading: false,
location: res || {},
});
});
};
useEffect(() => {
getCurrentLocal();
}, []);
// const getCurrentLocal = () => {
// updateState({
// getLocationLoading: true,
// });
// getCurrentLocation().then((res) => {
// updateState({
// getLocationLoading: false,
// location: res || {},
// });
// });
// };
// useEffect(() => {
// getCurrentLocal();
// }, []);
const handleInputClick = () => {
Taro.navigateTo({

View File

@@ -1,36 +1,72 @@
import { View, Text } from "@tarojs/components";
import { View } from "@tarojs/components";
import ListCard from "@/components/ListCard";
import ListLoadError from "@/components/ListLoadError";
import ListCardSkeleton from "@/components/ListCardSkeleton";
// import { VirtualList } from '@nutui/nutui-react-taro'
import "./index.scss";
import { useReachBottom } from "@tarojs/taro";
const ListContainer = (props) => {
const { loading, data = [], error, reload, recommendList } = props;
const {
loading,
data = [],
error,
reload,
recommendList,
loadMoreMatches,
} = props;
console.log("===data", data);
useReachBottom(() => {
console.log("触底了");
// 调用 store 的加载更多方法
// loadMoreMatches();
loadMoreMatches();
});
if (error) {
return <ListLoadError reload={reload} />;
}
const renderList = (list) => {
if (loading && list.length === 0) {
return (
<>
{new Array(10).fill(0).map(() => {
return <ListCardSkeleton />;
})}
</>
);
}
const renderSkeleton = () => {
return (
<>
{new Array(10).fill(0).map(() => {
return <ListCardSkeleton />;
})}
</>
);
};
// 渲染列表
const renderList = (list) => {
// 请求未回来显示骨架屏
// if (loading && list?.length === 0) {
// return (
// <>
// {new Array(10).fill(0).map(() => {
// return <ListCardSkeleton />;
// })}
// </>
// );
// }
// 请求数据为空
if (!loading && list?.length === 0) {
return <ListLoadError reload={reload} text="暂无数据" />;
}
// 渲染数据
return (
<>
{/* <VirtualList
containerHeight={1000}
itemHeight={144}
// itemEqual={false}
list={list}
itemRender={(data) => {
return <ListCard {...data}/>
}}
/> */}
{list?.map((match, index) => (
<ListCard key={match.id || index} {...match} />
))}
@@ -41,12 +77,14 @@ const ListContainer = (props) => {
return (
<View className="listContentWrapper">
{renderList(data)}
<View className="recommendTextWrapper">
{/* 显示骨架屏 */}
{loading && renderSkeleton()}
{/* <View className="recommendTextWrapper">
<Text className="recommendText">搜索结果较少,已为你推荐其他内容</Text>
</View>
{renderList(recommendList)}
{renderList(recommendList)} */}
{/* 到底了 */}
<View className="bottomTextWrapper"></View>
{data?.length > 0 && <View className="bottomTextWrapper"></View>}
</View>
);
};

View File

@@ -1,43 +0,0 @@
.container {
padding-left: 17px;
display: flex;
align-items: center;
gap: 8px;
.line {
width: 1px;
height: 25px;
background-color: #0000000F;
}
.logo {
width: 60px;
height: 34px;
}
.change {
width: 12px;
height: 12px;
}
.cityWrapper {
line-height: 20px;
}
.city {
font-weight: 600;
font-size: 13px;
line-height: 20px;
}
.infoWrapper {
line-height: 12px;
}
.info {
font-weight: 400;
font-size: 10px;
line-height: 12px;
color: #3C3C4399;
}
}

View File

@@ -0,0 +1,144 @@
.listNavWrapper {
position: relative;
}
.listNavContainer {
.listNavLine {
width: 1px;
height: 25px;
background-color: #0000000f;
}
.listNavLogo {
width: 60px;
height: 34px;
}
.listNavChange {
width: 12px;
height: 12px;
}
.listNavContentWrapper {
padding-left: 17px;
display: flex;
align-items: center;
gap: 8px;
}
.listNavCityWrapper {
line-height: 20px;
}
.listNavCity {
font-weight: 600;
font-size: 13px;
line-height: 20px;
}
.infoWrapper {
line-height: 12px;
}
.listNavInfoWrapper {
font-weight: 400;
font-size: 10px;
line-height: 12px;
color: #3c3c4399;
}
}
.inputCustomerNavbarContainer {
padding-left: 17px;
display: flex;
gap: 8px;
.logo {
width: 28px;
height: 16px;
}
.icon16 {
width: 16px;
height: 16px;
}
.navContent {
display: flex;
align-items: center;
gap: 4px;
width: 65%;
height: max-content;
// padding-top: 5px;
}
.searchContainer {
width: 100%;
display: flex;
align-items: center;
gap: 5.85px;
padding: 7.8px;
height: 30px;
box-sizing: border-box;
border-radius: 30px;
border: 0.488px solid rgba(0, 0, 0, 0.06);
box-shadow: 0 3.902px 46.829px 0 rgba(0, 0, 0, 0.08);
height: 30px;
box-sizing: border-box;
font-size: 13.659px;
font-style: normal;
font-weight: 400;
line-height: 17.561px;
flex: 1;
.nut-input {
padding: 0;
}
}
}
.inputCustomerNavbarShowInput {
padding-left: 10px;
.logo {
width: 32px;
height: 32px;
}
}
.toggleElement {
/* 绝对定位使两个元素重叠 */
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
/* 过渡动画设置,实现平滑切换 */
transition: opacity 0.5s ease, transform 0.5s ease;
}
/* 第一个元素样式 */
.firstElement {
// background-color: #4a90e2;
}
/* 第二个元素样式 */
.secondElement {
// background-color: #5cb85c;
/* 初始状态:透明且稍微偏移 */
opacity: 0;
// transform: translateY(20px);
}
/* 隐藏状态 */
.hidden {
opacity: 0;
transform: translateY(20px);
// pointer-events: none; /* 隐藏时不响应鼠标事件 */
}
/* 可见状态 */
.visible {
opacity: 1;
transform: translateY(0);
}

View File

@@ -1,65 +1,134 @@
import { View, Text, Image } from "@tarojs/components";
import img from "@/config/images";
import { getCurrentLocation } from "@/utils/locationUtils";
import styles from "./index.module.scss";
import { useEffect } from "react";
import { useGlobalState } from "@/store/global";
import { useListState } from "@/store/listStore";
import CustomNavbar from '@/components/CustomNavbar'
import CustomNavbar from "@/components/CustomNavbar";
import { Input } from "@nutui/nutui-react-taro";
import Taro from "@tarojs/taro";
import "./index.scss";
const ListHeader = () => {
interface IProps {
config?: {
showInput: boolean;
inputLeftIcon: string;
iconPath?: string;
leftIconClick: () => void;
};
}
const ListHeader = (props: IProps) => {
const { config } = props;
const {
showInput = false,
inputLeftIcon,
leftIconClick,
} = config || {};
const {
updateState,
location,
getLocationText,
getLocationLoading,
statusNavbarHeightInfo,
} = useGlobalState();
const { gamesNum } = useListState();
const { gamesNum, searchValue, isShowInputCustomerNavBar } = useListState();
const { statusBarHeight, navbarHeight } = statusNavbarHeightInfo;
// 获取位置信息
const getCurrentLocal = () => {
updateState({
getLocationLoading: true,
});
getCurrentLocation().then((res) => {
updateState({
getLocationLoading: false,
location: res || {},
});
});
};
useEffect(() => {
getCurrentLocal();
}, []);
const currentAddress = getLocationLoading
? getLocationText
: location?.address;
const handleInputClick = () => {
const pages = Taro.getCurrentPages();
const currentPage = pages[pages.length - 1];
const currentPagePath = currentPage.route;
if (currentPagePath === "pages/searchResult/index") {
Taro.navigateBack();
} else {
Taro.navigateTo({
url: "/pages/search/index",
});
}
};
// 点击logo
const handleLogoClick = () => {
Taro.redirectTo({
url: "pages/list/index", // 列表页
});
};
const handleInputLeftIconClick = () => {
if (leftIconClick) {
leftIconClick();
} else {
handleLogoClick();
}
};
return (
<CustomNavbar>
<View
className={styles.container}
style={{
height: `${navbarHeight}px`,
paddingTop: `${statusBarHeight}px`,
}}
>
{/* logo */}
<Image src={img.ICON_LOGO} className={styles.logo} />
<View className={styles.line} />
<View className={styles.content}>
<View className={styles.cityWrapper}>
{/* 位置 */}
<Text className={styles.city}>{currentAddress}</Text>
{!getLocationLoading && (
<Image src={img.ICON_CHANGE} className={styles.change} />
)}
<View className="listNavWrapper">
{/* 首页logo 导航*/}
<View
className={`listNavContainer toggleElement firstElement hidden ${
(!isShowInputCustomerNavBar && !showInput) && "visible"
}`}
style={{
height: `${navbarHeight}px`,
paddingTop: `${statusBarHeight}px`,
}}
>
<View className="listNavContentWrapper">
{/* logo */}
<Image
src={img.ICON_LOGO}
className="listNavLogo"
onClick={handleLogoClick}
/>
<View className="listNavLine" />
<View className="listNavContent">
<View className="listNavCityWrapper">
{/* 位置 */}
<Text className="listNavCity">{currentAddress}</Text>
{!getLocationLoading && currentAddress && (
<Image src={img.ICON_CHANGE} className="listNavChange" />
)}
</View>
<View className="listNavInfoWrapper">
<Text className="listNavInfo">${gamesNum}</Text>
</View>
</View>
</View>
<View className={styles.infoWrapper}>
<Text className={styles.info}>${gamesNum}</Text>
</View>
{/* 搜索导航 */}
<View
className={`inputCustomerNavbarContainer toggleElement secondElement hidden ${
(isShowInputCustomerNavBar || showInput) && "visible"
} ${showInput && "inputCustomerNavbarShowInput"}`}
style={{
height: `${navbarHeight}px`,
paddingTop: `${statusBarHeight}px`,
}}
>
<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="搜索上海的球局和场地"
clearable={false}
value={searchValue}
onClick={handleInputClick}
/>
</View>
</View>
</View>
</View>