Commit 5778d12a authored by xinglei's avatar xinglei

科技处告警跑马灯展示

parent 6ab4d9c7
...@@ -44,333 +44,337 @@ import java.util.Properties; ...@@ -44,333 +44,337 @@ import java.util.Properties;
@Component @Component
public class EquipmentListener extends EmqxListener implements InitializingBean { public class EquipmentListener extends EmqxListener implements InitializingBean {
private final Logger logger = LogManager.getLogger(EquipmentListener.class); private final Logger logger = LogManager.getLogger(EquipmentListener.class);
@Autowired @Autowired
private EmqKeeper emqKeeper; private EmqKeeper emqKeeper;
@Autowired @Autowired
private BankInfoMapper bankInfoMapper; private BankInfoMapper bankInfoMapper;
@Autowired @Autowired
private AmosWsClient client; private AmosWsClient client;
@Autowired @Autowired
EquipmentMapper equipmentMapper; EquipmentMapper equipmentMapper;
@Autowired @Autowired
RiskModelRemoteClient riskModelRemoteClient; RiskModelRemoteClient riskModelRemoteClient;
@Autowired @Autowired
private RemoteWebSocketServer webSocketServer; private RemoteWebSocketServer webSocketServer;
@Autowired @Autowired
private IAlarmPointService alarmPointService; private IAlarmPointService alarmPointService;
@Autowired @Autowired
private IAlarmService alarmService; private IAlarmService alarmService;
@Autowired @Autowired
private IAlarmRepository iAlarmDao; private IAlarmRepository iAlarmDao;
/** /**
* 监听主题 * 监听主题
*/ */
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
emqKeeper.subscript(CommTopic.AISLE_DEVICE.getTopic(), 2, this); emqKeeper.subscript(CommTopic.AISLE_DEVICE.getTopic(), 2, this);
} }
/** /**
* 接收主题下的消息 * 接收主题下的消息
*/ */
@Override @Override
public void processMessage(String s, MqttMessage mqttMessage) throws Exception { public void processMessage(String s, MqttMessage mqttMessage) throws Exception {
blueprintMsgtransfer(mqttMessage); blueprintMsgtransfer(mqttMessage);
} }
/** /**
* 消息处理 * 消息处理
* *
* @param mqttMessage * @param mqttMessage
*/ */
private void blueprintMsgtransfer(MqttMessage mqttMessage) { private void blueprintMsgtransfer(MqttMessage mqttMessage) {
try { try {
String jsonStr = new String(mqttMessage.getPayload()); String jsonStr = new String(mqttMessage.getPayload());
logger.info(">>>>>>>>>>>>>>>>>jsonStr", jsonStr); logger.info(">>>>>>>>>>>>>>>>>jsonStr", jsonStr);
JSONArray jsonArray = JSON.parseObject(jsonStr).getJSONArray("metricDatas"); JSONArray jsonArray = JSON.parseObject(jsonStr).getJSONArray("metricDatas");
if (ObjectUtils.isEmpty(jsonArray)) { if (ObjectUtils.isEmpty(jsonArray)) {
return; return;
} }
jsonArray.forEach(e -> { jsonArray.forEach(e -> {
JSONObject object = (JSONObject) e; JSONObject object = (JSONObject) e;
Long eqpId = object.getLong("eqpId"); Long eqpId = object.getLong("eqpId");
String string = object.getString("metricJson"); String string = object.getString("metricJson");
if (!StringUtil.isNotEmpty(string)) { if (!StringUtil.isNotEmpty(string)) {
return; return;
} }
logger.error(">>>>>>>>>>>>>>>>>string", string); logger.error(">>>>>>>>>>>>>>>>>string", string);
JSONObject metricJson = JSONObject.parseObject(string); JSONObject metricJson = JSONObject.parseObject(string);
String communication = metricJson.get("communication").toString(); String communication = metricJson.get("communication").toString();
int status = communication.equals("正常") ? 0 : 1; int status = communication.equals("正常") ? 0 : 1;
int sourceIdStatus = bankInfoMapper.findBySourceId(eqpId); String sourceIdStatus = bankInfoMapper.findBySourceId(eqpId);
if (status != sourceIdStatus) { if (!ObjectUtils.isEmpty(sourceIdStatus) && status != Integer.valueOf(sourceIdStatus).intValue()) {
bankInfoMapper.updateBySourceId(status, eqpId); bankInfoMapper.updateBySourceId(status, eqpId);
Map<String, Object> resultMap = bankInfoMapper.selectBankInfoBySourceId(eqpId); Map<String, Object> resultMap = bankInfoMapper.selectBankInfoBySourceId(eqpId);
resultMap.put("eqpId", eqpId); resultMap.put("eqpId", eqpId);
pushAisleAlarm(resultMap); pushAisleAlarm(resultMap);
logger.info("=======aisle状态有变化====="); logger.info("=======aisle状态有变化=====");
} }
}); });
//告警处理 //告警处理
handleAlarmData(jsonStr); handleAlarmData(jsonStr);
} catch (Exception e) { } catch (Exception e) {
logger.error("消息流转报错."); logger.error("消息流转报错.");
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
e.printStackTrace(); e.printStackTrace();
} }
} }
/** /**
* 发送通道刷新标识 * 发送通道刷新标识
*/ */
public void pushAisleAlarm(Map<String, Object> result) { public void pushAisleAlarm(Map<String, Object> result) {
WebsocketParam param = new WebsocketParam("aisleAlarm", JSON.toJSONString(result)); WebsocketParam param = new WebsocketParam("aisleAlarm", JSON.toJSONString(result));
client.sendMessage(param); client.sendMessage(param);
} }
public void handleAlarmData(String jsonStr) { public void handleAlarmData(String jsonStr) {
try { try {
logger.info("start handle ip equipment alarm.."); logger.info("start handle ip equipment alarm..");
JSONObject parseObject = JSON.parseObject(jsonStr); JSONObject parseObject = JSON.parseObject(jsonStr);
Long eqpId = parseObject.getLong("eqpId"); Long eqpId = parseObject.getLong("eqpId");
JSONArray jsonArray = parseObject.getJSONArray("metricDatas"); JSONArray jsonArray = parseObject.getJSONArray("metricDatas");
JSONArray eqpConfigMap = parseObject.getJSONArray("eqpConfigMap"); JSONArray eqpConfigMap = parseObject.getJSONArray("eqpConfigMap");
// 获取ip // 获取ip
String ipAddress = getEqpConfigMapValueByKey(eqpConfigMap, "IP"); String ipAddress = getEqpConfigMapValueByKey(eqpConfigMap, "IP");
// 所属楼层
// 所属楼层 String lou = getEqpConfigMapValueByKey(eqpConfigMap, "所属楼层");
String lou = getEqpConfigMapValueByKey(eqpConfigMap, "所属楼层"); // 三维位置
// 三维位置 String sanwei = getEqpConfigMapValueByKey(eqpConfigMap, "三维位置");
String sanwei = getEqpConfigMapValueByKey(eqpConfigMap, "三维位置"); // 资源ID
String sourceId = getEqpConfigMapValueByKey(eqpConfigMap, "设备ID");
// 资源ID String eqpName = parseObject.getString("eqpName");
String sourceId = getEqpConfigMapValueByKey(eqpConfigMap, "设备ID"); // orgcode
String orgcode = parseObject.getString("orgCode");
String eqpName = parseObject.getString("eqpName");
// orgcode if (ObjectUtils.isEmpty(jsonArray)) {
String orgcode = parseObject.getString("orgCode"); return;
}
if (ObjectUtils.isEmpty(jsonArray)) { // 告警信息
return; String metricKey = "";
} // 默认状态为正常
// 告警信息 Object communication = JSONObject.parseObject(((JSONObject) jsonArray.get(0)).getString("metricJson")).get("communication");
String metricKey = ""; int statusByName = !ObjectUtils.isEmpty(communication) && communication.equals("异常") ? 1 : 0;
// 默认状态为正常
int statusByName = 0; for (Object e : jsonArray) {
for (Object e : jsonArray) { JSONObject object = (JSONObject) e;
JSONObject object = (JSONObject) e; String string = object.getString("metricJson");
String string = object.getString("metricJson"); metricKey = object.getString("metricKey");
metricKey = object.getString("metricKey"); if (!StringUtil.isNotEmpty(string)) {
if (!StringUtil.isNotEmpty(string)) { return;
return; }
} logger.error("---------ip equipment--string", string);
logger.error("---------ip equipment--string", string); System.out.println("----ip equipment chuli recording : " + string);
System.out.println("----ip equipment chuli recording : " + string); // {"describe":"状态","communication":"异常"}
// {"describe":"状态","communication":"异常"} JSONObject metricJson = JSONObject.parseObject(string);
JSONObject metricJson = JSONObject.parseObject(string);
for (Map.Entry entry : metricJson.entrySet()) {
for (Map.Entry entry : metricJson.entrySet()) { // 指标名
// 指标名 System.out.println("----start chuli ip equipment state : " + entry);
System.out.println("----start chuli ip equipment state : " + entry); String remark = entry.getKey().toString();
String remark = entry.getKey().toString(); String statusName = entry.getValue().toString();
String statusName = entry.getValue().toString(); if (remark.equals("communication")) {
//拓扑闪烁
if (remark.equals("communication")) { topographyAlarm(sourceId, statusByName);
// 触发风险合格不合格
// 触发风险合格不合格 riskAlarm(eqpId, remark, statusName);
statusByName = riskAlarm(eqpId, remark, statusName); }
}
//拓扑闪烁 }
topographyAlarm(sourceId, statusByName);
} // 增加报警(跑马灯,首页)
} addAlarmMethod(eqpId, statusByName, eqpName, ipAddress, metricKey, orgcode, sanwei, lou);
}
; // 增建告警记录表
addAlarmRecord(eqpId, metricKey, statusByName, orgcode, ipAddress, eqpName);
// 增加报警(跑马灯,首页) } catch (Exception e) {
addAlarmMethod(eqpId, statusByName, eqpName, ipAddress, metricKey, orgcode, sanwei, lou); logger.error("消息流转报错.");
logger.error(e.getMessage(), e);
// 增建告警记录表 e.printStackTrace();
addAlarmRecord(eqpId, metricKey, statusByName, orgcode, ipAddress, eqpName); }
} catch (Exception e) { }
logger.error("消息流转报错.");
logger.error(e.getMessage(), e); private Integer riskAlarm(Long eqpId, String remark, String statusName) {
e.printStackTrace(); int statusByName = 0;
} EquipmentQualityVo queryEquipmentPoint = equipmentMapper.queryEquipmentPoint(eqpId, remark);
} if (!ObjectUtils.isEmpty(queryEquipmentPoint)) {
Long equipmentsPointId = queryEquipmentPoint.getId();
private Integer riskAlarm(Long eqpId, String remark, String statusName) { List<Long> riskFactorId = equipmentMapper.judgeEquipmentExists(equipmentsPointId);
int statusByName = 0;; if ("异常".equals(statusName)) {
EquipmentQualityVo queryEquipmentPoint = equipmentMapper.queryEquipmentPoint(eqpId, remark); Integer value = DevicePointEnum.getValue("异常");
Long equipmentsPointId = queryEquipmentPoint.getId(); equipmentMapper.updateEquipmentPointStatus(value, queryEquipmentPoint.getId());
List<Long> riskFactorId = equipmentMapper.judgeEquipmentExists(equipmentsPointId); statusByName = value;
if ("异常".equals(statusName)) { } else {
Integer value = DevicePointEnum.getValue("异常"); Integer value = DevicePointEnum.getValue("正常");
equipmentMapper.updateEquipmentPointStatus(value, queryEquipmentPoint.getId()); equipmentMapper.updateEquipmentPointStatus(value, queryEquipmentPoint.getId());
statusByName = value; statusByName = value;
} else { }
Integer value = DevicePointEnum.getValue("正常"); // 修改rpn值
equipmentMapper.updateEquipmentPointStatus(value, queryEquipmentPoint.getId()); for (int j = 0; j < riskFactorId.size(); j++) {
statusByName = value; try {
} riskModelRemoteClient.updateEquipmentAlarmData(riskFactorId.get(j));
// 修改rpn值 System.out.println("----udpate riskFactor sucess");
for (int j = 0; j < riskFactorId.size(); j++) { } catch (InnerInvokException e1) {
try { logger.error("update rpn fail " + e1.getMessage());
riskModelRemoteClient.updateEquipmentAlarmData(riskFactorId.get(j)); }
System.out.println("----udpate riskFactor sucess"); }
} catch (InnerInvokException e1) { }
logger.error("update rpn fail " + e1.getMessage()); return statusByName;
} }
}
return statusByName; private void topographyAlarm(String sourceId, Integer statusByName) {
} // 查询设备绑定的拓扑图标
TopographyNode node = equipmentMapper.queryNodeBySourceId(sourceId);
private void topographyAlarm(String sourceId, Integer statusByName) {
// 查询设备绑定的拓扑图标 // 拓扑闪烁
TopographyNode node = equipmentMapper.queryNodeBySourceId(sourceId); if (null != node && node.getState() != statusByName) {
node.setNumber(statusByName);
// 拓扑闪烁 node.setState(statusByName);
if (null != node) { equipmentMapper.updateNodeState(node);
node.setNumber(statusByName); String nodeDetail = (statusByName == 0 ? "[{\"name\":\"通信状态\",\"value\":\"正常\"}]"
node.setState(statusByName); : "[{\"name\":\"通信状态\",\"value\":\"异常\"}]");
equipmentMapper.updateNodeState(node); equipmentMapper.updateNodeDetail(node.getId(), nodeDetail);
String nodeDetail = (statusByName == 0 ? "[{\"name\":\"通信状态\",\"value\":\"正常\"}]" try {
: "[{\"name\":\"通信状态\",\"value\":\"异常\"}]"); //前端页面刷新告警
equipmentMapper.updateNodeDetail(node.getId(), nodeDetail); webSocketServer.sendMessage("refresh", "technologyIp");
try { } catch (Exception e1) {
//前端页面刷新告警 logger.error("webSocketServer send self! ");
webSocketServer.sendMessage("refresh", "technologyIp"); }
} catch (Exception e1) { }
logger.error("webSocketServer send self! "); }
}
} /**
} * 根据eqpConfigMap中的key获取value
*
/** * @param eqpConfigMap
* 根据eqpConfigMap中的key获取value * @param key
* @param eqpConfigMap * @return
* @param key */
* @return public String getEqpConfigMapValueByKey(JSONArray eqpConfigMap, String key) {
*/ // 配置信息
public String getEqpConfigMapValueByKey(JSONArray eqpConfigMap, String key) { if (null != eqpConfigMap && eqpConfigMap.size() > 0) {
// 配置信息 for (Object object : eqpConfigMap) {
if (null != eqpConfigMap && eqpConfigMap.size() > 0) { JSONObject obj = (JSONObject) object;
for (Object object : eqpConfigMap) { String displayName = obj.getString("displayName");
JSONObject obj = (JSONObject) object; if (displayName.contains(key)) {
String displayName = obj.getString("displayName"); String valueStr = obj.getString("valueStr");
if (displayName.contains(key)) { return valueStr;
String valueStr = obj.getString("valueStr"); }
return valueStr; }
} }
} return null;
} }
return null;
} /**
* 增加告警记录
/** *
* 增加告警记录 * @param eqpId
* @param eqpId * @param metricKey
* @param metricKey * @param statusByName
* @param statusByName * @param orgCode1
* @param orgCode1 * @param ipAddress
* @param ipAddress * @param eqpName
* @param eqpName */
*/ public void addAlarmRecord(Long eqpId, String metricKey, Integer statusByName, String orgCode1, String ipAddress, String eqpName) {
public void addAlarmRecord(Long eqpId,String metricKey,Integer statusByName,String orgCode1,String ipAddress,String eqpName) { List<Alarm> curAlarmList = alarmService.findByQueryColumn(eqpId + metricKey);
List<Alarm> curAlarmList = alarmService.findByQueryColumn(eqpId + metricKey); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); if (curAlarmList != null && curAlarmList.size() > 0) {
if (curAlarmList != null && curAlarmList.size() > 0) {
// if("异常".equals(curAlarmList.get(0).getCurrentState())){ // if("异常".equals(curAlarmList.get(0).getCurrentState())){
Alarm alarm = curAlarmList.get(0); Alarm alarm = curAlarmList.get(0);
alarm.setUpdateDate(df.format(new Date())); alarm.setUpdateDate(df.format(new Date()));
if (statusByName != 0) { if (statusByName != 0) {
alarm.setCurrentState("异常"); alarm.setCurrentState("异常");
} else { } else {
alarm.setCurrentState("正常"); alarm.setCurrentState("正常");
} }
alarm.setQueryColumn(eqpId + metricKey); alarm.setQueryColumn(eqpId + metricKey);
alarm.setAlarmSourceType(metricKey); alarm.setAlarmSourceType(metricKey);
alarm.setClearPerson(metricKey); alarm.setClearPerson(metricKey);
iAlarmDao.save(alarm); iAlarmDao.save(alarm);
// } // }
} else { } else {
Alarm alarm = new Alarm(); Alarm alarm = new Alarm();
alarm.setSourceId(eqpId + ""); alarm.setSourceId(eqpId + "");
alarm.setAlarmLevel("紧急告警"); alarm.setAlarmLevel("紧急告警");
alarm.setAlarmReason(""); alarm.setAlarmReason("");
alarm.setAlarmSourceIp(ipAddress + ""); alarm.setAlarmSourceIp(ipAddress + "");
alarm.setAlarmSourceName(eqpName); alarm.setAlarmSourceName(eqpName);
alarm.setAlarmSourceType(metricKey); alarm.setAlarmSourceType(metricKey);
alarm.setClearDate(""); alarm.setClearDate("");
alarm.setClearPerson(metricKey); alarm.setClearPerson(metricKey);
alarm.setContinueDate(""); alarm.setContinueDate("");
if (statusByName != 0) { if (statusByName != 0) {
alarm.setCurrentState("异常"); alarm.setCurrentState("异常");
} else { } else {
alarm.setCurrentState("正常"); alarm.setCurrentState("正常");
} }
alarm.setEnsureDate(""); alarm.setEnsureDate("");
alarm.setHappenDate(""); alarm.setHappenDate("");
alarm.setEnsurePerson(""); alarm.setEnsurePerson("");
alarm.setOrgCode(orgCode1); alarm.setOrgCode(orgCode1);
alarm.setUpdateDate(df.format(new Date())); alarm.setUpdateDate(df.format(new Date()));
alarm.setQueryColumn(eqpId + metricKey); alarm.setQueryColumn(eqpId + metricKey);
iAlarmDao.save(alarm); iAlarmDao.save(alarm);
} }
} }
public void addAlarmMethod(Long eqpId,Integer statusByName,String eqpName,String ipAddress,String metricKey,String orgCode,String sanwei,String lou) throws IOException { public void addAlarmMethod(Long eqpId, Integer statusByName, String eqpName, String ipAddress, String metricKey, String orgCode, String sanwei, String lou) throws IOException {
List<AlarmPoint> alarmPoint = alarmPointService.selectPointTypeAndPointId(AlarmPointTypeEnum.设备.getCode(), List<AlarmPoint> alarmPoint = alarmPointService.selectPointTypeAndPointId(AlarmPointTypeEnum.设备.getCode(),
eqpId); eqpId);
if (alarmPoint != null && alarmPoint.size() > 0) { if (alarmPoint != null && alarmPoint.size() > 0) {
// 存在报警,判断当前状态是不是合格,合格则删除上次的报警 // 存在报警,判断当前状态是不是合格,合格则删除上次的报警
if (statusByName == 0) { if (statusByName == 0) {
// 删除告警 // 删除告警
alarmPointService.delete(alarmPoint.get(0)); alarmPointService.delete(alarmPoint.get(0));
} pushAlarmPoint("alarmPoint", alarmPointService.findAll());
} else { }
// 不存在,判断当前状态是不是合格,不合格新增,合格不做任何操作 return;
if (statusByName != 0) { } else {
// 增加告警 // 不存在,判断当前状态是不是合格,不合格新增,合格不做任何操作
AlarmPoint alarmPoint1 = new AlarmPoint(); if (statusByName != 0) {
alarmPoint1.setPointId(eqpId); // 增加告警
alarmPoint1.setPointType(AlarmPointTypeEnum.设备.getCode()); AlarmPoint alarmPoint1 = new AlarmPoint();
alarmPoint1.setUpdateDate(new Date()); alarmPoint1.setPointId(eqpId);
alarmPoint1.setIsAlarm(1);// 不合格 alarmPoint1.setPointType(AlarmPointTypeEnum.设备.getCode());
alarmPoint1.setContent(eqpName + "-" + ipAddress + "-" + metricKey); alarmPoint1.setUpdateDate(new Date());
alarmPoint1.setCode(orgCode); alarmPoint1.setIsAlarm(1);// 不合格
alarmPoint1.setPointName(eqpName); alarmPoint1.setContent(eqpName + "-" + ipAddress + "-" + metricKey);
Map<String, Object> map = new HashMap<>(); alarmPoint1.setCode(orgCode);
map.put("position", sanwei); alarmPoint1.setPointName(eqpName);
map.put("storey", lou); Map<String, Object> map = new HashMap<>();
map.put("levelStr", "impEqu_04"); map.put("position", sanwei);
map.put("storey", lou);
alarmPoint1.setPointAttrs(JSON.toJSONString(map)); map.put("levelStr", "impEqu_04");
alarmPointService.save(alarmPoint1);
// 推送告警 alarmPoint1.setPointAttrs(JSON.toJSONString(map));
List<AlarmPoint> list = alarmPointService.findAll(); alarmPointService.save(alarmPoint1);
WebsocketParam param = new WebsocketParam("alarmPoint", JSON.toJSONString(list)); // 推送告警
Properties props = PropertiesLoaderUtils.loadAllProperties("application.properties"); pushAlarmPoint("alarmPoint", alarmPointService.findAll());
String url = (String) props.get("params.remoteWebsocketUrl") + "/generic/sendMessage"; }
HttpUtil.PostJson(url, JSON.toJSONString(param)); }
}
}
} /**
} * 发送跑马灯告警
*/
public void pushAlarmPoint(String WS, Object object) {
WebsocketParam param = new WebsocketParam(WS, JSON.toJSONString(object));
client.sendMessage(param);
}
} }
...@@ -234,7 +234,6 @@ public class SelfSupportListener extends EmqxListener implements InitializingBea ...@@ -234,7 +234,6 @@ public class SelfSupportListener extends EmqxListener implements InitializingBea
Properties props = PropertiesLoaderUtils.loadAllProperties("application.properties"); Properties props = PropertiesLoaderUtils.loadAllProperties("application.properties");
String url = (String) props.get("params.remoteWebsocketUrl") + "/generic/sendMessage"; String url = (String) props.get("params.remoteWebsocketUrl") + "/generic/sendMessage";
HttpUtil.PostJson(url, JSON.toJSONString(param)); HttpUtil.PostJson(url, JSON.toJSONString(param));
} }
} }
......
...@@ -16,7 +16,7 @@ public interface BankInfoMapper extends BaseMapper { ...@@ -16,7 +16,7 @@ public interface BankInfoMapper extends BaseMapper {
List<BankInfoDTO> selectBankInfoList(); List<BankInfoDTO> selectBankInfoList();
int findBySourceId(@Param("sourceId")Long sourceId); String findBySourceId(@Param("sourceId")Long sourceId);
void updateBySourceId(@Param("status") int status, @Param("sourceId")Long sourceId); void updateBySourceId(@Param("status") int status, @Param("sourceId")Long sourceId);
......
...@@ -40,5 +40,4 @@ public interface IEquipmentService { ...@@ -40,5 +40,4 @@ public interface IEquipmentService {
List<PointParam> handlePatrolPointData(Long factorId) throws InnerInvokException; List<PointParam> handlePatrolPointData(Long factorId) throws InnerInvokException;
Map<String, List> handlePointDatas(Long factorId) throws InnerInvokException; Map<String, List> handlePointDatas(Long factorId) throws InnerInvokException;
} }
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
from b_bank_info Bi left join b_bank_equipment Be on Bi.id = Be.bank_id group by Bi.id from b_bank_info Bi left join b_bank_equipment Be on Bi.id = Be.bank_id group by Bi.id
</select> </select>
<select id="findBySourceId" resultType="int"> <select id="findBySourceId" resultType="String">
select status from b_bank_equipment where 1=1 and source_id = #{sourceId} select status from b_bank_equipment where 1=1 and source_id = #{sourceId}
</select> </select>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment