driverSchool/newPages/orderDetails/index.vue

688 lines
17 KiB
Vue
Raw Normal View History

2025-04-11 18:06:20 +08:00
<template>
<view class="order-detail-container">
<!-- 头部信息 -->
<view style="width: 100%;background: #f4f5f6;box-sizing: border-box;padding-top: 88px;">
<headers titles="订单详情">
<uni-icons type="left" color="#000000" size="22px"></uni-icons>
</headers>
<view class="status-card" :class="'status-' + orderData.paymentStatus">
<text class="status-text">{{ getStatusText(orderData.paymentStatus) }}</text>
</view>
</view>
<!-- 课程信息 -->
<view class="course-card">
<view class="course-header">
<!-- <text class="course-type" :class="'type-' + orderData.courseType">{{ orderData.courseType }}</text> -->
<text class="order-time">{{ formatTime(orderData.createTime) }}</text>
</view>
<view class="course-info">
<image :src="imageUrl + '/' + orderData.photo" class="course-image"></image>
<view class="course-detail">
<text class="course-title">{{ orderData.courseName }}</text>
2025-04-12 17:52:46 +08:00
<view class='course-twoType'>
<text class="course-type" >{{ getLicenseTypeDescription(orderData.courseType) }}</text>
<text class="course-type" >{{ orderData.courseType }}</text>
</view>
2025-04-11 18:06:20 +08:00
<text class="course-desc">{{ courseDetails.tittle }}</text>
</view>
</view>
</view>
<!-- 用户信息 -->
<view class="info-card">
<view class="info-item">
<text class="info-title">学员姓名</text>
<text class="info-value">{{ orderData.userName }}</text>
</view>
<view class="info-item">
<text class="info-title">学员电话</text>
<text class="info-value">{{ orderData.userPhone }}</text>
</view>
<view class="info-item">
<text class="info-title">证件号码</text>
<text class="info-value">{{ orderData.userNo }}</text>
</view>
<view class="info-item" v-if="orderData.coachUserName">
<text class="info-title">教练姓名</text>
<text class="info-value">{{ orderData.coachUserName }}</text>
</view>
<view class="info-item" v-if="schoolDetails.corpName">
<text class="info-title">驾校名称</text>
<text class="info-value">{{ schoolDetails.corpName }}</text>
</view>
</view>
<!-- 订单信息 -->
<view class="info-card">
<view class="info-item">
<text class="info-title">订单编号</text>
<text class="info-value">{{ orderData.orderNo }}</text>
</view>
<view class="info-item">
<text class="info-title">下单时间</text>
<text class="info-value">{{ formatTime(orderData.createTime) }}</text>
</view>
<view class="info-item">
<text class="info-title">支付方式</text>
<text class="info-value">{{ getPayTypeText(orderData.payType) }}</text>
</view>
<view class="info-item">
<text class="info-title">支付状态</text>
<text class="info-value">{{ getStatusText(orderData.paymentStatus) }}</text>
</view>
<view class="info-item">
<text class="info-title">是否面签</text>
<text class="info-value">{{ orderData.isSign ? '已面签' : '未面签' }}</text>
</view>
<view class="info-item">
<text class="info-title">是否终止</text>
<text class="info-value">{{ orderData.ifEnd ? '已终止' : '未终止' }}</text>
</view>
<view class="info-item" v-if="orderData.endReason">
<text class="info-title">终止原因</text>
<text class="info-value">{{ orderData.endReason }}</text>
</view>
</view>
<!-- 价格信息 -->
<view class="price-card">
<!-- <view class="price-row">
<text class="price-label">课程{{ orderData.payType === '2' ? '定金' : '全款' }}</text>
<text class="price-value">¥{{ orderData.reserveMoney.toFixed(2) }}</text>
</view> -->
<view class="price-row">
<text class="price-label">课程金额</text>
<text class="price-value">¥{{ courseDetails.price }}</text>
</view>
<view class="price-row" v-if="orderData.payType === '1' && orderData.paymentStatus === '0' ">
<text class="price-label">定金金额</text>
<text class="price-value">¥{{ courseDetails.reserveMoney }}</text>
</view>
<view class="price-row" v-if="orderData.payType === '1' && orderData.paymentStatus === '0' ">
<text class="price-label">尾款金额</text>
<text class="price-value">¥{{ orderData.restMoney.toFixed(2) }}</text>
</view>
<view class="price-row" v-if="orderData.payType === '1' && orderData.paymentStatus === '2' ">
<text class="price-label">待付尾款</text>
<text class="price-value">¥{{ orderData.restMoney.toFixed(2) }}</text>
</view>
<view class="price-row total" v-if="orderData.reserveMoney && orderData.paymentStatus === '2'">
<text class="price-label">实付款</text>
<text class="price-value">¥{{ orderData.reserveMoney.toFixed(2) }}</text>
</view>
</view>
<!-- 底部操作按钮 -->
<view class="footer" v-if="orderData.paymentStatus === '0'">
<view class="cancel-button" @click="cancelOrder">
<text class="pay-button-text">取消订单</text>
</view>
<view class="pay-button" @click="handlePay">
<text class="pay-button-text">立即支付</text>
</view>
</view>
<!-- <view class="footer" v-else-if="orderData.payType === '1'">
<view class="pay-button" @click="handlePay">
<text class="pay-button-text">支付尾款</text>
</view>
</view> -->
</view>
</template>
<script>
import headers from "@/components/header/headers.vue";
import request from '@/utils/request.js'
export default {
components: {
headers
},
data() {
return {
imageUrl: this.$imagesUrl,
courseDetails: [],
schoolDetails: [],
orderData: {
/* coachUserId: 4289,
coachUserName: null,
courseId: "1",
courseName: "测试课程",
courseType: "C1",
createTime: 1744179195000,
creator: "5171",
deleted: false,
endReason: "测试",
endTime: null,
gradTime: null,
id: "6aea0dbe2c22ec7eaf2859ad6d0bc7ea",
ifAssignmentCoach: 0,
ifEnd: false,
isCreated: false,
isSign: 0,
oldOrderId: null,
orderNo: "69975643780792",
passTime: null,
payType: "1",
paymentStatus: "0",
photo: "lanan/5181406098997f57fbd12b968e65aec7d899c4e84f9011f754f5d6074eaa2888.png",
reserveMoney: null,
restMoney: 0.01,
tenantId: 180,
type: "C1",
updateTime: 1744179195000,
updater: "5171",
userId: 5171,
userName: "刘松源",
userNo: "612701199307280651",
userPhone: "15305306404",
userSex: "0" */
}
}
},
onLoad(options) {
const order = JSON.parse(decodeURIComponent(options.data));
this.orderData = order;
this.getCourseDetails()
},
methods: {
getStatusText(status) {
const statusMap = {
'0': '待支付',
'1': '已取消',
'2': '已支付',
'7': '退款中',
'8': '退款成功'
}
return statusMap[status] || '未知状态'
},
getPayTypeText(type) {
const typeMap = {
'2': '全款支付',
'1': '定金支付'
}
return typeMap[type] || '未知支付方式'
},
getCourseTypeText(type) {
const typeMap = {
'C1': 'C1驾照课程',
'C2': 'C2驾照课程'
}
return typeMap[type] || type
},
formatTime(timestamp) {
if (!timestamp) return '无'
const date = new Date(timestamp)
return `${date.getFullYear()}-${this.padZero(date.getMonth() + 1)}-${this.padZero(date.getDate())} ${this.padZero(date.getHours())}:${this.padZero(date.getMinutes())}:${this.padZero(date.getSeconds())}`
},
padZero(num) {
return num < 10 ? `0${num}` : num
},
/* handlePay() {
uni.showLoading({ title: '跳转支付中...' })
this.directWxPay(this.orderData.orderId, this.orderData.orderNo, this.orderData.payType)
setTimeout(() => {
uni.hideLoading()
uni.showToast({ title: '支付成功', icon: 'success' })
}, 1500)
}, */
async handlePay() {
uni.showLoading({ title: '跳转支付中...' });
try {
const res = await this.directWxPay(this.orderData.id, this.orderData.orderNo, this.orderData.payType);
if (res === 'success') {
uni.showToast({ title: '支付成功', icon: 'success' });
} else if (res === 'cancelled') {
uni.showToast({ title: '已取消支付', icon: 'none' });
} else {
uni.showToast({ title: '支付失败,请重试', icon: 'none' });
}
} catch (error) {
uni.showToast({ title: '支付异常', icon: 'none' });
console.error('支付异常', error);
} finally {
uni.hideLoading();
}
},
getCourseDetails() {
request({
url: '/app-api/dl-drive-school-course-small/get',
method: 'GET',
params: {
id: this.orderData.courseId,
tenantId: this.orderData.tenantId,
},
tenantIdFlag: false
}).then(res => {
this.courseDetails = res.data;
this.getSchoolDetails()
})
},
getSchoolDetails() {
request({
url: '/userClient/base/companySmallProgram/pageNoTenantId',
method: 'GET',
params: {
id: this.orderData.tenantId,
serviceCodes: 'jiaxiao',
},
tenantIdFlag: false
}).then(res => {
const data = res.data.records;
this.schoolDetails = Array.isArray(data) && data.length > 0 ? data[0] : null;
})
},
async directWxPay(orderId, orderNo, payType) {
try {
// 1. 获取预支付参数
const prepayRes = await request({
url: `/small/jxInfo/prepayment?type=jsapi&orderNo=${orderNo}&orderId=${orderId}&payType=${payType}`,
method: 'get'
});
// 2. 调用微信支付
const result = await this.handleWxPayment(prepayRes);
// 3. 支付成功后处理逻辑(可选)
if (result === 'success') {
await this.updateOrderStatus(orderId, '2');
await this.insertSchoolStudent(); // 如果有插入学员信息
this.signContract(); // 如果还需要签约
}
return result;
} catch (error) {
console.error("支付失败:", error);
uni.showToast({ title: '支付失败,请重试', icon: 'none' });
return 'fail';
}
},
handleWxPayment(paymentParams) {
return new Promise((resolve) => {
wx.requestPayment({
...paymentParams,
success: (res) => {
resolve(res.errMsg === 'requestPayment:ok' ? 'success' : 'fail');
},
fail: (err) => {
resolve(err.errMsg === 'requestPayment:fail cancel' ? 'cancelled' : 'fail');
}
});
});
},
// 插入学员信息
insertSchoolStudent() {
request({
url: '/app-api/small/dl-drive-school-student/create',
method: 'post',
data: {
name: this.orderData.userName,
sex: this.orderData.userSex,
phone: this.orderData.userPhone,
idCard: this.orderData.userNo,
registAddress: this.Address,
userId: this.orderData.userId,
tenantId: this.orderData.tenantId,
}
})
this.updateSysUsersNickName()
},
// 修改users信息
updateSysUsersNickName(){
request({
url: '/app-api/system/user/update',
method: 'PUT',
data: {
nickname: this.orderData.userName,
id: this.orderData.userId,
}
})
},
// 更新订单状态
async updateOrderStatus(orderId, status) {
await request({
url: '/app-api/small/drive/school-course-order/update',
method: 'put',
data: {
id: orderId,
paymentStatus: status
}
});
},
// 签合同
signContract() {
const contractData = {
adress: '',
name: this.orderData.userName,
tenantId: this.orderData.tenantId,
type: this.orderData.type,
carType: this.getLicenseTypeDescription(this.orderData.type),
money: this.orderData.reserveMoney,
indent: this.orderData.userNo,
phone: this.orderData.userPhone,
time: this.getCurrentDateTime()
};
uni.navigateTo({
url: '/pages/index/contract?data=' + encodeURIComponent(JSON.stringify(contractData))
})
},
// 格式化时间
getCurrentDateTime() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}`;
// return now;
},
getLicenseTypeDescription(code) {
const licenseMap = {
C1: "小型手动挡汽车",
C2: "小型自动档汽车",
B1: "中型客车",
B2: "大型货车",
A1: "大型客车",
A2: "牵引车",
A3: "城市公交车",
D: "三轮摩托车",
E: "两轮摩托车",
F: "轻便摩托车"
};
return licenseMap[code] || "未知类型";
},
// 取消订单
cancelOrder() {
request({
url: '/app-api/small/drive/school-course-order/update',
method: 'PUT',
data: {
id: this.orderData.id,
paymentStatus: '1',
}
}).then(res => {
if (res.code === 0) {
uni.showToast({
title: '取消成功',
icon: 'success',
duration: 2000
});
this.orderData.paymentStatus = '1';
}
});
},
}
}
</script>
<style scoped>
.order-detail-container {
padding-bottom: 200rpx;
background-color: #f7f7f7;
min-height: 100vh;
}
/* 头部样式 */
.header {
position: relative;
}
.navbar {
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #ffffff;
position: relative;
}
.navbar-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.status-card {
height: 40rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #fff;
}
.status-0 {
background: linear-gradient(to right, #ff976a, #ff6600);
}
.status-1 {
background: linear-gradient(to right, #ffcc00, #ff9900);
}
.status-2 {
background: linear-gradient(to right, #19be6b, #00b050);
}
.status-3 {
background: linear-gradient(to right, #dd6161, #cc0000);
}
.status-4 {
background: linear-gradient(to right, #909399, #808080);
}
.status-text {
font-size: 28rpx;
margin-top: 2rpx;
}
/* 卡片通用样式 */
.info-card, .course-card, .price-card {
margin: 30rpx;
background: #fff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.05);
}
/* 信息项样式 */
.info-item {
padding: 24rpx 30rpx;
display: flex;
justify-content: space-between;
border-bottom: 2rpx solid #f5f5f5;
}
.info-title {
color: #666;
font-size: 28rpx;
}
.info-value {
color: #333;
font-size: 28rpx;
font-weight: 500;
}
/* 课程卡片样式 */
.course-header {
padding: 30rpx 30rpx 0;
display: flex;
justify-content: space-between;
margin-bottom: 24rpx;
}
2025-04-12 17:52:46 +08:00
.course-twoType {
width: 90%;
display: flex;
justify-content: flex-start;
}
2025-04-11 18:06:20 +08:00
.course-type {
2025-04-12 17:52:46 +08:00
font-size: 22rpx;
2025-04-11 18:06:20 +08:00
padding: 4rpx 16rpx;
border-radius: 8rpx;
color: #fff;
background-color: #2979ff;
2025-04-12 17:52:46 +08:00
margin-right: 10rpx;
2025-04-11 18:06:20 +08:00
}
.type-C1 {
background-color: #19be6b;
}
.type-C2 {
background-color: #2979ff;
}
.order-time {
font-size: 24rpx;
color: #909399;
}
.course-info {
padding: 0 30rpx 30rpx;
display: flex;
}
.course-image {
width: 240rpx;
height: 180rpx;
border-radius: 8rpx;
}
.course-detail {
flex: 1;
margin-left: 24rpx;
display: flex;
flex-direction: column;
}
.course-title {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 12rpx;
color: #333;
}
.course-desc {
font-size: 24rpx;
color: #909399;
line-height: 1.5;
margin-bottom: 8rpx;
display: -webkit-box;
-webkit-line-clamp: 3; /* 限制显示3行 */
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
/* 价格卡片样式 */
.price-card {
padding: 30rpx;
}
.price-row {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
font-size: 28rpx;
}
.price-row.total {
margin-top: 20rpx;
padding-top: 20rpx;
border-top: 2rpx dashed #eee;
font-weight: bold;
font-size: 32rpx;
}
.price-label {
color: #666;
}
.price-value {
color: #ff6600;
}
/* 底部按钮样式 */
.footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx 30rpx;
background: #fff;
box-shadow: 0 -4rpx 16rpx rgba(0,0,0,0.05);
display: flex;
justify-content: space-around;
}
/* .pay-button {
height: 80rpx;
background-color: #ff9900;
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
}
.cancel-button {
height: 80rpx;
background-color: #ff0105;
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
} */
.pay-button,
.cancel-button {
flex: 1;
height: 80rpx;
margin: 0 10rpx; /* 两个按钮之间留点间距 */
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
}
.pay-button {
background-color: #ff9900;
}
.cancel-button {
background-color: #ff0105;
}
.pay-button-text {
color: #fff;
font-size: 32rpx;
font-weight: bold;
}
</style>