This commit is contained in:
mashuai 2025-03-17 18:11:07 +08:00
parent fb771ae29c
commit 0e3276f618
7 changed files with 436 additions and 6 deletions

View File

@ -7,6 +7,7 @@ import com.bonus.common.core.utils.poi.ExcelUtil;
import com.bonus.common.core.web.controller.BaseController;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.core.web.page.TableDataInfo;
import com.bonus.common.security.annotation.RequiresPermissions;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.device.domain.DevInfo;
import com.bonus.material.device.domain.dto.DevInfoImpDto;
@ -26,6 +27,7 @@ import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
@ -212,7 +214,7 @@ public class DevInfoController extends BaseController {
util.exportExcel(response, list, "设备信息数据");
}
@ApiOperation(value = "装备批量录入")
/*@ApiOperation(value = "装备批量录入")
@PostMapping("/importData")
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
String fileName = file.getOriginalFilename();
@ -232,7 +234,7 @@ public class DevInfoController extends BaseController {
Long userId = SecurityUtils.getLoginUser().getUserid();
String message = devInfoService.importMaProp(maPropInfoList, updateSupport, userId);
return success(message);
}
}*/
@ApiOperation(value = "装备模版下载")
@ -241,4 +243,26 @@ public class DevInfoController extends BaseController {
HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
devInfoService.downLoadTemplate(resp);
}
/**
* 设备批量导入模版下载
*/
@ApiOperation(value = "设备批量导入模版下载")
@PostMapping("/downLoadDev")
public void downLoadDev(){
HttpServletResponse resp = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
devInfoService.downLoadDev(resp);
}
/**
* 设备信息导入
* @param file
* @return
*/
@ApiOperation(value = "设备信息导入")
@PostMapping("/importData")
public AjaxResult importData(MultipartFile file)
{
return devInfoService.importTbPeople(file);
}
}

View File

@ -0,0 +1,83 @@
package com.bonus.material.device.domain.vo;
import com.bonus.common.core.annotation.Excel;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.List;
/**
* @author mashuai
* @date 2025/03/17 17:11
*/
@EqualsAndHashCode(callSuper = false)
@Data
@ToString
public class DevTemplateVo {
@ApiModelProperty(value = "装备名称")
@Excel(name = "装备名称")
private String deviceName;
@ApiModelProperty(value = "类型id")
private Long typeId;
@ApiModelProperty(value = "装备类别")
@Excel(name = "装备类目")
private String typeName;
@Excel(name = "装备品牌")
@ApiModelProperty(value = "设备品牌")
private String brand;
@Excel(name = "出厂日期")
@ApiModelProperty(value = "出厂日期")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private String productionDate;
@ApiModelProperty(value = "联系人")
@Excel(name = "联系人")
private String person;
@ApiModelProperty(value = "联系电话")
@Excel(name = "联系电话")
private String personPhone;
@Excel(name = "上架数量编码类型设备默传1")
@ApiModelProperty(value = "上架数量")
private Integer deviceCount;
@Excel(name = "唯一标识符")
@ApiModelProperty(value = "设备唯一标识符")
private String identifyCode;
@ApiModelProperty(value = "检修人")
@Excel(name = "检修人")
private String checkMan;
@ApiModelProperty(value = "检测日期")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@Excel(name = "检修时间2025-03-17")
private String checkDate;
@ApiModelProperty(value = "下次检测日期")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@Excel(name = "下次检测时间2025-03-17")
private String nextCheckDate;
@ApiModelProperty(value = "装备单位")
private String unitName;
@ApiModelProperty(value = "设备天租价")
private Float dayLeasePrice;
@ApiModelProperty(value = "装备证书详情列表")
private List<DevTemplateVo> dtoList;
}

View File

@ -243,5 +243,12 @@ public interface DevInfoMapper {
DevInfoVo getBuyCompanyList(DevInfoVo infoVo);
DevInfoVo selectDeptList(String companyId);
/**
* 根据装备类型名称查询
* @param typeName
* @return
*/
DevInfoVo selectDevTypeByName(String typeName);
}

View File

@ -8,6 +8,7 @@ import com.bonus.material.device.domain.DevInfo;
import com.bonus.material.device.domain.dto.DevInfoImpDto;
import com.bonus.material.device.domain.dto.InfoMotionDto;
import com.bonus.material.device.domain.vo.DevInfoVo;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@ -116,4 +117,17 @@ public interface DevInfoService {
* @return
*/
List<DevInfoVo> getLeaseDevList(DevInfoVo devInfo);
/**
* 设备批量导入模版下载
* @param resp
*/
void downLoadDev(HttpServletResponse resp);
/**
* 设备信息导入
* @param file
* @return
*/
AjaxResult importTbPeople(MultipartFile file);
}

View File

@ -2,6 +2,7 @@ package com.bonus.material.device.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.PhoneUtil;
import com.bonus.common.biz.constant.MaterialConstants;
import com.bonus.common.biz.domain.*;
import com.bonus.common.biz.enums.HttpCodeEnum;
@ -12,6 +13,8 @@ import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.utils.bean.BeanUtils;
import com.bonus.common.core.utils.bean.BeanValidators;
import com.bonus.common.core.utils.encryption.Sm4Utils;
import com.bonus.common.core.utils.poi.ExcelUtil;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.book.domain.BookCarInfoDto;
@ -20,10 +23,7 @@ import com.bonus.material.device.domain.MaDevQc;
import com.bonus.material.device.domain.Table;
import com.bonus.material.device.domain.dto.DevInfoImpDto;
import com.bonus.material.device.domain.dto.InfoMotionDto;
import com.bonus.material.device.domain.vo.DevInfoPropertyVo;
import com.bonus.material.device.domain.vo.DevInfoVo;
import com.bonus.material.device.domain.vo.DevNameVo;
import com.bonus.material.device.domain.vo.LeaseVo;
import com.bonus.material.device.domain.vo.*;
import com.bonus.material.device.mapper.BmFileInfoMapper;
import com.bonus.material.device.mapper.DevInfoMapper;
import com.bonus.material.device.mapper.MaDevQcMapper;
@ -35,10 +35,13 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
@ -47,6 +50,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.stream.Collectors;
@ -870,6 +876,289 @@ public class DevInfoServiceImpl implements DevInfoService {
return devInfoMapper.getLeaseDevList(devInfo);
}
/**
* 设备批量导入模版下载
* @param response
*/
@Override
public void downLoadDev(HttpServletResponse response) {
//模板名称
String templateName = "MaDevTemplate.xlsx";
OutputStream out = null;
InputStream input =null;
try {
input = this.getClass().getClassLoader().getResourceAsStream("template/MaDevTemplate.xlsx");
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition",
"attachment;filename=" + new String((templateName).getBytes(), "iso-8859-1"));
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
out = response.getOutputStream();
// 缓冲区
byte[] buffer = new byte[1024];
int bytesToRead = -1;
// 通过循环将读入内容输出到浏览器中
while ((bytesToRead = input.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
} catch (IOException e) {
log.error(e.getMessage());
} finally {
IOUtils.closeQuietly(input);
IOUtils.closeQuietly(out);
}
}
/**
* 设备信息导入
* @param file
* @return
*/
@Override
public AjaxResult importTbPeople(MultipartFile file) {
String fileName = file.getOriginalFilename();
if (fileName != null) {
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1);
if (!MaterialConstants.XLSX.equalsIgnoreCase(fileExtension)) {
// 文件后缀名不符合要求
return AjaxResult.error("导入失败:文件后缀名不符合要求,必须为xlsx结尾");
}
}
try {
InputStream inputStream = file.getInputStream();
Workbook workbook = new XSSFWorkbook(inputStream);
Sheet sheet = workbook.getSheetAt(0);
// 得到Excel的行数
int totalRows = sheet.getPhysicalNumberOfRows();
// 检查是否有行数
if (totalRows <= 1) {
throw new IllegalArgumentException("导入失败Excel文件中没有数据请检查后重新导入");
}
// 读取第一行表头
Row headerRow = sheet.getRow(0);
if (headerRow == null) {
throw new IllegalArgumentException("导入失败:文件中没有表头");
}
// 获取表头的列数
int totalCells = headerRow.getPhysicalNumberOfCells();
// 预期的表头列数为11列可以根据实际需求修改这个条件
if (totalCells != 11) {
throw new IllegalArgumentException("导入失败:表头列数与预期不符,请检查导入模板");
}
// 获取数据行数
int rowCount = sheet.getLastRowNum() + 1;
if (rowCount > 50) {
throw new IllegalArgumentException("导入失败:数据总条数不能超过 50 条");
}
// 读取表头内容并验证每一列
extractedText(headerRow, totalCells);
//读取Excel表格数据做非空及格式判断
//extractedCell(sheet, totalRows, totalCells);
ExcelUtil<DevTemplateVo> util = new ExcelUtil<>(DevTemplateVo.class);
List<DevTemplateVo> maDevList = util.importExcel(file.getInputStream());
List<DevTemplateVo> templateVos = new ArrayList<>();
List<DevTemplateVo> dtoList = new ArrayList<>();
// 判断装备类目是否为空查询装备id及价格
if (!CollectionUtils.isEmpty(maDevList)) {
for (DevTemplateVo devTemplateVo : maDevList) {
if (StringUtils.isNotBlank(devTemplateVo.getTypeName())) {
// 根据装备类目查询装备id及价格
DevInfoVo devType = devInfoMapper.selectDevTypeByName(devTemplateVo.getTypeName());
if (devType != null) {
devTemplateVo.setTypeId(Long.valueOf(devType.getId()));
devTemplateVo.setTypeName(devType.getTypeName());
devTemplateVo.setDayLeasePrice(devType.getDayLeasePrice());
devTemplateVo.setUnitName(devType.getUnitName());
if ("0".equals(devType.getManageType())) {
devTemplateVo.setDeviceCount(1);
}
}
}
}
// 对maDevList通过装备名称进行分组
Map<String, List<DevTemplateVo>> map = maDevList.stream().collect(Collectors.groupingBy(DevTemplateVo::getDeviceName));
for (Map.Entry<String, List<DevTemplateVo>> entry : map.entrySet()) {
// 如果map的数量大于1则进行遍历
if (entry.getValue().size() > 1) {
DevTemplateVo devTemplateVo = entry.getValue().get(0);
DevTemplateVo dto = new DevTemplateVo();
List<DevTemplateVo> devTemplateVos = entry.getValue();
for (DevTemplateVo templateVo : devTemplateVos) {
dto.setIdentifyCode(StringUtils.isNotBlank(templateVo.getIdentifyCode()) ? templateVo.getIdentifyCode() : null);
dto.setCheckMan(StringUtils.isNotBlank(templateVo.getCheckMan()) ? templateVo.getCheckMan() : null);
dto.setCheckDate(StringUtils.isNotBlank(templateVo.getCheckDate()) ? templateVo.getCheckDate() : null);
dto.setNextCheckDate(StringUtils.isNotBlank(templateVo.getNextCheckDate()) ? templateVo.getNextCheckDate() : null);
dtoList.add(dto);
}
devTemplateVo.setDtoList(dtoList);
templateVos.add(devTemplateVo);
} else {
DevTemplateVo devTemplateVo = entry.getValue().get(0);
templateVos.add(devTemplateVo);
}
}
}
return AjaxResult.success(templateVos);
} catch (IOException e) {
e.printStackTrace();
}
return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
}
/**
* 读取Excel表格数据做非空判断
* @param sheet
* @param totalRows
* @param totalCells
*/
private void extractedCell(Sheet sheet, int totalRows, int totalCells) {
//读取Excel表格数据做非空判断
// 循环Excel行数
DataFormatter dataFormatter = new DataFormatter();
for (int r = 1; r < totalRows; r++) {
Row row = sheet.getRow(r);
// 循环Excel列数
for (int c = 0; c < totalCells; c++) {
String cellValue = dataFormatter.formatCellValue(row.getCell(c));
switch (c) {
case 0:
checkBlank(cellValue, r, c);
break;
case 3:
checkDate(cellValue, r, c);
break;
case 4:
checkBlank(cellValue, r, c);
checkPhone(cellValue, r, c);
break;
default:
throw new IllegalArgumentException(
String.format("第 %d 行,第 %d 列超出范围,请检查后重新导入", r + 1, c + 1));
}
}
}
}
/**
* 检查日期格式
* @param cellValue
* @param rowIndex
* @param colIndex
*/
private void checkDate(String cellValue, int rowIndex, int colIndex) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
try {
// 尝试解析日期字符串
LocalDate.parse(cellValue, formatter);
System.out.println(true);
} catch (DateTimeParseException e) {
// 解析失败说明日期格式不符合要求
if (StringUtils.isBlank(cellValue)) {
throw new IllegalArgumentException(
String.format("第 %d 行,第 %d 列出厂日期不符合格式要求,请检查后重新导入", rowIndex + 1, colIndex + 1));
}
}
}
/**
* 检查数据是否为空
* @param cellValue
* @param rowIndex
* @param colIndex
*/
private void checkBlank(String cellValue, int rowIndex, int colIndex) {
if (StringUtils.isBlank(cellValue)) {
throw new IllegalArgumentException(
String.format("第 %d 行,第 %d 列数据为空,请检查后重新导入", rowIndex + 1, colIndex + 1));
}
}
/**
* 检查电话号码格式
* @param cellValue
* @param rowIndex
* @param colIndex
*/
private void checkPhone(String cellValue, int rowIndex, int colIndex) {
if (!PhoneUtil.isMobile(cellValue)) {
throw new IllegalArgumentException(
String.format("第 %d 行,第 %d 列电话号码格式不正确,请检查后重新导入", rowIndex + 1, colIndex + 1));
}
}
/**
* 读取Excel表格数据做非空及格式判断
* @param headerRow
* @param totalCells
*/
private void extractedText(Row headerRow, int totalCells) {
for (int cellNum = 0; cellNum < totalCells; cellNum++) {
Cell cell = headerRow.getCell(cellNum);
// 获取单元格内容并去除首尾空格
String headerValue = cell.getStringCellValue().trim();
// 根据列索引进行验证
switch (cellNum) {
case 0:
if (!"装备名称".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
case 1:
if (!"装备类目".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
case 2:
if (!"装备品牌".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
case 3:
if (!"出厂日期2025-03-17".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
case 4:
if (!"联系人".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
case 5:
if (!"联系电话".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
case 6:
if (!"上架数量编码类型设备默传1".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
case 7:
if (!"唯一标识符".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
case 8:
if (!"检修人".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
case 9:
if (!"检修时间2025-03-17".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
case 10:
if (!"下次检测时间2025-03-17".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
default:
break;
}
}
}
@Override
public void insertOutType(String devInfo) {
ObjectMapper objectMapper = new ObjectMapper();

View File

@ -1196,4 +1196,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
d.dept_id = #{companyId}
AND d.del_flag = '0'
</select>
<select id="selectDevTypeByName" resultType="com.bonus.material.device.domain.vo.DevInfoVo">
SELECT
type_id as typeId,
type_name as typeName,
manage_type as manageType,
lease_price as dayLeasePrice
FROM
ma_type
WHERE
type_name = #{typeName}
AND `level` = '4'
AND del_flag = '0'
</select>
</mapper>