忽略本地报错信息文件
This commit is contained in:
@@ -6,6 +6,8 @@ import type { HomeServiceCatalogType, HomeServicePackageType } from '@/types/hom
|
||||
import type { DeliveryServiceRecordType } from '@/types/delivery.uts'
|
||||
import {
|
||||
getServiceOrderStatusText,
|
||||
isArrivalPendingStatus,
|
||||
normalizeOrderStatusCode,
|
||||
normalizeServiceOrderStatus,
|
||||
type ServiceOrderAddressSnapshotType,
|
||||
type ServiceEvidenceFileType,
|
||||
@@ -217,6 +219,7 @@ function shouldBypassEcCareTaskCreate(error: any): boolean {
|
||||
|| hasMissingColumnError(error, 'service_catalog_id')
|
||||
|| hasMissingColumnError(error, 'elder_name')
|
||||
|| hasMissingColumnError(error, 'contact_name')
|
||||
|| hasMissingColumnError(error, 'contact_phone')
|
||||
}
|
||||
|
||||
function readServiceItems(source: any): Array<DeliveryServiceItemType> {
|
||||
@@ -256,33 +259,79 @@ function buildDefaultServiceItems(order: DeliveryOrderType): Array<DeliveryServi
|
||||
names.push('用药情况核对')
|
||||
names.push('随访结论反馈')
|
||||
} else {
|
||||
names.push('上门签到确认')
|
||||
names.push('服务项目执行')
|
||||
names.push('服务过程记录')
|
||||
names.push('完成情况确认')
|
||||
}
|
||||
const result = [] as Array<DeliveryServiceItemType>
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
result.push({
|
||||
id: order.id + '-item-' + String(i + 1),
|
||||
name: names[i],
|
||||
required: true,
|
||||
completed: false,
|
||||
incompleteReason: '',
|
||||
remark: '',
|
||||
updatedAt: ''
|
||||
} as DeliveryServiceItemType)
|
||||
payload.address_snapshot_json = params.address as any
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
async function getCurrentStaffId(): Promise<string> {
|
||||
const userId = getCurrentUserId()
|
||||
if (userId == '') {
|
||||
return ''
|
||||
function buildEcCareTaskPayloadWithoutAddress(params: CreateServiceOrderParams, userId: string, requestId: string, taskId: string, taskNo: string, createdAt: string, appointmentTime: string | null): any {
|
||||
return {
|
||||
id: taskId,
|
||||
task_no: taskNo,
|
||||
request_id: requestId,
|
||||
user_id: userId,
|
||||
service_catalog_id: params.service.id,
|
||||
service_name: params.service.name,
|
||||
service_category: params.service.category,
|
||||
service_snapshot_json: buildServiceSnapshot(params),
|
||||
elder_name: params.recipientName,
|
||||
elder_phone: params.recipientPhone,
|
||||
elder_age: params.recipientAge,
|
||||
elder_gender: params.recipientGender,
|
||||
contact_name: params.contactName,
|
||||
contact_phone: params.contactPhone,
|
||||
scheduled_at: appointmentTime,
|
||||
remark: params.remark,
|
||||
status: 'ORDER_CREATED',
|
||||
created_at: createdAt,
|
||||
updated_at: createdAt
|
||||
} as any
|
||||
}
|
||||
|
||||
function parseTimeline(item: any): ServiceOrderTimelineItemType {
|
||||
return {
|
||||
id: readString(item, 'id'),
|
||||
orderId: readString(item, 'order_id'),
|
||||
fromStatus: readString(item, 'from_status'),
|
||||
toStatus: normalizeServiceOrderStatus(readString(item, 'to_status')),
|
||||
operatorId: readString(item, 'operator_id'),
|
||||
operatorRole: readString(item, 'operator_role'),
|
||||
remark: readString(item, 'remark'),
|
||||
createdAt: readString(item, 'created_at')
|
||||
}
|
||||
}
|
||||
|
||||
function parseReview(item: any): ServiceReviewType {
|
||||
return {
|
||||
id: readString(item, 'id'),
|
||||
orderId: readString(item, 'order_id'),
|
||||
userId: readString(item, 'user_id'),
|
||||
rating: readNumber(item, 'rating') == 0 ? 5 : readNumber(item, 'rating'),
|
||||
tags: safeParseArray(safeJsonField(item, 'tags_json')),
|
||||
content: readString(item, 'content'),
|
||||
createdAt: readString(item, 'created_at')
|
||||
}
|
||||
}
|
||||
|
||||
function parseExecutionRecord(item: any): ServiceExecutionRecordType {
|
||||
return {
|
||||
id: readString(item, 'id'),
|
||||
orderId: readString(item, 'order_id'),
|
||||
assignmentId: readString(item, 'assignment_id'),
|
||||
checkinTime: readString(item, 'checkin_time'),
|
||||
checkinLatitude: readNumber(item, 'checkin_latitude'),
|
||||
checkinLongitude: readNumber(item, 'checkin_longitude'),
|
||||
checkinAddress: readString(item, 'checkin_address'),
|
||||
serviceStartedAt: readString(item, 'service_started_at'),
|
||||
serviceFinishedAt: readString(item, 'service_finished_at'),
|
||||
actualDurationMinutes: readNumber(item, 'actual_duration_minutes'),
|
||||
serviceItemsJson: safeJsonField(item, 'service_items_json'),
|
||||
summary: readString(item, 'summary'),
|
||||
remark: readString(item, 'remark'),
|
||||
trackPointsJson: safeJsonField(item, 'track_points_json'),
|
||||
createdAt: readString(item, 'created_at'),
|
||||
updatedAt: readString(item, 'updated_at')
|
||||
}
|
||||
const profile = await getDeliveryProfileByUserId(userId)
|
||||
return profile != null ? profile.id : ''
|
||||
}
|
||||
|
||||
function getCurrentWorkerUserId(): string {
|
||||
@@ -479,6 +528,7 @@ function mapCareTaskToLegacyShape(item: any): any {
|
||||
appointment_time: readFirstString(item, ['scheduled_at', 'appointment_time']),
|
||||
remark: readString(item, 'remark'),
|
||||
status: derivedStatus,
|
||||
waiting_consumer_confirm: waitingConsumerConfirm,
|
||||
current_assignment_id: readFirstString(item, ['assignment_id', 'current_assignment_id']),
|
||||
current_staff_id: readFirstString(item, ['assigned_to', 'current_staff_id']),
|
||||
accepted_at: readString(item, 'accepted_at'),
|
||||
@@ -626,7 +676,7 @@ async function getCareTaskDetail(taskId: string): Promise<ServiceOrderType | nul
|
||||
parsed.dispatchStatus = parsed.currentStaffId != '' ? HOMECARE_DISPATCH_STATUS_ASSIGNED : HOMECARE_DISPATCH_STATUS_PENDING
|
||||
parsed.dispatchErrorCode = ''
|
||||
parsed.dispatchErrorMessage = ''
|
||||
return parsed
|
||||
return applyArrivalPendingState(parsed)
|
||||
}
|
||||
|
||||
async function tryCreateCareTask(params: CreateServiceOrderParams): Promise<ServiceOrderType | null> {
|
||||
@@ -748,7 +798,7 @@ async function getLegacyServiceOrderDetail(orderId: string): Promise<ServiceOrde
|
||||
}
|
||||
}
|
||||
}
|
||||
return parsed
|
||||
return applyArrivalPendingState(parsed)
|
||||
}
|
||||
|
||||
export function buildAddressSnapshot(address: UserAddress, latitude: number, longitude: number): ServiceOrderAddressSnapshotType {
|
||||
@@ -768,6 +818,197 @@ export function buildAddressSnapshot(address: UserAddress, latitude: number, lon
|
||||
}
|
||||
}
|
||||
|
||||
export function getHomecareOrderDisplayStatus(order: ServiceOrderType): string {
|
||||
if (order.paymentStatus == 1 && order.status == 'created' && isHomecarePaymentExpired(order)) {
|
||||
return '已超时未支付'
|
||||
}
|
||||
if (order.paymentStatus == 1 && order.status == 'created') {
|
||||
return '待付款'
|
||||
}
|
||||
if (order.paymentStatus == 2 && order.dispatchStatus == HOMECARE_DISPATCH_STATUS_PENDING) {
|
||||
return '待派单'
|
||||
}
|
||||
if (order.paymentStatus == 2 && order.dispatchStatus == HOMECARE_DISPATCH_STATUS_DISPATCHING) {
|
||||
return '正在派单'
|
||||
}
|
||||
if (order.paymentStatus == 2 && order.dispatchStatus == HOMECARE_DISPATCH_STATUS_FAILED) {
|
||||
return '派单未成功'
|
||||
}
|
||||
if (order.paymentStatus == 2 && order.dispatchStatus == HOMECARE_DISPATCH_STATUS_ASSIGNED) {
|
||||
return '已派单'
|
||||
}
|
||||
return getServiceOrderStatusText(order.status)
|
||||
}
|
||||
|
||||
function isHomecarePaymentExpired(order: ServiceOrderType): boolean {
|
||||
if (order.paymentStatus != 1 || order.status != 'created') {
|
||||
return false
|
||||
}
|
||||
const payExpireAt = order.payExpireAt != null ? order.payExpireAt : ''
|
||||
if (payExpireAt == '') {
|
||||
return false
|
||||
}
|
||||
const expireMs = Date.parse(payExpireAt)
|
||||
if (isNaN(expireMs)) {
|
||||
return false
|
||||
}
|
||||
return expireMs <= Date.now()
|
||||
}
|
||||
|
||||
export async function dispatchPaidHomecareOrder(orderId: string): Promise<HomecareDispatchResult> {
|
||||
if (orderId == null || orderId.trim() == '') {
|
||||
return {
|
||||
success: false,
|
||||
code: 'ORDER_ID_REQUIRED',
|
||||
message: '订单信息异常,请返回后重试',
|
||||
display_type: 'modal',
|
||||
retryable: false
|
||||
}
|
||||
}
|
||||
|
||||
// LEGACY/TODO: rpc_homecare_auto_dispatch 当前只操作 hss_service_orders(旧交易链)。
|
||||
// 对于 ec_care_tasks 新链(UUID 格式订单 ID),不要调用旧 RPC,避免错误回写旧表。
|
||||
if (shouldUseCareTaskPath(orderId)) {
|
||||
return {
|
||||
success: true,
|
||||
code: 'SYNC_IN_PROGRESS',
|
||||
message: '付款成功,服务安排信息正在同步中,请稍后在我的服务中查看。',
|
||||
display_type: 'toast',
|
||||
retryable: false,
|
||||
dispatch_status: HOMECARE_DISPATCH_STATUS_PENDING,
|
||||
order_id: orderId
|
||||
}
|
||||
}
|
||||
|
||||
const { data, error } = await supa.rpc('rpc_homecare_auto_dispatch', {
|
||||
p_order_id: orderId
|
||||
} as any)
|
||||
|
||||
if (error != null) {
|
||||
console.error('[homecare-dispatch] rpc failed:', error)
|
||||
return {
|
||||
success: false,
|
||||
code: 'RPC_EXECUTION_FAILED',
|
||||
message: '派单服务暂时异常,请稍后重试',
|
||||
display_type: 'modal',
|
||||
retryable: true,
|
||||
dispatch_status: 'failed',
|
||||
order_id: orderId
|
||||
}
|
||||
}
|
||||
|
||||
if (data == null) {
|
||||
return {
|
||||
success: false,
|
||||
code: 'RPC_EMPTY_RESULT',
|
||||
message: '未获取到派单结果,请稍后重试',
|
||||
display_type: 'modal',
|
||||
retryable: true,
|
||||
dispatch_status: 'failed',
|
||||
order_id: orderId
|
||||
}
|
||||
}
|
||||
|
||||
const result = plainObject(data)
|
||||
const successValue = result['success']
|
||||
const isSuccess = successValue === true || successValue === 'true' || (typeof successValue === 'boolean' && successValue)
|
||||
const code = readString(result, 'code')
|
||||
const message = readString(result, 'message')
|
||||
const displayType = readString(result, 'display_type')
|
||||
const retryable = result['retryable'] === true || result['retryable'] === 'true'
|
||||
const dispatchStatus = readString(result, 'dispatch_status')
|
||||
|
||||
if (isSuccess || code == 'DISPATCH_ASSIGNED' || code == 'ALREADY_ASSIGNED' || code == 'ALREADY_ASSIGNED_RECOVERED') {
|
||||
return {
|
||||
success: true,
|
||||
code: code != '' ? code : 'DISPATCH_ASSIGNED',
|
||||
message: message != '' ? message : '系统已为您匹配服务人员',
|
||||
display_type: displayType != '' ? displayType : 'none',
|
||||
retryable: false,
|
||||
dispatch_status: dispatchStatus != '' ? dispatchStatus : 'assigned',
|
||||
order_id: readString(result, 'order_id'),
|
||||
assignment_id: readString(result, 'assignment_id'),
|
||||
staff_id: readString(result, 'staff_id'),
|
||||
station_id: readString(result, 'station_id'),
|
||||
dispatch_distance_km: readNumber(result, 'dispatch_distance_km')
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: false,
|
||||
code: code != '' ? code : 'DISPATCH_FAILED',
|
||||
message: message != '' ? message : '派单失败,请稍后重试',
|
||||
display_type: displayType != '' ? displayType : 'modal',
|
||||
retryable: retryable,
|
||||
dispatch_status: dispatchStatus != '' ? dispatchStatus : 'failed',
|
||||
order_id: readString(result, 'order_id')
|
||||
}
|
||||
}
|
||||
|
||||
export function showHomecareDispatchFailureModal(orderId: string, result: HomecareDispatchResult, retryCallback: (id: string) => void): void {
|
||||
const code = result.code
|
||||
let title = '操作失败'
|
||||
let allowRetry = false
|
||||
|
||||
if (code == 'ORDER_ID_REQUIRED') {
|
||||
title = '操作失败'
|
||||
allowRetry = false
|
||||
} else if (code == 'UNAUTHENTICATED') {
|
||||
title = '请重新登录'
|
||||
allowRetry = false
|
||||
} else if (code == 'USER_PROFILE_NOT_FOUND') {
|
||||
title = '账户异常'
|
||||
allowRetry = false
|
||||
} else if (code == 'ORDER_NOT_FOUND') {
|
||||
title = '订单异常'
|
||||
allowRetry = false
|
||||
} else if (code == 'ORDER_ACCESS_DENIED') {
|
||||
title = '无权操作'
|
||||
allowRetry = false
|
||||
} else if (code == 'ORDER_NOT_PAID') {
|
||||
title = '暂不能派单'
|
||||
allowRetry = false
|
||||
} else if (code == 'ORDER_STATUS_NOT_DISPATCHABLE') {
|
||||
title = '暂不能派单'
|
||||
allowRetry = false
|
||||
} else if (code == 'NO_ONLINE_STAFF' || code == 'NO_STAFF_IN_SERVICE_STATION' || code == 'NO_QUALIFIED_STAFF' || code == 'NO_NEARBY_STAFF' || code == 'ALL_ELIGIBLE_STAFF_BUSY') {
|
||||
title = '暂未匹配成功'
|
||||
allowRetry = true
|
||||
} else if (code == 'DISPATCH_CONFLICT_RETRY') {
|
||||
title = '请重新尝试'
|
||||
allowRetry = true
|
||||
} else if (code == 'RPC_EXECUTION_FAILED' || code == 'RPC_EMPTY_RESULT') {
|
||||
title = '派单服务异常'
|
||||
allowRetry = true
|
||||
} else {
|
||||
title = '操作失败'
|
||||
allowRetry = result.retryable
|
||||
}
|
||||
|
||||
if (!allowRetry) {
|
||||
uni.showModal({
|
||||
title: title,
|
||||
content: result.message,
|
||||
showCancel: false,
|
||||
confirmText: '我知道了'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
uni.showModal({
|
||||
title: title,
|
||||
content: result.message,
|
||||
showCancel: true,
|
||||
cancelText: '稍后再试',
|
||||
confirmText: '重新派单',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
retryCallback(orderId)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function createServiceOrder(params: CreateServiceOrderParams): Promise<ServiceOrderType | null> {
|
||||
// 当前下单链路分为两层:
|
||||
// 1) 交易支付层:hss_service_orders(旧表,仍承担套餐价格快照与支付状态)。
|
||||
@@ -797,6 +1038,7 @@ export async function createServiceOrder(params: CreateServiceOrderParams): Prom
|
||||
user_id: userId,
|
||||
service_id: params.service.id,
|
||||
service_name: params.service.name,
|
||||
service_category: params.service.category != '' ? params.service.category : '居家服务',
|
||||
service_snapshot_json: serviceSnapshot,
|
||||
service_package_id: params.packageInfo.id,
|
||||
pricing_snapshot_json: pricingSnapshot,
|
||||
@@ -805,13 +1047,22 @@ export async function createServiceOrder(params: CreateServiceOrderParams): Prom
|
||||
total_amount: payableAmount,
|
||||
service_address_id: normalizeUuidOrNull(params.address.addressId),
|
||||
address_snapshot_json: params.address as any,
|
||||
service_lat: params.address.latitude != null ? params.address.latitude : null,
|
||||
service_lng: params.address.longitude != null ? params.address.longitude : null,
|
||||
recipient_name: params.recipientName,
|
||||
recipient_phone: params.recipientPhone,
|
||||
recipient_age: params.recipientAge,
|
||||
recipient_gender: params.recipientGender,
|
||||
elder_name: params.recipientName,
|
||||
elder_phone: params.recipientPhone,
|
||||
contact_name: params.contactName,
|
||||
contact_phone: params.contactPhone,
|
||||
appointment_time: appointmentTime,
|
||||
scheduled_at: appointmentTime,
|
||||
price: payableAmount,
|
||||
staff_income: payableAmount,
|
||||
duration_minutes: 90,
|
||||
request_id: '',
|
||||
remark: params.remark,
|
||||
status: 'created',
|
||||
payment_status: 1,
|
||||
|
||||
Reference in New Issue
Block a user