bk-shop/src/components/sp-page/index.js

419 lines
14 KiB
JavaScript
Executable File

import React, { useEffect, useState, useRef, useImperativeHandle } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import Taro, { useDidShow, usePageScroll, getCurrentInstance, useReady } from '@tarojs/taro'
import { View, Text, Image } from '@tarojs/components'
import { useImmer } from 'use-immer'
import { SpNavBar, SpFloatMenuItem, SpNote, SpLoading, SpImage, SpChat } from '@/components'
import { TABBAR_PATH } from '@/consts'
import { classNames, styleNames, hasNavbar, isWeixin, isAlipay, isGoodsShelves, entryLaunch, isObject } from '@/utils'
import { AtBadge } from 'taro-ui'
import './index.scss'
const initialState = {
lock: false,
lockStyle: {},
pageTitle: '',
isTabBarPage: true,
customNavigation: false,
cusCurrentPage: 0,
showLeftContainer: false,
currentPath: '',
showCustomNavigation: false,
showNavCartIcon: false,
}
function SpPage (props, ref) {
const $instance = getCurrentInstance()
const [state, setState] = useImmer(initialState)
const { cartCount = 0 } = useSelector((state) => state.cart)
const { lock, lockStyle, pageTitle, isTabBarPage, customNavigation, cusCurrentPage, showLeftContainer, currentPath, showCustomNavigation, showNavCartIcon } = state
const {
className,
children,
renderFloat,
renderFooter,
scrollToTopBtn = false,
isDefault = false,
defaultImg = 'empty_data.png',
renderDefault,
loading = false,
defaultMsg = '',
navbar = true,
onClickLeftIcon = null,
navigateTheme = 'light',
navigateMantle = false, // 自定义导航,开启滚动蒙层
pageConfig = null,
fixedTopContainer = null,
isTop = false,
isBlack = false,
title = '', // 页面导航标题
showNavLogo = false,
showNavkfIcon = false,
showNavHomeIcon = false,
showNavSearchIcon = false,
showLogoLoading = false,
alwaysBackUrl = '',
showNavBackIcon = true
} = props
let { renderTitle } = props
const wrapRef = useRef(null)
const scrollTopRef = useRef(0)
const sys = useSelector((state) => state.sys)
const [showToTop, setShowToTop] = useState(false)
const [mantle, setMantle] = useState(false)
const { colorPrimary, colorMarketing, colorAccent, rgb, appName } = sys
const pageTheme = {
'--color-primary': colorPrimary,
'--color-marketing': colorMarketing,
'--color-accent': colorAccent,
'--color-rgb': rgb,
'--color-dianwu-primary': '#4980FF'
}
useReady(() => {
// 导购货架数据上报
// const router = $instance.router
// console.log('sp pages use ready:', $instance)
})
useEffect(() => {
if (lock) {
setState((draft) => {
draft.lockStyle = {
position: 'fixed',
top: `-${scrollTopRef.current}px`,
left: '0px',
width: '100%',
bottom: '0px'
}
})
} else {
setState((draft) => {
draft.lockStyle = {}
})
}
}, [lock])
useEffect(() => {
if (isWeixin || isAlipay) {
const pages = Taro.getCurrentPages()
const { navigationStyle } = page.config
// customNavigation = navigationStyle === 'custom'
// cusCurrentPage = pages.length
setState(draft => {
// draft.customNavigation = navigationStyle === 'custom'
draft.customNavigation = true
draft.cusCurrentPage = pages.length
})
}
}, [])
useEffect(() => {
if (pageConfig) {
const { navigateBackgroundColor } = pageConfig
if (isAlipay) {
my.setNavigationBar({
backgroundColor: navigateBackgroundColor
})
}
}
}, [pageConfig])
useDidShow(() => {
const { page, router } = getCurrentInstance()
const pageTitle = page?.config?.navigationBarTitleText
const fidx = Object.values(TABBAR_PATH).findIndex(
(v) => v == $instance.router?.path.split('?')[0]
)
const isTabBarPage = fidx > -1
setState((draft) => {
draft.currentPath = `${page?.route}`
draft.pageTitle = pageTitle
draft.isTabBarPage = isTabBarPage
draft.showLeftContainer = !['/subpages/guide/index', '/pages/index'].includes(`/${page?.route}`)
// '/subpages/member/index',
draft.showCustomNavigation = ['/pages/cart/espier-index', '/pages/index', '/pages/category/index', '/pages/recommend/list'].includes(`/${page?.route}`)
// draft.showCustomNavigation = true
draft.showNavCartIcon = ['/subpages/marketing/coupon-center', '/subpages/marketing/coupon', '/pages/item/list'].includes(`/${page?.route}`)
})
// 导购货架分包路由,隐藏所有分享入口
if (router.path.indexOf('/subpages/guide') > -1) {
Taro.hideShareMenu({
menus: ["shareAppMessage", "shareTimeline"]
})
}
})
usePageScroll((res) => {
if (!lock) {
scrollTopRef.current = res.scrollTop
}
if (navigateMantle && res.scrollTop > 0) {
setMantle(true)
} else {
setMantle(false)
}
if (res.scrollTop > 300) {
setShowToTop(true)
} else {
setShowToTop(false)
}
})
const scrollToTop = () => {
Taro.pageScrollTo({
scrollTop: 0,
success: () => {
Taro.setStorageSync('scrollTop', 0)
}
})
}
useImperativeHandle(ref, () => ({
pageLock: () => {
setState((draft) => {
draft.lock = true
})
},
pageUnLock: () => {
setState((draft) => {
draft.lock = false
})
setTimeout(() => {
Taro.pageScrollTo({
scrollTop: scrollTopRef.current,
duration: 0
})
}, 0)
// console.log('scrollTopRef.current:', scrollTopRef.current)
}
}))
let model = ''
let ipx = false
let gNavbarH = 0, gStatusBarHeight = 0, gAreaH = 0
// let customNavigation = false
// let cusCurrentPage = 0
if (isWeixin || isAlipay) {
const deviceInfo = Taro.getSystemInfoSync()
// console.log('deviceInfo:', deviceInfo)
model = deviceInfo.model
ipx = model.search(/iPhone\s*X|iPhone\s*11|iPhone\s*12|iPhone\s*13|iPhone\s*14|iPhone\s*15|iPhone\s*16|iPhone\s*10/g) > -1
const menuButton = Taro.getMenuButtonBoundingClientRect()
const { statusBarHeight, safeArea, screenHeight } = deviceInfo
gAreaH = (screenHeight - safeArea.bottom)
gNavbarH = Math.floor(statusBarHeight + menuButton.height + (menuButton.top - statusBarHeight) * 2)
gStatusBarHeight = statusBarHeight
}
const { page, route } = getCurrentInstance()
const _pageTitle = page?.config?.navigationBarTitleText
// if (isWeixin) {
// const pages = Taro.getCurrentPages()
// // const currentPage = pages[pages.length - 1]
// const { navigationStyle } = page.config
// customNavigation = navigationStyle === 'custom'
// cusCurrentPage = pages.length
// }
const CustomNavigation = () => {
// const { page, route } = getCurrentInstance()
let pageStyle = {}, pageTitleStyle = {}
if (pageConfig) {
const { navigateBackgroundColor, navigateStyle, navigateBackgroundImage, titleStyle, titleColor, titleBackgroundImage, titlePosition } = pageConfig
// 导航颜色背景
if (navigateStyle == '1') {
pageStyle = {
'background-color': "#FFF" || navigateBackgroundColor
}
} else {
pageStyle = {
'background-image': `url(${navigateBackgroundImage})`,
'background-size': '100% 100%',
'background-repeat': 'no-repeat',
'background-position': 'center'
}
}
// 页面标题
if (titleStyle == '1') {
renderTitle = <Text style={styleNames({
color: titleColor
})}>{appName}</Text>
} else if (titleStyle == '2') {
renderTitle = <SpImage src={titleBackgroundImage} height={72} mode='heightFix' />
}
pageTitleStyle = {
'justify-content': titlePosition == 'left' ? 'flex-start' : 'center',
'color': titleColor
}
}
renderTitle = showCustomNavigation || showNavLogo ? <SpImage src={`member/logo-${isBlack ? "black" : "light"}.png`} height={34} mode='heightFix' isNew /> : undefined
const navigationBarTitleText = props.navigationBarTitleText || getCurrentInstance().page?.config?.navigationBarTitleText
return (
<View
className={classNames('custom-navigation', {
'mantle': mantle,
}, navigateTheme)}
style={styleNames({
// height: `${gNavbarH - gStatusBarHeight + 2}px`,
height: `${gNavbarH}px`,
paddingTop: `${gStatusBarHeight}px`,
// 'padding-top': `${gStatusBarHeight}px`,
// top: `${gStatusBarHeight - 2}px`,
...pageStyle,
'background-color': isTop ? 'transparent' : 'white',
})}
>
<View className="custom-status-bar" style={{ height: `${gStatusBarHeight}px` }}></View>
{<View className='left-container'>
{false && <View className='icon-wrap-1'>
<Text
className={classNames('iconfont', {
// 'icon-home1': cusCurrentPage == 1,
// 'icon-fanhui': cusCurrentPage != 1
"icon-sousuo-01": true
})}
onClick={() => {
if (cusCurrentPage == 1) {
Taro.redirectTo({
url: isGoodsShelves() ? '/subpages/guide/index' : '/pages/index'
})
} else {
Taro.navigateBack()
}
}}
/>
</View>}
{/* <Image className="chazhao" src={require("@/assets/chazhao-light.png")}></Image> */}
{showCustomNavigation ? <SpImage onClick={() => Taro.navigateTo({ url: '/pages/item/list?showSearch=true' })} src={`member/chazhao-${isBlack ? "black" : "light"}.png`} height={34} mode='heightFix' isNew />
: <View className='icon-wrap'>
{showNavBackIcon && <Text
className={classNames('iconfont', {
// 'icon-home1': cusCurrentPage == 1,
'icon-fanhui': alwaysBackUrl ? true : cusCurrentPage != 1
})}
// style={{ color: isBlack ? 'white' : 'black' }}
onClick={() => {
if (alwaysBackUrl) {
Taro.navigateTo({
url: alwaysBackUrl,
})
return
}
if (cusCurrentPage == 1) {
Taro.redirectTo({
url: isGoodsShelves() ? '/subpages/guide/index' : '/pages/index'
})
} else {
Taro.navigateBack()
}
}}
/>}
{showNavCartIcon ? cartCount > 0 ? <AtBadge value={cartCount} maxValue={99}><SpImage src={`member/cart.png`} onClick={() => Taro.redirectTo({ url: '/pages/cart/espier-index' })} height={36} mode='heightFix' isNew /></AtBadge> : <SpImage src={`member/cart.png`} onClick={() => Taro.redirectTo({ url: '/pages/cart/espier-index' })} height={36} mode='heightFix' isNew /> : null}
{showNavHomeIcon && <SpImage src={`cart/home.png`} onClick={() => Taro.redirectTo({ url: '/pages/index' })} height={36} mode='heightFix' isNew />}
{showNavSearchIcon && <SpImage onClick={() => Taro.navigateTo({ url: '/pages/item/list?showSearch=true' })} src={`member/chazhao-${isBlack ? "black" : "light"}.png`} height={34} mode='heightFix' isNew />}
</View>
}
{showNavkfIcon && <SpChat><SpImage className='icon-kf' src={`index/kf.png`} onClick={() => Taro.redirectTo({ url: '/pages/cart/espier-index' })} height={46} mode='heightFix' isNew /></SpChat>}
</View>}
{isWeixin && <View className='title-container' style={styleNames(pageTitleStyle)}>
{renderTitle || title || navigationBarTitleText}
{/* 吸顶区域 */}
{fixedTopContainer}
</View>}
{showLeftContainer && <View className='right-container'></View>}
</View>
)
}
let pageBackground = {}
if (pageConfig) {
const { pageBackgroundStyle, pageBackgroundColor, pageBackgroundImage } = pageConfig
if (pageBackgroundStyle == '1') {
pageBackground = {
'background-color': "#FFF" || pageBackgroundColor
}
} else {
pageBackground = {
'background-image': `url(${pageBackgroundImage})`,
'background-size': '100% 100%',
'background-position': 'center'
}
}
}
return (
<View
className={classNames('sp-page', className, {
// 'has-navbar': hasNavbar && !isTabBarPage && navbar,
'has-navbar': true,
'has-footer': renderFooter,
'has-custom-navigation': customNavigation && pageConfig,
'ipx': ipx
})}
style={styleNames({
...pageTheme, ...lockStyle, ...pageBackground, 'padding-top': isTop ? currentPath === 'pages/index' ? 0 : `${customNavigation ? gStatusBarHeight : 0}px` : `${customNavigation ? gNavbarH : 0}px`,
"--nav-height": `${gNavbarH}px`,
"--status-bar-height": `${gStatusBarHeight}px`,
"--area-bottom-height": `${gAreaH}rpx`,
})}
ref={wrapRef}
>
{hasNavbar && !isTabBarPage && navbar && (
<SpNavBar title={pageTitle || _pageTitle} onClickLeftIcon={onClickLeftIcon} />
)}
{isDefault && (renderDefault || <SpNote img={defaultImg} title={defaultMsg} isUrl={true} />)}
{/* 没有页面自动义头部配置样式,自动生成自定义导航 */}
{customNavigation && CustomNavigation()}
{/* {loading && <SpNote img='loading.gif' />} */}
{loading && <SpLoading />}
{showLogoLoading && <View className='loading-box'>
<SpImage height={244} width={244} src='logo-load.jpg' isNew />
</View>}
{!isDefault && !loading && <View className='sp-page-body' style={styleNames({
// height: `calc(100vh - ${customNavigation ? gNavbarH : 0}px - $tabbar-height - env(safe-area-inset-bottom))`,
// 'margin-top': `${0}px`
})}>{children}</View>}
{/* 置底操作区 */}
{!isDefault && renderFooter && <View className='sp-page-footer'>{renderFooter}</View>}
{/* 浮动 */}
{!isDefault && (
<View className='float-container'>
{renderFloat}
{showToTop && scrollToTopBtn && (
<SpFloatMenuItem onClick={scrollToTop}>
<Text className='iconfont icon-zhiding'></Text>
</SpFloatMenuItem>
)}
</View>
)}
<sp-wx-privacy />
</View>
)
}
export default React.forwardRef(SpPage)