Procházet zdrojové kódy

✨ feat(goods-list): 实现商品列表组件

- 创建商品列表组件 (mini/src/components/goods-list/index.tsx)
- 实现flex布局,参照tcb-shop-demo实际布局
- 集成商品卡片组件,支持事件回调
- 更新故事文档,修正布局描述

🤖 Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname před 1 měsícem
rodič
revize
e006bf5cf6

+ 14 - 5
docs/stories/001.004.homepage-ui-refactor.md

@@ -28,11 +28,11 @@ Draft
   - [x] 参照 `tcb-shop-demo/components/goods-card/index.wxml` 实现商品卡片布局
   - [x] 实现图片、标题、价格、购物车按钮布局
   - [x] 应用tcb-shop-demo的商品卡片样式
-- [ ] 实现商品列表组件 (AC: 1)
-  - [ ] 创建 `mini/src/components/goods-list/index.tsx` 商品列表组件
-  - [ ] 参照 `tcb-shop-demo/components/goods-list/index.wxml` 实现列表结构
-  - [ ] 实现瀑布流布局
-  - [ ] 集成商品卡片组件
+- [x] 实现商品列表组件 (AC: 1)
+  - [x] 创建 `mini/src/components/goods-list/index.tsx` 商品列表组件
+  - [x] 参照 `tcb-shop-demo/components/goods-list/index.wxml` 实现列表结构
+  - [x] 实现flex布局(按tcb-shop-demo实际布局)
+  - [x] 集成商品卡片组件
 - [ ] 创建首页组件结构 (AC: 1)
   - [ ] 创建 `mini/src/pages/index/index.tsx` 首页组件
   - [ ] 参照 `tcb-shop-demo/pages/home/home.wxml` 实现页面结构
@@ -319,6 +319,13 @@ export default function TDesignSwiper({
 - ✅ 已修复:Tabs组件TypeScript编译错误
 - ✅ 已修复:商品卡片组件TypeScript编译错误
 - ✅ 已验证:TypeScript编译正常,无TDesign相关错误
+- ✅ 已完成:创建 `mini/src/components/goods-list/index.tsx` - 商品列表组件
+- ✅ 已完成:创建 `mini/src/components/goods-list/index.css` - 商品列表组件样式
+- ✅ 已对照:`tcb-shop-demo/components/goods-list/` 目录结构和功能
+- ✅ 已修正:布局从瀑布流改为flex布局(按tcb-shop-demo实际布局)
+- ✅ 已集成:商品卡片组件到商品列表组件
+- ✅ 已验证:商品列表组件TypeScript编译正常
+- ✅ 已验证:组件导入和依赖关系正确
 
 ### File List
 - **创建**: `mini/src/components/tdesign/search/index.tsx` - TDesign Search 组件
@@ -328,6 +335,8 @@ export default function TDesignSwiper({
 - **创建**: `mini/src/components/tdesign/tabs/index.tsx` - TDesign Tabs 组件
 - **创建**: `mini/src/components/goods-card/index.tsx` - 商品卡片组件
 - **创建**: `mini/src/components/goods-card/index.css` - 商品卡片组件样式
+- **创建**: `mini/src/components/goods-list/index.tsx` - 商品列表组件
+- **创建**: `mini/src/components/goods-list/index.css` - 商品列表组件样式
 - **创建**: `mini/src/components/tdesign/search/index.css` - Search 组件样式
 - **创建**: `mini/src/components/tdesign/swiper/index.css` - Swiper 组件样式
 - **创建**: `mini/src/components/tdesign/toast/index.css` - Toast 组件样式

+ 11 - 0
mini/src/components/goods-list/index.css

@@ -0,0 +1,11 @@
+.goods-list-wrap {
+  display: flex;
+  flex-flow: row wrap;
+  justify-content: space-between;
+  padding: 0;
+  background: #f5f5f5;
+}
+
+.goods-card-inside {
+  margin-bottom: 32rpx;
+}

+ 55 - 0
mini/src/components/goods-list/index.tsx

@@ -0,0 +1,55 @@
+import { View } from '@tarojs/components'
+import GoodsCard, { GoodsData } from '../goods-card'
+import './index.css'
+
+export interface GoodsListProps {
+  goodsList: GoodsData[]
+  id?: string
+  thresholds?: any[]
+  onClick?: (goods: GoodsData, index: number) => void
+  onAddCart?: (goods: GoodsData, index: number) => void
+  onThumbClick?: (goods: GoodsData, index: number) => void
+}
+
+export default function GoodsList({
+  goodsList = [],
+  id,
+  thresholds = [],
+  onClick,
+  onAddCart,
+  onThumbClick
+}: GoodsListProps) {
+  const independentID = id || `goods-list-${Math.floor(Math.random() * 10 ** 8)}`
+
+  const handleGoodsClick = (goods: GoodsData, index: number) => {
+    onClick?.(goods, index)
+  }
+
+  const handleAddCart = (goods: GoodsData, index: number) => {
+    onAddCart?.(goods, index)
+  }
+
+  const handleThumbClick = (goods: GoodsData, index: number) => {
+    onThumbClick?.(goods, index)
+  }
+
+  return (
+    <View
+      id={independentID}
+      className="goods-list-wrap"
+    >
+      {goodsList.map((item, index) => (
+        <GoodsCard
+          key={item.id || index}
+          id={`${independentID}-gd-${index}`}
+          data={item}
+          currency={item.currency || '¥'}
+          onClick={() => handleGoodsClick(item, index)}
+          onAddCart={() => handleAddCart(item, index)}
+          onThumbClick={() => handleThumbClick(item, index)}
+          className="goods-card-inside"
+        />
+      ))}
+    </View>
+  )
+}