package handler import ( "net/http" "strings" "time" "bj_power_workstation/internal/auth" "bj_power_workstation/internal/svc" "golang.org/x/crypto/bcrypt" ) func healthHandler(ctx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if err := ctx.Store.Ping(); err == nil { ok(w, map[string]any{ "status": "UP", "time": time.Now().Format("2006-01-02 15:04:05"), "service": "bj_power_workstation", }) return } fail(w, http.StatusServiceUnavailable, "本地数据库不可用") } } // loginHandler 本地 SQLite + bcrypt 校验登录,返回 {token, expireAt, user}。 // 账号自动记录为操作人(前端通过 localStorage 的 user 保存操作人)。 func loginHandler(ctx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req struct { Username string `json:"username"` Password string `json:"password"` } if err := parseJSON(r, &req); err != nil { fail(w, http.StatusBadRequest, "参数错误") return } if strings.TrimSpace(req.Username) == "" || req.Password == "" { fail(w, http.StatusBadRequest, "用户名和密码必填") return } u, err := ctx.Store.GetUserByUsername(strings.TrimSpace(req.Username)) if err != nil { fail(w, http.StatusUnauthorized, "用户名或密码错误") return } if bcrypt.CompareHashAndPassword([]byte(u.PasswordHash), []byte(req.Password)) != nil { fail(w, http.StatusUnauthorized, "用户名或密码错误") return } token, expireAt, err := auth.SignToken( ctx.Config.Auth.AccessSecret, ctx.Config.Auth.AccessExpire, auth.TokenInfo{UserID: u.ID, Username: u.Username, RealName: u.RealName, Role: u.Role}, ) if err != nil { fail(w, http.StatusInternalServerError, "签发 token 失败") return } ctx.Store.AddEventLog("", u.RealName, "login", "账号登录") ok(w, map[string]any{ "token": token, "expireAt": expireAt, "user": map[string]any{ "id": u.ID, "username": u.Username, "realName": u.RealName, "role": u.Role, }, }) } } // configHandler GET /api/config 返回工位配置: // 固定工位号(Station.Code 为空则前端可自选)、本工位需拧紧的螺丝颗数。 func configHandler(ctx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { ok(w, map[string]any{ "station": ctx.Config.Station.Code, "screwCount": ctx.Config.Station.ScrewCount, }) } }