成功修改订单页面套餐金额 为 套餐金额/套餐小时 ,而不是固定的10元/小时
This commit is contained in:
+335
-335
@@ -1,336 +1,336 @@
|
||||
<template>
|
||||
<view class="deposit-container">
|
||||
<!-- 押金金额卡片 -->
|
||||
<view class="deposit-card">
|
||||
<view class="title">押金余额</view>
|
||||
<view class="amount">¥{{ depositAmount }}</view>
|
||||
<button class="withdraw-btn" @click="handleWithdraw" :disabled="depositAmount <= 0">提现</button>
|
||||
</view>
|
||||
|
||||
<!-- 提现说明 -->
|
||||
<view class="notice-card">
|
||||
<view class="notice-title">
|
||||
<view class="dot"></view>
|
||||
<text>提现说明</text>
|
||||
</view>
|
||||
<view class="notice-content">
|
||||
<view class="notice-item">1. 提现金额将原路退回支付账户</view>
|
||||
<view class="notice-item">2. 提现申请提交后预计0-7个工作日到账</view>
|
||||
<view class="notice-item">3. 如超时未收到,请联系客服处理</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 押金记录 -->
|
||||
<view class="record-card" v-if="records.length > 0">
|
||||
<view class="record-title">押金记录</view>
|
||||
<view class="record-list">
|
||||
<view class="record-item" v-for="(item, index) in records" :key="index">
|
||||
<view class="record-info">
|
||||
<text class="record-type">{{ item.type }}</text>
|
||||
<text class="record-time">{{ item.time }}</text>
|
||||
</view>
|
||||
<text class="record-amount" :class="item.type === '退还' ? 'refund' : ''">
|
||||
{{ item.type === '退还' ? '+' : '-' }}¥{{ item.amount }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getUserInfo } from '../../util/index.js'
|
||||
import { withdrawDeposit,queryById } from '../../config/user.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
depositAmount: '0.00',
|
||||
orderNo: '',
|
||||
records: [],
|
||||
orderId:''
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// this.loadUserInfo()
|
||||
},
|
||||
onShow() {
|
||||
this.loadUserInfo()
|
||||
},
|
||||
methods: {
|
||||
async loadUserInfo() {
|
||||
try {
|
||||
const res = await getUserInfo()
|
||||
console.log('loadUserInfo',res);
|
||||
if (res.code === 200) {
|
||||
this.depositAmount = res.data.balanceAmount || '0.00'
|
||||
this.orderNo = res.data.latestOrderNo || ''
|
||||
this.orderId = res.data.latestOrderId||''
|
||||
|
||||
// 如果存在余额,获取押金记录
|
||||
if (parseFloat(this.depositAmount) > 0 && this.orderNo) {
|
||||
this.records = [
|
||||
{
|
||||
type: '支付',
|
||||
time: this.formatDate(new Date()),
|
||||
amount: this.depositAmount
|
||||
}
|
||||
]
|
||||
} else {
|
||||
this.records = []
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
uni.showToast({
|
||||
title: '获取用户信息失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
async handleWithdraw() {
|
||||
if (parseFloat(this.depositAmount) <= 0) {
|
||||
uni.showToast({
|
||||
title: '无可提现余额',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
if(this.orderId.length!=0||this.orderNo.length!=0){
|
||||
const res = await queryById(Number(this.orderId))
|
||||
console.log(res);
|
||||
}
|
||||
|
||||
// if(this.orderNo.length!=0){
|
||||
// uni.showToast({
|
||||
// title:'当前存在进行中的订单',
|
||||
// icon:'none'
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
|
||||
uni.showModal({
|
||||
title: '确认提现',
|
||||
content: '押金将原路退回,预计0-7个工作日到账',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({
|
||||
title: '提现中...'
|
||||
})
|
||||
|
||||
try {
|
||||
console.log('发起提现请求,订单号:', this.orderNo)
|
||||
const result = await withdrawDeposit(this.orderNo)
|
||||
console.log('提现响应:', result)
|
||||
|
||||
if (result.code === 200) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '提现申请已提交',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 更新余额为0
|
||||
this.depositAmount = '0.00'
|
||||
this.records.push({
|
||||
type: '退还',
|
||||
time: this.formatDate(new Date()),
|
||||
amount: this.depositAmount
|
||||
})
|
||||
|
||||
// 重新加载用户信息
|
||||
setTimeout(() => {
|
||||
this.loadUserInfo()
|
||||
}, 1500)
|
||||
} else {
|
||||
throw new Error(result.msg || '提现失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提现失败:', error)
|
||||
uni.hideLoading()
|
||||
|
||||
// 更详细的错误处理
|
||||
let errorMessage = '提现失败,请稍后再试';
|
||||
|
||||
// 如果有具体错误信息,使用它
|
||||
if (error.message) {
|
||||
// 常见错误消息处理
|
||||
if (error.message.includes('尚未归还')) {
|
||||
errorMessage = '当前订单尚未归还,请归还后再提现';
|
||||
} else if (error.message.includes('已退还')) {
|
||||
errorMessage = '押金已退还,无需重复提现';
|
||||
} else if (error.message.includes('处理中')) {
|
||||
errorMessage = '押金退还处理中,请耐心等待';
|
||||
} else if (error.message.includes('余额为0')) {
|
||||
errorMessage = '账户余额为0,无法提现';
|
||||
} else {
|
||||
// 使用后端返回的具体错误消息
|
||||
errorMessage = error.message;
|
||||
}
|
||||
}
|
||||
|
||||
// 显示错误提示
|
||||
uni.showModal({
|
||||
title: '提现失败',
|
||||
content: errorMessage,
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
formatDate(date) {
|
||||
const year = date.getFullYear()
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0')
|
||||
const day = date.getDate().toString().padStart(2, '0')
|
||||
const hours = date.getHours().toString().padStart(2, '0')
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0')
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.deposit-container {
|
||||
min-height: 100vh;
|
||||
background: #f8f8f8;
|
||||
padding: 30rpx;
|
||||
|
||||
.deposit-card {
|
||||
background: linear-gradient(135deg, #1976D2, #64B5F6);
|
||||
border-radius: 20rpx;
|
||||
padding: 40rpx;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
box-shadow: 0 4rpx 20rpx rgba(25,118,210,0.2);
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
opacity: 0.9;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 72rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.withdraw-btn {
|
||||
background: #fff;
|
||||
color: #1976D2;
|
||||
width: 80%;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
margin: 0 auto;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
background: rgba(255,255,255,0.6);
|
||||
color: rgba(25,118,210,0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notice-card {
|
||||
margin-top: 30rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.04);
|
||||
|
||||
.notice-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: #1976D2;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.notice-content {
|
||||
.notice-item {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
line-height: 1.8;
|
||||
padding-left: 22rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.record-card {
|
||||
margin-top: 30rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.04);
|
||||
|
||||
.record-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
border-left: 8rpx solid #1976D2;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
.record-list {
|
||||
.record-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.record-info {
|
||||
.record-type {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
margin-bottom: 6rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.record-time {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.record-amount {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
|
||||
&.refund {
|
||||
color: #4CAF50;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
<template>
|
||||
<view class="deposit-container">
|
||||
<!-- 押金金额卡片 -->
|
||||
<view class="deposit-card">
|
||||
<view class="title">押金余额</view>
|
||||
<view class="amount">¥{{ depositAmount }}</view>
|
||||
<button class="withdraw-btn" @click="handleWithdraw" :disabled="depositAmount <= 0">提现</button>
|
||||
</view>
|
||||
|
||||
<!-- 提现说明 -->
|
||||
<view class="notice-card">
|
||||
<view class="notice-title">
|
||||
<view class="dot"></view>
|
||||
<text>提现说明</text>
|
||||
</view>
|
||||
<view class="notice-content">
|
||||
<view class="notice-item">1. 提现金额将原路退回支付账户</view>
|
||||
<view class="notice-item">2. 提现申请提交后预计0-7个工作日到账</view>
|
||||
<view class="notice-item">3. 如超时未收到,请联系客服处理</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 押金记录 -->
|
||||
<view class="record-card" v-if="records.length > 0">
|
||||
<view class="record-title">押金记录</view>
|
||||
<view class="record-list">
|
||||
<view class="record-item" v-for="(item, index) in records" :key="index">
|
||||
<view class="record-info">
|
||||
<text class="record-type">{{ item.type }}</text>
|
||||
<text class="record-time">{{ item.time }}</text>
|
||||
</view>
|
||||
<text class="record-amount" :class="item.type === '退还' ? 'refund' : ''">
|
||||
{{ item.type === '退还' ? '+' : '-' }}¥{{ item.amount }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getUserInfo } from '../../util/index.js'
|
||||
import { withdrawDeposit,queryById } from '../../config/user.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
depositAmount: '0.00',
|
||||
orderNo: '',
|
||||
records: [],
|
||||
orderId:''
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// this.loadUserInfo()
|
||||
},
|
||||
onShow() {
|
||||
this.loadUserInfo()
|
||||
},
|
||||
methods: {
|
||||
async loadUserInfo() {
|
||||
try {
|
||||
const res = await getUserInfo()
|
||||
console.log('loadUserInfo',res);
|
||||
if (res.code === 200) {
|
||||
this.depositAmount = res.data.balanceAmount || '0.00'
|
||||
this.orderNo = res.data.latestOrderNo || ''
|
||||
this.orderId = res.data.latestOrderId||''
|
||||
|
||||
// 如果存在余额,获取押金记录
|
||||
if (parseFloat(this.depositAmount) > 0 && this.orderNo) {
|
||||
this.records = [
|
||||
{
|
||||
type: '支付',
|
||||
time: this.formatDate(new Date()),
|
||||
amount: this.depositAmount
|
||||
}
|
||||
]
|
||||
} else {
|
||||
this.records = []
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
uni.showToast({
|
||||
title: '获取用户信息失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
async handleWithdraw() {
|
||||
if (parseFloat(this.depositAmount) <= 0) {
|
||||
uni.showToast({
|
||||
title: '无可提现余额',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
if(this.orderId.length!=0||this.orderNo.length!=0){
|
||||
const res = await queryById(Number(this.orderId))
|
||||
console.log(res);
|
||||
}
|
||||
|
||||
// if(this.orderNo.length!=0){
|
||||
// uni.showToast({
|
||||
// title:'当前存在进行中的订单',
|
||||
// icon:'none'
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
|
||||
uni.showModal({
|
||||
title: '确认提现',
|
||||
content: '押金将原路退回,预计0-7个工作日到账',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({
|
||||
title: '提现中...'
|
||||
})
|
||||
|
||||
try {
|
||||
console.log('发起提现请求,订单号:', this.orderNo)
|
||||
const result = await withdrawDeposit(this.orderNo)
|
||||
console.log('提现响应:', result)
|
||||
|
||||
if (result.code === 200) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '提现申请已提交',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 更新余额为0
|
||||
this.depositAmount = '0.00'
|
||||
this.records.push({
|
||||
type: '退还',
|
||||
time: this.formatDate(new Date()),
|
||||
amount: this.depositAmount
|
||||
})
|
||||
|
||||
// 重新加载用户信息
|
||||
setTimeout(() => {
|
||||
this.loadUserInfo()
|
||||
}, 1500)
|
||||
} else {
|
||||
throw new Error(result.msg || '提现失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提现失败:', error)
|
||||
uni.hideLoading()
|
||||
|
||||
// 更详细的错误处理
|
||||
let errorMessage = '提现失败,请稍后再试';
|
||||
|
||||
// 如果有具体错误信息,使用它
|
||||
if (error.message) {
|
||||
// 常见错误消息处理
|
||||
if (error.message.includes('尚未归还')) {
|
||||
errorMessage = '当前订单尚未归还,请归还后再提现';
|
||||
} else if (error.message.includes('已退还')) {
|
||||
errorMessage = '押金已退还,无需重复提现';
|
||||
} else if (error.message.includes('处理中')) {
|
||||
errorMessage = '押金退还处理中,请耐心等待';
|
||||
} else if (error.message.includes('余额为0')) {
|
||||
errorMessage = '账户余额为0,无法提现';
|
||||
} else {
|
||||
// 使用后端返回的具体错误消息
|
||||
errorMessage = error.message;
|
||||
}
|
||||
}
|
||||
|
||||
// 显示错误提示
|
||||
uni.showModal({
|
||||
title: '提现失败',
|
||||
content: errorMessage,
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
formatDate(date) {
|
||||
const year = date.getFullYear()
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0')
|
||||
const day = date.getDate().toString().padStart(2, '0')
|
||||
const hours = date.getHours().toString().padStart(2, '0')
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0')
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.deposit-container {
|
||||
min-height: 100vh;
|
||||
background: #f8f8f8;
|
||||
padding: 30rpx;
|
||||
|
||||
.deposit-card {
|
||||
background: linear-gradient(135deg, #1976D2, #64B5F6);
|
||||
border-radius: 20rpx;
|
||||
padding: 40rpx;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
box-shadow: 0 4rpx 20rpx rgba(25,118,210,0.2);
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
opacity: 0.9;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 72rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.withdraw-btn {
|
||||
background: #fff;
|
||||
color: #1976D2;
|
||||
width: 80%;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
margin: 0 auto;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
background: rgba(255,255,255,0.6);
|
||||
color: rgba(25,118,210,0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notice-card {
|
||||
margin-top: 30rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.04);
|
||||
|
||||
.notice-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: #1976D2;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.notice-content {
|
||||
.notice-item {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
line-height: 1.8;
|
||||
padding-left: 22rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.record-card {
|
||||
margin-top: 30rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.04);
|
||||
|
||||
.record-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
border-left: 8rpx solid #1976D2;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
.record-list {
|
||||
.record-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.record-info {
|
||||
.record-type {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
margin-bottom: 6rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.record-time {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.record-amount {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
|
||||
&.refund {
|
||||
color: #4CAF50;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+176
-141
@@ -110,9 +110,28 @@
|
||||
onLoad(options) {
|
||||
// console.log(options);
|
||||
this.deviceId = options.deviceNo
|
||||
this.checkOrderStatus() // 新增状态检查
|
||||
console.log(options.deviceNo);
|
||||
this.getDeviceInfo()
|
||||
|
||||
// 如果URL中包含了feeConfig参数,直接使用它
|
||||
if (options.feeConfig) {
|
||||
try {
|
||||
console.log('从URL获取到feeConfig:', options.feeConfig)
|
||||
const feeConfigStr = decodeURIComponent(options.feeConfig)
|
||||
// 存储到设备信息中,这样后续处理逻辑可以保持不变
|
||||
this.deviceInfo = { ...this.deviceInfo, feeConfig: feeConfigStr }
|
||||
// 马上解析feeConfig并生成套餐选项
|
||||
this.parseFeeConfig()
|
||||
} catch (e) {
|
||||
console.error('解析URL中的feeConfig失败:', e)
|
||||
// 如果解析失败,继续正常流程获取设备信息
|
||||
this.checkOrderStatus()
|
||||
this.getDeviceInfo()
|
||||
}
|
||||
} else {
|
||||
// 正常流程
|
||||
this.checkOrderStatus() // 新增状态检查
|
||||
console.log(options.deviceNo);
|
||||
this.getDeviceInfo()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 检查登录状态和订单
|
||||
@@ -148,133 +167,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 解析feeConfig并生成套餐选项
|
||||
if (this.deviceInfo.feeConfig) {
|
||||
try {
|
||||
const feeConfig = JSON.parse(this.deviceInfo.feeConfig);
|
||||
|
||||
// 检查是否为新格式 [{"hour":1,"timesPrice":4},{"hour":3,"timesPrice":10},{"hour":5,"timesPrice":15}]
|
||||
if (feeConfig.length > 0 && 'hour' in feeConfig[0] && 'timesPrice' in feeConfig[0]) {
|
||||
// 新格式处理 - 直接使用所有套餐
|
||||
this.packages = feeConfig.map(pkg => {
|
||||
const hour = pkg.hour;
|
||||
const price = pkg.timesPrice;
|
||||
const unitPrice = (price / hour).toFixed(2);
|
||||
|
||||
return {
|
||||
time: `${hour}小时`,
|
||||
price: price.toFixed(2),
|
||||
unitPrice: unitPrice,
|
||||
hour: hour // 添加小时信息,用于后续处理
|
||||
};
|
||||
});
|
||||
|
||||
// 按小时排序
|
||||
this.packages.sort((a, b) => a.hour - b.hour);
|
||||
} else {
|
||||
// 旧格式处理
|
||||
// 通常使用common规格的配置
|
||||
const commonConfig = feeConfig.find(item => item.specCode === 'common') || feeConfig[0];
|
||||
|
||||
if (commonConfig) {
|
||||
// 根据收费类型生成套餐
|
||||
if (this.deviceInfo.feeType === 'hour') {
|
||||
// 按小时收费
|
||||
const hourPrice = commonConfig.hourPrice > 0 ? commonConfig.hourPrice : commonConfig.timesPrice / 6;
|
||||
|
||||
this.packages = [
|
||||
{
|
||||
time: '1小时',
|
||||
price: hourPrice.toFixed(2),
|
||||
unitPrice: hourPrice.toFixed(2)
|
||||
},
|
||||
{
|
||||
time: '6小时',
|
||||
price: (hourPrice * 6).toFixed(2),
|
||||
unitPrice: hourPrice.toFixed(2)
|
||||
},
|
||||
{
|
||||
time: '12小时',
|
||||
price: (hourPrice * 12).toFixed(2),
|
||||
unitPrice: hourPrice.toFixed(2)
|
||||
}
|
||||
];
|
||||
} else if (this.deviceInfo.feeType === 'times') {
|
||||
// 按次收费
|
||||
const timesPrice = commonConfig.timesPrice;
|
||||
this.packages = [
|
||||
{
|
||||
time: '1次',
|
||||
price: timesPrice.toFixed(2),
|
||||
unitPrice: timesPrice.toFixed(2)
|
||||
}
|
||||
];
|
||||
} else {
|
||||
// 默认套餐
|
||||
this.packages = [
|
||||
{
|
||||
time: '1小时',
|
||||
price: '2.00',
|
||||
unitPrice: '2.00'
|
||||
},
|
||||
{
|
||||
time: '6小时',
|
||||
price: '10.00',
|
||||
unitPrice: '1.67'
|
||||
},
|
||||
{
|
||||
time: '12小时',
|
||||
price: '15.00',
|
||||
unitPrice: '1.25'
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 默认选中中间套餐
|
||||
this.selectedPackage = Math.min(1, this.packages.length - 1);
|
||||
} catch (e) {
|
||||
console.error('解析设备费用配置失败:', e);
|
||||
// 使用默认套餐
|
||||
this.packages = [
|
||||
{
|
||||
time: '1小时',
|
||||
price: '2.00',
|
||||
unitPrice: '2.00'
|
||||
},
|
||||
{
|
||||
time: '6小时',
|
||||
price: '10.00',
|
||||
unitPrice: '1.67'
|
||||
},
|
||||
{
|
||||
time: '12小时',
|
||||
price: '15.00',
|
||||
unitPrice: '1.25'
|
||||
}
|
||||
];
|
||||
}
|
||||
} else {
|
||||
// 如果没有feeConfig,使用默认套餐
|
||||
this.packages = [
|
||||
{
|
||||
time: '1小时',
|
||||
price: '2.00',
|
||||
unitPrice: '2.00'
|
||||
},
|
||||
{
|
||||
time: '6小时',
|
||||
price: '10.00',
|
||||
unitPrice: '1.67'
|
||||
},
|
||||
{
|
||||
time: '12小时',
|
||||
price: '15.00',
|
||||
unitPrice: '1.25'
|
||||
}
|
||||
];
|
||||
}
|
||||
// 使用抽取的方法解析feeConfig并生成套餐选项
|
||||
this.parseFeeConfig();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -355,16 +249,8 @@
|
||||
return
|
||||
}
|
||||
|
||||
const selectedPkg = this.packages[this.selectedPackage]
|
||||
uni.showModal({
|
||||
title: '确认租借',
|
||||
content: `确认支付押金¥{{ depositAmount }}及${selectedPkg.time}套餐费用¥${selectedPkg.price}?`,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.submitRentOrder()
|
||||
}
|
||||
}
|
||||
})
|
||||
// 直接提交订单,不显示确认对话框
|
||||
this.submitRentOrder()
|
||||
},
|
||||
|
||||
// 提交租借订单
|
||||
@@ -424,7 +310,7 @@
|
||||
|
||||
// 跳转到订单支付页面,传递订单ID、套餐信息和总金额
|
||||
uni.redirectTo({
|
||||
url: `/pages/order/payment?orderId=${order.orderId}&packageTimeHours=${selectedPkg.time.replace('小时', '')}&packagePrice=${selectedPkg.price}&totalAmount=${totalAmount}&depositAmount=${this.depositAmount}`
|
||||
url: `/pages/order/payment?orderId=${order.orderId}&packageTimeHours=${selectedPkg.time.replace('小时', '')}&packagePrice=${selectedPkg.price}&totalAmount=${totalAmount}&depositAmount=${this.depositAmount}${this.deviceInfo && this.deviceInfo.feeConfig ? '&feeConfig=' + encodeURIComponent(this.deviceInfo.feeConfig) : ''}`
|
||||
})
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
@@ -433,6 +319,155 @@
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// 单独抽取解析feeConfig的逻辑
|
||||
parseFeeConfig() {
|
||||
if (this.deviceInfo.feeConfig) {
|
||||
try {
|
||||
const feeConfig = JSON.parse(this.deviceInfo.feeConfig);
|
||||
|
||||
// 检查是否为新格式 [{"hour":1,"timesPrice":4},{"hour":3,"timesPrice":10},{"hour":5,"timesPrice":15}]
|
||||
if (feeConfig.length > 0 && 'hour' in feeConfig[0] && 'timesPrice' in feeConfig[0]) {
|
||||
// 新格式处理 - 直接使用所有套餐
|
||||
this.packages = feeConfig.map(pkg => {
|
||||
const hour = pkg.hour;
|
||||
const price = pkg.timesPrice;
|
||||
const unitPrice = (price / hour).toFixed(2);
|
||||
|
||||
return {
|
||||
time: `${hour}小时`,
|
||||
price: price.toFixed(2),
|
||||
unitPrice: unitPrice,
|
||||
hour: hour // 添加小时信息,用于后续处理
|
||||
};
|
||||
});
|
||||
|
||||
// 按小时排序
|
||||
this.packages.sort((a, b) => a.hour - b.hour);
|
||||
} else {
|
||||
// 旧格式处理
|
||||
// 通常使用common规格的配置
|
||||
const commonConfig = feeConfig.find(item => item.specCode === 'common') || feeConfig[0];
|
||||
|
||||
if (commonConfig) {
|
||||
// 根据收费类型生成套餐
|
||||
if (this.deviceInfo.feeType === 'hour') {
|
||||
// 按小时收费
|
||||
const hourPrice = commonConfig.hourPrice > 0 ? commonConfig.hourPrice : commonConfig.timesPrice / 6;
|
||||
|
||||
this.packages = [
|
||||
{
|
||||
time: '1小时',
|
||||
price: hourPrice.toFixed(2),
|
||||
unitPrice: hourPrice.toFixed(2),
|
||||
hour: 1
|
||||
},
|
||||
{
|
||||
time: '6小时',
|
||||
price: (hourPrice * 6).toFixed(2),
|
||||
unitPrice: hourPrice.toFixed(2),
|
||||
hour: 6
|
||||
},
|
||||
{
|
||||
time: '12小时',
|
||||
price: (hourPrice * 12).toFixed(2),
|
||||
unitPrice: hourPrice.toFixed(2),
|
||||
hour: 12
|
||||
}
|
||||
];
|
||||
} else if (this.deviceInfo.feeType === 'times') {
|
||||
// 按次收费
|
||||
const timesPrice = commonConfig.timesPrice;
|
||||
this.packages = [
|
||||
{
|
||||
time: '1次',
|
||||
price: timesPrice.toFixed(2),
|
||||
unitPrice: timesPrice.toFixed(2),
|
||||
hour: 1
|
||||
}
|
||||
];
|
||||
} else {
|
||||
// 默认套餐
|
||||
this.packages = [
|
||||
{
|
||||
time: '1小时',
|
||||
price: '2.00',
|
||||
unitPrice: '2.00',
|
||||
hour: 1
|
||||
},
|
||||
{
|
||||
time: '6小时',
|
||||
price: '10.00',
|
||||
unitPrice: '1.67',
|
||||
hour: 6
|
||||
},
|
||||
{
|
||||
time: '12小时',
|
||||
price: '15.00',
|
||||
unitPrice: '1.25',
|
||||
hour: 12
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 默认选中中间套餐
|
||||
this.selectedPackage = Math.min(1, this.packages.length - 1);
|
||||
} catch (e) {
|
||||
console.error('解析设备费用配置失败:', e);
|
||||
// 使用默认套餐
|
||||
this.packages = [
|
||||
{
|
||||
time: '1小时',
|
||||
price: '2.00',
|
||||
unitPrice: '2.00',
|
||||
hour: 1
|
||||
},
|
||||
{
|
||||
time: '6小时',
|
||||
price: '10.00',
|
||||
unitPrice: '1.67',
|
||||
hour: 6
|
||||
},
|
||||
{
|
||||
time: '12小时',
|
||||
price: '15.00',
|
||||
unitPrice: '1.25',
|
||||
hour: 12
|
||||
}
|
||||
];
|
||||
|
||||
// 默认选中中间套餐
|
||||
this.selectedPackage = 1;
|
||||
}
|
||||
} else {
|
||||
// 如果没有feeConfig,使用默认套餐
|
||||
this.packages = [
|
||||
{
|
||||
time: '1小时',
|
||||
price: '2.00',
|
||||
unitPrice: '2.00',
|
||||
hour: 1
|
||||
},
|
||||
{
|
||||
time: '6小时',
|
||||
price: '10.00',
|
||||
unitPrice: '1.67',
|
||||
hour: 6
|
||||
},
|
||||
{
|
||||
time: '12小时',
|
||||
price: '15.00',
|
||||
unitPrice: '1.25',
|
||||
hour: 12
|
||||
}
|
||||
];
|
||||
|
||||
// 默认选中中间套餐
|
||||
this.selectedPackage = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+299
-299
@@ -1,300 +1,300 @@
|
||||
<template>
|
||||
<view class="feedback-container">
|
||||
<!-- 问题类型选择 -->
|
||||
<view class="type-section">
|
||||
<view class="section-title">问题类型</view>
|
||||
<view class="type-grid">
|
||||
<view
|
||||
v-for="(type, index) in types"
|
||||
:key="index"
|
||||
class="type-item"
|
||||
:class="{ active: selectedType === index }"
|
||||
@click="selectType(index)"
|
||||
>
|
||||
{{ type }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 问题描述 -->
|
||||
<view class="description-section">
|
||||
<view class="section-title">问题描述</view>
|
||||
<textarea
|
||||
class="description-input"
|
||||
v-model="description"
|
||||
placeholder="请详细描述您遇到的问题,以便我们更好地为您解决"
|
||||
maxlength="500"
|
||||
/>
|
||||
<view class="word-count">{{ description.length }}/500</view>
|
||||
</view>
|
||||
|
||||
<!-- 图片上传 -->
|
||||
<view class="upload-section">
|
||||
<view class="section-title">图片上传(选填)</view>
|
||||
<view class="upload-grid">
|
||||
<view
|
||||
class="upload-item"
|
||||
v-for="(img, index) in images"
|
||||
:key="index"
|
||||
>
|
||||
<image :src="img" mode="aspectFill" />
|
||||
<view class="delete-btn" @click="deleteImage(index)">×</view>
|
||||
</view>
|
||||
<view class="upload-btn" @click="chooseImage" v-if="images.length < 3">
|
||||
<text class="plus">+</text>
|
||||
<text class="tip">上传图片</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系方式 -->
|
||||
<view class="contact-section">
|
||||
<view class="section-title">联系方式</view>
|
||||
<input
|
||||
class="contact-input"
|
||||
v-model="contact"
|
||||
placeholder="请留下您的手机号,方便我们联系您"
|
||||
type="number"
|
||||
maxlength="11"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-section">
|
||||
<button class="submit-btn" @click="submitFeedback">提交反馈</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
types: ['设备故障', '收费问题', '使用建议', '其他'],
|
||||
selectedType: -1,
|
||||
description: '',
|
||||
images: [],
|
||||
contact: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectType(index) {
|
||||
this.selectedType = index
|
||||
},
|
||||
chooseImage() {
|
||||
uni.chooseImage({
|
||||
count: 3 - this.images.length,
|
||||
success: (res) => {
|
||||
this.images = [...this.images, ...res.tempFilePaths]
|
||||
}
|
||||
})
|
||||
},
|
||||
deleteImage(index) {
|
||||
this.images.splice(index, 1)
|
||||
},
|
||||
submitFeedback() {
|
||||
if (this.selectedType === -1) {
|
||||
uni.showToast({
|
||||
title: '请选择问题类型',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!this.description.trim()) {
|
||||
uni.showToast({
|
||||
title: '请描述您的问题',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!this.contact) {
|
||||
uni.showToast({
|
||||
title: '请留下联系方式',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: 提交反馈
|
||||
uni.showToast({
|
||||
title: '提交成功',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.feedback-container {
|
||||
min-height: 100vh;
|
||||
background: #f8f8f8;
|
||||
padding: 30rpx;
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.type-section {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.type-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 -10rpx;
|
||||
|
||||
.type-item {
|
||||
width: calc(50% - 20rpx);
|
||||
margin: 10rpx;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #f5f5f5;
|
||||
border-radius: 10rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
transition: all 0.3s;
|
||||
|
||||
&.active {
|
||||
background: #E3F2FD;
|
||||
color: #1976D2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.description-section {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.description-input {
|
||||
width: 100%;
|
||||
height: 240rpx;
|
||||
background: #f8f8f8;
|
||||
border-radius: 10rpx;
|
||||
padding: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.word-count {
|
||||
text-align: right;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-section {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.upload-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.upload-item {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-right: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
position: relative;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
position: absolute;
|
||||
right: -10rpx;
|
||||
top: -10rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background: rgba(0,0,0,0.5);
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-btn {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
background: #f5f5f5;
|
||||
border-radius: 10rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #999;
|
||||
|
||||
.plus {
|
||||
font-size: 60rpx;
|
||||
line-height: 1;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.contact-section {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.contact-input {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
background: #f8f8f8;
|
||||
border-radius: 10rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
.submit-section {
|
||||
padding: 0 40rpx;
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
background: #1976D2;
|
||||
color: #fff;
|
||||
border-radius: 44rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
<template>
|
||||
<view class="feedback-container">
|
||||
<!-- 问题类型选择 -->
|
||||
<view class="type-section">
|
||||
<view class="section-title">问题类型</view>
|
||||
<view class="type-grid">
|
||||
<view
|
||||
v-for="(type, index) in types"
|
||||
:key="index"
|
||||
class="type-item"
|
||||
:class="{ active: selectedType === index }"
|
||||
@click="selectType(index)"
|
||||
>
|
||||
{{ type }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 问题描述 -->
|
||||
<view class="description-section">
|
||||
<view class="section-title">问题描述</view>
|
||||
<textarea
|
||||
class="description-input"
|
||||
v-model="description"
|
||||
placeholder="请详细描述您遇到的问题,以便我们更好地为您解决"
|
||||
maxlength="500"
|
||||
/>
|
||||
<view class="word-count">{{ description.length }}/500</view>
|
||||
</view>
|
||||
|
||||
<!-- 图片上传 -->
|
||||
<view class="upload-section">
|
||||
<view class="section-title">图片上传(选填)</view>
|
||||
<view class="upload-grid">
|
||||
<view
|
||||
class="upload-item"
|
||||
v-for="(img, index) in images"
|
||||
:key="index"
|
||||
>
|
||||
<image :src="img" mode="aspectFill" />
|
||||
<view class="delete-btn" @click="deleteImage(index)">×</view>
|
||||
</view>
|
||||
<view class="upload-btn" @click="chooseImage" v-if="images.length < 3">
|
||||
<text class="plus">+</text>
|
||||
<text class="tip">上传图片</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系方式 -->
|
||||
<view class="contact-section">
|
||||
<view class="section-title">联系方式</view>
|
||||
<input
|
||||
class="contact-input"
|
||||
v-model="contact"
|
||||
placeholder="请留下您的手机号,方便我们联系您"
|
||||
type="number"
|
||||
maxlength="11"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-section">
|
||||
<button class="submit-btn" @click="submitFeedback">提交反馈</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
types: ['设备故障', '收费问题', '使用建议', '其他'],
|
||||
selectedType: -1,
|
||||
description: '',
|
||||
images: [],
|
||||
contact: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectType(index) {
|
||||
this.selectedType = index
|
||||
},
|
||||
chooseImage() {
|
||||
uni.chooseImage({
|
||||
count: 3 - this.images.length,
|
||||
success: (res) => {
|
||||
this.images = [...this.images, ...res.tempFilePaths]
|
||||
}
|
||||
})
|
||||
},
|
||||
deleteImage(index) {
|
||||
this.images.splice(index, 1)
|
||||
},
|
||||
submitFeedback() {
|
||||
if (this.selectedType === -1) {
|
||||
uni.showToast({
|
||||
title: '请选择问题类型',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!this.description.trim()) {
|
||||
uni.showToast({
|
||||
title: '请描述您的问题',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!this.contact) {
|
||||
uni.showToast({
|
||||
title: '请留下联系方式',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: 提交反馈
|
||||
uni.showToast({
|
||||
title: '提交成功',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.feedback-container {
|
||||
min-height: 100vh;
|
||||
background: #f8f8f8;
|
||||
padding: 30rpx;
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.type-section {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.type-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 -10rpx;
|
||||
|
||||
.type-item {
|
||||
width: calc(50% - 20rpx);
|
||||
margin: 10rpx;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #f5f5f5;
|
||||
border-radius: 10rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
transition: all 0.3s;
|
||||
|
||||
&.active {
|
||||
background: #E3F2FD;
|
||||
color: #1976D2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.description-section {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.description-input {
|
||||
width: 100%;
|
||||
height: 240rpx;
|
||||
background: #f8f8f8;
|
||||
border-radius: 10rpx;
|
||||
padding: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.word-count {
|
||||
text-align: right;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-section {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.upload-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.upload-item {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-right: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
position: relative;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
position: absolute;
|
||||
right: -10rpx;
|
||||
top: -10rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background: rgba(0,0,0,0.5);
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-btn {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
background: #f5f5f5;
|
||||
border-radius: 10rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #999;
|
||||
|
||||
.plus {
|
||||
font-size: 60rpx;
|
||||
line-height: 1;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.contact-section {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.contact-input {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
background: #f8f8f8;
|
||||
border-radius: 10rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
.submit-section {
|
||||
padding: 0 40rpx;
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
background: #1976D2;
|
||||
color: #fff;
|
||||
border-radius: 44rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+162
-162
@@ -1,163 +1,163 @@
|
||||
<template>
|
||||
<view class="help-container">
|
||||
<!-- 常见问题 -->
|
||||
<view class="faq-list">
|
||||
<view
|
||||
class="faq-item"
|
||||
v-for="(item, index) in faqList"
|
||||
:key="index"
|
||||
@click="toggleFaq(index)"
|
||||
>
|
||||
<view class="faq-header">
|
||||
<text class="question">{{ item.question }}</text>
|
||||
<view class="arrow" :class="{ open: item.isOpen }"></view>
|
||||
</view>
|
||||
<view class="answer" v-show="item.isOpen">
|
||||
{{ item.answer }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系客服 -->
|
||||
<view class="contact-card">
|
||||
<view class="contact-title">{{ HELP_CONTENT.CONTACT.TITLE }}</view>
|
||||
<view class="contact-content">
|
||||
<view class="contact-item">
|
||||
<text class="label">{{ HELP_CONTENT.CONTACT.PHONE.LABEL }}</text>
|
||||
<text class="value" @click="makePhoneCall">{{ HELP_CONTENT.CONTACT.PHONE.VALUE }}</text>
|
||||
</view>
|
||||
<view class="contact-item">
|
||||
<text class="label">{{ HELP_CONTENT.CONTACT.SERVICE_TIME.LABEL }}</text>
|
||||
<text class="value">{{ HELP_CONTENT.CONTACT.SERVICE_TIME.VALUE }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { HELP_CONTENT } from '@/constants/help'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
HELP_CONTENT,
|
||||
faqList: HELP_CONTENT.FAQ_LIST.map(item => ({
|
||||
...item,
|
||||
isOpen: false
|
||||
}))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleFaq(index) {
|
||||
this.faqList[index].isOpen = !this.faqList[index].isOpen
|
||||
},
|
||||
makePhoneCall() {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: HELP_CONTENT.CONTACT.PHONE.VALUE
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.help-container {
|
||||
min-height: 100vh;
|
||||
background: #f8f8f8;
|
||||
padding: 30rpx;
|
||||
|
||||
.faq-list {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 30rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.04);
|
||||
|
||||
.faq-item {
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.faq-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 30rpx 20rpx;
|
||||
|
||||
.question {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
padding-right: 20rpx;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-right: 4rpx solid #999;
|
||||
border-bottom: 4rpx solid #999;
|
||||
transform: rotate(45deg);
|
||||
transition: all 0.3s;
|
||||
|
||||
&.open {
|
||||
transform: rotate(-135deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.answer {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
padding: 0 20rpx 30rpx;
|
||||
background: #f9f9f9;
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.contact-card {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.04);
|
||||
|
||||
.contact-title {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
margin-bottom: 20rpx;
|
||||
border-left: 8rpx solid #1976D2;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
.contact-content {
|
||||
.contact-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
|
||||
&:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
<template>
|
||||
<view class="help-container">
|
||||
<!-- 常见问题 -->
|
||||
<view class="faq-list">
|
||||
<view
|
||||
class="faq-item"
|
||||
v-for="(item, index) in faqList"
|
||||
:key="index"
|
||||
@click="toggleFaq(index)"
|
||||
>
|
||||
<view class="faq-header">
|
||||
<text class="question">{{ item.question }}</text>
|
||||
<view class="arrow" :class="{ open: item.isOpen }"></view>
|
||||
</view>
|
||||
<view class="answer" v-show="item.isOpen">
|
||||
{{ item.answer }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系客服 -->
|
||||
<view class="contact-card">
|
||||
<view class="contact-title">{{ HELP_CONTENT.CONTACT.TITLE }}</view>
|
||||
<view class="contact-content">
|
||||
<view class="contact-item">
|
||||
<text class="label">{{ HELP_CONTENT.CONTACT.PHONE.LABEL }}</text>
|
||||
<text class="value" @click="makePhoneCall">{{ HELP_CONTENT.CONTACT.PHONE.VALUE }}</text>
|
||||
</view>
|
||||
<view class="contact-item">
|
||||
<text class="label">{{ HELP_CONTENT.CONTACT.SERVICE_TIME.LABEL }}</text>
|
||||
<text class="value">{{ HELP_CONTENT.CONTACT.SERVICE_TIME.VALUE }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { HELP_CONTENT } from '@/constants/help'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
HELP_CONTENT,
|
||||
faqList: HELP_CONTENT.FAQ_LIST.map(item => ({
|
||||
...item,
|
||||
isOpen: false
|
||||
}))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleFaq(index) {
|
||||
this.faqList[index].isOpen = !this.faqList[index].isOpen
|
||||
},
|
||||
makePhoneCall() {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: HELP_CONTENT.CONTACT.PHONE.VALUE
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.help-container {
|
||||
min-height: 100vh;
|
||||
background: #f8f8f8;
|
||||
padding: 30rpx;
|
||||
|
||||
.faq-list {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 30rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.04);
|
||||
|
||||
.faq-item {
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.faq-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 30rpx 20rpx;
|
||||
|
||||
.question {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
padding-right: 20rpx;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-right: 4rpx solid #999;
|
||||
border-bottom: 4rpx solid #999;
|
||||
transform: rotate(45deg);
|
||||
transition: all 0.3s;
|
||||
|
||||
&.open {
|
||||
transform: rotate(-135deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.answer {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
padding: 0 20rpx 30rpx;
|
||||
background: #f9f9f9;
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.contact-card {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.04);
|
||||
|
||||
.contact-title {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
margin-bottom: 20rpx;
|
||||
border-left: 8rpx solid #1976D2;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
.contact-content {
|
||||
.contact-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
|
||||
&:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+395
-339
@@ -1,339 +1,395 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 宣传图片区域 -->
|
||||
<view class="banner">
|
||||
<view class="temp-banner">
|
||||
<text class="banner-text">共享风扇</text>
|
||||
<text class="banner-subtitle">让清凉随身携带</text>
|
||||
<view class="banner-bg"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 扫码按钮区域 -->
|
||||
<view class="scan-area">
|
||||
<view class="scan-btn" @click="handleScan">
|
||||
<view class="btn-content">
|
||||
<image class="btn-icon" src="../../static/scan-icon.png" mode="aspectFit" />
|
||||
<text class="btn-text">扫一扫</text>
|
||||
</view>
|
||||
<text class="btn-desc">扫描设备二维码使用或归还</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 使用提示区域 -->
|
||||
<view class="tips-section">
|
||||
<view class="tips-header">
|
||||
<view class="tips-title">使用小贴士</view>
|
||||
</view>
|
||||
<view class="tips-list">
|
||||
<view class="tip-item">
|
||||
<view class="tip-dot"></view>
|
||||
<text>租借时间:每次最长可租借12小时</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<view class="tip-dot"></view>
|
||||
<text>押金说明:租借需支付99元押金,归还后自动退还</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<view class="tip-dot"></view>
|
||||
<text>收费标准:2元/小时,不足1小时按1小时计算</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<view class="tip-dot"></view>
|
||||
<text>爱护提示:请勿将设备带离指定区域,保持设备清洁</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getQueryString, wxLogin }from '@/util/index.js'
|
||||
import {
|
||||
URL
|
||||
}from"@/config/url.js"
|
||||
export default {
|
||||
methods: {
|
||||
async handleScan() {
|
||||
try {
|
||||
const scanResult = await new Promise((resolve, reject) => {
|
||||
uni.scanCode({
|
||||
success: resolve,
|
||||
fail: reject
|
||||
})
|
||||
})
|
||||
|
||||
let deviceNo = getQueryString(scanResult.path, 'deviceNo')
|
||||
console.log('扫码路径:', scanResult.path)
|
||||
console.log('解析到的设备号:', deviceNo)
|
||||
|
||||
if (!deviceNo) {
|
||||
uni.showToast({
|
||||
title: '无效的设备二维码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 直接在当前页面查询是否有使用中的订单,避免跳转到中间页面
|
||||
if (!uni.getStorageSync('token')) {
|
||||
await wxLogin()
|
||||
}
|
||||
|
||||
// 检查是否有使用中的订单
|
||||
const inUseRes = await uni.request({
|
||||
url: `${URL || 'http://127.0.0.1:8080'}/app/order/inUse`,
|
||||
method: 'GET',
|
||||
header: {
|
||||
'Authorization': "Bearer " + uni.getStorageSync('token'),
|
||||
'Clientid': uni.getStorageSync('client_id')
|
||||
}
|
||||
})
|
||||
|
||||
console.log('使用中订单检查结果:', JSON.stringify(inUseRes))
|
||||
|
||||
if (inUseRes.statusCode == 200 && inUseRes.data.code == 200 && inUseRes.data.data) {
|
||||
// 存在使用中的订单,跳转到归还页面
|
||||
const inUseOrder = inUseRes.data.data
|
||||
console.log('检测到使用中订单,准备跳转:', inUseOrder)
|
||||
|
||||
// 直接使用reLaunch而不是navigateTo以确保页面跳转
|
||||
uni.reLaunch({
|
||||
url: `/pages/return/index?orderId=${inUseOrder.orderId}&deviceId=${deviceNo || inUseOrder.deviceNo}`
|
||||
})
|
||||
console.log('已发起页面跳转')
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否有待支付订单
|
||||
const orderRes = await uni.request({
|
||||
url: `${URL || 'http://127.0.0.1:8080'}/app/order/unpaid`,
|
||||
method: 'GET',
|
||||
header: {
|
||||
'Authorization': "Bearer " + uni.getStorageSync('token'),
|
||||
'Clientid': uni.getStorageSync('client_id')
|
||||
}
|
||||
})
|
||||
|
||||
console.log('待支付订单检查结果:', JSON.stringify(orderRes))
|
||||
|
||||
if (orderRes.statusCode == 200 && orderRes.data.code == 200 && orderRes.data.data) {
|
||||
// 存在待支付订单,跳转到支付页面
|
||||
const unpaidOrder = orderRes.data.data
|
||||
console.log('检测到待支付订单,准备跳转:', unpaidOrder)
|
||||
uni.navigateTo({
|
||||
url: `/pages/order/payment?orderId=${unpaidOrder.orderId}`
|
||||
})
|
||||
} else {
|
||||
// 查询设备信息并直接跳转到设备详情页面
|
||||
console.log('无待支付订单,直接跳转到设备详情页面, deviceNo:', deviceNo)
|
||||
uni.navigateTo({
|
||||
url: `/pages/device/detail?deviceNo=${deviceNo}`
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('扫码处理失败:', error)
|
||||
uni.showToast({
|
||||
title: '扫码失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
height: 87.5vh;
|
||||
background: #f8f8f8;
|
||||
padding-bottom: 40rpx;
|
||||
|
||||
.banner {
|
||||
padding: 30rpx;
|
||||
|
||||
.temp-banner {
|
||||
height: 300rpx;
|
||||
background: linear-gradient(135deg, #1976D2, #42A5F5);
|
||||
border-radius: 30rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
box-shadow: 0 8rpx 32rpx rgba(25, 118, 210, 0.2);
|
||||
|
||||
.banner-text {
|
||||
font-size: 56rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.banner-subtitle {
|
||||
font-size: 32rpx;
|
||||
opacity: 0.95;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.banner-bg {
|
||||
position: absolute;
|
||||
right: -60rpx;
|
||||
bottom: -60rpx;
|
||||
width: 300rpx;
|
||||
height: 300rpx;
|
||||
background: rgba(255,255,255,0.1);
|
||||
border-radius: 50%;
|
||||
transform: rotate(-15deg);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -80rpx;
|
||||
top: -80rpx;
|
||||
width: 240rpx;
|
||||
height: 240rpx;
|
||||
background: rgba(255,255,255,0.08);
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scan-area {
|
||||
padding: 20rpx 30rpx 40rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.scan-btn {
|
||||
width: 460rpx;
|
||||
height: 200rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #00C853, #69F0AE);
|
||||
border-radius: 30rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 200, 83, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 200, 83, 0.15);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(rgba(255,255,255,0.1), transparent);
|
||||
}
|
||||
|
||||
.btn-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 12rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.btn-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 42rpx;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-desc {
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips-section {
|
||||
margin: 0 30rpx;
|
||||
background: #fff;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.05);
|
||||
overflow: hidden;
|
||||
|
||||
.tips-header {
|
||||
padding: 30rpx;
|
||||
background: linear-gradient(to right, #F5F9FF, #fff);
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
|
||||
.tips-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
position: relative;
|
||||
padding-left: 24rpx;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 8rpx;
|
||||
height: 32rpx;
|
||||
background: #1976D2;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips-list {
|
||||
padding: 20rpx 30rpx;
|
||||
|
||||
.tip-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
padding: 0 10rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.tip-dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: #1976D2;
|
||||
border-radius: 50%;
|
||||
margin-right: 16rpx;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 2rpx 6rpx rgba(25,118,210,0.2);
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 宣传图片区域 -->
|
||||
<view class="banner">
|
||||
<view class="temp-banner">
|
||||
<text class="banner-text">共享风扇</text>
|
||||
<text class="banner-subtitle">让清凉随身携带</text>
|
||||
<view class="banner-bg"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 扫码按钮区域 -->
|
||||
<view class="scan-area">
|
||||
<view class="scan-btn" @click="handleScan">
|
||||
<view class="btn-content">
|
||||
<image class="btn-icon" src="../../static/scan-icon.png" mode="aspectFit" />
|
||||
<text class="btn-text">扫一扫</text>
|
||||
</view>
|
||||
<text class="btn-desc">扫描设备二维码使用或归还</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 使用提示区域 -->
|
||||
<view class="tips-section">
|
||||
<view class="tips-header">
|
||||
<view class="tips-title">使用小贴士</view>
|
||||
</view>
|
||||
<view class="tips-list">
|
||||
<view class="tip-item">
|
||||
<view class="tip-dot"></view>
|
||||
<text>租借时间:每次最长可租借12小时</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<view class="tip-dot"></view>
|
||||
<text>押金说明:租借需支付99元押金,归还后自动退还</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<view class="tip-dot"></view>
|
||||
<text>收费标准:2元/小时,不足1小时按1小时计算</text>
|
||||
</view>
|
||||
<view class="tip-item">
|
||||
<view class="tip-dot"></view>
|
||||
<text>爱护提示:请勿将设备带离指定区域,保持设备清洁</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getQueryString, wxLogin }from '@/util/index.js'
|
||||
import {
|
||||
URL
|
||||
}from"@/config/url.js"
|
||||
import { getDeviceInfo } from '@/config/user.js'
|
||||
export default {
|
||||
methods: {
|
||||
async handleScan() {
|
||||
try {
|
||||
const scanResult = await new Promise((resolve, reject) => {
|
||||
uni.scanCode({
|
||||
success: resolve,
|
||||
fail: reject
|
||||
})
|
||||
})
|
||||
|
||||
let deviceNo = getQueryString(scanResult.path, 'deviceNo')
|
||||
console.log('扫码路径:', scanResult.path)
|
||||
console.log('解析到的设备号:', deviceNo)
|
||||
|
||||
if (!deviceNo) {
|
||||
uni.showToast({
|
||||
title: '无效的设备二维码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 直接在当前页面查询是否有使用中的订单,避免跳转到中间页面
|
||||
if (!uni.getStorageSync('token')) {
|
||||
await wxLogin()
|
||||
}
|
||||
|
||||
// 检查是否有使用中的订单
|
||||
const inUseRes = await uni.request({
|
||||
url: `${URL || 'http://127.0.0.1:8080'}/app/order/inUse`,
|
||||
method: 'GET',
|
||||
header: {
|
||||
'Authorization': "Bearer " + uni.getStorageSync('token'),
|
||||
'Clientid': uni.getStorageSync('client_id')
|
||||
}
|
||||
})
|
||||
|
||||
console.log('使用中订单检查结果:', JSON.stringify(inUseRes))
|
||||
|
||||
if (inUseRes.statusCode == 200 && inUseRes.data.code == 200 && inUseRes.data.data) {
|
||||
// 存在使用中的订单,跳转到归还页面
|
||||
const inUseOrder = inUseRes.data.data
|
||||
console.log('检测到使用中订单,准备跳转:', inUseOrder)
|
||||
|
||||
// 直接使用reLaunch而不是navigateTo以确保页面跳转
|
||||
uni.reLaunch({
|
||||
url: `/pages/return/index?orderId=${inUseOrder.orderId}&deviceId=${deviceNo || inUseOrder.deviceNo}`
|
||||
})
|
||||
console.log('已发起页面跳转')
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否有待支付订单
|
||||
const orderRes = await uni.request({
|
||||
url: `${URL || 'http://127.0.0.1:8080'}/app/order/unpaid`,
|
||||
method: 'GET',
|
||||
header: {
|
||||
'Authorization': "Bearer " + uni.getStorageSync('token'),
|
||||
'Clientid': uni.getStorageSync('client_id')
|
||||
}
|
||||
})
|
||||
|
||||
console.log('待支付订单检查结果:', JSON.stringify(orderRes))
|
||||
|
||||
if (orderRes.statusCode == 200 && orderRes.data.code == 200 && orderRes.data.data) {
|
||||
// 存在待支付订单,跳转到支付页面
|
||||
const unpaidOrder = orderRes.data.data
|
||||
console.log('检测到待支付订单,准备跳转:', unpaidOrder)
|
||||
uni.navigateTo({
|
||||
url: `/pages/order/payment?orderId=${unpaidOrder.orderId}`
|
||||
})
|
||||
} else {
|
||||
// 修改:直接获取设备信息,而不是跳转到详情页面
|
||||
console.log('无待支付订单,获取设备信息, deviceNo:', deviceNo)
|
||||
|
||||
try {
|
||||
// 获取设备信息
|
||||
const deviceInfoRes = await getDeviceInfo(deviceNo)
|
||||
|
||||
if (deviceInfoRes.code == 200 && deviceInfoRes.data && deviceInfoRes.data.device) {
|
||||
const deviceInfo = deviceInfoRes.data.device
|
||||
|
||||
// 如果有feeConfig,直接解析并处理
|
||||
if (deviceInfo.feeConfig) {
|
||||
console.log('获取到设备feeConfig信息:', deviceInfo.feeConfig)
|
||||
|
||||
// 这里可以直接解析feeConfig并进行前端处理
|
||||
try {
|
||||
const feeConfig = JSON.parse(deviceInfo.feeConfig)
|
||||
|
||||
// 根据解析后的feeConfig进行页面跳转并传递信息
|
||||
uni.navigateTo({
|
||||
url: `/pages/device/detail?deviceNo=${deviceNo}&feeConfig=${encodeURIComponent(deviceInfo.feeConfig)}`
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('解析feeConfig失败:', e)
|
||||
|
||||
// 解析失败时仍然跳转到详情页面,由详情页面处理
|
||||
uni.navigateTo({
|
||||
url: `/pages/device/detail?deviceNo=${deviceNo}`
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 没有feeConfig时,跳转到详情页面
|
||||
uni.navigateTo({
|
||||
url: `/pages/device/detail?deviceNo=${deviceNo}`
|
||||
})
|
||||
}
|
||||
} else {
|
||||
console.error('获取设备信息失败:', deviceInfoRes.msg || '未知错误')
|
||||
uni.showToast({
|
||||
title: '获取设备信息失败',
|
||||
icon: 'none'
|
||||
})
|
||||
|
||||
// 失败时仍然跳转到详情页面
|
||||
uni.navigateTo({
|
||||
url: `/pages/device/detail?deviceNo=${deviceNo}`
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取设备信息异常:', error)
|
||||
uni.showToast({
|
||||
title: '获取设备信息失败',
|
||||
icon: 'none'
|
||||
})
|
||||
|
||||
// 异常时仍然跳转到详情页面
|
||||
uni.navigateTo({
|
||||
url: `/pages/device/detail?deviceNo=${deviceNo}`
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('扫码处理失败:', error)
|
||||
uni.showToast({
|
||||
title: '扫码失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
height: 87.5vh;
|
||||
background: #f8f8f8;
|
||||
padding-bottom: 40rpx;
|
||||
|
||||
.banner {
|
||||
padding: 30rpx;
|
||||
|
||||
.temp-banner {
|
||||
height: 300rpx;
|
||||
background: linear-gradient(135deg, #1976D2, #42A5F5);
|
||||
border-radius: 30rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
box-shadow: 0 8rpx 32rpx rgba(25, 118, 210, 0.2);
|
||||
|
||||
.banner-text {
|
||||
font-size: 56rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.banner-subtitle {
|
||||
font-size: 32rpx;
|
||||
opacity: 0.95;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.banner-bg {
|
||||
position: absolute;
|
||||
right: -60rpx;
|
||||
bottom: -60rpx;
|
||||
width: 300rpx;
|
||||
height: 300rpx;
|
||||
background: rgba(255,255,255,0.1);
|
||||
border-radius: 50%;
|
||||
transform: rotate(-15deg);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -80rpx;
|
||||
top: -80rpx;
|
||||
width: 240rpx;
|
||||
height: 240rpx;
|
||||
background: rgba(255,255,255,0.08);
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scan-area {
|
||||
padding: 20rpx 30rpx 40rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.scan-btn {
|
||||
width: 460rpx;
|
||||
height: 200rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #00C853, #69F0AE);
|
||||
border-radius: 30rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 200, 83, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 200, 83, 0.15);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(rgba(255,255,255,0.1), transparent);
|
||||
}
|
||||
|
||||
.btn-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 12rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.btn-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 42rpx;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-desc {
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips-section {
|
||||
margin: 0 30rpx;
|
||||
background: #fff;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.05);
|
||||
overflow: hidden;
|
||||
|
||||
.tips-header {
|
||||
padding: 30rpx;
|
||||
background: linear-gradient(to right, #F5F9FF, #fff);
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
|
||||
.tips-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
position: relative;
|
||||
padding-left: 24rpx;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 8rpx;
|
||||
height: 32rpx;
|
||||
background: #1976D2;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips-list {
|
||||
padding: 20rpx 30rpx;
|
||||
|
||||
.tip-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
padding: 0 10rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.tip-dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: #1976D2;
|
||||
border-radius: 50%;
|
||||
margin-right: 16rpx;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 2rpx 6rpx rgba(25,118,210,0.2);
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
+501
-501
File diff suppressed because it is too large
Load Diff
+582
-610
File diff suppressed because it is too large
Load Diff
+337
-337
@@ -1,338 +1,338 @@
|
||||
<template>
|
||||
<view class="success-container">
|
||||
<!-- 支付成功状态 -->
|
||||
<view class="status-card">
|
||||
<view class="status-icon success"></view>
|
||||
<view class="status-text">支付成功</view>
|
||||
<view class="status-desc">您的订单已支付成功</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="order-card">
|
||||
<view class="card-title">订单信息</view>
|
||||
<view class="info-item">
|
||||
<text class="label">订单号</text>
|
||||
<text class="value">{{ orderInfo.orderNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">设备号</text>
|
||||
<text class="value">{{ orderInfo.deviceNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">支付金额</text>
|
||||
<text class="value">¥{{ orderInfo.amount || '0.00' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">支付时间</text>
|
||||
<text class="value">{{ orderInfo.payTime || '-' }}</text>
|
||||
</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>
|
||||
<button class="secondary-btn" @click="goToOrderList">查看订单</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { queryById, confirmPaymentAndRent } from '@/config/user.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
orderId: '',
|
||||
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: '订单信息不存在',
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.goToHome()
|
||||
}, 1500)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async loadOrderInfo() {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '加载中'
|
||||
})
|
||||
|
||||
const res = await queryById(this.orderId)
|
||||
if (res.code === 200 && res.data) {
|
||||
const orderData = res.data
|
||||
this.orderInfo = {
|
||||
orderNo: orderData.orderNo || orderData.orderId,
|
||||
deviceNo: orderData.deviceNo,
|
||||
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('获取订单信息失败')
|
||||
}
|
||||
|
||||
uni.hideLoading()
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: error.message || '获取订单信息失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// 触发弹出充电宝
|
||||
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}`)
|
||||
|
||||
// 调用确认支付并弹出的方法
|
||||
const result = await confirmPaymentAndRent(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')
|
||||
const day = date.getDate().toString().padStart(2, '0')
|
||||
const hour = date.getHours().toString().padStart(2, '0')
|
||||
const minute = date.getMinutes().toString().padStart(2, '0')
|
||||
const second = date.getSeconds().toString().padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hour}:${minute}:${second}`
|
||||
},
|
||||
goToHome() {
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
},
|
||||
goToOrderList() {
|
||||
uni.redirectTo({
|
||||
url: '/pages/order/index'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.success-container {
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.status-card {
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.status-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin: 0 auto 16px;
|
||||
background-color: #07c160;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
border: 3px solid #fff;
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
transform-origin: center;
|
||||
transform: translate(-50%, -70%) rotate(-45deg);
|
||||
}
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #07c160;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.status-desc {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.order-card {
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
|
||||
.primary-btn {
|
||||
background-color: #07c160;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 24px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.secondary-btn {
|
||||
background-color: #fff;
|
||||
color: #07c160;
|
||||
border: 1px solid #07c160;
|
||||
border-radius: 24px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
|
||||
&:active {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
}
|
||||
}
|
||||
<template>
|
||||
<view class="success-container">
|
||||
<!-- 支付成功状态 -->
|
||||
<view class="status-card">
|
||||
<view class="status-icon success"></view>
|
||||
<view class="status-text">支付成功</view>
|
||||
<view class="status-desc">您的订单已支付成功</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="order-card">
|
||||
<view class="card-title">订单信息</view>
|
||||
<view class="info-item">
|
||||
<text class="label">订单号</text>
|
||||
<text class="value">{{ orderInfo.orderNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">设备号</text>
|
||||
<text class="value">{{ orderInfo.deviceNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">支付金额</text>
|
||||
<text class="value">¥{{ orderInfo.amount || '0.00' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">支付时间</text>
|
||||
<text class="value">{{ orderInfo.payTime || '-' }}</text>
|
||||
</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>
|
||||
<button class="secondary-btn" @click="goToOrderList">查看订单</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { queryById, confirmPaymentAndRent } from '@/config/user.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
orderId: '',
|
||||
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: '订单信息不存在',
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.goToHome()
|
||||
}, 1500)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async loadOrderInfo() {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '加载中'
|
||||
})
|
||||
|
||||
const res = await queryById(this.orderId)
|
||||
if (res.code === 200 && res.data) {
|
||||
const orderData = res.data
|
||||
this.orderInfo = {
|
||||
orderNo: orderData.orderNo || orderData.orderId,
|
||||
deviceNo: orderData.deviceNo,
|
||||
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('获取订单信息失败')
|
||||
}
|
||||
|
||||
uni.hideLoading()
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: error.message || '获取订单信息失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// 触发弹出充电宝
|
||||
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}`)
|
||||
|
||||
// 调用确认支付并弹出的方法
|
||||
const result = await confirmPaymentAndRent(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')
|
||||
const day = date.getDate().toString().padStart(2, '0')
|
||||
const hour = date.getHours().toString().padStart(2, '0')
|
||||
const minute = date.getMinutes().toString().padStart(2, '0')
|
||||
const second = date.getSeconds().toString().padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hour}:${minute}:${second}`
|
||||
},
|
||||
goToHome() {
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
},
|
||||
goToOrderList() {
|
||||
uni.redirectTo({
|
||||
url: '/pages/order/index'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.success-container {
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.status-card {
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.status-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin: 0 auto 16px;
|
||||
background-color: #07c160;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
border: 3px solid #fff;
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
transform-origin: center;
|
||||
transform: translate(-50%, -70%) rotate(-45deg);
|
||||
}
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #07c160;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.status-desc {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.order-card {
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.label {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
|
||||
.primary-btn {
|
||||
background-color: #07c160;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 24px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.secondary-btn {
|
||||
background-color: #fff;
|
||||
color: #07c160;
|
||||
border: 1px solid #07c160;
|
||||
border-radius: 24px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
|
||||
&:active {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+136
-136
@@ -1,137 +1,137 @@
|
||||
<template>
|
||||
<view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
wxLogin,
|
||||
} from '../../../util/index'
|
||||
|
||||
import {
|
||||
getMyIndexInfo
|
||||
} from "../../../config/user.js";
|
||||
import {
|
||||
queryHasOrder
|
||||
} from "../../../config/user.js";
|
||||
import {
|
||||
checkOrdersByStatus
|
||||
} from "../../../config/user.js";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
async onLoad(option) {
|
||||
console.log('bagCheck onLoad option:', option);
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '处理中...',
|
||||
mask: true
|
||||
});
|
||||
|
||||
// 检查是否传入设备编号
|
||||
if (!option || !option.deviceNo) {
|
||||
throw new Error('未识别到设备编号');
|
||||
}
|
||||
|
||||
const deviceNo = option.deviceNo;
|
||||
|
||||
// 检查用户是否有进行中(in_used)或待支付(waiting_for_payment)的订单
|
||||
const statusesToCheck = ['in_used', 'waiting_for_payment'];
|
||||
const res = await checkOrdersByStatus(deviceNo, statusesToCheck);
|
||||
|
||||
if (res.code === 200 && res.data && res.data.length > 0) {
|
||||
// 找到相关订单,取最新的一条
|
||||
const latestOrder = res.data[0]; // 假设返回结果按时间倒序
|
||||
|
||||
if (latestOrder.orderStatus === 'in_used') {
|
||||
// 如果是使用中的订单,跳转到归还页面
|
||||
console.log('检测到使用中订单,跳转归还页:', latestOrder.orderId);
|
||||
uni.redirectTo({
|
||||
url: `/pages/device/return?orderId=${latestOrder.orderId}`
|
||||
});
|
||||
} else if (latestOrder.orderStatus === 'waiting_for_payment') {
|
||||
// 如果是待支付订单,跳转到支付页面,并传递必要信息
|
||||
console.log('检测到待支付订单,跳转支付页:', latestOrder.orderId);
|
||||
|
||||
// 获取套餐时间(分钟)
|
||||
const packageTimeMinutes = latestOrder.packageTime || 60;
|
||||
|
||||
// 套餐小时数
|
||||
const packageTimeHours = (packageTimeMinutes / 60).toFixed(1);
|
||||
|
||||
// 套餐价格
|
||||
const packagePrice = latestOrder.packagePrice || '0.00';
|
||||
|
||||
// 计算每小时费率
|
||||
const hourlyRate = (parseFloat(packagePrice) / (packageTimeMinutes / 60)).toFixed(2);
|
||||
|
||||
// 押金金额
|
||||
const depositAmount = latestOrder.depositAmount || '99.00';
|
||||
|
||||
// 计算总金额(套餐+押金)
|
||||
const totalAmount = (parseFloat(depositAmount) + parseFloat(packagePrice)).toFixed(2);
|
||||
|
||||
uni.redirectTo({
|
||||
url: `/pages/order/payment?orderId=${latestOrder.orderId}&packageTimeHours=${packageTimeHours}&packagePrice=${packagePrice}&hourlyRate=${hourlyRate}&totalAmount=${totalAmount}&depositAmount=${depositAmount}`
|
||||
});
|
||||
} else {
|
||||
// 其他状态(理论上不应该到这里,除非statusesToCheck配置错误),默认到详情页
|
||||
console.log('检测到其他状态订单,跳转详情页:', latestOrder.orderId);
|
||||
uni.redirectTo({
|
||||
url: `/pages/device/detail?deviceNo=${deviceNo}`
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 没有找到相关状态的订单,跳转到设备详情页进行租借
|
||||
console.log('未检测到相关订单,跳转详情页');
|
||||
uni.redirectTo({
|
||||
url: `/pages/device/detail?deviceNo=${deviceNo}`
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
// 只处理真正的错误,不是"没有订单"的情况
|
||||
if (error.message && (
|
||||
error.message.includes('未识别到设备编号') ||
|
||||
error.message.includes('网络请求失败') ||
|
||||
error.message.includes('服务器错误')
|
||||
)) {
|
||||
console.error('扫码检查订单失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '处理失败,请稍后重试',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
} else {
|
||||
// 对于其他错误,包括"没有找到订单",直接跳转到详情页,不显示错误消息
|
||||
console.log('没有找到符合条件的订单或发生其他错误,直接跳转详情页');
|
||||
}
|
||||
|
||||
// 无论什么情况,都跳转到一个可用页面
|
||||
setTimeout(() => {
|
||||
if (option && option.deviceNo) {
|
||||
uni.redirectTo({
|
||||
url: `/pages/device/detail?deviceNo=${option.deviceNo}`
|
||||
});
|
||||
} else {
|
||||
// 如果连deviceNo都没有,则返回首页
|
||||
uni.switchTab({ url: '/pages/index/index' });
|
||||
}
|
||||
}, 2000);
|
||||
} finally {
|
||||
uni.hideLoading();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
<template>
|
||||
<view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
wxLogin,
|
||||
} from '../../../util/index'
|
||||
|
||||
import {
|
||||
getMyIndexInfo
|
||||
} from "../../../config/user.js";
|
||||
import {
|
||||
queryHasOrder
|
||||
} from "../../../config/user.js";
|
||||
import {
|
||||
checkOrdersByStatus
|
||||
} from "../../../config/user.js";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
async onLoad(option) {
|
||||
console.log('bagCheck onLoad option:', option);
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '处理中...',
|
||||
mask: true
|
||||
});
|
||||
|
||||
// 检查是否传入设备编号
|
||||
if (!option || !option.deviceNo) {
|
||||
throw new Error('未识别到设备编号');
|
||||
}
|
||||
|
||||
const deviceNo = option.deviceNo;
|
||||
|
||||
// 检查用户是否有进行中(in_used)或待支付(waiting_for_payment)的订单
|
||||
const statusesToCheck = ['in_used', 'waiting_for_payment'];
|
||||
const res = await checkOrdersByStatus(deviceNo, statusesToCheck);
|
||||
|
||||
if (res.code === 200 && res.data && res.data.length > 0) {
|
||||
// 找到相关订单,取最新的一条
|
||||
const latestOrder = res.data[0]; // 假设返回结果按时间倒序
|
||||
|
||||
if (latestOrder.orderStatus === 'in_used') {
|
||||
// 如果是使用中的订单,跳转到归还页面
|
||||
console.log('检测到使用中订单,跳转归还页:', latestOrder.orderId);
|
||||
uni.redirectTo({
|
||||
url: `/pages/device/return?orderId=${latestOrder.orderId}`
|
||||
});
|
||||
} else if (latestOrder.orderStatus === 'waiting_for_payment') {
|
||||
// 如果是待支付订单,跳转到支付页面,并传递必要信息
|
||||
console.log('检测到待支付订单,跳转支付页:', latestOrder.orderId);
|
||||
|
||||
// 获取套餐时间(分钟)
|
||||
const packageTimeMinutes = latestOrder.packageTime || 60;
|
||||
|
||||
// 套餐小时数
|
||||
const packageTimeHours = (packageTimeMinutes / 60).toFixed(1);
|
||||
|
||||
// 套餐价格
|
||||
const packagePrice = latestOrder.packagePrice || '0.00';
|
||||
|
||||
// 计算每小时费率
|
||||
const hourlyRate = (parseFloat(packagePrice) / (packageTimeMinutes / 60)).toFixed(2);
|
||||
|
||||
// 押金金额
|
||||
const depositAmount = latestOrder.depositAmount || '99.00';
|
||||
|
||||
// 计算总金额(套餐+押金)
|
||||
const totalAmount = (parseFloat(depositAmount) + parseFloat(packagePrice)).toFixed(2);
|
||||
|
||||
uni.redirectTo({
|
||||
url: `/pages/order/payment?orderId=${latestOrder.orderId}&packageTimeHours=${packageTimeHours}&packagePrice=${packagePrice}&hourlyRate=${hourlyRate}&totalAmount=${totalAmount}&depositAmount=${depositAmount}`
|
||||
});
|
||||
} else {
|
||||
// 其他状态(理论上不应该到这里,除非statusesToCheck配置错误),默认到详情页
|
||||
console.log('检测到其他状态订单,跳转详情页:', latestOrder.orderId);
|
||||
uni.redirectTo({
|
||||
url: `/pages/device/detail?deviceNo=${deviceNo}`
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 没有找到相关状态的订单,跳转到设备详情页进行租借
|
||||
console.log('未检测到相关订单,跳转详情页');
|
||||
uni.redirectTo({
|
||||
url: `/pages/device/detail?deviceNo=${deviceNo}`
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
// 只处理真正的错误,不是"没有订单"的情况
|
||||
if (error.message && (
|
||||
error.message.includes('未识别到设备编号') ||
|
||||
error.message.includes('网络请求失败') ||
|
||||
error.message.includes('服务器错误')
|
||||
)) {
|
||||
console.error('扫码检查订单失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '处理失败,请稍后重试',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
} else {
|
||||
// 对于其他错误,包括"没有找到订单",直接跳转到详情页,不显示错误消息
|
||||
console.log('没有找到符合条件的订单或发生其他错误,直接跳转详情页');
|
||||
}
|
||||
|
||||
// 无论什么情况,都跳转到一个可用页面
|
||||
setTimeout(() => {
|
||||
if (option && option.deviceNo) {
|
||||
uni.redirectTo({
|
||||
url: `/pages/device/detail?deviceNo=${option.deviceNo}`
|
||||
});
|
||||
} else {
|
||||
// 如果连deviceNo都没有,则返回首页
|
||||
uni.switchTab({ url: '/pages/index/index' });
|
||||
}
|
||||
}, 2000);
|
||||
} finally {
|
||||
uni.hideLoading();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
+229
-229
@@ -1,230 +1,230 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 用户信息卡片 -->
|
||||
<view class="user-card">
|
||||
<view class="avatar">
|
||||
<image :src="userInfo.avatar || '/static/images/default-avatar.png'" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="user-info">
|
||||
<text class="nickname">{{ userInfo.nickName || '未登录' }}</text>
|
||||
<text class="phone">{{ userInfo.phone || '未绑定手机号' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 余额卡片 -->
|
||||
<view class="balance-card">
|
||||
<view class="balance-title">余额</view>
|
||||
<view class="balance-amount">¥{{ userInfo.balanceAmount || '0.00' }}</view>
|
||||
<view class="balance-desc">可用于租借设备</view>
|
||||
</view>
|
||||
|
||||
<!-- 功能菜单 -->
|
||||
<view class="menu-list">
|
||||
<view class="menu-item" @click="navigateTo('/pages/order/list')">
|
||||
<text class="menu-icon">📋</text>
|
||||
<text class="menu-text">我的订单</text>
|
||||
<text class="menu-arrow">></text>
|
||||
</view>
|
||||
<view class="menu-item" @click="navigateTo('/pages/user/feedback')">
|
||||
<text class="menu-icon">💬</text>
|
||||
<text class="menu-text">意见反馈</text>
|
||||
<text class="menu-arrow">></text>
|
||||
</view>
|
||||
<view class="menu-item" @click="navigateTo('/pages/user/about')">
|
||||
<text class="menu-icon">ℹ️</text>
|
||||
<text class="menu-text">关于我们</text>
|
||||
<text class="menu-arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 退出登录按钮 -->
|
||||
<view class="logout-btn" @click="handleLogout" v-if="isLogin">
|
||||
<text>退出登录</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getUserInfo } from '@/api/user'
|
||||
import { URL } from '@/config/url'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
userInfo: {},
|
||||
isLogin: false
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
this.checkLoginStatus()
|
||||
this.loadUserInfo()
|
||||
},
|
||||
methods: {
|
||||
async loadUserInfo() {
|
||||
try {
|
||||
const res = await getUserInfo()
|
||||
if (res.code === 200) {
|
||||
this.userInfo = res.data
|
||||
this.isLogin = true
|
||||
} else {
|
||||
this.isLogin = false
|
||||
uni.showToast({
|
||||
title: '获取用户信息失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载用户信息失败:', error)
|
||||
this.isLogin = false
|
||||
}
|
||||
},
|
||||
checkLoginStatus() {
|
||||
const token = uni.getStorageSync('token')
|
||||
this.isLogin = !!token
|
||||
if (!this.isLogin) {
|
||||
uni.redirectTo({
|
||||
url: '/pages/login/index'
|
||||
})
|
||||
}
|
||||
},
|
||||
navigateTo(url) {
|
||||
uni.navigateTo({ url })
|
||||
},
|
||||
handleLogout() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要退出登录吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.removeStorageSync('token')
|
||||
uni.removeStorageSync('userInfo')
|
||||
this.isLogin = false
|
||||
uni.redirectTo({
|
||||
url: '/pages/login/index'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 60rpx;
|
||||
overflow: hidden;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
|
||||
.avatar image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.nickname {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 10rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.phone {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.balance-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.balance-title {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.balance-amount {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.balance-desc {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.menu-list {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
}
|
||||
|
||||
.menu-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
font-size: 36rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.menu-text {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.menu-arrow {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
margin-top: 40rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
text-align: center;
|
||||
color: #ff4d4f;
|
||||
font-size: 28rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 用户信息卡片 -->
|
||||
<view class="user-card">
|
||||
<view class="avatar">
|
||||
<image :src="userInfo.avatar || '/static/images/default-avatar.png'" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="user-info">
|
||||
<text class="nickname">{{ userInfo.nickName || '未登录' }}</text>
|
||||
<text class="phone">{{ userInfo.phone || '未绑定手机号' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 余额卡片 -->
|
||||
<view class="balance-card">
|
||||
<view class="balance-title">余额</view>
|
||||
<view class="balance-amount">¥{{ userInfo.balanceAmount || '0.00' }}</view>
|
||||
<view class="balance-desc">可用于租借设备</view>
|
||||
</view>
|
||||
|
||||
<!-- 功能菜单 -->
|
||||
<view class="menu-list">
|
||||
<view class="menu-item" @click="navigateTo('/pages/order/list')">
|
||||
<text class="menu-icon">📋</text>
|
||||
<text class="menu-text">我的订单</text>
|
||||
<text class="menu-arrow">></text>
|
||||
</view>
|
||||
<view class="menu-item" @click="navigateTo('/pages/user/feedback')">
|
||||
<text class="menu-icon">💬</text>
|
||||
<text class="menu-text">意见反馈</text>
|
||||
<text class="menu-arrow">></text>
|
||||
</view>
|
||||
<view class="menu-item" @click="navigateTo('/pages/user/about')">
|
||||
<text class="menu-icon">ℹ️</text>
|
||||
<text class="menu-text">关于我们</text>
|
||||
<text class="menu-arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 退出登录按钮 -->
|
||||
<view class="logout-btn" @click="handleLogout" v-if="isLogin">
|
||||
<text>退出登录</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getUserInfo } from '@/api/user'
|
||||
import { URL } from '@/config/url'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
userInfo: {},
|
||||
isLogin: false
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
this.checkLoginStatus()
|
||||
this.loadUserInfo()
|
||||
},
|
||||
methods: {
|
||||
async loadUserInfo() {
|
||||
try {
|
||||
const res = await getUserInfo()
|
||||
if (res.code === 200) {
|
||||
this.userInfo = res.data
|
||||
this.isLogin = true
|
||||
} else {
|
||||
this.isLogin = false
|
||||
uni.showToast({
|
||||
title: '获取用户信息失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载用户信息失败:', error)
|
||||
this.isLogin = false
|
||||
}
|
||||
},
|
||||
checkLoginStatus() {
|
||||
const token = uni.getStorageSync('token')
|
||||
this.isLogin = !!token
|
||||
if (!this.isLogin) {
|
||||
uni.redirectTo({
|
||||
url: '/pages/login/index'
|
||||
})
|
||||
}
|
||||
},
|
||||
navigateTo(url) {
|
||||
uni.navigateTo({ url })
|
||||
},
|
||||
handleLogout() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要退出登录吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.removeStorageSync('token')
|
||||
uni.removeStorageSync('userInfo')
|
||||
this.isLogin = false
|
||||
uni.redirectTo({
|
||||
url: '/pages/login/index'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 60rpx;
|
||||
overflow: hidden;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
|
||||
.avatar image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.nickname {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 10rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.phone {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.balance-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.balance-title {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.balance-amount {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.balance-desc {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.menu-list {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
}
|
||||
|
||||
.menu-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
font-size: 36rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.menu-text {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.menu-arrow {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
margin-top: 40rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
text-align: center;
|
||||
color: #ff4d4f;
|
||||
font-size: 28rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user