Parcourir la source

fix(mallApp): 修正拼团订单状态与操作展示

- 统一列表和详情的拼团状态文案,未成团订单不再误显示待配送
- 按成团结果控制支付、客服和售后入口,兼容拼团状态字段
- 修正失败或取消拼团的提示与配图
shizhongqi il y a 1 jour
Parent
commit
1008e6f8e1

+ 6 - 3
mallApp/src/api/order/index.js

@@ -13,15 +13,18 @@ export const buyItem = data => {
 }
 
 /** *
- * 商城下单-生成订单 m
+ * 商城顾客订单列表
+ * 拼团单含 groupBuyId / groupBuyStatus(1拼团中 2成功 3失败 4已取消)与 payStatus
  */
 export const getList = data => {
 	return https.get('/order/list', data)
 }
 
 /** *
- * 订单详情 m
- * canApplyRefund:可否新开售后;现金为 0 时需 hbId>0 且 hbAmount>实付;refundApplyId:最新顾客申请,有值则详情页展示「查看申请」
+ * 订单详情
+ * canApplyRefund:可否新开售后;拼团未成功为 0
+ * groupBuyStatus:拼团状态 1拼团中 2成功 3失败 4已取消,不能只看 status / payStatus
+ * refundApplyId:最新顾客申请,有值则详情页展示「查看申请」
  */
 export const getDetail = data => {
 	return https.get('/order/detail', data)

+ 46 - 25
mallApp/src/components/order/order-item.vue

@@ -1,6 +1,6 @@
 <!--
   订单列表卡片组件
-  供主包 Tab 页 pages/home/order 使用,展示店铺信息、商品明细与合计金额
+  用途:order / course 订单列表展示店铺、商品、金额;拼团单结合 groupBuyStatus 控制状态与履约按钮
 -->
 <template>
   <view class="order-card" @click="clickItemEvent">
@@ -12,7 +12,8 @@
         <text class="iconfont iconxiangyou shop-arrow"></text>
       </view>
       <view class="status-wrap">
-        <text v-if="info.groupBuyId > 0 && groupBuyStatusText" class="tag tag-groupbuy">{{ groupBuyStatusText }}</text>
+        <!-- 主状态已是拼团中/失败时不重复打标;待付款或已成团时用标签标明活动结果 -->
+        <text v-if="groupBuyStatusText" class="tag tag-groupbuy">{{ groupBuyStatusText }}</text>
         <text v-if="info.refund == 2" class="tag tag-refund">有退款</text>
         <text v-if="info.debt == 1" class="tag tag-debt">赊账</text>
         <text v-if="info.book == 1" class="tag tag-book">预订单</text>
@@ -95,7 +96,7 @@
           <text class="footer-price footer-price--discount">¥{{ displayActPrice }}</text>
         </block>
       </view>
-      <!-- 待付款:立即付款;待配送:联系客服 -->
+      <!-- 待付款:立即付款;待配送且可履约(拼团须成功):联系客服 -->
       <view v-if="showActionBar" class="card-actions" @click.stop>
         <view
           v-if="isWaitPay"
@@ -115,9 +116,18 @@
 <script>
 /**
  * 订单列表卡片
- * 供 pages/home/order 使用;按状态展示立即付款 / 联系客服
+ * 供 pages/home/order、course 使用;拼团单结合 groupBuyStatus 控制状态文案与履约按钮
  */
-import { getSystemStatusDesc } from '@/utils/orderStatus'
+import {
+  canShowWaitPayAction,
+  canShowWaitSendAction,
+  getGroupBuyStatus,
+  getOrderDisplayStatus,
+  GROUP_BUY_STATUS_ONGOING,
+  GROUP_BUY_STATUS_SUCCESS,
+  isGroupBuyClosed,
+  isGroupBuyOrder
+} from '@/utils/orderStatus'
 
 export default {
   name: "OrderItem",
@@ -141,27 +151,38 @@ export default {
     }
   },
   computed: {
-    /** 订单状态文案(优先接口 statusDesc,与 OrderStatusUtil::getSystemStatusDesc 一致) */
+    /**
+     * 订单状态文案:拼团单结合成团结果,已付未成团显示拼团中而不是待配送
+     */
     getStatusName() {
-      if (this.info.statusDesc) {
-        return this.info.statusDesc
-      }
-      return getSystemStatusDesc(this.info.status)
+      return getOrderDisplayStatus(this.info)
     },
-    /** 拼团状态文案(有 groupBuyId 时展示) */
+    /**
+     * 活动标签:待付款拼团中、或已成团成功时展示,避免与主状态文案重复
+     */
     groupBuyStatusText() {
-      const map = {
-        '1': '拼团中',
-        '2': '拼团成功',
-        '3': '拼团失败已退款',
-        '4': '拼团已取消'
-      };
-      const status = this.info.groupBuyStatus;
-      if (status === undefined || status === null || status === '') return '';
-      return map[String(status)] || '';
+      if (!isGroupBuyOrder(this.info)) {
+        return ''
+      }
+      const groupBuyStatus = getGroupBuyStatus(this.info)
+      if (groupBuyStatus === GROUP_BUY_STATUS_SUCCESS) {
+        return '拼团成功'
+      }
+      if (Number(this.info.status) === 1 && groupBuyStatus === GROUP_BUY_STATUS_ONGOING) {
+        return '拼团中'
+      }
+      return ''
     },
-    /** 状态颜色样式类 */
+    /** 状态颜色:拼团失败/取消按已取消色,拼团中按待配送色 */
     statusClass() {
+      if (isGroupBuyClosed(this.info)) {
+        return 'status-cancel'
+      }
+      if (isGroupBuyOrder(this.info)
+        && getGroupBuyStatus(this.info) === GROUP_BUY_STATUS_ONGOING
+        && Number(this.info.status) !== 1) {
+        return 'status-wait-send'
+      }
       const map = {
         '1': 'status-wait-pay',
         '2': 'status-wait-send',
@@ -171,13 +192,13 @@ export default {
       };
       return map[String(this.info.status)] || '';
     },
-    /** 待付款 */
+    /** 待付款且团未关闭:立即付款 */
     isWaitPay() {
-      return Number(this.info.status) === 1
+      return canShowWaitPayAction(this.info)
     },
-    /** 待配送 */
+    /** 待配送且可履约:拼团须成功才显示联系客服 */
     isWaitSend() {
-      return Number(this.info.status) === 2
+      return canShowWaitSendAction(this.info)
     },
     /** 是否展示底部操作区 */
     showActionBar() {

+ 1 - 1
mallApp/src/filters/constant.js

@@ -85,7 +85,7 @@ const _CONST_MAP = {
 		{ label: '拼团中', value: 1 },
 		{ label: '拼团成功', value: 2 },
 		{ label: '拼团失败已退款', value: 3 },
-		{ label: '已取消', value: 4 }
+		{ label: '拼团已取消', value: 4 }
 	],
 	// 配送状态
 	SEND_STATUS: [

+ 1 - 0
mallApp/src/pages/home/components/order-list-view.vue

@@ -1,6 +1,7 @@
 <!--
   订单列表公共组件(含业务逻辑)
   用途:order.vue / course.vue 共用状态 Tab、分页列表、详情/支付/客服;
+  拼团单状态与履约按钮由 order-item 结合 groupBuyStatus 控制。
   mode=tab 可插槽店铺筛选;mode=shop 可插槽 footer(如 shop-tab-bar)。
   页面仅转发触底/下拉/初始化,并通过 :hd-id 控制门店过滤。
 -->

+ 1 - 0
mallApp/src/pages/home/course.vue

@@ -1,6 +1,7 @@
 <!--
   店铺内订单页(pages/home/course)
   用途:shop-tab-bar「订单」入口;锁定当前门店;列表逻辑在 order-list-view 内
+  拼团单状态文案与履约按钮由 order-item 结合 groupBuyStatus 控制
   未登录:参考原生订单 Tab(order.vue),仍展示状态 Tab + 空态文案,点击跳转登录,不请求订单接口
   参数:account、hdId(底栏透传并写入缓存)
 -->

+ 58 - 32
mallApp/src/pages/order/detail.vue

@@ -1,7 +1,7 @@
 <!--
   商城订单详情
   用途:订单列表/支付回跳进入;展示状态、收货、商品、金额与售后入口
-  排版:分区卡片 + 绿主色状态头,避免大段挤在一起
+  拼团单:主状态结合 groupBuyStatus(1拼团中 2成功 3失败 4已取消),不能只看 status / payStatus
 -->
 <template>
   <view class="detail-page">
@@ -10,12 +10,9 @@
       <view class="hero-bg"></view>
       <view class="hero-inner">
         <view class="hero-left">
-          <text class="hero-status">{{ data.status | constantfilter('ORDER_STATUS') }}</text>
+          <text class="hero-status">{{ displayStatus }}</text>
           <text v-if="statusHint" class="hero-hint">{{ statusHint }}</text>
-          <text
-            v-if="data.groupBuyId > 0 && data.groupBuyStatus"
-            class="hero-group"
-          >{{ data.groupBuyStatus | constantfilter('GROUP_BUY_STATUS') }}</text>
+          <text v-if="groupBuySuccessTag" class="hero-group">{{ groupBuySuccessTag }}</text>
         </view>
         <image v-if="statusImg" class="hero-img" :src="statusImg" mode="aspectFit" />
       </view>
@@ -199,12 +196,12 @@
         <text class="footer-price__num">{{ money(data.actPrice) }}</text>
       </view>
       <view class="footer-actions">
-        <template v-if="Number(data.status) === 1">
+        <template v-if="showPayButton">
           <button class="foot-btn foot-btn--primary" @click="payFn">立即支付</button>
         </template>
         <template v-else>
           <button class="foot-btn foot-btn--ghost" @click="goViewRefund">售后记录</button>
-          <button class="foot-btn foot-btn--ghost" @click="goRefund">申请售后</button>
+          <button v-if="showApplyRefund" class="foot-btn foot-btn--ghost" @click="goRefund">申请售后</button>
         </template>
       </view>
     </view>
@@ -214,12 +211,23 @@
 <script>
 /**
  * 商城订单详情:状态 / 收货 / 商品 / 费用 / 售后入口
- * 底栏「售后记录」进本单售后列表;「申请售后」进申请页
+ * 拼团单结合 groupBuyStatus 展示主状态;未成团不开放申请售后
  */
 import { mapGetters } from 'vuex'
 import orderItem from '@/components/module/app-order-item'
 import ListModule from '@/components/module/app-order-list'
 import { getDetail } from '@/api/order'
+import {
+  canShowApplyRefundAction,
+  canShowWaitPayAction,
+  getGroupBuyStatus,
+  getOrderDisplayHint,
+  getOrderDisplayStatus,
+  GROUP_BUY_STATUS_SUCCESS,
+  isGroupBuyClosed,
+  isGroupBuyFulfillable,
+  isGroupBuyOrder
+} from '@/utils/orderStatus'
 
 export default {
   name: 'detail',
@@ -240,13 +248,38 @@ export default {
   },
   computed: {
     ...mapGetters({ shopUser: 'getShopUser' }),
-    /** 状态配图:与商城 ORDER_STATUS 取值对齐 */
+    /**
+     * 顶部主状态:拼团单结合成团结果,已付未成团显示拼团中而不是待配送
+     */
+    displayStatus() {
+      return getOrderDisplayStatus(this.data)
+    },
+    /**
+     * 已成团成功时在主状态旁标明活动结果;拼团中/失败已写入主状态,不再重复
+     */
+    groupBuySuccessTag() {
+      if (!isGroupBuyOrder(this.data)) {
+        return ''
+      }
+      if (getGroupBuyStatus(this.data) !== GROUP_BUY_STATUS_SUCCESS) {
+        return ''
+      }
+      return '拼团成功'
+    },
+    /** 状态配图:拼团未成团成功时不展示配送图标,避免误当成待发货 */
     statusImg() {
       const status = Number(this.data.status)
       const base = this.$constant.imgUrl + '/retail/order/'
+      // 团已失败或取消时不展示待付款图,避免与最终状态和隐藏的支付按钮冲突
+      if (isGroupBuyClosed(this.data)) {
+        return ''
+      }
       if (status === 1) {
         return base + 'wait-pay.png'
       }
+      if (isGroupBuyOrder(this.data) && !isGroupBuyFulfillable(this.data)) {
+        return ''
+      }
       if (status === 2) {
         return base + 'wait-delivery.png'
       }
@@ -258,28 +291,17 @@ export default {
       }
       return ''
     },
-    /** 状态下方一句提示,帮助用户理解当前该做什么 */
+    /** 状态下方一句提示:拼团单说明成团后再履约 */
     statusHint() {
-      const status = Number(this.data.status)
-      if (status === 1) {
-        return '请尽快完成支付,超时订单可能自动取消'
-      }
-      if (status === 2) {
-        return '商家备货中,请耐心等待配送'
-      }
-      if (status === 3) {
-        return '鲜花配送途中,注意查收'
-      }
-      if (status === 4) {
-        return '订单已完成,感谢您的惠顾'
-      }
-      if (status === 5) {
-        return '订单已取消'
-      }
-      if (status === 6) {
-        return '订单已退款'
-      }
-      return ''
+      return getOrderDisplayHint(this.data)
+    },
+    /** 待付款且团未关闭:立即支付 */
+    showPayButton() {
+      return canShowWaitPayAction(this.data)
+    },
+    /** 申请售后:接口 canApplyRefund 允许,且拼团单须成团成功 */
+    showApplyRefund() {
+      return canShowApplyRefundAction(this.data)
     },
     /** 配送时间展示:日期 + 时段文案 */
     reachTimeText() {
@@ -339,12 +361,16 @@ export default {
       })
     },
     /**
-     * 进申请售后页;分销已结算则拦截
+     * 进申请售后页;分销已结算、拼团未成功则拦截
      */
     goRefund() {
       if (!this.data.id) {
         return
       }
+      if (isGroupBuyOrder(this.data) && !isGroupBuyFulfillable(this.data)) {
+        uni.showToast({ title: '拼团未成功,暂无法申请售后', icon: 'none' })
+        return
+      }
       if (Number(this.data.distOrderSettled) === 1) {
         uni.showToast({ title: '分销佣金已结算,无法申请售后', icon: 'none' })
         return

+ 214 - 16
mallApp/src/utils/orderStatus.js

@@ -1,16 +1,214 @@
-/**
- * 订单 status 文案,与后端 OrderStatusUtil::getSystemStatusDesc 保持一致
- * @param {number|string} status 系统订单状态 1-5
- * @returns {string}
- */
-export function getSystemStatusDesc(status) {
-  const map = {
-    1: '待付款',
-    2: '待配送',
-    3: '配送中',
-    4: '已完成',
-    5: '已取消'
-  }
-  const key = Number(status)
-  return map[key] || '未知状态'
-}
+/**
+ * 商城订单状态文案与拼团履约判断
+ * 用途:订单列表卡片、订单详情共用,避免只看 status / payStatus 把未成团单当成待配送
+ * 拼团状态与后端 GroupBuyClass / xhGroupBuy.status 对齐:1拼团中 2成功 3失败 4已取消
+ */
+
+/** 拼团中 */
+export const GROUP_BUY_STATUS_ONGOING = 1
+/** 拼团成功,可按普通已支付订单履约 */
+export const GROUP_BUY_STATUS_SUCCESS = 2
+/** 拼团失败(自动退款) */
+export const GROUP_BUY_STATUS_FAIL = 3
+/** 拼团已取消 */
+export const GROUP_BUY_STATUS_CANCEL = 4
+
+export const GROUP_BUY_STATUS_TEXT = {
+  1: '拼团中',
+  2: '拼团成功',
+  3: '拼团失败已退款',
+  4: '拼团已取消'
+}
+
+/**
+ * 订单 status 文案,与后端 OrderStatusUtil::getSystemStatusDesc 保持一致
+ * @param {number|string} status 系统订单状态 1-5
+ * @returns {string}
+ */
+export function getSystemStatusDesc(status) {
+  const map = {
+    1: '待付款',
+    2: '待配送',
+    3: '配送中',
+    4: '已完成',
+    5: '已取消'
+  }
+  const key = Number(status)
+  return map[key] || '未知状态'
+}
+
+/**
+ * 是否团购单:groupBuyId > 0
+ * @param {Object} order 订单行/详情
+ * @returns {boolean}
+ */
+export function isGroupBuyOrder(order) {
+  return !!(order && Number(order.groupBuyId) > 0)
+}
+
+/**
+ * 读取拼团状态;兼容接口误写 grouBuyStatus
+ * @param {Object} order 订单行/详情
+ * @returns {number}
+ */
+export function getGroupBuyStatus(order) {
+  if (!order) {
+    return 0
+  }
+  const raw = order.groupBuyStatus != null && order.groupBuyStatus !== ''
+    ? order.groupBuyStatus
+    : order.grouBuyStatus
+  return Number(raw) || 0
+}
+
+/**
+ * 是否已支付:优先 payStatus=1;列表缺字段时用 status 推断(1/5 视为未履约支付)
+ * @param {Object} order 订单行/详情
+ * @returns {boolean}
+ */
+export function isOrderPaid(order) {
+  if (!order) {
+    return false
+  }
+  if (order.payStatus !== undefined && order.payStatus !== null && order.payStatus !== '') {
+    return Number(order.payStatus) === 1
+  }
+  const status = Number(order.status)
+  return status !== 1 && status !== 5
+}
+
+/**
+ * 团购单是否已成团成功,可按普通已支付订单履约/售后
+ * 非团购单直接视为可履约(再由 status / payStatus 决定)
+ * @param {Object} order 订单行/详情
+ * @returns {boolean}
+ */
+export function isGroupBuyFulfillable(order) {
+  if (!isGroupBuyOrder(order)) {
+    return true
+  }
+  return getGroupBuyStatus(order) === GROUP_BUY_STATUS_SUCCESS
+}
+
+/**
+ * 团购失败或团已取消:不可履约、不可支付
+ * @param {Object} order 订单行/详情
+ * @returns {boolean}
+ */
+export function isGroupBuyClosed(order) {
+  if (!isGroupBuyOrder(order)) {
+    return false
+  }
+  const groupBuyStatus = getGroupBuyStatus(order)
+  return groupBuyStatus === GROUP_BUY_STATUS_FAIL || groupBuyStatus === GROUP_BUY_STATUS_CANCEL
+}
+
+/**
+ * 列表/详情主状态文案:拼团未成团/失败时优先展示拼团状态,避免误显示「待配送」
+ * @param {Object} order 订单行/详情
+ * @returns {string}
+ */
+export function getOrderDisplayStatus(order) {
+  if (isGroupBuyOrder(order)) {
+    const groupBuyStatus = getGroupBuyStatus(order)
+    const status = Number(order.status)
+    // 已付款但团未成:展示拼团中,避免误当成待配送
+    if (groupBuyStatus === GROUP_BUY_STATUS_ONGOING && status !== 1 && status !== 5) {
+      return GROUP_BUY_STATUS_TEXT[GROUP_BUY_STATUS_ONGOING]
+    }
+    if (groupBuyStatus === GROUP_BUY_STATUS_FAIL) {
+      return GROUP_BUY_STATUS_TEXT[GROUP_BUY_STATUS_FAIL]
+    }
+    if (groupBuyStatus === GROUP_BUY_STATUS_CANCEL) {
+      return GROUP_BUY_STATUS_TEXT[GROUP_BUY_STATUS_CANCEL]
+    }
+  }
+  if (order && order.statusDesc) {
+    return order.statusDesc
+  }
+  return getSystemStatusDesc(order && order.status)
+}
+
+/**
+ * 详情状态下方提示:拼团单结合成团结果说明下一步
+ * @param {Object} order 订单详情
+ * @returns {string}
+ */
+export function getOrderDisplayHint(order) {
+  if (!order) {
+    return ''
+  }
+  const status = Number(order.status)
+  if (isGroupBuyOrder(order)) {
+    const groupBuyStatus = getGroupBuyStatus(order)
+    // 团已关闭时优先展示最终结果,避免未付款成员仍收到支付提示
+    if (groupBuyStatus === GROUP_BUY_STATUS_FAIL) {
+      return '未成团,款项将原路退回'
+    }
+    if (groupBuyStatus === GROUP_BUY_STATUS_CANCEL) {
+      return '拼团已取消'
+    }
+    if (status === 1) {
+      return '请尽快完成支付,支付后等待成团'
+    }
+    if (groupBuyStatus === GROUP_BUY_STATUS_ONGOING && status !== 5) {
+      return '成团后商家开始备货配送'
+    }
+  }
+  if (status === 1) {
+    return '请尽快完成支付,超时订单可能自动取消'
+  }
+  if (status === 2) {
+    return '商家备货中,请耐心等待配送'
+  }
+  if (status === 3) {
+    return '鲜花配送途中,注意查收'
+  }
+  if (status === 4) {
+    return '订单已完成,感谢您的惠顾'
+  }
+  if (status === 5) {
+    return '订单已取消'
+  }
+  if (status === 6) {
+    return '订单已退款'
+  }
+  return ''
+}
+
+/**
+ * 待付款操作:未取消的待付款单可立即付款(拼团中未支付仍需付款)
+ * @param {Object} order 订单行/详情
+ * @returns {boolean}
+ */
+export function canShowWaitPayAction(order) {
+  return Number(order && order.status) === 1 && !isGroupBuyClosed(order)
+}
+
+/**
+ * 待配送履约操作(联系客服):须已支付,拼团单还须成团成功
+ * @param {Object} order 订单行/详情
+ * @returns {boolean}
+ */
+export function canShowWaitSendAction(order) {
+  return Number(order && order.status) === 2 && isOrderPaid(order) && isGroupBuyFulfillable(order)
+}
+
+/**
+ * 申请售后:非待付款,且拼团须已成团(失败走自动退款)
+ * @param {Object} order 订单详情
+ * @returns {boolean}
+ */
+export function canShowApplyRefundAction(order) {
+  if (!order || Number(order.status) === 1) {
+    return false
+  }
+  // 拼团未成功一律不开放售后,即使旧接口 canApplyRefund 仍为 1
+  if (!isGroupBuyFulfillable(order)) {
+    return false
+  }
+  if (order.canApplyRefund !== undefined && order.canApplyRefund !== null && order.canApplyRefund !== '') {
+    return Number(order.canApplyRefund) === 1
+  }
+  return true
+}