mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-03 16:00:25 +08:00
feat: 代码优化、机器计划任务完善
This commit is contained in:
@@ -251,7 +251,6 @@ onMounted(async () => {
|
||||
const handleCommand = (commond: any) => {
|
||||
const data = commond.data;
|
||||
const type = commond.type;
|
||||
console.log(type);
|
||||
switch (type) {
|
||||
case 'detail': {
|
||||
showInfo(data);
|
||||
|
||||
@@ -3,14 +3,14 @@ package api
|
||||
import (
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/req"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/cryptox"
|
||||
)
|
||||
|
||||
type Common struct {
|
||||
}
|
||||
|
||||
func (i *Common) RasPublicKey(rc *req.Ctx) {
|
||||
publicKeyStr, err := utils.GetRsaPublicKey()
|
||||
publicKeyStr, err := cryptox.GetRsaPublicKey()
|
||||
biz.ErrIsNilAppendErr(err, "rsa生成公私钥失败")
|
||||
rc.ResData = publicKeyStr
|
||||
}
|
||||
|
||||
@@ -14,7 +14,9 @@ import (
|
||||
"mayfly-go/pkg/gormx"
|
||||
"mayfly-go/pkg/model"
|
||||
"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"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -57,7 +59,7 @@ func (d *Db) Save(rc *req.Ctx) {
|
||||
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")
|
||||
db.Password = originPwd
|
||||
|
||||
@@ -83,10 +85,10 @@ func (d *Db) GetDatabaseNames(rc *req.Ctx) {
|
||||
ginx.BindJsonAndValid(rc.GinCtx, form)
|
||||
|
||||
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")
|
||||
db.Password = originPwd
|
||||
|
||||
@@ -143,7 +145,7 @@ func (d *Db) ExecSql(rc *req.Ctx) {
|
||||
biz.NotEmpty(form.Sql, "sql不能为空")
|
||||
|
||||
// 去除前后空格及换行符
|
||||
sql := utils.StrTrimSpaceAndBr(form.Sql)
|
||||
sql := stringx.TrimSpaceAndBr(form.Sql)
|
||||
|
||||
execReq := &application.DbSqlExecReq{
|
||||
DbId: id,
|
||||
@@ -158,7 +160,7 @@ func (d *Db) ExecSql(rc *req.Ctx) {
|
||||
isMulti := len(sqls) > 1
|
||||
var execResAll *application.DbSqlExecRes
|
||||
for _, s := range sqls {
|
||||
s = utils.StrTrimSpaceAndBr(s)
|
||||
s = stringx.TrimSpaceAndBr(s)
|
||||
// 多条执行,如果有查询语句,则跳过
|
||||
if isMulti && strings.HasPrefix(strings.ToLower(s), "select") {
|
||||
continue
|
||||
@@ -308,7 +310,7 @@ func (d *Db) DumpSql(rc *req.Ctx) {
|
||||
if ok {
|
||||
values = append(values, fmt.Sprintf("%#v", strValue))
|
||||
} else {
|
||||
values = append(values, utils.ToString(value))
|
||||
values = append(values, stringx.AnyToStr(value))
|
||||
}
|
||||
}
|
||||
writer.WriteString(fmt.Sprintf(insertSql, table, strings.Join(values, ", ")))
|
||||
|
||||
@@ -11,7 +11,8 @@ import (
|
||||
"mayfly-go/pkg/cache"
|
||||
"mayfly-go/pkg/global"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/collx"
|
||||
"mayfly-go/pkg/utils/structx"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -120,7 +121,7 @@ func (d *dbAppImpl) Save(dbEntity *entity.Db) {
|
||||
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)
|
||||
})
|
||||
for _, v := range delDb {
|
||||
@@ -193,7 +194,7 @@ func (da *dbAppImpl) GetDbInstance(id uint64, db string) *DbInstance {
|
||||
d.PwdDecrypt()
|
||||
|
||||
dbInfo := new(DbInfo)
|
||||
utils.Copy(dbInfo, d)
|
||||
structx.Copy(dbInfo, d)
|
||||
dbInfo.Database = db
|
||||
dbi := &DbInstance{Id: cacheKey, Info: dbInfo}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package application
|
||||
import (
|
||||
"embed"
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/stringx"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -88,7 +88,7 @@ func GetLocalSql(file, key string) string {
|
||||
sqls := strings.Split(allSql, "---------------------------------------")
|
||||
var resSql string
|
||||
for _, sql := range sqls {
|
||||
sql = utils.StrTrimSpaceAndBr(sql)
|
||||
sql = stringx.TrimSpaceAndBr(sql)
|
||||
// 获取sql第一行的sql备注信息如:--MYSQL_TABLE_MA 表信息元数据
|
||||
info := strings.SplitN(sql, "\n", 2)
|
||||
// 原始sql,即去除第一行的key与备注信息
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"mayfly-go/internal/db/domain/entity"
|
||||
machineapp "mayfly-go/internal/machine/application"
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/anyx"
|
||||
"net"
|
||||
|
||||
"github.com/go-sql-driver/mysql"
|
||||
@@ -51,7 +51,7 @@ func (mm *MysqlMetadata) GetTables() []Table {
|
||||
for _, re := range res {
|
||||
tables = append(tables, Table{
|
||||
TableName: re["tableName"].(string),
|
||||
TableComment: utils.Any2String(re["tableComment"]),
|
||||
TableComment: anyx.ConvString(re["tableComment"]),
|
||||
})
|
||||
}
|
||||
return tables
|
||||
@@ -74,11 +74,11 @@ func (mm *MysqlMetadata) GetColumns(tableNames ...string) []Column {
|
||||
columns = append(columns, Column{
|
||||
TableName: re["tableName"].(string),
|
||||
ColumnName: re["columnName"].(string),
|
||||
ColumnType: utils.Any2String(re["columnType"]),
|
||||
ColumnComment: utils.Any2String(re["columnComment"]),
|
||||
Nullable: utils.Any2String(re["nullable"]),
|
||||
ColumnKey: utils.Any2String(re["columnKey"]),
|
||||
ColumnDefault: utils.Any2String(re["columnDefault"]),
|
||||
ColumnType: anyx.ConvString(re["columnType"]),
|
||||
ColumnComment: anyx.ConvString(re["columnComment"]),
|
||||
Nullable: anyx.ConvString(re["nullable"]),
|
||||
ColumnKey: anyx.ConvString(re["columnKey"]),
|
||||
ColumnDefault: anyx.ConvString(re["columnDefault"]),
|
||||
})
|
||||
}
|
||||
return columns
|
||||
@@ -106,11 +106,11 @@ func (mm *MysqlMetadata) GetTableInfos() []Table {
|
||||
for _, re := range res {
|
||||
tables = append(tables, Table{
|
||||
TableName: re["tableName"].(string),
|
||||
TableComment: utils.Any2String(re["tableComment"]),
|
||||
CreateTime: utils.Any2String(re["createTime"]),
|
||||
TableRows: utils.Any2Int(re["tableRows"]),
|
||||
DataLength: utils.Any2Int64(re["dataLength"]),
|
||||
IndexLength: utils.Any2Int64(re["indexLength"]),
|
||||
TableComment: anyx.ConvString(re["tableComment"]),
|
||||
CreateTime: anyx.ConvString(re["createTime"]),
|
||||
TableRows: anyx.ConvInt(re["tableRows"]),
|
||||
DataLength: anyx.ConvInt64(re["dataLength"]),
|
||||
IndexLength: anyx.ConvInt64(re["indexLength"]),
|
||||
})
|
||||
}
|
||||
return tables
|
||||
@@ -124,11 +124,11 @@ func (mm *MysqlMetadata) GetTableIndex(tableName string) []Index {
|
||||
for _, re := range res {
|
||||
indexs = append(indexs, Index{
|
||||
IndexName: re["indexName"].(string),
|
||||
ColumnName: utils.Any2String(re["columnName"]),
|
||||
IndexType: utils.Any2String(re["indexType"]),
|
||||
IndexComment: utils.Any2String(re["indexComment"]),
|
||||
NonUnique: utils.Any2Int(re["nonUnique"]),
|
||||
SeqInIndex: utils.Any2Int(re["seqInIndex"]),
|
||||
ColumnName: anyx.ConvString(re["columnName"]),
|
||||
IndexType: anyx.ConvString(re["indexType"]),
|
||||
IndexComment: anyx.ConvString(re["indexComment"]),
|
||||
NonUnique: anyx.ConvInt(re["nonUnique"]),
|
||||
SeqInIndex: anyx.ConvInt(re["seqInIndex"]),
|
||||
})
|
||||
}
|
||||
// 把查询结果以索引名分组,索引字段以逗号连接
|
||||
|
||||
@@ -7,7 +7,8 @@ import (
|
||||
"mayfly-go/internal/db/domain/entity"
|
||||
machineapp "mayfly-go/internal/machine/application"
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/anyx"
|
||||
"mayfly-go/pkg/utils/collx"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -21,7 +22,7 @@ func getPgsqlDB(d *entity.Db, db string) (*sql.DB, error) {
|
||||
if d.SshTunnelMachineId > 0 {
|
||||
// 如果使用了隧道,则使用`postgres:ssh:隧道机器id`注册名
|
||||
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.Drivers()
|
||||
@@ -78,7 +79,7 @@ func (pm *PgsqlMetadata) GetTables() []Table {
|
||||
for _, re := range res {
|
||||
tables = append(tables, Table{
|
||||
TableName: re["tableName"].(string),
|
||||
TableComment: utils.Any2String(re["tableComment"]),
|
||||
TableComment: anyx.ConvString(re["tableComment"]),
|
||||
})
|
||||
}
|
||||
return tables
|
||||
@@ -101,11 +102,11 @@ func (pm *PgsqlMetadata) GetColumns(tableNames ...string) []Column {
|
||||
columns = append(columns, Column{
|
||||
TableName: re["tableName"].(string),
|
||||
ColumnName: re["columnName"].(string),
|
||||
ColumnType: utils.Any2String(re["columnType"]),
|
||||
ColumnComment: utils.Any2String(re["columnComment"]),
|
||||
Nullable: utils.Any2String(re["nullable"]),
|
||||
ColumnKey: utils.Any2String(re["columnKey"]),
|
||||
ColumnDefault: utils.Any2String(re["columnDefault"]),
|
||||
ColumnType: anyx.ConvString(re["columnType"]),
|
||||
ColumnComment: anyx.ConvString(re["columnComment"]),
|
||||
Nullable: anyx.ConvString(re["nullable"]),
|
||||
ColumnKey: anyx.ConvString(re["columnKey"]),
|
||||
ColumnDefault: anyx.ConvString(re["columnDefault"]),
|
||||
})
|
||||
}
|
||||
return columns
|
||||
@@ -132,11 +133,11 @@ func (pm *PgsqlMetadata) GetTableInfos() []Table {
|
||||
for _, re := range res {
|
||||
tables = append(tables, Table{
|
||||
TableName: re["tableName"].(string),
|
||||
TableComment: utils.Any2String(re["tableComment"]),
|
||||
CreateTime: utils.Any2String(re["createTime"]),
|
||||
TableRows: utils.Any2Int(re["tableRows"]),
|
||||
DataLength: utils.Any2Int64(re["dataLength"]),
|
||||
IndexLength: utils.Any2Int64(re["indexLength"]),
|
||||
TableComment: anyx.ConvString(re["tableComment"]),
|
||||
CreateTime: anyx.ConvString(re["createTime"]),
|
||||
TableRows: anyx.ConvInt(re["tableRows"]),
|
||||
DataLength: anyx.ConvInt64(re["dataLength"]),
|
||||
IndexLength: anyx.ConvInt64(re["indexLength"]),
|
||||
})
|
||||
}
|
||||
return tables
|
||||
@@ -150,11 +151,11 @@ func (pm *PgsqlMetadata) GetTableIndex(tableName string) []Index {
|
||||
for _, re := range res {
|
||||
indexs = append(indexs, Index{
|
||||
IndexName: re["indexName"].(string),
|
||||
ColumnName: utils.Any2String(re["columnName"]),
|
||||
IndexType: utils.Any2String(re["indexType"]),
|
||||
IndexComment: utils.Any2String(re["indexComment"]),
|
||||
NonUnique: utils.Any2Int(re["nonUnique"]),
|
||||
SeqInIndex: utils.Any2Int(re["seqInIndex"]),
|
||||
ColumnName: anyx.ConvString(re["columnName"]),
|
||||
IndexType: anyx.ConvString(re["indexType"]),
|
||||
IndexComment: anyx.ConvString(re["indexComment"]),
|
||||
NonUnique: anyx.ConvInt(re["nonUnique"]),
|
||||
SeqInIndex: anyx.ConvInt(re["seqInIndex"]),
|
||||
})
|
||||
}
|
||||
return indexs
|
||||
|
||||
@@ -14,7 +14,8 @@ import (
|
||||
"mayfly-go/pkg/ginx"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/req"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/stringx"
|
||||
"mayfly-go/pkg/utils/structx"
|
||||
"mayfly-go/pkg/ws"
|
||||
"os"
|
||||
"path"
|
||||
@@ -82,7 +83,7 @@ func (m *Machine) TestConn(rc *req.Ctx) {
|
||||
ginx.BindJsonAndValid(g, machineForm)
|
||||
|
||||
me := new(entity.Machine)
|
||||
utils.Copy(me, machineForm)
|
||||
structx.Copy(me, machineForm)
|
||||
|
||||
m.MachineApp.TestConn(me)
|
||||
}
|
||||
@@ -192,7 +193,7 @@ func (m *Machine) WsSSH(g *gin.Context) {
|
||||
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")
|
||||
|
||||
// 记录系统操作日志
|
||||
|
||||
@@ -10,7 +10,8 @@ import (
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/ginx"
|
||||
"mayfly-go/pkg/req"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/jsonx"
|
||||
"mayfly-go/pkg/utils/stringx"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -63,7 +64,7 @@ func (m *MachineScript) RunMachineScript(rc *req.Ctx) {
|
||||
script := ms.Script
|
||||
// 如果有脚本参数,则用脚本参数替换脚本中的模板占位符参数
|
||||
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)
|
||||
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
|
||||
|
||||
@@ -5,8 +5,10 @@ import (
|
||||
"mayfly-go/internal/machine/domain/repository"
|
||||
"mayfly-go/pkg/global"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/rediscli"
|
||||
"mayfly-go/pkg/scheduler"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/collx"
|
||||
"mayfly-go/pkg/utils/stringx"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -107,7 +109,7 @@ func (m *machineCropJobAppImpl) GetRelateCronJobIds(machineId uint64) []uint64 {
|
||||
|
||||
func (m *machineCropJobAppImpl) CronJobRelateMachines(cronJobId uint64, machineIds []uint64, la *model.LoginAccount) {
|
||||
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)
|
||||
|
||||
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) {
|
||||
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)
|
||||
|
||||
now := time.Now()
|
||||
@@ -186,7 +188,7 @@ func (m *machineCropJobAppImpl) addCronJob(mcj *entity.MachineCronJob) {
|
||||
var key string
|
||||
isDisable := mcj.Status == entity.MachineCronJobStatusDisable
|
||||
if mcj.Id == 0 {
|
||||
key = utils.RandString(16)
|
||||
key = stringx.Rand(16)
|
||||
mcj.Key = key
|
||||
if isDisable {
|
||||
return
|
||||
@@ -201,11 +203,19 @@ func (m *machineCropJobAppImpl) addCronJob(mcj *entity.MachineCronJob) {
|
||||
}
|
||||
|
||||
scheduler.AddFunByKey(key, mcj.Cron, func() {
|
||||
m.runCronJob(key)
|
||||
go m.runCronJob(key)
|
||||
})
|
||||
}
|
||||
|
||||
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.Key = key
|
||||
err := m.machineCropJobRepo.GetBy(cronJob)
|
||||
|
||||
@@ -2,7 +2,7 @@ package machine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/stringx"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@@ -69,7 +69,7 @@ func TestTemplateRev(t *testing.T) {
|
||||
//key := temp[index+1 : ei-1]
|
||||
//value := SubString(str, index, UnicodeIndex(str, next))
|
||||
res := make(map[string]any)
|
||||
utils.ReverStrTemplate(temp, str, res)
|
||||
stringx.ReverStrTemplate(temp, str, res)
|
||||
fmt.Println(res)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"io"
|
||||
"mayfly-go/pkg/global"
|
||||
"mayfly-go/pkg/scheduler"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/netx"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
@@ -75,7 +75,7 @@ func (stm *SshTunnelMachine) OpenSshTunnel(id uint64, ip string, port int) (expo
|
||||
stm.mutex.Lock()
|
||||
defer stm.mutex.Unlock()
|
||||
|
||||
localPort, err := utils.GetAvailablePort()
|
||||
localPort, err := netx.GetAvailablePort()
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/gormx"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/collx"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@@ -29,7 +29,7 @@ func (m *machineRepoImpl) GetMachineList(condition *entity.MachineQuery, pagePar
|
||||
|
||||
if condition.Ids != "" {
|
||||
// ,分割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)
|
||||
return uint64(id)
|
||||
}))
|
||||
|
||||
@@ -12,7 +12,8 @@ import (
|
||||
"mayfly-go/pkg/cache"
|
||||
"mayfly-go/pkg/global"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/netx"
|
||||
"mayfly-go/pkg/utils/structx"
|
||||
"net"
|
||||
"regexp"
|
||||
"time"
|
||||
@@ -201,7 +202,7 @@ func connect(me *entity.Mongo) (*MongoInstance, error) {
|
||||
|
||||
func toMongiInfo(me *entity.Mongo) *MongoInfo {
|
||||
mi := new(MongoInfo)
|
||||
utils.Copy(mi, me)
|
||||
structx.Copy(mi, me)
|
||||
return mi
|
||||
}
|
||||
|
||||
@@ -212,7 +213,7 @@ type MongoSshDialer struct {
|
||||
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 {
|
||||
// 将ssh conn包装,否则内部部设置超时会报错,ssh conn不支持设置超时会返回错误: ssh: tcpChan: deadline not supported
|
||||
return &utils.WrapSshConn{Conn: sshConn}, nil
|
||||
return &netx.WrapSshConn{Conn: sshConn}, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ import (
|
||||
"mayfly-go/pkg/ginx"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/req"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/cryptox"
|
||||
"mayfly-go/pkg/utils/stringx"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -47,7 +48,7 @@ func (r *Redis) Save(rc *req.Ctx) {
|
||||
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")
|
||||
redis.Password = originPwd
|
||||
|
||||
@@ -133,7 +134,7 @@ func (r *Redis) RedisInfo(rc *req.Ctx) {
|
||||
break
|
||||
}
|
||||
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++
|
||||
key = strings.Trim(key, " ")
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/ginx"
|
||||
"mayfly-go/pkg/req"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/stringx"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -25,7 +25,7 @@ func (r *Redis) SetStringValue(rc *req.Ctx) {
|
||||
|
||||
ri := r.getRedisIns(rc)
|
||||
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()
|
||||
biz.ErrIsNilAppendErr(err, "保存字符串值失败: %s")
|
||||
|
||||
@@ -12,7 +12,8 @@ import (
|
||||
"mayfly-go/pkg/cache"
|
||||
"mayfly-go/pkg/global"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/netx"
|
||||
"mayfly-go/pkg/utils/structx"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -176,7 +177,7 @@ func getRedisCacheKey(id uint64, db int) string {
|
||||
|
||||
func toRedisInfo(re *entity.Redis, db int) *RedisInfo {
|
||||
redisInfo := new(RedisInfo)
|
||||
utils.Copy(redisInfo, re)
|
||||
structx.Copy(redisInfo, re)
|
||||
redisInfo.Db = db
|
||||
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) {
|
||||
if sshConn, err := sshTunnel.GetDialConn(network, addr); err == nil {
|
||||
// 将ssh conn包装,否则redis内部设置超时会报错,ssh conn不支持设置超时会返回错误: ssh: tcpChan: deadline not supported
|
||||
return &utils.WrapSshConn{Conn: sshConn}, nil
|
||||
return &netx.WrapSshConn{Conn: sshConn}, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -16,7 +16,12 @@ import (
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/otp"
|
||||
"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"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -55,7 +60,7 @@ func (a *Account) Login(rc *req.Ctx) {
|
||||
clientIp := getIpAndRegion(rc)
|
||||
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")
|
||||
|
||||
account := &entity.Account{Username: username}
|
||||
@@ -67,7 +72,7 @@ func (a *Account) Login(rc *req.Ctx) {
|
||||
loginFailMin := accountLoginSecurity.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++
|
||||
cache.SetStr(failCountKey, strconv.Itoa(nowFailCount), time.Minute*time.Duration(loginFailMin))
|
||||
panic(biz.NewBizErr(fmt.Sprintf("用户名或密码错误【当前登录失败%d次】", nowFailCount)))
|
||||
@@ -96,7 +101,7 @@ func (a *Account) Login(rc *req.Ctx) {
|
||||
// 修改状态为已注册
|
||||
otpStatus = OtpStatusReg
|
||||
// 该token用于otp双因素校验
|
||||
token = utils.RandString(32)
|
||||
token = stringx.Rand(32)
|
||||
// 未注册otp secret或重置了秘钥
|
||||
if otpSecret == "" || otpSecret == "-" {
|
||||
otpStatus = OtpStatusNoReg
|
||||
@@ -116,7 +121,7 @@ func (a *Account) Login(rc *req.Ctx) {
|
||||
OtpSecret: otpSecret,
|
||||
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 {
|
||||
// 不进行otp二次校验则直接返回accessToken
|
||||
token = accessToken
|
||||
@@ -133,7 +138,7 @@ func (a *Account) Login(rc *req.Ctx) {
|
||||
// 获取ip与归属地信息
|
||||
func getIpAndRegion(rc *req.Ctx) string {
|
||||
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 {
|
||||
@@ -214,22 +219,22 @@ func (a *Account) ChangePassword(rc *req.Ctx) {
|
||||
form := new(form.AccountChangePasswordForm)
|
||||
ginx.BindJsonAndValid(rc.GinCtx, form)
|
||||
|
||||
originOldPwd, err := utils.DefaultRsaDecrypt(form.OldPassword, true)
|
||||
originOldPwd, err := cryptox.DefaultRsaDecrypt(form.OldPassword, true)
|
||||
biz.ErrIsNilAppendErr(err, "解密旧密码错误: %s")
|
||||
|
||||
account := &entity.Account{Username: form.Username}
|
||||
err = a.AccountApp.GetAccount(account, "Id", "Username", "Password", "Status")
|
||||
biz.ErrIsNil(err, "旧密码错误")
|
||||
biz.IsTrue(utils.CheckPwdHash(originOldPwd, account.Password), "旧密码错误")
|
||||
biz.IsTrue(cryptox.CheckPwdHash(originOldPwd, account.Password), "旧密码错误")
|
||||
biz.IsTrue(account.IsEnable(), "该账号不可用")
|
||||
|
||||
originNewPwd, err := utils.DefaultRsaDecrypt(form.NewPassword, true)
|
||||
originNewPwd, err := cryptox.DefaultRsaDecrypt(form.NewPassword, true)
|
||||
biz.ErrIsNilAppendErr(err, "解密新密码错误: %s")
|
||||
biz.IsTrue(CheckPasswordLever(originNewPwd), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号")
|
||||
|
||||
updateAccount := new(entity.Account)
|
||||
updateAccount.Id = account.Id
|
||||
updateAccount.Password = utils.PwdHash(originNewPwd)
|
||||
updateAccount.Password = cryptox.PwdHash(originNewPwd)
|
||||
a.AccountApp.Update(updateAccount)
|
||||
|
||||
// 赋值loginAccount 主要用于记录操作日志,因为操作日志保存请求上下文没有该信息不保存日志
|
||||
@@ -267,7 +272,7 @@ func (a *Account) saveLogin(account *entity.Account, ip string) {
|
||||
// 创建登录消息
|
||||
loginMsg := &msgentity.Msg{
|
||||
RecipientId: int64(account.Id),
|
||||
Msg: fmt.Sprintf("于[%s]-[%s]登录", ip, utils.DefaultTimeFormat(now)),
|
||||
Msg: fmt.Sprintf("于[%s]-[%s]登录", ip, timex.DefaultFormat(now)),
|
||||
Type: 1,
|
||||
}
|
||||
loginMsg.CreateTime = &now
|
||||
@@ -295,7 +300,7 @@ func (a *Account) UpdateAccount(rc *req.Ctx) {
|
||||
|
||||
if updateAccount.Password != "" {
|
||||
biz.IsTrue(CheckPasswordLever(updateAccount.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号")
|
||||
updateAccount.Password = utils.PwdHash(updateAccount.Password)
|
||||
updateAccount.Password = cryptox.PwdHash(updateAccount.Password)
|
||||
}
|
||||
a.AccountApp.Update(updateAccount)
|
||||
}
|
||||
@@ -323,7 +328,7 @@ func (a *Account) SaveAccount(rc *req.Ctx) {
|
||||
} else {
|
||||
if account.Password != "" {
|
||||
biz.IsTrue(CheckPasswordLever(account.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号")
|
||||
account.Password = utils.PwdHash(account.Password)
|
||||
account.Password = cryptox.PwdHash(account.Password)
|
||||
}
|
||||
a.AccountApp.Update(account)
|
||||
}
|
||||
@@ -380,14 +385,14 @@ func (a *Account) SaveRoles(rc *req.Ctx) {
|
||||
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)
|
||||
return uint64(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
|
||||
})
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"mayfly-go/pkg/ginx"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/req"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/collx"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -72,14 +72,14 @@ func (r *Role) SaveResource(rc *req.Ctx) {
|
||||
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)
|
||||
return uint64(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
|
||||
})
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/gormx"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/cryptox"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -45,7 +45,7 @@ func (a *accountAppImpl) GetPageList(condition *entity.Account, pageParam *model
|
||||
func (a *accountAppImpl) Create(account *entity.Account) {
|
||||
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
|
||||
a.accountRepo.Insert(account)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"mayfly-go/pkg/cache"
|
||||
"mayfly-go/pkg/global"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/jsonx"
|
||||
)
|
||||
|
||||
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 {
|
||||
global.Log.Warnf("不存在key = [%s] 的系统配置", key)
|
||||
} else {
|
||||
cache.SetStr(SysConfigKeyPrefix+key, utils.ToJsonStr(config), -1)
|
||||
cache.SetStr(SysConfigKeyPrefix+key, jsonx.ToStr(config), -1)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"mayfly-go/internal/sys/domain/repository"
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/gormx"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/stringx"
|
||||
"strings"
|
||||
"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 {
|
||||
pResource := r.GetById(uint64(pid))
|
||||
biz.IsTrue(pResource != nil, "该父资源不存在")
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/req"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/anyx"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -50,7 +50,7 @@ func (m *syslogAppImpl) SaveFromReq(req *req.Ctx) {
|
||||
}
|
||||
|
||||
reqParam := req.ReqParam
|
||||
if !utils.IsBlank(reqParam) {
|
||||
if !anyx.IsBlank(reqParam) {
|
||||
// 如果是字符串类型,则不使用json序列化
|
||||
if reqStr, ok := reqParam.(string); ok {
|
||||
syslog.ReqParam = reqStr
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/ginx"
|
||||
"mayfly-go/pkg/req"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/collx"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@@ -125,7 +125,7 @@ func (p *Team) SaveTags(rc *req.Ctx) {
|
||||
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
|
||||
})
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ CREATE TABLE `t_machine_cron_job` (
|
||||
`modifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
|
||||
`create_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,
|
||||
PRIMARY KEY (`id`)
|
||||
) 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 '状态',
|
||||
`res` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin 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,
|
||||
PRIMARY KEY (`id`)
|
||||
) 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` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin 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,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='机器计划任务关联表';
|
||||
|
||||
@@ -3,7 +3,7 @@ package biz
|
||||
import (
|
||||
"fmt"
|
||||
"mayfly-go/pkg/global"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/anyx"
|
||||
|
||||
"reflect"
|
||||
)
|
||||
@@ -56,7 +56,7 @@ func NotNil(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...)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/assert"
|
||||
"mayfly-go/pkg/utils/cryptox"
|
||||
)
|
||||
|
||||
type Aes struct {
|
||||
@@ -12,12 +12,12 @@ type Aes struct {
|
||||
|
||||
// 编码并base64
|
||||
func (a *Aes) EncryptBase64(data []byte) (string, error) {
|
||||
return utils.AesEncryptBase64(data, []byte(a.Key))
|
||||
return cryptox.AesEncryptBase64(data, []byte(a.Key))
|
||||
}
|
||||
|
||||
// base64解码后再aes解码
|
||||
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() {
|
||||
|
||||
@@ -3,8 +3,8 @@ package config
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/assert"
|
||||
"mayfly-go/pkg/utils/ymlx"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
@@ -20,7 +20,7 @@ func Init() {
|
||||
startConfigParam := &CmdConfigParam{ConfigFilePath: path}
|
||||
// 读取配置文件信息
|
||||
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()))
|
||||
}
|
||||
// 校验配置文件内容信息
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/global"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/structx"
|
||||
"net/http"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
@@ -25,7 +25,7 @@ func BindJsonAndValid[T any](g *gin.Context, data T) T {
|
||||
// 绑定请求体中的json至form结构体,并拷贝至另一结构体
|
||||
func BindJsonAndCopyTo[T any](g *gin.Context, form any, toStruct T) T {
|
||||
BindJsonAndValid(g, form)
|
||||
utils.Copy(toStruct, form)
|
||||
structx.Copy(toStruct, form)
|
||||
return toStruct
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"mayfly-go/pkg/consts"
|
||||
"mayfly-go/pkg/global"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/anyx"
|
||||
"strings"
|
||||
|
||||
"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 {
|
||||
// 零值跳过
|
||||
if skipBlank && utils.IsBlank(val) {
|
||||
if skipBlank && anyx.IsBlank(val) {
|
||||
return q
|
||||
}
|
||||
q.columns = append(q.columns, fmt.Sprintf("%s %s ?", column, cond))
|
||||
|
||||
96
server/pkg/rediscli/lock.go
Normal file
96
server/pkg/rediscli/lock.go
Normal 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
|
||||
}
|
||||
@@ -4,7 +4,8 @@ import (
|
||||
"fmt"
|
||||
"mayfly-go/pkg/biz"
|
||||
"mayfly-go/pkg/logger"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/anyx"
|
||||
"mayfly-go/pkg/utils/stringx"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -72,21 +73,21 @@ func LogHandler(rc *Ctx) error {
|
||||
func getLogMsg(rc *Ctx) string {
|
||||
logInfo := rc.Conf.logInfo
|
||||
msg := logInfo.Description + fmt.Sprintf(" ->%dms", rc.timed)
|
||||
if !utils.IsBlank(rc.ReqParam) {
|
||||
msg = msg + fmt.Sprintf("\n--> %s", utils.ToString(rc.ReqParam))
|
||||
if !anyx.IsBlank(rc.ReqParam) {
|
||||
msg = msg + fmt.Sprintf("\n--> %s", stringx.AnyToStr(rc.ReqParam))
|
||||
}
|
||||
|
||||
// 返回结果不为空,则记录返回结果
|
||||
if logInfo.LogResp && !utils.IsBlank(rc.ResData) {
|
||||
msg = msg + fmt.Sprintf("\n<-- %s", utils.ToString(rc.ResData))
|
||||
if logInfo.LogResp && !anyx.IsBlank(rc.ResData) {
|
||||
msg = msg + fmt.Sprintf("\n<-- %s", stringx.AnyToStr(rc.ResData))
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func getErrMsg(rc *Ctx, err any) string {
|
||||
msg := rc.Conf.logInfo.Description
|
||||
if !utils.IsBlank(rc.ReqParam) {
|
||||
msg = msg + fmt.Sprintf("\n--> %s", utils.ToString(rc.ReqParam))
|
||||
if !anyx.IsBlank(rc.ReqParam) {
|
||||
msg = msg + fmt.Sprintf("\n--> %s", stringx.AnyToStr(rc.ReqParam))
|
||||
}
|
||||
|
||||
var errMsg string
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"mayfly-go/pkg/cache"
|
||||
"mayfly-go/pkg/config"
|
||||
"mayfly-go/pkg/rediscli"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/stringx"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -124,7 +124,7 @@ type RedisPermissionCodeRegistry struct {
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"mayfly-go/pkg/config"
|
||||
"mayfly-go/pkg/global"
|
||||
"mayfly-go/pkg/model"
|
||||
"mayfly-go/pkg/utils"
|
||||
"mayfly-go/pkg/utils/stringx"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
@@ -35,7 +35,7 @@ func CreateToken(userId uint64, username string) string {
|
||||
|
||||
// 如果配置文件中的jwt key为空,则随机生成字符串
|
||||
if JwtKey == "" {
|
||||
JwtKey = utils.RandString(32)
|
||||
JwtKey = stringx.Rand(32)
|
||||
global.Log.Infof("config.yml未配置jwt.key, 随机生成key为: %s", JwtKey)
|
||||
}
|
||||
// 使用自定义字符串加密 and get the complete encoded token as a string
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package starter
|
||||
|
||||
import (
|
||||
"mayfly-go/initialize"
|
||||
"mayfly-go/pkg/config"
|
||||
"mayfly-go/pkg/logger"
|
||||
"mayfly-go/pkg/req"
|
||||
@@ -9,17 +10,25 @@ import (
|
||||
func RunWebServer() {
|
||||
// 初始化config.yml配置文件映射信息
|
||||
config.Init()
|
||||
|
||||
// 初始化日志配置信息
|
||||
logger.Init()
|
||||
|
||||
// 初始化jwt key与expire time等
|
||||
req.InitTokenConfig()
|
||||
|
||||
// 打印banner
|
||||
printBanner()
|
||||
|
||||
// 初始化并赋值数据库全局变量
|
||||
initDb()
|
||||
|
||||
// 有配置redis信息,则初始化redis。多台机器部署需要使用redis存储验证码、权限、公私钥等
|
||||
initRedis()
|
||||
|
||||
// 初始化其他需要启动时运行的方法
|
||||
initialize.InitOther()
|
||||
|
||||
// 运行web服务
|
||||
runWebServer()
|
||||
}
|
||||
|
||||
@@ -19,9 +19,6 @@ func runWebServer() {
|
||||
// 注册路由
|
||||
web := initialize.InitRouter()
|
||||
|
||||
// 初始化其他需要启动时运行的方法
|
||||
initialize.InitOther()
|
||||
|
||||
server := config.Conf.Server
|
||||
port := server.GetPort()
|
||||
global.Log.Infof("Listening and serving HTTP on %s", port)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
77
server/pkg/utils/anyx/anyx.go
Normal file
77
server/pkg/utils/anyx/anyx.go
Normal 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())
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
package utils
|
||||
package collx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
import "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 {
|
||||
if v == el {
|
||||
return true
|
||||
@@ -64,7 +62,7 @@ func ArrContains[T comparable](arr []T, el T) bool {
|
||||
|
||||
// 数组转为map
|
||||
// @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))
|
||||
for _, val := range arr {
|
||||
key := keyFunc(val)
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package collx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package collx
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package collx
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package collx
|
||||
|
||||
// ConvertToINodeArray 其他的结构体想要生成菜单树,直接实现这个接口
|
||||
type INode interface {
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package cryptox
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -1,11 +1,12 @@
|
||||
package utils
|
||||
package jsonx
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"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
|
||||
if jsonStr == "" {
|
||||
return res
|
||||
@@ -14,7 +15,8 @@ func Json2Map(jsonStr string) map[string]any {
|
||||
return res
|
||||
}
|
||||
|
||||
func ToJsonStr(val any) string {
|
||||
// 转换为json字符串
|
||||
func ToStr(val any) string {
|
||||
if strBytes, err := json.Marshal(val); err != nil {
|
||||
global.Log.Error("toJsonStr error: ", err)
|
||||
return ""
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package netx
|
||||
|
||||
import (
|
||||
"mayfly-go/pkg/global"
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package netx
|
||||
|
||||
import (
|
||||
"net"
|
||||
@@ -1,9 +0,0 @@
|
||||
package utils
|
||||
|
||||
import "runtime"
|
||||
|
||||
// 获取调用堆栈信息
|
||||
func GetStackTrace() string {
|
||||
var buf [2 << 10]byte
|
||||
return string(buf[:runtime.Stack(buf[:], false)])
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package stringx
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
const randChar = "0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
|
||||
// 生成随机字符串
|
||||
func RandString(l int) string {
|
||||
func Rand(l int) string {
|
||||
strList := []byte(randChar)
|
||||
|
||||
result := []byte{}
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package stringx
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -9,17 +9,17 @@ import (
|
||||
)
|
||||
|
||||
// 可判断中文
|
||||
func StrLen(str string) int {
|
||||
func Len(str string) int {
|
||||
return len([]rune(str))
|
||||
}
|
||||
|
||||
// 去除字符串左右空字符
|
||||
func StrTrim(str string) string {
|
||||
func Trim(str string) string {
|
||||
return strings.Trim(str, " ")
|
||||
}
|
||||
|
||||
// 去除字符串左右空字符与\n\r换行回车符
|
||||
func StrTrimSpaceAndBr(str string) string {
|
||||
func TrimSpaceAndBr(str string) string {
|
||||
return strings.TrimFunc(str, func(r rune) bool {
|
||||
s := string(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) {
|
||||
index := UnicodeIndex(temp, "{")
|
||||
ei := UnicodeIndex(temp, "}") + 1
|
||||
next := StrTrim(temp[ei:])
|
||||
next := Trim(temp[ei:])
|
||||
nextContain := UnicodeIndex(next, "{")
|
||||
nextIndexValue := next
|
||||
if nextContain != -1 {
|
||||
@@ -106,19 +106,19 @@ func ReverStrTemplate(temp, str string, res map[string]any) {
|
||||
// 如果后面没有内容了,则取字符串的长度即可
|
||||
var valueLastIndex int
|
||||
if nextIndexValue == "" {
|
||||
valueLastIndex = StrLen(str)
|
||||
valueLastIndex = Len(str)
|
||||
} else {
|
||||
valueLastIndex = UnicodeIndex(str, nextIndexValue)
|
||||
}
|
||||
value := StrTrim(SubString(str, index, valueLastIndex))
|
||||
value := Trim(SubString(str, index, valueLastIndex))
|
||||
res[key] = value
|
||||
// 如果后面的还有需要解析的,则递归调用解析
|
||||
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
|
||||
var key string
|
||||
if value == nil {
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package stringx
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package structx
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@@ -1,7 +1,8 @@
|
||||
package utils
|
||||
package structx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mayfly-go/pkg/utils/stringx"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -188,7 +189,7 @@ func TestTemplateResolve(t *testing.T) {
|
||||
d := make(map[string]string)
|
||||
d["Name"] = "黄先生"
|
||||
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)
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package utils
|
||||
|
||||
import "time"
|
||||
|
||||
func DefaultTimeFormat(time time.Time) string {
|
||||
return time.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
7
server/pkg/utils/timex/timex.go
Normal file
7
server/pkg/utils/timex/timex.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package timex
|
||||
|
||||
import "time"
|
||||
|
||||
func DefaultFormat(time time.Time) string {
|
||||
return time.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package ymlx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
Reference in New Issue
Block a user