feat:新增地图视图效果,接口待对接

This commit is contained in:
2025-08-08 14:51:45 +08:00
parent 67eb4e5516
commit c5b8026fba
49 changed files with 2811 additions and 884 deletions
+420
View File
@@ -0,0 +1,420 @@
<template>
<view class="map-container">
<map
id="mainMap"
class="map"
:key="mapKey"
:longitude="mapCenter.longitude"
:latitude="mapCenter.latitude"
:scale="mapZoom"
:markers="mapMarkers"
:show-location="false"
:enable-scroll="true"
:enable-zoom="true"
:enable-rotate="false"
:show-compass="false"
@markertap="handleMarkerTap"
@regionchange="handleRegionChange"
></map>
<!-- 地图加载状态 -->
<view class="map-loading" v-if="!mapCenter.longitude">
<view class="loading-content">
<view class="loading-spinner"></view>
<text>地图加载中...</text>
</view>
</view>
<!-- 地图上的浮动按钮 -->
<view class="map-controls">
<view class="control-btn location-control" @click="handleRelocate">
<image class="control-icon" src="@/static/scan-icon.png" mode="aspectFit" />
<text>我的位置</text>
</view>
<view class="control-btn scan-control main-btn" @click="handleScan">
<image class="control-icon" src="@/static/scan-icon.png" mode="aspectFit" />
<text>扫码使用</text>
</view>
<view class="control-btn list-control" @click="handleShowList">
<image class="control-icon" src="@/static/scan-icon.png" mode="aspectFit" />
<text>附近场地</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed, watch, nextTick, onUnmounted, onMounted, getCurrentInstance } from 'vue'
import AmapUtil from '@/utils/amap.js'
// Props
const props = defineProps({
userLocation: {
type: Object,
default: null
},
positionList: {
type: Array,
default: () => []
},
filteredPositions: {
type: Array,
default: () => []
},
searchKeyword: {
type: String,
default: ''
}
})
// Emits
const emit = defineEmits([
'relocate',
'scan',
'showList',
'markerTap',
'mapCenterChange'
])
// 响应式数据
const mapKey = ref(0)
const mapZoom = ref(16) // 地图缩放级别 (16级约等于1:500m比例)
const mapCenter = ref({
longitude: 116.397128,
latitude: 39.916527
})
const loadPositionsTimer = ref(null)
const isMapInitialized = ref(false) // 标记地图是否已初始化
// 获取组件实例
const instance = getCurrentInstance()
// 方法定义(需要在watch之前定义)
const updateMapCenter = (longitude, latitude) => {
// 检查是否真的需要更新
if (mapCenter.value.longitude === longitude && mapCenter.value.latitude === latitude) {
return
}
mapCenter.value = { longitude, latitude }
mapZoom.value = 16 // 确保缩放级别正确
// 延迟调用地图API,确保DOM已更新
nextTick(() => {
setTimeout(() => {
const mapContext = uni.createMapContext('mainMap')
if (mapContext) {
mapContext.setCenterOffset({
longitude,
latitude,
success: () => {},
fail: () => {
// 备用方案
mapContext.includePoints({
points: [{ longitude, latitude }],
padding: [0, 0, 0, 0]
})
}
})
}
}, 200)
})
}
const handleRelocate = () => {
emit('relocate')
}
const handleScan = () => {
emit('scan')
}
const handleShowList = () => {
emit('showList')
}
const handleMarkerTap = (e) => {
if (!e.detail || typeof e.detail.markerId === 'undefined') {
return
}
const markerId = e.detail.markerId
if (markerId === 9999) {
uni.showToast({
title: '这是您的位置',
icon: 'none'
})
return
}
const position = props.filteredPositions[markerId]
if (position) {
emit('markerTap', position)
}
}
const handleRegionChange = (e) => {
if (e.detail.type === 'end') {
const { center } = e.detail
if (!center || typeof center.longitude === 'undefined' || typeof center.latitude === 'undefined') {
return
}
mapCenter.value = {
longitude: center.longitude,
latitude: center.latitude
}
mapZoom.value = 16 // 确保缩放级别保持正确
// 清除之前的定时器
if (loadPositionsTimer.value) {
clearTimeout(loadPositionsTimer.value)
}
// 设置防抖定时器,500ms后执行
loadPositionsTimer.value = setTimeout(() => {
emit('mapCenterChange', mapCenter.value)
}, 500)
}
}
// 计算属性 - 地图标记
const mapMarkers = computed(() => {
const markers = []
// 添加场地标记
props.filteredPositions.forEach((item, index) => {
if (item.longitude && item.latitude) {
markers.push({
id: index,
longitude: parseFloat(item.longitude),
latitude: parseFloat(item.latitude),
title: item.name,
iconPath: '/static/scan-icon.png',
width: 30,
height: 30,
callout: {
content: item.name,
fontSize: 14,
borderRadius: 8,
bgColor: '#ffffff',
padding: 10,
display: 'BYCLICK'
}
})
}
})
// 添加用户位置标记
if (props.userLocation) {
markers.push({
id: 9999, // 特殊ID标识用户位置
longitude: props.userLocation.longitude,
latitude: props.userLocation.latitude,
title: '我的位置',
iconPath: '/static/scan-icon.png',
width: 32,
height: 32,
callout: {
content: '我的位置',
fontSize: 14,
borderRadius: 8,
bgColor: '#2196F3',
color: '#ffffff',
padding: 10,
display: 'BYCLICK'
}
})
}
return markers
})
// 监听用户位置变化,更新地图中心
watch(() => props.userLocation, (newLocation) => {
if (newLocation && newLocation.longitude && newLocation.latitude && !isMapInitialized.value) {
updateMapCenter(newLocation.longitude, newLocation.latitude)
isMapInitialized.value = true
}
}, { immediate: true, deep: true })
// 组件挂载时的初始化
onMounted(() => {
// 现在组件只在有用户位置时才会渲染,所以不需要默认位置
})
// 组件卸载时清理
onUnmounted(() => {
if (loadPositionsTimer.value) {
clearTimeout(loadPositionsTimer.value)
}
})
// 暴露给父组件的方法
defineExpose({
mapCenter: computed(() => mapCenter.value)
})
</script>
<style lang="scss" scoped>
/* 地图容器 */
.map-container {
flex: 1;
position: relative;
height: 100vh;
width: 100%;
// min-height: 400rpx; /* 确保有最小高度 */
.map {
width: 100%;
height: 100%;
// min-height: 400rpx; /* 确保地图有最小高度 */
}
.map-loading {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.8);
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
.loading-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.loading-spinner {
width: 60rpx;
height: 60rpx;
border: 8rpx solid #f3f3f3;
border-top: 8rpx solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 20rpx;
}
text {
font-size: 32rpx;
color: #333;
font-weight: 500;
}
}
}
.map-controls {
position: absolute;
right: 30rpx;
bottom: 20rpx;
// margin-bottom: 30rpx;
left: 30rpx;
display: flex;
justify-content: center;
align-items: center;
gap: 30rpx;
.control-btn {
min-width: 140rpx;
height: 80rpx;
background: #ffffff;
border-radius: 40rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
transition: all 0.2s ease;
padding: 0 20rpx;
&:active {
transform: scale(0.95);
}
.control-icon {
width: 32rpx;
height: 32rpx;
margin-right: 12rpx;
}
text {
font-size: 26rpx;
color: #333;
white-space: nowrap;
font-weight: 500;
}
&.main-btn {
min-width: 160rpx;
height: 90rpx;
box-shadow: 0 6rpx 20rpx rgba(33, 150, 243, 0.4);
transform: translateY(-5rpx);
.control-icon {
width: 36rpx;
height: 36rpx;
margin-right: 16rpx;
}
text {
font-size: 28rpx;
font-weight: 600;
}
&:active {
transform: translateY(-5rpx) scale(0.95);
}
}
}
.scan-control {
background: #2196F3;
.control-icon {
filter: brightness(0) invert(1);
}
text {
color: #ffffff;
}
}
.list-control {
background: #4CAF50;
.control-icon {
filter: brightness(0) invert(1);
}
text {
color: #ffffff;
}
}
.location-control {
background: #ffffff;
border: 2rpx solid #e0e0e0;
.control-icon {
filter: none;
}
text {
color: #333;
}
}
}
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
+2 -2
View File
@@ -8,7 +8,7 @@ export const HELP_CONTENT = {
},
{
question: '收费标准是怎样的?',
answer: '使用费用为2元/小时,不足1小时按1小时计算。押金99元,归还后自动退还。'
answer: '本产品租界风扇采用免押金租借形式,无需支付押金,具体计费方式以场地机柜扫码提示为准。'
},
{
question: '如何归还风扇?',
@@ -29,7 +29,7 @@ export const HELP_CONTENT = {
TITLE: '联系客服',
PHONE: {
LABEL: '客服电话',
VALUE: '400-888-8888'
VALUE: '400-077-6018'
},
SERVICE_TIME: {
LABEL: '服务时间',
+19 -13
View File
@@ -5,7 +5,6 @@
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
@@ -16,11 +15,10 @@
"autoclose" : true,
"delay" : 0
},
/* */
"modules" : {},
/* */
"modules" : {
"Maps" : {}
},
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
@@ -37,30 +35,38 @@
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>"
]
},
/* ios */
"ios" : {},
/* SDK */
"sdkConfigs" : {}
"sdkConfigs" : {
"maps" : {
"amap" : {
"appkey_ios" : "4c513a688938fd89b88b296e867f66ec",
"appkey_android" : "4c513a688938fd89b88b296e867f66ec"
}
}
}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "wx2165f0be356ae7a9",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true,
// "requiredPrivateInfos" : [ "getPhoneNumber" ],
"permission" : {
"scope.getPhoneNumber" : {
"desc" : "您的手机号将用于登录和订单服务"
},
"scope.userLocation" : {
"desc" : "您的位置信息将用于获取附近的设备"
}
}
},
"requiredPrivateInfos" : [ "getLocation" ]
},
"mp-alipay" : {
"usingComponents" : true
+1 -1
View File
@@ -5,7 +5,7 @@
"pages": [{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "共享风扇"
"navigationBarTitleText": "附近场地"
}
},
{
+17 -8
View File
@@ -29,7 +29,7 @@
<text class="item-value">{{ deviceLocation }}</text>
</view>
</view>
<view class="card-item">
<!-- <view class="card-item">
<view class="item-icon battery-icon" :class="{ 'battery-low': batteryLevel < 20 }">
<image src="/static/images/Electricity.svg" mode="aspectFill"
style="width: 45rpx;height: 45rpx;"></image>
@@ -38,7 +38,7 @@
<text class="item-label">电池电量</text>
<text class="item-value">{{ batteryLevel }}%</text>
</view>
</view>
</view> -->
</view>
</view>
@@ -158,7 +158,8 @@
onMounted
} from 'vue'
import {
onLoad
onLoad,
onShow
} from '@dcloudio/uni-app'
import {
getDeviceInfo,
@@ -195,14 +196,22 @@
// 生命周期 onLoad 钩子
onLoad((options) => {
if (options.deviceNo != uni.getStorageSync('deviceId') || !uni.getStorageSync('deviceId')) {
deviceId.value = options.deviceNo
uni.setStorageSync('deviceId', options.deviceNo)
} else {
deviceId.value = uni.getStorageSync('deviceId')
// uni.removeStorageSync('deviceId')
}
checkOrderStatus()
console.log(options.deviceNo)
fetchDeviceInfo()
})
onMounted(() => {
checkUserPhone()
onMounted(async () => {
await checkUserPhone()
})
onShow(async () => {
await fetchDeviceInfo()
})
const checkUserPhone = async () => {
@@ -334,7 +343,7 @@
deviceStatus.class = 'offline'
}
}
console.log('feeconfig',deviceInfo.value.feeConfig);
console.log('feeconfig', deviceInfo.value.feeConfig);
deviceFeeConfig.value = JSON.parse(deviceInfo.value.feeConfig)[0] || {}
}
+736 -454
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -42,7 +42,13 @@
"permission": {
"scope.getPhoneNumber": {
"desc": "您的手机号将用于登录和订单服务"
},
"scope.userLocation": {
"desc": "您的位置信息将用于获取附近的设备"
}
},
"requiredPrivateInfos": [
"getLocation"
],
"usingComponents": {}
}
+1 -1
View File
@@ -1 +1 @@
"use strict";exports._imports_0="/static/logo.png",exports._imports_0$1="/static/user-active.png",exports._imports_0$2="/static/images/wxpayflag.png",exports._imports_0$3="/static/images/location-map.svg",exports._imports_1="/static/scan-icon.png",exports._imports_1$1="/static/jl.png",exports._imports_1$2="/static/images/Electricity.svg",exports._imports_2="/static/complaint.png",exports._imports_3="/static/hlep.png";
"use strict";exports._imports_0="/static/scan-icon.png",exports._imports_0$1="/static/user-active.png",exports._imports_0$2="/static/images/wxpayflag.png",exports._imports_0$3="/static/images/location-map.svg",exports._imports_1="/static/jl.png",exports._imports_2="/static/complaint.png",exports._imports_3="/static/hlep.png";
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
"use strict";const e=require("../common/vendor.js"),t=require("../common/assets.js"),i={__name:"MapComponent",props:{userLocation:{type:Object,default:null},positionList:{type:Array,default:()=>[]},filteredPositions:{type:Array,default:()=>[]},searchKeyword:{type:String,default:""}},emits:["relocate","scan","showList","markerTap","mapCenterChange"],setup(i,{expose:o,emit:a}){const n=i,l=a,u=e.ref(0),d=e.ref(16),r=e.ref({longitude:116.397128,latitude:39.916527}),s=e.ref(null),c=e.ref(!1),p=()=>{l("relocate")},f=()=>{l("scan")},m=()=>{l("showList")},g=t=>{if(!t.detail||void 0===t.detail.markerId)return;const i=t.detail.markerId;if(9999===i)return void e.index.showToast({title:"这是您的位置",icon:"none"});const o=n.filteredPositions[i];o&&l("markerTap",o)},v=e=>{if("end"===e.detail.type){const{center:t}=e.detail;if(!t||void 0===t.longitude||void 0===t.latitude)return;r.value={longitude:t.longitude,latitude:t.latitude},d.value=16,s.value&&clearTimeout(s.value),s.value=setTimeout((()=>{l("mapCenterChange",r.value)}),500)}},h=e.computed((()=>{const e=[];return n.filteredPositions.forEach(((t,i)=>{t.longitude&&t.latitude&&e.push({id:i,longitude:parseFloat(t.longitude),latitude:parseFloat(t.latitude),title:t.name,iconPath:"/static/scan-icon.png",width:30,height:30,callout:{content:t.name,fontSize:14,borderRadius:8,bgColor:"#ffffff",padding:10,display:"BYCLICK"}})})),n.userLocation&&e.push({id:9999,longitude:n.userLocation.longitude,latitude:n.userLocation.latitude,title:"我的位置",iconPath:"/static/scan-icon.png",width:32,height:32,callout:{content:"我的位置",fontSize:14,borderRadius:8,bgColor:"#2196F3",color:"#ffffff",padding:10,display:"BYCLICK"}}),e}));return e.watch((()=>n.userLocation),(t=>{var i,o;t&&t.longitude&&t.latitude&&!c.value&&(i=t.longitude,o=t.latitude,r.value.longitude===i&&r.value.latitude===o||(r.value={longitude:i,latitude:o},d.value=16,e.nextTick$1((()=>{setTimeout((()=>{const t=e.index.createMapContext("mainMap");t&&t.setCenterOffset({longitude:i,latitude:o,success:()=>{},fail:()=>{t.includePoints({points:[{longitude:i,latitude:o}],padding:[0,0,0,0]})}})}),200)}))),c.value=!0)}),{immediate:!0,deep:!0}),e.onMounted((()=>{})),e.onUnmounted((()=>{s.value&&clearTimeout(s.value)})),o({mapCenter:e.computed((()=>r.value))}),(i,o)=>e.e({a:u.value,b:r.value.longitude,c:r.value.latitude,d:d.value,e:h.value,f:e.o(g),g:e.o(v),h:!r.value.longitude},(r.value.longitude,{}),{i:t._imports_0,j:e.o(p),k:t._imports_0,l:e.o(f),m:t._imports_0,n:e.o(m)})}},o=e._export_sfc(i,[["__scopeId","data-v-65e2cece"]]);wx.createComponent(o);
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
@@ -0,0 +1 @@
<view class="map-container data-v-65e2cece"><map id="mainMap" class="map data-v-65e2cece" key="{{a}}" longitude="{{b}}" latitude="{{c}}" scale="{{d}}" markers="{{e}}" show-location="{{false}}" enable-scroll="{{true}}" enable-zoom="{{true}}" enable-rotate="{{false}}" show-compass="{{false}}" bindmarkertap="{{f}}" bindregionchange="{{g}}"></map><view wx:if="{{h}}" class="map-loading data-v-65e2cece"><view class="loading-content data-v-65e2cece"><view class="loading-spinner data-v-65e2cece"></view><text class="data-v-65e2cece">地图加载中...</text></view></view><view class="map-controls data-v-65e2cece"><view class="control-btn location-control data-v-65e2cece" bindtap="{{j}}"><image class="control-icon data-v-65e2cece" src="{{i}}" mode="aspectFit"/><text class="data-v-65e2cece">我的位置</text></view><view class="control-btn scan-control main-btn data-v-65e2cece" bindtap="{{l}}"><image class="control-icon data-v-65e2cece" src="{{k}}" mode="aspectFit"/><text class="data-v-65e2cece">扫码使用</text></view><view class="control-btn list-control data-v-65e2cece" bindtap="{{n}}"><image class="control-icon data-v-65e2cece" src="{{m}}" mode="aspectFit"/><text class="data-v-65e2cece">附近场地</text></view></view></view>
@@ -0,0 +1 @@
.map-container.data-v-65e2cece{flex:1;position:relative;height:100vh;width:100%}.map-container .map.data-v-65e2cece{width:100%;height:100%}.map-container .map-loading.data-v-65e2cece{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(255,255,255,.8);display:flex;justify-content:center;align-items:center;z-index:10}.map-container .map-loading .loading-content.data-v-65e2cece{display:flex;flex-direction:column;align-items:center;justify-content:center}.map-container .map-loading .loading-content .loading-spinner.data-v-65e2cece{width:60rpx;height:60rpx;border:8rpx solid #f3f3f3;border-top:8rpx solid #3498db;border-radius:50%;animation:spin-65e2cece 1s linear infinite;margin-bottom:20rpx}.map-container .map-loading .loading-content text.data-v-65e2cece{font-size:32rpx;color:#333;font-weight:500}.map-container .map-controls.data-v-65e2cece{position:absolute;right:30rpx;bottom:20rpx;left:30rpx;display:flex;justify-content:center;align-items:center;gap:30rpx}.map-container .map-controls .control-btn.data-v-65e2cece{min-width:140rpx;height:80rpx;background:#fff;border-radius:40rpx;display:flex;flex-direction:row;align-items:center;justify-content:center;box-shadow:0 4rpx 12rpx rgba(0,0,0,.1);transition:all .2s ease;padding:0 20rpx}.map-container .map-controls .control-btn.data-v-65e2cece:active{transform:scale(.95)}.map-container .map-controls .control-btn .control-icon.data-v-65e2cece{width:32rpx;height:32rpx;margin-right:12rpx}.map-container .map-controls .control-btn text.data-v-65e2cece{font-size:26rpx;color:#333;white-space:nowrap;font-weight:500}.map-container .map-controls .control-btn.main-btn.data-v-65e2cece{min-width:160rpx;height:90rpx;box-shadow:0 6rpx 20rpx rgba(33,150,243,.4);transform:translateY(-5rpx)}.map-container .map-controls .control-btn.main-btn .control-icon.data-v-65e2cece{width:36rpx;height:36rpx;margin-right:16rpx}.map-container .map-controls .control-btn.main-btn text.data-v-65e2cece{font-size:28rpx;font-weight:600}.map-container .map-controls .control-btn.main-btn.data-v-65e2cece:active{transform:translateY(-5rpx) scale(.95)}.map-container .map-controls .scan-control.data-v-65e2cece{background:#2196f3}.map-container .map-controls .scan-control .control-icon.data-v-65e2cece{filter:brightness(0) invert(1)}.map-container .map-controls .scan-control text.data-v-65e2cece{color:#fff}.map-container .map-controls .list-control.data-v-65e2cece{background:#4caf50}.map-container .map-controls .list-control .control-icon.data-v-65e2cece{filter:brightness(0) invert(1)}.map-container .map-controls .list-control text.data-v-65e2cece{color:#fff}.map-container .map-controls .location-control.data-v-65e2cece{background:#fff;border:2rpx solid #e0e0e0}.map-container .map-controls .location-control .control-icon.data-v-65e2cece{filter:none}.map-container .map-controls .location-control text.data-v-65e2cece{color:#333}@keyframes spin-65e2cece{0%{transform:rotate(0)}to{transform:rotate(360deg)}}
+1 -1
View File
@@ -1 +1 @@
"use strict";exports.HELP_CONTENT={FAQ_LIST:[{question:"如何租借风扇?",answer:'点击首页"扫码租借"按钮,使用微信扫描设备上的二维码,按提示完成支付即可使用。'},{question:"收费标准是怎样的?",answer:"使用费用为2元/小时,不足1小时按1小时计算。押金99元,归还后自动退还。"},{question:"如何归还风扇?",answer:'将风扇带到任意归还点,点击首页"扫码归还"按钮,扫描归还点二维码即可完成归还。'},{question:"押金多久能退还?",answer:"归还设备后押金将自动发起退款,预计0-7个工作日到账。"},{question:"设备无法正常使用怎么办?",answer:'您可以通过"我的-投诉与建议"提交故障反馈,或直接拨打客服电话处理。'}],CONTACT:{TITLE:"联系客服",PHONE:{LABEL:"客服电话",VALUE:"400-888-8888"},SERVICE_TIME:{LABEL:"服务时间",VALUE:"周一至周日 09:00-22:00"}}};
"use strict";exports.HELP_CONTENT={FAQ_LIST:[{question:"如何租借风扇?",answer:'点击首页"扫码租借"按钮,使用微信扫描设备上的二维码,按提示完成支付即可使用。'},{question:"收费标准是怎样的?",answer:"本产品租界风扇采用免押金租借形式,无需支付押金,具体计费方式以场地机柜扫码提示为准。"},{question:"如何归还风扇?",answer:'将风扇带到任意归还点,点击首页"扫码归还"按钮,扫描归还点二维码即可完成归还。'},{question:"押金多久能退还?",answer:"归还设备后押金将自动发起退款,预计0-7个工作日到账。"},{question:"设备无法正常使用怎么办?",answer:'您可以通过"我的-投诉与建议"提交故障反馈,或直接拨打客服电话处理。'}],CONTACT:{TITLE:"联系客服",PHONE:{LABEL:"客服电话",VALUE:"400-077-6018"},SERVICE_TIME:{LABEL:"服务时间",VALUE:"周一至周日 09:00-22:00"}}};
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
<view class="container data-v-f7bf7b27"><view class="device-header data-v-f7bf7b27"><view class="{{['device-status-card', 'data-v-f7bf7b27', b]}}"><view class="status-indicator data-v-f7bf7b27"></view><text class="status-text data-v-f7bf7b27">{{a}}</text></view><view class="device-title data-v-f7bf7b27"><text class="name data-v-f7bf7b27">共享风扇</text><view class="device-meta data-v-f7bf7b27"><text class="id-label data-v-f7bf7b27">设备号:</text><text class="id-value data-v-f7bf7b27">{{c}}</text></view></view></view><view class="card device-info-card data-v-f7bf7b27"><view class="card-row data-v-f7bf7b27"><view class="card-item data-v-f7bf7b27"><view class="item-icon location-icon data-v-f7bf7b27"><image class="data-v-f7bf7b27" src="{{d}}" mode="aspectFill" style="width:45rpx;height:45rpx"></image></view><view class="item-content data-v-f7bf7b27"><text class="item-label data-v-f7bf7b27">当前位置</text><text class="item-value data-v-f7bf7b27">{{e}}</text></view></view><view class="card-item data-v-f7bf7b27"><view class="{{['item-icon', 'battery-icon', 'data-v-f7bf7b27', g && 'battery-low']}}"><image class="data-v-f7bf7b27" src="{{f}}" mode="aspectFill" style="width:45rpx;height:45rpx"></image></view><view class="item-content data-v-f7bf7b27"><text class="item-label data-v-f7bf7b27">电池电量</text><text class="item-value data-v-f7bf7b27">{{h}}%</text></view></view></view></view><view class="card pricing-card data-v-f7bf7b27"><view class="card-header data-v-f7bf7b27"><text class="card-title data-v-f7bf7b27">计费规则</text></view><view class="pricing-banner data-v-f7bf7b27"><view class="pricing-main data-v-f7bf7b27"><text class="price data-v-f7bf7b27">¥{{i}}</text><text class="unit data-v-f7bf7b27">/小时</text></view><text class="cap-price data-v-f7bf7b27">封顶 ¥{{j}}</text></view><view class="pricing-rules data-v-f7bf7b27"><view class="rule-item data-v-f7bf7b27"><view class="rule-dot data-v-f7bf7b27"></view><text class="rule-text data-v-f7bf7b27">不足60分钟按60分钟计费</text></view><view class="rule-item data-v-f7bf7b27"><view class="rule-dot data-v-f7bf7b27"></view><text class="rule-text data-v-f7bf7b27">持续计费至99元视为买断</text></view></view></view><view class="card notice-card data-v-f7bf7b27"><view class="card-header data-v-f7bf7b27"><text class="card-title data-v-f7bf7b27">使用须知</text></view><view class="notice-items data-v-f7bf7b27"><view class="notice-item data-v-f7bf7b27"><view class="notice-dot data-v-f7bf7b27"></view><text class="notice-text data-v-f7bf7b27">请在使用前检查设备是否完好</text></view><view class="notice-item data-v-f7bf7b27"><view class="notice-dot data-v-f7bf7b27"></view><text class="notice-text data-v-f7bf7b27">请在指定区域内使用设备</text></view><view class="notice-item data-v-f7bf7b27"><view class="notice-dot data-v-f7bf7b27"></view><text class="notice-text data-v-f7bf7b27">归还时请确保设备完好,避免损坏</text></view></view></view><view class="footer data-v-f7bf7b27"><button class="{{['rent-button', 'data-v-f7bf7b27', l && 'return-button']}}" bindtap="{{m}}"><text class="data-v-f7bf7b27">{{k}}</text></button><view class="wechat-credit data-v-f7bf7b27"><image src="{{n}}" mode="aspectFit" class="wx-icon data-v-f7bf7b27"></image><view class="credit-text data-v-f7bf7b27"><text class="data-v-f7bf7b27">微信支付分</text><text class="credit-divider data-v-f7bf7b27">|</text><text class="credit-score data-v-f7bf7b27">550分及以上优享</text></view></view></view><view wx:if="{{o}}" class="phone-auth-popup data-v-f7bf7b27"><view class="popup-mask data-v-f7bf7b27" catchtap="{{p}}"></view><view class="popup-content data-v-f7bf7b27"><view class="popup-header data-v-f7bf7b27"><text class="popup-title data-v-f7bf7b27">授权获取手机号</text></view><view class="popup-body data-v-f7bf7b27"><view class="auth-desc data-v-f7bf7b27"><text class="data-v-f7bf7b27">为了提供更好的服务,需要授权获取您的手机号</text></view><button class="auth-btn data-v-f7bf7b27" open-type="getPhoneNumber" bindgetphonenumber="{{q}}"> 一键获取手机号 </button><view class="auth-cancel data-v-f7bf7b27" bindtap="{{r}}"><text class="data-v-f7bf7b27">暂不授权</text></view></view></view></view></view>
<view class="container data-v-f998093e"><view class="device-header data-v-f998093e"><view class="{{['device-status-card', 'data-v-f998093e', b]}}"><view class="status-indicator data-v-f998093e"></view><text class="status-text data-v-f998093e">{{a}}</text></view><view class="device-title data-v-f998093e"><text class="name data-v-f998093e">共享风扇</text><view class="device-meta data-v-f998093e"><text class="id-label data-v-f998093e">设备号:</text><text class="id-value data-v-f998093e">{{c}}</text></view></view></view><view class="card device-info-card data-v-f998093e"><view class="card-row data-v-f998093e"><view class="card-item data-v-f998093e"><view class="item-icon location-icon data-v-f998093e"><image class="data-v-f998093e" src="{{d}}" mode="aspectFill" style="width:45rpx;height:45rpx"></image></view><view class="item-content data-v-f998093e"><text class="item-label data-v-f998093e">当前位置</text><text class="item-value data-v-f998093e">{{e}}</text></view></view></view></view><view class="card pricing-card data-v-f998093e"><view class="card-header data-v-f998093e"><text class="card-title data-v-f998093e">计费规则</text></view><view class="pricing-banner data-v-f998093e"><view class="pricing-main data-v-f998093e"><text class="price data-v-f998093e">¥{{f}}</text><text class="unit data-v-f998093e">/小时</text></view><text class="cap-price data-v-f998093e">封顶 ¥{{g}}</text></view><view class="pricing-rules data-v-f998093e"><view class="rule-item data-v-f998093e"><view class="rule-dot data-v-f998093e"></view><text class="rule-text data-v-f998093e">不足60分钟按60分钟计费</text></view><view class="rule-item data-v-f998093e"><view class="rule-dot data-v-f998093e"></view><text class="rule-text data-v-f998093e">持续计费至99元视为买断</text></view></view></view><view class="card notice-card data-v-f998093e"><view class="card-header data-v-f998093e"><text class="card-title data-v-f998093e">使用须知</text></view><view class="notice-items data-v-f998093e"><view class="notice-item data-v-f998093e"><view class="notice-dot data-v-f998093e"></view><text class="notice-text data-v-f998093e">请在使用前检查设备是否完好</text></view><view class="notice-item data-v-f998093e"><view class="notice-dot data-v-f998093e"></view><text class="notice-text data-v-f998093e">请在指定区域内使用设备</text></view><view class="notice-item data-v-f998093e"><view class="notice-dot data-v-f998093e"></view><text class="notice-text data-v-f998093e">归还时请确保设备完好,避免损坏</text></view></view></view><view class="footer data-v-f998093e"><button class="{{['rent-button', 'data-v-f998093e', i && 'return-button']}}" bindtap="{{j}}"><text class="data-v-f998093e">{{h}}</text></button><view class="wechat-credit data-v-f998093e"><image src="{{k}}" mode="aspectFit" class="wx-icon data-v-f998093e"></image><view class="credit-text data-v-f998093e"><text class="data-v-f998093e">微信支付分</text><text class="credit-divider data-v-f998093e">|</text><text class="credit-score data-v-f998093e">550分及以上优享</text></view></view></view><view wx:if="{{l}}" class="phone-auth-popup data-v-f998093e"><view class="popup-mask data-v-f998093e" catchtap="{{m}}"></view><view class="popup-content data-v-f998093e"><view class="popup-header data-v-f998093e"><text class="popup-title data-v-f998093e">授权获取手机号</text></view><view class="popup-body data-v-f998093e"><view class="auth-desc data-v-f998093e"><text class="data-v-f998093e">为了提供更好的服务,需要授权获取您的手机号</text></view><button class="auth-btn data-v-f998093e" open-type="getPhoneNumber" bindgetphonenumber="{{n}}"> 一键获取手机号 </button><view class="auth-cancel data-v-f998093e" bindtap="{{o}}"><text class="data-v-f998093e">暂不授权</text></view></view></view></view></view>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4 -2
View File
@@ -1,4 +1,6 @@
{
"navigationBarTitleText": "共享风扇",
"usingComponents": {}
"navigationBarTitleText": "附近场地",
"usingComponents": {
"map-component": "../../components/MapComponent"
}
}
+1 -1
View File
@@ -1 +1 @@
<view class="container data-v-cb03dff0"><view class="header data-v-cb03dff0"><view class="header-bg data-v-cb03dff0"><view class="circle-decoration circle-1 data-v-cb03dff0"></view><view class="circle-decoration circle-2 data-v-cb03dff0"></view><view class="wave-decoration data-v-cb03dff0"></view></view><view class="header-content data-v-cb03dff0"><view class="brand-area data-v-cb03dff0"><image class="brand-logo data-v-cb03dff0" src="{{a}}" mode="aspectFit"></image><view class="brand-text data-v-cb03dff0"><text class="title data-v-cb03dff0">共享风扇</text><text class="subtitle data-v-cb03dff0">随时随地,享受清凉</text></view></view><view class="header-info data-v-cb03dff0"><view class="service-tag data-v-cb03dff0"><text class="data-v-cb03dff0">便捷租赁</text><text class="dot data-v-cb03dff0">·</text><text class="data-v-cb03dff0">品质保障</text></view></view></view></view><view class="scan-section data-v-cb03dff0"><view class="scan-card data-v-cb03dff0"><view class="scan-btn data-v-cb03dff0" bindtap="{{c}}"><image class="scan-icon data-v-cb03dff0" src="{{b}}" mode="aspectFit"/><text class="scan-text data-v-cb03dff0">扫码使用</text></view><view class="scan-desc data-v-cb03dff0"><text class="data-v-cb03dff0">扫描设备二维码即可使用或归还</text></view></view></view><view class="price-card data-v-cb03dff0"><view class="card-header data-v-cb03dff0"><text class="card-title data-v-cb03dff0">收费规则</text></view><view class="price-rules data-v-cb03dff0"><view class="price-item data-v-cb03dff0"><view class="price-tag data-v-cb03dff0">5.0<text class="unit data-v-cb03dff0">元/小时</text></view></view><view class="divider data-v-cb03dff0"></view><view class="rule-list data-v-cb03dff0"><view class="rule-item data-v-cb03dff0"><view class="rule-dot data-v-cb03dff0"></view><text class="data-v-cb03dff0">不足1小时按1小时计费</text></view><view class="rule-item data-v-cb03dff0"><view class="rule-dot data-v-cb03dff0"></view><text class="data-v-cb03dff0">封顶99元,计费达99元视为买断</text></view></view></view></view><view class="usage-steps data-v-cb03dff0"><view class="steps-header data-v-cb03dff0"><text class="steps-title data-v-cb03dff0">使用流程</text></view><view class="steps-container data-v-cb03dff0"><view class="step-item data-v-cb03dff0"><view class="step-icon data-v-cb03dff0"><text class="step-number data-v-cb03dff0">1</text></view><text class="step-text data-v-cb03dff0">扫码弹出</text></view><view class="step-arrow data-v-cb03dff0"></view><view class="step-item data-v-cb03dff0"><view class="step-icon data-v-cb03dff0"><text class="step-number data-v-cb03dff0">2</text></view><text class="step-text data-v-cb03dff0">使用风扇</text></view><view class="step-arrow data-v-cb03dff0"></view><view class="step-item data-v-cb03dff0"><view class="step-icon data-v-cb03dff0"><text class="step-number data-v-cb03dff0">3</text></view><text class="step-text data-v-cb03dff0">插入归还</text></view><view class="step-arrow data-v-cb03dff0"></view><view class="step-item data-v-cb03dff0"><view class="step-icon data-v-cb03dff0"><text class="step-number data-v-cb03dff0">4</text></view><text class="step-text data-v-cb03dff0">结束订单</text></view></view></view><view wx:if="{{d}}" class="phone-auth-popup data-v-cb03dff0"><view class="popup-mask data-v-cb03dff0" catchtap="{{e}}"></view><view class="popup-content data-v-cb03dff0"><view class="popup-header data-v-cb03dff0"><text class="popup-title data-v-cb03dff0">授权获取手机号</text></view><view class="popup-body data-v-cb03dff0"><view class="auth-desc data-v-cb03dff0"><text class="data-v-cb03dff0">为了提供更好的服务和紧急联系,需要授权获取您的手机号</text></view><button class="auth-btn data-v-cb03dff0" open-type="getPhoneNumber" bindgetphonenumber="{{f}}"><text class="data-v-cb03dff0">一键获取手机号</text></button><view class="auth-cancel data-v-cb03dff0" bindtap="{{g}}"><text class="data-v-cb03dff0">暂不授权</text></view></view></view></view></view>
<view class="container data-v-ef66b09a"><map-component wx:if="{{a}}" class="r data-v-ef66b09a" u-r="mapRef" bindrelocate="{{c}}" bindscan="{{d}}" bindshowList="{{e}}" bindmarkerTap="{{f}}" bindmapCenterChange="{{g}}" u-i="ef66b09a-0" bind:__l="__l" u-p="{{h}}"/><view wx:if="{{i}}" class="map-loading-placeholder data-v-ef66b09a"><view class="loading-content data-v-ef66b09a"><view class="loading-spinner data-v-ef66b09a"></view><text class="data-v-ef66b09a">正在获取位置信息...</text></view></view><view wx:if="{{j}}" class="location-popup data-v-ef66b09a"><view class="popup-mask data-v-ef66b09a" bindtap="{{k}}"></view><view class="{{['location-sheet', 'data-v-ef66b09a', t && 'expanded']}}"><view class="sheet-handle data-v-ef66b09a" bindtap="{{l}}"><view class="handle-bar data-v-ef66b09a"></view></view><view class="sheet-header data-v-ef66b09a"><text class="sheet-title data-v-ef66b09a">附近场地 ({{m}})</text><view class="close-btn data-v-ef66b09a" bindtap="{{o}}"><image class="close-icon data-v-ef66b09a" src="{{n}}" mode="aspectFit"/></view></view><scroll-view class="sheet-content data-v-ef66b09a" scroll-y="true"><view wx:for="{{p}}" wx:for-item="item" wx:key="k" class="position-item data-v-ef66b09a" bindtap="{{item.l}}"><view class="position-info data-v-ef66b09a"><view class="position-name data-v-ef66b09a">{{item.a}}</view><view class="position-desc data-v-ef66b09a">{{item.b}}</view><view class="position-location data-v-ef66b09a"><image class="location-icon-small data-v-ef66b09a" src="{{q}}" mode="aspectFit"/><text class="data-v-ef66b09a">{{item.c}}</text></view><view wx:if="{{item.d}}" class="position-time data-v-ef66b09a"><text class="data-v-ef66b09a">营业时间:{{item.e}}</text></view></view><view class="position-actions data-v-ef66b09a"><view wx:if="{{item.f}}" class="distance-info data-v-ef66b09a"><text class="data-v-ef66b09a">{{item.g}}km</text></view><view class="{{['status-tag', 'data-v-ef66b09a', item.i]}}"><text class="data-v-ef66b09a">{{item.h}}</text></view><view class="nav-btn data-v-ef66b09a" catchtap="{{item.j}}"><text class="data-v-ef66b09a">导航</text></view></view></view><view wx:if="{{r}}" class="empty-state data-v-ef66b09a"><image class="empty-icon data-v-ef66b09a" src="{{s}}" mode="aspectFit"/><text class="empty-text data-v-ef66b09a">暂无附近场地</text></view></scroll-view></view></view><view wx:if="{{v}}" class="loading-overlay data-v-ef66b09a"><view class="loading-content data-v-ef66b09a"><view class="loading-spinner data-v-ef66b09a"></view><text class="data-v-ef66b09a">正在获取场地信息...</text></view></view><view wx:if="{{w}}" class="phone-auth-popup data-v-ef66b09a"><view class="popup-mask data-v-ef66b09a" catchtap="{{x}}"></view><view class="popup-content data-v-ef66b09a"><view class="popup-header data-v-ef66b09a"><text class="popup-title data-v-ef66b09a">授权获取手机号</text></view><view class="popup-body data-v-ef66b09a"><view class="auth-desc data-v-ef66b09a"><text class="data-v-ef66b09a">为了提供更好的服务和紧急联系,需要授权获取您的手机号</text></view><button class="auth-btn data-v-ef66b09a" open-type="getPhoneNumber" bindgetphonenumber="{{y}}"><text class="data-v-ef66b09a">一键获取手机号</text></button><view class="auth-cancel data-v-ef66b09a" bindtap="{{z}}"><text class="data-v-ef66b09a">暂不授权</text></view></view></view></view></view>
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
"use strict";const e=require("../../common/vendor.js"),a=require("../../common/assets.js"),o=require("../../util/index.js");if(!Array){e.resolveComponent("uni-icons")()}const n={__name:"index",setup(n){const t=e.ref({}),r=e.ref("0.00"),i=e.ref(""),s=e.ref(null),d=e.ref(!1);e.onMounted((()=>{l()}));const l=async()=>{try{if(!e.index.getStorageSync("token"))return void(await o.wxLogin());const a=await o.getUserInfo();console.log("User info response:",a),200==a.code&&(a.data.openId&&(i.value=a.data.openId,e.index.setStorageSync("openId",a.data.openId)),t.value={nickName:a.data.nickname,phone:a.data.phone,avatar:a.data.iconUrl,isAdmin:a.data.isAdmin},e.index.setStorageSync("userInfo",t.value),r.value=a.data.balanceAmount||"0.00")}catch(a){console.error("获取用户信息失败:",a),e.index.showToast({title:"获取用户信息失败",icon:"none"})}},c=a=>{e.index.navigateTo({url:a})},p=()=>{c("/pages/deposit/index")},u=()=>{t.value||v()},v=()=>{s.value&&(s.value.open(),d.value=!0)};return(o,n)=>{return e.e({a:t.value.avatar},t.value.avatar?{b:t.value.avatar}:{c:a._imports_0$1},{d:t.value.isAdmin},(t.value.isAdmin,{}),{e:t.value},t.value?{f:e.t(t.value.nickName),g:e.t(t.value.phone?(i=t.value.phone,i?i.replace(/(\d{3})\d{4}(\d{4})/,"$1****$2"):""):"未绑定手机号")}:{},{h:e.p({type:"right",size:"16",color:"#999"}),i:e.o(u),j:e.t(r.value),k:e.o(p),l:a._imports_1$1,m:e.p({type:"right",size:"16",color:"#999"}),n:e.o((e=>c("/pages/order/index"))),o:a._imports_2,p:e.p({type:"right",size:"16",color:"#999"}),q:e.o((e=>c("/pages/feedback/index"))),r:a._imports_3,s:e.p({type:"right",size:"16",color:"#999"}),t:e.o((e=>c("/pages/help/index")))});var i}}},t=e._export_sfc(n,[["__scopeId","data-v-6fbc3933"]]);wx.createPage(t);
"use strict";const e=require("../../common/vendor.js"),a=require("../../common/assets.js"),o=require("../../util/index.js");if(!Array){e.resolveComponent("uni-icons")()}const n={__name:"index",setup(n){const t=e.ref({}),r=e.ref("0.00"),i=e.ref(""),s=e.ref(null),d=e.ref(!1);e.onMounted((()=>{l()}));const l=async()=>{try{if(!e.index.getStorageSync("token"))return void(await o.wxLogin());const a=await o.getUserInfo();console.log("User info response:",a),200==a.code&&(a.data.openId&&(i.value=a.data.openId,e.index.setStorageSync("openId",a.data.openId)),t.value={nickName:a.data.nickname,phone:a.data.phone,avatar:a.data.iconUrl,isAdmin:a.data.isAdmin},e.index.setStorageSync("userInfo",t.value),r.value=a.data.balanceAmount||"0.00")}catch(a){console.error("获取用户信息失败:",a),e.index.showToast({title:"获取用户信息失败",icon:"none"})}},c=a=>{e.index.navigateTo({url:a})},p=()=>{c("/pages/deposit/index")},u=()=>{t.value||v()},v=()=>{s.value&&(s.value.open(),d.value=!0)};return(o,n)=>{return e.e({a:t.value.avatar},t.value.avatar?{b:t.value.avatar}:{c:a._imports_0$1},{d:t.value.isAdmin},(t.value.isAdmin,{}),{e:t.value},t.value?{f:e.t(t.value.nickName),g:e.t(t.value.phone?(i=t.value.phone,i?i.replace(/(\d{3})\d{4}(\d{4})/,"$1****$2"):""):"未绑定手机号")}:{},{h:e.p({type:"right",size:"16",color:"#999"}),i:e.o(u),j:e.t(r.value),k:e.o(p),l:a._imports_1,m:e.p({type:"right",size:"16",color:"#999"}),n:e.o((e=>c("/pages/order/index"))),o:a._imports_2,p:e.p({type:"right",size:"16",color:"#999"}),q:e.o((e=>c("/pages/feedback/index"))),r:a._imports_3,s:e.p({type:"right",size:"16",color:"#999"}),t:e.o((e=>c("/pages/help/index")))});var i}}},t=e._export_sfc(n,[["__scopeId","data-v-6fbc3933"]]);wx.createPage(t);
+1
View File
@@ -0,0 +1 @@
"use strict";const t=require("../common/vendor.js");const e=new class{constructor(){this.key="4c513a688938fd89b88b296e867f66ec"}async regeocode(e,s){try{const a=await t.index.request({url:"https://restapi.amap.com/v3/geocode/regeo",method:"GET",data:{key:this.key,location:`${e},${s}`,poitype:"",radius:1e3,extensions:"base",batch:!1,roadlevel:0}});return 200===a.statusCode&&"1"===a.data.status?{success:!0,data:a.data.regeocode}:{success:!1,message:a.data.info||"逆地理编码失败"}}catch(a){return console.error("逆地理编码异常:",a),{success:!1,message:"网络异常"}}}async geocode(e,s=""){try{const a=await t.index.request({url:"https://restapi.amap.com/v3/geocode/geo",method:"GET",data:{key:this.key,address:e,city:s}});return 200===a.statusCode&&"1"===a.data.status&&a.data.geocodes.length>0?{success:!0,data:a.data.geocodes[0]}:{success:!1,message:a.data.info||"地理编码失败"}}catch(a){return console.error("地理编码异常:",a),{success:!1,message:"网络异常"}}}async searchPOI(e,s="",a=3e3,c=""){try{const o=await t.index.request({url:"https://restapi.amap.com/v3/place/text",method:"GET",data:{key:this.key,keywords:e,location:s,radius:a,city:c,citylimit:!0}});return 200===o.statusCode&&"1"===o.data.status?{success:!0,data:o.data.pois||[]}:{success:!1,message:o.data.info||"搜索失败"}}catch(o){return console.error("POI搜索异常:",o),{success:!1,message:"网络异常"}}}async getRoute(e,s,a=0){try{const c=await t.index.request({url:"https://restapi.amap.com/v3/direction/driving",method:"GET",data:{key:this.key,origin:e,destination:s,strategy:a,extensions:"base"}});return 200===c.statusCode&&"1"===c.data.status?{success:!0,data:c.data.route}:{success:!1,message:c.data.info||"路径规划失败"}}catch(c){return console.error("路径规划异常:",c),{success:!1,message:"网络异常"}}}calculateDistance(t,e,s,a){const c=t*Math.PI/180,o=s*Math.PI/180,r=c-o,n=e*Math.PI/180-a*Math.PI/180;let d=2*Math.asin(Math.sqrt(Math.pow(Math.sin(r/2),2)+Math.cos(c)*Math.cos(o)*Math.pow(Math.sin(n/2),2)));return d*=6378.137,d=Math.round(1e4*d)/1e4,d}};exports.AmapUtil=e;
@@ -1 +1 @@
{"version":3,"file":"assets.js","sources":["static/logo.png","static/scan-icon.png","static/user-active.png","static/jl.png","static/complaint.png","static/hlep.png","static/images/wxpayflag.png","static/images/location-map.svg","static/images/Electricity.svg"],"sourcesContent":["export default \"__VITE_ASSET__fcf1191c__\"","export default \"__VITE_ASSET__b9d91c1a__\"","export default \"__VITE_ASSET__e217d500__\"","export default \"__VITE_ASSET__44ff4dfa__\"","export default \"__VITE_ASSET__d1c6bbb6__\"","export default \"__VITE_ASSET__f0ed8f64__\"","export default \"__VITE_ASSET__9081434a__\"","export default \"__VITE_ASSET__52e4836e__\"","export default \"__VITE_ASSET__f8b20b4b__\""],"names":[],"mappings":";AAAA,MAAe,eAAA;ACAf,MAAe,eAAA;ACAf,MAAe,eAAA;ACAf,MAAe,eAAA;ACAf,MAAe,aAAA;ACAf,MAAe,aAAA;ACAf,MAAe,eAAA;ACAf,MAAe,aAAA;ACAf,MAAe,aAAA;;;;;;;;;;"}
{"version":3,"file":"assets.js","sources":["static/scan-icon.png","static/user-active.png","static/jl.png","static/complaint.png","static/hlep.png","static/images/wxpayflag.png","static/images/location-map.svg"],"sourcesContent":["export default \"__VITE_ASSET__b9d91c1a__\"","export default \"__VITE_ASSET__e217d500__\"","export default \"__VITE_ASSET__44ff4dfa__\"","export default \"__VITE_ASSET__d1c6bbb6__\"","export default \"__VITE_ASSET__f0ed8f64__\"","export default \"__VITE_ASSET__9081434a__\"","export default \"__VITE_ASSET__52e4836e__\""],"names":[],"mappings":";AAAA,MAAe,eAAA;ACAf,MAAe,eAAA;ACAf,MAAe,aAAA;ACAf,MAAe,aAAA;ACAf,MAAe,aAAA;ACAf,MAAe,eAAA;ACAf,MAAe,aAAA;;;;;;;;"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
{"version":3,"file":"help.js","sources":["constants/help.js"],"sourcesContent":["// 帮助中心文案配置\r\nexport const HELP_CONTENT = {\r\n // FAQ列表\r\n FAQ_LIST: [\r\n {\r\n question: '如何租借风扇?',\r\n answer: '点击首页\"扫码租借\"按钮,使用微信扫描设备上的二维码,按提示完成支付即可使用。'\r\n },\r\n {\r\n question: '收费标准是怎样的?',\r\n answer: '使用费用为2元/小时,不足1小时按1小时计算。押金99元,归还后自动退还。'\r\n },\r\n {\r\n question: '如何归还风扇?',\r\n answer: '将风扇带到任意归还点,点击首页\"扫码归还\"按钮,扫描归还点二维码即可完成归还。'\r\n },\r\n {\r\n question: '押金多久能退还?',\r\n answer: '归还设备后押金将自动发起退款,预计0-7个工作日到账。'\r\n },\r\n {\r\n question: '设备无法正常使用怎么办?',\r\n answer: '您可以通过\"我的-投诉与建议\"提交故障反馈,或直接拨打客服电话处理。'\r\n }\r\n ],\r\n\r\n // 联系方式\r\n CONTACT: {\r\n TITLE: '联系客服',\r\n PHONE: {\r\n LABEL: '客服电话',\r\n VALUE: '400-888-8888'\r\n },\r\n SERVICE_TIME: {\r\n LABEL: '服务时间',\r\n VALUE: '周一至周日 09:00-22:00'\r\n }\r\n }\r\n} "],"names":[],"mappings":";AACY,MAAC,eAAe;AAAA;AAAA,EAE1B,UAAU;AAAA,IACR;AAAA,MACE,UAAU;AAAA,MACV,QAAQ;AAAA,IACT;AAAA,IACD;AAAA,MACE,UAAU;AAAA,MACV,QAAQ;AAAA,IACT;AAAA,IACD;AAAA,MACE,UAAU;AAAA,MACV,QAAQ;AAAA,IACT;AAAA,IACD;AAAA,MACE,UAAU;AAAA,MACV,QAAQ;AAAA,IACT;AAAA,IACD;AAAA,MACE,UAAU;AAAA,MACV,QAAQ;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGD,SAAS;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IACR;AAAA,IACD,cAAc;AAAA,MACZ,OAAO;AAAA,MACP,OAAO;AAAA,IACR;AAAA,EACF;AACH;;"}
{"version":3,"file":"help.js","sources":["constants/help.js"],"sourcesContent":["// 帮助中心文案配置\r\nexport const HELP_CONTENT = {\r\n // FAQ列表\r\n FAQ_LIST: [\r\n {\r\n question: '如何租借风扇?',\r\n answer: '点击首页\"扫码租借\"按钮,使用微信扫描设备上的二维码,按提示完成支付即可使用。'\r\n },\r\n {\r\n question: '收费标准是怎样的?',\r\n answer: '本产品租界风扇采用免押金租借形式,无需支付押金,具体计费方式以场地机柜扫码提示为准。'\r\n },\r\n {\r\n question: '如何归还风扇?',\r\n answer: '将风扇带到任意归还点,点击首页\"扫码归还\"按钮,扫描归还点二维码即可完成归还。'\r\n },\r\n {\r\n question: '押金多久能退还?',\r\n answer: '归还设备后押金将自动发起退款,预计0-7个工作日到账。'\r\n },\r\n {\r\n question: '设备无法正常使用怎么办?',\r\n answer: '您可以通过\"我的-投诉与建议\"提交故障反馈,或直接拨打客服电话处理。'\r\n }\r\n ],\r\n\r\n // 联系方式\r\n CONTACT: {\r\n TITLE: '联系客服',\r\n PHONE: {\r\n LABEL: '客服电话',\r\n VALUE: '400-077-6018'\r\n },\r\n SERVICE_TIME: {\r\n LABEL: '服务时间',\r\n VALUE: '周一至周日 09:00-22:00'\r\n }\r\n }\r\n} "],"names":[],"mappings":";AACY,MAAC,eAAe;AAAA;AAAA,EAE1B,UAAU;AAAA,IACR;AAAA,MACE,UAAU;AAAA,MACV,QAAQ;AAAA,IACT;AAAA,IACD;AAAA,MACE,UAAU;AAAA,MACV,QAAQ;AAAA,IACT;AAAA,IACD;AAAA,MACE,UAAU;AAAA,MACV,QAAQ;AAAA,IACT;AAAA,IACD;AAAA,MACE,UAAU;AAAA,MACV,QAAQ;AAAA,IACT;AAAA,IACD;AAAA,MACE,UAAU;AAAA,MACV,QAAQ;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGD,SAAS;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IACR;AAAA,IACD,cAAc;AAAA,MACZ,OAAO;AAAA,MACP,OAAO;AAAA,IACR;AAAA,EACF;AACH;;"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+6
View File
@@ -42,7 +42,13 @@
"permission": {
"scope.getPhoneNumber": {
"desc": "您的手机号将用于登录和订单服务"
},
"scope.userLocation": {
"desc": "您的位置信息将用于获取附近的设备"
}
},
"requiredPrivateInfos": [
"getLocation"
],
"usingComponents": {}
}
+3 -7
View File
@@ -1,20 +1,16 @@
"use strict";
const _imports_0$3 = "/static/logo.png";
const _imports_1$2 = "/static/scan-icon.png";
const _imports_0$3 = "/static/scan-icon.png";
const _imports_0$2 = "/static/user-active.png";
const _imports_1$1 = "/static/jl.png";
const _imports_1 = "/static/jl.png";
const _imports_2 = "/static/complaint.png";
const _imports_3 = "/static/hlep.png";
const _imports_0$1 = "/static/images/wxpayflag.png";
const _imports_0 = "/static/images/location-map.svg";
const _imports_1 = "/static/images/Electricity.svg";
exports._imports_0 = _imports_0$3;
exports._imports_0$1 = _imports_0$2;
exports._imports_0$2 = _imports_0$1;
exports._imports_0$3 = _imports_0;
exports._imports_1 = _imports_1$2;
exports._imports_1$1 = _imports_1$1;
exports._imports_1$2 = _imports_1;
exports._imports_1 = _imports_1;
exports._imports_2 = _imports_2;
exports._imports_3 = _imports_3;
//# sourceMappingURL=../../.sourcemap/mp-weixin/common/assets.js.map
+13 -2
View File
@@ -5163,12 +5163,17 @@ function vFor(source, renderItem) {
}
return ret;
}
function setRef(ref2, id, opts = {}) {
const { $templateRefs } = getCurrentInstance();
$templateRefs.push({ i: id, r: ref2, k: opts.k, f: opts.f });
}
const o = (value, key) => vOn(value, key);
const f = (source, renderItem) => vFor(source, renderItem);
const e = (target, ...sources) => extend(target, ...sources);
const n = (value) => normalizeClass(value);
const t = (val) => toDisplayString(val);
const p = (props) => renderProps(props);
const sr = (ref2, id, opts) => setRef(ref2, id, opts);
function createApp$1(rootComponent, rootProps = null) {
rootComponent && (rootComponent.mpType = "app");
return createVueApp(rootComponent, rootProps).use(plugin);
@@ -6988,9 +6993,9 @@ function isConsoleWritable() {
return isWritable;
}
function initRuntimeSocketService() {
const hosts = "192.168.10.30,127.0.0.1";
const hosts = "198.18.0.1,192.168.1.8,127.0.0.1";
const port = "8090";
const id = "mp-weixin_wcZ9WZ";
const id = "mp-weixin_RTBzKu";
const lazy = typeof swan !== "undefined";
let restoreError = lazy ? () => {
} : initOnError();
@@ -8871,6 +8876,7 @@ index.$u = $u;
const createHook = (lifecycle) => (hook, target = getCurrentInstance()) => {
!isInSSRComponentSetup && injectHook(lifecycle, hook, target);
};
const onShow = /* @__PURE__ */ createHook(ON_SHOW);
const onLoad = /* @__PURE__ */ createHook(ON_LOAD);
exports._export_sfc = _export_sfc;
exports.computed = computed;
@@ -8879,13 +8885,18 @@ exports.e = e;
exports.f = f;
exports.index = index;
exports.n = n;
exports.nextTick$1 = nextTick$1;
exports.o = o;
exports.onLoad = onLoad;
exports.onMounted = onMounted;
exports.onShow = onShow;
exports.onUnmounted = onUnmounted;
exports.p = p;
exports.reactive = reactive;
exports.ref = ref;
exports.resolveComponent = resolveComponent;
exports.sr = sr;
exports.t = t;
exports.watch = watch;
exports.wx$1 = wx$1;
//# sourceMappingURL=../../.sourcemap/mp-weixin/common/vendor.js.map
+198
View File
@@ -0,0 +1,198 @@
"use strict";
const common_vendor = require("../common/vendor.js");
const common_assets = require("../common/assets.js");
const _sfc_main = {
__name: "MapComponent",
props: {
userLocation: {
type: Object,
default: null
},
positionList: {
type: Array,
default: () => []
},
filteredPositions: {
type: Array,
default: () => []
},
searchKeyword: {
type: String,
default: ""
}
},
emits: [
"relocate",
"scan",
"showList",
"markerTap",
"mapCenterChange"
],
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emit = __emit;
const mapKey = common_vendor.ref(0);
const mapZoom = common_vendor.ref(16);
const mapCenter = common_vendor.ref({
longitude: 116.397128,
latitude: 39.916527
});
const loadPositionsTimer = common_vendor.ref(null);
const isMapInitialized = common_vendor.ref(false);
const updateMapCenter = (longitude, latitude) => {
if (mapCenter.value.longitude === longitude && mapCenter.value.latitude === latitude) {
return;
}
mapCenter.value = { longitude, latitude };
mapZoom.value = 16;
common_vendor.nextTick$1(() => {
setTimeout(() => {
const mapContext = common_vendor.index.createMapContext("mainMap");
if (mapContext) {
mapContext.setCenterOffset({
longitude,
latitude,
success: () => {
},
fail: () => {
mapContext.includePoints({
points: [{ longitude, latitude }],
padding: [0, 0, 0, 0]
});
}
});
}
}, 200);
});
};
const handleRelocate = () => {
emit("relocate");
};
const handleScan = () => {
emit("scan");
};
const handleShowList = () => {
emit("showList");
};
const handleMarkerTap = (e) => {
if (!e.detail || typeof e.detail.markerId === "undefined") {
return;
}
const markerId = e.detail.markerId;
if (markerId === 9999) {
common_vendor.index.showToast({
title: "这是您的位置",
icon: "none"
});
return;
}
const position = props.filteredPositions[markerId];
if (position) {
emit("markerTap", position);
}
};
const handleRegionChange = (e) => {
if (e.detail.type === "end") {
const { center } = e.detail;
if (!center || typeof center.longitude === "undefined" || typeof center.latitude === "undefined") {
return;
}
mapCenter.value = {
longitude: center.longitude,
latitude: center.latitude
};
mapZoom.value = 16;
if (loadPositionsTimer.value) {
clearTimeout(loadPositionsTimer.value);
}
loadPositionsTimer.value = setTimeout(() => {
emit("mapCenterChange", mapCenter.value);
}, 500);
}
};
const mapMarkers = common_vendor.computed(() => {
const markers = [];
props.filteredPositions.forEach((item, index) => {
if (item.longitude && item.latitude) {
markers.push({
id: index,
longitude: parseFloat(item.longitude),
latitude: parseFloat(item.latitude),
title: item.name,
iconPath: "/static/scan-icon.png",
width: 30,
height: 30,
callout: {
content: item.name,
fontSize: 14,
borderRadius: 8,
bgColor: "#ffffff",
padding: 10,
display: "BYCLICK"
}
});
}
});
if (props.userLocation) {
markers.push({
id: 9999,
// 特殊ID标识用户位置
longitude: props.userLocation.longitude,
latitude: props.userLocation.latitude,
title: "我的位置",
iconPath: "/static/scan-icon.png",
width: 32,
height: 32,
callout: {
content: "我的位置",
fontSize: 14,
borderRadius: 8,
bgColor: "#2196F3",
color: "#ffffff",
padding: 10,
display: "BYCLICK"
}
});
}
return markers;
});
common_vendor.watch(() => props.userLocation, (newLocation) => {
if (newLocation && newLocation.longitude && newLocation.latitude && !isMapInitialized.value) {
updateMapCenter(newLocation.longitude, newLocation.latitude);
isMapInitialized.value = true;
}
}, { immediate: true, deep: true });
common_vendor.onMounted(() => {
});
common_vendor.onUnmounted(() => {
if (loadPositionsTimer.value) {
clearTimeout(loadPositionsTimer.value);
}
});
__expose({
mapCenter: common_vendor.computed(() => mapCenter.value)
});
return (_ctx, _cache) => {
return common_vendor.e({
a: mapKey.value,
b: mapCenter.value.longitude,
c: mapCenter.value.latitude,
d: mapZoom.value,
e: mapMarkers.value,
f: common_vendor.o(handleMarkerTap),
g: common_vendor.o(handleRegionChange),
h: !mapCenter.value.longitude
}, !mapCenter.value.longitude ? {} : {}, {
i: common_assets._imports_0,
j: common_vendor.o(handleRelocate),
k: common_assets._imports_0,
l: common_vendor.o(handleScan),
m: common_assets._imports_0,
n: common_vendor.o(handleShowList)
});
};
}
};
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-651a9dc3"]]);
wx.createComponent(Component);
//# sourceMappingURL=../../.sourcemap/mp-weixin/components/MapComponent.js.map
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
@@ -0,0 +1 @@
<view class="map-container data-v-651a9dc3"><map id="mainMap" class="map data-v-651a9dc3" key="{{a}}" longitude="{{b}}" latitude="{{c}}" scale="{{d}}" markers="{{e}}" show-location="{{false}}" enable-scroll="{{true}}" enable-zoom="{{true}}" enable-rotate="{{false}}" show-compass="{{false}}" bindmarkertap="{{f}}" bindregionchange="{{g}}"></map><view wx:if="{{h}}" class="map-loading data-v-651a9dc3"><view class="loading-content data-v-651a9dc3"><view class="loading-spinner data-v-651a9dc3"></view><text class="data-v-651a9dc3">地图加载中...</text></view></view><view class="map-controls data-v-651a9dc3"><view class="control-btn location-control data-v-651a9dc3" bindtap="{{j}}"><image class="control-icon data-v-651a9dc3" src="{{i}}" mode="aspectFit"/><text class="data-v-651a9dc3">我的位置</text></view><view class="control-btn scan-control main-btn data-v-651a9dc3" bindtap="{{l}}"><image class="control-icon data-v-651a9dc3" src="{{k}}" mode="aspectFit"/><text class="data-v-651a9dc3">扫码使用</text></view><view class="control-btn list-control data-v-651a9dc3" bindtap="{{n}}"><image class="control-icon data-v-651a9dc3" src="{{m}}" mode="aspectFit"/><text class="data-v-651a9dc3">附近场地</text></view></view></view>
@@ -0,0 +1,159 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
/* 地图容器 */
.map-container.data-v-651a9dc3 {
flex: 1;
position: relative;
height: 100vh;
width: 100%;
}
.map-container .map.data-v-651a9dc3 {
width: 100%;
height: 100%;
}
.map-container .map-loading.data-v-651a9dc3 {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.8);
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
}
.map-container .map-loading .loading-content.data-v-651a9dc3 {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.map-container .map-loading .loading-content .loading-spinner.data-v-651a9dc3 {
width: 60rpx;
height: 60rpx;
border: 8rpx solid #f3f3f3;
border-top: 8rpx solid #3498db;
border-radius: 50%;
animation: spin-651a9dc3 1s linear infinite;
margin-bottom: 20rpx;
}
.map-container .map-loading .loading-content text.data-v-651a9dc3 {
font-size: 32rpx;
color: #333;
font-weight: 500;
}
.map-container .map-controls.data-v-651a9dc3 {
position: absolute;
right: 30rpx;
bottom: 20rpx;
left: 30rpx;
display: flex;
justify-content: center;
align-items: center;
gap: 30rpx;
}
.map-container .map-controls .control-btn.data-v-651a9dc3 {
min-width: 140rpx;
height: 80rpx;
background: #ffffff;
border-radius: 40rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
transition: all 0.2s ease;
padding: 0 20rpx;
}
.map-container .map-controls .control-btn.data-v-651a9dc3:active {
transform: scale(0.95);
}
.map-container .map-controls .control-btn .control-icon.data-v-651a9dc3 {
width: 32rpx;
height: 32rpx;
margin-right: 12rpx;
}
.map-container .map-controls .control-btn text.data-v-651a9dc3 {
font-size: 26rpx;
color: #333;
white-space: nowrap;
font-weight: 500;
}
.map-container .map-controls .control-btn.main-btn.data-v-651a9dc3 {
min-width: 160rpx;
height: 90rpx;
box-shadow: 0 6rpx 20rpx rgba(33, 150, 243, 0.4);
transform: translateY(-5rpx);
}
.map-container .map-controls .control-btn.main-btn .control-icon.data-v-651a9dc3 {
width: 36rpx;
height: 36rpx;
margin-right: 16rpx;
}
.map-container .map-controls .control-btn.main-btn text.data-v-651a9dc3 {
font-size: 28rpx;
font-weight: 600;
}
.map-container .map-controls .control-btn.main-btn.data-v-651a9dc3:active {
transform: translateY(-5rpx) scale(0.95);
}
.map-container .map-controls .scan-control.data-v-651a9dc3 {
background: #2196F3;
}
.map-container .map-controls .scan-control .control-icon.data-v-651a9dc3 {
filter: brightness(0) invert(1);
}
.map-container .map-controls .scan-control text.data-v-651a9dc3 {
color: #ffffff;
}
.map-container .map-controls .list-control.data-v-651a9dc3 {
background: #4CAF50;
}
.map-container .map-controls .list-control .control-icon.data-v-651a9dc3 {
filter: brightness(0) invert(1);
}
.map-container .map-controls .list-control text.data-v-651a9dc3 {
color: #ffffff;
}
.map-container .map-controls .location-control.data-v-651a9dc3 {
background: #ffffff;
border: 2rpx solid #e0e0e0;
}
.map-container .map-controls .location-control .control-icon.data-v-651a9dc3 {
filter: none;
}
.map-container .map-controls .location-control text.data-v-651a9dc3 {
color: #333;
}
@keyframes spin-651a9dc3 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
+2 -2
View File
@@ -8,7 +8,7 @@ const HELP_CONTENT = {
},
{
question: "收费标准是怎样的?",
answer: "使用费用为2元/小时,不足1小时按1小时计算。押金99元,归还后自动退还。"
answer: "本产品租界风扇采用免押金租借形式,无需支付押金,具体计费方式以场地机柜扫码提示为准。"
},
{
question: "如何归还风扇?",
@@ -28,7 +28,7 @@ const HELP_CONTENT = {
TITLE: "联系客服",
PHONE: {
LABEL: "客服电话",
VALUE: "400-888-8888"
VALUE: "400-077-6018"
},
SERVICE_TIME: {
LABEL: "服务时间",
+38 -35
View File
@@ -10,7 +10,7 @@ const _sfc_main = {
const deviceId = common_vendor.ref("");
const deviceFeeConfig = common_vendor.ref({});
const deviceLocation = common_vendor.ref("一号教学楼大厅");
const batteryLevel = common_vendor.ref(95);
common_vendor.ref(95);
const hasActiveOrder = common_vendor.ref(false);
const deviceStatus = common_vendor.reactive({
text: "可使用",
@@ -20,29 +20,35 @@ const _sfc_main = {
const phoneNumber = common_vendor.ref("");
const showPhoneAuthPopup = common_vendor.ref(false);
common_vendor.onLoad((options) => {
if (options.deviceNo != common_vendor.index.getStorageSync("deviceId") || !common_vendor.index.getStorageSync("deviceId")) {
deviceId.value = options.deviceNo;
common_vendor.index.setStorageSync("deviceId", options.deviceNo);
} else {
deviceId.value = common_vendor.index.getStorageSync("deviceId");
}
checkOrderStatus();
common_vendor.index.__f__("log", "at pages/device/detail.vue:200", options.deviceNo);
fetchDeviceInfo();
});
common_vendor.onMounted(() => {
checkUserPhone();
common_vendor.onMounted(async () => {
await checkUserPhone();
});
common_vendor.onShow(async () => {
await fetchDeviceInfo();
});
const checkUserPhone = async () => {
try {
const userInfoRes = await util_index.getUserInfo();
common_vendor.index.__f__("log", "at pages/device/detail.vue:211", userInfoRes.data.phone, "getUserInfoPhone");
common_vendor.index.__f__("log", "at pages/device/detail.vue:220", userInfoRes.data.phone, "getUserInfoPhone");
if (userInfoRes.code == 200 && userInfoRes.data && userInfoRes.data.phone) {
phoneNumber.value = userInfoRes.data.phone;
} else {
showPhoneAuthPopup.value = true;
}
} catch (error) {
common_vendor.index.__f__("error", "at pages/device/detail.vue:220", "获取用户信息失败:", error);
common_vendor.index.__f__("error", "at pages/device/detail.vue:229", "获取用户信息失败:", error);
}
};
const onGetPhoneNumber = (e) => {
common_vendor.index.__f__("log", "at pages/device/detail.vue:226", "getPhoneNumber event:", e.detail);
common_vendor.index.__f__("log", "at pages/device/detail.vue:235", "getPhoneNumber event:", e.detail);
if (e.detail.errMsg && e.detail.errMsg.includes("deny")) {
common_vendor.index.showToast({
title: "需要授权手机号才能使用设备",
@@ -54,13 +60,13 @@ const _sfc_main = {
common_vendor.index.showLoading({
title: "获取中..."
});
common_vendor.index.__f__("log", "at pages/device/detail.vue:243", "获取到的授权code:", e.detail.code);
common_vendor.index.__f__("log", "at pages/device/detail.vue:252", "获取到的授权code:", e.detail.code);
try {
util_index.getUserPhoneNumber(e.detail.code).then((res) => {
common_vendor.index.__f__("log", "at pages/device/detail.vue:249", "获取手机号API响应原始数据:", JSON.stringify(res));
common_vendor.index.__f__("log", "at pages/device/detail.vue:258", "获取手机号API响应原始数据:", JSON.stringify(res));
common_vendor.index.hideLoading();
if (!res) {
common_vendor.index.__f__("error", "at pages/device/detail.vue:254", "API返回数据为空");
common_vendor.index.__f__("error", "at pages/device/detail.vue:263", "API返回数据为空");
common_vendor.index.showModal({
title: "数据异常",
content: "API返回为空",
@@ -68,8 +74,8 @@ const _sfc_main = {
});
return;
}
common_vendor.index.__f__("log", "at pages/device/detail.vue:264", "响应code:", res.code, "响应类型:", typeof res.code);
common_vendor.index.__f__("log", "at pages/device/detail.vue:265", "是否有data:", !!res.data, "是否有phone:", res.data && !!res.data.phone);
common_vendor.index.__f__("log", "at pages/device/detail.vue:273", "响应code:", res.code, "响应类型:", typeof res.code);
common_vendor.index.__f__("log", "at pages/device/detail.vue:274", "是否有data:", !!res.data, "是否有phone:", res.data && !!res.data.phone);
if (res.code == 200 && res.data && res.data.phoneNumber) {
phoneNumber.value = res.data.phoneNumber;
showPhoneAuthPopup.value = false;
@@ -78,7 +84,7 @@ const _sfc_main = {
icon: "success"
});
} else {
common_vendor.index.__f__("warn", "at pages/device/detail.vue:277", "获取手机号响应异常:", res.msg || "未知错误");
common_vendor.index.__f__("warn", "at pages/device/detail.vue:286", "获取手机号响应异常:", res.msg || "未知错误");
common_vendor.index.showModal({
title: "获取手机号异常",
content: `状态码: ${res.code}, 消息: ${res.msg || "无"}`,
@@ -87,7 +93,7 @@ const _sfc_main = {
}
}).catch((err) => {
common_vendor.index.hideLoading();
common_vendor.index.__f__("error", "at pages/device/detail.vue:287", "获取手机号码失败(catch):", err);
common_vendor.index.__f__("error", "at pages/device/detail.vue:296", "获取手机号码失败(catch):", err);
let errMsg = err.message || err.toString();
common_vendor.index.showModal({
title: "获取手机号失败",
@@ -97,7 +103,7 @@ const _sfc_main = {
});
} catch (outerError) {
common_vendor.index.hideLoading();
common_vendor.index.__f__("error", "at pages/device/detail.vue:299", "获取手机号外部错误:", outerError);
common_vendor.index.__f__("error", "at pages/device/detail.vue:308", "获取手机号外部错误:", outerError);
common_vendor.index.showModal({
title: "意外错误",
content: "处理过程发生异常: " + (outerError.message || outerError),
@@ -129,7 +135,7 @@ const _sfc_main = {
deviceStatus.class = "offline";
}
}
common_vendor.index.__f__("log", "at pages/device/detail.vue:337", "feeconfig", deviceInfo.value.feeConfig);
common_vendor.index.__f__("log", "at pages/device/detail.vue:346", "feeconfig", deviceInfo.value.feeConfig);
deviceFeeConfig.value = JSON.parse(deviceInfo.value.feeConfig)[0] || {};
}
};
@@ -210,17 +216,17 @@ const _sfc_main = {
packagePrice: parseFloat(selectedPkg.price)
});
if (updateRes.code !== 200) {
common_vendor.index.__f__("warn", "at pages/device/detail.vue:445", "更新订单套餐信息失败:", updateRes.msg);
common_vendor.index.__f__("warn", "at pages/device/detail.vue:454", "更新订单套餐信息失败:", updateRes.msg);
} else {
common_vendor.index.__f__("log", "at pages/device/detail.vue:448", "订单套餐信息已提前更新");
common_vendor.index.__f__("log", "at pages/device/detail.vue:457", "订单套餐信息已提前更新");
}
} catch (updateError) {
common_vendor.index.__f__("error", "at pages/device/detail.vue:451", "更新订单套餐信息时出错:", updateError);
common_vendor.index.__f__("error", "at pages/device/detail.vue:460", "更新订单套餐信息时出错:", updateError);
}
if (payWay == "wx-pay") {
common_vendor.index.hideLoading();
const res = await config_user.getOrderByOrderNo(order.orderNo);
common_vendor.index.__f__("log", "at pages/device/detail.vue:460", res);
common_vendor.index.__f__("log", "at pages/device/detail.vue:469", res);
const deposit = parseFloat(deviceInfo.value.depositAmount);
const packagePrice = parseFloat(selectedPkg.price);
const totalAmount = (deposit + packagePrice).toFixed(2);
@@ -237,7 +243,7 @@ const _sfc_main = {
const payResult = await util_index.initiateWeChatScorePayment(res);
if (payResult.errCode == "0") {
const res2 = await config_user.getOrderByOrderNoScorePayStatus(order.orderNo);
common_vendor.index.__f__("log", "at pages/device/detail.vue:488", res2.data.orderStatus);
common_vendor.index.__f__("log", "at pages/device/detail.vue:497", res2.data.orderStatus);
if (res2.data.orderStatus == "in_used") {
common_vendor.index.showToast({
title: "设备租借成功",
@@ -291,21 +297,18 @@ const _sfc_main = {
c: common_vendor.t(deviceId.value),
d: common_assets._imports_0$3,
e: common_vendor.t(deviceLocation.value),
f: common_assets._imports_1$2,
g: batteryLevel.value < 20 ? 1 : "",
h: common_vendor.t(batteryLevel.value),
i: common_vendor.t(deviceFeeConfig.value.maxHourPrice),
j: common_vendor.t(deviceInfo.value.depositAmount),
k: common_vendor.t(hasActiveOrder.value ? "归还设备" : "免押租借"),
l: hasActiveOrder.value ? 1 : "",
m: common_vendor.o(($event) => handleRent("wx-score-pay")),
n: common_assets._imports_0$2,
o: showPhoneAuthPopup.value
f: common_vendor.t(deviceFeeConfig.value.maxHourPrice),
g: common_vendor.t(deviceInfo.value.depositAmount),
h: common_vendor.t(hasActiveOrder.value ? "归还设备" : "免押租借"),
i: hasActiveOrder.value ? 1 : "",
j: common_vendor.o(($event) => handleRent("wx-score-pay")),
k: common_assets._imports_0$2,
l: showPhoneAuthPopup.value
}, showPhoneAuthPopup.value ? {
p: common_vendor.o(() => {
m: common_vendor.o(() => {
}),
q: common_vendor.o(onGetPhoneNumber),
r: common_vendor.o(($event) => showPhoneAuthPopup.value = false)
n: common_vendor.o(onGetPhoneNumber),
o: common_vendor.o(($event) => showPhoneAuthPopup.value = false)
} : {});
};
}
+1 -1
View File
@@ -1 +1 @@
<view class="container data-v-d65de3a7"><view class="device-header data-v-d65de3a7"><view class="{{['device-status-card', 'data-v-d65de3a7', b]}}"><view class="status-indicator data-v-d65de3a7"></view><text class="status-text data-v-d65de3a7">{{a}}</text></view><view class="device-title data-v-d65de3a7"><text class="name data-v-d65de3a7">共享风扇</text><view class="device-meta data-v-d65de3a7"><text class="id-label data-v-d65de3a7">设备号:</text><text class="id-value data-v-d65de3a7">{{c}}</text></view></view></view><view class="card device-info-card data-v-d65de3a7"><view class="card-row data-v-d65de3a7"><view class="card-item data-v-d65de3a7"><view class="item-icon location-icon data-v-d65de3a7"><image class="data-v-d65de3a7" src="{{d}}" mode="aspectFill" style="width:45rpx;height:45rpx"></image></view><view class="item-content data-v-d65de3a7"><text class="item-label data-v-d65de3a7">当前位置</text><text class="item-value data-v-d65de3a7">{{e}}</text></view></view><view class="card-item data-v-d65de3a7"><view class="{{['item-icon', 'battery-icon', 'data-v-d65de3a7', g && 'battery-low']}}"><image class="data-v-d65de3a7" src="{{f}}" mode="aspectFill" style="width:45rpx;height:45rpx"></image></view><view class="item-content data-v-d65de3a7"><text class="item-label data-v-d65de3a7">电池电量</text><text class="item-value data-v-d65de3a7">{{h}}%</text></view></view></view></view><view class="card pricing-card data-v-d65de3a7"><view class="card-header data-v-d65de3a7"><text class="card-title data-v-d65de3a7">计费规则</text></view><view class="pricing-banner data-v-d65de3a7"><view class="pricing-main data-v-d65de3a7"><text class="price data-v-d65de3a7">¥{{i}}</text><text class="unit data-v-d65de3a7">/小时</text></view><text class="cap-price data-v-d65de3a7">封顶 ¥{{j}}</text></view><view class="pricing-rules data-v-d65de3a7"><view class="rule-item data-v-d65de3a7"><view class="rule-dot data-v-d65de3a7"></view><text class="rule-text data-v-d65de3a7">不足60分钟按60分钟计费</text></view><view class="rule-item data-v-d65de3a7"><view class="rule-dot data-v-d65de3a7"></view><text class="rule-text data-v-d65de3a7">持续计费至99元视为买断</text></view></view></view><view class="card notice-card data-v-d65de3a7"><view class="card-header data-v-d65de3a7"><text class="card-title data-v-d65de3a7">使用须知</text></view><view class="notice-items data-v-d65de3a7"><view class="notice-item data-v-d65de3a7"><view class="notice-dot data-v-d65de3a7"></view><text class="notice-text data-v-d65de3a7">请在使用前检查设备是否完好</text></view><view class="notice-item data-v-d65de3a7"><view class="notice-dot data-v-d65de3a7"></view><text class="notice-text data-v-d65de3a7">请在指定区域内使用设备</text></view><view class="notice-item data-v-d65de3a7"><view class="notice-dot data-v-d65de3a7"></view><text class="notice-text data-v-d65de3a7">归还时请确保设备完好,避免损坏</text></view></view></view><view class="footer data-v-d65de3a7"><button class="{{['rent-button', 'data-v-d65de3a7', l && 'return-button']}}" bindtap="{{m}}"><text class="data-v-d65de3a7">{{k}}</text></button><view class="wechat-credit data-v-d65de3a7"><image src="{{n}}" mode="aspectFit" class="wx-icon data-v-d65de3a7"></image><view class="credit-text data-v-d65de3a7"><text class="data-v-d65de3a7">微信支付分</text><text class="credit-divider data-v-d65de3a7">|</text><text class="credit-score data-v-d65de3a7">550分及以上优享</text></view></view></view><view wx:if="{{o}}" class="phone-auth-popup data-v-d65de3a7"><view class="popup-mask data-v-d65de3a7" catchtap="{{p}}"></view><view class="popup-content data-v-d65de3a7"><view class="popup-header data-v-d65de3a7"><text class="popup-title data-v-d65de3a7">授权获取手机号</text></view><view class="popup-body data-v-d65de3a7"><view class="auth-desc data-v-d65de3a7"><text class="data-v-d65de3a7">为了提供更好的服务,需要授权获取您的手机号</text></view><button class="auth-btn data-v-d65de3a7" open-type="getPhoneNumber" bindgetphonenumber="{{q}}"> 一键获取手机号 </button><view class="auth-cancel data-v-d65de3a7" bindtap="{{r}}"><text class="data-v-d65de3a7">暂不授权</text></view></view></view></view></view>
<view class="container data-v-d65de3a7"><view class="device-header data-v-d65de3a7"><view class="{{['device-status-card', 'data-v-d65de3a7', b]}}"><view class="status-indicator data-v-d65de3a7"></view><text class="status-text data-v-d65de3a7">{{a}}</text></view><view class="device-title data-v-d65de3a7"><text class="name data-v-d65de3a7">共享风扇</text><view class="device-meta data-v-d65de3a7"><text class="id-label data-v-d65de3a7">设备号:</text><text class="id-value data-v-d65de3a7">{{c}}</text></view></view></view><view class="card device-info-card data-v-d65de3a7"><view class="card-row data-v-d65de3a7"><view class="card-item data-v-d65de3a7"><view class="item-icon location-icon data-v-d65de3a7"><image class="data-v-d65de3a7" src="{{d}}" mode="aspectFill" style="width:45rpx;height:45rpx"></image></view><view class="item-content data-v-d65de3a7"><text class="item-label data-v-d65de3a7">当前位置</text><text class="item-value data-v-d65de3a7">{{e}}</text></view></view></view></view><view class="card pricing-card data-v-d65de3a7"><view class="card-header data-v-d65de3a7"><text class="card-title data-v-d65de3a7">计费规则</text></view><view class="pricing-banner data-v-d65de3a7"><view class="pricing-main data-v-d65de3a7"><text class="price data-v-d65de3a7">¥{{f}}</text><text class="unit data-v-d65de3a7">/小时</text></view><text class="cap-price data-v-d65de3a7">封顶 ¥{{g}}</text></view><view class="pricing-rules data-v-d65de3a7"><view class="rule-item data-v-d65de3a7"><view class="rule-dot data-v-d65de3a7"></view><text class="rule-text data-v-d65de3a7">不足60分钟按60分钟计费</text></view><view class="rule-item data-v-d65de3a7"><view class="rule-dot data-v-d65de3a7"></view><text class="rule-text data-v-d65de3a7">持续计费至99元视为买断</text></view></view></view><view class="card notice-card data-v-d65de3a7"><view class="card-header data-v-d65de3a7"><text class="card-title data-v-d65de3a7">使用须知</text></view><view class="notice-items data-v-d65de3a7"><view class="notice-item data-v-d65de3a7"><view class="notice-dot data-v-d65de3a7"></view><text class="notice-text data-v-d65de3a7">请在使用前检查设备是否完好</text></view><view class="notice-item data-v-d65de3a7"><view class="notice-dot data-v-d65de3a7"></view><text class="notice-text data-v-d65de3a7">请在指定区域内使用设备</text></view><view class="notice-item data-v-d65de3a7"><view class="notice-dot data-v-d65de3a7"></view><text class="notice-text data-v-d65de3a7">归还时请确保设备完好,避免损坏</text></view></view></view><view class="footer data-v-d65de3a7"><button class="{{['rent-button', 'data-v-d65de3a7', i && 'return-button']}}" bindtap="{{j}}"><text class="data-v-d65de3a7">{{h}}</text></button><view class="wechat-credit data-v-d65de3a7"><image src="{{k}}" mode="aspectFit" class="wx-icon data-v-d65de3a7"></image><view class="credit-text data-v-d65de3a7"><text class="data-v-d65de3a7">微信支付分</text><text class="credit-divider data-v-d65de3a7">|</text><text class="credit-score data-v-d65de3a7">550分及以上优享</text></view></view></view><view wx:if="{{l}}" class="phone-auth-popup data-v-d65de3a7"><view class="popup-mask data-v-d65de3a7" catchtap="{{m}}"></view><view class="popup-content data-v-d65de3a7"><view class="popup-header data-v-d65de3a7"><text class="popup-title data-v-d65de3a7">授权获取手机号</text></view><view class="popup-body data-v-d65de3a7"><view class="auth-desc data-v-d65de3a7"><text class="data-v-d65de3a7">为了提供更好的服务,需要授权获取您的手机号</text></view><button class="auth-btn data-v-d65de3a7" open-type="getPhoneNumber" bindgetphonenumber="{{n}}"> 一键获取手机号 </button><view class="auth-cancel data-v-d65de3a7" bindtap="{{o}}"><text class="data-v-d65de3a7">暂不授权</text></view></view></view></view></view>
+286 -30
View File
@@ -1,12 +1,215 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const common_assets = require("../../common/assets.js");
const util_index = require("../../util/index.js");
const config_url = require("../../config/url.js");
const config_user = require("../../config/user.js");
const common_assets = require("../../common/assets.js");
const utils_amap = require("../../utils/amap.js");
if (!Math) {
MapComponent();
}
const MapComponent = () => "../../components/MapComponent.js";
const _sfc_main = {
methods: {
async handleScan() {
__name: "index",
setup(__props) {
const searchKeyword = common_vendor.ref("");
const userLocation = common_vendor.ref(null);
const positionList = common_vendor.ref([]);
const filteredPositions = common_vendor.ref([]);
const isExpanded = common_vendor.ref(false);
const isLoading = common_vendor.ref(false);
const showPhoneAuthPopup = common_vendor.ref(false);
const isLocationInitialized = common_vendor.ref(false);
const showLocationPopup = common_vendor.ref(false);
const mapRef = common_vendor.ref(null);
common_vendor.computed(() => {
if (userLocation.value && userLocation.value.address) {
return `${userLocation.value.district || "当前位置"} - 搜索附近场地`;
}
return "搜索附近场地";
});
common_vendor.onMounted(() => {
init();
});
common_vendor.onUnmounted(() => {
});
const init = async () => {
isLoading.value = true;
try {
await getUserLocation();
await loadPositions();
} catch (error) {
common_vendor.index.__f__("error", "at pages/index/index.vue:177", "初始化失败:", error);
await loadPositions();
} finally {
isLoading.value = false;
}
};
const getUserLocation = async () => {
try {
const location = await new Promise((resolve, reject) => {
common_vendor.index.getLocation({
type: "gcj02",
success: resolve,
fail: reject
});
});
userLocation.value = {
longitude: location.longitude,
latitude: location.latitude
};
if (!isLocationInitialized.value) {
isLocationInitialized.value = true;
}
try {
const addressResult = await utils_amap.AmapUtil.regeocode(location.longitude, location.latitude);
if (addressResult.success) {
const addressInfo = addressResult.data;
userLocation.value.address = addressInfo.formatted_address;
userLocation.value.city = addressInfo.addressComponent.city;
userLocation.value.district = addressInfo.addressComponent.district;
}
} catch (error) {
}
setTimeout(async () => {
await loadPositions();
common_vendor.index.hideLoading();
common_vendor.index.showToast({
title: "定位成功",
icon: "success"
});
}, 800);
} catch (error) {
common_vendor.index.__f__("error", "at pages/index/index.vue:231", "获取位置失败:", error);
common_vendor.index.showToast({
title: "获取位置失败,显示默认地图",
icon: "none"
});
}
};
const loadPositions = async () => {
try {
if (!common_vendor.index.getStorageSync("token")) {
await util_index.wxLogin();
}
const res = await common_vendor.index.request({
url: `${config_url.URL}/device/position/list`,
method: "GET",
header: {
"Authorization": "Bearer " + common_vendor.index.getStorageSync("token"),
"Clientid": common_vendor.index.getStorageSync("client_id")
}
});
if (res.statusCode === 200 && res.data.code === 200) {
positionList.value = res.data.rows || [];
calculateDistances();
filteredPositions.value = [...positionList.value];
} else {
common_vendor.index.__f__("error", "at pages/index/index.vue:259", "获取场地列表失败:", res.data.msg);
}
} catch (error) {
common_vendor.index.__f__("error", "at pages/index/index.vue:262", "获取场地列表异常:", error);
}
};
const calculateDistances = (centerPoint = null) => {
var _a;
const center = centerPoint || userLocation.value || ((_a = mapRef.value) == null ? void 0 : _a.mapCenter);
if (!center || typeof center.longitude === "undefined" || typeof center.latitude === "undefined") {
return;
}
positionList.value.forEach((item) => {
if (item.longitude && item.latitude) {
try {
const distance = utils_amap.AmapUtil.calculateDistance(
center.latitude,
center.longitude,
parseFloat(item.latitude),
parseFloat(item.longitude)
);
item.distance = distance.toFixed(1);
} catch (error) {
common_vendor.index.__f__("error", "at pages/index/index.vue:286", "计算距离异常:", error, item);
item.distance = "999.0";
}
}
});
positionList.value.sort((a, b) => {
return (parseFloat(a.distance) || 999) - (parseFloat(b.distance) || 999);
});
};
const loadPositionsByCenter = async (center) => {
try {
if (!common_vendor.index.getStorageSync("token")) {
await util_index.wxLogin();
}
const res = await common_vendor.index.request({
url: `${config_url.URL}/device/position/list`,
method: "GET",
header: {
"Authorization": "Bearer " + common_vendor.index.getStorageSync("token"),
"Clientid": common_vendor.index.getStorageSync("client_id")
}
});
if (res.statusCode === 200 && res.data.code === 200) {
positionList.value = res.data.rows || [];
calculateDistances(center);
const maxDistance = 10;
filteredPositions.value = positionList.value.filter((item) => {
return !item.distance || parseFloat(item.distance) <= maxDistance;
});
} else {
common_vendor.index.__f__("error", "at pages/index/index.vue:326", "根据地图中心加载场地失败:", res.data.msg);
positionList.value = [];
filteredPositions.value = [];
}
} catch (error) {
common_vendor.index.__f__("error", "at pages/index/index.vue:331", "根据地图中心加载场地异常:", error);
}
};
const handleRelocate = async () => {
common_vendor.index.showLoading({ title: "定位中..." });
common_vendor.index.reLaunch({
url: "/pages/index/index"
});
};
const onMapCenterChange = (center) => {
loadPositionsByCenter(center);
};
const selectPosition = (position) => {
common_vendor.index.showActionSheet({
itemList: ["扫码使用", "导航前往"],
success: (res) => {
switch (res.tapIndex) {
case 0:
handleScan();
break;
case 1:
navigateToPosition(position);
break;
}
}
});
};
const selectPositionFromPopup = (position) => {
hideLocationList();
setTimeout(() => {
selectPosition(position);
}, 200);
};
const navigateToPosition = (position) => {
const latitude = parseFloat(position.latitude);
const longitude = parseFloat(position.longitude);
common_vendor.index.openLocation({
latitude,
longitude,
name: position.name,
address: position.location
});
};
const toggleSheet = () => {
isExpanded.value = !isExpanded.value;
};
const handleScan = async () => {
try {
const scanResult = await new Promise((resolve, reject) => {
common_vendor.index.scanCode({
@@ -14,7 +217,6 @@ const _sfc_main = {
fail: reject
});
});
common_vendor.index.__f__("log", "at pages/index/index.vue:152", scanResult.path);
let deviceNo = util_index.getQueryString(scanResult.path, "deviceNo");
if (!deviceNo) {
common_vendor.index.showToast({
@@ -27,7 +229,7 @@ const _sfc_main = {
await util_index.wxLogin();
}
const inUseRes = await common_vendor.index.request({
url: `${config_url.URL || "http://127.0.0.1:8080"}/app/order/inUse`,
url: `${config_url.URL}/app/order/inUse`,
method: "GET",
header: {
"Authorization": "Bearer " + common_vendor.index.getStorageSync("token"),
@@ -39,18 +241,16 @@ const _sfc_main = {
common_vendor.index.reLaunch({
url: `/pages/return/index?orderId=${inUseOrder.orderId}&deviceId=${deviceNo || inUseOrder.deviceNo}`
});
common_vendor.index.__f__("log", "at pages/index/index.vue:187", "已发起页面跳转");
return;
}
const orderRes = await common_vendor.index.request({
url: `${config_url.URL || "http://127.0.0.1:8080"}/app/order/unpaid`,
url: `${config_url.URL}/app/order/unpaid`,
method: "GET",
header: {
"Authorization": "Bearer " + common_vendor.index.getStorageSync("token"),
"Clientid": common_vendor.index.getStorageSync("client_id")
}
});
common_vendor.index.__f__("log", "at pages/index/index.vue:201", "待支付订单检查结果:", JSON.stringify(orderRes));
if (orderRes.statusCode == 200 && orderRes.data.code == 200 && orderRes.data.data) {
const unpaidOrder = orderRes.data.data;
common_vendor.index.navigateTo({
@@ -62,14 +262,12 @@ const _sfc_main = {
if (deviceInfoRes.code == 200 && deviceInfoRes.data && deviceInfoRes.data.device) {
const deviceInfo = deviceInfoRes.data.device;
if (deviceInfo.feeConfig) {
common_vendor.index.__f__("log", "at pages/index/index.vue:219", "获取到设备feeConfig信息:", deviceInfo.feeConfig);
try {
const feeConfig = JSON.parse(deviceInfo.feeConfig);
common_vendor.index.navigateTo({
url: `/pages/device/detail?deviceNo=${deviceNo}&feeConfig=${encodeURIComponent(deviceInfo.feeConfig)}`
});
} catch (e) {
common_vendor.index.__f__("error", "at pages/index/index.vue:230", "解析feeConfig失败:", e);
common_vendor.index.navigateTo({
url: `/pages/device/detail?deviceNo=${deviceNo}`
});
@@ -80,7 +278,6 @@ const _sfc_main = {
});
}
} else {
common_vendor.index.__f__("error", "at pages/index/index.vue:244", "获取设备信息失败:", deviceInfoRes.msg || "未知错误");
common_vendor.index.showToast({
title: "获取设备信息失败",
icon: "none"
@@ -90,38 +287,97 @@ const _sfc_main = {
});
}
} catch (error) {
common_vendor.index.__f__("error", "at pages/index/index.vue:256", "获取设备信息异常:", error);
common_vendor.index.showToast({
title: "获取设备信息失败",
icon: "none"
});
common_vendor.index.__f__("error", "at pages/index/index.vue:492", "获取设备信息异常:", error);
common_vendor.index.navigateTo({
url: `/pages/device/detail?deviceNo=${deviceNo}`
});
}
}
} catch (error) {
common_vendor.index.__f__("error", "at pages/index/index.vue:269", "扫码处理失败:", error);
common_vendor.index.__f__("error", "at pages/index/index.vue:499", "扫码处理失败:", error);
common_vendor.index.showToast({
title: "扫码失败",
icon: "none"
});
}
};
const showLocationList = () => {
showLocationPopup.value = true;
};
const hideLocationList = () => {
showLocationPopup.value = false;
};
const onGetPhoneNumber = (e) => {
if (e.detail.errMsg === "getPhoneNumber:ok") {
showPhoneAuthPopup.value = false;
}
};
return (_ctx, _cache) => {
return common_vendor.e({
a: !isLoading.value && userLocation.value
}, !isLoading.value && userLocation.value ? {
b: common_vendor.sr(mapRef, "1cf27b2a-0", {
"k": "mapRef"
}),
c: common_vendor.o(handleRelocate),
d: common_vendor.o(handleScan),
e: common_vendor.o(showLocationList),
f: common_vendor.o(selectPosition),
g: common_vendor.o(onMapCenterChange),
h: common_vendor.p({
userLocation: userLocation.value,
positionList: positionList.value,
filteredPositions: filteredPositions.value,
searchKeyword: searchKeyword.value
})
} : {}, {
i: isLoading.value || !userLocation.value
}, isLoading.value || !userLocation.value ? {} : {}, {
j: showLocationPopup.value
}, showLocationPopup.value ? common_vendor.e({
k: common_vendor.o(hideLocationList),
l: common_vendor.o(toggleSheet),
m: common_vendor.t(filteredPositions.value.length),
n: common_assets._imports_0,
o: common_vendor.o(hideLocationList),
p: common_vendor.f(filteredPositions.value, (item, index, i0) => {
return common_vendor.e({
a: common_vendor.t(item.name),
b: common_vendor.t(item.describe),
c: common_vendor.t(item.location),
d: item.workTime && item.workTime !== "0"
}, item.workTime && item.workTime !== "0" ? {
e: common_vendor.t(item.workTime)
} : {}, {
f: item.distance
}, item.distance ? {
g: common_vendor.t(item.distance)
} : {}, {
h: common_vendor.t(item.status === "online" ? "营业中" : "暂停服务"),
i: common_vendor.n(item.status),
j: common_vendor.o(($event) => navigateToPosition(item), item.positionId),
k: item.positionId,
l: common_vendor.o(($event) => selectPositionFromPopup(item), item.positionId)
});
}),
q: common_assets._imports_0,
r: filteredPositions.value.length === 0 && !isLoading.value
}, filteredPositions.value.length === 0 && !isLoading.value ? {
s: common_assets._imports_0
} : {}, {
t: isExpanded.value ? 1 : ""
}) : {}, {
v: isLoading.value
}, isLoading.value ? {} : {}, {
w: showPhoneAuthPopup.value
}, showPhoneAuthPopup.value ? {
x: common_vendor.o(($event) => showPhoneAuthPopup.value = false),
y: common_vendor.o(onGetPhoneNumber),
z: common_vendor.o(($event) => showPhoneAuthPopup.value = false)
} : {});
};
}
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return common_vendor.e({
a: common_assets._imports_0,
b: common_assets._imports_1,
c: common_vendor.o((...args) => $options.handleScan && $options.handleScan(...args)),
d: _ctx.showPhoneAuthPopup
}, _ctx.showPhoneAuthPopup ? {
e: common_vendor.o(($event) => _ctx.showPhoneAuthPopup = false),
f: common_vendor.o((...args) => _ctx.onGetPhoneNumber && _ctx.onGetPhoneNumber(...args)),
g: common_vendor.o(($event) => _ctx.showPhoneAuthPopup = false)
} : {});
}
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-1cf27b2a"]]);
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-1cf27b2a"]]);
wx.createPage(MiniProgramPage);
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/index/index.js.map
+4 -2
View File
@@ -1,4 +1,6 @@
{
"navigationBarTitleText": "共享风扇",
"usingComponents": {}
"navigationBarTitleText": "附近场地",
"usingComponents": {
"map-component": "../../components/MapComponent"
}
}
+1 -1
View File
@@ -1 +1 @@
<view class="container data-v-1cf27b2a"><view class="header data-v-1cf27b2a"><view class="header-bg data-v-1cf27b2a"><view class="circle-decoration circle-1 data-v-1cf27b2a"></view><view class="circle-decoration circle-2 data-v-1cf27b2a"></view><view class="wave-decoration data-v-1cf27b2a"></view></view><view class="header-content data-v-1cf27b2a"><view class="brand-area data-v-1cf27b2a"><image class="brand-logo data-v-1cf27b2a" src="{{a}}" mode="aspectFit"></image><view class="brand-text data-v-1cf27b2a"><text class="title data-v-1cf27b2a">共享风扇</text><text class="subtitle data-v-1cf27b2a">随时随地,享受清凉</text></view></view><view class="header-info data-v-1cf27b2a"><view class="service-tag data-v-1cf27b2a"><text class="data-v-1cf27b2a">便捷租赁</text><text class="dot data-v-1cf27b2a">·</text><text class="data-v-1cf27b2a">品质保障</text></view></view></view></view><view class="scan-section data-v-1cf27b2a"><view class="scan-card data-v-1cf27b2a"><view class="scan-btn data-v-1cf27b2a" bindtap="{{c}}"><image class="scan-icon data-v-1cf27b2a" src="{{b}}" mode="aspectFit"/><text class="scan-text data-v-1cf27b2a">扫码使用</text></view><view class="scan-desc data-v-1cf27b2a"><text class="data-v-1cf27b2a">扫描设备二维码即可使用或归还</text></view></view></view><view class="price-card data-v-1cf27b2a"><view class="card-header data-v-1cf27b2a"><text class="card-title data-v-1cf27b2a">收费规则</text></view><view class="price-rules data-v-1cf27b2a"><view class="price-item data-v-1cf27b2a"><view class="price-tag data-v-1cf27b2a">5.0<text class="unit data-v-1cf27b2a">元/小时</text></view></view><view class="divider data-v-1cf27b2a"></view><view class="rule-list data-v-1cf27b2a"><view class="rule-item data-v-1cf27b2a"><view class="rule-dot data-v-1cf27b2a"></view><text class="data-v-1cf27b2a">不足1小时按1小时计费</text></view><view class="rule-item data-v-1cf27b2a"><view class="rule-dot data-v-1cf27b2a"></view><text class="data-v-1cf27b2a">封顶99元,计费达99元视为买断</text></view></view></view></view><view class="usage-steps data-v-1cf27b2a"><view class="steps-header data-v-1cf27b2a"><text class="steps-title data-v-1cf27b2a">使用流程</text></view><view class="steps-container data-v-1cf27b2a"><view class="step-item data-v-1cf27b2a"><view class="step-icon data-v-1cf27b2a"><text class="step-number data-v-1cf27b2a">1</text></view><text class="step-text data-v-1cf27b2a">扫码弹出</text></view><view class="step-arrow data-v-1cf27b2a"></view><view class="step-item data-v-1cf27b2a"><view class="step-icon data-v-1cf27b2a"><text class="step-number data-v-1cf27b2a">2</text></view><text class="step-text data-v-1cf27b2a">使用风扇</text></view><view class="step-arrow data-v-1cf27b2a"></view><view class="step-item data-v-1cf27b2a"><view class="step-icon data-v-1cf27b2a"><text class="step-number data-v-1cf27b2a">3</text></view><text class="step-text data-v-1cf27b2a">插入归还</text></view><view class="step-arrow data-v-1cf27b2a"></view><view class="step-item data-v-1cf27b2a"><view class="step-icon data-v-1cf27b2a"><text class="step-number data-v-1cf27b2a">4</text></view><text class="step-text data-v-1cf27b2a">结束订单</text></view></view></view><view wx:if="{{d}}" class="phone-auth-popup data-v-1cf27b2a"><view class="popup-mask data-v-1cf27b2a" catchtap="{{e}}"></view><view class="popup-content data-v-1cf27b2a"><view class="popup-header data-v-1cf27b2a"><text class="popup-title data-v-1cf27b2a">授权获取手机号</text></view><view class="popup-body data-v-1cf27b2a"><view class="auth-desc data-v-1cf27b2a"><text class="data-v-1cf27b2a">为了提供更好的服务和紧急联系,需要授权获取您的手机号</text></view><button class="auth-btn data-v-1cf27b2a" open-type="getPhoneNumber" bindgetphonenumber="{{f}}"><text class="data-v-1cf27b2a">一键获取手机号</text></button><view class="auth-cancel data-v-1cf27b2a" bindtap="{{g}}"><text class="data-v-1cf27b2a">暂不授权</text></view></view></view></view></view>
<view class="container data-v-1cf27b2a"><map-component wx:if="{{a}}" class="r data-v-1cf27b2a" u-r="mapRef" bindrelocate="{{c}}" bindscan="{{d}}" bindshowList="{{e}}" bindmarkerTap="{{f}}" bindmapCenterChange="{{g}}" u-i="1cf27b2a-0" bind:__l="__l" u-p="{{h}}"/><view wx:if="{{i}}" class="map-loading-placeholder data-v-1cf27b2a"><view class="loading-content data-v-1cf27b2a"><view class="loading-spinner data-v-1cf27b2a"></view><text class="data-v-1cf27b2a">正在获取位置信息...</text></view></view><view wx:if="{{j}}" class="location-popup data-v-1cf27b2a"><view class="popup-mask data-v-1cf27b2a" bindtap="{{k}}"></view><view class="{{['location-sheet', 'data-v-1cf27b2a', t && 'expanded']}}"><view class="sheet-handle data-v-1cf27b2a" bindtap="{{l}}"><view class="handle-bar data-v-1cf27b2a"></view></view><view class="sheet-header data-v-1cf27b2a"><text class="sheet-title data-v-1cf27b2a">附近场地 ({{m}})</text><view class="close-btn data-v-1cf27b2a" bindtap="{{o}}"><image class="close-icon data-v-1cf27b2a" src="{{n}}" mode="aspectFit"/></view></view><scroll-view class="sheet-content data-v-1cf27b2a" scroll-y="true"><view wx:for="{{p}}" wx:for-item="item" wx:key="k" class="position-item data-v-1cf27b2a" bindtap="{{item.l}}"><view class="position-info data-v-1cf27b2a"><view class="position-name data-v-1cf27b2a">{{item.a}}</view><view class="position-desc data-v-1cf27b2a">{{item.b}}</view><view class="position-location data-v-1cf27b2a"><image class="location-icon-small data-v-1cf27b2a" src="{{q}}" mode="aspectFit"/><text class="data-v-1cf27b2a">{{item.c}}</text></view><view wx:if="{{item.d}}" class="position-time data-v-1cf27b2a"><text class="data-v-1cf27b2a">营业时间:{{item.e}}</text></view></view><view class="position-actions data-v-1cf27b2a"><view wx:if="{{item.f}}" class="distance-info data-v-1cf27b2a"><text class="data-v-1cf27b2a">{{item.g}}km</text></view><view class="{{['status-tag', 'data-v-1cf27b2a', item.i]}}"><text class="data-v-1cf27b2a">{{item.h}}</text></view><view class="nav-btn data-v-1cf27b2a" catchtap="{{item.j}}"><text class="data-v-1cf27b2a">导航</text></view></view></view><view wx:if="{{r}}" class="empty-state data-v-1cf27b2a"><image class="empty-icon data-v-1cf27b2a" src="{{s}}" mode="aspectFit"/><text class="empty-text data-v-1cf27b2a">暂无附近场地</text></view></scroll-view></view></view><view wx:if="{{v}}" class="loading-overlay data-v-1cf27b2a"><view class="loading-content data-v-1cf27b2a"><view class="loading-spinner data-v-1cf27b2a"></view><text class="data-v-1cf27b2a">正在获取场地信息...</text></view></view><view wx:if="{{w}}" class="phone-auth-popup data-v-1cf27b2a"><view class="popup-mask data-v-1cf27b2a" catchtap="{{x}}"></view><view class="popup-content data-v-1cf27b2a"><view class="popup-header data-v-1cf27b2a"><text class="popup-title data-v-1cf27b2a">授权获取手机号</text></view><view class="popup-body data-v-1cf27b2a"><view class="auth-desc data-v-1cf27b2a"><text class="data-v-1cf27b2a">为了提供更好的服务和紧急联系,需要授权获取您的手机号</text></view><button class="auth-btn data-v-1cf27b2a" open-type="getPhoneNumber" bindgetphonenumber="{{y}}"><text class="data-v-1cf27b2a">一键获取手机号</text></button><view class="auth-cancel data-v-1cf27b2a" bindtap="{{z}}"><text class="data-v-1cf27b2a">暂不授权</text></view></view></view></view></view>
+329 -286
View File
@@ -24,332 +24,375 @@
/* 透明度 */
/* 文章场景相关 */
.container.data-v-1cf27b2a {
min-height: 100vh;
height: 100%;
width: 100%;
background-color: #f6f7fb;
padding-bottom: 40rpx;
display: flex;
flex-direction: column;
}
/* 顶部区域 */
.header.data-v-1cf27b2a {
height: 300rpx;
background: linear-gradient(135deg, #1E88E5, #29B6F6);
/* 顶部搜索栏 */
.header-search.data-v-1cf27b2a {
padding: 20rpx 30rpx;
background: #ffffff;
border-bottom: 1px solid #f0f0f0;
z-index: 10;
}
.header-search .search-box.data-v-1cf27b2a {
display: flex;
align-items: center;
background: #f8f9fa;
border-radius: 50rpx;
padding: 0 20rpx;
height: 80rpx;
}
.header-search .search-box .search-icon.data-v-1cf27b2a {
width: 32rpx;
height: 32rpx;
margin-right: 16rpx;
}
.header-search .search-box .search-input.data-v-1cf27b2a {
flex: 1;
font-size: 28rpx;
color: #333;
}
.header-search .search-box .location-btn.data-v-1cf27b2a {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
background: #2196F3;
border-radius: 50%;
margin-left: 16rpx;
}
.header-search .search-box .location-btn .location-icon.data-v-1cf27b2a {
width: 24rpx;
height: 24rpx;
}
/* 场地列表弹窗 */
.location-popup.data-v-1cf27b2a {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2000;
display: flex;
align-items: flex-end;
justify-content: center;
}
.location-popup .popup-mask.data-v-1cf27b2a {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
}
.location-popup .location-sheet.data-v-1cf27b2a {
background: #ffffff;
border-radius: 32rpx 32rpx 0 0;
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.1);
max-height: 70vh;
transition: all 0.3s ease;
z-index: 1;
position: relative;
width: 100%;
display: flex;
flex-direction: column;
animation: slideUp-1cf27b2a 0.3s ease-out;
}
.location-popup .location-sheet.expanded.data-v-1cf27b2a {
max-height: 85vh;
}
.location-popup .location-sheet .sheet-handle.data-v-1cf27b2a {
display: flex;
justify-content: center;
padding: 20rpx 0;
cursor: pointer;
}
.location-popup .location-sheet .sheet-handle .handle-bar.data-v-1cf27b2a {
width: 80rpx;
height: 8rpx;
background: #e0e0e0;
border-radius: 4rpx;
}
.location-popup .location-sheet .sheet-header.data-v-1cf27b2a {
padding: 0 30rpx 20rpx;
border-bottom: 1px solid #f0f0f0;
display: flex;
justify-content: space-between;
align-items: center;
}
.location-popup .location-sheet .sheet-header .sheet-title.data-v-1cf27b2a {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.location-popup .location-sheet .sheet-header .close-btn.data-v-1cf27b2a {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
background: #f0f0f0;
border-radius: 50%;
transition: all 0.2s ease;
}
.location-popup .location-sheet .sheet-header .close-btn.data-v-1cf27b2a:active {
background: #e0e0e0;
transform: scale(0.95);
}
.location-popup .location-sheet .sheet-header .close-btn .close-icon.data-v-1cf27b2a {
width: 24rpx;
height: 24rpx;
}
.location-popup .location-sheet .sheet-content.data-v-1cf27b2a {
flex: 1;
padding: 20rpx 0;
overflow: hidden;
}
.header .header-bg.data-v-1cf27b2a {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 1;
@keyframes slideUp-1cf27b2a {
from {
transform: translateY(100%);
}
.header .header-bg .circle-decoration.data-v-1cf27b2a {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
to {
transform: translateY(0);
}
.header .header-bg .circle-1.data-v-1cf27b2a {
width: 240rpx;
height: 240rpx;
right: -60rpx;
top: -90rpx;
}
.header .header-bg .circle-2.data-v-1cf27b2a {
width: 160rpx;
height: 160rpx;
left: -40rpx;
bottom: 30rpx;
background: rgba(255, 255, 255, 0.08);
}
.header .header-bg .wave-decoration.data-v-1cf27b2a {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 40rpx;
background-size: auto 100%;
opacity: 0.6;
}
.header .header-content.data-v-1cf27b2a {
position: relative;
z-index: 2;
padding: 40rpx 40rpx 0;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.header .header-content .brand-area.data-v-1cf27b2a {
/* 场地列表项 */
.position-item.data-v-1cf27b2a {
display: flex;
align-items: center;
padding: 24rpx 30rpx;
border-bottom: 1px solid #f8f9fa;
}
.header .header-content .brand-area .brand-logo.data-v-1cf27b2a {
width: 90rpx;
height: 90rpx;
margin-right: 20rpx;
.position-item .position-info.data-v-1cf27b2a {
flex: 1;
}
.header .header-content .brand-area .brand-text.data-v-1cf27b2a {
display: flex;
flex-direction: column;
.position-item .position-info .position-name.data-v-1cf27b2a {
font-size: 32rpx;
font-weight: 500;
color: #333;
margin-bottom: 8rpx;
}
.header .header-content .brand-area .brand-text .title.data-v-1cf27b2a {
font-size: 48rpx;
color: #ffffff;
font-weight: bold;
line-height: 1.2;
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
.position-item .position-info .position-desc.data-v-1cf27b2a {
font-size: 26rpx;
color: #666;
margin-bottom: 8rpx;
}
.header .header-content .brand-area .brand-text .subtitle.data-v-1cf27b2a {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.9);
}
.header .header-content .header-info.data-v-1cf27b2a {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
margin-bottom: 30rpx;
}
.header .header-content .header-info .service-tag.data-v-1cf27b2a {
.position-item .position-info .position-location.data-v-1cf27b2a {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.2);
border-radius: 40rpx;
padding: 10rpx 20rpx;
margin-bottom: 8rpx;
}
.header .header-content .header-info .service-tag text.data-v-1cf27b2a {
.position-item .position-info .position-location .location-icon-small.data-v-1cf27b2a {
width: 24rpx;
height: 24rpx;
margin-right: 8rpx;
}
.position-item .position-info .position-location text.data-v-1cf27b2a {
font-size: 24rpx;
color: #999;
}
.position-item .position-info .position-time.data-v-1cf27b2a {
font-size: 24rpx;
color: #999;
}
.position-item .position-actions.data-v-1cf27b2a {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 8rpx;
}
.position-item .position-actions .distance-info.data-v-1cf27b2a {
font-size: 24rpx;
color: #2196F3;
font-weight: 500;
}
.position-item .position-actions .status-tag.data-v-1cf27b2a {
padding: 8rpx 16rpx;
border-radius: 20rpx;
font-size: 22rpx;
}
.position-item .position-actions .status-tag.online.data-v-1cf27b2a {
background: #e8f5e8;
color: #4caf50;
}
.position-item .position-actions .status-tag.offline.data-v-1cf27b2a {
background: #ffeaea;
color: #f44336;
}
.position-item .position-actions .nav-btn.data-v-1cf27b2a {
padding: 12rpx 20rpx;
background: #2196F3;
border-radius: 20rpx;
font-size: 24rpx;
color: #ffffff;
}
.header .header-content .header-info .service-tag .dot.data-v-1cf27b2a {
margin: 0 8rpx;
font-weight: bold;
}
/* 扫码区域 */
.scan-section.data-v-1cf27b2a {
padding: 0 30rpx;
}
.scan-section .scan-card.data-v-1cf27b2a {
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-section .scan-card .scan-btn.data-v-1cf27b2a {
width: 220rpx;
height: 220rpx;
background: linear-gradient(135deg, #00B0FF, #0091EA);
border-radius: 50%;
/* 空状态 */
.empty-state.data-v-1cf27b2a {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 80rpx 0;
}
.empty-state .empty-icon.data-v-1cf27b2a {
width: 120rpx;
height: 120rpx;
margin-bottom: 24rpx;
box-shadow: 0 10rpx 20rpx rgba(0, 176, 255, 0.2);
position: relative;
transition: all 0.2s ease;
opacity: 0.5;
}
.scan-section .scan-card .scan-btn.data-v-1cf27b2a:active {
transform: scale(0.96);
}
.scan-section .scan-card .scan-btn .scan-icon.data-v-1cf27b2a {
width: 80rpx;
height: 80rpx;
margin-bottom: 12rpx;
}
.scan-section .scan-card .scan-btn .scan-text.data-v-1cf27b2a {
font-size: 36rpx;
color: #ffffff;
font-weight: 500;
}
.scan-section .scan-card .scan-desc.data-v-1cf27b2a {
.empty-state .empty-text.data-v-1cf27b2a {
font-size: 28rpx;
color: #666;
color: #999;
}
/* 收费规则卡片 */
.price-card.data-v-1cf27b2a {
margin: 30rpx;
background: #ffffff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.04);
/* 微信免押金区域 */
}
.price-card .card-header.data-v-1cf27b2a {
padding: 24rpx 30rpx;
background: linear-gradient(to right, #f5f9ff, #ffffff);
border-bottom: 2rpx solid #f0f0f0;
}
.price-card .card-header .card-title.data-v-1cf27b2a {
font-size: 32rpx;
font-weight: 600;
color: #333;
position: relative;
padding-left: 20rpx;
}
.price-card .card-header .card-title.data-v-1cf27b2a::before {
content: "";
position: absolute;
/* 加载状态 */
.loading-overlay.data-v-1cf27b2a {
position: fixed;
top: 0;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 28rpx;
background: #2196F3;
border-radius: 3rpx;
}
.price-card .deposit-free.data-v-1cf27b2a {
margin: 20rpx 30rpx 0;
padding: 12rpx 16rpx;
background: #f0f9ff;
border-radius: 8rpx;
border-left: 4rpx solid #03A9F4;
display: flex;
align-items: center;
}
.price-card .deposit-free .deposit-icon.data-v-1cf27b2a {
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
}
.price-card .deposit-free .deposit-text.data-v-1cf27b2a {
font-size: 26rpx;
color: #03A9F4;
font-weight: 500;
}
.price-card .price-rules.data-v-1cf27b2a {
padding: 20rpx 30rpx 30rpx;
}
.price-card .price-rules .price-item.data-v-1cf27b2a {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 20rpx;
}
.price-card .price-rules .price-item .price-tag.data-v-1cf27b2a {
font-size: 60rpx;
color: #FF6E00;
font-weight: bold;
line-height: 1;
}
.price-card .price-rules .price-item .price-tag .unit.data-v-1cf27b2a {
font-size: 32rpx;
font-weight: normal;
margin-left: 4rpx;
}
.price-card .price-rules .price-item .price-desc.data-v-1cf27b2a {
font-size: 28rpx;
color: #666;
margin-top: 10rpx;
}
.price-card .price-rules .divider.data-v-1cf27b2a {
height: 2rpx;
background-color: #f0f0f0;
margin: 20rpx 0 30rpx;
}
.price-card .price-rules .rule-list .rule-item.data-v-1cf27b2a {
display: flex;
align-items: flex-start;
margin-bottom: 20rpx;
}
.price-card .price-rules .rule-list .rule-item.data-v-1cf27b2a:last-child {
margin-bottom: 0;
}
.price-card .price-rules .rule-list .rule-item .rule-dot.data-v-1cf27b2a {
width: 12rpx;
height: 12rpx;
background: #2196F3;
border-radius: 50%;
margin: 12rpx 16rpx 0 0;
flex-shrink: 0;
}
.price-card .price-rules .rule-list .rule-item text.data-v-1cf27b2a {
font-size: 28rpx;
color: #666;
line-height: 1.5;
}
/* 使用流程 */
.usage-steps.data-v-1cf27b2a {
margin: 0 30rpx;
background: #ffffff;
border-radius: 16rpx;
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.04);
overflow: hidden;
}
.usage-steps .steps-header.data-v-1cf27b2a {
padding: 24rpx 30rpx;
background: linear-gradient(to right, #f5f9ff, #ffffff);
border-bottom: 2rpx solid #f0f0f0;
}
.usage-steps .steps-header .steps-title.data-v-1cf27b2a {
font-size: 32rpx;
font-weight: 600;
color: #333;
position: relative;
padding-left: 20rpx;
}
.usage-steps .steps-header .steps-title.data-v-1cf27b2a::before {
content: "";
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 28rpx;
background: #2196F3;
border-radius: 3rpx;
}
.usage-steps .steps-container.data-v-1cf27b2a {
padding: 40rpx 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.usage-steps .steps-container .step-item.data-v-1cf27b2a {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
}
.usage-steps .steps-container .step-item .step-icon.data-v-1cf27b2a {
width: 80rpx;
height: 80rpx;
background: #f0f9ff;
border: 2rpx solid #e1f5fe;
border-radius: 50%;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16rpx;
z-index: 1000;
}
.usage-steps .steps-container .step-item .step-icon .step-number.data-v-1cf27b2a {
font-size: 36rpx;
color: #2196F3;
font-weight: 600;
.loading-overlay .loading-content.data-v-1cf27b2a {
background: #ffffff;
border-radius: 16rpx;
padding: 40rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.usage-steps .steps-container .step-item .step-text.data-v-1cf27b2a {
font-size: 26rpx;
.loading-overlay .loading-content .loading-spinner.data-v-1cf27b2a {
width: 60rpx;
height: 60rpx;
border: 4rpx solid #f0f0f0;
border-top: 4rpx solid #2196F3;
border-radius: 50%;
animation: spin-1cf27b2a 1s linear infinite;
margin-bottom: 24rpx;
}
.loading-overlay .loading-content text.data-v-1cf27b2a {
font-size: 28rpx;
color: #666;
}
.usage-steps .steps-container .step-arrow.data-v-1cf27b2a {
width: 40rpx;
height: 4rpx;
background: #e1f5fe;
position: relative;
@keyframes spin-1cf27b2a {
0% {
transform: rotate(0deg);
}
.usage-steps .steps-container .step-arrow.data-v-1cf27b2a::after {
content: "";
100% {
transform: rotate(360deg);
}
}
/* 地图加载状态 */
.map-loading-placeholder.data-v-1cf27b2a {
position: absolute;
top: 0;
left: 0;
right: 0;
top: 50%;
margin-top: -8rpx;
border-left: 12rpx solid #e1f5fe;
border-top: 8rpx solid transparent;
border-bottom: 8rpx solid transparent;
bottom: 0;
background: #f6f7fb;
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
}
.map-loading-placeholder .loading-content.data-v-1cf27b2a {
background: #ffffff;
border-radius: 16rpx;
padding: 40rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.map-loading-placeholder .loading-content .loading-spinner.data-v-1cf27b2a {
width: 60rpx;
height: 60rpx;
border: 4rpx solid #f0f0f0;
border-top: 4rpx solid #2196F3;
border-radius: 50%;
animation: spin-1cf27b2a 1s linear infinite;
margin-bottom: 24rpx;
}
.map-loading-placeholder .loading-content text.data-v-1cf27b2a {
font-size: 28rpx;
color: #666;
}
/* 手机号授权弹窗 */
.phone-auth-popup.data-v-1cf27b2a {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2000;
display: flex;
align-items: center;
justify-content: center;
}
.phone-auth-popup .popup-mask.data-v-1cf27b2a {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
}
.phone-auth-popup .popup-content.data-v-1cf27b2a {
background: #ffffff;
border-radius: 24rpx;
margin: 0 60rpx;
padding: 40rpx;
position: relative;
z-index: 1;
}
.phone-auth-popup .popup-content .popup-header.data-v-1cf27b2a {
text-align: center;
margin-bottom: 30rpx;
}
.phone-auth-popup .popup-content .popup-header .popup-title.data-v-1cf27b2a {
font-size: 36rpx;
font-weight: 600;
color: #333;
}
.phone-auth-popup .popup-content .popup-body .auth-desc.data-v-1cf27b2a {
text-align: center;
margin-bottom: 40rpx;
}
.phone-auth-popup .popup-content .popup-body .auth-desc text.data-v-1cf27b2a {
font-size: 28rpx;
color: #666;
line-height: 1.6;
}
.phone-auth-popup .popup-content .popup-body .auth-btn.data-v-1cf27b2a {
width: 100%;
height: 88rpx;
background: #2196F3;
border-radius: 44rpx;
border: none;
color: #ffffff;
font-size: 32rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20rpx;
}
.phone-auth-popup .popup-content .popup-body .auth-cancel.data-v-1cf27b2a {
text-align: center;
padding: 20rpx;
}
.phone-auth-popup .popup-content .popup-body .auth-cancel text.data-v-1cf27b2a {
font-size: 28rpx;
color: #999;
}
+1 -1
View File
@@ -95,7 +95,7 @@ const _sfc_main = {
i: common_vendor.o(handleUserProfileClick),
j: common_vendor.t(deposit.value),
k: common_vendor.o(handleWithdraw),
l: common_assets._imports_1$1,
l: common_assets._imports_1,
m: common_vendor.p({
type: "right",
size: "16",
+155
View File
@@ -0,0 +1,155 @@
"use strict";
const common_vendor = require("../common/vendor.js");
const AMAP_KEY = "4c513a688938fd89b88b296e867f66ec";
class AmapUtil {
constructor() {
this.key = AMAP_KEY;
}
// 逆地理编码 - 根据经纬度获取地址信息
async regeocode(longitude, latitude) {
try {
const res = await common_vendor.index.request({
url: "https://restapi.amap.com/v3/geocode/regeo",
method: "GET",
data: {
key: this.key,
location: `${longitude},${latitude}`,
poitype: "",
radius: 1e3,
extensions: "base",
batch: false,
roadlevel: 0
}
});
if (res.statusCode === 200 && res.data.status === "1") {
return {
success: true,
data: res.data.regeocode
};
} else {
return {
success: false,
message: res.data.info || "逆地理编码失败"
};
}
} catch (error) {
common_vendor.index.__f__("error", "at utils/amap.js:38", "逆地理编码异常:", error);
return {
success: false,
message: "网络异常"
};
}
}
// 地理编码 - 根据地址获取经纬度
async geocode(address, city = "") {
try {
const res = await common_vendor.index.request({
url: "https://restapi.amap.com/v3/geocode/geo",
method: "GET",
data: {
key: this.key,
address,
city
}
});
if (res.statusCode === 200 && res.data.status === "1" && res.data.geocodes.length > 0) {
return {
success: true,
data: res.data.geocodes[0]
};
} else {
return {
success: false,
message: res.data.info || "地理编码失败"
};
}
} catch (error) {
common_vendor.index.__f__("error", "at utils/amap.js:71", "地理编码异常:", error);
return {
success: false,
message: "网络异常"
};
}
}
// 搜索POI
async searchPOI(keywords, location = "", radius = 3e3, city = "") {
try {
const res = await common_vendor.index.request({
url: "https://restapi.amap.com/v3/place/text",
method: "GET",
data: {
key: this.key,
keywords,
location,
radius,
city,
citylimit: true
}
});
if (res.statusCode === 200 && res.data.status === "1") {
return {
success: true,
data: res.data.pois || []
};
} else {
return {
success: false,
message: res.data.info || "搜索失败"
};
}
} catch (error) {
common_vendor.index.__f__("error", "at utils/amap.js:107", "POI搜索异常:", error);
return {
success: false,
message: "网络异常"
};
}
}
// 路径规划
async getRoute(origin, destination, strategy = 0) {
try {
const res = await common_vendor.index.request({
url: "https://restapi.amap.com/v3/direction/driving",
method: "GET",
data: {
key: this.key,
origin,
destination,
strategy,
extensions: "base"
}
});
if (res.statusCode === 200 && res.data.status === "1") {
return {
success: true,
data: res.data.route
};
} else {
return {
success: false,
message: res.data.info || "路径规划失败"
};
}
} catch (error) {
common_vendor.index.__f__("error", "at utils/amap.js:142", "路径规划异常:", error);
return {
success: false,
message: "网络异常"
};
}
}
// 计算两点间距离
calculateDistance(lat1, lng1, lat2, lng2) {
const radLat1 = lat1 * Math.PI / 180;
const radLat2 = lat2 * Math.PI / 180;
const a = radLat1 - radLat2;
const b = lng1 * Math.PI / 180 - lng2 * Math.PI / 180;
let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
s = s * 6378.137;
s = Math.round(s * 1e4) / 1e4;
return s;
}
}
const AmapUtil$1 = new AmapUtil();
exports.AmapUtil = AmapUtil$1;
//# sourceMappingURL=../../.sourcemap/mp-weixin/utils/amap.js.map
+163
View File
@@ -0,0 +1,163 @@
// 高德地图工具类
const AMAP_KEY = '4c513a688938fd89b88b296e867f66ec'
class AmapUtil {
constructor() {
this.key = AMAP_KEY
}
// 逆地理编码 - 根据经纬度获取地址信息
async regeocode(longitude, latitude) {
try {
const res = await uni.request({
url: 'https://restapi.amap.com/v3/geocode/regeo',
method: 'GET',
data: {
key: this.key,
location: `${longitude},${latitude}`,
poitype: '',
radius: 1000,
extensions: 'base',
batch: false,
roadlevel: 0
}
})
if (res.statusCode === 200 && res.data.status === '1') {
return {
success: true,
data: res.data.regeocode
}
} else {
return {
success: false,
message: res.data.info || '逆地理编码失败'
}
}
} catch (error) {
console.error('逆地理编码异常:', error)
return {
success: false,
message: '网络异常'
}
}
}
// 地理编码 - 根据地址获取经纬度
async geocode(address, city = '') {
try {
const res = await uni.request({
url: 'https://restapi.amap.com/v3/geocode/geo',
method: 'GET',
data: {
key: this.key,
address: address,
city: city
}
})
if (res.statusCode === 200 && res.data.status === '1' && res.data.geocodes.length > 0) {
return {
success: true,
data: res.data.geocodes[0]
}
} else {
return {
success: false,
message: res.data.info || '地理编码失败'
}
}
} catch (error) {
console.error('地理编码异常:', error)
return {
success: false,
message: '网络异常'
}
}
}
// 搜索POI
async searchPOI(keywords, location = '', radius = 3000, city = '') {
try {
const res = await uni.request({
url: 'https://restapi.amap.com/v3/place/text',
method: 'GET',
data: {
key: this.key,
keywords: keywords,
location: location,
radius: radius,
city: city,
citylimit: true
}
})
if (res.statusCode === 200 && res.data.status === '1') {
return {
success: true,
data: res.data.pois || []
}
} else {
return {
success: false,
message: res.data.info || '搜索失败'
}
}
} catch (error) {
console.error('POI搜索异常:', error)
return {
success: false,
message: '网络异常'
}
}
}
// 路径规划
async getRoute(origin, destination, strategy = 0) {
try {
const res = await uni.request({
url: 'https://restapi.amap.com/v3/direction/driving',
method: 'GET',
data: {
key: this.key,
origin: origin,
destination: destination,
strategy: strategy,
extensions: 'base'
}
})
if (res.statusCode === 200 && res.data.status === '1') {
return {
success: true,
data: res.data.route
}
} else {
return {
success: false,
message: res.data.info || '路径规划失败'
}
}
} catch (error) {
console.error('路径规划异常:', error)
return {
success: false,
message: '网络异常'
}
}
}
// 计算两点间距离
calculateDistance(lat1, lng1, lat2, lng2) {
const radLat1 = lat1 * Math.PI / 180.0
const radLat2 = lat2 * Math.PI / 180.0
const a = radLat1 - radLat2
const b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0
let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)))
s = s * 6378.137
s = Math.round(s * 10000) / 10000
return s
}
}
export default new AmapUtil()
+194
View File
@@ -0,0 +1,194 @@
// 高德静态地图API工具类
const AMAP_KEY = '4c513a688938fd89b88b296e867f66ec'
class StaticMapUtil {
constructor() {
this.key = AMAP_KEY
this.baseUrl = 'https://restapi.amap.com/v3/staticmap'
}
/**
* 生成静态地图URL
* @param {Object} options 地图配置选项
* @returns {String} 静态地图URL
*/
generateMapUrl(options = {}) {
const defaultOptions = {
location: '116.397128,39.916527', // 默认中心点(北京)
zoom: 13, // 缩放级别
size: '750*500', // 图片尺寸
scale: 2, // 高清显示
markers: [], // 标记点
labels: [], // 文字标注
paths: [], // 路径
traffic: 0, // 交通路况 0-不显示 1-显示
format: 'png' // 图片格式
}
const config = { ...defaultOptions, ...options }
let url = `${this.baseUrl}?key=${this.key}`
url += `&location=${config.location}`
url += `&zoom=${config.zoom}`
url += `&size=${config.size}`
url += `&scale=${config.scale}`
url += `&traffic=${config.traffic}`
url += `&format=${config.format}`
// 添加标记点
if (config.markers && config.markers.length > 0) {
const markersStr = config.markers.map(marker => {
let markerStr = ''
if (marker.size) markerStr += `size:${marker.size}|`
if (marker.color) markerStr += `color:${marker.color}|`
if (marker.label) markerStr += `label:${marker.label}|`
markerStr += `${marker.longitude},${marker.latitude}`
return markerStr
}).join('|')
url += `&markers=${encodeURIComponent(markersStr)}`
}
// 添加文字标注
if (config.labels && config.labels.length > 0) {
const labelsStr = config.labels.map(label => {
let labelStr = ''
if (label.content) labelStr += `content:${label.content}|`
if (label.font) labelStr += `font:${label.font}|`
if (label.bold) labelStr += `bold:${label.bold}|`
if (label.fontSize) labelStr += `fontSize:${label.fontSize}|`
if (label.fontColor) labelStr += `fontColor:${label.fontColor}|`
if (label.background) labelStr += `background:${label.background}|`
labelStr += `${label.longitude},${label.latitude}`
return labelStr
}).join('|')
url += `&labels=${encodeURIComponent(labelsStr)}`
}
return url
}
/**
* 为场地列表生成静态地图URL
* @param {Array} positions 场地列表
* @param {Object} options 额外选项
* @returns {String} 静态地图URL
*/
generatePositionsMapUrl(positions = [], options = {}) {
if (!positions || positions.length === 0) {
return this.generateMapUrl(options)
}
// 计算地图中心点和缩放级别
const center = this.calculateCenter(positions)
const zoom = this.calculateOptimalZoom(positions, center)
// 生成标记点
const markers = positions.map((position, index) => ({
longitude: parseFloat(position.longitude),
latitude: parseFloat(position.latitude),
size: 'mid',
color: position.status === 'online' ? 'green' : 'red',
label: String.fromCharCode(65 + (index % 26)) // A, B, C...
}))
return this.generateMapUrl({
location: `${center.longitude},${center.latitude}`,
zoom: zoom,
markers: markers,
...options
})
}
/**
* 计算多个点的中心位置
* @param {Array} positions 位置数组
* @returns {Object} 中心点坐标
*/
calculateCenter(positions) {
if (positions.length === 0) {
return { longitude: 116.397128, latitude: 39.916527 }
}
const validPositions = positions.filter(p => p.longitude && p.latitude)
if (validPositions.length === 0) {
return { longitude: 116.397128, latitude: 39.916527 }
}
const sum = validPositions.reduce((acc, pos) => ({
longitude: acc.longitude + parseFloat(pos.longitude),
latitude: acc.latitude + parseFloat(pos.latitude)
}), { longitude: 0, latitude: 0 })
return {
longitude: (sum.longitude / validPositions.length).toFixed(6),
latitude: (sum.latitude / validPositions.length).toFixed(6)
}
}
/**
* 计算最佳缩放级别
* @param {Array} positions 位置数组
* @param {Object} center 中心点
* @returns {Number} 缩放级别
*/
calculateOptimalZoom(positions, center) {
if (positions.length <= 1) return 15
const validPositions = positions.filter(p => p.longitude && p.latitude)
if (validPositions.length <= 1) return 15
// 计算最大距离
let maxDistance = 0
validPositions.forEach(pos => {
const distance = this.getDistance(
center.latitude, center.longitude,
parseFloat(pos.latitude), parseFloat(pos.longitude)
)
maxDistance = Math.max(maxDistance, distance)
})
// 根据最大距离确定缩放级别
if (maxDistance < 1) return 16 // 1km内
if (maxDistance < 2) return 15 // 2km内
if (maxDistance < 5) return 14 // 5km内
if (maxDistance < 10) return 13 // 10km内
if (maxDistance < 20) return 12 // 20km内
if (maxDistance < 50) return 11 // 50km内
return 10 // 50km以上
}
/**
* 计算两点间距离公里
* @param {Number} lat1 纬度1
* @param {Number} lng1 经度1
* @param {Number} lat2 纬度2
* @param {Number} lng2 经度2
* @returns {Number} 距离公里
*/
getDistance(lat1, lng1, lat2, lng2) {
const radLat1 = lat1 * Math.PI / 180.0
const radLat2 = lat2 * Math.PI / 180.0
const a = radLat1 - radLat2
const b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0
let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)))
s = s * 6378.137
s = Math.round(s * 10000) / 10000
return s
}
/**
* 预加载地图图片
* @param {String} mapUrl 地图URL
* @returns {Promise} 图片加载Promise
*/
preloadMapImage(mapUrl) {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = () => resolve(mapUrl)
img.onerror = reject
img.src = mapUrl
})
}
}
export default new StaticMapUtil()