Refactor employee management

This commit is contained in:
Frudrax Cheng
2026-05-28 10:05:59 +08:00
parent f394d3a8bd
commit d3ee215f61
17 changed files with 5391 additions and 174 deletions
+111 -19
View File
@@ -17,18 +17,57 @@ type UsersService struct{}
func toUserDTO(user models.User) models.UserDTO {
return models.UserDTO{
ID: user.ID,
Username: user.Username,
Name: user.Name,
Email: user.Email,
Role: user.Role,
CreatedAt: user.CreatedAt,
ID: user.ID,
Username: user.Username,
Name: user.Name,
Email: user.Email,
Phone: user.Phone,
EmployeeNo: user.EmployeeNo,
Position: user.Position,
Role: user.Role,
CreatedAt: user.CreatedAt,
EmployeeSerials: user.EmployeeSerials,
}
}
func hasBackendAccess(role string) bool {
return role == "admin" || role == "technician"
}
func isValidEmployeeRole(role string) bool {
return role == "admin" || role == "technician" || role == "employee"
}
// Create 创建用户
func (s *UsersService) Create(dto models.CreateUserDTO) (*models.UserDTO, error) {
name := strings.TrimSpace(dto.Name)
phone := strings.TrimSpace(dto.Phone)
employeeNo := strings.TrimSpace(dto.EmployeeNo)
position := strings.TrimSpace(dto.Position)
role := strings.TrimSpace(dto.Role)
username := strings.TrimSpace(dto.Username)
if username == "" {
username = employeeNo
}
if name == "" {
return nil, errors.New("姓名不能为空")
}
if phone == "" {
return nil, errors.New("电话不能为空")
}
if employeeNo == "" {
return nil, errors.New("工号不能为空")
}
if position == "" {
return nil, errors.New("岗位不能为空")
}
if !isValidEmployeeRole(role) {
return nil, errors.New("角色不正确")
}
if hasBackendAccess(role) && len(dto.Password) < 6 {
return nil, errors.New("管理员和技术员必须设置至少 6 位初始密码")
}
var existing models.User
err := database.DB.Where("username = ?", username).First(&existing).Error
@@ -39,21 +78,48 @@ func (s *UsersService) Create(dto models.CreateUserDTO) (*models.UserDTO, error)
return nil, fmt.Errorf("查询用户失败: %w", err)
}
hashed, err := bcrypt.GenerateFromPassword([]byte(dto.Password), bcrypt.DefaultCost)
if err != nil {
return nil, fmt.Errorf("密码加密失败: %w", err)
err = database.DB.Where("employee_no = ?", employeeNo).First(&existing).Error
if err == nil {
return nil, errors.New("工号已存在")
}
if !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("查询员工工号失败: %w", err)
}
hashed := ""
if hasBackendAccess(role) {
hashBytes, err := bcrypt.GenerateFromPassword([]byte(dto.Password), bcrypt.DefaultCost)
if err != nil {
return nil, fmt.Errorf("密码加密失败: %w", err)
}
hashed = string(hashBytes)
}
user := models.User{
Username: username,
Password: string(hashed),
Name: dto.Name,
Email: dto.Email,
Role: dto.Role,
Username: username,
Password: hashed,
Name: name,
Email: dto.Email,
Phone: phone,
EmployeeNo: employeeNo,
Position: position,
Role: role,
}
if err := database.DB.Create(&user).Error; err != nil {
return nil, fmt.Errorf("创建用户失败: %w", err)
err = database.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&user).Error; err != nil {
return fmt.Errorf("创建员工失败: %w", err)
}
serialService := EmployeeSerialsService{}
if _, err := serialService.GenerateForEmployee(tx, user, user.ID, ""); err != nil {
return err
}
return tx.Preload("EmployeeSerials").First(&user, user.ID).Error
})
if err != nil {
return nil, err
}
dtoOut := toUserDTO(user)
@@ -65,13 +131,14 @@ func (s *UsersService) FindAll(page int, limit int, role string, search string)
var users []models.User
var total int64
db := database.DB.Model(&models.User{})
db := database.DB.Model(&models.User{}).Preload("EmployeeSerials")
if role != "" {
db = db.Where("role = ?", role)
}
if search != "" {
pattern := "%" + search + "%"
db = db.Where("username LIKE ? OR name LIKE ? OR email LIKE ?", pattern, pattern, pattern)
db = db.Where("username LIKE ? OR name LIKE ? OR email LIKE ? OR phone LIKE ? OR employee_no LIKE ? OR position LIKE ?",
pattern, pattern, pattern, pattern, pattern, pattern)
}
if err := db.Count(&total).Error; err != nil {
@@ -114,12 +181,34 @@ func (s *UsersService) Update(userId uint, dto models.UpdateUserDTO, currentUser
}
if dto.Name != "" {
user.Name = dto.Name
user.Name = strings.TrimSpace(dto.Name)
}
if dto.Email != "" {
user.Email = dto.Email
}
if dto.Phone != "" {
user.Phone = strings.TrimSpace(dto.Phone)
}
if dto.EmployeeNo != "" {
employeeNo := strings.TrimSpace(dto.EmployeeNo)
var existing models.User
err := database.DB.Where("employee_no = ? AND id <> ?", employeeNo, userId).First(&existing).Error
if err == nil {
return nil, errors.New("工号已存在")
}
if !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("查询员工工号失败: %w", err)
}
user.EmployeeNo = employeeNo
user.Username = employeeNo
}
if dto.Position != "" {
user.Position = strings.TrimSpace(dto.Position)
}
if dto.Role != "" {
if !isValidEmployeeRole(dto.Role) {
return nil, errors.New("角色不正确")
}
// 防止管理员把自己降级
if user.ID == currentUserId && user.Role == "admin" && dto.Role != "admin" {
return nil, errors.New("不能修改自己的管理员角色")
@@ -141,6 +230,9 @@ func (s *UsersService) ResetPassword(userId uint, newPassword string) error {
if err := database.DB.First(&user, userId).Error; err != nil {
return errors.New("用户不存在")
}
if !hasBackendAccess(user.Role) {
return errors.New("员工无后台登录权限,不能设置密码")
}
hashed, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
if err != nil {