feat(ticket): 将送水订单功能重构为配送订单系统
- 修改页面标题从"送水订单"为"配送订单" - 扩展订单模型增加配送相关字段:配送开始时间、结束时间、送达照片、配送状态、客户确认时间等 - 新增配送员角色相关字段和筛选参数 - 实现完整的配送流程管理:待配送、配送中、待确认、已完成状态流转 - 添加配送订单标签页切换功能,支持按状态分类查看 - 集成配送操作界面,支持开始配送和确认送达功能 - 实现配送照片上传和展示功能 - 优化订单列表显示,增加配送流程进度展示 - 添加配送相关的业务逻辑验证和状态判断方法
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '送水订单',
|
||||
navigationBarTitleText: '配送订单',
|
||||
navigationBarTextStyle: 'black',
|
||||
navigationBarBackgroundColor: '#ffffff'
|
||||
})
|
||||
|
||||
|
||||
@@ -1,119 +1,492 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import Taro, { useDidShow } from '@tarojs/taro'
|
||||
import { View, Text } from '@tarojs/components'
|
||||
import { Cell, CellGroup, InfiniteLoading, PullToRefresh, Empty, Loading } from '@nutui/nutui-react-taro'
|
||||
import {
|
||||
Tabs,
|
||||
TabPane,
|
||||
Cell,
|
||||
Space,
|
||||
Button,
|
||||
Dialog,
|
||||
Image,
|
||||
Empty,
|
||||
InfiniteLoading,
|
||||
PullToRefresh,
|
||||
Loading
|
||||
} from '@nutui/nutui-react-taro'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
import { pageGltTicketOrder } from '@/api/glt/gltTicketOrder'
|
||||
import type { GltTicketOrder } from '@/api/glt/gltTicketOrder/model'
|
||||
import { pageGltTicketOrder, updateGltTicketOrder } from '@/api/glt/gltTicketOrder'
|
||||
import type { GltTicketOrder, GltTicketOrderParam } from '@/api/glt/gltTicketOrder/model'
|
||||
import { uploadFile } from '@/api/system/file'
|
||||
|
||||
const PAGE_SIZE = 10
|
||||
|
||||
export default function TicketOrdersPage() {
|
||||
const [list, setList] = useState<GltTicketOrder[]>([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [hasMore, setHasMore] = useState(true)
|
||||
const [page, setPage] = useState(1)
|
||||
|
||||
const userId = (() => {
|
||||
const riderId = useMemo(() => {
|
||||
const raw = Taro.getStorageSync('UserId')
|
||||
const id = Number(raw)
|
||||
return Number.isFinite(id) && id > 0 ? id : undefined
|
||||
})()
|
||||
}, [])
|
||||
|
||||
const reload = async (isRefresh = true) => {
|
||||
if (loading) return
|
||||
if (!userId) {
|
||||
setList([])
|
||||
setHasMore(false)
|
||||
return
|
||||
}
|
||||
const pageRef = useRef(1)
|
||||
const listRef = useRef<GltTicketOrder[]>([])
|
||||
|
||||
setLoading(true)
|
||||
try {
|
||||
const currentPage = isRefresh ? 1 : page
|
||||
const res = await pageGltTicketOrder({
|
||||
const [tabIndex, setTabIndex] = useState(0)
|
||||
const [list, setList] = useState<GltTicketOrder[]>([])
|
||||
const [hasMore, setHasMore] = useState(true)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
const [deliverDialogVisible, setDeliverDialogVisible] = useState(false)
|
||||
const [deliverSubmitting, setDeliverSubmitting] = useState(false)
|
||||
const [deliverOrder, setDeliverOrder] = useState<GltTicketOrder | null>(null)
|
||||
const [deliverImg, setDeliverImg] = useState<string | undefined>(undefined)
|
||||
|
||||
const riderTabs = useMemo(
|
||||
() => [
|
||||
{ index: 0, title: '全部' },
|
||||
{ index: 1, title: '待配送', deliveryStatus: 10 },
|
||||
{ index: 2, title: '配送中', deliveryStatus: 20 },
|
||||
{ index: 3, title: '待确认', deliveryStatus: 30 },
|
||||
{ index: 4, title: '已完成', deliveryStatus: 40 }
|
||||
],
|
||||
[]
|
||||
)
|
||||
|
||||
const getOrderStatusText = (order: GltTicketOrder) => {
|
||||
if (order.status === 1) return '已冻结'
|
||||
|
||||
const deliveryStatus = order.deliveryStatus
|
||||
if (deliveryStatus === 40) return '已完成'
|
||||
if (deliveryStatus === 30) return '待客户确认'
|
||||
if (deliveryStatus === 20) return '配送中'
|
||||
if (deliveryStatus === 10) return '待配送'
|
||||
|
||||
// 兼容:如果后端暂未下发 deliveryStatus,就用时间字段推断
|
||||
if (order.receiveConfirmTime) return '已完成'
|
||||
if (order.sendEndTime) return '待客户确认'
|
||||
if (order.sendStartTime) return '配送中'
|
||||
if (order.riderId) return '待配送'
|
||||
return '待派单'
|
||||
}
|
||||
|
||||
const getOrderStatusColor = (order: GltTicketOrder) => {
|
||||
const text = getOrderStatusText(order)
|
||||
if (text === '已完成') return 'text-green-600'
|
||||
if (text === '待客户确认') return 'text-purple-600'
|
||||
if (text === '配送中') return 'text-blue-600'
|
||||
if (text === '待配送') return 'text-amber-600'
|
||||
if (text === '已冻结') return 'text-orange-600'
|
||||
return 'text-gray-500'
|
||||
}
|
||||
|
||||
const canStartDeliver = (order: GltTicketOrder) => {
|
||||
if (!order.id) return false
|
||||
if (order.status === 1) return false
|
||||
if (!riderId || order.riderId !== riderId) return false
|
||||
if (order.deliveryStatus && order.deliveryStatus !== 10) return false
|
||||
return !order.sendStartTime && !order.sendEndTime
|
||||
}
|
||||
|
||||
const canConfirmDelivered = (order: GltTicketOrder) => {
|
||||
if (!order.id) return false
|
||||
if (order.status === 1) return false
|
||||
if (!riderId || order.riderId !== riderId) return false
|
||||
if (order.receiveConfirmTime) return false
|
||||
if (order.deliveryStatus === 40) return false
|
||||
return !order.sendEndTime
|
||||
}
|
||||
|
||||
const filterByTab = useCallback(
|
||||
(orders: GltTicketOrder[]) => {
|
||||
if (tabIndex === 0) return orders
|
||||
|
||||
const current = riderTabs.find(t => t.index === tabIndex)
|
||||
const status = current?.deliveryStatus
|
||||
if (!status) return orders
|
||||
|
||||
// 如果后端已实现 deliveryStatus 筛选,这里基本不会再过滤;否则用兼容逻辑兜底。
|
||||
return orders.filter(o => {
|
||||
const ds = o.deliveryStatus
|
||||
if (typeof ds === 'number') return ds === status
|
||||
if (status === 10) return !!o.riderId && !o.sendStartTime && !o.sendEndTime
|
||||
if (status === 20) return !!o.sendStartTime && !o.sendEndTime
|
||||
if (status === 30) return !!o.sendEndTime && !o.receiveConfirmTime
|
||||
if (status === 40) return !!o.receiveConfirmTime
|
||||
return true
|
||||
})
|
||||
},
|
||||
[riderTabs, tabIndex]
|
||||
)
|
||||
|
||||
const reload = useCallback(
|
||||
async (resetPage = false) => {
|
||||
if (!riderId) return
|
||||
if (loading) return
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
|
||||
const currentPage = resetPage ? 1 : pageRef.current
|
||||
const currentTab = riderTabs.find(t => t.index === tabIndex)
|
||||
|
||||
const params: GltTicketOrderParam = {
|
||||
page: currentPage,
|
||||
limit: PAGE_SIZE,
|
||||
userId
|
||||
} as any)
|
||||
riderId,
|
||||
deliveryStatus: currentTab?.deliveryStatus
|
||||
}
|
||||
|
||||
const resList = res?.list || []
|
||||
const next = isRefresh ? resList : [...list, ...resList]
|
||||
setList(next)
|
||||
try {
|
||||
const res = await pageGltTicketOrder(params as any)
|
||||
const incomingAll = (res?.list || []) as GltTicketOrder[]
|
||||
// 兼容:后端若暂未实现 riderId 过滤,前端兜底过滤掉非本人的订单
|
||||
const incoming = incomingAll.filter(o => o?.deleted !== 1 && o?.riderId === riderId)
|
||||
|
||||
const total = typeof res?.count === 'number' ? res.count : next.length
|
||||
setHasMore(next.length < total)
|
||||
setPage(currentPage + 1)
|
||||
const prev = resetPage ? [] : listRef.current
|
||||
const next = resetPage ? incoming : prev.concat(incoming)
|
||||
listRef.current = next
|
||||
setList(next)
|
||||
|
||||
const total = typeof res?.count === 'number' ? res.count : undefined
|
||||
const filteredOut = incomingAll.length - incoming.length
|
||||
if (typeof total === 'number' && filteredOut === 0) {
|
||||
setHasMore(next.length < total)
|
||||
} else {
|
||||
setHasMore(incomingAll.length >= PAGE_SIZE)
|
||||
}
|
||||
|
||||
pageRef.current = currentPage + 1
|
||||
} catch (e) {
|
||||
console.error('加载配送订单失败:', e)
|
||||
setError('加载失败,请重试')
|
||||
setHasMore(false)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
},
|
||||
[loading, riderId, riderTabs, tabIndex]
|
||||
)
|
||||
|
||||
const reloadMore = useCallback(async () => {
|
||||
if (loading || !hasMore) return
|
||||
await reload(false)
|
||||
}, [hasMore, loading, reload])
|
||||
|
||||
const openDeliverDialog = (order: GltTicketOrder) => {
|
||||
setDeliverOrder(order)
|
||||
setDeliverImg(order.sendEndImg)
|
||||
setDeliverDialogVisible(true)
|
||||
}
|
||||
|
||||
const handleChooseDeliverImg = async () => {
|
||||
try {
|
||||
const file = await uploadFile()
|
||||
setDeliverImg(file?.url)
|
||||
} catch (e) {
|
||||
console.error('获取送水订单失败:', e)
|
||||
Taro.showToast({ title: '获取送水订单失败', icon: 'none' })
|
||||
setHasMore(false)
|
||||
console.error('上传送达照片失败:', e)
|
||||
Taro.showToast({ title: '上传失败,请重试', icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
const handleStartDeliver = async (order: GltTicketOrder) => {
|
||||
if (!order?.id) return
|
||||
if (!canStartDeliver(order)) return
|
||||
try {
|
||||
await updateGltTicketOrder({
|
||||
id: order.id,
|
||||
deliveryStatus: 20,
|
||||
sendStartTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
|
||||
})
|
||||
Taro.showToast({ title: '已开始配送', icon: 'success' })
|
||||
pageRef.current = 1
|
||||
await reload(true)
|
||||
} catch (e) {
|
||||
console.error('开始配送失败:', e)
|
||||
Taro.showToast({ title: '开始配送失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
const handleConfirmDelivered = async () => {
|
||||
if (!deliverOrder?.id) return
|
||||
if (deliverSubmitting) return
|
||||
setDeliverSubmitting(true)
|
||||
try {
|
||||
// 说明:
|
||||
// - sendEndImg:送达照片留档(可选/必填由后端策略决定)
|
||||
// - sendEndTime:配送员确认送达时间
|
||||
// - deliveryStatus:建议后端设置为 30(待客户确认)
|
||||
await updateGltTicketOrder({
|
||||
id: deliverOrder.id,
|
||||
deliveryStatus: 30,
|
||||
sendEndTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
sendEndImg: deliverImg
|
||||
})
|
||||
Taro.showToast({ title: '已确认送达', icon: 'success' })
|
||||
setDeliverDialogVisible(false)
|
||||
setDeliverOrder(null)
|
||||
setDeliverImg(undefined)
|
||||
pageRef.current = 1
|
||||
await reload(true)
|
||||
} catch (e) {
|
||||
console.error('确认送达失败:', e)
|
||||
Taro.showToast({ title: '确认送达失败', icon: 'none' })
|
||||
} finally {
|
||||
setLoading(false)
|
||||
setDeliverSubmitting(false)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
listRef.current = list
|
||||
}, [list])
|
||||
|
||||
useDidShow(() => {
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
listRef.current = []
|
||||
setList([])
|
||||
setHasMore(true)
|
||||
reload(true)
|
||||
void reload(true)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
pageRef.current = 1
|
||||
listRef.current = []
|
||||
setList([])
|
||||
setHasMore(true)
|
||||
void reload(true)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [tabIndex, riderId])
|
||||
|
||||
if (!riderId) {
|
||||
return (
|
||||
<View className="bg-gray-50 min-h-screen p-4">
|
||||
<Text>请先登录</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const displayList = filterByTab(list)
|
||||
|
||||
return (
|
||||
<View className="bg-gray-50 min-h-screen">
|
||||
<Tabs value={tabIndex} onChange={paneKey => setTabIndex(Number(paneKey))} align="left">
|
||||
{riderTabs.map(t => (
|
||||
<TabPane key={t.index} title={loading && tabIndex === t.index ? `${t.title}...` : t.title} />
|
||||
))}
|
||||
</Tabs>
|
||||
|
||||
<View className="px-3">
|
||||
<PullToRefresh onRefresh={() => reload(true)}>
|
||||
{list.length === 0 && !loading ? (
|
||||
<View className="px-3 pb-4">
|
||||
<PullToRefresh
|
||||
onRefresh={async () => {
|
||||
pageRef.current = 1
|
||||
listRef.current = []
|
||||
setList([])
|
||||
setHasMore(true)
|
||||
await reload(true)
|
||||
}}
|
||||
>
|
||||
{error ? (
|
||||
<View className="bg-white rounded-lg p-6">
|
||||
<Empty description="暂无送水订单" />
|
||||
<View className="flex flex-col items-center justify-center">
|
||||
<Text className="text-gray-500 mb-3">{error}</Text>
|
||||
<Button size="small" type="primary" onClick={() => reload(true)}>
|
||||
重新加载
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<CellGroup>
|
||||
{list.map((o) => {
|
||||
<InfiniteLoading
|
||||
hasMore={hasMore}
|
||||
onLoadMore={reloadMore}
|
||||
loadingText={
|
||||
<View className="flex justify-center items-center py-4">
|
||||
<Loading />
|
||||
<View className="ml-2">加载中...</View>
|
||||
</View>
|
||||
}
|
||||
loadMoreText={
|
||||
displayList.length === 0 ? (
|
||||
<View className="bg-white rounded-lg p-6">
|
||||
<Empty description="暂无配送订单" />
|
||||
</View>
|
||||
) : (
|
||||
<View className="text-center py-4 text-gray-500">没有更多了</View>
|
||||
)
|
||||
}
|
||||
>
|
||||
{displayList.map(o => {
|
||||
const qty = Number(o.totalNum || 0)
|
||||
const timeText = o.createTime ? dayjs(o.createTime).format('YYYY-MM-DD HH:mm') : ''
|
||||
const addr = o.address || (o.addressId ? `地址ID:${o.addressId}` : '')
|
||||
const remark = o.buyerRemarks || ''
|
||||
const timeText = o.createTime ? dayjs(o.createTime).format('YYYY-MM-DD HH:mm') : '-'
|
||||
const addr = o.address || (o.addressId ? `地址ID:${o.addressId}` : '-')
|
||||
const remark = o.buyerRemarks || o.comments || ''
|
||||
|
||||
const flow1Done = !!o.riderId
|
||||
const flow2Done = !!o.sendStartTime || (typeof o.deliveryStatus === 'number' && o.deliveryStatus >= 20)
|
||||
const flow3Done = !!o.sendEndTime
|
||||
const flow4Done = !!o.receiveConfirmTime || o.deliveryStatus === 40
|
||||
|
||||
const phoneToCall = o.phone
|
||||
|
||||
return (
|
||||
<Cell
|
||||
key={o.id}
|
||||
title={
|
||||
<View className="flex flex-col">
|
||||
<Text className="text-sm text-gray-900">送水 {qty || '-'} 桶</Text>
|
||||
{addr ? <Text className="text-xs text-gray-500">{addr}</Text> : null}
|
||||
{remark ? <Text className="text-xs text-gray-500">备注:{remark}</Text> : null}
|
||||
<Cell key={String(o.id)} style={{ padding: '16px' }}>
|
||||
<View className="w-full">
|
||||
<View className="flex justify-between items-center">
|
||||
<Text className="text-gray-800 font-bold text-sm">{`订单#${o.id}`}</Text>
|
||||
<Text className={`${getOrderStatusColor(o)} text-sm font-medium`}>{getOrderStatusText(o)}</Text>
|
||||
</View>
|
||||
}
|
||||
extra={<Text className="text-xs text-gray-500">{timeText}</Text>}
|
||||
/>
|
||||
|
||||
<View className="text-gray-400 text-xs mt-1">下单时间:{timeText}</View>
|
||||
|
||||
<View className="mt-3 bg-white rounded-lg">
|
||||
<View className="text-sm text-gray-700">
|
||||
<Text className="text-gray-500">收货地址:</Text>
|
||||
<Text>{addr}</Text>
|
||||
</View>
|
||||
<View className="text-sm text-gray-700 mt-1">
|
||||
<Text className="text-gray-500">客户:</Text>
|
||||
<Text>
|
||||
{o.nickname || '-'} {o.phone ? `(${o.phone})` : ''}
|
||||
</Text>
|
||||
</View>
|
||||
<View className="text-sm text-gray-700 mt-1">
|
||||
<Text className="text-gray-500">预约配送:</Text>
|
||||
<Text>{o.sendTime ? dayjs(o.sendTime).format('YYYY-MM-DD HH:mm') : '-'}</Text>
|
||||
</View>
|
||||
<View className="text-sm text-gray-700 mt-1">
|
||||
<Text className="text-gray-500">数量:</Text>
|
||||
<Text>{qty || '-'}</Text>
|
||||
<Text className="text-gray-500 ml-3">门店:</Text>
|
||||
<Text>{o.storeName || '-'}</Text>
|
||||
</View>
|
||||
{remark ? (
|
||||
<View className="text-sm text-gray-700 mt-1">
|
||||
<Text className="text-gray-500">备注:</Text>
|
||||
<Text>{remark}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{o.sendStartTime ? (
|
||||
<View className="text-sm text-gray-700 mt-1">
|
||||
<Text className="text-gray-500">开始配送:</Text>
|
||||
<Text>{dayjs(o.sendStartTime).format('YYYY-MM-DD HH:mm')}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{o.sendEndTime ? (
|
||||
<View className="text-sm text-gray-700 mt-1">
|
||||
<Text className="text-gray-500">送达时间:</Text>
|
||||
<Text>{dayjs(o.sendEndTime).format('YYYY-MM-DD HH:mm')}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{o.receiveConfirmTime ? (
|
||||
<View className="text-sm text-gray-700 mt-1">
|
||||
<Text className="text-gray-500">确认收货:</Text>
|
||||
<Text>{dayjs(o.receiveConfirmTime).format('YYYY-MM-DD HH:mm')}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{o.sendEndImg ? (
|
||||
<View className="text-sm text-gray-700 mt-2">
|
||||
<Text className="text-gray-500">送达照片:</Text>
|
||||
<View className="mt-2">
|
||||
<Image src={o.sendEndImg} width="100%" height="120" />
|
||||
</View>
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
|
||||
{/* 配送流程 */}
|
||||
<View className="mt-3 bg-gray-50 rounded-lg p-2 text-xs">
|
||||
<Text className="text-gray-600">流程:</Text>
|
||||
<Text className={flow1Done ? 'text-green-600 font-medium' : 'text-gray-400'}>1 派单</Text>
|
||||
<Text className="mx-1 text-gray-400">{'>'}</Text>
|
||||
<Text className={flow2Done ? 'text-blue-600 font-medium' : 'text-gray-400'}>2 配送中</Text>
|
||||
<Text className="mx-1 text-gray-400">{'>'}</Text>
|
||||
<Text className={flow3Done ? 'text-purple-600 font-medium' : 'text-gray-400'}>3 送达留档</Text>
|
||||
<Text className="mx-1 text-gray-400">{'>'}</Text>
|
||||
<Text className={flow4Done ? 'text-green-600 font-medium' : 'text-gray-400'}>4 客户确认收货</Text>
|
||||
</View>
|
||||
|
||||
<View className="mt-3 flex justify-end">
|
||||
<Space>
|
||||
{!!phoneToCall && (
|
||||
<Button
|
||||
size="small"
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
Taro.makePhoneCall({ phoneNumber: phoneToCall })
|
||||
}}
|
||||
>
|
||||
联系客户
|
||||
</Button>
|
||||
)}
|
||||
{canStartDeliver(o) && (
|
||||
<Button
|
||||
size="small"
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
void handleStartDeliver(o)
|
||||
}}
|
||||
>
|
||||
开始配送
|
||||
</Button>
|
||||
)}
|
||||
{canConfirmDelivered(o) && (
|
||||
<Button
|
||||
size="small"
|
||||
type="primary"
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
openDeliverDialog(o)
|
||||
}}
|
||||
>
|
||||
确认送达
|
||||
</Button>
|
||||
)}
|
||||
</Space>
|
||||
</View>
|
||||
</View>
|
||||
</Cell>
|
||||
)
|
||||
})}
|
||||
</CellGroup>
|
||||
</InfiniteLoading>
|
||||
)}
|
||||
|
||||
<InfiniteLoading
|
||||
hasMore={hasMore}
|
||||
onLoadMore={() => reload(false)}
|
||||
loadingText={
|
||||
<View className="flex justify-center items-center py-4">
|
||||
<Loading />
|
||||
<View className="ml-2">加载中...</View>
|
||||
</View>
|
||||
}
|
||||
loadMoreText={
|
||||
<View className="text-center py-4 text-gray-500">
|
||||
{list.length === 0 ? '暂无数据' : '没有更多了'}
|
||||
</View>
|
||||
}
|
||||
/>
|
||||
</PullToRefresh>
|
||||
</View>
|
||||
|
||||
<Dialog
|
||||
title="确认送达"
|
||||
visible={deliverDialogVisible}
|
||||
confirmText={deliverSubmitting ? '提交中...' : '确认送达'}
|
||||
cancelText="取消"
|
||||
onConfirm={handleConfirmDelivered}
|
||||
onCancel={() => {
|
||||
if (deliverSubmitting) return
|
||||
setDeliverDialogVisible(false)
|
||||
setDeliverOrder(null)
|
||||
setDeliverImg(undefined)
|
||||
}}
|
||||
>
|
||||
<View className="text-sm text-gray-700">
|
||||
<View>到达收货点后,可拍照留档(推荐/可设为必填),再点确认送达。</View>
|
||||
<View className="mt-3">
|
||||
<Button size="small" onClick={handleChooseDeliverImg}>
|
||||
{deliverImg ? '重新拍照/上传' : '拍照/上传'}
|
||||
</Button>
|
||||
</View>
|
||||
{deliverImg && (
|
||||
<View className="mt-3">
|
||||
<Image src={deliverImg} width="100%" height="120" />
|
||||
<View className="mt-2 flex justify-end">
|
||||
<Button size="small" onClick={() => setDeliverImg(undefined)}>
|
||||
移除照片
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
<View className="mt-3 text-xs text-gray-500">
|
||||
送达后订单进入“待客户确认”;客户在用户端确认收货或超时自动确认(需后端支持)。
|
||||
</View>
|
||||
</View>
|
||||
</Dialog>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user