|
@@ -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>
|