Files
uni-fans-score/pages/order/detail.vue
T

1027 lines
27 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="order-detail-container">
<!-- 顶部标题 -->
<view class="page-header">
<view class="header-title">{{ getOrderStatusText() }}</view>
<view class="header-desc">{{ getStatusDesc() }}</view>
</view>
<!-- 订单信息卡片 -->
<view class="info-card">
<view class="info-row">
<view class="info-col">
<view class="info-value">{{ getUsedTimeNumber() }}</view>
<view class="info-label">{{ getUsedTimeUnit() }}</view>
</view>
<view class="info-col">
<view class="info-value">{{ getOrderFee() }}</view>
<view class="info-label">{{ isOrderCompleted() ? '订单金额' : '订单金额' }}</view>
</view>
<view class="info-col">
<view class="info-value">{{ orderInfo.packagePrice || '10' }}</view>
<view class="info-label"></view>
</view>
</view>
<view class="fee-rule">
计费规则5.0/60分钟 前15分钟内归还免费 不足60分钟按60分钟计费 封顶99元 持续计费至99元视为买断
</view>
</view>
<!-- 租借信息卡片 -->
<view class="rent-card">
<view class="rent-title">租借信息</view>
<view class="rent-item">
<view class="rent-label">订单编号</view>
<view class="rent-value">{{ orderInfo.orderNo || '-' }}</view>
</view>
<view class="rent-item">
<view class="rent-label">风扇编号</view>
<view class="rent-value">{{ deviceId || '-' }}</view>
</view>
<view class="rent-item">
<view class="rent-label">租借时间</view>
<view class="rent-value">{{ orderInfo.startTime || '-' }}</view>
</view>
<view class="rent-item">
<view class="rent-label">租借地点</view>
<view class="rent-value">{{ orderInfo.positionName || '新佳宜(九天银河店)' }}</view>
</view>
<view class="rent-item">
<view class="rent-label">租借方式</view>
<view class="rent-value">{{ getPayWayText() }}</view>
</view>
<view class="rent-item" v-if="isOrderCompleted() && orderInfo.endTime">
<view class="rent-label">归还时间</view>
<view class="rent-value">{{ orderInfo.endTime }}</view>
</view>
<view class="rent-item" v-if="isOrderCompleted() && orderInfo.returnPosition">
<view class="rent-label">归还地点</view>
<view class="rent-value">{{ orderInfo.returnPosition || '新佳宜(九天银河店)' }}</view>
</view>
<view class="rent-paid" v-if="isOrderCompleted()">
<text class="paid-label">已支付</text>
<text class="paid-value">{{ orderInfo.currentFee || orderInfo.payAmount || '10' }}</text>
<text class="paid-unit"></text>
</view>
</view>
<!-- 底部操作栏 -->
<view class="bottom-bar">
<!-- 使用中状态 -->
<template v-if="orderInfo.orderStatus === 'in_used'">
<view class="bottom-icon-btn" @click="contactService">
<image src="/static/customer-service.png" class="icon" mode="aspectFit"></image>
<text>客服中心</text>
</view>
<view v-if="!showExpressAction" class="countdown-btn">
{{ formatCountdown(countdownRemaining) }}后可快递归还
</view>
<view v-if="showExpressAction" class="action-btn secondary" @click="expressRetrunOrder">
暂停计费
</view>
<view v-if="showExpressAction" class="action-btn primary" @click="quickReturn">
快速归还
</view>
</template>
<!-- 已完成状态 -->
<template v-if="isOrderCompleted()">
<view class="bottom-icon-btn" @click="handleWithdraw" v-if="!orderInfo.isWithdrawn && orderInfo.refundAmount > 0">
<image src="/static/suggess.png" class="icon" mode="aspectFit"></image>
<text>费用申请</text>
</view>
<view class="bottom-icon-btn" @click="contactService">
<image src="/static/customer-service.png" class="icon" mode="aspectFit"></image>
<text>客服中心</text>
</view>
<view class="action-btn primary" @click="rentAgain">
再次租借
</view>
</template>
<!-- 待支付状态 -->
<template v-if="orderInfo.orderStatus === 'waiting_for_payment'">
<view class="action-btn secondary" @click="handleCancelOrder">取消订单</view>
<view class="action-btn primary" @click="handlePayment">立即支付</view>
</template>
<!-- 已取消状态 -->
<template v-if="orderInfo.orderStatus === 'order_cancelled'">
<view class="action-btn primary full-width" @click="goToHome">返回首页</view>
</template>
</view>
</view>
</template>
<script>
import {
queryById,
cancelOrder,
getSystemConfig
} from '@/config/user.js'
import {
URL
} from "@/config/url.js"
export default {
data() {
return {
deviceId: '',
orderInfo: {
orderId: '',
orderNo: '',
startTime: '',
endTime: '',
usedTime: '0分钟',
currentFee: '0.00',
orderStatus: '',
payWay: '',
depositAmount: '',
packageTime: '',
packagePrice: '',
payAmount: '0.00',
phone: '',
refundAmount: '0.00',
withdrawStatus: 'waiting',
isWithdrawn: false,
positionName: '',
returnPosition: ''
},
timer: null,
statusCheckTimer: null,
maxStatusChecks: 30,
currentStatusChecks: 0,
statusCheckInterval: 5000,
isPageActive: false,
expressThresholdSeconds: 180,
countdownRemaining: 0,
showExpressAction: false,
countdownTimer: null
}
},
onLoad(options) {
console.log('订单详情页加载,参数:', JSON.stringify(options))
this.isPageActive = true
this.orderInfo.orderId = options.orderId || ''
this.deviceId = options.deviceNo || options.deviceId || ''
if (!this.orderInfo.orderId && this.deviceId) {
this.getOrderByDevice()
} else if (this.orderInfo.orderId) {
this.getOrderDetails()
} else {
uni.showToast({
title: '缺少订单信息',
icon: 'none'
})
setTimeout(() => {
this.goToHome()
}, 1500)
}
// 注册全局订单完成事件监听器
uni.$on('orderCompleted', this.handleOrderCompleted)
// 获取系统配置
this.loadSystemConfig().then(() => {
if (this.orderInfo.orderStatus === 'in_used') {
this.startExpressCountdown()
}
})
},
onShow() {
this.isPageActive = true
if (this.orderInfo.orderStatus === 'in_used') {
this.startExpressCountdown()
}
},
onHide() {
console.log('订单详情页隐藏,清理资源')
this.isPageActive = false
this.clearTimer()
this.clearStatusCheckTimer()
this.clearExpressCountdown()
this.removeFromOrderMonitor()
},
onUnload() {
console.log('订单详情页卸载,清理所有资源')
this.isPageActive = false
this.clearTimer()
this.clearStatusCheckTimer()
this.clearExpressCountdown()
this.removeFromOrderMonitor()
uni.$off('orderCompleted', this.handleOrderCompleted)
},
methods: {
// 判断订单是否已完成
isOrderCompleted() {
return this.orderInfo.orderStatus === 'used_done' ||
this.orderInfo.orderStatus === 'used_down'
},
// 获取订单状态文字
getOrderStatusText() {
const statusMap = {
'waiting_for_payment': '待支付',
'payment_in_progress': '支付中',
'payment_successful': '支付成功',
'in_used': '使用中',
'payment_failed': '支付失败',
'order_cancelled': '已取消',
'used_done': '已完成',
'used_down': '已完成'
}
return statusMap[this.orderInfo.orderStatus] || '订单详情'
},
// 获取状态描述
getStatusDesc() {
const descMap = {
'waiting_for_payment': '请尽快完成支付',
'in_used': '请妥善保管设备,使用完毕后及时归还',
'used_done': '您的风扇已归还,感谢使用',
'used_down': '您的风扇已归还,感谢使用',
'order_cancelled': '订单已取消',
'payment_failed': '支付失败,请重新支付'
}
return descMap[this.orderInfo.orderStatus] || ''
},
// 获取状态图标样式
getStatusIconClass() {
const classMap = {
'waiting_for_payment': 'waiting',
'in_used': 'using',
'used_done': 'success',
'used_down': 'success',
'order_cancelled': 'cancelled',
'payment_failed': 'failed'
}
return classMap[this.orderInfo.orderStatus] || 'default'
},
// 获取退款状态文本
getWithdrawStatusText() {
const statusMap = {
'waiting': '待申请',
'processing': '处理中',
'success': '已退款',
'failed': '退款失败'
}
return statusMap[this.orderInfo.withdrawStatus] || '待申请'
},
// 获取支付方式文本
getPayWayText() {
const payWayMap = {
'wx_score_pay': '免押租借',
'wx_member_pay': '会员订单',
'wx_pay': '押金租借'
}
return payWayMap[this.orderInfo.payWay] || '免押租借'
},
// 格式化倒计时(显示为 HH:MM:SS 格式)
formatCountdown(totalSeconds) {
if (typeof totalSeconds !== 'number' || totalSeconds < 0) return '00:00:00'
const hours = Math.floor(totalSeconds / 3600)
const minutes = Math.floor((totalSeconds % 3600) / 60)
const seconds = totalSeconds % 60
const pad = (n) => n.toString().padStart(2, '0')
return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`
},
// 联系客服
contactService() {
uni.navigateTo({
url: '/pages/help/index'
})
},
// 快速归还
quickReturn() {
// 刷新订单状态,检查是否已归还
this.checkReturnStatus()
},
// 再次租借
rentAgain() {
uni.reLaunch({
url: '/pages/index/index'
})
},
// 获取使用时长的数字部分(用于显示)
getUsedTimeNumber() {
const usedTime = this.orderInfo.usedTime || '0分钟'
// 提取第一个数字(如 "1小时5分钟" -> "1"
const match = usedTime.match(/(\d+)/)
return match ? match[1] : '0'
},
// 获取使用时长的单位部分
getUsedTimeUnit() {
if (this.isOrderCompleted()) {
return '使用时长'
}
const usedTime = this.orderInfo.usedTime || '0分钟'
// 如果是完整的时长字符串,返回"已使用"
// 否则提取单位
if (usedTime.includes('小时')) {
return '小时'
} else if (usedTime.includes('分钟')) {
return '分钟'
}
return '已使用'
},
// 获取订单费用(不含单位)
getOrderFee() {
const fee = this.orderInfo.currentFee || this.orderInfo.payAmount || '0'
// 移除可能的"元"字符
return String(fee).replace(/[元¥]/g, '')
},
// 加载系统配置
async loadSystemConfig() {
try {
const res = await getSystemConfig()
if (res && res.code === 200 && res.data && typeof res.data.expressReturnCountdownSeconds === 'number') {
const seconds = res.data.expressReturnCountdownSeconds
if (seconds > 0) {
this.expressThresholdSeconds = seconds
}
}
if (this.orderInfo.orderStatus === 'in_used' && this.orderInfo.startTime) {
this.recomputeExpressCountdownFromStartTime()
}
} catch (e) {
console.log('加载系统配置失败:', e)
}
},
// 启动快递归还倒计时
startExpressCountdown() {
this.clearExpressCountdown()
this.recomputeExpressCountdownFromStartTime()
if (this.showExpressAction) return
this.countdownTimer = setInterval(() => {
if (!this.isPageActive) {
this.clearExpressCountdown()
return
}
if (this.orderInfo.orderStatus !== 'in_used') {
this.clearExpressCountdown()
return
}
this.recomputeExpressCountdownFromStartTime()
if (this.showExpressAction) {
this.clearExpressCountdown()
}
}, 1000)
},
// 清除倒计时
clearExpressCountdown() {
if (this.countdownTimer) {
clearInterval(this.countdownTimer)
this.countdownTimer = null
}
},
// 解析开始时间
parseStartTimeToMs(timeStr) {
if (!timeStr) return NaN
if (typeof timeStr === 'number') {
return timeStr < 1e12 ? timeStr * 1000 : timeStr
}
let normalized = String(timeStr).trim()
normalized = normalized.replace('T', ' ').replace(/\.\d+Z?$/, '')
const candidates = [
normalized,
normalized.replace(/-/g, '/')
]
for (let i = 0; i < candidates.length; i++) {
const ts = Date.parse(candidates[i])
if (!isNaN(ts)) return ts
}
const m = normalized.match(/(\d{4})[\/-](\d{1,2})[\/-](\d{1,2})\s+(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?/)
if (m) {
const y = parseInt(m[1])
const mon = parseInt(m[2]) - 1
const d = parseInt(m[3])
const h = parseInt(m[4])
const min = parseInt(m[5])
const s = m[6] ? parseInt(m[6]) : 0
return new Date(y, mon, d, h, min, s).getTime()
}
const num = Number(normalized)
if (!isNaN(num)) {
return num < 1e12 ? num * 1000 : num
}
return NaN
},
// 重新计算倒计时
recomputeExpressCountdownFromStartTime() {
if (this.orderInfo.orderStatus !== 'in_used') {
this.showExpressAction = false
this.countdownRemaining = 0
return
}
const startMs = this.parseStartTimeToMs(this.orderInfo.startTime)
if (isNaN(startMs)) {
this.showExpressAction = false
this.countdownRemaining = 0
return
}
const nowMs = Date.now()
const elapsedSeconds = Math.max(0, Math.floor((nowMs - startMs) / 1000))
const remaining = this.expressThresholdSeconds - elapsedSeconds
if (remaining <= 0) {
this.countdownRemaining = 0
this.showExpressAction = true
} else {
this.countdownRemaining = remaining
this.showExpressAction = false
}
},
// 从订单监控服务中移除当前订单
removeFromOrderMonitor() {
if (this.orderInfo.orderId && this.$orderMonitor) {
try {
this.$orderMonitor.removeOrder({
orderId: this.orderInfo.orderId
})
console.log('订单已从监控队列移除:', this.orderInfo.orderId)
} catch (error) {
console.error('从监控队列移除订单失败:', error)
}
}
},
// 处理订单完成事件
handleOrderCompleted(orderData) {
console.log('收到订单完成事件:', orderData)
if (orderData.orderId === this.orderInfo.orderId || orderData.orderNo === this.orderInfo.orderNo) {
// 刷新订单详情
this.getOrderDetails()
}
},
// 获取订单详情
async getOrderDetails() {
if (!this.isPageActive) {
console.log('页面已不活跃,跳过订单详情请求')
return
}
try {
if (!this.orderInfo.orderId) {
throw new Error('订单ID不能为空')
}
const result = await queryById(this.orderInfo.orderId)
if (result.code === 200 && result.data) {
const orderData = result.data
console.log('订单数据:', orderData)
// 更新订单信息
this.updateOrderInfo(orderData)
// 只有使用中的订单才启动定时器和监控
if (this.orderInfo.orderStatus === 'in_used') {
this.startTimer()
this.startStatusCheckTimer()
this.startExpressCountdown()
uni.setStorageSync('activeOrderId', this.orderInfo.orderId)
// 添加到监控队列
try {
if (this.$orderMonitor) {
this.$orderMonitor.removeOrder({
orderId: this.orderInfo.orderId
})
this.$orderMonitor.addOrder({
orderId: this.orderInfo.orderId
}, 'detail')
console.log('订单已添加到监控队列:', this.orderInfo.orderId)
}
} catch (error) {
console.error('添加订单到监控队列失败:', error)
}
}
} else {
throw new Error(result.msg || '获取订单详情失败')
}
} catch (error) {
console.error('获取订单详情错误:', error)
uni.showToast({
title: error.message || '获取订单信息失败',
icon: 'none'
})
setTimeout(() => {
this.goToHome()
}, 1500)
} finally {
uni.hideLoading()
}
},
// 更新订单信息
updateOrderInfo(orderData) {
this.orderInfo.usedTime = orderData.usedTime || '0分钟'
this.orderInfo.currentFee = orderData.currentFee || orderData.actualDeviceAmount || orderData.payAmount || '0.00'
this.orderInfo.orderStatus = orderData.orderStatus || ''
this.orderInfo.payWay = orderData.payWay || ''
this.orderInfo.startTime = orderData.startTime || orderData.createTime || ''
this.orderInfo.endTime = orderData.endTime || ''
this.orderInfo.depositAmount = orderData.depositAmount || ''
this.orderInfo.packageTime = orderData.packageTime || ''
this.orderInfo.packagePrice = orderData.packagePrice || ''
this.orderInfo.payAmount = orderData.payAmount || '0.00'
this.orderInfo.phone = orderData.phone || ''
this.orderInfo.orderNo = orderData.orderNo || ''
this.orderInfo.refundAmount = orderData.residueAmount || '0.00'
this.orderInfo.withdrawStatus = orderData.withdrawStatus || 'waiting'
this.orderInfo.isWithdrawn = orderData.withdrawStatus === 'success'
this.orderInfo.positionName = orderData.positionName || orderData.positionLocation || ''
this.orderInfo.returnPosition = orderData.returnPosition || orderData.positionName || orderData.positionLocation || ''
if (orderData.deviceNo && !this.deviceId) {
this.deviceId = orderData.deviceNo
}
},
// 更新使用时长的定时器
startTimer() {
this.clearTimer()
this.timer = setInterval(() => {
if (this.isPageActive) {
console.log('执行定时更新订单信息')
this.getOrderDetails()
} else {
console.log('页面已不活跃,停止计时器')
this.clearTimer()
}
}, 60000)
console.log('已启动使用时长更新计时器')
},
// 清除定时器
clearTimer() {
if (this.timer) {
clearInterval(this.timer)
this.timer = null
console.log('已清除使用时长更新计时器')
}
},
// 清除状态检查定时器
clearStatusCheckTimer() {
if (this.statusCheckTimer) {
clearInterval(this.statusCheckTimer)
this.statusCheckTimer = null
console.log('已清除归还状态检查计时器')
}
},
// 开始状态检查定时器
startStatusCheckTimer() {
this.currentStatusChecks = 0
this.clearStatusCheckTimer()
this.statusCheckTimer = setInterval(() => {
if (this.isPageActive) {
this.currentStatusChecks++
console.log(`执行归还状态检查 (${this.currentStatusChecks}/${this.maxStatusChecks})`)
this.checkReturnStatus()
if (this.currentStatusChecks >= this.maxStatusChecks) {
this.clearStatusCheckTimer()
uni.showToast({
title: '请手动刷新查看归还状态',
icon: 'none',
duration: 3000
})
}
} else {
console.log('页面已不活跃,停止状态检查计时器')
this.clearStatusCheckTimer()
}
}, this.statusCheckInterval)
console.log('已启动归还状态检查计时器')
},
// 通过设备号查询使用中的订单
async getOrderByDevice() {
try {
if (!this.deviceId) {
throw new Error('设备号不能为空')
}
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)
this.orderInfo.orderId = inUseOrder.orderId
this.orderInfo.orderStatus = inUseOrder.orderStatus || ''
this.orderInfo.payWay = inUseOrder.payWay || ''
this.orderInfo.startTime = inUseOrder.startTime || ''
this.getOrderDetails()
} else {
throw new Error('未找到使用中的订单')
}
} catch (error) {
console.error('通过设备号查询订单失败:', error)
uni.showToast({
title: error.message || '获取订单信息失败',
icon: 'none'
})
setTimeout(() => {
this.goToHome()
}, 1500)
} finally {
uni.hideLoading()
}
},
// 检查归还状态
async checkReturnStatus() {
try {
if (this.isPageActive) {
await this.getOrderDetails()
}
} catch (error) {
console.error('检查归还状态失败:', error)
}
},
// 快递归还
expressRetrunOrder() {
uni.navigateTo({
url: `/pages/expressReturn/addExpressReturn?orderId=${this.orderInfo.orderId}`
})
},
// 取消订单
handleCancelOrder() {
uni.showModal({
title: '确认取消',
content: '确定要取消此订单吗?',
success: async (res) => {
if (res.confirm) {
try {
uni.showLoading({
title: '处理中'
})
const result = await cancelOrder({
orderId: this.orderInfo.orderId
})
if (result.code === 200) {
uni.hideLoading()
uni.showToast({
title: '订单已取消',
icon: 'success'
})
await this.getOrderDetails()
} else {
throw new Error(result.msg || '取消订单失败')
}
} catch (error) {
uni.hideLoading()
uni.showToast({
title: error.message || '取消订单失败',
icon: 'none'
})
}
}
}
})
},
// 立即支付
handlePayment() {
uni.navigateTo({
url: `/pages/order/payment?orderId=${this.orderInfo.orderId}`
})
},
// 申请退款
async handleWithdraw() {
try {
uni.showLoading({
title: '处理中'
})
const res = await uni.request({
url: `${URL || 'http://127.0.0.1:8080'}/app/withdraw/add/${this.orderInfo.orderNo}`,
method: 'GET',
header: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + uni.getStorageSync('token'),
'Clientid': uni.getStorageSync('client_id')
}
})
if (res.statusCode === 200 && res.data.code === 200) {
uni.showToast({
title: '退款申请成功',
icon: 'success'
})
this.orderInfo.withdrawStatus = 'processing'
this.orderInfo.isWithdrawn = true
setTimeout(() => {
this.getOrderDetails()
}, 1500)
} else {
throw new Error(res.data.msg || '退款申请失败')
}
} catch (error) {
console.error('退款申请错误:', error)
uni.showToast({
title: error.message || '退款申请失败',
icon: 'none'
})
} finally {
uni.hideLoading()
}
},
// 返回首页
goToHome() {
uni.reLaunch({
url: '/pages/index/index'
})
},
// 格式化时间
formatTime(minutes) {
if (!minutes) return ''
const mins = parseInt(minutes)
if (mins < 60) {
return `${mins}分钟`
} else {
const hours = Math.floor(mins / 60)
const remainingMins = mins % 60
return remainingMins > 0 ? `${hours}小时${remainingMins}分钟` : `${hours}小时`
}
},
// 格式化倒计时
formatHms(totalSeconds) {
if (typeof totalSeconds !== 'number' || totalSeconds < 0) return '00:00:00'
const hours = Math.floor(totalSeconds / 3600)
const minutes = Math.floor((totalSeconds % 3600) / 60)
const seconds = totalSeconds % 60
const pad = (n) => n.toString().padStart(2, '0')
return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`
}
}
}
</script>
<style lang="scss" scoped>
.order-detail-container {
min-height: 100vh;
background: #f7f8fa;
padding: 30rpx;
padding-bottom: 180rpx;
box-sizing: border-box;
// 顶部标题
.page-header {
margin-bottom: 30rpx;
.header-title {
font-size: 48rpx;
font-weight: bold;
color: #333;
margin-bottom: 12rpx;
}
.header-desc {
font-size: 28rpx;
color: #999;
}
}
// 订单信息卡片
.info-card {
background: #fff;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
.info-row {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
.info-col {
flex: 1;
text-align: center;
.info-value {
font-size: 40rpx;
font-weight: bold;
color: #333;
margin-bottom: 8rpx;
}
.info-label {
font-size: 24rpx;
color: #999;
}
}
}
.fee-rule {
background: #E8F5E9;
border-radius: 8rpx;
padding: 16rpx;
font-size: 24rpx;
color: #4CAF50;
line-height: 1.6;
}
}
// 租借信息卡片
.rent-card {
background: #fff;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
.rent-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 24rpx;
}
.rent-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16rpx 0;
border-bottom: 1rpx solid #f0f0f0;
&:last-of-type {
border-bottom: none;
}
.rent-label {
font-size: 28rpx;
color: #999;
}
.rent-value {
font-size: 28rpx;
color: #333;
text-align: right;
max-width: 400rpx;
}
}
.rent-paid {
display: flex;
justify-content: flex-end;
align-items: baseline;
padding-top: 20rpx;
margin-top: 10rpx;
border-top: 1rpx solid #f0f0f0;
.paid-label {
font-size: 28rpx;
color: #999;
margin-right: 8rpx;
}
.paid-value {
font-size: 48rpx;
font-weight: bold;
color: #ff6b6b;
}
.paid-unit {
font-size: 28rpx;
color: #ff6b6b;
margin-left: 4rpx;
}
}
}
// 底部操作栏
.bottom-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: 20rpx 30rpx;
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
background: #fff;
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.04);
z-index: 10;
display: flex;
justify-content: space-between;
align-items: center;
gap: 20rpx;
.bottom-icon-btn {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-width: 100rpx;
.icon {
width: 48rpx;
height: 48rpx;
margin-bottom: 8rpx;
}
text {
font-size: 24rpx;
color: #666;
}
&:active {
opacity: 0.7;
}
}
.countdown-btn {
flex: 1;
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: #07c160;
background: #E8F5E9;
border-radius: 44rpx;
border: 2rpx solid #07c160;
}
.action-btn {
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
border-radius: 44rpx;
padding: 0 40rpx;
white-space: nowrap;
&.full-width {
flex: 1;
}
&.primary {
background: #07c160;
color: #fff;
flex: 1;
&:active {
opacity: 0.8;
}
}
&.secondary {
background: #f5f5f5;
color: #333;
border: 1rpx solid #e0e0e0;
&:active {
opacity: 0.8;
}
}
}
}
}
</style>