cebeefdb22
CI / verify (pull_request) Has been cancelled
Product flag, ON_SITE_PICKUP delivery, mini confirm/receive pages; pay skips warehouse auto-advance. Co-authored-by: Cursor <cursoragent@cursor.com>
138 lines
4.6 KiB
TypeScript
138 lines
4.6 KiB
TypeScript
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>
|
||
);
|
||
}
|