mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 08:20:25 +08:00 
			
		
		
		
	refactor: 新增base.Repo与base.App,重构repo与app层代码
This commit is contained in:
		@@ -12,6 +12,7 @@ import (
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/cache"
 | 
			
		||||
	"mayfly-go/pkg/captcha"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/ginx"
 | 
			
		||||
	"mayfly-go/pkg/otp"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
@@ -49,7 +50,7 @@ func (a *AccountLogin) Login(rc *req.Ctx) {
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "解密密码错误: %s")
 | 
			
		||||
 | 
			
		||||
	account := &sysentity.Account{Username: username}
 | 
			
		||||
	err = a.AccountApp.GetAccount(account, "Id", "Name", "Username", "Password", "Status", "LastLoginTime", "LastLoginIp", "OtpSecret")
 | 
			
		||||
	err = a.AccountApp.GetBy(account, "Id", "Name", "Username", "Password", "Status", "LastLoginTime", "LastLoginIp", "OtpSecret")
 | 
			
		||||
 | 
			
		||||
	failCountKey := fmt.Sprintf("account:login:failcount:%s", username)
 | 
			
		||||
	nowFailCount := cache.GetInt(failCountKey)
 | 
			
		||||
@@ -60,11 +61,11 @@ func (a *AccountLogin) Login(rc *req.Ctx) {
 | 
			
		||||
	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)))
 | 
			
		||||
		panic(errorx.NewBiz(fmt.Sprintf("用户名或密码错误【当前登录失败%d次】", nowFailCount)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 校验密码强度(新用户第一次登录密码与账号名一致)
 | 
			
		||||
	biz.IsTrueBy(utils.CheckAccountPasswordLever(originPwd), biz.NewBizErrCode(401, "您的密码安全等级较低,请修改后重新登录"))
 | 
			
		||||
	biz.IsTrueBy(utils.CheckAccountPasswordLever(originPwd), errorx.NewBizCode(401, "您的密码安全等级较低,请修改后重新登录"))
 | 
			
		||||
	rc.ResData = LastLoginCheck(account, accountLoginSecurity, clientIp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -98,7 +99,7 @@ func (a *AccountLogin) OtpVerify(rc *req.Ctx) {
 | 
			
		||||
 | 
			
		||||
	if !otp.Validate(otpVerify.Code, otpSecret) {
 | 
			
		||||
		cache.SetStr(failCountKey, strconv.Itoa(failCount+1), time.Minute*time.Duration(10))
 | 
			
		||||
		panic(biz.NewBizErr("双因素认证授权码不正确"))
 | 
			
		||||
		panic(errorx.NewBiz("双因素认证授权码不正确"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 如果是未注册状态,则更新account表的otpSecret信息
 | 
			
		||||
@@ -106,7 +107,7 @@ func (a *AccountLogin) OtpVerify(rc *req.Ctx) {
 | 
			
		||||
		update := &sysentity.Account{OtpSecret: otpSecret}
 | 
			
		||||
		update.Id = accountId
 | 
			
		||||
		update.OtpSecretEncrypt()
 | 
			
		||||
		a.AccountApp.Update(update)
 | 
			
		||||
		biz.ErrIsNil(a.AccountApp.Update(update))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	la := &sysentity.Account{Username: otpInfo.Username}
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,9 @@ func LastLoginCheck(account *sysentity.Account, accountLoginSecurity *config.Acc
 | 
			
		||||
	// 默认为不校验otp
 | 
			
		||||
	otpStatus := OtpStatusNone
 | 
			
		||||
	// 访问系统使用的token
 | 
			
		||||
	accessToken := req.CreateToken(account.Id, username)
 | 
			
		||||
	accessToken, err := req.CreateToken(account.Id, username)
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "token创建失败: %s")
 | 
			
		||||
 | 
			
		||||
	// 若系统配置中设置开启otp双因素校验,则进行otp校验
 | 
			
		||||
	if accountLoginSecurity.UseOtp {
 | 
			
		||||
		otpInfo, otpurl, otpToken := useOtp(account, accountLoginSecurity.OtpIssuer, accessToken)
 | 
			
		||||
@@ -106,7 +108,7 @@ func saveLogin(account *sysentity.Account, ip string) {
 | 
			
		||||
	updateAccount.Id = account.Id
 | 
			
		||||
	updateAccount.LastLoginIp = ip
 | 
			
		||||
	// 偷懒为了方便直接获取accountApp
 | 
			
		||||
	sysapp.GetAccountApp().Update(updateAccount)
 | 
			
		||||
	biz.ErrIsNil(sysapp.GetAccountApp().Update(updateAccount))
 | 
			
		||||
 | 
			
		||||
	// 创建登录消息
 | 
			
		||||
	loginMsg := &msgentity.Msg{
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ import (
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/cache"
 | 
			
		||||
	"mayfly-go/pkg/captcha"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/ginx"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
	"mayfly-go/pkg/utils/collx"
 | 
			
		||||
@@ -69,7 +70,7 @@ func (a *LdapLogin) Login(rc *req.Ctx) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		nowFailCount++
 | 
			
		||||
		cache.SetStr(failCountKey, strconv.Itoa(nowFailCount), time.Minute*time.Duration(loginFailMin))
 | 
			
		||||
		panic(biz.NewBizErr(fmt.Sprintf("用户名或密码错误【当前登录失败%d次】", nowFailCount)))
 | 
			
		||||
		panic(errorx.NewBiz(fmt.Sprintf("用户名或密码错误【当前登录失败%d次】", nowFailCount)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc.ResData = LastLoginCheck(account, accountLoginSecurity, clientIp)
 | 
			
		||||
@@ -77,7 +78,7 @@ func (a *LdapLogin) Login(rc *req.Ctx) {
 | 
			
		||||
 | 
			
		||||
func (a *LdapLogin) getUser(userName string, cols ...string) (*sysentity.Account, error) {
 | 
			
		||||
	account := &sysentity.Account{Username: userName}
 | 
			
		||||
	if err := a.AccountApp.GetAccount(account, cols...); err != nil {
 | 
			
		||||
	if err := a.AccountApp.GetBy(account, cols...); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return account, nil
 | 
			
		||||
@@ -87,10 +88,10 @@ func (a *LdapLogin) createUser(userName, displayName string) {
 | 
			
		||||
	account := &sysentity.Account{Username: userName}
 | 
			
		||||
	account.SetBaseInfo(nil)
 | 
			
		||||
	account.Name = displayName
 | 
			
		||||
	a.AccountApp.Create(account)
 | 
			
		||||
	biz.ErrIsNil(a.AccountApp.Create(account))
 | 
			
		||||
	// 将 LADP 用户本地密码设置为空,不允许本地登录
 | 
			
		||||
	account.Password = cryptox.PwdHash("")
 | 
			
		||||
	a.AccountApp.Update(account)
 | 
			
		||||
	biz.ErrIsNil(a.AccountApp.Update(account))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *LdapLogin) getOrCreateUserWithLdap(userName string, password string, cols ...string) (*sysentity.Account, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@ import (
 | 
			
		||||
	sysentity "mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/cache"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
	"mayfly-go/pkg/utils/collx"
 | 
			
		||||
@@ -97,7 +98,7 @@ func (a *Oauth2Login) OAuth2Callback(rc *req.Ctx) {
 | 
			
		||||
 | 
			
		||||
		account := new(sysentity.Account)
 | 
			
		||||
		account.Id = accountId
 | 
			
		||||
		err = a.AccountApp.GetAccount(account, "username")
 | 
			
		||||
		err = a.AccountApp.GetBy(account, "username")
 | 
			
		||||
		biz.ErrIsNilAppendErr(err, "该账号不存在")
 | 
			
		||||
		rc.ReqParam = collx.Kvs("username", account.Username, "type", "bind")
 | 
			
		||||
 | 
			
		||||
@@ -125,7 +126,7 @@ func (a *Oauth2Login) OAuth2Callback(rc *req.Ctx) {
 | 
			
		||||
		}
 | 
			
		||||
		rc.ResData = res
 | 
			
		||||
	} else {
 | 
			
		||||
		panic(biz.NewBizErr("state不合法"))
 | 
			
		||||
		panic(errorx.NewBiz("state不合法"))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -151,7 +152,7 @@ func (a *Oauth2Login) doLoginAction(rc *req.Ctx, userId string, oauth *config.Oa
 | 
			
		||||
			Name:     userId,
 | 
			
		||||
			Username: userId,
 | 
			
		||||
		}
 | 
			
		||||
		a.AccountApp.Create(account)
 | 
			
		||||
		biz.ErrIsNil(a.AccountApp.Create(account))
 | 
			
		||||
		// 绑定
 | 
			
		||||
		err := a.Oauth2App.BindOAuthAccount(&entity.Oauth2Account{
 | 
			
		||||
			AccountId:  account.Id,
 | 
			
		||||
@@ -170,7 +171,7 @@ func (a *Oauth2Login) doLoginAction(rc *req.Ctx, userId string, oauth *config.Oa
 | 
			
		||||
	account := &sysentity.Account{
 | 
			
		||||
		Model: model.Model{DeletedModel: model.DeletedModel{Id: accountId}},
 | 
			
		||||
	}
 | 
			
		||||
	err = a.AccountApp.GetAccount(account, "Id", "Name", "Username", "Password", "Status", "LastLoginTime", "LastLoginIp", "OtpSecret")
 | 
			
		||||
	err = a.AccountApp.GetBy(account, "Id", "Name", "Username", "Password", "Status", "LastLoginTime", "LastLoginIp", "OtpSecret")
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取用户信息失败: %s")
 | 
			
		||||
 | 
			
		||||
	clientIp := getIpAndRegion(rc)
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,6 @@ package application
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/auth/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/auth/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Oauth2 interface {
 | 
			
		||||
@@ -27,18 +24,16 @@ type oauth2AppImpl struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *oauth2AppImpl) GetOAuthAccount(condition *entity.Oauth2Account, cols ...string) error {
 | 
			
		||||
	err := a.oauthAccountRepo.GetOAuthAccount(condition, cols...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// 排除其他报错,如表不存在等
 | 
			
		||||
		biz.IsTrue(err == gorm.ErrRecordNotFound, "查询失败: %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
	return a.oauthAccountRepo.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *oauth2AppImpl) BindOAuthAccount(e *entity.Oauth2Account) error {
 | 
			
		||||
	return a.oauthAccountRepo.SaveOAuthAccount(e)
 | 
			
		||||
	if e.Id == 0 {
 | 
			
		||||
		return a.oauthAccountRepo.Insert(e)
 | 
			
		||||
	}
 | 
			
		||||
	return a.oauthAccountRepo.UpdateById(e)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *oauth2AppImpl) Unbind(accountId uint64) {
 | 
			
		||||
	a.oauthAccountRepo.DeleteBy(&entity.Oauth2Account{AccountId: accountId})
 | 
			
		||||
	a.oauthAccountRepo.DeleteByCond(&entity.Oauth2Account{AccountId: accountId})
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,10 @@
 | 
			
		||||
package repository
 | 
			
		||||
 | 
			
		||||
import "mayfly-go/internal/auth/domain/entity"
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/auth/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Oauth2Account interface {
 | 
			
		||||
	// GetOAuthAccount 根据identity获取第三方账号信息
 | 
			
		||||
	GetOAuthAccount(condition *entity.Oauth2Account, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	SaveOAuthAccount(e *entity.Oauth2Account) error
 | 
			
		||||
 | 
			
		||||
	DeleteBy(e *entity.Oauth2Account)
 | 
			
		||||
	base.Repo[*entity.Oauth2Account]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,26 +3,13 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/auth/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/auth/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type oauth2AccountRepoImpl struct{}
 | 
			
		||||
type oauth2AccountRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.Oauth2Account]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newAuthAccountRepo() repository.Oauth2Account {
 | 
			
		||||
	return new(oauth2AccountRepoImpl)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *oauth2AccountRepoImpl) GetOAuthAccount(condition *entity.Oauth2Account, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *oauth2AccountRepoImpl) SaveOAuthAccount(e *entity.Oauth2Account) error {
 | 
			
		||||
	if e.Id == 0 {
 | 
			
		||||
		return gormx.Insert(e)
 | 
			
		||||
	}
 | 
			
		||||
	return gormx.UpdateById(e)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *oauth2AccountRepoImpl) DeleteBy(e *entity.Oauth2Account) {
 | 
			
		||||
	gormx.DeleteByCondition(e)
 | 
			
		||||
	return &oauth2AccountRepoImpl{base.RepoImpl[*entity.Oauth2Account]{M: new(entity.Oauth2Account)}}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,9 @@ func (d *Db) Dbs(rc *req.Ctx) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	queryCond.TagIds = tagIds
 | 
			
		||||
	rc.ResData = d.DbApp.GetPageList(queryCond, page, new([]vo.SelectDataDbVO))
 | 
			
		||||
	res, err := d.DbApp.GetPageList(queryCond, page, new([]vo.SelectDataDbVO))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Db) DbTags(rc *req.Ctx) {
 | 
			
		||||
@@ -62,7 +64,7 @@ func (d *Db) Save(rc *req.Ctx) {
 | 
			
		||||
	rc.ReqParam = form
 | 
			
		||||
 | 
			
		||||
	db.SetBaseInfo(rc.LoginAccount)
 | 
			
		||||
	d.DbApp.Save(db)
 | 
			
		||||
	biz.ErrIsNil(d.DbApp.Save(db))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Db) DeleteDb(rc *req.Ctx) {
 | 
			
		||||
@@ -81,23 +83,31 @@ func (d *Db) DeleteDb(rc *req.Ctx) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Db) getDbConnection(g *gin.Context) *application.DbConnection {
 | 
			
		||||
	return d.DbApp.GetDbConnection(getDbId(g), getDbName(g))
 | 
			
		||||
	dc, err := d.DbApp.GetDbConnection(getDbId(g), getDbName(g))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	return dc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Db) TableInfos(rc *req.Ctx) {
 | 
			
		||||
	rc.ResData = d.getDbConnection(rc.GinCtx).GetMeta().GetTableInfos()
 | 
			
		||||
	res, err := d.getDbConnection(rc.GinCtx).GetMeta().GetTableInfos()
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取表信息失败: %s")
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Db) TableIndex(rc *req.Ctx) {
 | 
			
		||||
	tn := rc.GinCtx.Query("tableName")
 | 
			
		||||
	biz.NotEmpty(tn, "tableName不能为空")
 | 
			
		||||
	rc.ResData = d.getDbConnection(rc.GinCtx).GetMeta().GetTableIndex(tn)
 | 
			
		||||
	res, err := d.getDbConnection(rc.GinCtx).GetMeta().GetTableIndex(tn)
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取表索引信息失败: %s")
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Db) GetCreateTableDdl(rc *req.Ctx) {
 | 
			
		||||
	tn := rc.GinCtx.Query("tableName")
 | 
			
		||||
	biz.NotEmpty(tn, "tableName不能为空")
 | 
			
		||||
	rc.ResData = d.getDbConnection(rc.GinCtx).GetMeta().GetCreateTableDdl(tn)
 | 
			
		||||
	res, err := d.getDbConnection(rc.GinCtx).GetMeta().GetCreateTableDdl(tn)
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取表ddl失败: %s")
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Db) ExecSql(rc *req.Ctx) {
 | 
			
		||||
@@ -106,7 +116,8 @@ func (d *Db) ExecSql(rc *req.Ctx) {
 | 
			
		||||
	ginx.BindJsonAndValid(g, form)
 | 
			
		||||
 | 
			
		||||
	dbId := getDbId(g)
 | 
			
		||||
	dbConn := d.DbApp.GetDbConnection(dbId, form.Db)
 | 
			
		||||
	dbConn, err := d.DbApp.GetDbConnection(dbId, form.Db)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbConn.Info.TagPath), "%s")
 | 
			
		||||
 | 
			
		||||
	rc.ReqParam = fmt.Sprintf("%s\n-> %s", dbConn.Info.GetLogDesc(), form.Sql)
 | 
			
		||||
@@ -177,7 +188,8 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) {
 | 
			
		||||
	dbName := getDbName(g)
 | 
			
		||||
	clientId := g.Query("clientId")
 | 
			
		||||
 | 
			
		||||
	dbConn := d.DbApp.GetDbConnection(dbId, dbName)
 | 
			
		||||
	dbConn, err := d.DbApp.GetDbConnection(dbId, dbName)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbConn.Info.TagPath), "%s")
 | 
			
		||||
	rc.ReqParam = fmt.Sprintf("filename: %s -> %s", filename, dbConn.Info.GetLogDesc())
 | 
			
		||||
 | 
			
		||||
@@ -244,7 +256,8 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) {
 | 
			
		||||
			if !ok {
 | 
			
		||||
				logx.Warnf("sql解析失败: %s", sql)
 | 
			
		||||
			}
 | 
			
		||||
			dbConn = d.DbApp.GetDbConnection(dbId, stmtUse.DBName.String())
 | 
			
		||||
			dbConn, err = d.DbApp.GetDbConnection(dbId, stmtUse.DBName.String())
 | 
			
		||||
			biz.ErrIsNil(err)
 | 
			
		||||
			biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbConn.Info.TagPath), "%s")
 | 
			
		||||
			execReq.DbConn = dbConn
 | 
			
		||||
		}
 | 
			
		||||
@@ -282,7 +295,8 @@ func (d *Db) DumpSql(rc *req.Ctx) {
 | 
			
		||||
	// 是否需要导出数据
 | 
			
		||||
	needData := dumpType == "2" || dumpType == "3"
 | 
			
		||||
 | 
			
		||||
	db := d.DbApp.GetById(dbId)
 | 
			
		||||
	db, err := d.DbApp.GetById(new(entity.Db), dbId)
 | 
			
		||||
	biz.ErrIsNil(err, "该数据库不存在")
 | 
			
		||||
	biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, db.TagPath), "%s")
 | 
			
		||||
 | 
			
		||||
	now := time.Now()
 | 
			
		||||
@@ -320,7 +334,8 @@ func (d *Db) DumpSql(rc *req.Ctx) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Db) dumpDb(writer *gzipWriter, dbId uint64, dbName string, tables []string, needStruct bool, needData bool) {
 | 
			
		||||
	dbConn := d.DbApp.GetDbConnection(dbId, dbName)
 | 
			
		||||
	dbConn, err := d.DbApp.GetDbConnection(dbId, dbName)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	writer.WriteString("\n-- ----------------------------")
 | 
			
		||||
	writer.WriteString("\n-- 导出平台: mayfly-go")
 | 
			
		||||
	writer.WriteString(fmt.Sprintf("\n-- 导出时间: %s ", time.Now().Format("2006-01-02 15:04:05")))
 | 
			
		||||
@@ -332,7 +347,8 @@ func (d *Db) dumpDb(writer *gzipWriter, dbId uint64, dbName string, tables []str
 | 
			
		||||
 | 
			
		||||
	dbMeta := dbConn.GetMeta()
 | 
			
		||||
	if len(tables) == 0 {
 | 
			
		||||
		ti := dbMeta.GetTableInfos()
 | 
			
		||||
		ti, err := dbMeta.GetTableInfos()
 | 
			
		||||
		biz.ErrIsNil(err)
 | 
			
		||||
		tables = make([]string, len(ti))
 | 
			
		||||
		for i, table := range ti {
 | 
			
		||||
			tables[i] = table.TableName
 | 
			
		||||
@@ -345,7 +361,9 @@ func (d *Db) dumpDb(writer *gzipWriter, dbId uint64, dbName string, tables []str
 | 
			
		||||
		if needStruct {
 | 
			
		||||
			writer.WriteString(fmt.Sprintf("\n-- ----------------------------\n-- 表结构: %s \n-- ----------------------------\n", table))
 | 
			
		||||
			writer.WriteString(fmt.Sprintf("DROP TABLE IF EXISTS %s;\n", quotedTable))
 | 
			
		||||
			writer.WriteString(dbMeta.GetCreateTableDdl(table) + "\n")
 | 
			
		||||
			ddl, err := dbMeta.GetCreateTableDdl(table)
 | 
			
		||||
			biz.ErrIsNil(err)
 | 
			
		||||
			writer.WriteString(ddl + "\n")
 | 
			
		||||
		}
 | 
			
		||||
		if !needData {
 | 
			
		||||
			continue
 | 
			
		||||
@@ -380,7 +398,9 @@ func (d *Db) dumpDb(writer *gzipWriter, dbId uint64, dbName string, tables []str
 | 
			
		||||
// @router /api/db/:dbId/t-metadata [get]
 | 
			
		||||
func (d *Db) TableMA(rc *req.Ctx) {
 | 
			
		||||
	dbi := d.getDbConnection(rc.GinCtx)
 | 
			
		||||
	rc.ResData = dbi.GetMeta().GetTables()
 | 
			
		||||
	res, err := dbi.GetMeta().GetTables()
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取表基础信息失败: %s")
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// @router /api/db/:dbId/c-metadata [get]
 | 
			
		||||
@@ -390,7 +410,9 @@ func (d *Db) ColumnMA(rc *req.Ctx) {
 | 
			
		||||
	biz.NotEmpty(tn, "tableName不能为空")
 | 
			
		||||
 | 
			
		||||
	dbi := d.getDbConnection(rc.GinCtx)
 | 
			
		||||
	rc.ResData = dbi.GetMeta().GetColumns(tn)
 | 
			
		||||
	res, err := dbi.GetMeta().GetColumns(tn)
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取数据库列信息失败: %s")
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// @router /api/db/:dbId/hint-tables [get]
 | 
			
		||||
@@ -399,7 +421,8 @@ func (d *Db) HintTables(rc *req.Ctx) {
 | 
			
		||||
 | 
			
		||||
	dm := dbi.GetMeta()
 | 
			
		||||
	// 获取所有表
 | 
			
		||||
	tables := dm.GetTables()
 | 
			
		||||
	tables, err := dm.GetTables()
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	tableNames := make([]string, 0)
 | 
			
		||||
	for _, v := range tables {
 | 
			
		||||
		tableNames = append(tableNames, v.TableName)
 | 
			
		||||
@@ -414,7 +437,8 @@ func (d *Db) HintTables(rc *req.Ctx) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 获取所有表下的所有列信息
 | 
			
		||||
	columnMds := dm.GetColumns(tableNames...)
 | 
			
		||||
	columnMds, err := dm.GetColumns(tableNames...)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	for _, v := range columnMds {
 | 
			
		||||
		tName := v.TableName
 | 
			
		||||
		if res[tName] == nil {
 | 
			
		||||
@@ -481,8 +505,7 @@ func (d *Db) DeleteSql(rc *req.Ctx) {
 | 
			
		||||
	dbSql.Name = rc.GinCtx.Query("name")
 | 
			
		||||
	dbSql.Db = rc.GinCtx.Query("db")
 | 
			
		||||
 | 
			
		||||
	gormx.DeleteByCondition(dbSql)
 | 
			
		||||
 | 
			
		||||
	biz.ErrIsNil(gormx.DeleteBy(dbSql))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// @router /api/db/:dbId/sql [get]
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package api
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/db/application"
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/ginx"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
)
 | 
			
		||||
@@ -14,5 +15,7 @@ type DbSqlExec struct {
 | 
			
		||||
func (d *DbSqlExec) DbSqlExecs(rc *req.Ctx) {
 | 
			
		||||
	queryCond, page := ginx.BindQueryAndPage(rc.GinCtx, new(entity.DbSqlExecQuery))
 | 
			
		||||
	queryCond.CreatorId = rc.LoginAccount.Id
 | 
			
		||||
	rc.ResData = d.DbSqlExecApp.GetPageList(queryCond, page, new([]entity.DbSqlExec))
 | 
			
		||||
	res, err := d.DbSqlExecApp.GetPageList(queryCond, page, new([]entity.DbSqlExec))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,9 @@ type Instance struct {
 | 
			
		||||
// @router /api/instances [get]
 | 
			
		||||
func (d *Instance) Instances(rc *req.Ctx) {
 | 
			
		||||
	queryCond, page := ginx.BindQueryAndPage[*entity.InstanceQuery](rc.GinCtx, new(entity.InstanceQuery))
 | 
			
		||||
	rc.ResData = d.InstanceApp.GetPageList(queryCond, page, new([]vo.SelectDataInstanceVO))
 | 
			
		||||
	res, err := d.InstanceApp.GetPageList(queryCond, page, new([]vo.SelectDataInstanceVO))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SaveInstance 保存数据库实例信息
 | 
			
		||||
@@ -43,15 +45,15 @@ func (d *Instance) SaveInstance(rc *req.Ctx) {
 | 
			
		||||
	rc.ReqParam = form
 | 
			
		||||
 | 
			
		||||
	instance.SetBaseInfo(rc.LoginAccount)
 | 
			
		||||
	d.InstanceApp.Save(instance)
 | 
			
		||||
	biz.ErrIsNil(d.InstanceApp.Save(instance))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetInstance 获取数据库实例密码,由于数据库是加密存储,故提供该接口展示原文密码
 | 
			
		||||
// @router /api/instances/:instance [GET]
 | 
			
		||||
func (d *Instance) GetInstance(rc *req.Ctx) {
 | 
			
		||||
	dbId := getInstanceId(rc.GinCtx)
 | 
			
		||||
	dbEntity := d.InstanceApp.GetById(dbId)
 | 
			
		||||
	biz.IsTrue(dbEntity != nil, "获取数据库实例错误")
 | 
			
		||||
	dbEntity, err := d.InstanceApp.GetById(new(entity.Instance), dbId)
 | 
			
		||||
	biz.ErrIsNil(err, "获取数据库实例错误")
 | 
			
		||||
	dbEntity.Password = ""
 | 
			
		||||
	rc.ResData = dbEntity
 | 
			
		||||
}
 | 
			
		||||
@@ -60,8 +62,8 @@ func (d *Instance) GetInstance(rc *req.Ctx) {
 | 
			
		||||
// @router /api/instances/:instance/pwd [GET]
 | 
			
		||||
func (d *Instance) GetInstancePwd(rc *req.Ctx) {
 | 
			
		||||
	instanceId := getInstanceId(rc.GinCtx)
 | 
			
		||||
	instanceEntity := d.InstanceApp.GetById(instanceId, "Password")
 | 
			
		||||
	biz.IsTrue(instanceEntity != nil, "获取数据库实例错误")
 | 
			
		||||
	instanceEntity, err := d.InstanceApp.GetById(new(entity.Instance), instanceId, "Password")
 | 
			
		||||
	biz.ErrIsNil(err, "获取数据库实例错误")
 | 
			
		||||
	instanceEntity.PwdDecrypt()
 | 
			
		||||
	rc.ResData = instanceEntity.Password
 | 
			
		||||
}
 | 
			
		||||
@@ -78,8 +80,8 @@ func (d *Instance) DeleteInstance(rc *req.Ctx) {
 | 
			
		||||
		biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s")
 | 
			
		||||
		instanceId := uint64(value)
 | 
			
		||||
		if d.DbApp.Count(&entity.DbQuery{InstanceId: instanceId}) != 0 {
 | 
			
		||||
			instance := d.InstanceApp.GetById(instanceId, "name")
 | 
			
		||||
			biz.NotNil(instance, "获取数据库实例错误,数据库实例ID为:%d", instance.Id)
 | 
			
		||||
			instance, err := d.InstanceApp.GetById(new(entity.Instance), instanceId, "name")
 | 
			
		||||
			biz.ErrIsNil(err, "获取数据库实例错误,数据库实例ID为: %d", instance.Id)
 | 
			
		||||
			biz.IsTrue(false, "不能删除数据库实例【%s】,请先删除其关联的数据库资源。", instance.Name)
 | 
			
		||||
		}
 | 
			
		||||
		d.InstanceApp.Delete(instanceId)
 | 
			
		||||
@@ -89,10 +91,12 @@ func (d *Instance) DeleteInstance(rc *req.Ctx) {
 | 
			
		||||
// 获取数据库实例的所有数据库名
 | 
			
		||||
func (d *Instance) GetDatabaseNames(rc *req.Ctx) {
 | 
			
		||||
	instanceId := getInstanceId(rc.GinCtx)
 | 
			
		||||
	instance := d.InstanceApp.GetById(instanceId, "Password")
 | 
			
		||||
	biz.IsTrue(instance != nil, "获取数据库实例错误")
 | 
			
		||||
	instance, err := d.InstanceApp.GetById(new(entity.Instance), instanceId, "Password")
 | 
			
		||||
	biz.ErrIsNil(err, "获取数据库实例错误")
 | 
			
		||||
	instance.PwdDecrypt()
 | 
			
		||||
	rc.ResData = d.InstanceApp.GetDatabases(instance)
 | 
			
		||||
	res, err := d.InstanceApp.GetDatabases(instance)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getInstanceId(g *gin.Context) uint64 {
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,9 @@ import (
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/db/domain/repository"
 | 
			
		||||
	"mayfly-go/internal/machine/infrastructure/machine"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/cache"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/logx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
	"mayfly-go/pkg/utils/collx"
 | 
			
		||||
@@ -20,79 +21,71 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Db interface {
 | 
			
		||||
	base.App[*entity.Db]
 | 
			
		||||
 | 
			
		||||
	// 分页获取
 | 
			
		||||
	GetPageList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	Count(condition *entity.DbQuery) int64
 | 
			
		||||
 | 
			
		||||
	// 根据条件获取
 | 
			
		||||
	GetDbBy(condition *entity.Db, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.Db
 | 
			
		||||
 | 
			
		||||
	Save(entity *entity.Db)
 | 
			
		||||
	Save(entity *entity.Db) error
 | 
			
		||||
 | 
			
		||||
	// 删除数据库信息
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
	Delete(id uint64) error
 | 
			
		||||
 | 
			
		||||
	// 获取数据库连接实例
 | 
			
		||||
	// @param id 数据库实例id
 | 
			
		||||
	// @param db 数据库
 | 
			
		||||
	GetDbConnection(dbId uint64, dbName string) *DbConnection
 | 
			
		||||
	GetDbConnection(dbId uint64, dbName string) (*DbConnection, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newDbApp(dbRepo repository.Db, dbSqlRepo repository.DbSql, dbInstanceApp Instance) Db {
 | 
			
		||||
	return &dbAppImpl{
 | 
			
		||||
		dbRepo:        dbRepo,
 | 
			
		||||
	app := &dbAppImpl{
 | 
			
		||||
		dbSqlRepo:     dbSqlRepo,
 | 
			
		||||
		dbInstanceApp: dbInstanceApp,
 | 
			
		||||
	}
 | 
			
		||||
	app.Repo = dbRepo
 | 
			
		||||
	return app
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type dbAppImpl struct {
 | 
			
		||||
	dbRepo        repository.Db
 | 
			
		||||
	base.AppImpl[*entity.Db, repository.Db]
 | 
			
		||||
 | 
			
		||||
	dbSqlRepo     repository.DbSql
 | 
			
		||||
	dbInstanceApp Instance
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取数据库信息列表
 | 
			
		||||
func (d *dbAppImpl) GetPageList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
	return d.dbRepo.GetDbList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
func (d *dbAppImpl) GetPageList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return d.GetRepo().GetDbList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dbAppImpl) Count(condition *entity.DbQuery) int64 {
 | 
			
		||||
	return d.dbRepo.Count(condition)
 | 
			
		||||
	return d.GetRepo().Count(condition)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据条件获取
 | 
			
		||||
func (d *dbAppImpl) GetDbBy(condition *entity.Db, cols ...string) error {
 | 
			
		||||
	return d.dbRepo.GetDb(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取
 | 
			
		||||
func (d *dbAppImpl) GetById(id uint64, cols ...string) *entity.Db {
 | 
			
		||||
	return d.dbRepo.GetById(id, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dbAppImpl) Save(dbEntity *entity.Db) {
 | 
			
		||||
func (d *dbAppImpl) Save(dbEntity *entity.Db) error {
 | 
			
		||||
	// 查找是否存在
 | 
			
		||||
	oldDb := &entity.Db{Name: dbEntity.Name, InstanceId: dbEntity.InstanceId}
 | 
			
		||||
	err := d.GetDbBy(oldDb)
 | 
			
		||||
	err := d.GetBy(oldDb)
 | 
			
		||||
 | 
			
		||||
	if dbEntity.Id == 0 {
 | 
			
		||||
		biz.IsTrue(err != nil, "该实例下数据库名已存在")
 | 
			
		||||
		d.dbRepo.Insert(dbEntity)
 | 
			
		||||
		return
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			return errorx.NewBiz("该实例下数据库名已存在")
 | 
			
		||||
		}
 | 
			
		||||
		return d.Insert(dbEntity)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 如果存在该库,则校验修改的库是否为该库
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		biz.IsTrue(oldDb.Id == dbEntity.Id, "该实例下数据库名已存在")
 | 
			
		||||
	if err == nil && oldDb.Id != dbEntity.Id {
 | 
			
		||||
		return errorx.NewBiz("该实例下数据库名已存在")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dbId := dbEntity.Id
 | 
			
		||||
	old := d.GetById(dbId)
 | 
			
		||||
	old, err := d.GetById(new(entity.Db), dbId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errorx.NewBiz("该数据库不存在")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	oldDbs := strings.Split(old.Database, " ")
 | 
			
		||||
	newDbs := strings.Split(dbEntity.Database, " ")
 | 
			
		||||
@@ -105,27 +98,30 @@ func (d *dbAppImpl) Save(dbEntity *entity.Db) {
 | 
			
		||||
		// 关闭数据库连接
 | 
			
		||||
		CloseDb(dbEntity.Id, v)
 | 
			
		||||
		// 删除该库关联的所有sql记录
 | 
			
		||||
		d.dbSqlRepo.DeleteBy(&entity.DbSql{DbId: dbId, Db: v})
 | 
			
		||||
		d.dbSqlRepo.DeleteByCond(&entity.DbSql{DbId: dbId, Db: v})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	d.dbRepo.Update(dbEntity)
 | 
			
		||||
	return d.UpdateById(dbEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dbAppImpl) Delete(id uint64) {
 | 
			
		||||
	db := d.GetById(id)
 | 
			
		||||
func (d *dbAppImpl) Delete(id uint64) error {
 | 
			
		||||
	db, err := d.GetById(new(entity.Db), id)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errorx.NewBiz("该数据库不存在")
 | 
			
		||||
	}
 | 
			
		||||
	dbs := strings.Split(db.Database, " ")
 | 
			
		||||
	for _, v := range dbs {
 | 
			
		||||
		// 关闭连接
 | 
			
		||||
		CloseDb(id, v)
 | 
			
		||||
	}
 | 
			
		||||
	d.dbRepo.Delete(id)
 | 
			
		||||
	// 删除该库下用户保存的所有sql信息
 | 
			
		||||
	d.dbSqlRepo.DeleteBy(&entity.DbSql{DbId: id})
 | 
			
		||||
	d.dbSqlRepo.DeleteByCond(&entity.DbSql{DbId: id})
 | 
			
		||||
	return d.DeleteById(id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var mutex sync.Mutex
 | 
			
		||||
 | 
			
		||||
func (d *dbAppImpl) GetDbConnection(dbId uint64, dbName string) *DbConnection {
 | 
			
		||||
func (d *dbAppImpl) GetDbConnection(dbId uint64, dbName string) (*DbConnection, error) {
 | 
			
		||||
	cacheKey := GetDbCacheKey(dbId, dbName)
 | 
			
		||||
 | 
			
		||||
	// Id不为0,则为需要缓存
 | 
			
		||||
@@ -133,18 +129,24 @@ func (d *dbAppImpl) GetDbConnection(dbId uint64, dbName string) *DbConnection {
 | 
			
		||||
	if needCache {
 | 
			
		||||
		load, ok := dbCache.Get(cacheKey)
 | 
			
		||||
		if ok {
 | 
			
		||||
			return load.(*DbConnection)
 | 
			
		||||
			return load.(*DbConnection), nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	mutex.Lock()
 | 
			
		||||
	defer mutex.Unlock()
 | 
			
		||||
 | 
			
		||||
	db := d.GetById(dbId)
 | 
			
		||||
	biz.NotNil(db, "数据库信息不存在")
 | 
			
		||||
	biz.IsTrue(strings.Contains(" "+db.Database+" ", " "+dbName+" "), "未配置数据库【%s】的操作权限", dbName)
 | 
			
		||||
	db, err := d.GetById(new(entity.Db), dbId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errorx.NewBiz("数据库信息不存在")
 | 
			
		||||
	}
 | 
			
		||||
	if !strings.Contains(" "+db.Database+" ", " "+dbName+" ") {
 | 
			
		||||
		return nil, errorx.NewBiz("未配置数据库【%s】的操作权限", dbName)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	instance := d.dbInstanceApp.GetById(db.InstanceId)
 | 
			
		||||
	biz.NotNil(instance, "数据库实例不存在")
 | 
			
		||||
	instance, err := d.dbInstanceApp.GetById(new(entity.Instance), db.InstanceId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errorx.NewBiz("数据库实例不存在")
 | 
			
		||||
	}
 | 
			
		||||
	// 密码解密
 | 
			
		||||
	instance.PwdDecrypt()
 | 
			
		||||
 | 
			
		||||
@@ -156,7 +158,7 @@ func (d *dbAppImpl) GetDbConnection(dbId uint64, dbName string) *DbConnection {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		dbi.Close()
 | 
			
		||||
		logx.Errorf("连接db失败: %s:%d/%s", dbInfo.Host, dbInfo.Port, dbName)
 | 
			
		||||
		panic(biz.NewBizErr(fmt.Sprintf("数据库连接失败: %s", err.Error())))
 | 
			
		||||
		return nil, errorx.NewBiz(fmt.Sprintf("数据库连接失败: %s", err.Error()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 最大连接周期,超过时间的连接就close
 | 
			
		||||
@@ -171,7 +173,7 @@ func (d *dbAppImpl) GetDbConnection(dbId uint64, dbName string) *DbConnection {
 | 
			
		||||
	if needCache {
 | 
			
		||||
		dbCache.Put(cacheKey, dbi)
 | 
			
		||||
	}
 | 
			
		||||
	return dbi
 | 
			
		||||
	return dbi, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//----------------------------------------  db instance  ------------------------------------
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ import (
 | 
			
		||||
	"mayfly-go/internal/db/config"
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/db/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
@@ -51,7 +51,7 @@ type DbSqlExec interface {
 | 
			
		||||
	DeleteBy(condition *entity.DbSqlExec)
 | 
			
		||||
 | 
			
		||||
	// 分页获取
 | 
			
		||||
	GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newDbSqlExecApp(dbExecSqlRepo repository.DbSqlExec) DbSqlExec {
 | 
			
		||||
@@ -91,7 +91,9 @@ func (d *dbSqlExecAppImpl) Exec(execSqlReq *DbSqlExecReq) (*DbSqlExecRes, error)
 | 
			
		||||
			// 如果配置为0,则不校验分页参数
 | 
			
		||||
			maxCount := config.GetDbQueryMaxCount()
 | 
			
		||||
			if maxCount != 0 {
 | 
			
		||||
				biz.IsTrue(strings.Contains(lowerSql, "limit"), "请完善分页信息后执行")
 | 
			
		||||
				if !strings.Contains(lowerSql, "limit") {
 | 
			
		||||
					return nil, errorx.NewBiz("请完善分页信息后执行")
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		var execErr error
 | 
			
		||||
@@ -148,10 +150,10 @@ func (d *dbSqlExecAppImpl) saveSqlExecLog(isQuery bool, dbSqlExecRecord *entity.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dbSqlExecAppImpl) DeleteBy(condition *entity.DbSqlExec) {
 | 
			
		||||
	d.dbSqlExecRepo.DeleteBy(condition)
 | 
			
		||||
	d.dbSqlExecRepo.DeleteByCond(condition)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dbSqlExecAppImpl) GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (d *dbSqlExecAppImpl) GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return d.dbSqlExecRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -163,10 +165,18 @@ func doSelect(selectStmt *sqlparser.Select, execSqlReq *DbSqlExecReq) (*DbSqlExe
 | 
			
		||||
		maxCount := config.GetDbQueryMaxCount()
 | 
			
		||||
		if maxCount != 0 {
 | 
			
		||||
			limit := selectStmt.Limit
 | 
			
		||||
			biz.NotNil(limit, "请完善分页信息后执行")
 | 
			
		||||
			if limit == nil {
 | 
			
		||||
				return nil, errorx.NewBiz("请完善分页信息后执行")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			count, err := strconv.Atoi(sqlparser.String(limit.Rowcount))
 | 
			
		||||
			biz.ErrIsNil(err, "分页参数有误")
 | 
			
		||||
			biz.IsTrue(count <= maxCount, "查询结果集数需小于系统配置的%d条", maxCount)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, errorx.NewBiz("分页参数有误")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if count > maxCount {
 | 
			
		||||
				return nil, errorx.NewBiz("查询结果集数需小于系统配置的%d条", maxCount)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -193,7 +203,9 @@ func doUpdate(update *sqlparser.Update, execSqlReq *DbSqlExecReq, dbSqlExec *ent
 | 
			
		||||
	// 可能使用别名,故空格切割
 | 
			
		||||
	tableName := strings.Split(tableStr, " ")[0]
 | 
			
		||||
	where := sqlparser.String(update.Where)
 | 
			
		||||
	biz.IsTrue(len(where) > 0, "SQL[%s]未执行. 请完善 where 条件后再执行", execSqlReq.Sql)
 | 
			
		||||
	if len(where) == 0 {
 | 
			
		||||
		return nil, errorx.NewBiz("SQL[%s]未执行. 请完善 where 条件后再执行", execSqlReq.Sql)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	updateExprs := update.Exprs
 | 
			
		||||
	updateColumns := make([]string, 0)
 | 
			
		||||
@@ -202,7 +214,10 @@ func doUpdate(update *sqlparser.Update, execSqlReq *DbSqlExecReq, dbSqlExec *ent
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 获取表主键列名,排除使用别名
 | 
			
		||||
	primaryKey := dbConn.GetMeta().GetPrimaryKey(tableName)
 | 
			
		||||
	primaryKey, err := dbConn.GetMeta().GetPrimaryKey(tableName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errorx.NewBiz("获取表主键信息失败")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	updateColumnsAndPrimaryKey := strings.Join(updateColumns, ",") + "," + primaryKey
 | 
			
		||||
	// 查询要更新字段数据的旧值,以及主键值
 | 
			
		||||
@@ -228,7 +243,9 @@ func doDelete(delete *sqlparser.Delete, execSqlReq *DbSqlExecReq, dbSqlExec *ent
 | 
			
		||||
	// 可能使用别名,故空格切割
 | 
			
		||||
	table := strings.Split(tableStr, " ")[0]
 | 
			
		||||
	where := sqlparser.String(delete.Where)
 | 
			
		||||
	biz.IsTrue(len(where) > 0, "SQL[%s]未执行. 请完善 where 条件后再执行", execSqlReq.Sql)
 | 
			
		||||
	if len(where) == 0 {
 | 
			
		||||
		return nil, errorx.NewBiz("SQL[%s]未执行. 请完善 where 条件后再执行", execSqlReq.Sql)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 查询删除数据
 | 
			
		||||
	selectSql := fmt.Sprintf("SELECT * FROM %s %s LIMIT 200", tableStr, where)
 | 
			
		||||
 
 | 
			
		||||
@@ -5,67 +5,56 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/db/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Instance interface {
 | 
			
		||||
	base.App[*entity.Instance]
 | 
			
		||||
 | 
			
		||||
	// GetPageList 分页获取数据库实例
 | 
			
		||||
	GetPageList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	Count(condition *entity.InstanceQuery) int64
 | 
			
		||||
 | 
			
		||||
	// GetInstanceBy 根据条件获取数据库实例
 | 
			
		||||
	GetInstanceBy(condition *entity.Instance, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	// GetById 根据id获取数据库实例
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.Instance
 | 
			
		||||
 | 
			
		||||
	Save(instanceEntity *entity.Instance)
 | 
			
		||||
	Save(instanceEntity *entity.Instance) error
 | 
			
		||||
 | 
			
		||||
	// Delete 删除数据库信息
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
	Delete(id uint64) error
 | 
			
		||||
 | 
			
		||||
	// GetDatabases 获取数据库实例的所有数据库列表
 | 
			
		||||
	GetDatabases(entity *entity.Instance) []string
 | 
			
		||||
	GetDatabases(entity *entity.Instance) ([]string, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newInstanceApp(InstanceRepo repository.Instance) Instance {
 | 
			
		||||
	return &instanceAppImpl{
 | 
			
		||||
		instanceRepo: InstanceRepo,
 | 
			
		||||
	}
 | 
			
		||||
func newInstanceApp(instanceRepo repository.Instance) Instance {
 | 
			
		||||
	app := new(instanceAppImpl)
 | 
			
		||||
	app.Repo = instanceRepo
 | 
			
		||||
	return app
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type instanceAppImpl struct {
 | 
			
		||||
	instanceRepo repository.Instance
 | 
			
		||||
	base.AppImpl[*entity.Instance, repository.Instance]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetPageList 分页获取数据库实例
 | 
			
		||||
func (app *instanceAppImpl) GetPageList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
	return app.instanceRepo.GetInstanceList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
func (app *instanceAppImpl) GetPageList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return app.GetRepo().GetInstanceList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (app *instanceAppImpl) Count(condition *entity.InstanceQuery) int64 {
 | 
			
		||||
	return app.instanceRepo.Count(condition)
 | 
			
		||||
	return app.CountByCond(condition)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetInstanceBy 根据条件获取数据库实例
 | 
			
		||||
func (app *instanceAppImpl) GetInstanceBy(condition *entity.Instance, cols ...string) error {
 | 
			
		||||
	return app.instanceRepo.GetInstance(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetById 根据id获取数据库实例
 | 
			
		||||
func (app *instanceAppImpl) GetById(id uint64, cols ...string) *entity.Instance {
 | 
			
		||||
	return app.instanceRepo.GetById(id, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (app *instanceAppImpl) Save(instanceEntity *entity.Instance) {
 | 
			
		||||
func (app *instanceAppImpl) Save(instanceEntity *entity.Instance) error {
 | 
			
		||||
	// 默认tcp连接
 | 
			
		||||
	instanceEntity.Network = instanceEntity.GetNetwork()
 | 
			
		||||
 | 
			
		||||
	// 测试连接
 | 
			
		||||
	if instanceEntity.Password != "" {
 | 
			
		||||
		testConnection(instanceEntity)
 | 
			
		||||
		if err := testConnection(instanceEntity); err != nil {
 | 
			
		||||
			return errorx.NewBiz("数据库连接失败: %s", err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 查找是否存在该库
 | 
			
		||||
@@ -74,24 +63,28 @@ func (app *instanceAppImpl) Save(instanceEntity *entity.Instance) {
 | 
			
		||||
		oldInstance.SshTunnelMachineId = instanceEntity.SshTunnelMachineId
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := app.GetInstanceBy(oldInstance)
 | 
			
		||||
	err := app.GetBy(oldInstance)
 | 
			
		||||
	if instanceEntity.Id == 0 {
 | 
			
		||||
		biz.NotEmpty(instanceEntity.Password, "密码不能为空")
 | 
			
		||||
		biz.IsTrue(err != nil, "该数据库实例已存在")
 | 
			
		||||
		instanceEntity.PwdEncrypt()
 | 
			
		||||
		app.instanceRepo.Insert(instanceEntity)
 | 
			
		||||
	} else {
 | 
			
		||||
		// 如果存在该库,则校验修改的库是否为该库
 | 
			
		||||
		if instanceEntity.Password == "" {
 | 
			
		||||
			return errorx.NewBiz("密码不能为空")
 | 
			
		||||
		}
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			biz.IsTrue(oldInstance.Id == instanceEntity.Id, "该数据库实例已存在")
 | 
			
		||||
			return errorx.NewBiz("该数据库实例已存在")
 | 
			
		||||
		}
 | 
			
		||||
		instanceEntity.PwdEncrypt()
 | 
			
		||||
		app.instanceRepo.Update(instanceEntity)
 | 
			
		||||
		return app.Insert(instanceEntity)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 如果存在该库,则校验修改的库是否为该库
 | 
			
		||||
	if err == nil && oldInstance.Id != instanceEntity.Id {
 | 
			
		||||
		return errorx.NewBiz("该数据库实例已存在")
 | 
			
		||||
	}
 | 
			
		||||
	instanceEntity.PwdEncrypt()
 | 
			
		||||
	return app.UpdateById(instanceEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (app *instanceAppImpl) Delete(id uint64) {
 | 
			
		||||
	app.instanceRepo.Delete(id)
 | 
			
		||||
func (app *instanceAppImpl) Delete(id uint64) error {
 | 
			
		||||
	return app.DeleteById(id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getInstanceConn 获取数据库连接数据库实例
 | 
			
		||||
@@ -119,14 +112,17 @@ func getInstanceConn(instance *entity.Instance, db string) (*sql.DB, error) {
 | 
			
		||||
	return conn, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func testConnection(d *entity.Instance) {
 | 
			
		||||
func testConnection(d *entity.Instance) error {
 | 
			
		||||
	// 不指定数据库名称
 | 
			
		||||
	conn, err := getInstanceConn(d, "")
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "数据库连接失败: %s")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer conn.Close()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (app *instanceAppImpl) GetDatabases(ed *entity.Instance) []string {
 | 
			
		||||
func (app *instanceAppImpl) GetDatabases(ed *entity.Instance) ([]string, error) {
 | 
			
		||||
	ed.Network = ed.GetNetwork()
 | 
			
		||||
	databases := make([]string, 0)
 | 
			
		||||
	var dbConn *sql.DB
 | 
			
		||||
@@ -134,14 +130,18 @@ func (app *instanceAppImpl) GetDatabases(ed *entity.Instance) []string {
 | 
			
		||||
	getDatabasesSql := ed.Type.StmtSelectDbName()
 | 
			
		||||
 | 
			
		||||
	dbConn, err := getInstanceConn(ed, metaDb)
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "数据库连接失败: %s")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errorx.NewBiz("数据库连接失败: %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	defer dbConn.Close()
 | 
			
		||||
 | 
			
		||||
	_, res, err := selectDataByDb(dbConn, getDatabasesSql)
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取数据库列表失败")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	for _, re := range res {
 | 
			
		||||
		databases = append(databases, re["dbname"].(string))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return databases
 | 
			
		||||
	return databases, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -44,22 +44,22 @@ type Index struct {
 | 
			
		||||
type DbMetadata interface {
 | 
			
		||||
 | 
			
		||||
	// 获取表基础元信息
 | 
			
		||||
	GetTables() []Table
 | 
			
		||||
	GetTables() ([]Table, error)
 | 
			
		||||
 | 
			
		||||
	// 获取指定表名的所有列元信息
 | 
			
		||||
	GetColumns(tableNames ...string) []Column
 | 
			
		||||
	GetColumns(tableNames ...string) ([]Column, error)
 | 
			
		||||
 | 
			
		||||
	// 获取表主键字段名,没有主键标识则默认第一个字段
 | 
			
		||||
	GetPrimaryKey(tablename string) string
 | 
			
		||||
	GetPrimaryKey(tablename string) (string, error)
 | 
			
		||||
 | 
			
		||||
	// 获取表信息,比GetTables获取更详细的表信息
 | 
			
		||||
	GetTableInfos() []Table
 | 
			
		||||
	GetTableInfos() ([]Table, error)
 | 
			
		||||
 | 
			
		||||
	// 获取表索引信息
 | 
			
		||||
	GetTableIndex(tableName string) []Index
 | 
			
		||||
	GetTableIndex(tableName string) ([]Index, error)
 | 
			
		||||
 | 
			
		||||
	// 获取建表ddl
 | 
			
		||||
	GetCreateTableDdl(tableName string) string
 | 
			
		||||
	GetCreateTableDdl(tableName string) (string, error)
 | 
			
		||||
 | 
			
		||||
	// 获取指定表的数据-分页查询
 | 
			
		||||
	// @return columns: 列字段名;result: 结果集;error: 错误
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	machineapp "mayfly-go/internal/machine/application"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/utils/anyx"
 | 
			
		||||
	"net"
 | 
			
		||||
 | 
			
		||||
@@ -16,7 +16,10 @@ import (
 | 
			
		||||
func getMysqlDB(d *entity.Instance, db string) (*sql.DB, error) {
 | 
			
		||||
	// SSH Conect
 | 
			
		||||
	if d.SshTunnelMachineId > 0 {
 | 
			
		||||
		sshTunnelMachine := machineapp.GetMachineApp().GetSshTunnelMachine(d.SshTunnelMachineId)
 | 
			
		||||
		sshTunnelMachine, err := machineapp.GetMachineApp().GetSshTunnelMachine(d.SshTunnelMachineId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		mysql.RegisterDialContext(d.Network, func(ctx context.Context, addr string) (net.Conn, error) {
 | 
			
		||||
			return sshTunnelMachine.GetDialConn("tcp", addr)
 | 
			
		||||
		})
 | 
			
		||||
@@ -43,9 +46,11 @@ type MysqlMetadata struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取表基础元信息, 如表名等
 | 
			
		||||
func (mm *MysqlMetadata) GetTables() []Table {
 | 
			
		||||
func (mm *MysqlMetadata) GetTables() ([]Table, error) {
 | 
			
		||||
	_, res, err := mm.di.SelectData(GetLocalSql(MYSQL_META_FILE, MYSQL_TABLE_MA_KEY))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取表基本信息失败: %s")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tables := make([]Table, 0)
 | 
			
		||||
	for _, re := range res {
 | 
			
		||||
@@ -54,11 +59,11 @@ func (mm *MysqlMetadata) GetTables() []Table {
 | 
			
		||||
			TableComment: anyx.ConvString(re["tableComment"]),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return tables
 | 
			
		||||
	return tables, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取列元信息, 如列名等
 | 
			
		||||
func (mm *MysqlMetadata) GetColumns(tableNames ...string) []Column {
 | 
			
		||||
func (mm *MysqlMetadata) GetColumns(tableNames ...string) ([]Column, error) {
 | 
			
		||||
	tableName := ""
 | 
			
		||||
	for i := 0; i < len(tableNames); i++ {
 | 
			
		||||
		if i != 0 {
 | 
			
		||||
@@ -68,7 +73,10 @@ func (mm *MysqlMetadata) GetColumns(tableNames ...string) []Column {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, res, err := mm.di.SelectData(fmt.Sprintf(GetLocalSql(MYSQL_META_FILE, MYSQL_COLUMN_MA_KEY), tableName))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取数据库列信息失败: %s")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	columns := make([]Column, 0)
 | 
			
		||||
	for _, re := range res {
 | 
			
		||||
		columns = append(columns, Column{
 | 
			
		||||
@@ -81,26 +89,34 @@ func (mm *MysqlMetadata) GetColumns(tableNames ...string) []Column {
 | 
			
		||||
			ColumnDefault: anyx.ConvString(re["columnDefault"]),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return columns
 | 
			
		||||
	return columns, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取表主键字段名,不存在主键标识则默认第一个字段
 | 
			
		||||
func (mm *MysqlMetadata) GetPrimaryKey(tablename string) string {
 | 
			
		||||
	columns := mm.GetColumns(tablename)
 | 
			
		||||
	biz.IsTrue(len(columns) > 0, "[%s] 表不存在", tablename)
 | 
			
		||||
func (mm *MysqlMetadata) GetPrimaryKey(tablename string) (string, error) {
 | 
			
		||||
	columns, err := mm.GetColumns(tablename)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	if len(columns) == 0 {
 | 
			
		||||
		return "", errorx.NewBiz("[%s] 表不存在", tablename)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, v := range columns {
 | 
			
		||||
		if v.ColumnKey == "PRI" {
 | 
			
		||||
			return v.ColumnName
 | 
			
		||||
			return v.ColumnName, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return columns[0].ColumnName
 | 
			
		||||
	return columns[0].ColumnName, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取表信息,比GetTableMetedatas获取更详细的表信息
 | 
			
		||||
func (mm *MysqlMetadata) GetTableInfos() []Table {
 | 
			
		||||
func (mm *MysqlMetadata) GetTableInfos() ([]Table, error) {
 | 
			
		||||
	_, res, err := mm.di.SelectData(GetLocalSql(MYSQL_META_FILE, MYSQL_TABLE_INFO_KEY))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取表信息失败: %s")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tables := make([]Table, 0)
 | 
			
		||||
	for _, re := range res {
 | 
			
		||||
@@ -113,13 +129,16 @@ func (mm *MysqlMetadata) GetTableInfos() []Table {
 | 
			
		||||
			IndexLength:  anyx.ConvInt64(re["indexLength"]),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return tables
 | 
			
		||||
	return tables, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取表索引信息
 | 
			
		||||
func (mm *MysqlMetadata) GetTableIndex(tableName string) []Index {
 | 
			
		||||
func (mm *MysqlMetadata) GetTableIndex(tableName string) ([]Index, error) {
 | 
			
		||||
	_, res, err := mm.di.SelectData(fmt.Sprintf(GetLocalSql(MYSQL_META_FILE, MYSQL_INDEX_INFO_KEY), tableName))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取表索引信息失败: %s")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	indexs := make([]Index, 0)
 | 
			
		||||
	for _, re := range res {
 | 
			
		||||
		indexs = append(indexs, Index{
 | 
			
		||||
@@ -147,14 +166,16 @@ func (mm *MysqlMetadata) GetTableIndex(tableName string) []Index {
 | 
			
		||||
			result = append(result, v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return result
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取建表ddl
 | 
			
		||||
func (mm *MysqlMetadata) GetCreateTableDdl(tableName string) string {
 | 
			
		||||
func (mm *MysqlMetadata) GetCreateTableDdl(tableName string) (string, error) {
 | 
			
		||||
	_, res, err := mm.di.SelectData(fmt.Sprintf("show create table `%s` ", tableName))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取表结构失败: %s")
 | 
			
		||||
	return res[0]["Create Table"].(string) + ";"
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return res[0]["Create Table"].(string) + ";", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (mm *MysqlMetadata) GetTableRecord(tableName string, pageNum, pageSize int) ([]string, []map[string]any, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	machineapp "mayfly-go/internal/machine/application"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/utils/anyx"
 | 
			
		||||
	"mayfly-go/pkg/utils/collx"
 | 
			
		||||
	"net"
 | 
			
		||||
@@ -49,7 +49,11 @@ func (d *PqSqlDialer) Open(name string) (driver.Conn, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pd *PqSqlDialer) Dial(network, address string) (net.Conn, error) {
 | 
			
		||||
	if sshConn, err := machineapp.GetMachineApp().GetSshTunnelMachine(pd.sshTunnelMachineId).GetDialConn("tcp", address); err == nil {
 | 
			
		||||
	sshTunnel, err := machineapp.GetMachineApp().GetSshTunnelMachine(pd.sshTunnelMachineId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if sshConn, err := sshTunnel.GetDialConn("tcp", address); err == nil {
 | 
			
		||||
		return sshConn, nil
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, err
 | 
			
		||||
@@ -75,9 +79,11 @@ type PgsqlMetadata struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取表基础元信息, 如表名等
 | 
			
		||||
func (pm *PgsqlMetadata) GetTables() []Table {
 | 
			
		||||
func (pm *PgsqlMetadata) GetTables() ([]Table, error) {
 | 
			
		||||
	_, res, err := pm.di.SelectData(GetLocalSql(PGSQL_META_FILE, PGSQL_TABLE_MA_KEY))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取表基本信息失败: %s")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tables := make([]Table, 0)
 | 
			
		||||
	for _, re := range res {
 | 
			
		||||
@@ -86,11 +92,11 @@ func (pm *PgsqlMetadata) GetTables() []Table {
 | 
			
		||||
			TableComment: anyx.ConvString(re["tableComment"]),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return tables
 | 
			
		||||
	return tables, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取列元信息, 如列名等
 | 
			
		||||
func (pm *PgsqlMetadata) GetColumns(tableNames ...string) []Column {
 | 
			
		||||
func (pm *PgsqlMetadata) GetColumns(tableNames ...string) ([]Column, error) {
 | 
			
		||||
	tableName := ""
 | 
			
		||||
	for i := 0; i < len(tableNames); i++ {
 | 
			
		||||
		if i != 0 {
 | 
			
		||||
@@ -100,7 +106,10 @@ func (pm *PgsqlMetadata) GetColumns(tableNames ...string) []Column {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, res, err := pm.di.SelectData(fmt.Sprintf(GetLocalSql(PGSQL_META_FILE, PGSQL_COLUMN_MA_KEY), tableName))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取数据库列信息失败: %s")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	columns := make([]Column, 0)
 | 
			
		||||
	for _, re := range res {
 | 
			
		||||
		columns = append(columns, Column{
 | 
			
		||||
@@ -113,25 +122,32 @@ func (pm *PgsqlMetadata) GetColumns(tableNames ...string) []Column {
 | 
			
		||||
			ColumnDefault: anyx.ConvString(re["columnDefault"]),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return columns
 | 
			
		||||
	return columns, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pm *PgsqlMetadata) GetPrimaryKey(tablename string) string {
 | 
			
		||||
	columns := pm.GetColumns(tablename)
 | 
			
		||||
	biz.IsTrue(len(columns) > 0, "[%s] 表不存在", tablename)
 | 
			
		||||
func (pm *PgsqlMetadata) GetPrimaryKey(tablename string) (string, error) {
 | 
			
		||||
	columns, err := pm.GetColumns(tablename)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	if len(columns) == 0 {
 | 
			
		||||
		return "", errorx.NewBiz("[%s] 表不存在", tablename)
 | 
			
		||||
	}
 | 
			
		||||
	for _, v := range columns {
 | 
			
		||||
		if v.ColumnKey == "PRI" {
 | 
			
		||||
			return v.ColumnName
 | 
			
		||||
			return v.ColumnName, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return columns[0].ColumnName
 | 
			
		||||
	return columns[0].ColumnName, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取表信息,比GetTables获取更详细的表信息
 | 
			
		||||
func (pm *PgsqlMetadata) GetTableInfos() []Table {
 | 
			
		||||
func (pm *PgsqlMetadata) GetTableInfos() ([]Table, error) {
 | 
			
		||||
	_, res, err := pm.di.SelectData(GetLocalSql(PGSQL_META_FILE, PGSQL_TABLE_INFO_KEY))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取表信息失败: %s")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tables := make([]Table, 0)
 | 
			
		||||
	for _, re := range res {
 | 
			
		||||
@@ -144,13 +160,16 @@ func (pm *PgsqlMetadata) GetTableInfos() []Table {
 | 
			
		||||
			IndexLength:  anyx.ConvInt64(re["indexLength"]),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return tables
 | 
			
		||||
	return tables, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取表索引信息
 | 
			
		||||
func (pm *PgsqlMetadata) GetTableIndex(tableName string) []Index {
 | 
			
		||||
func (pm *PgsqlMetadata) GetTableIndex(tableName string) ([]Index, error) {
 | 
			
		||||
	_, res, err := pm.di.SelectData(fmt.Sprintf(GetLocalSql(PGSQL_META_FILE, PGSQL_INDEX_INFO_KEY), tableName))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取表索引信息失败: %s")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	indexs := make([]Index, 0)
 | 
			
		||||
	for _, re := range res {
 | 
			
		||||
		indexs = append(indexs, Index{
 | 
			
		||||
@@ -162,22 +181,26 @@ func (pm *PgsqlMetadata) GetTableIndex(tableName string) []Index {
 | 
			
		||||
			SeqInIndex:   anyx.ConvInt(re["seqInIndex"]),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return indexs
 | 
			
		||||
	return indexs, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取建表ddl
 | 
			
		||||
func (pm *PgsqlMetadata) GetCreateTableDdl(tableName string) string {
 | 
			
		||||
func (pm *PgsqlMetadata) GetCreateTableDdl(tableName string) (string, error) {
 | 
			
		||||
	_, err := pm.di.Exec(GetLocalSql(PGSQL_META_FILE, PGSQL_TABLE_DDL_KEY))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "创建ddl函数失败: %s")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, schemaRes, _ := pm.di.SelectData("select current_schema() as schema")
 | 
			
		||||
	schemaName := schemaRes[0]["schema"].(string)
 | 
			
		||||
 | 
			
		||||
	ddlSql := fmt.Sprintf("select showcreatetable('%s','%s') as sql", schemaName, tableName)
 | 
			
		||||
	_, res, err := pm.di.SelectData(ddlSql)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取表ddl失败: %s")
 | 
			
		||||
	return res[0]["sql"].(string)
 | 
			
		||||
	return res[0]["sql"].(string), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pm *PgsqlMetadata) GetTableRecord(tableName string, pageNum, pageSize int) ([]string, []map[string]any, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,24 +2,15 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Db interface {
 | 
			
		||||
	base.Repo[*entity.Db]
 | 
			
		||||
 | 
			
		||||
	// 分页获取数据信息列表
 | 
			
		||||
	GetDbList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetDbList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	Count(condition *entity.DbQuery) int64
 | 
			
		||||
 | 
			
		||||
	// 根据条件获取数据库信息
 | 
			
		||||
	GetDb(condition *entity.Db, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.Db
 | 
			
		||||
 | 
			
		||||
	Insert(db *entity.Db)
 | 
			
		||||
 | 
			
		||||
	Update(db *entity.Db)
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,10 @@
 | 
			
		||||
package repository
 | 
			
		||||
 | 
			
		||||
import "mayfly-go/internal/db/domain/entity"
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DbSql interface {
 | 
			
		||||
	DeleteBy(condition *entity.DbSql)
 | 
			
		||||
	base.Repo[*entity.DbSql]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,14 +2,13 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DbSqlExec interface {
 | 
			
		||||
	Insert(d *entity.DbSqlExec)
 | 
			
		||||
 | 
			
		||||
	DeleteBy(condition *entity.DbSqlExec)
 | 
			
		||||
	base.Repo[*entity.DbSqlExec]
 | 
			
		||||
 | 
			
		||||
	// 分页获取
 | 
			
		||||
	GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,24 +2,13 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Instance interface {
 | 
			
		||||
	base.Repo[*entity.Instance]
 | 
			
		||||
 | 
			
		||||
	// 分页获取数据库实例信息列表
 | 
			
		||||
	GetInstanceList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
 | 
			
		||||
	Count(condition *entity.InstanceQuery) int64
 | 
			
		||||
 | 
			
		||||
	// 根据条件获取实例信息
 | 
			
		||||
	GetInstance(condition *entity.Instance, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.Instance
 | 
			
		||||
 | 
			
		||||
	Insert(db *entity.Instance)
 | 
			
		||||
 | 
			
		||||
	Update(db *entity.Instance)
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
	GetInstanceList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,19 +3,21 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/db/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type dbRepoImpl struct{}
 | 
			
		||||
type dbRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.Db]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newDbRepo() repository.Db {
 | 
			
		||||
	return new(dbRepoImpl)
 | 
			
		||||
	return &dbRepoImpl{base.RepoImpl[*entity.Db]{M: new(entity.Db)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取数据库信息列表
 | 
			
		||||
func (d *dbRepoImpl) GetDbList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (d *dbRepoImpl) GetDbList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQueryWithTableName("t_db db").
 | 
			
		||||
		Select("db.*, inst.name instance_name, inst.type instance_type").
 | 
			
		||||
		Joins("JOIN t_db_instance inst ON db.instance_id = inst.id").
 | 
			
		||||
@@ -38,32 +40,5 @@ func (d *dbRepoImpl) Count(condition *entity.DbQuery) int64 {
 | 
			
		||||
	if condition.InstanceId > 0 {
 | 
			
		||||
		where["instance_id"] = condition.InstanceId
 | 
			
		||||
	}
 | 
			
		||||
	return gormx.CountByCond(new(entity.Db), where)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据条件获取账号信息
 | 
			
		||||
func (d *dbRepoImpl) GetDb(condition *entity.Db, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取
 | 
			
		||||
func (d *dbRepoImpl) GetById(id uint64, cols ...string) *entity.Db {
 | 
			
		||||
	db := new(entity.Db)
 | 
			
		||||
	if err := gormx.GetById(db, id, cols...); err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return db
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dbRepoImpl) Insert(db *entity.Db) {
 | 
			
		||||
	biz.ErrIsNil(gormx.Insert(db), "新增数据库信息失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dbRepoImpl) Update(db *entity.Db) {
 | 
			
		||||
	biz.ErrIsNil(gormx.UpdateById(db), "更新数据库信息失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dbRepoImpl) Delete(id uint64) {
 | 
			
		||||
	gormx.DeleteById(new(entity.Db), id)
 | 
			
		||||
	return d.CountByCond(where)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,17 +3,13 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/db/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type dbSqlRepoImpl struct{}
 | 
			
		||||
type dbSqlRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.DbSql]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newDbSqlRepo() repository.DbSql {
 | 
			
		||||
	return new(dbSqlRepoImpl)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取数据库信息列表
 | 
			
		||||
func (d *dbSqlRepoImpl) DeleteBy(condition *entity.DbSql) {
 | 
			
		||||
	biz.ErrIsNil(gormx.DeleteByCondition(condition), "删除sql失败")
 | 
			
		||||
	return &dbSqlRepoImpl{base.RepoImpl[*entity.DbSql]{M: new(entity.DbSql)}}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,27 +3,21 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/db/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type dbSqlExecRepoImpl struct{}
 | 
			
		||||
type dbSqlExecRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.DbSqlExec]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newDbSqlExecRepo() repository.DbSqlExec {
 | 
			
		||||
	return new(dbSqlExecRepoImpl)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dbSqlExecRepoImpl) Insert(dse *entity.DbSqlExec) {
 | 
			
		||||
	gormx.Insert(dse)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *dbSqlExecRepoImpl) DeleteBy(condition *entity.DbSqlExec) {
 | 
			
		||||
	biz.ErrIsNil(gormx.DeleteByCondition(condition), "删除sql执行记录失败")
 | 
			
		||||
	return &dbSqlExecRepoImpl{base.RepoImpl[*entity.DbSqlExec]{M: new(entity.DbSqlExec)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取
 | 
			
		||||
func (d *dbSqlExecRepoImpl) GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (d *dbSqlExecRepoImpl) GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(new(entity.DbSqlExec)).WithCondModel(condition).WithOrderBy(orderBy...)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,53 +3,24 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/db/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/db/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type instanceRepoImpl struct{}
 | 
			
		||||
type instanceRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.Instance]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newInstanceRepo() repository.Instance {
 | 
			
		||||
	return new(instanceRepoImpl)
 | 
			
		||||
	return &instanceRepoImpl{base.RepoImpl[*entity.Instance]{M: new(entity.Instance)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取数据库信息列表
 | 
			
		||||
func (d *instanceRepoImpl) GetInstanceList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (d *instanceRepoImpl) GetInstanceList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(new(entity.Instance)).
 | 
			
		||||
		Eq("id", condition.Id).
 | 
			
		||||
		Eq("host", condition.Host).
 | 
			
		||||
		Like("name", condition.Name)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *instanceRepoImpl) Count(condition *entity.InstanceQuery) int64 {
 | 
			
		||||
	where := make(map[string]any)
 | 
			
		||||
	return gormx.CountByCond(new(entity.Instance), where)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据条件获数据库实例信息
 | 
			
		||||
func (d *instanceRepoImpl) GetInstance(condition *entity.Instance, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取数据库实例
 | 
			
		||||
func (d *instanceRepoImpl) GetById(id uint64, cols ...string) *entity.Instance {
 | 
			
		||||
	instance := new(entity.Instance)
 | 
			
		||||
	if err := gormx.GetById(instance, id, cols...); err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return instance
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *instanceRepoImpl) Insert(db *entity.Instance) {
 | 
			
		||||
	biz.ErrIsNil(gormx.Insert(db), "新增数据库实例失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *instanceRepoImpl) Update(db *entity.Instance) {
 | 
			
		||||
	biz.ErrIsNil(gormx.UpdateById(db), "更新数据库实例失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *instanceRepoImpl) Delete(id uint64) {
 | 
			
		||||
	gormx.DeleteById(new(entity.Instance), id)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,14 +18,17 @@ type AuthCert struct {
 | 
			
		||||
 | 
			
		||||
func (ac *AuthCert) BaseAuthCerts(rc *req.Ctx) {
 | 
			
		||||
	queryCond, page := ginx.BindQueryAndPage(rc.GinCtx, new(entity.AuthCertQuery))
 | 
			
		||||
	rc.ResData = ac.AuthCertApp.GetPageList(queryCond, page, new([]vo.AuthCertBaseVO))
 | 
			
		||||
	res, err := ac.AuthCertApp.GetPageList(queryCond, page, new([]vo.AuthCertBaseVO))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ac *AuthCert) AuthCerts(rc *req.Ctx) {
 | 
			
		||||
	queryCond, page := ginx.BindQueryAndPage(rc.GinCtx, new(entity.AuthCertQuery))
 | 
			
		||||
 | 
			
		||||
	res := new([]*entity.AuthCert)
 | 
			
		||||
	pageRes := ac.AuthCertApp.GetPageList(queryCond, page, res)
 | 
			
		||||
	pageRes, err := ac.AuthCertApp.GetPageList(queryCond, page, res)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	for _, r := range *res {
 | 
			
		||||
		r.PwdDecrypt()
 | 
			
		||||
	}
 | 
			
		||||
@@ -42,7 +45,7 @@ func (c *AuthCert) SaveAuthCert(rc *req.Ctx) {
 | 
			
		||||
	rc.ReqParam = acForm
 | 
			
		||||
 | 
			
		||||
	ac.SetBaseInfo(rc.LoginAccount)
 | 
			
		||||
	c.AuthCertApp.Save(ac)
 | 
			
		||||
	biz.ErrIsNil(c.AuthCertApp.Save(ac))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *AuthCert) Delete(rc *req.Ctx) {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,9 +11,11 @@ import (
 | 
			
		||||
	tagapp "mayfly-go/internal/tag/application"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/config"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/ginx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
	"mayfly-go/pkg/utils/anyx"
 | 
			
		||||
	"mayfly-go/pkg/utils/collx"
 | 
			
		||||
	"mayfly-go/pkg/utils/stringx"
 | 
			
		||||
	"mayfly-go/pkg/ws"
 | 
			
		||||
@@ -44,7 +46,8 @@ func (m *Machine) Machines(rc *req.Ctx) {
 | 
			
		||||
	}
 | 
			
		||||
	condition.TagIds = tagIds
 | 
			
		||||
 | 
			
		||||
	res := m.MachineApp.GetMachineList(condition, pageParam, new([]*vo.MachineVO))
 | 
			
		||||
	res, err := m.MachineApp.GetMachineList(condition, pageParam, new([]*vo.MachineVO))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	if res.Total == 0 {
 | 
			
		||||
		rc.ResData = res
 | 
			
		||||
		return
 | 
			
		||||
@@ -61,8 +64,9 @@ func (m *Machine) MachineTags(rc *req.Ctx) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Machine) MachineStats(rc *req.Ctx) {
 | 
			
		||||
	stats := m.MachineApp.GetCli(GetMachineId(rc.GinCtx)).GetAllStats()
 | 
			
		||||
	rc.ResData = stats
 | 
			
		||||
	cli, err := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
 | 
			
		||||
	rc.ResData = cli.GetAllStats()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 保存机器信息
 | 
			
		||||
@@ -74,12 +78,13 @@ func (m *Machine) SaveMachine(rc *req.Ctx) {
 | 
			
		||||
	rc.ReqParam = machineForm
 | 
			
		||||
 | 
			
		||||
	me.SetBaseInfo(rc.LoginAccount)
 | 
			
		||||
	m.MachineApp.Save(me)
 | 
			
		||||
	biz.ErrIsNil(m.MachineApp.Save(me))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Machine) TestConn(rc *req.Ctx) {
 | 
			
		||||
	me := ginx.BindJsonAndCopyTo(rc.GinCtx, new(form.MachineForm), new(entity.Machine))
 | 
			
		||||
	m.MachineApp.TestConn(me)
 | 
			
		||||
	// 测试连接
 | 
			
		||||
	biz.ErrIsNilAppendErr(m.MachineApp.TestConn(me), "该机器无法连接: %s")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Machine) ChangeStatus(rc *req.Ctx) {
 | 
			
		||||
@@ -87,7 +92,7 @@ func (m *Machine) ChangeStatus(rc *req.Ctx) {
 | 
			
		||||
	id := uint64(ginx.PathParamInt(g, "machineId"))
 | 
			
		||||
	status := int8(ginx.PathParamInt(g, "status"))
 | 
			
		||||
	rc.ReqParam = collx.Kvs("id", id, "status", status)
 | 
			
		||||
	m.MachineApp.ChangeStatus(id, status)
 | 
			
		||||
	biz.ErrIsNil(m.MachineApp.ChangeStatus(id, status))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Machine) DeleteMachine(rc *req.Ctx) {
 | 
			
		||||
@@ -126,7 +131,8 @@ func (m *Machine) GetProcess(rc *req.Ctx) {
 | 
			
		||||
	count := ginx.QueryInt(g, "count", 10)
 | 
			
		||||
	cmd += "| head -n " + fmt.Sprintf("%d", count)
 | 
			
		||||
 | 
			
		||||
	cli := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
 | 
			
		||||
	cli, err := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
 | 
			
		||||
	biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
 | 
			
		||||
 | 
			
		||||
	res, err := cli.Run(cmd)
 | 
			
		||||
@@ -139,7 +145,8 @@ func (m *Machine) KillProcess(rc *req.Ctx) {
 | 
			
		||||
	pid := rc.GinCtx.Query("pid")
 | 
			
		||||
	biz.NotEmpty(pid, "进程id不能为空")
 | 
			
		||||
 | 
			
		||||
	cli := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
 | 
			
		||||
	cli, err := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
 | 
			
		||||
	biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
 | 
			
		||||
 | 
			
		||||
	res, err := cli.Run("sudo kill -9 " + pid)
 | 
			
		||||
@@ -151,7 +158,7 @@ func (m *Machine) WsSSH(g *gin.Context) {
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if wsConn != nil {
 | 
			
		||||
			if err := recover(); err != nil {
 | 
			
		||||
				wsConn.WriteMessage(websocket.TextMessage, []byte(err.(error).Error()))
 | 
			
		||||
				wsConn.WriteMessage(websocket.TextMessage, []byte(anyx.ToString(err)))
 | 
			
		||||
			}
 | 
			
		||||
			wsConn.Close()
 | 
			
		||||
		}
 | 
			
		||||
@@ -161,10 +168,11 @@ func (m *Machine) WsSSH(g *gin.Context) {
 | 
			
		||||
	// 权限校验
 | 
			
		||||
	rc := req.NewCtxWithGin(g).WithRequiredPermission(req.NewPermission("machine:terminal"))
 | 
			
		||||
	if err = req.PermissionHandler(rc); err != nil {
 | 
			
		||||
		panic(biz.NewBizErr("\033[1;31m您没有权限操作该机器终端,请重新登录后再试~\033[0m"))
 | 
			
		||||
		panic(errorx.NewBiz("\033[1;31m您没有权限操作该机器终端,请重新登录后再试~\033[0m"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cli := m.MachineApp.GetCli(GetMachineId(g))
 | 
			
		||||
	cli, err := m.MachineApp.GetCli(GetMachineId(g))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
 | 
			
		||||
	biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
 | 
			
		||||
 | 
			
		||||
	cols := ginx.QueryInt(g, "cols", 80)
 | 
			
		||||
 
 | 
			
		||||
@@ -22,12 +22,13 @@ func (m *MachineCronJob) MachineCronJobs(rc *req.Ctx) {
 | 
			
		||||
	cond, pageParam := ginx.BindQueryAndPage(rc.GinCtx, new(entity.MachineCronJob))
 | 
			
		||||
 | 
			
		||||
	vos := new([]*vo.MachineCronJobVO)
 | 
			
		||||
	pr := m.MachineCronJobApp.GetPageList(cond, pageParam, vos)
 | 
			
		||||
	pageRes, err := m.MachineCronJobApp.GetPageList(cond, pageParam, vos)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	for _, mcj := range *vos {
 | 
			
		||||
		mcj.Running = scheduler.ExistKey(mcj.Key)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc.ResData = pr
 | 
			
		||||
	rc.ResData = pageRes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MachineCronJob) Save(rc *req.Ctx) {
 | 
			
		||||
@@ -35,7 +36,8 @@ func (m *MachineCronJob) Save(rc *req.Ctx) {
 | 
			
		||||
	mcj := ginx.BindJsonAndCopyTo[*entity.MachineCronJob](rc.GinCtx, jobForm, new(entity.MachineCronJob))
 | 
			
		||||
	rc.ReqParam = jobForm
 | 
			
		||||
	mcj.SetBaseInfo(rc.LoginAccount)
 | 
			
		||||
	cronJobId := m.MachineCronJobApp.Save(mcj)
 | 
			
		||||
	cronJobId, err := m.MachineCronJobApp.Save(mcj)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
 | 
			
		||||
	// 关联机器
 | 
			
		||||
	m.MachineCronJobApp.CronJobRelateMachines(cronJobId, jobForm.MachineIds, rc.LoginAccount)
 | 
			
		||||
@@ -63,5 +65,7 @@ func (m *MachineCronJob) GetRelateCronJobIds(rc *req.Ctx) {
 | 
			
		||||
 | 
			
		||||
func (m *MachineCronJob) CronJobExecs(rc *req.Ctx) {
 | 
			
		||||
	cond, pageParam := ginx.BindQueryAndPage[*entity.MachineCronJobExec](rc.GinCtx, new(entity.MachineCronJobExec))
 | 
			
		||||
	rc.ResData = m.MachineCronJobApp.GetExecPageList(cond, pageParam, new([]entity.MachineCronJobExec))
 | 
			
		||||
	res, err := m.MachineCronJobApp.GetExecPageList(cond, pageParam, new([]entity.MachineCronJobExec))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@ import (
 | 
			
		||||
	msgapp "mayfly-go/internal/msg/application"
 | 
			
		||||
	msgdto "mayfly-go/internal/msg/application/dto"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/ginx"
 | 
			
		||||
	"mayfly-go/pkg/logx"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
@@ -43,7 +44,9 @@ const (
 | 
			
		||||
func (m *MachineFile) MachineFiles(rc *req.Ctx) {
 | 
			
		||||
	g := rc.GinCtx
 | 
			
		||||
	condition := &entity.MachineFile{MachineId: GetMachineId(g)}
 | 
			
		||||
	rc.ResData = m.MachineFileApp.GetPageList(condition, ginx.GetPageParam(g), new([]vo.MachineFileVO))
 | 
			
		||||
	res, err := m.MachineFileApp.GetPageList(condition, ginx.GetPageParam(g), new([]vo.MachineFileVO))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MachineFile) SaveMachineFiles(rc *req.Ctx) {
 | 
			
		||||
@@ -52,11 +55,11 @@ func (m *MachineFile) SaveMachineFiles(rc *req.Ctx) {
 | 
			
		||||
	entity.SetBaseInfo(rc.LoginAccount)
 | 
			
		||||
 | 
			
		||||
	rc.ReqParam = fileForm
 | 
			
		||||
	m.MachineFileApp.Save(entity)
 | 
			
		||||
	biz.ErrIsNil(m.MachineFileApp.Save(entity))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MachineFile) DeleteFile(rc *req.Ctx) {
 | 
			
		||||
	m.MachineFileApp.Delete(GetMachineFileId(rc.GinCtx))
 | 
			
		||||
	biz.ErrIsNil(m.MachineFileApp.Delete(GetMachineFileId(rc.GinCtx)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/***      sftp相关操作      */
 | 
			
		||||
@@ -121,7 +124,9 @@ func (m *MachineFile) GetDirEntry(rc *req.Ctx) {
 | 
			
		||||
	if !strings.HasSuffix(readPath, "/") {
 | 
			
		||||
		readPath = readPath + "/"
 | 
			
		||||
	}
 | 
			
		||||
	fis := m.MachineFileApp.ReadDir(fid, readPath)
 | 
			
		||||
	fis, err := m.MachineFileApp.ReadDir(fid, readPath)
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "读取目录失败: %s")
 | 
			
		||||
 | 
			
		||||
	fisVO := make([]vo.MachineFileInfo, 0)
 | 
			
		||||
	for _, fi := range fis {
 | 
			
		||||
		fisVO = append(fisVO, vo.MachineFileInfo{
 | 
			
		||||
@@ -143,7 +148,9 @@ func (m *MachineFile) GetDirSize(rc *req.Ctx) {
 | 
			
		||||
	fid := GetMachineFileId(g)
 | 
			
		||||
	readPath := g.Query("path")
 | 
			
		||||
 | 
			
		||||
	rc.ResData = m.MachineFileApp.GetDirSize(fid, readPath)
 | 
			
		||||
	size, err := m.MachineFileApp.GetDirSize(fid, readPath)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = size
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MachineFile) GetFileStat(rc *req.Ctx) {
 | 
			
		||||
@@ -151,7 +158,9 @@ func (m *MachineFile) GetFileStat(rc *req.Ctx) {
 | 
			
		||||
	fid := GetMachineFileId(g)
 | 
			
		||||
	readPath := g.Query("path")
 | 
			
		||||
 | 
			
		||||
	rc.ResData = m.MachineFileApp.FileStat(fid, readPath)
 | 
			
		||||
	res, err := m.MachineFileApp.FileStat(fid, readPath)
 | 
			
		||||
	biz.ErrIsNil(err, res)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MachineFile) WriteFileContent(rc *req.Ctx) {
 | 
			
		||||
@@ -220,9 +229,12 @@ func (m *MachineFile) UploadFolder(rc *req.Ctx) {
 | 
			
		||||
	paths := mf.Value["paths"]
 | 
			
		||||
 | 
			
		||||
	folderName := filepath.Dir(paths[0])
 | 
			
		||||
	mcli := m.MachineFileApp.GetMachineCli(fid, basePath+"/"+folderName)
 | 
			
		||||
	mcli, err := m.MachineFileApp.GetMachineCli(fid, basePath+"/"+folderName)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	mi := mcli.GetMachine()
 | 
			
		||||
	sftpCli := mcli.GetSftpCli()
 | 
			
		||||
 | 
			
		||||
	sftpCli, err := mcli.GetSftpCli()
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ReqParam = collx.Kvs("machine", mi, "path", fmt.Sprintf("%s/%s", basePath, folderName))
 | 
			
		||||
 | 
			
		||||
	folderFiles := make([]FolderFile, len(paths))
 | 
			
		||||
@@ -258,7 +270,7 @@ func (m *MachineFile) UploadFolder(rc *req.Ctx) {
 | 
			
		||||
				if err := recover(); err != nil {
 | 
			
		||||
					logx.Errorf("文件上传失败: %s", err)
 | 
			
		||||
					switch t := err.(type) {
 | 
			
		||||
					case biz.BizError:
 | 
			
		||||
					case errorx.BizError:
 | 
			
		||||
						m.MsgApp.CreateAndSend(la, msgdto.ErrSysMsg("文件上传失败", fmt.Sprintf("执行文件上传失败:\n<-e errCode: %d, errMsg: %s", t.Code(), t.Error())))
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,9 @@ type MachineScript struct {
 | 
			
		||||
func (m *MachineScript) MachineScripts(rc *req.Ctx) {
 | 
			
		||||
	g := rc.GinCtx
 | 
			
		||||
	condition := &entity.MachineScript{MachineId: GetMachineId(g)}
 | 
			
		||||
	rc.ResData = m.MachineScriptApp.GetPageList(condition, ginx.GetPageParam(g), new([]vo.MachineScriptVO))
 | 
			
		||||
	res, err := m.MachineScriptApp.GetPageList(condition, ginx.GetPageParam(g), new([]vo.MachineScriptVO))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MachineScript) SaveMachineScript(rc *req.Ctx) {
 | 
			
		||||
@@ -37,7 +39,7 @@ func (m *MachineScript) SaveMachineScript(rc *req.Ctx) {
 | 
			
		||||
	rc.ReqParam = form
 | 
			
		||||
	machineScript.SetBaseInfo(rc.LoginAccount)
 | 
			
		||||
 | 
			
		||||
	m.MachineScriptApp.Save(machineScript)
 | 
			
		||||
	biz.ErrIsNil(m.MachineScriptApp.Save(machineScript))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MachineScript) DeleteMachineScript(rc *req.Ctx) {
 | 
			
		||||
@@ -57,8 +59,8 @@ func (m *MachineScript) RunMachineScript(rc *req.Ctx) {
 | 
			
		||||
 | 
			
		||||
	scriptId := GetMachineScriptId(g)
 | 
			
		||||
	machineId := GetMachineId(g)
 | 
			
		||||
	ms := m.MachineScriptApp.GetById(scriptId, "MachineId", "Name", "Script")
 | 
			
		||||
	biz.NotNil(ms, "该脚本不存在")
 | 
			
		||||
	ms, err := m.MachineScriptApp.GetById(new(entity.MachineScript), scriptId, "MachineId", "Name", "Script")
 | 
			
		||||
	biz.ErrIsNil(err, "该脚本不存在")
 | 
			
		||||
	biz.IsTrue(ms.MachineId == application.Common_Script_Machine_Id || ms.MachineId == machineId, "该脚本不属于该机器")
 | 
			
		||||
 | 
			
		||||
	script := ms.Script
 | 
			
		||||
@@ -66,7 +68,8 @@ func (m *MachineScript) RunMachineScript(rc *req.Ctx) {
 | 
			
		||||
	if params := g.Query("params"); params != "" {
 | 
			
		||||
		script = stringx.TemplateParse(ms.Script, jsonx.ToMap(params))
 | 
			
		||||
	}
 | 
			
		||||
	cli := m.MachineApp.GetCli(machineId)
 | 
			
		||||
	cli, err := m.MachineApp.GetCli(machineId)
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
 | 
			
		||||
	biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
 | 
			
		||||
 | 
			
		||||
	res, err := cli.Run(script)
 | 
			
		||||
 
 | 
			
		||||
@@ -5,17 +5,23 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	machineFileApp MachineFile = newMachineFileApp(persistence.GetMachineFileRepo(), persistence.GetMachineRepo())
 | 
			
		||||
 | 
			
		||||
	machineScriptApp MachineScript = newMachineScriptApp(persistence.GetMachineScriptRepo(), persistence.GetMachineRepo())
 | 
			
		||||
 | 
			
		||||
	authCertApp AuthCert = newAuthCertApp(persistence.GetAuthCertRepo())
 | 
			
		||||
 | 
			
		||||
	machineApp Machine = newMachineApp(
 | 
			
		||||
		persistence.GetMachineRepo(),
 | 
			
		||||
		GetAuthCertApp(),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	machineFileApp MachineFile = newMachineFileApp(
 | 
			
		||||
		persistence.GetMachineFileRepo(),
 | 
			
		||||
		GetMachineApp(),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	machineScriptApp MachineScript = newMachineScriptApp(
 | 
			
		||||
		persistence.GetMachineScriptRepo(),
 | 
			
		||||
		GetMachineApp(),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	authCertApp AuthCert = newAuthCertApp(persistence.GetAuthCertRepo())
 | 
			
		||||
 | 
			
		||||
	machineCropJobApp MachineCronJob = newMachineCronJobApp(
 | 
			
		||||
		persistence.GetMachineCronJobRepo(),
 | 
			
		||||
		persistence.GetMachineCronJobRelateRepo(),
 | 
			
		||||
 
 | 
			
		||||
@@ -3,62 +3,56 @@ package application
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type AuthCert interface {
 | 
			
		||||
	GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	base.App[*entity.AuthCert]
 | 
			
		||||
 | 
			
		||||
	Save(ac *entity.AuthCert)
 | 
			
		||||
	GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	GetById(id uint64) *entity.AuthCert
 | 
			
		||||
	Save(ac *entity.AuthCert) error
 | 
			
		||||
 | 
			
		||||
	GetByIds(ids ...uint64) []*entity.AuthCert
 | 
			
		||||
 | 
			
		||||
	DeleteById(id uint64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newAuthCertApp(authCertRepo repository.AuthCert) AuthCert {
 | 
			
		||||
	return &authCertAppImpl{
 | 
			
		||||
		authCertRepo: authCertRepo,
 | 
			
		||||
		base.AppImpl[*entity.AuthCert, repository.AuthCert]{Repo: authCertRepo},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type authCertAppImpl struct {
 | 
			
		||||
	authCertRepo repository.AuthCert
 | 
			
		||||
	base.AppImpl[*entity.AuthCert, repository.AuthCert]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *authCertAppImpl) GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
	return a.authCertRepo.GetPageList(condition, pageParam, toEntity)
 | 
			
		||||
func (a *authCertAppImpl) GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return a.GetRepo().GetPageList(condition, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *authCertAppImpl) Save(ac *entity.AuthCert) {
 | 
			
		||||
func (a *authCertAppImpl) Save(ac *entity.AuthCert) error {
 | 
			
		||||
	oldAc := &entity.AuthCert{Name: ac.Name}
 | 
			
		||||
	err := a.authCertRepo.GetByCondition(oldAc, "Id", "Name")
 | 
			
		||||
	err := a.GetBy(oldAc, "Id", "Name")
 | 
			
		||||
 | 
			
		||||
	ac.PwdEncrypt()
 | 
			
		||||
	if ac.Id == 0 {
 | 
			
		||||
		biz.IsTrue(err != nil, "该凭证名已存在")
 | 
			
		||||
		a.authCertRepo.Insert(ac)
 | 
			
		||||
		return
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			return errorx.NewBiz("该凭证名已存在")
 | 
			
		||||
		}
 | 
			
		||||
		return a.Insert(ac)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 如果存在该库,则校验修改的库是否为该库
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		biz.IsTrue(oldAc.Id == ac.Id, "该凭证名已存在")
 | 
			
		||||
	if err == nil && oldAc.Id != ac.Id {
 | 
			
		||||
		return errorx.NewBiz("该凭证名已存在")
 | 
			
		||||
	}
 | 
			
		||||
	a.authCertRepo.Update(ac)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *authCertAppImpl) GetById(id uint64) *entity.AuthCert {
 | 
			
		||||
	return a.authCertRepo.GetById(id)
 | 
			
		||||
	return a.UpdateById(ac)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *authCertAppImpl) GetByIds(ids ...uint64) []*entity.AuthCert {
 | 
			
		||||
	return a.authCertRepo.GetByIds(ids...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *authCertAppImpl) DeleteById(id uint64) {
 | 
			
		||||
	a.authCertRepo.DeleteById(id)
 | 
			
		||||
	acs := new([]*entity.AuthCert)
 | 
			
		||||
	a.GetByIdIn(acs, ids)
 | 
			
		||||
	return *acs
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,8 @@ import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/repository"
 | 
			
		||||
	"mayfly-go/internal/machine/infrastructure/machine"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
 | 
			
		||||
@@ -13,90 +14,93 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Machine interface {
 | 
			
		||||
	// 根据条件获取账号信息
 | 
			
		||||
	GetMachine(condition *entity.Machine, cols ...string) error
 | 
			
		||||
	base.App[*entity.Machine]
 | 
			
		||||
 | 
			
		||||
	Save(*entity.Machine)
 | 
			
		||||
	Save(*entity.Machine) error
 | 
			
		||||
 | 
			
		||||
	// 测试机器连接
 | 
			
		||||
	TestConn(me *entity.Machine)
 | 
			
		||||
	TestConn(me *entity.Machine) error
 | 
			
		||||
 | 
			
		||||
	// 调整机器状态
 | 
			
		||||
	ChangeStatus(id uint64, status int8)
 | 
			
		||||
	ChangeStatus(id uint64, status int8) error
 | 
			
		||||
 | 
			
		||||
	Count(condition *entity.MachineQuery) int64
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.Machine
 | 
			
		||||
	Delete(id uint64) error
 | 
			
		||||
 | 
			
		||||
	// 分页获取机器信息列表
 | 
			
		||||
	GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) *model.PageResult[*[]*vo.MachineVO]
 | 
			
		||||
	GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) (*model.PageResult[*[]*vo.MachineVO], error)
 | 
			
		||||
 | 
			
		||||
	// 获取机器连接
 | 
			
		||||
	GetCli(id uint64) *machine.Cli
 | 
			
		||||
	GetCli(id uint64) (*machine.Cli, error)
 | 
			
		||||
 | 
			
		||||
	// 获取ssh隧道机器连接
 | 
			
		||||
	GetSshTunnelMachine(id int) *machine.SshTunnelMachine
 | 
			
		||||
	GetSshTunnelMachine(id int) (*machine.SshTunnelMachine, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newMachineApp(machineRepo repository.Machine, authCertApp AuthCert) Machine {
 | 
			
		||||
	return &machineAppImpl{
 | 
			
		||||
		machineRepo: machineRepo,
 | 
			
		||||
	app := &machineAppImpl{
 | 
			
		||||
		authCertApp: authCertApp,
 | 
			
		||||
	}
 | 
			
		||||
	app.Repo = machineRepo
 | 
			
		||||
	return app
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type machineAppImpl struct {
 | 
			
		||||
	machineRepo repository.Machine
 | 
			
		||||
	base.AppImpl[*entity.Machine, repository.Machine]
 | 
			
		||||
 | 
			
		||||
	authCertApp AuthCert
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取机器信息列表
 | 
			
		||||
func (m *machineAppImpl) GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) *model.PageResult[*[]*vo.MachineVO] {
 | 
			
		||||
	return m.machineRepo.GetMachineList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
func (m *machineAppImpl) GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) (*model.PageResult[*[]*vo.MachineVO], error) {
 | 
			
		||||
	return m.GetRepo().GetMachineList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineAppImpl) Count(condition *entity.MachineQuery) int64 {
 | 
			
		||||
	return m.machineRepo.Count(condition)
 | 
			
		||||
	return m.GetRepo().Count(condition)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineAppImpl) Save(me *entity.Machine) {
 | 
			
		||||
func (m *machineAppImpl) Save(me *entity.Machine) error {
 | 
			
		||||
	oldMachine := &entity.Machine{Ip: me.Ip, Port: me.Port, Username: me.Username}
 | 
			
		||||
	if me.SshTunnelMachineId > 0 {
 | 
			
		||||
		oldMachine.SshTunnelMachineId = me.SshTunnelMachineId
 | 
			
		||||
	}
 | 
			
		||||
	err := m.GetMachine(oldMachine)
 | 
			
		||||
	err := m.GetBy(oldMachine)
 | 
			
		||||
 | 
			
		||||
	me.PwdEncrypt()
 | 
			
		||||
	if me.Id == 0 {
 | 
			
		||||
		biz.IsTrue(err != nil, "该机器信息已存在")
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			return errorx.NewBiz("该机器信息已存在")
 | 
			
		||||
		}
 | 
			
		||||
		// 新增机器,默认启用状态
 | 
			
		||||
		me.Status = entity.MachineStatusEnable
 | 
			
		||||
		m.machineRepo.Create(me)
 | 
			
		||||
		return
 | 
			
		||||
		return m.Insert(me)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 如果存在该库,则校验修改的库是否为该库
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		biz.IsTrue(oldMachine.Id == me.Id, "该机器信息已存在")
 | 
			
		||||
	if err == nil && oldMachine.Id != me.Id {
 | 
			
		||||
		return errorx.NewBiz("该机器信息已存在")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 关闭连接
 | 
			
		||||
	machine.DeleteCli(me.Id)
 | 
			
		||||
	m.machineRepo.UpdateById(me)
 | 
			
		||||
	return m.UpdateById(me)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineAppImpl) TestConn(me *entity.Machine) {
 | 
			
		||||
func (m *machineAppImpl) TestConn(me *entity.Machine) error {
 | 
			
		||||
	me.Id = 0
 | 
			
		||||
	// 测试连接
 | 
			
		||||
	biz.ErrIsNilAppendErr(machine.TestConn(*m.toMachineInfo(me), func(u uint64) *machine.Info {
 | 
			
		||||
	mi, err := m.toMachineInfo(me)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return machine.TestConn(*mi, func(u uint64) (*machine.Info, error) {
 | 
			
		||||
		return m.toMachineInfoById(u)
 | 
			
		||||
	}), "该机器无法连接: %s")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineAppImpl) ChangeStatus(id uint64, status int8) {
 | 
			
		||||
func (m *machineAppImpl) ChangeStatus(id uint64, status int8) error {
 | 
			
		||||
	if status == entity.MachineStatusDisable {
 | 
			
		||||
		// 关闭连接
 | 
			
		||||
		machine.DeleteCli(id)
 | 
			
		||||
@@ -104,63 +108,55 @@ func (m *machineAppImpl) ChangeStatus(id uint64, status int8) {
 | 
			
		||||
	machine := new(entity.Machine)
 | 
			
		||||
	machine.Id = id
 | 
			
		||||
	machine.Status = status
 | 
			
		||||
	m.machineRepo.UpdateById(machine)
 | 
			
		||||
	return m.UpdateById(machine)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据条件获取机器信息
 | 
			
		||||
func (m *machineAppImpl) Delete(id uint64) {
 | 
			
		||||
func (m *machineAppImpl) Delete(id uint64) error {
 | 
			
		||||
	// 关闭连接
 | 
			
		||||
	machine.DeleteCli(id)
 | 
			
		||||
	gormx.Tx(
 | 
			
		||||
	return gormx.Tx(
 | 
			
		||||
		func(db *gorm.DB) error {
 | 
			
		||||
			// 删除machine表信息
 | 
			
		||||
			return gormx.DeleteByIdWithDb(db, new(entity.Machine), id)
 | 
			
		||||
		},
 | 
			
		||||
		func(db *gorm.DB) error {
 | 
			
		||||
			// 删除machine_file
 | 
			
		||||
			return gormx.DeleteByConditionWithDb(db, &entity.MachineFile{MachineId: id})
 | 
			
		||||
			return gormx.DeleteByWithDb(db, &entity.MachineFile{MachineId: id})
 | 
			
		||||
		},
 | 
			
		||||
		func(db *gorm.DB) error {
 | 
			
		||||
			// 删除machine_script
 | 
			
		||||
			return gormx.DeleteByConditionWithDb(db, &entity.MachineScript{MachineId: id})
 | 
			
		||||
			return gormx.DeleteByWithDb(db, &entity.MachineScript{MachineId: id})
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据条件获取机器信息
 | 
			
		||||
func (m *machineAppImpl) GetMachine(condition *entity.Machine, cols ...string) error {
 | 
			
		||||
	return m.machineRepo.GetMachine(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineAppImpl) GetById(id uint64, cols ...string) *entity.Machine {
 | 
			
		||||
	return m.machineRepo.GetById(id, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineAppImpl) GetCli(machineId uint64) *machine.Cli {
 | 
			
		||||
	cli, err := machine.GetCli(machineId, func(mid uint64) *machine.Info {
 | 
			
		||||
func (m *machineAppImpl) GetCli(machineId uint64) (*machine.Cli, error) {
 | 
			
		||||
	return machine.GetCli(machineId, func(mid uint64) (*machine.Info, error) {
 | 
			
		||||
		return m.toMachineInfoById(mid)
 | 
			
		||||
	})
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取客户端错误: %s")
 | 
			
		||||
	return cli
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineAppImpl) GetSshTunnelMachine(machineId int) *machine.SshTunnelMachine {
 | 
			
		||||
	sshTunnel, err := machine.GetSshTunnelMachine(machineId, func(mid uint64) *machine.Info {
 | 
			
		||||
func (m *machineAppImpl) GetSshTunnelMachine(machineId int) (*machine.SshTunnelMachine, error) {
 | 
			
		||||
	return machine.GetSshTunnelMachine(machineId, func(mid uint64) (*machine.Info, error) {
 | 
			
		||||
		return m.toMachineInfoById(mid)
 | 
			
		||||
	})
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取ssh隧道连接失败: %s")
 | 
			
		||||
	return sshTunnel
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 生成机器信息,根据授权凭证id填充用户密码等
 | 
			
		||||
func (m *machineAppImpl) toMachineInfoById(machineId uint64) *machine.Info {
 | 
			
		||||
	me := m.GetById(machineId)
 | 
			
		||||
	biz.IsTrue(me.Status == entity.MachineStatusEnable, "该机器已被停用")
 | 
			
		||||
func (m *machineAppImpl) toMachineInfoById(machineId uint64) (*machine.Info, error) {
 | 
			
		||||
	me, err := m.GetById(new(entity.Machine), machineId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errorx.NewBiz("机器信息不存在")
 | 
			
		||||
	}
 | 
			
		||||
	if me.Status != entity.MachineStatusEnable {
 | 
			
		||||
		return nil, errorx.NewBiz("该机器已被停用")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return m.toMachineInfo(me)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineAppImpl) toMachineInfo(me *entity.Machine) *machine.Info {
 | 
			
		||||
func (m *machineAppImpl) toMachineInfo(me *entity.Machine) (*machine.Info, error) {
 | 
			
		||||
	mi := new(machine.Info)
 | 
			
		||||
	mi.Id = me.Id
 | 
			
		||||
	mi.Name = me.Name
 | 
			
		||||
@@ -173,8 +169,10 @@ func (m *machineAppImpl) toMachineInfo(me *entity.Machine) *machine.Info {
 | 
			
		||||
	mi.SshTunnelMachineId = me.SshTunnelMachineId
 | 
			
		||||
 | 
			
		||||
	if me.UseAuthCert() {
 | 
			
		||||
		ac := m.authCertApp.GetById(uint64(me.AuthCertId))
 | 
			
		||||
		biz.NotNil(ac, "授权凭证信息已不存在,请重新关联")
 | 
			
		||||
		ac, err := m.authCertApp.GetById(new(entity.AuthCert), uint64(me.AuthCertId))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, errorx.NewBiz("授权凭证信息已不存在,请重新关联")
 | 
			
		||||
		}
 | 
			
		||||
		mi.AuthMethod = ac.AuthMethod
 | 
			
		||||
		ac.PwdDecrypt()
 | 
			
		||||
		mi.Password = ac.Password
 | 
			
		||||
@@ -186,5 +184,5 @@ func (m *machineAppImpl) toMachineInfo(me *entity.Machine) *machine.Info {
 | 
			
		||||
		}
 | 
			
		||||
		mi.Password = me.Password
 | 
			
		||||
	}
 | 
			
		||||
	return mi
 | 
			
		||||
	return mi, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,30 +3,33 @@ package application
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/logx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
	"mayfly-go/pkg/rediscli"
 | 
			
		||||
	"mayfly-go/pkg/scheduler"
 | 
			
		||||
	"mayfly-go/pkg/utils/anyx"
 | 
			
		||||
	"mayfly-go/pkg/utils/collx"
 | 
			
		||||
	"mayfly-go/pkg/utils/stringx"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type MachineCronJob interface {
 | 
			
		||||
	base.App[*entity.MachineCronJob]
 | 
			
		||||
 | 
			
		||||
	// 分页获取机器任务列表信息
 | 
			
		||||
	GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	// 获取分页执行结果列表
 | 
			
		||||
	GetExecPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetExecPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.MachineCronJob
 | 
			
		||||
 | 
			
		||||
	Save(entity *entity.MachineCronJob) uint64
 | 
			
		||||
	Save(entity *entity.MachineCronJob) (uint64, error)
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
 | 
			
		||||
	// 获取管理的机器列表id
 | 
			
		||||
	// 获取计划任务关联的机器列表id
 | 
			
		||||
	GetRelateMachineIds(cronJobId uint64) []uint64
 | 
			
		||||
 | 
			
		||||
	// 获取机器关联的计划任务列表
 | 
			
		||||
@@ -43,7 +46,8 @@ type MachineCronJob interface {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type machineCropJobAppImpl struct {
 | 
			
		||||
	machineCropJobRepo       repository.MachineCronJob
 | 
			
		||||
	base.AppImpl[*entity.MachineCronJob, repository.MachineCronJob]
 | 
			
		||||
 | 
			
		||||
	machineCropJobRelateRepo repository.MachineCronJobRelate
 | 
			
		||||
	machineCropJobExecRepo   repository.MachineCronJobExec
 | 
			
		||||
	machineApp               Machine
 | 
			
		||||
@@ -55,48 +59,50 @@ func newMachineCronJobApp(
 | 
			
		||||
	machineCropJobExecRepo repository.MachineCronJobExec,
 | 
			
		||||
	machineApp Machine,
 | 
			
		||||
) MachineCronJob {
 | 
			
		||||
	return &machineCropJobAppImpl{
 | 
			
		||||
		machineCropJobRepo:       machineCropJobRepo,
 | 
			
		||||
	app := &machineCropJobAppImpl{
 | 
			
		||||
		machineCropJobRelateRepo: machineCropJobRelateRepo,
 | 
			
		||||
		machineCropJobExecRepo:   machineCropJobExecRepo,
 | 
			
		||||
		machineApp:               machineApp,
 | 
			
		||||
	}
 | 
			
		||||
	app.Repo = machineCropJobRepo
 | 
			
		||||
	return app
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取机器脚本任务列表
 | 
			
		||||
func (m *machineCropJobAppImpl) GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
	return m.machineCropJobRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
func (m *machineCropJobAppImpl) GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return m.GetRepo().GetPageList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取分页执行结果列表
 | 
			
		||||
func (m *machineCropJobAppImpl) GetExecPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (m *machineCropJobAppImpl) GetExecPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return m.machineCropJobExecRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取
 | 
			
		||||
func (m *machineCropJobAppImpl) GetById(id uint64, cols ...string) *entity.MachineCronJob {
 | 
			
		||||
	return m.machineCropJobRepo.GetById(id, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 保存机器任务信息
 | 
			
		||||
func (m *machineCropJobAppImpl) Save(mcj *entity.MachineCronJob) uint64 {
 | 
			
		||||
func (m *machineCropJobAppImpl) Save(mcj *entity.MachineCronJob) (uint64, error) {
 | 
			
		||||
	// 更新操作
 | 
			
		||||
	if mcj.Id != 0 {
 | 
			
		||||
		m.machineCropJobRepo.UpdateById(mcj)
 | 
			
		||||
		m.UpdateById(mcj)
 | 
			
		||||
		cj, err := m.GetById(new(entity.MachineCronJob), mcj.Id)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, errorx.NewBiz("该任务不存在")
 | 
			
		||||
		}
 | 
			
		||||
		// 处理最新的计划任务
 | 
			
		||||
		m.addCronJob(m.GetById(mcj.Id))
 | 
			
		||||
		return mcj.Id
 | 
			
		||||
		m.addCronJob(cj)
 | 
			
		||||
		return mcj.Id, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m.addCronJob(mcj)
 | 
			
		||||
	m.machineCropJobRepo.Insert(mcj)
 | 
			
		||||
	return mcj.Id
 | 
			
		||||
	if err := m.Insert(mcj); err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return mcj.Id, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobAppImpl) Delete(id uint64) {
 | 
			
		||||
	m.machineCropJobRepo.Delete(id)
 | 
			
		||||
	m.machineCropJobExecRepo.Delete(&entity.MachineCronJobExec{CronJobId: id})
 | 
			
		||||
	m.machineCropJobRelateRepo.Delete(&entity.MachineCronJobRelate{CronJobId: id})
 | 
			
		||||
	m.DeleteById(id)
 | 
			
		||||
	m.machineCropJobExecRepo.DeleteByCond(&entity.MachineCronJobExec{CronJobId: id})
 | 
			
		||||
	m.machineCropJobRelateRepo.DeleteByCond(&entity.MachineCronJobRelate{CronJobId: id})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobAppImpl) GetRelateMachineIds(cronJobId uint64) []uint64 {
 | 
			
		||||
@@ -125,7 +131,7 @@ func (m *machineCropJobAppImpl) CronJobRelateMachines(cronJobId uint64, machineI
 | 
			
		||||
	m.machineCropJobRelateRepo.BatchInsert(addVals)
 | 
			
		||||
 | 
			
		||||
	for _, delId := range delIds {
 | 
			
		||||
		m.machineCropJobRelateRepo.Delete(&entity.MachineCronJobRelate{CronJobId: cronJobId, MachineId: delId})
 | 
			
		||||
		m.machineCropJobRelateRepo.DeleteByCond(&entity.MachineCronJobRelate{CronJobId: cronJobId, MachineId: delId})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -147,14 +153,14 @@ func (m *machineCropJobAppImpl) MachineRelateCronJobs(machineId uint64, cronJobs
 | 
			
		||||
	m.machineCropJobRelateRepo.BatchInsert(addVals)
 | 
			
		||||
 | 
			
		||||
	for _, delId := range delIds {
 | 
			
		||||
		m.machineCropJobRelateRepo.Delete(&entity.MachineCronJobRelate{CronJobId: delId, MachineId: machineId})
 | 
			
		||||
		m.machineCropJobRelateRepo.DeleteByCond(&entity.MachineCronJobRelate{CronJobId: delId, MachineId: machineId})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobAppImpl) InitCronJob() {
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if err := recover(); err != nil {
 | 
			
		||||
			logx.Errorf("机器计划任务初始化失败: %s", err.(error).Error())
 | 
			
		||||
			logx.ErrorTrace("机器计划任务初始化失败: %s", err.(error))
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
@@ -166,7 +172,7 @@ func (m *machineCropJobAppImpl) InitCronJob() {
 | 
			
		||||
	cond.Status = entity.MachineCronJobStatusEnable
 | 
			
		||||
	mcjs := new([]entity.MachineCronJob)
 | 
			
		||||
 | 
			
		||||
	pr := m.GetPageList(cond, pageParam, mcjs)
 | 
			
		||||
	pr, _ := m.GetPageList(cond, pageParam, mcjs)
 | 
			
		||||
	total := pr.Total
 | 
			
		||||
	add := 0
 | 
			
		||||
 | 
			
		||||
@@ -218,7 +224,7 @@ func (m *machineCropJobAppImpl) runCronJob(key string) {
 | 
			
		||||
 | 
			
		||||
	cronJob := new(entity.MachineCronJob)
 | 
			
		||||
	cronJob.Key = key
 | 
			
		||||
	err := m.machineCropJobRepo.GetBy(cronJob)
 | 
			
		||||
	err := m.GetBy(cronJob)
 | 
			
		||||
	// 不存在或禁用,则移除该任务
 | 
			
		||||
	if err != nil || cronJob.Status == entity.MachineCronJobStatusDisable {
 | 
			
		||||
		scheduler.RemoveByKey(key)
 | 
			
		||||
@@ -233,7 +239,7 @@ func (m *machineCropJobAppImpl) runCronJob(key string) {
 | 
			
		||||
func (m *machineCropJobAppImpl) runCronJob0(mid uint64, cronJob *entity.MachineCronJob) {
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if err := recover(); err != nil {
 | 
			
		||||
			res := err.(error).Error()
 | 
			
		||||
			res := anyx.ToString(err)
 | 
			
		||||
			m.machineCropJobExecRepo.Insert(&entity.MachineCronJobExec{
 | 
			
		||||
				MachineId: mid,
 | 
			
		||||
				CronJobId: cronJob.Id,
 | 
			
		||||
@@ -245,7 +251,9 @@ func (m *machineCropJobAppImpl) runCronJob0(mid uint64, cronJob *entity.MachineC
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	res, err := m.machineApp.GetCli(uint64(mid)).Run(cronJob.Script)
 | 
			
		||||
	machineCli, err := m.machineApp.GetCli(uint64(mid))
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
 | 
			
		||||
	res, err := machineCli.Run(cronJob.Script)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if res == "" {
 | 
			
		||||
			res = err.Error()
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/repository"
 | 
			
		||||
	"mayfly-go/internal/machine/infrastructure/machine"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/logx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
	"os"
 | 
			
		||||
@@ -19,7 +19,7 @@ import (
 | 
			
		||||
 | 
			
		||||
type MachineFile interface {
 | 
			
		||||
	// 分页获取机器文件信息列表
 | 
			
		||||
	GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	// 根据条件获取
 | 
			
		||||
	GetMachineFile(condition *entity.MachineFile, cols ...string) error
 | 
			
		||||
@@ -27,15 +27,15 @@ type MachineFile interface {
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.MachineFile
 | 
			
		||||
 | 
			
		||||
	Save(entity *entity.MachineFile)
 | 
			
		||||
	Save(entity *entity.MachineFile) error
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
	Delete(id uint64) error
 | 
			
		||||
 | 
			
		||||
	// 获取文件关联的机器信息,主要用于记录日志使用
 | 
			
		||||
	// GetMachine(fileId uint64) *machine.Info
 | 
			
		||||
 | 
			
		||||
	// 检查文件路径,并返回机器id
 | 
			
		||||
	GetMachineCli(fileId uint64, path ...string) *machine.Cli
 | 
			
		||||
	GetMachineCli(fileId uint64, path ...string) (*machine.Cli, error)
 | 
			
		||||
 | 
			
		||||
	/**  sftp 相关操作 **/
 | 
			
		||||
 | 
			
		||||
@@ -46,13 +46,13 @@ type MachineFile interface {
 | 
			
		||||
	CreateFile(fid uint64, path string) (*machine.Info, error)
 | 
			
		||||
 | 
			
		||||
	// 读取目录
 | 
			
		||||
	ReadDir(fid uint64, path string) []fs.FileInfo
 | 
			
		||||
	ReadDir(fid uint64, path string) ([]fs.FileInfo, error)
 | 
			
		||||
 | 
			
		||||
	// 获取指定目录内容大小
 | 
			
		||||
	GetDirSize(fid uint64, path string) string
 | 
			
		||||
	GetDirSize(fid uint64, path string) (string, error)
 | 
			
		||||
 | 
			
		||||
	// 获取文件stat
 | 
			
		||||
	FileStat(fid uint64, path string) string
 | 
			
		||||
	FileStat(fid uint64, path string) (string, error)
 | 
			
		||||
 | 
			
		||||
	// 读取文件内容
 | 
			
		||||
	ReadFile(fileId uint64, path string) (*sftp.File, *machine.Info, error)
 | 
			
		||||
@@ -73,18 +73,19 @@ type MachineFile interface {
 | 
			
		||||
	Rename(fileId uint64, oldname string, newname string) (*machine.Info, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newMachineFileApp(machineFileRepo repository.MachineFile, machineRepo repository.Machine) MachineFile {
 | 
			
		||||
	return &machineFileAppImpl{machineRepo: machineRepo, machineFileRepo: machineFileRepo}
 | 
			
		||||
func newMachineFileApp(machineFileRepo repository.MachineFile, machineApp Machine) MachineFile {
 | 
			
		||||
	return &machineFileAppImpl{machineApp: machineApp, machineFileRepo: machineFileRepo}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type machineFileAppImpl struct {
 | 
			
		||||
	machineFileRepo repository.MachineFile
 | 
			
		||||
	machineRepo     repository.Machine
 | 
			
		||||
 | 
			
		||||
	machineApp Machine
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取机器脚本信息列表
 | 
			
		||||
func (m *machineFileAppImpl) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (m *machineFileAppImpl) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return m.machineFileRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -99,34 +100,41 @@ func (m *machineFileAppImpl) GetById(id uint64, cols ...string) *entity.MachineF
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 保存机器文件配置
 | 
			
		||||
func (m *machineFileAppImpl) Save(entity *entity.MachineFile) {
 | 
			
		||||
	biz.NotNil(m.machineRepo.GetById(entity.MachineId, "Name"), "该机器不存在")
 | 
			
		||||
 | 
			
		||||
	if entity.Id != 0 {
 | 
			
		||||
		m.machineFileRepo.UpdateById(entity)
 | 
			
		||||
	} else {
 | 
			
		||||
		m.machineFileRepo.Create(entity)
 | 
			
		||||
func (m *machineFileAppImpl) Save(mf *entity.MachineFile) error {
 | 
			
		||||
	_, err := m.machineApp.GetById(new(entity.Machine), mf.MachineId, "Name")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errorx.NewBiz("该机器不存在")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if mf.Id != 0 {
 | 
			
		||||
		return m.machineFileRepo.UpdateById(mf)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return m.machineFileRepo.Create(mf)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id删除
 | 
			
		||||
func (m *machineFileAppImpl) Delete(id uint64) {
 | 
			
		||||
	m.machineFileRepo.Delete(id)
 | 
			
		||||
func (m *machineFileAppImpl) Delete(id uint64) error {
 | 
			
		||||
	return m.machineFileRepo.Delete(id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineFileAppImpl) ReadDir(fid uint64, path string) []fs.FileInfo {
 | 
			
		||||
	mcli := m.GetMachineCli(fid, path)
 | 
			
		||||
func (m *machineFileAppImpl) ReadDir(fid uint64, path string) ([]fs.FileInfo, error) {
 | 
			
		||||
	if !strings.HasSuffix(path, "/") {
 | 
			
		||||
		path = path + "/"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fis, err := mcli.GetSftpCli().ReadDir(path)
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "读取目录失败: %s")
 | 
			
		||||
	return fis
 | 
			
		||||
	_, sftpCli, err := m.GetMachineSftpCli(fid, path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return sftpCli.ReadDir(path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineFileAppImpl) GetDirSize(fid uint64, path string) string {
 | 
			
		||||
	mcli := m.GetMachineCli(fid, path)
 | 
			
		||||
func (m *machineFileAppImpl) GetDirSize(fid uint64, path string) (string, error) {
 | 
			
		||||
	mcli, err := m.GetMachineCli(fid, path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	res, err := mcli.Run(fmt.Sprintf("du -sh %s", path))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// 若存在目录为空,则可能会返回如下内容。最后一行即为真正目录内容所占磁盘空间大小
 | 
			
		||||
@@ -134,56 +142,74 @@ func (m *machineFileAppImpl) GetDirSize(fid uint64, path string) string {
 | 
			
		||||
		//du: cannot access ‘/proc/19087/fdinfo/3’: No such file or directory\n
 | 
			
		||||
		//18G     /\n
 | 
			
		||||
		if res == "" {
 | 
			
		||||
			panic(biz.NewBizErr(fmt.Sprintf("获取目录大小失败: %s", err.Error())))
 | 
			
		||||
			return "", errorx.NewBiz("获取目录大小失败: %s", err.Error())
 | 
			
		||||
		}
 | 
			
		||||
		strs := strings.Split(res, "\n")
 | 
			
		||||
		res = strs[len(strs)-2]
 | 
			
		||||
 | 
			
		||||
		if !strings.Contains(res, "\t") {
 | 
			
		||||
			panic(biz.NewBizErr(res))
 | 
			
		||||
			return "", errorx.NewBiz(res)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// 返回 32K\t/tmp\n
 | 
			
		||||
	return strings.Split(res, "\t")[0]
 | 
			
		||||
	return strings.Split(res, "\t")[0], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineFileAppImpl) FileStat(fid uint64, path string) string {
 | 
			
		||||
	mcli := m.GetMachineCli(fid, path)
 | 
			
		||||
	res, err := mcli.Run(fmt.Sprintf("stat -L %s", path))
 | 
			
		||||
	biz.ErrIsNil(err, res)
 | 
			
		||||
	return res
 | 
			
		||||
func (m *machineFileAppImpl) FileStat(fid uint64, path string) (string, error) {
 | 
			
		||||
	mcli, err := m.GetMachineCli(fid, path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return mcli.Run(fmt.Sprintf("stat -L %s", path))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineFileAppImpl) MkDir(fid uint64, path string) (*machine.Info, error) {
 | 
			
		||||
	mcli := m.GetMachineCli(fid, path)
 | 
			
		||||
	if !strings.HasSuffix(path, "/") {
 | 
			
		||||
		path = path + "/"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := mcli.GetSftpCli().MkdirAll(path)
 | 
			
		||||
	return mcli.GetMachine(), err
 | 
			
		||||
	mi, sftpCli, err := m.GetMachineSftpCli(fid, path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sftpCli.MkdirAll(path)
 | 
			
		||||
	return mi, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineFileAppImpl) CreateFile(fid uint64, path string) (*machine.Info, error) {
 | 
			
		||||
	mcli := m.GetMachineCli(fid, path)
 | 
			
		||||
	file, err := mcli.GetSftpCli().Create(path)
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "创建文件失败: %s")
 | 
			
		||||
	mi, sftpCli, err := m.GetMachineSftpCli(fid, path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	file, err := sftpCli.Create(path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errorx.NewBiz("创建文件失败: %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	defer file.Close()
 | 
			
		||||
	return mcli.GetMachine(), err
 | 
			
		||||
	return mi, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineFileAppImpl) ReadFile(fileId uint64, path string) (*sftp.File, *machine.Info, error) {
 | 
			
		||||
	mcli := m.GetMachineCli(fileId, path)
 | 
			
		||||
	mi, sftpCli, err := m.GetMachineSftpCli(fileId, path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 读取文件内容
 | 
			
		||||
	fc, err := mcli.GetSftpCli().Open(path)
 | 
			
		||||
	return fc, mcli.GetMachine(), err
 | 
			
		||||
	fc, err := sftpCli.Open(path)
 | 
			
		||||
	return fc, mi, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 写文件内容
 | 
			
		||||
func (m *machineFileAppImpl) WriteFileContent(fileId uint64, path string, content []byte) (*machine.Info, error) {
 | 
			
		||||
	mcli := m.GetMachineCli(fileId, path)
 | 
			
		||||
	mi := mcli.GetMachine()
 | 
			
		||||
	f, err := mcli.GetSftpCli().OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE|os.O_RDWR)
 | 
			
		||||
	mi, sftpCli, err := m.GetMachineSftpCli(fileId, path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f, err := sftpCli.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE|os.O_RDWR)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return mi, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -194,13 +220,16 @@ func (m *machineFileAppImpl) WriteFileContent(fileId uint64, path string, conten
 | 
			
		||||
 | 
			
		||||
// 上传文件
 | 
			
		||||
func (m *machineFileAppImpl) UploadFile(fileId uint64, path, filename string, reader io.Reader) (*machine.Info, error) {
 | 
			
		||||
	mcli := m.GetMachineCli(fileId, path)
 | 
			
		||||
	mi := mcli.GetMachine()
 | 
			
		||||
	if !strings.HasSuffix(path, "/") {
 | 
			
		||||
		path = path + "/"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	createfile, err := mcli.GetSftpCli().Create(path + filename)
 | 
			
		||||
	mi, sftpCli, err := m.GetMachineSftpCli(fileId, path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	createfile, err := sftpCli.Create(path + filename)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return mi, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -211,7 +240,10 @@ func (m *machineFileAppImpl) UploadFile(fileId uint64, path, filename string, re
 | 
			
		||||
 | 
			
		||||
// 删除文件
 | 
			
		||||
func (m *machineFileAppImpl) RemoveFile(fileId uint64, path ...string) (*machine.Info, error) {
 | 
			
		||||
	mcli := m.GetMachineCli(fileId, path...)
 | 
			
		||||
	mcli, err := m.GetMachineCli(fileId, path...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	minfo := mcli.GetMachine()
 | 
			
		||||
 | 
			
		||||
	// 优先使用命令删除(速度快),sftp需要递归遍历删除子文件等
 | 
			
		||||
@@ -221,7 +253,11 @@ func (m *machineFileAppImpl) RemoveFile(fileId uint64, path ...string) (*machine
 | 
			
		||||
	}
 | 
			
		||||
	logx.Errorf("使用命令rm删除文件失败: %s", res)
 | 
			
		||||
 | 
			
		||||
	sftpCli := mcli.GetSftpCli()
 | 
			
		||||
	sftpCli, err := mcli.GetSftpCli()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return minfo, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, p := range path {
 | 
			
		||||
		err = sftpCli.RemoveAll(p)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
@@ -232,7 +268,11 @@ func (m *machineFileAppImpl) RemoveFile(fileId uint64, path ...string) (*machine
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineFileAppImpl) Copy(fileId uint64, toPath string, paths ...string) (*machine.Info, error) {
 | 
			
		||||
	mcli := m.GetMachineCli(fileId, paths...)
 | 
			
		||||
	mcli, err := m.GetMachineCli(fileId, paths...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mi := mcli.GetMachine()
 | 
			
		||||
	res, err := mcli.Run(fmt.Sprintf("cp -r %s %s", strings.Join(paths, " "), toPath))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -242,28 +282,54 @@ func (m *machineFileAppImpl) Copy(fileId uint64, toPath string, paths ...string)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineFileAppImpl) Mv(fileId uint64, toPath string, paths ...string) (*machine.Info, error) {
 | 
			
		||||
	mcli := m.GetMachineCli(fileId, paths...)
 | 
			
		||||
	mcli, err := m.GetMachineCli(fileId, paths...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mi := mcli.GetMachine()
 | 
			
		||||
	res, err := mcli.Run(fmt.Sprintf("mv %s %s", strings.Join(paths, " "), toPath))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return mi, errors.New(res)
 | 
			
		||||
		return mi, errorx.NewBiz(res)
 | 
			
		||||
	}
 | 
			
		||||
	return mi, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineFileAppImpl) Rename(fileId uint64, oldname string, newname string) (*machine.Info, error) {
 | 
			
		||||
	mcli := m.GetMachineCli(fileId, newname)
 | 
			
		||||
	return mcli.GetMachine(), mcli.GetSftpCli().Rename(oldname, newname)
 | 
			
		||||
	mi, sftpCli, err := m.GetMachineSftpCli(fileId, newname)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return mi, sftpCli.Rename(oldname, newname)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取文件机器cli
 | 
			
		||||
func (m *machineFileAppImpl) GetMachineCli(fid uint64, inputPath ...string) *machine.Cli {
 | 
			
		||||
	biz.IsTrue(fid != 0, "文件id不能为空")
 | 
			
		||||
func (m *machineFileAppImpl) GetMachineCli(fid uint64, inputPath ...string) (*machine.Cli, error) {
 | 
			
		||||
	mf := m.GetById(fid)
 | 
			
		||||
	biz.NotNil(mf, "文件不存在")
 | 
			
		||||
	if mf == nil {
 | 
			
		||||
		return nil, errorx.NewBiz("文件不存在")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, path := range inputPath {
 | 
			
		||||
		// 接口传入的地址需为配置路径的子路径
 | 
			
		||||
		biz.IsTrue(strings.HasPrefix(path, mf.Path), "无权访问该目录或文件: %s", path)
 | 
			
		||||
		if !strings.HasPrefix(path, mf.Path) {
 | 
			
		||||
			return nil, errorx.NewBiz("无权访问该目录或文件: %s", path)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return GetMachineApp().GetCli(mf.MachineId)
 | 
			
		||||
	return m.machineApp.GetCli(mf.MachineId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取文件机器 sftp cli
 | 
			
		||||
func (m *machineFileAppImpl) GetMachineSftpCli(fid uint64, inputPath ...string) (*machine.Info, *sftp.Client, error) {
 | 
			
		||||
	mcli, err := m.GetMachineCli(fid, inputPath...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sftpCli, err := mcli.GetSftpCli()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return mcli.GetMachine(), sftpCli, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,68 +3,58 @@ package application
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type MachineScript interface {
 | 
			
		||||
	base.App[*entity.MachineScript]
 | 
			
		||||
 | 
			
		||||
	// 分页获取机器脚本信息列表
 | 
			
		||||
	GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	// 根据条件获取
 | 
			
		||||
	GetMachineScript(condition *entity.MachineScript, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.MachineScript
 | 
			
		||||
 | 
			
		||||
	Save(entity *entity.MachineScript)
 | 
			
		||||
	Save(entity *entity.MachineScript) error
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newMachineScriptApp(machineScriptRepo repository.MachineScript, machineRepo repository.Machine) MachineScript {
 | 
			
		||||
	return &machineScriptAppImpl{machineRepo: machineRepo, machineScriptRepo: machineScriptRepo}
 | 
			
		||||
 | 
			
		||||
func newMachineScriptApp(machineScriptRepo repository.MachineScript, machineApp Machine) MachineScript {
 | 
			
		||||
	app := &machineScriptAppImpl{machineApp: machineApp}
 | 
			
		||||
	app.Repo = machineScriptRepo
 | 
			
		||||
	return app
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type machineScriptAppImpl struct {
 | 
			
		||||
	machineScriptRepo repository.MachineScript
 | 
			
		||||
	machineRepo       repository.Machine
 | 
			
		||||
	base.AppImpl[*entity.MachineScript, repository.MachineScript]
 | 
			
		||||
 | 
			
		||||
	machineApp Machine
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Common_Script_Machine_Id = 9999999
 | 
			
		||||
 | 
			
		||||
// 分页获取机器脚本信息列表
 | 
			
		||||
func (m *machineScriptAppImpl) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
	return m.machineScriptRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据条件获取
 | 
			
		||||
func (m *machineScriptAppImpl) GetMachineScript(condition *entity.MachineScript, cols ...string) error {
 | 
			
		||||
	return m.machineScriptRepo.GetMachineScript(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取
 | 
			
		||||
func (m *machineScriptAppImpl) GetById(id uint64, cols ...string) *entity.MachineScript {
 | 
			
		||||
	return m.machineScriptRepo.GetById(id, cols...)
 | 
			
		||||
func (m *machineScriptAppImpl) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return m.GetRepo().GetPageList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 保存机器脚本
 | 
			
		||||
func (m *machineScriptAppImpl) Save(entity *entity.MachineScript) {
 | 
			
		||||
func (m *machineScriptAppImpl) Save(ms *entity.MachineScript) error {
 | 
			
		||||
	// 如果机器id不为公共脚本id,则校验机器是否存在
 | 
			
		||||
	if machineId := entity.MachineId; machineId != Common_Script_Machine_Id {
 | 
			
		||||
		biz.NotNil(m.machineRepo.GetById(machineId, "Name"), "该机器不存在")
 | 
			
		||||
	if machineId := ms.MachineId; machineId != Common_Script_Machine_Id {
 | 
			
		||||
		_, err := m.machineApp.GetById(new(entity.Machine), machineId, "Name")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return errorx.NewBiz("该机器不存在")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if entity.Id != 0 {
 | 
			
		||||
		gormx.UpdateById(entity)
 | 
			
		||||
	} else {
 | 
			
		||||
		gormx.Insert(entity)
 | 
			
		||||
	if ms.Id != 0 {
 | 
			
		||||
		return m.UpdateById(ms)
 | 
			
		||||
	}
 | 
			
		||||
	return m.Insert(ms)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id删除
 | 
			
		||||
func (m *machineScriptAppImpl) Delete(id uint64) {
 | 
			
		||||
	m.machineScriptRepo.Delete(id)
 | 
			
		||||
	m.DeleteById(id)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,21 +2,14 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type AuthCert interface {
 | 
			
		||||
	GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	base.Repo[*entity.AuthCert]
 | 
			
		||||
 | 
			
		||||
	Insert(ac *entity.AuthCert)
 | 
			
		||||
	GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	Update(ac *entity.AuthCert)
 | 
			
		||||
 | 
			
		||||
	GetById(id uint64) *entity.AuthCert
 | 
			
		||||
 | 
			
		||||
	GetByIds(ids ...uint64) []*entity.AuthCert
 | 
			
		||||
 | 
			
		||||
	GetByCondition(condition *entity.AuthCert, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	DeleteById(id uint64)
 | 
			
		||||
	// GetByIds(ids ...uint64) []*entity.AuthCert
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,22 +3,15 @@ package repository
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/api/vo"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Machine interface {
 | 
			
		||||
	base.Repo[*entity.Machine]
 | 
			
		||||
 | 
			
		||||
	// 分页获取机器信息列表
 | 
			
		||||
	GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) *model.PageResult[*[]*vo.MachineVO]
 | 
			
		||||
	GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) (*model.PageResult[*[]*vo.MachineVO], error)
 | 
			
		||||
 | 
			
		||||
	Count(condition *entity.MachineQuery) int64
 | 
			
		||||
 | 
			
		||||
	// 根据条件获取账号信息
 | 
			
		||||
	GetMachine(condition *entity.Machine, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.Machine
 | 
			
		||||
 | 
			
		||||
	Create(entity *entity.Machine)
 | 
			
		||||
 | 
			
		||||
	UpdateById(entity *entity.Machine)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,41 +2,28 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type MachineCronJob interface {
 | 
			
		||||
	GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	base.Repo[*entity.MachineCronJob]
 | 
			
		||||
 | 
			
		||||
	// 根据条件获取
 | 
			
		||||
	GetBy(condition *entity.MachineCronJob, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.MachineCronJob
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
 | 
			
		||||
	Insert(entity *entity.MachineCronJob)
 | 
			
		||||
 | 
			
		||||
	UpdateById(entity *entity.MachineCronJob)
 | 
			
		||||
	GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type MachineCronJobRelate interface {
 | 
			
		||||
	base.Repo[*entity.MachineCronJobRelate]
 | 
			
		||||
 | 
			
		||||
	GetList(condition *entity.MachineCronJobRelate) []entity.MachineCronJobRelate
 | 
			
		||||
 | 
			
		||||
	GetMachineIds(cronJobId uint64) []uint64
 | 
			
		||||
 | 
			
		||||
	GetCronJobIds(machineId uint64) []uint64
 | 
			
		||||
 | 
			
		||||
	Delete(condition *entity.MachineCronJobRelate)
 | 
			
		||||
 | 
			
		||||
	BatchInsert(mcjrs []*entity.MachineCronJobRelate)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type MachineCronJobExec interface {
 | 
			
		||||
	GetPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	base.Repo[*entity.MachineCronJobExec]
 | 
			
		||||
 | 
			
		||||
	Insert(mcje *entity.MachineCronJobExec)
 | 
			
		||||
 | 
			
		||||
	Delete(m *entity.MachineCronJobExec)
 | 
			
		||||
	GetPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ import (
 | 
			
		||||
 | 
			
		||||
type MachineFile interface {
 | 
			
		||||
	// 分页获取机器脚本信息列表
 | 
			
		||||
	GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	// 根据条件获取
 | 
			
		||||
	GetMachineFile(condition *entity.MachineFile, cols ...string) error
 | 
			
		||||
@@ -15,9 +15,9 @@ type MachineFile interface {
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.MachineFile
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
	Delete(id uint64) error
 | 
			
		||||
 | 
			
		||||
	Create(entity *entity.MachineFile)
 | 
			
		||||
	Create(entity *entity.MachineFile) error
 | 
			
		||||
 | 
			
		||||
	UpdateById(entity *entity.MachineFile)
 | 
			
		||||
	UpdateById(entity *entity.MachineFile) error
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,22 +2,13 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type MachineScript interface {
 | 
			
		||||
	base.Repo[*entity.MachineScript]
 | 
			
		||||
 | 
			
		||||
	// 分页获取机器脚本信息列表
 | 
			
		||||
	GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
 | 
			
		||||
	// 根据条件获取
 | 
			
		||||
	GetMachineScript(condition *entity.MachineScript, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.MachineScript
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
 | 
			
		||||
	Create(entity *entity.MachineScript)
 | 
			
		||||
 | 
			
		||||
	UpdateById(entity *entity.MachineScript)
 | 
			
		||||
	GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,11 @@
 | 
			
		||||
package machine
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"mayfly-go/internal/common/consts"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/cache"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/logx"
 | 
			
		||||
	"net"
 | 
			
		||||
	"time"
 | 
			
		||||
@@ -87,10 +86,10 @@ func (c *Cli) Close() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取sftp client
 | 
			
		||||
func (c *Cli) GetSftpCli() *sftp.Client {
 | 
			
		||||
func (c *Cli) GetSftpCli() (*sftp.Client, error) {
 | 
			
		||||
	if c.client == nil {
 | 
			
		||||
		if err := c.connect(); err != nil {
 | 
			
		||||
			panic(biz.NewBizErr("连接ssh失败:" + err.Error()))
 | 
			
		||||
			return nil, errorx.NewBiz("连接ssh失败: %s", err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	sftpclient := c.sftpClient
 | 
			
		||||
@@ -98,13 +97,13 @@ func (c *Cli) GetSftpCli() *sftp.Client {
 | 
			
		||||
	if sftpclient == nil {
 | 
			
		||||
		sc, serr := sftp.NewClient(c.client)
 | 
			
		||||
		if serr != nil {
 | 
			
		||||
			panic(biz.NewBizErr("获取sftp client失败:" + serr.Error()))
 | 
			
		||||
			return nil, errorx.NewBiz("获取sftp client失败: %s", serr.Error())
 | 
			
		||||
		}
 | 
			
		||||
		sftpclient = sc
 | 
			
		||||
		c.sftpClient = sftpclient
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sftpclient
 | 
			
		||||
	return sftpclient, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取session
 | 
			
		||||
@@ -172,15 +171,19 @@ func DeleteCli(id uint64) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 从缓存中获取客户端信息,不存在则回调获取机器信息函数,并新建
 | 
			
		||||
func GetCli(machineId uint64, getMachine func(uint64) *Info) (*Cli, error) {
 | 
			
		||||
func GetCli(machineId uint64, getMachine func(uint64) (*Info, error)) (*Cli, error) {
 | 
			
		||||
	if load, ok := cliCache.Get(machineId); ok {
 | 
			
		||||
		return load.(*Cli), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	me := getMachine(machineId)
 | 
			
		||||
	err := IfUseSshTunnelChangeIpPort(me, getMachine)
 | 
			
		||||
	me, err := getMachine(machineId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("ssh隧道连接失败: %s", err.Error())
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = IfUseSshTunnelChangeIpPort(me, getMachine)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errorx.NewBiz("ssh隧道连接失败: %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	c, err := newClient(me)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -194,7 +197,7 @@ func GetCli(machineId uint64, getMachine func(uint64) *Info) (*Cli, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 测试连接,使用传值的方式,而非引用。因为如果使用了ssh隧道,则ip和端口会变为本地映射地址与端口
 | 
			
		||||
func TestConn(me Info, getSshTunnelMachine func(uint64) *Info) error {
 | 
			
		||||
func TestConn(me Info, getSshTunnelMachine func(uint64) (*Info, error)) error {
 | 
			
		||||
	originId := me.Id
 | 
			
		||||
	if originId == 0 {
 | 
			
		||||
		// 随机设置一个ip,如果使用了隧道则用于临时保存隧道
 | 
			
		||||
@@ -202,7 +205,9 @@ func TestConn(me Info, getSshTunnelMachine func(uint64) *Info) error {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := IfUseSshTunnelChangeIpPort(&me, getSshTunnelMachine)
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "ssh隧道连接失败: %s")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("ssh隧道连接失败: %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	if me.UseSshTunnel() {
 | 
			
		||||
		defer CloseSshTunnelMachine(me.SshTunnelMachineId, me.Id)
 | 
			
		||||
	}
 | 
			
		||||
@@ -215,11 +220,11 @@ func TestConn(me Info, getSshTunnelMachine func(uint64) *Info) error {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 如果使用了ssh隧道,则修改机器ip port为暴露的ip port
 | 
			
		||||
func IfUseSshTunnelChangeIpPort(me *Info, getMachine func(uint64) *Info) error {
 | 
			
		||||
func IfUseSshTunnelChangeIpPort(me *Info, getMachine func(uint64) (*Info, error)) error {
 | 
			
		||||
	if !me.UseSshTunnel() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	sshTunnelMachine, err := GetSshTunnelMachine(me.SshTunnelMachineId, func(u uint64) *Info {
 | 
			
		||||
	sshTunnelMachine, err := GetSshTunnelMachine(me.SshTunnelMachineId, func(u uint64) (*Info, error) {
 | 
			
		||||
		return getMachine(u)
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -272,7 +277,7 @@ func GetSshClient(m *Info) (*ssh.Client, error) {
 | 
			
		||||
// 根据机器信息创建客户端对象
 | 
			
		||||
func newClient(machine *Info) (*Cli, error) {
 | 
			
		||||
	if machine == nil {
 | 
			
		||||
		return nil, errors.New("机器不存在")
 | 
			
		||||
		return nil, errorx.NewBiz("机器不存在")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	logx.Infof("[%s]机器连接:%s:%d", machine.Name, machine.Ip, machine.Port)
 | 
			
		||||
 
 | 
			
		||||
@@ -136,7 +136,7 @@ func (stm *SshTunnelMachine) Close() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取ssh隧道机器,方便统一管理充当ssh隧道的机器,避免创建多个ssh client
 | 
			
		||||
func GetSshTunnelMachine(machineId int, getMachine func(uint64) *Info) (*SshTunnelMachine, error) {
 | 
			
		||||
func GetSshTunnelMachine(machineId int, getMachine func(uint64) (*Info, error)) (*SshTunnelMachine, error) {
 | 
			
		||||
	sshTunnelMachine := sshTunnelMachines[machineId]
 | 
			
		||||
	if sshTunnelMachine != nil {
 | 
			
		||||
		return sshTunnelMachine, nil
 | 
			
		||||
@@ -145,7 +145,11 @@ func GetSshTunnelMachine(machineId int, getMachine func(uint64) *Info) (*SshTunn
 | 
			
		||||
	mutex.Lock()
 | 
			
		||||
	defer mutex.Unlock()
 | 
			
		||||
 | 
			
		||||
	me := getMachine(uint64(machineId))
 | 
			
		||||
	me, err := getMachine(uint64(machineId))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sshClient, err := GetSshClient(me)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
 
 | 
			
		||||
@@ -3,49 +3,26 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type authCertRepoImpl struct{}
 | 
			
		||||
 | 
			
		||||
func newAuthCertRepo() repository.AuthCert {
 | 
			
		||||
	return new(authCertRepoImpl)
 | 
			
		||||
type authCertRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.AuthCert]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *authCertRepoImpl) GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func newAuthCertRepo() repository.AuthCert {
 | 
			
		||||
	return &authCertRepoImpl{base.RepoImpl[*entity.AuthCert]{M: new(entity.AuthCert)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *authCertRepoImpl) GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(new(entity.AuthCert)).WithCondModel(condition).WithOrderBy(orderBy...)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *authCertRepoImpl) Insert(ac *entity.AuthCert) {
 | 
			
		||||
	biz.ErrIsNil(gormx.Insert(ac), "新增授权凭证失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *authCertRepoImpl) Update(ac *entity.AuthCert) {
 | 
			
		||||
	biz.ErrIsNil(gormx.UpdateById(ac), "更新授权凭证失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *authCertRepoImpl) GetById(id uint64) *entity.AuthCert {
 | 
			
		||||
	ac := new(entity.AuthCert)
 | 
			
		||||
	err := gormx.GetById(ac, id)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return ac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *authCertRepoImpl) GetByIds(ids ...uint64) []*entity.AuthCert {
 | 
			
		||||
	acs := new([]*entity.AuthCert)
 | 
			
		||||
	gormx.GetByIdIn(new(entity.AuthCert), acs, ids)
 | 
			
		||||
	return *acs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *authCertRepoImpl) GetByCondition(condition *entity.AuthCert, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *authCertRepoImpl) DeleteById(id uint64) {
 | 
			
		||||
	gormx.DeleteById(new(entity.AuthCert), id)
 | 
			
		||||
}
 | 
			
		||||
// func (m *authCertRepoImpl) GetByIds(ids ...uint64) []*entity.AuthCert {
 | 
			
		||||
// 	acs := new([]*entity.AuthCert)
 | 
			
		||||
// 	gormx.GetByIdIn(new(entity.AuthCert), acs, ids)
 | 
			
		||||
// 	return *acs
 | 
			
		||||
// }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import (
 | 
			
		||||
	"mayfly-go/internal/machine/api/vo"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
	"mayfly-go/pkg/utils/collx"
 | 
			
		||||
@@ -12,14 +12,16 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type machineRepoImpl struct{}
 | 
			
		||||
type machineRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.Machine]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newMachineRepo() repository.Machine {
 | 
			
		||||
	return new(machineRepoImpl)
 | 
			
		||||
	return &machineRepoImpl{base.RepoImpl[*entity.Machine]{M: new(entity.Machine)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取机器信息列表
 | 
			
		||||
func (m *machineRepoImpl) GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) *model.PageResult[*[]*vo.MachineVO] {
 | 
			
		||||
func (m *machineRepoImpl) GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) (*model.PageResult[*[]*vo.MachineVO], error) {
 | 
			
		||||
	qd := gormx.NewQuery(new(entity.Machine)).
 | 
			
		||||
		Like("ip", condition.Ip).
 | 
			
		||||
		Like("name", condition.Name).
 | 
			
		||||
@@ -44,28 +46,5 @@ func (m *machineRepoImpl) Count(condition *entity.MachineQuery) int64 {
 | 
			
		||||
		where["tag_id"] = condition.TagIds
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gormx.CountByCond(new(entity.Machine), where)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据条件获取账号信息
 | 
			
		||||
func (m *machineRepoImpl) GetMachine(condition *entity.Machine, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取
 | 
			
		||||
func (m *machineRepoImpl) GetById(id uint64, cols ...string) *entity.Machine {
 | 
			
		||||
	machine := new(entity.Machine)
 | 
			
		||||
	if err := gormx.GetById(machine, id, cols...); err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return machine
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineRepoImpl) Create(entity *entity.Machine) {
 | 
			
		||||
	biz.ErrIsNilAppendErr(gormx.Insert(entity), "创建机器信息失败: %s")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineRepoImpl) UpdateById(entity *entity.Machine) {
 | 
			
		||||
	biz.ErrIsNilAppendErr(gormx.UpdateById(entity), "更新机器信息失败: %s")
 | 
			
		||||
	return m.CountByCond(where)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,44 +3,21 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type machineCropJobRepoImpl struct{}
 | 
			
		||||
type machineCropJobRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.MachineCronJob]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newMachineCronJobRepo() repository.MachineCronJob {
 | 
			
		||||
	return new(machineCropJobRepoImpl)
 | 
			
		||||
	return &machineCropJobRepoImpl{base.RepoImpl[*entity.MachineCronJob]{M: new(entity.MachineCronJob)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取机器信息列表
 | 
			
		||||
func (m *machineCropJobRepoImpl) GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (m *machineCropJobRepoImpl) GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(condition).Like("name", condition.Name).Eq("status", condition.Status).WithOrderBy(orderBy...)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobRepoImpl) GetBy(cond *entity.MachineCronJob, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(cond, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobRepoImpl) GetById(id uint64, cols ...string) *entity.MachineCronJob {
 | 
			
		||||
	res := new(entity.MachineCronJob)
 | 
			
		||||
	if err := gormx.GetById(res, id, cols...); err == nil {
 | 
			
		||||
		return res
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobRepoImpl) Delete(id uint64) {
 | 
			
		||||
	biz.ErrIsNil(gormx.DeleteById(new(entity.MachineCronJob), id), "删除失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobRepoImpl) Insert(entity *entity.MachineCronJob) {
 | 
			
		||||
	gormx.Insert(entity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobRepoImpl) UpdateById(entity *entity.MachineCronJob) {
 | 
			
		||||
	gormx.UpdateById(entity)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,26 +3,21 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type machineCropJobExecRepoImpl struct{}
 | 
			
		||||
type machineCropJobExecRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.MachineCronJobExec]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newMachineCronJobExecRepo() repository.MachineCronJobExec {
 | 
			
		||||
	return new(machineCropJobExecRepoImpl)
 | 
			
		||||
	return &machineCropJobExecRepoImpl{base.RepoImpl[*entity.MachineCronJobExec]{M: new(entity.MachineCronJobExec)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取机器信息列表
 | 
			
		||||
func (m *machineCropJobExecRepoImpl) GetPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (m *machineCropJobExecRepoImpl) GetPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobExecRepoImpl) Insert(entity *entity.MachineCronJobExec) {
 | 
			
		||||
	gormx.Insert(entity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobExecRepoImpl) Delete(mcje *entity.MachineCronJobExec) {
 | 
			
		||||
	gormx.DeleteByCondition(mcje)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,24 +3,27 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type machineCropJobRelateRepoImpl struct{}
 | 
			
		||||
type machineCropJobRelateRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.MachineCronJobRelate]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newMachineCropJobRelateRepo() repository.MachineCronJobRelate {
 | 
			
		||||
	return new(machineCropJobRelateRepoImpl)
 | 
			
		||||
	return &machineCropJobRelateRepoImpl{base.RepoImpl[*entity.MachineCronJobRelate]{M: new(entity.MachineCronJobRelate)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobRelateRepoImpl) GetList(condition *entity.MachineCronJobRelate) []entity.MachineCronJobRelate {
 | 
			
		||||
	list := new([]entity.MachineCronJobRelate)
 | 
			
		||||
	gormx.ListByOrder(condition, list)
 | 
			
		||||
	m.ListByCond(condition, list)
 | 
			
		||||
	return *list
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobRelateRepoImpl) GetMachineIds(cronJobId uint64) []uint64 {
 | 
			
		||||
	var machineIds []uint64
 | 
			
		||||
	gormx.ListBy(&entity.MachineCronJobRelate{CronJobId: cronJobId}, &machineIds, "machine_id")
 | 
			
		||||
	m.ListByCond(&entity.MachineCronJobRelate{CronJobId: cronJobId}, &machineIds, "machine_id")
 | 
			
		||||
	return machineIds
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -29,11 +32,3 @@ func (m *machineCropJobRelateRepoImpl) GetCronJobIds(machineId uint64) []uint64
 | 
			
		||||
	gormx.ListBy(&entity.MachineCronJobRelate{MachineId: machineId}, &cronJobIds, "cron_job_id")
 | 
			
		||||
	return cronJobIds
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobRelateRepoImpl) Delete(condition *entity.MachineCronJobRelate) {
 | 
			
		||||
	gormx.DeleteByCondition(condition)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineCropJobRelateRepoImpl) BatchInsert(mcjrs []*entity.MachineCronJobRelate) {
 | 
			
		||||
	gormx.BatchInsert(mcjrs)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
@@ -15,7 +14,7 @@ func newMachineFileRepo() repository.MachineFile {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取机器文件信息列表
 | 
			
		||||
func (m *machineFileRepoImpl) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (m *machineFileRepoImpl) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
@@ -35,14 +34,14 @@ func (m *machineFileRepoImpl) GetById(id uint64, cols ...string) *entity.Machine
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取
 | 
			
		||||
func (m *machineFileRepoImpl) Delete(id uint64) {
 | 
			
		||||
	biz.ErrIsNil(gormx.DeleteById(new(entity.MachineFile), id), "删除失败")
 | 
			
		||||
func (m *machineFileRepoImpl) Delete(id uint64) error {
 | 
			
		||||
	return gormx.DeleteById(new(entity.MachineFile), id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineFileRepoImpl) Create(entity *entity.MachineFile) {
 | 
			
		||||
	biz.ErrIsNil(gormx.Insert(entity), "新增机器文件配置失败")
 | 
			
		||||
func (m *machineFileRepoImpl) Create(entity *entity.MachineFile) error {
 | 
			
		||||
	return gormx.Insert(entity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineFileRepoImpl) UpdateById(entity *entity.MachineFile) {
 | 
			
		||||
	biz.ErrIsNil(gormx.UpdateById(entity), "更新机器文件失败")
 | 
			
		||||
func (m *machineFileRepoImpl) UpdateById(entity *entity.MachineFile) error {
 | 
			
		||||
	return gormx.UpdateById(entity)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,47 +3,21 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/machine/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/machine/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type machineScriptRepoImpl struct{}
 | 
			
		||||
type machineScriptRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.MachineScript]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newMachineScriptRepo() repository.MachineScript {
 | 
			
		||||
	return new(machineScriptRepoImpl)
 | 
			
		||||
	return &machineScriptRepoImpl{base.RepoImpl[*entity.MachineScript]{M: new(entity.MachineScript)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取机器信息列表
 | 
			
		||||
func (m *machineScriptRepoImpl) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (m *machineScriptRepoImpl) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据条件获取账号信息
 | 
			
		||||
func (m *machineScriptRepoImpl) GetMachineScript(condition *entity.MachineScript, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取
 | 
			
		||||
func (m *machineScriptRepoImpl) GetById(id uint64, cols ...string) *entity.MachineScript {
 | 
			
		||||
	ms := new(entity.MachineScript)
 | 
			
		||||
	if err := gormx.GetById(ms, id, cols...); err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return ms
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取
 | 
			
		||||
func (m *machineScriptRepoImpl) Delete(id uint64) {
 | 
			
		||||
	biz.ErrIsNil(gormx.DeleteById(new(entity.MachineScript), id), "删除失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineScriptRepoImpl) Create(entity *entity.MachineScript) {
 | 
			
		||||
	gormx.Insert(entity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *machineScriptRepoImpl) UpdateById(entity *entity.MachineScript) {
 | 
			
		||||
	gormx.UpdateById(entity)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,9 @@ func (m *Mongo) Mongos(rc *req.Ctx) {
 | 
			
		||||
	}
 | 
			
		||||
	queryCond.TagIds = tagIds
 | 
			
		||||
 | 
			
		||||
	rc.ResData = m.MongoApp.GetPageList(queryCond, page, new([]entity.Mongo))
 | 
			
		||||
	res, err := m.MongoApp.GetPageList(queryCond, page, new([]entity.Mongo))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Mongo) MongoTags(rc *req.Ctx) {
 | 
			
		||||
@@ -56,7 +58,7 @@ func (m *Mongo) Save(rc *req.Ctx) {
 | 
			
		||||
	rc.ReqParam = form
 | 
			
		||||
 | 
			
		||||
	mongo.SetBaseInfo(rc.LoginAccount)
 | 
			
		||||
	m.MongoApp.Save(mongo)
 | 
			
		||||
	biz.ErrIsNil(m.MongoApp.Save(mongo))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Mongo) DeleteMongo(rc *req.Ctx) {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ import (
 | 
			
		||||
	"mayfly-go/internal/machine/infrastructure/machine"
 | 
			
		||||
	"mayfly-go/internal/mongo/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/mongo/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/cache"
 | 
			
		||||
	"mayfly-go/pkg/logx"
 | 
			
		||||
@@ -23,21 +24,17 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Mongo interface {
 | 
			
		||||
	base.App[*entity.Mongo]
 | 
			
		||||
 | 
			
		||||
	// 分页获取机器脚本信息列表
 | 
			
		||||
	GetPageList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	Count(condition *entity.MongoQuery) int64
 | 
			
		||||
 | 
			
		||||
	// 根据条件获取
 | 
			
		||||
	GetBy(condition *entity.Mongo, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.Mongo
 | 
			
		||||
 | 
			
		||||
	Save(entity *entity.Mongo)
 | 
			
		||||
	Save(entity *entity.Mongo) error
 | 
			
		||||
 | 
			
		||||
	// 删除数据库信息
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
	Delete(id uint64) error
 | 
			
		||||
 | 
			
		||||
	// 获取mongo连接实例
 | 
			
		||||
	// @param id mongo id
 | 
			
		||||
@@ -46,53 +43,45 @@ type Mongo interface {
 | 
			
		||||
 | 
			
		||||
func newMongoAppImpl(mongoRepo repository.Mongo) Mongo {
 | 
			
		||||
	return &mongoAppImpl{
 | 
			
		||||
		mongoRepo: mongoRepo,
 | 
			
		||||
		base.AppImpl[*entity.Mongo, repository.Mongo]{Repo: mongoRepo},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type mongoAppImpl struct {
 | 
			
		||||
	mongoRepo repository.Mongo
 | 
			
		||||
	base.AppImpl[*entity.Mongo, repository.Mongo]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取数据库信息列表
 | 
			
		||||
func (d *mongoAppImpl) GetPageList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
	return d.mongoRepo.GetList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
func (d *mongoAppImpl) GetPageList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return d.GetRepo().GetList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *mongoAppImpl) Count(condition *entity.MongoQuery) int64 {
 | 
			
		||||
	return d.mongoRepo.Count(condition)
 | 
			
		||||
	return d.GetRepo().Count(condition)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据条件获取
 | 
			
		||||
func (d *mongoAppImpl) GetBy(condition *entity.Mongo, cols ...string) error {
 | 
			
		||||
	return d.mongoRepo.Get(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取
 | 
			
		||||
func (d *mongoAppImpl) GetById(id uint64, cols ...string) *entity.Mongo {
 | 
			
		||||
	return d.mongoRepo.GetById(id, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *mongoAppImpl) Delete(id uint64) {
 | 
			
		||||
	d.mongoRepo.Delete(id)
 | 
			
		||||
func (d *mongoAppImpl) Delete(id uint64) error {
 | 
			
		||||
	DeleteMongoCache(id)
 | 
			
		||||
	return d.GetRepo().DeleteById(id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *mongoAppImpl) Save(m *entity.Mongo) {
 | 
			
		||||
func (d *mongoAppImpl) Save(m *entity.Mongo) error {
 | 
			
		||||
	if m.Id == 0 {
 | 
			
		||||
		d.mongoRepo.Insert(m)
 | 
			
		||||
	} else {
 | 
			
		||||
		// 先关闭连接
 | 
			
		||||
		DeleteMongoCache(m.Id)
 | 
			
		||||
		d.mongoRepo.Update(m)
 | 
			
		||||
		return d.GetRepo().Insert(m)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 先关闭连接
 | 
			
		||||
	DeleteMongoCache(m.Id)
 | 
			
		||||
	return d.GetRepo().UpdateById(m)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *mongoAppImpl) GetMongoInst(id uint64) *MongoInstance {
 | 
			
		||||
	mongoInstance, err := GetMongoInstance(id, func(u uint64) *entity.Mongo {
 | 
			
		||||
		mongo := d.GetById(u)
 | 
			
		||||
		biz.NotNil(mongo, "mongo信息不存在")
 | 
			
		||||
		return mongo
 | 
			
		||||
	mongoInstance, err := GetMongoInstance(id, func(u uint64) (*entity.Mongo, error) {
 | 
			
		||||
		mongo, err := d.GetById(new(entity.Mongo), u)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return mongo, nil
 | 
			
		||||
	})
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "连接mongo失败: %s")
 | 
			
		||||
	return mongoInstance
 | 
			
		||||
@@ -122,9 +111,14 @@ func init() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取mongo的连接实例
 | 
			
		||||
func GetMongoInstance(mongoId uint64, getMongoEntity func(uint64) *entity.Mongo) (*MongoInstance, error) {
 | 
			
		||||
func GetMongoInstance(mongoId uint64, getMongoEntity func(uint64) (*entity.Mongo, error)) (*MongoInstance, error) {
 | 
			
		||||
	mi, err := mongoCliCache.ComputeIfAbsent(mongoId, func(_ any) (any, error) {
 | 
			
		||||
		c, err := connect(getMongoEntity(mongoId))
 | 
			
		||||
		mongoEntity, err := getMongoEntity(mongoId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		c, err := connect(mongoEntity)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
@@ -211,7 +205,11 @@ 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 {
 | 
			
		||||
	stm, err := machineapp.GetMachineApp().GetSshTunnelMachine(sd.machineId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if sshConn, err := stm.GetDialConn(network, address); err == nil {
 | 
			
		||||
		// 将ssh conn包装,否则内部部设置超时会报错,ssh conn不支持设置超时会返回错误: ssh: tcpChan: deadline not supported
 | 
			
		||||
		return &netx.WrapSshConn{Conn: sshConn}, nil
 | 
			
		||||
	} else {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,24 +2,15 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/mongo/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Mongo interface {
 | 
			
		||||
	base.Repo[*entity.Mongo]
 | 
			
		||||
 | 
			
		||||
	// 分页获取列表
 | 
			
		||||
	GetList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	Count(condition *entity.MongoQuery) int64
 | 
			
		||||
 | 
			
		||||
	// 根据条件获取
 | 
			
		||||
	Get(condition *entity.Mongo, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.Mongo
 | 
			
		||||
 | 
			
		||||
	Insert(db *entity.Mongo)
 | 
			
		||||
 | 
			
		||||
	Update(db *entity.Mongo)
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,19 +3,21 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/mongo/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/mongo/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type mongoRepoImpl struct{}
 | 
			
		||||
type mongoRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.Mongo]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newMongoRepo() repository.Mongo {
 | 
			
		||||
	return new(mongoRepoImpl)
 | 
			
		||||
	return &mongoRepoImpl{base.RepoImpl[*entity.Mongo]{M: new(entity.Mongo)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取数据库信息列表
 | 
			
		||||
func (d *mongoRepoImpl) GetList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (d *mongoRepoImpl) GetList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(new(entity.Mongo)).
 | 
			
		||||
		Like("name", condition.Name).
 | 
			
		||||
		In("tag_id", condition.TagIds).
 | 
			
		||||
@@ -31,30 +33,3 @@ func (d *mongoRepoImpl) Count(condition *entity.MongoQuery) int64 {
 | 
			
		||||
	}
 | 
			
		||||
	return gormx.CountByCond(new(entity.Mongo), where)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据条件获取
 | 
			
		||||
func (d *mongoRepoImpl) Get(condition *entity.Mongo, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取
 | 
			
		||||
func (d *mongoRepoImpl) GetById(id uint64, cols ...string) *entity.Mongo {
 | 
			
		||||
	db := new(entity.Mongo)
 | 
			
		||||
	if err := gormx.GetById(db, id, cols...); err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return db
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *mongoRepoImpl) Insert(db *entity.Mongo) {
 | 
			
		||||
	biz.ErrIsNil(gormx.Insert(db), "新增mongo信息失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *mongoRepoImpl) Update(db *entity.Mongo) {
 | 
			
		||||
	biz.ErrIsNil(gormx.UpdateById(db), "更新mongo信息失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *mongoRepoImpl) Delete(id uint64) {
 | 
			
		||||
	gormx.DeleteById(new(entity.Mongo), id)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package api
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/msg/application"
 | 
			
		||||
	"mayfly-go/internal/msg/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/ginx"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
)
 | 
			
		||||
@@ -16,5 +17,7 @@ func (m *Msg) GetMsgs(rc *req.Ctx) {
 | 
			
		||||
	condition := &entity.Msg{
 | 
			
		||||
		RecipientId: int64(rc.LoginAccount.Id),
 | 
			
		||||
	}
 | 
			
		||||
	rc.ResData = m.MsgApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]entity.Msg))
 | 
			
		||||
	res, err := m.MsgApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]entity.Msg))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Msg interface {
 | 
			
		||||
	GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	Create(msg *entity.Msg)
 | 
			
		||||
 | 
			
		||||
@@ -28,7 +28,7 @@ type msgAppImpl struct {
 | 
			
		||||
	msgRepo repository.Msg
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *msgAppImpl) GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (a *msgAppImpl) GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return a.msgRepo.GetPageList(condition, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,12 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/msg/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Msg interface {
 | 
			
		||||
	GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	base.Repo[*entity.Msg]
 | 
			
		||||
 | 
			
		||||
	Insert(msg *entity.Msg)
 | 
			
		||||
	GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,22 +3,20 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/msg/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/msg/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type msgRepoImpl struct{}
 | 
			
		||||
 | 
			
		||||
func newMsgRepo() repository.Msg {
 | 
			
		||||
	return new(msgRepoImpl)
 | 
			
		||||
type msgRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.Msg]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *msgRepoImpl) GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func newMsgRepo() repository.Msg {
 | 
			
		||||
	return &msgRepoImpl{base.RepoImpl[*entity.Msg]{M: new(entity.Msg)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *msgRepoImpl) GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *msgRepoImpl) Insert(account *entity.Msg) {
 | 
			
		||||
	biz.ErrIsNil(gormx.Insert(account), "新增消息记录失败")
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,8 @@ func (r *Redis) ScanKeys(rc *req.Ctx) {
 | 
			
		||||
		redisAddr := ri.Cli.Options().Addr
 | 
			
		||||
		cursorRes[redisAddr] = form.Cursor[redisAddr]
 | 
			
		||||
		for {
 | 
			
		||||
			ks, cursor := ri.Scan(cursorRes[redisAddr], form.Match, form.Count)
 | 
			
		||||
			ks, cursor, err := ri.Scan(cursorRes[redisAddr], form.Match, form.Count)
 | 
			
		||||
			biz.ErrIsNil(err)
 | 
			
		||||
			cursorRes[redisAddr] = cursor
 | 
			
		||||
			if len(ks) > 0 {
 | 
			
		||||
				// 返回了数据则追加总集合中
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,9 @@ func (r *Redis) RedisList(rc *req.Ctx) {
 | 
			
		||||
	}
 | 
			
		||||
	queryCond.TagIds = tagIds
 | 
			
		||||
 | 
			
		||||
	rc.ResData = r.RedisApp.GetPageList(queryCond, page, new([]vo.Redis))
 | 
			
		||||
	res, err := r.RedisApp.GetPageList(queryCond, page, new([]vo.Redis))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Redis) RedisTags(rc *req.Ctx) {
 | 
			
		||||
@@ -58,13 +60,14 @@ func (r *Redis) Save(rc *req.Ctx) {
 | 
			
		||||
	rc.ReqParam = form
 | 
			
		||||
 | 
			
		||||
	redis.SetBaseInfo(rc.LoginAccount)
 | 
			
		||||
	r.RedisApp.Save(redis)
 | 
			
		||||
	biz.ErrIsNil(r.RedisApp.Save(redis))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取redis实例密码,由于数据库是加密存储,故提供该接口展示原文密码
 | 
			
		||||
func (r *Redis) GetRedisPwd(rc *req.Ctx) {
 | 
			
		||||
	rid := uint64(ginx.PathParamInt(rc.GinCtx, "id"))
 | 
			
		||||
	re := r.RedisApp.GetById(rid, "Password")
 | 
			
		||||
	re, err := r.RedisApp.GetById(new(entity.Redis), rid, "Password")
 | 
			
		||||
	biz.ErrIsNil(err, "redis信息不存在")
 | 
			
		||||
	re.PwdDecrypt()
 | 
			
		||||
	rc.ResData = re.Password
 | 
			
		||||
}
 | 
			
		||||
@@ -83,7 +86,8 @@ func (r *Redis) DeleteRedis(rc *req.Ctx) {
 | 
			
		||||
 | 
			
		||||
func (r *Redis) RedisInfo(rc *req.Ctx) {
 | 
			
		||||
	g := rc.GinCtx
 | 
			
		||||
	ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), 0)
 | 
			
		||||
	ri, err := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), 0)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
 | 
			
		||||
	section := rc.GinCtx.Query("section")
 | 
			
		||||
	mode := ri.Info.Mode
 | 
			
		||||
@@ -116,7 +120,6 @@ func (r *Redis) RedisInfo(rc *req.Ctx) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res string
 | 
			
		||||
	var err error
 | 
			
		||||
	if section == "" {
 | 
			
		||||
		res, err = redisCli.Info(ctx).Result()
 | 
			
		||||
	} else {
 | 
			
		||||
@@ -161,7 +164,8 @@ func (r *Redis) RedisInfo(rc *req.Ctx) {
 | 
			
		||||
 | 
			
		||||
func (r *Redis) ClusterInfo(rc *req.Ctx) {
 | 
			
		||||
	g := rc.GinCtx
 | 
			
		||||
	ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), 0)
 | 
			
		||||
	ri, err := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), 0)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	biz.IsEquals(ri.Info.Mode, entity.RedisModeCluster, "非集群模式")
 | 
			
		||||
	info, _ := ri.ClusterCli.ClusterInfo(context.Background()).Result()
 | 
			
		||||
	nodesStr, _ := ri.ClusterCli.ClusterNodes(context.Background()).Result()
 | 
			
		||||
@@ -211,7 +215,8 @@ func (r *Redis) checkKeyAndGetRedisIns(rc *req.Ctx) (*application.RedisInstance,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Redis) getRedisIns(rc *req.Ctx) *application.RedisInstance {
 | 
			
		||||
	ri := r.RedisApp.GetRedisInstance(getIdAndDbNum(rc.GinCtx))
 | 
			
		||||
	ri, err := r.RedisApp.GetRedisInstance(getIdAndDbNum(rc.GinCtx))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	biz.ErrIsNilAppendErr(r.TagApp.CanAccess(rc.LoginAccount.Id, ri.Info.TagPath), "%s")
 | 
			
		||||
	return ri
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,9 @@ import (
 | 
			
		||||
	"mayfly-go/internal/machine/infrastructure/machine"
 | 
			
		||||
	"mayfly-go/internal/redis/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/redis/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/cache"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/logx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
	"mayfly-go/pkg/utils/netx"
 | 
			
		||||
@@ -23,61 +24,49 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Redis interface {
 | 
			
		||||
	base.App[*entity.Redis]
 | 
			
		||||
 | 
			
		||||
	// 分页获取机器脚本信息列表
 | 
			
		||||
	GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	Count(condition *entity.RedisQuery) int64
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.Redis
 | 
			
		||||
 | 
			
		||||
	// 根据条件获取
 | 
			
		||||
	GetRedisBy(condition *entity.Redis, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	Save(entity *entity.Redis)
 | 
			
		||||
	Save(entity *entity.Redis) error
 | 
			
		||||
 | 
			
		||||
	// 删除数据库信息
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
	Delete(id uint64) error
 | 
			
		||||
 | 
			
		||||
	// 获取数据库连接实例
 | 
			
		||||
	// id: 数据库实例id
 | 
			
		||||
	// db: 库号
 | 
			
		||||
	GetRedisInstance(id uint64, db int) *RedisInstance
 | 
			
		||||
	GetRedisInstance(id uint64, db int) (*RedisInstance, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newRedisApp(redisRepo repository.Redis) Redis {
 | 
			
		||||
	return &redisAppImpl{
 | 
			
		||||
		redisRepo: redisRepo,
 | 
			
		||||
		base.AppImpl[*entity.Redis, repository.Redis]{Repo: redisRepo},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type redisAppImpl struct {
 | 
			
		||||
	redisRepo repository.Redis
 | 
			
		||||
	base.AppImpl[*entity.Redis, repository.Redis]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取机器脚本信息列表
 | 
			
		||||
func (r *redisAppImpl) GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
	return r.redisRepo.GetRedisList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
func (r *redisAppImpl) GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return r.GetRepo().GetRedisList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *redisAppImpl) Count(condition *entity.RedisQuery) int64 {
 | 
			
		||||
	return r.redisRepo.Count(condition)
 | 
			
		||||
	return r.GetRepo().Count(condition)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取
 | 
			
		||||
func (r *redisAppImpl) GetById(id uint64, cols ...string) *entity.Redis {
 | 
			
		||||
	return r.redisRepo.GetById(id, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据条件获取
 | 
			
		||||
func (r *redisAppImpl) GetRedisBy(condition *entity.Redis, cols ...string) error {
 | 
			
		||||
	return r.redisRepo.GetRedis(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *redisAppImpl) Save(re *entity.Redis) {
 | 
			
		||||
func (r *redisAppImpl) Save(re *entity.Redis) error {
 | 
			
		||||
	// ’修改信息且密码不为空‘ or ‘新增’需要测试是否可连接
 | 
			
		||||
	if (re.Id != 0 && re.Password != "") || re.Id == 0 {
 | 
			
		||||
		TestRedisConnection(re)
 | 
			
		||||
		if err := TestRedisConnection(re); err != nil {
 | 
			
		||||
			return errorx.NewBiz("Redis连接失败: %s", err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 查找是否存在该库
 | 
			
		||||
@@ -85,55 +74,61 @@ func (r *redisAppImpl) Save(re *entity.Redis) {
 | 
			
		||||
	if re.SshTunnelMachineId > 0 {
 | 
			
		||||
		oldRedis.SshTunnelMachineId = re.SshTunnelMachineId
 | 
			
		||||
	}
 | 
			
		||||
	err := r.GetRedisBy(oldRedis)
 | 
			
		||||
	err := r.GetBy(oldRedis)
 | 
			
		||||
 | 
			
		||||
	if re.Id == 0 {
 | 
			
		||||
		biz.IsTrue(err != nil, "该实例已存在")
 | 
			
		||||
		re.PwdEncrypt()
 | 
			
		||||
		r.redisRepo.Insert(re)
 | 
			
		||||
	} else {
 | 
			
		||||
		// 如果存在该库,则校验修改的库是否为该库
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			biz.IsTrue(oldRedis.Id == re.Id, "该实例已存在")
 | 
			
		||||
		}
 | 
			
		||||
		// 如果修改了redis实例的库信息,则关闭旧库的连接
 | 
			
		||||
		if oldRedis.Db != re.Db || oldRedis.SshTunnelMachineId != re.SshTunnelMachineId {
 | 
			
		||||
			for _, dbStr := range strings.Split(oldRedis.Db, ",") {
 | 
			
		||||
				db, _ := strconv.Atoi(dbStr)
 | 
			
		||||
				CloseRedis(re.Id, db)
 | 
			
		||||
			}
 | 
			
		||||
			return errorx.NewBiz("该实例已存在")
 | 
			
		||||
		}
 | 
			
		||||
		re.PwdEncrypt()
 | 
			
		||||
		r.redisRepo.Update(re)
 | 
			
		||||
		return r.Insert(re)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 如果存在该库,则校验修改的库是否为该库
 | 
			
		||||
	if err == nil && oldRedis.Id != re.Id {
 | 
			
		||||
		return errorx.NewBiz("该实例已存在")
 | 
			
		||||
	}
 | 
			
		||||
	// 如果修改了redis实例的库信息,则关闭旧库的连接
 | 
			
		||||
	if oldRedis.Db != re.Db || oldRedis.SshTunnelMachineId != re.SshTunnelMachineId {
 | 
			
		||||
		for _, dbStr := range strings.Split(oldRedis.Db, ",") {
 | 
			
		||||
			db, _ := strconv.Atoi(dbStr)
 | 
			
		||||
			CloseRedis(re.Id, db)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	re.PwdEncrypt()
 | 
			
		||||
	return r.UpdateById(re)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 删除Redis信息
 | 
			
		||||
func (r *redisAppImpl) Delete(id uint64) {
 | 
			
		||||
	re := r.GetById(id)
 | 
			
		||||
	biz.NotNil(re, "该redis信息不存在")
 | 
			
		||||
func (r *redisAppImpl) Delete(id uint64) error {
 | 
			
		||||
	re, err := r.GetById(new(entity.Redis), id)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errorx.NewBiz("该redis信息不存在")
 | 
			
		||||
	}
 | 
			
		||||
	// 如果存在连接,则关闭所有库连接信息
 | 
			
		||||
	for _, dbStr := range strings.Split(re.Db, ",") {
 | 
			
		||||
		db, _ := strconv.Atoi(dbStr)
 | 
			
		||||
		CloseRedis(re.Id, db)
 | 
			
		||||
	}
 | 
			
		||||
	r.redisRepo.Delete(id)
 | 
			
		||||
	return r.DeleteById(id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取数据库连接实例
 | 
			
		||||
func (r *redisAppImpl) GetRedisInstance(id uint64, db int) *RedisInstance {
 | 
			
		||||
func (r *redisAppImpl) GetRedisInstance(id uint64, db int) (*RedisInstance, error) {
 | 
			
		||||
	// Id不为0,则为需要缓存
 | 
			
		||||
	needCache := id != 0
 | 
			
		||||
	if needCache {
 | 
			
		||||
		load, ok := redisCache.Get(getRedisCacheKey(id, db))
 | 
			
		||||
		if ok {
 | 
			
		||||
			return load.(*RedisInstance)
 | 
			
		||||
			return load.(*RedisInstance), nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// 缓存不存在,则回调获取redis信息
 | 
			
		||||
	re := r.GetById(id)
 | 
			
		||||
	re, err := r.GetById(new(entity.Redis), id)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errorx.NewBiz("redis信息不存在")
 | 
			
		||||
	}
 | 
			
		||||
	re.PwdDecrypt()
 | 
			
		||||
	biz.NotNil(re, "redis信息不存在")
 | 
			
		||||
 | 
			
		||||
	redisMode := re.Mode
 | 
			
		||||
	var ri *RedisInstance
 | 
			
		||||
@@ -143,7 +138,7 @@ func (r *redisAppImpl) GetRedisInstance(id uint64, db int) *RedisInstance {
 | 
			
		||||
		_, e := ri.Cli.Ping(context.Background()).Result()
 | 
			
		||||
		if e != nil {
 | 
			
		||||
			ri.Close()
 | 
			
		||||
			panic(biz.NewBizErr(fmt.Sprintf("redis连接失败: %s", e.Error())))
 | 
			
		||||
			return nil, errorx.NewBiz("redis连接失败: %s", e.Error())
 | 
			
		||||
		}
 | 
			
		||||
	} else if redisMode == entity.RedisModeCluster {
 | 
			
		||||
		ri = getRedisClusterClient(re)
 | 
			
		||||
@@ -151,7 +146,7 @@ func (r *redisAppImpl) GetRedisInstance(id uint64, db int) *RedisInstance {
 | 
			
		||||
		_, e := ri.ClusterCli.Ping(context.Background()).Result()
 | 
			
		||||
		if e != nil {
 | 
			
		||||
			ri.Close()
 | 
			
		||||
			panic(biz.NewBizErr(fmt.Sprintf("redis集群连接失败: %s", e.Error())))
 | 
			
		||||
			return nil, errorx.NewBiz("redis集群连接失败: %s", e.Error())
 | 
			
		||||
		}
 | 
			
		||||
	} else if redisMode == entity.RedisModeSentinel {
 | 
			
		||||
		ri = getRedisSentinelCient(re, db)
 | 
			
		||||
@@ -159,7 +154,7 @@ func (r *redisAppImpl) GetRedisInstance(id uint64, db int) *RedisInstance {
 | 
			
		||||
		_, e := ri.Cli.Ping(context.Background()).Result()
 | 
			
		||||
		if e != nil {
 | 
			
		||||
			ri.Close()
 | 
			
		||||
			panic(biz.NewBizErr(fmt.Sprintf("redis sentinel连接失败: %s", e.Error())))
 | 
			
		||||
			return nil, errorx.NewBiz("redis sentinel连接失败: %s", e.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -167,7 +162,7 @@ func (r *redisAppImpl) GetRedisInstance(id uint64, db int) *RedisInstance {
 | 
			
		||||
	if needCache {
 | 
			
		||||
		redisCache.Put(getRedisCacheKey(id, db), ri)
 | 
			
		||||
	}
 | 
			
		||||
	return ri
 | 
			
		||||
	return ri, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 生成redis连接缓存key
 | 
			
		||||
@@ -240,8 +235,12 @@ func getRedisSentinelCient(re *entity.Redis, db int) *RedisInstance {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getRedisDialer(machineId int) func(ctx context.Context, network, addr string) (net.Conn, error) {
 | 
			
		||||
	sshTunnel := machineapp.GetMachineApp().GetSshTunnelMachine(machineId)
 | 
			
		||||
	return func(_ context.Context, network, addr string) (net.Conn, error) {
 | 
			
		||||
		sshTunnel, err := machineapp.GetMachineApp().GetSshTunnelMachine(machineId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if sshConn, err := sshTunnel.GetDialConn(network, addr); err == nil {
 | 
			
		||||
			// 将ssh conn包装,否则redis内部设置超时会报错,ssh conn不支持设置超时会返回错误: ssh: tcpChan: deadline not supported
 | 
			
		||||
			return &netx.WrapSshConn{Conn: sshConn}, nil
 | 
			
		||||
@@ -279,7 +278,7 @@ func init() {
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestRedisConnection(re *entity.Redis) {
 | 
			
		||||
func TestRedisConnection(re *entity.Redis) error {
 | 
			
		||||
	var cmd redis.Cmdable
 | 
			
		||||
	// 取第一个库测试连接即可
 | 
			
		||||
	dbStr := strings.Split(re.Db, ",")[0]
 | 
			
		||||
@@ -300,7 +299,7 @@ func TestRedisConnection(re *entity.Redis) {
 | 
			
		||||
 | 
			
		||||
	// 测试连接
 | 
			
		||||
	_, e := cmd.Ping(context.Background()).Result()
 | 
			
		||||
	biz.ErrIsNilAppendErr(e, "Redis连接失败: %s")
 | 
			
		||||
	return e
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type RedisInfo struct {
 | 
			
		||||
@@ -340,10 +339,8 @@ func (r *RedisInstance) GetCmdable() redis.Cmdable {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *RedisInstance) Scan(cursor uint64, match string, count int64) ([]string, uint64) {
 | 
			
		||||
	keys, newcursor, err := r.GetCmdable().Scan(context.Background(), cursor, match, count).Result()
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "scan失败: %s")
 | 
			
		||||
	return keys, newcursor
 | 
			
		||||
func (r *RedisInstance) Scan(cursor uint64, match string, count int64) ([]string, uint64, error) {
 | 
			
		||||
	return r.GetCmdable().Scan(context.Background(), cursor, match, count).Result()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *RedisInstance) Close() {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,23 +2,15 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/redis/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Redis interface {
 | 
			
		||||
	base.Repo[*entity.Redis]
 | 
			
		||||
 | 
			
		||||
	// 分页获取机器信息列表
 | 
			
		||||
	GetRedisList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetRedisList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	Count(condition *entity.RedisQuery) int64
 | 
			
		||||
 | 
			
		||||
	// 根据id获取
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.Redis
 | 
			
		||||
 | 
			
		||||
	GetRedis(condition *entity.Redis, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	Insert(redis *entity.Redis)
 | 
			
		||||
 | 
			
		||||
	Update(redis *entity.Redis)
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,19 +3,21 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/redis/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/redis/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type redisRepoImpl struct{}
 | 
			
		||||
type redisRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.Redis]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newRedisRepo() repository.Redis {
 | 
			
		||||
	return new(redisRepoImpl)
 | 
			
		||||
	return &redisRepoImpl{base.RepoImpl[*entity.Redis]{M: new(entity.Redis)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 分页获取机器信息列表
 | 
			
		||||
func (r *redisRepoImpl) GetRedisList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (r *redisRepoImpl) GetRedisList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(new(entity.Redis)).
 | 
			
		||||
		Like("host", condition.Host).
 | 
			
		||||
		In("tag_id", condition.TagIds).
 | 
			
		||||
@@ -32,28 +34,3 @@ func (r *redisRepoImpl) Count(condition *entity.RedisQuery) int64 {
 | 
			
		||||
 | 
			
		||||
	return gormx.CountByCond(new(entity.Redis), where)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据id获取
 | 
			
		||||
func (r *redisRepoImpl) GetById(id uint64, cols ...string) *entity.Redis {
 | 
			
		||||
	rd := new(entity.Redis)
 | 
			
		||||
	if err := gormx.GetById(rd, id, cols...); err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return rd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *redisRepoImpl) GetRedis(condition *entity.Redis, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *redisRepoImpl) Insert(redis *entity.Redis) {
 | 
			
		||||
	biz.ErrIsNilAppendErr(gormx.Insert(redis), "新增失败: %s")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *redisRepoImpl) Update(redis *entity.Redis) {
 | 
			
		||||
	biz.ErrIsNilAppendErr(gormx.UpdateById(redis), "更新失败: %s")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *redisRepoImpl) Delete(id uint64) {
 | 
			
		||||
	biz.ErrIsNilAppendErr(gormx.DeleteById(new(entity.Redis), id), "删除失败: %s")
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ func (a *Account) GetPermissions(rc *req.Ctx) {
 | 
			
		||||
 | 
			
		||||
	var resources vo.AccountResourceVOList
 | 
			
		||||
	// 获取账号菜单资源
 | 
			
		||||
	a.ResourceApp.GetAccountResources(account.Id, &resources)
 | 
			
		||||
	biz.ErrIsNil(a.ResourceApp.GetAccountResources(account.Id, &resources))
 | 
			
		||||
	// 菜单树与权限code数组
 | 
			
		||||
	var menus vo.AccountResourceVOList
 | 
			
		||||
	var permissions []string
 | 
			
		||||
@@ -66,7 +66,7 @@ func (a *Account) ChangePassword(rc *req.Ctx) {
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "解密旧密码错误: %s")
 | 
			
		||||
 | 
			
		||||
	account := &entity.Account{Username: form.Username}
 | 
			
		||||
	err = a.AccountApp.GetAccount(account, "Id", "Username", "Password", "Status")
 | 
			
		||||
	err = a.AccountApp.GetBy(account, "Id", "Username", "Password", "Status")
 | 
			
		||||
	biz.ErrIsNil(err, "旧密码错误")
 | 
			
		||||
	biz.IsTrue(cryptox.CheckPwdHash(originOldPwd, account.Password), "旧密码错误")
 | 
			
		||||
	biz.IsTrue(account.IsEnable(), "该账号不可用")
 | 
			
		||||
@@ -78,7 +78,7 @@ func (a *Account) ChangePassword(rc *req.Ctx) {
 | 
			
		||||
	updateAccount := new(entity.Account)
 | 
			
		||||
	updateAccount.Id = account.Id
 | 
			
		||||
	updateAccount.Password = cryptox.PwdHash(originNewPwd)
 | 
			
		||||
	a.AccountApp.Update(updateAccount)
 | 
			
		||||
	biz.ErrIsNil(a.AccountApp.Update(updateAccount), "更新账号密码失败")
 | 
			
		||||
 | 
			
		||||
	// 赋值loginAccount 主要用于记录操作日志,因为操作日志保存请求上下文没有该信息不保存日志
 | 
			
		||||
	if rc.LoginAccount == nil {
 | 
			
		||||
@@ -111,13 +111,14 @@ func (a *Account) UpdateAccount(rc *req.Ctx) {
 | 
			
		||||
		updateAccount.Password = cryptox.PwdHash(updateAccount.Password)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	oldAcc := a.AccountApp.GetById(updateAccount.Id)
 | 
			
		||||
	oldAcc, err := a.AccountApp.GetById(new(entity.Account), updateAccount.Id)
 | 
			
		||||
	biz.ErrIsNil(err, "账号信息不存在")
 | 
			
		||||
	// 账号创建十分钟内允许修改用户名(兼容oauth2首次登录修改用户名),否则不允许修改
 | 
			
		||||
	if oldAcc.CreateTime.Add(10 * time.Minute).Before(time.Now()) {
 | 
			
		||||
		// 禁止更新用户名,防止误传被更新
 | 
			
		||||
		updateAccount.Username = ""
 | 
			
		||||
	}
 | 
			
		||||
	a.AccountApp.Update(updateAccount)
 | 
			
		||||
	biz.ErrIsNil(a.AccountApp.Update(updateAccount))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**    后台账号操作    **/
 | 
			
		||||
@@ -126,7 +127,9 @@ func (a *Account) UpdateAccount(rc *req.Ctx) {
 | 
			
		||||
func (a *Account) Accounts(rc *req.Ctx) {
 | 
			
		||||
	condition := &entity.Account{}
 | 
			
		||||
	condition.Username = rc.GinCtx.Query("username")
 | 
			
		||||
	rc.ResData = a.AccountApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]vo.AccountManageVO))
 | 
			
		||||
	res, err := a.AccountApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]vo.AccountManageVO))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// @router /accounts
 | 
			
		||||
@@ -139,7 +142,7 @@ func (a *Account) SaveAccount(rc *req.Ctx) {
 | 
			
		||||
	account.SetBaseInfo(rc.LoginAccount)
 | 
			
		||||
 | 
			
		||||
	if account.Id == 0 {
 | 
			
		||||
		a.AccountApp.Create(account)
 | 
			
		||||
		biz.ErrIsNil(a.AccountApp.Create(account))
 | 
			
		||||
	} else {
 | 
			
		||||
		if account.Password != "" {
 | 
			
		||||
			biz.IsTrue(utils.CheckAccountPasswordLever(account.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号")
 | 
			
		||||
@@ -147,7 +150,7 @@ func (a *Account) SaveAccount(rc *req.Ctx) {
 | 
			
		||||
		}
 | 
			
		||||
		// 更新操作不允许修改用户名、防止误传更新
 | 
			
		||||
		account.Username = ""
 | 
			
		||||
		a.AccountApp.Update(account)
 | 
			
		||||
		biz.ErrIsNil(a.AccountApp.Update(account))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -158,7 +161,7 @@ func (a *Account) ChangeStatus(rc *req.Ctx) {
 | 
			
		||||
	account.Id = uint64(ginx.PathParamInt(g, "id"))
 | 
			
		||||
	account.Status = int8(ginx.PathParamInt(g, "status"))
 | 
			
		||||
	rc.ReqParam = collx.Kvs("accountId", account.Id, "status", account.Status)
 | 
			
		||||
	a.AccountApp.Update(account)
 | 
			
		||||
	biz.ErrIsNil(a.AccountApp.Update(account))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *Account) DeleteAccount(rc *req.Ctx) {
 | 
			
		||||
@@ -169,7 +172,7 @@ func (a *Account) DeleteAccount(rc *req.Ctx) {
 | 
			
		||||
	for _, v := range ids {
 | 
			
		||||
		value, err := strconv.Atoi(v)
 | 
			
		||||
		biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s")
 | 
			
		||||
		a.AccountApp.Delete(uint64(value))
 | 
			
		||||
		biz.ErrIsNilAppendErr(a.AccountApp.Delete(uint64(value)), "删除失败:%s")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -188,7 +191,7 @@ func (a *Account) AccountRoles(rc *req.Ctx) {
 | 
			
		||||
func (a *Account) AccountResources(rc *req.Ctx) {
 | 
			
		||||
	var resources vo.ResourceManageVOList
 | 
			
		||||
	// 获取账号菜单资源
 | 
			
		||||
	a.ResourceApp.GetAccountResources(uint64(ginx.PathParamInt(rc.GinCtx, "id")), &resources)
 | 
			
		||||
	biz.ErrIsNil(a.ResourceApp.GetAccountResources(uint64(ginx.PathParamInt(rc.GinCtx, "id")), &resources))
 | 
			
		||||
	rc.ResData = resources.ToTrees(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -213,5 +216,5 @@ func (a *Account) ResetOtpSecret(rc *req.Ctx) {
 | 
			
		||||
	accountId := uint64(ginx.PathParamInt(rc.GinCtx, "id"))
 | 
			
		||||
	account.Id = accountId
 | 
			
		||||
	rc.ReqParam = collx.Kvs("accountId", accountId)
 | 
			
		||||
	a.AccountApp.Update(account)
 | 
			
		||||
	biz.ErrIsNil(a.AccountApp.Update(account))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,14 @@
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/captcha"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
	"mayfly-go/pkg/utils/collx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func GenerateCaptcha(rc *req.Ctx) {
 | 
			
		||||
	id, image := captcha.Generate()
 | 
			
		||||
	id, image, err := captcha.Generate()
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "获取验证码错误: %s")
 | 
			
		||||
	rc.ResData = collx.M{"base64Captcha": image, "cid": id}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,9 @@ func (c *Config) Configs(rc *req.Ctx) {
 | 
			
		||||
	g := rc.GinCtx
 | 
			
		||||
	condition := &entity.Config{Key: g.Query("key")}
 | 
			
		||||
	condition.Permission = rc.LoginAccount.Username
 | 
			
		||||
	rc.ResData = c.ConfigApp.GetPageList(condition, ginx.GetPageParam(g), new([]entity.Config))
 | 
			
		||||
	res, err := c.ConfigApp.GetPageList(condition, ginx.GetPageParam(g), new([]entity.Config))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Config) GetConfigValueByKey(rc *req.Ctx) {
 | 
			
		||||
@@ -39,5 +41,5 @@ func (c *Config) SaveConfig(rc *req.Ctx) {
 | 
			
		||||
	config := ginx.BindJsonAndCopyTo(rc.GinCtx, form, new(entity.Config))
 | 
			
		||||
	rc.ReqParam = form
 | 
			
		||||
	config.SetBaseInfo(rc.LoginAccount)
 | 
			
		||||
	c.ConfigApp.Save(config)
 | 
			
		||||
	biz.ErrIsNil(c.ConfigApp.Save(config))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ import (
 | 
			
		||||
	"mayfly-go/internal/sys/api/vo"
 | 
			
		||||
	"mayfly-go/internal/sys/application"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/ginx"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
	"mayfly-go/pkg/utils/collx"
 | 
			
		||||
@@ -17,12 +18,14 @@ type Resource struct {
 | 
			
		||||
 | 
			
		||||
func (r *Resource) GetAllResourceTree(rc *req.Ctx) {
 | 
			
		||||
	var resources vo.ResourceManageVOList
 | 
			
		||||
	r.ResourceApp.GetResourceList(new(entity.Resource), &resources, "weight asc")
 | 
			
		||||
	r.ResourceApp.ListByCondOrder(new(entity.Resource), &resources, "weight asc")
 | 
			
		||||
	rc.ResData = resources.ToTrees(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Resource) GetById(rc *req.Ctx) {
 | 
			
		||||
	rc.ResData = r.ResourceApp.GetById(uint64(ginx.PathParamInt(rc.GinCtx, "id")))
 | 
			
		||||
	res, err := r.ResourceApp.GetById(new(entity.Resource), uint64(ginx.PathParamInt(rc.GinCtx, "id")))
 | 
			
		||||
	biz.ErrIsNil(err, "该资源不存在")
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Resource) SaveResource(rc *req.Ctx) {
 | 
			
		||||
@@ -37,18 +40,18 @@ func (r *Resource) SaveResource(rc *req.Ctx) {
 | 
			
		||||
	entity.Meta = string(bytes)
 | 
			
		||||
 | 
			
		||||
	entity.SetBaseInfo(rc.LoginAccount)
 | 
			
		||||
	r.ResourceApp.Save(entity)
 | 
			
		||||
	biz.ErrIsNil(r.ResourceApp.Save(entity))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Resource) DelResource(rc *req.Ctx) {
 | 
			
		||||
	r.ResourceApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id")))
 | 
			
		||||
	biz.ErrIsNil(r.ResourceApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id"))))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Resource) ChangeStatus(rc *req.Ctx) {
 | 
			
		||||
	rid := uint64(ginx.PathParamInt(rc.GinCtx, "id"))
 | 
			
		||||
	status := int8(ginx.PathParamInt(rc.GinCtx, "status"))
 | 
			
		||||
	rc.ReqParam = collx.Kvs("id", rid, "status", status)
 | 
			
		||||
	r.ResourceApp.ChangeStatus(rid, status)
 | 
			
		||||
	biz.ErrIsNil(r.ResourceApp.ChangeStatus(rid, status))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Resource) Sort(rc *req.Ctx) {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,9 @@ type Role struct {
 | 
			
		||||
func (r *Role) Roles(rc *req.Ctx) {
 | 
			
		||||
	g := rc.GinCtx
 | 
			
		||||
	condition := &entity.Role{Name: g.Query("name")}
 | 
			
		||||
	rc.ResData = r.RoleApp.GetPageList(condition, ginx.GetPageParam(g), new([]entity.Role))
 | 
			
		||||
	res, err := r.RoleApp.GetPageList(condition, ginx.GetPageParam(g), new([]entity.Role))
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 保存角色信息
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package api
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/sys/application"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/ginx"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
)
 | 
			
		||||
@@ -13,5 +14,7 @@ type Syslog struct {
 | 
			
		||||
 | 
			
		||||
func (r *Syslog) Syslogs(rc *req.Ctx) {
 | 
			
		||||
	queryCond, page := ginx.BindQueryAndPage[*entity.SysLogQuery](rc.GinCtx, new(entity.SysLogQuery))
 | 
			
		||||
	rc.ResData = r.SyslogApp.GetPageList(queryCond, page, new([]entity.SysLog), "create_time DESC")
 | 
			
		||||
	res, err := r.SyslogApp.GetPageList(queryCond, page, new([]entity.SysLog), "create_time DESC")
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ func (s *System) ConnectWs(g *gin.Context) {
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if err := recover(); err != nil {
 | 
			
		||||
			errInfo := anyx.ToString(err)
 | 
			
		||||
			logx.Error("websocket连接失败: ", errInfo)
 | 
			
		||||
			logx.Errorf("websocket连接失败: %s", errInfo)
 | 
			
		||||
			if wsConn != nil {
 | 
			
		||||
				wsConn.WriteMessage(websocket.TextMessage, []byte(errInfo))
 | 
			
		||||
				wsConn.Close()
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,8 @@ package application
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
	"mayfly-go/pkg/utils/cryptox"
 | 
			
		||||
@@ -12,71 +13,60 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Account interface {
 | 
			
		||||
	GetAccount(condition *entity.Account, cols ...string) error
 | 
			
		||||
	base.App[*entity.Account]
 | 
			
		||||
 | 
			
		||||
	GetById(id uint64) *entity.Account
 | 
			
		||||
	GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	Create(account *entity.Account) error
 | 
			
		||||
 | 
			
		||||
	Create(account *entity.Account)
 | 
			
		||||
	Update(account *entity.Account) error
 | 
			
		||||
 | 
			
		||||
	Update(account *entity.Account)
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
	Delete(id uint64) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newAccountApp(accountRepo repository.Account) Account {
 | 
			
		||||
	return &accountAppImpl{
 | 
			
		||||
		accountRepo: accountRepo,
 | 
			
		||||
	}
 | 
			
		||||
	return &accountAppImpl{base.AppImpl[*entity.Account, repository.Account]{Repo: accountRepo}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type accountAppImpl struct {
 | 
			
		||||
	accountRepo repository.Account
 | 
			
		||||
	base.AppImpl[*entity.Account, repository.Account]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据条件获取账号信息
 | 
			
		||||
func (a *accountAppImpl) GetAccount(condition *entity.Account, cols ...string) error {
 | 
			
		||||
	return a.accountRepo.GetAccount(condition, cols...)
 | 
			
		||||
func (a *accountAppImpl) GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return a.GetRepo().GetPageList(condition, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *accountAppImpl) GetById(id uint64) *entity.Account {
 | 
			
		||||
	return a.accountRepo.GetById(id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *accountAppImpl) GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
	return a.accountRepo.GetPageList(condition, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *accountAppImpl) Create(account *entity.Account) {
 | 
			
		||||
	biz.IsTrue(a.GetAccount(&entity.Account{Username: account.Username}) != nil, "该账号用户名已存在")
 | 
			
		||||
func (a *accountAppImpl) Create(account *entity.Account) error {
 | 
			
		||||
	if a.GetBy(&entity.Account{Username: account.Username}) == nil {
 | 
			
		||||
		return errorx.NewBiz("该账号用户名已存在")
 | 
			
		||||
	}
 | 
			
		||||
	// 默认密码为账号用户名
 | 
			
		||||
	account.Password = cryptox.PwdHash(account.Username)
 | 
			
		||||
	account.Status = entity.AccountEnableStatus
 | 
			
		||||
	a.accountRepo.Insert(account)
 | 
			
		||||
	return a.Insert(account)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *accountAppImpl) Update(account *entity.Account) {
 | 
			
		||||
func (a *accountAppImpl) Update(account *entity.Account) error {
 | 
			
		||||
	if account.Username != "" {
 | 
			
		||||
		unAcc := &entity.Account{Username: account.Username}
 | 
			
		||||
		err := a.GetAccount(unAcc)
 | 
			
		||||
		biz.IsTrue(err != nil || unAcc.Id == account.Id, "该用户名已存在")
 | 
			
		||||
		err := a.GetBy(unAcc)
 | 
			
		||||
		if err == nil && unAcc.Id != account.Id {
 | 
			
		||||
			return errorx.NewBiz("该用户名已存在")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	a.accountRepo.Update(account)
 | 
			
		||||
	return a.UpdateById(account)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *accountAppImpl) Delete(id uint64) {
 | 
			
		||||
	err := gormx.Tx(
 | 
			
		||||
func (a *accountAppImpl) Delete(id uint64) error {
 | 
			
		||||
	return gormx.Tx(
 | 
			
		||||
		func(db *gorm.DB) error {
 | 
			
		||||
			// 删除account表信息
 | 
			
		||||
			return db.Delete(new(entity.Account), "id = ?", id).Error
 | 
			
		||||
			// 删除account信息
 | 
			
		||||
			return a.DeleteByIdWithDb(db, id)
 | 
			
		||||
		},
 | 
			
		||||
		func(db *gorm.DB) error {
 | 
			
		||||
			// 删除账号关联的角色信息
 | 
			
		||||
			accountRole := &entity.AccountRole{AccountId: id}
 | 
			
		||||
			return db.Where(accountRole).Delete(accountRole).Error
 | 
			
		||||
			return gormx.DeleteByWithDb(db, &entity.AccountRole{AccountId: id})
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
	biz.ErrIsNilAppendErr(err, "删除失败:%s")
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,9 @@ import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/cache"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/logx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
	"mayfly-go/pkg/utils/jsonx"
 | 
			
		||||
@@ -15,40 +16,48 @@ import (
 | 
			
		||||
const SysConfigKeyPrefix = "mayfly:sys:config:"
 | 
			
		||||
 | 
			
		||||
type Config interface {
 | 
			
		||||
	GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	base.App[*entity.Config]
 | 
			
		||||
 | 
			
		||||
	Save(config *entity.Config)
 | 
			
		||||
	GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	Save(config *entity.Config) error
 | 
			
		||||
 | 
			
		||||
	// GetConfig 获取指定key的配置信息, 不会返回nil, 若不存在则值都默认值即空字符串
 | 
			
		||||
	GetConfig(key string) *entity.Config
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newConfigApp(configRepo repository.Config) Config {
 | 
			
		||||
	return &configAppImpl{
 | 
			
		||||
		configRepo: configRepo,
 | 
			
		||||
	}
 | 
			
		||||
	configApp := new(configAppImpl)
 | 
			
		||||
	configApp.Repo = configRepo
 | 
			
		||||
	return configApp
 | 
			
		||||
	// return &configAppImpl{base.AppImpl[*entity.Config, repository.Config]{Repo: configRepo}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type configAppImpl struct {
 | 
			
		||||
	configRepo repository.Config
 | 
			
		||||
	base.AppImpl[*entity.Config, repository.Config]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *configAppImpl) GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
	return a.configRepo.GetPageList(condition, pageParam, toEntity)
 | 
			
		||||
func (a *configAppImpl) GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return a.GetRepo().GetPageList(condition, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *configAppImpl) Save(config *entity.Config) {
 | 
			
		||||
func (a *configAppImpl) Save(config *entity.Config) error {
 | 
			
		||||
	if config.Id == 0 {
 | 
			
		||||
		a.configRepo.Insert(config)
 | 
			
		||||
		if err := a.Insert(config); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		oldConfig := a.GetConfig(config.Key)
 | 
			
		||||
		if oldConfig.Permission != "all" {
 | 
			
		||||
			biz.IsTrue(strings.Contains(oldConfig.Permission, config.Modifier), "您无权修改该配置")
 | 
			
		||||
		if oldConfig.Permission != "all" && !strings.Contains(oldConfig.Permission, config.Modifier) {
 | 
			
		||||
			return errorx.NewBiz("您无权修改该配置")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		a.configRepo.Update(config)
 | 
			
		||||
		if err := a.UpdateById(config); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	cache.Del(SysConfigKeyPrefix + config.Key)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *configAppImpl) GetConfig(key string) *entity.Config {
 | 
			
		||||
@@ -60,7 +69,7 @@ func (a *configAppImpl) GetConfig(key string) *entity.Config {
 | 
			
		||||
		return config
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := a.configRepo.GetConfig(config, "Id", "Key", "Value", "Permission"); err != nil {
 | 
			
		||||
	if err := a.GetBy(config, "Id", "Key", "Value", "Permission"); err != nil {
 | 
			
		||||
		logx.Warnf("不存在key = [%s] 的系统配置", key)
 | 
			
		||||
	} else {
 | 
			
		||||
		cache.SetStr(SysConfigKeyPrefix+key, jsonx.ToStr(config), -1)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,8 @@ import (
 | 
			
		||||
	"mayfly-go/internal/common/consts"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/utils/stringx"
 | 
			
		||||
	"strings"
 | 
			
		||||
@@ -12,58 +13,54 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Resource interface {
 | 
			
		||||
	GetResourceList(condition *entity.Resource, toEntity any, orderBy ...string)
 | 
			
		||||
	base.App[*entity.Resource]
 | 
			
		||||
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.Resource
 | 
			
		||||
	Save(entity *entity.Resource) error
 | 
			
		||||
 | 
			
		||||
	Save(entity *entity.Resource)
 | 
			
		||||
	Delete(id uint64) error
 | 
			
		||||
 | 
			
		||||
	ChangeStatus(resourceId uint64, status int8)
 | 
			
		||||
	ChangeStatus(resourceId uint64, status int8) error
 | 
			
		||||
 | 
			
		||||
	Sort(re *entity.Resource)
 | 
			
		||||
	Sort(re *entity.Resource) error
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
 | 
			
		||||
	GetAccountResources(accountId uint64, toEntity any)
 | 
			
		||||
	GetAccountResources(accountId uint64, toEntity any) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newResourceApp(resourceRepo repository.Resource) Resource {
 | 
			
		||||
	return &resourceAppImpl{
 | 
			
		||||
		resourceRepo: resourceRepo,
 | 
			
		||||
		base.AppImpl[*entity.Resource, repository.Resource]{Repo: resourceRepo},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type resourceAppImpl struct {
 | 
			
		||||
	resourceRepo repository.Resource
 | 
			
		||||
	base.AppImpl[*entity.Resource, repository.Resource]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceAppImpl) GetResourceList(condition *entity.Resource, toEntity any, orderBy ...string) {
 | 
			
		||||
	r.resourceRepo.GetResourceList(condition, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceAppImpl) GetById(id uint64, cols ...string) *entity.Resource {
 | 
			
		||||
	return r.resourceRepo.GetById(id, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceAppImpl) Save(resource *entity.Resource) {
 | 
			
		||||
func (r *resourceAppImpl) Save(resource *entity.Resource) error {
 | 
			
		||||
	// 更新操作
 | 
			
		||||
	if resource.Id != 0 {
 | 
			
		||||
		if resource.Code != "" {
 | 
			
		||||
			oldRes := r.GetById(resource.Id, "Code")
 | 
			
		||||
			oldRes, err := r.GetById(new(entity.Resource), resource.Id, "Code")
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return errorx.NewBiz("更新失败, 该资源不存在")
 | 
			
		||||
			}
 | 
			
		||||
			// 如果修改了code,则校验新code是否存在
 | 
			
		||||
			if oldRes.Code != resource.Code {
 | 
			
		||||
				r.checkCode(resource.Code)
 | 
			
		||||
				if err := r.checkCode(resource.Code); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		gormx.UpdateById(resource)
 | 
			
		||||
		return
 | 
			
		||||
		return gormx.UpdateById(resource)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 生成随机八位唯一标识符
 | 
			
		||||
	ui := stringx.Rand(8)
 | 
			
		||||
	if pid := resource.Pid; pid != 0 {
 | 
			
		||||
		pResource := r.GetById(uint64(pid))
 | 
			
		||||
		biz.IsTrue(pResource != nil, "该父资源不存在")
 | 
			
		||||
		pResource, err := r.GetById(new(entity.Resource), uint64(pid))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return errorx.NewBiz("该父资源不存在")
 | 
			
		||||
		}
 | 
			
		||||
		resource.UiPath = pResource.UiPath + ui + entity.ResourceUiPathSp
 | 
			
		||||
	} else {
 | 
			
		||||
		resource.UiPath = ui + entity.ResourceUiPathSp
 | 
			
		||||
@@ -72,27 +69,33 @@ func (r *resourceAppImpl) Save(resource *entity.Resource) {
 | 
			
		||||
	if resource.Status == 0 {
 | 
			
		||||
		resource.Status = entity.ResourceStatusEnable
 | 
			
		||||
	}
 | 
			
		||||
	r.checkCode(resource.Code)
 | 
			
		||||
	if err := r.checkCode(resource.Code); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	resource.Weight = int(time.Now().Unix())
 | 
			
		||||
	gormx.Insert(resource)
 | 
			
		||||
	return gormx.Insert(resource)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceAppImpl) ChangeStatus(resourceId uint64, status int8) {
 | 
			
		||||
	resource := r.resourceRepo.GetById(resourceId)
 | 
			
		||||
	biz.NotNil(resource, "资源不存在")
 | 
			
		||||
func (r *resourceAppImpl) ChangeStatus(resourceId uint64, status int8) error {
 | 
			
		||||
	resource, err := r.GetById(new(entity.Resource), resourceId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errorx.NewBiz("资源不存在")
 | 
			
		||||
	}
 | 
			
		||||
	resource.Status = status
 | 
			
		||||
	r.resourceRepo.UpdateByUiPathLike(resource)
 | 
			
		||||
	return r.GetRepo().UpdateByUiPathLike(resource)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceAppImpl) Sort(sortResource *entity.Resource) {
 | 
			
		||||
	resource := r.resourceRepo.GetById(sortResource.Id)
 | 
			
		||||
	biz.NotNil(resource, "资源不存在")
 | 
			
		||||
func (r *resourceAppImpl) Sort(sortResource *entity.Resource) error {
 | 
			
		||||
	resource, err := r.GetById(new(entity.Resource), sortResource.Id)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errorx.NewBiz("资源不存在")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 未改变父节点,则更新排序值即可
 | 
			
		||||
	if sortResource.Pid == resource.Pid {
 | 
			
		||||
		saveE := &entity.Resource{Weight: sortResource.Weight}
 | 
			
		||||
		saveE.Id = sortResource.Id
 | 
			
		||||
		r.Save(saveE)
 | 
			
		||||
		return
 | 
			
		||||
		return r.Save(saveE)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 若资源原本唯一标识路径为:xxxx/yyyy/zzzz/,则获取其父节点路径标识 xxxx/yyyy/ 与自身节点标识 zzzz/
 | 
			
		||||
@@ -109,12 +112,14 @@ func (r *resourceAppImpl) Sort(sortResource *entity.Resource) {
 | 
			
		||||
 | 
			
		||||
	newParentResourceUiPath := ""
 | 
			
		||||
	if sortResource.Pid != 0 {
 | 
			
		||||
		newParentResource := r.resourceRepo.GetById(uint64(sortResource.Pid))
 | 
			
		||||
		biz.NotNil(newParentResource, "父资源不存在")
 | 
			
		||||
		newParentResource, err := r.GetById(new(entity.Resource), uint64(sortResource.Pid))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return errorx.NewBiz("父资源不存在")
 | 
			
		||||
		}
 | 
			
		||||
		newParentResourceUiPath = newParentResource.UiPath
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	children := r.resourceRepo.GetChildren(resource.UiPath)
 | 
			
		||||
	children := r.GetRepo().GetChildren(resource.UiPath)
 | 
			
		||||
	for _, v := range children {
 | 
			
		||||
		if v.Id == sortResource.Id {
 | 
			
		||||
			continue
 | 
			
		||||
@@ -137,36 +142,43 @@ func (r *resourceAppImpl) Sort(sortResource *entity.Resource) {
 | 
			
		||||
	}
 | 
			
		||||
	condition := new(entity.Resource)
 | 
			
		||||
	condition.Id = sortResource.Id
 | 
			
		||||
	gormx.Updates(condition, updateMap)
 | 
			
		||||
	return gormx.Updates(condition, updateMap)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceAppImpl) checkCode(code string) {
 | 
			
		||||
	biz.IsTrue(!strings.Contains(code, ","), "code不能包含','")
 | 
			
		||||
	biz.IsEquals(gormx.CountBy(&entity.Resource{Code: code}), int64(0), "该code已存在")
 | 
			
		||||
func (r *resourceAppImpl) checkCode(code string) error {
 | 
			
		||||
	if strings.Contains(code, ",") {
 | 
			
		||||
		return errorx.NewBiz("code不能包含','")
 | 
			
		||||
	}
 | 
			
		||||
	if gormx.CountBy(&entity.Resource{Code: code}) == 0 {
 | 
			
		||||
		return errorx.NewBiz("该code已存在")
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceAppImpl) Delete(id uint64) {
 | 
			
		||||
	resource := r.resourceRepo.GetById(id)
 | 
			
		||||
	biz.NotNil(resource, "资源不存在")
 | 
			
		||||
func (r *resourceAppImpl) Delete(id uint64) error {
 | 
			
		||||
	resource, err := r.GetById(new(entity.Resource), id)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errorx.NewBiz("资源不存在")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 删除当前节点及其所有子节点
 | 
			
		||||
	children := r.resourceRepo.GetChildren(resource.UiPath)
 | 
			
		||||
	children := r.GetRepo().GetChildren(resource.UiPath)
 | 
			
		||||
	for _, v := range children {
 | 
			
		||||
		r.resourceRepo.Delete(v.Id)
 | 
			
		||||
		r.GetRepo().DeleteById(v.Id)
 | 
			
		||||
		// 删除角色关联的资源信息
 | 
			
		||||
		gormx.DeleteByCondition(&entity.RoleResource{ResourceId: v.Id})
 | 
			
		||||
		gormx.DeleteBy(&entity.RoleResource{ResourceId: v.Id})
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceAppImpl) GetAccountResources(accountId uint64, toEntity any) {
 | 
			
		||||
func (r *resourceAppImpl) GetAccountResources(accountId uint64, toEntity any) error {
 | 
			
		||||
	// 超级管理员返回所有
 | 
			
		||||
	if accountId == consts.AdminId {
 | 
			
		||||
		cond := &entity.Resource{
 | 
			
		||||
			Status: entity.ResourceStatusEnable,
 | 
			
		||||
		}
 | 
			
		||||
		r.resourceRepo.GetResourceList(cond, toEntity, "pid asc", "weight asc")
 | 
			
		||||
		return
 | 
			
		||||
		return r.ListByCondOrder(cond, toEntity, "pid asc", "weight asc")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r.resourceRepo.GetAccountResources(accountId, toEntity)
 | 
			
		||||
	return r.GetRepo().GetAccountResources(accountId, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,14 +10,16 @@ import (
 | 
			
		||||
	"mayfly-go/pkg/utils/collx"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Role interface {
 | 
			
		||||
	GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	SaveRole(role *entity.Role)
 | 
			
		||||
	SaveRole(role *entity.Role) error
 | 
			
		||||
 | 
			
		||||
	DeleteRole(id uint64)
 | 
			
		||||
	DeleteRole(id uint64) error
 | 
			
		||||
 | 
			
		||||
	GetRoleResourceIds(roleId uint64) []uint64
 | 
			
		||||
 | 
			
		||||
@@ -50,26 +52,32 @@ type roleAppImpl struct {
 | 
			
		||||
	roleRepo repository.Role
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *roleAppImpl) GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (m *roleAppImpl) GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return m.roleRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *roleAppImpl) SaveRole(role *entity.Role) {
 | 
			
		||||
func (m *roleAppImpl) SaveRole(role *entity.Role) error {
 | 
			
		||||
	role.Code = strings.ToUpper(role.Code)
 | 
			
		||||
	if role.Id != 0 {
 | 
			
		||||
		// code不可更改,防止误传
 | 
			
		||||
		role.Code = ""
 | 
			
		||||
		gormx.UpdateById(role)
 | 
			
		||||
	} else {
 | 
			
		||||
		role.Status = 1
 | 
			
		||||
		gormx.Insert(role)
 | 
			
		||||
		return gormx.UpdateById(role)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	role.Status = 1
 | 
			
		||||
	return gormx.Insert(role)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *roleAppImpl) DeleteRole(id uint64) {
 | 
			
		||||
	m.roleRepo.Delete(id)
 | 
			
		||||
func (m *roleAppImpl) DeleteRole(id uint64) error {
 | 
			
		||||
	// 删除角色与资源的关联关系
 | 
			
		||||
	gormx.DeleteByCondition(&entity.RoleResource{RoleId: id})
 | 
			
		||||
	return gormx.Tx(
 | 
			
		||||
		func(db *gorm.DB) error {
 | 
			
		||||
			return m.roleRepo.DeleteByIdWithDb(db, id)
 | 
			
		||||
		},
 | 
			
		||||
		func(db *gorm.DB) error {
 | 
			
		||||
			return gormx.DeleteByWithDb(db, &entity.RoleResource{RoleId: id})
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *roleAppImpl) GetRoleResourceIds(roleId uint64) []uint64 {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
	"mayfly-go/pkg/utils/anyx"
 | 
			
		||||
@@ -13,7 +13,7 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Syslog interface {
 | 
			
		||||
	GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	// 从请求上下文的参数保存系统日志
 | 
			
		||||
	SaveFromReq(req *req.Ctx)
 | 
			
		||||
@@ -29,7 +29,7 @@ type syslogAppImpl struct {
 | 
			
		||||
	syslogRepo repository.Syslog
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *syslogAppImpl) GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (m *syslogAppImpl) GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return m.syslogRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -64,7 +64,7 @@ func (m *syslogAppImpl) SaveFromReq(req *req.Ctx) {
 | 
			
		||||
		syslog.Type = entity.SyslogTypeError
 | 
			
		||||
		var errMsg string
 | 
			
		||||
		switch t := err.(type) {
 | 
			
		||||
		case *biz.BizError:
 | 
			
		||||
		case errorx.BizError:
 | 
			
		||||
			errMsg = fmt.Sprintf("errCode: %d, errMsg: %s", t.Code(), t.Error())
 | 
			
		||||
		case error:
 | 
			
		||||
			errMsg = t.Error()
 | 
			
		||||
 
 | 
			
		||||
@@ -2,18 +2,12 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Account interface {
 | 
			
		||||
	// 根据条件获取账号信息
 | 
			
		||||
	GetAccount(condition *entity.Account, cols ...string) error
 | 
			
		||||
	base.Repo[*entity.Account]
 | 
			
		||||
 | 
			
		||||
	GetById(id uint64) *entity.Account
 | 
			
		||||
 | 
			
		||||
	GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
 | 
			
		||||
	Insert(account *entity.Account)
 | 
			
		||||
 | 
			
		||||
	Update(account *entity.Account)
 | 
			
		||||
	GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,17 +2,12 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Config interface {
 | 
			
		||||
	GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	base.Repo[*entity.Config]
 | 
			
		||||
 | 
			
		||||
	Insert(config *entity.Config)
 | 
			
		||||
 | 
			
		||||
	Update(config *entity.Config)
 | 
			
		||||
 | 
			
		||||
	GetConfig(config *entity.Config, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	GetByCondition(condition *entity.Config, cols ...string) error
 | 
			
		||||
	GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,24 +2,18 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Resource interface {
 | 
			
		||||
	// 获取资源列表
 | 
			
		||||
	GetResourceList(condition *entity.Resource, toEntity any, orderBy ...string)
 | 
			
		||||
 | 
			
		||||
	GetById(id uint64, cols ...string) *entity.Resource
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
 | 
			
		||||
	GetByCondition(condition *entity.Resource, cols ...string) error
 | 
			
		||||
	base.Repo[*entity.Resource]
 | 
			
		||||
 | 
			
		||||
	// 获取账号资源列表
 | 
			
		||||
	GetAccountResources(accountId uint64, toEntity any)
 | 
			
		||||
	GetAccountResources(accountId uint64, toEntity any) error
 | 
			
		||||
 | 
			
		||||
	// 获取所有子节点id
 | 
			
		||||
	GetChildren(uiPath string) []entity.Resource
 | 
			
		||||
 | 
			
		||||
	// 根据uiPath右匹配更新所有相关类资源
 | 
			
		||||
	UpdateByUiPathLike(resource *entity.Resource)
 | 
			
		||||
	UpdateByUiPathLike(resource *entity.Resource) error
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,13 +2,14 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Role interface {
 | 
			
		||||
	GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	base.Repo[*entity.Role]
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
	GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	// 获取角色拥有的资源id数组,从role_resource表获取
 | 
			
		||||
	GetRoleResourceIds(roleId uint64) []uint64
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,12 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Syslog interface {
 | 
			
		||||
	GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	base.Repo[*entity.SysLog]
 | 
			
		||||
 | 
			
		||||
	Insert(log *entity.SysLog)
 | 
			
		||||
	GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,40 +3,22 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type accountRepoImpl struct{}
 | 
			
		||||
type accountRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.Account]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newAccountRepo() repository.Account {
 | 
			
		||||
	return new(accountRepoImpl)
 | 
			
		||||
	return &accountRepoImpl{base.RepoImpl[*entity.Account]{M: new(entity.Account)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *accountRepoImpl) GetAccount(condition *entity.Account, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *accountRepoImpl) GetById(id uint64) *entity.Account {
 | 
			
		||||
	ac := new(entity.Account)
 | 
			
		||||
	if err := gormx.GetById(ac, id); err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return ac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *accountRepoImpl) GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (m *accountRepoImpl) GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(new(entity.Account)).
 | 
			
		||||
		Like("name", condition.Name).
 | 
			
		||||
		Like("username", condition.Username)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *accountRepoImpl) Insert(account *entity.Account) {
 | 
			
		||||
	biz.ErrIsNil(gormx.Insert(account), "新增账号信息失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *accountRepoImpl) Update(account *entity.Account) {
 | 
			
		||||
	biz.ErrIsNil(gormx.UpdateById(account), "更新账号信息失败")
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,37 +3,23 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type configRepoImpl struct{}
 | 
			
		||||
 | 
			
		||||
func newConfigRepo() repository.Config {
 | 
			
		||||
	return new(configRepoImpl)
 | 
			
		||||
type configRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.Config]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *configRepoImpl) GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func newConfigRepo() repository.Config {
 | 
			
		||||
	return &configRepoImpl{base.RepoImpl[*entity.Config]{M: new(entity.Config)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *configRepoImpl) GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(condition).
 | 
			
		||||
		Eq("key", condition.Key).
 | 
			
		||||
		And("permission = 'all' OR permission LIKE ?", "%"+condition.Permission+",%").
 | 
			
		||||
		WithOrderBy(orderBy...)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *configRepoImpl) Insert(config *entity.Config) {
 | 
			
		||||
	biz.ErrIsNil(gormx.Insert(config), "新增系统配置失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *configRepoImpl) Update(config *entity.Config) {
 | 
			
		||||
	biz.ErrIsNil(gormx.UpdateById(config), "更新系统配置失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *configRepoImpl) GetConfig(condition *entity.Config, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *configRepoImpl) GetByCondition(condition *entity.Config, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,35 +3,18 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type resourceRepoImpl struct{}
 | 
			
		||||
type resourceRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.Resource]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newResourceRepo() repository.Resource {
 | 
			
		||||
	return new(resourceRepoImpl)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceRepoImpl) GetResourceList(condition *entity.Resource, toEntity any, orderBy ...string) {
 | 
			
		||||
	gormx.ListByOrder(condition, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceRepoImpl) GetById(id uint64, cols ...string) *entity.Resource {
 | 
			
		||||
	res := new(entity.Resource)
 | 
			
		||||
	if err := gormx.GetById(res, id, cols...); err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
 | 
			
		||||
	return &resourceRepoImpl{
 | 
			
		||||
		base.RepoImpl[*entity.Resource]{M: new(entity.Resource)},
 | 
			
		||||
	}
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceRepoImpl) Delete(id uint64) {
 | 
			
		||||
	biz.ErrIsNil(gormx.DeleteById(new(entity.Resource), id), "删除失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceRepoImpl) GetByCondition(condition *entity.Resource, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceRepoImpl) GetChildren(uiPath string) []entity.Resource {
 | 
			
		||||
@@ -41,12 +24,12 @@ func (r *resourceRepoImpl) GetChildren(uiPath string) []entity.Resource {
 | 
			
		||||
	return rs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceRepoImpl) UpdateByUiPathLike(resource *entity.Resource) {
 | 
			
		||||
func (r *resourceRepoImpl) UpdateByUiPathLike(resource *entity.Resource) error {
 | 
			
		||||
	sql := "UPDATE t_sys_resource SET status=? WHERE (ui_path LIKE ?)"
 | 
			
		||||
	gormx.ExecSql(sql, resource.Status, resource.UiPath+"%")
 | 
			
		||||
	return gormx.ExecSql(sql, resource.Status, resource.UiPath+"%")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *resourceRepoImpl) GetAccountResources(accountId uint64, toEntity any) {
 | 
			
		||||
func (r *resourceRepoImpl) GetAccountResources(accountId uint64, toEntity any) error {
 | 
			
		||||
	sql := `SELECT
 | 
			
		||||
	           m.id,
 | 
			
		||||
	           m.pid,
 | 
			
		||||
@@ -80,5 +63,5 @@ func (r *resourceRepoImpl) GetAccountResources(accountId uint64, toEntity any) {
 | 
			
		||||
            ORDER BY
 | 
			
		||||
	        m.pid ASC,
 | 
			
		||||
	        m.weight ASC`
 | 
			
		||||
	biz.ErrIsNilAppendErr(gormx.GetListBySql2Model(sql, toEntity, accountId), "查询账号资源失败: %s")
 | 
			
		||||
	return gormx.GetListBySql2Model(sql, toEntity, accountId)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,26 +3,24 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type roleRepoImpl struct{}
 | 
			
		||||
type roleRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.Role]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newRoleRepo() repository.Role {
 | 
			
		||||
	return new(roleRepoImpl)
 | 
			
		||||
	return &roleRepoImpl{base.RepoImpl[*entity.Role]{M: new(entity.Role)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *roleRepoImpl) GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (m *roleRepoImpl) GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *roleRepoImpl) Delete(id uint64) {
 | 
			
		||||
	biz.ErrIsNil(gormx.DeleteById(new(entity.Role), id), "删除角色失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取角色拥有的资源id数组,从role_resource表获取
 | 
			
		||||
func (m *roleRepoImpl) GetRoleResourceIds(roleId uint64) []uint64 {
 | 
			
		||||
	var rrs []entity.RoleResource
 | 
			
		||||
@@ -51,7 +49,7 @@ func (m *roleRepoImpl) SaveRoleResource(rr []*entity.RoleResource) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *roleRepoImpl) DeleteRoleResource(roleId uint64, resourceId uint64) {
 | 
			
		||||
	gormx.DeleteByCondition(&entity.RoleResource{RoleId: roleId, ResourceId: resourceId})
 | 
			
		||||
	gormx.DeleteBy(&entity.RoleResource{RoleId: roleId, ResourceId: resourceId})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *roleRepoImpl) GetAccountRoleIds(accountId uint64) []uint64 {
 | 
			
		||||
@@ -72,7 +70,7 @@ func (m *roleRepoImpl) SaveAccountRole(ar *entity.AccountRole) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *roleRepoImpl) DeleteAccountRole(accountId, roleId uint64) {
 | 
			
		||||
	gormx.DeleteByCondition(&entity.AccountRole{RoleId: roleId, AccountId: accountId})
 | 
			
		||||
	gormx.DeleteBy(&entity.AccountRole{RoleId: roleId, AccountId: accountId})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获取账号角色信息列表
 | 
			
		||||
 
 | 
			
		||||
@@ -3,22 +3,21 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/sys/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/sys/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type syslogRepoImpl struct{}
 | 
			
		||||
 | 
			
		||||
func newSyslogRepo() repository.Syslog {
 | 
			
		||||
	return new(syslogRepoImpl)
 | 
			
		||||
type syslogRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.SysLog]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *syslogRepoImpl) GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func newSyslogRepo() repository.Syslog {
 | 
			
		||||
	return &syslogRepoImpl{base.RepoImpl[*entity.SysLog]{M: new(entity.SysLog)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *syslogRepoImpl) GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(new(entity.SysLog)).Like("description", condition.Description).
 | 
			
		||||
		Eq("creator_id", condition.CreatorId).Eq("type", condition.Type).WithOrderBy(orderBy...)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *syslogRepoImpl) Insert(syslog *entity.SysLog) {
 | 
			
		||||
	gormx.Insert(syslog)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import (
 | 
			
		||||
	"mayfly-go/internal/tag/api/vo"
 | 
			
		||||
	"mayfly-go/internal/tag/application"
 | 
			
		||||
	"mayfly-go/internal/tag/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/ginx"
 | 
			
		||||
	"mayfly-go/pkg/req"
 | 
			
		||||
	"strings"
 | 
			
		||||
@@ -47,11 +48,11 @@ func (p *TagTree) SaveTagTree(rc *req.Ctx) {
 | 
			
		||||
 | 
			
		||||
	loginAccount := rc.LoginAccount
 | 
			
		||||
	tagTree.SetBaseInfo(loginAccount)
 | 
			
		||||
	p.TagTreeApp.Save(tagTree)
 | 
			
		||||
 | 
			
		||||
	rc.ReqParam = fmt.Sprintf("tagTreeId: %d, tagName: %s, codePath: %s", tagTree.Id, tagTree.Name, tagTree.CodePath)
 | 
			
		||||
 | 
			
		||||
	biz.ErrIsNil(p.TagTreeApp.Save(tagTree))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *TagTree) DelTagTree(rc *req.Ctx) {
 | 
			
		||||
	p.TagTreeApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id")))
 | 
			
		||||
	biz.ErrIsNil(p.TagTreeApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id"))))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,9 @@ type Team struct {
 | 
			
		||||
 | 
			
		||||
func (p *Team) GetTeams(rc *req.Ctx) {
 | 
			
		||||
	teams := &[]entity.Team{}
 | 
			
		||||
	rc.ResData = p.TeamApp.GetPageList(&entity.Team{}, ginx.GetPageParam(rc.GinCtx), teams)
 | 
			
		||||
	res, err := p.TeamApp.GetPageList(&entity.Team{}, ginx.GetPageParam(rc.GinCtx), teams)
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Team) SaveTeam(rc *req.Ctx) {
 | 
			
		||||
@@ -66,7 +68,9 @@ func (p *Team) GetTeamMembers(rc *req.Ctx) {
 | 
			
		||||
	condition := &entity.TeamMember{TeamId: uint64(ginx.PathParamInt(rc.GinCtx, "id"))}
 | 
			
		||||
	condition.Username = rc.GinCtx.Query("username")
 | 
			
		||||
 | 
			
		||||
	rc.ResData = p.TeamApp.GetMemberPage(condition, ginx.GetPageParam(rc.GinCtx), &[]vo.TeamMember{})
 | 
			
		||||
	res, err := p.TeamApp.GetMemberPage(condition, ginx.GetPageParam(rc.GinCtx), &[]vo.TeamMember{})
 | 
			
		||||
	biz.ErrIsNil(err)
 | 
			
		||||
	rc.ResData = res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 保存团队信息
 | 
			
		||||
@@ -84,7 +88,7 @@ func (p *Team) SaveTeamMember(rc *req.Ctx) {
 | 
			
		||||
		// 校验账号,并赋值username
 | 
			
		||||
		account := &sys_entity.Account{}
 | 
			
		||||
		account.Id = accountId
 | 
			
		||||
		biz.ErrIsNil(p.AccountApp.GetAccount(account, "Id", "Username"), "账号不存在")
 | 
			
		||||
		biz.ErrIsNil(p.AccountApp.GetBy(account, "Id", "Username"), "账号不存在")
 | 
			
		||||
 | 
			
		||||
		teamMember := new(entity.TeamMember)
 | 
			
		||||
		teamMember.TeamId = teamId
 | 
			
		||||
@@ -132,8 +136,8 @@ func (p *Team) SaveTags(rc *req.Ctx) {
 | 
			
		||||
	loginAccount := rc.LoginAccount
 | 
			
		||||
	for _, v := range addIds {
 | 
			
		||||
		tagId := v
 | 
			
		||||
		tag := p.TagApp.GetById(tagId)
 | 
			
		||||
		biz.NotNil(tag, "存在非法标签id")
 | 
			
		||||
		tag, err := p.TagApp.GetById(new(entity.TagTree), tagId)
 | 
			
		||||
		biz.ErrIsNil(err, "存在非法标签id")
 | 
			
		||||
 | 
			
		||||
		ptt := &entity.TagTreeTeam{TeamId: teamId, TagId: tagId, TagPath: tag.CodePath}
 | 
			
		||||
		ptt.SetBaseInfo(loginAccount)
 | 
			
		||||
 
 | 
			
		||||
@@ -11,20 +11,21 @@ import (
 | 
			
		||||
	redisentity "mayfly-go/internal/redis/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/tag/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/tag/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/errorx"
 | 
			
		||||
	"mayfly-go/pkg/global"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type TagTree interface {
 | 
			
		||||
	base.App[*entity.TagTree]
 | 
			
		||||
 | 
			
		||||
	ListByQuery(condition *entity.TagTreeQuery, toEntity any)
 | 
			
		||||
 | 
			
		||||
	GetById(id uint64) *entity.TagTree
 | 
			
		||||
	Save(tt *entity.TagTree) error
 | 
			
		||||
 | 
			
		||||
	Save(tt *entity.TagTree)
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
	Delete(id uint64) error
 | 
			
		||||
 | 
			
		||||
	// 获取账号id拥有的可访问的标签id
 | 
			
		||||
	ListTagIdByAccountId(accountId uint64) []uint64
 | 
			
		||||
@@ -52,18 +53,20 @@ func newTagTreeApp(tagTreeRepo repository.TagTree,
 | 
			
		||||
	redisApp redisapp.Redis,
 | 
			
		||||
	dbApp dbapp.Db,
 | 
			
		||||
	mongoApp mongoapp.Mongo) TagTree {
 | 
			
		||||
	return &tagTreeAppImpl{
 | 
			
		||||
		tagTreeRepo:     tagTreeRepo,
 | 
			
		||||
	tagTreeApp := &tagTreeAppImpl{
 | 
			
		||||
		tagTreeTeamRepo: tagTreeTeamRepo,
 | 
			
		||||
		machineApp:      machineApp,
 | 
			
		||||
		redisApp:        redisApp,
 | 
			
		||||
		dbApp:           dbApp,
 | 
			
		||||
		mongoApp:        mongoApp,
 | 
			
		||||
	}
 | 
			
		||||
	tagTreeApp.Repo = tagTreeRepo
 | 
			
		||||
	return tagTreeApp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type tagTreeAppImpl struct {
 | 
			
		||||
	tagTreeRepo     repository.TagTree
 | 
			
		||||
	base.AppImpl[*entity.TagTree, repository.TagTree]
 | 
			
		||||
 | 
			
		||||
	tagTreeTeamRepo repository.TagTreeTeam
 | 
			
		||||
	machineApp      machineapp.Machine
 | 
			
		||||
	redisApp        redisapp.Redis
 | 
			
		||||
@@ -71,38 +74,39 @@ type tagTreeAppImpl struct {
 | 
			
		||||
	dbApp           dbapp.Db
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeAppImpl) Save(tag *entity.TagTree) {
 | 
			
		||||
func (p *tagTreeAppImpl) Save(tag *entity.TagTree) error {
 | 
			
		||||
	// 新建项目树节点信息
 | 
			
		||||
	if tag.Id == 0 {
 | 
			
		||||
		biz.IsTrue(!strings.Contains(tag.Code, entity.CodePathSeparator), "标识符不能包含'/'")
 | 
			
		||||
		if strings.Contains(tag.Code, entity.CodePathSeparator) {
 | 
			
		||||
			return errorx.NewBiz("标识符不能包含'/'")
 | 
			
		||||
		}
 | 
			
		||||
		if tag.Pid != 0 {
 | 
			
		||||
			parentTag := p.tagTreeRepo.SelectById(tag.Pid)
 | 
			
		||||
			biz.NotNil(parentTag, "父节点不存在")
 | 
			
		||||
			parentTag, err := p.GetById(new(entity.TagTree), tag.Pid)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return errorx.NewBiz("父节点不存在")
 | 
			
		||||
			}
 | 
			
		||||
			tag.CodePath = parentTag.CodePath + tag.Code + entity.CodePathSeparator
 | 
			
		||||
		} else {
 | 
			
		||||
			tag.CodePath = tag.Code + entity.CodePathSeparator
 | 
			
		||||
		}
 | 
			
		||||
		// 判断该路径是否存在
 | 
			
		||||
		var hasLikeTags []entity.TagTree
 | 
			
		||||
		p.tagTreeRepo.SelectByCondition(&entity.TagTreeQuery{CodePathLike: tag.CodePath}, &hasLikeTags)
 | 
			
		||||
		biz.IsTrue(len(hasLikeTags) == 0, "已存在该标签路径开头的标签, 请修改该标识code")
 | 
			
		||||
		p.GetRepo().SelectByCondition(&entity.TagTreeQuery{CodePathLike: tag.CodePath}, &hasLikeTags)
 | 
			
		||||
		if len(hasLikeTags) > 0 {
 | 
			
		||||
			return errorx.NewBiz("已存在该标签路径开头的标签, 请修改该标识code")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p.tagTreeRepo.Insert(tag)
 | 
			
		||||
		return
 | 
			
		||||
		return p.GetRepo().Insert(tag)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 防止误传导致被更新
 | 
			
		||||
	tag.Code = ""
 | 
			
		||||
	tag.CodePath = ""
 | 
			
		||||
	p.tagTreeRepo.UpdateById(tag)
 | 
			
		||||
	return p.GetRepo().UpdateById(tag)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeAppImpl) ListByQuery(condition *entity.TagTreeQuery, toEntity any) {
 | 
			
		||||
	p.tagTreeRepo.SelectByCondition(condition, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeAppImpl) GetById(tagId uint64) *entity.TagTree {
 | 
			
		||||
	return p.tagTreeRepo.SelectById(tagId)
 | 
			
		||||
	p.GetRepo().SelectByCondition(condition, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeAppImpl) ListTagIdByAccountId(accountId uint64) []uint64 {
 | 
			
		||||
@@ -112,7 +116,7 @@ func (p *tagTreeAppImpl) ListTagIdByAccountId(accountId uint64) []uint64 {
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeAppImpl) ListTagByPath(tagPaths ...string) []entity.TagTree {
 | 
			
		||||
	var tags []entity.TagTree
 | 
			
		||||
	p.tagTreeRepo.SelectByCondition(&entity.TagTreeQuery{CodePathLikes: tagPaths}, &tags)
 | 
			
		||||
	p.GetRepo().SelectByCondition(&entity.TagTreeQuery{CodePathLikes: tagPaths}, &tags)
 | 
			
		||||
	return tags
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -154,16 +158,25 @@ func (p *tagTreeAppImpl) CanAccess(accountId uint64, tagPath string) error {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return biz.NewBizErr("您无权操作该资源")
 | 
			
		||||
	return errorx.NewBiz("您无权操作该资源")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeAppImpl) Delete(id uint64) {
 | 
			
		||||
func (p *tagTreeAppImpl) Delete(id uint64) error {
 | 
			
		||||
	tagIds := [1]uint64{id}
 | 
			
		||||
	biz.IsTrue(p.machineApp.Count(&machineentity.MachineQuery{TagIds: tagIds[:]}) == 0, "请先删除该项目关联的机器信息")
 | 
			
		||||
	biz.IsTrue(p.redisApp.Count(&redisentity.RedisQuery{TagIds: tagIds[:]}) == 0, "请先删除该项目关联的redis信息")
 | 
			
		||||
	biz.IsTrue(p.dbApp.Count(&dbentity.DbQuery{TagIds: tagIds[:]}) == 0, "请先删除该项目关联的数据库信息")
 | 
			
		||||
	biz.IsTrue(p.mongoApp.Count(&mongoentity.MongoQuery{TagIds: tagIds[:]}) == 0, "请先删除该项目关联的Mongo信息")
 | 
			
		||||
	p.tagTreeRepo.Delete(id)
 | 
			
		||||
	if p.machineApp.Count(&machineentity.MachineQuery{TagIds: tagIds[:]}) > 0 {
 | 
			
		||||
		return errorx.NewBiz("请先删除该标签关联的机器信息")
 | 
			
		||||
	}
 | 
			
		||||
	if p.redisApp.Count(&redisentity.RedisQuery{TagIds: tagIds[:]}) > 0 {
 | 
			
		||||
		return errorx.NewBiz("请先删除该标签关联的redis信息")
 | 
			
		||||
	}
 | 
			
		||||
	if p.dbApp.Count(&dbentity.DbQuery{TagIds: tagIds[:]}) > 0 {
 | 
			
		||||
		return errorx.NewBiz("请先删除该标签关联的数据库信息")
 | 
			
		||||
	}
 | 
			
		||||
	if p.mongoApp.Count(&mongoentity.MongoQuery{TagIds: tagIds[:]}) > 0 {
 | 
			
		||||
		return errorx.NewBiz("请先删除该标签关联的Mongo信息")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p.DeleteById(id)
 | 
			
		||||
	// 删除该标签关联的团队信息
 | 
			
		||||
	p.tagTreeTeamRepo.DeleteBy(&entity.TagTreeTeam{TagId: id})
 | 
			
		||||
	return p.tagTreeTeamRepo.DeleteByCond(&entity.TagTreeTeam{TagId: id})
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,20 +4,23 @@ import (
 | 
			
		||||
	"mayfly-go/internal/tag/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/tag/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Team interface {
 | 
			
		||||
	// 分页获取项目团队信息列表
 | 
			
		||||
	GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	Save(team *entity.Team)
 | 
			
		||||
	Save(team *entity.Team) error
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
	Delete(id uint64) error
 | 
			
		||||
 | 
			
		||||
	//--------------- 团队成员相关接口 ---------------
 | 
			
		||||
 | 
			
		||||
	GetMemberPage(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) *model.PageResult[any]
 | 
			
		||||
	GetMemberPage(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	SaveMember(tagTeamMember *entity.TeamMember)
 | 
			
		||||
 | 
			
		||||
@@ -29,9 +32,9 @@ type Team interface {
 | 
			
		||||
 | 
			
		||||
	ListTagIds(teamId uint64) []uint64
 | 
			
		||||
 | 
			
		||||
	SaveTag(tagTeam *entity.TagTreeTeam)
 | 
			
		||||
	SaveTag(tagTeam *entity.TagTreeTeam) error
 | 
			
		||||
 | 
			
		||||
	DeleteTag(teamId, tagId uint64)
 | 
			
		||||
	DeleteTag(teamId, tagId uint64) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTeamApp(teamRepo repository.Team,
 | 
			
		||||
@@ -51,27 +54,34 @@ type teamAppImpl struct {
 | 
			
		||||
	tagTreeTeamRepo repository.TagTreeTeam
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamAppImpl) GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func (p *teamAppImpl) GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	return p.teamRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamAppImpl) Save(team *entity.Team) {
 | 
			
		||||
func (p *teamAppImpl) Save(team *entity.Team) error {
 | 
			
		||||
	if team.Id == 0 {
 | 
			
		||||
		p.teamRepo.Insert(team)
 | 
			
		||||
	} else {
 | 
			
		||||
		p.teamRepo.UpdateById(team)
 | 
			
		||||
		return p.teamRepo.Insert(team)
 | 
			
		||||
	}
 | 
			
		||||
	return p.teamRepo.UpdateById(team)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamAppImpl) Delete(id uint64) {
 | 
			
		||||
	p.teamRepo.Delete(id)
 | 
			
		||||
	p.teamMemberRepo.DeleteBy(&entity.TeamMember{TeamId: id})
 | 
			
		||||
	p.tagTreeTeamRepo.DeleteBy(&entity.TagTreeTeam{TeamId: id})
 | 
			
		||||
func (p *teamAppImpl) Delete(id uint64) error {
 | 
			
		||||
	return gormx.Tx(
 | 
			
		||||
		func(db *gorm.DB) error {
 | 
			
		||||
			return p.teamRepo.DeleteByIdWithDb(db, id)
 | 
			
		||||
		},
 | 
			
		||||
		func(db *gorm.DB) error {
 | 
			
		||||
			return p.teamMemberRepo.DeleteByCondWithDb(db, &entity.TeamMember{TeamId: id})
 | 
			
		||||
		},
 | 
			
		||||
		func(db *gorm.DB) error {
 | 
			
		||||
			return p.tagTreeTeamRepo.DeleteByCondWithDb(db, &entity.TagTreeTeam{TeamId: id})
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --------------- 团队成员相关接口 ---------------
 | 
			
		||||
 | 
			
		||||
func (p *teamAppImpl) GetMemberPage(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) *model.PageResult[any] {
 | 
			
		||||
func (p *teamAppImpl) GetMemberPage(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) (*model.PageResult[any], error) {
 | 
			
		||||
	return p.teamMemberRepo.GetPageList(condition, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -79,12 +89,12 @@ func (p *teamAppImpl) GetMemberPage(condition *entity.TeamMember, pageParam *mod
 | 
			
		||||
func (p *teamAppImpl) SaveMember(teamMember *entity.TeamMember) {
 | 
			
		||||
	teamMember.Id = 0
 | 
			
		||||
	biz.IsTrue(!p.teamMemberRepo.IsExist(teamMember.TeamId, teamMember.AccountId), "该成员已存在")
 | 
			
		||||
	p.teamMemberRepo.Save(teamMember)
 | 
			
		||||
	p.teamMemberRepo.Insert(teamMember)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 删除团队成员信息
 | 
			
		||||
func (p *teamAppImpl) DeleteMember(teamId, accountId uint64) {
 | 
			
		||||
	p.teamMemberRepo.DeleteBy(&entity.TeamMember{TeamId: teamId, AccountId: accountId})
 | 
			
		||||
	p.teamMemberRepo.DeleteByCond(&entity.TeamMember{TeamId: teamId, AccountId: accountId})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamAppImpl) IsExistMember(teamId, accounId uint64) bool {
 | 
			
		||||
@@ -95,7 +105,7 @@ func (p *teamAppImpl) IsExistMember(teamId, accounId uint64) bool {
 | 
			
		||||
 | 
			
		||||
func (p *teamAppImpl) ListTagIds(teamId uint64) []uint64 {
 | 
			
		||||
	tags := &[]entity.TagTreeTeam{}
 | 
			
		||||
	p.tagTreeTeamRepo.ListTag(&entity.TagTreeTeam{TeamId: teamId}, tags)
 | 
			
		||||
	p.tagTreeTeamRepo.ListByCondOrder(&entity.TagTreeTeam{TeamId: teamId}, tags)
 | 
			
		||||
	ids := make([]uint64, 0)
 | 
			
		||||
	for _, v := range *tags {
 | 
			
		||||
		ids = append(ids, v.TagId)
 | 
			
		||||
@@ -104,12 +114,12 @@ func (p *teamAppImpl) ListTagIds(teamId uint64) []uint64 {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 保存关联项目信息
 | 
			
		||||
func (p *teamAppImpl) SaveTag(tagTreeTeam *entity.TagTreeTeam) {
 | 
			
		||||
func (p *teamAppImpl) SaveTag(tagTreeTeam *entity.TagTreeTeam) error {
 | 
			
		||||
	tagTreeTeam.Id = 0
 | 
			
		||||
	p.tagTreeTeamRepo.Save(tagTreeTeam)
 | 
			
		||||
	return p.tagTreeTeamRepo.Insert(tagTreeTeam)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 删除关联项目信息
 | 
			
		||||
func (p *teamAppImpl) DeleteTag(teamId, tagId uint64) {
 | 
			
		||||
	p.tagTreeTeamRepo.DeleteBy(&entity.TagTreeTeam{TeamId: teamId, TagId: tagId})
 | 
			
		||||
func (p *teamAppImpl) DeleteTag(teamId, tagId uint64) error {
 | 
			
		||||
	return p.tagTreeTeamRepo.DeleteByCond(&entity.TagTreeTeam{TeamId: teamId, TagId: tagId})
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,20 +2,12 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/tag/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type TagTree interface {
 | 
			
		||||
	base.Repo[*entity.TagTree]
 | 
			
		||||
 | 
			
		||||
	// 根据条件查询
 | 
			
		||||
	SelectByCondition(condition *entity.TagTreeQuery, toEntity any, orderBy ...string)
 | 
			
		||||
 | 
			
		||||
	GetBy(condition *entity.TagTree, cols ...string) error
 | 
			
		||||
 | 
			
		||||
	// 根据主键查询,若不存在返回nil
 | 
			
		||||
	SelectById(id uint64) *entity.TagTree
 | 
			
		||||
 | 
			
		||||
	Insert(p *entity.TagTree)
 | 
			
		||||
 | 
			
		||||
	UpdateById(p *entity.TagTree)
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,15 @@
 | 
			
		||||
package repository
 | 
			
		||||
 | 
			
		||||
import "mayfly-go/internal/tag/domain/entity"
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/tag/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type TagTreeTeam interface {
 | 
			
		||||
	base.Repo[*entity.TagTreeTeam]
 | 
			
		||||
 | 
			
		||||
	// 获取团队标签信息列表
 | 
			
		||||
	ListTag(condition *entity.TagTreeTeam, toEntity any, orderBy ...string)
 | 
			
		||||
 | 
			
		||||
	Save(mp *entity.TagTreeTeam)
 | 
			
		||||
 | 
			
		||||
	DeleteBy(condition *entity.TagTreeTeam)
 | 
			
		||||
	// ListTag(condition *entity.TagTreeTeam, toEntity any, orderBy ...string)
 | 
			
		||||
 | 
			
		||||
	SelectTagPathsByAccountId(accountId uint64) []string
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,17 +2,12 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/tag/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Team interface {
 | 
			
		||||
	GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
 | 
			
		||||
	base.Repo[*entity.Team]
 | 
			
		||||
 | 
			
		||||
	Insert(p *entity.Team)
 | 
			
		||||
 | 
			
		||||
	UpdateById(p *entity.Team)
 | 
			
		||||
 | 
			
		||||
	Delete(id uint64)
 | 
			
		||||
 | 
			
		||||
	DeleteBy(p *entity.Team)
 | 
			
		||||
	GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,19 +2,17 @@ package repository
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/tag/domain/entity"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type TeamMember interface {
 | 
			
		||||
	base.Repo[*entity.TeamMember]
 | 
			
		||||
 | 
			
		||||
	// 获取项目成员列表
 | 
			
		||||
	ListMemeber(condition *entity.TeamMember, toEntity any, orderBy ...string)
 | 
			
		||||
 | 
			
		||||
	Save(mp *entity.TeamMember)
 | 
			
		||||
 | 
			
		||||
	GetPageList(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) *model.PageResult[any]
 | 
			
		||||
 | 
			
		||||
	DeleteBy(condition *entity.TeamMember)
 | 
			
		||||
	GetPageList(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) (*model.PageResult[any], error)
 | 
			
		||||
 | 
			
		||||
	// 是否存在指定的团队成员关联信息
 | 
			
		||||
	IsExist(teamId, accountId uint64) bool
 | 
			
		||||
 
 | 
			
		||||
@@ -4,15 +4,17 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"mayfly-go/internal/tag/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/tag/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type tagTreeRepoImpl struct{}
 | 
			
		||||
type tagTreeRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.TagTree]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTagTreeRepo() repository.TagTree {
 | 
			
		||||
	return new(tagTreeRepoImpl)
 | 
			
		||||
	return &tagTreeRepoImpl{base.RepoImpl[*entity.TagTree]{M: new(entity.TagTree)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeRepoImpl) SelectByCondition(condition *entity.TagTreeQuery, toEntity any, orderBy ...string) {
 | 
			
		||||
@@ -51,27 +53,3 @@ func (p *tagTreeRepoImpl) SelectByCondition(condition *entity.TagTreeQuery, toEn
 | 
			
		||||
	sql = sql + " ORDER BY p.code_path"
 | 
			
		||||
	gormx.GetListBySql2Model(sql, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeRepoImpl) SelectById(id uint64) *entity.TagTree {
 | 
			
		||||
	pt := new(entity.TagTree)
 | 
			
		||||
	if err := gormx.GetById(pt, id); err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return pt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *tagTreeRepoImpl) GetBy(condition *entity.TagTree, cols ...string) error {
 | 
			
		||||
	return gormx.GetBy(condition, cols...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeRepoImpl) Insert(tagTree *entity.TagTree) {
 | 
			
		||||
	biz.ErrIsNil(gormx.Insert(tagTree), "新增标签失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeRepoImpl) UpdateById(tagTree *entity.TagTree) {
 | 
			
		||||
	biz.ErrIsNil(gormx.UpdateById(tagTree), "更新标签失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeRepoImpl) Delete(id uint64) {
 | 
			
		||||
	gormx.DeleteById(new(entity.TagTree), id)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,26 +3,16 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/tag/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/tag/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type tagTreeTeamRepoImpl struct{}
 | 
			
		||||
type tagTreeTeamRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.TagTreeTeam]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTagTreeTeamRepo() repository.TagTreeTeam {
 | 
			
		||||
	return new(tagTreeTeamRepoImpl)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeTeamRepoImpl) ListTag(condition *entity.TagTreeTeam, toEntity any, orderBy ...string) {
 | 
			
		||||
	gormx.ListByOrder(condition, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeTeamRepoImpl) Save(pm *entity.TagTreeTeam) {
 | 
			
		||||
	biz.ErrIsNilAppendErr(gormx.Insert(pm), "保存团队项目信息失败:%s")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeTeamRepoImpl) DeleteBy(condition *entity.TagTreeTeam) {
 | 
			
		||||
	gormx.DeleteByCondition(condition)
 | 
			
		||||
	return &tagTreeTeamRepoImpl{base.RepoImpl[*entity.TagTreeTeam]{M: new(entity.TagTreeTeam)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagTreeTeamRepoImpl) SelectTagPathsByAccountId(accountId uint64) []string {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,34 +3,20 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/tag/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/tag/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type teamRepoImpl struct{}
 | 
			
		||||
 | 
			
		||||
func newTeamRepo() repository.Team {
 | 
			
		||||
	return new(teamRepoImpl)
 | 
			
		||||
type teamRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.Team]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamRepoImpl) GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
 | 
			
		||||
func newTeamRepo() repository.Team {
 | 
			
		||||
	return &teamRepoImpl{base.RepoImpl[*entity.Team]{M: new(entity.Team)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamRepoImpl) GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamRepoImpl) Insert(team *entity.Team) {
 | 
			
		||||
	biz.ErrIsNil(gormx.Insert(team), "新增团队失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamRepoImpl) UpdateById(team *entity.Team) {
 | 
			
		||||
	biz.ErrIsNil(gormx.UpdateById(team), "更新团队失败")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamRepoImpl) Delete(id uint64) {
 | 
			
		||||
	gormx.DeleteById(new(entity.Team), id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamRepoImpl) DeleteBy(team *entity.Team) {
 | 
			
		||||
	gormx.DeleteByCondition(team)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,26 +3,24 @@ package persistence
 | 
			
		||||
import (
 | 
			
		||||
	"mayfly-go/internal/tag/domain/entity"
 | 
			
		||||
	"mayfly-go/internal/tag/domain/repository"
 | 
			
		||||
	"mayfly-go/pkg/biz"
 | 
			
		||||
	"mayfly-go/pkg/base"
 | 
			
		||||
	"mayfly-go/pkg/gormx"
 | 
			
		||||
	"mayfly-go/pkg/model"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type teamMemberRepoImpl struct{}
 | 
			
		||||
type teamMemberRepoImpl struct {
 | 
			
		||||
	base.RepoImpl[*entity.TeamMember]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTeamMemberRepo() repository.TeamMember {
 | 
			
		||||
	return new(teamMemberRepoImpl)
 | 
			
		||||
	return &teamMemberRepoImpl{base.RepoImpl[*entity.TeamMember]{M: new(entity.TeamMember)}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamMemberRepoImpl) ListMemeber(condition *entity.TeamMember, toEntity any, orderBy ...string) {
 | 
			
		||||
	gormx.ListByOrder(condition, toEntity, orderBy...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamMemberRepoImpl) Save(pm *entity.TeamMember) {
 | 
			
		||||
	biz.ErrIsNilAppendErr(gormx.Insert(pm), "保存团队成员失败:%s")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamMemberRepoImpl) GetPageList(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) *model.PageResult[any] {
 | 
			
		||||
func (p *teamMemberRepoImpl) GetPageList(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) (*model.PageResult[any], error) {
 | 
			
		||||
	qd := gormx.NewQueryWithTableName("t_team_member t").
 | 
			
		||||
		Select("t.*, a.name").
 | 
			
		||||
		Joins("JOIN t_sys_account a ON t.account_id = a.id AND a.status = 1").
 | 
			
		||||
@@ -35,10 +33,6 @@ func (p *teamMemberRepoImpl) GetPageList(condition *entity.TeamMember, pageParam
 | 
			
		||||
	return gormx.PageQuery(qd, pageParam, toEntity)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamMemberRepoImpl) DeleteBy(condition *entity.TeamMember) {
 | 
			
		||||
	gormx.DeleteByCondition(condition)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *teamMemberRepoImpl) IsExist(teamId, accountId uint64) bool {
 | 
			
		||||
	return gormx.CountBy(&entity.TeamMember{TeamId: teamId, AccountId: accountId}) > 0
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user