feat(ops): add HQ admin proxy order and mini-user store session fixes

Align HQ orders page with partner dual-SMS offline proxy flow; improve mini-user stores session and WeChat confirm-receive handling.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-31 09:18:19 +08:00
parent 1a0afb6d39
commit 2cd4e25682
21 changed files with 1438 additions and 143 deletions
+44 -10
View File
@@ -28,6 +28,7 @@ import {
fmtTime,
} from '../lib/constants';
import { FULFILLMENT_HOLD_REASON_LABELS } from '@dukang/shared-types';
import ProxyOrderModal from '../components/ProxyOrderModal';
type ShipDefaults = {
provider: string;
@@ -182,7 +183,9 @@ export default function OrdersPage() {
const [shipTarget, setShipTarget] = useState<OrderDetail | null>(null);
const [shipMode, setShipMode] = useState<ShipMode>('EXPRESS');
const [warehouses, setWarehouses] = useState<WarehouseOption[]>([]);
const [proxyOpen, setProxyOpen] = useState(false);
const canDeleteOrders = (profile?.permissionKeys ?? []).includes('orders_delete');
const canProxyOrder = (profile?.permissionKeys ?? []).includes('orders');
const selectedOrders = useMemo(
() => (data?.items ?? []).filter((row) => selectedRowKeys.includes(row.id)),
@@ -415,6 +418,11 @@ export default function OrdersPage() {
<Space size={4} wrap>
<Tag color={ORDER_STATUS_COLORS[s] || 'default'}>{ORDER_STATUS_LABELS[s] || s}</Tag>
{row.fulfillmentHold ? <Tag color="orange"></Tag> : null}
{row.orderType === 'PROXY' || row.isProxyOrder ? (
<Tag color="purple" title={row.proxyPartnerName || undefined}>
</Tag>
) : null}
</Space>
),
},
@@ -422,7 +430,8 @@ export default function OrdersPage() {
title: '配送',
dataIndex: 'deliveryType',
width: 90,
render: (v) => (v === 'LOCAL' ? '同城' : '跨城'),
render: (v) =>
v === 'ON_SITE_PICKUP' ? '现场提货' : v === 'LOCAL' ? '同城' : '跨城',
},
{ title: '实付', dataIndex: 'payAmount', width: 90, render: (v) => `¥${v}` },
{ title: '收货人', dataIndex: 'receiverName', width: 90 },
@@ -467,15 +476,22 @@ export default function OrdersPage() {
<div>
<Space style={{ marginBottom: 16, width: '100%', justifyContent: 'space-between' }}>
<Typography.Title level={4} style={{ margin: 0 }}></Typography.Title>
{canDeleteOrders ? (
<Button
danger
disabled={!selectedRowKeys.length}
onClick={() => setBatchDeleteOpen(true)}
>
{selectedRowKeys.length ? ` (${selectedRowKeys.length})` : ''}
</Button>
) : null}
<Space>
{canProxyOrder ? (
<Button type="primary" onClick={() => setProxyOpen(true)}>
</Button>
) : null}
{canDeleteOrders ? (
<Button
danger
disabled={!selectedRowKeys.length}
onClick={() => setBatchDeleteOpen(true)}
>
{selectedRowKeys.length ? ` (${selectedRowKeys.length})` : ''}
</Button>
) : null}
</Space>
</Space>
<Form form={form} layout="inline" style={{ marginBottom: 16 }} onFinish={() => { setPage(1); void load(); }}>
<Form.Item name="orderNo" label="订单号">
@@ -588,8 +604,16 @@ export default function OrdersPage() {
'大单待确认'}
</Tag>
) : null}
{detail.orderType === 'PROXY' || detail.isProxyOrder ? (
<Tag color="purple"></Tag>
) : null}
</Space>
</Descriptions.Item>
{detail.orderType === 'PROXY' || detail.isProxyOrder || detail.proxyPartnerName ? (
<Descriptions.Item label="代下单人">
{[detail.proxyPartnerName, detail.proxyPartnerPhone].filter(Boolean).join(' / ') || '—'}
</Descriptions.Item>
) : null}
<Descriptions.Item label="用户">{detail.user?.userNo} / {detail.user?.nickname}</Descriptions.Item>
<Descriptions.Item label="商品额">¥{detail.productAmount}</Descriptions.Item>
<Descriptions.Item label="实付">¥{detail.payAmount}</Descriptions.Item>
@@ -1112,6 +1136,16 @@ export default function OrdersPage() {
]}
/>
</Modal>
<ProxyOrderModal
open={proxyOpen}
onClose={() => setProxyOpen(false)}
onSuccess={(order) => {
setProxyOpen(false);
void load();
void openDetail(order.id);
}}
/>
</div>
);
}