更新项目配置,新增设备同步模块,优化WebSocket和Swagger配置,增强SCADA系统的免登录接口,支持数据字典项和登录日志的免登录查询与记录。调整Java编译设置,确保更好的开发体验。
This commit is contained in:
@@ -61,6 +61,10 @@
|
||||
<artifactId>jeecg-boot-module-airag</artifactId>
|
||||
<version>${jeecgboot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-messaging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>pdfbox</artifactId>
|
||||
|
||||
@@ -10,9 +10,14 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import org.jeecg.common.base.BaseMap;
|
||||
import org.jeecg.common.constant.WebsocketConst;
|
||||
import org.jeecg.common.modules.redis.client.JeecgRedisClient;
|
||||
import org.jeecg.modules.system.entity.SysLog;
|
||||
import org.jeecg.modules.system.service.ISysLogService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Author scott
|
||||
@@ -27,6 +32,13 @@ public class WebSocket {
|
||||
/**线程安全Map*/
|
||||
private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 当前在线 WebSocket 连接数。
|
||||
*/
|
||||
public static int getOnlineCount() {
|
||||
return sessionPool.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Redis触发监听名字
|
||||
*/
|
||||
@@ -34,10 +46,15 @@ public class WebSocket {
|
||||
|
||||
//避免初次调用出现空指针的情况
|
||||
private static JeecgRedisClient jeecgRedisClient;
|
||||
private static ISysLogService sysLogService;
|
||||
@Autowired
|
||||
private void setJeecgRedisClient(JeecgRedisClient jeecgRedisClient){
|
||||
WebSocket.jeecgRedisClient = jeecgRedisClient;
|
||||
}
|
||||
@Autowired
|
||||
private void setSysLogService(ISysLogService sysLogService){
|
||||
WebSocket.sysLogService = sysLogService;
|
||||
}
|
||||
|
||||
|
||||
//==========【websocket接受、推送消息等方法 —— 具体服务节点推送ws消息】========================================================================================
|
||||
@@ -45,7 +62,7 @@ public class WebSocket {
|
||||
public void onOpen(Session session, @PathParam(value = "userId") String userId) {
|
||||
try {
|
||||
sessionPool.put(userId, session);
|
||||
log.debug("【系统 WebSocket】有新的连接,总数为:" + sessionPool.size());
|
||||
log.info("【系统 WebSocket】连接建立 userId={}, sessionId={}, online={}", userId, session.getId(), sessionPool.size());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
@@ -54,7 +71,7 @@ public class WebSocket {
|
||||
public void onClose(@PathParam("userId") String userId) {
|
||||
try {
|
||||
sessionPool.remove(userId);
|
||||
log.debug("【系统 WebSocket】连接断开,总数为:" + sessionPool.size());
|
||||
log.info("【系统 WebSocket】连接断开 userId={}, online={}", userId, sessionPool.size());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -67,6 +84,8 @@ public class WebSocket {
|
||||
* @param message
|
||||
*/
|
||||
public void pushMessage(String userId, String message) {
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
for (Map.Entry<String, Session> item : sessionPool.entrySet()) {
|
||||
//userId key值= {用户id + "_"+ 登录token的md5串}
|
||||
//TODO vue2未改key新规则,暂时不影响逻辑
|
||||
@@ -75,29 +94,57 @@ public class WebSocket {
|
||||
try {
|
||||
// 代码逻辑说明: websocket报错 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU
|
||||
synchronized (session){
|
||||
log.debug("【系统 WebSocket】推送单人消息:" + message);
|
||||
session.getBasicRemote().sendText(message);
|
||||
}
|
||||
successCount++;
|
||||
} catch (Exception e) {
|
||||
failCount++;
|
||||
log.error(e.getMessage(),e);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 日志分级策略:业务消息 info,心跳消息 debug,异常场景 warn/error
|
||||
if (failCount > 0) {
|
||||
log.warn("【系统 WebSocket】定向推送存在失败 userKeyContains={}, success={}, fail={}, payload={}",
|
||||
userId, successCount, failCount, message);
|
||||
} else if (isHeartbeatOrBlank(message == null ? "" : message.trim())) {
|
||||
log.debug("【系统 WebSocket】定向心跳推送 userKeyContains={}, success={}, fail={}",
|
||||
userId, successCount, failCount);
|
||||
} else {
|
||||
log.info("【系统 WebSocket】定向业务推送 userKeyContains={}, success={}, fail={}, payload={}",
|
||||
userId, successCount, failCount, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ws遍历群发消息
|
||||
*/
|
||||
public void pushMessage(String message) {
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
try {
|
||||
for (Map.Entry<String, Session> item : sessionPool.entrySet()) {
|
||||
String sessionKey = item.getKey();
|
||||
Session session = item.getValue();
|
||||
try {
|
||||
item.getValue().getAsyncRemote().sendText(message);
|
||||
if (session == null || !session.isOpen()) {
|
||||
failCount++;
|
||||
log.warn("【系统 WebSocket】连接不可用,跳过发送,key={}", sessionKey);
|
||||
continue;
|
||||
}
|
||||
// 使用同步发送提升送达确定性,避免 AsyncRemote 在断连边界下静默丢消息
|
||||
synchronized (session) {
|
||||
session.getBasicRemote().sendText(message);
|
||||
}
|
||||
successCount++;
|
||||
} catch (Exception e) {
|
||||
failCount++;
|
||||
log.warn("【系统 WebSocket】发送失败,key={},原因={}", sessionKey, e.getMessage());
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
log.debug("【系统 WebSocket】群发消息:" + message);
|
||||
log.info("【系统 WebSocket】群发完成 success={}, fail={}, online={}, payload={}",
|
||||
successCount, failCount, sessionPool.size(), message);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
@@ -109,13 +156,25 @@ public class WebSocket {
|
||||
*/
|
||||
@OnMessage
|
||||
public void onMessage(String message, @PathParam(value = "userId") String userId) {
|
||||
if(!"ping".equals(message) && !WebsocketConst.CMD_CHECK.equals(message)){
|
||||
log.debug("【系统 WebSocket】收到客户端消息:" + message);
|
||||
}else{
|
||||
log.debug("【系统 WebSocket】收到客户端消息:" + message);
|
||||
// 代码逻辑说明: 【issues/1161】前端websocket因心跳导致监听不起作用---
|
||||
this.sendMessage(userId, "ping");
|
||||
String normalized = message == null ? "" : message.trim();
|
||||
if (isHeartbeatOrBlank(normalized)) {
|
||||
log.debug("【系统 WebSocket】收到客户端心跳/空消息:{}", normalized);
|
||||
if ("ping".equalsIgnoreCase(normalized) || WebsocketConst.CMD_CHECK.equalsIgnoreCase(normalized)) {
|
||||
// 代码逻辑说明: 【issues/1161】前端websocket因心跳导致监听不起作用---
|
||||
this.sendMessage(userId, "ping");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isJsonMessage(normalized)) {
|
||||
log.debug("【系统 WebSocket】忽略非JSON消息:{}", normalized);
|
||||
return;
|
||||
}
|
||||
|
||||
if (handleScadaLog(normalized, userId)) {
|
||||
return;
|
||||
}
|
||||
log.debug("【系统 WebSocket】收到客户端消息:" + normalized);
|
||||
|
||||
// //------------------------------------------------------------------------------
|
||||
// JSONObject obj = new JSONObject();
|
||||
@@ -179,6 +238,82 @@ public class WebSocket {
|
||||
sendMessage(userId, message);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleScadaLog(String message, String userId) {
|
||||
try {
|
||||
JSONObject obj = JSONObject.parseObject(message);
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
String cmd = obj.getString("cmd");
|
||||
if (!"SCADA_LOGIN_LOG".equals(cmd) && !"SCADA_LOG".equals(cmd)) {
|
||||
return false;
|
||||
}
|
||||
if (sysLogService == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String category = obj.getString("category");
|
||||
String account = obj.getString("account");
|
||||
Boolean success = obj.getBoolean("success");
|
||||
String msg = obj.getString("message");
|
||||
String clientIp = obj.getString("clientIp");
|
||||
String clientType = normalizeClientType(obj.getString("clientType"));
|
||||
String exception = obj.getString("exception");
|
||||
Integer logType = obj.getInteger("logType");
|
||||
Integer operateType = obj.getInteger("operateType");
|
||||
String method = obj.getString("method");
|
||||
String requestUrl = obj.getString("requestUrl");
|
||||
|
||||
SysLog logEntity = new SysLog();
|
||||
logEntity.setCreateTime(new Date());
|
||||
logEntity.setLogType(logType == null ? ("EXCEPTION".equalsIgnoreCase(category) ? 2 : 1) : logType);
|
||||
logEntity.setOperateType(operateType == null ? ("LOGIN".equalsIgnoreCase(category) ? 1 : 5) : operateType);
|
||||
logEntity.setRequestType("WS");
|
||||
logEntity.setRequestUrl(oConvertUtils.isEmpty(requestUrl) ? ("/websocket/" + userId) : requestUrl);
|
||||
logEntity.setMethod(oConvertUtils.isEmpty(method) ? "SCADA_LOG" : method);
|
||||
logEntity.setUsername(account);
|
||||
logEntity.setUserid(account);
|
||||
logEntity.setIp(oConvertUtils.isEmpty(clientIp) ? "desktop" : clientIp);
|
||||
logEntity.setClientType(clientType);
|
||||
if ("LOGIN".equalsIgnoreCase(category) || "SCADA_LOGIN_LOG".equals(cmd)) {
|
||||
logEntity.setLogContent(String.format("桌面端登录%s:%s", Boolean.TRUE.equals(success) ? "成功" : "失败", oConvertUtils.isEmpty(msg) ? "" : msg));
|
||||
} else if ("EXCEPTION".equalsIgnoreCase(category)) {
|
||||
String exceptionMsg = oConvertUtils.isEmpty(exception) ? "" : (" 异常: " + exception);
|
||||
logEntity.setLogContent(String.format("桌面端异常日志:%s%s", oConvertUtils.isEmpty(msg) ? "" : msg, exceptionMsg));
|
||||
} else {
|
||||
logEntity.setLogContent(String.format("桌面端操作日志:%s", oConvertUtils.isEmpty(msg) ? "" : msg));
|
||||
}
|
||||
logEntity.setRequestParam(message);
|
||||
sysLogService.save(logEntity);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.warn("处理 SCADA 登录日志消息失败: {}", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isHeartbeatOrBlank(String message) {
|
||||
return oConvertUtils.isEmpty(message)
|
||||
|| "ping".equalsIgnoreCase(message)
|
||||
|| "pong".equalsIgnoreCase(message)
|
||||
|| WebsocketConst.CMD_CHECK.equalsIgnoreCase(message);
|
||||
}
|
||||
|
||||
private boolean isJsonMessage(String message) {
|
||||
return !oConvertUtils.isEmpty(message) && message.startsWith("{");
|
||||
}
|
||||
|
||||
private String normalizeClientType(String rawClientType) {
|
||||
if (oConvertUtils.isEmpty(rawClientType)) {
|
||||
return "gkj";
|
||||
}
|
||||
String value = rawClientType.trim().toLowerCase();
|
||||
if ("desktop".equals(value) || "pc".equals(value) || "windows".equals(value)) {
|
||||
return "gkj";
|
||||
}
|
||||
return value;
|
||||
}
|
||||
//=======【采用redis发布订阅模式——推送消息】==========================================================================================
|
||||
|
||||
}
|
||||
@@ -40,6 +40,7 @@ import org.jeecgframework.poi.excel.entity.ExportParams;
|
||||
import org.jeecgframework.poi.excel.entity.ImportParams;
|
||||
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
|
||||
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
@@ -153,6 +154,108 @@ public class SysDictController {
|
||||
return Result.ok(res);
|
||||
}
|
||||
|
||||
/**
|
||||
* SCADA 系统专用:免登录查询数据字典项。
|
||||
* 支持按 dictCode / dictName / itemText / itemValue 条件过滤,支持增量同步。
|
||||
*/
|
||||
@GetMapping("/scada/queryDictItem")
|
||||
@Operation(summary = "SCADA-免登录查询数据字典项")
|
||||
public Result<List<Map<String, Object>>> scadaQueryDictItem(
|
||||
@RequestParam(name = "dictCode", required = false) String dictCode,
|
||||
@RequestParam(name = "dictName", required = false) String dictName,
|
||||
@RequestParam(name = "itemText", required = false) String itemText,
|
||||
@RequestParam(name = "itemValue", required = false) String itemValue,
|
||||
@RequestParam(name = "status", required = false) Integer status,
|
||||
@RequestParam(name = "updatedAfter", required = false) String updatedAfter,
|
||||
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "500") Integer pageSize) {
|
||||
|
||||
if (pageNo == null || pageNo < 1) {
|
||||
pageNo = 1;
|
||||
}
|
||||
if (pageSize == null || pageSize < 1) {
|
||||
pageSize = 500;
|
||||
}
|
||||
pageSize = Math.min(pageSize, 1000);
|
||||
|
||||
LambdaQueryWrapper<SysDictItem> itemWrapper = new LambdaQueryWrapper<>();
|
||||
itemWrapper.like(oConvertUtils.isNotEmpty(itemText), SysDictItem::getItemText, itemText);
|
||||
itemWrapper.like(oConvertUtils.isNotEmpty(itemValue), SysDictItem::getItemValue, itemValue);
|
||||
itemWrapper.eq(status != null, SysDictItem::getStatus, status);
|
||||
|
||||
if (oConvertUtils.isNotEmpty(updatedAfter)) {
|
||||
try {
|
||||
Date parsedSyncTime;
|
||||
try {
|
||||
parsedSyncTime = DateUtils.parseDate(updatedAfter, "yyyy-MM-dd HH:mm:ss");
|
||||
} catch (Exception firstEx) {
|
||||
parsedSyncTime = DateUtils.parseDate(updatedAfter, "yyyy-MM-dd'T'HH:mm:ss");
|
||||
}
|
||||
final Date syncTime = parsedSyncTime;
|
||||
itemWrapper.and(w -> w.ge(SysDictItem::getUpdateTime, syncTime).or().ge(SysDictItem::getCreateTime, syncTime));
|
||||
} catch (Exception e) {
|
||||
return Result.error("updatedAfter格式错误,支持:yyyy-MM-dd HH:mm:ss 或 yyyy-MM-dd'T'HH:mm:ss");
|
||||
}
|
||||
}
|
||||
|
||||
// 若传入字典头过滤条件,先按字典头筛出 dictId 再查询字典项
|
||||
if (oConvertUtils.isNotEmpty(dictCode) || oConvertUtils.isNotEmpty(dictName)) {
|
||||
LambdaQueryWrapper<SysDict> dictFilter = new LambdaQueryWrapper<>();
|
||||
dictFilter.eq(SysDict::getDelFlag, CommonConstant.DEL_FLAG_0);
|
||||
dictFilter.like(oConvertUtils.isNotEmpty(dictCode), SysDict::getDictCode, dictCode);
|
||||
dictFilter.like(oConvertUtils.isNotEmpty(dictName), SysDict::getDictName, dictName);
|
||||
List<SysDict> filteredDicts = sysDictService.list(dictFilter);
|
||||
if (oConvertUtils.isEmpty(filteredDicts)) {
|
||||
return Result.ok(new ArrayList<>());
|
||||
}
|
||||
List<String> filteredDictIds = filteredDicts.stream().map(SysDict::getId).collect(java.util.stream.Collectors.toList());
|
||||
itemWrapper.in(SysDictItem::getDictId, filteredDictIds);
|
||||
}
|
||||
|
||||
itemWrapper.orderByAsc(SysDictItem::getSortOrder);
|
||||
itemWrapper.orderByDesc(SysDictItem::getCreateTime);
|
||||
|
||||
IPage<SysDictItem> itemPage = sysDictItemService.page(new Page<>(pageNo, pageSize), itemWrapper);
|
||||
List<SysDictItem> itemList = itemPage.getRecords();
|
||||
if (oConvertUtils.isEmpty(itemList)) {
|
||||
return Result.ok(new ArrayList<>());
|
||||
}
|
||||
|
||||
List<String> dictIds = itemList.stream().map(SysDictItem::getDictId).distinct().collect(java.util.stream.Collectors.toList());
|
||||
LambdaQueryWrapper<SysDict> dictQuery = new LambdaQueryWrapper<>();
|
||||
dictQuery.in(SysDict::getId, dictIds);
|
||||
dictQuery.eq(SysDict::getDelFlag, CommonConstant.DEL_FLAG_0);
|
||||
List<SysDict> dictList = sysDictService.list(dictQuery);
|
||||
Map<String, SysDict> dictMap = dictList.stream().collect(java.util.stream.Collectors.toMap(SysDict::getId, d -> d));
|
||||
|
||||
List<Map<String, Object>> resultList = new ArrayList<>();
|
||||
for (SysDictItem item : itemList) {
|
||||
SysDict dict = dictMap.get(item.getDictId());
|
||||
if (dict == null) {
|
||||
continue;
|
||||
}
|
||||
Map<String, Object> row = new LinkedHashMap<>(24);
|
||||
row.put("id", item.getId());
|
||||
row.put("dictId", item.getDictId());
|
||||
row.put("dictName", dict.getDictName());
|
||||
row.put("dictCode", dict.getDictCode());
|
||||
row.put("dictType", dict.getType());
|
||||
row.put("dictDescription", dict.getDescription());
|
||||
row.put("itemText", item.getItemText());
|
||||
row.put("itemValue", item.getItemValue());
|
||||
row.put("itemDescription", item.getDescription());
|
||||
row.put("sortOrder", item.getSortOrder());
|
||||
row.put("status", item.getStatus());
|
||||
row.put("itemColor", item.getItemColor());
|
||||
row.put("createBy", item.getCreateBy());
|
||||
row.put("createTime", item.getCreateTime());
|
||||
row.put("updateBy", item.getUpdateBy());
|
||||
row.put("updateTime", item.getUpdateTime());
|
||||
resultList.add(row);
|
||||
}
|
||||
return Result.ok(resultList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典数据
|
||||
* @param dictCode
|
||||
|
||||
@@ -8,11 +8,11 @@ import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.IpUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.JeecgBaseConfig;
|
||||
import org.jeecg.modules.system.entity.SysLog;
|
||||
@@ -23,6 +23,8 @@ import org.jeecgframework.poi.excel.entity.ExportParams;
|
||||
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
|
||||
import org.jeecgframework.poi.handler.inter.IExcelExportServerEnhanced;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@@ -32,6 +34,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@@ -51,6 +54,77 @@ public class SysLogController extends JeecgController<SysLog, ISysLogService> {
|
||||
@Autowired
|
||||
private ISysLogService sysLogService;
|
||||
|
||||
@PostMapping("/scada/addLoginLog")
|
||||
@Operation(summary = "SCADA-免登录写入登录日志")
|
||||
public Result<String> scadaAddLoginLog(@RequestBody java.util.Map<String, Object> payload, HttpServletRequest request) {
|
||||
payload.put("category", "LOGIN");
|
||||
return scadaAddLog(payload, request);
|
||||
}
|
||||
|
||||
@PostMapping("/scada/addLog")
|
||||
@Operation(summary = "SCADA-免登录写入通用日志")
|
||||
public Result<String> scadaAddLog(@RequestBody java.util.Map<String, Object> payload, HttpServletRequest request) {
|
||||
try {
|
||||
String account = oConvertUtils.getString(payload.get("account"));
|
||||
String message = oConvertUtils.getString(payload.get("message"));
|
||||
String category = oConvertUtils.getString(payload.get("category"));
|
||||
boolean success = Boolean.parseBoolean(oConvertUtils.getString(payload.get("success")));
|
||||
String clientType = normalizeClientType(oConvertUtils.getString(payload.get("clientType")));
|
||||
String exception = oConvertUtils.getString(payload.get("exception"));
|
||||
int logType = oConvertUtils.getInt(payload.get("logType"), "EXCEPTION".equalsIgnoreCase(category) ? 2 : 1);
|
||||
int operateType = oConvertUtils.getInt(payload.get("operateType"), "LOGIN".equalsIgnoreCase(category) ? 1 : 5);
|
||||
String method = oConvertUtils.getString(payload.get("method"));
|
||||
if (oConvertUtils.isEmpty(method)) {
|
||||
method = "LOGIN".equalsIgnoreCase(category) ? "LOGIN" : "SCADA_LOG";
|
||||
}
|
||||
String requestUrl = oConvertUtils.getString(payload.get("requestUrl"));
|
||||
if (oConvertUtils.isEmpty(requestUrl)) {
|
||||
requestUrl = "/sys/log/scada/addLog";
|
||||
}
|
||||
|
||||
SysLog logEntity = new SysLog();
|
||||
logEntity.setCreateTime(new java.util.Date());
|
||||
logEntity.setLogType(logType);
|
||||
logEntity.setOperateType(operateType);
|
||||
logEntity.setRequestType("WS/HTTP");
|
||||
logEntity.setRequestUrl(requestUrl);
|
||||
logEntity.setMethod(method);
|
||||
logEntity.setUsername(account);
|
||||
logEntity.setUserid(account);
|
||||
logEntity.setIp(IpUtils.getIpAddr(request));
|
||||
logEntity.setClientType(clientType);
|
||||
logEntity.setLogContent(buildLogContent(category, success, message, exception));
|
||||
logEntity.setRequestParam(com.alibaba.fastjson.JSON.toJSONString(payload));
|
||||
sysLogService.save(logEntity);
|
||||
return Result.OK("ok");
|
||||
} catch (Exception e) {
|
||||
log.error("SCADA写入日志失败", e);
|
||||
return Result.error("写入失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String buildLogContent(String category, boolean success, String message, String exception) {
|
||||
if ("LOGIN".equalsIgnoreCase(category)) {
|
||||
return String.format("桌面端登录%s:%s", success ? "成功" : "失败", oConvertUtils.isEmpty(message) ? "" : message);
|
||||
}
|
||||
if ("EXCEPTION".equalsIgnoreCase(category)) {
|
||||
String exceptionMsg = oConvertUtils.isEmpty(exception) ? "" : (" 异常: " + exception);
|
||||
return String.format("桌面端异常日志:%s%s", oConvertUtils.isEmpty(message) ? "" : message, exceptionMsg);
|
||||
}
|
||||
return String.format("桌面端操作日志:%s", oConvertUtils.isEmpty(message) ? "" : message);
|
||||
}
|
||||
|
||||
private String normalizeClientType(String rawClientType) {
|
||||
if (oConvertUtils.isEmpty(rawClientType)) {
|
||||
return "gkj";
|
||||
}
|
||||
String value = rawClientType.trim().toLowerCase();
|
||||
if ("desktop".equals(value) || "pc".equals(value) || "windows".equals(value)) {
|
||||
return "gkj";
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* for [issues/8699]AutoPoi在使用@ExcelEntity当设置show=true并且该项为null时报错
|
||||
*/
|
||||
|
||||
@@ -9,8 +9,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.time.DateUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
@@ -22,6 +25,7 @@ import org.jeecg.common.constant.CacheConstant;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.PasswordConstant;
|
||||
import org.jeecg.common.constant.SymbolConstant;
|
||||
import org.jeecg.common.constant.WebsocketConst;
|
||||
import org.jeecg.common.modules.redis.client.JeecgRedisClient;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
@@ -35,11 +39,13 @@ import org.jeecg.modules.system.excelstyle.ExcelExportSysUserStyle;
|
||||
import org.jeecg.modules.system.model.DepartIdModel;
|
||||
import org.jeecg.modules.system.model.SysUserSysDepPostModel;
|
||||
import org.jeecg.modules.system.model.SysUserSysDepartModel;
|
||||
import org.jeecg.modules.message.websocket.WebSocket;
|
||||
import org.jeecg.modules.system.service.*;
|
||||
import org.jeecg.modules.system.util.ImportSysUserCache;
|
||||
import org.jeecg.modules.system.vo.SysDepartUsersVO;
|
||||
import org.jeecg.modules.system.vo.SysUserExportVo;
|
||||
import org.jeecg.modules.system.vo.SysUserRoleVO;
|
||||
import org.jeecg.modules.system.vo.SysUserTenantVo;
|
||||
import org.jeecg.modules.system.vo.lowapp.DepartAndUserInfo;
|
||||
import org.jeecg.modules.system.vo.lowapp.UpdateDepartInfo;
|
||||
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
||||
@@ -48,6 +54,7 @@ import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
|
||||
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@@ -70,6 +77,7 @@ import java.util.stream.Collectors;
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/sys/user")
|
||||
@Tag(name = "用户管理")
|
||||
public class SysUserController {
|
||||
|
||||
@Autowired
|
||||
@@ -109,6 +117,66 @@ public class SysUserController {
|
||||
private JeecgRedisClient jeecgRedisClient;
|
||||
@Autowired
|
||||
private JeecgBaseConfig jeecgBaseConfig;
|
||||
|
||||
@Autowired
|
||||
private WebSocket webSocket;
|
||||
|
||||
/** 设备同步模块 STOMP:与桌面端统一通道 /topic/sync/jeecg-users(无 device-sync 模块时为 null) */
|
||||
@Autowired(required = false)
|
||||
private SimpMessagingTemplate simpMessagingTemplate;
|
||||
|
||||
private void notifyScadaUserChanged(String action, String userId) {
|
||||
try {
|
||||
JSONObject payload = new JSONObject();
|
||||
payload.put(WebsocketConst.MSG_CMD, "SCADA_USER_CHANGED");
|
||||
payload.put("action", action);
|
||||
payload.put("userId", userId);
|
||||
payload.put("timestamp", System.currentTimeMillis());
|
||||
log.info("SCADA用户变更通知开始 action={}, userId={}, onlineWs={}", action, userId, WebSocket.getOnlineCount());
|
||||
// 固定工控机通道定向推送(桌面端连接 /websocket/scada-sync)
|
||||
webSocket.pushMessage("scada-sync", payload.toJSONString());
|
||||
// 单机直推(避免仅依赖Redis链路导致消息偶发丢失)
|
||||
webSocket.pushMessage(payload.toJSONString());
|
||||
// 集群转发:通过Redis发布订阅推送到其它节点在线客户端
|
||||
webSocket.sendMessage(payload.toJSONString());
|
||||
pushUserChangeToStompTopic(payload.toJSONString());
|
||||
log.info("SCADA用户变更通知完成 action={}, userId={}, payload={}", action, userId, payload.toJSONString());
|
||||
} catch (Exception e) {
|
||||
log.warn("推送SCADA用户变更消息失败 action={}, userId={}", action, userId, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void pushUserChangeToStompTopic(String jsonPayload) {
|
||||
if (simpMessagingTemplate == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
simpMessagingTemplate.convertAndSend("/topic/sync/jeecg-users", jsonPayload);
|
||||
} catch (Exception e) {
|
||||
log.debug("STOMP 广播用户变更跳过(device-sync 未启用或 Broker 未就绪): {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyScadaUsersChanged(String action, String ids) {
|
||||
try {
|
||||
JSONObject payload = new JSONObject();
|
||||
payload.put(WebsocketConst.MSG_CMD, "SCADA_USER_CHANGED");
|
||||
payload.put("action", action);
|
||||
payload.put("userIds", ids);
|
||||
payload.put("timestamp", System.currentTimeMillis());
|
||||
log.info("SCADA批量用户变更通知开始 action={}, ids={}, onlineWs={}", action, ids, WebSocket.getOnlineCount());
|
||||
// 固定工控机通道定向推送(桌面端连接 /websocket/scada-sync)
|
||||
webSocket.pushMessage("scada-sync", payload.toJSONString());
|
||||
// 单机直推(避免仅依赖Redis链路导致消息偶发丢失)
|
||||
webSocket.pushMessage(payload.toJSONString());
|
||||
// 集群转发:通过Redis发布订阅推送到其它节点在线客户端
|
||||
webSocket.sendMessage(payload.toJSONString());
|
||||
pushUserChangeToStompTopic(payload.toJSONString());
|
||||
log.info("SCADA批量用户变更通知完成 action={}, ids={}, payload={}", action, ids, payload.toJSONString());
|
||||
} catch (Exception e) {
|
||||
log.warn("推送SCADA批量用户变更消息失败 action={}, ids={}", action, ids, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取租户下用户数据(支持租户隔离)
|
||||
@@ -119,6 +187,7 @@ public class SysUserController {
|
||||
* @return
|
||||
*/
|
||||
@PermissionData(pageComponent = "system/UserList")
|
||||
@Operation(summary = "用户管理-分页查询")
|
||||
@RequestMapping(value = "/list", method = RequestMethod.GET)
|
||||
public Result<IPage<SysUser>> queryPageList(SysUser user,@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,HttpServletRequest req) {
|
||||
@@ -156,6 +225,7 @@ public class SysUserController {
|
||||
}
|
||||
|
||||
@RequiresPermissions("system:user:add")
|
||||
@Operation(summary = "用户管理-新增用户")
|
||||
@RequestMapping(value = "/add", method = RequestMethod.POST)
|
||||
public Result<SysUser> add(@RequestBody JSONObject jsonObject) {
|
||||
Result<SysUser> result = new Result<SysUser>();
|
||||
@@ -178,6 +248,7 @@ public class SysUserController {
|
||||
String relTenantIds = jsonObject.getString("relTenantIds");
|
||||
sysUserService.saveUser(user, selectedRoles, selectedDeparts, relTenantIds, false);
|
||||
baseCommonService.addLog("添加用户,username: " +user.getUsername() ,CommonConstant.LOG_TYPE_2, 2);
|
||||
notifyScadaUserChanged("add", user.getId());
|
||||
result.success("添加成功!");
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
@@ -187,6 +258,7 @@ public class SysUserController {
|
||||
}
|
||||
|
||||
@RequiresPermissions("system:user:edit")
|
||||
@Operation(summary = "用户管理-编辑用户")
|
||||
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
|
||||
public Result<SysUser> edit(@RequestBody JSONObject jsonObject) {
|
||||
Result<SysUser> result = new Result<SysUser>();
|
||||
@@ -215,6 +287,7 @@ public class SysUserController {
|
||||
//update-begin---author:wangshuai---date:2025-11-12---for:【JHHB-776】用户编辑,应该从数据库查出老数据,页面传递什么字段,把这些字段覆盖数据库查询结果,再更新---
|
||||
oConvertUtils.copyNonNullFields(user, sysUser);
|
||||
sysUserService.editUser(sysUser, roles, departs, relTenantIds, updateFromPage);
|
||||
notifyScadaUserChanged("edit", sysUser.getId());
|
||||
//update-end---author:wangshuai---date:2025-11-12---for:【JHHB-776】用户编辑,应该从数据库查出老数据,页面传递什么字段,把这些字段覆盖数据库查询结果,再更新---
|
||||
result.success("修改成功!");
|
||||
}
|
||||
@@ -253,6 +326,7 @@ public class SysUserController {
|
||||
String relTenantIds = jsonObject.getString("relTenantIds");
|
||||
sysUserService.saveUser(user, selectedRoles, selectedDeparts, relTenantIds, true);
|
||||
baseCommonService.addLog("添加用户,username: " + user.getUsername(), CommonConstant.LOG_TYPE_2, 2);
|
||||
notifyScadaUserChanged("addTenantUser", user.getId());
|
||||
result.success("添加成功!");
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
@@ -265,11 +339,13 @@ public class SysUserController {
|
||||
* 删除用户
|
||||
*/
|
||||
@RequiresPermissions("system:user:delete")
|
||||
@Operation(summary = "用户管理-删除用户")
|
||||
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
|
||||
public Result<?> delete(@RequestParam(name="id",required=true) String id) {
|
||||
baseCommonService.addLog("删除用户,id: " +id ,CommonConstant.LOG_TYPE_2, 3);
|
||||
List<String> userNameList = sysUserService.userIdToUsername(Arrays.asList(id));
|
||||
this.sysUserService.deleteUser(id);
|
||||
notifyScadaUserChanged("delete", id);
|
||||
|
||||
if (!userNameList.isEmpty()) {
|
||||
String joinedString = String.join(",", userNameList);
|
||||
@@ -281,11 +357,13 @@ public class SysUserController {
|
||||
* 批量删除用户
|
||||
*/
|
||||
@RequiresPermissions("system:user:deleteBatch")
|
||||
@Operation(summary = "用户管理-批量删除用户")
|
||||
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
|
||||
public Result<?> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
|
||||
baseCommonService.addLog("批量删除用户, ids: " +ids ,CommonConstant.LOG_TYPE_2, 3);
|
||||
List<String> userNameList = sysUserService.userIdToUsername(Arrays.asList(ids.split(",")));
|
||||
this.sysUserService.deleteBatchUsers(ids);
|
||||
notifyScadaUsersChanged("deleteBatch", ids);
|
||||
|
||||
// 用户变更,触发同步工作流
|
||||
if (!userNameList.isEmpty()) {
|
||||
@@ -312,6 +390,7 @@ public class SysUserController {
|
||||
if(oConvertUtils.isNotEmpty(id)) {
|
||||
// 代码逻辑说明: [QQYUN-5577]用户列表-冻结用户,再解冻之后,用户还是无法登陆,有缓存问题 #5066------------
|
||||
sysUserService.updateStatus(id,status);
|
||||
notifyScadaUserChanged("status", id);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -329,6 +408,7 @@ public class SysUserController {
|
||||
*/
|
||||
@RequiresRoles({"admin"})
|
||||
@RequiresPermissions("system:user:resetPassword")
|
||||
@Operation(summary = "用户管理-重置密码")
|
||||
@RequestMapping(value = "/resetPassword", method = RequestMethod.PUT)
|
||||
public Result<SysUser> resetPassword(@RequestParam(name = "usernames") String usernames) {
|
||||
Result<SysUser> result = new Result<SysUser>();
|
||||
@@ -344,6 +424,7 @@ public class SysUserController {
|
||||
}
|
||||
|
||||
@RequiresPermissions("system:user:queryById")
|
||||
@Operation(summary = "用户管理-根据ID查询")
|
||||
@RequestMapping(value = "/queryById", method = RequestMethod.GET)
|
||||
public Result<SysUser> queryById(@RequestParam(name = "id", required = true) String id) {
|
||||
Result<SysUser> result = new Result<SysUser>();
|
||||
@@ -384,6 +465,7 @@ public class SysUserController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/checkOnlyUser", method = RequestMethod.GET)
|
||||
@Operation(summary = "用户管理-校验账号唯一")
|
||||
public Result<Boolean> checkOnlyUser(SysUser sysUser) {
|
||||
Result<Boolean> result = new Result<>();
|
||||
//如果此参数为false则程序发生异常
|
||||
@@ -411,6 +493,7 @@ public class SysUserController {
|
||||
* 修改密码
|
||||
*/
|
||||
@RequiresPermissions("system:user:changepwd")
|
||||
@Operation(summary = "用户管理-修改密码")
|
||||
@RequestMapping(value = "/changePassword", method = RequestMethod.PUT)
|
||||
public Result<?> changePassword(@RequestBody SysUser sysUser, HttpServletRequest request) {
|
||||
//-------------------------------------------------------------------------------------
|
||||
@@ -432,6 +515,107 @@ public class SysUserController {
|
||||
return sysUserService.changePassword(sysUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* SCADA 系统专用:免登录查询用户信息。
|
||||
* 支持通过 username / workNo / phone 任一条件查询,返回基础信息(不返回敏感字段)。
|
||||
*/
|
||||
@GetMapping("/scada/queryUser")
|
||||
@Operation(summary = "SCADA-免登录查询用户信息")
|
||||
public Result<List<Map<String, Object>>> scadaQueryUser(@RequestParam(name = "username", required = false) String username,
|
||||
@RequestParam(name = "workNo", required = false) String workNo,
|
||||
@RequestParam(name = "phone", required = false) String phone,
|
||||
@RequestParam(name = "updatedAfter", required = false) String updatedAfter,
|
||||
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "200") Integer pageSize,
|
||||
@RequestParam(name = "includeDetail", defaultValue = "false") Boolean includeDetail) {
|
||||
if (pageNo == null || pageNo < 1) {
|
||||
pageNo = 1;
|
||||
}
|
||||
if (pageSize == null || pageSize < 1) {
|
||||
pageSize = 200;
|
||||
}
|
||||
// 控制单次最大拉取量,避免接口被大查询拖慢
|
||||
pageSize = Math.min(pageSize, 1000);
|
||||
|
||||
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysUser::getDelFlag, CommonConstant.DEL_FLAG_0);
|
||||
queryWrapper.eq(SysUser::getStatus, Integer.valueOf(CommonConstant.STATUS_1));
|
||||
queryWrapper.eq(oConvertUtils.isNotEmpty(username), SysUser::getUsername, username);
|
||||
queryWrapper.eq(oConvertUtils.isNotEmpty(workNo), SysUser::getWorkNo, workNo);
|
||||
queryWrapper.eq(oConvertUtils.isNotEmpty(phone), SysUser::getPhone, phone);
|
||||
if (oConvertUtils.isNotEmpty(updatedAfter)) {
|
||||
try {
|
||||
Date syncTime = DateUtils.parseDate(updatedAfter, new String[]{"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss"});
|
||||
queryWrapper.and(w -> w.ge(SysUser::getUpdateTime, syncTime).or().ge(SysUser::getCreateTime, syncTime));
|
||||
} catch (Exception e) {
|
||||
return Result.error("updatedAfter格式错误,支持:yyyy-MM-dd HH:mm:ss 或 yyyy-MM-dd'T'HH:mm:ss");
|
||||
}
|
||||
}
|
||||
queryWrapper.orderByAsc(SysUser::getSort);
|
||||
queryWrapper.orderByDesc(SysUser::getCreateTime);
|
||||
|
||||
IPage<SysUser> userPage = sysUserService.page(new Page<>(pageNo, pageSize), queryWrapper);
|
||||
List<SysUser> userList = userPage.getRecords();
|
||||
|
||||
List<Map<String, Object>> resultList = new ArrayList<>();
|
||||
for (SysUser user : userList) {
|
||||
List<Map<String, Object>> departList = new ArrayList<>();
|
||||
List<Map<String, Object>> companyList = new ArrayList<>();
|
||||
List<Map<String, Object>> tenantList = new ArrayList<>();
|
||||
|
||||
if (Boolean.TRUE.equals(includeDetail)) {
|
||||
List<SysDepart> userDeparts = sysDepartService.queryUserDeparts(user.getId());
|
||||
for (SysDepart depart : userDeparts) {
|
||||
Map<String, Object> departInfo = new LinkedHashMap<>(8);
|
||||
departInfo.put("id", depart.getId());
|
||||
departInfo.put("departName", depart.getDepartName());
|
||||
departInfo.put("orgCode", depart.getOrgCode());
|
||||
departInfo.put("orgCategory", depart.getOrgCategory());
|
||||
departList.add(departInfo);
|
||||
// 机构类别:1公司、4子公司
|
||||
if ("1".equals(depart.getOrgCategory()) || "4".equals(depart.getOrgCategory())) {
|
||||
companyList.add(departInfo);
|
||||
}
|
||||
}
|
||||
List<SysUserTenantVo> userTenants = userTenantService.getTenantListByUserId(user.getId(), Collections.singletonList(CommonConstant.STATUS_1));
|
||||
for (SysUserTenantVo tenantVo : userTenants) {
|
||||
Map<String, Object> tenantInfo = new LinkedHashMap<>(8);
|
||||
tenantInfo.put("tenantId", tenantVo.getRelTenantIds());
|
||||
tenantInfo.put("tenantName", tenantVo.getName());
|
||||
tenantInfo.put("tenantUserStatus", tenantVo.getUserTenantStatus());
|
||||
tenantInfo.put("tenantUserId", tenantVo.getTenantUserId());
|
||||
tenantInfo.put("tenantAdmin", tenantVo.getTenantAdmin());
|
||||
tenantList.add(tenantInfo);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> userInfo = new LinkedHashMap<>(16);
|
||||
userInfo.put("id", user.getId());
|
||||
userInfo.put("username", user.getUsername());
|
||||
userInfo.put("realname", user.getRealname());
|
||||
// SysUser无独立nickname字段,SCADA同步端约定用realname兼容昵称展示
|
||||
userInfo.put("nickname", user.getRealname());
|
||||
userInfo.put("password", user.getPassword());
|
||||
userInfo.put("salt", user.getSalt());
|
||||
userInfo.put("workNo", user.getWorkNo());
|
||||
userInfo.put("phone", user.getPhone());
|
||||
userInfo.put("email", user.getEmail());
|
||||
userInfo.put("orgCode", user.getOrgCode());
|
||||
userInfo.put("post", user.getPost());
|
||||
userInfo.put("status", user.getStatus());
|
||||
userInfo.put("createTime", user.getCreateTime());
|
||||
userInfo.put("updateTime", user.getUpdateTime());
|
||||
userInfo.put("lastPwdUpdateTime", user.getLastPwdUpdateTime());
|
||||
userInfo.put("departIds", user.getDepartIds());
|
||||
userInfo.put("departmentList", departList);
|
||||
userInfo.put("companyList", companyList);
|
||||
userInfo.put("loginTenantId", user.getLoginTenantId());
|
||||
userInfo.put("tenantList", tenantList);
|
||||
resultList.add(userInfo);
|
||||
}
|
||||
return Result.ok(resultList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定用户和部门关联的数据
|
||||
*
|
||||
|
||||
@@ -36,6 +36,12 @@
|
||||
<artifactId>jeecg-module-xslmes</artifactId>
|
||||
<version>${jeecgboot.version}</version>
|
||||
</dependency>
|
||||
<!-- 设备断联续传同步模块 -->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot3</groupId>
|
||||
<artifactId>jeecg-module-device-sync</artifactId>
|
||||
<version>${jeecgboot.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- flyway 数据库自动升级 -->
|
||||
<dependency>
|
||||
|
||||
@@ -22,7 +22,10 @@ import java.util.Map;
|
||||
* 报错提醒: 未集成mongo报错,可以打开启动类上面的注释 exclude={MongoAutoConfiguration.class}
|
||||
*/
|
||||
@Slf4j
|
||||
@SpringBootApplication(exclude = MongoAutoConfiguration.class)
|
||||
@SpringBootApplication(
|
||||
exclude = MongoAutoConfiguration.class,
|
||||
scanBasePackages = {"org.jeecg"}
|
||||
)
|
||||
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
|
||||
public class JeecgSystemApplication extends SpringBootServletInitializer {
|
||||
|
||||
@@ -32,6 +35,7 @@ public class JeecgSystemApplication extends SpringBootServletInitializer {
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws UnknownHostException {
|
||||
|
||||
SpringApplication app = new SpringApplication(JeecgSystemApplication.class);
|
||||
Map<String, Object> defaultProperties = new HashMap<>();
|
||||
defaultProperties.put("management.health.elasticsearch.enabled", false);
|
||||
|
||||
@@ -233,7 +233,7 @@ jeecg:
|
||||
#webapp文件路径
|
||||
webapp: /opt/webapp
|
||||
shiro:
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/sys/user/scada/queryUser,/sys/dict/scada/queryDictItem,/sys/log/scada/addLoginLog
|
||||
# 短信发送方式 aliyun阿里云短信 tencent腾讯云短信
|
||||
smsSendType: aliyun
|
||||
#阿里云oss存储和大鱼短信秘钥配置
|
||||
|
||||
@@ -199,7 +199,7 @@ jeecg:
|
||||
#webapp文件路径
|
||||
webapp: /opt/webapp
|
||||
shiro:
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/sys/user/scada/queryUser,/sys/dict/scada/queryDictItem,/sys/log/scada/addLoginLog
|
||||
#阿里云oss存储和大鱼短信秘钥配置
|
||||
oss:
|
||||
accessKey: ??
|
||||
|
||||
@@ -222,7 +222,7 @@ jeecg:
|
||||
#webapp文件路径
|
||||
webapp: /opt/webapp
|
||||
shiro:
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/sys/user/scada/queryUser,/sys/dict/scada/queryDictItem,/sys/log/scada/addLoginLog
|
||||
#阿里云oss存储和大鱼短信秘钥配置
|
||||
oss:
|
||||
accessKey: ??
|
||||
|
||||
@@ -219,7 +219,7 @@ jeecg:
|
||||
#webapp文件路径
|
||||
webapp: /opt/webapp
|
||||
shiro:
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/sys/user/scada/queryUser,/sys/dict/scada/queryDictItem,/sys/log/scada/addLoginLog
|
||||
#阿里云oss存储和大鱼短信秘钥配置
|
||||
oss:
|
||||
accessKey: ??
|
||||
|
||||
@@ -213,7 +213,7 @@ jeecg:
|
||||
#webapp文件路径
|
||||
webapp: /opt/webapp
|
||||
shiro:
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/sys/user/scada/queryUser,/sys/dict/scada/queryDictItem,/sys/log/scada/addLoginLog
|
||||
#阿里云oss存储和大鱼短信秘钥配置
|
||||
oss:
|
||||
accessKey: ??
|
||||
|
||||
@@ -226,7 +226,7 @@ jeecg:
|
||||
#webapp文件路径
|
||||
webapp: /opt/webapp
|
||||
shiro:
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/sys/user/scada/queryUser,/sys/dict/scada/queryDictItem,/sys/log/scada/addLoginLog
|
||||
#阿里云oss存储和大鱼短信秘钥配置
|
||||
oss:
|
||||
accessKey: ??
|
||||
|
||||
@@ -226,7 +226,7 @@ jeecg:
|
||||
#webapp文件路径
|
||||
webapp: /opt/jeecg-boot/webapp
|
||||
shiro:
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/api/getUserInfo
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/api/getUserInfo,/sys/user/scada/queryUser,/sys/dict/scada/queryDictItem,/sys/log/scada/addLoginLog
|
||||
# 短信发送方式 aliyun阿里云短信 tencent腾讯云短信
|
||||
smsSendType: aliyun
|
||||
#阿里云oss存储和大鱼短信秘钥配置
|
||||
|
||||
@@ -208,7 +208,7 @@ jeecg:
|
||||
#webapp文件路径
|
||||
webapp: /opt/webapp
|
||||
shiro:
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/sys/user/scada/queryUser,/sys/dict/scada/queryDictItem,/sys/log/scada/addLoginLog
|
||||
#阿里云oss存储和大鱼短信秘钥配置
|
||||
oss:
|
||||
accessKey: ??
|
||||
|
||||
@@ -227,7 +227,7 @@ jeecg:
|
||||
#webapp文件路径
|
||||
webapp: D://opt//webapp
|
||||
shiro:
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/sys/user/scada/queryUser,/sys/dict/scada/queryDictItem,/sys/log/scada/addLoginLog
|
||||
# 短信发送方式 aliyun阿里云短信 tencent腾讯云短信
|
||||
smsSendType: aliyun
|
||||
#阿里云oss存储和大鱼短信秘钥配置
|
||||
|
||||
Reference in New Issue
Block a user