- 优化导入路径,修复 PageParam 类型引用 - 新增 DeliverConfirmMode 类型定义,支持拍照完成和等待客户确认两种模式 - 实现配送确认的双模式功能,支持直接完成和等待确认流程 - 重构订单状态判断逻辑,完善配送流程状态管理 - 新增用户端确认收货功能,支持手动确认收货操作 - 优化订单列表展示,增加票号、取货点、门店电话等详细信息 - 添加地址复制和联系门店功能按钮 - 实现补传照片完成订单功能 - 更新订单流程状态显示,提供更准确的状态标识 - 添加配送确认模式切换的单选框界面 - 优化下单成功后的页面跳转逻辑 - 新增水票配送订单后端接口设计文档
604 lines
24 KiB
TypeScript
604 lines
24 KiB
TypeScript
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||
import Taro, { useDidShow } from '@tarojs/taro'
|
||
import { View, Text } from '@tarojs/components'
|
||
import {
|
||
Tabs,
|
||
TabPane,
|
||
Cell,
|
||
Space,
|
||
Button,
|
||
Dialog,
|
||
Radio,
|
||
RadioGroup,
|
||
Image,
|
||
Empty,
|
||
InfiniteLoading,
|
||
PullToRefresh,
|
||
Loading
|
||
} from '@nutui/nutui-react-taro'
|
||
import dayjs from 'dayjs'
|
||
|
||
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
|
||
|
||
type DeliverConfirmMode = 'photoComplete' | 'waitCustomerConfirm'
|
||
|
||
export default function TicketOrdersPage() {
|
||
const riderId = useMemo(() => {
|
||
const raw = Taro.getStorageSync('UserId')
|
||
const id = Number(raw)
|
||
return Number.isFinite(id) && id > 0 ? id : undefined
|
||
}, [])
|
||
|
||
const pageRef = useRef(1)
|
||
const listRef = useRef<GltTicketOrder[]>([])
|
||
|
||
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 [deliverConfirmMode, setDeliverConfirmMode] = useState<DeliverConfirmMode>('photoComplete')
|
||
|
||
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
|
||
if (order.sendEndTime) return false
|
||
|
||
// 只允许在“配送中”阶段确认送达
|
||
if (typeof order.deliveryStatus === 'number') return order.deliveryStatus === 20
|
||
return !!order.sendStartTime
|
||
}
|
||
|
||
const canCompleteByPhoto = (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,
|
||
riderId,
|
||
deliveryStatus: currentTab?.deliveryStatus
|
||
}
|
||
|
||
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 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, opts?: { mode?: DeliverConfirmMode }) => {
|
||
setDeliverOrder(order)
|
||
setDeliverImg(order.sendEndImg)
|
||
setDeliverConfirmMode(opts?.mode || (order.sendEndImg ? 'photoComplete' : 'waitCustomerConfirm'))
|
||
setDeliverDialogVisible(true)
|
||
}
|
||
|
||
const handleChooseDeliverImg = async () => {
|
||
try {
|
||
const file = await uploadFile()
|
||
setDeliverImg(file?.url)
|
||
} catch (e) {
|
||
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
|
||
if (deliverConfirmMode === 'photoComplete' && !deliverImg) {
|
||
Taro.showToast({ title: '请先拍照/上传送达照片', icon: 'none' })
|
||
return
|
||
}
|
||
setDeliverSubmitting(true)
|
||
try {
|
||
const now = dayjs().format('YYYY-MM-DD HH:mm:ss')
|
||
// 送达时间:首次“确认送达”写入;补传照片时不要覆盖原送达时间
|
||
const deliveredAt = deliverOrder.sendEndTime || now
|
||
// 说明:
|
||
// - waitCustomerConfirm:只标记“已送达”,进入待客户确认(客户点击确认收货后完成)
|
||
// - photoComplete:拍照留档后可直接完成(由后端策略决定是否允许)
|
||
const payload: GltTicketOrder =
|
||
deliverConfirmMode === 'photoComplete'
|
||
? {
|
||
id: deliverOrder.id,
|
||
deliveryStatus: 40,
|
||
sendEndTime: deliveredAt,
|
||
sendEndImg: deliverImg,
|
||
receiveConfirmTime: now,
|
||
receiveConfirmType: 20
|
||
}
|
||
: {
|
||
id: deliverOrder.id,
|
||
deliveryStatus: 30,
|
||
sendEndTime: deliveredAt,
|
||
sendEndImg: deliverImg
|
||
}
|
||
|
||
await updateGltTicketOrder(payload)
|
||
Taro.showToast({ title: '已确认送达', icon: 'success' })
|
||
setDeliverDialogVisible(false)
|
||
setDeliverOrder(null)
|
||
setDeliverImg(undefined)
|
||
setDeliverConfirmMode('photoComplete')
|
||
pageRef.current = 1
|
||
await reload(true)
|
||
} catch (e) {
|
||
console.error('确认送达失败:', e)
|
||
Taro.showToast({ title: '确认送达失败', icon: 'none' })
|
||
} finally {
|
||
setDeliverSubmitting(false)
|
||
}
|
||
}
|
||
|
||
useEffect(() => {
|
||
listRef.current = list
|
||
}, [list])
|
||
|
||
useDidShow(() => {
|
||
pageRef.current = 1
|
||
listRef.current = []
|
||
setList([])
|
||
setHasMore(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 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">
|
||
<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>
|
||
) : (
|
||
<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 || o.comments || ''
|
||
const ticketNo = o.userTicketId || '-'
|
||
|
||
const flow1Done = !!o.riderId
|
||
const flow2Done =
|
||
!!o.sendStartTime || (typeof o.deliveryStatus === 'number' && o.deliveryStatus >= 20)
|
||
const flow3Done =
|
||
!!o.sendEndTime || (typeof o.deliveryStatus === 'number' && o.deliveryStatus >= 30)
|
||
const flow4Done = !!o.receiveConfirmTime || o.deliveryStatus === 40
|
||
|
||
const phoneToCall = o.phone
|
||
const storePhone = o.storePhone
|
||
const pickupName = o.warehouseName || o.storeName
|
||
const pickupAddr = o.warehouseAddress || o.storeAddress
|
||
|
||
return (
|
||
<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>
|
||
|
||
<View className="text-gray-400 text-xs mt-1">下单时间:{timeText}</View>
|
||
<View className="text-gray-400 text-xs mt-1">票号:{ticketNo}</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>{pickupName || '-'}</Text>
|
||
</View>
|
||
{pickupAddr ? (
|
||
<View className="text-sm text-gray-700 mt-1">
|
||
<Text className="text-gray-500">取货地址:</Text>
|
||
<Text>{pickupAddr}</Text>
|
||
</View>
|
||
) : null}
|
||
<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>
|
||
{o.storePhone ? (
|
||
<View className="text-sm text-gray-700 mt-1">
|
||
<Text className="text-gray-500">门店电话:</Text>
|
||
<Text>{o.storePhone}</Text>
|
||
</View>
|
||
) : null}
|
||
{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>
|
||
)}
|
||
{!!addr && addr !== '-' && (
|
||
<Button
|
||
size="small"
|
||
onClick={e => {
|
||
e.stopPropagation()
|
||
void Taro.setClipboardData({ data: addr })
|
||
Taro.showToast({ title: '地址已复制', icon: 'none' })
|
||
}}
|
||
>
|
||
复制地址
|
||
</Button>
|
||
)}
|
||
{!!storePhone && (
|
||
<Button
|
||
size="small"
|
||
onClick={e => {
|
||
e.stopPropagation()
|
||
Taro.makePhoneCall({ phoneNumber: storePhone })
|
||
}}
|
||
>
|
||
联系门店
|
||
</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, { mode: 'waitCustomerConfirm' })
|
||
}}
|
||
>
|
||
确认送达
|
||
</Button>
|
||
)}
|
||
{canCompleteByPhoto(o) && (
|
||
<Button
|
||
size="small"
|
||
type="primary"
|
||
onClick={e => {
|
||
e.stopPropagation()
|
||
openDeliverDialog(o, { mode: 'photoComplete' })
|
||
}}
|
||
>
|
||
补传照片完成
|
||
</Button>
|
||
)}
|
||
</Space>
|
||
</View>
|
||
</View>
|
||
</Cell>
|
||
)
|
||
})}
|
||
</InfiniteLoading>
|
||
)}
|
||
</PullToRefresh>
|
||
</View>
|
||
|
||
<Dialog
|
||
title="确认送达"
|
||
visible={deliverDialogVisible}
|
||
confirmText={
|
||
deliverSubmitting
|
||
? '提交中...'
|
||
: deliverConfirmMode === 'photoComplete'
|
||
? '拍照完成'
|
||
: '确认送达'
|
||
}
|
||
cancelText="取消"
|
||
onConfirm={handleConfirmDelivered}
|
||
onCancel={() => {
|
||
if (deliverSubmitting) return
|
||
setDeliverDialogVisible(false)
|
||
setDeliverOrder(null)
|
||
setDeliverImg(undefined)
|
||
setDeliverConfirmMode('photoComplete')
|
||
}}
|
||
>
|
||
<View className="text-sm text-gray-700">
|
||
<View>到达收货点后,可选择“拍照留档直接完成”或“等待客户确认收货”。</View>
|
||
|
||
<View className="mt-3">
|
||
<RadioGroup value={deliverConfirmMode} onChange={v => setDeliverConfirmMode(v as DeliverConfirmMode)}>
|
||
<Radio value="photoComplete">拍照留档(直接完成)</Radio>
|
||
<Radio value="waitCustomerConfirm">客户确认收货(可不拍照)</Radio>
|
||
</RadioGroup>
|
||
</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>
|
||
)
|
||
}
|