587 lines
20 KiB
Plaintext
587 lines
20 KiB
Plaintext
<template>
|
||
<ServicePageScaffold title="到达签到" fallback-url="/pages/mall/delivery/orders/route">
|
||
<ServicePanel title="居家服务认证" subtitle="使用居家服务系统账号登录">
|
||
<view v-if="!isHomecareLoggedIn">
|
||
<text class="info-text">状态:未登录</text>
|
||
<text class="info-text warning-text">居家服务认证服务暂不可用,请跳过此步骤继续操作</text>
|
||
</view>
|
||
<view v-else>
|
||
<text class="info-text">已登录:{{ homecareUserEmail }}</text>
|
||
<text class="info-text success-text">居家服务认证通过</text>
|
||
</view>
|
||
</ServicePanel>
|
||
|
||
<ServicePanel title="签到要求" subtitle="定位签到或扫码签到,要求在 50 米范围内并上传现场图片。">
|
||
<text v-if="order != null" class="info-text">服务地址:{{ order.fullAddress }}</text>
|
||
<text class="info-text">当前定位:{{ locationText }}</text>
|
||
<text class="info-text">定位精度:{{ accuracyText }}</text>
|
||
<text class="info-text">现场图片:{{ photos.length }} 张</text>
|
||
</ServicePanel>
|
||
|
||
<ServicePanel title="距离预校验" subtitle="获取定位后校验是否在允许签到范围内">
|
||
<text class="info-text">距离服务点:{{ distanceText }}</text>
|
||
<text class="info-text">允许半径:{{ allowedRadiusText }}</text>
|
||
<text class="info-text">校验状态:{{ precheckStatusText }}</text>
|
||
<text v-if="reasonText !== ''" class="info-text warning-text">{{ reasonText }}</text>
|
||
<view class="button-stack">
|
||
<button class="secondary-btn" :disabled="prechecking" @click="handlePrecheck">{{ prechecking ? '预校验中...' : '距离预校验' }}</button>
|
||
</view>
|
||
</ServicePanel>
|
||
|
||
<ServicePanel title="签到操作" subtitle="定位失败时要给出清晰提示。">
|
||
<view class="button-stack">
|
||
<button class="secondary-btn" @click="getCurrentLocation">获取 GPS 定位</button>
|
||
<button class="secondary-btn" @click="choosePhoto">拍照上传现场图片</button>
|
||
<input class="note-input" v-model="note" placeholder="补充签到说明,例如入户前核验联系人" />
|
||
<button class="primary-btn" :disabled="submitting" @click="submitCheckin">{{ submitting ? '签到中...' : '完成签到' }}</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 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'
|
||
import {
|
||
emailLogin,
|
||
checkinPrecheck,
|
||
getReasonText
|
||
} from '@/utils/homecareAuth.uts'
|
||
import { debugCurrentUser, getCurrentAkUserId } from '@/utils/akUserMapping.uts'
|
||
|
||
const orderId = ref('')
|
||
const order = ref<DeliveryOrderType | null>(null)
|
||
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)
|
||
|
||
// 居家服务认证状态
|
||
const isHomecareLoggedIn = ref(false)
|
||
const homecareUserEmail = ref('')
|
||
|
||
// 距离预校验状态
|
||
const prechecking = ref(false)
|
||
const canCheckin = ref(false)
|
||
const distanceText = ref('未校验')
|
||
const allowedRadiusText = ref('未校验')
|
||
const precheckStatusText = ref('未校验')
|
||
const reasonText = ref('')
|
||
|
||
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: ' + akUserId.substring(0, 8) + '...)'
|
||
console.warn('[CHECKIN AUTH] 居家服务认证通过')
|
||
} else {
|
||
isHomecareLoggedIn.value = false
|
||
homecareUserEmail.value = ''
|
||
console.warn('[CHECKIN AUTH] 居家服务认证失败:akUserId 为空')
|
||
}
|
||
}
|
||
|
||
async function loginHomecare(): Promise<void> {
|
||
const token = getHomecareToken()
|
||
if (token !== '') {
|
||
uni.showToast({ title: '已登录,无需重复登录', icon: 'success' })
|
||
return
|
||
}
|
||
uni.showToast({ title: '居家服务认证服务暂不可用', icon: 'none' })
|
||
}
|
||
|
||
function toRadians(value: number): number {
|
||
return value * 3.1415926 / 180
|
||
}
|
||
|
||
function calculateDistance(lat1: number, lng1: number, lat2: number, lng2: number): number {
|
||
const earthRadius = 6378137
|
||
const deltaLat = toRadians(lat2 - lat1)
|
||
const deltaLng = toRadians(lng2 - lng1)
|
||
const a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) * Math.sin(deltaLng / 2) * Math.sin(deltaLng / 2)
|
||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
|
||
return earthRadius * c
|
||
}
|
||
|
||
function wrapLocation(): Promise<DeliveryLocationType> {
|
||
console.warn('[CHECKIN DEBUG] wrapLocation: starting...')
|
||
return new Promise((resolve, reject) => {
|
||
uni.getLocation({
|
||
type: 'gcj02',
|
||
isHighAccuracy: true,
|
||
enableHighAccuracy: true,
|
||
success: (res) => {
|
||
console.warn('[CHECKIN DEBUG] wrapLocation SUCCESS:', JSON.stringify({
|
||
latitude: res.latitude,
|
||
longitude: res.longitude,
|
||
accuracy: res.accuracy,
|
||
speed: res.speed,
|
||
altitude: res.altitude,
|
||
altitudeAccuracy: res.altitudeAccuracy,
|
||
heading: res.heading,
|
||
timestamp: res.timestamp
|
||
}))
|
||
resolve({
|
||
latitude: res.latitude,
|
||
longitude: res.longitude,
|
||
address: '当前位置',
|
||
time: new Date().toISOString().replace('T', ' ').substring(0, 19)
|
||
})
|
||
},
|
||
fail: (err) => {
|
||
console.warn('[CHECKIN DEBUG] wrapLocation FAIL:', JSON.stringify(err))
|
||
reject(new Error('定位失败'))
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
type LocationFullResult = {
|
||
location: DeliveryLocationType
|
||
accuracy: number
|
||
}
|
||
|
||
function wrapLocationFull(): Promise<LocationFullResult> {
|
||
console.warn('[CHECKIN DEBUG] wrapLocationFull: starting...')
|
||
return new Promise((resolve, reject) => {
|
||
uni.getLocation({
|
||
type: 'gcj02',
|
||
isHighAccuracy: true,
|
||
enableHighAccuracy: true,
|
||
success: (res) => {
|
||
console.warn('[CHECKIN DEBUG] wrapLocationFull SUCCESS:', JSON.stringify({
|
||
latitude: res.latitude,
|
||
longitude: res.longitude,
|
||
accuracy: res.accuracy,
|
||
speed: res.speed,
|
||
altitude: res.altitude,
|
||
altitudeAccuracy: res.altitudeAccuracy,
|
||
heading: res.heading,
|
||
timestamp: res.timestamp
|
||
}))
|
||
const loc: DeliveryLocationType = {
|
||
latitude: res.latitude,
|
||
longitude: res.longitude,
|
||
address: '当前位置',
|
||
time: new Date().toISOString().replace('T', ' ').substring(0, 19)
|
||
}
|
||
const acc = res.accuracy != null ? res.accuracy : 0
|
||
console.warn('[CHECKIN DEBUG] wrapLocationFull resolved with accuracy:', acc)
|
||
resolve({ location: loc, accuracy: acc })
|
||
},
|
||
fail: (err) => {
|
||
console.warn('[CHECKIN DEBUG] wrapLocationFull FAIL:', JSON.stringify(err))
|
||
reject(new Error('定位失败'))
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
function wrapChooseImage(): Promise<Array<string>> {
|
||
return new Promise((resolve, reject) => {
|
||
uni.chooseImage({
|
||
count: 3,
|
||
sourceType: ['camera'],
|
||
success: (res) => {
|
||
resolve(res.tempFilePaths)
|
||
},
|
||
fail: () => {
|
||
reject(new Error('拍照失败'))
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
async function loadData() {
|
||
console.warn('[CHECKIN DEBUG] loadData: called, orderId:', orderId.value)
|
||
const authResult = await requireDeliveryAuth({ redirectOnFail: true, toastOnFail: true })
|
||
if (!authResult.ok || orderId.value == '') {
|
||
console.warn('[CHECKIN DEBUG] loadData: auth failed or orderId empty')
|
||
return
|
||
}
|
||
console.warn('[CHECKIN DEBUG] loadData: fetching order detail')
|
||
order.value = await getDeliveryOrderDetail(orderId.value)
|
||
console.warn('[CHECKIN DEBUG] loadData: order fetched:', JSON.stringify({
|
||
id: order.value?.id,
|
||
fullAddress: order.value?.fullAddress,
|
||
latitude: order.value?.latitude,
|
||
longitude: order.value?.longitude,
|
||
allowCheckinRadiusMeters: order.value?.allowCheckinRadiusMeters
|
||
}))
|
||
updateHomecareLoginStatus()
|
||
}
|
||
|
||
async function getCurrentLocation() {
|
||
console.warn('[CHECKIN DEBUG] getCurrentLocation: called')
|
||
try {
|
||
currentLocation.value = await wrapLocation()
|
||
locationText.value = '纬度 ' + String(currentLocation.value.latitude) + ' / 经度 ' + String(currentLocation.value.longitude)
|
||
console.warn('[CHECKIN DEBUG] getCurrentLocation completed, location:', JSON.stringify(currentLocation.value))
|
||
} catch (error) {
|
||
console.warn('[CHECKIN DEBUG] getCurrentLocation error:', error)
|
||
uni.showToast({ title: '签到定位失败,请检查定位权限', icon: 'none' })
|
||
}
|
||
}
|
||
|
||
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' })
|
||
}
|
||
}
|
||
|
||
async function handlePrecheck(): Promise<void> {
|
||
console.warn('[CHECKIN PAGE] ========== handlePrecheck START ==========')
|
||
console.warn('[CHECKIN PAGE] 当前 orderId:', orderId.value)
|
||
|
||
if (prechecking.value) {
|
||
console.warn('[CHECKIN PAGE] 已经在预校验中,直接返回')
|
||
return
|
||
}
|
||
|
||
if (orderId.value === '') {
|
||
console.warn('[CHECKIN PAGE] orderId 为空')
|
||
uni.showToast({ title: '工单信息缺失', icon: 'none' })
|
||
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 信息
|
||
debugCurrentUser()
|
||
|
||
prechecking.value = true
|
||
canCheckin.value = false
|
||
distanceText.value = '定位中...'
|
||
allowedRadiusText.value = '定位中...'
|
||
precheckStatusText.value = '定位中...'
|
||
reasonText.value = ''
|
||
|
||
try {
|
||
console.warn('[CHECKIN PAGE] 步骤 1: 调用 wrapLocationFull 获取位置')
|
||
const fullResult = await wrapLocationFull()
|
||
const location = fullResult.location
|
||
const accuracy = fullResult.accuracy
|
||
console.warn('[CHECKIN PAGE] 位置信息: lat=', location.latitude, ' lng=', location.longitude, ' accuracy=', accuracy)
|
||
|
||
currentLocation.value = location
|
||
locationText.value = '纬度 ' + String(location.latitude) + ' / 经度 ' + String(location.longitude)
|
||
accuracyText.value = accuracy > 0 ? String(accuracy) + ' 米' : '未知'
|
||
|
||
// 调用 RPC 预校验(现在直接走 Supabase,不需要本地后端)
|
||
console.warn('[CHECKIN PAGE] 步骤 2: 调用 checkinPrecheck RPC')
|
||
const result = await checkinPrecheck(
|
||
orderId.value,
|
||
location.latitude,
|
||
location.longitude,
|
||
accuracy
|
||
)
|
||
console.warn('[CHECKIN PAGE] RPC 返回结果: distance=', result.distanceMeters, ' radius=', result.allowedRadiusMeters, ' canCheckin=', result.canCheckin, ' reason=', result.reasonCode)
|
||
|
||
if (result.distanceMeters != null) {
|
||
distanceText.value = String(result.distanceMeters) + ' 米'
|
||
} else {
|
||
distanceText.value = '未知'
|
||
}
|
||
allowedRadiusText.value = String(result.allowedRadiusMeters) + ' 米'
|
||
|
||
if (result.canCheckin) {
|
||
canCheckin.value = true
|
||
precheckStatusText.value = '可以签到 / 下一步拍照'
|
||
reasonText.value = ''
|
||
console.warn('[CHECKIN PAGE] 可以签到')
|
||
} else {
|
||
canCheckin.value = false
|
||
precheckStatusText.value = '不可签到'
|
||
reasonText.value = getReasonText(result.reasonCode)
|
||
console.warn('[CHECKIN PAGE] 不可签到,原因:', result.reasonCode, getReasonText(result.reasonCode))
|
||
}
|
||
} catch (error) {
|
||
console.warn('[CHECKIN PAGE] ========== 捕获异常 ==========')
|
||
console.warn('[CHECKIN PAGE] 异常类型:', error instanceof Error ? 'Error' : typeof error)
|
||
console.warn('[CHECKIN PAGE] 异常信息:', error)
|
||
console.warn('[CHECKIN PAGE] ========== handlePrecheck END (ERROR) ==========')
|
||
|
||
uni.showToast({ title: '预校验失败,请重试', icon: 'none' })
|
||
precheckStatusText.value = '预校验失败'
|
||
} finally {
|
||
prechecking.value = false
|
||
console.warn('[CHECKIN PAGE] ========== handlePrecheck END (FINISHED) ==========')
|
||
}
|
||
}
|
||
|
||
async function submitCheckin() {
|
||
console.warn('[CHECKIN DEBUG] submitCheckin: called')
|
||
if (submitting.value) {
|
||
console.warn('[CHECKIN DEBUG] submitCheckin: already submitting, returning')
|
||
return
|
||
}
|
||
if (order.value == null) {
|
||
console.warn('[CHECKIN DEBUG] submitCheckin: order is null')
|
||
uni.showToast({ title: '订单信息缺失', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
// 必须通过预校验才能提交
|
||
if (!canCheckin.value) {
|
||
uni.showToast({ title: '请先完成距离预校验', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
if (currentLocation.value == null) {
|
||
console.warn('[CHECKIN DEBUG] submitCheckin: currentLocation is null, calling getCurrentLocation')
|
||
await getCurrentLocation()
|
||
if (currentLocation.value == null) {
|
||
console.warn('[CHECKIN DEBUG] submitCheckin: still null after getCurrentLocation')
|
||
return
|
||
}
|
||
}
|
||
if (photos.value.length == 0) {
|
||
console.warn('[CHECKIN DEBUG] submitCheckin: no photos uploaded')
|
||
uni.showToast({ title: '请至少上传一张现场图片', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
// 服务坐标以后端 precheck 返回为准,不再以前端 order.latitude/order.longitude 为准
|
||
// 删除了之前的坐标检查
|
||
|
||
console.warn('[CHECKIN DEBUG] submitCheckin: proceeding with checkin, photos count:', photos.value.length, ' evidenceFileIds:', evidenceFileIds.value)
|
||
doCheckin()
|
||
}
|
||
|
||
async function doCheckin() {
|
||
submitting.value = true
|
||
try {
|
||
// 获取 akUserId
|
||
const akUserId = await getCurrentAkUserId()
|
||
console.warn('[CHECKIN RPC] akUserId:', akUserId)
|
||
|
||
if (akUserId == '') {
|
||
uni.showToast({ title: '未获取到业务用户 ID,请重新登录', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
// 调用居家服务正式签到 RPC:rpc_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({
|
||
title: '签到成功',
|
||
content: '已提交到达签到,等待消费者确认',
|
||
showCancel: false,
|
||
success: () => {
|
||
// 返回订单列表
|
||
uni.navigateBack()
|
||
}
|
||
})
|
||
} catch (error) {
|
||
console.warn('[CHECKIN DEBUG] submitCheckin error:', error)
|
||
uni.showToast({ title: '签到失败,请重试', icon: 'none' })
|
||
} finally {
|
||
submitting.value = false
|
||
}
|
||
}
|
||
|
||
onLoad((options) => {
|
||
console.warn('[CHECKIN DEBUG] onLoad: called, options:', JSON.stringify(options))
|
||
if (options != null) {
|
||
orderId.value = getDeliveryRouteParam(options as UTSJSONObject, 'id')
|
||
console.warn('[CHECKIN DEBUG] onLoad: extracted orderId:', orderId.value)
|
||
}
|
||
console.warn('[CHECKIN DEBUG] onLoad: calling loadData')
|
||
loadData()
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
.info-text {
|
||
display: block;
|
||
margin-bottom: 14rpx;
|
||
font-size: 26rpx;
|
||
line-height: 38rpx;
|
||
color: #16324f;
|
||
}
|
||
|
||
.success-text {
|
||
color: #0f766e;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.warning-text {
|
||
color: #dc2626;
|
||
}
|
||
|
||
.button-stack {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.primary-btn,
|
||
.secondary-btn {
|
||
margin-bottom: 18rpx;
|
||
border-radius: 18rpx;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.primary-btn {
|
||
background: #0f766e;
|
||
color: #ffffff;
|
||
}
|
||
|
||
.primary-btn[disabled] {
|
||
background: #9ca3af;
|
||
}
|
||
|
||
.secondary-btn {
|
||
background: #eaf2f0;
|
||
color: #0f766e;
|
||
}
|
||
|
||
.note-input {
|
||
height: 84rpx;
|
||
padding: 0 24rpx;
|
||
margin-bottom: 18rpx;
|
||
border-radius: 18rpx;
|
||
background: #f2f7f6;
|
||
font-size: 28rpx;
|
||
}
|
||
</style>
|