feat(admin-web): widen benefit coupon detail and enrich redeem record drawer (v3.4.13)

Share redeem detail fields across benefit coupon and redeem records pages;
widen coupon drawer to avoid horizontal scroll.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-06 00:27:11 +08:00
parent a346fae7a4
commit 3ef4432b2f
5 changed files with 131 additions and 124 deletions
+13 -82
View File
@@ -18,6 +18,7 @@ import type { ColumnsType } from 'antd/es/table';
import type { AdminBenefitGrantRequest } from '@dukang/shared-types';
import { request } from '../lib/api';
import { COUPON_STATUS_LABELS, fmtTime } from '../lib/constants';
import RedeemRecordDetailDescriptions from '../components/RedeemRecordDetailDescriptions';
import { useAdminList } from '../lib/useAdminList';
type Row = {
@@ -242,7 +243,8 @@ export default function BenefitCouponsPage() {
<Drawer
title="权益券详情"
width={720}
width={980}
styles={{ body: { paddingBottom: 24 } }}
open={drawerOpen}
onClose={() => setDrawerOpen(false)}
extra={
@@ -310,14 +312,15 @@ export default function BenefitCouponsPage() {
size="small"
rowKey="id"
pagination={false}
tableLayout="fixed"
locale={{ emptyText: '暂无关联核销单' }}
dataSource={detail.redeemRecords ?? []}
columns={[
{ title: '核销号', dataIndex: 'redeemNo', width: 160, ellipsis: true },
{ title: '核销号', dataIndex: 'redeemNo', ellipsis: true },
{
title: '角色',
dataIndex: 'role',
width: 70,
width: 72,
render: (v: string | undefined) =>
v === 'SECONDARY' ? <Tag color="orange"></Tag> : <Tag color="blue"></Tag>,
},
@@ -331,31 +334,31 @@ export default function BenefitCouponsPage() {
{
title: '本券分摊',
dataIndex: 'couponAmount',
width: 95,
width: 96,
render: (v: number | undefined, row: CouponRedeemRecord) =>
`¥${Number(v ?? row.amount).toFixed(2)}`,
},
{
title: '核销总额',
dataIndex: 'amount',
width: 90,
width: 96,
render: (v: number) => `¥${Number(v).toFixed(2)}`,
},
{
title: '结算额',
dataIndex: 'settleAmount',
width: 90,
width: 96,
render: (v: number) => `¥${Number(v).toFixed(2)}`,
},
{
title: '时间',
dataIndex: 'createdAt',
width: 150,
width: 148,
render: (v: string) => fmtTime(v),
},
{
title: '操作',
width: 70,
width: 64,
render: (_: unknown, row: CouponRedeemRecord) => (
<Button type="link" size="small" onClick={() => void openRedeemDetail(row.id)}>
@@ -374,7 +377,7 @@ export default function BenefitCouponsPage() {
<Drawer
title="核销单详情"
width={520}
width={640}
open={redeemDrawerOpen}
onClose={() => {
setRedeemDrawerOpen(false);
@@ -385,79 +388,7 @@ export default function BenefitCouponsPage() {
{redeemDetailLoading ? (
<Typography.Text type="secondary"></Typography.Text>
) : redeemDetail ? (
<Descriptions column={1} bordered size="small">
<Descriptions.Item label="核销号">{String(redeemDetail.redeemNo ?? '—')}</Descriptions.Item>
<Descriptions.Item label="核销额">
¥{Number(redeemDetail.amount ?? 0).toFixed(2)}
</Descriptions.Item>
<Descriptions.Item label="结算额">
¥{Number(redeemDetail.settleAmount ?? 0).toFixed(2)}
</Descriptions.Item>
<Descriptions.Item label="时间">{fmtTime(String(redeemDetail.createdAt ?? ''))}</Descriptions.Item>
<Descriptions.Item label="用户">
{String((redeemDetail.user as { userNo?: string } | undefined)?.userNo ?? '—')}
{(redeemDetail.user as { phone?: string | null } | undefined)?.phone
? ` / ${(redeemDetail.user as { phone?: string | null }).phone}`
: ''}
</Descriptions.Item>
<Descriptions.Item label="门店">
{String((redeemDetail.store as { name?: string } | undefined)?.name ?? '—')}
{(redeemDetail.store as { cityName?: string } | undefined)?.cityName
? `${(redeemDetail.store as { cityName?: string }).cityName}`
: ''}
</Descriptions.Item>
<Descriptions.Item label="门店地址">
{String((redeemDetail.store as { address?: string } | undefined)?.address ?? '—')}
</Descriptions.Item>
<Descriptions.Item label="合伙人">
{String(
(redeemDetail.store as { partnerAccount?: { companyName?: string } } | undefined)
?.partnerAccount?.companyName ?? '—',
)}
</Descriptions.Item>
<Descriptions.Item label="权益券号">
{String((redeemDetail.coupon as { couponNo?: string } | undefined)?.couponNo ?? '—')}
</Descriptions.Item>
<Descriptions.Item label="关联订单">
{String(
(redeemDetail.coupon as { order?: { orderNo?: string } } | undefined)?.order?.orderNo ??
'—',
)}
</Descriptions.Item>
{Array.isArray(redeemDetail.allocations) &&
(redeemDetail.allocations as unknown[]).length > 0 ? (
<Descriptions.Item label="券分摊">
{(
redeemDetail.allocations as Array<{
couponNo?: string;
orderNo?: string | null;
amount?: number;
sortOrder?: number;
}>
)
.map((a, idx) => {
const role = idx === 0 ? '主' : '次';
return `${role} ${a.couponNo ?? '—'}¥${Number(a.amount ?? 0).toFixed(2)}${
a.orderNo ? `(订单 ${a.orderNo}` : ''
}`;
})
.join('')}
</Descriptions.Item>
) : null}
{redeemDetail.payout ? (
<Descriptions.Item label="门店结算单">
¥{Number((redeemDetail.payout as { settleAmount?: number }).settleAmount ?? 0).toFixed(2)}
{' / '}
{String((redeemDetail.payout as { status?: string }).status ?? '—')}
</Descriptions.Item>
) : null}
{redeemDetail.rating ? (
<Descriptions.Item label="评价">
{(redeemDetail.rating as { serviceScore?: number }).serviceScore ?? '—'} / {' '}
{(redeemDetail.rating as { envScore?: number }).envScore ?? '—'}
</Descriptions.Item>
) : null}
</Descriptions>
<RedeemRecordDetailDescriptions detail={redeemDetail} />
) : null}
</Drawer>
</div>