fix(web): sync finding traffic bindings between overview and reproduction steps

This commit is contained in:
RuoJi6 committed 2026-10-27 18:18:04 +08:00
1 parent 8ad507e31f
commit 4273ef5d97
3 files changed
+27 -9

No files matched your search

@@ -63,6 +63,7 @@ function FindingDetailInner() {
const [finding, setFinding] = React.useState<Finding | null>(null);
const [loaded, setLoaded] = React.useState(false);
const [tab, setTab] = React.useState("overview");
const [trafficReload, setTrafficReload] = React.useState(0);
const load = React.useCallback(() => {
if (!id) {
@@ -79,6 +80,11 @@ function FindingDetailInner() {
load();
}, [load]);
const handleTrafficChanged = React.useCallback(() => {
setTrafficReload((value) => value + 1);
load();
}, [load]);
const changeSeverity = React.useCallback(
async (next: Severity) => {
if (!finding || finding.inherited || next === finding.severity) return;
@@ -191,7 +197,8 @@ function FindingDetailInner() {
reproduction={finding.reproduction}
contextTask={contextTaskId || undefined}
readOnly={finding.inherited}
onChanged={load}
onChanged={handleTrafficChanged}
trafficReload={trafficReload}
/>
) : null}
<details open={!structuredReproduction} className="group">
@@ -215,7 +222,8 @@ function FindingDetailInner() {
readOnly={finding.inherited}
stepIndex={structuredReproduction ? 0 : undefined}
title={structuredReproduction ? "未归入步骤的流量" : undefined}
onChanged={load}
onChanged={handleTrafficChanged}
trafficReload={trafficReload}
/>
{/* 证据下方:详细报告(Markdown 渲染) */}
<Card>
@@ -43,12 +43,14 @@ export function FindingReproductionSection({
contextTask,
readOnly,
onChanged,
trafficReload = 0,
}: {
findingId: string;
reproduction: Reproduction;
contextTask?: string;
readOnly?: boolean;
onChanged?: () => void;
trafficReload?: number;
}) {
const [traffic, setTraffic] = React.useState<FindingTraffic | null>(null);
const [pickerStep, setPickerStep] = React.useState<number | null>(null);
@@ -59,14 +61,20 @@ export function FindingReproductionSection({
const [editingStepIndex, setEditingStepIndex] = React.useState("0");
const [busy, setBusy] = React.useState(false);
const [reload, setReload] = React.useState(0);
const load = React.useCallback(() => {
React.useEffect(() => {
let active = true;
api
.findingTraffic(findingId, contextTask)
.then(setTraffic)
.catch(() => setTraffic(null));
}, [findingId, contextTask]);
// biome-ignore lint/correctness/useExhaustiveDependencies: retry token intentionally refreshes this request.
React.useEffect(() => load(), [load, reload]);
.then((value) => {
if (active) setTraffic(value);
})
.catch(() => {
if (active) setTraffic(null);
});
return () => {
active = false;
};
}, [findingId, contextTask, reload, trafficReload]);
const steps = reproduction.steps ?? [];
const allBindings = traffic?.bindings ?? [];
+3 -1
View File
@@ -46,6 +46,7 @@ export function FindingTrafficPanel({
onChanged,
stepIndex: filterStepIndex,
title,
trafficReload = 0,
}: {
findingId: string;
contextTask?: string;
@@ -53,6 +54,7 @@ export function FindingTrafficPanel({
onChanged: () => void;
stepIndex?: number;
title?: string;
trafficReload?: number;
}) {
const [data, setData] = React.useState<FindingTraffic | null>(null);
const [error, setError] = React.useState("");
@@ -84,7 +86,7 @@ export function FindingTrafficPanel({
return () => {
active = false;
};
}, [findingId, contextTask, reload, filterStepIndex]);
}, [findingId, contextTask, reload, filterStepIndex, trafficReload]);
async function mutate(action: () => Promise<FindingTraffic>) {
setBusy(true);