|
|
@@ -1,25 +1,43 @@
|
|
|
import React from 'react'
|
|
|
import { View, Text, ScrollView } from '@tarojs/components'
|
|
|
-import { useInfiniteQuery } from '@tanstack/react-query'
|
|
|
+import { useInfiniteQuery, useQuery } from '@tanstack/react-query'
|
|
|
import { TabBarLayout } from '@/layouts/tab-bar-layout'
|
|
|
import TDesignSearch from '@/components/tdesign/search'
|
|
|
-import TDesignSwiper from '@/components/tdesign/swiper'
|
|
|
import GoodsList from '@/components/goods-list'
|
|
|
import { GoodsData } from '@/components/goods-card'
|
|
|
-import { goodsClient } from '@/api'
|
|
|
+import { goodsClient, advertisementClient } from '@/api'
|
|
|
import { InferResponseType } from 'hono'
|
|
|
import './index.css'
|
|
|
+import { Carousel } from '@/components/ui/carousel'
|
|
|
|
|
|
type GoodsResponse = InferResponseType<typeof goodsClient.$get, 200>
|
|
|
type Goods = GoodsResponse['data'][0]
|
|
|
+type AdvertisementResponse = InferResponseType<typeof advertisementClient.$get, 200>
|
|
|
+type Advertisement = AdvertisementResponse['data'][0]
|
|
|
|
|
|
const HomePage: React.FC = () => {
|
|
|
- // 模拟轮播图数据
|
|
|
- const imgSrcs = [
|
|
|
- 'https://via.placeholder.com/750x400/fa4126/ffffff?text=Banner1',
|
|
|
- 'https://via.placeholder.com/750x400/fa550f/ffffff?text=Banner2',
|
|
|
- 'https://via.placeholder.com/750x400/34c759/ffffff?text=Banner3'
|
|
|
- ]
|
|
|
+ // 广告数据查询
|
|
|
+ const {
|
|
|
+ data: advertisementData,
|
|
|
+ isLoading: isAdLoading,
|
|
|
+ error: adError
|
|
|
+ } = useQuery({
|
|
|
+ queryKey: ['home-advertisements'],
|
|
|
+ queryFn: async () => {
|
|
|
+ const response = await advertisementClient.$get({
|
|
|
+ query: {
|
|
|
+ // filters: JSON.stringify({ status: 1 }), // 暂时移除过滤条件
|
|
|
+ sortBy: 'sort', // 按sort字段排序
|
|
|
+ sortOrder: 'ASC'
|
|
|
+ }
|
|
|
+ })
|
|
|
+ if (response.status !== 200) {
|
|
|
+ throw new Error('获取广告数据失败')
|
|
|
+ }
|
|
|
+ return response.json()
|
|
|
+ },
|
|
|
+ staleTime: 5 * 60 * 1000, // 5分钟缓存
|
|
|
+ })
|
|
|
|
|
|
const {
|
|
|
data,
|
|
|
@@ -58,18 +76,26 @@ const HomePage: React.FC = () => {
|
|
|
// 数据转换:将API返回的商品数据转换为GoodsData接口格式
|
|
|
const convertToGoodsData = (goods: Goods): GoodsData => {
|
|
|
return {
|
|
|
- id: goods.id.toString(), // 将number类型的id转换为string
|
|
|
- name: goods.name,
|
|
|
- cover_image: goods.imageFile?.fullUrl || '',
|
|
|
- price: goods.price,
|
|
|
- originPrice: goods.originPrice,
|
|
|
- tags: goods.salesNum > 100 ? ['热销'] : ['新品']
|
|
|
+ id: goods?.id?.toString() || '', // 将number类型的id转换为string
|
|
|
+ name: goods?.name || '',
|
|
|
+ cover_image: goods?.imageFile?.fullUrl || '',
|
|
|
+ price: goods?.price || 0,
|
|
|
+ originPrice: goods?.originPrice || 0,
|
|
|
+ tags: (goods?.salesNum || 0) > 100 ? ['热销'] : ['新品']
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 转换后的商品列表
|
|
|
const goodsList = allGoods.map(convertToGoodsData)
|
|
|
|
|
|
+ // 广告数据转换:提取图片URL并过滤掉没有图片的广告
|
|
|
+ const finalImgSrcs = advertisementData?.data
|
|
|
+
|
|
|
+ // 错误处理
|
|
|
+ if (adError) {
|
|
|
+ console.error('广告数据获取失败:', adError)
|
|
|
+ }
|
|
|
+
|
|
|
// 触底加载更多
|
|
|
const handleScrollToLower = () => {
|
|
|
if (hasNextPage && !isFetchingNextPage) {
|
|
|
@@ -118,14 +144,26 @@ const HomePage: React.FC = () => {
|
|
|
|
|
|
{/* 轮播图 */}
|
|
|
<View className="swiper-wrap">
|
|
|
- {imgSrcs.length > 0 && (
|
|
|
- <TDesignSwiper
|
|
|
- images={imgSrcs}
|
|
|
- autoplay={true}
|
|
|
- interval={5000}
|
|
|
- indicatorDots={true}
|
|
|
- height="300rpx"
|
|
|
+ {isAdLoading ? (
|
|
|
+ <View className="loading-container">
|
|
|
+ <Text className="loading-text">广告加载中...</Text>
|
|
|
+ </View>
|
|
|
+ ) : adError ? (
|
|
|
+ <View className="error-container">
|
|
|
+ <Text className="error-text">广告加载失败</Text>
|
|
|
+ </View>
|
|
|
+ ) : finalImgSrcs && finalImgSrcs.length > 0 ? (
|
|
|
+ <Carousel
|
|
|
+ items={finalImgSrcs.filter(item => item.imageFile?.fullUrl).map((item) => ({
|
|
|
+ src: item.imageFile!.fullUrl
|
|
|
+ }))}
|
|
|
+ height={300}
|
|
|
+ className="h-100"
|
|
|
/>
|
|
|
+ ) : (
|
|
|
+ <View className="empty-container">
|
|
|
+ <Text className="empty-text">暂无广告</Text>
|
|
|
+ </View>
|
|
|
)}
|
|
|
</View>
|
|
|
</View>
|