新增完整的异步任务管理体系: 1. 新增Redis缓存层实现任务状态实时存储与降级机制 2. 实现并发拉取+批量写入的高性能入库流程 3. 添加任务管理HTTP接口与路由 4. 重构行情控制器使用共享SQLite存储 5. 配套添加Docker Compose Redis启动配置 6. 前端新增任务管理面板支持操作与进度查看
78 lines
2.8 KiB
Go
78 lines
2.8 KiB
Go
// Package router 负责 HTTP 路由注册,将请求分发到 Controller。
|
||
package router
|
||
|
||
import (
|
||
"fmt"
|
||
"net/http"
|
||
"path/filepath"
|
||
"strings"
|
||
|
||
"stock-analysis/internal/controller"
|
||
)
|
||
|
||
// New 构建应用路由处理器。
|
||
// webDir 为前端静态资源目录(View 层)。
|
||
func New(mc *controller.MarketController, ac *controller.AuthController, tc *controller.TaskController, webDir string) http.Handler {
|
||
mux := http.NewServeMux()
|
||
|
||
// 公开接口:无需登录。
|
||
mux.HandleFunc("POST /api/auth/send-code", ac.SendCode)
|
||
mux.HandleFunc("POST /api/auth/register", ac.Register)
|
||
mux.HandleFunc("POST /api/auth/login", ac.Login)
|
||
|
||
// 受保护接口:需要登录。
|
||
mux.HandleFunc("GET /api/auth/me", ac.Me)
|
||
mux.HandleFunc("POST /api/auth/logout", ac.Logout)
|
||
mux.HandleFunc("GET /api/bonds", requireAuth(ac, mc.ListBonds))
|
||
mux.HandleFunc("GET /api/bonds/{code}/kline", requireAuth(ac, mc.GetKline))
|
||
mux.HandleFunc("POST /api/backtest", requireAuth(ac, mc.RunBacktest))
|
||
mux.HandleFunc("GET /api/status", requireAuth(ac, mc.GetDataStatus))
|
||
mux.HandleFunc("GET /api/db/bonds", requireAuth(ac, mc.ListDBBonds))
|
||
|
||
// 数据入库任务接口:创建/查询/取消(需要登录)。
|
||
mux.HandleFunc("POST /api/tasks", requireAuth(ac, tc.CreateTask))
|
||
mux.HandleFunc("GET /api/tasks", requireAuth(ac, tc.ListTasks))
|
||
mux.HandleFunc("GET /api/tasks/{id}", requireAuth(ac, tc.GetTask))
|
||
mux.HandleFunc("POST /api/tasks/{id}/cancel", requireAuth(ac, tc.CancelTask))
|
||
|
||
// 静态资源:登录页及样式脚本公开,首页受保护。
|
||
fs := noCache(http.FileServer(http.Dir(webDir)))
|
||
mux.Handle("/auth.html", fs)
|
||
mux.Handle("/style.css", fs)
|
||
mux.HandleFunc("/", requireAuth(ac, func(w http.ResponseWriter, r *http.Request) {
|
||
if r.URL.Path != "/" && r.URL.Path != "/index.html" {
|
||
http.NotFound(w, r)
|
||
return
|
||
}
|
||
http.ServeFile(w, r, filepath.Join(webDir, "index.html"))
|
||
}))
|
||
return mux
|
||
}
|
||
|
||
// requireAuth 中间件:未登录的 API 请求返回 401,页面请求重定向到登录页。
|
||
func requireAuth(ac *controller.AuthController, next http.HandlerFunc) http.HandlerFunc {
|
||
return func(w http.ResponseWriter, r *http.Request) {
|
||
if _, err := ac.CurrentUser(r); err != nil {
|
||
if strings.HasPrefix(r.URL.Path, "/api/") {
|
||
w.Header().Set("Content-Type", "application/json")
|
||
w.WriteHeader(http.StatusUnauthorized)
|
||
fmt.Fprintf(w, `{"error":"%s"}`, err.Error())
|
||
} else {
|
||
http.Redirect(w, r, "/auth.html", http.StatusFound)
|
||
}
|
||
return
|
||
}
|
||
next.ServeHTTP(w, r)
|
||
}
|
||
}
|
||
|
||
// noCache 中间件:禁止浏览器缓存静态资源,确保每次加载最新版本。
|
||
func noCache(next http.Handler) http.Handler {
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
|
||
w.Header().Set("Pragma", "no-cache")
|
||
w.Header().Set("Expires", "0")
|
||
next.ServeHTTP(w, r)
|
||
})
|
||
}
|