feat(ems): 添加备件库记录盘点功能

- 新增盘点记录相关API和UI
- 实现备件库记录的动态列展示
- 添加盘点记录的添加和删除功能
- 优化表单布局和数据处理逻辑
boardTest
zch 8 months ago
parent ff83ba78ec
commit 7d4811a57f

@ -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<PowerEnergySparePartsRegistration> list = service.selectList(params);
```
2. **设置图片路径**
确保实体对象的`imageLocation`字段包含正确的图片路径
3. **执行导出**
```java
ExcelUtil<PowerEnergySparePartsRegistration> util = new ExcelUtil<>(PowerEnergySparePartsRegistration.class);
util.exportExcel(response, list, "备件登记数据");
```
4. **结果**
- 生成包含图片的Excel文件
- 图片自动嵌入到对应单元格中
- 图片尺寸根据注解自动调整
### 导入流程
1. **上传Excel文件**
- 支持.xlsx和.xls格式
- 文件中可包含嵌入的图片
2. **图片提取**
```java
List<PowerEnergySparePartsRegistration> 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. 功能扩展
- 批量图片处理
- 图片预览功能
- 历史版本管理

@ -0,0 +1,241 @@
# 前端Excel图片导入导出功能说明
## 功能概述
前端已完整适配Excel图片导入导出功能提供了用户友好的界面和完善的错误处理机制。
### 新增功能
1. **Excel导入功能**
- 文件拖拽上传
- 格式验证 (.xlsx, .xls)
- 进度提示
- 错误处理和结果展示
2. **导入模板下载**
- 一键下载包含图片列的Excel模板
- 预设字段格式和说明
3. **增强的导出功能**
- 图片自动嵌入Excel
- 优化的文件下载体验
## 界面变化
### 1. 新增按钮
在操作工具栏中新增:
```html
<el-button
type="info"
plain
icon="el-icon-upload2"
size="mini"
@click="handleImport"
v-hasPermi="['ems/info:powerEnergyRegistration:import']"
>导入</el-button>
```
### 2. 导入对话框
```html
<el-dialog :title="uploadTitle" :visible.sync="uploadOpen" width="400px">
<el-upload
ref="upload"
:limit="1"
accept=".xlsx, .xls"
:headers="uploadHeaders"
:action="uploadUrl"
:disabled="uploadLoading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:on-error="handleFileError"
:auto-upload="false"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将Excel文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<div class="el-upload__tip">
<el-checkbox v-model="updateSupport" /> 是否更新已经存在的数据
</div>
<span>仅允许导入xls、xlsx格式文件。</span>
<el-link type="primary" @click="importTemplate">下载模板</el-link>
</div>
</el-upload>
</el-dialog>
```
## 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+
建议使用最新版本的现代浏览器以获得最佳体验。

@ -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<PowerEnergySparePartsRegistration> util = new ExcelUtil<PowerEnergySparePartsRegistration>(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<PowerEnergySparePartsRegistration> util = new ExcelUtil<PowerEnergySparePartsRegistration>(PowerEnergySparePartsRegistration.class);
List<PowerEnergySparePartsRegistration> recordList = util.importExcel(file.getInputStream());
List<PowerEnergySparePartsRegistration> 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<PowerEnergySparePartsRegistration> util = new ExcelUtil<PowerEnergySparePartsRegistration>(PowerEnergySparePartsRegistration.class);
return util.importTemplateExcel("动力能源部行输科废旧备件登记数据");
}
}

@ -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<SparePartsInventory> list = sparePartsInventoryService.selectSparePartsInventoryList(sparePartsInventory);
ExcelUtil<SparePartsInventory> util = new ExcelUtil<SparePartsInventory>(SparePartsInventory.class);
util.exportExcel(response, list, "备件库记录主数据");
// 获取包含动态列的数据
List<SparePartsInventoryExportVO> list = sparePartsInventoryService.selectSparePartsInventoryExportList(sparePartsInventory);
// 收集所有的盘点列名
Set<String> 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<String> 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<SparePartsInventoryExportVO> 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<String> 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<SparePartsInventory> util = new ExcelUtil<SparePartsInventory>(SparePartsInventory.class);
List<SparePartsInventory> dataList = util.importExcel(file.getInputStream());
String message = sparePartsInventoryService.importSparePartsInventory(dataList, updateSupport, getUsername());
// 解析Excel文件支持动态列
List<SparePartsInventoryExportVO> dataList = parseExcelWithDynamicColumns(file);
String message = sparePartsInventoryService.importSparePartsInventoryWithDynamicColumns(dataList, updateSupport, getUsername());
return AjaxResult.success(message);
}
/**
* Excel
*/
private List<SparePartsInventoryExportVO> parseExcelWithDynamicColumns(MultipartFile file) throws Exception {
List<SparePartsInventoryExportVO> dataList = new ArrayList<>();
Workbook workbook = new XSSFWorkbook(file.getInputStream());
Sheet sheet = workbook.getSheetAt(0);
// 解析表头
Row headerRow = sheet.getRow(0);
Map<Integer, String> 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<Integer, String> 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;
}
}
/**
*
*/

@ -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();
}
}

@ -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<String, Long> 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<String, Long> getCheckData() { return checkData; }
public void setCheckData(Map<String, Long> 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();
}
}

@ -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
{

@ -58,4 +58,11 @@ public interface SparePartsInventoryCheckMapper
* @return
*/
public int deleteSparePartsInventoryCheckByIds(Long[] ids);
/**
*
*
* @return
*/
public List<String> selectDistinctCheckNames();
}

@ -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<PowerEnergySparePartsRegistration> recordList, Boolean isUpdateSupport, String operName);
public String importPowerEnergySparePartsRegistration(List<PowerEnergySparePartsRegistration> registrationList, Boolean isUpdateSupport, String operName);
}

@ -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<SparePartsInventory> selectSparePartsInventoryList(SparePartsInventory sparePartsInventory);
/**
*
*
* @param sparePartsInventory
* @return
*/
public List<SparePartsInventoryExportVO> selectSparePartsInventoryExportList(SparePartsInventory sparePartsInventory);
/**
*
*
@ -68,4 +77,45 @@ public interface ISparePartsInventoryService
* @return
*/
public String importSparePartsInventory(List<SparePartsInventory> recordList, Boolean isUpdateSupport, String operName);
/**
*
*
* @param exportList
* @param isUpdateSupport
* @param operName
* @return
*/
public String importSparePartsInventoryWithDynamicColumns(List<SparePartsInventoryExportVO> 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<String> getAllCheckNames();
}

@ -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<PowerEnergySparePartsRegistration> recordList, Boolean isUpdateSupport, String operName)
public String importPowerEnergySparePartsRegistration(List<PowerEnergySparePartsRegistration> 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<PowerEnergySparePartsRegistration> 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<PowerEnergySparePartsRegistration> 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("<br/>" + successNum + "、废旧备件登记 " + record.getType() + " 导入成功");
successMsg.append("<br/>" + 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("<br/>" + successNum + "、废旧备件登记 " + record.getType() + " 更新成功");
successMsg.append("<br/>" + successNum + "、废旧备件登记 " + registration.getSparePartsName() + " 更新成功");
}
else
{
failureNum++;
failureMsg.append("<br/>" + failureNum + "、废旧备件登记 " + record.getType() + " 已存在");
failureMsg.append("<br/>" + failureNum + "、废旧备件登记 " + registration.getSparePartsName() + " 已存在");
}
}
catch (Exception e)
{
failureNum++;
String msg = "<br/>" + failureNum + "、废旧备件登记 " + record.getType() + " 导入失败:";
String msg = "<br/>" + failureNum + "、废旧备件登记 " + registration.getSparePartsName() + " 导入失败:";
failureMsg.append(msg + e.getMessage());
}
}

@ -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<SparePartsInventoryExportVO> selectSparePartsInventoryExportList(SparePartsInventory sparePartsInventory)
{
// 1. 查询主表数据
List<SparePartsInventory> mainList = sparePartsInventoryMapper.selectSparePartsInventoryList(sparePartsInventory);
// 2. 查询所有明细数据
List<SparePartsInventoryCheck> checkList = sparePartsInventoryCheckMapper.selectSparePartsInventoryCheckList(new SparePartsInventoryCheck());
// 3. 按主表ID分组明细数据
Map<Long, List<SparePartsInventoryCheck>> checkMap = checkList.stream()
.collect(Collectors.groupingBy(SparePartsInventoryCheck::getInventoryObjid));
// 4. 转换为导出VO
List<SparePartsInventoryExportVO> exportList = new ArrayList<>();
for (SparePartsInventory main : mainList) {
SparePartsInventoryExportVO exportVO = new SparePartsInventoryExportVO();
BeanUtils.copyProperties(main, exportVO);
// 设置动态盘点数据
List<SparePartsInventoryCheck> 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<SparePartsInventoryCheck> checkList = sparePartsInventoryCheckMapper.selectSparePartsInventoryCheckList(checkParam);
// 构建盘点数据Map
Map<String, Long> 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<SparePartsInventoryExportVO> 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<SparePartsInventory> 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<SparePartsInventoryCheck> existingChecks = sparePartsInventoryCheckMapper.selectSparePartsInventoryCheckList(deleteQuery);
for (SparePartsInventoryCheck check : existingChecks) {
sparePartsInventoryCheckMapper.deleteSparePartsInventoryCheckById(check.getId());
}
}
else
{
failureNum++;
failureMsg.append("<br/>" + failureNum + "、备件库记录 " + main.getItemName() + " 已存在");
continue;
}
// 5. 处理动态盘点数据
Map<String, Long> checkData = exportVO.getCheckData();
if (checkData != null && !checkData.isEmpty()) {
for (Map.Entry<String, Long> 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("<br/>" + successNum + "、备件库记录 " + main.getItemName() + " 导入成功");
}
catch (Exception e)
{
failureNum++;
String msg = "<br/>" + 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<String, Long> 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<SparePartsInventoryCheck> existingChecks = sparePartsInventoryCheckMapper.selectSparePartsInventoryCheckList(deleteParam);
for (SparePartsInventoryCheck existingCheck : existingChecks) {
sparePartsInventoryCheckMapper.deleteSparePartsInventoryCheckById(existingCheck.getId());
}
// 插入新的盘点记录
if (sparePartsInventoryVO.getCheckData() != null && !sparePartsInventoryVO.getCheckData().isEmpty()) {
for (Map.Entry<String, Long> 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<String> getAllCheckNames()
{
return sparePartsInventoryCheckMapper.selectDistinctCheckNames();
}
}

@ -6,53 +6,31 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<resultMap type="PowerEnergySparePartsRegistration" id="PowerEnergySparePartsRegistrationResult">
<result property="objid" column="objid" />
<result property="type" column="type" />
<result property="referenceLocation" column="reference_location" />
<result property="locationDescription" column="location_description" />
<result property="powerSource" column="power_source" />
<result property="batteryType" column="battery_type" />
<result property="date" column="date" />
<result property="sparePartsName" column="spare_parts_name" />
<result property="wasteQuantity" column="waste_quantity" />
<result property="storageLocation" column="storage_location" />
<result property="registrar" column="registrar" />
<result property="warehouseConfirmation" column="warehouse_confirmation" />
<result property="remarks" column="remarks" />
<result property="imageLocation" column="image_location" />
<result property="firstInstance" column="first_instance" />
<result property="secondInstance" column="second_instance" />
<result property="thirdInstance" column="third_instance" />
<result property="fourthInstance" column="fourth_instance" />
<result property="fifthInstance" column="fifth_instance" />
<result property="sixthInstance" column="sixth_instance" />
<result property="seventhInstance" column="seventh_instance" />
<result property="eighthInstance" column="eighth_instance" />
<result property="ninthInstance" column="ninth_instance" />
<result property="tenthInstance" column="tenth_instance" />
<result property="eleventhInstance" column="eleventh_instance" />
<result property="twelfthInstance" column="twelfth_instance" />
<result property="sparePartModel" column="spare_part_model" />
</resultMap>
<sql id="selectPowerEnergySparePartsRegistrationVo">
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
</sql>
<select id="selectPowerEnergySparePartsRegistrationList" parameterType="PowerEnergySparePartsRegistration" resultMap="PowerEnergySparePartsRegistrationResult">
<include refid="selectPowerEnergySparePartsRegistrationVo"/>
<where>
<if test="type != null and type != ''"> and type like concat('%', #{type}, '%')</if>
<if test="referenceLocation != null and referenceLocation != ''"> and reference_location like concat('%', #{referenceLocation}, '%')</if>
<if test="locationDescription != null and locationDescription != ''"> and location_description like concat('%', #{locationDescription}, '%')</if>
<if test="powerSource != null and powerSource != ''"> and power_source like concat('%', #{powerSource}, '%')</if>
<if test="batteryType != null and batteryType != ''"> and battery_type like concat('%', #{batteryType}, '%')</if>
<if test="date != null and date != ''"> and date like concat('%', #{date}, '%')</if>
<if test="sparePartsName != null and sparePartsName != ''"> and spare_parts_name like concat('%', #{sparePartsName}, '%')</if>
<if test="wasteQuantity != null "> and waste_quantity like concat('%', #{wasteQuantity}, '%')</if>
<if test="storageLocation != null and storageLocation != ''"> and storage_location like concat('%', #{storageLocation}, '%')</if>
<if test="registrar != null and registrar != ''"> and registrar like concat('%', #{registrar}, '%')</if>
<if test="warehouseConfirmation != null and warehouseConfirmation != ''"> and warehouse_confirmation like concat('%', #{warehouseConfirmation}, '%')</if>
<if test="remarks != null and remarks != ''"> and remarks = #{remarks}</if>
<if test="imageLocation != null and imageLocation != ''"> and image_location = #{imageLocation}</if>
<if test="firstInstance != null and firstInstance != ''"> and first_instance = #{firstInstance}</if>
<if test="secondInstance != null and secondInstance != ''"> and second_instance = #{secondInstance}</if>
<if test="thirdInstance != null and thirdInstance != ''"> and third_instance = #{thirdInstance}</if>
<if test="fourthInstance != null and fourthInstance != ''"> and fourth_instance = #{fourthInstance}</if>
<if test="fifthInstance != null and fifthInstance != ''"> and fifth_instance = #{fifthInstance}</if>
<if test="sixthInstance != null and sixthInstance != ''"> and sixth_instance = #{sixthInstance}</if>
<if test="seventhInstance != null and seventhInstance != ''"> and seventh_instance = #{seventhInstance}</if>
<if test="eighthInstance != null and eighthInstance != ''"> and eighth_instance = #{eighthInstance}</if>
<if test="ninthInstance != null and ninthInstance != ''"> and ninth_instance = #{ninthInstance}</if>
<if test="tenthInstance != null and tenthInstance != ''"> and tenth_instance = #{tenthInstance}</if>
<if test="eleventhInstance != null and eleventhInstance != ''"> and eleventh_instance = #{eleventhInstance}</if>
<if test="twelfthInstance != null and twelfthInstance != ''"> and twelfth_instance = #{twelfthInstance}</if>
<if test="sparePartModel != null and sparePartModel != ''"> and spare_part_model like concat('%', #{sparePartModel}, '%')</if>
</where>
</select>
@ -64,71 +42,38 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<insert id="insertPowerEnergySparePartsRegistration" parameterType="PowerEnergySparePartsRegistration" useGeneratedKeys="true" keyProperty="objid">
insert into power_energy_spare_parts_registration
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="type != null">type,</if>
<if test="referenceLocation != null">reference_location,</if>
<if test="locationDescription != null">location_description,</if>
<if test="powerSource != null">power_source,</if>
<if test="batteryType != null">battery_type,</if>
<if test="date != null">date,</if>
<if test="sparePartsName != null">spare_parts_name,</if>
<if test="wasteQuantity != null">waste_quantity,</if>
<if test="storageLocation != null">storage_location,</if>
<if test="registrar != null">registrar,</if>
<if test="warehouseConfirmation != null">warehouse_confirmation,</if>
<if test="remarks != null">remarks,</if>
<if test="imageLocation != null">image_location,</if>
<if test="firstInstance != null">first_instance,</if>
<if test="secondInstance != null">second_instance,</if>
<if test="thirdInstance != null">third_instance,</if>
<if test="fourthInstance != null">fourth_instance,</if>
<if test="fifthInstance != null">fifth_instance,</if>
<if test="sixthInstance != null">sixth_instance,</if>
<if test="seventhInstance != null">seventh_instance,</if>
<if test="eighthInstance != null">eighth_instance,</if>
<if test="ninthInstance != null">ninth_instance,</if>
<if test="tenthInstance != null">tenth_instance,</if>
<if test="eleventhInstance != null">eleventh_instance,</if>
<if test="twelfthInstance != null">twelfth_instance,</if>
<if test="sparePartModel != null">spare_part_model,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="type != null">#{type},</if>
<if test="referenceLocation != null">#{referenceLocation},</if>
<if test="locationDescription != null">#{locationDescription},</if>
<if test="powerSource != null">#{powerSource},</if>
<if test="batteryType != null">#{batteryType},</if>
<if test="date != null">#{date},</if>
<if test="sparePartsName != null">#{sparePartsName},</if>
<if test="wasteQuantity != null">#{wasteQuantity},</if>
<if test="storageLocation != null">#{storageLocation},</if>
<if test="registrar != null">#{registrar},</if>
<if test="warehouseConfirmation != null">#{warehouseConfirmation},</if>
<if test="remarks != null">#{remarks},</if>
<if test="imageLocation != null">#{imageLocation},</if>
<if test="firstInstance != null">#{firstInstance},</if>
<if test="secondInstance != null">#{secondInstance},</if>
<if test="thirdInstance != null">#{thirdInstance},</if>
<if test="fourthInstance != null">#{fourthInstance},</if>
<if test="fifthInstance != null">#{fifthInstance},</if>
<if test="sixthInstance != null">#{sixthInstance},</if>
<if test="seventhInstance != null">#{seventhInstance},</if>
<if test="eighthInstance != null">#{eighthInstance},</if>
<if test="ninthInstance != null">#{ninthInstance},</if>
<if test="tenthInstance != null">#{tenthInstance},</if>
<if test="eleventhInstance != null">#{eleventhInstance},</if>
<if test="twelfthInstance != null">#{twelfthInstance},</if>
<if test="sparePartModel != null">#{sparePartModel},</if>
</trim>
</insert>
<update id="updatePowerEnergySparePartsRegistration" parameterType="PowerEnergySparePartsRegistration">
update power_energy_spare_parts_registration
<trim prefix="SET" suffixOverrides=",">
<if test="type != null">type = #{type},</if>
<if test="referenceLocation != null">reference_location = #{referenceLocation},</if>
<if test="locationDescription != null">location_description = #{locationDescription},</if>
<if test="powerSource != null">power_source = #{powerSource},</if>
<if test="batteryType != null">battery_type = #{batteryType},</if>
<if test="date != null">date = #{date},</if>
<if test="sparePartsName != null">spare_parts_name = #{sparePartsName},</if>
<if test="wasteQuantity != null">waste_quantity = #{wasteQuantity},</if>
<if test="storageLocation != null">storage_location = #{storageLocation},</if>
<if test="registrar != null">registrar = #{registrar},</if>
<if test="warehouseConfirmation != null">warehouse_confirmation = #{warehouseConfirmation},</if>
<if test="remarks != null">remarks = #{remarks},</if>
<if test="imageLocation != null">image_location = #{imageLocation},</if>
<if test="firstInstance != null">first_instance = #{firstInstance},</if>
<if test="secondInstance != null">second_instance = #{secondInstance},</if>
<if test="thirdInstance != null">third_instance = #{thirdInstance},</if>
<if test="fourthInstance != null">fourth_instance = #{fourthInstance},</if>
<if test="fifthInstance != null">fifth_instance = #{fifthInstance},</if>
<if test="sixthInstance != null">sixth_instance = #{sixthInstance},</if>
<if test="seventhInstance != null">seventh_instance = #{seventhInstance},</if>
<if test="eighthInstance != null">eighth_instance = #{eighthInstance},</if>
<if test="ninthInstance != null">ninth_instance = #{ninthInstance},</if>
<if test="tenthInstance != null">tenth_instance = #{tenthInstance},</if>
<if test="eleventhInstance != null">eleventh_instance = #{eleventhInstance},</if>
<if test="twelfthInstance != null">twelfth_instance = #{twelfthInstance},</if>
<if test="sparePartModel != null">spare_part_model = #{sparePartModel},</if>
</trim>
where objid = #{objid}
</update>

@ -68,4 +68,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{id}
</foreach>
</delete>
<select id="selectDistinctCheckNames" resultType="String">
select distinct check_name from spare_parts_inventory_check
where check_name is not null and check_name != ''
order by check_name
</select>
</mapper>
Loading…
Cancel
Save