包含前端(Vue3 + VueFlow 画布)、后端(Go)、文档体系。 - 工作台画布:节点拖放、连线模式、右键菜单、AI 助手 - 后端:连接器 API、专员种子数据 - 导航:左侧导航、工坊、市场、控制台
76 lines
1.7 KiB
Go
76 lines
1.7 KiB
Go
package api
|
|
|
|
import (
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"eaisalestrain/backend/internal/auth"
|
|
"eaisalestrain/backend/internal/middleware"
|
|
"eaisalestrain/backend/internal/model"
|
|
"eaisalestrain/backend/internal/store"
|
|
"eaisalestrain/backend/internal/web"
|
|
)
|
|
|
|
type loginRequest struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
// Login 登录 → JWT
|
|
func Login(c *gin.Context) {
|
|
var req loginRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
web.Fail(c, web.NewBadRequest("请求参数错误"))
|
|
return
|
|
}
|
|
|
|
var user model.User
|
|
if err := store.DB.Where("username = ?", req.Username).First(&user).Error; err != nil {
|
|
web.Fail(c, web.NewAuthError("用户名或密码错误"))
|
|
return
|
|
}
|
|
if user.Status != "active" {
|
|
web.Fail(c, web.NewAuthError("账号已禁用"))
|
|
return
|
|
}
|
|
if !auth.VerifyPassword(req.Password, user.PasswordHash) {
|
|
web.Fail(c, web.NewAuthError("用户名或密码错误"))
|
|
return
|
|
}
|
|
|
|
token, err := auth.CreateToken(user.Username, user.Role, Cfg.JWTSecret, Cfg.JWTExpireMin)
|
|
if err != nil {
|
|
web.Fail(c, web.NewBadRequest("令牌签发失败"))
|
|
return
|
|
}
|
|
|
|
web.OK(c, gin.H{
|
|
"token": token,
|
|
"expires_in": Cfg.JWTExpireMin * 60,
|
|
"user": gin.H{
|
|
"id": user.ID,
|
|
"username": user.Username,
|
|
"full_name": user.FullName,
|
|
"role": user.Role,
|
|
"ai_points": user.AiPoints,
|
|
},
|
|
})
|
|
}
|
|
|
|
// Me 当前用户信息
|
|
func Me(c *gin.Context) {
|
|
u := middleware.CurrentUser(c)
|
|
if u == nil {
|
|
web.Fail(c, web.NewAuthError("未登录"))
|
|
return
|
|
}
|
|
web.OK(c, gin.H{
|
|
"id": u.ID,
|
|
"username": u.Username,
|
|
"full_name": u.FullName,
|
|
"role": u.Role,
|
|
"status": u.Status,
|
|
"ai_points": u.AiPoints,
|
|
"learning_points": u.LearningPoints,
|
|
})
|
|
}
|