89fd333702
Add client-logging SDK, expanded event taxonomy, API observability, admin domain events UI, and move SENTRY_DSN to HQ system settings with @sentry/node bootstrap after config preload. Co-authored-by: Cursor <cursoragent@cursor.com>
116 lines
4.3 KiB
TypeScript
116 lines
4.3 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { Link, useNavigate, useSearchParams } from 'react-router-dom';
|
|
import PageHeader from '@dukang/shared-ui/PageHeader';
|
|
import AppImage from '@dukang/shared-ui/AppImage';
|
|
import OrderStatusTabs from '@dukang/shared-ui/OrderStatusTabs';
|
|
import { request } from '../lib/api';
|
|
import { usePageView } from '../lib/usePageView';
|
|
|
|
const TABS = [
|
|
{ key: 'all', label: '全部' },
|
|
{ key: 'pending_pay', label: '待付款' },
|
|
{ key: 'paid', label: '已付款' },
|
|
{ key: 'completed', label: '已完成' },
|
|
];
|
|
|
|
const STATUS_LABEL: Record<string, string> = {
|
|
PENDING_PAY: '待付款',
|
|
PENDING_SHIP: '待发货',
|
|
OUT_WAREHOUSE: '已出库',
|
|
SHIPPING: '配送中',
|
|
PENDING_RECEIVE: '待收货',
|
|
COMPLETED: '已完成',
|
|
CANCELLED: '已取消',
|
|
REFUNDING: '退款中',
|
|
REFUNDED: '已退款',
|
|
};
|
|
|
|
function isReshipOrder(order: Record<string, unknown>) {
|
|
return String(order.orderType) === 'RESHIPMENT';
|
|
}
|
|
|
|
function orderStatusLabel(order: Record<string, unknown>) {
|
|
if (isReshipOrder(order)) return '补发中';
|
|
return STATUS_LABEL[String(order.status)] || String(order.status);
|
|
}
|
|
|
|
export default function OrderListPage() {
|
|
const [params, setParams] = useSearchParams();
|
|
const tab = params.get('tab') || 'all';
|
|
usePageView('order_list_view', { tab });
|
|
const [data, setData] = useState<{ list: Array<Record<string, unknown>> }>({ list: [] });
|
|
const navigate = useNavigate();
|
|
|
|
useEffect(() => {
|
|
request<{ list: Array<Record<string, unknown>> }>('USER_H5', `/trade/orders?tab=${tab}`).then(setData);
|
|
}, [tab]);
|
|
|
|
return (
|
|
<div className="page-no-tab">
|
|
<PageHeader title="我的订单" onBack={() => navigate('/mine')} />
|
|
<OrderStatusTabs tabs={TABS} active={tab} onChange={(key) => setParams({ tab: key })} />
|
|
{data.list.length === 0 && <div className="empty">暂无订单</div>}
|
|
{data.list.map((o) => {
|
|
const items = (o.items as Array<Record<string, unknown>>) || [];
|
|
const item = items[0];
|
|
const isReship = isReshipOrder(o);
|
|
const isProxy = String(o.orderType) === 'PROXY' || o.isProxyOrder === true;
|
|
const isPendingPay = String(o.status) === 'PENDING_PAY';
|
|
return (
|
|
<div key={String(o.id)} className="card">
|
|
<div className="card-row" style={{ marginBottom: 8 }}>
|
|
<span className="label-md text-muted">
|
|
订单号: {String(o.orderNo)}
|
|
{isReship && (
|
|
<span className="tag-reship" style={{ marginLeft: 8 }}>
|
|
补发单
|
|
</span>
|
|
)}
|
|
{isProxy && (
|
|
<span className="tag-reship" style={{ marginLeft: 8 }}>
|
|
代下单
|
|
</span>
|
|
)}
|
|
</span>
|
|
<span className="status-tag">{orderStatusLabel(o)}</span>
|
|
</div>
|
|
{isProxy && o.proxyPartnerName ? (
|
|
<div className="label-md text-muted" style={{ marginBottom: 8 }}>
|
|
由合伙人 {String(o.proxyPartnerName)} 代下
|
|
</div>
|
|
) : null}
|
|
{item && (
|
|
<div className="card-row">
|
|
<AppImage
|
|
src={String(item.productImage)}
|
|
alt={String(item.productName || '')}
|
|
wrapperClassName="order-list-thumb"
|
|
/>
|
|
<div style={{ flex: 1 }}>
|
|
<div className="headline-md">{String(item.productName)}</div>
|
|
<div className="text-muted body-md">{String(item.productSpec)} x{Number(item.quantity)}</div>
|
|
</div>
|
|
<div className="amount-lg">¥{Number(o.payAmount)}</div>
|
|
</div>
|
|
)}
|
|
<div style={{ textAlign: 'right', marginTop: 12, display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
|
|
{isPendingPay && (
|
|
<button
|
|
type="button"
|
|
className="btn btn-primary btn-pill"
|
|
onClick={() => navigate(`/pay?orderId=${o.id}`)}
|
|
>
|
|
去付款
|
|
</button>
|
|
)}
|
|
<Link to={`/orders/${o.id}`} className="btn btn-outline btn-pill">
|
|
查看详情
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|