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>
Showing
3 changed files
with
47 additions
and
23 deletions
| ... | @@ -35,7 +35,7 @@ declare module 'vue' { | ... | @@ -35,7 +35,7 @@ declare module 'vue' { |
| 35 | PdfPreview: typeof import('./src/components/PdfPreview.vue')['default'] | 35 | PdfPreview: typeof import('./src/components/PdfPreview.vue')['default'] |
| 36 | Picker: typeof import('./src/components/time-picker-data/picker.vue')['default'] | 36 | Picker: typeof import('./src/components/time-picker-data/picker.vue')['default'] |
| 37 | PlanFormContainer: typeof import('./src/components/PlanFormContainer.vue')['default'] | 37 | PlanFormContainer: typeof import('./src/components/PlanFormContainer.vue')['default'] |
| 38 | - PlanPopup: typeof import('./src/components/PlanSchemes/PlanPopup.vue')['default'] | 38 | + PlanPopup: typeof import('./src/components/PlanPopup/index.vue')['default'] |
| 39 | PosterBuilder: typeof import('./src/components/PosterBuilder/index.vue')['default'] | 39 | PosterBuilder: typeof import('./src/components/PosterBuilder/index.vue')['default'] |
| 40 | ProductCard: typeof import('./src/components/ProductCard.vue')['default'] | 40 | ProductCard: typeof import('./src/components/ProductCard.vue')['default'] |
| 41 | QrCode: typeof import('./src/components/qrCode.vue')['default'] | 41 | QrCode: typeof import('./src/components/qrCode.vue')['default'] | ... | ... |
| ... | @@ -5,6 +5,29 @@ | ... | @@ -5,6 +5,29 @@ |
| 5 | 5 | ||
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | +## [2026-02-06] - 优化产品中心列表UI (布局调整) | ||
| 9 | + | ||
| 10 | +### 优化 | ||
| 11 | +- 增加产品卡片图片和高度(从 200rpx 增加到 220rpx),缓解内容拥挤感 | ||
| 12 | +- 调整标题和标签间距,使布局更紧凑 | ||
| 13 | +- 使用 `mt-auto` 将操作按钮组沉底,确保与上方标签保持合理间距,并使卡片视觉重心更稳 | ||
| 14 | + | ||
| 15 | +### 技术实现 | ||
| 16 | +- 图片容器大小:`w-[220rpx] h-[220rpx]` | ||
| 17 | +- 按钮组:添加 `mt-auto` | ||
| 18 | +- 标题间距:`mb-[12rpx]` | ||
| 19 | +- 标签间距:`mb-[8rpx]` | ||
| 20 | + | ||
| 21 | +## [2026-02-06] - 优化产品中心列表UI | ||
| 22 | + | ||
| 23 | +### 优化 | ||
| 24 | +- 调整产品列表动态标签的间距,修复 gap 属性拼写错误 | ||
| 25 | +- 将产品卡片右侧的图标按钮组改为更直观的纯文字按钮("详情"、"计划书") | ||
| 26 | + | ||
| 27 | +### 技术实现 | ||
| 28 | +- 修复 `gap-[8rpx` 为 `gap-[8rpx]`,增加标签间距 | ||
| 29 | +- 替换 `IconFont` 组件为带样式的 `view` 标签,统一按钮风格 | ||
| 30 | + | ||
| 8 | ## [2026-02-06] - 添加 mock 数据支持并修复滚动加载功能 | 31 | ## [2026-02-06] - 添加 mock 数据支持并修复滚动加载功能 |
| 9 | 32 | ||
| 10 | ### 新增 | 33 | ### 新增 | ... | ... |
| ... | @@ -51,15 +51,17 @@ | ... | @@ -51,15 +51,17 @@ |
| 51 | <text class="text-gray-400 text-[28rpx]">加载中...</text> | 51 | <text class="text-gray-400 text-[28rpx]">加载中...</text> |
| 52 | </view> | 52 | </view> |
| 53 | 53 | ||
| 54 | - <!-- Product Grid --> | 54 | + <!-- Product List --> |
| 55 | - <view v-else class="flex flex-wrap justify-between px-[40rpx]"> | 55 | + <view v-else class="px-[40rpx]"> |
| 56 | <!-- Card Item --> | 56 | <!-- Card Item --> |
| 57 | <view v-for="(item, index) in products" :key="item.id" | 57 | <view v-for="(item, index) in products" :key="item.id" |
| 58 | - class="w-[48%] bg-white rounded-[24rpx] overflow-hidden mb-[24rpx] shadow-sm flex flex-col active:scale-[0.98] transition-transform duration-200" | 58 | + class="bg-white rounded-[24rpx] overflow-hidden mb-[24rpx] shadow-sm active:scale-[0.98] transition-transform duration-200" |
| 59 | :style="{ animationDelay: `${index * 50}ms` }" | 59 | :style="{ animationDelay: `${index * 50}ms` }" |
| 60 | - @tap="handleProductClick(item)"> | 60 | + > |
| 61 | + <!-- Product Content (Horizontal Layout) --> | ||
| 62 | + <view class="flex gap-[24rpx]" @tap="handleProductClick(item)"> | ||
| 61 | <!-- Image Container --> | 63 | <!-- Image Container --> |
| 62 | - <view class="relative w-full h-[200rpx] product-card-item"> | 64 | + <view class="relative w-[220rpx] h-[220rpx] flex-shrink-0 product-card-item"> |
| 63 | <image :src="item.cover_image" class="w-full h-full object-cover bg-gray-100" mode="aspectFill" /> | 65 | <image :src="item.cover_image" class="w-full h-full object-cover bg-gray-100" mode="aspectFill" /> |
| 64 | <!-- Tag --> | 66 | <!-- Tag --> |
| 65 | <view v-if="item.recommend === 'hot'" | 67 | <view v-if="item.recommend === 'hot'" |
| ... | @@ -69,16 +71,16 @@ | ... | @@ -69,16 +71,16 @@ |
| 69 | </view> | 71 | </view> |
| 70 | 72 | ||
| 71 | <!-- Content --> | 73 | <!-- Content --> |
| 72 | - <view class="p-[20rpx] flex flex-col flex-1"> | 74 | + <view class="flex-1 flex flex-col py-[20rpx] pr-[20rpx]"> |
| 73 | <!-- Title --> | 75 | <!-- Title --> |
| 74 | - <view class="text-[#1F2937] text-[28rpx] font-medium leading-[1.4] line-clamp-2 mb-[16rpx]"> | 76 | + <view class="text-[#1F2937] text-[28rpx] font-medium leading-[1.4] line-clamp-2 mb-[12rpx]"> |
| 75 | {{ item.product_name }} | 77 | {{ item.product_name }} |
| 76 | </view> | 78 | </view> |
| 77 | 79 | ||
| 78 | <!-- 动态标签 --> | 80 | <!-- 动态标签 --> |
| 79 | - <view v-if="item.tags && item.tags.length > 0" class="flex flex-wrap gap-[8rpx] mb-[16rpx]"> | 81 | + <view v-if="item.tags && item.tags.length > 0" class="flex flex-wrap gap-[8rpx] mb-[8rpx]"> |
| 80 | <view | 82 | <view |
| 81 | - v-for="tag in item.tags.slice(0, 2)" | 83 | + v-for="tag in item.tags" |
| 82 | :key="tag.id" | 84 | :key="tag.id" |
| 83 | class="text-[20rpx] px-[12rpx] py-[4rpx] rounded-full" | 85 | class="text-[20rpx] px-[12rpx] py-[4rpx] rounded-full" |
| 84 | :style="{ | 86 | :style="{ |
| ... | @@ -90,25 +92,24 @@ | ... | @@ -90,25 +92,24 @@ |
| 90 | </view> | 92 | </view> |
| 91 | </view> | 93 | </view> |
| 92 | 94 | ||
| 93 | - <!-- 按钮组 --> | 95 | + <!-- 按钮组 - 靠右对齐(纯文字按钮) --> |
| 94 | - <view class="flex gap-[12rpx] mt-auto"> | 96 | + <view class="flex gap-[16rpx] ml-auto items-center mt-auto" @tap.stop> |
| 95 | - <nut-button | 97 | + <!-- 详情按钮 --> |
| 96 | - plain | 98 | + <view |
| 97 | - color="#2563EB" | 99 | + class="text-[24rpx] text-[#2563EB] bg-blue-50 px-[24rpx] py-[8rpx] rounded-full active:bg-blue-100 transition-colors duration-200" |
| 98 | - size="small" | ||
| 99 | - class="flex-1 !h-[56rpx] !rounded-[12rpx] !text-[22rpx] !m-0 !border-blue-600" | ||
| 100 | @tap.stop="handleProductClick(item)" | 100 | @tap.stop="handleProductClick(item)" |
| 101 | > | 101 | > |
| 102 | 详情 | 102 | 详情 |
| 103 | - </nut-button> | 103 | + </view> |
| 104 | - <nut-button | 104 | + |
| 105 | - color="#2563EB" | 105 | + <!-- 计划书按钮 --> |
| 106 | - size="small" | 106 | + <view |
| 107 | - class="flex-1 !h-[56rpx] !rounded-[12rpx] !text-[22rpx] !m-0" | 107 | + class="text-[24rpx] text-white bg-blue-500 px-[24rpx] py-[8rpx] rounded-full active:bg-blue-600 transition-colors duration-200" |
| 108 | @tap.stop="openPlanPopup(item)" | 108 | @tap.stop="openPlanPopup(item)" |
| 109 | > | 109 | > |
| 110 | 计划书 | 110 | 计划书 |
| 111 | - </nut-button> | 111 | + </view> |
| 112 | + </view> | ||
| 112 | </view> | 113 | </view> |
| 113 | </view> | 114 | </view> |
| 114 | </view> | 115 | </view> | ... | ... |
-
Please register or login to post a comment