|
|
@@ -5,12 +5,9 @@ import Taro from '@tarojs/taro'
|
|
|
import { goodsClient } from '@/api'
|
|
|
import { InferResponseType } from 'hono'
|
|
|
import { Navbar } from '@/components/ui/navbar'
|
|
|
-import { Card } from '@/components/ui/card'
|
|
|
-import { Button } from '@/components/ui/button'
|
|
|
import { useCart } from '@/utils/cart'
|
|
|
-import { Image } from '@/components/ui/image'
|
|
|
-import { Input } from '@/components/ui/input'
|
|
|
-import { TabBarLayout } from '@/layouts/tab-bar-layout'
|
|
|
+import GoodsList from '@/components/goods-list'
|
|
|
+import TDesignSearch from '@/components/tdesign/search'
|
|
|
|
|
|
type GoodsResponse = InferResponseType<typeof goodsClient.$get, 200>
|
|
|
type Goods = GoodsResponse['data'][0]
|
|
|
@@ -99,7 +96,7 @@ export default function GoodsListPage() {
|
|
|
}
|
|
|
|
|
|
return (
|
|
|
- <TabBarLayout activeKey="goods-list">
|
|
|
+ <View className="min-h-screen bg-white">
|
|
|
<Navbar
|
|
|
title="商品列表"
|
|
|
leftIcon="i-heroicons-chevron-left-20-solid"
|
|
|
@@ -115,37 +112,20 @@ export default function GoodsListPage() {
|
|
|
refresherTriggered={false}
|
|
|
onRefresherRefresh={onPullDownRefresh}
|
|
|
>
|
|
|
- <View className="px-4 py-4">
|
|
|
+ <View className="goods-page-container bg-[#f2f2f2] p-[20rpx_24rpx]">
|
|
|
{/* 搜索栏 */}
|
|
|
- <View className="bg-white rounded-2xl p-4 mb-4 shadow-lg">
|
|
|
- <View className="flex items-center space-x-3">
|
|
|
- <View className="flex-1 relative">
|
|
|
- <View className="absolute left-4 top-1/2 -translate-y-1/2">
|
|
|
- <View className="i-heroicons-magnifying-glass-20-solid w-5 h-5 text-gray-400" />
|
|
|
- </View>
|
|
|
- <Input
|
|
|
- type="text"
|
|
|
- placeholder="搜索你想要的商品..."
|
|
|
- className="w-full pl-12 pr-4 py-3 bg-gray-50 rounded-xl outline-none focus:bg-gray-100 transition-colors text-sm"
|
|
|
- value={searchKeyword}
|
|
|
- onChange={(value) => setSearchKeyword(value)}
|
|
|
- onConfirm={() => refetch()}
|
|
|
- />
|
|
|
- </View>
|
|
|
- {searchKeyword && (
|
|
|
- <Button
|
|
|
- size="sm"
|
|
|
- variant="ghost"
|
|
|
- className="!w-8 !h-8 !p-0"
|
|
|
- onClick={() => {
|
|
|
- setSearchKeyword('')
|
|
|
- refetch()
|
|
|
- }}
|
|
|
- >
|
|
|
- <View className="i-heroicons-x-mark-20-solid w-4 h-4 text-gray-500" />
|
|
|
- </Button>
|
|
|
- )}
|
|
|
- </View>
|
|
|
+ <View className="search-bar-container mb-4">
|
|
|
+ <TDesignSearch
|
|
|
+ placeholder="搜索你想要的商品..."
|
|
|
+ shape="round"
|
|
|
+ value={searchKeyword}
|
|
|
+ onChange={(value) => setSearchKeyword(value)}
|
|
|
+ onSubmit={() => refetch()}
|
|
|
+ onClear={() => {
|
|
|
+ setSearchKeyword('')
|
|
|
+ refetch()
|
|
|
+ }}
|
|
|
+ />
|
|
|
</View>
|
|
|
|
|
|
{/* 分类筛选 */}
|
|
|
@@ -175,88 +155,18 @@ export default function GoodsListPage() {
|
|
|
</View>
|
|
|
) : (
|
|
|
<>
|
|
|
- <View className="grid grid-cols-2 gap-4">
|
|
|
- {allGoods.map((goods) => (
|
|
|
- <Card
|
|
|
- key={goods.id}
|
|
|
- className="overflow-hidden bg-white rounded-2xl shadow-sm active:shadow-lg transition-all duration-300 active:scale-95"
|
|
|
- onClick={() => handleGoodsClick(goods)}
|
|
|
- >
|
|
|
- <View className="relative">
|
|
|
- <View className="w-full aspect-square bg-gradient-to-br from-gray-100 to-gray-200 overflow-hidden">
|
|
|
- {goods.imageFile?.fullUrl ? (
|
|
|
- <Image
|
|
|
- src={goods.imageFile.fullUrl}
|
|
|
- className="w-full h-full object-cover transition-transform duration-300 active:scale-110"
|
|
|
- mode="aspectFill"
|
|
|
- />
|
|
|
- ) : (
|
|
|
- <View className="w-full h-full flex items-center justify-center text-gray-400">
|
|
|
- <View className="i-heroicons-photo-20-solid w-12 h-12" />
|
|
|
- </View>
|
|
|
- )}
|
|
|
- </View>
|
|
|
-
|
|
|
- {goods.stock <= 0 && (
|
|
|
- <View className="absolute inset-0 bg-black/50 flex items-center justify-center">
|
|
|
- <Text className="text-white font-bold text-sm">已售罄</Text>
|
|
|
- </View>
|
|
|
- )}
|
|
|
-
|
|
|
- {goods.stock > 0 && goods.salesNum > 100 && (
|
|
|
- <View className="absolute top-2 left-2 bg-gradient-to-r from-orange-500 to-red-500 text-white text-xs px-2 py-1 rounded-full shadow-lg">
|
|
|
- 热销
|
|
|
- </View>
|
|
|
- )}
|
|
|
-
|
|
|
- {goods.stock > 0 && goods.salesNum <= 100 && (
|
|
|
- <View className="absolute top-2 right-2 bg-white/90 backdrop-blur text-gray-700 text-xs px-2 py-1 rounded-full shadow-md">
|
|
|
- 库存{goods.stock}
|
|
|
- </View>
|
|
|
- )}
|
|
|
- </View>
|
|
|
-
|
|
|
- <View className="p-3">
|
|
|
- <Text className="text-sm font-semibold text-gray-900 mb-1 line-clamp-2 h-10 leading-tight">
|
|
|
- {goods.name}
|
|
|
- </Text>
|
|
|
-
|
|
|
- <Text className="text-xs text-gray-500 mb-2 line-clamp-1">
|
|
|
- {goods.instructions || '优质商品,值得信赖'}
|
|
|
- </Text>
|
|
|
-
|
|
|
- <View className="flex items-center justify-between">
|
|
|
- <View>
|
|
|
- <Text className="text-red-500 text-lg font-bold">
|
|
|
- ¥{goods.price.toFixed(2)}
|
|
|
- </Text>
|
|
|
- <Text className="text-xs text-gray-400 ml-1">
|
|
|
- 已售{goods.salesNum}
|
|
|
- </Text>
|
|
|
- </View>
|
|
|
-
|
|
|
- <Button
|
|
|
- size="sm"
|
|
|
- className={`!w-8 !h-8 !p-0 rounded-full transition-all ${
|
|
|
- goods.stock > 0
|
|
|
- ? 'bg-gradient-to-r from-blue-500 to-blue-600 text-white shadow-md active:shadow-lg'
|
|
|
- : 'bg-gray-200 text-gray-400'
|
|
|
- }`}
|
|
|
- onClick={(e) => {
|
|
|
- e.stopPropagation()
|
|
|
- if (goods.stock > 0) {
|
|
|
- handleAddToCart(goods)
|
|
|
- }
|
|
|
- }}
|
|
|
- disabled={goods.stock <= 0}
|
|
|
- >
|
|
|
- <View className={`w-4 h-4 ${goods.stock > 0 ? 'i-heroicons-plus-20-solid' : 'i-heroicons-minus-20-solid'}`} />
|
|
|
- </Button>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- </Card>
|
|
|
- ))}
|
|
|
- </View>
|
|
|
+ <GoodsList
|
|
|
+ goodsList={allGoods.map(goods => ({
|
|
|
+ id: goods.id.toString(),
|
|
|
+ name: goods.name,
|
|
|
+ cover_image: goods.imageFile?.fullUrl,
|
|
|
+ price: goods.price,
|
|
|
+ originPrice: goods.originPrice,
|
|
|
+ tags: goods.stock <= 0 ? ['已售罄'] : goods.salesNum > 100 ? ['热销'] : []
|
|
|
+ }))}
|
|
|
+ onClick={(goods) => handleGoodsClick(allGoods.find(g => g.id.toString() === goods.id)!)}
|
|
|
+ onAddCart={(goods) => handleAddToCart(allGoods.find(g => g.id.toString() === goods.id)!)}
|
|
|
+ />
|
|
|
|
|
|
{isFetchingNextPage && (
|
|
|
<View className="flex justify-center py-4 mt-4">
|
|
|
@@ -285,6 +195,6 @@ export default function GoodsListPage() {
|
|
|
)}
|
|
|
</View>
|
|
|
</ScrollView>
|
|
|
- </TabBarLayout>
|
|
|
+ </View>
|
|
|
)
|
|
|
}
|