package api import ( "encoding/json" "net/http" "strconv" "strings" "AI-Status-Light/internal/database" ) type Server struct { db *database.DB server *http.Server } type Response struct { Code int `json:"code"` Message string `json:"message"` Data interface{} `json:"data,omitempty"` } func New(db *database.DB, addr string) *Server { s := &Server{db: db} mux := http.NewServeMux() mux.HandleFunc("/api/mqtt", s.handleMQTT) mux.HandleFunc("/api/mqtt/", s.handleMQTTByID) mux.HandleFunc("/api/health", s.handleHealth) s.server = &http.Server{ Addr: addr, Handler: corsMiddleware(mux), } return s } func (s *Server) Start() error { return s.server.ListenAndServe() } func corsMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Content-Type") if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK) return } next.ServeHTTP(w, r) }) } func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, Response{Code: 0, Message: "ok"}) } func (s *Server) handleMQTT(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: s.listMQTTConfigs(w, r) case http.MethodPost: s.createMQTTConfig(w, r) default: writeJSON(w, http.StatusMethodNotAllowed, Response{Code: -1, Message: "方法不允许"}) } } func (s *Server) handleMQTTByID(w http.ResponseWriter, r *http.Request) { idStr := strings.TrimPrefix(r.URL.Path, "/api/mqtt/") id, err := strconv.Atoi(idStr) if err != nil { writeJSON(w, http.StatusBadRequest, Response{Code: -1, Message: "无效的 ID"}) return } switch r.Method { case http.MethodGet: s.getMQTTConfig(w, id) case http.MethodPut: s.updateMQTTConfig(w, r, id) case http.MethodDelete: s.deleteMQTTConfig(w, id) default: writeJSON(w, http.StatusMethodNotAllowed, Response{Code: -1, Message: "方法不允许"}) } } func (s *Server) listMQTTConfigs(w http.ResponseWriter, r *http.Request) { configs, err := s.db.ListMQTTConfigs() if err != nil { writeJSON(w, http.StatusInternalServerError, Response{Code: -1, Message: err.Error()}) return } writeJSON(w, http.StatusOK, Response{Code: 0, Message: "ok", Data: configs}) } func (s *Server) createMQTTConfig(w http.ResponseWriter, r *http.Request) { var cfg database.MQTTConfig if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil { writeJSON(w, http.StatusBadRequest, Response{Code: -1, Message: "无效的请求体"}) return } if cfg.Broker == "" { writeJSON(w, http.StatusBadRequest, Response{Code: -1, Message: "broker 不能为空"}) return } if cfg.ClientID == "" { cfg.ClientID = "opencode-monitor" } if cfg.Topic == "" { cfg.Topic = "opencode/status" } if err := s.db.SaveMQTTConfig(&cfg); err != nil { writeJSON(w, http.StatusInternalServerError, Response{Code: -1, Message: err.Error()}) return } writeJSON(w, http.StatusCreated, Response{Code: 0, Message: "创建成功", Data: cfg}) } func (s *Server) getMQTTConfig(w http.ResponseWriter, id int) { configs, err := s.db.ListMQTTConfigs() if err != nil { writeJSON(w, http.StatusInternalServerError, Response{Code: -1, Message: err.Error()}) return } for _, cfg := range configs { if cfg.ID == id { writeJSON(w, http.StatusOK, Response{Code: 0, Message: "ok", Data: cfg}) return } } writeJSON(w, http.StatusNotFound, Response{Code: -1, Message: "配置不存在"}) } func (s *Server) updateMQTTConfig(w http.ResponseWriter, r *http.Request, id int) { var cfg database.MQTTConfig if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil { writeJSON(w, http.StatusBadRequest, Response{Code: -1, Message: "无效的请求体"}) return } cfg.ID = id if cfg.Broker == "" { writeJSON(w, http.StatusBadRequest, Response{Code: -1, Message: "broker 不能为空"}) return } if cfg.ClientID == "" { cfg.ClientID = "opencode-monitor" } if cfg.Topic == "" { cfg.Topic = "opencode/status" } if err := s.db.SaveMQTTConfig(&cfg); err != nil { writeJSON(w, http.StatusInternalServerError, Response{Code: -1, Message: err.Error()}) return } writeJSON(w, http.StatusOK, Response{Code: 0, Message: "更新成功", Data: cfg}) } func (s *Server) deleteMQTTConfig(w http.ResponseWriter, id int) { if err := s.db.DeleteMQTTConfig(id); err != nil { writeJSON(w, http.StatusInternalServerError, Response{Code: -1, Message: err.Error()}) return } writeJSON(w, http.StatusOK, Response{Code: 0, Message: "删除成功"}) } func writeJSON(w http.ResponseWriter, statusCode int, data interface{}) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(statusCode) json.NewEncoder(w).Encode(data) } func (s *Server) GetAddr() string { return s.server.Addr }