init
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import PageHeader from '@dukang/shared-ui/PageHeader';
|
||||
import { request } from '../lib/api';
|
||||
|
||||
const TIMELINE = [
|
||||
{ key: 'confirm', label: '待确认' },
|
||||
{ key: 'accepted', label: '已接单' },
|
||||
{ key: 'delivering', label: '配送中' },
|
||||
{ key: 'shipping', label: '运输中', desc: '包裹正在送往目的地' },
|
||||
{ key: 'done', label: '已送达' },
|
||||
];
|
||||
|
||||
function statusIndex(status: string) {
|
||||
const s = String(status).toUpperCase();
|
||||
if (s === 'COMPLETED') return 4;
|
||||
if (s.includes('SHIP') || s === 'OUT_WAREHOUSE') return 3;
|
||||
if (s === 'PENDING_RECEIVE') return 3;
|
||||
if (s.includes('DELIVER')) return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
function statusBanner(status: string) {
|
||||
const s = String(status).toUpperCase();
|
||||
if (s.includes('SHIP') || s === 'OUT_WAREHOUSE') return { title: '运输中', desc: '预计今日 18:00 前送达', icon: 'local_shipping' };
|
||||
if (s === 'COMPLETED') return { title: '已完成', desc: '订单已送达', icon: 'check_circle' };
|
||||
if (s.includes('PENDING')) return { title: '待发货', desc: '商家正在备货', icon: 'inventory_2' };
|
||||
return { title: status, desc: '', icon: 'receipt_long' };
|
||||
}
|
||||
|
||||
export default function OrderDetailPage() {
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [order, setOrder] = useState<Record<string, unknown> | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (id) request('PARTNER_H5', `/partner/orders/${id}`).then(setOrder);
|
||||
}, [id]);
|
||||
|
||||
async function advance(status: string) {
|
||||
await request('PARTNER_H5', `/partner/orders/${id}/mock-advance-delivery`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ targetStatus: status }),
|
||||
});
|
||||
if (id) request('PARTNER_H5', `/partner/orders/${id}`).then(setOrder);
|
||||
}
|
||||
|
||||
if (!order) return <div className="empty">加载中...</div>;
|
||||
|
||||
const banner = statusBanner(String(order.status));
|
||||
const currentIdx = statusIndex(String(order.status));
|
||||
const payAmount = Number(order.payAmount || 0);
|
||||
|
||||
return (
|
||||
<div className="partner-order-detail">
|
||||
<PageHeader title="订单详情" onBack={() => navigate('/orders')} />
|
||||
|
||||
<section className="partner-status-banner">
|
||||
<div style={{ position: 'relative', zIndex: 1 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
|
||||
<span className="material-symbols-outlined" style={{ fontVariationSettings: "'FILL' 1" }}>{banner.icon}</span>
|
||||
<h2 className="headline-md" style={{ color: '#fff' }}>{banner.title}</h2>
|
||||
</div>
|
||||
{banner.desc && <p className="body-md" style={{ color: 'rgba(255,255,255,0.9)' }}>{banner.desc}</p>}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="partner-timeline">
|
||||
<div className="partner-timeline-line" />
|
||||
{TIMELINE.map((item, i) => {
|
||||
const done = i < currentIdx;
|
||||
const current = i === currentIdx;
|
||||
const pending = i > currentIdx;
|
||||
return (
|
||||
<div key={item.key} className="partner-timeline-item">
|
||||
<div className={`partner-timeline-dot${done ? ' partner-timeline-dot--done' : ''}${current ? ' partner-timeline-dot--current' : ''}${pending ? ' partner-timeline-dot--pending' : ''}`}>
|
||||
{done && <span className="material-symbols-outlined">check</span>}
|
||||
</div>
|
||||
<div>
|
||||
<p className={current ? 'headline-md text-primary' : 'label-md'} style={{ fontWeight: current ? 700 : 500 }}>{item.label}</p>
|
||||
{item.desc && current && <p className="text-muted body-md" style={{ marginTop: 4 }}>{item.desc}</p>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
|
||||
<section className="partner-detail-section partner-detail-section--accent">
|
||||
<div style={{ display: 'flex', gap: 16 }}>
|
||||
<div className="partner-order-product-img" style={{ width: 96, height: 96, position: 'relative' }}>
|
||||
<div style={{ width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'var(--color-surface-container)' }}>
|
||||
<span className="material-symbols-outlined text-muted" style={{ fontSize: 32 }}>liquor</span>
|
||||
</div>
|
||||
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, background: 'rgba(166,29,36,0.8)', textAlign: 'center', padding: '2px 0' }}>
|
||||
<span className="label-md" style={{ color: '#fff', fontSize: 10 }}>正品保证</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
<h3 className="headline-md">{String(order.productName || '杜康好酒')}</h3>
|
||||
<p className="text-muted body-md" style={{ marginTop: 4 }}>x{Number(order.quantity || 1)}</p>
|
||||
<div style={{ marginTop: 8, display: 'flex', alignItems: 'baseline', gap: 2 }}>
|
||||
<span className="label-md text-primary">¥</span>
|
||||
<span className="amount-lg">{payAmount.toFixed(2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, margin: '0 20px' }}>
|
||||
<div className="partner-detail-section" style={{ margin: 0, borderTop: '2px solid var(--color-heritage-red)' }}>
|
||||
<p className="label-md text-muted" style={{ marginBottom: 8 }}>佣金明细</p>
|
||||
<div className="partner-info-row">
|
||||
<span className="label-md text-muted">订单佣金</span>
|
||||
<span className="text-primary" style={{ fontWeight: 700, fontSize: 12 }}>¥{(payAmount * 0.04).toFixed(2)}</span>
|
||||
</div>
|
||||
<div className="partner-info-row">
|
||||
<span className="label-md text-muted">权益核销</span>
|
||||
<span className="text-primary" style={{ fontWeight: 700, fontSize: 12 }}>¥{(payAmount * 0.04).toFixed(2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="partner-detail-section" style={{ margin: 0, borderTop: '2px solid var(--color-aged-amber)' }}>
|
||||
<p className="label-md text-muted" style={{ marginBottom: 4 }}>赠送好客权益</p>
|
||||
<span className="amount-lg" style={{ color: 'var(--color-aged-amber)' }}>¥{Math.round(payAmount * 0.2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section className="partner-detail-section">
|
||||
<h4 className="headline-md" style={{ marginBottom: 16, display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<span style={{ width: 4, height: 16, background: 'var(--color-heritage-red)', borderRadius: 2 }} />
|
||||
订单信息
|
||||
</h4>
|
||||
<div className="partner-info-row">
|
||||
<span className="text-muted body-md">订单编号</span>
|
||||
<span className="body-md">{String(order.orderNo)}</span>
|
||||
</div>
|
||||
<div className="partner-info-row">
|
||||
<span className="text-muted body-md">订单状态</span>
|
||||
<span className="body-md">{String(order.status)}</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="partner-detail-section">
|
||||
<h4 className="headline-md" style={{ marginBottom: 16, display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<span style={{ width: 4, height: 16, background: 'var(--color-heritage-red)', borderRadius: 2 }} />
|
||||
收货地址
|
||||
</h4>
|
||||
<div style={{ display: 'flex', gap: 12 }}>
|
||||
<span className="material-symbols-outlined text-muted">location_on</span>
|
||||
<div>
|
||||
<p className="headline-md" style={{ fontSize: 16 }}>
|
||||
{String(order.receiverName)} <span className="body-md text-muted" style={{ fontWeight: 400 }}>{String(order.receiverPhone)}</span>
|
||||
</p>
|
||||
<p className="text-muted body-md" style={{ marginTop: 4, lineHeight: 1.5 }}>{String(order.receiverAddress)}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer className="partner-order-footer">
|
||||
<div>
|
||||
<span className="label-md text-muted">佣金合计</span>
|
||||
<p className="headline-md text-primary" style={{ fontWeight: 700 }}>¥{(payAmount * 0.08).toFixed(2)}</p>
|
||||
</div>
|
||||
<button type="button" className="btn btn-outline" style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 24px' }}>
|
||||
<span className="material-symbols-outlined" style={{ fontSize: 18 }}>support_agent</span>
|
||||
联系配送员
|
||||
</button>
|
||||
</footer>
|
||||
|
||||
{import.meta.env.DEV && (
|
||||
<details className="partner-dev-tools">
|
||||
<summary>Dev: Mock 推进配送</summary>
|
||||
{['OUT_WAREHOUSE', 'SHIPPING', 'PENDING_RECEIVE', 'COMPLETED'].map((s) => (
|
||||
<button key={s} type="button" onClick={() => advance(s)}>{s}</button>
|
||||
))}
|
||||
</details>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user