From cff4319321b58154b38c0cc5836e3a9bfd792f01 Mon Sep 17 00:00:00 2001 From: fish Date: Mon, 4 May 2026 23:26:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=89=8B=E5=8A=A8=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E6=95=B0=E6=8D=AE=E5=8A=9F=E8=83=BD=EF=BC=9A=E7=82=B9?= =?UTF-8?q?=E5=87=BB=E4=BE=A7=E8=BE=B9=E6=A0=8F"=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E6=95=B0=E6=8D=AE"=E8=B0=83=E7=94=A8=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E6=89=93=E5=88=86=E6=8E=A5=E5=8F=A3=EF=BC=8C=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E5=90=8E=E8=B7=B3=E8=BD=AC=E6=89=93=E5=88=86=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E5=B9=B6=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- web/backend/internal/handlers/run.go | 14 ++++++++++++++ web/backend/internal/router/router.go | 1 + web/frontend/src/App.vue | 27 ++++++++++++++++++++++++++- web/frontend/src/api/run.ts | 4 ++++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/web/backend/internal/handlers/run.go b/web/backend/internal/handlers/run.go index c9ebf7a..78861ff 100644 --- a/web/backend/internal/handlers/run.go +++ b/web/backend/internal/handlers/run.go @@ -42,6 +42,20 @@ func (d *Deps) RunPipeline(w http.ResponseWriter, r *http.Request) { _, _ = io.Copy(w, resp.Body) } +func (d *Deps) RunBatch(w http.ResponseWriter, r *http.Request) { + client := &http.Client{Timeout: 120 * time.Second} + resp, err := client.Post(d.TushareURL+"/api/v1/run/batch", "application/json", nil) + if err != nil { + writeErr(w, http.StatusBadGateway, fmt.Sprintf("tushare service unavailable: %v", err)) + return + } + defer resp.Body.Close() + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(resp.StatusCode) + _, _ = io.Copy(w, resp.Body) +} + func (d *Deps) GetActiveContract(w http.ResponseWriter, r *http.Request) { symbol := r.URL.Query().Get("symbol") if symbol == "" { diff --git a/web/backend/internal/router/router.go b/web/backend/internal/router/router.go index 8fd5dbc..3dcccc6 100644 --- a/web/backend/internal/router/router.go +++ b/web/backend/internal/router/router.go @@ -31,6 +31,7 @@ func New(d *handlers.Deps, dist fs.FS) http.Handler { r.Get("/contracts/active", d.GetActiveContract) r.Get("/candles", d.ListCandles) r.Post("/run", d.RunPipeline) + r.Post("/run/batch", d.RunBatch) r.Group(func(r chi.Router) { r.Use(mw.RequireAdmin) diff --git a/web/frontend/src/App.vue b/web/frontend/src/App.vue index 7850c71..6d967e3 100644 --- a/web/frontend/src/App.vue +++ b/web/frontend/src/App.vue @@ -6,6 +6,7 @@ import { useAuthStore } from '@/stores/auth' import { useThemeStore } from '@/stores/theme' import { useMobile } from '@/composables/useMobile' import { resetAllData } from '@/api/admin' +import { runBatch } from '@/api/run' const auth = useAuthStore() const theme = useThemeStore() @@ -15,6 +16,7 @@ const { isMobile } = useMobile() const drawerOpen = ref(false) const resetting = ref(false) +const syncing = ref(false) const showLayout = computed(() => route.meta.layout !== 'blank' && !!auth.token) @@ -57,6 +59,23 @@ async function handleReset() { resetting.value = false } } + +async function handleSync() { + syncing.value = true + try { + await runBatch() + ElMessage.success('同步完成') + if (route.path === '/scores') { + router.go(0) + } else { + router.push('/scores') + } + } catch { + ElMessage.error('同步失败') + } finally { + syncing.value = false + } +}