From fa5fa07ef6f1e652a12487bc0f0e2a93b4b9e68c Mon Sep 17 00:00:00 2001 From: fish Date: Mon, 4 May 2026 23:20:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=95=B0=E6=8D=AE=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E5=8A=9F=E8=83=BD=EF=BC=9A=E7=AE=A1=E7=90=86=E5=91=98?= =?UTF-8?q?=E5=8F=AF=E4=B8=80=E9=94=AE=E6=B8=85=E7=A9=BA=E6=89=80=E6=9C=89?= =?UTF-8?q?=E8=A1=8C=E6=83=85=E6=95=B0=E6=8D=AE=EF=BC=8C=E9=9C=80=E8=BE=93?= =?UTF-8?q?=E5=85=A5=E7=A1=AE=E8=AE=A4=E6=96=87=E5=AD=97=E9=98=B2=E8=AF=AF?= =?UTF-8?q?=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- tushare/src/api.py | 7 +++++++ tushare/src/storage.py | 11 +++++++++++ web/backend/internal/handlers/reset.go | 22 ++++++++++++++++++++++ web/backend/internal/router/router.go | 1 + web/frontend/src/App.vue | 26 ++++++++++++++++++++++++++ web/frontend/src/api/admin.ts | 5 +++++ 6 files changed, 72 insertions(+) create mode 100644 web/backend/internal/handlers/reset.go create mode 100644 web/frontend/src/api/admin.ts diff --git a/tushare/src/api.py b/tushare/src/api.py index 5d6d6b0..4fb72f6 100644 --- a/tushare/src/api.py +++ b/tushare/src/api.py @@ -193,3 +193,10 @@ def list_candles( return [dict(zip(cols, row)) for row in cur.fetchall()] finally: conn.close() + + +@app.post("/api/v1/admin/reset-data") +def reset_data(): + """清空所有行情数据(仅限管理员调用)。""" + storage.truncate_all() + return {"status": "ok", "message": "已清空所有行情数据"} diff --git a/tushare/src/storage.py b/tushare/src/storage.py index 0363824..c3ca757 100644 --- a/tushare/src/storage.py +++ b/tushare/src/storage.py @@ -152,3 +152,14 @@ def get_latest_score(ts_code: str, db_url: str = DEFAULT_DB_URL) -> Optional[dic return dict(row) if row else None finally: conn.close() + + +def truncate_all(db_url: str = DEFAULT_DB_URL): + """清空所有行情数据(candles + scores),保留用户表。""" + conn = _get_conn(db_url) + try: + with conn.cursor() as cur: + cur.execute("TRUNCATE TABLE candles, scores") + conn.commit() + finally: + conn.close() diff --git a/web/backend/internal/handlers/reset.go b/web/backend/internal/handlers/reset.go new file mode 100644 index 0000000..caadabb --- /dev/null +++ b/web/backend/internal/handlers/reset.go @@ -0,0 +1,22 @@ +package handlers + +import ( + "fmt" + "io" + "net/http" + "time" +) + +func (d *Deps) AdminResetData(w http.ResponseWriter, r *http.Request) { + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Post(d.TushareURL+"/api/v1/admin/reset-data", "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) +} diff --git a/web/backend/internal/router/router.go b/web/backend/internal/router/router.go index e109c27..8fd5dbc 100644 --- a/web/backend/internal/router/router.go +++ b/web/backend/internal/router/router.go @@ -38,6 +38,7 @@ func New(d *handlers.Deps, dist fs.FS) http.Handler { r.Post("/admin/users", d.AdminCreateUser) r.Patch("/admin/users/{id}", d.AdminPatchUser) r.Delete("/admin/users/{id}", d.AdminDeleteUser) + r.Post("/admin/reset-data", d.AdminResetData) }) }) }) diff --git a/web/frontend/src/App.vue b/web/frontend/src/App.vue index 9a92b7c..2ef8a9c 100644 --- a/web/frontend/src/App.vue +++ b/web/frontend/src/App.vue @@ -1,9 +1,11 @@