Files
2025-11-17 13:32:54 +08:00

392 lines
10 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// pages/refund/refund-apply/index.js
import Toast from 'tdesign-miniprogram/toast/index';
import { config } from '../../../config/index';
Page({
// 检查登录状态并导航到登录页
checkLoginAndNavigate() {
const token = wx.getStorageSync('token');
if (!token) {
wx.showModal({
title: '提示',
content: '请先登录后再进行操作',
showCancel: true,
cancelText: '取消',
confirmText: '去登录',
success: (res) => {
if (res.confirm) {
wx.navigateTo({
url: '/pages/login/index'
});
}
}
});
return false;
}
return true;
},
data: {
orderDetail: null,
refundAmount: '',
maxRefundAmount: '0.00',
selectedReason: '',
customReason: '',
description: '',
reasonOptions: [
{ value: 'quality', label: '商品质量问题' },
{ value: 'description', label: '商品与描述不符' },
{ value: 'logistics', label: '物流问题' },
{ value: 'service', label: '服务问题' },
{ value: 'personal', label: '个人原因' },
{ value: 'other', label: '其他原因' }
],
isReapply: false,
originalRefundId: null,
submitting: false,
loading: true,
error: null
},
computed: {
canSubmit() {
const { refundAmount, selectedReason, customReason } = this.data;
const hasValidAmount = refundAmount && parseFloat(refundAmount) > 0;
const hasValidReason = selectedReason && (selectedReason !== 'other' || customReason.trim());
return hasValidAmount && hasValidReason;
}
},
onLoad(options) {
console.log('[退款申请] 页面加载', options);
this.orderNo = options.orderNo;
this.setData({
isReapply: options.reapply === '1',
originalRefundId: options.refundId || null
});
if (!this.orderNo) {
this.setData({
error: '订单号不能为空',
loading: false
});
return;
}
this.loadOrderDetail();
},
onShow() {
// 重新计算canSubmit
this.updateCanSubmit();
},
// 加载订单详情
loadOrderDetail() {
this.setData({
loading: true,
error: null
});
if (!this.checkLoginAndNavigate()) {
this.setData({
loading: false
});
return;
}
const token = wx.getStorageSync('token');
console.log('[退款申请] 请求订单详情', { orderNo: this.orderNo });
wx.request({
url: `${config.apiBase}/orders/${this.orderNo}`,
method: 'GET',
header: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
success: (res) => {
console.log('[退款申请] 订单详情API响应', res);
if (res.statusCode === 200 && res.data.code === 200) {
const orderDetail = this.processOrderDetail(res.data.data);
this.setData({
orderDetail: orderDetail,
maxRefundAmount: orderDetail.totalAmount,
refundAmount: orderDetail.totalAmount, // 默认全额退款
loading: false
});
this.updateCanSubmit();
} else {
console.error('[退款申请] 订单详情API错误', res.data);
this.setData({
error: res.data.message || '获取订单详情失败',
loading: false
});
}
},
fail: (error) => {
console.error('[退款申请] 网络错误', error);
this.setData({
error: '网络错误',
loading: false
});
}
});
},
// 处理订单详情数据
processOrderDetail(data) {
// 订单状态映射
const statusMap = {
1: '待付款',
2: '待发货',
3: '待发货',
4: '已发货',
5: '待收货',
6: '已完成',
7: '已取消',
8: '退货中',
9: '已退款'
};
// 使用正确的字段名根据后端JSON标签
const rawAmount = data.totalAmount || 0;
// 格式化金额(后端返回的是以分为单位的整数,需要转换为元)
const totalAmount = (rawAmount / 100).toFixed(2);
return {
orderId: data.orderId, // 保存订单ID用于提交退款申请
orderNo: data.orderNo,
statusText: statusMap[data.orderStatus] || '未知状态',
totalAmount: totalAmount
};
},
// 更新提交按钮状态
updateCanSubmit() {
const { refundAmount, selectedReason, customReason } = this.data;
const hasValidAmount = refundAmount && parseFloat(refundAmount) > 0;
const hasValidReason = selectedReason && (selectedReason !== 'other' || customReason.trim());
const canSubmit = hasValidAmount && hasValidReason;
this.setData({ canSubmit });
},
// 金额输入
onAmountInput(e) {
let value = e.detail.value;
// 只允许数字和小数点
value = value.replace(/[^\d.]/g, '');
// 只允许一个小数点
const dotIndex = value.indexOf('.');
if (dotIndex !== -1) {
value = value.substring(0, dotIndex + 1) + value.substring(dotIndex + 1).replace(/\./g, '');
// 限制小数点后两位
if (value.length > dotIndex + 3) {
value = value.substring(0, dotIndex + 3);
}
}
// 检查是否超过最大退款金额
const maxAmount = parseFloat(this.data.maxRefundAmount);
const inputAmount = parseFloat(value);
if (inputAmount > maxAmount) {
value = this.data.maxRefundAmount;
Toast({
context: this,
selector: '#t-toast',
message: '退款金额不能超过订单金额',
theme: 'warning',
});
}
this.setData({ refundAmount: value });
this.updateCanSubmit();
},
// 快速填充全额
onQuickFillAmount() {
this.setData({ refundAmount: this.data.maxRefundAmount });
this.updateCanSubmit();
},
// 选择退款原因
onReasonSelect(e) {
const value = e.currentTarget.dataset.value;
this.setData({
selectedReason: value,
customReason: value === 'other' ? this.data.customReason : ''
});
this.updateCanSubmit();
},
// 自定义原因输入
onCustomReasonInput(e) {
this.setData({ customReason: e.detail.value });
this.updateCanSubmit();
},
// 退款说明输入
onDescriptionInput(e) {
this.setData({ description: e.detail.value });
},
// 订单点击
onOrderTap() {
const { orderDetail } = this.data;
if (orderDetail && orderDetail.orderNo) {
wx.navigateTo({
url: `/pages/order/order-detail/index?orderNo=${orderDetail.orderNo}`
});
}
},
// 提交申请
onSubmit() {
if (!this.data.canSubmit || this.data.submitting) {
return;
}
// 验证数据
const { refundAmount, selectedReason, customReason, description } = this.data;
if (!refundAmount || parseFloat(refundAmount) <= 0) {
Toast({
context: this,
selector: '#t-toast',
message: '请输入有效的退款金额',
theme: 'warning',
});
return;
}
if (!selectedReason) {
Toast({
context: this,
selector: '#t-toast',
message: '请选择退款原因',
theme: 'warning',
});
return;
}
if (selectedReason === 'other' && !customReason.trim()) {
Toast({
context: this,
selector: '#t-toast',
message: '请填写具体的退款原因',
theme: 'warning',
});
return;
}
// 确认提交
const confirmText = this.data.isReapply ? '确定要重新提交退款申请吗?' : '确定要提交退款申请吗?';
wx.showModal({
title: '确认提交',
content: confirmText,
success: (res) => {
if (res.confirm) {
this.performSubmit();
}
}
});
},
// 执行提交
performSubmit() {
this.setData({ submitting: true });
const token = wx.getStorageSync('token');
const { refundAmount, selectedReason, customReason, description, isReapply, originalRefundId } = this.data;
// 构建退款原因
let reason = '';
if (selectedReason === 'other') {
reason = customReason.trim();
} else {
const reasonOption = this.data.reasonOptions.find(option => option.value === selectedReason);
reason = reasonOption ? reasonOption.label : '';
}
// 构建请求数据UserID由后端从JWT token中获取不需要前端传递
const requestData = {
order_id: parseInt(this.data.orderDetail.orderId), // 转换为数字类型
refund_amount: parseFloat(refundAmount), // 后端期望的是元为单位的浮点数
refund_reason: reason, // 使用正确的字段名
refund_type: 1 // 1:仅退款 2:退货退款,默认为仅退款
};
console.log('[退款申请] 提交数据', requestData);
// 选择API端点
let url = `${config.apiBase}/refunds`;
let method = 'POST';
if (isReapply && originalRefundId) {
url = `${config.apiBase}/refunds/${originalRefundId}/reapply`;
method = 'PUT';
}
wx.request({
url: url,
method: method,
header: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
data: requestData,
success: (res) => {
console.log('[退款申请] 提交响应', res);
this.setData({ submitting: false });
if (res.statusCode === 200 && res.data.code === 200) {
Toast({
context: this,
selector: '#t-toast',
message: isReapply ? '重新申请成功' : '申请提交成功',
theme: 'success',
});
// 延迟跳转
setTimeout(() => {
wx.navigateBack({
delta: 1
});
}, 1500);
} else {
console.error('[退款申请] 提交失败', res.data);
Toast({
context: this,
selector: '#t-toast',
message: res.data.message || '提交失败',
theme: 'error',
});
}
},
fail: (error) => {
console.error('[退款申请] 网络错误', error);
this.setData({ submitting: false });
Toast({
context: this,
selector: '#t-toast',
message: '网络错误',
theme: 'error',
});
}
});
},
// 重试
onRetry() {
this.loadOrderDetail();
}
});