package code import ( . "../common" "../db" "errors" "fmt" "io/ioutil" "net/http" "os" "path/filepath" "strings" ) type MakeCode struct { IndexMenus Map TableConfig Map TableColumns map[string]map[string]Map SearchColumns map[string]map[string]Map Config Map Error } func (that *MakeCode) Db2JSON(name string, path string, db db.HoTimeDB) { isMake := false idSlice := Slice{} if that.TableColumns == nil { that.TableColumns = make(map[string]map[string]Map) } if that.SearchColumns == nil { that.SearchColumns = make(map[string]map[string]Map) } //加载配置文件 btes, err := ioutil.ReadFile(path) Config["name"] = name that.Config = DeepCopyMap(Config).(Map) if err == nil { cmap := Map{} //文件是否损坏 cmap.JsonToMap(string(btes), &that.Error) for k, v := range cmap { that.Config[k] = v //程序配置 Config[k] = v //系统配置 } } else { that.Error.SetError(errors.New("配置文件不存在,或者配置出错,使用缺省默认配置")) } that.IndexMenus = Map{} menusConfig := that.Config.GetSlice("menus") //将配置写入到内存中仅作为判断用 if menusConfig != nil { for kmenu, _ := range menusConfig { menu := menusConfig.GetMap(kmenu) if menu != nil { mname := menu.GetString("table") if mname == "" { //如果为空则不是表格 mname = menu.GetString("name") } that.IndexMenus[mname] = menu childMenus := menu.GetSlice("menus") if childMenus != nil { for ckmenu, _ := range childMenus { cmenu := childMenus.GetMap(ckmenu) if cmenu != nil { cname := cmenu.GetString("table") if cmenu.GetString("table") == "" { continue } that.IndexMenus[mname+"/"+cname] = cmenu } } } } } } that.TableConfig = that.Config.GetMap("tables") if that.TableConfig == nil { that.TableConfig = Map{} } for tableName, _ := range that.TableConfig { columns := that.TableConfig.GetMap(tableName).GetSlice("columns") search := that.TableConfig.GetMap(tableName).GetSlice("search") //初始化 if that.TableColumns[tableName] == nil { that.TableColumns[tableName] = map[string]Map{} } //初始化搜索项 if that.SearchColumns[tableName] == nil { that.SearchColumns[tableName] = map[string]Map{} } //注入源数据 for index, _ := range columns { columnsName := columns.GetMap(index).GetString("name") that.TableColumns[tableName][columnsName] = columns.GetMap(index) } //注入search源数据 for index, _ := range search { searchName := search.GetMap(index).GetString("name") that.SearchColumns[tableName][searchName] = search.GetMap(index) } } myInit := strings.Replace(InitTpt, "{{name}}", name, -1) ctrList := "" nowTables := make([]Map, 0) if db.Type == "mysql" { nowTables = db.Select("INFORMATION_SCHEMA.TABLES", "TABLE_NAME as name,TABLE_COMMENT as label", Map{"TABLE_SCHEMA": db.DBName}) } if db.Type == "sqlite" { nowTables = db.Select("sqlite_sequence", "name") } //idSlice=append(idSlice,nowTables) for _, v := range nowTables { if that.TableConfig.GetMap(v.GetString("name")) == nil { if v.GetString("label") == "" { v["label"] = v.GetString("name") } that.TableConfig[v.GetString("name")] = Map{ "label": v.GetString("label"), "table": v.GetString("name"), "auth": []string{"add", "delete", "edit", "info"}, "columns": []Map{}, "search": []Map{ //{"type": "tree", "name": "oid", "label": "组织", "table": "organization", "showName": "label", "children": "children"}, {"type": "search", "name": "keyword", "label": "请输入关键词", "value": nil}, {"type": "search", "name": "daterange", "label": "时间段", "value": nil}, {"type": "search", "name": "sort", "label": "排序", "value": nil}, //{"type": "select", "name": "state", "label": "状态", "value": nil, // "options": []Map{ // {"name": "正常", "value": 0}, // {"name": "异常", "value": 1}, // {"name": "全部", "value": nil}, // }, //}, }, } } //else { // if !(that.TableConfig.GetMap(v.GetString("name")).GetString("label") != "备注" && // v.GetString("label") == "备注") { // that.TableConfig.GetMap(v.GetString("name"))["label"] = v.GetString("label") // } // //} //初始化 if that.TableColumns[v.GetString("name")] == nil { that.TableColumns[v.GetString("name")] = make(map[string]Map) } //初始化 if that.SearchColumns[v.GetString("name")] == nil { that.SearchColumns[v.GetString("name")] = make(map[string]Map) } tableInfo := make([]Map, 0) if db.Type == "mysql" { tableInfo = db.Select("INFORMATION_SCHEMA.COLUMNS", "COLUMN_NAME AS name,COLUMN_TYPE AS type,COLUMN_COMMENT AS label", Map{"AND": Map{"TABLE_SCHEMA": db.DBName, "TABLE_NAME": v.GetString("name")}}) } if db.Type == "sqlite" { tableInfo = db.Query("pragma table_info([" + v.GetString("name") + "]);") } idSlice = append(idSlice, tableInfo) for _, info := range tableInfo { if info.GetString("label") == "" { info["label"] = info.GetString("name") } coloum := that.TableColumns[v.GetString("name")][info.GetString("name")] if coloum == nil { //根据类型判断真实类型 for k, v := range ColumnDataType { if strings.Contains(info.GetString("type"), k) { info["type"] = v break } } coloum = Map{ "name": info.GetString("name"), "type": info.GetString("type"), "label": info.GetString("label"), //"add": false, "info": false, "edit": false, "list": true, //"must": false, } //备注以空格隔开,空格后的是其他备注 indexNum := strings.Index(info.GetString("label"), " ") if indexNum > 0 { coloum["label"] = info.GetString("label")[:indexNum] } for _, v := range ColumnNameType { if (v.Strict && coloum.GetString("name") == v.Name) || strings.Contains(coloum.GetString("name"), v.Name) { //全部都不需要则不加入 if v.Edit == false && v.List == false && v.Info == false { coloum["notUse"] = true break } if v.Info == false { coloum["info"] = v.Info } if v.Edit == false { coloum["edit"] = v.Edit coloum["add"] = v.Edit } if v.List == false { coloum["list"] = v.List } if v.Must == true { coloum["must"] = v.Must } if v.Type != "" { coloum["type"] = v.Type } break } } //如果是select类型需要设置options if coloum.GetString("type") == "number" { coloum["sortable"] = true } //如果是select类型需要设置options if coloum.GetString("type") == "select" { options := Slice{} comments := strings.Split(info.GetString("label"), " ") if len(comments) >= 2 { optionComment := strings.Split(comments[1], ",") for _, v := range optionComment { optionSlice := strings.Split(v, "-") if len(optionSlice) >= 2 { options = append(options, Map{"name": optionSlice[1], "value": optionSlice[0]}) } } } coloum["options"] = options } if !coloum.GetBool("notUse") { that.TableConfig.GetMap(v.GetString("name"))["columns"] = append(that.TableConfig.GetMap(v.GetString("name")).GetSlice("columns"), coloum) } } //else { // // //if !(coloum.GetString("label") != "备注" && info.GetString("label") == "备注") { // // coloum["label"] = info.GetString("label") // //} // //coloum["type"] = info.GetString("type") //} //暂时不关闭参数,保证表数据完全读取到 that.TableColumns[v.GetString("name")][info.GetString("name")] = coloum } //创建模块文件 //判断文件是否存在 //_, err := os.OpenFile(name+"/"+v.GetString("name"), os.O_RDONLY, os.ModePerm) _, err := os.Stat(name + "/" + v.GetString("name") + ".go") if err != nil { //文件不存在,则根据模板创建 myCtr := strings.Replace(CtrTpt, "{{name}}", name, -1) myCtr = strings.Replace(myCtr, "{{table}}", v.GetString("name"), -1) _ = os.MkdirAll(name, os.ModeDir) err = ioutil.WriteFile(name+"/"+v.GetString("name")+".go", []byte(myCtr), os.ModePerm) if err != nil { that.Error.SetError(err) } isMake = true } ctrList = ctrList + `"` + v.GetString("name") + `":` + v.GetString("name") + "Ctr,\r\n " } that.Config["tables"] = that.TableConfig //生成id,判断数据库是否有改变,以保证数据库和配置文件匹配唯一 id := Md5(ObjToStr(idSlice)) if id == that.Config.GetString("id") { if isMake { //有生成包文件 fmt.Println("有新的业务代码生成,请重新运行") os.Exit(-1) } return } //数据生成完后进一步解析 for fk, fv := range that.TableColumns { //判断是否将表写入menu中 isMenusGet := false //判断是否被目录收录 for indexKey, _ := range that.IndexMenus { indexCode := strings.Index(indexKey, fk) //如果相等或者表名在目录中已经设置(主要前一位是/并且他是最后一个字符串) if indexKey == fk || (indexCode != -1 && indexKey[indexCode-1] == '/' && indexKey[indexCode:] == fk) { isMenusGet = true break } } //目录没有收录 if !isMenusGet { tablePrefixCode := strings.Index(fk, "_") isNewPrefix := false //假定表名没有前缀 prefixName := "" //并且代表有前缀,根据数据表分库设定使用 if tablePrefixCode != -1 { prefixName = fk[:tablePrefixCode] } if tablePrefixCode != -1 { for ck, _ := range that.TableColumns { //判断不止一个前缀相同 if strings.Index(ck, prefixName) == 0 && ck != prefixName && ck != fk { isNewPrefix = true break } } } menuIns := Map{"label": that.TableConfig.GetMap(fk).GetString("label"), "table": fk} //多耗费一点内存 mMenu := Map{"menus": Slice{menuIns}, "label": that.TableConfig.GetMap(fk).GetString("label"), "name": prefixName, "icon": "el-icon-setting"} //表名有前缀 if !isNewPrefix { //是否已有对应前缀,已经有对应的menu只需要push进去即可 prefixName = DefaultMenuParentName mMenu = Map{"menus": Slice{menuIns}, "label": "系统管理", "name": prefixName, "icon": "el-icon-setting"} } //没有新前缀 if that.IndexMenus[prefixName] != nil { that.IndexMenus.GetMap(prefixName)["menus"] = append(that.IndexMenus.GetMap(prefixName).GetSlice("menus"), menuIns) that.IndexMenus[prefixName+"/"+fk] = menuIns } else { that.Config["menus"] = append(that.Config.GetSlice("menus"), mMenu) //注入配置 //写入Index that.IndexMenus[prefixName] = mMenu that.IndexMenus[prefixName+"/"+fk] = menuIns } } for k, v := range fv { //搜索服务 if that.SearchColumns[fk][v.GetString("name")] == nil && v.GetString("type") == "select" { search := that.TableConfig.GetMap(fk).GetSlice("search") sv := DeepCopyMap(v).(Map) sv["value"] = nil sv["options"] = append(sv.GetSlice("options"), Map{"name": "全部", "value": nil}) that.TableConfig.GetMap(fk)["search"] = append(search, sv) } //虚招后缀是_id结尾的表字段 假设org_id if len(k) <= 3 || strings.LastIndex(k, "_id") != len(k)-3 { continue } //普通表匹配 org_id匹配为org oldTableName := k[:len(k)-3] //上级ID匹配 if oldTableName == "parent" { oldTableName = fk } //如果依然找不到则查询system_org是否存在 if that.TableConfig[DefaultMenuParentName+"_"+oldTableName] != nil { oldTableName = DefaultMenuParentName + "_" + oldTableName } //字段有动词前缀,自动进行解析 prefixColumn := strings.Index(oldTableName, "_") //sys_org_id oldTableName即为sys此处判断为org表存在 if prefixColumn > -1 && that.TableConfig[oldTableName[prefixColumn+1:]] != nil { oldTableName = oldTableName[prefixColumn+1:] } //如果依然找不到则查询system_org是否存在 if prefixColumn > -1 && that.TableConfig[DefaultMenuParentName+"_"+oldTableName[prefixColumn+1:]] != nil { oldTableName = DefaultMenuParentName + "_" + oldTableName[prefixColumn+1:] } //普通方式查询不到,则转换为大型项目模块划分,暂时只支持一级模块划分, //比如表sys_user 字段org_id,查询不到sys_org表则查询org表,org表查询不到则查询默认前缀system_org表 //都查询不到则找不到, prefix := strings.Index(fk, "_") tableName := oldTableName if prefix > 0 { //表模块前缀sys_user sys即为前缀 sys_org tableName = fk[:prefix+1] + oldTableName if that.TableConfig[tableName] == nil { //不存在则改为org tableName = oldTableName } //表前缀+去除字段前缀 prefixColumn := strings.Index(oldTableName, "_") if prefixColumn > -1 { tableName = fk[:prefix+1] + oldTableName[prefixColumn+1:] if that.TableConfig[tableName] == nil { tableName = oldTableName } } } //如果数据匹配则写入到配置中 if that.TableConfig[tableName] != nil { v["link"] = tableName //一般查询name字段或者label字段,如果没有name字段则默认第二个地段 if that.TableColumns[tableName]["name"] != nil { v["value"] = "name" continue } if that.TableColumns[tableName]["label"] != nil { v["value"] = "label" continue } if len(that.TableConfig.GetMap(tableName).GetSlice("columns")) > 2 { v["value"] = that.TableConfig.GetMap(tableName).GetSlice("columns").GetMap(1).GetString("name") continue } } } } fmt.Println(id, "---", that.Config.GetString("id")) that.Config["id"] = id //init文件初始化 myInit = strings.Replace(myInit, "{{id}}", id, -1) myInit = strings.Replace(myInit, "{{tablesCtr}}", ctrList, -1) _ = os.MkdirAll(name, os.ModeDir) err = ioutil.WriteFile(name+"/init.go", []byte(myInit), os.ModePerm) if err != nil { that.Error.SetError(err) } //写入配置文件 //var configByte bytes.Buffer //err = json.Indent(&configByte, []byte(that.Config.ToJsonString()), "", "\t") _ = os.MkdirAll(filepath.Dir(path), os.ModeDir) err = ioutil.WriteFile(path, []byte(that.Config.ToJsonString()), os.ModePerm) if err != nil { that.Error.SetError(err) } fmt.Println("有新的代码生成,请重新运行") os.Exit(-1) } func (that *MakeCode) Info(table string) string { reStr := "" for _, v := range that.TableColumns[table] { if v == nil { continue } if v.Get("info") == nil || v.GetBool("info") { reStr += v.GetString("name") + "," } } if len(reStr) != 0 { reStr = reStr[:len(reStr)-1] } return reStr } func (that *MakeCode) Add(table string, req *http.Request) Map { data := Map{} for _, v := range that.TableColumns[table] { //不可使用,未在前端展示,但在内存中保持有 if v.GetBool("notUse") { continue } if v.Get("add") == nil || v.GetBool("add") { reqValue := req.FormValue(v.GetString("name")) if reqValue == "" { return nil } data[v.GetString("name")] = reqValue } } if len(data) == 0 { return nil } return data } func (that *MakeCode) Edit(table string, req *http.Request) Map { data := Map{} for _, v := range that.TableColumns[table] { //不可使用,未在前端展示,但在内存中保持有 if v.GetBool("notUse") { continue } if v.Get("edit") == nil || v.GetBool("edit") { reqValue := req.FormValue(v.GetString("name")) if reqValue == "" { continue } data[v.GetString("name")] = reqValue } } if len(data) == 0 { return nil } return data } func (that *MakeCode) Search(table string, req *http.Request, db *db.HoTimeDB) (string, Map, Map) { reStr := "" leftJoin := Map{} data := Map{} keyword := Map{} daterange := Map{} sort := Map{} keywordStr := req.FormValue("keyword") for _, v := range that.TableColumns[table] { //不可使用,未在前端展示,但在内存中保持有 if v.GetBool("notUse") { continue } if v["list"] != false { if v.GetString("link") != "" && v.GetString("name") != "parent_id" { reStr += v.GetString("link") + "." + v.GetString("value") + " AS " + v.GetString("link") + "_" + v.GetString("name") + "_" + v.GetString("value") + "," leftJoin["[>]"+v.GetString("link")] = table + "." + v.GetString("name") + "=" + v.GetString("link") + ".id" } else { reStr += table + "." + v.GetString("name") + "," } if keywordStr != "" { if v.GetString("type") == "text" { keyword[table+"."+v.GetString("name")+"[~]"] = keywordStr } if v.GetString("name") == "id" { keyword[table+"."+v.GetString("name")] = keywordStr } if v.GetString("link") != "" && v.GetString("name") != "parent_id" { childs := db.Select(v.GetString("link"), "id", Map{v.GetString("value") + "[~]": keywordStr}) childIds := Slice{} for _, cv := range childs { childIds = append(childIds, cv.GetString("id")) } if len(childIds) != 0 { keyword[v.GetString("link")+".id"] = childIds } } } } } if len(reStr) != 0 { reStr = reStr[:len(reStr)-1] } search := that.TableConfig.GetMap(table).GetSlice("search") for k, _ := range search { reqValue := req.FormValue(search.GetMap(k).GetString("name")) if reqValue == "" { continue } searchItem := search.GetMap(k) searchItemName := searchItem.GetString("name") //columns := that.TableConfig.GetMap(table).GetSlice("columns") if searchItem.GetString("type") == "search" { for _, v := range that.TableColumns[table] { if v["list"] == false { continue } //日期类型 if searchItemName == "daterange" && v.GetString("type") == "time" { fmt.Println(req.Form["daterange"]) daterange[table+"."+v.GetString("name")+"[<>]"] = ObjToSlice(req.Form["daterange"]) } } if searchItem.GetString("name") == "sort" { sort["ORDER"] = table + "." + reqValue } continue } data[searchItemName] = reqValue } //树节点模式搜索 if req.Form["parent_id"] != nil { parentID := ObjToInt(req.FormValue("parent_id")) if parentID == 0 { data["OR"] = Map{table + ".parent_id[#]": 0, table + ".parent_id": nil} } else { data[table+".parent_id"] = parentID } } where := Map{} if len(keyword) == 1 { for k, v := range keyword { data[k] = v } } if len(keyword) > 1 { if data["OR"] != nil { data = Map{"AND": data, "OR": keyword} } else { data["OR"] = keyword } } if len(daterange) == 1 { for k, v := range daterange { data[k] = v } } if len(daterange) > 1 { if data["AND"] != nil { data = Map{"AND": Map{"AND": data, "OR": daterange}} } } if len(data) > 1 { where["AND"] = data } if len(data) == 1 { where = data } if len(sort) != 0 { for k, v := range sort { where[k] = v } } return reStr, leftJoin, where }