This commit is contained in:
hayu 2025-09-06 17:55:53 +08:00
parent 9361352ee1
commit 3e07175e67
3 changed files with 371 additions and 86 deletions

View File

@ -1,6 +1,7 @@
package com.bonus.material.codeCollection.mapper;
import com.bonus.material.codeCollection.domain.WsMaInfo;
import com.bonus.material.ma.domain.Type;
import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@ -142,4 +143,18 @@ public interface WsMaInfoMapper {
* @return 条数
*/
int updateGadgetInfo(WsMaInfo info);
/**
* 根据级别查询所有匹配的记录
* @param level
* @param typeName
* @return
*/
// 根据级别查询所有r匹配的记录
List<Type> listByLevelAndName(@Param("level") String level, @Param("typeName") String typeName);
Type selectTypeRelation(@Param("parentLevel") String parentLevel,
@Param("parentName") String parentName,
@Param("childLevel") String childLevel,
@Param("childName") String childName);
}

View File

@ -8,15 +8,16 @@ import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.codeCollection.domain.WsMaInfo;
import com.bonus.material.codeCollection.mapper.WsMaInfoMapper;
import com.bonus.material.codeCollection.service.WsMaInfoService;
import com.bonus.material.ma.domain.Type;
import com.bonus.material.ma.domain.vo.ExceptionEnum;
import com.bonus.material.ma.domain.vo.MaTypeVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.hibernate.validator.internal.util.StringHelper;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@ -25,10 +26,9 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* {@code WsMaInfoServiceImpl}
@ -329,112 +329,362 @@ public class WsMaInfoServiceImpl implements WsMaInfoService {
}
}
/**
* 导入数据
* @param file
* @return
*/
@Override
public AjaxResult importTbData(MultipartFile file) {
String fileName = file.getOriginalFilename();
if (fileName != null) {
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1);
if (!GlobalConstants.XLSX.equalsIgnoreCase(fileExtension) && !GlobalConstants.XLS.equalsIgnoreCase(fileExtension)) {
// 文件后缀名不符合要求
return AjaxResult.error("导入失败:文件后缀名不符合要求,必须为xlsx或xls结尾");
}
}
try {
InputStream inputStream = file.getInputStream();
Workbook workbook = new XSSFWorkbook(inputStream);
Workbook workbook = WorkbookFactory.create(inputStream);
Sheet sheet = workbook.getSheetAt(0);
// 得到Excel的行数
// 得到Excel的行数跳过表头行
int totalRows = sheet.getPhysicalNumberOfRows();
// 检查是否有行数
if (totalRows <= 1) {
throw new IllegalArgumentException("导入失败Excel文件中没有数据请检查后重新导入");
}
// 读取第一行表头
Row headerRow = sheet.getRow(0);
// 读取表头行第一行
Row headerRow = sheet.getRow(1);
if (headerRow == null) {
throw new IllegalArgumentException("导入失败:文件中没有表头");
}
// 获取表头的列数
int totalCells = headerRow.getPhysicalNumberOfCells();
// 预期的表头列数为5列可以根据实际需求修改这个条件
if (totalCells != 5) {
throw new IllegalArgumentException("导入失败:表头列数与预期不符,请检查导入模板");
}
// 读取表头内容并验证每一列
extracted(headerRow, totalCells);
//读取Excel表格数据做非空及格式判断
//extractedCell(sheet, totalRows, totalCells);
ExcelUtil<WsMaInfo> util = new ExcelUtil<>(WsMaInfo.class);
List<WsMaInfo> wsMaInfos = util.importExcel(file.getInputStream());
int result = 0;
for (WsMaInfo wmInfo : wsMaInfos) {
/*List<WsMaInfo> wsMaInfoList = mapper.queryByName(wmInfo);
if (CollectionUtils.isNotEmpty(wsMaInfoList)) {
for (WsMaInfo wmInfo : wsMaInfoList) {
if () {
//进行更新操作
} else {
// 验证表头
validateHeader(headerRow);
List<WsMaInfo> wsMaInfos = new ArrayList<>();
int successCount = 0;
int failCount = 0;
List<String> errorMessages = new ArrayList<>();
// 从第二行开始读取数据索引1
for (int rowNum = 2; rowNum < totalRows; rowNum++) {
Row row = sheet.getRow(rowNum);
if (row == null) {
continue;
}
try {
WsMaInfo wsMaInfo = parseRowToWsMaInfo(row);
if (wsMaInfo != null) {
wsMaInfos.add(wsMaInfo);
// 新增操作
wsMaInfo.setOptUser(SecurityUtils.getLoginUser().getSysUser().getNickName());
mapper.addWsMaInfoData(wsMaInfo);
successCount++;
}
} catch (Exception e) {
failCount++;
errorMessages.add("" + (rowNum + 1) + " 行数据解析失败: " + e.getMessage());
}
}
// 处理结果返回
if (failCount == 0) {
return AjaxResult.success("导入成功,共导入 " + successCount + " 条数据");
} else {
String errorMsg = "导入完成,成功 " + successCount + " 条,失败 " + failCount + " 条。";
if (!errorMessages.isEmpty()) {
errorMsg += "错误信息:" + String.join("; ", errorMessages);
}
return AjaxResult.error(errorMsg);
}
}*/
}
if (result > 0) {
return AjaxResult.success(ExceptionEnum.SUCCESS.getMsg(), result);
}
} catch (IOException e) {
e.printStackTrace();
log.error("导入文件读取失败", e);
return AjaxResult.error("导入失败:文件读取异常");
} catch (IllegalArgumentException e) {
return AjaxResult.error(e.getMessage());
} catch (Exception e) {
log.error("导入过程发生异常", e);
return AjaxResult.error("导入失败:系统异常");
}
return AjaxResult.error(ExceptionEnum.SAVE_TO_DATABASE.getCode(), ExceptionEnum.SAVE_TO_DATABASE.getMsg());
}
/**
* 读取Excel表头模板方法抽取
* @param headerRow
* @param totalCells
* 验证表头格式
*/
private void extracted(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) + " 列表头列名与预期不符,请检查导入模板");
private void validateHeader(Row headerRow) {
String[] expectedHeaders = {
"序号", "机具名称", "规格型号", "机具编号", "本次检验时间",
"下次检验时间", "检修员", "检验员", "联系方式", "结果"
};
int cellCount = headerRow.getPhysicalNumberOfCells();
if (cellCount < expectedHeaders.length) {
throw new IllegalArgumentException("导入失败:表头列数不足,请检查导入模板");
}
break;
case 1:
if (!"性别0 女 1 男)".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
for (int i = 0; i < expectedHeaders.length; i++) {
Cell cell = headerRow.getCell(i);
if (cell == null) {
throw new IllegalArgumentException("导入失败:第 " + (i + 1) + " 列表头为空");
}
break;
case 2:
if (!"岗位工种".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
String headerValue = getCellValueAsString(cell).trim();
if (!expectedHeaders[i].equals(headerValue)) {
throw new IllegalArgumentException("导入失败:第 " + (i + 1) + " 列表头 '" + headerValue +
"' 与预期 '" + expectedHeaders[i] + "' 不符");
}
break;
case 3:
if (!"身份证号码".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
case 4:
if (!"电话".equals(headerValue)) {
throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
}
break;
/**
* 解析单行数据到WsMaInfo对象
*/
private WsMaInfo parseRowToWsMaInfo(Row row) {
WsMaInfo wsMaInfo = new WsMaInfo();
// 机具名称
String maName = getCellValueAsString(row.getCell(1));
if (StringHelper.isNullOrEmptyString(maName)){
throw new IllegalArgumentException("机具名称不能为空");
}
wsMaInfo.setMaName(maName);
// 规格型号
String maModel = getCellValueAsString(row.getCell(2));
if (StringHelper.isNullOrEmptyString(maModel)){
throw new IllegalArgumentException("规格型号不能为空");
}
wsMaInfo.setMaModel(maModel);
// 机具编号
String maCode = getCellValueAsString(row.getCell(3));
if (StringUtils.isEmpty(maCode)) {
throw new IllegalArgumentException("机具编号不能为空");
}
wsMaInfo.setMaCode(maCode);
// 本次检验时间
String thisCheckTime = getCellValueAsString(row.getCell(4));
if (!isValidDate(thisCheckTime)) {
throw new IllegalArgumentException("本次检验时间格式不正确");
}
wsMaInfo.setThisCheckTime(thisCheckTime);
// 下次检验时间
String nextCheckTime = getCellValueAsString(row.getCell(5));
if (!isValidDate(nextCheckTime)) {
throw new IllegalArgumentException("下次检验时间格式不正确");
}
wsMaInfo.setNextCheckTime(nextCheckTime);
// 检修员
wsMaInfo.setRepairMan(getCellValueAsString(row.getCell(6)));
// 检验员
wsMaInfo.setCheckMan(getCellValueAsString(row.getCell(7)));
// 联系方式
wsMaInfo.setPhone(getCellValueAsString(row.getCell(8)));
// 结果
String result = getCellValueAsString(row.getCell(9));
if (!"合格".equals(result) && !"不合格".equals(result)) {
throw new IllegalArgumentException("检验结果必须是'合格'或'不合格'");
}
wsMaInfo.setResult(result);
// 验证设备类型和规格型号的层级关系
validateTypeHierarchy(wsMaInfo, maName, maModel);
//判断该类型下编码是否已存在
WsMaInfo info = mapper.getInfoByTypeAndModelAndCode(wsMaInfo);
if (info != null){
throw new IllegalArgumentException("该类型下编码已存在");
}
return wsMaInfo;
}
/**
* 验证设备类型和规格型号的层级关系
*/
/**
* 通过关联查询验证层级关系更高效
*/
private void validateTypeHierarchy(WsMaInfo wsMaInfo, String typeName, String modelName) {
// 使用关联查询直接验证层级关系
Type relation = mapper.selectTypeRelation("3", typeName, "4", modelName);
if (relation == null) {
throw new IllegalArgumentException("规格型号 '" + modelName + "' 不属于设备类型 '" + typeName + "' 或不存在");
}
wsMaInfo.setModelId(String.valueOf(relation.getTypeId()));
}
/**
* 更新已存在的记录
*/
private void updateExistingRecord(WsMaInfo existing, WsMaInfo newData) {
existing.setThisCheckTime(newData.getThisCheckTime());
existing.setNextCheckTime(newData.getNextCheckTime());
existing.setRepairMan(newData.getRepairMan());
existing.setCheckMan(newData.getCheckMan());
existing.setPhone(newData.getPhone());
existing.setResult(newData.getResult());
existing.setOptTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
existing.setOptUser(SecurityUtils.getUsername());
}
/**
* 获取单元格值的通用方法
*/
private String getCellValueAsString(Cell cell) {
if (cell == null) {
return "";
}
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue().trim();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
return new SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
} else {
return String.valueOf((int) cell.getNumericCellValue());
}
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case FORMULA:
return cell.getCellFormula();
default:
break;
return "";
}
}
/**
* 验证日期格式
*/
private boolean isValidDate(String dateStr) {
if (StringUtils.isEmpty(dateStr)) {
return false;
}
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setLenient(false);
sdf.parse(dateStr);
return true;
} catch (ParseException e) {
return false;
}
}
// /**
// * 导入数据
// * @param file
// * @return
// */
// @Override
// public AjaxResult importTbData(MultipartFile file) {
// String fileName = file.getOriginalFilename();
// if (fileName != null) {
// String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1);
// if (!GlobalConstants.XLSX.equalsIgnoreCase(fileExtension) && !GlobalConstants.XLS.equalsIgnoreCase(fileExtension)) {
// // 文件后缀名不符合要求
// return AjaxResult.error("导入失败:文件后缀名不符合要求,必须为xlsx或xls结尾");
// }
// }
// 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();
// // 预期的表头列数为5列可以根据实际需求修改这个条件
// if (totalCells != 5) {
// throw new IllegalArgumentException("导入失败:表头列数与预期不符,请检查导入模板");
// }
// // 读取表头内容并验证每一列
// extracted(headerRow, totalCells);
// //读取Excel表格数据做非空及格式判断
// //extractedCell(sheet, totalRows, totalCells);
// ExcelUtil<WsMaInfo> util = new ExcelUtil<>(WsMaInfo.class);
// List<WsMaInfo> wsMaInfos = util.importExcel(file.getInputStream());
// int result = 0;
// for (WsMaInfo wmInfo : wsMaInfos) {
// /*List<WsMaInfo> wsMaInfoList = mapper.queryByName(wmInfo);
// if (CollectionUtils.isNotEmpty(wsMaInfoList)) {
// for (WsMaInfo wmInfo : wsMaInfoList) {
// if () {
// //进行更新操作
//
// } else {
// //新增操作
//
// }
// }
// }*/
// }
// if (result > 0) {
// return AjaxResult.success(ExceptionEnum.SUCCESS.getMsg(), result);
// }
// } catch (IOException e) {
// e.printStackTrace();
// }
// return AjaxResult.error(ExceptionEnum.SAVE_TO_DATABASE.getCode(), ExceptionEnum.SAVE_TO_DATABASE.getMsg());
// }
//
// /**
// * 读取Excel表头模板方法抽取
// * @param headerRow
// * @param totalCells
// */
// private void extracted(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 (!"性别0 女 1 男)".equals(headerValue)) {
// throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
// }
// break;
// case 2:
// if (!"岗位工种".equals(headerValue)) {
// throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
// }
// break;
// case 3:
// if (!"身份证号码".equals(headerValue)) {
// throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
// }
// break;
// case 4:
// if (!"电话".equals(headerValue)) {
// throw new IllegalArgumentException("" + (cellNum + 1) + " 列表头列名与预期不符,请检查导入模板");
// }
// break;
// default:
// break;
// }
// }
// }
}

View File

@ -122,7 +122,8 @@
</select>
<select id="getGadgetList" resultType="com.bonus.material.codeCollection.domain.WsMaInfo">
SELECT id,
SELECT
id,
ma_name AS maName,
ma_model AS maModel,
ma_code AS maCode,
@ -132,8 +133,8 @@
check_man AS checkMan,
phone,
result
FROM ws_ma_info wmi
WHERE 1=1
FROM ws_ma_info FORCE INDEX (idx_ws_ma_info_basic)
WHERE ma_name IS NOT NULL
<if test="keyWord != null and keyWord != ''">
and ( ma_name like concat('%', #{keyWord}, '%') or
ma_model like concat('%', #{keyWord}, '%') or
@ -150,6 +151,7 @@
)
]]>
</if>
ORDER BY ma_name, ma_model, this_check_time DESC
</select>
<select id="getGadgetInfo" resultType="com.bonus.material.codeCollection.domain.WsMaInfo">
SELECT wmi.id,
@ -202,6 +204,24 @@
and ma_model = #{maModel}
and ma_code = #{maCode}
</select>
<select id="listByLevelAndName" resultType="com.bonus.material.ma.domain.Type">
SELECT type_id AS typeId, type_name as typeName, level, parent_id as parentId
FROM ma_type
WHERE level = #{level}
AND type_name = #{typeName}
</select>
<select id="selectTypeRelation" resultType="com.bonus.material.ma.domain.Type">
SELECT
mt3.type_id as parentId,
mt4.type_id as typeId
FROM ma_type mt3
INNER JOIN ma_type mt4 ON mt3.type_id = mt4.parent_id
WHERE mt3.level = #{parentLevel}
AND mt3.type_name = #{parentName}
AND mt4.level = #{childLevel}
AND mt4.type_name = #{childName}
LIMIT 1
</select>
<insert id="insert" parameterType="com.bonus.material.codeCollection.domain.WsMaInfo" useGeneratedKeys="true"
keyProperty="id">
INSERT INTO ws_ma_info (ma_name, ma_model, ma_code, supplier, this_check_time, next_check_time,