467 lines
15 KiB
Plaintext
467 lines
15 KiB
Plaintext
import {
|
||
acceptDeliveryOrderById,
|
||
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,
|
||
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<DeliveryOrderType>
|
||
} as DeliveryDashboardType
|
||
}
|
||
|
||
async function getCurrentStaffIdOrEmpty(): Promise<string> {
|
||
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<DeliveryOrderType>): Array<DeliveryOrderType> {
|
||
const result = [] as Array<DeliveryOrderType>
|
||
for (let i = 0; i < orders.length; i++) {
|
||
if (hasOrderCoreInfo(orders[i])) {
|
||
result.push(orders[i])
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
function shouldFallbackOrders(orders: Array<DeliveryOrderType>): boolean {
|
||
if (orders.length == 0) {
|
||
return false
|
||
}
|
||
for (let i = 0; i < orders.length; i++) {
|
||
if (hasOrderCoreInfo(orders[i])) {
|
||
return false
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
|
||
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<DeliveryLoginResultType> {
|
||
return await loginDeliveryApi(payload)
|
||
}
|
||
|
||
export async function getDeliveryProfile(): Promise<DeliveryInfoType | null> {
|
||
const authResult = await requireDeliveryAuth({ redirectOnFail: false, toastOnFail: false })
|
||
if (!authResult.ok) {
|
||
return null
|
||
}
|
||
return authResult.deliveryInfo
|
||
}
|
||
|
||
export async function getDeliveryByUserId(userId: string): Promise<DeliveryInfoType | null> {
|
||
return await getDeliveryProfileByUserId(userId)
|
||
}
|
||
|
||
export async function getCurrentDeliverer(): Promise<DeliveryInfoType | null> {
|
||
return await getDeliveryProfile()
|
||
}
|
||
|
||
export async function checkDeliveryAccountByUserId(userId: string): Promise<DeliveryInfoType | null> {
|
||
return await getDeliveryProfileByUserId(userId)
|
||
}
|
||
|
||
export async function checkDeliveryAuth(): Promise<boolean> {
|
||
const result = await requireDeliveryAuth({ redirectOnFail: false, toastOnFail: false })
|
||
return result.ok
|
||
}
|
||
|
||
async function getCurrentStaffId(): Promise<string> {
|
||
// 旧 delivery RPC(dashboard / order_list)需要 ml_delivery_staff.id(513449ca...)
|
||
const deliveryInfo = getDeliveryInfo()
|
||
if (deliveryInfo != null && deliveryInfo.id != null && String(deliveryInfo.id) != '') {
|
||
console.warn('[deliveryService] getCurrentStaffId: 使用 deliveryStaffId =', String(deliveryInfo.id))
|
||
return String(deliveryInfo.id)
|
||
}
|
||
|
||
console.error('[deliveryService] getCurrentStaffId: 未获取到 deliveryStaffId')
|
||
return ''
|
||
}
|
||
|
||
function createEmptyLocation(): DeliveryLocationType {
|
||
return {
|
||
latitude: 0,
|
||
longitude: 0,
|
||
address: '',
|
||
time: new Date().toISOString().replace('T', ' ').substring(0, 19)
|
||
}
|
||
}
|
||
|
||
export async function getDeliveryDashboard(): Promise<DeliveryDashboardType> {
|
||
const staffId = await getCurrentStaffId()
|
||
if (staffId != '') {
|
||
return await getDeliveryDashboardByStaffId(staffId)
|
||
}
|
||
// staffId 为空时返回空 dashboard
|
||
console.error('[deliveryService] getDeliveryDashboard: staffId 为空,返回空数据')
|
||
return emptyDashboard()
|
||
}
|
||
|
||
export async function getDeliveryOrders(params: DeliveryOrderQueryType): Promise<Array<DeliveryOrderType>> {
|
||
const staffId = await getCurrentStaffId()
|
||
if (staffId != '') {
|
||
return await getDeliveryOrdersByStaffId(staffId, params)
|
||
}
|
||
// staffId 为空时返回空列表
|
||
console.error('[deliveryService] getDeliveryOrders: staffId 为空,返回空列表')
|
||
return [] as Array<DeliveryOrderType>
|
||
}
|
||
|
||
export async function getDeliveryOrderDetail(id: string): Promise<DeliveryOrderType | null> {
|
||
return await getDeliveryOrderDetailById(id)
|
||
}
|
||
|
||
export async function acceptDeliveryOrder(id: string): Promise<DeliveryOrderType | null> {
|
||
return await acceptDeliveryOrderById(id)
|
||
}
|
||
|
||
export async function rejectDeliveryOrder(id: string, reason: string): Promise<DeliveryOrderType | null> {
|
||
return rejectCareOrder(id, reason)
|
||
}
|
||
|
||
export async function startDepart(id: string, location: DeliveryLocationType): Promise<DeliveryOrderType | null> {
|
||
return await startDepartById(id, location)
|
||
}
|
||
|
||
export async function arriveOrder(id: string, location: DeliveryLocationType): Promise<DeliveryOrderType | null> {
|
||
return await arriveOrderById(id, location)
|
||
}
|
||
|
||
export async function checkinOrder(id: string, payload: DeliveryCheckinPayloadType): Promise<DeliveryOrderType | null> {
|
||
return await checkinOrderById(id, payload)
|
||
}
|
||
|
||
export async function startService(id: string): Promise<DeliveryOrderType | null> {
|
||
return await startServiceById(id)
|
||
}
|
||
|
||
export async function saveServiceProgress(id: string, payload: DeliveryProgressPayloadType): Promise<DeliveryOrderType | null> {
|
||
return await saveServiceProgressById(id, payload)
|
||
}
|
||
|
||
export async function uploadEvidence(id: string, phase: string, files: Array<string>): Promise<Array<any>> {
|
||
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<any>
|
||
}
|
||
|
||
export async function retryUploadEvidence(id: string, evidenceId: string): Promise<any | null> {
|
||
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<DeliveryOrderType | null> {
|
||
return submitCareAbnormalReport(id, payload)
|
||
}
|
||
|
||
export async function finishService(id: string, payload: DeliveryFinishPayloadType | null = null): Promise<DeliveryOrderType | null> {
|
||
const finishPayload = payload != null ? payload : {
|
||
serviceSummary: '',
|
||
signatureName: '',
|
||
confirmByFamily: false
|
||
} as DeliveryFinishPayloadType
|
||
return await finishServiceById(id, finishPayload)
|
||
}
|
||
|
||
export async function getDeliveryRecords(): Promise<Array<DeliveryRecordType>> {
|
||
return getCareRecords()
|
||
}
|
||
|
||
export async function getDeliveryMessages(): Promise<Array<DeliveryMessageType>> {
|
||
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<DeliveryInfoType | null> {
|
||
if (status == 'online' || status == 'resting' || status == 'busy') {
|
||
return updateDeliveryCareOnlineStatus(status)
|
||
}
|
||
return getDeliveryCareProfile()
|
||
}
|
||
|
||
export async function getDeliveryDashboardStats(): Promise<DeliveryDashboardType> {
|
||
return await getDeliveryDashboard()
|
||
}
|
||
|
||
export async function getPendingServiceOrders(): Promise<Array<DeliveryOrderType>> {
|
||
const orders = await getDeliveryOrders({ tab: 'pending', keyword: '' } as DeliveryOrderQueryType)
|
||
const validOrders = filterOrdersWithCoreInfo(orders)
|
||
if (validOrders.length > 0) {
|
||
return validOrders
|
||
}
|
||
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 fallbackOrders
|
||
}
|
||
}
|
||
return orders
|
||
}
|
||
|
||
export async function getTodayServiceOrders(): Promise<Array<DeliveryOrderType>> {
|
||
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<Array<DeliveryOrderType>> {
|
||
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<DeliveryOrderType | null> {
|
||
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<DeliveryOrderType | null> {
|
||
// 居家服务订单必须调用 rpc_homecare_accept_assignment_v2
|
||
// 不再调用 acceptDeliveryOrder / rpc_delivery_accept_order
|
||
const akUserId = await resolveCurrentAkUserIdForDelivery()
|
||
console.warn('[HOMECARE ACCEPT] acceptServiceOrder: orderId=', orderId, ' akUserId=', akUserId)
|
||
|
||
if (akUserId == '') {
|
||
uni.showToast({ title: '未获取到业务用户 ID,请重新登录', icon: 'none' })
|
||
return null
|
||
}
|
||
|
||
// 调用居家服务接单 RPC
|
||
const { acceptHomecareAssignmentV2 } = await import('@/api/delivery.uts')
|
||
const result = await acceptHomecareAssignmentV2(orderId, akUserId)
|
||
console.warn('[HOMECARE ACCEPT] rpc_homecare_accept_assignment_v2 result:', result)
|
||
|
||
// 刷新订单列表
|
||
await loadData()
|
||
return null
|
||
}
|
||
|
||
/**
|
||
* 获取当前业务用户 ID(从 akUserMapping 或缓存)
|
||
*/
|
||
async function resolveCurrentAkUserIdForDelivery(): Promise<string> {
|
||
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<DeliveryOrderType | null> {
|
||
return rejectCareOrder(orderId, reason)
|
||
}
|
||
|
||
export async function markDeparted(orderId: string): Promise<DeliveryOrderType | null> {
|
||
return await startDepartById(orderId, createEmptyLocation())
|
||
}
|
||
|
||
export async function markArrived(orderId: string): Promise<DeliveryOrderType | null> {
|
||
return await arriveOrderById(orderId, createEmptyLocation())
|
||
}
|
||
|
||
export async function checkInServiceOrder(orderId: string, note: string, location: DeliveryLocationType | null = null): Promise<DeliveryOrderType | null> {
|
||
if (location == null) {
|
||
return null
|
||
}
|
||
return await checkinOrderById(orderId, {
|
||
location,
|
||
note,
|
||
photos: [] as Array<string>,
|
||
checkinMode: 'gps'
|
||
})
|
||
}
|
||
|
||
export async function startServiceOrder(orderId: string): Promise<DeliveryOrderType | null> {
|
||
return await startServiceById(orderId)
|
||
}
|
||
|
||
export async function submitServiceRecord(orderId: string, record: DeliveryServiceRecordType): Promise<DeliveryOrderType | null> {
|
||
return await saveRealServiceRecord(orderId, record)
|
||
}
|
||
|
||
export async function completeServiceOrder(orderId: string): Promise<DeliveryOrderType | null> {
|
||
return await finishService(orderId)
|
||
}
|
||
|
||
export async function submitAbnormalReport(orderId: string, report: DeliveryExceptionPayloadType): Promise<DeliveryOrderType | null> {
|
||
return submitCareAbnormalReport(orderId, report)
|
||
}
|
||
|
||
export async function updateOrderStatus(orderId: string, nextStatus: DeliveryOrderStatus, extraRemark: string = ''): Promise<DeliveryOrderType | null> {
|
||
return updateCareOrderStatus(orderId, nextStatus, extraRemark)
|
||
}
|
||
|
||
export async function getAbnormalReport(orderId: string): Promise<DeliveryAbnormalReportType | null> {
|
||
const order = getCareOrderDetail(orderId)
|
||
return order != null ? order.abnormalReport : null
|
||
}
|