Merge branch 'master' into develop-QA

develop-QA
Tom Li 3 months ago
commit 10a27d93a7
  1. 28
      blade-ops/blade-job/src/main/java/org/springblade/job/processor/device/IotEquipmentProcessor.java
  2. 26
      blade-ops/blade-job/src/main/java/org/springblade/job/processor/device/IotFeiBaProcessor.java
  3. 26
      blade-ops/blade-job/src/main/java/org/springblade/job/processor/device/IotRecorderProcessor.java
  4. 42
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/device/feign/IotEquipmentTaskClient.java
  5. 2
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/device/pojo/entity/RecorderEntity.java
  6. 26
      blade-service/blade-desk/src/main/java/org/springblade/desk/device/controller/EquipmentController.java
  7. 26
      blade-service/blade-desk/src/main/java/org/springblade/desk/device/controller/FeiBaSetController.java
  8. 4
      blade-service/blade-desk/src/main/java/org/springblade/desk/device/controller/MeasurementRecordsController.java
  9. 26
      blade-service/blade-desk/src/main/java/org/springblade/desk/device/controller/RecorderController.java
  10. 39
      blade-service/blade-desk/src/main/java/org/springblade/desk/device/feign/IotEquipmentTaskClientImpl.java
  11. 2
      blade-service/blade-desk/src/main/java/org/springblade/desk/device/service/IMeasurementRecordsService.java
  12. 7
      blade-service/blade-desk/src/main/java/org/springblade/desk/device/service/IRecorderService.java
  13. 2
      blade-service/blade-desk/src/main/java/org/springblade/desk/device/service/impl/FeiBaSetServiceImpl.java
  14. 256
      blade-service/blade-desk/src/main/java/org/springblade/desk/device/service/impl/IMeasurementRecordsServiceImpl.java
  15. 409
      blade-service/blade-desk/src/main/java/org/springblade/desk/device/service/impl/RecorderServiceImpl.java
  16. 8
      blade-service/blade-desk/src/main/resources/application-dev.yml
  17. 5
      doc/sql/mes/increase-260120.sql

@ -0,0 +1,28 @@
package org.springblade.job.processor.device;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springblade.desk.device.feign.IotEquipmentTaskClient;
import org.springblade.desk.quality.feign.ILquidTankTaskClient;
import org.springframework.stereotype.Component;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext;
import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
import tech.powerjob.worker.log.OmsLogger;
/**
* 同步设备数据任务
*/
@Component
@Slf4j
public class IotEquipmentProcessor implements BasicProcessor {
@Resource
private IotEquipmentTaskClient iotEquipmentTaskClient;
@Override
public ProcessResult process(TaskContext context) throws Exception {
iotEquipmentTaskClient.synchronizeEquipmentTask();
return new ProcessResult(true);
}
}

@ -0,0 +1,26 @@
package org.springblade.job.processor.device;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springblade.desk.device.feign.IotEquipmentTaskClient;
import org.springframework.stereotype.Component;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext;
import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
/**
* 同步飞靶数据任务
*/
@Component
@Slf4j
public class IotFeiBaProcessor implements BasicProcessor {
@Resource
private IotEquipmentTaskClient iotEquipmentTaskClient;
@Override
public ProcessResult process(TaskContext context) throws Exception {
iotEquipmentTaskClient.synchronizeFeibaTask();
return new ProcessResult(true);
}
}

@ -0,0 +1,26 @@
package org.springblade.job.processor.device;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springblade.desk.device.feign.IotEquipmentTaskClient;
import org.springframework.stereotype.Component;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext;
import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
/**
* 同步记录仪记录数据任务
*/
@Component
@Slf4j
public class IotRecorderProcessor implements BasicProcessor {
@Resource
private IotEquipmentTaskClient iotEquipmentTaskClient;
@Override
public ProcessResult process(TaskContext context) throws Exception {
iotEquipmentTaskClient.synchronizeRecorderTask();
return new ProcessResult(true);
}
}

@ -0,0 +1,42 @@
package org.springblade.desk.device.feign;
import org.springblade.core.launch.constant.AppConstant;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(
value = AppConstant.APPLICATION_DESK_NAME
)
/**
* 同步IOT设备相关信息
*/
public interface IotEquipmentTaskClient {
String API_PREFIX = "/feign/device/iot-task";
String SYNCHRONIZE_EQUIPMENT_TASK = API_PREFIX + "/synchronize-equipment-task";
String SYNCHRONIZE_FEIBA_TASK = API_PREFIX + "/synchronize-feiba-task";
String SYNCHRONIZE_RECORDER_TASK = API_PREFIX + "/synchronize-recorder-task";
/**
* 同步设备数据
*/
@GetMapping(SYNCHRONIZE_EQUIPMENT_TASK)
void synchronizeEquipmentTask();
/**
* 同步飞靶数据
*/
@GetMapping(SYNCHRONIZE_FEIBA_TASK)
void synchronizeFeibaTask();
/**
* 同步记录仪记录数据
*/
@GetMapping(SYNCHRONIZE_RECORDER_TASK)
void synchronizeRecorderTask();
}

@ -31,7 +31,7 @@ public class RecorderEntity extends BaseEntity {
* 记录仪
*/
@Schema(description = "记录仪")
private BigDecimal recorder;
private String recorder;
/**
* 记录时间
*/

@ -186,18 +186,18 @@ public class EquipmentController extends BladeController {
ExcelUtil.export(response, "设备信息表数据" + DateUtil.time(), "设备信息表数据表", list, EquipmentExcel.class);
}
@PostConstruct // 项目启动后立即执行一次
public void init() {
regularlyUpdated();
}
/**
* 同步IOT设备数据
* TODO 以后需要交由PowerJob服务统一管理
*/
@Scheduled(cron = "0 0 0/23 * * ?") // 每23小时执行一次
public void regularlyUpdated() {
equipmentService.regularlyUpdated();
}
// @PostConstruct // 项目启动后立即执行一次
// public void init() {
// regularlyUpdated();
// }
//
// /**
// * 同步IOT设备数据
// * TODO 以后需要交由PowerJob服务统一管理
// */
// @Scheduled(cron = "0 0 0/23 * * ?") // 每23小时执行一次
// public void regularlyUpdated() {
// equipmentService.regularlyUpdated();
// }
}

@ -149,17 +149,17 @@ public class FeiBaSetController extends BladeController {
ExcelUtil.export(response, "飞靶设置数据" + DateUtil.time(), "飞靶设置数据表", list, FeiBaSetExcel.class);
}
@PostConstruct // 项目启动后立即执行一次
public void init() {
regularlyUpdated();
}
/**
* 同步IOT飞靶数据
* TODO 以后需要交由PowerJob服务统一管理
*/
@Scheduled(cron = "0 0 0/23 * * ?") // 每23小时执行一次
public void regularlyUpdated() {
feiBaSetService.regularlyUpdated();
}
// @PostConstruct // 项目启动后立即执行一次
// public void init() {
// regularlyUpdated();
// }
//
// /**
// * 同步IOT飞靶数据
// * TODO 以后需要交由PowerJob服务统一管理
// */
// @Scheduled(cron = "0 0 0/23 * * ?") // 每23小时执行一次
// public void regularlyUpdated() {
// feiBaSetService.regularlyUpdated();
// }
}

@ -45,8 +45,8 @@ public class MeasurementRecordsController extends BladeController {
@GetMapping("/page")
@ApiOperationSupport(order = 3)
@Operation(summary = "分页", description = "")
public R<IPage<JSONObject>> page(@RequestParam("cmType") Integer cmType, Query query) {
IPage<JSONObject> pages = iMeasurementRecordsService.selectMeasurementRecordsPage(Condition.getPage(query), cmType);
public R<IPage<MeasurementRecordsEntity>> page(@RequestParam("cmType") Integer cmType, Query query) {
IPage<MeasurementRecordsEntity> pages = iMeasurementRecordsService.selectMeasurementRecordsPage(Condition.getPage(query), cmType);
return R.data(pages);
}

@ -1,9 +1,13 @@
package org.springblade.desk.device.controller;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import jakarta.annotation.PostConstruct;
import lombok.AllArgsConstructor;
import jakarta.validation.Valid;
@ -16,6 +20,7 @@ import org.springblade.core.tool.utils.Func;
import org.springblade.desk.device.pojo.excel.RecorderExcel;
import org.springblade.desk.device.pojo.request.RecorderQuery;
import org.springblade.desk.device.pojo.vo.LoadRecorderVO;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
@ -64,9 +69,12 @@ public class RecorderController extends BladeController {
@GetMapping("/page")
@ApiOperationSupport(order = 3)
@Operation(summary = "分页", description = "传入recorder")
@Parameters({
@Parameter(name = "recorder", description = "记录仪编码", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
})
public R<IPage<RecorderVO>> page(RecorderVO recorder, Query query) {
IPage<RecorderVO> pages = recorderService.selectRecorderPage(Condition.getPage(query), recorder);
return R.data(pages);
IPage<RecorderEntity> pages = recorderService.selectRecorderPage(Condition.getPage(query), recorder);
return R.data(RecorderWrapper.build().pageVO(pages));
}
/**
@ -137,4 +145,18 @@ public class RecorderController extends BladeController {
ExcelUtil.export(response, "记录仪记录数据" + DateUtil.time(), "记录仪记录数据表", list, RecorderExcel.class);
}
// @PostConstruct // 项目启动后立即执行一次
// public void init() {
// regularlyUpdated();
// }
//
// /**
// * 同步记录仪数据
// * TODO 以后需要交由PowerJob服务统一管理
// */
// @Scheduled(cron = "0 0 0/23 * * ?") // 每23小时执行一次
// public void regularlyUpdated() {
// recorderService.regularlyUpdated();
// }
}

@ -0,0 +1,39 @@
package org.springblade.desk.device.feign;
import io.swagger.v3.oas.annotations.Hidden;
import jakarta.annotation.Resource;
import org.springblade.desk.device.service.IEquipmentService;
import org.springblade.desk.device.service.IFeiBaSetService;
import org.springblade.desk.device.service.IRecorderService;
import org.springblade.desk.quality.feign.IIotThicknessClient;
import org.springblade.desk.quality.service.IotThicknessService2;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Hidden
public class IotEquipmentTaskClientImpl implements IotEquipmentTaskClient {
@Resource
private IEquipmentService equipmentService;
@Resource
private IFeiBaSetService feiBaSetService;
@Resource
private IRecorderService recorderService;
@Override
public void synchronizeEquipmentTask() {
equipmentService.regularlyUpdated();
}
@Override
public void synchronizeFeibaTask() {
feiBaSetService.regularlyUpdated();
}
@Override
public void synchronizeRecorderTask() {
recorderService.regularlyUpdated();
}
}

@ -20,7 +20,7 @@ public interface IMeasurementRecordsService {
* @param cmType 查询参数
* @return IPage<JSONObject>
*/
IPage<JSONObject> selectMeasurementRecordsPage(IPage<JSONObject> page, Integer cmType);
IPage<MeasurementRecordsEntity> selectMeasurementRecordsPage(IPage<MeasurementRecordsEntity> page, Integer cmType);
// /**

@ -25,7 +25,7 @@ public interface IRecorderService extends BaseService<RecorderEntity> {
* @param recorder 查询参数
* @return IPage<RecorderVO>
*/
IPage<RecorderVO> selectRecorderPage(IPage<RecorderVO> page, RecorderVO recorder);
IPage<RecorderEntity> selectRecorderPage(IPage<RecorderEntity> page, RecorderVO recorder);
/**
@ -43,4 +43,9 @@ public interface IRecorderService extends BaseService<RecorderEntity> {
* @return
*/
LoadRecorderVO loadCalRecorder(RecorderQuery recorderQuery);
/**
* 同步记录仪数据
*/
void regularlyUpdated();
}

@ -104,7 +104,7 @@ public class FeiBaSetServiceImpl extends BaseServiceImpl<FeiBaSetMapper, FeiBaSe
JSONObject result = JSONObject.parseObject(responseBody);
log.debug("同步飞靶数据: {}", result.toJSONString());
if (result != null && result.getInteger("code").equals(0)) {
List<JSONObject> jsonList = JSONArray.parseArray(result.getJSONArray("result").toJSONString(), JSONObject.class);
List<JSONObject> jsonList = JSONArray.parseArray(result.getJSONArray("data").toJSONString(), JSONObject.class);
if (jsonList != null && jsonList.size() > 0) {
//接口返回飞靶code即为本系统code
Map<String, JSONObject> equCodeObjectMap = jsonList.stream().collect(Collectors.toMap(

@ -17,6 +17,7 @@ import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@ -32,7 +33,7 @@ public class IMeasurementRecordsServiceImpl implements IMeasurementRecordsServic
private String limsUrl;
@Override
public IPage<JSONObject> selectMeasurementRecordsPage(IPage<JSONObject> page, Integer cmType) {
public IPage<MeasurementRecordsEntity> selectMeasurementRecordsPage(IPage<MeasurementRecordsEntity> page, Integer cmType) {
// 构建请求体JSON
JSONObject requestBody = buildRequestBody(page, cmType);
@ -55,6 +56,7 @@ public class IMeasurementRecordsServiceImpl implements IMeasurementRecordsServic
} catch (Exception e) {
log.error("获取计量记录记录数据接口调用失败: {}", e.getMessage(), e);
List<MeasurementRecordsEntity> entityList1 = new ArrayList<>();
return page.setRecords(List.of()); // 返回空列表而不是null
}
}
@ -62,7 +64,7 @@ public class IMeasurementRecordsServiceImpl implements IMeasurementRecordsServic
/**
* 构建请求体
*/
private JSONObject buildRequestBody(IPage<JSONObject> page, Integer cmType) {
private JSONObject buildRequestBody(IPage<MeasurementRecordsEntity> page, Integer cmType) {
JSONObject requestBody = new JSONObject();
requestBody.put("currPage", page.getCurrent());
requestBody.put("pageSize", page.getSize());
@ -77,12 +79,224 @@ public class IMeasurementRecordsServiceImpl implements IMeasurementRecordsServic
/**
* 处理HTTP响应
*/
private IPage<JSONObject> processResponse(HttpResponse<String> response, IPage<JSONObject> page) {
private IPage<MeasurementRecordsEntity> processResponse(HttpResponse<String> response, IPage<MeasurementRecordsEntity> page) {
if (response.statusCode() != 200) {
log.error("HTTP请求失败,状态码: {}", response.statusCode());
throw new RuntimeException("HTTP请求失败,状态码: " + response.statusCode());
}
/*String responseBody = "{\n" +
" \"success\": true,\n" +
" \"rows\": [\n" +
" {\n" +
" \"alarmState\": 1,\n" +
" \"assetsCode\": \"LS321295\",\n" +
" \"belong\": \"在用\",\n" +
" \"createdBy\": \"1397884728111006697\",\n" +
" \"createdByName\": \"超级管理员\",\n" +
" \"describe\": \"\",\n" +
" \"deviceName\": \"钢直尺\",\n" +
" \"deviceNameNo\": \"钢直尺 null\",\n" +
" \"deviceSource\": \"市计量所\",\n" +
" \"deviceWhere\": \"\",\n" +
" \"guaranteePeriod\": 0,\n" +
" \"id\": \"20542\",\n" +
" \"isOverDue\": \"4\",\n" +
" \"labId\": \"2\",\n" +
" \"labelNo\": \"长度\",\n" +
" \"model\": \"0-50cm\",\n" +
" \"needDoPage\": false,\n" +
" \"objectCheckState\": 0,\n" +
" \"objectState\": 0,\n" +
" \"serialNo\": \"\",\n" +
" \"startPage\": 1,\n" +
" \"state\": 1,\n" +
" \"str1\": \"1\",\n" +
" \"str10\": \"一次性检定合格\",\n" +
" \"str2\": \"钢直尺\",\n" +
" \"str20\": \"长度外检\",\n" +
" \"str5\": \"\",\n" +
" \"str6\": \"\",\n" +
" \"str7\": \"\",\n" +
" \"str8\": \"JJG1钢直尺检定规程\",\n" +
" \"str9\": \"\",\n" +
" \"unit\": \"C\",\n" +
" \"verificationCycle\": 1,\n" +
" \"verifyState\": 0,\n" +
" \"whenAccept\": 1464105600000,\n" +
" \"workGuideNo\": \"热表分厂\",\n" +
" \"total\": \"3809\",\n" +
" \"isOverStr\": \"正常\"\n" +
" },\n" +
" {\n" +
" \"alarmState\": 1,\n" +
" \"assetsCode\": \"LS321294\",\n" +
" \"belong\": \"在用\",\n" +
" \"createdBy\": \"1397884728111006697\",\n" +
" \"createdByName\": \"超级管理员\",\n" +
" \"describe\": \"\",\n" +
" \"deviceName\": \"钢直尺\",\n" +
" \"deviceNameNo\": \"钢直尺 null\",\n" +
" \"deviceSource\": \"市计量所\",\n" +
" \"deviceWhere\": \"\",\n" +
" \"guaranteePeriod\": 0,\n" +
" \"id\": \"20606\",\n" +
" \"isOverDue\": \"4\",\n" +
" \"labId\": \"2\",\n" +
" \"labelNo\": \"长度\",\n" +
" \"model\": \"0-30cm\",\n" +
" \"needDoPage\": false,\n" +
" \"objectCheckState\": 0,\n" +
" \"objectState\": 0,\n" +
" \"serialNo\": \"\",\n" +
" \"startPage\": 1,\n" +
" \"state\": 1,\n" +
" \"str1\": \"1\",\n" +
" \"str10\": \"一次性检定合格\",\n" +
" \"str2\": \"钢直尺\",\n" +
" \"str20\": \"长度外检\",\n" +
" \"str5\": \"\",\n" +
" \"str6\": \"\",\n" +
" \"str7\": \"\",\n" +
" \"str8\": \"JJG1钢直尺检定规程\",\n" +
" \"str9\": \"\",\n" +
" \"unit\": \"C\",\n" +
" \"verificationCycle\": 1,\n" +
" \"verifyState\": 0,\n" +
" \"whenAccept\": 1464105600000,\n" +
" \"workGuideNo\": \"热表分厂\",\n" +
" \"total\": \"3809\",\n" +
" \"isOverStr\": \"正常\"\n" +
" },\n" +
" {\n" +
" \"alarmState\": 1,\n" +
" \"assetsCode\": \"LS321296\",\n" +
" \"belong\": \"在用\",\n" +
" \"createdBy\": \"1397884728111006697\",\n" +
" \"createdByName\": \"超级管理员\",\n" +
" \"describe\": \"\",\n" +
" \"deviceName\": \"钢直尺\",\n" +
" \"deviceNameNo\": \"钢直尺 null\",\n" +
" \"deviceSource\": \"市计量所\",\n" +
" \"deviceWhere\": \"\",\n" +
" \"guaranteePeriod\": 0,\n" +
" \"id\": \"22798\",\n" +
" \"isOverDue\": \"4\",\n" +
" \"labId\": \"2\",\n" +
" \"labelNo\": \"长度\",\n" +
" \"model\": \"0-50cm\",\n" +
" \"needDoPage\": false,\n" +
" \"objectCheckState\": 0,\n" +
" \"objectState\": 0,\n" +
" \"serialNo\": \"\",\n" +
" \"startPage\": 1,\n" +
" \"state\": 1,\n" +
" \"str1\": \"1\",\n" +
" \"str10\": \"一次性检定合格\",\n" +
" \"str2\": \"钢直尺\",\n" +
" \"str20\": \"长度外检\",\n" +
" \"str5\": \"\",\n" +
" \"str6\": \"\",\n" +
" \"str7\": \"\",\n" +
" \"str8\": \"\",\n" +
" \"str9\": \"\",\n" +
" \"unit\": \"C\",\n" +
" \"verificationCycle\": 1,\n" +
" \"verifyState\": 0,\n" +
" \"whenAccept\": 1464105600000,\n" +
" \"workGuideNo\": \"热表分厂\",\n" +
" \"total\": \"3809\",\n" +
" \"isOverStr\": \"正常\"\n" +
" },\n" +
" {\n" +
" \"alarmState\": 1,\n" +
" \"assetsCode\": \"LS321296\",\n" +
" \"belong\": \"在用\",\n" +
" \"createdBy\": \"1397884728111006697\",\n" +
" \"createdByName\": \"超级管理员\",\n" +
" \"describe\": \"\",\n" +
" \"deviceName\": \"钢直尺\",\n" +
" \"deviceNameNo\": \"钢直尺 null\",\n" +
" \"deviceSource\": \"市计量所\",\n" +
" \"deviceWhere\": \"\",\n" +
" \"guaranteePeriod\": 0,\n" +
" \"id\": \"23798\",\n" +
" \"isOverDue\": \"4\",\n" +
" \"labId\": \"2\",\n" +
" \"labelNo\": \"长度\",\n" +
" \"model\": \"0-50cm\",\n" +
" \"needDoPage\": false,\n" +
" \"objectCheckState\": 0,\n" +
" \"objectState\": 0,\n" +
" \"serialNo\": \"\",\n" +
" \"startPage\": 1,\n" +
" \"state\": 1,\n" +
" \"str1\": \"1\",\n" +
" \"str10\": \"一次性检定合格\",\n" +
" \"str2\": \"钢直尺\",\n" +
" \"str20\": \"长度外检\",\n" +
" \"str5\": \"\",\n" +
" \"str6\": \"\",\n" +
" \"str7\": \"\",\n" +
" \"str8\": \"\",\n" +
" \"str9\": \"\",\n" +
" \"unit\": \"C\",\n" +
" \"verificationCycle\": 1,\n" +
" \"verifyState\": 0,\n" +
" \"whenAccept\": 1464105600000,\n" +
" \"workGuideNo\": \"热表分厂\",\n" +
" \"total\": \"3809\",\n" +
" \"isOverStr\": \"正常\"\n" +
" },{\n" +
" \"alarmState\": 1,\n" +
" \"assetsCode\": \"YQ202512057\",\n" +
" \"belong\": \"在用\",\n" +
" \"createdBy\": \"1413079875727655913\",\n" +
" \"createdByName\": \"张曼\",\n" +
" \"date1\": 1795708800000,\n" +
" \"describe\": \"±5%\",\n" +
" \"deviceName\": \"磁导率测试仪\",\n" +
" \"deviceNameNo\": \"磁导率测试仪 null\",\n" +
" \"deviceSource\": \"FOERSTER\",\n" +
" \"deviceWhere\": \"FOERSTER\",\n" +
" \"guaranteePeriod\": 12,\n" +
" \"id\": \"1527021013731116009\",\n" +
" \"isOverDue\": \"0\",\n" +
" \"labId\": \"2\",\n" +
" \"labelNo\": \"电学\",\n" +
" \"model\": \"MAGNETOSCOP1.070\",\n" +
" \"modifiedBy\": \"1413079875727655913\",\n" +
" \"modifiedByName\": \"张曼\",\n" +
" \"needDoPage\": false,\n" +
" \"objectCheckState\": 0,\n" +
" \"objectState\": 0,\n" +
" \"serialNo\": \"17175\",\n" +
" \"startPage\": 1,\n" +
" \"state\": 1,\n" +
" \"str1\": \"1\",\n" +
" \"str12\": \"1413079875727655913,1413079965921969129\",\n" +
" \"str13\": \"张曼,高佳璇\",\n" +
" \"str2\": \"磁导率测试仪\",\n" +
" \"str20\": \"电学\",\n" +
" \"str5\": \"1.068/1.069\",\n" +
" \"str6\": \"\",\n" +
" \"str8\": \"厂家检测报告\",\n" +
" \"unit\": \"B\",\n" +
" \"verificationCycle\": 1,\n" +
" \"verifyState\": 0,\n" +
" \"whenAccept\": 1764259200000,\n" +
" \"whenCreated\": 1768448919000,\n" +
" \"whenModified\": 1768448919000,\n" +
" \"whenUse\": 1764259200000,\n" +
" \"workGuideNo\": \"热表分厂\",\n" +
" \"total\": \"3809\",\n" +
" \"isOverStr\": \"正常\"\n" +
" }\n" +
" ],\n" +
" \"total\": \"3809\",\n" +
" \"recordsTotal\": \"3809\",\n" +
" \"recordsFiltered\": \"3809\"\n" +
"}";*/
String responseBody = response.body();
if (responseBody == null || responseBody.trim().isEmpty()) {
log.error("响应体为空");
@ -92,11 +306,43 @@ public class IMeasurementRecordsServiceImpl implements IMeasurementRecordsServic
try {
JSONObject result = JSONObject.parseObject(responseBody);
if (result != null && result.getBoolean("success")) {
JSONObject data = result.getJSONObject("data");
JSONArray data = result.getJSONArray("rows");
if (data != null) {
List<JSONObject> records = JSONArray.parseArray(data.toJSONString(), JSONObject.class);
log.info("成功获取{}条计量记录记录", records != null ? records.size() : 0);
return page.setRecords(records != null ? records : List.of());
MeasurementRecordsEntity measurementRecordsEntity;
List<MeasurementRecordsEntity> list = new ArrayList<>();
for (JSONObject jsonObj : records) {
measurementRecordsEntity = new MeasurementRecordsEntity();
measurementRecordsEntity.setMcName(jsonObj.getString("deviceName"));
measurementRecordsEntity.setNorms(jsonObj.getString("model"));
measurementRecordsEntity.setMcClass(jsonObj.getString("unit"));
measurementRecordsEntity.setLabelNo(jsonObj.getString("labelNo"));
measurementRecordsEntity.setStr2(jsonObj.getString("str2"));
measurementRecordsEntity.setMcCode(jsonObj.getString("assetsCode"));
measurementRecordsEntity.setUseUnit(jsonObj.getString("workGuideNo"));
measurementRecordsEntity.setAccuracy(jsonObj.getString("describe"));
measurementRecordsEntity.setOemCode(jsonObj.getString("serialNo"));
measurementRecordsEntity.setMcOem(jsonObj.getString("deviceWhere"));
measurementRecordsEntity.setEnableDate(jsonObj.getDate("whenUse"));
measurementRecordsEntity.setWhenDccept(jsonObj.getString("whenDccept"));
measurementRecordsEntity.setMcType(jsonObj.getString("str5"));
measurementRecordsEntity.setTestCycle(jsonObj.getInteger("guaranteePeriod"));
measurementRecordsEntity.setDueDate(jsonObj.getDate("date1"));
measurementRecordsEntity.setDate2(jsonObj.getDate("date2"));
measurementRecordsEntity.setBelong(jsonObj.getString("belong"));
measurementRecordsEntity.setWhenBuy(jsonObj.getDate("whenBuy"));
measurementRecordsEntity.setTestDept(jsonObj.getString("deviceSource"));
measurementRecordsEntity.setTestMethod(jsonObj.getString("str8"));
measurementRecordsEntity.setStr9(jsonObj.getString("str9"));
measurementRecordsEntity.setStr10(jsonObj.getString("str10"));
measurementRecordsEntity.setAssetsNo(jsonObj.getString("assetsNo"));
measurementRecordsEntity.setStr6(jsonObj.getString("str6"));
measurementRecordsEntity.setPurposeClass(jsonObj.getString("str7"));
measurementRecordsEntity.setIsOverStr(jsonObj.getString("isOverStr"));
list.add(measurementRecordsEntity);
}
return page.setRecords(list != null ? list : List.of());
}
} else {
String errorMsg = result != null ? result.getString("message") : "未知错误";

@ -2,9 +2,14 @@ package org.springblade.desk.device.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import jakarta.annotation.Resource;
import org.springblade.desk.device.mapper.EquipmentMapper;
import org.springblade.desk.device.pojo.entity.EquipmentEntity;
import org.springblade.desk.device.pojo.entity.RecorderCompareEntity;
import org.springblade.desk.device.pojo.entity.RecorderEntity;
import org.springblade.desk.device.pojo.excel.RecorderExcel;
@ -15,12 +20,20 @@ import org.springblade.desk.device.pojo.vo.RecorderVO;
import org.springblade.desk.device.mapper.RecorderMapper;
import org.springblade.desk.device.service.IRecorderCompareService;
import org.springblade.desk.device.service.IRecorderService;
import org.springblade.desk.jobtransfer.pojo.entity.PostHandleEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseServiceImpl;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
@ -30,15 +43,40 @@ import java.util.stream.Collectors;
* @author qyl
* @since 2026-01-06
*/
@Slf4j
@Service
public class RecorderServiceImpl extends BaseServiceImpl<RecorderMapper, RecorderEntity> implements IRecorderService {
@Autowired
private IRecorderCompareService iRecorderCompareService;
@Resource
private EquipmentMapper equipmentMapper;
@Value("${request.iotNew.url}")
private String iotNewUrl;
@Value("${request.iot.orgId}")
private String orgId;
@Value("${request.iot.systemId}")
private String systemId;
// 使用JDK 17内置的HttpClient(线程安全,可复用)
private final HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(30))
.version(HttpClient.Version.HTTP_2)
.build();
@Override
public IPage<RecorderVO> selectRecorderPage(IPage<RecorderVO> page, RecorderVO recorder) {
return page.setRecords(baseMapper.selectRecorderPage(page, recorder));
public IPage<RecorderEntity> selectRecorderPage(IPage<RecorderEntity> page, RecorderVO recorder) {
// 1. 创建条件构造器
LambdaQueryWrapper<RecorderEntity> wrapper = Wrappers.<RecorderEntity>lambdaQuery();
// 2. 动态添加条件(核心!)
// 根据实体对象 entity 中字段是否为空,来动态拼接WHERE条件
wrapper.eq(Objects.nonNull(recorder.getRecorder()), RecorderEntity::getRecorder, recorder.getRecorder());
return baseMapper.selectPage(page, wrapper);
}
@ -137,4 +175,371 @@ public class RecorderServiceImpl extends BaseServiceImpl<RecorderMapper, Recorde
return loadRecorderVO;
}
/**
* 定期更新记录仪数据的方法
* 该方法会查询所有非产线设备并同步其记录仪数据到系统数据库
* 同步时间范围根据设备最后记录时间动态计算确保数据连续性
*/
@Override
public void regularlyUpdated() {
// 查询全部非产线设备
List<EquipmentEntity> equipmentEntities = getNonProductionEquipment();
if (equipmentEntities.isEmpty()) {
log.error("同步记录仪数据失败,当前系统无非产线设备");
return;
}
// 批量处理设备数据,使用并行流提高处理效率(根据设备数量决定是否启用)
equipmentEntities.stream()
.filter(equipment -> processEquipmentData(equipment))
.collect(Collectors.toList());
}
/**
* 获取非产线设备列表
*/
private List<EquipmentEntity> getNonProductionEquipment() {
LambdaQueryWrapper<EquipmentEntity> equiWrapper = new LambdaQueryWrapper<>();
equiWrapper.ne(EquipmentEntity::getCategorys, "产线设备");
return equipmentMapper.selectList(equiWrapper);
}
/**
* 处理单个设备的数据同步
*
* @return 处理成功返回true失败返回false
*/
private boolean processEquipmentData(EquipmentEntity equipmentEntity) {
try {
// 获取设备对应的记录仪信息
RecorderEntity recorderEntity = getRecorderEntity(equipmentEntity.getDeviceCode());
if (recorderEntity == null) {
log.warn("设备 {} 无对应的记录仪信息,跳过处理", equipmentEntity.getDeviceCode());
return false;
}
// 检查记录时间有效性(跳过未来时间的异常记录)
if (isFutureRecord(recorderEntity.getRecordDate())) {
log.debug("记录仪 {} 记录时间为未来时间,跳过处理", equipmentEntity.getDeviceCode());
return false;
}
// 计算时间范围
TimeRange timeRange = calculateTimeRange(recorderEntity);
if (timeRange == null) {
return false;
}
// 调用同步接口获取记录仪数据
JSONArray dataArray = doPost(equipmentEntity.getDeviceCode(),
timeRange.getStartTime(), timeRange.getStopTime());
// 处理同步结果
return processSyncResult(dataArray, equipmentEntity, recorderEntity);
} catch (Exception e) {
log.error("处理记录仪 {} 数据时发生异常", equipmentEntity.getDeviceCode(), e);
return false;
}
}
/**
* 获取记录仪实体
*/
private RecorderEntity getRecorderEntity(String deviceCode) {
return this.getOne(new LambdaQueryWrapper<RecorderEntity>()
.eq(RecorderEntity::getRecorder, deviceCode));
}
/**
* 检查记录时间是否为未来时间
*/
private boolean isFutureRecord(Date recordDate) {
return recordDate.getTime() > System.currentTimeMillis();
}
/**
* 计算数据同步的时间范围
*/
private TimeRange calculateTimeRange(RecorderEntity recorderEntity) {
// 计算基准时间点:当前时间前推8分钟(用于时间比较)
long baselineTime = OffsetDateTime.now().minusMinutes(8).toInstant().toEpochMilli();
Instant recordInstant = recorderEntity.getRecordDate().toInstant();
// 设置默认查询时间范围:当前时间前推6分钟到前推5分钟
String startTime = OffsetDateTime.now().minusMinutes(6)
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
String stopTime = OffsetDateTime.now().minusMinutes(5)
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
// 判断记录时间是否在基准时间之前或相等
if (recordInstant.isBefore(Instant.ofEpochMilli(baselineTime)) ||
recordInstant.equals(Instant.ofEpochMilli(baselineTime))) {
// 设置基于记录时间的开始时间
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
startTime = recordInstant.atZone(ZoneId.systemDefault()).format(formatter);
// 如果记录时间超过当前时间10分钟,设置基于记录时间的结束时间
if (recordInstant.plusSeconds(60 * 10).isBefore(Instant.ofEpochMilli(baselineTime))) {
stopTime = recordInstant.plusSeconds(120).atZone(ZoneId.systemDefault()).format(formatter);
}
}
return new TimeRange(startTime, stopTime);
}
/**
* 处理同步返回的数据
*/
private boolean processSyncResult(JSONArray dataArray, EquipmentEntity equipment,
RecorderEntity existingRecorder) {
if (dataArray != null && !dataArray.isEmpty()) {
return processSuccessfulSync(dataArray, equipment);
} else {
return createFallbackRecord(equipment, existingRecorder);
}
}
/**
* 处理有数据的同步结果
*/
private boolean processSuccessfulSync(JSONArray dataArray, EquipmentEntity equipment) {
// 获取最新的一条记录
JSONObject lastRecord = dataArray.getJSONObject(dataArray.size() - 1);
String deviceId = lastRecord.getString("deivceId");
String value = lastRecord.getString("value");
Date recordTime = lastRecord.getDate("timestamp");
// 检查记录是否已存在(去重判断)
if (isDuplicateRecord(equipment.getDeviceCode(), recordTime)) {
// log.debug("设备 {} 记录已存在,跳过保存", equipment.getDeviceCode());
return true;
}
// 创建新记录并保存
return saveNewRecord(deviceId, value, recordTime);
}
/**
* 检查重复记录
*/
private boolean isDuplicateRecord(String deviceCode, Date recordTime) {
return this.exists(new LambdaQueryWrapper<RecorderEntity>()
.eq(RecorderEntity::getRecorder, deviceCode)
.eq(RecorderEntity::getRecordDate, recordTime));
}
/**
* 保存新记录
*/
private boolean saveNewRecord(String deviceId, String value, Date recordTime) {
try {
RecorderEntity recorder = new RecorderEntity();
recorder.setRecorder(deviceId);
recorder.setRecordDate(recordTime);
recorder.setMemo(value);
return this.save(recorder);
} catch (Exception e) {
log.error("保存记录仪 {} 记录失败", deviceId, e);
return false;
}
}
/**
* 创建无数据时的回退记录
*/
private boolean createFallbackRecord(EquipmentEntity equipment, RecorderEntity existingRecorder) {
try {
RecorderEntity recorder = new RecorderEntity();
recorder.setRecorder(equipment.getDeviceCode());
recorder.setMemo("");
// 设置记录时间:有历史记录则基于最后记录时间,否则基于当前时间
Date newRecordDate = calculateFallbackDate(existingRecorder);
recorder.setRecordDate(newRecordDate);
return this.save(recorder);
} catch (Exception e) {
log.error("创建回退记录失败,记录仪:{}", equipment.getDeviceCode(), e);
return false;
}
}
/**
* 计算回退记录的日期
*/
private Date calculateFallbackDate(RecorderEntity existingRecorder) {
LocalDateTime baseTime;
if (existingRecorder != null && existingRecorder.getId() != null) {
// 有历史记录:在最后记录时间基础上增加2分钟
baseTime = existingRecorder.getRecordDate().toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime()
.plusMinutes(2);
} else {
// 无历史记录:当前时间前推5分钟
baseTime = LocalDateTime.now().minusMinutes(5);
}
return Date.from(baseTime.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* 时间范围封装类
*/
private static class TimeRange {
private final String startTime;
private final String stopTime;
public TimeRange(String startTime, String stopTime) {
this.startTime = startTime;
this.stopTime = stopTime;
}
public String getStartTime() {
return startTime;
}
public String getStopTime() {
return stopTime;
}
}
/*public void regularlyUpdated() {
//查询全部非产线设备
LambdaQueryWrapper<EquipmentEntity> equiWrapper = new LambdaQueryWrapper<>();
equiWrapper.ne(EquipmentEntity::getCategorys,"产线设备");
List<EquipmentEntity> equipmentEntities = equipmentMapper.selectList(equiWrapper);
if(null == equipmentEntities || equipmentEntities.size() < 1){
log.error("同步记录仪数据失败,当前系统无非产线设备");
return;
}
String startTime;
String stopTime;
for (EquipmentEntity equipmentEntity : equipmentEntities) {
// 获取当前时间并减去8分钟,然后转换为时间戳
long time = OffsetDateTime.now().minusMinutes(8).toInstant().toEpochMilli();
// 获取当前时间并减去6分钟,然后格式化为字符串
startTime = OffsetDateTime.now().minusMinutes(6)
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); // 使用ISO格式,包含时区信息
// 获取当前时间并减去5分钟,然后格式化为字符串
stopTime = OffsetDateTime.now().minusMinutes(5)
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
RecorderEntity recorderEntity = this.getOne(new LambdaQueryWrapper<RecorderEntity>().eq(RecorderEntity::getRecorder, equipmentEntity.getDeviceCode()));
if (recorderEntity == null) return;
Date recordDate = recorderEntity.getRecordDate();
if (recordDate.getTime() > new Date().getTime()) continue;
if (recorderEntity != null && recorderEntity.getId() != null) {
if (recordDate != null) {
Instant recordInstant = recordDate.toInstant();
if (recordInstant.isBefore(Instant.ofEpochMilli(time)) || recordInstant.equals(Instant.ofEpochMilli(time))) {
// 格式化开始时间
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 根据需求调整格式
startTime = recordInstant.atZone(ZoneId.systemDefault()).format(formatter);
// 判断是否超过当前时间10分钟
if (recordInstant.plusSeconds(60 * 10).isBefore(Instant.ofEpochMilli(time))) {
// 在 recordDate 基础上加2分钟作为结束时间
stopTime = recordInstant.plusSeconds(120).atZone(ZoneId.systemDefault()).format(formatter);
}
}
}
}
//同步接口调用
JSONArray array = doPost(equipmentEntity.getDeviceCode(), startTime, stopTime);
//处理返回数据
RecorderEntity recorder = null;
if (array != null && array.size() > 0) {
JSONObject obj = null;
String deivceId = "", value = "";
Date recTime = null;
obj = array.getJSONObject(array.size() - 1);
deivceId = obj.getString("deivceId");
value = obj.getString("value");
recTime = obj.getDate("timestamp");
RecorderEntity getOneRecorder = this.getOne(new LambdaQueryWrapper<RecorderEntity>().eq(RecorderEntity::getRecorder, equipmentEntity.getDeviceCode())
.eq(RecorderEntity::getRecordDate,recTime));
if (getOneRecorder != null && getOneRecorder.getId() != null) continue;
//去重 增加唯一标识
recorder = new RecorderEntity();
recorder.setRecorder(deivceId);
recorder.setRecordDate(recTime);
recorder.setMemo(value);
this.save(recorder);
} else {
recorder = new RecorderEntity();
recorder.setRecorder(equipmentEntity.getDeviceCode());
if (recorderEntity != null && recorderEntity.getId() != null) {
// 将 Date 转换为 LocalDateTime 进行操作
LocalDateTime newRecordDate = recordDate.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime()
.plusMinutes(2); // 增加2分钟
recorder.setRecordDate(Date.from(newRecordDate.atZone(ZoneId.systemDefault()).toInstant()));
} else {
// 当前时间减去5分钟
LocalDateTime newRecordDate = LocalDateTime.now().minusMinutes(5);
recorder.setRecordDate(Date.from(newRecordDate.atZone(ZoneId.systemDefault()).toInstant()));
}
recorder.setMemo("");
this.save(recorder);
}
}
}*/
/**
* 从IOT同步数据
*
* @param deviceCode
* @param startTime
* @param stopTime
* @return
*/
private JSONArray doPost(String deviceCode, String startTime, String stopTime) {
log.debug("开始同步记录仪数据");
JSONArray retuArray = null;
// 构建请求体JSON
JSONObject requestBody = buildRequestBody(deviceCode, startTime, stopTime);
// 创建HTTP请求
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(iotNewUrl + "/deviceForZhgd/deviceDataHistory"))
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody.toJSONString()))
.timeout(Duration.ofSeconds(60))
.build();
try {
// 发送同步请求
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// 处理响应
String responseBody = response.body();
JSONObject result = JSONObject.parseObject(responseBody);
log.debug("同步记录仪数据: {}", result.toJSONString());
if (result != null && result.getInteger("code").equals(0)) {
retuArray = result.getJSONArray("result");
}
} catch (Exception e) {
log.error("同步记录仪数据接口调用失败: {}", e.getMessage(), e);
}
return retuArray;
}
/**
* 构建请求体
*/
private JSONObject buildRequestBody(String deviceCode, String startTime, String stopTime) {
JSONObject requestBody = new JSONObject();
requestBody.put("orgId", orgId);
requestBody.put("systemId", systemId);
requestBody.put("startTime", startTime);
requestBody.put("deviceId", deviceCode);
requestBody.put("endTime", stopTime);
requestBody.put("category", "");
log.debug("同步记录仪数据请求参数: {}", requestBody.toJSONString());
return requestBody;
}
}

@ -45,17 +45,17 @@ request:
orgId: 16
#业务系统id
systemId: 344123
url: http://192.168.169.32:80720
url: "http://192.168.169.32:80720"
iotNew:
url: http://192.168.169.23:8072
url: "http://192.168.169.23:8072"
#量具使用记录
measuringTool:
url: "192.168.191.11:8888"
url: "http://192.168.191.11:8888"
#计量记录
lims:
url: "http://192.168.169.50:30000"
#飞拔信息接口请求地址
equ:
url: http://192.168.169.69
url: "http://192.168.169.69"
logging:
config: classpath:logback.xml

@ -41,3 +41,8 @@ ALTER TABLE MES_ASSAY_CONTENT_DETAIL ADD ADD_VAL NUMBER(20,10) NULL;
COMMENT ON COLUMN MES_ASSAY_CONTENT_DETAIL.ADD_VAL IS '添加量值';
ALTER TABLE MES_RECORDER
MODIFY (RECORDER NVARCHAR2(255));
ALTER TABLE MES_RECORDER
MODIFY (MEMO CLOB);
Loading…
Cancel
Save