u
This commit is contained in:
1 parent
35951777b0
commit
63f1d4d1dc
39 files changed
+880
-133
No files matched your search
+5
-5
@@ -21,15 +21,15 @@
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="aliyun" />
|
||||
<option name="name" value="aliyun" />
|
||||
<option name="url" value="http://maven.aliyun.com/nexus/content/groups/public" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://maven.aliyun.com/repository/public" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="aliyun" />
|
||||
<option name="name" value="aliyun" />
|
||||
<option name="url" value="http://maven.aliyun.com/nexus/content/groups/public" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+1
-1
@@ -8,5 +8,5 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="temurin-1.8" project-jdk-type="JavaSDK" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
@@ -58,11 +58,11 @@
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<optional>true</optional> <!-- 可选依赖,不打包到生产 -->
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||
<!-- <artifactId>spring-boot-devtools</artifactId>-->
|
||||
<!-- <optional>true</optional> <!– 可选依赖,不打包到生产 –>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
|
||||
@@ -24,6 +24,7 @@ public class AuthController {
|
||||
response.put("message", "Missing parameters");
|
||||
return response;
|
||||
}
|
||||
|
||||
UserInfo userInfo = UserRepository.getUserPasswordById(orgId, userId);
|
||||
if (userInfo != null && userInfo.getPassword().equals(password)) {
|
||||
String token = JwtUtil.generateToken(userId, orgId);
|
||||
@@ -33,6 +34,7 @@ public class AuthController {
|
||||
} else {
|
||||
response.put("message", "Invalid credentials");
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
-5
@@ -19,10 +19,7 @@ public class ColumnConfigController {
|
||||
*/
|
||||
@GetMapping("/api/columns")
|
||||
public Result<?> getColumnConfig(@RequestParam String tableName, HttpServletRequest request) {
|
||||
|
||||
|
||||
try {
|
||||
|
||||
String orgId = UserContext.getOrgId();
|
||||
System.out.println("api/columns:"+orgId);
|
||||
List<Map<String, Object>> data = JsonUtils.queryColumnConfig(orgId, tableName);
|
||||
@@ -32,10 +29,8 @@ public class ColumnConfigController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/api/columnsEdit")
|
||||
public Result<?> getColumnEditConfig(@RequestParam String tableName, HttpServletRequest request) {
|
||||
|
||||
try {
|
||||
String orgId = UserContext.getOrgId();
|
||||
List<Map<String, Object>> data = JsonUtils.queryColumnEditConfig(orgId, tableName);
|
||||
|
||||
@@ -8,7 +8,7 @@ public class WebConfig implements WebMvcConfigurer {
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOriginPatterns("http://localhost:5173", "http://localhost:8089","http://localhost:5174") // 前端地址
|
||||
.allowedOriginPatterns("*") // 前端地址
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||
.allowedHeaders("*")
|
||||
.allowCredentials(true);
|
||||
|
||||
@@ -3,11 +3,15 @@ package com.link.api.util;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.link.im.manager.UserChannelManager;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.sql.*;
|
||||
import java.sql.Date;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PaginationUtils {
|
||||
|
||||
@@ -470,5 +474,5 @@ public class PaginationUtils {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.link.im.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.link.api.util.DruidDataSourceManager;
|
||||
import com.link.api.util.PaginationUtils;
|
||||
import com.link.api.util.Result;
|
||||
import com.link.api.util.UserContext;
|
||||
import com.link.im.manager.UserChannelManager;
|
||||
import com.link.im.utils.DbUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
@CrossOrigin
|
||||
public class CompanyController {
|
||||
|
||||
@GetMapping("/api/loadCompanyList")
|
||||
public Result<?> getCompanyList(){
|
||||
try {
|
||||
String orgId = UserContext.getOrgId();
|
||||
String sql = "select b_id,b_name from b_user where b_canuse = '1' ";
|
||||
|
||||
List<Map<String, Object>> maps = DbUtils.queryForList(orgId, sql);
|
||||
|
||||
for (Map<String, Object> map : maps) {
|
||||
String bId = map.get("b_id").toString();
|
||||
|
||||
map.put("_online",UserChannelManager.isOnline(bId));
|
||||
}
|
||||
|
||||
return Result.ok("成功",maps);
|
||||
} catch (Exception e) {
|
||||
return Result.fail("公司列表查询异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.link.im.handler;
|
||||
|
||||
import com.link.api.util.UserContext;
|
||||
import com.link.im.manager.UserChannelManager;
|
||||
import com.link.im.manager.WriteManager;
|
||||
import com.link.im.model.ImRequest;
|
||||
import com.link.im.model.ImResponse;
|
||||
import com.link.im.utils.CommonUtils;
|
||||
import com.link.im.utils.DbUtils;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class ImMessageProcessor {
|
||||
public void process(ChannelHandlerContext ctx, ImRequest request) {
|
||||
String type = request.getType();
|
||||
if (type == null) {
|
||||
WriteManager.writeToChannel(ctx.channel(), "消息类型不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case "ping":
|
||||
handlePing(ctx);
|
||||
break;
|
||||
case "login":
|
||||
handleLogin(ctx, request);
|
||||
break;
|
||||
default:
|
||||
WriteManager.writeToChannel(ctx.channel(), "未知的消息类型: " + type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePing(ChannelHandlerContext ctx) {
|
||||
WriteManager.writeToChannel(ctx.channel(), ImResponse.success("pong",null));
|
||||
}
|
||||
|
||||
private void handleLogin(ChannelHandlerContext ctx,ImRequest request){
|
||||
String fromUserid = request.getFrom();
|
||||
UserChannelManager.addUser(fromUserid,ctx.channel());
|
||||
String orgId = request.getOrgId();
|
||||
|
||||
System.out.println(orgId);
|
||||
|
||||
// 1.通知给好友
|
||||
String sql1 = "select b_frienduser_Id from IM_Friends where b_user_id = '" + fromUserid +"'";
|
||||
try {
|
||||
List<Map<String, Object>> maps = DbUtils.queryForList(orgId, sql1);
|
||||
for (Map<String, Object> map : maps) {
|
||||
String bFrienduserId = map.get("b_frienduser_Id").toString();
|
||||
if (CommonUtils.isNotEmpty(bFrienduserId)) {
|
||||
boolean friendOnline = UserChannelManager.isOnline(bFrienduserId);
|
||||
if(friendOnline){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
// 2.通知给群组
|
||||
|
||||
// 3.通知给全部(测试用,先留,后面会删)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import com.link.im.manager.GroupManager;
|
||||
import com.link.im.manager.UserChannelManager;
|
||||
import com.link.im.manager.WriteManager;
|
||||
import com.link.im.model.ImMessage;
|
||||
import com.link.im.model.ImRequest;
|
||||
import com.link.im.model.ImResponse;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
@@ -17,6 +19,7 @@ import org.slf4j.LoggerFactory;
|
||||
public class ImWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ImWebSocketHandler.class);
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
private final ImMessageProcessor imMessageProcessor = new ImMessageProcessor();
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) {
|
||||
@@ -35,14 +38,15 @@ public class ImWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocke
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
|
||||
String text = msg.text();
|
||||
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
|
||||
try {
|
||||
ImMessage imMessage = MAPPER.readValue(text, ImMessage.class);
|
||||
|
||||
System.out.println(imMessage);
|
||||
System.out.println(msg.text());
|
||||
ImRequest request = MAPPER.readValue(msg.text(), ImRequest.class);
|
||||
imMessageProcessor.process(ctx,request);
|
||||
} catch (Exception e) {
|
||||
WriteManager.writeToChannel(ctx.channel(),"JSON格式错误");
|
||||
logger.error("channelRead0数据处理失败", e);
|
||||
|
||||
WriteManager.writeToChannel(ctx.channel(),ImResponse.error("error",e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.link.im.manager;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -14,20 +12,45 @@ public class UserChannelManager {
|
||||
private static final ConcurrentHashMap<String, Channel> userChannelMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 添加用户与Channel绑定
|
||||
* 添加用户与Channel绑定,如果已有绑定,先移除旧的
|
||||
*/
|
||||
public static void addUser(String userId, Channel channel) {
|
||||
if (userId != null && channel != null) {
|
||||
userChannelMap.put(userId, channel);
|
||||
if (userId == null || channel == null) return;
|
||||
|
||||
// 如果已有旧的 channel,先移除
|
||||
Channel oldChannel = userChannelMap.put(userId, channel);
|
||||
|
||||
if (oldChannel != null && oldChannel != channel) {
|
||||
try {
|
||||
if (oldChannel.isActive()) {
|
||||
oldChannel.close();
|
||||
}
|
||||
logger.info("用户 {} 已有旧 channel,被替换: oldChannelId={}, newChannelId={}",
|
||||
userId, oldChannel.id().asShortText(), channel.id().asShortText());
|
||||
} catch (Exception e) {
|
||||
logger.error("关闭旧 channel 异常: userId={}", userId, e);
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("用户上线: userId={}, channelId={}", userId, channel.id().asShortText());
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除用户绑定
|
||||
*/
|
||||
public static void removeUserById(String userId) {
|
||||
if (userId != null) {
|
||||
userChannelMap.remove(userId);
|
||||
if (userId == null) return;
|
||||
|
||||
Channel removed = userChannelMap.remove(userId);
|
||||
if (removed != null) {
|
||||
try {
|
||||
if (removed.isActive()) {
|
||||
removed.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("关闭 channel 异常: userId={}", userId, e);
|
||||
}
|
||||
logger.info("用户下线: userId={}, channelId={}", userId, removed.id().asShortText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,5 +83,4 @@ public class UserChannelManager {
|
||||
Channel ch = userChannelMap.get(userId);
|
||||
return ch != null && ch.isActive();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,6 +24,18 @@ public class ImMessage {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ImMessage{" +
|
||||
"type='" + type + '\'' +
|
||||
", msg='" + msg + '\'' +
|
||||
", from='" + from + '\'' +
|
||||
", to='" + to + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
", timestamp=" + timestamp +
|
||||
'}';
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.link.im.model;
|
||||
|
||||
public class ImRequest {
|
||||
private String type;
|
||||
private String from;
|
||||
private String to;
|
||||
private String content;
|
||||
private String orgId;
|
||||
private long timestamp;
|
||||
|
||||
// 无参构造
|
||||
public ImRequest() {}
|
||||
|
||||
// 全参构造
|
||||
public ImRequest(String type, String from, String to, String content, long timestamp,String orgId) {
|
||||
this.type = type;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.content = content;
|
||||
this.timestamp = timestamp;
|
||||
this.orgId = orgId;
|
||||
}
|
||||
|
||||
public String getOrgId() {
|
||||
return orgId;
|
||||
}
|
||||
|
||||
public void setOrgId(String orgId) {
|
||||
this.orgId = orgId;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public void setFrom(String from) {
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
public String getTo() {
|
||||
return to;
|
||||
}
|
||||
|
||||
public void setTo(String to) {
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ImRequest{" +
|
||||
"type='" + type + '\'' +
|
||||
", from='" + from + '\'' +
|
||||
", to='" + to + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
", timestamp=" + timestamp +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.link.im.model;
|
||||
|
||||
public class ImResponse {
|
||||
private String type;
|
||||
private int code;
|
||||
private String message;
|
||||
private long timestamp;
|
||||
private Object data;
|
||||
|
||||
// 无参构造
|
||||
public ImResponse() {}
|
||||
|
||||
// 全参构造
|
||||
public ImResponse(String type, int code, String message, long timestamp, Object data) {
|
||||
this.type = type;
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.timestamp = timestamp;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static ImResponse success(String type, Object data) {
|
||||
return new ImResponse(type, 200, "success", System.currentTimeMillis(), data);
|
||||
}
|
||||
|
||||
public static ImResponse success(String type, String message, Object data) {
|
||||
return new ImResponse(type, 200, message, System.currentTimeMillis(), data);
|
||||
}
|
||||
|
||||
public static ImResponse error(String type, String message) {
|
||||
return new ImResponse(type, 500, message, System.currentTimeMillis(), null);
|
||||
}
|
||||
|
||||
public static ImResponse error(String type, int code, String message) {
|
||||
return new ImResponse(type, code, message, System.currentTimeMillis(), null);
|
||||
}
|
||||
|
||||
// Getter & Setter
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(Object data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ImResponse{" +
|
||||
"type='" + type + '\'' +
|
||||
", code=" + code +
|
||||
", message='" + message + '\'' +
|
||||
", timestamp=" + timestamp +
|
||||
", data=" + data +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.link.im.utils;
|
||||
|
||||
public class CommonUtils {
|
||||
/**
|
||||
* 判断字符串是否为空(null 或 "")
|
||||
* @param str 待判断的字符串
|
||||
* @return true 如果字符串为 null 或 空串
|
||||
*/
|
||||
public static boolean isEmpty(String str) {
|
||||
return str == null || str.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断字符串是否非空(不是 null 且不为空串)
|
||||
* @param str 待判断的字符串
|
||||
* @return true 如果字符串非空
|
||||
*/
|
||||
public static boolean isNotEmpty(String str) {
|
||||
return !isEmpty(str);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.link.im.utils;
|
||||
|
||||
|
||||
import com.link.api.util.DruidDataSourceManager;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
|
||||
public class DbUtils {
|
||||
|
||||
/**
|
||||
* 根据 SQL 查询数据
|
||||
*
|
||||
* @param orgCode 数据源组织编码
|
||||
* @param sql 查询 SQL
|
||||
* @return List<Map<String,Object>>,每一行作为 Map
|
||||
*/
|
||||
public static List<Map<String, Object>> queryForList(String orgCode, String sql) throws SQLException {
|
||||
List<Map<String, Object>> resultList = new ArrayList<>();
|
||||
|
||||
try (Connection conn = DruidDataSourceManager.getConnection(orgCode);
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
ResultSet rs = stmt.executeQuery()) {
|
||||
|
||||
ResultSetMetaData metaData = rs.getMetaData();
|
||||
int columnCount = metaData.getColumnCount();
|
||||
|
||||
while (rs.next()) {
|
||||
Map<String, Object> rowMap = new LinkedHashMap<>();
|
||||
for (int i = 1; i <= columnCount; i++) {
|
||||
String columnName = metaData.getColumnLabel(i);
|
||||
Object value = rs.getObject(i);
|
||||
rowMap.put(columnName, value);
|
||||
}
|
||||
resultList.add(rowMap);
|
||||
}
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
url=jdbc:sqlserver://127.0.0.1:1433;databaseName=G3HY2025
|
||||
url=jdbc:sqlserver://192.168.1.189:1433;databaseName=G3-Link;encrypt=false
|
||||
username=sa
|
||||
password=g3soft
|
||||
driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
url=jdbc:sqlserver://127.0.0.1:1433;databaseName=G3HY2025
|
||||
url=jdbc:sqlserver://192.168.1.189:1433;databaseName=G3-Link;encrypt=false
|
||||
username=sa
|
||||
password=g3soft
|
||||
driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
Reference in new issue
Block a user