style:调整样式
This commit is contained in:
+63
-3
@@ -38,13 +38,13 @@
|
||||
<view class="info-icon">
|
||||
<text class="icon-text">ⓘ</text>
|
||||
</view>
|
||||
<text class="info-text">5元/小时,45元/24小时</text>
|
||||
<text class="info-text">{{ getPricingInfoText() }}</text>
|
||||
</view>
|
||||
<view class="pricing-info">
|
||||
<view class="info-icon">
|
||||
<text class="icon-text">ⓘ</text>
|
||||
</view>
|
||||
<text class="info-text">前15分钟内归还免费,不足60分钟按60分钟计费点总封顶99元,持续计费至99元视为买断</text>
|
||||
<text class="info-text">{{ getDetailInfoText() }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -138,6 +138,7 @@
|
||||
const deviceInfo = ref({})
|
||||
const deviceId = ref('')
|
||||
const deviceFeeConfig = ref({})
|
||||
const positionInfo = ref({})
|
||||
const deviceLocation = ref('一号教学楼大厅')
|
||||
const batteryLevel = ref(95)
|
||||
const hasActiveOrder = ref(false)
|
||||
@@ -283,6 +284,11 @@
|
||||
if (res.code == 200) {
|
||||
deviceInfo.value = res.data.device || {}
|
||||
|
||||
// 保存 position 信息
|
||||
if (res.data.position) {
|
||||
positionInfo.value = res.data.position
|
||||
}
|
||||
|
||||
// 更新设备位置信息
|
||||
if (deviceInfo.value.deviceLocation) {
|
||||
deviceLocation.value = deviceInfo.value.deviceLocation
|
||||
@@ -377,10 +383,64 @@
|
||||
|
||||
const selectedPkg = reactive({
|
||||
time: '1小时',
|
||||
price: '5.00'
|
||||
price: '5'
|
||||
})
|
||||
const depositAmount = ref('99.00')
|
||||
|
||||
// 计算计费单位时间(分钟)
|
||||
const getBillingUnitMinutes = () => {
|
||||
if (!deviceFeeConfig.value || !deviceFeeConfig.value.hourPrice) return 60
|
||||
const hourPrice = parseFloat(deviceFeeConfig.value.hourPrice)
|
||||
// hourPrice 为 0.5 时表示 30 分钟,为 1 时表示 60 分钟
|
||||
return hourPrice === 0.5 ? 30 : 60
|
||||
}
|
||||
|
||||
// 计算每个计费单位的价格
|
||||
const getBillingUnitPrice = () => {
|
||||
if (!deviceFeeConfig.value || !deviceFeeConfig.value.maxHourPrice) return '5'
|
||||
const maxHourPrice = parseFloat(deviceFeeConfig.value.maxHourPrice)
|
||||
const hourPrice = parseFloat(deviceFeeConfig.value.hourPrice || 1)
|
||||
// maxHourPrice 是1小时的价格,需要根据 hourPrice 换算
|
||||
const unitPrice = maxHourPrice * hourPrice
|
||||
return unitPrice.toFixed(2)
|
||||
}
|
||||
|
||||
// 获取免费时间(分钟)
|
||||
const getFreeMinutes = () => {
|
||||
if (!positionInfo.value || !positionInfo.value.freeRentTime) return 15
|
||||
return parseInt(positionInfo.value.freeRentTime)
|
||||
}
|
||||
|
||||
// 计算24小时封顶价格
|
||||
const get24HourCapPrice = () => {
|
||||
if (!deviceFeeConfig.value || !deviceFeeConfig.value.maxHourPrice || !deviceFeeConfig.value.maxHour) return '45.00'
|
||||
const maxHourPrice = parseFloat(deviceFeeConfig.value.maxHourPrice)
|
||||
const maxHour = parseFloat(deviceFeeConfig.value.maxHour)
|
||||
return (maxHourPrice * maxHour).toFixed(2)
|
||||
}
|
||||
|
||||
// 生成计费说明文本
|
||||
const getPricingInfoText = () => {
|
||||
const unitMinutes = getBillingUnitMinutes()
|
||||
const unitPrice = getBillingUnitPrice()
|
||||
const maxHourPrice = deviceFeeConfig.value.maxHourPrice || '5'
|
||||
|
||||
if (unitMinutes === 30) {
|
||||
return `${unitPrice}元/${unitMinutes}分钟,${maxHourPrice}元/小时`
|
||||
} else {
|
||||
return `${maxHourPrice}元/小时`
|
||||
}
|
||||
}
|
||||
|
||||
// 生成详细说明文本
|
||||
const getDetailInfoText = () => {
|
||||
const freeMinutes = getFreeMinutes()
|
||||
const unitMinutes = getBillingUnitMinutes()
|
||||
const depositAmount = deviceInfo.value.depositAmount || '99'
|
||||
|
||||
return `前${freeMinutes}分钟内归还免费,不足${unitMinutes}分钟按${unitMinutes}分钟计费,封顶${depositAmount}元,持续计费至${depositAmount}元视为买断`
|
||||
}
|
||||
|
||||
// 提交租借订单
|
||||
const submitRentOrder = async (payWay) => {
|
||||
try {
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { getExpressReturnDetail } from '@/config/api/expressReturn.js'
|
||||
import { getCustomerPhone } from '@/util/index.js'
|
||||
|
||||
// 详情数据
|
||||
const detailData = ref({
|
||||
@@ -159,15 +160,16 @@ const handleCopyTracking = () => {
|
||||
|
||||
// 联系客服
|
||||
const handleContactService = () => {
|
||||
const customerPhone = getCustomerPhone()
|
||||
uni.showModal({
|
||||
title: '联系客服',
|
||||
content: '客服电话:400-123-4567\n工作时间:9:00-18:00',
|
||||
content: `客服电话:${customerPhone}\n工作时间:周一至周日 09:00-22:00`,
|
||||
confirmText: '拨打',
|
||||
cancelText: '取消',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: '400-123-4567'
|
||||
phoneNumber: customerPhone
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@
|
||||
type: paramsType.value,
|
||||
content: description.value,
|
||||
phone: contact.value,
|
||||
picturePath: images.value
|
||||
picturePath: images.value[0]
|
||||
}
|
||||
|
||||
uni.request({
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<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>
|
||||
<text class="value" @click="makePhoneCall">{{ customerPhone }}</text>
|
||||
</view>
|
||||
<view class="contact-item">
|
||||
<text class="label">{{ HELP_CONTENT.CONTACT.SERVICE_TIME.LABEL }}</text>
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
<script>
|
||||
import { HELP_CONTENT } from '@/constants/help'
|
||||
import { getCustomerPhone } from '@/util/index.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -45,16 +46,21 @@ export default {
|
||||
faqList: HELP_CONTENT.FAQ_LIST.map(item => ({
|
||||
...item,
|
||||
isOpen: false
|
||||
}))
|
||||
})),
|
||||
customerPhone: HELP_CONTENT.CONTACT.PHONE.VALUE // 默认客服电话
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// 从缓存读取客服电话
|
||||
this.customerPhone = getCustomerPhone()
|
||||
},
|
||||
methods: {
|
||||
toggleFaq(index) {
|
||||
this.faqList[index].isOpen = !this.faqList[index].isOpen
|
||||
},
|
||||
makePhoneCall() {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: HELP_CONTENT.CONTACT.PHONE.VALUE
|
||||
phoneNumber: this.customerPhone
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+205
-62
@@ -1,19 +1,36 @@
|
||||
<template>
|
||||
<view class="container fullscreen">
|
||||
<view class="" style="font-size: 32rpx;font-weight: 600;margin: 15rpx 20rpx;">风电者共享风扇&暖手充电宝</view>
|
||||
<view class="map-notice" v-if="noticeText">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||||
<view class="navbar-content" :style="{ height: navBarHeight + 'px' }">
|
||||
<text class="navbar-title">风电者共享风扇&暖手充电宝</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="map-notice" v-if="noticeText" @click="openNoticePopup">
|
||||
<uv-notice-bar :text="noticeText" :speed="50" :show-icon="true" color="#07c160" bg-color="#E8F8EF"
|
||||
icon="volume"></uv-notice-bar>
|
||||
</view>
|
||||
|
||||
<!-- 全屏地图组件 -->
|
||||
<MapComponent v-if="!isLoading && userLocation" ref="mapRef" :userLocation="userLocation"
|
||||
:positionList="positionList" :filteredPositions="filteredPositions" :searchKeyword="searchKeyword"
|
||||
:enableMarkers="true"
|
||||
@relocate="handleRelocate" @scan="handleScan" @showList="showLocationList" @markerTap="selectPosition"
|
||||
@mapCenterChange="onMapCenterChange" />
|
||||
<!-- 内容区域 -->
|
||||
<view class="main-content" :style="{ paddingTop: (statusBarHeight) + 'px' }">
|
||||
<!-- 全屏地图组件 -->
|
||||
<MapComponent v-if="!isLoading && userLocation" ref="mapRef" :userLocation="userLocation"
|
||||
:positionList="positionList" :filteredPositions="filteredPositions" :searchKeyword="searchKeyword"
|
||||
:enableMarkers="true"
|
||||
@relocate="handleRelocate" @scan="handleScan" @showList="showLocationList" @markerTap="selectPosition"
|
||||
@mapCenterChange="onMapCenterChange" />
|
||||
|
||||
<!-- 地图加载状态 -->
|
||||
<view v-if="isLoading || !userLocation" class="map-loading-placeholder">
|
||||
<view class="loading-content">
|
||||
<view class="loading-spinner"></view>
|
||||
<text>正在获取位置信息...</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部操作栏:附近设备 / 扫码使用 / 我的 -->
|
||||
<!-- 底部操作栏:附近设备 / 扫码使用 / 我的 -->
|
||||
<view class="bottom-actions">
|
||||
<!-- <view class="action-btn secondary small btn-nearby" @click="showLocationList">
|
||||
<view class="icon-wrap">
|
||||
@@ -44,16 +61,6 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 地图加载状态 -->
|
||||
<view v-if="isLoading || !userLocation" class="map-loading-placeholder">
|
||||
<view class="loading-content">
|
||||
<view class="loading-spinner"></view>
|
||||
<text>正在获取位置信息...</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<!-- 场地列表弹窗组件 -->
|
||||
<LocationListSheet
|
||||
:show="showLocationPopup"
|
||||
@@ -95,33 +102,50 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 使用指南:居中弹出(ref 控制 open/close) -->
|
||||
<uv-popup ref="guidePopup" mode="center" round="24" :overlay="true" :closeOnClickOverlay="false" :safeAreaInsetBottom="false">
|
||||
<view class="guide-popup">
|
||||
<view class="guide-header">
|
||||
<text class="guide-title">使用指南</text>
|
||||
<!-- <view class="guide-close" @click="closeGuidePopup">
|
||||
<uv-icon name="close" size="20"></uv-icon>
|
||||
</view> -->
|
||||
</view>
|
||||
<view class="guide-content">
|
||||
<view class="guide-step" v-for="(step, idx) in guideSteps" :key="idx">
|
||||
<view class="step-index">{{ idx + 1 }}</view>
|
||||
<view class="step-info">
|
||||
<view class="step-title">{{ step.title }}</view>
|
||||
<view class="step-desc">{{ step.desc }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="guide-actions">
|
||||
<!-- <view class="primary-btn" @click="closeGuidePopup"></view> -->
|
||||
<view class="primary-btn" @click="closeGuidePopup">
|
||||
<uv-icon name="close" size="20"></uv-icon>
|
||||
<!-- 使用指南:居中弹出(ref 控制 open/close) -->
|
||||
<uv-popup ref="guidePopup" mode="center" round="24" :overlay="true" :closeOnClickOverlay="false" :safeAreaInsetBottom="false">
|
||||
<view class="guide-popup">
|
||||
<view class="guide-header">
|
||||
<text class="guide-title">使用指南</text>
|
||||
<!-- <view class="guide-close" @click="closeGuidePopup">
|
||||
<uv-icon name="close" size="20"></uv-icon>
|
||||
</view> -->
|
||||
</view>
|
||||
<view class="guide-content">
|
||||
<view class="guide-step" v-for="(step, idx) in guideSteps" :key="idx">
|
||||
<view class="step-index">{{ idx + 1 }}</view>
|
||||
<view class="step-info">
|
||||
<view class="step-title">{{ step.title }}</view>
|
||||
<view class="step-desc">{{ step.desc }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uv-popup>
|
||||
</view>
|
||||
<view class="guide-actions">
|
||||
<!-- <view class="primary-btn" @click="closeGuidePopup"></view> -->
|
||||
<view class="primary-btn" @click="closeGuidePopup">
|
||||
<uv-icon name="close" size="20"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uv-popup>
|
||||
|
||||
<!-- 通知详情弹窗:居中弹出 -->
|
||||
<uv-popup ref="noticePopup" mode="center" round="24" :overlay="true" :closeOnClickOverlay="true" :safeAreaInsetBottom="false">
|
||||
<view class="notice-popup">
|
||||
<view class="notice-header">
|
||||
<text class="notice-title">通知公告</text>
|
||||
</view>
|
||||
<view class="notice-content">
|
||||
<text class="notice-text">{{ noticeText }}</text>
|
||||
</view>
|
||||
<view class="notice-actions">
|
||||
<view class="primary-btn" @click="closeNoticePopup">
|
||||
<uv-icon name="close" size="20"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uv-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -177,6 +201,10 @@
|
||||
const isLocationInitialized = ref(false)
|
||||
const showLocationPopup = ref(false)
|
||||
const isRelocating = ref(false) // 防抖标志:是否正在重新定位
|
||||
|
||||
// 导航栏高度相关
|
||||
const statusBarHeight = ref(0)
|
||||
const navBarHeight = ref(44) // 默认导航栏内容高度
|
||||
|
||||
// 使用指南步骤
|
||||
const guideSteps = ref([
|
||||
@@ -231,9 +259,10 @@
|
||||
}
|
||||
|
||||
|
||||
// 组件引用
|
||||
const mapRef = ref(null)
|
||||
const guidePopup = ref(null)
|
||||
// 组件引用
|
||||
const mapRef = ref(null)
|
||||
const guidePopup = ref(null)
|
||||
const noticePopup = ref(null)
|
||||
|
||||
// 计算属性
|
||||
const searchPlaceholder = computed(() => {
|
||||
@@ -243,8 +272,36 @@
|
||||
return '搜索附近场地'
|
||||
})
|
||||
|
||||
// 计算导航栏高度
|
||||
const initNavBarHeight = () => {
|
||||
try {
|
||||
const systemInfo = uni.getSystemInfoSync()
|
||||
statusBarHeight.value = systemInfo.statusBarHeight || 0
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 获取胶囊按钮位置信息
|
||||
const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
|
||||
// 计算导航栏内容高度:(胶囊底部坐标 - 状态栏高度) 确保与胶囊对齐
|
||||
navBarHeight.value = (menuButtonInfo.top - systemInfo.statusBarHeight) * 2 + menuButtonInfo.height
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
// 非微信小程序使用默认高度
|
||||
navBarHeight.value = 44
|
||||
// #endif
|
||||
|
||||
console.log('状态栏高度:', statusBarHeight.value)
|
||||
console.log('导航栏内容高度:', navBarHeight.value)
|
||||
} catch (error) {
|
||||
console.error('获取导航栏高度失败:', error)
|
||||
statusBarHeight.value = 20
|
||||
navBarHeight.value = 44
|
||||
}
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
initNavBarHeight()
|
||||
init()
|
||||
})
|
||||
|
||||
@@ -741,18 +798,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 使用指南弹窗控制
|
||||
const openPopup = () => {
|
||||
try {
|
||||
guidePopup.value && typeof guidePopup.value.open === 'function' && guidePopup.value.open()
|
||||
} catch (e) {}
|
||||
}
|
||||
// 使用指南弹窗控制
|
||||
const openPopup = () => {
|
||||
try {
|
||||
guidePopup.value && typeof guidePopup.value.open === 'function' && guidePopup.value.open()
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
const closeGuidePopup = () => {
|
||||
try {
|
||||
guidePopup.value && typeof guidePopup.value.close === 'function' && guidePopup.value.close()
|
||||
} catch (e) {}
|
||||
}
|
||||
const closeGuidePopup = () => {
|
||||
try {
|
||||
guidePopup.value && typeof guidePopup.value.close === 'function' && guidePopup.value.close()
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 通知弹窗控制
|
||||
const openNoticePopup = () => {
|
||||
try {
|
||||
noticePopup.value && typeof noticePopup.value.open === 'function' && noticePopup.value.open()
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
const closeNoticePopup = () => {
|
||||
try {
|
||||
noticePopup.value && typeof noticePopup.value.close === 'function' && noticePopup.value.close()
|
||||
} catch (e) {}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
@@ -790,6 +860,37 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 自定义导航栏 */
|
||||
.custom-navbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #ffffff;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.navbar-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.navbar-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 主内容区域 */
|
||||
.main-content {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 顶部Logo和通知栏 */
|
||||
.header-section {
|
||||
width: 92%;
|
||||
@@ -1271,7 +1372,7 @@
|
||||
|
||||
/* 地图加载状态 */
|
||||
.map-loading-placeholder {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
@@ -1403,10 +1504,7 @@
|
||||
|
||||
.map-notice {
|
||||
margin: 0 20rpx;
|
||||
// position: absolute;
|
||||
// left: 20rpx;
|
||||
// right: 20rpx;
|
||||
// top: 20rpx;
|
||||
margin-top: 10rpx;
|
||||
border-radius: 20rpx;
|
||||
z-index: 15;
|
||||
}
|
||||
@@ -1517,4 +1615,49 @@
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 通知详情弹窗样式 */
|
||||
.notice-popup {
|
||||
width: 640rpx;
|
||||
max-width: 86vw;
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
padding: 24rpx 24rpx 16rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.notice-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.notice-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.notice-content {
|
||||
max-height: 600rpx;
|
||||
overflow-y: auto;
|
||||
padding: 16rpx 12rpx;
|
||||
box-sizing: border-box;
|
||||
background: #F8F9FA;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.notice-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
line-height: 1.8;
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.notice-actions {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user