From f651af970f7d249b620929819b69680ae6555a69 Mon Sep 17 00:00:00 2001 From: Istil <66511737+Keyun-Istil@users.noreply.github.com> Date: Wed, 18 Aug 2021 16:43:39 +0800 Subject: [PATCH] feat: support classpaths prefix tree display (#769) --- http/router.go | 4 ++ http/router_classpath.go | 15 ++++++ models/classpath.go | 102 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 119 insertions(+), 2 deletions(-) diff --git a/http/router.go b/http/router.go index 3cb6db6d..4aa79b4d 100644 --- a/http/router.go +++ b/http/router.go @@ -83,6 +83,8 @@ func configRoutes(r *gin.Engine) { pages.DELETE("/user-group/:id", login(), userGroupDel) pages.GET("/classpaths", login(), classpathListGets) + pages.GET("/classpaths/tree", login(), classpathListNodeGets) + pages.GET("/classpaths/tree-node/:id", login(), classpathListNodeGetsById) pages.POST("/classpaths", login(), classpathAdd) pages.PUT("/classpath/:id", login(), classpathPut) pages.DELETE("/classpath/:id", login(), classpathDel) @@ -213,6 +215,8 @@ func configRoutes(r *gin.Engine) { v1.DELETE("/user-group/:id", login(), userGroupDel) v1.GET("/classpaths", login(), classpathListGets) + v1.GET("/classpaths/tree", login(), classpathListNodeGets) + v1.GET("/classpaths/tree-node/:id", login(), classpathListNodeGetsById) v1.POST("/classpaths", login(), classpathAdd) v1.PUT("/classpath/:id", login(), classpathPut) v1.DELETE("/classpath/:id", login(), classpathDel) diff --git a/http/router_classpath.go b/http/router_classpath.go index 76c8d45f..3c80f6ee 100644 --- a/http/router_classpath.go +++ b/http/router_classpath.go @@ -24,6 +24,21 @@ func classpathListGets(c *gin.Context) { }, nil) } +func classpathListNodeGets(c *gin.Context) { + query := queryStr(c, "query", "") + + list, err := models.ClasspathNodeGets(query) + dangerous(err) + + renderData(c, list, nil) +} + +func classpathListNodeGetsById(c *gin.Context) { + cp := Classpath(urlParamInt64(c, "id")) + children, err := cp.DirectChildren() + renderData(c, children, err) +} + func classpathFavoriteGet(c *gin.Context) { lst, err := loginUser(c).FavoriteClasspaths() renderData(c, lst, err) diff --git a/models/classpath.go b/models/classpath.go index 46f0a564..5e68b4da 100644 --- a/models/classpath.go +++ b/models/classpath.go @@ -19,6 +19,14 @@ type Classpath struct { UpdateBy string `json:"update_by"` } +type ClasspathNode struct { + Id int64 `json:"id"` + Path string `json:"path"` + Note string `json:"note"` + Preset int `json:"preset"` + Children []*ClasspathNode `json:"children"` +} + func (c *Classpath) TableName() string { return "classpath" } @@ -104,7 +112,6 @@ func ClasspathGets(query string, limit, offset int) ([]Classpath, error) { q := "%" + query + "%" session = session.Where("path like ?", q) } - var objs []Classpath err := session.Find(&objs) if err != nil { @@ -151,7 +158,7 @@ func ClasspathGet(where string, args ...interface{}) (*Classpath, error) { func ClasspathGetsByPrefix(prefix string) ([]Classpath, error) { var objs []Classpath - err := DB.Where("path like ?", prefix+"%").Find(&objs) + err := DB.Where("path like ?", prefix+"%").OrderBy("path").Find(&objs) if err != nil { logger.Errorf("mysql.error: query classpath fail: %v", err) return objs, internalServerError @@ -218,3 +225,94 @@ func (c *Classpath) AddResources(idents []string) error { func (c *Classpath) DelResources(idents []string) error { return ClasspathResourceDel(c.Id, idents) } + +func ClasspathNodeGets(query string) ([]*ClasspathNode, error) { + session := DB.OrderBy("path") + if query != "" { + q := "%" + query + "%" + session = session.Where("path like ?", q) + } + var objs []Classpath + err := session.Find(&objs) + if err != nil { + logger.Errorf("mysql.error: query classpath fail: %v", err) + return []*ClasspathNode{}, internalServerError + } + + if len(objs) == 0 { + return []*ClasspathNode{}, nil + } + pcs := ClasspathNodeAllChildren(objs) + + return pcs, nil +} + +func (cp *Classpath) DirectChildren() ([]Classpath, error) { + var pcs []Classpath + objs, err := ClasspathGetsByPrefix(cp.Path) + if err != nil { + logger.Errorf("mysql.error: query prefix classpath fail: %v", err) + return []Classpath{}, internalServerError + } + if len(objs) < 2 { + return []Classpath{}, nil + } + + pre := objs[1] + path := pre.Path[len(objs[0].Path):] + pre.Path = path + pcs = append(pcs, pre) + + for _, cp := range objs[2:] { + has := strings.HasPrefix(cp.Path, pre.Path) + if !has { + path := cp.Path[len(objs[0].Path):] + pre.Path = path + pcs = append(pcs, pre) + pre = cp + } + } + + return pcs, nil +} + +func ClasspathNodeAllChildren(cps []Classpath) []*ClasspathNode { + var node ClasspathNode + for _, cp := range cps { + ListInsert(cp, &node) + } + + return node.Children +} + +func ListInsert(obj Classpath, node *ClasspathNode) { + path := obj.Path + has := true + for { + if len(node.Children) == 0 { + break + } + children := node.Children[len(node.Children)-1] + prefix := children.Path + has = strings.HasPrefix(path, prefix) + if !has { + break + } + path = path[len(prefix):] + node = children + } + + newNode := ToClasspathNode(obj, path) + node.Children = append(node.Children, &newNode) +} + +func ToClasspathNode(cp Classpath, path string) ClasspathNode { + var obj ClasspathNode + obj.Id = cp.Id + obj.Path = path + obj.Note = cp.Note + obj.Preset = cp.Preset + obj.Children = []*ClasspathNode{} + + return obj +}