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 + } +}