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.Contractor; 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.ContractorMapper; 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 lombok.RequiredArgsConstructor; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; 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; @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 ContractorMapper contractorMapper; 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 Map menuIds = new HashMap<>(); private final Map baseIds = new HashMap<>(); private final Map productDeviceIds = new HashMap<>(); private final List contractorIds = new ArrayList<>(); @Override @Transactional public void run(String... args) { seedMenusAndRoles(); ensureMajorConfigMenus(); seedMajors(); seedContractors(); seedTrees(); indexProductDevices(); ensureDemoProductDevices(); 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, "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("completion-list", fault, "完工情况处理", "/fault/completion", null, 1, 70); createMenu("completion-report", fault, "完工信息上报", "/completion/report", null, 1, 80); 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, "按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); 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("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); createMenu("three-member", system, "三员控制", "/system/three-member", null, 1, 70); } 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")); Long pid = system == null ? 0L : system.getId(); ensureMenu(pid, "工程专业配置", "/system/engineering-majors", 35); ensureMenu(pid, "T队专业配置", "/system/team-majors", 36); } private void ensureMenu(Long pid, String name, String url, int sort) { if (menuMapper.selectCount(Wrappers.lambdaQuery().eq(SysMenu::getUrl, url)) > 0) { return; } SysMenu menu = new SysMenu(); menu.setPid(pid); menu.setName(name); menu.setUrl(url); menu.setMenuType(1); menu.setSortNo(sort); menu.setVisible(1); menu.setCreateTime(LocalDateTime.now()); menu.setUpdateTime(LocalDateTime.now()); menuMapper.insert(menu); } /** * 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() { 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()); } } 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); 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); 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); } } 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)) { List 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("、")); 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()); Contractor contractor = contractorMapper.selectById(contractorId); fault.setContractorIds(String.valueOf(contractorId)); fault.setContractorNames(contractor.getName()); 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 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 nodes = productNodeMapper.selectList(Wrappers.lambdaQuery() .eq(ProductNode::getNodeLevel, level) .eq(ProductNode::getName, name) .last("LIMIT 1")); return nodes.isEmpty() ? null : nodes.get(0); } 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 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 + "T队"); fault.setReportDate(date); fault.setOwner("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); 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); } }