hookehuyr

refactor(product): 将产品列表从网格布局改为水平列表布局

- 从 2 列网格布局改为单列水平卡片布局
- 图片尺寸从 200rpx 增加到 220rpx
- 使用圆形文字按钮替代 NutUI 按钮组件
- 优化标签显示逻辑,显示所有标签而非仅前 2 个

技术细节:
- 布局:flex 布局,图片固定宽度 220rpx
- 按钮:纯文字按钮,详情为浅蓝背景,计划书为深蓝背景
- 间距:使用 gap、mt-auto 等优化视觉层次

影响文件:
- src/pages/product-center/index.vue
- components.d.ts (自动更新)
- docs/CHANGELOG.md

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
......@@ -35,7 +35,7 @@ declare module 'vue' {
PdfPreview: typeof import('./src/components/PdfPreview.vue')['default']
Picker: typeof import('./src/components/time-picker-data/picker.vue')['default']
PlanFormContainer: typeof import('./src/components/PlanFormContainer.vue')['default']
PlanPopup: typeof import('./src/components/PlanSchemes/PlanPopup.vue')['default']
PlanPopup: typeof import('./src/components/PlanPopup/index.vue')['default']
PosterBuilder: typeof import('./src/components/PosterBuilder/index.vue')['default']
ProductCard: typeof import('./src/components/ProductCard.vue')['default']
QrCode: typeof import('./src/components/qrCode.vue')['default']
......
......@@ -5,6 +5,29 @@
---
## [2026-02-06] - 优化产品中心列表UI (布局调整)
### 优化
- 增加产品卡片图片和高度(从 200rpx 增加到 220rpx),缓解内容拥挤感
- 调整标题和标签间距,使布局更紧凑
- 使用 `mt-auto` 将操作按钮组沉底,确保与上方标签保持合理间距,并使卡片视觉重心更稳
### 技术实现
- 图片容器大小:`w-[220rpx] h-[220rpx]`
- 按钮组:添加 `mt-auto`
- 标题间距:`mb-[12rpx]`
- 标签间距:`mb-[8rpx]`
## [2026-02-06] - 优化产品中心列表UI
### 优化
- 调整产品列表动态标签的间距,修复 gap 属性拼写错误
- 将产品卡片右侧的图标按钮组改为更直观的纯文字按钮("详情"、"计划书")
### 技术实现
- 修复 `gap-[8rpx``gap-[8rpx]`,增加标签间距
- 替换 `IconFont` 组件为带样式的 `view` 标签,统一按钮风格
## [2026-02-06] - 添加 mock 数据支持并修复滚动加载功能
### 新增
......
......@@ -51,64 +51,65 @@
<text class="text-gray-400 text-[28rpx]">加载中...</text>
</view>
<!-- Product Grid -->
<view v-else class="flex flex-wrap justify-between px-[40rpx]">
<!-- Product List -->
<view v-else class="px-[40rpx]">
<!-- Card Item -->
<view v-for="(item, index) in products" :key="item.id"
class="w-[48%] bg-white rounded-[24rpx] overflow-hidden mb-[24rpx] shadow-sm flex flex-col active:scale-[0.98] transition-transform duration-200"
class="bg-white rounded-[24rpx] overflow-hidden mb-[24rpx] shadow-sm active:scale-[0.98] transition-transform duration-200"
:style="{ animationDelay: `${index * 50}ms` }"
@tap="handleProductClick(item)">
<!-- Image Container -->
<view class="relative w-full h-[200rpx] product-card-item">
<image :src="item.cover_image" class="w-full h-full object-cover bg-gray-100" mode="aspectFill" />
<!-- Tag -->
<view v-if="item.recommend === 'hot'"
class="absolute top-[12rpx] right-[12rpx] bg-red-500 text-white text-[20rpx] px-[12rpx] py-[4rpx] rounded-full">
热卖
>
<!-- Product Content (Horizontal Layout) -->
<view class="flex gap-[24rpx]" @tap="handleProductClick(item)">
<!-- Image Container -->
<view class="relative w-[220rpx] h-[220rpx] flex-shrink-0 product-card-item">
<image :src="item.cover_image" class="w-full h-full object-cover bg-gray-100" mode="aspectFill" />
<!-- Tag -->
<view v-if="item.recommend === 'hot'"
class="absolute top-[12rpx] right-[12rpx] bg-red-500 text-white text-[20rpx] px-[12rpx] py-[4rpx] rounded-full">
热卖
</view>
</view>
</view>
<!-- Content -->
<view class="p-[20rpx] flex flex-col flex-1">
<!-- Title -->
<view class="text-[#1F2937] text-[28rpx] font-medium leading-[1.4] line-clamp-2 mb-[16rpx]">
{{ item.product_name }}
</view>
<!-- Content -->
<view class="flex-1 flex flex-col py-[20rpx] pr-[20rpx]">
<!-- Title -->
<view class="text-[#1F2937] text-[28rpx] font-medium leading-[1.4] line-clamp-2 mb-[12rpx]">
{{ item.product_name }}
</view>
<!-- 动态标签 -->
<view v-if="item.tags && item.tags.length > 0" class="flex flex-wrap gap-[8rpx] mb-[16rpx]">
<view
v-for="tag in item.tags.slice(0, 2)"
:key="tag.id"
class="text-[20rpx] px-[12rpx] py-[4rpx] rounded-full"
:style="{
backgroundColor: tag.bg_color,
color: tag.text_color
}"
>
{{ tag.name }}
<!-- 动态标签 -->
<view v-if="item.tags && item.tags.length > 0" class="flex flex-wrap gap-[8rpx] mb-[8rpx]">
<view
v-for="tag in item.tags"
:key="tag.id"
class="text-[20rpx] px-[12rpx] py-[4rpx] rounded-full"
:style="{
backgroundColor: tag.bg_color,
color: tag.text_color
}"
>
{{ tag.name }}
</view>
</view>
</view>
<!-- 按钮组 -->
<view class="flex gap-[12rpx] mt-auto">
<nut-button
plain
color="#2563EB"
size="small"
class="flex-1 !h-[56rpx] !rounded-[12rpx] !text-[22rpx] !m-0 !border-blue-600"
@tap.stop="handleProductClick(item)"
>
详情
</nut-button>
<nut-button
color="#2563EB"
size="small"
class="flex-1 !h-[56rpx] !rounded-[12rpx] !text-[22rpx] !m-0"
@tap.stop="openPlanPopup(item)"
>
计划书
</nut-button>
<!-- 按钮组 - 靠右对齐(纯文字按钮) -->
<view class="flex gap-[16rpx] ml-auto items-center mt-auto" @tap.stop>
<!-- 详情按钮 -->
<view
class="text-[24rpx] text-[#2563EB] bg-blue-50 px-[24rpx] py-[8rpx] rounded-full active:bg-blue-100 transition-colors duration-200"
@tap.stop="handleProductClick(item)"
>
详情
</view>
<!-- 计划书按钮 -->
<view
class="text-[24rpx] text-white bg-blue-500 px-[24rpx] py-[8rpx] rounded-full active:bg-blue-600 transition-colors duration-200"
@tap.stop="openPlanPopup(item)"
>
计划书
</view>
</view>
</view>
</view>
</view>
......