419 lines
14 KiB
JavaScript
Executable File
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)
|