20260531:平台对接第2版实现
This commit is contained in:
parent
6fa88356fa
commit
db44cda413
@ -97,6 +97,12 @@ public class DeviceTask {
|
|||||||
return builder(FastBeeConstant.TASK.TRIGGER_POWER_ON_TASK_ASYNC);
|
return builder(FastBeeConstant.TASK.TRIGGER_POWER_ON_TASK_ASYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*第三方平台推送*/
|
||||||
|
@Bean(FastBeeConstant.TASK.PUSH_TO_THIRD_PLATFORM_ASYNC)
|
||||||
|
public Executor pushToThirdPlatformExecutor() {
|
||||||
|
return builder(FastBeeConstant.TASK.PUSH_TO_THIRD_PLATFORM_ASYNC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*组装线程池*/
|
/*组装线程池*/
|
||||||
private ThreadPoolTaskExecutor builder(String threadNamePrefix) {
|
private ThreadPoolTaskExecutor builder(String threadNamePrefix) {
|
||||||
|
|||||||
@ -99,6 +99,9 @@ public interface FastBeeConstant {
|
|||||||
|
|
||||||
// 设备上电即触发异步任务 TriggerPowerOnTaskAsync
|
// 设备上电即触发异步任务 TriggerPowerOnTaskAsync
|
||||||
String TRIGGER_POWER_ON_TASK_ASYNC = "triggerPowerOnTaskAsync";
|
String TRIGGER_POWER_ON_TASK_ASYNC = "triggerPowerOnTaskAsync";
|
||||||
|
|
||||||
|
// 设备上报数据-推送到第三方平台
|
||||||
|
String PUSH_TO_THIRD_PLATFORM_ASYNC = "pushToThirdPlatformAsync";
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MQTT {
|
interface MQTT {
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import com.fastbee.common.utils.gateway.mq.TopicsUtils;
|
|||||||
import com.fastbee.iot.cache.SceneModelTagCache;
|
import com.fastbee.iot.cache.SceneModelTagCache;
|
||||||
import com.fastbee.iot.data.executor.ConditionTriggerTaskExecutor;
|
import com.fastbee.iot.data.executor.ConditionTriggerTaskExecutor;
|
||||||
import com.fastbee.iot.data.service.IDataHandler;
|
import com.fastbee.iot.data.service.IDataHandler;
|
||||||
|
import com.fastbee.iot.platform.trigger.DeviceReportTrigger;
|
||||||
import com.fastbee.iot.data.service.IMqttMessagePublish;
|
import com.fastbee.iot.data.service.IMqttMessagePublish;
|
||||||
import com.fastbee.iot.data.service.IRuleEngine;
|
import com.fastbee.iot.data.service.IRuleEngine;
|
||||||
import com.fastbee.iot.domain.*;
|
import com.fastbee.iot.domain.*;
|
||||||
@ -84,6 +85,9 @@ public class DataHandlerImpl implements IDataHandler {
|
|||||||
@Resource
|
@Resource
|
||||||
private IFunctionLogService functionLogService;
|
private IFunctionLogService functionLogService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DeviceReportTrigger deviceReportTrigger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上报属性或功能处理
|
* 上报属性或功能处理
|
||||||
*
|
*
|
||||||
@ -116,6 +120,8 @@ public class DataHandlerImpl implements IDataHandler {
|
|||||||
// payload 与 MQTT 上报格式一致:ThingsModelSimpleItem JSON 数组(含计算物模型)
|
// payload 与 MQTT 上报格式一致:ThingsModelSimpleItem JSON 数组(含计算物模型)
|
||||||
String bridgePayload = JSON.toJSONString(result);
|
String bridgePayload = JSON.toJSONString(result);
|
||||||
ruleProcess.processRuleScript(serialNumber, 1, "tcp/property/post", bridgePayload);
|
ruleProcess.processRuleScript(serialNumber, 1, "tcp/property/post", bridgePayload);
|
||||||
|
// 平台对接推送(异步,不阻塞主链路)
|
||||||
|
deviceReportTrigger.onDeviceReport(serialNumber, bridgePayload);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("数据桥接规则引擎执行异常 sn={}, msg={}", serialNumber, e.getMessage(), e);
|
log.error("数据桥接规则引擎执行异常 sn={}, msg={}", serialNumber, e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,4 +33,12 @@ public class PlatformPushLogController extends BaseController {
|
|||||||
public AjaxResult getInfo(@PathVariable Long id) {
|
public AjaxResult getInfo(@PathVariable Long id) {
|
||||||
return success(pushLogService.getById(id));
|
return success(pushLogService.getById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('platform:pushLog:edit')")
|
||||||
|
@PostMapping("/{id}/retry")
|
||||||
|
@ApiOperation("手动重推")
|
||||||
|
public AjaxResult retry(@PathVariable Long id) {
|
||||||
|
pushLogService.retry(id);
|
||||||
|
return success("重推成功");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,6 +71,7 @@ public class DcpPlatformAdapter {
|
|||||||
logEntry.setInterfaceCode("dcp_push_" + sensorType);
|
logEntry.setInterfaceCode("dcp_push_" + sensorType);
|
||||||
logEntry.setStatus(0);
|
logEntry.setStatus(0);
|
||||||
logEntry.setRetryCount(0);
|
logEntry.setRetryCount(0);
|
||||||
|
logEntry.setLogType(1); // 数据推送日志
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 1. 字段映射转换
|
// 1. 字段映射转换
|
||||||
@ -126,7 +127,12 @@ public class DcpPlatformAdapter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
JSONArray fieldMappings = JSON.parseArray(mapping.getFieldMapping());
|
JSONArray fieldMappings = JSON.parseArray(mapping.getFieldMapping());
|
||||||
JSONObject reportData = JSON.parseObject(payload);
|
|
||||||
|
// payload 可能是数组 [{id,value,ts},...] 或对象 {key:value,...}
|
||||||
|
JSONObject reportData = parsePayloadToMap(payload);
|
||||||
|
if (reportData == null || reportData.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
JSONObject dcpData = new JSONObject();
|
JSONObject dcpData = new JSONObject();
|
||||||
dcpData.put("deviceId", mapping.getPlatformDeviceId());
|
dcpData.put("deviceId", mapping.getPlatformDeviceId());
|
||||||
@ -158,6 +164,35 @@ public class DcpPlatformAdapter {
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将设备上报 payload 解析为 {identifier: value} 的扁平 map
|
||||||
|
* 支持两种格式:
|
||||||
|
* 1. 数组: [{"id":"AngX","value":"-1.55","ts":"..."},...]
|
||||||
|
* 2. 对象: {"AngX":"-1.55","T":"21.6",...}
|
||||||
|
*/
|
||||||
|
private JSONObject parsePayloadToMap(String payload) {
|
||||||
|
String trimmed = payload.trim();
|
||||||
|
if (trimmed.startsWith("[")) {
|
||||||
|
JSONArray arr = JSON.parseArray(trimmed);
|
||||||
|
JSONObject map = new JSONObject();
|
||||||
|
for (int i = 0; i < arr.size(); i++) {
|
||||||
|
JSONObject item = arr.getJSONObject(i);
|
||||||
|
String id = item.getString("id");
|
||||||
|
if (id == null) id = item.getString("identifier");
|
||||||
|
if (id == null) continue;
|
||||||
|
Object value = item.get("value");
|
||||||
|
map.put(id, value);
|
||||||
|
// 同时保存 ts 供时间转换使用
|
||||||
|
if (item.containsKey("ts")) {
|
||||||
|
map.put(id + "__ts", item.get("ts"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
} else {
|
||||||
|
return JSON.parseObject(trimmed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** 确保 Token 有效,过期则执行 flow_type=3 的 Token 刷新流程 */
|
/** 确保 Token 有效,过期则执行 flow_type=3 的 Token 刷新流程 */
|
||||||
private String ensureToken(PlatformInstance platform) {
|
private String ensureToken(PlatformInstance platform) {
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
|
|||||||
@ -57,6 +57,9 @@ public class PlatformPushLog implements Serializable {
|
|||||||
@ApiModelProperty("状态(0=进行中,1=成功,2=失败)")
|
@ApiModelProperty("状态(0=进行中,1=成功,2=失败)")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
@ApiModelProperty("日志类型(1=数据推送,2=操作日志)")
|
||||||
|
private Integer logType;
|
||||||
|
|
||||||
@ApiModelProperty("错误信息")
|
@ApiModelProperty("错误信息")
|
||||||
private String errorMsg;
|
private String errorMsg;
|
||||||
|
|
||||||
|
|||||||
@ -69,6 +69,7 @@ public class PlatformFlowExecutor {
|
|||||||
logEntry.setInterfaceCode(iface.getCode());
|
logEntry.setInterfaceCode(iface.getCode());
|
||||||
logEntry.setStatus(0);
|
logEntry.setStatus(0);
|
||||||
logEntry.setRetryCount(0);
|
logEntry.setRetryCount(0);
|
||||||
|
logEntry.setLogType(2); // 操作日志(认证/入网等流程步骤)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 1. 解析入参
|
// 1. 解析入参
|
||||||
|
|||||||
@ -14,4 +14,7 @@ public interface IPlatformPushLogService extends IService<PlatformPushLog> {
|
|||||||
|
|
||||||
/** 查询某设备某接口最后一次成功推送的响应体(用于递增约束校验) */
|
/** 查询某设备某接口最后一次成功推送的响应体(用于递增约束校验) */
|
||||||
String selectLastSuccessResponseBody(Long deviceId, String interfaceCode);
|
String selectLastSuccessResponseBody(Long deviceId, String interfaceCode);
|
||||||
|
|
||||||
|
/** 手动重推:重新发送已记录的请求,更新日志状态 */
|
||||||
|
void retry(Long id);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,13 @@ package com.fastbee.iot.platform.service.impl;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.dtflys.forest.http.ForestRequest;
|
||||||
|
import com.dtflys.forest.http.ForestRequestType;
|
||||||
|
import com.fastbee.http.model.HttpClientConfig;
|
||||||
|
import com.fastbee.http.service.HttpClientFactory;
|
||||||
|
import com.fastbee.iot.platform.domain.PlatformInstance;
|
||||||
import com.fastbee.iot.platform.domain.PlatformPushLog;
|
import com.fastbee.iot.platform.domain.PlatformPushLog;
|
||||||
|
import com.fastbee.iot.platform.mapper.PlatformInstanceMapper;
|
||||||
import com.fastbee.iot.platform.mapper.PlatformPushLogMapper;
|
import com.fastbee.iot.platform.mapper.PlatformPushLogMapper;
|
||||||
import com.fastbee.iot.platform.service.IPlatformPushLogService;
|
import com.fastbee.iot.platform.service.IPlatformPushLogService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -11,7 +17,9 @@ import org.springframework.scheduling.annotation.Async;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class PlatformPushLogServiceImpl extends ServiceImpl<PlatformPushLogMapper, PlatformPushLog>
|
public class PlatformPushLogServiceImpl extends ServiceImpl<PlatformPushLogMapper, PlatformPushLog>
|
||||||
@ -19,6 +27,8 @@ public class PlatformPushLogServiceImpl extends ServiceImpl<PlatformPushLogMappe
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private PlatformPushLogMapper pushLogMapper;
|
private PlatformPushLogMapper pushLogMapper;
|
||||||
|
@Autowired
|
||||||
|
private PlatformInstanceMapper instanceMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PlatformPushLog> selectList(PlatformPushLog query) {
|
public List<PlatformPushLog> selectList(PlatformPushLog query) {
|
||||||
@ -26,6 +36,7 @@ public class PlatformPushLogServiceImpl extends ServiceImpl<PlatformPushLogMappe
|
|||||||
.eq(query.getPlatformId() != null, PlatformPushLog::getPlatformId, query.getPlatformId())
|
.eq(query.getPlatformId() != null, PlatformPushLog::getPlatformId, query.getPlatformId())
|
||||||
.eq(query.getDeviceId() != null, PlatformPushLog::getDeviceId, query.getDeviceId())
|
.eq(query.getDeviceId() != null, PlatformPushLog::getDeviceId, query.getDeviceId())
|
||||||
.eq(query.getStatus() != null, PlatformPushLog::getStatus, query.getStatus())
|
.eq(query.getStatus() != null, PlatformPushLog::getStatus, query.getStatus())
|
||||||
|
.eq(query.getLogType() != null, PlatformPushLog::getLogType, query.getLogType())
|
||||||
.eq(StringUtils.hasText(query.getSerialNumber()), PlatformPushLog::getSerialNumber, query.getSerialNumber())
|
.eq(StringUtils.hasText(query.getSerialNumber()), PlatformPushLog::getSerialNumber, query.getSerialNumber())
|
||||||
.orderByDesc(PlatformPushLog::getCreateTime);
|
.orderByDesc(PlatformPushLog::getCreateTime);
|
||||||
return this.list(wrapper);
|
return this.list(wrapper);
|
||||||
@ -41,4 +52,66 @@ public class PlatformPushLogServiceImpl extends ServiceImpl<PlatformPushLogMappe
|
|||||||
public String selectLastSuccessResponseBody(Long deviceId, String interfaceCode) {
|
public String selectLastSuccessResponseBody(Long deviceId, String interfaceCode) {
|
||||||
return pushLogMapper.selectLastSuccessResponseBody(deviceId, interfaceCode);
|
return pushLogMapper.selectLastSuccessResponseBody(deviceId, interfaceCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void retry(Long id) {
|
||||||
|
PlatformPushLog log = this.getById(id);
|
||||||
|
if (log == null) throw new RuntimeException("日志记录不存在: " + id);
|
||||||
|
if (!StringUtils.hasText(log.getRequestUrl()) || !StringUtils.hasText(log.getRequestBody())) {
|
||||||
|
throw new RuntimeException("日志缺少请求URL或请求体,无法重推");
|
||||||
|
}
|
||||||
|
|
||||||
|
long startMs = System.currentTimeMillis();
|
||||||
|
// 标记为进行中
|
||||||
|
PlatformPushLog update = new PlatformPushLog();
|
||||||
|
update.setId(id);
|
||||||
|
update.setStatus(0);
|
||||||
|
update.setRetryCount(log.getRetryCount() == null ? 1 : log.getRetryCount() + 1);
|
||||||
|
update.setErrorMsg(null);
|
||||||
|
this.updateById(update);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 获取平台 token
|
||||||
|
String token = null;
|
||||||
|
if (log.getPlatformId() != null) {
|
||||||
|
PlatformInstance platform = instanceMapper.selectById(log.getPlatformId());
|
||||||
|
if (platform != null) {
|
||||||
|
token = platform.getAccessToken();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> headers = new HashMap<>();
|
||||||
|
headers.put("Content-Type", "application/json");
|
||||||
|
if (StringUtils.hasText(token)) {
|
||||||
|
headers.put("Authorization", "Bearer " + token);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpClientConfig config = HttpClientConfig.builder()
|
||||||
|
.url(log.getRequestUrl())
|
||||||
|
.method(ForestRequestType.POST)
|
||||||
|
.headers(headers)
|
||||||
|
.body(log.getRequestBody())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ForestRequest<?> request = HttpClientFactory.instance(config);
|
||||||
|
String responseBody = request.executeAsString();
|
||||||
|
|
||||||
|
PlatformPushLog success = new PlatformPushLog();
|
||||||
|
success.setId(id);
|
||||||
|
success.setStatus(1);
|
||||||
|
success.setResponseBody(responseBody);
|
||||||
|
success.setResponseCode(200);
|
||||||
|
success.setCostMs((int) (System.currentTimeMillis() - startMs));
|
||||||
|
this.updateById(success);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
PlatformPushLog fail = new PlatformPushLog();
|
||||||
|
fail.setId(id);
|
||||||
|
fail.setStatus(2);
|
||||||
|
fail.setErrorMsg(e.getMessage());
|
||||||
|
fail.setCostMs((int) (System.currentTimeMillis() - startMs));
|
||||||
|
this.updateById(fail);
|
||||||
|
throw new RuntimeException("重推失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.fastbee.iot.platform.trigger;
|
package com.fastbee.iot.platform.trigger;
|
||||||
|
|
||||||
|
import com.fastbee.common.constant.FastBeeConstant;
|
||||||
import com.fastbee.iot.platform.adapter.dcp.DcpPlatformAdapter;
|
import com.fastbee.iot.platform.adapter.dcp.DcpPlatformAdapter;
|
||||||
import com.fastbee.iot.platform.domain.PlatformDeviceMapping;
|
import com.fastbee.iot.platform.domain.PlatformDeviceMapping;
|
||||||
import com.fastbee.iot.platform.domain.PlatformInstance;
|
import com.fastbee.iot.platform.domain.PlatformInstance;
|
||||||
@ -36,7 +37,7 @@ public class DeviceReportTrigger {
|
|||||||
* @param serialNumber 设备序列号
|
* @param serialNumber 设备序列号
|
||||||
* @param payload 上报数据 JSON
|
* @param payload 上报数据 JSON
|
||||||
*/
|
*/
|
||||||
@Async
|
@Async(FastBeeConstant.TASK.PUSH_TO_THIRD_PLATFORM_ASYNC)
|
||||||
public void onDeviceReport(String serialNumber, String payload) {
|
public void onDeviceReport(String serialNumber, String payload) {
|
||||||
try {
|
try {
|
||||||
List<PlatformDeviceMapping> mappings = mappingService.selectBySerialNumber(serialNumber);
|
List<PlatformDeviceMapping> mappings = mappingService.selectBySerialNumber(serialNumber);
|
||||||
|
|||||||
@ -236,7 +236,9 @@ SET @flow_inclino_id = LAST_INSERT_ID();
|
|||||||
INSERT INTO `platform_flow_step` (`flow_id`,`step_order`,`interface_id`,`result_key`,`result_save`,`remark`)
|
INSERT INTO `platform_flow_step` (`flow_id`,`step_order`,`interface_id`,`result_key`,`result_save`,`remark`)
|
||||||
VALUES (@flow_inclino_id, 1,
|
VALUES (@flow_inclino_id, 1,
|
||||||
(SELECT id FROM platform_interface WHERE platform_id=@dcp_platform_id AND code='dcp_create_point' LIMIT 1),
|
(SELECT id FROM platform_interface WHERE platform_id=@dcp_platform_id AND code='dcp_create_point' LIMIT 1),
|
||||||
'step1', NULL, '创建测点,获取pointId');
|
'step1',
|
||||||
|
'[{"field":"id","saveTo":"device_mapping.platform_point_id"}]',
|
||||||
|
'创建测点,获取pointId并回填');
|
||||||
|
|
||||||
INSERT INTO `platform_flow_step` (`flow_id`,`step_order`,`interface_id`,`result_key`,`result_save`,`remark`)
|
INSERT INTO `platform_flow_step` (`flow_id`,`step_order`,`interface_id`,`result_key`,`result_save`,`remark`)
|
||||||
VALUES (@flow_inclino_id, 2,
|
VALUES (@flow_inclino_id, 2,
|
||||||
@ -252,10 +254,12 @@ VALUES (@dcp_platform_id, 'DCP轴力计入网', 'dcp_onboard_stress', 2, 'stress
|
|||||||
|
|
||||||
SET @flow_stress_id = LAST_INSERT_ID();
|
SET @flow_stress_id = LAST_INSERT_ID();
|
||||||
|
|
||||||
INSERT INTO `platform_flow_step` (`flow_id`,`step_order`,`interface_id`,`result_key`,`remark`)
|
INSERT INTO `platform_flow_step` (`flow_id`,`step_order`,`interface_id`,`result_key`,`result_save`,`remark`)
|
||||||
VALUES (@flow_stress_id, 1,
|
VALUES (@flow_stress_id, 1,
|
||||||
(SELECT id FROM platform_interface WHERE platform_id=@dcp_platform_id AND code='dcp_create_point' LIMIT 1),
|
(SELECT id FROM platform_interface WHERE platform_id=@dcp_platform_id AND code='dcp_create_point' LIMIT 1),
|
||||||
'step1', '创建测点');
|
'step1',
|
||||||
|
'[{"field":"id","saveTo":"device_mapping.platform_point_id"}]',
|
||||||
|
'创建测点');
|
||||||
|
|
||||||
INSERT INTO `platform_flow_step` (`flow_id`,`step_order`,`interface_id`,`result_key`,`result_save`,`remark`)
|
INSERT INTO `platform_flow_step` (`flow_id`,`step_order`,`interface_id`,`result_key`,`result_save`,`remark`)
|
||||||
VALUES (@flow_stress_id, 2,
|
VALUES (@flow_stress_id, 2,
|
||||||
@ -271,10 +275,12 @@ VALUES (@dcp_platform_id, 'DCP雨量计入网', 'dcp_onboard_hyeto', 2, 'hyeto',
|
|||||||
|
|
||||||
SET @flow_hyeto_id = LAST_INSERT_ID();
|
SET @flow_hyeto_id = LAST_INSERT_ID();
|
||||||
|
|
||||||
INSERT INTO `platform_flow_step` (`flow_id`,`step_order`,`interface_id`,`result_key`,`remark`)
|
INSERT INTO `platform_flow_step` (`flow_id`,`step_order`,`interface_id`,`result_key`,`result_save`,`remark`)
|
||||||
VALUES (@flow_hyeto_id, 1,
|
VALUES (@flow_hyeto_id, 1,
|
||||||
(SELECT id FROM platform_interface WHERE platform_id=@dcp_platform_id AND code='dcp_create_point' LIMIT 1),
|
(SELECT id FROM platform_interface WHERE platform_id=@dcp_platform_id AND code='dcp_create_point' LIMIT 1),
|
||||||
'step1', '创建测点');
|
'step1',
|
||||||
|
'[{"field":"id","saveTo":"device_mapping.platform_point_id"}]',
|
||||||
|
'创建测点');
|
||||||
|
|
||||||
INSERT INTO `platform_flow_step` (`flow_id`,`step_order`,`interface_id`,`result_key`,`result_save`,`remark`)
|
INSERT INTO `platform_flow_step` (`flow_id`,`step_order`,`interface_id`,`result_key`,`result_save`,`remark`)
|
||||||
VALUES (@flow_hyeto_id, 2,
|
VALUES (@flow_hyeto_id, 2,
|
||||||
|
|||||||
@ -128,6 +128,7 @@ CREATE TABLE IF NOT EXISTS `platform_push_log` (
|
|||||||
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '状态(0=进行中,1=成功,2=失败)',
|
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '状态(0=进行中,1=成功,2=失败)',
|
||||||
`error_msg` varchar(1000) DEFAULT NULL COMMENT '错误信息',
|
`error_msg` varchar(1000) DEFAULT NULL COMMENT '错误信息',
|
||||||
`idempotency_key` varchar(100) DEFAULT NULL COMMENT '幂等键,防重复推送',
|
`idempotency_key` varchar(100) DEFAULT NULL COMMENT '幂等键,防重复推送',
|
||||||
|
`log_type` tinyint(1) NOT NULL DEFAULT 1 COMMENT '日志类型(1=数据推送,2=操作日志)',
|
||||||
`retry_count` int(11) NOT NULL DEFAULT 0 COMMENT '重试次数',
|
`retry_count` int(11) NOT NULL DEFAULT 0 COMMENT '重试次数',
|
||||||
`cost_ms` int(11) DEFAULT NULL COMMENT '耗时毫秒',
|
`cost_ms` int(11) DEFAULT NULL COMMENT '耗时毫秒',
|
||||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
|||||||
@ -7,3 +7,7 @@ export function listPlatformPushLog(params) {
|
|||||||
export function getPlatformPushLog(id) {
|
export function getPlatformPushLog(id) {
|
||||||
return request({ url: `/platform/push-log/${id}`, method: 'get' })
|
return request({ url: `/platform/push-log/${id}`, method: 'get' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function retryPlatformPushLog(id) {
|
||||||
|
return request({ url: `/platform/push-log/${id}/retry`, method: 'post' })
|
||||||
|
}
|
||||||
|
|||||||
@ -28,13 +28,18 @@
|
|||||||
<el-card>
|
<el-card>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
|
||||||
|
|
||||||
|
<el-tabs v-model="activeTab" @tab-click="onTabChange">
|
||||||
|
<el-tab-pane label="数据推送" name="1" />
|
||||||
|
<el-tab-pane label="操作日志" name="2" />
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="list">
|
<el-table v-loading="loading" :data="list">
|
||||||
<el-table-column label="时间" prop="createTime" width="160" />
|
<el-table-column label="时间" prop="createTime" width="160" />
|
||||||
<el-table-column label="平台" width="120">
|
<el-table-column label="平台" width="120">
|
||||||
<template slot-scope="scope">{{ platformName(scope.row.platformId) }}</template>
|
<template slot-scope="scope">{{ platformName(scope.row.platformId) }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="设备序列号" prop="serialNumber" width="140" />
|
<el-table-column label="设备序列号" prop="serialNumber" width="140" />
|
||||||
<el-table-column label="接口" prop="interfaceCode" width="160" show-overflow-tooltip />
|
<el-table-column label="接口" prop="interfaceCode" width="180" show-overflow-tooltip />
|
||||||
<el-table-column label="状态" width="80" align="center">
|
<el-table-column label="状态" width="80" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag size="small" type="info" v-if="scope.row.status===0">进行中</el-tag>
|
<el-tag size="small" type="info" v-if="scope.row.status===0">进行中</el-tag>
|
||||||
@ -44,9 +49,14 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="耗时(ms)" prop="costMs" width="90" align="right" />
|
<el-table-column label="耗时(ms)" prop="costMs" width="90" align="right" />
|
||||||
<el-table-column label="错误信息" prop="errorMsg" min-width="160" show-overflow-tooltip />
|
<el-table-column label="错误信息" prop="errorMsg" min-width="160" show-overflow-tooltip />
|
||||||
<el-table-column label="操作" fixed="right" width="80" align="center">
|
<el-table-column label="操作" fixed="right" width="140" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleDetail(scope.row)">详情</el-button>
|
<el-button size="mini" type="text" icon="el-icon-view" @click="handleDetail(scope.row)">详情</el-button>
|
||||||
|
<el-button
|
||||||
|
v-if="scope.row.status===2 && activeTab==='1'"
|
||||||
|
size="mini" type="text" icon="el-icon-refresh"
|
||||||
|
:loading="retryingId===scope.row.id"
|
||||||
|
@click="handleRetry(scope.row)">重推</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@ -55,12 +65,13 @@
|
|||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<!-- 详情弹窗 -->
|
<!-- 详情弹窗 -->
|
||||||
<el-dialog title="推送详情" :visible.sync="detailOpen" width="800px" append-to-body>
|
<el-dialog title="日志详情" :visible.sync="detailOpen" width="800px" append-to-body>
|
||||||
<el-descriptions :column="2" border size="small" style="margin-bottom:16px">
|
<el-descriptions :column="2" border size="small" style="margin-bottom:16px">
|
||||||
<el-descriptions-item label="平台">{{ platformName(detail.platformId) }}</el-descriptions-item>
|
<el-descriptions-item label="平台">{{ platformName(detail.platformId) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="接口">{{ detail.interfaceCode }}</el-descriptions-item>
|
<el-descriptions-item label="接口">{{ detail.interfaceCode }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="设备序列号">{{ detail.serialNumber }}</el-descriptions-item>
|
<el-descriptions-item label="设备序列号">{{ detail.serialNumber }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="状态">
|
<el-descriptions-item label="状态">
|
||||||
|
<el-tag size="small" type="info" v-if="detail.status===0">进行中</el-tag>
|
||||||
<el-tag size="small" type="success" v-if="detail.status===1">成功</el-tag>
|
<el-tag size="small" type="success" v-if="detail.status===1">成功</el-tag>
|
||||||
<el-tag size="small" type="danger" v-if="detail.status===2">失败</el-tag>
|
<el-tag size="small" type="danger" v-if="detail.status===2">失败</el-tag>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
@ -88,7 +99,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listPlatformPushLog, getPlatformPushLog } from '@/api/platform/pushLog'
|
import { listPlatformPushLog, getPlatformPushLog, retryPlatformPushLog } from '@/api/platform/pushLog'
|
||||||
import { listPlatformInstance } from '@/api/platform/instance'
|
import { listPlatformInstance } from '@/api/platform/instance'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -100,10 +111,12 @@ export default {
|
|||||||
total: 0,
|
total: 0,
|
||||||
list: [],
|
list: [],
|
||||||
platformList: [],
|
platformList: [],
|
||||||
|
activeTab: '1',
|
||||||
|
retryingId: null,
|
||||||
detailOpen: false,
|
detailOpen: false,
|
||||||
detailTab: 'req',
|
detailTab: 'req',
|
||||||
detail: {},
|
detail: {},
|
||||||
queryParams: { pageNum: 1, pageSize: 20, platformId: null, serialNumber: '', status: null }
|
queryParams: { pageNum: 1, pageSize: 20, platformId: null, serialNumber: '', status: null, logType: 1 }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@ -121,6 +134,11 @@ export default {
|
|||||||
const p = this.platformList.find(x => x.id === id)
|
const p = this.platformList.find(x => x.id === id)
|
||||||
return p ? p.name : id
|
return p ? p.name : id
|
||||||
},
|
},
|
||||||
|
onTabChange(tab) {
|
||||||
|
this.queryParams.logType = parseInt(tab.name)
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
handleQuery() { this.queryParams.pageNum = 1; this.getList() },
|
handleQuery() { this.queryParams.pageNum = 1; this.getList() },
|
||||||
resetQuery() { this.resetForm('queryForm'); this.handleQuery() },
|
resetQuery() { this.resetForm('queryForm'); this.handleQuery() },
|
||||||
handleDetail(row) {
|
handleDetail(row) {
|
||||||
@ -130,6 +148,17 @@ export default {
|
|||||||
this.detailOpen = true
|
this.detailOpen = true
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
handleRetry(row) {
|
||||||
|
this.retryingId = row.id
|
||||||
|
retryPlatformPushLog(row.id).then(() => {
|
||||||
|
this.$message.success('重推成功')
|
||||||
|
this.getList()
|
||||||
|
}).catch(err => {
|
||||||
|
this.$message.error(err.message || '重推失败')
|
||||||
|
}).finally(() => {
|
||||||
|
this.retryingId = null
|
||||||
|
})
|
||||||
|
},
|
||||||
formatJson(str) {
|
formatJson(str) {
|
||||||
if (!str) return ''
|
if (!str) return ''
|
||||||
try { return JSON.stringify(JSON.parse(str), null, 2) } catch { return str }
|
try { return JSON.stringify(JSON.parse(str), null, 2) } catch { return str }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user