From 92fc2f1ad03b589c811066cc4b1da000768b4b70 Mon Sep 17 00:00:00 2001 From: luojiaquan <1583622118@qq.com> Date: Mon, 19 Oct 2026 09:59:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9TMS=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=8F=AA=E5=A2=9E=E9=87=8F=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/system/SysUserController.java | 9 +- .../bms/system/orgsync/OrgSyncService.java | 191 ++++++++++++++++++ .../com/bms/system/orgsync/OrgSyncWriter.java | 22 ++ .../mapper/SysOrgSyncWriterMapper.java | 9 + .../mapper/system/SysOrgSyncWriterMapper.xml | 39 ++++ bms-front/src/views/system/user/index.vue | 10 +- 6 files changed, 271 insertions(+), 9 deletions(-) diff --git a/bms-back/bms-admin/src/main/java/com/bms/web/controller/system/SysUserController.java b/bms-back/bms-admin/src/main/java/com/bms/web/controller/system/SysUserController.java index fbe41f8c..4d83e025 100644 --- a/bms-back/bms-admin/src/main/java/com/bms/web/controller/system/SysUserController.java +++ b/bms-back/bms-admin/src/main/java/com/bms/web/controller/system/SysUserController.java @@ -72,15 +72,16 @@ public class SysUserController extends BaseController } /** - * 从老系统(Oracle)同步部门/角色/用户。 - * 覆盖式迁移:除内置超级管理员外,现有演示部门、角色、用户将被替换。 + * 从 TMS(老系统 Oracle)增量同步用户。 + * 不变更组织机构、不同步角色:已存在用户(优先工号,其次姓名+机构匹配)保持不变, + * 仅新增不存在的用户;机构匹配不到的新用户挂在“威狮国际”下。 */ @PreAuthorize("@ss.hasPermi('system:user:add')") - @Log(title = "用户管理-老系统组织同步", businessType = BusinessType.IMPORT) + @Log(title = "用户管理-TMS同步用户", businessType = BusinessType.IMPORT) @PostMapping("/syncFromOracle") public AjaxResult syncFromOracle() { - Map result = orgSyncService.syncFromOracle(); + Map result = orgSyncService.syncUsersOnly(); return AjaxResult.success(String.valueOf(result.get("summary")), result); } diff --git a/bms-back/bms-system/src/main/java/com/bms/system/orgsync/OrgSyncService.java b/bms-back/bms-system/src/main/java/com/bms/system/orgsync/OrgSyncService.java index 59417ca9..9994c4ae 100644 --- a/bms-back/bms-system/src/main/java/com/bms/system/orgsync/OrgSyncService.java +++ b/bms-back/bms-system/src/main/java/com/bms/system/orgsync/OrgSyncService.java @@ -40,6 +40,9 @@ public class OrgSyncService /** 写库人标记 */ public static final String SYNC_MARKER = "oracle-sync"; + /** TMS 用户增量同步写库人标记 */ + public static final String USER_SYNC_MARKER = "tms-user-sync"; + /** 新用户默认密码(BCrypt,明文 123456) */ private static final String DEFAULT_PASSWORD = "$2a$10$gAOzrNJaYLM2m85.9ykkLO0IPvQktxqee8RVpAu1e3.J0Ujiv4Z0G"; @@ -101,6 +104,194 @@ public class OrgSyncService return result; } + /** + * TMS 用户增量同步(按钮「TMS同步用户」)。 + * 规则: + * 1) 不变动组织机构(sys_dept)、不同步角色/岗位(sys_role、sys_user_role、sys_user_post); + * 2) 只同步用户:已存在的用户一律保持不变,仅新增系统中不存在的用户; + * 3) 匹配优先级:先按工号(EMPLOYEE_CODE = sys_user.user_name)匹配, + * 再按姓名(EMPLOYEE_NAME = sys_user.nick_name)+ 所在机构匹配; + * 4) 新用户部门:按 TMS 部门名称匹配现有机构(优先“威狮国际”直属部门), + * 机构匹配不到的统一挂到根部门“威狮国际”(dept_id=200); + * 5) 新用户 user_id 自增、默认密码 123456、不分配角色。 + */ + public Map syncUsersOnly() + { + long t0 = System.currentTimeMillis(); + + List> deptRows = oracleOrgReader.readAllDept(); + List> empRows = oracleOrgReader.readAllEmployee(); + + // TMS 部门编码 -> 部门名称(TAB_DEPT 中 DEPT_NAME 即机构名) + Map tmsDeptNameByCode = new HashMap(); + for (Map row : deptRows) + { + String code = clean(str(row, "DEPT_CODE")); + String name = clean(str(row, "DEPT_NAME")); + if (code != null && name != null && !tmsDeptNameByCode.containsKey(code)) + { + tmsDeptNameByCode.put(code, name); + } + } + + // 现有机构:部门名称 -> deptId(重名时优先“威狮国际”直属部门) + List bmsDepts = orgSyncWriter.readSyncDepts(); + Map bmsDeptIdByName = new HashMap(); + for (SysDept d : bmsDepts) + { + String name = clean(d.getDeptName()); + if (name == null || d.getDeptId() == null) + { + continue; + } + Long exist = bmsDeptIdByName.get(name); + if (exist == null + || (d.getParentId() != null && d.getParentId().longValue() == ROOT_DEPT_ID + && exist.longValue() != ROOT_DEPT_ID)) + { + bmsDeptIdByName.put(name, d.getDeptId()); + } + } + + // 现有用户匹配索引:工号(小写);姓名 + 机构 + List bmsUsers = orgSyncWriter.readSyncUsers(); + Map userByLoginName = new HashMap(); + Map userByNameDept = new HashMap(); + for (SysUser u : bmsUsers) + { + if (u == null || u.getUserId() == null) + { + continue; + } + if (clean(u.getUserName()) != null + && !userByLoginName.containsKey(u.getUserName().trim().toLowerCase())) + { + userByLoginName.put(u.getUserName().trim().toLowerCase(), u); + } + if (clean(u.getNickName()) != null && u.getDeptId() != null) + { + String key = nameDeptKey(u.getDeptId(), u.getNickName()); + if (!userByNameDept.containsKey(key)) + { + userByNameDept.put(key, u); + } + } + } + + List toInsert = new ArrayList(); + Set batchLoginNames = new HashSet(); + long matchedByCode = 0; + long matchedByName = 0; + long orgFallback = 0; + long skipped = 0; + + for (Map row : empRows) + { + String code = clean(str(row, "EMPLOYEE_CODE")); + String name = clean(str(row, "EMPLOYEE_NAME")); + if (code == null && name == null) + { + skipped++; + continue; + } + if (code != null && BUILTIN_ADMIN.equalsIgnoreCase(code)) + { + // 不动 BMS 内置超级管理员 + skipped++; + continue; + } + + // 按机构匹配部门:TMS DEPT_CODE -> TMS 部门名称 -> 现有 sys_dept;匹配不到挂威狮国际 + Long targetDeptId = ROOT_DEPT_ID; + String deptCode = clean(str(row, "DEPT_CODE")); + if (deptCode != null) + { + String tmsDeptName = tmsDeptNameByCode.get(deptCode); + if (tmsDeptName != null) + { + Long matched = bmsDeptIdByName.get(tmsDeptName); + if (matched != null) + { + targetDeptId = matched; + } + } + } + boolean underRoot = targetDeptId == ROOT_DEPT_ID; + + // 1) 优先工号匹配 + if (code != null && userByLoginName.containsKey(code.toLowerCase())) + { + matchedByCode++; + continue; + } + // 2) 再按姓名 + 所在机构匹配 + if (name != null && userByNameDept.containsKey(nameDeptKey(targetDeptId, name))) + { + matchedByName++; + continue; + } + + // 3) 不存在 -> 新增(工号是登录账号,缺失无法建号) + if (code == null) + { + log.warn("TMS 用户同步跳过:姓名={} 缺少工号(EMPLOYEE_CODE),无法创建登录账号", name); + skipped++; + continue; + } + if (!batchLoginNames.add(code.toLowerCase())) + { + log.warn("TMS 用户同步跳过:工号 {}({}) 在 TMS 数据中重复", code, name); + skipped++; + continue; + } + if (underRoot) + { + orgFallback++; + } + + SysUser u = new SysUser(); + u.setDeptId(targetDeptId); + u.setUserName(code); + u.setNickName(name != null ? truncate(name, 30) : code); + u.setPassword(DEFAULT_PASSWORD); + u.setStatus("1".equals(clean(str(row, "BL_OPEN"))) ? "0" : "1"); + u.setSex(mapSex(clean(str(row, "SEX")))); + u.setEmail(cleanEmail(str(row, "EMAIL"))); + u.setPhonenumber(cleanPhone(str(row, "MOBILE_PHONE"))); + u.setRemark(truncate(clean(str(row, "REMARK")), 500)); + Object createDate = row.get("CREATE_DATE"); + u.setCreateTime(createDate instanceof Date ? (Date) createDate : new Date()); + u.setCreateBy(USER_SYNC_MARKER); + toInsert.add(u); + } + + orgSyncWriter.insertNewUsers(toInsert); + + long cost = System.currentTimeMillis() - t0; + String summary = String.format( + "TMS 用户同步完成:读取 TMS 员工 %d 人,已存在保持不变 %d 人(工号匹配 %d / 姓名+机构匹配 %d),新增 %d 人(其中机构未匹配挂“%s”%d 人),跳过 %d 条,耗时 %dms。新用户默认密码 123456,未分配角色。", + empRows.size(), matchedByCode + matchedByName, matchedByCode, matchedByName, + toInsert.size(), ROOT_DEPT_NAME, orgFallback, skipped, cost); + log.info(summary); + + Map result = new LinkedHashMap(); + result.put("total", empRows.size()); + result.put("existCount", matchedByCode + matchedByName); + result.put("matchedByCode", matchedByCode); + result.put("matchedByName", matchedByName); + result.put("insertCount", toInsert.size()); + result.put("orgFallbackCount", orgFallback); + result.put("skipCount", skipped); + result.put("costMs", cost); + result.put("summary", summary); + return result; + } + + private static String nameDeptKey(Long deptId, String name) + { + return deptId + "|" + name.trim(); + } + private List buildDepts(List> rows) { List list = new ArrayList<>(); diff --git a/bms-back/bms-system/src/main/java/com/bms/system/orgsync/OrgSyncWriter.java b/bms-back/bms-system/src/main/java/com/bms/system/orgsync/OrgSyncWriter.java index f0fa4a97..6d79d2f7 100644 --- a/bms-back/bms-system/src/main/java/com/bms/system/orgsync/OrgSyncWriter.java +++ b/bms-back/bms-system/src/main/java/com/bms/system/orgsync/OrgSyncWriter.java @@ -59,4 +59,26 @@ public class OrgSyncWriter // 6. 超级管理员挂到根部门 writerMapper.updateUserDept(1L, adminDeptId); } + + /** TMS 用户增量同步:读取现有全部未删除部门 */ + public List readSyncDepts() + { + return writerMapper.selectSyncDepts(); + } + + /** TMS 用户增量同步:读取现有全部未删除用户(仅匹配字段) */ + public List readSyncUsers() + { + return writerMapper.selectSyncUsers(); + } + + /** TMS 用户增量同步:仅新增用户(user_id 自增,不触碰部门/角色/岗位),单事务 */ + @Transactional(rollbackFor = Exception.class) + public void insertNewUsers(List users) + { + for (int i = 0; i < users.size(); i += USER_BATCH) + { + writerMapper.batchInsertUserAutoId(users.subList(i, Math.min(i + USER_BATCH, users.size()))); + } + } } diff --git a/bms-back/bms-system/src/main/java/com/bms/system/orgsync/mapper/SysOrgSyncWriterMapper.java b/bms-back/bms-system/src/main/java/com/bms/system/orgsync/mapper/SysOrgSyncWriterMapper.java index e8c74b8b..0a5180ca 100644 --- a/bms-back/bms-system/src/main/java/com/bms/system/orgsync/mapper/SysOrgSyncWriterMapper.java +++ b/bms-back/bms-system/src/main/java/com/bms/system/orgsync/mapper/SysOrgSyncWriterMapper.java @@ -43,4 +43,13 @@ public interface SysOrgSyncWriterMapper /** 将指定用户挂到根部门 */ int updateUserDept(@Param("userId") Long userId, @Param("deptId") Long deptId); + + /** 查询全部未删除部门(TMS 用户增量同步:按部门名称匹配机构) */ + List selectSyncDepts(); + + /** 查询全部未删除用户的匹配字段(TMS 用户增量同步:工号/姓名+机构匹配) */ + List selectSyncUsers(); + + /** 批量新增用户(user_id 自增,不指定 ID,不写角色/岗位) */ + int batchInsertUserAutoId(@Param("list") List list); } diff --git a/bms-back/bms-system/src/main/resources/mapper/system/SysOrgSyncWriterMapper.xml b/bms-back/bms-system/src/main/resources/mapper/system/SysOrgSyncWriterMapper.xml index 79099ab0..4882481e 100644 --- a/bms-back/bms-system/src/main/resources/mapper/system/SysOrgSyncWriterMapper.xml +++ b/bms-back/bms-system/src/main/resources/mapper/system/SysOrgSyncWriterMapper.xml @@ -4,6 +4,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + + + + + + + + + + + + + + + delete from sys_role_dept @@ -62,4 +77,28 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" update sys_user set dept_id = #{deptId} where user_id = #{userId} + + + + + + + insert into sys_user(dept_id, user_name, nick_name, user_type, email, phonenumber, sex, + password, status, del_flag, create_by, create_time, remark) + values + + (#{u.deptId}, #{u.userName}, #{u.nickName}, '00', #{u.email}, #{u.phonenumber}, + #{u.sex}, #{u.password}, #{u.status}, '0', #{u.createBy}, + #{u.createTime}sysdate(), + #{u.remark}) + + diff --git a/bms-front/src/views/system/user/index.vue b/bms-front/src/views/system/user/index.vue index 128a09c2..5be3face 100644 --- a/bms-front/src/views/system/user/index.vue +++ b/bms-front/src/views/system/user/index.vue @@ -28,9 +28,9 @@ 导出 - - - + + TMS同步用户 +