392 lines
10 KiB
JavaScript
392 lines
10 KiB
JavaScript
// 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();
|
||
}
|
||
}); |