Forráskód Böngészése

feat(hdApp): 调整首页专区商品展示配置

- 移除热门推荐、今日上新、下拉商品的前端排列与展示数量提交,由后端按真实商品数量推导

- 团购和秒杀配置新增商品展开开关,并提交 expand 控制首页展开展示
shizhongqi 2 hete
szülő
commit
4fb1e55cf0

+ 4 - 69
hdApp/src/admin/homePageConfig/goodsSection.vue

@@ -111,34 +111,6 @@
           </view>
         </view>
       </view>
-
-      <view class="field-row">
-        <text class="field-label required">排列规则</text>
-        <view class="radio-row">
-          <view
-            v-for="opt in layoutColsOptions"
-            :key="opt.value"
-            class="radio-item"
-            @click="form.layoutCols = opt.value"
-          >
-            <view class="radio-dot" :class="{ on: form.layoutCols === opt.value }"></view>
-            <text>{{ opt.label }}</text>
-          </view>
-        </view>
-      </view>
-
-      <view class="field-row">
-        <text class="field-label">商品展示数量</text>
-        <input
-          v-model="form.displayCount"
-          class="count-input"
-          type="number"
-          maxlength="2"
-          placeholder="默认全部"
-          placeholder-class="phcolor"
-        />
-        <view class="field-hint">范围1-10,留空为全部;设置数量超出商品总数时按全部展示</view>
-      </view>
     </view>
 
     <view class="bottom-bar">
@@ -179,9 +151,7 @@ export default {
         name: '',
         type: 2,
         value: '',
-        sort: 1,
-        layoutCols: 3,
-        displayCount: ''
+        sort: 1
       },
       typeOptions: [
         { label: '商品', value: 2 },
@@ -193,11 +163,6 @@ export default {
         { label: '按销量', value: 2 },
         { label: '按上新时间', value: 3 }
       ],
-      layoutColsOptions: [
-        { label: '1排1列', value: 1 },
-        { label: '1排2列', value: 2 },
-        { label: '1排3列', value: 3 }
-      ],
       categoryData: [],
       useCaseData: [],
       categoryPanelShow: false,
@@ -257,9 +222,7 @@ export default {
           name: d.name || this.cfg.defaultName,
           type: parseInt(d.type, 10) || 2,
           value: d.value || '',
-          sort: parseInt(d.sort, 10) || 1,
-          layoutCols: [1, 2, 3].includes(parseInt(d.layoutCols, 10)) ? parseInt(d.layoutCols, 10) : 3,
-          displayCount: d.displayCount ? String(d.displayCount) : ''
+          sort: parseInt(d.sort, 10) || 1
         }
         if (this.form.type === 2 && this.form.value) {
           const ids = this.parseIds(this.form.value)
@@ -308,17 +271,6 @@ export default {
       else ids.push(key)
       this.form.value = ids.join(',')
     },
-    /** 解析并校验商品展示数量:空=全部(0),否则必须在 1-10 */
-    parseDisplayCount() {
-      const raw = String(this.form.displayCount == null ? '' : this.form.displayCount).trim()
-      if (raw === '') return 0
-      const n = parseInt(raw, 10)
-      if (isNaN(n) || n < 1 || n > 10) {
-        this.$msg('商品展示数量范围为1-10')
-        return null
-      }
-      return n
-    },
     saveFn() {
       if (this.saving) return
       if (!String(this.form.name || '').trim()) {
@@ -329,8 +281,7 @@ export default {
         this.$msg('请选择关联内容')
         return
       }
-      const displayCount = this.parseDisplayCount()
-      if (displayCount === null) return
+      // layoutCols/displayCount 由后端按真实商品数量自动推导,前端不再提交
       this.saving = true
       this.cfg
         .saveApi({
@@ -338,9 +289,7 @@ export default {
           name: String(this.form.name).trim(),
           type: this.form.type,
           value: this.form.value,
-          sort: this.form.sort,
-          layoutCols: this.form.layoutCols,
-          displayCount
+          sort: this.form.sort
         })
         .then((res) => {
           if (res.code === 1) {
@@ -507,20 +456,6 @@ export default {
     background: radial-gradient(circle, #09c567 0 45%, transparent 50%);
   }
 }
-.count-input {
-  height: 72upx;
-  padding: 0 20upx;
-  font-size: 28upx;
-  color: #333;
-  border: 1upx solid #e5e5e5;
-  border-radius: 8upx;
-  box-sizing: border-box;
-}
-.field-hint {
-  margin-top: 12upx;
-  font-size: 22upx;
-  color: $fontColor3;
-}
 .bottom-bar {
   position: fixed;
   left: 0;

+ 34 - 87
hdApp/src/admin/homePageConfig/groupBuy.vue

@@ -41,26 +41,18 @@
         <view class="char-count">{{ subtitleLen }}/20</view>
       </tui-list-cell>
 
+      <!-- 显示倒计时与商品展开同排:展开开启后首页按1排1列展示全部商品 -->
       <tui-list-cell class="line-cell between" :hover="false">
-        <view class="tui-title">显示倒计时</view>
-        <view class="tui-operate switch-wrap">
-          <switch :checked="form.showCountdown == 1" color="#09C567" @change="onShowCountdownChange" />
+        <view class="switch-item">
+          <view class="tui-title switch-title-narrow">显示倒计时</view>
+          <switch class="switch-ctrl" :checked="form.showCountdown == 1" color="#09C567" @change="onShowCountdownChange" />
+        </view>
+        <view class="switch-item">
+          <view class="tui-title switch-title-narrow">商品展开</view>
+          <switch class="switch-ctrl" :checked="form.expand == 1" color="#09C567" @change="onExpandChange" />
         </view>
       </tui-list-cell>
 
-      <tui-list-cell class="line-cell" :hover="false">
-        <view class="tui-title">商品展示数量</view>
-        <input
-          v-model="form.displayCount"
-          class="tui-input"
-          type="number"
-          maxlength="2"
-          placeholder="默认全部"
-          placeholder-class="phcolor"
-        />
-      </tui-list-cell>
-      <view class="field-hint">范围1-10,留空为全部;设置数量超出商品总数时按全部展示</view>
-
       <tui-list-cell class="line-cell time-cell" :hover="false">
         <view class="tui-title required">开始时间</view>
         <datetime-picker
@@ -92,24 +84,6 @@
       <view class="char-count desc-count">{{ descLen }}/500</view>
     </view>
 
-    <view class="cols-section">
-      <view class="section-title">排列规则</view>
-      <radio-group class="cols-radio" @change="onLayoutColsChange">
-        <label class="cols-label">
-          <radio value="1" :checked="form.layoutCols == 1" color="#FF6B88" />
-          <text class="cols-text">1排1列</text>
-        </label>
-        <label class="cols-label">
-          <radio value="2" :checked="form.layoutCols == 2" color="#FF6B88" />
-          <text class="cols-text">1排2列</text>
-        </label>
-        <label class="cols-label">
-          <radio value="3" :checked="form.layoutCols == 3" color="#FF6B88" />
-          <text class="cols-text">1排3列</text>
-        </label>
-      </radio-group>
-    </view>
-
     <view class="goods-section">
       <view class="section-title">团购商品</view>
       <view v-if="!form.goods.length" class="goods-empty">暂无团购商品,请点击底部新增</view>
@@ -197,14 +171,14 @@ export default {
         title: '',
         subtitle: '',
         showCountdown: 1,
-        displayCount: '',
+        // 商品展开:默认关闭;开启后首页按1排1列展示全部商品
+        expand: 0,
         startTime: 0,
         endTime: 0,
         startTimeStr: '',
         endTimeStr: '',
         desc: '',
         status: 0,
-        layoutCols: 3,
         goods: []
       },
       saving: false
@@ -261,14 +235,13 @@ export default {
         title: data.title || '',
         subtitle: data.subtitle || '',
         showCountdown: data.showCountdown == 1 ? 1 : 0,
-        displayCount: data.displayCount ? String(data.displayCount) : '',
+        expand: data.expand == 1 ? 1 : 0,
         startTime,
         endTime,
         startTimeStr: unixToDatetime(startTime),
         endTimeStr: unixToDatetime(endTime),
         desc: data.desc || '',
         status: data.status !== undefined ? parseInt(data.status, 10) : calcLocalStatus(startTime, endTime, enabled),
-        layoutCols: [1, 2, 3].includes(parseInt(data.layoutCols, 10)) ? parseInt(data.layoutCols, 10) : 3,
         goods
       }
     },
@@ -300,23 +273,9 @@ export default {
     onShowCountdownChange(e) {
       this.form.showCountdown = e.detail.value ? 1 : 0
     },
-    /** 解析并校验商品展示数量:空=全部(0),否则必须在 1-10 */
-    parseDisplayCount() {
-      const raw = String(this.form.displayCount == null ? '' : this.form.displayCount).trim()
-      if (raw === '') return 0
-      const n = parseInt(raw, 10)
-      if (isNaN(n) || n < 1 || n > 10) {
-        this.$msg('商品展示数量范围为1-10')
-        return null
-      }
-      return n
-    },
-    /** 切换首页排列规则:1排1列/1排2列/1排3列 */
-    onLayoutColsChange(e) {
-      const cols = parseInt(e.detail.value, 10)
-      if ([1, 2, 3].includes(cols)) {
-        this.form.layoutCols = cols
-      }
+    /** 切换商品展开:开启后首页按1排1列展示全部商品 */
+    onExpandChange(e) {
+      this.form.expand = e.detail.value ? 1 : 0
     },
     onStartTimeInput(val) {
       this.form.startTimeStr = val || ''
@@ -383,8 +342,6 @@ export default {
         this.$msg('活动说明不能超过500字')
         return
       }
-      const displayCount = this.parseDisplayCount()
-      if (displayCount === null) return
       const goodsPayload = (this.form.goods || []).map((g) => ({
         goodsId: g.goodsId,
         price: parseFloat(g.price) || 0,
@@ -400,16 +357,16 @@ export default {
         originPrice: parseFloat(g.originPrice) || 0
       }))
       this.saving = true
+      // layoutCols/displayCount 由后端按商品数量与 expand 自动推导,前端不再提交
       saveGroupBuy({
         enabled: this.form.enabled,
         title,
         subtitle,
         showCountdown: this.form.showCountdown,
-        displayCount,
+        expand: this.form.expand,
         startTime: this.form.startTime,
         endTime: this.form.endTime,
         desc,
-        layoutCols: this.form.layoutCols,
         goods: JSON.stringify(goodsPayload)
       })
         .then((res) => {
@@ -443,6 +400,24 @@ export default {
   @include disFlex(center, flex-end);
 }
 
+.switch-item {
+  @include disFlex(center, flex-start);
+  flex: 1;
+}
+
+// common.scss 中全局定义了 .input-line-wrap .line-cell .tui-title { width: 210upx },
+// 页面内联 style 的优先级理论上更高,但和该全局选择器同处一个 scoped 样式合并时曾出现被覆盖的情况,
+// 这里用 !important 明确保证该模块下的标题宽度按需生效(同类写法见 hb-select.vue)。
+.switch-title-narrow {
+  width: 140px !important;
+}
+
+.switch-ctrl {
+  margin-left: 12upx;
+  transform: scale(0.85);
+  transform-origin: center right;
+}
+
 .switch-title-row {
   @include disFlex(center, flex-start);
 }
@@ -486,13 +461,6 @@ export default {
   align-items: flex-start;
 }
 
-.field-hint {
-  padding: 0 30upx 20upx;
-  font-size: 22upx;
-  color: $fontColor3;
-  background: #fff;
-}
-
 .desc-card {
   margin: 20upx 0 0;
   padding: 24upx 30upx;
@@ -521,27 +489,6 @@ export default {
   margin-top: 10upx;
 }
 
-.cols-section {
-  margin-top: 20upx;
-  padding: 24upx 30upx;
-  background: #fff;
-}
-
-.cols-radio {
-  @include disFlex(center, flex-start);
-}
-
-.cols-label {
-  @include disFlex(center, flex-start);
-  margin-right: 48upx;
-}
-
-.cols-text {
-  margin-left: 10upx;
-  font-size: 28upx;
-  color: #333;
-}
-
 .goods-section {
   margin-top: 20upx;
   padding: 0 24upx;

+ 31 - 87
hdApp/src/admin/homePageConfig/seckill.vue

@@ -41,26 +41,18 @@
         <view class="char-count">{{ subtitleLen }}/20</view>
       </tui-list-cell>
 
+      <!-- 显示倒计时与商品展开同排:展开开启后首页按1排1列展示全部商品 -->
       <tui-list-cell class="line-cell between" :hover="false">
-        <view class="tui-title">显示倒计时</view>
-        <view class="tui-operate switch-wrap">
-          <switch :checked="form.showCountdown == 1" color="#09C567" @change="onShowCountdownChange" />
+        <view class="switch-item">
+          <view class="tui-title switch-title-narrow">显示倒计时</view>
+          <switch class="switch-ctrl" :checked="form.showCountdown == 1" color="#09C567" @change="onShowCountdownChange" />
+        </view>
+        <view class="switch-item">
+          <view class="tui-title switch-title-narrow">商品展开</view>
+          <switch class="switch-ctrl" :checked="form.expand == 1" color="#09C567" @change="onExpandChange" />
         </view>
       </tui-list-cell>
 
-      <tui-list-cell class="line-cell" :hover="false">
-        <view class="tui-title">商品展示数量</view>
-        <input
-          v-model="form.displayCount"
-          class="tui-input"
-          type="number"
-          maxlength="2"
-          placeholder="默认全部"
-          placeholder-class="phcolor"
-        />
-      </tui-list-cell>
-      <view class="field-hint">范围1-10,留空为全部;设置数量超出商品总数时按全部展示</view>
-
       <tui-list-cell class="line-cell time-cell" :hover="false">
         <view class="tui-title required">开始时间</view>
         <datetime-picker
@@ -92,24 +84,6 @@
       <view class="char-count desc-count">{{ descLen }}/500</view>
     </view>
 
-    <view class="cols-section">
-      <view class="section-title">排列规则</view>
-      <radio-group class="cols-radio" @change="onLayoutColsChange">
-        <label class="cols-label">
-          <radio value="1" :checked="form.layoutCols == 1" color="#FF6B88" />
-          <text class="cols-text">1排1列</text>
-        </label>
-        <label class="cols-label">
-          <radio value="2" :checked="form.layoutCols == 2" color="#FF6B88" />
-          <text class="cols-text">1排2列</text>
-        </label>
-        <label class="cols-label">
-          <radio value="3" :checked="form.layoutCols == 3" color="#FF6B88" />
-          <text class="cols-text">1排3列</text>
-        </label>
-      </radio-group>
-    </view>
-
     <view class="goods-section">
       <view class="section-title">秒杀商品</view>
       <view v-if="!form.goods.length" class="goods-empty">暂无秒杀商品,请点击底部新增</view>
@@ -197,14 +171,14 @@ export default {
         title: '',
         subtitle: '',
         showCountdown: 1,
-        displayCount: '',
+        // 商品展开:默认关闭;开启后首页按1排1列展示全部商品
+        expand: 0,
         startTime: 0,
         endTime: 0,
         startTimeStr: '',
         endTimeStr: '',
         desc: '',
         status: 0,
-        layoutCols: 3,
         goods: []
       },
       saving: false,
@@ -262,14 +236,13 @@ export default {
         title: data.title || '',
         subtitle: data.subtitle || '',
         showCountdown: data.showCountdown == 1 ? 1 : 0,
-        displayCount: data.displayCount ? String(data.displayCount) : '',
+        expand: data.expand == 1 ? 1 : 0,
         startTime,
         endTime,
         startTimeStr: unixToDatetime(startTime),
         endTimeStr: unixToDatetime(endTime),
         desc: data.desc || '',
         status: data.status !== undefined ? parseInt(data.status, 10) : calcLocalStatus(startTime, endTime, enabled),
-        layoutCols: [1, 2, 3].includes(parseInt(data.layoutCols, 10)) ? parseInt(data.layoutCols, 10) : 3,
         goods
       }
     },
@@ -302,23 +275,9 @@ export default {
     onShowCountdownChange(e) {
       this.form.showCountdown = e.detail.value ? 1 : 0
     },
-    /** 解析并校验商品展示数量:空=全部(0),否则必须在 1-10 */
-    parseDisplayCount() {
-      const raw = String(this.form.displayCount == null ? '' : this.form.displayCount).trim()
-      if (raw === '') return 0
-      const n = parseInt(raw, 10)
-      if (isNaN(n) || n < 1 || n > 10) {
-        this.$msg('商品展示数量范围为1-10')
-        return null
-      }
-      return n
-    },
-    /** 切换首页排列规则:1排1列/1排2列/1排3列 */
-    onLayoutColsChange(e) {
-      const cols = parseInt(e.detail.value, 10)
-      if ([1, 2, 3].includes(cols)) {
-        this.form.layoutCols = cols
-      }
+    /** 切换商品展开:开启后首页按1排1列展示全部商品 */
+    onExpandChange(e) {
+      this.form.expand = e.detail.value ? 1 : 0
     },
     onStartTimeInput(val) {
       this.form.startTimeStr = val || ''
@@ -387,8 +346,6 @@ export default {
         this.$msg('活动说明不能超过500字')
         return
       }
-      const displayCount = this.parseDisplayCount()
-      if (displayCount === null) return
       const goodsPayload = (this.form.goods || []).map((g) => ({
         goodsId: g.goodsId,
         price: parseFloat(g.price) || 0,
@@ -400,16 +357,16 @@ export default {
         originPrice: parseFloat(g.originPrice) || 0
       }))
       this.saving = true
+      // layoutCols/displayCount 由后端按商品数量与 expand 自动推导,前端不再提交
       saveSeckill({
         enabled: this.form.enabled,
         title,
         subtitle,
         showCountdown: this.form.showCountdown,
-        displayCount,
+        expand: this.form.expand,
         startTime: this.form.startTime,
         endTime: this.form.endTime,
         desc,
-        layoutCols: this.form.layoutCols,
         goods: JSON.stringify(goodsPayload)
       })
         .then((res) => {
@@ -443,6 +400,21 @@ export default {
   @include disFlex(center, flex-end);
 }
 
+.switch-item {
+  @include disFlex(center, flex-start);
+  flex: 1;
+}
+
+.switch-title-narrow {
+  width: 140px !important;
+}
+
+.switch-ctrl {
+  margin-left: 12upx;
+  transform: scale(0.85);
+  transform-origin: center right;
+}
+
 .switch-title-row {
   @include disFlex(center, flex-start);
 }
@@ -486,13 +458,6 @@ export default {
   align-items: flex-start;
 }
 
-.field-hint {
-  padding: 0 30upx 20upx;
-  font-size: 22upx;
-  color: $fontColor3;
-  background: #fff;
-}
-
 .desc-card {
   margin: 20upx 0 0;
   padding: 24upx 30upx;
@@ -521,27 +486,6 @@ export default {
   margin-top: 10upx;
 }
 
-.cols-section {
-  margin-top: 20upx;
-  padding: 24upx 30upx;
-  background: #fff;
-}
-
-.cols-radio {
-  @include disFlex(center, flex-start);
-}
-
-.cols-label {
-  @include disFlex(center, flex-start);
-  margin-right: 48upx;
-}
-
-.cols-text {
-  margin-left: 10upx;
-  font-size: 28upx;
-  color: #333;
-}
-
 .goods-section {
   margin-top: 20upx;
   padding: 0 24upx;