1746 lines
55 KiB
Plaintext
1746 lines
55 KiB
Plaintext
import type {
|
||
DeliveryCertificateType,
|
||
DeliveryCheckinPayloadType,
|
||
DeliveryDashboardType,
|
||
DeliveryTimelineItemType,
|
||
DeliveryExceptionPayloadType,
|
||
DeliveryFinishPayloadType,
|
||
DeliveryInfoType,
|
||
DeliveryLocationType,
|
||
DeliveryLoginPayloadType,
|
||
DeliveryLoginResultType,
|
||
DeliveryMessageType,
|
||
DeliveryOrderQueryType,
|
||
DeliveryOrderType,
|
||
DeliveryProgressPayloadType,
|
||
DeliveryRecordType,
|
||
DeliveryEvidenceRecordType,
|
||
DeliveryServiceItemType
|
||
} from '@/types/delivery.uts'
|
||
import supa, { ensureSupabaseReady } from '@/components/supadb/aksupainstance.uts'
|
||
import { getCurrentUser } from '@/utils/store.uts'
|
||
import type { UserProfile } from '@/types/mall-types.uts'
|
||
import { IS_TEST_MODE } from '@/ak/config.uts'
|
||
|
||
const DELIVERY_RPC_DASHBOARD = 'rpc_delivery_dashboard'
|
||
const DELIVERY_RPC_ORDER_LIST = 'rpc_delivery_order_list'
|
||
const DELIVERY_RPC_ORDER_DETAIL = 'rpc_delivery_order_detail'
|
||
const DELIVERY_RPC_ACCEPT_ORDER = 'rpc_delivery_accept_order'
|
||
const DELIVERY_RPC_REJECT_ORDER = 'rpc_delivery_reject_order'
|
||
const DELIVERY_RPC_START_DEPART = 'rpc_delivery_start_depart'
|
||
const DELIVERY_RPC_ARRIVE_ORDER = 'rpc_delivery_arrive_order'
|
||
const DELIVERY_RPC_CHECKIN_ORDER = 'rpc_delivery_checkin_order'
|
||
const DELIVERY_RPC_START_SERVICE = 'rpc_delivery_start_service'
|
||
const DELIVERY_RPC_SAVE_PROGRESS = 'rpc_delivery_save_progress'
|
||
const DELIVERY_RPC_UPLOAD_EVIDENCE = 'rpc_delivery_upload_evidence'
|
||
const DELIVERY_RPC_RETRY_EVIDENCE = 'rpc_delivery_retry_evidence'
|
||
const DELIVERY_RPC_SUBMIT_EXCEPTION = 'rpc_delivery_submit_exception'
|
||
const DELIVERY_RPC_FINISH_SERVICE = 'rpc_delivery_finish_service'
|
||
const DELIVERY_RPC_RECORD_LIST = 'rpc_delivery_record_list'
|
||
const DELIVERY_RPC_MESSAGE_LIST = 'rpc_delivery_message_list'
|
||
const DELIVERY_RPC_SET_ONLINE_STATUS = 'rpc_delivery_set_online_status'
|
||
const DELIVERY_MOCK_PROFILE_KEY = 'delivery_mock_profile'
|
||
const DELIVERY_MOCK_ORDERS_KEY = 'delivery_mock_orders'
|
||
const DELIVERY_FORCE_REMOTE_KEY = 'delivery_force_remote'
|
||
|
||
const missingDeliveryRpcNames = [] as Array<string>
|
||
|
||
function isMissingDeliveryRpc(functionName: string): boolean {
|
||
for (let i = 0; i < missingDeliveryRpcNames.length; i++) {
|
||
if (missingDeliveryRpcNames[i] == functionName) {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
function markMissingDeliveryRpc(functionName: string): void {
|
||
if (!isMissingDeliveryRpc(functionName)) {
|
||
missingDeliveryRpcNames.push(functionName)
|
||
}
|
||
}
|
||
|
||
function mapLoginError(rawData: UTSJSONObject): string {
|
||
const errorMsg = rawData.getString('msg') ?? rawData.getString('message') ?? rawData.getString('error') ?? ''
|
||
const errorCode = rawData.getString('error_code') ?? ''
|
||
if ((errorMsg.includes('email') && errorMsg.includes('confirm')) || errorCode === 'email_not_confirmed' || (errorMsg.includes('邮箱') && errorMsg.includes('确认'))) {
|
||
return '邮箱未确认,请先检查邮箱并点击确认链接'
|
||
}
|
||
if (errorMsg.includes('Invalid authentication credentials')) {
|
||
return '网关认证失败,请检查 delivery 端的 SUPA_URL 与 SUPA_KEY 是否属于同一套 Supabase 实例'
|
||
}
|
||
if (errorMsg.includes('Invalid login credentials') || errorCode === 'invalid_credentials' || errorMsg.includes('Invalid credentials') || errorMsg.includes('credentials') || errorMsg.includes('invalid')) {
|
||
return '用户名或密码错误'
|
||
}
|
||
return errorMsg != '' ? errorMsg : '登录失败,请重试'
|
||
}
|
||
|
||
function readObjectField(raw: any, key: string): any {
|
||
if (raw == null) {
|
||
return null
|
||
}
|
||
if (typeof raw.getJSONObject === 'function') {
|
||
const nested = raw.getJSONObject(key)
|
||
if (nested != null) {
|
||
return nested
|
||
}
|
||
}
|
||
try {
|
||
const plain = JSON.parse(JSON.stringify(raw)) as any
|
||
return plain[key]
|
||
} catch (error) {}
|
||
return null
|
||
}
|
||
|
||
function readStringField(raw: any, key: string): string {
|
||
if (raw == null) {
|
||
return ''
|
||
}
|
||
if (typeof raw.getString === 'function') {
|
||
return raw.getString(key) ?? ''
|
||
}
|
||
try {
|
||
const plain = JSON.parse(JSON.stringify(raw)) as any
|
||
const value = plain[key]
|
||
if (typeof value == 'string') {
|
||
return value
|
||
}
|
||
if (value != null) {
|
||
return String(value)
|
||
}
|
||
} catch (error) {}
|
||
return ''
|
||
}
|
||
|
||
function readNumberField(raw: any, key: string): number | null {
|
||
if (raw == null) {
|
||
return null
|
||
}
|
||
if (typeof raw.getNumber === 'function') {
|
||
return raw.getNumber(key)
|
||
}
|
||
try {
|
||
const plain = JSON.parse(JSON.stringify(raw)) as any
|
||
const value = plain[key]
|
||
if (typeof value == 'number') {
|
||
return value
|
||
}
|
||
} catch (error) {}
|
||
return null
|
||
}
|
||
|
||
function readBooleanField(raw: any, key: string): boolean | null {
|
||
if (raw == null) {
|
||
return null
|
||
}
|
||
if (typeof raw.getBoolean === 'function') {
|
||
return raw.getBoolean(key)
|
||
}
|
||
try {
|
||
const plain = JSON.parse(JSON.stringify(raw)) as any
|
||
const value = plain[key]
|
||
if (typeof value == 'boolean') {
|
||
return value
|
||
}
|
||
} catch (error) {}
|
||
return null
|
||
}
|
||
|
||
function normalizeDeliveryStatus(raw: any): 'active' | 'disabled' | 'locked' | 'suspended' {
|
||
const status = readNumberField(raw, 'status')
|
||
const isActive = readBooleanField(raw, 'is_active')
|
||
if (status === 0 || isActive === false) {
|
||
return 'disabled'
|
||
}
|
||
return 'active'
|
||
}
|
||
|
||
function normalizeOnlineStatus(raw: any): 'online' | 'resting' | 'busy' {
|
||
const value = readStringField(raw, 'online_status')
|
||
if (value == 'online' || value == 'busy') {
|
||
return value
|
||
}
|
||
return 'resting'
|
||
}
|
||
|
||
function normalizeCertificateStatus(raw: any): 'valid' | 'expired' | 'pending' {
|
||
const value = readStringField(raw, 'certificate_status')
|
||
if (value == 'valid' || value == 'expired') {
|
||
return value
|
||
}
|
||
return 'pending'
|
||
}
|
||
|
||
function normalizeStringArray(rawValue: string): Array<string> {
|
||
const value = rawValue.trim()
|
||
if (value == '') {
|
||
return [] as Array<string>
|
||
}
|
||
try {
|
||
const parsed = JSON.parse(value)
|
||
if (parsed instanceof Array) {
|
||
const result = [] as Array<string>
|
||
for (let i = 0; i < parsed.length; i++) {
|
||
const item = parsed[i]
|
||
if (typeof item == 'string') {
|
||
result.push(item)
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
} catch (error) {}
|
||
return [] as Array<string>
|
||
}
|
||
|
||
function readStationObject(raw: any): any {
|
||
const station = readObjectField(raw, 'station')
|
||
if (station != null) {
|
||
return station
|
||
}
|
||
const nested = readObjectField(raw, 'ml_delivery_stations')
|
||
if (nested != null) {
|
||
return nested
|
||
}
|
||
return null
|
||
}
|
||
|
||
function buildDeliveryInfoFromStaff(raw: any): DeliveryInfoType {
|
||
const id = readStringField(raw, 'id')
|
||
const station = readStationObject(raw)
|
||
const stationId = readStringField(raw, 'station_id')
|
||
const skillsRaw = readStringField(raw, 'skills')
|
||
const certificateExpireAt = readStringField(raw, 'certificate_expire_at')
|
||
const organizationName = station != null ? readStringField(station, 'name') : ''
|
||
return {
|
||
id,
|
||
userId: readStringField(raw, 'uid'),
|
||
staffNo: readStringField(raw, 'staff_no') != '' ? readStringField(raw, 'staff_no') : (id != '' ? 'DEL-' + id.substring(0, Math.min(8, id.length)).toUpperCase() : ''),
|
||
name: readStringField(raw, 'nickname') != '' ? readStringField(raw, 'nickname') : '服务人员',
|
||
phone: readStringField(raw, 'phone'),
|
||
role: 'delivery',
|
||
status: normalizeDeliveryStatus(raw),
|
||
organizationId: stationId,
|
||
organizationName: organizationName != '' ? organizationName : stationId,
|
||
certificates: [] as Array<any>,
|
||
certificateStatus: normalizeCertificateStatus(raw),
|
||
certificateExpireAt,
|
||
onlineStatus: normalizeOnlineStatus(raw),
|
||
serviceArea: readStringField(raw, 'service_area'),
|
||
skills: normalizeStringArray(skillsRaw),
|
||
avatarUrl: readStringField(raw, 'avatar'),
|
||
todayAccepted: 0,
|
||
todayServing: 0,
|
||
todayCompleted: 0,
|
||
usesMock: false
|
||
} as DeliveryInfoType
|
||
}
|
||
|
||
async function fetchDeliveryProfileFromRemote(userId: string): Promise<DeliveryInfoType | null> {
|
||
if (userId == '') {
|
||
return null
|
||
}
|
||
const selectFields = '*, station:ml_delivery_stations(id, name)'
|
||
try {
|
||
let response = await supa.from('ml_delivery_staff').select(selectFields).eq('uid', userId).limit(1).execute()
|
||
if (response.error == null && response.data != null) {
|
||
const rows = response.data as Array<UTSJSONObject>
|
||
if (rows.length > 0) {
|
||
return buildDeliveryInfoFromStaff(rows[0])
|
||
}
|
||
}
|
||
|
||
response = await supa.from('ml_delivery_staff').select(selectFields).eq('id', userId).limit(1).execute()
|
||
if (response.error == null && response.data != null) {
|
||
const rows = response.data as Array<UTSJSONObject>
|
||
if (rows.length > 0) {
|
||
return buildDeliveryInfoFromStaff(rows[0])
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.warn('[delivery api] 读取 ml_delivery_staff 失败,回退 mock:', error)
|
||
}
|
||
return null
|
||
}
|
||
|
||
function isDelivererRole(userInfo: UserProfile | null): boolean {
|
||
if (userInfo == null) {
|
||
return false
|
||
}
|
||
const role = userInfo.role ?? ''
|
||
return role == 'delivery' || role == 'Deliverer'
|
||
}
|
||
|
||
function shouldBypassDeliveryRpc(): boolean {
|
||
if (IS_TEST_MODE !== true) {
|
||
return false
|
||
}
|
||
const forceRemote = uni.getStorageSync(DELIVERY_FORCE_REMOTE_KEY)
|
||
if (forceRemote === true) {
|
||
return false
|
||
}
|
||
if (typeof forceRemote == 'string' && (forceRemote == 'true' || forceRemote == '1')) {
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
async function callDeliveryRpc(functionName: string, params: UTSJSONObject): Promise<any> {
|
||
if (shouldBypassDeliveryRpc()) {
|
||
return null
|
||
}
|
||
if (isMissingDeliveryRpc(functionName)) {
|
||
return null
|
||
}
|
||
try {
|
||
await ensureSupabaseReady()
|
||
const res: any = await supa.rpc(functionName, params)
|
||
if (res?.status === 404) {
|
||
markMissingDeliveryRpc(functionName)
|
||
console.warn('[delivery api] RPC 不存在,已切换 fallback:' + functionName)
|
||
return null
|
||
}
|
||
if (res?.error != null) {
|
||
throw res.error
|
||
}
|
||
return res.data
|
||
} catch (error) {
|
||
console.warn('[delivery api] RPC 调用失败,回退 mock:' + functionName, error)
|
||
return null
|
||
}
|
||
}
|
||
|
||
function normalizeRpcOrderList(data: any): Array<DeliveryOrderType> | null {
|
||
if (!Array.isArray(data)) {
|
||
return null
|
||
}
|
||
return data as Array<DeliveryOrderType>
|
||
}
|
||
|
||
function normalizeRpcMessages(data: any): Array<DeliveryMessageType> | null {
|
||
if (!Array.isArray(data)) {
|
||
return null
|
||
}
|
||
return data as Array<DeliveryMessageType>
|
||
}
|
||
|
||
function normalizeRpcRecords(data: any): Array<DeliveryRecordType> | null {
|
||
if (!Array.isArray(data)) {
|
||
return null
|
||
}
|
||
return data as Array<DeliveryRecordType>
|
||
}
|
||
|
||
function normalizeRpcEvidenceList(data: any): Array<DeliveryEvidenceRecordType> | null {
|
||
if (!Array.isArray(data)) {
|
||
return null
|
||
}
|
||
return data as Array<DeliveryEvidenceRecordType>
|
||
}
|
||
|
||
function normalizeRpcOrder(data: any): DeliveryOrderType | null {
|
||
if (data == null) {
|
||
return null
|
||
}
|
||
return data as DeliveryOrderType
|
||
}
|
||
|
||
function normalizeRpcDashboard(data: any): DeliveryDashboardType | null {
|
||
if (data == null) {
|
||
return null
|
||
}
|
||
return data as DeliveryDashboardType
|
||
}
|
||
|
||
function normalizeRpcDeliveryInfo(data: any): DeliveryInfoType | null {
|
||
if (data == null) {
|
||
return null
|
||
}
|
||
return data as DeliveryInfoType
|
||
}
|
||
|
||
function cloneDeliveryInfo(info: DeliveryInfoType): DeliveryInfoType {
|
||
return JSON.parse(JSON.stringify(info)) as DeliveryInfoType
|
||
}
|
||
|
||
function cloneDeliveryOrders(orders: Array<DeliveryOrderType>): Array<DeliveryOrderType> {
|
||
return JSON.parse(JSON.stringify(orders)) as Array<DeliveryOrderType>
|
||
}
|
||
|
||
function cloneDeliveryOrder(order: DeliveryOrderType): DeliveryOrderType {
|
||
return JSON.parse(JSON.stringify(order)) as DeliveryOrderType
|
||
}
|
||
|
||
function cloneDeliveryMessages(messages: Array<DeliveryMessageType>): Array<DeliveryMessageType> {
|
||
return JSON.parse(JSON.stringify(messages)) as Array<DeliveryMessageType>
|
||
}
|
||
|
||
function cloneDeliveryRecords(records: Array<DeliveryRecordType>): Array<DeliveryRecordType> {
|
||
return JSON.parse(JSON.stringify(records)) as Array<DeliveryRecordType>
|
||
}
|
||
|
||
function isObjectLike(value: any): boolean {
|
||
return value != null && typeof value == 'object'
|
||
}
|
||
|
||
function isValidDeliveryInfoCache(value: any): boolean {
|
||
if (!isObjectLike(value)) {
|
||
return false
|
||
}
|
||
const info = value as DeliveryInfoType
|
||
return typeof info.id == 'string' && typeof info.userId == 'string' && typeof info.name == 'string'
|
||
}
|
||
|
||
function isValidDeliveryOrdersCache(value: any): boolean {
|
||
if (!Array.isArray(value)) {
|
||
return false
|
||
}
|
||
for (let i = 0; i < value.length; i++) {
|
||
const item = value[i] as any
|
||
if (!isObjectLike(item) || typeof item.id != 'string' || typeof item.orderNo != 'string' || typeof item.status != 'string') {
|
||
return false
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
|
||
function currentDateTimeText(): string {
|
||
return new Date().toISOString().replace('T', ' ').substring(0, 19)
|
||
}
|
||
|
||
function buildMockCertificates(): Array<DeliveryCertificateType> {
|
||
return [
|
||
{
|
||
id: 'mock-cert-1',
|
||
name: '养老护理员职业技能证书',
|
||
status: 'valid',
|
||
expireAt: '2027-12-31',
|
||
issuer: '梅州市居家养老服务协会',
|
||
imageUrl: ''
|
||
} as DeliveryCertificateType,
|
||
{
|
||
id: 'mock-cert-2',
|
||
name: '慢病随访服务培训合格证',
|
||
status: 'valid',
|
||
expireAt: '长期有效',
|
||
issuer: '粤东健康照护培训中心',
|
||
imageUrl: ''
|
||
} as DeliveryCertificateType
|
||
] as Array<DeliveryCertificateType>
|
||
}
|
||
|
||
function buildMockServiceItems(orderId: string, serviceName: string): Array<DeliveryServiceItemType> {
|
||
return [
|
||
{
|
||
id: orderId + '-item-1',
|
||
name: serviceName + '签到核验',
|
||
required: true,
|
||
completed: true,
|
||
incompleteReason: '',
|
||
remark: '已完成身份核验与入户风险提示。',
|
||
updatedAt: '2026-05-18 08:45:00'
|
||
} as DeliveryServiceItemType,
|
||
{
|
||
id: orderId + '-item-2',
|
||
name: '生命体征记录',
|
||
required: true,
|
||
completed: true,
|
||
incompleteReason: '',
|
||
remark: '血压、脉搏、血氧记录完整。',
|
||
updatedAt: '2026-05-18 09:10:00'
|
||
} as DeliveryServiceItemType,
|
||
{
|
||
id: orderId + '-item-3',
|
||
name: '家属沟通与宣教',
|
||
required: true,
|
||
completed: false,
|
||
incompleteReason: '',
|
||
remark: '',
|
||
updatedAt: ''
|
||
} as DeliveryServiceItemType
|
||
] as Array<DeliveryServiceItemType>
|
||
}
|
||
|
||
function buildMockTimeline(orderNo: string, phase: string): Array<DeliveryTimelineItemType> {
|
||
return [
|
||
{
|
||
id: orderNo + '-tl-1',
|
||
title: '工单已生成',
|
||
time: '2026-05-18 07:30:00',
|
||
description: '系统已创建服务任务并进入调度流程。'
|
||
} as DeliveryTimelineItemType,
|
||
{
|
||
id: orderNo + '-tl-2',
|
||
title: '调度已派发',
|
||
time: '2026-05-18 07:50:00',
|
||
description: '工单已分配至当前服务人员。'
|
||
} as DeliveryTimelineItemType,
|
||
{
|
||
id: orderNo + '-tl-3',
|
||
title: phase,
|
||
time: '2026-05-18 08:20:00',
|
||
description: '当前环节已进入执行节点。'
|
||
} as DeliveryTimelineItemType
|
||
] as Array<DeliveryTimelineItemType>
|
||
}
|
||
|
||
function buildMockEvidence(orderId: string): Array<DeliveryEvidenceRecordType> {
|
||
return [
|
||
{
|
||
id: orderId + '-evi-1',
|
||
orderId,
|
||
phase: 'checkin',
|
||
fileType: 'image',
|
||
name: '到场签到照片',
|
||
url: '',
|
||
localPath: '/static/mock/checkin-' + orderId + '.jpg',
|
||
status: 'success',
|
||
progress: 100,
|
||
retryable: false,
|
||
createdAt: '2026-05-18 08:42:00'
|
||
} as DeliveryEvidenceRecordType
|
||
] as Array<DeliveryEvidenceRecordType>
|
||
}
|
||
|
||
function buildMockProfile(userId: string): DeliveryInfoType {
|
||
const resolvedUserId = userId != '' ? userId : 'mock-user-delivery-001'
|
||
return {
|
||
id: 'mock-staff-001',
|
||
userId: resolvedUserId,
|
||
staffNo: 'DEL-0520',
|
||
name: '陈护理',
|
||
phone: '13688886666',
|
||
role: 'delivery',
|
||
status: 'active',
|
||
organizationId: 'org-001',
|
||
organizationName: '梅州安康居家服务中心',
|
||
certificates: buildMockCertificates(),
|
||
certificateStatus: 'valid',
|
||
certificateExpireAt: '2027-12-31',
|
||
onlineStatus: 'online',
|
||
serviceArea: '梅江区 / 梅县区重点片区',
|
||
skills: ['基础护理', '慢病随访', '康复指导'],
|
||
avatarUrl: '',
|
||
todayAccepted: 0,
|
||
todayServing: 0,
|
||
todayCompleted: 0,
|
||
usesMock: true
|
||
} as DeliveryInfoType
|
||
}
|
||
|
||
function buildMockOrders(profile: DeliveryInfoType): Array<DeliveryOrderType> {
|
||
return [
|
||
{
|
||
id: 'mock-order-001',
|
||
orderNo: 'YS202605180001',
|
||
serviceType: '基础照护',
|
||
serviceName: '基础上门护理',
|
||
serviceItems: buildMockServiceItems('mock-order-001', '基础上门护理'),
|
||
elderId: 'elder-001',
|
||
elderNameMasked: '李奶奶',
|
||
elderPhoneMasked: '138****1024',
|
||
fullElderName: '李秀珍',
|
||
fullPhone: '13800131024',
|
||
addressSummary: '梅江区江南路 18 号 2 栋 602',
|
||
fullAddress: '广东省梅州市梅江区江南路 18 号 2 栋 602 室',
|
||
latitude: 24.2898,
|
||
longitude: 116.1179,
|
||
appointmentStartTime: '2026-05-18 09:00',
|
||
appointmentEndTime: '2026-05-18 11:00',
|
||
estimatedDuration: 120,
|
||
actualStartTime: '',
|
||
actualEndTime: '',
|
||
status: 'pending_accept',
|
||
statusText: '待接单',
|
||
statusTone: 'warning',
|
||
riskTags: ['跌倒风险', '晨间血压波动'],
|
||
careLevel: '护理二级',
|
||
merchantId: 'merchant-001',
|
||
merchantName: '梅州安康居家服务中心',
|
||
deliveryStaffId: profile.id,
|
||
deliveryStaffName: profile.name,
|
||
acceptTime: '',
|
||
departTime: '',
|
||
arriveTime: '',
|
||
checkinTime: '',
|
||
finishTime: '',
|
||
cancelReason: '',
|
||
exceptionType: '',
|
||
exceptionDesc: '',
|
||
evidenceList: [] as Array<DeliveryEvidenceRecordType>,
|
||
signatureUrl: '',
|
||
signatureName: '',
|
||
satisfactionStatus: '待评价',
|
||
settlementStatus: '待结算',
|
||
archiveStatus: '未归档',
|
||
createdAt: '2026-05-18 07:30:00',
|
||
updatedAt: '2026-05-18 07:50:00',
|
||
contactName: '李晓兰',
|
||
contactPhone: '13900139000',
|
||
notices: ['入户前需电话确认', '注意老人步态不稳'],
|
||
timeline: buildMockTimeline('YS202605180001', '等待服务人员接单'),
|
||
serviceSummary: '',
|
||
progressNote: '',
|
||
distanceKm: '2.4km',
|
||
allowCheckinRadiusMeters: 100,
|
||
lastLocation: null,
|
||
trackPoints: [] as Array<DeliveryLocationType>
|
||
} as DeliveryOrderType,
|
||
{
|
||
id: 'mock-order-002',
|
||
orderNo: 'YS202605180002',
|
||
serviceType: '康复指导',
|
||
serviceName: '居家康复训练指导',
|
||
serviceItems: buildMockServiceItems('mock-order-002', '康复训练'),
|
||
elderId: 'elder-002',
|
||
elderNameMasked: '张爷爷',
|
||
elderPhoneMasked: '137****2233',
|
||
fullElderName: '张志坤',
|
||
fullPhone: '13700132233',
|
||
addressSummary: '梅县区新城锦绣花园 5 栋 1403',
|
||
fullAddress: '广东省梅州市梅县区新城锦绣花园 5 栋 1403 室',
|
||
latitude: 24.3071,
|
||
longitude: 116.1365,
|
||
appointmentStartTime: '2026-05-18 10:30',
|
||
appointmentEndTime: '2026-05-18 12:00',
|
||
estimatedDuration: 90,
|
||
actualStartTime: '',
|
||
actualEndTime: '',
|
||
status: 'accepted',
|
||
statusText: '待出发',
|
||
statusTone: 'primary',
|
||
riskTags: ['术后恢复'],
|
||
careLevel: '康复随访',
|
||
merchantId: 'merchant-001',
|
||
merchantName: '梅州安康居家服务中心',
|
||
deliveryStaffId: profile.id,
|
||
deliveryStaffName: profile.name,
|
||
acceptTime: '2026-05-18 08:00:00',
|
||
departTime: '',
|
||
arriveTime: '',
|
||
checkinTime: '',
|
||
finishTime: '',
|
||
cancelReason: '',
|
||
exceptionType: '',
|
||
exceptionDesc: '',
|
||
evidenceList: [] as Array<DeliveryEvidenceRecordType>,
|
||
signatureUrl: '',
|
||
signatureName: '',
|
||
satisfactionStatus: '待评价',
|
||
settlementStatus: '待结算',
|
||
archiveStatus: '未归档',
|
||
createdAt: '2026-05-18 07:40:00',
|
||
updatedAt: '2026-05-18 08:00:00',
|
||
contactName: '张春梅',
|
||
contactPhone: '13600136666',
|
||
notices: ['需携带康复弹力带', '家属会同步在场'],
|
||
timeline: buildMockTimeline('YS202605180002', '已接单,等待出发'),
|
||
serviceSummary: '',
|
||
progressNote: '',
|
||
distanceKm: '5.8km',
|
||
allowCheckinRadiusMeters: 120,
|
||
lastLocation: null,
|
||
trackPoints: [] as Array<DeliveryLocationType>
|
||
} as DeliveryOrderType,
|
||
{
|
||
id: 'mock-order-003',
|
||
orderNo: 'YS202605180003',
|
||
serviceType: '慢病随访',
|
||
serviceName: '慢病健康随访',
|
||
serviceItems: buildMockServiceItems('mock-order-003', '慢病随访'),
|
||
elderId: 'elder-003',
|
||
elderNameMasked: '黄阿姨',
|
||
elderPhoneMasked: '135****5566',
|
||
fullElderName: '黄玉英',
|
||
fullPhone: '13500135566',
|
||
addressSummary: '梅江区学海路康养公寓 A 座 907',
|
||
fullAddress: '广东省梅州市梅江区学海路康养公寓 A 座 907 室',
|
||
latitude: 24.2861,
|
||
longitude: 116.1231,
|
||
appointmentStartTime: '2026-05-18 13:30',
|
||
appointmentEndTime: '2026-05-18 15:00',
|
||
estimatedDuration: 90,
|
||
actualStartTime: '',
|
||
actualEndTime: '',
|
||
status: 'arrived',
|
||
statusText: '待签到',
|
||
statusTone: 'primary',
|
||
riskTags: ['糖尿病', '需测血糖'],
|
||
careLevel: '慢病管理',
|
||
merchantId: 'merchant-001',
|
||
merchantName: '梅州安康居家服务中心',
|
||
deliveryStaffId: profile.id,
|
||
deliveryStaffName: profile.name,
|
||
acceptTime: '2026-05-18 08:10:00',
|
||
departTime: '2026-05-18 13:00:00',
|
||
arriveTime: '2026-05-18 13:22:00',
|
||
checkinTime: '',
|
||
finishTime: '',
|
||
cancelReason: '',
|
||
exceptionType: '',
|
||
exceptionDesc: '',
|
||
evidenceList: [] as Array<DeliveryEvidenceRecordType>,
|
||
signatureUrl: '',
|
||
signatureName: '',
|
||
satisfactionStatus: '待评价',
|
||
settlementStatus: '待结算',
|
||
archiveStatus: '未归档',
|
||
createdAt: '2026-05-18 08:00:00',
|
||
updatedAt: '2026-05-18 13:22:00',
|
||
contactName: '黄晓娟',
|
||
contactPhone: '13500130088',
|
||
notices: ['入户前请确认血糖试纸数量', '注意老人午后低血糖风险'],
|
||
timeline: buildMockTimeline('YS202605180003', '已到达服务地点'),
|
||
serviceSummary: '',
|
||
progressNote: '已联系家属,准备入户签到。',
|
||
distanceKm: '1.1km',
|
||
allowCheckinRadiusMeters: 80,
|
||
lastLocation: {
|
||
latitude: 24.2861,
|
||
longitude: 116.1231,
|
||
address: '康养公寓门口',
|
||
time: '2026-05-18 13:22:00'
|
||
} as DeliveryLocationType,
|
||
trackPoints: [] as Array<DeliveryLocationType>
|
||
} as DeliveryOrderType,
|
||
{
|
||
id: 'mock-order-004',
|
||
orderNo: 'YS202605180004',
|
||
serviceType: '居家护理',
|
||
serviceName: '压疮护理与翻身指导',
|
||
serviceItems: [
|
||
{
|
||
id: 'mock-order-004-item-1',
|
||
name: '压疮护理',
|
||
required: true,
|
||
completed: true,
|
||
incompleteReason: '',
|
||
remark: '已完成创面清洁与敷料更换。',
|
||
updatedAt: '2026-05-18 14:25:00'
|
||
} as DeliveryServiceItemType,
|
||
{
|
||
id: 'mock-order-004-item-2',
|
||
name: '翻身指导',
|
||
required: true,
|
||
completed: true,
|
||
incompleteReason: '',
|
||
remark: '已向家属示范翻身角度与频次。',
|
||
updatedAt: '2026-05-18 14:40:00'
|
||
} as DeliveryServiceItemType,
|
||
{
|
||
id: 'mock-order-004-item-3',
|
||
name: '家属签字确认',
|
||
required: true,
|
||
completed: false,
|
||
incompleteReason: '',
|
||
remark: '',
|
||
updatedAt: ''
|
||
} as DeliveryServiceItemType
|
||
] as Array<DeliveryServiceItemType>,
|
||
elderId: 'elder-004',
|
||
elderNameMasked: '陈伯伯',
|
||
elderPhoneMasked: '139****3301',
|
||
fullElderName: '陈国辉',
|
||
fullPhone: '13900133301',
|
||
addressSummary: '梅县区扶老社区 11 栋 203',
|
||
fullAddress: '广东省梅州市梅县区扶老社区 11 栋 203 室',
|
||
latitude: 24.3022,
|
||
longitude: 116.1441,
|
||
appointmentStartTime: '2026-05-18 14:00',
|
||
appointmentEndTime: '2026-05-18 16:00',
|
||
estimatedDuration: 120,
|
||
actualStartTime: '2026-05-18 14:05:00',
|
||
actualEndTime: '',
|
||
status: 'serving',
|
||
statusText: '服务中',
|
||
statusTone: 'primary',
|
||
riskTags: ['卧床护理', '家属需培训'],
|
||
careLevel: '护理三级',
|
||
merchantId: 'merchant-001',
|
||
merchantName: '梅州安康居家服务中心',
|
||
deliveryStaffId: profile.id,
|
||
deliveryStaffName: profile.name,
|
||
acceptTime: '2026-05-18 09:20:00',
|
||
departTime: '2026-05-18 13:20:00',
|
||
arriveTime: '2026-05-18 13:55:00',
|
||
checkinTime: '2026-05-18 14:00:00',
|
||
finishTime: '',
|
||
cancelReason: '',
|
||
exceptionType: '',
|
||
exceptionDesc: '',
|
||
evidenceList: buildMockEvidence('mock-order-004'),
|
||
signatureUrl: '',
|
||
signatureName: '',
|
||
satisfactionStatus: '待评价',
|
||
settlementStatus: '待结算',
|
||
archiveStatus: '未归档',
|
||
createdAt: '2026-05-18 09:00:00',
|
||
updatedAt: '2026-05-18 14:40:00',
|
||
contactName: '陈丽芳',
|
||
contactPhone: '13800136660',
|
||
notices: ['护理过程注意皮肤完整性', '家属需学习翻身技巧'],
|
||
timeline: buildMockTimeline('YS202605180004', '服务执行中'),
|
||
serviceSummary: '已完成基础护理与翻身指导,待家属签字确认。',
|
||
progressNote: '创面情况稳定,已完成阶段性护理。',
|
||
distanceKm: '3.6km',
|
||
allowCheckinRadiusMeters: 100,
|
||
lastLocation: {
|
||
latitude: 24.3022,
|
||
longitude: 116.1441,
|
||
address: '扶老社区 11 栋 203 室',
|
||
time: '2026-05-18 14:00:00'
|
||
} as DeliveryLocationType,
|
||
trackPoints: [
|
||
{
|
||
latitude: 24.3001,
|
||
longitude: 116.1412,
|
||
address: '扶老社区北门',
|
||
time: '2026-05-18 13:48:00'
|
||
} as DeliveryLocationType,
|
||
{
|
||
latitude: 24.3022,
|
||
longitude: 116.1441,
|
||
address: '扶老社区 11 栋 203 室',
|
||
time: '2026-05-18 14:00:00'
|
||
} as DeliveryLocationType
|
||
] as Array<DeliveryLocationType>
|
||
} as DeliveryOrderType,
|
||
{
|
||
id: 'mock-order-005',
|
||
orderNo: 'YS202605180005',
|
||
serviceType: '异常跟进',
|
||
serviceName: '用药异常上报处理',
|
||
serviceItems: buildMockServiceItems('mock-order-005', '异常处理'),
|
||
elderId: 'elder-005',
|
||
elderNameMasked: '王阿婆',
|
||
elderPhoneMasked: '134****7744',
|
||
fullElderName: '王月兰',
|
||
fullPhone: '13400137744',
|
||
addressSummary: '梅江区东汇城旁康颐楼 3 单元 1204',
|
||
fullAddress: '广东省梅州市梅江区东汇城旁康颐楼 3 单元 1204 室',
|
||
latitude: 24.2932,
|
||
longitude: 116.1205,
|
||
appointmentStartTime: '2026-05-18 16:00',
|
||
appointmentEndTime: '2026-05-18 17:00',
|
||
estimatedDuration: 60,
|
||
actualStartTime: '2026-05-18 16:05:00',
|
||
actualEndTime: '',
|
||
status: 'exception_pending',
|
||
statusText: '异常处理中',
|
||
statusTone: 'warning',
|
||
riskTags: ['用药异常', '需医生回访'],
|
||
careLevel: '异常处置',
|
||
merchantId: 'merchant-001',
|
||
merchantName: '梅州安康居家服务中心',
|
||
deliveryStaffId: profile.id,
|
||
deliveryStaffName: profile.name,
|
||
acceptTime: '2026-05-18 15:20:00',
|
||
departTime: '2026-05-18 15:35:00',
|
||
arriveTime: '2026-05-18 15:58:00',
|
||
checkinTime: '2026-05-18 16:03:00',
|
||
finishTime: '',
|
||
cancelReason: '',
|
||
exceptionType: 'elder_health_abnormal',
|
||
exceptionDesc: '老人午后血压异常升高,已建议暂停训练并等待医生回访。',
|
||
evidenceList: buildMockEvidence('mock-order-005'),
|
||
signatureUrl: '',
|
||
signatureName: '',
|
||
satisfactionStatus: '待处理',
|
||
settlementStatus: '待确认',
|
||
archiveStatus: '未归档',
|
||
createdAt: '2026-05-18 15:00:00',
|
||
updatedAt: '2026-05-18 16:10:00',
|
||
contactName: '王秀玲',
|
||
contactPhone: '13600139922',
|
||
notices: ['优先联系家属', '记录老人异常表现并上传照片'],
|
||
timeline: buildMockTimeline('YS202605180005', '异常已上报,等待处理'),
|
||
serviceSummary: '发现老人血压异常升高,已完成初步安抚并联系家属。',
|
||
progressNote: '异常已同步机构值班护士。',
|
||
distanceKm: '4.2km',
|
||
allowCheckinRadiusMeters: 100,
|
||
lastLocation: {
|
||
latitude: 24.2932,
|
||
longitude: 116.1205,
|
||
address: '康颐楼 3 单元 1204 室',
|
||
time: '2026-05-18 16:03:00'
|
||
} as DeliveryLocationType,
|
||
trackPoints: [] as Array<DeliveryLocationType>
|
||
} as DeliveryOrderType,
|
||
{
|
||
id: 'mock-order-006',
|
||
orderNo: 'YS202605170006',
|
||
serviceType: '康复护理',
|
||
serviceName: '术后恢复陪护',
|
||
serviceItems: [
|
||
{
|
||
id: 'mock-order-006-item-1',
|
||
name: '步态训练',
|
||
required: true,
|
||
completed: true,
|
||
incompleteReason: '',
|
||
remark: '完成 15 分钟辅助行走训练。',
|
||
updatedAt: '2026-05-17 15:10:00'
|
||
} as DeliveryServiceItemType,
|
||
{
|
||
id: 'mock-order-006-item-2',
|
||
name: '术后注意事项宣教',
|
||
required: true,
|
||
completed: true,
|
||
incompleteReason: '',
|
||
remark: '已向家属说明饮食与休息要求。',
|
||
updatedAt: '2026-05-17 15:28:00'
|
||
} as DeliveryServiceItemType
|
||
] as Array<DeliveryServiceItemType>,
|
||
elderId: 'elder-006',
|
||
elderNameMasked: '刘叔叔',
|
||
elderPhoneMasked: '133****6655',
|
||
fullElderName: '刘建华',
|
||
fullPhone: '13300136655',
|
||
addressSummary: '梅江区和顺苑 9 栋 401',
|
||
fullAddress: '广东省梅州市梅江区和顺苑 9 栋 401 室',
|
||
latitude: 24.2806,
|
||
longitude: 116.1115,
|
||
appointmentStartTime: '2026-05-17 14:00',
|
||
appointmentEndTime: '2026-05-17 15:30',
|
||
estimatedDuration: 90,
|
||
actualStartTime: '2026-05-17 14:05:00',
|
||
actualEndTime: '2026-05-17 15:32:00',
|
||
status: 'completed',
|
||
statusText: '已完成',
|
||
statusTone: 'success',
|
||
riskTags: ['术后恢复'],
|
||
careLevel: '康复照护',
|
||
merchantId: 'merchant-001',
|
||
merchantName: '梅州安康居家服务中心',
|
||
deliveryStaffId: profile.id,
|
||
deliveryStaffName: profile.name,
|
||
acceptTime: '2026-05-17 12:40:00',
|
||
departTime: '2026-05-17 13:20:00',
|
||
arriveTime: '2026-05-17 13:55:00',
|
||
checkinTime: '2026-05-17 14:00:00',
|
||
finishTime: '2026-05-17 15:32:00',
|
||
cancelReason: '',
|
||
exceptionType: '',
|
||
exceptionDesc: '',
|
||
evidenceList: buildMockEvidence('mock-order-006'),
|
||
signatureUrl: '',
|
||
signatureName: '刘建华',
|
||
satisfactionStatus: '已评价',
|
||
settlementStatus: '已结算',
|
||
archiveStatus: '已归档',
|
||
createdAt: '2026-05-17 12:20:00',
|
||
updatedAt: '2026-05-17 15:32:00',
|
||
contactName: '刘晓芳',
|
||
contactPhone: '13800132299',
|
||
notices: ['术后行动缓慢,注意搀扶'],
|
||
timeline: buildMockTimeline('YS202605170006', '服务完成待回访'),
|
||
serviceSummary: '术后恢复训练顺利完成,家属已确认并签字。',
|
||
progressNote: '服务完成,建议两日后再次回访。',
|
||
distanceKm: '6.1km',
|
||
allowCheckinRadiusMeters: 100,
|
||
lastLocation: {
|
||
latitude: 24.2806,
|
||
longitude: 116.1115,
|
||
address: '和顺苑 9 栋 401 室',
|
||
time: '2026-05-17 15:32:00'
|
||
} as DeliveryLocationType,
|
||
trackPoints: [] as Array<DeliveryLocationType>
|
||
} as DeliveryOrderType
|
||
] as Array<DeliveryOrderType>
|
||
}
|
||
|
||
function readMockDeliveryInfo(): DeliveryInfoType | null {
|
||
const cached = uni.getStorageSync(DELIVERY_MOCK_PROFILE_KEY)
|
||
if (!isValidDeliveryInfoCache(cached)) {
|
||
return null
|
||
}
|
||
return cached as DeliveryInfoType
|
||
}
|
||
|
||
function persistMockDeliveryInfo(info: DeliveryInfoType): void {
|
||
uni.setStorageSync(DELIVERY_MOCK_PROFILE_KEY, cloneDeliveryInfo(info))
|
||
}
|
||
|
||
function readMockOrders(): Array<DeliveryOrderType> | null {
|
||
const cached = uni.getStorageSync(DELIVERY_MOCK_ORDERS_KEY)
|
||
if (!isValidDeliveryOrdersCache(cached)) {
|
||
return null
|
||
}
|
||
return cached as Array<DeliveryOrderType>
|
||
}
|
||
|
||
function persistMockOrders(orders: Array<DeliveryOrderType>): void {
|
||
uni.setStorageSync(DELIVERY_MOCK_ORDERS_KEY, cloneDeliveryOrders(orders))
|
||
}
|
||
|
||
function ensureMockProfile(userId: string): DeliveryInfoType {
|
||
const cached = readMockDeliveryInfo()
|
||
if (cached != null) {
|
||
if (cached.userId == '' && userId != '') {
|
||
cached.userId = userId
|
||
persistMockDeliveryInfo(cached)
|
||
}
|
||
return cached
|
||
}
|
||
const profile = buildMockProfile(userId)
|
||
persistMockDeliveryInfo(profile)
|
||
return profile
|
||
}
|
||
|
||
function ensureMockOrders(userId: string): Array<DeliveryOrderType> {
|
||
const cached = readMockOrders()
|
||
if (cached != null && cached.length > 0) {
|
||
return cached
|
||
}
|
||
const profile = ensureMockProfile(userId)
|
||
const orders = buildMockOrders(profile)
|
||
persistMockOrders(orders)
|
||
return orders
|
||
}
|
||
|
||
function isPendingDepartStatus(status: string): boolean {
|
||
return status == 'accepted' || status == 'on_the_way' || status == 'arrived'
|
||
}
|
||
|
||
function isServingStatus(status: string): boolean {
|
||
return status == 'checked_in' || status == 'serving' || status == 'pending_submit' || status == 'pending_acceptance'
|
||
}
|
||
|
||
function isCompletedStatus(status: string): boolean {
|
||
return status == 'completed' || status == 'settled' || status == 'archived'
|
||
}
|
||
|
||
function buildMockProfileWithStats(userId: string): DeliveryInfoType {
|
||
const profile = cloneDeliveryInfo(ensureMockProfile(userId))
|
||
const orders = ensureMockOrders(userId)
|
||
let acceptedCount = 0
|
||
let servingCount = 0
|
||
let completedCount = 0
|
||
for (let i = 0; i < orders.length; i++) {
|
||
if (orders[i].acceptTime != '') {
|
||
acceptedCount++
|
||
}
|
||
if (isServingStatus(orders[i].status)) {
|
||
servingCount++
|
||
}
|
||
if (isCompletedStatus(orders[i].status)) {
|
||
completedCount++
|
||
}
|
||
}
|
||
profile.todayAccepted = acceptedCount
|
||
profile.todayServing = servingCount
|
||
profile.todayCompleted = completedCount
|
||
profile.usesMock = true
|
||
return profile
|
||
}
|
||
|
||
function buildMockMessages(orders: Array<DeliveryOrderType>): Array<DeliveryMessageType> {
|
||
return [
|
||
{
|
||
id: 'mock-msg-1',
|
||
title: '新工单待接单',
|
||
content: '基础照护 · 基础上门护理已分配给你,服务对象:李奶奶,预约时间:2026-05-18 09:00,请及时确认接单并做好上门准备。',
|
||
type: 'order',
|
||
createdAt: '2026-05-18 08:20',
|
||
read: false,
|
||
orderId: orders[0].id
|
||
} as DeliveryMessageType,
|
||
{
|
||
id: 'mock-msg-2',
|
||
title: '出发提醒',
|
||
content: '康复指导 · 居家康复训练指导将在 30 分钟后开始,服务地址:梅县区新城锦绣花园 5 栋 1403,请提前规划路线并按时出发。',
|
||
type: 'reminder',
|
||
createdAt: '2026-05-18 10:00',
|
||
read: false,
|
||
orderId: orders[1].id
|
||
} as DeliveryMessageType,
|
||
{
|
||
id: 'mock-msg-3',
|
||
title: '异常处理提醒',
|
||
content: '慢病随访工单出现异常:当前暂时无法联系服务对象,请尽快查看工单详情并提交处理结果。',
|
||
type: 'exception',
|
||
createdAt: '2026-05-18 10:35',
|
||
read: false,
|
||
orderId: orders[4].id
|
||
} as DeliveryMessageType,
|
||
{
|
||
id: 'mock-msg-4',
|
||
title: '工单改派通知',
|
||
content: '平台已将“陪诊协助 · 复诊陪同”改派给你,预约时间:2026-05-18 14:30,请及时查看服务要求与上门信息。',
|
||
type: 'dispatch',
|
||
createdAt: '2026-05-18 11:10',
|
||
read: false,
|
||
orderId: orders[3].id
|
||
} as DeliveryMessageType,
|
||
{
|
||
id: 'mock-msg-5',
|
||
title: '签到提醒',
|
||
content: '你已接近服务地点,请在到达后完成签到,签到成功后即可开始服务记录。',
|
||
type: 'checkin',
|
||
createdAt: '2026-05-18 13:20',
|
||
read: true,
|
||
orderId: orders[2].id
|
||
} as DeliveryMessageType,
|
||
{
|
||
id: 'mock-msg-6',
|
||
title: '服务验收通过',
|
||
content: '基础照护工单已完成验收,服务对象家属已确认本次服务,相关记录已同步更新。',
|
||
type: 'result',
|
||
createdAt: '2026-05-17 18:40',
|
||
read: true,
|
||
orderId: orders[5].id
|
||
} as DeliveryMessageType,
|
||
{
|
||
id: 'mock-msg-7',
|
||
title: '结算通知',
|
||
content: '昨日完成的 3 个服务工单已进入结算流程,请在“我的-服务记录”中查看结算进度。',
|
||
type: 'settlement',
|
||
createdAt: '2026-05-17 09:15',
|
||
read: true,
|
||
orderId: ''
|
||
} as DeliveryMessageType,
|
||
{
|
||
id: 'mock-msg-8',
|
||
title: '系统公告',
|
||
content: '请服务人员上门前核对服务对象信息,服务过程中注意留痕记录,并按规范完成异常上报。',
|
||
type: 'notice',
|
||
createdAt: '2026-05-16 16:00',
|
||
read: true,
|
||
orderId: ''
|
||
} as DeliveryMessageType
|
||
] as Array<DeliveryMessageType>
|
||
}
|
||
|
||
function buildMockRecords(orders: Array<DeliveryOrderType>): Array<DeliveryRecordType> {
|
||
const result = [] as Array<DeliveryRecordType>
|
||
for (let i = 0; i < orders.length; i++) {
|
||
const item = orders[i]
|
||
if (isCompletedStatus(item.status) || item.status == 'exception_pending') {
|
||
result.push({
|
||
id: 'record-' + item.id,
|
||
orderId: item.id,
|
||
orderNo: item.orderNo,
|
||
serviceName: item.serviceName,
|
||
elderNameMasked: item.elderNameMasked,
|
||
status: item.status,
|
||
statusText: item.statusText,
|
||
appointmentStartTime: item.appointmentStartTime,
|
||
actualStartTime: item.actualStartTime,
|
||
actualEndTime: item.actualEndTime != '' ? item.actualEndTime : item.updatedAt,
|
||
settlementStatus: item.settlementStatus,
|
||
acceptanceStatus: item.satisfactionStatus,
|
||
exceptionDesc: item.exceptionDesc,
|
||
ratingText: item.status == 'completed' ? '五星好评' : '待补充说明'
|
||
} as DeliveryRecordType)
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
function findMockOrderIndex(orders: Array<DeliveryOrderType>, orderId: string): number {
|
||
for (let i = 0; i < orders.length; i++) {
|
||
if (orders[i].id == orderId) {
|
||
return i
|
||
}
|
||
}
|
||
return -1
|
||
}
|
||
|
||
function sortMockRecentOrders(orders: Array<DeliveryOrderType>): Array<DeliveryOrderType> {
|
||
const pendingException = [] as Array<DeliveryOrderType>
|
||
const actionable = [] as Array<DeliveryOrderType>
|
||
const completed = [] as Array<DeliveryOrderType>
|
||
for (let i = 0; i < orders.length; i++) {
|
||
const item = orders[i]
|
||
if (item.status == 'exception_pending') {
|
||
pendingException.push(item)
|
||
} else if (!isCompletedStatus(item.status)) {
|
||
actionable.push(item)
|
||
} else {
|
||
completed.push(item)
|
||
}
|
||
}
|
||
return pendingException.concat(actionable).concat(completed)
|
||
}
|
||
|
||
function filterMockOrders(orders: Array<DeliveryOrderType>, query: DeliveryOrderQueryType): Array<DeliveryOrderType> {
|
||
const keyword = query.keyword.trim()
|
||
const result = [] as Array<DeliveryOrderType>
|
||
for (let i = 0; i < orders.length; i++) {
|
||
const item = orders[i]
|
||
let tabMatched = false
|
||
if (query.tab == 'all' || query.tab == '') {
|
||
tabMatched = true
|
||
} else if (query.tab == 'pending_accept') {
|
||
tabMatched = item.status == 'pending_accept'
|
||
} else if (query.tab == 'accepted') {
|
||
tabMatched = isPendingDepartStatus(item.status)
|
||
} else if (query.tab == 'serving') {
|
||
tabMatched = isServingStatus(item.status)
|
||
} else if (query.tab == 'pending_submit') {
|
||
tabMatched = item.status == 'pending_submit' || item.status == 'pending_acceptance'
|
||
} else if (query.tab == 'completed') {
|
||
tabMatched = isCompletedStatus(item.status)
|
||
} else if (query.tab == 'exception') {
|
||
tabMatched = item.status == 'exception_pending'
|
||
}
|
||
if (!tabMatched) {
|
||
continue
|
||
}
|
||
if (keyword != '') {
|
||
const matched = item.orderNo.includes(keyword) || item.serviceName.includes(keyword) || item.elderNameMasked.includes(keyword) || item.addressSummary.includes(keyword)
|
||
if (!matched) {
|
||
continue
|
||
}
|
||
}
|
||
result.push(cloneDeliveryOrder(item))
|
||
}
|
||
return result
|
||
}
|
||
|
||
function readCachedDeliveryInfo(userId: string): DeliveryInfoType | null {
|
||
const cached = uni.getStorageSync('delivery_info')
|
||
if (!isValidDeliveryInfoCache(cached)) {
|
||
return null
|
||
}
|
||
const info = cached as DeliveryInfoType
|
||
if (userId == '' || info.userId == userId || info.id == userId) {
|
||
return info
|
||
}
|
||
return null
|
||
}
|
||
|
||
async function fallbackGetDeliveryProfileByUserId(userId: string): Promise<DeliveryInfoType | null> {
|
||
const cached = readCachedDeliveryInfo(userId)
|
||
if (cached != null) {
|
||
return cached
|
||
}
|
||
return buildMockProfileWithStats(userId)
|
||
}
|
||
|
||
async function fallbackGetDashboard(staffId: string): Promise<DeliveryDashboardType> {
|
||
const profile = buildMockProfileWithStats(staffId)
|
||
const orders = ensureMockOrders(staffId)
|
||
let pendingAcceptCount = 0
|
||
let pendingDepartCount = 0
|
||
let servingCount = 0
|
||
let completedCount = 0
|
||
let exceptionCount = 0
|
||
for (let i = 0; i < orders.length; i++) {
|
||
const status = orders[i].status
|
||
if (status == 'pending_accept') {
|
||
pendingAcceptCount++
|
||
} else if (isPendingDepartStatus(status)) {
|
||
pendingDepartCount++
|
||
} else if (isServingStatus(status)) {
|
||
servingCount++
|
||
} else if (status == 'exception_pending') {
|
||
exceptionCount++
|
||
} else if (isCompletedStatus(status)) {
|
||
completedCount++
|
||
}
|
||
}
|
||
return {
|
||
pendingAcceptCount,
|
||
pendingDepartCount,
|
||
servingCount,
|
||
completedCount,
|
||
exceptionCount,
|
||
onlineStatus: profile.onlineStatus,
|
||
recentOrders: sortMockRecentOrders(cloneDeliveryOrders(orders)).slice(0, 5) as Array<DeliveryOrderType>
|
||
} as DeliveryDashboardType
|
||
}
|
||
|
||
async function fallbackGetOrders(staffId: string, query: DeliveryOrderQueryType): Promise<Array<DeliveryOrderType>> {
|
||
const orders = ensureMockOrders(staffId)
|
||
return filterMockOrders(orders, query)
|
||
}
|
||
|
||
async function fallbackGetOrderDetail(orderId: string): Promise<DeliveryOrderType | null> {
|
||
const orders = ensureMockOrders('')
|
||
const index = findMockOrderIndex(orders, orderId)
|
||
if (index < 0) {
|
||
return null
|
||
}
|
||
return cloneDeliveryOrder(orders[index])
|
||
}
|
||
|
||
async function fallbackAcceptOrder(orderId: string): Promise<DeliveryOrderType | null> {
|
||
const orders = ensureMockOrders('')
|
||
const index = findMockOrderIndex(orders, orderId)
|
||
if (index < 0) {
|
||
return null
|
||
}
|
||
orders[index].status = 'accepted'
|
||
orders[index].statusText = '待出发'
|
||
orders[index].statusTone = 'primary'
|
||
orders[index].acceptTime = currentDateTimeText()
|
||
orders[index].updatedAt = currentDateTimeText()
|
||
orders[index].timeline.push({
|
||
id: orders[index].orderNo + '-accepted',
|
||
title: '服务人员已接单',
|
||
time: orders[index].updatedAt,
|
||
description: '已确认接单,待前往服务地点。'
|
||
} as DeliveryTimelineItemType)
|
||
persistMockOrders(orders)
|
||
return cloneDeliveryOrder(orders[index])
|
||
}
|
||
|
||
async function fallbackRejectOrder(orderId: string, _reason: string): Promise<DeliveryOrderType | null> {
|
||
const orders = ensureMockOrders('')
|
||
const index = findMockOrderIndex(orders, orderId)
|
||
if (index < 0) {
|
||
return null
|
||
}
|
||
orders[index].status = 'cancelled'
|
||
orders[index].statusText = '已取消'
|
||
orders[index].statusTone = 'neutral'
|
||
orders[index].updatedAt = currentDateTimeText()
|
||
persistMockOrders(orders)
|
||
return cloneDeliveryOrder(orders[index])
|
||
}
|
||
|
||
async function fallbackStartDepart(orderId: string, _location: DeliveryLocationType): Promise<DeliveryOrderType | null> {
|
||
const orders = ensureMockOrders('')
|
||
const index = findMockOrderIndex(orders, orderId)
|
||
if (index < 0) {
|
||
return null
|
||
}
|
||
orders[index].status = 'on_the_way'
|
||
orders[index].statusText = '前往服务中'
|
||
orders[index].statusTone = 'primary'
|
||
orders[index].departTime = currentDateTimeText()
|
||
orders[index].updatedAt = orders[index].departTime
|
||
persistMockOrders(orders)
|
||
return cloneDeliveryOrder(orders[index])
|
||
}
|
||
|
||
async function fallbackArriveOrder(orderId: string, _location: DeliveryLocationType): Promise<DeliveryOrderType | null> {
|
||
const orders = ensureMockOrders('')
|
||
const index = findMockOrderIndex(orders, orderId)
|
||
if (index < 0) {
|
||
return null
|
||
}
|
||
orders[index].status = 'arrived'
|
||
orders[index].statusText = '待签到'
|
||
orders[index].statusTone = 'primary'
|
||
orders[index].arriveTime = currentDateTimeText()
|
||
orders[index].updatedAt = orders[index].arriveTime
|
||
persistMockOrders(orders)
|
||
return cloneDeliveryOrder(orders[index])
|
||
}
|
||
|
||
async function fallbackCheckinOrder(orderId: string, payload: DeliveryCheckinPayloadType): Promise<DeliveryOrderType | null> {
|
||
const orders = ensureMockOrders('')
|
||
const index = findMockOrderIndex(orders, orderId)
|
||
if (index < 0) {
|
||
return null
|
||
}
|
||
orders[index].status = 'checked_in'
|
||
orders[index].statusText = '已签到'
|
||
orders[index].statusTone = 'primary'
|
||
orders[index].checkinTime = currentDateTimeText()
|
||
orders[index].updatedAt = orders[index].checkinTime
|
||
orders[index].lastLocation = payload.location
|
||
if (payload.photos.length > 0) {
|
||
for (let i = 0; i < payload.photos.length; i++) {
|
||
orders[index].evidenceList.push({
|
||
id: orderId + '-checkin-photo-' + String(i + 1),
|
||
orderId,
|
||
phase: 'checkin',
|
||
fileType: 'image',
|
||
name: '签到照片' + String(i + 1),
|
||
url: '',
|
||
localPath: payload.photos[i],
|
||
status: 'success',
|
||
progress: 100,
|
||
retryable: false,
|
||
createdAt: currentDateTimeText()
|
||
} as DeliveryEvidenceRecordType)
|
||
}
|
||
}
|
||
persistMockOrders(orders)
|
||
return cloneDeliveryOrder(orders[index])
|
||
}
|
||
|
||
async function fallbackStartService(orderId: string): Promise<DeliveryOrderType | null> {
|
||
const orders = ensureMockOrders('')
|
||
const index = findMockOrderIndex(orders, orderId)
|
||
if (index < 0) {
|
||
return null
|
||
}
|
||
orders[index].status = 'serving'
|
||
orders[index].statusText = '服务中'
|
||
orders[index].statusTone = 'primary'
|
||
if (orders[index].actualStartTime == '') {
|
||
orders[index].actualStartTime = currentDateTimeText()
|
||
}
|
||
orders[index].updatedAt = currentDateTimeText()
|
||
persistMockOrders(orders)
|
||
return cloneDeliveryOrder(orders[index])
|
||
}
|
||
|
||
async function fallbackSaveProgress(orderId: string, payload: DeliveryProgressPayloadType): Promise<DeliveryOrderType | null> {
|
||
const orders = ensureMockOrders('')
|
||
const index = findMockOrderIndex(orders, orderId)
|
||
if (index < 0) {
|
||
return null
|
||
}
|
||
orders[index].serviceItems = JSON.parse(JSON.stringify(payload.items)) as Array<DeliveryServiceItemType>
|
||
orders[index].progressNote = payload.progressNote
|
||
orders[index].serviceSummary = payload.serviceSummary
|
||
orders[index].updatedAt = currentDateTimeText()
|
||
persistMockOrders(orders)
|
||
return cloneDeliveryOrder(orders[index])
|
||
}
|
||
|
||
async function fallbackUploadEvidence(orderId: string, phase: string, files: Array<string>): Promise<Array<DeliveryEvidenceRecordType>> {
|
||
const orders = ensureMockOrders('')
|
||
const index = findMockOrderIndex(orders, orderId)
|
||
if (index < 0) {
|
||
return [] as Array<DeliveryEvidenceRecordType>
|
||
}
|
||
const added = [] as Array<DeliveryEvidenceRecordType>
|
||
for (let i = 0; i < files.length; i++) {
|
||
const item = {
|
||
id: orderId + '-evidence-' + String(orders[index].evidenceList.length + i + 1),
|
||
orderId,
|
||
phase,
|
||
fileType: 'image',
|
||
name: '服务留痕图片' + String(i + 1),
|
||
url: '',
|
||
localPath: files[i],
|
||
status: 'success',
|
||
progress: 100,
|
||
retryable: false,
|
||
createdAt: currentDateTimeText()
|
||
} as DeliveryEvidenceRecordType
|
||
orders[index].evidenceList.push(item)
|
||
added.push(item)
|
||
}
|
||
orders[index].updatedAt = currentDateTimeText()
|
||
persistMockOrders(orders)
|
||
return JSON.parse(JSON.stringify(added)) as Array<DeliveryEvidenceRecordType>
|
||
}
|
||
|
||
async function fallbackRetryEvidence(orderId: string, evidenceId: string): Promise<DeliveryEvidenceRecordType | null> {
|
||
const orders = ensureMockOrders('')
|
||
const index = findMockOrderIndex(orders, orderId)
|
||
if (index < 0) {
|
||
return null
|
||
}
|
||
for (let i = 0; i < orders[index].evidenceList.length; i++) {
|
||
if (orders[index].evidenceList[i].id == evidenceId) {
|
||
orders[index].evidenceList[i].status = 'success'
|
||
orders[index].evidenceList[i].progress = 100
|
||
orders[index].evidenceList[i].retryable = false
|
||
persistMockOrders(orders)
|
||
return orders[index].evidenceList[i]
|
||
}
|
||
}
|
||
return null
|
||
}
|
||
|
||
async function fallbackSubmitException(orderId: string, payload: DeliveryExceptionPayloadType): Promise<DeliveryOrderType | null> {
|
||
const orders = ensureMockOrders('')
|
||
const index = findMockOrderIndex(orders, orderId)
|
||
if (index < 0) {
|
||
return null
|
||
}
|
||
orders[index].status = 'exception_pending'
|
||
orders[index].statusText = '异常处理中'
|
||
orders[index].statusTone = 'warning'
|
||
orders[index].exceptionType = payload.exceptionType
|
||
orders[index].exceptionDesc = payload.description
|
||
orders[index].updatedAt = currentDateTimeText()
|
||
persistMockOrders(orders)
|
||
return cloneDeliveryOrder(orders[index])
|
||
}
|
||
|
||
async function fallbackFinishService(orderId: string, payload: DeliveryFinishPayloadType): Promise<DeliveryOrderType | null> {
|
||
const orders = ensureMockOrders('')
|
||
const index = findMockOrderIndex(orders, orderId)
|
||
if (index < 0) {
|
||
return null
|
||
}
|
||
orders[index].status = 'completed'
|
||
orders[index].statusText = '已完成'
|
||
orders[index].statusTone = 'success'
|
||
orders[index].serviceSummary = payload.serviceSummary
|
||
orders[index].signatureName = payload.signatureName
|
||
orders[index].actualEndTime = currentDateTimeText()
|
||
orders[index].finishTime = orders[index].actualEndTime
|
||
orders[index].satisfactionStatus = payload.confirmByFamily ? '待回访' : '待确认'
|
||
orders[index].settlementStatus = '待结算'
|
||
orders[index].archiveStatus = '待归档'
|
||
orders[index].updatedAt = orders[index].actualEndTime
|
||
persistMockOrders(orders)
|
||
return cloneDeliveryOrder(orders[index])
|
||
}
|
||
|
||
async function fallbackGetRecords(staffId: string): Promise<Array<DeliveryRecordType>> {
|
||
const orders = ensureMockOrders(staffId)
|
||
return cloneDeliveryRecords(buildMockRecords(orders))
|
||
}
|
||
|
||
async function fallbackGetMessages(): Promise<Array<DeliveryMessageType>> {
|
||
const orders = ensureMockOrders('')
|
||
return cloneDeliveryMessages(buildMockMessages(orders))
|
||
}
|
||
|
||
async function fallbackUpdateOnlineStatus(staffId: string, status: string): Promise<DeliveryInfoType | null> {
|
||
const cachedInfo = buildMockProfileWithStats(staffId)
|
||
const nextInfo = {
|
||
...cachedInfo,
|
||
onlineStatus: status as 'online' | 'resting' | 'busy'
|
||
} as DeliveryInfoType
|
||
persistMockDeliveryInfo(nextInfo)
|
||
return nextInfo
|
||
}
|
||
|
||
export async function loginDelivery(payload: DeliveryLoginPayloadType): Promise<DeliveryLoginResultType> {
|
||
const account = payload.account.trim()
|
||
if (!account.includes('@')) {
|
||
throw new Error('请使用真实邮箱账号登录服务人员端')
|
||
}
|
||
|
||
const result = await supa.signIn(account, payload.password)
|
||
if (result.user == null) {
|
||
const rawData = result.raw as UTSJSONObject
|
||
throw new Error(mapLoginError(rawData))
|
||
}
|
||
|
||
const profile = await getCurrentUser()
|
||
if (profile == null || profile.id == null || profile.id == '') {
|
||
try {
|
||
await supa.signOut()
|
||
} catch (error) {}
|
||
throw new Error('登录状态已失效,请重新登录')
|
||
}
|
||
|
||
if (!isDelivererRole(profile)) {
|
||
try {
|
||
await supa.signOut()
|
||
} catch (error) {}
|
||
throw new Error('当前账号不是上门服务人员账号')
|
||
}
|
||
|
||
const deliveryInfo = await fetchDeliveryProfileFromRemote(profile.id)
|
||
if (deliveryInfo == null) {
|
||
try {
|
||
await supa.signOut()
|
||
} catch (error) {}
|
||
throw new Error('当前账号未绑定服务人员档案')
|
||
}
|
||
|
||
return {
|
||
token: result.access_token,
|
||
userInfo: profile,
|
||
deliveryInfo,
|
||
usesMock: false
|
||
}
|
||
}
|
||
|
||
export async function getDeliveryProfileByUserId(userId: string): Promise<DeliveryInfoType | null> {
|
||
const remoteInfo = await fetchDeliveryProfileFromRemote(userId)
|
||
if (remoteInfo != null) {
|
||
return remoteInfo
|
||
}
|
||
return await fallbackGetDeliveryProfileByUserId(userId)
|
||
}
|
||
|
||
export async function getDeliveryDashboardByStaffId(staffId: string): Promise<DeliveryDashboardType> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_DASHBOARD, {
|
||
p_staff_id: staffId
|
||
} as UTSJSONObject)
|
||
const dashboard = normalizeRpcDashboard(rpcData)
|
||
if (dashboard != null) {
|
||
return dashboard
|
||
}
|
||
return await fallbackGetDashboard(staffId)
|
||
}
|
||
|
||
export async function getDeliveryOrdersByStaffId(staffId: string, query: DeliveryOrderQueryType): Promise<Array<DeliveryOrderType>> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_ORDER_LIST, {
|
||
p_staff_id: staffId,
|
||
p_tab: query.tab,
|
||
p_keyword: query.keyword
|
||
} as UTSJSONObject)
|
||
const orders = normalizeRpcOrderList(rpcData)
|
||
if (orders != null) {
|
||
return orders
|
||
}
|
||
return await fallbackGetOrders(staffId, query)
|
||
}
|
||
|
||
export async function getDeliveryOrderDetailById(orderId: string): Promise<DeliveryOrderType | null> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_ORDER_DETAIL, {
|
||
p_order_id: orderId
|
||
} as UTSJSONObject)
|
||
const order = normalizeRpcOrder(rpcData)
|
||
if (order != null) {
|
||
return order
|
||
}
|
||
return await fallbackGetOrderDetail(orderId)
|
||
}
|
||
|
||
export async function acceptDeliveryOrderById(orderId: string): Promise<DeliveryOrderType | null> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_ACCEPT_ORDER, {
|
||
p_order_id: orderId
|
||
} as UTSJSONObject)
|
||
const order = normalizeRpcOrder(rpcData)
|
||
if (order != null) {
|
||
return order
|
||
}
|
||
return await fallbackAcceptOrder(orderId)
|
||
}
|
||
|
||
export async function rejectDeliveryOrderById(orderId: string, reason: string): Promise<DeliveryOrderType | null> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_REJECT_ORDER, {
|
||
p_order_id: orderId,
|
||
p_reason: reason
|
||
} as UTSJSONObject)
|
||
const order = normalizeRpcOrder(rpcData)
|
||
if (order != null) {
|
||
return order
|
||
}
|
||
return await fallbackRejectOrder(orderId, reason)
|
||
}
|
||
|
||
export async function startDepartById(orderId: string, location: DeliveryLocationType): Promise<DeliveryOrderType | null> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_START_DEPART, {
|
||
p_order_id: orderId,
|
||
p_location: location
|
||
} as UTSJSONObject)
|
||
const order = normalizeRpcOrder(rpcData)
|
||
if (order != null) {
|
||
return order
|
||
}
|
||
return await fallbackStartDepart(orderId, location)
|
||
}
|
||
|
||
export async function arriveOrderById(orderId: string, location: DeliveryLocationType): Promise<DeliveryOrderType | null> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_ARRIVE_ORDER, {
|
||
p_order_id: orderId,
|
||
p_location: location
|
||
} as UTSJSONObject)
|
||
const order = normalizeRpcOrder(rpcData)
|
||
if (order != null) {
|
||
return order
|
||
}
|
||
return await fallbackArriveOrder(orderId, location)
|
||
}
|
||
|
||
export async function checkinOrderById(orderId: string, payload: DeliveryCheckinPayloadType): Promise<DeliveryOrderType | null> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_CHECKIN_ORDER, {
|
||
p_order_id: orderId,
|
||
p_payload: payload
|
||
} as UTSJSONObject)
|
||
const order = normalizeRpcOrder(rpcData)
|
||
if (order != null) {
|
||
return order
|
||
}
|
||
return await fallbackCheckinOrder(orderId, payload)
|
||
}
|
||
|
||
export async function startServiceById(orderId: string): Promise<DeliveryOrderType | null> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_START_SERVICE, {
|
||
p_order_id: orderId
|
||
} as UTSJSONObject)
|
||
const order = normalizeRpcOrder(rpcData)
|
||
if (order != null) {
|
||
return order
|
||
}
|
||
return await fallbackStartService(orderId)
|
||
}
|
||
|
||
export async function saveServiceProgressById(orderId: string, payload: DeliveryProgressPayloadType): Promise<DeliveryOrderType | null> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_SAVE_PROGRESS, {
|
||
p_order_id: orderId,
|
||
p_payload: payload
|
||
} as UTSJSONObject)
|
||
const order = normalizeRpcOrder(rpcData)
|
||
if (order != null) {
|
||
return order
|
||
}
|
||
return await fallbackSaveProgress(orderId, payload)
|
||
}
|
||
|
||
export async function uploadEvidenceById(orderId: string, phase: string, files: Array<string>): Promise<Array<DeliveryEvidenceRecordType>> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_UPLOAD_EVIDENCE, {
|
||
p_order_id: orderId,
|
||
p_phase: phase,
|
||
p_files: files
|
||
} as UTSJSONObject)
|
||
const evidenceList = normalizeRpcEvidenceList(rpcData)
|
||
if (evidenceList != null) {
|
||
return evidenceList
|
||
}
|
||
return await fallbackUploadEvidence(orderId, phase, files)
|
||
}
|
||
|
||
export async function retryEvidenceById(orderId: string, evidenceId: string): Promise<DeliveryEvidenceRecordType | null> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_RETRY_EVIDENCE, {
|
||
p_order_id: orderId,
|
||
p_evidence_id: evidenceId
|
||
} as UTSJSONObject)
|
||
if (rpcData != null) {
|
||
return rpcData as DeliveryEvidenceRecordType
|
||
}
|
||
return await fallbackRetryEvidence(orderId, evidenceId)
|
||
}
|
||
|
||
export async function submitExceptionById(orderId: string, payload: DeliveryExceptionPayloadType): Promise<DeliveryOrderType | null> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_SUBMIT_EXCEPTION, {
|
||
p_order_id: orderId,
|
||
p_payload: payload
|
||
} as UTSJSONObject)
|
||
const order = normalizeRpcOrder(rpcData)
|
||
if (order != null) {
|
||
return order
|
||
}
|
||
return await fallbackSubmitException(orderId, payload)
|
||
}
|
||
|
||
export async function finishServiceById(orderId: string, payload: DeliveryFinishPayloadType): Promise<DeliveryOrderType | null> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_FINISH_SERVICE, {
|
||
p_order_id: orderId,
|
||
p_payload: payload
|
||
} as UTSJSONObject)
|
||
const order = normalizeRpcOrder(rpcData)
|
||
if (order != null) {
|
||
return order
|
||
}
|
||
return await fallbackFinishService(orderId, payload)
|
||
}
|
||
|
||
export async function getDeliveryRecordsByStaffId(staffId: string): Promise<Array<DeliveryRecordType>> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_RECORD_LIST, {
|
||
p_staff_id: staffId
|
||
} as UTSJSONObject)
|
||
const records = normalizeRpcRecords(rpcData)
|
||
if (records != null) {
|
||
return records
|
||
}
|
||
return await fallbackGetRecords(staffId)
|
||
}
|
||
|
||
export async function getDeliveryMessagesList(): Promise<Array<DeliveryMessageType>> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_MESSAGE_LIST, {} as UTSJSONObject)
|
||
const messages = normalizeRpcMessages(rpcData)
|
||
if (messages != null && messages.length > 0) {
|
||
return messages
|
||
}
|
||
return await fallbackGetMessages()
|
||
}
|
||
|
||
export async function updateDeliveryOnlineStatusByStaffId(staffId: string, status: string): Promise<DeliveryInfoType | null> {
|
||
const rpcData = await callDeliveryRpc(DELIVERY_RPC_SET_ONLINE_STATUS, {
|
||
p_staff_id: staffId,
|
||
p_status: status
|
||
} as UTSJSONObject)
|
||
const deliveryInfo = normalizeRpcDeliveryInfo(rpcData)
|
||
if (deliveryInfo != null) {
|
||
return deliveryInfo
|
||
}
|
||
return await fallbackUpdateOnlineStatus(staffId, status)
|
||
} |