style:调整样式

This commit is contained in:
2025-10-28 18:32:23 +08:00
parent 449c63ecc4
commit 985d739324
9 changed files with 345 additions and 74 deletions
+9
View File
@@ -18,3 +18,12 @@ export const getNoticeTextData = (data) => {
}) })
} }
// 根据品牌名称获取客服信息
export const getCommonByBrand = (brandName) => {
return request({
url: `/device/common/by/${brandName}`,
method: 'get',
hideLoading: true
})
}
+2 -2
View File
@@ -1,6 +1,6 @@
export const URL = "https://my.gxfs123.com/api" //正式服务器 // export const URL = "https://my.gxfs123.com/api" //正式服务器
// export const URL = "https://fansdev.gxfs123.com/api" //测试服务器 // export const URL = "https://fansdev.gxfs123.com/api" //测试服务器
// export const URL = "http://192.168.5.37:8080" //本地调试 export const URL = "http://192.168.5.120:8080" //本地调试
// export const URL = "http://127.0.0.1:8080" //本地调试 // export const URL = "http://127.0.0.1:8080" //本地调试
export const appid = "wx2165f0be356ae7a9" //小程序appid export const appid = "wx2165f0be356ae7a9" //小程序appid
+1 -1
View File
@@ -11,7 +11,7 @@
"style": { "style": {
"navigationBarTitleText": "", "navigationBarTitleText": "",
"navigationBarBackgroundColor": "#ffffff", "navigationBarBackgroundColor": "#ffffff",
"navigationStyle": "default", "navigationStyle": "custom",
"enableShareAppMessage": true, "enableShareAppMessage": true,
"enableShareTimeline": true "enableShareTimeline": true
} }
+63 -3
View File
@@ -38,13 +38,13 @@
<view class="info-icon"> <view class="info-icon">
<text class="icon-text"></text> <text class="icon-text"></text>
</view> </view>
<text class="info-text">5/小时45/24小时</text> <text class="info-text">{{ getPricingInfoText() }}</text>
</view> </view>
<view class="pricing-info"> <view class="pricing-info">
<view class="info-icon"> <view class="info-icon">
<text class="icon-text"></text> <text class="icon-text"></text>
</view> </view>
<text class="info-text">前15分钟内归还免费不足60分钟按60分钟计费点总封顶99元持续计费至99元视为买断</text> <text class="info-text">{{ getDetailInfoText() }}</text>
</view> </view>
</view> </view>
@@ -138,6 +138,7 @@
const deviceInfo = ref({}) const deviceInfo = ref({})
const deviceId = ref('') const deviceId = ref('')
const deviceFeeConfig = ref({}) const deviceFeeConfig = ref({})
const positionInfo = ref({})
const deviceLocation = ref('一号教学楼大厅') const deviceLocation = ref('一号教学楼大厅')
const batteryLevel = ref(95) const batteryLevel = ref(95)
const hasActiveOrder = ref(false) const hasActiveOrder = ref(false)
@@ -283,6 +284,11 @@
if (res.code == 200) { if (res.code == 200) {
deviceInfo.value = res.data.device || {} deviceInfo.value = res.data.device || {}
// 保存 position 信息
if (res.data.position) {
positionInfo.value = res.data.position
}
// 更新设备位置信息 // 更新设备位置信息
if (deviceInfo.value.deviceLocation) { if (deviceInfo.value.deviceLocation) {
deviceLocation.value = deviceInfo.value.deviceLocation deviceLocation.value = deviceInfo.value.deviceLocation
@@ -377,10 +383,64 @@
const selectedPkg = reactive({ const selectedPkg = reactive({
time: '1小时', time: '1小时',
price: '5.00' price: '5'
}) })
const depositAmount = ref('99.00') 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) => { const submitRentOrder = async (payWay) => {
try { try {
+4 -2
View File
@@ -88,6 +88,7 @@
<script setup> <script setup>
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import { getExpressReturnDetail } from '@/config/api/expressReturn.js' import { getExpressReturnDetail } from '@/config/api/expressReturn.js'
import { getCustomerPhone } from '@/util/index.js'
// 详情数据 // 详情数据
const detailData = ref({ const detailData = ref({
@@ -159,15 +160,16 @@ const handleCopyTracking = () => {
// 联系客服 // 联系客服
const handleContactService = () => { const handleContactService = () => {
const customerPhone = getCustomerPhone()
uni.showModal({ uni.showModal({
title: '联系客服', title: '联系客服',
content: '客服电话:400-123-4567\n工作时间:9:00-18:00', content: `客服电话:${customerPhone}\n工作时间:周一至周日 09:00-22:00`,
confirmText: '拨打', confirmText: '拨打',
cancelText: '取消', cancelText: '取消',
success: (res) => { success: (res) => {
if (res.confirm) { if (res.confirm) {
uni.makePhoneCall({ uni.makePhoneCall({
phoneNumber: '400-123-4567' phoneNumber: customerPhone
}) })
} }
} }
+1 -1
View File
@@ -146,7 +146,7 @@
type: paramsType.value, type: paramsType.value,
content: description.value, content: description.value,
phone: contact.value, phone: contact.value,
picturePath: images.value picturePath: images.value[0]
} }
uni.request({ uni.request({
+9 -3
View File
@@ -24,7 +24,7 @@
<view class="contact-content"> <view class="contact-content">
<view class="contact-item"> <view class="contact-item">
<text class="label">{{ HELP_CONTENT.CONTACT.PHONE.LABEL }}</text> <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>
<view class="contact-item"> <view class="contact-item">
<text class="label">{{ HELP_CONTENT.CONTACT.SERVICE_TIME.LABEL }}</text> <text class="label">{{ HELP_CONTENT.CONTACT.SERVICE_TIME.LABEL }}</text>
@@ -37,6 +37,7 @@
<script> <script>
import { HELP_CONTENT } from '@/constants/help' import { HELP_CONTENT } from '@/constants/help'
import { getCustomerPhone } from '@/util/index.js'
export default { export default {
data() { data() {
@@ -45,16 +46,21 @@ export default {
faqList: HELP_CONTENT.FAQ_LIST.map(item => ({ faqList: HELP_CONTENT.FAQ_LIST.map(item => ({
...item, ...item,
isOpen: false isOpen: false
})) })),
customerPhone: HELP_CONTENT.CONTACT.PHONE.VALUE // 默认客服电话
} }
}, },
onLoad() {
// 从缓存读取客服电话
this.customerPhone = getCustomerPhone()
},
methods: { methods: {
toggleFaq(index) { toggleFaq(index) {
this.faqList[index].isOpen = !this.faqList[index].isOpen this.faqList[index].isOpen = !this.faqList[index].isOpen
}, },
makePhoneCall() { makePhoneCall() {
uni.makePhoneCall({ uni.makePhoneCall({
phoneNumber: HELP_CONTENT.CONTACT.PHONE.VALUE phoneNumber: this.customerPhone
}) })
} }
} }
+160 -17
View File
@@ -1,11 +1,19 @@
<template> <template>
<view class="container fullscreen"> <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" <uv-notice-bar :text="noticeText" :speed="50" :show-icon="true" color="#07c160" bg-color="#E8F8EF"
icon="volume"></uv-notice-bar> icon="volume"></uv-notice-bar>
</view> </view>
<!-- 内容区域 -->
<view class="main-content" :style="{ paddingTop: (statusBarHeight) + 'px' }">
<!-- 全屏地图组件 --> <!-- 全屏地图组件 -->
<MapComponent v-if="!isLoading && userLocation" ref="mapRef" :userLocation="userLocation" <MapComponent v-if="!isLoading && userLocation" ref="mapRef" :userLocation="userLocation"
:positionList="positionList" :filteredPositions="filteredPositions" :searchKeyword="searchKeyword" :positionList="positionList" :filteredPositions="filteredPositions" :searchKeyword="searchKeyword"
@@ -13,6 +21,15 @@
@relocate="handleRelocate" @scan="handleScan" @showList="showLocationList" @markerTap="selectPosition" @relocate="handleRelocate" @scan="handleScan" @showList="showLocationList" @markerTap="selectPosition"
@mapCenterChange="onMapCenterChange" /> @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="bottom-actions">
<!-- <view class="action-btn secondary small btn-nearby" @click="showLocationList"> <!-- <view class="action-btn secondary small btn-nearby" @click="showLocationList">
@@ -44,16 +61,6 @@
</view> </view>
</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 <LocationListSheet
:show="showLocationPopup" :show="showLocationPopup"
@@ -121,6 +128,23 @@
</view> </view>
</view> </view>
</uv-popup> </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> </view>
</template> </template>
@@ -178,6 +202,10 @@
const showLocationPopup = ref(false) const showLocationPopup = ref(false)
const isRelocating = ref(false) // 防抖标志:是否正在重新定位 const isRelocating = ref(false) // 防抖标志:是否正在重新定位
// 导航栏高度相关
const statusBarHeight = ref(0)
const navBarHeight = ref(44) // 默认导航栏内容高度
// 使用指南步骤 // 使用指南步骤
const guideSteps = ref([ const guideSteps = ref([
{ title: '扫码使用', desc: '找到附近设备,扫描设备上的二维码' }, { title: '扫码使用', desc: '找到附近设备,扫描设备上的二维码' },
@@ -234,6 +262,7 @@
// 组件引用 // 组件引用
const mapRef = ref(null) const mapRef = ref(null)
const guidePopup = ref(null) const guidePopup = ref(null)
const noticePopup = ref(null)
// 计算属性 // 计算属性
const searchPlaceholder = computed(() => { const searchPlaceholder = computed(() => {
@@ -243,8 +272,36 @@
return '搜索附近场地' 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(() => { onMounted(() => {
initNavBarHeight()
init() init()
}) })
@@ -753,6 +810,19 @@
guidePopup.value && typeof guidePopup.value.close === 'function' && guidePopup.value.close() guidePopup.value && typeof guidePopup.value.close === 'function' && guidePopup.value.close()
} catch (e) {} } 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>
<script> <script>
@@ -790,6 +860,37 @@
padding: 0; 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和通知栏 */ /* 顶部Logo和通知栏 */
.header-section { .header-section {
width: 92%; width: 92%;
@@ -1271,7 +1372,7 @@
/* 地图加载状态 */ /* 地图加载状态 */
.map-loading-placeholder { .map-loading-placeholder {
position: absolute; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
@@ -1403,10 +1504,7 @@
.map-notice { .map-notice {
margin: 0 20rpx; margin: 0 20rpx;
// position: absolute; margin-top: 10rpx;
// left: 20rpx;
// right: 20rpx;
// top: 20rpx;
border-radius: 20rpx; border-radius: 20rpx;
z-index: 15; z-index: 15;
} }
@@ -1517,4 +1615,49 @@
font-size: 32rpx; font-size: 32rpx;
font-weight: 600; 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> </style>
+51
View File
@@ -6,6 +6,8 @@ import {
URL, URL,
appid appid
} from "@/config/url.js" } from "@/config/url.js"
import { getCommonByBrand } from "@/config/api/system"
import { HELP_CONTENT } from "@/constants/help"
// import { GET_PHONE_NUMBER_URL } from "../config/url" // import { GET_PHONE_NUMBER_URL } from "../config/url"
// 微信登录方法 // 微信登录方法
@@ -30,6 +32,11 @@ export const wxLogin = () => {
uni.setStorageSync('token', result.data.LoginWxVo.access_token) uni.setStorageSync('token', result.data.LoginWxVo.access_token)
uni.setStorageSync('client_id', result.data.LoginWxVo.client_id) uni.setStorageSync('client_id', result.data.LoginWxVo.client_id)
// 4. 登录成功后获取并缓存客服电话
fetchAndCacheCustomerPhone().catch(err => {
console.error('获取客服电话失败,但不影响登录', err)
})
resolve(result.data) resolve(result.data)
} else { } else {
throw new Error(result.message || '登录失败') throw new Error(result.message || '登录失败')
@@ -174,3 +181,47 @@ export const getQueryString = function(url, name) {
} }
return null; return null;
} }
// 获取并缓存客服电话
export const fetchAndCacheCustomerPhone = async () => {
try {
// 获取当前语言
const locale = uni.getLocale ? uni.getLocale() : uni.getSystemInfoSync().language
const isEnglish = locale && (locale.toLowerCase().startsWith('en') || locale.toLowerCase().includes('en'))
// 根据语言设置品牌名称
const brandName = isEnglish ? 'fdzpower' : '风电者'
console.log('获取客服电话,当前语言:', locale, '品牌名称:', brandName)
// 调用接口获取客服电话
const res = await getCommonByBrand(brandName)
if (res.code === 200 && res.data && res.data.servicePhone) {
const phone = res.data.servicePhone
// 缓存客服电话
uni.setStorageSync('customerPhone', phone)
console.log('客服电话已缓存:', phone)
return phone
} else {
console.warn('获取客服电话失败,使用内置默认电话')
// 使用内置默认电话并缓存
const defaultPhone = HELP_CONTENT.CONTACT.PHONE.VALUE
uni.setStorageSync('customerPhone', defaultPhone)
return defaultPhone
}
} catch (error) {
console.error('获取客服电话出错,使用内置默认电话:', error)
// 使用内置默认电话并缓存
const defaultPhone = HELP_CONTENT.CONTACT.PHONE.VALUE
uni.setStorageSync('customerPhone', defaultPhone)
return defaultPhone
}
}
// 从缓存获取客服电话
export const getCustomerPhone = () => {
const phone = uni.getStorageSync('customerPhone')
// 如果没有缓存,返回内置默认值
return phone || HELP_CONTENT.CONTACT.PHONE.VALUE
}