mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 08:20:25 +08:00 
			
		
		
		
	feat: v1.7.1新增支持sqlite&oracle分页限制等问题修复
This commit is contained in:
		@@ -22,7 +22,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### 介绍
 | 
					### 介绍
 | 
				
			||||||
 | 
					
 | 
				
			||||||
web 版 **linux(终端[终端回放] 文件 脚本 进程 计划任务)、数据库(mysql postgres oracle 达梦 高斯)、redis(单机 哨兵 集群)、mongo 统一管理操作平台**
 | 
					web 版 **linux(终端[终端回放] 文件 脚本 进程 计划任务)、数据库(mysql postgres oracle 达梦 高斯 sqlite)、redis(单机 哨兵 集群)、mongo 统一管理操作平台**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 开发语言与主要框架
 | 
					### 开发语言与主要框架
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@
 | 
				
			|||||||
    "countup.js": "^2.7.0",
 | 
					    "countup.js": "^2.7.0",
 | 
				
			||||||
    "cropperjs": "^1.5.11",
 | 
					    "cropperjs": "^1.5.11",
 | 
				
			||||||
    "echarts": "^5.4.3",
 | 
					    "echarts": "^5.4.3",
 | 
				
			||||||
    "element-plus": "^2.5.1",
 | 
					    "element-plus": "^2.5.2",
 | 
				
			||||||
    "js-base64": "^3.7.5",
 | 
					    "js-base64": "^3.7.5",
 | 
				
			||||||
    "jsencrypt": "^3.3.2",
 | 
					    "jsencrypt": "^3.3.2",
 | 
				
			||||||
    "lodash": "^4.17.21",
 | 
					    "lodash": "^4.17.21",
 | 
				
			||||||
@@ -33,7 +33,7 @@
 | 
				
			|||||||
    "splitpanes": "^3.1.5",
 | 
					    "splitpanes": "^3.1.5",
 | 
				
			||||||
    "sql-formatter": "^15.0.2",
 | 
					    "sql-formatter": "^15.0.2",
 | 
				
			||||||
    "uuid": "^9.0.1",
 | 
					    "uuid": "^9.0.1",
 | 
				
			||||||
    "vue": "^3.4.14",
 | 
					    "vue": "^3.4.15",
 | 
				
			||||||
    "vue-router": "^4.2.5",
 | 
					    "vue-router": "^4.2.5",
 | 
				
			||||||
    "xterm": "^5.3.0",
 | 
					    "xterm": "^5.3.0",
 | 
				
			||||||
    "xterm-addon-fit": "^0.8.0",
 | 
					    "xterm-addon-fit": "^0.8.0",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -307,7 +307,8 @@ const NodeTypeTableMenu = new NodeType(SqlExecNodeType.TableMenu)
 | 
				
			|||||||
        state.reloadStatus = false;
 | 
					        state.reloadStatus = false;
 | 
				
			||||||
        let dbTableSize = 0;
 | 
					        let dbTableSize = 0;
 | 
				
			||||||
        const tablesNode = tables.map((x: any) => {
 | 
					        const tablesNode = tables.map((x: any) => {
 | 
				
			||||||
            dbTableSize += x.dataLength + x.indexLength;
 | 
					            const tableSize = x.dataLength + x.indexLength;
 | 
				
			||||||
 | 
					            dbTableSize += tableSize;
 | 
				
			||||||
            return new TagTreeNode(`${id}.${db}.${x.tableName}`, x.tableName, NodeTypeTable)
 | 
					            return new TagTreeNode(`${id}.${db}.${x.tableName}`, x.tableName, NodeTypeTable)
 | 
				
			||||||
                .withIsLeaf(true)
 | 
					                .withIsLeaf(true)
 | 
				
			||||||
                .withParams({
 | 
					                .withParams({
 | 
				
			||||||
@@ -315,13 +316,13 @@ const NodeTypeTableMenu = new NodeType(SqlExecNodeType.TableMenu)
 | 
				
			|||||||
                    db,
 | 
					                    db,
 | 
				
			||||||
                    tableName: x.tableName,
 | 
					                    tableName: x.tableName,
 | 
				
			||||||
                    tableComment: x.tableComment,
 | 
					                    tableComment: x.tableComment,
 | 
				
			||||||
                    size: formatByteSize(x.dataLength + x.indexLength, 1),
 | 
					                    size: tableSize == 0 ? '' : formatByteSize(tableSize, 1),
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .withIcon(TableIcon)
 | 
					                .withIcon(TableIcon)
 | 
				
			||||||
                .withLabelRemark(`${x.tableName} ${x.tableComment ? '| ' + x.tableComment : ''}`);
 | 
					                .withLabelRemark(`${x.tableName} ${x.tableComment ? '| ' + x.tableComment : ''}`);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        // 设置父节点参数的表大小
 | 
					        // 设置父节点参数的表大小
 | 
				
			||||||
        parentNode.params.dbTableSize = formatByteSize(dbTableSize);
 | 
					        parentNode.params.dbTableSize = dbTableSize == 0 ? '' : formatByteSize(dbTableSize);
 | 
				
			||||||
        return tablesNode;
 | 
					        return tablesNode;
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    .withNodeClickFunc(nodeClickChangeDb);
 | 
					    .withNodeClickFunc(nodeClickChangeDb);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -868,7 +868,7 @@ defineExpose({
 | 
				
			|||||||
        color: var(--el-color-info-light-3);
 | 
					        color: var(--el-color-info-light-3);
 | 
				
			||||||
        font-weight: bold;
 | 
					        font-weight: bold;
 | 
				
			||||||
        position: absolute;
 | 
					        position: absolute;
 | 
				
			||||||
        top: -7px;
 | 
					        top: -5px;
 | 
				
			||||||
        padding: 2px;
 | 
					        padding: 2px;
 | 
				
			||||||
        height: 12px;
 | 
					        height: 12px;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -142,7 +142,7 @@ const search = async () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const changeStatus = async (row: any) => {
 | 
					const changeStatus = async (row: any) => {
 | 
				
			||||||
    let id = row.id;
 | 
					    let id = row.id;
 | 
				
			||||||
    let status = row.status == -1 ? 1 : -1;
 | 
					    let status = row.status == AccountStatusEnum.Disable.value ? AccountStatusEnum.Enable.value : AccountStatusEnum.Disable.value;
 | 
				
			||||||
    await accountApi.changeStatus.request({
 | 
					    await accountApi.changeStatus.request({
 | 
				
			||||||
        id,
 | 
					        id,
 | 
				
			||||||
        status,
 | 
					        status,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@ require (
 | 
				
			|||||||
	github.com/pquerna/otp v1.4.0
 | 
						github.com/pquerna/otp v1.4.0
 | 
				
			||||||
	github.com/redis/go-redis/v9 v9.4.0
 | 
						github.com/redis/go-redis/v9 v9.4.0
 | 
				
			||||||
	github.com/robfig/cron/v3 v3.0.1 // 定时任务
 | 
						github.com/robfig/cron/v3 v3.0.1 // 定时任务
 | 
				
			||||||
	github.com/sijms/go-ora/v2 v2.8.5
 | 
						github.com/sijms/go-ora/v2 v2.8.6
 | 
				
			||||||
	github.com/stretchr/testify v1.8.4
 | 
						github.com/stretchr/testify v1.8.4
 | 
				
			||||||
	go.mongodb.org/mongo-driver v1.13.1 // mongo
 | 
						go.mongodb.org/mongo-driver v1.13.1 // mongo
 | 
				
			||||||
	golang.org/x/crypto v0.18.0 // ssh
 | 
						golang.org/x/crypto v0.18.0 // ssh
 | 
				
			||||||
@@ -35,6 +35,7 @@ require (
 | 
				
			|||||||
	// gorm
 | 
						// gorm
 | 
				
			||||||
	gorm.io/driver/mysql v1.5.2
 | 
						gorm.io/driver/mysql v1.5.2
 | 
				
			||||||
	gorm.io/gorm v1.25.5
 | 
						gorm.io/gorm v1.25.5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,10 +3,11 @@ package oracle
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"database/sql"
 | 
						"database/sql"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	go_ora "github.com/sijms/go-ora/v2"
 | 
					 | 
				
			||||||
	"mayfly-go/internal/db/dbm/dbi"
 | 
						"mayfly-go/internal/db/dbm/dbi"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go_ora "github.com/sijms/go-ora/v2"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -58,10 +59,6 @@ func (md *OraMeta) GetSqlDb(d *dbi.DbInfo) (*sql.DB, error) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// 默认设置为UTF8
 | 
					 | 
				
			||||||
	//if urlOptions["client charset"] == "" {
 | 
					 | 
				
			||||||
	//	urlOptions["client charset"] = "UTF8"
 | 
					 | 
				
			||||||
	//}
 | 
					 | 
				
			||||||
	urlOptions["TIMEOUT"] = "10"
 | 
						urlOptions["TIMEOUT"] = "10"
 | 
				
			||||||
	connStr := go_ora.BuildUrl(d.Host, d.Port, d.Sid, d.Username, d.Password, urlOptions)
 | 
						connStr := go_ora.BuildUrl(d.Host, d.Port, d.Sid, d.Username, d.Password, urlOptions)
 | 
				
			||||||
	conn, err := sql.Open(driverName, connStr)
 | 
						conn, err := sql.Open(driverName, connStr)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,6 @@ package sqlite
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"database/sql"
 | 
						"database/sql"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	_ "github.com/mattn/go-sqlite3"
 | 
					 | 
				
			||||||
	"mayfly-go/internal/db/dbm/dbi"
 | 
						"mayfly-go/internal/db/dbm/dbi"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
@@ -30,7 +29,7 @@ func (md *SqliteMeta) GetSqlDb(d *dbi.DbInfo) (*sql.DB, error) {
 | 
				
			|||||||
	if _, err := os.Stat(d.Host); err != nil {
 | 
						if _, err := os.Stat(d.Host); err != nil {
 | 
				
			||||||
		return nil, errors.New("数据库文件不存在")
 | 
							return nil, errors.New("数据库文件不存在")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return sql.Open("sqlite3", d.Host)
 | 
						return sql.Open("sqlite", d.Host)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (md *SqliteMeta) GetDialect(conn *dbi.DbConn) dbi.Dialect {
 | 
					func (md *SqliteMeta) GetDialect(conn *dbi.DbConn) dbi.Dialect {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -154,7 +154,11 @@ func (a *Account) ChangeStatus(rc *req.Ctx) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	account := &entity.Account{}
 | 
						account := &entity.Account{}
 | 
				
			||||||
	account.Id = uint64(ginx.PathParamInt(g, "id"))
 | 
						account.Id = uint64(ginx.PathParamInt(g, "id"))
 | 
				
			||||||
	account.Status = int8(ginx.PathParamInt(g, "status"))
 | 
					
 | 
				
			||||||
 | 
						status := entity.AccountStatus(int8(ginx.PathParamInt(g, "status")))
 | 
				
			||||||
 | 
						biz.ErrIsNil(entity.AccountStatusEnum.Valid(status))
 | 
				
			||||||
 | 
						account.Status = status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc.ReqParam = collx.Kvs("accountId", account.Id, "status", account.Status)
 | 
						rc.ReqParam = collx.Kvs("accountId", account.Id, "status", account.Status)
 | 
				
			||||||
	biz.ErrIsNil(a.AccountApp.Update(rc.MetaCtx, account))
 | 
						biz.ErrIsNil(a.AccountApp.Update(rc.MetaCtx, account))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
package vo
 | 
					package vo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"mayfly-go/internal/sys/domain/entity"
 | 
				
			||||||
	"mayfly-go/pkg/model"
 | 
						"mayfly-go/pkg/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -9,7 +10,7 @@ type AccountManageVO struct {
 | 
				
			|||||||
	model.Model
 | 
						model.Model
 | 
				
			||||||
	Name          string               `json:"name"`
 | 
						Name          string               `json:"name"`
 | 
				
			||||||
	Username      string               `json:"username"`
 | 
						Username      string               `json:"username"`
 | 
				
			||||||
	Status        int        `json:"status"`
 | 
						Status        entity.AccountStatus `json:"status"`
 | 
				
			||||||
	LastLoginTime *time.Time           `json:"lastLoginTime"`
 | 
						LastLoginTime *time.Time           `json:"lastLoginTime"`
 | 
				
			||||||
	OtpSecret     string               `json:"otpSecret"`
 | 
						OtpSecret     string               `json:"otpSecret"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -23,7 +24,7 @@ type AccountRoleVO struct {
 | 
				
			|||||||
	AccountId     uint64               `json:"accountId" gorm:"column:accountId"`
 | 
						AccountId     uint64               `json:"accountId" gorm:"column:accountId"`
 | 
				
			||||||
	AccountName   string               `json:"accountName" gorm:"column:accountName"`
 | 
						AccountName   string               `json:"accountName" gorm:"column:accountName"`
 | 
				
			||||||
	Username      string               `json:"username"`
 | 
						Username      string               `json:"username"`
 | 
				
			||||||
	AccountStatus int        `json:"accountStatus" gorm:"column:accountStatus"`
 | 
						AccountStatus entity.AccountStatus `json:"accountStatus" gorm:"column:accountStatus"`
 | 
				
			||||||
	CreateTime    *time.Time           `json:"createTime"`
 | 
						CreateTime    *time.Time           `json:"createTime"`
 | 
				
			||||||
	Creator       string               `json:"creator"`
 | 
						Creator       string               `json:"creator"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,7 @@ func (a *accountAppImpl) Create(ctx context.Context, account *entity.Account) er
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	// 默认密码为账号用户名
 | 
						// 默认密码为账号用户名
 | 
				
			||||||
	account.Password = cryptox.PwdHash(account.Username)
 | 
						account.Password = cryptox.PwdHash(account.Username)
 | 
				
			||||||
	account.Status = entity.AccountEnableStatus
 | 
						account.Status = entity.AccountEnable
 | 
				
			||||||
	return a.Insert(ctx, account)
 | 
						return a.Insert(ctx, account)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ package entity
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"mayfly-go/internal/common/utils"
 | 
						"mayfly-go/internal/common/utils"
 | 
				
			||||||
 | 
						"mayfly-go/pkg/enumx"
 | 
				
			||||||
	"mayfly-go/pkg/model"
 | 
						"mayfly-go/pkg/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -13,7 +14,7 @@ type Account struct {
 | 
				
			|||||||
	Name          string        `json:"name"`
 | 
						Name          string        `json:"name"`
 | 
				
			||||||
	Username      string        `json:"username"`
 | 
						Username      string        `json:"username"`
 | 
				
			||||||
	Password      string        `json:"-"`
 | 
						Password      string        `json:"-"`
 | 
				
			||||||
	Status        int8       `json:"status"`
 | 
						Status        AccountStatus `json:"status"`
 | 
				
			||||||
	LastLoginTime *time.Time    `json:"lastLoginTime"`
 | 
						LastLoginTime *time.Time    `json:"lastLoginTime"`
 | 
				
			||||||
	LastLoginIp   string        `json:"lastLoginIp"`
 | 
						LastLoginIp   string        `json:"lastLoginIp"`
 | 
				
			||||||
	OtpSecret     string        `json:"-"`
 | 
						OtpSecret     string        `json:"-"`
 | 
				
			||||||
@@ -25,7 +26,7 @@ func (a *Account) TableName() string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// 是否可用
 | 
					// 是否可用
 | 
				
			||||||
func (a *Account) IsEnable() bool {
 | 
					func (a *Account) IsEnable() bool {
 | 
				
			||||||
	return a.Status == AccountEnableStatus
 | 
						return a.Status == AccountEnable
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (a *Account) OtpSecretEncrypt() error {
 | 
					func (a *Account) OtpSecretEncrypt() error {
 | 
				
			||||||
@@ -49,7 +50,13 @@ func (a *Account) OtpSecretDecrypt() error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AccountStatus int8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	AccountEnableStatus  int8 = 1  // 启用状态
 | 
						AccountEnable  AccountStatus = 1  // 启用状态
 | 
				
			||||||
	AccountDisableStatus int8 = -1 // 禁用状态
 | 
						AccountDisable AccountStatus = -1 // 禁用状态
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var AccountStatusEnum = enumx.NewEnum[AccountStatus]("账号状态").
 | 
				
			||||||
 | 
						Add(AccountEnable, "启用").
 | 
				
			||||||
 | 
						Add(AccountDisable, "禁用")
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										50
									
								
								server/pkg/enumx/enumx.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								server/pkg/enumx/enumx.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					package enumx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"mayfly-go/pkg/errorx"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Enum[T comparable] struct {
 | 
				
			||||||
 | 
						name string // 枚举值名称
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						values map[T]string // 所有枚举值。枚举值 -> desc(描述)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 新建枚举
 | 
				
			||||||
 | 
					func NewEnum[T comparable](name string) *Enum[T] {
 | 
				
			||||||
 | 
						return &Enum[T]{
 | 
				
			||||||
 | 
							name:   name,
 | 
				
			||||||
 | 
							values: make(map[T]string),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 添加枚举值
 | 
				
			||||||
 | 
					func (e *Enum[T]) Add(value T, desc string) *Enum[T] {
 | 
				
			||||||
 | 
						e.values[value] = desc
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 校验枚举值是否合法
 | 
				
			||||||
 | 
					func (e *Enum[T]) Valid(value T) error {
 | 
				
			||||||
 | 
						_, ok := e.values[value]
 | 
				
			||||||
 | 
						if ok {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						errMsg := fmt.Sprintf("%s可选值为: ", e.name)
 | 
				
			||||||
 | 
						for val, desc := range e.values {
 | 
				
			||||||
 | 
							errMsg = fmt.Sprintf("%s [%v->%s]", errMsg, val, desc)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return errorx.NewBiz(errMsg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 根据枚举值获取描述
 | 
				
			||||||
 | 
					func (e *Enum[T]) GetDesc(value T) string {
 | 
				
			||||||
 | 
						desc, ok := e.values[value]
 | 
				
			||||||
 | 
						if ok {
 | 
				
			||||||
 | 
							return desc
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user