预校验、签到流程跑通

This commit is contained in:
2026-06-16 11:32:53 +08:00
parent 72d29d4b68
commit 6b11144366
13 changed files with 3900 additions and 6067 deletions

View File

@@ -0,0 +1,131 @@
{
"pages": [
{
"path": "pages/user/register",
"style": {
"navigationBarTitleText": "服务人员注册",
"navigationStyle": "custom"
}
},
{
"path": "pages/user/terms",
"style": {
"navigationBarTitleText": "用户协议与隐私政策",
"navigationStyle": "custom"
}
},
{
"path": "pages/user/login",
"style": {
"navigationBarTitleText": "服务人员登录",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/home/index",
"style": {
"navigationBarTitleText": "工作台",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/index",
"style": {
"navigationBarTitleText": "工单列表",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/detail",
"style": {
"navigationBarTitleText": "订单详情",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/route",
"style": {
"navigationBarTitleText": "出发与导航",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/checkin",
"style": {
"navigationBarTitleText": "到岗签到",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/service-record/index",
"style": {
"navigationBarTitleText": "服务记录",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/exception",
"style": {
"navigationBarTitleText": "异常上报",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/profile/index",
"style": {
"navigationBarTitleText": "我的",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/profile/settings",
"style": {
"navigationBarTitleText": "设置",
"navigationStyle": "custom"
}
}
],
"subPackages": [],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "delivery",
"navigationBarBackgroundColor": "#FFFFFF",
"backgroundColor": "#F3F7F9"
},
"tabBar": {
"color": "#6B7280",
"selectedColor": "#0F766E",
"backgroundColor": "#FFFFFF",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/mall/delivery/home/index",
"text": "工作台",
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/home-active.png"
},
{
"pagePath": "pages/mall/delivery/orders/index",
"text": "订单",
"iconPath": "static/tabbar/cart.png",
"selectedIconPath": "static/tabbar/cart.png"
},
{
"pagePath": "pages/mall/delivery/profile/index",
"text": "我的",
"iconPath": "static/tabbar/user.png",
"selectedIconPath": "static/tabbar/user.png"
}
]
},
"condition": {
"current": 0,
"list": [
{
"name": "delivery端",
"path": "pages/user/login",
"query": "mode=delivery&role=delivery"
}
]
}
}

View File

@@ -0,0 +1,131 @@
{
"pages": [
{
"path": "pages/user/register",
"style": {
"navigationBarTitleText": "服务人员注册",
"navigationStyle": "custom"
}
},
{
"path": "pages/user/terms",
"style": {
"navigationBarTitleText": "用户协议与隐私政策",
"navigationStyle": "custom"
}
},
{
"path": "pages/user/login",
"style": {
"navigationBarTitleText": "服务人员登录",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/home/index",
"style": {
"navigationBarTitleText": "工作台",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/index",
"style": {
"navigationBarTitleText": "工单列表",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/detail",
"style": {
"navigationBarTitleText": "订单详情",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/route",
"style": {
"navigationBarTitleText": "出发与导航",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/checkin",
"style": {
"navigationBarTitleText": "到岗签到",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/service-record/index",
"style": {
"navigationBarTitleText": "服务记录",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/exception",
"style": {
"navigationBarTitleText": "异常上报",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/profile/index",
"style": {
"navigationBarTitleText": "我的",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/profile/settings",
"style": {
"navigationBarTitleText": "设置",
"navigationStyle": "custom"
}
}
],
"subPackages": [],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "delivery",
"navigationBarBackgroundColor": "#FFFFFF",
"backgroundColor": "#F3F7F9"
},
"tabBar": {
"color": "#6B7280",
"selectedColor": "#0F766E",
"backgroundColor": "#FFFFFF",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/mall/delivery/home/index",
"text": "工作台",
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/home-active.png"
},
{
"pagePath": "pages/mall/delivery/orders/index",
"text": "订单",
"iconPath": "static/tabbar/cart.png",
"selectedIconPath": "static/tabbar/cart.png"
},
{
"pagePath": "pages/mall/delivery/profile/index",
"text": "我的",
"iconPath": "static/tabbar/user.png",
"selectedIconPath": "static/tabbar/user.png"
}
]
},
"condition": {
"current": 0,
"list": [
{
"name": "delivery端",
"path": "pages/user/login",
"query": "mode=delivery&role=delivery"
}
]
}
}

View File

@@ -0,0 +1,131 @@
{
"pages": [
{
"path": "pages/user/register",
"style": {
"navigationBarTitleText": "服务人员注册",
"navigationStyle": "custom"
}
},
{
"path": "pages/user/terms",
"style": {
"navigationBarTitleText": "用户协议与隐私政策",
"navigationStyle": "custom"
}
},
{
"path": "pages/user/login",
"style": {
"navigationBarTitleText": "服务人员登录",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/home/index",
"style": {
"navigationBarTitleText": "工作台",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/index",
"style": {
"navigationBarTitleText": "工单列表",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/detail",
"style": {
"navigationBarTitleText": "订单详情",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/route",
"style": {
"navigationBarTitleText": "出发与导航",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/checkin",
"style": {
"navigationBarTitleText": "到岗签到",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/service-record/index",
"style": {
"navigationBarTitleText": "服务记录",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/orders/exception",
"style": {
"navigationBarTitleText": "异常上报",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/profile/index",
"style": {
"navigationBarTitleText": "我的",
"navigationStyle": "custom"
}
},
{
"path": "pages/mall/delivery/profile/settings",
"style": {
"navigationBarTitleText": "设置",
"navigationStyle": "custom"
}
}
],
"subPackages": [],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "delivery",
"navigationBarBackgroundColor": "#FFFFFF",
"backgroundColor": "#F3F7F9"
},
"tabBar": {
"color": "#6B7280",
"selectedColor": "#0F766E",
"backgroundColor": "#FFFFFF",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/mall/delivery/home/index",
"text": "工作台",
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/home-active.png"
},
{
"pagePath": "pages/mall/delivery/orders/index",
"text": "订单",
"iconPath": "static/tabbar/cart.png",
"selectedIconPath": "static/tabbar/cart.png"
},
{
"pagePath": "pages/mall/delivery/profile/index",
"text": "我的",
"iconPath": "static/tabbar/user.png",
"selectedIconPath": "static/tabbar/user.png"
}
]
},
"condition": {
"current": 0,
"list": [
{
"name": "delivery端",
"path": "pages/user/login",
"query": "mode=delivery&role=delivery"
}
]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -165,7 +165,11 @@ async function handleOrderAction(orderId: string) {
return return
} }
if (order.status == 'pending_assignment' || order.status == 'pending_accept') { if (order.status == 'pending_assignment' || order.status == 'pending_accept') {
await acceptServiceOrder(orderId) const result = await acceptServiceOrder(orderId)
if (!result.ok) {
uni.showToast({ title: result.message != '' ? result.message : '接单失败', icon: 'none' })
return
}
uni.showToast({ title: '已接单', icon: 'success' }) uni.showToast({ title: '已接单', icon: 'success' })
loadData() loadData()
return return

File diff suppressed because it is too large Load Diff

View File

@@ -165,7 +165,11 @@ async function handlePrimary() {
} }
const status = order.value.status const status = order.value.status
if (status == 'pending_assignment' || status == 'pending_accept') { if (status == 'pending_assignment' || status == 'pending_accept') {
await acceptServiceOrder(orderId.value) const result = await acceptServiceOrder(orderId.value)
if (!result.ok) {
uni.showToast({ title: result.message != '' ? result.message : '接单失败', icon: 'none' })
return
}
uni.showToast({ title: '已接单', icon: 'success' }) uni.showToast({ title: '已接单', icon: 'success' })
loadData() loadData()
return return
@@ -174,14 +178,18 @@ async function handlePrimary() {
uni.navigateTo({ url: '/pages/mall/delivery/orders/route?id=' + orderId.value }) uni.navigateTo({ url: '/pages/mall/delivery/orders/route?id=' + orderId.value })
return return
} }
if (status == 'departed' || status == 'on_the_way') { if (status == 'assigned' || status == 'order_accepted' || status == 'ORDER_ACCEPTED') {
uni.navigateTo({ url: '/pages/mall/delivery/orders/route?id=' + orderId.value }) uni.navigateTo({ url: '/pages/mall/delivery/orders/route?id=' + orderId.value })
return return
} }
if (status == 'arrived') { if (status == 'departed' || status == 'on_the_way' || status == 'order_departed' || status == 'ORDER_DEPARTED') {
uni.navigateTo({ url: '/pages/mall/delivery/orders/checkin?id=' + orderId.value }) uni.navigateTo({ url: '/pages/mall/delivery/orders/checkin?id=' + orderId.value })
return return
} }
if (status == 'arrival_pending' || status == 'ARRIVAL_PENDING') {
uni.showToast({ title: '等待消费者确认到达', icon: 'none' })
return
}
if (status == 'in_service' || status == 'serving' || status == 'completed') { if (status == 'in_service' || status == 'serving' || status == 'completed') {
goRecord() goRecord()
return return

View File

@@ -49,7 +49,7 @@
<text v-if="item.acceptedByName != ''" class="meta-text accepted-by">接单人:{{ item.acceptedByName }}</text> <text v-if="item.acceptedByName != ''" class="meta-text accepted-by">接单人:{{ item.acceptedByName }}</text>
</view> </view>
<view class="action-row"> <view class="action-row">
<view class="outline-btn" @click="goDetail(item.id)"><text class="outline-btn-text">查看详情</text></view> <view v-if="getActionText(item.status) != '查看详情'" class="outline-btn" @click="goDetail(item.id)"><text class="outline-btn-text">查看详情</text></view>
<view v-if="showReject(item.status)" class="warn-btn" @click="rejectOrder(item.id)"><text class="warn-btn-text">拒单</text></view> <view v-if="showReject(item.status)" class="warn-btn" @click="rejectOrder(item.id)"><text class="warn-btn-text">拒单</text></view>
<view class="primary-btn" @click="handleAction(item.id, item.status)"><text class="primary-btn-text">{{ getActionText(item.status) }}</text></view> <view class="primary-btn" @click="handleAction(item.id, item.status)"><text class="primary-btn-text">{{ getActionText(item.status) }}</text></view>
</view> </view>
@@ -162,14 +162,83 @@ function sortOrderList(list: Array<DeliveryOrderType>): Array<DeliveryOrderType>
return wrapped.map((entry) => entry.item) return wrapped.map((entry) => entry.item)
} }
function normalizeStatus(status: string): string {
return String(status ?? '').trim().toLowerCase()
}
function isPendingStatus(status: string): boolean {
const s = normalizeStatus(status)
return s == 'pending' || s == 'pending_assignment' || s == 'pending_accept' || s == 'pending_assign' || s == 'pending_dispatch' || s == 'pending_acceptance_new'
}
function isOngoingStatus(status: string): boolean {
const s = normalizeStatus(status)
return s == 'assigned' || s == 'accepted' || s == 'waiting_departure' || s == 'departed' || s == 'on_the_way' || s == 'arrived' || s == 'in_service' || s == 'serving' || s == 'pending_acceptance' || s == 'arrival_pending' || s == 'order_accepted' || s == 'order_departed' || s == 'order_checked_in' || s == 'order_in_service'
}
function isHistoryStatus(status: string): boolean {
const s = normalizeStatus(status)
return s == 'completed' || s == 'settled' || s == 'archived' || s == 'cancelled' || s == 'canceled' || s == 'rejected' || s == 'abnormal' || s == 'exception_pending' || s == 'order_completed' || s == 'order_cancelled'
}
function getOrderCanonicalKey(item: DeliveryOrderType): string {
const orderNo = String(item.orderNo ?? '').trim()
if (orderNo != '') return 'orderNo:' + orderNo
const sourceOrderId = String(item.sourceOrderId ?? '').trim()
if (sourceOrderId != '') return 'sourceOrderId:' + sourceOrderId
const legacyServiceOrderId = String(item.legacyServiceOrderId ?? '').trim()
if (legacyServiceOrderId != '') return 'legacyServiceOrderId:' + legacyServiceOrderId
return 'id:' + String(item.id ?? '')
}
function getOrderUpdateTime(item: DeliveryOrderType): number {
if (item.updatedAt != '') return parseTime(item.updatedAt)
if (item.createdAt != '') return parseTime(item.createdAt)
return 0
}
function dedupeOrders(list: Array<DeliveryOrderType>): Array<DeliveryOrderType> {
const map = new Map<string, DeliveryOrderType>()
for (let i = 0; i < list.length; i++) {
const item = list[i]
const key = getOrderCanonicalKey(item)
const old = map.get(key)
if (old == null) {
map.set(key, item)
continue
}
if (isPendingStatus(old.status) && isOngoingStatus(item.status)) {
map.set(key, item)
continue
}
if (isOngoingStatus(old.status) && isPendingStatus(item.status)) {
continue
}
if (getOrderUpdateTime(item) > getOrderUpdateTime(old)) {
map.set(key, item)
}
}
return Array.from(map.values())
}
const filteredOrders = computed((): Array<DeliveryOrderType> => { const filteredOrders = computed((): Array<DeliveryOrderType> => {
const keyword = searchKeyword.value.trim().toLowerCase() const keyword = searchKeyword.value.trim().toLowerCase()
let result: Array<DeliveryOrderType> let result = orders.value.slice()
if (keyword == '') { if (keyword == '') {
result = orders.value.slice() result = result.slice()
} else { } else {
result = orders.value.filter((item) => item.orderNo.toLowerCase().includes(keyword)) result = result.filter((item) => item.orderNo.toLowerCase().includes(keyword))
} }
if (currentTab.value == 'pending') {
result = result.filter((item) => isPendingStatus(item.status))
}
if (currentTab.value == 'today' || currentTab.value == 'ongoing') {
result = result.filter((item) => isOngoingStatus(item.status))
}
if (currentTab.value == 'history') {
result = result.filter((item) => isHistoryStatus(item.status))
}
result = dedupeOrders(result)
return sortOrderList(result) return sortOrderList(result)
}) })
@@ -233,7 +302,8 @@ function formatTags(tags: Array<string>): string {
} }
function showReject(status: DeliveryOrderStatus): boolean { function showReject(status: DeliveryOrderStatus): boolean {
return status == 'pending_assignment' || status == 'pending_accept' // 仅待接单状态可拒单assigned已派单不可拒单只能查看详情/出发
return isPendingStatus(String(status))
} }
function getActionText(status: DeliveryOrderStatus): string { function getActionText(status: DeliveryOrderStatus): string {
@@ -262,26 +332,38 @@ function rejectOrder(orderId: string) {
} }
async function handleAction(orderId: string, status: DeliveryOrderStatus) { async function handleAction(orderId: string, status: DeliveryOrderStatus) {
if (status == 'pending_assignment' || status == 'pending_accept') { const s = normalizeStatus(String(status))
await acceptServiceOrder(orderId) // 待接单:可以接单
if (isPendingStatus(s)) {
const result = await acceptServiceOrder(orderId)
if (!result.ok) {
uni.showToast({ title: result.message != '' ? result.message : '接单失败', icon: 'none' })
return
}
uni.showToast({ title: '接单成功', icon: 'success' }) uni.showToast({ title: '接单成功', icon: 'success' })
loadData() await loadData()
return
}
// 已派单:不显示接单按钮,显示查看详情;如果需要出发则显示出发
if (s == 'assigned' || s == 'accepted' || s == 'waiting_departure' || s == 'order_accepted') {
// 已派单状态:当前流程需要出发时,跳转到出发页;否则显示查看详情
uni.navigateTo({ url: '/pages/mall/delivery/orders/route?id=' + orderId })
return return
} }
if (status == 'accepted' || status == 'waiting_departure') { if (status == 'accepted' || status == 'waiting_departure') {
uni.navigateTo({ url: '/pages/mall/delivery/orders/route?id=' + orderId }) uni.navigateTo({ url: '/pages/mall/delivery/orders/route?id=' + orderId })
return return
} }
if (status == 'departed' || status == 'on_the_way') { if (s == 'departed' || s == 'on_the_way' || s == 'order_departed') {
uni.navigateTo({ url: '/pages/mall/delivery/orders/route?id=' + orderId })
return
}
if (status == 'arrived') {
uni.navigateTo({ url: '/pages/mall/delivery/orders/checkin?id=' + orderId }) uni.navigateTo({ url: '/pages/mall/delivery/orders/checkin?id=' + orderId })
return return
} }
if (status == 'in_service' || status == 'serving' || status == 'completed') { if (s == 'arrival_pending') {
goRecord(orderId) uni.showToast({ title: '等待消费者确认到达', icon: 'none' })
return
}
if (status == 'in_service' || status == 'serving' || status == 'ORDER_IN_SERVICE' || status == 'completed' || status == 'ORDER_COMPLETED') {
goDetail(orderId)
return return
} }
if (status == 'pending_confirm' || status == 'pending_acceptance' || status == 'pending_submit') { if (status == 'pending_confirm' || status == 'pending_acceptance' || status == 'pending_submit') {

View File

@@ -1,5 +1,6 @@
import { import {
acceptDeliveryOrderById, acceptDeliveryOrderById,
acceptHomecareAssignmentV2,
arriveOrderById, arriveOrderById,
checkinOrderById, checkinOrderById,
finishServiceById, finishServiceById,
@@ -33,6 +34,7 @@ import type {
DeliveryLocationType, DeliveryLocationType,
DeliveryLoginPayloadType, DeliveryLoginPayloadType,
DeliveryLoginResultType, DeliveryLoginResultType,
DeliveryActionResultType,
DeliveryMessageType, DeliveryMessageType,
DeliveryOrderQueryType, DeliveryOrderQueryType,
DeliveryOrderStatus, DeliveryOrderStatus,
@@ -99,6 +101,80 @@ function shouldFallbackOrders(orders: Array<DeliveryOrderType>): boolean {
return true 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<DeliveryOrderType>): Array<string> {
const keys = [] as Array<string>
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<DeliveryOrderType>, activeKeys: Array<string>): Array<DeliveryOrderType> {
if (orders.length == 0 || activeKeys.length == 0) {
return orders
}
const result = [] as Array<DeliveryOrderType>
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 { function mapOrderToRecord(order: DeliveryOrderType): DeliveryRecordType {
const isAccepted = order.status == 'completed' || order.status == 'pending_acceptance' || order.status == 'settled' || order.status == 'archived' const isAccepted = order.status == 'completed' || order.status == 'pending_acceptance' || order.status == 'settled' || order.status == 'archived'
return { return {
@@ -130,7 +206,6 @@ export async function loginDelivery(payload: DeliveryLoginPayloadType): Promise<
export async function getDeliveryProfile(): Promise<DeliveryInfoType | null> { export async function getDeliveryProfile(): Promise<DeliveryInfoType | null> {
const authResult = await requireDeliveryAuth({ redirectOnFail: false, toastOnFail: false }) const authResult = await requireDeliveryAuth({ redirectOnFail: false, toastOnFail: false })
if (!authResult.ok) { if (!authResult.ok) {
return null
} }
return authResult.deliveryInfo return authResult.deliveryInfo
} }
@@ -153,14 +228,28 @@ export async function checkDeliveryAuth(): Promise<boolean> {
} }
async function getCurrentStaffId(): Promise<string> { async function getCurrentStaffId(): Promise<string> {
// 旧 delivery RPCdashboard / order_list需要 ml_delivery_staff.id513449ca... console.log('[DELIVERY_SERVICE_TRACE][getCurrentStaffId][START]', {
hasDeliveryInfo: getDeliveryInfo() != null
})
// delivery RPC (dashboard / order_list) 需要使用 ml_delivery_staff.id
const deliveryInfo = getDeliveryInfo() const deliveryInfo = getDeliveryInfo()
if (deliveryInfo != null && deliveryInfo.id != null && String(deliveryInfo.id) != '') { if (deliveryInfo != null && deliveryInfo.id != null && String(deliveryInfo.id) != '') {
console.warn('[deliveryService] getCurrentStaffId: 使用 deliveryStaffId =', String(deliveryInfo.id)) const resolvedId = String(deliveryInfo.id)
return String(deliveryInfo.id) console.log('[DELIVERY_SERVICE_TRACE][getCurrentStaffId][RESOLVED]', {
source: 'deliveryStaffId',
resolvedId: resolvedId
})
return resolvedId
} }
console.error('[deliveryService] getCurrentStaffId: 未获取到 deliveryStaffId') console.error('[DELIVERY_SERVICE_TRACE][getCurrentStaffId][ERROR]', {
errorMessage: 'deliveryStaffId not available',
errorStack: '',
params: {
hasDeliveryInfo: deliveryInfo != null
}
})
return '' return ''
} }
@@ -174,27 +263,91 @@ function createEmptyLocation(): DeliveryLocationType {
} }
export async function getDeliveryDashboard(): Promise<DeliveryDashboardType> { export async function getDeliveryDashboard(): Promise<DeliveryDashboardType> {
console.log('[DELIVERY_SERVICE_TRACE][getDeliveryDashboard][START]', {})
const staffId = await getCurrentStaffId() const staffId = await getCurrentStaffId()
if (staffId != '') { if (staffId != '') {
return await getDeliveryDashboardByStaffId(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()
}
} }
// staffId 为空时返回空 dashboard console.error('[DELIVERY_SERVICE_TRACE][getDeliveryDashboard][ERROR]', {
console.error('[deliveryService] getDeliveryDashboard: staffId 为空,返回空数据') errorMessage: 'staffId is empty',
errorStack: '',
params: {}
})
return emptyDashboard() return emptyDashboard()
} }
export async function getDeliveryOrders(params: DeliveryOrderQueryType): Promise<Array<DeliveryOrderType>> { export async function getDeliveryOrders(params: DeliveryOrderQueryType): Promise<Array<DeliveryOrderType>> {
console.log('[DELIVERY_SERVICE_TRACE][getDeliveryOrders][START]', {
params: params
})
const staffId = await getCurrentStaffId() const staffId = await getCurrentStaffId()
if (staffId != '') { if (staffId != '') {
return await getDeliveryOrdersByStaffId(staffId, params) 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<DeliveryOrderType>
}
} }
// staffId 为空时返回空列表 console.error('[DELIVERY_SERVICE_TRACE][getDeliveryOrders][ERROR]', {
console.error('[deliveryService] getDeliveryOrders: staffId 为空,返回空列表') errorMessage: 'staffId is empty',
errorStack: '',
params: {
query: params
}
})
return [] as Array<DeliveryOrderType> return [] as Array<DeliveryOrderType>
} }
export async function getDeliveryOrderDetail(id: string): Promise<DeliveryOrderType | null> { export async function getDeliveryOrderDetail(id: string): Promise<DeliveryOrderType | null> {
return await getDeliveryOrderDetailById(id) 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<DeliveryOrderType | null> { export async function acceptDeliveryOrder(id: string): Promise<DeliveryOrderType | null> {
@@ -301,18 +454,36 @@ export async function getDeliveryDashboardStats(): Promise<DeliveryDashboardType
export async function getPendingServiceOrders(): Promise<Array<DeliveryOrderType>> { export async function getPendingServiceOrders(): Promise<Array<DeliveryOrderType>> {
const orders = await getDeliveryOrders({ tab: 'pending', keyword: '' } as DeliveryOrderQueryType) const orders = await getDeliveryOrders({ tab: 'pending', keyword: '' } as DeliveryOrderQueryType)
const validOrders = filterOrdersWithCoreInfo(orders) let pendingOrders = filterOrdersWithCoreInfo(orders)
if (validOrders.length > 0) { if (pendingOrders.length == 0) {
return validOrders 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)) { if (shouldFallbackOrders(orders)) {
console.warn('[deliveryService] pending orders missing core info, fallback to direct query') console.warn('[deliveryService] pending orders missing core info, fallback to direct query')
const fallbackOrders = await getDirectOrdersByTab('pending') const fallbackOrders = await getDirectOrdersByTab('pending')
if (fallbackOrders.length > 0) { if (fallbackOrders.length > 0) {
return fallbackOrders return filterPendingOrdersAgainstActiveKeys(fallbackOrders, activeKeys)
} }
} }
return orders return filteredPendingOrders
} }
export async function getTodayServiceOrders(): Promise<Array<DeliveryOrderType>> { export async function getTodayServiceOrders(): Promise<Array<DeliveryOrderType>> {
@@ -359,29 +530,37 @@ export async function getServiceOrderDetail(orderId: string): Promise<DeliveryOr
return order return order
} }
export async function acceptServiceOrder(orderId: string): Promise<DeliveryOrderType | null> { export async function acceptServiceOrder(orderId: string): Promise<DeliveryActionResultType> {
// 居家服务订单必须调用 rpc_homecare_accept_assignment_v2
// 不再调用 acceptDeliveryOrder / rpc_delivery_accept_order
const akUserId = await resolveCurrentAkUserIdForDelivery() const akUserId = await resolveCurrentAkUserIdForDelivery()
console.warn('[HOMECARE ACCEPT] acceptServiceOrder: orderId=', orderId, ' akUserId=', akUserId) console.warn('[HOMECARE ACCEPT] acceptServiceOrder: orderId=', orderId, ' akUserId=', akUserId)
if (akUserId == '') { if (akUserId == '') {
uni.showToast({ title: '未获取到业务用户 ID请重新登录', icon: 'none' }) return {
return null ok: false,
message: '未获取到业务用户 ID请重新登录',
order: null
} as DeliveryActionResultType
} }
// 调用居家服务接单 RPC
const { acceptHomecareAssignmentV2 } = await import('@/api/delivery.uts')
const result = await acceptHomecareAssignmentV2(orderId, akUserId) const result = await acceptHomecareAssignmentV2(orderId, akUserId)
console.warn('[HOMECARE ACCEPT] rpc_homecare_accept_assignment_v2 result:', result) console.warn('[HOMECARE ACCEPT] rpc_homecare_accept_assignment_v2 result:', result)
if (result == null) {
// 刷新订单列表 return {
await loadData() ok: false,
return null 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 或缓存) * 鑾峰彇褰撳墠涓氬姟鐢ㄦ埛 ID锛堜粠 akUserMapping 鎴栫紦瀛橈級
*/ */
async function resolveCurrentAkUserIdForDelivery(): Promise<string> { async function resolveCurrentAkUserIdForDelivery(): Promise<string> {
try { try {

View File

@@ -7,27 +7,66 @@ export type DeliveryAccountStatus = 'active' | 'disabled' | 'locked' | 'suspende
export type DeliveryCertificateStatus = 'valid' | 'expired' | 'pending' export type DeliveryCertificateStatus = 'valid' | 'expired' | 'pending'
export type DeliveryOrderStatus = export type DeliveryOrderStatus =
'pending' |
'pending_assignment' | 'pending_assignment' |
'pending_accept' | 'pending_accept' |
'pending_assign' |
'pending_dispatch' |
'pending_acceptance_new' |
'assigned' |
'accepted' | 'accepted' |
'order_accepted' |
'waiting_departure' | 'waiting_departure' |
'departed' | 'departed' |
'on_the_way' | 'on_the_way' |
'order_departed' |
'arrived' | 'arrived' |
'arrival_pending' |
'order_checked_in' |
'checked_in' | 'checked_in' |
'in_service' | 'in_service' |
'serving' | 'serving' |
'order_in_service' |
'pending_confirm' | 'pending_confirm' |
'pending_submit' | 'pending_submit' |
'pending_acceptance' | 'pending_acceptance' |
'completed' | 'completed' |
'order_completed' |
'rejected' | 'rejected' |
'abnormal' | 'abnormal' |
'terminated' | 'terminated' |
'exception_pending' | 'exception_pending' |
'cancelled' | 'cancelled' |
'canceled' |
'order_cancelled' |
'settled' | 'settled' |
'archived' 'archived' |
'PENDING_ASSIGNMENT' |
'PENDING_ACCEPT' |
'PENDING_ACCEPTANCE' |
'ASSIGNED' |
'ACCEPTED' |
'WAITING_DEPARTURE' |
'DEPARTED' |
'ON_THE_WAY' |
'ARRIVAL_PENDING' |
'CHECKED_IN' |
'IN_SERVICE' |
'SERVING' |
'COMPLETED' |
'SETTLED' |
'ARCHIVED' |
'CANCELLED' |
'CANCELED' |
'REJECTED' |
'ABNORMAL' |
'EXCEPTION_PENDING' |
'ORDER_ACCEPTED' |
'ORDER_DEPARTED' |
'ORDER_CHECKED_IN' |
'ORDER_IN_SERVICE' |
'ORDER_COMPLETED' |
'ORDER_CANCELLED'
export type DeliveryExceptionType = export type DeliveryExceptionType =
'cannot_contact_user' | 'cannot_contact_user' |
@@ -148,6 +187,9 @@ export type DeliveryAbnormalReportType = {
export type DeliveryOrderType = { export type DeliveryOrderType = {
id: string id: string
orderNo: string orderNo: string
sourceOrderId: string
legacyServiceOrderId: string
resolvedWorkOrderId: string
serviceType: string serviceType: string
serviceName: string serviceName: string
serviceCategory: string serviceCategory: string
@@ -227,6 +269,12 @@ export type DeliveryOrderType = {
abnormalReport: DeliveryAbnormalReportType | null abnormalReport: DeliveryAbnormalReportType | null
} }
export type DeliveryActionResultType = {
ok: boolean
message: string
order: DeliveryOrderType | null
}
export type DeliveryCertificateType = { export type DeliveryCertificateType = {
id: string id: string
name: string name: string
@@ -349,4 +397,4 @@ export type DeliveryExceptionPayloadType = {
needPlatformIntervention?: boolean needPlatformIntervention?: boolean
requestCancelOrder?: boolean requestCancelOrder?: boolean
requestReschedule?: boolean requestReschedule?: boolean
} }

View File

@@ -5,65 +5,78 @@ export type DeliveryTabOptionType = {
value: string value: string
} }
function normalizeStatus(status: DeliveryOrderStatus): string {
return String(status ?? '').trim().toLowerCase()
}
export function getDeliveryOrderTabs(): Array<DeliveryTabOptionType> { export function getDeliveryOrderTabs(): Array<DeliveryTabOptionType> {
return [ return [
{ label: '待接单', value: 'pending' } as DeliveryTabOptionType, { label: '待接单', value: 'pending' } as DeliveryTabOptionType,
{ label: '今日订单', value: 'today' } as DeliveryTabOptionType, { label: '进行中', value: 'today' } as DeliveryTabOptionType,
{ label: '历史订单', value: 'history' } as DeliveryTabOptionType { label: '历史订单', value: 'history' } as DeliveryTabOptionType
] ]
} }
export function isHistoryStatus(status: DeliveryOrderStatus): boolean { export function isHistoryStatus(status: DeliveryOrderStatus): boolean {
return status == 'completed' || status == 'pending_acceptance' || status == 'rejected' || status == 'cancelled' || status == 'abnormal' || status == 'terminated' || status == 'archived' const s = normalizeStatus(status)
return s == 'completed' || s == 'settled' || s == 'archived' || s == 'cancelled' || s == 'canceled' || s == 'rejected' || s == 'abnormal' || s == 'exception_pending' || s == 'terminated' || s == 'order_completed' || s == 'order_cancelled'
} }
export function getDeliveryStatusLabel(status: DeliveryOrderStatus): string { export function getDeliveryStatusLabel(status: DeliveryOrderStatus): string {
if (status == 'pending_assignment' || status == 'pending_accept') return '待接单' const s = normalizeStatus(status)
if (status == 'accepted') return '接单' if (s == 'pending' || s == 'pending_assignment' || s == 'pending_accept' || s == 'pending_assign' || s == 'pending_dispatch' || s == 'pending_acceptance_new') return '接单'
if (status == 'departed' || status == 'on_the_way') return '已出发' if (s == 'assigned') return '已派单'
if (status == 'arrived') return '已到达' if (s == 'accepted' || s == 'order_accepted' || s == 'waiting_departure') return '待出发'
if (status == 'in_service' || status == 'serving') return '服务中' if (s == 'departed' || s == 'on_the_way' || s == 'order_departed') return '已出发'
if (status == 'pending_confirm' || status == 'pending_acceptance' || status == 'pending_submit') return '待确认' if (s == 'arrival_pending') return '等待消费者确认到达'
if (status == 'completed') return '已完成' if (s == 'arrived' || s == 'checked_in' || s == 'order_checked_in') return '已到达'
if (status == 'rejected') return '已拒单' if (s == 'in_service' || s == 'serving' || s == 'order_in_service') return '服务中'
if (status == 'cancelled') return '已取消' if (s == 'pending_acceptance' || s == 'pending_confirm' || s == 'pending_submit') return '等待验收'
if (status == 'abnormal' || status == 'exception_pending') return '异常上报' if (s == 'completed' || s == 'order_completed' || s == 'settled') return '已完成'
if (status == 'terminated') return '服务终止' if (s == 'rejected') return '已拒单'
return '已归档' if (s == 'cancelled' || s == 'canceled' || s == 'order_cancelled') return '已取消'
if (s == 'abnormal' || s == 'exception_pending') return '异常上报'
if (s == 'terminated') return '服务终止'
if (s == 'archived') return '已归档'
return '查看详情'
} }
export function getPrimaryActionText(status: DeliveryOrderStatus): string { export function getPrimaryActionText(status: DeliveryOrderStatus): string {
if (status == 'pending_assignment' || status == 'pending_accept') return '接单' const s = normalizeStatus(status)
if (status == 'accepted' || status == 'waiting_departure') return '前往服务' if (s == 'pending' || s == 'pending_assignment' || s == 'pending_accept' || s == 'pending_assign' || s == 'pending_dispatch' || s == 'pending_acceptance_new') return '接单'
if (status == 'departed' || status == 'on_the_way') return '我已到达' if (s == 'assigned' || s == 'accepted' || s == 'waiting_departure' || s == 'order_accepted') return '出发'
if (status == 'arrived') return '签到' if (s == 'departed' || s == 'on_the_way' || s == 'order_departed') return '到达签到'
if (status == 'in_service' || status == 'serving') return '填写记录' if (s == 'arrival_pending') return '等待确认'
if (status == 'pending_confirm' || status == 'pending_acceptance' || status == 'pending_submit') return '等待验收' if (s == 'arrived' || s == 'checked_in' || s == 'order_checked_in') return '开始服务'
if (status == 'completed') return '查看记录' if (s == 'in_service' || s == 'serving' || s == 'order_in_service') return '继续服务'
if (status == 'abnormal' || status == 'exception_pending') return '查看异常' if (s == 'completed' || s == 'order_completed' || s == 'settled' || s == 'archived') return '查看详情'
return '查看详情' return '查看详情'
} }
export function getNextStepText(status: DeliveryOrderStatus): string { export function getNextStepText(status: DeliveryOrderStatus): string {
if (status == 'pending_assignment' || status == 'pending_accept') return '确认是否接单' const s = normalizeStatus(status)
if (status == 'accepted' || status == 'waiting_departure') return '前往服务对象地址并发起导航' if (s == 'pending' || s == 'pending_assignment' || s == 'pending_accept' || s == 'pending_assign' || s == 'pending_dispatch' || s == 'pending_acceptance_new') return '确认是否接单'
if (status == 'departed' || status == 'on_the_way') return '到达服务地' if (s == 'assigned' || s == 'accepted' || s == 'waiting_departure' || s == 'order_accepted') return '准备出发前往服务地'
if (status == 'arrived') return '完成签到确认' if (s == 'departed' || s == 'on_the_way' || s == 'order_departed') return '到达服务地点后完成签到'
if (status == 'in_service' || status == 'serving') return '补充服务记录并完成服务' if (s == 'arrival_pending') return '等待消费者确认到达'
if (status == 'pending_confirm' || status == 'pending_acceptance' || status == 'pending_submit') return '等待用户确认验收' if (s == 'arrived' || s == 'checked_in' || s == 'order_checked_in') return '开始服务并补充记录'
if (status == 'completed') return '查看历史记录' if (s == 'in_service' || s == 'serving' || s == 'order_in_service') return '继续服务并完善服务记录'
if (status == 'abnormal' || status == 'exception_pending') return '跟进异常处置' if (s == 'pending_acceptance' || s == 'pending_confirm' || s == 'pending_submit') return '等待用户确认验收'
if (s == 'completed' || s == 'order_completed' || s == 'settled') return '查看历史服务记录'
if (s == 'abnormal' || s == 'exception_pending') return '跟进异常处理'
return '查看订单详情' return '查看订单详情'
} }
export function getStatusClass(status: DeliveryOrderStatus): string { export function getStatusClass(status: DeliveryOrderStatus): string {
if (status == 'pending_assignment' || status == 'pending_accept' || status == 'pending_confirm' || status == 'pending_acceptance' || status == 'pending_submit') return 'warning' const s = normalizeStatus(status)
if (status == 'completed') return 'success' if (s == 'pending' || s == 'pending_assignment' || s == 'pending_accept' || s == 'pending_assign' || s == 'pending_dispatch' || s == 'pending_acceptance_new' || s == 'pending_confirm' || s == 'pending_acceptance' || s == 'pending_submit' || s == 'arrival_pending') return 'warning'
if (status == 'abnormal' || status == 'exception_pending') return 'danger' if (s == 'assigned' || s == 'accepted' || s == 'waiting_departure' || s == 'departed' || s == 'on_the_way' || s == 'order_accepted' || s == 'order_departed') return 'primary'
if (status == 'rejected' || status == 'cancelled' || status == 'terminated') return 'muted' if (s == 'completed' || s == 'order_completed' || s == 'settled' || s == 'archived') return 'success'
if (s == 'abnormal' || s == 'exception_pending') return 'danger'
if (s == 'rejected' || s == 'cancelled' || s == 'canceled' || s == 'terminated' || s == 'order_cancelled') return 'muted'
return 'primary' return 'primary'
} }
export function needsServiceRecord(order: DeliveryOrderType): boolean { export function needsServiceRecord(order: DeliveryOrderType): boolean {
return order.serviceRecord == null return order.serviceRecord == null
} }

View File

@@ -85,6 +85,8 @@ export function getHomecareTaskStatusTheme(status: string): string {
// 给定角色与状态,返回允许的前端操作标识 // 给定角色与状态,返回允许的前端操作标识
export function getHomecareTaskAllowedActions(status: string, role: string): Array<string> { export function getHomecareTaskAllowedActions(status: string, role: string): Array<string> {
const actions = [] as Array<string> const actions = [] as Array<string>
const normalizedStatus = normalizeToOrderStatus(status)
if (role == 'FAMILY_USER' || role == 'consumer') { if (role == 'FAMILY_USER' || role == 'consumer') {
if (status == ORDER_COMPLETED || status == ACCEPTANCE_PENDING) { if (status == ORDER_COMPLETED || status == ACCEPTANCE_PENDING) {
actions.push('confirm_acceptance') actions.push('confirm_acceptance')
@@ -116,6 +118,15 @@ export function getHomecareTaskAllowedActions(status: string, role: string): Arr
actions.push('dispatch') actions.push('dispatch')
} }
} }
console.log('[HOMECARE_STATUS_TRACE][ACTIONS]', {
rawStatus: status,
normalizedStatus: normalizedStatus,
role: role,
actions: actions,
departedAllowsCheckin: normalizedStatus == ORDER_ACCEPTED
})
return actions return actions
} }
@@ -159,3 +170,147 @@ export function normalizeToOrderStatus(raw: string): string {
export function isHomecareTaskClosed(status: string): boolean { export function isHomecareTaskClosed(status: string): boolean {
return status == ARCHIVED || status == ORDER_CANCELLED || status == ORDER_CLOSED || status == ACCEPTED || status == SETTLEMENT_READY return status == ARCHIVED || status == ORDER_CANCELLED || status == ORDER_CLOSED || status == ACCEPTED || status == SETTLEMENT_READY
} }
// =============================================================================
// 新增delivery / consumer 通用订单状态映射(含 ARRIVAL_PENDING
// 用于 deliveryService、checkin.uvue、order-detail.uvue 等
// =============================================================================
/** 服务人员已提交到达签到,等待消费者确认 */
export const ARRIVAL_PENDING = 'ARRIVAL_PENDING'
/** 订单状态元信息 */
export type OrderStatusMeta = {
statusText: string
statusDesc: string
statusTone: string
waitingConsumerConfirm: boolean
canArriveCheckin: boolean
canStartService: boolean
canFinishService: boolean
tab: string
}
/**
* 归一化订单状态元信息
* 覆盖旧 delivery 状态 + 居家服务新状态(含 ARRIVAL_PENDING
*/
export function normalizeOrderStatus(raw: string): OrderStatusMeta {
const s = raw.trim().toUpperCase()
// ARRIVAL_PENDING — 服务人员已提交到达签到,等待消费者确认
if (s == ARRIVAL_PENDING) {
return {
statusText: '等待消费者确认到达',
statusDesc: '服务人员已提交到达签到,等待消费者确认',
statusTone: 'warning',
waitingConsumerConfirm: true,
canArriveCheckin: false,
canStartService: false,
canFinishService: false,
tab: 'in_progress'
} as OrderStatusMeta
}
// 旧 delivery 状态映射
if (s == 'PENDING_ASSIGNMENT' || s == 'CREATED') return { statusText: '待派单', statusDesc: '订单已创建,等待调度员派单', statusTone: 'default', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'pending' } as OrderStatusMeta
if (s == 'PENDING_ACCEPT' || s == 'PENDING_ACCEPTANCE') return { statusText: '待接单', statusDesc: '订单已派发,等待服务人员接单', statusTone: 'warning', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'pending_accept' } as OrderStatusMeta
if (s == 'ACCEPTED') return { statusText: '已接单', statusDesc: '服务人员已接单,准备出发', statusTone: 'primary', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'in_progress' } as OrderStatusMeta
if (s == 'WAITING_DEPARTURE') return { statusText: '待出发', statusDesc: '等待服务人员出发', statusTone: 'primary', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'in_progress' } as OrderStatusMeta
if (s == 'DEPARTED' || s == 'ON_THE_WAY') return { statusText: '前往中', statusDesc: '服务人员正在前往服务地点', statusTone: 'primary', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'in_progress' } as OrderStatusMeta
if (s == 'ARRIVED' || s == 'CHECKED_IN') return { statusText: '已到达', statusDesc: '服务人员已到达服务地点', statusTone: 'success', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: true, canFinishService: false, tab: 'in_progress' } as OrderStatusMeta
if (s == 'IN_SERVICE' || s == 'SERVING') return { statusText: '服务中', statusDesc: '服务人员正在提供服务', statusTone: 'success', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: true, tab: 'in_progress' } as OrderStatusMeta
if (s == 'PENDING_CONFIRM' || s == 'PENDING_SUBMIT') return { statusText: '待确认', statusDesc: '等待消费者确认服务完成', statusTone: 'warning', waitingConsumerConfirm: true, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'in_progress' } as OrderStatusMeta
if (s == 'COMPLETED') return { statusText: '已完成', statusDesc: '订单已完成', statusTone: 'success', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'completed' } as OrderStatusMeta
if (s == 'CANCELLED') return { statusText: '已取消', statusDesc: '订单已取消', statusTone: 'info', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'cancelled' } as OrderStatusMeta
if (s == 'REJECTED') return { statusText: '已拒绝', statusDesc: '服务人员已拒绝该订单', statusTone: 'danger', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'cancelled' } as OrderStatusMeta
if (s == 'ABNORMAL' || s == 'EXCEPTION' || s == 'EXCEPTION_PENDING') return { statusText: '异常处理中', statusDesc: '订单发生异常', statusTone: 'danger', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'in_progress' } as OrderStatusMeta
if (s == 'SETTLED' || s == 'ARCHIVED') return { statusText: '已完成', statusDesc: '订单已完成', statusTone: 'success', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'completed' } as OrderStatusMeta
// 居家服务 ORDER_* 状态
if (s == ORDER_CREATED) return { statusText: '待安排服务', statusDesc: '订单已创建,等待调度员派单', statusTone: 'default', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'pending' } as OrderStatusMeta
if (s == ORDER_ASSIGNED) return { statusText: '已安排服务人员,等待接单', statusDesc: '工单已分配至服务人员', statusTone: 'primary', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'pending_accept' } as OrderStatusMeta
if (s == ORDER_ACCEPTED) return { statusText: '服务人员已接单,等待上门', statusDesc: '服务人员已接单', statusTone: 'primary', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'in_progress' } as OrderStatusMeta
if (s == ORDER_CHECKED_IN) return { statusText: '服务人员已到达', statusDesc: '服务人员已到达现场', statusTone: 'success', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: true, canFinishService: false, tab: 'in_progress' } as OrderStatusMeta
if (s == ORDER_IN_SERVICE) return { statusText: '服务进行中', statusDesc: '服务人员正在提供服务', statusTone: 'success', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: true, tab: 'in_progress' } as OrderStatusMeta
if (s == ORDER_COMPLETED) return { statusText: '服务已完成,待验收', statusDesc: '服务人员已提交完成', statusTone: 'primary', waitingConsumerConfirm: true, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'in_progress' } as OrderStatusMeta
if (s == ACCEPTANCE_PENDING) return { statusText: '待验收', statusDesc: '等待消费者验收', statusTone: 'warning', waitingConsumerConfirm: true, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'in_progress' } as OrderStatusMeta
if (s == ACCEPTED) return { statusText: '已验收', statusDesc: '消费者已验收', statusTone: 'success', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'completed' } as OrderStatusMeta
if (s == ORDER_CANCELLED) return { statusText: '已取消', statusDesc: '订单已取消', statusTone: 'info', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'cancelled' } as OrderStatusMeta
if (s == ARCHIVED) return { statusText: '已归档', statusDesc: '订单已归档', statusTone: 'info', waitingConsumerConfirm: false, canArriveCheckin: false, canStartService: false, canFinishService: false, tab: 'completed' } as OrderStatusMeta
// 未知状态
return {
statusText: raw,
statusDesc: '未知状态',
statusTone: 'default',
waitingConsumerConfirm: false,
canArriveCheckin: false,
canStartService: false,
canFinishService: false,
tab: 'pending'
} as OrderStatusMeta
}
/**
* 获取状态文本(用于卡片标签)
*/
export function getOrderStatusText(raw: string): string {
return normalizeOrderStatus(raw).statusText
}
/**
* 获取状态描述(用于详情页说明)
*/
export function getOrderStatusDesc(raw: string): string {
return normalizeOrderStatus(raw).statusDesc
}
/**
* 获取状态色调(用于 UI 颜色)
*/
export function getOrderStatusTone(raw: string): string {
return normalizeOrderStatus(raw).statusTone
}
/**
* 是否可以显示"到达签到"按钮
*/
export function canShowArriveCheckin(raw: string): boolean {
return normalizeOrderStatus(raw).canArriveCheckin
}
/**
* 是否需要等待消费者确认(到达确认 / 服务验收)
*/
export function canShowWaitingConsumerConfirm(raw: string): boolean {
return normalizeOrderStatus(raw).waitingConsumerConfirm
}
/**
* 判断订单是否属于"进行中" tab
*/
export function isInProgress(raw: string): boolean {
return normalizeOrderStatus(raw).tab == 'in_progress'
}
/**
* 判断订单是否属于"待接单" tab
*/
export function isPendingAccept(raw: string): boolean {
return normalizeOrderStatus(raw).tab == 'pending_accept'
}
/**
* 判断订单是否属于"已完成" tab
*/
export function isCompleted(raw: string): boolean {
return normalizeOrderStatus(raw).tab == 'completed'
}
/**
* 判断订单是否属于"已取消" tab
*/
export function isCancelled(raw: string): boolean {
return normalizeOrderStatus(raw).tab == 'cancelled'
}

File diff suppressed because one or more lines are too long