diff --git a/components/MapComponent.vue b/components/MapComponent.vue
index 270ae6c..585acf3 100644
--- a/components/MapComponent.vue
+++ b/components/MapComponent.vue
@@ -17,18 +17,19 @@
+
+
+
+
-
+
-
-
-
-
+
@@ -530,7 +531,7 @@ const handleSearch = () => {
flex-direction: row;
align-items: center;
justify-content: center;
- box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.12);
+ // box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.12);
padding: 20rpx;
border: 2rpx solid #e0e0e0;
diff --git a/components/OrderItemCard.vue b/components/OrderItemCard.vue
index dee3cfc..8aedfcf 100644
--- a/components/OrderItemCard.vue
+++ b/components/OrderItemCard.vue
@@ -16,6 +16,9 @@
{{ $t('order.depositFree') }}
+
+ {{ $t('order.whitelistOrder') }}
+
{{ $t('order.memberOrder') }}
@@ -59,10 +62,22 @@
-
-
- ¥
- {{ deviceFeeConfig.maxHourPrice || '5.00' }}
- /{{ $t('time.hour') }}
-
-
- {{ deviceInfo.depositAmount || '99' }}{{ $t('device.capLimit') }}
-
+
+
+ ¥
+ {{ deviceFeeConfig.maxHourPrice || '5.00' }}
+ /{{ getPriceUnit() }}
+
+ {{ deviceInfo.depositAmount || '99' }}{{ $t('device.capLimit') }}
+
+
@@ -111,8 +111,7 @@
onMounted
} from 'vue'
import {
- onLoad,
- onShow
+ onLoad
} from '@dcloudio/uni-app'
import {
getDeviceInfo,
@@ -120,14 +119,9 @@
} from '@/config/api/device.js'
import {
getOrderByOrderNoScore,
- getOrderByOrderNoScorePayStatus,
getOrderByOrderNo,
- updateOrderPackage,
cancelOrder
} from '@/config/api/order.js'
- import {
- URL
- } from "@/config/url.js"
import {
initiateWeChatScorePayment,
getUserInfo,
@@ -147,7 +141,6 @@
const deviceFeeConfig = ref({})
const positionInfo = ref({})
const deviceLocation = ref('一号教学楼大厅')
- const batteryLevel = ref(95)
const hasActiveOrder = ref(false)
const deviceStatus = reactive({
text: $t('device.available'),
@@ -164,7 +157,6 @@
uni.setStorageSync('deviceId', options.deviceNo)
} else {
deviceId.value = uni.getStorageSync('deviceId')
- // uni.removeStorageSync('deviceId')
}
await checkOrderStatus()
await fetchDeviceInfo()
@@ -178,10 +170,6 @@
await fetchDeviceInfo()
})
- // onShow(async () => {
- // await fetchDeviceInfo()
- // })
-
const checkUserPhone = async () => {
try {
const userInfoRes = await getUserInfo()
@@ -318,15 +306,14 @@
}
}
- if (deviceInfo.value.feeConfig) {
- deviceFeeConfig.value = JSON.parse(deviceInfo.value.feeConfig)[0] || {}
- console.log('deviceFeeConfig', deviceFeeConfig.value);
- } else {
- deviceFeeConfig.value = {
- maxHourPrice: '5.00',
- }
- discount.value = '99.00'
+ if (deviceInfo.value.feeConfig) {
+ deviceFeeConfig.value = JSON.parse(deviceInfo.value.feeConfig)[0] || {}
+ console.log('deviceFeeConfig', deviceFeeConfig.value);
+ } else {
+ deviceFeeConfig.value = {
+ maxHourPrice: '5.00',
}
+ }
}
@@ -395,14 +382,23 @@
submitRentOrder(payWay)
}
- const selectedPkg = reactive({
- time: '1小时',
- price: '5'
- })
- const depositAmount = ref('99.00')
+ // 获取价格单位文本
+ const getPriceUnit = () => {
+ // 按分钟计费
+ if (deviceInfo.value && deviceInfo.value.feeType === 'minute') {
+ return '分钟'
+ }
+ // 按小时计费(默认)
+ return $t('time.hour')
+ }
// 计算计费单位时间(分钟)
const getBillingUnitMinutes = () => {
+ // 按分钟计费时,单位为1分钟
+ if (deviceInfo.value && deviceInfo.value.feeType === 'minute') {
+ return 1
+ }
+ // 按小时计费
if (!deviceFeeConfig.value || !deviceFeeConfig.value.hourPrice) return 60
const hourPrice = parseFloat(deviceFeeConfig.value.hourPrice)
// hourPrice 为 0.5 时表示 30 分钟,为 1 时表示 60 分钟
@@ -413,8 +409,14 @@
const getBillingUnitPrice = () => {
if (!deviceFeeConfig.value || !deviceFeeConfig.value.maxHourPrice) return '5'
const maxHourPrice = parseFloat(deviceFeeConfig.value.maxHourPrice)
+
+ // 按分钟计费时,直接返回每分钟价格
+ if (deviceInfo.value && deviceInfo.value.feeType === 'minute') {
+ return maxHourPrice.toFixed(2)
+ }
+
+ // 按小时计费
const hourPrice = parseFloat(deviceFeeConfig.value.hourPrice || 1)
- // maxHourPrice 是1小时的价格,需要根据 hourPrice 换算
const unitPrice = maxHourPrice * hourPrice
return unitPrice.toFixed(2)
}
@@ -425,21 +427,18 @@
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 (deviceInfo.value && deviceInfo.value.feeType === 'minute') {
+ return `${unitPrice}元/分钟`
+ }
+
+ // 按小时计费
+ const unitMinutes = getBillingUnitMinutes()
if (unitMinutes === 30) {
return `${unitPrice}元/${unitMinutes}分钟,${maxHourPrice}元/小时`
} else {
@@ -453,6 +452,12 @@
const unitMinutes = getBillingUnitMinutes()
const depositAmount = deviceInfo.value.depositAmount || '99'
+ // 按分钟计费
+ if (deviceInfo.value && deviceInfo.value.feeType === 'minute') {
+ return `前${freeMinutes}分钟内归还免费,不足${unitMinutes}分钟按${unitMinutes}分钟计费,封顶${depositAmount}元,持续计费至${depositAmount}元视为买断`
+ }
+
+ // 按小时计费
return `前${freeMinutes}分钟内归还免费,不足${unitMinutes}分钟按${unitMinutes}分钟计费,封顶${depositAmount}元,持续计费至${depositAmount}元视为买断`
}
@@ -496,54 +501,23 @@
throw new Error(rentResult.msg || $t('device.rentFailed'))
}
- // 获取后端返回的订单信息
- const order = rentResult.data
- console.log('订单信息', order);
+ // 获取后端返回的订单信息
+ const order = rentResult.data
+ console.log('订单信息', order);
- // // --- 统一:先更新订单套餐信息 ---
- // try {
- // let packageTimeMinutes = 0;
- // if (selectedPkg.time.includes('小时')) {
- // packageTimeMinutes = parseInt(selectedPkg.time) * 60;
- // } else if (selectedPkg.time.includes('分钟')) {
- // packageTimeMinutes = parseInt(selectedPkg.time);
- // } else {
- // packageTimeMinutes = parseInt(selectedPkg.time) * 60; // 默认按小时处理
- // }
-
- // const updateRes = await updateOrderPackage({
- // orderId: order.orderId,
- // packageTime: packageTimeMinutes,
- // packagePrice: parseFloat(selectedPkg.price)
- // });
- // if (updateRes.code !== 200) {
- // console.warn("更新订单套餐信息失败:", updateRes.msg);
- // // 这里可以选择是否提示用户或阻止流程,当前不阻止
- // } else {
- // console.log("订单套餐信息已提前更新");
- // }
- // } catch (updateError) {
- // console.error("更新订单套餐信息时出错:", updateError);
- // // 即使更新失败,也继续流程
- // }
- // --- 套餐信息更新结束 ---
-
- if (payWay == 'wx-pay') {
- //当支付方式为押金支付时
+ if (payWay == 'wx-pay') {
+ // 当支付方式为押金支付时
uni.hideLoading()
const res = await getOrderByOrderNo(order.orderNo);
console.log(res);
- // --- 新增:计算总金额 ---
+
const deposit = parseFloat(order.depositAmount);
const packagePrice = parseFloat(order.unitPrice);
const totalAmount = deposit.toFixed(2);
- // --- 计算结束 ---
- uni.hideLoading()
-
- // 跳转到订单支付页面,传递订单ID、套餐信息和总金额
+ // 跳转到订单支付页面
uni.redirectTo({
- url: `/pages/order/payment?orderId=${order.orderId}&packageTimeHours=${selectedPkg.time.replace('小时', '')}&packagePrice=${packagePrice}&totalAmount=${totalAmount}&depositAmount=${depositAmount.value}${deviceInfo.value && deviceInfo.value.feeConfig ? '&feeConfig=' + encodeURIComponent(deviceInfo.value.feeConfig) : ''}`
+ url: `/pages/order/payment?orderId=${order.orderId}&packagePrice=${packagePrice}&totalAmount=${totalAmount}&depositAmount=${deposit}${deviceInfo.value && deviceInfo.value.feeConfig ? '&feeConfig=' + encodeURIComponent(deviceInfo.value.feeConfig) : ''}`
})
} else if (payWay == 'wx-score-pay') {
@@ -915,15 +889,10 @@
margin-right: 8rpx;
}
- .credit-text {
- font-size: 24rpx;
- color: #999;
-
- .divider {
- margin: 0 8rpx;
- color: #ddd;
- }
- }
+ .credit-text {
+ font-size: 24rpx;
+ color: #999;
+ }
}
}
diff --git a/pages/help/index.vue b/pages/help/index.vue
index 9ec0fd1..8bd8bbf 100644
--- a/pages/help/index.vue
+++ b/pages/help/index.vue
@@ -1,21 +1,19 @@
-
-
-
-
- {{ $t(item.answer) }}
-
-
+
+
+
+
+ {{ $t(item.answer) }}
+
+
+
@@ -43,10 +41,7 @@ export default {
data() {
return {
HELP_CONTENT,
- faqList: HELP_CONTENT.FAQ_LIST.map(item => ({
- ...item,
- isOpen: false
- })),
+ faqList: HELP_CONTENT.FAQ_LIST,
customerPhone: HELP_CONTENT.CONTACT.PHONE.VALUE // 默认客服电话
}
},
@@ -59,9 +54,6 @@ export default {
this.customerPhone = getCustomerPhone()
},
methods: {
- toggleFaq(index) {
- this.faqList[index].isOpen = !this.faqList[index].isOpen
- },
makePhoneCall() {
uni.makePhoneCall({
phoneNumber: this.customerPhone
@@ -77,55 +69,22 @@ export default {
background: #f8f8f8;
padding: 30rpx;
- .faq-list {
+ .faq-section {
background: #fff;
border-radius: 20rpx;
- padding: 20rpx;
margin-bottom: 30rpx;
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.04);
+ overflow: hidden;
- .faq-item {
- border-bottom: 1rpx solid #f5f5f5;
+ .answer-content {
+ padding: 20rpx 30rpx 30rpx;
+ background: #f9f9f9;
- &: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 {
+ .answer-text {
font-size: 28rpx;
color: #666;
- line-height: 1.6;
- padding: 0 20rpx 30rpx;
- background: #f9f9f9;
- border-radius: 10rpx;
- margin: 0 20rpx 20rpx;
+ line-height: 1.8;
+ display: block;
}
}
}
@@ -145,7 +104,7 @@ export default {
font-weight: 500;
margin-bottom: 20rpx;
padding-bottom: 8rpx;
- width:fit-content;
+ width: fit-content;
&::after {
z-index: -1;
@@ -156,8 +115,7 @@ export default {
width: 88%;
height: 16rpx;
border-radius: 20rpx;
- // background: transparent;
- background: #07C160; // 底部高亮(微信绿)
+ background: #07C160;
}
}
diff --git a/pages/index/index.vue b/pages/index/index.vue
index e4cb78d..0a07dc1 100644
--- a/pages/index/index.vue
+++ b/pages/index/index.vue
@@ -22,7 +22,7 @@
@@ -150,6 +150,24 @@
+
+
+
+
+
@@ -176,7 +194,8 @@
getPotionsDetail
} from '../../config/api/order.js'
import {
- getNoticeTextData
+ getNoticeTextData,
+ getActiveActivity
} from '../../config/api/system.js'
// 导入地图工具函数
import {
@@ -214,6 +233,8 @@ const showLocationPopup = ref(false)
const isRelocating = ref(false) // 防抖标志:是否正在重新定位
const showGuidePopup = ref(false) // 使用指南弹窗显示状态
const showNoticePopup = ref(false) // 通知详情弹窗显示状态
+const showActivityPopup = ref(false) // 活动弹窗显示状态
+const activityData = ref(null) // 活动数据
// 导航栏高度相关
const statusBarHeight = ref(0)
@@ -267,6 +288,31 @@ const statusBarHeight = ref(0)
console.warn('缓存通知内容失败:', e);
}
}
+
+ // 查询最近的活动
+ const checkActiveActivity = async () => {
+ try {
+ // 检查是否已经显示过活动弹窗(本次会话)
+ const hasShownActivity = uni.getStorageSync('hasShownActivityInSession');
+ if (hasShownActivity) {
+ console.log('本次会话已显示过活动弹窗,跳过');
+ return;
+ }
+
+ const res = await getActiveActivity();
+ if (res.code === 200 && res.data) {
+ activityData.value = res.data;
+ // 延迟一下显示,避免与其他弹窗冲突
+ setTimeout(() => {
+ openActivityPopup();
+ // 标记本次会话已显示过活动弹窗
+ uni.setStorageSync('hasShownActivityInSession', true);
+ }, 500);
+ }
+ } catch (e) {
+ console.warn('查询活动失败:', e);
+ }
+ }
// 距离格式化函数
const formatDistance = (distanceInMeters) => {
@@ -282,6 +328,7 @@ const statusBarHeight = ref(0)
const mapRef = ref(null)
const guidePopup = ref(null)
const noticePopup = ref(null)
+const activityPopup = ref(null)
// 计算属性
const searchPlaceholder = computed(() => {
@@ -344,8 +391,8 @@ const noticePopup = ref(null)
// 2. 加载场地列表
await loadPositions()
- // 3. 检查是否需要显示使用指南(可以根据用户行为记录来决定)
- // 这里暂时默认显示,后续可以根据用户使用情况优化
+ // 3. 查询活动并显示弹窗
+ await checkActiveActivity()
} catch (error) {
console.error('初始化失败:', error)
@@ -843,6 +890,21 @@ const closeNoticePopup = () => {
noticePopup.value && typeof noticePopup.value.close === 'function' && noticePopup.value.close()
} catch (e) {}
}
+
+// 活动弹窗控制
+const openActivityPopup = () => {
+ try {
+ showActivityPopup.value = true
+ activityPopup.value && typeof activityPopup.value.open === 'function' && activityPopup.value.open()
+ } catch (e) {}
+}
+
+const closeActivityPopup = () => {
+ try {
+ showActivityPopup.value = false
+ activityPopup.value && typeof activityPopup.value.close === 'function' && activityPopup.value.close()
+ } catch (e) {}
+}