Parcourir la source

Merge branch 'redesign‌-260706' of http://git.huaml.com/zhh/front-end into redesign‌-260706

ouyang il y a 1 jour
Parent
commit
772b29336e

+ 1 - 0
mallApp/src/api/category/index.js

@@ -10,6 +10,7 @@ export const getClass = data => {
 /**
  * 获取分类的商品 m
  * 可选筛选:categoryIds、useCaseIds、goodsIds、minPrice、maxPrice、searchText、page、pageSize、requestType
+ * 分页按唯一商品:同一商品挂多个分类时不占重复名额,total/moreData 也按去重后的商品计
  */
 export const getList = data => {
 	return https.get('/category/goods-list', data)

+ 1 - 1
mallApp/src/pages.json

@@ -86,7 +86,7 @@
             "root": "pages/goods",
             "pages": [
                 { "path": "detail", "style": { "navigationBarTitleText": "详情" } },
-                { "path": "list", "style": { "navigationBarTitleText": "商品列表", "enablePullDownRefresh": true } },
+                { "path": "list", "style": { "navigationBarTitleText": "商品列表", "enablePullDownRefresh": true, "onReachBottomDistance": 80 } },
                 { "path": "section-list", "style": { "navigationBarTitleText": "商品列表", "enablePullDownRefresh": true } }
             ]
         },

+ 94 - 95
mallApp/src/pages/goods/detail.vue

@@ -2,7 +2,8 @@
   商城商品详情
   谁用:mallApp 顾客查看花束并加购/购买
   解决问题:多规格 specList 首项即主记录可售规格,选中后 specGoodsId 可等于主商品 id;
-  顶部信息卡按标题/分享、副文案、价格已售、服务保障排布,秒杀条保留在价格上方;
+  顶部信息卡按标题/分享、价格已售、规格选择、服务保障排布,秒杀条保留在价格上方;
+  标题:多规格展示当前规格名,单规格展示商品名称;多规格卡片嵌在信息卡内;
   无价格商品作为秒杀时展示秒杀价,底部走加购/购买而不是询价;
   未登录可浏览详情:仅点购物车/咨询/加入购物车/购买(含询价)时弹 wangCg
 -->
@@ -15,14 +16,10 @@
         :list="imgList"
       />
       <view class="shop-intro">
-        <!-- 标题左、分享右;规格名作副文案,避免挤掉秒杀等原有信息 -->
+        <!-- 标题左、分享右;多规格用规格名作标题,单规格用商品名 -->
         <view class="tui-pro-titbox">
           <view class="tui-pro-title-wrap">
-            <view class="tui-pro-title">{{ data.name }}</view>
-            <view
-              v-if="displaySpecName"
-              class="shop-spec"
-            >{{ displaySpecName }}</view>
+            <view class="tui-pro-title">{{ displayTitle }}</view>
           </view>
           <button open-type="share" class="share-button" @click="shareFn">
             <text class="iconfont iconfenxiang share-icon"></text>
@@ -51,6 +48,25 @@
           </view>
           <text class="sold-text">已售 {{ displaySold }}</text>
         </view>
+        <!-- 多规格嵌在信息卡内:切规格同步价格/库存与顶部轮播图 -->
+        <view
+          v-if="data.specEnabled == 1 && data.specList && data.specList.length"
+          class="spec-module"
+        >
+          <view class="spec-module-tit">花束规格</view>
+          <view class="spec-card-list">
+            <view
+              v-for="(spec, index) in data.specList"
+              :key="spec.id"
+              class="spec-card"
+              :class="{ active: specIndex === index }"
+              @click="selectSpecOnPage(index)"
+            >
+              <view class="spec-card-name">{{ spec.specName }}</view>
+              <view class="spec-card-price">{{ specPriceText(spec) }}</view>
+            </view>
+          </view>
+        </view>
         <!-- 三项服务保障:保留原有文案,按设计稿改成图标+主副标题横条 -->
         <view class="shop-express">
           <view class="express-item">
@@ -76,25 +92,6 @@
           </view>
         </view>
       </view>
-      <!-- 多规格:卡片选规格,切换时同步价格/库存与顶部轮播图 -->
-      <view
-        v-if="data.specEnabled == 1 && data.specList && data.specList.length"
-        class="module-wrap spec-module"
-      >
-        <view class="spec-module-tit app-size-32 app-bold">花束规格</view>
-        <view class="spec-card-list">
-          <view
-            v-for="(spec, index) in data.specList"
-            :key="spec.id"
-            class="spec-card"
-            :class="{ active: specIndex === index }"
-            @click="selectSpecOnPage(index)"
-          >
-            <view class="spec-card-name app-bold">{{ spec.specName }}</view>
-            <view class="spec-card-price">{{ specPriceText(spec) }}</view>
-          </view>
-        </view>
-      </view>
       <view class="module-wrap shop-detail">
         <view class="module-tit app-size-32 app-bold">商品详情</view>
         <view class="module-det">
@@ -322,19 +319,21 @@ export default {
       return count;
     },
     /**
-     * 标题下规格名:多规格展示当前选中规格(默认首规格),规格 SKU 详情展示自身 specName
+     * 顶部标题文案:多规格展示当前选中规格名(默认首规格),否则展示商品名称
      */
-    displaySpecName() {
-      if (this.data.selectedSpecName) {
-        return this.data.selectedSpecName;
-      }
-      if (Number(this.data.specEnabled) === 1 && this.data.specList && this.data.specList[0]) {
-        return this.data.specList[0].specName || '';
-      }
-      if (this.data.masterId && String(this.data.masterId) !== '0') {
-        return this.data.specName || '';
+    displayTitle() {
+      const goods = this.data || {};
+      const specList = goods.specList || [];
+      // 多规格:切规格后用 selectedSpecName,初始用当前下标对应规格
+      if (Number(goods.specEnabled) === 1 && specList.length) {
+        const selected = goods.selectedSpecName
+          || (specList[this.specIndex] && specList[this.specIndex].specName)
+          || specList[0].specName;
+        if (selected) {
+          return selected;
+        }
       }
-      return '';
+      return goods.name || '';
     },
     /**
      * 已售文案数字:优先 sold,兼容列表口径 totalSold;过万缩成 x.x万+
@@ -672,9 +671,11 @@ export default {
         res.data.stock = res.data.stock ? parseInt(res.data.stock) : 0;
         this.data = res.data;
         this.customId = res.data.customId;
+        uni.setNavigationBarTitle({
+          title: res.data.name || ''
+        });
         this._originPriceSnapshot = null;
         this.applySeckillPriceIfNeeded();
-
         //商品描述
         this.title =
           (res.data.picTextGoods && res.data.picTextGoods.title) || "";
@@ -996,20 +997,20 @@ export default {
       }
     }
   }
-  // 商品信息卡:上圆角压住轮播,标题/价格/保障按设计稿分层
+  // 商品信息卡:上圆角压住轮播,标题/价格/规格/保障分层
   .shop-intro {
+    $specGreen: #7ba23f;
     position: relative;
     z-index: 1;
     margin-top: -32upx;
-    padding: 32upx 28upx 28upx;
+    padding: 28upx 28upx 24upx;
     background: #fff;
     border-radius: 32upx 32upx 0 0;
     .seckill-bar {
       display: flex;
       align-items: center;
       justify-content: space-between;
-      padding: 12upx 0 0;
-      margin-top: 8upx;
+      margin-top: 16upx;
       .seckill-bar-left {
         display: flex;
         align-items: center;
@@ -1053,12 +1054,6 @@ export default {
         color: #222;
         line-height: 1.4;
       }
-      .shop-spec {
-        margin-top: 10upx;
-        font-size: 26upx;
-        color: #999;
-        line-height: 1.5;
-      }
       .share-button {
         display: flex;
         flex-direction: column;
@@ -1094,7 +1089,7 @@ export default {
       display: flex;
       align-items: baseline;
       justify-content: space-between;
-      margin-top: 24upx;
+      margin-top: 20upx;
       .price-wrap {
         flex: 1;
         overflow: hidden;
@@ -1117,11 +1112,60 @@ export default {
         color: #999;
       }
     }
+    // 规格卡片:选中绿色描边+绿色价格;最后一行底边由负 margin 抵消,交给下一块控制间距
+    .spec-module {
+      margin-top: 24upx;
+      .spec-module-tit {
+        margin-bottom: 16upx;
+        font-size: 26upx;
+        font-weight: 700;
+        color: #333;
+      }
+      .spec-card-list {
+        display: flex;
+        flex-wrap: wrap;
+        margin-bottom: -12upx;
+      }
+      .spec-card {
+        width: calc((100% - 24upx) / 3);
+        margin: 0 12upx 12upx 0;
+        padding: 16upx 12upx;
+        box-sizing: border-box;
+        background: #f7f7f5;
+        border: 2upx solid transparent;
+        border-radius: 12upx;
+        overflow: hidden;
+        &:nth-child(3n) {
+          margin-right: 0;
+        }
+        .spec-card-name {
+          font-size: 26upx;
+          font-weight: 700;
+          color: #333;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+        .spec-card-price {
+          margin-top: 10upx;
+          font-size: 24upx;
+          color: #999;
+        }
+        &.active {
+          background: #fff;
+          border-color: $specGreen;
+          .spec-card-price {
+            color: $specGreen;
+            font-weight: 600;
+          }
+        }
+      }
+    }
     .shop-express {
       display: flex;
       align-items: center;
       margin-top: 24upx;
-      padding: 26upx 38upx;
+      padding: 20upx 24upx;
       background: #f7f7f7;
       border-radius: 16upx;
       .express-item {
@@ -1159,51 +1203,6 @@ export default {
       }
     }
   }
-  // 规格卡片模块:选中项绿色描边+绿色价格,不带角标
-  .spec-module {
-    $specGreen: #7ba23f;
-    padding: 24upx;
-    .spec-module-tit {
-      margin-bottom: 24upx;
-    }
-    .spec-card-list {
-      display: flex;
-      flex-wrap: wrap;
-    }
-    .spec-card {
-      width: calc((100% - 40upx) / 3);
-      margin: 0 20upx 20upx 0;
-      padding: 24upx;
-      box-sizing: border-box;
-      background: #f7f7f5;
-      border: 2upx solid transparent;
-      border-radius: 16upx;
-      overflow: hidden;
-      &:nth-child(3n) {
-        margin-right: 0;
-      }
-      .spec-card-name {
-        font-size: 30upx;
-        color: #333;
-        white-space: nowrap;
-        overflow: hidden;
-        text-overflow: ellipsis;
-      }
-      .spec-card-price {
-        margin-top: 16upx;
-        font-size: 28upx;
-        color: #999;
-      }
-      &.active {
-        background: #fff;
-        border-color: $specGreen;
-        .spec-card-price {
-          color: $specGreen;
-          font-weight: 600;
-        }
-      }
-    }
-  }
   .shop-desc {
     .module-det {
       line-height: 48upx;

+ 17 - 1
mallApp/src/pages/goods/list.vue

@@ -407,11 +407,27 @@ export default {
       }
       return params
     },
-    loadGoods() {
+    /**
+     * 拉取商品列表
+     * 正常按页请求;若本页不足 pageSize 且还有更多,自动续拉,避免去重后条数太少无法触底
+     * @param {number} [remainFill] 自动续拉剩余次数,默认 5
+     * @returns {Promise}
+     */
+    loadGoods(remainFill) {
+      // remainFill:本页去重后条数不足、页面无法触底时自动续拉的剩余次数,防止空页死循环
+      if (remainFill == null) {
+        remainFill = 2
+      }
       this.list.loading = true
       return getList(this.buildQuery())
         .then((res) => {
+          const pageList = (res && res.data && res.data.list) ? res.data.list : []
           this.completes(res)
+          // 后端按分类行分页再过滤时本页可能只有几条,撑不满屏就无法上拉;有更多数据则自动拉下一页
+          if (!this.list.finished && pageList.length < 10 && remainFill > 0) {
+            this.list.loading = true
+            return this.loadGoods(remainFill - 1)
+          }
         })
         .catch(() => {
           this.list.loading = false