From 073605b6d62363dd7d48f5ca047a1d401418574a Mon Sep 17 00:00:00 2001
From: zzw <228544128@qq.com>
Date: 星期日, 04 十月 2026 17:34:06 +0800
Subject: [PATCH] docs: record 2026-10-04 integration commit

---
 emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DataInitializer.java |  316 +++++++++++++++++++++++++++++++---------------------
 1 files changed, 188 insertions(+), 128 deletions(-)

diff --git a/emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DataInitializer.java b/emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DataInitializer.java
index f4ff232..b186d98 100644
--- a/emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DataInitializer.java
+++ b/emergency-repair-server/src/main/java/com/emergencyrepair/bootstrap/DataInitializer.java
@@ -5,7 +5,6 @@
 import com.emergencyrepair.business.entity.Acceptance;
 import com.emergencyrepair.business.entity.BaseEquipment;
 import com.emergencyrepair.business.entity.CompletionInfo;
-import com.emergencyrepair.business.entity.Contractor;
 import com.emergencyrepair.business.entity.EngineeringMajor;
 import com.emergencyrepair.business.entity.Fault;
 import com.emergencyrepair.business.entity.ProductNode;
@@ -14,7 +13,6 @@
 import com.emergencyrepair.business.mapper.AcceptanceMapper;
 import com.emergencyrepair.business.mapper.BaseEquipmentMapper;
 import com.emergencyrepair.business.mapper.CompletionInfoMapper;
-import com.emergencyrepair.business.mapper.ContractorMapper;
 import com.emergencyrepair.business.mapper.EngineeringMajorMapper;
 import com.emergencyrepair.business.mapper.FaultMapper;
 import com.emergencyrepair.business.mapper.ProductNodeMapper;
@@ -34,10 +32,12 @@
 import com.emergencyrepair.system.mapper.SysRoleMenuMapper;
 import com.emergencyrepair.system.mapper.SysRoleUserMapper;
 import com.emergencyrepair.system.mapper.SysTenantMenuMapper;
+import com.emergencyrepair.system.service.ButtonPermissionCatalog;
 import lombok.RequiredArgsConstructor;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Component;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 
@@ -60,7 +60,6 @@
     private final SysRoleMenuMapper roleMenuMapper;
     private final SysTenantMenuMapper tenantMenuMapper;
     private final SysRoleUserMapper roleUserMapper;
-    private final ContractorMapper contractorMapper;
     private final EngineeringMajorMapper engineeringMajorMapper;
     private final TeamMajorMapper teamMajorMapper;
     private final CompletionInfoMapper completionInfoMapper;
@@ -71,22 +70,27 @@
     private final AcceptanceMapper acceptanceMapper;
     private final BusinessService businessService;
     private final ObjectMapper objectMapper;
+    private final JdbcTemplate jdbcTemplate;
+    private final ButtonPermissionCatalog buttonPermissionCatalog;
 
     private final Map<String, Long> menuIds = new HashMap<>();
-    private final Map<String, Long> baseIds = new HashMap<>();
     private final Map<String, Long> productDeviceIds = new HashMap<>();
     private final List<Long> contractorIds = new ArrayList<>();
+    private final Map<Long, String> contractorNames = new HashMap<>();
 
     @Override
     @Transactional
     public void run(String... args) {
         seedMenusAndRoles();
+        ensureSystemMenus();
+        normalizeSensitiveTerms();
+        normalizeEquipmentTerms();
+        seedButtonMenus();
+        ensureAdminRoleAssignment();
         ensureMajorConfigMenus();
         seedMajors();
         seedContractors();
         seedTrees();
-        indexProductDevices();
-        ensureDemoProductDevices();
         indexProductDevices();
         backfillFaultXNoFromEquipment();
         linkFaultEquipment();
@@ -103,11 +107,11 @@
             createMenu("dashboard", null, "棣栭〉闂ㄦ埛", "/dashboard", "el-icon-s-home", 1, 10);
             Long fault = createMenu("fault", null, "鏁呴殰绠$悊", null, "el-icon-warning-outline", 0, 20);
             createMenu("fault-report", fault, "鏁呴殰涓婃姤", "/fault/report", null, 1, 10);
-            createMenu("xcb-review", fault, "XCB鍔╃悊瀹℃牳", "/fault/review", null, 1, 20);
-            createMenu("cmb-approval", fault, "CMB棰嗗瀹℃壒", "/fault/approval/cmb", null, 1, 30);
-            createMenu("jcc-assistant", fault, "JCC鍔╃悊瀹℃壒", "/fault/approval/jcc-assistant", null, 1, 40);
-            createMenu("jcc-director", fault, "JCC澶勯暱瀹℃壒", "/fault/approval/jcc-director", null, 1, 50);
-            createMenu("dispatch", fault, "XCB鍔╃悊娲惧崟", "/fault/dispatch", null, 1, 60);
+            createMenu("xcb-review", fault, "rk_XCB鍔╃悊瀹℃牳", "/fault/review", null, 1, 20);
+            createMenu("cmb-approval", fault, "rk_CMB棰嗗瀹℃壒", "/fault/approval/cmb", null, 1, 30);
+            createMenu("jcc-assistant", fault, "rk_JCC鍔╃悊瀹℃壒", "/fault/approval/jcc-assistant", null, 1, 40);
+            createMenu("jcc-director", fault, "rk_JCC澶勯暱瀹℃壒", "/fault/approval/jcc-director", null, 1, 50);
+            createMenu("dispatch", fault, "rk_XCB鍔╃悊娲惧崟", "/fault/dispatch", null, 1, 60);
             createMenu("completion-list", fault, "瀹屽伐鎯呭喌澶勭悊", "/fault/completion", null, 1, 70);
             createMenu("completion-report", fault, "瀹屽伐淇℃伅涓婃姤", "/completion/report", null, 1, 80);
 
@@ -119,18 +123,19 @@
             createMenu("accept-rating", acceptance, "淇悗璐ㄩ噺璇勭骇", "/acceptance/rating", null, 1, 50);
 
             Long reports = createMenu("reports", null, "缁熻鎶ヨ〃", null, "el-icon-data-analysis", 0, 40);
-            createMenu("report-overview", reports, "瑁呭鏁呴殰鎬讳綋鍒嗘瀽", "/reports/overview", null, 1, 10);
+            createMenu("report-overview", reports, "璁惧鏁呴殰鎬讳綋鍒嗘瀽", "/reports/overview", null, 1, 10);
             createMenu("report-top", reports, "鏁呴殰楂樺彂璁惧Top", "/reports/top-equipment", null, 1, 20);
-            createMenu("report-team", reports, "鎸塗缁熻", "/reports/by-team", null, 1, 30);
+            createMenu("report-team", reports, "rk_鎸塗缁熻", "/reports/by-team", null, 1, 30);
             createMenu("report-contractor", reports, "鍘傚缁翠慨鎯呭喌", "/reports/contractors", null, 1, 40);
             createMenu("report-trend", reports, "鏁呴殰鏁�/澶囧搧澶囦欢娑堣�楀勾搴﹁秼鍔�", "/reports/trend", null, 1, 50);
 
             Long system = createMenu("system", null, "绯荤粺绠$悊", null, "el-icon-setting", 0, 50);
+            createMenu("organization", system, "缁勭粐鏈烘瀯", "/system/organization", null, 1, 5);
             createMenu("contractors", system, "鎵夸慨鍗曚綅绠$悊", "/system/contractors", null, 1, 10);
             createMenu("product-tree", system, "浜у搧缁撴瀯鏍戠鐞�", "/system/product-tree", null, 1, 20);
             createMenu("base-equipment", system, "璁惧鍩虹搴撶鐞�", "/system/base-equipment", null, 1, 30);
             createMenu("engineering-majors", system, "宸ョ▼涓撲笟閰嶇疆", "/system/engineering-majors", null, 1, 35);
-            createMenu("team-majors", system, "T闃熶笓涓氶厤缃�", "/system/team-majors", null, 1, 36);
+            createMenu("team-majors", system, "rk_T闃熶笓涓氶厤缃�", "/system/team-majors", null, 1, 36);
             createMenu("roles", system, "瑙掕壊绠$悊", "/system/roles", null, 1, 40);
             createMenu("menus", system, "鑿滃崟绠$悊", "/system/menus", null, 1, 50);
             createMenu("menu-permissions", system, "鑿滃崟鏉冮檺绠$悊", "/system/menu-permissions", null, 1, 60);
@@ -175,7 +180,7 @@
                 .last("LIMIT 1"));
         Long pid = system == null ? 0L : system.getId();
         ensureMenu(pid, "宸ョ▼涓撲笟閰嶇疆", "/system/engineering-majors", 35);
-        ensureMenu(pid, "T闃熶笓涓氶厤缃�", "/system/team-majors", 36);
+        ensureMenu(pid, "rk_T闃熶笓涓氶厤缃�", "/system/team-majors", 36);
     }
 
     private void ensureMenu(Long pid, String name, String url, int sort) {
@@ -192,6 +197,134 @@
         menu.setCreateTime(LocalDateTime.now());
         menu.setUpdateTime(LocalDateTime.now());
         menuMapper.insert(menu);
+    }
+
+    private void ensureSystemMenus() {
+        SysMenu system = menuMapper.selectOne(Wrappers.<SysMenu>lambdaQuery()
+                .eq(SysMenu::getName, "\u7cfb\u7edf\u7ba1\u7406").last("LIMIT 1"));
+        Long pid = system == null ? 0L : system.getId();
+        ensureMenu(pid, "缁勭粐鏈烘瀯", "/system/organization", 5);
+        ensureMenu(pid, "\u7528\u6237\u7ba1\u7406", "/system/users", 37);
+        ensureMenu(pid, "\u767b\u5f55\u65e5\u5fd7", "/system/login-logs", 65);
+        ensureMenu(pid, "\u64cd\u4f5c\u65e5\u5fd7", "/system/operation-logs", 66);
+        grantAdminMenus("/system/organization", "/system/users", "/system/login-logs", "/system/operation-logs");
+    }
+
+    private void grantAdminMenus(String... urls) {
+        SysRole adminRole = roleMapper.selectOne(Wrappers.<SysRole>lambdaQuery()
+                .eq(SysRole::getCode, "SYS_ADMIN").last("LIMIT 1"));
+        if (adminRole == null) {
+            return;
+        }
+        for (String url : urls) {
+            SysMenu menu = menuMapper.selectOne(Wrappers.<SysMenu>lambdaQuery()
+                    .eq(SysMenu::getUrl, url).last("LIMIT 1"));
+            if (menu != null) {
+                ensureRoleMenu(adminRole.getId(), menu.getId());
+                ensureTenantMenu(1L, menu.getId());
+            }
+        }
+    }
+
+    /**
+     * Materializes the declarative button catalog as MENU_TYPE=2 rows.
+     * Existing rows are left untouched so manual menu edits are preserved.
+     */
+    private void seedButtonMenus() {
+        SysRole adminRole = roleMapper.selectOne(Wrappers.<SysRole>lambdaQuery()
+                .eq(SysRole::getCode, "SYS_ADMIN").last("LIMIT 1"));
+        for (Map.Entry<String, List<ButtonPermissionCatalog.ButtonDefinition>> entry : buttonPermissionCatalog.catalog().entrySet()) {
+            SysMenu menu = menuMapper.selectOne(Wrappers.<SysMenu>lambdaQuery()
+                    .eq(SysMenu::getUrl, entry.getKey()).last("LIMIT 1"));
+            if (menu == null || menu.getMenuType() == null || menu.getMenuType() != 1) {
+                continue;
+            }
+            List<ButtonPermissionCatalog.ButtonDefinition> definitions = entry.getValue();
+            for (int index = 0; index < definitions.size(); index++) {
+                ButtonPermissionCatalog.ButtonDefinition definition = definitions.get(index);
+                SysMenu existing = menuMapper.selectOne(Wrappers.<SysMenu>lambdaQuery()
+                        .eq(SysMenu::getPid, menu.getId())
+                        .eq(SysMenu::getMenuType, 2)
+                        .eq(SysMenu::getPermissions, definition.getCode())
+                        .last("LIMIT 1"));
+                if (existing != null) {
+                    continue;
+                }
+                SysMenu child = new SysMenu();
+                child.setPid(menu.getId());
+                child.setName(definition.getName());
+                child.setPermissions(definition.getCode());
+                child.setMenuType(2);
+                child.setSortNo((index + 1) * 10);
+                child.setVisible(1);
+                child.setCreateTime(LocalDateTime.now());
+                child.setUpdateTime(LocalDateTime.now());
+                menuMapper.insert(child);
+                if (adminRole != null) {
+                    ensureRoleMenu(adminRole.getId(), child.getId());
+                }
+                ensureTenantMenu(1L, child.getId());
+            }
+        }
+    }
+
+    private void ensureRoleMenu(Long roleId, Long menuId) {
+        if (roleId == null || menuId == null) {
+            return;
+        }
+        long count = roleMenuMapper.selectCount(Wrappers.<SysRoleMenu>lambdaQuery()
+                .eq(SysRoleMenu::getRoleId, roleId).eq(SysRoleMenu::getMenuId, menuId));
+        if (count == 0) {
+            SysRoleMenu relation = new SysRoleMenu();
+            relation.setRoleId(roleId);
+            relation.setMenuId(menuId);
+            relation.setCreateTime(LocalDateTime.now());
+            roleMenuMapper.insert(relation);
+        }
+    }
+
+    private void ensureTenantMenu(Long tenantId, Long menuId) {
+        if (tenantId == null || menuId == null) {
+            return;
+        }
+        long count = tenantMenuMapper.selectCount(Wrappers.<SysTenantMenu>lambdaQuery()
+                .eq(SysTenantMenu::getTenantId, tenantId).eq(SysTenantMenu::getMenuId, menuId));
+        if (count == 0) {
+            SysTenantMenu relation = new SysTenantMenu();
+            relation.setTenantId(tenantId);
+            relation.setMenuId(menuId);
+            relation.setCreateTime(LocalDateTime.now());
+            tenantMenuMapper.insert(relation);
+        }
+    }
+
+    private void ensureAdminRoleAssignment() {
+        SysRole adminRole = roleMapper.selectOne(Wrappers.<SysRole>lambdaQuery()
+                .eq(SysRole::getCode, "SYS_ADMIN").last("LIMIT 1"));
+        if (adminRole == null) {
+            return;
+        }
+        List<Long> ids = jdbcTemplate.query(
+                "SELECT USER_ID FROM CSICZB_ZB.SYS_USER WHERE USER_NAME = 'admin' AND (DEL_FLAG = '0' OR DEL_FLAG IS NULL)",
+                (rs, rowNum) -> rs.getLong(1));
+        if (!ids.isEmpty()) {
+            Long userId = ids.get(0);
+            long count = roleUserMapper.selectCount(Wrappers.<SysRoleUser>lambdaQuery()
+                    .eq(SysRoleUser::getRoleId, adminRole.getId())
+                    .eq(SysRoleUser::getUserId, userId));
+            if (count == 0) {
+                SysRoleUser relation = new SysRoleUser();
+                relation.setRoleId(adminRole.getId());
+                relation.setUserId(userId);
+                relation.setCreateTime(LocalDateTime.now());
+                roleUserMapper.insert(relation);
+            }
+        }
+        Integer placeholder = jdbcTemplate.queryForObject(
+                "SELECT COUNT(*) FROM CSICZB_ZB.SYS_USER WHERE USER_ID = 1", Integer.class);
+        if (placeholder == null || placeholder == 0) {
+            roleUserMapper.delete(Wrappers.<SysRoleUser>lambdaQuery().eq(SysRoleUser::getUserId, 1L));
+        }
     }
 
     /**
@@ -228,42 +361,26 @@
     }
 
     private void seedContractors() {
-        if (contractorMapper.selectCount(null) > 0) {
-            return;
-        }
-        String[][] rows = {
-                {"鍖楁柟鏈虹數淇悊鍘�", "鍖楁柟鏈虹數", "鍘傚", "1", "寮犲伐", "0"},
-                {"娴峰煄鍔ㄥ姏璁惧鍘�", "娴峰煄鍔ㄥ姏", "鍘傚", "2", "鏉庡伐", "0"},
-                {"鑱斿悎鐢垫皵缁翠慨涓績", "鑱斿悎鐢垫皵", "鍘傚", "3", "鐜嬪伐", "0"},
-                {"鍗庤繙鏈烘淇�犲巶", "鍗庤繙鏈烘", "鍘傚", "4", "璧靛伐", "0"},
-                {"姹熸捣鑷姩鍖栨湇鍔¢儴", "姹熸捣鑷姩鍖�", "鏈嶅姟鍟�", "5", "鍛ㄥ伐", "0"},
-                {"杩滆埅鐢叉澘璁惧鍏徃", "杩滆埅鐢叉澘", "鍘傚", "6", "闄堝伐", "0"},
-                {"绮惧伐娑插帇缁翠慨鍘�", "绮惧伐娑插帇", "鍘傚", "7", "鍒樺伐", "0"},
-                {"鍚槑鎺у埗璁惧鍘�", "鍚槑鎺у埗", "鍘傚", "8", "瀛欏伐", "0"},
-                {"鎭掍俊绠$郴宸ョ▼閮�", "鎭掍俊绠$郴", "鏈嶅姟鍟�", "9", "鍚村伐", "1"},
-                {"鏂板煄缁煎悎缁翠慨涓績", "鏂板煄缁翠慨", "缁煎悎鍗曚綅", "10", "閮戝伐", "0"}
-        };
-        for (String[] row : rows) {
-            Contractor contractor = new Contractor();
-            contractor.setName(row[0]);
-            contractor.setShortName(row[1]);
-            contractor.setNature(row[2]);
-            contractor.setSortNo(Integer.valueOf(row[3]));
-            contractor.setContact(row[4]);
-            contractor.setDishonest(Integer.valueOf(row[5]));
-            contractor.setCreateTime(LocalDateTime.now());
-            contractor.setUpdateTime(LocalDateTime.now());
-            contractorMapper.insert(contractor);
-            contractorIds.add(contractor.getId());
+        contractorIds.clear();
+        contractorNames.clear();
+        List<Map<String, Object>> rows = jdbcTemplate.query(
+                "SELECT DEPT_ID, DEPT_NAME FROM CSICZB_ZB.SYS_DEPT " +
+                        "WHERE DEPT_TYPE = 'cj' AND (DEL_FLAG = '0' OR DEL_FLAG IS NULL) ORDER BY ORDER_NUM, DEPT_ID",
+                (rs, rowNum) -> {
+                    Map<String, Object> item = new LinkedHashMap<>();
+                    item.put("id", rs.getLong("DEPT_ID"));
+                    item.put("name", rs.getString("DEPT_NAME"));
+                    return item;
+                });
+        for (Map<String, Object> item : rows) {
+            Long id = ((Number) item.get("id")).longValue();
+            contractorIds.add(id);
+            contractorNames.put(id, String.valueOf(item.get("name")));
         }
     }
 
     private void seedTrees() {
-        if (productNodeMapper.selectCount(null) == 0) {
-            ProductNode model = product("LX-A鍨嬬患鍚堜繚闅滃钩鍙�", "LX-A", null, 1, "MODEL", null, 1);
-            ProductNode x01 = product("X01", "X01", model.getId(), 2, "X_NO", null, 1);
-            ProductNode x02 = product("X02", "X02", model.getId(), 2, "X_NO", null, 2);
-            ProductNode x03 = product("X03", "X03", model.getId(), 2, "X_NO", null, 3);
+        if (baseEquipmentMapper.selectCount(null) == 0) {
             Long power = base("鍔ㄥ姏绯荤粺", "BASE-POWER", null, 1, 1);
             Long electric = base("鐢垫皵绯荤粺", "BASE-ELECTRIC", null, 1, 2);
             Long deck = base("鐢叉澘绯荤粺", "BASE-DECK", null, 1, 3);
@@ -279,20 +396,6 @@
             Long controlDevice = base("闆嗕腑鎺у埗鏌�", "DEV-CONTROL", control, 3, 1);
             Long hydraulicDevice = base("娑插帇娉电粍", "DEV-HYD", hydraulic, 3, 1);
             Long compressorDevice = base("绌烘皵鍘嬬缉鏈虹粍", "DEV-AIR", auxiliary, 3, 1);
-
-            addProductDevice(x01, "鍔ㄥ姏绯荤粺", "SYS-POWER", "鎺ㄨ繘瀛愮郴缁�", "SUB-PROP", "涓绘帹杩涜缃�", "DEV-PROP", propulsionDevice, 1);
-            addProductDevice(x01, "鐢垫皵绯荤粺", "SYS-ELECTRIC", "鐢靛姏瀛愮郴缁�", "SUB-GRID", "涓婚厤鐢佃缃�", "DEV-DIST", distributionDevice, 2);
-            addProductDevice(x01, "鐢叉澘绯荤粺", "SYS-DECK", "娑插帇瀛愮郴缁�", "SUB-HYD", "娑插帇娉电粍", "DEV-HYD", hydraulicDevice, 3);
-            addProductDevice(x02, "鍔ㄥ姏绯荤粺", "SYS-POWER", "浼犲姩瀛愮郴缁�", "SUB-TRANS", "鍑忛�熼娇杞", "DEV-GEAR", gearDevice, 1);
-            addProductDevice(x02, "鐢垫皵绯荤粺", "SYS-ELECTRIC", "鎺у埗瀛愮郴缁�", "SUB-CTRL", "闆嗕腑鎺у埗鏌�", "DEV-CONTROL", controlDevice, 2);
-            addProductDevice(x02, "鐢叉澘绯荤粺", "SYS-DECK", "杈呮満瀛愮郴缁�", "SUB-AUX", "绌烘皵鍘嬬缉鏈虹粍", "DEV-AIR", compressorDevice, 3);
-            addProductDevice(x03, "鍔ㄥ姏绯荤粺", "SYS-POWER", "鎺ㄨ繘瀛愮郴缁�", "SUB-PROP", "涓绘帹杩涜缃�", "DEV-PROP", propulsionDevice, 1);
-            addProductDevice(x03, "鐢垫皵绯荤粺", "SYS-ELECTRIC", "鐢靛姏瀛愮郴缁�", "SUB-GRID", "涓婚厤鐢佃缃�", "DEV-DIST", distributionDevice, 2);
-            addProductDevice(x03, "鐢叉澘绯荤粺", "SYS-DECK", "娑插帇瀛愮郴缁�", "SUB-HYD", "娑插帇娉电粍", "DEV-HYD", hydraulicDevice, 3);
-            addProductDevice(x01, "鐢垫皵绯荤粺", "SYS-ELECTRIC", "鎺у埗瀛愮郴缁�", "SUB-CTRL", "闆嗕腑鎺у埗鏌�", "DEV-CONTROL", controlDevice, 4);
-            addProductDevice(x02, "鍔ㄥ姏绯荤粺", "SYS-POWER", "鎺ㄨ繘瀛愮郴缁�", "SUB-PROP", "涓绘帹杩涜缃敼杩涘瀷", "DEV-PROP-X02", propulsionDevice, 4);
-            addProductDevice(x03, "鐢垫皵绯荤粺", "SYS-ELECTRIC", "鎺у埗瀛愮郴缁�", "SUB-CTRL", "闆嗕腑鎺у埗鏌�", "DEV-CONTROL", controlDevice, 4);
-            addProductDevice(x03, "鐢叉澘绯荤粺", "SYS-DECK", "杈呮満瀛愮郴缁�", "SUB-AUX", "绌烘皵鍘嬬缉鏈虹粍", "DEV-AIR", compressorDevice, 4);
         }
     }
 
@@ -336,8 +439,13 @@
         Fault fault = baseFault(code, xNo, equipment, team, nature, date, description);
         fault.setTaskStatus(status);
         if (!StatusConstants.Task.UNREPORTED.equals(status)) {
-            List<Long> ids = Arrays.asList(contractorIds.get(Math.abs(code.hashCode()) % 7), contractorIds.get((Math.abs(code.hashCode()) + 1) % 7));
-            String names = contractorMapper.selectBatchIds(ids).stream().map(Contractor::getName).collect(java.util.stream.Collectors.joining("銆�"));
+            int size = contractorIds.size();
+            List<Long> ids = Arrays.asList(
+                    contractorIds.get(Math.abs(code.hashCode()) % size),
+                    contractorIds.get((Math.abs(code.hashCode()) + 1) % size));
+            String names = ids.stream().map(contractorNames::get)
+                    .filter(java.util.Objects::nonNull)
+                    .collect(java.util.stream.Collectors.joining("銆�"));
             fault.setContractorIds(ids.stream().map(String::valueOf).collect(java.util.stream.Collectors.joining(",")));
             fault.setContractorNames(names);
             fault.setEngineeringNo("LX-" + xNo + "-" + date.toString().replace("-", "").substring(2) + "-001");
@@ -350,9 +458,8 @@
         Fault fault = baseFault(code, xNo, equipment, team, nature, date, description);
         fault.setTaskStatus(StatusConstants.Task.JCC_DIRECTOR_APPROVED);
         Long contractorId = contractorIds.get(contractorIndex % contractorIds.size());
-        Contractor contractor = contractorMapper.selectById(contractorId);
         fault.setContractorIds(String.valueOf(contractorId));
-        fault.setContractorNames(contractor.getName());
+        fault.setContractorNames(contractorNames.get(contractorId));
         fault.setEngineeringNo("LX-" + xNo + "-" + date.toString().replace("-", "").substring(2) + "-001");
         fault.setXcbReviewTime(LocalDateTime.now().minusDays(5));
         faultMapper.insert(fault);
@@ -460,45 +567,7 @@
         }
     }
 
-    private void ensureDemoProductDevices() {
-        loadBaseIds();
-        ensureProductDevice("X01", "鐢垫皵绯荤粺", "SYS-ELECTRIC", "鎺у埗瀛愮郴缁�", "SUB-CTRL", "闆嗕腑鎺у埗鏌�", "DEV-CONTROL", "DEV-CONTROL", 4);
-        ensureProductDevice("X02", "鍔ㄥ姏绯荤粺", "SYS-POWER", "鎺ㄨ繘瀛愮郴缁�", "SUB-PROP", "涓绘帹杩涜缃敼杩涘瀷", "DEV-PROP-X02", "DEV-PROP", 4);
-        ensureProductDevice("X03", "鐢垫皵绯荤粺", "SYS-ELECTRIC", "鎺у埗瀛愮郴缁�", "SUB-CTRL", "闆嗕腑鎺у埗鏌�", "DEV-CONTROL", "DEV-CONTROL", 4);
-        ensureProductDevice("X03", "鐢叉澘绯荤粺", "SYS-DECK", "杈呮満瀛愮郴缁�", "SUB-AUX", "绌烘皵鍘嬬缉鏈虹粍", "DEV-AIR", "DEV-AIR", 4);
-    }
 
-    private void ensureProductDevice(String xNo, String system1, String code1, String system2, String code2,
-                                     String device, String deviceCode, String baseCode, int sort) {
-        if (productDeviceIds.containsKey(deviceKey(xNo, device))) {
-            return;
-        }
-        ProductNode xNode = productNode(2, xNo);
-        Long baseId = baseIds.get(baseCode);
-        if (xNode == null || baseId == null) {
-            return;
-        }
-        addProductDevice(xNode, system1, code1, system2, code2, device, deviceCode, baseId, sort);
-    }
-
-    private void loadBaseIds() {
-        if (!baseIds.isEmpty()) {
-            return;
-        }
-        for (BaseEquipment node : baseEquipmentMapper.selectList(null)) {
-            if (StringUtils.hasText(node.getCode())) {
-                baseIds.putIfAbsent(node.getCode(), node.getId());
-            }
-        }
-    }
-
-    private ProductNode productNode(int level, String name) {
-        List<ProductNode> nodes = productNodeMapper.selectList(Wrappers.<ProductNode>lambdaQuery()
-                .eq(ProductNode::getNodeLevel, level)
-                .eq(ProductNode::getName, name)
-                .last("LIMIT 1"));
-        return nodes.isEmpty() ? null : nodes.get(0);
-    }
 
     private void backfillFaultXNoFromEquipment() {
         List<ProductNode> nodes = productNodeMapper.selectList(null);
@@ -607,6 +676,20 @@
         }
     }
 
+    private void normalizeSensitiveTerms() {
+        jdbcTemplate.update("UPDATE LX.T_SYS_MENU SET NAME = REPLACE(NAME, 'XCB', 'rk_XCB') WHERE NAME LIKE '%XCB%' AND NAME NOT LIKE '%rk_XCB%'");
+        jdbcTemplate.update("UPDATE LX.T_SYS_MENU SET NAME = REPLACE(NAME, 'CMB', 'rk_CMB') WHERE NAME LIKE '%CMB%' AND NAME NOT LIKE '%rk_CMB%'");
+        jdbcTemplate.update("UPDATE LX.T_SYS_MENU SET NAME = REPLACE(NAME, 'JCC', 'rk_JCC') WHERE NAME LIKE '%JCC%' AND NAME NOT LIKE '%rk_JCC%'");
+        jdbcTemplate.update("UPDATE LX.T_SYS_MENU SET NAME = REPLACE(NAME, 'T闃�', 'rk_T闃�') WHERE NAME LIKE '%T闃�%' AND NAME NOT LIKE '%rk_T闃�%'");
+        jdbcTemplate.update("UPDATE LX.T_SYS_MENU SET NAME = REPLACE(NAME, 'T鍛�', 'rk_T鍛�') WHERE NAME LIKE '%T鍛�%' AND NAME NOT LIKE '%rk_T鍛�%'");
+        jdbcTemplate.update("UPDATE LX.T_SYS_MENU SET NAME = REPLACE(NAME, '鎸塗缁熻', 'rk_鎸塗缁熻') WHERE NAME LIKE '%鎸塗缁熻%' AND NAME NOT LIKE '%rk_鎸塗缁熻%'");
+        jdbcTemplate.update("UPDATE LX.T_SYS_MENU SET NAME = REPLACE(NAME, '娑塇', 'rk_娑塇') WHERE NAME LIKE '%娑塇%' AND NAME NOT LIKE '%rk_娑塇%'");
+    }
+
+    private void normalizeEquipmentTerms() {
+        jdbcTemplate.update("UPDATE LX.T_SYS_MENU SET NAME = REPLACE(NAME, '\u88c5\u5907', '\u8bbe\u5907') WHERE NAME LIKE '%\u88c5\u5907%'");
+    }
+
     private void normalizeParentSystemSeparators() {
         for (Fault fault : faultMapper.selectList(null)) {
             String normalized = normalizeParentSystem(fault.getParentSystem());
@@ -656,9 +739,9 @@
         fault.setParentSystem(equipment.contains("娑插帇") ? "鐢叉澘绯荤粺" : equipment.contains("鎺у埗") ? "鐢垫皵绯荤粺" : "鍔ㄥ姏绯荤粺");
         fault.setEngineeringMajor(team);
         fault.setTeamMajor(team);
-        fault.setReportUnit(team + "T闃�");
+        fault.setReportUnit(team + "rk_T闃�");
         fault.setReportDate(date);
-        fault.setOwner("T鍛�" + xNo);
+        fault.setOwner("rk_T鍛�" + xNo);
         fault.setFaultImpact("渚涙皵".equals(team) ? "渚涙皵" : "杩愯");
         fault.setFaultNature(nature);
         fault.setEngineeringNameDesc(description);
@@ -747,29 +830,6 @@
         node.setCreateTime(LocalDateTime.now());
         node.setUpdateTime(LocalDateTime.now());
         baseEquipmentMapper.insert(node);
-        baseIds.put(code, node.getId());
         return node.getId();
-    }
-
-    private ProductNode product(String name, String code, Long parentId, int level, String type, Long baseEquipmentId, int sort) {
-        ProductNode node = new ProductNode();
-        node.setParentId(parentId == null ? 0L : parentId);
-        node.setNodeLevel(level);
-        node.setNodeType(type);
-        node.setName(name);
-        node.setCode(code);
-        node.setBaseEquipmentId(baseEquipmentId);
-        node.setSortNo(sort);
-        node.setCreateTime(LocalDateTime.now());
-        node.setUpdateTime(LocalDateTime.now());
-        productNodeMapper.insert(node);
-        return node;
-    }
-
-    private void addProductDevice(ProductNode xNode, String system1, String code1, String system2, String code2,
-                                  String device, String code, Long baseId, int sort) {
-        ProductNode node1 = product(system1, code1 + "-" + xNode.getCode(), xNode.getId(), 3, "SYSTEM1", null, sort);
-        ProductNode node2 = product(system2, code2 + "-" + xNode.getCode(), node1.getId(), 4, "SYSTEM2", null, 1);
-        product(device, code + "-" + xNode.getCode(), node2.getId(), 5, "DEVICE", baseId, 1);
     }
 }

--
Gitblit v1.9.1