forked from gxwebsoft/mp-10550
feat(ticket): 完善水票配送订单功能
- 优化导入路径,修复 PageParam 类型引用 - 新增 DeliverConfirmMode 类型定义,支持拍照完成和等待客户确认两种模式 - 实现配送确认的双模式功能,支持直接完成和等待确认流程 - 重构订单状态判断逻辑,完善配送流程状态管理 - 新增用户端确认收货功能,支持手动确认收货操作 - 优化订单列表展示,增加票号、取货点、门店电话等详细信息 - 添加地址复制和联系门店功能按钮 - 实现补传照片完成订单功能 - 更新订单流程状态显示,提供更准确的状态标识 - 添加配送确认模式切换的单选框界面 - 优化下单成功后的页面跳转逻辑 - 新增水票配送订单后端接口设计文档
This commit is contained in:
@@ -16,7 +16,7 @@ import {
|
||||
import { View, Text, Image } from '@tarojs/components';
|
||||
import { pageGltUserTicket } from '@/api/glt/gltUserTicket';
|
||||
import type { GltUserTicket } from '@/api/glt/gltUserTicket/model';
|
||||
import { pageGltTicketOrder } from '@/api/glt/gltTicketOrder';
|
||||
import { pageGltTicketOrder, updateGltTicketOrder } from '@/api/glt/gltTicketOrder';
|
||||
import type { GltTicketOrder } from '@/api/glt/gltTicketOrder/model';
|
||||
import { BaseUrl } from '@/config/app';
|
||||
import dayjs from "dayjs";
|
||||
@@ -37,7 +37,10 @@ const UserTicketList = () => {
|
||||
const [orderPage, setOrderPage] = useState(1);
|
||||
const [orderTotal, setOrderTotal] = useState(0);
|
||||
|
||||
const [activeTab, setActiveTab] = useState<'ticket' | 'order'>('ticket');
|
||||
const [activeTab, setActiveTab] = useState<'ticket' | 'order'>(() => {
|
||||
const tab = Taro.getCurrentInstance().router?.params?.tab
|
||||
return tab === 'order' ? 'order' : 'ticket'
|
||||
});
|
||||
|
||||
const [qrVisible, setQrVisible] = useState(false);
|
||||
const [qrTicket, setQrTicket] = useState<GltUserTicket | null>(null);
|
||||
@@ -253,13 +256,56 @@ const UserTicketList = () => {
|
||||
return d.isValid() ? d.format('YYYY年MM月DD日 HH:mm:ss') : v;
|
||||
};
|
||||
|
||||
const getOrderStatusText = (status?: number) => {
|
||||
// Backend field meaning may vary; page asks for "是否送达".
|
||||
if (status === 1) return { text: '已送达', type: 'success' as const };
|
||||
if (status === 0) return { text: '未送达', type: 'warning' as const };
|
||||
return { text: status == null ? '-' : String(status), type: 'primary' as const };
|
||||
const getTicketOrderStatusMeta = (order: GltTicketOrder) => {
|
||||
if (order.status === 1) return { text: '已冻结', type: 'warning' as const };
|
||||
|
||||
const ds = order.deliveryStatus
|
||||
if (ds === 40 || order.receiveConfirmTime) return { text: '已完成', type: 'success' as const };
|
||||
if (ds === 30 || order.sendEndTime) return { text: '待确认收货', type: 'primary' as const };
|
||||
if (ds === 20 || order.sendStartTime) return { text: '配送中', type: 'primary' as const };
|
||||
if (ds === 10 || order.riderId) return { text: '待配送', type: 'warning' as const };
|
||||
return { text: '待派单', type: 'primary' as const };
|
||||
};
|
||||
|
||||
const canUserConfirmReceive = (order: GltTicketOrder) => {
|
||||
if (!order?.id) return false
|
||||
if (order.status === 1) return false
|
||||
if (order.deliveryStatus === 40) return false
|
||||
if (order.receiveConfirmTime) return false
|
||||
// 必须是“已送达”后才能确认收货
|
||||
return !!order.sendEndTime || order.deliveryStatus === 30
|
||||
}
|
||||
|
||||
const handleUserConfirmReceive = async (order: GltTicketOrder) => {
|
||||
if (!order?.id) return
|
||||
if (!canUserConfirmReceive(order)) return
|
||||
|
||||
const modal = await Taro.showModal({
|
||||
title: '确认收货',
|
||||
content: '请确认已收到本次送水,确认后将无法撤销。',
|
||||
confirmText: '确认收货'
|
||||
})
|
||||
if (!modal.confirm) return
|
||||
|
||||
try {
|
||||
Taro.showLoading({ title: '提交中...' })
|
||||
const now = dayjs().format('YYYY-MM-DD HH:mm:ss')
|
||||
await updateGltTicketOrder({
|
||||
id: order.id,
|
||||
deliveryStatus: 40,
|
||||
receiveConfirmTime: now,
|
||||
receiveConfirmType: 10
|
||||
})
|
||||
Taro.showToast({ title: '已确认收货', icon: 'success' })
|
||||
await reloadOrders(true)
|
||||
} catch (e) {
|
||||
console.error('确认收货失败:', e)
|
||||
Taro.showToast({ title: '确认失败,请重试', icon: 'none' })
|
||||
} finally {
|
||||
Taro.hideLoading()
|
||||
}
|
||||
}
|
||||
|
||||
useDidShow(() => {
|
||||
if (activeTab === 'ticket') {
|
||||
reloadTickets(true).then();
|
||||
@@ -436,10 +482,52 @@ const UserTicketList = () => {
|
||||
</View>
|
||||
</View>
|
||||
{(() => {
|
||||
const meta = getOrderStatusText(item.status);
|
||||
const meta = getTicketOrderStatusMeta(item);
|
||||
return <Tag type={meta.type}>{meta.text}</Tag>;
|
||||
})()}
|
||||
</View>
|
||||
<View className="mt-2 text-xs text-gray-500">
|
||||
<Text>订单号:{item.id ?? '-'}</Text>
|
||||
</View>
|
||||
<View className="mt-1 text-xs text-gray-500">
|
||||
<Text>收货地址:{item.address || '-'}</Text>
|
||||
</View>
|
||||
{item.storeName ? (
|
||||
<View className="mt-1 text-xs text-gray-500">
|
||||
<Text>门店:{item.storeName}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{item.sendStartTime ? (
|
||||
<View className="mt-1 text-xs text-gray-500">
|
||||
<Text>开始配送:{formatDateTime(item.sendStartTime)}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{item.sendEndTime ? (
|
||||
<View className="mt-1 text-xs text-gray-500">
|
||||
<Text>送达时间:{formatDateTime(item.sendEndTime)}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{item.receiveConfirmTime ? (
|
||||
<View className="mt-1 text-xs text-gray-500">
|
||||
<Text>确认收货:{formatDateTime(item.receiveConfirmTime)}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{item.sendEndImg ? (
|
||||
<View className="mt-3">
|
||||
<Image src={item.sendEndImg} mode="aspectFill" style={{ width: '100%', height: '160px', borderRadius: '8px' }} />
|
||||
</View>
|
||||
) : null}
|
||||
{canUserConfirmReceive(item) ? (
|
||||
<View className="mt-3 flex justify-end">
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
onClick={() => handleUserConfirmReceive(item)}
|
||||
>
|
||||
确认收货
|
||||
</Button>
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user