1.添加安全登录功能
2.调整部分接口
This commit is contained in:
53
pom.xml
53
pom.xml
@@ -155,6 +155,56 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.xerial</groupId>
|
||||||
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--mybatis-plus插件-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<version>3.4.3.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||||
|
<version>3.5.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.jeffreyning</groupId>
|
||||||
|
<artifactId>mybatisplus-plus</artifactId>
|
||||||
|
<version>1.5.1-RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--druid连接池-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
|
<version>1.2.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.njcn</groupId>
|
||||||
|
<artifactId>pqs-influx</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -163,9 +213,6 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
<configuration>
|
|
||||||
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package com.njcn.roma;
|
package com.njcn.roma;
|
||||||
|
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.DependsOn;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication(scanBasePackages = "com.njcn")
|
||||||
|
@MapperScan("com.njcn.roma.mapper")
|
||||||
|
@DependsOn("proxyMapperRegister")
|
||||||
public class RomaApplication {
|
public class RomaApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -6,6 +6,7 @@ import com.njcn.roma.pojo.UpSendPojo;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
@@ -78,32 +79,63 @@ public class SendCommandController {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("IOException---------------------------");
|
System.out.println("IOException---------------------------");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "执行异常";
|
return e.getMessage();
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
System.out.println("NoSuchAlgorithmException---------------------------");
|
System.out.println("NoSuchAlgorithmException---------------------------");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "执行异常";
|
return e.getMessage();
|
||||||
} catch (KeyStoreException e) {
|
} catch (KeyStoreException e) {
|
||||||
System.out.println("KeyStoreException---------------------------");
|
System.out.println("KeyStoreException---------------------------");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "执行异常";
|
return e.getMessage();
|
||||||
} catch (KeyManagementException e) {
|
} catch (KeyManagementException e) {
|
||||||
System.out.println("KeyManagementException---------------------------");
|
System.out.println("KeyManagementException---------------------------");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "执行异常";
|
return e.getMessage();
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
System.out.println("Exception---------------------------");
|
System.out.println("Exception---------------------------");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "执行异常";
|
return e.getMessage();
|
||||||
}
|
}
|
||||||
return "执行成功";
|
return "执行成功";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("test")
|
|
||||||
public String test(){
|
|
||||||
return "6666";
|
|
||||||
|
@GetMapping("queryService")
|
||||||
|
public String test(@RequestParam(value = "deviceId",defaultValue = "D2899233167kupZT")String deviceId){
|
||||||
|
//String url = "https://" + sendIp + "/iot/1.0/deviceCommands?appId=" + appId;
|
||||||
|
|
||||||
|
String url = "https://" + sendIp + "/iot/1.0/services?appId=" + appId+"&deviceId="+deviceId;
|
||||||
|
HttpGet httpGet = new HttpGet(url); //创建post请求
|
||||||
|
setSSLHeader(httpGet); //设置请求的header
|
||||||
|
try {
|
||||||
|
org.apache.http.HttpEntity responseEntity = getSSLResponse(httpGet);//获取响应结果
|
||||||
|
return EntityUtils.toString(responseEntity);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("IOException---------------------------");
|
||||||
|
e.printStackTrace();
|
||||||
|
return e.getMessage();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
System.out.println("NoSuchAlgorithmException---------------------------");
|
||||||
|
e.printStackTrace();
|
||||||
|
return e.getMessage();
|
||||||
|
} catch (KeyStoreException e) {
|
||||||
|
System.out.println("KeyStoreException---------------------------");
|
||||||
|
e.printStackTrace();
|
||||||
|
return e.getMessage();
|
||||||
|
} catch (KeyManagementException e) {
|
||||||
|
System.out.println("KeyManagementException---------------------------");
|
||||||
|
e.printStackTrace();
|
||||||
|
return e.getMessage();
|
||||||
|
}catch (Exception e){
|
||||||
|
System.out.println("Exception---------------------------");
|
||||||
|
e.printStackTrace();
|
||||||
|
return e.getMessage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,19 +1,45 @@
|
|||||||
package com.njcn.roma.controller;
|
package com.njcn.roma.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.date.DatePattern;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
||||||
|
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
|
||||||
import com.huawei.it.eip.ump.client.producer.Producer;
|
import com.huawei.it.eip.ump.client.producer.Producer;
|
||||||
import com.huawei.it.eip.ump.client.producer.SendResult;
|
import com.huawei.it.eip.ump.client.producer.SendResult;
|
||||||
import com.huawei.it.eip.ump.common.exception.UmpException;
|
import com.huawei.it.eip.ump.common.exception.UmpException;
|
||||||
import com.huawei.it.eip.ump.common.message.Message;
|
import com.huawei.it.eip.ump.common.message.Message;
|
||||||
|
import com.njcn.influx.base.InfluxDbBaseMapper;
|
||||||
|
import com.njcn.influx.imapper.DataVMapper;
|
||||||
|
import com.njcn.influx.pojo.po.DataV;
|
||||||
|
import com.njcn.influx.service.IDataVService;
|
||||||
import com.njcn.roma.client.ClientHandler;
|
import com.njcn.roma.client.ClientHandler;
|
||||||
|
import com.njcn.roma.mapper.EleEpdPqdMapper;
|
||||||
|
import com.njcn.roma.mapper.PmsHistoryDataMapper;
|
||||||
|
import com.njcn.roma.pojo.EleEpdPqd;
|
||||||
|
import com.njcn.roma.pojo.PmsHistoryDataPO;
|
||||||
import com.njcn.roma.server.WebSocketServer;
|
import com.njcn.roma.server.WebSocketServer;
|
||||||
|
import com.njcn.roma.utils.JsonValueFluctuator;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.jdbc.core.ColumnMapRowMapper;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.Map;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Random;
|
import java.math.BigDecimal;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* roma
|
* roma
|
||||||
@@ -29,6 +55,16 @@ public class TestController {
|
|||||||
|
|
||||||
private final WebSocketServer webSocketServer;
|
private final WebSocketServer webSocketServer;
|
||||||
|
|
||||||
|
public String topicMsg = "{\"HRPhV_H14_phsC\":\"0.0000\",\"HRPhV_H14_phsB\":\"0.0000\",\"HRPhV_H14_phsA\":\"0.0000\",\"HRPhV_H2_phsB\":\"0.0100\",\"HRPhV_H2_phsA\":\"0.0100\",\"HRPhV_H2_phsC\":\"0.0100\",\"HRPhV_H15_phsA\":\"0.0120\",\"TotW\":\"19771.1367\",\"HRPhV_H15_phsB\":\"0.0120\",\"HRPhV_H15_phsC\":\"0.0120\",\"FreqDev\":\"0.0000\",\"PPV_phsAB\":\"384.0318\",\"A_phsC\":\"60.7116\",\"TotPF\":\"0.4946\",\"A_phsA\":\"60.7123\",\"A_phsB\":\"60.7111\",\"PPV_phsBC\":\"383.3656\",\"HRPhV_H25_phsB\":\"0.0080\",\"HRPhV_H25_phsC\":\"0.0080\",\"HRPhV_H25_phsA\":\"0.0080\",\"DataTag\":\"0\",\"HRPhV_H20_phsA\":\"0.0000\",\"HRPhV_H20_phsB\":\"0.0000\",\"HRPhV_H20_phsC\":\"0.0000\",\"PPV_phsCA\":\"383.3637\",\"HRPhV_H3_phsB\":\"0.0640\",\"HRPhV_H3_phsC\":\"0.0640\",\"HRPhV_H9_phsC\":\"0.0220\",\"ThdPhV_phsA\":\"0.0913\",\"HRPhV_H9_phsB\":\"0.0220\",\"HRPhV_H9_phsA\":\"0.0220\",\"ThdPhV_phsB\":\"0.0913\",\"ThdPhV_phsC\":\"0.0913\",\"HRPhV_H19_phsC\":\"0.0100\",\"HRPhV_H19_phsB\":\"0.0100\",\"HRPhV_H19_phsA\":\"0.0100\",\"HRPhV_H16_phsA\":\"0.0000\",\"HRPhV_H13_phsA\":\"0.0140\",\"HRPhV_H16_phsC\":\"0.0000\",\"HRPhV_H13_phsB\":\"0.0140\",\"HRPhV_H16_phsB\":\"0.0000\",\"TotVA\":\"39977.2305\",\"HRPhV_H13_phsC\":\"0.0140\",\"HRPhV_H6_phsB\":\"0.0026\",\"HRPhV_H3_phsA\":\"0.0640\",\"HRPhV_H6_phsA\":\"0.0026\",\"HRPhV_H10_phsA\":\"0.0026\",\"HRPhV_H10_phsB\":\"0.0026\",\"HRPhV_H6_phsC\":\"0.0026\",\"HRPhV_H10_phsC\":\"0.0026\",\"ImbNgV\":\"0.0012\",\"TotVar\":\"34745.9492\",\"HRPhV_H7_phsC\":\"0.0280\",\"HRPhV_H7_phsB\":\"0.0280\",\"HRPhV_H22_phsC\":\"0.0000\",\"HRPhV_H22_phsB\":\"0.0000\",\"ImbZroV\":\"0.0012\",\"HRPhV_H22_phsA\":\"0.0000\",\"HRPhV_H7_phsA\":\"0.0280\",\"HRPhV_H8_phsA\":\"0.0026\",\"HRPhV_H23_phsB\":\"0.0080\",\"PhV_phsA\":\"221.9935\",\"HRPhV_H8_phsB\":\"0.0026\",\"HRPhV_H23_phsC\":\"0.0080\",\"HRPhV_H8_phsC\":\"0.0026\",\"PhV_phsB\":\"221.9947\",\"PhV_phsC\":\"221.9979\",\"HRPhV_H23_phsA\":\"0.0080\",\"PstPhV_phsC\":\"3.2942\",\"PstPhV_phsA\":\"3.3086\",\"PstPhV_phsB\":\"3.2987\",\"Freq\":\"50.0000\",\"HRPhV_H11_phsA\":\"0.0180\",\"HRPhV_H11_phsB\":\"0.0180\",\"HRPhV_H17_phsC\":\"0.0100\",\"HRPhV_H11_phsC\":\"0.0180\",\"HRPhV_H17_phsB\":\"0.0100\",\"HRPhV_H17_phsA\":\"0.0100\",\"SeqV_C2\":\"0.0715\",\"HRPhV_H4_phsB\":\"0.0050\",\"SeqV_C1\":\"60.4601\",\"HRPhV_H4_phsA\":\"0.0050\",\"SeqV_C0\":\"0.0714\",\"PhVDev_phsC\":\"0.0119\",\"HRPhV_H5_phsA\":\"0.0400\",\"HRPhV_H5_phsB\":\"0.0400\",\"HRPhV_H5_phsC\":\"0.0400\",\"PhVDev_phsB\":\"0.0119\",\"HRPhV_H12_phsC\":\"0.0010\",\"PltPhV_phsA\":\"0.0000\",\"PhVDev_phsA\":\"0.0119\",\"HRPhV_H12_phsB\":\"0.0010\",\"HRPhV_H4_phsC\":\"0.0050\",\"HRPhV_H18_phsB\":\"0.0000\",\"HRPhV_H18_phsC\":\"0.0000\",\"HRPhV_H12_phsA\":\"0.0010\",\"HRPhV_H18_phsA\":\"0.0000\",\"HFundPhV_phsC\":\"220.8052\",\"HRPhV_H21_phsC\":\"0.0080\",\"HRPhV_H21_phsB\":\"0.0080\",\"HRPhV_H24_phsC\":\"0.0000\",\"HFundPhV_phsA\":\"220.8056\",\"HRPhV_H21_phsA\":\"0.0080\",\"HFundPhV_phsB\":\"220.8055\",\"HRPhV_H24_phsB\":\"0.0000\",\"PltPhV_phsC\":\"0.0000\",\"HRPhV_H24_phsA\":\"0.0000\",\"PltPhV_phsB\":\"0.0000\",\"time\":\"20240816T150000Z\"}";
|
||||||
|
|
||||||
|
public String devId = "暂无数据";
|
||||||
|
|
||||||
|
private final PmsHistoryDataMapper pmsHistoryDataMapper;
|
||||||
|
|
||||||
|
private final EleEpdPqdMapper eleEpdPqdMapper;
|
||||||
|
|
||||||
|
|
||||||
|
private final IDataVService iDataVService;
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("send")
|
@GetMapping("send")
|
||||||
@@ -81,9 +117,9 @@ public class TestController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动客户端
|
* 启动客户端
|
||||||
|
*
|
||||||
* @author cdf
|
* @author cdf
|
||||||
* @date 2024/7/1
|
* @date 2024/7/1
|
||||||
*/
|
*/
|
||||||
@@ -94,27 +130,30 @@ public class TestController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("list")
|
||||||
@GetMapping("show")
|
@DS("sqlite")
|
||||||
public String show() {
|
public List<JSONObject> list(@RequestParam("startTime") String startTime, @RequestParam("endTime") String endTime, @RequestParam("devId") String devId) {
|
||||||
return clientHandler.topicMsg +" >>>>>>> "+ clientHandler.devId;
|
String sql = "select content from pms_history_data where dev_id ='" + devId + "' and time between '" + startTime + "' and '" + endTime + "'";
|
||||||
|
List<String> list = new ArrayList<>(); //= this.jdbcTemplate.queryForList(sql, String.class);
|
||||||
|
List<JSONObject> jsonObjectList = new ArrayList<>();
|
||||||
|
list.forEach(item -> jsonObjectList.add(JSONObject.parseObject(item)));
|
||||||
|
return jsonObjectList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@DS("sqlite")
|
||||||
@GetMapping("simulationWebSocket")
|
@GetMapping("simulationWebSocket")
|
||||||
public String simulationWebSocket() {
|
public String simulationWebSocket() {
|
||||||
clientHandler.devId = "NJCN230497";
|
devId = "NJCN230497";
|
||||||
// 浮动范围(比如,我们希望数值在原始值的基础上最多变化10%)
|
// 浮动范围(比如,我们希望数值在原始值的基础上最多变化10%)
|
||||||
double fluctuationRange = 0.10;
|
double fluctuationRange = 0.10;
|
||||||
|
|
||||||
// 创建Random实例
|
// 创建Random实例
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
|
|
||||||
|
for (int i = 0; i < 30; i++) {
|
||||||
|
JSONObject map = JSONObject.parseObject(topicMsg);
|
||||||
for(int i=0;i<1000;i++){
|
map.put("customDevId", devId);
|
||||||
JSONObject map = JSONObject.parseObject(clientHandler.topicMsg);
|
|
||||||
map.put("customDevId",clientHandler.devId);
|
|
||||||
double vA = Double.valueOf(map.get("PhV_phsA").toString());
|
double vA = Double.valueOf(map.get("PhV_phsA").toString());
|
||||||
double vB = Double.valueOf(map.get("PhV_phsB").toString());
|
double vB = Double.valueOf(map.get("PhV_phsB").toString());
|
||||||
double vC = Double.valueOf(map.get("PhV_phsC").toString());
|
double vC = Double.valueOf(map.get("PhV_phsC").toString());
|
||||||
@@ -135,7 +174,6 @@ public class TestController {
|
|||||||
map.put("PhV_phsC", String.valueOf(newValueC));
|
map.put("PhV_phsC", String.valueOf(newValueC));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
double iA = Double.valueOf(map.get("A_phsA").toString());
|
double iA = Double.valueOf(map.get("A_phsA").toString());
|
||||||
double iB = Double.valueOf(map.get("A_phsB").toString());
|
double iB = Double.valueOf(map.get("A_phsB").toString());
|
||||||
double iC = Double.valueOf(map.get("A_phsC").toString());
|
double iC = Double.valueOf(map.get("A_phsC").toString());
|
||||||
@@ -155,9 +193,43 @@ public class TestController {
|
|||||||
map.put("A_phsB", String.valueOf(newValueIB));
|
map.put("A_phsB", String.valueOf(newValueIB));
|
||||||
map.put("A_phsC", String.valueOf(newValueIC));
|
map.put("A_phsC", String.valueOf(newValueIC));
|
||||||
|
|
||||||
|
String time = map.get("time").toString();
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmssX");
|
||||||
|
try {
|
||||||
|
ZonedDateTime dateTime = ZonedDateTime.parse(time, formatter);
|
||||||
|
long aa = 1000 - i;
|
||||||
|
System.out.println(aa);
|
||||||
|
dateTime = dateTime.minusMinutes(aa);
|
||||||
|
String ten = dateTime.format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
|
||||||
|
System.out.println(ten);
|
||||||
|
map.put("time", ten);
|
||||||
webSocketServer.sendSocketMessageToAll(map.toJSONString());
|
webSocketServer.sendSocketMessageToAll(map.toJSONString());
|
||||||
|
|
||||||
|
//入库influxdb
|
||||||
|
List<DataV> poList = new ArrayList<>();
|
||||||
|
iDataVService.insertBatch(poList);
|
||||||
|
|
||||||
|
DataV dataV = new DataV();
|
||||||
|
Class<?> clazz = dataV.getClass();
|
||||||
|
Field timeInflux = clazz.getDeclaredField("time");
|
||||||
|
timeInflux.setAccessible(true);
|
||||||
|
timeInflux.set(dataV, dateTime.toInstant());
|
||||||
|
|
||||||
|
/* try {
|
||||||
|
PmsHistoryDataPO pmsHistoryDataPO = new PmsHistoryDataPO();
|
||||||
|
pmsHistoryDataPO.setTime(ten);
|
||||||
|
pmsHistoryDataPO.setDevId(devId);
|
||||||
|
pmsHistoryDataPO.setContent(map.toJSONString());
|
||||||
|
pmsHistoryDataMapper.insert(pmsHistoryDataPO);
|
||||||
|
//int ret = jdbcTemplate.update();
|
||||||
|
}catch (Exception e){
|
||||||
|
System.out.println("执行sql语句错误"+e.getMessage());
|
||||||
|
}*/
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
//Thread.sleep(180000);
|
//Thread.sleep(180000);
|
||||||
@@ -169,4 +241,109 @@ public class TestController {
|
|||||||
return "推送成功";
|
return "推送成功";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("simulationInfluxdb")
|
||||||
|
@DS("master")
|
||||||
|
public String simulationInfluxdb() {
|
||||||
|
List<EleEpdPqd> eleEpdPqdList = eleEpdPqdMapper.selectList(new LambdaQueryWrapper<EleEpdPqd>().eq(EleEpdPqd::getSystemType, "pms"));
|
||||||
|
Map<String,List<EleEpdPqd>> elePhaseMap = eleEpdPqdList.stream().collect(Collectors.groupingBy(EleEpdPqd::getPhase));
|
||||||
|
|
||||||
|
//Map<String, EleEpdPqd> eleEpdPqdMap = eleEpdPqdList.stream().collect(Collectors.toMap(EleEpdPqd::getName, Function.identity()));
|
||||||
|
devId = "NJCN230497";
|
||||||
|
|
||||||
|
List<DataV> poList = new ArrayList<>();
|
||||||
|
|
||||||
|
cn.hutool.json.JSONObject jsonObject = JsonValueFluctuator.fluctuateValuesInJson(topicMsg);
|
||||||
|
|
||||||
|
|
||||||
|
jsonObject.put("customDevId", devId);
|
||||||
|
elePhaseMap.forEach((phase,list)->{
|
||||||
|
|
||||||
|
Map<String,EleEpdPqd> m = list.stream().collect(Collectors.toMap(EleEpdPqd::getName,Function.identity()));
|
||||||
|
Map<String, Double> map = new HashMap<>();
|
||||||
|
m.forEach((mk,mv)->{
|
||||||
|
if(jsonObject.containsKey(mk)){
|
||||||
|
if(StrUtil.isNotBlank(mv.getOtherName())) {
|
||||||
|
map.put(mv.getOtherName(), Double.valueOf(jsonObject.get(mk).toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DataV dataV = new DataV();
|
||||||
|
BeanUtil.copyProperties(map,dataV);
|
||||||
|
|
||||||
|
dataV.setPhaseType(phase);
|
||||||
|
dataV.setLineId(jsonObject.get("customDevId").toString());
|
||||||
|
dataV.setValueType("CP95");
|
||||||
|
dataV.setQualityFlag("0");
|
||||||
|
Class<?> clazz = dataV.getClass();
|
||||||
|
Field timeInflux = null;
|
||||||
|
try {
|
||||||
|
timeInflux = clazz.getDeclaredField("time");
|
||||||
|
timeInflux.setAccessible(true);
|
||||||
|
timeInflux.set(dataV, jsonObject.get("time"));
|
||||||
|
|
||||||
|
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValueFluctuator.setNullNumberFieldsToZero(dataV);
|
||||||
|
poList.add(dataV);
|
||||||
|
|
||||||
|
});
|
||||||
|
//for (int i = 0; i < 30; i++) {
|
||||||
|
//for (int j = 0; j < 4; j++) {
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
//入库influxdb
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
iDataVService.insertBatch(poList);
|
||||||
|
/* try {
|
||||||
|
PmsHistoryDataPO pmsHistoryDataPO = new PmsHistoryDataPO();
|
||||||
|
pmsHistoryDataPO.setTime(ten);
|
||||||
|
pmsHistoryDataPO.setDevId(devId);
|
||||||
|
pmsHistoryDataPO.setContent(map.toJSONString());
|
||||||
|
pmsHistoryDataMapper.insert(pmsHistoryDataPO);
|
||||||
|
//int ret = jdbcTemplate.update();
|
||||||
|
}catch (Exception e){
|
||||||
|
System.out.println("执行sql语句错误"+e.getMessage());
|
||||||
|
}*/
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
//Thread.sleep(180000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
// }
|
||||||
|
|
||||||
|
return "推送成功";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("createTable")
|
||||||
|
public String createTable() {
|
||||||
|
String ddl = "CREATE TABLE \"pms_history_data\" (\n" +
|
||||||
|
" \"time\" text(16) NOT NULL,\n" +
|
||||||
|
" \"dev_id\" text(10) NOT NULL,\n" +
|
||||||
|
" \"content\" text NOT NULL,\n" +
|
||||||
|
" PRIMARY KEY (\"time\", \"dev_id\")\n" +
|
||||||
|
");";
|
||||||
|
|
||||||
|
return "创建pms_history_data成功";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/main/java/com/njcn/roma/mapper/EleEpdPqdMapper.java
Normal file
22
src/main/java/com/njcn/roma/mapper/EleEpdPqdMapper.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package com.njcn.roma.mapper;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.njcn.roma.pojo.EleEpdPqd;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author xuyang
|
||||||
|
* @since 2023-05-24
|
||||||
|
*/
|
||||||
|
public interface EleEpdPqdMapper extends BaseMapper<EleEpdPqd> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.njcn.roma.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.njcn.roma.pojo.PmsHistoryDataPO;
|
||||||
|
|
||||||
|
public interface PmsHistoryDataMapper extends BaseMapper<PmsHistoryDataPO> {
|
||||||
|
}
|
||||||
170
src/main/java/com/njcn/roma/pojo/EleEpdPqd.java
Normal file
170
src/main/java/com/njcn/roma/pojo/EleEpdPqd.java
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
package com.njcn.roma.pojo;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author xuyang
|
||||||
|
* @since 2023-05-24
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("ele_epd_pqd")
|
||||||
|
public class EleEpdPqd {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id
|
||||||
|
*/
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 别名
|
||||||
|
*/
|
||||||
|
private String otherName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 展示
|
||||||
|
*/
|
||||||
|
private String showName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据编号
|
||||||
|
*/
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据类型
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 相别
|
||||||
|
*/
|
||||||
|
private String phase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单位
|
||||||
|
*/
|
||||||
|
private String unit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据开始谐波次数
|
||||||
|
*/
|
||||||
|
private Integer harmStart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据结束谐波次数
|
||||||
|
*/
|
||||||
|
private Integer harmEnd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据分类,唯一类别
|
||||||
|
*/
|
||||||
|
private String classId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据统计方法,“max”“min”“avg”“cp95”
|
||||||
|
*/
|
||||||
|
private String statMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统类别(区分用能/电能)
|
||||||
|
*/
|
||||||
|
private String systemType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据类型(epd、pqd...)
|
||||||
|
*/
|
||||||
|
private String dataType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据是否上送 0:不上送 1:上送
|
||||||
|
*/
|
||||||
|
private Integer tranFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上送规则 变化:“change”周期:“period”
|
||||||
|
*/
|
||||||
|
private String tranRule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* evt的事件类别 "1"、"2"; parm的参数类别 系统参数:“sys”,运行参数:“run”,功能参数:“fun”; set的定值数据类型 “hex”“number”
|
||||||
|
*/
|
||||||
|
private String eventType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sts、di的是否存储 1:存储 0:不存储; ctrl的是否加密 1:加密 0:不加密
|
||||||
|
*/
|
||||||
|
private Integer storeFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sts、do的当前值; ctrl的是否需遥控校验 1:需要 0:不需要
|
||||||
|
*/
|
||||||
|
private Integer curSts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* do的是否可远程控制 1:是 0:否; parm的是否可修改 1:是 0:否; ctrl的是否支持自动控制 1:是 0:否
|
||||||
|
*/
|
||||||
|
private Integer ctlSts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置最大值
|
||||||
|
*/
|
||||||
|
private Double maxNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置最小值
|
||||||
|
*/
|
||||||
|
private Double minNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数为enum可设置的所有值序列
|
||||||
|
*/
|
||||||
|
private String setValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数string可设置字符串的长度上限
|
||||||
|
*/
|
||||||
|
private Integer strlen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数缺省值
|
||||||
|
*/
|
||||||
|
private String defaultValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态(0:删除 1:正常)
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 报表数据来源(mysql表名)
|
||||||
|
*/
|
||||||
|
private String resourcesId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限值名称
|
||||||
|
*/
|
||||||
|
private String limitName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限值表名
|
||||||
|
*/
|
||||||
|
private String limitTable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超标判断方式
|
||||||
|
*/
|
||||||
|
private String formula;
|
||||||
|
|
||||||
|
}
|
||||||
24
src/main/java/com/njcn/roma/pojo/PmsHistoryDataPO.java
Normal file
24
src/main/java/com/njcn/roma/pojo/PmsHistoryDataPO.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package com.njcn.roma.pojo;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("pms_history_data")
|
||||||
|
public class PmsHistoryDataPO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableField(value = "time")
|
||||||
|
private String time;
|
||||||
|
|
||||||
|
@TableField(value = "dev_id")
|
||||||
|
private String devId;
|
||||||
|
|
||||||
|
@TableField(value = "content")
|
||||||
|
private String content;
|
||||||
|
}
|
||||||
92
src/main/java/com/njcn/roma/utils/JsonValueFluctuator.java
Normal file
92
src/main/java/com/njcn/roma/utils/JsonValueFluctuator.java
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package com.njcn.roma.utils;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class JsonValueFluctuator {
|
||||||
|
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmssX");
|
||||||
|
|
||||||
|
|
||||||
|
private static final Random random = new Random();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模拟给定JSON字符串中数值属性的值上下浮动10%
|
||||||
|
* @param jsonString JSON字符串
|
||||||
|
* @return 修改后的JSON字符串
|
||||||
|
*/
|
||||||
|
public static JSONObject fluctuateValuesInJson(String jsonString) {
|
||||||
|
JSONObject jsonObject = new JSONObject(jsonString);
|
||||||
|
|
||||||
|
// 遍历JSONObject的键值对
|
||||||
|
jsonObject.keySet().forEach(key -> {
|
||||||
|
Object value = jsonObject.get(key);
|
||||||
|
if(key.equals("time")){
|
||||||
|
ZonedDateTime dateTime = ZonedDateTime.parse(value.toString(), formatter);
|
||||||
|
dateTime = dateTime.minusHours(8);
|
||||||
|
Instant instant = dateTime.toInstant();
|
||||||
|
jsonObject.put(key,instant);
|
||||||
|
}else {
|
||||||
|
// 假设只有Double类型(或可以转换为Double的)值需要变动
|
||||||
|
if (value instanceof Number) {
|
||||||
|
double numberValue = ((Number) value).doubleValue();
|
||||||
|
double fluctuatedValue = fluctuateValue(numberValue);
|
||||||
|
jsonObject.put(key, fluctuatedValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将对象中所有数字类型的null值字段设置为0(对于包装类型)
|
||||||
|
* 注意:此方法不处理基本数据类型,因为基本数据类型不能是null
|
||||||
|
*
|
||||||
|
* @param obj 要处理的对象
|
||||||
|
*/
|
||||||
|
public static void setNullNumberFieldsToZero(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Field[] fields = obj.getClass().getDeclaredFields();
|
||||||
|
for (Field field : fields) {
|
||||||
|
// 确保我们可以访问私有字段
|
||||||
|
field.setAccessible(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 检查字段是否为数字类型的包装类
|
||||||
|
if(Integer.class.isAssignableFrom(field.getType())){
|
||||||
|
field.set(obj, 0);
|
||||||
|
} else if (Number.class.isAssignableFrom(field.getType())) {
|
||||||
|
// 对于包装类型,我们可以安全地调用get和set
|
||||||
|
// 如果字段为null,则设置为0
|
||||||
|
if (field.get(obj) == null) {
|
||||||
|
field.set(obj, 0.00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// 处理反射访问异常
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对给定数值进行上下10%的随机浮动
|
||||||
|
* @param value 原始数值
|
||||||
|
* @return 浮动后的数值
|
||||||
|
*/
|
||||||
|
private static double fluctuateValue(double value) {
|
||||||
|
double factor = 1.0 + (random.nextDouble() * 0.2) - 0.1; // 随机产生0.9到1.1之间的因子
|
||||||
|
return value * factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,82 @@ spring:
|
|||||||
password: dnzl@#002
|
password: dnzl@#002
|
||||||
application:
|
application:
|
||||||
name: roma
|
name: roma
|
||||||
|
#datasource:
|
||||||
|
#type: com.zaxxer.hikari.HikariDataSource
|
||||||
|
#driver-class-name: org.sqlite.JDBC
|
||||||
|
#url: "jdbc:sqlite:D:\\pmsTest.db"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
autoconfigure:
|
||||||
|
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
|
||||||
|
datasource:
|
||||||
|
dynamic:
|
||||||
|
druid:
|
||||||
|
initial-size: 10
|
||||||
|
# 初始化大小,最小,最大
|
||||||
|
min-idle: 20
|
||||||
|
maxActive: 500
|
||||||
|
# 配置获取连接等待超时的时间
|
||||||
|
maxWait: 60000
|
||||||
|
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||||
|
timeBetweenEvictionRunsMillis: 60000
|
||||||
|
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||||
|
minEvictableIdleTimeMillis: 300000
|
||||||
|
testWhileIdle: true
|
||||||
|
testOnBorrow: true
|
||||||
|
validation-query: SELECT 1 from dual
|
||||||
|
testOnReturn: false
|
||||||
|
# 打开PSCache,并且指定每个连接上PSCache的大小
|
||||||
|
poolPreparedStatements: false
|
||||||
|
maxPoolPreparedStatementPerConnectionSize: -1
|
||||||
|
filters: stat,wall
|
||||||
|
filter:
|
||||||
|
wall:
|
||||||
|
config:
|
||||||
|
multi-statement-allow: true
|
||||||
|
none-base-statement-allow: true
|
||||||
|
enabled: true
|
||||||
|
# 配置DruidStatFilter
|
||||||
|
web-stat-filter:
|
||||||
|
enabled: true
|
||||||
|
url-pattern: "/*"
|
||||||
|
exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
|
||||||
|
# 配置DruidStatViewServlet
|
||||||
|
stat-view-servlet:
|
||||||
|
enabled: true
|
||||||
|
url-pattern: "/druid/*"
|
||||||
|
# IP白名单(没有配置或者为空,则允许所有访问)
|
||||||
|
allow: #127.0.0.1,192.168.163.1
|
||||||
|
# IP黑名单 (存在共同时,deny优先于allow)
|
||||||
|
deny: #192.168.1.73
|
||||||
|
# 禁用HTML页面上的“Reset All”功能
|
||||||
|
reset-enable: false
|
||||||
|
# 登录名
|
||||||
|
login-username: admin
|
||||||
|
# 登录密码
|
||||||
|
login-password: njcnpqs
|
||||||
|
query-timeout: 36000
|
||||||
|
primary: master
|
||||||
|
strict: false
|
||||||
|
datasource:
|
||||||
|
master:
|
||||||
|
url: jdbc:mysql://192.168.1.24:13306/pqsinfo_pmscs?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=CTT
|
||||||
|
username: root
|
||||||
|
password: njcnpqs
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
sqlite:
|
||||||
|
url: "jdbc:sqlite:D:\\pmsTest.db"
|
||||||
|
driver-class-name: org.sqlite.JDBC
|
||||||
|
type: com.alibaba.druid.pool.DruidDataSource
|
||||||
|
|
||||||
|
|
||||||
|
#influxDB内容配置
|
||||||
|
influx:
|
||||||
|
url: http://192.168.1.24:8086
|
||||||
|
user: admin
|
||||||
|
password: 123456
|
||||||
|
database: pqsinfo_pms
|
||||||
|
|
||||||
|
|
||||||
roma:
|
roma:
|
||||||
@@ -18,3 +94,10 @@ roma:
|
|||||||
appId: X_DNZLXT
|
appId: X_DNZLXT
|
||||||
appKey: IoKU7u47seGwzO4CqGmCaQ==
|
appKey: IoKU7u47seGwzO4CqGmCaQ==
|
||||||
|
|
||||||
|
|
||||||
|
#mybatis配置信息
|
||||||
|
mybatis-plus:
|
||||||
|
#别名扫描
|
||||||
|
type-aliases-package: com.njcn.roma.pojo
|
||||||
|
global-config:
|
||||||
|
enable-sql-runner: true
|
||||||
6763
src/main/resources/static/css/bootstrap/bootstrap.css
vendored
Normal file
6763
src/main/resources/static/css/bootstrap/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
src/main/resources/static/css/bootstrap/bootstrap.min.css
vendored
Normal file
6
src/main/resources/static/css/bootstrap/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1632
src/main/resources/static/css/bootstrap/docs.css
Normal file
1632
src/main/resources/static/css/bootstrap/docs.css
Normal file
File diff suppressed because it is too large
Load Diff
418
src/main/resources/static/css/datatimepicker/bootstrap-datetimepicker.css
vendored
Normal file
418
src/main/resources/static/css/datatimepicker/bootstrap-datetimepicker.css
vendored
Normal file
@@ -0,0 +1,418 @@
|
|||||||
|
/*!
|
||||||
|
* Datetimepicker for Bootstrap
|
||||||
|
*
|
||||||
|
* Copyright 2012 Stefan Petre
|
||||||
|
* Improvements by Andrew Rowls
|
||||||
|
* Licensed under the Apache License v2.0
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
.datetimepicker {
|
||||||
|
padding: 4px;
|
||||||
|
margin-top: 1px;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker-inline {
|
||||||
|
width: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker.datetimepicker-rtl {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker.datetimepicker-rtl table tr td span {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker-dropdown, .datetimepicker-dropdown-left {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class*=" datetimepicker-dropdown"]:before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
border-left: 7px solid transparent;
|
||||||
|
border-right: 7px solid transparent;
|
||||||
|
border-bottom: 7px solid #cccccc;
|
||||||
|
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class*=" datetimepicker-dropdown"]:after {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
border-bottom: 6px solid #ffffff;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class*=" datetimepicker-dropdown-top"]:before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
border-left: 7px solid transparent;
|
||||||
|
border-right: 7px solid transparent;
|
||||||
|
border-top: 7px solid #cccccc;
|
||||||
|
border-top-color: rgba(0, 0, 0, 0.2);
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class*=" datetimepicker-dropdown-top"]:after {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
border-top: 6px solid #ffffff;
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker-dropdown-bottom-left:before {
|
||||||
|
top: -7px;
|
||||||
|
right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker-dropdown-bottom-left:after {
|
||||||
|
top: -6px;
|
||||||
|
right: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker-dropdown-bottom-right:before {
|
||||||
|
top: -7px;
|
||||||
|
left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker-dropdown-bottom-right:after {
|
||||||
|
top: -6px;
|
||||||
|
left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker-dropdown-top-left:before {
|
||||||
|
bottom: -7px;
|
||||||
|
right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker-dropdown-top-left:after {
|
||||||
|
bottom: -6px;
|
||||||
|
right: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker-dropdown-top-right:before {
|
||||||
|
bottom: -7px;
|
||||||
|
left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker-dropdown-top-right:after {
|
||||||
|
bottom: -6px;
|
||||||
|
left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker > div {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker.minutes div.datetimepicker-minutes {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker.hours div.datetimepicker-hours {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker.days div.datetimepicker-days {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker.months div.datetimepicker-months {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker.years div.datetimepicker-years {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker td,
|
||||||
|
.datetimepicker th {
|
||||||
|
text-align: center;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-striped .datetimepicker table tr td,
|
||||||
|
.table-striped .datetimepicker table tr th {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td.minute:hover {
|
||||||
|
background: #eeeeee;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td.hour:hover {
|
||||||
|
background: #eeeeee;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td.day:hover {
|
||||||
|
background: #eeeeee;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td.old,
|
||||||
|
.datetimepicker table tr td.new {
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td.disabled,
|
||||||
|
.datetimepicker table tr td.disabled:hover {
|
||||||
|
background: none;
|
||||||
|
color: #999999;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td.today,
|
||||||
|
.datetimepicker table tr td.today:hover,
|
||||||
|
.datetimepicker table tr td.today.disabled,
|
||||||
|
.datetimepicker table tr td.today.disabled:hover {
|
||||||
|
background-color: #fde19a;
|
||||||
|
background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);
|
||||||
|
background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
|
||||||
|
background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);
|
||||||
|
background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);
|
||||||
|
background-image: linear-gradient(to bottom, #fdd49a, #fdf59a);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
|
||||||
|
border-color: #fdf59a #fdf59a #fbed50;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td.today:hover,
|
||||||
|
.datetimepicker table tr td.today:hover:hover,
|
||||||
|
.datetimepicker table tr td.today.disabled:hover,
|
||||||
|
.datetimepicker table tr td.today.disabled:hover:hover,
|
||||||
|
.datetimepicker table tr td.today:active,
|
||||||
|
.datetimepicker table tr td.today:hover:active,
|
||||||
|
.datetimepicker table tr td.today.disabled:active,
|
||||||
|
.datetimepicker table tr td.today.disabled:hover:active,
|
||||||
|
.datetimepicker table tr td.today.active,
|
||||||
|
.datetimepicker table tr td.today:hover.active,
|
||||||
|
.datetimepicker table tr td.today.disabled.active,
|
||||||
|
.datetimepicker table tr td.today.disabled:hover.active,
|
||||||
|
.datetimepicker table tr td.today.disabled,
|
||||||
|
.datetimepicker table tr td.today:hover.disabled,
|
||||||
|
.datetimepicker table tr td.today.disabled.disabled,
|
||||||
|
.datetimepicker table tr td.today.disabled:hover.disabled,
|
||||||
|
.datetimepicker table tr td.today[disabled],
|
||||||
|
.datetimepicker table tr td.today:hover[disabled],
|
||||||
|
.datetimepicker table tr td.today.disabled[disabled],
|
||||||
|
.datetimepicker table tr td.today.disabled:hover[disabled] {
|
||||||
|
background-color: #fdf59a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td.today:active,
|
||||||
|
.datetimepicker table tr td.today:hover:active,
|
||||||
|
.datetimepicker table tr td.today.disabled:active,
|
||||||
|
.datetimepicker table tr td.today.disabled:hover:active,
|
||||||
|
.datetimepicker table tr td.today.active,
|
||||||
|
.datetimepicker table tr td.today:hover.active,
|
||||||
|
.datetimepicker table tr td.today.disabled.active,
|
||||||
|
.datetimepicker table tr td.today.disabled:hover.active {
|
||||||
|
background-color: #fbf069;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td.active,
|
||||||
|
.datetimepicker table tr td.active:hover,
|
||||||
|
.datetimepicker table tr td.active.disabled,
|
||||||
|
.datetimepicker table tr td.active.disabled:hover {
|
||||||
|
background-color: #006dcc;
|
||||||
|
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
||||||
|
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: linear-gradient(to bottom, #0088cc, #0044cc);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
||||||
|
border-color: #0044cc #0044cc #002a80;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
color: #ffffff;
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td.active:hover,
|
||||||
|
.datetimepicker table tr td.active:hover:hover,
|
||||||
|
.datetimepicker table tr td.active.disabled:hover,
|
||||||
|
.datetimepicker table tr td.active.disabled:hover:hover,
|
||||||
|
.datetimepicker table tr td.active:active,
|
||||||
|
.datetimepicker table tr td.active:hover:active,
|
||||||
|
.datetimepicker table tr td.active.disabled:active,
|
||||||
|
.datetimepicker table tr td.active.disabled:hover:active,
|
||||||
|
.datetimepicker table tr td.active.active,
|
||||||
|
.datetimepicker table tr td.active:hover.active,
|
||||||
|
.datetimepicker table tr td.active.disabled.active,
|
||||||
|
.datetimepicker table tr td.active.disabled:hover.active,
|
||||||
|
.datetimepicker table tr td.active.disabled,
|
||||||
|
.datetimepicker table tr td.active:hover.disabled,
|
||||||
|
.datetimepicker table tr td.active.disabled.disabled,
|
||||||
|
.datetimepicker table tr td.active.disabled:hover.disabled,
|
||||||
|
.datetimepicker table tr td.active[disabled],
|
||||||
|
.datetimepicker table tr td.active:hover[disabled],
|
||||||
|
.datetimepicker table tr td.active.disabled[disabled],
|
||||||
|
.datetimepicker table tr td.active.disabled:hover[disabled] {
|
||||||
|
background-color: #0044cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td.active:active,
|
||||||
|
.datetimepicker table tr td.active:hover:active,
|
||||||
|
.datetimepicker table tr td.active.disabled:active,
|
||||||
|
.datetimepicker table tr td.active.disabled:hover:active,
|
||||||
|
.datetimepicker table tr td.active.active,
|
||||||
|
.datetimepicker table tr td.active:hover.active,
|
||||||
|
.datetimepicker table tr td.active.disabled.active,
|
||||||
|
.datetimepicker table tr td.active.disabled:hover.active {
|
||||||
|
background-color: #003399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td span {
|
||||||
|
display: block;
|
||||||
|
width: 23%;
|
||||||
|
height: 54px;
|
||||||
|
line-height: 54px;
|
||||||
|
float: left;
|
||||||
|
margin: 1%;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker .datetimepicker-hours span {
|
||||||
|
height: 26px;
|
||||||
|
line-height: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker .datetimepicker-hours table tr td span.hour_am,
|
||||||
|
.datetimepicker .datetimepicker-hours table tr td span.hour_pm {
|
||||||
|
width: 14.6%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker .datetimepicker-hours fieldset legend,
|
||||||
|
.datetimepicker .datetimepicker-minutes fieldset legend {
|
||||||
|
margin-bottom: inherit;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker .datetimepicker-minutes span {
|
||||||
|
height: 26px;
|
||||||
|
line-height: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td span:hover {
|
||||||
|
background: #eeeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td span.disabled,
|
||||||
|
.datetimepicker table tr td span.disabled:hover {
|
||||||
|
background: none;
|
||||||
|
color: #999999;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td span.active,
|
||||||
|
.datetimepicker table tr td span.active:hover,
|
||||||
|
.datetimepicker table tr td span.active.disabled,
|
||||||
|
.datetimepicker table tr td span.active.disabled:hover {
|
||||||
|
background-color: #006dcc;
|
||||||
|
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
||||||
|
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: linear-gradient(to bottom, #0088cc, #0044cc);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
||||||
|
border-color: #0044cc #0044cc #002a80;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
color: #ffffff;
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td span.active:hover,
|
||||||
|
.datetimepicker table tr td span.active:hover:hover,
|
||||||
|
.datetimepicker table tr td span.active.disabled:hover,
|
||||||
|
.datetimepicker table tr td span.active.disabled:hover:hover,
|
||||||
|
.datetimepicker table tr td span.active:active,
|
||||||
|
.datetimepicker table tr td span.active:hover:active,
|
||||||
|
.datetimepicker table tr td span.active.disabled:active,
|
||||||
|
.datetimepicker table tr td span.active.disabled:hover:active,
|
||||||
|
.datetimepicker table tr td span.active.active,
|
||||||
|
.datetimepicker table tr td span.active:hover.active,
|
||||||
|
.datetimepicker table tr td span.active.disabled.active,
|
||||||
|
.datetimepicker table tr td span.active.disabled:hover.active,
|
||||||
|
.datetimepicker table tr td span.active.disabled,
|
||||||
|
.datetimepicker table tr td span.active:hover.disabled,
|
||||||
|
.datetimepicker table tr td span.active.disabled.disabled,
|
||||||
|
.datetimepicker table tr td span.active.disabled:hover.disabled,
|
||||||
|
.datetimepicker table tr td span.active[disabled],
|
||||||
|
.datetimepicker table tr td span.active:hover[disabled],
|
||||||
|
.datetimepicker table tr td span.active.disabled[disabled],
|
||||||
|
.datetimepicker table tr td span.active.disabled:hover[disabled] {
|
||||||
|
background-color: #0044cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td span.active:active,
|
||||||
|
.datetimepicker table tr td span.active:hover:active,
|
||||||
|
.datetimepicker table tr td span.active.disabled:active,
|
||||||
|
.datetimepicker table tr td span.active.disabled:hover:active,
|
||||||
|
.datetimepicker table tr td span.active.active,
|
||||||
|
.datetimepicker table tr td span.active:hover.active,
|
||||||
|
.datetimepicker table tr td span.active.disabled.active,
|
||||||
|
.datetimepicker table tr td span.active.disabled:hover.active {
|
||||||
|
background-color: #003399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker table tr td span.old {
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker th.switch {
|
||||||
|
width: 145px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker th span.glyphicon {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker thead tr:first-child th,
|
||||||
|
.datetimepicker tfoot th {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimepicker thead tr:first-child th:hover,
|
||||||
|
.datetimepicker tfoot th:hover {
|
||||||
|
background: #eeeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-append.date .add-on i,
|
||||||
|
.input-prepend.date .add-on i,
|
||||||
|
.input-group.date .input-group-addon span {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
@@ -5,9 +5,13 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<title>稳态数据</title>
|
<title>稳态数据</title>
|
||||||
<link rel="stylesheet" href="./element.css"/>
|
<link rel="stylesheet" href="./element.css"/>
|
||||||
|
<link rel="stylesheet" href="./css/bootstrap/bootstrap.min.css" >
|
||||||
|
<link rel="stylesheet" href="./css/datatimepicker/bootstrap-datetimepicker.css">
|
||||||
<script src="./vue.js"></script>
|
<script src="./vue.js"></script>
|
||||||
<script src="./echarts.min.js"></script>
|
<script src="./echarts.min.js"></script>
|
||||||
<script src="./jquery.min.js"></script>
|
<script src="./jquery.min.js"></script>
|
||||||
|
<script src="./js/bootstrap/bootstrap-datetimepicker.js"></script>
|
||||||
|
<script src="./js/bootstrap/bootstrap-datetimepicker.zh-CN.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<div>
|
||||||
@@ -22,9 +26,22 @@
|
|||||||
<option value="NJCN230497">NJCN230447</option>
|
<option value="NJCN230497">NJCN230447</option>
|
||||||
<option value="3206010121">3206010121</option>
|
<option value="3206010121">3206010121</option>
|
||||||
</select>
|
</select>
|
||||||
|
<button id="queryRealData">查询实时数据</button>
|
||||||
|
|
||||||
|
<div style="display: inline;margin-left: 100px">
|
||||||
|
<label>时间范围</label>
|
||||||
|
<input type="text" class="form_datetime"
|
||||||
|
id="startTime" style="width: 140px">
|
||||||
|
—
|
||||||
|
<input type="text" class=" form_datetime"
|
||||||
|
id="endTime" style="width: 140px">
|
||||||
|
|
||||||
|
<button id="queryData">查询历史数据</button>
|
||||||
|
<button id="export">导出历史数据</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<button style="margin-left: 100px" id="export">导出历史数据</button>
|
|
||||||
|
|
||||||
<span style="float: right" id="stationId">xxxxxxxxxxxxxx</span>
|
<span style="float: right" id="stationId">xxxxxxxxxxxxxx</span>
|
||||||
|
|
||||||
@@ -41,6 +58,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
var webSocket;
|
||||||
|
$('.form_datetime').datetimepicker({
|
||||||
|
minView: "month", //选择日期后,不会再跳转去选择时分秒
|
||||||
|
language: 'zh-CN',
|
||||||
|
format: 'yyyy-mm-dd',
|
||||||
|
todayBtn: false,//今日按钮
|
||||||
|
autoclose: 1,
|
||||||
|
});
|
||||||
|
|
||||||
var devId;
|
var devId;
|
||||||
$(function () {
|
$(function () {
|
||||||
@@ -49,7 +74,7 @@
|
|||||||
|
|
||||||
devId = $('#selectId').find('option:selected').val()
|
devId = $('#selectId').find('option:selected').val()
|
||||||
|
|
||||||
var webSocket = getWebSocket();
|
|
||||||
initVEchart()
|
initVEchart()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -74,20 +99,33 @@
|
|||||||
|
|
||||||
$('#export').click(function () {
|
$('#export').click(function () {
|
||||||
let str = ``;
|
let str = ``;
|
||||||
if(historyMessage.length > 0){
|
|
||||||
|
|
||||||
for(let i in historyMessage[0]){
|
let startTime = $("#startTime").val()
|
||||||
|
let endTime = $("#endTime").val()
|
||||||
|
let devId = $('#selectId').find('option:selected').val()
|
||||||
|
$.ajax({
|
||||||
|
type: 'get',
|
||||||
|
dataType: "json",
|
||||||
|
url: '/list',
|
||||||
|
data: {
|
||||||
|
startTime: startTime,
|
||||||
|
endTime: endTime,
|
||||||
|
devId: devId
|
||||||
|
},
|
||||||
|
success: function (data) {
|
||||||
|
if (data) {
|
||||||
|
if (data.length > 0) {
|
||||||
|
for (let i in data[0]) {
|
||||||
str += i + ',';
|
str += i + ',';
|
||||||
}
|
}
|
||||||
str = str.substring(0, str.lastIndexOf(',')) + '\n'
|
str = str.substring(0, str.lastIndexOf(',')) + '\n'
|
||||||
|
download(str, data)
|
||||||
}else {
|
}else {
|
||||||
alert("当前无历史数据")
|
alert("没有查询到数据!")
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
download(str, historyMessage)
|
});
|
||||||
})
|
})
|
||||||
const download = (str, data) => {
|
const download = (str, data) => {
|
||||||
// 增加\t为了不让表格显示科学计数法或者其他格式
|
// 增加\t为了不让表格显示科学计数法或者其他格式
|
||||||
@@ -108,6 +146,117 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//查询实时数据
|
||||||
|
$('#queryRealData').click(function () {
|
||||||
|
realFlag = true
|
||||||
|
webSocket = getWebSocket();
|
||||||
|
})
|
||||||
|
|
||||||
|
var realFlag = true;
|
||||||
|
$('#queryData').click(function () {
|
||||||
|
realFlag = false;
|
||||||
|
|
||||||
|
if(webSocket){
|
||||||
|
webSocket.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let startTime = $("#startTime").val()
|
||||||
|
let endTime = $("#endTime").val()
|
||||||
|
let devId = $('#selectId').find('option:selected').val()
|
||||||
|
|
||||||
|
if(startTime == null || startTime == ''){
|
||||||
|
alert("请选择开始时间")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if(endTime == null || endTime == ''){
|
||||||
|
alert("请选择结束时间")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: 'get',
|
||||||
|
dataType: "json",
|
||||||
|
url: '/list',
|
||||||
|
data: {
|
||||||
|
startTime: startTime,
|
||||||
|
endTime: endTime,
|
||||||
|
devId: devId
|
||||||
|
},
|
||||||
|
success: function (data) {
|
||||||
|
|
||||||
|
if(data.length>0){
|
||||||
|
vTime = []
|
||||||
|
vA = []
|
||||||
|
vB = []
|
||||||
|
vC = []
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
iA = []
|
||||||
|
iB = []
|
||||||
|
iC = []
|
||||||
|
for(let message of data){
|
||||||
|
|
||||||
|
vTime.push(message.time)
|
||||||
|
vA.push(message.PhV_phsA)
|
||||||
|
vB.push(message.PhV_phsB)
|
||||||
|
vC.push(message.PhV_phsC)
|
||||||
|
|
||||||
|
iA.push(message.A_phsA)
|
||||||
|
iB.push(message.A_phsB)
|
||||||
|
iC.push(message.A_phsC)
|
||||||
|
}
|
||||||
|
|
||||||
|
vEchar.setOption({
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
data: vTime
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: vA
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: vB
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: vC
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
iEchar.setOption({
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
data: vTime
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: iA
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: iB
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: iC
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}else {
|
||||||
|
alert("当前时间段无数据")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
function initVEchart() {
|
function initVEchart() {
|
||||||
// 基于准备好的dom,初始化echarts实例
|
// 基于准备好的dom,初始化echarts实例
|
||||||
vEchar = echarts.init(document.getElementById('mainOne'));
|
vEchar = echarts.init(document.getElementById('mainOne'));
|
||||||
@@ -407,7 +556,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var historyMessage = []
|
//var historyMessage = []
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -417,6 +566,7 @@
|
|||||||
* 1、WebSocket客户端通过回调函数来接收服务端消息。例如:webSocket.onmessage
|
* 1、WebSocket客户端通过回调函数来接收服务端消息。例如:webSocket.onmessage
|
||||||
* 2、WebSocket客户端通过send方法来发送消息给服务端。例如:webSocket.send();
|
* 2、WebSocket客户端通过send方法来发送消息给服务端。例如:webSocket.send();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function getWebSocket() {
|
function getWebSocket() {
|
||||||
/**
|
/**
|
||||||
* 配置 WebSocket
|
* 配置 WebSocket
|
||||||
@@ -427,7 +577,6 @@
|
|||||||
* 当服务端打开连接
|
* 当服务端打开连接
|
||||||
*/
|
*/
|
||||||
webSocket.onopen = function (event) {
|
webSocket.onopen = function (event) {
|
||||||
historyMessage = []
|
|
||||||
console.log('WebSocket打开连接');
|
console.log('WebSocket打开连接');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -438,7 +587,6 @@
|
|||||||
console.log('WebSocket收到消息:%c' + event.data, 'color:green');
|
console.log('WebSocket收到消息:%c' + event.data, 'color:green');
|
||||||
//获取服务端消息
|
//获取服务端消息
|
||||||
var message = JSON.parse(event.data) || {};
|
var message = JSON.parse(event.data) || {};
|
||||||
historyMessage.push(message)
|
|
||||||
|
|
||||||
|
|
||||||
devId = $('#selectId').find('option:selected').val()
|
devId = $('#selectId').find('option:selected').val()
|
||||||
@@ -446,7 +594,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#timeId").text(message.time.substring(0, 4) + '-' + message.time.substring(4, 6) + '-' + message.time.substring(6, 8) + ' ' + message.time.substring(9, 11) + ':' + message.time.substring(11, 13) + ':' + message.time.substring(13, 15))
|
$("#timeId").text(message.time)
|
||||||
|
|
||||||
if (devId == 'NJCN230447') {
|
if (devId == 'NJCN230447') {
|
||||||
$("#stationId").text("当前位置:保定-满城区-电能质量监测装置-0447")
|
$("#stationId").text("当前位置:保定-满城区-电能质量监测装置-0447")
|
||||||
@@ -460,7 +608,7 @@
|
|||||||
} else {
|
} else {
|
||||||
$("#stationId").text("暂无数据")
|
$("#stationId").text("暂无数据")
|
||||||
}
|
}
|
||||||
if (vTime.length > 50) {
|
if (vTime.length > 100) {
|
||||||
vTime.shift();
|
vTime.shift();
|
||||||
|
|
||||||
vA.shift();
|
vA.shift();
|
||||||
@@ -471,9 +619,7 @@
|
|||||||
iC.shift();
|
iC.shift();
|
||||||
}
|
}
|
||||||
|
|
||||||
let temDate = message.time
|
vTime.push(message.time)
|
||||||
let aaaDate = temDate.substring(0, 4) + '-' + temDate.substring(4, 6) + '-' + temDate.substring(6, 8) + ' ' + temDate.substring(9, 11) + ':' + temDate.substring(11, 13) + ':' + temDate.substring(13, 15)
|
|
||||||
vTime.push(aaaDate)
|
|
||||||
vA.push(message.PhV_phsA)
|
vA.push(message.PhV_phsA)
|
||||||
vB.push(message.PhV_phsB)
|
vB.push(message.PhV_phsB)
|
||||||
vC.push(message.PhV_phsC)
|
vC.push(message.PhV_phsC)
|
||||||
@@ -546,6 +692,10 @@
|
|||||||
* 关闭连接
|
* 关闭连接
|
||||||
*/
|
*/
|
||||||
webSocket.onclose = function (event) {
|
webSocket.onclose = function (event) {
|
||||||
|
|
||||||
|
if(realFlag){
|
||||||
|
reconnect()
|
||||||
|
}
|
||||||
console.log('WebSocket关闭连接');
|
console.log('WebSocket关闭连接');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -772,6 +922,26 @@
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var limitConnect = 3; // 断线重连次数
|
||||||
|
var timeConnect = 0;
|
||||||
|
|
||||||
|
// 重连
|
||||||
|
function reconnect() {
|
||||||
|
// lockReconnect加锁,防止onclose、onerror两次重连
|
||||||
|
if (limitConnect > 0) {
|
||||||
|
limitConnect--;
|
||||||
|
timeConnect++;
|
||||||
|
console.log("第" + timeConnect + "次重连");
|
||||||
|
// 进行重连
|
||||||
|
setTimeout(function () {
|
||||||
|
getWebSocket();
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log("TCP连接已超时");
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div style="float: left">装置标识:{{data.customDevId}}</div>
|
<div style="float: left">装置标识:{{data.customDevId}}</div>
|
||||||
<div v-if="data.time" style="float: right">{{data.time.substring(0,4)+'-'+data.time.substring(4,6)+'-'+data.time.substring(6,8)+' '+data.time.substring(9,11)+':'+data.time.substring(11,13)+':'+data.time.substring(13,15)}}</div>
|
<div v-if="data.time" style="float: right">{{data.time}}</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
7
src/main/resources/static/js/bootstrap/3.3.7/bootstrap.min.js
vendored
Normal file
7
src/main/resources/static/js/bootstrap/3.3.7/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1974
src/main/resources/static/js/bootstrap/bootstrap-datetimepicker.js
vendored
Normal file
1974
src/main/resources/static/js/bootstrap/bootstrap-datetimepicker.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
16
src/main/resources/static/js/bootstrap/bootstrap-datetimepicker.zh-CN.js
vendored
Normal file
16
src/main/resources/static/js/bootstrap/bootstrap-datetimepicker.zh-CN.js
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Simplified Chinese translation for bootstrap-datetimepicker
|
||||||
|
* Yuan Cheung <advanimal@gmail.com>
|
||||||
|
*/
|
||||||
|
;(function($){
|
||||||
|
$.fn.datetimepicker.dates['zh-CN'] = {
|
||||||
|
days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
|
||||||
|
daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
|
||||||
|
daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"],
|
||||||
|
months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
||||||
|
monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
||||||
|
today: "今天",
|
||||||
|
suffix: [],
|
||||||
|
meridiem: ["上午", "下午"]
|
||||||
|
};
|
||||||
|
}(jQuery));
|
||||||
3082
src/main/resources/static/js/bootstrap/bootstrap-select.js
vendored
Normal file
3082
src/main/resources/static/js/bootstrap/bootstrap-select.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
src/main/resources/static/js/bootstrap/bootstrap.min.js
vendored
Normal file
7
src/main/resources/static/js/bootstrap/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
26
src/main/resources/static/js/bootstrap/docs.js
Normal file
26
src/main/resources/static/js/bootstrap/docs.js
Normal file
File diff suppressed because one or more lines are too long
@@ -1,13 +1,40 @@
|
|||||||
package com.njcn.roma;
|
package com.njcn.roma;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.jdbc.core.ColumnMapRowMapper;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
|
||||||
@SpringBootTest
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
class RomaApplicationTests {
|
class RomaApplicationTests {
|
||||||
|
static final Logger log = LoggerFactory.getLogger(RomaApplicationTests.class);
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contextLoads() {
|
public void test() throws Exception {
|
||||||
|
// 1、首先创建数据表
|
||||||
|
//String ddl = "CREATE TABLE `user` (id INTEGER PRIMARY KEY NOT NULL,name TEXT,create_at TEXT);";
|
||||||
|
|
||||||
|
//this.jdbcTemplate.execute(ddl);
|
||||||
|
|
||||||
|
// 2、插入一条数据
|
||||||
|
int ret = this.jdbcTemplate.update("INSERT INTO `pms_history_data` (`time`, `dev_id`, `content`) VALUES (?, ?, ?);", new Object[] {"20240704T152745Z", "NJCN230497", "{\"HRPhV_H14_phsC\":\"0.0000\",\"HRPhV_H14_phsB\":\"0.0000\",\"HRPhV_H14_phsA\":\"0.0000\",\"HRPhV_H2_phsB\":\"0.0100\",\"HRPhV_H2_phsA\":\"0.0100\",\"HRPhV_H2_phsC\":\"0.0100\",\"HRPhV_H15_phsA\":\"0.0120\",\"TotW\":\"19771.1367\",\"HRPhV_H15_phsB\":\"0.0120\",\"HRPhV_H15_phsC\":\"0.0120\",\"FreqDev\":\"0.0000\",\"PPV_phsAB\":\"384.0318\",\"A_phsC\":\"60.86038396125226\",\"TotPF\":\"0.4946\",\"A_phsA\":\"51.428441086632795\",\"A_phsB\":\"62.205840471904295\",\"PPV_phsBC\":\"383.3656\",\"HRPhV_H25_phsB\":\"0.0080\",\"HRPhV_H25_phsC\":\"0.0080\",\"HRPhV_H25_phsA\":\"0.0080\",\"DataTag\":\"0\",\"HRPhV_H20_phsA\":\"0.0000\",\"HRPhV_H20_phsB\":\"0.0000\",\"HRPhV_H20_phsC\":\"0.0000\",\"PPV_phsCA\":\"383.3637\",\"HRPhV_H3_phsB\":\"0.0640\",\"HRPhV_H3_phsC\":\"0.0640\",\"HRPhV_H9_phsC\":\"0.0220\",\"ThdPhV_phsA\":\"0.0913\",\"HRPhV_H9_phsB\":\"0.0220\",\"HRPhV_H9_phsA\":\"0.0220\",\"ThdPhV_phsB\":\"0.0913\",\"ThdPhV_phsC\":\"0.0913\",\"HRPhV_H19_phsC\":\"0.0100\",\"HRPhV_H19_phsB\":\"0.0100\",\"HRPhV_H19_phsA\":\"0.0100\",\"HRPhV_H16_phsA\":\"0.0000\",\"HRPhV_H13_phsA\":\"0.0140\",\"HRPhV_H16_phsC\":\"0.0000\",\"HRPhV_H13_phsB\":\"0.0140\",\"HRPhV_H16_phsB\":\"0.0000\",\"TotVA\":\"39977.2305\",\"HRPhV_H13_phsC\":\"0.0140\",\"HRPhV_H6_phsB\":\"0.0026\",\"HRPhV_H3_phsA\":\"0.0640\",\"HRPhV_H6_phsA\":\"0.0026\",\"HRPhV_H10_phsA\":\"0.0026\",\"HRPhV_H10_phsB\":\"0.0026\",\"HRPhV_H6_phsC\":\"0.0026\",\"HRPhV_H10_phsC\":\"0.0026\",\"ImbNgV\":\"0.0012\",\"TotVar\":\"34745.9492\",\"HRPhV_H7_phsC\":\"0.0280\",\"HRPhV_H7_phsB\":\"0.0280\",\"HRPhV_H22_phsC\":\"0.0000\",\"HRPhV_H22_phsB\":\"0.0000\",\"ImbZroV\":\"0.0012\",\"HRPhV_H22_phsA\":\"0.0000\",\"HRPhV_H7_phsA\":\"0.0280\",\"HRPhV_H8_phsA\":\"0.0026\",\"HRPhV_H23_phsB\":\"0.0080\",\"PhV_phsA\":\"223.11256669838613\",\"HRPhV_H8_phsB\":\"0.0026\",\"HRPhV_H23_phsC\":\"0.0080\",\"HRPhV_H8_phsC\":\"0.0026\",\"customDevId\":\"NJCN230497\",\"PhV_phsB\":\"211.46998705183373\",\"PhV_phsC\":\"214.58076323270137\",\"HRPhV_H23_phsA\":\"0.0080\",\"PstPhV_phsC\":\"3.2942\",\"PstPhV_phsA\":\"3.3086\",\"PstPhV_phsB\":\"3.2987\",\"Freq\":\"50.0000\",\"HRPhV_H11_phsA\":\"0.0180\",\"HRPhV_H11_phsB\":\"0.0180\",\"HRPhV_H17_phsC\":\"0.0100\",\"HRPhV_H11_phsC\":\"0.0180\",\"HRPhV_H17_phsB\":\"0.0100\",\"HRPhV_H17_phsA\":\"0.0100\",\"SeqV_C2\":\"0.0715\",\"HRPhV_H4_phsB\":\"0.0050\",\"SeqV_C1\":\"60.4601\",\"HRPhV_H4_phsA\":\"0.0050\",\"SeqV_C0\":\"0.0714\",\"PhVDev_phsC\":\"0.0119\",\"HRPhV_H5_phsA\":\"0.0400\",\"HRPhV_H5_phsB\":\"0.0400\",\"HRPhV_H5_phsC\":\"0.0400\",\"PhVDev_phsB\":\"0.0119\",\"HRPhV_H12_phsC\":\"0.0010\",\"PltPhV_phsA\":\"0.0000\",\"PhVDev_phsA\":\"0.0119\",\"HRPhV_H12_phsB\":\"0.0010\",\"HRPhV_H4_phsC\":\"0.0050\",\"HRPhV_H18_phsB\":\"0.0000\",\"HRPhV_H18_phsC\":\"0.0000\",\"HRPhV_H12_phsA\":\"0.0010\",\"HRPhV_H18_phsA\":\"0.0000\",\"HFundPhV_phsC\":\"220.8052\",\"HRPhV_H21_phsC\":\"0.0080\",\"HRPhV_H21_phsB\":\"0.0080\",\"HRPhV_H24_phsC\":\"0.0000\",\"HFundPhV_phsA\":\"220.8056\",\"HRPhV_H21_phsA\":\"0.0080\",\"HFundPhV_phsB\":\"220.8055\",\"HRPhV_H24_phsB\":\"0.0000\",\"PltPhV_phsC\":\"0.0000\",\"HRPhV_H24_phsA\":\"0.0000\",\"PltPhV_phsB\":\"0.0000\",\"time\":\"20240704T152745Z\"}"});
|
||||||
|
|
||||||
|
log.info("插入数据:{}", ret);
|
||||||
|
|
||||||
|
// 3、检索一条数据
|
||||||
|
//Map<String, Object> user = this.jdbcTemplate.queryForObject("SELECT * FROM `user` WHERE `id` = ?", new ColumnMapRowMapper(), 1L);
|
||||||
|
|
||||||
|
//log.info("检索数据:{}", user);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user