|
|
@@ -39,30 +39,30 @@ Draft
|
|
|
- [ ] 应用商品卡片间距和布局
|
|
|
- [ ] 应用主色调(#fa550f, #fa4126)
|
|
|
- [ ] 集成TDesign MiniProgram组件 (AC: 1, 5)
|
|
|
- - [ ] 安装TDesign原生小程序组件库依赖
|
|
|
- - [ ] 安装 `tdesign-miniprogram`
|
|
|
- - [ ] 在 `mini/package.json` 中添加依赖
|
|
|
- - [ ] 配置Taro项目支持原生小程序组件
|
|
|
- - [ ] 在 `mini/config/index.js` 中配置小程序组件路径
|
|
|
- - [ ] 在 `mini/app.config.ts` 中配置usingComponents
|
|
|
+ - [ ] 创建Taro React版本的TDesign组件
|
|
|
+ - [ ] 创建 `mini/src/components/tdesign-search/index.tsx` - Search组件
|
|
|
+ - [ ] 创建 `mini/src/components/tdesign-swiper/index.tsx` - Swiper组件
|
|
|
+ - [ ] 创建 `mini/src/components/tdesign-icon/index.tsx` - Icon组件
|
|
|
+ - [ ] 创建 `mini/src/components/tdesign-toast/index.tsx` - Toast组件
|
|
|
+ - [ ] 创建 `mini/src/components/tdesign-tabs/index.tsx` - Tabs组件
|
|
|
- [ ] 使用TDesign search组件实现搜索栏
|
|
|
- - [ ] 在首页组件中使用 `t-search` 组件
|
|
|
+ - [ ] 在首页组件中导入自定义Search组件
|
|
|
- [ ] 配置搜索栏属性:placeholder、disabled、shape等
|
|
|
- [ ] 应用tcb-shop-demo的搜索栏样式(圆角32rpx,高度64rpx)
|
|
|
- [ ] 使用TDesign swiper组件实现轮播图
|
|
|
- - [ ] 在首页组件中使用 `t-swiper` 组件
|
|
|
- - [ ] 配置轮播图属性:autoplay、interval、indicator-dots等
|
|
|
+ - [ ] 在首页组件中导入自定义Swiper组件
|
|
|
+ - [ ] 配置轮播图属性:autoplay、interval、indicatorDots等
|
|
|
- [ ] 实现轮播图数据绑定和图片展示
|
|
|
- [ ] 使用TDesign icon组件实现图标
|
|
|
- - [ ] 在首页组件中使用 `t-icon` 组件
|
|
|
+ - [ ] 在首页组件中导入自定义Icon组件
|
|
|
- [ ] 使用搜索图标、购物车图标等
|
|
|
- [ ] 配置图标颜色和大小匹配tcb-shop-demo设计
|
|
|
- [ ] 使用TDesign toast组件实现提示
|
|
|
- - [ ] 在首页组件中使用 `t-toast` 组件
|
|
|
+ - [ ] 在首页组件中导入自定义Toast组件
|
|
|
- [ ] 实现加载状态、成功提示、错误提示等
|
|
|
- [ ] 配置Toast样式和位置
|
|
|
- [ ] 使用TDesign tabs组件实现分类切换
|
|
|
- - [ ] 在首页组件中使用 `t-tabs` 和 `t-tab-panel` 组件
|
|
|
+ - [ ] 在首页组件中导入自定义Tabs组件
|
|
|
- [ ] 配置分类数据源和切换逻辑
|
|
|
- [ ] 实现分类切换时的商品列表更新
|
|
|
- [ ] 测试和验证 (AC: 5)
|
|
|
@@ -77,8 +77,8 @@ Draft
|
|
|
- **前端框架**: React 18.0.0
|
|
|
- **小程序框架**: Taro 4.1.4
|
|
|
- **样式系统**: Tailwind CSS + 自定义CSS (tcb-theme.css)
|
|
|
-- **组件库**: TDesign原生小程序组件 (tdesign-miniprogram)
|
|
|
-- **集成方式**: Taro中使用原生小程序组件
|
|
|
+- **组件库**: 自定义Taro React组件 (基于TDesign设计规范)
|
|
|
+- **集成方式**: 直接使用Taro React组件,无需原生组件集成
|
|
|
|
|
|
### 项目结构信息 [Source: architecture/source-tree.md]
|
|
|
- **首页位置**: `mini/src/pages/index/index.tsx`
|
|
|
@@ -107,118 +107,151 @@ Draft
|
|
|
- **主色调**: 搜索图标颜色、购物车按钮颜色、选中状态颜色使用 #fa550f 和 #fa4126
|
|
|
|
|
|
### 组件依赖
|
|
|
-- **TDesign原生小程序组件**: t-search, t-swiper, t-icon, t-toast, t-tabs
|
|
|
+- **自定义Taro React组件**: TDesignSearch, TDesignSwiper, TDesignIcon, TDesignToast, TDesignTabs
|
|
|
- **自定义组件**: goods-list, goods-card, load-more
|
|
|
|
|
|
-### TDesign原生小程序组件集成说明
|
|
|
+### TDesign组件转写说明
|
|
|
|
|
|
-#### 1. 安装依赖
|
|
|
-```bash
|
|
|
-cd mini
|
|
|
-npm install tdesign-miniprogram
|
|
|
-```
|
|
|
-
|
|
|
-#### 2. 配置Taro项目
|
|
|
-
|
|
|
-**在 `mini/config/index.js` 中配置组件路径:**
|
|
|
-```javascript
|
|
|
-const config = {
|
|
|
- // ... 其他配置
|
|
|
- copy: {
|
|
|
- patterns: [
|
|
|
- {
|
|
|
- from: 'node_modules/tdesign-miniprogram/miniprogram_dist/',
|
|
|
- to: 'tdesign/',
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
-}
|
|
|
-```
|
|
|
+#### 1. 组件创建策略
|
|
|
+- 基于TDesign原生组件源码转写成Taro React组件
|
|
|
+- 保持TDesign的设计规范和交互体验
|
|
|
+- 使用React Hooks和Taro API实现功能
|
|
|
+- 应用tcb-shop-demo的主题样式
|
|
|
|
|
|
-**在 `mini/app.config.ts` 中注册全局组件:**
|
|
|
-```typescript
|
|
|
-export default defineAppConfig({
|
|
|
- usingComponents: {
|
|
|
- 't-search': 'tdesign/search/index',
|
|
|
- 't-swiper': 'tdesign/swiper/index',
|
|
|
- 't-icon': 'tdesign/icon/index',
|
|
|
- 't-toast': 'tdesign/toast/index',
|
|
|
- 't-tabs': 'tdesign/tabs/index',
|
|
|
- 't-tab-panel': 'tdesign/tabs/tab-panel/index',
|
|
|
- },
|
|
|
-})
|
|
|
-```
|
|
|
-
|
|
|
-#### 3. 组件使用示例
|
|
|
+#### 2. 组件实现示例
|
|
|
|
|
|
-**Search组件**
|
|
|
+**Search组件 (mini/src/components/tdesign-search/index.tsx)**
|
|
|
```tsx
|
|
|
-<t-search
|
|
|
- placeholder="搜索商品"
|
|
|
- disabled={false}
|
|
|
- shape="round"
|
|
|
- class="rounded-[32rpx] h-[64rpx]"
|
|
|
-/>
|
|
|
-```
|
|
|
+import { useState } from 'react'
|
|
|
+import { View, Input } from '@tarojs/components'
|
|
|
+import TDesignIcon from '../tdesign-icon'
|
|
|
+
|
|
|
+interface SearchProps {
|
|
|
+ placeholder?: string
|
|
|
+ disabled?: boolean
|
|
|
+ shape?: 'round' | 'square'
|
|
|
+ value?: string
|
|
|
+ onChange?: (value: string) => void
|
|
|
+ onFocus?: () => void
|
|
|
+ onBlur?: () => void
|
|
|
+ onSubmit?: (value: string) => void
|
|
|
+}
|
|
|
|
|
|
-**Swiper组件**
|
|
|
-```tsx
|
|
|
-<t-swiper
|
|
|
- autoplay
|
|
|
- interval={3000}
|
|
|
- indicator-dots
|
|
|
->
|
|
|
- {banners.map((banner, index) => (
|
|
|
- <swiper-item key={index}>
|
|
|
- <image src={banner.image} mode="aspectFill" />
|
|
|
- </swiper-item>
|
|
|
- ))}
|
|
|
-</t-swiper>
|
|
|
+export default function TDesignSearch({
|
|
|
+ placeholder = '搜索商品',
|
|
|
+ disabled = false,
|
|
|
+ shape = 'round',
|
|
|
+ value = '',
|
|
|
+ onChange,
|
|
|
+ onFocus,
|
|
|
+ onBlur,
|
|
|
+ onSubmit
|
|
|
+}: SearchProps) {
|
|
|
+ const [focused, setFocused] = useState(false)
|
|
|
+
|
|
|
+ const handleInput = (e) => {
|
|
|
+ onChange?.(e.detail.value)
|
|
|
+ }
|
|
|
+
|
|
|
+ const handleFocus = () => {
|
|
|
+ setFocused(true)
|
|
|
+ onFocus?.()
|
|
|
+ }
|
|
|
+
|
|
|
+ const handleBlur = () => {
|
|
|
+ setFocused(false)
|
|
|
+ onBlur?.()
|
|
|
+ }
|
|
|
+
|
|
|
+ const handleConfirm = (e) => {
|
|
|
+ onSubmit?.(e.detail.value)
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <View className={`tdesign-search tdesign-search--${shape}`}>
|
|
|
+ <View className={`tdesign-search__input-box ${focused ? 'tdesign-search__input-box--focused' : ''}`}>
|
|
|
+ <TDesignIcon name="search" size="32rpx" color="#fa550f" />
|
|
|
+ <Input
|
|
|
+ type="text"
|
|
|
+ placeholder={placeholder}
|
|
|
+ disabled={disabled}
|
|
|
+ value={value}
|
|
|
+ onInput={handleInput}
|
|
|
+ onFocus={handleFocus}
|
|
|
+ onBlur={handleBlur}
|
|
|
+ onConfirm={handleConfirm}
|
|
|
+ className="tdesign-search__input"
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ )
|
|
|
+}
|
|
|
```
|
|
|
|
|
|
-**Icon组件**
|
|
|
+**Icon组件 (mini/src/components/tdesign-icon/index.tsx)**
|
|
|
```tsx
|
|
|
-<t-icon name="search" size="32rpx" color="#fa550f" />
|
|
|
-<t-icon name="cart" size="32rpx" color="#fa550f" />
|
|
|
-```
|
|
|
+import { View } from '@tarojs/components'
|
|
|
|
|
|
-**Toast组件**
|
|
|
-```tsx
|
|
|
-// 在TSX中需要通过ref调用
|
|
|
-import { createSelectorQuery } from '@tarojs/taro'
|
|
|
-
|
|
|
-const showToast = () => {
|
|
|
- const query = createSelectorQuery()
|
|
|
- query.select('#toast').node((res) => {
|
|
|
- const toast = res.node
|
|
|
- toast.show({
|
|
|
- message: '操作成功',
|
|
|
- theme: 'success',
|
|
|
- duration: 2000,
|
|
|
- })
|
|
|
- }).exec()
|
|
|
+interface IconProps {
|
|
|
+ name: string
|
|
|
+ size?: string
|
|
|
+ color?: string
|
|
|
}
|
|
|
|
|
|
-// 在render中
|
|
|
-<t-toast id="toast" />
|
|
|
+export default function TDesignIcon({ name, size = '32rpx', color = '#fa550f' }: IconProps) {
|
|
|
+ return (
|
|
|
+ <View
|
|
|
+ className={`tdesign-icon tdesign-icon--${name}`}
|
|
|
+ style={{ fontSize: size, color }}
|
|
|
+ >
|
|
|
+ {/* 使用Unicode或SVG图标 */}
|
|
|
+ </View>
|
|
|
+ )
|
|
|
+}
|
|
|
```
|
|
|
|
|
|
-**Tabs组件**
|
|
|
+**Swiper组件 (mini/src/components/tdesign-swiper/index.tsx)**
|
|
|
```tsx
|
|
|
-<t-tabs value={activeTab} bindchange={handleTabChange}>
|
|
|
- {categories.map(category => (
|
|
|
- <t-tab-panel key={category.id} label={category.name} value={category.id}>
|
|
|
- <GoodsList categoryId={category.id} />
|
|
|
- </t-tab-panel>
|
|
|
- ))}
|
|
|
-</t-tabs>
|
|
|
+import { useState } from 'react'
|
|
|
+import { Swiper, SwiperItem, Image } from '@tarojs/components'
|
|
|
+
|
|
|
+interface SwiperProps {
|
|
|
+ images: string[]
|
|
|
+ autoplay?: boolean
|
|
|
+ interval?: number
|
|
|
+ indicatorDots?: boolean
|
|
|
+}
|
|
|
+
|
|
|
+export default function TDesignSwiper({
|
|
|
+ images = [],
|
|
|
+ autoplay = true,
|
|
|
+ interval = 3000,
|
|
|
+ indicatorDots = true
|
|
|
+}: SwiperProps) {
|
|
|
+ return (
|
|
|
+ <Swiper
|
|
|
+ className="tdesign-swiper"
|
|
|
+ autoplay={autoplay}
|
|
|
+ interval={interval}
|
|
|
+ indicatorDots={indicatorDots}
|
|
|
+ indicatorColor="#999"
|
|
|
+ indicatorActiveColor="#fa550f"
|
|
|
+ >
|
|
|
+ {images.map((image, index) => (
|
|
|
+ <SwiperItem key={index}>
|
|
|
+ <Image src={image} mode="aspectFill" className="tdesign-swiper__image" />
|
|
|
+ </SwiperItem>
|
|
|
+ ))}
|
|
|
+ </Swiper>
|
|
|
+ )
|
|
|
+}
|
|
|
```
|
|
|
|
|
|
-#### 4. 样式集成
|
|
|
-- 使用Tailwind CSS类名覆盖TDesign组件默认样式
|
|
|
+#### 3. 样式集成
|
|
|
+- 使用Tailwind CSS类名和自定义CSS
|
|
|
- 应用tcb-theme.css中的主题变量
|
|
|
-- 确保组件样式与tcb-shop-demo设计保持一致
|
|
|
-- 注意:原生小程序组件使用 `class` 属性而不是 `className`
|
|
|
+- 保持与tcb-shop-demo设计的一致性
|
|
|
+- 使用标准的React className属性
|
|
|
|
|
|
### Testing
|
|
|
|