shish 12 цаг өмнө
parent
commit
23d4b7d0af

+ 276 - 5
ghsApp/src/admin/billing/forwardResult.vue

@@ -4,6 +4,7 @@
     1) 无原单退款、线下原单售后成功后:选手选「已线下转账」或「返充到客户余额」
     1) 无原单退款、线下原单售后成功后:选手选「已线下转账」或「返充到客户余额」
     2) 已返充余额、挂账原路:绘制带小程序码的退款凭证海报
     2) 已返充余额、挂账原路:绘制带小程序码的退款凭证海报
     3) 其它原路退回:说明退到哪里、怎么退
     3) 其它原路退回:说明退到哪里、怎么退
+    4) 退货并退款:海报/成功区下方展示花材,可报损、减库存、选售后原因(对齐 refundSuccess)
   谁用:freeRefundConfirm、refund.vue 售后、售后详情/列表补发。
   谁用:freeRefundConfirm、refund.vue 售后、售后详情/列表补发。
 -->
 -->
 <template>
 <template>
@@ -67,6 +68,75 @@
       </button>
       </button>
     </appResult>
     </appResult>
 
 
+    <!-- 退货并退款:海报/成功区后面展示花材,可报损、减库存(当天/跨天一致) -->
+    <view v-if="showWasteSection" class="waste-section">
+      <view class="waste-section__title">退回花材</view>
+      <block v-for="(item, index) in itemList" :key="index">
+        <view class="waste-item">
+          <text class="waste-item__name" @click="pageTo({url:'/admin/item/detail?id='+item.productId})">
+            {{item.name}} <text class="waste-item__back">已退回{{item.xhNum}}{{item.xhUnitName}}</text>
+          </text>
+          <view class="waste-item__stat" v-if="Number(item.xhWasteNum)>0">
+            <text class="waste-item__stat-text">已报损{{item.xhWasteNum}}{{item.xhUnitName}}</text>
+          </view>
+          <view class="waste-item__stat" v-if="Number(item.xhReduceNum)>0">
+            <text class="waste-item__stat-text">已减库存{{item.xhReduceNum}}{{item.xhUnitName}}</text>
+          </view>
+          <view class="waste-item__option" v-if="item.refundOptionId!=0">{{ item.refundOptionName }}</view>
+          <view class="waste-item__actions">
+            <button class="admin-button-com middle waste-btn" @click="selOption(item)">售后原因</button>
+            <button class="admin-button-com middle waste-btn" @click="beginWastage(item)" v-if="item.xhUnitType == 0">报损</button>
+            <button class="admin-button-com middle waste-btn" @click="pageTo({url:'/admin/item/detail?id='+item.productId})" v-else>去损报</button>
+            <button class="admin-button-com middle default waste-btn" @click="beginReduce(item)">减库存</button>
+          </view>
+        </view>
+      </block>
+    </view>
+
+    <modal-module :show="wastageShow" @click="confirmWastage" :maskClosable="true" title="报损数量" padding="30rpx 30rpx" >
+      <template v-slot:content>
+        <div class="app-modal-input-wrap">
+          <div class="inp-list-line">
+            <div class="line-input">
+              <input type="number" style="width:61.8%;text-align:center;" v-model="wastageNum" :adjust-position="false" class="inp-input" @focus="wastageNum=''" />
+            </div>
+          </div>
+        </div>
+      </template>
+    </modal-module>
+
+    <modal-module :show="reduceShow" @click="confirmReduce" :maskClosable="true" title="减少数量" padding="30rpx 30rpx" >
+      <template v-slot:content>
+        <div class="app-modal-input-wrap">
+          <div class="inp-list-line">
+            <div class="line-input">
+              <input type="number" style="width:61.8%;text-align:center;" v-model="reduceNum" :adjust-position="false" class="inp-input" @focus="reduceNum=''" />
+            </div>
+          </div>
+        </div>
+      </template>
+    </modal-module>
+
+    <uni-popup ref="optionRef" background-color="#fff" type="center" :animation="false" class="class-popup-style">
+      <view class="option-popup">
+        <view class="option-popup__title">请选择:</view>
+        <view class="option-popup__list">
+          <view v-for="(item, index) in refundOption" :key="index" class="option-popup__item">
+            <button
+              class="admin-button-com staff-btn"
+              @click.stop="getOption(item)"
+              :class="{'selected': currentInfo.refundOptionId === item.id}"
+            >
+              {{ item.name }}
+            </button>
+          </view>
+        </view>
+        <view class="option-popup__cancel">
+          <button class="admin-button-com big blue" style="width:210upx;" @click="cancelOption()">取消选择</button>
+        </view>
+      </view>
+    </uni-popup>
+
     <!-- 离屏 canvas,用于绘制凭证海报 -->
     <!-- 离屏 canvas,用于绘制凭证海报 -->
     <canvas
     <canvas
       canvas-id="forwardPosterCanvas"
       canvas-id="forwardPosterCanvas"
@@ -79,9 +149,10 @@
 <script>
 <script>
 import dayjs from 'dayjs'
 import dayjs from 'dayjs'
 import appResult from '@/components/app-result'
 import appResult from '@/components/app-result'
+import ModalModule from '@/components/plugin/modal'
 import { getGatheringMiniCode } from '@/api/custom'
 import { getGatheringMiniCode } from '@/api/custom'
 import { getUserDet } from '@/api/member'
 import { getUserDet } from '@/api/member'
-import { markHasReturn, returnBalance } from '@/api/refund'
+import { markHasReturn, returnBalance, refundDetail, refundWaste, refundReduce, changeRefundOption } from '@/api/refund'
 
 
 /** 本地缓存键:跳转本页前写入,onLoad 与 URL 参数合并 */
 /** 本地缓存键:跳转本页前写入,onLoad 与 URL 参数合并 */
 const STORAGE_KEY = 'forwardResultPayload'
 const STORAGE_KEY = 'forwardResultPayload'
@@ -89,7 +160,8 @@ const STORAGE_KEY = 'forwardResultPayload'
 export default {
 export default {
   name: 'forwardResult',
   name: 'forwardResult',
   components: {
   components: {
-    appResult
+    appResult,
+    ModalModule
   },
   },
   data() {
   data() {
     return {
     return {
@@ -114,7 +186,17 @@ export default {
       canvasW: 360,
       canvasW: 360,
       canvasH: 640,
       canvasH: 640,
       // 当天=1 / 跨天=0,挂账海报文案区分减欠款 vs 加余额
       // 当天=1 / 跨天=0,挂账海报文案区分减欠款 vs 加余额
-      sameDay: 1
+      sameDay: 1,
+      // 1=退货并退款,需展示报损花材区
+      refundType: 0,
+      itemList: [],
+      refundOption: [],
+      currentInfo: {},
+      wastageShow: false,
+      wastageNum: 0,
+      refundItemId: 0,
+      reduceShow: false,
+      reduceNum: 0
     }
     }
   },
   },
   computed: {
   computed: {
@@ -134,6 +216,10 @@ export default {
     showPoster() {
     showPoster() {
       return Number(this.returnBalance) === 1 || this.isBalanceOrDebtOriginReturn
       return Number(this.returnBalance) === 1 || this.isBalanceOrDebtOriginReturn
     },
     },
+    /** 退货并退款且有花材明细时,在海报/成功区后展示报损操作 */
+    showWasteSection() {
+      return Number(this.refundType) === 1 && !this.$util.isEmpty(this.itemList)
+    },
     posterPageTitle() {
     posterPageTitle() {
       if (this.isBalanceOrDebtOriginReturn) return '原路退回成功'
       if (this.isBalanceOrDebtOriginReturn) return '原路退回成功'
       return '退款成功'
       return '退款成功'
@@ -259,11 +345,14 @@ export default {
         this.needFundAction = 1
         this.needFundAction = 1
       }
       }
       this.sameDay = payload.sameDay != null ? Number(payload.sameDay) : 1
       this.sameDay = payload.sameDay != null ? Number(payload.sameDay) : 1
+      this.refundType = payload.refundType != null ? Number(payload.refundType) : 0
 
 
       // 返充或挂账原路:生成带小程序码的凭证海报
       // 返充或挂账原路:生成带小程序码的凭证海报
       if (this.showPoster && this.customId > 0) {
       if (this.showPoster && this.customId > 0) {
         this.generatePoster()
         this.generatePoster()
       }
       }
+      // 有售后单 id 则拉详情:确认退货并退款后展示报损花材
+      this.loadWasteItems()
     },
     },
 
 
     /** 同步缓存,避免返回再进丢状态 */
     /** 同步缓存,避免返回再进丢状态 */
@@ -283,7 +372,104 @@ export default {
         couldReturn: this.couldReturn,
         couldReturn: this.couldReturn,
         returnBalance: this.returnBalance,
         returnBalance: this.returnBalance,
         needFundAction: this.needFundAction,
         needFundAction: this.needFundAction,
-        sameDay: this.sameDay
+        sameDay: this.sameDay,
+        refundType: this.refundType
+      })
+    },
+
+    /**
+     * 拉取售后明细:退货并退款时填充花材列表,供报损/减库存
+     */
+    loadWasteItems() {
+      if (!this.forwardId) {
+        return
+      }
+      refundDetail({ id: this.forwardId }).then(res => {
+        if (res.code != 1 || !res.data) {
+          return
+        }
+        const info = res.data.info || {}
+        // 以详情为准,避免入口漏传 refundType
+        if (info.refundType != null) {
+          this.refundType = Number(info.refundType)
+        }
+        if (Number(this.refundType) === 1) {
+          this.itemList = res.data.itemList || []
+          this.refundOption = res.data.itemRefundOption || []
+        } else {
+          this.itemList = []
+        }
+        this.persistPayload()
+      })
+    },
+
+    beginWastage(item) {
+      this.wastageShow = true
+      this.wastageNum = item.xhNum
+      this.refundItemId = item.id
+    },
+    hideWaste() {
+      this.wastageShow = false
+      this.wastageNum = 0
+    },
+    confirmWastage(val) {
+      if (val.index === 0) {
+        this.hideWaste()
+        return false
+      }
+      refundWaste({
+        wasteNum: this.wastageNum,
+        remark: '退货时报损',
+        refundItemId: this.refundItemId
+      }).then(res => {
+        if (res.code == 1) {
+          this.hideWaste()
+          this.loadWasteItems()
+        }
+      })
+    },
+    beginReduce(item) {
+      this.reduceShow = true
+      this.reduceNum = item.xhNum
+      this.refundItemId = item.id
+    },
+    hideReduce() {
+      this.reduceShow = false
+      this.reduceNum = 0
+    },
+    confirmReduce(val) {
+      if (val.index === 0) {
+        this.hideReduce()
+        return false
+      }
+      refundReduce({
+        reduceNum: this.reduceNum,
+        refundItemId: this.refundItemId
+      }).then(res => {
+        if (res.code == 1) {
+          this.hideReduce()
+          this.loadWasteItems()
+        }
+      })
+    },
+    selOption(info) {
+      this.currentInfo = info
+      this.$refs.optionRef.open('center')
+    },
+    cancelOption() {
+      this.$refs.optionRef.close()
+    },
+    getOption(item) {
+      changeRefundOption({
+        id: this.forwardId,
+        sonId: this.currentInfo.id,
+        optionId: item.id
+      }).then(res => {
+        if (res.code == 1) {
+          this.$msg('修改成功')
+          this.loadWasteItems()
+          this.$refs.optionRef.close()
+        }
       })
       })
     },
     },
 
 
@@ -617,7 +803,7 @@ export default {
 }
 }
 
 
 .poster-img {
 .poster-img {
-  width: 480upx;
+  width: 450upx;
   max-width: 100%;
   max-width: 100%;
   border-radius: 12upx;
   border-radius: 12upx;
   box-shadow: 0 8upx 24upx rgba(0, 0, 0, 0.12);
   box-shadow: 0 8upx 24upx rgba(0, 0, 0, 0.12);
@@ -665,4 +851,89 @@ export default {
   top: -9999px;
   top: -9999px;
   z-index: -1;
   z-index: -1;
 }
 }
+
+.waste-section {
+  margin: 20upx 24upx 40upx;
+  padding: 24upx 20upx 10upx;
+  background: #fff;
+  border-radius: 16upx;
+}
+.waste-section__title {
+  margin-bottom: 20upx;
+  font-size: 30upx;
+  font-weight: bold;
+  color: #333;
+  text-align: center;
+}
+.waste-item {
+  margin-bottom: 28upx;
+  padding-bottom: 20upx;
+  border-bottom: 1upx solid #f0f0f0;
+  text-align: center;
+}
+.waste-item:last-child {
+  border-bottom: 0;
+}
+.waste-item__name {
+  font-size: 32upx;
+  color: #333;
+}
+.waste-item__back {
+  margin-left: 8upx;
+  color: #3385ff;
+}
+.waste-item__stat {
+  margin-top: 10upx;
+}
+.waste-item__stat-text {
+  margin-left: 12upx;
+  color: red;
+  font-size: 30upx;
+  font-weight: bold;
+}
+.waste-item__option {
+  margin-top: 10upx;
+  color: #ad760d;
+  font-size: 30upx;
+}
+.waste-item__actions {
+  width: 100%;
+  margin-top: 16upx;
+}
+.waste-btn {
+  width: 150upx;
+  margin-left: 20upx;
+  margin-bottom: 12upx;
+}
+.waste-btn:first-child {
+  margin-left: 0;
+  width: 160upx;
+}
+.option-popup {
+  max-height: 90vh;
+  overflow: scroll;
+}
+.option-popup__title {
+  margin-left: 30upx;
+  margin-top: 19upx;
+  font-size: 27upx;
+  font-weight: bold;
+}
+.option-popup__list {
+  display: flex;
+  padding: 20upx;
+  justify-content: flex-start;
+  align-items: center;
+  flex-wrap: wrap;
+  max-height: 100vh;
+  overflow: auto;
+}
+.option-popup__item {
+  margin-bottom: 20upx;
+  margin-left: 3upx;
+}
+.option-popup__cancel {
+  text-align: center;
+  padding: 10upx 0;
+}
 </style>
 </style>

+ 3 - 1
ghsApp/src/pagesOrder/refund.vue

@@ -436,7 +436,9 @@ export default {
 							couldReturn: data.couldReturn != null ? data.couldReturn : 1,
 							couldReturn: data.couldReturn != null ? data.couldReturn : 1,
 							returnBalance: data.returnBalance || 0,
 							returnBalance: data.returnBalance || 0,
 							needFundAction: needFund ? 1 : 0,
 							needFundAction: needFund ? 1 : 0,
-							sameDay: data.sameDay != null ? data.sameDay : (refundParams.sameDay != null ? refundParams.sameDay : 1)
+							sameDay: data.sameDay != null ? data.sameDay : (refundParams.sameDay != null ? refundParams.sameDay : 1),
+							// 退货并退款:结果页海报后展示报损/减库存花材
+							refundType: data.refundType != null ? data.refundType : that.refundType
 						}
 						}
 						uni.setStorageSync('forwardResultPayload', payload)
 						uni.setStorageSync('forwardResultPayload', payload)
 						that.$util.pageTo({
 						that.$util.pageTo({

+ 2 - 0
ghsApp/src/pagesOrder/refundDetail.vue

@@ -422,6 +422,8 @@ export default {
 				returnBalance: info.returnBalance || 0,
 				returnBalance: info.returnBalance || 0,
 				needFundAction: this.canFundAction ? 1 : 0,
 				needFundAction: this.canFundAction ? 1 : 0,
 				sameDay: info.sameDay != null ? info.sameDay : 1,
 				sameDay: info.sameDay != null ? info.sameDay : 1,
+				// 退货并退款时结果页可继续报损/减库存
+				refundType: info.refundType != null ? info.refundType : this.refundType,
 				mode: mode || ''
 				mode: mode || ''
 			}
 			}
 		},
 		},