This commit is contained in:
juguohong
2025-08-30 18:20:50 +08:00
parent 1cb303b86d
commit d92419f3c5
23 changed files with 456 additions and 266 deletions

View File

@@ -1,5 +1,8 @@
.customerNavbar {
// background-color: red;
position: sticky;
top: 0;
z-index: 999;
background-color: #ffffff;
.container {
padding-left: 17px;

View File

@@ -1,22 +1,22 @@
import { View, Text, Image } from "@tarojs/components";
import img from "@/config/images";
import { getCurrentLocation } from "@/utils/locationUtils";
import { getNavbarHeight } from "@/utils/getNavbarHeight";
import styles from "./index.module.scss";
import { useEffect } from "react";
import { useGlobalState } from "@/store/global";
import { useListState } from "@/store/listStore";
const ListHeader = () => {
const { statusBarHeight, navbarHeight, totalHeight } = getNavbarHeight();
const {
updateState,
location,
getLocationText,
getLocationLoading,
getNavbarHeightInfo,
statusNavbarHeightInfo,
} = useGlobalState();
const { gamesNum } = useListState();
console.log("===statusNavbarHeightInfo", statusNavbarHeightInfo);
const { statusBarHeight, navbarHeight, totalHeight } = statusNavbarHeightInfo;
// 获取位置信息
const getCurrentLocal = () => {
@@ -31,7 +31,7 @@ const ListHeader = () => {
});
};
useEffect(() => {
getNavbarHeightInfo();
// getNavbarHeightInfo();
getCurrentLocal();
}, []);

View File

@@ -14,6 +14,7 @@
justify-content: space-between;
align-items: center;
padding: 20px 12px env(safe-area-inset-bottom);
z-index: 999;
&-pages {
display: flex;

View File

@@ -1,4 +1,10 @@
.list-item {
.listCard {
background: linear-gradient(90deg, rgba(183, 248, 113, 0.5) 0%, rgba(183, 248, 113, 0.1) 100%);
border-radius: 20px;
border-width: 0.5px;
}
.listItem {
display: flex;
padding: 12px 15px;
background: #ffffff;
@@ -247,4 +253,43 @@
width: 100%;
height: 100%;
object-fit: cover;
}
// 底部
.smoothPlayingGame {
padding: 5px 12px;
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
.smoothWrapper,
.localAreaWrapper {
line-height: 18px;
display: flex;
align-items: center;
gap: 5px;
}
.smoothTitle {
font-size: 14px;
}
.line {
height: 8px;
width: 1px;
background: #00000040;
border-radius: 99px;
}
.iconListPlayingGame,
.localArea {
width: 14px;
height: 14px;
}
.localArea {
border: 0.5px solid #FFFFFFA6;
border-radius: 50%;
}
}

View File

@@ -1,5 +1,5 @@
import { View, Text, Image } from "@tarojs/components";
import Taro from '@tarojs/taro'
import Taro from "@tarojs/taro";
import img from "../../config/images";
import { ListCardProps } from "../../../types/list/types";
import "./index.scss";
@@ -14,7 +14,7 @@ const ListCard: React.FC<ListCardProps> = ({
maxCount,
skillLevel,
matchType,
images=[],
images = [],
shinei,
}) => {
const renderItemImage = (src: string) => {
@@ -23,9 +23,9 @@ const ListCard: React.FC<ListCardProps> = ({
const handleViewDetail = () => {
Taro.navigateTo({
url: `/pages/detail/index?id=${id || 1}&from=list&autoShare=0`
})
}
url: `/pages/detail/index?id=${id || 1}&from=list&autoShare=0`,
});
};
// 根据图片数量决定展示样式
const renderImages = () => {
@@ -34,9 +34,7 @@ const ListCard: React.FC<ListCardProps> = ({
if (images?.length === 1) {
return (
<View className="single-image">
<View className="image-container">
{renderItemImage(images[0])}
</View>
<View className="image-container">{renderItemImage(images[0])}</View>
</View>
);
}
@@ -44,12 +42,8 @@ const ListCard: React.FC<ListCardProps> = ({
if (images?.length === 2) {
return (
<View className="double-image">
<View className="image-container">
{renderItemImage(images[0])}
</View>
<View className="image-container">
{renderItemImage(images[1])}
</View>
<View className="image-container">{renderItemImage(images[0])}</View>
<View className="image-container">{renderItemImage(images[1])}</View>
</View>
);
}
@@ -64,72 +58,87 @@ const ListCard: React.FC<ListCardProps> = ({
);
};
return (
<View className="list-item" onClick={handleViewDetail}>
{/* 左侧内容区域 */}
<View className="content">
{/* 标题 */}
<View className="titleWrapper">
<Text className="title">{title}</Text>
<Image
src={img.ICON_LIST_RIGHT_ARROW}
className="title-right-arrow"
mode="aspectFit"
/>
</View>
{/* 时间信息 */}
<View className="date-time">
<Text>{dateTime}</Text>
</View>
{/* 地点,室内外,距离 */}
<View className="location">
<Text className="location-text location-position">{location}</Text>
<Text className="location-text location-time-distance">
{shinei && `${shinei}`}
{distance && `${distance}`}
</Text>
</View>
{/* 底部信息行:头像组、报名人数、技能等级、比赛类型 */}
<View className="bottom-info">
<View className="left-section">
<View className="avatar-group">
{Array.from({ length: Math.min(registeredCount, 3) }).map(
(_, index) => (
<View key={index} className="avatar">
<Image
className="avatar-image"
src="https://images.unsplash.com/photo-1554068865-24cecd4e34b8?w=200&h=200&fit=crop&crop=center"
mode="aspectFill"
/>
</View>
)
)}
</View>
<View className="listCard">
<View className="listItem" onClick={handleViewDetail}>
{/* 左侧内容区域 */}
<View className="content">
{/* 标题 */}
<View className="titleWrapper">
<Text className="title">{title}</Text>
<Image
src={img.ICON_LIST_RIGHT_ARROW}
className="title-right-arrow"
mode="aspectFit"
/>
</View>
<View className="tags">
<View className="tag">
<Text className="tag-text">
{registeredCount}/
<Text className="tag-text-max">{maxCount}</Text>
</Text>
{/* 时间信息 */}
<View className="date-time">
<Text>{dateTime}</Text>
</View>
{/* 地点,室内外,距离 */}
<View className="location">
<Text className="location-text location-position">{location}</Text>
<Text className="location-text location-time-distance">
{shinei && `${shinei}`}
{distance && `${distance}`}
</Text>
</View>
{/* 底部信息行:头像组、报名人数、技能等级、比赛类型 */}
<View className="bottom-info">
<View className="left-section">
<View className="avatar-group">
{Array.from({ length: Math.min(registeredCount, 3) }).map(
(_, index) => (
<View key={index} className="avatar">
<Image
className="avatar-image"
src="https://images.unsplash.com/photo-1554068865-24cecd4e34b8?w=200&h=200&fit=crop&crop=center"
mode="aspectFill"
/>
</View>
)
)}
</View>
</View>
<View className="tag">
<Text className="tag-text">{skillLevel}</Text>
</View>
<View className="tag">
<Text className="tag-text">{matchType}</Text>
<View className="tags">
<View className="tag">
<Text className="tag-text">
{registeredCount}/
<Text className="tag-text-max">{maxCount}</Text>
</Text>
</View>
<View className="tag">
<Text className="tag-text">{skillLevel}</Text>
</View>
<View className="tag">
<Text className="tag-text">{matchType}</Text>
</View>
</View>
</View>
</View>
{/* 右侧图片区域 */}
<View className="image-section">{renderImages()}</View>
</View>
{/* 畅打球局 */}
<View className="smoothPlayingGame">
<View className="smoothWrapper">
<Image src={img.ICON_LIST_PLAYING_GAME} className="iconListPlayingGame" />
<Text className="smoothTitle"></Text>
</View>
<View className="line" />
<View>:</View>
<View className="localAreaWrapper">
<Image className="localArea" src="https://images.unsplash.com/photo-1554068865-24cecd4e34b8?w=200&h=200&fit=crop&crop=center" />
<Text className="localAreaText"></Text>
</View>
</View>
{/* 右侧图片区域 */}
<View className="image-section">{renderImages()}</View>
</View>
);
};

View File

@@ -13,7 +13,6 @@ const ListCard = () => {
</View>
{/* 时间信息 */}
<View className="date-time">
<Skeleton visible={false} style={{ width: "88px", }} />
</View>

View File

@@ -0,0 +1,44 @@
.listLoadError {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 400px;
.listLoadErrorImg {
width: 154px;
height: 154px;
}
.listLoadErrorText {
margin-top: 35px;
margin-bottom: 12px;
font-weight: 500;
font-style: Medium;
font-size: 14px;
line-height: 24px;
letter-spacing: 0px;
}
.listLoadErrorBtn {
display: flex;
align-items: center;
justify-content: center;
width: 76px;
background: #00000008;
border: 0.5px solid #0000001F;
border-radius: 12px;
padding: 12px 0;
font-weight: 500;
font-style: Medium;
font-size: 14px;
line-height: 24px;
letter-spacing: 0px;
}
.reloadIcon {
width: 16px;
height: 16px;
}
}

View File

@@ -0,0 +1,24 @@
import { Image, View, Text, Button } from "@tarojs/components";
import styles from "./index.module.scss";
import img from "@/config/images";
const ListLoadError = ({ reload }: { reload: () => void }) => {
const handleReload = () => {
reload && typeof reload === "function" && reload();
};
return (
<View className={styles.listLoadError}>
<Image
className={styles.listLoadErrorImg}
src={img.ICON_LIST_LOAD_ERROR}
/>
<Text className={styles.listLoadErrorText}></Text>
<Button className={styles.listLoadErrorBtn} onClick={handleReload}>
<Image src={img?.ICON_LIST_RELOAD} className={styles.reloadIcon} />
</Button>
</View>
);
};
export default ListLoadError;

View File

@@ -5,9 +5,16 @@
--nutui-searchbar-input-text-color: #000000;
--nutui-searchbar-input-padding: 0 0 0 10px;
--nutui-searchbar-padding: 10px 0 0 0;
:global(.nut-searchbar-content) {
box-shadow: 0 4px 48px #00000014;
}
.searchBarLeft {
display: flex;
align-items: center;
}
.searchBarRight {
position: relative;
width: 44px;
@@ -18,14 +25,17 @@
display: flex;
align-items: center;
justify-content: center;
&.active {
background-color: #000000;
}
}
.filterIcon {
width: 20px;
height: 20px;
}
.filterCount {
background-color: #000000;
position: absolute;
@@ -41,8 +51,9 @@
justify-content: center;
font-size: 11px;
}
.searchIcon {
width: 20px;
height: 20px;
}
}
}

View File

@@ -12,6 +12,7 @@ interface IProps {
const SearchBarComponent = (props: IProps) => {
const { handleFilterIcon, isSelect, filterCount, onChange } = props;
const handleChange = (value: string) => {
onChange && onChange(value);
};
@@ -19,9 +20,9 @@ const SearchBarComponent = (props: IProps) => {
<>
<SearchBar
leftIn={
<div>
<View className={styles.searchBarLeft}>
<Image className={styles.searchIcon} src={img.ICON_SEARCH} />
</div>
</View>
}
right={
<View