feat(coupon-data): 领券数据看板加领券状态多选筛选(默认全选)

- 筛选卡加状态多选(未完成/完成/失败/中途退出),默认全选=现状不改口径
- status 数组用 paramsSerializer indexes:null 序列化为 status=a&status=b(对齐 FastAPI list[str])

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
guke
2026-07-08 16:01:15 +08:00
parent a560ad1963
commit 25adbec48a
+18 -1
View File
@@ -327,6 +327,8 @@ export default function CouponDataPage() {
const [range, setRange] = useState<[Dayjs, Dayjs]>([dayjs().subtract(6, 'day'), dayjs()]);
const [user, setUser] = useState<string>('');
const [appEnv, setAppEnv] = useState<string>('prod');
// 领券状态多选(方案 A:整视图联动),默认全选四态(= 现状,不改口径)。
const [statuses, setStatuses] = useState<string[]>(['started', 'completed', 'failed', 'abandoned']);
const [granularity, setGranularity] = useState<'day' | 'hour'>('day');
const [sortBy, setSortBy] = useState<'time' | 'elapsed'>('time');
const [limit, setLimit] = useState<number>(100);
@@ -362,11 +364,14 @@ export default function CouponDataPage() {
date_to: to,
user: user.trim() || undefined,
app_env: appEnv,
status: statuses,
granularity: gran,
limit: targetLimit,
offset: (targetPage - 1) * targetLimit,
sort: targetSort,
},
// status 是数组:repeat 无方括号序列化(status=a&status=b),对齐 FastAPI list[str] Query
paramsSerializer: { indexes: null },
});
setData(res.data);
// 并行拉「按券成功率」(独立端点,失败不影响主报表)
@@ -386,7 +391,7 @@ export default function CouponDataPage() {
setLoading(false);
}
},
[range, user, appEnv, granularity, limit, sortBy, message],
[range, user, appEnv, statuses, granularity, limit, sortBy, message],
);
useEffect(() => {
@@ -581,6 +586,18 @@ export default function CouponDataPage() {
]}
/>
</Space>
<Space size={6}>
<Typography.Text type="secondary"></Typography.Text>
<Select
mode="multiple"
value={statuses}
onChange={setStatuses}
style={{ minWidth: 240 }}
maxTagCount="responsive"
placeholder="全部状态"
options={Object.entries(STATUS_TAG).map(([value, t]) => ({ value, label: t.label }))}
/>
</Space>
<Space size={6}>
<Typography.Text type="secondary"></Typography.Text>
<Select