Files
hotime/code/makecode.go
T
hoteas 3e08b20698 fix(makecode): 达梦列注释按 OWNER 对齐,并兼容选项解析边界
同时修复新增默认 state、导出 sheet 名长度与目录权限。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 05:36:37 +08:00

1407 lines
42 KiB
Go
Raw Permalink 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 (
. "code.hoteas.com/golang/hotime/common"
"code.hoteas.com/golang/hotime/db"
"code.hoteas.com/golang/hotime/log"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"sort"
"strings"
"time"
)
type MakeCode struct {
FileConfig Map
IndexMenus Map
TableConfig Map
TableColumns map[string]map[string]Map
SearchColumns map[string]map[string]Map
Config Map
RuleConfig []Map
Log *log.Logger
}
func (that *MakeCode) Db2JSON(db *db.HoTimeDB, config Map) {
isMake := false
//hasConfigFile := false
idSlice := Slice{}
that.FileConfig = config
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(config.GetString("config"))
var err error
that.Config = DeepCopyMap(Config).(Map)
that.Config["name"] = config.GetString("table")
//加载规则文件
btesRule, errRule := ioutil.ReadFile(config.GetString("rule"))
that.RuleConfig = []Map{}
if errRule == nil {
//cmap := Map{}
//文件是否损坏
ruleLis := ObjToSlice(string(btesRule))
//cmap.JSON()
for k, _ := range ruleLis {
that.RuleConfig = append(that.RuleConfig, ruleLis.GetMap(k))
}
} else {
for _, v := range RuleConfig {
that.RuleConfig = append(that.RuleConfig, ObjToMap(DeepCopyMap(v)))
}
if db != nil {
_ = os.MkdirAll(filepath.Dir(config.GetString("rule")), os.ModeDir)
err = ioutil.WriteFile(config.GetString("rule"), []byte(ObjToStr(that.RuleConfig)), os.ModePerm)
if err != nil {
that.Log.Error().Err(err).Msg("写入 rule 配置文件失败")
}
}
that.Log.Warnf("rule配置文件不存在或配置出错,使用缺省默认配置")
}
that.IndexMenus = Map{}
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}}", config.GetString("table"), -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_master", "name", Map{"type": "table"})
}
if db.Type == "dm" || db.Type == "dameng" {
nowTables = db.Query(`SELECT TABLE_NAME AS "name", COMMENTS AS "label" FROM ALL_TAB_COMMENTS WHERE TABLE_TYPE='TABLE' AND OWNER='` + db.DBName + `'`)
}
//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")
}
if strings.HasSuffix(v.GetString("label"), "表") {
withoutTable := strings.TrimSuffix(v.GetString("label"), "表")
if len([]rune(withoutTable)) <= 3 {
v["label"] = withoutTable + "管理"
} else {
v["label"] = withoutTable
}
}
that.TableConfig[v.GetString("name")] = Map{
"label": v.GetString("label"),
"table": v.GetString("name"),
"auth": []string{"show", "add", "delete", "edit", "info", "download"},
"columns": []Map{},
"search": []Map{
{"type": "search", "name": "keywordtable", "label": "筛选", "options": Slice{Map{"name": "无", "value": nil}}, "value": nil},
{"type": "search", "name": "daterangetable", "label": "筛选", "options": Slice{Map{"name": "无", "value": nil}}, "value": nil},
{"type": "search", "name": "keyword", "label": "请输入关键词", "value": nil},
{"type": "search", "name": "daterange", "label": "时间段", "value": nil},
{"type": "search", "name": "sort", "label": "排序", "value": nil},
},
}
if v.GetString("name") == "logs" {
that.TableConfig.GetMap(v.GetString("name"))["auth"] = []string{"show", "download"}
}
}
//初始化
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,IS_NULLABLE AS must,COLUMN_DEFAULT AS dflt_value", Map{"AND": Map{"TABLE_SCHEMA": db.DBName, "TABLE_NAME": v.GetString("name")}, "ORDER": "ORDINAL_POSITION"})
}
if db.Type == "sqlite" {
tableInfo = db.Query("pragma table_info([" + v.GetString("name") + "]);")
}
if db.Type == "dm" || db.Type == "dameng" {
// 必须用 ALL_COL_COMMENTS 并按 OWNER 对齐:USER_COL_COMMENTS 无 schema
// 在 SYSDBA 下常混入同名表空注释或读不到业务库(如 login_config)列备注。
tableInfo = db.Query(`SELECT c.COLUMN_NAME AS "name", c.DATA_TYPE AS "type", m.COMMENTS AS "label", c.NULLABLE AS "must", c.DATA_DEFAULT AS "dflt_value" FROM ALL_TAB_COLUMNS c LEFT JOIN ALL_COL_COMMENTS m ON c.OWNER=m.OWNER AND c.TABLE_NAME=m.TABLE_NAME AND c.COLUMN_NAME=m.COLUMN_NAME WHERE c.TABLE_NAME='` + v.GetString("name") + `' AND c.OWNER='` + db.DBName + `' ORDER BY c.COLUMN_ID`)
}
idSlice = append(idSlice, tableInfo)
for _, info1 := range tableInfo {
info := DeepCopyMap(info1).(Map)
if info.GetString("label") == "" {
info["label"] = info.GetString("name")
}
coloum := that.TableColumns[v.GetString("name")][info.GetString("name")]
if coloum == nil {
//根据类型判断真实类型
for k, v1 := range ColumnDataType {
if strings.Contains(strings.ToLower(info.GetString("type")), k) {
info["type"] = v1
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,
}
if info.GetString("must") == "NO" {
coloum["must"] = true
}
if info["dflt_value"] != nil {
coloum["default"] = info["dflt_value"]
}
if info["pk"] != nil && info.GetCeilInt64("pk") == 1 {
coloum["must"] = true
}
//提取括号内的提示信息:支持 ()、()、{}
rawLabel := info.GetString("label")
for _, pair := range [][2]string{{"(", ")"}, {"", ""}, {"{", "}"}} {
start := strings.Index(rawLabel, pair[0])
end := strings.Index(rawLabel, pair[1])
if start != -1 && end > start {
coloum["ps"] = rawLabel[start+len(pair[0]) : end]
rawLabel = rawLabel[:start] + rawLabel[end+len(pair[1]):]
break
}
}
//空格截断,空格后的内容丢弃
if idx := strings.Index(rawLabel, " "); idx > -1 {
rawLabel = rawLabel[:idx]
}
//冒号截断,去除选项数据部分
if idx := strings.Index(rawLabel, ":"); idx > -1 {
rawLabel = rawLabel[:idx]
}
coloum["label"] = rawLabel
for _, ColumnName := range that.RuleConfig {
if (ColumnName.GetBool("strict") && coloum.GetString("name") == ColumnName.GetString("name")) ||
(!ColumnName.GetBool("strict") && strings.Contains(coloum.GetString("name"), ColumnName.GetString("name"))) ||
(v.GetString("name")+"."+coloum.GetString("name") == ColumnName.GetString("name")) {
//全部都不需要则不加入
if ColumnName.GetBool("edit") == false && ColumnName.GetBool("list") == false && ColumnName.GetBool("info") == false {
coloum["notUse"] = true
//continue
}
coloum["info"] = ColumnName.GetBool("info")
coloum["edit"] = ColumnName.GetBool("edit")
coloum["add"] = ColumnName["add"]
coloum["list"] = ColumnName.GetBool("list")
//coloum["must"] = ColumnName.GetBool("must")
if coloum["must"] == nil {
coloum["must"] = ColumnName.GetBool("must")
} else {
if ColumnName["must"] != nil {
coloum["must"] = ColumnName.GetBool("must")
}
}
if ColumnName.GetBool("info") {
delete(coloum, "info")
}
if ColumnName.GetBool("edit") {
delete(coloum, "edit")
}
if ColumnName["add"] == nil || ColumnName.GetBool("add") {
delete(coloum, "add")
}
if ColumnName.GetBool("list") {
delete(coloum, "list")
}
if !ColumnName.GetBool("must") {
delete(coloum, "must")
}
if ColumnName.GetString("type") != "" {
if ColumnName.GetString("type") == "time" && coloum["type"] == "number" {
coloum["type"] = "unixTime"
} else {
coloum["type"] = ColumnName.GetString("type")
}
}
if ColumnName.GetBool("strict") && coloum.GetString("name") == ColumnName.GetString("name") {
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 {
// 截掉空格后附加说明 / {} 提示,避免污染 options 解析
optPart := comments[1]
if idx := strings.Index(optPart, " "); idx > -1 {
optPart = optPart[:idx]
}
for _, pair := range [][2]string{{"{", "}"}, {"(", ")"}, {"", ""}} {
if start := strings.Index(optPart, pair[0]); start != -1 {
optPart = optPart[:start]
break
}
}
optionComment := strings.Split(optPart, ",")
for _, v := range optionComment {
v = strings.TrimSpace(v)
if v == "" {
continue
}
// 兼容规范「值-名称」与存量「值=名称」
sep := -1
for i, r := range v {
if r == '-' || r == '=' {
sep = i
break
}
}
if sep > 0 && sep < len(v)-1 {
options = append(options, Map{"name": strings.TrimSpace(v[sep+1:]), "value": strings.TrimSpace(v[:sep])})
}
}
}
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 {
//对已有配置列也提取 ps 并清理 label
rawLabel := coloum.GetString("label")
for _, pair := range [][2]string{{"(", ")"}, {"", ""}, {"{", "}"}} {
start := strings.Index(rawLabel, pair[0])
end := strings.Index(rawLabel, pair[1])
if start != -1 && end > start {
coloum["ps"] = rawLabel[start+len(pair[0]) : end]
rawLabel = rawLabel[:start] + rawLabel[end+len(pair[1]):]
break
}
}
if idx := strings.Index(rawLabel, " "); idx > -1 {
rawLabel = rawLabel[:idx]
}
if idx := strings.Index(rawLabel, ":"); idx > -1 {
rawLabel = rawLabel[:idx]
}
coloum["label"] = rawLabel
}
//暂时不关闭参数,保证表数据完全读取到
that.TableColumns[v.GetString("name")][info.GetString("name")] = coloum
}
if config.GetInt("mode") != 0 {
//创建模块文件
//判断文件是否存在
//_, err := os.OpenFile(name+"/"+v.GetString("name"), os.O_RDONLY, os.ModePerm)
_, err := os.Stat(config.GetString("name") + "/" + v.GetString("name") + ".go")
if err != nil { //文件不存在,则根据模板创建
myCtr := strings.Replace(CtrTpt, "{{name}}", config.GetString("name"), -1)
myCtr = strings.Replace(myCtr, "{{table}}", v.GetString("name"), -1)
_ = os.MkdirAll(config.GetString("name"), os.ModeDir)
err = ioutil.WriteFile(config.GetString("name")+"/"+v.GetString("name")+".go", []byte(myCtr), os.ModePerm)
if err != nil {
that.Log.Error().Err(err).Msg("写入代码文件失败")
}
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 {
//目录没有收录
//if !isMenusGet {
//if !hasConfigFile {
tablePrefixCode := strings.Index(fk, "_")
isNewPrefix := false //假定表名没有前缀
prefixName := ""
//并且代表有前缀,根据数据表分库设定使用
if tablePrefixCode != -1 {
prefixName = fk[:tablePrefixCode]
} else {
prefixName = fk
}
//if tablePrefixCode != -1 {
for ck, _ := range that.TableColumns {
//判断不止一个前缀相同
if (strings.Index(ck, prefixName) == 0 || strings.Index(prefixName, ck) == 4) && ck != fk {
isNewPrefix = true
break
}
}
//}
prefixName = DefaultMenuParentName + ":" + prefixName
menuIns := Map{"label": that.TableConfig.GetMap(fk).GetString("label"), "table": fk, "auth": that.TableConfig.GetMap(fk).GetSlice("auth")}
//多耗费一点内存
mMenu := Map{"menus": Slice{menuIns}, "auth": Slice{"show"}, "label": that.TableConfig.GetMap(fk).GetString("label"), "name": prefixName, "icon": "Setting"}
//表名有前缀
if !isNewPrefix {
//是否已有对应前缀,已经有对应的menu只需要push进去即可
prefixName = DefaultMenuParentName
mMenu = Map{"menus": Slice{menuIns}, "auth": Slice{"show"}, "label": "系统管理", "name": prefixName, "icon": "Setting"}
}
//没有新前缀
if that.IndexMenus[prefixName] != nil {
if that.IndexMenus[prefixName+"/"+fk] == nil {
that.IndexMenus.GetMap(prefixName)["menus"] = append(that.IndexMenus.GetMap(prefixName).GetSlice("menus"), menuIns)
that.IndexMenus[prefixName+"/"+fk] = menuIns
} else {
for k, v := range menuIns {
that.IndexMenus.GetMap(prefixName + "/" + fk)[k] = v
}
}
} else {
that.Config["menus"] = append(that.Config.GetSlice("menus"), mMenu) //注入配置
//写入Index
that.IndexMenus[prefixName] = mMenu
that.IndexMenus[prefixName+"/"+fk] = menuIns
}
//}
search := that.TableConfig.GetMap(fk).GetSlice("search")
for k, v := range fv {
//虚招后缀是_id结尾的表字段 假设org_id
if !(len(k) <= 3 || strings.LastIndex(k, "_id") != len(k)-3) {
//普通表匹配 org_id匹配为org
oldTableName := k[:len(k)-3]
//上级ID匹配
if oldTableName == "parent" {
oldTableName = fk
}
//如果本身匹配则不再继续精简匹配
if that.TableConfig[oldTableName] == nil {
//如果依然找不到则查询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:]
}
if prefixColumn >= len(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
}
tempC := that.TableConfig.GetMap(tableName).GetSlice("columns")
isGet := true
for k2, _ := range tempC {
if strings.Contains(tempC.GetMap(k2).GetString("name"), "name") || strings.Contains(tempC.GetMap(k2).GetString("name"), "title") {
v["value"] = tempC.GetMap(k2).GetString("name")
isGet = false
break
}
}
if isGet && len(that.TableConfig.GetMap(tableName).GetSlice("columns")) > 2 {
v["value"] = that.TableConfig.GetMap(tableName).GetSlice("columns").GetMap(1).GetString("name")
continue
}
}
}
//搜索服务
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})
search = append(search, sv)
that.TableConfig.GetMap(fk)["search"] = search
that.SearchColumns[fk][k] = sv
}
//搜索关键字
if strings.Contains(v.GetString("type"), "text") || v.GetString("name") == "id" {
keyWordSearchData := search.GetMap(0)
keyWordSearchData["options"] = append(keyWordSearchData.GetSlice("options"), Map{"name": v.GetString("label"), "value": v.GetString("name")})
search[0] = keyWordSearchData
}
if v.GetString("link") != "" &&
v.GetString("name") != "parent_id" {
keyWordSearchData := search.GetMap(0)
name := strings.Replace(that.TableConfig.GetMap(v.GetString("link")).GetString("label"), "管理", "", -1)
keyWordSearchData["options"] = append(keyWordSearchData.GetSlice("options"), Map{"name": name, "value": v.GetString("name")})
search[0] = keyWordSearchData
}
//搜索时间
if strings.Contains(v.GetString("type"), "time") {
daterangeData := search.GetMap(1)
daterangeData["options"] = append(daterangeData.GetSlice("options"), Map{"name": v.GetString("label"), "value": v.GetString("name")})
search[1] = daterangeData
}
}
}
flow := Map{}
//"user": {"table": "user", "stop": true,
// "SQL": {
// "role_id": "role_id",
// "admin_id": "admin_id",
// "parent_ids": "%,user_id,%"}}
//搜索增加树节点
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
}
//if fk == that.FileConfig.GetString("table") && v["link"] != nil && that.TableColumns[v.GetString("link")]["parent_id"] != nil {
// that.Config["stop"] = append(that.Config.GetSlice("stop"), v.GetString("link"))
// //that.
//}
for _, av := range that.TableColumns[that.FileConfig.GetString("table")] {
//同字段
if av["link"] != nil && av.GetString("link") == v.GetString("link") {
if flow[fk] == nil {
flow[fk] = Map{"table": fk, "stop": false, "sql": Map{}}
}
sql := flow.GetMap(fk).GetMap("sql")
if k == "parent_id" {
sql["parent_ids[~]"] = "," + av.GetString("name") + ","
} else {
sql[k] = k
}
flow.GetMap(fk)["sql"] = sql
}
//同表
if av["link"] != nil && av.GetString("link") == fk {
if flow[fk] == nil {
flow[fk] = Map{"table": fk, "stop": false, "sql": Map{}}
}
ta := flow.GetMap(fk)
ta["stop"] = true
flow[fk] = ta
if k == "id" && that.TableColumns[fk]["parent_id"] == nil {
sql := flow.GetMap(fk).GetMap("sql")
sql[k] = av.GetString("name")
flow.GetMap(fk)["sql"] = sql
}
}
}
if k == that.FileConfig.GetString("table")+"_id" {
if flow[fk] == nil {
flow[fk] = Map{"table": fk, "stop": false, "sql": Map{}}
}
sql := flow.GetMap(fk).GetMap("sql")
sql[k] = "id"
flow.GetMap(fk)["sql"] = sql
}
//当前用户
if k == "parent_id" && that.FileConfig.GetString("table") == fk {
if flow[fk] == nil {
flow[fk] = Map{"table": fk, "stop": false, "sql": Map{}}
}
sql := flow.GetMap(fk).GetMap("sql")
sql["parent_ids[~]"] = ",id,"
flow.GetMap(fk)["sql"] = sql
}
}
}
//fmt.Println(flow)
that.Config["flow"] = flow
//fmt.Println(id, "---", that.Config.GetString("id"))
//that.Config["id"] = id
if config.GetInt("mode") != 0 {
//init文件初始化
//myInit = strings.Replace(myInit, "{{id}}", id, -1)
myInit = strings.Replace(myInit, "{{tablesCtr}}", ctrList, -1)
_ = os.MkdirAll(config.GetString("name"), os.ModeDir)
err = ioutil.WriteFile(config.GetString("name")+"/init.go", []byte(myInit), os.ModePerm)
if err != nil {
that.Log.Error().Err(err).Msg("写入 init.go 失败")
}
}
//配置文件
if config.GetString("configDB") != "" {
that.Config["id"] = id
_ = os.MkdirAll(filepath.Dir(config.GetString("configDB")), os.ModeDir)
err = ioutil.WriteFile(config.GetString("configDB"), []byte(that.Config.ToJsonString()), os.ModePerm)
if err != nil {
that.Log.Error().Err(err).Msg("写入 configDB 文件失败")
}
that.Log.Infof("新建 configDB: %s", config.GetString("configDB"))
}
//不存在配置文件则生成,存在则不管
_, err = ioutil.ReadFile(config.GetString("config"))
if err != nil {
that.Config["id"] = id
_ = os.MkdirAll(filepath.Dir(config.GetString("config")), os.ModeDir)
newConfig := DeepCopyMap(that.Config).(Map)
delete(newConfig, "tables")
err = ioutil.WriteFile(config.GetString("config"), []byte(newConfig.ToJsonString()), os.ModePerm)
if err != nil {
that.Log.Error().Err(err).Msg("写入 config 文件失败")
}
that.Log.Infof("新建 config: %s", config.GetString("config"))
}
//fmt.Println("有新的代码生成,请重新运行")
//os.Exit(-1)
}
func (that *MakeCode) Info(table string, userData Map, db *db.HoTimeDB) (string, Map) {
reStr := ""
data := Map{}
var ruleData Map
testQu := []string{}
testQuData := that.TableColumns[table]
for key, _ := range testQuData {
//fmt.Println(key, ":", value)
testQu = append(testQu, key)
}
sort.Strings(testQu)
for _, k := range testQu {
v := testQuData[k]
if v == nil {
continue
}
//准备加入索引权限
if v.GetString("link") != "" &&
userData != nil &&
that.TableColumns[v.GetString("link")]["parent_id"] != nil {
//初始化ruleData
if ruleData == nil {
ruleData = Map{}
for _, v := range that.TableColumns[that.FileConfig.GetString("table")] {
if v.GetString("link") != "" &&
v.GetString("name") != "parent_id" &&
userData.Get(v.GetString("name")) != nil {
ruleData[v.GetString("link")] = userData.Get(v.GetString("name"))
}
}
}
if ruleData[v.GetString("link")] != nil {
parent_idsStr := ""
parent_ids := that.TableColumns[v.GetString("link")]["parent_ids"]
if parent_ids != nil {
parent_idsStr = "parent_ids[~]"
}
index := that.TableColumns[v.GetString("link")]["index"]
if index != nil {
parent_idsStr = "index[~]"
}
if v.GetString("name") == "parent_id" {
data[parent_idsStr] = "," + ruleData.GetString(v.GetString("link")) + ","
} else {
idMap := db.Select(v.GetString("link"), "id", Map{parent_idsStr: "," + ruleData.GetString(v.GetString("link")) + ","})
ids := Slice{ruleData.GetCeilInt(v.GetString("link"))}
for _, v := range idMap {
ids = append(ids, v.GetCeilInt("id"))
}
data[v.GetString("name")] = ids
}
}
}
if v.Get("info") == nil || v.GetBool("info") {
reStr += "`" + v.GetString("name") + "`,"
}
}
if len(reStr) != 0 {
reStr = reStr[:len(reStr)-1]
}
return reStr, data
}
func (that *MakeCode) Add(table string, user Map, req *http.Request) Map {
data := Map{}
for _, v := range that.TableColumns[table] {
//不可使用,未在前端展示,但在内存中保持有
if v.GetBool("notUse") {
if v.GetString("type") == "index" && that.TableColumns[table]["parent_id"] != nil {
data[v.GetString("name")] = ","
}
continue
}
if v.Get("add") == nil || v.GetBool("add") {
if len(req.Form[v.GetString("name")]) == 0 || req.FormValue(v.GetString("name")) == "" {
if v["link"] != nil && user[v.GetString("name")] != nil {
data[v.GetString("name")] = user[v.GetString("name")]
continue
}
if that.FileConfig.GetString("table")+"_id" == v.GetString("name") {
data[v.GetString("name")] = user["id"]
continue
}
//if user[v.GetString("name")] != nil {
//
// data[v.GetString("name")] = user[v.GetString("name")]
// continue
//
//}
if v.GetBool("must") {
return nil
} else {
continue
}
}
if req.Form[v.GetString("name")] == nil {
continue
}
reqValue := req.FormValue(v.GetString("name"))
if reqValue == "null" {
data[v.GetString("name")] = nil
continue
}
if v.GetString("type") == "password" {
data[v.GetString("name")] = Md5(reqValue)
continue
}
data[v.GetString("name")] = reqValue
}
//sn则自动生成
if v.GetString("name") == "sn" {
reqValue := req.FormValue(v.GetString("name"))
if reqValue == "" {
data[v.GetString("name")] = Md5(ObjToStr(time.Now().UnixNano()))
} else {
data[v.GetString("name")] = reqValue
}
}
if v.GetString("name") == "create_time" {
if v.GetString("type") == "unixTime" {
data[v.GetString("name")] = time.Now().Unix()
}
if v.GetString("type") == "time" {
data[v.GetString("name")] = time.Now().Format("2006-01-02 15:04:05")
}
continue
}
if v.GetString("name") == "modify_time" {
if v.GetString("type") == "unixTime" {
data[v.GetString("name")] = time.Now().Unix()
}
if v.GetString("type") == "time" {
data[v.GetString("name")] = time.Now().Format("2006-01-02 15:04:05")
}
}
}
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") {
//if v.GetString("type") == "index" && that.TableColumns[table]["parent_id"] != nil {
// data[v.GetString("name")] = ","
//}
continue
}
if v.Get("edit") == nil || v.GetBool("edit") {
if len(req.Form[v.GetString("name")]) == 0 {
continue
}
reqValue := req.FormValue(v.GetString("name"))
if reqValue == "null" {
data[v.GetString("name")] = nil
continue
}
if v.GetString("type") == "number" && reqValue == "" {
data[v.GetString("name")] = nil
continue
}
if v.GetString("type") == "password" {
data[v.GetString("name")] = Md5(reqValue)
} else {
data[v.GetString("name")] = reqValue
}
}
if v.GetString("name") == "modify_time" {
if v.GetString("type") == "unixTime" {
data[v.GetString("name")] = time.Now().Unix()
}
if v.GetString("type") == "time" {
data[v.GetString("name")] = time.Now().Format("2006-01-02 15:04:05")
}
}
}
if len(data) == 0 {
return nil
}
return data
}
func (that *MakeCode) Delete(table string, req *http.Request) Map {
data := Map{}
//for _, v := range that.TableColumns[table] {
// //不可使用,未在前端展示,但在内存中保持有
// if v.GetBool("notUse") {
// //if v.GetString("type") == "index" && that.TableColumns[table]["parent_id"] != nil {
// // data[v.GetString("name")] = ","
// //}
// continue
// }
//
//}
return data
}
func (that *MakeCode) Search(table string, userData Map, data Map, req *http.Request, db *db.HoTimeDB) (string, Map) {
reStr := ""
//leftJoin := Map{}
//data := Map{}
if data == nil {
data = Map{}
}
keyword := Map{}
daterange := Map{}
sortMap := Map{}
//var ruleData Map
hasUser := false
keywordStr := req.FormValue("keyword")
keywordTableStr := req.FormValue("keywordtable")
daterangeTableStr := req.FormValue("daterangetable")
testQu := []string{}
testQuData := that.TableColumns[table]
for key, _ := range testQuData {
//fmt.Println(key, ":", value)
testQu = append(testQu, key)
}
sort.Strings(testQu)
for _, k := range testQu {
v := testQuData[k]
//不可使用,未在前端展示,但在内存中保持有
if v.GetBool("notUse") {
continue
}
if v["list"] != false {
//if v.GetString("link") != "" &&
// v.GetString("name") != "parent_id" {
//
// reStr += table + "." + v.GetString("name") + ","
// //+
// // v.GetString("link") + "." + v.GetString("value") + " AS " +
// // v.GetString("link") + "_" + v.GetString("name") + "_" + v.GetString("value") + ","
//
// if v.GetString("value") == "name" && that.TableColumns[v.GetString("link")]["nickname"] != nil {
// reStr += v.GetString("link") + ".nickname AS " +
// v.GetString("link") + "_" + v.GetString("name") + "_nickname,"
// }
//
// if that.TableColumns[v.GetString("link")]["phone"] != nil {
// reStr += v.GetString("link") + ".phone AS " +
// v.GetString("link") + "_" + v.GetString("name") + "_phone,"
// }
//
// leftJoin["[>]"+v.GetString("link")] =
// table + "." + v.GetString("name") + "=" +
// v.GetString("link") + ".id"
//
// if v.GetString("link") == "admin" {
// hasUser = true
// }
//
reqValue := req.FormValue(v.GetString("name"))
// text 类字段只走下方模糊匹配([~]),此处不再生成等值条件,
// 否则等值(必不命中部分关键词)与模糊匹配在 where 中以 AND 叠加,
// 查询恒为空(见 docs/CodeGen_代码生成.md 通用 Search 筛选说明)。
if v.GetString("name") != "parent_id" && reqValue != "" &&
!strings.Contains(v.GetString("type"), "text") {
data[v.GetString("name")] = reqValue
}
//
//} else {
reStr += "`" + v.GetString("name") + "`,"
//}
//if v["name"] == "parent_id" && v.GetString("link") != "" {
// leftJoin["[>]"+v.GetString("link")+" selfParent"] =
// "selfParent.id=" +
// v.GetString("link") + "." + v.GetString("name")
// reStr += "selfParent." + v.GetString("value") + " AS " + v.GetString("link") + "_" + v.GetString("name") + "_" + v.GetString("value") + ","
//}
//准备加入索引权限
if v.GetString("link") != "" &&
userData != nil &&
that.TableColumns[v.GetString("link")]["parent_id"] != nil {
//初始化ruleData
//if ruleData == nil {
// ruleData = Map{}
// for _, v := range that.TableColumns[that.FileConfig.GetString("table")] {
// if v.GetString("link") != "" &&
// v.GetString("name") != "parent_id" &&
// userData.Get(v.GetString("name")) != nil {
// ruleData[v.GetString("link")] = userData.Get(v.GetString("name"))
// }
// }
//}
//if ruleData[v.GetString("link")] != nil {
// parent_idsStr := ""
// parent_ids := that.TableColumns[v.GetString("link")]["parent_ids"]
// if parent_ids != nil {
// parent_idsStr = "parent_ids[~]"
// }
// index := that.TableColumns[v.GetString("link")]["index"]
// if index != nil {
// parent_idsStr = "index[~]"
// }
//
// if v.GetString("name") == "parent_id" {
//
// data[table+"."+parent_idsStr] = "," + ruleData.GetString(v.GetString("link")) + ","
//
// } else {
// idMap := db.Select(v.GetString("link"), "id", Map{parent_idsStr: "," + ruleData.GetString(v.GetString("link")) + ","})
// ids := Slice{ruleData.GetCeilInt(v.GetString("link"))}
// for _, v := range idMap {
// ids = append(ids, v.GetCeilInt("id"))
// }
// data[table+"."+v.GetString("name")] = ids
// }
//
//}
}
}
if strings.Contains(v.GetString("type"), "text") {
reqValue := req.FormValue(v.GetString("name"))
if reqValue != "" {
data[v.GetString("name")+"[~]"] = reqValue
}
}
if v.GetString("type") == "unixtime" {
if len(req.Form[v.GetString("name")]) == 1 {
daterange[v.GetString("name")+"[>]"] = req.FormValue("daterange")
} else if len(req.Form[v.GetString("name")]) == 2 {
daterange[v.GetString("name")+"[<>]"] = ObjToSlice(req.Form["daterange"])
}
//fmt.Println(req.Form["daterange"])
}
if v.GetString("type") == "time" {
//fmt.Println(req.Form["daterange"])
if len(req.Form[v.GetString("name")]) == 1 {
t := time.Unix(ObjToCeilInt64(req.FormValue(v.GetString("name"))), 0).Format("2006-01-02 15:04:05")
daterange[v.GetString("name")+"[>]"] = t
} else if len(req.Form[v.GetString("name")]) == 2 {
t1 := time.Unix(ObjToCeilInt64(req.Form[v.GetString("name")][0]), 0).Format("2006-01-02 15:04:05")
t2 := time.Unix(ObjToCeilInt64(req.Form[v.GetString("name")][1]), 0).Format("2006-01-02 15:04:05")
daterange[v.GetString("name")+"[<>]"] = Slice{t1, t2}
}
}
}
if len(reStr) != 0 {
reStr = reStr[:len(reStr)-1]
}
search := that.TableConfig.GetMap(table).GetSlice("search")
for k, _ := range search {
searchItem := search.GetMap(k)
searchItemName := searchItem.GetString("name")
//if data[table+"."+searchItemName] != nil {
// delete(data, table+"."+searchItemName)
//}
reqValue := req.Form[searchItemName]
parent_idsStr := ""
if searchItem.GetString("link") != "" {
parent_ids := that.TableColumns[searchItem.GetString("link")]["parent_ids"]
if parent_ids != nil {
parent_idsStr = "parent_ids[~]"
}
index := that.TableColumns[searchItem.GetString("link")]["index"]
if index != nil {
parent_idsStr = "index[~]"
}
//reqValue := req.FormValue(search.GetMap(k).GetString("name"))
if len(reqValue) == 0 || reqValue[0] == "" {
if parent_idsStr != "" && userData[searchItem.GetString("name")] != nil {
if data[searchItemName] == nil {
continue
}
where := Map{parent_idsStr: "," + ObjToStr(userData.GetCeilInt64(searchItem.GetString("name"))) + ","}
r := db.Select(searchItem.GetString("link"), "id", where)
reqValue = []string{}
for _, v := range r {
reqValue = append(reqValue, v.GetString("id"))
}
data[searchItemName] = reqValue
}
continue
}
}
//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" {
if daterangeTableStr != "" && daterangeTableStr != v.GetString("name") {
continue
}
if v.GetString("type") == "unixtime" {
//fmt.Println(req.Form["daterange"])
if len(req.Form["daterange"]) == 1 && req.Form["daterange"][0] != "" {
daterange[v.GetString("name")+"[>]"] = req.FormValue("daterange")
} else if len(req.Form["daterange"]) == 2 {
daterange[v.GetString("name")+"[<>]"] = ObjToSlice(req.Form["daterange"])
}
}
if v.GetString("type") == "time" {
//fmt.Println(req.Form["daterange"])
if len(req.Form["daterange"]) == 1 && req.Form["daterange"][0] != "" {
t := time.Unix(ObjToCeilInt64(req.FormValue("daterange")), 0).Format("2006-01-02 15:04:05")
daterange[v.GetString("name")+"[>]"] = t
} else if len(req.Form["daterange"]) == 2 {
t1 := time.Unix(ObjToCeilInt64(req.Form["daterange"][0]), 0).Format("2006-01-02 15:04:05")
t2 := time.Unix(ObjToCeilInt64(req.Form["daterange"][1]), 0).Format("2006-01-02 15:04:05")
daterange[v.GetString("name")+"[<>]"] = Slice{t1, t2}
}
}
}
if searchItemName == "keyword" && keywordStr != "" {
if keywordTableStr != "" {
if keywordTableStr == v.GetString("name") {
data[keywordTableStr+"[~]"] = keywordStr
}
if keywordTableStr == v.GetString("value") {
childs := db.Select(v.GetString("link"), "id", Map{v.GetString("value") + "[~]": keywordStr})
childIds := Slice{}
for _, cv := range childs {
childIds = append(childIds, cv.GetCeilInt64("id"))
}
if len(childIds) != 0 {
data[v.GetString("name")] = childIds
}
}
continue
}
if strings.Contains(v.GetString("type"), "text") {
keyword[v.GetString("name")+"[~]"] = keywordStr
}
if v.GetString("name") == "id" {
keyword[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.GetCeilInt64("id"))
}
if len(childIds) != 0 {
keyword[v.GetString("name")] = childIds
}
}
}
}
if len(reqValue) != 0 && searchItem.GetString("name") == "sort" && reqValue[0] != "" {
parts := strings.Fields(reqValue[0])
if len(parts) == 2 {
col := parts[0]
dir := strings.ToUpper(parts[1])
if (dir == "ASC" || dir == "DESC") && that.TableColumns[table][col] != nil {
sortMap["ORDER"] = col + " " + dir
}
}
}
continue
}
//树节点模式搜索
if searchItemName == "parent_id" {
parentID := ObjToInt(req.FormValue("parent_id"))
if parentID == 0 {
parentID = userData.GetCeilInt(table + "_id")
data["OR"] = Map{"id": parentID, "parent_id": nil}
} else {
//是否展示全部子级
where := Map{}
if req.FormValue("showall") == "1" {
for _, v := range reqValue {
if len(where) == 0 {
where[parent_idsStr] = "," + v + ","
continue
}
where = Map{"OR": where, parent_idsStr: "," + v + ","}
}
} else {
where["parent_id"] = reqValue
}
//是否展示自己:仅在 showall=1(选中节点及全部子孙)场景生效;
//普通子级懒加载(仅 parent_id=X)不得把 id=X 的行本身混入结果,
//否则前端树把节点当成自己的子级,造成无限嵌套
if req.FormValue("showself") == "1" && req.FormValue("showall") == "1" {
if len(where) == 0 {
data["OR"] = Map{"id": reqValue}
} else {
data["OR"] = Map{"OR": where, "id": reqValue}
}
} else {
if len(where) != 0 {
data["OR"] = where
}
}
}
continue
}
//如果是树节点则需要判断是否符合权限
if searchItem.GetString("type") == "tree" {
if parent_idsStr != "" {
//where := Map{}
//是否全部展示
if req.FormValue("showall") != "1" {
if len(reqValue) != 0 {
data[searchItem.GetString("name")] = reqValue
}
} else {
ls := []int64{}
for _, v := range reqValue {
ls1 := db.Select(searchItem.GetString("link"), "id", Map{"OR": Map{parent_idsStr: "," + v + ",", "id": v}})
for _, vls1 := range ls1 {
ls = append(ls, vls1.GetCeilInt64("id"))
}
}
if len(ls) != 0 {
data[searchItem.GetString("name")] = ls
}
}
//用户
//if userData[searchItem.GetString("name")] != nil {
//
// where = Map{"AND": Map{searchItem.GetString("link") + "." + parent_idsStr: "," + ObjToStr(userData.GetCeilInt64(searchItem.GetString("name"))) + ",", "OR": where}}
//}
//if len(where)!=0{
// data["OR"] = where
//}
continue
//r := db.Select(searchItem.GetString("link"), "id", where)
//for _, v := range r {
// reqValue = append(reqValue, v.GetString("id"))
//}
}
}
if len(reqValue) != 0 && reqValue[0] != "" {
if that.TableColumns[table][searchItemName] != nil {
data[searchItemName] = reqValue
}
}
}
if sortMap["ORDER"] == nil {
sortMap["ORDER"] = "id DESC"
}
where := Map{}
//if where==nil{
// 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 == nil || len(data) == 0 {
data = Map{"OR": daterange}
} else {
data = Map{"AND": Map{"AND": data, "OR": daterange}}
}
}
if len(data) > 1 {
where["AND"] = data
}
if len(data) == 1 {
where = data
}
if len(where) == 0 && hasUser {
//where["admin.id"] = userData["id"]
}
if len(sortMap) != 0 {
for k, v := range sortMap {
where[k] = v
}
}
return reStr, where
}