导入设备数据

This commit is contained in:
2025-11-18 15:34:46 +08:00
parent 6d58268874
commit 3798e52ee0
23 changed files with 1351 additions and 192 deletions

View File

@ -13,12 +13,14 @@ import com.fuyuanshen.common.satoken.utils.LoginHelper;
import com.fuyuanshen.common.web.core.BaseController;
import com.fuyuanshen.customer.mapper.CustomerMapper;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.dto.DeviceExcelImportDTO;
import com.fuyuanshen.equipment.domain.dto.ImportResult;
import com.fuyuanshen.equipment.domain.form.DeviceForm;
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
import com.fuyuanshen.equipment.domain.vo.CustomerVo;
import com.fuyuanshen.equipment.excel.DeviceImportParams;
import com.fuyuanshen.equipment.excel.HeadValidateListener;
import com.fuyuanshen.equipment.excel.UploadDeviceDataListener;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
@ -39,7 +41,10 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @Description:
@ -163,7 +168,7 @@ public class DeviceController extends BaseController {
@Operation(summary = "导出数据设备")
@GetMapping(value = "/download")
@GetMapping(value = "/download1")
public R<Void> exportDevice(HttpServletResponse response, DeviceQueryCriteria criteria) throws IOException {
List<Device> devices = deviceService.queryAll(criteria);
exportService.export(devices, response);
@ -171,9 +176,36 @@ public class DeviceController extends BaseController {
}
/**
* 导出设备数据(包含完整设备类型信息)
*
* @param response HttpServletResponse对象
* @param criteria 查询条件
* @return R<Void>
*/
@Operation(summary = "导出设备数据(包含完整设备类型信息)")
@GetMapping(value = "/download")
public R<Void> exportDeviceWithFullTypeInfo(HttpServletResponse response, DeviceQueryCriteria criteria) {
// 获取所有符合条件的设备
List<Device> devices = deviceService.queryAll(criteria);
// 获取所有设备类型信息
List<DeviceType> deviceTypes = deviceTypeService.queryDeviceTypes();
// 导出数据(包含完整设备类型信息)
exportService.exportWithTypeInfo(devices, deviceTypes, response);
return R.ok();
}
/**
* 导入设备数据
*
* @param file
* @return
* @throws BadRequestException
*/
@Operation(summary = "导入设备数据")
@PostMapping(value = "/import", consumes = "multipart/form-data")
public R<ImportResult> importData(@Parameter(name = "文件", required = true) @RequestPart("file") MultipartFile file) throws BadRequestException {
@PostMapping(value = "/import1", consumes = "multipart/form-data")
public R<ImportResult> importData1(@Parameter(name = "文件", required = true) @RequestPart("file") MultipartFile file) throws BadRequestException {
String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
if (!("xlsx".equalsIgnoreCase(suffix))) {
@ -207,6 +239,105 @@ public class DeviceController extends BaseController {
}
}
/**
* 导入设备数据
*
* @param file 文件
* @return R<ImportResult>
*/
@Operation(summary = "导入设备数据")
@PostMapping(value = "/import", consumes = "multipart/form-data")
public R<ImportResult> importData(@Parameter(name = "文件", required = true) @RequestPart("file") MultipartFile file) throws BadRequestException {
String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
if (!("xlsx".equalsIgnoreCase(suffix))) {
throw new BadRequestException("只能上传Excel——xlsx格式文件");
}
// 检查文件大小限制为100MB
if (file.getSize() > 100 * 10 * 1024 * 1024) {
throw new BadRequestException("文件大小不能超过100MB");
}
// 校验模板
validateExcelTemplate(file);
ImportResult result = new ImportResult();
try {
LoginUser loginUser = LoginHelper.getLoginUser();
DeviceImportParams params = DeviceImportParams.builder().ossService(ossService)
.deviceService(deviceService).tenantId(loginUser.getTenantId())
.file(file).filePath("").deviceMapper(deviceMapper).deviceTypeService(deviceTypeService)
.deviceTypeMapper(deviceTypeMapper).userId(loginUser.getUserId())
.build();
// 创建监听器
UploadDeviceDataListener listener = new UploadDeviceDataListener(params);
// 读取Excel
EasyExcel.read(file.getInputStream(), DeviceExcelImportDTO.class, listener).sheet().doRead();
// 获取导入结果
result = listener.getImportResult();
// 设置响应消息
String message = String.format("成功导入 %d 条数据,失败 %d 条", result.getSuccessCount(), result.getFailureCount());
// 返回带有正确泛型的响应
return R.ok(message, result);
} catch (Exception e) {
log.error("导入设备数据出错: {}", e.getMessage(), e);
// 在异常情况下,设置默认结果
String errorMessage = String.format("导入失败: %s。成功 %d 条,失败 %d 条", e.getMessage(), result.getSuccessCount(), result.getFailureCount());
// 使用新方法确保类型正确
return R.fail(errorMessage, result);
}
}
/**
* 校验Excel模板是否正确
*
* @param file MultipartFile对象
* @throws BadRequestException 当模板不正确时抛出异常
*/
private void validateExcelTemplate(MultipartFile file) throws BadRequestException {
try {
// 创建一个只读取表头的监听器
HeadValidateListener headValidateListener = new HeadValidateListener();
// 使用EasyExcel读取表头
EasyExcel.read(file.getInputStream(), headValidateListener)
.sheet()
.headRowNumber(0)
.doRead();
// 获取读取到的表头信息
List<String> actualHeaders = headValidateListener.getHeadNames();
// 定义必需的表头
Set<String> requiredHeaders = new HashSet<>(Arrays.asList(
"设备名称", "设备类型名称", "设备图片", "设备MAC", "蓝牙名称", "设备IMEI",
"备注", "是否支持蓝牙", "定位方式", "通讯方式",
"型号字典用于APP页面跳转", "型号字典用于PC页面跳转"
));
// 检查必需的表头是否都存在
Set<String> actualHeaderSet = new HashSet<>(actualHeaders);
if (!actualHeaderSet.containsAll(requiredHeaders)) {
requiredHeaders.removeAll(actualHeaderSet);
throw new BadRequestException("Excel模板缺少必需的列: " + String.join(", ", requiredHeaders));
}
// 检查第三列索引为2是否为"设备图片"
if (actualHeaders.size() > 2 && !"设备图片".equals(actualHeaders.get(2))) {
throw new BadRequestException("Excel模板不正确第三列必须是'设备图片'列");
}
} catch (BadRequestException e) {
throw e; // 直接重新抛出
} catch (Exception e) {
log.error("校验Excel模板时发生错误: {}", e.getMessage(), e);
throw new BadRequestException("校验Excel模板时发生错误: " + e.getMessage());
}
}
}