diff --git a/frontend/src/api/backtest.ts b/frontend/src/api/backtest.ts index 1a7d899..e4ef2e5 100644 --- a/frontend/src/api/backtest.ts +++ b/frontend/src/api/backtest.ts @@ -6,6 +6,7 @@ export interface CtaSubmit { params: Record start: string end: string + benchmark?: string } export interface TaskStatus { diff --git a/frontend/src/views/backtest/New.vue b/frontend/src/views/backtest/New.vue index 55f83e0..bbe7720 100644 --- a/frontend/src/views/backtest/New.vue +++ b/frontend/src/views/backtest/New.vue @@ -16,6 +16,7 @@ const form = reactive({ symbol: '600000', start: '2024-01-01', end: '2024-06-30', + benchmark: 'hs300', }) const paramValues = reactive>({}) @@ -65,6 +66,7 @@ async function onSubmit(): Promise { params, start: form.start, end: form.end, + benchmark: form.benchmark, }) ElMessage.success('回测已提交') router.push(`/backtest/progress/${tid}`) @@ -103,6 +105,12 @@ async function onSubmit(): Promise { + + + + + + 提交回测 diff --git a/sanguo_api/main.py b/sanguo_api/main.py index 2a12440..ba81c35 100644 --- a/sanguo_api/main.py +++ b/sanguo_api/main.py @@ -72,6 +72,19 @@ def build_app(config_path: str = "config/backtest.yaml", static_dir: str | None app.mount("/", StaticFiles(directory=static_dir, html=True), name="spa") + # SPA history fallback: deep links like /backtest/result/:id hit StaticFiles + # (no such file) → 404. For browser navigation (Accept: text/html) serve + # index.html so vue-router can take over; API 404s (Accept: application/json) + # still return JSON. This makes refresh/bookmark of any SPA route work. + from starlette.exceptions import HTTPException as StarletteHTTPException + from starlette.responses import JSONResponse + + @app.exception_handler(StarletteHTTPException) + async def _spa_fallback(request, exc): # noqa: ANN001 + if exc.status_code == 404 and "text/html" in request.headers.get("accept", ""): + return FileResponse(index_html) + return JSONResponse({"detail": exc.detail}, status_code=exc.status_code) + return app