shish 4 дней назад
Родитель
Сommit
bfefc8fa53

+ 380 - 27
ghsApp/src/admin/billing/forwardResult.vue

@@ -1,73 +1,389 @@
 <!--
-  冲销成功结果页(方案A)
-  用途:create 成功后跳转;fundType=2(返余额)时展示收款小程序码海报,其它仅简单成功提示。
+  冲销成功 / 退款凭证页(方案A)
+  用途:create 成功且 fundType=返余额时,本地 canvas 绘制「退款凭证」海报(含收款小程序码),
+  海报图直接展示在本页(不弹框),可长按转发或保存;其它 fundType 仅展示简单成功信息。
 -->
 <template>
 	<appResult title="冲销成功">
-		<view class="forward-info" v-if="Number(fundType) === 2">
-			<text class="forward-info__amount">已返充 ¥{{ actPrice }} 到 {{ customName || '客户' }} 余额</text>
-			<text class="forward-info__sn" v-if="forwardSn">冲销单号 {{ forwardSn }}</text>
-		</view>
-		<view class="forward-info" v-else>
-			<text class="forward-info__amount">冲销成功 ¥{{ actPrice }}</text>
+		<!-- 返余额:金额/单号/余额已在海报图内展示,页面上不再重复 -->
+		<view class="forward-info" v-if="Number(fundType) !== 2">
+			<text class="forward-info__amount">冲销成功 ¥{{ formatMoney(actPrice) }}</text>
 			<text class="forward-info__sn" v-if="forwardSn">冲销单号 {{ forwardSn }}</text>
 			<text class="forward-info__tip">{{ fundTypeTip }}</text>
 		</view>
 
-		<!-- 返余额:展示小程序码海报,客户可扫码充值 -->
-		<view class="poster-wrap" v-if="Number(fundType) === 2 && miniCodeUrl">
-			<image class="poster-img" :src="miniCodeUrl" mode="widthFix" show-menu-by-longpress />
-			<text class="poster-tip">长按图片可转发或保存,客户扫码向您充值</text>
+		<!-- 退款凭证海报:直接展示在页面上 -->
+		<view class="poster-wrap" v-if="Number(fundType) === 2">
+			<view v-if="drawing && !posterUrl" class="poster-loading">
+				<text>凭证生成中...</text>
+			</view>
+			<image
+				v-if="posterUrl"
+				class="poster-img"
+				:src="posterUrl"
+				mode="widthFix"
+				show-menu-by-longpress
+			/>
+			<text v-if="posterUrl" class="poster-tip">长按图片转发或保存到相册</text>
 		</view>
 
-		<button class="admin-button-com big blue" v-if="orderId" @click="goOrder">查看原单</button>
-		<button class="admin-button-com big" @click="goHome">返回首页</button>
+		<!-- 底部操作按钮统一宽度,与海报视觉对齐 -->
+		<view class="btn-col">
+			<button
+				v-if="Number(fundType) === 2 && posterUrl"
+				class="admin-button-com big blue btn-item"
+				@click="savePosterImg"
+			>保存到相册</button>
+			<button
+				v-if="Number(fundType) === 2 && !posterUrl && !drawing"
+				class="admin-button-com big blue btn-item"
+				@click="generatePoster"
+			>重新生成凭证</button>
+			<button
+				v-if="orderId"
+				class="admin-button-com big blue btn-item"
+				@click="goOrder"
+			>查看原单</button>
+			<button class="admin-button-com big btn-item" @click="goHome">返回首页</button>
+		</view>
+
+		<canvas
+			canvas-id="forwardPosterCanvas"
+			class="poster-canvas"
+			:style="{ width: canvasW + 'px', height: canvasH + 'px' }"
+		/>
 	</appResult>
 </template>
 
 <script>
 import appResult from '@/components/app-result'
 import { getGatheringMiniCode } from '@/api/custom'
+import { getUserDet } from '@/api/member'
+import dayjs from 'dayjs'
+
+// 冲销成功页缓存 key:绕过小程序 URL 长度限制,保证 customBalance 不丢
+const FORWARD_RESULT_CACHE_KEY = 'forwardResultPayload'
 
 export default {
 	name: 'forwardResult',
-	components: { appResult },
+	components: {
+		appResult
+	},
 	data() {
 		return {
 			fundType: 0,
 			actPrice: 0,
 			customId: 0,
 			customName: '',
+			customBalance: null,
 			forwardSn: '',
 			forwardId: 0,
 			orderId: 0,
-			miniCodeUrl: ''
+			posterUrl: '',
+			drawing: false,
+			canvasW: 360,
+			canvasH: 640
 		}
 	},
 	computed: {
 		fundTypeTip() {
 			const map = { 1: '已发起原路退回', 2: '已返充余额', 3: '仅记账,未动资金' }
 			return map[Number(this.fundType)] || ''
+		},
+		hasBalance() {
+			return this.customBalance !== null && this.customBalance !== '' && !isNaN(Number(this.customBalance))
 		}
 	},
 	onLoad(option) {
 		this.fundType = Number(option.fundType || 0)
 		this.actPrice = parseFloat(option.amount || option.actPrice || 0)
 		this.customId = Number(option.customId || 0)
-		this.customName = option.customName || ''
+		try {
+			this.customName = decodeURIComponent(option.customName || '')
+		} catch (e) {
+			this.customName = option.customName || ''
+		}
+		// 兼容 query 传数字/字符串;缺省为 null,海报里不画成 --
+		if (option.customBalance !== undefined && option.customBalance !== null && option.customBalance !== '') {
+			const bal = parseFloat(option.customBalance)
+			this.customBalance = isNaN(bal) ? null : bal
+		} else {
+			this.customBalance = null
+		}
 		this.forwardSn = option.forwardSn || ''
 		this.forwardId = Number(option.forwardId || 0)
 		this.orderId = Number(option.orderId || 0)
-		// 返余额时拉取收款小程序码做海报
+		// 优先用本地缓存补全(create 成功页写入),避免 query 丢余额
+		this.applyCachedPayload()
 		if (this.fundType === 2 && this.customId > 0) {
-			this.loadMiniCode()
+			this.generatePoster()
 		}
 	},
 	methods: {
-		loadMiniCode() {
-			getGatheringMiniCode({ id: this.customId }).then(res => {
+		formatMoney(v) {
+			const n = Number(v)
+			if (isNaN(n)) {
+				return '0.00'
+			}
+			return n.toFixed(2)
+		},
+		/**
+		 * 读取冲销成功跳转前写入的缓存,补全余额/单号等关键字段
+		 */
+		applyCachedPayload() {
+			try {
+				const cached = uni.getStorageSync(FORWARD_RESULT_CACHE_KEY)
+				if (!cached || typeof cached !== 'object') {
+					return
+				}
+				// 仅在同一次冲销(forwardId/customId 对得上)时采用缓存,避免串数据
+				const sameForward = !cached.forwardId || !this.forwardId || Number(cached.forwardId) === Number(this.forwardId)
+				const sameCustom = !cached.customId || !this.customId || Number(cached.customId) === Number(this.customId)
+				if (!sameForward || !sameCustom) {
+					return
+				}
+				if (!this.hasBalance) {
+					this.applyBalanceFromApi(cached.customBalance)
+				}
+				if (!this.customName && cached.customName) {
+					this.customName = cached.customName
+				}
+				if (!this.forwardSn && cached.forwardSn) {
+					this.forwardSn = cached.forwardSn
+				}
+				if (!this.customId && cached.customId) {
+					this.customId = Number(cached.customId)
+				}
+				if (!this.orderId && cached.orderId) {
+					this.orderId = Number(cached.orderId)
+				}
+				if (!this.actPrice && cached.amount != null) {
+					this.actPrice = parseFloat(cached.amount) || 0
+				}
+				if (!this.fundType && cached.fundType != null) {
+					this.fundType = Number(cached.fundType)
+				}
+				uni.removeStorageSync(FORWARD_RESULT_CACHE_KEY)
+			} catch (e) {
+				// 缓存读失败不影响主流程,后续走接口补余额
+			}
+		},
+		/**
+		 * 用接口/缓存返回的客户余额补全页面/海报展示
+		 */
+		applyBalanceFromApi(raw) {
+			if (raw === undefined || raw === null || raw === '') {
+				return
+			}
+			const bal = parseFloat(raw)
+			if (!isNaN(bal)) {
+				this.customBalance = bal
+			}
+		},
+		/**
+		 * 生成凭证:并行拉小程序码 + 客户详情余额,保证「最新余额」一定有数
+		 */
+		generatePoster() {
+			if (!this.customId || this.drawing) {
+				return
+			}
+			this.drawing = true
+			this.posterUrl = ''
+			uni.showLoading({ mask: true, title: '生成凭证中' })
+			const that = this
+			const codeReq = getGatheringMiniCode({
+				id: this.customId,
+				env_version: this.$util.getMiniEnvVersion ? this.$util.getMiniEnvVersion() : 'release'
+			})
+			// 客户详情是余额权威来源;query/拉码任一丢参时仍能画出正确余额
+			const detailReq = getUserDet({ id: this.customId }).catch(() => null)
+			Promise.all([codeReq, detailReq]).then(([res, detRes]) => {
+				if (detRes && detRes.code == 1 && detRes.data) {
+					that.applyBalanceFromApi(detRes.data.balance)
+				}
 				if (res.code == 1 && res.data && res.data.imgUrl) {
-					this.miniCodeUrl = res.data.imgUrl
+					that.applyBalanceFromApi(res.data.balance)
+					uni.downloadFile({
+						url: res.data.imgUrl,
+						success: downloadRes => {
+							if (downloadRes.statusCode === 200) {
+								that.drawPoster(downloadRes.tempFilePath)
+							} else {
+								that.drawing = false
+								uni.hideLoading()
+								uni.showToast({ title: '小程序码下载失败', icon: 'none' })
+							}
+						},
+						fail: () => {
+							that.drawing = false
+							uni.hideLoading()
+							uni.showToast({ title: '小程序码下载失败', icon: 'none' })
+						}
+					})
+				} else {
+					that.drawing = false
+					uni.hideLoading()
+					uni.showToast({ title: res.msg || '获取小程序码失败', icon: 'none' })
+				}
+			}).catch(() => {
+				that.drawing = false
+				uni.hideLoading()
+			})
+		},
+		/**
+		 * 按可用宽度缩小单号字号,保证与「冲销单号」标签同一行且不重叠
+		 */
+		fitSnFontSize(ctx, sn, maxWidth) {
+			let size = 16
+			while (size > 10) {
+				ctx.setFontSize(size)
+				const measured = ctx.measureText ? ctx.measureText(sn) : null
+				const w = measured && measured.width ? measured.width : sn.length * size * 0.62
+				if (w <= maxWidth) {
+					return size
+				}
+				size -= 1
+			}
+			return 10
+		},
+		/**
+		 * 绘制退款凭证海报。
+		 * 冲销单号与标签同一行:单号用更小字号,避免换行难看,也避免盖住左侧文案。
+		 */
+		drawPoster(qrPath) {
+			const that = this
+			const ctx = uni.createCanvasContext('forwardPosterCanvas', this)
+			const width = this.canvasW
+			const height = this.canvasH
+			const radius = 20
+			const padX = 30
+
+			ctx.save()
+			ctx.beginPath()
+			ctx.moveTo(radius, 0)
+			ctx.lineTo(width - radius, 0)
+			ctx.arcTo(width, 0, width, radius, radius)
+			ctx.lineTo(width, height - radius)
+			ctx.arcTo(width, height, width - radius, height, radius)
+			ctx.lineTo(radius, height)
+			ctx.arcTo(0, height, 0, height - radius, radius)
+			ctx.lineTo(0, radius)
+			ctx.arcTo(0, 0, radius, 0, radius)
+			ctx.closePath()
+			ctx.clip()
+
+			ctx.setFillStyle('#ffffff')
+			ctx.fillRect(0, 0, width, height)
+
+			ctx.setFillStyle('#3385ff')
+			ctx.fillRect(0, 0, width, 140)
+			ctx.setFontSize(28)
+			ctx.setFillStyle('#ffffff')
+			ctx.setTextAlign('center')
+			ctx.fillText('退款凭证', width / 2, 60)
+			ctx.setFontSize(22)
+			ctx.fillText(this.customName || '客户', width / 2, 100)
+
+			ctx.setFontSize(46)
+			ctx.setFillStyle('#ff2842')
+			ctx.setTextAlign('center')
+			ctx.fillText('¥' + this.formatMoney(this.actPrice), width / 2, 205)
+			ctx.setFontSize(22)
+			ctx.setFillStyle('#999999')
+			ctx.fillText('已返充到余额', width / 2, 235)
+
+			ctx.setStrokeStyle('#eeeeee')
+			ctx.beginPath()
+			ctx.moveTo(padX, 258)
+			ctx.lineTo(width - padX, 258)
+			ctx.stroke()
+
+			// 最新余额(有值才画金额,无值画 --)
+			const balanceText = this.hasBalance ? ('¥' + this.formatMoney(this.customBalance)) : '--'
+			ctx.setFontSize(24)
+			ctx.setFillStyle('#333333')
+			ctx.setTextAlign('left')
+			ctx.fillText('最新余额', padX, 298)
+			ctx.setTextAlign('right')
+			ctx.setFillStyle('#3385ff')
+			ctx.fillText(balanceText, width - padX, 298)
+
+			// 冲销单号同一行:左侧标签,右侧按宽度缩小字号,保证不换行、不重叠
+			const snLabel = '冲销单号'
+			const snText = this.forwardSn || '--'
+			const snLabelSize = 24
+			ctx.setFontSize(snLabelSize)
+			ctx.setFillStyle('#333333')
+			ctx.setTextAlign('left')
+			ctx.fillText(snLabel, padX, 333)
+			const snLabelW = (ctx.measureText ? ctx.measureText(snLabel).width : snLabelSize * 4) || snLabelSize * 4
+			const snMaxW = width - padX * 2 - snLabelW - 16
+			const snSize = this.fitSnFontSize(ctx, snText, snMaxW)
+			ctx.setTextAlign('right')
+			ctx.setFontSize(snSize)
+			ctx.setFillStyle('#666666')
+			ctx.fillText(snText, width - padX, 333)
+
+			ctx.setFontSize(24)
+			ctx.setFillStyle('#333333')
+			ctx.setTextAlign('left')
+			ctx.fillText('日期', padX, 368)
+			ctx.setTextAlign('right')
+			ctx.setFontSize(20)
+			ctx.setFillStyle('#666666')
+			ctx.fillText(dayjs().format('YYYY-MM-DD HH:mm'), width - padX, 368)
+
+			const qrSize = 150
+			const qrX = (width - qrSize) / 2
+			const qrY = 400
+			ctx.drawImage(qrPath, qrX, qrY, qrSize, qrSize)
+
+			ctx.setFontSize(20)
+			ctx.setFillStyle('#999999')
+			ctx.setTextAlign('center')
+			ctx.fillText('长按识别,查看余额明细', width / 2, qrY + qrSize + 36)
+
+			ctx.restore()
+
+			ctx.draw(false, () => {
+				setTimeout(() => {
+					uni.canvasToTempFilePath(
+						{
+							canvasId: 'forwardPosterCanvas',
+							fileType: 'jpg',
+							quality: 1,
+							destWidth: width * 2,
+							destHeight: height * 2,
+							success: res => {
+								that.drawing = false
+								uni.hideLoading()
+								that.posterUrl = res.tempFilePath
+							},
+							fail: () => {
+								that.drawing = false
+								uni.hideLoading()
+								uni.showToast({ title: '生成图片失败', icon: 'none' })
+							}
+						},
+						that
+					)
+				}, 300)
+			})
+		},
+		savePosterImg() {
+			if (!this.posterUrl) {
+				return
+			}
+			uni.showLoading({ title: '正在保存...', mask: true })
+			uni.saveImageToPhotosAlbum({
+				filePath: this.posterUrl,
+				success() {
+					uni.hideLoading()
+					uni.showToast({ title: '保存成功', icon: 'success' })
+				},
+				fail() {
+					uni.hideLoading()
+					uni.showToast({ title: '保存失败,请检查相册权限', icon: 'none' })
 				}
 			})
 		},
@@ -90,6 +406,7 @@ export default {
 	flex-direction: column;
 	align-items: center;
 	margin-bottom: 30upx;
+	width: 100%;
 
 	&__amount {
 		font-size: 32upx;
@@ -102,6 +419,14 @@ export default {
 		margin-top: 12upx;
 		font-size: 26upx;
 		color: #666;
+		word-break: break-all;
+		text-align: center;
+	}
+
+	&__balance {
+		margin-top: 12upx;
+		font-size: 26upx;
+		color: #3385ff;
 	}
 
 	&__tip {
@@ -115,23 +440,51 @@ export default {
 	display: flex;
 	flex-direction: column;
 	align-items: center;
-	margin-bottom: 30upx;
+	width: 100%;
+	margin-bottom: 10upx;
+}
+
+.poster-loading {
+	padding: 40upx 0;
+	font-size: 26upx;
+	color: #999;
 }
 
 .poster-img {
-	width: 420upx;
+	width: 100%;
 	background: #fff;
-	border-radius: 12upx;
+	border-radius: 16upx;
+	box-shadow: 0 8upx 24upx rgba(0, 0, 0, 0.08);
 }
 
 .poster-tip {
 	margin-top: 16upx;
-	font-size: 24upx;
+	margin-bottom: 10upx;
+	font-size: 26upx;
 	color: #999;
 	text-align: center;
 }
 
-.admin-button-com {
+/* 与海报同宽拉满,保证「保存/查看原单/返回首页」一样长 */
+.btn-col {
+	width: 100%;
+	display: flex;
+	flex-direction: column;
+	align-items: stretch;
+	box-sizing: border-box;
+}
+
+.btn-item {
+	width: 100% !important;
+	display: block !important;
+	box-sizing: border-box;
 	margin-top: 20upx;
 }
+
+.poster-canvas {
+	position: fixed;
+	left: -9999px;
+	top: -9999px;
+	z-index: -1;
+}
 </style>

+ 31 - 15
ghsApp/src/pagesOrder/forwardConfirm.vue

@@ -171,12 +171,13 @@ export default {
 				return
 			}
 			const unitPrice = parseFloat(p.price || p.bigPrice || 0)
+			// 自由冲销默认大单位:数量只记 xhNum + xhUnitType
 			this.items.push({
 				productId,
 				name: p.name || '',
+				xhNum: 1,
 				num: 1,
-				bigNum: 1,
-				smallNum: 0,
+				xhUnitType: 0,
 				unitPrice,
 				price: unitPrice,
 				amount: unitPrice
@@ -187,12 +188,13 @@ export default {
 			this.items.splice(idx, 1)
 		},
 		recalcAmount(it) {
+			// 输入框绑的是 num,同步到规范字段 xhNum
 			const num = Number(it.num) || 0
 			const price = Number(it.unitPrice) || 0
+			it.xhNum = num
+			it.num = num
 			it.amount = parseFloat((num * price).toFixed(2))
 			it.price = price
-			it.bigNum = num
-			it.smallNum = 0
 		},
 		submit() {
 			if (!this.customId) {
@@ -214,16 +216,19 @@ export default {
 			if (this.submitting) {
 				return
 			}
-			const payloadItems = this.items.map(it => ({
-				productId: it.productId,
-				name: it.name,
-				num: Number(it.num) || 0,
-				bigNum: Number(it.bigNum) || Number(it.num) || 0,
-				smallNum: Number(it.smallNum) || 0,
-				unitPrice: Number(it.unitPrice) || 0,
-				price: Number(it.price || it.unitPrice) || 0,
-				amount: Number(it.amount) || 0
-			}))
+			const payloadItems = this.items.map(it => {
+				const xhNum = Number(it.xhNum != null ? it.xhNum : it.num) || 0
+				return {
+					productId: it.productId,
+					name: it.name,
+					xhNum,
+					num: xhNum,
+					xhUnitType: Number(it.xhUnitType) || 0,
+					unitPrice: Number(it.unitPrice) || 0,
+					price: Number(it.price || it.unitPrice) || 0,
+					amount: Number(it.amount) || 0
+				}
+			})
 			this.$util.confirmModal({ content: '确认提交冲销凭证?' }, () => {
 				this.submitting = true
 				uni.showLoading({ title: '提交中', mask: true })
@@ -239,6 +244,16 @@ export default {
 					this.submitting = false
 					if (res.code == 1) {
 						const data = res.data || {}
+						// 余额走本地缓存,避免 URL 丢参导致海报「最新余额」空白
+						uni.setStorageSync('forwardResultPayload', {
+							fundType: data.fundType || this.fundType,
+							amount: data.amount || this.totalAmount,
+							customId: data.customId || this.customId,
+							customBalance: data.customBalance != null ? data.customBalance : '',
+							customName: data.customName || this.customName || '',
+							forwardSn: data.forwardSn || '',
+							forwardId: data.forwardId || 0
+						})
 						this.$util.pageTo({
 							url: '/admin/billing/forwardResult',
 							type: 2,
@@ -246,7 +261,8 @@ export default {
 								fundType: data.fundType || this.fundType,
 								amount: data.amount || this.totalAmount,
 								customId: data.customId || this.customId,
-								customName: this.customName,
+								customBalance: data.customBalance != null ? data.customBalance : '',
+								customName: encodeURIComponent(data.customName || this.customName || ''),
 								forwardSn: data.forwardSn || '',
 								forwardId: data.forwardId || 0
 							}

+ 19 - 5
ghsApp/src/pagesOrder/refund.vue

@@ -389,7 +389,10 @@ export default {
 				})
 			})
 		},
-		/** 把售后页勾选的花材转成冲销明细(xhUnitType:0大单位 1小单位) */
+		/**
+		 * 把售后页勾选的花材转成冲销明细
+		 * 数量只传当前单位:xhNum + xhUnitType(0大单位/1小单位);不用 num/bigNum/smallNum 作依据
+		 */
 		buildForwardItems(){
 			const items = []
 			this.product.forEach(ele => {
@@ -397,16 +400,15 @@ export default {
 				if(count <= 0){
 					return
 				}
-				const isSmall = Number(ele.xhUnitType) === 1
 				const unitPrice = Number(ele.xhUnitPrice) || 0
 				const amount = parseFloat((count * unitPrice).toFixed(2))
 				items.push({
 					productId: ele.productId,
 					orderItemId: ele.id || ele.orderItemId || 0,
 					name: ele.name || '',
+					xhNum: count,
 					num: count,
-					bigNum: isSmall ? 0 : count,
-					smallNum: isSmall ? count : 0,
+					xhUnitType: Number(ele.xhUnitType) || 0,
 					unitPrice,
 					price: unitPrice,
 					amount
@@ -434,6 +436,17 @@ export default {
 				uni.hideLoading()
 				if(res.code == 1){
 					const data = res.data || {}
+					// 余额等关键字段走本地缓存,避免小程序 URL 过长丢参导致海报「最新余额」为 --
+					uni.setStorageSync('forwardResultPayload', {
+						fundType: data.fundType || opt.fundType,
+						amount: data.amount || that.refundMoney,
+						customId: data.customId || that.orderInfo.customId,
+						customBalance: data.customBalance != null ? data.customBalance : '',
+						customName: data.customName || that.orderInfo.customName || '',
+						forwardSn: data.forwardSn || '',
+						forwardId: data.forwardId || 0,
+						orderId: that.option.id
+					})
 					that.$util.pageTo({
 						url: '/admin/billing/forwardResult',
 						type: 2,
@@ -441,7 +454,8 @@ export default {
 							fundType: data.fundType || opt.fundType,
 							amount: data.amount || that.refundMoney,
 							customId: data.customId || that.orderInfo.customId,
-							customName: that.orderInfo.customName || '',
+							customBalance: data.customBalance != null ? data.customBalance : '',
+							customName: encodeURIComponent(data.customName || that.orderInfo.customName || ''),
 							forwardSn: data.forwardSn || '',
 							forwardId: data.forwardId || 0,
 							orderId: that.option.id

+ 14 - 1
ghsApp/src/pagesOrder/refundDetail.vue

@@ -371,13 +371,26 @@ export default {
 				uni.hideLoading()
 				if (res.code == 1) {
 					const data = res.data || {}
+					// 余额走本地缓存,避免 URL 丢参导致海报「最新余额」空白
+					uni.setStorageSync('forwardResultPayload', {
+						fundType: data.fundType || opt.fundType,
+						amount: data.amount || that.refundPrice,
+						customId: data.customId || that.info.customId || 0,
+						customBalance: data.customBalance != null ? data.customBalance : '',
+						customName: data.customName || that.info.customName || '',
+						forwardSn: data.forwardSn || '',
+						forwardId: data.forwardId || 0,
+						orderId: that.forwardOrderId || that.info.relateOrderId || 0
+					})
 					that.$util.pageTo({
 						url: '/admin/billing/forwardResult',
 						type: 2,
 						query: {
 							fundType: data.fundType || opt.fundType,
 							amount: data.amount || that.refundPrice,
-							customId: data.customId || 0,
+							customId: data.customId || that.info.customId || 0,
+							customBalance: data.customBalance != null ? data.customBalance : '',
+							customName: encodeURIComponent(data.customName || that.info.customName || ''),
 							forwardSn: data.forwardSn || '',
 							forwardId: data.forwardId || 0,
 							orderId: that.forwardOrderId || that.info.relateOrderId || 0