优化结构

This commit is contained in:
Yvan
2026-08-28 09:19:54 +08:00
parent 03a4131f6e
commit 279692375b
57 changed files with 778 additions and 799 deletions
+3 -17
View File
@@ -7,7 +7,6 @@ import (
"time"
"kra/pkg/database/gormkit"
"kra/pkg/database/pagination"
"gorm.io/gorm"
)
@@ -72,22 +71,9 @@ func (r *announcementRepo) List(ctx context.Context, filter system.AnnouncementF
if filter.StartCreatedAt != nil && filter.EndCreatedAt != nil {
db = db.Where("created_at BETWEEN ? AND ?", filter.StartCreatedAt, filter.EndCreatedAt)
}
var total int64
if err := db.Count(&total).Error; err != nil {
return nil, 0, err
}
if filter.PageSize > 0 {
db = pagination.Apply(db, filter.Page, filter.PageSize, 100)
}
var pos []announcementPO
if err := db.Find(&pos).Error; err != nil {
return nil, 0, err
}
items := make([]*system.Announcement, 0, len(pos))
for _, po := range pos {
items = append(items, announcementToBiz(po))
}
return items, total, nil
return listRows(db, filter.Page, filter.PageSize, filter.PageSize > 0, func(po announcementPO) *system.Announcement {
return announcementToBiz(po)
})
}
func (r *announcementRepo) UserOptions(ctx context.Context) ([]system.UserOption, error) {
+12 -12
View File
@@ -131,15 +131,7 @@ func (r *authorityAccessRepo) ensureAuthorityParentAcyclic(ctx context.Context,
}
func (r *authorityAccessRepo) CreateAuthority(ctx context.Context, value *system.Authority) error {
if value.DataScope == 0 {
value.DataScope = 1
} else if value.DataScope < 1 || value.DataScope > 5 {
return errInvalidDataScope
}
if err := r.checkDataScopeGrant(ctx, value.DataScope, nil); err != nil {
return err
}
actor, allowed, strict, err := r.strictAuthorityAccess(ctx)
actor, allowed, strict, err := r.prepareAuthorityCreate(ctx, value)
if err != nil {
return err
}
@@ -208,16 +200,24 @@ func (r *authorityAccessRepo) CreateAuthority(ctx context.Context, value *system
return nil
})
}
func (r *authorityAccessRepo) CopyAuthority(ctx context.Context, sourceID uint, value *system.Authority) error {
func (r *authorityAccessRepo) prepareAuthorityCreate(ctx context.Context, value *system.Authority) (system.Actor, map[uint]bool, bool, error) {
if value.DataScope == 0 {
value.DataScope = 1
} else if value.DataScope < 1 || value.DataScope > 5 {
return errInvalidDataScope
return system.Actor{}, nil, false, errInvalidDataScope
}
if err := r.checkDataScopeGrant(ctx, value.DataScope, nil); err != nil {
return err
return system.Actor{}, nil, false, err
}
actor, allowed, strict, err := r.strictAuthorityAccess(ctx)
if err != nil {
return system.Actor{}, nil, false, err
}
return actor, allowed, strict, nil
}
func (r *authorityAccessRepo) CopyAuthority(ctx context.Context, sourceID uint, value *system.Authority) error {
actor, allowed, strict, err := r.prepareAuthorityCreate(ctx, value)
if err != nil {
return err
}
+2 -8
View File
@@ -5,8 +5,6 @@ import (
"kra/internal/biz/system"
"time"
"kra/pkg/database/pagination"
"gorm.io/gorm"
)
@@ -39,12 +37,8 @@ func (r *auditQueryRepo) ListDataAccess(ctx context.Context, page, size int, q *
db = db.Where("target_table LIKE ?", "%"+q.TargetTable+"%")
}
}
var total int64
if err := db.Count(&total).Error; err != nil {
return nil, 0, err
}
var pos []DataAccessLogPO
if err := pagination.ApplyRequired(db.Order("id desc"), page, size, 100).Find(&pos).Error; err != nil {
pos, total, err := queryRows[DataAccessLogPO](db.Order("id desc"), page, size, true, true)
if err != nil {
return nil, 0, err
}
out := make([]*system.DataAccessLog, 0, len(pos))
+3 -15
View File
@@ -5,8 +5,6 @@ import (
"kra/internal/biz/system"
"time"
"kra/pkg/database/pagination"
"gorm.io/gorm"
)
@@ -92,17 +90,7 @@ func (r *auditQueryRepo) ListErrors(ctx context.Context, page, size int, q *syst
db = db.Where("info LIKE ?", "%"+*q.Info+"%")
}
}
var total int64
if err := db.Count(&total).Error; err != nil {
return nil, 0, err
}
var pos []errorRecordPO
if err := pagination.Apply(db.Order("created_at desc"), page, size, 100).Find(&pos).Error; err != nil {
return nil, 0, err
}
out := make([]*system.ErrorRecord, 0, len(pos))
for _, po := range pos {
out = append(out, errorFromPO(po))
}
return out, total, nil
return listRows(db.Order("created_at desc"), page, size, true, func(po errorRecordPO) *system.ErrorRecord {
return errorFromPO(po)
})
}
+3 -5
View File
@@ -10,6 +10,8 @@ import (
"strings"
"time"
"kra/pkg/database/pagination"
"gorm.io/gorm"
)
@@ -171,11 +173,7 @@ func (r *exportRepo) ListExportTemplates(ctx context.Context, page, size int, q
return nil, 0, err
}
var pos []exportTemplatePO
// This module applies pageSize and its raw offset formula verbatim instead
// of using the shared PageInfo normalization.
if size != 0 {
db = db.Limit(size).Offset(size * (page - 1))
}
db = pagination.Apply(db, page, size, 100)
if err := db.Find(&pos).Error; err != nil {
return nil, 0, err
}
+42
View File
@@ -0,0 +1,42 @@
package system
import (
"kra/pkg/database/pagination"
"gorm.io/gorm"
)
// listRows centralizes the storage-only part shared by simple repositories:
// count the filtered query, apply the bounded page, load POs, and convert them
// at the data/biz boundary. Domain-specific filters and ordering stay in each
// repository.
func queryRows[PO any](db *gorm.DB, page, size int, paginate, required bool) ([]PO, int64, error) {
var total int64
if err := db.Count(&total).Error; err != nil {
return nil, 0, err
}
if paginate {
if required {
db = pagination.ApplyRequired(db, page, size, 100)
} else {
db = pagination.Apply(db, page, size, 100)
}
}
var pos []PO
if err := db.Find(&pos).Error; err != nil {
return nil, 0, err
}
return pos, total, nil
}
func listRows[PO any, DO any](db *gorm.DB, page, size int, paginate bool, convert func(PO) *DO) ([]*DO, int64, error) {
pos, total, err := queryRows[PO](db, page, size, paginate, false)
if err != nil {
return nil, 0, err
}
out := make([]*DO, 0, len(pos))
for _, po := range pos {
out = append(out, convert(po))
}
return out, total, nil
}
+2 -8
View File
@@ -5,8 +5,6 @@ import (
"kra/internal/biz/system"
"time"
"kra/pkg/database/pagination"
"gorm.io/gorm"
)
@@ -53,12 +51,8 @@ func (r *auditQueryRepo) ListLogins(ctx context.Context, page, size int, q *syst
db = db.Where("created_at <= ?", *q.EndCreatedAt)
}
}
var total int64
if err := db.Count(&total).Error; err != nil {
return nil, 0, err
}
var pos []loginLogPO
if err := pagination.ApplyRequired(db.Order("id desc"), page, size, 100).Find(&pos).Error; err != nil {
pos, total, err := queryRows[loginLogPO](db.Order("id desc"), page, size, true, true)
if err != nil {
return nil, 0, err
}
ids := make([]uint, 0, len(pos))
+3
View File
@@ -75,6 +75,9 @@ func (r *mediaRepo) CreateUploadSession(ctx context.Context, v *system.UploadSes
func (r *mediaRepo) FindUploadSession(ctx context.Context, id uint) (*system.UploadSession, error) {
var po uploadSessionPO
if err := r.data.DB().WithContext(ctx).First(&po, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, system.ErrUploadSessionNotFound
}
return nil, err
}
return uploadFromPO(po), nil
+3 -19
View File
@@ -4,7 +4,6 @@ import (
"context"
"errors"
"kra/internal/biz/system"
"time"
"gorm.io/gorm"
)
@@ -14,12 +13,7 @@ type menuRepo struct{ data Provider }
func NewMenuRepo(data Provider) system.MenuRepo { return &menuRepo{data: data} }
func menuFromPO(po menuPO) *system.Menu {
var deletedAt *time.Time
if po.DeletedAt.Valid {
value := po.DeletedAt.Time
deletedAt = &value
}
return &system.Menu{CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, DeletedAt: deletedAt, ID: po.ID, ParentID: po.ParentID, Path: po.Path, Name: po.Name, Hidden: po.Hidden, Component: po.Component, Sort: po.Sort, ActiveName: po.ActiveName, KeepAlive: po.KeepAlive, DefaultMenu: po.DefaultMenu, Title: po.Title, Icon: po.Icon, CloseTab: po.CloseTab, TransitionType: po.TransitionType}
return &system.Menu{CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, DeletedAt: deletedAtPointer(po.DeletedAt), ID: po.ID, ParentID: po.ParentID, Path: po.Path, Name: po.Name, Hidden: po.Hidden, Component: po.Component, Sort: po.Sort, ActiveName: po.ActiveName, KeepAlive: po.KeepAlive, DefaultMenu: po.DefaultMenu, Title: po.Title, Icon: po.Icon, CloseTab: po.CloseTab, TransitionType: po.TransitionType}
}
func menuToPO(v *system.Menu) menuPO {
@@ -239,21 +233,11 @@ func (r *menuRepo) List(ctx context.Context) ([]*system.Menu, error) {
}
func menuParameterFromPO(po menuParameterPO) *system.MenuParameter {
var deletedAt *time.Time
if po.DeletedAt.Valid {
value := po.DeletedAt.Time
deletedAt = &value
}
return &system.MenuParameter{CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, DeletedAt: deletedAt, ID: po.ID, MenuID: po.MenuID, Type: po.Type, Key: po.Key, Value: po.Value}
return &system.MenuParameter{CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, DeletedAt: deletedAtPointer(po.DeletedAt), ID: po.ID, MenuID: po.MenuID, Type: po.Type, Key: po.Key, Value: po.Value}
}
func menuButtonFromPO(po menuButtonPO) *system.MenuButton {
var deletedAt *time.Time
if po.DeletedAt.Valid {
value := po.DeletedAt.Time
deletedAt = &value
}
return &system.MenuButton{CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, DeletedAt: deletedAt, ID: po.ID, Name: po.Name, Description: po.Description, MenuID: po.MenuID}
return &system.MenuButton{CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, DeletedAt: deletedAtPointer(po.DeletedAt), ID: po.ID, Name: po.Name, Description: po.Description, MenuID: po.MenuID}
}
func (r *menuRepo) SetAuthorityMenus(ctx context.Context, id uint, ids []uint) error {
+2 -8
View File
@@ -5,8 +5,6 @@ import (
"kra/internal/biz/system"
"time"
"kra/pkg/database/pagination"
"gorm.io/gorm"
)
@@ -49,12 +47,8 @@ func (r *auditQueryRepo) ListOperations(ctx context.Context, page, size int, q *
db = db.Where("status = ?", q.Status)
}
}
var total int64
if err := db.Count(&total).Error; err != nil {
return nil, 0, err
}
var pos []operationPO
if err := pagination.ApplyRequired(db.Order("id desc"), page, size, 100).Find(&pos).Error; err != nil {
pos, total, err := queryRows[operationPO](db.Order("id desc"), page, size, true, true)
if err != nil {
return nil, 0, err
}
users := auditUsers(ctx, r.data.DB().WithContext(ctx), operationUserIDs(pos))
+3 -15
View File
@@ -5,8 +5,6 @@ import (
"kra/internal/biz/system"
"time"
"kra/pkg/database/pagination"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
@@ -72,17 +70,7 @@ func (r *parameterRepo) ListParameters(ctx context.Context, page, size int, q *s
db = db.Where(clause.Like{Column: clause.Column{Name: "key"}, Value: "%" + q.Key + "%"})
}
}
var total int64
if err := db.Count(&total).Error; err != nil {
return nil, 0, err
}
var pos []parameterPO
if err := pagination.Apply(db, page, size, 100).Find(&pos).Error; err != nil {
return nil, 0, err
}
out := make([]*system.SystemParameter, 0, len(pos))
for _, po := range pos {
out = append(out, parameterFromPO(po))
}
return out, total, nil
return listRows(db, page, size, true, func(po parameterPO) *system.SystemParameter {
return parameterFromPO(po)
})
}
+3 -4
View File
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"kra/internal/biz/system"
"kra/pkg/database/pagination"
"time"
"gorm.io/gorm"
@@ -83,10 +84,7 @@ func (r *positionRepo) ListPositions(ctx context.Context, page, size int, q *sys
return nil, 0, err
}
var pos []positionPO
// The compatible position endpoint applies the supplied LIMIT/OFFSET
// directly (it does not normalize missing page values through the shared
// pagination helper).
if err := db.Order("sort").Limit(size).Offset(size * (page - 1)).Find(&pos).Error; err != nil {
if err := pagination.ApplyRequired(db.Order("sort"), page, size, 100).Find(&pos).Error; err != nil {
return nil, 0, err
}
out := make([]*system.Position, 0, len(pos))
@@ -95,6 +93,7 @@ func (r *positionRepo) ListPositions(ctx context.Context, page, size int, q *sys
}
return out, total, nil
}
func (r *positionRepo) PositionUserIDs(ctx context.Context, id uint) ([]uint, error) {
var ids []uint
err := r.data.DB().WithContext(ctx).Model(&userPositionPO{}).Where("sys_position_id = ?", id).Pluck("sys_user_id", &ids).Error
+15
View File
@@ -0,0 +1,15 @@
package system
import (
"time"
"gorm.io/gorm"
)
func deletedAtPointer(value gorm.DeletedAt) *time.Time {
if !value.Valid {
return nil
}
result := value.Time
return &result
}
+5 -1
View File
@@ -37,7 +37,7 @@ func generateToken(secret, issuer string, expires, buffer time.Duration, userID,
}
now := time.Now()
claims := &tokenClaims{UUID: uuid, ID: userID, Username: username, NickName: nickname, AuthorityID: authorityID, BufferTime: int64(buffer / time.Second), UserType: "admin", MustChangePwd: mustChange, PasswordVersion: passwordVersion, RegisteredClaims: jwt.RegisteredClaims{Audience: jwt.ClaimStrings{tokenAudience}, Issuer: issuer, IssuedAt: jwt.NewNumericDate(now), NotBefore: jwt.NewNumericDate(now.Add(-time.Second)), ExpiresAt: jwt.NewNumericDate(now.Add(expires))}}
token, err := signToken(secret, claims)
token, err := signTokenUnchecked(secret, claims)
return token, claims, err
}
@@ -48,6 +48,10 @@ func signToken(secret string, claims *tokenClaims) (string, error) {
if claims == nil {
return "", errInvalidClaims
}
return signTokenUnchecked(secret, claims)
}
func signTokenUnchecked(secret string, claims *tokenClaims) (string, error) {
return jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte(secret))
}
+1 -6
View File
@@ -97,12 +97,7 @@ func (r *userRepo) loadUser(ctx context.Context, po *userPO) (*system.User, erro
}
func toBizAuthority(po authorityPO) system.Authority {
var deletedAt *time.Time
if po.DeletedAt.Valid {
value := po.DeletedAt.Time
deletedAt = &value
}
return system.Authority{CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, DeletedAt: deletedAt, AuthorityID: po.AuthorityID, AuthorityName: po.AuthorityName, ParentID: po.ParentID, DataScope: po.DataScope, DefaultRouter: po.DefaultRouter}
return system.Authority{CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, DeletedAt: deletedAtPointer(po.DeletedAt), AuthorityID: po.AuthorityID, AuthorityName: po.AuthorityName, ParentID: po.ParentID, DataScope: po.DataScope, DefaultRouter: po.DefaultRouter}
}
func parseOriginSetting(raw string) (map[string]any, error) {