Files
dukang/apps/h5-partner/src/pages/ProxyOrderListPage.tsx
T

150 lines
5.5 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, useEffect, useState, type FormEvent } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import PageHeader from '@dukang/shared-ui/PageHeader';
import PullToRefresh from '@dukang/shared-ui/PullToRefresh';
import type { PartnerProxyOrderListItem, PartnerProxyOrderListResponse } from '@dukang/shared-types';
import { isLoggedIn, request } from '../lib/api';
import {
proxyOrderStatusColor,
proxyOrderStatusLabel,
} from '../lib/proxyOrderStatus';
function fmtMoney(n: number) {
return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
function fmtTime(value: string | undefined) {
if (!value) return '—';
const d = new Date(value);
if (Number.isNaN(d.getTime())) return value;
const pad = (n: number) => String(n).padStart(2, '0');
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
}
function deliveryLabel(item: PartnerProxyOrderListItem) {
const t = String(item.deliveryType || '').toUpperCase();
if (t === 'ON_SITE_PICKUP') return '现场提货';
if (t === 'CROSS_CITY') return '跨城配送';
if (t === 'LOCAL') return '同城配送';
return '线下代下单';
}
function coverUrl(item: PartnerProxyOrderListItem) {
return item.imageResource?.url || '';
}
export default function ProxyOrderListPage() {
const navigate = useNavigate();
const [list, setList] = useState<PartnerProxyOrderListItem[]>([]);
const [total, setTotal] = useState(0);
const [keyword, setKeyword] = useState('');
const [q, setQ] = useState('');
const [loading, setLoading] = useState(true);
const loadList = useCallback(() => {
if (!isLoggedIn()) {
navigate('/login');
return Promise.resolve();
}
setLoading(true);
const params = new URLSearchParams({ page: '1', pageSize: '50' });
if (q.trim()) params.set('keyword', q.trim());
return request<PartnerProxyOrderListResponse>('PARTNER_H5', `/partner/proxy-orders?${params}`)
.then((res) => {
setList(Array.isArray(res.list) ? res.list : []);
setTotal(Number(res.total) || 0);
})
.catch(() => {
setList([]);
setTotal(0);
})
.finally(() => setLoading(false));
}, [navigate, q]);
useEffect(() => {
document.title = '代下单列表';
}, []);
useEffect(() => {
void loadList();
}, [loadList]);
function submitSearch(e: FormEvent) {
e.preventDefault();
setQ(keyword.trim());
}
return (
<PullToRefresh onRefresh={loadList} className="page-no-tab partner-orders-page">
<PageHeader title="代下单列表" onBack={() => navigate('/center')} />
<div style={{ padding: '0 20px 12px' }}>
<form className="partner-search" onSubmit={submitSearch}>
<span className="material-symbols-outlined">search</span>
<input
placeholder="订单号 / 手机号 / 姓名 / 商品"
value={keyword}
onChange={(e) => setKeyword(e.target.value)}
/>
</form>
<p className="label-md text-muted" style={{ marginTop: 8 }}>
{loading ? '加载中…' : `共 ${total} 笔代下单`}
</p>
</div>
<div style={{ padding: '0 16px 24px' }}>
{!loading && list.length === 0 && <div className="empty">暂无代下单记录</div>}
{list.map((o) => {
const orderId = String(o.id);
const img = coverUrl(o);
return (
<Link key={orderId} to={`/center/proxy-orders/${orderId}`} className="partner-order-card" style={{ marginBottom: 12 }}>
<div className="partner-order-card-top">
<span className="label-md text-muted">NO. {o.orderNo}</span>
<span
className="label-md"
style={{ color: proxyOrderStatusColor(o.status), fontWeight: 600 }}
>
{proxyOrderStatusLabel(o.status)}
</span>
</div>
<div className="partner-order-product">
<div
className="partner-order-product-img"
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
overflow: 'hidden',
background: img ? `center/cover no-repeat url(${img})` : undefined,
}}
>
{!img && <span className="material-symbols-outlined text-muted">liquor</span>}
</div>
<div style={{ flex: 1, minWidth: 0 }}>
<h3 className="headline-md line-2-clamp">{o.productName || '杜康好酒'}</h3>
<p className="text-variant body-md" style={{ marginTop: 4 }}>
×{o.quantity} · ¥{fmtMoney(Number(o.payAmount || 0))}
</p>
<p className="label-md text-muted" style={{ marginTop: 4 }}>
{deliveryLabel(o)} · {fmtTime(o.createdAt)}
</p>
</div>
</div>
<div className="partner-order-address">
<span className="material-symbols-outlined" style={{ fontSize: 18 }}>person</span>
<p className="line-2-clamp">
{o.receiverName || '客户'}
{o.receiverPhone ? ` · ${o.receiverPhone}` : ''}
{o.receiverAddress ? ` · ${o.receiverAddress}` : ''}
</p>
</div>
</Link>
);
})}
</div>
</PullToRefresh>
);
}