You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1294 lines
31 KiB
1294 lines
31 KiB
<!--学员订单管理页面-->
|
|
<template>
|
|
<view class="main_box">
|
|
<!-- 自定义导航栏 -->
|
|
<view class="navbar_section">
|
|
<view class="navbar_back" @click="goBack">
|
|
<text class="back_icon">‹</text>
|
|
</view>
|
|
<view class="navbar_title">订单管理</view>
|
|
<view class="navbar_action"></view>
|
|
</view>
|
|
|
|
<!-- 学员信息 -->
|
|
<view class="student_info_section" v-if="studentInfo">
|
|
<view class="student_name">{{ studentInfo.name }}</view>
|
|
<view class="order_stats">
|
|
<text class="stat_item">总订单:{{ orderStats.total_orders || 0 }}个</text>
|
|
<text class="stat_item">待付款:{{ orderStats.pending_payment || 0 }}个</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 订单状态筛选 -->
|
|
<view class="filter_section">
|
|
<view class="filter_tabs">
|
|
<view
|
|
v-for="tab in statusTabs"
|
|
:key="tab.value"
|
|
:class="['filter_tab', activeStatus === tab.value ? 'active' : '']"
|
|
@click="changeStatus(tab.value)"
|
|
>
|
|
{{ tab.text }}
|
|
<view class="tab_badge" v-if="tab.count > 0">{{ tab.count }}</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 订单列表 -->
|
|
<view class="orders_section">
|
|
<view v-if="loading" class="loading_section">
|
|
<view class="loading_text">加载中...</view>
|
|
</view>
|
|
|
|
<view v-else-if="filteredOrders.length === 0" class="empty_section">
|
|
<view class="empty_icon">📋</view>
|
|
<view class="empty_text">暂无订单</view>
|
|
<view class="empty_hint">完成购买后订单会在这里显示</view>
|
|
</view>
|
|
|
|
<view v-else class="orders_list">
|
|
<view
|
|
v-for="order in filteredOrders"
|
|
:key="order.id"
|
|
class="order_item"
|
|
@click="viewOrderDetail(order)"
|
|
>
|
|
<view class="order_header">
|
|
<view class="order_number">订单号:{{ order.order_no }}</view>
|
|
<view class="order_status" :class="order.status">
|
|
{{ getStatusText(order.status) }}
|
|
</view>
|
|
</view>
|
|
|
|
<view class="order_content">
|
|
<view class="order_info">
|
|
<view class="product_name">{{ order.product_name }}</view>
|
|
<view class="product_specs">{{ order.product_specs }}</view>
|
|
<view class="order_meta">
|
|
<text class="meta_item">数量:{{ order.quantity }}</text>
|
|
<text class="meta_item">{{ formatDate(order.create_time) }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="order_amount">
|
|
<view class="amount_label">订单金额</view>
|
|
<view class="amount_value">¥{{ order.total_amount }}</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="order_actions">
|
|
<fui-button
|
|
v-if="order.status === 'pending_payment'"
|
|
background="#29d3b4"
|
|
size="small"
|
|
@click="(e) => payOrder(order, e)"
|
|
>
|
|
立即付款
|
|
</fui-button>
|
|
|
|
<fui-button
|
|
v-if="order.status === 'pending_payment'"
|
|
background="transparent"
|
|
color="#999"
|
|
size="small"
|
|
@click="(e) => cancelOrder(order, e)"
|
|
>
|
|
取消订单
|
|
</fui-button>
|
|
|
|
<fui-button
|
|
background="transparent"
|
|
color="#666"
|
|
size="small"
|
|
@click="(e) => viewOrderDetail(order, e)"
|
|
>
|
|
查看详情
|
|
</fui-button>
|
|
|
|
<fui-button
|
|
v-if="order.status === 'paid' || order.status === 'completed'"
|
|
background="#29d3b4"
|
|
color="#fff"
|
|
size="small"
|
|
@click="(e) => viewContract(order, e)"
|
|
>
|
|
查看合同
|
|
</fui-button>
|
|
|
|
<fui-button
|
|
v-if="order.status === 'refunding' || order.status === 'refunded'"
|
|
background="transparent"
|
|
color="#f39c12"
|
|
size="small"
|
|
@click="(e) => viewRefundDetail(order, e)"
|
|
>
|
|
查看退款
|
|
</fui-button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 加载更多 -->
|
|
<view class="load_more_section" v-if="!loading && hasMore">
|
|
<fui-button
|
|
background="transparent"
|
|
color="#666"
|
|
@click="loadMoreOrders"
|
|
:loading="loadingMore"
|
|
>
|
|
{{ loadingMore ? '加载中...' : '加载更多' }}
|
|
</fui-button>
|
|
</view>
|
|
|
|
<!-- 支付方式选择弹窗 -->
|
|
<view class="payment_popup" v-if="showPaymentPopup" @click="closePaymentPopup">
|
|
<view class="popup_content" @click.stop>
|
|
<view class="popup_header">
|
|
<view class="popup_title">选择支付方式</view>
|
|
<view class="popup_close" @click="closePaymentPopup">×</view>
|
|
</view>
|
|
|
|
<view class="payment_order_info" v-if="selectedOrder">
|
|
<view class="order_summary">
|
|
<view class="summary_row">
|
|
<text class="summary_label">订单号:</text>
|
|
<text class="summary_value">{{ selectedOrder.order_no }}</text>
|
|
</view>
|
|
<view class="summary_row">
|
|
<text class="summary_label">商品:</text>
|
|
<text class="summary_value">{{ selectedOrder.product_name }}</text>
|
|
</view>
|
|
<view class="summary_row">
|
|
<text class="summary_label">金额:</text>
|
|
<text class="summary_value amount">¥{{ selectedOrder.total_amount }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="payment_methods">
|
|
<view
|
|
v-for="method in paymentMethods"
|
|
:key="method.value"
|
|
:class="['payment_method', selectedPaymentMethod === method.value ? 'selected' : '']"
|
|
@click="selectPaymentMethod(method.value)"
|
|
>
|
|
<view class="method_icon">
|
|
<image :src="method.icon" class="icon_image"></image>
|
|
</view>
|
|
<view class="method_info">
|
|
<view class="method_name">{{ method.name }}</view>
|
|
<view class="method_desc">{{ method.desc }}</view>
|
|
</view>
|
|
<view class="method_radio">
|
|
<view v-if="selectedPaymentMethod === method.value" class="radio_checked">✓</view>
|
|
<view v-else class="radio_unchecked"></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="popup_actions">
|
|
<fui-button
|
|
background="#f8f9fa"
|
|
color="#666"
|
|
@click="closePaymentPopup"
|
|
>
|
|
取消
|
|
</fui-button>
|
|
<fui-button
|
|
background="#29d3b4"
|
|
:loading="paying"
|
|
@click="confirmPayment"
|
|
>
|
|
{{ paying ? '支付中...' : '确认支付' }}
|
|
</fui-button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import apiRoute from '@/api/apiRoute.js'
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
studentId: 0,
|
|
studentInfo: {},
|
|
ordersList: [],
|
|
filteredOrders: [],
|
|
orderStats: {},
|
|
loading: false,
|
|
loadingMore: false,
|
|
hasMore: true,
|
|
currentPage: 1,
|
|
activeStatus: 'all',
|
|
showPaymentPopup: false,
|
|
selectedOrder: null,
|
|
selectedPaymentMethod: 'wxpay',
|
|
paying: false,
|
|
statusTabs: [
|
|
{ value: 'all', text: '全部', count: 0 },
|
|
{ value: 'pending_payment', text: '待付款', count: 0 },
|
|
{ value: 'paid', text: '已付款', count: 0 },
|
|
{ value: 'completed', text: '已完成', count: 0 },
|
|
{ value: 'cancelled', text: '已取消', count: 0 },
|
|
{ value: 'refunded', text: '已退款', count: 0 }
|
|
],
|
|
paymentMethods: [
|
|
{
|
|
value: 'wxpay',
|
|
name: '微信支付',
|
|
desc: '推荐使用',
|
|
icon: '/static/payment/wxpay.png'
|
|
},
|
|
{
|
|
value: 'alipay',
|
|
name: '支付宝',
|
|
desc: '快捷安全',
|
|
icon: '/static/payment/alipay.png'
|
|
}
|
|
],
|
|
// 状态文本映射
|
|
STATUS_TEXT_MAP: {
|
|
'pending_payment': '待付款',
|
|
'paid': '已付款',
|
|
'signed': '已签署',
|
|
'completed': '已完成',
|
|
'cancelled': '已取消',
|
|
'refunding': '退款中',
|
|
'refunded': '已退款'
|
|
}
|
|
}
|
|
},
|
|
|
|
onLoad(options) {
|
|
console.log('订单列表页面加载,参数:', options)
|
|
|
|
// 优先从参数获取学员ID,如果没有则从用户信息获取
|
|
this.studentId = parseInt(options.student_id) || 0
|
|
|
|
if (!this.studentId) {
|
|
// 从用户信息中获取学员ID
|
|
const userInfo = uni.getStorageSync('userInfo')
|
|
if (userInfo && userInfo.id) {
|
|
this.studentId = userInfo.id
|
|
}
|
|
}
|
|
|
|
console.log('订单列表页面学员ID确认:', this.studentId)
|
|
|
|
if (this.studentId) {
|
|
this.initPage()
|
|
} else {
|
|
uni.showToast({
|
|
title: '请先登录',
|
|
icon: 'none'
|
|
})
|
|
setTimeout(() => {
|
|
uni.redirectTo({
|
|
url: '/pages-student/login/login'
|
|
})
|
|
}, 1500)
|
|
}
|
|
},
|
|
|
|
onShow() {
|
|
console.log('订单列表页面显示')
|
|
},
|
|
|
|
onReady() {
|
|
console.log('订单列表页面准备完成')
|
|
},
|
|
|
|
methods: {
|
|
goBack() {
|
|
uni.navigateBack()
|
|
},
|
|
|
|
async initPage() {
|
|
await this.loadStudentInfo()
|
|
await this.loadOrders()
|
|
this.updateOrderDisplay()
|
|
},
|
|
|
|
async loadStudentInfo() {
|
|
try {
|
|
// 获取当前登录学员信息
|
|
const userInfo = uni.getStorageSync('userInfo')
|
|
|
|
if (userInfo && userInfo.id) {
|
|
// 如果URL没有传递student_id,才使用本地存储的用户ID
|
|
if (!this.studentId) {
|
|
this.studentId = userInfo.id
|
|
}
|
|
|
|
this.studentInfo = {
|
|
id: this.studentId, // 使用确定的学员ID
|
|
name: userInfo.name || userInfo.nickname || '学员'
|
|
}
|
|
|
|
console.log('学员信息设置完成:', {
|
|
studentId: this.studentId,
|
|
userName: this.studentInfo.name
|
|
})
|
|
} else {
|
|
// 如果没有用户信息,跳转到登录页
|
|
uni.showToast({
|
|
title: '请先登录',
|
|
icon: 'none'
|
|
})
|
|
setTimeout(() => {
|
|
uni.redirectTo({
|
|
url: '/pages-student/login/login'
|
|
})
|
|
}, 1500)
|
|
}
|
|
} catch (error) {
|
|
console.error('获取学员信息失败:', error)
|
|
}
|
|
},
|
|
|
|
async loadOrders() {
|
|
this.loading = true
|
|
try {
|
|
|
|
// 调用学员端订单列表接口
|
|
console.log('调用学员端订单接口,参数:', {
|
|
student_id: this.studentId,
|
|
page: this.currentPage,
|
|
limit: 10
|
|
});
|
|
|
|
const response = await apiRoute.xy_getStudentOrders({
|
|
student_id: this.studentId,
|
|
page: this.currentPage,
|
|
limit: 10
|
|
})
|
|
|
|
if (response.code === 1) {
|
|
const newList = this.processOrderData(response.data?.data || [])
|
|
if (this.currentPage === 1) {
|
|
this.ordersList = newList
|
|
} else {
|
|
this.ordersList = [...this.ordersList, ...newList]
|
|
}
|
|
|
|
// 处理分页信息
|
|
this.hasMore = response.data?.current_page < response.data?.last_page
|
|
|
|
// 更新订单显示
|
|
this.updateOrderDisplay()
|
|
} else {
|
|
uni.showToast({
|
|
title: response.msg || '获取订单列表失败',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
} catch (error) {
|
|
console.error('获取订单列表失败:', error)
|
|
uni.showToast({
|
|
title: '获取订单列表失败',
|
|
icon: 'none'
|
|
})
|
|
} finally {
|
|
this.loading = false
|
|
this.loadingMore = false
|
|
}
|
|
},
|
|
|
|
// 处理订单数据,将后端数据转换为前端需要的格式
|
|
processOrderData(rawData) {
|
|
return rawData.map(item => {
|
|
// 处理订单金额
|
|
const orderAmount = item.order_amount || item.total_amount || item.amount || '0.00'
|
|
|
|
// 处理订单号
|
|
const orderNo = item.order_no || item.order_number || item.payment_id || `订单${item.id}`
|
|
|
|
// 处理课程名称
|
|
const productName = item.course_id_name || item.course_name || item.product_name || '课程订单'
|
|
|
|
// 处理状态
|
|
const orderStatus = this.mapOrderStatus(item.order_status || item.status)
|
|
|
|
return {
|
|
id: item.id,
|
|
order_no: orderNo,
|
|
product_name: productName,
|
|
product_specs: item.course_specs || item.product_specs || '',
|
|
quantity: item.quantity || 1,
|
|
total_amount: orderAmount,
|
|
status: orderStatus,
|
|
create_time: item.created_at || item.create_time,
|
|
payment_method: this.mapPaymentMethod(item.payment_type || item.payment_method),
|
|
payment_time: item.payment_time || item.paid_at,
|
|
refund_time: item.refund_time,
|
|
refund_amount: item.refund_amount,
|
|
// 课程相关字段
|
|
course_count: item.total_hours || item.course_count || 0,
|
|
used_count: item.use_total_hours || item.used_count || 0,
|
|
remaining_count: item.remaining_count || 0,
|
|
gift_hours: item.gift_hours || 0,
|
|
use_gift_hours: item.use_gift_hours || 0,
|
|
// 其他字段
|
|
cancel_reason: item.after_sales_reason || item.cancel_reason || '',
|
|
remark: item.remark || '',
|
|
// 关联信息
|
|
staff_name: item.staff_id_name || '',
|
|
class_name: item.class_id_name || '',
|
|
campus_id: item.campus_id || 0
|
|
}
|
|
})
|
|
},
|
|
|
|
// 映射订单状态
|
|
mapOrderStatus(status) {
|
|
const statusMap = {
|
|
// 数字状态映射
|
|
'0': 'pending_payment', // 待付款
|
|
'1': 'completed', // 已完成
|
|
'2': 'cancelled', // 已取消
|
|
'3': 'refunded', // 已退款
|
|
// 字符串状态映射
|
|
'pending': 'pending_payment', // 待付款
|
|
'paid': 'paid', // 已付款
|
|
'signed': 'completed', // 已签署/已完成
|
|
'completed': 'completed', // 已完成
|
|
'transfer': 'cancelled', // 转让/已取消
|
|
'cancelled': 'cancelled', // 已取消
|
|
'refunded': 'refunded', // 已退款
|
|
'refunding': 'refunding' // 退款中
|
|
}
|
|
return statusMap[status] || 'pending_payment'
|
|
},
|
|
|
|
// 映射支付方式
|
|
mapPaymentMethod(method) {
|
|
const methodMap = {
|
|
'wxpay': '微信支付',
|
|
'alipay': '支付宝',
|
|
'cash': '现金支付',
|
|
'bank': '银行转账',
|
|
'': ''
|
|
}
|
|
return methodMap[method] || method || ''
|
|
},
|
|
|
|
// 支付方式代码转文本
|
|
mapPaymentMethodText(method) {
|
|
const methodMap = {
|
|
'wxpay': '微信支付',
|
|
'alipay': '支付宝'
|
|
}
|
|
return methodMap[method] || method || ''
|
|
},
|
|
|
|
async loadMoreOrders() {
|
|
if (this.loadingMore || !this.hasMore) return
|
|
|
|
this.loadingMore = true
|
|
this.currentPage++
|
|
await this.loadOrders()
|
|
},
|
|
|
|
changeStatus(status) {
|
|
this.activeStatus = status
|
|
this.updateOrderDisplay()
|
|
},
|
|
|
|
updateOrderDisplay() {
|
|
// 同时更新过滤列表和统计数据
|
|
if (this.activeStatus === 'all') {
|
|
this.filteredOrders = [...this.ordersList]
|
|
} else {
|
|
this.filteredOrders = this.ordersList.filter(order => order.status === this.activeStatus)
|
|
}
|
|
|
|
// 更新标签页统计
|
|
const counts = {}
|
|
this.ordersList.forEach(order => {
|
|
counts[order.status] = (counts[order.status] || 0) + 1
|
|
})
|
|
|
|
this.statusTabs.forEach(tab => {
|
|
tab.count = tab.value === 'all' ? this.ordersList.length : (counts[tab.value] || 0)
|
|
})
|
|
|
|
// 更新订单统计信息
|
|
this.orderStats = {
|
|
total_orders: this.ordersList.length,
|
|
pending_payment: counts['pending_payment'] || 0,
|
|
paid: counts['paid'] || 0,
|
|
completed: counts['completed'] || 0,
|
|
cancelled: counts['cancelled'] || 0,
|
|
refunded: counts['refunded'] || 0
|
|
}
|
|
},
|
|
|
|
|
|
getStatusText(status) {
|
|
return this.STATUS_TEXT_MAP[status] || status
|
|
},
|
|
|
|
formatDate(dateString) {
|
|
const date = new Date(dateString)
|
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
const day = String(date.getDate()).padStart(2, '0')
|
|
const hours = String(date.getHours()).padStart(2, '0')
|
|
const minutes = String(date.getMinutes()).padStart(2, '0')
|
|
return `${month}-${day} ${hours}:${minutes}`
|
|
},
|
|
|
|
// 通用工具方法
|
|
updateOrderStatus(orderId, statusUpdates) {
|
|
const orderIndex = this.ordersList.findIndex(o => o.id === orderId)
|
|
if (orderIndex !== -1) {
|
|
Object.assign(this.ordersList[orderIndex], statusUpdates)
|
|
}
|
|
this.updateOrderDisplay()
|
|
},
|
|
|
|
showOperationSuccess(message, callback) {
|
|
uni.showToast({
|
|
title: message,
|
|
icon: 'success'
|
|
})
|
|
if (callback) callback()
|
|
},
|
|
|
|
handleError(error, message) {
|
|
console.error(`${message}:`, error)
|
|
uni.showToast({
|
|
title: message,
|
|
icon: 'none'
|
|
})
|
|
},
|
|
|
|
simulateDelay(ms = 1000) {
|
|
return new Promise(resolve => setTimeout(resolve, ms))
|
|
},
|
|
|
|
getCurrentTimestamp() {
|
|
return new Date().toISOString().slice(0, 19).replace('T', ' ')
|
|
},
|
|
|
|
// 统一订单操作处理
|
|
async executeOrderOperation(operation, config) {
|
|
const { order, statusKey, statusValue, delay = 1000, successMessage, errorMessage, callback } = config
|
|
|
|
try {
|
|
if (operation.loadingKey) {
|
|
this[operation.loadingKey] = true
|
|
}
|
|
|
|
await this.simulateDelay(delay)
|
|
|
|
const updates = { [statusKey]: statusValue }
|
|
if (operation.additionalUpdates) {
|
|
Object.assign(updates, operation.additionalUpdates)
|
|
}
|
|
|
|
this.updateOrderStatus(order.id, updates)
|
|
this.showOperationSuccess(successMessage, callback)
|
|
} catch (error) {
|
|
this.handleError(error, errorMessage)
|
|
} finally {
|
|
if (operation.loadingKey) {
|
|
this[operation.loadingKey] = false
|
|
}
|
|
}
|
|
},
|
|
|
|
async viewOrderDetail(order, event) {
|
|
// 阻止事件冒泡
|
|
if (event && event.stopPropagation) {
|
|
event.stopPropagation()
|
|
}
|
|
|
|
try {
|
|
console.log('跳转订单详情,参数:', {
|
|
order_id: order.id,
|
|
student_id: this.studentId
|
|
})
|
|
|
|
// 先显示加载提示
|
|
uni.showLoading({
|
|
title: '正在加载...'
|
|
})
|
|
|
|
// 延迟跳转确保页面状态稳定
|
|
setTimeout(() => {
|
|
uni.hideLoading()
|
|
// 直接跳转到订单详情页面,传递学员ID和订单ID
|
|
uni.navigateTo({
|
|
url: `/pages-student/orders/detail?id=${order.id}&student_id=${this.studentId}`,
|
|
success: () => {
|
|
console.log('订单详情页面跳转成功')
|
|
},
|
|
fail: (error) => {
|
|
console.error('页面跳转失败:', error)
|
|
uni.showToast({
|
|
title: '页面跳转失败',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
})
|
|
}, 100)
|
|
|
|
} catch (error) {
|
|
uni.hideLoading()
|
|
console.error('跳转订单详情失败:', error)
|
|
uni.showToast({
|
|
title: '跳转失败',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
},
|
|
|
|
payOrder(order, event) {
|
|
// 阻止事件冒泡
|
|
if (event && event.stopPropagation) {
|
|
event.stopPropagation()
|
|
}
|
|
|
|
this.selectedOrder = order
|
|
this.showPaymentPopup = true
|
|
},
|
|
|
|
closePaymentPopup() {
|
|
this.showPaymentPopup = false
|
|
this.selectedOrder = null
|
|
this.selectedPaymentMethod = 'wxpay'
|
|
},
|
|
|
|
selectPaymentMethod(method) {
|
|
this.selectedPaymentMethod = method
|
|
},
|
|
|
|
async confirmPayment() {
|
|
if (!this.selectedOrder || this.paying) return
|
|
|
|
this.paying = true
|
|
|
|
try {
|
|
// 调用真实支付API
|
|
const paymentData = {
|
|
order_id: this.selectedOrder.id,
|
|
student_id: this.studentId,
|
|
payment_method: this.selectedPaymentMethod,
|
|
payment_amount: this.selectedOrder.total_amount
|
|
}
|
|
|
|
console.log('发起支付请求:', paymentData)
|
|
|
|
// 根据支付方式调用不同的支付接口
|
|
let paymentResponse
|
|
if (this.selectedPaymentMethod === 'wxpay') {
|
|
// 微信支付
|
|
paymentResponse = await this.processWechatPayment(paymentData)
|
|
} else if (this.selectedPaymentMethod === 'alipay') {
|
|
// 支付宝支付
|
|
paymentResponse = await this.processAlipayPayment(paymentData)
|
|
} else {
|
|
throw new Error('不支持的支付方式')
|
|
}
|
|
|
|
if (paymentResponse.code === 1) {
|
|
// 支付成功,更新订单状态
|
|
this.updateOrderStatus(this.selectedOrder.id, {
|
|
status: 'paid',
|
|
payment_method: this.mapPaymentMethodText(this.selectedPaymentMethod),
|
|
payment_time: this.getCurrentTimestamp()
|
|
})
|
|
|
|
uni.showToast({
|
|
title: '支付成功',
|
|
icon: 'success'
|
|
})
|
|
|
|
this.closePaymentPopup()
|
|
} else {
|
|
throw new Error(paymentResponse.msg || '支付失败')
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('支付失败:', error)
|
|
uni.showToast({
|
|
title: error.message || '支付失败',
|
|
icon: 'none'
|
|
})
|
|
} finally {
|
|
this.paying = false
|
|
}
|
|
},
|
|
|
|
// 微信支付处理
|
|
async processWechatPayment(paymentData) {
|
|
try {
|
|
// 调用后端接口获取微信支付参数
|
|
const response = await apiRoute.xs_orderTableUpdatePaymentStatus({
|
|
order_id: paymentData.order_id,
|
|
payment_type: 'wxpay_online',
|
|
payment_amount: paymentData.payment_amount
|
|
})
|
|
|
|
if (response.code === 1) {
|
|
// 如果后端返回支付参数,调用微信支付
|
|
if (response.data && response.data.pay_params) {
|
|
// 调用微信支付
|
|
const wxPayResult = await this.callWechatPay(response.data.pay_params)
|
|
return wxPayResult
|
|
} else {
|
|
// 直接标记为支付成功(现金支付等)
|
|
return { code: 1, msg: '支付成功' }
|
|
}
|
|
} else {
|
|
throw new Error(response.msg || '获取支付信息失败')
|
|
}
|
|
} catch (error) {
|
|
console.error('微信支付处理失败:', error)
|
|
throw error
|
|
}
|
|
},
|
|
|
|
// 支付宝支付处理
|
|
async processAlipayPayment(paymentData) {
|
|
try {
|
|
// 调用后端接口获取支付宝支付参数
|
|
const response = await apiRoute.xs_orderTableUpdatePaymentStatus({
|
|
order_id: paymentData.order_id,
|
|
payment_type: 'alipay',
|
|
payment_amount: paymentData.payment_amount
|
|
})
|
|
|
|
if (response.code === 1) {
|
|
// 如果后端返回支付参数,调用支付宝支付
|
|
if (response.data && response.data.pay_params) {
|
|
// 调用支付宝支付
|
|
const aliPayResult = await this.callAlipay(response.data.pay_params)
|
|
return aliPayResult
|
|
} else {
|
|
// 直接标记为支付成功
|
|
return { code: 1, msg: '支付成功' }
|
|
}
|
|
} else {
|
|
throw new Error(response.msg || '获取支付信息失败')
|
|
}
|
|
} catch (error) {
|
|
console.error('支付宝支付处理失败:', error)
|
|
throw error
|
|
}
|
|
},
|
|
|
|
// 调用微信支付
|
|
async callWechatPay(payParams) {
|
|
return new Promise((resolve, reject) => {
|
|
// #ifdef MP-WEIXIN
|
|
wx.requestPayment({
|
|
...payParams,
|
|
success: (res) => {
|
|
console.log('微信支付成功:', res)
|
|
resolve({ code: 1, msg: '支付成功' })
|
|
},
|
|
fail: (err) => {
|
|
console.error('微信支付失败:', err)
|
|
if (err.errMsg.includes('cancel')) {
|
|
reject(new Error('用户取消支付'))
|
|
} else {
|
|
reject(new Error('微信支付失败'))
|
|
}
|
|
}
|
|
})
|
|
// #endif
|
|
|
|
// #ifndef MP-WEIXIN
|
|
// 其他平台的处理
|
|
console.log('非微信小程序环境,模拟支付成功')
|
|
resolve({ code: 1, msg: '支付成功' })
|
|
// #endif
|
|
})
|
|
},
|
|
|
|
// 调用支付宝支付
|
|
async callAlipay(payParams) {
|
|
return new Promise((resolve, reject) => {
|
|
// #ifdef APP-PLUS
|
|
// App端支付宝支付
|
|
plus.payment.request('alipay', payParams, (result) => {
|
|
console.log('支付宝支付成功:', result)
|
|
resolve({ code: 1, msg: '支付成功' })
|
|
}, (error) => {
|
|
console.error('支付宝支付失败:', error)
|
|
reject(new Error('支付宝支付失败'))
|
|
})
|
|
// #endif
|
|
|
|
// #ifndef APP-PLUS
|
|
// 其他平台的处理
|
|
console.log('非App环境,模拟支付成功')
|
|
resolve({ code: 1, msg: '支付成功' })
|
|
// #endif
|
|
})
|
|
},
|
|
|
|
async cancelOrder(order, event) {
|
|
// 阻止事件冒泡
|
|
if (event && event.stopPropagation) {
|
|
event.stopPropagation()
|
|
}
|
|
|
|
uni.showModal({
|
|
title: '确认取消',
|
|
content: '确定要取消此订单吗?',
|
|
success: async (res) => {
|
|
if (res.confirm) {
|
|
await this.executeOrderOperation(
|
|
{},
|
|
{
|
|
order,
|
|
statusKey: 'status',
|
|
statusValue: 'cancelled',
|
|
delay: 500,
|
|
successMessage: '取消成功',
|
|
errorMessage: '取消失败'
|
|
}
|
|
)
|
|
}
|
|
}
|
|
})
|
|
},
|
|
|
|
// 查看合同
|
|
async viewContract(order, event) {
|
|
// 阻止事件冒泡
|
|
if (event && event.stopPropagation) {
|
|
event.stopPropagation()
|
|
}
|
|
|
|
try {
|
|
// 直接跳转到合同页面,因为合同和订单是一对一关系
|
|
// 根据你提供的URL格式进行跳转
|
|
uni.navigateTo({
|
|
url: `/pages-student/contracts/index?student_id=${this.studentId}&order_id=${order.id}`
|
|
})
|
|
} catch (error) {
|
|
console.error('跳转合同页面失败:', error)
|
|
uni.showToast({
|
|
title: '跳转合同页面失败',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
},
|
|
|
|
viewRefundDetail(order, event) {
|
|
// 阻止事件冒泡
|
|
if (event && event.stopPropagation) {
|
|
event.stopPropagation()
|
|
}
|
|
|
|
const refundInfo = `订单号:${order.order_no}\n退款金额:¥${order.refund_amount || order.total_amount}\n退款时间:${order.refund_time || '处理中'}`
|
|
uni.showModal({
|
|
title: '退款详情',
|
|
content: refundInfo,
|
|
showCancel: false
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.main_box {
|
|
background: #f8f9fa;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
// 自定义导航栏
|
|
.navbar_section {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
background: #29D3B4;
|
|
padding: 40rpx 32rpx 20rpx;
|
|
|
|
// 小程序端适配状态栏
|
|
// #ifdef MP-WEIXIN
|
|
padding-top: 80rpx;
|
|
// #endif
|
|
|
|
.navbar_back {
|
|
width: 60rpx;
|
|
|
|
.back_icon {
|
|
color: #fff;
|
|
font-size: 40rpx;
|
|
font-weight: 600;
|
|
}
|
|
}
|
|
|
|
.navbar_title {
|
|
color: #fff;
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.navbar_action {
|
|
width: 60rpx;
|
|
}
|
|
}
|
|
|
|
// 学员信息
|
|
.student_info_section {
|
|
background: #fff;
|
|
padding: 24rpx 32rpx;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
|
.student_name {
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
color: #333;
|
|
margin-bottom: 12rpx;
|
|
}
|
|
|
|
.order_stats {
|
|
display: flex;
|
|
gap: 24rpx;
|
|
|
|
.stat_item {
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 状态筛选
|
|
.filter_section {
|
|
background: #fff;
|
|
margin: 20rpx;
|
|
border-radius: 16rpx;
|
|
padding: 24rpx 32rpx;
|
|
|
|
.filter_tabs {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 16rpx;
|
|
|
|
.filter_tab {
|
|
position: relative;
|
|
padding: 12rpx 24rpx;
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
background: #f8f9fa;
|
|
border-radius: 20rpx;
|
|
|
|
&.active {
|
|
color: #fff;
|
|
background: #29D3B4;
|
|
}
|
|
|
|
.tab_badge {
|
|
position: absolute;
|
|
top: -8rpx;
|
|
right: -8rpx;
|
|
background: #ff4757;
|
|
color: #fff;
|
|
font-size: 18rpx;
|
|
padding: 2rpx 8rpx;
|
|
border-radius: 12rpx;
|
|
min-width: 16rpx;
|
|
text-align: center;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 订单列表
|
|
.orders_section {
|
|
margin: 0 20rpx;
|
|
|
|
.loading_section, .empty_section {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 80rpx 32rpx;
|
|
text-align: center;
|
|
|
|
.loading_text, .empty_text {
|
|
font-size: 28rpx;
|
|
color: #666;
|
|
margin-bottom: 12rpx;
|
|
}
|
|
|
|
.empty_icon {
|
|
font-size: 80rpx;
|
|
margin-bottom: 24rpx;
|
|
}
|
|
|
|
.empty_hint {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.orders_list {
|
|
.order_item {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 24rpx;
|
|
margin-bottom: 20rpx;
|
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
|
|
|
.order_header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 20rpx;
|
|
|
|
.order_number {
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
}
|
|
|
|
.order_status {
|
|
font-size: 24rpx;
|
|
padding: 6rpx 12rpx;
|
|
border-radius: 12rpx;
|
|
|
|
&.pending_payment {
|
|
color: #f39c12;
|
|
background: rgba(243, 156, 18, 0.1);
|
|
}
|
|
|
|
&.paid {
|
|
color: #3498db;
|
|
background: rgba(52, 152, 219, 0.1);
|
|
}
|
|
|
|
&.completed {
|
|
color: #27ae60;
|
|
background: rgba(39, 174, 96, 0.1);
|
|
}
|
|
|
|
&.cancelled {
|
|
color: #95a5a6;
|
|
background: rgba(149, 165, 166, 0.1);
|
|
}
|
|
|
|
&.refunded {
|
|
color: #e74c3c;
|
|
background: rgba(231, 76, 60, 0.1);
|
|
}
|
|
}
|
|
}
|
|
|
|
.order_content {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
margin-bottom: 20rpx;
|
|
|
|
.order_info {
|
|
flex: 1;
|
|
|
|
.product_name {
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
color: #333;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.product_specs {
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
margin-bottom: 12rpx;
|
|
}
|
|
|
|
.order_meta {
|
|
display: flex;
|
|
gap: 16rpx;
|
|
|
|
.meta_item {
|
|
font-size: 22rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
}
|
|
|
|
.order_amount {
|
|
text-align: right;
|
|
|
|
.amount_label {
|
|
font-size: 22rpx;
|
|
color: #666;
|
|
margin-bottom: 4rpx;
|
|
}
|
|
|
|
.amount_value {
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
color: #e74c3c;
|
|
}
|
|
}
|
|
}
|
|
|
|
.order_actions {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 16rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 加载更多
|
|
.load_more_section {
|
|
padding: 40rpx 20rpx 80rpx;
|
|
}
|
|
|
|
// 支付弹窗
|
|
.payment_popup {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
z-index: 999;
|
|
|
|
.popup_content {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
width: 85%;
|
|
max-height: 70vh;
|
|
overflow: hidden;
|
|
|
|
.popup_header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 32rpx;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
|
.popup_title {
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
color: #333;
|
|
}
|
|
|
|
.popup_close {
|
|
font-size: 48rpx;
|
|
color: #999;
|
|
font-weight: 300;
|
|
}
|
|
}
|
|
|
|
.payment_order_info {
|
|
padding: 24rpx 32rpx;
|
|
border-bottom: 1px solid #f8f9fa;
|
|
|
|
.order_summary {
|
|
.summary_row {
|
|
display: flex;
|
|
margin-bottom: 12rpx;
|
|
|
|
.summary_label {
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
min-width: 120rpx;
|
|
}
|
|
|
|
.summary_value {
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
|
|
&.amount {
|
|
color: #e74c3c;
|
|
font-weight: 600;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.payment_methods {
|
|
padding: 24rpx 32rpx;
|
|
|
|
.payment_method {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 20rpx 0;
|
|
border-bottom: 1px solid #f8f9fa;
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
&.selected {
|
|
background: rgba(41, 211, 180, 0.05);
|
|
}
|
|
|
|
.method_icon {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
margin-right: 20rpx;
|
|
|
|
.icon_image {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
.method_info {
|
|
flex: 1;
|
|
|
|
.method_name {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
margin-bottom: 4rpx;
|
|
}
|
|
|
|
.method_desc {
|
|
font-size: 22rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.method_radio {
|
|
.radio_checked {
|
|
width: 32rpx;
|
|
height: 32rpx;
|
|
background: #29d3b4;
|
|
border-radius: 50%;
|
|
color: #fff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 18rpx;
|
|
}
|
|
|
|
.radio_unchecked {
|
|
width: 32rpx;
|
|
height: 32rpx;
|
|
border: 2rpx solid #ddd;
|
|
border-radius: 50%;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.popup_actions {
|
|
padding: 24rpx 32rpx;
|
|
display: flex;
|
|
gap: 16rpx;
|
|
|
|
fui-button {
|
|
flex: 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|