feat: 添加归还成功页面及相关功能

在 `pages.json` 中新增归还成功页面的配置,并在 `order/success.vue` 中实现设备状态提示和加载动画。同时,更新了订单支付逻辑,确保在支付成功后能够正确弹出充电宝。优化了订单状态查询和处理逻辑,提升用户体验。
This commit is contained in:
8vd8
2025-04-11 18:03:32 +08:00
parent 2da6ef8f41
commit f96ff2b030
33 changed files with 1505 additions and 536 deletions
+121 -4
View File
@@ -28,6 +28,14 @@
</view>
</view>
<!-- 设备状态 -->
<view class="device-status">
<view class="status-message">{{ deviceMessage }}</view>
<view class="loading-animation" v-if="isLoading">
<view class="loading-circle"></view>
</view>
</view>
<!-- 操作按钮 -->
<view class="button-group">
<button class="primary-btn" @click="goToHome">返回首页</button>
@@ -37,19 +45,28 @@
</template>
<script>
import { queryById } from '@/config/user.js'
import { queryById, confirmPaymentAndRent, sendRentCommand } from '@/config/user.js'
export default {
data() {
return {
orderId: '',
orderInfo: {}
orderInfo: {},
isLoading: true,
deviceMessage: '正在准备您的设备,请稍候...',
hasTriggeredDevice: false
}
},
onLoad(options) {
if (options && options.orderId) {
this.orderId = options.orderId
this.loadOrderInfo()
// 添加页面显示监听,防止页面切换后重复触发弹出
uni.$once('orderSuccess:' + this.orderId, () => {
console.log('已经触发过弹出逻辑,不再重复触发')
this.hasTriggeredDevice = true
})
} else {
uni.showToast({
title: '订单信息不存在',
@@ -73,8 +90,24 @@ export default {
this.orderInfo = {
orderNo: orderData.orderNo || orderData.orderId,
deviceNo: orderData.deviceNo,
amount: orderData.amount,
payTime: this.formatTime(new Date())
amount: orderData.payAmount || orderData.amount,
payTime: orderData.payTime || this.formatTime(new Date())
}
// 检查订单状态
if (orderData.orderStatus === 'IN_USED') {
// 如果已经是使用中状态,可能说明开锁已经完成
this.deviceMessage = '设备已弹出,请取走您的充电宝'
this.isLoading = false
// 如果是第一次加载页面且设备已弹出,记录状态,避免重复弹出
if (!this.hasTriggeredDevice) {
uni.$emit('orderSuccess:' + this.orderId)
this.hasTriggeredDevice = true
}
} else {
// 正常触发弹出逻辑
this.triggerDeviceEject()
}
} else {
throw new Error('获取订单信息失败')
@@ -89,6 +122,55 @@ export default {
})
}
},
// 触发弹出充电宝
async triggerDeviceEject() {
if (this.hasTriggeredDevice) {
console.log('已经触发过弹出充电宝,不重复触发')
return
}
this.hasTriggeredDevice = true
uni.$emit('orderSuccess:' + this.orderId)
this.isLoading = true
this.deviceMessage = '正在准备您的设备,请稍候...'
try {
console.log(`准备触发弹出充电宝,orderId: ${this.orderId}`)
// 先尝试使用确认支付并弹出的方法
let result
try {
result = await confirmPaymentAndRent(this.orderId)
console.log('确认支付并弹出充电宝结果:', JSON.stringify(result))
} catch (error) {
console.error('确认支付并弹出失败,尝试备用方法:', error)
// 如果第一种方法失败,尝试使用备用方法直接发送租借指令
result = await sendRentCommand(this.orderId)
console.log('发送租借指令结果:', JSON.stringify(result))
}
if (result && result.code === 200) {
this.deviceMessage = '设备已弹出,请取走您的充电宝'
uni.showToast({
title: '充电宝已弹出',
icon: 'success'
})
} else {
throw new Error((result && result.msg) || '弹出充电宝失败')
}
} catch (error) {
console.error('弹出充电宝错误:', error)
this.deviceMessage = '弹出设备失败,请联系客服'
uni.showToast({
title: error.message || '弹出充电宝失败,请联系客服',
icon: 'none'
})
} finally {
this.isLoading = false
}
},
formatTime(date) {
const year = date.getFullYear()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
@@ -194,6 +276,41 @@ export default {
}
}
.device-status {
background-color: #fff;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
text-align: center;
.status-message {
font-size: 16px;
color: #333;
margin-bottom: 12px;
}
.loading-animation {
display: flex;
justify-content: center;
align-items: center;
height: 40px;
.loading-circle {
width: 30px;
height: 30px;
border-radius: 50%;
border: 3px solid #f0f0f0;
border-top-color: #07c160;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
}
}
.button-group {
margin-top: 30px;
display: flex;