fix: implement session-to-events cross-page navigation
Some checks failed
Deploy Admin Frontend / build-and-deploy (push) Failing after 6s

- Session detail: add "查看关联事件" button linking to /learning/events
- ReadingEventPage: read clientSessionId from URL search params on mount
- ReadingEventPage: add Client Session ID filter input

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
wangdl 2026-06-15 21:47:25 +08:00
parent 37d5a51514
commit 42c3a604ab

View File

@ -16,7 +16,13 @@ function PageWrapper({ title, children }: { title: string; children: React.React
export function ReadingEventPage() { export function ReadingEventPage() {
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [filters, setFilters] = useState<Record<string, string>>({}); const [filters, setFilters] = useState<Record<string, string>>(() => {
const params = new URLSearchParams(window.location.search);
const init: Record<string, string> = {};
const csid = params.get('clientSessionId');
if (csid) init.clientSessionId = csid;
return init;
});
const [detailId, setDetailId] = useState<string | null>(null); const [detailId, setDetailId] = useState<string | null>(null);
const { data, isLoading } = useQuery({ const { data, isLoading } = useQuery({
queryKey: ['admin-events', page, filters], queryKey: ['admin-events', page, filters],
@ -46,6 +52,7 @@ export function ReadingEventPage() {
<Space style={{ marginBottom: 16 }} wrap> <Space style={{ marginBottom: 16 }} wrap>
<Input placeholder="用户ID" allowClear onChange={e => setFilters(f => ({ ...f, userId: e.target.value }))} style={{ width: 140 }} /> <Input placeholder="用户ID" allowClear onChange={e => setFilters(f => ({ ...f, userId: e.target.value }))} style={{ width: 140 }} />
<Input placeholder="资料ID" allowClear onChange={e => setFilters(f => ({ ...f, materialId: e.target.value }))} style={{ width: 140 }} /> <Input placeholder="资料ID" allowClear onChange={e => setFilters(f => ({ ...f, materialId: e.target.value }))} style={{ width: 140 }} />
<Input placeholder="Client Session ID" allowClear onChange={e => setFilters(f => ({ ...f, clientSessionId: e.target.value }))} style={{ width: 170 }} />
<Select placeholder="事件类型" allowClear style={{ width: 130 }} onChange={v => setFilters(f => ({ ...f, eventType: v || '' }))} <Select placeholder="事件类型" allowClear style={{ width: 130 }} onChange={v => setFilters(f => ({ ...f, eventType: v || '' }))}
options={['material_opened','material_closed','position_changed','heartbeat','marked_as_read'].map(t => ({ value: t, label: t }))} /> options={['material_opened','material_closed','position_changed','heartbeat','marked_as_read'].map(t => ({ value: t, label: t }))} />
<Select placeholder="状态" allowClear style={{ width: 110 }} onChange={v => setFilters(f => ({ ...f, status: v || '' }))} <Select placeholder="状态" allowClear style={{ width: 110 }} onChange={v => setFilters(f => ({ ...f, status: v || '' }))}
@ -162,6 +169,11 @@ export function SessionPage() {
<Descriptions.Item label="时长组成">{detail.durationBreakdown || '-'}</Descriptions.Item> <Descriptions.Item label="时长组成">{detail.durationBreakdown || '-'}</Descriptions.Item>
</Descriptions> </Descriptions>
)} )}
{detail?.clientSessionId && (
<div style={{ marginTop: 16, textAlign: 'right' }}>
<Button type="primary" onClick={() => window.location.href = `/learning/events?clientSessionId=${encodeURIComponent(detail.clientSessionId)}`}></Button>
</div>
)}
</Drawer> </Drawer>
</PageWrapper> </PageWrapper>
); );