// 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(); } });