package sysdb import ( "container/list" "encoding/json" "errors" "fmt" "git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys" "git.qianqiusoft.com/qianqiusoft/light-apiengine/models" "strings" ) type TreeNode struct { ID string `json:"id"` Text string `json:"text"` Parent string `json:"-"` Nodes []*TreeNode `json:"nodes"` } type ZTreeNode struct { Id string `json:"id"` Parent string `json:"parent"` Name string `json:"name"` } type ZTreeConvertor struct { IdField string NameField string ParentField string CntParent string Maps []map[string]string ZTreeNodeArray []*ZTreeNode TreeNodeArray []*TreeNode } func TreeList(c *entitys.CtrlContext, user *entitys.Token, tbName, parentField, parentValue, textFiled, valueFiled, cntParent, domainchk, filter, sord string) ([]*TreeNode, error) { ztConvertor := &ZTreeConvertor{} domain := "" if !IsSuperUser(user) { if domainchk == "1" { domain = user.Domain } } pv := "" if !IsSuperUser(user) { pv = parentValue if cntParent != "1" { pv = "" } } filterObj := &models.Filter{} if len(filter) > 0 { if err := json.Unmarshal([]byte(filter), filterObj); err != nil { return ztConvertor.TreeNodeArray, errors.New(`filters parameter only allows {"groupOp":"AND","rules":[{"field":"org_name","op":"eq","data":"测试"}]}`) } } paramsArr, err := GetTreeList(c, domain, tbName, parentField, textFiled, valueFiled, pv, filterObj, sord) if err != nil { return ztConvertor.TreeNodeArray, err } ztConvertor.IdField = valueFiled ztConvertor.NameField = textFiled ztConvertor.ParentField = parentField ztConvertor.CntParent = cntParent ztConvertor.Maps = paramsArr if !ztConvertor.BuildTreeArray(strings.TrimSpace(pv)) { return ztConvertor.TreeNodeArray, errors.New("orm.params convert to ztree error") } return ztConvertor.TreeNodeArray, nil } func GetTreeList(c *entitys.CtrlContext, domain, tbName, parentFiled, textFiled, valueFiled, parentValue string, filter *models.Filter, sord string) ([]map[string]string, error) { sql := fmt.Sprintf("SELECT `%s`, `%s`, `%s` FROM `%s`", valueFiled, textFiled, parentFiled, tbName) where := " where (" groupOp := strings.ToLower(filter.GroupOp) datas := make([]interface{}, 0) isAnd := true if groupOp == "or" { isAnd = false where += "1 <> 1" } else { isAnd = true where += "1 = 1" } for _, field := range filter.Rules { fData := models.FormatData(field.Op, field.Data) switch fData.(type) { case string: { if len(fData.(string)) >= 0 { datas = append(datas, fData) } } case []string: { fDataArr := fData.([]string) for _, arr := range fDataArr { if len(arr) > 0 { datas = append(datas, arr) } } } } whereStr := models.FormatOp(tbName, field.Op, field.Field, field.Data) if len(whereStr) > 0 { if isAnd { where += " and " } else { where += " or " } where += whereStr } } where += ")" if domain != "" { where += " and (" where += fmt.Sprintf(" domain = '%s')", domain) } sql = sql + where if parentValue != "" { sql1 := fmt.Sprintf("select `%s`, `%s`, `%s` from `%s` where `%s` = ?", valueFiled, textFiled, parentFiled, tbName, valueFiled) sql = sql + " union " + sql1 datas = append(datas, parentValue) } if strings.TrimSpace(sord) == "" { sql = sql + " order by " + parentFiled } else { sql = sql + " order by " + sord } if len(datas) > 0 { //result, err := c.Db.QueryInterface(sql, datas) result, err := c.Db.QueryString(sql, datas) return result, err } else { result, err := c.Db.QueryString(sql) return result, err } } func (this *ZTreeConvertor) BuildTreeArray(root string) bool { rootArr := []*TreeNode{} if len(this.Maps) <= 0 { this.TreeNodeArray = rootArr return true } paramsArr := this.Maps valueFiled := this.IdField parentField := this.ParentField textFiled := this.NameField parentValue := root treeNodeList := list.New() originNodeList := list.New() if root != "" && this.CntParent == "1" { for _, params := range paramsArr { value := getStringValueByInterface(params[valueFiled], "") parent := getStringValueByInterface(params[parentField], "") text := getStringValueByInterface(params[textFiled], "") //fmt.Println("========" + text + "-----" + value + "======" + parentValue) if value == parentValue { //fmt.Println("root ========" + text + "-----" + value) node := &TreeNode{ ID: value, Text: text, Parent: parent, } treeNodeList.PushBack(node) rootArr = append(rootArr, node) } else { originNodeList.PushBack(&TreeNode{ ID: value, Text: text, Parent: parent, }) } } } else { for _, params := range paramsArr { value := getStringValueByInterface(params[valueFiled], "") parent := getStringValueByInterface(params[parentField], "") text := getStringValueByInterface(params[textFiled], "") //fmt.Println("========" + text + "-----" + value + "======" + parentValue) if parent == parentValue { //fmt.Println("root ========" + text + "-----" + value) node := &TreeNode{ ID: value, Text: text, Parent: parent, } treeNodeList.PushBack(node) rootArr = append(rootArr, node) } else { originNodeList.PushBack(&TreeNode{ ID: value, Text: text, Parent: parent, }) } } } fmt.Println(len(rootArr)) for ele := treeNodeList.Front(); ele != nil; ele = ele.Next() { treeNode := ele.Value.(*TreeNode) //fmt.Println("=================" + treeNode.ID + "===========" + treeNode.Text) originEle := originNodeList.Front() if originEle == nil { break } flag := false for originEle != nil { originNextEle := originEle.Next() originNode := originEle.Value.(*TreeNode) //fmt.Println("---------------" + originNode.ID + "------------" + originNode.Text) if originNode.Parent == treeNode.ID { flag = true treeNodeList.InsertAfter(originNode, ele) treeNode.Nodes = append(treeNode.Nodes, originNode) originNodeList.Remove(originEle) } else if flag { break } originEle = originNextEle } } this.TreeNodeArray = rootArr return true } func getStringValueByInterface(vali interface{}, nilVal string) string { if vali == nil { return nilVal } return vali.(string) }