iedc-go/code/makecode.go
2021-09-12 05:35:14 +08:00

720 lines
20 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}
}
if db==nil{
return
}
//数据库反哺
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 v.GetString("name") == "cached" {
continue
}
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) || strings.Contains(info.GetString("name"), 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) || (!v.Strict && 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
}
if !coloum.GetBool("notUse") {
that.TableConfig.GetMap(v.GetString("name"))["columns"] = append(that.TableConfig.GetMap(v.GetString("name")).GetSlice("columns"), coloum)
}
//如果是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]})
}
}
}
if coloum.GetString("type") == "select" {
coloum["must"] = true
coloum["options"] = options
} else if len(options) > 0 {
coloum["must"] = true
coloum["options"] = options
coloum["type"] = "select"
}
//}
}
//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)
that.SearchColumns[fk][k] = 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 || that.TableConfig[oldTableName] != 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
}
}
}
}
//搜索增加树节点
for fk, fv := range that.TableColumns {
for k, v := range fv {
if v.GetString("link") != "" && that.SearchColumns[fk][k] == nil &&
that.TableColumns[v.GetString("link")]["parent_id"] != nil {
//搜索服务
search := that.TableConfig.GetMap(fk).GetSlice("search")
sv := Map{"type": "tree", "label": v["label"], "name": v["name"], "value": v["value"], "link": v["link"]}
that.TableConfig.GetMap(fk)["search"] = append(search, sv)
that.SearchColumns[fk][k] = sv
}
}
}
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") {
if len(req.Form[v.GetString("name")]) == 0 {
return nil
}
reqValue := req.FormValue(v.GetString("name"))
if (reqValue == "" || reqValue == "null") && strings.Contains(v.GetString("name"), "id") {
data[v.GetString("name")] = nil
} else {
if v.GetString("type") == "password" {
data[v.GetString("name")] = Md5(reqValue)
} else {
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 == "" || reqValue == "null" {
continue
}
if v.GetString("type") == "password" {
data[v.GetString("name")] = Md5(reqValue)
} else {
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
}
//树节点模式搜索
if searchItemName == "parent_id" {
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
}
continue
}
data[table+"."+searchItemName] = reqValue
}
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
}