用户端跨城订单界面优化
CI / verify (pull_request) Has been cancelled

This commit is contained in:
2026-07-17 09:06:53 +08:00
parent e9537ce052
commit 00b52b9aaa
3 changed files with 73 additions and 20 deletions
@@ -42,6 +42,9 @@ type OrderPreview = {
payAmount: number;
benefitAmount: number;
city?: { localMinQty: number; crossMinQty: number };
quantityOk?: boolean;
quantityMessage?: string | null;
minQty?: number;
};
function formatAddress(a: Address) {
@@ -53,7 +56,7 @@ export default function OrderConfirmPage() {
const checkoutCtx = readCheckoutContext(router.params);
const productId = checkoutCtx.productId ?? '';
const forceCross = checkoutCtx.cross === true;
const [quantity, setQuantity] = useState(Math.max(2, Number(checkoutCtx.qty || 2)));
const [quantity, setQuantity] = useState(Math.max(1, Number(checkoutCtx.qty || 2)));
const [addresses, setAddresses] = useState<Address[]>([]);
const [addressId, setAddressId] = useState(checkoutCtx.addressId || '');
const [preview, setPreview] = useState<OrderPreview | null>(null);
@@ -91,7 +94,7 @@ export default function OrderConfirmPage() {
.then((data) => {
if (!cancelled) {
setPreview(data);
setMsg('');
setMsg(data.quantityOk === false ? (data.quantityMessage || '') : '');
}
})
.catch((e) => {
@@ -115,18 +118,14 @@ export default function OrderConfirmPage() {
);
const isCross = forceCross || preview?.deliveryType === 'CROSS_CITY';
const minQty = isCross ? (preview?.city?.crossMinQty ?? 6) : (preview?.city?.localMinQty ?? 2);
const minQty =
preview?.minQty ??
(isCross ? (preview?.city?.crossMinQty ?? 6) : (preview?.city?.localMinQty ?? 2));
const quantityOk = preview ? preview.quantityOk !== false && quantity >= minQty : false;
const canSubmit = !!addressId && !!preview && quantityOk && !loading && !previewLoading;
function updateQuantity(next: number) {
if (next < minQty) {
setMsg(
!isCross
? `同城配送至少购买 ${minQty}`
: `跨城配送至少购买 ${minQty} 瓶(1箱)`,
);
return;
}
setMsg('');
if (next < 1) return;
setQuantity(next);
}
@@ -158,8 +157,18 @@ export default function OrderConfirmPage() {
}
async function submit() {
if (!addressId) {
setMsg('请选择收货地址');
if (!canSubmit) {
if (!addressId) {
setMsg('请选择收货地址');
return;
}
if (!quantityOk) {
setMsg(
isCross
? `跨城配送至少购买 ${minQty} 瓶(1箱)`
: `同城配送至少购买 ${minQty}`,
);
}
return;
}
@@ -206,6 +215,13 @@ export default function OrderConfirmPage() {
}
const productImage = preview?.product ? getProductMainImage(preview.product) : '';
const submitLabel = loading
? '提交中…'
: !addressId
? '请选择地址'
: !quantityOk
? `至少购买 ${minQty}`
: '提交订单';
return (
<PageShell variant="sub" className="order-confirm-page" hasFixedFooter>
@@ -241,7 +257,8 @@ export default function OrderConfirmPage() {
{isCross ? (
<View className="order-card">
<Text className="u-muted">
{quantity < minQty ? `;跨城至少购买 ${minQty} 瓶(1箱)` : ''}
</Text>
</View>
) : null}
@@ -269,7 +286,7 @@ export default function OrderConfirmPage() {
<Text></Text>
<View className="order-qty-controls">
<View
className="order-qty-btn"
className={`order-qty-btn${quantity <= 1 ? ' order-qty-btn--disabled' : ''}`}
onClick={() => updateQuantity(quantity - 1)}
>
<Text></Text>
@@ -283,6 +300,13 @@ export default function OrderConfirmPage() {
</View>
</View>
</View>
{!quantityOk ? (
<Text className="order-qty-hint">
{isCross
? `跨城配送至少购买 ${minQty} 瓶(1箱),请调整数量`
: `同城配送至少购买 ${minQty} 瓶,请调整数量`}
</Text>
) : null}
</View>
<View className="order-card">
@@ -320,10 +344,13 @@ export default function OrderConfirmPage() {
</Text>
</View>
<View
className="order-confirm-submit"
onClick={() => !loading && void submit()}
className={`order-confirm-submit${canSubmit ? '' : ' order-confirm-submit--disabled'}`}
onClick={() => {
if (!canSubmit) return;
void submit();
}}
>
<Text>{loading ? '提交中…' : !addressId ? '请选择地址' : '提交订单'}</Text>
<Text>{submitLabel}</Text>
</View>
</View>
</PageShell>
+20
View File
@@ -93,6 +93,11 @@
color: var(--color-on-surface);
}
.order-qty-btn--disabled {
opacity: 0.4;
pointer-events: none;
}
.order-qty-value {
margin: 0 14px;
font-size: 16px;
@@ -101,6 +106,14 @@
text-align: center;
}
.order-qty-hint {
display: block;
margin-top: 10px;
font-size: 13px;
color: var(--color-heritage-red);
line-height: 1.4;
}
.order-row {
display: flex;
justify-content: space-between;
@@ -180,6 +193,13 @@
justify-content: center;
}
.order-confirm-submit--disabled {
background: #c9c5c0;
color: #fff;
opacity: 0.85;
pointer-events: none;
}
.order-tabs {
display: flex;
padding: 0 var(--space-page);