Files
dukang/apps/mini-user/src/pages/pickup-receive/index.tsx
T
jacy cebeefdb22
CI / verify (pull_request) Has been cancelled
feat(trade): add on-site pickup order flow
Product flag, ON_SITE_PICKUP delivery, mini confirm/receive pages; pay skips warehouse auto-advance.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 01:17:59 +08:00

138 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useCallback, useState } from 'react';
import { View, Text, Image } from '@tarojs/components';
import Taro, { useDidShow, useRouter } from '@tarojs/taro';
import PageShell from '../../components/PageShell';
import SubPageHeader from '../../components/SubPageHeader';
import { request, toast } from '../../lib/api';
import { getProductMainImage } from '../../lib/product-images';
type OrderDetail = {
id: string;
orderNo?: string;
status?: string;
payAmount?: number | string;
productName?: string;
productSpec?: string;
quantity?: number;
product?: {
name?: string;
spec?: string;
mainImageUrl?: string | null;
carouselUrls?: string[] | null;
};
imageUrl?: string | null;
mainImageUrl?: string | null;
};
export default function PickupReceivePage() {
const router = useRouter();
const orderId = router.params.id ?? router.params.orderId ?? '';
const [order, setOrder] = useState<OrderDetail | null>(null);
const [loading, setLoading] = useState(false);
const [submitting, setSubmitting] = useState(false);
const load = useCallback(() => {
if (!orderId) return;
setLoading(true);
request<OrderDetail>(`/trade/orders/${orderId}`)
.then((data) => setOrder(data))
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'))
.finally(() => setLoading(false));
}, [orderId]);
useDidShow(() => {
load();
});
async function confirmReceive() {
if (!orderId || submitting) return;
setSubmitting(true);
try {
await request(`/trade/orders/${orderId}/confirm-receive`, {
method: 'POST',
data: {},
});
toast('确认收货成功', 'success');
setTimeout(() => {
Taro.redirectTo({ url: '/pages/orders/index?tab=done' });
}, 500);
} catch (e) {
toast(e instanceof Error ? e.message : '确认失败');
} finally {
setSubmitting(false);
}
}
const name = order?.productName || order?.product?.name || '商品';
const spec = order?.productSpec || order?.product?.spec;
const image =
order?.mainImageUrl ||
order?.imageUrl ||
(order?.product ? getProductMainImage(order.product) : '') ||
'';
const amount = Number(order?.payAmount ?? 0);
const canConfirm = order?.status === 'PENDING_RECEIVE' || order?.status === 'DELIVERED';
return (
<PageShell variant="sub" className="order-confirm-page" hasFixedFooter>
<SubPageHeader title="确认收货" />
<View className="sub-page-body">
<View className="order-card">
<Text className="order-card-title">现场取货</Text>
<Text className="u-muted">请确认已在现场拿到商品后再点击确认收货</Text>
</View>
{loading && !order ? (
<View className="order-card">
<Text className="u-muted">加载中…</Text>
</View>
) : null}
{order ? (
<>
<View className="order-card">
<View className="order-row">
<Text className="order-row-label">订单号</Text>
<Text className="order-row-value">{order.orderNo || '—'}</Text>
</View>
<View className="order-product-row" style={{ marginTop: 12 }}>
<View className="order-product-thumb">
{image ? (
<Image className="order-product-thumb-img" src={image} mode="aspectFill" />
) : null}
</View>
<View style={{ flex: 1 }}>
<Text className="order-product-name">{name}</Text>
{spec ? <Text className="u-muted">{spec}</Text> : null}
<Text className="u-muted">×{order.quantity ?? 1}</Text>
</View>
</View>
</View>
<View className="order-card">
<View className="order-row">
<Text className="order-row-label">实付金额</Text>
<Text className="order-row-value order-pay-amount">
¥{Number.isFinite(amount) ? amount.toFixed(2) : '—'}
</Text>
</View>
</View>
</>
) : null}
</View>
<View className="pay-bar">
<View
className="order-confirm-submit"
style={{ flex: 1, opacity: canConfirm && !submitting ? 1 : 0.6 }}
onClick={() => {
if (!canConfirm || submitting) return;
void confirmReceive();
}}
>
<Text>{submitting ? '提交中…' : canConfirm ? '确认收货' : '订单状态不可确认'}</Text>
</View>
</View>
</PageShell>
);
}