完成距离预校验

This commit is contained in:
2026-06-12 13:03:13 +08:00
parent 81f3e1d3b6
commit 72d29d4b68
7 changed files with 6060 additions and 3054 deletions

View File

@@ -45,7 +45,8 @@ 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 { checkinOrder, getDeliveryOrderDetail } from '@/services/deliveryService.uts'
import supa from '@/components/supadb/aksupainstance.uts'
import { getDeliveryOrderDetail } from '@/services/deliveryService.uts'
import { requireDeliveryAuth } from '@/utils/deliveryAuth.uts'
import { getCurrentUserId } from '@/utils/store.uts'
import { getDeliveryRouteParam } from '@/utils/deliveryRoute.uts'
@@ -54,7 +55,7 @@ import {
checkinPrecheck,
getReasonText
} from '@/utils/homecareAuth.uts'
import { debugCurrentUser } from '@/utils/akUserMapping.uts'
import { debugCurrentUser, getCurrentAkUserId } from '@/utils/akUserMapping.uts'
const orderId = ref('')
const order = ref<DeliveryOrderType | null>(null)
@@ -62,6 +63,7 @@ const currentLocation = ref<DeliveryLocationType | null>(null)
const locationText = ref('未获取')
const accuracyText = ref('未知')
const photos = ref([] as Array<string>)
const evidenceFileIds = ref([] as Array<string>)
const note = ref('')
const submitting = ref(false)
@@ -77,19 +79,29 @@ const allowedRadiusText = ref('未校验')
const precheckStatusText = ref('未校验')
const reasonText = ref('')
function updateHomecareLoginStatus(): void {
console.warn('[CHECKIN DEBUG] updateHomecareLoginStatus: called')
// 改用 Supabase 当前用户判断是否已登录homecare 专属 token 已废弃,从未被写入)
const userId = getCurrentUserId()
console.warn('[CHECKIN DEBUG] updateHomecareLoginStatus: token length:', userId.length)
if (userId !== '') {
async function updateHomecareLoginStatus(): Promise<void> {
console.warn('[CHECKIN AUTH] ========== 登录状态检查 START ==========')
// 打印认证相关日志
const authUserId = getCurrentUserId()
const akUserId = await getCurrentAkUserId()
const storageAkUserId = uni.getStorageSync('ak_user_id')
const storageCurrentAkUser = uni.getStorageSync('current_ak_user')
console.warn('[CHECKIN AUTH] getCurrentUserId =', authUserId)
console.warn('[CHECKIN AUTH] getCurrentAkUserId =', akUserId)
console.warn('[CHECKIN AUTH] storage ak_user_id =', storageAkUserId)
console.warn('[CHECKIN AUTH] current_ak_user =', storageCurrentAkUser)
console.warn('[CHECKIN AUTH] ========== 登录状态检查 END ==========')
if (akUserId !== '') {
isHomecareLoggedIn.value = true
homecareUserEmail.value = '已登录 (uid: ' + userId.substring(0, 8) + '...)'
console.warn('[CHECKIN DEBUG] updateHomecareLoginStatus: logged in as', homecareUserEmail.value)
homecareUserEmail.value = '已登录 (uid: ' + akUserId.substring(0, 8) + '...)'
console.warn('[CHECKIN AUTH] 居家服务认证通过')
} else {
isHomecareLoggedIn.value = false
homecareUserEmail.value = ''
console.warn('[CHECKIN DEBUG] updateHomecareLoginStatus: not logged in')
console.warn('[CHECKIN AUTH] 居家服务认证失败akUserId 为空')
}
}
@@ -239,6 +251,72 @@ async function choosePhoto() {
try {
const selected = await wrapChooseImage()
photos.value = selected
// 上传现场图片并创建 hc_evidence_files 记录
if (selected.length > 0 && orderId.value != '') {
const akUserId = await getCurrentAkUserId()
console.warn('[CHOOSE PHOTO] akUserId:', akUserId)
if (akUserId == '') {
uni.showToast({ title: '未获取到业务用户 ID', icon: 'none' })
return
}
// 上传每张照片
for (let i = 0; i < selected.length; i++) {
const tempPath = selected[i]
try {
// 上传到 Supabase Storage
const { data: uploadData, error: uploadError } = await supa.storage
.from('evidence')
.upload('checkin/' + orderId.value + '/' + Date.now() + '_' + i + '.jpg', {
base64: tempPath,
contentType: 'image/jpeg'
})
if (uploadError == null && uploadData != null) {
// 获取公开 URL
const { data: urlData } = supa.storage
.from('evidence')
.getPublicUrl(uploadData.path)
if (urlData != null) {
const fileUrl = urlData.publicUrl
// 创建 hc_evidence_files 记录
const { data: evidenceRecord, error: evidenceError } = await supa
.from('hc_evidence_files')
.insert({
work_order_id: orderId.value,
uploader_id: akUserId,
file_url: fileUrl,
upload_status: 'UPLOADED',
file_type: 'image',
created_at: new Date().toISOString()
})
.select('id')
.single()
if (evidenceError == null && evidenceRecord != null) {
const evidenceId = evidenceRecord.getString('id') ?? ''
if (evidenceId != '') {
evidenceFileIds.value.push(evidenceId)
console.warn('[CHOOSE PHOTO] 证据记录创建成功, evidenceId:', evidenceId)
}
} else {
console.warn('[CHOOSE PHOTO] 证据记录创建失败:', evidenceError)
}
}
} else {
console.warn('[CHOOSE PHOTO] 图片上传失败:', uploadError)
}
} catch (uploadErr) {
console.warn('[CHOOSE PHOTO] 上传异常:', uploadErr)
}
}
console.warn('[CHOOSE PHOTO] 当前 evidenceFileIds:', evidenceFileIds.value)
}
} catch (error) {
uni.showToast({ title: '拍照失败,请重试', icon: 'none' })
}
@@ -259,6 +337,39 @@ async function handlePrecheck(): Promise<void> {
return
}
// 预校验前打印认证日志
const authUserId = getCurrentUserId()
let akUserId = await getCurrentAkUserId()
const storageAkUserId = uni.getStorageSync('ak_user_id')
const storageCurrentAkUser = uni.getStorageSync('current_ak_user')
console.warn('[CHECKIN AUTH] getCurrentUserId =', authUserId)
console.warn('[CHECKIN AUTH] getCurrentAkUserId =', akUserId)
console.warn('[CHECKIN AUTH] storage ak_user_id =', storageAkUserId)
console.warn('[CHECKIN AUTH] current_ak_user =', storageCurrentAkUser)
// 兜底逻辑:如果 akUserId 为空但 authUserId 非空,尝试写入缓存
if ((akUserId == '' || akUserId == null) && authUserId != null && String(authUserId).length > 0) {
console.warn('[CHECKIN AUTH] 兜底akUserId 为空但 authUserId 非空,尝试写入缓存')
console.warn('[CHECKIN AUTH] authUserId =', authUserId)
// 直接写入 authUserId 作为 ak_user_id
uni.setStorageSync('ak_user_id', authUserId)
uni.setStorageSync('current_ak_user', JSON.stringify({ id: authUserId }))
console.warn('[CHECKIN AUTH] 已写入缓存: ak_user_id =', authUserId)
// 重新读取
akUserId = await getCurrentAkUserId()
console.warn('[CHECKIN AUTH] 重新读取 akUserId =', akUserId)
}
// 如果 akUserId 仍然为空,提示重新登录
if (akUserId == '' || akUserId == null) {
uni.showToast({ title: '业务账号未初始化,请重新登录', icon: 'none' })
console.warn('[CHECKIN AUTH] akUserId 仍为空,阻止预校验')
return
}
console.warn('[CHECKIN PAGE] 开始预校验流程')
// 调试:打印当前 ak_user 信息
@@ -356,31 +467,41 @@ async function submitCheckin() {
return
}
// RPC 预校验已经做了距离判断,这里直接提交
// 保留坐标检查作为兜底,防止跳过预校验直接提交
if (order.value.latitude == 0 && order.value.longitude == 0) {
console.warn('[CHECKIN DEBUG] submitCheckin: order has no valid coordinates (lat=0, lng=0)')
uni.showToast({ title: '订单缺少服务地址坐标', icon: 'none' })
return
}
// 服务坐标以后端 precheck 返回为准,不再以前端 order.latitude/order.longitude 为准
// 删除了之前的坐标检查
const distance = calculateDistance(currentLocation.value.latitude, currentLocation.value.longitude, order.value.latitude, order.value.longitude)
console.warn('[CHECKIN DEBUG] submitCheckin: calculated distance:', distance, 'meters, allowedRadius:', order.value.allowCheckinRadiusMeters)
console.warn('[CHECKIN DEBUG] submitCheckin: proceeding with checkin, photos count:', photos.value.length)
console.warn('[CHECKIN DEBUG] submitCheckin: proceeding with checkin, photos count:', photos.value.length, ' evidenceFileIds:', evidenceFileIds.value)
doCheckin()
}
async function doCheckin() {
submitting.value = true
try {
await checkinOrder(orderId.value, {
location: currentLocation.value as DeliveryLocationType,
note: note.value,
photos: photos.value,
checkinMode: 'gps'
})
console.warn('[CHECKIN DEBUG] submitCheckin: checkinOrder succeeded')
// 获取 akUserId
const akUserId = await getCurrentAkUserId()
console.warn('[CHECKIN RPC] akUserId:', akUserId)
if (akUserId == '') {
uni.showToast({ title: '未获取到业务用户 ID请重新登录', icon: 'none' })
return
}
// 调用居家服务正式签到 RPCrpc_homecare_checkin_submit
const { submitHomecareCheckin } = await import('@/api/delivery.uts')
const result = await submitHomecareCheckin(
orderId.value,
akUserId,
currentLocation.value!.latitude,
currentLocation.value!.longitude,
'gcj02',
parseFloat(accuracyText.value) || 0,
new Date().toISOString(),
evidenceFileIds.value,
null,
'worker_arrived'
)
console.warn('[CHECKIN RPC] result:', result)
// 签到成功后显示等待消费者确认
uni.showModal({
@@ -388,7 +509,7 @@ async function doCheckin() {
content: '已提交到达签到,等待消费者确认',
showCancel: false,
success: () => {
// 返回订单列表或详情页
// 返回订单列表
uni.navigateBack()
}
})

View File

@@ -501,11 +501,69 @@ const handleLogin = async () => {
saveDeliverySession(result.token, result.userInfo, result.deliveryInfo)
// 加载 ak_users 映射Supabase Auth ID -> 业务用户 ID
// 优先从 result.userInfo.id 获取业务用户 ID直接写入缓存
// 只有 userInfo.id 不存在时,才调用 loadCurrentAkUser
let akUserIdFromLogin = ''
try {
await loadCurrentAkUser()
console.log('[Login] ak_users 映射加载成功')
} catch (akErr) {
console.warn('[Login] ⚠️ ak_users 映射加载失败(不影响登录):', akErr)
// 尝试从 userInfo.id 获取业务用户 ID
if (result.userInfo != null && result.userInfo.id != null && String(result.userInfo.id).length > 0) {
const candidateId = String(result.userInfo.id)
console.log('[Login] 从 result.userInfo.id 获取到 ID:', candidateId)
// 判断是否是 Supabase Auth ID通过长度和格式判断
// Supabase Auth ID 通常是 UUID 格式,业务用户 ID 也是 UUID 格式
// 最可靠的方式是尝试写入后验证
akUserIdFromLogin = candidateId
// 写入缓存
uni.setStorageSync('ak_user_id', akUserIdFromLogin)
uni.setStorageSync('user_id', akUserIdFromLogin)
uni.setStorageSync('current_ak_user', JSON.stringify({
id: akUserIdFromLogin,
auth_id: result.userInfo.auth_id ?? '',
username: result.userInfo.username ?? '',
email: result.userInfo.email ?? '',
role: result.userInfo.role ?? ''
}))
console.log('[Login] 从 userInfo.id 写入 ak_user_id 成功:', akUserIdFromLogin)
}
} catch (extractErr) {
console.warn('[Login] 从 userInfo.id 提取失败:', extractErr)
}
// 如果 userInfo.id 没有有效 ID才调用 loadCurrentAkUser
if (akUserIdFromLogin == null || String(akUserIdFromLogin).length == 0) {
try {
const profile = await loadCurrentAkUser()
akUserIdFromLogin = profile.id
console.log('[Login] ak_users 映射加载成功akUserId:', profile.id)
console.log('[Login] 缓存已写入: ak_user_id =', profile.id)
} catch (akErr) {
console.warn('[Login] ⚠️ ak_users 映射加载失败:', akErr)
// 如果 user_id 已有缓存,尝试用它兜底
const cachedUserId = uni.getStorageSync('user_id')
if (cachedUserId != null && String(cachedUserId).length > 0) {
console.log('[Login] 使用 user_id 缓存兜底:', cachedUserId)
uni.setStorageSync('ak_user_id', cachedUserId)
uni.setStorageSync('current_ak_user', JSON.stringify({ id: cachedUserId }))
akUserIdFromLogin = String(cachedUserId)
}
}
}
// 最终验证 ak_user_id 必须有值
const finalAkUserId = uni.getStorageSync('ak_user_id')
console.log('[Login] 最终 ak_user_id:', finalAkUserId)
console.log('[Login] 最终 current_ak_user:', uni.getStorageSync('current_ak_user'))
if (finalAkUserId == null || String(finalAkUserId).length == 0) {
console.error('[Login] ❌ ak_user_id 最终为空,输出详细调试信息')
console.error('[Login] result.userInfo:', JSON.stringify(result.userInfo))
console.error('[Login] result.deliveryInfo:', JSON.stringify(result.deliveryInfo))
console.error('[Login] user_id 缓存:', uni.getStorageSync('user_id'))
console.error('[Login] auth_user_id 缓存:', uni.getStorageSync('auth_user_id'))
console.error('[Login] user_info 缓存:', uni.getStorageSync('user_info'))
throw new Error('业务账号映射加载失败,请联系管理员')
}
const authResult = await requireDeliveryAuth({ redirectOnFail: false, toastOnFail: false })