feat: 代码优化、机器计划任务完善

This commit is contained in:
meilin.huang
2023-07-21 17:07:04 +08:00
parent 7b51705f4e
commit 7f9e972828
56 changed files with 376 additions and 235 deletions

View File

@@ -251,7 +251,6 @@ onMounted(async () => {
const handleCommand = (commond: any) => { const handleCommand = (commond: any) => {
const data = commond.data; const data = commond.data;
const type = commond.type; const type = commond.type;
console.log(type);
switch (type) { switch (type) {
case 'detail': { case 'detail': {
showInfo(data); showInfo(data);

View File

@@ -3,14 +3,14 @@ package api
import ( import (
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/cryptox"
) )
type Common struct { type Common struct {
} }
func (i *Common) RasPublicKey(rc *req.Ctx) { func (i *Common) RasPublicKey(rc *req.Ctx) {
publicKeyStr, err := utils.GetRsaPublicKey() publicKeyStr, err := cryptox.GetRsaPublicKey()
biz.ErrIsNilAppendErr(err, "rsa生成公私钥失败") biz.ErrIsNilAppendErr(err, "rsa生成公私钥失败")
rc.ResData = publicKeyStr rc.ResData = publicKeyStr
} }

View File

@@ -14,7 +14,9 @@ import (
"mayfly-go/pkg/gormx" "mayfly-go/pkg/gormx"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/cryptox"
"mayfly-go/pkg/utils/stringx"
"mayfly-go/pkg/utils/structx"
"mayfly-go/pkg/ws" "mayfly-go/pkg/ws"
"strconv" "strconv"
"strings" "strings"
@@ -57,7 +59,7 @@ func (d *Db) Save(rc *req.Ctx) {
db := ginx.BindJsonAndCopyTo[*entity.Db](rc.GinCtx, form, new(entity.Db)) db := ginx.BindJsonAndCopyTo[*entity.Db](rc.GinCtx, form, new(entity.Db))
// 密码解密,并使用解密后的赋值 // 密码解密,并使用解密后的赋值
originPwd, err := utils.DefaultRsaDecrypt(form.Password, true) originPwd, err := cryptox.DefaultRsaDecrypt(form.Password, true)
biz.ErrIsNilAppendErr(err, "解密密码错误: %s") biz.ErrIsNilAppendErr(err, "解密密码错误: %s")
db.Password = originPwd db.Password = originPwd
@@ -83,10 +85,10 @@ func (d *Db) GetDatabaseNames(rc *req.Ctx) {
ginx.BindJsonAndValid(rc.GinCtx, form) ginx.BindJsonAndValid(rc.GinCtx, form)
db := new(entity.Db) db := new(entity.Db)
utils.Copy(db, form) structx.Copy(db, form)
// 密码解密,并使用解密后的赋值 // 密码解密,并使用解密后的赋值
originPwd, err := utils.DefaultRsaDecrypt(form.Password, true) originPwd, err := cryptox.DefaultRsaDecrypt(form.Password, true)
biz.ErrIsNilAppendErr(err, "解密密码错误: %s") biz.ErrIsNilAppendErr(err, "解密密码错误: %s")
db.Password = originPwd db.Password = originPwd
@@ -143,7 +145,7 @@ func (d *Db) ExecSql(rc *req.Ctx) {
biz.NotEmpty(form.Sql, "sql不能为空") biz.NotEmpty(form.Sql, "sql不能为空")
// 去除前后空格及换行符 // 去除前后空格及换行符
sql := utils.StrTrimSpaceAndBr(form.Sql) sql := stringx.TrimSpaceAndBr(form.Sql)
execReq := &application.DbSqlExecReq{ execReq := &application.DbSqlExecReq{
DbId: id, DbId: id,
@@ -158,7 +160,7 @@ func (d *Db) ExecSql(rc *req.Ctx) {
isMulti := len(sqls) > 1 isMulti := len(sqls) > 1
var execResAll *application.DbSqlExecRes var execResAll *application.DbSqlExecRes
for _, s := range sqls { for _, s := range sqls {
s = utils.StrTrimSpaceAndBr(s) s = stringx.TrimSpaceAndBr(s)
// 多条执行,如果有查询语句,则跳过 // 多条执行,如果有查询语句,则跳过
if isMulti && strings.HasPrefix(strings.ToLower(s), "select") { if isMulti && strings.HasPrefix(strings.ToLower(s), "select") {
continue continue
@@ -308,7 +310,7 @@ func (d *Db) DumpSql(rc *req.Ctx) {
if ok { if ok {
values = append(values, fmt.Sprintf("%#v", strValue)) values = append(values, fmt.Sprintf("%#v", strValue))
} else { } else {
values = append(values, utils.ToString(value)) values = append(values, stringx.AnyToStr(value))
} }
} }
writer.WriteString(fmt.Sprintf(insertSql, table, strings.Join(values, ", "))) writer.WriteString(fmt.Sprintf(insertSql, table, strings.Join(values, ", ")))

View File

@@ -11,7 +11,8 @@ import (
"mayfly-go/pkg/cache" "mayfly-go/pkg/cache"
"mayfly-go/pkg/global" "mayfly-go/pkg/global"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/collx"
"mayfly-go/pkg/utils/structx"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
@@ -120,7 +121,7 @@ func (d *dbAppImpl) Save(dbEntity *entity.Db) {
newDbs = append(newDbs, v) newDbs = append(newDbs, v)
} }
// 比较新旧数据库列表,需要将移除的数据库相关联的信息删除 // 比较新旧数据库列表,需要将移除的数据库相关联的信息删除
_, delDb, _ := utils.ArrayCompare(newDbs, oldDbs, func(i1, i2 any) bool { _, delDb, _ := collx.ArrayCompare(newDbs, oldDbs, func(i1, i2 any) bool {
return i1.(string) == i2.(string) return i1.(string) == i2.(string)
}) })
for _, v := range delDb { for _, v := range delDb {
@@ -193,7 +194,7 @@ func (da *dbAppImpl) GetDbInstance(id uint64, db string) *DbInstance {
d.PwdDecrypt() d.PwdDecrypt()
dbInfo := new(DbInfo) dbInfo := new(DbInfo)
utils.Copy(dbInfo, d) structx.Copy(dbInfo, d)
dbInfo.Database = db dbInfo.Database = db
dbi := &DbInstance{Id: cacheKey, Info: dbInfo} dbi := &DbInstance{Id: cacheKey, Info: dbInfo}

View File

@@ -3,7 +3,7 @@ package application
import ( import (
"embed" "embed"
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/stringx"
"strings" "strings"
) )
@@ -88,7 +88,7 @@ func GetLocalSql(file, key string) string {
sqls := strings.Split(allSql, "---------------------------------------") sqls := strings.Split(allSql, "---------------------------------------")
var resSql string var resSql string
for _, sql := range sqls { for _, sql := range sqls {
sql = utils.StrTrimSpaceAndBr(sql) sql = stringx.TrimSpaceAndBr(sql)
// 获取sql第一行的sql备注信息如--MYSQL_TABLE_MA 表信息元数据 // 获取sql第一行的sql备注信息如--MYSQL_TABLE_MA 表信息元数据
info := strings.SplitN(sql, "\n", 2) info := strings.SplitN(sql, "\n", 2)
// 原始sql即去除第一行的key与备注信息 // 原始sql即去除第一行的key与备注信息

View File

@@ -7,7 +7,7 @@ import (
"mayfly-go/internal/db/domain/entity" "mayfly-go/internal/db/domain/entity"
machineapp "mayfly-go/internal/machine/application" machineapp "mayfly-go/internal/machine/application"
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/anyx"
"net" "net"
"github.com/go-sql-driver/mysql" "github.com/go-sql-driver/mysql"
@@ -51,7 +51,7 @@ func (mm *MysqlMetadata) GetTables() []Table {
for _, re := range res { for _, re := range res {
tables = append(tables, Table{ tables = append(tables, Table{
TableName: re["tableName"].(string), TableName: re["tableName"].(string),
TableComment: utils.Any2String(re["tableComment"]), TableComment: anyx.ConvString(re["tableComment"]),
}) })
} }
return tables return tables
@@ -74,11 +74,11 @@ func (mm *MysqlMetadata) GetColumns(tableNames ...string) []Column {
columns = append(columns, Column{ columns = append(columns, Column{
TableName: re["tableName"].(string), TableName: re["tableName"].(string),
ColumnName: re["columnName"].(string), ColumnName: re["columnName"].(string),
ColumnType: utils.Any2String(re["columnType"]), ColumnType: anyx.ConvString(re["columnType"]),
ColumnComment: utils.Any2String(re["columnComment"]), ColumnComment: anyx.ConvString(re["columnComment"]),
Nullable: utils.Any2String(re["nullable"]), Nullable: anyx.ConvString(re["nullable"]),
ColumnKey: utils.Any2String(re["columnKey"]), ColumnKey: anyx.ConvString(re["columnKey"]),
ColumnDefault: utils.Any2String(re["columnDefault"]), ColumnDefault: anyx.ConvString(re["columnDefault"]),
}) })
} }
return columns return columns
@@ -106,11 +106,11 @@ func (mm *MysqlMetadata) GetTableInfos() []Table {
for _, re := range res { for _, re := range res {
tables = append(tables, Table{ tables = append(tables, Table{
TableName: re["tableName"].(string), TableName: re["tableName"].(string),
TableComment: utils.Any2String(re["tableComment"]), TableComment: anyx.ConvString(re["tableComment"]),
CreateTime: utils.Any2String(re["createTime"]), CreateTime: anyx.ConvString(re["createTime"]),
TableRows: utils.Any2Int(re["tableRows"]), TableRows: anyx.ConvInt(re["tableRows"]),
DataLength: utils.Any2Int64(re["dataLength"]), DataLength: anyx.ConvInt64(re["dataLength"]),
IndexLength: utils.Any2Int64(re["indexLength"]), IndexLength: anyx.ConvInt64(re["indexLength"]),
}) })
} }
return tables return tables
@@ -124,11 +124,11 @@ func (mm *MysqlMetadata) GetTableIndex(tableName string) []Index {
for _, re := range res { for _, re := range res {
indexs = append(indexs, Index{ indexs = append(indexs, Index{
IndexName: re["indexName"].(string), IndexName: re["indexName"].(string),
ColumnName: utils.Any2String(re["columnName"]), ColumnName: anyx.ConvString(re["columnName"]),
IndexType: utils.Any2String(re["indexType"]), IndexType: anyx.ConvString(re["indexType"]),
IndexComment: utils.Any2String(re["indexComment"]), IndexComment: anyx.ConvString(re["indexComment"]),
NonUnique: utils.Any2Int(re["nonUnique"]), NonUnique: anyx.ConvInt(re["nonUnique"]),
SeqInIndex: utils.Any2Int(re["seqInIndex"]), SeqInIndex: anyx.ConvInt(re["seqInIndex"]),
}) })
} }
// 把查询结果以索引名分组,索引字段以逗号连接 // 把查询结果以索引名分组,索引字段以逗号连接

View File

@@ -7,7 +7,8 @@ import (
"mayfly-go/internal/db/domain/entity" "mayfly-go/internal/db/domain/entity"
machineapp "mayfly-go/internal/machine/application" machineapp "mayfly-go/internal/machine/application"
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/collx"
"net" "net"
"strings" "strings"
"time" "time"
@@ -21,7 +22,7 @@ func getPgsqlDB(d *entity.Db, db string) (*sql.DB, error) {
if d.SshTunnelMachineId > 0 { if d.SshTunnelMachineId > 0 {
// 如果使用了隧道,则使用`postgres:ssh:隧道机器id`注册名 // 如果使用了隧道,则使用`postgres:ssh:隧道机器id`注册名
driverName = fmt.Sprintf("postgres:ssh:%d", d.SshTunnelMachineId) driverName = fmt.Sprintf("postgres:ssh:%d", d.SshTunnelMachineId)
if !utils.ArrContains(sql.Drivers(), driverName) { if !collx.ArrayContains(sql.Drivers(), driverName) {
sql.Register(driverName, &PqSqlDialer{sshTunnelMachineId: d.SshTunnelMachineId}) sql.Register(driverName, &PqSqlDialer{sshTunnelMachineId: d.SshTunnelMachineId})
} }
sql.Drivers() sql.Drivers()
@@ -78,7 +79,7 @@ func (pm *PgsqlMetadata) GetTables() []Table {
for _, re := range res { for _, re := range res {
tables = append(tables, Table{ tables = append(tables, Table{
TableName: re["tableName"].(string), TableName: re["tableName"].(string),
TableComment: utils.Any2String(re["tableComment"]), TableComment: anyx.ConvString(re["tableComment"]),
}) })
} }
return tables return tables
@@ -101,11 +102,11 @@ func (pm *PgsqlMetadata) GetColumns(tableNames ...string) []Column {
columns = append(columns, Column{ columns = append(columns, Column{
TableName: re["tableName"].(string), TableName: re["tableName"].(string),
ColumnName: re["columnName"].(string), ColumnName: re["columnName"].(string),
ColumnType: utils.Any2String(re["columnType"]), ColumnType: anyx.ConvString(re["columnType"]),
ColumnComment: utils.Any2String(re["columnComment"]), ColumnComment: anyx.ConvString(re["columnComment"]),
Nullable: utils.Any2String(re["nullable"]), Nullable: anyx.ConvString(re["nullable"]),
ColumnKey: utils.Any2String(re["columnKey"]), ColumnKey: anyx.ConvString(re["columnKey"]),
ColumnDefault: utils.Any2String(re["columnDefault"]), ColumnDefault: anyx.ConvString(re["columnDefault"]),
}) })
} }
return columns return columns
@@ -132,11 +133,11 @@ func (pm *PgsqlMetadata) GetTableInfos() []Table {
for _, re := range res { for _, re := range res {
tables = append(tables, Table{ tables = append(tables, Table{
TableName: re["tableName"].(string), TableName: re["tableName"].(string),
TableComment: utils.Any2String(re["tableComment"]), TableComment: anyx.ConvString(re["tableComment"]),
CreateTime: utils.Any2String(re["createTime"]), CreateTime: anyx.ConvString(re["createTime"]),
TableRows: utils.Any2Int(re["tableRows"]), TableRows: anyx.ConvInt(re["tableRows"]),
DataLength: utils.Any2Int64(re["dataLength"]), DataLength: anyx.ConvInt64(re["dataLength"]),
IndexLength: utils.Any2Int64(re["indexLength"]), IndexLength: anyx.ConvInt64(re["indexLength"]),
}) })
} }
return tables return tables
@@ -150,11 +151,11 @@ func (pm *PgsqlMetadata) GetTableIndex(tableName string) []Index {
for _, re := range res { for _, re := range res {
indexs = append(indexs, Index{ indexs = append(indexs, Index{
IndexName: re["indexName"].(string), IndexName: re["indexName"].(string),
ColumnName: utils.Any2String(re["columnName"]), ColumnName: anyx.ConvString(re["columnName"]),
IndexType: utils.Any2String(re["indexType"]), IndexType: anyx.ConvString(re["indexType"]),
IndexComment: utils.Any2String(re["indexComment"]), IndexComment: anyx.ConvString(re["indexComment"]),
NonUnique: utils.Any2Int(re["nonUnique"]), NonUnique: anyx.ConvInt(re["nonUnique"]),
SeqInIndex: utils.Any2Int(re["seqInIndex"]), SeqInIndex: anyx.ConvInt(re["seqInIndex"]),
}) })
} }
return indexs return indexs

View File

@@ -14,7 +14,8 @@ import (
"mayfly-go/pkg/ginx" "mayfly-go/pkg/ginx"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/stringx"
"mayfly-go/pkg/utils/structx"
"mayfly-go/pkg/ws" "mayfly-go/pkg/ws"
"os" "os"
"path" "path"
@@ -82,7 +83,7 @@ func (m *Machine) TestConn(rc *req.Ctx) {
ginx.BindJsonAndValid(g, machineForm) ginx.BindJsonAndValid(g, machineForm)
me := new(entity.Machine) me := new(entity.Machine)
utils.Copy(me, machineForm) structx.Copy(me, machineForm)
m.MachineApp.TestConn(me) m.MachineApp.TestConn(me)
} }
@@ -192,7 +193,7 @@ func (m *Machine) WsSSH(g *gin.Context) {
recorder = machine.NewRecorder(f) recorder = machine.NewRecorder(f)
} }
mts, err := machine.NewTerminalSession(utils.RandString(16), wsConn, cli, rows, cols, recorder) mts, err := machine.NewTerminalSession(stringx.Rand(16), wsConn, cli, rows, cols, recorder)
biz.ErrIsNilAppendErr(err, "\033[1;31m连接失败: %s\033[0m") biz.ErrIsNilAppendErr(err, "\033[1;31m连接失败: %s\033[0m")
// 记录系统操作日志 // 记录系统操作日志

View File

@@ -10,7 +10,8 @@ import (
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/ginx" "mayfly-go/pkg/ginx"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/jsonx"
"mayfly-go/pkg/utils/stringx"
"strconv" "strconv"
"strings" "strings"
@@ -63,7 +64,7 @@ func (m *MachineScript) RunMachineScript(rc *req.Ctx) {
script := ms.Script script := ms.Script
// 如果有脚本参数,则用脚本参数替换脚本中的模板占位符参数 // 如果有脚本参数,则用脚本参数替换脚本中的模板占位符参数
if params := g.Query("params"); params != "" { if params := g.Query("params"); params != "" {
script = utils.TemplateParse(ms.Script, utils.Json2Map(params)) script = stringx.TemplateParse(ms.Script, jsonx.ToMap(params))
} }
cli := m.MachineApp.GetCli(machineId) cli := m.MachineApp.GetCli(machineId)
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s") biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")

View File

@@ -5,8 +5,10 @@ import (
"mayfly-go/internal/machine/domain/repository" "mayfly-go/internal/machine/domain/repository"
"mayfly-go/pkg/global" "mayfly-go/pkg/global"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/rediscli"
"mayfly-go/pkg/scheduler" "mayfly-go/pkg/scheduler"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/collx"
"mayfly-go/pkg/utils/stringx"
"time" "time"
) )
@@ -107,7 +109,7 @@ func (m *machineCropJobAppImpl) GetRelateCronJobIds(machineId uint64) []uint64 {
func (m *machineCropJobAppImpl) CronJobRelateMachines(cronJobId uint64, machineIds []uint64, la *model.LoginAccount) { func (m *machineCropJobAppImpl) CronJobRelateMachines(cronJobId uint64, machineIds []uint64, la *model.LoginAccount) {
oldMachineIds := m.machineCropJobRelateRepo.GetMachineIds(cronJobId) oldMachineIds := m.machineCropJobRelateRepo.GetMachineIds(cronJobId)
addIds, delIds, _ := utils.ArrayCompare[uint64](machineIds, oldMachineIds, func(u1, u2 uint64) bool { return u1 == u2 }) addIds, delIds, _ := collx.ArrayCompare[uint64](machineIds, oldMachineIds, func(u1, u2 uint64) bool { return u1 == u2 })
addVals := make([]*entity.MachineCronJobRelate, 0) addVals := make([]*entity.MachineCronJobRelate, 0)
now := time.Now() now := time.Now()
@@ -129,7 +131,7 @@ func (m *machineCropJobAppImpl) CronJobRelateMachines(cronJobId uint64, machineI
func (m *machineCropJobAppImpl) MachineRelateCronJobs(machineId uint64, cronJobs []uint64, la *model.LoginAccount) { func (m *machineCropJobAppImpl) MachineRelateCronJobs(machineId uint64, cronJobs []uint64, la *model.LoginAccount) {
oldCronIds := m.machineCropJobRelateRepo.GetCronJobIds(machineId) oldCronIds := m.machineCropJobRelateRepo.GetCronJobIds(machineId)
addIds, delIds, _ := utils.ArrayCompare[uint64](cronJobs, oldCronIds, func(u1, u2 uint64) bool { return u1 == u2 }) addIds, delIds, _ := collx.ArrayCompare[uint64](cronJobs, oldCronIds, func(u1, u2 uint64) bool { return u1 == u2 })
addVals := make([]*entity.MachineCronJobRelate, 0) addVals := make([]*entity.MachineCronJobRelate, 0)
now := time.Now() now := time.Now()
@@ -186,7 +188,7 @@ func (m *machineCropJobAppImpl) addCronJob(mcj *entity.MachineCronJob) {
var key string var key string
isDisable := mcj.Status == entity.MachineCronJobStatusDisable isDisable := mcj.Status == entity.MachineCronJobStatusDisable
if mcj.Id == 0 { if mcj.Id == 0 {
key = utils.RandString(16) key = stringx.Rand(16)
mcj.Key = key mcj.Key = key
if isDisable { if isDisable {
return return
@@ -201,11 +203,19 @@ func (m *machineCropJobAppImpl) addCronJob(mcj *entity.MachineCronJob) {
} }
scheduler.AddFunByKey(key, mcj.Cron, func() { scheduler.AddFunByKey(key, mcj.Cron, func() {
m.runCronJob(key) go m.runCronJob(key)
}) })
} }
func (m *machineCropJobAppImpl) runCronJob(key string) { func (m *machineCropJobAppImpl) runCronJob(key string) {
// 简单使用redis分布式锁防止多实例同一时刻重复执行
if lock := rediscli.NewLock(key, 30*time.Second); lock != nil {
if !lock.Lock() {
return
}
defer lock.UnLock()
}
cronJob := new(entity.MachineCronJob) cronJob := new(entity.MachineCronJob)
cronJob.Key = key cronJob.Key = key
err := m.machineCropJobRepo.GetBy(cronJob) err := m.machineCropJobRepo.GetBy(cronJob)

View File

@@ -2,7 +2,7 @@ package machine
import ( import (
"fmt" "fmt"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/stringx"
"strings" "strings"
"testing" "testing"
) )
@@ -69,7 +69,7 @@ func TestTemplateRev(t *testing.T) {
//key := temp[index+1 : ei-1] //key := temp[index+1 : ei-1]
//value := SubString(str, index, UnicodeIndex(str, next)) //value := SubString(str, index, UnicodeIndex(str, next))
res := make(map[string]any) res := make(map[string]any)
utils.ReverStrTemplate(temp, str, res) stringx.ReverStrTemplate(temp, str, res)
fmt.Println(res) fmt.Println(res)
} }

View File

@@ -5,7 +5,7 @@ import (
"io" "io"
"mayfly-go/pkg/global" "mayfly-go/pkg/global"
"mayfly-go/pkg/scheduler" "mayfly-go/pkg/scheduler"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/netx"
"net" "net"
"os" "os"
"sync" "sync"
@@ -75,7 +75,7 @@ func (stm *SshTunnelMachine) OpenSshTunnel(id uint64, ip string, port int) (expo
stm.mutex.Lock() stm.mutex.Lock()
defer stm.mutex.Unlock() defer stm.mutex.Unlock()
localPort, err := utils.GetAvailablePort() localPort, err := netx.GetAvailablePort()
if err != nil { if err != nil {
return "", 0, err return "", 0, err
} }

View File

@@ -7,7 +7,7 @@ import (
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/gormx" "mayfly-go/pkg/gormx"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/collx"
"strconv" "strconv"
"strings" "strings"
) )
@@ -29,7 +29,7 @@ func (m *machineRepoImpl) GetMachineList(condition *entity.MachineQuery, pagePar
if condition.Ids != "" { if condition.Ids != "" {
// ,分割id转为id数组 // ,分割id转为id数组
qd.In("id", utils.ArrayMap[string, uint64](strings.Split(condition.Ids, ","), func(val string) uint64 { qd.In("id", collx.ArrayMap[string, uint64](strings.Split(condition.Ids, ","), func(val string) uint64 {
id, _ := strconv.Atoi(val) id, _ := strconv.Atoi(val)
return uint64(id) return uint64(id)
})) }))

View File

@@ -12,7 +12,8 @@ import (
"mayfly-go/pkg/cache" "mayfly-go/pkg/cache"
"mayfly-go/pkg/global" "mayfly-go/pkg/global"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/netx"
"mayfly-go/pkg/utils/structx"
"net" "net"
"regexp" "regexp"
"time" "time"
@@ -201,7 +202,7 @@ func connect(me *entity.Mongo) (*MongoInstance, error) {
func toMongiInfo(me *entity.Mongo) *MongoInfo { func toMongiInfo(me *entity.Mongo) *MongoInfo {
mi := new(MongoInfo) mi := new(MongoInfo)
utils.Copy(mi, me) structx.Copy(mi, me)
return mi return mi
} }
@@ -212,7 +213,7 @@ type MongoSshDialer struct {
func (sd *MongoSshDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { func (sd *MongoSshDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
if sshConn, err := machineapp.GetMachineApp().GetSshTunnelMachine(sd.machineId).GetDialConn(network, address); err == nil { if sshConn, err := machineapp.GetMachineApp().GetSshTunnelMachine(sd.machineId).GetDialConn(network, address); err == nil {
// 将ssh conn包装否则内部部设置超时会报错,ssh conn不支持设置超时会返回错误: ssh: tcpChan: deadline not supported // 将ssh conn包装否则内部部设置超时会报错,ssh conn不支持设置超时会返回错误: ssh: tcpChan: deadline not supported
return &utils.WrapSshConn{Conn: sshConn}, nil return &netx.WrapSshConn{Conn: sshConn}, nil
} else { } else {
return nil, err return nil, err
} }

View File

@@ -11,7 +11,8 @@ import (
"mayfly-go/pkg/ginx" "mayfly-go/pkg/ginx"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/cryptox"
"mayfly-go/pkg/utils/stringx"
"strconv" "strconv"
"strings" "strings"
@@ -47,7 +48,7 @@ func (r *Redis) Save(rc *req.Ctx) {
redis := ginx.BindJsonAndCopyTo[*entity.Redis](rc.GinCtx, form, new(entity.Redis)) redis := ginx.BindJsonAndCopyTo[*entity.Redis](rc.GinCtx, form, new(entity.Redis))
// 密码解密,并使用解密后的赋值 // 密码解密,并使用解密后的赋值
originPwd, err := utils.DefaultRsaDecrypt(redis.Password, true) originPwd, err := cryptox.DefaultRsaDecrypt(redis.Password, true)
biz.ErrIsNilAppendErr(err, "解密密码错误: %s") biz.ErrIsNilAppendErr(err, "解密密码错误: %s")
redis.Password = originPwd redis.Password = originPwd
@@ -133,7 +134,7 @@ func (r *Redis) RedisInfo(rc *req.Ctx) {
break break
} }
if strings.Contains(datas[i], "#") { if strings.Contains(datas[i], "#") {
key := utils.SubString(datas[i], strings.Index(datas[i], "#")+1, utils.StrLen(datas[i])) key := stringx.SubString(datas[i], strings.Index(datas[i], "#")+1, stringx.Len(datas[i]))
i++ i++
key = strings.Trim(key, " ") key = strings.Trim(key, " ")

View File

@@ -7,7 +7,7 @@ import (
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/ginx" "mayfly-go/pkg/ginx"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/stringx"
"time" "time"
) )
@@ -25,7 +25,7 @@ func (r *Redis) SetStringValue(rc *req.Ctx) {
ri := r.getRedisIns(rc) ri := r.getRedisIns(rc)
cmd := ri.GetCmdable() cmd := ri.GetCmdable()
rc.ReqParam = fmt.Sprintf("%s -> %s", ri.Info.GetLogDesc(), utils.ToString(keyValue)) rc.ReqParam = fmt.Sprintf("%s -> %s", ri.Info.GetLogDesc(), stringx.AnyToStr(keyValue))
str, err := cmd.Set(context.TODO(), keyValue.Key, keyValue.Value, time.Second*time.Duration(keyValue.Timed)).Result() str, err := cmd.Set(context.TODO(), keyValue.Key, keyValue.Value, time.Second*time.Duration(keyValue.Timed)).Result()
biz.ErrIsNilAppendErr(err, "保存字符串值失败: %s") biz.ErrIsNilAppendErr(err, "保存字符串值失败: %s")

View File

@@ -12,7 +12,8 @@ import (
"mayfly-go/pkg/cache" "mayfly-go/pkg/cache"
"mayfly-go/pkg/global" "mayfly-go/pkg/global"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/netx"
"mayfly-go/pkg/utils/structx"
"net" "net"
"strconv" "strconv"
"strings" "strings"
@@ -176,7 +177,7 @@ func getRedisCacheKey(id uint64, db int) string {
func toRedisInfo(re *entity.Redis, db int) *RedisInfo { func toRedisInfo(re *entity.Redis, db int) *RedisInfo {
redisInfo := new(RedisInfo) redisInfo := new(RedisInfo)
utils.Copy(redisInfo, re) structx.Copy(redisInfo, re)
redisInfo.Db = db redisInfo.Db = db
return redisInfo return redisInfo
} }
@@ -243,7 +244,7 @@ func getRedisDialer(machineId int) func(ctx context.Context, network, addr strin
return func(_ context.Context, network, addr string) (net.Conn, error) { return func(_ context.Context, network, addr string) (net.Conn, error) {
if sshConn, err := sshTunnel.GetDialConn(network, addr); err == nil { if sshConn, err := sshTunnel.GetDialConn(network, addr); err == nil {
// 将ssh conn包装否则redis内部设置超时会报错,ssh conn不支持设置超时会返回错误: ssh: tcpChan: deadline not supported // 将ssh conn包装否则redis内部设置超时会报错,ssh conn不支持设置超时会返回错误: ssh: tcpChan: deadline not supported
return &utils.WrapSshConn{Conn: sshConn}, nil return &netx.WrapSshConn{Conn: sshConn}, nil
} else { } else {
return nil, err return nil, err
} }

View File

@@ -16,7 +16,12 @@ import (
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/otp" "mayfly-go/pkg/otp"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/collx"
"mayfly-go/pkg/utils/cryptox"
"mayfly-go/pkg/utils/jsonx"
"mayfly-go/pkg/utils/netx"
"mayfly-go/pkg/utils/stringx"
"mayfly-go/pkg/utils/timex"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@@ -55,7 +60,7 @@ func (a *Account) Login(rc *req.Ctx) {
clientIp := getIpAndRegion(rc) clientIp := getIpAndRegion(rc)
rc.ReqParam = fmt.Sprintf("username: %s | ip: %s", username, clientIp) rc.ReqParam = fmt.Sprintf("username: %s | ip: %s", username, clientIp)
originPwd, err := utils.DefaultRsaDecrypt(loginForm.Password, true) originPwd, err := cryptox.DefaultRsaDecrypt(loginForm.Password, true)
biz.ErrIsNilAppendErr(err, "解密密码错误: %s") biz.ErrIsNilAppendErr(err, "解密密码错误: %s")
account := &entity.Account{Username: username} account := &entity.Account{Username: username}
@@ -67,7 +72,7 @@ func (a *Account) Login(rc *req.Ctx) {
loginFailMin := accountLoginSecurity.LoginFailMin loginFailMin := accountLoginSecurity.LoginFailMin
biz.IsTrue(nowFailCount < loginFailCount, "登录失败超过%d次, 请%d分钟后再试", loginFailCount, loginFailMin) biz.IsTrue(nowFailCount < loginFailCount, "登录失败超过%d次, 请%d分钟后再试", loginFailCount, loginFailMin)
if err != nil || !utils.CheckPwdHash(originPwd, account.Password) { if err != nil || !cryptox.CheckPwdHash(originPwd, account.Password) {
nowFailCount++ nowFailCount++
cache.SetStr(failCountKey, strconv.Itoa(nowFailCount), time.Minute*time.Duration(loginFailMin)) cache.SetStr(failCountKey, strconv.Itoa(nowFailCount), time.Minute*time.Duration(loginFailMin))
panic(biz.NewBizErr(fmt.Sprintf("用户名或密码错误【当前登录失败%d次】", nowFailCount))) panic(biz.NewBizErr(fmt.Sprintf("用户名或密码错误【当前登录失败%d次】", nowFailCount)))
@@ -96,7 +101,7 @@ func (a *Account) Login(rc *req.Ctx) {
// 修改状态为已注册 // 修改状态为已注册
otpStatus = OtpStatusReg otpStatus = OtpStatusReg
// 该token用于otp双因素校验 // 该token用于otp双因素校验
token = utils.RandString(32) token = stringx.Rand(32)
// 未注册otp secret或重置了秘钥 // 未注册otp secret或重置了秘钥
if otpSecret == "" || otpSecret == "-" { if otpSecret == "" || otpSecret == "-" {
otpStatus = OtpStatusNoReg otpStatus = OtpStatusNoReg
@@ -116,7 +121,7 @@ func (a *Account) Login(rc *req.Ctx) {
OtpSecret: otpSecret, OtpSecret: otpSecret,
AccessToken: accessToken, AccessToken: accessToken,
} }
cache.SetStr(fmt.Sprintf("otp:token:%s", token), utils.ToJsonStr(otpInfo), time.Minute*time.Duration(3)) cache.SetStr(fmt.Sprintf("otp:token:%s", token), jsonx.ToStr(otpInfo), time.Minute*time.Duration(3))
} else { } else {
// 不进行otp二次校验则直接返回accessToken // 不进行otp二次校验则直接返回accessToken
token = accessToken token = accessToken
@@ -133,7 +138,7 @@ func (a *Account) Login(rc *req.Ctx) {
// 获取ip与归属地信息 // 获取ip与归属地信息
func getIpAndRegion(rc *req.Ctx) string { func getIpAndRegion(rc *req.Ctx) string {
clientIp := rc.GinCtx.ClientIP() clientIp := rc.GinCtx.ClientIP()
return fmt.Sprintf("%s %s", clientIp, utils.Ip2Region(clientIp)) return fmt.Sprintf("%s %s", clientIp, netx.Ip2Region(clientIp))
} }
type OtpVerifyInfo struct { type OtpVerifyInfo struct {
@@ -214,22 +219,22 @@ func (a *Account) ChangePassword(rc *req.Ctx) {
form := new(form.AccountChangePasswordForm) form := new(form.AccountChangePasswordForm)
ginx.BindJsonAndValid(rc.GinCtx, form) ginx.BindJsonAndValid(rc.GinCtx, form)
originOldPwd, err := utils.DefaultRsaDecrypt(form.OldPassword, true) originOldPwd, err := cryptox.DefaultRsaDecrypt(form.OldPassword, true)
biz.ErrIsNilAppendErr(err, "解密旧密码错误: %s") biz.ErrIsNilAppendErr(err, "解密旧密码错误: %s")
account := &entity.Account{Username: form.Username} account := &entity.Account{Username: form.Username}
err = a.AccountApp.GetAccount(account, "Id", "Username", "Password", "Status") err = a.AccountApp.GetAccount(account, "Id", "Username", "Password", "Status")
biz.ErrIsNil(err, "旧密码错误") biz.ErrIsNil(err, "旧密码错误")
biz.IsTrue(utils.CheckPwdHash(originOldPwd, account.Password), "旧密码错误") biz.IsTrue(cryptox.CheckPwdHash(originOldPwd, account.Password), "旧密码错误")
biz.IsTrue(account.IsEnable(), "该账号不可用") biz.IsTrue(account.IsEnable(), "该账号不可用")
originNewPwd, err := utils.DefaultRsaDecrypt(form.NewPassword, true) originNewPwd, err := cryptox.DefaultRsaDecrypt(form.NewPassword, true)
biz.ErrIsNilAppendErr(err, "解密新密码错误: %s") biz.ErrIsNilAppendErr(err, "解密新密码错误: %s")
biz.IsTrue(CheckPasswordLever(originNewPwd), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号") biz.IsTrue(CheckPasswordLever(originNewPwd), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号")
updateAccount := new(entity.Account) updateAccount := new(entity.Account)
updateAccount.Id = account.Id updateAccount.Id = account.Id
updateAccount.Password = utils.PwdHash(originNewPwd) updateAccount.Password = cryptox.PwdHash(originNewPwd)
a.AccountApp.Update(updateAccount) a.AccountApp.Update(updateAccount)
// 赋值loginAccount 主要用于记录操作日志,因为操作日志保存请求上下文没有该信息不保存日志 // 赋值loginAccount 主要用于记录操作日志,因为操作日志保存请求上下文没有该信息不保存日志
@@ -267,7 +272,7 @@ func (a *Account) saveLogin(account *entity.Account, ip string) {
// 创建登录消息 // 创建登录消息
loginMsg := &msgentity.Msg{ loginMsg := &msgentity.Msg{
RecipientId: int64(account.Id), RecipientId: int64(account.Id),
Msg: fmt.Sprintf("于[%s]-[%s]登录", ip, utils.DefaultTimeFormat(now)), Msg: fmt.Sprintf("于[%s]-[%s]登录", ip, timex.DefaultFormat(now)),
Type: 1, Type: 1,
} }
loginMsg.CreateTime = &now loginMsg.CreateTime = &now
@@ -295,7 +300,7 @@ func (a *Account) UpdateAccount(rc *req.Ctx) {
if updateAccount.Password != "" { if updateAccount.Password != "" {
biz.IsTrue(CheckPasswordLever(updateAccount.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号") biz.IsTrue(CheckPasswordLever(updateAccount.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号")
updateAccount.Password = utils.PwdHash(updateAccount.Password) updateAccount.Password = cryptox.PwdHash(updateAccount.Password)
} }
a.AccountApp.Update(updateAccount) a.AccountApp.Update(updateAccount)
} }
@@ -323,7 +328,7 @@ func (a *Account) SaveAccount(rc *req.Ctx) {
} else { } else {
if account.Password != "" { if account.Password != "" {
biz.IsTrue(CheckPasswordLever(account.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号") biz.IsTrue(CheckPasswordLever(account.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号")
account.Password = utils.PwdHash(account.Password) account.Password = cryptox.PwdHash(account.Password)
} }
a.AccountApp.Update(account) a.AccountApp.Update(account)
} }
@@ -380,14 +385,14 @@ func (a *Account) SaveRoles(rc *req.Ctx) {
rc.ReqParam = form rc.ReqParam = form
// 将,拼接的字符串进行切割并转换 // 将,拼接的字符串进行切割并转换
newIds := utils.ArrayMap[string, uint64](strings.Split(form.RoleIds, ","), func(val string) uint64 { newIds := collx.ArrayMap[string, uint64](strings.Split(form.RoleIds, ","), func(val string) uint64 {
id, _ := strconv.Atoi(val) id, _ := strconv.Atoi(val)
return uint64(id) return uint64(id)
}) })
oIds := a.RoleApp.GetAccountRoleIds(uint64(form.Id)) oIds := a.RoleApp.GetAccountRoleIds(uint64(form.Id))
addIds, delIds, _ := utils.ArrayCompare(newIds, oIds, func(i1, i2 uint64) bool { addIds, delIds, _ := collx.ArrayCompare(newIds, oIds, func(i1, i2 uint64) bool {
return i1 == i2 return i1 == i2
}) })

View File

@@ -9,7 +9,7 @@ import (
"mayfly-go/pkg/ginx" "mayfly-go/pkg/ginx"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/collx"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -72,14 +72,14 @@ func (r *Role) SaveResource(rc *req.Ctx) {
rc.ReqParam = form rc.ReqParam = form
// 将,拼接的字符串进行切割并转换 // 将,拼接的字符串进行切割并转换
newIds := utils.ArrayMap[string, uint64](strings.Split(form.ResourceIds, ","), func(val string) uint64 { newIds := collx.ArrayMap[string, uint64](strings.Split(form.ResourceIds, ","), func(val string) uint64 {
id, _ := strconv.Atoi(val) id, _ := strconv.Atoi(val)
return uint64(id) return uint64(id)
}) })
oIds := r.RoleApp.GetRoleResourceIds(uint64(form.Id)) oIds := r.RoleApp.GetRoleResourceIds(uint64(form.Id))
addIds, delIds, _ := utils.ArrayCompare(newIds, oIds, func(i1, i2 uint64) bool { addIds, delIds, _ := collx.ArrayCompare(newIds, oIds, func(i1, i2 uint64) bool {
return i1 == i2 return i1 == i2
}) })

View File

@@ -6,7 +6,7 @@ import (
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/gormx" "mayfly-go/pkg/gormx"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/cryptox"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -45,7 +45,7 @@ func (a *accountAppImpl) GetPageList(condition *entity.Account, pageParam *model
func (a *accountAppImpl) Create(account *entity.Account) { func (a *accountAppImpl) Create(account *entity.Account) {
biz.IsTrue(a.GetAccount(&entity.Account{Username: account.Username}) != nil, "该账号用户名已存在") biz.IsTrue(a.GetAccount(&entity.Account{Username: account.Username}) != nil, "该账号用户名已存在")
// 默认密码为账号用户名 // 默认密码为账号用户名
account.Password = utils.PwdHash(account.Username) account.Password = cryptox.PwdHash(account.Username)
account.Status = entity.AccountEnableStatus account.Status = entity.AccountEnableStatus
a.accountRepo.Insert(account) a.accountRepo.Insert(account)
} }

View File

@@ -7,7 +7,7 @@ import (
"mayfly-go/pkg/cache" "mayfly-go/pkg/cache"
"mayfly-go/pkg/global" "mayfly-go/pkg/global"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/jsonx"
) )
const SysConfigKeyPrefix = "sys:config:" const SysConfigKeyPrefix = "sys:config:"
@@ -56,7 +56,7 @@ func (a *configAppImpl) GetConfig(key string) *entity.Config {
if err := a.configRepo.GetConfig(config, "Id", "Key", "Value"); err != nil { if err := a.configRepo.GetConfig(config, "Id", "Key", "Value"); err != nil {
global.Log.Warnf("不存在key = [%s] 的系统配置", key) global.Log.Warnf("不存在key = [%s] 的系统配置", key)
} else { } else {
cache.SetStr(SysConfigKeyPrefix+key, utils.ToJsonStr(config), -1) cache.SetStr(SysConfigKeyPrefix+key, jsonx.ToStr(config), -1)
} }
return config return config
} }

View File

@@ -5,7 +5,7 @@ import (
"mayfly-go/internal/sys/domain/repository" "mayfly-go/internal/sys/domain/repository"
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/gormx" "mayfly-go/pkg/gormx"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/stringx"
"strings" "strings"
"time" "time"
) )
@@ -59,7 +59,7 @@ func (r *resourceAppImpl) Save(resource *entity.Resource) {
} }
// 生成随机八位唯一标识符 // 生成随机八位唯一标识符
ui := utils.RandString(8) ui := stringx.Rand(8)
if pid := resource.Pid; pid != 0 { if pid := resource.Pid; pid != 0 {
pResource := r.GetById(uint64(pid)) pResource := r.GetById(uint64(pid))
biz.IsTrue(pResource != nil, "该父资源不存在") biz.IsTrue(pResource != nil, "该父资源不存在")

View File

@@ -8,7 +8,7 @@ import (
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/anyx"
"time" "time"
) )
@@ -50,7 +50,7 @@ func (m *syslogAppImpl) SaveFromReq(req *req.Ctx) {
} }
reqParam := req.ReqParam reqParam := req.ReqParam
if !utils.IsBlank(reqParam) { if !anyx.IsBlank(reqParam) {
// 如果是字符串类型则不使用json序列化 // 如果是字符串类型则不使用json序列化
if reqStr, ok := reqParam.(string); ok { if reqStr, ok := reqParam.(string); ok {
syslog.ReqParam = reqStr syslog.ReqParam = reqStr

View File

@@ -11,7 +11,7 @@ import (
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/ginx" "mayfly-go/pkg/ginx"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/collx"
"strconv" "strconv"
"strings" "strings"
) )
@@ -125,7 +125,7 @@ func (p *Team) SaveTags(rc *req.Ctx) {
oIds := p.TeamApp.ListTagIds(teamId) oIds := p.TeamApp.ListTagIds(teamId)
// 比较新旧两合集 // 比较新旧两合集
addIds, delIds, _ := utils.ArrayCompare(form.TagIds, oIds, func(i1, i2 uint64) bool { addIds, delIds, _ := collx.ArrayCompare(form.TagIds, oIds, func(i1, i2 uint64) bool {
return i1 == i2 return i1 == i2
}) })

View File

@@ -253,7 +253,7 @@ CREATE TABLE `t_machine_cron_job` (
`modifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, `modifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`create_time` datetime DEFAULT NULL, `create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL,
`is_deleted` tinyint NOT NULL DEFAULT '-1', `is_deleted` tinyint NOT NULL DEFAULT 0,
`delete_time` datetime DEFAULT NULL, `delete_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='机器计划任务'; ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='机器计划任务';
@@ -266,7 +266,7 @@ CREATE TABLE `t_machine_cron_job_exec` (
`status` tinyint DEFAULT NULL COMMENT '状态', `status` tinyint DEFAULT NULL COMMENT '状态',
`res` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '执行结果', `res` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '执行结果',
`exec_time` datetime DEFAULT NULL COMMENT '执行时间', `exec_time` datetime DEFAULT NULL COMMENT '执行时间',
`is_deleted` tinyint NOT NULL DEFAULT '-1', `is_deleted` tinyint NOT NULL DEFAULT 0,
`delete_time` datetime DEFAULT NULL, `delete_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='机器计划任务执行记录'; ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='机器计划任务执行记录';
@@ -279,7 +279,7 @@ CREATE TABLE `t_machine_cron_job_relate` (
`creator_id` bigint DEFAULT NULL, `creator_id` bigint DEFAULT NULL,
`creator` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, `creator` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`create_time` datetime DEFAULT NULL, `create_time` datetime DEFAULT NULL,
`is_deleted` tinyint NOT NULL DEFAULT '-1', `is_deleted` tinyint NOT NULL DEFAULT 0,
`delete_time` datetime DEFAULT NULL, `delete_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='机器计划任务关联表'; ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='机器计划任务关联表';

View File

@@ -3,7 +3,7 @@ package biz
import ( import (
"fmt" "fmt"
"mayfly-go/pkg/global" "mayfly-go/pkg/global"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/anyx"
"reflect" "reflect"
) )
@@ -56,7 +56,7 @@ func NotNil(data any, msg string, params ...any) {
} }
func NotBlank(data any, msg string, params ...any) { func NotBlank(data any, msg string, params ...any) {
if utils.IsBlank(data) { if anyx.IsBlank(data) {
panic(NewBizErr(fmt.Sprintf(msg, params...))) panic(NewBizErr(fmt.Sprintf(msg, params...)))
} }
} }

View File

@@ -2,8 +2,8 @@ package config
import ( import (
"fmt" "fmt"
"mayfly-go/pkg/utils"
"mayfly-go/pkg/utils/assert" "mayfly-go/pkg/utils/assert"
"mayfly-go/pkg/utils/cryptox"
) )
type Aes struct { type Aes struct {
@@ -12,12 +12,12 @@ type Aes struct {
// 编码并base64 // 编码并base64
func (a *Aes) EncryptBase64(data []byte) (string, error) { func (a *Aes) EncryptBase64(data []byte) (string, error) {
return utils.AesEncryptBase64(data, []byte(a.Key)) return cryptox.AesEncryptBase64(data, []byte(a.Key))
} }
// base64解码后再aes解码 // base64解码后再aes解码
func (a *Aes) DecryptBase64(data string) ([]byte, error) { func (a *Aes) DecryptBase64(data string) ([]byte, error) {
return utils.AesDecryptBase64(data, []byte(a.Key)) return cryptox.AesDecryptBase64(data, []byte(a.Key))
} }
func (j *Aes) Valid() { func (j *Aes) Valid() {

View File

@@ -3,8 +3,8 @@ package config
import ( import (
"flag" "flag"
"fmt" "fmt"
"mayfly-go/pkg/utils"
"mayfly-go/pkg/utils/assert" "mayfly-go/pkg/utils/assert"
"mayfly-go/pkg/utils/ymlx"
"os" "os"
"path/filepath" "path/filepath"
) )
@@ -20,7 +20,7 @@ func Init() {
startConfigParam := &CmdConfigParam{ConfigFilePath: path} startConfigParam := &CmdConfigParam{ConfigFilePath: path}
// 读取配置文件信息 // 读取配置文件信息
yc := &Config{} yc := &Config{}
if err := utils.LoadYml(startConfigParam.ConfigFilePath, yc); err != nil { if err := ymlx.LoadYml(startConfigParam.ConfigFilePath, yc); err != nil {
panic(fmt.Sprintf("读取配置文件[%s]失败: %s", startConfigParam.ConfigFilePath, err.Error())) panic(fmt.Sprintf("读取配置文件[%s]失败: %s", startConfigParam.ConfigFilePath, err.Error()))
} }
// 校验配置文件内容信息 // 校验配置文件内容信息

View File

@@ -5,7 +5,7 @@ import (
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/global" "mayfly-go/pkg/global"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/structx"
"net/http" "net/http"
"runtime/debug" "runtime/debug"
"strconv" "strconv"
@@ -25,7 +25,7 @@ func BindJsonAndValid[T any](g *gin.Context, data T) T {
// 绑定请求体中的json至form结构体并拷贝至另一结构体 // 绑定请求体中的json至form结构体并拷贝至另一结构体
func BindJsonAndCopyTo[T any](g *gin.Context, form any, toStruct T) T { func BindJsonAndCopyTo[T any](g *gin.Context, form any, toStruct T) T {
BindJsonAndValid(g, form) BindJsonAndValid(g, form)
utils.Copy(toStruct, form) structx.Copy(toStruct, form)
return toStruct return toStruct
} }

View File

@@ -5,7 +5,7 @@ import (
"mayfly-go/pkg/consts" "mayfly-go/pkg/consts"
"mayfly-go/pkg/global" "mayfly-go/pkg/global"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/anyx"
"strings" "strings"
"gorm.io/gorm" "gorm.io/gorm"
@@ -159,7 +159,7 @@ func (q *QueryCond) Le(column string, val any) *QueryCond {
func (q *QueryCond) Cond(cond, column string, val any, skipBlank bool) *QueryCond { func (q *QueryCond) Cond(cond, column string, val any, skipBlank bool) *QueryCond {
// 零值跳过 // 零值跳过
if skipBlank && utils.IsBlank(val) { if skipBlank && anyx.IsBlank(val) {
return q return q
} }
q.columns = append(q.columns, fmt.Sprintf("%s %s ?", column, cond)) q.columns = append(q.columns, fmt.Sprintf("%s %s ?", column, cond))

View File

@@ -0,0 +1,96 @@
package rediscli
import (
"context"
"mayfly-go/pkg/global"
"mayfly-go/pkg/utils/stringx"
"time"
"github.com/redis/go-redis/v9"
)
const LockKeyPrefix = "mayfly:lock:"
// RedisLock redis实现的分布式锁
type RedisLock struct {
key string
value string // 唯一标识,一般使用uuid
expiration time.Duration
}
func NewLock(key string, expiration time.Duration) *RedisLock {
if key == "" || cli == nil {
return nil
}
return &RedisLock{
key: key,
value: stringx.Rand(32),
expiration: expiration,
}
}
// Lock 添加分布式锁,expiration过期时间,小于等于0,不过期,需要通过 UnLock方法释放锁
func (rl *RedisLock) Lock() bool {
result, err := cli.SetNX(context.Background(), LockKeyPrefix+rl.key, rl.value, rl.expiration).Result()
if err != nil {
global.Log.Errorf("redis lock setNx fail: %s", err.Error())
return false
}
return result
}
// TryLock 加锁重试五次
func (rl *RedisLock) TryLock() bool {
var locked bool
for index := 0; index < 5; index++ {
locked = rl.Lock()
if locked {
return locked
}
time.Sleep(50 * time.Millisecond)
}
return locked
}
func (rl *RedisLock) UnLock() bool {
script := redis.NewScript(`
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
`)
result, err := script.Run(context.Background(), cli, []string{LockKeyPrefix + rl.key}, rl.value).Int64()
if err != nil {
global.Log.Errorf("redis unlock runScript fail: %s", err.Error())
return false
}
return result > 0
}
// RefreshLock 存在则更新过期时间,不存在则创建key
func (rl *RedisLock) RefreshLock() bool {
script := redis.NewScript(`
local val = redis.call("GET", KEYS[1])
if not val then
redis.call("setex", KEYS[1], ARGV[2], ARGV[1])
return 2
elseif val == ARGV[1] then
return redis.call("expire", KEYS[1], ARGV[2])
else
return 0
end
`)
result, err := script.Run(context.Background(), cli, []string{LockKeyPrefix + rl.key}, rl.value, rl.expiration/time.Second).Int64()
if err != nil {
global.Log.Errorf("redis refreshLock runScript fail: %s", err.Error())
return false
}
return result > 0
}

View File

@@ -4,7 +4,8 @@ import (
"fmt" "fmt"
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/logger" "mayfly-go/pkg/logger"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/stringx"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@@ -72,21 +73,21 @@ func LogHandler(rc *Ctx) error {
func getLogMsg(rc *Ctx) string { func getLogMsg(rc *Ctx) string {
logInfo := rc.Conf.logInfo logInfo := rc.Conf.logInfo
msg := logInfo.Description + fmt.Sprintf(" ->%dms", rc.timed) msg := logInfo.Description + fmt.Sprintf(" ->%dms", rc.timed)
if !utils.IsBlank(rc.ReqParam) { if !anyx.IsBlank(rc.ReqParam) {
msg = msg + fmt.Sprintf("\n--> %s", utils.ToString(rc.ReqParam)) msg = msg + fmt.Sprintf("\n--> %s", stringx.AnyToStr(rc.ReqParam))
} }
// 返回结果不为空,则记录返回结果 // 返回结果不为空,则记录返回结果
if logInfo.LogResp && !utils.IsBlank(rc.ResData) { if logInfo.LogResp && !anyx.IsBlank(rc.ResData) {
msg = msg + fmt.Sprintf("\n<-- %s", utils.ToString(rc.ResData)) msg = msg + fmt.Sprintf("\n<-- %s", stringx.AnyToStr(rc.ResData))
} }
return msg return msg
} }
func getErrMsg(rc *Ctx, err any) string { func getErrMsg(rc *Ctx, err any) string {
msg := rc.Conf.logInfo.Description msg := rc.Conf.logInfo.Description
if !utils.IsBlank(rc.ReqParam) { if !anyx.IsBlank(rc.ReqParam) {
msg = msg + fmt.Sprintf("\n--> %s", utils.ToString(rc.ReqParam)) msg = msg + fmt.Sprintf("\n--> %s", stringx.AnyToStr(rc.ReqParam))
} }
var errMsg string var errMsg string

View File

@@ -7,7 +7,7 @@ import (
"mayfly-go/pkg/cache" "mayfly-go/pkg/cache"
"mayfly-go/pkg/config" "mayfly-go/pkg/config"
"mayfly-go/pkg/rediscli" "mayfly-go/pkg/rediscli"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/stringx"
"time" "time"
) )
@@ -124,7 +124,7 @@ type RedisPermissionCodeRegistry struct {
} }
func (r *RedisPermissionCodeRegistry) SaveCodes(userId uint64, codes []string) { func (r *RedisPermissionCodeRegistry) SaveCodes(userId uint64, codes []string) {
rediscli.Set(fmt.Sprintf("mayfly:%v:codes", userId), utils.ToString(codes), time.Minute*time.Duration(config.Conf.Jwt.ExpireTime)) rediscli.Set(fmt.Sprintf("mayfly:%v:codes", userId), stringx.AnyToStr(codes), time.Minute*time.Duration(config.Conf.Jwt.ExpireTime))
} }
func (r *RedisPermissionCodeRegistry) HasCode(userId uint64, code string) bool { func (r *RedisPermissionCodeRegistry) HasCode(userId uint64, code string) bool {

View File

@@ -7,7 +7,7 @@ import (
"mayfly-go/pkg/config" "mayfly-go/pkg/config"
"mayfly-go/pkg/global" "mayfly-go/pkg/global"
"mayfly-go/pkg/model" "mayfly-go/pkg/model"
"mayfly-go/pkg/utils" "mayfly-go/pkg/utils/stringx"
"time" "time"
"github.com/golang-jwt/jwt/v5" "github.com/golang-jwt/jwt/v5"
@@ -35,7 +35,7 @@ func CreateToken(userId uint64, username string) string {
// 如果配置文件中的jwt key为空则随机生成字符串 // 如果配置文件中的jwt key为空则随机生成字符串
if JwtKey == "" { if JwtKey == "" {
JwtKey = utils.RandString(32) JwtKey = stringx.Rand(32)
global.Log.Infof("config.yml未配置jwt.key, 随机生成key为: %s", JwtKey) global.Log.Infof("config.yml未配置jwt.key, 随机生成key为: %s", JwtKey)
} }
// 使用自定义字符串加密 and get the complete encoded token as a string // 使用自定义字符串加密 and get the complete encoded token as a string

View File

@@ -1,6 +1,7 @@
package starter package starter
import ( import (
"mayfly-go/initialize"
"mayfly-go/pkg/config" "mayfly-go/pkg/config"
"mayfly-go/pkg/logger" "mayfly-go/pkg/logger"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
@@ -9,17 +10,25 @@ import (
func RunWebServer() { func RunWebServer() {
// 初始化config.yml配置文件映射信息 // 初始化config.yml配置文件映射信息
config.Init() config.Init()
// 初始化日志配置信息 // 初始化日志配置信息
logger.Init() logger.Init()
// 初始化jwt key与expire time等 // 初始化jwt key与expire time等
req.InitTokenConfig() req.InitTokenConfig()
// 打印banner // 打印banner
printBanner() printBanner()
// 初始化并赋值数据库全局变量 // 初始化并赋值数据库全局变量
initDb() initDb()
// 有配置redis信息则初始化redis。多台机器部署需要使用redis存储验证码、权限、公私钥等 // 有配置redis信息则初始化redis。多台机器部署需要使用redis存储验证码、权限、公私钥等
initRedis() initRedis()
// 初始化其他需要启动时运行的方法
initialize.InitOther()
// 运行web服务 // 运行web服务
runWebServer() runWebServer()
} }

View File

@@ -19,9 +19,6 @@ func runWebServer() {
// 注册路由 // 注册路由
web := initialize.InitRouter() web := initialize.InitRouter()
// 初始化其他需要启动时运行的方法
initialize.InitOther()
server := config.Conf.Server server := config.Conf.Server
port := server.GetPort() port := server.GetPort()
global.Log.Infof("Listening and serving HTTP on %s", port) global.Log.Infof("Listening and serving HTTP on %s", port)

View File

@@ -1,54 +0,0 @@
package utils
import (
"strconv"
)
// any类型转换为string, 如果any为nil则返回空字符串
func Any2String(val any) string {
if value, ok := val.(string); !ok {
return ""
} else {
return value
}
}
// any类型转换为int可将字符串或int64转换, 如果any为nil则返回0
func Any2Int(val any) int {
switch value := val.(type) {
case int:
return value
case string:
if intV, err := strconv.Atoi(value); err == nil {
return intV
}
case int64:
return int(value)
case uint64:
return int(value)
case int32:
return int(value)
case uint32:
return int(value)
case int16:
return int(value)
case uint16:
return int(value)
case int8:
return int(value)
case uint8:
return int(value)
default:
return 0
}
return 0
}
// any类型转换为int64, 如果any为nil则返回0
func Any2Int64(val any) int64 {
if value, ok := val.(int64); !ok {
return int64(Any2Int(val))
} else {
return value
}
}

View File

@@ -0,0 +1,77 @@
package anyx
import (
"reflect"
"strconv"
)
// any类型转换为string, 如果any为nil则返回空字符串
func ConvString(val any) string {
if value, ok := val.(string); !ok {
return ""
} else {
return value
}
}
// any类型转换为int可将字符串或int64转换, 如果any为nil则返回0
func ConvInt(val any) int {
switch value := val.(type) {
case int:
return value
case string:
if intV, err := strconv.Atoi(value); err == nil {
return intV
}
case int64:
return int(value)
case uint64:
return int(value)
case int32:
return int(value)
case uint32:
return int(value)
case int16:
return int(value)
case uint16:
return int(value)
case int8:
return int(value)
case uint8:
return int(value)
default:
return 0
}
return 0
}
// any类型转换为int64, 如果any为nil则返回0
func ConvInt64(val any) int64 {
if value, ok := val.(int64); !ok {
return int64(ConvInt(val))
} else {
return value
}
}
func IsBlank(value any) bool {
if value == nil {
return true
}
rValue := reflect.ValueOf(value)
switch rValue.Kind() {
case reflect.String:
return rValue.Len() == 0
case reflect.Bool:
return !rValue.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return rValue.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return rValue.Uint() == 0
case reflect.Float32, reflect.Float64:
return rValue.Float() == 0
case reflect.Interface, reflect.Ptr:
return rValue.IsNil()
}
return reflect.DeepEqual(rValue.Interface(), reflect.Zero(rValue.Type()).Interface())
}

View File

@@ -1,8 +1,6 @@
package utils package collx
import ( import "fmt"
"fmt"
)
// 数组比较 // 数组比较
// 依次返回,新增值,删除值,以及不变值 // 依次返回,新增值,删除值,以及不变值
@@ -53,7 +51,7 @@ func NumberArr2StrArr[T NumT](numberArr []T) []string {
} }
// 判断数组中是否含有指定元素 // 判断数组中是否含有指定元素
func ArrContains[T comparable](arr []T, el T) bool { func ArrayContains[T comparable](arr []T, el T) bool {
for _, v := range arr { for _, v := range arr {
if v == el { if v == el {
return true return true
@@ -64,7 +62,7 @@ func ArrContains[T comparable](arr []T, el T) bool {
// 数组转为map // 数组转为map
// @param keyFunc key的主键 // @param keyFunc key的主键
func Array2Map[T any, K comparable](arr []T, keyFunc func(val T) K) map[K]T { func ArrayToMap[T any, K comparable](arr []T, keyFunc func(val T) K) map[K]T {
res := make(map[K]T, len(arr)) res := make(map[K]T, len(arr))
for _, val := range arr { for _, val := range arr {
key := keyFunc(val) key := keyFunc(val)

View File

@@ -1,4 +1,4 @@
package utils package collx
import ( import (
"fmt" "fmt"

View File

@@ -1,4 +1,4 @@
package utils package collx
import "encoding/binary" import "encoding/binary"

View File

@@ -1,4 +1,4 @@
package utils package collx
import ( import (
"reflect" "reflect"

View File

@@ -1,4 +1,4 @@
package utils package collx
// ConvertToINodeArray 其他的结构体想要生成菜单树,直接实现这个接口 // ConvertToINodeArray 其他的结构体想要生成菜单树,直接实现这个接口
type INode interface { type INode interface {

View File

@@ -1,4 +1,4 @@
package utils package cryptox
import ( import (
"bytes" "bytes"

View File

@@ -1,11 +1,12 @@
package utils package jsonx
import ( import (
"encoding/json" "encoding/json"
"mayfly-go/pkg/global" "mayfly-go/pkg/global"
) )
func Json2Map(jsonStr string) map[string]any { // json字符串转map
func ToMap(jsonStr string) map[string]any {
var res map[string]any var res map[string]any
if jsonStr == "" { if jsonStr == "" {
return res return res
@@ -14,7 +15,8 @@ func Json2Map(jsonStr string) map[string]any {
return res return res
} }
func ToJsonStr(val any) string { // 转换为json字符串
func ToStr(val any) string {
if strBytes, err := json.Marshal(val); err != nil { if strBytes, err := json.Marshal(val); err != nil {
global.Log.Error("toJsonStr error: ", err) global.Log.Error("toJsonStr error: ", err)
return "" return ""

View File

@@ -1,4 +1,4 @@
package utils package netx
import ( import (
"mayfly-go/pkg/global" "mayfly-go/pkg/global"

View File

@@ -1,4 +1,4 @@
package utils package netx
import ( import (
"net" "net"

View File

@@ -1,9 +0,0 @@
package utils
import "runtime"
// 获取调用堆栈信息
func GetStackTrace() string {
var buf [2 << 10]byte
return string(buf[:runtime.Stack(buf[:], false)])
}

View File

@@ -1,4 +1,4 @@
package utils package stringx
import ( import (
"math/rand" "math/rand"
@@ -8,7 +8,7 @@ import (
const randChar = "0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" const randChar = "0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
// 生成随机字符串 // 生成随机字符串
func RandString(l int) string { func Rand(l int) string {
strList := []byte(randChar) strList := []byte(randChar)
result := []byte{} result := []byte{}

View File

@@ -1,4 +1,4 @@
package utils package stringx
import ( import (
"bytes" "bytes"
@@ -9,17 +9,17 @@ import (
) )
// 可判断中文 // 可判断中文
func StrLen(str string) int { func Len(str string) int {
return len([]rune(str)) return len([]rune(str))
} }
// 去除字符串左右空字符 // 去除字符串左右空字符
func StrTrim(str string) string { func Trim(str string) string {
return strings.Trim(str, " ") return strings.Trim(str, " ")
} }
// 去除字符串左右空字符与\n\r换行回车符 // 去除字符串左右空字符与\n\r换行回车符
func StrTrimSpaceAndBr(str string) string { func TrimSpaceAndBr(str string) string {
return strings.TrimFunc(str, func(r rune) bool { return strings.TrimFunc(str, func(r rune) bool {
s := string(r) s := string(r)
return s == " " || s == "\n" || s == "\r" return s == " " || s == "\n" || s == "\r"
@@ -96,7 +96,7 @@ func TemplateResolve(temp string, data any) string {
func ReverStrTemplate(temp, str string, res map[string]any) { func ReverStrTemplate(temp, str string, res map[string]any) {
index := UnicodeIndex(temp, "{") index := UnicodeIndex(temp, "{")
ei := UnicodeIndex(temp, "}") + 1 ei := UnicodeIndex(temp, "}") + 1
next := StrTrim(temp[ei:]) next := Trim(temp[ei:])
nextContain := UnicodeIndex(next, "{") nextContain := UnicodeIndex(next, "{")
nextIndexValue := next nextIndexValue := next
if nextContain != -1 { if nextContain != -1 {
@@ -106,19 +106,19 @@ func ReverStrTemplate(temp, str string, res map[string]any) {
// 如果后面没有内容了,则取字符串的长度即可 // 如果后面没有内容了,则取字符串的长度即可
var valueLastIndex int var valueLastIndex int
if nextIndexValue == "" { if nextIndexValue == "" {
valueLastIndex = StrLen(str) valueLastIndex = Len(str)
} else { } else {
valueLastIndex = UnicodeIndex(str, nextIndexValue) valueLastIndex = UnicodeIndex(str, nextIndexValue)
} }
value := StrTrim(SubString(str, index, valueLastIndex)) value := Trim(SubString(str, index, valueLastIndex))
res[key] = value res[key] = value
// 如果后面的还有需要解析的,则递归调用解析 // 如果后面的还有需要解析的,则递归调用解析
if nextContain != -1 { if nextContain != -1 {
ReverStrTemplate(next, StrTrim(SubString(str, UnicodeIndex(str, value)+StrLen(value), StrLen(str))), res) ReverStrTemplate(next, Trim(SubString(str, UnicodeIndex(str, value)+Len(value), Len(str))), res)
} }
} }
func ToString(value any) string { func AnyToStr(value any) string {
// interface 转 string // interface 转 string
var key string var key string
if value == nil { if value == nil {

View File

@@ -1,4 +1,4 @@
package utils package stringx
import ( import (
"bytes" "bytes"

View File

@@ -1,4 +1,4 @@
package utils package structx
import ( import (
"database/sql" "database/sql"

View File

@@ -1,7 +1,8 @@
package utils package structx
import ( import (
"fmt" "fmt"
"mayfly-go/pkg/utils/stringx"
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
@@ -188,7 +189,7 @@ func TestTemplateResolve(t *testing.T) {
d := make(map[string]string) d := make(map[string]string)
d["Name"] = "黄先生" d["Name"] = "黄先生"
d["Age"] = "23jlfdsjf" d["Age"] = "23jlfdsjf"
resolve := TemplateResolve("{{.Name}} is name, and {{.Age}} is age", d) resolve := stringx.TemplateResolve("{{.Name}} is name, and {{.Age}} is age", d)
fmt.Println(resolve) fmt.Println(resolve)
} }

View File

@@ -1,7 +0,0 @@
package utils
import "time"
func DefaultTimeFormat(time time.Time) string {
return time.Format("2006-01-02 15:04:05")
}

View File

@@ -0,0 +1,7 @@
package timex
import "time"
func DefaultFormat(time time.Time) string {
return time.Format("2006-01-02 15:04:05")
}

View File

@@ -1,4 +1,4 @@
package utils package ymlx
import ( import (
"errors" "errors"