图片识别导出下载
This commit is contained in:
parent
cbb23dc612
commit
62b8f1c934
|
|
@ -0,0 +1,92 @@
|
|||
package com.bonus.web.controller.data;
|
||||
|
||||
import com.bonus.common.domain.data.dto.ParamsDto;
|
||||
import com.bonus.common.domain.data.vo.ExportTask;
|
||||
import com.bonus.web.service.data.ExportService;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @className:ExportController
|
||||
* @author:cwchen
|
||||
* @date:2025-12-26-10:15
|
||||
* @version:1.0
|
||||
* @description:导出zip压缩包-web层
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/device/imageRecognition")
|
||||
@CrossOrigin
|
||||
public class ExportController {
|
||||
|
||||
@Resource(name = "ExportService")
|
||||
private ExportService exportService;
|
||||
|
||||
/**
|
||||
* 1. 启动导出任务
|
||||
* 对应前端: exportImageRecognitionAPI
|
||||
*/
|
||||
@GetMapping("/export")
|
||||
public Map<String, Object> startExport(ParamsDto dto) {
|
||||
// 启动异步任务
|
||||
String taskId = exportService.createExportTask(dto);
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("taskId", taskId);
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("code", 200);
|
||||
result.put("msg", "任务已启动");
|
||||
result.put("data", data);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 2. 查询进度
|
||||
* 对应前端: getExportProgressAPI
|
||||
*/
|
||||
@GetMapping("/progress")
|
||||
public Map<String, Object> getProgress(@RequestParam String taskId) {
|
||||
ExportTask task = exportService.getTaskStatus(taskId);
|
||||
// 修改 404 情况
|
||||
if (task == null) {
|
||||
Map<String, Object> errorResult = new HashMap<>();
|
||||
errorResult.put("code", 404);
|
||||
errorResult.put("msg", "任务不存在");
|
||||
return errorResult;
|
||||
}
|
||||
// 修改成功情况
|
||||
Map<String, Object> successResult = new HashMap<>();
|
||||
successResult.put("code", 200);
|
||||
successResult.put("data", task);
|
||||
return successResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 3. 下载文件
|
||||
* 对应前端: downloadExportFileAPI
|
||||
*/
|
||||
@GetMapping("/download")
|
||||
public ResponseEntity<org.springframework.core.io.Resource> downloadFile(
|
||||
@RequestParam(required = false) String taskId) throws IOException {
|
||||
|
||||
File file = exportService.getExportFile(taskId);
|
||||
|
||||
if (file == null || !file.exists()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
org.springframework.core.io.Resource resource = new org.springframework.core.io.FileSystemResource(file);
|
||||
String fileName = URLEncoder.encode(file.getName(), "UTF-8").replaceAll("\\+", "%20");
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"")
|
||||
.body(resource);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.bonus.common.core.domain.AjaxResult;
|
|||
import com.bonus.common.domain.data.dto.ParamsDto;
|
||||
import com.bonus.common.domain.data.vo.DeviceIdentificationDataCountVo;
|
||||
import com.bonus.common.domain.data.vo.DeviceIdentificationDataVo;
|
||||
import com.bonus.common.domain.data.vo.ImageRecord;
|
||||
import com.bonus.data.service.DIDeviceIdentificationService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -113,4 +114,33 @@ public class DeviceIdentificationService {
|
|||
private double round(double value) {
|
||||
return BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询要下载的识别图片
|
||||
* @param dto
|
||||
* @return List<ImageRecord>
|
||||
* @author cwchen
|
||||
* @date 2025/12/26 10:38
|
||||
*/
|
||||
public List<ImageRecord> getImageData(ParamsDto dto) {
|
||||
try {
|
||||
if (dto.getStartTime() == null || dto.getEndTime() == null) {
|
||||
// 获取今天的日期
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
// 设置开始时间为 00:00:00
|
||||
LocalDateTime startOfDay = now.with(LocalTime.MIN);
|
||||
// 设置结束时间为 23:59:59 (也可以使用 LocalTime.MAX)
|
||||
LocalDateTime endOfDay = now.with(LocalTime.MAX);
|
||||
// 转换为 Date 赋值给 dto (如果你的字段类型是 Date)
|
||||
ZoneId zone = ZoneId.systemDefault();
|
||||
dto.setStartTime(Date.from(startOfDay.atZone(zone).toInstant()));
|
||||
dto.setEndTime(Date.from(endOfDay.atZone(zone).toInstant()));
|
||||
}
|
||||
List<ImageRecord> result = deviceIdentificationService.getImageData(dto);
|
||||
return result != null ? result : Collections.emptyList();
|
||||
} catch (Exception e) {
|
||||
log.error(e.toString(), e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,275 @@
|
|||
package com.bonus.web.service.data;
|
||||
|
||||
import com.bonus.common.domain.data.dto.ParamsDto;
|
||||
import com.bonus.common.domain.data.vo.ExportTask;
|
||||
import com.bonus.common.domain.data.vo.ImageRecord;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* @className:ExportService
|
||||
* @author:cwchen
|
||||
* @date:2025-12-26-10:21
|
||||
* @version:1.0
|
||||
* @description:识别图片导出-业务层
|
||||
*/
|
||||
@Slf4j
|
||||
@Service(value = "ExportService")
|
||||
public class ExportService {
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Resource(name = "DeviceIdentificationService")
|
||||
private DeviceIdentificationService deviceIdentificationService;
|
||||
|
||||
// Redis Key 前缀
|
||||
private static final String REDIS_KEY_PREFIX = "EXPORT:TASK:";
|
||||
// 任务在 Redis 中的过期时间
|
||||
private static final long EXPIRE_TIME = 24;
|
||||
|
||||
// 临时文件存放目录
|
||||
private static final String TEMP_DIR = System.getProperty("java.io.tmpdir") + "/export_tasks/";
|
||||
|
||||
/**
|
||||
* 创建任务并立即返回 TaskID
|
||||
*/
|
||||
public String createExportTask(ParamsDto dto) {
|
||||
String taskId = UUID.randomUUID().toString();
|
||||
|
||||
ExportTask task = new ExportTask();
|
||||
task.setTaskId(taskId);
|
||||
task.setProgress(0);
|
||||
task.setStatus("processing");
|
||||
|
||||
// 存入 Redis
|
||||
saveTaskToRedis(task);
|
||||
|
||||
// 异步执行
|
||||
processExportAsync(taskId, dto);
|
||||
|
||||
return taskId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 Redis 获取任务状态
|
||||
*/
|
||||
public ExportTask getTaskStatus(String taskId) {
|
||||
Object obj = redisTemplate.opsForValue().get(REDIS_KEY_PREFIX + taskId);
|
||||
if (obj instanceof ExportTask) {
|
||||
return (ExportTask) obj;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public File getExportFile(String taskId) {
|
||||
ExportTask task = getTaskStatus(taskId);
|
||||
// 注意:文件路径还是存在本地磁盘的。
|
||||
// 如果是多实例部署,这里需要改为上传到 OSS/S3 并返回云存储链接,
|
||||
// 或者使用 NFS/共享存储挂载该目录。
|
||||
// 下面代码假设仍在单机磁盘或挂载盘上。
|
||||
if (task != null && task.getFinalFilePath() != null) {
|
||||
return new File(task.getFinalFilePath());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 辅助方法:保存/更新任务到 Redis
|
||||
*/
|
||||
private void saveTaskToRedis(ExportTask task) {
|
||||
String key = REDIS_KEY_PREFIX + task.getTaskId();
|
||||
// 设置 Key 和 过期时间
|
||||
redisTemplate.opsForValue().set(key, task, EXPIRE_TIME, TimeUnit.HOURS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心异步处理逻辑 (业务逻辑大体不变,变的是状态更新方式)
|
||||
*/
|
||||
@Async("taskExecutor")
|
||||
public void processExportAsync(String taskId, ParamsDto dto) {
|
||||
// 先从 Redis 拿最新的状态
|
||||
ExportTask task = getTaskStatus(taskId);
|
||||
if (task == null) return; // 任务可能已过期或被删
|
||||
|
||||
File masterZipFile = null;
|
||||
|
||||
try {
|
||||
List<ImageRecord> allImages = mockDatabaseQuery(dto);
|
||||
|
||||
if (allImages.isEmpty()) {
|
||||
throw new RuntimeException("没有查询到数据");
|
||||
}
|
||||
|
||||
Map<String, List<ImageRecord>> groupedImages = new HashMap<>();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
for (ImageRecord img : allImages) {
|
||||
String dateStr = sdf.format(img.getCreateTime());
|
||||
groupedImages.computeIfAbsent(dateStr, k -> new ArrayList<>()).add(img);
|
||||
}
|
||||
|
||||
File tempDir = new File(TEMP_DIR);
|
||||
if (!tempDir.exists()) tempDir.mkdirs();
|
||||
|
||||
String masterFileName = "图像识别数据_" + System.currentTimeMillis() + ".zip";
|
||||
masterZipFile = new File(tempDir, masterFileName);
|
||||
|
||||
int totalDates = groupedImages.size();
|
||||
int processedCount = 0;
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(masterZipFile);
|
||||
ZipOutputStream masterZos = new ZipOutputStream(fos)) {
|
||||
|
||||
for (Map.Entry<String, List<ImageRecord>> entry : groupedImages.entrySet()) {
|
||||
String date = entry.getKey();
|
||||
List<ImageRecord> dailyImages = entry.getValue();
|
||||
|
||||
File dailyZipFile = createDailyZip(date, dailyImages);
|
||||
|
||||
ZipEntry zipEntry = new ZipEntry(date + ".zip");
|
||||
masterZos.putNextEntry(zipEntry);
|
||||
|
||||
try (FileInputStream dailyFis = new FileInputStream(dailyZipFile)) {
|
||||
IOUtils.copy(dailyFis, masterZos);
|
||||
}
|
||||
masterZos.closeEntry();
|
||||
dailyZipFile.delete();
|
||||
|
||||
processedCount++;
|
||||
// 更新 Redis 中的进度
|
||||
int currentProgress = (int) ((double) processedCount / totalDates * 90);
|
||||
updateProgressInRedis(taskId, currentProgress);
|
||||
}
|
||||
masterZos.finish();
|
||||
}
|
||||
|
||||
// 完成状态更新到 Redis
|
||||
task.setProgress(100);
|
||||
task.setStatus("completed");
|
||||
// 这里生成下载接口的地址
|
||||
task.setDownloadUrl("/device/imageRecognition/download?taskId=" + taskId);
|
||||
task.setFileName(masterFileName);
|
||||
task.setFinalFilePath(masterZipFile.getAbsolutePath());
|
||||
saveTaskToRedis(task);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
task.setStatus("failed");
|
||||
task.setMessage("导出失败: " + e.getMessage());
|
||||
saveTaskToRedis(task);
|
||||
|
||||
if (masterZipFile != null && masterZipFile.exists()) {
|
||||
masterZipFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateProgressInRedis(String taskId, int progress) {
|
||||
ExportTask task = getTaskStatus(taskId);
|
||||
if (task != null) {
|
||||
if (progress > 99) progress = 99;
|
||||
if (progress > task.getProgress()) {
|
||||
task.setProgress(progress);
|
||||
saveTaskToRedis(task); // 写回 Redis
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成某一天的压缩包 (已修复:支持真实图片下载)
|
||||
*/
|
||||
/**
|
||||
* 生成某一天的压缩包 (已修改:支持从服务器本地路径读取文件)
|
||||
*
|
||||
* @param dateStr 日期字符串
|
||||
* @param images 包含本地路径信息的图片记录列表
|
||||
* @return 压缩后的临时文件
|
||||
*/
|
||||
private File createDailyZip(String dateStr, List<ImageRecord> images) throws IOException {
|
||||
// 确保临时目录存在
|
||||
File tempDir = new File(TEMP_DIR);
|
||||
if (!tempDir.exists()) {
|
||||
tempDir.mkdirs();
|
||||
}
|
||||
|
||||
File dailyZip = new File(TEMP_DIR, "temp_" + dateStr + "_" + UUID.randomUUID() + ".zip");
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(dailyZip);
|
||||
ZipOutputStream dailyZos = new ZipOutputStream(fos)) {
|
||||
|
||||
for (ImageRecord img : images) {
|
||||
// 这里假设你的 ImageRecord.getUrl() 存储的是本地绝对路径,例如 /home/data/images/1.jpg
|
||||
// 如果字段名不同(比如叫 getFilePath),请自行替换
|
||||
String localPath = img.getUrl();
|
||||
|
||||
if (localPath == null || localPath.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
File imageFile = new File(localPath);
|
||||
|
||||
// 检查本地文件是否存在且可读
|
||||
if (!imageFile.exists() || !imageFile.isFile()) {
|
||||
log.error("本地文件不存在或不是有效文件: {}", localPath);
|
||||
// 写入错误说明到压缩包内
|
||||
writeErrorEntry(dailyZos, localPath, "文件不存在");
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// 1. 确定在压缩包内的文件名 (防止重名)
|
||||
String originalFileName = imageFile.getName();
|
||||
String zipEntryName = UUID.randomUUID().toString().substring(0, 8) + "_" + originalFileName;
|
||||
|
||||
// 2. 创建 Zip 条目
|
||||
ZipEntry entry = new ZipEntry(zipEntryName);
|
||||
dailyZos.putNextEntry(entry);
|
||||
|
||||
// 3. 将本地文件流拷贝到压缩输出流 (核心操作)
|
||||
try (FileInputStream fis = new FileInputStream(imageFile)) {
|
||||
// 使用已有的 IOUtils 进行高效流拷贝
|
||||
IOUtils.copy(fis, dailyZos);
|
||||
}
|
||||
|
||||
// 4. 关闭当前条目
|
||||
dailyZos.closeEntry();
|
||||
log.info("成功添加本地文件到压缩包: {}", localPath);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("处理本地文件失败: Path={}, Error={}", localPath, e.getMessage());
|
||||
writeErrorEntry(dailyZos, localPath, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return dailyZip;
|
||||
}
|
||||
|
||||
/**
|
||||
* 辅助方法:向压缩包写入错误信息文件
|
||||
*/
|
||||
private void writeErrorEntry(ZipOutputStream zos, String path, String reason) {
|
||||
try {
|
||||
ZipEntry errorEntry = new ZipEntry("error_" + UUID.randomUUID().toString().substring(0, 8) + ".txt");
|
||||
zos.putNextEntry(errorEntry);
|
||||
String errorMsg = "读取文件失败: " + path + "\n原因: " + reason;
|
||||
zos.write(errorMsg.getBytes());
|
||||
zos.closeEntry();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private List<ImageRecord> mockDatabaseQuery(ParamsDto dto) {
|
||||
return deviceIdentificationService.getImageData(dto);
|
||||
}
|
||||
}
|
||||
|
|
@ -70,4 +70,16 @@ public class AsyncConfig {
|
|||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
|
||||
// 配置线程池 (可选,但推荐,防止大量导出任务拖垮系统)
|
||||
@Bean("exportTaskExecutor")
|
||||
public Executor exportTaskExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(5); // 核心线程数
|
||||
executor.setMaxPoolSize(10); // 最大线程数
|
||||
executor.setQueueCapacity(20); // 队列大小
|
||||
executor.setThreadNamePrefix("Export-Executor-");
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
package com.bonus.common.domain.admin;
|
||||
|
||||
import java.util.Date;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 标签表
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class TbLabel {
|
||||
/**
|
||||
* 标签id
|
||||
*/
|
||||
private Long labelId;
|
||||
|
||||
/**
|
||||
* 标签组id
|
||||
*/
|
||||
private Long labelGroupId;
|
||||
|
||||
/**
|
||||
* 标签名称
|
||||
*/
|
||||
private String labelName;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private Long createUserId;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 修改人
|
||||
*/
|
||||
private Long updateUserId;
|
||||
|
||||
/**
|
||||
* 是否删除 0.未删除 1.删除
|
||||
*/
|
||||
private String delFlag;
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package com.bonus.common.domain.admin;
|
||||
|
||||
import java.util.Date;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 标签组管理表
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class TbLabelGroup {
|
||||
/**
|
||||
* 标签组id
|
||||
*/
|
||||
private Long labelGroupId;
|
||||
|
||||
/**
|
||||
* 标签组名称
|
||||
*/
|
||||
private String labelGroupName;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private Long createUserId;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 修改人
|
||||
*/
|
||||
private Long updateUserId;
|
||||
|
||||
/**
|
||||
* 是否删除 0.未删除 1.删除
|
||||
*/
|
||||
private String delFlag;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.bonus.common.domain.data.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @className:ExportTask
|
||||
* @author:cwchen
|
||||
* @date:2025-12-26-10:15
|
||||
* @version:1.0
|
||||
* @description:导出任务
|
||||
*/
|
||||
@Data
|
||||
public class ExportTask {
|
||||
private String taskId;
|
||||
private Integer progress; // 0 - 100
|
||||
private String status; // "processing", "completed", "failed"
|
||||
private String message; // 错误信息
|
||||
private String downloadUrl;
|
||||
private String fileName;
|
||||
private String finalFilePath; // 服务器本地存储路径
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.bonus.common.domain.data.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @className:ImageRecord
|
||||
* @author:cwchen
|
||||
* @date:2025-12-26-10:39
|
||||
* @version:1.0
|
||||
* @description: 下载图片实体类
|
||||
*/
|
||||
@Data
|
||||
public class ImageRecord {
|
||||
|
||||
private String url;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date createTime;
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.bonus.data.mapper;
|
|||
|
||||
import com.bonus.common.domain.data.dto.ParamsDto;
|
||||
import com.bonus.common.domain.data.vo.DeviceIdentificationDataVo;
|
||||
import com.bonus.common.domain.data.vo.ImageRecord;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -24,4 +25,13 @@ public interface DIDeviceIdentificationMapper {
|
|||
* @date 2025/12/23 16:42
|
||||
*/
|
||||
List<DeviceIdentificationDataVo> getDeviceIdentificationList(ParamsDto dto);
|
||||
|
||||
/**
|
||||
* 查询要下载的图片
|
||||
* @param dto
|
||||
* @return List<ImageRecord>
|
||||
* @author cwchen
|
||||
* @date 2025/12/26 10:41
|
||||
*/
|
||||
List<ImageRecord> getImageData(ParamsDto dto);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.bonus.data.service;
|
|||
import com.bonus.common.domain.data.dto.ParamsDto;
|
||||
import com.bonus.common.domain.data.vo.AlarmVo;
|
||||
import com.bonus.common.domain.data.vo.DeviceIdentificationDataVo;
|
||||
import com.bonus.common.domain.data.vo.ImageRecord;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -24,4 +25,13 @@ public interface DIDeviceIdentificationService {
|
|||
* @date 2025/12/23 16:38
|
||||
*/
|
||||
List<DeviceIdentificationDataVo> getDeviceIdentificationList(ParamsDto dto);
|
||||
|
||||
/**
|
||||
* 查询要下载的识别图片
|
||||
* @param dto
|
||||
* @return List<ImageRecord>
|
||||
* @author cwchen
|
||||
* @date 2025/12/26 10:38
|
||||
*/
|
||||
List<ImageRecord> getImageData(ParamsDto dto);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.bonus.data.service.impl;
|
|||
import com.bonus.common.domain.data.dto.ParamsDto;
|
||||
import com.bonus.common.domain.data.vo.AlarmVo;
|
||||
import com.bonus.common.domain.data.vo.DeviceIdentificationDataVo;
|
||||
import com.bonus.common.domain.data.vo.ImageRecord;
|
||||
import com.bonus.data.mapper.DIDeviceIdentificationMapper;
|
||||
import com.bonus.data.service.DIDeviceIdentificationService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -28,4 +29,9 @@ public class DDeviceIdentificationServiceImpl implements DIDeviceIdentificationS
|
|||
public List<DeviceIdentificationDataVo> getDeviceIdentificationList(ParamsDto dto) {
|
||||
return diDeviceIdentificationMapper.getDeviceIdentificationList(dto);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ImageRecord> getImageData(ParamsDto dto) {
|
||||
return diDeviceIdentificationMapper.getImageData(dto);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,31 @@
|
|||
LEFT JOIN sys_resource_file srf
|
||||
ON srf.business_id = tdid.identification_data_id
|
||||
AND srf.source_table = 'tb_device_identification_data'
|
||||
AND srf.file_type = '1'
|
||||
<where>
|
||||
<if test="startTime != null">
|
||||
AND tdid.identification_time >= #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND tdid.identification_time <= #{endTime}
|
||||
</if>
|
||||
<if test="carType != null and carType != ''">
|
||||
AND tdid.car_type = #{carType}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY tdid.identification_time DESC
|
||||
</select>
|
||||
|
||||
<!--查询要下载的图片-->
|
||||
<select id="getImageData" resultType="com.bonus.common.domain.data.vo.ImageRecord">
|
||||
SELECT
|
||||
tdid.identification_time AS createTime,
|
||||
srf.file_path AS url
|
||||
FROM tb_device_identification_data tdid
|
||||
LEFT JOIN sys_resource_file srf
|
||||
ON srf.business_id = tdid.identification_data_id
|
||||
AND srf.source_table = 'tb_device_identification_data'
|
||||
AND srf.file_type = '2'
|
||||
<where>
|
||||
<if test="startTime != null">
|
||||
AND tdid.identification_time >= #{startTime}
|
||||
|
|
|
|||
Loading…
Reference in New Issue