fix(reports): export via authed axios blob download instead of window.open
Some checks failed
CI / test (push) Failing after 2m50s
Some checks failed
CI / test (push) Failing after 2m50s
启用登录鉴权后,导出 HTML/MD/JSON 用 window.open 直连 API 无法携带 X-Auth-Token,服务端返回 401 导致导出失效。改为经 axios 拉取 blob (拦截器自动附加凭据)后触发浏览器下载。
This commit is contained in:
parent
5dd3c4ff1c
commit
cbab55843b
@ -264,9 +264,16 @@ export interface RunLogsResponse {
|
|||||||
|
|
||||||
export const reportsApi = {
|
export const reportsApi = {
|
||||||
get: (runId: string) => api.get(`/reports/${runId}`),
|
get: (runId: string) => api.get(`/reports/${runId}`),
|
||||||
html: (runId: string) => api.get(`/reports/${runId}/html`),
|
download: async (runId: string, format: 'html' | 'json' | 'markdown') => {
|
||||||
json: (runId: string) => api.get(`/reports/${runId}/json`),
|
const ext = format === 'markdown' ? 'md' : format
|
||||||
markdownUrl: (runId: string) => `/api/reports/${runId}/markdown`,
|
const res = await api.get(`/reports/${runId}/${format}`, { responseType: 'blob' })
|
||||||
|
const url = URL.createObjectURL(res.data as Blob)
|
||||||
|
const a = document.createElement('a')
|
||||||
|
a.href = url
|
||||||
|
a.download = `report-${runId.slice(0, 8)}.${ext}`
|
||||||
|
a.click()
|
||||||
|
URL.revokeObjectURL(url)
|
||||||
|
},
|
||||||
compare: (run1: string, run2: string) =>
|
compare: (run1: string, run2: string) =>
|
||||||
api.get(`/reports/compare`, { params: { run1, run2 } }),
|
api.get(`/reports/compare`, { params: { run1, run2 } }),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -325,10 +325,10 @@ export default function ReportsPage() {
|
|||||||
|
|
||||||
{viewMode === 'single' && report && (
|
{viewMode === 'single' && report && (
|
||||||
<Space style={{ flexShrink: 0 }}>
|
<Space style={{ flexShrink: 0 }}>
|
||||||
<Button icon={<DownloadOutlined />} onClick={() => window.open(`/api/reports/${selectedRunId}/html`, '_blank')}>
|
<Button icon={<DownloadOutlined />} onClick={() => reportsApi.download(selectedRunId, 'html')}>
|
||||||
导出 HTML
|
导出 HTML
|
||||||
</Button>
|
</Button>
|
||||||
<Button icon={<FileMarkdownOutlined />} onClick={() => window.open(reportsApi.markdownUrl(selectedRunId), '_blank')}>
|
<Button icon={<FileMarkdownOutlined />} onClick={() => reportsApi.download(selectedRunId, 'markdown')}>
|
||||||
导出 MD
|
导出 MD
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
FileTextOutlined, PlayCircleOutlined, ReloadOutlined, StopOutlined,
|
FileTextOutlined, PlayCircleOutlined, ReloadOutlined, StopOutlined,
|
||||||
} from '@ant-design/icons'
|
} from '@ant-design/icons'
|
||||||
import { runsApi, scenariosApi, targetsApi, type Run, type Scenario, type Target } from '../api'
|
import { reportsApi, runsApi, scenariosApi, targetsApi, type Run, type Scenario, type Target } from '../api'
|
||||||
import RunList from '../components/RunList'
|
import RunList from '../components/RunList'
|
||||||
import CaseBlock from '../components/CaseBlock'
|
import CaseBlock from '../components/CaseBlock'
|
||||||
import RuleOverview from '../components/RuleOverview'
|
import RuleOverview from '../components/RuleOverview'
|
||||||
@ -226,7 +226,7 @@ export default function RunsPage() {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onOpenReport={handleOpenReport}
|
onOpenReport={handleOpenReport}
|
||||||
onExportJson={(runId) => window.open(`/api/reports/${runId}/json`, '_blank')}
|
onExportJson={(runId) => reportsApi.download(runId, 'json')}
|
||||||
onRerun={async () => {
|
onRerun={async () => {
|
||||||
if (!session.run) return
|
if (!session.run) return
|
||||||
await startRun(session.run.target_id, session.run.scenario_id)
|
await startRun(session.run.target_id, session.run.scenario_id)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user