Compare commits
6 Commits
bb0e14dcfb
...
3f50e4bf2b
Author | SHA1 | Date |
---|---|---|
|
3f50e4bf2b | |
|
2a4525c2d7 | |
|
cb78214dd6 | |
|
070b9aa140 | |
|
47351f643c | |
|
0e2c1386bb |
|
@ -51,6 +51,8 @@ logs
|
|||
doc
|
||||
bin
|
||||
.github
|
||||
protocolFile
|
||||
nginx
|
||||
|
||||
ry.bat
|
||||
/LICENSE
|
|
@ -71,6 +71,7 @@
|
|||
<version>2.5.15</version>
|
||||
<configuration>
|
||||
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
|
||||
<includeSystemScope>true</includeSystemScope>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.springframework.boot.SpringApplication;
|
|||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
/**
|
||||
* 启动程序
|
||||
|
@ -12,21 +13,12 @@ import org.springframework.cache.annotation.EnableCaching;
|
|||
*/
|
||||
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
|
||||
@EnableCaching
|
||||
@EnableAsync
|
||||
public class RuoYiApplication
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// System.setProperty("spring.devtools.restart.enabled", "false");
|
||||
SpringApplication.run(RuoYiApplication.class, args);
|
||||
// System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" +
|
||||
// " .-------. ____ __ \n" +
|
||||
// " | _ _ \\ \\ \\ / / \n" +
|
||||
// " | ( ' ) | \\ _. / ' \n" +
|
||||
// " |(_ o _) / _( )_ .' \n" +
|
||||
// " | (_,_).' __ ___(_ o _)' \n" +
|
||||
// " | |\\ \\ | || |(_,_)' \n" +
|
||||
// " | | \\ `' /| `-' / \n" +
|
||||
// " | | \\ / \\ / \n" +
|
||||
// " ''-' `'-' `-..-' ");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.ruoyi.web.controller.board;
|
||||
|
||||
import com.ruoyi.board.domain.AlertPlan;
|
||||
import com.ruoyi.board.domain.dto.AlertPlanAndPlanTypeDTO;
|
||||
import com.ruoyi.board.service.IAlertPlanService;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
|
@ -34,7 +35,7 @@ public class AlertPlanController extends BaseController {
|
|||
@GetMapping("/list")
|
||||
public TableDataInfo list(AlertPlan alertPlan) {
|
||||
startPage();
|
||||
List<AlertPlan> list = alertPlanService.selectList(alertPlan);
|
||||
List<AlertPlanAndPlanTypeDTO> list = alertPlanService.listPage(alertPlan);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
|
@ -56,7 +57,7 @@ public class AlertPlanController extends BaseController {
|
|||
@PreAuthorize("@ss.hasPermi('alert:plan:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id) {
|
||||
return success(alertPlanService.getById(id));
|
||||
return success(alertPlanService.getDTOById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,9 +33,9 @@ public class BoardInfoController extends BaseController {
|
|||
*/
|
||||
@PreAuthorize("@ss.hasPermi('board:info:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(BoardInfo BoardInfo) {
|
||||
public TableDataInfo list(BoardInfo boardInfo) {
|
||||
startPage();
|
||||
List<BoardInfo> list = boardInfoService.list();
|
||||
List<BoardInfo> list = boardInfoService.listPage(boardInfo);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
package com.ruoyi.web.controller.board;
|
||||
|
||||
import com.ruoyi.board.domain.PlanType;
|
||||
import com.ruoyi.board.service.IPlanTypeService;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 计划发布中的类型Controller
|
||||
*
|
||||
* @author fuhao
|
||||
* @date 2024-09-02
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/plan/type")
|
||||
public class PlanTypeController extends BaseController {
|
||||
@Autowired
|
||||
private IPlanTypeService planTypeService;
|
||||
|
||||
/**
|
||||
* 查询计划发布中的类型列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('plan:type:list')")
|
||||
@GetMapping("/list")
|
||||
public AjaxResult list(PlanType planType) {
|
||||
List<PlanType> list = planTypeService.list();
|
||||
return success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出计划发布中的类型列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('plan:type:export')")
|
||||
@Log(title = "计划发布中的类型", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, PlanType planType) {
|
||||
List<PlanType> list = planTypeService.list();
|
||||
ExcelUtil<PlanType> util = new ExcelUtil<PlanType>(PlanType.class);
|
||||
util.exportExcel(response, list, "计划发布中的类型数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取计划发布中的类型详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('plan:type:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id) {
|
||||
return success(planTypeService.getById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增计划发布中的类型
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('plan:type:add')")
|
||||
@Log(title = "计划发布中的类型", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody PlanType planType) {
|
||||
return toAjax(planTypeService.save(planType));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改计划发布中的类型
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('plan:type:edit')")
|
||||
@Log(title = "计划发布中的类型", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody PlanType planType) {
|
||||
return toAjax(planTypeService.saveOrUpdate(planType));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除计划发布中的类型
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('plan:type:remove')")
|
||||
@Log(title = "计划发布中的类型", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable List<Integer> ids) {
|
||||
return toAjax(planTypeService.removeByIds(ids));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取类型树列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('plan:type:list')")
|
||||
@GetMapping("/planTree")
|
||||
public AjaxResult deptTree(PlanType planType) {
|
||||
return success(planTypeService.listPlanTree(planType));
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@ public class PresetContentController extends BaseController
|
|||
public TableDataInfo list(PresetContent presetContent)
|
||||
{
|
||||
startPage();
|
||||
List<PresetContent> list = presetContentService.list();
|
||||
List<PresetContent> list = presetContentService.listPage(presetContent);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,24 +1,64 @@
|
|||
package com.ruoyi.web.controller.sensor;
|
||||
|
||||
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.sm4.SM4Utils;
|
||||
import com.ruoyi.sensor.domain.PerceptionParams;
|
||||
import com.ruoyi.sensor.service.ISensorDataService;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/sensor/data")
|
||||
public class OpenSensorDataController {
|
||||
|
||||
private static final String SIGN_HEADER_NAME = "sign";
|
||||
private static final String SIGN_KEY_BASE64 = "RkYnZj5lcChmMSZQQHJFUg==";
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(OpenSensorDataController.class);
|
||||
|
||||
@Autowired
|
||||
private ISensorDataService sensorDataService;
|
||||
|
||||
@Value("${remote.sign}")
|
||||
private boolean signSwitch;
|
||||
|
||||
|
||||
@Anonymous
|
||||
@PostMapping("/judge")
|
||||
public void list(PerceptionParams perceptionParams) {
|
||||
sensorDataService.perceptionParamsHandler(perceptionParams);
|
||||
public AjaxResult list(HttpServletRequest request, @RequestBody PerceptionParams perceptionParams) {
|
||||
if (signSwitch) {
|
||||
if (!verifyRequest(request, perceptionParams.getStr())) {
|
||||
return AjaxResult.error("sign in error");
|
||||
}
|
||||
}
|
||||
sensorDataService.putPerceptionParamsToMap(perceptionParams);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
private boolean verifyRequest(HttpServletRequest request, String str) {
|
||||
byte[] keyByte = Base64.decodeBase64(SIGN_KEY_BASE64);
|
||||
String sign = request.getHeader(SIGN_HEADER_NAME);
|
||||
if (StringUtils.isEmpty(sign)) {
|
||||
log.error("Header 中没有 sign");
|
||||
return false;
|
||||
}
|
||||
// 验证是否正确
|
||||
try {
|
||||
byte[] bytes = SM4Utils.encryptData_ECB(str, keyByte);
|
||||
String base64String = Base64.encodeBase64String(bytes);
|
||||
log.info("sign:{}, base64String:{}", sign, base64String);
|
||||
return sign.equals(base64String);
|
||||
} catch (Exception e) {
|
||||
log.error("{}", e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ spring:
|
|||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
url: jdbc:mysql://192.168.2.137:33306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
# url: jdbc:mysql://mdb:3306/ry_vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
url: jdbc:mysql://192.168.2.137:33306/ry_vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: 1qaz@WSX
|
||||
# 从库数据源
|
||||
|
|
|
@ -107,15 +107,6 @@ token:
|
|||
# 令牌有效期(默认30分钟)
|
||||
expireTime: 30
|
||||
|
||||
## MyBatis配置
|
||||
#mybatis:
|
||||
# # 搜索指定包别名
|
||||
# typeAliasesPackage: com.ruoyi.**.domain
|
||||
# # 配置mapper的扫描,找到所有的mapper.xml映射文件
|
||||
# mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||
# # 加载全局的配置文件
|
||||
# configLocation: classpath:mybatis/mybatis-config.xml
|
||||
|
||||
# MyBatis Plus配置
|
||||
mybatis-plus:
|
||||
# 搜索指定包别名
|
||||
|
@ -146,3 +137,11 @@ xss:
|
|||
excludes: /system/notice
|
||||
# 匹配链接
|
||||
urlPatterns: /system/*,/monitor/*,/tool/*
|
||||
|
||||
remote:
|
||||
# 签名验证开关
|
||||
sign: false
|
||||
# 状态上报地址
|
||||
statusReport: "http://192.166.1.246:8080/status"
|
||||
# 发布记录上报地址
|
||||
logReport: "http://192.166.1.246:8080/publish_log"
|
|
@ -148,7 +148,7 @@
|
|||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
<artifactId>mybatis-plus-join-boot-starter</artifactId>
|
||||
<version>1.4.5</version>
|
||||
<version>1.4.13</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -172,4 +172,6 @@
|
|||
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
</project>
|
|
@ -163,7 +163,7 @@ public class Constants
|
|||
/**
|
||||
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
|
||||
*/
|
||||
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.quartz.task" };
|
||||
public static final String[] JOB_WHITELIST_STR = {"com.ruoyi.quartz.task", "com.ruoyi.sensor.task"};
|
||||
|
||||
/**
|
||||
* 定时任务违规的字符
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package com.ruoyi.common.core.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||
|
||||
/**
|
||||
* Treeselect树结构实体类
|
||||
|
|
|
@ -14,7 +14,7 @@ public class HttpConf
|
|||
public static int CONNECT_TIMEOUT = 10000;
|
||||
|
||||
// 读取超时时间
|
||||
public static int SO_TIMEOUT = 60000;
|
||||
public static int SO_TIMEOUT = 3000;
|
||||
|
||||
// 最大连接数
|
||||
public static int MAX_TOTAL_CONN = 200;
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
package com.ruoyi.common.utils.sm4;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 国密SM4工具类(自行实现国密SM4算法)
|
||||
* <p>有些项目中,需要单独实现国密SM4算法,
|
||||
* <p>比如:已经集成了老版本的bouncycastle,但老版本的bouncycastle无法实现国密SM4算法。但你又不能升级它,而你又需要国密SM4算法。
|
||||
*
|
||||
* <p>参考:</p>
|
||||
* <ol>
|
||||
* <li><a href="https://blog.csdn.net/sunxmwebstudy/article/details/114699704">SM4对称加密算法及Java实现</a></li>
|
||||
* <li><a href="https://www.jianshu.com/p/5ec8464b0a1b">SM4对称加密算法</a></li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>另外有开源项目实现了国密的全部算法:</p>
|
||||
* <a href="https://github.com/GmSSL/GmSSL-Java">GmSSL-Java(基于JNI)</a>
|
||||
* <a href="https://gitee.com/openeuler/bgmprovider">BGMProvider</a>
|
||||
* <a href="https://github.com/Tencent/TencentKonaSMSuite">腾讯Kona国密套件</a>
|
||||
*/
|
||||
public class SM4Utils {
|
||||
|
||||
public static byte[] encryptData_ECB(String plainText, byte[] keyBytes) throws Exception {
|
||||
SM4_Context ctx = new SM4_Context();
|
||||
ctx.isPadding = true;
|
||||
ctx.mode = SM4_Body.SM4_ENCRYPT;
|
||||
|
||||
SM4_Body sm4Body = new SM4_Body();
|
||||
sm4Body.sm4_setkey_enc(ctx, keyBytes);
|
||||
return sm4Body.sm4_crypt_ecb(ctx, plainText.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public static String decryptData_ECB(String cipherText, byte[] keyBytes) throws Exception {
|
||||
if (cipherText != null && !cipherText.trim().isEmpty()) {
|
||||
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
|
||||
Matcher m = p.matcher(cipherText);
|
||||
cipherText = m.replaceAll("");
|
||||
}
|
||||
|
||||
return decryptData_ECB(Base64.decodeBase64(cipherText),keyBytes);
|
||||
}
|
||||
|
||||
public static String decryptData_ECB(byte[] cipherByte, byte[] keyBytes) throws Exception {
|
||||
SM4_Context ctx = new SM4_Context();
|
||||
ctx.isPadding = true;
|
||||
ctx.mode = SM4_Body.SM4_DECRYPT;
|
||||
|
||||
SM4_Body sm4Body = new SM4_Body();
|
||||
sm4Body.sm4_setkey_dec(ctx, keyBytes);
|
||||
byte[] decrypted = sm4Body.sm4_crypt_ecb(ctx, cipherByte);
|
||||
return new String(decrypted, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static byte[] encryptData_CBC(String plainText, byte[] keyBytes, byte[] ivBytes) throws Exception {
|
||||
SM4_Context ctx = new SM4_Context();
|
||||
ctx.isPadding = true;
|
||||
ctx.mode = SM4_Body.SM4_ENCRYPT;
|
||||
|
||||
SM4_Body sm4Body = new SM4_Body();
|
||||
sm4Body.sm4_setkey_enc(ctx, keyBytes);
|
||||
|
||||
return sm4Body.sm4_crypt_cbc(ctx, ivBytes, plainText.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public static String decryptData_CBC(String cipherText, byte[] keyBytes, byte[] ivBytes) throws Exception {
|
||||
if (cipherText != null && !cipherText.trim().isEmpty()) {
|
||||
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
|
||||
Matcher m = p.matcher(cipherText);
|
||||
cipherText = m.replaceAll("");
|
||||
}
|
||||
|
||||
return decryptData_CBC(Base64.decodeBase64(cipherText),keyBytes,ivBytes);
|
||||
}
|
||||
|
||||
public static String decryptData_CBC(byte[] cipherByte, byte[] keyBytes, byte[] ivBytes) throws Exception {
|
||||
SM4_Context ctx = new SM4_Context();
|
||||
ctx.isPadding = true;
|
||||
ctx.mode = SM4_Body.SM4_DECRYPT;
|
||||
|
||||
SM4_Body sm4Body = new SM4_Body();
|
||||
sm4Body.sm4_setkey_dec(ctx, keyBytes);
|
||||
|
||||
byte[] decrypted = sm4Body.sm4_crypt_cbc(ctx, ivBytes, cipherByte);
|
||||
|
||||
return new String(decrypted, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String plainText = "abc";
|
||||
// key 16 位字符串
|
||||
String key = "UVMxWFBaZXVSNm9YVTU0dg==";
|
||||
byte[] keyByte = Base64.decodeBase64(key);
|
||||
|
||||
System.out.println("ECB模式加密");
|
||||
byte[] cipherTextByte = SM4Utils.encryptData_ECB(plainText, keyByte);
|
||||
String cipherText = Base64.encodeBase64String(cipherTextByte);
|
||||
System.out.println("密文: " + cipherText);//qtu7LHVpilXxaz8mPW1VjQ==
|
||||
String plainText2 = SM4Utils.decryptData_ECB(cipherText, keyByte);
|
||||
System.out.println("解密: " + plainText2);
|
||||
|
||||
System.out.println("CBC模式加密");
|
||||
String iv = "3131313131313131";
|
||||
//byte[] ivByte = Base64.decodeBase64(iv);
|
||||
byte[] ivByte = iv.getBytes();
|
||||
|
||||
byte[] cipherText2Byte = SM4Utils.encryptData_CBC(plainText,keyByte,ivByte);
|
||||
String cipherText2 = Base64.encodeBase64String(cipherText2Byte);
|
||||
System.out.println("加密密文: " + cipherText2);
|
||||
String plainText3 = SM4Utils.decryptData_CBC(cipherText2Byte,keyByte,ivByte);
|
||||
System.out.println("解密明文: " + plainText3);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,338 @@
|
|||
package com.ruoyi.common.utils.sm4;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 自行实现国密SM4算法
|
||||
*/
|
||||
public class SM4_Body {
|
||||
public static final int SM4_ENCRYPT = 1;
|
||||
|
||||
public static final int SM4_DECRYPT = 0;
|
||||
|
||||
private long GET_ULONG_BE(byte[] b, int i) {
|
||||
long n = (long) (b[i] & 0xff) << 24 | (long) ((b[i + 1] & 0xff) << 16) | (long) ((b[i + 2] & 0xff) << 8) | (long) (b[i + 3] & 0xff) & 0xffffffffL;
|
||||
return n;
|
||||
}
|
||||
|
||||
private void PUT_ULONG_BE(long n, byte[] b, int i) {
|
||||
b[i] = (byte) (int) (0xFF & n >> 24);
|
||||
b[i + 1] = (byte) (int) (0xFF & n >> 16);
|
||||
b[i + 2] = (byte) (int) (0xFF & n >> 8);
|
||||
b[i + 3] = (byte) (int) (0xFF & n);
|
||||
}
|
||||
|
||||
private long SHL(long x, int n) {
|
||||
return (x & 0xFFFFFFFF) << n;
|
||||
}
|
||||
|
||||
private long ROTL(long x, int n) {
|
||||
return SHL(x, n) | x >> (32 - n);
|
||||
}
|
||||
|
||||
private void SWAP(long[] sk, int i) {
|
||||
long t = sk[i];
|
||||
sk[i] = sk[(31 - i)];
|
||||
sk[(31 - i)] = t;
|
||||
}
|
||||
|
||||
//S 盒
|
||||
public static final byte[] SboxTable = {(byte) 0xd6, (byte) 0x90, (byte) 0xe9, (byte) 0xfe,
|
||||
(byte) 0xcc, (byte) 0xe1, 0x3d, (byte) 0xb7, 0x16, (byte) 0xb6,
|
||||
0x14, (byte) 0xc2, 0x28, (byte) 0xfb, 0x2c, 0x05, 0x2b, 0x67,
|
||||
(byte) 0x9a, 0x76, 0x2a, (byte) 0xbe, 0x04, (byte) 0xc3,
|
||||
(byte) 0xaa, 0x44, 0x13, 0x26, 0x49, (byte) 0x86, 0x06,
|
||||
(byte) 0x99, (byte) 0x9c, 0x42, 0x50, (byte) 0xf4, (byte) 0x91,
|
||||
(byte) 0xef, (byte) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43,
|
||||
(byte) 0xed, (byte) 0xcf, (byte) 0xac, 0x62, (byte) 0xe4,
|
||||
(byte) 0xb3, 0x1c, (byte) 0xa9, (byte) 0xc9, 0x08, (byte) 0xe8,
|
||||
(byte) 0x95, (byte) 0x80, (byte) 0xdf, (byte) 0x94, (byte) 0xfa,
|
||||
0x75, (byte) 0x8f, 0x3f, (byte) 0xa6, 0x47, 0x07, (byte) 0xa7,
|
||||
(byte) 0xfc, (byte) 0xf3, 0x73, 0x17, (byte) 0xba, (byte) 0x83,
|
||||
0x59, 0x3c, 0x19, (byte) 0xe6, (byte) 0x85, 0x4f, (byte) 0xa8,
|
||||
0x68, 0x6b, (byte) 0x81, (byte) 0xb2, 0x71, 0x64, (byte) 0xda,
|
||||
(byte) 0x8b, (byte) 0xf8, (byte) 0xeb, 0x0f, 0x4b, 0x70, 0x56,
|
||||
(byte) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (byte) 0xd1,
|
||||
(byte) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (byte) 0x87,
|
||||
(byte) 0xd4, 0x00, 0x46, 0x57, (byte) 0x9f, (byte) 0xd3, 0x27,
|
||||
0x52, 0x4c, 0x36, 0x02, (byte) 0xe7, (byte) 0xa0, (byte) 0xc4,
|
||||
(byte) 0xc8, (byte) 0x9e, (byte) 0xea, (byte) 0xbf, (byte) 0x8a,
|
||||
(byte) 0xd2, 0x40, (byte) 0xc7, 0x38, (byte) 0xb5, (byte) 0xa3,
|
||||
(byte) 0xf7, (byte) 0xf2, (byte) 0xce, (byte) 0xf9, 0x61, 0x15,
|
||||
(byte) 0xa1, (byte) 0xe0, (byte) 0xae, 0x5d, (byte) 0xa4,
|
||||
(byte) 0x9b, 0x34, 0x1a, 0x55, (byte) 0xad, (byte) 0x93, 0x32,
|
||||
0x30, (byte) 0xf5, (byte) 0x8c, (byte) 0xb1, (byte) 0xe3, 0x1d,
|
||||
(byte) 0xf6, (byte) 0xe2, 0x2e, (byte) 0x82, 0x66, (byte) 0xca,
|
||||
0x60, (byte) 0xc0, 0x29, 0x23, (byte) 0xab, 0x0d, 0x53, 0x4e, 0x6f,
|
||||
(byte) 0xd5, (byte) 0xdb, 0x37, 0x45, (byte) 0xde, (byte) 0xfd,
|
||||
(byte) 0x8e, 0x2f, 0x03, (byte) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b,
|
||||
0x51, (byte) 0x8d, 0x1b, (byte) 0xaf, (byte) 0x92, (byte) 0xbb,
|
||||
(byte) 0xdd, (byte) 0xbc, 0x7f, 0x11, (byte) 0xd9, 0x5c, 0x41,
|
||||
0x1f, 0x10, 0x5a, (byte) 0xd8, 0x0a, (byte) 0xc1, 0x31,
|
||||
(byte) 0x88, (byte) 0xa5, (byte) 0xcd, 0x7b, (byte) 0xbd, 0x2d,
|
||||
0x74, (byte) 0xd0, 0x12, (byte) 0xb8, (byte) 0xe5, (byte) 0xb4,
|
||||
(byte) 0xb0, (byte) 0x89, 0x69, (byte) 0x97, 0x4a, 0x0c,
|
||||
(byte) 0x96, 0x77, 0x7e, 0x65, (byte) 0xb9, (byte) 0xf1, 0x09,
|
||||
(byte) 0xc5, 0x6e, (byte) 0xc6, (byte) 0x84, 0x18, (byte) 0xf0,
|
||||
0x7d, (byte) 0xec, 0x3a, (byte) 0xdc, 0x4d, 0x20, 0x79,
|
||||
(byte) 0xee, 0x5f, 0x3e, (byte) 0xd7, (byte) 0xcb, 0x39, 0x48};
|
||||
|
||||
public static final int[] FK = {0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc};
|
||||
|
||||
public static final int[] CK = {0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
|
||||
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
|
||||
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
|
||||
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
|
||||
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
|
||||
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
|
||||
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
|
||||
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279};
|
||||
|
||||
private byte sm4Sbox(byte inch) {
|
||||
int i = inch & 0xFF;
|
||||
return SboxTable[i];
|
||||
}
|
||||
|
||||
private long sm4Lt(long ka) {
|
||||
long bb = 0L;
|
||||
long c = 0L;
|
||||
byte[] a = new byte[4];
|
||||
byte[] b = new byte[4];
|
||||
PUT_ULONG_BE(ka, a, 0);
|
||||
b[0] = sm4Sbox(a[0]);
|
||||
b[1] = sm4Sbox(a[1]);
|
||||
b[2] = sm4Sbox(a[2]);
|
||||
b[3] = sm4Sbox(a[3]);
|
||||
bb = GET_ULONG_BE(b, 0);
|
||||
c = bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24);
|
||||
return c;
|
||||
}
|
||||
|
||||
private long sm4F(long x0, long x1, long x2, long x3, long rk) {
|
||||
return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);
|
||||
}
|
||||
|
||||
private long sm4CalciRK(long ka) {
|
||||
long bb = 0L;
|
||||
long rk = 0L;
|
||||
byte[] a = new byte[4];
|
||||
byte[] b = new byte[4];
|
||||
PUT_ULONG_BE(ka, a, 0);
|
||||
b[0] = sm4Sbox(a[0]);
|
||||
b[1] = sm4Sbox(a[1]);
|
||||
b[2] = sm4Sbox(a[2]);
|
||||
b[3] = sm4Sbox(a[3]);
|
||||
bb = GET_ULONG_BE(b, 0);
|
||||
rk = bb ^ ROTL(bb, 13) ^ ROTL(bb, 23);
|
||||
return rk;
|
||||
}
|
||||
|
||||
private void sm4_setkey(long[] SK, byte[] key) {
|
||||
long[] MK = new long[4];
|
||||
long[] k = new long[36];
|
||||
int i = 0;
|
||||
MK[0] = GET_ULONG_BE(key, 0);
|
||||
MK[1] = GET_ULONG_BE(key, 4);
|
||||
MK[2] = GET_ULONG_BE(key, 8);
|
||||
MK[3] = GET_ULONG_BE(key, 12);
|
||||
k[0] = MK[0] ^ (long) FK[0];
|
||||
k[1] = MK[1] ^ (long) FK[1];
|
||||
k[2] = MK[2] ^ (long) FK[2];
|
||||
k[3] = MK[3] ^ (long) FK[3];
|
||||
for (; i < 32; i++) {
|
||||
k[(i + 4)] = (k[i] ^ sm4CalciRK(k[(i + 1)] ^ k[(i + 2)] ^ k[(i + 3)] ^ (long) CK[i]));
|
||||
SK[i] = k[(i + 4)];
|
||||
}
|
||||
}
|
||||
|
||||
private void sm4_one_round(long[] sk, byte[] input, byte[] output) {
|
||||
int i = 0;
|
||||
long[] ulbuf = new long[36];
|
||||
ulbuf[0] = GET_ULONG_BE(input, 0);
|
||||
ulbuf[1] = GET_ULONG_BE(input, 4);
|
||||
ulbuf[2] = GET_ULONG_BE(input, 8);
|
||||
ulbuf[3] = GET_ULONG_BE(input, 12);
|
||||
while (i < 32) {
|
||||
ulbuf[(i + 4)] = sm4F(ulbuf[i], ulbuf[(i + 1)], ulbuf[(i + 2)], ulbuf[(i + 3)], sk[i]);
|
||||
i++;
|
||||
}
|
||||
PUT_ULONG_BE(ulbuf[35], output, 0);
|
||||
PUT_ULONG_BE(ulbuf[34], output, 4);
|
||||
PUT_ULONG_BE(ulbuf[33], output, 8);
|
||||
PUT_ULONG_BE(ulbuf[32], output, 12);
|
||||
}
|
||||
|
||||
public static byte[] PKCS5Padding(byte[] inputByte) {
|
||||
// 获字节长度
|
||||
int length = inputByte.length;
|
||||
// 补齐位数
|
||||
int leftLength = 16 - (length % 16);
|
||||
// 定义新字节
|
||||
byte[] arrayReturn = new byte[length + leftLength];
|
||||
// 定义填充字节
|
||||
byte[] plusbyte = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||
0x0f,0x10 };
|
||||
// 不满足16倍数自动填充
|
||||
for (int i = 0; i < length + leftLength; i++) {
|
||||
if (i < length) {
|
||||
// 赋值
|
||||
arrayReturn[i] = inputByte[i];
|
||||
} else {
|
||||
// 补齐位数
|
||||
arrayReturn[i] = (byte)leftLength;
|
||||
}
|
||||
}
|
||||
|
||||
return arrayReturn;
|
||||
}
|
||||
|
||||
public static byte[] PKCS7PaddingRestore(byte[] paramArray) {
|
||||
//try {
|
||||
// 定义是否需要消除填充数据
|
||||
//boolean needRestore = true;
|
||||
int length = paramArray.length;// 获取字节长度
|
||||
// 拆分并获取最后一组16倍数数值
|
||||
byte[] paramByteLast = Arrays.copyOfRange(paramArray, length - 16, length);
|
||||
// 获取最后一个字节
|
||||
byte byteLast = paramByteLast[paramByteLast.length - 1];
|
||||
|
||||
return Arrays.copyOfRange(paramArray,0,length-byteLast);
|
||||
}
|
||||
|
||||
//修改了填充模式,为模式
|
||||
private byte[] padding(byte[] input, int mode) {
|
||||
byte[] ret = (byte[]) null;
|
||||
if (mode == SM4_ENCRYPT) {
|
||||
ret = PKCS5Padding(input);
|
||||
} else {
|
||||
ret = PKCS7PaddingRestore(input);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void sm4_setkey_enc(SM4_Context ctx, byte[] key) throws RuntimeException{
|
||||
if (ctx == null) {
|
||||
throw new RuntimeException("ctx is null!");
|
||||
}
|
||||
|
||||
if (key == null || key.length != 16) {
|
||||
throw new RuntimeException("key error!");
|
||||
}
|
||||
|
||||
ctx.mode = SM4_ENCRYPT;
|
||||
sm4_setkey(ctx.sk, key);
|
||||
}
|
||||
|
||||
public void sm4_setkey_dec(SM4_Context ctx, byte[] key) throws RuntimeException {
|
||||
if (ctx == null) {
|
||||
throw new RuntimeException("ctx is null!");
|
||||
}
|
||||
|
||||
if (key == null || key.length != 16) {
|
||||
throw new RuntimeException("key error!");
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
ctx.mode = SM4_DECRYPT;
|
||||
sm4_setkey(ctx.sk, key);
|
||||
for (i = 0; i < 16; i++) {
|
||||
SWAP(ctx.sk, i);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] sm4_crypt_ecb(SM4_Context ctx, byte[] input) throws RuntimeException, IOException {
|
||||
if (input == null) {
|
||||
throw new RuntimeException("input is null!");
|
||||
}
|
||||
|
||||
if ((ctx.isPadding) && (ctx.mode == SM4_ENCRYPT)) {
|
||||
input = padding(input, SM4_ENCRYPT);
|
||||
}
|
||||
|
||||
byte[] output = null;
|
||||
try(ByteArrayInputStream bins = new ByteArrayInputStream(input);
|
||||
ByteArrayOutputStream bous = new ByteArrayOutputStream();) {
|
||||
int length = input.length;
|
||||
|
||||
for (; length > 0; length -= 16) {
|
||||
byte[] in = new byte[16];
|
||||
byte[] out = new byte[16];
|
||||
bins.read(in);
|
||||
sm4_one_round(ctx.sk, in, out);
|
||||
bous.write(out);
|
||||
}
|
||||
|
||||
output = bous.toByteArray();
|
||||
if (ctx.isPadding && ctx.mode == SM4_DECRYPT) {
|
||||
output = padding(output, SM4_DECRYPT);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public byte[] sm4_crypt_cbc(SM4_Context ctx, byte[] iv, byte[] input) throws RuntimeException, IOException {
|
||||
if (iv == null || iv.length != 16) {
|
||||
throw new RuntimeException("iv error!");
|
||||
}
|
||||
|
||||
if (input == null) {
|
||||
throw new RuntimeException("input is null!");
|
||||
}
|
||||
|
||||
byte[] tempIv = new byte[iv.length];//防止iv被改变
|
||||
System.arraycopy(iv, 0, tempIv, 0, iv.length);
|
||||
|
||||
if (ctx.isPadding && ctx.mode == SM4_ENCRYPT) {
|
||||
input = padding(input, SM4_ENCRYPT);
|
||||
}
|
||||
|
||||
byte[] output = null;
|
||||
try(ByteArrayInputStream bins = new ByteArrayInputStream(input);
|
||||
ByteArrayOutputStream bous = new ByteArrayOutputStream();) {
|
||||
|
||||
int i = 0;
|
||||
int length = input.length;
|
||||
if (ctx.mode == SM4_ENCRYPT) {
|
||||
for (; length > 0; length -= 16) {
|
||||
byte[] in = new byte[16];
|
||||
byte[] out = new byte[16];
|
||||
byte[] out1 = new byte[16];
|
||||
|
||||
bins.read(in);
|
||||
for (i = 0; i < 16; i++) {
|
||||
out[i] = ((byte) (in[i] ^ tempIv[i]));
|
||||
}
|
||||
sm4_one_round(ctx.sk, out, out1);
|
||||
System.arraycopy(out1, 0, tempIv, 0, 16);
|
||||
bous.write(out1);
|
||||
}
|
||||
} else {
|
||||
byte[] temp = new byte[16];
|
||||
for (; length > 0; length -= 16) {
|
||||
byte[] in = new byte[16];
|
||||
byte[] out = new byte[16];
|
||||
byte[] out1 = new byte[16];
|
||||
|
||||
bins.read(in);
|
||||
System.arraycopy(in, 0, temp, 0, 16);
|
||||
sm4_one_round(ctx.sk, in, out);
|
||||
for (i = 0; i < 16; i++) {
|
||||
out1[i] = ((byte) (out[i] ^ tempIv[i]));
|
||||
}
|
||||
System.arraycopy(temp, 0, tempIv, 0, 16);
|
||||
bous.write(out1);
|
||||
}
|
||||
}
|
||||
|
||||
output = bous.toByteArray();
|
||||
if (ctx.isPadding && ctx.mode == SM4_DECRYPT) {
|
||||
output = padding(output, SM4_DECRYPT);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.ruoyi.common.utils.sm4;
|
||||
|
||||
public class SM4_Context {
|
||||
|
||||
/**
|
||||
* 模式(0:解密,1:加密)
|
||||
*/
|
||||
public int mode;
|
||||
|
||||
/**
|
||||
* 是否填充
|
||||
*/
|
||||
public boolean isPadding;
|
||||
|
||||
public long[] sk;
|
||||
|
||||
|
||||
public SM4_Context(){
|
||||
this.mode = 1;
|
||||
this.isPadding = true;
|
||||
this.sk = new long[32];//以字(32位)为单位进行加密运算
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,9 @@
|
|||
package com.ruoyi.framework.config;
|
||||
|
||||
import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
|
||||
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
|
||||
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
|
||||
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
@ -16,10 +20,6 @@ import org.springframework.security.web.SecurityFilterChain;
|
|||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
|
||||
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
|
||||
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
|
||||
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
|
||||
|
||||
/**
|
||||
* spring security配置
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package com.ruoyi.board.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
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;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 计划发布中的类型对象 pub_plan_type
|
||||
*
|
||||
* @author fuhao
|
||||
* @date 2024-09-02
|
||||
*/
|
||||
@Data
|
||||
@TableName(value = "pub_plan_type")
|
||||
public class PlanType implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 唯一标识
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** 类型名称 */
|
||||
@TableField(value = "type_name")
|
||||
private String typeName;
|
||||
|
||||
/** 类型父级id */
|
||||
@TableField(value = "parent_id")
|
||||
private Long parentId;
|
||||
|
||||
@TableField(select = false)
|
||||
private List<PlanType> children = new ArrayList<>();
|
||||
}
|
|
@ -42,4 +42,10 @@ public class ReleaseRecord {
|
|||
*/
|
||||
@TableField(value = "created_by")
|
||||
private Integer createdBy;
|
||||
|
||||
/**
|
||||
* 预警计划级别
|
||||
*/
|
||||
@TableField(value = "plan_id")
|
||||
private Integer planId;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.ruoyi.board.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class AlertPlanAndPlanTypeDTO {
|
||||
/**
|
||||
* 主键自增
|
||||
*/
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
private String typeName;
|
||||
|
||||
|
||||
/**
|
||||
* 等级
|
||||
*/
|
||||
private Integer level;
|
||||
|
||||
/**
|
||||
* 最大值
|
||||
*/
|
||||
private BigDecimal maxValue;
|
||||
|
||||
/**
|
||||
* 最小值
|
||||
*/
|
||||
private BigDecimal minValue;
|
||||
|
||||
/**
|
||||
* 显示内容
|
||||
*/
|
||||
private String displayContent;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.ruoyi.board.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class ReleaseRecordAndPresetContentDTO {
|
||||
|
||||
/**
|
||||
* 主键自增
|
||||
*/
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 情报板ID
|
||||
*/
|
||||
private Integer boardId;
|
||||
|
||||
/**
|
||||
* 预置信息ID
|
||||
*/
|
||||
private Integer presetContentId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 信息类型
|
||||
*/
|
||||
private Integer infoType;
|
||||
|
||||
/**
|
||||
* 预警计划级别
|
||||
*/
|
||||
private Integer presetContentLevel;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.ruoyi.board.mapper;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseMapper;
|
||||
import com.ruoyi.board.domain.PlanType;
|
||||
|
||||
public interface PlanTypeMapper extends MPJBaseMapper<PlanType> {
|
||||
}
|
|
@ -2,12 +2,15 @@ package com.ruoyi.board.service;
|
|||
|
||||
import com.github.yulichang.base.MPJBaseService;
|
||||
import com.ruoyi.board.domain.AlertPlan;
|
||||
import com.ruoyi.board.domain.dto.AlertPlanAndPlanTypeDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IAlertPlanService extends MPJBaseService<AlertPlan> {
|
||||
|
||||
List<AlertPlan> selectList(AlertPlan alertPlan);
|
||||
List<AlertPlanAndPlanTypeDTO> listPage(AlertPlan alertPlan);
|
||||
|
||||
AlertPlan getOneByTypeAndValue(Integer type, Double value);
|
||||
|
||||
AlertPlanAndPlanTypeDTO getDTOById(Long id);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,11 @@ package com.ruoyi.board.service;
|
|||
import com.github.yulichang.base.MPJBaseService;
|
||||
import com.ruoyi.board.domain.BoardInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IBoardInfoService extends MPJBaseService<BoardInfo> {
|
||||
|
||||
BoardInfo getOneByIP(String ip);
|
||||
|
||||
List<BoardInfo> listPage(BoardInfo boardInfo);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package com.ruoyi.board.service;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseService;
|
||||
import com.ruoyi.board.domain.PlanType;
|
||||
import com.ruoyi.common.core.domain.TreeSelect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IPlanTypeService extends MPJBaseService<PlanType>{
|
||||
|
||||
List<TreeSelect> listPlanTree(PlanType planType);
|
||||
}
|
|
@ -3,7 +3,11 @@ package com.ruoyi.board.service;
|
|||
import com.github.yulichang.base.MPJBaseService;
|
||||
import com.ruoyi.board.domain.PresetContent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IPresetContentService extends MPJBaseService<PresetContent> {
|
||||
|
||||
PresetContent getOneByContentAndBoardSize(String content, String boardSize, Integer type);
|
||||
|
||||
List<PresetContent> listPage(PresetContent presetContent);
|
||||
}
|
||||
|
|
|
@ -2,8 +2,13 @@ package com.ruoyi.board.service;
|
|||
|
||||
import com.github.yulichang.base.MPJBaseService;
|
||||
import com.ruoyi.board.domain.ReleaseRecord;
|
||||
import com.ruoyi.board.domain.dto.ReleaseRecordAndPresetContentDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IReleaseRecordService extends MPJBaseService<ReleaseRecord> {
|
||||
|
||||
ReleaseRecord getOneLatestByBoardId(String boardId, Integer type);
|
||||
List<ReleaseRecordAndPresetContentDTO> listLatest2minRecordDtoByBoardId(Integer boardId);
|
||||
|
||||
List<ReleaseRecord> listLatest2minRecordByBoardId(Integer boardId);
|
||||
}
|
||||
|
|
|
@ -2,23 +2,32 @@ package com.ruoyi.board.service.impl;
|
|||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.github.yulichang.base.MPJBaseServiceImpl;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import com.ruoyi.board.domain.AlertPlan;
|
||||
import com.ruoyi.board.domain.PlanType;
|
||||
import com.ruoyi.board.domain.dto.AlertPlanAndPlanTypeDTO;
|
||||
import com.ruoyi.board.mapper.AlertPlanMapper;
|
||||
import com.ruoyi.board.service.IAlertPlanService;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class AlertPlanServiceImpl extends MPJBaseServiceImpl<AlertPlanMapper, AlertPlan> implements IAlertPlanService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AlertPlanServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public List<AlertPlan> selectList(AlertPlan alertPlan) {
|
||||
LambdaQueryWrapper<AlertPlan> alertPlanLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
alertPlanLambdaQueryWrapper.eq(ObjectUtils.isNotEmpty(alertPlan.getType()), AlertPlan::getType, alertPlan.getType());
|
||||
alertPlanLambdaQueryWrapper.eq(ObjectUtils.isNotEmpty(alertPlan.getLevel()), AlertPlan::getLevel, alertPlan.getLevel());
|
||||
return list(alertPlanLambdaQueryWrapper);
|
||||
public List<AlertPlanAndPlanTypeDTO> listPage(AlertPlan alertPlan) {
|
||||
MPJLambdaWrapper<AlertPlan> eq = new MPJLambdaWrapper<AlertPlan>()
|
||||
.selectAll(AlertPlan.class)
|
||||
.select(PlanType::getTypeName)
|
||||
.leftJoin(PlanType.class, PlanType::getId, AlertPlan::getType)
|
||||
.eq(ObjectUtils.isNotEmpty(alertPlan.getType()), AlertPlan::getType, alertPlan.getType());
|
||||
return selectJoinList(AlertPlanAndPlanTypeDTO.class, eq);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -33,4 +42,15 @@ public class AlertPlanServiceImpl extends MPJBaseServiceImpl<AlertPlanMapper, Al
|
|||
.ge(AlertPlan::getMaxValue, value);
|
||||
return getOne(alertPlanLambdaQueryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlertPlanAndPlanTypeDTO getDTOById(Long id) {
|
||||
MPJLambdaWrapper<AlertPlan> eq = new MPJLambdaWrapper<AlertPlan>()
|
||||
.selectAll(AlertPlan.class)
|
||||
.select(PlanType::getTypeName)
|
||||
.leftJoin(PlanType.class, PlanType::getId, AlertPlan::getType)
|
||||
.eq(AlertPlan::getId, id);
|
||||
return selectJoinOne(AlertPlanAndPlanTypeDTO.class, eq);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,11 +2,14 @@ package com.ruoyi.board.service.impl;
|
|||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.github.yulichang.base.MPJBaseServiceImpl;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.board.mapper.BoardInfoMapper;
|
||||
import com.ruoyi.board.domain.BoardInfo;
|
||||
import com.ruoyi.board.service.IBoardInfoService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class BoardInfoServiceImpl extends MPJBaseServiceImpl<BoardInfoMapper, BoardInfo> implements IBoardInfoService {
|
||||
|
||||
|
@ -16,4 +19,16 @@ public class BoardInfoServiceImpl extends MPJBaseServiceImpl<BoardInfoMapper, Bo
|
|||
boardInfoLambdaQueryWrapper.eq(BoardInfo::getBoardIp, ip);
|
||||
return getOne(boardInfoLambdaQueryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BoardInfo> listPage(BoardInfo boardInfo) {
|
||||
LambdaQueryWrapper<BoardInfo> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.likeRight(StringUtils.isNotEmpty(boardInfo.getBoardName()), BoardInfo::getBoardName, boardInfo.getBoardName());
|
||||
wrapper.likeRight(StringUtils.isNotEmpty(boardInfo.getBoardMileage()), BoardInfo::getBoardMileage, boardInfo.getBoardMileage());
|
||||
wrapper.eq(StringUtils.isNotEmpty(boardInfo.getBoardSize()), BoardInfo::getBoardSize, boardInfo.getBoardSize());
|
||||
wrapper.eq(StringUtils.isNotEmpty(boardInfo.getBoardBrand()), BoardInfo::getBoardBrand, boardInfo.getBoardBrand());
|
||||
wrapper.eq(StringUtils.isNotEmpty(boardInfo.getBoardCommunicationProtocol()), BoardInfo::getBoardCommunicationProtocol, boardInfo.getBoardCommunicationProtocol());
|
||||
wrapper.eq(StringUtils.isNotEmpty(boardInfo.getBoardRoadSection()), BoardInfo::getBoardRoadSection, boardInfo.getBoardRoadSection());
|
||||
return list(wrapper);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package com.ruoyi.board.service.impl;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseServiceImpl;
|
||||
import com.ruoyi.board.domain.PlanType;
|
||||
import com.ruoyi.board.mapper.PlanTypeMapper;
|
||||
import com.ruoyi.board.service.IPlanTypeService;
|
||||
import com.ruoyi.common.core.domain.TreeSelect;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class PlanTypeServiceImpl extends MPJBaseServiceImpl<PlanTypeMapper, PlanType> implements IPlanTypeService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(PlanTypeServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public List<TreeSelect> listPlanTree(PlanType planType) {
|
||||
List<PlanType> list = list();
|
||||
List<PlanType> planTypes = buildPlanTree(list);
|
||||
return planTypes.stream().map(this::buildTreeSelect).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private TreeSelect buildTreeSelect(PlanType planType){
|
||||
List<TreeSelect> childTreeSelectList = planType.getChildren().stream().map(this::buildTreeSelect).collect(Collectors.toList());
|
||||
TreeSelect treeSelect = new TreeSelect();
|
||||
treeSelect.setId(planType.getId());
|
||||
treeSelect.setLabel(planType.getTypeName());
|
||||
treeSelect.setChildren(childTreeSelectList);
|
||||
return treeSelect;
|
||||
};
|
||||
|
||||
private List<PlanType> buildPlanTree(List<PlanType> list) {
|
||||
List<PlanType> returnList = new ArrayList<>();
|
||||
List<Long> tempList = list.stream().map(PlanType::getId).collect(Collectors.toList());
|
||||
for (PlanType planType : list)
|
||||
{
|
||||
// 如果是顶级节点, 遍历该父节点的所有子节点
|
||||
if (!tempList.contains(planType.getParentId()))
|
||||
{
|
||||
recursionFn(list, planType);
|
||||
returnList.add(planType);
|
||||
}
|
||||
}
|
||||
if (returnList.isEmpty())
|
||||
{
|
||||
returnList = list;
|
||||
}
|
||||
return returnList;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归列表
|
||||
*/
|
||||
private void recursionFn(List<PlanType> list, PlanType t)
|
||||
{
|
||||
// 得到子节点列表
|
||||
List<PlanType> childList = getChildList(list, t);
|
||||
t.setChildren(childList);
|
||||
for (PlanType tChild : childList)
|
||||
{
|
||||
if (hasChild(list, tChild))
|
||||
{
|
||||
recursionFn(list, tChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到子节点列表
|
||||
*/
|
||||
private List<PlanType> getChildList(List<PlanType> list, PlanType t)
|
||||
{
|
||||
List<PlanType> tlist = new ArrayList<>();
|
||||
for (PlanType n : list) {
|
||||
if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getId().longValue()) {
|
||||
tlist.add(n);
|
||||
}
|
||||
}
|
||||
return tlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有子节点
|
||||
*/
|
||||
private boolean hasChild(List<PlanType> list, PlanType t)
|
||||
{
|
||||
return !getChildList(list, t).isEmpty();
|
||||
}
|
||||
}
|
|
@ -2,11 +2,15 @@ package com.ruoyi.board.service.impl;
|
|||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.github.yulichang.base.MPJBaseServiceImpl;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.board.mapper.PresetContentMapper;
|
||||
import com.ruoyi.board.domain.PresetContent;
|
||||
import com.ruoyi.board.service.IPresetContentService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class PresetContentServiceImpl extends MPJBaseServiceImpl<PresetContentMapper, PresetContent> implements IPresetContentService {
|
||||
@Override
|
||||
|
@ -18,4 +22,13 @@ public class PresetContentServiceImpl extends MPJBaseServiceImpl<PresetContentMa
|
|||
.eq(PresetContent::getInfoType, type);
|
||||
return getOne(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PresetContent> listPage(PresetContent presetContent) {
|
||||
LambdaQueryWrapper<PresetContent> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.likeRight(StringUtils.isNotEmpty(presetContent.getName()), PresetContent::getName, presetContent.getName());
|
||||
queryWrapper.eq(StringUtils.isNotEmpty(presetContent.getBoardSize()), PresetContent::getBoardSize, presetContent.getBoardSize());
|
||||
queryWrapper.eq(ObjectUtils.isNotEmpty(presetContent.getInfoType()), PresetContent::getInfoType, presetContent.getInfoType());
|
||||
return list(queryWrapper);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,36 +4,42 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||
import com.github.yulichang.base.MPJBaseServiceImpl;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import com.ruoyi.board.domain.PresetContent;
|
||||
import com.ruoyi.board.domain.ReleaseRecordDto;
|
||||
import lombok.Data;
|
||||
import com.ruoyi.board.domain.dto.ReleaseRecordAndPresetContentDTO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.ruoyi.board.domain.ReleaseRecord;
|
||||
import com.ruoyi.board.mapper.ReleaseRecordMapper;
|
||||
import com.ruoyi.board.service.IReleaseRecordService;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class ReleaseRecordServiceImpl extends MPJBaseServiceImpl<ReleaseRecordMapper, ReleaseRecord> implements IReleaseRecordService {
|
||||
private static final Logger log = LoggerFactory.getLogger(ReleaseRecordServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public ReleaseRecord getOneLatestByBoardId(String boardId, Integer type) {
|
||||
// LambdaQueryWrapper<ReleaseRecord> releaseRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
// releaseRecordLambdaQueryWrapper
|
||||
// .eq(ReleaseRecord::getBoardId, boardId)
|
||||
// .orderByDesc(ReleaseRecord::getCreateTime)
|
||||
// .last("LIMIT 1");
|
||||
|
||||
ReleaseRecordDto releaseRecord = selectJoinOne(ReleaseRecordDto.class,
|
||||
public List<ReleaseRecordAndPresetContentDTO> listLatest2minRecordDtoByBoardId(Integer boardId) {
|
||||
Date before2min = new Date(System.currentTimeMillis() - 30 * 60 * 1000);
|
||||
return selectJoinList(ReleaseRecordAndPresetContentDTO.class,
|
||||
new MPJLambdaWrapper<ReleaseRecord>()
|
||||
.selectAll(ReleaseRecord.class)
|
||||
.select(PresetContent::getInfoType)
|
||||
.leftJoin(PresetContent.class, PresetContent::getId, ReleaseRecord::getPresetContentId)
|
||||
.eq(ReleaseRecord::getBoardId, boardId)
|
||||
.eq(PresetContent::getInfoType, type)
|
||||
.orderByDesc(ReleaseRecord::getCreateTime)
|
||||
.last("LIMIT 1")
|
||||
.gt(ReleaseRecord::getCreateTime, before2min)
|
||||
.eq(PresetContent::getPresetType, 0)
|
||||
);
|
||||
System.out.println(releaseRecord);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ReleaseRecord> listLatest2minRecordByBoardId(Integer boardId) {
|
||||
Date before2min = new Date(System.currentTimeMillis() - 30 * 60 * 1000);
|
||||
LambdaQueryWrapper<ReleaseRecord> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(ReleaseRecord::getBoardId, boardId)
|
||||
.gt(ReleaseRecord::getCreateTime, before2min);
|
||||
return list(queryWrapper);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package com.ruoyi.protocol.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum ProtocolDefault {
|
||||
SanSi(1, "SanSi", 2929),;
|
||||
private final Integer id;
|
||||
private final String name;
|
||||
private final Integer port;
|
||||
|
||||
ProtocolDefault(Integer id, String name, Integer port) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.port = port;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,18 @@
|
|||
package com.ruoyi.protocol.sansi;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ruoyi.board.domain.BoardInfo;
|
||||
import com.ruoyi.board.domain.PresetContent;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.uuid.UUID;
|
||||
import com.ruoyi.protocol.enums.ProtocolDefault;
|
||||
import com.ruoyi.protocol.sansi.enums.SanSiFontColor;
|
||||
import com.ruoyi.protocol.sansi.enums.SanSiFontStyle;
|
||||
import com.ruoyi.protocol.service.IProtocolService;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import zhishuang.wang.sansi.fcms.devinfor.DeviceControl;
|
||||
import zhishuang.wang.sansi.fcms.devinfor.DeviceVar;
|
||||
import zhishuang.wang.sansi.playlist.AreaItem;
|
||||
|
@ -17,38 +23,39 @@ import zhishuang.wang.sansi.playlist.fcms.PlayListFcms;
|
|||
import zhishuang.wang.sansi.tools.ReturnData;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SanSiProtocol {
|
||||
@Service
|
||||
public class SanSiProtocol implements IProtocolService {
|
||||
private static final Logger log = LoggerFactory.getLogger(SanSiProtocol.class);
|
||||
Integer deviceId = 0;
|
||||
|
||||
String deviceId = "1";
|
||||
|
||||
public String createTextItem(PresetContent presetContent, BoardInfo boardInfo) {
|
||||
private String createTextItem(List<PresetContent> presetContentList, BoardInfo boardInfo) {
|
||||
Animation animation = new Animation();
|
||||
animation.setInAnimation(0);
|
||||
animation.setInAnimationSpeed(200);
|
||||
List<PlayItem> playItemList = new ArrayList<>();
|
||||
|
||||
TextBase textBase = new TextBase(0, presetContent.getContent());
|
||||
textBase.setFontSize(presetContent.getFontSize()+","+presetContent.getFontSize());
|
||||
textBase.setFontName(presetContent.getFontStyle());
|
||||
textBase.setWordSpace(presetContent.getLetterSpacing());
|
||||
BaseColour fontColour = SanSiFontColor.getBaseColourByColorName(presetContent.getFontColor());
|
||||
int index = 1;
|
||||
presetContentList.forEach(i -> {
|
||||
TextBase textBase = new TextBase(0, i.getContent());
|
||||
textBase.setFontSize(i.getFontSize()+","+i.getFontSize());
|
||||
textBase.setFontName(SanSiFontStyle.getStyleValueByName(i.getFontStyle()));
|
||||
textBase.setWordSpace(i.getLetterSpacing());
|
||||
BaseColour fontColour = SanSiFontColor.getBaseColourByColorName(i.getFontColor());
|
||||
if (null == fontColour) {
|
||||
log.error("BaseColour fontColour = SanSiFontColor.getBaseColourByColorName(presetContent.getFontColor()); 没有匹配到相应的字体颜色");
|
||||
return null;
|
||||
}
|
||||
textBase.setFontColour(fontColour);
|
||||
|
||||
PlayTimeBase textPlayTime = new PlayTimeBase(presetContent.getPlayTime());
|
||||
PlayItem textPlayItem = new PlayItem(1, "1", "test", textBase, textPlayTime);
|
||||
PlayTimeBase textPlayTime = new PlayTimeBase(i.getPlayTime() * 10);
|
||||
PlayItem textPlayItem = new PlayItem(index, Integer.toString(index), "test" + index, textBase, textPlayTime);
|
||||
textPlayItem.setAnimation(animation);
|
||||
textPlayItem.setX(presetContent.getFontPositionX());
|
||||
textPlayItem.setY(presetContent.getFontPositionY());
|
||||
|
||||
List<PlayItem> playItemList = new ArrayList<>();
|
||||
textPlayItem.setX(i.getFontPositionX());
|
||||
textPlayItem.setY(i.getFontPositionY());
|
||||
playItemList.add(textPlayItem);
|
||||
});
|
||||
|
||||
String boardSize = boardInfo.getBoardSize();
|
||||
String[] split = StringUtils.split(boardSize, "*");
|
||||
|
@ -68,45 +75,58 @@ public class SanSiProtocol {
|
|||
PageItem pageItem = new PageItem("1", "pageItem", areaItemList);
|
||||
PlayListFcms plf = new PlayListFcms();
|
||||
|
||||
String path = "./sansi/" + UUID.fastUUID() + "/play.lst";
|
||||
File file = new File(path);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
String path = "./protocolFile/SanSi/" + DateUtils.dateTimeNow();
|
||||
String file = path + "/play.lst";
|
||||
try {
|
||||
FileUtils.forceMkdir(new File(path));
|
||||
} catch (IOException e) {
|
||||
log.error("创建文件夹失败");
|
||||
return null;
|
||||
}
|
||||
|
||||
ReturnData rd = plf.createFcmsPlayList(path, pageItem);
|
||||
System.out.println("====" + rd.getCode());
|
||||
System.out.println("====" + rd.getMessage());
|
||||
ReturnData rd = plf.createFcmsPlayList(file, pageItem);
|
||||
if (rd.getCode() != 0) {
|
||||
log.error("生成三思的上传文件出错了");
|
||||
return null;
|
||||
}
|
||||
return path;
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
private void loginDevice(BoardInfo boardInfo) {
|
||||
DeviceVar.deviceInforInit(deviceId, 1, boardInfo.getBoardIp(), boardInfo.getBoardPort(), 2048);
|
||||
@Override
|
||||
public boolean protocolSupport(String protocolName) {
|
||||
return StringUtils.equals(ProtocolDefault.SanSi.getName(), protocolName);
|
||||
}
|
||||
|
||||
private boolean uploadAndStartPlayList(String path) {
|
||||
ReturnData uploadPlayListRD = DeviceControl.fcmsUploadPlayList(deviceId, path);//上传播放表
|
||||
if (uploadPlayListRD.getCode() != 0) {
|
||||
log.error("上传错误");
|
||||
return false;
|
||||
@Override
|
||||
public void loginDevice(BoardInfo boardInfo) {
|
||||
if (deviceId > 10) {
|
||||
deviceId = 0;
|
||||
}
|
||||
ReturnData activePlayListRD = DeviceControl.fcmsActivePlayList(deviceId, "play.lst");
|
||||
if (activePlayListRD.getCode() != 0) {
|
||||
log.error("播放错误");
|
||||
return false;
|
||||
deviceId++;
|
||||
if (boardInfo.getBoardPort()<1) {
|
||||
boardInfo.setBoardPort(ProtocolDefault.SanSi.getPort());
|
||||
}
|
||||
return true;
|
||||
DeviceVar.deviceInforInit(Integer.toString(deviceId), 1, boardInfo.getBoardIp(), boardInfo.getBoardPort(), 2048);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logoutDevice() {
|
||||
DeviceVar.deviceInforDel(Integer.toString(deviceId));
|
||||
}
|
||||
|
||||
public boolean publishContent(BoardInfo boardInfo, PresetContent presetContent){
|
||||
loginDevice(boardInfo);
|
||||
String filePath = createTextItem(presetContent, boardInfo);
|
||||
return uploadAndStartPlayList(filePath);
|
||||
@Override
|
||||
public void publishContent(BoardInfo boardInfo, List<PresetContent> presetContentList) {
|
||||
String path = createTextItem(presetContentList, boardInfo);
|
||||
uploadAndStartPlayList(path);
|
||||
}
|
||||
|
||||
private void uploadAndStartPlayList(String path) {
|
||||
ReturnData uploadPlayListRD = DeviceControl.fcmsUploadPlayList(Integer.toString(deviceId), path);//上传播放表
|
||||
log.info("uploadPlayListRD:{}", JSON.toJSONString(uploadPlayListRD));
|
||||
// ReturnData activePlayListRD = DeviceControl.fcmsActivePlayList(Integer.toString(deviceId), "000");
|
||||
// if (activePlayListRD.getCode() != 0) {
|
||||
// log.error("播放错误");
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package com.ruoyi.protocol.sansi.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Getter
|
||||
public enum SanSiFontStyle {
|
||||
SongTi("宋体", "s");
|
||||
private final String name;
|
||||
private final String value;
|
||||
|
||||
SanSiFontStyle(String name, String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static String getStyleValueByName(String name) {
|
||||
return Stream.of(SanSiFontStyle.values())
|
||||
.filter(fontColor -> fontColor.getName().equals(name))
|
||||
.map(SanSiFontStyle::getValue)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,4 +1,30 @@
|
|||
package com.ruoyi.protocol.service;
|
||||
|
||||
import com.ruoyi.board.domain.BoardInfo;
|
||||
import com.ruoyi.board.domain.PresetContent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IProtocolService {
|
||||
|
||||
boolean protocolSupport(String protocolName);
|
||||
|
||||
void loginDevice(BoardInfo boardInfo);
|
||||
|
||||
void logoutDevice();
|
||||
|
||||
void publishContent(BoardInfo boardInfo, List<PresetContent> presetContentList);
|
||||
|
||||
default void publishInformation(BoardInfo boardInfo, List<PresetContent> presetContentList){
|
||||
// 登录
|
||||
loginDevice(boardInfo);
|
||||
// 发布
|
||||
publishContent(boardInfo, presetContentList);
|
||||
// 登出
|
||||
logoutDevice();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package com.ruoyi.protocol.service.impl;
|
||||
|
||||
import com.ruoyi.board.domain.BoardInfo;
|
||||
import com.ruoyi.board.domain.PresetContent;
|
||||
import com.ruoyi.protocol.service.IProtocolService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class ContentPublishingService {
|
||||
private static final Logger log = LoggerFactory.getLogger(ContentPublishingService.class);
|
||||
@Autowired
|
||||
List<IProtocolService> protocolServiceList;
|
||||
|
||||
public void contentPublish(BoardInfo boardInfo, List<PresetContent> presetContentList) {
|
||||
IProtocolService iProtocolService = protocolServiceList.stream().filter(i -> i.protocolSupport(boardInfo.getBoardCommunicationProtocol())).findFirst().orElse(null);
|
||||
if (iProtocolService ==null) {
|
||||
log.error("协议不支持");
|
||||
return;
|
||||
}
|
||||
iProtocolService.publishInformation(boardInfo, presetContentList);
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
package com.ruoyi.protocol.service.impl;
|
||||
|
||||
import com.ruoyi.protocol.service.IProtocolService;
|
||||
|
||||
public class ProtocolServiceImpl implements IProtocolService {
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.ruoyi.sensor.common;
|
||||
|
||||
import com.ruoyi.sensor.domain.dto.PerceptionHandlerDTO;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class PerceptionHandlerMap {
|
||||
public static final HashMap<String, PerceptionHandlerDTO> perceptionHandlerMap = new HashMap<>();
|
||||
}
|
|
@ -20,8 +20,14 @@ public class PerceptionParams {
|
|||
*/
|
||||
private String boardIp;
|
||||
|
||||
/**
|
||||
* 情报板协议
|
||||
*/
|
||||
private String boardProtocol;
|
||||
// /**
|
||||
// * 情报板协议
|
||||
// */
|
||||
// private String boardProtocol;
|
||||
|
||||
public String getStr() {
|
||||
return "perceptionType=" + perceptionType +
|
||||
",perceptionValue=" + perceptionValue +
|
||||
",boardIp='" + boardIp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package com.ruoyi.sensor.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class PerceptionWarningStatusInfo {
|
||||
private String boardIp;
|
||||
private String perceptionType;
|
||||
private Double perceptionValue;
|
||||
private Integer perceptionLevel;
|
||||
private String perceptionStatus;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime perceptionTime;
|
||||
private String perceptionMsg;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.ruoyi.sensor.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PresetContentStyle {
|
||||
private String areaType;
|
||||
private String backgroundColor;
|
||||
private String bmpFileName;
|
||||
private String content;
|
||||
private String font;
|
||||
private String fontColor;
|
||||
private Integer fontSize;
|
||||
private Integer width;
|
||||
private Integer height;
|
||||
private String imageAddress;
|
||||
private Integer startX;
|
||||
private Integer startY;
|
||||
private Integer stay;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.ruoyi.sensor.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ReleaseLogReport {
|
||||
private String boardIp;
|
||||
private String perceptionType;
|
||||
private int perceptionLevel;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime releaseTime;
|
||||
private String releaseStatus;
|
||||
private String releaseContent;
|
||||
private List<PresetContentStyle> lines;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package com.ruoyi.sensor.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class WarningStatusInfo {
|
||||
private String infoBoardIP;
|
||||
private String warningType;
|
||||
private Double warningValue;
|
||||
private Integer currentWarningLevel;
|
||||
private String status;
|
||||
private Date triggerTime;
|
||||
private String warningMessage;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.ruoyi.sensor.domain.dto;
|
||||
|
||||
import com.ruoyi.sensor.domain.PerceptionParams;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class PerceptionHandlerDTO {
|
||||
private Date createTime = new Date();
|
||||
private Date updateTime = new Date();
|
||||
private Integer allReceiveTimes = 0;
|
||||
private Integer currentMinReceiveTimes = 0;
|
||||
private PerceptionParams perceptionParams;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.ruoyi.sensor.enums;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public enum PrintColor {
|
||||
|
||||
red("red", "255000000"),
|
||||
yellow("yellow", "255255000"),
|
||||
green("green", "000255000");
|
||||
|
||||
private final String colorName;
|
||||
private final String colourBitStr;
|
||||
|
||||
PrintColor(String colorName, String colourBitStr) {
|
||||
this.colorName = colorName;
|
||||
this.colourBitStr = colourBitStr;
|
||||
}
|
||||
|
||||
public static String getBitColor(String colorName) {
|
||||
return Stream.of(PrintColor.values())
|
||||
.filter(fontColor -> fontColor.colorName.equals(colorName))
|
||||
.map(fontColor -> fontColor.colourBitStr)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
|
@ -2,35 +2,54 @@ package com.ruoyi.sensor.merchants;
|
|||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ruoyi.common.utils.http.HttpUtils;
|
||||
import com.ruoyi.sensor.domain.WarningStatusInfo;
|
||||
import com.ruoyi.sensor.domain.PerceptionWarningStatusInfo;
|
||||
import com.ruoyi.sensor.domain.ReleaseLogReport;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class MerchantsHttp {
|
||||
private static final Logger log = LoggerFactory.getLogger(MerchantsHttp.class);
|
||||
|
||||
private static final String uri = "http://localhost:8080/merchants";
|
||||
private static String STATUS_URI;
|
||||
private static String PUBLICATION_LOG_URI;
|
||||
|
||||
public static void sendWarning(WarningStatusInfo warningStatusInfo){
|
||||
String jsonString = JSON.toJSONString(warningStatusInfo);
|
||||
@Value("${remote.statusReport}")
|
||||
public void setStatusUri(String statusUri) {
|
||||
STATUS_URI = statusUri;
|
||||
}
|
||||
|
||||
@Value("${remote.logReport}")
|
||||
public void setPublicationLogUri(String publicationLogUri) {
|
||||
PUBLICATION_LOG_URI = publicationLogUri;
|
||||
}
|
||||
|
||||
public static void sendWarningStatus(PerceptionWarningStatusInfo perceptionWarningStatusInfo){
|
||||
String jsonString = JSON.toJSONString(perceptionWarningStatusInfo);
|
||||
send(STATUS_URI, jsonString);
|
||||
}
|
||||
|
||||
public static void sendPublicationLog(ReleaseLogReport releaseLogReport){
|
||||
String jsonString = JSON.toJSONString(releaseLogReport);
|
||||
send(PUBLICATION_LOG_URI, jsonString);
|
||||
|
||||
}
|
||||
|
||||
private static void send(String URI, String jsonStr) {
|
||||
String result = null;
|
||||
Map<String, String> header = new HashMap<>();
|
||||
try {
|
||||
result = HttpUtils.postCall(uri, jsonString, header);
|
||||
result = HttpUtils.postCall(URI, jsonStr);
|
||||
} catch (Exception e) {
|
||||
log.error("send warning error", e);
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isEmpty(result)) {
|
||||
log.error("send warning error");
|
||||
return;
|
||||
}
|
||||
// 记录上报结果
|
||||
log.error("发送信息成功,但是没有接收到响应信息");
|
||||
} else {
|
||||
log.info(result);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,4 +6,7 @@ public interface ISensorDataService {
|
|||
|
||||
void perceptionParamsHandler(PerceptionParams params);
|
||||
|
||||
void putPerceptionParamsToMap(PerceptionParams perceptionParams);
|
||||
|
||||
void handlerPerceptionMap();
|
||||
}
|
||||
|
|
|
@ -9,23 +9,34 @@ import com.ruoyi.board.service.IAlertPlanService;
|
|||
import com.ruoyi.board.service.IBoardInfoService;
|
||||
import com.ruoyi.board.service.IPresetContentService;
|
||||
import com.ruoyi.board.service.IReleaseRecordService;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.protocol.sansi.SanSiProtocol;
|
||||
import com.ruoyi.protocol.service.impl.ContentPublishingService;
|
||||
import com.ruoyi.sensor.common.PerceptionHandlerMap;
|
||||
import com.ruoyi.sensor.domain.PerceptionParams;
|
||||
import com.ruoyi.sensor.domain.WarningStatusInfo;
|
||||
import com.ruoyi.sensor.domain.PerceptionWarningStatusInfo;
|
||||
import com.ruoyi.sensor.domain.PresetContentStyle;
|
||||
import com.ruoyi.sensor.domain.ReleaseLogReport;
|
||||
import com.ruoyi.sensor.domain.dto.PerceptionHandlerDTO;
|
||||
import com.ruoyi.sensor.enums.PrintColor;
|
||||
import com.ruoyi.sensor.merchants.MerchantsHttp;
|
||||
import com.ruoyi.sensor.service.ISensorDataService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class SensorDataServiceImpl implements ISensorDataService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SensorDataServiceImpl.class);
|
||||
private static final Integer ALL_TIMES_THRESHOLD = 5;
|
||||
private static final Integer MIN_TIMES_THRESHOLD = 4;
|
||||
@Autowired
|
||||
private IBoardInfoService boardInfoService;
|
||||
@Autowired
|
||||
|
@ -34,55 +45,206 @@ public class SensorDataServiceImpl implements ISensorDataService {
|
|||
private IPresetContentService presetContentService;
|
||||
@Autowired
|
||||
private IReleaseRecordService releaseRecordService;
|
||||
@Autowired
|
||||
private ContentPublishingService contentPublishingService;
|
||||
|
||||
@Override
|
||||
@Async
|
||||
public void perceptionParamsHandler(PerceptionParams params) {
|
||||
int planTypeByName = AlertPlanType.getPlanTypeByName(params.getPerceptionType());
|
||||
int currentContentPlanType = AlertPlanType.getPlanTypeByName(params.getPerceptionType());
|
||||
// 找到符合计划的预警
|
||||
AlertPlan oneByTypeAndValue = alertPlanService.getOneByTypeAndValue(planTypeByName, params.getPerceptionValue());
|
||||
if (null == oneByTypeAndValue) {
|
||||
AlertPlan currentAlertPlan = alertPlanService.getOneByTypeAndValue(currentContentPlanType, params.getPerceptionValue());
|
||||
if (null == currentAlertPlan) {
|
||||
log.error("找不到预警计划");
|
||||
return;
|
||||
}
|
||||
// 情报板设备信息
|
||||
BoardInfo oneByIP = boardInfoService.getOneByIP(params.getBoardIp());
|
||||
if (null == oneByIP) {
|
||||
BoardInfo boardInfo = boardInfoService.getOneByIP(params.getBoardIp());
|
||||
if (null == boardInfo) {
|
||||
log.error("找不到情报板信息");
|
||||
return;
|
||||
}
|
||||
// 预置发布的信息
|
||||
PresetContent oneByContentAndBoardSize = presetContentService.getOneByContentAndBoardSize(oneByTypeAndValue.getDisplayContent(), oneByIP.getBoardSize(), planTypeByName);
|
||||
if (null == oneByContentAndBoardSize) {
|
||||
PresetContent currentContent = presetContentService.getOneByContentAndBoardSize(currentAlertPlan.getDisplayContent(), boardInfo.getBoardSize(), currentContentPlanType);
|
||||
if (null == currentContent) {
|
||||
log.error("找不到预置发布的信息");
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取同类型最新的一条发布记录
|
||||
ReleaseRecord oneLatestByBoardId = releaseRecordService.getOneLatestByBoardId(oneByIP.getBoardIp(), 1);
|
||||
if (null == oneLatestByBoardId) {
|
||||
// 说明之前没有发布记录
|
||||
// 预警信息发布流程
|
||||
List<PresetContent> informationToBeReleasedList = new ArrayList<>();
|
||||
String presetStatus = "预警开始";
|
||||
// 查询这个情报板 2 分钟内所有发布内容
|
||||
List<ReleaseRecord> releaseRecordList = releaseRecordService.listLatest2minRecordByBoardId(boardInfo.getId());
|
||||
if (releaseRecordList.isEmpty()) {
|
||||
// 如果查到为空,说明 2 分钟内没有发布内容,这里是第一次发布,直接走发布逻辑
|
||||
informationToBeReleasedList.add(currentContent);
|
||||
} else {
|
||||
// 如果不为空,说明 2 分钟内是发布了内容的,查询所有的发布内容
|
||||
List<Integer> presetContentIdList = releaseRecordList.stream().map(ReleaseRecord::getPresetContentId).collect(Collectors.toList());
|
||||
List<PresetContent> existPresetContentList = presetContentService.listByIds(presetContentIdList);
|
||||
// 先把已经存在的都加入进去
|
||||
informationToBeReleasedList.addAll(existPresetContentList);
|
||||
// 判断所有发布内容中是否存在当前要发布的类型
|
||||
PresetContent isExistsPresetContent = existPresetContentList.stream().filter(i -> i.getInfoType() == currentContentPlanType).findFirst().orElse(null);
|
||||
if (isExistsPresetContent == null) {
|
||||
// 说明这是一个新发布的预警类型
|
||||
informationToBeReleasedList.add(currentContent);
|
||||
} else {
|
||||
// 说明这是一个已有的类型,需要获取预警等级,然后进行判断
|
||||
// 判断已有类型是否和现在的一样然后再替换掉
|
||||
// 现在需要知道这个同类型的属于是哪个级别的
|
||||
int foundPlanId = releaseRecordList.stream()
|
||||
.filter(i -> Objects.equals(i.getPresetContentId(), isExistsPresetContent.getId()))
|
||||
.mapToInt(ReleaseRecord::getPlanId)
|
||||
.findFirst().orElse(-1);
|
||||
AlertPlan byId = alertPlanService.getById(foundPlanId);
|
||||
int compare = NumberUtils.compare(byId.getLevel(),
|
||||
currentAlertPlan.getLevel());
|
||||
switch (compare) {
|
||||
case 0:
|
||||
// 两个一样等级
|
||||
// 这时候就不需要替换,也不需要重新发布
|
||||
presetStatus = "预警持续";
|
||||
break;
|
||||
case 1:
|
||||
// getPresetContentLevel > alertPlan.getLevel()
|
||||
// 预警减弱
|
||||
// 此时需要将同类型的信息给替换掉,并重新发布
|
||||
presetStatus = "预警减弱";
|
||||
break;
|
||||
case -1:
|
||||
// getPresetContentLevel < alertPlan.getLevel()
|
||||
// 预警加强
|
||||
// 此时需要将同类型的信息给替换掉,并重新发布
|
||||
presetStatus = "预警加强";
|
||||
break;
|
||||
}
|
||||
|
||||
// todo 发布
|
||||
boolean sanSiProtocol = new SanSiProtocol().publishContent(oneByIP, oneByContentAndBoardSize);
|
||||
// 替换同类型的预警信息
|
||||
for (int i = 0; i < existPresetContentList.size(); i++) {
|
||||
if (existPresetContentList.get(i).getInfoType() == currentContentPlanType) {
|
||||
existPresetContentList.set(i, currentContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// todo 发布
|
||||
contentPublishingService.contentPublish(boardInfo, informationToBeReleasedList);
|
||||
// 经过主动发布之后就变成预置信息
|
||||
// 发布之后记录发布内容 ReleaseRecord
|
||||
this.saveRecord(boardInfo.getId(), currentContent.getId(), currentAlertPlan.getId());
|
||||
// 记录完了之后就需要向对方发送状态日志记录
|
||||
this.sendStatus(presetStatus, boardInfo.getBoardIp(), params.getPerceptionType(), currentContent.getContent(), params.getPerceptionValue(), currentAlertPlan.getLevel());
|
||||
// 发送情报板发布信息日志记录
|
||||
this.sendPublicLog(boardInfo.getBoardIp(), params.getPerceptionType(), currentAlertPlan.getLevel(), currentContent.getContent(), informationToBeReleasedList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putPerceptionParamsToMap(PerceptionParams perceptionParams) {
|
||||
String key = perceptionParams.getPerceptionType() + perceptionParams.getBoardIp();
|
||||
PerceptionHandlerDTO orDefault = PerceptionHandlerMap.perceptionHandlerMap.getOrDefault(key, new PerceptionHandlerDTO());
|
||||
orDefault.setPerceptionParams(perceptionParams);
|
||||
orDefault.setAllReceiveTimes(orDefault.getAllReceiveTimes() + 1);
|
||||
orDefault.setCurrentMinReceiveTimes(orDefault.getCurrentMinReceiveTimes() + 1);
|
||||
orDefault.setUpdateTime(new Date());
|
||||
PerceptionHandlerMap.perceptionHandlerMap.put(key, orDefault);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void handlerPerceptionMap(){
|
||||
List<PerceptionParams> publishList = new ArrayList<>();
|
||||
List<PerceptionParams> cancelList = new ArrayList<>();
|
||||
List<String> delList = new ArrayList<>();
|
||||
long now = new Date().getTime();
|
||||
log.info("{}", PerceptionHandlerMap.perceptionHandlerMap);
|
||||
PerceptionHandlerMap.perceptionHandlerMap.forEach((key, value) -> {
|
||||
long lastUpdateTime = value.getUpdateTime().getTime();
|
||||
// 最后的接收时间大于 1 分钟
|
||||
if (now - lastUpdateTime > 60 * 1000) {
|
||||
delList.add(key);
|
||||
if (value.getAllReceiveTimes() > ALL_TIMES_THRESHOLD ) {
|
||||
cancelList.add(value.getPerceptionParams());
|
||||
}
|
||||
} else {
|
||||
// 接收时间 < 1 分钟 && 接收次数 > 5
|
||||
// 要不要 + 个属性,当前分钟内接收的次数,以及接收的总次数
|
||||
if (value.getAllReceiveTimes() > ALL_TIMES_THRESHOLD && value.getCurrentMinReceiveTimes() > MIN_TIMES_THRESHOLD) {
|
||||
publishList.add(value.getPerceptionParams());
|
||||
}
|
||||
}
|
||||
value.setCurrentMinReceiveTimes(0);
|
||||
});
|
||||
// 需要删除的内容,有的是没有发布的浮动信息,有的是已经显示过了,需要取消显示的
|
||||
cancelList.forEach(this::cancelPublication);
|
||||
log.info("cancelPublication:{}", cancelList);
|
||||
delList.forEach(PerceptionHandlerMap.perceptionHandlerMap::remove);
|
||||
log.info("delList:{}", delList);
|
||||
publishList.forEach(this::perceptionParamsHandler);
|
||||
log.info("publishList:{}", publishList);
|
||||
}
|
||||
|
||||
private void sendPublicLog(String ip, String type, Integer level, String content, List<PresetContent> informationToBeReleasedList) {
|
||||
ReleaseLogReport releaseLogReport = new ReleaseLogReport();
|
||||
releaseLogReport.setBoardIp(ip);
|
||||
releaseLogReport.setPerceptionType(type);
|
||||
releaseLogReport.setPerceptionLevel(level);
|
||||
releaseLogReport.setReleaseContent(content);
|
||||
releaseLogReport.setReleaseTime(LocalDateTime.now());
|
||||
releaseLogReport.setReleaseStatus("发布成功");
|
||||
List<PresetContentStyle> presetContentStyles = new ArrayList<>();
|
||||
informationToBeReleasedList.forEach(i -> {
|
||||
String[] split = StringUtils.split(i.getBoardSize(), "*");
|
||||
PresetContentStyle p = new PresetContentStyle();
|
||||
p.setFont(i.getFontStyle());
|
||||
p.setFontSize(i.getFontSize());
|
||||
p.setFontColor(PrintColor.getBitColor(i.getFontColor()));
|
||||
p.setContent(i.getContent());
|
||||
p.setStartX(i.getFontPositionX());
|
||||
p.setStartY(i.getFontPositionY());
|
||||
p.setWidth(NumberUtils.toInt(split[1]));
|
||||
p.setHeight(NumberUtils.toInt(split[0]));
|
||||
p.setStay(i.getPlayTime());
|
||||
presetContentStyles.add(p);
|
||||
});
|
||||
releaseLogReport.setLines(presetContentStyles);
|
||||
MerchantsHttp.sendPublicationLog(releaseLogReport);
|
||||
}
|
||||
|
||||
private void sendStatus(String status, String ip, String type, String content, Double value, Integer level) {
|
||||
PerceptionWarningStatusInfo statusInfo = new PerceptionWarningStatusInfo();
|
||||
statusInfo.setPerceptionStatus(status);
|
||||
statusInfo.setBoardIp(ip);
|
||||
statusInfo.setPerceptionType(type);
|
||||
statusInfo.setPerceptionValue(value);
|
||||
statusInfo.setPerceptionMsg(content);
|
||||
statusInfo.setPerceptionLevel(level);
|
||||
statusInfo.setPerceptionTime(LocalDateTime.now());
|
||||
// // 开始发送状态记录
|
||||
MerchantsHttp.sendWarningStatus(statusInfo);
|
||||
}
|
||||
|
||||
@Async
|
||||
public void cancelPublication(PerceptionParams params) {
|
||||
PerceptionWarningStatusInfo statusInfo = new PerceptionWarningStatusInfo();
|
||||
statusInfo.setPerceptionStatus("预警结束");
|
||||
statusInfo.setBoardIp(params.getBoardIp());
|
||||
statusInfo.setPerceptionType(params.getPerceptionType());
|
||||
statusInfo.setPerceptionValue(params.getPerceptionValue());
|
||||
statusInfo.setPerceptionMsg("");
|
||||
statusInfo.setPerceptionLevel(1);
|
||||
statusInfo.setPerceptionTime(LocalDateTime.now());
|
||||
// // 开始发送状态记录
|
||||
MerchantsHttp.sendWarningStatus(statusInfo);
|
||||
}
|
||||
|
||||
private void saveRecord(Integer boardId, Integer presetContentId, Integer planId) {
|
||||
ReleaseRecord releaseRecord = new ReleaseRecord();
|
||||
releaseRecord.setBoardId(oneByIP.getId());
|
||||
releaseRecord.setPresetContentId(oneByContentAndBoardSize.getId());
|
||||
releaseRecord.setBoardId(boardId);
|
||||
releaseRecord.setPresetContentId(presetContentId);
|
||||
releaseRecord.setPlanId(planId);
|
||||
releaseRecord.setCreateTime(new Date());
|
||||
releaseRecord.setCreatedBy(SecurityUtils.getUserId().intValue());
|
||||
releaseRecord.setCreatedBy(1);
|
||||
releaseRecordService.save(releaseRecord);
|
||||
// 记录完了之后就需要向对方发送日志记录
|
||||
WarningStatusInfo statusInfo = new WarningStatusInfo();
|
||||
statusInfo.setStatus("");
|
||||
statusInfo.setInfoBoardIP(oneByIP.getBoardIp());
|
||||
statusInfo.setWarningType(params.getPerceptionType());
|
||||
statusInfo.setWarningMessage(oneByContentAndBoardSize.getContent());
|
||||
statusInfo.setWarningValue(params.getPerceptionValue());
|
||||
statusInfo.setCurrentWarningLevel(oneByTypeAndValue.getLevel());
|
||||
statusInfo.setTriggerTime(new Date());
|
||||
// 开始发送状态记录
|
||||
MerchantsHttp.sendWarning(new WarningStatusInfo());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package com.ruoyi.sensor.task;
|
||||
|
||||
import com.ruoyi.sensor.service.ISensorDataService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("clearPerceptionTask")
|
||||
public class ClearPerceptionTask {
|
||||
|
||||
@Autowired
|
||||
private ISensorDataService sensorDataService;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ClearPerceptionTask.class);
|
||||
|
||||
public void clearPerception(){
|
||||
sensorDataService.handlerPerceptionMap();
|
||||
log.info("handlerPerceptionMap 处理完了");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.board.mapper.PlanTypeMapper">
|
||||
</mapper>
|
|
@ -0,0 +1,53 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 查询计划发布中的类型列表
|
||||
export function listType(query) {
|
||||
return request({
|
||||
url: '/plan/type/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询计划发布中的类型详细
|
||||
export function getType(id) {
|
||||
return request({
|
||||
url: '/plan/type/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增计划发布中的类型
|
||||
export function addType(data) {
|
||||
return request({
|
||||
url: '/plan/type',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改计划发布中的类型
|
||||
export function updateType(data) {
|
||||
return request({
|
||||
url: '/plan/type',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除计划发布中的类型
|
||||
export function delType(id) {
|
||||
return request({
|
||||
url: '/plan/type/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询部门下拉树结构
|
||||
export function planTypeTreeSelect() {
|
||||
return request({
|
||||
url: '/plan/type/planTree',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
<template>
|
||||
<div>
|
||||
<!-- 调整缩放比例的控件 -->
|
||||
<el-form label-position="left" label-width="70px">
|
||||
<el-form-item label="缩放比例">
|
||||
<el-row :gutter="20" align="middle">
|
||||
<el-col :span="10">
|
||||
<el-slider
|
||||
v-model="scale"
|
||||
:min="0.5"
|
||||
:max="3"
|
||||
:step="0.5"
|
||||
show-input
|
||||
input-size="mini"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item label="文字预览">
|
||||
<div :style="containerStyle">
|
||||
<span :style="textStyle">
|
||||
{{ content }}
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
scale: 1, // 默认的缩放比例
|
||||
};
|
||||
},
|
||||
props: {
|
||||
fontStyle: {
|
||||
type: String,
|
||||
default: 'normal',
|
||||
},
|
||||
fontColor: {
|
||||
type: String,
|
||||
default: '#ff0000', // 字体默认颜色改为红色
|
||||
},
|
||||
fontSize: {
|
||||
type: Number,
|
||||
default: 16,
|
||||
},
|
||||
letterSpacing: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
fontX: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
fontY: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
backgroundWidth: {
|
||||
type: Number,
|
||||
default: 320,
|
||||
},
|
||||
backgroundHeight: {
|
||||
type: Number,
|
||||
default: 160,
|
||||
},
|
||||
lineHeight: {
|
||||
type: Number,
|
||||
default: 1, // 默认行间距为1
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: '这里是示例内容,哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈',
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
containerStyle() {
|
||||
return {
|
||||
width: `${this.backgroundWidth * this.scale}px`,
|
||||
height: `${this.backgroundHeight * this.scale}px`,
|
||||
position: 'relative',
|
||||
background: '#000000',
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
};
|
||||
},
|
||||
textStyle() {
|
||||
return {
|
||||
position: 'absolute',
|
||||
top: `${-this.fontY * this.scale}px`,
|
||||
left: `${this.fontX * this.scale}px`,
|
||||
fontStyle: this.fontStyle,
|
||||
color: this.fontColor,
|
||||
fontSize: `${this.fontSize * this.scale}px`,
|
||||
letterSpacing: `${this.letterSpacing * this.scale}px`,
|
||||
lineHeight: `${this.lineHeight}`,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -22,9 +22,9 @@
|
|||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-form-item label="信息类型" prop="type">
|
||||
<el-select
|
||||
v-model="queryParams.type"
|
||||
v-model="queryParams.infoType"
|
||||
clearable
|
||||
placeholder="全部"
|
||||
>
|
||||
|
@ -75,16 +75,16 @@
|
|||
v-hasPermi="['board:content:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['board:content:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<!-- <el-col :span="1.5">-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="warning"-->
|
||||
<!-- plain-->
|
||||
<!-- icon="el-icon-download"-->
|
||||
<!-- size="mini"-->
|
||||
<!-- @click="handleExport"-->
|
||||
<!-- v-hasPermi="['board:content:export']"-->
|
||||
<!-- >导出</el-button>-->
|
||||
<!-- </el-col>-->
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
|
@ -138,7 +138,7 @@
|
|||
/>
|
||||
|
||||
<!-- 添加或修改预置信息及模版对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="auto">
|
||||
<el-form-item label="预置信息名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入预置信息名称" />
|
||||
|
@ -199,7 +199,7 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="字体大小" prop="fontSize">
|
||||
<el-input-number :min="0" v-model="form.fontSize" placeholder="请输入字体大小" />
|
||||
<el-input-number :min="20" :max="50" v-model="form.fontSize" placeholder="请输入字体大小" />
|
||||
</el-form-item>
|
||||
<el-form-item label="字体间距" prop="letterSpacing">
|
||||
<el-input-number :min="0" v-model="form.letterSpacing" placeholder="请输入字体间距" />
|
||||
|
@ -213,11 +213,18 @@
|
|||
<el-form-item label="播放时间" prop="playTime">
|
||||
<el-input-number :min="0" v-model="form.playTime" placeholder="请输入播放时间" />
|
||||
</el-form-item>
|
||||
<el-form-item label="预览路径" prop="previewPath">
|
||||
<el-input v-model="form.previewPath" placeholder="请输入预览路径" />
|
||||
</el-form-item>
|
||||
|
||||
<text-preview
|
||||
fontStyle="SongTi"
|
||||
:fontSize="form.fontSize"
|
||||
:letterSpacing="form.letterSpacing"
|
||||
:fontX="form.fontPositionX"
|
||||
:fontY="form.fontPositionY"
|
||||
:backgroundWidth="bgSize.width"
|
||||
:backgroundHeight="bgSize.height"
|
||||
:lineHeight="1"
|
||||
:content="form.content" />
|
||||
</el-form>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
|
@ -228,9 +235,11 @@
|
|||
|
||||
<script>
|
||||
import { listContent, getContent, delContent, addContent, updateContent } from "@/api/board/content";
|
||||
import TextPreview from "@/views/board/component/TextPreview.vue";
|
||||
|
||||
export default {
|
||||
name: "Content",
|
||||
components: {TextPreview},
|
||||
dicts: ['board_size','font_color','font_style', 'alert_type'],
|
||||
data() {
|
||||
return {
|
||||
|
@ -334,6 +343,15 @@ export default {
|
|||
created() {
|
||||
this.getList();
|
||||
},
|
||||
computed:{
|
||||
bgSize() {
|
||||
if (!this.form.boardSize) {
|
||||
return {width: 320, height:160}
|
||||
}
|
||||
let [height, width] = this.form.boardSize.split("*").map(Number);
|
||||
return {width, height}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/** 查询预置信息及模版列表 */
|
||||
getList() {
|
||||
|
|
|
@ -98,17 +98,17 @@
|
|||
>删除
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['board:info:export']"
|
||||
>导出
|
||||
</el-button>
|
||||
</el-col>
|
||||
<!-- <el-col :span="1.5">-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="warning"-->
|
||||
<!-- plain-->
|
||||
<!-- icon="el-icon-download"-->
|
||||
<!-- size="mini"-->
|
||||
<!-- @click="handleExport"-->
|
||||
<!-- v-hasPermi="['board:info:export']"-->
|
||||
<!-- >导出-->
|
||||
<!-- </el-button>-->
|
||||
<!-- </el-col>-->
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
|
@ -228,11 +228,12 @@ import {listInfo, getInfo, delInfo, addInfo, updateInfo} from "@/api/board/info"
|
|||
import {deptTreeSelect} from "@/api/system/user";
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
import TextPreview from "@/views/board/component/TextPreview.vue";
|
||||
|
||||
export default {
|
||||
name: "Info",
|
||||
dicts: ['board_size', 'board_protocol'],
|
||||
components: {Treeselect},
|
||||
components: {TextPreview, Treeselect},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
|
|
|
@ -1,56 +1,22 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="auto">
|
||||
<el-form-item label="等级" prop="level">
|
||||
<el-select
|
||||
v-model="queryParams.level"
|
||||
clearable
|
||||
placeholder="全部"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dict.type.alert_level"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select
|
||||
v-model="queryParams.type"
|
||||
clearable
|
||||
placeholder="全部"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dict.type.alert_type"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="最大值" prop="maxValue">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="4" :xs="24">
|
||||
<div class="head-container">
|
||||
<el-input
|
||||
v-model="queryParams.maxValue"
|
||||
placeholder="请输入最大值"
|
||||
v-model="searchValue"
|
||||
placeholder="请输入名称"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
size="small"
|
||||
prefix-icon="el-icon-search"
|
||||
style="margin-bottom: 20px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="最小值" prop="minValue">
|
||||
<el-input
|
||||
v-model="queryParams.minValue"
|
||||
placeholder="请输入最小值"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
<div class="head-container">
|
||||
<plan-type-tree @node-clicked="handleNodeClick" :search-value="searchValue" />
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="20" :xs="24">
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
|
@ -84,32 +50,23 @@
|
|||
v-hasPermi="['board:plan:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['board:plan:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<!-- <el-col :span="1.5">-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="warning"-->
|
||||
<!-- plain-->
|
||||
<!-- icon="el-icon-download"-->
|
||||
<!-- size="mini"-->
|
||||
<!-- @click="handleExport"-->
|
||||
<!-- v-hasPermi="['board:plan:export']"-->
|
||||
<!-- >导出</el-button>-->
|
||||
<!-- </el-col>-->
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="planList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="唯一编号" align="center" prop="id" />
|
||||
<el-table-column label="类型" align="center" prop="type">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.alert_type" :value="scope.row.type"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="等级" align="center" prop="level">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.alert_level" :value="scope.row.level"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" align="center" prop="typeName" />
|
||||
<el-table-column label="等级" align="center" prop="level" />
|
||||
<el-table-column label="最大值" align="center" prop="maxValue" />
|
||||
<el-table-column label="最小值" align="center" prop="minValue" />
|
||||
<el-table-column label="显示内容" align="center" prop="displayContent" />
|
||||
|
@ -139,36 +96,17 @@
|
|||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 添加或修改警报计划对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="等级" prop="level">
|
||||
<el-select
|
||||
v-model="form.level"
|
||||
placeholder="全部"
|
||||
:value="1"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dict.type.alert_level"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input v-model="form.level" placeholder="请输入等级" />
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select
|
||||
v-model="form.type"
|
||||
placeholder="全部"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dict.type.alert_type"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-form-item label="类型" prop="typeName">
|
||||
<el-input v-model="clickNodeData.label" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="最小值" prop="minValue">
|
||||
<el-input-number :min="0" :precision="2" v-model="form.minValue" placeholder="请输入最小值" />
|
||||
|
@ -190,12 +128,16 @@
|
|||
|
||||
<script>
|
||||
import { listPlan, getPlan, delPlan, addPlan, updatePlan } from "@/api/board/plan";
|
||||
import PlanTypeTree from "@/views/board/plan/planTypeTree.vue";
|
||||
import {planTypeTreeSelect} from "@/api/board/plantype";
|
||||
|
||||
export default {
|
||||
name: "Plan",
|
||||
components: {PlanTypeTree},
|
||||
dicts: ['alert_level','alert_type'],
|
||||
data() {
|
||||
return {
|
||||
searchValue: "",
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
|
@ -224,6 +166,10 @@ export default {
|
|||
minValue: null,
|
||||
displayContent: null
|
||||
},
|
||||
clickNodeData: {
|
||||
id: 0,
|
||||
label: "",
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
|
@ -247,7 +193,7 @@ export default {
|
|||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getPlanTypeTree();
|
||||
},
|
||||
methods: {
|
||||
/** 查询警报计划列表 */
|
||||
|
@ -304,8 +250,6 @@ export default {
|
|||
const id = row.id || this.ids
|
||||
getPlan(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.form.type += '';
|
||||
this.form.level += '';
|
||||
this.open = true;
|
||||
this.title = "修改警报计划";
|
||||
});
|
||||
|
@ -321,6 +265,7 @@ export default {
|
|||
this.getList();
|
||||
});
|
||||
} else {
|
||||
this.form.type = this.clickNodeData.id;
|
||||
addPlan(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
|
@ -346,10 +291,18 @@ export default {
|
|||
...this.queryParams
|
||||
}, `plan_${new Date().getTime()}.xlsx`)
|
||||
},
|
||||
/** 字典翻译 */
|
||||
dictAlertPlanTypeFormat(){
|
||||
|
||||
}
|
||||
}
|
||||
handleNodeClick(data) {
|
||||
this.clickNodeData = data;
|
||||
this.queryParams.type = data.id;
|
||||
this.handleQuery();
|
||||
},
|
||||
getPlanTypeTree() {
|
||||
planTypeTreeSelect().then(response => {
|
||||
this.clickNodeData = response.data[0].children[0];
|
||||
this.queryParams.type = response.data[0].children[0].id;
|
||||
this.getList();
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-tree
|
||||
:data="planTypeOptions"
|
||||
node-key="id"
|
||||
:props="defaultProps"
|
||||
:filter-node-method="filterNode"
|
||||
@node-click="handleNodeClick"
|
||||
:expand-on-click-node="false"
|
||||
ref="tree"
|
||||
default-expand-all
|
||||
highlight-current
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div class="custom-tree-node">
|
||||
<span>{{ data.label }}</span>
|
||||
<span class="custom-tree-node-btns">
|
||||
<el-button
|
||||
type="text"
|
||||
icon="el-icon-plus"
|
||||
@click="handleAdd(node, data)"
|
||||
></el-button>
|
||||
<el-button
|
||||
type="text"
|
||||
icon="el-icon-minus"
|
||||
@click="handleDelete(node, data)"
|
||||
></el-button>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
|
||||
<!-- 新增节点对话框 -->
|
||||
<el-dialog
|
||||
title="新增节点"
|
||||
:visible.sync="dialogVisible">
|
||||
<el-form :model="form" label-width="auto">
|
||||
<el-form-item label="类型名称">
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-input v-model="form.label"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item label="节点类型">
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-select v-model="form.addType">
|
||||
<el-option
|
||||
v-for="item in [{label: '同级',value: true},{label: '子级',value: false},]"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"/>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmAdd">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 删除确认框 -->
|
||||
<el-dialog
|
||||
title="确认删除"
|
||||
:visible.sync="deleteDialogVisible"
|
||||
>
|
||||
<span>确定删除节点 "{{ selectedNodeLabel }}" 吗?</span>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="deleteDialogVisible = false">取消</el-button>
|
||||
<el-button type="danger" @click="confirmDelete">删除</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {addType, delType, planTypeTreeSelect} from "@/api/board/plantype";
|
||||
|
||||
export default {
|
||||
name: "PlanTypeTree",
|
||||
watch: {
|
||||
// 根据名称筛选部门树
|
||||
searchValue(val) {
|
||||
this.$refs.tree.filter(val);
|
||||
},
|
||||
},
|
||||
props: {
|
||||
searchValue: {
|
||||
type: String,
|
||||
default: "",
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
planTypeOptions: undefined,
|
||||
treeData: [],
|
||||
dialogVisible: false,
|
||||
deleteDialogVisible: false,
|
||||
form: {
|
||||
label: "",
|
||||
addType: true,
|
||||
selectedNodeId: 0,
|
||||
selectedNodeLevel: 0,
|
||||
selectedNodeParentId: 0,
|
||||
},
|
||||
parentNodeLabel: "",
|
||||
selectedNode: null,
|
||||
selectedNodeLabel: "",
|
||||
defaultProps: {
|
||||
children: "children",
|
||||
label: "label",
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleAdd(node, data) {
|
||||
this.selectedNode = node;
|
||||
this.parentNodeLabel = data.label;
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
confirmAdd() {
|
||||
let addObj = {
|
||||
typeName: this.form.label,
|
||||
parentId: this.form.selectedNodeId,
|
||||
}
|
||||
if (this.form.addType === true) {
|
||||
addObj.parentId = this.form.selectedNodeLevel === 1 ? 0 : this.form.selectedNodeParentId;
|
||||
}
|
||||
addType(addObj).then(resp => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.getPlanTypeTree();
|
||||
})
|
||||
this.dialogVisible = false;
|
||||
|
||||
},
|
||||
handleDelete(node, data) {
|
||||
this.selectedNode = node;
|
||||
this.selectedNodeLabel = data.label;
|
||||
this.deleteDialogVisible = true;
|
||||
},
|
||||
confirmDelete() {
|
||||
delType(this.form.selectedNodeId).then(resp => {
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
this.getPlanTypeTree();
|
||||
})
|
||||
this.deleteDialogVisible = false;
|
||||
},
|
||||
handleNodeClick(data, node) {
|
||||
if (node.level < 2) {
|
||||
return;
|
||||
}
|
||||
this.$emit('node-clicked', data);
|
||||
this.form.selectedNodeId = data.id;
|
||||
this.form.selectedNodeLevel = node.level;
|
||||
if (node.level === 1) {
|
||||
this.form.selectedNodeParentId = 0;
|
||||
} else {
|
||||
this.form.selectedNodeParentId = node.parent.data.id;
|
||||
}
|
||||
},
|
||||
/** 查询类型下拉树结构 */
|
||||
getPlanTypeTree() {
|
||||
planTypeTreeSelect().then(response => {
|
||||
this.planTypeOptions = response.data;
|
||||
});
|
||||
},
|
||||
// 筛选节点
|
||||
filterNode(value, data) {
|
||||
if (!value) return true;
|
||||
return data.label.indexOf(value) !== -1;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getPlanTypeTree();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.custom-tree-node {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.custom-tree-node-btns {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.custom-tree-node:hover .custom-tree-node-btns {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
|
@ -1,33 +1,34 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="20">
|
||||
<!--部门数据-->
|
||||
<el-col :span="4" :xs="24">
|
||||
<div class="head-container">
|
||||
<el-input
|
||||
v-model="deptName"
|
||||
placeholder="请输入部门名称"
|
||||
clearable
|
||||
size="small"
|
||||
prefix-icon="el-icon-search"
|
||||
style="margin-bottom: 20px"
|
||||
/>
|
||||
</div>
|
||||
<div class="head-container">
|
||||
<el-tree
|
||||
:data="deptOptions"
|
||||
:props="defaultProps"
|
||||
:expand-on-click-node="false"
|
||||
:filter-node-method="filterNode"
|
||||
ref="tree"
|
||||
node-key="id"
|
||||
default-expand-all
|
||||
highlight-current
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<h1>瓷器活发布系统</h1>
|
||||
<!-- <el-row :gutter="20">-->
|
||||
<!-- <!–部门数据–>-->
|
||||
<!-- <el-col :span="4" :xs="24">-->
|
||||
<!-- <div class="head-container">-->
|
||||
<!-- <el-input-->
|
||||
<!-- v-model="deptName"-->
|
||||
<!-- placeholder="请输入部门名称"-->
|
||||
<!-- clearable-->
|
||||
<!-- size="small"-->
|
||||
<!-- prefix-icon="el-icon-search"-->
|
||||
<!-- style="margin-bottom: 20px"-->
|
||||
<!-- />-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="head-container">-->
|
||||
<!-- <el-tree-->
|
||||
<!-- :data="deptOptions"-->
|
||||
<!-- :props="defaultProps"-->
|
||||
<!-- :expand-on-click-node="false"-->
|
||||
<!-- :filter-node-method="filterNode"-->
|
||||
<!-- ref="tree"-->
|
||||
<!-- node-key="id"-->
|
||||
<!-- default-expand-all-->
|
||||
<!-- highlight-current-->
|
||||
<!-- @node-click="handleNodeClick"-->
|
||||
<!-- />-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-col>-->
|
||||
<!-- </el-row>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ const CompressionPlugin = require('compression-webpack-plugin')
|
|||
|
||||
const name = process.env.VUE_APP_TITLE || '瓷器活发布系统' // 网页标题
|
||||
|
||||
const port = process.env.port || process.env.npm_config_port || 80 // 端口
|
||||
const port = process.env.port || process.env.npm_config_port || 8888 // 端口
|
||||
|
||||
// vue.config.js 配置说明
|
||||
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
|
||||
|
|
Loading…
Reference in New Issue