Просмотр исходного кода

fix(shop): 商城三页UI调整与会员价计算修复

- 确认订单页: 提交订单按钮居右(覆盖微信原生button默认margin)、底栏/按钮/价格行加高
- 商品详情页: 底栏加高、按钮加高、加入购物车改纯图标、生成海报改海报、新增微信分享按钮
- 购物车页: 去结算按钮居右、金额样式对齐确认订单页、勾选/全选响应式修复()
- 购物车进确认订单页未用会员价: calcAmount改用effectivePrice, 会员状态异步确认后重算
Agnes Agent 1 неделя назад
Родитель
Сommit
28a194b918

+ 51 - 28
cfc-frontend/pages/discover-detail/product-detail/product-detail.vue

@@ -172,15 +172,12 @@
     <!-- 底部操作栏:必须与 scroll-view 平级,否则 iOS 上 position: fixed 在 scroll-view 内不生效(按钮不显示) -->
     <!-- 底部操作栏:必须与 scroll-view 平级,否则 iOS 上 position: fixed 在 scroll-view 内不生效(按钮不显示) -->
     <view class="bottom-bar" v-if="!loading && product.id">
     <view class="bottom-bar" v-if="!loading && product.id">
       <view class="action-left">
       <view class="action-left">
-        <view class="action-extra">
-          <button class="btn-share" @click="onShareProduct"><image class="btn-share-icon" src="/static/icons/poster.png" mode="aspectFit" /><text class="btn-share-text">生成海报</text></button>
-        </view>
+        <button class="btn-share-friend" open-type="share"><text class="btn-share-friend-icon">📤</text></button>
+        <button class="btn-share" @click="onShareProduct"><image class="btn-share-icon" src="/static/icons/poster.png" mode="aspectFit" /><text class="btn-share-text">海报</text></button>
       </view>
       </view>
       <view class="action-right">
       <view class="action-right">
-        <view class="action-extra">
-          <button class="btn-cart" @click="onAddToCart">加入购物车</button>
-        </view>
-          <button class="btn-buy" @click="onBuy">{{ buyButtonText }}</button>
+        <button class="btn-cart" @click="onAddToCart"><text class="btn-cart-icon">🛒</text></button>
+        <button class="btn-buy" @click="onBuy">{{ buyButtonText }}</button>
       </view>
       </view>
     </view>
     </view>
 
 
@@ -893,7 +890,7 @@ export default {
 }
 }
 .content {
 .content {
   height: calc(100vh - 120rpx);
   height: calc(100vh - 120rpx);
-  padding-bottom: 120rpx;
+  padding-bottom: 140rpx;
 }
 }
 .cover-swiper {
 .cover-swiper {
   width: 100%;
   width: 100%;
@@ -1264,7 +1261,7 @@ export default {
   bottom: 0;
   bottom: 0;
   left: 0;
   left: 0;
   right: 0;
   right: 0;
-  height: 100rpx;
+  height: 120rpx;
   background: $app-surface;
   background: $app-surface;
   border-top: 1rpx solid $facade-hairline-2;
   border-top: 1rpx solid $facade-hairline-2;
   display: flex;
   display: flex;
@@ -1299,47 +1296,51 @@ export default {
 .btn-buy {
 .btn-buy {
   background: linear-gradient(135deg, $brand-primary, $brand-primary-light);
   background: linear-gradient(135deg, $brand-primary, $brand-primary-light);
   color: $app-surface;
   color: $app-surface;
-  font-size: calc(28rpx * var(--font-scale, 1));
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
-  padding: 0 60rpx;
-  height: 72rpx;
-  line-height: 72rpx;
+  padding: 0 56rpx;
+  height: 88rpx;
+  line-height: 88rpx;
   border-radius: 24rpx;
   border-radius: 24rpx;
   border: none;
   border: none;
 }
 }
 .btn-buy::after {
 .btn-buy::after {
   border: none;
   border: none;
 }
 }
-.action-extra {
-  display: flex;
-  align-items: center;
-  margin-right: 20rpx;
-}
 .btn-favorite {
 .btn-favorite {
   font-size: calc(40rpx * var(--font-scale, 1));
   font-size: calc(40rpx * var(--font-scale, 1));
   margin-right: 16rpx;
   margin-right: 16rpx;
   padding: 0 8rpx;
   padding: 0 8rpx;
 }
 }
 .btn-cart {
 .btn-cart {
+  width: 88rpx;
+  height: 88rpx;
   background: $app-surface;
   background: $app-surface;
   color: $brand-primary;
   color: $brand-primary;
   border: 2rpx solid $brand-primary;
   border: 2rpx solid $brand-primary;
-  font-size: calc(28rpx * var(--font-scale, 1));
-  padding: 0 24rpx;
-  height: 72rpx;
-  line-height: 72rpx;
   border-radius: 24rpx;
   border-radius: 24rpx;
+  margin-right: 16rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 0;
+  line-height: 1;
+  flex-shrink: 0;
 }
 }
 .btn-cart::after {
 .btn-cart::after {
   border: none;
   border: none;
 }
 }
+.btn-cart-icon {
+  font-size: calc(44rpx * var(--font-scale, 1));
+  line-height: 1;
+}
 .btn-share {
 .btn-share {
   background: $app-surface;
   background: $app-surface;
   border: 2rpx solid $brand-primary;
   border: 2rpx solid $brand-primary;
-  font-size: calc(24rpx * var(--font-scale, 1));
-  padding: 0 24rpx;
-  height: 64rpx;
-  line-height: 64rpx;
+  font-size: calc(26rpx * var(--font-scale, 1));
+  padding: 0 28rpx;
+  height: 80rpx;
+  line-height: 80rpx;
   border-radius: 24rpx;
   border-radius: 24rpx;
   margin-right: 16rpx;
   margin-right: 16rpx;
   display: flex;
   display: flex;
@@ -1348,8 +1349,30 @@ export default {
   font-weight: 600;
   font-weight: 600;
   text-align: center;
   text-align: center;
 }
 }
-.btn-share-icon { width: calc(32rpx * var(--font-scale, 1)); height: calc(32rpx * var(--font-scale, 1)); margin-right: 6rpx; flex-shrink: 0; }
-.btn-share-text { font-size: calc(24rpx * var(--font-scale, 1)); }
+.btn-share-icon { width: calc(36rpx * var(--font-scale, 1)); height: calc(36rpx * var(--font-scale, 1)); margin-right: 8rpx; flex-shrink: 0; }
+.btn-share-text { font-size: calc(26rpx * var(--font-scale, 1)); }
+.btn-share-friend {
+  width: 88rpx;
+  height: 88rpx;
+  background: $app-surface;
+  border: 2rpx solid $brand-primary;
+  border-radius: 24rpx;
+  margin-right: 16rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: $brand-primary;
+  padding: 0;
+  line-height: 1;
+  flex-shrink: 0;
+}
+.btn-share-friend::after {
+  border: none;
+}
+.btn-share-friend-icon {
+  font-size: calc(44rpx * var(--font-scale, 1));
+  line-height: 1;
+}
 
 
 /* 配送信息 */
 /* 配送信息 */
 .delivery-info-section {
 .delivery-info-section {

+ 22 - 11
cfc-frontend/pages/shop/cart/cart.vue

@@ -27,6 +27,7 @@
           v-for="item in items"
           v-for="item in items"
           :key="item.productId"
           :key="item.productId"
           class="cart-item-card"
           class="cart-item-card"
+          :class="item.checked ? 'checked' : ''"
         >
         >
           <view class="item-left">
           <view class="item-left">
             <image
             <image
@@ -354,8 +355,10 @@ export default {
             var result = res.data.data
             var result = res.data.data
             that.items = result.items || []
             that.items = result.items || []
             for (var i = 0; i < that.items.length; i++) {
             for (var i = 0; i < that.items.length; i++) {
-              that.items[i].checked = true
-              that.items[i].subtotal = that.items[i].unitPrice * that.items[i].quantity
+              // 用 $set 声明响应式:checked/subtotal 是接口返回后新加的字段,
+              // 直接赋值 Vue2 不会触发重渲染,会导致"勾选/全选无回显、已选与合计不变"
+              that.$set(that.items[i], 'checked', true)
+              that.$set(that.items[i], 'subtotal', that.items[i].unitPrice * that.items[i].quantity)
             }
             }
             that.giftPromo = result.giftPromo || null
             that.giftPromo = result.giftPromo || null
             that.loadGiftProgress()
             that.loadGiftProgress()
@@ -562,6 +565,11 @@ export default {
   padding: 20rpx;
   padding: 20rpx;
   box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.06);
   box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.06);
 }
 }
+/* 勾选状态回显:卡片高亮边框,让选中态一目了然 */
+.cart-item-card.checked {
+  border: 2rpx solid $brand-primary-light-2;
+  background: $uni-primary-pale;
+}
 .item-left {
 .item-left {
   margin-right: 16rpx;
   margin-right: 16rpx;
 }
 }
@@ -658,7 +666,7 @@ export default {
   bottom: 0;
   bottom: 0;
   left: 0;
   left: 0;
   right: 0;
   right: 0;
-  height: 100rpx;
+  height: 120rpx;
   background: $app-surface;
   background: $app-surface;
   border-top: 1rpx solid $facade-hairline-2;
   border-top: 1rpx solid $facade-hairline-2;
   display: flex;
   display: flex;
@@ -672,29 +680,32 @@ export default {
   align-items: baseline;
   align-items: baseline;
 }
 }
 .selected-count {
 .selected-count {
-  font-size: calc(24rpx * var(--font-scale, 1));
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-body;
   color: $facade-text-body;
   margin-right: 12rpx;
   margin-right: 12rpx;
 }
 }
 .total-amount-label {
 .total-amount-label {
-  font-size: calc(24rpx * var(--font-scale, 1));
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-body;
   color: $facade-text-body;
 }
 }
 .total-amount {
 .total-amount {
-  font-size: calc(36rpx * var(--font-scale, 1));
+  font-size: calc(42rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: bold;
   font-weight: bold;
 }
 }
 .checkout-btn {
 .checkout-btn {
   background: linear-gradient(135deg, $brand-primary, $brand-primary-light);
   background: linear-gradient(135deg, $brand-primary, $brand-primary-light);
   color: $app-surface;
   color: $app-surface;
-  font-size: calc(28rpx * var(--font-scale, 1));
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
-  padding: 0 50rpx;
-  height: 72rpx;
-  line-height: 72rpx;
+  padding: 0 56rpx;
+  height: 88rpx;
+  line-height: 88rpx;
   border-radius: 24rpx;
   border-radius: 24rpx;
   border: none;
   border: none;
+  margin-left: auto;  /* 右下居右:覆盖微信原生 button 默认 margin,贴右对齐 */
+  margin-right: 0;
+  flex-shrink: 0;
 }
 }
 .checkout-btn::after {
 .checkout-btn::after {
   border: none;
   border: none;
@@ -733,7 +744,7 @@ export default {
   text-decoration: line-through;
   text-decoration: line-through;
 }
 }
 .price-estimate {
 .price-estimate {
-  font-size: calc(34rpx * var(--font-scale, 1));
+  font-size: calc(40rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
   color: $brand-primary;
   color: $brand-primary;
 }
 }

+ 15 - 9
cfc-frontend/pages/shop/checkout/checkout.vue

@@ -708,7 +708,7 @@ export default {
     calcAmount() {
     calcAmount() {
       var total = 0
       var total = 0
       for (var i = 0; i < this.items.length; i++) {
       for (var i = 0; i < this.items.length; i++) {
-        total = total + (this.items[i].unitPrice * this.items[i].quantity)
+        total = total + (this.effectivePrice(this.items[i]) * this.items[i].quantity)
       }
       }
       this.actualAmount = total
       this.actualAmount = total
     },
     },
@@ -954,6 +954,8 @@ export default {
       getMyMembership().then(function(res) {
       getMyMembership().then(function(res) {
         if (res.data && res.data.memberLevel) {
         if (res.data && res.data.memberLevel) {
           that.isMember = res.data.memberLevel !== 'FREE'
           that.isMember = res.data.memberLevel !== 'FREE'
+          // 会员身份异步确认后重算价格:首次 calcAmount 时 isMember 还是 false,会员价未生效
+          that.calcAmount()
         }
         }
       }).catch(function() {})
       }).catch(function() {})
     },
     },
@@ -1284,6 +1286,7 @@ showOnlineSlotPicker: function() {
 }
 }
 .content {
 .content {
   height: calc(100vh - 120rpx);
   height: calc(100vh - 120rpx);
+  padding-bottom: 160rpx;
 }
 }
 .section {
 .section {
   background: $app-surface;
   background: $app-surface;
@@ -1659,14 +1662,14 @@ showOnlineSlotPicker: function() {
   border: none;
   border: none;
 }
 }
 .bottom-spacer {
 .bottom-spacer {
-  height: 140rpx;
+  height: 160rpx;
 }
 }
 .bottom-bar {
 .bottom-bar {
   position: fixed;
   position: fixed;
   bottom: 0;
   bottom: 0;
   left: 0;
   left: 0;
   right: 0;
   right: 0;
-  height: 100rpx;
+  height: 120rpx;
   background: $app-surface;
   background: $app-surface;
   border-top: 1rpx solid $facade-hairline-2;
   border-top: 1rpx solid $facade-hairline-2;
   display: flex;
   display: flex;
@@ -1680,24 +1683,27 @@ showOnlineSlotPicker: function() {
   align-items: baseline;
   align-items: baseline;
 }
 }
 .total-label {
 .total-label {
-  font-size: calc(26rpx * var(--font-scale, 1));
+  font-size: calc(28rpx * var(--font-scale, 1));
   color: $facade-text-body;
   color: $facade-text-body;
 }
 }
 .total-amount {
 .total-amount {
-  font-size: calc(36rpx * var(--font-scale, 1));
+  font-size: calc(42rpx * var(--font-scale, 1));
   color: $brand-primary;
   color: $brand-primary;
   font-weight: bold;
   font-weight: bold;
 }
 }
 .submit-btn {
 .submit-btn {
   background: linear-gradient(135deg, $brand-primary, $brand-primary-light);
   background: linear-gradient(135deg, $brand-primary, $brand-primary-light);
   color: $app-surface;
   color: $app-surface;
-  font-size: calc(28rpx * var(--font-scale, 1));
+  font-size: calc(30rpx * var(--font-scale, 1));
   font-weight: bold;
   font-weight: bold;
-  padding: 0 60rpx;
-  height: 72rpx;
-  line-height: 72rpx;
+  padding: 0 56rpx;
+  height: 88rpx;
+  line-height: 88rpx;
   border-radius: 24rpx;
   border-radius: 24rpx;
   border: none;
   border: none;
+  margin-left: auto;  /* 右下居右:无论容器是否 space-between,都贴右对齐 */
+  margin-right: 0;    /* 覆盖微信原生 button 默认的 margin-right:auto,防止被居中 */
+  flex-shrink: 0;     /* 不被左侧合计区挤压 */
 }
 }
 .submit-btn::after {
 .submit-btn::after {
   border: none;
   border: none;