基础架构

This commit is contained in:
2025-07-13 16:36:20 +08:00
parent e3d64e7485
commit 807004f78d
128 changed files with 17232 additions and 11396 deletions

View File

@@ -2,12 +2,19 @@ package repositories
import (
"context"
"tyapi-server/internal/domains/admin/dto"
"tyapi-server/internal/domains/admin/entities"
"tyapi-server/internal/domains/admin/repositories/queries"
"tyapi-server/internal/shared/interfaces"
)
// AdminStats 管理员统计
type AdminStats struct {
TotalAdmins int64
ActiveAdmins int64
TodayLogins int64
TotalOperations int64
}
// AdminRepository 管理员仓储接口
type AdminRepository interface {
interfaces.Repository[entities.Admin]
@@ -17,8 +24,8 @@ type AdminRepository interface {
FindByEmail(ctx context.Context, email string) (*entities.Admin, error)
// 管理员管理
ListAdmins(ctx context.Context, req *dto.AdminListRequest) (*dto.AdminListResponse, error)
GetStats(ctx context.Context) (*dto.AdminStatsResponse, error)
ListAdmins(ctx context.Context, query *queries.ListAdminsQuery) ([]*entities.Admin, int64, error)
GetStats(ctx context.Context, query *queries.GetAdminInfoQuery) (*AdminStats, error)
// 权限管理
GetPermissionsByRole(ctx context.Context, role entities.AdminRole) ([]entities.AdminPermission, error)
@@ -34,7 +41,7 @@ type AdminLoginLogRepository interface {
interfaces.Repository[entities.AdminLoginLog]
// 日志查询
ListLogs(ctx context.Context, req *dto.AdminLoginLogRequest) (*dto.AdminLoginLogResponse, error)
ListLogs(ctx context.Context, query *queries.ListAdminLoginLogQuery) ([]*entities.AdminLoginLog, int64, error)
// 统计查询
GetTodayLoginCount(ctx context.Context) (int64, error)
@@ -46,7 +53,7 @@ type AdminOperationLogRepository interface {
interfaces.Repository[entities.AdminOperationLog]
// 日志查询
ListLogs(ctx context.Context, req *dto.AdminOperationLogRequest) (*dto.AdminOperationLogResponse, error)
ListLogs(ctx context.Context, query *queries.ListAdminOperationLogQuery) ([]*entities.AdminOperationLog, int64, error)
// 统计查询
GetTotalOperations(ctx context.Context) (int64, error)

View File

@@ -1,341 +0,0 @@
package repositories
import (
"context"
"encoding/json"
"fmt"
"time"
"go.uber.org/zap"
"gorm.io/gorm"
"tyapi-server/internal/domains/admin/dto"
"tyapi-server/internal/domains/admin/entities"
"tyapi-server/internal/shared/interfaces"
)
// GormAdminRepository 管理员GORM仓储实现
type GormAdminRepository struct {
db *gorm.DB
logger *zap.Logger
}
// NewGormAdminRepository 创建管理员GORM仓储
func NewGormAdminRepository(db *gorm.DB, logger *zap.Logger) *GormAdminRepository {
return &GormAdminRepository{
db: db,
logger: logger,
}
}
// Create 创建管理员
func (r *GormAdminRepository) Create(ctx context.Context, admin entities.Admin) error {
r.logger.Info("创建管理员", zap.String("username", admin.Username))
return r.db.WithContext(ctx).Create(&admin).Error
}
// GetByID 根据ID获取管理员
func (r *GormAdminRepository) GetByID(ctx context.Context, id string) (entities.Admin, error) {
var admin entities.Admin
err := r.db.WithContext(ctx).Where("id = ?", id).First(&admin).Error
return admin, err
}
// Update 更新管理员
func (r *GormAdminRepository) Update(ctx context.Context, admin entities.Admin) error {
r.logger.Info("更新管理员", zap.String("id", admin.ID))
return r.db.WithContext(ctx).Save(&admin).Error
}
// Delete 删除管理员
func (r *GormAdminRepository) Delete(ctx context.Context, id string) error {
r.logger.Info("删除管理员", zap.String("id", id))
return r.db.WithContext(ctx).Delete(&entities.Admin{}, "id = ?", id).Error
}
// SoftDelete 软删除管理员
func (r *GormAdminRepository) SoftDelete(ctx context.Context, id string) error {
r.logger.Info("软删除管理员", zap.String("id", id))
return r.db.WithContext(ctx).Delete(&entities.Admin{}, "id = ?", id).Error
}
// Restore 恢复管理员
func (r *GormAdminRepository) Restore(ctx context.Context, id string) error {
r.logger.Info("恢复管理员", zap.String("id", id))
return r.db.WithContext(ctx).Unscoped().Model(&entities.Admin{}).Where("id = ?", id).Update("deleted_at", nil).Error
}
// Count 统计管理员数量
func (r *GormAdminRepository) Count(ctx context.Context, options interfaces.CountOptions) (int64, error) {
var count int64
query := r.db.WithContext(ctx).Model(&entities.Admin{})
// 应用过滤条件
if options.Filters != nil {
for key, value := range options.Filters {
query = query.Where(key+" = ?", value)
}
}
// 应用搜索条件
if options.Search != "" {
query = query.Where("username LIKE ? OR email LIKE ? OR real_name LIKE ?",
"%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%")
}
return count, query.Count(&count).Error
}
// Exists 检查管理员是否存在
func (r *GormAdminRepository) Exists(ctx context.Context, id string) (bool, error) {
var count int64
err := r.db.WithContext(ctx).Model(&entities.Admin{}).Where("id = ?", id).Count(&count).Error
return count > 0, err
}
// CreateBatch 批量创建管理员
func (r *GormAdminRepository) CreateBatch(ctx context.Context, admins []entities.Admin) error {
r.logger.Info("批量创建管理员", zap.Int("count", len(admins)))
return r.db.WithContext(ctx).Create(&admins).Error
}
// GetByIDs 根据ID列表获取管理员
func (r *GormAdminRepository) GetByIDs(ctx context.Context, ids []string) ([]entities.Admin, error) {
var admins []entities.Admin
err := r.db.WithContext(ctx).Where("id IN ?", ids).Find(&admins).Error
return admins, err
}
// UpdateBatch 批量更新管理员
func (r *GormAdminRepository) UpdateBatch(ctx context.Context, admins []entities.Admin) error {
r.logger.Info("批量更新管理员", zap.Int("count", len(admins)))
return r.db.WithContext(ctx).Save(&admins).Error
}
// DeleteBatch 批量删除管理员
func (r *GormAdminRepository) DeleteBatch(ctx context.Context, ids []string) error {
r.logger.Info("批量删除管理员", zap.Strings("ids", ids))
return r.db.WithContext(ctx).Delete(&entities.Admin{}, "id IN ?", ids).Error
}
// List 获取管理员列表
func (r *GormAdminRepository) List(ctx context.Context, options interfaces.ListOptions) ([]entities.Admin, error) {
var admins []entities.Admin
query := r.db.WithContext(ctx).Model(&entities.Admin{})
// 应用过滤条件
if options.Filters != nil {
for key, value := range options.Filters {
query = query.Where(key+" = ?", value)
}
}
// 应用搜索条件
if options.Search != "" {
query = query.Where("username LIKE ? OR email LIKE ? OR real_name LIKE ?",
"%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%")
}
// 应用排序
if options.Sort != "" {
order := "ASC"
if options.Order != "" {
order = options.Order
}
query = query.Order(options.Sort + " " + order)
}
// 应用分页
if options.Page > 0 && options.PageSize > 0 {
offset := (options.Page - 1) * options.PageSize
query = query.Offset(offset).Limit(options.PageSize)
}
return admins, query.Find(&admins).Error
}
// WithTx 使用事务
func (r *GormAdminRepository) WithTx(tx interface{}) interfaces.Repository[entities.Admin] {
if gormTx, ok := tx.(*gorm.DB); ok {
return &GormAdminRepository{
db: gormTx,
logger: r.logger,
}
}
return r
}
// FindByUsername 根据用户名查找管理员
func (r *GormAdminRepository) FindByUsername(ctx context.Context, username string) (*entities.Admin, error) {
var admin entities.Admin
err := r.db.WithContext(ctx).Where("username = ?", username).First(&admin).Error
if err != nil {
return nil, err
}
return &admin, nil
}
// FindByEmail 根据邮箱查找管理员
func (r *GormAdminRepository) FindByEmail(ctx context.Context, email string) (*entities.Admin, error) {
var admin entities.Admin
err := r.db.WithContext(ctx).Where("email = ?", email).First(&admin).Error
if err != nil {
return nil, err
}
return &admin, nil
}
// ListAdmins 获取管理员列表(带分页和筛选)
func (r *GormAdminRepository) ListAdmins(ctx context.Context, req *dto.AdminListRequest) (*dto.AdminListResponse, error) {
var admins []entities.Admin
var total int64
query := r.db.WithContext(ctx).Model(&entities.Admin{})
// 应用筛选条件
if req.Username != "" {
query = query.Where("username LIKE ?", "%"+req.Username+"%")
}
if req.Email != "" {
query = query.Where("email LIKE ?", "%"+req.Email+"%")
}
if req.Role != "" {
query = query.Where("role = ?", req.Role)
}
if req.IsActive != nil {
query = query.Where("is_active = ?", *req.IsActive)
}
// 统计总数
if err := query.Count(&total).Error; err != nil {
return nil, err
}
// 应用分页
offset := (req.Page - 1) * req.PageSize
query = query.Offset(offset).Limit(req.PageSize)
// 默认排序
query = query.Order("created_at DESC")
// 查询数据
if err := query.Find(&admins).Error; err != nil {
return nil, err
}
// 转换为DTO
adminInfos := make([]dto.AdminInfo, len(admins))
for i, admin := range admins {
adminInfos[i] = r.convertToAdminInfo(admin)
}
return &dto.AdminListResponse{
Total: total,
Page: req.Page,
Size: req.PageSize,
Admins: adminInfos,
}, nil
}
// GetStats 获取管理员统计信息
func (r *GormAdminRepository) GetStats(ctx context.Context) (*dto.AdminStatsResponse, error) {
var stats dto.AdminStatsResponse
// 总管理员数
if err := r.db.WithContext(ctx).Model(&entities.Admin{}).Count(&stats.TotalAdmins).Error; err != nil {
return nil, err
}
// 激活管理员数
if err := r.db.WithContext(ctx).Model(&entities.Admin{}).Where("is_active = ?", true).Count(&stats.ActiveAdmins).Error; err != nil {
return nil, err
}
// 今日登录数
today := time.Now().Truncate(24 * time.Hour)
if err := r.db.WithContext(ctx).Model(&entities.AdminLoginLog{}).Where("created_at >= ?", today).Count(&stats.TodayLogins).Error; err != nil {
return nil, err
}
// 总操作数
if err := r.db.WithContext(ctx).Model(&entities.AdminOperationLog{}).Count(&stats.TotalOperations).Error; err != nil {
return nil, err
}
return &stats, nil
}
// GetPermissionsByRole 根据角色获取权限
func (r *GormAdminRepository) GetPermissionsByRole(ctx context.Context, role entities.AdminRole) ([]entities.AdminPermission, error) {
var permissions []entities.AdminPermission
query := r.db.WithContext(ctx).
Joins("JOIN admin_role_permissions ON admin_permissions.id = admin_role_permissions.permission_id").
Where("admin_role_permissions.role = ? AND admin_permissions.is_active = ?", role, true)
return permissions, query.Find(&permissions).Error
}
// UpdatePermissions 更新管理员权限
func (r *GormAdminRepository) UpdatePermissions(ctx context.Context, adminID string, permissions []string) error {
permissionsJSON, err := json.Marshal(permissions)
if err != nil {
return fmt.Errorf("序列化权限失败: %w", err)
}
return r.db.WithContext(ctx).
Model(&entities.Admin{}).
Where("id = ?", adminID).
Update("permissions", string(permissionsJSON)).Error
}
// UpdateLoginStats 更新登录统计
func (r *GormAdminRepository) UpdateLoginStats(ctx context.Context, adminID string) error {
return r.db.WithContext(ctx).
Model(&entities.Admin{}).
Where("id = ?", adminID).
Updates(map[string]interface{}{
"last_login_at": time.Now(),
"login_count": gorm.Expr("login_count + 1"),
}).Error
}
// UpdateReviewStats 更新审核统计
func (r *GormAdminRepository) UpdateReviewStats(ctx context.Context, adminID string, approved bool) error {
updates := map[string]interface{}{
"review_count": gorm.Expr("review_count + 1"),
}
if approved {
updates["approved_count"] = gorm.Expr("approved_count + 1")
} else {
updates["rejected_count"] = gorm.Expr("rejected_count + 1")
}
return r.db.WithContext(ctx).
Model(&entities.Admin{}).
Where("id = ?", adminID).
Updates(updates).Error
}
// convertToAdminInfo 转换为管理员信息DTO
func (r *GormAdminRepository) convertToAdminInfo(admin entities.Admin) dto.AdminInfo {
var permissions []string
if admin.Permissions != "" {
json.Unmarshal([]byte(admin.Permissions), &permissions)
}
return dto.AdminInfo{
ID: admin.ID,
Username: admin.Username,
Email: admin.Email,
Phone: admin.Phone,
RealName: admin.RealName,
Role: admin.Role,
IsActive: admin.IsActive,
LastLoginAt: admin.LastLoginAt,
LoginCount: admin.LoginCount,
Permissions: permissions,
CreatedAt: admin.CreatedAt,
}
}

View File

@@ -0,0 +1,9 @@
package queries
type ListAdminLoginLogQuery struct {
Page int `json:"page"`
PageSize int `json:"page_size"`
AdminID string `json:"admin_id"`
StartDate string `json:"start_date"`
EndDate string `json:"end_date"`
}

View File

@@ -0,0 +1,11 @@
package queries
type ListAdminOperationLogQuery struct {
Page int `json:"page"`
PageSize int `json:"page_size"`
AdminID string `json:"admin_id"`
Module string `json:"module"`
Action string `json:"action"`
StartDate string `json:"start_date"`
EndDate string `json:"end_date"`
}

View File

@@ -0,0 +1,16 @@
package queries
import "tyapi-server/internal/domains/admin/entities"
type ListAdminsQuery struct {
Page int `json:"page"`
PageSize int `json:"page_size"`
Username string `json:"username"`
Email string `json:"email"`
Role entities.AdminRole `json:"role"`
IsActive *bool `json:"is_active"`
}
type GetAdminInfoQuery struct {
AdminID string `json:"admin_id"`
}