import { useCallback, useMemo, useRef, useState } from 'react' import Taro, { useDidShow, useReachBottom } from '@tarojs/taro' import { View, Text, Image } from '@tarojs/components' import { Grid, GridItem, Icon, Search, Swiper, SwiperItem } from '@antmjs/vantui' import useCartStore from '@/stores/cart/useCartStore' import { getHomeConfigApi } from '@/services/home' import type { HomeConfig } from '@/services/home' import { getSpecialListApi, normalizeSpecialCart } from '@/services/special' import { getProductCover } from '@/types/product' import type { Product, ProductCartPatch } from '@/types/product' import { getToken } from '@/utils/request' import CartBall from '@/components/CartBall' import CartStepper from '@/components/CartStepper' import {formatRetailPrice, formatSpec} from '@/utils/format' import './index.less' import CustomTabBar from "@/components/CustomTabBar"; /** 首页 → 商品页的本地存储传参 key(switchTab 无法带参) */ const PENDING_CATEGORY_KEY = 'product_category_id' const PENDING_KEYWORD_KEY = 'product_keyword' /** 特价推荐每页条数 */ const SPECIAL_PAGE_SIZE = 10 /** tabBar 页面路径(link 跳转需改用 switchTab) */ const TAB_PATHS = [ 'pages/index/index', 'pages/product/index', 'pages/cart/index', 'pages/message/index', 'pages/profile/index', ] /** 宫格导航无图时的兜底色块配色(生鲜红橙系) */ const NAV_COLORS = ['#ee0a24', '#ff7a1a', '#07c160', '#1989fa', '#8a5cf6', '#ff976a', '#00b8d9', '#f56c6c'] /** 获取状态栏高度(H5 端为 0) */ function getStatusBarHeight(): number { try { const info = typeof Taro.getWindowInfo === 'function' ? Taro.getWindowInfo() : Taro.getSystemInfoSync() return info.statusBarHeight || 0 } catch { return 0 } } export default function IndexPage() { const addItem = useCartStore(s => s.addItem) const setSummary = useCartStore(s => s.setSummary) /** 首页配置(轮播图 / 宫格导航 / 促销卡片) */ const [config, setConfig] = useState({ banners: [], navs: [], promos: [] }) /** 特价推荐商品(后台「客户端配置 → 特价推荐」标记,价格为登录门店的等级价) */ const [specials, setSpecials] = useState([]) /** 特价推荐分页 */ const [specialPage, setSpecialPage] = useState(1) const [specialHasMore, setSpecialHasMore] = useState(false) /** 加载更多中(首屏重置不展示,避免已渲染列表下方闪烁) */ const [specialLoading, setSpecialLoading] = useState(false) /** 特价推荐请求序号(返回 tab 重置与上拉加载并发时,仅采用最后一次响应) */ const specialSeqRef = useRef(0) /** 是否有「加载更多」请求进行中 */ const specialLoadingRef = useRef(false) /** 搜索框输入 */ const [keyword, setKeyword] = useState('') const statusBarHeight = useMemo(() => getStatusBarHeight(), []) useDidShow(() => { loadHomeConfig() loadSpecials(1, true) }) /** 上拉加载更多特价推荐 */ useReachBottom(() => { if (!specialHasMore) return loadSpecials(specialPage + 1, false) }) /** 首页配置聚合数据(响应附带悬浮球汇总) */ const loadHomeConfig = useCallback(async () => { try { const res = await getHomeConfigApi() setConfig(res.data) // 旧版本后端可能未返回 cart 块 if (res.data.cart) setSummary(res.data.cart) } catch { // 错误已由 request 层 toast } }, [setSummary]) /** * 特价推荐商品(reset 时回到第一页整体替换)。 * 行结构与 /mini/product/list 一致;响应附带悬浮球汇总 */ const loadSpecials = useCallback( async (pageNum: number, reset: boolean) => { if (!reset && specialLoadingRef.current) return const seq = ++specialSeqRef.current specialLoadingRef.current = true if (!reset) setSpecialLoading(true) try { const res = await getSpecialListApi({ page: pageNum, pageSize: SPECIAL_PAGE_SIZE }) if (seq !== specialSeqRef.current) return // 已有更新的请求,丢弃本次响应 const { data, total, cart } = res.data setSpecials(prev => (reset ? data : [...prev, ...data])) setSpecialPage(pageNum) setSpecialHasMore(pageNum * SPECIAL_PAGE_SIZE < total) // 列表响应附带悬浮球汇总(旧版本后端可能未返回) const summary = normalizeSpecialCart(cart) if (summary) setSummary(summary) } catch { // 错误已由 request 层 toast } finally { if (seq === specialSeqRef.current) { specialLoadingRef.current = false setSpecialLoading(false) } } }, [setSummary], ) /** * 后台配置的 link 统一跳转: * - 空字符串不跳转 * - tabBar 页面用 switchTab,其余用 navigateTo */ const handleLink = useCallback((link: string) => { if (!link) return const path = link.split('?')[0].replace(/^\//, '') if (TAB_PATHS.includes(path)) { Taro.switchTab({ url: `/${path}` }) } else { Taro.navigateTo({ url: link }) } }, []) /** 跳转商品页并带上关键词 */ const goProduct = useCallback((kw?: string) => { try { if (kw !== undefined) Taro.setStorageSync(PENDING_KEYWORD_KEY, kw) Taro.removeStorageSync(PENDING_CATEGORY_KEY) } catch { // noop } Taro.switchTab({ url: '/pages/product/index' }) }, []) /** 跳转商品详情 */ const goDetail = useCallback((id: number) => { Taro.navigateTo({ url: `/pages/product-detail/index?id=${id}` }) }, []) /** 搜索框聚焦/提交 → 商品页搜索 */ const handleSearchFocus = useCallback(() => { goProduct(keyword.trim()) }, [goProduct, keyword]) /** 行内加减购确认后回写特价商品项的购物车字段 */ const handleRowSync = useCallback((productId: number, patch: ProductCartPatch) => { setSpecials(prev => prev.map(p => (p.id === productId ? { ...p, ...patch } : p))) }, []) /** 快捷加购(用返回的购物车行回写,卡片随即展示加减器) */ const handleQuickAdd = useCallback( async (product: Product, e: any) => { e.stopPropagation() try { const res = await addItem(product.id, 1) handleRowSync(product.id, { cart_id: res.id, cart_quantity: res.quantity }) Taro.showToast({ title: '已加入购物车', icon: 'success' }) } catch { // 错误(未设等级价等)已由 request 层 toast } }, [addItem, handleRowSync], ) /** 无价格时点击:未登录引导登录,已登录但未设等级价提示原因 */ const handlePriceGuide = useCallback((e: any) => { e.stopPropagation() if (getToken()) { Taro.showToast({ title: '该商品暂未设置等级价', icon: 'none' }) } else { Taro.navigateTo({ url: '/pages/login/index' }) } }, []) return ( {/* ========== 自定义顶部导航栏 ========== */} 鲜采直供 产地直采 · 新鲜直达 Taro.switchTab({ url: '/pages/message/index' })}> setKeyword(String(e.detail))} onFocus={handleSearchFocus} onSearch={handleSearchFocus} /> {/* ========== 轮播图 ========== */} {config.banners.length > 0 ? ( config.banners.map(banner => banner.image_url ? ( handleLink(banner.link)} /> ) : null, ) ) : ( 新鲜直采 每日凌晨采货 · 天亮前到店 )} {/* ========== 宫格导航(一行四个) ========== */} {config.navs.length > 0 && ( {config.navs.map((nav, idx) => ( handleLink(nav.link)} renderIcon={ nav.image_url ? ( ) : ( {nav.name.slice(0, 1)} ) } /> ))} )} {/* ========== 促销推荐卡片 ========== */} {config.promos.length > 0 && ( {config.promos.map(promo => ( handleLink(promo.link)}> {promo.image_url && ( )} {promo.title && } {promo.title} {promo.sub_title && {promo.sub_title}} ))} )} {/* ========== 特价推荐 ========== */} 特价推荐 goProduct()}>查看更多 › { specials.length === 0 ? ( 暂无特价商品 ) : ( <> {specials.map(product => ( goDetail(product.id)}> {product.name} {formatSpec(product.spec, product.unit)}{' '} {product.price !== null && <> 单价:{formatRetailPrice(product.price, product.spec)} {product.price_unit} } {product.price !== null ? ( ¥{product.price} ) : ( 登录后查看价格 )} {/* 已加购展示行内加减器,否则展示快捷加购按钮 */} {Number(product.cart_quantity ?? 0) > 0 ? ( ) : ( handleQuickAdd(product, e)}> )} ))} {/* 加载更多状态 */} {specialLoading && ( 加载中… )} {!specialHasMore && specialPage > 1 && ( 已加载全部特价商品 )} )} {/* ========== 购物车悬浮球 ========== */} {process.env.TARO_ENV === 'h5' && } ) }