diff --git a/server/cmd/main.go b/server/cmd/main.go index 5517235..95abcbc 100644 --- a/server/cmd/main.go +++ b/server/cmd/main.go @@ -67,7 +67,6 @@ func main() { // app management admin.POST("/app/list", appHandler.List) - admin.GET("/app/tree", appHandler.Tree) admin.GET("/app/:id", appHandler.GetById) admin.POST("/app/add", appHandler.Add) admin.POST("/app/update", appHandler.Update) diff --git a/server/internal/config/config.go b/server/internal/config/config.go index 81835fa..6eee5ab 100644 --- a/server/internal/config/config.go +++ b/server/internal/config/config.go @@ -137,5 +137,5 @@ func intProp(props map[string]string, key string, defaultVal int) int { } func (d *DatabaseConfig) DSN() string { - return d.User + ":" + d.Password + "@tcp(" + d.Host + ":" + strconv.Itoa(d.Port) + ")/" + d.Name + "?charset=utf8&parseTime=true" + return d.User + ":" + d.Password + "@tcp(" + d.Host + ":" + strconv.Itoa(d.Port) + ")/" + d.Name + "?charset=utf8&parseTime=true&loc=Local" } diff --git a/server/internal/dao/engine.go b/server/internal/dao/engine.go index fa3885e..aba7001 100644 --- a/server/internal/dao/engine.go +++ b/server/internal/dao/engine.go @@ -1,7 +1,6 @@ package dao import ( - "fmt" "kenaito-conf/server/internal/config" "kenaito-conf/server/internal/model" "kenaito-conf/server/internal/util" @@ -14,9 +13,7 @@ import ( var Engine *xorm.Engine func Init() error { - cfg := config.Cfg.Database - dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=true&loc=Local", - cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.Name) + dsn := config.Cfg.Database.DSN() var err error Engine, err = xorm.NewEngine("mysql", dsn) diff --git a/server/internal/handler/app.go b/server/internal/handler/app.go index 48e45d7..1850e8e 100644 --- a/server/internal/handler/app.go +++ b/server/internal/handler/app.go @@ -48,7 +48,7 @@ func (h *AppHandler) List(c *gin.Context) { total, _ := query.Count(&model.Application{}) query.Limit(req.PageSize, (req.PageNo-1)*req.PageSize).Find(&apps) - // load group names + // load group names - batch query to avoid N+1 groupIds := make(map[int]bool) for _, app := range apps { if app.GroupId != nil { @@ -56,10 +56,15 @@ func (h *AppHandler) List(c *gin.Context) { } } groupMap := make(map[int]string) - for gid := range groupIds { - var group model.BusinessGroup - if has, _ := dao.Engine.ID(gid).Get(&group); has { - groupMap[gid] = group.Name + if len(groupIds) > 0 { + ids := make([]int, 0, len(groupIds)) + for gid := range groupIds { + ids = append(ids, gid) + } + var groups []model.BusinessGroup + dao.Engine.In("id", ids).Find(&groups) + for _, g := range groups { + groupMap[g.Id] = g.Name } } for i := range apps { @@ -82,38 +87,6 @@ func (h *AppHandler) GetById(c *gin.Context) { c.JSON(http.StatusOK, model.WrapperResponse{Code: 0, Data: app}) } -func (h *AppHandler) Tree(c *gin.Context) { - var apps []model.Application - dao.Engine.Find(&apps) - - tree := make(map[string]*AppTreeModel) - for _, app := range apps { - node := &AppTreeModel{ - Id: strconv.Itoa(app.Id), - Name: app.Name, - Code: app.Code, - ServiceId: app.ServiceId, - Children: make([]*AppTreeModel, 0), - } - tree[strconv.Itoa(app.Id)] = node - } - - result := make([]*AppTreeModel, 0) - for _, app := range apps { - node := tree[strconv.Itoa(app.Id)] - if app.ParentId == nil { - result = append(result, node) - } else { - parentId := strconv.Itoa(*app.ParentId) - if parent, ok := tree[parentId]; ok { - parent.Children = append(parent.Children, node) - } - } - } - - c.JSON(http.StatusOK, model.WrapperResponse{Code: 0, Data: result}) -} - type AddAppRequest struct { Id int `json:"id"` GroupId *int `json:"groupId"` @@ -295,14 +268,6 @@ func (h *AppHandler) Options(c *gin.Context) { c.JSON(http.StatusOK, model.WrapperResponse{Code: 0, Data: options}) } -type AppTreeModel struct { - Id string `json:"id"` - Name string `json:"name"` - Code string `json:"code"` - ServiceId string `json:"serviceId,omitempty"` - Children []*AppTreeModel `json:"children"` -} - func (h *AppHandler) GenerateToken(c *gin.Context) { id, _ := strconv.Atoi(c.Param("id")) userInfo := middleware.GetUserInfo(c) diff --git a/server/internal/handler/config.go b/server/internal/handler/config.go index e0f0a72..9bf9828 100644 --- a/server/internal/handler/config.go +++ b/server/internal/handler/config.go @@ -45,10 +45,7 @@ func (h *ConfigHandler) List(c *gin.Context) { if *req.AppId <= 0 { query = query.And("(app_id is null OR app_id = 0)") } else { - var app model.Application - if has, _ := dao.Engine.ID(*req.AppId).Get(&app); has { - query = query.And("app_code like ?", app.Code+"%") - } + query = query.And("app_id = ?", *req.AppId) } } diff --git a/server/internal/handler/profile.go b/server/internal/handler/profile.go index 3144642..ee56fa1 100644 --- a/server/internal/handler/profile.go +++ b/server/internal/handler/profile.go @@ -6,6 +6,7 @@ import ( "kenaito-conf/server/internal/model" "net/http" "strconv" + "time" "github.com/gin-gonic/gin" ) @@ -64,6 +65,7 @@ func (h *ProfileHandler) Add(c *gin.Context) { Alias: req.Alias, IsDefault: req.IsDefault, Enabled: true, + CreatedAt: func() *time.Time { t := time.Now(); return &t }(), } dao.Engine.Insert(&profile) @@ -104,7 +106,9 @@ func (h *ProfileHandler) Update(c *gin.Context) { } profile.Alias = req.Alias - dao.Engine.ID(profile.Id).Update(&profile) + now := time.Now() + profile.UpdatedAt = &now + dao.Engine.ID(profile.Id).Cols("alias", "is_default", "updated_at").Update(&profile) c.JSON(http.StatusOK, model.WrapperResponse{Code: 0, Data: true}) } diff --git a/server/internal/handler/user.go b/server/internal/handler/user.go index 6d1f5db..2d109cd 100644 --- a/server/internal/handler/user.go +++ b/server/internal/handler/user.go @@ -27,7 +27,7 @@ func (h *UserHandler) List(c *gin.Context) { userInfo := middleware.GetUserInfo(c) var users []model.User - query := dao.Engine.Where("1=1") + query := dao.Engine.Where("enabled = 1") if !userInfo.IsSuperAdmin() && userInfo.GroupId != nil { query = query.And("group_id = ?", *userInfo.GroupId) @@ -84,13 +84,13 @@ func (h *UserHandler) Add(c *gin.Context) { return } - // check name exists + // check name exists - only check active users (enabled = 1) var existing model.User - if has, _ := dao.Engine.Where("name = ?", req.Name).Get(&existing); has { + if has, _ := dao.Engine.Where("name = ? AND enabled = 1", req.Name).Get(&existing); has { c.JSON(http.StatusOK, model.WrapperResponse{Code: 1001, Msg: "用户名已存在"}) return } - if has, _ := dao.Engine.Where("mobile = ?", req.Mobile).Get(&existing); has { + if has, _ := dao.Engine.Where("mobile = ? AND enabled = 1", req.Mobile).Get(&existing); has { c.JSON(http.StatusOK, model.WrapperResponse{Code: 1001, Msg: "手机号已存在"}) return } @@ -150,7 +150,7 @@ func (h *UserHandler) Update(c *gin.Context) { userId, _ := strconv.Atoi(userInfo.Id) var user model.User - has, _ := dao.Engine.ID(userId).Get(&user) + has, _ := dao.Engine.Where("id = ? AND enabled = 1", userId).Get(&user) if !has { c.JSON(http.StatusOK, model.WrapperResponse{Code: 404, Msg: "用户不存在"}) return @@ -203,7 +203,7 @@ func (h *UserHandler) AdminUpdate(c *gin.Context) { } var user model.User - has, _ := dao.Engine.ID(req.Id).Get(&user) + has, _ := dao.Engine.Where("id = ? AND enabled = 1", req.Id).Get(&user) if !has { c.JSON(http.StatusOK, model.WrapperResponse{Code: 404, Msg: "用户不存在"}) return @@ -264,7 +264,7 @@ func (h *UserHandler) Delete(c *gin.Context) { userInfo := middleware.GetUserInfo(c) var user model.User - has, _ := dao.Engine.ID(id).Get(&user) + has, _ := dao.Engine.Where("id = ? AND enabled = 1", id).Get(&user) if !has { c.JSON(http.StatusOK, model.WrapperResponse{Code: 404, Msg: "用户不存在"}) return @@ -275,7 +275,10 @@ func (h *UserHandler) Delete(c *gin.Context) { return } - dao.Engine.ID(id).Delete(&model.User{}) + user.Enabled = false + now := time.Now() + user.UpdatedAt = &now + dao.Engine.ID(user.Id).Cols("enabled", "updated_at").Update(&user) c.JSON(http.StatusOK, model.WrapperResponse{Code: 0}) } @@ -283,7 +286,7 @@ func (h *UserHandler) Delete(c *gin.Context) { func (h *UserHandler) ResetPassword(c *gin.Context) { id, _ := strconv.Atoi(c.Param("id")) var user model.User - has, _ := dao.Engine.ID(id).Get(&user) + has, _ := dao.Engine.Where("id = ? AND enabled = 1", id).Get(&user) if !has { c.JSON(http.StatusOK, model.WrapperResponse{Code: 404, Msg: "用户不存在"}) return @@ -302,7 +305,7 @@ func (h *UserHandler) ResetPassword(c *gin.Context) { func (h *UserHandler) Switch(c *gin.Context) { id, _ := strconv.Atoi(c.Param("id")) var user model.User - has, _ := dao.Engine.ID(id).Get(&user) + has, _ := dao.Engine.Where("id = ? AND enabled = 1", id).Get(&user) if !has { c.JSON(http.StatusOK, model.WrapperResponse{Code: 404, Msg: "用户不存在"}) return diff --git a/server/internal/model/profile.go b/server/internal/model/profile.go index 1006004..7788e8a 100644 --- a/server/internal/model/profile.go +++ b/server/internal/model/profile.go @@ -1,11 +1,15 @@ package model +import "time" + type Profile struct { - Id int `xorm:"int autoincr pk" json:"id"` - Name string `xorm:"varchar(32)" json:"name"` - Alias string `xorm:"varchar(32)" json:"alias"` - IsDefault bool `xorm:"tinyint(1) default 0" json:"isDefault"` - Enabled bool `xorm:"tinyint(1) default 1" json:"enabled"` + Id int `xorm:"int autoincr pk" json:"id"` + Name string `xorm:"varchar(32)" json:"name"` + Alias string `xorm:"varchar(32)" json:"alias"` + IsDefault bool `xorm:"tinyint(1) default 0" json:"isDefault"` + Enabled bool `xorm:"tinyint(1) default 1" json:"enabled"` + CreatedAt *time.Time `xorm:"datetime" json:"createdAt"` + UpdatedAt *time.Time `xorm:"datetime" json:"updatedAt"` } type AppExtrAttr struct { diff --git a/web/src/api/app.js b/web/src/api/app.js index 2af89a6..04c7323 100644 --- a/web/src/api/app.js +++ b/web/src/api/app.js @@ -8,13 +8,6 @@ export function getAppList(params) { }) } -export function getAppTree() { - return request({ - url: '/admin/app/tree', - method: 'get' - }) -} - export function getApp(id) { return request({ url: `/admin/app/${id}`,