| | |
| | | |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.json.JSONObject; |
| | | import com.alibaba.excel.EasyExcel; |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
| | |
| | | import com.ruoyi.basic.mapper.StructureItemParameterMapper; |
| | | import com.ruoyi.basic.pojo.StructureItemParameter; |
| | | import com.ruoyi.common.core.domain.Result; |
| | | import com.ruoyi.common.core.domain.entity.SysDictData; |
| | | import com.ruoyi.common.core.domain.entity.SysDept; |
| | | import com.ruoyi.common.core.domain.entity.User; |
| | | import com.ruoyi.common.utils.QueryWrappers; |
| | | import com.ruoyi.device.dto.*; |
| | | import com.ruoyi.device.excel.upload.DeviceImport; |
| | | import com.ruoyi.device.mapper.CollectBridgeMapper; |
| | | import com.ruoyi.device.mapper.DeviceMaintenanceMapper; |
| | | import com.ruoyi.device.mapper.DeviceMapper; |
| | |
| | | import com.ruoyi.inspect.mapper.InsSampleMapper; |
| | | import com.ruoyi.inspect.pojo.InsProduct; |
| | | import com.ruoyi.inspect.util.HackLoopTableRenderPolicy; |
| | | import com.ruoyi.system.mapper.SysDictDataMapper; |
| | | import com.ruoyi.system.mapper.SysDeptMapper; |
| | | import com.ruoyi.system.mapper.UserMapper; |
| | | import lombok.AllArgsConstructor; |
| | | import org.apache.logging.log4j.util.Strings; |
| | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.math.BigDecimal; |
| | | import java.net.URLEncoder; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDate; |
| | |
| | | private DeviceMapper deviceMapper; |
| | | |
| | | private UserMapper userMapper; |
| | | |
| | | private SysDeptMapper sysDeptMapper; |
| | | |
| | | private SysDictDataMapper sysDictDataMapper; |
| | | |
| | | private StructureItemParameterMapper structureItemParameterMapper; |
| | | |
| | |
| | | throw new RuntimeException("导出失败"); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void downloadImportTemplate(HttpServletResponse response) { |
| | | response.reset(); |
| | | response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); |
| | | response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); |
| | | try { |
| | | String fileName = URLEncoder.encode("设备导入模板.xlsx", "UTF-8"); |
| | | response.setHeader("Content-Disposition", "attachment;filename=" + fileName); |
| | | EasyExcel.write(response.getOutputStream(), DeviceImport.class) |
| | | .sheet("设备导入模板") |
| | | .doWrite(Collections.emptyList()); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("设备导入模板下载失败", e); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int importDevice(org.springframework.web.multipart.MultipartFile file) { |
| | | if (file == null || file.isEmpty()) { |
| | | throw new RuntimeException("请选择需要导入的Excel文件"); |
| | | } |
| | | String fileName = file.getOriginalFilename(); |
| | | if (fileName == null || !fileName.toLowerCase(Locale.ROOT).endsWith(".xlsx")) { |
| | | throw new RuntimeException("仅支持.xlsx格式文件"); |
| | | } |
| | | |
| | | final List<DeviceImport> rows; |
| | | try { |
| | | rows = EasyExcel.read(file.getInputStream()) |
| | | .head(DeviceImport.class) |
| | | .sheet() |
| | | .doReadSync(); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("Excel解析失败,请使用下载的导入模板", e); |
| | | } |
| | | if (CollectionUtils.isEmpty(rows)) { |
| | | throw new RuntimeException("导入文件没有设备数据"); |
| | | } |
| | | |
| | | Set<String> managementNumbers = new HashSet<>(); |
| | | for (int i = 0; i < rows.size(); i++) { |
| | | String managementNumber = required(rows.get(i).getManagementNumber(), i + 2, "管理编号"); |
| | | if (!managementNumbers.add(managementNumber)) { |
| | | throw new RuntimeException("第" + (i + 2) + "行:管理编号" + managementNumber + "在文件中重复"); |
| | | } |
| | | } |
| | | Set<String> existingNumbers = baseMapper.selectList(Wrappers.<Device>lambdaQuery() |
| | | .in(Device::getManagementNumber, managementNumbers) |
| | | .select(Device::getManagementNumber)) |
| | | .stream().map(Device::getManagementNumber).collect(Collectors.toSet()); |
| | | |
| | | Map<String, List<SysDept>> departmentMap = sysDeptMapper.selectDeptList(new SysDept()).stream() |
| | | .filter(item -> StringUtils.isNotBlank(item.getDeptName())) |
| | | .collect(Collectors.groupingBy(item -> item.getDeptName().trim())); |
| | | Map<String, List<User>> userMap = userMapper.selectList(Wrappers.<User>lambdaQuery() |
| | | .isNotNull(User::getName).select(User::getId, User::getName)) |
| | | .stream().collect(Collectors.groupingBy(item -> item.getName().trim())); |
| | | Map<String, String> statusMap = dictMap("device_status"); |
| | | Map<String, String> typeMap = dictMap("device_type"); |
| | | |
| | | List<Device> devices = new ArrayList<>(); |
| | | for (int i = 0; i < rows.size(); i++) { |
| | | int rowNumber = i + 2; |
| | | DeviceImport row = rows.get(i); |
| | | String managementNumber = required(row.getManagementNumber(), rowNumber, "管理编号"); |
| | | if (existingNumbers.contains(managementNumber)) { |
| | | throw new RuntimeException("第" + rowNumber + "行:管理编号" + managementNumber + "已存在"); |
| | | } |
| | | |
| | | String laboratoryName = required(row.getLaboratoryName(), rowNumber, "所属部门"); |
| | | List<SysDept> departments = departmentMap.get(laboratoryName); |
| | | if (CollectionUtils.isEmpty(departments) || departments.size() > 1) { |
| | | throw new RuntimeException("第" + rowNumber + "行:所属部门“" + laboratoryName + "”不存在或不唯一"); |
| | | } |
| | | |
| | | Device device = new Device(); |
| | | device.setDeviceName(required(row.getDeviceName(), rowNumber, "仪器名称")); |
| | | device.setSpecificationModel(required(row.getSpecificationModel(), rowNumber, "规格型号")); |
| | | device.setManagementNumber(managementNumber); |
| | | device.setActivationDate(parseDate(row.getActivationDate(), rowNumber, "校准有效期", true)); |
| | | device.setSubordinateDepartmentsId(departments.get(0).getDeptId().intValue()); |
| | | device.setDeviceStatus(Integer.valueOf(dictValue(statusMap, row.getDeviceStatus(), rowNumber, "当前状态", true))); |
| | | device.setCalibrationDate(required(row.getCalibrationDate(), rowNumber, "校准周期(月)")); |
| | | device.setEnDeviceName(trim(row.getEnDeviceName())); |
| | | device.setManufacturer(trim(row.getManufacturer())); |
| | | device.setFactoryNo(trim(row.getFactoryNo())); |
| | | device.setAssetCode(trim(row.getAssetCode())); |
| | | device.setOrigin(trim(row.getOrigin())); |
| | | device.setAcquisitionDate(parseDate(row.getAcquisitionDate(), rowNumber, "购置日期", false)); |
| | | device.setStoragePoint(trim(row.getStoragePoint())); |
| | | device.setTechnicalIndicators(trim(row.getTechnicalIndicators())); |
| | | device.setCalibrationServices(trim(row.getCalibrationServices())); |
| | | device.setLastCalibrationDate(parseDate(row.getLastCalibrationDate(), rowNumber, "最近校准日期", false)); |
| | | device.setNextCalibrationDate(parseDate(row.getNextCalibrationDate(), rowNumber, "下次校准日期", false)); |
| | | device.setLargeCategory(dictValue(typeMap, row.getLargeCategory(), rowNumber, "设备类型", false)); |
| | | device.setUnitPrice(parseDecimal(row.getUnitPrice(), rowNumber, "单价(万元)")); |
| | | |
| | | String managerName = trim(row.getEquipmentManagerName()); |
| | | if (StringUtils.isNotBlank(managerName)) { |
| | | List<User> users = userMap.get(managerName); |
| | | if (CollectionUtils.isEmpty(users) || users.size() > 1) { |
| | | throw new RuntimeException("第" + rowNumber + "行:负责人“" + managerName + "”不存在或不唯一"); |
| | | } |
| | | device.setEquipmentManager(users.get(0).getId()); |
| | | } |
| | | devices.add(device); |
| | | } |
| | | saveBatch(devices); |
| | | return devices.size(); |
| | | } |
| | | |
| | | private Map<String, String> dictMap(String dictType) { |
| | | return sysDictDataMapper.selectDictDataByType(dictType).stream() |
| | | .collect(Collectors.toMap(item -> item.getDictLabel().trim(), SysDictData::getDictValue, (first, second) -> first)); |
| | | } |
| | | |
| | | private String dictValue(Map<String, String> values, String input, int rowNumber, String column, boolean required) { |
| | | String text = trim(input); |
| | | if (StringUtils.isBlank(text)) { |
| | | if (required) { |
| | | throw new RuntimeException("第" + rowNumber + "行:" + column + "不能为空"); |
| | | } |
| | | return null; |
| | | } |
| | | String value = values.get(text); |
| | | if (value == null && values.containsValue(text)) { |
| | | value = text; |
| | | } |
| | | if (value == null) { |
| | | throw new RuntimeException("第" + rowNumber + "行:" + column + "“" + text + "”不在系统字典中"); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | private LocalDateTime parseDate(String input, int rowNumber, String column, boolean required) { |
| | | String text = trim(input); |
| | | if (StringUtils.isBlank(text)) { |
| | | if (required) { |
| | | throw new RuntimeException("第" + rowNumber + "行:" + column + "不能为空"); |
| | | } |
| | | return null; |
| | | } |
| | | try { |
| | | return LocalDate.parse(text.substring(0, Math.min(text.length(), 10)).replace('/', '-'), DateTimeFormatter.ofPattern("yyyy-M-d")) |
| | | .atStartOfDay(); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("第" + rowNumber + "行:" + column + "格式应为yyyy-MM-dd", e); |
| | | } |
| | | } |
| | | |
| | | private BigDecimal parseDecimal(String input, int rowNumber, String column) { |
| | | String text = trim(input); |
| | | if (StringUtils.isBlank(text)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return new BigDecimal(text); |
| | | } catch (NumberFormatException e) { |
| | | throw new RuntimeException("第" + rowNumber + "行:" + column + "必须是数字", e); |
| | | } |
| | | } |
| | | |
| | | private String required(String input, int rowNumber, String column) { |
| | | String value = trim(input); |
| | | if (StringUtils.isBlank(value)) { |
| | | throw new RuntimeException("第" + rowNumber + "行:" + column + "不能为空"); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | private String trim(String value) { |
| | | return value == null ? null : value.trim(); |
| | | } |
| | | } |