import { acceptDeliveryOrderById, acceptHomecareAssignmentV2, arriveOrderById, checkinOrderById, finishServiceById, getDeliveryDashboardByStaffId, getDeliveryOrderDetailById, getDeliveryOrdersByStaffId, getDeliveryProfileByUserId, loginDelivery as loginDeliveryApi, saveServiceProgressById, startDepartById, startServiceById } from '@/api/delivery.uts' import { getOrderDetail as getDirectServiceOrderDetail, getOrdersByTab as getDirectOrdersByTab } from '@/services/serviceOrderService.uts' import { getDeliveryInfo, getUserInfo, requireDeliveryAuth, setDeliveryInfo } from '@/utils/deliveryAuth.uts' import { getCurrentAkUserId as readCurrentAkUserId } from '@/utils/akUserMapping.uts' import type { DeliveryAbnormalReportType, DeliveryCheckinPayloadType, DeliveryDashboardType, DeliveryExceptionPayloadType, DeliveryFinishPayloadType, DeliveryInfoType, DeliveryLocationType, DeliveryLoginPayloadType, DeliveryLoginResultType, DeliveryActionResultType, DeliveryMessageType, DeliveryOrderQueryType, DeliveryOrderStatus, DeliveryOrderType, DeliveryProgressPayloadType, DeliveryRecordType, DeliveryServiceRecordType } from '@/types/delivery.uts' function nowText(): string { return new Date().toISOString().replace('T', ' ').substring(0, 19) } function emptyDashboard(): DeliveryDashboardType { return { pendingAssignmentCount: 0, pendingAcceptCount: 0, todayOrderCount: 0, pendingDepartCount: 0, servingCount: 0, completedCount: 0, exceptionCount: 0, expectedIncome: 0, onlineStatus: 'resting', nextOrder: null, recentOrders: [] as Array } as DeliveryDashboardType } async function getCurrentStaffIdOrEmpty(): Promise { const authResult = await requireDeliveryAuth({ redirectOnFail: false, toastOnFail: false }) if (!authResult.ok || authResult.deliveryInfo == null) { return '' } return authResult.deliveryInfo.id } function hasOrderCoreInfo(order: DeliveryOrderType | null): boolean { if (order == null) { return false } return order.serviceName != '' || order.elderName != '' || order.address != '' || order.contactName != '' } function filterOrdersWithCoreInfo(orders: Array): Array { const result = [] as Array for (let i = 0; i < orders.length; i++) { if (hasOrderCoreInfo(orders[i])) { result.push(orders[i]) } } return result } function shouldFallbackOrders(orders: Array): boolean { if (orders.length == 0) { return false } for (let i = 0; i < orders.length; i++) { if (hasOrderCoreInfo(orders[i])) { return false } } return true } function getOrderCanonicalKey(order: DeliveryOrderType): string { const orderNo = String(order.orderNo).trim().toLowerCase() if (orderNo != '') { return orderNo } const sourceOrderId = String(order.sourceOrderId).trim().toLowerCase() if (sourceOrderId != '') { return sourceOrderId } const legacyServiceOrderId = String(order.legacyServiceOrderId).trim().toLowerCase() if (legacyServiceOrderId != '') { return legacyServiceOrderId } return String(order.id).trim().toLowerCase() } function isActiveHomecareStatus(status: string): boolean { const s = String(status).trim().toLowerCase() return s == 'assigned' || s == 'accepted' || s == 'departed' || s == 'arrived' || s == 'in_service' || s == 'serving' || s == 'service_started' || s == 'completed' } function buildActiveOrderKeys(orders: Array): Array { const keys = [] as Array for (let i = 0; i < orders.length; i++) { const order = orders[i] if (!isActiveHomecareStatus(String(order.status))) { continue } const key = getOrderCanonicalKey(order) if (key == '') { continue } let exists = false for (let j = 0; j < keys.length; j++) { if (keys[j] == key) { exists = true break } } if (!exists) { keys.push(key) } } return keys } function filterPendingOrdersAgainstActiveKeys(orders: Array, activeKeys: Array): Array { if (orders.length == 0 || activeKeys.length == 0) { return orders } const result = [] as Array for (let i = 0; i < orders.length; i++) { const key = getOrderCanonicalKey(orders[i]) let duplicated = false for (let j = 0; j < activeKeys.length; j++) { if (activeKeys[j] == key) { duplicated = true break } } if (!duplicated) { result.push(orders[i]) } } return result } function mapOrderToRecord(order: DeliveryOrderType): DeliveryRecordType { const isAccepted = order.status == 'completed' || order.status == 'pending_acceptance' || order.status == 'settled' || order.status == 'archived' return { id: order.id, orderId: order.id, orderNo: order.orderNo, serviceName: order.serviceName, elderName: order.fullElderName != '' ? order.fullElderName : order.elderName, elderNameMasked: order.elderNameMasked != '' ? order.elderNameMasked : order.elderName, status: order.status, statusText: order.statusText, appointmentStartTime: order.appointmentStartTime, appointmentTime: order.appointmentTime, actualStartTime: order.actualStartTime, actualEndTime: order.actualEndTime != '' ? order.actualEndTime : order.finishTime, staffIncome: order.staffIncome, settlementStatus: order.settlementStatus != '' ? order.settlementStatus : '待结算', acceptanceStatus: order.status, exceptionDesc: order.exceptionDesc, ratingText: isAccepted ? '已验收' : (order.status == 'pending_acceptance' ? '待验收' : '待补充'), hasServiceRecord: order.serviceRecord != null } as DeliveryRecordType } export async function loginDelivery(payload: DeliveryLoginPayloadType): Promise { return await loginDeliveryApi(payload) } export async function getDeliveryProfile(): Promise { const authResult = await requireDeliveryAuth({ redirectOnFail: false, toastOnFail: false }) if (!authResult.ok) { } return authResult.deliveryInfo } export async function getDeliveryByUserId(userId: string): Promise { return await getDeliveryProfileByUserId(userId) } export async function getCurrentDeliverer(): Promise { return await getDeliveryProfile() } export async function checkDeliveryAccountByUserId(userId: string): Promise { return await getDeliveryProfileByUserId(userId) } export async function checkDeliveryAuth(): Promise { const result = await requireDeliveryAuth({ redirectOnFail: false, toastOnFail: false }) return result.ok } async function getCurrentStaffId(): Promise { console.log('[DELIVERY_SERVICE_TRACE][getCurrentStaffId][START]', { hasDeliveryInfo: getDeliveryInfo() != null }) // delivery RPC (dashboard / order_list) 需要使用 ml_delivery_staff.id const deliveryInfo = getDeliveryInfo() if (deliveryInfo != null && deliveryInfo.id != null && String(deliveryInfo.id) != '') { const resolvedId = String(deliveryInfo.id) console.log('[DELIVERY_SERVICE_TRACE][getCurrentStaffId][RESOLVED]', { source: 'deliveryStaffId', resolvedId: resolvedId }) return resolvedId } console.error('[DELIVERY_SERVICE_TRACE][getCurrentStaffId][ERROR]', { errorMessage: 'deliveryStaffId not available', errorStack: '', params: { hasDeliveryInfo: deliveryInfo != null } }) return '' } function createEmptyLocation(): DeliveryLocationType { return { latitude: 0, longitude: 0, address: '', time: new Date().toISOString().replace('T', ' ').substring(0, 19) } } export async function getDeliveryDashboard(): Promise { console.log('[DELIVERY_SERVICE_TRACE][getDeliveryDashboard][START]', {}) const staffId = await getCurrentStaffId() if (staffId != '') { try { const result = await getDeliveryDashboardByStaffId(staffId) console.log('[DELIVERY_SERVICE_TRACE][getDeliveryDashboard][SUCCESS]', { result: result }) return result } catch (e) { console.error('[DELIVERY_SERVICE_TRACE][getDeliveryDashboard][ERROR]', { errorMessage: e != null ? String(e.message ?? e) : '', errorStack: e != null ? String(e.stack ?? '') : '', params: { staffId: staffId } }) return emptyDashboard() } } console.error('[DELIVERY_SERVICE_TRACE][getDeliveryDashboard][ERROR]', { errorMessage: 'staffId is empty', errorStack: '', params: {} }) return emptyDashboard() } export async function getDeliveryOrders(params: DeliveryOrderQueryType): Promise> { console.log('[DELIVERY_SERVICE_TRACE][getDeliveryOrders][START]', { params: params }) const staffId = await getCurrentStaffId() if (staffId != '') { try { const result = await getDeliveryOrdersByStaffId(staffId, params) console.log('[DELIVERY_SERVICE_TRACE][getDeliveryOrders][SUCCESS]', { count: result.length, result: result }) return result } catch (e) { console.error('[DELIVERY_SERVICE_TRACE][getDeliveryOrders][ERROR]', { errorMessage: e != null ? String(e.message ?? e) : '', errorStack: e != null ? String(e.stack ?? '') : '', params: { staffId: staffId, query: params } }) return [] as Array } } console.error('[DELIVERY_SERVICE_TRACE][getDeliveryOrders][ERROR]', { errorMessage: 'staffId is empty', errorStack: '', params: { query: params } }) return [] as Array } export async function getDeliveryOrderDetail(id: string): Promise { console.log('[DELIVERY_SERVICE_TRACE][getDeliveryOrderDetail][START]', { id: id }) try { const result = await getDeliveryOrderDetailById(id) console.log('[DELIVERY_SERVICE_TRACE][getDeliveryOrderDetail][SUCCESS]', { id: id, hasResult: result != null, result: result }) return result } catch (e) { console.error('[DELIVERY_SERVICE_TRACE][getDeliveryOrderDetail][ERROR]', { errorMessage: e != null ? String(e.message ?? e) : '', errorStack: e != null ? String(e.stack ?? '') : '', params: { id: id } }) return null } } export async function acceptDeliveryOrder(id: string): Promise { return await acceptDeliveryOrderById(id) } export async function rejectDeliveryOrder(id: string, reason: string): Promise { return rejectCareOrder(id, reason) } export async function startDepart(id: string, location: DeliveryLocationType): Promise { return await startDepartById(id, location) } export async function arriveOrder(id: string, location: DeliveryLocationType): Promise { return await arriveOrderById(id, location) } export async function checkinOrder(id: string, payload: DeliveryCheckinPayloadType): Promise { return await checkinOrderById(id, payload) } export async function startService(id: string): Promise { return await startServiceById(id) } export async function saveServiceProgress(id: string, payload: DeliveryProgressPayloadType): Promise { return await saveServiceProgressById(id, payload) } export async function uploadEvidence(id: string, phase: string, files: Array): Promise> { return files.map((item, index) => ({ id: id + '-evidence-' + String(index + 1), orderId: id, phase, fileType: 'image', name: 'mock-image-' + String(index + 1), url: '', localPath: item, status: 'success', progress: 100, retryable: false, createdAt: new Date().toISOString().replace('T', ' ').substring(0, 19) })) as Array } export async function retryUploadEvidence(id: string, evidenceId: string): Promise { return { id: evidenceId, orderId: id, phase: 'service', fileType: 'image', name: 'mock-retry', url: '', localPath: '', status: 'success', progress: 100, retryable: false, createdAt: new Date().toISOString().replace('T', ' ').substring(0, 19) } as any } export async function submitException(id: string, payload: DeliveryExceptionPayloadType): Promise { return submitCareAbnormalReport(id, payload) } export async function finishService(id: string, payload: DeliveryFinishPayloadType | null = null): Promise { const finishPayload = payload != null ? payload : { serviceSummary: '', signatureName: '', confirmByFamily: false } as DeliveryFinishPayloadType return await finishServiceById(id, finishPayload) } export async function getDeliveryRecords(): Promise> { return getCareRecords() } export async function getDeliveryMessages(): Promise> { return [ { id: 'delivery-msg-01', title: '今日待服务提醒', content: '请优先处理上午 9:00 的上门助浴订单。', type: 'workbench', createdAt: new Date().toISOString().replace('T', ' ').substring(0, 19), read: false, orderId: 'mock-care-001' } as DeliveryMessageType ] } export async function updateDeliveryOnlineStatus(status: string): Promise { if (status == 'online' || status == 'resting' || status == 'busy') { return updateDeliveryCareOnlineStatus(status) } return getDeliveryCareProfile() } export async function getDeliveryDashboardStats(): Promise { return await getDeliveryDashboard() } export async function getPendingServiceOrders(): Promise> { const orders = await getDeliveryOrders({ tab: 'pending', keyword: '' } as DeliveryOrderQueryType) let pendingOrders = filterOrdersWithCoreInfo(orders) if (pendingOrders.length == 0) { pendingOrders = orders } let todayOrders = await getDeliveryOrders({ tab: 'today', keyword: '' } as DeliveryOrderQueryType) let validTodayOrders = filterOrdersWithCoreInfo(todayOrders) if (validTodayOrders.length == 0) { validTodayOrders = todayOrders } if (shouldFallbackOrders(todayOrders)) { const fallbackTodayOrders = await getDirectOrdersByTab('today') if (fallbackTodayOrders.length > 0) { validTodayOrders = fallbackTodayOrders } } const activeKeys = buildActiveOrderKeys(validTodayOrders) const filteredPendingOrders = filterPendingOrdersAgainstActiveKeys(pendingOrders, activeKeys) if (filteredPendingOrders.length > 0 || pendingOrders.length == 0) { return filteredPendingOrders } if (shouldFallbackOrders(orders)) { console.warn('[deliveryService] pending orders missing core info, fallback to direct query') const fallbackOrders = await getDirectOrdersByTab('pending') if (fallbackOrders.length > 0) { return filterPendingOrdersAgainstActiveKeys(fallbackOrders, activeKeys) } } return filteredPendingOrders } export async function getTodayServiceOrders(): Promise> { const orders = await getDeliveryOrders({ tab: 'today', keyword: '' } as DeliveryOrderQueryType) const validOrders = filterOrdersWithCoreInfo(orders) if (validOrders.length > 0) { return validOrders } if (shouldFallbackOrders(orders)) { console.warn('[deliveryService] today orders missing core info, fallback to direct query') const fallbackOrders = await getDirectOrdersByTab('today') if (fallbackOrders.length > 0) { return fallbackOrders } } return orders } export async function getHistoryServiceOrders(): Promise> { const orders = await getDeliveryOrders({ tab: 'history', keyword: '' } as DeliveryOrderQueryType) const validOrders = filterOrdersWithCoreInfo(orders) if (validOrders.length > 0) { return validOrders } if (shouldFallbackOrders(orders)) { console.warn('[deliveryService] history orders missing core info, fallback to direct query') const fallbackOrders = await getDirectOrdersByTab('history') if (fallbackOrders.length > 0) { return fallbackOrders } } return orders } export async function getServiceOrderDetail(orderId: string): Promise { const order = await getDeliveryOrderDetailById(orderId) if (!hasOrderCoreInfo(order)) { console.warn('[deliveryService] order detail missing core info, fallback to direct query:', orderId) const fallbackOrder = await getDirectServiceOrderDetail(orderId) if (hasOrderCoreInfo(fallbackOrder)) { return fallbackOrder } } return order } export async function acceptServiceOrder(orderId: string): Promise { const akUserId = await resolveCurrentAkUserIdForDelivery() console.warn('[HOMECARE ACCEPT] acceptServiceOrder: orderId=', orderId, ' akUserId=', akUserId) if (akUserId == '') { return { ok: false, message: '未获取到业务用户 ID,请重新登录', order: null } as DeliveryActionResultType } const result = await acceptHomecareAssignmentV2(orderId, akUserId) console.warn('[HOMECARE ACCEPT] rpc_homecare_accept_assignment_v2 result:', result) if (result == null) { return { ok: false, message: '接单失败,请稍后重试', order: null } as DeliveryActionResultType } const ok = result.getBoolean('ok') ?? false const message = result.getString('message') ?? '' return { ok, message, order: null } as DeliveryActionResultType } /** * 鑾峰彇褰撳墠涓氬姟鐢ㄦ埛 ID锛堜粠 akUserMapping 鎴栫紦瀛橈級 */ async function resolveCurrentAkUserIdForDelivery(): Promise { try { const id = await readCurrentAkUserId() if (id != null && id != '') { console.warn('[deliveryService] resolveCurrentAkUserIdForDelivery: from akUserMapping =', id) return id } } catch (e) { console.warn('[deliveryService] readCurrentAkUserId failed:', e) } try { const cached = uni.getStorageSync('ak_user_id') if (cached != null && String(cached) != '') { console.warn('[deliveryService] resolveCurrentAkUserIdForDelivery: from storage ak_user_id =', String(cached)) return String(cached) } } catch (e) {} try { const currentAkUser = uni.getStorageSync('current_ak_user') if (currentAkUser != null && String(currentAkUser) != '') { const obj = JSON.parse(String(currentAkUser)) as any if (obj != null && obj.id != null && String(obj.id) != '') { console.warn('[deliveryService] resolveCurrentAkUserIdForDelivery: from current_ak_user.id =', String(obj.id)) return String(obj.id) } } } catch (e) {} return '' } export async function rejectServiceOrder(orderId: string, reason: string): Promise { return rejectCareOrder(orderId, reason) } export async function markDeparted(orderId: string): Promise { return await startDepartById(orderId, createEmptyLocation()) } export async function markArrived(orderId: string): Promise { return await arriveOrderById(orderId, createEmptyLocation()) } export async function checkInServiceOrder(orderId: string, note: string, location: DeliveryLocationType | null = null): Promise { if (location == null) { return null } return await checkinOrderById(orderId, { location, note, photos: [] as Array, checkinMode: 'gps' }) } export async function startServiceOrder(orderId: string): Promise { return await startServiceById(orderId) } export async function submitServiceRecord(orderId: string, record: DeliveryServiceRecordType): Promise { return await saveRealServiceRecord(orderId, record) } export async function completeServiceOrder(orderId: string): Promise { return await finishService(orderId) } export async function submitAbnormalReport(orderId: string, report: DeliveryExceptionPayloadType): Promise { return submitCareAbnormalReport(orderId, report) } export async function updateOrderStatus(orderId: string, nextStatus: DeliveryOrderStatus, extraRemark: string = ''): Promise { return updateCareOrderStatus(orderId, nextStatus, extraRemark) } export async function getAbnormalReport(orderId: string): Promise { const order = getCareOrderDetail(orderId) return order != null ? order.abnormalReport : null }