feat: 使用标签替代项目

This commit is contained in:
meilin.huang
2022-10-26 20:49:29 +08:00
parent 6c197edddd
commit e925a808c4
201 changed files with 3302 additions and 2140 deletions

View File

@@ -15,7 +15,7 @@ require (
github.com/sirupsen/logrus v1.9.0
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2
go.mongodb.org/mongo-driver v1.9.1 // mongo
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // ssh
golang.org/x/crypto v0.1.0 // ssh
gopkg.in/yaml.v3 v3.0.1
// gorm
gorm.io/driver/mysql v1.4.1
@@ -50,10 +50,10 @@ require (
github.com/xdg-go/stringprep v1.0.2 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
golang.org/x/image v0.0.0-20220302094943-723b81ca9867 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect

View File

@@ -7,9 +7,9 @@ import (
db_router "mayfly-go/internal/db/router"
machine_router "mayfly-go/internal/machine/router"
mongo_router "mayfly-go/internal/mongo/router"
project_router "mayfly-go/internal/project/router"
redis_router "mayfly-go/internal/redis/router"
sys_router "mayfly-go/internal/sys/router"
tag_router "mayfly-go/internal/tag/router"
"mayfly-go/pkg/config"
"mayfly-go/pkg/middleware"
"mayfly-go/static"
@@ -74,7 +74,8 @@ func InitRouter() *gin.Engine {
sys_router.Init(api)
project_router.Init(api)
// project_router.Init(api)
tag_router.Init(api)
machine_router.Init(api)
db_router.Init(api)
redis_router.Init(api)

View File

@@ -3,28 +3,43 @@ package api
import (
dbapp "mayfly-go/internal/db/application"
dbentity "mayfly-go/internal/db/domain/entity"
machineentity "mayfly-go/internal/machine/domain/entity"
projectentity "mayfly-go/internal/project/domain/entity"
redisentity "mayfly-go/internal/redis/domain/entity"
machineapp "mayfly-go/internal/machine/application"
projectapp "mayfly-go/internal/project/application"
machineentity "mayfly-go/internal/machine/domain/entity"
mongoapp "mayfly-go/internal/mongo/application"
mongoentity "mayfly-go/internal/mongo/domain/entity"
redisapp "mayfly-go/internal/redis/application"
redisentity "mayfly-go/internal/redis/domain/entity"
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/ctx"
)
type Index struct {
ProjectApp projectapp.Project
TagApp tagapp.TagTree
MachineApp machineapp.Machine
DbApp dbapp.Db
RedisApp redisapp.Redis
MongoApp mongoapp.Mongo
}
func (i *Index) Count(rc *ctx.ReqCtx) {
accountId := rc.LoginAccount.Id
tagIds := i.TagApp.ListTagIdByAccountId(accountId)
var mongoNum int64
var redisNum int64
var dbNum int64
var machienNum int64
if len(tagIds) > 0 {
mongoNum = i.MongoApp.Count(&mongoentity.MongoQuery{TagIds: tagIds})
machienNum = i.MachineApp.Count(&machineentity.MachineQuery{TagIds: tagIds})
dbNum = i.DbApp.Count(&dbentity.DbQuery{TagIds: tagIds})
redisNum = i.RedisApp.Count(&redisentity.RedisQuery{TagIds: tagIds})
}
rc.ResData = map[string]interface{}{
"projectNum": i.ProjectApp.Count(new(projectentity.Project)),
"machineNum": i.MachineApp.Count(new(machineentity.Machine)),
"dbNum": i.DbApp.Count(new(dbentity.Db)),
"redisNum": i.RedisApp.Count(new(redisentity.Redis)),
"mongoNum": mongoNum,
"machineNum": machienNum,
"dbNum": dbNum,
"redisNum": redisNum,
}
}

View File

@@ -4,8 +4,9 @@ import (
"mayfly-go/internal/common/api"
dbapp "mayfly-go/internal/db/application"
machineapp "mayfly-go/internal/machine/application"
projectapp "mayfly-go/internal/project/application"
mongoapp "mayfly-go/internal/mongo/application"
redisapp "mayfly-go/internal/redis/application"
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/ctx"
"github.com/gin-gonic/gin"
@@ -14,10 +15,11 @@ import (
func InitIndexRouter(router *gin.RouterGroup) {
index := router.Group("common/index")
i := &api.Index{
ProjectApp: projectapp.GetProjectApp(),
TagApp: tagapp.GetTagTreeApp(),
MachineApp: machineapp.GetMachineApp(),
DbApp: dbapp.GetDbApp(),
RedisApp: redisapp.GetRedisApp(),
MongoApp: mongoapp.GetMongoApp(),
}
{
// 首页基本信息统计

View File

@@ -7,8 +7,8 @@ import (
"mayfly-go/internal/db/api/vo"
"mayfly-go/internal/db/application"
"mayfly-go/internal/db/domain/entity"
projectapp "mayfly-go/internal/project/application"
sysapp "mayfly-go/internal/sys/application"
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/ctx"
"mayfly-go/pkg/ginx"
@@ -27,19 +27,24 @@ type Db struct {
DbApp application.Db
DbSqlExecApp application.DbSqlExec
MsgApp sysapp.Msg
ProjectApp projectapp.Project
TagApp tagapp.TagTree
}
const DEFAULT_ROW_SIZE = 1800
// @router /api/dbs [get]
func (d *Db) Dbs(rc *ctx.ReqCtx) {
g := rc.GinCtx
m := &entity.Db{EnvId: uint64(ginx.QueryInt(g, "envId", 0)),
ProjectId: uint64(ginx.QueryInt(g, "projectId", 0)),
condition := new(entity.DbQuery)
condition.TagPathLike = rc.GinCtx.Query("tagPath")
// 不存在可访问标签id即没有可操作数据
tagIds := d.TagApp.ListTagIdByAccountId(rc.LoginAccount.Id)
if len(tagIds) == 0 {
rc.ResData = model.EmptyPageResult()
return
}
m.CreatorId = rc.LoginAccount.Id
rc.ResData = d.DbApp.GetPageList(m, ginx.GetPageParam(rc.GinCtx), new([]vo.SelectDataDbVO))
condition.TagIds = tagIds
rc.ResData = d.DbApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]vo.SelectDataDbVO))
}
func (d *Db) Save(rc *ctx.ReqCtx) {
@@ -121,7 +126,7 @@ func (d *Db) ExecSql(rc *ctx.ReqCtx) {
id := GetDbId(g)
db := form.Db
dbInstance := d.DbApp.GetDbInstance(id, db)
biz.ErrIsNilAppendErr(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbInstance.ProjectId), "%s")
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbInstance.TagPath), "%s")
// 去除前后空格及换行符
sql := strings.TrimFunc(form.Sql, func(r rune) bool {
@@ -163,7 +168,7 @@ func (d *Db) ExecSqlFile(rc *ctx.ReqCtx) {
db := d.DbApp.GetDbInstance(dbId, db)
dbEntity := d.DbApp.GetById(dbId)
dbInfo := fmt.Sprintf("于%s的%s环境", dbEntity.Name, dbEntity.Env)
dbInfo := fmt.Sprintf("于%s的%s环境", dbEntity.Name, dbEntity.TagPath)
defer func() {
if err := recover(); err != nil {
@@ -174,7 +179,7 @@ func (d *Db) ExecSqlFile(rc *ctx.ReqCtx) {
}
}()
biz.ErrIsNilAppendErr(d.ProjectApp.CanAccess(rc.LoginAccount.Id, db.ProjectId), "%s")
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, db.TagPath), "%s")
tokens := sqlparser.NewTokenizer(file)
for {
@@ -208,7 +213,7 @@ func (d *Db) DumpSql(rc *ctx.ReqCtx) {
needData := dumpType == "2" || dumpType == "3"
dbInstance := d.DbApp.GetDbInstance(dbId, db)
biz.ErrIsNilAppendErr(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbInstance.ProjectId), "%s")
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbInstance.TagPath), "%s")
now := time.Now()
filename := fmt.Sprintf("%s.%s.sql", db, now.Format("200601021504"))
@@ -294,7 +299,7 @@ func (d *Db) DumpSql(rc *ctx.ReqCtx) {
// @router /api/db/:dbId/t-metadata [get]
func (d *Db) TableMA(rc *ctx.ReqCtx) {
dbi := d.DbApp.GetDbInstance(GetIdAndDb(rc.GinCtx))
biz.ErrIsNilAppendErr(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbi.ProjectId), "%s")
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbi.TagPath), "%s")
rc.ResData = dbi.GetMeta().GetTables()
}
@@ -305,14 +310,14 @@ func (d *Db) ColumnMA(rc *ctx.ReqCtx) {
biz.NotEmpty(tn, "tableName不能为空")
dbi := d.DbApp.GetDbInstance(GetIdAndDb(rc.GinCtx))
biz.ErrIsNilAppendErr(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbi.ProjectId), "%s")
// biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbInstance.TagPath), "%s")
rc.ResData = dbi.GetMeta().GetColumns(tn)
}
// @router /api/db/:dbId/hint-tables [get]
func (d *Db) HintTables(rc *ctx.ReqCtx) {
dbi := d.DbApp.GetDbInstance(GetIdAndDb(rc.GinCtx))
biz.ErrIsNilAppendErr(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbi.ProjectId), "%s")
// biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbInstance.TagPath), "%s")
dm := dbi.GetMeta()
// 获取所有表

View File

@@ -1,19 +1,18 @@
package form
type DbForm struct {
Id uint64
Name string `binding:"required" json:"name"`
Type string `binding:"required" json:"type"` // 类型mysql oracle等
Host string `binding:"required" json:"host"`
Port int `binding:"required" json:"port"`
Username string `binding:"required" json:"username"`
Password string `json:"password"`
Params string `json:"params"`
Database string `json:"database"`
ProjectId uint64 `binding:"required" json:"projectId"`
Project string `json:"project"`
Env string `json:"env"`
EnvId uint64 `binding:"required" json:"envId"`
Id uint64
Name string `binding:"required" json:"name"`
Type string `binding:"required" json:"type"` // 类型mysql oracle等
Host string `binding:"required" json:"host"`
Port int `binding:"required" json:"port"`
Username string `binding:"required" json:"username"`
Password string `json:"password"`
Params string `json:"params"`
Database string `json:"database"`
Remark string `json:"remark"`
TagId uint64 `json:"tagId"`
TagPath string `json:"tagPath"`
EnableSshTunnel int8 `json:"enableSshTunnel"`
SshTunnelMachineId uint64 `json:"sshTunnelMachineId"`

View File

@@ -12,10 +12,9 @@ type SelectDataDbVO struct {
Params *string `json:"params"`
Database *string `json:"database"`
Username *string `json:"username"`
ProjectId *int64 `json:"projectId"`
Project *string `json:"project"`
Env *string `json:"env"`
EnvId *int64 `json:"envId"`
Remark *string `json:"remark"`
TagId *int64 `json:"tagId"`
TagPath *string `json:"tagPath"`
CreateTime *time.Time `json:"createTime"`
Creator *string `json:"creator"`
CreatorId *int64 `json:"creatorId"`

View File

@@ -27,9 +27,9 @@ import (
type Db interface {
// 分页获取
GetPageList(condition *entity.Db, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
GetPageList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
Count(condition *entity.Db) int64
Count(condition *entity.DbQuery) int64
// 根据条件获取
GetDbBy(condition *entity.Db, cols ...string) error
@@ -64,11 +64,11 @@ type dbAppImpl struct {
}
// 分页获取数据库信息列表
func (d *dbAppImpl) GetPageList(condition *entity.Db, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
func (d *dbAppImpl) GetPageList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return d.dbRepo.GetDbList(condition, pageParam, toEntity, orderBy...)
}
func (d *dbAppImpl) Count(condition *entity.Db) int64 {
func (d *dbAppImpl) Count(condition *entity.DbQuery) int64 {
return d.dbRepo.Count(condition)
}
@@ -92,7 +92,7 @@ func (d *dbAppImpl) Save(dbEntity *entity.Db) {
}
// 查找是否存在该库
oldDb := &entity.Db{Host: dbEntity.Host, Port: dbEntity.Port, EnvId: dbEntity.EnvId}
oldDb := &entity.Db{Host: dbEntity.Host, Port: dbEntity.Port, TagId: dbEntity.TagId}
err := d.GetDbBy(oldDb)
if dbEntity.Id == 0 {
@@ -194,7 +194,7 @@ func (da *dbAppImpl) GetDbInstance(id uint64, db string) *DbInstance {
biz.IsTrue(strings.Contains(d.Database, db), "未配置该库的操作权限")
cacheKey := GetDbCacheKey(id, db)
dbi := &DbInstance{Id: cacheKey, Type: d.Type, ProjectId: d.ProjectId, sshTunnelMachineId: d.SshTunnelMachineId}
dbi := &DbInstance{Id: cacheKey, Type: d.Type, TagPath: d.TagPath, sshTunnelMachineId: d.SshTunnelMachineId}
DB, err := GetDbConn(d, db)
if err != nil {
@@ -206,7 +206,7 @@ func (da *dbAppImpl) GetDbInstance(id uint64, db string) *DbInstance {
// 最大连接周期超过时间的连接就close
// DB.SetConnMaxLifetime(100 * time.Second)
// 设置最大连接数
DB.SetMaxOpenConns(2)
DB.SetMaxOpenConns(5)
// 设置闲置连接数
DB.SetMaxIdleConns(1)
@@ -224,7 +224,7 @@ func (da *dbAppImpl) GetDbInstance(id uint64, db string) *DbInstance {
type DbInstance struct {
Id string
Type string
ProjectId uint64
TagPath string
db *sql.DB
sshTunnelMachineId uint64
}

View File

@@ -20,6 +20,7 @@ const (
PGSQL_COLUMN_MA = `SELECT
C.relname AS "tableName",
A.attname AS "columnName",
tc.is_nullable AS "nullable",
concat_ws ( '', t.typname, SUBSTRING ( format_type ( a.atttypid, a.atttypmod ) FROM '\(.*\)' ) ) AS "columnType",
d.description AS "columnComment"
FROM
@@ -28,6 +29,7 @@ const (
LEFT JOIN pg_class c ON A.attrelid = c.oid
LEFT JOIN pg_namespace pn ON c.relnamespace = pn.oid
LEFT JOIN pg_type t ON a.atttypid = t.oid
JOIN information_schema.columns tc ON tc.column_name = a.attname AND tc.table_name = C.relname AND tc.table_schema = pn.nspname
WHERE
A.attnum >= 0
AND pn.nspname = (select current_schema())

View File

@@ -9,19 +9,18 @@ import (
type Db struct {
model.Model
Name string `orm:"column(name)" json:"name"`
Type string `orm:"column(type)" json:"type"` // 类型mysql oracle等
Host string `orm:"column(host)" json:"host"`
Port int `orm:"column(port)" json:"port"`
Network string `orm:"column(network)" json:"network"`
Username string `orm:"column(username)" json:"username"`
Password string `orm:"column(password)" json:"-"`
Database string `orm:"column(database)" json:"database"`
Params string `json:"params"`
ProjectId uint64
Project string
EnvId uint64
Env string
Name string `orm:"column(name)" json:"name"`
Type string `orm:"column(type)" json:"type"` // 类型mysql oracle等
Host string `orm:"column(host)" json:"host"`
Port int `orm:"column(port)" json:"port"`
Network string `orm:"column(network)" json:"network"`
Username string `orm:"column(username)" json:"username"`
Password string `orm:"column(password)" json:"-"`
Database string `orm:"column(database)" json:"database"`
Params string `json:"params"`
Remark string `json:"remark"`
TagId uint64
TagPath string
EnableSshTunnel int8 `orm:"column(enable_ssh_tunnel)" json:"enableSshTunnel"` // 是否启用ssh隧道
SshTunnelMachineId uint64 `orm:"column(ssh_tunnel_machine_id)" json:"sshTunnelMachineId"` // ssh隧道机器id

View File

@@ -0,0 +1,24 @@
package entity
import "mayfly-go/pkg/model"
// 数据库查询实体,不与数据库表字段一一对应
type DbQuery struct {
model.Model
Name string `orm:"column(name)" json:"name"`
Type string `orm:"column(type)" json:"type"` // 类型mysql oracle等
Host string `orm:"column(host)" json:"host"`
Port int `orm:"column(port)" json:"port"`
Network string `orm:"column(network)" json:"network"`
Username string `orm:"column(username)" json:"username"`
Password string `orm:"column(password)" json:"-"`
Database string `orm:"column(database)" json:"database"`
Params string `json:"params"`
Remark string `json:"remark"`
TagId uint64
ProjectIds []uint64
TagIds []uint64
TagPathLike string
}

View File

@@ -7,9 +7,9 @@ import (
type Db interface {
// 分页获取机器信息列表
GetDbList(condition *entity.Db, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
GetDbList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
Count(condition *entity.Db) int64
Count(condition *entity.DbQuery) int64
// 根据条件获取账号信息
GetDb(condition *entity.Db, cols ...string) error

View File

@@ -6,6 +6,8 @@ import (
"mayfly-go/internal/db/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils"
"strings"
)
type dbRepoImpl struct{}
@@ -15,30 +17,33 @@ func newDbRepo() repository.Db {
}
// 分页获取数据库信息列表
func (d *dbRepoImpl) GetDbList(condition *entity.Db, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
sql := "SELECT d.* FROM t_db d JOIN t_project_member pm ON d.project_id = pm.project_id WHERE 1 = 1 "
if condition.CreatorId != 0 {
// 使用创建者id模拟项目成员id
sql = fmt.Sprintf("%s AND pm.account_id = %d", sql, condition.CreatorId)
}
if condition.ProjectId != 0 {
sql = fmt.Sprintf("%s AND d.project_id = %d", sql, condition.ProjectId)
}
if condition.EnvId != 0 {
sql = fmt.Sprintf("%s AND d.env_id = %d", sql, condition.EnvId)
}
func (d *dbRepoImpl) GetDbList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
sql := "SELECT d.* FROM t_db d WHERE 1 = 1 "
if condition.Host != "" {
sql = sql + " AND d.host LIKE '%" + condition.Host + "%'"
}
if condition.Database != "" {
sql = sql + " AND d.database LIKE '%" + condition.Database + "%'"
}
if len(condition.TagIds) > 0 {
sql = sql + " AND d.tag_id IN " + fmt.Sprintf("(%s)", strings.Join(utils.NumberArr2StrArr(condition.TagIds), ","))
}
if condition.TagPathLike != "" {
sql = sql + " AND d.tag_path LIKE '" + condition.TagPathLike + "%'"
}
sql = sql + " ORDER BY d.create_time DESC"
return model.GetPageBySql(sql, pageParam, toEntity)
}
func (d *dbRepoImpl) Count(condition *entity.Db) int64 {
return model.CountBy(condition)
func (d *dbRepoImpl) Count(condition *entity.DbQuery) int64 {
where := make(map[string]interface{})
if len(condition.TagIds) > 0 {
where["tag_id"] = condition.TagIds
}
if condition.TagId != 0 {
where["tag_id"] = condition.TagId
}
return model.CountByMap(new(entity.Db), where)
}
// 根据条件获取账号信息

View File

@@ -23,5 +23,5 @@ func (d *dbSqlExecRepoImpl) DeleteBy(condition *entity.DbSqlExec) {
// 分页获取
func (d *dbSqlExecRepoImpl) GetPageList(condition *entity.DbSqlExec, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity, orderBy...)
return model.GetPage(pageParam, condition, condition, toEntity, orderBy...)
}

View File

@@ -3,8 +3,8 @@ package router
import (
"mayfly-go/internal/db/api"
"mayfly-go/internal/db/application"
projectapp "mayfly-go/internal/project/application"
sysapp "mayfly-go/internal/sys/application"
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/ctx"
"github.com/gin-gonic/gin"
@@ -17,7 +17,7 @@ func InitDbRouter(router *gin.RouterGroup) {
DbApp: application.GetDbApp(),
DbSqlExecApp: application.GetDbSqlExecApp(),
MsgApp: sysapp.GetMsgApp(),
ProjectApp: projectapp.GetProjectApp(),
TagApp: tagapp.GetTagTreeApp(),
}
// 获取所有数据库列表
db.GET("", func(c *gin.Context) {

View File

@@ -2,8 +2,6 @@ package form
type MachineForm struct {
Id uint64 `json:"id"`
ProjectId uint64 `json:"projectId"`
ProjectName string `json:"projectName"`
Name string `json:"name" binding:"required"`
Ip string `json:"ip" binding:"required"` // IP地址
Username string `json:"username" binding:"required"` // 用户名
@@ -14,6 +12,8 @@ type MachineForm struct {
EnableSshTunnel int8 `json:"enableSshTunnel"` // 是否启用ssh隧道
SshTunnelMachineId uint64 `json:"sshTunnelMachineId"` // ssh隧道机器id
EnableRecorder int8 `json:"enableRecorder"` // 是否启用终端回放记录
TagId uint64 `json:"tagId"`
TagPath string `json:"tagPath"`
}
type MachineRunForm struct {

View File

@@ -8,11 +8,12 @@ import (
"mayfly-go/internal/machine/application"
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/internal/machine/infrastructure/machine"
projectapp "mayfly-go/internal/project/application"
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/config"
"mayfly-go/pkg/ctx"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils"
"mayfly-go/pkg/ws"
"os"
@@ -27,16 +28,22 @@ import (
type Machine struct {
MachineApp application.Machine
ProjectApp projectapp.Project
TagApp tagapp.TagTree
}
func (m *Machine) Machines(rc *ctx.ReqCtx) {
condition := new(entity.Machine)
// 使用创建者id模拟账号成员id
condition.CreatorId = rc.LoginAccount.Id
condition := new(entity.MachineQuery)
condition.Ip = rc.GinCtx.Query("ip")
condition.Name = rc.GinCtx.Query("name")
condition.ProjectId = uint64(ginx.QueryInt(rc.GinCtx, "projectId", 0))
condition.TagPathLike = rc.GinCtx.Query("tagPath")
// 不存在可访问标签id即没有可操作数据
tagIds := m.TagApp.ListTagIdByAccountId(rc.LoginAccount.Id)
if len(tagIds) == 0 {
rc.ResData = model.EmptyPageResult()
return
}
condition.TagIds = tagIds
res := m.MachineApp.GetMachineList(condition, ginx.GetPageParam(rc.GinCtx), new([]*vo.MachineVO))
if res.Total == 0 {
@@ -130,7 +137,7 @@ func (m *Machine) GetProcess(rc *ctx.ReqCtx) {
cmd += "| head -n " + count
cli := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
biz.ErrIsNilAppendErr(m.ProjectApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().ProjectId), "%s")
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
res, err := cli.Run(cmd)
biz.ErrIsNilAppendErr(err, "获取进程信息失败: %s")
@@ -143,7 +150,7 @@ func (m *Machine) KillProcess(rc *ctx.ReqCtx) {
biz.NotEmpty(pid, "进程id不能为空")
cli := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
biz.ErrIsNilAppendErr(m.ProjectApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().ProjectId), "%s")
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
_, err := cli.Run("sudo kill -9 " + pid)
biz.ErrIsNilAppendErr(err, "终止进程失败: %s")
@@ -168,7 +175,7 @@ func (m *Machine) WsSSH(g *gin.Context) {
}
cli := m.MachineApp.GetCli(GetMachineId(g))
biz.ErrIsNilAppendErr(m.ProjectApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().ProjectId), "%s")
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
cols := ginx.QueryInt(g, "cols", 80)
rows := ginx.QueryInt(g, "rows", 40)

View File

@@ -6,7 +6,7 @@ import (
"mayfly-go/internal/machine/api/vo"
"mayfly-go/internal/machine/application"
"mayfly-go/internal/machine/domain/entity"
projectapp "mayfly-go/internal/project/application"
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/ctx"
"mayfly-go/pkg/ginx"
@@ -19,7 +19,7 @@ import (
type MachineScript struct {
MachineScriptApp application.MachineScript
MachineApp application.Machine
ProjectApp projectapp.Project
TagApp tagapp.TagTree
}
func (m *MachineScript) MachineScripts(rc *ctx.ReqCtx) {
@@ -65,7 +65,7 @@ func (m *MachineScript) RunMachineScript(rc *ctx.ReqCtx) {
script = utils.TemplateParse(ms.Script, utils.Json2Map(params))
}
cli := m.MachineApp.GetCli(machineId)
biz.ErrIsNilAppendErr(m.ProjectApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().ProjectId), "%s")
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
res, err := cli.Run(script)
// 记录请求参数

View File

@@ -2,22 +2,8 @@ package vo
import "time"
type AccountVO struct {
//models.BaseModel
Id *int64 `json:"id"`
Username *string `json:"username"`
CreateTime *string `json:"createTime"`
Creator *string `json:"creator"`
CreatorId *int64 `json:"creatorId"`
// Role *RoleVO `json:"roles"`
//Status int8 `json:"status"`
}
type MachineVO struct {
//models.BaseModel
Id *uint64 `json:"id"`
ProjectId uint64 `json:"projectId"`
ProjectName string `json:"projectName"`
Name *string `json:"name"`
Username *string `json:"username"`
Ip *string `json:"ip"`
@@ -35,6 +21,8 @@ type MachineVO struct {
HasCli bool `json:"hasCli" gorm:"-"`
Remark *string `json:"remark"`
EnableRecorder int8 `json:"enableRecorder"`
TagId uint64 `json:"tagId"`
TagPath string `json:"tagPath"`
}
type MachineScriptVO struct {

View File

@@ -19,7 +19,7 @@ type Machine interface {
// 调整机器状态
ChangeStatus(id uint64, status int8)
Count(condition *entity.Machine) int64
Count(condition *entity.MachineQuery) int64
Delete(id uint64)
@@ -27,7 +27,7 @@ type Machine interface {
GetById(id uint64, cols ...string) *entity.Machine
// 分页获取机器信息列表
GetMachineList(condition *entity.Machine, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
// 获取机器连接
GetCli(id uint64) *machine.Cli
@@ -46,11 +46,11 @@ type machineAppImpl struct {
}
// 分页获取机器信息列表
func (m *machineAppImpl) GetMachineList(condition *entity.Machine, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
func (m *machineAppImpl) GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return m.machineRepo.GetMachineList(condition, pageParam, toEntity, orderBy...)
}
func (m *machineAppImpl) Count(condition *entity.Machine) int64 {
func (m *machineAppImpl) Count(condition *entity.MachineQuery) int64 {
return m.machineRepo.Count(condition)
}

View File

@@ -7,8 +7,7 @@ import (
type Machine struct {
model.Model
ProjectId uint64 `json:"projectId"`
ProjectName string `json:"projectName"`
Name string `json:"name"`
Ip string `json:"ip"` // IP地址
Username string `json:"username"` // 用户名
@@ -20,6 +19,8 @@ type Machine struct {
EnableSshTunnel int8 `json:"enableSshTunnel"` // 是否启用ssh隧道
SshTunnelMachineId uint64 `json:"sshTunnelMachineId"` // ssh隧道机器id
EnableRecorder int8 `json:"enableRecorder"` // 是否启用终端回放记录
TagId uint64 `json:"tagId"`
TagPath string `json:"tagPath"`
}
const (

View File

@@ -0,0 +1,16 @@
package entity
import "mayfly-go/pkg/model"
// 机器任务配置
type MachineTaskConfig struct {
model.Model
Name string `json:"name"`
Cron string `json:"cron"` // cron表达式
Script string `json:"script"` // 任务内容
Status string `json:"status"`
EnableNotify int `json:"enableNotify"` // 是否启用通知
NotifyTemplate string `json:"notifyTemplate"` // 通知模板
Remark string `json:"remark"` // 备注
}

View File

@@ -0,0 +1,25 @@
package entity
import "mayfly-go/pkg/model"
type MachineQuery struct {
model.Model
ProjectId uint64 `json:"projectId"`
ProjectName string `json:"projectName"`
Name string `json:"name"`
Ip string `json:"ip"` // IP地址
Username string `json:"username"` // 用户名
AuthMethod int8 `json:"authMethod"` // 授权认证方式
Password string `json:"-"`
Port int `json:"port"` // 端口号
Status int8 `json:"status"` // 状态 1:启用2:停用
Remark string `json:"remark"` // 备注
EnableSshTunnel int8 `json:"enableSshTunnel"` // 是否启用ssh隧道
SshTunnelMachineId uint64 `json:"sshTunnelMachineId"` // ssh隧道机器id
EnableRecorder int8 `json:"enableRecorder"` // 是否启用终端回放记录
ProjectIds []uint64
TagId uint64
TagPathLike string
TagIds []uint64
}

View File

@@ -7,9 +7,9 @@ import (
type Machine interface {
// 分页获取机器信息列表
GetMachineList(condition *entity.Machine, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
Count(condition *entity.Machine) int64
Count(condition *entity.MachineQuery) int64
// 根据条件获取账号信息
GetMachine(condition *entity.Machine, cols ...string) error

View File

@@ -0,0 +1,22 @@
package repository
import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/pkg/model"
)
type MachineTaskConfig interface {
GetPageList(condition *entity.MachineTaskConfig, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
// 根据条件获取
GetBy(condition *entity.MachineTaskConfig, cols ...string) error
// 根据id获取
GetById(id uint64, cols ...string) *entity.MachineTaskConfig
Delete(id uint64)
Create(entity *entity.MachineTaskConfig)
UpdateById(entity *entity.MachineTaskConfig)
}

View File

@@ -6,6 +6,8 @@ import (
"mayfly-go/internal/machine/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils"
"strings"
)
type machineRepoImpl struct{}
@@ -15,27 +17,34 @@ func newMachineRepo() repository.Machine {
}
// 分页获取机器信息列表
func (m *machineRepoImpl) GetMachineList(condition *entity.Machine, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
sql := "SELECT m.* FROM t_machine m JOIN t_project_member pm ON m.project_id = pm.project_id WHERE 1 = 1 "
if condition.CreatorId != 0 {
// 使用创建者id模拟项目成员id
sql = fmt.Sprintf("%s AND pm.account_id = %d", sql, condition.CreatorId)
}
if condition.ProjectId != 0 {
sql = fmt.Sprintf("%s AND m.project_id = %d", sql, condition.ProjectId)
}
func (m *machineRepoImpl) GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
sql := "SELECT m.* FROM t_machine m WHERE 1 = 1 "
if condition.Ip != "" {
sql = sql + " AND m.ip LIKE '%" + condition.Ip + "%'"
}
if condition.Name != "" {
sql = sql + " AND m.name LIKE '%" + condition.Name + "%'"
}
sql = sql + " ORDER BY m.project_id, m.create_time DESC"
if len(condition.TagIds) > 0 {
sql = fmt.Sprintf("%s AND m.tag_id IN (%s) ", sql, strings.Join(utils.NumberArr2StrArr(condition.TagIds), ","))
}
if condition.TagPathLike != "" {
sql = sql + " AND m.tag_path LIKE '" + condition.TagPathLike + "%'"
}
sql = sql + " ORDER BY m.tag_id, m.create_time DESC"
return model.GetPageBySql(sql, pageParam, toEntity)
}
func (m *machineRepoImpl) Count(condition *entity.Machine) int64 {
return model.CountBy(condition)
func (m *machineRepoImpl) Count(condition *entity.MachineQuery) int64 {
where := make(map[string]interface{})
if len(condition.TagIds) > 0 {
where["tag_id"] = condition.TagIds
}
if condition.TagId != 0 {
where["tag_id"] = condition.TagId
}
return model.CountByMap(new(entity.Machine), where)
}
// 根据条件获取账号信息

View File

@@ -15,7 +15,7 @@ func newMachineFileRepo() repository.MachineFile {
// 分页获取机器文件信息列表
func (m *machineFileRepoImpl) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity, orderBy...)
return model.GetPage(pageParam, condition, condition, toEntity, orderBy...)
}
// 根据条件获取账号信息

View File

@@ -15,7 +15,7 @@ func newMachineScriptRepo() repository.MachineScript {
// 分页获取机器信息列表
func (m *machineScriptRepoImpl) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity, orderBy...)
return model.GetPage(pageParam, condition, condition, toEntity, orderBy...)
}
// 根据条件获取账号信息

View File

@@ -3,7 +3,7 @@ package router
import (
"mayfly-go/internal/machine/api"
"mayfly-go/internal/machine/application"
projectapp "mayfly-go/internal/project/application"
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/ctx"
"github.com/gin-gonic/gin"
@@ -12,7 +12,7 @@ import (
func InitMachineRouter(router *gin.RouterGroup) {
m := &api.Machine{
MachineApp: application.GetMachineApp(),
ProjectApp: projectapp.GetProjectApp(),
TagApp: tagapp.GetTagTreeApp(),
}
machines := router.Group("machines")

View File

@@ -3,7 +3,7 @@ package router
import (
"mayfly-go/internal/machine/api"
"mayfly-go/internal/machine/application"
projectapp "mayfly-go/internal/project/application"
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/ctx"
"github.com/gin-gonic/gin"
@@ -15,7 +15,7 @@ func InitMachineScriptRouter(router *gin.RouterGroup) {
ms := &api.MachineScript{
MachineScriptApp: application.GetMachineScriptApp(),
MachineApp: application.GetMachineApp(),
ProjectApp: projectapp.GetProjectApp(),
TagApp: tagapp.GetTagTreeApp(),
}
// 获取指定机器脚本列表

View File

@@ -6,10 +6,8 @@ type Mongo struct {
EnableSshTunnel int8 `json:"enableSshTunnel"` // 是否启用ssh隧道
SshTunnelMachineId uint64 `json:"sshTunnelMachineId"` // ssh隧道机器id
Name string `binding:"required" json:"name"`
ProjectId uint64 `binding:"required" json:"projectId"`
Project string `json:"project"`
Env string `json:"env"`
EnvId uint64 `binding:"required" json:"envId"`
TagId uint64 `binding:"required" json:"tagId"`
TagPath string `json:"tagPath"`
}
type MongoCommand struct {

View File

@@ -5,9 +5,11 @@ import (
"mayfly-go/internal/mongo/api/form"
"mayfly-go/internal/mongo/application"
"mayfly-go/internal/mongo/domain/entity"
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/ctx"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils"
"regexp"
"strconv"
@@ -20,15 +22,21 @@ import (
type Mongo struct {
MongoApp application.Mongo
TagApp tagapp.TagTree
}
func (m *Mongo) Mongos(rc *ctx.ReqCtx) {
g := rc.GinCtx
mc := &entity.Mongo{EnvId: uint64(ginx.QueryInt(g, "envId", 0)),
ProjectId: uint64(ginx.QueryInt(g, "projectId", 0)),
condition := new(entity.MongoQuery)
condition.TagPathLike = rc.GinCtx.Query("tagPath")
// 不存在可访问标签id即没有可操作数据
tagIds := m.TagApp.ListTagIdByAccountId(rc.LoginAccount.Id)
if len(tagIds) == 0 {
rc.ResData = model.EmptyPageResult()
return
}
mc.CreatorId = rc.LoginAccount.Id
rc.ResData = m.MongoApp.GetPageList(mc, ginx.GetPageParam(rc.GinCtx), new([]entity.Mongo))
condition.TagIds = tagIds
rc.ResData = m.MongoApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]entity.Mongo))
}
func (m *Mongo) Save(rc *ctx.ReqCtx) {

View File

@@ -22,9 +22,9 @@ import (
type Mongo interface {
// 分页获取机器脚本信息列表
GetPageList(condition *entity.Mongo, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
GetPageList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
Count(condition *entity.Mongo) int64
Count(condition *entity.MongoQuery) int64
// 根据条件获取
GetBy(condition *entity.Mongo, cols ...string) error
@@ -53,11 +53,11 @@ type mongoAppImpl struct {
}
// 分页获取数据库信息列表
func (d *mongoAppImpl) GetPageList(condition *entity.Mongo, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
func (d *mongoAppImpl) GetPageList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return d.mongoRepo.GetList(condition, pageParam, toEntity, orderBy...)
}
func (d *mongoAppImpl) Count(condition *entity.Mongo) int64 {
func (d *mongoAppImpl) Count(condition *entity.MongoQuery) int64 {
return d.mongoRepo.Count(condition)
}
@@ -141,7 +141,7 @@ func DeleteMongoCache(mongoId uint64) {
type MongoInstance struct {
Id uint64
ProjectId uint64
TagPath string
Cli *mongo.Client
sshTunnelMachineId uint64
}
@@ -160,7 +160,7 @@ func connect(me *entity.Mongo) (*MongoInstance, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
mongoInstance := &MongoInstance{Id: me.Id, ProjectId: me.ProjectId}
mongoInstance := &MongoInstance{Id: me.Id, TagPath: me.TagPath}
mongoOptions := options.Client().ApplyURI(me.Uri).
SetMaxPoolSize(1)

View File

@@ -9,8 +9,6 @@ type Mongo struct {
Uri string `orm:"column(uri)" json:"uri"`
EnableSshTunnel int8 `orm:"column(enable_ssh_tunnel)" json:"enableSshTunnel"` // 是否启用ssh隧道
SshTunnelMachineId uint64 `orm:"column(ssh_tunnel_machine_id)" json:"sshTunnelMachineId"` // ssh隧道机器id
ProjectId uint64 `json:"projectId"`
Project string `json:"project"`
EnvId uint64 `json:"envId"`
Env string `json:"env"`
TagId uint64 `json:"tagId"`
TagPath string `json:"tagPath"`
}

View File

@@ -0,0 +1,17 @@
package entity
import "mayfly-go/pkg/model"
type MongoQuery struct {
model.Model
Name string
Uri string
EnableSshTunnel int8 // 是否启用ssh隧道
SshTunnelMachineId uint64 // ssh隧道机器id
TagId uint64 `json:"tagId"`
TagPath string `json:"tagPath"`
TagIds []uint64
TagPathLike string
}

View File

@@ -7,9 +7,9 @@ import (
type Mongo interface {
// 分页获取列表
GetList(condition *entity.Mongo, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
GetList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
Count(condition *entity.Mongo) int64
Count(condition *entity.MongoQuery) int64
// 根据条件获取
Get(condition *entity.Mongo, cols ...string) error

View File

@@ -6,6 +6,8 @@ import (
"mayfly-go/internal/mongo/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils"
"strings"
)
type mongoRepoImpl struct{}
@@ -15,24 +17,28 @@ func newMongoRepo() repository.Mongo {
}
// 分页获取数据库信息列表
func (d *mongoRepoImpl) GetList(condition *entity.Mongo, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
sql := "SELECT d.* FROM t_mongo d JOIN t_project_member pm ON d.project_id = pm.project_id WHERE 1 = 1 "
if condition.CreatorId != 0 {
// 使用创建者id模拟项目成员id
sql = fmt.Sprintf("%s AND pm.account_id = %d", sql, condition.CreatorId)
func (d *mongoRepoImpl) GetList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
sql := "SELECT d.* FROM t_mongo d WHERE 1=1 "
if len(condition.TagIds) > 0 {
sql = sql + " AND d.tag_id IN " + fmt.Sprintf("(%s)", strings.Join(utils.NumberArr2StrArr(condition.TagIds), ","))
}
if condition.ProjectId != 0 {
sql = fmt.Sprintf("%s AND d.project_id = %d", sql, condition.ProjectId)
}
if condition.EnvId != 0 {
sql = fmt.Sprintf("%s AND d.env_id = %d", sql, condition.EnvId)
if condition.TagPathLike != "" {
sql = sql + " AND d.tag_path LIKE '" + condition.TagPathLike + "%'"
}
sql = sql + " ORDER BY d.create_time DESC"
return model.GetPageBySql(sql, pageParam, toEntity)
}
func (d *mongoRepoImpl) Count(condition *entity.Mongo) int64 {
return model.CountBy(condition)
func (d *mongoRepoImpl) Count(condition *entity.MongoQuery) int64 {
where := make(map[string]interface{})
if len(condition.TagIds) > 0 {
where["tag_id"] = condition.TagIds
}
if condition.TagId != 0 {
where["tag_id"] = condition.TagId
}
return model.CountByMap(new(entity.Mongo), where)
}
// 根据条件获取

View File

@@ -3,6 +3,7 @@ package router
import (
"mayfly-go/internal/mongo/api"
"mayfly-go/internal/mongo/application"
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/ctx"
"github.com/gin-gonic/gin"
@@ -13,6 +14,7 @@ func InitMongoRouter(router *gin.RouterGroup) {
{
ma := &api.Mongo{
MongoApp: application.GetMongoApp(),
TagApp: tagapp.GetTagTreeApp(),
}
// 获取所有mongo列表
@@ -60,7 +62,7 @@ func InitMongoRouter(router *gin.RouterGroup) {
})
// 执行mongo update by id命令
updateDocById := ctx.NewLogInfo("mongo-更新文档")
updateDocById := ctx.NewLogInfo("mongo-更新文档").WithSave(true)
m.POST(":id/command/update-by-id", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).
WithLog(updateDocById).
@@ -68,7 +70,7 @@ func InitMongoRouter(router *gin.RouterGroup) {
})
// 执行mongo delete by id命令
deleteDoc := ctx.NewLogInfo("mongo-删除文档")
deleteDoc := ctx.NewLogInfo("mongo-删除文档").WithSave(true)
m.POST(":id/command/delete-by-id", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).
WithLog(deleteDoc).
@@ -76,7 +78,7 @@ func InitMongoRouter(router *gin.RouterGroup) {
})
// 执行mongo insert 命令
insertDoc := ctx.NewLogInfo("mongo-新增文档")
insertDoc := ctx.NewLogInfo("mongo-新增文档").WithSave(true)
m.POST(":id/command/insert", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).
WithLog(insertDoc).

View File

@@ -1,110 +0,0 @@
package api
import (
"fmt"
"mayfly-go/internal/project/api/vo"
projectapp "mayfly-go/internal/project/application"
"mayfly-go/internal/project/domain/entity"
sys_applicaiton "mayfly-go/internal/sys/application"
sys_entity "mayfly-go/internal/sys/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/ctx"
"mayfly-go/pkg/ginx"
)
type Project struct {
ProjectApp projectapp.Project
AccountApp sys_applicaiton.Account
}
// 获取当前登录用户可以访问的项目列表
func (p *Project) GetProjectsByLoginAccount(rc *ctx.ReqCtx) {
// 获取登录用户拥有的项目ids
projectMembers := &[]entity.ProjectMember{}
p.ProjectApp.ListMember(&entity.ProjectMember{AccountId: rc.LoginAccount.Id}, projectMembers)
var pids []uint64
for _, pm := range *projectMembers {
pids = append(pids, pm.ProjectId)
}
// 获取项目信息
projects := &vo.AccountProjects{}
p.ProjectApp.ListProjectByIds(pids, projects)
rc.ResData = projects
}
func (p *Project) GetProjects(rc *ctx.ReqCtx) {
condition := &entity.Project{}
ginx.BindQuery(rc.GinCtx, condition)
// condition.Name = rc.GinCtx.Query("name")
rc.ResData = p.ProjectApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]entity.Project))
}
func (p *Project) SaveProject(rc *ctx.ReqCtx) {
project := &entity.Project{}
ginx.BindJsonAndValid(rc.GinCtx, project)
rc.ReqParam = fmt.Sprintf("projectId: %d, projectName: %s, remark: %s", project.Id, project.Name, project.Remark)
project.SetBaseInfo(rc.LoginAccount)
p.ProjectApp.SaveProject(project)
}
func (p *Project) DelProject(rc *ctx.ReqCtx) {
p.ProjectApp.DelProject(uint64(ginx.QueryInt(rc.GinCtx, "id", 0)))
}
func (p *Project) DelProjectEnv(rc *ctx.ReqCtx) {
p.ProjectApp.DelProjectEnv(uint64(ginx.QueryInt(rc.GinCtx, "id", 0)))
}
// 获取项目下的环境信息
func (p *Project) GetProjectEnvs(rc *ctx.ReqCtx) {
projectEnvs := &[]entity.ProjectEnv{}
p.ProjectApp.ListEnvByProjectId(uint64(ginx.PathParamInt(rc.GinCtx, "projectId")), projectEnvs)
rc.ResData = projectEnvs
}
// 保存项目下的环境信息
func (p *Project) SaveProjectEnvs(rc *ctx.ReqCtx) {
projectEnv := &entity.ProjectEnv{}
ginx.BindJsonAndValid(rc.GinCtx, projectEnv)
rc.ReqParam = projectEnv
projectEnv.SetBaseInfo(rc.LoginAccount)
p.ProjectApp.SaveProjectEnv(projectEnv)
}
// 获取项目下的成员信息
func (p *Project) GetProjectMembers(rc *ctx.ReqCtx) {
projectMems := &[]entity.ProjectMember{}
rc.ResData = p.ProjectApp.GetMemberPage(&entity.ProjectMember{ProjectId: uint64(ginx.PathParamInt(rc.GinCtx, "projectId"))},
ginx.GetPageParam(rc.GinCtx), projectMems)
}
// 保存项目的成员信息
func (p *Project) SaveProjectMember(rc *ctx.ReqCtx) {
projectMem := &entity.ProjectMember{}
ginx.BindJsonAndValid(rc.GinCtx, projectMem)
rc.ReqParam = fmt.Sprintf("projectId: %d, username: %s", projectMem.ProjectId, projectMem.Username)
// 校验账号并赋值username
account := &sys_entity.Account{}
account.Id = projectMem.AccountId
biz.ErrIsNil(p.AccountApp.GetAccount(account, "Id", "Username"), "账号不存在")
projectMem.Username = account.Username
projectMem.SetBaseInfo(rc.LoginAccount)
p.ProjectApp.SaveProjectMember(projectMem)
}
// 删除项目成员
func (p *Project) DelProjectMember(rc *ctx.ReqCtx) {
g := rc.GinCtx
pid := ginx.PathParamInt(g, "projectId")
aid := ginx.PathParamInt(g, "accountId")
rc.ReqParam = fmt.Sprintf("projectId: %d, accountId: %d", pid, aid)
p.ProjectApp.DeleteMember(uint64(pid), uint64(aid))
}

View File

@@ -1,25 +0,0 @@
package application
import (
dbapp "mayfly-go/internal/db/application"
machineapp "mayfly-go/internal/machine/application"
mongoapp "mayfly-go/internal/mongo/application"
"mayfly-go/internal/project/infrastructure/persistence"
redisapp "mayfly-go/internal/redis/application"
)
var (
projectApp Project = newProjectApp(
persistence.GetProjectRepo(),
persistence.GetProjectEnvRepo(),
persistence.GetProjectMemberRepo(),
machineapp.GetMachineApp(),
redisapp.GetRedisApp(),
dbapp.GetDbApp(),
mongoapp.GetMongoApp(),
)
)
func GetProjectApp() Project {
return projectApp
}

View File

@@ -1,156 +0,0 @@
package application
import (
dbapp "mayfly-go/internal/db/application"
dbentity "mayfly-go/internal/db/domain/entity"
machineapp "mayfly-go/internal/machine/application"
machineentity "mayfly-go/internal/machine/domain/entity"
mongoapp "mayfly-go/internal/mongo/application"
mongoentity "mayfly-go/internal/mongo/domain/entity"
"mayfly-go/internal/project/domain/entity"
"mayfly-go/internal/project/domain/repository"
redisapp "mayfly-go/internal/redis/application"
redisentity "mayfly-go/internal/redis/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
)
type Project interface {
// 分页获取项目信息列表
GetPageList(condition *entity.Project, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
Count(condition *entity.Project) int64
ListProjectByIds(ids []uint64, toEntity interface{}, orderBy ...string)
SaveProject(project *entity.Project)
DelProject(id uint64)
DelProjectEnv(id uint64)
// 根据项目id获取所有该项目下的环境信息列表
ListEnvByProjectId(projectId uint64, listPtr interface{})
// 保存项目环境信息
SaveProjectEnv(projectEnv *entity.ProjectEnv)
// 根据条件获取项目成员信息
ListMember(condition *entity.ProjectMember, toEntity interface{}, orderBy ...string)
SaveProjectMember(pm *entity.ProjectMember)
// 根据条件获取项目成员信息
GetMemberPage(condition *entity.ProjectMember, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
DeleteMember(projectId, accountId uint64)
// 账号是否有权限访问该项目关联的资源信息
CanAccess(accountId, projectId uint64) error
}
func newProjectApp(projectRepo repository.Project,
projectEnvRepo repository.ProjectEnv,
projectMemberRepo repository.ProjectMemeber,
machineApp machineapp.Machine,
redisApp redisapp.Redis,
dbApp dbapp.Db,
mongoApp mongoapp.Mongo) Project {
return &projectAppImpl{
projectRepo: projectRepo,
projectEnvRepo: projectEnvRepo,
projectMemberRepo: projectMemberRepo,
machineApp: machineApp,
redisApp: redisApp,
dbApp: dbApp,
mongoApp: mongoApp,
}
}
type projectAppImpl struct {
projectRepo repository.Project
projectEnvRepo repository.ProjectEnv
projectMemberRepo repository.ProjectMemeber
machineApp machineapp.Machine
redisApp redisapp.Redis
mongoApp mongoapp.Mongo
dbApp dbapp.Db
}
// 分页获取项目信息列表
func (p *projectAppImpl) GetPageList(condition *entity.Project, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return p.projectRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
func (p *projectAppImpl) Count(condition *entity.Project) int64 {
return p.projectRepo.Count(condition)
}
func (p *projectAppImpl) ListProjectByIds(ids []uint64, toEntity interface{}, orderBy ...string) {
p.projectRepo.GetByIdIn(ids, toEntity, orderBy...)
}
func (p *projectAppImpl) SaveProject(project *entity.Project) {
if project.Id == 0 {
p.projectRepo.Save(project)
} else {
// 防止误传导致项目名更新
project.Name = ""
p.projectRepo.Update(project)
}
}
func (p *projectAppImpl) DelProject(id uint64) {
biz.IsTrue(p.machineApp.Count(&machineentity.Machine{ProjectId: id}) == 0, "请先删除该项目关联的机器信息")
biz.IsTrue(p.redisApp.Count(&redisentity.Redis{ProjectId: id}) == 0, "请先删除该项目关联的redis信息")
biz.IsTrue(p.dbApp.Count(&dbentity.Db{ProjectId: id}) == 0, "请先删除该项目关联的数据库信息")
biz.IsTrue(p.mongoApp.Count(&mongoentity.Mongo{ProjectId: id}) == 0, "请先删除该项目关联的Mongo信息")
p.projectRepo.Delete(id)
p.projectEnvRepo.DeleteEnvs(id)
p.projectMemberRepo.DeleteMems(id)
}
// 根据项目id获取所有该项目下的环境信息列表
func (p *projectAppImpl) ListEnvByProjectId(projectId uint64, listPtr interface{}) {
p.projectEnvRepo.ListEnv(&entity.ProjectEnv{ProjectId: projectId}, listPtr)
}
// 保存项目环境信息
func (p *projectAppImpl) SaveProjectEnv(projectEnv *entity.ProjectEnv) {
p.projectEnvRepo.Save(projectEnv)
}
// 删除项目环境信息
func (p *projectAppImpl) DelProjectEnv(id uint64) {
biz.IsTrue(p.redisApp.Count(&redisentity.Redis{EnvId: id}) == 0, "请先删除该项目环境关联的redis信息")
biz.IsTrue(p.dbApp.Count(&dbentity.Db{EnvId: id}) == 0, "请先删除该项目环境关联的数据库信息")
biz.IsTrue(p.mongoApp.Count(&mongoentity.Mongo{ProjectId: id}) == 0, "请先删除该项目环境关联的Mongo信息")
p.projectEnvRepo.DeleteEnv(id)
}
// 根据条件获取项目成员信息
func (p *projectAppImpl) ListMember(condition *entity.ProjectMember, toEntity interface{}, orderBy ...string) {
p.projectMemberRepo.ListMemeber(condition, toEntity, orderBy...)
}
func (p *projectAppImpl) SaveProjectMember(pm *entity.ProjectMember) {
pms := new([]entity.ProjectMember)
p.ListMember(&entity.ProjectMember{ProjectId: pm.ProjectId, AccountId: pm.AccountId}, pms)
biz.IsTrue(len(*pms) == 0, "该成员已存在")
p.projectMemberRepo.Save(pm)
}
func (p *projectAppImpl) GetMemberPage(condition *entity.ProjectMember, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return p.projectMemberRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
func (p *projectAppImpl) DeleteMember(projectId, accountId uint64) {
p.projectMemberRepo.DeleteByPidMid(projectId, accountId)
}
func (p *projectAppImpl) CanAccess(accountId, projectId uint64) error {
if p.projectMemberRepo.IsExist(projectId, accountId) {
return nil
}
return biz.NewBizErr("您无权操作该资源")
}

View File

@@ -1,11 +0,0 @@
package entity
import "mayfly-go/pkg/model"
// 项目环境
type ProjectEnv struct {
model.Model
Name string `json:"name"` // 环境名
ProjectId uint64 `json:"projectId"` // 项目id
Remark string `json:"remark"` // 备注说明
}

View File

@@ -1,11 +0,0 @@
package entity
import "mayfly-go/pkg/model"
// 项目成员,用于对项目下组件的访问控制
type ProjectMember struct {
model.Model
AccountId uint64 `json:"accountId"` // 账号
Username string `json:"username"` // 账号用户名
ProjectId uint64 `json:"projectId"` // 项目id
}

View File

@@ -1,20 +0,0 @@
package repository
import (
"mayfly-go/internal/project/domain/entity"
"mayfly-go/pkg/model"
)
type Project interface {
GetPageList(condition *entity.Project, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
Count(condition *entity.Project) int64
GetByIdIn(ids []uint64, toEntity interface{}, orderBy ...string)
Save(p *entity.Project)
Update(project *entity.Project)
Delete(id uint64)
}

View File

@@ -1,14 +0,0 @@
package repository
import "mayfly-go/internal/project/domain/entity"
type ProjectEnv interface {
// 获取项目环境列表
ListEnv(condition *entity.ProjectEnv, toEntity interface{}, orderBy ...string)
Save(entity *entity.ProjectEnv)
DeleteEnvs(projectId uint64)
DeleteEnv(envId uint64)
}

View File

@@ -1,24 +0,0 @@
package repository
import (
"mayfly-go/internal/project/domain/entity"
"mayfly-go/pkg/model"
)
type ProjectMemeber interface {
// 获取项目成员列表
ListMemeber(condition *entity.ProjectMember, toEntity interface{}, orderBy ...string)
Save(mp *entity.ProjectMember)
GetPageList(condition *entity.ProjectMember, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
// 根据成员id和项目id删除关联关系
DeleteByPidMid(projectId, accountId uint64)
DeleteMems(projectId uint64)
// 是否存在指定的项目成员关联信息
IsExist(projectId, accountId uint64) bool
}

View File

@@ -1,21 +0,0 @@
package persistence
import "mayfly-go/internal/project/domain/repository"
var (
projectRepo repository.Project = newProjectRepo()
projectEnvRepo repository.ProjectEnv = newProjectEnvRepo()
projectMemberRepo repository.ProjectMemeber = newProjectMemberRepo()
)
func GetProjectRepo() repository.Project {
return projectRepo
}
func GetProjectEnvRepo() repository.ProjectEnv {
return projectEnvRepo
}
func GetProjectMemberRepo() repository.ProjectMemeber {
return projectMemberRepo
}

View File

@@ -1,38 +0,0 @@
package persistence
import (
"mayfly-go/internal/project/domain/entity"
"mayfly-go/internal/project/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
)
type projectRepoImpl struct{}
func newProjectRepo() repository.Project {
return new(projectRepoImpl)
}
func (p *projectRepoImpl) GetPageList(condition *entity.Project, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity, orderBy...)
}
func (p *projectRepoImpl) Count(condition *entity.Project) int64 {
return model.CountBy(condition)
}
func (p *projectRepoImpl) GetByIdIn(ids []uint64, toEntity interface{}, orderBy ...string) {
model.GetByIdIn(new(entity.Project), toEntity, ids, orderBy...)
}
func (p *projectRepoImpl) Save(project *entity.Project) {
biz.ErrIsNil(model.Insert(project), "保存项目失败")
}
func (p *projectRepoImpl) Update(project *entity.Project) {
biz.ErrIsNil(model.UpdateById(project), "更新项目信息")
}
func (p *projectRepoImpl) Delete(id uint64) {
model.DeleteById(new(entity.Project), id)
}

View File

@@ -1,30 +0,0 @@
package persistence
import (
"mayfly-go/internal/project/domain/entity"
"mayfly-go/internal/project/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
)
type projectEnvRepoImpl struct{}
func newProjectEnvRepo() repository.ProjectEnv {
return new(projectEnvRepoImpl)
}
func (p *projectEnvRepoImpl) ListEnv(condition *entity.ProjectEnv, toEntity interface{}, orderBy ...string) {
model.ListByOrder(condition, toEntity, orderBy...)
}
func (p *projectEnvRepoImpl) Save(entity *entity.ProjectEnv) {
biz.ErrIsNilAppendErr(model.Insert(entity), "保存环境失败:%s")
}
func (p *projectEnvRepoImpl) DeleteEnvs(projectId uint64) {
model.DeleteByCondition(&entity.ProjectEnv{ProjectId: projectId})
}
func (p *projectEnvRepoImpl) DeleteEnv(envId uint64) {
model.DeleteById(new(entity.ProjectEnv), envId)
}

View File

@@ -1,38 +0,0 @@
package persistence
import (
"mayfly-go/internal/project/domain/entity"
"mayfly-go/internal/project/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
)
type projectMemberRepoImpl struct{}
func newProjectMemberRepo() repository.ProjectMemeber {
return new(projectMemberRepoImpl)
}
func (p *projectMemberRepoImpl) ListMemeber(condition *entity.ProjectMember, toEntity interface{}, orderBy ...string) {
model.ListByOrder(condition, toEntity, orderBy...)
}
func (p *projectMemberRepoImpl) Save(pm *entity.ProjectMember) {
biz.ErrIsNilAppendErr(model.Insert(pm), "保存项目成员失败:%s")
}
func (p *projectMemberRepoImpl) GetPageList(condition *entity.ProjectMember, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity, orderBy...)
}
func (p *projectMemberRepoImpl) DeleteByPidMid(projectId, accountId uint64) {
model.DeleteByCondition(&entity.ProjectMember{ProjectId: projectId, AccountId: accountId})
}
func (p *projectMemberRepoImpl) DeleteMems(projectId uint64) {
model.DeleteByCondition(&entity.ProjectMember{ProjectId: projectId})
}
func (p *projectMemberRepoImpl) IsExist(projectId, accountId uint64) bool {
return model.CountBy(&entity.ProjectMember{ProjectId: projectId, AccountId: accountId}) > 0
}

View File

@@ -1,90 +0,0 @@
package router
import (
"mayfly-go/internal/project/api"
projectapp "mayfly-go/internal/project/application"
sysapp "mayfly-go/internal/sys/application"
"mayfly-go/pkg/ctx"
"github.com/gin-gonic/gin"
)
func InitProjectRouter(router *gin.RouterGroup) {
m := &api.Project{
ProjectApp: projectapp.GetProjectApp(),
AccountApp: sysapp.GetAccountApp()}
project := router.Group("/projects")
{
router.GET("/accounts/projects", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(m.GetProjectsByLoginAccount)
})
// 获取项目列表
project.GET("", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(m.GetProjects)
})
saveProjectLog := ctx.NewLogInfo("保存项目信息").WithSave(true)
savePP := ctx.NewPermission("project:save")
// 保存项目下的环境信息
project.POST("", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(saveProjectLog).
WithRequiredPermission(savePP).
Handle(m.SaveProject)
})
delProjectLog := ctx.NewLogInfo("删除项目信息").WithSave(true)
delPP := ctx.NewPermission("project:del")
// 删除项目
project.DELETE("", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(delProjectLog).
WithRequiredPermission(delPP).
Handle(m.DelProject)
})
// 获取项目下的环境信息列表
project.GET("/:projectId/envs", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(m.GetProjectEnvs)
})
saveProjectEnvLog := ctx.NewLogInfo("新增项目环境信息").WithSave(true)
savePeP := ctx.NewPermission("project:env:add")
// 保存项目下的环境信息
project.POST("/:projectId/envs", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(saveProjectEnvLog).
WithRequiredPermission(savePeP).
Handle(m.SaveProjectEnvs)
})
delProjectEnvLog := ctx.NewLogInfo("删除项目环境信息").WithSave(true)
project.DELETE("/envs", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(delProjectEnvLog).
WithRequiredPermission(delPP).
Handle(m.DelProjectEnv)
})
// 获取项目下的成员信息列表
project.GET("/:projectId/members", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(m.GetProjectMembers)
})
// 保存项目成员
saveProjectMemLog := ctx.NewLogInfo("新增项目成员").WithSave(true)
savePmP := ctx.NewPermission("project:member:add")
project.POST("/:projectId/members", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(saveProjectMemLog).
WithRequiredPermission(savePmP).
Handle(m.SaveProjectMember)
})
// 删除项目成员
delProjectMemLog := ctx.NewLogInfo("删除项目成员").WithSave(true)
savePmdP := ctx.NewPermission("project:member:del")
project.DELETE("/:projectId/members/:accountId", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(delProjectMemLog).
WithRequiredPermission(savePmdP).
Handle(m.DelProjectMember)
})
}
}

View File

@@ -2,16 +2,15 @@ package form
type Redis struct {
Id uint64
Name string `json:"name"`
Host string `binding:"required" json:"host"`
Password string `json:"password"`
Mode string `json:"mode"`
Db string `json:"db"`
EnableSshTunnel int8 `json:"enableSshTunnel"` // 是否启用ssh隧道
SshTunnelMachineId uint64 `json:"sshTunnelMachineId"` // ssh隧道机器id
ProjectId uint64 `binding:"required" json:"projectId"`
Project string `json:"project"`
Env string `json:"env"`
EnvId uint64 `binding:"required" json:"envId"`
TagId uint64 `binding:"required" json:"tagId"`
TagPath string `json:"tagPath"`
Remark string `json:"remark"`
}

View File

@@ -2,14 +2,15 @@ package api
import (
"context"
projectapp "mayfly-go/internal/project/application"
"mayfly-go/internal/redis/api/form"
"mayfly-go/internal/redis/api/vo"
"mayfly-go/internal/redis/application"
"mayfly-go/internal/redis/domain/entity"
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/ctx"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils"
"strconv"
"strings"
@@ -20,17 +21,22 @@ import (
)
type Redis struct {
RedisApp application.Redis
ProjectApp projectapp.Project
RedisApp application.Redis
TagApp tagapp.TagTree
}
func (r *Redis) RedisList(rc *ctx.ReqCtx) {
g := rc.GinCtx
m := &entity.Redis{EnvId: uint64(ginx.QueryInt(g, "envId", 0)),
ProjectId: uint64(ginx.QueryInt(g, "projectId", 0)),
condition := new(entity.RedisQuery)
condition.TagPathLike = rc.GinCtx.Query("tagPath")
// 不存在可访问标签id即没有可操作数据
tagIds := r.TagApp.ListTagIdByAccountId(rc.LoginAccount.Id)
if len(tagIds) == 0 {
rc.ResData = model.EmptyPageResult()
return
}
m.CreatorId = rc.LoginAccount.Id
rc.ResData = r.RedisApp.GetPageList(m, ginx.GetPageParam(rc.GinCtx), new([]vo.Redis))
condition.TagIds = tagIds
rc.ResData = r.RedisApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]vo.Redis))
}
func (r *Redis) Save(rc *ctx.ReqCtx) {
@@ -184,7 +190,7 @@ func (r *Redis) ClusterInfo(rc *ctx.ReqCtx) {
func (r *Redis) Scan(rc *ctx.ReqCtx) {
g := rc.GinCtx
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), ginx.PathParamInt(g, "db"))
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
biz.ErrIsNilAppendErr(r.TagApp.CanAccess(rc.LoginAccount.Id, ri.TagPath), "%s")
form := &form.RedisScanForm{}
ginx.BindJsonAndValid(rc.GinCtx, form)
@@ -263,7 +269,7 @@ func (r *Redis) DeleteKey(rc *ctx.ReqCtx) {
biz.NotEmpty(key, "key不能为空")
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), ginx.PathParamInt(g, "db"))
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
biz.ErrIsNilAppendErr(r.TagApp.CanAccess(rc.LoginAccount.Id, ri.TagPath), "%s")
rc.ReqParam = key
ri.GetCmdable().Del(context.Background(), key)
@@ -275,7 +281,7 @@ func (r *Redis) checkKey(rc *ctx.ReqCtx) (*application.RedisInstance, string) {
biz.NotEmpty(key, "key不能为空")
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), ginx.PathParamInt(g, "db"))
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
biz.ErrIsNilAppendErr(r.TagApp.CanAccess(rc.LoginAccount.Id, ri.TagPath), "%s")
return ri, key
}
@@ -293,7 +299,7 @@ func (r *Redis) SetStringValue(rc *ctx.ReqCtx) {
ginx.BindJsonAndValid(g, keyValue)
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), ginx.PathParamInt(g, "db"))
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
biz.ErrIsNilAppendErr(r.TagApp.CanAccess(rc.LoginAccount.Id, ri.TagPath), "%s")
str, err := ri.GetCmdable().Set(context.TODO(), keyValue.Key, keyValue.Value, time.Second*time.Duration(keyValue.Timed)).Result()
biz.ErrIsNilAppendErr(err, "保存字符串值失败: %s")
@@ -345,7 +351,7 @@ func (r *Redis) SetHashValue(rc *ctx.ReqCtx) {
ginx.BindJsonAndValid(g, hashValue)
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), ginx.PathParamInt(g, "db"))
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
biz.ErrIsNilAppendErr(r.TagApp.CanAccess(rc.LoginAccount.Id, ri.TagPath), "%s")
cmd := ri.GetCmdable()
key := hashValue.Key
@@ -372,7 +378,7 @@ func (r *Redis) SetSetValue(rc *ctx.ReqCtx) {
ginx.BindJsonAndValid(g, keyvalue)
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), ginx.PathParamInt(g, "db"))
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
biz.ErrIsNilAppendErr(r.TagApp.CanAccess(rc.LoginAccount.Id, ri.TagPath), "%s")
cmd := ri.GetCmdable()
key := keyvalue.Key
@@ -411,7 +417,7 @@ func (r *Redis) SaveListValue(rc *ctx.ReqCtx) {
ginx.BindJsonAndValid(g, listValue)
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), ginx.PathParamInt(g, "db"))
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
biz.ErrIsNilAppendErr(r.TagApp.CanAccess(rc.LoginAccount.Id, ri.TagPath), "%s")
cmd := ri.GetCmdable()
key := listValue.Key
@@ -431,7 +437,7 @@ func (r *Redis) SetListValue(rc *ctx.ReqCtx) {
ginx.BindJsonAndValid(g, listSetValue)
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), ginx.PathParamInt(g, "db"))
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
biz.ErrIsNilAppendErr(r.TagApp.CanAccess(rc.LoginAccount.Id, ri.TagPath), "%s")
_, err := ri.GetCmdable().LSet(context.TODO(), listSetValue.Key, listSetValue.Index, listSetValue.Value).Result()
biz.ErrIsNilAppendErr(err, "list set失败: %s")

View File

@@ -3,8 +3,8 @@ package vo
import "time"
type Redis struct {
Id *int64 `json:"id"`
// Name *string `json:"name"`
Id *int64 `json:"id"`
Name *string `json:"name"`
Host *string `json:"host"`
Db string `json:"db"`
ProjectId *int64 `json:"projectId"`
@@ -13,8 +13,8 @@ type Redis struct {
EnableSshTunnel *int8 `json:"enableSshTunnel"` // 是否启用ssh隧道
SshTunnelMachineId *uint64 `json:"sshTunnelMachineId"` // ssh隧道机器id
Remark *string `json:"remark"`
Env *string `json:"env"`
EnvId *int64 `json:"envId"`
TagId *uint64 `json:"tagId"`
TagPath *string `json:"tagPath"`
CreateTime *time.Time `json:"createTime"`
Creator *string `json:"creator"`
CreatorId *int64 `json:"creatorId"`

View File

@@ -23,9 +23,9 @@ import (
type Redis interface {
// 分页获取机器脚本信息列表
GetPageList(condition *entity.Redis, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
Count(condition *entity.Redis) int64
Count(condition *entity.RedisQuery) int64
// 根据id获取
GetById(id uint64, cols ...string) *entity.Redis
@@ -55,11 +55,11 @@ type redisAppImpl struct {
}
// 分页获取机器脚本信息列表
func (r *redisAppImpl) GetPageList(condition *entity.Redis, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
func (r *redisAppImpl) GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return r.redisRepo.GetRedisList(condition, pageParam, toEntity, orderBy...)
}
func (r *redisAppImpl) Count(condition *entity.Redis) int64 {
func (r *redisAppImpl) Count(condition *entity.RedisQuery) int64 {
return r.redisRepo.Count(condition)
}
@@ -172,7 +172,7 @@ func getRedisCacheKey(id uint64, db int) string {
}
func getRedisCient(re *entity.Redis, db int) *RedisInstance {
ri := &RedisInstance{Id: getRedisCacheKey(re.Id, db), ProjectId: re.ProjectId, Mode: re.Mode}
ri := &RedisInstance{Id: getRedisCacheKey(re.Id, db), TagPath: re.TagPath, Mode: re.Mode}
redisOptions := &redis.Options{
Addr: re.Host,
@@ -191,7 +191,7 @@ func getRedisCient(re *entity.Redis, db int) *RedisInstance {
}
func getRedisClusterClient(re *entity.Redis) *RedisInstance {
ri := &RedisInstance{Id: getRedisCacheKey(re.Id, 0), ProjectId: re.ProjectId, Mode: re.Mode}
ri := &RedisInstance{Id: getRedisCacheKey(re.Id, 0), TagPath: re.TagPath, Mode: re.Mode}
redisClusterOptions := &redis.ClusterOptions{
Addrs: strings.Split(re.Host, ","),
@@ -207,7 +207,7 @@ func getRedisClusterClient(re *entity.Redis) *RedisInstance {
}
func getRedisSentinelCient(re *entity.Redis, db int) *RedisInstance {
ri := &RedisInstance{Id: getRedisCacheKey(re.Id, db), ProjectId: re.ProjectId, Mode: re.Mode}
ri := &RedisInstance{Id: getRedisCacheKey(re.Id, db), TagPath: re.TagPath, Mode: re.Mode}
// sentinel模式host为 masterName=host:port,host:port
masterNameAndHosts := strings.Split(re.Host, "=")
sentinelOptions := &redis.FailoverOptions{
@@ -294,7 +294,7 @@ func TestRedisConnection(re *entity.Redis) {
// redis实例
type RedisInstance struct {
Id string
ProjectId uint64
TagPath string
Mode string
Cli *redis.Client
ClusterCli *redis.ClusterClient

View File

@@ -0,0 +1,20 @@
package entity
import "mayfly-go/pkg/model"
type RedisQuery struct {
model.Model
Name string `orm:"column(name)" json:"name"`
Host string `orm:"column(host)" json:"host"`
Mode string `json:"mode"`
Password string `orm:"column(password)" json:"-"`
Db string `orm:"column(database)" json:"db"`
EnableSshTunnel int8 `orm:"column(enable_ssh_tunnel)" json:"enableSshTunnel"` // 是否启用ssh隧道
SshTunnelMachineId uint64 `orm:"column(ssh_tunnel_machine_id)" json:"sshTunnelMachineId"` // ssh隧道机器id
Remark string
TagId uint64
TagIds []uint64
TagPathLike string
}

View File

@@ -8,6 +8,7 @@ import (
type Redis struct {
model.Model
Name string `orm:"column(name)" json:"name"`
Host string `orm:"column(host)" json:"host"`
Mode string `json:"mode"`
Password string `orm:"column(password)" json:"-"`
@@ -15,10 +16,8 @@ type Redis struct {
EnableSshTunnel int8 `orm:"column(enable_ssh_tunnel)" json:"enableSshTunnel"` // 是否启用ssh隧道
SshTunnelMachineId uint64 `orm:"column(ssh_tunnel_machine_id)" json:"sshTunnelMachineId"` // ssh隧道机器id
Remark string
ProjectId uint64
Project string
EnvId uint64
Env string
TagId uint64
TagPath string
}
const (

View File

@@ -7,9 +7,9 @@ import (
type Redis interface {
// 分页获取机器信息列表
GetRedisList(condition *entity.Redis, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
GetRedisList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
Count(condition *entity.Redis) int64
Count(condition *entity.RedisQuery) int64
// 根据id获取
GetById(id uint64, cols ...string) *entity.Redis

View File

@@ -6,6 +6,8 @@ import (
"mayfly-go/internal/redis/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils"
"strings"
)
type redisRepoImpl struct{}
@@ -15,27 +17,32 @@ func newRedisRepo() repository.Redis {
}
// 分页获取机器信息列表
func (r *redisRepoImpl) GetRedisList(condition *entity.Redis, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
sql := "SELECT d.* FROM t_redis d JOIN t_project_member pm ON d.project_id = pm.project_id WHERE 1 = 1 "
if condition.CreatorId != 0 {
// 使用创建者id模拟项目成员id
sql = fmt.Sprintf("%s AND pm.account_id = %d", sql, condition.CreatorId)
}
if condition.ProjectId != 0 {
sql = fmt.Sprintf("%s AND d.project_id = %d", sql, condition.ProjectId)
}
if condition.EnvId != 0 {
sql = fmt.Sprintf("%s AND d.env_id = %d", sql, condition.EnvId)
}
func (r *redisRepoImpl) GetRedisList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
sql := "SELECT d.* FROM t_redis d WHERE 1=1 "
if condition.Host != "" {
sql = sql + " AND d.host LIKE '%" + condition.Host + "%'"
}
if len(condition.TagIds) > 0 {
sql = sql + " AND d.tag_id IN " + fmt.Sprintf("(%s)", strings.Join(utils.NumberArr2StrArr(condition.TagIds), ","))
}
if condition.TagPathLike != "" {
sql = sql + " AND d.tag_path LIKE '" + condition.TagPathLike + "%'"
}
sql = sql + " ORDER BY d.create_time DESC"
return model.GetPageBySql(sql, pageParam, toEntity)
}
func (r *redisRepoImpl) Count(condition *entity.Redis) int64 {
return model.CountBy(condition)
func (r *redisRepoImpl) Count(condition *entity.RedisQuery) int64 {
where := make(map[string]interface{})
if len(condition.TagIds) > 0 {
where["tag_id"] = condition.TagIds
}
if condition.TagId != 0 {
where["tag_id"] = condition.TagId
}
return model.CountByMap(new(entity.Redis), where)
}
// 根据id获取

View File

@@ -1,9 +1,9 @@
package router
import (
projectapp "mayfly-go/internal/project/application"
"mayfly-go/internal/redis/api"
"mayfly-go/internal/redis/application"
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/ctx"
"github.com/gin-gonic/gin"
@@ -13,8 +13,8 @@ func InitRedisRouter(router *gin.RouterGroup) {
redis := router.Group("redis")
{
rs := &api.Redis{
RedisApp: application.GetRedisApp(),
ProjectApp: projectapp.GetProjectApp(),
RedisApp: application.GetRedisApp(),
TagApp: tagapp.GetTagTreeApp(),
}
// 获取redis list

View File

@@ -2,8 +2,9 @@ package form
type ConfigForm struct {
Id int
Name string `binding:"required"`
Key string `binding:"required"`
Name string
Key string
Params string
Value string
Remark string `json:"remark"`
}

View File

@@ -1,6 +1,9 @@
package entity
import "mayfly-go/pkg/model"
import (
"encoding/json"
"mayfly-go/pkg/model"
)
const (
ConfigKeyUseLoginCaptcha string = "UseLoginCaptcha" // 是否使用登录验证码
@@ -10,6 +13,7 @@ type Config struct {
model.Model
Name string `json:"name"` // 配置名
Key string `json:"key"` // 配置key
Params string `json:"params"`
Value string `json:"value"`
Remark string `json:"remark"`
}
@@ -27,3 +31,13 @@ func (c *Config) BoolValue(defaultValue bool) bool {
}
return c.Value == "1"
}
// 值返回json map
func (c *Config) GetJsonMap() map[string]string {
var res map[string]string
if c.Id == 0 || c.Value == "" {
return res
}
_ = json.Unmarshal([]byte(c.Value), &res)
return res
}

View File

@@ -14,7 +14,7 @@ func newConfigRepo() repository.Config {
}
func (m *configRepoImpl) GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity)
return model.GetPage(pageParam, condition, condition, toEntity)
}
func (m *configRepoImpl) Insert(config *entity.Config) {

View File

@@ -14,7 +14,7 @@ func newMsgRepo() repository.Msg {
}
func (m *msgRepoImpl) GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity)
return model.GetPage(pageParam, condition, condition, toEntity)
}
func (m *msgRepoImpl) Insert(account *entity.Msg) {

View File

@@ -14,7 +14,7 @@ func newRoleRepo() repository.Role {
}
func (m *roleRepoImpl) GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity, orderBy...)
return model.GetPage(pageParam, condition, condition, toEntity, orderBy...)
}
func (m *roleRepoImpl) Delete(id uint64) {

View File

@@ -13,7 +13,7 @@ func newSyslogRepo() repository.Syslog {
}
func (m *syslogRepoImpl) GetPageList(condition *entity.Syslog, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity, orderBy...)
return model.GetPage(pageParam, condition, condition, toEntity, orderBy...)
}
func (m *syslogRepoImpl) Insert(syslog *entity.Syslog) {

View File

@@ -0,0 +1,6 @@
package form
type TagTreeTeam struct {
TeamId uint64 `json:"teamId"`
TagIds []uint64 `json:"tagIds"`
}

View File

@@ -0,0 +1,39 @@
package api
import (
"fmt"
"mayfly-go/internal/tag/api/vo"
"mayfly-go/internal/tag/application"
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/ctx"
"mayfly-go/pkg/ginx"
)
type TagTree struct {
TagTreeApp application.TagTree
}
func (p *TagTree) GetAccountTags(rc *ctx.ReqCtx) {
rc.ResData = p.TagTreeApp.ListTagByAccountId(rc.LoginAccount.Id)
}
func (p *TagTree) GetTagTree(rc *ctx.ReqCtx) {
var tagTrees vo.TagTreeVOS
p.TagTreeApp.ListByQuery(new(entity.TagTreeQuery), &tagTrees)
rc.ResData = tagTrees.ToTrees(0)
}
func (p *TagTree) SaveTagTree(rc *ctx.ReqCtx) {
projectTree := &entity.TagTree{}
ginx.BindJsonAndValid(rc.GinCtx, projectTree)
loginAccount := rc.LoginAccount
projectTree.SetBaseInfo(loginAccount)
p.TagTreeApp.Save(projectTree)
rc.ReqParam = fmt.Sprintf("tagTreeId: %d, tagName: %s, codePath: %s", projectTree.Id, projectTree.Name, projectTree.CodePath)
}
func (p *TagTree) DelTagTree(rc *ctx.ReqCtx) {
p.TagTreeApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id")))
}

View File

@@ -0,0 +1,133 @@
package api
import (
"fmt"
sys_applicaiton "mayfly-go/internal/sys/application"
sys_entity "mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/tag/api/form"
"mayfly-go/internal/tag/application"
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/ctx"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/utils"
)
type Team struct {
TeamApp application.Team
TagApp application.TagTree
AccountApp sys_applicaiton.Account
}
func (p *Team) GetTeams(rc *ctx.ReqCtx) {
teams := &[]entity.Team{}
rc.ResData = p.TeamApp.GetPageList(&entity.Team{}, ginx.GetPageParam(rc.GinCtx), teams)
}
func (p *Team) SaveTeam(rc *ctx.ReqCtx) {
team := &entity.Team{}
ginx.BindJsonAndValid(rc.GinCtx, team)
isAdd := team.Id == 0
loginAccount := rc.LoginAccount
team.SetBaseInfo(loginAccount)
p.TeamApp.Save(team)
// 如果是新增团队则默认将自己加入该团队
if isAdd {
teamMem := &entity.TeamMember{}
teamMem.AccountId = loginAccount.Id
teamMem.Username = loginAccount.Username
teamMem.TeamId = team.Id
teamMem.SetBaseInfo(rc.LoginAccount)
p.TeamApp.SaveMember(teamMem)
}
}
func (p *Team) DelTeam(rc *ctx.ReqCtx) {
p.TeamApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id")))
}
// 获取团队的成员信息
func (p *Team) GetTeamMembers(rc *ctx.ReqCtx) {
teamMems := &[]entity.TeamMember{}
rc.ResData = p.TeamApp.GetMemberPage(&entity.TeamMember{TeamId: uint64(ginx.PathParamInt(rc.GinCtx, "id"))},
ginx.GetPageParam(rc.GinCtx), teamMems)
}
// 保存团队信息
func (p *Team) SaveTeamMember(rc *ctx.ReqCtx) {
projectMem := &entity.TeamMember{}
ginx.BindJsonAndValid(rc.GinCtx, projectMem)
rc.ReqParam = fmt.Sprintf("projectId: %d, username: %s", projectMem.TeamId, projectMem.Username)
// 校验账号并赋值username
account := &sys_entity.Account{}
account.Id = projectMem.AccountId
biz.ErrIsNil(p.AccountApp.GetAccount(account, "Id", "Username"), "账号不存在")
projectMem.Username = account.Username
projectMem.SetBaseInfo(rc.LoginAccount)
p.TeamApp.SaveMember(projectMem)
}
// 删除团队成员
func (p *Team) DelTeamMember(rc *ctx.ReqCtx) {
g := rc.GinCtx
tid := ginx.PathParamInt(g, "id")
aid := ginx.PathParamInt(g, "accountId")
rc.ReqParam = fmt.Sprintf("teamId: %d, accountId: %d", tid, aid)
p.TeamApp.DeleteMember(uint64(tid), uint64(aid))
}
// 获取团队关联的标签id
func (p *Team) GetTagIds(rc *ctx.ReqCtx) {
rc.ResData = p.TeamApp.ListTagIds(uint64(ginx.PathParamInt(rc.GinCtx, "id")))
}
// 保存团队关联标签信息
func (p *Team) SaveTags(rc *ctx.ReqCtx) {
g := rc.GinCtx
var form form.TagTreeTeam
ginx.BindJsonAndValid(g, &form)
teamId := form.TeamId
// 将[]uint64转为[]interface{}
oIds := p.TeamApp.ListTagIds(teamId)
var oldIds []interface{}
for _, v := range oIds {
oldIds = append(oldIds, v)
}
var newIds []interface{}
for _, v := range form.TagIds {
newIds = append(newIds, v)
}
// 比较新旧两合集
addIds, delIds, _ := utils.ArrayCompare(newIds, oldIds, func(i1, i2 interface{}) bool {
return i1.(uint64) == i2.(uint64)
})
loginAccount := rc.LoginAccount
for _, v := range addIds {
tagId := v.(uint64)
tag := p.TagApp.GetById(tagId)
biz.NotNil(tag, "存在非法标签id")
ptt := &entity.TagTreeTeam{TeamId: teamId, TagId: tagId, TagPath: tag.CodePath}
ptt.SetBaseInfo(loginAccount)
p.TeamApp.SaveTag(ptt)
}
for _, v := range delIds {
p.TeamApp.DeleteTag(teamId, v.(uint64))
}
rc.ReqParam = form
}

View File

@@ -0,0 +1,50 @@
package vo
import "time"
type TagTreeVO struct {
Id int `json:"id"`
Pid int `json:"pid"`
Name string `json:"name"`
Code string `json:"code"`
CodePath string `json:"codePath"`
Remark string `json:"remark"`
Creator string `json:"creator"`
CreateTime time.Time `json:"createTime"`
Modifier string `json:"modifier"`
UpdateTime time.Time `json:"updateTime"`
}
type TagTreeVOS []TagTreeVO
type TagTreeItem struct {
TagTreeVO
Children []TagTreeItem `json:"children"`
}
func (m *TagTreeVOS) ToTrees(pid int) []TagTreeItem {
var resourceTree []TagTreeItem
list := m.findChildren(pid)
if len(list) == 0 {
return resourceTree
}
for _, v := range list {
Children := m.ToTrees(int(v.Id))
resourceTree = append(resourceTree, TagTreeItem{v, Children})
}
return resourceTree
}
func (m *TagTreeVOS) findChildren(pid int) []TagTreeVO {
child := []TagTreeVO{}
for _, v := range *m {
if v.Pid == pid {
child = append(child, v)
}
}
return child
}

View File

@@ -0,0 +1,34 @@
package application
import (
dbapp "mayfly-go/internal/db/application"
machineapp "mayfly-go/internal/machine/application"
mongoapp "mayfly-go/internal/mongo/application"
redisapp "mayfly-go/internal/redis/application"
"mayfly-go/internal/tag/infrastructure/persistence"
)
var (
tagTreeApp TagTree = newTagTreeApp(
persistence.GetTagTreeRepo(),
persistence.GetTagTreeTeamRepo(),
machineapp.GetMachineApp(),
redisapp.GetRedisApp(),
dbapp.GetDbApp(),
mongoapp.GetMongoApp(),
)
teamApp Team = newTeamApp(
persistence.GetTeamRepo(),
persistence.GetTeamMemberRepo(),
persistence.GetTagTreeTeamRepo(),
)
)
func GetTagTreeApp() TagTree {
return tagTreeApp
}
func GetTeamApp() Team {
return teamApp
}

View File

@@ -0,0 +1,150 @@
package application
import (
"fmt"
dbapp "mayfly-go/internal/db/application"
dbentity "mayfly-go/internal/db/domain/entity"
machineapp "mayfly-go/internal/machine/application"
machineentity "mayfly-go/internal/machine/domain/entity"
mongoapp "mayfly-go/internal/mongo/application"
mongoentity "mayfly-go/internal/mongo/domain/entity"
redisapp "mayfly-go/internal/redis/application"
redisentity "mayfly-go/internal/redis/domain/entity"
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/pkg/biz"
"strings"
)
type TagTree interface {
ListByQuery(condition *entity.TagTreeQuery, toEntity interface{})
GetById(id uint64) *entity.TagTree
Save(project *entity.TagTree)
Delete(id uint64)
// 获取账号id拥有的可访问的标签id
ListTagIdByAccountId(accountId uint64) []uint64
// 获取以指定tagPath数组开头的所有标签id
ListTagIdByPath(tagPath ...string) []uint64
// 根据账号id获取其可访问标签信息
ListTagByAccountId(accountId uint64) []string
// 账号是否有权限访问该标签关联的资源信息
CanAccess(accountId uint64, tagPath string) error
}
func newTagTreeApp(tagTreeRepo repository.TagTree,
tagTreeTeamRepo repository.TagTreeTeam,
machineApp machineapp.Machine,
redisApp redisapp.Redis,
dbApp dbapp.Db,
mongoApp mongoapp.Mongo) TagTree {
return &tagTreeAppImpl{
tagTreeRepo: tagTreeRepo,
tagTreeTeamRepo: tagTreeTeamRepo,
machineApp: machineApp,
redisApp: redisApp,
dbApp: dbApp,
mongoApp: mongoApp,
}
}
type tagTreeAppImpl struct {
tagTreeRepo repository.TagTree
tagTreeTeamRepo repository.TagTreeTeam
machineApp machineapp.Machine
redisApp redisapp.Redis
mongoApp mongoapp.Mongo
dbApp dbapp.Db
}
func (p *tagTreeAppImpl) Save(tag *entity.TagTree) {
// 新建项目树节点信息
if tag.Id == 0 {
biz.IsTrue(!strings.Contains(tag.Code, entity.CodePathSeparator), "标识符不能包含'/'")
if tag.Pid != 0 {
parentTag := p.tagTreeRepo.SelectById(tag.Pid)
biz.NotNil(parentTag, "父节点不存在")
tag.CodePath = parentTag.CodePath + entity.CodePathSeparator + tag.Code
} else {
tag.CodePath = tag.Code
}
// 判断该路径是否存在
var hasLikeTags []entity.TagTree
p.tagTreeRepo.SelectByCondition(&entity.TagTreeQuery{CodePathLike: tag.CodePath}, &hasLikeTags)
biz.IsTrue(len(hasLikeTags) == 0, "已存在该标签路径开头的标签, 请修改该标识code")
// 校验同级标签是否有以该code为开头的标识符
p.tagTreeRepo.SelectByCondition(&entity.TagTreeQuery{Pid: tag.Pid}, &hasLikeTags)
for _, v := range hasLikeTags {
if strings.HasPrefix(tag.Code, v.Code) {
panic(biz.NewBizErr(fmt.Sprintf("同级标签下的[%s]与[%s]存在相似开头字符, 请修改该标识code", v.Code, tag.Code)))
}
}
p.tagTreeRepo.Insert(tag)
return
}
// 防止误传导致被更新
tag.Code = ""
tag.CodePath = ""
p.tagTreeRepo.UpdateById(tag)
}
func (p *tagTreeAppImpl) ListByQuery(condition *entity.TagTreeQuery, toEntity interface{}) {
p.tagTreeRepo.SelectByCondition(condition, toEntity)
}
func (p *tagTreeAppImpl) GetById(tagId uint64) *entity.TagTree {
return p.tagTreeRepo.SelectById(tagId)
}
func (p *tagTreeAppImpl) ListTagIdByAccountId(accountId uint64) []uint64 {
// 获取该账号可操作的标签路径
return p.ListTagIdByPath(p.ListTagByAccountId(accountId)...)
}
func (p *tagTreeAppImpl) ListTagIdByPath(tagPaths ...string) []uint64 {
tagIds := make([]uint64, 0)
if len(tagPaths) == 0 {
return tagIds
}
var tags []entity.TagTree
p.tagTreeRepo.SelectByCondition(&entity.TagTreeQuery{CodePathLikes: tagPaths}, &tags)
for _, v := range tags {
tagIds = append(tagIds, v.Id)
}
return tagIds
}
func (p *tagTreeAppImpl) ListTagByAccountId(accountId uint64) []string {
return p.tagTreeTeamRepo.SelectTagPathsByAccountId(accountId)
}
func (p *tagTreeAppImpl) CanAccess(accountId uint64, tagPath string) error {
tagPaths := p.ListTagByAccountId(accountId)
// 判断该资源标签是否为该账号拥有的标签或其子标签
for _, v := range tagPaths {
if strings.HasPrefix(tagPath, v) {
return nil
}
}
return biz.NewBizErr("您无权操作该资源")
}
func (p *tagTreeAppImpl) Delete(id uint64) {
biz.IsTrue(p.machineApp.Count(&machineentity.MachineQuery{TagId: id}) == 0, "请先删除该项目关联的机器信息")
biz.IsTrue(p.redisApp.Count(&redisentity.RedisQuery{TagId: id}) == 0, "请先删除该项目关联的redis信息")
biz.IsTrue(p.dbApp.Count(&dbentity.DbQuery{TagId: id}) == 0, "请先删除该项目关联的数据库信息")
biz.IsTrue(p.mongoApp.Count(&mongoentity.MongoQuery{TagId: id}) == 0, "请先删除该项目关联的Mongo信息")
p.tagTreeRepo.Delete(id)
// 删除该标签关联的团队信息
p.tagTreeTeamRepo.DeleteBy(&entity.TagTreeTeam{TagId: id})
}

View File

@@ -0,0 +1,111 @@
package application
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
)
type Team interface {
// 分页获取项目团队信息列表
GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
Save(projectTeam *entity.Team)
Delete(id uint64)
//--------------- 团队成员相关接口 ---------------
GetMemberPage(condition *entity.TeamMember, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
SaveMember(projectTeamMember *entity.TeamMember)
DeleteMember(teamId, accountId uint64)
// 账号是否有权限访问该项目关联的资源信息
// CanAccess(accountId, projectId uint64) error
//--------------- 关联项目相关接口 ---------------
ListTagIds(teamId uint64) []uint64
SaveTag(tagTeam *entity.TagTreeTeam)
DeleteTag(teamId, projectId uint64)
}
func newTeamApp(projectTeamRepo repository.Team,
projectTeamMemberRepo repository.TeamMember,
tagTreeTeamRepo repository.TagTreeTeam,
) Team {
return &projectTeamAppImpl{
projectTeamRepo: projectTeamRepo,
projectTeamMemberRepo: projectTeamMemberRepo,
tagTreeTeamRepo: tagTreeTeamRepo,
}
}
type projectTeamAppImpl struct {
projectTeamRepo repository.Team
projectTeamMemberRepo repository.TeamMember
tagTreeTeamRepo repository.TagTreeTeam
}
func (p *projectTeamAppImpl) GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return p.projectTeamRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
func (p *projectTeamAppImpl) Save(projectTeam *entity.Team) {
if projectTeam.Id == 0 {
p.projectTeamRepo.Insert(projectTeam)
} else {
p.projectTeamRepo.UpdateById(projectTeam)
}
}
func (p *projectTeamAppImpl) Delete(id uint64) {
p.projectTeamRepo.Delete(id)
p.projectTeamMemberRepo.DeleteBy(&entity.TeamMember{TeamId: id})
}
// --------------- 团队成员相关接口 ---------------
func (p *projectTeamAppImpl) GetMemberPage(condition *entity.TeamMember, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return p.projectTeamMemberRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
// 保存团队成员信息
func (p *projectTeamAppImpl) SaveMember(projectTeamMember *entity.TeamMember) {
projectTeamMember.Id = 0
biz.IsTrue(!p.projectTeamMemberRepo.IsExist(projectTeamMember.TeamId, projectTeamMember.AccountId), "该成员已存在")
p.projectTeamMemberRepo.Save(projectTeamMember)
}
// 删除团队成员信息
func (p *projectTeamAppImpl) DeleteMember(teamId, accountId uint64) {
p.projectTeamMemberRepo.DeleteBy(&entity.TeamMember{TeamId: teamId, AccountId: accountId})
}
//--------------- 关联项目相关接口 ---------------
func (p *projectTeamAppImpl) ListTagIds(teamId uint64) []uint64 {
projects := &[]entity.TagTreeTeam{}
p.tagTreeTeamRepo.ListProject(&entity.TagTreeTeam{TeamId: teamId}, projects)
ids := make([]uint64, 0)
for _, v := range *projects {
ids = append(ids, v.TagId)
}
return ids
}
// 保存关联项目信息
func (p *projectTeamAppImpl) SaveTag(projectTreeTeam *entity.TagTreeTeam) {
projectTreeTeam.Id = 0
p.tagTreeTeamRepo.Save(projectTreeTeam)
}
// 删除关联项目信息
func (p *projectTeamAppImpl) DeleteTag(teamId, tagId uint64) {
p.tagTreeTeamRepo.DeleteBy(&entity.TagTreeTeam{TeamId: teamId, TagId: tagId})
}

View File

@@ -0,0 +1,15 @@
package entity
import "mayfly-go/pkg/model"
type TagTreeQuery struct {
model.Model
Pid uint64
Code string `json:"code"` // 标识
CodePath string `json:"codePath"` // 标识路径
Name string `json:"name"` // 名称
CodePathLike string // 标识符路径模糊查询
CodePathLikes []string
}

View File

@@ -0,0 +1,27 @@
package entity
import (
"mayfly-go/pkg/model"
"strings"
)
// 标签树
type TagTree struct {
model.Model
Pid uint64 `json:"pid"`
Code string `json:"code"` // 标识
CodePath string `json:"codePath"` // 标识路径
Name string `json:"name"` // 名称
Remark string `json:"remark"` // 备注说明
}
const (
// 标识路径分隔符
CodePathSeparator = "/"
)
// 获取根路径信息
func (pt *TagTree) GetRootCode() string {
return strings.Split(pt.CodePath, CodePathSeparator)[0]
}

View File

@@ -0,0 +1,12 @@
package entity
import "mayfly-go/pkg/model"
// 标签树与团队关联信息
type TagTreeTeam struct {
model.Model
TagId uint64 `json:"tagId"`
TagPath string `json:"tagPath"`
TeamId uint64 `json:"teamId"`
}

View File

@@ -2,9 +2,10 @@ package entity
import "mayfly-go/pkg/model"
// 项目
type Project struct {
// 团队信息
type Team struct {
model.Model
Name string `json:"name"` // 项目名
Name string `json:"name"` // 名称
Remark string `json:"remark"` // 备注说明
}

View File

@@ -0,0 +1,12 @@
package entity
import "mayfly-go/pkg/model"
// 团队成员关联信息
type TeamMember struct {
model.Model
TeamId uint64 `json:"teamId"`
AccountId uint64 `json:"accountId"`
Username string `json:"username"`
}

View File

@@ -0,0 +1,21 @@
package repository
import (
"mayfly-go/internal/tag/domain/entity"
)
type TagTree interface {
// 根据条件查询
SelectByCondition(condition *entity.TagTreeQuery, toEntity interface{}, 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)
}

View File

@@ -0,0 +1,15 @@
package repository
import "mayfly-go/internal/tag/domain/entity"
type TagTreeTeam interface {
// 获取团队项目信息列表
ListProject(condition *entity.TagTreeTeam, toEntity interface{}, orderBy ...string)
Save(mp *entity.TagTreeTeam)
DeleteBy(condition *entity.TagTreeTeam)
SelectTagPathsByAccountId(accountId uint64) []string
}

View File

@@ -0,0 +1,18 @@
package repository
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/model"
)
type Team interface {
GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
Insert(p *entity.Team)
UpdateById(p *entity.Team)
Delete(id uint64)
DeleteBy(p *entity.Team)
}

View File

@@ -0,0 +1,21 @@
package repository
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/model"
)
type TeamMember interface {
// 获取项目成员列表
ListMemeber(condition *entity.TeamMember, toEntity interface{}, orderBy ...string)
Save(mp *entity.TeamMember)
GetPageList(condition *entity.TeamMember, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
DeleteBy(condition *entity.TeamMember)
// 是否存在指定的团队成员关联信息
IsExist(teamId, accountId uint64) bool
}

View File

@@ -0,0 +1,26 @@
package persistence
import "mayfly-go/internal/tag/domain/repository"
var (
tagTreeRepo repository.TagTree = newTagTreeRepo()
tagTreeTeamRepo repository.TagTreeTeam = newTagTreeTeamRepo()
teamRepo repository.Team = newTeamRepo()
teamMemberRepo repository.TeamMember = newTeamMemberRepo()
)
func GetTagTreeRepo() repository.TagTree {
return tagTreeRepo
}
func GetTagTreeTeamRepo() repository.TagTreeTeam {
return tagTreeTeamRepo
}
func GetTeamRepo() repository.Team {
return teamRepo
}
func GetTeamMemberRepo() repository.TeamMember {
return teamMemberRepo
}

View File

@@ -0,0 +1,68 @@
package persistence
import (
"fmt"
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
)
type tagTreeRepoImpl struct{}
func newTagTreeRepo() repository.TagTree {
return new(tagTreeRepoImpl)
}
func (p *tagTreeRepoImpl) SelectByCondition(condition *entity.TagTreeQuery, toEntity interface{}, orderBy ...string) {
sql := "SELECT p.* FROM t_tag_tree p WHERE 1 = 1 "
if condition.Name != "" {
sql = sql + " AND p.name LIKE '%" + condition.Name + "%'"
}
if condition.CodePath != "" {
sql = fmt.Sprintf("%s AND p.code_path = '%s'", sql, condition.CodePath)
}
if condition.CodePathLike != "" {
sql = fmt.Sprintf("%s AND p.code_path LIKE '%s'", sql, condition.CodePathLike+"%")
}
if condition.Pid != 0 {
sql = fmt.Sprintf("%s AND p.pid = %d ", sql, condition.Pid)
}
if len(condition.CodePathLikes) > 0 {
sql = sql + " AND ("
for i, v := range condition.CodePathLikes {
if i == 0 {
sql = sql + fmt.Sprintf("p.code_path LIKE '%s'", v+"%")
} else {
sql = sql + fmt.Sprintf(" OR p.code_path LIKE '%s'", v+"%")
}
}
sql = sql + ")"
}
sql = sql + " ORDER BY p.pid DESC"
model.GetListBySql2Model(sql, toEntity)
}
func (p *tagTreeRepoImpl) SelectById(id uint64) *entity.TagTree {
pt := new(entity.TagTree)
if err := model.GetById(pt, id); err != nil {
return nil
}
return pt
}
func (a *tagTreeRepoImpl) GetBy(condition *entity.TagTree, cols ...string) error {
return model.GetBy(condition, cols...)
}
func (p *tagTreeRepoImpl) Insert(project *entity.TagTree) {
biz.ErrIsNil(model.Insert(project), "新增项目失败")
}
func (p *tagTreeRepoImpl) UpdateById(project *entity.TagTree) {
biz.ErrIsNil(model.UpdateById(project), "更新项目失败")
}
func (p *tagTreeRepoImpl) Delete(id uint64) {
model.DeleteById(new(entity.TagTree), id)
}

View File

@@ -0,0 +1,32 @@
package persistence
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
)
type tagTreeTeamRepoImpl struct{}
func newTagTreeTeamRepo() repository.TagTreeTeam {
return new(tagTreeTeamRepoImpl)
}
func (p *tagTreeTeamRepoImpl) ListProject(condition *entity.TagTreeTeam, toEntity interface{}, orderBy ...string) {
model.ListByOrder(condition, toEntity, orderBy...)
}
func (p *tagTreeTeamRepoImpl) Save(pm *entity.TagTreeTeam) {
biz.ErrIsNilAppendErr(model.Insert(pm), "保存团队项目信息失败:%s")
}
func (p *tagTreeTeamRepoImpl) DeleteBy(condition *entity.TagTreeTeam) {
model.DeleteByCondition(condition)
}
func (p *tagTreeTeamRepoImpl) SelectTagPathsByAccountId(accountId uint64) []string {
var res []string
model.GetListBySql2Model("SELECT DISTINCT(t1.tag_path) FROM t_tag_tree_team t1 JOIN t_team_member t2 ON t1.team_id = t2.team_id WHERE t2.account_id = ?", &res, accountId)
return res
}

View File

@@ -0,0 +1,34 @@
package persistence
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
)
type teamRepoImpl struct{}
func newTeamRepo() repository.Team {
return new(teamRepoImpl)
}
func (p *teamRepoImpl) GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, condition, toEntity, orderBy...)
}
func (p *teamRepoImpl) Insert(projectTeam *entity.Team) {
biz.ErrIsNil(model.Insert(projectTeam), "新增团队失败")
}
func (p *teamRepoImpl) UpdateById(projectTeam *entity.Team) {
biz.ErrIsNil(model.UpdateById(projectTeam), "更新团队失败")
}
func (p *teamRepoImpl) Delete(id uint64) {
model.DeleteById(new(entity.Team), id)
}
func (p *teamRepoImpl) DeleteBy(projectTeam *entity.Team) {
model.DeleteByCondition(projectTeam)
}

View File

@@ -0,0 +1,34 @@
package persistence
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/model"
)
type teamMemberRepoImpl struct{}
func newTeamMemberRepo() repository.TeamMember {
return new(teamMemberRepoImpl)
}
func (p *teamMemberRepoImpl) ListMemeber(condition *entity.TeamMember, toEntity interface{}, orderBy ...string) {
model.ListByOrder(condition, toEntity, orderBy...)
}
func (p *teamMemberRepoImpl) Save(pm *entity.TeamMember) {
biz.ErrIsNilAppendErr(model.Insert(pm), "保存团队成员失败:%s")
}
func (p *teamMemberRepoImpl) GetPageList(condition *entity.TeamMember, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, condition, toEntity, orderBy...)
}
func (p *teamMemberRepoImpl) DeleteBy(condition *entity.TeamMember) {
model.DeleteByCondition(condition)
}
func (p *teamMemberRepoImpl) IsExist(teamId, accountId uint64) bool {
return model.CountBy(&entity.TeamMember{TeamId: teamId, AccountId: accountId}) > 0
}

View File

@@ -3,5 +3,6 @@ package router
import "github.com/gin-gonic/gin"
func Init(router *gin.RouterGroup) {
InitProjectRouter(router)
InitTagTreeRouter(router)
InitTeamRouter(router)
}

View File

@@ -0,0 +1,46 @@
package router
import (
"mayfly-go/internal/tag/api"
"mayfly-go/internal/tag/application"
"mayfly-go/pkg/ctx"
"github.com/gin-gonic/gin"
)
func InitTagTreeRouter(router *gin.RouterGroup) {
m := &api.TagTree{
TagTreeApp: application.GetTagTreeApp(),
}
project := router.Group("/tag-trees")
{
// 获取标签树列表
project.GET("", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(m.GetTagTree)
})
// 获取登录账号拥有的标签信息
project.GET("account-has", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(m.GetAccountTags)
})
saveProjectTreeLog := ctx.NewLogInfo("保存标签树信息").WithSave(true)
savePP := ctx.NewPermission("tag:save")
// 保存项目树下的环境信息
project.POST("", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(saveProjectTreeLog).
WithRequiredPermission(savePP).
Handle(m.SaveTagTree)
})
delProjectLog := ctx.NewLogInfo("删除标签树信息").WithSave(true)
delPP := ctx.NewPermission("tag:del")
// 删除标签
project.DELETE(":id", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(delProjectLog).
WithRequiredPermission(delPP).
Handle(m.DelTagTree)
})
}
}

View File

@@ -0,0 +1,81 @@
package router
import (
sysapp "mayfly-go/internal/sys/application"
"mayfly-go/internal/tag/api"
"mayfly-go/internal/tag/application"
"mayfly-go/pkg/ctx"
"github.com/gin-gonic/gin"
)
func InitTeamRouter(router *gin.RouterGroup) {
m := &api.Team{
TeamApp: application.GetTeamApp(),
TagApp: application.GetTagTreeApp(),
AccountApp: sysapp.GetAccountApp(),
}
project := router.Group("/teams")
{
// 获取团队列表
project.GET("", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(m.GetTeams)
})
saveProjectTeamLog := ctx.NewLogInfo("保存项目团队信息").WithSave(true)
savePP := ctx.NewPermission("team:save")
// 保存项目团队信息
project.POST("", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(saveProjectTeamLog).
WithRequiredPermission(savePP).
Handle(m.SaveTeam)
})
delProjectTeamLog := ctx.NewLogInfo("删除项目团队信息").WithSave(true)
delPP := ctx.NewPermission("team:del")
project.DELETE(":id", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(delProjectTeamLog).
WithRequiredPermission(delPP).
Handle(m.DelTeam)
})
// 获取团队的成员信息列表
project.GET("/:id/members", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(m.GetTeamMembers)
})
// 保存团队成员
saveProjectTeamMemLog := ctx.NewLogInfo("新增团队成员").WithSave(true)
savePmP := ctx.NewPermission("team:member:save")
project.POST("/:id/members", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(saveProjectTeamMemLog).
WithRequiredPermission(savePmP).
Handle(m.SaveTeamMember)
})
// 删除团队成员
delProjectTeamMemLog := ctx.NewLogInfo("删除团队成员").WithSave(true)
savePmdP := ctx.NewPermission("team:member:del")
project.DELETE("/:id/members/:accountId", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).WithLog(delProjectTeamMemLog).
WithRequiredPermission(savePmdP).
Handle(m.DelTeamMember)
})
// 获取团队关联的标签id列表
project.GET("/:id/tags", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(m.GetTagIds)
})
// 保存团队标签关联信息
saveTeamTagLog := ctx.NewLogInfo("保存团队标签关联信息").WithSave(true)
saveTeamTagP := ctx.NewPermission("team:tag:save")
project.POST("/:id/tags", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).
WithLog(saveTeamTagLog).
WithRequiredPermission(saveTeamTagP).
Handle(m.SaveTags)
})
}
}

View File

@@ -32,18 +32,17 @@ CREATE TABLE `t_db` (
`network` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`enable_ssh_tunnel` tinyint(2) DEFAULT NULL COMMENT '是否启用ssh隧道',
`ssh_tunnel_machine_id` bigint(20) DEFAULT NULL COMMENT 'ssh隧道的机器id',
`project_id` bigint(20) DEFAULT NULL,
`project` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`env_id` bigint(20) DEFAULT NULL COMMENT '环境id',
`env` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '环境描述',
`remark` varchar(125) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '备注,描述等',
`tag_id` bigint(20) DEFAULT NULL COMMENT '标签id',
`tag_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '标签路径',
`create_time` datetime DEFAULT NULL,
`creator_id` bigint(20) DEFAULT NULL,
`creator` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`modifier_id` bigint(20) DEFAULT NULL,
`modifier` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`)
PRIMARY KEY (`id`),
KEY `idx_path` (`tag_path`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='数据库资源信息表';
-- ----------------------------
@@ -112,10 +111,8 @@ COMMIT;
DROP TABLE IF EXISTS `t_machine`;
CREATE TABLE `t_machine` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`project_id` bigint(20) DEFAULT NULL,
`project_name` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`ip` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`port` int(12) NOT NULL,
`username` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`auth_method` tinyint(2) DEFAULT NULL COMMENT '1.密码登录2.publickey登录',
@@ -125,6 +122,8 @@ CREATE TABLE `t_machine` (
`enable_recorder` tinyint(2) DEFAULT NULL COMMENT '是否启用终端回放记录',
`status` tinyint(2) NOT NULL COMMENT '状态: 1:启用; -1:禁用',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`tag_id` bigint(20) DEFAULT NULL COMMENT '标签id',
`tag_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '标签路径',
`need_monitor` tinyint(2) DEFAULT NULL,
`create_time` datetime NOT NULL,
`creator` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
@@ -132,7 +131,8 @@ CREATE TABLE `t_machine` (
`update_time` datetime NOT NULL,
`modifier` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`modifier_id` bigint(32) DEFAULT NULL,
PRIMARY KEY (`id`)
PRIMARY KEY (`id`),
KEY `idx_path` (`tag_path`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='机器信息';
-- ----------------------------
@@ -228,10 +228,8 @@ CREATE TABLE `t_mongo` (
`uri` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '连接uri',
`enable_ssh_tunnel` tinyint(2) DEFAULT NULL COMMENT '是否启用ssh隧道',
`ssh_tunnel_machine_id` bigint(20) DEFAULT NULL COMMENT 'ssh隧道的机器id',
`project_id` bigint(20) NOT NULL,
`project` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`env_id` bigint(20) DEFAULT NULL,
`env` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`tag_id` bigint(20) DEFAULT NULL COMMENT '标签id',
`tag_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '标签路径',
`create_time` datetime NOT NULL,
`creator_id` bigint(20) DEFAULT NULL,
`creator` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
@@ -247,83 +245,13 @@ CREATE TABLE `t_mongo` (
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for t_project
-- ----------------------------
DROP TABLE IF EXISTS `t_project`;
CREATE TABLE `t_project` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '项目名',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '备注说明',
`create_time` datetime DEFAULT NULL,
`creator_id` bigint(20) DEFAULT NULL,
`creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`modifier_id` bigint(20) DEFAULT NULL,
`modifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='项目信息表';
-- ----------------------------
-- Records of t_project
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for t_project_env
-- ----------------------------
DROP TABLE IF EXISTS `t_project_env`;
CREATE TABLE `t_project_env` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`project_id` bigint(20) NOT NULL COMMENT '关联的项目id',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '环境名',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '说明备注',
`create_time` datetime DEFAULT NULL,
`creator_id` bigint(20) DEFAULT NULL,
`creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`modifier_id` bigint(20) DEFAULT NULL,
`modifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='项目环境';
-- ----------------------------
-- Records of t_project_env
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for t_project_member
-- ----------------------------
DROP TABLE IF EXISTS `t_project_member`;
CREATE TABLE `t_project_member` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`project_id` bigint(20) NOT NULL COMMENT '项目id',
`account_id` bigint(20) NOT NULL COMMENT '账号id',
`username` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '账号用户名冗余',
`create_time` datetime DEFAULT NULL,
`creator_id` bigint(20) DEFAULT NULL,
`creator` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`modifier_id` bigint(20) DEFAULT NULL,
`modifier` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='项目成员关联表';
-- ----------------------------
-- Records of t_project_member
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for t_redis
-- ----------------------------
DROP TABLE IF EXISTS `t_redis`;
CREATE TABLE `t_redis` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '名称',
`host` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`db` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '库号: 多个库用,分割',
@@ -331,17 +259,16 @@ CREATE TABLE `t_redis` (
`enable_ssh_tunnel` tinyint(2) DEFAULT NULL COMMENT '是否启用ssh隧道',
`ssh_tunnel_machine_id` bigint(20) DEFAULT NULL COMMENT 'ssh隧道的机器id',
`remark` varchar(125) COLLATE utf8mb4_bin DEFAULT NULL,
`project_id` bigint(20) DEFAULT NULL,
`project` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`env_id` bigint(20) DEFAULT NULL,
`env` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`tag_id` bigint(20) DEFAULT NULL COMMENT '标签id',
`tag_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '标签路径',
`creator` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`creator_id` bigint(32) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`modifier` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`modifier_id` bigint(20) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
PRIMARY KEY (`id`),
KEY `idx_tag_path` (`tag_path`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='redis信息';
-- ----------------------------
@@ -374,7 +301,7 @@ CREATE TABLE `t_sys_account` (
-- Records of t_sys_account
-- ----------------------------
BEGIN;
INSERT INTO `t_sys_account` VALUES (1, 'admin', '$2a$10$w3Wky2U.tinvR7c/s0aKPuwZsIu6pM1/DMJalwBDMbE6niHIxVrrm', 1, '2022-10-08 10:53:04', '::1', '2020-01-01 19:00:00', 1, 'admin', '2020-01-01 19:00:00', 1, 'admin');
INSERT INTO `t_sys_account` VALUES (1, 'admin', '$2a$10$w3Wky2U.tinvR7c/s0aKPuwZsIu6pM1/DMJalwBDMbE6niHIxVrrm', 1, '2022-10-26 20:03:48', '::1', '2020-01-01 19:00:00', 1, 'admin', '2020-01-01 19:00:00', 1, 'admin');
COMMIT;
-- ----------------------------
@@ -406,6 +333,7 @@ CREATE TABLE `t_sys_config` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '配置名',
`key` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '配置key',
`params` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '配置key',
`value` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '配置value',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '备注',
`create_time` datetime NOT NULL,
@@ -440,11 +368,13 @@ CREATE TABLE `t_sys_log` (
`create_time` datetime NOT NULL COMMENT '操作时间',
PRIMARY KEY (`id`),
KEY `idx_creator_id` (`creator_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='系统操作日志';
) ENGINE=InnoDB AUTO_INCREMENT=58 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='系统操作日志';
-- ----------------------------
-- Records of t_sys_log
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for t_sys_msg
@@ -459,11 +389,13 @@ CREATE TABLE `t_sys_msg` (
`creator` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`create_time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=89 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='系统消息表';
) ENGINE=InnoDB AUTO_INCREMENT=91 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='系统消息表';
-- ----------------------------
-- Records of t_sys_msg
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for t_sys_resource
@@ -485,7 +417,7 @@ CREATE TABLE `t_sys_resource` (
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=89 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='资源表';
) ENGINE=InnoDB AUTO_INCREMENT=103 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='资源表';
-- ----------------------------
-- Records of t_sys_resource
@@ -531,15 +463,9 @@ INSERT INTO `t_sys_resource` VALUES (44, 3, 2, 1, '文件管理-删除文件按
INSERT INTO `t_sys_resource` VALUES (45, 3, 2, 1, '脚本管理-保存脚本按钮', 'machine:script:save', 12, 'null', 1, 'admin', 1, 'admin', '2021-06-08 11:09:01', '2021-06-08 11:09:01');
INSERT INTO `t_sys_resource` VALUES (46, 3, 2, 1, '脚本管理-删除按钮', 'machine:script:del', 13, 'null', 1, 'admin', 1, 'admin', '2021-06-08 11:09:27', '2021-06-08 11:09:27');
INSERT INTO `t_sys_resource` VALUES (47, 3, 2, 1, '脚本管理-执行按钮', 'machine:script:run', 14, 'null', 1, 'admin', 1, 'admin', '2021-06-08 11:09:50', '2021-06-08 11:09:50');
INSERT INTO `t_sys_resource` VALUES (48, 86, 1, 1, '项目列表', 'projects', 1, '{\"component\":\"ProjectList\",\"icon\":\"Menu\",\"isKeepAlive\":true,\"routeName\":\"ProjectList\"}', 1, 'admin', 1, 'admin', '2021-06-30 16:19:49', '2021-06-30 16:20:12');
INSERT INTO `t_sys_resource` VALUES (49, 36, 1, 1, '数据库管理', 'dbs', 2, '{\"component\":\"DbList\",\"icon\":\"Menu\",\"isKeepAlive\":true,\"routeName\":\"DbList\"}', 1, 'admin', 1, 'admin', '2021-07-07 15:13:55', '2021-07-07 15:13:55');
INSERT INTO `t_sys_resource` VALUES (50, 48, 2, 1, '项目保存', 'project:save', 1, 'null', 1, 'admin', 1, 'admin', '2021-07-08 17:27:28', '2021-07-08 17:35:07');
INSERT INTO `t_sys_resource` VALUES (51, 48, 2, 1, '成员分配', 'project:member:add', 2, 'null', 1, 'admin', 1, 'admin', '2021-07-08 17:29:25', '2021-07-08 17:29:25');
INSERT INTO `t_sys_resource` VALUES (52, 48, 2, 1, '成员移除', 'project:member:del', 3, 'null', 1, 'admin', 1, 'admin', '2021-07-08 17:30:01', '2021-07-08 17:30:01');
INSERT INTO `t_sys_resource` VALUES (53, 48, 2, 1, '环境新增', 'project:env:add', 4, 'null', 1, 'admin', 1, 'admin', '2021-07-08 17:30:17', '2021-07-08 17:30:17');
INSERT INTO `t_sys_resource` VALUES (54, 49, 2, 1, '数据库保存', 'db:save', 1, 'null', 1, 'admin', 1, 'admin', '2021-07-08 17:30:36', '2021-07-08 17:31:05');
INSERT INTO `t_sys_resource` VALUES (55, 49, 2, 1, '数据库删除', 'db:del', 2, 'null', 1, 'admin', 1, 'admin', '2021-07-08 17:30:48', '2021-07-08 17:30:48');
INSERT INTO `t_sys_resource` VALUES (56, 48, 2, 1, '项目基本权限', 'project', 1, 'null', 1, 'admin', 1, 'admin', '2021-07-09 10:47:19', '2021-07-09 11:09:20');
INSERT INTO `t_sys_resource` VALUES (57, 3, 2, 1, '基本权限', 'machine', 0, 'null', 1, 'admin', 1, 'admin', '2021-07-09 10:48:02', '2021-07-09 10:48:02');
INSERT INTO `t_sys_resource` VALUES (58, 49, 2, 1, '基本权限', 'db', 0, 'null', 1, 'admin', 1, 'admin', '2021-07-09 10:48:22', '2021-07-09 10:48:22');
INSERT INTO `t_sys_resource` VALUES (59, 38, 2, 1, '基本权限', 'db:exec', 1, 'null', 1, 'admin', 1, 'admin', '2021-07-09 10:50:13', '2021-07-09 10:50:13');
@@ -548,7 +474,6 @@ INSERT INTO `t_sys_resource` VALUES (61, 60, 1, 1, '数据操作', 'data-operati
INSERT INTO `t_sys_resource` VALUES (62, 61, 2, 1, '基本权限', 'redis:data', 1, 'null', 1, 'admin', 1, 'admin', '2021-07-19 20:18:54', '2021-07-19 20:18:54');
INSERT INTO `t_sys_resource` VALUES (63, 60, 1, 1, 'redis管理', 'manage', 2, '{\"component\":\"RedisList\",\"icon\":\"Menu\",\"isKeepAlive\":true,\"routeName\":\"RedisList\"}', 1, 'admin', 1, 'admin', '2021-07-20 10:48:04', '2021-07-20 10:48:04');
INSERT INTO `t_sys_resource` VALUES (64, 63, 2, 1, '基本权限', 'redis:manage', 1, 'null', 1, 'admin', 1, 'admin', '2021-07-20 10:48:26', '2021-07-20 10:48:26');
INSERT INTO `t_sys_resource` VALUES (70, 48, 2, 1, '项目删除', 'project:del', 6, 'null', 1, 'admin', 1, 'admin', '2021-08-17 11:20:37', '2021-08-17 11:20:37');
INSERT INTO `t_sys_resource` VALUES (71, 61, 2, 1, '数据保存', 'redis:data:save', 6, 'null', 1, 'admin', 1, 'admin', '2021-08-17 11:20:37', '2021-08-17 11:20:37');
INSERT INTO `t_sys_resource` VALUES (72, 3, 2, 1, '终止进程', 'machine:killprocess', 6, 'null', 1, 'admin', 1, 'admin', '2021-08-17 11:20:37', '2021-08-17 11:20:37');
INSERT INTO `t_sys_resource` VALUES (79, 0, 1, 1, 'Mongo', '/mongo', 7, '{\"icon\":\"Document\",\"isKeepAlive\":true,\"routeName\":\"Mongo\"}', 1, 'admin', 1, 'admin', '2022-05-13 14:00:41', '2022-10-06 15:01:34');
@@ -558,9 +483,18 @@ INSERT INTO `t_sys_resource` VALUES (82, 79, 1, 1, 'Mongo管理', 'mongo-manage'
INSERT INTO `t_sys_resource` VALUES (83, 82, 2, 1, '基本权限', 'mongo:manage:base', 1, 'null', 1, 'admin', 1, 'admin', '2022-05-16 18:13:25', '2022-05-16 18:13:25');
INSERT INTO `t_sys_resource` VALUES (84, 4, 1, 1, '操作日志', 'syslogs', 4, '{\"component\":\"SyslogList\",\"icon\":\"Tickets\",\"routeName\":\"SyslogList\"}', 1, 'admin', 1, 'admin', '2022-07-13 19:57:07', '2022-07-13 22:58:19');
INSERT INTO `t_sys_resource` VALUES (85, 84, 2, 1, '操作日志基本权限', 'syslog', 1, 'null', 1, 'admin', 1, 'admin', '2022-07-13 19:57:55', '2022-07-13 19:57:55');
INSERT INTO `t_sys_resource` VALUES (86, 0, 1, 1, '项目管理', '/project', 3, '{\"icon\":\"Menu\",\"isKeepAlive\":true,\"routeName\":\"Project\"}', 1, 'admin', 1, 'admin', '2022-10-06 14:48:05', '2022-10-06 14:59:00');
INSERT INTO `t_sys_resource` VALUES (87, 4, 1, 1, '系统配置', 'configs', 5, '{\"component\":\"ConfigList\",\"icon\":\"Setting\",\"isKeepAlive\":true,\"routeName\":\"ConfigList\"}', 1, 'admin', 1, 'admin', '2022-08-25 22:18:55', '2022-08-25 22:19:18');
INSERT INTO `t_sys_resource` VALUES (88, 87, 2, 1, '基本权限', 'config:base', 1, 'null', 1, 'admin', 1, 'admin', '2022-08-25 22:19:35', '2022-08-25 22:19:35');
INSERT INTO `t_sys_resource` VALUES (93, 0, 1, 1, '标签管理', '/tag', 3, '{\"icon\":\"CollectionTag\",\"isKeepAlive\":true,\"routeName\":\"Tag\"}', 1, 'admin', 1, 'admin', '2022-10-24 15:18:40', '2022-10-24 15:24:29');
INSERT INTO `t_sys_resource` VALUES (94, 93, 1, 1, '标签树', 'tag-trees', 1, '{\"component\":\"TagTreeList\",\"icon\":\"CollectionTag\",\"isKeepAlive\":true,\"routeName\":\"TagTreeList\"}', 1, 'admin', 1, 'admin', '2022-10-24 15:19:40', '2022-10-24 15:28:07');
INSERT INTO `t_sys_resource` VALUES (95, 93, 1, 1, '团队管理', 'teams', 2, '{\"component\":\"TeamList\",\"icon\":\"UserFilled\",\"isKeepAlive\":true,\"routeName\":\"TeamList\"}', 1, 'admin', 1, 'admin', '2022-10-24 15:20:09', '2022-10-24 15:24:01');
INSERT INTO `t_sys_resource` VALUES (96, 94, 2, 1, '保存标签', 'tag:save', 1, 'null', 1, 'admin', 1, 'admin', '2022-10-24 15:20:40', '2022-10-26 13:58:36');
INSERT INTO `t_sys_resource` VALUES (97, 95, 2, 1, '保存团队', 'team:save', 1, 'null', 1, 'admin', 1, 'admin', '2022-10-24 15:20:57', '2022-10-26 13:58:56');
INSERT INTO `t_sys_resource` VALUES (98, 94, 2, 1, '删除标签', 'tag:del', 2, 'null', 1, 'admin', 1, 'admin', '2022-10-26 13:58:47', '2022-10-26 13:58:47');
INSERT INTO `t_sys_resource` VALUES (99, 95, 2, 1, '删除团队', 'team:del', 2, 'null', 1, 'admin', 1, 'admin', '2022-10-26 13:59:06', '2022-10-26 13:59:06');
INSERT INTO `t_sys_resource` VALUES (100, 95, 2, 1, '新增团队成员', 'team:member:save', 3, 'null', 1, 'admin', 1, 'admin', '2022-10-26 13:59:27', '2022-10-26 13:59:27');
INSERT INTO `t_sys_resource` VALUES (101, 95, 2, 1, '移除团队成员', 'team:member:del', 4, 'null', 1, 'admin', 1, 'admin', '2022-10-26 13:59:43', '2022-10-26 13:59:43');
INSERT INTO `t_sys_resource` VALUES (102, 95, 2, 1, '保存团队标签', 'team:tag:save', 5, 'null', 1, 'admin', 1, 'admin', '2022-10-26 13:59:57', '2022-10-26 13:59:57');
COMMIT;
-- ----------------------------
@@ -605,7 +539,7 @@ CREATE TABLE `t_sys_role_resource` (
`creator` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=516 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='角色资源关联表';
) ENGINE=InnoDB AUTO_INCREMENT=526 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='角色资源关联表';
-- ----------------------------
-- Records of t_sys_role_resource
@@ -670,48 +604,32 @@ INSERT INTO `t_sys_role_resource` VALUES (398, 6, 4, 1, 'admin', '2021-06-08 15:
INSERT INTO `t_sys_role_resource` VALUES (399, 6, 14, 1, 'admin', '2021-06-08 15:10:58');
INSERT INTO `t_sys_role_resource` VALUES (400, 6, 11, 1, 'admin', '2021-06-08 15:10:58');
INSERT INTO `t_sys_role_resource` VALUES (401, 6, 5, 1, 'admin', '2021-06-08 15:10:58');
INSERT INTO `t_sys_role_resource` VALUES (402, 1, 48, 1, 'admin', '2021-06-30 16:22:35');
INSERT INTO `t_sys_role_resource` VALUES (403, 7, 1, 1, 'admin', '2021-07-06 15:07:09');
INSERT INTO `t_sys_role_resource` VALUES (405, 1, 49, 1, 'admin', '2021-07-07 15:14:17');
INSERT INTO `t_sys_role_resource` VALUES (406, 1, 50, 1, 'admin', '2021-07-08 17:32:19');
INSERT INTO `t_sys_role_resource` VALUES (407, 1, 51, 1, 'admin', '2021-07-08 17:32:19');
INSERT INTO `t_sys_role_resource` VALUES (408, 1, 52, 1, 'admin', '2021-07-08 17:32:19');
INSERT INTO `t_sys_role_resource` VALUES (409, 1, 53, 1, 'admin', '2021-07-08 17:32:19');
INSERT INTO `t_sys_role_resource` VALUES (410, 1, 54, 1, 'admin', '2021-07-08 17:32:19');
INSERT INTO `t_sys_role_resource` VALUES (411, 1, 55, 1, 'admin', '2021-07-08 17:32:19');
INSERT INTO `t_sys_role_resource` VALUES (412, 1, 56, 1, 'admin', '2021-07-09 10:48:50');
INSERT INTO `t_sys_role_resource` VALUES (413, 1, 57, 1, 'admin', '2021-07-09 10:48:50');
INSERT INTO `t_sys_role_resource` VALUES (414, 1, 58, 1, 'admin', '2021-07-09 10:48:50');
INSERT INTO `t_sys_role_resource` VALUES (415, 8, 1, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (416, 8, 39, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (417, 8, 56, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (418, 8, 57, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (419, 8, 12, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (420, 8, 15, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (421, 8, 38, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (422, 8, 58, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (423, 8, 2, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (424, 8, 48, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (425, 8, 3, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (426, 8, 36, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (427, 8, 49, 1, 'admin', '2021-07-09 10:49:46');
INSERT INTO `t_sys_role_resource` VALUES (428, 1, 59, 1, 'admin', '2021-07-09 10:50:20');
INSERT INTO `t_sys_role_resource` VALUES (429, 8, 59, 1, 'admin', '2021-07-09 10:50:32');
INSERT INTO `t_sys_role_resource` VALUES (430, 6, 56, 1, 'admin', '2021-07-12 16:44:12');
INSERT INTO `t_sys_role_resource` VALUES (431, 6, 57, 1, 'admin', '2021-07-12 16:44:12');
INSERT INTO `t_sys_role_resource` VALUES (432, 6, 48, 1, 'admin', '2021-07-12 16:44:12');
INSERT INTO `t_sys_role_resource` VALUES (433, 1, 60, 1, 'admin', '2021-07-19 20:19:29');
INSERT INTO `t_sys_role_resource` VALUES (434, 1, 61, 1, 'admin', '2021-07-19 20:19:29');
INSERT INTO `t_sys_role_resource` VALUES (435, 1, 62, 1, 'admin', '2021-07-19 20:19:29');
INSERT INTO `t_sys_role_resource` VALUES (436, 1, 63, 1, 'admin', '2021-07-20 10:48:39');
INSERT INTO `t_sys_role_resource` VALUES (437, 1, 64, 1, 'admin', '2021-07-20 10:48:39');
INSERT INTO `t_sys_role_resource` VALUES (443, 1, 70, 1, 'admin', '2021-08-17 11:20:51');
INSERT INTO `t_sys_role_resource` VALUES (444, 7, 39, 1, 'admin', '2021-09-09 10:10:30');
INSERT INTO `t_sys_role_resource` VALUES (445, 6, 50, 1, 'admin', '2021-09-09 15:52:38');
INSERT INTO `t_sys_role_resource` VALUES (446, 6, 51, 1, 'admin', '2021-09-09 15:52:38');
INSERT INTO `t_sys_role_resource` VALUES (447, 6, 52, 1, 'admin', '2021-09-09 15:52:38');
INSERT INTO `t_sys_role_resource` VALUES (448, 6, 53, 1, 'admin', '2021-09-09 15:52:38');
INSERT INTO `t_sys_role_resource` VALUES (449, 6, 70, 1, 'admin', '2021-09-09 15:52:38');
INSERT INTO `t_sys_role_resource` VALUES (450, 6, 16, 1, 'admin', '2021-09-09 15:52:38');
INSERT INTO `t_sys_role_resource` VALUES (451, 6, 17, 1, 'admin', '2021-09-09 15:52:38');
INSERT INTO `t_sys_role_resource` VALUES (452, 6, 18, 1, 'admin', '2021-09-09 15:52:38');
@@ -766,13 +684,124 @@ INSERT INTO `t_sys_role_resource` VALUES (505, 1, 82, 1, 'admin', '2022-07-14 11
INSERT INTO `t_sys_role_resource` VALUES (506, 1, 83, 1, 'admin', '2022-07-14 11:03:09');
INSERT INTO `t_sys_role_resource` VALUES (507, 1, 84, 1, 'admin', '2022-07-14 11:10:11');
INSERT INTO `t_sys_role_resource` VALUES (508, 1, 85, 1, 'admin', '2022-07-14 11:10:11');
INSERT INTO `t_sys_role_resource` VALUES (509, 1, 86, 1, 'admin', '2022-07-14 11:10:11');
INSERT INTO `t_sys_role_resource` VALUES (510, 1, 87, 1, 'admin', '2022-07-14 11:10:11');
INSERT INTO `t_sys_role_resource` VALUES (511, 1, 88, 1, 'admin', '2022-10-08 10:54:06');
INSERT INTO `t_sys_role_resource` VALUES (512, 8, 80, 1, 'admin', '2022-10-08 10:54:34');
INSERT INTO `t_sys_role_resource` VALUES (513, 8, 81, 1, 'admin', '2022-10-08 10:54:34');
INSERT INTO `t_sys_role_resource` VALUES (514, 8, 86, 1, 'admin', '2022-10-08 10:54:34');
INSERT INTO `t_sys_role_resource` VALUES (515, 8, 79, 1, 'admin', '2022-10-08 10:54:34');
INSERT INTO `t_sys_role_resource` VALUES (516, 1, 93, 1, 'admin', '2022-10-26 20:03:14');
INSERT INTO `t_sys_role_resource` VALUES (517, 1, 94, 1, 'admin', '2022-10-26 20:03:14');
INSERT INTO `t_sys_role_resource` VALUES (518, 1, 96, 1, 'admin', '2022-10-26 20:03:14');
INSERT INTO `t_sys_role_resource` VALUES (519, 1, 98, 1, 'admin', '2022-10-26 20:03:14');
INSERT INTO `t_sys_role_resource` VALUES (520, 1, 95, 1, 'admin', '2022-10-26 20:03:14');
INSERT INTO `t_sys_role_resource` VALUES (521, 1, 97, 1, 'admin', '2022-10-26 20:03:14');
INSERT INTO `t_sys_role_resource` VALUES (522, 1, 99, 1, 'admin', '2022-10-26 20:03:14');
INSERT INTO `t_sys_role_resource` VALUES (523, 1, 100, 1, 'admin', '2022-10-26 20:03:14');
INSERT INTO `t_sys_role_resource` VALUES (524, 1, 101, 1, 'admin', '2022-10-26 20:03:14');
INSERT INTO `t_sys_role_resource` VALUES (525, 1, 102, 1, 'admin', '2022-10-26 20:03:14');
COMMIT;
-- ----------------------------
-- Table structure for t_tag_tree
-- ----------------------------
DROP TABLE IF EXISTS `t_tag_tree`;
CREATE TABLE `t_tag_tree` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`pid` bigint(20) NOT NULL DEFAULT '0',
`code` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '标识符',
`code_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '标识符路径',
`name` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '名称',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`create_time` datetime NOT NULL,
`creator_id` bigint(20) NOT NULL,
`creator` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`update_time` datetime NOT NULL,
`modifier_id` bigint(20) NOT NULL,
`modifier` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_code_path` (`code_path`(100)) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='标签树';
-- ----------------------------
-- Records of t_tag_tree
-- ----------------------------
BEGIN;
INSERT INTO `t_tag_tree` VALUES (33, 0, 'default', 'default', '默认', '默认标签', '2022-10-26 20:04:19', 1, 'admin', '2022-10-26 20:04:19', 1, 'admin');
COMMIT;
-- ----------------------------
-- Table structure for t_tag_tree_team
-- ----------------------------
DROP TABLE IF EXISTS `t_tag_tree_team`;
CREATE TABLE `t_tag_tree_team` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`tag_id` bigint(20) NOT NULL COMMENT '项目树id',
`tag_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`team_id` bigint(20) NOT NULL COMMENT '团队id',
`create_time` datetime NOT NULL,
`creator_id` bigint(20) NOT NULL,
`creator` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`update_time` datetime NOT NULL,
`modifier_id` bigint(20) NOT NULL,
`modifier` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_tag_id` (`tag_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='标签树团队关联信息';
-- ----------------------------
-- Records of t_tag_tree_team
-- ----------------------------
BEGIN;
INSERT INTO `t_tag_tree_team` VALUES (31, 33, 'default', 3, '2022-10-26 20:04:45', 1, 'admin', '2022-10-26 20:04:45', 1, 'admin');
COMMIT;
-- ----------------------------
-- Table structure for t_team
-- ----------------------------
DROP TABLE IF EXISTS `t_team`;
CREATE TABLE `t_team` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '名称',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '备注',
`create_time` datetime NOT NULL,
`creator_id` bigint(20) NOT NULL,
`creator` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`modifier_id` bigint(20) DEFAULT NULL,
`modifier` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='团队信息';
-- ----------------------------
-- Records of t_team
-- ----------------------------
BEGIN;
INSERT INTO `t_team` VALUES (3, '默认团队', '默认团队', '2022-10-26 20:04:36', 1, 'admin', '2022-10-26 20:04:36', 1, 'admin');
COMMIT;
-- ----------------------------
-- Table structure for t_team_member
-- ----------------------------
DROP TABLE IF EXISTS `t_team_member`;
CREATE TABLE `t_team_member` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`team_id` bigint(20) NOT NULL COMMENT '项目团队id',
`account_id` bigint(20) NOT NULL COMMENT '成员id',
`username` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`create_time` datetime NOT NULL,
`creator_id` bigint(20) NOT NULL,
`creator` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`update_time` datetime NOT NULL,
`modifier_id` bigint(20) NOT NULL,
`modifier` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='团队成员表';
-- ----------------------------
-- Records of t_team_member
-- ----------------------------
BEGIN;
INSERT INTO `t_team_member` VALUES (7, 3, 1, 'admin', '2022-10-26 20:04:36', 1, 'admin', '2022-10-26 20:04:36', 1, 'admin');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -4,7 +4,7 @@ import "fmt"
const (
AppName = "mayfly-go"
Version = "v1.2.12"
Version = "v1.3.0"
)
func GetAppInfo() string {

View File

@@ -66,11 +66,13 @@ func Tx(funcs ...func(db *gorm.DB) error) (err error) {
// 根据id获取实体对象。model需为指针类型需要将查询出来的值赋值给model
//
// 若error不为nil则为不存在该记录
// @param model 数据库映射实体模型
func GetById(model interface{}, id uint64, cols ...string) error {
return global.Db.Select(cols).Where("id = ?", id).First(model).Error
}
// 根据id列表查询
// 根据map条件查询列表map中的值如果为数组则使用in查询
// @param model 数据库映射实体模型
func GetByIdIn(model interface{}, list interface{}, ids []uint64, orderBy ...string) {
var orderByStr string
if orderBy == nil {
@@ -81,6 +83,17 @@ func GetByIdIn(model interface{}, list interface{}, ids []uint64, orderBy ...str
global.Db.Model(model).Where("id in (?)", ids).Order(orderByStr).Find(list)
}
// 根据id列表查询
func SelectByMap(model interface{}, list interface{}, where map[string]interface{}, orderBy ...string) {
var orderByStr string
if orderBy == nil {
orderByStr = "id desc"
} else {
orderByStr = strings.Join(orderBy, ",")
}
global.Db.Model(model).Where(where).Order(orderByStr).Find(list)
}
// 根据id列表查询
func CountBy(model interface{}) int64 {
var count int64
@@ -88,22 +101,42 @@ func CountBy(model interface{}) int64 {
return count
}
// 根据map为条件统计数量map中的值如果为数组则使用in查询
// @param model 数据库映射实体模型
// @param where 条件map
func CountByMap(model interface{}, where map[string]interface{}) int64 {
var count int64
global.Db.Model(model).Where(where).Count(&count)
return count
}
// 根据统计sql返回统计数量
func CountBySql(sql string) int64 {
var count int64
global.Db.Raw(sql).Scan(&count)
return count
}
// 根据id更新model更新字段为model中不为空的值即int类型不为0ptr类型不为nil这类字段值
// @param model 数据库映射实体模型
func UpdateById(model interface{}) error {
return global.Db.Model(model).Updates(model).Error
}
// 根据id删除model
// @param model 数据库映射实体模型
func DeleteById(model interface{}, id uint64) error {
return global.Db.Delete(model, "id = ?", id).Error
}
// 根据条件删除
// @param model 数据库映射实体模型
func DeleteByCondition(model interface{}) error {
return global.Db.Where(model).Delete(model).Error
}
// 插入model
// @param model 数据库映射实体模型
func Insert(model interface{}) error {
return global.Db.Create(model).Error
}
@@ -118,6 +151,7 @@ func ListBy(model interface{}, list interface{}, cols ...string) {
// 获取满足model中不为空的字段值条件的所有数据.
//
// @param list为数组类型 如 var users *[]User可指定为非model结构体
// @param model 数据库映射实体模型
func ListByOrder(model interface{}, list interface{}, order ...string) {
var orderByStr string
if order == nil {
@@ -131,21 +165,24 @@ func ListByOrder(model interface{}, list interface{}, order ...string) {
// 获取满足model中不为空的字段值条件的单个对象。model需为指针类型需要将查询出来的值赋值给model
//
// 若 error不为nil则为不存在该记录
// @param model 数据库映射实体模型
func GetBy(model interface{}, cols ...string) error {
return global.Db.Select(cols).Where(model).First(model).Error
}
// 获取满足conditionModel中不为空的字段值条件的单个对象。model需为指针类型需要将查询出来的值赋值给model
//
// @param toModel 需要查询的字段
//
// 若 error不为nil则为不存在该记录
func GetByConditionTo(conditionModel interface{}, toModel interface{}) error {
return global.Db.Model(conditionModel).Where(conditionModel).First(toModel).Error
}
// 获取分页结果
func GetPage(pageParam *PageParam, conditionModel interface{}, toModels interface{}, orderBy ...string) *PageResult {
func GetPage(pageParam *PageParam, model interface{}, conditionModel interface{}, toModels interface{}, orderBy ...string) *PageResult {
var count int64
err := global.Db.Model(conditionModel).Where(conditionModel).Count(&count).Error
err := global.Db.Model(model).Where(conditionModel).Count(&count).Error
biz.ErrIsNilAppendErr(err, " 查询错误:%s")
if count == 0 {
return &PageResult{Total: 0, List: []string{}}
@@ -159,7 +196,7 @@ func GetPage(pageParam *PageParam, conditionModel interface{}, toModels interfac
} else {
orderByStr = strings.Join(orderBy, ",")
}
err = global.Db.Model(conditionModel).Where(conditionModel).Order(orderByStr).Limit(pageSize).Offset((page - 1) * pageSize).Find(toModels).Error
err = global.Db.Model(model).Where(conditionModel).Order(orderByStr).Limit(pageSize).Offset((page - 1) * pageSize).Find(toModels).Error
biz.ErrIsNil(err, "查询失败")
return &PageResult{Total: count, List: toModels}
}

View File

@@ -11,3 +11,8 @@ type PageResult struct {
Total int64 `json:"total"`
List interface{} `json:"list"`
}
// 空分页结果日志
func EmptyPageResult() *PageResult {
return &PageResult{Total: 0, List: make([]interface{}, 0)}
}

View File

@@ -1,5 +1,7 @@
package utils
import "fmt"
// 数组比较
// 依次返回,新增值,删除值,以及不变值
func ArrayCompare(newArr []interface{}, oldArr []interface{}, compareFun func(interface{}, interface{}) bool) ([]interface{}, []interface{}, []interface{}) {
@@ -19,10 +21,14 @@ func ArrayCompare(newArr []interface{}, oldArr []interface{}, compareFun func(in
if compareFun(nv, ov) {
unmodifierValue = append(unmodifierValue, nv)
// 新数组移除该位置值
newArr = append(newArr[:ni], newArr[ni+1:]...)
oldArr = append(oldArr[:oi], oldArr[oi+1:]...)
ni = ni - 1
oi = oi - 1
if len(newArr) > ni {
newArr = append(newArr[:ni], newArr[ni+1:]...)
ni = ni - 1
}
if len(oldArr) > oi {
oldArr = append(oldArr[:oi], oldArr[oi+1:]...)
oi = oi - 1
}
}
oi = oi + 1
}
@@ -31,3 +37,16 @@ func ArrayCompare(newArr []interface{}, oldArr []interface{}, compareFun func(in
return newArr, oldArr, unmodifierValue
}
type NumT interface {
~int | ~int32 | ~uint64
}
func NumberArr2StrArr[T NumT](numberArr []T) []string {
strArr := make([]string, 0)
for _, v := range numberArr {
strArr = append(strArr, fmt.Sprintf("%d", v))
}
return strArr
}

View File

@@ -1 +0,0 @@
import{_ as s,u as n,b as l,e as c,h as e,g as d,w as f,$ as m,Q as u,R as _,d as p,B as h}from"./index.1665826199593.js";var x="assets/401.1665826199593.png";const v={name:"401",setup(){const t=n();return{onSetAuth:()=>{m(),t.push("/login")}}}},o=t=>(u("data-v-6ec92039"),t=t(),_(),t),g={class:"error"},y={class:"error-flex"},b={class:"left"},C={class:"left-item"},B=o(()=>e("div",{class:"left-item-animation left-item-num"},"401",-1)),w=o(()=>e("div",{class:"left-item-animation left-item-title"},"\u60A8\u672A\u88AB\u6388\u6743\u6216\u767B\u5F55\u8D85\u65F6\uFF0C\u6CA1\u6709\u64CD\u4F5C\u6743\u9650",-1)),A=o(()=>e("div",{class:"left-item-animation left-item-msg"},null,-1)),S={class:"left-item-animation left-item-btn"},F=o(()=>e("div",{class:"right"},[e("img",{src:x})],-1));function k(t,r,I,a,$,z){const i=l("el-button");return p(),c("div",g,[e("div",y,[e("div",b,[e("div",C,[B,w,A,e("div",S,[d(i,{type:"primary",round:"",onClick:a.onSetAuth},{default:f(()=>[h("\u91CD\u65B0\u767B\u5F55")]),_:1},8,["onClick"])])])]),F])])}var N=s(v,[["render",k],["__scopeId","data-v-6ec92039"]]);export{N as default};

View File

@@ -0,0 +1 @@
import{_ as s,b as n,k as l,p as c,y as e,q as d,w as m,I as f,B as u,C as _,m as p,A as h}from"./index.1666788454973.js";var x="assets/401.1666788454973.png";const v={name:"401",setup(){const t=n();return{onSetAuth:()=>{f(),t.push("/login")}}}},o=t=>(u("data-v-6ec92039"),t=t(),_(),t),g={class:"error"},y={class:"error-flex"},C={class:"left"},b={class:"left-item"},A=o(()=>e("div",{class:"left-item-animation left-item-num"},"401",-1)),B=o(()=>e("div",{class:"left-item-animation left-item-title"},"\u60A8\u672A\u88AB\u6388\u6743\u6216\u767B\u5F55\u8D85\u65F6\uFF0C\u6CA1\u6709\u64CD\u4F5C\u6743\u9650",-1)),w=o(()=>e("div",{class:"left-item-animation left-item-msg"},null,-1)),S={class:"left-item-animation left-item-btn"},k=o(()=>e("div",{class:"right"},[e("img",{src:x})],-1));function F(t,r,I,a,z,D){const i=l("el-button");return p(),c("div",g,[e("div",y,[e("div",C,[e("div",b,[A,B,w,e("div",S,[d(i,{type:"primary",round:"",onClick:a.onSetAuth},{default:m(()=>[h("\u91CD\u65B0\u767B\u5F55")]),_:1},8,["onClick"])])])]),k])])}var V=s(v,[["render",F],["__scopeId","data-v-6ec92039"]]);export{V as default};

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Some files were not shown because too many files have changed in this diff Show More