forked from gxwebsoft/mp-10550
feat(index): 实现Header组件吸顶效果和轮播图触摸优化
- 添加Sticky组件实现Header吸顶功能 - 优化轮播图触摸事件,防止与页面滚动冲突 - 调整轮播图容器样式,确保手势操作流畅 - 更新Header组件结构以支持粘性布局 - 修复Banner组件中图片列表的key属性问题 - 移除不必要的状态传递和冗余代码
This commit is contained in:
@@ -98,7 +98,7 @@ const MyPage = () => {
|
|||||||
return (
|
return (
|
||||||
<View className="flex p-2 justify-between" style={{height: `${carouselHeight}px`}}>
|
<View className="flex p-2 justify-between" style={{height: `${carouselHeight}px`}}>
|
||||||
{/* 左侧轮播图区域 */}
|
{/* 左侧轮播图区域 */}
|
||||||
<View style={{width: '50%', height: '100%'}}>
|
<View style={{width: '50%', height: '100%'}} className="banner-swiper-container">
|
||||||
<Swiper
|
<Swiper
|
||||||
defaultValue={0}
|
defaultValue={0}
|
||||||
height={carouselHeight}
|
height={carouselHeight}
|
||||||
@@ -106,9 +106,10 @@ const MyPage = () => {
|
|||||||
autoPlay
|
autoPlay
|
||||||
duration={3000}
|
duration={3000}
|
||||||
style={{
|
style={{
|
||||||
height: `${carouselHeight}px`,
|
height: `${carouselHeight}px`
|
||||||
touchAction: 'pan-y'
|
|
||||||
}}
|
}}
|
||||||
|
disableTouch={false}
|
||||||
|
touchAngle={"45"} // 关键修改:设置触摸角度阈值
|
||||||
>
|
>
|
||||||
{carouselData && carouselData?.imageList?.map((img, index) => (
|
{carouselData && carouselData?.imageList?.map((img, index) => (
|
||||||
<Swiper.Item key={index}>
|
<Swiper.Item key={index}>
|
||||||
@@ -139,7 +140,7 @@ const MyPage = () => {
|
|||||||
}}>
|
}}>
|
||||||
{
|
{
|
||||||
hotToday?.imageList?.map(item => (
|
hotToday?.imageList?.map(item => (
|
||||||
<View className={'item flex flex-col mr-1'}>
|
<View className={'item flex flex-col mr-1'} key={item.url}>
|
||||||
<Image
|
<Image
|
||||||
width={70}
|
width={70}
|
||||||
height={70}
|
height={70}
|
||||||
@@ -180,5 +181,4 @@ const MyPage = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MyPage
|
export default MyPage
|
||||||
|
|
||||||
@@ -14,3 +14,10 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 吸顶状态下的样式 */
|
||||||
|
.nutui-sticky--fixed {
|
||||||
|
.header-bg {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import Taro from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
import {Button, Space} from '@nutui/nutui-react-taro'
|
import {Button, Space, Sticky} from '@nutui/nutui-react-taro'
|
||||||
import {TriangleDown} from '@nutui/icons-react-taro'
|
import {TriangleDown} from '@nutui/icons-react-taro'
|
||||||
import {Avatar, NavBar} from '@nutui/nutui-react-taro'
|
import {Avatar, NavBar} from '@nutui/nutui-react-taro'
|
||||||
import {getUserInfo, getWxOpenId} from "@/api/layout";
|
import {getUserInfo, getWxOpenId} from "@/api/layout";
|
||||||
@@ -22,6 +22,7 @@ const Header = (props: any) => {
|
|||||||
|
|
||||||
const [IsLogin, setIsLogin] = useState<boolean>(true)
|
const [IsLogin, setIsLogin] = useState<boolean>(true)
|
||||||
const [statusBarHeight, setStatusBarHeight] = useState<number>()
|
const [statusBarHeight, setStatusBarHeight] = useState<number>()
|
||||||
|
const [stickyStatus, setStickyStatus] = useState<boolean>(false)
|
||||||
|
|
||||||
const reload = async () => {
|
const reload = async () => {
|
||||||
Taro.getSystemInfo({
|
Taro.getSystemInfo({
|
||||||
@@ -166,53 +167,76 @@ const Header = (props: any) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理粘性布局状态变化
|
||||||
|
const onStickyChange = (isSticky: boolean) => {
|
||||||
|
setStickyStatus(isSticky)
|
||||||
|
console.log('Header 粘性状态:', isSticky ? '已固定' : '取消固定')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取小程序系统信息
|
||||||
|
const getSystemInfo = () => {
|
||||||
|
const systemInfo = Taro.getSystemInfoSync()
|
||||||
|
// 状态栏高度 + 导航栏高度 (一般为44px)
|
||||||
|
return (systemInfo.statusBarHeight || 0) + 44
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
reload().then()
|
reload().then()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<View className={'fixed top-0 header-bg'} style={{
|
<Sticky
|
||||||
height: !props.stickyStatus ? '180px' : `${(statusBarHeight || 0) + 44}px`,
|
threshold={0}
|
||||||
paddingBottom: !props.stickyStatus ? '12px' : '0px'
|
onChange={onStickyChange}
|
||||||
}}>
|
|
||||||
{/* 只在非吸顶状态下显示搜索框 */}
|
|
||||||
{!props.stickyStatus && <MySearch statusBarHeight={statusBarHeight} />}
|
|
||||||
</View>
|
|
||||||
<NavBar
|
|
||||||
style={{
|
style={{
|
||||||
marginTop: `${statusBarHeight}px`,
|
zIndex: 1000,
|
||||||
marginBottom: '0px',
|
backgroundColor: stickyStatus ? '#03605c' : 'transparent',
|
||||||
backgroundColor: 'transparent'
|
transition: 'background-color 0.3s ease',
|
||||||
}}
|
}}
|
||||||
onBackClick={() => {
|
>
|
||||||
}}
|
<View className={'header-bg'} style={{
|
||||||
left={
|
height: !stickyStatus ? '180px' : `${(statusBarHeight || 0) + 44}px`,
|
||||||
!IsLogin ? (
|
paddingBottom: !stickyStatus ? '12px' : '0px'
|
||||||
<View style={{display: 'flex', alignItems: 'center'}}>
|
}}>
|
||||||
<Button style={{color: '#ffffff'}} open-type="getPhoneNumber" onGetPhoneNumber={handleGetPhoneNumber}>
|
{/* 只在非吸顶状态下显示搜索框 */}
|
||||||
<Space>
|
{!stickyStatus && <MySearch statusBarHeight={statusBarHeight} />}
|
||||||
<Avatar
|
</View>
|
||||||
size="22"
|
<NavBar
|
||||||
src={getWebsiteLogo()}
|
style={{
|
||||||
/>
|
marginTop: `${statusBarHeight}px`,
|
||||||
<Text style={{color: '#ffffff'}}>{getWebsiteName()}</Text>
|
marginBottom: '0px',
|
||||||
<TriangleDown size={9} className={'text-white'}/>
|
backgroundColor: 'transparent'
|
||||||
</Space>
|
}}
|
||||||
</Button>
|
onBackClick={() => {
|
||||||
</View>
|
}}
|
||||||
) : (
|
left={
|
||||||
<View style={{display: 'flex', alignItems: 'center', gap: '8px'}}>
|
!IsLogin ? (
|
||||||
<Avatar
|
<View style={{display: 'flex', alignItems: 'center'}}>
|
||||||
size="22"
|
<Button style={{color: '#ffffff'}} open-type="getPhoneNumber" onGetPhoneNumber={handleGetPhoneNumber}>
|
||||||
src={getWebsiteLogo()}
|
<Space>
|
||||||
/>
|
<Avatar
|
||||||
<Text className={'text-white'}>{getWebsiteName()}</Text>
|
size="22"
|
||||||
<TriangleDown className={'text-white'} size={9}/>
|
src={getWebsiteLogo()}
|
||||||
</View>
|
/>
|
||||||
)}>
|
<Text style={{color: '#ffffff'}}>{getWebsiteName()}</Text>
|
||||||
{/*<QRLoginButton />*/}
|
<TriangleDown size={9} className={'text-white'}/>
|
||||||
</NavBar>
|
</Space>
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<View style={{display: 'flex', alignItems: 'center', gap: '8px'}}>
|
||||||
|
<Avatar
|
||||||
|
size="22"
|
||||||
|
src={getWebsiteLogo()}
|
||||||
|
/>
|
||||||
|
<Text className={'text-white'}>{getWebsiteName()}</Text>
|
||||||
|
<TriangleDown className={'text-white'} size={9}/>
|
||||||
|
</View>
|
||||||
|
)}>
|
||||||
|
{/*<QRLoginButton />*/}
|
||||||
|
</NavBar>
|
||||||
|
</Sticky>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,3 +18,29 @@ page {
|
|||||||
height: 70px;
|
height: 70px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 轮播图容器样式,确保不阻止页面滚动 */
|
||||||
|
.banner-swiper-container {
|
||||||
|
touch-action: pan-y !important;
|
||||||
|
|
||||||
|
.nut-swiper {
|
||||||
|
touch-action: pan-y !important;
|
||||||
|
pointer-events: none; // 关键修改:禁用Swiper的指针事件
|
||||||
|
|
||||||
|
.nut-swiper-item {
|
||||||
|
touch-action: pan-y !important;
|
||||||
|
pointer-events: none; // 关键修改:禁用Swiper Item的指针事件
|
||||||
|
|
||||||
|
image {
|
||||||
|
pointer-events: auto; // 重新启用图片的指针事件,以便点击功能正常
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 吸顶状态下的样式 */
|
||||||
|
.nutui-sticky--fixed {
|
||||||
|
.header-bg {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,19 +4,16 @@ import Taro from '@tarojs/taro';
|
|||||||
import {useShareAppMessage} from "@tarojs/taro"
|
import {useShareAppMessage} from "@tarojs/taro"
|
||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import {getShopInfo} from "@/api/layout";
|
import {getShopInfo} from "@/api/layout";
|
||||||
import {Sticky} from '@nutui/nutui-react-taro'
|
|
||||||
import Menu from "./Menu";
|
import Menu from "./Menu";
|
||||||
import Banner from "./Banner";
|
import Banner from "./Banner";
|
||||||
import {checkAndHandleInviteRelation, hasPendingInvite} from "@/utils/invite";
|
import {checkAndHandleInviteRelation, hasPendingInvite} from "@/utils/invite";
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
||||||
// import GoodsList from "./GoodsList";
|
|
||||||
|
|
||||||
function Home() {
|
function Home() {
|
||||||
// 吸顶状态
|
// 吸顶状态
|
||||||
// const [stickyStatus, setStickyStatus] = useState<boolean>(false)
|
// const [stickyStatus, setStickyStatus] = useState<boolean>(false)
|
||||||
// Tabs粘性状态
|
// Tabs粘性状态
|
||||||
const [tabsStickyStatus, setTabsStickyStatus] = useState<boolean>(false)
|
const [_, setTabsStickyStatus] = useState<boolean>(false)
|
||||||
|
|
||||||
useShareAppMessage(() => {
|
useShareAppMessage(() => {
|
||||||
// 获取当前用户ID,用于生成邀请链接
|
// 获取当前用户ID,用于生成邀请链接
|
||||||
@@ -157,20 +154,13 @@ function Home() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Header区域 - 根据Tabs粘性状态决定是否固定 */}
|
{/* Header区域 - 现在由Header组件内部处理吸顶逻辑 */}
|
||||||
{tabsStickyStatus ? (
|
<Header />
|
||||||
<Sticky threshold={0}>
|
|
||||||
<Header stickyStatus={tabsStickyStatus}/>
|
|
||||||
</Sticky>
|
|
||||||
) : (
|
|
||||||
<Header stickyStatus={tabsStickyStatus}/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className={'flex flex-col mt-12'}>
|
<div className={'flex flex-col mt-12'}>
|
||||||
<Menu/>
|
<Menu/>
|
||||||
<Banner/>
|
<Banner/>
|
||||||
<BestSellers onStickyChange={handleTabsStickyChange}/>
|
<BestSellers onStickyChange={handleTabsStickyChange}/>
|
||||||
{/*<GoodsList/>*/}
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
// 订单页面样式
|
|
||||||
.order-page {
|
|
||||||
// 订单相关样式
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user