liu
2026-10-28 cc5438a25896d19f02b652865781dc443b274354
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package cn.iocoder.yudao.module.hrm.service.employee.listener;
 
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO;
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeEducationMapper;
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeEmergencyContactMapper;
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeMapper;
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeWorkHistoryMapper;
import cn.iocoder.yudao.module.system.api.user.event.AdminUserDeletedEvent;
import cn.iocoder.yudao.module.system.api.user.event.AdminUserUpdatedEvent;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
 
import java.util.List;
 
/**
 * 系统账号变更 -> 员工档案 同步监听器
 *
 * 设计说明:
 * 1. 只处理「已存在员工档案」的账号;没有员工档案的账号(admin、test、用户管理直接建的账号)直接跳过,不报错。
 * 2. 使用 {@link EventListener} 同步执行,与发布方处于同一事务,保证一致性。
 * 3. 监听器内只使用 Mapper,不调用会再次发布事件的 Service,避免死循环。
 *
 * @author 超级管理员
 */
@Component
@Slf4j
public class HrmEmployeeUserSyncListener {
 
    @Resource
    private HrmEmployeeMapper employeeMapper;
    @Resource
    private HrmEmployeeEducationMapper educationMapper;
    @Resource
    private HrmEmployeeWorkHistoryMapper workHistoryMapper;
    @Resource
    private HrmEmployeeEmergencyContactMapper emergencyContactMapper;
 
    /**
     * 删除账号 -> 联动删除员工档案及子表
     */
    @EventListener
    public void onUserDeleted(AdminUserDeletedEvent event) {
        Long userId = event.getUserId();
        if (userId == null) {
            return;
        }
        List<HrmEmployeeDO> employees = employeeMapper.selectList(HrmEmployeeDO::getUserId, userId);
        if (employees.isEmpty()) {
            // admin/test/未建员工档案的账号,直接跳过
            return;
        }
        if (employees.size() > 1) {
            // 一员工一账号约定下不应出现;为安全起见不自动删除
            log.error("[onUserDeleted][用户({}) 关联了 {} 条员工档案,预期为 1 条,跳过自动删除]", userId, employees.size());
            return;
        }
        Long employeeId = employees.get(0).getId();
        deleteEmployeeCascade(employeeId);
        log.info("[onUserDeleted][用户({}) 删除,已联动删除员工档案({})]", userId, employeeId);
    }
 
    /**
     * 修改账号 -> 回写员工档案可对应字段
     */
    @EventListener
    public void onUserUpdated(AdminUserUpdatedEvent event) {
        Long userId = event.getUserId();
        if (userId == null) {
            return;
        }
        List<HrmEmployeeDO> employees = employeeMapper.selectList(HrmEmployeeDO::getUserId, userId);
        if (employees.isEmpty()) {
            // 没有员工档案的账号,直接跳过
            return;
        }
        if (employees.size() > 1) {
            log.error("[onUserUpdated][用户({}) 关联了 {} 条员工档案,预期为 1 条,跳过同步]", userId, employees.size());
            return;
        }
        try {
            HrmEmployeeDO updateObj = new HrmEmployeeDO();
            updateObj.setId(employees.get(0).getId());
            if (StrUtil.isNotBlank(event.getNickname())) {
                updateObj.setName(event.getNickname());
            }
            if (StrUtil.isNotBlank(event.getMobile())) {
                updateObj.setPhone(event.getMobile());
            }
            if (event.getDeptId() != null) {
                updateObj.setDeptId(event.getDeptId());
            }
            if (event.getSex() != null && event.getSex() != 0) {
                updateObj.setGender(event.getSex());
            }
            if (StrUtil.isNotBlank(event.getEmail())) {
                updateObj.setEmail(event.getEmail());
            }
            employeeMapper.updateById(updateObj);
            log.info("[onUserUpdated][用户({}) 修改,已同步员工档案({})]", userId, updateObj.getId());
        } catch (Exception ex) {
            // 修改同步失败不影响账号修改主流程,仅记录日志
            log.error("[onUserUpdated][用户({}) 同步员工档案失败]", userId, ex);
        }
    }
 
    private void deleteEmployeeCascade(Long employeeId) {
        educationMapper.deleteByEmployeeId(employeeId);
        workHistoryMapper.deleteByEmployeeId(employeeId);
        emergencyContactMapper.deleteByEmployeeId(employeeId);
        employeeMapper.deleteById(employeeId);
    }
 
}