基础架构

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

@@ -0,0 +1,21 @@
package admin
import (
"context"
"tyapi-server/internal/application/admin/dto/commands"
"tyapi-server/internal/application/admin/dto/queries"
"tyapi-server/internal/application/admin/dto/responses"
)
// AdminApplicationService 管理员应用服务接口
type AdminApplicationService interface {
Login(ctx context.Context, cmd *commands.AdminLoginCommand) (*responses.AdminLoginResponse, error)
CreateAdmin(ctx context.Context, cmd *commands.CreateAdminCommand) error
UpdateAdmin(ctx context.Context, cmd *commands.UpdateAdminCommand) error
ChangePassword(ctx context.Context, cmd *commands.ChangeAdminPasswordCommand) error
ListAdmins(ctx context.Context, query *queries.ListAdminsQuery) (*responses.AdminListResponse, error)
GetAdminByID(ctx context.Context, query *queries.GetAdminInfoQuery) (*responses.AdminInfoResponse, error)
DeleteAdmin(ctx context.Context, cmd *commands.DeleteAdminCommand) error
GetAdminStats(ctx context.Context) (*responses.AdminStatsResponse, error)
}

View File

@@ -0,0 +1,164 @@
package admin
import (
"context"
"encoding/json"
"fmt"
"time"
"go.uber.org/zap"
"golang.org/x/crypto/bcrypt"
"tyapi-server/internal/application/admin/dto/commands"
"tyapi-server/internal/application/admin/dto/queries"
"tyapi-server/internal/application/admin/dto/responses"
"tyapi-server/internal/domains/admin/entities"
"tyapi-server/internal/domains/admin/repositories"
)
// AdminApplicationServiceImpl 管理员应用服务实现
type AdminApplicationServiceImpl struct {
adminRepo repositories.AdminRepository
loginLogRepo repositories.AdminLoginLogRepository
operationLogRepo repositories.AdminOperationLogRepository
permissionRepo repositories.AdminPermissionRepository
logger *zap.Logger
}
// NewAdminApplicationService 创建管理员应用服务
func NewAdminApplicationService(
adminRepo repositories.AdminRepository,
loginLogRepo repositories.AdminLoginLogRepository,
operationLogRepo repositories.AdminOperationLogRepository,
permissionRepo repositories.AdminPermissionRepository,
logger *zap.Logger,
) AdminApplicationService {
return &AdminApplicationServiceImpl{
adminRepo: adminRepo,
loginLogRepo: loginLogRepo,
operationLogRepo: operationLogRepo,
permissionRepo: permissionRepo,
logger: logger,
}
}
func (s *AdminApplicationServiceImpl) Login(ctx context.Context, cmd *commands.AdminLoginCommand) (*responses.AdminLoginResponse, error) {
s.logger.Info("管理员登录", zap.String("username", cmd.Username))
admin, err := s.adminRepo.FindByUsername(ctx, cmd.Username)
if err != nil {
s.logger.Warn("管理员登录失败:用户不存在", zap.String("username", cmd.Username))
return nil, fmt.Errorf("用户名或密码错误")
}
if !admin.IsActive {
s.logger.Warn("管理员登录失败:账户已禁用", zap.String("username", cmd.Username))
return nil, fmt.Errorf("账户已被禁用,请联系管理员")
}
if err := bcrypt.CompareHashAndPassword([]byte(admin.Password), []byte(cmd.Password)); err != nil {
s.logger.Warn("管理员登录失败:密码错误", zap.String("username", cmd.Username))
return nil, fmt.Errorf("用户名或密码错误")
}
if err := s.adminRepo.UpdateLoginStats(ctx, admin.ID); err != nil {
s.logger.Error("更新登录统计失败", zap.Error(err))
}
// This part would ideally be in a separate auth service or helper
token, expiresAt, err := s.generateJWTToken(admin)
if err != nil {
return nil, fmt.Errorf("生成令牌失败: %w", err)
}
permissions, err := s.getAdminPermissions(ctx, admin)
if err != nil {
s.logger.Error("获取管理员权限失败", zap.Error(err))
permissions = []string{}
}
adminInfo := responses.AdminInfoResponse{
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,
}
s.logger.Info("管理员登录成功", zap.String("username", cmd.Username))
return &responses.AdminLoginResponse{
Token: token,
ExpiresAt: expiresAt,
Admin: adminInfo,
}, nil
}
func (s *AdminApplicationServiceImpl) CreateAdmin(ctx context.Context, cmd *commands.CreateAdminCommand) error {
// ... implementation ...
return nil
}
func (s *AdminApplicationServiceImpl) UpdateAdmin(ctx context.Context, cmd *commands.UpdateAdminCommand) error {
// ... implementation ...
return nil
}
func (s *AdminApplicationServiceImpl) ChangePassword(ctx context.Context, cmd *commands.ChangeAdminPasswordCommand) error {
// ... implementation ...
return nil
}
func (s *AdminApplicationServiceImpl) ListAdmins(ctx context.Context, query *queries.ListAdminsQuery) (*responses.AdminListResponse, error) {
// ... implementation ...
return nil, nil
}
func (s *AdminApplicationServiceImpl) GetAdminByID(ctx context.Context, query *queries.GetAdminInfoQuery) (*responses.AdminInfoResponse, error) {
// ... implementation ...
return nil, nil
}
func (s *AdminApplicationServiceImpl) DeleteAdmin(ctx context.Context, cmd *commands.DeleteAdminCommand) error {
// ... implementation ...
return nil
}
func (s *AdminApplicationServiceImpl) GetAdminStats(ctx context.Context) (*responses.AdminStatsResponse, error) {
// ... implementation ...
return nil, nil
}
// Private helper methods from old service
func (s *AdminApplicationServiceImpl) getAdminPermissions(ctx context.Context, admin *entities.Admin) ([]string, error) {
rolePermissions, err := s.adminRepo.GetPermissionsByRole(ctx, admin.Role)
if err != nil {
return nil, err
}
permissions := make([]string, 0, len(rolePermissions))
for _, perm := range rolePermissions {
permissions = append(permissions, perm.Code)
}
if admin.Permissions != "" {
var customPermissions []string
if err := json.Unmarshal([]byte(admin.Permissions), &customPermissions); err == nil {
permissions = append(permissions, customPermissions...)
}
}
return permissions, nil
}
func (s *AdminApplicationServiceImpl) generateJWTToken(admin *entities.Admin) (string, time.Time, error) {
// This should be handled by a dedicated auth service
token := fmt.Sprintf("admin_token_%s_%d", admin.ID, time.Now().Unix())
expiresAt := time.Now().Add(24 * time.Hour)
return token, expiresAt, nil
}

View File

@@ -0,0 +1,44 @@
package commands
// AdminLoginCommand 管理员登录命令
type AdminLoginCommand struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
// CreateAdminCommand 创建管理员命令
type CreateAdminCommand struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
Email string `json:"email" binding:"required,email"`
Phone string `json:"phone"`
RealName string `json:"real_name" binding:"required"`
Role string `json:"role" binding:"required"`
Permissions []string `json:"permissions"`
OperatorID string `json:"-"`
}
// UpdateAdminCommand 更新管理员命令
type UpdateAdminCommand struct {
AdminID string `json:"-"`
Email string `json:"email" binding:"email"`
Phone string `json:"phone"`
RealName string `json:"real_name"`
Role string `json:"role"`
IsActive *bool `json:"is_active"`
Permissions []string `json:"permissions"`
OperatorID string `json:"-"`
}
// ChangeAdminPasswordCommand 修改密码命令
type ChangeAdminPasswordCommand struct {
AdminID string `json:"-"`
OldPassword string `json:"old_password" binding:"required"`
NewPassword string `json:"new_password" binding:"required"`
}
// DeleteAdminCommand 删除管理员命令
type DeleteAdminCommand struct {
AdminID string `json:"-"`
OperatorID string `json:"-"`
}

View File

@@ -0,0 +1,16 @@
package queries
// ListAdminsQuery 获取管理员列表查询
type ListAdminsQuery struct {
Page int `form:"page" binding:"min=1"`
PageSize int `form:"page_size" binding:"min=1,max=100"`
Username string `form:"username"`
Email string `form:"email"`
Role string `form:"role"`
IsActive *bool `form:"is_active"`
}
// GetAdminInfoQuery 获取管理员信息查询
type GetAdminInfoQuery struct {
AdminID string `uri:"id" binding:"required"`
}

View File

@@ -0,0 +1,45 @@
package responses
import (
"time"
"tyapi-server/internal/domains/admin/entities"
)
// AdminLoginResponse 管理员登录响应
type AdminLoginResponse struct {
Token string `json:"token"`
ExpiresAt time.Time `json:"expires_at"`
Admin AdminInfoResponse `json:"admin"`
}
// AdminInfoResponse 管理员信息响应
type AdminInfoResponse struct {
ID string `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Phone string `json:"phone"`
RealName string `json:"real_name"`
Role entities.AdminRole `json:"role"`
IsActive bool `json:"is_active"`
LastLoginAt *time.Time `json:"last_login_at"`
LoginCount int `json:"login_count"`
Permissions []string `json:"permissions"`
CreatedAt time.Time `json:"created_at"`
}
// AdminListResponse 管理员列表响应
type AdminListResponse struct {
Total int64 `json:"total"`
Page int `json:"page"`
Size int `json:"size"`
Admins []AdminInfoResponse `json:"admins"`
}
// AdminStatsResponse 管理员统计响应
type AdminStatsResponse struct {
TotalAdmins int64 `json:"total_admins"`
ActiveAdmins int64 `json:"active_admins"`
TodayLogins int64 `json:"today_logins"`
TotalOperations int64 `json:"total_operations"`
}