package com.emergencyrepair.bootstrap; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.emergencyrepair.business.dto.Requests; import com.emergencyrepair.business.entity.Acceptance; import com.emergencyrepair.business.entity.BaseEquipment; import com.emergencyrepair.business.entity.CompletionInfo; import com.emergencyrepair.business.entity.EngineeringMajor; import com.emergencyrepair.business.entity.Fault; import com.emergencyrepair.business.entity.ProductNode; import com.emergencyrepair.business.entity.TeamMajor; import com.emergencyrepair.business.entity.WorkOrder; import com.emergencyrepair.business.mapper.AcceptanceMapper; import com.emergencyrepair.business.mapper.BaseEquipmentMapper; import com.emergencyrepair.business.mapper.CompletionInfoMapper; import com.emergencyrepair.business.mapper.EngineeringMajorMapper; import com.emergencyrepair.business.mapper.FaultMapper; import com.emergencyrepair.business.mapper.ProductNodeMapper; import com.emergencyrepair.business.mapper.TeamMajorMapper; import com.emergencyrepair.business.mapper.WorkOrderMapper; import com.emergencyrepair.business.service.BusinessService; import com.emergencyrepair.common.StatusConstants; import com.emergencyrepair.system.entity.SysMenu; import com.emergencyrepair.system.entity.SysRole; import com.emergencyrepair.system.entity.SysRoleMenu; import com.emergencyrepair.system.entity.SysRoleUser; import com.emergencyrepair.system.entity.SysTenantMenu; import com.emergencyrepair.system.mapper.SysMenuMapper; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.emergencyrepair.system.mapper.SysRoleMapper; 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; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @Component @Order(2) @RequiredArgsConstructor public class DataInitializer implements CommandLineRunner { private final SysMenuMapper menuMapper; private final SysRoleMapper roleMapper; private final SysRoleMenuMapper roleMenuMapper; private final SysTenantMenuMapper tenantMenuMapper; private final SysRoleUserMapper roleUserMapper; private final EngineeringMajorMapper engineeringMajorMapper; private final TeamMajorMapper teamMajorMapper; private final CompletionInfoMapper completionInfoMapper; private final BaseEquipmentMapper baseEquipmentMapper; private final ProductNodeMapper productNodeMapper; private final FaultMapper faultMapper; private final WorkOrderMapper workOrderMapper; private final AcceptanceMapper acceptanceMapper; private final BusinessService businessService; private final ObjectMapper objectMapper; private final JdbcTemplate jdbcTemplate; private final ButtonPermissionCatalog buttonPermissionCatalog; private final Map menuIds = new HashMap<>(); private final Map productDeviceIds = new HashMap<>(); private final List contractorIds = new ArrayList<>(); private final Map contractorNames = new HashMap<>(); @Override @Transactional public void run(String... args) { seedMenusAndRoles(); ensureSystemMenus(); ensureCompletionMenus(); normalizeSensitiveTerms(); normalizeEquipmentTerms(); seedButtonMenus(); ensureAdminRoleAssignment(); ensureMajorConfigMenus(); ensureRoleMenuAncestors(); seedMajors(); seedContractors(); seedTrees(); indexProductDevices(); backfillFaultXNoFromEquipment(); linkFaultEquipment(); backfillFaultEquipmentIds(); upgradeDemoFaultEquipment(); upgradeDemoMultiEquipmentFault(); seedBusinessData(); backfillCompletionConsumableCounts(); normalizeParentSystemSeparators(); } private void seedMenusAndRoles() { if (menuMapper.selectCount(null) == 0) { 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, "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); createMenu("completion-query", fault, "完工信息查阅", "/completion/query", null, 1, 90); Long acceptance = createMenu("acceptance", null, "完工验收", null, "el-icon-circle-check", 0, 30); createMenu("accept-application", acceptance, "验收申请", "/acceptance/application", null, 1, 10); createMenu("accept-inspector", acceptance, "质检员验收", "/acceptance/inspector", null, 1, 20); createMenu("accept-leader", acceptance, "质检负责人验收", "/acceptance/leader", null, 1, 30); createMenu("accept-print", acceptance, "完工验收打印输出", "/acceptance/print", null, 1, 40); 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-top", reports, "故障高发设备Top", "/reports/top-equipment", null, 1, 20); createMenu("report-team", reports, "rk_按T统计", "/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); Long systemConfig = createMenu("system-config", system, "系统配置", null, "el-icon-s-tools", 0, 10); createMenu("organization", systemConfig, "组织机构", "/system/organization", null, 1, 10); createMenu("contractors", systemConfig, "承修单位管理", "/system/contractors", null, 1, 20); createMenu("product-tree", systemConfig, "产品结构树", "/system/product-tree", null, 1, 30); createMenu("base-equipment", systemConfig, "设备基础库管理", "/system/base-equipment", null, 1, 40); createMenu("engineering-majors", systemConfig, "工程专业配置", "/system/engineering-majors", null, 1, 50); createMenu("team-majors", systemConfig, "rk_T队专业配置", "/system/team-majors", null, 1, 60); createMenu("three-member", systemConfig, "三员控制", "/system/three-member", null, 1, 70); Long permissionConfig = createMenu("permission-config", system, "权限配置", null, "el-icon-lock", 0, 20); createMenu("users", permissionConfig, "用户管理", "/system/users", null, 1, 10); createMenu("roles", permissionConfig, "角色管理", "/system/roles", null, 1, 20); createMenu("menus", permissionConfig, "菜单管理", "/system/menus", null, 1, 30); Long logConfig = createMenu("log-config", system, "日志管理", null, "el-icon-document", 0, 30); createMenu("login-logs", logConfig, "登录日志", "/system/login-logs", null, 1, 10); createMenu("operation-logs", logConfig, "操作日志", "/system/operation-logs", null, 1, 20); createMenu("error-logs", logConfig, "错误日志", "/system/error-logs", null, 1, 30); } else { for (SysMenu menu : menuMapper.selectList(null)) { menuIds.put(menu.getUrl() == null ? "id-" + menu.getId() : menu.getUrl(), menu.getId()); } } Long allMenuIds = menuMapper.selectCount(null); if (allMenuIds == 0) { return; } if (roleMapper.selectCount(null) > 0) { return; } SysRole systemAdmin = role("系统管理员", "SYS_ADMIN", "SYSTEM_ADMIN", 10, "第一版默认使用 admin 全功能运行"); SysRole securityAdmin = role("安全保密管理员", "SECURITY_ADMIN", "SECURITY_ADMIN", 20, "负责安全保密策略维护"); SysRole auditAdmin = role("安全审计管理员", "AUDIT_ADMIN", "AUDIT_ADMIN", 30, "负责审计日志与访问行为审计"); List allMenus = menuMapper.selectList(null).stream().map(SysMenu::getId).collect(java.util.stream.Collectors.toList()); saveRoleMenus(systemAdmin.getId(), allMenus); saveRoleMenus(securityAdmin.getId(), menuId("dashboard"), menuId("system"), menuId("three-member")); saveRoleMenus(auditAdmin.getId(), menuId("dashboard"), menuId("system"), menuId("three-member")); saveTenantMenus(1L, allMenus); SysRoleUser roleUser = new SysRoleUser(); roleUser.setRoleId(systemAdmin.getId()); roleUser.setUserId(1L); roleUser.setCreateTime(LocalDateTime.now()); roleUserMapper.insert(roleUser); } /** * Adds the two major configuration menus to an already initialized menu tree. * Fresh databases get them from seedMenusAndRoles; this keeps existing ones in sync. */ private void ensureMajorConfigMenus() { SysMenu system = menuMapper.selectOne(Wrappers.lambdaQuery() .eq(SysMenu::getName, "系统管理") .last("LIMIT 1")); SysMenu config = menuMapper.selectOne(Wrappers.lambdaQuery() .eq(SysMenu::getName, "系统配置") .eq(SysMenu::getMenuType, 0) .last("LIMIT 1")); Long pid = config == null ? (system == null ? 0L : system.getId()) : config.getId(); ensureMenu(pid, "工程专业配置", "/system/engineering-majors", 50); ensureMenu(pid, "rk_T队专业配置", "/system/team-majors", 60); } private Long ensureGroupMenu(Long pid, String name, String icon, int sort) { SysMenu menu = menuMapper.selectOne(Wrappers.lambdaQuery() .eq(SysMenu::getPid, pid) .eq(SysMenu::getName, name) .eq(SysMenu::getMenuType, 0) .last("LIMIT 1")); LocalDateTime now = LocalDateTime.now(); if (menu == null) { menu = new SysMenu(); menu.setPid(pid); menu.setName(name); menu.setIcon(icon); menu.setMenuType(0); menu.setSortNo(sort); menu.setVisible(1); menu.setCreateTime(now); menu.setUpdateTime(now); menuMapper.insert(menu); return menu.getId(); } boolean changed = !java.util.Objects.equals(menu.getIcon(), icon) || !java.util.Objects.equals(menu.getSortNo(), sort) || !java.util.Objects.equals(menu.getVisible(), 1); if (changed) { menu.setIcon(icon); menu.setSortNo(sort); menu.setVisible(1); menu.setUpdateTime(now); menuMapper.updateById(menu); } return menu.getId(); } private Long ensureMenu(Long pid, String name, String url, int sort) { SysMenu menu = menuMapper.selectOne(Wrappers.lambdaQuery() .eq(SysMenu::getUrl, url).last("LIMIT 1")); LocalDateTime now = LocalDateTime.now(); if (menu == null) { menu = new SysMenu(); menu.setPid(pid); menu.setName(name); menu.setUrl(url); menu.setMenuType(1); menu.setSortNo(sort); menu.setVisible(1); menu.setCreateTime(now); menu.setUpdateTime(now); menuMapper.insert(menu); return menu.getId(); } // Existing menu names are user-managed; startup only repairs structural fields. boolean changed = !java.util.Objects.equals(menu.getPid(), pid) || !java.util.Objects.equals(menu.getSortNo(), sort) || !java.util.Objects.equals(menu.getMenuType(), 1) || !java.util.Objects.equals(menu.getVisible(), 1); if (changed) { menu.setPid(pid); menu.setMenuType(1); menu.setSortNo(sort); menu.setVisible(1); menu.setUpdateTime(now); menuMapper.updateById(menu); } return menu.getId(); } private void ensureCompletionMenus() { SysMenu fault = menuMapper.selectOne(Wrappers.lambdaQuery() .eq(SysMenu::getName, "故障管理") .eq(SysMenu::getMenuType, 0) .last("LIMIT 1")); Long pid = fault == null ? 0L : fault.getId(); ensureMenu(pid, "完工信息查阅", "/completion/query", 90); grantAdminMenus("/completion/query"); } private void ensureSystemMenus() { SysMenu system = menuMapper.selectOne(Wrappers.lambdaQuery() .eq(SysMenu::getName, "\u7cfb\u7edf\u7ba1\u7406").last("LIMIT 1")); Long pid = system == null ? 0L : system.getId(); Long systemConfig = ensureGroupMenu(pid, "系统配置", "el-icon-s-tools", 10); Long permissionConfig = ensureGroupMenu(pid, "权限配置", "el-icon-lock", 20); Long logConfig = ensureGroupMenu(pid, "日志管理", "el-icon-document", 30); ensureMenu(systemConfig, "组织机构", "/system/organization", 10); ensureMenu(systemConfig, "承修单位管理", "/system/contractors", 20); ensureMenu(systemConfig, "产品结构树", "/system/product-tree", 30); ensureMenu(systemConfig, "设备基础库管理", "/system/base-equipment", 40); ensureMenu(systemConfig, "工程专业配置", "/system/engineering-majors", 50); ensureMenu(systemConfig, "rk_T队专业配置", "/system/team-majors", 60); ensureMenu(systemConfig, "三员控制", "/system/three-member", 70); ensureMenu(permissionConfig, "用户管理", "/system/users", 10); ensureMenu(permissionConfig, "角色管理", "/system/roles", 20); ensureMenu(permissionConfig, "菜单管理", "/system/menus", 30); ensureMenu(logConfig, "登录日志", "/system/login-logs", 10); ensureMenu(logConfig, "操作日志", "/system/operation-logs", 20); ensureMenu(logConfig, "错误日志", "/system/error-logs", 30); removeMenuByUrl("/system/menu-permissions"); grantAdminMenuIds(systemConfig, permissionConfig, logConfig); grantAdminMenus("/system/organization", "/system/contractors", "/system/product-tree", "/system/base-equipment", "/system/engineering-majors", "/system/team-majors", "/system/three-member", "/system/users", "/system/roles", "/system/menus", "/system/login-logs", "/system/operation-logs", "/system/error-logs"); } private void grantAdminMenus(String... urls) { SysRole adminRole = roleMapper.selectOne(Wrappers.lambdaQuery() .eq(SysRole::getCode, "SYS_ADMIN").last("LIMIT 1")); if (adminRole == null) { return; } for (String url : urls) { SysMenu menu = menuMapper.selectOne(Wrappers.lambdaQuery() .eq(SysMenu::getUrl, url).last("LIMIT 1")); if (menu != null) { ensureRoleMenu(adminRole.getId(), menu.getId()); ensureTenantMenu(1L, menu.getId()); } } } private void grantAdminMenuIds(Long... menuIds) { SysRole adminRole = roleMapper.selectOne(Wrappers.lambdaQuery() .eq(SysRole::getCode, "SYS_ADMIN").last("LIMIT 1")); if (adminRole == null) { return; } for (Long menuId : menuIds) { ensureRoleMenu(adminRole.getId(), menuId); ensureTenantMenu(1L, menuId); } } private void removeMenuByUrl(String url) { SysMenu menu = menuMapper.selectOne(Wrappers.lambdaQuery() .eq(SysMenu::getUrl, url).last("LIMIT 1")); if (menu == null) { return; } List children = menuMapper.selectList(Wrappers.lambdaQuery() .eq(SysMenu::getPid, menu.getId())); for (SysMenu child : children) { removeMenuRelations(child.getId()); menuMapper.deleteById(child.getId()); } removeMenuRelations(menu.getId()); menuMapper.deleteById(menu.getId()); } private void removeMenuRelations(Long menuId) { roleMenuMapper.delete(Wrappers.lambdaQuery().eq(SysRoleMenu::getMenuId, menuId)); tenantMenuMapper.delete(Wrappers.lambdaQuery().eq(SysTenantMenu::getMenuId, menuId)); } private void ensureRoleMenuAncestors() { Map menuById = menuMapper.selectList(null).stream() .collect(java.util.stream.Collectors.toMap(SysMenu::getId, item -> item)); List relations = new ArrayList<>(roleMenuMapper.selectList(null)); Set existing = relations.stream() .map(item -> item.getRoleId() + "-" + item.getMenuId()) .collect(java.util.stream.Collectors.toSet()); for (SysRoleMenu relation : relations) { SysMenu menu = menuById.get(relation.getMenuId()); Long cursor = menu == null ? null : menu.getPid(); int guard = 0; while (cursor != null && cursor != 0L && guard++ < 32) { String key = relation.getRoleId() + "-" + cursor; if (existing.add(key)) { ensureRoleMenu(relation.getRoleId(), cursor); } SysMenu parent = menuById.get(cursor); cursor = parent == null ? null : parent.getPid(); } } } /** * 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.lambdaQuery() .eq(SysRole::getCode, "SYS_ADMIN").last("LIMIT 1")); for (Map.Entry> entry : buttonPermissionCatalog.catalog().entrySet()) { SysMenu menu = menuMapper.selectOne(Wrappers.lambdaQuery() .eq(SysMenu::getUrl, entry.getKey()).last("LIMIT 1")); if (menu == null || menu.getMenuType() == null || menu.getMenuType() != 1) { continue; } List definitions = entry.getValue(); for (int index = 0; index < definitions.size(); index++) { ButtonPermissionCatalog.ButtonDefinition definition = definitions.get(index); SysMenu existing = menuMapper.selectOne(Wrappers.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.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.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.lambdaQuery() .eq(SysRole::getCode, "SYS_ADMIN").last("LIMIT 1")); if (adminRole == null) { return; } List 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.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.lambdaQuery().eq(SysRoleUser::getUserId, 1L)); } } /** * Seeds the configurable engineering majors and T team majors (with A/B category). * Categories are a reasonable default split and can be edited from the UI. */ private void seedMajors() { if (engineeringMajorMapper.selectCount(null) == 0) { String[] names = {"动力专业", "电气专业", "液压专业", "辅机专业"}; for (String name : names) { EngineeringMajor major = new EngineeringMajor(); major.setName(name); major.setCreateTime(LocalDateTime.now()); major.setUpdateTime(LocalDateTime.now()); engineeringMajorMapper.insert(major); } } if (teamMajorMapper.selectCount(null) == 0) { String[][] rows = { {"动力专业", "A"}, {"液压专业", "A"}, {"电气专业", "B"}, {"辅机专业", "B"} }; for (String[] row : rows) { TeamMajor major = new TeamMajor(); major.setName(row[0]); major.setCategory(row[1]); major.setCreateTime(LocalDateTime.now()); major.setUpdateTime(LocalDateTime.now()); teamMajorMapper.insert(major); } } } private void seedContractors() { contractorIds.clear(); contractorNames.clear(); List> 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 item = new LinkedHashMap<>(); item.put("id", rs.getLong("DEPT_ID")); item.put("name", rs.getString("DEPT_NAME")); return item; }); for (Map item : rows) { Long id = ((Number) item.get("id")).longValue(); contractorIds.add(id); contractorNames.put(id, String.valueOf(item.get("name"))); } } private void seedTrees() { 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); Long propulsion = base("推进子系统", "BASE-PROP", power, 2, 1); Long transmission = base("传动子系统", "BASE-TRANS", power, 2, 2); Long powerGrid = base("电力子系统", "BASE-GRID", electric, 2, 1); Long control = base("控制子系统", "BASE-CTRL", electric, 2, 2); Long hydraulic = base("液压子系统", "BASE-HYD", deck, 2, 1); Long auxiliary = base("辅机子系统", "BASE-AUX", deck, 2, 2); Long propulsionDevice = base("主推进装置", "DEV-PROP", propulsion, 3, 1); Long gearDevice = base("减速齿轮箱", "DEV-GEAR", transmission, 3, 1); Long distributionDevice = base("主配电装置", "DEV-DIST", powerGrid, 3, 1); Long controlDevice = base("集中控制柜", "DEV-CONTROL", control, 3, 1); Long hydraulicDevice = base("液压泵组", "DEV-HYD", hydraulic, 3, 1); Long compressorDevice = base("空气压缩机组", "DEV-AIR", auxiliary, 3, 1); } } private void seedBusinessData() { if (faultMapper.selectCount(null) > 0 || contractorIds.isEmpty()) { return; } seedFault("GZ-2026-001", "X01", "主推进装置", "动力专业", "重大", StatusConstants.Task.UNREPORTED, LocalDate.of(2026, 9, 8), "滑油压力异常"); seedFault("GZ-2026-002", "X02", "集中控制柜", "电气专业", "一般", StatusConstants.Task.REPORTED_XCB, LocalDate.of(2026, 9, 9), "控制柜偶发报警"); seedFault("GZ-2026-003", "X03", "液压泵组", "液压专业", "一般", StatusConstants.Task.RETURNED, LocalDate.of(2026, 9, 10), "液压压力波动"); seedFault("GZ-2026-004", "X01", "主配电装置", "电气专业", "重大", StatusConstants.Task.XCB_REVIEWED, LocalDate.of(2026, 8, 28), "配电单元温升异常"); seedFault("GZ-2026-005", "X02", "减速齿轮箱", "动力专业", "一般", StatusConstants.Task.CMB_APPROVED, LocalDate.of(2026, 8, 29), "齿轮箱振动偏高"); seedFault("GZ-2026-006", "X03", "空气压缩机组", "辅机专业", "一般", StatusConstants.Task.JCC_ASSISTANT_APPROVED, LocalDate.of(2026, 8, 30), "压缩机组启动困难"); seedFault("GZ-2026-007", "X01", "液压泵组", "液压专业", "一般", StatusConstants.Task.JCC_DIRECTOR_APPROVED, LocalDate.of(2026, 9, 1), "液压泵密封渗漏"); seedFault("GZ-2026-008", "X02", "主推进装置改进型", "动力专业", "重大", StatusConstants.Task.JCC_DIRECTOR_APPROVED, LocalDate.of(2026, 9, 2), "推进装置轴承温度升高"); WorkOrder order9 = dispatchOne("GZ-2026-009", "X03", "集中控制柜", "电气专业", "一般", LocalDate.of(2026, 8, 12), "控制模块通信中断", 0); updateStatus(order9, StatusConstants.Completion.WAIT_PARTS); WorkOrder order10 = dispatchOne("GZ-2026-010", "X01", "主配电装置", "电气专业", "一般", LocalDate.of(2026, 8, 15), "配电保护动作", 1); updateStatus(order10, StatusConstants.Completion.WAIT_TEST); WorkOrder order11 = dispatchOne("GZ-2026-011", "X02", "减速齿轮箱", "动力专业", "一般", LocalDate.of(2026, 8, 18), "齿轮箱异响", 2); complete(order11, "APPLICATION"); WorkOrder order12 = dispatchOne("GZ-2026-012", "X03", "空气压缩机组", "辅机专业", "一般", LocalDate.of(2026, 8, 20), "气阀组件磨损", 3); complete(order12, "INSPECTOR"); WorkOrder order13 = dispatchOne("GZ-2026-013", "X01", "液压泵组", "液压专业", "一般", LocalDate.of(2025, 11, 12), "液压泵噪声增大", 4); complete(order13, "LEADER"); WorkOrder order14 = dispatchOne("GZ-2026-014", "X02", "集中控制柜", "电气专业", "重大", LocalDate.of(2025, 6, 16), "集中控制单元失效", 5); complete(order14, "PRINT"); WorkOrder order15 = dispatchOne("GZ-2026-015", "X03", "主推进装置", "动力专业", "一般", LocalDate.of(2024, 9, 12), "推进装置轴瓦磨损", 6); complete(order15, "RATING"); WorkOrder order16 = dispatchOne("GZ-2026-016", "X01", "集中控制柜", "电气专业", "一般", LocalDate.of(2024, 5, 8), "控制单元电源模块故障", 7); complete(order16, "COMPLETED"); setScore(order13, 4, "运行稳定,建议持续观察"); setScore(order14, 5, "修后质量良好"); setScore(order15, 4, "满足使用要求"); setScore(order16, 5, "复测正常") ; } private void seedFault(String code, String xNo, String equipment, String team, String nature, String status, LocalDate date, String description) { Fault fault = baseFault(code, xNo, equipment, team, nature, date, description); fault.setTaskStatus(status); if (!StatusConstants.Task.UNREPORTED.equals(status)) { int size = contractorIds.size(); List 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"); fault.setXcbReviewTime(LocalDateTime.now()); } faultMapper.insert(fault); } private WorkOrder dispatchOne(String code, String xNo, String equipment, String team, String nature, LocalDate date, String description, int contractorIndex) { Fault fault = baseFault(code, xNo, equipment, team, nature, date, description); fault.setTaskStatus(StatusConstants.Task.JCC_DIRECTOR_APPROVED); Long contractorId = contractorIds.get(contractorIndex % contractorIds.size()); fault.setContractorIds(String.valueOf(contractorId)); fault.setContractorNames(contractorNames.get(contractorId)); fault.setEngineeringNo("LX-" + xNo + "-" + date.toString().replace("-", "").substring(2) + "-001"); fault.setXcbReviewTime(LocalDateTime.now().minusDays(5)); faultMapper.insert(fault); Requests.DispatchRequest request = new Requests.DispatchRequest(); request.setFaultIds(Collections.singletonList(fault.getId())); return businessService.dispatch(request).get(0); } private void complete(WorkOrder workOrder, String targetStage) { Requests.CompletionRequest request = new Requests.CompletionRequest(); request.setWorkOrderId(workOrder.getId()); request.setEngineeringNo(workOrder.getWorkOrderNo() + "-W"); request.setStartDate(LocalDate.now().minusDays(12)); request.setFinishDate(LocalDate.now().minusDays(2)); request.setContractorPerson("承修负责人"); request.setTInternalConstruction("T01-施工组"); request.setRelatedProject("无"); request.setDurationDays(10); request.setPersonCount(4); request.setAcceptanceMode("冷态"); request.setQualityInfo("修理后运行参数稳定"); request.setReasonAnalysis("长期运行磨耗"); request.setFaultDescription("设备运行异常"); request.setItemName(workOrder.getEquipmentName() + "检修"); Requests.SolutionItem firstSolution = new Requests.SolutionItem(); firstSolution.setContent("更换磨损件"); Requests.SolutionItem secondSolution = new Requests.SolutionItem(); secondSolution.setContent("完成复测"); request.setSolutions(Arrays.asList(firstSolution, secondSolution)); Requests.MaterialItem material = new Requests.MaterialItem(); material.setName("密封组件"); material.setSpecification("M-25"); material.setTechnicalParameter("耐压2.5MPa"); material.setSource("库存"); material.setUnit("套"); material.setCertificate("HG-2026-001"); material.setOutboundNo("CK-2026-001"); material.setQuantity(2); request.setMaterials(Collections.singletonList(material)); businessService.submitCompletion(request); Acceptance acceptance = acceptanceMapper.selectOne(Wrappers.lambdaQuery() .eq(Acceptance::getWorkOrderId, workOrder.getId()).last("LIMIT 1")); if (acceptance == null || "APPLICATION".equals(targetStage)) { return; } acceptance.setInspectorResult("通过"); if ("INSPECTOR".equals(targetStage)) { acceptance.setStage("QUALITY_LEADER"); acceptance.setStatus(StatusConstants.Acceptance.QUALITY_LEADER_PENDING); acceptanceMapper.updateById(acceptance); return; } acceptance.setLeaderResult("通过"); if ("LEADER".equals(targetStage)) { acceptance.setStage("PRINT"); acceptance.setStatus(StatusConstants.Acceptance.PRINT_PENDING); acceptanceMapper.updateById(acceptance); return; } acceptance.setPrintTime(LocalDateTime.now().minusDays(1)); if ("PRINT".equals(targetStage)) { acceptance.setStage("RATING"); acceptance.setStatus(StatusConstants.Acceptance.RATING_PENDING); acceptanceMapper.updateById(acceptance); return; } acceptance.setStage("COMPLETED"); acceptance.setStatus(StatusConstants.Acceptance.COMPLETED); acceptance.setRating("优良"); acceptance.setRatingRemark("修后状态满足使用要求"); acceptance.setRatingTime(LocalDateTime.now()); acceptanceMapper.updateById(acceptance); } private void updateStatus(WorkOrder workOrder, String status) { Requests.StatusRequest request = new Requests.StatusRequest(); request.setId(workOrder.getId()); request.setStatus(status); businessService.updateCompletionStatus(request); } private void setScore(WorkOrder workOrder, int score, String opinion) { Requests.ScoreRequest request = new Requests.ScoreRequest(); request.setId(workOrder.getId()); request.setScore(score); request.setOpinion(opinion); businessService.scoreWorkOrder(request); } private void indexProductDevices() { productDeviceIds.clear(); List nodes = productNodeMapper.selectList(null); Map byId = new HashMap<>(); for (ProductNode node : nodes) { byId.put(node.getId(), node); } for (ProductNode node : nodes) { if (!Integer.valueOf(5).equals(node.getNodeLevel())) { continue; } String xNo = findProductXNo(node, byId); if (StringUtils.hasText(xNo) && StringUtils.hasText(node.getName())) { productDeviceIds.putIfAbsent(deviceKey(xNo, node.getName()), node.getId()); } } } private void backfillFaultXNoFromEquipment() { List nodes = productNodeMapper.selectList(null); Map byId = new HashMap<>(); for (ProductNode node : nodes) { byId.put(node.getId(), node); } for (Fault fault : faultMapper.selectList(null)) { if (StringUtils.hasText(fault.getXNo()) || fault.getEquipmentId() == null) { continue; } String xNo = findProductXNo(byId.get(fault.getEquipmentId()), byId); if (!StringUtils.hasText(xNo)) { continue; } fault.setXNo(xNo); fault.setUpdateTime(LocalDateTime.now()); faultMapper.updateById(fault); } } private void linkFaultEquipment() { List faults = faultMapper.selectList(Wrappers.lambdaQuery().isNull(Fault::getEquipmentId)); for (Fault fault : faults) { Long equipmentId = productDeviceIds.get(deviceKey(fault.getXNo(), fault.getEquipmentName())); if (equipmentId == null) { continue; } fault.setEquipmentId(equipmentId); fault.setUpdateTime(LocalDateTime.now()); faultMapper.updateById(fault); } } private void backfillFaultEquipmentIds() { List faults = faultMapper.selectList(Wrappers.lambdaQuery() .isNull(Fault::getEquipmentIds)); for (Fault fault : faults) { if (fault.getEquipmentId() == null) { continue; } fault.setEquipmentIds(String.valueOf(fault.getEquipmentId())); fault.setUpdateTime(LocalDateTime.now()); faultMapper.updateById(fault); } } private void upgradeDemoFaultEquipment() { Fault fault = faultMapper.selectOne(Wrappers.lambdaQuery() .eq(Fault::getFaultCode, "GZ-2026-008") .last("LIMIT 1")); if (fault == null) { return; } Long equipmentId = productDeviceIds.get(deviceKey("X02", "主推进装置改进型")); fault.setEquipmentName("主推进装置改进型"); fault.setEquipmentId(equipmentId); fault.setEquipmentIds(equipmentId == null ? null : String.valueOf(equipmentId)); fault.setUpdateTime(LocalDateTime.now()); faultMapper.updateById(fault); } private void upgradeDemoMultiEquipmentFault() { Fault fault = faultMapper.selectOne(Wrappers.lambdaQuery() .eq(Fault::getFaultCode, "GZ-2026-001") .last("LIMIT 1")); if (fault == null) { return; } Long firstId = productDeviceIds.get(deviceKey("X01", "主推进装置")); Long secondId = productDeviceIds.get(deviceKey("X01", "主配电装置")); if (firstId == null || secondId == null) { return; } fault.setEquipmentId(firstId); fault.setEquipmentIds(firstId + "," + secondId); fault.setEquipmentName("主推进装置、主配电装置"); fault.setParentSystem("动力系统 / 推进子系统、电气系统 / 电力子系统"); fault.setUpdateTime(LocalDateTime.now()); faultMapper.updateById(fault); } private void backfillCompletionConsumableCounts() { List rows = completionInfoMapper.selectList(Wrappers.lambdaQuery() .isNull(CompletionInfo::getConsumableCount)); for (CompletionInfo info : rows) { info.setConsumableCount(materialQuantity(info.getConsumablesJson())); info.setUpdateTime(LocalDateTime.now()); completionInfoMapper.updateById(info); } } private int materialQuantity(String json) { if (!StringUtils.hasText(json)) { return 0; } try { List materials = objectMapper.readValue(json, new TypeReference>() { }); return materials.stream() .filter(item -> item != null && item.getQuantity() != null) .mapToInt(Requests.MaterialItem::getQuantity) .sum(); } catch (Exception ignored) { return 0; } } 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, '按T统计', 'rk_按T统计') WHERE NAME LIKE '%按T统计%' AND NAME NOT LIKE '%rk_按T统计%'"); jdbcTemplate.update("UPDATE LX.T_SYS_MENU SET NAME = REPLACE(NAME, '涉H', 'rk_涉H') WHERE NAME LIKE '%涉H%' AND NAME NOT LIKE '%rk_涉H%'"); } 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()); if (normalized != null && !normalized.equals(fault.getParentSystem())) { fault.setParentSystem(normalized); fault.setUpdateTime(LocalDateTime.now()); faultMapper.updateById(fault); } } for (WorkOrder workOrder : workOrderMapper.selectList(null)) { String normalized = normalizeParentSystem(workOrder.getParentSystem()); if (normalized != null && !normalized.equals(workOrder.getParentSystem())) { workOrder.setParentSystem(normalized); workOrder.setUpdateTime(LocalDateTime.now()); workOrderMapper.updateById(workOrder); } } } private String normalizeParentSystem(String value) { return value == null ? null : value.replace(";", "、").replace(";", "、"); } private String findProductXNo(ProductNode node, Map byId) { ProductNode current = node; while (current != null) { if (Integer.valueOf(2).equals(current.getNodeLevel()) && StringUtils.hasText(current.getName())) { return current.getName(); } current = byId.get(current.getParentId()); } return null; } private String deviceKey(String xNo, String equipmentName) { return (xNo == null ? "" : xNo) + "|" + (equipmentName == null ? "" : equipmentName); } private Fault baseFault(String code, String xNo, String equipment, String team, String nature, LocalDate date, String description) { Fault fault = new Fault(); fault.setFaultCode(code); fault.setXNo(xNo); Long equipmentId = productDeviceIds.get(deviceKey(xNo, equipment)); fault.setEquipmentId(equipmentId); fault.setEquipmentIds(equipmentId == null ? null : String.valueOf(equipmentId)); fault.setEquipmentName(equipment); fault.setParentSystem(equipment.contains("液压") ? "甲板系统" : equipment.contains("控制") ? "电气系统" : "动力系统"); fault.setEngineeringMajor(team); fault.setTeamMajor(team); fault.setReportUnit(team + "rk_T队"); fault.setReportDate(date); fault.setOwner("rk_T员" + xNo); fault.setFaultImpact("供气".equals(team) ? "供气" : "运行"); fault.setFaultNature(nature); fault.setEngineeringNameDesc(description); fault.setRepairRequirement("完成故障定位、修复和功能复测"); fault.setMajorFaultDesc("重大".equals(nature) ? description + ",影响任务执行" : description); fault.setIsSelfRepair(0); fault.setIsHRelated("重大".equals(nature) ? 1 : 0); fault.setIsMonitorItem(1); fault.setMonitorItem(equipment + "运行参数"); fault.setMonitorValue("超限"); fault.setRequestedFinishDate(date.plusDays(30)); fault.setRemark("演示数据"); fault.setCreateTime(LocalDateTime.now()); fault.setUpdateTime(LocalDateTime.now()); return fault; } private Long createMenu(String key, Long pid, String name, String url, String icon, int type, int sort) { SysMenu menu = new SysMenu(); menu.setPid(pid == null ? 0L : pid); menu.setName(name); menu.setUrl(url); menu.setIcon(icon); menu.setMenuType(type); menu.setPermissions(key); menu.setSortNo(sort); menu.setVisible(1); menu.setCreateTime(LocalDateTime.now()); menu.setUpdateTime(LocalDateTime.now()); menuMapper.insert(menu); menuIds.put(key, menu.getId()); return menu.getId(); } private SysRole role(String name, String code, String type, int sort, String remark) { SysRole role = new SysRole(); role.setName(name); role.setCode(code); role.setRoleType(type); role.setSortNo(sort); role.setRemark(remark); role.setCreateTime(LocalDateTime.now()); role.setUpdateTime(LocalDateTime.now()); roleMapper.insert(role); return role; } private void saveRoleMenus(Long roleId, Long... menuIds) { for (Long menuId : menuIds) { if (menuId == null) { continue; } SysRoleMenu relation = new SysRoleMenu(); relation.setRoleId(roleId); relation.setMenuId(menuId); relation.setCreateTime(LocalDateTime.now()); roleMenuMapper.insert(relation); } } private void saveRoleMenus(Long roleId, List menuIds) { saveRoleMenus(roleId, menuIds.toArray(new Long[0])); } private void saveTenantMenus(Long tenantId, List menuIds) { for (Long menuId : menuIds) { SysTenantMenu relation = new SysTenantMenu(); relation.setTenantId(tenantId); relation.setMenuId(menuId); relation.setCreateTime(LocalDateTime.now()); tenantMenuMapper.insert(relation); } } private Long menuId(String key) { return menuIds.get(key); } private Long base(String name, String code, Long parentId, int level, int sort) { BaseEquipment node = new BaseEquipment(); node.setParentId(parentId == null ? 0L : parentId); node.setNodeLevel(level); node.setName(name); node.setCode(code); node.setSortNo(sort); node.setCreateTime(LocalDateTime.now()); node.setUpdateTime(LocalDateTime.now()); baseEquipmentMapper.insert(node); return node.getId(); } }