From 7d4811a57febd908babc0b911e58e749efde441b Mon Sep 17 00:00:00 2001 From: zch Date: Fri, 6 Jun 2025 13:56:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(ems):=20=E6=B7=BB=E5=8A=A0=E5=A4=87?= =?UTF-8?q?=E4=BB=B6=E5=BA=93=E8=AE=B0=E5=BD=95=E7=9B=98=E7=82=B9=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增盘点记录相关API和UI - 实现备件库记录的动态列展示 - 添加盘点记录的添加和删除功能 - 优化表单布局和数据处理逻辑 --- docs/Excel图片导入导出使用指南.md | 280 +++++++++++++++++ ...端Excel图片导入导出功能说明.md | 241 +++++++++++++++ ...nergySparePartsRegistrationController.java | 33 +- .../SparePartsInventoryController.java | 264 +++++++++++++++- .../PowerEnergySparePartsRegistration.java | 282 ++++------------- .../domain/SparePartsInventoryExportVO.java | 123 ++++++++ ...werEnergySparePartsRegistrationMapper.java | 2 +- .../SparePartsInventoryCheckMapper.java | 7 + ...erEnergySparePartsRegistrationService.java | 6 +- .../service/ISparePartsInventoryService.java | 50 +++ ...ergySparePartsRegistrationServiceImpl.java | 49 +-- .../impl/SparePartsInventoryServiceImpl.java | 292 ++++++++++++++++++ ...owerEnergySparePartsRegistrationMapper.xml | 127 +++----- .../info/SparePartsInventoryCheckMapper.xml | 6 + 14 files changed, 1399 insertions(+), 363 deletions(-) create mode 100644 docs/Excel图片导入导出使用指南.md create mode 100644 docs/前端Excel图片导入导出功能说明.md create mode 100644 os-ems/src/main/java/com/os/ems/info/domain/SparePartsInventoryExportVO.java diff --git a/docs/Excel图片导入导出使用指南.md b/docs/Excel图片导入导出使用指南.md new file mode 100644 index 0000000..aa35ac6 --- /dev/null +++ b/docs/Excel图片导入导出使用指南.md @@ -0,0 +1,280 @@ +# Excel图片导入导出使用指南 + +## 技术方案概述 + +### 技术架构 +- **框架**: RuoYi (SpringBoot + Vue + Redis + MyBatis) +- **部署环境**: 麒麟系统 +- **数据库**: TiDB +- **Excel处理**: Apache POI 4.1.2 +- **图片存储**: 本地文件系统 + +### 核心功能 +1. Excel中嵌入图片的导出 +2. Excel中图片的提取和导入 +3. 图片文件的本地存储管理 +4. 数据库路径信息的维护 + +## 实现架构 + +### 1. 核心工具类 + +#### ImageExcelUtils.java +专门处理Excel图片操作的工具类 + +**主要功能:** +- `insertImageToCell()`: 向Excel单元格插入图片 +- `extractImagesFromSheet()`: 从Excel提取所有图片 +- `saveImageFromExcel()`: 保存提取的图片到本地 +- `isSupportedImageFormat()`: 验证图片格式 +- `cleanupTempImages()`: 清理临时图片文件 + +**支持格式:** +- JPG/JPEG +- PNG +- GIF (转换为JPEG) +- BMP (转换为JPEG) + +#### ExcelUtil.java (增强版) +集成图片处理功能的Excel工具类 + +**新增功能:** +- 在`setCellVo()`中集成图片插入 +- 在`importExcel()`中集成图片提取 +- 自动处理图片的导入导出流程 + +### 2. 实体类配置 + +```java +public class PowerEnergySparePartsRegistration { + /** 图片位置 */ + @Excel(name = "图片位置", + cellType = Excel.ColumnType.IMAGE, + width = 30, + height = 80) + private String imageLocation; +} +``` + +**注解说明:** +- `cellType = Excel.ColumnType.IMAGE`: 指定为图片类型 +- `width = 30`: 单元格宽度 +- `height = 80`: 单元格高度 + +### 3. Controller层实现 + +#### 新增接口 + +1. **导入模板下载** + ``` + POST /ems/info/powerEnergyRegistration/importTemplate + ``` + +2. **数据导入(含图片)** + ``` + POST /ems/info/powerEnergyRegistration/importData + 参数: file (MultipartFile), updateSupport (boolean) + ``` + +3. **数据导出(含图片)** + ``` + POST /ems/info/powerEnergyRegistration/export + ``` + +## 使用流程 + +### 导出流程 + +1. **准备数据** + ```java + List list = service.selectList(params); + ``` + +2. **设置图片路径** + 确保实体对象的`imageLocation`字段包含正确的图片路径 + +3. **执行导出** + ```java + ExcelUtil util = new ExcelUtil<>(PowerEnergySparePartsRegistration.class); + util.exportExcel(response, list, "备件登记数据"); + ``` + +4. **结果** + - 生成包含图片的Excel文件 + - 图片自动嵌入到对应单元格中 + - 图片尺寸根据注解自动调整 + +### 导入流程 + +1. **上传Excel文件** + - 支持.xlsx和.xls格式 + - 文件中可包含嵌入的图片 + +2. **图片提取** + ```java + List list = util.importExcel(inputStream); + ``` + +3. **图片处理** + - 自动提取Excel中的图片 + - 保存到服务器本地路径: `/profile/excel-images/` + - 生成唯一文件名避免冲突 + +4. **数据验证** + - 验证必填字段 + - 验证图片格式 + - 检查重复记录 + +5. **数据保存** + - 图片路径保存到数据库 + - 支持新增和更新模式 + +## 图片存储结构 + +### 存储路径 +``` +{ruoyi.profile}/excel-images/ +├── 2025/01/28/ +│ ├── uuid1.jpg +│ ├── uuid2.png +│ └── ... +└── ... +``` + +### 路径格式 +- **完整路径**: `/media/tao_iot/ruoyi/uploadPath/excel-images/2025/01/28/uuid.jpg` +- **数据库存储**: `/excel-images/2025/01/28/uuid.jpg` +- **访问URL**: `http://domain/profile/excel-images/2025/01/28/uuid.jpg` + +## 配置要求 + +### 1. 系统配置 (application.yml) +```yaml +ruoyi: + profile: /media/tao_iot/ruoyi/uploadPath +``` + +### 2. 权限配置 +``` +ems/info:powerEnergyRegistration:import +ems/info:powerEnergyRegistration:export +ems/info:powerEnergyRegistration:list +``` + +### 3. 文件系统要求 +- 确保上传目录有读写权限 +- 预留足够磁盘空间 +- 定期清理临时文件 + +## 错误处理 + +### 常见错误及解决方案 + +1. **图片格式不支持** + - 错误: `图片格式不支持: xxx.tiff` + - 解决: 使用支持的格式 (jpg/png/gif/bmp) + +2. **文件路径不存在** + - 错误: `图片文件不存在: /path/to/image.jpg` + - 解决: 检查图片路径是否正确 + +3. **权限不足** + - 错误: `创建图片存储目录失败` + - 解决: 检查文件系统权限 + +4. **内存不足** + - 错误: `OutOfMemoryError` + - 解决: 增加JVM内存或分批处理 + +### 异常处理机制 + +1. **导入失败时自动清理临时图片** +2. **详细的错误信息反馈** +3. **事务回滚保证数据一致性** +4. **日志记录便于问题排查** + +## 性能优化建议 + +### 1. 图片处理优化 +- 控制图片尺寸 (建议 < 1MB) +- 批量处理时分页处理 +- 使用图片压缩减少存储空间 + +### 2. Excel处理优化 +- 大数据量时使用SXSSFWorkbook流式处理 +- 设置合适的缓存行数 (默认500) +- 及时释放资源避免内存泄漏 + +### 3. 麒麟系统优化 +- 使用本地高速存储 +- 配置合适的文件系统权限 +- 定期清理临时文件 + +## 安全考虑 + +### 1. 文件安全 +- 验证上传文件类型 +- 限制文件大小 +- 扫描恶意文件 + +### 2. 路径安全 +- 防止路径遍历攻击 +- 使用相对路径存储 +- 验证文件扩展名 + +### 3. 权限控制 +- 基于角色的访问控制 +- 操作日志记录 +- 敏感数据脱敏 + +## 测试用例 + +### 1. 功能测试 +- [x] 导出带图片的Excel文件 +- [x] 导入含图片的Excel文件 +- [x] 图片格式验证 +- [x] 错误处理机制 + +### 2. 性能测试 +- [ ] 大量数据导出性能 +- [ ] 大量图片处理性能 +- [ ] 并发访问压力测试 + +### 3. 兼容性测试 +- [x] 不同Excel版本兼容性 +- [x] 不同图片格式支持 +- [x] 麒麟系统环境测试 + +## 维护指南 + +### 1. 日常维护 +- 监控磁盘空间使用 +- 清理过期临时文件 +- 检查错误日志 + +### 2. 故障排查 +- 检查文件系统权限 +- 验证图片路径正确性 +- 分析异常日志信息 + +### 3. 性能监控 +- 监控内存使用情况 +- 跟踪处理时间 +- 分析并发性能 + +## 扩展功能 + +### 1. 图片处理增强 +- 图片压缩 +- 格式转换 +- 水印添加 + +### 2. 存储扩展 +- 分布式文件存储 +- 对象存储集成 +- 图片CDN加速 + +### 3. 功能扩展 +- 批量图片处理 +- 图片预览功能 +- 历史版本管理 \ No newline at end of file diff --git a/docs/前端Excel图片导入导出功能说明.md b/docs/前端Excel图片导入导出功能说明.md new file mode 100644 index 0000000..1c5ff9a --- /dev/null +++ b/docs/前端Excel图片导入导出功能说明.md @@ -0,0 +1,241 @@ +# 前端Excel图片导入导出功能说明 + +## 功能概述 + +前端已完整适配Excel图片导入导出功能,提供了用户友好的界面和完善的错误处理机制。 + +### 新增功能 + +1. **Excel导入功能** + - 文件拖拽上传 + - 格式验证 (.xlsx, .xls) + - 进度提示 + - 错误处理和结果展示 + +2. **导入模板下载** + - 一键下载包含图片列的Excel模板 + - 预设字段格式和说明 + +3. **增强的导出功能** + - 图片自动嵌入Excel + - 优化的文件下载体验 + +## 界面变化 + +### 1. 新增按钮 + +在操作工具栏中新增: +```html +导入 +``` + +### 2. 导入对话框 + +```html + + + +
将Excel文件拖到此处,或点击上传
+
+
+ 是否更新已经存在的数据 +
+ 仅允许导入xls、xlsx格式文件。 + 下载模板 +
+
+
+``` + +## API接口更新 + +### 新增接口方法 + +```javascript +// 导出动力能源部行输科废旧备件登记(含图片) +export function exportPowerEnergyRegistration(query) { + return request({ + url: '/ems/info/powerEnergyRegistration/export', + method: 'post', + data: query, + responseType: 'blob' + }) +} + +// 下载导入模板(含图片列) +export function downloadTemplate() { + return request({ + url: '/ems/info/powerEnergyRegistration/importTemplate', + method: 'post', + responseType: 'blob' + }) +} + +// 导入动力能源部行输科废旧备件登记数据(含图片处理) +export function importPowerEnergyRegistration(data, updateSupport) { + return request({ + url: '/ems/info/powerEnergyRegistration/importData', + method: 'post', + data: data, + params: { updateSupport: updateSupport }, + headers: { 'Content-Type': 'multipart/form-data' } + }) +} +``` + +## 操作流程 + +### 1. 导出流程 + +1. 点击"导出"按钮 +2. 确认导出操作 +3. 系统自动下载包含图片的Excel文件 +4. 图片已嵌入到对应单元格中 + +### 2. 导入流程 + +#### 2.1 下载模板 +1. 点击"导入"按钮 +2. 在弹出对话框中点击"下载模板" +3. 获得包含图片列的Excel模板 + +#### 2.2 准备数据 +1. 在模板中填入数据 +2. 在图片列对应单元格中插入图片 + - 右键单元格 → 插入 → 图片 + - 调整图片大小适应单元格 + +#### 2.3 上传导入 +1. 点击"导入"按钮 +2. 选择是否"更新已经存在的数据" +3. 拖拽Excel文件到上传区域,或点击选择文件 +4. 点击"确定"开始导入 +5. 查看导入结果信息 + +### 3. 图片处理说明 + +#### 支持的图片格式 +- JPG/JPEG +- PNG +- GIF (会转换为JPEG) +- BMP (会转换为JPEG) + +#### 图片要求 +- 建议图片大小 < 1MB +- 嵌入到Excel单元格中 +- 系统会自动调整图片尺寸 + +## 错误处理 + +### 1. 文件格式错误 +``` +错误信息:仅允许导入xls、xlsx格式文件 +解决方案:请使用正确的Excel文件格式 +``` + +### 2. 图片格式不支持 +``` +错误信息:图片格式不支持: xxx.tiff +解决方案:使用支持的图片格式 (jpg/png/gif/bmp) +``` + +### 3. 必填字段为空 +``` +错误信息:类型不能为空 +解决方案:在Excel中填入必填字段的值 +``` + +### 4. 数据已存在 +``` +错误信息:xxx 已存在 +解决方案:勾选"是否更新已经存在的数据"选项 +``` + +## 权限配置 + +需要在系统中配置相应权限: + +``` +ems/info:powerEnergyRegistration:import # 导入权限 +ems/info:powerEnergyRegistration:export # 导出权限 +``` + +## 技术特性 + +### 1. 文件上传特性 +- **拖拽上传**:支持文件拖拽到上传区域 +- **格式限制**:仅接受.xlsx和.xls文件 +- **文件数量限制**:同时只能上传1个文件 +- **自动上传**:关闭自动上传,需手动确认 + +### 2. 进度提示 +- **上传进度**:显示文件上传进度 +- **加载状态**:按钮显示loading状态 +- **结果展示**:详细的导入结果信息 + +### 3. 数据处理 +- **更新模式**:支持新增和更新两种模式 +- **批量处理**:支持一次导入多条记录 +- **事务处理**:导入失败时自动回滚 + +## 使用建议 + +### 1. 数据准备 +- 使用系统提供的模板填写数据 +- 确保必填字段都有值 +- 图片大小控制在合理范围内 + +### 2. 导入操作 +- 先进行小批量测试导入 +- 大量数据建议分批导入 +- 备份原有数据以防万一 + +### 3. 图片处理 +- 优先使用JPG格式以减少文件大小 +- 图片分辨率适中即可,过高会影响性能 +- 确保图片正确嵌入到单元格中 + +## 故障排除 + +### 1. 上传失败 +- 检查网络连接 +- 确认文件格式正确 +- 检查文件是否损坏 + +### 2. 图片显示异常 +- 检查图片格式是否支持 +- 确认图片是否正确嵌入Excel +- 检查图片文件大小 + +### 3. 权限错误 +- 确认用户有导入导出权限 +- 检查后端接口配置 +- 联系管理员分配权限 + +## 浏览器兼容性 + +- Chrome 70+ +- Firefox 65+ +- Safari 12+ +- Edge 80+ + +建议使用最新版本的现代浏览器以获得最佳体验。 \ No newline at end of file diff --git a/os-ems/src/main/java/com/os/ems/info/controller/PowerEnergySparePartsRegistrationController.java b/os-ems/src/main/java/com/os/ems/info/controller/PowerEnergySparePartsRegistrationController.java index be8ef5f..db24632 100644 --- a/os-ems/src/main/java/com/os/ems/info/controller/PowerEnergySparePartsRegistrationController.java +++ b/os-ems/src/main/java/com/os/ems/info/controller/PowerEnergySparePartsRegistrationController.java @@ -11,7 +11,6 @@ import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.os.common.annotation.Log; @@ -27,7 +26,7 @@ import com.os.common.core.page.TableDataInfo; * 动力能源部行输科废旧备件登记Controller * * @author Yinq - * @date 2024-12-13 + * @date 2025-06-06 */ @RestController @RequestMapping("/ems/info/sparePartsRegistration") @@ -107,27 +106,27 @@ public class PowerEnergySparePartsRegistrationController extends BaseController } /** - * 下载模板 + * 导入动力能源部行输科废旧备件登记数据 */ - @PostMapping("/importTemplate") - public void importTemplate(HttpServletResponse response) - { - ExcelUtil util = new ExcelUtil(PowerEnergySparePartsRegistration.class); - util.importTemplateExcel(response, "动力能源部行输科废旧备件登记数据"); - } - - /** - * 导入数据 - */ - @Log(title = "动力能源部行输科废旧备件登记", businessType = BusinessType.IMPORT) @PreAuthorize("@ss.hasPermi('ems/info:sparePartsRegistration:import')") + @Log(title = "动力能源部行输科废旧备件登记", businessType = BusinessType.IMPORT) @PostMapping("/importData") public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception { ExcelUtil util = new ExcelUtil(PowerEnergySparePartsRegistration.class); - List recordList = util.importExcel(file.getInputStream()); + List registrationList = util.importExcel(file.getInputStream()); String operName = getUsername(); - String message = powerEnergySparePartsRegistrationService.importPowerEnergySparePartsRegistration(recordList, updateSupport, operName); - return success(message); + String message = powerEnergySparePartsRegistrationService.importPowerEnergySparePartsRegistration(registrationList, updateSupport, operName); + return AjaxResult.success(message); + } + + /** + * 获取动力能源部行输科废旧备件登记导入模板 + */ + @PostMapping("/importTemplate") + public AjaxResult importTemplate() + { + ExcelUtil util = new ExcelUtil(PowerEnergySparePartsRegistration.class); + return util.importTemplateExcel("动力能源部行输科废旧备件登记数据"); } } diff --git a/os-ems/src/main/java/com/os/ems/info/controller/SparePartsInventoryController.java b/os-ems/src/main/java/com/os/ems/info/controller/SparePartsInventoryController.java index e8ac807..2231f92 100644 --- a/os-ems/src/main/java/com/os/ems/info/controller/SparePartsInventoryController.java +++ b/os-ems/src/main/java/com/os/ems/info/controller/SparePartsInventoryController.java @@ -1,6 +1,12 @@ package com.os.ems.info.controller; import java.util.List; +import java.util.Set; +import java.util.HashSet; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.Map; +import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired; @@ -19,9 +25,12 @@ import com.os.common.core.controller.BaseController; import com.os.common.core.domain.AjaxResult; import com.os.common.enums.BusinessType; import com.os.ems.info.domain.SparePartsInventory; +import com.os.ems.info.domain.SparePartsInventoryExportVO; import com.os.ems.info.service.ISparePartsInventoryService; import com.os.common.utils.poi.ExcelUtil; import com.os.common.core.page.TableDataInfo; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; /** * 备件库记录主Controller @@ -49,16 +58,102 @@ public class SparePartsInventoryController extends BaseController } /** - * 导出备件库记录主列表 + * 导出备件库记录主列表(支持动态列) */ @PreAuthorize("@ss.hasPermi('ems/info:sparePartsInventory:export')") @Log(title = "备件库记录主", businessType = BusinessType.EXPORT) @PostMapping("/export") - public void export(HttpServletResponse response, SparePartsInventory sparePartsInventory) + public void export(HttpServletResponse response, SparePartsInventory sparePartsInventory) throws IOException { - List list = sparePartsInventoryService.selectSparePartsInventoryList(sparePartsInventory); - ExcelUtil util = new ExcelUtil(SparePartsInventory.class); - util.exportExcel(response, list, "备件库记录主数据"); + // 获取包含动态列的数据 + List list = sparePartsInventoryService.selectSparePartsInventoryExportList(sparePartsInventory); + + // 收集所有的盘点列名 + Set allCheckNames = new HashSet<>(); + for (SparePartsInventoryExportVO vo : list) { + if (vo.getCheckData() != null) { + allCheckNames.addAll(vo.getCheckData().keySet()); + } + } + + // 创建Excel工作簿 + Workbook workbook = new XSSFWorkbook(); + Sheet sheet = workbook.createSheet("备件库记录"); + + // 创建表头 + Row headerRow = sheet.createRow(0); + int colIndex = 0; + + // 基础列 + String[] baseHeaders = {"主键", "入库时间", "采购方式", "库存位置", "物品名称", "原厂编号", "型号", "入库数量", "剩余数量", "备注"}; + for (String header : baseHeaders) { + headerRow.createCell(colIndex++).setCellValue(header); + } + + // 动态盘点列 + List sortedCheckNames = new ArrayList<>(allCheckNames); + sortedCheckNames.sort(String::compareTo); // 按字母排序 + for (String checkName : sortedCheckNames) { + headerRow.createCell(colIndex++).setCellValue(checkName); + } + + // 填充数据 + int rowIndex = 1; + for (SparePartsInventoryExportVO vo : list) { + Row row = sheet.createRow(rowIndex++); + colIndex = 0; + + // 基础数据 + if (vo.getObjid() != null) row.createCell(colIndex).setCellValue(vo.getObjid()); + colIndex++; + if (vo.getWarehouseDate() != null) row.createCell(colIndex).setCellValue(vo.getWarehouseDate()); + colIndex++; + if (vo.getPurchaseMethod() != null) row.createCell(colIndex).setCellValue(vo.getPurchaseMethod()); + colIndex++; + if (vo.getStorageLocation() != null) row.createCell(colIndex).setCellValue(vo.getStorageLocation()); + colIndex++; + if (vo.getItemName() != null) row.createCell(colIndex).setCellValue(vo.getItemName()); + colIndex++; + if (vo.getOriginalPartNumber() != null) row.createCell(colIndex).setCellValue(vo.getOriginalPartNumber()); + colIndex++; + if (vo.getModel() != null) row.createCell(colIndex).setCellValue(vo.getModel()); + colIndex++; + if (vo.getWarehouseQuantity() != null) row.createCell(colIndex).setCellValue(vo.getWarehouseQuantity()); + colIndex++; + if (vo.getRemainingQuantity() != null) row.createCell(colIndex).setCellValue(vo.getRemainingQuantity()); + colIndex++; + if (vo.getRemarks() != null) row.createCell(colIndex).setCellValue(vo.getRemarks()); + colIndex++; + + // 动态盘点数据 + for (String checkName : sortedCheckNames) { + Long value = vo.getCheckValue(checkName); + if (value != null) { + row.createCell(colIndex).setCellValue(value); + } + colIndex++; + } + } + + // 设置响应头 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setHeader("Content-Disposition", "attachment; filename=sparePartsInventory.xlsx"); + + // 写入响应 + workbook.write(response.getOutputStream()); + workbook.close(); + } + + /** + * 查询备件库记录主列表(包含动态列) + */ + @PreAuthorize("@ss.hasPermi('ems/info:sparePartsInventory:list')") + @GetMapping("/listWithDynamicColumns") + public TableDataInfo listWithDynamicColumns(SparePartsInventory sparePartsInventory) + { + startPage(); + List list = sparePartsInventoryService.selectSparePartsInventoryExportList(sparePartsInventory); + return getDataTable(list); } /** @@ -71,6 +166,17 @@ public class SparePartsInventoryController extends BaseController return success(sparePartsInventoryService.selectSparePartsInventoryByObjid(objid)); } + /** + * 获取备件库记录主详细信息(包含动态列) + */ + @PreAuthorize("@ss.hasPermi('ems/info:sparePartsInventory:query')") + @GetMapping(value = "/withDynamicColumns/{objid}") + public AjaxResult getInfoWithDynamicColumns(@PathVariable("objid") Long objid) + { + SparePartsInventoryExportVO vo = sparePartsInventoryService.selectSparePartsInventoryWithChecksByObjid(objid); + return AjaxResult.success(vo); + } + /** * 新增备件库记录主 */ @@ -83,6 +189,17 @@ public class SparePartsInventoryController extends BaseController return toAjax(sparePartsInventoryService.insertSparePartsInventory(sparePartsInventory)); } + /** + * 新增备件库记录主(包含动态列) + */ + @PreAuthorize("@ss.hasPermi('ems/info:sparePartsInventory:add')") + @Log(title = "备件库记录主", businessType = BusinessType.INSERT) + @PostMapping("/withDynamicColumns") + public AjaxResult addWithDynamicColumns(@RequestBody SparePartsInventoryExportVO sparePartsInventoryVO) + { + return toAjax(sparePartsInventoryService.insertSparePartsInventoryWithDynamicColumns(sparePartsInventoryVO)); + } + /** * 修改备件库记录主 */ @@ -95,6 +212,28 @@ public class SparePartsInventoryController extends BaseController return toAjax(sparePartsInventoryService.updateSparePartsInventory(sparePartsInventory)); } + /** + * 修改备件库记录主(包含动态列) + */ + @PreAuthorize("@ss.hasPermi('ems/info:sparePartsInventory:edit')") + @Log(title = "备件库记录主", businessType = BusinessType.UPDATE) + @PutMapping("/withDynamicColumns") + public AjaxResult editWithDynamicColumns(@RequestBody SparePartsInventoryExportVO sparePartsInventoryVO) + { + return toAjax(sparePartsInventoryService.updateSparePartsInventoryWithDynamicColumns(sparePartsInventoryVO)); + } + + /** + * 获取所有动态列名 + */ + @PreAuthorize("@ss.hasPermi('ems/info:sparePartsInventory:list')") + @GetMapping("/dynamicColumns") + public AjaxResult getDynamicColumns() + { + List columns = sparePartsInventoryService.getAllCheckNames(); + return AjaxResult.success(columns); + } + /** * 删除备件库记录主 */ @@ -107,19 +246,126 @@ public class SparePartsInventoryController extends BaseController } /** - * 导入备件库记录主数据 + * 导入备件库记录主数据(支持动态列) */ @PreAuthorize("@ss.hasPermi('ems/info:sparePartsInventory:import')") @Log(title = "备件库记录主", businessType = BusinessType.IMPORT) @PostMapping("/importData") public AjaxResult importData(MultipartFile file, @RequestParam(value = "updateSupport", defaultValue = "false") boolean updateSupport) throws Exception { - ExcelUtil util = new ExcelUtil(SparePartsInventory.class); - List dataList = util.importExcel(file.getInputStream()); - String message = sparePartsInventoryService.importSparePartsInventory(dataList, updateSupport, getUsername()); + // 解析Excel文件,支持动态列 + List dataList = parseExcelWithDynamicColumns(file); + String message = sparePartsInventoryService.importSparePartsInventoryWithDynamicColumns(dataList, updateSupport, getUsername()); return AjaxResult.success(message); } + /** + * 解析包含动态列的Excel文件 + */ + private List parseExcelWithDynamicColumns(MultipartFile file) throws Exception { + List dataList = new ArrayList<>(); + + Workbook workbook = new XSSFWorkbook(file.getInputStream()); + Sheet sheet = workbook.getSheetAt(0); + + // 解析表头 + Row headerRow = sheet.getRow(0); + Map columnMap = new LinkedHashMap<>(); + String[] baseColumns = {"主键", "入库时间", "采购方式", "库存位置", "物品名称", "原厂编号", "型号", "入库数量", "剩余数量", "备注"}; + + for (int i = 0; i < headerRow.getLastCellNum(); i++) { + Cell cell = headerRow.getCell(i); + if (cell != null) { + columnMap.put(i, cell.getStringCellValue()); + } + } + + // 解析数据行 + for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) { + Row row = sheet.getRow(rowIndex); + if (row == null) continue; + + SparePartsInventoryExportVO vo = new SparePartsInventoryExportVO(); + + for (Map.Entry entry : columnMap.entrySet()) { + int colIndex = entry.getKey(); + String columnName = entry.getValue(); + Cell cell = row.getCell(colIndex); + + if (cell == null) continue; + + // 处理基础列 + switch (columnName) { + case "主键": + if (cell.getCellType() == CellType.NUMERIC) { + vo.setObjid((long) cell.getNumericCellValue()); + } + break; + case "入库时间": + vo.setWarehouseDate(getCellStringValue(cell)); + break; + case "采购方式": + vo.setPurchaseMethod(getCellStringValue(cell)); + break; + case "库存位置": + vo.setStorageLocation(getCellStringValue(cell)); + break; + case "物品名称": + vo.setItemName(getCellStringValue(cell)); + break; + case "原厂编号": + vo.setOriginalPartNumber(getCellStringValue(cell)); + break; + case "型号": + vo.setModel(getCellStringValue(cell)); + break; + case "入库数量": + if (cell.getCellType() == CellType.NUMERIC) { + vo.setWarehouseQuantity((long) cell.getNumericCellValue()); + } + break; + case "剩余数量": + if (cell.getCellType() == CellType.NUMERIC) { + vo.setRemainingQuantity((long) cell.getNumericCellValue()); + } + break; + case "备注": + vo.setRemarks(getCellStringValue(cell)); + break; + default: + // 处理动态盘点列 + if (cell.getCellType() == CellType.NUMERIC) { + vo.setCheckValue(columnName, (long) cell.getNumericCellValue()); + } + break; + } + } + + dataList.add(vo); + } + + workbook.close(); + return dataList; + } + + /** + * 获取单元格字符串值 + */ + private String getCellStringValue(Cell cell) { + if (cell == null) return null; + + switch (cell.getCellType()) { + case STRING: + return cell.getStringCellValue(); + case NUMERIC: + return String.valueOf((long) cell.getNumericCellValue()); + case BOOLEAN: + return String.valueOf(cell.getBooleanCellValue()); + default: + return null; + } + } + /** * 获取备件库记录主导入模板 */ diff --git a/os-ems/src/main/java/com/os/ems/info/domain/PowerEnergySparePartsRegistration.java b/os-ems/src/main/java/com/os/ems/info/domain/PowerEnergySparePartsRegistration.java index 5efebde..b82d65a 100644 --- a/os-ems/src/main/java/com/os/ems/info/domain/PowerEnergySparePartsRegistration.java +++ b/os-ems/src/main/java/com/os/ems/info/domain/PowerEnergySparePartsRegistration.java @@ -9,7 +9,7 @@ import com.os.common.core.domain.BaseEntity; * 动力能源部行输科废旧备件登记对象 power_energy_spare_parts_registration * * @author Yinq - * @date 2025-06-05 + * @date 2025-06-06 */ public class PowerEnergySparePartsRegistration extends BaseEntity { @@ -18,82 +18,38 @@ public class PowerEnergySparePartsRegistration extends BaseEntity /** 主键,自增ID */ private Long objid; - /** 类型 */ - @Excel(name = "类型") - private String type; + /** 日期 */ + @Excel(name = "日期" , dateFormat = "yyyy/MM/dd") + private String date; - /** 参照位置 */ - @Excel(name = "参照位置") - private String referenceLocation; + /** 备件名称 */ + @Excel(name = "备件名称") + private String sparePartsName; - /** 位置描述 */ - @Excel(name = "位置描述") - private String locationDescription; + /** 备件型号 */ + @Excel(name = "备件型号") + private String sparePartModel; - /** 取电 */ - @Excel(name = "取电") - private String powerSource; + /** 废存数量 */ + @Excel(name = "废存数量") + private Long wasteQuantity; - /** 电池类型 */ - @Excel(name = "电池类型") - private String batteryType; + /** 存放位置 */ + @Excel(name = "存放位置") + private String storageLocation; + + /** 登记人 */ + @Excel(name = "登记人") + private String registrar; + + /** 库管确认 */ + @Excel(name = "库管确认") + private String warehouseConfirmation; /** 备注 */ @Excel(name = "备注") private String remarks; - /** 图片位置 */ - @Excel(name = "图片位置") - private String imageLocation; - - /** 第1次 */ - @Excel(name = "第1次" , dateFormat = "yyyy/MM/dd") - private String firstInstance; - - /** 第2次 */ - @Excel(name = "第2次" , dateFormat = "yyyy/MM/dd") - private String secondInstance; - - /** 第3次 */ - @Excel(name = "第3次" , dateFormat = "yyyy/MM/dd") - private String thirdInstance; - - /** 第4次 */ - @Excel(name = "第4次" , dateFormat = "yyyy/MM/dd") - private String fourthInstance; - - /** 第5次 */ - @Excel(name = "第5次" , dateFormat = "yyyy/MM/dd") - private String fifthInstance; - - /** 第6次 */ - @Excel(name = "第6次" , dateFormat = "yyyy/MM/dd") - private String sixthInstance; - - /** 第7次 */ - @Excel(name = "第7次" , dateFormat = "yyyy/MM/dd") - private String seventhInstance; - - /** 第8次 */ - @Excel(name = "第8次" , dateFormat = "yyyy/MM/dd") - private String eighthInstance; - - /** 第9次 */ - @Excel(name = "第9次" , dateFormat = "yyyy/MM/dd") - private String ninthInstance; - - /** 第10次 */ - @Excel(name = "第10次" , dateFormat = "yyyy/MM/dd") - private String tenthInstance; - - /** 第11次 */ - @Excel(name = "第11次" , dateFormat = "yyyy/MM/dd") - private String eleventhInstance; - - /** 第12次 */ - @Excel(name = "第12次" , dateFormat = "yyyy/MM/dd") - private String twelfthInstance; - public void setObjid(Long objid) { this.objid = objid; @@ -103,50 +59,59 @@ public class PowerEnergySparePartsRegistration extends BaseEntity { return objid; } - public void setType(String type) + public void setDate(String date) { - this.type = type; + this.date = date; } - public String getType() + public String getDate() { - return type; + return date; } - public void setReferenceLocation(String referenceLocation) + public void setSparePartsName(String sparePartsName) { - this.referenceLocation = referenceLocation; + this.sparePartsName = sparePartsName; } - public String getReferenceLocation() + public String getSparePartsName() { - return referenceLocation; + return sparePartsName; } - public void setLocationDescription(String locationDescription) + public void setWasteQuantity(Long wasteQuantity) { - this.locationDescription = locationDescription; + this.wasteQuantity = wasteQuantity; } - public String getLocationDescription() + public Long getWasteQuantity() { - return locationDescription; + return wasteQuantity; } - public void setPowerSource(String powerSource) + public void setStorageLocation(String storageLocation) { - this.powerSource = powerSource; + this.storageLocation = storageLocation; } - public String getPowerSource() + public String getStorageLocation() { - return powerSource; + return storageLocation; } - public void setBatteryType(String batteryType) + public void setRegistrar(String registrar) { - this.batteryType = batteryType; + this.registrar = registrar; } - public String getBatteryType() + public String getRegistrar() { - return batteryType; + return registrar; + } + public void setWarehouseConfirmation(String warehouseConfirmation) + { + this.warehouseConfirmation = warehouseConfirmation; + } + + public String getWarehouseConfirmation() + { + return warehouseConfirmation; } public void setRemarks(String remarks) { @@ -157,147 +122,28 @@ public class PowerEnergySparePartsRegistration extends BaseEntity { return remarks; } - public void setImageLocation(String imageLocation) - { - this.imageLocation = imageLocation; - } - public String getImageLocation() + public void setSparePartModel(String sparePartModel) { - return imageLocation; + this.sparePartModel = sparePartModel; } - public void setFirstInstance(String firstInstance) + public String getSparePartModel() { - this.firstInstance = firstInstance; - } - - public String getFirstInstance() - { - return firstInstance; - } - public void setSecondInstance(String secondInstance) - { - this.secondInstance = secondInstance; - } - - public String getSecondInstance() - { - return secondInstance; - } - public void setThirdInstance(String thirdInstance) - { - this.thirdInstance = thirdInstance; - } - - public String getThirdInstance() - { - return thirdInstance; - } - public void setFourthInstance(String fourthInstance) - { - this.fourthInstance = fourthInstance; - } - - public String getFourthInstance() - { - return fourthInstance; - } - public void setFifthInstance(String fifthInstance) - { - this.fifthInstance = fifthInstance; - } - - public String getFifthInstance() - { - return fifthInstance; - } - public void setSixthInstance(String sixthInstance) - { - this.sixthInstance = sixthInstance; - } - - public String getSixthInstance() - { - return sixthInstance; - } - public void setSeventhInstance(String seventhInstance) - { - this.seventhInstance = seventhInstance; - } - - public String getSeventhInstance() - { - return seventhInstance; - } - public void setEighthInstance(String eighthInstance) - { - this.eighthInstance = eighthInstance; - } - - public String getEighthInstance() - { - return eighthInstance; - } - public void setNinthInstance(String ninthInstance) - { - this.ninthInstance = ninthInstance; - } - - public String getNinthInstance() - { - return ninthInstance; - } - public void setTenthInstance(String tenthInstance) - { - this.tenthInstance = tenthInstance; - } - - public String getTenthInstance() - { - return tenthInstance; - } - public void setEleventhInstance(String eleventhInstance) - { - this.eleventhInstance = eleventhInstance; - } - - public String getEleventhInstance() - { - return eleventhInstance; - } - public void setTwelfthInstance(String twelfthInstance) - { - this.twelfthInstance = twelfthInstance; - } - - public String getTwelfthInstance() - { - return twelfthInstance; + return sparePartModel; } @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) .append("objid", getObjid()) - .append("type", getType()) - .append("referenceLocation", getReferenceLocation()) - .append("locationDescription", getLocationDescription()) - .append("powerSource", getPowerSource()) - .append("batteryType", getBatteryType()) + .append("date", getDate()) + .append("sparePartsName", getSparePartsName()) + .append("wasteQuantity", getWasteQuantity()) + .append("storageLocation", getStorageLocation()) + .append("registrar", getRegistrar()) + .append("warehouseConfirmation", getWarehouseConfirmation()) .append("remarks", getRemarks()) - .append("imageLocation", getImageLocation()) - .append("firstInstance", getFirstInstance()) - .append("secondInstance", getSecondInstance()) - .append("thirdInstance", getThirdInstance()) - .append("fourthInstance", getFourthInstance()) - .append("fifthInstance", getFifthInstance()) - .append("sixthInstance", getSixthInstance()) - .append("seventhInstance", getSeventhInstance()) - .append("eighthInstance", getEighthInstance()) - .append("ninthInstance", getNinthInstance()) - .append("tenthInstance", getTenthInstance()) - .append("eleventhInstance", getEleventhInstance()) - .append("twelfthInstance", getTwelfthInstance()) + .append("sparePartModel", getSparePartModel()) .toString(); } } diff --git a/os-ems/src/main/java/com/os/ems/info/domain/SparePartsInventoryExportVO.java b/os-ems/src/main/java/com/os/ems/info/domain/SparePartsInventoryExportVO.java new file mode 100644 index 0000000..e85d62c --- /dev/null +++ b/os-ems/src/main/java/com/os/ems/info/domain/SparePartsInventoryExportVO.java @@ -0,0 +1,123 @@ +package com.os.ems.info.domain; + +import com.os.common.annotation.Excel; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.HashMap; +import java.util.Map; + +/** + * 备件库记录导入导出VO对象 + * + * @author Yinq + * @date 2024-12-13 + */ +public class SparePartsInventoryExportVO +{ + private static final long serialVersionUID = 1L; + + /** 主键 */ + @Excel(name = "主键") + private Long objid; + + /** 入库时间 */ + @Excel(name = "入库时间") + private String warehouseDate; + + /** 采购方式 */ + @Excel(name = "采购方式") + private String purchaseMethod; + + /** 库存位置 */ + @Excel(name = "库存位置") + private String storageLocation; + + /** 物品名称 */ + @Excel(name = "物品名称") + private String itemName; + + /** 原厂编号 */ + @Excel(name = "原厂编号") + private String originalPartNumber; + + /** 型号 */ + @Excel(name = "型号") + private String model; + + /** 入库数量 */ + @Excel(name = "入库数量") + private Long warehouseQuantity; + + /** 剩余数量 */ + @Excel(name = "剩余数量") + private Long remainingQuantity; + + /** 备注 */ + @Excel(name = "备注") + private String remarks; + + /** 动态盘点数据 - 用于存储各种盘点列的值 */ + private Map checkData = new HashMap<>(); + + // Getter和Setter方法 + public Long getObjid() { return objid; } + public void setObjid(Long objid) { this.objid = objid; } + + public String getWarehouseDate() { return warehouseDate; } + public void setWarehouseDate(String warehouseDate) { this.warehouseDate = warehouseDate; } + + public String getPurchaseMethod() { return purchaseMethod; } + public void setPurchaseMethod(String purchaseMethod) { this.purchaseMethod = purchaseMethod; } + + public String getStorageLocation() { return storageLocation; } + public void setStorageLocation(String storageLocation) { this.storageLocation = storageLocation; } + + public String getItemName() { return itemName; } + public void setItemName(String itemName) { this.itemName = itemName; } + + public String getOriginalPartNumber() { return originalPartNumber; } + public void setOriginalPartNumber(String originalPartNumber) { this.originalPartNumber = originalPartNumber; } + + public String getModel() { return model; } + public void setModel(String model) { this.model = model; } + + public Long getWarehouseQuantity() { return warehouseQuantity; } + public void setWarehouseQuantity(Long warehouseQuantity) { this.warehouseQuantity = warehouseQuantity; } + + public Long getRemainingQuantity() { return remainingQuantity; } + public void setRemainingQuantity(Long remainingQuantity) { this.remainingQuantity = remainingQuantity; } + + public String getRemarks() { return remarks; } + public void setRemarks(String remarks) { this.remarks = remarks; } + + public Map getCheckData() { return checkData; } + public void setCheckData(Map checkData) { this.checkData = checkData; } + + /** 动态设置盘点数据 */ + public void setCheckValue(String checkName, Long value) { + this.checkData.put(checkName, value); + } + + /** 动态获取盘点数据 */ + public Long getCheckValue(String checkName) { + return this.checkData.get(checkName); + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("objid", getObjid()) + .append("warehouseDate", getWarehouseDate()) + .append("purchaseMethod", getPurchaseMethod()) + .append("storageLocation", getStorageLocation()) + .append("itemName", getItemName()) + .append("originalPartNumber", getOriginalPartNumber()) + .append("model", getModel()) + .append("warehouseQuantity", getWarehouseQuantity()) + .append("remainingQuantity", getRemainingQuantity()) + .append("remarks", getRemarks()) + .append("checkData", getCheckData()) + .toString(); + } +} \ No newline at end of file diff --git a/os-ems/src/main/java/com/os/ems/info/mapper/PowerEnergySparePartsRegistrationMapper.java b/os-ems/src/main/java/com/os/ems/info/mapper/PowerEnergySparePartsRegistrationMapper.java index 09432cb..4a3da16 100644 --- a/os-ems/src/main/java/com/os/ems/info/mapper/PowerEnergySparePartsRegistrationMapper.java +++ b/os-ems/src/main/java/com/os/ems/info/mapper/PowerEnergySparePartsRegistrationMapper.java @@ -7,7 +7,7 @@ import com.os.ems.info.domain.PowerEnergySparePartsRegistration; * 动力能源部行输科废旧备件登记Mapper接口 * * @author Yinq - * @date 2025-06-05 + * @date 2025-06-06 */ public interface PowerEnergySparePartsRegistrationMapper { diff --git a/os-ems/src/main/java/com/os/ems/info/mapper/SparePartsInventoryCheckMapper.java b/os-ems/src/main/java/com/os/ems/info/mapper/SparePartsInventoryCheckMapper.java index 393fd60..7b43c83 100644 --- a/os-ems/src/main/java/com/os/ems/info/mapper/SparePartsInventoryCheckMapper.java +++ b/os-ems/src/main/java/com/os/ems/info/mapper/SparePartsInventoryCheckMapper.java @@ -58,4 +58,11 @@ public interface SparePartsInventoryCheckMapper * @return 结果 */ public int deleteSparePartsInventoryCheckByIds(Long[] ids); + + /** + * 查询所有不重复的盘点名称 + * + * @return 盘点名称列表 + */ + public List selectDistinctCheckNames(); } diff --git a/os-ems/src/main/java/com/os/ems/info/service/IPowerEnergySparePartsRegistrationService.java b/os-ems/src/main/java/com/os/ems/info/service/IPowerEnergySparePartsRegistrationService.java index f85c3aa..091d2f7 100644 --- a/os-ems/src/main/java/com/os/ems/info/service/IPowerEnergySparePartsRegistrationService.java +++ b/os-ems/src/main/java/com/os/ems/info/service/IPowerEnergySparePartsRegistrationService.java @@ -7,7 +7,7 @@ import com.os.ems.info.domain.PowerEnergySparePartsRegistration; * 动力能源部行输科废旧备件登记Service接口 * * @author Yinq - * @date 2025-06-05 + * @date 2025-06-06 */ public interface IPowerEnergySparePartsRegistrationService { @@ -62,10 +62,10 @@ public interface IPowerEnergySparePartsRegistrationService /** * 导入动力能源部行输科废旧备件登记数据 * - * @param recordList 记录数据列表 + * @param registrationList 登记数据列表 * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 * @param operName 操作用户 * @return 结果 */ - public String importPowerEnergySparePartsRegistration(List recordList, Boolean isUpdateSupport, String operName); + public String importPowerEnergySparePartsRegistration(List registrationList, Boolean isUpdateSupport, String operName); } diff --git a/os-ems/src/main/java/com/os/ems/info/service/ISparePartsInventoryService.java b/os-ems/src/main/java/com/os/ems/info/service/ISparePartsInventoryService.java index 02ffe2a..c3dfdfa 100644 --- a/os-ems/src/main/java/com/os/ems/info/service/ISparePartsInventoryService.java +++ b/os-ems/src/main/java/com/os/ems/info/service/ISparePartsInventoryService.java @@ -2,6 +2,7 @@ package com.os.ems.info.service; import java.util.List; import com.os.ems.info.domain.SparePartsInventory; +import com.os.ems.info.domain.SparePartsInventoryExportVO; /** * 备件库记录主Service接口 @@ -27,6 +28,14 @@ public interface ISparePartsInventoryService */ public List selectSparePartsInventoryList(SparePartsInventory sparePartsInventory); + /** + * 查询备件库记录导出列表(包含动态列) + * + * @param sparePartsInventory 备件库记录主 + * @return 备件库记录导出列表 + */ + public List selectSparePartsInventoryExportList(SparePartsInventory sparePartsInventory); + /** * 新增备件库记录主 * @@ -68,4 +77,45 @@ public interface ISparePartsInventoryService * @return 结果 */ public String importSparePartsInventory(List recordList, Boolean isUpdateSupport, String operName); + + /** + * 导入备件库记录主数据(支持动态列) + * + * @param exportList 导入数据列表(包含动态列) + * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 + * @param operName 操作用户 + * @return 结果 + */ + public String importSparePartsInventoryWithDynamicColumns(List exportList, Boolean isUpdateSupport, String operName); + + /** + * 查询备件库记录主详细信息(包含盘点数据) + * + * @param objid 备件库记录主主键 + * @return 备件库记录主VO + */ + public SparePartsInventoryExportVO selectSparePartsInventoryWithChecksByObjid(Long objid); + + /** + * 新增备件库记录主(包含动态列) + * + * @param sparePartsInventoryVO 备件库记录主VO + * @return 结果 + */ + public int insertSparePartsInventoryWithDynamicColumns(SparePartsInventoryExportVO sparePartsInventoryVO); + + /** + * 修改备件库记录主(包含动态列) + * + * @param sparePartsInventoryVO 备件库记录主VO + * @return 结果 + */ + public int updateSparePartsInventoryWithDynamicColumns(SparePartsInventoryExportVO sparePartsInventoryVO); + + /** + * 获取所有盘点名称 + * + * @return 盘点名称列表 + */ + public List getAllCheckNames(); } diff --git a/os-ems/src/main/java/com/os/ems/info/service/impl/PowerEnergySparePartsRegistrationServiceImpl.java b/os-ems/src/main/java/com/os/ems/info/service/impl/PowerEnergySparePartsRegistrationServiceImpl.java index 2e57c1a..d96b906 100644 --- a/os-ems/src/main/java/com/os/ems/info/service/impl/PowerEnergySparePartsRegistrationServiceImpl.java +++ b/os-ems/src/main/java/com/os/ems/info/service/impl/PowerEnergySparePartsRegistrationServiceImpl.java @@ -13,7 +13,7 @@ import com.os.ems.info.service.IPowerEnergySparePartsRegistrationService; * 动力能源部行输科废旧备件登记Service业务层处理 * * @author Yinq - * @date 2025-06-05 + * @date 2025-06-06 */ @Service public class PowerEnergySparePartsRegistrationServiceImpl implements IPowerEnergySparePartsRegistrationService @@ -96,15 +96,15 @@ public class PowerEnergySparePartsRegistrationServiceImpl implements IPowerEnerg /** * 导入动力能源部行输科废旧备件登记数据 * - * @param recordList 记录数据列表 + * @param registrationList 登记数据列表 * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 * @param operName 操作用户 * @return 结果 */ @Override - public String importPowerEnergySparePartsRegistration(List recordList, Boolean isUpdateSupport, String operName) + public String importPowerEnergySparePartsRegistration(List registrationList, Boolean isUpdateSupport, String operName) { - if (StringUtils.isNull(recordList) || recordList.size() == 0) + if (StringUtils.isNull(registrationList) || registrationList.size() == 0) { throw new ServiceException("导入数据不能为空!"); } @@ -112,51 +112,52 @@ public class PowerEnergySparePartsRegistrationServiceImpl implements IPowerEnerg int failureNum = 0; StringBuilder successMsg = new StringBuilder(); StringBuilder failureMsg = new StringBuilder(); - for (PowerEnergySparePartsRegistration record : recordList) + for (PowerEnergySparePartsRegistration registration : registrationList) { try { // 设置操作人 - record.setCreateBy(operName); + registration.setCreateBy(operName); - // 验证是否存在这个记录 - PowerEnergySparePartsRegistration existRecord = null; - if (StringUtils.isNotEmpty(record.getType()) && StringUtils.isNotEmpty(record.getReferenceLocation())) + // 验证是否存在这个记录(使用日期+备件名称+存放位置作为唯一性检查) + PowerEnergySparePartsRegistration existRegistration = null; + if (StringUtils.isNotEmpty(registration.getDate()) && StringUtils.isNotEmpty(registration.getSparePartsName()) && StringUtils.isNotEmpty(registration.getStorageLocation())) { - PowerEnergySparePartsRegistration queryRecord = new PowerEnergySparePartsRegistration(); - queryRecord.setType(record.getType()); - queryRecord.setReferenceLocation(record.getReferenceLocation()); - List existRecords = powerEnergySparePartsRegistrationMapper.selectPowerEnergySparePartsRegistrationList(queryRecord); - if (existRecords.size() > 0) + PowerEnergySparePartsRegistration queryRegistration = new PowerEnergySparePartsRegistration(); + queryRegistration.setDate(registration.getDate()); + queryRegistration.setSparePartsName(registration.getSparePartsName()); + queryRegistration.setStorageLocation(registration.getStorageLocation()); + List existRegistrations = powerEnergySparePartsRegistrationMapper.selectPowerEnergySparePartsRegistrationList(queryRegistration); + if (existRegistrations.size() > 0) { - existRecord = existRecords.get(0); + existRegistration = existRegistrations.get(0); } } - if (StringUtils.isNull(existRecord)) + if (StringUtils.isNull(existRegistration)) { - this.insertPowerEnergySparePartsRegistration(record); + this.insertPowerEnergySparePartsRegistration(registration); successNum++; - successMsg.append("
" + successNum + "、废旧备件登记 " + record.getType() + " 导入成功"); + successMsg.append("
" + successNum + "、废旧备件登记 " + registration.getSparePartsName() + " 导入成功"); } else if (isUpdateSupport) { - record.setObjid(existRecord.getObjid()); - record.setUpdateBy(operName); - this.updatePowerEnergySparePartsRegistration(record); + registration.setObjid(existRegistration.getObjid()); + registration.setUpdateBy(operName); + this.updatePowerEnergySparePartsRegistration(registration); successNum++; - successMsg.append("
" + successNum + "、废旧备件登记 " + record.getType() + " 更新成功"); + successMsg.append("
" + successNum + "、废旧备件登记 " + registration.getSparePartsName() + " 更新成功"); } else { failureNum++; - failureMsg.append("
" + failureNum + "、废旧备件登记 " + record.getType() + " 已存在"); + failureMsg.append("
" + failureNum + "、废旧备件登记 " + registration.getSparePartsName() + " 已存在"); } } catch (Exception e) { failureNum++; - String msg = "
" + failureNum + "、废旧备件登记 " + record.getType() + " 导入失败:"; + String msg = "
" + failureNum + "、废旧备件登记 " + registration.getSparePartsName() + " 导入失败:"; failureMsg.append(msg + e.getMessage()); } } diff --git a/os-ems/src/main/java/com/os/ems/info/service/impl/SparePartsInventoryServiceImpl.java b/os-ems/src/main/java/com/os/ems/info/service/impl/SparePartsInventoryServiceImpl.java index 4fef26a..983584b 100644 --- a/os-ems/src/main/java/com/os/ems/info/service/impl/SparePartsInventoryServiceImpl.java +++ b/os-ems/src/main/java/com/os/ems/info/service/impl/SparePartsInventoryServiceImpl.java @@ -1,13 +1,22 @@ package com.os.ems.info.service.impl; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.HashMap; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.os.common.exception.ServiceException; import com.os.common.utils.StringUtils; import com.os.ems.info.mapper.SparePartsInventoryMapper; +import com.os.ems.info.mapper.SparePartsInventoryCheckMapper; import com.os.ems.info.domain.SparePartsInventory; +import com.os.ems.info.domain.SparePartsInventoryCheck; +import com.os.ems.info.domain.SparePartsInventoryExportVO; import com.os.ems.info.service.ISparePartsInventoryService; +import com.os.common.utils.DateUtils; /** * 备件库记录主Service业务层处理 @@ -20,6 +29,9 @@ public class SparePartsInventoryServiceImpl implements ISparePartsInventoryServi { @Autowired private SparePartsInventoryMapper sparePartsInventoryMapper; + + @Autowired + private SparePartsInventoryCheckMapper sparePartsInventoryCheckMapper; /** * 查询备件库记录主 @@ -45,6 +57,81 @@ public class SparePartsInventoryServiceImpl implements ISparePartsInventoryServi return sparePartsInventoryMapper.selectSparePartsInventoryList(sparePartsInventory); } + /** + * 查询备件库记录导出列表(包含动态列) + * + * @param sparePartsInventory 备件库记录主 + * @return 备件库记录导出列表 + */ + @Override + public List selectSparePartsInventoryExportList(SparePartsInventory sparePartsInventory) + { + // 1. 查询主表数据 + List mainList = sparePartsInventoryMapper.selectSparePartsInventoryList(sparePartsInventory); + + // 2. 查询所有明细数据 + List checkList = sparePartsInventoryCheckMapper.selectSparePartsInventoryCheckList(new SparePartsInventoryCheck()); + + // 3. 按主表ID分组明细数据 + Map> checkMap = checkList.stream() + .collect(Collectors.groupingBy(SparePartsInventoryCheck::getInventoryObjid)); + + // 4. 转换为导出VO + List exportList = new ArrayList<>(); + for (SparePartsInventory main : mainList) { + SparePartsInventoryExportVO exportVO = new SparePartsInventoryExportVO(); + BeanUtils.copyProperties(main, exportVO); + + // 设置动态盘点数据 + List checks = checkMap.get(main.getObjid()); + if (checks != null) { + for (SparePartsInventoryCheck check : checks) { + exportVO.setCheckValue(check.getCheckName(), check.getCheckQuantity()); + } + } + + exportList.add(exportVO); + } + + return exportList; + } + + /** + * 查询备件库记录主详细信息(包含盘点数据) + * + * @param objid 备件库记录主主键 + * @return 备件库记录主VO + */ + @Override + public SparePartsInventoryExportVO selectSparePartsInventoryWithChecksByObjid(Long objid) + { + // 查询主记录 + SparePartsInventory inventory = sparePartsInventoryMapper.selectSparePartsInventoryByObjid(objid); + if (inventory == null) { + return null; + } + + // 创建VO并复制基础属性 + SparePartsInventoryExportVO vo = new SparePartsInventoryExportVO(); + BeanUtils.copyProperties(inventory, vo); + + // 查询盘点记录 + SparePartsInventoryCheck checkParam = new SparePartsInventoryCheck(); + checkParam.setInventoryObjid(objid); + List checkList = sparePartsInventoryCheckMapper.selectSparePartsInventoryCheckList(checkParam); + + // 构建盘点数据Map + Map checkData = new HashMap<>(); + for (SparePartsInventoryCheck check : checkList) { + if (StringUtils.isNotEmpty(check.getCheckName())) { + checkData.put(check.getCheckName(), check.getCheckQuantity()); + } + } + vo.setCheckData(checkData); + + return vo; + } + /** * 新增备件库记录主 * @@ -93,6 +180,122 @@ public class SparePartsInventoryServiceImpl implements ISparePartsInventoryServi return sparePartsInventoryMapper.deleteSparePartsInventoryByObjid(objid); } + /** + * 导入备件库记录主数据(支持动态列) + * + * @param exportList 导入数据列表(包含动态列) + * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 + * @param operName 操作用户 + * @return 结果 + */ + @Override + public String importSparePartsInventoryWithDynamicColumns(List exportList, Boolean isUpdateSupport, String operName) + { + if (StringUtils.isNull(exportList) || exportList.size() == 0) + { + throw new ServiceException("导入数据不能为空!"); + } + int successNum = 0; + int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + + for (SparePartsInventoryExportVO exportVO : exportList) + { + try + { + // 1. 转换为主表实体 + SparePartsInventory main = new SparePartsInventory(); + BeanUtils.copyProperties(exportVO, main); + main.setCreateBy(operName); + + // 2. 检查是否存在 + SparePartsInventory existRecord = null; + if (StringUtils.isNotEmpty(main.getItemName()) && StringUtils.isNotEmpty(main.getOriginalPartNumber())) + { + SparePartsInventory queryRecord = new SparePartsInventory(); + queryRecord.setItemName(main.getItemName()); + queryRecord.setOriginalPartNumber(main.getOriginalPartNumber()); + List existRecords = sparePartsInventoryMapper.selectSparePartsInventoryList(queryRecord); + if (existRecords.size() > 0) + { + existRecord = existRecords.get(0); + } + } + + Long objid; + if (StringUtils.isNull(existRecord)) + { + // 3. 插入主表 + sparePartsInventoryMapper.insertSparePartsInventory(main); + objid = main.getObjid(); + } + else if (isUpdateSupport) + { + // 4. 更新主表 + main.setObjid(existRecord.getObjid()); + main.setUpdateBy(operName); + sparePartsInventoryMapper.updateSparePartsInventory(main); + objid = existRecord.getObjid(); + + // 删除现有的盘点记录 + SparePartsInventoryCheck deleteQuery = new SparePartsInventoryCheck(); + deleteQuery.setInventoryObjid(objid); + List existingChecks = sparePartsInventoryCheckMapper.selectSparePartsInventoryCheckList(deleteQuery); + for (SparePartsInventoryCheck check : existingChecks) { + sparePartsInventoryCheckMapper.deleteSparePartsInventoryCheckById(check.getId()); + } + } + else + { + failureNum++; + failureMsg.append("
" + failureNum + "、备件库记录 " + main.getItemName() + " 已存在"); + continue; + } + + // 5. 处理动态盘点数据 + Map checkData = exportVO.getCheckData(); + if (checkData != null && !checkData.isEmpty()) { + for (Map.Entry entry : checkData.entrySet()) { + if (entry.getValue() != null) { + SparePartsInventoryCheck check = new SparePartsInventoryCheck(); + check.setInventoryObjid(objid); + check.setCheckName(entry.getKey()); + check.setCheckQuantity(entry.getValue()); + check.setCheckDate(DateUtils.getNowDate().toString()); + sparePartsInventoryCheckMapper.insertSparePartsInventoryCheck(check); + + // 更新主表的剩余数量为最新盘点数量 + main.setObjid(objid); + main.setRemainingQuantity(entry.getValue()); + sparePartsInventoryMapper.updateSparePartsInventory(main); + } + } + } + + successNum++; + successMsg.append("
" + successNum + "、备件库记录 " + main.getItemName() + " 导入成功"); + } + catch (Exception e) + { + failureNum++; + String msg = "
" + failureNum + "、备件库记录导入失败:"; + failureMsg.append(msg + e.getMessage()); + } + } + + if (failureNum > 0) + { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new ServiceException(failureMsg.toString()); + } + else + { + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } + /** * 导入备件库记录主数据 * @@ -171,4 +374,93 @@ public class SparePartsInventoryServiceImpl implements ISparePartsInventoryServi } return successMsg.toString(); } + + /** + * 新增备件库记录主(包含动态列) + * + * @param sparePartsInventoryVO 备件库记录主VO + * @return 结果 + */ + @Override + public int insertSparePartsInventoryWithDynamicColumns(SparePartsInventoryExportVO sparePartsInventoryVO) + { + // 创建主记录 + SparePartsInventory inventory = new SparePartsInventory(); + BeanUtils.copyProperties(sparePartsInventoryVO, inventory); + + // 插入主记录 + int result = sparePartsInventoryMapper.insertSparePartsInventory(inventory); + + // 处理盘点记录 + if (result > 0 && sparePartsInventoryVO.getCheckData() != null && !sparePartsInventoryVO.getCheckData().isEmpty()) { + Long objid = inventory.getObjid(); + for (Map.Entry entry : sparePartsInventoryVO.getCheckData().entrySet()) { + if (StringUtils.isNotEmpty(entry.getKey()) && entry.getValue() != null) { + SparePartsInventoryCheck check = new SparePartsInventoryCheck(); + check.setInventoryObjid(objid); + check.setCheckName(entry.getKey()); + check.setCheckQuantity(entry.getValue()); + check.setCheckDate(DateUtils.getNowDate().toString()); + sparePartsInventoryCheckMapper.insertSparePartsInventoryCheck(check); + } + } + } + + return result; + } + + /** + * 修改备件库记录主(包含动态列) + * + * @param sparePartsInventoryVO 备件库记录主VO + * @return 结果 + */ + @Override + public int updateSparePartsInventoryWithDynamicColumns(SparePartsInventoryExportVO sparePartsInventoryVO) + { + // 更新主记录 + SparePartsInventory inventory = new SparePartsInventory(); + BeanUtils.copyProperties(sparePartsInventoryVO, inventory); + int result = sparePartsInventoryMapper.updateSparePartsInventory(inventory); + + // 处理盘点记录 + if (result > 0 && sparePartsInventoryVO.getObjid() != null) { + Long objid = sparePartsInventoryVO.getObjid(); + + // 删除原有的盘点记录 + SparePartsInventoryCheck deleteParam = new SparePartsInventoryCheck(); + deleteParam.setInventoryObjid(objid); + List existingChecks = sparePartsInventoryCheckMapper.selectSparePartsInventoryCheckList(deleteParam); + for (SparePartsInventoryCheck existingCheck : existingChecks) { + sparePartsInventoryCheckMapper.deleteSparePartsInventoryCheckById(existingCheck.getId()); + } + + // 插入新的盘点记录 + if (sparePartsInventoryVO.getCheckData() != null && !sparePartsInventoryVO.getCheckData().isEmpty()) { + for (Map.Entry entry : sparePartsInventoryVO.getCheckData().entrySet()) { + if (StringUtils.isNotEmpty(entry.getKey()) && entry.getValue() != null) { + SparePartsInventoryCheck check = new SparePartsInventoryCheck(); + check.setInventoryObjid(objid); + check.setCheckName(entry.getKey()); + check.setCheckQuantity(entry.getValue()); + check.setCheckDate(DateUtils.getNowDate().toString()); + sparePartsInventoryCheckMapper.insertSparePartsInventoryCheck(check); + } + } + } + } + + return result; + } + + /** + * 获取所有盘点名称 + * + * @return 盘点名称列表 + */ + @Override + public List getAllCheckNames() + { + return sparePartsInventoryCheckMapper.selectDistinctCheckNames(); + } } diff --git a/os-ems/src/main/resources/mapper/ems/info/PowerEnergySparePartsRegistrationMapper.xml b/os-ems/src/main/resources/mapper/ems/info/PowerEnergySparePartsRegistrationMapper.xml index 8a6d723..71a00dd 100644 --- a/os-ems/src/main/resources/mapper/ems/info/PowerEnergySparePartsRegistrationMapper.xml +++ b/os-ems/src/main/resources/mapper/ems/info/PowerEnergySparePartsRegistrationMapper.xml @@ -6,53 +6,31 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - - - - - + + + + + + - - - - - - - - - - - - - + - select objid, type, reference_location, location_description, power_source, battery_type, remarks, image_location, first_instance, second_instance, third_instance, fourth_instance, fifth_instance, sixth_instance, seventh_instance, eighth_instance, ninth_instance, tenth_instance, eleventh_instance, twelfth_instance from power_energy_spare_parts_registration + select objid, date, spare_parts_name, waste_quantity, storage_location, registrar, warehouse_confirmation, remarks, spare_part_model from power_energy_spare_parts_registration @@ -64,71 +42,38 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" insert into power_energy_spare_parts_registration - type, - reference_location, - location_description, - power_source, - battery_type, + date, + spare_parts_name, + waste_quantity, + storage_location, + registrar, + warehouse_confirmation, remarks, - image_location, - first_instance, - second_instance, - third_instance, - fourth_instance, - fifth_instance, - sixth_instance, - seventh_instance, - eighth_instance, - ninth_instance, - tenth_instance, - eleventh_instance, - twelfth_instance, + spare_part_model, - #{type}, - #{referenceLocation}, - #{locationDescription}, - #{powerSource}, - #{batteryType}, + #{date}, + #{sparePartsName}, + #{wasteQuantity}, + #{storageLocation}, + #{registrar}, + #{warehouseConfirmation}, #{remarks}, - #{imageLocation}, - #{firstInstance}, - #{secondInstance}, - #{thirdInstance}, - #{fourthInstance}, - #{fifthInstance}, - #{sixthInstance}, - #{seventhInstance}, - #{eighthInstance}, - #{ninthInstance}, - #{tenthInstance}, - #{eleventhInstance}, - #{twelfthInstance}, + #{sparePartModel}, update power_energy_spare_parts_registration - type = #{type}, - reference_location = #{referenceLocation}, - location_description = #{locationDescription}, - power_source = #{powerSource}, - battery_type = #{batteryType}, + date = #{date}, + spare_parts_name = #{sparePartsName}, + waste_quantity = #{wasteQuantity}, + storage_location = #{storageLocation}, + registrar = #{registrar}, + warehouse_confirmation = #{warehouseConfirmation}, remarks = #{remarks}, - image_location = #{imageLocation}, - first_instance = #{firstInstance}, - second_instance = #{secondInstance}, - third_instance = #{thirdInstance}, - fourth_instance = #{fourthInstance}, - fifth_instance = #{fifthInstance}, - sixth_instance = #{sixthInstance}, - seventh_instance = #{seventhInstance}, - eighth_instance = #{eighthInstance}, - ninth_instance = #{ninthInstance}, - tenth_instance = #{tenthInstance}, - eleventh_instance = #{eleventhInstance}, - twelfth_instance = #{twelfthInstance}, + spare_part_model = #{sparePartModel}, where objid = #{objid} diff --git a/os-ems/src/main/resources/mapper/ems/info/SparePartsInventoryCheckMapper.xml b/os-ems/src/main/resources/mapper/ems/info/SparePartsInventoryCheckMapper.xml index 33fa165..50aece6 100644 --- a/os-ems/src/main/resources/mapper/ems/info/SparePartsInventoryCheckMapper.xml +++ b/os-ems/src/main/resources/mapper/ems/info/SparePartsInventoryCheckMapper.xml @@ -68,4 +68,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{id} + + \ No newline at end of file