fix(IconFont): 修复动态切换图标名称时图标不更新的问题
为 IconFont 组件添加 key 属性,强制其在图标名称变化时重新渲染,解决因 NutUI 组件未正确响应 props 变化导致的问题。 同时优化产品详情页的收藏图标交互与视觉: - 将收藏按钮移至标题右侧,采用 Flexbox 布局避免长标题遮挡 - 统一使用 NutUI 标准图标名称(Heart/HeartFill) - 为收藏按钮添加圆形背景与阴影,增强视觉反馈 - 优化热卖标签样式,采用玻璃拟态设计
Showing
3 changed files
with
29 additions
and
14 deletions
| ... | @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. | ... | @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. |
| 5 | ## [Unreleased] | 5 | ## [Unreleased] |
| 6 | 6 | ||
| 7 | ### Changed | 7 | ### Changed |
| 8 | +- 优化 "产品详情" 页面 (`src/pages/product-detail`): | ||
| 9 | + - 修复收藏图标状态切换无效的问题(修正图标名称为 NutUI 标准命名 `Heart`/`HeartFill`) | ||
| 10 | + - 优化顶部操作区视觉体验,统一 "热卖" 标签与 "收藏" 按钮风格,采用玻璃拟态(Glassmorphism)设计 | ||
| 11 | + - 增强收藏按钮交互反馈,增加白色圆形背景与阴影,确保在任意 Banner 背景下均清晰可见 | ||
| 12 | + - 调整产品标题与收藏按钮布局: | ||
| 13 | + - 将收藏按钮移至标题右侧,采用 Flexbox 布局实现左右对齐 | ||
| 14 | + - 标题自适应占据剩余空间,收藏按钮固定在右侧,避免长标题遮挡按钮 | ||
| 15 | + | ||
| 16 | +### Fixed | ||
| 17 | +- 修复 `IconFont` 组件在动态切换 `name` 属性时图标不更新的问题: | ||
| 18 | + - 问题原因:NutUI 的 `IconFont` 组件在某些环境下未正确响应 props 变化 | ||
| 19 | + - 解决方案:在 `src/components/IconFont.vue` 中添加 `:key="name"`,强制组件在图标名称变化时重新渲染 | ||
| 20 | + | ||
| 21 | +### Changed | ||
| 8 | - 全量替换项目内 IconFont 调用为 `@nutui/icons-vue-taro` 的 `IconFont` 组件,统一使用 `class` 属性,移除自定义封装组件依赖 | 22 | - 全量替换项目内 IconFont 调用为 `@nutui/icons-vue-taro` 的 `IconFont` 组件,统一使用 `class` 属性,移除自定义封装组件依赖 |
| 9 | - 优化 "帮助中心" 页面 (`src/pages/help-center`): | 23 | - 优化 "帮助中心" 页面 (`src/pages/help-center`): |
| 10 | - 重构 "联系客服" 弹窗,将硬编码数据提取为 `contactMethods` 数组,并优化样式布局 | 24 | - 重构 "联系客服" 弹窗,将硬编码数据提取为 `contactMethods` 数组,并优化样式布局 | ... | ... |
| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | * @Description: 图标字体组件 | 6 | * @Description: 图标字体组件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <IconFontBase :name="name" :size="size" :color="color" :class="customClass" /> | 9 | + <IconFontBase :key="name" :name="name" :size="size" :color="color" :class="customClass" /> |
| 10 | </template> | 10 | </template> |
| 11 | 11 | ||
| 12 | <script setup> | 12 | <script setup> | ... | ... |
| ... | @@ -13,29 +13,30 @@ | ... | @@ -13,29 +13,30 @@ |
| 13 | :src="bannerImage" | 13 | :src="bannerImage" |
| 14 | mode="aspectFill" | 14 | mode="aspectFill" |
| 15 | /> | 15 | /> |
| 16 | - <div class="absolute top-[32rpx] right-[32rpx] flex gap-[16rpx]"> | 16 | + <div class="absolute top-[32rpx] right-[32rpx] flex items-center gap-[16rpx]"> |
| 17 | <!-- Hot Tag --> | 17 | <!-- Hot Tag --> |
| 18 | - <div class="bg-red-500 text-white text-[24rpx] px-[16rpx] py-[8rpx] rounded-full shadow-sm"> | 18 | + <div class="bg-red-500 text-white text-[24rpx] px-[20rpx] py-[10rpx] rounded-full shadow-sm backdrop-blur-sm bg-opacity-90"> |
| 19 | 热卖 | 19 | 热卖 |
| 20 | </div> | 20 | </div> |
| 21 | + </div> | ||
| 22 | + </div> | ||
| 23 | + | ||
| 24 | + <!-- Product Header --> | ||
| 25 | + <div class="relative mt-[-40rpx] bg-white rounded-t-[40rpx] px-[40rpx] pt-[48rpx] pb-[40rpx] z-10"> | ||
| 26 | + <div class="flex items-start justify-between mb-[24rpx]"> | ||
| 27 | + <h1 class="text-[#1F2937] text-[44rpx] font-bold flex-1 mr-[24rpx] leading-[1.2]">终身寿险尊享版</h1> | ||
| 21 | <!-- Favorite Button --> | 28 | <!-- Favorite Button --> |
| 22 | <div | 29 | <div |
| 23 | - class="w-[64rpx] h-[48rpx] rounded-full shadow-md flex items-center justify-center" | 30 | + class="w-[72rpx] h-[72rpx] flex-shrink-0 flex items-center justify-center rounded-full bg-gray-50 active:scale-95 transition-transform" |
| 24 | - :class="isCollected ? 'bg-[#F59E0B]' : 'bg-white'" | ||
| 25 | @tap="toggleCollect" | 31 | @tap="toggleCollect" |
| 26 | > | 32 | > |
| 27 | <IconFont | 33 | <IconFont |
| 28 | - :name="isCollected ? 'StarFill' : 'Star'" | 34 | + :name="isCollected ? 'heart-fill' : 'heart'" |
| 29 | - :size="20" | 35 | + size="24" |
| 30 | - :color="isCollected ? 'white' : '#9CA3AF'" | 36 | + :color="isCollected ? '#EF4444' : '#9CA3AF'" |
| 31 | /> | 37 | /> |
| 32 | </div> | 38 | </div> |
| 33 | </div> | 39 | </div> |
| 34 | - </div> | ||
| 35 | - | ||
| 36 | - <!-- Product Header --> | ||
| 37 | - <div class="relative mt-[-40rpx] bg-white rounded-t-[40rpx] px-[40rpx] pt-[48rpx] pb-[40rpx] z-10"> | ||
| 38 | - <h1 class="text-[#1F2937] text-[44rpx] font-bold mb-[24rpx]">终身寿险尊享版</h1> | ||
| 39 | 40 | ||
| 40 | <div class="flex flex-wrap gap-[16rpx]"> | 41 | <div class="flex flex-wrap gap-[16rpx]"> |
| 41 | <div class="px-[16rpx] py-[6rpx] bg-red-50 rounded-[8rpx]"> | 42 | <div class="px-[16rpx] py-[6rpx] bg-red-50 rounded-[8rpx]"> |
| ... | @@ -71,7 +72,7 @@ | ... | @@ -71,7 +72,7 @@ |
| 71 | <div class="flex flex-col gap-[32rpx]"> | 72 | <div class="flex flex-col gap-[32rpx]"> |
| 72 | <div v-for="(feature, index) in features" :key="index" class="flex items-start"> | 73 | <div v-for="(feature, index) in features" :key="index" class="flex items-start"> |
| 73 | <div class="w-[48rpx] h-[48rpx] rounded-full bg-blue-50 flex items-center justify-center mr-[24rpx] flex-shrink-0"> | 74 | <div class="w-[48rpx] h-[48rpx] rounded-full bg-blue-50 flex items-center justify-center mr-[24rpx] flex-shrink-0"> |
| 74 | - <IconFont name="check" size="14" color="#2563EB" /> | 75 | + <IconFont name="Check" size="14" color="#2563EB" /> |
| 75 | </div> | 76 | </div> |
| 76 | <div class="flex-1"> | 77 | <div class="flex-1"> |
| 77 | <div class="text-[#1F2937] text-[28rpx] font-medium leading-[1.4]">{{ feature.title }}</div> | 78 | <div class="text-[#1F2937] text-[28rpx] font-medium leading-[1.4]">{{ feature.title }}</div> | ... | ... |
-
Please register or login to post a comment