Files
uni-fans-score/pages/index/index.vue
T

644 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<!-- 顶部区域 -->
<view class="header">
<view class="header-bg">
<view class="circle-decoration circle-1"></view>
<view class="circle-decoration circle-2"></view>
<view class="wave-decoration"></view>
</view>
<view class="header-content">
<view class="brand-area">
<image class="brand-logo" src="@/static/logo.png" mode="aspectFit"></image>
<view class="brand-text">
<text class="title">共享风扇</text>
<text class="subtitle">随时随地享受清凉</text>
</view>
</view>
<view class="header-info">
<view class="service-tag">
<text>便捷租赁</text>
<text class="dot">·</text>
<text>品质保障</text>
</view>
</view>
</view>
</view>
<!-- 主扫码区域 -->
<view class="scan-section">
<view class="scan-card">
<view class="scan-btn" @click="handleScan">
<image class="scan-icon" src="@/static/scan-icon.png" mode="aspectFit" />
<text class="scan-text">扫码使用</text>
</view>
<view class="scan-desc">
<text>扫描设备二维码即可使用或归还</text>
</view>
</view>
</view>
<!-- 收费规则卡片 -->
<view class="price-card">
<view class="card-header">
<text class="card-title">收费规则</text>
</view>
<!-- 微信免押金标识 -->
<!-- <view class="deposit-free">
<image class="deposit-icon" src="@/static/images/wxpayflag.png" mode="aspectFit" />
<text class="deposit-text">微信支付分免押金</text>
</view> -->
<view class="price-rules">
<view class="price-item">
<view class="price-tag">5.0<text class="unit">/小时</text></view>
</view>
<view class="divider"></view>
<view class="rule-list">
<view class="rule-item">
<view class="rule-dot"></view>
<text>15分钟内归还免费</text>
</view>
<view class="rule-item">
<view class="rule-dot"></view>
<text>不足1小时按1小时计费</text>
</view>
<view class="rule-item">
<view class="rule-dot"></view>
<text>封顶99元计费达99元视为买断</text>
</view>
</view>
</view>
</view>
<!-- 使用流程 -->
<view class="usage-steps">
<view class="steps-header">
<text class="steps-title">使用流程</text>
</view>
<view class="steps-container">
<view class="step-item">
<view class="step-icon">
<text class="step-number">1</text>
</view>
<text class="step-text">扫码开锁</text>
</view>
<view class="step-arrow"></view>
<view class="step-item">
<view class="step-icon">
<text class="step-number">2</text>
</view>
<text class="step-text">使用风扇</text>
</view>
<view class="step-arrow"></view>
<view class="step-item">
<view class="step-icon">
<text class="step-number">3</text>
</view>
<text class="step-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
})
})
console.log(scanResult.path);
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 {
min-height: 100vh;
background-color: #f6f7fb;
padding-bottom: 40rpx;
}
/* 顶部区域 */
.header {
height: 300rpx;
background: linear-gradient(135deg, #1E88E5, #29B6F6);
position: relative;
overflow: hidden;
.header-bg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 1;
.circle-decoration {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
}
.circle-1 {
width: 240rpx;
height: 240rpx;
right: -60rpx;
top: -90rpx;
}
.circle-2 {
width: 160rpx;
height: 160rpx;
left: -40rpx;
bottom: 30rpx;
background: rgba(255, 255, 255, 0.08);
}
.wave-decoration {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 40rpx;
// background: url('@/static/images/wave.png') repeat-x;
background-size: auto 100%;
opacity: 0.6;
}
}
.header-content {
position: relative;
z-index: 2;
padding: 40rpx 40rpx 0;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
.brand-area {
display: flex;
align-items: center;
.brand-logo {
width: 90rpx;
height: 90rpx;
margin-right: 20rpx;
}
.brand-text {
display: flex;
flex-direction: column;
.title {
font-size: 48rpx;
color: #ffffff;
font-weight: bold;
line-height: 1.2;
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
}
.subtitle {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.9);
}
}
}
.header-info {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
margin-bottom: 30rpx;
.service-tag {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.2);
border-radius: 40rpx;
padding: 10rpx 20rpx;
text {
font-size: 24rpx;
color: #ffffff;
}
.dot {
margin: 0 8rpx;
font-weight: bold;
}
}
}
}
}
/* 扫码区域 */
.scan-section {
padding: 0 30rpx;
margin-top: -60rpx;
.scan-card {
background: #ffffff;
border-radius: 16rpx;
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.05);
padding: 36rpx 0;
display: flex;
flex-direction: column;
align-items: center;
.scan-btn {
width: 220rpx;
height: 220rpx;
background: linear-gradient(135deg, #00B0FF, #0091EA);
border-radius: 50%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-bottom: 24rpx;
box-shadow: 0 10rpx 20rpx rgba(0, 176, 255, 0.2);
position: relative;
transition: all 0.2s ease;
&:active {
transform: scale(0.96);
}
.scan-icon {
width: 80rpx;
height: 80rpx;
margin-bottom: 12rpx;
}
.scan-text {
font-size: 36rpx;
color: #ffffff;
font-weight: 500;
}
}
.scan-desc {
font-size: 28rpx;
color: #666;
}
}
}
/* 收费规则卡片 */
.price-card {
margin: 30rpx;
background: #ffffff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.04);
.card-header {
padding: 24rpx 30rpx;
background: linear-gradient(to right, #f5f9ff, #ffffff);
border-bottom: 2rpx solid #f0f0f0;
.card-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
position: relative;
padding-left: 20rpx;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 28rpx;
background: #2196F3;
border-radius: 3rpx;
}
}
}
/* 微信免押金区域 */
.deposit-free {
margin: 20rpx 30rpx 0;
padding: 12rpx 16rpx;
background: #f0f9ff;
border-radius: 8rpx;
border-left: 4rpx solid #03A9F4;
display: flex;
align-items: center;
.deposit-icon {
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
}
.deposit-text {
font-size: 26rpx;
color: #03A9F4;
font-weight: 500;
}
}
.price-rules {
padding: 20rpx 30rpx 30rpx;
.price-item {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 20rpx;
.price-tag {
font-size: 60rpx;
color: #FF6E00;
font-weight: bold;
line-height: 1;
.unit {
font-size: 32rpx;
font-weight: normal;
margin-left: 4rpx;
}
}
.price-desc {
font-size: 28rpx;
color: #666;
margin-top: 10rpx;
}
}
.divider {
height: 2rpx;
background-color: #f0f0f0;
margin: 20rpx 0 30rpx;
}
.rule-list {
.rule-item {
display: flex;
align-items: flex-start;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
.rule-dot {
width: 12rpx;
height: 12rpx;
background: #2196F3;
border-radius: 50%;
margin: 12rpx 16rpx 0 0;
flex-shrink: 0;
}
text {
font-size: 28rpx;
color: #666;
line-height: 1.5;
}
}
}
}
}
/* 使用流程 */
.usage-steps {
margin: 0 30rpx;
background: #ffffff;
border-radius: 16rpx;
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.04);
overflow: hidden;
.steps-header {
padding: 24rpx 30rpx;
background: linear-gradient(to right, #f5f9ff, #ffffff);
border-bottom: 2rpx solid #f0f0f0;
.steps-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
position: relative;
padding-left: 20rpx;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 28rpx;
background: #2196F3;
border-radius: 3rpx;
}
}
}
.steps-container {
padding: 40rpx 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
.step-item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
.step-icon {
width: 80rpx;
height: 80rpx;
background: #f0f9ff;
border: 2rpx solid #e1f5fe;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16rpx;
.step-number {
font-size: 36rpx;
color: #2196F3;
font-weight: 600;
}
}
.step-text {
font-size: 26rpx;
color: #666;
}
}
.step-arrow {
width: 40rpx;
height: 4rpx;
background: #e1f5fe;
position: relative;
&::after {
content: '';
position: absolute;
right: 0;
top: 50%;
margin-top: -8rpx;
border-left: 12rpx solid #e1f5fe;
border-top: 8rpx solid transparent;
border-bottom: 8rpx solid transparent;
}
}
}
}
</style>