From cf61a7adc29252bfc5fab381e69b564df1ca4c89 Mon Sep 17 00:00:00 2001 From: mashuai Date: Sat, 6 Sep 2025 15:33:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96=E5=8F=8A?= =?UTF-8?q?=E5=B0=8F=E5=B7=A5=E5=85=B7=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/biz/constant/GlobalConstants.java | 10 ++ .../service/impl/BmQrBoxServiceImpl.java | 6 +- .../controller/WsMaInfoController.java | 27 ++- .../service/WsMaInfoService.java | 18 +- .../service/impl/WsMaInfoServiceImpl.java | 156 ++++++++++++++++++ .../impl/RepairAuditDetailsServiceImpl.java | 14 +- .../mapper/material/basic/BmQrBoxMapper.xml | 2 +- .../template/机具检验标识信息导入模板.xls | Bin 0 -> 20480 bytes 8 files changed, 224 insertions(+), 9 deletions(-) create mode 100644 bonus-modules/bonus-material/src/main/resources/template/机具检验标识信息导入模板.xls diff --git a/bonus-common-biz/src/main/java/com/bonus/common/biz/constant/GlobalConstants.java b/bonus-common-biz/src/main/java/com/bonus/common/biz/constant/GlobalConstants.java index ece95065..b2bade50 100644 --- a/bonus-common-biz/src/main/java/com/bonus/common/biz/constant/GlobalConstants.java +++ b/bonus-common-biz/src/main/java/com/bonus/common/biz/constant/GlobalConstants.java @@ -557,4 +557,14 @@ public class GlobalConstants { */ public static final Long LONG_65535 = 65535L; + /** + * xls + */ + public static final String XLS = "xls"; + + /** + * XLSX + */ + public static final String XLSX = "xlsx"; + } diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/basic/service/impl/BmQrBoxServiceImpl.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/basic/service/impl/BmQrBoxServiceImpl.java index 24f0d460..253a1dbd 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/basic/service/impl/BmQrBoxServiceImpl.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/basic/service/impl/BmQrBoxServiceImpl.java @@ -301,7 +301,11 @@ public class BmQrBoxServiceImpl implements BmQrBoxService { */ @Override public AjaxResult appTransfer(BmQrBoxInfo bmQrBoxInfo) { - + // 根据boxId查询该标准箱里面是否存在设备,空箱不允许移交 + List list = bmQrBoxMapper.getList(bmQrBoxInfo); + if (CollectionUtils.isEmpty(list)) { + return AjaxResult.error("该标准箱中无相关设备,无法进行移交!"); + } bmQrBoxInfo.setBoxCode(null).setBoxName(null).setBoxType(null).setStatus(QrBoxStatusEnum.QR_BOX_STATUS_WAIT_RECEIVE.getStatus().toString()); bmQrBoxInfo.setTransferUser(SecurityUtils.getLoginUser().getUserid()); return 0 < bmQrBoxMapper.updateBmQrcodeInfoById(bmQrBoxInfo) ? AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg()) : diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/codeCollection/controller/WsMaInfoController.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/codeCollection/controller/WsMaInfoController.java index ed070fb2..83be7556 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/codeCollection/controller/WsMaInfoController.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/codeCollection/controller/WsMaInfoController.java @@ -9,13 +9,16 @@ import com.bonus.common.log.enums.OperaType; import com.bonus.common.security.utils.SecurityUtils; import com.bonus.material.codeCollection.domain.WsMaInfo; import com.bonus.material.codeCollection.service.WsMaInfoService; -import com.bonus.material.common.annotation.PreventRepeatSubmit; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.util.List; +import java.util.Objects; /** * 机具信息控制器 @@ -147,4 +150,26 @@ public class WsMaInfoController extends BaseController { public AjaxResult updateGadgetInfo(@RequestBody WsMaInfo info) { return service.updateGadgetInfo(info); } + + /** + * 导入小工具信息模板 + */ + @ApiOperation(value = "小工具导入模版下载") + @PostMapping("/downLoad") + public void downLoadExcelFile(){ + HttpServletResponse resp = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse(); + service.downLoadTemplate(resp); + } + + /** + * 小工具信息导入 + * @param file + * @return + */ + @ApiOperation(value = "小工具信息导入") + @PostMapping("/importData") + public AjaxResult importData(MultipartFile file) + { + return service.importTbData(file); + } } diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/codeCollection/service/WsMaInfoService.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/codeCollection/service/WsMaInfoService.java index 1b6808d3..c559696b 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/codeCollection/service/WsMaInfoService.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/codeCollection/service/WsMaInfoService.java @@ -2,11 +2,10 @@ package com.bonus.material.codeCollection.service; import com.bonus.common.core.web.domain.AjaxResult; import com.bonus.material.codeCollection.domain.WsMaInfo; -import org.apache.ibatis.annotations.MapKey; +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; import java.util.List; -import java.util.Map; -import java.util.Objects; /** * WsMaInfoService @@ -120,4 +119,17 @@ public interface WsMaInfoService { * @return */ AjaxResult updateGadgetInfo(WsMaInfo info); + + /** + * 小工具导入模版下载 + * @param resp + */ + void downLoadTemplate(HttpServletResponse resp); + + /** + * 导入小工具信息 + * @param file + * @return + */ + AjaxResult importTbData(MultipartFile file); } diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/codeCollection/service/impl/WsMaInfoServiceImpl.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/codeCollection/service/impl/WsMaInfoServiceImpl.java index 3eade8d3..995bebfc 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/codeCollection/service/impl/WsMaInfoServiceImpl.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/codeCollection/service/impl/WsMaInfoServiceImpl.java @@ -1,16 +1,30 @@ package com.bonus.material.codeCollection.service.impl; import com.alibaba.nacos.common.utils.CollectionUtils; +import com.bonus.common.biz.constant.GlobalConstants; +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.codeCollection.domain.WsMaInfo; import com.bonus.material.codeCollection.mapper.WsMaInfoMapper; import com.bonus.material.codeCollection.service.WsMaInfoService; +import com.bonus.material.ma.domain.vo.ExceptionEnum; 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.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; +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; @@ -281,4 +295,146 @@ public class WsMaInfoServiceImpl implements WsMaInfoService { return AjaxResult.error("更新失败"); } } + + /** + * 小工具导入模版下载 + * @param response + */ + @Override + public void downLoadTemplate(HttpServletResponse response) { + //模板名称 + String templateName = "机具检验标识信息导入模板.xls"; + OutputStream out = null; + InputStream input =null; + try { + input = this.getClass().getClassLoader().getResourceAsStream("template/机具检验标识信息导入模板.xls"); + 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 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 util = new ExcelUtil<>(WsMaInfo.class); + List wsMaInfos = util.importExcel(file.getInputStream()); + int result = 0; + for (WsMaInfo wmInfo : wsMaInfos) { + List 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; + } + } + } } diff --git a/bonus-modules/bonus-material/src/main/java/com/bonus/material/repair/service/impl/RepairAuditDetailsServiceImpl.java b/bonus-modules/bonus-material/src/main/java/com/bonus/material/repair/service/impl/RepairAuditDetailsServiceImpl.java index 83aef58f..bdc1c95f 100644 --- a/bonus-modules/bonus-material/src/main/java/com/bonus/material/repair/service/impl/RepairAuditDetailsServiceImpl.java +++ b/bonus-modules/bonus-material/src/main/java/com/bonus/material/repair/service/impl/RepairAuditDetailsServiceImpl.java @@ -10,7 +10,6 @@ import com.bonus.common.core.utils.DateUtils; import com.bonus.common.core.utils.StringUtils; import com.bonus.common.security.utils.SecurityUtils; import com.bonus.material.back.mapper.BackApplyInfoMapper; -import com.bonus.material.basic.domain.report.PurChaseReportInfo; import com.bonus.material.repair.domain.*; import com.bonus.material.repair.domain.vo.RepairAuditDetailsVO; import com.bonus.material.repair.domain.vo.RepairHomeInfo; @@ -28,7 +27,6 @@ import com.bonus.material.task.domain.TmTaskAgreement; import com.bonus.material.task.mapper.TmTaskAgreementMapper; import com.bonus.material.task.mapper.TmTaskMapper; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ObjectUtils; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -910,8 +908,13 @@ public class RepairAuditDetailsServiceImpl implements IRepairAuditDetailsService private Long insertScrapTt() { Long newTask = null; int thisMonthMaxOrder = taskMapper.getMonthMaxOrderByDate(DateUtils.getCurrentYear(), DateUtils.getCurrentMonth(), TmTaskTypeEnum.TM_TASK_SCRAP.getTaskTypeId()); - // 生成修饰入库单号 + // 生成报废单号 String code = genderBfTaskCode(thisMonthMaxOrder); + // 根据单号查询该任务是否存在 + TmTask task = taskMapper.selectTaskByCode(code); + if (task != null) { + throw new RuntimeException("该审核任务正在进行中,请勿重复提交!"); + } TmTask tmTask = new TmTask(null, TmTaskTypeEnum.TM_TASK_SCRAP.getTaskTypeId(), ScrapTaskStatusEnum.SCRAP_TASK_NO_FINISHED.getStatus(), null,thisMonthMaxOrder + 1, code); tmTask.setCreateTime(DateUtils.getNowDate()); @@ -963,6 +966,11 @@ public class RepairAuditDetailsServiceImpl implements IRepairAuditDetailsService null,thisMonthMaxOrder + 1, code); tmTask.setCreateTime(DateUtils.getNowDate()); tmTask.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName()); + // 根据code查询此任务单号是否存在 + TmTask task = taskMapper.selectTaskByCode(code); + if (task != null) { + throw new RuntimeException("该审核任务正在进行中,请勿重复提交!"); + } // 插入任务 int taskId = taskMapper.insertTmTask(tmTask); // 如果插入成功且返回的 taskId 大于 0 diff --git a/bonus-modules/bonus-material/src/main/resources/mapper/material/basic/BmQrBoxMapper.xml b/bonus-modules/bonus-material/src/main/resources/mapper/material/basic/BmQrBoxMapper.xml index 8949ea46..81d54d79 100644 --- a/bonus-modules/bonus-material/src/main/resources/mapper/material/basic/BmQrBoxMapper.xml +++ b/bonus-modules/bonus-material/src/main/resources/mapper/material/basic/BmQrBoxMapper.xml @@ -448,6 +448,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - update bm_qrcode_box set box_status = 5 where box_id = #{boxId} + update bm_qrcode_box set box_status = 6 where box_id = #{boxId} diff --git a/bonus-modules/bonus-material/src/main/resources/template/机具检验标识信息导入模板.xls b/bonus-modules/bonus-material/src/main/resources/template/机具检验标识信息导入模板.xls new file mode 100644 index 0000000000000000000000000000000000000000..9c90a4a2e41408f5d95b089f57b41243eba6f446 GIT binary patch literal 20480 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