- 移除了立即送水按钮中的固定商品ID参数 - 修改ensureLoggedIn函数调用,不再传递商品ID - 更新Taro.navigateTo路径,移除硬编码的goodsId参数
381 lines
13 KiB
TypeScript
381 lines
13 KiB
TypeScript
// import Header from './Header'
|
||
import Banner from './Banner'
|
||
import Taro, { useDidShow, useShareAppMessage } from '@tarojs/taro'
|
||
import { View, Text, Image, ScrollView } from '@tarojs/components'
|
||
import { useEffect, useMemo, useState, type ReactNode } from 'react'
|
||
import { Cart, Gift, Ticket, Agenda, ArrowRight } from '@nutui/icons-react-taro'
|
||
import { getShopInfo } from '@/api/layout'
|
||
import { checkAndHandleInviteRelation, hasPendingInvite } from '@/utils/invite'
|
||
import { pageShopGoods } from '@/api/shop/shopGoods'
|
||
import type { ShopGoods, ShopGoodsParam } from '@/api/shop/shopGoods/model'
|
||
import { getMyGltUserTicketTotal } from '@/api/glt/gltUserTicket'
|
||
import { ensureLoggedIn } from '@/utils/auth'
|
||
import './index.scss'
|
||
// import navTo from "@/utils/common";
|
||
|
||
function Home() {
|
||
const [activeTabKey, setActiveTabKey] = useState('recommend')
|
||
const [goodsList, setGoodsList] = useState<ShopGoods[]>([])
|
||
const [ticketTotal, setTicketTotal] = useState(0)
|
||
|
||
useShareAppMessage(() => {
|
||
// 获取当前用户ID,用于生成邀请链接
|
||
const userId = Taro.getStorageSync('UserId');
|
||
const user = Taro.getStorageSync('User') || {};
|
||
const nickname =
|
||
(user && (user.nickname || user.realName || user.username)) || '';
|
||
|
||
return {
|
||
title: (nickname || '') + '超值推荐',
|
||
path: userId ? `/pages/index/index?inviter=${userId}&source=share&t=${Date.now()}` : `/pages/index/index`,
|
||
success: function () {
|
||
console.log('首页分享成功');
|
||
Taro.showToast({
|
||
title: '分享成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
});
|
||
},
|
||
fail: function () {
|
||
console.log('首页分享失败');
|
||
Taro.showToast({
|
||
title: '分享失败',
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
}
|
||
};
|
||
});
|
||
|
||
// const reloadMore = async () => {
|
||
// setPage(page + 1)
|
||
// }
|
||
|
||
const showAuthModal = () => {
|
||
Taro.showModal({
|
||
title: '授权提示',
|
||
content: '需要获取您的用户信息',
|
||
confirmText: '去授权',
|
||
cancelText: '取消',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
// 用户点击确认,打开授权设置页面
|
||
openSetting();
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
const openSetting = () => {
|
||
// Taro.openSetting:调起客户端小程序设置界面,返回用户设置的操作结果。设置界面只会出现小程序已经向用户请求过的权限。
|
||
Taro.openSetting({
|
||
success: (res) => {
|
||
if (res.authSetting['scope.userInfo']) {
|
||
// 用户授权成功,可以获取用户信息
|
||
reload();
|
||
} else {
|
||
// 用户拒绝授权,提示授权失败
|
||
Taro.showToast({
|
||
title: '授权失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
// const onSticky = (item: IArguments) => {
|
||
// if(item){
|
||
// setStickyStatus(!stickyStatus)
|
||
// }
|
||
// }
|
||
|
||
// 处理Tabs粘性状态变化
|
||
// const handleTabsStickyChange = (isSticky: boolean) => {}
|
||
|
||
const reload = () => {
|
||
const token = Taro.getStorageSync('access_token')
|
||
const userIdRaw = Taro.getStorageSync('UserId')
|
||
const userId = Number(userIdRaw)
|
||
const hasUserId = Number.isFinite(userId) && userId > 0
|
||
if (!token && !hasUserId) {
|
||
setTicketTotal(0)
|
||
return
|
||
}
|
||
getMyGltUserTicketTotal(hasUserId ? userId : undefined)
|
||
.then((total) => setTicketTotal(typeof total === 'number' ? total : 0))
|
||
.catch((err) => {
|
||
console.error('首页水票总数加载失败:', err)
|
||
setTicketTotal(0)
|
||
})
|
||
};
|
||
|
||
// 回到首页/首次进入时都刷新一次(避免依赖 scope.userInfo 导致不触发 reload)
|
||
useDidShow(() => {
|
||
reload()
|
||
})
|
||
|
||
useEffect(() => {
|
||
// 获取站点信息
|
||
getShopInfo().then(() => {
|
||
|
||
})
|
||
|
||
// 检查是否有待处理的邀请关系 - 异步处理,不阻塞页面加载
|
||
if (hasPendingInvite()) {
|
||
console.log('检测到待处理的邀请关系')
|
||
// 延迟处理,确保用户信息已加载,并设置超时保护
|
||
setTimeout(async () => {
|
||
try {
|
||
// 设置超时保护,避免长时间等待
|
||
const timeoutPromise = new Promise((_, reject) =>
|
||
setTimeout(() => reject(new Error('邀请关系处理超时')), 8000)
|
||
);
|
||
|
||
const invitePromise = checkAndHandleInviteRelation();
|
||
|
||
const success = await Promise.race([invitePromise, timeoutPromise]);
|
||
if (success) {
|
||
console.log('首页邀请关系处理成功')
|
||
}
|
||
} catch (error) {
|
||
console.error('首页邀请关系处理失败:', error)
|
||
// 邀请关系处理失败不应该影响页面正常显示
|
||
// 可以选择清除邀请参数,避免重复尝试
|
||
const errorMessage = error instanceof Error ? error.message : String(error)
|
||
if (errorMessage?.includes('超时')) {
|
||
console.log('邀请关系处理超时,清除邀请参数')
|
||
// 可以选择清除邀请参数或稍后重试
|
||
}
|
||
}
|
||
}, 2000)
|
||
}
|
||
|
||
// Taro.getSetting:获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限。
|
||
Taro.getSetting({
|
||
success: (res) => {
|
||
if (res.authSetting['scope.userInfo']) {
|
||
// 用户已经授权过,可以直接获取用户信息
|
||
console.log('用户已经授权过,可以直接获取用户信息')
|
||
} else {
|
||
// 用户未授权,需要弹出授权窗口
|
||
console.log('用户未授权,需要弹出授权窗口')
|
||
showAuthModal();
|
||
}
|
||
}
|
||
});
|
||
// 获取用户信息
|
||
Taro.getUserInfo({
|
||
success: (res) => {
|
||
const avatar = res.userInfo.avatarUrl;
|
||
// Keep WeChat display name in storage so share title can use it.
|
||
console.log(avatar, 'avatarUrl')
|
||
}
|
||
});
|
||
}, []);
|
||
|
||
const tabs = useMemo<
|
||
Array<{ key: string; title: string; params: Partial<ShopGoodsParam> }>
|
||
>(
|
||
() => [
|
||
{ key: 'recommend', title: '推荐', params: { recommend: 1 } },
|
||
{ key: '4476', title: '桶装水', params: { categoryId: 4476 } },
|
||
{ key: '4556', title: '水票套餐', params: { categoryId: 4556 } },
|
||
// { key: '4557', title: '购机套餐', params: { categoryId: 4557 } },
|
||
// { key: '4477', title: '饮水设备', params: { categoryId: 4477 } },
|
||
],
|
||
[]
|
||
)
|
||
|
||
useEffect(() => {
|
||
const tab = tabs.find((t) => t.key === activeTabKey) || tabs[0]
|
||
if (!tab) return
|
||
|
||
pageShopGoods({ ...tab.params, status: 0 })
|
||
.then((res) => setGoodsList((res?.list || []).filter((g) => g?.status === 0)))
|
||
.catch((err) => {
|
||
console.error('首页商品列表加载失败:', err)
|
||
setGoodsList([])
|
||
})
|
||
}, [activeTabKey, tabs])
|
||
|
||
const shortcuts = useMemo<
|
||
Array<{ key: string; title: string; icon: ReactNode; onClick: () => void }>
|
||
>(
|
||
() => [
|
||
{
|
||
key: 'ticket',
|
||
title: '我的水票',
|
||
icon: <Ticket size={30} />,
|
||
onClick: () => {
|
||
if (!ensureLoggedIn('/user/ticket/index')) return
|
||
Taro.navigateTo({ url: '/user/ticket/index' })
|
||
},
|
||
},
|
||
{
|
||
key: 'order',
|
||
title: '立即送水',
|
||
icon: <Cart size={30} />,
|
||
onClick: () => {
|
||
if (!ensureLoggedIn('/user/ticket/use')) return
|
||
Taro.navigateTo({ url: '/user/ticket/use' })
|
||
},
|
||
},
|
||
{
|
||
key: 'order',
|
||
title: '送水订单',
|
||
icon: <Agenda size={30} />,
|
||
onClick: () => {
|
||
const url = '/user/ticket/index?tab=order'
|
||
if (!ensureLoggedIn(url)) return
|
||
Taro.navigateTo({ url })
|
||
},
|
||
},
|
||
{
|
||
key: 'invite',
|
||
title: '邀请有礼',
|
||
icon: <Gift size={30} />,
|
||
onClick: () => {
|
||
if (!ensureLoggedIn('/dealer/qrcode/index')) return
|
||
Taro.navigateTo({ url: '/dealer/qrcode/index' })
|
||
},
|
||
},
|
||
// {
|
||
// key: 'coupon',
|
||
// title: '领券中心',
|
||
// icon: <Coupon size={30} />,
|
||
// onClick: () => Taro.navigateTo({ url: '/coupon/index' }),
|
||
// },
|
||
],
|
||
[]
|
||
)
|
||
|
||
const visibleGoods = useMemo(() => {
|
||
// 先按效果图展示两列卡片,数据不够时也保持布局稳定
|
||
const list = goodsList || []
|
||
if (list.length <= 6) return list
|
||
return list.slice(0, 6)
|
||
}, [goodsList])
|
||
|
||
return (
|
||
<>
|
||
{/* Header区域 */}
|
||
{/*<Header />*/}
|
||
|
||
<View className="home-page">
|
||
{/* 顶部活动主视觉:使用 Banner 组件 */}
|
||
<Banner />
|
||
|
||
{/* 电子水票 */}
|
||
<View className="ticket-card">
|
||
<View className="ticket-card__head">
|
||
<Text className="ticket-card__title">电子水票</Text>
|
||
<Text className="ticket-card__count">
|
||
您还有 <Text className="ticket-card__countNum">{ticketTotal}</Text> 张水票
|
||
</Text>
|
||
</View>
|
||
|
||
<View className="ticket-card__body">
|
||
<View className="shortcut-grid">
|
||
{shortcuts.map((item) => (
|
||
<View
|
||
key={item.key}
|
||
className="shortcut-grid__item"
|
||
onClick={item.onClick}
|
||
>
|
||
<View className="shortcut-grid__icon">{item.icon}</View>
|
||
<Text className="shortcut-grid__text">{item.title}</Text>
|
||
</View>
|
||
))}
|
||
</View>
|
||
</View>
|
||
</View>
|
||
|
||
<View className="ticket-card" onClick={() => Taro.navigateTo({ url: `/shop/category/index?id=4560` })}>
|
||
<View className="ticket-card__head">
|
||
<Text className="ticket-card__title">政企采购专区</Text>
|
||
<ArrowRight className={'text-gray-50'} size={16} />
|
||
</View>
|
||
</View>
|
||
|
||
<View className="ticket-card" onClick={() => Taro.navigateTo({ url: `/shop/category/index?id=4556` })}>
|
||
<View className="ticket-card__head">
|
||
<Text className="ticket-card__title">桂乐淘·福利惊爆区</Text>
|
||
<ArrowRight className={'text-gray-50'} size={16} />
|
||
</View>
|
||
</View>
|
||
|
||
{/*分类Tabs*/}
|
||
<ScrollView className="home-tabs" scrollX enableFlex>
|
||
<View className="home-tabs__inner">
|
||
{tabs.map((tab) => {
|
||
const active = tab.key === activeTabKey
|
||
return (
|
||
<View
|
||
key={tab.key}
|
||
className={`home-tabs__item ${active ? 'home-tabs__item--active' : ''}`}
|
||
onClick={() => setActiveTabKey(tab.key)}
|
||
>
|
||
<Text className="home-tabs__itemText">{tab.title}</Text>
|
||
</View>
|
||
)
|
||
})}
|
||
</View>
|
||
</ScrollView>
|
||
{/* 商品列表 */}
|
||
<View className="goods-grid">
|
||
{visibleGoods.map((item) => (
|
||
<View key={item.goodsId} className="goods-card">
|
||
<View className="goods-card__imgWrap">
|
||
<Image
|
||
className="goods-card__img"
|
||
src={item.image || ''}
|
||
mode="aspectFill"
|
||
lazyLoad={false}
|
||
onClick={() =>
|
||
Taro.navigateTo({ url: `/shop/goodsDetail/index?id=${item.goodsId}` })
|
||
}
|
||
/>
|
||
</View>
|
||
|
||
<View className="goods-card__body">
|
||
<Text className="goods-card__title">{item.name}</Text>
|
||
<View className="goods-card__meta">
|
||
<Text className="goods-card__sold">已购:{item.sales || 0}人</Text>
|
||
<View className="goods-card__price">
|
||
<Text className="goods-card__priceUnit">¥</Text>
|
||
<Text className="goods-card__priceValue">{item.buyingPrice}</Text>
|
||
</View>
|
||
</View>
|
||
|
||
<View className="goods-card__actions">
|
||
{/*<View*/}
|
||
{/* className="goods-card__btn goods-card__btn--ghost"*/}
|
||
{/* onClick={() => {*/}
|
||
{/* if (!ensureLoggedIn('/shop/orderConfirm/index?goodsId=10074')) return*/}
|
||
{/* Taro.navigateTo({ url: '/shop/orderConfirm/index?goodsId=10074' })*/}
|
||
{/* }}*/}
|
||
{/*>*/}
|
||
{/* <Text className="goods-card__btnText">买水票更优惠</Text>*/}
|
||
{/*</View>*/}
|
||
<View
|
||
className="goods-card__btn goods-card__btn--primary"
|
||
onClick={() =>
|
||
Taro.navigateTo({ url: `/shop/goodsDetail/index?id=${item.goodsId}` })
|
||
}
|
||
>
|
||
<Text className="goods-card__btnText goods-card__btnText--primary">立即购买</Text>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
))}
|
||
</View>
|
||
|
||
</View>
|
||
</>
|
||
)
|
||
}
|
||
|
||
export default Home
|