fix: implement session-to-events cross-page navigation
Some checks failed
Deploy Admin Frontend / build-and-deploy (push) Failing after 6s
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:
parent
37d5a51514
commit
42c3a604ab
@ -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>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user