Commit 2ac23d6e authored by suhuiguang's avatar suhuiguang

1.新增推送数据刷新-全景监控

parent d8726fc5
package com.yeejoin.amos.fas.common.enums;
/**
* @author suhg
*/
public enum DataRefreshTypeEum {
/**
* 数据刷新触发原因
*/
rpn("rpn变化","rpn"),
alarm("设备报警","alarm"),
planTask("检查任务","planTask"),
check("巡检","check"),
trouble("设备故障","trouble"),
dutyChange("值班信息","dutyChange");
private String code;
private String name;
DataRefreshTypeEum(String code,String name){
this.name = name;
this.code = code;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.yeejoin.amos.fas.common.enums; package com.yeejoin.amos.fas.common.enums;
import java.util.ArrayList;
import java.util.List;
/** /**
* @author suhg * @author suhg
*/ */
public enum View3dRefreshAreaEum { public enum View3dRefreshAreaEum {
/** /**
* 3d页面数据区域 * 3d页面数据区域(triggerBy枚举定义见DataRefreshTypeEum.java)
*/ */
all("全部区域","all"), all("全部区域", "all", "dateChange"),
today_safety_index("今日安全指数","today_safety_index"), today_safety_index("今日安全指数", "today_safety_index", "rpn,check,trouble"),
fire_safety("消防安全执行","fire_safety"), fire_safety("消防安全执行", "fire_safety", "alarm,rpn,check,trouble"),
week_safety_index("一周安全指数趋势","week_safety_index"), error_status("异常区域", "error_status", "rpn,trouble"),
today_check_status("今日巡检情况","today_check_status"), week_safety_index("一周安全指数趋势", "week_safety_index", "rpn"),
today_duty("今日值班","today_duty"); today_check_status("今日巡检情况", "today_check_status", "planTask,check"),
today_duty("今日值班", "today_duty", "dutyChange");
private String code; private String code;
private String name; private String name;
View3dRefreshAreaEum(String name,String code){ private String triggerBy;
View3dRefreshAreaEum(String name, String code, String triggerBy) {
this.name = name; this.name = name;
this.code = code; this.code = code;
this.triggerBy = triggerBy;
} }
public String getCode() { public String getCode() {
...@@ -40,4 +47,31 @@ public enum View3dRefreshAreaEum { ...@@ -40,4 +47,31 @@ public enum View3dRefreshAreaEum {
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
public String getTriggerBy() {
return triggerBy;
}
public void setTriggerBy(String triggerBy) {
this.triggerBy = triggerBy;
}
public static List<View3dRefreshAreaEum> getEumListByTrigger(String trigger) {
List<View3dRefreshAreaEum> eumList = new ArrayList<>();
for (View3dRefreshAreaEum eum : View3dRefreshAreaEum.values()) {
if (eum.getTriggerBy().contains(trigger)) {
eumList.add(eum);
}
}
return eumList;
}
public static View3dRefreshAreaEum getEumByCode(String code) {
for (View3dRefreshAreaEum eum : View3dRefreshAreaEum.values()) {
if (code.equals(eum.getCode())) {
return eum;
}
}
return null;
}
} }
package com.yeejoin.amos.fas.business.controller;
import com.yeejoin.amos.fas.business.service.intfc.IDataRefreshService;
import com.yeejoin.amos.fas.core.util.CommonResponse;
import com.yeejoin.amos.fas.core.util.CommonResponseUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author suhg
*/
@RestController
@RequestMapping("/api/data")
@Api(tags = "三维屏数据刷新api")
public class DataRefreshController {
@Autowired
private IDataRefreshService dataRefreshService;
/**
* 全景监控执行数据刷新
* @return success
*/
@ApiOperation(value = "全景监控执行数据刷新",notes = "check-巡检记录,planTask-执行数据")
@GetMapping(value = "refresh/{dataType}")
public CommonResponse checkDataRefresh(@PathVariable String dataType){
dataRefreshService.refreshViewData(dataType);
return CommonResponseUtil.success();
}
}
...@@ -8,7 +8,6 @@ import com.yeejoin.amos.fas.business.service.intfc.IExcelService; ...@@ -8,7 +8,6 @@ import com.yeejoin.amos.fas.business.service.intfc.IExcelService;
import com.yeejoin.amos.fas.business.util.FileHelper; import com.yeejoin.amos.fas.business.util.FileHelper;
import com.yeejoin.amos.fas.core.util.CommonResponse; import com.yeejoin.amos.fas.core.util.CommonResponse;
import com.yeejoin.amos.fas.core.util.CommonResponseUtil; import com.yeejoin.amos.fas.core.util.CommonResponseUtil;
import com.yeejoin.amos.fas.core.util.FileUtil;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
...@@ -19,7 +18,6 @@ import org.springframework.web.bind.annotation.*; ...@@ -19,7 +18,6 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
...@@ -72,7 +70,7 @@ public class ExcelController extends BaseController { ...@@ -72,7 +70,7 @@ public class ExcelController extends BaseController {
@ApiOperation(value = "导出数据", notes = "导出数据") @ApiOperation(value = "导出数据", notes = "导出数据")
@PostMapping(value = "/export") @PostMapping(value = "/export")
//@Authorization(ingore = true) //@Authorization(ingore = true)
public void export(HttpServletResponse response, public void export(HttpServletResponse response,
@ApiParam(value = "data:导出数据;model:导出模板", required = true) @RequestParam String exportType, @ApiParam(value = "data:导出数据;model:导出模板", required = true) @RequestParam String exportType,
@ApiParam(value = "point:监测点;equipment:设备", required = true) @RequestParam String modelName, @ApiParam(value = "point:监测点;equipment:设备", required = true) @RequestParam String modelName,
......
...@@ -14,7 +14,6 @@ import com.yeejoin.amos.fas.core.util.CommonResponseUtil; ...@@ -14,7 +14,6 @@ import com.yeejoin.amos.fas.core.util.CommonResponseUtil;
import com.yeejoin.amos.fas.dao.entity.Fmea; import com.yeejoin.amos.fas.dao.entity.Fmea;
import com.yeejoin.amos.fas.dao.entity.RiskSource; import com.yeejoin.amos.fas.dao.entity.RiskSource;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel; import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
...@@ -33,7 +32,7 @@ import java.util.List; ...@@ -33,7 +32,7 @@ import java.util.List;
@Api(tags = "风险模型api") @Api(tags = "风险模型api")
public class RiskModelController extends BaseController { public class RiskModelController extends BaseController {
private final Logger log = LoggerFactory.getLogger(RiskLevelController.class); private final Logger log = LoggerFactory.getLogger(RiskModelController.class);
@Autowired @Autowired
private IRiskSourceService riskSourceService; private IRiskSourceService riskSourceService;
......
...@@ -40,6 +40,7 @@ public class View3dController extends BaseController { ...@@ -40,6 +40,7 @@ public class View3dController extends BaseController {
public CommonResponse getRegionTree() { public CommonResponse getRegionTree() {
ReginParams reginParams =getSelectedOrgInfo(); ReginParams reginParams =getSelectedOrgInfo();
String orgCode = this.getOrgCode(reginParams); String orgCode = this.getOrgCode(reginParams);
//TODO:待删除
orgCode = "10"; orgCode = "10";
return CommonResponseUtil.success(riskSourceService.findRegionTree(orgCode)); return CommonResponseUtil.success(riskSourceService.findRegionTree(orgCode));
} }
...@@ -49,6 +50,7 @@ public class View3dController extends BaseController { ...@@ -49,6 +50,7 @@ public class View3dController extends BaseController {
public CommonResponse getRegionDetail(@PathVariable("riskSourceId") Long riskSourceId) { public CommonResponse getRegionDetail(@PathVariable("riskSourceId") Long riskSourceId) {
ReginParams reginParams =getSelectedOrgInfo(); ReginParams reginParams =getSelectedOrgInfo();
String orgCode = this.getOrgCode(reginParams); String orgCode = this.getOrgCode(reginParams);
//TODO:待删除
orgCode = "10"; orgCode = "10";
return CommonResponseUtil.success(riskSourceService.findRegionById(riskSourceId,orgCode)); return CommonResponseUtil.success(riskSourceService.findRegionById(riskSourceId,orgCode));
} }
...@@ -76,6 +78,7 @@ public class View3dController extends BaseController { ...@@ -76,6 +78,7 @@ public class View3dController extends BaseController {
if(ResourceTypeDefEnum.containsTypeCode(type)) { if(ResourceTypeDefEnum.containsTypeCode(type)) {
ReginParams reginParams =getSelectedOrgInfo(); ReginParams reginParams =getSelectedOrgInfo();
String orgCode = this.getOrgCode(reginParams); String orgCode = this.getOrgCode(reginParams);
//TODO:待删除
orgCode = "10"; orgCode = "10";
return CommonResponseUtil.success(view3dService.getPointTreeByType(type,orgCode)); return CommonResponseUtil.success(view3dService.getPointTreeByType(type,orgCode));
} }
...@@ -87,6 +90,7 @@ public class View3dController extends BaseController { ...@@ -87,6 +90,7 @@ public class View3dController extends BaseController {
public CommonResponse getPointDetail(String type,Long pointId) { public CommonResponse getPointDetail(String type,Long pointId) {
ReginParams reginParams =getSelectedOrgInfo(); ReginParams reginParams =getSelectedOrgInfo();
String orgCode = this.getOrgCode(reginParams); String orgCode = this.getOrgCode(reginParams);
//TODO:待删除
orgCode = "1*2"; orgCode = "1*2";
return CommonResponseUtil.success(view3dService.getPointDetailByTypeAndId(type,pointId,orgCode)); return CommonResponseUtil.success(view3dService.getPointDetailByTypeAndId(type,pointId,orgCode));
} }
...@@ -96,6 +100,7 @@ public class View3dController extends BaseController { ...@@ -96,6 +100,7 @@ public class View3dController extends BaseController {
public CommonResponse safetyIndexWeek(String type,Long pointId) { public CommonResponse safetyIndexWeek(String type,Long pointId) {
ReginParams reginParams =getSelectedOrgInfo(); ReginParams reginParams =getSelectedOrgInfo();
String orgCode = this.getOrgCode(reginParams); String orgCode = this.getOrgCode(reginParams);
//TODO:待删除
orgCode = "10"; orgCode = "10";
return CommonResponseUtil.success(view3dService.getSafetyIndexWeek(orgCode)); return CommonResponseUtil.success(view3dService.getSafetyIndexWeek(orgCode));
} }
...@@ -105,6 +110,7 @@ public class View3dController extends BaseController { ...@@ -105,6 +110,7 @@ public class View3dController extends BaseController {
public CommonResponse getSafetyIndexInfoByDate(@RequestParam(name = "date",required = false) String date){ public CommonResponse getSafetyIndexInfoByDate(@RequestParam(name = "date",required = false) String date){
ReginParams reginParams =getSelectedOrgInfo(); ReginParams reginParams =getSelectedOrgInfo();
String orgCode = this.getOrgCode(reginParams); String orgCode = this.getOrgCode(reginParams);
//TODO:待删除
orgCode = "1*2"; orgCode = "1*2";
return CommonResponseUtil.success(view3dService.getSafetyIndexInfoByDate(orgCode,date)); return CommonResponseUtil.success(view3dService.getSafetyIndexInfoByDate(orgCode,date));
} }
...@@ -139,6 +145,7 @@ public class View3dController extends BaseController { ...@@ -139,6 +145,7 @@ public class View3dController extends BaseController {
public CommonResponse getSafetyExecuteListTop5(@PathVariable("type")String type){ public CommonResponse getSafetyExecuteListTop5(@PathVariable("type")String type){
ReginParams reginParams =getSelectedOrgInfo(); ReginParams reginParams =getSelectedOrgInfo();
String orgCode = this.getOrgCode(reginParams); String orgCode = this.getOrgCode(reginParams);
//TODO:待删除
orgCode = "1*2"; orgCode = "1*2";
return CommonResponseUtil.success(view3dService.getSafetyExecuteListTop5(type,orgCode)); return CommonResponseUtil.success(view3dService.getSafetyExecuteListTop5(type,orgCode));
} }
...@@ -171,6 +178,7 @@ public class View3dController extends BaseController { ...@@ -171,6 +178,7 @@ public class View3dController extends BaseController {
public CommonResponse initViewNode(String type){ public CommonResponse initViewNode(String type){
ReginParams reginParams =getSelectedOrgInfo(); ReginParams reginParams =getSelectedOrgInfo();
String orgCode = this.getOrgCode(reginParams); String orgCode = this.getOrgCode(reginParams);
//TODO:待删除
orgCode = "1*2"; orgCode = "1*2";
return CommonResponseUtil.success(view3dService.initViewNode(type,orgCode)); return CommonResponseUtil.success(view3dService.initViewNode(type,orgCode));
} }
......
package com.yeejoin.amos.fas.business.service.impl;
import com.alibaba.fastjson.JSON;
import com.yeejoin.amos.fas.business.feign.RemoteWebSocketServer;
import com.yeejoin.amos.fas.business.service.intfc.IDataRefreshService;
import com.yeejoin.amos.fas.common.enums.View3dRefreshAreaEum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 数据刷新
*/
@Service("dataRefreshService")
public class DataRefreshServiceImpl implements IDataRefreshService {
private final Logger log = LoggerFactory.getLogger(DataRefreshServiceImpl.class);
@Autowired
private RemoteWebSocketServer remoteWebSocketServer;
@Override
public void refreshViewData(String dataType) {
/*
* check 巡检数据刷新(影响区域:消防安全执行、今日巡检)
* planTask 执行数据刷新(影响区域:今日巡检)
*/
Map<String,Object> param = new HashMap<>();
List<View3dRefreshAreaEum> notifyAreaList = View3dRefreshAreaEum.getEumListByTrigger(dataType);
notifyAreaList.forEach(eum->{
param.clear();
param.put("refreshType",eum.getCode());
this.notifyDataRefresh(param);
});
}
private void notifyDataRefresh(Map<String, Object> param) {
try {
remoteWebSocketServer.sendMessage("3dViewMessage", JSON.toJSONString(param));
} catch (Exception e) {
log.error("通知前端数据刷新失败-->"+JSON.toJSONString(param));
}
}
}
...@@ -21,6 +21,8 @@ import java.util.stream.Collectors; ...@@ -21,6 +21,8 @@ import java.util.stream.Collectors;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import com.yeejoin.amos.fas.business.service.intfc.*;
import com.yeejoin.amos.fas.common.enums.DataRefreshTypeEum;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
...@@ -74,10 +76,6 @@ import com.yeejoin.amos.fas.business.jpush.PushMsgParam; ...@@ -74,10 +76,6 @@ import com.yeejoin.amos.fas.business.jpush.PushMsgParam;
import com.yeejoin.amos.fas.business.param.AlarmParam; import com.yeejoin.amos.fas.business.param.AlarmParam;
import com.yeejoin.amos.fas.business.param.CommonPageInfoParam; import com.yeejoin.amos.fas.business.param.CommonPageInfoParam;
import com.yeejoin.amos.fas.business.param.FmeaBindParam; import com.yeejoin.amos.fas.business.param.FmeaBindParam;
import com.yeejoin.amos.fas.business.service.intfc.IContingencyInstance;
import com.yeejoin.amos.fas.business.service.intfc.IEquipmentService;
import com.yeejoin.amos.fas.business.service.intfc.IRiskSourceService;
import com.yeejoin.amos.fas.business.service.intfc.Node3dVoService;
import com.yeejoin.amos.fas.business.service.model.CheckInputItemRo; import com.yeejoin.amos.fas.business.service.model.CheckInputItemRo;
import com.yeejoin.amos.fas.business.service.model.ContingencyDeviceStatus; import com.yeejoin.amos.fas.business.service.model.ContingencyDeviceStatus;
import com.yeejoin.amos.fas.business.service.model.ContingencyRo; import com.yeejoin.amos.fas.business.service.model.ContingencyRo;
...@@ -226,6 +224,9 @@ public class RiskSourceServiceImpl implements IRiskSourceService { ...@@ -226,6 +224,9 @@ public class RiskSourceServiceImpl implements IRiskSourceService {
return Redis.genKey(CacheType.ERASABLE.name(), "CONTINGENCYRUNING"); return Redis.genKey(CacheType.ERASABLE.name(), "CONTINGENCYRUNING");
} }
@Autowired
private IDataRefreshService iDataRefreshService;
@Override @Override
public RiskSource editRiskSource(HashMap<String, Object> map) throws Exception { public RiskSource editRiskSource(HashMap<String, Object> map) throws Exception {
RiskSource riskSource = (RiskSource) map.get("param"); RiskSource riskSource = (RiskSource) map.get("param");
...@@ -263,7 +264,7 @@ public class RiskSourceServiceImpl implements IRiskSourceService { ...@@ -263,7 +264,7 @@ public class RiskSourceServiceImpl implements IRiskSourceService {
node3dVoService.syncData(() -> node3dVoService.incrementalCreate(Node3dVoService.DATATYPE_RISKSOURCE)); node3dVoService.syncData(() -> node3dVoService.incrementalCreate(Node3dVoService.DATATYPE_RISKSOURCE));
else else
node3dVoService.syncData(() -> node3dVoService.incrementalUpdate(Node3dVoService.DATATYPE_RISKSOURCE)); node3dVoService.syncData(() -> node3dVoService.incrementalUpdate(Node3dVoService.DATATYPE_RISKSOURCE));
iDataRefreshService.refreshViewData(DataRefreshTypeEum.rpn.getCode());
return riskSource; return riskSource;
} }
...@@ -292,7 +293,7 @@ public class RiskSourceServiceImpl implements IRiskSourceService { ...@@ -292,7 +293,7 @@ public class RiskSourceServiceImpl implements IRiskSourceService {
//同步数据 //同步数据
node3dVoService.syncData(() -> node3dVoService.incrementalRemove(Node3dVoService.DATATYPE_RISKSOURCE)); node3dVoService.syncData(() -> node3dVoService.incrementalRemove(Node3dVoService.DATATYPE_RISKSOURCE));
iDataRefreshService.refreshViewData(DataRefreshTypeEum.rpn.getCode());
} }
@Override @Override
...@@ -914,6 +915,7 @@ public class RiskSourceServiceImpl implements IRiskSourceService { ...@@ -914,6 +915,7 @@ public class RiskSourceServiceImpl implements IRiskSourceService {
RsDataQueue rsDataQueue = RsDataQueue.getInstance(); RsDataQueue rsDataQueue = RsDataQueue.getInstance();
fmeaIds.forEach(fmeaId -> rsDataQueue.addPatrolMessage(fmeaId)); fmeaIds.forEach(fmeaId -> rsDataQueue.addPatrolMessage(fmeaId));
} }
iDataRefreshService.refreshViewData(DataRefreshTypeEum.check.getCode());
//asymbleWithParent(bacthNo,riskSources, ProtalDataRo.class.getSimpleName(),protalData.getId(),protalData.getNodeState(),protalData.getOriginalNodeState(),protalData.getPointInputitems()); //asymbleWithParent(bacthNo,riskSources, ProtalDataRo.class.getSimpleName(),protalData.getId(),protalData.getNodeState(),protalData.getOriginalNodeState(),protalData.getPointInputitems());
} }
...@@ -1196,9 +1198,13 @@ public class RiskSourceServiceImpl implements IRiskSourceService { ...@@ -1196,9 +1198,13 @@ public class RiskSourceServiceImpl implements IRiskSourceService {
redisTemplate.opsForHash().put("currentContingency", "contingencyPlan", null); redisTemplate.opsForHash().put("currentContingency", "contingencyPlan", null);
redisTemplate.opsForHash().put("currentContingency", "alarmType", null); redisTemplate.opsForHash().put("currentContingency", "alarmType", null);
// redisTemplate.opsForValue().set("equipmentId", null); // redisTemplate.opsForValue().set("equipmentId", null);
//通知刷新3d页面告警数据
iDataRefreshService.refreshViewData(DataRefreshTypeEum.alarm.getCode());
} else { } else {
if ("alarm_type_trouble".equals(fireEquipmentPointType)) { if ("alarm_type_trouble".equals(fireEquipmentPointType)) {
notifyAlarm(fireEquipmentPoint, deviceData); notifyAlarm(fireEquipmentPoint, deviceData);
//通知刷新3d页面相关故障数据
iDataRefreshService.refreshViewData(DataRefreshTypeEum.trouble.getCode());
} }
String alarmType = (String) redisTemplate.opsForHash().get("currentContingency", "alarmType"); String alarmType = (String) redisTemplate.opsForHash().get("currentContingency", "alarmType");
if (!ObjectUtils.isEmpty(alarmType) && dict.getDictValue().equals(alarmType)) { if (!ObjectUtils.isEmpty(alarmType) && dict.getDictValue().equals(alarmType)) {
...@@ -1688,6 +1694,7 @@ public class RiskSourceServiceImpl implements IRiskSourceService { ...@@ -1688,6 +1694,7 @@ public class RiskSourceServiceImpl implements IRiskSourceService {
jpushRiskSourceMessage("风险点告警", jpushTarget); jpushRiskSourceMessage("风险点告警", jpushTarget);
notifyRule(riskSourceId, rpn, rpni, oldRiskLevel.getLevel(), newRiskLevel.getLevel(), notifyType); notifyRule(riskSourceId, rpn, rpni, oldRiskLevel.getLevel(), newRiskLevel.getLevel(), notifyType);
} }
iDataRefreshService.refreshViewData(DataRefreshTypeEum.rpn.getCode());
} }
private void jpushRiskSourceMessage(String content, String jpushTarget) { private void jpushRiskSourceMessage(String content, String jpushTarget) {
......
package com.yeejoin.amos.fas.business.service.intfc;
/**
* @author suhg
*/
public interface IDataRefreshService {
/**
* 数据刷新
* @param dataType 触发数据类型
*/
void refreshViewData(String dataType);
}
package com.yeejoin.amos.fas.config; package com.yeejoin.amos.fas.config;
import com.yeejoin.amos.fas.core.util.StringUtil;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
...@@ -89,7 +90,7 @@ public class Config { ...@@ -89,7 +90,7 @@ public class Config {
factory.setPort(port); factory.setPort(port);
factory.setTimeout(timeout); factory.setTimeout(timeout);
factory.setDatabase(database); factory.setDatabase(database);
factory.setPassword(password); factory.setPassword(StringUtil.isNotEmpty(password) ? password : null );
return factory; return factory;
} }
......
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