Files
medical-mall/pages/mall/delivery/orders/route.uvue
2026-06-12 10:16:27 +08:00

150 lines
4.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<ServicePageScaffold title="出发与导航" fallback-url="/pages/mall/delivery/orders/detail">
<ServicePanel title="路线信息" subtitle="支持出发状态回写、地图导航和位置上报。">
<text v-if="order != null" class="info-text">服务地址:{{ order.fullAddress }}</text>
<text v-if="order != null" class="info-text">预约时间:{{ formatDateTime(order.appointmentStartTime) }}</text>
<text class="info-text">当前位置:{{ currentLocationText }}</text>
</ServicePanel>
<ServicePanel title="执行动作" subtitle="先获取位置,再执行出发或到达。">
<view class="button-stack">
<button class="secondary-btn" @click="getCurrentLocation">获取当前位置</button>
<button class="primary-btn" :disabled="submitting" @click="startDepartAction">{{ submitting ? '处理中...' : '点击出发' }}</button>
<button class="secondary-btn" @click="openMap">打开地图导航</button>
<button class="primary-btn" :disabled="submitting" @click="goToCheckin">标记到达签到</button>
</view>
</ServicePanel>
</ServicePageScaffold>
</template>
<script setup lang="uts">
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import ServicePageScaffold from '@/components/homeService/ServicePageScaffold.uvue'
import ServicePanel from '@/components/homeService/ServicePanel.uvue'
import type { DeliveryLocationType, DeliveryOrderType } from '@/types/delivery.uts'
import { getDeliveryOrderDetail, startDepart } from '@/services/deliveryService.uts'
import { requireDeliveryAuth } from '@/utils/deliveryAuth.uts'
import { getDeliveryRouteParam } from '@/utils/deliveryRoute.uts'
import { formatDateTime } from '@/utils/utils.uts'
const orderId = ref('')
const order = ref<DeliveryOrderType | null>(null)
const currentLocation = ref<DeliveryLocationType | null>(null)
const currentLocationText = ref('未获取')
const submitting = ref(false)
function wrapLocation(): Promise<DeliveryLocationType> {
return new Promise((resolve, reject) => {
uni.getLocation({
type: 'gcj02',
success: (res) => {
resolve({
latitude: res.latitude,
longitude: res.longitude,
address: '当前位置',
time: new Date().toISOString().replace('T', ' ').substring(0, 19)
})
},
fail: () => {
reject(new Error('定位失败,请检查定位权限后重试'))
}
})
})
}
async function loadData() {
const authResult = await requireDeliveryAuth({ redirectOnFail: true, toastOnFail: true })
if (!authResult.ok || orderId.value == '') {
return
}
order.value = await getDeliveryOrderDetail(orderId.value)
}
async function getCurrentLocation() {
try {
currentLocation.value = await wrapLocation()
currentLocationText.value = '纬度 ' + String(currentLocation.value.latitude) + ' / 经度 ' + String(currentLocation.value.longitude)
} catch (error) {
uni.showToast({ title: '定位失败,请检查定位权限', icon: 'none' })
}
}
async function startDepartAction() {
if (submitting.value) return
if (currentLocation.value == null) {
await getCurrentLocation()
if (currentLocation.value == null) {
return
}
}
submitting.value = true
try {
await startDepart(orderId.value, currentLocation.value as DeliveryLocationType)
uni.showToast({ title: '已更新为出发中', icon: 'success' })
loadData()
} finally {
submitting.value = false
}
}
/**
* 跳转到签到页面
* 不再直接调用 arriveOrder RPC而是进入签到页面执行距离预校验、拍照上传、正式签到
*/
function goToCheckin() {
if (submitting.value) return
// 先获取当前位置(签到页面会再次获取)
if (currentLocation.value == null) {
getCurrentLocation()
}
// 直接跳转到签到页面
uni.navigateTo({ url: '/pages/mall/delivery/orders/checkin?id=' + orderId.value })
}
function openMap() {
if (order.value == null) {
return
}
uni.openLocation({ latitude: order.value.latitude, longitude: order.value.longitude, address: order.value.fullAddress })
}
onLoad((options) => {
if (options != null) {
orderId.value = getDeliveryRouteParam(options as UTSJSONObject, 'id')
}
loadData()
})
</script>
<style scoped>
.info-text {
display: block;
margin-bottom: 14rpx;
font-size: 26rpx;
line-height: 38rpx;
color: #16324f;
}
.button-stack {
flex-direction: column;
}
.primary-btn,
.secondary-btn {
margin-bottom: 18rpx;
border-radius: 18rpx;
font-size: 28rpx;
}
.primary-btn {
background: #0f766e;
color: #ffffff;
}
.secondary-btn {
background: #eaf2f0;
color: #0f766e;
}
</style>