Kaynağa Gözat

结后退款

shish 17 saat önce
ebeveyn
işleme
4e60af23fc

+ 108 - 32
hdApp/src/admin/order/refund.vue

@@ -1,14 +1,17 @@
 <template>
 	<view class="refund-page">
 
-		<!-- 隔天售后提示 -->
-		<view class="warning-tip" v-if="shAddPay == 1">
+		<!-- 隔天售后提示:接口预检 / 本地兜底 / 订单 shAddPay -->
+		<view class="warning-tip" v-if="showNextDayTip">
 			<view class="warning-icon">⚠</view>
 			<text class="warning-text" v-if="shAddPayReason == 1">已过可售后时间,将按隔天售后办理</text>
-			<text class="warning-text" v-else>
-				<block v-if="Number(orderInfo.remainDebtPrice)<=0">订单已结账,将按隔天售后办理</block>
-				<block v-else>订单已部分结账,将按隔天售后办理</block>
+			<text class="warning-text" v-else-if="orderCleared || Number(orderInfo.clearId) > 0 || (Number(orderInfo.debtPrice) > 0 && Number(orderInfo.remainDebtPrice) <= 0)">
+				订单已结账,将按隔天售后办理
 			</text>
+			<text class="warning-text" v-else-if="shAddPay == 1 && Number(orderInfo.remainDebtPrice) > 0">
+				订单已部分结账或售后超额,将按隔天售后办理
+			</text>
+			<text class="warning-text" v-else>非付款日,将按隔天售后办理</text>
 		</view>
 
 		<!-- 退款方式选择卡片 -->
@@ -178,7 +181,7 @@
 			<button class="action-btn confirm-btn" @tap="askRefund">退款</button>
 		</view>
 
-		<!-- 退款确认弹框 -->
+		<!-- 当天售后确认弹框 -->
 		<ModalModule 
 			:show="showRefundModal" 
 			:custom="true" 
@@ -195,30 +198,38 @@
 						<text class="amount-value">¥{{refundMoney}}</text>
 					</view>
 					<view class="confirm-text">
-						<text v-if="shAddPay == 0">确认要退款吗?</text>
-						<text v-else>确认按隔天售后办理吗?</text>
+						<text>确认要退款吗?</text>
 					</view>
 				</view>
 				<view class="modal-actions">
 					<button class="modal-btn cancel-modal-btn" @tap="cancelRefundModal">取消</button>
-					<button class="modal-btn confirm-modal-btn" @tap="executeRefund" v-if="shAddPay == 0">确认退款</button>
-					<button class="modal-btn confirm-modal-btn" @tap="executeRefund" v-else>确认</button>
+					<button class="modal-btn confirm-modal-btn" @tap="executeRefund">确认退款</button>
 				</view>
 			</view>
 		</ModalModule>
+
+		<!-- 隔天售后确认(对齐 ghs:写 sameDay=0,资金原路) -->
+		<forward-options-popup
+			:show="showForwardPop"
+			:order-cleared="orderCleared"
+			@cancel="showForwardPop = false"
+			@confirm="onForwardConfirm"
+		/>
 	</view>
 </template>
 <script>
 /**
  * 花店订单售后页:选择退货商品、填写退款金额并提交。
  * 退货单价直接取订单原单价,只需填数量。
- * 提交成功后统一跳转 admin/billing/forwardResult(资金落地 / 海报 / 原路成功)。
+ * 隔天售后:预检 + 确认弹窗后提交 sameDay=0;成功进 forwardResult
  */
 import { getDetail,refund } from "@/api/order/index";
+import { checkNextDayEligible } from "@/api/refund/index";
 import ModalModule from "@/components/plugin/modal";
+import ForwardOptionsPopup from "@/components/forward-options-popup";
 export default {
 	name: "orderDetail",
-	components: { ModalModule },
+	components: { ModalModule, ForwardOptionsPopup },
 	data() {
 		return {
 			goodsInfoList:[],
@@ -230,12 +241,20 @@ export default {
 			orderInfo:{},
 			coundRefundPrice:0,
 			showRefundModal: false,
-			shAddPay:0,//0正常当天售后,1隔天售后
+			showForwardPop: false,
+			nextDayEligible: false,
+			orderCleared: false,
+			_pendingRefundParams: null,
+			shAddPay:0,//0正常当天售后,1隔天售后(订单详情兜底)
 			shAddPayReason:0,//0欠款已结清或部分结清,1可售后时间到了
 		};
 	},
 
 	computed:{
+		/** 顶部隔天提示:接口预检 / 本地兜底 / 订单 shAddPay */
+		showNextDayTip() {
+			return this.nextDayEligible || this.shAddPay == 1 || this.isMustNextDayOrder()
+		},
 		canRefundBackHb(){
 			// 订单全额退款时(即 refundMoney == coundRefundPrice),红包才能选择退回
 			if (this.refundMoney === '' || this.refundMoney === null || this.refundMoney === undefined) return false
@@ -379,9 +398,57 @@ export default {
 				return false
 			}
 
-			// 显示确认退款弹框
+			const selectProductJson = JSON.stringify(selectProduct)
+			this._pendingRefundParams = {
+				product: selectProductJson,
+				id: this.option.id,
+				price: this.refundMoney,
+				remark: this.remark,
+				refundType: this.refundType,
+				refundHb: this.refundHb,
+				getOriginalItem: 1,
+				version: 2
+			}
+			// 非当天 / 已结清 / 预检通过 → 隔天售后确认弹窗
+			if (this.nextDayEligible || this.shAddPay == 1 || this.isMustNextDayOrder()) {
+				if (!this.nextDayEligible && !this.orderCleared) {
+					this.orderCleared = Number(this.orderInfo.clearId) > 0
+						|| (Number(this.orderInfo.debtPrice) > 0 && Number(this.orderInfo.remainDebtPrice) <= 0)
+				}
+				this.showForwardPop = true
+				return
+			}
+			// 当天售后:原确认弹框
 			this.showRefundModal = true
 		},
+		/** 是否有有效支付时间(与后端 hasValidPayTime 一致) */
+		hasValidPayTime() {
+			const payTime = (this.orderInfo && this.orderInfo.payTime) || ''
+			return !!payTime && payTime !== '0000-00-00 00:00:00'
+		},
+		/**
+		 * 本地判断是否必须隔天售后:非当天支付 / 已结账单 / 挂账已结清
+		 */
+		isMustNextDayOrder() {
+			const info = this.orderInfo || {}
+			if (!this.hasValidPayTime()) {
+				return false
+			}
+			if (Number(info.clearId) > 0) {
+				return true
+			}
+			const debtPrice = Number(info.debtPrice) || 0
+			const remainDebt = Number(info.remainDebtPrice) || 0
+			if (debtPrice > 0 && remainDebt === 0) {
+				return true
+			}
+			const payDay = String(info.payTime).substr(0, 10)
+			const now = new Date()
+			const m = now.getMonth() + 1
+			const d = now.getDate()
+			const today = now.getFullYear() + '-' + (m < 10 ? '0' + m : m) + '-' + (d < 10 ? '0' + d : d)
+			return payDay !== today
+		},
 		// 弹框相关方法
 		handleRefundModalClick(e) {
 			// 处理弹框点击事件
@@ -389,26 +456,20 @@ export default {
 		cancelRefundModal() {
 			this.showRefundModal = false
 		},
+		/** 当天售后确认提交 */
 		executeRefund() {
 			this.showRefundModal = false
-			// 获取之前验证过的商品数据
-			let selectProduct = []
-			if(!this.$util.isEmpty(this.goodsInfoList)){
-				this.goodsInfoList.forEach(ele=>{
-					if(Number(ele.refundCount)>0){
-						selectProduct.push({"productId":ele.goodsId,"num":ele.refundCount,"unitType":ele.unitType,unitName:ele.unitName,unitPrice:ele.unitPrice,property:0})
-					}
-				})
-			}
-			if(!this.$util.isEmpty(this.itemInfoList)){
-				this.itemInfoList.forEach(ele=>{
-					if(Number(ele.refundCount)>0){
-						selectProduct.push({"productId":ele.itemId,"num":ele.refundCount,"unitType":ele.unitType,unitName:ele.unitName,unitPrice:ele.unitPrice,property:1})
-					}
-				})
-			}
-			let refundParams = {product:JSON.stringify(selectProduct),id: this.option.id,price:this.refundMoney,remark:this.remark,refundType:this.refundType,refundHb:this.refundHb,getOriginalItem:1,version:2}
-			this.doRefund(refundParams)
+			this.doRefund(this._pendingRefundParams || {})
+		},
+		/**
+		 * 隔天售后确认:写 sameDay=0,资金按原单原路处理
+		 */
+		onForwardConfirm() {
+			this.showForwardPop = false
+			const params = Object.assign({}, this._pendingRefundParams || {}, {
+				sameDay: 0
+			})
+			this.doRefund(params)
 		},
 		/**
 		 * 提交售后退款;成功后统一进 forwardResult(对齐 ghs 端)
@@ -471,6 +532,21 @@ export default {
 			this.itemInfoList = res.data.itemInfoList.map(ele=>{
 				return {...ele,refundCount:null}
 			})
+
+			// 预检是否可走隔天售后(对齐 ghs)
+			checkNextDayEligible({ orderId: this.option.id }).then(r => {
+				if (r.code == 1 && r.data && r.data.ok) {
+					this.nextDayEligible = true
+					this.orderCleared = Number(r.data.orderCleared) === 1
+				} else {
+					this.nextDayEligible = false
+					if (!this.orderCleared) {
+						this.orderCleared = Number(this.orderInfo.clearId) > 0
+					}
+				}
+			}).catch(() => {
+				this.nextDayEligible = false
+			})
 		}
 	}
 };

+ 10 - 2
hdApp/src/admin/order/refundDetail.vue

@@ -241,7 +241,7 @@ export default {
 	methods: {
 		/** 拉取售后详情并回填商品/金额/资金字段 */
 		init() {
-			refundDetail({ id: this.option.id }).then(res => {
+			return refundDetail({ id: this.option.id }).then(res => {
 				if (res.code != 1 || !res.data) {
 					return
 				}
@@ -283,6 +283,9 @@ export default {
 				}
 			)
 		},
+		/**
+		 * 审核通过:成功后若已返充余额则进凭证页(对齐 ghs)
+		 */
 		doPass() {
 			this.busy = true
 			uni.showLoading({ mask: true, title: '处理中' })
@@ -291,7 +294,12 @@ export default {
 				this.busy = false
 				if (res.code == 1) {
 					this.$msg(res.msg || '已通过')
-					this.init()
+					// 通过后若已返充余额,直接进凭证页(对齐 ghs)
+					this.init().then(() => {
+						if (this.canShowPoster) {
+							this.goPoster()
+						}
+					})
 				}
 			}).catch(() => {
 				uni.hideLoading()

+ 5 - 0
hdApp/src/api/refund/index.js

@@ -41,3 +41,8 @@ export const markHasReturn = data => {
 export const returnBalance = data => {
 	return https.post('/refund/return-balance', data)
 }
+
+/** 原单是否可走隔天售后(预检,对齐 ghs) */
+export const checkNextDayEligible = data => {
+	return https.get('/refund/check-next-day-eligible', data)
+}

+ 110 - 0
hdApp/src/components/forward-options-popup.vue

@@ -0,0 +1,110 @@
+<!--
+  隔天售后确认弹框
+  用途:隔天/已结账售后二次确认;资金默认原路,不再选手选 fundType。
+  mode=purchase:上游采购文案(退回采购账户余额)
+-->
+<template>
+	<view v-if="show" class="mask" @click="onCancel">
+		<view class="panel" @click.stop>
+			<view class="title">退款确认</view>
+			<view class="tip">{{ tipText }}</view>
+			<view class="btns">
+				<button class="popup-btn cancel" @click="onCancel">取消</button>
+				<button class="popup-btn confirm" @click="onOk">确认退款</button>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	name: 'forward-options-popup',
+	props: {
+		show: { type: Boolean, default: false },
+		// 已结账单当天售后也走隔天口径
+		orderCleared: { type: Boolean, default: false },
+		// free=无原单退款;purchase=上游采购隔天
+		mode: { type: String, default: '' }
+	},
+	computed: {
+		tipText() {
+			if (this.mode === 'free') {
+				return '无关联销售单:退货回库;资金请在成功页确认按原路退回或返充余额。'
+			}
+			if (this.mode === 'purchase') {
+				if (this.orderCleared) {
+					return '采购单已结清,本次售后不减实付,只会算今天退款;金额将退回采购账户余额。'
+				}
+				return '本次售后不减采购实付,只会算作今天退款;金额将退回采购账户余额。'
+			}
+			if (this.orderCleared) {
+				return '订单已结账,本次售后不减订单实付,只会算今天退款;资金将原路退回。'
+			}
+			return '本次售后不减订单实付,只会算今天退款;资金将原路退回。'
+		}
+	},
+	methods: {
+		onCancel() {
+			this.$emit('cancel')
+		},
+		onOk() {
+			this.$emit('confirm', {})
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.mask {
+	position: fixed;
+	left: 0;
+	right: 0;
+	top: 0;
+	bottom: 0;
+	background: rgba(0, 0, 0, 0.45);
+	z-index: 1000;
+	display: flex;
+	align-items: flex-end;
+	justify-content: center;
+}
+.panel {
+	width: 100%;
+	background: #fff;
+	border-radius: 24upx 24upx 0 0;
+	padding: 36upx 32upx calc(24upx + env(safe-area-inset-bottom));
+	box-sizing: border-box;
+}
+.title {
+	font-size: 46upx;
+	font-weight: bold;
+	color: #333;
+	text-align: center;
+	margin-bottom: 16upx;
+}
+.tip {
+	font-size: 38upx;
+	color: #666;
+	line-height: 1.6;
+	margin-bottom: 60upx;
+}
+.btns {
+	display: flex;
+	justify-content: space-between;
+}
+.popup-btn {
+	flex: 1;
+	height: 100upx;
+	line-height: 100upx;
+	border-radius: 12upx;
+	font-size: 36upx;
+	margin: 0 10upx;
+}
+.popup-btn.cancel {
+	background: #f5f5f5;
+	color: #666;
+}
+.popup-btn.confirm {
+	background: #3385ff;
+	color: #fff;
+}
+</style>